xref: /aosp_15_r20/art/runtime/interpreter/mterp/x86ng/control_flow.S (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker%def bincmp(revcmp=""):
2*795d594fSAndroid Build Coastguard Worker/*
3*795d594fSAndroid Build Coastguard Worker * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
4*795d594fSAndroid Build Coastguard Worker * fragment that specifies the *reverse* comparison to perform, e.g.
5*795d594fSAndroid Build Coastguard Worker * for "if-le" you would use "gt".
6*795d594fSAndroid Build Coastguard Worker *
7*795d594fSAndroid Build Coastguard Worker * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
8*795d594fSAndroid Build Coastguard Worker */
9*795d594fSAndroid Build Coastguard Worker    /* if-cmp vA, vB, +CCCC */
10*795d594fSAndroid Build Coastguard Worker    movl    rINST, %ecx                     # rcx <- A+
11*795d594fSAndroid Build Coastguard Worker    sarl    $$4, rINST                      # rINST <- B
12*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, %cl                      # rcx <- A
13*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %ecx                     # eax <- vA
14*795d594fSAndroid Build Coastguard Worker    cmpl    VREG_ADDRESS(rINST), %eax       # compare (vA, vB)
15*795d594fSAndroid Build Coastguard Worker    j${revcmp} 1f
16*795d594fSAndroid Build Coastguard Worker    movswl  2(rPC), rINST                   # Get signed branch offset
17*795d594fSAndroid Build Coastguard Worker    BRANCH
18*795d594fSAndroid Build Coastguard Worker1:
19*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
20*795d594fSAndroid Build Coastguard Worker
21*795d594fSAndroid Build Coastguard Worker%def zcmp(revcmp=""):
22*795d594fSAndroid Build Coastguard Worker/*
23*795d594fSAndroid Build Coastguard Worker * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
24*795d594fSAndroid Build Coastguard Worker * fragment that specifies the *reverse* comparison to perform, e.g.
25*795d594fSAndroid Build Coastguard Worker * for "if-le" you would use "gt".
26*795d594fSAndroid Build Coastguard Worker *
27*795d594fSAndroid Build Coastguard Worker * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
28*795d594fSAndroid Build Coastguard Worker */
29*795d594fSAndroid Build Coastguard Worker    /* if-cmp vAA, +BBBB */
30*795d594fSAndroid Build Coastguard Worker    cmpl    $$0, VREG_ADDRESS(rINST)        # compare (vA, 0)
31*795d594fSAndroid Build Coastguard Worker    j${revcmp} 1f
32*795d594fSAndroid Build Coastguard Worker    movswl  2(rPC), rINST                   # fetch signed displacement
33*795d594fSAndroid Build Coastguard Worker    BRANCH
34*795d594fSAndroid Build Coastguard Worker1:
35*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
36*795d594fSAndroid Build Coastguard Worker
37*795d594fSAndroid Build Coastguard Worker%def op_goto():
38*795d594fSAndroid Build Coastguard Worker/*
39*795d594fSAndroid Build Coastguard Worker * Unconditional branch, 8-bit offset.
40*795d594fSAndroid Build Coastguard Worker *
41*795d594fSAndroid Build Coastguard Worker * The branch distance is a signed code-unit offset, which we need to
42*795d594fSAndroid Build Coastguard Worker * double to get a byte offset.
43*795d594fSAndroid Build Coastguard Worker */
44*795d594fSAndroid Build Coastguard Worker    /* goto +AA */
45*795d594fSAndroid Build Coastguard Worker    movsbl  rINSTbl, rINST                  # rINST <- ssssssAA
46*795d594fSAndroid Build Coastguard Worker    BRANCH
47*795d594fSAndroid Build Coastguard Worker
48*795d594fSAndroid Build Coastguard Worker%def op_goto_16():
49*795d594fSAndroid Build Coastguard Worker/*
50*795d594fSAndroid Build Coastguard Worker * Unconditional branch, 16-bit offset.
51*795d594fSAndroid Build Coastguard Worker *
52*795d594fSAndroid Build Coastguard Worker * The branch distance is a signed code-unit offset, which we need to
53*795d594fSAndroid Build Coastguard Worker * double to get a byte offset.
54*795d594fSAndroid Build Coastguard Worker */
55*795d594fSAndroid Build Coastguard Worker    /* goto/16 +AAAA */
56*795d594fSAndroid Build Coastguard Worker    movswl  2(rPC), rINST                   # rINST <- ssssAAAA
57*795d594fSAndroid Build Coastguard Worker    BRANCH
58*795d594fSAndroid Build Coastguard Worker
59*795d594fSAndroid Build Coastguard Worker%def op_goto_32():
60*795d594fSAndroid Build Coastguard Worker/*
61*795d594fSAndroid Build Coastguard Worker * Unconditional branch, 32-bit offset.
62*795d594fSAndroid Build Coastguard Worker *
63*795d594fSAndroid Build Coastguard Worker * The branch distance is a signed code-unit offset, which we need to
64*795d594fSAndroid Build Coastguard Worker * double to get a byte offset.
65*795d594fSAndroid Build Coastguard Worker */
66*795d594fSAndroid Build Coastguard Worker    /* goto/32 +AAAAAAAA */
67*795d594fSAndroid Build Coastguard Worker    movl  2(rPC), rINST                   # rINST <- AAAAAAAA
68*795d594fSAndroid Build Coastguard Worker    BRANCH
69*795d594fSAndroid Build Coastguard Worker
70*795d594fSAndroid Build Coastguard Worker%def op_if_eq():
71*795d594fSAndroid Build Coastguard Worker%  bincmp(revcmp="ne")
72*795d594fSAndroid Build Coastguard Worker
73*795d594fSAndroid Build Coastguard Worker%def op_if_eqz():
74*795d594fSAndroid Build Coastguard Worker%  zcmp(revcmp="ne")
75*795d594fSAndroid Build Coastguard Worker
76*795d594fSAndroid Build Coastguard Worker%def op_if_ge():
77*795d594fSAndroid Build Coastguard Worker%  bincmp(revcmp="l")
78*795d594fSAndroid Build Coastguard Worker
79*795d594fSAndroid Build Coastguard Worker%def op_if_gez():
80*795d594fSAndroid Build Coastguard Worker%  zcmp(revcmp="l")
81*795d594fSAndroid Build Coastguard Worker
82*795d594fSAndroid Build Coastguard Worker%def op_if_gt():
83*795d594fSAndroid Build Coastguard Worker%  bincmp(revcmp="le")
84*795d594fSAndroid Build Coastguard Worker
85*795d594fSAndroid Build Coastguard Worker%def op_if_gtz():
86*795d594fSAndroid Build Coastguard Worker%  zcmp(revcmp="le")
87*795d594fSAndroid Build Coastguard Worker
88*795d594fSAndroid Build Coastguard Worker%def op_if_le():
89*795d594fSAndroid Build Coastguard Worker%  bincmp(revcmp="g")
90*795d594fSAndroid Build Coastguard Worker
91*795d594fSAndroid Build Coastguard Worker%def op_if_lez():
92*795d594fSAndroid Build Coastguard Worker%  zcmp(revcmp="g")
93*795d594fSAndroid Build Coastguard Worker
94*795d594fSAndroid Build Coastguard Worker%def op_if_lt():
95*795d594fSAndroid Build Coastguard Worker%  bincmp(revcmp="ge")
96*795d594fSAndroid Build Coastguard Worker
97*795d594fSAndroid Build Coastguard Worker%def op_if_ltz():
98*795d594fSAndroid Build Coastguard Worker%  zcmp(revcmp="ge")
99*795d594fSAndroid Build Coastguard Worker
100*795d594fSAndroid Build Coastguard Worker%def op_if_ne():
101*795d594fSAndroid Build Coastguard Worker%  bincmp(revcmp="e")
102*795d594fSAndroid Build Coastguard Worker
103*795d594fSAndroid Build Coastguard Worker%def op_if_nez():
104*795d594fSAndroid Build Coastguard Worker%  zcmp(revcmp="e")
105*795d594fSAndroid Build Coastguard Worker
106*795d594fSAndroid Build Coastguard Worker%def op_packed_switch(func="NterpDoPackedSwitch"):
107*795d594fSAndroid Build Coastguard Worker/*
108*795d594fSAndroid Build Coastguard Worker * Handle a packed-switch or sparse-switch instruction.  In both cases
109*795d594fSAndroid Build Coastguard Worker * we decode it and hand it off to a helper function.
110*795d594fSAndroid Build Coastguard Worker *
111*795d594fSAndroid Build Coastguard Worker * We don't really expect backward branches in a switch statement, but
112*795d594fSAndroid Build Coastguard Worker * they're perfectly legal, so we check for them here.
113*795d594fSAndroid Build Coastguard Worker *
114*795d594fSAndroid Build Coastguard Worker * for: packed-switch, sparse-switch
115*795d594fSAndroid Build Coastguard Worker */
116*795d594fSAndroid Build Coastguard Worker    /* op vAA, +BBBB */
117*795d594fSAndroid Build Coastguard Worker    movl    2(rPC), ARG0                # eax <- BBBBbbbb
118*795d594fSAndroid Build Coastguard Worker    leal    (rPC,ARG0,2), ARG0          # eax <- PC + BBBBbbbb*2
119*795d594fSAndroid Build Coastguard Worker    GET_VREG ARG1, rINST                # ecx <- vAA
120*795d594fSAndroid Build Coastguard Worker    pushl   ARG1
121*795d594fSAndroid Build Coastguard Worker    pushl   ARG0
122*795d594fSAndroid Build Coastguard Worker    call    SYMBOL($func)
123*795d594fSAndroid Build Coastguard Worker    addl MACRO_LITERAL(8), %esp
124*795d594fSAndroid Build Coastguard Worker    RESTORE_IBASE
125*795d594fSAndroid Build Coastguard Worker    FETCH_INST_CLEAR_OPCODE
126*795d594fSAndroid Build Coastguard Worker    movl  %eax, rINST
127*795d594fSAndroid Build Coastguard Worker    BRANCH
128*795d594fSAndroid Build Coastguard Worker
129*795d594fSAndroid Build Coastguard Worker/*
130*795d594fSAndroid Build Coastguard Worker * Return a 32-bit value.
131*795d594fSAndroid Build Coastguard Worker */
132*795d594fSAndroid Build Coastguard Worker%def op_return(is_object="0"):
133*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, rINST                    # eax <- vAA
134*795d594fSAndroid Build Coastguard Worker    .if !$is_object
135*795d594fSAndroid Build Coastguard Worker    // In case we're going back to compiled code, put the
136*795d594fSAndroid Build Coastguard Worker    // result also in a xmm register.
137*795d594fSAndroid Build Coastguard Worker    movd %eax, %xmm0
138*795d594fSAndroid Build Coastguard Worker    .endif
139*795d594fSAndroid Build Coastguard Worker    CFI_REMEMBER_STATE
140*795d594fSAndroid Build Coastguard Worker    movl -4(rREFS), %esp
141*795d594fSAndroid Build Coastguard Worker    DROP_PARAMETERS_SAVES
142*795d594fSAndroid Build Coastguard Worker    CFI_DEF_CFA(esp, CALLEE_SAVES_SIZE)
143*795d594fSAndroid Build Coastguard Worker    RESTORE_ALL_CALLEE_SAVES
144*795d594fSAndroid Build Coastguard Worker    ret
145*795d594fSAndroid Build Coastguard Worker    CFI_RESTORE_STATE
146*795d594fSAndroid Build Coastguard Worker    NTERP_DEF_CFA CFI_REFS
147*795d594fSAndroid Build Coastguard Worker
148*795d594fSAndroid Build Coastguard Worker%def op_return_object():
149*795d594fSAndroid Build Coastguard Worker%  op_return(is_object="1")
150*795d594fSAndroid Build Coastguard Worker
151*795d594fSAndroid Build Coastguard Worker%def op_return_void():
152*795d594fSAndroid Build Coastguard Worker    // Thread fence for constructor is a no-op on x86_64.
153*795d594fSAndroid Build Coastguard Worker    CFI_REMEMBER_STATE
154*795d594fSAndroid Build Coastguard Worker    movl -4(rREFS), %esp
155*795d594fSAndroid Build Coastguard Worker    DROP_PARAMETERS_SAVES
156*795d594fSAndroid Build Coastguard Worker    CFI_DEF_CFA(esp, CALLEE_SAVES_SIZE)
157*795d594fSAndroid Build Coastguard Worker    RESTORE_ALL_CALLEE_SAVES
158*795d594fSAndroid Build Coastguard Worker    ret
159*795d594fSAndroid Build Coastguard Worker    CFI_RESTORE_STATE
160*795d594fSAndroid Build Coastguard Worker    NTERP_DEF_CFA CFI_REFS
161*795d594fSAndroid Build Coastguard Worker
162*795d594fSAndroid Build Coastguard Worker%def op_return_wide():
163*795d594fSAndroid Build Coastguard Worker    // In case we're going back to compiled code, put the
164*795d594fSAndroid Build Coastguard Worker    // result also in a xmm register.
165*795d594fSAndroid Build Coastguard Worker    GET_WIDE_FP_VREG %xmm0, rINST
166*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, rINST        # eax <- vAA
167*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH %edx, rINST   # edx <- vAA
168*795d594fSAndroid Build Coastguard Worker    CFI_REMEMBER_STATE
169*795d594fSAndroid Build Coastguard Worker    movl    -4(rREFS), %esp
170*795d594fSAndroid Build Coastguard Worker    DROP_PARAMETERS_SAVES
171*795d594fSAndroid Build Coastguard Worker    CFI_DEF_CFA(esp, CALLEE_SAVES_SIZE)
172*795d594fSAndroid Build Coastguard Worker    RESTORE_ALL_CALLEE_SAVES
173*795d594fSAndroid Build Coastguard Worker    ret
174*795d594fSAndroid Build Coastguard Worker    CFI_RESTORE_STATE
175*795d594fSAndroid Build Coastguard Worker    NTERP_DEF_CFA CFI_REFS
176*795d594fSAndroid Build Coastguard Worker
177*795d594fSAndroid Build Coastguard Worker%def op_sparse_switch():
178*795d594fSAndroid Build Coastguard Worker%  op_packed_switch(func="NterpDoSparseSwitch")
179*795d594fSAndroid Build Coastguard Worker
180*795d594fSAndroid Build Coastguard Worker%def op_throw():
181*795d594fSAndroid Build Coastguard Worker  EXPORT_PC
182*795d594fSAndroid Build Coastguard Worker  GET_VREG ARG0, rINST                   # eax <- vAA (exception object)
183*795d594fSAndroid Build Coastguard Worker  movl rSELF:THREAD_SELF_OFFSET, ARG1
184*795d594fSAndroid Build Coastguard Worker  call SYMBOL(art_quick_deliver_exception)
185*795d594fSAndroid Build Coastguard Worker  int3
186