1%def field(helper=""): 2 /* 3 * General field read / write (iget-* iput-* sget-* sput-*). 4 */ 5 .extern $helper 6 mov x0, xPC // arg0: Instruction* inst 7 mov x1, xINST // arg1: uint16_t inst_data 8 add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf 9 mov x3, xSELF // arg3: Thread* self 10 PREFETCH_INST 2 // prefetch next opcode 11 bl $helper 12 cbz x0, MterpPossibleException 13 ADVANCE 2 14 GET_INST_OPCODE ip // extract opcode from rINST 15 GOTO_OPCODE ip // jump to next instruction 16 17%def op_check_cast(): 18 /* 19 * Check to see if a cast from one class to another is allowed. 20 */ 21 /* check-cast vAA, class//BBBB */ 22 EXPORT_PC 23 FETCH w0, 1 // w0<- BBBB 24 lsr w1, wINST, #8 // w1<- AA 25 VREG_INDEX_TO_ADDR x1, w1 // w1<- &object 26 ldr x2, [xFP, #OFF_FP_METHOD] // w2<- method 27 mov x3, xSELF // w3<- self 28 bl MterpCheckCast // (index, &obj, method, self) 29 PREFETCH_INST 2 30 cbnz w0, MterpPossibleException 31 ADVANCE 2 32 GET_INST_OPCODE ip // extract opcode from rINST 33 GOTO_OPCODE ip // jump to next instruction 34 35%def op_iget(is_object=False, is_wide=False, load="ldr", helper="MterpIGetU32"): 36 // Fast-path which gets the field offset from thread-local cache. 37 add x0, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address 38 ubfx x1, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index 39 add x0, x0, x1, lsl #4 // entry address within the cache 40 ldp x0, x1, [x0] // entry key (pc) and value (offset) 41 lsr w2, wINST, #12 // B 42 GET_VREG w2, w2 // object we're operating on 43 cmp x0, xPC 44% slow_path_label = add_helper(lambda: field(helper)) 45 b.ne ${slow_path_label} // cache miss 46 cbz w2, common_errNullObject // null object 47% if is_wide: 48 ldr x0, [x2, x1] // x0<- obj.field 49% else: 50 ${load} w0, [x2, x1] // w0<- obj.field 51% #endif 52% if is_object: 53 UNPOISON_HEAP_REF w0 54#if defined(USE_READ_BARRIER) 55# if defined(USE_BAKER_READ_BARRIER) 56 ldr w1, [xSELF, #THREAD_IS_GC_MARKING_OFFSET] 57 cbnz w1, .L_${opcode}_mark // GC is active. 58.L_${opcode}_marked: 59# else 60 bl artReadBarrierMark // x0 <- artReadBarrierMark(x0) 61# endif 62#endif 63% #endif 64 ubfx w2, wINST, #8, #4 // w2<- A 65 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 66% if is_object: 67 SET_VREG_OBJECT w0, w2 // fp[A]<- w0 68% elif is_wide: 69 SET_VREG_WIDE x0, w2 // fp[A]<- x0 70% else: 71 SET_VREG w0, w2 // fp[A]<- w0 72% #endif 73 GET_INST_OPCODE ip // extract opcode from rINST 74 GOTO_OPCODE ip // jump to next instruction 75% if is_object: 76#if defined(USE_READ_BARRIER) && defined(USE_BAKER_READ_BARRIER) 77.L_${opcode}_mark: 78 bl artReadBarrierMark // x0 <- artReadBarrierMark(x0) 79 b .L_${opcode}_marked 80#endif 81% #endif 82 83%def op_iget_boolean(): 84% op_iget(load="ldrb", helper="MterpIGetU8") 85 86%def op_iget_byte(): 87% op_iget(load="ldrsb", helper="MterpIGetI8") 88 89%def op_iget_char(): 90% op_iget(load="ldrh", helper="MterpIGetU16") 91 92%def op_iget_object(): 93% op_iget(is_object=True, helper="MterpIGetObj") 94 95%def op_iget_short(): 96% op_iget(load="ldrsh", helper="MterpIGetI16") 97 98%def op_iget_wide(): 99% op_iget(is_wide=True, helper="MterpIGetU64") 100 101%def op_instance_of(): 102 /* 103 * Check to see if an object reference is an instance of a class. 104 * 105 * Most common situation is a non-null object, being compared against 106 * an already-resolved class. 107 */ 108 /* instance-of vA, vB, class//CCCC */ 109 EXPORT_PC 110 FETCH w0, 1 // w0<- CCCC 111 lsr w1, wINST, #12 // w1<- B 112 VREG_INDEX_TO_ADDR x1, w1 // w1<- &object 113 ldr x2, [xFP, #OFF_FP_METHOD] // w2<- method 114 mov x3, xSELF // w3<- self 115 bl MterpInstanceOf // (index, &obj, method, self) 116 ldr x1, [xSELF, #THREAD_EXCEPTION_OFFSET] 117 ubfx w2, wINST, #8, #4 // w2<- A 118 PREFETCH_INST 2 119 cbnz x1, MterpException 120 ADVANCE 2 // advance rPC 121 SET_VREG w0, w2 // vA<- w0 122 GET_INST_OPCODE ip // extract opcode from rINST 123 GOTO_OPCODE ip // jump to next instruction 124 125%def op_iput(helper="MterpIPutU32"): 126% field(helper=helper) 127 128%def op_iput_boolean(): 129% op_iput(helper="MterpIPutU8") 130 131%def op_iput_byte(): 132% op_iput(helper="MterpIPutI8") 133 134%def op_iput_char(): 135% op_iput(helper="MterpIPutU16") 136 137%def op_iput_object(): 138% op_iput(helper="MterpIPutObj") 139 140%def op_iput_short(): 141% op_iput(helper="MterpIPutI16") 142 143%def op_iput_wide(): 144% op_iput(helper="MterpIPutU64") 145 146%def op_new_instance(): 147 /* 148 * Create a new instance of a class. 149 */ 150 /* new-instance vAA, class//BBBB */ 151 EXPORT_PC 152 add x0, xFP, #OFF_FP_SHADOWFRAME 153 mov x1, xSELF 154 mov w2, wINST 155 bl MterpNewInstance // (shadow_frame, self, inst_data) 156 cbz w0, MterpPossibleException 157 FETCH_ADVANCE_INST 2 // advance rPC, load rINST 158 GET_INST_OPCODE ip // extract opcode from rINST 159 GOTO_OPCODE ip // jump to next instruction 160 161%def op_sget(helper="MterpSGetU32"): 162% field(helper=helper) 163 164%def op_sget_boolean(): 165% op_sget(helper="MterpSGetU8") 166 167%def op_sget_byte(): 168% op_sget(helper="MterpSGetI8") 169 170%def op_sget_char(): 171% op_sget(helper="MterpSGetU16") 172 173%def op_sget_object(): 174% op_sget(helper="MterpSGetObj") 175 176%def op_sget_short(): 177% op_sget(helper="MterpSGetI16") 178 179%def op_sget_wide(): 180% op_sget(helper="MterpSGetU64") 181 182%def op_sput(helper="MterpSPutU32"): 183% field(helper=helper) 184 185%def op_sput_boolean(): 186% op_sput(helper="MterpSPutU8") 187 188%def op_sput_byte(): 189% op_sput(helper="MterpSPutI8") 190 191%def op_sput_char(): 192% op_sput(helper="MterpSPutU16") 193 194%def op_sput_object(): 195% op_sput(helper="MterpSPutObj") 196 197%def op_sput_short(): 198% op_sput(helper="MterpSPutI16") 199 200%def op_sput_wide(): 201% op_sput(helper="MterpSPutU64") 202