void ShortDataType::PushLiteral(std::string value) { Instruction* instruction; Parser* parser = g_app->GetParser(); // TODO: Physically truncate use min/max // Allocate register. Register reg = parser->AllocateRegister(this); // Move into register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_MOV, parser->GetCurrentToken()); instruction->AddRegisterOperand(reg); instruction->AddStringLiteralOperand(value); // Truncate. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_AND, parser->GetCurrentToken()); instruction->AddRegisterOperand(reg); instruction->AddStringLiteralOperand("0x0000FFFF"); // Push result. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_PUSH, parser->GetCurrentToken()); instruction->AddRegisterOperand(reg); // Deallocate register. parser->DeallocateRegister(reg); }
DataType* ShortDataType::OpDivide() { Instruction* instruction; Parser* parser = g_app->GetParser(); // Allocate registers. parser->SetRegisterAllocation(REG_EAX, true); parser->SetRegisterAllocation(REG_EDX, true); Register lReg = parser->AllocateRegister(this); Register rReg = parser->AllocateRegister(this); // Pop l-value into register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_POP, parser->GetCurrentToken()); instruction->AddRegisterOperand(rReg); // Pop r-value into register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_POP, parser->GetCurrentToken()); instruction->AddRegisterOperand(lReg); // Blank out high bits of EDX:EAX register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_MOV, parser->GetCurrentToken()); instruction->AddRegisterOperand(REG_EDX); instruction->AddIntLiteralOperand(0); // Move value into low bits of EDX:EAX register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_MOVZX, parser->GetCurrentToken()); instruction->AddRegisterOperand(REG_EDX); instruction->AddRegisterOperand(lReg); // Extend the sign bit from 32 to 64 bits. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_CDQ, parser->GetCurrentToken()); // Perform the divide operation. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_IDIV, parser->GetCurrentToken()); instruction->AddRegisterOperand(rReg); // Truncate. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_AND, parser->GetCurrentToken()); instruction->AddRegisterOperand(lReg); instruction->AddStringLiteralOperand("0x0000FFFF"); // Push the result into the stack. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_PUSH, parser->GetCurrentToken()); instruction->AddRegisterOperand(REG_EAX); // Deallocate registers. parser->DeallocateRegister(lReg); parser->DeallocateRegister(rReg); parser->SetRegisterAllocation(REG_EAX, false); parser->SetRegisterAllocation(REG_EDX, false); return this; }
void ShortDataType::AssignToVariable(VariableSymbol* variable) { Instruction* instruction; Parser* parser = g_app->GetParser(); // Allocate register. Register reg = parser->AllocateRegister(this); Register reg16Bit = parser->Register32BitTo16Bit(reg); Register thisReg = parser->AllocateRegister(new IntDataType()); // Pop value into a register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_POP, parser->GetCurrentToken()); instruction->AddRegisterOperand(reg); // Pop the pointer to the class off the stack. if (variable->VariableType == VT_FIELD) { instruction = new Instruction(parser->GetInstructionScope(), OPCODE_POP, parser->GetCurrentToken()); instruction->AddRegisterOperand(thisReg); } // Assign value to variable. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_MOV, parser->GetCurrentToken()); instruction->AddOperand(parser->GetVariableAccessOperand(variable, 0, thisReg)); instruction->AddRegisterOperand(reg16Bit); // Push "this" variable back into stack. if (variable->VariableType == VT_FIELD) { instruction = new Instruction(parser->GetInstructionScope(), OPCODE_PUSH, parser->GetCurrentToken()); instruction->AddRegisterOperand(thisReg); } // Deallocate register. parser->DeallocateRegister(reg); parser->DeallocateRegister(thisReg); }
void ShortDataType::PushVariableValue(VariableSymbol* variable) { Instruction* instruction; Parser* parser = g_app->GetParser(); // Allocate register. Register reg = parser->AllocateRegister(this); Register thisReg = parser->AllocateRegister(new IntDataType()); // Pop the pointer to the class off the stack. if (variable->VariableType == VT_FIELD) { instruction = new Instruction(parser->GetInstructionScope(), OPCODE_POP, parser->GetCurrentToken()); instruction->AddRegisterOperand(thisReg); } // Move into register so we can pad to 32bit. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_MOVZX, parser->GetCurrentToken()); instruction->AddRegisterOperand(reg); instruction->AddOperand(parser->GetVariableAccessOperand(variable, 0, thisReg)); // Push "this" variable back into stack. if (variable->VariableType == VT_FIELD) { instruction = new Instruction(parser->GetInstructionScope(), OPCODE_PUSH, parser->GetCurrentToken()); instruction->AddRegisterOperand(thisReg); } // Push register onto the stack. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_PUSH, parser->GetCurrentToken()); instruction->AddRegisterOperand(reg); // Deallocate register. parser->DeallocateRegister(reg); parser->DeallocateRegister(thisReg); }
DataType* ShortDataType::OpCompareNotEqual() { Instruction* instruction; Parser* parser = g_app->GetParser(); // Allocate registers. Register lReg = parser->AllocateRegister(this); Register rReg = parser->AllocateRegister(this); // Pop l-value into register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_POP, parser->GetCurrentToken()); instruction->AddRegisterOperand(rReg); // Pop r-value into register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_POP, parser->GetCurrentToken()); instruction->AddRegisterOperand(lReg); // Perform comparison. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_CMP, parser->GetCurrentToken()); instruction->AddRegisterOperand(lReg); instruction->AddRegisterOperand(rReg); // Zero out register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_MOV, parser->GetCurrentToken()); instruction->AddRegisterOperand(lReg); instruction->AddIntLiteralOperand(0); // Set register depending on condition. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_SETNE, parser->GetCurrentToken()); instruction->AddRegisterOperand(parser->Register32BitTo8Bit(lReg)); // Push the register result. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_PUSH, parser->GetCurrentToken()); instruction->AddRegisterOperand(lReg); // Deallocate registers. parser->DeallocateRegister(lReg); parser->DeallocateRegister(rReg); return new BoolDataType(); }
DataType* ShortDataType::OpMultiply() { Instruction* instruction; Parser* parser = g_app->GetParser(); // Allocate registers. Register lReg = parser->AllocateRegister(this); Register rReg = parser->AllocateRegister(this); // Pop l-value into register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_POP, parser->GetCurrentToken()); instruction->AddRegisterOperand(rReg); // Pop r-value into register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_POP, parser->GetCurrentToken()); instruction->AddRegisterOperand(lReg); // Perform multiplication. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_IMUL, parser->GetCurrentToken()); instruction->AddRegisterOperand(lReg); instruction->AddRegisterOperand(rReg); // Truncate. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_AND, parser->GetCurrentToken()); instruction->AddRegisterOperand(lReg); instruction->AddStringLiteralOperand("0x0000FFFF"); // Push the result. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_PUSH, parser->GetCurrentToken()); instruction->AddRegisterOperand(lReg); // Deallocate registers. parser->DeallocateRegister(lReg); parser->DeallocateRegister(rReg); return this; }
bool ShortDataType::CastTo(DataType* dt, bool explicitCast) { Instruction* instruction; Parser* parser = g_app->GetParser(); bool result = false; // Check we are not casting to the same thing. if (dt->GetPrimitive() == GetPrimitive()) return true; PrimitiveDataType pdt = dt->GetPrimitive(); if (pdt == PDT_CLASS && dynamic_cast<StringDataType*>(dt) != NULL) pdt = PDT_STRING; switch (pdt) { case PDT_BOOL: case PDT_BYTE: { // Allocate register. Register reg = parser->AllocateRegister(this); Register reg2Main = parser->AllocateRegister(this); Register reg2 = parser->Register32BitTo8Bit(reg2Main); // Pop value into a register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_POP, parser->GetCurrentToken()); instruction->AddRegisterOperand(reg2); // Truncate. //instruction = new Instruction(parser->GetInstructionScope(), OPCODE_AND, parser->GetCurrentToken()); //instruction->AddRegisterOperand(reg); //instruction->AddStringLiteralOperand("0x000000FF"); // Move with zero extend. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_MOVZX, parser->GetCurrentToken()); instruction->AddRegisterOperand(reg); instruction->AddRegisterOperand(reg2); // TODO: CBW, CWD // Push into stack. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_PUSH, parser->GetCurrentToken()); instruction->AddRegisterOperand(reg); // Deallocate register. parser->DeallocateRegister(reg2Main); parser->DeallocateRegister(reg); result = true; break; } case PDT_INT: { // Allocate register. Register reg = parser->AllocateRegister(this); Register reg2Main = parser->AllocateRegister(this); Register reg2 = parser->Register32BitTo8Bit(reg2Main); // Pop value into a register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_POP, parser->GetCurrentToken()); instruction->AddRegisterOperand(reg2); // Truncate. //instruction = new Instruction(parser->GetInstructionScope(), OPCODE_AND, parser->GetCurrentToken()); //instruction->AddRegisterOperand(reg); //instruction->AddStringLiteralOperand("0x000000FF"); // Move with zero extend. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_MOVZX, parser->GetCurrentToken()); instruction->AddRegisterOperand(reg); instruction->AddRegisterOperand(reg2); // Convert from word to dword. //instruction = new Instruction(parser->GetInstructionScope(), OPCODE_CWD, parser->GetCurrentToken()); // TODO: CBW, CWD // Push into stack. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_PUSH, parser->GetCurrentToken()); instruction->AddRegisterOperand(reg); // Deallocate register. parser->DeallocateRegister(reg2Main); parser->DeallocateRegister(reg); result = true; break; } case PDT_LONG: { // Allocate register. Register reg = REG_EAX; parser->SetRegisterAllocation(REG_EAX, true); parser->SetRegisterAllocation(REG_EDX, true); //Register reg = parser->AllocateRegister(dt); Register loBits = parser->Register64LoBitsTwin(reg); Register hiBits = parser->Register64HiBitsTwin(reg); // Pop value into a register. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_POP, parser->GetCurrentToken()); instruction->AddRegisterOperand(reg); // Truncate. //instruction = new Instruction(parser->GetInstructionScope(), OPCODE_AND, parser->GetCurrentToken()); //instruction->AddRegisterOperand(reg); //instruction->AddStringLiteralOperand("0x0000FFFF"); // Convert from word to dword. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_CWD, parser->GetCurrentToken()); // Convert from dword to quad. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_CDQ, parser->GetCurrentToken()); // Push hi-bits onto stack. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_PUSH, parser->GetCurrentToken()); instruction->AddRegisterOperand(hiBits); // Push lo-bits onto stack. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_PUSH, parser->GetCurrentToken()); instruction->AddRegisterOperand(loBits); // Deallocate register. parser->SetRegisterAllocation(REG_EAX, false); parser->SetRegisterAllocation(REG_EDX, false); result = true; break; } case PDT_FLOAT: { // Invoke class allocation function. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_CALL, parser->GetCurrentToken()); instruction->AddStringLiteralOperand("_icr__Int_IntToFloat"); // Cleanup Stack instruction = new Instruction(parser->GetInstructionScope(), OPCODE_ADD, parser->GetCurrentToken()); instruction->AddRegisterOperand(REG_ESP); instruction->AddIntLiteralOperand(4); // Push in the resulting value. dt->PushReturn(); result = true; break; } case PDT_DOUBLE: { // Invoke class allocation function. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_CALL, parser->GetCurrentToken()); instruction->AddStringLiteralOperand("_icr__Int_IntToDouble"); // Cleanup Stack instruction = new Instruction(parser->GetInstructionScope(), OPCODE_ADD, parser->GetCurrentToken()); instruction->AddRegisterOperand(REG_ESP); instruction->AddIntLiteralOperand(4); // Push in the resulting value. dt->PushReturn(); result = true; break; } case PDT_STRING: { // Invoke class allocation function. instruction = new Instruction(parser->GetInstructionScope(), OPCODE_CALL, parser->GetCurrentToken()); instruction->AddStringLiteralOperand("_icr__Int_IntToString"); // Cleanup Stack instruction = new Instruction(parser->GetInstructionScope(), OPCODE_ADD, parser->GetCurrentToken()); instruction->AddRegisterOperand(REG_ESP); instruction->AddIntLiteralOperand(4); // Push in the resulting value. dt->PushReturn(); result = true; break; } case PDT_VOID: break; case PDT_CLASS: { ClassDataType* classDT = (ClassDataType*)dt; result = false; break; } } // Error? Perhaps this should go in parser? if (result == false) g_app->EmitError("Unable to cast between '" + GetMnemonicForDataType(this) + "' and '" + GetMnemonicForDataType(dt) + "'.", ES_PARSER, EL_FATAL, parser->GetCurrentToken().Line, parser->GetCurrentToken().Column, parser->GetCurrentToken().Path); return result; }