mirror of
https://github.com/cc65/cc65.git
synced 2024-12-23 19:29:37 +00:00
Polishing and minor corrections
git-svn-id: svn://svn.cc65.org/cc65/trunk@741 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
0e80187cec
commit
12ec031f9a
@ -86,23 +86,29 @@ static const FuncInfo FuncInfoTable[] = {
|
||||
{ "decax7", REG_AX, REG_AX },
|
||||
{ "decax8", REG_AX, REG_AX },
|
||||
{ "decaxy", REG_AXY, REG_AX },
|
||||
{ "decsp2", REG_NONE, REG_A },
|
||||
{ "decsp3", REG_NONE, REG_A },
|
||||
{ "decsp4", REG_NONE, REG_A },
|
||||
{ "decsp5", REG_NONE, REG_A },
|
||||
{ "decsp6", REG_NONE, REG_A },
|
||||
{ "decsp7", REG_NONE, REG_A },
|
||||
{ "decsp8", REG_NONE, REG_A },
|
||||
{ "decsp1", REG_NONE, REG_Y },
|
||||
{ "decsp2", REG_NONE, REG_A },
|
||||
{ "decsp3", REG_NONE, REG_A },
|
||||
{ "decsp4", REG_NONE, REG_A },
|
||||
{ "decsp5", REG_NONE, REG_A },
|
||||
{ "decsp6", REG_NONE, REG_A },
|
||||
{ "decsp7", REG_NONE, REG_A },
|
||||
{ "decsp8", REG_NONE, REG_A },
|
||||
{ "incsp1", REG_NONE, REG_NONE },
|
||||
{ "incsp2", REG_NONE, REG_Y },
|
||||
{ "incsp3", REG_NONE, REG_Y },
|
||||
{ "incsp4", REG_NONE, REG_Y },
|
||||
{ "incsp5", REG_NONE, REG_Y },
|
||||
{ "incsp6", REG_NONE, REG_Y },
|
||||
{ "incsp7", REG_NONE, REG_Y },
|
||||
{ "incsp8", REG_NONE, REG_Y },
|
||||
{ "incsp2", REG_NONE, REG_Y },
|
||||
{ "incsp3", REG_NONE, REG_Y },
|
||||
{ "incsp4", REG_NONE, REG_Y },
|
||||
{ "incsp5", REG_NONE, REG_Y },
|
||||
{ "incsp6", REG_NONE, REG_Y },
|
||||
{ "incsp7", REG_NONE, REG_Y },
|
||||
{ "incsp8", REG_NONE, REG_Y },
|
||||
{ "ldaui", REG_AX, REG_AXY },
|
||||
{ "ldauidx", REG_AXY, REG_AX },
|
||||
{ "ldax0sp", REG_Y, REG_AX },
|
||||
{ "ldaxi", REG_AX, REG_AXY },
|
||||
{ "ldaxidx", REG_AXY, REG_AX },
|
||||
{ "ldaxysp", REG_Y, REG_AX },
|
||||
{ "leaasp", REG_A, REG_AX },
|
||||
{ "pusha", REG_A, REG_Y },
|
||||
{ "pusha0", REG_A, REG_XY },
|
||||
{ "pushax", REG_AX, REG_Y },
|
||||
@ -157,11 +163,11 @@ void GetFuncInfo (const char* Name, unsigned char* Use, unsigned char* Chg)
|
||||
if (Name[0] == '_') {
|
||||
|
||||
/* Search in the symbol table, skip the leading underscore */
|
||||
SymEntry* E = FindSym (Name+1);
|
||||
SymEntry* E = FindGlobalSym (Name+1);
|
||||
|
||||
/* Did we find it in the top level table? */
|
||||
if (E && E->Owner->PrevTab == 0 && IsTypeFunc (E->Type)) {
|
||||
|
||||
if (E && IsTypeFunc (E->Type)) {
|
||||
|
||||
/* A function may use the A or A/X registers if it is a fastcall
|
||||
* function. If it is not a fastcall function but a variadic one,
|
||||
* it will use the Y register (the parameter size is passed here).
|
||||
|
@ -588,38 +588,32 @@ unsigned OptUnusedLoads (CodeSeg* S)
|
||||
/* Remove loads of registers where the value loaded is not used later. */
|
||||
{
|
||||
unsigned Changes = 0;
|
||||
unsigned I;
|
||||
|
||||
/* Get the number of entries, bail out if we have not enough */
|
||||
unsigned Count = GetCodeEntryCount (S);
|
||||
if (Count < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Walk over the entries */
|
||||
I = 0;
|
||||
while (I < Count-1) {
|
||||
unsigned I = 0;
|
||||
while (I < GetCodeEntryCount (S)) {
|
||||
|
||||
CodeEntry* N;
|
||||
|
||||
/* Get next entry */
|
||||
CodeEntry* E = GetCodeEntry (S, I);
|
||||
|
||||
/* Check if it's a register load */
|
||||
if ((E->Info & OF_LOAD) != 0) {
|
||||
/* Check if it's a register load or transfer insn */
|
||||
if ((E->Info & (OF_LOAD | OF_XFR)) != 0 &&
|
||||
(N = GetNextCodeEntry (S, I)) != 0 &&
|
||||
(N->Info & OF_FBRA) == 0) {
|
||||
|
||||
unsigned char R;
|
||||
|
||||
/* Get the next instruction, it must not be a conditional branch */
|
||||
CodeEntry* N = GetCodeEntry (S, I+1);
|
||||
if ((N->Info & OF_CBRA) != 0) {
|
||||
goto NextEntry;
|
||||
}
|
||||
|
||||
/* Check which sort of load it is */
|
||||
/* Check which sort of load or transfer it is */
|
||||
unsigned R;
|
||||
switch (E->OPC) {
|
||||
case OPC_TXA:
|
||||
case OPC_TYA:
|
||||
case OPC_LDA: R = REG_A; break;
|
||||
case OPC_TAX:
|
||||
case OPC_LDX: R = REG_X; break;
|
||||
case OPC_TAY:
|
||||
case OPC_LDY: R = REG_Y; break;
|
||||
default: goto NextEntry; /* OOPS */
|
||||
default: goto NextEntry; /* OOPS */
|
||||
}
|
||||
|
||||
/* Get register usage and check if the register value is used later */
|
||||
@ -627,7 +621,6 @@ unsigned OptUnusedLoads (CodeSeg* S)
|
||||
|
||||
/* Register value is not used, remove the load */
|
||||
DelCodeEntry (S, I);
|
||||
--Count;
|
||||
|
||||
/* Remember, we had changes */
|
||||
++Changes;
|
||||
|
@ -121,14 +121,14 @@ const OPCDesc OPCTable[OPC_COUNT] = {
|
||||
{ OPC_STA, "sta", 0, REG_A, REG_NONE, OF_NONE },
|
||||
{ OPC_STX, "stx", 0, REG_X, REG_NONE, OF_NONE },
|
||||
{ OPC_STY, "sty", 0, REG_Y, REG_NONE, OF_NONE },
|
||||
{ OPC_TAX, "tax", 1, REG_A, REG_X, OF_NONE },
|
||||
{ OPC_TAY, "tay", 1, REG_A, REG_Y, OF_NONE },
|
||||
{ OPC_TAX, "tax", 1, REG_A, REG_X, OF_XFR },
|
||||
{ OPC_TAY, "tay", 1, REG_A, REG_Y, OF_XFR },
|
||||
{ OPC_TRB, "trb", 0, REG_A, REG_NONE, OF_NONE },
|
||||
{ OPC_TSB, "tsb", 0, REG_A, REG_NONE, OF_NONE },
|
||||
{ OPC_TSX, "tsx", 1, REG_NONE, REG_X, OF_NONE },
|
||||
{ OPC_TXA, "txa", 1, REG_X, REG_A, OF_NONE },
|
||||
{ OPC_TXS, "txs", 1, REG_X, REG_NONE, OF_NONE },
|
||||
{ OPC_TYA, "tya", 1, REG_A, REG_A, OF_NONE },
|
||||
{ OPC_TSX, "tsx", 1, REG_NONE, REG_X, OF_XFR },
|
||||
{ OPC_TXA, "txa", 1, REG_X, REG_A, OF_XFR },
|
||||
{ OPC_TXS, "txs", 1, REG_X, REG_NONE, OF_XFR },
|
||||
{ OPC_TYA, "tya", 1, REG_A, REG_A, OF_XFR },
|
||||
};
|
||||
|
||||
|
||||
|
@ -162,9 +162,10 @@ typedef enum {
|
||||
#define OF_CBRA 0x0002U /* Conditional branch */
|
||||
#define OF_ZBRA 0x0004U /* Branch on zero flag condition */
|
||||
#define OF_FBRA 0x0008U /* Branch on cond set by a load */
|
||||
#define OF_LBRA 0x0010U /* Jump/branch is long */
|
||||
#define OF_LBRA 0x0010U /* Jump/branch is long */
|
||||
#define OF_RET 0x0020U /* Return from function */
|
||||
#define OF_LOAD 0x0040U /* Register load */
|
||||
#define OF_XFR 0x0080 /* Transfer instruction */
|
||||
#define OF_BRA (OF_UBRA|OF_CBRA) /* Operation is a jump/branch */
|
||||
#define OF_DEAD (OF_UBRA|OF_RET) /* Dead end - no exec behind this point */
|
||||
|
||||
|
164
src/cc65/stmt.c
164
src/cc65/stmt.c
@ -51,8 +51,8 @@
|
||||
|
||||
|
||||
|
||||
static int doif (void)
|
||||
/* Handle 'if' statement here */
|
||||
static int DoIf (void)
|
||||
/* Handle an 'if' statement */
|
||||
{
|
||||
int flab1;
|
||||
int flab2;
|
||||
@ -108,57 +108,84 @@ static int doif (void)
|
||||
|
||||
|
||||
|
||||
static void dowhile (char wtype)
|
||||
/* Handle 'while' statement here */
|
||||
static void DoDo (void)
|
||||
/* Handle the 'do' statement */
|
||||
{
|
||||
int loop;
|
||||
int lab;
|
||||
/* Get the loop control labels */
|
||||
unsigned loop = GetLocalLabel ();
|
||||
unsigned lab = GetLocalLabel ();
|
||||
|
||||
/* Skip the while token */
|
||||
NextToken ();
|
||||
loop = GetLocalLabel ();
|
||||
lab = GetLocalLabel ();
|
||||
|
||||
/* Add the loop to the loop stack */
|
||||
AddLoop (oursp, loop, lab, 0, 0);
|
||||
|
||||
/* Define the head label */
|
||||
g_defcodelabel (loop);
|
||||
if (wtype == 'w') {
|
||||
|
||||
/* While loop */
|
||||
test (lab, 0);
|
||||
/* Parse the loop body */
|
||||
Statement ();
|
||||
|
||||
/* If the statement following the while loop is empty, that is, we have
|
||||
* something like "while (1) ;", the test function ommitted the jump as
|
||||
* an optimization. Since we know, the condition codes are set, we can
|
||||
* do another small optimization here, and use a conditional jump
|
||||
* instead an absolute one.
|
||||
*/
|
||||
if (CurTok.Tok == TOK_SEMI) {
|
||||
/* Shortcut */
|
||||
NextToken ();
|
||||
/* Use a conditional jump */
|
||||
g_truejump (CF_NONE, loop);
|
||||
} else {
|
||||
/* There is code inside the while loop */
|
||||
Statement ();
|
||||
g_jump (loop);
|
||||
g_defcodelabel (lab);
|
||||
}
|
||||
/* Parse the end condition */
|
||||
Consume (TOK_WHILE, "`while' expected");
|
||||
test (loop, 1);
|
||||
ConsumeSemi ();
|
||||
|
||||
/* Define the break label */
|
||||
g_defcodelabel (lab);
|
||||
|
||||
/* Remove the loop from the loop stack */
|
||||
DelLoop ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DoWhile (void)
|
||||
/* Handle the 'while' statement */
|
||||
{
|
||||
/* Get the loop control labels */
|
||||
unsigned loop = GetLocalLabel ();
|
||||
unsigned lab = GetLocalLabel ();
|
||||
|
||||
/* Skip the while token */
|
||||
NextToken ();
|
||||
|
||||
/* Add the loop to the loop stack */
|
||||
AddLoop (oursp, loop, lab, 0, 0);
|
||||
|
||||
/* Define the head label */
|
||||
g_defcodelabel (loop);
|
||||
|
||||
/* Test the loop condition */
|
||||
test (lab, 0);
|
||||
|
||||
/* If the statement following the while loop is empty, that is, we have
|
||||
* something like "while (1) ;", the test function ommitted the jump as
|
||||
* an optimization. Since we know, the condition codes are set, we can
|
||||
* do another small optimization here, and use a conditional jump
|
||||
* instead an absolute one.
|
||||
*/
|
||||
if (CurTok.Tok == TOK_SEMI) {
|
||||
/* Use a conditional jump */
|
||||
g_truejump (CF_NONE, loop);
|
||||
/* Shortcut */
|
||||
NextToken ();
|
||||
} else {
|
||||
|
||||
/* Do loop */
|
||||
Statement ();
|
||||
Consume (TOK_WHILE, "`while' expected");
|
||||
test (loop, 1);
|
||||
ConsumeSemi ();
|
||||
g_defcodelabel (lab);
|
||||
|
||||
/* There is code inside the while loop, parse the body */
|
||||
Statement ();
|
||||
g_jump (loop);
|
||||
g_defcodelabel (lab);
|
||||
}
|
||||
|
||||
/* Remove the loop from the loop stack */
|
||||
DelLoop ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DoReturn (void)
|
||||
/* Handle 'return' statement here */
|
||||
/* Handle the 'return' statement */
|
||||
{
|
||||
struct expent lval;
|
||||
|
||||
@ -188,8 +215,8 @@ static void DoReturn (void)
|
||||
|
||||
|
||||
|
||||
static void dobreak (void)
|
||||
/* Handle 'break' statement here */
|
||||
static void DoBreak (void)
|
||||
/* Handle the 'break' statement */
|
||||
{
|
||||
LoopDesc* L;
|
||||
|
||||
@ -215,8 +242,8 @@ static void dobreak (void)
|
||||
|
||||
|
||||
|
||||
static void docontinue (void)
|
||||
/* Handle 'continue' statement here */
|
||||
static void DoContinue (void)
|
||||
/* Handle the 'continue' statement */
|
||||
{
|
||||
LoopDesc* L;
|
||||
|
||||
@ -254,7 +281,7 @@ static void docontinue (void)
|
||||
|
||||
|
||||
|
||||
static void cascadeswitch (struct expent* eval)
|
||||
static void CascadeSwitch (struct expent* eval)
|
||||
/* Handle a switch statement for chars with a cmp cascade for the selector */
|
||||
{
|
||||
unsigned ExitLab; /* Exit label */
|
||||
@ -339,9 +366,9 @@ static void cascadeswitch (struct expent* eval)
|
||||
if (Val < -32768 || Val > 32767) {
|
||||
Error ("Range error");
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case T_UINT:
|
||||
case T_UINT:
|
||||
if (Val < 0 || Val > 65535) {
|
||||
Error ("Range error");
|
||||
}
|
||||
@ -382,9 +409,9 @@ static void cascadeswitch (struct expent* eval)
|
||||
/* Handle the pathologic case: DEFAULT followed by CASE */
|
||||
if (CurTok.Tok == TOK_CASE) {
|
||||
if (CodeLab == 0) {
|
||||
CodeLab = GetLocalLabel ();
|
||||
CodeLab = GetLocalLabel ();
|
||||
}
|
||||
g_jump (CodeLab);
|
||||
g_jump (CodeLab);
|
||||
}
|
||||
|
||||
/* Skip the colon */
|
||||
@ -432,7 +459,7 @@ static void cascadeswitch (struct expent* eval)
|
||||
|
||||
|
||||
|
||||
static void tableswitch (struct expent* eval)
|
||||
static void TableSwitch (struct expent* eval)
|
||||
/* Handle a switch statement via table based selector */
|
||||
{
|
||||
/* Entry for one case in a switch statement */
|
||||
@ -542,10 +569,10 @@ static void tableswitch (struct expent* eval)
|
||||
|
||||
|
||||
|
||||
static void doswitch (void)
|
||||
/* Handle 'switch' statement here */
|
||||
static void DoSwitch (void)
|
||||
/* Handle a 'switch' statement */
|
||||
{
|
||||
struct expent eval; /* Switch statement expression */
|
||||
struct expent eval; /* Switch statement expression */
|
||||
|
||||
/* Eat the "switch" */
|
||||
NextToken ();
|
||||
@ -560,16 +587,16 @@ static void doswitch (void)
|
||||
|
||||
/* Now decide which sort of switch we will create: */
|
||||
if (IsTypeChar (eval.e_tptr) || (CodeSizeFactor >= 200 && IsClassInt (eval.e_tptr))) {
|
||||
cascadeswitch (&eval);
|
||||
CascadeSwitch (&eval);
|
||||
} else {
|
||||
tableswitch (&eval);
|
||||
TableSwitch (&eval);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void dofor (void)
|
||||
/* Handle 'for' statement here */
|
||||
static void DoFor (void)
|
||||
/* Handle a 'for' statement */
|
||||
{
|
||||
int loop;
|
||||
int lab;
|
||||
@ -685,37 +712,37 @@ int Statement (void)
|
||||
return CompoundStatement ();
|
||||
|
||||
case TOK_IF:
|
||||
return doif ();
|
||||
return DoIf ();
|
||||
|
||||
case TOK_WHILE:
|
||||
dowhile ('w');
|
||||
break;
|
||||
DoWhile ();
|
||||
break;
|
||||
|
||||
case TOK_DO:
|
||||
dowhile ('d');
|
||||
break;
|
||||
DoDo ();
|
||||
break;
|
||||
|
||||
case TOK_SWITCH:
|
||||
doswitch ();
|
||||
break;
|
||||
DoSwitch ();
|
||||
break;
|
||||
|
||||
case TOK_RETURN:
|
||||
DoReturn ();
|
||||
ConsumeSemi ();
|
||||
return 1;
|
||||
DoReturn ();
|
||||
ConsumeSemi ();
|
||||
return 1;
|
||||
|
||||
case TOK_BREAK:
|
||||
dobreak ();
|
||||
DoBreak ();
|
||||
ConsumeSemi ();
|
||||
return 1;
|
||||
|
||||
case TOK_CONTINUE:
|
||||
docontinue ();
|
||||
DoContinue ();
|
||||
ConsumeSemi ();
|
||||
return 1;
|
||||
|
||||
case TOK_FOR:
|
||||
dofor ();
|
||||
DoFor ();
|
||||
break;
|
||||
|
||||
case TOK_GOTO:
|
||||
@ -724,7 +751,7 @@ int Statement (void)
|
||||
return 1;
|
||||
|
||||
case TOK_SEMI:
|
||||
/* ignore it. */
|
||||
/* Ignore it */
|
||||
NextToken ();
|
||||
break;
|
||||
|
||||
@ -733,6 +760,7 @@ int Statement (void)
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Actual statement */
|
||||
expression (&lval);
|
||||
ConsumeSemi ();
|
||||
}
|
||||
|
@ -441,6 +441,14 @@ SymEntry* FindSym (const char* Name)
|
||||
|
||||
|
||||
|
||||
SymEntry* FindGlobalSym (const char* Name)
|
||||
/* Find the symbol with the given name in the global symbol table only */
|
||||
{
|
||||
return FindSymInTable (SymTab0, Name, HashStr (Name));
|
||||
}
|
||||
|
||||
|
||||
|
||||
SymEntry* FindLocalSym (const char* Name)
|
||||
/* Find the symbol with the given name in the current symbol table only */
|
||||
{
|
||||
|
@ -117,6 +117,9 @@ void LeaveStructLevel (void);
|
||||
SymEntry* FindSym (const char* Name);
|
||||
/* Find the symbol with the given name */
|
||||
|
||||
SymEntry* FindGlobalSym (const char* Name);
|
||||
/* Find the symbol with the given name in the global symbol table only */
|
||||
|
||||
SymEntry* FindLocalSym (const char* Name);
|
||||
/* Find the symbol with the given name in the current symbol table only */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user