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;
}
Exemple #3
0
/* 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;
  }