Smaller C improvements
- type specifiers may occur in any order (e.g. "unsigned short int" and "int short unsigned") - use .rodata/.rdata section for string literals - arbitrary length string literals (hooray!) - better concatenation of adjacent string literals (now works even across preprocessor directives) Support .bss section - -nobss option in smlrc: use .data instead of .bss as before - take advantage of .bss in smlrc (put a large array into it) Remove dead/useless code Remove useless/rarely used features/options: -use-gp (MIPS) -flat16/-flat32 (x86) -seg16t (x86), -seg16 is now the default -ctor-fxn Add/change: - use EXIT_FAILURE=1 instead of -1 in smlrc when aborting due to an error
This commit is contained in:
@@ -39,14 +39,6 @@ either expressed or implied, of the FreeBSD Project.
|
||||
|
||||
// Works around bugs in RetroBSD's as instruction reordering
|
||||
#define REORDER_WORKAROUND
|
||||
// Works around bugs in RetroBSD's as immediate operand truncation to 16 bits
|
||||
//#define INSTR_IMM_WORKAROUND
|
||||
// Allows the -use-gp option (generally unreliable since implemented simplistically)
|
||||
//#define ALLOW_GP
|
||||
|
||||
#ifdef ALLOW_GP
|
||||
int UseGp = 0;
|
||||
#endif
|
||||
|
||||
STATIC
|
||||
void GenInit(void)
|
||||
@@ -54,8 +46,10 @@ void GenInit(void)
|
||||
// initialization of target-specific code generator
|
||||
SizeOfWord = 4;
|
||||
OutputFormat = FormatSegmented;
|
||||
CodeHeader = "\t.text";
|
||||
DataHeader = "\t.data";
|
||||
CodeHeaderFooter[0] = "\t.text";
|
||||
DataHeaderFooter[0] = "\t.data";
|
||||
RoDataHeaderFooter[0] = "\t.rdata";
|
||||
BssHeaderFooter[0] = "\t.bss";
|
||||
UseLeadingUnderscores = 0;
|
||||
#ifdef REORDER_WORKAROUND
|
||||
FileHeader = "\t.set\tnoreorder";
|
||||
@@ -69,15 +63,6 @@ int GenInitParams(int argc, char** argv, int* idx)
|
||||
{
|
||||
(void)argc;
|
||||
// initialization of target-specific code generator with parameters
|
||||
#ifdef ALLOW_GP
|
||||
if (!strcmp(argv[*idx], "-use-gp"))
|
||||
{
|
||||
UseGp = 1;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
// fallthrough
|
||||
#endif
|
||||
if (!strcmp(argv[*idx], "-v"))
|
||||
{
|
||||
// RetroBSD's cc may supply this parameter. Just need to consume it.
|
||||
@@ -100,8 +85,9 @@ void GenStartCommentLine(void)
|
||||
}
|
||||
|
||||
STATIC
|
||||
void GenWordAlignment(void)
|
||||
void GenWordAlignment(int bss)
|
||||
{
|
||||
(void)bss;
|
||||
printf2("\t.align 2\n");
|
||||
}
|
||||
|
||||
@@ -109,7 +95,7 @@ STATIC
|
||||
void GenLabel(char* Label, int Static)
|
||||
{
|
||||
{
|
||||
if (OutputFormat != FormatFlat && !Static && GenExterns)
|
||||
if (!Static && GenExterns)
|
||||
printf2("\t.globl\t%s\n", Label);
|
||||
printf2("%s:\n", Label);
|
||||
}
|
||||
@@ -139,8 +125,9 @@ void GenPrintNumLabel(int label)
|
||||
}
|
||||
|
||||
STATIC
|
||||
void GenZeroData(unsigned Size)
|
||||
void GenZeroData(unsigned Size, int bss)
|
||||
{
|
||||
(void)bss;
|
||||
printf2("\t.space\t%u\n", truncUint(Size)); // or ".fill size"
|
||||
}
|
||||
|
||||
@@ -318,7 +305,7 @@ void GenPrintInstr(int instr, int val)
|
||||
#define MipsOpConst 0x80
|
||||
#define MipsOpLabel 0x81
|
||||
#define MipsOpNumLabel 0x82
|
||||
#define MipsOpLabelGpOption 0x83
|
||||
#define MipsOpLabelLo 0x83
|
||||
#define MipsOpIndLocal MipsOpIndRegFp
|
||||
|
||||
#define MAX_TEMP_REGS 8 // this many temp registers used beginning with T0 to hold subexpression results
|
||||
@@ -349,22 +336,10 @@ void GenPrintOperand(int op, int val)
|
||||
switch (op)
|
||||
{
|
||||
case MipsOpConst: printf2("%d", truncInt(val)); break;
|
||||
case MipsOpLabelGpOption:
|
||||
#ifdef ALLOW_GP
|
||||
if (UseGp)
|
||||
{
|
||||
printf2("%%gp_rel(");
|
||||
GenPrintLabel(IdentTable + val);
|
||||
printf2(")($28)");
|
||||
}
|
||||
else
|
||||
// fallthrough
|
||||
#endif
|
||||
{
|
||||
printf2("%%lo(");
|
||||
GenPrintLabel(IdentTable + val);
|
||||
printf2(")($1)");
|
||||
}
|
||||
case MipsOpLabelLo:
|
||||
printf2("%%lo(");
|
||||
GenPrintLabel(IdentTable + val);
|
||||
printf2(")($1)");
|
||||
break;
|
||||
case MipsOpLabel: GenPrintLabel(IdentTable + val); break;
|
||||
case MipsOpNumLabel: GenPrintNumLabel(val); break;
|
||||
@@ -427,62 +402,11 @@ void GenPrintInstr3Operands(int instr, int instrval,
|
||||
int operand2, int operand2val,
|
||||
int operand3, int operand3val)
|
||||
{
|
||||
#ifdef INSTR_IMM_WORKAROUND
|
||||
int useAt = 0;
|
||||
#endif
|
||||
|
||||
if (operand3 == MipsOpConst && operand3val == 0 &&
|
||||
(instr == MipsInstrAddU || instr == MipsInstrSubU) &&
|
||||
operand1 == operand2)
|
||||
return;
|
||||
|
||||
#ifdef INSTR_IMM_WORKAROUND
|
||||
if (operand3 == MipsOpConst)
|
||||
{
|
||||
unsigned imm = truncUint(operand3val);
|
||||
|
||||
switch (instr)
|
||||
{
|
||||
// signed imm16:
|
||||
// addi[u], subi[u], slti[u]
|
||||
case MipsInstrAddU:
|
||||
case MipsInstrSLT:
|
||||
case MipsInstrSLTU:
|
||||
if (imm > 0x7FFF && imm < 0xFFFF8000) // if not (-0x8000 <= imm <= 0x7FFF)
|
||||
useAt = 1;
|
||||
break;
|
||||
case MipsInstrSubU:
|
||||
// subi[u] will be transformed into addi[u] and the immediate will be negated,
|
||||
// hence the immediate range is shifted by 1
|
||||
if (imm > 0x8000 && imm < 0xFFFF8001) // if not (-0x7FFF <= imm <= 0x8000)
|
||||
useAt = 1;
|
||||
break;
|
||||
|
||||
// unsigned imm16:
|
||||
// andi, ori, xori
|
||||
case MipsInstrAnd:
|
||||
case MipsInstrOr:
|
||||
case MipsInstrXor:
|
||||
if (imm > 0xFFFF)
|
||||
useAt = 1;
|
||||
break;
|
||||
|
||||
// also: various trap instructions
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (useAt)
|
||||
{
|
||||
puts2("\t.set\tnoat");
|
||||
GenPrintInstr2Operands(MipsInstrLI, 0,
|
||||
MipsOpRegAt, 0,
|
||||
MipsOpConst, operand3val);
|
||||
operand3 = MipsOpRegAt;
|
||||
}
|
||||
#endif
|
||||
|
||||
GenPrintInstr(instr, instrval);
|
||||
GenPrintOperand(operand1, operand1val);
|
||||
GenPrintOperandSeparator();
|
||||
@@ -491,13 +415,6 @@ void GenPrintInstr3Operands(int instr, int instrval,
|
||||
GenPrintOperand(operand3, operand3val);
|
||||
GenPrintNewLine();
|
||||
|
||||
#ifdef INSTR_IMM_WORKAROUND
|
||||
if (useAt)
|
||||
{
|
||||
puts2("\t.set\tat");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef REORDER_WORKAROUND
|
||||
if (instr == MipsInstrBEQ || instr == MipsInstrBNE)
|
||||
GenNop();
|
||||
@@ -749,10 +666,6 @@ int GenGetBinaryOperatorInstr(int tok)
|
||||
STATIC
|
||||
void GenPreIdentAccess(int label)
|
||||
{
|
||||
#ifdef ALLOW_GP
|
||||
if (UseGp)
|
||||
return;
|
||||
#endif
|
||||
printf2("\t.set\tnoat\n\tlui\t$1, %%hi(");
|
||||
GenPrintLabel(IdentTable + label);
|
||||
puts2(")");
|
||||
@@ -761,10 +674,6 @@ void GenPreIdentAccess(int label)
|
||||
STATIC
|
||||
void GenPostIdentAccess(void)
|
||||
{
|
||||
#ifdef ALLOW_GP
|
||||
if (UseGp)
|
||||
return;
|
||||
#endif
|
||||
puts2("\t.set\tat");
|
||||
}
|
||||
|
||||
@@ -791,7 +700,7 @@ void GenReadIdent(int regDst, int opSz, int label)
|
||||
}
|
||||
GenPrintInstr2Operands(instr, 0,
|
||||
regDst, 0,
|
||||
MipsOpLabelGpOption, label);
|
||||
MipsOpLabelLo, label);
|
||||
GenPostIdentAccess();
|
||||
}
|
||||
|
||||
@@ -860,7 +769,7 @@ void GenWriteIdent(int regSrc, int opSz, int label)
|
||||
}
|
||||
GenPrintInstr2Operands(instr, 0,
|
||||
regSrc, 0,
|
||||
MipsOpLabelGpOption, label);
|
||||
MipsOpLabelLo, label);
|
||||
GenPostIdentAccess();
|
||||
}
|
||||
|
||||
@@ -1160,7 +1069,7 @@ void GenPrep(int* idx)
|
||||
{
|
||||
if (tok == tokUMod || tok == tokAssignUMod)
|
||||
{
|
||||
stack[oldIdxRight][1] = uint2int(m - 1);
|
||||
stack[oldIdxRight][1] = (int)(m - 1);
|
||||
tok = (tok == tokUMod) ? '&' : tokAssignAnd;
|
||||
}
|
||||
else
|
||||
@@ -2215,103 +2124,36 @@ void GenExpr0(void)
|
||||
}
|
||||
|
||||
STATIC
|
||||
unsigned GenStrData(int generatingCode, unsigned requiredLen)
|
||||
void GenDumpChar(int ch)
|
||||
{
|
||||
int i;
|
||||
unsigned total = 0;
|
||||
|
||||
// insert string literals into the code
|
||||
for (i = 0; i < sp; i++)
|
||||
if (ch < 0)
|
||||
{
|
||||
int tok = stack[i][0];
|
||||
char* p = IdentTable + stack[i][1];
|
||||
if (tok == tokIdent && isdigit(*p))
|
||||
{
|
||||
int label = atoi(p);
|
||||
unsigned len;
|
||||
|
||||
p = FindString(label);
|
||||
len = *p++ & 0xFF;
|
||||
|
||||
// If this is a string literal initializing an array of char,
|
||||
// truncate or pad it as necessary.
|
||||
if (requiredLen)
|
||||
{
|
||||
if (len >= requiredLen)
|
||||
{
|
||||
len = requiredLen; // copy count
|
||||
requiredLen = 0; // count to be zeroed out
|
||||
}
|
||||
else
|
||||
{
|
||||
requiredLen -= len; // count to be zeroed out
|
||||
}
|
||||
}
|
||||
// Also, calculate its real size for incompletely typed arrays.
|
||||
total = len + requiredLen;
|
||||
|
||||
if (generatingCode)
|
||||
{
|
||||
if (OutputFormat == FormatFlat)
|
||||
{
|
||||
GenJumpUncond(label + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts2(CodeFooter);
|
||||
puts2(DataHeader);
|
||||
}
|
||||
}
|
||||
|
||||
GenNumLabel(label);
|
||||
|
||||
GenStartAsciiString();
|
||||
printf2("\"");
|
||||
while (len--)
|
||||
{
|
||||
// quote ASCII chars for better readability
|
||||
if (*p >= 0x20 && *p <= 0x7E)
|
||||
{
|
||||
if (*p == '\"' || *p == '\\')
|
||||
printf2("\\");
|
||||
printf2("%c", *p);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf2("\\%03o", *p & 0xFFu);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
while (requiredLen)
|
||||
{
|
||||
printf2("\\000");
|
||||
requiredLen--;
|
||||
}
|
||||
printf2("\"");
|
||||
puts2("");
|
||||
|
||||
if (generatingCode)
|
||||
{
|
||||
if (OutputFormat == FormatFlat)
|
||||
{
|
||||
GenNumLabel(label + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts2(DataFooter);
|
||||
puts2(CodeHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (TokenStringLen)
|
||||
printf2("\"\n");
|
||||
return;
|
||||
}
|
||||
|
||||
return total;
|
||||
if (TokenStringLen == 0)
|
||||
{
|
||||
GenStartAsciiString();
|
||||
printf2("\"");
|
||||
}
|
||||
|
||||
if (ch >= 0x20 && ch <= 0x7E)
|
||||
{
|
||||
if (ch == '"' || ch == '\\')
|
||||
printf2("\\");
|
||||
printf2("%c", ch);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf2("\\%03o", ch);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
void GenExpr(void)
|
||||
{
|
||||
GenStrData(1, 0);
|
||||
GenExpr0();
|
||||
}
|
||||
|
||||
@@ -2320,19 +2162,11 @@ void GenFin(void)
|
||||
{
|
||||
if (StructCpyLabel)
|
||||
{
|
||||
char s[1 + 2 + (2 + CHAR_BIT * sizeof StructCpyLabel) / 3];
|
||||
char *p = s + sizeof s;
|
||||
int lbl = LabelCnt++;
|
||||
|
||||
*--p = '\0';
|
||||
p = lab2str(p, StructCpyLabel);
|
||||
*--p = '_';
|
||||
*--p = '_';
|
||||
puts2(CodeHeaderFooter[0]);
|
||||
|
||||
if (OutputFormat != FormatFlat)
|
||||
puts2(CodeHeader);
|
||||
|
||||
GenLabel(p, 1);
|
||||
GenNumLabel(StructCpyLabel);
|
||||
|
||||
puts2("\tmove\t$2, $6\n"
|
||||
"\tmove\t$3, $6");
|
||||
@@ -2352,64 +2186,6 @@ void GenFin(void)
|
||||
GenNop();
|
||||
#endif
|
||||
|
||||
if (OutputFormat != FormatFlat)
|
||||
puts2(CodeFooter);
|
||||
puts2(CodeHeaderFooter[1]);
|
||||
}
|
||||
|
||||
#ifdef USE_SWITCH_TAB
|
||||
if (SwitchJmpLabel)
|
||||
{
|
||||
char s[1 + 2 + (2 + CHAR_BIT * sizeof SwitchJmpLabel) / 3];
|
||||
char *p = s + sizeof s;
|
||||
int lbl = (LabelCnt += 3) - 3;
|
||||
|
||||
*--p = '\0';
|
||||
p = lab2str(p, SwitchJmpLabel);
|
||||
*--p = '_';
|
||||
*--p = '_';
|
||||
|
||||
if (OutputFormat != FormatFlat)
|
||||
puts2(CodeHeader);
|
||||
|
||||
GenLabel(p, 1);
|
||||
|
||||
puts2("\tlw\t$2, 0($4)\n"
|
||||
"\tlw\t$31, 4($4)");
|
||||
printf2("\tbeq\t$2, $0, "); GenPrintNumLabel(lbl + 2); // beq $2, $0, L3
|
||||
puts2("");
|
||||
#ifdef REORDER_WORKAROUND
|
||||
GenNop();
|
||||
#endif
|
||||
GenNumLabel(lbl); // L1:
|
||||
puts2("\taddiu\t$4, $4, 8\n"
|
||||
"\tlw\t$6, 0($4)");
|
||||
printf2("\tbne\t$6, $5, "); GenPrintNumLabel(lbl + 1); // bne $6, $6, L2
|
||||
puts2("");
|
||||
#ifdef REORDER_WORKAROUND
|
||||
GenNop();
|
||||
#endif
|
||||
puts2("\tlw\t$31, 4($4)");
|
||||
printf2("\tj "); GenPrintNumLabel(lbl + 2); // j L3
|
||||
puts2("");
|
||||
#ifdef REORDER_WORKAROUND
|
||||
GenNop();
|
||||
#endif
|
||||
GenNumLabel(lbl + 1); // L2:
|
||||
puts2("\taddiu\t$2, $2, -1");
|
||||
printf2("\tbne\t$2, $0, "); GenPrintNumLabel(lbl); // bne $2, $0, L1
|
||||
puts2("");
|
||||
#ifdef REORDER_WORKAROUND
|
||||
GenNop();
|
||||
#endif
|
||||
GenNumLabel(lbl + 2); // L3:
|
||||
puts2("\taddiu\t$29, $29, 16\n"
|
||||
"\tj\t$31");
|
||||
#ifdef REORDER_WORKAROUND
|
||||
GenNop();
|
||||
#endif
|
||||
|
||||
if (OutputFormat != FormatFlat)
|
||||
puts2(CodeFooter);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ void GenAddGlobal(char* s, int use)
|
||||
{
|
||||
int i = 0;
|
||||
int l;
|
||||
if (OutputFormat != FormatFlat && GenExterns)
|
||||
if (GenExterns)
|
||||
{
|
||||
while (i < GlobalsTableLen)
|
||||
{
|
||||
@@ -86,7 +86,7 @@ void GenInit(void)
|
||||
{
|
||||
// initialization of target-specific code generator
|
||||
SizeOfWord = 2;
|
||||
OutputFormat = FormatSegTurbo;
|
||||
OutputFormat = FormatSegmented;
|
||||
UseLeadingUnderscores = 1;
|
||||
}
|
||||
|
||||
@@ -96,33 +96,23 @@ int GenInitParams(int argc, char** argv, int* idx)
|
||||
(void)argc;
|
||||
// initialization of target-specific code generator with parameters
|
||||
|
||||
if (!strcmp(argv[*idx], "-seg16t"))
|
||||
if (!strcmp(argv[*idx], "-nobss"))
|
||||
{
|
||||
// this is the default option for x86
|
||||
OutputFormat = FormatSegTurbo; SizeOfWord = 2;
|
||||
UseBss = 0;
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(argv[*idx], "-seg16"))
|
||||
{
|
||||
// this is the default option for x86
|
||||
OutputFormat = FormatSegmented; SizeOfWord = 2;
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(argv[*idx], "-flat16"))
|
||||
{
|
||||
OutputFormat = FormatFlat; SizeOfWord = 2;
|
||||
return 1;
|
||||
}
|
||||
#ifdef CAN_COMPILE_32BIT
|
||||
else if (!strcmp(argv[*idx], "-seg32"))
|
||||
{
|
||||
OutputFormat = FormatSegmented; SizeOfWord = 4;
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(argv[*idx], "-flat32"))
|
||||
{
|
||||
OutputFormat = FormatFlat; SizeOfWord = 4;
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(argv[*idx], "-huge"))
|
||||
{
|
||||
OutputFormat = FormatSegHuge; SizeOfWord = 4;
|
||||
@@ -144,27 +134,14 @@ void GenInitFinalize(void)
|
||||
// finalization of initialization of target-specific code generator
|
||||
|
||||
// Change the output assembly format/content according to the options
|
||||
if (OutputFormat == FormatSegTurbo)
|
||||
{
|
||||
FileHeader = "SEGMENT _TEXT PUBLIC CLASS=CODE USE16\n"
|
||||
"SEGMENT _DATA PUBLIC CLASS=DATA\n";
|
||||
CodeHeader = "SEGMENT _TEXT";
|
||||
CodeFooter = "; SEGMENT _TEXT";
|
||||
DataHeader = "SEGMENT _DATA";
|
||||
DataFooter = "; SEGMENT _DATA";
|
||||
}
|
||||
CodeHeaderFooter[0] = "section .text";
|
||||
DataHeaderFooter[0] = "section .data";
|
||||
RoDataHeaderFooter[0] = "section .rodata";
|
||||
BssHeaderFooter[0] = "section .bss";
|
||||
if (SizeOfWord == 2 || OutputFormat == FormatSegHuge)
|
||||
FileHeader = "bits 16\n";
|
||||
else
|
||||
{
|
||||
if (OutputFormat == FormatSegmented || OutputFormat == FormatSegHuge)
|
||||
{
|
||||
CodeHeader = "section .text";
|
||||
DataHeader = "section .data";
|
||||
}
|
||||
if (SizeOfWord == 2 || OutputFormat == FormatSegHuge)
|
||||
FileHeader = "bits 16\n";
|
||||
else
|
||||
FileHeader = "bits 32\n";
|
||||
}
|
||||
FileHeader = "bits 32\n";
|
||||
}
|
||||
|
||||
STATIC
|
||||
@@ -174,9 +151,9 @@ void GenStartCommentLine(void)
|
||||
}
|
||||
|
||||
STATIC
|
||||
void GenWordAlignment(void)
|
||||
void GenWordAlignment(int bss)
|
||||
{
|
||||
printf2("\talign %d\n", SizeOfWord);
|
||||
printf2(bss ? "\talignb %d\n" : "\talign %d\n", SizeOfWord);
|
||||
}
|
||||
|
||||
STATIC
|
||||
@@ -184,13 +161,13 @@ void GenLabel(char* Label, int Static)
|
||||
{
|
||||
if (UseLeadingUnderscores)
|
||||
{
|
||||
if (OutputFormat != FormatFlat && !Static && GenExterns)
|
||||
if (!Static && GenExterns)
|
||||
printf2("\tglobal\t_%s\n", Label);
|
||||
printf2("_%s:\n", Label);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (OutputFormat != FormatFlat && !Static && GenExterns)
|
||||
if (!Static && GenExterns)
|
||||
printf2("\tglobal\t$%s\n", Label);
|
||||
printf2("$%s:\n", Label);
|
||||
}
|
||||
@@ -235,9 +212,9 @@ void GenPrintNumLabel(int label)
|
||||
}
|
||||
|
||||
STATIC
|
||||
void GenZeroData(unsigned Size)
|
||||
void GenZeroData(unsigned Size, int bss)
|
||||
{
|
||||
printf2("\ttimes\t%u db 0\n", truncUint(Size));
|
||||
printf2(bss ? "\tresb\t%u\n" : "\ttimes\t%u db 0\n", truncUint(Size));
|
||||
}
|
||||
|
||||
STATIC
|
||||
@@ -269,7 +246,7 @@ void GenAddrData(int Size, char* Label, int ofs)
|
||||
{
|
||||
int lab = LabelCnt++;
|
||||
printf2("section .relod\n\tdd\t"); GenPrintNumLabel(lab); puts2("");
|
||||
puts2(DataHeader);
|
||||
puts2(DataHeaderFooter[0]);
|
||||
GenNumLabel(lab);
|
||||
}
|
||||
#endif
|
||||
@@ -641,7 +618,7 @@ void GenPrintInstr1Operand(int instr, int instrval, int operand, int operandval)
|
||||
{
|
||||
int lab = LabelCnt++;
|
||||
printf2("section .relod\n\tdd\t"); GenPrintNumLabel(lab); puts2("");
|
||||
puts2(CodeHeader);
|
||||
puts2(CodeHeaderFooter[0]);
|
||||
puts2("\tdb\t0x66, 0x68"); // push dword const
|
||||
GenNumLabel(lab);
|
||||
printf2("\tdd\t"); GenPrintLabel(IdentTable + operandval); puts2("");
|
||||
@@ -690,7 +667,7 @@ void GenPrintInstr2Operands(int instr, int instrval, int operand1, int operand1v
|
||||
{
|
||||
int lab = LabelCnt++;
|
||||
printf2("section .relod\n\tdd\t"); GenPrintNumLabel(lab); puts2("");
|
||||
puts2(CodeHeader);
|
||||
puts2(CodeHeaderFooter[0]);
|
||||
puts2("\tdb\t0x66, 0xB8"); // mov eax, const
|
||||
GenNumLabel(lab);
|
||||
printf2("\tdd\t"); GenPrintLabel(IdentTable + operand2val); puts2("");
|
||||
@@ -778,7 +755,6 @@ void GenJumpUncond(int label)
|
||||
X86OpNumLabel, label);
|
||||
}
|
||||
|
||||
#ifndef USE_SWITCH_TAB
|
||||
STATIC
|
||||
void GenJumpIfEqual(int val, int label)
|
||||
{
|
||||
@@ -788,7 +764,6 @@ void GenJumpIfEqual(int val, int label)
|
||||
GenPrintInstr1Operand(X86InstrJcc, tokEQ,
|
||||
X86OpNumLabel, label);
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC
|
||||
void GenJumpIfZero(int label)
|
||||
@@ -839,21 +814,14 @@ void GenGrowStack(int size)
|
||||
{
|
||||
// When targeting Windows, call equivalent of _chkstk() to
|
||||
// correctly grow the stack page by page by probing it
|
||||
char s[1 + 2 + (2 + CHAR_BIT * sizeof WinChkStkLabel) / 3];
|
||||
char *p = s + sizeof s;
|
||||
|
||||
if (!WinChkStkLabel)
|
||||
WinChkStkLabel = LabelCnt++;
|
||||
|
||||
GenPrintInstr2Operands(X86InstrMov, 0,
|
||||
X86OpRegAWord, 0,
|
||||
X86OpConst, size);
|
||||
*--p = '\0';
|
||||
p = lab2str(p, WinChkStkLabel);
|
||||
*--p = '_';
|
||||
*--p = '_';
|
||||
printf2("\tcall\t");
|
||||
GenPrintLabel(p);
|
||||
GenPrintNumLabel(WinChkStkLabel); // TBD??? use dedicated instr/op fxn???
|
||||
puts2("");
|
||||
}
|
||||
#endif
|
||||
@@ -2642,7 +2610,7 @@ void GenExpr1(void)
|
||||
int lab = LabelCnt++;
|
||||
puts2("\tdb\t0x9A"); // call far seg:ofs
|
||||
printf2("section .relot\n\tdd\t"); GenPrintNumLabel(lab); puts2("");
|
||||
puts2(CodeHeader);
|
||||
puts2(CodeHeaderFooter[0]);
|
||||
GenNumLabel(lab);
|
||||
printf2("\tdd\t"); GenPrintLabel(IdentTable + stack[i - 1][1]); puts2("");
|
||||
}
|
||||
@@ -2659,7 +2627,7 @@ void GenExpr1(void)
|
||||
int lab = (LabelCnt += 3) - 3;
|
||||
puts2("\tdb\t0x9A"); // call far seg:ofs (only to generate return address)
|
||||
printf2("section .relot\n\tdd\t"); GenPrintNumLabel(lab); puts2("");
|
||||
puts2(CodeHeader);
|
||||
puts2(CodeHeaderFooter[0]);
|
||||
GenNumLabel(lab);
|
||||
printf2("\tdd\t"); GenPrintNumLabel(lab + 1); puts2("");
|
||||
GenNumLabel(lab + 1);
|
||||
@@ -2764,7 +2732,7 @@ void GenExpr0(void)
|
||||
int lab = (LabelCnt += 3) - 3;
|
||||
puts2("\tdb\t0x9A"); // call far seg:ofs (only to generate return address)
|
||||
printf2("section .relot\n\tdd\t"); GenPrintNumLabel(lab); puts2("");
|
||||
puts2(CodeHeader);
|
||||
puts2(CodeHeaderFooter[0]);
|
||||
GenNumLabel(lab);
|
||||
printf2("\tdd\t"); GenPrintNumLabel(lab + 1); puts2("");
|
||||
GenNumLabel(lab + 1);
|
||||
@@ -2995,13 +2963,17 @@ void GenExpr0(void)
|
||||
GenPrintInstr2Operands(X86InstrMov, 0,
|
||||
X86OpRegCWord, 0,
|
||||
X86OpRegAWord, 0);
|
||||
GenPrintInstr2Operands(instr, 0,
|
||||
GenSelectByteOrWord(X86OpIndRegBExplicitByteOrWord, v), 0,
|
||||
X86OpRegCByte, 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;
|
||||
|
||||
@@ -3066,6 +3038,18 @@ void GenExpr0(void)
|
||||
X86OpRegAWord, 0,
|
||||
X86OpConst, 0xFF);
|
||||
break;
|
||||
#ifdef CAN_COMPILE_32BIT
|
||||
case tokShort:
|
||||
GenPrintInstr2Operands(X86InstrMovSx, 0,
|
||||
X86OpRegAWord, 0,
|
||||
X86OpRegAHalfWord, 0);
|
||||
break;
|
||||
case tokUShort:
|
||||
GenPrintInstr2Operands(X86InstrMovZx, 0,
|
||||
X86OpRegAWord, 0,
|
||||
X86OpRegAHalfWord, 0);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case tokShortCirc:
|
||||
#ifndef NO_ANNOTATIONS
|
||||
@@ -3118,126 +3102,60 @@ void GenExpr0(void)
|
||||
#endif // #ifndef CG_STACK_BASED
|
||||
|
||||
STATIC
|
||||
unsigned GenStrData(int generatingCode, unsigned requiredLen)
|
||||
void GenDumpChar(int ch)
|
||||
{
|
||||
int i;
|
||||
unsigned total = 0;
|
||||
static int quot = 0;
|
||||
|
||||
// insert string literals into the code
|
||||
for (i = 0; i < sp; i++)
|
||||
if (ch < 0)
|
||||
{
|
||||
int tok = stack[i][0];
|
||||
char* p = IdentTable + stack[i][1];
|
||||
if (tok == tokIdent && isdigit(*p))
|
||||
if (quot)
|
||||
{
|
||||
int label = atoi(p);
|
||||
int quot = 0;
|
||||
unsigned len;
|
||||
|
||||
p = FindString(label);
|
||||
len = *p++ & 0xFF;
|
||||
|
||||
// If this is a string literal initializing an array of char,
|
||||
// truncate or pad it as necessary.
|
||||
if (requiredLen)
|
||||
{
|
||||
if (len >= requiredLen)
|
||||
{
|
||||
len = requiredLen; // copy count
|
||||
requiredLen = 0; // count to be zeroed out
|
||||
}
|
||||
else
|
||||
{
|
||||
requiredLen -= len; // count to be zeroed out
|
||||
}
|
||||
}
|
||||
// Also, calculate its real size for incompletely typed arrays.
|
||||
total = len + requiredLen;
|
||||
|
||||
if (generatingCode)
|
||||
{
|
||||
if (OutputFormat == FormatFlat)
|
||||
{
|
||||
GenJumpUncond(label + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts2(CodeFooter);
|
||||
puts2(DataHeader);
|
||||
}
|
||||
}
|
||||
|
||||
GenNumLabel(label);
|
||||
|
||||
GenStartAsciiString();
|
||||
while (len--)
|
||||
{
|
||||
// quote ASCII chars for better readability
|
||||
if (*p >= 0x20 && *p <= 0x7E && *p != '\"')
|
||||
{
|
||||
if (!quot)
|
||||
{
|
||||
quot = 1;
|
||||
printf2("\"");
|
||||
}
|
||||
printf2("%c", *p);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (quot)
|
||||
{
|
||||
quot = 0;
|
||||
printf2("\",");
|
||||
}
|
||||
printf2("%u", *p & 0xFFu);
|
||||
if (len || requiredLen)
|
||||
printf2(",");
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (quot)
|
||||
{
|
||||
printf2("\"");
|
||||
if (requiredLen)
|
||||
printf2(",");
|
||||
}
|
||||
while (requiredLen)
|
||||
{
|
||||
printf2("0");
|
||||
if (--requiredLen)
|
||||
printf2(",");
|
||||
}
|
||||
puts2("");
|
||||
|
||||
if (generatingCode)
|
||||
{
|
||||
if (OutputFormat == FormatFlat)
|
||||
{
|
||||
GenNumLabel(label + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
puts2(DataFooter);
|
||||
puts2(CodeHeader);
|
||||
}
|
||||
}
|
||||
printf2("\"");
|
||||
quot = 0;
|
||||
}
|
||||
if (TokenStringLen)
|
||||
printf2("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
return total;
|
||||
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 (OutputFormat != FormatFlat && GenExterns)
|
||||
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);
|
||||
}
|
||||
GenStrData(1, 0);
|
||||
#ifndef CG_STACK_BASED
|
||||
GenExpr1();
|
||||
#else
|
||||
@@ -3250,18 +3168,9 @@ void GenFin(void)
|
||||
{
|
||||
if (StructCpyLabel)
|
||||
{
|
||||
char s[1 + 2 + (2 + CHAR_BIT * sizeof StructCpyLabel) / 3];
|
||||
char *p = s + sizeof s;
|
||||
puts2(CodeHeaderFooter[0]);
|
||||
|
||||
*--p = '\0';
|
||||
p = lab2str(p, StructCpyLabel);
|
||||
*--p = '_';
|
||||
*--p = '_';
|
||||
|
||||
if (OutputFormat != FormatFlat)
|
||||
puts2(CodeHeader);
|
||||
|
||||
GenLabel(p, 1);
|
||||
GenNumLabel(StructCpyLabel);
|
||||
GenFxnProlog();
|
||||
|
||||
if (SizeOfWord == 2)
|
||||
@@ -3330,25 +3239,15 @@ void GenFin(void)
|
||||
|
||||
GenFxnEpilog();
|
||||
|
||||
if (OutputFormat != FormatFlat)
|
||||
puts2(CodeFooter);
|
||||
puts2(CodeHeaderFooter[1]);
|
||||
}
|
||||
|
||||
#ifndef NO_STRUCT_BY_VAL
|
||||
if (StructPushLabel)
|
||||
{
|
||||
char s[1 + 2 + (2 + CHAR_BIT * sizeof StructPushLabel) / 3];
|
||||
char *p = s + sizeof s;
|
||||
puts2(CodeHeaderFooter[0]);
|
||||
|
||||
*--p = '\0';
|
||||
p = lab2str(p, StructPushLabel);
|
||||
*--p = '_';
|
||||
*--p = '_';
|
||||
|
||||
if (OutputFormat != FormatFlat)
|
||||
puts2(CodeHeader);
|
||||
|
||||
GenLabel(p, 1);
|
||||
GenNumLabel(StructPushLabel);
|
||||
GenFxnProlog();
|
||||
|
||||
if (SizeOfWord == 2)
|
||||
@@ -3432,115 +3331,7 @@ void GenFin(void)
|
||||
|
||||
// GenFxnEpilog();
|
||||
|
||||
if (OutputFormat != FormatFlat)
|
||||
puts2(CodeFooter);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SWITCH_TAB
|
||||
if (SwitchJmpLabel)
|
||||
{
|
||||
char s[1 + 2 + (2 + CHAR_BIT * sizeof SwitchJmpLabel) / 3];
|
||||
char *p = s + sizeof s;
|
||||
|
||||
*--p = '\0';
|
||||
p = lab2str(p, SwitchJmpLabel);
|
||||
*--p = '_';
|
||||
*--p = '_';
|
||||
|
||||
if (OutputFormat != FormatFlat)
|
||||
puts2(CodeHeader);
|
||||
|
||||
GenLabel(p, 1);
|
||||
GenFxnProlog();
|
||||
|
||||
if (SizeOfWord == 2)
|
||||
{
|
||||
int lbl = (LabelCnt += 3) - 3;
|
||||
puts2("\tmov\tbx, [bp + 4]\n"
|
||||
"\tmov\tsi, [bx + 2]\n"
|
||||
"\tmov\tcx, [bx]");
|
||||
printf2("\tjcxz\t"); GenPrintNumLabel(lbl + 2); // jcxz L3
|
||||
puts2("\n\tmov\tax, [bp + 6]");
|
||||
GenNumLabel(lbl); // L1:
|
||||
puts2("\tadd\tbx, 4\n"
|
||||
"\tcmp\tax, [bx]");
|
||||
printf2("\tjne\t"); GenPrintNumLabel(lbl + 1); // jne L2
|
||||
puts2("\n\tmov\tsi, [bx + 2]");
|
||||
printf2("\tjmp\t"); GenPrintNumLabel(lbl + 2); // jmp L3
|
||||
puts2("");
|
||||
GenNumLabel(lbl + 1); // L2:
|
||||
printf2("\tloop\t"); GenPrintNumLabel(lbl); // loop L1
|
||||
puts2("");
|
||||
GenNumLabel(lbl + 2); // L3:
|
||||
puts2("\tmov\t[bp + 2], si\n"
|
||||
"\tleave\n"
|
||||
"\tret\t4");
|
||||
}
|
||||
#ifdef CAN_COMPILE_32BIT
|
||||
else if (OutputFormat != FormatSegHuge)
|
||||
{
|
||||
int lbl = (LabelCnt += 3) - 3;
|
||||
puts2("\tmov\tebx, [ebp + 8]\n"
|
||||
"\tmov\tesi, [ebx + 4]\n"
|
||||
"\tmov\tecx, [ebx]");
|
||||
printf2("\tjecxz\t"); GenPrintNumLabel(lbl + 2); // jecxz L3
|
||||
puts2("\n\tmov\teax, [ebp + 12]");
|
||||
GenNumLabel(lbl); // L1:
|
||||
puts2("\tadd\tebx, 8\n"
|
||||
"\tcmp\teax, [ebx]");
|
||||
printf2("\tjne\t"); GenPrintNumLabel(lbl + 1); // jne L2
|
||||
puts2("\n\tmov\tesi, [ebx + 4]");
|
||||
printf2("\tjmp\t"); GenPrintNumLabel(lbl + 2); // jmp L3
|
||||
puts2("");
|
||||
GenNumLabel(lbl + 1); // L2:
|
||||
printf2("\tloop\t"); GenPrintNumLabel(lbl); // loop L1
|
||||
puts2("");
|
||||
GenNumLabel(lbl + 2); // L3:
|
||||
puts2("\tmov\t[ebp + 4], esi\n"
|
||||
"\tleave\n"
|
||||
"\tret\t8");
|
||||
}
|
||||
else
|
||||
{
|
||||
int lbl = (LabelCnt += 3) - 3;
|
||||
puts2("\tmov\tebx, [bp + 8]\n"
|
||||
"\tror\tebx, 4\n"
|
||||
"\tmov\tds, ebx\n"
|
||||
"\tshr\tebx, 28\n"
|
||||
"\tmov\tsi, [bx + 4]\n"
|
||||
"\tmov\tcx, [bx]"); // use only 16 bits of case counter
|
||||
printf2("\tjcxz\t"); GenPrintNumLabel(lbl + 2); // jcxz L3
|
||||
puts2("\n\tmov\teax, [bp + 12]");
|
||||
GenNumLabel(lbl); // L1:
|
||||
// No segment reload inside the loop, hence the number of cases is limited to ~8190
|
||||
puts2("\tadd\tbx, 8\n"
|
||||
"\tcmp\teax, [bx]");
|
||||
printf2("\tjne\t"); GenPrintNumLabel(lbl + 1); // jne L2
|
||||
puts2("\n\tmov\tsi, [bx + 4]");
|
||||
printf2("\tjmp\t"); GenPrintNumLabel(lbl + 2); // jmp L3
|
||||
puts2("");
|
||||
GenNumLabel(lbl + 1); // L2:
|
||||
printf2("\tloop\t"); GenPrintNumLabel(lbl); // loop L1
|
||||
puts2("");
|
||||
GenNumLabel(lbl + 2); // L3:
|
||||
// Preserve CS on return
|
||||
puts2("\tmov\tax, [bp + 6]\n"
|
||||
"\tshl\tax, 4\n"
|
||||
"\tsub\tsi, ax\n"
|
||||
"\tmov\t[bp + 4], si\n"
|
||||
"\tdb\t0x66\n"
|
||||
"\tleave\n"
|
||||
"\tretf\t8");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Not using GenFxnEpilog() here because we need to remove the parameters
|
||||
// from the stack
|
||||
// GenFxnEpilog();
|
||||
|
||||
if (OutputFormat != FormatFlat)
|
||||
puts2(CodeFooter);
|
||||
puts2(CodeHeaderFooter[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -3549,19 +3340,11 @@ void GenFin(void)
|
||||
{
|
||||
// When targeting Windows, simulate _chkstk() to
|
||||
// correctly grow the stack page by page by probing it
|
||||
char s[1 + 2 + (2 + CHAR_BIT * sizeof WinChkStkLabel) / 3];
|
||||
char *p = s + sizeof s;
|
||||
int lbl = LabelCnt++;
|
||||
|
||||
*--p = '\0';
|
||||
p = lab2str(p, WinChkStkLabel);
|
||||
*--p = '_';
|
||||
*--p = '_';
|
||||
puts2(CodeHeaderFooter[0]);
|
||||
|
||||
if (OutputFormat != FormatFlat)
|
||||
puts2(CodeHeader);
|
||||
|
||||
GenLabel(p, 1);
|
||||
GenNumLabel(WinChkStkLabel);
|
||||
puts2("\tlea\tebx, [esp+4]\n"
|
||||
"\tmov\tecx, ebx\n"
|
||||
"\tsub\tecx, eax\n"
|
||||
@@ -3574,12 +3357,11 @@ void GenFin(void)
|
||||
printf2("\tjne\t"); GenPrintNumLabel(lbl); // jne L1
|
||||
puts2("\n\tret");
|
||||
|
||||
if (OutputFormat != FormatFlat)
|
||||
puts2(CodeFooter);
|
||||
puts2(CodeHeaderFooter[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (OutputFormat != FormatFlat && GenExterns)
|
||||
if (GenExterns)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user