Home | History | Annotate | Download | only in x86
      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  * 32-bit x86 definitions and declarations.
     18  */
     19 
     20 /*
     21 386 ABI general notes:
     22 
     23 Caller save set:
     24    eax, edx, ecx, st(0)-st(7)
     25 Callee save set:
     26    ebx, esi, edi, ebp
     27 Return regs:
     28    32-bit in eax
     29    64-bit in edx:eax (low-order 32 in eax)
     30    fp on top of fp stack st(0)
     31 
     32 Parameters passed on stack, pushed right-to-left.  On entry to target, first
     33 parm is at 4(%esp).  Traditional entry code is:
     34 
     35 functEntry:
     36     push    %ebp             # save old frame pointer
     37     mov     %ebp,%esp        # establish new frame pointer
     38     sub     FrameSize,%esp   # Allocate storage for spill, locals & outs
     39 
     40 Once past the prologue, arguments are referenced at ((argno + 2)*4)(%ebp)
     41 
     42 Alignment of stack not strictly required, but should be for performance.  We'll
     43 align frame sizes to 16-byte multiples.
     44 
     45 If we're not doing variable stack allocation (alloca), the frame pointer can be
     46 eliminated and all arg references adjusted to be esp relative.
     47 
     48 Mterp notes:
     49 
     50 Some key interpreter variables will be assigned to registers.  Note that each
     51 will also have an associated spill location (mostly used useful for those assigned
     52 to callee save registers).
     53 
     54   nick     reg   purpose
     55   rPC      edx   interpreted program counter, used for fetching instructions
     56   rFP      esi   interpreted frame pointer, used for accessing locals and args
     57   rIBASE   edi   Base pointer for instruction dispatch computed goto
     58   rINST    bx    first 16-bit code of current instruction
     59   rOPCODE  bl    opcode portion of instruction word
     60   rINST_HI bh    high byte of instruction word, usually contains src/tgt reg names
     61 
     62 Notes:
     63    o High order 16 bits of ebx must be zero on entry to handler
     64    o rPC, rFP, rIBASE, rINST/rOPCODE valid on handler entry and exit
     65    o eax and ecx are scratch, rINST/ebx sometimes scratch
     66    o rPC is in the caller save set, and will be killed across external calls. Don't
     67      forget to SPILL/UNSPILL it around call points
     68 
     69 */
     70 
     71 #define rPC      %edx
     72 #define rFP      %esi
     73 #define rIBASE   %edi
     74 #define rINST_FULL %ebx
     75 #define rINST    %bx
     76 #define rINST_HI %bh
     77 #define rINST_LO %bl
     78 #define rOPCODE  %bl
     79 
     80 
     81 /* Frame diagram while executing dvmMterpStdRun, high to low addresses */
     82 #define IN_ARG0        (  8)
     83 #define CALLER_RP      (  4)
     84 #define PREV_FP        (  0) /* <- dvmMterpStdRun ebp */
     85 /* Spill offsets relative to %ebp */
     86 #define EDI_SPILL      ( -4)
     87 #define ESI_SPILL      ( -8)
     88 #define EDX_SPILL      (-12) /* <- esp following dmMterpStdRun header */
     89 #define rPC_SPILL      (-16)
     90 #define rFP_SPILL      (-20)
     91 #define rGLUE_SPILL    (-24)
     92 #define rIBASE_SPILL   (-28)
     93 #define rINST_FULL_SPILL    (-32)
     94 #define TMP_SPILL      (-36)
     95 #define LOCAL0_OFFSET  (-40)
     96 #define LOCAL1_OFFSET  (-44)
     97 #define LOCAL2_OFFSET  (-48)
     98 #define LOCAL3_OFFSET  (-52)
     99 /* Out Arg offsets, relative to %sp */
    100 #define OUT_ARG4       ( 16)
    101 #define OUT_ARG3       ( 12)
    102 #define OUT_ARG2       (  8)
    103 #define OUT_ARG1       (  4)
    104 #define OUT_ARG0       (  0)  /* <- dvmMterpStdRun esp */
    105 
    106 #define SPILL(reg) movl reg##,reg##_SPILL(%ebp)
    107 #define UNSPILL(reg) movl reg##_SPILL(%ebp),reg
    108 #define SPILL_TMP(reg) movl reg,TMP_SPILL(%ebp)
    109 #define UNSPILL_TMP(reg) movl TMP_SPILL(%ebp),reg
    110 
    111 
    112 /* save/restore the PC and/or FP from the glue struct */
    113 #define LOAD_PC_FROM_GLUE(_glu)     movl    offGlue_pc(_glu),rPC
    114 #define SAVE_PC_TO_GLUE(_glu)       movl    rPC,offGlue_pc(_glu)
    115 #define LOAD_FP_FROM_GLUE(_glu)     movl    offGlue_fp(_glu),rFP
    116 #define SAVE_FP_TO_GLUE(_glu)       movl    rFP,offGlue_fp(_glu)
    117 
    118 #define GET_GLUE(_reg)     movl   rGLUE_SPILL(%ebp),_reg
    119 
    120 /* The interpreter assumes a properly aligned stack on entry, and
    121  * will preserve 16-byte alignment.
    122  */
    123 
    124 /*
    125  * "export" the PC to the interpreted stack frame, f/b/o future exception
    126  * objects.  Must * be done *before* something calls dvmThrowException.
    127  *
    128  * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
    129  * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
    130  *
    131  * It's okay to do this more than once.
    132  */
    133 #define EXPORT_PC() \
    134     movl     rPC, (-sizeofStackSaveArea + offStackSaveArea_currentPc)(rFP)
    135 
    136 /*
    137  * Given a frame pointer, find the stack save area.
    138  *
    139  * In C this is "((StackSaveArea*)(_fp) -1)".
    140  */
    141 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
    142     leal    -sizeofStackSaveArea(_fpreg),_reg
    143 
    144 /*
    145  * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
    146  */
    147 #define FETCH_INST()            movzwl    (rPC),rINST_FULL
    148 
    149 /*
    150  * Fetch the nth instruction word from rPC into rINST.  Does not advance
    151  * rPC, and _count is in words
    152  */
    153 #define FETCH_INST_WORD(_count)  movzwl  _count*2(rPC),rINST_FULL
    154 
    155 /*
    156  * Fetch instruction word indexed (used for branching).
    157  * Index is in instruction word units.
    158  */
    159 #define FETCH_INST_INDEXED(_reg) movzwl  (rPC,_reg,2),rINST_FULL
    160 
    161 /*
    162  * Extract the opcode of the instruction in rINST
    163  */
    164 #define EXTRACT_OPCODE(_reg)   movzx rOPCODE,_reg
    165 
    166 /*
    167  * Advance rPC by instruction count
    168  */
    169 #define ADVANCE_PC(_count)    leal  2*_count(rPC),rPC
    170 
    171 /*
    172  * Advance rPC by branch offset in register
    173  */
    174 #define ADVANCE_PC_INDEXED(_reg) leal (rPC,_reg,2),rPC
    175 
    176 /*
    177  * Note: assumes opcode previously fetched and in rINST, and
    178  *       %eax is killable at this point.
    179  */
    180 #if 1
    181 .macro GOTO_NEXT
    182     /* For computed next version */
    183      movzx    rOPCODE,%eax
    184      sall     $$$handler_size_bits,%eax
    185      addl     rIBASE,%eax
    186      jmp      *%eax
    187 .endm
    188 #else
    189    /* For jump table version */
    190 .macro GOTO_NEXT
    191      movzx   rOPCODE,%eax
    192      jmp     *(rIBASE,%eax,4)
    193 .endm
    194 #endif
    195 
    196 /*
    197  * Get/set the 32-bit value from a Dalvik register.
    198  */
    199 #define GET_VREG(_reg, _vreg)   movl     (rFP,_vreg,4),_reg
    200 #define SET_VREG(_reg, _vreg)   movl     _reg,(rFP,_vreg,4)
    201 #define GET_VREG_WORD(_reg, _vreg, _offset)   movl     4*(_offset)(rFP,_vreg,4),_reg
    202 #define SET_VREG_WORD(_reg, _vreg, _offset)   movl     _reg,4*(_offset)(rFP,_vreg,4)
    203 
    204 /*
    205  * This is a #include, not a %include, because we want the C pre-processor
    206  * to expand the macros into assembler assignment statements.
    207  */
    208 #include "../common/asm-constants.h"
    209 
    210