📄 cc4.c
字号:
/*** Small-C Compiler -- Part 4 -- Back End.** Copyright 1982, 1983, 1985, 1988 J. E. Hendrix** Copyright 1998 H T Walheim** All rights reserved.*/#include <stdio.h>#include "cc.h"/*************************** externals ****************************/extern char*cptr, *macn, *litq, *symtab, optimize, ssname[NAMESIZE];extern int*stage, litlab, litptr, csp, output, oldseg, usexpr, *snext, *stail, *slast;/***************** optimizer command definitions ******************/ /* -- p-codes must not overlap these */#define any 0x00FF /* matches any p-code */#define _pop 0x00FE /* matches if corresponding POP2 exists */#define pfree 0x00FD /* matches if pri register free */#define sfree 0x00FC /* matches if sec register free */#define comm 0x00FB /* matches if registers are commutative */ /* -- these digits are reserved for n */#define go 0x0100 /* go n entries */#define gc 0x0200 /* get code from n entries away */#define gv 0x0300 /* get value from n entries away */#define sum 0x0400 /* add value from nth entry away */#define neg 0x0500 /* negate the value */#define ife 0x0600 /* if value == n do commands to next 0 */#define ifl 0x0700 /* if value < n do commands to next 0 */#define swv 0x0800 /* swap value with value n entries away */#define topop 0x0900 /* moves |code and current value to POP2 */#define p1 0x0001 /* plus 1 */#define p2 0x0002 /* plus 2 */#define p3 0x0003 /* plus 3 */#define p4 0x0004 /* plus 4 */#define m1 0x00FF /* minus 1 */#define m2 0x00FE /* minus 2 */#define m3 0x00FD /* minus 3 */#define m4 0x00FC /* minus 4 */#define PRI 0030 /* primary register bits */#define SEC 0003 /* secondary register bits */#define USES 0011 /* use register contents */#define ZAPS 0022 /* zap register contents */#define PUSHES 0100 /* pushes onto the stack */#define COMMUTES 0200 /* commutative p-code *//******************** optimizer command lists *********************/int seq00[] = { 0, ADD12, MOVE21, 0, /* ADD21 */ go | p1, ADD21, 0}, seq01[] = { 0, ADD1n, 0, /* rINC1 or rDEC1 ? */ifl | m2, 0, ifl | 0, rDEC1, neg, 0, ifl | p3, rINC1, 0, 0}, seq02[] = { 0, ADD2n, 0, /* rINC2 or rDEC2 ? */ifl | m2, 0, ifl | 0, rDEC2, neg, 0, ifl | p3, rINC2, 0, 0}, seq03[] = { 0, rDEC1, PUTbp1, rINC1, 0, /* SUBbpn or DECbp */go | p2, ife | p1, DECbp, 0, SUBbpn, 0}, seq04[] = { 0, rDEC1, PUTwp1, rINC1, 0, /* SUBwpn or DECwp */go | p2, ife | p1, DECwp, 0, SUBwpn, 0}, seq05[] = { 0, rDEC1, PUTbm1, rINC1, 0, /* SUB_m_ COMMAn */go | p1, SUB_m_, go | p1, COMMAn, go | m1, 0}, seq06[] = { 0, rDEC1, PUTwm1, rINC1, 0, /* SUB_m_ COMMAn */go | p1, SUB_m_, go | p1, COMMAn, go | m1, 0}, seq07[] = { 0, GETw1m, GETw2n, ADD12, MOVE21, GETb1p, 0, /* GETw2m GETb1p */go | p4, gv | m3, go | m1, GETw2m, gv | m3, 0}, seq08[] = { 0, GETw1m, GETw2n, ADD12, MOVE21, GETb1pu, 0, /* GETw2m GETb1pu */go | p4, gv | m3, go | m1, GETw2m, gv | m3, 0}, seq09[] = { 0, GETw1m, GETw2n, ADD12, MOVE21, GETw1p, 0, /* GETw2m GETw1p */go | p4, gv | m3, go | m1, GETw2m, gv | m3, 0}, seq10[] = { 0, GETw1m, GETw2m, SWAP12, 0, /* GETw2m GETw1m */go | p2, GETw1m, gv | m1, go | m1, gv | m1, 0}, seq11[] = { 0, GETw1m, MOVE21, 0, /* GETw2m */go | p1, GETw2m, gv | m1, 0}, seq12[] = { 0, GETw1m, PUSH1, pfree, 0, /* PUSHm */go | p1, PUSHm, gv | m1, 0}, seq13[] = { 0, GETw1n, PUTbm1, pfree, 0, /* PUT_m_ COMMAn */PUT_m_, go | p1, COMMAn, go | m1, swv | p1, 0}, seq14[] = { 0, GETw1n, PUTwm1, pfree, 0, /* PUT_m_ COMMAn */PUT_m_, go | p1, COMMAn, go | m1, swv | p1, 0}, seq15[] = { 0, GETw1p, PUSH1, pfree, 0, /* PUSHp */go | p1, PUSHp, gv | m1, 0}, seq16[] = { 0, GETw1s, GETw2n, ADD12, MOVE21, 0, /* GETw2s ADD2n */go | p3, ADD2n, gv | m2, go | m1, GETw2s, gv | m2, 0}, seq17[] = { 0, GETw1s, GETw2s, SWAP12, 0, /* GETw2s GETw1s */go | p2, GETw1s, gv | m1, go | m1, GETw2s, gv | m1, 0}, seq18[] = { 0, GETw1s, MOVE21, 0, /* GETw2s */go | p1, GETw2s, gv | m1, 0}, seq19[] = { 0, GETw2m, GETw1n, SWAP12, SUB12, 0, /* GETw1m SUB1n */go | p3, SUB1n, gv | m2, go | m1, GETw1m, gv | m2, 0}, seq20[] = { 0, GETw2n, ADD12, 0, /* ADD1n */go | p1, ADD1n, gv | m1, 0}, seq21[] = { 0, GETw2s, GETw1n, SWAP12, SUB12, 0, /* GETw1s SUB1n */go | p3, SUB1n, gv | m2, go | m1, GETw1s, gv | m2, 0}, seq22[] = { 0, rINC1, PUTbm1, rDEC1, 0, /* ADDm_ COMMAn */go | p1, ADDm_, go | p1, COMMAn, go | m1, 0}, seq23[] = { 0, rINC1, PUTwm1, rDEC1, 0, /* ADDm_ COMMAn */go | p1, ADDm_, go | p1, COMMAn, go | m1, 0}, seq24[] = { 0, rINC1, PUTbp1, rDEC1, 0, /* ADDbpn or INCbp */go | p2, ife | p1, INCbp, 0, ADDbpn, 0}, seq25[] = { 0, rINC1, PUTwp1, rDEC1, 0, /* ADDwpn or INCwp */go | p2, ife | p1, INCwp, 0, ADDwpn, 0}, seq26[] = { 0, MOVE21, GETw1n, SWAP12, SUB12, 0, /* SUB1n */go | p3, SUB1n, gv | m2, 0}, seq27[] = { 0, MOVE21, GETw1n, comm, 0, /* GETw2n comm */go | p1, GETw2n, 0}, seq28[] = { 0, POINT1m, GETw2n, ADD12, MOVE21, 0, /* POINT2m_ PLUSn */go | p3, PLUSn, gv | m2, go | m1, POINT2m_, gv | m2, 0}, seq29[] = { 0, POINT1m, MOVE21, pfree, 0, /* POINT2m */go | p1, POINT2m, gv | m1, 0}, seq30[] = { 0, POINT1m, PUSH1, pfree, _pop, 0, /* ... POINT2m */topop | POINT2m, go | p2, 0}, seq31[] = { 0, POINT1s, GETw2n, ADD12, MOVE21, 0, /* POINT2s */sum | p1, go | p3, POINT2s, gv | m3, 0}, seq32[] = { 0, POINT1s, PUSH1, MOVE21, 0, /* POINT2s PUSH2 */go | p1, POINT2s, gv | m1, go | p1, PUSH2, go | m1, 0}, seq33[] = { 0, POINT1s, PUSH1, pfree, _pop, 0, /* ... POINT2s */topop | POINT2s, go | p2, 0}, seq34[] = { 0, POINT1s, MOVE21, 0, /* POINT2s */go | p1, POINT2s, gv | m1, 0}, seq35[] = { 0, POINT2m, GETb1p, sfree, 0, /* GETb1m */go | p1, GETb1m, gv | m1, 0}, seq36[] = { 0, POINT2m, GETb1pu, sfree, 0, /* GETb1mu */go | p1, GETb1mu, gv | m1, 0}, seq37[] = { 0, POINT2m, GETw1p, sfree, 0, /* GETw1m */go | p1, GETw1m, gv | m1, 0}, seq38[] = { 0, POINT2m_, PLUSn, GETw1p, sfree, 0, /* GETw1m_ PLUSn */go | p2, gc | m1, gv | m1, go | m1, GETw1m_, gv | m1, 0}, seq39[] = { 0, POINT2s, GETb1p, sfree, 0, /* GETb1s */sum | p1, go | p1, GETb1s, gv | m1, 0}, seq40[] = { 0, POINT2s, GETb1pu, sfree, 0, /* GETb1su */sum | p1, go | p1, GETb1su, gv | m1, 0}, seq41[] = { 0, POINT2s, GETw1p, PUSH1, pfree, 0, /* PUSHs */sum | p1, go | p2, PUSHs, gv | m2, 0}, seq42[] = { 0, POINT2s, GETw1p, sfree, 0, /* GETw1s */sum | p1, go | p1, GETw1s, gv | m1, 0}, seq43[] = { 0, PUSH1, any, POP2, 0, /* MOVE21 any */go | p2, gc | m1, gv | m1, go | m1, MOVE21, 0}, seq44[] = { 0, PUSHm, _pop, 0, /* ... GETw2m */topop | GETw2m, go | p1, 0}, seq45[] = { 0, PUSHp, any, POP2, 0, /* GETw2p ... */go | p2, gc | m1, gv | m1, go | m1, GETw2p, gv | m1, 0}, seq46[] = { 0, PUSHs, _pop, 0, /* ... GETw2s */topop | GETw2s, go | p1, 0}, seq47[] = { 0, SUB1n, 0, /* rDEC1 or rINC1 ? */ifl | m2, 0, ifl | 0, rINC1, neg, 0, ifl | p3, rDEC1, 0, 0};#define HIGH_SEQ 47int seq[HIGH_SEQ + 1];setseq(){ seq[0] = seq00; seq[1] = seq01; seq[2] = seq02; seq[3] = seq03; seq[4] = seq04; seq[5] = seq05; seq[6] = seq06; seq[7] = seq07; seq[8] = seq08; seq[9] = seq09; seq[10] = seq10; seq[11] = seq11; seq[12] = seq12; seq[13] = seq13; seq[14] = seq14; seq[15] = seq15; seq[16] = seq16; seq[17] = seq17; seq[18] = seq18; seq[19] = seq19; seq[20] = seq20; seq[21] = seq21; seq[22] = seq22; seq[23] = seq23; seq[24] = seq24; seq[25] = seq25; seq[26] = seq26; seq[27] = seq27; seq[28] = seq28; seq[29] = seq29; seq[30] = seq30; seq[31] = seq31; seq[32] = seq32; seq[33] = seq33; seq[34] = seq34; seq[35] = seq35; seq[36] = seq36; seq[37] = seq37; seq[38] = seq38; seq[39] = seq39; seq[40] = seq40; seq[41] = seq41; seq[42] = seq42; seq[43] = seq43; seq[44] = seq44; seq[45] = seq45; seq[46] = seq46; seq[47] = seq47;}/***************** assembly-code strings ******************/int code[PCODES];/*** First byte contains flag bits indicating:** the value in ax is needed (010) or zapped (020)** the value in bx is needed (001) or zapped (002)*/setcodes(){ setseq(); code[ADD12] = "\211ADD EAX,EBX\n"; code[ADD1n] = "\010?ADD EAX,<n>\n??"; code[ADD21] = "\211ADD EBX,EAX\n"; code[ADD2n] = "\010?ADD EBX,<n>\n??"; code[ADDbpn] = "\001ADD BYTE [EBX],<n>\n"; code[ADDwpn] = "\001ADD WORD [EBX],<n>\n"; code[ADDm_] = "\000ADD <m>"; code[ADDSP] = "\000?ADD ESP,<n>\n??"; code[AND12] = "\211AND EAX,EBX\n"; code[ANEG1] = "\010NEG EAX\n"; code[ARGCNTn] = "\000?MOV CL,<n>?XOR CL,CL?\n"; code[ASL12] = "\011MOV ECX,EAX\n\tMOV EAX,EBX\n\tSAL EAX,CL\n"; code[ASR12] = "\011MOV ECX,EAX\n\tMOV EAX,EBX\n\tSAR EAX,CL\n"; code[CALL1] = "\010CALL EAX\n"; code[CALLm] = "\020CALL $<m>\n"; code[BYTE_] = "\000 DB "; code[BYTEn] = "\000 RESB <n>\n"; code[BYTEr0] = "\000 TIMES <n> DB 0\n"; code[COM1] = "\010NOT EAX\n"; code[COMMAn] = "\000,<n>\n"; code[DBL1] = "\010SHL EAX,1\n"; code[DBL2] = "\001SHL EBX,1\n"; code[DECbp] = "\001DEC BYTE [EBX]\n"; code[DECwp] = "\001DEC WORD [EBX]\n"; code[DIV12] = "\011CDQ\n\tIDIV EBX\n"; /* see gen() */ code[DIV12u] = "\011XOR EDX,EDX\n\tDIV EBX\n"; /* see gen() */ code[DWORD_] = "\000 DD "; code[DWORDn] = "\000 DD <n>\n"; code[DWORDr0] = "\000 TIMES <n> DD 0\n"; code[ENTER] = "\100PUSH EBP\n\tMOV EBP,ESP\n"; code[EQ10f] = "\010<g>OR EAX,EAX\n\tJE _<d>\n\tJMP _<n>\n_<d>:\n"; code[EQ12] = ""; // code[EQ12] = "\211CALL __eq\n"; code[GE10f] = "\010<g>OR EAX,EAX\n\tJGE _<d>\n\tJMP _<n>\n_<d>:\n"; code[GE12] = "";// code[GE12] = "\011CALL __ge\n";// code[GE12u] = "\011CALL __uge\n"; code[GE12u] = ""; code[GETb1m] = "\020MOVSX EAX,BYTE [$<m>]\n"; code[GETb1mu] = "\020MOVZX EAX,BYTE [$<m>]\n"; code[GETb1p] = "\021MOVSX EAX,BYTE [EBX?<o>??]\n"; /* see gen() */ code[GETb1pu] = "\021MOVZX EAX,BYTE [EBX?<o>??]\n"; /* see gen() */ code[GETb1s] = "\020MOVSX EAX,BYTE [EBP<o>]\n"; code[GETb1su] = "\020MOVZX EAX,BYTE [EBP<o>]\n"; code[GETd1m] = "\020MOV EAX,[$<m>]\n"; code[GETd1n] = "\020?MOV EAX,<n>?XOR EAX,EAX?\n"; code[GETd1p] = "\021MOV EAX, [EBX?<o>??]\n"; /* see gen() */ code[GETd2n] = "\002?MOV EBX,<n>?XOR EBX,EBX?\n"; code[GETw1m] = "\020MOVSX EAX,WORD [$<m>]\n"; code[GETw1m_] = "\020MOVSX EAX,WORD [$<m>]"; code[GETw1n] = "\020?MOV EAX,<n>?XOR EAX,EAX?\n"; code[GETw1p] = "\021MOVSX EAX, WORD [EBX?<o>??]\n"; /* see gen() */ code[GETw1s] = "\020MOVSX EAX, WORD [EBP<o>]\n"; code[GETw2m] = "\002MOVSX EBX,WORD <m>\n"; code[GETw2n] = "\002?MOV EBX,<n>?XOR EBX,EBX?\n"; code[GETw2p] = "\021MOVSX EBX,WORD [EBX?<o>??]\n"; code[GETw2s] = "\002MOVSX EBX,WORD [EBP<o>]\n"; code[GT10f] = "\010<g>OR EAX,EAX\n\tJG _<d>\n\tJMP _<n>\n_<d>:\n"; code[GT12] = "";// code[GT12] = "\010CALL __gt\n"; code[GT12u] = "";// code[GT12u] = "\011CALL __ugt\n"; code[INCbp] = "\001INC BYTE [EBX]\n"; code[INCwp] = "\001INC WORD [EBX]\n"; code[WORD_] = "\000 DW "; code[WORDn] = "\000 RESW <n>\n"; code[WORDr0] = "\000 TIMES <n> DW 0\n"; code[JMPm] = "\000JMP _<n>\n"; code[LABm] = "\000_<n>:\n"; code[LE10f] = "\010<g>OR EAX,EAX\n\tJLE _<d>\n\tJMP _<n>\n_<d>:\n"; code[LE12] = "";// code[LE12] = "\011CALL __le\n"; code[LE12u] = ""; code[LNEG1] = ""; code[LT10f] = "\010<g>OR EAX,EAX\n\tJL _<d>\n\tJMP _<n>\n_<d>:\n"; code[LT12] = "";// code[LT12] = "\011CALL __lt\n"; code[LT12u] = ""; code[MOD12] = "\011CDQ\n\tIDIV EBX\n\tMOV EAX,EDX\n"; /* see gen() */ code[MOD12u] = "\011XOR EDX,EDX\n\tDIV EBX\n\tMOV EAX,EDX\n"; /* see gen() */ code[MOVE21] = "\012MOV EBX,EAX\n"; code[MUL12] = "\211IMUL EBX\n"; code[MUL12u] = "\211MUL EBX\n"; code[NE10f] = "\010<g>OR EAX,EAX\n\tJNE _<d>\n\tJMP _<n>\n\t_<d>:\n"; code[NE12] = ""; code[NEARm] = "\000 DD _<n>\n"; code[OR12] = "\211OR EAX,EBX\n"; code[PLUSn] = "\000?+<n>??\n"; code[POINT1l] = "\020MOV EAX,_<l>+<n>\n"; code[POINT1m] = "\020MOV EAX,<m>\n"; code[POINT1s] = "\020LEA EAX,[EBP<o>]\n"; code[POINT2m] = "\002MOV EBX,<m>\n"; code[POINT2m_] = "\002MOV EBX,<m>"; code[POINT2s] = "\002LEA EBX,[EBP<o>]\n"; code[POP2] = "\002POP EBX\n"; code[PUSH1] = "\110PUSH EAX\n"; code[PUSH2] = "\101PUSH EBX\n"; code[PUSHm] = "\100PUSH $<m>\n"; code[PUSHp] = "\100PUSH [EBX?<o>??]\n"; code[PUSHs] = "\100PUSH [EBP?<o>??]\n"; code[PUT_m_] = "\000MOV $<m>"; code[PUTbm1] = "\010MOV BYTE [$<m>],AL\n"; code[PUTbp1] = "\011MOV [EBX],AL\n"; code[PUTdm1] = "\010MOV DWORD [$<m>],EAX\n"; code[PUTdp1] = "\011MOV [EBX],EAX\n"; code[PUTwm1] = "\010MOV WORD [$<m>],AX\n"; code[PUTwp1] = "\011MOV [EBX],AX\n"; code[rDEC1] = "\010#DEC EAX\n#"; code[rDEC2] = "\010#DEC EBX\n#"; code[REFm] = "\000_<n>"; code[RETURN] = "\000?MOV ESP,EBP\n\t??POP EBP\n\tRET\n"; code[rINC1] = "\010#INC EAX\n#"; code[rINC2] = "\010#INC EBX\n#"; code[SUB_m_] = "\000SUB $<m>"; code[SUB12] = "\011SUB EAX,EBX\n"; /* see gen() */ code[SUB1n] = "\010?SUB EAX,<n>\n??"; code[SUBbpn] = "\001SUB [EBX],<n>\n"; code[SUBwpn] = "\001SUB [EBX],<n>\n"; code[SWAP12] = "\011XCHG EAX,EBX\n"; code[SWAP1s] = "\012POP EBX\n\tXCHG EAX,EBX\n\tPUSH EBX\n"; code[SWITCH] = ""; code[XOR12] = "\211XOR EAX,EBX\n";}/***************** code generation functions *****************//*** print all assembler info before any code is generated** and ensure that the segments appear in the correct order.*/header(){ toseg(CODESEG); outline("; Compiled with Simple C - http://retro.tunes.org/simplec");/* outline("EXTERN __eq"); outline("EXTERN __ne"); outline("EXTERN __le"); outline("EXTERN __lt"); outline("EXTERN __ge"); outline("EXTERN __gt"); outline("EXTERN __ule"); outline("EXTERN __ult"); outline("EXTERN __uge"); outline("EXTERN __ugt"); outline("EXTERN __lneg"); outline("EXTERN __switch");*/ toseg(DATASEG);}/*** print any assembler stuff needed at the end*/trailer(){ char *cp; cptr = STARTGLB; while (cptr < ENDGLB) { if (cptr[IDENT] == FUNCTION && cptr[CLASS] == AUTOEXT) external(cptr + NAME, 0, FUNCTION); cptr += SYMMAX; } toseg(NULL); outline("END");}/*** remember where we are in the queue in case we have to back up.*/setstage(before, start)int *before, *start;{ if ((*before = snext) == 0) snext = stage; *start = snext;}/*** generate code in staging buffer.*/gen(pcode, value)int pcode, value;{ int newcsp; switch (pcode) { case GETb1pu: case GETb1p: case GETw1p: case GETd1p: gen(MOVE21, 0); break; case SUB12: case MOD12: case MOD12u: case DIV12: case DIV12u: gen(SWAP12, 0); break; case PUSH1: csp -= BPD; break; case POP2: csp += BPD; break; case ADDSP: case RETURN: newcsp = value; value -= csp; csp = newcsp; } if (snext == 0) { outcode(pcode, value); return; } if (snext >= slast) { error("staging buffer overflow"); return; } snext[0] = pcode; snext[1] = value; snext += 2;}/*** dump the contents of the queue.** If start = 0, throw away contents.** If before != 0, don't dump queue yet.*/clearstage(before, start)int *before, *start;{ if (before) { snext = before; return; } if (start) dumpstage(); snext = 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -