TranslationTable::MachineInstructionVector TranslationTable::translateInstruction( const ir::Instruction* instruction) const { auto translation = getTranslation(instruction->opcodeString()); if(translation == nullptr) { // Fail the translation by returning nothing return MachineInstructionVector(); } return translation->translateInstruction(instruction); }
/* Function that translates every code and data segment. * This function returns ASM_OK if everything went good */ int translateCode(t_translation_infos *infos, FILE *fp) { int instruction_counter; t_list *current_instruction; void *instruction_or_data; int errorcode; /* unchecked preconditions: pf and infos are different from NULL */ if (infos->code == NULL) return ASM_CODE_NOT_PRESENT; /* initialize the instruction_counter */ instruction_counter = 0; current_instruction = infos->code; errorcode = ASM_OK; /* translate the instruction segment */ while (instruction_counter < infos->codesize) { instruction_or_data = LDATA(current_instruction); assert(instruction_or_data != NULL); /* translate every single instruction */ errorcode = translateInstruction (infos, (t_asm_instruction *) instruction_or_data, fp); /* verify the errorcode */ if (errorcode != ASM_OK) return errorcode; /* update the instruction counter and the current instruction data */ instruction_counter++; current_instruction = LNEXT(current_instruction); } #ifndef NDEBUG fprintf(stderr, "\n"); #endif /* translate the data segment */ while (current_instruction != NULL) { instruction_or_data = LDATA(current_instruction); assert(instruction_or_data != NULL); /* translate every single element of data */ #ifndef NDEBUG fprintf(stderr, "Adding data into the data segment [datatype == %s \t; " , dataType_toString(((t_asm_data *)instruction_or_data)->dataType) ); fprintf(stderr, "value == 0x%08x] \n" , ((t_asm_data *)instruction_or_data)->value); #endif errorcode = translateData(infos, (t_asm_data *) instruction_or_data, fp); /* verify the errorcode */ if (errorcode != ASM_OK) return errorcode; current_instruction = LNEXT(current_instruction); } #ifndef NDEBUG fprintf(stderr, "\n"); #endif return ASM_OK; }
void Translator::generateCode() { sourceOutput << "void SMBEngine::code(int mode)\n" << "{\n" << TAB << "switch (mode)\n" << TAB << "{\n" << TAB << "case 0:\n" << TAB << TAB << "loadConstantData();\n" << TAB << TAB << "goto Start;\n" << TAB << "case 1:\n" << TAB << TAB << "goto NonMaskableInterrupt;\n" << TAB << "}\n\n"; // Search through the root node, and grab all code label nodes // for (std::list<AstNode*>::iterator it = root->children.begin(); it != root->children.end(); ++it) { AstNode* node = (*it); if (node->type != AST_LABEL) { continue; } LabelNode* label = static_cast<LabelNode*>(node); if (label->labelType != LABEL_CODE) { continue; } // Output a C++ label for the label // sourceOutput << "\n"; sourceOutput << label->value.s; // Output a comment, if the label has one // if (label->lineNumber != 0) { const char* comment = lookupComment(label->lineNumber); if (comment) { // Skip the first character of the ASM comment (;) // sourceOutput << " // " << (comment + 1); } } sourceOutput << "\n"; // Translate each piece of code under the label... // ListNode* listElement = static_cast<ListNode*>(label->child); while (listElement != NULL) { AstNode* instruction = listElement->value.node; if (instruction->type == AST_INSTRUCTION) { sourceOutput << TAB << translateInstruction(static_cast<InstructionNode*>(instruction)); if (instruction->lineNumber != 0) { const char* comment = lookupComment(instruction->lineNumber); if (comment) { // Skip the first character of the ASM comment (;) // sourceOutput << " // " << (comment + 1); } } // Add a nice line separator after return statements // if (static_cast<InstructionNode*>(instruction)->code == RTS) { sourceOutput << "\n\n"; sourceOutput << LINE_SEPARATOR_COMMENT; } else { // Or just a newline for all other instructions // sourceOutput << "\n"; } if (skipNextInstruction) { // If we had a .db $2c instruction immediately before this one, // we need to add a label to be able to skip this instruction // char indexStr[8]; sprintf(indexStr, "%d", skipNextInstructionIndex++); sourceOutput << "Skip_" << indexStr << ":\n"; skipNextInstruction = false; } } else if (instruction->type == AST_DATA8 && strcmp(instruction->value.node->value.node->value.s, "$2c") == 0) { // Special case: .db $2c // We need to goto the next instruction // skipNextInstruction = true; char indexStr[8]; sprintf(indexStr, "%d", skipNextInstructionIndex); sourceOutput << TAB << "goto Skip_" << indexStr << ";\n"; } listElement = static_cast<ListNode*>(listElement->next); } } // Generate a return jump table at the end of the code // sourceOutput << "// Return handler\n" << "// This emulates the RTS instruction using a generated jump table\n" << "//\n" << "Return:\n" << TAB << "switch (popReturnIndex())\n" << TAB << "{\n"; for (int i = 0; i < returnLabelIndex; i++) { char indexStr[8]; sprintf(indexStr, "%d", i); sourceOutput << TAB << "case " << indexStr << ":\n" << TAB << TAB << "goto Return_" << indexStr << ";\n"; } sourceOutput << TAB << "}\n"; // Final closing block for the code() function // sourceOutput << "}\n"; }