// ArmletDisassembler.cpp: implementation of the ArmletDisassembler class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "archimedes.h" #include "ArmletDisassembler.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CArmletDisassembler::CArmletDisassembler() { } CArmletDisassembler::~CArmletDisassembler() { } CString CArmletDisassembler::disassemble(uint32 number, Armlet *armlet) { CString output = ""; CString opcodeLabel = ""; // ??? debugging if( 0 ) { TRACE("opcode = %d ", armlet->opcode); TRACE("rd = %d ", armlet->rd); TRACE("rx = %d ", armlet->rx); TRACE("ry = %d ", armlet->ry); TRACE("value = 0x%x \n", armlet->value); TRACE("inflags = 0x%x \n", armlet->inflags); TRACE("outflags = 0x%x \n", armlet->outflags); } // decode inflags char flagName[4] = { 'V', 'C', 'Z', 'N' }; output += "["; for(int inflag=3; inflag>=0; inflag--) { if(armlet->inflags & (1<=0; outflag--) { if(armlet->outflags & (1<opcode) { // implied, no operands, emit() case irCLEARTRANS : opcodeLabel = "cleartrans"; break; case irSETTRANS : opcodeLabel = "settrans"; break; case irSETPC : opcodeLabel = "setpc"; break; // one variable and one value operand, emit1() case irMOVC : opcodeLabel = "movc"; break; case irGETPC : opcodeLabel = "getpc"; break; case irINTCHECK : opcodeLabel = "intcheck"; break; // two variable operands, emit2() case irMOV : opcodeLabel = "mov"; break; case irMVN : opcodeLabel = "mvn"; break; case irTST : opcodeLabel = "tst"; break; case irTEQ : opcodeLabel = "teq"; break; case irCMP : opcodeLabel = "cmp"; break; case irCMN : opcodeLabel = "cmn"; break; case irRRX : opcodeLabel = "rrx"; break; // three variable operands, emit3() case irAND : opcodeLabel = "and"; break; case irEOR : opcodeLabel = "eor"; break; case irSUB : opcodeLabel = "sub"; break; case irADD : opcodeLabel = "add"; break; case irADC : opcodeLabel = "adc"; break; case irSBC : opcodeLabel = "sbc"; break; case irORR : opcodeLabel = "orr"; break; case irLSL : opcodeLabel = "lsl"; break; case irLSR : opcodeLabel = "lsr"; break; case irASR : opcodeLabel = "asr"; break; case irROR : opcodeLabel = "ror"; break; case irMUL : opcodeLabel = "mul"; break; case irLDB : opcodeLabel = "ldb"; break; case irSTB : opcodeLabel = "stb"; break; case irLDW : opcodeLabel = "ldw"; break; case irSTW : opcodeLabel = "stw"; break; // one value operand, emitV() case irGOTOEQ : opcodeLabel = "gotoeq"; break; case irGOTONE : opcodeLabel = "gotone"; break; case irGOTOCS : opcodeLabel = "gotocs"; break; case irGOTOCC : opcodeLabel = "gotocc"; break; case irGOTOMI : opcodeLabel = "gotomi"; break; case irGOTOPL : opcodeLabel = "gotopl"; break; case irGOTOVS : opcodeLabel = "gotovs"; break; case irGOTOVC : opcodeLabel = "gotovc"; break; case irGOTOHI : opcodeLabel = "gotohi"; break; case irGOTOLS : opcodeLabel = "gotols"; break; case irGOTOGE : opcodeLabel = "gotoge"; break; case irGOTOLT : opcodeLabel = "gotolt"; break; case irGOTOGT : opcodeLabel = "gotogt"; break; case irGOTOLE : opcodeLabel = "gotole"; break; case irGOTO : opcodeLabel = "goto"; break; case irGOTONV : opcodeLabel = "gotonv"; break; case irLEAVE : opcodeLabel = "leave"; break; default: opcodeLabel.Format("", armlet->opcode); } CString operands = ""; // decode operands if(armlet->opcode < irLastImplied) { // implied, no operands, emit() } else { if(armlet->opcode < irLastOneVar) { // one variable and one value operand, emit1() CString value; value.Format("0x%x", armlet->value); operands = getVariableLabel(armlet->rd) + "," + value; } else { if(armlet->opcode < irLastTwoVar) { if(armlet->ry == vUNUSED) { // two variable operands that use rd rather than ry i.e. MOV and MVN operands = getVariableLabel(armlet->rd) + "," + getVariableLabel(armlet->rx); } else { // two variable operands, emit2() operands = getVariableLabel(armlet->rx) + "," + getVariableLabel(armlet->ry); } } else { if(armlet->opcode < irLastThreeVar) { // three variable operands, emit3() operands = getVariableLabel(armlet->rd) + "," + getVariableLabel(armlet->rx) + "," + getVariableLabel(armlet->ry); } else { // one value operand, emitV() operands.Format("0x%x", armlet->value); } } } } output += opcodeLabel; // if more operands allow spaces for 20 chars and 3 spaces if(operands != "") { while( output.GetLength() < 23) output += " "; } output += operands; if(armlet->leader) { output += " <--"; } return output; } // // return the string for the given variable name // CString CArmletDisassembler::getVariableLabel(uint variable) { // bounds check before look up if(variable > maxTemp+1) { CString errorString; errorString.Format(" INVALID VARIABLE NUMBER: 0x%x ", variable); return errorString; } const CString labels[vMODE+2] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc", "nflag", "zflag", "cflag", "vflag", "iflag", "fflag", "mode", "UNUSED - error in profiler or disassembler, this should not appear", }; if(variable >= vT0) { // temp CString tempLabel = ""; tempLabel.Format("t%d", variable - vT0 ); return tempLabel; } else { return labels[variable]; } }