Bill Buzbee | 3b0b4b9 | 2016-02-02 13:45:36 +0000 | [diff] [blame] | 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 xFP 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 xFP & |
| 30 | number_of_vregs_. |
| 31 | |
| 32 | */ |
| 33 | |
| 34 | /* |
| 35 | ARM64 Runtime register usage conventions. |
| 36 | |
| 37 | r0 : w0 is 32-bit return register and x0 is 64-bit. |
| 38 | r0-r7 : Argument registers. |
| 39 | r8-r15 : Caller save registers (used as temporary registers). |
| 40 | r16-r17: Also known as ip0-ip1, respectively. Used as scratch registers by |
| 41 | the linker, by the trampolines and other stubs (the backend uses |
| 42 | these as temporary registers). |
| 43 | r18 : Caller save register (used as temporary register). |
| 44 | r19 : Pointer to thread-local storage. |
| 45 | r20-r29: Callee save registers. |
| 46 | r30 : (lr) is reserved (the link register). |
| 47 | rsp : (sp) is reserved (the stack pointer). |
| 48 | rzr : (zr) is reserved (the zero register). |
| 49 | |
| 50 | Floating-point registers |
| 51 | v0-v31 |
| 52 | |
| 53 | v0 : s0 is return register for singles (32-bit) and d0 for doubles (64-bit). |
| 54 | This is analogous to the C/C++ (hard-float) calling convention. |
| 55 | v0-v7 : Floating-point argument registers in both Dalvik and C/C++ conventions. |
| 56 | Also used as temporary and codegen scratch registers. |
| 57 | |
| 58 | v0-v7 and v16-v31 : trashed across C calls. |
| 59 | v8-v15 : bottom 64-bits preserved across C calls (d8-d15 are preserved). |
| 60 | |
| 61 | v16-v31: Used as codegen temp/scratch. |
| 62 | v8-v15 : Can be used for promotion. |
| 63 | |
| 64 | Must maintain 16-byte stack alignment. |
| 65 | |
| 66 | Mterp notes: |
| 67 | |
| 68 | The following registers have fixed assignments: |
| 69 | |
| 70 | reg nick purpose |
| 71 | x20 xPC interpreted program counter, used for fetching instructions |
| 72 | x21 xFP interpreted frame pointer, used for accessing locals and args |
| 73 | x22 xSELF self (Thread) pointer |
| 74 | x23 xINST first 16-bit code unit of current instruction |
| 75 | x24 xIBASE interpreted instruction base pointer, used for computed goto |
| 76 | x25 xREFS base of object references in shadow frame (ideally, we'll get rid of this later). |
Bill Buzbee | 1d011d9 | 2016-04-04 16:59:29 +0000 | [diff] [blame] | 77 | x26 wPROFILE jit profile hotness countdown |
Bill Buzbee | 3b0b4b9 | 2016-02-02 13:45:36 +0000 | [diff] [blame] | 78 | x16 ip scratch reg |
| 79 | x17 ip2 scratch reg (used by macros) |
| 80 | |
| 81 | Macros are provided for common operations. They MUST NOT alter unspecified registers or condition |
| 82 | codes. |
| 83 | */ |
| 84 | |
| 85 | /* |
| 86 | * This is a #include, not a %include, because we want the C pre-processor |
| 87 | * to expand the macros into assembler assignment statements. |
| 88 | */ |
| 89 | #include "asm_support.h" |
| 90 | |
Bill Buzbee | fd522f9 | 2016-02-11 22:37:42 +0000 | [diff] [blame] | 91 | #define MTERP_PROFILE_BRANCHES 1 |
| 92 | #define MTERP_LOGGING 0 |
| 93 | |
Bill Buzbee | 3b0b4b9 | 2016-02-02 13:45:36 +0000 | [diff] [blame] | 94 | /* During bringup, we'll use the shadow frame model instead of xFP */ |
| 95 | /* single-purpose registers, given names for clarity */ |
Bill Buzbee | 1d011d9 | 2016-04-04 16:59:29 +0000 | [diff] [blame] | 96 | #define xPC x20 |
| 97 | #define xFP x21 |
| 98 | #define xSELF x22 |
| 99 | #define xINST x23 |
| 100 | #define wINST w23 |
| 101 | #define xIBASE x24 |
| 102 | #define xREFS x25 |
| 103 | #define wPROFILE w26 |
| 104 | #define xPROFILE x26 |
| 105 | #define ip x16 |
| 106 | #define ip2 x17 |
Bill Buzbee | 3b0b4b9 | 2016-02-02 13:45:36 +0000 | [diff] [blame] | 107 | |
| 108 | /* |
| 109 | * Instead of holding a pointer to the shadow frame, we keep xFP at the base of the vregs. So, |
| 110 | * to access other shadow frame fields, we need to use a backwards offset. Define those here. |
| 111 | */ |
| 112 | #define OFF_FP(a) (a - SHADOWFRAME_VREGS_OFFSET) |
| 113 | #define OFF_FP_NUMBER_OF_VREGS OFF_FP(SHADOWFRAME_NUMBER_OF_VREGS_OFFSET) |
| 114 | #define OFF_FP_DEX_PC OFF_FP(SHADOWFRAME_DEX_PC_OFFSET) |
| 115 | #define OFF_FP_LINK OFF_FP(SHADOWFRAME_LINK_OFFSET) |
| 116 | #define OFF_FP_METHOD OFF_FP(SHADOWFRAME_METHOD_OFFSET) |
| 117 | #define OFF_FP_RESULT_REGISTER OFF_FP(SHADOWFRAME_RESULT_REGISTER_OFFSET) |
| 118 | #define OFF_FP_DEX_PC_PTR OFF_FP(SHADOWFRAME_DEX_PC_PTR_OFFSET) |
| 119 | #define OFF_FP_CODE_ITEM OFF_FP(SHADOWFRAME_CODE_ITEM_OFFSET) |
Bill Buzbee | 1d011d9 | 2016-04-04 16:59:29 +0000 | [diff] [blame] | 120 | #define OFF_FP_SHADOWFRAME OFF_FP(0) |
Bill Buzbee | 3b0b4b9 | 2016-02-02 13:45:36 +0000 | [diff] [blame] | 121 | |
| 122 | /* |
Bill Buzbee | 3b0b4b9 | 2016-02-02 13:45:36 +0000 | [diff] [blame] | 123 | * "export" the PC to dex_pc field in the shadow frame, f/b/o future exception objects. Must |
| 124 | * be done *before* something throws. |
| 125 | * |
| 126 | * It's okay to do this more than once. |
| 127 | * |
| 128 | * NOTE: the fast interpreter keeps track of dex pc as a direct pointer to the mapped |
| 129 | * dex byte codes. However, the rest of the runtime expects dex pc to be an instruction |
| 130 | * offset into the code_items_[] array. For effiency, we will "export" the |
| 131 | * current dex pc as a direct pointer using the EXPORT_PC macro, and rely on GetDexPC |
| 132 | * to convert to a dex pc when needed. |
| 133 | */ |
| 134 | .macro EXPORT_PC |
| 135 | str xPC, [xFP, #OFF_FP_DEX_PC_PTR] |
| 136 | .endm |
| 137 | |
| 138 | /* |
| 139 | * Fetch the next instruction from xPC into wINST. Does not advance xPC. |
| 140 | */ |
| 141 | .macro FETCH_INST |
| 142 | ldrh wINST, [xPC] |
| 143 | .endm |
| 144 | |
| 145 | /* |
| 146 | * Fetch the next instruction from the specified offset. Advances xPC |
| 147 | * to point to the next instruction. "_count" is in 16-bit code units. |
| 148 | * |
| 149 | * Because of the limited size of immediate constants on ARM, this is only |
| 150 | * suitable for small forward movements (i.e. don't try to implement "goto" |
| 151 | * with this). |
| 152 | * |
| 153 | * This must come AFTER anything that can throw an exception, or the |
| 154 | * exception catch may miss. (This also implies that it must come after |
| 155 | * EXPORT_PC.) |
| 156 | */ |
| 157 | .macro FETCH_ADVANCE_INST count |
| 158 | ldrh wINST, [xPC, #((\count)*2)]! |
| 159 | .endm |
| 160 | |
| 161 | /* |
| 162 | * The operation performed here is similar to FETCH_ADVANCE_INST, except the |
| 163 | * src and dest registers are parameterized (not hard-wired to xPC and xINST). |
| 164 | */ |
| 165 | .macro PREFETCH_ADVANCE_INST dreg, sreg, count |
| 166 | ldrh \dreg, [\sreg, #((\count)*2)]! |
| 167 | .endm |
| 168 | |
| 169 | /* |
| 170 | * Similar to FETCH_ADVANCE_INST, but does not update xPC. Used to load |
| 171 | * xINST ahead of possible exception point. Be sure to manually advance xPC |
| 172 | * later. |
| 173 | */ |
| 174 | .macro PREFETCH_INST count |
| 175 | ldrh wINST, [xPC, #((\count)*2)] |
| 176 | .endm |
| 177 | |
| 178 | /* Advance xPC by some number of code units. */ |
| 179 | .macro ADVANCE count |
| 180 | add xPC, xPC, #((\count)*2) |
| 181 | .endm |
| 182 | |
| 183 | /* |
| 184 | * Fetch the next instruction from an offset specified by _reg and advance xPC. |
| 185 | * xPC to point to the next instruction. "_reg" must specify the distance |
| 186 | * in bytes, *not* 16-bit code units, and may be a signed value. Must not set flags. |
| 187 | * |
| 188 | */ |
| 189 | .macro FETCH_ADVANCE_INST_RB reg |
| 190 | add xPC, xPC, \reg, sxtw |
| 191 | ldrh wINST, [xPC] |
| 192 | .endm |
| 193 | |
| 194 | /* |
| 195 | * Fetch a half-word code unit from an offset past the current PC. The |
| 196 | * "_count" value is in 16-bit code units. Does not advance xPC. |
| 197 | * |
| 198 | * The "_S" variant works the same but treats the value as signed. |
| 199 | */ |
| 200 | .macro FETCH reg, count |
| 201 | ldrh \reg, [xPC, #((\count)*2)] |
| 202 | .endm |
| 203 | |
| 204 | .macro FETCH_S reg, count |
| 205 | ldrsh \reg, [xPC, #((\count)*2)] |
| 206 | .endm |
| 207 | |
| 208 | /* |
| 209 | * Fetch one byte from an offset past the current PC. Pass in the same |
| 210 | * "_count" as you would for FETCH, and an additional 0/1 indicating which |
| 211 | * byte of the halfword you want (lo/hi). |
| 212 | */ |
| 213 | .macro FETCH_B reg, count, byte |
| 214 | ldrb \reg, [xPC, #((\count)*2+(\byte))] |
| 215 | .endm |
| 216 | |
| 217 | /* |
| 218 | * Put the instruction's opcode field into the specified register. |
| 219 | */ |
| 220 | .macro GET_INST_OPCODE reg |
| 221 | and \reg, xINST, #255 |
| 222 | .endm |
| 223 | |
| 224 | /* |
| 225 | * Put the prefetched instruction's opcode field into the specified register. |
| 226 | */ |
| 227 | .macro GET_PREFETCHED_OPCODE oreg, ireg |
| 228 | and \oreg, \ireg, #255 |
| 229 | .endm |
| 230 | |
| 231 | /* |
| 232 | * Begin executing the opcode in _reg. Clobbers reg |
| 233 | */ |
| 234 | |
| 235 | .macro GOTO_OPCODE reg |
| 236 | add \reg, xIBASE, \reg, lsl #${handler_size_bits} |
| 237 | br \reg |
| 238 | .endm |
| 239 | .macro GOTO_OPCODE_BASE base,reg |
| 240 | add \reg, \base, \reg, lsl #${handler_size_bits} |
| 241 | br \reg |
| 242 | .endm |
| 243 | |
| 244 | /* |
| 245 | * Get/set the 32-bit value from a Dalvik register. |
| 246 | */ |
| 247 | .macro GET_VREG reg, vreg |
| 248 | ldr \reg, [xFP, \vreg, uxtw #2] |
| 249 | .endm |
| 250 | .macro SET_VREG reg, vreg |
| 251 | str \reg, [xFP, \vreg, uxtw #2] |
| 252 | str wzr, [xREFS, \vreg, uxtw #2] |
| 253 | .endm |
| 254 | .macro SET_VREG_OBJECT reg, vreg, tmpreg |
| 255 | str \reg, [xFP, \vreg, uxtw #2] |
| 256 | str \reg, [xREFS, \vreg, uxtw #2] |
| 257 | .endm |
| 258 | |
| 259 | /* |
| 260 | * Get/set the 64-bit value from a Dalvik register. |
| 261 | * TUNING: can we do better here? |
| 262 | */ |
| 263 | .macro GET_VREG_WIDE reg, vreg |
| 264 | add ip2, xFP, \vreg, lsl #2 |
| 265 | ldr \reg, [ip2] |
| 266 | .endm |
| 267 | .macro SET_VREG_WIDE reg, vreg |
| 268 | add ip2, xFP, \vreg, lsl #2 |
| 269 | str \reg, [ip2] |
| 270 | add ip2, xREFS, \vreg, lsl #2 |
| 271 | str xzr, [ip2] |
| 272 | .endm |
| 273 | |
| 274 | /* |
| 275 | * Convert a virtual register index into an address. |
| 276 | */ |
| 277 | .macro VREG_INDEX_TO_ADDR reg, vreg |
buzbee | ace690f | 2016-03-11 09:51:11 -0800 | [diff] [blame] | 278 | add \reg, xFP, \vreg, lsl #2 /* WARNING: handle shadow frame vreg zero if store */ |
Bill Buzbee | 3b0b4b9 | 2016-02-02 13:45:36 +0000 | [diff] [blame] | 279 | .endm |
| 280 | |
| 281 | /* |
| 282 | * Refresh handler table. |
| 283 | */ |
| 284 | .macro REFRESH_IBASE |
| 285 | ldr xIBASE, [xSELF, #THREAD_CURRENT_IBASE_OFFSET] |
| 286 | .endm |