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_byte(): 91% op_iget(load="ldrsb", helper="MterpIGetI8") 92 93%def op_iget_char(): 94% op_iget(load="ldrh", helper="MterpIGetU16") 95 96%def op_iget_object(): 97% op_iget(is_object=True, helper="MterpIGetObj") 98 99%def op_iget_short(): 100% op_iget(load="ldrsh", helper="MterpIGetI16") 101 102%def op_iget_wide(): 103% op_iget(is_wide=True, helper="MterpIGetU64") 104 105%def op_instance_of(): 106 /* 107 * Check to see if an object reference is an instance of a class. 108 * 109 * Most common situation is a non-null object, being compared against 110 * an already-resolved class. 111 */ 112 /* instance-of vA, vB, class@CCCC */ 113 EXPORT_PC 114 FETCH r0, 1 @ r0<- CCCC 115 mov r1, rINST, lsr #12 @ r1<- B 116 VREG_INDEX_TO_ADDR r1, r1 @ r1<- &object 117 ldr r2, [rFP, #OFF_FP_METHOD] @ r2<- method 118 mov r3, rSELF @ r3<- self 119 bl MterpInstanceOf @ (index, &obj, method, self) 120 ldr r1, [rSELF, #THREAD_EXCEPTION_OFFSET] 121 ubfx r9, rINST, #8, #4 @ r9<- A 122 PREFETCH_INST 2 123 cmp r1, #0 @ exception pending? 124 bne MterpException 125 ADVANCE 2 @ advance rPC 126 SET_VREG r0, r9 @ vA<- r0 127 GET_INST_OPCODE ip @ extract opcode from rINST 128 GOTO_OPCODE ip @ jump to next instruction 129 130%def op_iput(helper="MterpIPutU32"): 131% field(helper=helper) 132 133%def op_iput_boolean(): 134% op_iput(helper="MterpIPutU8") 135 136%def op_iput_byte(): 137% op_iput(helper="MterpIPutI8") 138 139%def op_iput_char(): 140% op_iput(helper="MterpIPutU16") 141 142%def op_iput_object(): 143% op_iput(helper="MterpIPutObj") 144 145%def op_iput_short(): 146% op_iput(helper="MterpIPutI16") 147 148%def op_iput_wide(): 149% op_iput(helper="MterpIPutU64") 150 151%def op_new_instance(): 152 /* 153 * Create a new instance of a class. 154 */ 155 /* new-instance vAA, class@BBBB */ 156 EXPORT_PC 157 add r0, rFP, #OFF_FP_SHADOWFRAME 158 mov r1, rSELF 159 mov r2, rINST 160 bl MterpNewInstance @ (shadow_frame, self, inst_data) 161 cmp r0, #0 162 beq MterpPossibleException 163 FETCH_ADVANCE_INST 2 @ advance rPC, load rINST 164 GET_INST_OPCODE ip @ extract opcode from rINST 165 GOTO_OPCODE ip @ jump to next instruction 166 167%def op_sget(helper="MterpSGetU32"): 168% field(helper=helper) 169 170%def op_sget_boolean(): 171% op_sget(helper="MterpSGetU8") 172 173%def op_sget_byte(): 174% op_sget(helper="MterpSGetI8") 175 176%def op_sget_char(): 177% op_sget(helper="MterpSGetU16") 178 179%def op_sget_object(): 180% op_sget(helper="MterpSGetObj") 181 182%def op_sget_short(): 183% op_sget(helper="MterpSGetI16") 184 185%def op_sget_wide(): 186% op_sget(helper="MterpSGetU64") 187 188%def op_sput(helper="MterpSPutU32"): 189% field(helper=helper) 190 191%def op_sput_boolean(): 192% op_sput(helper="MterpSPutU8") 193 194%def op_sput_byte(): 195% op_sput(helper="MterpSPutI8") 196 197%def op_sput_char(): 198% op_sput(helper="MterpSPutU16") 199 200%def op_sput_object(): 201% op_sput(helper="MterpSPutObj") 202 203%def op_sput_short(): 204% op_sput(helper="MterpSPutI16") 205 206%def op_sput_wide(): 207% op_sput(helper="MterpSPutU64") 208