You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
6.4 KiB
202 lines
6.4 KiB
%def field(helper=""):
|
|
/*
|
|
* General field read / write (iget-* iput-* sget-* sput-*).
|
|
*/
|
|
.extern $helper
|
|
mov x0, xPC // arg0: Instruction* inst
|
|
mov x1, xINST // arg1: uint16_t inst_data
|
|
add x2, xFP, #OFF_FP_SHADOWFRAME // arg2: ShadowFrame* sf
|
|
mov x3, xSELF // arg3: Thread* self
|
|
PREFETCH_INST 2 // prefetch next opcode
|
|
bl $helper
|
|
cbz x0, MterpPossibleException
|
|
ADVANCE 2
|
|
GET_INST_OPCODE ip // extract opcode from rINST
|
|
GOTO_OPCODE ip // jump to next instruction
|
|
|
|
%def op_check_cast():
|
|
/*
|
|
* Check to see if a cast from one class to another is allowed.
|
|
*/
|
|
/* check-cast vAA, class//BBBB */
|
|
EXPORT_PC
|
|
FETCH w0, 1 // w0<- BBBB
|
|
lsr w1, wINST, #8 // w1<- AA
|
|
VREG_INDEX_TO_ADDR x1, w1 // w1<- &object
|
|
ldr x2, [xFP, #OFF_FP_METHOD] // w2<- method
|
|
mov x3, xSELF // w3<- self
|
|
bl MterpCheckCast // (index, &obj, method, self)
|
|
PREFETCH_INST 2
|
|
cbnz w0, MterpPossibleException
|
|
ADVANCE 2
|
|
GET_INST_OPCODE ip // extract opcode from rINST
|
|
GOTO_OPCODE ip // jump to next instruction
|
|
|
|
%def op_iget(is_object=False, is_wide=False, load="ldr", helper="MterpIGetU32"):
|
|
// Fast-path which gets the field offset from thread-local cache.
|
|
add x0, xSELF, #THREAD_INTERPRETER_CACHE_OFFSET // cache address
|
|
ubfx x1, xPC, #2, #THREAD_INTERPRETER_CACHE_SIZE_LOG2 // entry index
|
|
add x0, x0, x1, lsl #4 // entry address within the cache
|
|
ldp x0, x1, [x0] // entry key (pc) and value (offset)
|
|
lsr w2, wINST, #12 // B
|
|
GET_VREG w2, w2 // object we're operating on
|
|
cmp x0, xPC
|
|
% slow_path_label = add_helper(lambda: field(helper))
|
|
b.ne ${slow_path_label} // cache miss
|
|
cbz w2, common_errNullObject // null object
|
|
% if is_wide:
|
|
ldr x0, [x2, x1] // x0<- obj.field
|
|
% else:
|
|
${load} w0, [x2, x1] // w0<- obj.field
|
|
% #endif
|
|
% if is_object:
|
|
UNPOISON_HEAP_REF w0
|
|
#if defined(USE_READ_BARRIER)
|
|
# if defined(USE_BAKER_READ_BARRIER)
|
|
ldr w1, [xSELF, #THREAD_IS_GC_MARKING_OFFSET]
|
|
cbnz w1, .L_${opcode}_mark // GC is active.
|
|
.L_${opcode}_marked:
|
|
# else
|
|
bl artReadBarrierMark // x0 <- artReadBarrierMark(x0)
|
|
# endif
|
|
#endif
|
|
% #endif
|
|
ubfx w2, wINST, #8, #4 // w2<- A
|
|
FETCH_ADVANCE_INST 2 // advance rPC, load rINST
|
|
% if is_object:
|
|
SET_VREG_OBJECT w0, w2 // fp[A]<- w0
|
|
% elif is_wide:
|
|
SET_VREG_WIDE x0, w2 // fp[A]<- x0
|
|
% else:
|
|
SET_VREG w0, w2 // fp[A]<- w0
|
|
% #endif
|
|
GET_INST_OPCODE ip // extract opcode from rINST
|
|
GOTO_OPCODE ip // jump to next instruction
|
|
% if is_object:
|
|
#if defined(USE_READ_BARRIER) && defined(USE_BAKER_READ_BARRIER)
|
|
.L_${opcode}_mark:
|
|
bl artReadBarrierMark // x0 <- artReadBarrierMark(x0)
|
|
b .L_${opcode}_marked
|
|
#endif
|
|
% #endif
|
|
|
|
%def op_iget_boolean():
|
|
% op_iget(load="ldrb", helper="MterpIGetU8")
|
|
|
|
%def op_iget_byte():
|
|
% op_iget(load="ldrsb", helper="MterpIGetI8")
|
|
|
|
%def op_iget_char():
|
|
% op_iget(load="ldrh", helper="MterpIGetU16")
|
|
|
|
%def op_iget_object():
|
|
% op_iget(is_object=True, helper="MterpIGetObj")
|
|
|
|
%def op_iget_short():
|
|
% op_iget(load="ldrsh", helper="MterpIGetI16")
|
|
|
|
%def op_iget_wide():
|
|
% op_iget(is_wide=True, helper="MterpIGetU64")
|
|
|
|
%def op_instance_of():
|
|
/*
|
|
* Check to see if an object reference is an instance of a class.
|
|
*
|
|
* Most common situation is a non-null object, being compared against
|
|
* an already-resolved class.
|
|
*/
|
|
/* instance-of vA, vB, class//CCCC */
|
|
EXPORT_PC
|
|
FETCH w0, 1 // w0<- CCCC
|
|
lsr w1, wINST, #12 // w1<- B
|
|
VREG_INDEX_TO_ADDR x1, w1 // w1<- &object
|
|
ldr x2, [xFP, #OFF_FP_METHOD] // w2<- method
|
|
mov x3, xSELF // w3<- self
|
|
bl MterpInstanceOf // (index, &obj, method, self)
|
|
ldr x1, [xSELF, #THREAD_EXCEPTION_OFFSET]
|
|
ubfx w2, wINST, #8, #4 // w2<- A
|
|
PREFETCH_INST 2
|
|
cbnz x1, MterpException
|
|
ADVANCE 2 // advance rPC
|
|
SET_VREG w0, w2 // vA<- w0
|
|
GET_INST_OPCODE ip // extract opcode from rINST
|
|
GOTO_OPCODE ip // jump to next instruction
|
|
|
|
%def op_iput(helper="MterpIPutU32"):
|
|
% field(helper=helper)
|
|
|
|
%def op_iput_boolean():
|
|
% op_iput(helper="MterpIPutU8")
|
|
|
|
%def op_iput_byte():
|
|
% op_iput(helper="MterpIPutI8")
|
|
|
|
%def op_iput_char():
|
|
% op_iput(helper="MterpIPutU16")
|
|
|
|
%def op_iput_object():
|
|
% op_iput(helper="MterpIPutObj")
|
|
|
|
%def op_iput_short():
|
|
% op_iput(helper="MterpIPutI16")
|
|
|
|
%def op_iput_wide():
|
|
% op_iput(helper="MterpIPutU64")
|
|
|
|
%def op_new_instance():
|
|
/*
|
|
* Create a new instance of a class.
|
|
*/
|
|
/* new-instance vAA, class//BBBB */
|
|
EXPORT_PC
|
|
add x0, xFP, #OFF_FP_SHADOWFRAME
|
|
mov x1, xSELF
|
|
mov w2, wINST
|
|
bl MterpNewInstance // (shadow_frame, self, inst_data)
|
|
cbz w0, MterpPossibleException
|
|
FETCH_ADVANCE_INST 2 // advance rPC, load rINST
|
|
GET_INST_OPCODE ip // extract opcode from rINST
|
|
GOTO_OPCODE ip // jump to next instruction
|
|
|
|
%def op_sget(helper="MterpSGetU32"):
|
|
% field(helper=helper)
|
|
|
|
%def op_sget_boolean():
|
|
% op_sget(helper="MterpSGetU8")
|
|
|
|
%def op_sget_byte():
|
|
% op_sget(helper="MterpSGetI8")
|
|
|
|
%def op_sget_char():
|
|
% op_sget(helper="MterpSGetU16")
|
|
|
|
%def op_sget_object():
|
|
% op_sget(helper="MterpSGetObj")
|
|
|
|
%def op_sget_short():
|
|
% op_sget(helper="MterpSGetI16")
|
|
|
|
%def op_sget_wide():
|
|
% op_sget(helper="MterpSGetU64")
|
|
|
|
%def op_sput(helper="MterpSPutU32"):
|
|
% field(helper=helper)
|
|
|
|
%def op_sput_boolean():
|
|
% op_sput(helper="MterpSPutU8")
|
|
|
|
%def op_sput_byte():
|
|
% op_sput(helper="MterpSPutI8")
|
|
|
|
%def op_sput_char():
|
|
% op_sput(helper="MterpSPutU16")
|
|
|
|
%def op_sput_object():
|
|
% op_sput(helper="MterpSPutObj")
|
|
|
|
%def op_sput_short():
|
|
% op_sput(helper="MterpSPutI16")
|
|
|
|
%def op_sput_wide():
|
|
% op_sput(helper="MterpSPutU64")
|