void CppEmitShift(OpcodeInfo *theOp, char *oper, int imm, int issigned) { char *us = ""; if (issigned) us = "(unsigned int)"; // Dest RebuildEmit(" %s = ", Cpp_reg[theOp->rd]); // Typecast and Src RebuildEmit("%s %s", us, Cpp_reg[theOp->rd]); // Operator RebuildEmit(" %s ", oper); if (imm) { RebuildEmit("0x%x;", theOp->imm); return; } else RebuildEmit("%s;", Cpp_reg[theOp->rs]); return; }
void JavaDecodeReturn(int emit_r15) { switch(ThisFunctionRetType) { case RET_null: RebuildEmit(" return ?; // Error report to MobileSorcery"); break; case RET_void: RebuildEmit(" return;"); break; case RET_float: case RET_int: RebuildEmit(" return r14;"); break; case RET_double: if (emit_r15) RebuildEmit(" " DBL_HIGH " = r15;\n"); RebuildEmit(" return r14;"); break; } }
void CppEmitJumpCond(OpcodeInfo *theOp, char *str, int unsign) { if(unsign) RebuildEmit(" if ((unsigned long)%s %s (unsigned long)%s) ",Cpp_reg[theOp->rd], str, Cpp_reg[theOp->rs]); else RebuildEmit(" if (%s %s %s) ",Cpp_reg[theOp->rd], str, Cpp_reg[theOp->rs]); CppDecodeLabel(theOp, "goto label_%d;"); unsign = 0; }
void CppEmitArith(OpcodeInfo *theOp, char *str, int imm) { if (imm) { RebuildEmit(" %s %s= 0x%x;", Cpp_reg[theOp->rd], str, theOp->imm); return; } RebuildEmit(" %s %s= %s;", Cpp_reg[theOp->rd], str, Cpp_reg[theOp->rs]); return; }
void RebuildCppEpilog(SYMBOL *sym) { // ThisFunctionExit if (ReturnCount > 0) RebuildEmit("label_0:;\n"); CppDecodeReturn(1); RebuildEmit("\n"); RebuildEmit("} // %s\n", sym->Name); }
void CppEmitDivu(OpcodeInfo *theOp, int imm) { if (imm) { if (theOp->imm == 0) Warning("Division by zero in recompiler"); RebuildEmit(" %s = (int) ((unsigned long)(%s)) / ((unsigned long)(%d));", Cpp_reg[theOp->rd], Cpp_reg[theOp->rd], theOp->imm); } else { RebuildEmit(" if(%s == 0) MoSyncDiv0();\n", Cpp_reg[theOp->rs]); RebuildEmit(" %s = (int) ((unsigned long)(%s)) / ((unsigned long)(%s));", Cpp_reg[theOp->rd], Cpp_reg[theOp->rd], Cpp_reg[theOp->rs]); } }
int CppDecodeLabel(OpcodeInfo *theOp, char *str) { SYMBOL *ref, *labref; int addr; ref = (SYMBOL *) ArrayGet(&CallArray, theOp->rip); // !! Check if what it points to in lablearry and use that !! if (!ref) return 0; addr = ref->Value; labref = (SYMBOL *) ArrayGet(&CodeLabelArray, addr); if (!labref) return 0; ref = labref; RebuildEmit(str, ref->LabelEnum); return 1; }
void Cpp_LoadMem(OpcodeInfo *theOp, char *str) { if (theOp->rs == 0) { RebuildEmit(" %s = %s(0x%x);", Cpp_reg[theOp->rd], str, theOp->imm); return; } if (theOp->imm == 0) { RebuildEmit(" %s = %s(%s);", Cpp_reg[theOp->rd], str, Cpp_reg[theOp->rs]); return; } RebuildEmit(" %s = %s(%s+0x%x);", Cpp_reg[theOp->rd], str, Cpp_reg[theOp->rs], theOp->imm); }
void Cpp_StoreMem(OpcodeInfo *theOp, char *str) { if (theOp->rd == 0) { RebuildEmit(" %s(0x%x, %s);", str, theOp->imm, Cpp_reg[theOp->rs]); return; } if (theOp->imm == 0) { RebuildEmit(" %s(%s, %s);", str, Cpp_reg[theOp->rd], Cpp_reg[theOp->rs]); return; } RebuildEmit(" %s(%s+0x%x, %s);", str, Cpp_reg[theOp->rd], theOp->imm, Cpp_reg[theOp->rs]); }
int CppDecodeSwitch(OpcodeInfo *theOp) { int start, len, data_ip, def_ip, i; int lab_ip; data_ip = theOp->imm; start = GetDataMemLong(data_ip++); len = GetDataMemLong(data_ip++); def_ip = GetDataMemLong(data_ip++); // default case RebuildEmit(" switch(%s)\n", Cpp_reg[theOp->rd]); RebuildEmit(" {\n"); for (i=0;i<len+1;i++) { lab_ip = GetDataMemLong(data_ip++); RebuildEmit(" case 0x%x: ", start); CppDecodeCase(lab_ip); RebuildEmit("\n"); start++; } RebuildEmit(" default: ", start); CppDecodeCase(def_ip); RebuildEmit("\n"); RebuildEmit(" }\n"); return 1; }
void RebuildCpp_EmitDS() { int need_comma; int count; int n; RebuildEmit("\n"); RebuildEmit("//****************************************\n"); RebuildEmit("// Data Section\n"); RebuildEmit("//****************************************\n\n"); RebuildEmit("#define ds_len %d\n", DataIP >> 2); RebuildEmit("#define bs_len %d\n", BssIP >> 2); RebuildEmit("#define all_len %d\n\n", (BssIP + DataIP) >> 2); RebuildEmit("#define MaxDataIP %d\n\n", MaxDataIP >> 2); RebuildEmit("int *mem_ds\n"); }
void CppEmitDiv(OpcodeInfo *theOp, int imm) { if ((theOp->rs == 0) || (theOp->imm == 0)) printf(" "); if (imm) { if (theOp->imm == 0) Warning("Division by zero in recompiler"); RebuildEmit(" %s /= %d;", Cpp_reg[theOp->rd], theOp->imm); } else { RebuildEmit(" if (%s == 0) MoSyncDiv0();\n", Cpp_reg[theOp->rs]); RebuildEmit(" %s /= %s;", Cpp_reg[theOp->rd], Cpp_reg[theOp->rs]); } }
void RebuildEmitStabs(int ip) { int line = ArrayGet(&SLD_Line_Array, ip); int file = ArrayGet(&SLD_File_Array, ip); char *FileStr; if (line == 0) return; if (file != lastfileno) { lastfileno = file; FileStr = GetFileNumString(file); if (FileStr) RebuildEmit(".sourcefile '%s'\n", FileStr); } RebuildEmit(".line %d\n", line); }
int CppDecodeCase(int ip) { SYMBOL *ref; ref = (SYMBOL *) ArrayGet(&CodeLabelArray, ip); if (!ref) return 0; RebuildEmit("goto label_%d;", ref->LabelEnum); return 1; }
void CppEmitReturnDecl(int rettype) { switch(rettype) { case RET_null: RebuildEmit("? // Error report to MoSync"); break; case RET_void: RebuildEmit("void "); break; case RET_float: case RET_int: RebuildEmit("int "); break; case RET_double: RebuildEmit("int "); break; } }
void Java_LoadMem(OpcodeInfo *theOp, char *str) { SetRegInit(theOp->rd); if (strcmp(str, "RINT") == 0) { // Optimization for int if (theOp->rs == 0) { RebuildEmit(" %s = " MEM_DS "[0x%x];", java_reg[theOp->rd], theOp->imm >> 2); return; } if (theOp->imm == 0) { RebuildEmit(" %s = " MEM_DS "[%s >> 2];", java_reg[theOp->rd], java_reg[theOp->rs]); return; } RebuildEmit(" %s = " MEM_DS "[(%s+0x%x) >> 2];", java_reg[theOp->rd], java_reg[theOp->rs], theOp->imm); return; }
void RebuildCpp_EmitProtos() { SYMBOL *sym; int n; RebuildEmit("\n// Prototypes\n\n"); RebuildEmit("static int CallReg(int s, int i0, int i1, int i2, int i3);\n"); for (n=0;n<CodeIP+1;n++) { sym = (SYMBOL *) ArrayGet(&CodeLabelArray, n); if (sym) { if (sym->Flags & SymFlag_Ref) if (sym->LabelType >= label_Function) { RebuildCppFunc(sym, 1); } } } }
void CppDecodeReturnNull() { switch(ThisFunctionRetType) { case RET_null: RebuildEmit(" return ?; // Error report to MobileSorcery"); break; case RET_void: RebuildEmit(" return;"); break; case RET_float: case RET_int: RebuildEmit(" return 0;"); break; case RET_double: RebuildEmit(" __dbl_high = 0;\n"); RebuildEmit(" return 0;"); break; } }
int CppCallFunction(SYMBOL *ref, int emit_r15) { int param_count, need_comma, n; int rettype = ref->RetType; int regs; CppEmitReturnType(rettype); RebuildEmit("%s_%d(", ref->Name, ref->LocalScope); param_count = ref->Params; if (param_count > 4) param_count = 4; need_comma = 0; regs = funcprop.reg_used; for (n=0;n<param_count;n++) { if (need_comma) RebuildEmit(", "); RebuildEmit("%s", Cpp_reg[REG_i0 + n]); need_comma = 1; } RebuildEmit(");"); if (rettype == RET_double && emit_r15 && (regs & REGBIT(REG_r15))) { RebuildEmit("\n r15 = __dbl_high;"); SetRegInit(REG_r15); } return 1; }
void CppDecodeReturn(int shouldPassR15) { switch(ThisFunctionRetType) { case RET_null: RebuildEmit(" return ?; // Error report to MobileSorcery"); break; case RET_void: RebuildEmit(" return;"); break; case RET_float: case RET_int: RebuildEmit(" return r14;"); break; case RET_double: if(shouldPassR15) RebuildEmit(" __dbl_high = r15;\n"); RebuildEmit(" return r14;"); break; } }
void CppDecodeSysCall(OpcodeInfo *theOp) { int param_count, need_comma, n; SYMBOL *syscall = FindSysCall(theOp->imm); if (!syscall) { Error(Error_System, "Could'nt locate syscall\n"); return; } CppSyscallUsed[theOp->imm]++; param_count = syscall->Params; CppEmitReturnType(syscall->RetType); RebuildEmit("SYSCALL("); RebuildEmit("%s", &syscall->Name[1]); RebuildEmit(")("); if (param_count > 4) param_count = 4; need_comma = 0; for (n=0;n<param_count;n++) { if (need_comma) RebuildEmit(", "); RebuildEmit("%s", Cpp_reg[REG_i0 + n]); need_comma = 1; } RebuildEmit(");"); if (syscall->RetType == RET_double) RebuildEmit("\n r15 = __dbl_high;"); }
void JavaDecodeSysCall(OpcodeInfo *theOp) { int param_count, need_comma, n; SYMBOL *theSysCall = FindSysCall(theOp->imm); if (!theSysCall) { Error(Error_System, "Could'nt locate syscall\n"); return; } JavaSyscallUsed[theOp->imm]++; param_count = theSysCall->Params; JavaEmitReturnType(theSysCall->RetType); if (theSysCall->Interface == 0) RebuildEmit( SYSCALLDOT "%s(", theSysCall->Name + 1); else RebuildEmit("%s(", theSysCall->Name); if (param_count > 4) param_count = 4; need_comma = 0; for (n=0;n<param_count;n++) { if (need_comma) RebuildEmit(", "); RebuildEmit("%s", java_reg[REG_i0 + n]); need_comma = 1; } RebuildEmit(");"); if (theSysCall->RetType == RET_double) { RebuildEmit("\n r15 = " DBL_HIGH ";"); SetRegInit(REG_r15); } }
void Rebuild_Main() { ArrayInit(&RebuildArray, sizeof(char), 0); ArrayInit(&LabelDone, sizeof(char), 0); lastfileno = -1; Rebuild_Mode = 1; RebuildEmit("//****************************************\n"); RebuildEmit("// Generated code\n"); RebuildEmit("//****************************************\n\n"); RebuildEmit(".lfile 'rebuild.s'\n"); RebuildEmit(".code\n"); Rebuild_Code(); RebuildEmit(".data\n"); Rebuild_Memory(); ArrayWrite(&RebuildArray, "rebuild.s"); }
void Rebuild_Data(SYMBOL *sym) { SYMBOL *thisSym; //uint ta = 0; int ip; int len; int n; int c; int left; int align; int opt_bss; // decode the field ip = sym->Value; if (sym->Type == SECT_bss) ip += MaxDataIP; len = sym->EndIP; left = len; // Has this been done already if (ArrayGet(&LabelDone, ip)) return; // Mark as done ArraySet(&LabelDone, ip, 1); if (!len) { len = FindLabelExtent(ip); if (!len) { RebuildEmit("// empty %s_%d,%d\n", sym->Name, sym->LocalScope, len); return; } // Save the result for later sym->EndIP = len; RebuildEmit("// found extent %s_%d,%d\n", sym->Name, sym->LocalScope, len); } align = ArrayGet(&DataAlignArray, ip); if (sym->Type == SECT_bss) { RebuildEmit("\t.comm %s_%d,%d\n", sym->Name, sym->LocalScope, len); return; } if (sym->Type != SECT_data) Error(Error_System, "(Rebuild_Data) Illegal section in data output"); // Check if this data field can be moved to bss #if 1 opt_bss = Rebuild_CanMoveToBss(ip, len); if (opt_bss) { // Make sure bss output is aligned int bss_len = len; while(bss_len & 3) bss_len++; RebuildEmit("\t.comm %s_%d,%d //moved to bss\n", sym->Name, sym->LocalScope, bss_len); return; } #endif if (align) RebuildEmit("\t.align %d\n", align); // write a data section field RebuildEmit("%s_%d:\n", sym->Name, sym->LocalScope ); // write array c = 0; for (n=ip;n<ip+len;n++) { thisSym = (SYMBOL *) ArrayGet(&DataArray, n); if (!thisSym) { RebuildEmit("\t.byte 0x%s\n", Hex8(GetDataMem(n)) ); left--; continue; } // check if we hit a .word reference if (left >= 4) { if (thisSym) { SYMBOL *labref = NULL; int addr; addr = thisSym->Value; if (thisSym->Type == SECT_code) { labref = (SYMBOL *) ArrayGet(&CodeLabelArray, addr); if (labref == 0) Error(Error_System, "Could not repoint label !!"); // labref = thisSym; } if (thisSym->Type == SECT_data) { labref = (SYMBOL *) ArrayGet(&LabelArray, addr); if (labref == 0) Error(Error_System, "Could not repoint label !!"); } if (thisSym->Type == SECT_bss) { labref = (SYMBOL *) ArrayGet(&LabelArray, addr + MaxDataIP); if (labref == 0) Error(Error_System, "Could not repoint label !!"); } if(labref == NULL) Error(Error_System, "Broken label"); RebuildEmit("\t.word %s_%d\n", labref->Name, labref->LocalScope); left-=4; n+=3; } } } RebuildEmit("\n\n"); return; }
void CppDecodeCallReg(OpcodeInfo *theOp) { // changed ThisFunctionRegs to funcprop.reg_used (didn't take the parameters to the function into account). int i0 = funcprop.reg_used & REGBIT(REG_i0); int i1 = funcprop.reg_used & REGBIT(REG_i1); int i2 = funcprop.reg_used & REGBIT(REG_i2); int i3 = funcprop.reg_used & REGBIT(REG_i3); RebuildEmit(" r14 = CallReg(%s", Cpp_reg[theOp->rd]); if (i0) RebuildEmit(", i0"); else RebuildEmit(", 0"); if (i1) RebuildEmit(", i1"); else RebuildEmit(", 0"); if (i2) RebuildEmit(", i2"); else RebuildEmit(", 0"); if (i3) RebuildEmit(", i3"); else RebuildEmit(", 0"); CppUsedCallReg = 1; RebuildEmit(");\n"); // r14 and r15 are always scratch registers after a function call (they may have changed. So we can safely overwrite the content here). if(funcprop.reg_used & REGBIT(REG_r15)) { RebuildEmit(" r15 = __dbl_high;\n"); } }
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; }
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); } }
void RebuildCppProlog(SYMBOL *sym, int isproto) { int reg_used; int reg_alloc; int param_count; int need_comma; int n; // Find registers used in function reg_used = FunctionRegAnalyse(sym, &funcprop); reg_alloc = 0; // Output helpful header if (isproto == 0) { RebuildEmit("\n//****************************************\n"); RebuildEmit("// Function: %s\n", sym->Name); RebuildEmit("//****************************************\n\n"); } if (!isproto) { RebuildEmit("// rrrrrrrrrrrrrrrriiiiddddddddfrsz\n"); RebuildEmit("// fedcba9876543210321076543210rtpr\n"); RebuildEmit("//src_reg = %s\n", Bin32(funcprop.src_reg)); RebuildEmit("//dst_reg = %s\n", Bin32(funcprop.dst_reg)); RebuildEmit("//assign_reg = %s\n", Bin32(funcprop.assign_reg)); RebuildEmit("//uninit_reg = %s\n", Bin32(funcprop.uninit_reg)); RebuildEmit("//used_reg = %s\n", Bin32(funcprop.reg_used)); RebuildEmit("//tfr = %s\n", Bin32(ThisFunctionRegs)); RebuildEmit("\n"); } else RebuildEmit("static "); // Output function decl switch(ThisFunctionRetType) { case RET_null: RebuildEmit(" ?; // Error report to MobileSorcery\n"); break; case RET_void: RebuildEmit("void "); break; case RET_float: case RET_int: case RET_double: RebuildEmit("int "); break; } RebuildEmit("%s_%d(", sym->Name, sym->LocalScope); param_count = sym->Params; if (param_count > 4) param_count = 4; need_comma = 0; for (n=0;n<param_count;n++) { if (need_comma) RebuildEmit(", "); RebuildEmit("int %s", Cpp_reg[REG_i0 + n]); need_comma = 1; reg_alloc |= 1 << (REG_i0 + n); } if (isproto) { RebuildEmit(");\n"); return; } RebuildEmit(")\n{\n"); // Write local decl // Remove regs that are already declared in func decl // ok this has sort of been reverse engineered by looking at the bitmasks in the rebuilt code... ;) // this is added to remove warnings about unusued variables. reg_used &= ThisFunctionRegs | (1 << REG_r14) | (1 << REG_r15) | (1 << REG_i0) | (1 << REG_i1) | (1 << REG_i2) | (1 << REG_i3); reg_used &= (~reg_alloc); // remove sp from locals reg_used &= ~(1 << REG_sp); reg_used &= ~(1 << REG_zero); if (ThisFunctionRetType != RET_null && ThisFunctionRetType != RET_void) reg_used |= (1 << REG_r14); if (ThisFunctionRetType == RET_double) reg_used |= (1 << REG_r15); if (reg_used) { RebuildEmit("\tint "); need_comma = 0; for (n=0;n<32;n++) { if (reg_used & (1 << n)) { if (need_comma) RebuildEmit(", "); RebuildEmit("%s", Cpp_reg[n]); if (funcprop.uninit_reg & (1<<n)) RebuildEmit("=0"); need_comma = 1; } } RebuildEmit(";\n\n"); } }
void RebuildCpp_EmitSyscallFunc(SYMBOL *sym, int proto, int stub) { int param_count, need_comma, n; if (!stub) if (!sym->Interface) return; if (!proto) { RebuildEmit("\n"); RebuildEmit("//****************************************\n"); RebuildEmit("// Syscall interface '%s'\n", sym->Name); RebuildEmit("//****************************************\n"); RebuildEmit("\n"); } param_count = sym->Params; CppEmitReturnDecl(sym->RetType); RebuildEmit("%s(", sym->Name); if (param_count > 4) param_count = 4; need_comma = 0; for (n=0;n<param_count;n++) { if (need_comma) RebuildEmit(", "); RebuildEmit("int %s", Cpp_reg[REG_i0 + n]); need_comma = 1; } RebuildEmit(")"); if (proto) { RebuildEmit(";\n"); return; } RebuildEmit("\n{\n"); if (!stub) RebuildEmit(" %s", sym->Interface); else { ThisFunctionRetType = sym->RetType; CppDecodeReturnNull(); } RebuildEmit("\n}\n"); }
void RebuildCpp_Main() { if (ArgConstOpt != 0) Error(Error_System, "(RebuildCpp_Main) ArgConstOpt must be switched off"); #ifdef CPP_SHOW_LINES InitFiles(); #endif ArrayInit(&RebuildArray, sizeof(char), 0); ArrayInit(&LabelDone, sizeof(char), 0); memset(CppSyscallUsed, 0, sizeof(CppSyscallUsed)); CppForceSysCallUsed("RBYTE"); CppForceSysCallUsed("WBYTE"); Rebuild_Mode = 1; CppUsedCallReg = 0; RebuildEmit("//****************************************\n"); RebuildEmit("// Generated Cpp code\n"); RebuildEmit("//****************************************\n"); RebuildEmit("\n"); RebuildEmit("#include \"mstypeinfo.h\"\n"); RebuildEmit("\n"); #if 0 //My Testing only RebuildCpp_EmitExtensionsProto(); #endif RebuildCpp_EmitProtos(); // RebuildCpp_EmitDS(); // RebuildEmit("class MoSyncCode\n"); // RebuildEmit("{\n"); // RebuildEmit("\n"); // Out in .h file // RebuildEmit("int sp;\n"); // RebuildEmit("int __dbl_high;\n"); RebuildEmit("\n"); // RebuildCpp_EmitDS(); RebuildCpp_StartUp(); MaxEnumLabel = 0; RebuildCpp_Code(); //RebuildCpp_EmitExtensions(1); RebuildCpp_CallReg(); // RebuildEmit("}; // End of MosyncCode class\n"); // RebuildEmit("// MaxEnumLabel=%d\n", MaxEnumLabel); // RebuildCpp_FlowClass(); #ifdef CPP_SHOW_LINES FreeFiles(); #endif ArrayWrite(&RebuildArray, "rebuild.build.cpp"); }