1%def field(helper=""): 2 /* 3 * General field read / write (iget-* iput-* sget-* sput-*). 4 */ 5 .extern $helper 6 mov r0, rPC @ arg0: Instruction* inst 7 mov r1, rINST @ arg1: uint16_t inst_data 8 add r2, rFP, #OFF_FP_SHADOWFRAME @ arg2: ShadowFrame* sf 9 mov r3, rSELF @ arg3: Thread* self 10 PREFETCH_INST 2 @ prefetch next opcode 11 bl $helper 12 cmp r0, #0 13 beq MterpPossibleException 14 ADVANCE 2 15 GET_INST_OPCODE ip @ extract opcode from rINST 16 GOTO_OPCODE ip @ jump to next instruction 17 18%def op_check_cast(): 19 /* 20 * Check to see if a cast from one class to another is allowed. 21 */ 22 /* check-cast vAA, class@BBBB */ 23 EXPORT_PC 24 FETCH r0, 1 @ r0<- BBBB 25 mov r1, rINST, lsr #8 @ r1<- AA 26 VREG_INDEX_TO_ADDR r1, r1 @ r1<- &object 27 ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- method 28 mov r3, rSELF @ r3<- self 29 bl MterpCheckCast @ (index, &obj, method, self) 30 PREFETCH_INST 2 31 cmp r0, #0 32 bne MterpPossibleException 33 ADVANCE 2 34 GET_INST_OPCODE ip @ extract opcode from rINST 35 GOTO_OPCODE ip @ jump to next instruction 36 37%def op_iget(is_object=False, is_wide=False, load="ldr", helper="MterpIGetU32"): 38 @ Fast-path which gets the field offset from thread-local cache. 39 add r0, rSELF, #THREAD_INTERPRETER_CACHE_OFFSET @ cache address 40 ubfx r1, rPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 @ entry index 41 add r0, r0, r1, lsl #3 @ entry address within the cache 42 ldrd r0, r1, [r0] @ entry key (pc) and value (offset) 43 mov r2, rINST, lsr #12 @ B 44 GET_VREG r2, r2 @ object we're operating on 45 cmp r0, rPC 46% slow_path_label = add_helper(lambda: field(helper)) 47 bne ${slow_path_label} @ cache miss 48 cmp r2, #0 49 beq common_errNullObject @ null object 50% if is_wide: 51 ldrd r0, r1, [r1, r2] @ r0,r1 <- obj.field 52% else: 53 ${load} r0, [r2, r1] @ r0 <- obj.field 54% #endif 55% if is_object: 56 UNPOISON_HEAP_REF r0 57#if defined(USE_READ_BARRIER) 58# if defined(USE_BAKER_READ_BARRIER) 59 ldr ip, [rSELF, #THREAD_IS_GC_MARKING_OFFSET] 60 cmp ip, #0 61 bne .L_${opcode}_mark @ GC is active 62.L_${opcode}_marked: 63# else 64 bl artReadBarrierMark @ r0 <- artReadBarrierMark(r0) 65# endif 66#endif 67% #endif 68 ubfx r2, rINST, #8, #4 @ A 69 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 70% if is_object: 71 SET_VREG_OBJECT r0, r2 @ fp[A]<- r0 72% elif is_wide: 73 SET_VREG_WIDE r0, r1, r2 @ fp[A]<- r0, r1 74% else: 75 SET_VREG r0, r2 @ fp[A]<- r0 76% #endif 77 GET_INST_OPCODE ip @ extract opcode from rINST 78 GOTO_OPCODE ip @ jump to next instruction 79% if is_object: 80#if defined(USE_READ_BARRIER) && defined(USE_BAKER_READ_BARRIER) 81.L_${opcode}_mark: 82 bl artReadBarrierMark @ r0 <- artReadBarrierMark(r0) 83 b .L_${opcode}_marked 84#endif 85% #endif 86 87%def op_iget_boolean(): 88% op_iget(load="ldrb", helper="MterpIGetU8") 89 90%def op_iget_boolean_quick(): 91% op_iget_quick(load="ldrb") 92 93%def op_iget_byte(): 94% op_iget(load="ldrsb", helper="MterpIGetI8") 95 96%def op_iget_byte_quick(): 97% op_iget_quick(load="ldrsb") 98 99%def op_iget_char(): 100% op_iget(load="ldrh", helper="MterpIGetU16") 101 102%def op_iget_char_quick(): 103% op_iget_quick(load="ldrh") 104 105%def op_iget_object(): 106% op_iget(is_object=True, helper="MterpIGetObj") 107 108%def op_iget_object_quick(): 109 /* For: iget-object-quick */ 110 /* op vA, vB, offset@CCCC */ 111 mov r2, rINST, lsr #12 @ r2<- B 112 FETCH r1, 1 @ r1<- field byte offset 113 EXPORT_PC 114 GET_VREG r0, r2 @ r0<- object we're operating on 115 bl artIGetObjectFromMterp @ (obj, offset) 116 ldr r3, [rSELF, #THREAD_EXCEPTION_OFFSET] 117 ubfx r2, rINST, #8, #4 @ r2<- A 118 PREFETCH_INST 2 119 cmp r3, #0 120 bne MterpPossibleException @ bail out 121 SET_VREG_OBJECT r0, r2 @ fp[A]<- r0 122 ADVANCE 2 @ advance rPC 123 GET_INST_OPCODE ip @ extract opcode from rINST 124 GOTO_OPCODE ip @ jump to next instruction 125 126%def op_iget_quick(load="ldr"): 127 /* For: iget-quick, iget-boolean-quick, iget-byte-quick, iget-char-quick, iget-short-quick */ 128 /* op vA, vB, offset@CCCC */ 129 mov r2, rINST, lsr #12 @ r2<- B 130 FETCH r1, 1 @ r1<- field byte offset 131 GET_VREG r3, r2 @ r3<- object we're operating on 132 ubfx r2, rINST, #8, #4 @ r2<- A 133 cmp r3, #0 @ check object for null 134 beq common_errNullObject @ object was null 135 $load r0, [r3, r1] @ r0<- obj.field 136 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 137 SET_VREG r0, r2 @ fp[A]<- r0 138 GET_INST_OPCODE ip @ extract opcode from rINST 139 GOTO_OPCODE ip @ jump to next instruction 140 141%def op_iget_short(): 142% op_iget(load="ldrsh", helper="MterpIGetI16") 143 144%def op_iget_short_quick(): 145% op_iget_quick(load="ldrsh") 146 147%def op_iget_wide(): 148% op_iget(is_wide=True, helper="MterpIGetU64") 149 150%def op_iget_wide_quick(): 151 /* iget-wide-quick vA, vB, offset@CCCC */ 152 mov r2, rINST, lsr #12 @ r2<- B 153 FETCH ip, 1 @ ip<- field byte offset 154 GET_VREG r3, r2 @ r3<- object we're operating on 155 ubfx r2, rINST, #8, #4 @ r2<- A 156 cmp r3, #0 @ check object for null 157 beq common_errNullObject @ object was null 158 ldrd r0, [r3, ip] @ r0<- obj.field (64 bits, aligned) 159 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 160 VREG_INDEX_TO_ADDR r3, r2 @ r3<- &fp[A] 161 CLEAR_SHADOW_PAIR r2, ip, lr @ Zero out the shadow regs 162 GET_INST_OPCODE ip @ extract opcode from rINST 163 SET_VREG_WIDE_BY_ADDR r0, r1, r3 @ fp[A]<- r0/r1 164 GOTO_OPCODE ip @ jump to next instruction 165 166%def op_instance_of(): 167 /* 168 * Check to see if an object reference is an instance of a class. 169 * 170 * Most common situation is a non-null object, being compared against 171 * an already-resolved class. 172 */ 173 /* instance-of vA, vB, class@CCCC */ 174 EXPORT_PC 175 FETCH r0, 1 @ r0<- CCCC 176 mov r1, rINST, lsr #12 @ r1<- B 177 VREG_INDEX_TO_ADDR r1, r1 @ r1<- &object 178 ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- method 179 mov r3, rSELF @ r3<- self 180 bl MterpInstanceOf @ (index, &obj, method, self) 181 ldr r1, [rSELF, #THREAD_EXCEPTION_OFFSET] 182 ubfx r9, rINST, #8, #4 @ r9<- A 183 PREFETCH_INST 2 184 cmp r1, #0 @ exception pending? 185 bne MterpException 186 ADVANCE 2 @ advance rPC 187 SET_VREG r0, r9 @ vA<- r0 188 GET_INST_OPCODE ip @ extract opcode from rINST 189 GOTO_OPCODE ip @ jump to next instruction 190 191%def op_iput(helper="MterpIPutU32"): 192% field(helper=helper) 193 194%def op_iput_boolean(): 195% op_iput(helper="MterpIPutU8") 196 197%def op_iput_boolean_quick(): 198% op_iput_quick(store="strb") 199 200%def op_iput_byte(): 201% op_iput(helper="MterpIPutI8") 202 203%def op_iput_byte_quick(): 204% op_iput_quick(store="strb") 205 206%def op_iput_char(): 207% op_iput(helper="MterpIPutU16") 208 209%def op_iput_char_quick(): 210% op_iput_quick(store="strh") 211 212%def op_iput_object(): 213% op_iput(helper="MterpIPutObj") 214 215%def op_iput_object_quick(): 216 EXPORT_PC 217 add r0, rFP, #OFF_FP_SHADOWFRAME 218 mov r1, rPC 219 mov r2, rINST 220 bl MterpIputObjectQuick 221 cmp r0, #0 222 beq MterpException 223 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 224 GET_INST_OPCODE ip @ extract opcode from rINST 225 GOTO_OPCODE ip @ jump to next instruction 226 227%def op_iput_quick(store="str"): 228 /* For: iput-quick, iput-object-quick */ 229 /* op vA, vB, offset@CCCC */ 230 mov r2, rINST, lsr #12 @ r2<- B 231 FETCH r1, 1 @ r1<- field byte offset 232 GET_VREG r3, r2 @ r3<- fp[B], the object pointer 233 ubfx r2, rINST, #8, #4 @ r2<- A 234 cmp r3, #0 @ check object for null 235 beq common_errNullObject @ object was null 236 GET_VREG r0, r2 @ r0<- fp[A] 237 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 238 $store r0, [r3, r1] @ obj.field<- r0 239 GET_INST_OPCODE ip @ extract opcode from rINST 240 GOTO_OPCODE ip @ jump to next instruction 241 242%def op_iput_short(): 243% op_iput(helper="MterpIPutI16") 244 245%def op_iput_short_quick(): 246% op_iput_quick(store="strh") 247 248%def op_iput_wide(): 249% op_iput(helper="MterpIPutU64") 250 251%def op_iput_wide_quick(): 252 /* iput-wide-quick vA, vB, offset@CCCC */ 253 mov r2, rINST, lsr #12 @ r2<- B 254 FETCH r3, 1 @ r3<- field byte offset 255 GET_VREG r2, r2 @ r2<- fp[B], the object pointer 256 ubfx r0, rINST, #8, #4 @ r0<- A 257 cmp r2, #0 @ check object for null 258 beq common_errNullObject @ object was null 259 VREG_INDEX_TO_ADDR r0, r0 @ r0<- &fp[A] 260 GET_VREG_WIDE_BY_ADDR r0, r1, r0 @ r0/r1<- fp[A]/fp[A+1] 261 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 262 strd r0, [r2, r3] @ obj.field<- r0/r1 263 GET_INST_OPCODE ip @ extract opcode from rINST 264 GOTO_OPCODE ip @ jump to next instruction 265 266%def op_new_instance(): 267 /* 268 * Create a new instance of a class. 269 */ 270 /* new-instance vAA, class@BBBB */ 271 EXPORT_PC 272 add r0, rFP, #OFF_FP_SHADOWFRAME 273 mov r1, rSELF 274 mov r2, rINST 275 bl MterpNewInstance @ (shadow_frame, self, inst_data) 276 cmp r0, #0 277 beq MterpPossibleException 278 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 279 GET_INST_OPCODE ip @ extract opcode from rINST 280 GOTO_OPCODE ip @ jump to next instruction 281 282%def op_sget(helper="MterpSGetU32"): 283% field(helper=helper) 284 285%def op_sget_boolean(): 286% op_sget(helper="MterpSGetU8") 287 288%def op_sget_byte(): 289% op_sget(helper="MterpSGetI8") 290 291%def op_sget_char(): 292% op_sget(helper="MterpSGetU16") 293 294%def op_sget_object(): 295% op_sget(helper="MterpSGetObj") 296 297%def op_sget_short(): 298% op_sget(helper="MterpSGetI16") 299 300%def op_sget_wide(): 301% op_sget(helper="MterpSGetU64") 302 303%def op_sput(helper="MterpSPutU32"): 304% field(helper=helper) 305 306%def op_sput_boolean(): 307% op_sput(helper="MterpSPutU8") 308 309%def op_sput_byte(): 310% op_sput(helper="MterpSPutI8") 311 312%def op_sput_char(): 313% op_sput(helper="MterpSPutU16") 314 315%def op_sput_object(): 316% op_sput(helper="MterpSPutObj") 317 318%def op_sput_short(): 319% op_sput(helper="MterpSPutI16") 320 321%def op_sput_wide(): 322% op_sput(helper="MterpSPutU64") 323