From 4d5480c1fcca5abcf7d9c91bfe2d323720e3482c Mon Sep 17 00:00:00 2001 From: Humberto Costa Date: Fri, 10 May 2024 13:47:12 -0300 Subject: [PATCH 1/6] Merge all changes from last year - Clean 8086 CodeGen code - Remove irrelevant code from 8086 - Update base code from current main project - Fix 8086 bugs --- common.mk | 7 +- v0100/cg8086.c | 2850 +++++++++++++++++++++++++++++++++++++++ v0100/smlrc.c | 18 +- v0100/smlrcc.c | 78 +- v0100/srclib/lcds86.txt | 178 +++ v0100/tests/Makefile | 25 + 6 files changed, 3121 insertions(+), 35 deletions(-) create mode 100644 v0100/cg8086.c create mode 100644 v0100/srclib/lcds86.txt create mode 100644 v0100/tests/Makefile diff --git a/common.mk b/common.mk index d1272d6..f1e60fd 100644 --- a/common.mk +++ b/common.mk @@ -16,8 +16,8 @@ else CPPFLAGS += -DHOST_LINUX endif -bins = smlrc smlrl smlrcc smlrpp n2f -libs = lcdh.a lcdu.a lcds.a lcw.a lcl.a lcdp.a lcm.a +bins = smlrc smlrc86 smlrl smlrcc smlrpp n2f +libs = lcdh.a lcdu.a lcds.a lcds86.a lcw.a lcl.a lcdp.a lcm.a stub = dpstub.exe all: $(libs) $(stub) @@ -46,6 +46,9 @@ clean: $(stub): ./smlrcc -small $(srcdir)/srclib/dpstub.asm -o $@ +smlrc86: + $(CC) $(CFLAGS) -DONLY8086 -o $@ v0100/smlrc.c + smlrpp: $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ -DSTAND_ALONE -DUCPP_CONFIG \ $(srcdir)/ucpp/arith.c \ diff --git a/v0100/cg8086.c b/v0100/cg8086.c new file mode 100644 index 0000000..092675f --- /dev/null +++ b/v0100/cg8086.c @@ -0,0 +1,2850 @@ +/* +Copyright (c) 2012-2018, Alexey Frunze +Copyright (c) 2023-2024, Humberto Costa dos Santos Junior +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/*****************************************************************************/ +/* */ +/* Smaller C */ +/* */ +/* A simple and small single-pass C compiler */ +/* */ +/* Generic code generator */ +/* */ +/*****************************************************************************/ + +#define MAX_GLOBALS_TABLE_LEN MAX_IDENT_TABLE_LEN + +/* + Globals table entry format: + use char: use: bit 0 = defined, bit 1 = used + idlen char: string length (<= 127) + id char[idlen]: string (ASCIIZ) +*/ +char GlobalsTable[MAX_GLOBALS_TABLE_LEN]; +int GlobalsTableLen = 0; + +STATIC +void GenAddGlobal(char* s, int use) +{ + int i = 0; + int l; + if (GenExterns) + { + while (i < GlobalsTableLen) + { + if (!strcmp(GlobalsTable + i + 2, s)) + { + if (GlobalsTable[i] & use & 1) + errorRedecl(s); // the assembler would error-out in this case as well + GlobalsTable[i] |= use; + return; + } + i += GlobalsTable[i + 1] + 2; + } + l = strlen(s) + 1; + if (GlobalsTableLen + l + 2 > MAX_GLOBALS_TABLE_LEN) + error("Globals tbl exhausted\n"); + GlobalsTable[GlobalsTableLen++] = use; + GlobalsTable[GlobalsTableLen++] = l; + memcpy(GlobalsTable + GlobalsTableLen, s, l); + GlobalsTableLen += l; + } +} + +STATIC +void GenInit(void) +{ + // initialization of target-specific code generator + SizeOfWord = 2; + OutputFormat = FormatSegmented; + UseLeadingUnderscores = 1; +} + +STATIC +int GenInitParams(int argc, char** argv, int* idx) +{ + (void)argc; + // initialization of target-specific code generator with parameters + + if (!strcmp(argv[*idx], "-nobss")) + { + UseBss = 0; + return 1; + } + else if (!strcmp(argv[*idx], "-seg16")) + { + // this is the default option for x86 + OutputFormat = FormatSegmented; SizeOfWord = 2; + return 1; + } + + return 0; +} + +STATIC +void GenInitFinalize(void) +{ + // finalization of initialization of target-specific code generator + + // Change the output assembly format/content according to the options + CodeHeaderFooter[0] = "section .text"; + DataHeaderFooter[0] = "section .data"; + RoDataHeaderFooter[0] = "section .rodata"; + BssHeaderFooter[0] = "section .bss"; + FileHeader = "bits 16\ncpu 8086\n"; +} + +STATIC +void GenStartCommentLine(void) +{ + printf2("; "); +} + +STATIC +void GenWordAlignment(int bss) +{ + printf2(bss ? "\talignb %d\n" : "\talign %d\n", SizeOfWord); +} + +STATIC +void GenLabel(char* Label, int Static) +{ + if (UseLeadingUnderscores) + { + if (!Static && GenExterns) + printf2("\tglobal\t_%s\n", Label); + printf2("_%s:\n", Label); + } + else + { + if (!Static && GenExterns) + printf2("\tglobal\t$%s\n", Label); + printf2("$%s:\n", Label); + } + GenAddGlobal(Label, 1); +} + +STATIC +void GenPrintLabel(char* Label) +{ + if (UseLeadingUnderscores) + { + printf2(isdigit(*Label) ? "L%s" : "_%s", Label); + } + else + { + printf2(isdigit(*Label) ? "..@L%s" : "$%s", Label); + } +} + +STATIC +void GenNumLabel(int Label) +{ + printf2(UseLeadingUnderscores ? "L%d:\n" :"..@L%d:\n", Label); +} + +STATIC +void GenPrintNumLabel(int label) +{ + printf2(UseLeadingUnderscores ? "L%d" : "..@L%d", label); +} + +STATIC +void GenZeroData(unsigned Size, int bss) +{ + printf2(bss ? "\tresb\t%u\n" : "\ttimes\t%u db 0\n", truncUint(Size)); +} + +STATIC +void GenIntData(int Size, int Val) +{ + Val = truncInt(Val); + printf2(Size == 1 ? "\tdb\t%d\n" : "\tdw\t%d\n", Val); +} + +STATIC +void GenStartAsciiString(void) +{ + printf2("\tdb\t"); +} + +STATIC +void GenAddrData(int Size, char* Label, int ofs) +{ + ofs = truncInt(ofs); + printf2(Size == 1 ? "\tdb\t" : "\tdw\t"); + GenPrintLabel(Label); + if (ofs) + printf2(" %+d", ofs); + puts2(""); + if (!isdigit(*Label)) + GenAddGlobal(Label, 2); +} + +STATIC +int GenFxnSizeNeeded(void) +{ + return 0; +} + +STATIC +void GenRecordFxnSize(char* startLabelName, int endLabelNo) +{ + // In the huge mode(l) individual functions must each fit into a 64KB segment. + // A special non-allocated section, ".fxnsz", will hold function sizes and + // the linker will check them. + (void)startLabelName; + (void)endLabelNo; +} + +#define X86InstrMov 0x00 +#define X86InstrMovSx 0x01 +#define X86InstrMovZx 0x02 +#define X86InstrXchg 0x03 +#define X86InstrLea 0x04 +#define X86InstrPush 0x05 +#define X86InstrPop 0x06 +#define X86InstrInc 0x07 +#define X86InstrDec 0x08 +#define X86InstrAdd 0x09 +#define X86InstrSub 0x0A +#define X86InstrAnd 0x0B +#define X86InstrXor 0x0C +#define X86InstrOr 0x0D +#define X86InstrCmp 0x0E +#define X86InstrTest 0x0F +#define X86InstrMul 0x10 +#define X86InstrImul 0x11 +#define X86InstrIdiv 0x12 +#define X86InstrDiv 0x13 +#define X86InstrShl 0x14 +#define X86InstrSar 0x15 +#define X86InstrShr 0x16 +#define X86InstrNeg 0x17 +#define X86InstrNot 0x18 +#define X86InstrCbw 0x19 +#define X86InstrCwd 0x1A +#define X86InstrCdq 0x1B +#define X86InstrSetCc 0x1C +#define X86InstrJcc 0x1D +#define X86InstrJNotCc 0x1E +#define X86InstrLeave 0x1F +#define X86InstrCall 0x20 +#define X86InstrRet 0x21 +#define X86InstrJmp 0x22 + +char* winstrs[] = +{ + "mov", + "movsx", + "movzx", + "xchg", + "lea", + "push", + "pop", + "inc", + "dec", + "add", + "sub", + "and", + "xor", + "or", + "cmp", + "test", + "mul", + "imul", + "idiv", + "div", + "shl", + "sar", + "shr", + "neg", + "not", + "cbw", + "cwd", + "cdq", + 0, // setcc + 0, // jcc + 0, // j!cc + 0, // leave + "call", + 0, // ret + "jmp", +}; + +STATIC +void GenPrintInstr(int instr, int val) +{ + char* p = ""; + + switch (instr) + { + case X86InstrLeave: + p = (OutputFormat != FormatSegHuge && OutputFormat != FormatSegUnreal) ? "leave" : "db\t0x66\n\tleave"; + break; + + case X86InstrRet: + p = (OutputFormat != FormatSegHuge && OutputFormat != FormatSegUnreal) ? "ret" : "retf"; + break; + + case X86InstrJcc: + switch (val) + { + case '<': p = "jl"; break; + case tokULess: p = "jb"; break; + case '>': p = "jg"; break; + case tokUGreater: p = "ja"; break; + case tokLEQ: p = "jle"; break; + case tokULEQ: p = "jbe"; break; + case tokGEQ: p = "jge"; break; + case tokUGEQ: p = "jae"; break; + case tokEQ: p = "je"; break; + case tokNEQ: p = "jne"; break; + } + break; + case X86InstrJNotCc: + switch (val) + { + case '<': p = "jge"; break; + case tokULess: p = "jae"; break; + case '>': p = "jle"; break; + case tokUGreater: p = "jbe"; break; + case tokLEQ: p = "jg"; break; + case tokULEQ: p = "ja"; break; + case tokGEQ: p = "jl"; break; + case tokUGEQ: p = "jb"; break; + case tokEQ: p = "jne"; break; + case tokNEQ: p = "je"; break; + } + break; + + case X86InstrSetCc: + switch (val) + { + case '<': p = "setl"; break; + case tokULess: p = "setb"; break; + case '>': p = "setg"; break; + case tokUGreater: p = "seta"; break; + case tokLEQ: p = "setle"; break; + case tokULEQ: p = "setbe"; break; + case tokGEQ: p = "setge"; break; + case tokUGEQ: p = "setae"; break; + case tokEQ: p = "sete"; break; + case tokNEQ: p = "setne"; break; + } + break; + + default: + p = winstrs[instr]; + break; + } + + switch (instr) + { + case X86InstrCbw: + case X86InstrCwd: + case X86InstrLeave: + case X86InstrRet: + printf2("\t%s", p); + break; + default: + printf2("\t%s\t", p); + break; + } +} + +#define X86OpRegAByte 0x00 +#define X86OpRegAByteHigh 0x01 +#define X86OpRegCByte 0x02 +#define X86OpRegAWord 0x03 +#define X86OpRegBWord 0x04 +#define X86OpRegCWord 0x05 +#define X86OpRegDWord 0x06 +#define X86OpRegAHalfWord 0x07 +#define X86OpRegCHalfWord 0x08 +#define X86OpRegBpWord 0x09 +#define X86OpRegSpWord 0x0A +#define X86OpRegAByteOrWord 0x0B +#define X86OpRegCByteOrWord 0x0C +#define X86OpConst 0x0D +#define X86OpLabel 0x0E +#define X86OpNumLabel 0x0F +#define X86OpIndLabel 0x10 +#define X86OpIndLabelExplicitByte 0x11 +#define X86OpIndLabelExplicitWord 0x12 +#define X86OpIndLabelExplicitHalfWord 0x13 +#define X86OpIndLabelExplicitByteOrWord 0x14 +#define X86OpIndLocal 0x15 +#define X86OpIndLocalExplicitByte 0x16 +#define X86OpIndLocalExplicitWord 0x17 +#define X86OpIndLocalExplicitHalfWord 0x18 +#define X86OpIndLocalExplicitByteOrWord 0x19 +#define X86OpIndRegB 0x1A +#define X86OpIndRegBExplicitByte 0x1B +#define X86OpIndRegBExplicitWord 0x1C +#define X86OpIndRegBExplicitHalfWord 0x1D +#define X86OpIndRegBExplicitByteOrWord 0x1E +#define X86OpRegCByteHigh 0x1F + +STATIC +int GenSelectByteOrWord(int op, int opSz) +{ + int tmp = opSz == 2; + switch (op) + { + case X86OpRegAByteOrWord: + return tmp ? X86OpRegAWord: X86OpRegAByte; + case X86OpRegCByteOrWord: + return tmp ? X86OpRegCWord : X86OpRegCByte; + case X86OpIndLabelExplicitByteOrWord: + return tmp ? X86OpIndLabelExplicitWord : X86OpIndLabelExplicitByte; + case X86OpIndLocalExplicitByteOrWord: + return tmp ? X86OpIndLocalExplicitWord : X86OpIndLocalExplicitByte; + case X86OpIndRegBExplicitByteOrWord: + return tmp ? X86OpIndRegBExplicitWord: X86OpIndRegBExplicitByte; + } + return op; +} + +STATIC +void GenPrintOperand(int op, int val) +{ + switch (op) + { + case X86OpRegAByte: printf2("al"); break; + case X86OpRegAByteHigh: printf2("ah"); break; + case X86OpRegCByte: printf2("cl"); break; + case X86OpRegCByteHigh: printf2("ch"); break; + case X86OpRegAWord: printf2("ax"); break; + case X86OpRegBWord: printf2("bx"); break; + case X86OpRegCWord: printf2("cx"); break; + case X86OpRegDWord: printf2("dx"); break; + case X86OpRegBpWord: printf2("bp"); break; + case X86OpRegSpWord: printf2("sp"); break; + case X86OpConst: printf2("%d", truncInt(val)); break; + case X86OpLabel: GenPrintLabel(IdentTable + val); break; + case X86OpNumLabel: GenPrintNumLabel(val); break; + case X86OpIndLabel: printf2("["); GenPrintLabel(IdentTable + val); printf2("]"); break; + case X86OpIndLabelExplicitByte: printf2("byte ["); GenPrintLabel(IdentTable + val); printf2("]"); break; + case X86OpIndLabelExplicitWord: printf2("word ["); GenPrintLabel(IdentTable + val); printf2("]"); break; + case X86OpIndLocal: printf2("[bp%+d]", truncInt(val)); break; + case X86OpIndLocalExplicitByte: printf2("byte [bp%+d]", truncInt(val)); break; + case X86OpIndLocalExplicitWord: printf2("word [bp%+d]", truncInt(val)); break; + case X86OpIndRegB: printf2("[bx]"); break; + case X86OpIndRegBExplicitByte: printf2("byte [bx]"); break; + case X86OpIndRegBExplicitWord: printf2("word [bx]"); break; + } +} + +STATIC +void GenPrintOperandSeparator(void) +{ + printf2(", "); +} + +STATIC +void GenPrintNewLine(void) +{ + puts2(""); +} + +STATIC +void GenPrintInstrNoOperand(int instr) +{ + GenPrintInstr(instr, 0); + GenPrintNewLine(); +} + +STATIC +void GenPrintInstr1Operand(int instr, int instrval, int operand, int operandval) +{ + GenPrintInstr(instr, instrval); + GenPrintOperand(operand, operandval); + GenPrintNewLine(); +} + +STATIC +void GenPrintInstr2Operands(int instr, int instrval, int operand1, int operand1val, int operand2, int operand2val) +{ + /* + if (operand2 == X86OpConst && truncUint(operand2val) == 0 && + (instr == X86InstrAdd || instr == X86InstrSub)) + return; + + if (operand2 == X86OpConst && + (operand2val == 1 || operand2val == -1) && + (instr == X86InstrAdd || instr == X86InstrSub)) + { + if ((operand2val == 1 && instr == X86InstrAdd) || + (operand2val == -1 && instr == X86InstrSub)) + GenPrintInstr(X86InstrInc, 0); + else + GenPrintInstr(X86InstrDec, 0); + + GenPrintOperand(operand1, operand1val); + GenPrintNewLine(); + return; + } + */ + + GenPrintInstr(instr, instrval); + GenPrintOperand(operand1, operand1val); + GenPrintOperandSeparator(); + GenPrintOperand(operand2, operand2val); + GenPrintNewLine(); +} + +STATIC +void GenPrintInstr3Operands(int instr, int instrval, + int operand1, int operand1val, + int operand2, int operand2val, + int operand3, int operand3val) +{ + GenPrintInstr(instr, instrval); + GenPrintOperand(operand1, operand1val); + GenPrintOperandSeparator(); + GenPrintOperand(operand2, operand2val); + GenPrintOperandSeparator(); + GenPrintOperand(operand3, operand3val); + GenPrintNewLine(); +} + +STATIC +void GenExtendRegAIfNeeded(int opSz) +{ + if (opSz == -1) + GenPrintInstrNoOperand(X86InstrCbw); + else if (opSz == 1) + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAByteHigh, 0, + X86OpConst, 0); + +} + +STATIC +void GenJumpUncond(int label) +{ + GenPrintInstr1Operand(X86InstrJmp, 0, + X86OpNumLabel, label); +} + +STATIC +void GenJumpIfEqual(int val, int label) +{ + GenPrintInstr2Operands(X86InstrCmp, 0, + X86OpRegAWord, 0, + X86OpConst, val); + GenPrintInstr1Operand(X86InstrJcc, tokEQ, + X86OpNumLabel, label); +} + + +STATIC +void GenJumpIfZero(int label) +{ + printf2(UseLeadingUnderscores ? "\ttest ax, ax\n\tje L%d\n" : "\ttest ax, ax\n\tje ..@L%d\n", label); +} + +STATIC +void GenJumpIfNotZero(int label) +{ + printf2(UseLeadingUnderscores ? "\ttest ax, ax\n\tjne L%d\n" : "\ttest ax, ax\n\tjne ..@L%d\n", label); +} + +fpos_t GenPrologPos; + +STATIC +void GenWriteFrameSize(void) +{ + unsigned size = -CurFxnMinLocalOfs; + int pfx = size ? ' ' : ';'; + if (SizeOfWord == 2 || OutputFormat == FormatSegHuge || OutputFormat == FormatSegUnreal) + printf2("\t%csub\tsp, %10u\n", pfx, size); // 10 chars are enough for 32-bit unsigned ints +} + +STATIC +void GenUpdateFrameSize(void) +{ + fpos_t pos; + fgetpos(OutFile, &pos); + fsetpos(OutFile, &GenPrologPos); + GenWriteFrameSize(); + fsetpos(OutFile, &pos); +} + +STATIC +void GenFxnProlog(void) +{ + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpRegBpWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegBpWord, 0, + X86OpRegSpWord, 0); + fgetpos(OutFile, &GenPrologPos); + GenWriteFrameSize(); +} + +STATIC +void GenGrowStack(int size) +{ + if (!size) + return; + GenPrintInstr2Operands(X86InstrSub, 0, + X86OpRegSpWord, 0, + X86OpConst, size); +} + +STATIC +void GenFxnEpilog(void) +{ + GenUpdateFrameSize(); + GenPrintInstr2Operands(X86InstrMov,0, + X86OpRegSpWord, 0, + X86OpRegBpWord, 0); + GenPrintInstr1Operand(X86InstrPop,0, + X86OpRegBpWord, 0); + GenPrintInstrNoOperand(X86InstrRet); +} + +STATIC +int GenMaxLocalsSize(void) +{ + return 0x7FFF; +} + + +STATIC +void GenReadIdent(int opSz, int label) +{ + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, + X86OpIndLabel, label); + GenExtendRegAIfNeeded(opSz); +} + +STATIC +void GenReadLocal(int opSz, int ofs) +{ + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, + X86OpIndLocal, ofs); + GenExtendRegAIfNeeded(opSz); +} + +STATIC +void GenReadIndirect(int opSz) +{ + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegBWord, 0, + X86OpRegAWord, 0); + + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, + X86OpIndRegB, 0); + GenExtendRegAIfNeeded(opSz); +} + +STATIC +void GenReadCRegIdent(int opSz, int label) +{ + if (opSz == -1) + { + + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpRegAWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAByte, 0, + X86OpIndLabelExplicitByte, label); + GenPrintInstrNoOperand(X86InstrCbw); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCWord, 0, + X86OpRegAWord, 0); + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegAWord, 0); + } + else if (opSz == 1) + { + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCByte, 0, + X86OpIndLabelExplicitByte, label); + GenPrintInstr2Operands(X86InstrXor, 0, + X86OpRegCByteHigh, 0, + X86OpRegCByteHigh, 0); + } + else + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCWord, 0, + X86OpIndLabel, label); +} + +STATIC +void GenReadCRegLocal(int opSz, int ofs) +{ + if (opSz == -1) + { + + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpRegAWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAByte, 0, + X86OpIndLocalExplicitByte, ofs); + GenPrintInstrNoOperand(X86InstrCbw); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCWord, 0, + X86OpRegAWord, 0); + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegAWord, 0); + } + else if (opSz == 1) + { + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCByte, 0, + X86OpIndLocalExplicitByte, ofs); + GenPrintInstr2Operands(X86InstrXor, 0, + X86OpRegCByteHigh, 0, + X86OpRegCByteHigh, 0); + } + else + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCWord, 0, + X86OpIndLocal, ofs); +} + +STATIC +void GenReadCRegIndirect(int opSz) +{ + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegBWord, 0, + X86OpRegAWord, 0); + + if (opSz == -1) + { + + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpRegAWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAByte, 0, + X86OpIndRegBExplicitByte, 0); + GenPrintInstrNoOperand(X86InstrCbw); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCWord, 0, + X86OpRegAWord, 0); + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegAWord, 0); + } + else if (opSz == 1) + { + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCByte, 0, + X86OpIndRegBExplicitByte, 0); + GenPrintInstr2Operands(X86InstrXor, 0, + X86OpRegCByteHigh, 0, + X86OpRegCByteHigh, 0); + } + else + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCWord, 0, + X86OpIndRegB, 0); +} + +STATIC +void GenIncDecIdent(int opSz, int label, int tok) +{ + int instr = X86InstrInc; + + if (tok != tokInc) + instr = X86InstrDec; + + GenPrintInstr1Operand(instr, 0, + GenSelectByteOrWord(X86OpIndLabelExplicitByteOrWord, opSz), label); + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, + X86OpIndLabel, label); + GenExtendRegAIfNeeded(opSz); +} + +STATIC +void GenIncDecLocal(int opSz, int ofs, int tok) +{ + int instr = X86InstrInc; + + if (tok != tokInc) + instr = X86InstrDec; + + GenPrintInstr1Operand(instr, 0, + GenSelectByteOrWord(X86OpIndLocalExplicitByteOrWord, opSz), ofs); + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, + X86OpIndLocal, ofs); + GenExtendRegAIfNeeded(opSz); +} + +STATIC +void GenIncDecIndirect(int opSz, int tok) +{ + int instr = X86InstrInc; + + if (tok != tokInc) + instr = X86InstrDec; + + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegBWord, 0, + X86OpRegAWord, 0); + + GenPrintInstr1Operand(instr, 0, + GenSelectByteOrWord(X86OpIndRegBExplicitByteOrWord, opSz), 0); + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, + X86OpIndRegB, 0); + GenExtendRegAIfNeeded(opSz); +} + +STATIC +void GenPostIncDecIdent(int opSz, int label, int tok) +{ + int instr = X86InstrInc; + + if (tok != tokPostInc) + instr = X86InstrDec; + + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, + X86OpIndLabel, label); + GenExtendRegAIfNeeded(opSz); + GenPrintInstr1Operand(instr, 0, + GenSelectByteOrWord(X86OpIndLabelExplicitByteOrWord, opSz), label); +} + +STATIC +void GenPostIncDecLocal(int opSz, int ofs, int tok) +{ + int instr = X86InstrInc; + + if (tok != tokPostInc) + instr = X86InstrDec; + + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, + X86OpIndLocal, ofs); + GenExtendRegAIfNeeded(opSz); + GenPrintInstr1Operand(instr, 0, + GenSelectByteOrWord(X86OpIndLocalExplicitByteOrWord, opSz), ofs); +} + +STATIC +void GenPostIncDecIndirect(int opSz, int tok) +{ + int instr = X86InstrInc; + + if (tok != tokPostInc) + instr = X86InstrDec; + + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegBWord, 0, + X86OpRegAWord, 0); + + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, + X86OpIndRegB, 0); + GenExtendRegAIfNeeded(opSz); + GenPrintInstr1Operand(instr, 0, + GenSelectByteOrWord(X86OpIndRegBExplicitByteOrWord, opSz), 0); +} + +STATIC +void GenPostAddSubIdent(int opSz, int val, int label, int tok) +{ + int instr = X86InstrAdd; + + if (tok != tokPostAdd) + instr = X86InstrSub; + + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, + X86OpIndLabel, label); + GenExtendRegAIfNeeded(opSz); + GenPrintInstr2Operands(instr, 0, + GenSelectByteOrWord(X86OpIndLabelExplicitByteOrWord, opSz), label, + X86OpConst, val); +} + +STATIC +void GenPostAddSubLocal(int opSz, int val, int ofs, int tok) +{ + int instr = X86InstrAdd; + + if (tok != tokPostAdd) + instr = X86InstrSub; + + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, + X86OpIndLocal, ofs); + GenExtendRegAIfNeeded(opSz); + GenPrintInstr2Operands(instr, 0, + GenSelectByteOrWord(X86OpIndLocalExplicitByteOrWord, opSz), ofs, + X86OpConst, val); +} + +STATIC +void GenPostAddSubIndirect(int opSz, int val, int tok) +{ + int instr = X86InstrAdd; + + if (tok != tokPostAdd) + instr = X86InstrSub; + + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegBWord, 0, + X86OpRegAWord, 0); + + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, + X86OpIndRegB, 0); + GenExtendRegAIfNeeded(opSz); + GenPrintInstr2Operands(instr, 0, + GenSelectByteOrWord(X86OpIndRegBExplicitByteOrWord, opSz), 0, + X86OpConst, val); +} + +#define tokOpNumInt 0x100 +#define tokOpNumUint 0x101 +#define tokOpIdent 0x102 +#define tokOpLocalOfs 0x103 +#define tokOpAcc 0x104 +#define tokOpIndIdent 0x105 +#define tokOpIndLocalOfs 0x106 +#define tokOpIndAcc 0x107 +#define tokOpStack 0x108 +#define tokOpIndStack 0x109 + +#define tokPushAcc 0x200 + +STATIC +int GetOperandInfo(int idx, int lvalSize, int* val, int* size, int* delDeref) +{ + int idx0 = idx; + + *delDeref = 0; + + while (stack[idx][0] >= tokOpNumInt && stack[idx][0] <= tokOpIndAcc) + idx--; + + if (stack[idx][0] == tokUnaryStar) + { + if (lvalSize) + { + // lvalue dereference is implied for the left operand of = + // and for operands of ++/--, these operands contain the + // lvalue address + *size = lvalSize; + *val = 0; + return tokOpIndAcc; + } + + *size = stack[idx][1]; // take size from tokUnaryStar + + *delDeref = 1; + *val = stack[idx + 1][1]; // operand "value" is in tokUnaryStar's operand + return stack[idx + 1][0] + tokOpIndIdent - tokOpIdent; // add indirection + } + + idx = idx0; + + if (lvalSize) + { + // lvalue dereference is implied for the left operand of = + // and for operands of ++/-- + *size = lvalSize; + *val = stack[idx][1]; + + switch (stack[idx][0]) + { + case tokIdent: + + return tokOpIndIdent; + case tokLocalOfs: + return tokOpIndLocalOfs; + + default: + *val = 0; + return tokOpIndAcc; + } + } + + *size = SizeOfWord; + *val = stack[idx][1]; + + switch (stack[idx][0]) + { + case tokNumInt: + return tokOpNumInt; + case tokNumUint: + return tokOpNumUint; + case tokIdent: + return tokOpIdent; + case tokLocalOfs: + return tokOpLocalOfs; + + default: + *val = 0; + return tokOpAcc; + } +} + +STATIC +void GenFuse(int* idx) +{ + int tok; + int oldIdxRight, oldSpRight; + int oldIdxLeft, oldSpLeft; + int opSzRight, opSzLeft; + int opTypRight, opTypLeft; + int opValRight, opValLeft; + int delDerefRight, delDerefLeft; + int num, lvalSize; + + if (*idx < 0) + //error("GenFuse(): idx < 0\n"); + errorInternal(100); + + tok = stack[*idx][0]; + + --*idx; + + oldIdxRight = *idx; + oldSpRight = sp; + + switch (tok) + { + case tokNumInt: + case tokNumUint: + case tokIdent: + case tokLocalOfs: + break; + + case tokShortCirc: + case tokGoto: + GenFuse(idx); + break; + + case tokUnaryStar: + opSzRight = stack[*idx + 1][1]; + GenFuse(idx); + oldIdxRight -= oldSpRight - sp; + + switch (stack[oldIdxRight][0]) + { + case tokIdent: + case tokLocalOfs: + if (stack[oldIdxRight][0] == tokIdent) + stack[oldIdxRight + 1][0] = tokOpIdent; + else + stack[oldIdxRight + 1][0] = tokOpLocalOfs; + stack[oldIdxRight + 1][1] = stack[oldIdxRight][1]; + stack[oldIdxRight][0] = tok; + stack[oldIdxRight][1] = opSzRight; + break; + default: + ins(oldIdxRight + 2, tokOpAcc); + break; + } + break; + + case tokInc: + case tokDec: + case tokPostInc: + case tokPostDec: + opSzRight = stack[*idx + 1][1]; + GenFuse(idx); + oldIdxRight -= oldSpRight - sp; + + switch (stack[oldIdxRight][0]) + { + case tokIdent: + case tokLocalOfs: + if (stack[oldIdxRight][0] == tokIdent) + stack[oldIdxRight + 1][0] = tokOpIndIdent; + else + stack[oldIdxRight + 1][0] = tokOpIndLocalOfs; + stack[oldIdxRight + 1][1] = stack[oldIdxRight][1]; + stack[oldIdxRight][0] = tok; + stack[oldIdxRight][1] = opSzRight; + break; + default: + ins(oldIdxRight + 2, tokOpIndAcc); + break; + } + break; + + case '~': + case tokUnaryPlus: + case tokUnaryMinus: + case tok_Bool: + case tokVoid: + case tokUChar: + case tokSChar: + GenFuse(idx); + oldIdxRight -= oldSpRight - sp; + if (tok == tokUnaryPlus) + del(oldIdxRight + 1, 1); + break; + + case tokPostAdd: + case tokPostSub: + opSzRight = stack[*idx + 1][1]; + num = stack[*idx][1]; + oldIdxRight = --*idx; // skip tokNum + GenFuse(idx); + oldIdxRight -= oldSpRight - sp; + switch (stack[oldIdxRight][0]) + { + case tokIdent: + case tokLocalOfs: + stack[oldIdxRight + 2][0] = tokOpNumInt; + stack[oldIdxRight + 2][1] = num; + if (stack[oldIdxRight][0] == tokIdent) + stack[oldIdxRight + 1][0] = tokOpIndIdent; + else + stack[oldIdxRight + 1][0] = tokOpIndLocalOfs; + stack[oldIdxRight + 1][1] = stack[oldIdxRight][1]; + stack[oldIdxRight][0] = tok; + stack[oldIdxRight][1] = opSzRight; + break; + default: + stack[oldIdxRight + 1][0] = tok; + stack[oldIdxRight + 1][1] = opSzRight; + stack[oldIdxRight + 2][0] = tokOpIndAcc; + ins2(oldIdxRight + 3, tokOpNumInt, num); + break; + } + break; + +/* + Operator-operand fusion: + + ac = lft: ac op= rht: lft = ac: + (load) ("execute") (store) + + *(id/l) *(id/l) *(id/l) + mov a?,mlft op a?,mrht mov mlft,a? + --- + mov cl,mrht + shift ax,cl + --- + mov c?,mrht + cwd + idiv cx + opt: mov ax,dx + + *ac *ac *ac + mov bx,ax < mov bx,ax ; bx preserved + mov a?,[bx] < mov c?,[bx] mov [bx],a? + op ax,cx(cl) + + *ac-stack n/a *ac-stack + pop bx ; bx preserved + mov a?,[bx] mov [bx],a? + + id/num id/num + mov ax,ilft op ax,irht + --- + mov cx,irht + op ax,cx + + l l + lea ax,llft lea cx,lrht + op ax,cx + + ac ac + nop < mov cx,ax + op ax,cx + + ac-stack n/a + pop ax + + lft (*)ac -> lft (*)ac-stack IFF rht is (*)ac + + Legend: + - lft/rht - left/right operand + - num - number + - id - global/static identifier/location + - l - local variable location + - * - dereference operator + - m - memory operand at address id/l + - i - immediate/number/constant operand + - ac - accumulator (al or ax) + - a? - accumulator (al or ax), depending on operand size + - b? - bl or bx, depending on operand size + - >push axlft - need to insert "push ax" at the end of the left operand evaluation + + instruction operand combinations (dst/lft, src/rht): + - r/m, r/imm + - r, m + + special instructions: + - lea r, m + - shl/sar + - mul/imul/idiv + - cbw/cwd + - movsx/movzx +*/ + + case '=': + case tokAssignAdd: + case tokAssignSub: + case tokAssignMul: + case tokAssignDiv: + case tokAssignUDiv: + case tokAssignMod: + case tokAssignUMod: + case tokAssignLSh: + case tokAssignRSh: + case tokAssignURSh: + case tokAssignAnd: + case tokAssignXor: + case tokAssignOr: + case '+': + case '-': + case '*': + case '/': + case tokUDiv: + case '%': + case tokUMod: + case tokLShift: + case tokRShift: + case tokURShift: + case '&': + case '^': + case '|': + case '<': + case '>': + case tokLEQ: + case tokGEQ: + case tokEQ: + case tokNEQ: + case tokULess: + case tokUGreater: + case tokULEQ: + case tokUGEQ: + case tokLogAnd: + case tokLogOr: + case tokComma: + switch (tok) + { + case '=': + case tokAssignAdd: + case tokAssignSub: + case tokAssignMul: + case tokAssignDiv: + case tokAssignUDiv: + case tokAssignMod: + case tokAssignUMod: + case tokAssignLSh: + case tokAssignRSh: + case tokAssignURSh: + case tokAssignAnd: + case tokAssignXor: + case tokAssignOr: + lvalSize = stack[*idx + 1][1]; + break; + default: + lvalSize = 0; + break; + } + + GenFuse(idx); + oldIdxRight -= oldSpRight - sp; + opTypRight = GetOperandInfo(oldIdxRight, 0, &opValRight, &opSzRight, &delDerefRight); + + oldIdxLeft = *idx; oldSpLeft = sp; + GenFuse(idx); + oldIdxLeft -= oldSpLeft - sp; + oldIdxRight -= oldSpLeft - sp; + opTypLeft = GetOperandInfo(oldIdxLeft, lvalSize, &opValLeft, &opSzLeft, &delDerefLeft); + + // operands of &&, || and comma aren't to be fused into &&, || and comma + if (tok == tokLogAnd || tok == tokLogOr || tok == tokComma) + break; + + if (opTypLeft != tokOpAcc && opTypLeft != tokOpIndAcc) + { + // the left operand will be fully fused into the operator, remove it + int cnt = oldIdxLeft - *idx; + del(*idx + 1, cnt); + oldIdxLeft -= cnt; + oldIdxRight -= cnt; + } + else if (opTypRight == tokOpAcc || opTypRight == tokOpIndAcc) + { + // preserve ax after the evaluation of the left operand + // because the right operand's value ends up in ax as well + ins(++oldIdxLeft, tokPushAcc); + oldIdxRight++; + // adjust the left operand "type"/location + if (opTypLeft == tokOpAcc) + opTypLeft = tokOpStack; + else + opTypLeft = tokOpIndStack; + if (delDerefLeft) + { + // remove the dereference, fusing will take care of it + del(oldIdxLeft -= 2, 2); + oldIdxRight -= 2; + } + } + else if (delDerefLeft) + { + // remove the dereference, fusing will take care of it + del(oldIdxLeft - 1, 2); + oldIdxLeft -= 2; + oldIdxRight -= 2; + } + + if (opTypRight != tokOpAcc && opTypRight != tokOpIndAcc) + { + // the right operand will be fully fused into the operator, remove it + int cnt = oldIdxRight - oldIdxLeft; + del(oldIdxLeft + 1, cnt); + oldIdxRight -= cnt; + } + else if (delDerefRight) + { + // remove the dereference, fusing will take care of it + del(oldIdxRight - 1, 2); + oldIdxRight -= 2; + } + + // store the operand sizes into the operator + stack[oldIdxRight + 1][1] = (opSzLeft + 8) * 16 + (opSzRight + 8); + + // fuse the operands into the operator + ins2(oldIdxRight + 2, opTypRight, opValRight); + ins2(oldIdxRight + 2, opTypLeft, opValLeft); + break; + + case ')': + while (stack[*idx][0] != '(') + { + GenFuse(idx); + if (stack[*idx][0] == ',') + --*idx; + } + --*idx; + break; + + default: + //error("GenFuse: unexpected token %s\n", GetTokenName(tok)); + errorInternal(101); + } +} + +STATIC +int GenGetBinaryOperatorInstr(int tok) +{ + switch (tok) + { + case tokPostAdd: + case tokAssignAdd: + case '+': + return X86InstrAdd; + case tokPostSub: + case tokAssignSub: + case '-': + return X86InstrSub; + case '&': + case tokAssignAnd: + return X86InstrAnd; + case '^': + case tokAssignXor: + return X86InstrXor; + case '|': + case tokAssignOr: + return X86InstrOr; + case '<': + case '>': + case tokLEQ: + case tokGEQ: + case tokEQ: + case tokNEQ: + case tokULess: + case tokUGreater: + case tokULEQ: + case tokUGEQ: + return X86InstrCmp; + case '*': + case tokAssignMul: + return X86InstrMul; + case '/': + case '%': + case tokAssignDiv: + case tokAssignMod: + return X86InstrIdiv; + case tokUDiv: + case tokUMod: + case tokAssignUDiv: + case tokAssignUMod: + return X86InstrDiv; + case tokLShift: + case tokAssignLSh: + return X86InstrShl; + case tokRShift: + case tokAssignRSh: + return X86InstrSar; + case tokURShift: + case tokAssignURSh: + return X86InstrShr; + + default: + //error("Error: Invalid operator\n"); + errorInternal(102); + return 0; + } +} + +// Newer, less stack-dependent code generator, +// generates more compact code (~30% less) than the stack-based generator +#ifndef CG_STACK_BASED +STATIC +void GenExpr1(void) +{ + int s = sp - 1; + int i; + + if (stack[s][0] == tokIf || stack[s][0] == tokIfNot || stack[s][0] == tokReturn) + s--; + GenFuse(&s); + +#ifndef NO_ANNOTATIONS + printf2("; Fused expression: \""); + for (i = 0; i < sp; i++) + { + int tok = stack[i][0]; + switch (tok) + { + case tokNumInt: + case tokOpNumInt: + printf2("%d", truncInt(stack[i][1])); + break; + case tokNumUint: + case tokOpNumUint: + printf2("%uu", truncUint(stack[i][1])); + break; + case tokIdent: + case tokOpIdent: + { + char* p = IdentTable + stack[i][1]; + if (isdigit(*p)) + printf2("L"); + printf2("%s", p); + } + break; + case tokOpIndIdent: + printf2("*%s", IdentTable + stack[i][1]); + break; + case tokShortCirc: + if (stack[i][1] >= 0) + printf2("[sh&&->%d]", stack[i][1]); + else + printf2("[sh||->%d]", -stack[i][1]); + break; + case tokGoto: + printf2("[goto->%d]", stack[i][1]); + break; + case tokLocalOfs: + case tokOpLocalOfs: + printf2("(@%d)", truncInt(stack[i][1])); + break; + case tokOpIndLocalOfs: + printf2("*(@%d)", truncInt(stack[i][1])); + break; + case tokUnaryStar: + printf2("*(%d)", stack[i][1]); + break; + case '(': case ',': + printf2("%c", tok); + break; + case ')': + printf2(")%d", stack[i][1]); + break; + case tokOpAcc: + printf2("ax"); + break; + case tokOpIndAcc: + printf2("*ax"); + break; + case tokOpStack: + printf2("*sp"); + break; + case tokOpIndStack: + printf2("**sp"); + break; + case tokPushAcc: + printf2("push-ax"); + break; + case tokIf: + printf2("IF"); + break; + case tokIfNot: + printf2("IF!"); + break; + case tokReturn: + break; + default: + printf2("%s", GetTokenName(tok)); + switch (tok) + { + case tokLogOr: case tokLogAnd: + printf2("[%d]", stack[i][1]); + break; + case '=': + case tokInc: case tokDec: + case tokPostInc: case tokPostDec: + case tokAssignAdd: case tokAssignSub: + case tokPostAdd: case tokPostSub: + case tokAssignMul: case tokAssignDiv: case tokAssignMod: + case tokAssignUDiv: case tokAssignUMod: + case tokAssignLSh: case tokAssignRSh: case tokAssignURSh: + case tokAssignAnd: case tokAssignXor: case tokAssignOr: + printf2("(%d)", stack[i][1]); + break; + } + break; + } + printf2(" "); + } + printf2("\"\n"); +#endif + + for (i = 0; i < sp; i++) + { + int tok = stack[i][0]; + int v = stack[i][1]; + int instr; + + switch (tok) + { + case tokNumInt: + case tokNumUint: + // Don't load operand into ax when ax is going to be pushed next, push it directly + if (!(i + 1 < sp && stack[i + 1][0] == ',')) +// GenPrintInstr2Operands(X86InstrMov, 0, +// X86OpRegAWord, 0, +// X86OpConst, v); + printf2("\tmov ax, %d\n", v); + break; + case tokIdent: + // Don't load operand into ax when ax is going to be pushed next, push it directly + if (!(i + 1 < sp && (stack[i + 1][0] == ',' || stack[i + 1][0] == ')'))) + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAWord, 0, + X86OpLabel, v); + break; + case tokLocalOfs: + GenPrintInstr2Operands(X86InstrLea, 0, + X86OpRegAWord, 0, + X86OpIndLocal, v); + break; + + case '~': + GenPrintInstr1Operand(X86InstrNot, 0, + X86OpRegAWord, 0); + break; + case tokUnaryMinus: + GenPrintInstr1Operand(X86InstrNeg, 0, + X86OpRegAWord, 0); + break; + case tok_Bool: + GenPrintInstr2Operands(X86InstrTest, 0, + X86OpRegAWord, 0, + X86OpRegAWord, 0); + int labelCC = LabelCnt++; + int labelCCAfter = LabelCnt++; + GenPrintInstr1Operand(X86InstrJcc, tokNEQ, + X86OpNumLabel, labelCC); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAByte, 0, + X86OpConst, 0); + GenPrintInstr1Operand(X86InstrJmp, 0, + X86OpNumLabel, labelCCAfter); + GenNumLabel(labelCC); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAByte, 0, + X86OpConst, 1); + GenNumLabel(labelCCAfter); + + // fallthrough + case tokSChar: + GenPrintInstrNoOperand(X86InstrCbw); + break; + case tokUChar: + GenPrintInstr2Operands(X86InstrAnd, 0, + X86OpRegAWord, 0, + X86OpConst, 0xFF); + break; + + case tokShortCirc: + if (v >= 0) + GenJumpIfZero(v); // && + else + GenJumpIfNotZero(-v); // || + break; + case tokGoto: + GenJumpUncond(v); + break; + case tokLogAnd: + case tokLogOr: + GenNumLabel(v); + break; + + case tokPushAcc: + // TBD??? handle similarly to ','??? + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpRegAWord, 0); + break; + + case ',': + // push operand directly if it hasn't been loaded into ax + if (stack[i - 2][0] == tokUnaryStar && stack[i - 2][1] == SizeOfWord) + { + switch (stack[i - 1][0]) + { + case tokOpIdent: + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpIndLabelExplicitWord, stack[i - 1][1]); + break; + case tokOpLocalOfs: + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpIndLocalExplicitWord, stack[i - 1][1]); + break; + case tokOpAcc: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegBWord, 0, + X86OpRegAWord, 0); + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpIndRegBExplicitWord, 0); + break; + } + } + else + { + switch (stack[i - 1][0]) + { + case tokNumInt: + case tokNumUint: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAWord, 0, + X86OpConst, stack[i - 1][1]); + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpRegAWord, 0); + break; + case tokIdent: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAWord, 0, + X86OpLabel, stack[i - 1][1]); + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpRegAWord, 0); + break; + default: + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpRegAWord, 0); + break; + } + } + break; + + case tokUnaryStar: + // Don't load operand into ax when ax is going to be pushed next, push it directly + if (!(v == SizeOfWord && i + 2 < sp && stack[i + 2][0] == ',')) + { + switch (stack[i + 1][0]) + { + case tokOpIdent: + GenReadIdent(v, stack[i + 1][1]); + break; + case tokOpLocalOfs: + GenReadLocal(v, stack[i + 1][1]); + break; + case tokOpAcc: + GenReadIndirect(v); + break; + } + } + i++; + break; + + case tokInc: + case tokDec: + switch (stack[i + 1][0]) + { + case tokOpIndIdent: + GenIncDecIdent(v, stack[i + 1][1], tok); + break; + case tokOpIndLocalOfs: + GenIncDecLocal(v, stack[i + 1][1], tok); + break; + case tokOpIndAcc: + GenIncDecIndirect(v, tok); + break; + } + i++; + break; + + case tokPostInc: + case tokPostDec: + switch (stack[i + 1][0]) + { + case tokOpIndIdent: + GenPostIncDecIdent(v, stack[i + 1][1], tok); + break; + case tokOpIndLocalOfs: + GenPostIncDecLocal(v, stack[i + 1][1], tok); + break; + case tokOpIndAcc: + GenPostIncDecIndirect(v, tok); + break; + } + i++; + break; + + case tokPostAdd: + case tokPostSub: + switch (stack[i + 1][0]) + { + case tokOpIndIdent: + GenPostAddSubIdent(v, stack[i + 2][1], stack[i + 1][1], tok); + break; + case tokOpIndLocalOfs: + GenPostAddSubLocal(v, stack[i + 2][1], stack[i + 1][1], tok); + break; + case tokOpIndAcc: + GenPostAddSubIndirect(v, stack[i + 2][1], tok); + break; + } + i += 2; + break; + + case '=': + case tokAssignAdd: + case tokAssignSub: + case tokAssignMul: + case tokAssignDiv: + case tokAssignUDiv: + case tokAssignMod: + case tokAssignUMod: + case tokAssignLSh: + case tokAssignRSh: + case tokAssignURSh: + case tokAssignAnd: + case tokAssignXor: + case tokAssignOr: + case '+': + case '-': + case '*': + case '/': + case tokUDiv: + case '%': + case tokUMod: + case tokLShift: + case tokRShift: + case tokURShift: + case '&': + case '^': + case '|': + case '<': + case '>': + case tokLEQ: + case tokGEQ: + case tokEQ: + case tokNEQ: + case tokULess: + case tokUGreater: + case tokULEQ: + case tokUGEQ: + // save the right operand from ax in cx, so it's not + // overwritten by the left operand in ax + if (tok != '=') + { + if (stack[i + 2][0] == tokOpAcc) + { + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCWord, 0, + X86OpRegAWord, 0); + } + else if (stack[i + 2][0] == tokOpIndAcc) + { + GenReadCRegIndirect(v % 16 - 8); + } + } + + // load the left operand into ax (or the right operand if it's '=') + + if (tok == '=') + { + if (stack[i + 1][0] == tokOpIndAcc) + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegBWord, 0, + X86OpRegAWord, 0); + // "swap" left and right operands + i++; + v = v / 16 + v % 16 * 16; + } + + switch (stack[i + 1][0]) + { + case tokOpNumInt: + case tokOpNumUint: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAWord, 0, + X86OpConst, stack[i + 1][1]); + break; + case tokOpIdent: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAWord, 0, + X86OpLabel, stack[i + 1][1]); + break; + case tokOpLocalOfs: + GenPrintInstr2Operands(X86InstrLea, 0, + X86OpRegAWord, 0, + X86OpIndLocal, stack[i + 1][1]); + break; + case tokOpAcc: + break; + case tokOpIndIdent: + GenReadIdent(v / 16 - 8, stack[i + 1][1]); + break; + case tokOpIndLocalOfs: + GenReadLocal(v / 16 - 8, stack[i + 1][1]); + break; + case tokOpIndAcc: + GenReadIndirect(v / 16 - 8); + break; + case tokOpStack: + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegAWord, 0); + break; + case tokOpIndStack: + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegBWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, v / 16 - 8), 0, + X86OpIndRegB, 0); + GenExtendRegAIfNeeded(v / 16 - 8); + break; + } + + if (tok == '=') + { + // "unswap" left and right operands + i--; + v = v / 16 + v % 16 * 16; + + if (stack[i + 1][0] == tokOpIndStack) + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegBWord, 0); + } + + // operator + switch (tok) + { + case tokAssignAdd: + case tokAssignSub: + case tokAssignAnd: + case tokAssignXor: + case tokAssignOr: + case '+': + case '-': + case '&': + case '^': + case '|': + case '<': + case '>': + case tokLEQ: + case tokGEQ: + case tokEQ: + case tokNEQ: + case tokULess: + case tokUGreater: + case tokULEQ: + case tokUGEQ: + instr = GenGetBinaryOperatorInstr(tok); + + switch (stack[i + 2][0]) + { + case tokOpNumInt: + case tokOpNumUint: + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpConst, stack[i + 2][1]); + break; + case tokOpIdent: + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpLabel, stack[i + 2][1]); + break; + case tokOpLocalOfs: + GenPrintInstr2Operands(X86InstrLea, 0, + X86OpRegCWord, 0, + X86OpIndLocal, stack[i + 2][1]); + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpRegCWord, 0); + break; + case tokOpAcc: + case tokOpIndAcc: + // right operand in cx already + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpRegCWord, 0); + break; + case tokOpIndIdent: + if (v % 16 - 8 != SizeOfWord) + { + GenReadCRegIdent(v % 16 - 8, stack[i + 2][1]); + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpRegCWord, 0); + } + else + { + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpIndLabel, stack[i + 2][1]); + } + break; + case tokOpIndLocalOfs: + if (v % 16 - 8 != SizeOfWord) + { + GenReadCRegLocal(v % 16 - 8, stack[i + 2][1]); + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpRegCWord, 0); + } + else + { + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpIndLocal, stack[i + 2][1]); + } + break; + } + + if (i + 3 < sp && (stack[i + 3][0] == tokIf || stack[i + 3][0] == tokIfNot)) + { + switch (tok) + { + case '<': + case tokULess: + case '>': + case tokUGreater: + case tokLEQ: + case tokULEQ: + case tokGEQ: + case tokUGEQ: + case tokEQ: + case tokNEQ: + if (stack[i + 3][0] == tokIf) + GenPrintInstr1Operand(X86InstrJcc, tok, + X86OpNumLabel, stack[i + 3][1]); + else + GenPrintInstr1Operand(X86InstrJNotCc, tok, + X86OpNumLabel, stack[i + 3][1]); + break; + } + } + else + { + switch (tok) + { + case '<': + case tokULess: + case '>': + case tokUGreater: + case tokLEQ: + case tokULEQ: + case tokGEQ: + case tokUGEQ: + case tokEQ: + case tokNEQ: + { + int labelCC = LabelCnt++; + int labelCCAfter = LabelCnt++; + GenPrintInstr1Operand(X86InstrJcc, tok, + X86OpNumLabel, labelCC); +// GenPrintInstr2Operands(X86InstrMov, 0, +// X86OpRegAByte, 0, +// X86OpConst, 0); + puts2("xor al, al"); + GenPrintInstr1Operand(X86InstrJmp, 0, + X86OpNumLabel, labelCCAfter); + GenNumLabel(labelCC); +// GenPrintInstr2Operands(X86InstrMov, 0, +// X86OpRegAByte, 0, +// X86OpConst, 1); + puts2("mov al, 1"); + GenNumLabel(labelCCAfter); + + GenPrintInstrNoOperand(X86InstrCbw); + } + break; + } + } + break; + + case '*': + case tokAssignMul: + instr = GenGetBinaryOperatorInstr(tok); + + switch (stack[i + 2][0]) + { + case tokOpNumInt: + case tokOpNumUint: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegBWord, 0, + X86OpConst, stack[i + 2][1]); + GenPrintInstr1Operand(X86InstrImul, 0, + X86OpRegBWord, 0); + break; + case tokOpIdent: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegBWord, 0, + X86OpLabel, stack[i + 2][1]); + GenPrintInstr1Operand(X86InstrImul, 0, + X86OpRegBWord, 0); + break; + case tokOpLocalOfs: + GenPrintInstr2Operands(X86InstrLea, 0, + X86OpRegCWord, 0, + X86OpIndLocal, stack[i + 2][1]); + GenPrintInstr1Operand(instr, 0, + X86OpRegCWord, 0); + break; + case tokOpAcc: + case tokOpIndAcc: + // right operand in cx already + GenPrintInstr1Operand(instr, 0, + X86OpRegCWord, 0); + break; + case tokOpIndIdent: + if (v % 16 - 8 != SizeOfWord) + { + GenReadCRegIdent(v % 16 - 8, stack[i + 2][1]); + GenPrintInstr1Operand(instr, 0, + X86OpRegCWord, 0); + } + else + { + GenPrintInstr1Operand(instr, 0, + X86OpIndLabelExplicitWord, stack[i + 2][1]); + } + break; + case tokOpIndLocalOfs: + if (v % 16 - 8 != SizeOfWord) + { + GenReadCRegLocal(v % 16 - 8, stack[i + 2][1]); + GenPrintInstr1Operand(instr, 0, + X86OpRegCWord, 0); + } + else + { + GenPrintInstr1Operand(instr, 0, + X86OpIndLocalExplicitWord, stack[i + 2][1]); + } + break; + } + break; + + case '/': + case tokUDiv: + case '%': + case tokUMod: + case tokAssignDiv: + case tokAssignUDiv: + case tokAssignMod: + case tokAssignUMod: + instr = GenGetBinaryOperatorInstr(tok); + + switch (tok) + { + case '/': + case '%': + case tokAssignDiv: + case tokAssignMod: + + GenPrintInstrNoOperand(X86InstrCwd); + break; + default: +// GenPrintInstr2Operands(X86InstrMov, 0, +// X86OpRegDWord, 0, +// X86OpConst, 0); + puts2("\txor dx, dx\n"); + break; + } + + switch (stack[i + 2][0]) + { + case tokOpNumInt: + case tokOpNumUint: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCWord, 0, + X86OpConst, stack[i + 2][1]); + GenPrintInstr1Operand(instr, 0, + X86OpRegCWord, 0); + break; + case tokOpIdent: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCWord, 0, + X86OpLabel, stack[i + 2][1]); + GenPrintInstr1Operand(instr, 0, + X86OpRegCWord, 0); + break; + case tokOpLocalOfs: + GenPrintInstr2Operands(X86InstrLea, 0, + X86OpRegCWord, 0, + X86OpIndLocal, stack[i + 2][1]); + GenPrintInstr1Operand(instr, 0, + X86OpRegCWord, 0); + break; + case tokOpAcc: + case tokOpIndAcc: + // right operand in cx already + GenPrintInstr1Operand(instr, 0, + X86OpRegCWord, 0); + break; + case tokOpIndIdent: + if (v % 16 - 8 != SizeOfWord) + { + GenReadCRegIdent(v % 16 - 8, stack[i + 2][1]); + GenPrintInstr1Operand(instr, 0, + X86OpRegCWord, 0); + } + else + { + GenPrintInstr1Operand(instr, 0, + X86OpIndLabelExplicitWord, stack[i + 2][1]); + } + break; + case tokOpIndLocalOfs: + if (v % 16 - 8 != SizeOfWord) + { + GenReadCRegLocal(v % 16 - 8, stack[i + 2][1]); + GenPrintInstr1Operand(instr, 0, + X86OpRegCWord, 0); + } + else + { + GenPrintInstr1Operand(instr, 0, + X86OpIndLocalExplicitWord, stack[i + 2][1]); + } + } + + if (tok == '%' || tok == tokAssignMod || + tok == tokUMod || tok == tokAssignUMod) + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAWord, 0, + X86OpRegDWord, 0); + break; + + case tokLShift: + case tokRShift: + case tokURShift: + case tokAssignLSh: + case tokAssignRSh: + case tokAssignURSh: + instr = GenGetBinaryOperatorInstr(tok); + + switch (stack[i + 2][0]) + { + case tokOpNumInt: + case tokOpNumUint: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCByte, 0, + X86OpConst, stack[i + 2][1]); + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpRegCByte, 0); + break; + case tokOpIdent: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCByte, 0, + X86OpLabel, stack[i + 2][1]); + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpRegCByte, 0); + break; + case tokOpLocalOfs: + GenPrintInstr2Operands(X86InstrLea, 0, + X86OpRegCWord, 0, + X86OpIndLocal, stack[i + 2][1]); + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpRegCByte, 0); + break; + case tokOpAcc: + case tokOpIndAcc: + // right operand in cx already + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpRegCByte, 0); + break; + case tokOpIndIdent: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCByte, 0, + X86OpIndLabel, stack[i + 2][1]); + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpRegCByte, 0); + break; + case tokOpIndLocalOfs: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCByte, 0, + X86OpIndLocal, stack[i + 2][1]); + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpRegCByte, 0); + break; + } + break; + + case '=': + break; + + default: + //error("Error: Internal Error: GenExpr1() a: unexpected token %s\n", GetTokenName(tok)); + errorInternal(103); + break; + } + + // store ax into the left operand, if needed + switch (tok) + { + case '=': + case tokAssignAdd: + case tokAssignSub: + case tokAssignMul: + case tokAssignDiv: + case tokAssignUDiv: + case tokAssignMod: + case tokAssignUMod: + case tokAssignLSh: + case tokAssignRSh: + case tokAssignURSh: + case tokAssignAnd: + case tokAssignXor: + case tokAssignOr: + switch (stack[i + 1][0]) + { + case tokOpIndIdent: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpIndLabel, stack[i + 1][1], + GenSelectByteOrWord(X86OpRegAByteOrWord, v / 16 - 8), 0); + break; + case tokOpIndLocalOfs: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpIndLocal, stack[i + 1][1], + GenSelectByteOrWord(X86OpRegAByteOrWord, v / 16 - 8), 0); + break; + case tokOpIndAcc: + case tokOpIndStack: + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpIndRegB, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, v / 16 - 8), 0); + break; + } + // the result of the expression is of type of the + // left lvalue operand, so, "truncate" it if needed + GenExtendRegAIfNeeded(v / 16 - 8); + } + i += 2; + break; + + case ')': + // DONE: "call ident" + if (stack[i - 1][0] == tokIdent) + { + GenPrintInstr1Operand(X86InstrCall, 0, + X86OpLabel, stack[i - 1][1]); + } + else + { +// GenPrintInstr1Operand(X86InstrCall, 0, +// X86OpRegAWord, 0); + puts2("\tcall ax\n"); + } + GenGrowStack(-v); + break; + + case '(': + case tokIf: + case tokIfNot: + case tokReturn: + break; + + case tokVoid: + case tokComma: + break; + + default: + //error("Error: Internal Error: GenExpr1() b: unexpected token %s\n", GetTokenName(tok)); + errorInternal(104); + break; + } + } +} +#else // #ifndef CG_STACK_BASED +// Original, primitive stack-based code generator +// DONE: test 32-bit code generation +STATIC +void GenExpr0(void) +{ + int i; + int gotUnary = 0; + + for (i = 0; i < sp; i++) + { + int tok = stack[i][0]; + int v = stack[i][1]; + +#ifndef NO_ANNOTATIONS + switch (tok) + { + case tokNumInt: printf2("; %d\n", truncInt(v)); break; + case tokNumUint: printf2("; %uu\n", truncUint(v)); break; + case tokIdent: printf2("; %s\n", IdentTable + v); break; + case tokLocalOfs: printf2("; local ofs\n"); break; + case ')': printf2("; ) fxn call\n"); break; + case tokUnaryStar: printf2("; * (read dereference)\n"); break; + case '=': printf2("; = (write dereference)\n"); break; + case tokShortCirc: printf2("; short-circuit "); break; + case tokGoto: printf2("; sh-circ-goto "); break; + case tokLogAnd: printf2("; short-circuit && target\n"); break; + case tokLogOr: printf2("; short-circuit || target\n"); break; + case tokIf: case tokIfNot: case tokReturn: break; + default: printf2("; %s\n", GetTokenName(tok)); break; + } +#endif + + switch (tok) + { + case tokNumInt: + case tokNumUint: + if (gotUnary) + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpRegAWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAWord, 0, + X86OpConst, v); + gotUnary = 1; + break; + + case tokIdent: + if (gotUnary) + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpRegAWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAWord, 0, + X86OpLabel, v); + gotUnary = 1; + break; + + case tokLocalOfs: + if (gotUnary) + GenPrintInstr1Operand(X86InstrPush, 0, + X86OpRegAWord, 0); + GenPrintInstr2Operands(X86InstrLea, 0, + X86OpRegAWord, 0, + X86OpIndLocal, v); + gotUnary = 1; + break; + + case ')': + GenPrintInstr1Operand(X86InstrCall, 0, + X86OpRegAWord, 0); + GenGrowStack(-v); + break; + + case tokUnaryStar: + GenReadIndirect(v); + break; + + case tokUnaryPlus: + break; + case '~': + GenPrintInstr1Operand(X86InstrNot, 0, + X86OpRegAWord, 0); + break; + case tokUnaryMinus: + GenPrintInstr1Operand(X86InstrNeg, 0, + X86OpRegAWord, 0); + break; + + case '+': + case '-': + case '*': + case '&': + case '^': + case '|': + { + int instr = GenGetBinaryOperatorInstr(tok); + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegBWord, 0); + if (tok == '-') +// GenPrintInstr2Operands(X86InstrXchg, 0, +// X86OpRegAWord, 0, +// X86OpRegBWord, 0); + puts2("\txchg ax, bx\n"); + if (tok != '*') + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpRegBWord, 0); + else + GenPrintInstr1Operand(instr, 0, + X86OpRegBWord, 0); + } + break; + + case '/': + case tokUDiv: + case '%': + case tokUMod: +// GenPrintInstr1Operand(X86InstrPop, 0, +// X86OpRegBWord, 0); +// GenPrintInstr2Operands(X86InstrXchg, 0, +// X86OpRegAWord, 0, +// X86OpRegBWord, 0); + puts2("\tpop bx\n\txchg ax, bx\n"); + if (tok == '/' || tok == '%') + { + + GenPrintInstrNoOperand(X86InstrCwd); + GenPrintInstr1Operand(X86InstrIdiv, 0, + X86OpRegBWord, 0); + } + else + { + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegDWord, 0, + X86OpConst, 0); + GenPrintInstr1Operand(X86InstrDiv, 0, + X86OpRegBWord, 0); + } + if (tok == '%' || tok == tokUMod) + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAWord, 0, + X86OpRegDWord, 0); + break; + + case tokLShift: + case tokRShift: + case tokURShift: + { + int instr = GenGetBinaryOperatorInstr(tok); + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegCWord, 0); + GenPrintInstr2Operands(X86InstrXchg, 0, + X86OpRegAWord, 0, + X86OpRegCWord, 0); + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpRegCByte, 0); + } + break; + + case tokInc: + GenIncDecIndirect(v, tok); + break; + case tokDec: + GenIncDecIndirect(v, tok); + break; + case tokPostInc: + GenPostIncDecIndirect(v, tok); + break; + case tokPostDec: + GenPostIncDecIndirect(v, tok); + break; + + case tokPostAdd: + case tokPostSub: + { + int instr = GenGetBinaryOperatorInstr(tok); + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegBWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCWord, 0, + X86OpRegAWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0, + X86OpIndRegB, 0); + GenPrintInstr2Operands(instr, 0, + X86OpIndRegB, 0, + GenSelectByteOrWord(X86OpRegCByteOrWord, v), 0); + GenExtendRegAIfNeeded(v); + } + break; + + case tokAssignAdd: + case tokAssignSub: + case tokAssignMul: + case tokAssignAnd: + case tokAssignXor: + case tokAssignOr: + { + int instr = GenGetBinaryOperatorInstr(tok); + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegBWord, 0); + if (tok != tokAssignMul) + { + GenPrintInstr2Operands(instr, 0, + X86OpIndRegB, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0); + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0, + X86OpIndRegB, 0); + } + else + { + GenPrintInstr1Operand(instr, 0, + GenSelectByteOrWord(X86OpIndRegBExplicitByteOrWord, v), 0); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpIndRegB, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0); + } + GenExtendRegAIfNeeded(v); + } + break; + + case tokAssignDiv: + case tokAssignUDiv: + case tokAssignMod: + case tokAssignUMod: + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegBWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCWord, 0, + X86OpRegAWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0, + X86OpIndRegB, 0); + GenExtendRegAIfNeeded(v); + if (tok == tokAssignDiv || tok == tokAssignMod) + { + + GenPrintInstrNoOperand(X86InstrCwd); + GenPrintInstr1Operand(X86InstrIdiv, 0, + X86OpRegCWord, 0); + } + else + { + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegDWord, 0, + X86OpConst, 0); + GenPrintInstr1Operand(X86InstrDiv, 0, + X86OpRegCWord, 0); + } + if (tok == tokAssignMod || tok == tokAssignUMod) + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAWord, 0, + X86OpRegDWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpIndRegB, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0); + GenExtendRegAIfNeeded(v); + break; + + case tokAssignLSh: + case tokAssignRSh: + case tokAssignURSh: + { + int instr = GenGetBinaryOperatorInstr(tok); + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegBWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegCWord, 0, + X86OpRegAWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0, + X86OpIndRegB, 0); + GenExtendRegAIfNeeded(v); + GenPrintInstr2Operands(instr, 0, + X86OpRegAWord, 0, + X86OpRegCByte, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpIndRegB, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0); + GenExtendRegAIfNeeded(v); + } + break; + + case '=': + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegBWord, 0); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpIndRegB, 0, + GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0); + GenExtendRegAIfNeeded(v); + break; + + case '<': + case tokULess: + case '>': + case tokUGreater: + case tokLEQ: + case tokULEQ: + case tokGEQ: + case tokUGEQ: + case tokEQ: + case tokNEQ: + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegBWord, 0); + GenPrintInstr2Operands(X86InstrCmp, 0, + X86OpRegBWord, 0, + X86OpRegAWord, 0); + GenPrintInstr1Operand(X86InstrSetCc, tok, + X86OpRegAByte, 0); + + GenPrintInstrNoOperand(X86InstrCbw); + break; + + case tok_Bool: + GenPrintInstr2Operands(X86InstrTest, 0, + X86OpRegAWord, 0, + X86OpRegAWord, 0); + GenPrintInstr1Operand(X86InstrSetCc, tokNEQ, + X86OpRegAByte, 0); + // fallthrough + case tokSChar: + + GenPrintInstrNoOperand(X86InstrCbw); + break; + case tokUChar: + GenPrintInstr2Operands(X86InstrAnd, 0, + X86OpRegAWord, 0, + X86OpConst, 0xFF); + break; + + case tokShortCirc: +#ifndef NO_ANNOTATIONS + if (v >= 0) + printf2("&&\n"); + else + printf2("||\n"); +#endif + if (v >= 0) + GenJumpIfZero(v); // && + else + GenJumpIfNotZero(-v); // || + gotUnary = 0; + break; + case tokGoto: +#ifndef NO_ANNOTATIONS + printf2("goto\n"); +#endif + GenJumpUncond(v); + gotUnary = 0; + break; + case tokLogAnd: + case tokLogOr: + GenNumLabel(v); + break; + + case tokVoid: + gotUnary = 0; + break; + + case tokComma: + case ',': + case '(': + case tokReturn: + break; + + case tokIf: + GenJumpIfNotZero(stack[i][1]); + break; + case tokIfNot: + GenJumpIfZero(stack[i][1]); + break; + + default: + //error("Error: Internal Error: GenExpr0(): unexpected token %s\n", GetTokenName(tok)); + errorInternal(105); + break; + } + } +} +#endif // #ifndef CG_STACK_BASED + +STATIC +void GenDumpChar(int ch) +{ + static int quot = 0; + + if (ch < 0) + { + if (quot) + { + printf2("\""); + quot = 0; + } + if (TokenStringLen) + printf2("\n"); + return; + } + + if (TokenStringLen == 0) + GenStartAsciiString(); + + // quote ASCII chars for better readability + if (ch >= 0x20 && ch <= 0x7E && ch != '"') + { + if (!quot) + { + quot = 1; + if (TokenStringLen) + printf2(","); + printf2("\""); + } + printf2("%c", ch); + } + else + { + if (quot) + { + quot = 0; + printf2("\""); + } + if (TokenStringLen) + printf2(","); + printf2("%u", ch & 0xFFu); + } +} + +STATIC +void GenExpr(void) +{ + if (GenExterns) + { + int i; + for (i = 0; i < sp; i++) + if (stack[i][0] == tokIdent && !isdigit(IdentTable[stack[i][1]])) + GenAddGlobal(IdentTable + stack[i][1], 2); + } +#ifndef CG_STACK_BASED + GenExpr1(); +#else + GenExpr0(); +#endif +} + +STATIC +void GenFin(void) +{ + if (StructCpyLabel) + { + puts2(CodeHeaderFooter[0]); + + GenNumLabel(StructCpyLabel); + CurFxnMinLocalOfs = 0; + GenFxnProlog(); + + puts2("\tmov\tdi, [bp+8]\n" + "\tmov\tsi, [bp+6]\n" + "\tmov\tcx, [bp+4]\n" + "\tcld\n" + "\trep\tmovsb\n" + "\tmov\tax, [bp+8]"); + + GenFxnEpilog(); + + puts2(CodeHeaderFooter[1]); + } + +#ifndef NO_STRUCT_BY_VAL + if (StructPushLabel) + { + puts2(CodeHeaderFooter[0]); + + GenNumLabel(StructPushLabel); + CurFxnMinLocalOfs = 0; + GenFxnProlog(); + + puts2("\tmov\tdx, [bp+2]\n" // dx = return address + "\tmov\tsi, [bp+4]\n" // si = &struct + "\tmov\tcx, [bp+6]\n" // cx = sizeof(struct) + "\tmov\tbp, [bp]\n" // restore bp + + "\tmov\tax, cx\n" // ax = sizeof(struct) + "\tinc\tax\n" // ax = sizeof(struct) + 1 + "\tand\tax, -2\n" // ax = sizeof(struct) rounded up to multiple of 2 bytes + "\tadd\tsp, 4*2\n" // remove bp, return address and 2 args from stack + "\tsub\tsp, ax"); // allocate stack space for struct + + puts2("\tmov\tdi, sp\n" // di = where struct should be copied to + "\tcld\n" + "\trep\tmovsb\n" // copy + + "\tpop\tax\n" // return first 2 bytes of struct in ax + "\tpush\tax\n" + "\txor\tcx, cx\n" // Set 0 in cx to push (8086 cant push numbers in stack) + "\tpush\tcx\n" // caller will remove this 0 and first 2 bytes of struct from stack (as 2 args) + "\tpush\tdx\n" // and then it will push ax (first 2 bytes of struct) back + "\tret"); // actually return to return address saved in dx + + +// GenFxnEpilog(); + + puts2(CodeHeaderFooter[1]); + } +#endif + + + if (GenExterns) + { + int i = 0; + + puts2(""); + while (i < GlobalsTableLen) + { + if (GlobalsTable[i] == 2) + { + printf2("\textern\t"); + GenPrintLabel(GlobalsTable + i + 2); + puts2(""); + } + i += GlobalsTable[i + 1] + 2; + } + } +} + +#ifdef CAN_COMPILE_32BIT + +void GenIsrProlog(void) +{ + error("Not supported in this platform"); +} + +void GenIsrEpilog(void) +{ + error("Not supported in this platform"); +} +#endif \ No newline at end of file diff --git a/v0100/smlrc.c b/v0100/smlrc.c index 04681be..543a521 100644 --- a/v0100/smlrc.c +++ b/v0100/smlrc.c @@ -2374,12 +2374,16 @@ void errorRedecl(char* s) } #ifdef MIPS -#ifndef CAN_COMPILE_32BIT -#error MIPS target requires a 32-bit compiler -#endif -#include "cgmips.c" + #ifndef CAN_COMPILE_32BIT + #error MIPS target requires a 32-bit compiler + #endif + #include "cgmips.c" #else -#include "cgx86.c" + #ifdef ONLY8086 + #include "cg8086.c" + #else + #include "cgx86.c" + #endif #endif // #ifdef MIPS // expr.c code @@ -5928,8 +5932,8 @@ void error(char* format, ...) if (OutFile) fclose(OutFile); - - printf("Error in \"%s\" (%d:%d)\n", FileNames[fidx], LineNo, LinePos); + // Make error output compatilble with Modern Editors (VSCode, Atom, etc) + printf("Error in \"%s\":%d:%d:\n", FileNames[fidx], LineNo, LinePos); #ifndef __SMALLER_C__ vprintf(format, vl); diff --git a/v0100/smlrcc.c b/v0100/smlrcc.c index 2d80b1f..28d12a0 100644 --- a/v0100/smlrcc.c +++ b/v0100/smlrcc.c @@ -152,35 +152,41 @@ typedef struct char* OutName; -#define FormatDosComTiny 1 -#define FormatDosExeSmall 2 -#define FormatDosExeHuge 3 -#define FormatDosExeUnreal 4 -#define FormatAoutDpmi 5 -#define FormatFlat16 6 -#define FormatFlat32 7 -#define FormatWinPe32 8 -#define FormatElf32 9 -#define FormatMach32 10 +#define FormatDosComTiny 1 +#define FormatDosExeSmall 2 +#define FormatDosExeHuge 3 +#define FormatDosExeUnreal 4 +#define FormatAoutDpmi 5 +#define FormatFlat16 6 +#define FormatFlat32 7 +#define FormatWinPe32 8 +#define FormatElf32 9 +#define FormatMach32 10 +#define FormatDos8086ComTiny 11 +#define FormatDos8086ExeSmall 12 int OutputFormat = 0; const char* LibName[] = { NULL, - "lcds.a", // FormatDosComTiny - "lcds.a", // FormatDosExeSmall - "lcdh.a", // FormatDosExeHuge - "lcdu.a", // FormatDosExeUnreal - "lcdp.a", // FormatAoutDpmi - NULL, // FormatFlat16 - NULL, // FormatFlat32 - "lcw.a", // FormatWinPe32 - "lcl.a", // FormatElf32 - "lcm.a", // FormatMach32 + "lcds.a", // FormatDosComTiny + "lcds.a", // FormatDosExeSmall + "lcdh.a", // FormatDosExeHuge + "lcdu.a", // FormatDosExeUnreal + "lcdp.a", // FormatAoutDpmi + NULL, // FormatFlat16 + NULL, // FormatFlat32 + "lcw.a", // FormatWinPe32 + "lcl.a", // FormatElf32 + "lcm.a", // FormatMach32 + "lcds86.a", // FormatDos8086ComTiny + "lcds86.a", // FormatDos8086ExeSmall }; int verbose = 0; +int Use8086InstrOnly = 0; + int PreprocessWithGcc = 0; int UseExternalPreprocessor = 0; // 1 if use gcc/ucpp, 0 if use primitive pp in smlrc @@ -1372,7 +1378,7 @@ int main(int argc, char* argv[]) // Set the compiler and linker names early as their options will pile up #ifdef UNIX_LIKE - AddOption(&CompilerOptions, &CompilerOptionsLen, "smlrc"); + AddOption(&CompilerOptions, &CompilerOptionsLen, Use8086InstrOnly ? "smlrc86" : "smlrc"); AddOption(&LinkerOptions, &LinkerOptionsLen, "smlrl"); #else // Use explicit extensions (".exe") to let system() know that @@ -1381,7 +1387,7 @@ int main(int argc, char* argv[]) // if possible. // This helps recover the program exit status under DOS and thus // stop compilation as soon as one compilation stage fails. - AddOption(&CompilerOptions, &CompilerOptionsLen, "smlrc.exe"); + AddOption(&CompilerOptions, &CompilerOptionsLen, Use8086InstrOnly ? "smlrc86.exe" : "smlrc.exe"); AddOption(&LinkerOptions, &LinkerOptionsLen, "smlrl.exe"); #endif @@ -1429,6 +1435,13 @@ int main(int argc, char* argv[]) AddOptions(&PrepOptions, &PrepOptionsLen, "smlrpp.exe -U __STDC_VERSION__ -zI"); #endif } + for (i = 1; i < argc; i++) + { + if (!strcmp(argv[i], "-8086")) + { + Use8086InstrOnly = 1; + } + } for (i = 1; i < argc; i++) { @@ -1538,9 +1551,14 @@ int main(int argc, char* argv[]) argv[i] = NULL; continue; } + else if (!strcmp(argv[i], "-8086")) + { + argv[i] = NULL; + continue; + } else if (!strcmp(argv[i], "-tiny")) { - OutputFormat = FormatDosComTiny; + OutputFormat = Use8086InstrOnly ? FormatDos8086ComTiny : FormatDosComTiny; AddOption(&CompilerOptions, &CompilerOptionsLen, "-seg16"); AddOption(&LinkerOptions, &LinkerOptionsLen, argv[i]); argv[i] = NULL; @@ -1548,7 +1566,7 @@ int main(int argc, char* argv[]) } else if (!strcmp(argv[i], "-dost")) { - OutputFormat = FormatDosComTiny; + OutputFormat = Use8086InstrOnly ? FormatDos8086ComTiny : FormatDosComTiny; AddOption(&CompilerOptions, &CompilerOptionsLen, "-seg16"); DefineMacro("_DOS"); AddOption(&LinkerOptions, &LinkerOptionsLen, "-tiny"); @@ -1558,7 +1576,7 @@ int main(int argc, char* argv[]) } else if (!strcmp(argv[i], "-small")) { - OutputFormat = FormatDosExeSmall; + OutputFormat = Use8086InstrOnly ? FormatDos8086ExeSmall : FormatDosExeSmall; AddOption(&CompilerOptions, &CompilerOptionsLen, "-seg16"); AddOption(&LinkerOptions, &LinkerOptionsLen, argv[i]); argv[i] = NULL; @@ -1566,7 +1584,7 @@ int main(int argc, char* argv[]) } else if (!strcmp(argv[i], "-doss")) { - OutputFormat = FormatDosExeSmall; + OutputFormat = Use8086InstrOnly ? FormatDos8086ExeSmall : FormatDosExeSmall; AddOption(&CompilerOptions, &CompilerOptionsLen, "-seg16"); DefineMacro("_DOS"); AddOption(&LinkerOptions, &LinkerOptionsLen, "-small"); @@ -1920,6 +1938,14 @@ int main(int argc, char* argv[]) case FormatDosExeSmall: DefineMacro("__SMALLER_C_16__"); break; + case FormatDos8086ComTiny: + DefineMacro("__SMALLER_C_16__"); + DefineMacro("__SMALLER_C_8086__"); + break; + case FormatDos8086ExeSmall: + DefineMacro("__SMALLER_C_16__"); + DefineMacro("__SMALLER_C_8086__"); + break; case FormatDosExeHuge: DefineMacro("__SMALLER_C_32__"); DefineMacro("__HUGE__"); diff --git a/v0100/srclib/lcds86.txt b/v0100/srclib/lcds86.txt new file mode 100644 index 0000000..5c771b9 --- /dev/null +++ b/v0100/srclib/lcds86.txt @@ -0,0 +1,178 @@ +-8086 -doss -c -Wall -o lcds86.a + +c0ds.asm +c0.c + +assert.c + +ctype.c +isalnum.c +isalpha.c +isblank.c +iscntrl.c +isdigit.c +isgraph.c +islower.c +isprint.c +ispunct.c +isspace.c +isupper.c +isxdigit.c +tolower.c +toupper.c + +errno.c + +open_.c +open.c +creat_.c +creat.c +close_.c +close.c +read_.c +read.c +write_.c +write.c +lseek_.c +lseek.c +lseek16.c +unlink_.c +unlink.c +isatty_.c +isatty.c + +setlocal.c +localeco.c + +longjmp.c + +signal.c +raise.c + +stdio1.c +stdio2.c +stdin.c +stdout.c +stderr.c +fileno_.c +fileno.c +fopen.c +freopen.c +fflush.c +remove.c +rename.c +fclose.c +fillbuf.c +flushbuf.c +fread.c +fgetc.c +getc.c +getchar.c +fgets.c +gets.c +ungetc.c +fwrite.c +fputc.c +putc.c +putchar.c +fputs.c +puts.c +perror.c +ftell.c +ftell16.c +fseek.c +fseek16.c +rewind.c +fgetpos.c +fsetpos.c +feof.c +ferror.c +clearerr.c +setvbuf.c +setbuf.c +doprint.c +vfprintf.c +fprintf.c +vprintf.c +printf.c +vsprintf.c +sprintf.c +vsnprint.c +snprintf.c +doscan.c +vfscanf.c +fscanf.c +vscanf.c +scanf.c +vsscanf.c +sscanf.c +tmpnam.c +tmpfile.c + +exit.c +atexit.c +abort.c +malloc.c +calloc.c +free.c +realloc.c +abs.c +labs.c +div.c +ldiv.c +atoi.c +atol.c +strtol.c +strtoul.c +rand.c +srand.c +bsearch.c +qsort.c +getenv.c +system.c + +memchr.c +memcmp.c +memcpy.c +memmove.c +memset.c +strcat.c +strchr.c +strcmp.c +strcoll.c +strcpy.c +strcspn.c +strlen.c +strncat.c +strncmp.c +strncpy.c +strpbrk.c +strrchr.c +strspn.c +strstr.c +strtok.c +strxfrm.c +strerror.c + +time1.c +clock.c +bldtime.c +brktime.c +time.c +gmtime.c +localtim.c +mktime.c +asctime.c +ctime.c +strftime.c + +lngfu.c +lngfs.c +lngtu.c +lngts.c +lngadd.c +lngsub.c +lngeq.c +lngul.c +lngltz.c +lngsl.c \ No newline at end of file diff --git a/v0100/tests/Makefile b/v0100/tests/Makefile new file mode 100644 index 0000000..79506bd --- /dev/null +++ b/v0100/tests/Makefile @@ -0,0 +1,25 @@ +# Test suite for 8086 +# Usage: make FILE.com +# Prereqs: Installed SmallerC and DOSBOX +# Example: make c99.com + +%.com: %.c .AWAYS + smlrcc -8086 -dost -o $@ $< + dosbox -C "mount c: ./" -C "c:" -C "$@" + +%.exe: %.c .AWAYS + smlrcc -8086 -doss -o $@ $< + dosbox -C "mount c: ./" -C "c:" -C "$@" + +%.s: %.c .AWAYS + smlrcc -S -8086 -o $@ $< + + +%.o: %.c .AWAYS + smlrcc -S -8086 -o $(patsubst %.o,%.s,$@) $< + nasm -f elf -o $@ $(patsubst %.o,%.s,$@) + +clean: + rm -f *.com *.exe *.s *.o + +.AWAYS: \ No newline at end of file From bf2f023c795ce351f54eeb12a3ca8f86f03ab97b Mon Sep 17 00:00:00 2001 From: Humberto Costa Date: Fri, 10 May 2024 14:11:23 -0300 Subject: [PATCH 2/6] Merge last version of cg8086 from another branch - Remove shortcuts for Small Model version of compiler --- v0100/cg8086.c | 51 ++++++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/v0100/cg8086.c b/v0100/cg8086.c index 092675f..433d578 100644 --- a/v0100/cg8086.c +++ b/v0100/cg8086.c @@ -1549,10 +1549,9 @@ void GenExpr1(void) case tokNumUint: // Don't load operand into ax when ax is going to be pushed next, push it directly if (!(i + 1 < sp && stack[i + 1][0] == ',')) -// GenPrintInstr2Operands(X86InstrMov, 0, -// X86OpRegAWord, 0, -// X86OpConst, v); - printf2("\tmov ax, %d\n", v); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAWord, 0, + X86OpConst, v); break; case tokIdent: // Don't load operand into ax when ax is going to be pushed next, push it directly @@ -1992,17 +1991,15 @@ void GenExpr1(void) int labelCCAfter = LabelCnt++; GenPrintInstr1Operand(X86InstrJcc, tok, X86OpNumLabel, labelCC); -// GenPrintInstr2Operands(X86InstrMov, 0, -// X86OpRegAByte, 0, -// X86OpConst, 0); - puts2("xor al, al"); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAByte, 0, + X86OpConst, 0); GenPrintInstr1Operand(X86InstrJmp, 0, X86OpNumLabel, labelCCAfter); GenNumLabel(labelCC); -// GenPrintInstr2Operands(X86InstrMov, 0, -// X86OpRegAByte, 0, -// X86OpConst, 1); - puts2("mov al, 1"); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegAByte, 0, + X86OpConst, 1); GenNumLabel(labelCCAfter); GenPrintInstrNoOperand(X86InstrCbw); @@ -2095,10 +2092,9 @@ void GenExpr1(void) GenPrintInstrNoOperand(X86InstrCwd); break; default: -// GenPrintInstr2Operands(X86InstrMov, 0, -// X86OpRegDWord, 0, -// X86OpConst, 0); - puts2("\txor dx, dx\n"); + GenPrintInstr2Operands(X86InstrMov, 0, + X86OpRegDWord, 0, + X86OpConst, 0); break; } @@ -2288,9 +2284,8 @@ void GenExpr1(void) } else { -// GenPrintInstr1Operand(X86InstrCall, 0, -// X86OpRegAWord, 0); - puts2("\tcall ax\n"); + GenPrintInstr1Operand(X86InstrCall, 0, + X86OpRegAWord, 0); } GenGrowStack(-v); break; @@ -2410,10 +2405,9 @@ void GenExpr0(void) GenPrintInstr1Operand(X86InstrPop, 0, X86OpRegBWord, 0); if (tok == '-') -// GenPrintInstr2Operands(X86InstrXchg, 0, -// X86OpRegAWord, 0, -// X86OpRegBWord, 0); - puts2("\txchg ax, bx\n"); + GenPrintInstr2Operands(X86InstrXchg, 0, + X86OpRegAWord, 0, + X86OpRegBWord, 0); if (tok != '*') GenPrintInstr2Operands(instr, 0, X86OpRegAWord, 0, @@ -2428,12 +2422,11 @@ void GenExpr0(void) case tokUDiv: case '%': case tokUMod: -// GenPrintInstr1Operand(X86InstrPop, 0, -// X86OpRegBWord, 0); -// GenPrintInstr2Operands(X86InstrXchg, 0, -// X86OpRegAWord, 0, -// X86OpRegBWord, 0); - puts2("\tpop bx\n\txchg ax, bx\n"); + GenPrintInstr1Operand(X86InstrPop, 0, + X86OpRegBWord, 0); + GenPrintInstr2Operands(X86InstrXchg, 0, + X86OpRegAWord, 0, + X86OpRegBWord, 0); if (tok == '/' || tok == '%') { From f3b1f3c6f5a090cd701afc6e6cfb3c5dbab090d7 Mon Sep 17 00:00:00 2001 From: Humberto Costa Date: Sat, 11 May 2024 23:47:39 -0300 Subject: [PATCH 3/6] Changed the names and add format error on 8086 - Changed the names of cg8086 constants - Added error when trying to compile 8086 in unsupported formats --- v0100/cg8086.c | 1233 ++++++++++++++++++++--------------------- v0100/smlrcc.c | 3 + v0100/tests/snake.com | Bin 6212 -> 0 bytes 3 files changed, 616 insertions(+), 620 deletions(-) delete mode 100644 v0100/tests/snake.com diff --git a/v0100/cg8086.c b/v0100/cg8086.c index 433d578..73a316d 100644 --- a/v0100/cg8086.c +++ b/v0100/cg8086.c @@ -219,47 +219,45 @@ void GenRecordFxnSize(char* startLabelName, int endLabelNo) (void)endLabelNo; } -#define X86InstrMov 0x00 -#define X86InstrMovSx 0x01 -#define X86InstrMovZx 0x02 -#define X86InstrXchg 0x03 -#define X86InstrLea 0x04 -#define X86InstrPush 0x05 -#define X86InstrPop 0x06 -#define X86InstrInc 0x07 -#define X86InstrDec 0x08 -#define X86InstrAdd 0x09 -#define X86InstrSub 0x0A -#define X86InstrAnd 0x0B -#define X86InstrXor 0x0C -#define X86InstrOr 0x0D -#define X86InstrCmp 0x0E -#define X86InstrTest 0x0F -#define X86InstrMul 0x10 -#define X86InstrImul 0x11 -#define X86InstrIdiv 0x12 -#define X86InstrDiv 0x13 -#define X86InstrShl 0x14 -#define X86InstrSar 0x15 -#define X86InstrShr 0x16 -#define X86InstrNeg 0x17 -#define X86InstrNot 0x18 -#define X86InstrCbw 0x19 -#define X86InstrCwd 0x1A -#define X86InstrCdq 0x1B -#define X86InstrSetCc 0x1C -#define X86InstrJcc 0x1D -#define X86InstrJNotCc 0x1E -#define X86InstrLeave 0x1F -#define X86InstrCall 0x20 -#define X86InstrRet 0x21 -#define X86InstrJmp 0x22 +#define I8086InstrMov 0x00 +#define I8086InstrXchg 0x03 +#define I8086InstrLea 0x04 +#define I8086InstrPush 0x05 +#define I8086InstrPop 0x06 +#define I8086InstrInc 0x07 +#define I8086InstrDec 0x08 +#define I8086InstrAdd 0x09 +#define I8086InstrSub 0x0A +#define I8086InstrAnd 0x0B +#define I8086InstrXor 0x0C +#define I8086InstrOr 0x0D +#define I8086InstrCmp 0x0E +#define I8086InstrTest 0x0F +#define I8086InstrMul 0x10 +#define I8086InstrImul 0x11 +#define I8086InstrIdiv 0x12 +#define I8086InstrDiv 0x13 +#define I8086InstrShl 0x14 +#define I8086InstrSar 0x15 +#define I8086InstrShr 0x16 +#define I8086InstrNeg 0x17 +#define I8086InstrNot 0x18 +#define I8086InstrCbw 0x19 +#define I8086InstrCwd 0x1A +#define I8086InstrCdq 0x1B +#define I8086InstrSetCc 0x1C +#define I8086InstrJcc 0x1D +#define I8086InstrJNotCc 0x1E +#define I8086InstrLeave 0x1F +#define I8086InstrCall 0x20 +#define I8086InstrRet 0x21 +#define I8086InstrJmp 0x22 char* winstrs[] = { "mov", - "movsx", - "movzx", + 0, + 0, "xchg", "lea", "push", @@ -301,15 +299,15 @@ void GenPrintInstr(int instr, int val) switch (instr) { - case X86InstrLeave: + case I8086InstrLeave: p = (OutputFormat != FormatSegHuge && OutputFormat != FormatSegUnreal) ? "leave" : "db\t0x66\n\tleave"; break; - case X86InstrRet: + case I8086InstrRet: p = (OutputFormat != FormatSegHuge && OutputFormat != FormatSegUnreal) ? "ret" : "retf"; break; - case X86InstrJcc: + case I8086InstrJcc: switch (val) { case '<': p = "jl"; break; @@ -324,7 +322,7 @@ void GenPrintInstr(int instr, int val) case tokNEQ: p = "jne"; break; } break; - case X86InstrJNotCc: + case I8086InstrJNotCc: switch (val) { case '<': p = "jge"; break; @@ -340,7 +338,7 @@ void GenPrintInstr(int instr, int val) } break; - case X86InstrSetCc: + case I8086InstrSetCc: switch (val) { case '<': p = "setl"; break; @@ -363,10 +361,10 @@ void GenPrintInstr(int instr, int val) switch (instr) { - case X86InstrCbw: - case X86InstrCwd: - case X86InstrLeave: - case X86InstrRet: + case I8086InstrCbw: + case I8086InstrCwd: + case I8086InstrLeave: + case I8086InstrRet: printf2("\t%s", p); break; default: @@ -375,38 +373,33 @@ void GenPrintInstr(int instr, int val) } } -#define X86OpRegAByte 0x00 -#define X86OpRegAByteHigh 0x01 -#define X86OpRegCByte 0x02 -#define X86OpRegAWord 0x03 -#define X86OpRegBWord 0x04 -#define X86OpRegCWord 0x05 -#define X86OpRegDWord 0x06 -#define X86OpRegAHalfWord 0x07 -#define X86OpRegCHalfWord 0x08 -#define X86OpRegBpWord 0x09 -#define X86OpRegSpWord 0x0A -#define X86OpRegAByteOrWord 0x0B -#define X86OpRegCByteOrWord 0x0C -#define X86OpConst 0x0D -#define X86OpLabel 0x0E -#define X86OpNumLabel 0x0F -#define X86OpIndLabel 0x10 -#define X86OpIndLabelExplicitByte 0x11 -#define X86OpIndLabelExplicitWord 0x12 -#define X86OpIndLabelExplicitHalfWord 0x13 -#define X86OpIndLabelExplicitByteOrWord 0x14 -#define X86OpIndLocal 0x15 -#define X86OpIndLocalExplicitByte 0x16 -#define X86OpIndLocalExplicitWord 0x17 -#define X86OpIndLocalExplicitHalfWord 0x18 -#define X86OpIndLocalExplicitByteOrWord 0x19 -#define X86OpIndRegB 0x1A -#define X86OpIndRegBExplicitByte 0x1B -#define X86OpIndRegBExplicitWord 0x1C -#define X86OpIndRegBExplicitHalfWord 0x1D -#define X86OpIndRegBExplicitByteOrWord 0x1E -#define X86OpRegCByteHigh 0x1F +#define I8086OpRegAByte 0x00 +#define I8086OpRegAByteHigh 0x01 +#define I8086OpRegCByte 0x02 +#define I8086OpRegAWord 0x03 +#define I8086OpRegBWord 0x04 +#define I8086OpRegCWord 0x05 +#define I8086OpRegDWord 0x06 +#define I8086OpRegBpWord 0x09 +#define I8086OpRegSpWord 0x0A +#define I8086OpRegAByteOrWord 0x0B +#define I8086OpRegCByteOrWord 0x0C +#define I8086OpConst 0x0D +#define I8086OpLabel 0x0E +#define I8086OpNumLabel 0x0F +#define I8086OpIndLabel 0x10 +#define I8086OpIndLabelExplicitByte 0x11 +#define I8086OpIndLabelExplicitWord 0x12 +#define I8086OpIndLabelExplicitByteOrWord 0x14 +#define I8086OpIndLocal 0x15 +#define I8086OpIndLocalExplicitByte 0x16 +#define I8086OpIndLocalExplicitWord 0x17 +#define I8086OpIndLocalExplicitByteOrWord 0x19 +#define I8086OpIndRegB 0x1A +#define I8086OpIndRegBExplicitByte 0x1B +#define I8086OpIndRegBExplicitWord 0x1C +#define I8086OpIndRegBExplicitByteOrWord 0x1E +#define I8086OpRegCByteHigh 0x1F STATIC int GenSelectByteOrWord(int op, int opSz) @@ -414,16 +407,16 @@ int GenSelectByteOrWord(int op, int opSz) int tmp = opSz == 2; switch (op) { - case X86OpRegAByteOrWord: - return tmp ? X86OpRegAWord: X86OpRegAByte; - case X86OpRegCByteOrWord: - return tmp ? X86OpRegCWord : X86OpRegCByte; - case X86OpIndLabelExplicitByteOrWord: - return tmp ? X86OpIndLabelExplicitWord : X86OpIndLabelExplicitByte; - case X86OpIndLocalExplicitByteOrWord: - return tmp ? X86OpIndLocalExplicitWord : X86OpIndLocalExplicitByte; - case X86OpIndRegBExplicitByteOrWord: - return tmp ? X86OpIndRegBExplicitWord: X86OpIndRegBExplicitByte; + case I8086OpRegAByteOrWord: + return tmp ? I8086OpRegAWord: I8086OpRegAByte; + case I8086OpRegCByteOrWord: + return tmp ? I8086OpRegCWord : I8086OpRegCByte; + case I8086OpIndLabelExplicitByteOrWord: + return tmp ? I8086OpIndLabelExplicitWord : I8086OpIndLabelExplicitByte; + case I8086OpIndLocalExplicitByteOrWord: + return tmp ? I8086OpIndLocalExplicitWord : I8086OpIndLocalExplicitByte; + case I8086OpIndRegBExplicitByteOrWord: + return tmp ? I8086OpIndRegBExplicitWord: I8086OpIndRegBExplicitByte; } return op; } @@ -433,28 +426,28 @@ void GenPrintOperand(int op, int val) { switch (op) { - case X86OpRegAByte: printf2("al"); break; - case X86OpRegAByteHigh: printf2("ah"); break; - case X86OpRegCByte: printf2("cl"); break; - case X86OpRegCByteHigh: printf2("ch"); break; - case X86OpRegAWord: printf2("ax"); break; - case X86OpRegBWord: printf2("bx"); break; - case X86OpRegCWord: printf2("cx"); break; - case X86OpRegDWord: printf2("dx"); break; - case X86OpRegBpWord: printf2("bp"); break; - case X86OpRegSpWord: printf2("sp"); break; - case X86OpConst: printf2("%d", truncInt(val)); break; - case X86OpLabel: GenPrintLabel(IdentTable + val); break; - case X86OpNumLabel: GenPrintNumLabel(val); break; - case X86OpIndLabel: printf2("["); GenPrintLabel(IdentTable + val); printf2("]"); break; - case X86OpIndLabelExplicitByte: printf2("byte ["); GenPrintLabel(IdentTable + val); printf2("]"); break; - case X86OpIndLabelExplicitWord: printf2("word ["); GenPrintLabel(IdentTable + val); printf2("]"); break; - case X86OpIndLocal: printf2("[bp%+d]", truncInt(val)); break; - case X86OpIndLocalExplicitByte: printf2("byte [bp%+d]", truncInt(val)); break; - case X86OpIndLocalExplicitWord: printf2("word [bp%+d]", truncInt(val)); break; - case X86OpIndRegB: printf2("[bx]"); break; - case X86OpIndRegBExplicitByte: printf2("byte [bx]"); break; - case X86OpIndRegBExplicitWord: printf2("word [bx]"); break; + case I8086OpRegAByte: printf2("al"); break; + case I8086OpRegAByteHigh: printf2("ah"); break; + case I8086OpRegCByte: printf2("cl"); break; + case I8086OpRegCByteHigh: printf2("ch"); break; + case I8086OpRegAWord: printf2("ax"); break; + case I8086OpRegBWord: printf2("bx"); break; + case I8086OpRegCWord: printf2("cx"); break; + case I8086OpRegDWord: printf2("dx"); break; + case I8086OpRegBpWord: printf2("bp"); break; + case I8086OpRegSpWord: printf2("sp"); break; + case I8086OpConst: printf2("%d", truncInt(val)); break; + case I8086OpLabel: GenPrintLabel(IdentTable + val); break; + case I8086OpNumLabel: GenPrintNumLabel(val); break; + case I8086OpIndLabel: printf2("["); GenPrintLabel(IdentTable + val); printf2("]"); break; + case I8086OpIndLabelExplicitByte: printf2("byte ["); GenPrintLabel(IdentTable + val); printf2("]"); break; + case I8086OpIndLabelExplicitWord: printf2("word ["); GenPrintLabel(IdentTable + val); printf2("]"); break; + case I8086OpIndLocal: printf2("[bp%+d]", truncInt(val)); break; + case I8086OpIndLocalExplicitByte: printf2("byte [bp%+d]", truncInt(val)); break; + case I8086OpIndLocalExplicitWord: printf2("word [bp%+d]", truncInt(val)); break; + case I8086OpIndRegB: printf2("[bx]"); break; + case I8086OpIndRegBExplicitByte: printf2("byte [bx]"); break; + case I8086OpIndRegBExplicitWord: printf2("word [bx]"); break; } } @@ -489,19 +482,19 @@ STATIC void GenPrintInstr2Operands(int instr, int instrval, int operand1, int operand1val, int operand2, int operand2val) { /* - if (operand2 == X86OpConst && truncUint(operand2val) == 0 && - (instr == X86InstrAdd || instr == X86InstrSub)) + if (operand2 == I8086OpConst && truncUint(operand2val) == 0 && + (instr == I8086InstrAdd || instr == I8086InstrSub)) return; - if (operand2 == X86OpConst && + if (operand2 == I8086OpConst && (operand2val == 1 || operand2val == -1) && - (instr == X86InstrAdd || instr == X86InstrSub)) + (instr == I8086InstrAdd || instr == I8086InstrSub)) { - if ((operand2val == 1 && instr == X86InstrAdd) || - (operand2val == -1 && instr == X86InstrSub)) - GenPrintInstr(X86InstrInc, 0); + if ((operand2val == 1 && instr == I8086InstrAdd) || + (operand2val == -1 && instr == I8086InstrSub)) + GenPrintInstr(I8086InstrInc, 0); else - GenPrintInstr(X86InstrDec, 0); + GenPrintInstr(I8086InstrDec, 0); GenPrintOperand(operand1, operand1val); GenPrintNewLine(); @@ -535,29 +528,29 @@ STATIC void GenExtendRegAIfNeeded(int opSz) { if (opSz == -1) - GenPrintInstrNoOperand(X86InstrCbw); + GenPrintInstrNoOperand(I8086InstrCbw); else if (opSz == 1) - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAByteHigh, 0, - X86OpConst, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAByteHigh, 0, + I8086OpConst, 0); } STATIC void GenJumpUncond(int label) { - GenPrintInstr1Operand(X86InstrJmp, 0, - X86OpNumLabel, label); + GenPrintInstr1Operand(I8086InstrJmp, 0, + I8086OpNumLabel, label); } STATIC void GenJumpIfEqual(int val, int label) { - GenPrintInstr2Operands(X86InstrCmp, 0, - X86OpRegAWord, 0, - X86OpConst, val); - GenPrintInstr1Operand(X86InstrJcc, tokEQ, - X86OpNumLabel, label); + GenPrintInstr2Operands(I8086InstrCmp, 0, + I8086OpRegAWord, 0, + I8086OpConst, val); + GenPrintInstr1Operand(I8086InstrJcc, tokEQ, + I8086OpNumLabel, label); } @@ -597,11 +590,11 @@ void GenUpdateFrameSize(void) STATIC void GenFxnProlog(void) { - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpRegBpWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegBpWord, 0, - X86OpRegSpWord, 0); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpRegBpWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegBpWord, 0, + I8086OpRegSpWord, 0); fgetpos(OutFile, &GenPrologPos); GenWriteFrameSize(); } @@ -611,21 +604,21 @@ void GenGrowStack(int size) { if (!size) return; - GenPrintInstr2Operands(X86InstrSub, 0, - X86OpRegSpWord, 0, - X86OpConst, size); + GenPrintInstr2Operands(I8086InstrSub, 0, + I8086OpRegSpWord, 0, + I8086OpConst, size); } STATIC void GenFxnEpilog(void) { GenUpdateFrameSize(); - GenPrintInstr2Operands(X86InstrMov,0, - X86OpRegSpWord, 0, - X86OpRegBpWord, 0); - GenPrintInstr1Operand(X86InstrPop,0, - X86OpRegBpWord, 0); - GenPrintInstrNoOperand(X86InstrRet); + GenPrintInstr2Operands(I8086InstrMov,0, + I8086OpRegSpWord, 0, + I8086OpRegBpWord, 0); + GenPrintInstr1Operand(I8086InstrPop,0, + I8086OpRegBpWord, 0); + GenPrintInstrNoOperand(I8086InstrRet); } STATIC @@ -638,31 +631,31 @@ int GenMaxLocalsSize(void) STATIC void GenReadIdent(int opSz, int label) { - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, - X86OpIndLabel, label); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, opSz), 0, + I8086OpIndLabel, label); GenExtendRegAIfNeeded(opSz); } STATIC void GenReadLocal(int opSz, int ofs) { - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, - X86OpIndLocal, ofs); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, opSz), 0, + I8086OpIndLocal, ofs); GenExtendRegAIfNeeded(opSz); } STATIC void GenReadIndirect(int opSz) { - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegBWord, 0, - X86OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegBWord, 0, + I8086OpRegAWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, - X86OpIndRegB, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, opSz), 0, + I8086OpIndRegB, 0); GenExtendRegAIfNeeded(opSz); } @@ -672,31 +665,31 @@ void GenReadCRegIdent(int opSz, int label) if (opSz == -1) { - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpRegAWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAByte, 0, - X86OpIndLabelExplicitByte, label); - GenPrintInstrNoOperand(X86InstrCbw); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCWord, 0, - X86OpRegAWord, 0); - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAByte, 0, + I8086OpIndLabelExplicitByte, label); + GenPrintInstrNoOperand(I8086InstrCbw); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCWord, 0, + I8086OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegAWord, 0); } else if (opSz == 1) { - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCByte, 0, - X86OpIndLabelExplicitByte, label); - GenPrintInstr2Operands(X86InstrXor, 0, - X86OpRegCByteHigh, 0, - X86OpRegCByteHigh, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCByte, 0, + I8086OpIndLabelExplicitByte, label); + GenPrintInstr2Operands(I8086InstrXor, 0, + I8086OpRegCByteHigh, 0, + I8086OpRegCByteHigh, 0); } else - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCWord, 0, - X86OpIndLabel, label); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCWord, 0, + I8086OpIndLabel, label); } STATIC @@ -705,227 +698,227 @@ void GenReadCRegLocal(int opSz, int ofs) if (opSz == -1) { - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpRegAWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAByte, 0, - X86OpIndLocalExplicitByte, ofs); - GenPrintInstrNoOperand(X86InstrCbw); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCWord, 0, - X86OpRegAWord, 0); - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAByte, 0, + I8086OpIndLocalExplicitByte, ofs); + GenPrintInstrNoOperand(I8086InstrCbw); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCWord, 0, + I8086OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegAWord, 0); } else if (opSz == 1) { - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCByte, 0, - X86OpIndLocalExplicitByte, ofs); - GenPrintInstr2Operands(X86InstrXor, 0, - X86OpRegCByteHigh, 0, - X86OpRegCByteHigh, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCByte, 0, + I8086OpIndLocalExplicitByte, ofs); + GenPrintInstr2Operands(I8086InstrXor, 0, + I8086OpRegCByteHigh, 0, + I8086OpRegCByteHigh, 0); } else - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCWord, 0, - X86OpIndLocal, ofs); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCWord, 0, + I8086OpIndLocal, ofs); } STATIC void GenReadCRegIndirect(int opSz) { - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegBWord, 0, - X86OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegBWord, 0, + I8086OpRegAWord, 0); if (opSz == -1) { - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpRegAWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAByte, 0, - X86OpIndRegBExplicitByte, 0); - GenPrintInstrNoOperand(X86InstrCbw); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCWord, 0, - X86OpRegAWord, 0); - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAByte, 0, + I8086OpIndRegBExplicitByte, 0); + GenPrintInstrNoOperand(I8086InstrCbw); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCWord, 0, + I8086OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegAWord, 0); } else if (opSz == 1) { - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCByte, 0, - X86OpIndRegBExplicitByte, 0); - GenPrintInstr2Operands(X86InstrXor, 0, - X86OpRegCByteHigh, 0, - X86OpRegCByteHigh, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCByte, 0, + I8086OpIndRegBExplicitByte, 0); + GenPrintInstr2Operands(I8086InstrXor, 0, + I8086OpRegCByteHigh, 0, + I8086OpRegCByteHigh, 0); } else - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCWord, 0, - X86OpIndRegB, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCWord, 0, + I8086OpIndRegB, 0); } STATIC void GenIncDecIdent(int opSz, int label, int tok) { - int instr = X86InstrInc; + int instr = I8086InstrInc; if (tok != tokInc) - instr = X86InstrDec; + instr = I8086InstrDec; GenPrintInstr1Operand(instr, 0, - GenSelectByteOrWord(X86OpIndLabelExplicitByteOrWord, opSz), label); - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, - X86OpIndLabel, label); + GenSelectByteOrWord(I8086OpIndLabelExplicitByteOrWord, opSz), label); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, opSz), 0, + I8086OpIndLabel, label); GenExtendRegAIfNeeded(opSz); } STATIC void GenIncDecLocal(int opSz, int ofs, int tok) { - int instr = X86InstrInc; + int instr = I8086InstrInc; if (tok != tokInc) - instr = X86InstrDec; + instr = I8086InstrDec; GenPrintInstr1Operand(instr, 0, - GenSelectByteOrWord(X86OpIndLocalExplicitByteOrWord, opSz), ofs); - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, - X86OpIndLocal, ofs); + GenSelectByteOrWord(I8086OpIndLocalExplicitByteOrWord, opSz), ofs); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, opSz), 0, + I8086OpIndLocal, ofs); GenExtendRegAIfNeeded(opSz); } STATIC void GenIncDecIndirect(int opSz, int tok) { - int instr = X86InstrInc; + int instr = I8086InstrInc; if (tok != tokInc) - instr = X86InstrDec; + instr = I8086InstrDec; - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegBWord, 0, - X86OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegBWord, 0, + I8086OpRegAWord, 0); GenPrintInstr1Operand(instr, 0, - GenSelectByteOrWord(X86OpIndRegBExplicitByteOrWord, opSz), 0); - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, - X86OpIndRegB, 0); + GenSelectByteOrWord(I8086OpIndRegBExplicitByteOrWord, opSz), 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, opSz), 0, + I8086OpIndRegB, 0); GenExtendRegAIfNeeded(opSz); } STATIC void GenPostIncDecIdent(int opSz, int label, int tok) { - int instr = X86InstrInc; + int instr = I8086InstrInc; if (tok != tokPostInc) - instr = X86InstrDec; + instr = I8086InstrDec; - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, - X86OpIndLabel, label); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, opSz), 0, + I8086OpIndLabel, label); GenExtendRegAIfNeeded(opSz); GenPrintInstr1Operand(instr, 0, - GenSelectByteOrWord(X86OpIndLabelExplicitByteOrWord, opSz), label); + GenSelectByteOrWord(I8086OpIndLabelExplicitByteOrWord, opSz), label); } STATIC void GenPostIncDecLocal(int opSz, int ofs, int tok) { - int instr = X86InstrInc; + int instr = I8086InstrInc; if (tok != tokPostInc) - instr = X86InstrDec; + instr = I8086InstrDec; - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, - X86OpIndLocal, ofs); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, opSz), 0, + I8086OpIndLocal, ofs); GenExtendRegAIfNeeded(opSz); GenPrintInstr1Operand(instr, 0, - GenSelectByteOrWord(X86OpIndLocalExplicitByteOrWord, opSz), ofs); + GenSelectByteOrWord(I8086OpIndLocalExplicitByteOrWord, opSz), ofs); } STATIC void GenPostIncDecIndirect(int opSz, int tok) { - int instr = X86InstrInc; + int instr = I8086InstrInc; if (tok != tokPostInc) - instr = X86InstrDec; + instr = I8086InstrDec; - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegBWord, 0, - X86OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegBWord, 0, + I8086OpRegAWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, - X86OpIndRegB, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, opSz), 0, + I8086OpIndRegB, 0); GenExtendRegAIfNeeded(opSz); GenPrintInstr1Operand(instr, 0, - GenSelectByteOrWord(X86OpIndRegBExplicitByteOrWord, opSz), 0); + GenSelectByteOrWord(I8086OpIndRegBExplicitByteOrWord, opSz), 0); } STATIC void GenPostAddSubIdent(int opSz, int val, int label, int tok) { - int instr = X86InstrAdd; + int instr = I8086InstrAdd; if (tok != tokPostAdd) - instr = X86InstrSub; + instr = I8086InstrSub; - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, - X86OpIndLabel, label); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, opSz), 0, + I8086OpIndLabel, label); GenExtendRegAIfNeeded(opSz); GenPrintInstr2Operands(instr, 0, - GenSelectByteOrWord(X86OpIndLabelExplicitByteOrWord, opSz), label, - X86OpConst, val); + GenSelectByteOrWord(I8086OpIndLabelExplicitByteOrWord, opSz), label, + I8086OpConst, val); } STATIC void GenPostAddSubLocal(int opSz, int val, int ofs, int tok) { - int instr = X86InstrAdd; + int instr = I8086InstrAdd; if (tok != tokPostAdd) - instr = X86InstrSub; + instr = I8086InstrSub; - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, - X86OpIndLocal, ofs); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, opSz), 0, + I8086OpIndLocal, ofs); GenExtendRegAIfNeeded(opSz); GenPrintInstr2Operands(instr, 0, - GenSelectByteOrWord(X86OpIndLocalExplicitByteOrWord, opSz), ofs, - X86OpConst, val); + GenSelectByteOrWord(I8086OpIndLocalExplicitByteOrWord, opSz), ofs, + I8086OpConst, val); } STATIC void GenPostAddSubIndirect(int opSz, int val, int tok) { - int instr = X86InstrAdd; + int instr = I8086InstrAdd; if (tok != tokPostAdd) - instr = X86InstrSub; + instr = I8086InstrSub; - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegBWord, 0, - X86OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegBWord, 0, + I8086OpRegAWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, opSz), 0, - X86OpIndRegB, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, opSz), 0, + I8086OpIndRegB, 0); GenExtendRegAIfNeeded(opSz); GenPrintInstr2Operands(instr, 0, - GenSelectByteOrWord(X86OpIndRegBExplicitByteOrWord, opSz), 0, - X86OpConst, val); + GenSelectByteOrWord(I8086OpIndRegBExplicitByteOrWord, opSz), 0, + I8086OpConst, val); } #define tokOpNumInt 0x100 @@ -1368,20 +1361,20 @@ int GenGetBinaryOperatorInstr(int tok) case tokPostAdd: case tokAssignAdd: case '+': - return X86InstrAdd; + return I8086InstrAdd; case tokPostSub: case tokAssignSub: case '-': - return X86InstrSub; + return I8086InstrSub; case '&': case tokAssignAnd: - return X86InstrAnd; + return I8086InstrAnd; case '^': case tokAssignXor: - return X86InstrXor; + return I8086InstrXor; case '|': case tokAssignOr: - return X86InstrOr; + return I8086InstrOr; case '<': case '>': case tokLEQ: @@ -1392,29 +1385,29 @@ int GenGetBinaryOperatorInstr(int tok) case tokUGreater: case tokULEQ: case tokUGEQ: - return X86InstrCmp; + return I8086InstrCmp; case '*': case tokAssignMul: - return X86InstrMul; + return I8086InstrMul; case '/': case '%': case tokAssignDiv: case tokAssignMod: - return X86InstrIdiv; + return I8086InstrIdiv; case tokUDiv: case tokUMod: case tokAssignUDiv: case tokAssignUMod: - return X86InstrDiv; + return I8086InstrDiv; case tokLShift: case tokAssignLSh: - return X86InstrShl; + return I8086InstrShl; case tokRShift: case tokAssignRSh: - return X86InstrSar; + return I8086InstrSar; case tokURShift: case tokAssignURSh: - return X86InstrShr; + return I8086InstrShr; default: //error("Error: Invalid operator\n"); @@ -1549,58 +1542,58 @@ void GenExpr1(void) case tokNumUint: // Don't load operand into ax when ax is going to be pushed next, push it directly if (!(i + 1 < sp && stack[i + 1][0] == ',')) - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAWord, 0, - X86OpConst, v); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAWord, 0, + I8086OpConst, v); break; case tokIdent: // Don't load operand into ax when ax is going to be pushed next, push it directly if (!(i + 1 < sp && (stack[i + 1][0] == ',' || stack[i + 1][0] == ')'))) - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAWord, 0, - X86OpLabel, v); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAWord, 0, + I8086OpLabel, v); break; case tokLocalOfs: - GenPrintInstr2Operands(X86InstrLea, 0, - X86OpRegAWord, 0, - X86OpIndLocal, v); + GenPrintInstr2Operands(I8086InstrLea, 0, + I8086OpRegAWord, 0, + I8086OpIndLocal, v); break; case '~': - GenPrintInstr1Operand(X86InstrNot, 0, - X86OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrNot, 0, + I8086OpRegAWord, 0); break; case tokUnaryMinus: - GenPrintInstr1Operand(X86InstrNeg, 0, - X86OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrNeg, 0, + I8086OpRegAWord, 0); break; case tok_Bool: - GenPrintInstr2Operands(X86InstrTest, 0, - X86OpRegAWord, 0, - X86OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrTest, 0, + I8086OpRegAWord, 0, + I8086OpRegAWord, 0); int labelCC = LabelCnt++; int labelCCAfter = LabelCnt++; - GenPrintInstr1Operand(X86InstrJcc, tokNEQ, - X86OpNumLabel, labelCC); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAByte, 0, - X86OpConst, 0); - GenPrintInstr1Operand(X86InstrJmp, 0, - X86OpNumLabel, labelCCAfter); + GenPrintInstr1Operand(I8086InstrJcc, tokNEQ, + I8086OpNumLabel, labelCC); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAByte, 0, + I8086OpConst, 0); + GenPrintInstr1Operand(I8086InstrJmp, 0, + I8086OpNumLabel, labelCCAfter); GenNumLabel(labelCC); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAByte, 0, - X86OpConst, 1); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAByte, 0, + I8086OpConst, 1); GenNumLabel(labelCCAfter); // fallthrough case tokSChar: - GenPrintInstrNoOperand(X86InstrCbw); + GenPrintInstrNoOperand(I8086InstrCbw); break; case tokUChar: - GenPrintInstr2Operands(X86InstrAnd, 0, - X86OpRegAWord, 0, - X86OpConst, 0xFF); + GenPrintInstr2Operands(I8086InstrAnd, 0, + I8086OpRegAWord, 0, + I8086OpConst, 0xFF); break; case tokShortCirc: @@ -1619,8 +1612,8 @@ void GenExpr1(void) case tokPushAcc: // TBD??? handle similarly to ','??? - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpRegAWord, 0); break; case ',': @@ -1630,19 +1623,19 @@ void GenExpr1(void) switch (stack[i - 1][0]) { case tokOpIdent: - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpIndLabelExplicitWord, stack[i - 1][1]); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpIndLabelExplicitWord, stack[i - 1][1]); break; case tokOpLocalOfs: - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpIndLocalExplicitWord, stack[i - 1][1]); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpIndLocalExplicitWord, stack[i - 1][1]); break; case tokOpAcc: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegBWord, 0, - X86OpRegAWord, 0); - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpIndRegBExplicitWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegBWord, 0, + I8086OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpIndRegBExplicitWord, 0); break; } } @@ -1652,22 +1645,22 @@ void GenExpr1(void) { case tokNumInt: case tokNumUint: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAWord, 0, - X86OpConst, stack[i - 1][1]); - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAWord, 0, + I8086OpConst, stack[i - 1][1]); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpRegAWord, 0); break; case tokIdent: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAWord, 0, - X86OpLabel, stack[i - 1][1]); - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAWord, 0, + I8086OpLabel, stack[i - 1][1]); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpRegAWord, 0); break; default: - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpRegAWord, 0); break; } } @@ -1787,9 +1780,9 @@ void GenExpr1(void) { if (stack[i + 2][0] == tokOpAcc) { - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCWord, 0, - X86OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCWord, 0, + I8086OpRegAWord, 0); } else if (stack[i + 2][0] == tokOpIndAcc) { @@ -1802,9 +1795,9 @@ void GenExpr1(void) if (tok == '=') { if (stack[i + 1][0] == tokOpIndAcc) - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegBWord, 0, - X86OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegBWord, 0, + I8086OpRegAWord, 0); // "swap" left and right operands i++; v = v / 16 + v % 16 * 16; @@ -1814,19 +1807,19 @@ void GenExpr1(void) { case tokOpNumInt: case tokOpNumUint: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAWord, 0, - X86OpConst, stack[i + 1][1]); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAWord, 0, + I8086OpConst, stack[i + 1][1]); break; case tokOpIdent: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAWord, 0, - X86OpLabel, stack[i + 1][1]); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAWord, 0, + I8086OpLabel, stack[i + 1][1]); break; case tokOpLocalOfs: - GenPrintInstr2Operands(X86InstrLea, 0, - X86OpRegAWord, 0, - X86OpIndLocal, stack[i + 1][1]); + GenPrintInstr2Operands(I8086InstrLea, 0, + I8086OpRegAWord, 0, + I8086OpIndLocal, stack[i + 1][1]); break; case tokOpAcc: break; @@ -1840,15 +1833,15 @@ void GenExpr1(void) GenReadIndirect(v / 16 - 8); break; case tokOpStack: - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegAWord, 0); break; case tokOpIndStack: - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegBWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, v / 16 - 8), 0, - X86OpIndRegB, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegBWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, v / 16 - 8), 0, + I8086OpIndRegB, 0); GenExtendRegAIfNeeded(v / 16 - 8); break; } @@ -1860,8 +1853,8 @@ void GenExpr1(void) v = v / 16 + v % 16 * 16; if (stack[i + 1][0] == tokOpIndStack) - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegBWord, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegBWord, 0); } // operator @@ -1894,42 +1887,42 @@ void GenExpr1(void) case tokOpNumInt: case tokOpNumUint: GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpConst, stack[i + 2][1]); + I8086OpRegAWord, 0, + I8086OpConst, stack[i + 2][1]); break; case tokOpIdent: GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpLabel, stack[i + 2][1]); + I8086OpRegAWord, 0, + I8086OpLabel, stack[i + 2][1]); break; case tokOpLocalOfs: - GenPrintInstr2Operands(X86InstrLea, 0, - X86OpRegCWord, 0, - X86OpIndLocal, stack[i + 2][1]); + GenPrintInstr2Operands(I8086InstrLea, 0, + I8086OpRegCWord, 0, + I8086OpIndLocal, stack[i + 2][1]); GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpRegCWord, 0); + I8086OpRegAWord, 0, + I8086OpRegCWord, 0); break; case tokOpAcc: case tokOpIndAcc: // right operand in cx already GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpRegCWord, 0); + I8086OpRegAWord, 0, + I8086OpRegCWord, 0); break; case tokOpIndIdent: if (v % 16 - 8 != SizeOfWord) { GenReadCRegIdent(v % 16 - 8, stack[i + 2][1]); GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpRegCWord, 0); + I8086OpRegAWord, 0, + I8086OpRegCWord, 0); } else { GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpIndLabel, stack[i + 2][1]); + I8086OpRegAWord, 0, + I8086OpIndLabel, stack[i + 2][1]); } break; case tokOpIndLocalOfs: @@ -1937,14 +1930,14 @@ void GenExpr1(void) { GenReadCRegLocal(v % 16 - 8, stack[i + 2][1]); GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpRegCWord, 0); + I8086OpRegAWord, 0, + I8086OpRegCWord, 0); } else { GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpIndLocal, stack[i + 2][1]); + I8086OpRegAWord, 0, + I8086OpIndLocal, stack[i + 2][1]); } break; } @@ -1964,11 +1957,11 @@ void GenExpr1(void) case tokEQ: case tokNEQ: if (stack[i + 3][0] == tokIf) - GenPrintInstr1Operand(X86InstrJcc, tok, - X86OpNumLabel, stack[i + 3][1]); + GenPrintInstr1Operand(I8086InstrJcc, tok, + I8086OpNumLabel, stack[i + 3][1]); else - GenPrintInstr1Operand(X86InstrJNotCc, tok, - X86OpNumLabel, stack[i + 3][1]); + GenPrintInstr1Operand(I8086InstrJNotCc, tok, + I8086OpNumLabel, stack[i + 3][1]); break; } } @@ -1989,20 +1982,20 @@ void GenExpr1(void) { int labelCC = LabelCnt++; int labelCCAfter = LabelCnt++; - GenPrintInstr1Operand(X86InstrJcc, tok, - X86OpNumLabel, labelCC); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAByte, 0, - X86OpConst, 0); - GenPrintInstr1Operand(X86InstrJmp, 0, - X86OpNumLabel, labelCCAfter); + GenPrintInstr1Operand(I8086InstrJcc, tok, + I8086OpNumLabel, labelCC); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAByte, 0, + I8086OpConst, 0); + GenPrintInstr1Operand(I8086InstrJmp, 0, + I8086OpNumLabel, labelCCAfter); GenNumLabel(labelCC); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAByte, 0, - X86OpConst, 1); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAByte, 0, + I8086OpConst, 1); GenNumLabel(labelCCAfter); - GenPrintInstrNoOperand(X86InstrCbw); + GenPrintInstrNoOperand(I8086InstrCbw); } break; } @@ -2017,43 +2010,43 @@ void GenExpr1(void) { case tokOpNumInt: case tokOpNumUint: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegBWord, 0, - X86OpConst, stack[i + 2][1]); - GenPrintInstr1Operand(X86InstrImul, 0, - X86OpRegBWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegBWord, 0, + I8086OpConst, stack[i + 2][1]); + GenPrintInstr1Operand(I8086InstrImul, 0, + I8086OpRegBWord, 0); break; case tokOpIdent: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegBWord, 0, - X86OpLabel, stack[i + 2][1]); - GenPrintInstr1Operand(X86InstrImul, 0, - X86OpRegBWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegBWord, 0, + I8086OpLabel, stack[i + 2][1]); + GenPrintInstr1Operand(I8086InstrImul, 0, + I8086OpRegBWord, 0); break; case tokOpLocalOfs: - GenPrintInstr2Operands(X86InstrLea, 0, - X86OpRegCWord, 0, - X86OpIndLocal, stack[i + 2][1]); + GenPrintInstr2Operands(I8086InstrLea, 0, + I8086OpRegCWord, 0, + I8086OpIndLocal, stack[i + 2][1]); GenPrintInstr1Operand(instr, 0, - X86OpRegCWord, 0); + I8086OpRegCWord, 0); break; case tokOpAcc: case tokOpIndAcc: // right operand in cx already GenPrintInstr1Operand(instr, 0, - X86OpRegCWord, 0); + I8086OpRegCWord, 0); break; case tokOpIndIdent: if (v % 16 - 8 != SizeOfWord) { GenReadCRegIdent(v % 16 - 8, stack[i + 2][1]); GenPrintInstr1Operand(instr, 0, - X86OpRegCWord, 0); + I8086OpRegCWord, 0); } else { GenPrintInstr1Operand(instr, 0, - X86OpIndLabelExplicitWord, stack[i + 2][1]); + I8086OpIndLabelExplicitWord, stack[i + 2][1]); } break; case tokOpIndLocalOfs: @@ -2061,12 +2054,12 @@ void GenExpr1(void) { GenReadCRegLocal(v % 16 - 8, stack[i + 2][1]); GenPrintInstr1Operand(instr, 0, - X86OpRegCWord, 0); + I8086OpRegCWord, 0); } else { GenPrintInstr1Operand(instr, 0, - X86OpIndLocalExplicitWord, stack[i + 2][1]); + I8086OpIndLocalExplicitWord, stack[i + 2][1]); } break; } @@ -2089,12 +2082,12 @@ void GenExpr1(void) case tokAssignDiv: case tokAssignMod: - GenPrintInstrNoOperand(X86InstrCwd); + GenPrintInstrNoOperand(I8086InstrCwd); break; default: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegDWord, 0, - X86OpConst, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegDWord, 0, + I8086OpConst, 0); break; } @@ -2102,43 +2095,43 @@ void GenExpr1(void) { case tokOpNumInt: case tokOpNumUint: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCWord, 0, - X86OpConst, stack[i + 2][1]); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCWord, 0, + I8086OpConst, stack[i + 2][1]); GenPrintInstr1Operand(instr, 0, - X86OpRegCWord, 0); + I8086OpRegCWord, 0); break; case tokOpIdent: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCWord, 0, - X86OpLabel, stack[i + 2][1]); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCWord, 0, + I8086OpLabel, stack[i + 2][1]); GenPrintInstr1Operand(instr, 0, - X86OpRegCWord, 0); + I8086OpRegCWord, 0); break; case tokOpLocalOfs: - GenPrintInstr2Operands(X86InstrLea, 0, - X86OpRegCWord, 0, - X86OpIndLocal, stack[i + 2][1]); + GenPrintInstr2Operands(I8086InstrLea, 0, + I8086OpRegCWord, 0, + I8086OpIndLocal, stack[i + 2][1]); GenPrintInstr1Operand(instr, 0, - X86OpRegCWord, 0); + I8086OpRegCWord, 0); break; case tokOpAcc: case tokOpIndAcc: // right operand in cx already GenPrintInstr1Operand(instr, 0, - X86OpRegCWord, 0); + I8086OpRegCWord, 0); break; case tokOpIndIdent: if (v % 16 - 8 != SizeOfWord) { GenReadCRegIdent(v % 16 - 8, stack[i + 2][1]); GenPrintInstr1Operand(instr, 0, - X86OpRegCWord, 0); + I8086OpRegCWord, 0); } else { GenPrintInstr1Operand(instr, 0, - X86OpIndLabelExplicitWord, stack[i + 2][1]); + I8086OpIndLabelExplicitWord, stack[i + 2][1]); } break; case tokOpIndLocalOfs: @@ -2146,20 +2139,20 @@ void GenExpr1(void) { GenReadCRegLocal(v % 16 - 8, stack[i + 2][1]); GenPrintInstr1Operand(instr, 0, - X86OpRegCWord, 0); + I8086OpRegCWord, 0); } else { GenPrintInstr1Operand(instr, 0, - X86OpIndLocalExplicitWord, stack[i + 2][1]); + I8086OpIndLocalExplicitWord, stack[i + 2][1]); } } if (tok == '%' || tok == tokAssignMod || tok == tokUMod || tok == tokAssignUMod) - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAWord, 0, - X86OpRegDWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAWord, 0, + I8086OpRegDWord, 0); break; case tokLShift: @@ -2174,51 +2167,51 @@ void GenExpr1(void) { case tokOpNumInt: case tokOpNumUint: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCByte, 0, - X86OpConst, stack[i + 2][1]); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCByte, 0, + I8086OpConst, stack[i + 2][1]); GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpRegCByte, 0); + I8086OpRegAWord, 0, + I8086OpRegCByte, 0); break; case tokOpIdent: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCByte, 0, - X86OpLabel, stack[i + 2][1]); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCByte, 0, + I8086OpLabel, stack[i + 2][1]); GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpRegCByte, 0); + I8086OpRegAWord, 0, + I8086OpRegCByte, 0); break; case tokOpLocalOfs: - GenPrintInstr2Operands(X86InstrLea, 0, - X86OpRegCWord, 0, - X86OpIndLocal, stack[i + 2][1]); + GenPrintInstr2Operands(I8086InstrLea, 0, + I8086OpRegCWord, 0, + I8086OpIndLocal, stack[i + 2][1]); GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpRegCByte, 0); + I8086OpRegAWord, 0, + I8086OpRegCByte, 0); break; case tokOpAcc: case tokOpIndAcc: // right operand in cx already GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpRegCByte, 0); + I8086OpRegAWord, 0, + I8086OpRegCByte, 0); break; case tokOpIndIdent: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCByte, 0, - X86OpIndLabel, stack[i + 2][1]); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCByte, 0, + I8086OpIndLabel, stack[i + 2][1]); GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpRegCByte, 0); + I8086OpRegAWord, 0, + I8086OpRegCByte, 0); break; case tokOpIndLocalOfs: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCByte, 0, - X86OpIndLocal, stack[i + 2][1]); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCByte, 0, + I8086OpIndLocal, stack[i + 2][1]); GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpRegCByte, 0); + I8086OpRegAWord, 0, + I8086OpRegCByte, 0); break; } break; @@ -2252,20 +2245,20 @@ void GenExpr1(void) switch (stack[i + 1][0]) { case tokOpIndIdent: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpIndLabel, stack[i + 1][1], - GenSelectByteOrWord(X86OpRegAByteOrWord, v / 16 - 8), 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpIndLabel, stack[i + 1][1], + GenSelectByteOrWord(I8086OpRegAByteOrWord, v / 16 - 8), 0); break; case tokOpIndLocalOfs: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpIndLocal, stack[i + 1][1], - GenSelectByteOrWord(X86OpRegAByteOrWord, v / 16 - 8), 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpIndLocal, stack[i + 1][1], + GenSelectByteOrWord(I8086OpRegAByteOrWord, v / 16 - 8), 0); break; case tokOpIndAcc: case tokOpIndStack: - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpIndRegB, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, v / 16 - 8), 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpIndRegB, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, v / 16 - 8), 0); break; } // the result of the expression is of type of the @@ -2279,13 +2272,13 @@ void GenExpr1(void) // DONE: "call ident" if (stack[i - 1][0] == tokIdent) { - GenPrintInstr1Operand(X86InstrCall, 0, - X86OpLabel, stack[i - 1][1]); + GenPrintInstr1Operand(I8086InstrCall, 0, + I8086OpLabel, stack[i - 1][1]); } else { - GenPrintInstr1Operand(X86InstrCall, 0, - X86OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrCall, 0, + I8086OpRegAWord, 0); } GenGrowStack(-v); break; @@ -2345,37 +2338,37 @@ void GenExpr0(void) case tokNumInt: case tokNumUint: if (gotUnary) - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpRegAWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAWord, 0, - X86OpConst, v); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAWord, 0, + I8086OpConst, v); gotUnary = 1; break; case tokIdent: if (gotUnary) - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpRegAWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAWord, 0, - X86OpLabel, v); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAWord, 0, + I8086OpLabel, v); gotUnary = 1; break; case tokLocalOfs: if (gotUnary) - GenPrintInstr1Operand(X86InstrPush, 0, - X86OpRegAWord, 0); - GenPrintInstr2Operands(X86InstrLea, 0, - X86OpRegAWord, 0, - X86OpIndLocal, v); + GenPrintInstr1Operand(I8086InstrPush, 0, + I8086OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrLea, 0, + I8086OpRegAWord, 0, + I8086OpIndLocal, v); gotUnary = 1; break; case ')': - GenPrintInstr1Operand(X86InstrCall, 0, - X86OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrCall, 0, + I8086OpRegAWord, 0); GenGrowStack(-v); break; @@ -2386,12 +2379,12 @@ void GenExpr0(void) case tokUnaryPlus: break; case '~': - GenPrintInstr1Operand(X86InstrNot, 0, - X86OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrNot, 0, + I8086OpRegAWord, 0); break; case tokUnaryMinus: - GenPrintInstr1Operand(X86InstrNeg, 0, - X86OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrNeg, 0, + I8086OpRegAWord, 0); break; case '+': @@ -2402,19 +2395,19 @@ void GenExpr0(void) case '|': { int instr = GenGetBinaryOperatorInstr(tok); - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegBWord, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegBWord, 0); if (tok == '-') - GenPrintInstr2Operands(X86InstrXchg, 0, - X86OpRegAWord, 0, - X86OpRegBWord, 0); + GenPrintInstr2Operands(I8086InstrXchg, 0, + I8086OpRegAWord, 0, + I8086OpRegBWord, 0); if (tok != '*') GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpRegBWord, 0); + I8086OpRegAWord, 0, + I8086OpRegBWord, 0); else GenPrintInstr1Operand(instr, 0, - X86OpRegBWord, 0); + I8086OpRegBWord, 0); } break; @@ -2422,30 +2415,30 @@ void GenExpr0(void) case tokUDiv: case '%': case tokUMod: - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegBWord, 0); - GenPrintInstr2Operands(X86InstrXchg, 0, - X86OpRegAWord, 0, - X86OpRegBWord, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegBWord, 0); + GenPrintInstr2Operands(I8086InstrXchg, 0, + I8086OpRegAWord, 0, + I8086OpRegBWord, 0); if (tok == '/' || tok == '%') { - GenPrintInstrNoOperand(X86InstrCwd); - GenPrintInstr1Operand(X86InstrIdiv, 0, - X86OpRegBWord, 0); + GenPrintInstrNoOperand(I8086InstrCwd); + GenPrintInstr1Operand(I8086InstrIdiv, 0, + I8086OpRegBWord, 0); } else { - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegDWord, 0, - X86OpConst, 0); - GenPrintInstr1Operand(X86InstrDiv, 0, - X86OpRegBWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegDWord, 0, + I8086OpConst, 0); + GenPrintInstr1Operand(I8086InstrDiv, 0, + I8086OpRegBWord, 0); } if (tok == '%' || tok == tokUMod) - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAWord, 0, - X86OpRegDWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAWord, 0, + I8086OpRegDWord, 0); break; case tokLShift: @@ -2453,14 +2446,14 @@ void GenExpr0(void) case tokURShift: { int instr = GenGetBinaryOperatorInstr(tok); - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegCWord, 0); - GenPrintInstr2Operands(X86InstrXchg, 0, - X86OpRegAWord, 0, - X86OpRegCWord, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegCWord, 0); + GenPrintInstr2Operands(I8086InstrXchg, 0, + I8086OpRegAWord, 0, + I8086OpRegCWord, 0); GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpRegCByte, 0); + I8086OpRegAWord, 0, + I8086OpRegCByte, 0); } break; @@ -2481,17 +2474,17 @@ void GenExpr0(void) case tokPostSub: { int instr = GenGetBinaryOperatorInstr(tok); - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegBWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCWord, 0, - X86OpRegAWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0, - X86OpIndRegB, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegBWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCWord, 0, + I8086OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0, + I8086OpIndRegB, 0); GenPrintInstr2Operands(instr, 0, - X86OpIndRegB, 0, - GenSelectByteOrWord(X86OpRegCByteOrWord, v), 0); + I8086OpIndRegB, 0, + GenSelectByteOrWord(I8086OpRegCByteOrWord, v), 0); GenExtendRegAIfNeeded(v); } break; @@ -2504,24 +2497,24 @@ void GenExpr0(void) case tokAssignOr: { int instr = GenGetBinaryOperatorInstr(tok); - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegBWord, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegBWord, 0); if (tok != tokAssignMul) { GenPrintInstr2Operands(instr, 0, - X86OpIndRegB, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0); - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0, - X86OpIndRegB, 0); + I8086OpIndRegB, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0, + I8086OpIndRegB, 0); } else { GenPrintInstr1Operand(instr, 0, - GenSelectByteOrWord(X86OpIndRegBExplicitByteOrWord, v), 0); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpIndRegB, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0); + GenSelectByteOrWord(I8086OpIndRegBExplicitByteOrWord, v), 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpIndRegB, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0); } GenExtendRegAIfNeeded(v); } @@ -2531,37 +2524,37 @@ void GenExpr0(void) case tokAssignUDiv: case tokAssignMod: case tokAssignUMod: - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegBWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCWord, 0, - X86OpRegAWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0, - X86OpIndRegB, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegBWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCWord, 0, + I8086OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0, + I8086OpIndRegB, 0); GenExtendRegAIfNeeded(v); if (tok == tokAssignDiv || tok == tokAssignMod) { - GenPrintInstrNoOperand(X86InstrCwd); - GenPrintInstr1Operand(X86InstrIdiv, 0, - X86OpRegCWord, 0); + GenPrintInstrNoOperand(I8086InstrCwd); + GenPrintInstr1Operand(I8086InstrIdiv, 0, + I8086OpRegCWord, 0); } else { - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegDWord, 0, - X86OpConst, 0); - GenPrintInstr1Operand(X86InstrDiv, 0, - X86OpRegCWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegDWord, 0, + I8086OpConst, 0); + GenPrintInstr1Operand(I8086InstrDiv, 0, + I8086OpRegCWord, 0); } if (tok == tokAssignMod || tok == tokAssignUMod) - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegAWord, 0, - X86OpRegDWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpIndRegB, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegAWord, 0, + I8086OpRegDWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpIndRegB, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0); GenExtendRegAIfNeeded(v); break; @@ -2570,31 +2563,31 @@ void GenExpr0(void) case tokAssignURSh: { int instr = GenGetBinaryOperatorInstr(tok); - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegBWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpRegCWord, 0, - X86OpRegAWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0, - X86OpIndRegB, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegBWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpRegCWord, 0, + I8086OpRegAWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0, + I8086OpIndRegB, 0); GenExtendRegAIfNeeded(v); GenPrintInstr2Operands(instr, 0, - X86OpRegAWord, 0, - X86OpRegCByte, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpIndRegB, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0); + I8086OpRegAWord, 0, + I8086OpRegCByte, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpIndRegB, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0); GenExtendRegAIfNeeded(v); } break; case '=': - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegBWord, 0); - GenPrintInstr2Operands(X86InstrMov, 0, - X86OpIndRegB, 0, - GenSelectByteOrWord(X86OpRegAByteOrWord, v), 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegBWord, 0); + GenPrintInstr2Operands(I8086InstrMov, 0, + I8086OpIndRegB, 0, + GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0); GenExtendRegAIfNeeded(v); break; @@ -2608,32 +2601,32 @@ void GenExpr0(void) case tokUGEQ: case tokEQ: case tokNEQ: - GenPrintInstr1Operand(X86InstrPop, 0, - X86OpRegBWord, 0); - GenPrintInstr2Operands(X86InstrCmp, 0, - X86OpRegBWord, 0, - X86OpRegAWord, 0); - GenPrintInstr1Operand(X86InstrSetCc, tok, - X86OpRegAByte, 0); + GenPrintInstr1Operand(I8086InstrPop, 0, + I8086OpRegBWord, 0); + GenPrintInstr2Operands(I8086InstrCmp, 0, + I8086OpRegBWord, 0, + I8086OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrSetCc, tok, + I8086OpRegAByte, 0); - GenPrintInstrNoOperand(X86InstrCbw); + GenPrintInstrNoOperand(I8086InstrCbw); break; case tok_Bool: - GenPrintInstr2Operands(X86InstrTest, 0, - X86OpRegAWord, 0, - X86OpRegAWord, 0); - GenPrintInstr1Operand(X86InstrSetCc, tokNEQ, - X86OpRegAByte, 0); + GenPrintInstr2Operands(I8086InstrTest, 0, + I8086OpRegAWord, 0, + I8086OpRegAWord, 0); + GenPrintInstr1Operand(I8086InstrSetCc, tokNEQ, + I8086OpRegAByte, 0); // fallthrough case tokSChar: - GenPrintInstrNoOperand(X86InstrCbw); + GenPrintInstrNoOperand(I8086InstrCbw); break; case tokUChar: - GenPrintInstr2Operands(X86InstrAnd, 0, - X86OpRegAWord, 0, - X86OpConst, 0xFF); + GenPrintInstr2Operands(I8086InstrAnd, 0, + I8086OpRegAWord, 0, + I8086OpConst, 0xFF); break; case tokShortCirc: diff --git a/v0100/smlrcc.c b/v0100/smlrcc.c index 28d12a0..4b07c15 100644 --- a/v0100/smlrcc.c +++ b/v0100/smlrcc.c @@ -1787,6 +1787,9 @@ int main(int argc, char* argv[]) InputFileCnt++; } + if(Use8086InstrOnly && !(OutputFormat == FormatDos8086ComTiny || OutputFormat == FormatDos8086ExeSmall)) + error("Invalid output format for 8086 option."); + if (!InputFileCnt) error("No inputs\n"); diff --git a/v0100/tests/snake.com b/v0100/tests/snake.com deleted file mode 100644 index d0b85582019df647eeda75c9db312f12f9e80085..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6212 zcmeHHU1%d!6u#-q&P-!zs?_3a!OcQ-SBmSpT0<>CeefD7W(U>Gp4h-o^vNnGFo4J@?lDv z+pfz9^SLqE9#a;mHm@FN zx7bv(f|dn!g#<$y{^FKmK4;#~e&xk2&!RP()-39o&w}Y&-&7a=FPeUDgw|$%w5e=W zY+AQeSQX11xT#sHsG_(P6~_LL3Avmg)!!^yKTEd_b`C&bRWsPjxPpukx}8&a+OsKq zYJ+rJl;90g7pf5cdhE6G;#_&Q6GG<7D9Btn-{EvPml|iuHdUs|hb1acK^YWKyHEs0k9e1E(*BAvOs3=h_Ww0mOJ%}aIXi9+XKpBA? z1iBr=|CN_!RTflK@fg$zQW-EV944j``!x1g=Nib?66^hI0kJ-BfNCX~Sk$$tTXe~b zL(o!*x`=}vk7CEau~th*No4KRyt>$KhojP%=Tu6B%u~L|3sIbih6JNfxhoEtT* zpD9nLzkFbF-|$gFCYQmm%6e|$FNuIsw~j+6H-}C(BW%NixiVwfUft|6qs#+!T=oGB zPJSP|`i zJ7l;43=?`YFyUh**ef8gD>k-TbR)4>#jD-jv>fu^asL6Iy?z&g>eMrg{xty Date: Sun, 12 May 2024 00:01:39 -0300 Subject: [PATCH 4/6] Remove unused code in cg8086 --- v0100/cg8086.c | 402 ------------------------------------------------- 1 file changed, 402 deletions(-) diff --git a/v0100/cg8086.c b/v0100/cg8086.c index 73a316d..90dc533 100644 --- a/v0100/cg8086.c +++ b/v0100/cg8086.c @@ -245,7 +245,6 @@ void GenRecordFxnSize(char* startLabelName, int endLabelNo) #define I8086InstrCbw 0x19 #define I8086InstrCwd 0x1A #define I8086InstrCdq 0x1B -#define I8086InstrSetCc 0x1C #define I8086InstrJcc 0x1D #define I8086InstrJNotCc 0x1E #define I8086InstrLeave 0x1F @@ -338,21 +337,6 @@ void GenPrintInstr(int instr, int val) } break; - case I8086InstrSetCc: - switch (val) - { - case '<': p = "setl"; break; - case tokULess: p = "setb"; break; - case '>': p = "setg"; break; - case tokUGreater: p = "seta"; break; - case tokLEQ: p = "setle"; break; - case tokULEQ: p = "setbe"; break; - case tokGEQ: p = "setge"; break; - case tokUGEQ: p = "setae"; break; - case tokEQ: p = "sete"; break; - case tokNEQ: p = "setne"; break; - } - break; default: p = winstrs[instr]; @@ -1416,9 +1400,6 @@ int GenGetBinaryOperatorInstr(int tok) } } -// Newer, less stack-dependent code generator, -// generates more compact code (~30% less) than the stack-based generator -#ifndef CG_STACK_BASED STATIC void GenExpr1(void) { @@ -2300,385 +2281,6 @@ void GenExpr1(void) } } } -#else // #ifndef CG_STACK_BASED -// Original, primitive stack-based code generator -// DONE: test 32-bit code generation -STATIC -void GenExpr0(void) -{ - int i; - int gotUnary = 0; - - for (i = 0; i < sp; i++) - { - int tok = stack[i][0]; - int v = stack[i][1]; - -#ifndef NO_ANNOTATIONS - switch (tok) - { - case tokNumInt: printf2("; %d\n", truncInt(v)); break; - case tokNumUint: printf2("; %uu\n", truncUint(v)); break; - case tokIdent: printf2("; %s\n", IdentTable + v); break; - case tokLocalOfs: printf2("; local ofs\n"); break; - case ')': printf2("; ) fxn call\n"); break; - case tokUnaryStar: printf2("; * (read dereference)\n"); break; - case '=': printf2("; = (write dereference)\n"); break; - case tokShortCirc: printf2("; short-circuit "); break; - case tokGoto: printf2("; sh-circ-goto "); break; - case tokLogAnd: printf2("; short-circuit && target\n"); break; - case tokLogOr: printf2("; short-circuit || target\n"); break; - case tokIf: case tokIfNot: case tokReturn: break; - default: printf2("; %s\n", GetTokenName(tok)); break; - } -#endif - - switch (tok) - { - case tokNumInt: - case tokNumUint: - if (gotUnary) - GenPrintInstr1Operand(I8086InstrPush, 0, - I8086OpRegAWord, 0); - GenPrintInstr2Operands(I8086InstrMov, 0, - I8086OpRegAWord, 0, - I8086OpConst, v); - gotUnary = 1; - break; - - case tokIdent: - if (gotUnary) - GenPrintInstr1Operand(I8086InstrPush, 0, - I8086OpRegAWord, 0); - GenPrintInstr2Operands(I8086InstrMov, 0, - I8086OpRegAWord, 0, - I8086OpLabel, v); - gotUnary = 1; - break; - - case tokLocalOfs: - if (gotUnary) - GenPrintInstr1Operand(I8086InstrPush, 0, - I8086OpRegAWord, 0); - GenPrintInstr2Operands(I8086InstrLea, 0, - I8086OpRegAWord, 0, - I8086OpIndLocal, v); - gotUnary = 1; - break; - - case ')': - GenPrintInstr1Operand(I8086InstrCall, 0, - I8086OpRegAWord, 0); - GenGrowStack(-v); - break; - - case tokUnaryStar: - GenReadIndirect(v); - break; - - case tokUnaryPlus: - break; - case '~': - GenPrintInstr1Operand(I8086InstrNot, 0, - I8086OpRegAWord, 0); - break; - case tokUnaryMinus: - GenPrintInstr1Operand(I8086InstrNeg, 0, - I8086OpRegAWord, 0); - break; - - case '+': - case '-': - case '*': - case '&': - case '^': - case '|': - { - int instr = GenGetBinaryOperatorInstr(tok); - GenPrintInstr1Operand(I8086InstrPop, 0, - I8086OpRegBWord, 0); - if (tok == '-') - GenPrintInstr2Operands(I8086InstrXchg, 0, - I8086OpRegAWord, 0, - I8086OpRegBWord, 0); - if (tok != '*') - GenPrintInstr2Operands(instr, 0, - I8086OpRegAWord, 0, - I8086OpRegBWord, 0); - else - GenPrintInstr1Operand(instr, 0, - I8086OpRegBWord, 0); - } - break; - - case '/': - case tokUDiv: - case '%': - case tokUMod: - GenPrintInstr1Operand(I8086InstrPop, 0, - I8086OpRegBWord, 0); - GenPrintInstr2Operands(I8086InstrXchg, 0, - I8086OpRegAWord, 0, - I8086OpRegBWord, 0); - if (tok == '/' || tok == '%') - { - - GenPrintInstrNoOperand(I8086InstrCwd); - GenPrintInstr1Operand(I8086InstrIdiv, 0, - I8086OpRegBWord, 0); - } - else - { - GenPrintInstr2Operands(I8086InstrMov, 0, - I8086OpRegDWord, 0, - I8086OpConst, 0); - GenPrintInstr1Operand(I8086InstrDiv, 0, - I8086OpRegBWord, 0); - } - if (tok == '%' || tok == tokUMod) - GenPrintInstr2Operands(I8086InstrMov, 0, - I8086OpRegAWord, 0, - I8086OpRegDWord, 0); - break; - - case tokLShift: - case tokRShift: - case tokURShift: - { - int instr = GenGetBinaryOperatorInstr(tok); - GenPrintInstr1Operand(I8086InstrPop, 0, - I8086OpRegCWord, 0); - GenPrintInstr2Operands(I8086InstrXchg, 0, - I8086OpRegAWord, 0, - I8086OpRegCWord, 0); - GenPrintInstr2Operands(instr, 0, - I8086OpRegAWord, 0, - I8086OpRegCByte, 0); - } - break; - - case tokInc: - GenIncDecIndirect(v, tok); - break; - case tokDec: - GenIncDecIndirect(v, tok); - break; - case tokPostInc: - GenPostIncDecIndirect(v, tok); - break; - case tokPostDec: - GenPostIncDecIndirect(v, tok); - break; - - case tokPostAdd: - case tokPostSub: - { - int instr = GenGetBinaryOperatorInstr(tok); - GenPrintInstr1Operand(I8086InstrPop, 0, - I8086OpRegBWord, 0); - GenPrintInstr2Operands(I8086InstrMov, 0, - I8086OpRegCWord, 0, - I8086OpRegAWord, 0); - GenPrintInstr2Operands(I8086InstrMov, 0, - GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0, - I8086OpIndRegB, 0); - GenPrintInstr2Operands(instr, 0, - I8086OpIndRegB, 0, - GenSelectByteOrWord(I8086OpRegCByteOrWord, v), 0); - GenExtendRegAIfNeeded(v); - } - break; - - case tokAssignAdd: - case tokAssignSub: - case tokAssignMul: - case tokAssignAnd: - case tokAssignXor: - case tokAssignOr: - { - int instr = GenGetBinaryOperatorInstr(tok); - GenPrintInstr1Operand(I8086InstrPop, 0, - I8086OpRegBWord, 0); - if (tok != tokAssignMul) - { - GenPrintInstr2Operands(instr, 0, - I8086OpIndRegB, 0, - GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0); - GenPrintInstr2Operands(I8086InstrMov, 0, - GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0, - I8086OpIndRegB, 0); - } - else - { - GenPrintInstr1Operand(instr, 0, - GenSelectByteOrWord(I8086OpIndRegBExplicitByteOrWord, v), 0); - GenPrintInstr2Operands(I8086InstrMov, 0, - I8086OpIndRegB, 0, - GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0); - } - GenExtendRegAIfNeeded(v); - } - break; - - case tokAssignDiv: - case tokAssignUDiv: - case tokAssignMod: - case tokAssignUMod: - GenPrintInstr1Operand(I8086InstrPop, 0, - I8086OpRegBWord, 0); - GenPrintInstr2Operands(I8086InstrMov, 0, - I8086OpRegCWord, 0, - I8086OpRegAWord, 0); - GenPrintInstr2Operands(I8086InstrMov, 0, - GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0, - I8086OpIndRegB, 0); - GenExtendRegAIfNeeded(v); - if (tok == tokAssignDiv || tok == tokAssignMod) - { - - GenPrintInstrNoOperand(I8086InstrCwd); - GenPrintInstr1Operand(I8086InstrIdiv, 0, - I8086OpRegCWord, 0); - } - else - { - GenPrintInstr2Operands(I8086InstrMov, 0, - I8086OpRegDWord, 0, - I8086OpConst, 0); - GenPrintInstr1Operand(I8086InstrDiv, 0, - I8086OpRegCWord, 0); - } - if (tok == tokAssignMod || tok == tokAssignUMod) - GenPrintInstr2Operands(I8086InstrMov, 0, - I8086OpRegAWord, 0, - I8086OpRegDWord, 0); - GenPrintInstr2Operands(I8086InstrMov, 0, - I8086OpIndRegB, 0, - GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0); - GenExtendRegAIfNeeded(v); - break; - - case tokAssignLSh: - case tokAssignRSh: - case tokAssignURSh: - { - int instr = GenGetBinaryOperatorInstr(tok); - GenPrintInstr1Operand(I8086InstrPop, 0, - I8086OpRegBWord, 0); - GenPrintInstr2Operands(I8086InstrMov, 0, - I8086OpRegCWord, 0, - I8086OpRegAWord, 0); - GenPrintInstr2Operands(I8086InstrMov, 0, - GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0, - I8086OpIndRegB, 0); - GenExtendRegAIfNeeded(v); - GenPrintInstr2Operands(instr, 0, - I8086OpRegAWord, 0, - I8086OpRegCByte, 0); - GenPrintInstr2Operands(I8086InstrMov, 0, - I8086OpIndRegB, 0, - GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0); - GenExtendRegAIfNeeded(v); - } - break; - - case '=': - GenPrintInstr1Operand(I8086InstrPop, 0, - I8086OpRegBWord, 0); - GenPrintInstr2Operands(I8086InstrMov, 0, - I8086OpIndRegB, 0, - GenSelectByteOrWord(I8086OpRegAByteOrWord, v), 0); - GenExtendRegAIfNeeded(v); - break; - - case '<': - case tokULess: - case '>': - case tokUGreater: - case tokLEQ: - case tokULEQ: - case tokGEQ: - case tokUGEQ: - case tokEQ: - case tokNEQ: - GenPrintInstr1Operand(I8086InstrPop, 0, - I8086OpRegBWord, 0); - GenPrintInstr2Operands(I8086InstrCmp, 0, - I8086OpRegBWord, 0, - I8086OpRegAWord, 0); - GenPrintInstr1Operand(I8086InstrSetCc, tok, - I8086OpRegAByte, 0); - - GenPrintInstrNoOperand(I8086InstrCbw); - break; - - case tok_Bool: - GenPrintInstr2Operands(I8086InstrTest, 0, - I8086OpRegAWord, 0, - I8086OpRegAWord, 0); - GenPrintInstr1Operand(I8086InstrSetCc, tokNEQ, - I8086OpRegAByte, 0); - // fallthrough - case tokSChar: - - GenPrintInstrNoOperand(I8086InstrCbw); - break; - case tokUChar: - GenPrintInstr2Operands(I8086InstrAnd, 0, - I8086OpRegAWord, 0, - I8086OpConst, 0xFF); - break; - - case tokShortCirc: -#ifndef NO_ANNOTATIONS - if (v >= 0) - printf2("&&\n"); - else - printf2("||\n"); -#endif - if (v >= 0) - GenJumpIfZero(v); // && - else - GenJumpIfNotZero(-v); // || - gotUnary = 0; - break; - case tokGoto: -#ifndef NO_ANNOTATIONS - printf2("goto\n"); -#endif - GenJumpUncond(v); - gotUnary = 0; - break; - case tokLogAnd: - case tokLogOr: - GenNumLabel(v); - break; - - case tokVoid: - gotUnary = 0; - break; - - case tokComma: - case ',': - case '(': - case tokReturn: - break; - - case tokIf: - GenJumpIfNotZero(stack[i][1]); - break; - case tokIfNot: - GenJumpIfZero(stack[i][1]); - break; - - default: - //error("Error: Internal Error: GenExpr0(): unexpected token %s\n", GetTokenName(tok)); - errorInternal(105); - break; - } - } -} -#endif // #ifndef CG_STACK_BASED STATIC void GenDumpChar(int ch) @@ -2735,11 +2337,7 @@ void GenExpr(void) if (stack[i][0] == tokIdent && !isdigit(IdentTable[stack[i][1]])) GenAddGlobal(IdentTable + stack[i][1], 2); } -#ifndef CG_STACK_BASED GenExpr1(); -#else - GenExpr0(); -#endif } STATIC From faaec0a9ab5ed38eb1f63a13cfa9c806fb7539c1 Mon Sep 17 00:00:00 2001 From: Humberto Costa Date: Sun, 12 May 2024 22:29:48 -0300 Subject: [PATCH 5/6] Allow custom MaxHeap/MinHeap on Small DOS EXE, with Stack realoc to end of Heap - Add (optional) custom Heap+Stack configuration on Small DOS EXE, generating really small footprint for limited environvments (HP 95LX or IBM PC with < 256K RAM) --- v0100/smlrl.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/v0100/smlrl.c b/v0100/smlrl.c index 6c2dc37..908b4f3 100644 --- a/v0100/smlrl.c +++ b/v0100/smlrl.c @@ -2727,8 +2727,29 @@ void RwDosExe(void) // data/stack segment starts right after code segment's padding: DosExeHeader.InitSs = (pSectDescrs[SectCnt].Stop + 15) / 16 - sizeof(tDosExeHeader) / 16; - // maximum stack size = data segment size - data size: - DosExeHeader.MaxAlloc = DosExeHeader.MinAlloc = 4096 - dsz / 16; + // if MaxHeap or MinHeap is defined, calculate new data segment size + // permit data segment < 64KiB + if(MaxHeap != 0xFFFFFFFF || MinHeap != 0xFFFFFFFF) + { + uint32 hsz = pSectDescrs[SectCnt + 2].Start - pSectDescrs[SectCnt + hasData].Stop; + if(MinHeap != 0xFFFFFFFF && hsz < MinHeap) + errStackTooBig(); + if(MaxHeap != 0xFFFFFFFF && hsz > MaxHeap) + { + pSectDescrs[SectCnt + 2].Start = (pSectDescrs[SectCnt + hasData].Stop + MaxHeap) & 0xfffc; + if(pSectDescrs[SectCnt + 2].Start > (0xfffc - StackSize)) + errStackTooBig(); + pSectDescrs[SectCnt + 2].Stop = (pSectDescrs[SectCnt + 2].Start + StackSize - 1) & 0xfffc; + DosExeHeader.InitSp = pSectDescrs[SectCnt + 2].Stop; + } + // maximum stack size = data segment size - data size + heap size + stack size: + DosExeHeader.MaxAlloc = DosExeHeader.MinAlloc = (DosExeHeader.InitSp + 15) / 16 - dsz / 16; + } + else + { + // maximum stack size = data segment size - data size: + DosExeHeader.MaxAlloc = DosExeHeader.MinAlloc = 4096 - dsz / 16; + } Fwrite(&DosExeHeader, sizeof DosExeHeader, fout); } break; From 71095f3fdb2ada5fadb42517240cbb8fd6129f97 Mon Sep 17 00:00:00 2001 From: Humberto Costa Date: Thu, 4 Jul 2024 17:09:19 -0300 Subject: [PATCH 6/6] Fix smrlcc ignores -8086 flag --- v0100/include/stdbool.h | 15 +++++++++++++++ v0100/smlrcc.c | 14 +++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 v0100/include/stdbool.h diff --git a/v0100/include/stdbool.h b/v0100/include/stdbool.h new file mode 100644 index 0000000..8212029 --- /dev/null +++ b/v0100/include/stdbool.h @@ -0,0 +1,15 @@ +/* + Copyright (c) 2014, Alexey Frunze + 2-clause BSD license. +*/ +#ifndef __STDBOOL_H +#define __STDBOOL_H + +#ifdef __SMALLER_PP__ +#define _Bool int +#define bool _Bool +#define true 1 +#define false 0 +#endif + +#endif diff --git a/v0100/smlrcc.c b/v0100/smlrcc.c index 4b07c15..3f0ac12 100644 --- a/v0100/smlrcc.c +++ b/v0100/smlrcc.c @@ -1367,6 +1367,13 @@ int main(int argc, char* argv[]) int UnsignedChar = 0; // default in smlrc int UnsignedWideChar = -1; int ShortWideChar = -1; + for (i = 1; i < argc; i++) + { + if (!strcmp(argv[i], "-8086")) + { + Use8086InstrOnly = 1; + } + } #ifdef __SMALLER_C__ #ifdef DETERMINE_VA_LIST @@ -1435,13 +1442,6 @@ int main(int argc, char* argv[]) AddOptions(&PrepOptions, &PrepOptionsLen, "smlrpp.exe -U __STDC_VERSION__ -zI"); #endif } - for (i = 1; i < argc; i++) - { - if (!strcmp(argv[i], "-8086")) - { - Use8086InstrOnly = 1; - } - } for (i = 1; i < argc; i++) {