• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "arch/asm_support.h"
17#include "arch/x86/shorty.S"
18
19#define SHORTY_PTR_REG DEFAULT_SHORTY_PTR_REG
20#define SHORTY_REG DEFAULT_SHORTY_REG
21
22.macro PUSH_ARG arg_ptr, stack_ptr, tmp1, tmp2
23    cmpl $SHORTY_TAGGED, %ecx
24    je 2f
25
26    subl $SHORTY_FIRST_64, %ecx
27    cmpl $(SHORTY_NUM_64BIT_TYPES - 1), %ecx
28    jbe 1f
29
30    // it is a 32bit value
31    movl (\arg_ptr), \tmp1
32    movl \tmp1, (\stack_ptr)
33    addl $4, \stack_ptr
34    jmp 3f
351:
36    // it is a 64bit value
37    movl (\arg_ptr), \tmp1
38    movl 4(\arg_ptr), \tmp2
39    movl \tmp1, (\stack_ptr)
40    movl \tmp2, 4(\stack_ptr)
41    addl $8, \stack_ptr
42    jne 3f
43
442:  // it is a value of type 'any'
45    // copy the value
46    movl (\arg_ptr), \tmp1
47    movl 4(\arg_ptr), \tmp2
48    movl \tmp1, (\stack_ptr)
49    movl \tmp2, 4(\stack_ptr)
50    // copy the tag
51    movl 8(\arg_ptr), \tmp1
52    movl 12(\arg_ptr), \tmp2
53    movl \tmp1, 8(\stack_ptr)
54    movl \tmp2, 12(\stack_ptr)
55    addl $16, \stack_ptr
56
573:
58.endm
59
60// The macro reserves stack space for the arguments
61// Input:
62// %eax - SHORTY_PTR_REG
63// %edx - SHORTY_REG
64// %ecx - shorty value (no initialization needed)
65// %ebx - method
66// The macro musn't use other registers
67.macro PREPARE_ARG_STACK
68    // check the return type
69    NEXT_SHORTY %ecx
70
71    cmpl $SHORTY_TAGGED, %ecx
72    jne 1f
73    // reserve space for the pointer to which the result will be stored
74    subl $4, %esp
75
761:  subl $4, %esp // space for Method
77
78    // parameter 'this' of instance methods is not encoded in the shorty
79    // check whether the method is an instance
80    movl METHOD_ACCESS_FLAGS_OFFSET(%ebx), %ecx
81    testl $ACCESS_STATIC, %ecx
82    jne 3f
83    // it is an instance method
84    subl $4, %esp // reserve space for this
85
863:
87    NEXT_SHORTY %ecx
88    cmpl $0, %ecx
89    je 6f
90
91    cmpl $SHORTY_TAGGED, %ecx
92    je 5f
93
94    subl $SHORTY_FIRST_64, %ecx
95    cmpl $(SHORTY_NUM_64BIT_TYPES - 1), %ecx
96    jbe 4f
97
98    // it is a 32bit value
99    subl $4, %esp
100    jmp 3b
1014:
102    // it is a 64bit value
103    subl $8, %esp
104    jne 3b
105
1065:  // it is 'any'
107    subl $16, %esp
108    jne 3b
109
1106:
111    // align arg slot 16 byte
112    andl $0xFFFFFFF0, %esp
113.endm
114
115// void InterpreterToCompiledCodeBridge(const BytecodeInstruction* insn, const Frame *iframe, const Method *method, ManagedThread* thread)
116.global InterpreterToCompiledCodeBridge
117.type InterpreterToCompiledCodeBridge, %function
118InterpreterToCompiledCodeBridge:
119    // %esp % 16 == 12 here (-4 == 12 (mod 16))
120    movl %esp, %eax
121
122    pushl 8(%eax) // iframe*
123
124    // According to the current frame kind set the bridge type
125    movl 16(%eax), %ecx
126    movb MANAGED_THREAD_FRAME_KIND_OFFSET(%ecx), %cl
127    testb %cl, %cl
128    jz 1f
129    pushl $BYPASS_BRIDGE
130    jmp 2f
1311:
132    pushl $INTERPRETER_TO_COMPILED_CODE_BRIDGE
1332:
134
135    pushl %ebp
136    pushl %THREAD_REG:thread_pointer@NTPOFF
137
138    pushl %ebx
139    pushl %esi
140    pushl %edi
141    // %esp should be 16-byte aligned here
142
143    movl %eax, %ebp // set frame pointer
144
145    movl 16(%ebp), %eax // thread*
146    movl %eax, %THREAD_REG:thread_pointer@NTPOFF
147
148    movl 12(%ebp), %ebx // method*
149    movl METHOD_SHORTY_OFFSET(%ebx), %SHORTY_PTR_REG // method->shorty*
150    INIT_SHORTY_REG
151
152    PREPARE_ARG_STACK
153
154    // setup regs and memory as follow
155    // %eax - SHORTY_PTR_REG, %edx - SHORTY_REG, %ecx - shorty value, (%esp) - insn_ptr,
156    // 8(%ebp) - iframe, 4(%esp) - iframe->vregs[], %edi - pointer to stack
157    movl METHOD_SHORTY_OFFSET(%ebx), %SHORTY_PTR_REG // method->shorty*
158    INIT_SHORTY_REG
159
160    movl %esp, %edi
161    subl $8, %esp
162
163    movl 8(%ebp), %ebx // iframe*
164    addl $FRAME_VREGS_OFFSET, %ebx // iframe->vregs[]
165    pushl %ebx
166
167    // check the return type
168    NEXT_SHORTY %ecx
169    cmpl $SHORTY_TAGGED, %ecx
170    jne 1f
171    // the return type is 'any'
172    movl 8(%ebp), %ebx
173    addl $FRAME_ACC_OFFSET, %ebx // iframe->acc
174    movl %ebx, (%edi)
175    addl $4, %edi
176
1771:  movl 12(%ebp), %ebx // method*
178    movl %ebx, (%edi) // push method to the stack
179    addl $4, %edi
180
181    // parameter 'this' of instance methods is not encoded in the shorty
182    // in case of instance method hack SHORTY_REG by replacing the return type by REF
183    // in the another case just skip the return type
184    // check whether the method is an instance
185    movl METHOD_ACCESS_FLAGS_OFFSET(%ebx), %ecx
186    testl $ACCESS_STATIC, %ecx
187    jne 1f
188    // it is an instance method
189    // replace the return type by REF
190    shll $4, %SHORTY_REG // unshift SHORTY_REG back
191    orl $SHORTY_REFERENCE, %SHORTY_REG
192
1931:  movl 4(%ebp), %esi // insn*
194    movzbl (%esi), %ebx // read opcode and advance insn_ptr
195    addl $1, %esi
196    pushl %esi
197
198    // The file contains code which checks opcode and jumps
199    // to the corresponding handler.
200    // At the end each handler jumps to .Linvoke_from_bridge label.
201    // The file is autogenerated from runtime/templates/bridge_dispatch.S.erb
202    // Handlers are distinguished by format and located in the corresponding files with name:
203    // handle_call_<format>.S
204    // If you get a compilation error that there is no such file it seems
205    // new call format was introduced and you have to implement the corresponding handler.
206#include "bridge_dispatch_x86.S"
207
208.Linvoke_from_bridge:
209    addl $16, %esp
210    // %esp should be 16-byte aligned here
211    movl 12(%ebp), %ebx // method*
212    movl METHOD_SHORTY_OFFSET(%ebx), %esi // method->shorty*
213    movl METHOD_COMPILED_ENTRY_POINT_OFFSET(%ebx), %ebx // method->entry_point*
214
215    calll *%ebx
216
217    // handle the result
218    // setup registers as follow
219    // %eax, %edx - result, %esi - shorty[0] & 0xF, %edi - frame.acc, %ebx, %ecx - temp
220    movzbl (%esi), %esi
221    andl $0xF, %esi
222
223    cmpl $SHORTY_VOID, %esi
224    je .Lreturn
225    cmpl $SHORTY_TAGGED, %esi
226    je .Lreturn
227
228    movl 8(%ebp), %edi // iframe*
229    addl $FRAME_ACC_OFFSET, %edi
230
231    xorl %ecx, %ecx
232    cmpl $SHORTY_REFERENCE, %esi
233    sete %cl
234    movl %ecx, FRAME_ACC_MIRROR_OFFSET(%edi)
235    je .L32bit_arg
236
237    movl %esi, %ebx
238    movl %esi, %ecx
239
240    subl $SHORTY_FIRST_FLOAT, %ebx
241    cmpl $(SHORTY_NUM_FLOAT_TYPES - 1), %ebx
242    jbe .Lfloat
243
244    subl $SHORTY_FIRST_64, %esi
245    cmpl $(SHORTY_NUM_64BIT_TYPES - 1), %esi
246    jbe .L64bit_arg
247
248    cmpl $SHORTY_I32, %ecx
249    jae .L32bit_arg
250
251    // less than 32-bit
252    cmpl $SHORTY_I16, %ecx
253    je .LI16
254    ja .LU16
255
256    cmpl $SHORTY_I8, %ecx
257    je .LI8
258    jne .LU1_U8
259
260.LU1_U8:
261    movzbl %al, %eax
262    jmp .L32bit_arg
263.LI8:
264    movsbl %al, %eax
265    jmp .L32bit_arg
266.LI16:
267    movswl %ax, %eax
268    jmp .L32bit_arg
269.LU16:
270    movzwl %ax, %eax
271.L32bit_arg:
272    movl %eax, (%edi)
273    jmp .Lreturn
274.Lfloat:
275    fstpl (%edi)
276    jmp .Lreturn
277.L64bit_arg:
278    movl %eax, (%edi)
279    movl %edx, 4(%edi)
280
281.Lreturn:
282    leal -28(%ebp), %esp
283
284    popl %edi
285    popl %esi
286    popl %ebx
287    popl %THREAD_REG:thread_pointer@NTPOFF
288    popl %ebp
289
290    addl $8, %esp
291    retl
292
293
294// uint64_t InvokeCompiledCodeWithArgArray(const int64_t* args, const Frame *iframe, const Method *method, ManagedThread* thread)
295.global InvokeCompiledCodeWithArgArray
296.type InvokeCompiledCodeWithArgArray, %function
297InvokeCompiledCodeWithArgArray:
298    // Since Invocation result is 128bit structure the first argument is a pointer to
299    // memory where the result must be stored
300
301    // %esp % 16 == 12 here (-4 == 12 (mod 16))
302    movl %esp, %eax
303
304    pushl 12(%eax) // iframe*
305
306    // According to the current frame kind set the bridge type
307    movl 20(%eax), %ecx
308    movb MANAGED_THREAD_FRAME_KIND_OFFSET(%ecx), %cl
309    testb %cl, %cl
310    jz 1f
311    pushl $BYPASS_BRIDGE
312    jmp 2f
3131:
314    pushl $INTERPRETER_TO_COMPILED_CODE_BRIDGE
3152:
316
317    pushl %ebp
318    pushl %THREAD_REG:thread_pointer@NTPOFF
319
320    pushl %ebx
321    pushl %esi
322    pushl %edi
323    // %esp should be 16-byte aligned here
324
325    movl %eax, %ebp // set frame pointer
326
327    movl 20(%ebp), %eax // thread*
328    movl %eax, %THREAD_REG:thread_pointer@NTPOFF
329
330    movl 16(%ebp), %ebx // method*
331    movl METHOD_SHORTY_OFFSET(%ebx), %esi // method->shorty*
332
3331:
334    movl METHOD_SHORTY_OFFSET(%ebx), %SHORTY_PTR_REG // method->shorty*
335    INIT_SHORTY_REG
336
337    PREPARE_ARG_STACK
338
339    // setup regs and memory as follow
340    // %eax - SHORTY_PTR_REG, %edx - SHORTY_REG, %ecx - shorty value, %esi - args[],
341    // %edi - pointer to stack
342    movl METHOD_SHORTY_OFFSET(%ebx), %SHORTY_PTR_REG // method->shorty*
343    INIT_SHORTY_REG
344
345    movl 8(%ebp), %esi // args[]
346    movl %esp, %edi
347    subl $8, %esp
348
349    // check the return type
350    NEXT_SHORTY %ecx
351    cmpl $SHORTY_TAGGED, %ecx
352    jne 1f
353    // the return type is 'any'
354    // push the pointer to memory where the result must be stored
355    movl 4(%ebp), %ecx
356    movl %ecx, (%edi)
357    addl $4, %edi
358
3591:  movl %ebx, (%edi) // push method to the stack
360    addl $4, %edi
361
362    // parameter 'this' of instance methods is not encoded in the shorty
363    // in case of instance method hack SHORTY_REG by replacing the return type by REF
364    // in the another case just skip the return type
365    // check whether the method is an instance
366    movl METHOD_ACCESS_FLAGS_OFFSET(%ebx), %ecx
367    testl $ACCESS_STATIC, %ecx
368    jne .Lloop_args_push
369    // it is an instance method
370    // replace the return type by REF
371    shll $4, %SHORTY_REG // unshift SHORTY_REG back
372    orl $SHORTY_REFERENCE, %SHORTY_REG
373
374.Lloop_args_push:
375    NEXT_SHORTY %ecx
376    cmpl $0, %ecx
377    je .Lloopend_args_push
378
379    movl %eax, (%esp)
380    movl %edx, 4(%esp)
381    // handle the first arg index
382    PUSH_ARG %esi, %edi, %eax, %edx
383    movl (%esp), %eax
384    movl 4(%esp), %edx
385
386    addl $8, %esi
387    jmp .Lloop_args_push
388.Lloopend_args_push:
389    movl METHOD_SHORTY_OFFSET(%ebx), %esi // method->shorty*
390    addl $8, %esp
391
392.Linvoke_with_args:
393    movl METHOD_COMPILED_ENTRY_POINT_OFFSET(%ebx), %ebx // method->entry_point*
394    calll *%ebx
395
396    // handle the result
397    // setup registers as follow
398    // %eax, %edx - result, %esi - shorty[0] & 0xF, %edi - tag, %ebx - temp
399    movzbl (%esi), %esi
400    andl $0xF, %esi
401
402    cmpl $SHORTY_VOID, %esi
403    je .Lreturn_
404    cmpl $SHORTY_TAGGED, %esi
405    je .Lreturn_
406
407    movl %esi, %ebx
408    movl %esi, %ecx
409
410    subl $SHORTY_FIRST_FLOAT, %ebx
411    cmpl $(SHORTY_NUM_FLOAT_TYPES - 1), %ebx
412    jbe .Lfloat_
413
414    subl $SHORTY_FIRST_64, %esi
415    cmpl $(SHORTY_NUM_64BIT_TYPES - 1), %esi
416    jbe .Lstore_result_
417
418    // set high 32 bits of 64bit value to 0
419    xorl %edx, %edx
420
421    cmpl $SHORTY_I32, %ecx
422    jae .Lstore_result_ // i32, u32 or ref
423
424    // less than 32-bit
425    cmpl $SHORTY_I16, %ecx
426    je .LI16_
427    ja .LU16_
428
429    cmpl $SHORTY_I8, %ecx
430    je .LI8_
431    jne .LU1_U8_
432
433.LU1_U8_:
434    movzbl %al, %eax
435    jmp .Lstore_result_
436.LI8_:
437    movsbl %al, %eax
438    jmp .Lstore_result_
439.LI16_:
440    movswl %ax, %eax
441    jmp .Lstore_result_
442.LU16_:
443    movzwl %ax, %eax
444    jmp .Lstore_result_
445.Lfloat_:
446    subl $8, %esp
447    fstpl (%esp)
448    movl (%esp), %eax
449    movl 4(%esp), %edx
450    addl $8, %esp
451
452.Lstore_result_:
453    // get result ptr in %ebx
454    movl 4(%ebp), %ebx
455    // store value
456    movl %eax, (%ebx)
457    movl %edx, 4(%ebx)
458.Lreturn_:
459    leal -28(%ebp), %esp
460
461    popl %edi
462    popl %esi
463    popl %ebx
464    popl %THREAD_REG:thread_pointer@NTPOFF
465    popl %ebp
466
467    addl $8, %esp
468    // return and pop the pointer to the result
469    retl $4
470
471.type thread_pointer,@object
472.section .tbss,"awT",@nobits
473.globl thread_pointer
474.p2align 2
475thread_pointer:
476    .long 0
477    .size  thread_pointer, 4
478