| #include "../common/asm-constants.h" |
| #include "../common/mips-defines.h" |
| #include <asm/regdef.h> |
| #include <asm/fpregdef.h> |
| |
| #ifdef __mips_hard_float |
| #define HARD_FLOAT |
| #else |
| #define SOFT_FLOAT |
| #endif |
| |
| #if (__mips==32) && (__mips_isa_rev>=2) |
| #define MIPS32R2 |
| #endif |
| |
| /* MIPS definitions and declarations |
| |
| reg nick purpose |
| s0 rPC interpreted program counter, used for fetching instructions |
| s1 rFP interpreted frame pointer, used for accessing locals and args |
| s2 rSELF self (Thread) pointer |
| s3 rIBASE interpreted instruction base pointer, used for computed goto |
| s4 rINST first 16-bit code unit of current instruction |
| */ |
| |
| |
| /* single-purpose registers, given names for clarity */ |
| #define rPC s0 |
| #define rFP s1 |
| #define rSELF s2 |
| #define rIBASE s3 |
| #define rINST s4 |
| #define rOBJ s5 |
| #define rBIX s6 |
| #define rTEMP s7 |
| |
| /* The long arguments sent to function calls in Big-endian mode should be register |
| swapped when sent to functions in little endian mode. In other words long variable |
| sent as a0(MSW), a1(LSW) for a function call in LE mode should be sent as a1, a0 in |
| Big Endian mode */ |
| |
| #ifdef HAVE_LITTLE_ENDIAN |
| #define rARG0 a0 |
| #define rARG1 a1 |
| #define rARG2 a2 |
| #define rARG3 a3 |
| #define rRESULT0 v0 |
| #define rRESULT1 v1 |
| #else |
| #define rARG0 a1 |
| #define rARG1 a0 |
| #define rARG2 a3 |
| #define rARG3 a2 |
| #define rRESULT0 v1 |
| #define rRESULT1 v0 |
| #endif |
| |
| |
| /* save/restore the PC and/or FP from the glue struct */ |
| #define LOAD_PC_FROM_SELF() lw rPC, offThread_pc(rSELF) |
| #define SAVE_PC_TO_SELF() sw rPC, offThread_pc(rSELF) |
| #define LOAD_FP_FROM_SELF() lw rFP, offThread_curFrame(rSELF) |
| #define SAVE_FP_TO_SELF() sw rFP, offThread_curFrame(rSELF) |
| #define LOAD_PC_FP_FROM_SELF() \ |
| LOAD_PC_FROM_SELF(); \ |
| LOAD_FP_FROM_SELF() |
| #define SAVE_PC_FP_TO_SELF() \ |
| SAVE_PC_TO_SELF(); \ |
| SAVE_FP_TO_SELF() |
| |
| #define EXPORT_PC() \ |
| sw rPC, (offStackSaveArea_currentPc - sizeofStackSaveArea)(rFP) |
| |
| #define SAVEAREA_FROM_FP(rd, _fpreg) \ |
| subu rd, _fpreg, sizeofStackSaveArea |
| |
| #define FETCH_INST() lhu rINST, (rPC) |
| |
| #define FETCH_ADVANCE_INST(_count) lhu rINST, ((_count)*2)(rPC); \ |
| addu rPC, rPC, ((_count) * 2) |
| |
| #define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \ |
| lhu _dreg, ((_count)*2)(_sreg) ; \ |
| addu _sreg, _sreg, (_count)*2 |
| |
| #define FETCH_ADVANCE_INST_RB(rd) addu rPC, rPC, rd; \ |
| lhu rINST, (rPC) |
| |
| #define FETCH(rd, _count) lhu rd, ((_count) * 2)(rPC) |
| #define FETCH_S(rd, _count) lh rd, ((_count) * 2)(rPC) |
| |
| #ifdef HAVE_LITTLE_ENDIAN |
| |
| #define FETCH_B(rd, _count) lbu rd, ((_count) * 2)(rPC) |
| #define FETCH_C(rd, _count) lbu rd, ((_count) * 2 + 1)(rPC) |
| |
| #else |
| |
| #define FETCH_B(rd, _count) lbu rd, ((_count) * 2 + 1)(rPC) |
| #define FETCH_C(rd, _count) lbu rd, ((_count) * 2)(rPC) |
| |
| #endif |
| |
| #define GET_INST_OPCODE(rd) and rd, rINST, 0xFF |
| |
| /* |
| * Put the prefetched instruction's opcode field into the specified register. |
| */ |
| |
| #define GET_PREFETCHED_OPCODE(dreg, sreg) andi dreg, sreg, 255 |
| |
| #define GOTO_OPCODE(rd) sll rd, rd, ${handler_size_bits}; \ |
| addu rd, rIBASE, rd; \ |
| jr rd |
| |
| #define GOTO_OPCODE_BASE(_base, rd) sll rd, rd, ${handler_size_bits}; \ |
| addu rd, _base, rd; \ |
| jr rd |
| |
| #define GET_VREG(rd, rix) LOAD_eas2(rd, rFP, rix) |
| |
| #define GET_VREG_F(rd, rix) EAS2(AT, rFP, rix); \ |
| .set noat; l.s rd, (AT); .set at |
| |
| #define SET_VREG(rd, rix) STORE_eas2(rd, rFP, rix) |
| |
| #define SET_VREG_GOTO(rd, rix, dst) .set noreorder; \ |
| sll dst, dst, ${handler_size_bits}; \ |
| addu dst, rIBASE, dst; \ |
| sll t8, rix, 2; \ |
| addu t8, t8, rFP; \ |
| jr dst; \ |
| sw rd, 0(t8); \ |
| .set reorder |
| |
| #define SET_VREG_F(rd, rix) EAS2(AT, rFP, rix); \ |
| .set noat; s.s rd, (AT); .set at |
| |
| |
| #define GET_OPA(rd) srl rd, rINST, 8 |
| #ifndef MIPS32R2 |
| #define GET_OPA4(rd) GET_OPA(rd); and rd, 0xf |
| #else |
| #define GET_OPA4(rd) ext rd, rINST, 8, 4 |
| #endif |
| #define GET_OPB(rd) srl rd, rINST, 12 |
| |
| #define LOAD_rSELF_OFF(rd, off) lw rd, offThread_##off## (rSELF) |
| |
| #define LOAD_rSELF_method(rd) LOAD_rSELF_OFF(rd, method) |
| #define LOAD_rSELF_methodClassDex(rd) LOAD_rSELF_OFF(rd, methodClassDex) |
| #define LOAD_rSELF_interpStackEnd(rd) LOAD_rSELF_OFF(rd, interpStackEnd) |
| #define LOAD_rSELF_retval(rd) LOAD_rSELF_OFF(rd, retval) |
| #define LOAD_rSELF_pActiveProfilers(rd) LOAD_rSELF_OFF(rd, pActiveProfilers) |
| #define LOAD_rSELF_bailPtr(rd) LOAD_rSELF_OFF(rd, bailPtr) |
| #define LOAD_rSELF_SelfSuspendCount(rd) LOAD_rSELF_OFF(rd, SelfSuspendCount) |
| |
| |
| /* |
| * Form an Effective Address rd = rbase + roff<<n; |
| * Uses reg AT |
| */ |
| #define EASN(rd, rbase, roff, rshift) .set noat; \ |
| sll AT, roff, rshift; \ |
| addu rd, rbase, AT; \ |
| .set at |
| |
| #define EAS1(rd, rbase, roff) EASN(rd, rbase, roff, 1) |
| #define EAS2(rd, rbase, roff) EASN(rd, rbase, roff, 2) |
| #define EAS3(rd, rbase, roff) EASN(rd, rbase, roff, 3) |
| #define EAS4(rd, rbase, roff) EASN(rd, rbase, roff, 4) |
| |
| /* |
| * Form an Effective Shift Right rd = rbase + roff>>n; |
| * Uses reg AT |
| */ |
| #define ESRN(rd, rbase, roff, rshift) .set noat; \ |
| srl AT, roff, rshift; \ |
| addu rd, rbase, AT; \ |
| .set at |
| |
| #define LOAD_eas2(rd, rbase, roff) EAS2(AT, rbase, roff); \ |
| .set noat; lw rd, 0(AT); .set at |
| |
| #define STORE_eas2(rd, rbase, roff) EAS2(AT, rbase, roff); \ |
| .set noat; sw rd, 0(AT); .set at |
| |
| #define LOAD_RB_OFF(rd, rbase, off) lw rd, off(rbase) |
| #define LOADu2_RB_OFF(rd, rbase, off) lhu rd, off(rbase) |
| #define STORE_RB_OFF(rd, rbase, off) sw rd, off(rbase) |
| |
| #ifdef HAVE_LITTLE_ENDIAN |
| |
| #define STORE64_off(rlo, rhi, rbase, off) sw rlo, off(rbase); \ |
| sw rhi, (off+4)(rbase) |
| #define LOAD64_off(rlo, rhi, rbase, off) lw rlo, off(rbase); \ |
| lw rhi, (off+4)(rbase) |
| |
| #define vSTORE64_off(rlo, rhi, rbase, off) sw rlo, off(rbase); \ |
| sw rhi, (off+4)(rbase) |
| #define vLOAD64_off(rlo, rhi, rbase, off) lw rlo, off(rbase); \ |
| lw rhi, (off+4)(rbase) |
| |
| #define STORE64_off_F(rlo, rhi, rbase, off) s.s rlo, off(rbase); \ |
| s.s rhi, (off+4)(rbase) |
| #define LOAD64_off_F(rlo, rhi, rbase, off) l.s rlo, off(rbase); \ |
| l.s rhi, (off+4)(rbase) |
| #else |
| |
| #define STORE64_off(rlo, rhi, rbase, off) sw rlo, (off+4)(rbase); \ |
| sw rhi, (off)(rbase) |
| #define LOAD64_off(rlo, rhi, rbase, off) lw rlo, (off+4)(rbase); \ |
| lw rhi, (off)(rbase) |
| #define vSTORE64_off(rlo, rhi, rbase, off) sw rlo, (off+4)(rbase); \ |
| sw rhi, (off)(rbase) |
| #define vLOAD64_off(rlo, rhi, rbase, off) lw rlo, (off+4)(rbase); \ |
| lw rhi, (off)(rbase) |
| #define STORE64_off_F(rlo, rhi, rbase, off) s.s rlo, (off+4)(rbase); \ |
| s.s rhi, (off)(rbase) |
| #define LOAD64_off_F(rlo, rhi, rbase, off) l.s rlo, (off+4)(rbase); \ |
| l.s rhi, (off)(rbase) |
| #endif |
| |
| #define STORE64(rlo, rhi, rbase) STORE64_off(rlo, rhi, rbase, 0) |
| #define LOAD64(rlo, rhi, rbase) LOAD64_off(rlo, rhi, rbase, 0) |
| |
| #define vSTORE64(rlo, rhi, rbase) vSTORE64_off(rlo, rhi, rbase, 0) |
| #define vLOAD64(rlo, rhi, rbase) vLOAD64_off(rlo, rhi, rbase, 0) |
| |
| #define STORE64_F(rlo, rhi, rbase) STORE64_off_F(rlo, rhi, rbase, 0) |
| #define LOAD64_F(rlo, rhi, rbase) LOAD64_off_F(rlo, rhi, rbase, 0) |
| |
| #define STORE64_lo(rd, rbase) sw rd, 0(rbase) |
| #define STORE64_hi(rd, rbase) sw rd, 4(rbase) |
| |
| |
| #define LOAD_offThread_exception(rd, rbase) LOAD_RB_OFF(rd, rbase, offThread_exception) |
| #define LOAD_base_offArrayObject_length(rd, rbase) LOAD_RB_OFF(rd, rbase, offArrayObject_length) |
| #define LOAD_base_offClassObject_accessFlags(rd, rbase) LOAD_RB_OFF(rd, rbase, offClassObject_accessFlags) |
| #define LOAD_base_offClassObject_descriptor(rd, rbase) LOAD_RB_OFF(rd, rbase, offClassObject_descriptor) |
| #define LOAD_base_offClassObject_super(rd, rbase) LOAD_RB_OFF(rd, rbase, offClassObject_super) |
| |
| #define LOAD_base_offClassObject_vtable(rd, rbase) LOAD_RB_OFF(rd, rbase, offClassObject_vtable) |
| #define LOAD_base_offClassObject_vtableCount(rd, rbase) LOAD_RB_OFF(rd, rbase, offClassObject_vtableCount) |
| #define LOAD_base_offDvmDex_pResClasses(rd, rbase) LOAD_RB_OFF(rd, rbase, offDvmDex_pResClasses) |
| #define LOAD_base_offDvmDex_pResFields(rd, rbase) LOAD_RB_OFF(rd, rbase, offDvmDex_pResFields) |
| |
| #define LOAD_base_offDvmDex_pResMethods(rd, rbase) LOAD_RB_OFF(rd, rbase, offDvmDex_pResMethods) |
| #define LOAD_base_offDvmDex_pResStrings(rd, rbase) LOAD_RB_OFF(rd, rbase, offDvmDex_pResStrings) |
| #define LOAD_base_offInstField_byteOffset(rd, rbase) LOAD_RB_OFF(rd, rbase, offInstField_byteOffset) |
| #define LOAD_base_offStaticField_value(rd, rbase) LOAD_RB_OFF(rd, rbase, offStaticField_value) |
| #define LOAD_base_offMethod_clazz(rd, rbase) LOAD_RB_OFF(rd, rbase, offMethod_clazz) |
| |
| #define LOAD_base_offMethod_name(rd, rbase) LOAD_RB_OFF(rd, rbase, offMethod_name) |
| #define LOAD_base_offObject_clazz(rd, rbase) LOAD_RB_OFF(rd, rbase, offObject_clazz) |
| |
| #define LOADu2_offMethod_methodIndex(rd, rbase) LOADu2_RB_OFF(rd, rbase, offMethod_methodIndex) |
| |
| |
| #define STORE_offThread_exception(rd, rbase) STORE_RB_OFF(rd, rbase, offThread_exception) |
| |
| |
| #define STACK_STORE(rd, off) sw rd, off(sp) |
| #define STACK_LOAD(rd, off) lw rd, off(sp) |
| #define CREATE_STACK(n) subu sp, sp, n |
| #define DELETE_STACK(n) addu sp, sp, n |
| |
| #define SAVE_RA(offset) STACK_STORE(ra, offset) |
| #define LOAD_RA(offset) STACK_LOAD(ra, offset) |
| |
| #define LOAD_ADDR(dest, addr) la dest, addr |
| #define LOAD_IMM(dest, imm) li dest, imm |
| #define MOVE_REG(dest, src) move dest, src |
| #define RETURN jr ra |
| #define STACK_SIZE 128 |
| |
| #define STACK_OFFSET_ARG04 16 |
| #define STACK_OFFSET_ARG05 20 |
| #define STACK_OFFSET_ARG06 24 |
| #define STACK_OFFSET_ARG07 28 |
| #define STACK_OFFSET_SCR 32 |
| #define STACK_OFFSET_SCRMX 80 |
| #define STACK_OFFSET_GP 84 |
| #define STACK_OFFSET_rFP 112 |
| |
| #define JAL(n) jal n |
| #define BAL(n) bal n |
| |
| #define STACK_STORE_RA() CREATE_STACK(STACK_SIZE); \ |
| STACK_STORE(gp, STACK_OFFSET_GP); \ |
| STACK_STORE(ra, 124) |
| |
| #define STACK_STORE_S0() STACK_STORE_RA(); \ |
| STACK_STORE(s0, 116) |
| |
| #define STACK_STORE_S0S1() STACK_STORE_S0(); \ |
| STACK_STORE(s1, STACK_OFFSET_rFP) |
| |
| #define STACK_LOAD_RA() STACK_LOAD(ra, 124); \ |
| STACK_LOAD(gp, STACK_OFFSET_GP); \ |
| DELETE_STACK(STACK_SIZE) |
| |
| #define STACK_LOAD_S0() STACK_LOAD(s0, 116); \ |
| STACK_LOAD_RA() |
| |
| #define STACK_LOAD_S0S1() STACK_LOAD(s1, STACK_OFFSET_rFP); \ |
| STACK_LOAD_S0() |
| |
| #define STACK_STORE_FULL() CREATE_STACK(STACK_SIZE); \ |
| STACK_STORE(ra, 124); \ |
| STACK_STORE(fp, 120); \ |
| STACK_STORE(s0, 116); \ |
| STACK_STORE(s1, STACK_OFFSET_rFP); \ |
| STACK_STORE(s2, 108); \ |
| STACK_STORE(s3, 104); \ |
| STACK_STORE(s4, 100); \ |
| STACK_STORE(s5, 96); \ |
| STACK_STORE(s6, 92); \ |
| STACK_STORE(s7, 88); |
| |
| #define STACK_LOAD_FULL() STACK_LOAD(gp, STACK_OFFSET_GP); \ |
| STACK_LOAD(s7, 88); \ |
| STACK_LOAD(s6, 92); \ |
| STACK_LOAD(s5, 96); \ |
| STACK_LOAD(s4, 100); \ |
| STACK_LOAD(s3, 104); \ |
| STACK_LOAD(s2, 108); \ |
| STACK_LOAD(s1, STACK_OFFSET_rFP); \ |
| STACK_LOAD(s0, 116); \ |
| STACK_LOAD(fp, 120); \ |
| STACK_LOAD(ra, 124); \ |
| DELETE_STACK(STACK_SIZE) |
| |
| /* |
| * first 8 words are reserved for function calls |
| * Maximum offset is STACK_OFFSET_SCRMX-STACK_OFFSET_SCR |
| */ |
| #define SCRATCH_STORE(r,off) \ |
| STACK_STORE(r, STACK_OFFSET_SCR+off); |
| #define SCRATCH_LOAD(r,off) \ |
| STACK_LOAD(r, STACK_OFFSET_SCR+off); |
| |
| #if defined(WITH_JIT) |
| #include "../common/jit-config.h" |
| #endif |