void RebuildFunc(SYMBOL *sym) { OpcodeInfo thisOp; SYMBOL *ref; uchar *ip, *ip_end, *ip_last; int real_ip; char str[256]; if (!sym) return; RebuildEmit("\n//****************************************\n"); RebuildEmit("// Function: %s\n", sym->Name); RebuildEmit("//****************************************\n\n"); #if 0 //OLD if (strcmp(sym->Name, Code_EntryPoint) == 0) { RebuildEmit(".global %s\n", sym->Name); RebuildEmit(".func %s\n", sym->Name); } else { RebuildEmit(".func %s_%d\n", sym->Name, sym->LocalScope); } #else //New if (strcmp(sym->Name, Code_EntryPoint) == 0) { RebuildEmit(".global %s\n", sym->Name); RebuildEmit(".func %s, %d, %s\n", sym->Name, sym->Params, RebuildRetType(sym->RetType) ); } else { RebuildEmit(".func %s_%d, %d, %s\n", sym->Name, sym->LocalScope, sym->Params, RebuildRetType(sym->RetType)); } #endif ip_end = (uchar *) ArrayPtr(&CodeMemArray, sym->EndIP); ip = (uchar *) ArrayPtr(&CodeMemArray, sym->Value); real_ip = sym->Value; while(1) { ip_last = ip; if (ip > ip_end) break; // Print labels ref = (SYMBOL *) ArrayGet(&CodeLabelArray, real_ip); if (ref) { if (ref->LabelType == label_Local) RebuildEmit("%s_%d:\n", ref->Name, ref->LocalScope); } RebuildEmitStabs(real_ip); // Peeper(ip, ip_end); if (ArgSkipElim == 0) if (ArrayGet(&CodeTouchArray, real_ip) == 0) RebuildEmit("// "); CaseRef = 0; ip = DecodeOpcode(&thisOp, ip); DecodeAsmString(&thisOp, str, 1); RebuildEmit("\t%s", str); // DecodeAsmString(&thisOp, str, 0); // Sanity testing // CodeSanityChecker(thisOp.rip, str); if (ArgDebugRebuild) { int len = 4 + strlen(str); str[0] = 0; while(len < 40) { RebuildEmit(" ", str); len++; } RebuildEmit("; 0x%x - ", real_ip); DisassembleFromSource(real_ip, str); RebuildEmit("%s", str); } RebuildEmit("\n"); // Check for case statement, which need case data after them if (CaseRef) { RebuildEmit(".data\n"); Rebuild_Data(CaseRef); RebuildEmit(".code\n"); } real_ip += (ip - ip_last); } }
int RebuildCppInst(OpcodeInfo *theOp) { int ip = theOp->rip; char str[256]; #ifdef CPP_DEBUG str[0] = 0; DisassembleFromSource(ip, str); RebuildEmit("\t\t\t\t\t\t//%s\n", str); #endif #ifdef CPP_SHOW_LINES { int line = ArrayGet(&SLD_Line_Array, ip); int file = ArrayGet(&SLD_File_Array, ip); if(line!=0) { RebuildEmit("\n // %s:%d\n", GetFileNumString(file), line); RebuildEmit(" // %s\n", GetFileLine(file, line)); } } #endif switch (theOp->op) { case _PUSH: RebuildEmit(" //push %s,%d\n",Cpp_reg[theOp->rd], theOp->rs); if (REGUSED(funcprop.reg_used, REG_sp)) { RebuildEmit(" sp -= %d;\n",theOp->rs*4); } return 1; case _POP: RebuildEmit(" //pop %s,%d\n",Cpp_reg[theOp->rd], theOp->rs); if (REGUSED(funcprop.reg_used, REG_sp)) { RebuildEmit(" sp += %d;\n",theOp->rs*4); } return 1; case _CASE: CppDecodeSwitch(theOp); break; case _CALLI: CppDecodeCall(theOp); break; case _SYSCALL: CppDecodeSysCall(theOp); break; case _CALL: CppDecodeCallReg(theOp); break; case _LDI: RebuildEmit(" %s = 0x%x;", Cpp_reg[theOp->rd], theOp->imm); break; case _LDR: { if (IsRegConst(theOp->rs)) RebuildEmit(" %s = 0x%x;", Cpp_reg[theOp->rd], ConstRegValue(theOp->rs)); else RebuildEmit(" %s = %s;", Cpp_reg[theOp->rd], Cpp_reg[theOp->rs]); } break; // Arithmatic case _ADD: CppEmitArith(theOp,"+", 0); break; case _ADDI: CppEmitArith(theOp,"+", 1); break; case _MUL: CppEmitArith(theOp,"*", 0); break; case _MULI: CppEmitArith(theOp,"*", 1); break; case _SUB: CppEmitArith(theOp,"-", 0); break; case _SUBI: CppEmitArith(theOp,"-", 1); break; case _AND: CppEmitArith(theOp,"&", 0); break; case _ANDI: CppEmitArith(theOp,"&", 1); break; case _OR: CppEmitArith(theOp,"|", 0); break; case _ORI: CppEmitArith(theOp,"|", 1); break; case _XOR: CppEmitArith(theOp,"^", 0); break; case _XORI: CppEmitArith(theOp,"^", 1); break; case _DIVU: CppEmitDivu(theOp, 0); break; case _DIVUI: CppEmitDivu(theOp, 1); break; case _DIV: CppEmitArith(theOp,"/", 0); break; case _DIVI: CppEmitArith(theOp,"/", 1); break; // Shifts case _SLL: CppEmitShift(theOp,"<<", 0, 0); break; case _SLLI: CppEmitShift(theOp,"<<", 1, 0); break; case _SRA: CppEmitShift(theOp,">>", 0, 0); break; case _SRAI: CppEmitShift(theOp,">>", 1, 0); break; case _SRL: CppEmitShift(theOp,">>", 0, 1); // Unsigned break; case _SRLI: CppEmitShift(theOp,">>", 1, 1); // Unsigned break; case _NOT: RebuildEmit(" %s = ~%s;", Cpp_reg[theOp->rd], Cpp_reg[theOp->rs]); break; case _NEG: RebuildEmit(" %s = -%s;", Cpp_reg[theOp->rd], Cpp_reg[theOp->rs]); break; case _RET: { if (ThisFunctionExit == 0) // Don't output a return jump on last instruction { RebuildEmit(" goto label_0; // return"); ReturnCount++; } } break; // Conditional jumps case _JC_EQ: CppEmitJumpCond(theOp, "==", 0); break; case _JC_NE: CppEmitJumpCond(theOp, "!=", 0); break; case _JC_GE: CppEmitJumpCond(theOp, ">=", 0); break; case _JC_GEU: CppEmitJumpCond(theOp, ">=", 1); break; case _JC_GT: CppEmitJumpCond(theOp, ">", 0); break; case _JC_GTU: CppEmitJumpCond(theOp, ">", 1); break; case _JC_LE: CppEmitJumpCond(theOp, "<=", 0); break; case _JC_LEU: CppEmitJumpCond(theOp, "<=", 1); break; case _JC_LT: CppEmitJumpCond(theOp, "<", 0); break; case _JC_LTU: CppEmitJumpCond(theOp, "<", 1); break; case _JPI: CppDecodeLabel(theOp, " goto label_%d;"); break; // Memory instructions case _LDW: Cpp_LoadMem(theOp, "RINT"); break; case _LDH: Cpp_LoadMem(theOp, "RSHORT"); break; case _LDB: Cpp_LoadMem(theOp, "RBYTE"); break; case _STW: Cpp_StoreMem(theOp, "WINT"); break; case _STH: Cpp_StoreMem(theOp, "WSHORT"); break; case _STB: Cpp_StoreMem(theOp, "WBYTE"); break; case _XB: RebuildEmit(" %s = (int)((char) %s);", Cpp_reg[theOp->rd], Cpp_reg[theOp->rs]); break; case _XH: RebuildEmit(" %s = (int)((short) %s);", Cpp_reg[theOp->rd], Cpp_reg[theOp->rs]); break; default: str[0] = 0; DisassembleFromSource(ip, str); ErrorOnIP(Error_Fatal, ip, "Missing instruction in Cpp rebuilder '%s'\n", str); } // ArraySet(&SLD_Line_Array, CodeIP, line); // ArraySet(&SLD_File_Array, CodeIP, This_SLD_File); // RebuildEmit("\n"); RebuildEmit("\n"); #ifdef LOG_REGISTER_STATE_CHANGES if (funcprop.reg_used) { /* int n; for (n=0;n<32;n++) { if (reg_used & (1 << n)) { RebuildEmit("if(last_%s != %s) { LOG_REGISTER(%s); last_%s = %s;}\n", Cpp_reg[n], Cpp_reg[n], Cpp_reg[n], Cpp_reg[n], Cpp_reg[n]); } } RebuildEmit(";\n\n"); */ RebuildEmit("\tLOG_REGISTER_STATE_CHANGES(0x%x)\n", funcprop.reg_used); } #endif return 1; }
int FunctionRegAnalyse(SYMBOL *sym, FuncProp *fp) { OpcodeInfo thisOp; uchar *ip, *ip_end; int params,n; fp->src_reg = 0; fp->dst_reg = 0; fp->assign_reg = 0; fp->uninit_reg = 0; // Make sure we have a valid symbol if (!sym) return -1; // Make sure the symbol is a function if (sym->Type != SECT_code) return -1; // Get the start and end of the function in the code array ip_end = (uchar *) ArrayPtr(&CodeMemArray, sym->EndIP); ip = (uchar *) ArrayPtr(&CodeMemArray, sym->Value); // Set up the parameter regs params = sym->Params; for (n=0;n<params;n++) { fp->assign_reg |= REGBIT(REG_i0 + n); } // Scan the function #ifdef AFDEBUG printf("\n"); #endif while(1) { if (ip > ip_end) break; #ifdef AFDEBUG { char buf[2560]; buf[0] = 0; DisassembleFromSource(ip - CodeMemArray.array, buf); printf("%s\n", buf); } #endif ip = DecodeOpcode(&thisOp, ip); // Ignor push and pop if (thisOp.op == _PUSH) continue; if (thisOp.op == _POP) continue; //----------------------------------------- // Deal with syscalls // for some strange reason rd is the syscallId which will // tag unused registers as used for void functions //----------------------------------------- if(thisOp.op == _SYSCALL) { FunctionReg_Syscall(&thisOp, fp); } // Check for a dest reg else if (thisOp.flags & fetch_d) { if (thisOp.rd < 32) { // Since this is a dst regs we say its initialized fp->assign_reg |= REGBIT(thisOp.rd); // Say this reg was used as a dst reg fp->dst_reg |= REGBIT(thisOp.rd); } } // Check for a source reg if (thisOp.flags & fetch_s) { if (thisOp.rs < 32) { // check if this reg was assigned previously, if it was'nt it is uninitialized before use int is_assigned = fp->assign_reg & REGBIT(thisOp.rs); if (!is_assigned) fp->uninit_reg |= REGBIT(thisOp.rs); fp->src_reg |= REGBIT(thisOp.rs); } } //----------------------------------------- // Deal with immediate calls //----------------------------------------- // Add the call parameters to the used list if (thisOp.op == _CALLI) { FunctionReg_Calli(&thisOp, fp); } //----------------------------------------- // Deal with register calls //----------------------------------------- // Add the call parameters to the used list if (thisOp.op == _CALL) { FunctionReg_CallReg(&thisOp, fp); } } #ifdef AFDEBUG printf("\n"); printf(" rrrrrrrrrrrrrrrriiiiddddddddfrsz\n"); printf(" fedcba9876543210321076543210rtpr\n"); printf("src_reg = %s\n", Bin32(fp->src_reg)); printf("dst_reg = %s\n", Bin32(fp->dst_reg)); printf("assign_reg = %s\n", Bin32(fp->assign_reg)); printf("uninit_reg = %s\n", Bin32(fp->uninit_reg)); if (fp->uninit_reg) printf(""); #endif // Make sure zr is never uninitialized fp->uninit_reg &= ~REGBIT(REG_zero); // Make a composit of which reg's were used fp->reg_used = fp->src_reg | fp->dst_reg; return fp->reg_used; }
void RebuildCppFunc(SYMBOL *sym, int isproto) { OpcodeInfo thisOp; SYMBOL *ref; uchar *ip, *ip_end, *ip_last; int real_ip; // char str[256]; if (!sym) return; // Say no returns yet ReturnCount = 0; // Enumerate this functions labels, unless we're generating a proto if (isproto == 0) EnumerateFunctionLabels(sym); ThisFunctionRegs = FunctionRegUsage(sym); ThisFunctionRetType = sym->RetType; if (ThisFunctionRegs == -1) return; RebuildCppProlog(sym, isproto); // if we're generating a proto return if (isproto) return; ip_end = (uchar *) ArrayPtr(&CodeMemArray, sym->EndIP); ip = (uchar *) ArrayPtr(&CodeMemArray, sym->Value); real_ip = sym->Value; while(1) { ip_last = ip; if (ip > ip_end) break; // Print labels ref = (SYMBOL *) ArrayGet(&CodeLabelArray, real_ip); if (ref) { if (ref->LabelType == label_Local) { #ifdef Cpp_DEBUG RebuildEmit("// %s_%d:\n", ref->Name, ref->LocalScope); #endif RebuildEmit("label_%d:;\n", ref->LabelEnum); } } if (ArrayGet(&CodeTouchArray, real_ip) == 0) RebuildEmit("// "); CaseRef = 0; ip = DecodeOpcode(&thisOp, ip); ThisFunctionExit = 0; if (ip > ip_end) ThisFunctionExit = 1; RebuildCppInst(&thisOp); // DecodeAsmString(&thisOp, str); // RebuildEmit("\t%s", str); #ifdef CPP_DEBUG { int len = 4 + strlen(str); str[0] = 0; while(len < 40) { RebuildEmit(" ", str); len++; } DisassembleFromSource(real_ip, str); RebuildEmit(";%s", str); } #endif // RebuildEmit("\n"); // Check for case statement, which need case data after them /* if (CaseRef) { RebuildEmit(".data\n"); Rebuild_Data(CaseRef); RebuildEmit(".code\n"); } */ real_ip += (ip - ip_last); } RebuildCppEpilog(sym); }
int RebuildJavaInst(OpcodeInfo *theOp) { int ip = theOp->rip; char str[256]; #ifdef JRDEBUG str[0] = 0; DisassembleFromSource(ip, str); RebuildEmit("\t\t\t\t\t\t//%s\n", str); #endif switch (theOp->op) { case _PUSH: RebuildEmit(" //push %s,%d\n",java_reg[theOp->rd], theOp->rs); if (function_registers_used & (1 << REG_sp)) { RebuildEmit(" " SP_STR " -= %d;\n",theOp->rs*4); } return 1; case _POP: RebuildEmit(" //pop %s,%d\n",java_reg[theOp->rd], theOp->rs); if (function_registers_used & (1 << REG_sp)) { RebuildEmit(" " SP_STR " += %d;\n",theOp->rs*4); } return 1; case _CASE: JavaDecodeSwitch(theOp); break; case _CALLI: JavaDecodeCall(theOp); break; case _SYSCALL: JavaDecodeSysCall(theOp); break; case _CALL: JavaDecodeCallReg(theOp); break; case _LDI: RebuildEmit(" %s = 0x%x;", java_reg[theOp->rd], theOp->imm); SetRegInit(theOp->rd); break; case _LDR: { SetRegInit(theOp->rd); if (IsRegConst(theOp->rs)) RebuildEmit(" %s = 0x%x;", java_reg[theOp->rd], ConstRegValue(theOp->rs)); else RebuildEmit(" %s = %s;", java_reg[theOp->rd], java_reg[theOp->rs]); } break; // Arithmatic case _ADD: JavaEmitArith(theOp,"+", 0); break; case _ADDI: JavaEmitArith(theOp,"+", 1); break; case _MUL: JavaEmitArith(theOp,"*", 0); break; case _MULI: JavaEmitArith(theOp,"*", 1); break; case _SUB: JavaEmitArith(theOp,"-", 0); break; case _SUBI: JavaEmitArith(theOp,"-", 1); break; case _AND: JavaEmitArith(theOp,"&", 0); break; case _ANDI: JavaEmitArith(theOp,"&", 1); break; case _OR: JavaEmitArith(theOp,"|", 0); break; case _ORI: JavaEmitArith(theOp,"|", 1); break; case _XOR: JavaEmitArith(theOp,"^", 0); break; case _XORI: JavaEmitArith(theOp,"^", 1); break; case _DIVU: JavaEmitDivu(theOp, 0); break; case _DIVUI: JavaEmitDivu(theOp, 1); break; case _DIV: JavaEmitArith(theOp,"/", 0); break; case _DIVI: JavaEmitArith(theOp,"/", 1); break; // Shifts case _SLL: JavaEmitArith(theOp,"<<", 0); break; case _SLLI: JavaEmitArith(theOp,"<<", 1); break; case _SRA: JavaEmitArith(theOp,">>", 0); break; case _SRAI: JavaEmitArith(theOp,">>", 1); break; case _SRL: JavaEmitArith(theOp,">>>", 0); break; case _SRLI: JavaEmitArith(theOp,">>>", 1); break; case _NOT: RebuildEmit(" %s = ~%s;", java_reg[theOp->rd], java_reg[theOp->rs]); SetRegInit(theOp->rd); break; case _NEG: RebuildEmit(" %s = -%s;", java_reg[theOp->rd], java_reg[theOp->rs]); SetRegInit(theOp->rd); break; case _RET: { if (ThisFunctionExit == 0) // Don't output a return jump on last instruction { RebuildEmit(" ms.goto_0(); // return"); ReturnCount++; } } break; // Conditional jumps case _JC_EQ: JavaEmitJumpCond(theOp, "==", 0); break; case _JC_NE: JavaEmitJumpCond(theOp, "!=", 0); break; case _JC_GE: JavaEmitJumpCond(theOp, ">=", 0); break; case _JC_GEU: JavaEmitJumpCond(theOp, ">=", 1); break; case _JC_GT: JavaEmitJumpCond(theOp, ">", 0); break; case _JC_GTU: JavaEmitJumpCond(theOp, ">", 1); break; case _JC_LE: JavaEmitJumpCond(theOp, "<=", 0); break; case _JC_LEU: JavaEmitJumpCond(theOp, "<=", 1); break; case _JC_LT: JavaEmitJumpCond(theOp, "<", 0); break; case _JC_LTU: JavaEmitJumpCond(theOp, "<", 1); break; case _JPI: JavaDecodeLabel(theOp, " ms.goto_%d();"); break; #ifdef NO_ELIM case _JPR: // JavaDecodeLabel(theOp, " ms.goto_%d();"); break; #endif // Memory instructions case _LDW: Java_LoadMem(theOp, "RINT"); break; case _LDH: Java_LoadMem(theOp, "RSHORT"); break; case _LDB: Java_LoadMem(theOp, "RBYTE"); break; case _STW: Java_StoreMem(theOp, "WINT"); break; case _STH: Java_StoreMem(theOp, "WSHORT"); break; case _STB: Java_StoreMem(theOp, "WBYTE"); break; case _XB: RebuildEmit(" %s = (int)((byte) %s);", java_reg[theOp->rd], java_reg[theOp->rs]); break; case _XH: RebuildEmit(" %s = (int)((short) %s);", java_reg[theOp->rd], java_reg[theOp->rs]); break; default: str[0] = 0; DisassembleFromSource(ip, str); ErrorOnIP(Error_Fatal, ip, "Missing instruction in Java rebuilder '%s'\n", str); } RebuildEmit("\n"); return 1; }