// mips_build_intervals: build intervals for the range [beg_insn, // end_insn). Returns the first interval if retFirst is true, // otherwise returns the last. static UNW_INTERVAL_t mips_build_intervals(uint32_t* beg_insn, uint32_t* end_insn, bool retFirst, int verbose) { UNW_INTERVAL_t beg_ui = NEW_UI(INSN(beg_insn), FrmTy_SP, FrmFlg_RAReg, 0, unwarg_NULL, MIPS_REG_RA, NULL); UNW_INTERVAL_t ui = beg_ui; UNW_INTERVAL_t nxt_ui = UNW_INTERVAL_NULL; // canonical intervals UNW_INTERVAL_t canon_ui = beg_ui; UNW_INTERVAL_t canonSP_ui = beg_ui; UNW_INTERVAL_t canonFP_ui = UNW_INTERVAL_NULL; // currently not needed int fp_saved_reg = 0; uint32_t* cur_insn = beg_insn; while (cur_insn < end_insn) { //TMSG(INTV, "insn: 0x%x [%p,%p)", *cur_insn, cur_insn, end_insn); //-------------------------------------------------- // 1. SP-frames // // SP-frame --> SP-frame: alloc/dealloc constant-sized frame // FP-frame --> FP-frame: additional storage [UNCOMMON] //-------------------------------------------------- if (isAdjustSPByConst(*cur_insn)) { int sp_arg, ra_arg; if (UI_FLD(ui,ty) == FrmTy_SP) { //checkUI(UI_ARG(ui), FrmTy_SP, cur_insn); int amnt = getAdjustSPByConstAmnt(*cur_insn); sp_arg = UI_FLD(ui,sp_arg) + amnt; checkSPOfst(&sp_arg, UI_FLD(ui,sp_arg)); ra_arg = UI_FLD(ui,ra_arg); if (!frameflg_isset(UI_FLD(ui,flgs), FrmFlg_RAReg)) { ra_arg += amnt; checkSPOfst(&ra_arg, UI_FLD(ui,ra_arg)); } } else { sp_arg = UI_FLD(ui,sp_arg); ra_arg = UI_FLD(ui,ra_arg); } nxt_ui = NEW_UI(nextInsn(cur_insn), UI_FLD(ui,ty), UI_FLD(ui,flgs), sp_arg, UI_FLD(ui,fp_arg), ra_arg, ui); ui = nxt_ui; } //-------------------------------------------------- // SP-frame --> SP-frame: store RA/FP // *** canonical frame *** //-------------------------------------------------- else if (isStoreRegInFrame(*cur_insn, MIPS_REG_SP, MIPS_REG_RA)) { checkUI(UI_ARG(ui), FrmTy_SP, cur_insn); // store return address int ra_arg = getStoreRegInFrameOffset(*cur_insn); int16_t flgs = UI_FLD(ui,flgs); frameflg_unset(&flgs, FrmFlg_RAReg); nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_SP, flgs, UI_FLD(ui,sp_arg), UI_FLD(ui,fp_arg), ra_arg, ui); ui = nxt_ui; canon_ui = canonSP_ui = nxt_ui; } else if (isStoreRegInFrame(*cur_insn, MIPS_REG_SP, MIPS_REG_FP)) { checkUI(UI_ARG(ui), FrmTy_SP, cur_insn); // store frame pointer (N.B. fp may be used as saved reg s8) int fp_arg = getStoreRegInFrameOffset(*cur_insn); nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_SP, UI_FLD(ui,flgs), UI_FLD(ui,sp_arg), fp_arg, UI_FLD(ui,ra_arg), ui); ui = nxt_ui; canon_ui = canonSP_ui = nxt_ui; } //-------------------------------------------------- // SP-frame --> SP-frame: load RA by SP //-------------------------------------------------- else if (isLoadRegFromFrame(*cur_insn, MIPS_REG_SP, MIPS_REG_RA)) { checkUI(UI_ARG(ui), FrmTy_SP, cur_insn); // sanity check: sp_arg must be positive! // TODO: apply this check to other SP-relative ops. Fix prior intervals int sp_arg = UI_FLD(ui,sp_arg); if ( !(sp_arg > 0) ) { sp_arg = UI_FLD(canonSP_ui,sp_arg); } nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_SP, FrmFlg_RAReg, sp_arg, UI_FLD(ui,fp_arg), MIPS_REG_RA, ui); ui = nxt_ui; } //-------------------------------------------------- // 2. General: interior epilogues before returns //-------------------------------------------------- else if (isJumpToReg(*cur_insn, MIPS_REG_RA) && ((cur_insn + 1/*delay slot*/ + 1) < end_insn)) { // An interior return. Restore the canonical interval if necessary. // // N.B.: Although the delay slot instruction may affect the // frame, because of the return, we will never see its effect // within this procedure. Therefore, it is harmless to skip // processing of this delay slot. if (!ui_cmp(UI_ARG(ui), UI_ARG(canon_ui))) { nxt_ui = NEW_UI(nextInsn(cur_insn + 1/*delay slot*/), UI_FLD(canon_ui,ty), UI_FLD(canon_ui,flgs), UI_FLD(canon_ui,sp_arg), UI_FLD(canon_ui,fp_arg), UI_FLD(canon_ui,ra_arg), ui); ui = nxt_ui; cur_insn++; // skip delay slot and align new interval } } //-------------------------------------------------- // General: interior epilogues before callsites //-------------------------------------------------- else if (isCall(*cur_insn) && frameflg_isset(UI_FLD(ui,flgs), FrmFlg_RAReg)) { // The callsite (jalr) is clobbering r31, but RA is in r31. We // assume this is an inconsistency arising from control flow // jumping around an interior epilogue before the callsite. // Restore the canonical interval. if (!ui_cmp(UI_ARG(ui), UI_ARG(canon_ui))) { nxt_ui = NEW_UI(nextInsn(cur_insn), UI_FLD(canon_ui,ty), UI_FLD(canon_ui,flgs), UI_FLD(canon_ui,sp_arg), UI_FLD(canon_ui,fp_arg), UI_FLD(canon_ui,ra_arg), ui); ui = nxt_ui; } } //-------------------------------------------------- // 3. Basic support for FP frames. // // *-frame --> FP-frame: store RA by FP // *** canonical frame *** //-------------------------------------------------- else if (isStoreRegInFrame(*cur_insn, MIPS_REG_FP, MIPS_REG_RA)) { int sp_arg, fp_arg; if (UI_FLD(ui,ty) == FrmTy_SP) { sp_arg = unwarg_NULL; fp_arg = convertSPToFPOfst(UI_FLD(ui,sp_arg), UI_FLD(ui,fp_arg)); } else { sp_arg = UI_FLD(ui,sp_arg); fp_arg = UI_FLD(ui,fp_arg); } int ra_arg = getStoreRegInFrameOffset(*cur_insn); int16_t flgs = UI_FLD(ui,flgs); frameflg_unset(&flgs, FrmFlg_RAReg); nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_FP, flgs, sp_arg, fp_arg, ra_arg, ui); ui = nxt_ui; canon_ui = canonFP_ui = nxt_ui; } //-------------------------------------------------- // *-frame --> FP-frame: store parent FP (saved in reg) by FP // *** canonical frame *** //-------------------------------------------------- else if (isMoveReg(*cur_insn, MIPS_REG_V0, MIPS_REG_FP)) { frameflg_set(&UI_FLD(ui,flgs), FrmFlg_FPInV); fp_saved_reg = MIPS_REG_V0; } else if (isMoveReg(*cur_insn, MIPS_REG_V1, MIPS_REG_FP)) { frameflg_set(&UI_FLD(ui,flgs), FrmFlg_FPInV); fp_saved_reg = MIPS_REG_V1; } else if (frameflg_isset(UI_FLD(ui,flgs), FrmFlg_FPInV) && isStoreRegInFrame(*cur_insn, MIPS_REG_FP, fp_saved_reg)) { int sp_arg, ra_arg; if (UI_FLD(ui,ty) == FrmTy_SP) { sp_arg = unwarg_NULL; ra_arg = convertSPToFPOfst(UI_FLD(ui,sp_arg), UI_FLD(ui,ra_arg)); } else { sp_arg = UI_FLD(ui,sp_arg); ra_arg = UI_FLD(ui,ra_arg); } int fp_arg = getStoreRegInFrameOffset(*cur_insn); nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_FP, UI_FLD(ui,flgs), sp_arg, fp_arg, ra_arg, ui); ui = nxt_ui; canon_ui = canonFP_ui = nxt_ui; } /* else if (store-parent's-SP): useless */ //-------------------------------------------------- // *-frame --> FP-frame: allocate variable-sized frame // *** canonical frame *** //-------------------------------------------------- else if (isMoveReg(*cur_insn, MIPS_REG_FP, MIPS_REG_SP)) { // FP is set to SP, likely meaning it will point to the middle // of the frame (pos. offsets) rather than the top (neg. offsets) // ??? test that the canonical FP frame has not been set ??? frameflg_set(&UI_FLD(ui,flgs), FrmFlg_FPOfstPos); } else if (isAdjustSPByVar(*cur_insn)) { // TODO: ensure "daddu sp,sp,v0" is allocation rather than deallocation // if canonical interval has been set and it is an SP-frame... if (!UI_CMP_OPT(canon_ui, beg_ui) && UI_FLD(canon_ui,ty) == FrmTy_SP) { int16_t flgs = UI_FLD(ui,flgs); int sp_arg, fp_arg, ra_arg; if (frameflg_isset(flgs, FrmFlg_FPOfstPos)) { sp_arg = UI_FLD(canon_ui,sp_arg); fp_arg = UI_FLD(canon_ui,fp_arg); ra_arg = UI_FLD(canon_ui,ra_arg); } else { sp_arg = unwarg_NULL; fp_arg = convertSPToFPOfst(UI_FLD(canon_ui,sp_arg), UI_FLD(canon_ui,fp_arg)); ra_arg = convertSPToFPOfst(UI_FLD(canon_ui,sp_arg), UI_FLD(canon_ui,ra_arg)); } frameflg_set(&flgs, FrmFlg_FrmSzUnk); nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_FP, flgs, sp_arg, fp_arg, ra_arg, ui); ui = nxt_ui; canon_ui = canonFP_ui = nxt_ui; } } //-------------------------------------------------- // FP-frame --> FP-frame: load RA by FP //-------------------------------------------------- else if (isLoadRegFromFrame(*cur_insn, MIPS_REG_FP, MIPS_REG_RA)) { checkUI(UI_ARG(ui), FrmTy_FP, cur_insn); nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_FP, FrmFlg_RAReg, UI_FLD(ui,sp_arg), UI_FLD(ui,fp_arg), MIPS_REG_RA, ui); ui = nxt_ui; } /* else if (load-parent's-FP): not needed */ /* else if (load-parent's-SP): useless */ //-------------------------------------------------- // FP-frame --> SP-frame: deallocate (all/part of) frame by restoring SP //-------------------------------------------------- else if (isMoveReg(*cur_insn, MIPS_REG_SP, MIPS_REG_FP)) { if (UI_FLD(ui,ty) == FrmTy_FP) { bool isFullDealloc = (!frameflg_isset(UI_FLD(canon_ui,flgs), FrmFlg_RAReg) && frameflg_isset(UI_FLD(ui,flgs), FrmFlg_RAReg)); int flgs = (isFullDealloc) ? FrmFlg_RAReg : UI_FLD(canonSP_ui,flgs); int sp_arg, fp_arg, ra_arg; sp_arg = (isFullDealloc) ? 0 : UI_FLD(canonSP_ui,sp_arg); fp_arg = (isFullDealloc) ? unwarg_NULL : UI_FLD(canonSP_ui,fp_arg); ra_arg = (isFullDealloc) ? MIPS_REG_RA : UI_FLD(canonSP_ui,ra_arg); nxt_ui = NEW_UI(nextInsn(cur_insn), FrmTy_SP, flgs, sp_arg, fp_arg, ra_arg, ui); ui = nxt_ui; } else { // wierd code, e.g., monitor_main! Assume rest of frame will // be deallocated normally. Could restore a canonical frame // (FIXME). } } cur_insn++; } HPC_IFNO_UNW_LITE( UI_FLD(ui,common).end = INSN(end_insn); ) #if (!HPC_UNW_LITE) if (verbose) {
void Interpreter::executeFun(uint16_t id) { _bc = ((BytecodeFunction*)_code->functionById(id))->bytecode(); _insPtr = 0; Instruction inst; while (true) { inst = nextInsn(); //cout << "Current instruction " << inst << endl; //cout << "__STACK:" << endl; //printStack(); switch (inst) { case BC_INVALID: _out << inst << " Invalid instruction" << endl; assert(false); break; case BC_DLOAD: loadDouble(); break; case BC_ILOAD: loadInt(); break; case BC_SLOAD: loadString(); break; case BC_DLOAD0: _out << inst << " Not implemented" << endl; assert(false); break; case BC_ILOAD0: pushInt(0); break; case BC_SLOAD0: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_DLOAD1: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_ILOAD1: pushInt(1); break; case BC_DLOADM1: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_ILOADM1: pushInt(-1); break; case BC_DADD: addDoubles(); break; case BC_IADD: addInts(); break; case BC_DSUB: subDoubles(); break; case BC_ISUB: subInts(); break; case BC_DMUL: dMul(); break; case BC_IMUL: iMul(); break; case BC_DDIV: divDoubles(); break; case BC_IDIV: divInts(); break; case BC_IMOD: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_DNEG: dNeg(); break; case BC_INEG: iNeg(); break; case BC_IPRINT: printInt(); break; case BC_DPRINT: printDouble(); break; case BC_SPRINT: printString(); break; case BC_I2D: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_D2I: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_S2I: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_SWAP: swap(); break; case BC_POP: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADDVAR0: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADDVAR1: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADDVAR2: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADDVAR3: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADIVAR0: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADIVAR1: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADIVAR2: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADIVAR3: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADSVAR0: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADSVAR1: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADSVAR2: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADSVAR3: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STOREDVAR0: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STOREDVAR1: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STOREDVAR2: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STOREDVAR3: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STOREIVAR0: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STOREIVAR1: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STOREIVAR2: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STOREIVAR3: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STORESVAR0: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STORESVAR1: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STORESVAR2: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STORESVAR3: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADDVAR: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADIVAR: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADSVAR: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STOREDVAR: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STOREIVAR: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STORESVAR: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_LOADCTXDVAR: loadCtxDouble(); break; case BC_LOADCTXIVAR: loadCtxInt(); break; case BC_LOADCTXSVAR: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STORECTXDVAR: storeCtxDouble(); break; case BC_STORECTXIVAR: storeCtxInt(); break; case BC_STORECTXSVAR: _out << inst << " STORE STRING ? Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_DCMP: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_ICMP: compareInts(); break; case BC_JA: jumpAlways(); break; case BC_IFICMPNE: intsNotEqualJMP(); break; case BC_IFICMPE: intsEqualJMP(); break; case BC_IFICMPG: GJump(); break; case BC_IFICMPGE: GEJump(); break; case BC_IFICMPL: //cout << "IFLESS" << endl; assert(false); break; case BC_IFICMPLE: LEJump(); break; case BC_DUMP: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_STOP: this->popContext(); return; case BC_CALL: //cout << "CALLING. STACK SIZE: " << _stack.size() << endl; call(); break; case BC_CALLNATIVE: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; case BC_RETURN: doReturn(); break; case BC_BREAK: _out << inst << " Not implemented" << endl; exit(EXIT_FAILURE); break; default: _out << "Bad instruction" << endl; break; } } this->popContext(); }