1 %def const(helper="UndefinedConstHandler"): 2 /* const/class vAA, type@BBBB */ 3 /* const/method-handle vAA, method_handle@BBBB */ 4 /* const/method-type vAA, proto@BBBB */ 5 /* const/string vAA, string@@BBBB */ 6 .extern $helper 7 EXPORT_PC 8 FETCH w0, 1 // w0<- BBBB 9 lsr w1, wINST, #8 // w1<- AA 10 add x2, xFP, #OFF_FP_SHADOWFRAME 11 mov x3, xSELF 12 bl $helper // (index, tgt_reg, shadow_frame, self) 13 PREFETCH_INST 2 // load rINST 14 cbnz w0, MterpPossibleException // let reference interpreter deal with it. 15 ADVANCE 2 // advance rPC 16 GET_INST_OPCODE ip // extract opcode from rINST 17 GOTO_OPCODE ip // jump to next instruction 18 19 %def unused(): 20 /* 21 * Bail to reference interpreter to throw. 22 */ 23 b MterpFallback 24 25 %def op_const(): 26 /* const vAA, #+BBBBbbbb */ 27 lsr w3, wINST, #8 // w3<- AA 28 FETCH w0, 1 // w0<- bbbb (low 29 FETCH w1, 2 // w1<- BBBB (high 30 FETCH_ADVANCE_INST 3 // advance rPC, load wINST 31 orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb 32 GET_INST_OPCODE ip // extract opcode from wINST 33 SET_VREG w0, w3 // vAA<- w0 34 GOTO_OPCODE ip // jump to next instruction 35 36 %def op_const_16(): 37 /* const/16 vAA, #+BBBB */ 38 FETCH_S w0, 1 // w0<- ssssBBBB (sign-extended) 39 lsr w3, wINST, #8 // w3<- AA 40 FETCH_ADVANCE_INST 2 // advance xPC, load wINST 41 SET_VREG w0, w3 // vAA<- w0 42 GET_INST_OPCODE ip // extract opcode from wINST 43 GOTO_OPCODE ip // jump to next instruction 44 45 %def op_const_4(): 46 /* const/4 vA, #+B */ 47 sbfx w1, wINST, #12, #4 // w1<- sssssssB 48 ubfx w0, wINST, #8, #4 // w0<- A 49 FETCH_ADVANCE_INST 1 // advance xPC, load wINST 50 GET_INST_OPCODE ip // ip<- opcode from xINST 51 SET_VREG w1, w0 // fp[A]<- w1 52 GOTO_OPCODE ip // execute next instruction 53 54 %def op_const_class(): 55 % const(helper="MterpConstClass") 56 57 %def op_const_high16(): 58 /* const/high16 vAA, #+BBBB0000 */ 59 FETCH w0, 1 // r0<- 0000BBBB (zero-extended) 60 lsr w3, wINST, #8 // r3<- AA 61 lsl w0, w0, #16 // r0<- BBBB0000 62 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 63 SET_VREG w0, w3 // vAA<- r0 64 GET_INST_OPCODE ip // extract opcode from rINST 65 GOTO_OPCODE ip // jump to next instruction 66 67 %def op_const_method_handle(): 68 % const(helper="MterpConstMethodHandle") 69 70 %def op_const_method_type(): 71 % const(helper="MterpConstMethodType") 72 73 %def op_const_string(): 74 % const(helper="MterpConstString") 75 76 %def op_const_string_jumbo(): 77 /* const/string vAA, String//BBBBBBBB */ 78 EXPORT_PC 79 FETCH w0, 1 // w0<- bbbb (low 80 FETCH w2, 2 // w2<- BBBB (high 81 lsr w1, wINST, #8 // w1<- AA 82 orr w0, w0, w2, lsl #16 // w1<- BBBBbbbb 83 add x2, xFP, #OFF_FP_SHADOWFRAME 84 mov x3, xSELF 85 bl MterpConstString // (index, tgt_reg, shadow_frame, self) 86 PREFETCH_INST 3 // advance rPC 87 cbnz w0, MterpPossibleException // let reference interpreter deal with it. 88 ADVANCE 3 // advance rPC 89 GET_INST_OPCODE ip // extract opcode from rINST 90 GOTO_OPCODE ip // jump to next instruction 91 92 %def op_const_wide(): 93 /* const-wide vAA, #+HHHHhhhhBBBBbbbb */ 94 FETCH w0, 1 // w0<- bbbb (low) 95 FETCH w1, 2 // w1<- BBBB (low middle) 96 FETCH w2, 3 // w2<- hhhh (high middle) 97 FETCH w3, 4 // w3<- HHHH (high) 98 lsr w4, wINST, #8 // r4<- AA 99 FETCH_ADVANCE_INST 5 // advance rPC, load wINST 100 GET_INST_OPCODE ip // extract opcode from wINST 101 orr w0, w0, w1, lsl #16 // w0<- BBBBbbbb 102 orr x0, x0, x2, lsl #32 // w0<- hhhhBBBBbbbb 103 orr x0, x0, x3, lsl #48 // w0<- HHHHhhhhBBBBbbbb 104 SET_VREG_WIDE x0, w4 105 GOTO_OPCODE ip // jump to next instruction 106 107 %def op_const_wide_16(): 108 /* const-wide/16 vAA, #+BBBB */ 109 FETCH_S x0, 1 // x0<- ssssssssssssBBBB (sign-extended) 110 lsr w3, wINST, #8 // w3<- AA 111 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 112 GET_INST_OPCODE ip // extract opcode from rINST 113 SET_VREG_WIDE x0, w3 114 GOTO_OPCODE ip // jump to next instruction 115 116 %def op_const_wide_32(): 117 /* const-wide/32 vAA, #+BBBBbbbb */ 118 FETCH w0, 1 // x0<- 000000000000bbbb (low) 119 lsr w3, wINST, #8 // w3<- AA 120 FETCH_S x2, 2 // x2<- ssssssssssssBBBB (high) 121 FETCH_ADVANCE_INST 3 // advance rPC, load wINST 122 GET_INST_OPCODE ip // extract opcode from wINST 123 orr x0, x0, x2, lsl #16 // x0<- ssssssssBBBBbbbb 124 SET_VREG_WIDE x0, w3 125 GOTO_OPCODE ip // jump to next instruction 126 127 %def op_const_wide_high16(): 128 /* const-wide/high16 vAA, #+BBBB000000000000 */ 129 FETCH w0, 1 // w0<- 0000BBBB (zero-extended) 130 lsr w1, wINST, #8 // w1<- AA 131 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 132 lsl x0, x0, #48 133 SET_VREG_WIDE x0, w1 134 GET_INST_OPCODE ip // extract opcode from wINST 135 GOTO_OPCODE ip // jump to next instruction 136 137 %def op_monitor_enter(): 138 /* 139 * Synchronize on an object. 140 */ 141 /* monitor-enter vAA */ 142 EXPORT_PC 143 lsr w2, wINST, #8 // w2<- AA 144 GET_VREG w0, w2 // w0<- vAA (object) 145 mov x1, xSELF // w1<- self 146 bl artLockObjectFromCode 147 cbnz w0, MterpException 148 FETCH_ADVANCE_INST 1 149 ldr w0, [xSELF, #THREAD_USE_MTERP_OFFSET] 150 cbz w0, MterpFallback 151 GET_INST_OPCODE ip // extract opcode from rINST 152 GOTO_OPCODE ip // jump to next instruction 153 154 %def op_monitor_exit(): 155 /* 156 * Unlock an object. 157 * 158 * Exceptions that occur when unlocking a monitor need to appear as 159 * if they happened at the following instruction. See the Dalvik 160 * instruction spec. 161 */ 162 /* monitor-exit vAA */ 163 EXPORT_PC 164 lsr w2, wINST, #8 // w2<- AA 165 GET_VREG w0, w2 // w0<- vAA (object) 166 mov x1, xSELF // w0<- self 167 bl artUnlockObjectFromCode // w0<- success for unlock(self, obj) 168 cbnz w0, MterpException 169 FETCH_ADVANCE_INST 1 // before throw: advance rPC, load rINST 170 ldr w0, [xSELF, #THREAD_USE_MTERP_OFFSET] 171 cbz w0, MterpFallback 172 GET_INST_OPCODE ip // extract opcode from rINST 173 GOTO_OPCODE ip // jump to next instruction 174 175 %def op_move(is_object="0"): 176 /* for move, move-object, long-to-int */ 177 /* op vA, vB */ 178 lsr w1, wINST, #12 // x1<- B from 15:12 179 ubfx w0, wINST, #8, #4 // x0<- A from 11:8 180 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 181 GET_VREG w2, w1 // x2<- fp[B] 182 GET_INST_OPCODE ip // ip<- opcode from wINST 183 .if $is_object 184 SET_VREG_OBJECT w2, w0 // fp[A]<- x2 185 .else 186 SET_VREG w2, w0 // fp[A]<- x2 187 .endif 188 GOTO_OPCODE ip // execute next instruction 189 190 %def op_move_16(is_object="0"): 191 /* for: move/16, move-object/16 */ 192 /* op vAAAA, vBBBB */ 193 FETCH w1, 2 // w1<- BBBB 194 FETCH w0, 1 // w0<- AAAA 195 FETCH_ADVANCE_INST 3 // advance xPC, load xINST 196 GET_VREG w2, w1 // w2<- fp[BBBB] 197 GET_INST_OPCODE ip // extract opcode from xINST 198 .if $is_object 199 SET_VREG_OBJECT w2, w0 // fp[AAAA]<- w2 200 .else 201 SET_VREG w2, w0 // fp[AAAA]<- w2 202 .endif 203 GOTO_OPCODE ip // jump to next instruction 204 205 %def op_move_exception(): 206 /* move-exception vAA */ 207 lsr w2, wINST, #8 // w2<- AA 208 ldr x3, [xSELF, #THREAD_EXCEPTION_OFFSET] 209 mov x1, #0 // w1<- 0 210 FETCH_ADVANCE_INST 1 // advance rPC, load rINST 211 SET_VREG_OBJECT w3, w2 // fp[AA]<- exception obj 212 GET_INST_OPCODE ip // extract opcode from rINST 213 str x1, [xSELF, #THREAD_EXCEPTION_OFFSET] // clear exception 214 GOTO_OPCODE ip // jump to next instruction 215 216 %def op_move_from16(is_object="0"): 217 /* for: move/from16, move-object/from16 */ 218 /* op vAA, vBBBB */ 219 FETCH w1, 1 // r1<- BBBB 220 lsr w0, wINST, #8 // r0<- AA 221 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 222 GET_VREG w2, w1 // r2<- fp[BBBB] 223 GET_INST_OPCODE ip // extract opcode from wINST 224 .if $is_object 225 SET_VREG_OBJECT w2, w0 // fp[AA]<- r2 226 .else 227 SET_VREG w2, w0 // fp[AA]<- r2 228 .endif 229 GOTO_OPCODE ip // jump to next instruction 230 231 %def op_move_object(): 232 % op_move(is_object="1") 233 234 %def op_move_object_16(): 235 % op_move_16(is_object="1") 236 237 %def op_move_object_from16(): 238 % op_move_from16(is_object="1") 239 240 %def op_move_result(is_object="0"): 241 /* for: move-result, move-result-object */ 242 /* op vAA */ 243 lsr w2, wINST, #8 // r2<- AA 244 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 245 ldr x0, [xFP, #OFF_FP_RESULT_REGISTER] // get pointer to result JType. 246 ldr w0, [x0] // r0 <- result.i. 247 GET_INST_OPCODE ip // extract opcode from wINST 248 .if $is_object 249 SET_VREG_OBJECT w0, w2, w1 // fp[AA]<- r0 250 .else 251 SET_VREG w0, w2 // fp[AA]<- r0 252 .endif 253 GOTO_OPCODE ip // jump to next instruction 254 255 %def op_move_result_object(): 256 % op_move_result(is_object="1") 257 258 %def op_move_result_wide(): 259 /* for: move-result-wide */ 260 /* op vAA */ 261 lsr w2, wINST, #8 // r2<- AA 262 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 263 ldr x0, [xFP, #OFF_FP_RESULT_REGISTER] // get pointer to result JType. 264 ldr x0, [x0] // r0 <- result.i. 265 GET_INST_OPCODE ip // extract opcode from wINST 266 SET_VREG_WIDE x0, x2 // fp[AA]<- r0 267 GOTO_OPCODE ip // jump to next instruction 268 269 %def op_move_wide(): 270 /* move-wide vA, vB */ 271 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 272 lsr w3, wINST, #12 // w3<- B 273 ubfx w2, wINST, #8, #4 // w2<- A 274 GET_VREG_WIDE x3, w3 275 FETCH_ADVANCE_INST 1 // advance rPC, load wINST 276 GET_INST_OPCODE ip // extract opcode from wINST 277 SET_VREG_WIDE x3, w2 278 GOTO_OPCODE ip // jump to next instruction 279 280 %def op_move_wide_16(): 281 /* move-wide/16 vAAAA, vBBBB */ 282 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 283 FETCH w3, 2 // w3<- BBBB 284 FETCH w2, 1 // w2<- AAAA 285 GET_VREG_WIDE x3, w3 286 FETCH_ADVANCE_INST 3 // advance rPC, load rINST 287 SET_VREG_WIDE x3, w2 288 GET_INST_OPCODE ip // extract opcode from rINST 289 GOTO_OPCODE ip // jump to next instruction 290 291 %def op_move_wide_from16(): 292 /* move-wide/from16 vAA, vBBBB */ 293 /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */ 294 FETCH w3, 1 // w3<- BBBB 295 lsr w2, wINST, #8 // w2<- AA 296 GET_VREG_WIDE x3, w3 297 FETCH_ADVANCE_INST 2 // advance rPC, load wINST 298 GET_INST_OPCODE ip // extract opcode from wINST 299 SET_VREG_WIDE x3, w2 300 GOTO_OPCODE ip // jump to next instruction 301 302 %def op_nop(): 303 FETCH_ADVANCE_INST 1 // advance to next instr, load rINST 304 GET_INST_OPCODE ip // ip<- opcode from rINST 305 GOTO_OPCODE ip // execute it 306 307 %def op_unused_3e(): 308 % unused() 309 310 %def op_unused_3f(): 311 % unused() 312 313 %def op_unused_40(): 314 % unused() 315 316 %def op_unused_41(): 317 % unused() 318 319 %def op_unused_42(): 320 % unused() 321 322 %def op_unused_43(): 323 % unused() 324 325 %def op_unused_73(): 326 % unused() 327 328 %def op_unused_79(): 329 % unused() 330 331 %def op_unused_7a(): 332 % unused() 333 334 %def op_unused_f3(): 335 % unused() 336 337 %def op_unused_f4(): 338 % unused() 339 340 %def op_unused_f5(): 341 % unused() 342 343 %def op_unused_f6(): 344 % unused() 345 346 %def op_unused_f7(): 347 % unused() 348 349 %def op_unused_f8(): 350 % unused() 351 352 %def op_unused_f9(): 353 % unused() 354 355 %def op_unused_fc(): 356 % unused() 357 358 %def op_unused_fd(): 359 % unused() 360