void Emit1 (unsigned char OPC, ExprNode* Value) /* Emit an instruction with an one byte argument */ { long V; Fragment* F; if (IsEasyConst (Value, &V)) { /* Must be in byte range */ if (!IsByteRange (V)) { Error ("Range error (%ld not in [0..255])", V); } /* Create a literal fragment */ F = GenFragment (FRAG_LITERAL, 2); F->V.Data[0] = OPC; F->V.Data[1] = (unsigned char) V; FreeExpr (Value); } else { /* Emit the opcode */ Emit0 (OPC); /* Emit the argument as an expression */ F = GenFragment (FRAG_EXPR, 1); F->V.Expr = Value; } }
TType *TCodeGenerator::EmitExpression(void) { TType *pOperand1Type; // ptr to first operand's type TType *pOperand2Type; // ptr to second operand's type TType *pResultType; // ptr to result type TTokenCode op; // operator TInstruction jumpOpcode; // jump instruction opcode int jumpLabelIndex; // assembly jump label index //--Emit code for the first simple expression. pResultType = EmitSimpleExpression(); //--If we now see a relational operator, //--emit code for the second simple expression. if (TokenIn(token, tlRelOps)) { EmitPushOperand(pResultType); op = token; pOperand1Type = pResultType->Base(); GetToken(); pOperand2Type = EmitSimpleExpression()->Base(); //--Perform the operation, and push the resulting value //--onto the stack. if ( ((pOperand1Type == pIntegerType) && (pOperand2Type == pIntegerType)) || ((pOperand1Type == pCharType) && (pOperand2Type == pCharType)) || (pOperand1Type->form == fcEnum)) { //--integer <op> integer //--boolean <op> boolean //--char <op> char //--enum <op> enum //--Compare dx (operand 1) to ax (operand 2). Emit1(pop, Reg(dx)); Emit2(cmp, Reg(dx), Reg(ax)); } else if ((pOperand1Type == pRealType) || (pOperand2Type == pRealType)) { //--real <op> real //--real <op> integer //--integer <op> real //--Convert the integer operand to real. //--Call _FloatCompare to do the comparison, which //--returns -1 (less), 0 (equal), or +1 (greater). EmitPushOperand(pOperand2Type); EmitPromoteToReal(pOperand1Type, pOperand2Type); Emit1(call, NameLit(FLOAT_COMPARE)); Emit2(add, Reg(sp), IntegerLit(8)); Emit2(cmp, Reg(ax), IntegerLit(0)); } else { //--string <op> string //--Compare the string pointed to by si (operand 1) //--to the string pointed to by di (operand 2). Emit1(pop, Reg(di)); Emit1(pop, Reg(si)); Emit2(mov, Reg(ax), Reg(ds)); Emit2(mov, Reg(es), Reg(ax)); Emit0(cld); Emit2(mov, Reg(cx), IntegerLit(pOperand1Type->array.elmtCount)); Emit0(repe_cmpsb); } Emit2(mov, Reg(ax), IntegerLit(1)); // default: load 1 switch (op) { case tcLt: jumpOpcode = jl; break; case tcLe: jumpOpcode = jle; break; case tcEqual: jumpOpcode = je; break; case tcNe: jumpOpcode = jne; break; case tcGe: jumpOpcode = jge; break; case tcGt: jumpOpcode = jg; break; } jumpLabelIndex = ++asmLabelIndex; Emit1(jumpOpcode, Label(STMT_LABEL_PREFIX, jumpLabelIndex)); Emit2(sub, Reg(ax), Reg(ax)); // load 0 if false EmitStatementLabel(jumpLabelIndex); pResultType = pBooleanType; } return pResultType; }
void EmitPCRel (unsigned char OPC, ExprNode* Expr, unsigned Size) /* Emit an opcode with a PC relative argument of one or two bytes */ { Emit0 (OPC); EmitSigned (Expr, Size); }
void Emit3 (unsigned char OPC, ExprNode* Expr) /* Emit an instruction with a three byte argument */ { Emit0 (OPC); EmitFarAddr (Expr); }
void Emit2 (unsigned char OPC, ExprNode* Value) /* Emit an instruction with a two byte argument */ { Emit0 (OPC); EmitWord (Value); }
void Emit1 (unsigned char OPC, ExprNode* Value) /* Emit an instruction with an one byte argument */ { Emit0 (OPC); EmitByte (Value); }