Home | History | Annotate | Download | only in armv5te
      1 /*
      2  * Copyright (C) 2008 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  * ARMv5 definitions and declarations.
     19  */
     20 
     21 /*
     22 ARM EABI general notes:
     23 
     24 r0-r3 hold first 4 args to a method; they are not preserved across method calls
     25 r4-r8 are available for general use
     26 r9 is given special treatment in some situations, but not for us
     27 r10 (sl) seems to be generally available
     28 r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
     29 r12 (ip) is scratch -- not preserved across method calls
     30 r13 (sp) should be managed carefully in case a signal arrives
     31 r14 (lr) must be preserved
     32 r15 (pc) can be tinkered with directly
     33 
     34 r0 holds returns of <= 4 bytes
     35 r0-r1 hold returns of 8 bytes, low word in r0
     36 
     37 Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
     38 is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
     39 s0-s15 (d0-d7, q0-a3) do not need to be.
     40 
     41 Stack is "full descending".  Only the arguments that don't fit in the first 4
     42 registers are placed on the stack.  "sp" points at the first stacked argument
     43 (i.e. the 5th arg).
     44 
     45 VFP: single-precision results in s0, double-precision results in d0.
     46 
     47 In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
     48 64-bit quantities (long long, double) must be 64-bit aligned.
     49 */
     50 
     51 /*
     52 Mterp and ARM notes:
     53 
     54 The following registers have fixed assignments:
     55 
     56   reg nick      purpose
     57   r4  rPC       interpreted program counter, used for fetching instructions
     58   r5  rFP       interpreted frame pointer, used for accessing locals and args
     59   r6  rSELF     self (Thread) pointer
     60   r7  rINST     first 16-bit code unit of current instruction
     61   r8  rIBASE    interpreted instruction base pointer, used for computed goto
     62 
     63 Macros are provided for common operations.  Each macro MUST emit only
     64 one instruction to make instruction-counting easier.  They MUST NOT alter
     65 unspecified registers or condition codes.
     66 */
     67 
     68 /* single-purpose registers, given names for clarity */
     69 #define rPC     r4
     70 #define rFP     r5
     71 #define rSELF   r6
     72 #define rINST   r7
     73 #define rIBASE  r8
     74 
     75 /* save/restore the PC and/or FP from the thread struct */
     76 #define LOAD_PC_FROM_SELF()     ldr     rPC, [rSELF, #offThread_pc]
     77 #define SAVE_PC_TO_SELF()       str     rPC, [rSELF, #offThread_pc]
     78 #define LOAD_FP_FROM_SELF()     ldr     rFP, [rSELF, #offThread_curFrame]
     79 #define SAVE_FP_TO_SELF()       str     rFP, [rSELF, #offThread_curFrame]
     80 #define LOAD_PC_FP_FROM_SELF()  ldmia   rSELF, {rPC, rFP}
     81 #define SAVE_PC_FP_TO_SELF()    stmia   rSELF, {rPC, rFP}
     82 
     83 /*
     84  * "export" the PC to the stack frame, f/b/o future exception objects.  Must
     85  * be done *before* something throws.
     86  *
     87  * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
     88  * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
     89  *
     90  * It's okay to do this more than once.
     91  */
     92 #define EXPORT_PC() \
     93     str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
     94 
     95 /*
     96  * Given a frame pointer, find the stack save area.
     97  *
     98  * In C this is "((StackSaveArea*)(_fp) -1)".
     99  */
    100 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
    101     sub     _reg, _fpreg, #sizeofStackSaveArea
    102 
    103 /*
    104  * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
    105  */
    106 #define FETCH_INST()            ldrh    rINST, [rPC]
    107 
    108 /*
    109  * Fetch the next instruction from the specified offset.  Advances rPC
    110  * to point to the next instruction.  "_count" is in 16-bit code units.
    111  *
    112  * Because of the limited size of immediate constants on ARM, this is only
    113  * suitable for small forward movements (i.e. don't try to implement "goto"
    114  * with this).
    115  *
    116  * This must come AFTER anything that can throw an exception, or the
    117  * exception catch may miss.  (This also implies that it must come after
    118  * EXPORT_PC().)
    119  */
    120 #define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #((_count)*2)]!
    121 
    122 /*
    123  * The operation performed here is similar to FETCH_ADVANCE_INST, except the
    124  * src and dest registers are parameterized (not hard-wired to rPC and rINST).
    125  */
    126 #define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
    127         ldrh    _dreg, [_sreg, #((_count)*2)]!
    128 
    129 /*
    130  * Fetch the next instruction from an offset specified by _reg.  Updates
    131  * rPC to point to the next instruction.  "_reg" must specify the distance
    132  * in bytes, *not* 16-bit code units, and may be a signed value.
    133  *
    134  * We want to write "ldrh rINST, [rPC, _reg, lsl #1]!", but some of the
    135  * bits that hold the shift distance are used for the half/byte/sign flags.
    136  * In some cases we can pre-double _reg for free, so we require a byte offset
    137  * here.
    138  */
    139 #define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
    140 
    141 /*
    142  * Fetch a half-word code unit from an offset past the current PC.  The
    143  * "_count" value is in 16-bit code units.  Does not advance rPC.
    144  *
    145  * The "_S" variant works the same but treats the value as signed.
    146  */
    147 #define FETCH(_reg, _count)     ldrh    _reg, [rPC, #((_count)*2)]
    148 #define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #((_count)*2)]
    149 
    150 /*
    151  * Fetch one byte from an offset past the current PC.  Pass in the same
    152  * "_count" as you would for FETCH, and an additional 0/1 indicating which
    153  * byte of the halfword you want (lo/hi).
    154  */
    155 #define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #((_count)*2+(_byte))]
    156 
    157 /*
    158  * Put the instruction's opcode field into the specified register.
    159  */
    160 #define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
    161 
    162 /*
    163  * Put the prefetched instruction's opcode field into the specified register.
    164  */
    165 #define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
    166 
    167 /*
    168  * Begin executing the opcode in _reg.  Because this only jumps within the
    169  * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
    170  */
    171 #define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #${handler_size_bits}
    172 #define GOTO_OPCODE_BASE(_base,_reg)  add     pc, _base, _reg, lsl #${handler_size_bits}
    173 #define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #${handler_size_bits}
    174 #define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #${handler_size_bits}
    175 
    176 /*
    177  * Get/set the 32-bit value from a Dalvik register.
    178  */
    179 #define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
    180 #define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
    181 
    182 /*
    183  * Convert a virtual register index into an address.
    184  */
    185 #define VREG_INDEX_TO_ADDR(_reg, _vreg) \
    186         add     _reg, rFP, _vreg, lsl #2
    187 
    188 /*
    189  * This is a #include, not a %include, because we want the C pre-processor
    190  * to expand the macros into assembler assignment statements.
    191  */
    192 #include "../common/asm-constants.h"
    193 
    194 #if defined(WITH_JIT)
    195 #include "../common/jit-config.h"
    196 #endif
    197