Home | History | Annotate | Download | only in mips
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18   Art assembly interpreter notes:
     19 
     20   First validate assembly code by implementing ExecuteXXXImpl() style body (doesn't
     21   handle invoke, allows higher-level code to create frame & shadow frame.
     22 
     23   Once that's working, support direct entry code & eliminate shadow frame (and
     24   excess locals allocation.
     25 
     26   Some (hopefully) temporary ugliness.  We'll treat rFP as pointing to the
     27   base of the vreg array within the shadow frame.  Access the other fields,
     28   dex_pc_, method_ and number_of_vregs_ via negative offsets.  For now, we'll continue
     29   the shadow frame mechanism of double-storing object references - via rFP &
     30   number_of_vregs_.
     31 
     32  */
     33 
     34 #include "asm_support.h"
     35 
     36 #if (__mips==32) && (__mips_isa_rev>=2)
     37 #define MIPS32REVGE2    /* mips32r2 and greater */
     38 #if (__mips==32) && (__mips_isa_rev>=5)
     39 #define FPU64           /* 64 bit FPU */
     40 #if (__mips==32) && (__mips_isa_rev>=6)
     41 #define MIPS32REVGE6    /* mips32r6 and greater */
     42 #endif
     43 #endif
     44 #endif
     45 
     46 /* MIPS definitions and declarations
     47 
     48    reg  nick      purpose
     49    s0   rPC       interpreted program counter, used for fetching instructions
     50    s1   rFP       interpreted frame pointer, used for accessing locals and args
     51    s2   rSELF     self (Thread) pointer
     52    s3   rIBASE    interpreted instruction base pointer, used for computed goto
     53    s4   rINST     first 16-bit code unit of current instruction
     54    s5   rOBJ      object pointer
     55    s6   rREFS     base of object references in shadow frame (ideally, we'll get rid of this later).
     56    s7   rTEMP     used as temp storage that can survive a function call
     57    s8   rPROFILE  branch profiling countdown
     58 
     59 */
     60 
     61 /* single-purpose registers, given names for clarity */
     62 #define rPC s0
     63 #define rFP s1
     64 #define rSELF s2
     65 #define rIBASE s3
     66 #define rINST s4
     67 #define rOBJ s5
     68 #define rREFS s6
     69 #define rTEMP s7
     70 #define rPROFILE s8
     71 
     72 #define rARG0 a0
     73 #define rARG1 a1
     74 #define rARG2 a2
     75 #define rARG3 a3
     76 #define rRESULT0 v0
     77 #define rRESULT1 v1
     78 
     79 /* GP register definitions */
     80 #define zero    $$0      /* always zero */
     81 #define AT      $$at     /* assembler temp */
     82 #define v0      $$2      /* return value */
     83 #define v1      $$3
     84 #define a0      $$4      /* argument registers */
     85 #define a1      $$5
     86 #define a2      $$6
     87 #define a3      $$7
     88 #define t0      $$8      /* temp registers (not saved across subroutine calls) */
     89 #define t1      $$9
     90 #define t2      $$10
     91 #define t3      $$11
     92 #define t4      $$12
     93 #define t5      $$13
     94 #define t6      $$14
     95 #define t7      $$15
     96 #define ta0     $$12     /* alias */
     97 #define ta1     $$13
     98 #define ta2     $$14
     99 #define ta3     $$15
    100 #define s0      $$16     /* saved across subroutine calls (callee saved) */
    101 #define s1      $$17
    102 #define s2      $$18
    103 #define s3      $$19
    104 #define s4      $$20
    105 #define s5      $$21
    106 #define s6      $$22
    107 #define s7      $$23
    108 #define t8      $$24     /* two more temp registers */
    109 #define t9      $$25
    110 #define k0      $$26     /* kernel temporary */
    111 #define k1      $$27
    112 #define gp      $$28     /* global pointer */
    113 #define sp      $$29     /* stack pointer */
    114 #define s8      $$30     /* one more callee saved */
    115 #define ra      $$31     /* return address */
    116 
    117 /* FP register definitions */
    118 #define fv0    $$f0
    119 #define fv0f   $$f1
    120 #define fv1    $$f2
    121 #define fv1f   $$f3
    122 #define fa0    $$f12
    123 #define fa0f   $$f13
    124 #define fa1    $$f14
    125 #define fa1f   $$f15
    126 #define ft0    $$f4
    127 #define ft0f   $$f5
    128 #define ft1    $$f6
    129 #define ft1f   $$f7
    130 #define ft2    $$f8
    131 #define ft2f   $$f9
    132 #define ft3    $$f10
    133 #define ft3f   $$f11
    134 #define ft4    $$f16
    135 #define ft4f   $$f17
    136 #define ft5    $$f18
    137 #define ft5f   $$f19
    138 #define fs0    $$f20
    139 #define fs0f   $$f21
    140 #define fs1    $$f22
    141 #define fs1f   $$f23
    142 #define fs2    $$f24
    143 #define fs2f   $$f25
    144 #define fs3    $$f26
    145 #define fs3f   $$f27
    146 #define fs4    $$f28
    147 #define fs4f   $$f29
    148 #define fs5    $$f30
    149 #define fs5f   $$f31
    150 
    151 #ifndef MIPS32REVGE6
    152 #define fcc0   $$fcc0
    153 #define fcc1   $$fcc1
    154 #endif
    155 
    156 #ifdef MIPS32REVGE2
    157 #define SEB(rd, rt) \
    158     seb       rd, rt
    159 #define SEH(rd, rt) \
    160     seh       rd, rt
    161 #define INSERT_HIGH_HALF(rd_lo, rt_hi) \
    162     ins       rd_lo, rt_hi, 16, 16
    163 #else
    164 #define SEB(rd, rt) \
    165     sll       rd, rt, 24; \
    166     sra       rd, rd, 24
    167 #define SEH(rd, rt) \
    168     sll       rd, rt, 16; \
    169     sra       rd, rd, 16
    170 /* Clobbers rt_hi on pre-R2. */
    171 #define INSERT_HIGH_HALF(rd_lo, rt_hi) \
    172     sll       rt_hi, rt_hi, 16; \
    173     or        rd_lo, rt_hi
    174 #endif
    175 
    176 #ifdef FPU64
    177 #define MOVE_TO_FPU_HIGH(r, flo, fhi) \
    178     mthc1     r, flo
    179 #else
    180 #define MOVE_TO_FPU_HIGH(r, flo, fhi) \
    181     mtc1      r, fhi
    182 #endif
    183 
    184 #ifdef MIPS32REVGE6
    185 #define JR(rt) \
    186     jic       rt, 0
    187 #define LSA(rd, rs, rt, sa) \
    188     .if sa; \
    189     lsa       rd, rs, rt, sa; \
    190     .else; \
    191     addu      rd, rs, rt; \
    192     .endif
    193 #else
    194 #define JR(rt) \
    195     jalr      zero, rt
    196 #define LSA(rd, rs, rt, sa) \
    197     .if sa; \
    198     .set      push; \
    199     .set      noat; \
    200     sll       AT, rs, sa; \
    201     addu      rd, AT, rt; \
    202     .set      pop; \
    203     .else; \
    204     addu      rd, rs, rt; \
    205     .endif
    206 #endif
    207 
    208 /*
    209  * Instead of holding a pointer to the shadow frame, we keep rFP at the base of the vregs.  So,
    210  * to access other shadow frame fields, we need to use a backwards offset.  Define those here.
    211  */
    212 #define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET)
    213 #define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET)
    214 #define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET)
    215 #define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET)
    216 #define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET)
    217 #define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET)
    218 #define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET)
    219 #define OFF_FP_CODE_ITEM OFF_FP(SHADOWFRAME_CODE_ITEM_OFFSET)
    220 #define OFF_FP_SHADOWFRAME OFF_FP(0)
    221 
    222 #define MTERP_PROFILE_BRANCHES 1
    223 #define MTERP_LOGGING 0
    224 
    225 /*
    226  * "export" the PC to dex_pc field in the shadow frame, f/b/o future exception objects.  Must
    227  * be done *before* something throws.
    228  *
    229  * It's okay to do this more than once.
    230  *
    231  * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped
    232  * dex byte codes.  However, the rest of the runtime expects dex pc to be an instruction
    233  * offset into the code_items_[] array.  For effiency, we will "export" the
    234  * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC
    235  * to convert to a dex pc when needed.
    236  */
    237 #define EXPORT_PC() \
    238     sw        rPC, OFF_FP_DEX_PC_PTR(rFP)
    239 
    240 #define EXPORT_DEX_PC(tmp) \
    241     lw        tmp, OFF_FP_CODE_ITEM(rFP); \
    242     sw        rPC, OFF_FP_DEX_PC_PTR(rFP); \
    243     addu      tmp, CODEITEM_INSNS_OFFSET; \
    244     subu      tmp, rPC, tmp; \
    245     sra       tmp, tmp, 1; \
    246     sw        tmp, OFF_FP_DEX_PC(rFP)
    247 
    248 /*
    249  * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
    250  */
    251 #define FETCH_INST() lhu rINST, (rPC)
    252 
    253 /*
    254  * Fetch the next instruction from the specified offset.  Advances rPC
    255  * to point to the next instruction.  "_count" is in 16-bit code units.
    256  *
    257  * This must come AFTER anything that can throw an exception, or the
    258  * exception catch may miss.  (This also implies that it must come after
    259  * EXPORT_PC().)
    260  */
    261 #define FETCH_ADVANCE_INST(_count) \
    262     lhu       rINST, ((_count)*2)(rPC); \
    263     addu      rPC, rPC, ((_count) * 2)
    264 
    265 /*
    266  * Similar to FETCH_ADVANCE_INST, but does not update rPC.  Used to load
    267  * rINST ahead of possible exception point.  Be sure to manually advance rPC
    268  * later.
    269  */
    270 #define PREFETCH_INST(_count) lhu rINST, ((_count)*2)(rPC)
    271 
    272 /* Advance rPC by some number of code units. */
    273 #define ADVANCE(_count) addu rPC, rPC, ((_count) * 2)
    274 
    275 /*
    276  * Fetch the next instruction from an offset specified by rd.  Updates
    277  * rPC to point to the next instruction.  "rd" must specify the distance
    278  * in bytes, *not* 16-bit code units, and may be a signed value.
    279  */
    280 #define FETCH_ADVANCE_INST_RB(rd) \
    281     addu      rPC, rPC, rd; \
    282     lhu       rINST, (rPC)
    283 
    284 /*
    285  * Fetch a half-word code unit from an offset past the current PC.  The
    286  * "_count" value is in 16-bit code units.  Does not advance rPC.
    287  *
    288  * The "_S" variant works the same but treats the value as signed.
    289  */
    290 #define FETCH(rd, _count) lhu rd, ((_count) * 2)(rPC)
    291 #define FETCH_S(rd, _count) lh rd, ((_count) * 2)(rPC)
    292 
    293 /*
    294  * Fetch one byte from an offset past the current PC.  Pass in the same
    295  * "_count" as you would for FETCH, and an additional 0/1 indicating which
    296  * byte of the halfword you want (lo/hi).
    297  */
    298 #define FETCH_B(rd, _count, _byte) lbu rd, ((_count) * 2 + _byte)(rPC)
    299 
    300 /*
    301  * Put the instruction's opcode field into the specified register.
    302  */
    303 #define GET_INST_OPCODE(rd) and rd, rINST, 0xFF
    304 
    305 /*
    306  * Transform opcode into branch target address.
    307  */
    308 #define GET_OPCODE_TARGET(rd) \
    309     sll       rd, rd, ${handler_size_bits}; \
    310     addu      rd, rIBASE, rd
    311 
    312 /*
    313  * Begin executing the opcode in rd.
    314  */
    315 #define GOTO_OPCODE(rd) \
    316     GET_OPCODE_TARGET(rd); \
    317     JR(rd)
    318 
    319 /*
    320  * Get/set the 32-bit value from a Dalvik register.
    321  */
    322 #define GET_VREG(rd, rix) LOAD_eas2(rd, rFP, rix)
    323 
    324 #define GET_VREG_F(rd, rix) \
    325     .set noat; \
    326     EAS2(AT, rFP, rix); \
    327     l.s       rd, (AT); \
    328     .set at
    329 
    330 #ifdef MIPS32REVGE6
    331 #define SET_VREG(rd, rix) \
    332     lsa       t8, rix, rFP, 2; \
    333     sw        rd, 0(t8); \
    334     lsa       t8, rix, rREFS, 2; \
    335     sw        zero, 0(t8)
    336 #else
    337 #define SET_VREG(rd, rix) \
    338     .set noat; \
    339     sll       AT, rix, 2; \
    340     addu      t8, rFP, AT; \
    341     sw        rd, 0(t8); \
    342     addu      t8, rREFS, AT; \
    343     .set at; \
    344     sw        zero, 0(t8)
    345 #endif
    346 
    347 #ifdef MIPS32REVGE6
    348 #define SET_VREG_OBJECT(rd, rix) \
    349     lsa       t8, rix, rFP, 2; \
    350     sw        rd, 0(t8); \
    351     lsa       t8, rix, rREFS, 2; \
    352     sw        rd, 0(t8)
    353 #else
    354 #define SET_VREG_OBJECT(rd, rix) \
    355     .set noat; \
    356     sll       AT, rix, 2; \
    357     addu      t8, rFP, AT; \
    358     sw        rd, 0(t8); \
    359     addu      t8, rREFS, AT; \
    360     .set at; \
    361     sw        rd, 0(t8)
    362 #endif
    363 
    364 #ifdef MIPS32REVGE6
    365 #define SET_VREG64(rlo, rhi, rix) \
    366     lsa       t8, rix, rFP, 2; \
    367     sw        rlo, 0(t8); \
    368     sw        rhi, 4(t8); \
    369     lsa       t8, rix, rREFS, 2; \
    370     sw        zero, 0(t8); \
    371     sw        zero, 4(t8)
    372 #else
    373 #define SET_VREG64(rlo, rhi, rix) \
    374     .set noat; \
    375     sll       AT, rix, 2; \
    376     addu      t8, rFP, AT; \
    377     sw        rlo, 0(t8); \
    378     sw        rhi, 4(t8); \
    379     addu      t8, rREFS, AT; \
    380     .set at; \
    381     sw        zero, 0(t8); \
    382     sw        zero, 4(t8)
    383 #endif
    384 
    385 #ifdef MIPS32REVGE6
    386 #define SET_VREG_F(rd, rix) \
    387     lsa       t8, rix, rFP, 2; \
    388     s.s       rd, 0(t8); \
    389     lsa       t8, rix, rREFS, 2; \
    390     sw        zero, 0(t8)
    391 #else
    392 #define SET_VREG_F(rd, rix) \
    393     .set noat; \
    394     sll       AT, rix, 2; \
    395     addu      t8, rFP, AT; \
    396     s.s       rd, 0(t8); \
    397     addu      t8, rREFS, AT; \
    398     .set at; \
    399     sw        zero, 0(t8)
    400 #endif
    401 
    402 #ifdef MIPS32REVGE6
    403 #define SET_VREG64_F(rlo, rhi, rix) \
    404     lsa       t8, rix, rFP, 2; \
    405     .set noat; \
    406     mfhc1     AT, rlo; \
    407     s.s       rlo, 0(t8); \
    408     sw        AT, 4(t8); \
    409     .set at; \
    410     lsa       t8, rix, rREFS, 2; \
    411     sw        zero, 0(t8); \
    412     sw        zero, 4(t8)
    413 #elif defined(FPU64)
    414 #define SET_VREG64_F(rlo, rhi, rix) \
    415     .set noat; \
    416     sll       AT, rix, 2; \
    417     addu      t8, rREFS, AT; \
    418     sw        zero, 0(t8); \
    419     sw        zero, 4(t8); \
    420     addu      t8, rFP, AT; \
    421     mfhc1     AT, rlo; \
    422     sw        AT, 4(t8); \
    423     .set at; \
    424     s.s       rlo, 0(t8)
    425 #else
    426 #define SET_VREG64_F(rlo, rhi, rix) \
    427     .set noat; \
    428     sll       AT, rix, 2; \
    429     addu      t8, rFP, AT; \
    430     s.s       rlo, 0(t8); \
    431     s.s       rhi, 4(t8); \
    432     addu      t8, rREFS, AT; \
    433     .set at; \
    434     sw        zero, 0(t8); \
    435     sw        zero, 4(t8)
    436 #endif
    437 
    438 /* Combination of the SET_VREG and GOTO_OPCODE functions to save 1 instruction */
    439 #ifdef MIPS32REVGE6
    440 #define SET_VREG_GOTO(rd, rix, dst) \
    441     .set noreorder; \
    442     GET_OPCODE_TARGET(dst); \
    443     lsa       t8, rix, rFP, 2; \
    444     sw        rd, 0(t8); \
    445     lsa       t8, rix, rREFS, 2; \
    446     jalr      zero, dst; \
    447     sw        zero, 0(t8); \
    448     .set reorder
    449 #else
    450 #define SET_VREG_GOTO(rd, rix, dst) \
    451     .set noreorder; \
    452     GET_OPCODE_TARGET(dst); \
    453     .set noat; \
    454     sll       AT, rix, 2; \
    455     addu      t8, rFP, AT; \
    456     sw        rd, 0(t8); \
    457     addu      t8, rREFS, AT; \
    458     .set at; \
    459     jalr      zero, dst; \
    460     sw        zero, 0(t8); \
    461     .set reorder
    462 #endif
    463 
    464 /* Combination of the SET_VREG_OBJECT and GOTO_OPCODE functions to save 1 instruction */
    465 #ifdef MIPS32REVGE6
    466 #define SET_VREG_OBJECT_GOTO(rd, rix, dst) \
    467     .set noreorder; \
    468     GET_OPCODE_TARGET(dst); \
    469     lsa       t8, rix, rFP, 2; \
    470     sw        rd, 0(t8); \
    471     lsa       t8, rix, rREFS, 2; \
    472     jalr      zero, dst; \
    473     sw        rd, 0(t8); \
    474     .set reorder
    475 #else
    476 #define SET_VREG_OBJECT_GOTO(rd, rix, dst) \
    477     .set noreorder; \
    478     GET_OPCODE_TARGET(dst); \
    479     .set noat; \
    480     sll       AT, rix, 2; \
    481     addu      t8, rFP, AT; \
    482     sw        rd, 0(t8); \
    483     addu      t8, rREFS, AT; \
    484     .set at; \
    485     jalr      zero, dst; \
    486     sw        rd, 0(t8); \
    487     .set reorder
    488 #endif
    489 
    490 /* Combination of the SET_VREG64 and GOTO_OPCODE functions to save 1 instruction */
    491 #ifdef MIPS32REVGE6
    492 #define SET_VREG64_GOTO(rlo, rhi, rix, dst) \
    493     .set noreorder; \
    494     GET_OPCODE_TARGET(dst); \
    495     lsa       t8, rix, rFP, 2; \
    496     sw        rlo, 0(t8); \
    497     sw        rhi, 4(t8); \
    498     lsa       t8, rix, rREFS, 2; \
    499     sw        zero, 0(t8); \
    500     jalr      zero, dst; \
    501     sw        zero, 4(t8); \
    502     .set reorder
    503 #else
    504 #define SET_VREG64_GOTO(rlo, rhi, rix, dst) \
    505     .set noreorder; \
    506     GET_OPCODE_TARGET(dst); \
    507     .set noat; \
    508     sll       AT, rix, 2; \
    509     addu      t8, rFP, AT; \
    510     sw        rlo, 0(t8); \
    511     sw        rhi, 4(t8); \
    512     addu      t8, rREFS, AT; \
    513     .set at; \
    514     sw        zero, 0(t8); \
    515     jalr      zero, dst; \
    516     sw        zero, 4(t8); \
    517     .set reorder
    518 #endif
    519 
    520 /* Combination of the SET_VREG_F and GOTO_OPCODE functions to save 1 instruction */
    521 #ifdef MIPS32REVGE6
    522 #define SET_VREG_F_GOTO(rd, rix, dst) \
    523     .set noreorder; \
    524     GET_OPCODE_TARGET(dst); \
    525     lsa       t8, rix, rFP, 2; \
    526     s.s       rd, 0(t8); \
    527     lsa       t8, rix, rREFS, 2; \
    528     jalr      zero, dst; \
    529     sw        zero, 0(t8); \
    530     .set reorder
    531 #else
    532 #define SET_VREG_F_GOTO(rd, rix, dst) \
    533     .set noreorder; \
    534     GET_OPCODE_TARGET(dst); \
    535     .set noat; \
    536     sll       AT, rix, 2; \
    537     addu      t8, rFP, AT; \
    538     s.s       rd, 0(t8); \
    539     addu      t8, rREFS, AT; \
    540     .set at; \
    541     jalr      zero, dst; \
    542     sw        zero, 0(t8); \
    543     .set reorder
    544 #endif
    545 
    546 /* Combination of the SET_VREG64_F and GOTO_OPCODE functions to save 1 instruction */
    547 #ifdef MIPS32REVGE6
    548 #define SET_VREG64_F_GOTO(rlo, rhi, rix, dst) \
    549     .set noreorder; \
    550     GET_OPCODE_TARGET(dst); \
    551     lsa       t8, rix, rFP, 2; \
    552     .set noat; \
    553     mfhc1     AT, rlo; \
    554     s.s       rlo, 0(t8); \
    555     sw        AT, 4(t8); \
    556     .set at; \
    557     lsa       t8, rix, rREFS, 2; \
    558     sw        zero, 0(t8); \
    559     jalr      zero, dst; \
    560     sw        zero, 4(t8); \
    561     .set reorder
    562 #elif defined(FPU64)
    563 #define SET_VREG64_F_GOTO(rlo, rhi, rix, dst) \
    564     .set noreorder; \
    565     GET_OPCODE_TARGET(dst); \
    566     .set noat; \
    567     sll       AT, rix, 2; \
    568     addu      t8, rREFS, AT; \
    569     sw        zero, 0(t8); \
    570     sw        zero, 4(t8); \
    571     addu      t8, rFP, AT; \
    572     mfhc1     AT, rlo; \
    573     sw        AT, 4(t8); \
    574     .set at; \
    575     jalr      zero, dst; \
    576     s.s       rlo, 0(t8); \
    577     .set reorder
    578 #else
    579 #define SET_VREG64_F_GOTO(rlo, rhi, rix, dst) \
    580     .set noreorder; \
    581     GET_OPCODE_TARGET(dst); \
    582     .set noat; \
    583     sll       AT, rix, 2; \
    584     addu      t8, rFP, AT; \
    585     s.s       rlo, 0(t8); \
    586     s.s       rhi, 4(t8); \
    587     addu      t8, rREFS, AT; \
    588     .set at; \
    589     sw        zero, 0(t8); \
    590     jalr      zero, dst; \
    591     sw        zero, 4(t8); \
    592     .set reorder
    593 #endif
    594 
    595 #define GET_OPA(rd) srl rd, rINST, 8
    596 #ifdef MIPS32REVGE2
    597 #define GET_OPA4(rd) ext rd, rINST, 8, 4
    598 #else
    599 #define GET_OPA4(rd) GET_OPA(rd); and rd, 0xf
    600 #endif
    601 #define GET_OPB(rd) srl rd, rINST, 12
    602 
    603 /*
    604  * Form an Effective Address rd = rbase + roff<<shift;
    605  * Uses reg AT on pre-R6.
    606  */
    607 #define EASN(rd, rbase, roff, shift) LSA(rd, roff, rbase, shift)
    608 
    609 #define EAS1(rd, rbase, roff) EASN(rd, rbase, roff, 1)
    610 #define EAS2(rd, rbase, roff) EASN(rd, rbase, roff, 2)
    611 #define EAS3(rd, rbase, roff) EASN(rd, rbase, roff, 3)
    612 #define EAS4(rd, rbase, roff) EASN(rd, rbase, roff, 4)
    613 
    614 #define LOAD_eas2(rd, rbase, roff) \
    615     .set noat; \
    616     EAS2(AT, rbase, roff); \
    617     lw        rd, 0(AT); \
    618     .set at
    619 
    620 #define STORE_eas2(rd, rbase, roff) \
    621     .set noat; \
    622     EAS2(AT, rbase, roff); \
    623     sw        rd, 0(AT); \
    624     .set at
    625 
    626 #define LOAD_RB_OFF(rd, rbase, off) lw rd, off(rbase)
    627 #define STORE_RB_OFF(rd, rbase, off) sw rd, off(rbase)
    628 
    629 #define STORE64_off(rlo, rhi, rbase, off) \
    630     sw        rlo, off(rbase); \
    631     sw        rhi, (off+4)(rbase)
    632 #define LOAD64_off(rlo, rhi, rbase, off) \
    633     lw        rlo, off(rbase); \
    634     lw        rhi, (off+4)(rbase)
    635 
    636 #define STORE64(rlo, rhi, rbase) STORE64_off(rlo, rhi, rbase, 0)
    637 #define LOAD64(rlo, rhi, rbase) LOAD64_off(rlo, rhi, rbase, 0)
    638 
    639 #ifdef FPU64
    640 #define STORE64_off_F(rlo, rhi, rbase, off) \
    641     s.s       rlo, off(rbase); \
    642     .set noat; \
    643     mfhc1     AT, rlo; \
    644     sw        AT, (off+4)(rbase); \
    645     .set at
    646 #define LOAD64_off_F(rlo, rhi, rbase, off) \
    647     l.s       rlo, off(rbase); \
    648     .set noat; \
    649     lw        AT, (off+4)(rbase); \
    650     mthc1     AT, rlo; \
    651     .set at
    652 #else
    653 #define STORE64_off_F(rlo, rhi, rbase, off) \
    654     s.s       rlo, off(rbase); \
    655     s.s       rhi, (off+4)(rbase)
    656 #define LOAD64_off_F(rlo, rhi, rbase, off) \
    657     l.s       rlo, off(rbase); \
    658     l.s       rhi, (off+4)(rbase)
    659 #endif
    660 
    661 #define STORE64_F(rlo, rhi, rbase) STORE64_off_F(rlo, rhi, rbase, 0)
    662 #define LOAD64_F(rlo, rhi, rbase) LOAD64_off_F(rlo, rhi, rbase, 0)
    663 
    664 
    665 #define LOAD_base_offMirrorArray_length(rd, rbase) LOAD_RB_OFF(rd, rbase, MIRROR_ARRAY_LENGTH_OFFSET)
    666 
    667 #define STACK_STORE(rd, off) sw rd, off(sp)
    668 #define STACK_LOAD(rd, off) lw rd, off(sp)
    669 #define CREATE_STACK(n) subu sp, sp, n
    670 #define DELETE_STACK(n) addu sp, sp, n
    671 
    672 #define LOAD_ADDR(dest, addr) la dest, addr
    673 #define LOAD_IMM(dest, imm) li dest, imm
    674 #define MOVE_REG(dest, src) move dest, src
    675 #define STACK_SIZE 128
    676 
    677 #define STACK_OFFSET_ARG04 16
    678 #define STACK_OFFSET_ARG05 20
    679 #define STACK_OFFSET_ARG06 24
    680 #define STACK_OFFSET_ARG07 28
    681 #define STACK_OFFSET_GP    84
    682 
    683 #define JAL(n) jal n
    684 #define BAL(n) bal n
    685 
    686 /*
    687  * FP register usage restrictions:
    688  * 1) We don't use the callee save FP registers so we don't have to save them.
    689  * 2) We don't use the odd FP registers so we can share code with mips32r6.
    690  */
    691 #define STACK_STORE_FULL() CREATE_STACK(STACK_SIZE); \
    692     STACK_STORE(ra, 124); \
    693     STACK_STORE(s8, 120); \
    694     STACK_STORE(s0, 116); \
    695     STACK_STORE(s1, 112); \
    696     STACK_STORE(s2, 108); \
    697     STACK_STORE(s3, 104); \
    698     STACK_STORE(s4, 100); \
    699     STACK_STORE(s5, 96); \
    700     STACK_STORE(s6, 92); \
    701     STACK_STORE(s7, 88);
    702 
    703 #define STACK_LOAD_FULL() STACK_LOAD(gp, STACK_OFFSET_GP); \
    704     STACK_LOAD(s7, 88); \
    705     STACK_LOAD(s6, 92); \
    706     STACK_LOAD(s5, 96); \
    707     STACK_LOAD(s4, 100); \
    708     STACK_LOAD(s3, 104); \
    709     STACK_LOAD(s2, 108); \
    710     STACK_LOAD(s1, 112); \
    711     STACK_LOAD(s0, 116); \
    712     STACK_LOAD(s8, 120); \
    713     STACK_LOAD(ra, 124); \
    714     DELETE_STACK(STACK_SIZE)
    715 
    716 #define REFRESH_IBASE() \
    717     lw        rIBASE, THREAD_CURRENT_IBASE_OFFSET(rSELF)
    718 
    719 /* Constants for float/double_to_int/long conversions */
    720 #define INT_MIN                 0x80000000
    721 #define INT_MIN_AS_FLOAT        0xCF000000
    722 #define INT_MIN_AS_DOUBLE_HIGH  0xC1E00000
    723 #define LONG_MIN_HIGH           0x80000000
    724 #define LONG_MIN_AS_FLOAT       0xDF000000
    725 #define LONG_MIN_AS_DOUBLE_HIGH 0xC3E00000
    726