xref: /aosp_15_r20/art/runtime/interpreter/mterp/arm64ng/invoke.S (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker%def op_invoke_custom():
2*795d594fSAndroid Build Coastguard Worker   EXPORT_PC
3*795d594fSAndroid Build Coastguard Worker   FETCH w0, 1 // call_site index, first argument of runtime call.
4*795d594fSAndroid Build Coastguard Worker   b NterpCommonInvokeCustom
5*795d594fSAndroid Build Coastguard Worker
6*795d594fSAndroid Build Coastguard Worker%def op_invoke_custom_range():
7*795d594fSAndroid Build Coastguard Worker   EXPORT_PC
8*795d594fSAndroid Build Coastguard Worker   FETCH w0, 1 // call_site index, first argument of runtime call.
9*795d594fSAndroid Build Coastguard Worker   b NterpCommonInvokeCustomRange
10*795d594fSAndroid Build Coastguard Worker
11*795d594fSAndroid Build Coastguard Worker%def invoke_direct_or_super(helper="", range="", is_super=""):
12*795d594fSAndroid Build Coastguard Worker   EXPORT_PC
13*795d594fSAndroid Build Coastguard Worker   // Fast-path which gets the method from thread-local cache.
14*795d594fSAndroid Build Coastguard Worker%  fetch_from_thread_cache("x0", miss_label="2f")
15*795d594fSAndroid Build Coastguard Worker1:
16*795d594fSAndroid Build Coastguard Worker   // Load the first argument (the 'this' pointer).
17*795d594fSAndroid Build Coastguard Worker   FETCH w1, 2
18*795d594fSAndroid Build Coastguard Worker   .if !$range
19*795d594fSAndroid Build Coastguard Worker   and w1, w1, #0xf
20*795d594fSAndroid Build Coastguard Worker   .endif
21*795d594fSAndroid Build Coastguard Worker   GET_VREG w1, w1
22*795d594fSAndroid Build Coastguard Worker   cbz w1, common_errNullObject    // bail if null
23*795d594fSAndroid Build Coastguard Worker   b $helper
24*795d594fSAndroid Build Coastguard Worker2:
25*795d594fSAndroid Build Coastguard Worker   mov x0, xSELF
26*795d594fSAndroid Build Coastguard Worker   ldr x1, [sp]
27*795d594fSAndroid Build Coastguard Worker   mov x2, xPC
28*795d594fSAndroid Build Coastguard Worker   bl nterp_get_method
29*795d594fSAndroid Build Coastguard Worker   .if $is_super
30*795d594fSAndroid Build Coastguard Worker   b 1b
31*795d594fSAndroid Build Coastguard Worker   .else
32*795d594fSAndroid Build Coastguard Worker   tbz x0, #0, 1b
33*795d594fSAndroid Build Coastguard Worker   and x0, x0, #-2 // Remove the extra bit that marks it's a String.<init> method.
34*795d594fSAndroid Build Coastguard Worker   .if $range
35*795d594fSAndroid Build Coastguard Worker   b NterpHandleStringInitRange
36*795d594fSAndroid Build Coastguard Worker   .else
37*795d594fSAndroid Build Coastguard Worker   b NterpHandleStringInit
38*795d594fSAndroid Build Coastguard Worker   .endif
39*795d594fSAndroid Build Coastguard Worker   .endif
40*795d594fSAndroid Build Coastguard Worker
41*795d594fSAndroid Build Coastguard Worker%def op_invoke_direct():
42*795d594fSAndroid Build Coastguard Worker%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="0")
43*795d594fSAndroid Build Coastguard Worker
44*795d594fSAndroid Build Coastguard Worker%def op_invoke_direct_range():
45*795d594fSAndroid Build Coastguard Worker%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="0")
46*795d594fSAndroid Build Coastguard Worker
47*795d594fSAndroid Build Coastguard Worker%def op_invoke_super():
48*795d594fSAndroid Build Coastguard Worker%  invoke_direct_or_super(helper="NterpCommonInvokeInstance", range="0", is_super="1")
49*795d594fSAndroid Build Coastguard Worker
50*795d594fSAndroid Build Coastguard Worker%def op_invoke_super_range():
51*795d594fSAndroid Build Coastguard Worker%  invoke_direct_or_super(helper="NterpCommonInvokeInstanceRange", range="1", is_super="1")
52*795d594fSAndroid Build Coastguard Worker
53*795d594fSAndroid Build Coastguard Worker%def op_invoke_polymorphic():
54*795d594fSAndroid Build Coastguard Worker   EXPORT_PC
55*795d594fSAndroid Build Coastguard Worker   // No need to fetch the target method.
56*795d594fSAndroid Build Coastguard Worker   // Load the first argument (the 'this' pointer).
57*795d594fSAndroid Build Coastguard Worker   FETCH w1, 2
58*795d594fSAndroid Build Coastguard Worker   and w1, w1, #0xf
59*795d594fSAndroid Build Coastguard Worker   GET_VREG w1, w1
60*795d594fSAndroid Build Coastguard Worker   cbz w1, common_errNullObject    // bail if null
61*795d594fSAndroid Build Coastguard Worker   b NterpCommonInvokePolymorphic
62*795d594fSAndroid Build Coastguard Worker
63*795d594fSAndroid Build Coastguard Worker%def op_invoke_polymorphic_range():
64*795d594fSAndroid Build Coastguard Worker   EXPORT_PC
65*795d594fSAndroid Build Coastguard Worker   // No need to fetch the target method.
66*795d594fSAndroid Build Coastguard Worker   // Load the first argument (the 'this' pointer).
67*795d594fSAndroid Build Coastguard Worker   FETCH w1, 2
68*795d594fSAndroid Build Coastguard Worker   GET_VREG w1, w1
69*795d594fSAndroid Build Coastguard Worker   cbz w1, common_errNullObject    // bail if null
70*795d594fSAndroid Build Coastguard Worker   b NterpCommonInvokePolymorphicRange
71*795d594fSAndroid Build Coastguard Worker
72*795d594fSAndroid Build Coastguard Worker%def invoke_interface(range=""):
73*795d594fSAndroid Build Coastguard Worker%  slow_path = add_slow_path(invoke_interface_slow_path, range)
74*795d594fSAndroid Build Coastguard Worker   EXPORT_PC
75*795d594fSAndroid Build Coastguard Worker   // Fast-path which gets the method from thread-local cache.
76*795d594fSAndroid Build Coastguard Worker%  fetch_from_thread_cache("x26", miss_label=slow_path)
77*795d594fSAndroid Build Coastguard Worker.L${opcode}_resume:
78*795d594fSAndroid Build Coastguard Worker   // First argument is the 'this' pointer.
79*795d594fSAndroid Build Coastguard Worker   FETCH w1, 2
80*795d594fSAndroid Build Coastguard Worker   .if !$range
81*795d594fSAndroid Build Coastguard Worker   and w1, w1, #0xf
82*795d594fSAndroid Build Coastguard Worker   .endif
83*795d594fSAndroid Build Coastguard Worker   GET_VREG w1, w1
84*795d594fSAndroid Build Coastguard Worker   // Note: if w1 is null, this will be handled by our SIGSEGV handler.
85*795d594fSAndroid Build Coastguard Worker   ldr w2, [x1, #MIRROR_OBJECT_CLASS_OFFSET]
86*795d594fSAndroid Build Coastguard Worker   UNPOISON_HEAP_REF w2
87*795d594fSAndroid Build Coastguard Worker   // Test the first two bits of the fetched ArtMethod:
88*795d594fSAndroid Build Coastguard Worker   // - If the first bit is set, this is a method on j.l.Object
89*795d594fSAndroid Build Coastguard Worker   // - If the second bit is set, this is a default method.
90*795d594fSAndroid Build Coastguard Worker   tst w26, #0x3
91*795d594fSAndroid Build Coastguard Worker   b.ne 2f
92*795d594fSAndroid Build Coastguard Worker   ldrh w3, [x26, #ART_METHOD_IMT_INDEX_OFFSET]
93*795d594fSAndroid Build Coastguard Worker1:
94*795d594fSAndroid Build Coastguard Worker   ldr x2, [x2, #MIRROR_CLASS_IMT_PTR_OFFSET_64]
95*795d594fSAndroid Build Coastguard Worker   ldr x0, [x2, w3, uxtw #3]
96*795d594fSAndroid Build Coastguard Worker   .if $range
97*795d594fSAndroid Build Coastguard Worker   b NterpCommonInvokeInterfaceRange
98*795d594fSAndroid Build Coastguard Worker   .else
99*795d594fSAndroid Build Coastguard Worker   b NterpCommonInvokeInterface
100*795d594fSAndroid Build Coastguard Worker   .endif
101*795d594fSAndroid Build Coastguard Worker2:
102*795d594fSAndroid Build Coastguard Worker   tbnz w26, #0, 3f
103*795d594fSAndroid Build Coastguard Worker   and x26, x26, #-4
104*795d594fSAndroid Build Coastguard Worker   ldrh w3, [x26, #ART_METHOD_METHOD_INDEX_OFFSET]
105*795d594fSAndroid Build Coastguard Worker   and w3, w3, #ART_METHOD_IMT_MASK
106*795d594fSAndroid Build Coastguard Worker   b 1b
107*795d594fSAndroid Build Coastguard Worker3:
108*795d594fSAndroid Build Coastguard Worker   lsr w26, w26, #16
109*795d594fSAndroid Build Coastguard Worker   add w2, w2, #MIRROR_CLASS_VTABLE_OFFSET_64
110*795d594fSAndroid Build Coastguard Worker   ldr x0, [x2, w26, uxtw #3]
111*795d594fSAndroid Build Coastguard Worker   .if $range
112*795d594fSAndroid Build Coastguard Worker   b NterpCommonInvokeInstanceRange
113*795d594fSAndroid Build Coastguard Worker   .else
114*795d594fSAndroid Build Coastguard Worker   b NterpCommonInvokeInstance
115*795d594fSAndroid Build Coastguard Worker   .endif
116*795d594fSAndroid Build Coastguard Worker
117*795d594fSAndroid Build Coastguard Worker%def invoke_interface_slow_path(range):
118*795d594fSAndroid Build Coastguard Worker   mov x0, xSELF
119*795d594fSAndroid Build Coastguard Worker   ldr x1, [sp]
120*795d594fSAndroid Build Coastguard Worker   mov x2, xPC
121*795d594fSAndroid Build Coastguard Worker   bl nterp_get_method
122*795d594fSAndroid Build Coastguard Worker   mov x26, x0
123*795d594fSAndroid Build Coastguard Worker   b .L${opcode}_resume
124*795d594fSAndroid Build Coastguard Worker
125*795d594fSAndroid Build Coastguard Worker%def op_invoke_interface():
126*795d594fSAndroid Build Coastguard Worker%  invoke_interface(range="0")
127*795d594fSAndroid Build Coastguard Worker
128*795d594fSAndroid Build Coastguard Worker%def op_invoke_interface_range():
129*795d594fSAndroid Build Coastguard Worker%  invoke_interface(range="1")
130*795d594fSAndroid Build Coastguard Worker
131*795d594fSAndroid Build Coastguard Worker%def invoke_static(helper=""):
132*795d594fSAndroid Build Coastguard Worker   EXPORT_PC
133*795d594fSAndroid Build Coastguard Worker   // Fast-path which gets the method from thread-local cache.
134*795d594fSAndroid Build Coastguard Worker%  fetch_from_thread_cache("x0", miss_label="1f")
135*795d594fSAndroid Build Coastguard Worker   b $helper
136*795d594fSAndroid Build Coastguard Worker1:
137*795d594fSAndroid Build Coastguard Worker   mov x0, xSELF
138*795d594fSAndroid Build Coastguard Worker   ldr x1, [sp]
139*795d594fSAndroid Build Coastguard Worker   mov x2, xPC
140*795d594fSAndroid Build Coastguard Worker   bl nterp_get_method
141*795d594fSAndroid Build Coastguard Worker   b $helper
142*795d594fSAndroid Build Coastguard Worker
143*795d594fSAndroid Build Coastguard Worker%def op_invoke_static():
144*795d594fSAndroid Build Coastguard Worker%  invoke_static(helper="NterpCommonInvokeStatic")
145*795d594fSAndroid Build Coastguard Worker
146*795d594fSAndroid Build Coastguard Worker%def op_invoke_static_range():
147*795d594fSAndroid Build Coastguard Worker%  invoke_static(helper="NterpCommonInvokeStaticRange")
148*795d594fSAndroid Build Coastguard Worker
149*795d594fSAndroid Build Coastguard Worker%def invoke_virtual(helper="", range=""):
150*795d594fSAndroid Build Coastguard Worker   EXPORT_PC
151*795d594fSAndroid Build Coastguard Worker   // Fast-path which gets the method from thread-local cache.
152*795d594fSAndroid Build Coastguard Worker%  fetch_from_thread_cache("x2", miss_label="2f")
153*795d594fSAndroid Build Coastguard Worker1:
154*795d594fSAndroid Build Coastguard Worker   FETCH w1, 2
155*795d594fSAndroid Build Coastguard Worker   .if !$range
156*795d594fSAndroid Build Coastguard Worker   and w1, w1, #0xf
157*795d594fSAndroid Build Coastguard Worker   .endif
158*795d594fSAndroid Build Coastguard Worker   GET_VREG w1, w1
159*795d594fSAndroid Build Coastguard Worker   // Note: if w1 is null, this will be handled by our SIGSEGV handler.
160*795d594fSAndroid Build Coastguard Worker   ldr w0, [x1, #MIRROR_OBJECT_CLASS_OFFSET]
161*795d594fSAndroid Build Coastguard Worker   UNPOISON_HEAP_REF w0
162*795d594fSAndroid Build Coastguard Worker   add w0, w0, #MIRROR_CLASS_VTABLE_OFFSET_64
163*795d594fSAndroid Build Coastguard Worker   ldr x0, [x0, w2, uxtw #3]
164*795d594fSAndroid Build Coastguard Worker   b $helper
165*795d594fSAndroid Build Coastguard Worker2:
166*795d594fSAndroid Build Coastguard Worker   mov x0, xSELF
167*795d594fSAndroid Build Coastguard Worker   ldr x1, [sp]
168*795d594fSAndroid Build Coastguard Worker   mov x2, xPC
169*795d594fSAndroid Build Coastguard Worker   bl nterp_get_method
170*795d594fSAndroid Build Coastguard Worker   mov x2, x0
171*795d594fSAndroid Build Coastguard Worker   b 1b
172*795d594fSAndroid Build Coastguard Worker
173*795d594fSAndroid Build Coastguard Worker%def op_invoke_virtual():
174*795d594fSAndroid Build Coastguard Worker%  invoke_virtual(helper="NterpCommonInvokeInstance", range="0")
175*795d594fSAndroid Build Coastguard Worker
176*795d594fSAndroid Build Coastguard Worker%def op_invoke_virtual_range():
177*795d594fSAndroid Build Coastguard Worker%  invoke_virtual(helper="NterpCommonInvokeInstanceRange", range="1")
178