void savereg() { int i; for(i = FBASE + 1; i < FMAX; i++) if(reg_map[i] == 1) { reg_map[i] = 0; asmsttemp(i); } }
/* Generate code for arithmetic expression, return a register number */ int genarith(TOKEN code) { int num, reg; float fnum; TOKEN lhs, rhs; int reg1, reg2, freg; int offs; if (DEBUGGEN) { printf("genarith\n"); dbugprinttok(code); }; //printf("tokentype: %i\n", code->tokentype); switch ( code->tokentype ) { case NUMBERTOK: switch (code->datatype) { case INTEGER: num = code->intval; reg = getreg(WORD); if ( num >= MINIMMEDIATE && num <= MAXIMMEDIATE ) asmimmed(MOVL, num, reg); break; case REAL: fnum = code->realval; reg = getreg(FLOAT); makeflit(fnum, nextlabel); asmldflit(MOVSD, nextlabel, reg); nextlabel++; break; case POINTER: num = 0; reg = getreg(WORD); asmimmed(MOVQ, num, reg); break; } break; case IDENTIFIERTOK: offs = code->symentry->offset - stkframesize; /* net offset of the var */ switch(code->datatype) { case INTEGER: reg = getreg(WORD); //printf("kind: %i\n", code->symtype->datatype->kind); if(code->symtype == NULL || code->symtype->kind == BASICTYPE) asmld(MOVL, offs, reg, code->stringval); else asmld(MOVQ, offs, reg, code->stringval); break; case REAL: reg = getreg(FLOAT); asmld(MOVSD, offs, reg, code->stringval); break; } break; case OPERATOR: if(code->whichval != FUNCALLOP && code->whichval != AREFOP) { lhs = code->operands; rhs = lhs->link; if(code->datatype == REAL) { reg1 = genarith( lhs ); if(rhs != NULL) { if(rhs->tokentype == OPERATOR && rhs->whichval == FUNCALLOP) { asmsttemp(reg1); reg_map[reg1] = 0; reg2 = genarith( rhs ); reg1 = getreg(FLOAT); asmldtemp(reg1); } else { reg2 = genarith( rhs ); } } } else { reg1 = genarith( lhs ); if(rhs != NULL) reg2 = genarith( rhs ); } } switch(code->whichval) { case PLUSOP: if(code->datatype == INTEGER) asmrr(ADDL, reg2, reg1); else asmrr(ADDSD, reg2, reg1); reg = reg1; break; case MINUSOP: if(rhs != NULL) { if(code->datatype == INTEGER) asmrr(SUBL, reg2, reg1); else asmrr(SUBSD, reg2, reg1); } else { reg2 = getreg(FLOAT); asmfneg(reg1, reg2); reg_map[reg2] = 0; } reg = reg1; break; case TIMESOP: if(code->datatype == INTEGER) asmrr(IMULL, reg2, reg1); else asmrr(MULSD, reg2, reg1); reg = reg1; break; case DIVIDEOP: if(code->datatype == INTEGER) asmrr(DIVL, reg2, reg1); else asmrr(DIVSD, reg2, reg1); reg = reg1; break; case EQOP: case NEOP: case LTOP: case LEOP: case GEOP: case GTOP: asmrr(CMPL, reg2, reg1); reg = reg1; break; case FLOATOP: freg = getreg(FLOAT); asmfloat(reg1, freg); reg_map[reg1] = 0; reg = freg; break; case FIXOP: reg2 = getreg(WORD); asmfix(reg1, reg2); reg_map[freg] = 0; reg = reg2; break; case FUNCALLOP: reg = genfun(code); break; case AREFOP: reg = genaref(code, FBASE); break; } break; case STRINGTOK: makeblit(code->stringval, nextlabel); return nextlabel++; break; }; return reg; }
/* Generate code for arithmetic expression, return a register number */ int genarith(TOKEN code) { int num1, num2, reg1, reg2, offs; TOKEN tok, lhs, rhs; SYMBOL sym, lsym, rsym; if (DEBUGGEN) { printf("genarith\n"); dbugprinttok(code); }; // This switch determines how to handle the token based on its type switch ( code->tokentype ) { case NUMBERTOK: switch (code->datatype) { case INTEGER: num1 = code->intval; reg1 = getreg(WORD); if (code->symtype != NULL) { if(code->symtype->kind == POINTERSYM) asmimmed(MOVQ, num1, reg1); } else if ( num1 >= MINIMMEDIATE && num1 <= MAXIMMEDIATE ) asmimmed(MOVL, num1, reg1); break; case REAL: reg1 = getreg(FLOAT); makeflit(code->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg1); break; } break; case IDENTIFIERTOK: reg1 = getreg(WORD); sym = code->symentry; offs = sym->offset - stkframesize; asmld(MOVQ, offs, reg1, code->stringval); break; case OPERATOR: switch(code->whichval) { case PLUSOP: lhs = code->operands; rhs = lhs->link; lsym = lhs->symentry; rsym = rhs->symentry; if(lsym != NULL & lhs->tokentype != NUMBERTOK) { switch(lsym->basicdt) { case INTEGER: reg1 = getreg(WORD); break; case REAL: reg1 = getreg(FLOAT); break; } asmldr(MOVL, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); } else { if(lhs->tokentype == OPERATOR) reg1 = genarith(lhs); else switch(lhs->datatype) { case INTEGER: reg1 = getreg(WORD); asmimmed(MOVL, lhs->intval, reg1); break; case REAL: reg1 = getreg(FLOAT); makeflit(lhs->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg1); break; } } if(rsym != NULL & rhs->tokentype != NUMBERTOK) { switch(rsym->basicdt) { case INTEGER: reg2 = getreg(WORD); break; case REAL: reg2 = getreg(FLOAT); break; } asmldr(MOVL, rsym->offset - stkframesize, RBP, reg2, rsym->namestring); } else { if(rhs->tokentype == OPERATOR) reg2 = genarith(rhs); else switch(rhs->datatype) { case INTEGER: reg2 = getreg(WORD); asmimmed(MOVL, rhs->intval, reg2); break; case REAL: reg2 = getreg(FLOAT); makeflit(rhs->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg2); break; } } if(reg1 < 8 & reg2 < 8) asmrr(ADDL, reg2, reg1); else asmrr(ADDSD, reg2, reg1); unused(reg2); break; case MINUSOP: lhs = code->operands; lsym = lhs->symentry; rhs = lhs->link; if(rhs == NULL) //if this is just a negation { if(lsym != NULL & lhs->tokentype != NUMBERTOK) { switch(lsym->basicdt) { case INTEGER: reg1 = getreg(WORD); asmldr(MOVL, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); break; case REAL: reg1 = getreg(FLOAT); reg2 = getreg(FLOAT); asmldr(MOVSD, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); asmfneg(reg1, reg2); unused(reg2); break; } } else { if(lhs->tokentype == OPERATOR) reg1 = genarith(lhs); else switch(lhs->datatype) { case INTEGER: reg1 = getreg(WORD); asmimmed(MOVL, lhs->intval, reg1); break; case REAL: reg1 = getreg(FLOAT); reg2 = getreg(FLOAT); asmldflit(MOVSD, nextlabel++, reg1); asmfneg(reg1, reg2); unused(reg2); break; } } return reg1; } rsym = rhs->symentry; if(lsym != NULL & lhs->tokentype != NUMBERTOK) { switch(lsym->basicdt) { case INTEGER: reg1 = getreg(WORD); asmldr(MOVL, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); break; case REAL: reg1 = getreg(FLOAT); asmldr(MOVSD, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); break; } } else { if(lhs->tokentype == OPERATOR) reg1 = genarith(lhs); else switch(lhs->datatype) { case INTEGER: reg1 = getreg(WORD); asmimmed(MOVL, lhs->intval, reg1); break; case REAL: reg1 = getreg(FLOAT); makeflit(lhs->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg1); break; } } if(rsym != NULL & rhs->tokentype != NUMBERTOK) { switch(rsym->basicdt) { case INTEGER: reg2 = getreg(WORD); asmldr(MOVL, rsym->offset - stkframesize, RBP, reg2, rsym->namestring); break; case REAL: reg2 = getreg(FLOAT); asmldr(MOVSD, rsym->offset - stkframesize, RBP, reg2, rsym->namestring); break; } } else { if(rhs->tokentype == OPERATOR) reg2 = genarith(rhs); else switch(rhs->datatype) { case INTEGER: reg2 = getreg(WORD); asmimmed(MOVL, rhs->intval, reg2); break; case REAL: reg2 = getreg(FLOAT); makeflit(rhs->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg2); break; } } if(reg1 < 8 & reg2 < 8) asmrr(SUBL, reg2, reg1); else asmrr(SUBSD, reg2, reg1); unused(reg2); break; case TIMESOP: lhs = code->operands; rhs = lhs->link; lsym = lhs->symentry; rsym = rhs->symentry; if(lsym != NULL & lhs->tokentype != NUMBERTOK) { switch(lsym->basicdt) { case INTEGER: reg1 = getreg(WORD); asmldr(MOVL, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); break; case REAL: reg1 = getreg(FLOAT); asmldr(MOVSD, lsym->offset - stkframesize, RBP, reg1, lsym->namestring); break; } } else { if(lhs->tokentype == OPERATOR) { reg1 = genarith(lhs); if(lhs->whichval == FUNCALLOP & rhs->whichval == FUNCALLOP) { asmsttemp(reg1); unused(reg1); } } else switch(lhs->datatype) { case INTEGER: reg1 = getreg(WORD); asmimmed(MOVL, lhs->intval, reg1); break; case REAL: reg1 = getreg(FLOAT); makeflit(lhs->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg1); break; } } if(rsym != NULL & rhs->tokentype != NUMBERTOK) { switch(rsym->basicdt) { case INTEGER: reg2 = getreg(WORD); asmldr(MOVL, rsym->offset - stkframesize, RBP, reg2, rsym->namestring); break; case REAL: reg2 = getreg(FLOAT); asmldr(MOVSD, rsym->offset - stkframesize, RBP, reg2, rsym->namestring); break; } } else { if(rhs->tokentype == OPERATOR) { reg2 = genarith(rhs); if(lhs->whichval == FUNCALLOP & rhs->whichval == FUNCALLOP) { switch(lhs->datatype) { case INTEGER: reg1 = getreg(WORD); break; case REAL: reg1 = getreg(FLOAT); break; } asmldtemp(reg1); } } else switch(rhs->datatype) { case INTEGER: reg2 = getreg(WORD); asmimmed(MOVL, rhs->intval, reg2); break; case REAL: reg2 = getreg(FLOAT); makeflit(rhs->realval, nextlabel++); asmldflit(MOVSD, nextlabel-1, reg2); break; } } if(reg1 < 8 & reg2 < 8) asmrr(IMULL, reg2, reg1); else asmrr(MULSD, reg2, reg1); unused(reg2); break; case FLOATOP: lhs = code->operands; lsym = lhs->symentry; reg1 = getreg(FLOAT); reg2 = getreg(WORD); asmldr(MOVL, lsym->offset - stkframesize, RBP, reg2, lsym->namestring); asmfloat(reg2, reg1); unused(reg2); break; case FUNCALLOP: tok = code->operands; if(tok->link != NULL) { switch(tok->link->tokentype) { case STRINGTOK: asmlitarg(nextlabel++, EDI); makeblit(tok->link->stringval, nextlabel-1); asmcall(tok->stringval); break; case OPERATOR: reg1 = genarith(tok->link); break; case NUMBERTOK: switch(tok->link->datatype) { case INTEGER: reg1 = getreg(WORD); asmimmed(MOVL,tok->link->intval,reg1); asmrr(MOVL, reg1, EDI); break; case REAL: reg1 = getreg(FLOAT); asmimmed(MOVSD,tok->link->realval,reg1); asmrr(MOVSD, reg1, EDI); break; } } } asmcall(tok->stringval); break; case FIXOP: reg1 = getreg(WORD); reg2 = genarith(code->operands); asmfix(reg2,reg1); break; case POINTEROP: lhs = code->operands; if(lhs->tokentype == OPERATOR & lhs->whichval == AREFOP) { reg1 = genarith(lhs); } else { reg1 = getreg(WORD); lsym = code->operands->symentry; asmld(MOVQ, lsym->offset - stkframesize, reg1, code->operands->stringval); } break; case AREFOP: lhs = code->operands; rhs = lhs->link; if(lhs->tokentype == OPERATOR & lhs->whichval == POINTEROP) { reg2 = genarith(lhs->operands); if(lhs->symtype != NULL) { if(lhs->symtype->basicdt == REAL) { reg1 = getreg(FLOAT); asmldr(MOVSD, rhs->intval, reg2, reg1, "^. "); unused(reg2); break; } } reg1 = getreg(WORD); asmldr(MOVQ, rhs->intval, reg2, reg1, "^. "); } unused(reg2); break; } break; }; return reg1; }