xref: /aosp_15_r20/art/runtime/interpreter/mterp/x86ng/arithmetic.S (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker%def bindiv(result="", special="", rem=""):
2*795d594fSAndroid Build Coastguard Worker/*
3*795d594fSAndroid Build Coastguard Worker * 32-bit binary div/rem operation.  Handles special case of op0=minint and
4*795d594fSAndroid Build Coastguard Worker * op1=-1.
5*795d594fSAndroid Build Coastguard Worker */
6*795d594fSAndroid Build Coastguard Worker    /* div/rem vAA, vBB, vCC */
7*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- BB
8*795d594fSAndroid Build Coastguard Worker    movzbl  3(rPC), %ecx                    # ecx <- CC
9*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax                     # eax <- vBB
10*795d594fSAndroid Build Coastguard Worker    GET_VREG %ecx, %ecx                     # ecx <- vCC
11*795d594fSAndroid Build Coastguard Worker    mov     rIBASE, LOCAL0(%esp)
12*795d594fSAndroid Build Coastguard Worker    testl   %ecx, %ecx
13*795d594fSAndroid Build Coastguard Worker    je      common_errDivideByZero
14*795d594fSAndroid Build Coastguard Worker    movl    %eax, %edx
15*795d594fSAndroid Build Coastguard Worker    orl     %ecx, %edx
16*795d594fSAndroid Build Coastguard Worker    testl   $$0xFFFFFF00, %edx              # If both arguments are less
17*795d594fSAndroid Build Coastguard Worker                                            #   than 8-bit and +ve
18*795d594fSAndroid Build Coastguard Worker    jz      .L${opcode}_8                   # Do 8-bit divide
19*795d594fSAndroid Build Coastguard Worker    testl   $$0xFFFF0000, %edx              # If both arguments are less
20*795d594fSAndroid Build Coastguard Worker                                            #   than 16-bit and +ve
21*795d594fSAndroid Build Coastguard Worker    jz      .L${opcode}_16                  # Do 16-bit divide
22*795d594fSAndroid Build Coastguard Worker    cmpl    $$-1, %ecx
23*795d594fSAndroid Build Coastguard Worker    jne     .L${opcode}_32
24*795d594fSAndroid Build Coastguard Worker    cmpl    $$0x80000000, %eax
25*795d594fSAndroid Build Coastguard Worker    jne     .L${opcode}_32
26*795d594fSAndroid Build Coastguard Worker    movl    $special, $result
27*795d594fSAndroid Build Coastguard Worker    jmp     .L${opcode}_finish
28*795d594fSAndroid Build Coastguard Worker%  add_slow_path(bindiv_helper, result, rem)
29*795d594fSAndroid Build Coastguard Worker
30*795d594fSAndroid Build Coastguard Worker%def bindiv_helper(result, rem):
31*795d594fSAndroid Build Coastguard Worker.L${opcode}_32:
32*795d594fSAndroid Build Coastguard Worker    cltd
33*795d594fSAndroid Build Coastguard Worker    idivl   %ecx
34*795d594fSAndroid Build Coastguard Worker    jmp     .L${opcode}_finish
35*795d594fSAndroid Build Coastguard Worker.L${opcode}_8:
36*795d594fSAndroid Build Coastguard Worker    div     %cl                             # 8-bit divide otherwise.
37*795d594fSAndroid Build Coastguard Worker                                            # Remainder in %ah, quotient in %al
38*795d594fSAndroid Build Coastguard Worker    .if $rem
39*795d594fSAndroid Build Coastguard Worker    movl    %eax, %edx
40*795d594fSAndroid Build Coastguard Worker    shr     $$8, %edx
41*795d594fSAndroid Build Coastguard Worker    .else
42*795d594fSAndroid Build Coastguard Worker    andl    $$0x000000FF, %eax
43*795d594fSAndroid Build Coastguard Worker    .endif
44*795d594fSAndroid Build Coastguard Worker    jmp     .L${opcode}_finish
45*795d594fSAndroid Build Coastguard Worker.L${opcode}_16:
46*795d594fSAndroid Build Coastguard Worker    xorl    %edx, %edx                      # Clear %edx before divide
47*795d594fSAndroid Build Coastguard Worker    div     %cx
48*795d594fSAndroid Build Coastguard Worker.L${opcode}_finish:
49*795d594fSAndroid Build Coastguard Worker    SET_VREG $result, rINST
50*795d594fSAndroid Build Coastguard Worker    mov     LOCAL0(%esp), rIBASE
51*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
52*795d594fSAndroid Build Coastguard Worker
53*795d594fSAndroid Build Coastguard Worker%def bindiv2addr(result="", special=""):
54*795d594fSAndroid Build Coastguard Worker/*
55*795d594fSAndroid Build Coastguard Worker * 32-bit binary div/rem operation.  Handles special case of op0=minint and
56*795d594fSAndroid Build Coastguard Worker * op1=-1.
57*795d594fSAndroid Build Coastguard Worker */
58*795d594fSAndroid Build Coastguard Worker    /* div/rem/2addr vA, vB */
59*795d594fSAndroid Build Coastguard Worker    movzx   rINSTbl, %ecx                   # eax <- BA
60*795d594fSAndroid Build Coastguard Worker    mov     rIBASE, LOCAL0(%esp)
61*795d594fSAndroid Build Coastguard Worker    sarl    $$4, %ecx                       # ecx <- B
62*795d594fSAndroid Build Coastguard Worker    GET_VREG %ecx, %ecx                     # eax <- vBB
63*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, rINSTbl                  # rINST <- A
64*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, rINST                    # eax <- vBB
65*795d594fSAndroid Build Coastguard Worker    testl   %ecx, %ecx
66*795d594fSAndroid Build Coastguard Worker    je      common_errDivideByZero
67*795d594fSAndroid Build Coastguard Worker    cmpl    $$-1, %ecx
68*795d594fSAndroid Build Coastguard Worker    jne     .L${opcode}_continue_div2addr
69*795d594fSAndroid Build Coastguard Worker    cmpl    $$0x80000000, %eax
70*795d594fSAndroid Build Coastguard Worker    jne     .L${opcode}_continue_div2addr
71*795d594fSAndroid Build Coastguard Worker    movl    $special, $result
72*795d594fSAndroid Build Coastguard Worker    SET_VREG $result, rINST
73*795d594fSAndroid Build Coastguard Worker    mov     LOCAL0(%esp), rIBASE
74*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
75*795d594fSAndroid Build Coastguard Worker%  add_slow_path(bindiv2addr_helper, result)
76*795d594fSAndroid Build Coastguard Worker
77*795d594fSAndroid Build Coastguard Worker%def bindiv2addr_helper(result):
78*795d594fSAndroid Build Coastguard Worker.L${opcode}_continue_div2addr:
79*795d594fSAndroid Build Coastguard Worker    cltd
80*795d594fSAndroid Build Coastguard Worker    idivl   %ecx
81*795d594fSAndroid Build Coastguard Worker    SET_VREG $result, rINST
82*795d594fSAndroid Build Coastguard Worker    mov     LOCAL0(%esp), rIBASE
83*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
84*795d594fSAndroid Build Coastguard Worker
85*795d594fSAndroid Build Coastguard Worker%def bindivLit16(result="", special=""):
86*795d594fSAndroid Build Coastguard Worker/*
87*795d594fSAndroid Build Coastguard Worker * 32-bit binary div/rem operation.  Handles special case of op0=minint and
88*795d594fSAndroid Build Coastguard Worker * op1=-1.
89*795d594fSAndroid Build Coastguard Worker */
90*795d594fSAndroid Build Coastguard Worker    /* div/rem/lit16 vA, vB, #+CCCC */
91*795d594fSAndroid Build Coastguard Worker    /* Need A in rINST, ssssCCCC in ecx, vB in eax */
92*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl, %eax                   # eax <- 000000BA
93*795d594fSAndroid Build Coastguard Worker    sarl    $$4, %eax                       # eax <- B
94*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax                     # eax <- vB
95*795d594fSAndroid Build Coastguard Worker    movswl  2(rPC), %ecx                    # ecx <- ssssCCCC
96*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, rINSTbl                  # rINST <- A
97*795d594fSAndroid Build Coastguard Worker    testl   %ecx, %ecx
98*795d594fSAndroid Build Coastguard Worker    je      common_errDivideByZero
99*795d594fSAndroid Build Coastguard Worker    cmpl    $$-1, %ecx
100*795d594fSAndroid Build Coastguard Worker    jne     .L${opcode}_continue_div
101*795d594fSAndroid Build Coastguard Worker    cmpl    $$0x80000000, %eax
102*795d594fSAndroid Build Coastguard Worker    jne     .L${opcode}_continue_div
103*795d594fSAndroid Build Coastguard Worker    movl    $special, %eax
104*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST
105*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
106*795d594fSAndroid Build Coastguard Worker
107*795d594fSAndroid Build Coastguard Worker.L${opcode}_continue_div:
108*795d594fSAndroid Build Coastguard Worker    mov     rIBASE, LOCAL0(%esp)
109*795d594fSAndroid Build Coastguard Worker    cltd
110*795d594fSAndroid Build Coastguard Worker    idivl   %ecx
111*795d594fSAndroid Build Coastguard Worker    SET_VREG $result, rINST
112*795d594fSAndroid Build Coastguard Worker    mov     LOCAL0(%esp), rIBASE
113*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
114*795d594fSAndroid Build Coastguard Worker
115*795d594fSAndroid Build Coastguard Worker%def bindivLit8(result="", special=""):
116*795d594fSAndroid Build Coastguard Worker/*
117*795d594fSAndroid Build Coastguard Worker * 32-bit div/rem "lit8" binary operation.  Handles special case of
118*795d594fSAndroid Build Coastguard Worker * op0=minint & op1=-1
119*795d594fSAndroid Build Coastguard Worker */
120*795d594fSAndroid Build Coastguard Worker    /* div/rem/lit8 vAA, vBB, #+CC */
121*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- BB
122*795d594fSAndroid Build Coastguard Worker    movsbl  3(rPC), %ecx                    # ecx <- ssssssCC
123*795d594fSAndroid Build Coastguard Worker    GET_VREG  %eax, %eax                    # eax <- rBB
124*795d594fSAndroid Build Coastguard Worker    testl   %ecx, %ecx
125*795d594fSAndroid Build Coastguard Worker    je      common_errDivideByZero
126*795d594fSAndroid Build Coastguard Worker    cmpl    $$0x80000000, %eax
127*795d594fSAndroid Build Coastguard Worker    jne     .L${opcode}_continue_div
128*795d594fSAndroid Build Coastguard Worker    cmpl    $$-1, %ecx
129*795d594fSAndroid Build Coastguard Worker    jne     .L${opcode}_continue_div
130*795d594fSAndroid Build Coastguard Worker    movl    $special, %eax
131*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST
132*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
133*795d594fSAndroid Build Coastguard Worker
134*795d594fSAndroid Build Coastguard Worker.L${opcode}_continue_div:
135*795d594fSAndroid Build Coastguard Worker    mov     rIBASE, LOCAL0(%esp)
136*795d594fSAndroid Build Coastguard Worker    cltd
137*795d594fSAndroid Build Coastguard Worker    idivl   %ecx
138*795d594fSAndroid Build Coastguard Worker    SET_VREG $result, rINST
139*795d594fSAndroid Build Coastguard Worker    mov     LOCAL0(%esp), rIBASE
140*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
141*795d594fSAndroid Build Coastguard Worker
142*795d594fSAndroid Build Coastguard Worker%def binop(result="%eax", instr=""):
143*795d594fSAndroid Build Coastguard Worker/*
144*795d594fSAndroid Build Coastguard Worker * Generic 32-bit binary operation.  Provide an "instr" line that
145*795d594fSAndroid Build Coastguard Worker * specifies an instruction that performs "result = eax op VREG_ADDRESS(%ecx)".
146*795d594fSAndroid Build Coastguard Worker * This could be an x86 instruction or a function call.  (If the result
147*795d594fSAndroid Build Coastguard Worker * comes back in a register other than eax, you can override "result".)
148*795d594fSAndroid Build Coastguard Worker *
149*795d594fSAndroid Build Coastguard Worker * For: add-int, sub-int, and-int, or-int,
150*795d594fSAndroid Build Coastguard Worker *      xor-int, shl-int, shr-int, ushr-int
151*795d594fSAndroid Build Coastguard Worker */
152*795d594fSAndroid Build Coastguard Worker    /* binop vAA, vBB, vCC */
153*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- BB
154*795d594fSAndroid Build Coastguard Worker    movzbl  3(rPC), %ecx                    # ecx <- CC
155*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax                     # eax <- vBB
156*795d594fSAndroid Build Coastguard Worker    $instr VREG_ADDRESS(%ecx), %eax
157*795d594fSAndroid Build Coastguard Worker    SET_VREG $result, rINST
158*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
159*795d594fSAndroid Build Coastguard Worker
160*795d594fSAndroid Build Coastguard Worker%def binop1(result="%eax", tmp="%ecx", instr=""):
161*795d594fSAndroid Build Coastguard Worker/*
162*795d594fSAndroid Build Coastguard Worker * Generic 32-bit binary operation in which both operands loaded to
163*795d594fSAndroid Build Coastguard Worker * registers (op0 in eax, op1 in ecx).
164*795d594fSAndroid Build Coastguard Worker */
165*795d594fSAndroid Build Coastguard Worker    /* binop vAA, vBB, vCC */
166*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC),%eax                     # eax <- BB
167*795d594fSAndroid Build Coastguard Worker    movzbl  3(rPC),%ecx                     # ecx <- CC
168*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax                     # eax <- vBB
169*795d594fSAndroid Build Coastguard Worker    GET_VREG %ecx, %ecx                     # eax <- vBB
170*795d594fSAndroid Build Coastguard Worker    $instr                                  # ex: addl    %ecx,%eax
171*795d594fSAndroid Build Coastguard Worker    SET_VREG $result, rINST
172*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
173*795d594fSAndroid Build Coastguard Worker
174*795d594fSAndroid Build Coastguard Worker%def binop2addr(result="%eax", instr=""):
175*795d594fSAndroid Build Coastguard Worker/*
176*795d594fSAndroid Build Coastguard Worker * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
177*795d594fSAndroid Build Coastguard Worker * that specifies an instruction that performs "result = r0 op r1".
178*795d594fSAndroid Build Coastguard Worker * This could be an instruction or a function call.
179*795d594fSAndroid Build Coastguard Worker *
180*795d594fSAndroid Build Coastguard Worker * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
181*795d594fSAndroid Build Coastguard Worker *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
182*795d594fSAndroid Build Coastguard Worker *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
183*795d594fSAndroid Build Coastguard Worker *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
184*795d594fSAndroid Build Coastguard Worker */
185*795d594fSAndroid Build Coastguard Worker    /* binop/2addr vA, vB */
186*795d594fSAndroid Build Coastguard Worker    movzx   rINSTbl, %ecx                   # ecx <- A+
187*795d594fSAndroid Build Coastguard Worker    sarl    $$4, rINST                      # rINST <- B
188*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, rINST                    # eax <- vB
189*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, %cl                      # ecx <- A
190*795d594fSAndroid Build Coastguard Worker    $instr %eax, VREG_ADDRESS(%ecx)
191*795d594fSAndroid Build Coastguard Worker    CLEAR_REF %ecx
192*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
193*795d594fSAndroid Build Coastguard Worker
194*795d594fSAndroid Build Coastguard Worker%def binopLit16(result="%eax", instr=""):
195*795d594fSAndroid Build Coastguard Worker/*
196*795d594fSAndroid Build Coastguard Worker * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
197*795d594fSAndroid Build Coastguard Worker * that specifies an instruction that performs "result = eax op ecx".
198*795d594fSAndroid Build Coastguard Worker * This could be an x86 instruction or a function call.  (If the result
199*795d594fSAndroid Build Coastguard Worker * comes back in a register other than eax, you can override "result".)
200*795d594fSAndroid Build Coastguard Worker *
201*795d594fSAndroid Build Coastguard Worker * For: add-int/lit16, rsub-int,
202*795d594fSAndroid Build Coastguard Worker *      and-int/lit16, or-int/lit16, xor-int/lit16
203*795d594fSAndroid Build Coastguard Worker */
204*795d594fSAndroid Build Coastguard Worker    /* binop/lit16 vA, vB, #+CCCC */
205*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl, %eax                   # eax <- 000000BA
206*795d594fSAndroid Build Coastguard Worker    sarl    $$4, %eax                       # eax <- B
207*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax                     # eax <- vB
208*795d594fSAndroid Build Coastguard Worker    movswl  2(rPC), %ecx                    # ecx <- ssssCCCC
209*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, rINSTbl                  # rINST <- A
210*795d594fSAndroid Build Coastguard Worker    $instr                                  # for example: addl %ecx, %eax
211*795d594fSAndroid Build Coastguard Worker    SET_VREG $result, rINST
212*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
213*795d594fSAndroid Build Coastguard Worker
214*795d594fSAndroid Build Coastguard Worker%def binopLit8(result="%eax", instr=""):
215*795d594fSAndroid Build Coastguard Worker/*
216*795d594fSAndroid Build Coastguard Worker * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
217*795d594fSAndroid Build Coastguard Worker * that specifies an instruction that performs "result = eax op ecx".
218*795d594fSAndroid Build Coastguard Worker * This could be an x86 instruction or a function call.  (If the result
219*795d594fSAndroid Build Coastguard Worker * comes back in a register other than r0, you can override "result".)
220*795d594fSAndroid Build Coastguard Worker *
221*795d594fSAndroid Build Coastguard Worker * For: add-int/lit8, rsub-int/lit8
222*795d594fSAndroid Build Coastguard Worker *      and-int/lit8, or-int/lit8, xor-int/lit8,
223*795d594fSAndroid Build Coastguard Worker *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
224*795d594fSAndroid Build Coastguard Worker */
225*795d594fSAndroid Build Coastguard Worker    /* binop/lit8 vAA, vBB, #+CC */
226*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- BB
227*795d594fSAndroid Build Coastguard Worker    movsbl  3(rPC), %ecx                    # ecx <- ssssssCC
228*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax                     # eax <- rBB
229*795d594fSAndroid Build Coastguard Worker    $instr                                  # ex: addl %ecx,%eax
230*795d594fSAndroid Build Coastguard Worker    SET_VREG $result, rINST
231*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
232*795d594fSAndroid Build Coastguard Worker
233*795d594fSAndroid Build Coastguard Worker%def binopWide(instr1="", instr2=""):
234*795d594fSAndroid Build Coastguard Worker/*
235*795d594fSAndroid Build Coastguard Worker * Generic 64-bit binary operation.
236*795d594fSAndroid Build Coastguard Worker */
237*795d594fSAndroid Build Coastguard Worker    /* binop vAA, vBB, vCC */
238*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- BB
239*795d594fSAndroid Build Coastguard Worker    movzbl  3(rPC), %ecx                    # ecx <- CC
240*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, LOCAL0(%esp)            # save rIBASE
241*795d594fSAndroid Build Coastguard Worker    GET_VREG rIBASE, %eax                   # rIBASE <- v[BB+0]
242*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH %eax, %eax                # eax <- v[BB+1]
243*795d594fSAndroid Build Coastguard Worker    $instr1 VREG_ADDRESS(%ecx), rIBASE
244*795d594fSAndroid Build Coastguard Worker    $instr2 VREG_HIGH_ADDRESS(%ecx), %eax
245*795d594fSAndroid Build Coastguard Worker    SET_VREG rIBASE, rINST                  # v[AA+0] <- rIBASE
246*795d594fSAndroid Build Coastguard Worker    movl    LOCAL0(%esp), rIBASE            # restore rIBASE
247*795d594fSAndroid Build Coastguard Worker    SET_VREG_HIGH %eax, rINST               # v[AA+1] <- eax
248*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
249*795d594fSAndroid Build Coastguard Worker
250*795d594fSAndroid Build Coastguard Worker%def binopWide2addr(instr1="", instr2=""):
251*795d594fSAndroid Build Coastguard Worker/*
252*795d594fSAndroid Build Coastguard Worker * Generic 64-bit binary operation.
253*795d594fSAndroid Build Coastguard Worker */
254*795d594fSAndroid Build Coastguard Worker    /* binop/2addr vA, vB */
255*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl, %ecx                   # ecx<- BA
256*795d594fSAndroid Build Coastguard Worker    sarl    $$4, %ecx                       # ecx<- B
257*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %ecx                     # eax<- v[B+0]
258*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH %ecx, %ecx                # eax<- v[B+1]
259*795d594fSAndroid Build Coastguard Worker    andb    $$0xF, rINSTbl                  # rINST<- A
260*795d594fSAndroid Build Coastguard Worker    $instr1 %eax, VREG_ADDRESS(rINST)
261*795d594fSAndroid Build Coastguard Worker    $instr2 %ecx, VREG_HIGH_ADDRESS(rINST)
262*795d594fSAndroid Build Coastguard Worker    CLEAR_WIDE_REF rINST
263*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
264*795d594fSAndroid Build Coastguard Worker
265*795d594fSAndroid Build Coastguard Worker%def cvtfp_int(srcdouble="1", tgtlong="1"):
266*795d594fSAndroid Build Coastguard Worker/* On fp to int conversions, Java requires that
267*795d594fSAndroid Build Coastguard Worker * if the result > maxint, it should be clamped to maxint.  If it is less
268*795d594fSAndroid Build Coastguard Worker * than minint, it should be clamped to minint.  If it is a nan, the result
269*795d594fSAndroid Build Coastguard Worker * should be zero.  Further, the rounding mode is to truncate.  This model
270*795d594fSAndroid Build Coastguard Worker * differs from what is delivered normally via the x86 fpu, so we have
271*795d594fSAndroid Build Coastguard Worker * to play some games.
272*795d594fSAndroid Build Coastguard Worker */
273*795d594fSAndroid Build Coastguard Worker    /* float/double to int/long vA, vB */
274*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl, %ecx                   # ecx <- A+
275*795d594fSAndroid Build Coastguard Worker    sarl    $$4, rINST                      # rINST <- B
276*795d594fSAndroid Build Coastguard Worker    .if $srcdouble
277*795d594fSAndroid Build Coastguard Worker    fldl    VREG_ADDRESS(rINST)             # %st0 <- vB
278*795d594fSAndroid Build Coastguard Worker    .else
279*795d594fSAndroid Build Coastguard Worker    flds    VREG_ADDRESS(rINST)             # %st0 <- vB
280*795d594fSAndroid Build Coastguard Worker    .endif
281*795d594fSAndroid Build Coastguard Worker    ftst
282*795d594fSAndroid Build Coastguard Worker    fnstcw  LOCAL0(%esp)                    # remember original rounding mode
283*795d594fSAndroid Build Coastguard Worker    movzwl  LOCAL0(%esp), %eax
284*795d594fSAndroid Build Coastguard Worker    movb    $$0xc, %ah
285*795d594fSAndroid Build Coastguard Worker    movw    %ax, LOCAL0+2(%esp)
286*795d594fSAndroid Build Coastguard Worker    fldcw   LOCAL0+2(%esp)                  # set "to zero" rounding mode
287*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, %cl                      # ecx <- A
288*795d594fSAndroid Build Coastguard Worker    .if $tgtlong
289*795d594fSAndroid Build Coastguard Worker    fistpll VREG_ADDRESS(%ecx)              # convert and store
290*795d594fSAndroid Build Coastguard Worker    .else
291*795d594fSAndroid Build Coastguard Worker    fistpl  VREG_ADDRESS(%ecx)              # convert and store
292*795d594fSAndroid Build Coastguard Worker    .endif
293*795d594fSAndroid Build Coastguard Worker    fldcw   LOCAL0(%esp)                    # restore previous rounding mode
294*795d594fSAndroid Build Coastguard Worker    .if $tgtlong
295*795d594fSAndroid Build Coastguard Worker    movl    $$0x80000000, %eax
296*795d594fSAndroid Build Coastguard Worker    xorl    VREG_HIGH_ADDRESS(%ecx), %eax
297*795d594fSAndroid Build Coastguard Worker    orl     VREG_ADDRESS(%ecx), %eax
298*795d594fSAndroid Build Coastguard Worker    .else
299*795d594fSAndroid Build Coastguard Worker    cmpl    $$0x80000000, VREG_ADDRESS(%ecx)
300*795d594fSAndroid Build Coastguard Worker    .endif
301*795d594fSAndroid Build Coastguard Worker    je      .L${opcode}_special_case # fix up result
302*795d594fSAndroid Build Coastguard Worker
303*795d594fSAndroid Build Coastguard Worker.L${opcode}_finish:
304*795d594fSAndroid Build Coastguard Worker    xor     %eax, %eax
305*795d594fSAndroid Build Coastguard Worker    mov     %eax, VREG_REF_ADDRESS(%ecx)
306*795d594fSAndroid Build Coastguard Worker    .if $tgtlong
307*795d594fSAndroid Build Coastguard Worker    mov     %eax, VREG_REF_HIGH_ADDRESS(%ecx)
308*795d594fSAndroid Build Coastguard Worker    .endif
309*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
310*795d594fSAndroid Build Coastguard Worker%  add_slow_path(cvtfp_int_helper, tgtlong)
311*795d594fSAndroid Build Coastguard Worker
312*795d594fSAndroid Build Coastguard Worker%def cvtfp_int_helper(tgtlong):
313*795d594fSAndroid Build Coastguard Worker.L${opcode}_special_case:
314*795d594fSAndroid Build Coastguard Worker    fnstsw  %ax
315*795d594fSAndroid Build Coastguard Worker    sahf
316*795d594fSAndroid Build Coastguard Worker    jp      .L${opcode}_isNaN
317*795d594fSAndroid Build Coastguard Worker    adcl    $$-1, VREG_ADDRESS(%ecx)
318*795d594fSAndroid Build Coastguard Worker    .if $tgtlong
319*795d594fSAndroid Build Coastguard Worker    adcl    $$-1, VREG_HIGH_ADDRESS(%ecx)
320*795d594fSAndroid Build Coastguard Worker    .endif
321*795d594fSAndroid Build Coastguard Worker   jmp      .L${opcode}_finish
322*795d594fSAndroid Build Coastguard Worker.L${opcode}_isNaN:
323*795d594fSAndroid Build Coastguard Worker    movl    $$0, VREG_ADDRESS(%ecx)
324*795d594fSAndroid Build Coastguard Worker    .if $tgtlong
325*795d594fSAndroid Build Coastguard Worker    movl    $$0, VREG_HIGH_ADDRESS(%ecx)
326*795d594fSAndroid Build Coastguard Worker    .endif
327*795d594fSAndroid Build Coastguard Worker    jmp     .L${opcode}_finish
328*795d594fSAndroid Build Coastguard Worker
329*795d594fSAndroid Build Coastguard Worker%def shop2addr(result="%eax", instr=""):
330*795d594fSAndroid Build Coastguard Worker/*
331*795d594fSAndroid Build Coastguard Worker * Generic 32-bit "shift/2addr" operation.
332*795d594fSAndroid Build Coastguard Worker */
333*795d594fSAndroid Build Coastguard Worker    /* shift/2addr vA, vB */
334*795d594fSAndroid Build Coastguard Worker    movzx   rINSTbl, %ecx                   # eax <- BA
335*795d594fSAndroid Build Coastguard Worker    sarl    $$4, %ecx                       # ecx <- B
336*795d594fSAndroid Build Coastguard Worker    GET_VREG %ecx, %ecx                     # eax <- vBB
337*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, rINSTbl                  # rINST <- A
338*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, rINST                    # eax <- vAA
339*795d594fSAndroid Build Coastguard Worker    $instr                                  # ex: sarl %cl, %eax
340*795d594fSAndroid Build Coastguard Worker    SET_VREG $result, rINST
341*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
342*795d594fSAndroid Build Coastguard Worker
343*795d594fSAndroid Build Coastguard Worker%def unop(instr=""):
344*795d594fSAndroid Build Coastguard Worker/*
345*795d594fSAndroid Build Coastguard Worker * Generic 32-bit unary operation.  Provide an "instr" line that
346*795d594fSAndroid Build Coastguard Worker * specifies an instruction that performs "result = op eax".
347*795d594fSAndroid Build Coastguard Worker */
348*795d594fSAndroid Build Coastguard Worker    /* unop vA, vB */
349*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl,%ecx                    # ecx <- A+
350*795d594fSAndroid Build Coastguard Worker    sarl    $$4,rINST                       # rINST <- B
351*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, rINST                    # eax <- vB
352*795d594fSAndroid Build Coastguard Worker    andb    $$0xf,%cl                       # ecx <- A
353*795d594fSAndroid Build Coastguard Worker    $instr
354*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, %ecx
355*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
356*795d594fSAndroid Build Coastguard Worker
357*795d594fSAndroid Build Coastguard Worker%def op_add_int():
358*795d594fSAndroid Build Coastguard Worker%  binop(instr="addl")
359*795d594fSAndroid Build Coastguard Worker
360*795d594fSAndroid Build Coastguard Worker%def op_add_int_2addr():
361*795d594fSAndroid Build Coastguard Worker%  binop2addr(instr="addl")
362*795d594fSAndroid Build Coastguard Worker
363*795d594fSAndroid Build Coastguard Worker%def op_add_int_lit16():
364*795d594fSAndroid Build Coastguard Worker%  binopLit16(instr="addl    %ecx, %eax")
365*795d594fSAndroid Build Coastguard Worker
366*795d594fSAndroid Build Coastguard Worker%def op_add_int_lit8():
367*795d594fSAndroid Build Coastguard Worker%  binopLit8(instr="addl    %ecx, %eax")
368*795d594fSAndroid Build Coastguard Worker
369*795d594fSAndroid Build Coastguard Worker%def op_add_long():
370*795d594fSAndroid Build Coastguard Worker%  binopWide(instr1="addl", instr2="adcl")
371*795d594fSAndroid Build Coastguard Worker
372*795d594fSAndroid Build Coastguard Worker%def op_add_long_2addr():
373*795d594fSAndroid Build Coastguard Worker%  binopWide2addr(instr1="addl", instr2="adcl")
374*795d594fSAndroid Build Coastguard Worker
375*795d594fSAndroid Build Coastguard Worker%def op_and_int():
376*795d594fSAndroid Build Coastguard Worker%  binop(instr="andl")
377*795d594fSAndroid Build Coastguard Worker
378*795d594fSAndroid Build Coastguard Worker%def op_and_int_2addr():
379*795d594fSAndroid Build Coastguard Worker%  binop2addr(instr="andl")
380*795d594fSAndroid Build Coastguard Worker
381*795d594fSAndroid Build Coastguard Worker%def op_and_int_lit16():
382*795d594fSAndroid Build Coastguard Worker%  binopLit16(instr="andl    %ecx, %eax")
383*795d594fSAndroid Build Coastguard Worker
384*795d594fSAndroid Build Coastguard Worker%def op_and_int_lit8():
385*795d594fSAndroid Build Coastguard Worker%  binopLit8(instr="andl    %ecx, %eax")
386*795d594fSAndroid Build Coastguard Worker
387*795d594fSAndroid Build Coastguard Worker%def op_and_long():
388*795d594fSAndroid Build Coastguard Worker%  binopWide(instr1="andl", instr2="andl")
389*795d594fSAndroid Build Coastguard Worker
390*795d594fSAndroid Build Coastguard Worker%def op_and_long_2addr():
391*795d594fSAndroid Build Coastguard Worker%  binopWide2addr(instr1="andl", instr2="andl")
392*795d594fSAndroid Build Coastguard Worker
393*795d594fSAndroid Build Coastguard Worker%def op_cmp_long():
394*795d594fSAndroid Build Coastguard Worker/*
395*795d594fSAndroid Build Coastguard Worker * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
396*795d594fSAndroid Build Coastguard Worker * register based on the results of the comparison.
397*795d594fSAndroid Build Coastguard Worker */
398*795d594fSAndroid Build Coastguard Worker    /* cmp-long vAA, vBB, vCC */
399*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- BB
400*795d594fSAndroid Build Coastguard Worker    movzbl  3(rPC), %ecx                    # ecx <- CC
401*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH %eax, %eax                # eax <- v[BB+1], BB is clobbered
402*795d594fSAndroid Build Coastguard Worker    cmpl    VREG_HIGH_ADDRESS(%ecx), %eax
403*795d594fSAndroid Build Coastguard Worker    jl      .L${opcode}_smaller
404*795d594fSAndroid Build Coastguard Worker    jg      .L${opcode}_bigger
405*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- BB, restore BB
406*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax                     # eax <- v[BB]
407*795d594fSAndroid Build Coastguard Worker    sub     VREG_ADDRESS(%ecx), %eax
408*795d594fSAndroid Build Coastguard Worker    ja      .L${opcode}_bigger
409*795d594fSAndroid Build Coastguard Worker    jb      .L${opcode}_smaller
410*795d594fSAndroid Build Coastguard Worker.L${opcode}_finish:
411*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST
412*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
413*795d594fSAndroid Build Coastguard Worker
414*795d594fSAndroid Build Coastguard Worker.L${opcode}_bigger:
415*795d594fSAndroid Build Coastguard Worker    movl    $$1, %eax
416*795d594fSAndroid Build Coastguard Worker    jmp     .L${opcode}_finish
417*795d594fSAndroid Build Coastguard Worker
418*795d594fSAndroid Build Coastguard Worker.L${opcode}_smaller:
419*795d594fSAndroid Build Coastguard Worker    movl    $$-1, %eax
420*795d594fSAndroid Build Coastguard Worker    jmp     .L${opcode}_finish
421*795d594fSAndroid Build Coastguard Worker
422*795d594fSAndroid Build Coastguard Worker%def op_div_int():
423*795d594fSAndroid Build Coastguard Worker%  bindiv(result="%eax", special="$0x80000000", rem="0")
424*795d594fSAndroid Build Coastguard Worker
425*795d594fSAndroid Build Coastguard Worker%def op_div_int_2addr():
426*795d594fSAndroid Build Coastguard Worker%  bindiv2addr(result="%eax", special="$0x80000000")
427*795d594fSAndroid Build Coastguard Worker
428*795d594fSAndroid Build Coastguard Worker%def op_div_int_lit16():
429*795d594fSAndroid Build Coastguard Worker%  bindivLit16(result="%eax", special="$0x80000000")
430*795d594fSAndroid Build Coastguard Worker
431*795d594fSAndroid Build Coastguard Worker%def op_div_int_lit8():
432*795d594fSAndroid Build Coastguard Worker%  bindivLit8(result="%eax", special="$0x80000000")
433*795d594fSAndroid Build Coastguard Worker
434*795d594fSAndroid Build Coastguard Worker%def op_div_long(routine="art_quick_ldiv"):
435*795d594fSAndroid Build Coastguard Worker/* art_quick_* methods has quick abi,
436*795d594fSAndroid Build Coastguard Worker *   so use eax, ecx, edx, ebx for args
437*795d594fSAndroid Build Coastguard Worker */
438*795d594fSAndroid Build Coastguard Worker    /* div vAA, vBB, vCC */
439*795d594fSAndroid Build Coastguard Worker    .extern $routine
440*795d594fSAndroid Build Coastguard Worker    mov     rIBASE, LOCAL0(%esp)            # save rIBASE/%edx
441*795d594fSAndroid Build Coastguard Worker    mov     rINST, LOCAL1(%esp)             # save rINST/%ebx
442*795d594fSAndroid Build Coastguard Worker    movzbl  3(rPC), %eax                    # eax <- CC
443*795d594fSAndroid Build Coastguard Worker    GET_VREG %ecx, %eax
444*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH %ebx, %eax
445*795d594fSAndroid Build Coastguard Worker    movl    %ecx, %edx
446*795d594fSAndroid Build Coastguard Worker    orl     %ebx, %ecx
447*795d594fSAndroid Build Coastguard Worker    jz      common_errDivideByZero
448*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- BB
449*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH %ecx, %eax
450*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax
451*795d594fSAndroid Build Coastguard Worker    call    SYMBOL($routine)
452*795d594fSAndroid Build Coastguard Worker    mov     LOCAL1(%esp), rINST             # restore rINST/%ebx
453*795d594fSAndroid Build Coastguard Worker    SET_VREG_HIGH rIBASE, rINST
454*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST
455*795d594fSAndroid Build Coastguard Worker    mov     LOCAL0(%esp), rIBASE            # restore rIBASE/%edx
456*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
457*795d594fSAndroid Build Coastguard Worker
458*795d594fSAndroid Build Coastguard Worker%def op_div_long_2addr(routine="art_quick_ldiv"):
459*795d594fSAndroid Build Coastguard Worker/* art_quick_* methods has quick abi,
460*795d594fSAndroid Build Coastguard Worker *   so use eax, ecx, edx, ebx for args
461*795d594fSAndroid Build Coastguard Worker */
462*795d594fSAndroid Build Coastguard Worker    /* div/2addr vA, vB */
463*795d594fSAndroid Build Coastguard Worker    .extern   $routine
464*795d594fSAndroid Build Coastguard Worker    mov     rIBASE, LOCAL0(%esp)            # save rIBASE/%edx
465*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl, %eax
466*795d594fSAndroid Build Coastguard Worker    shrl    $$4, %eax                       # eax <- B
467*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, rINSTbl                  # rINST <- A
468*795d594fSAndroid Build Coastguard Worker    mov     rINST, LOCAL1(%esp)             # save rINST/%ebx
469*795d594fSAndroid Build Coastguard Worker    movl    %ebx, %ecx
470*795d594fSAndroid Build Coastguard Worker    GET_VREG %edx, %eax
471*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH %ebx, %eax
472*795d594fSAndroid Build Coastguard Worker    movl    %edx, %eax
473*795d594fSAndroid Build Coastguard Worker    orl     %ebx, %eax
474*795d594fSAndroid Build Coastguard Worker    jz      common_errDivideByZero
475*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %ecx
476*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH %ecx, %ecx
477*795d594fSAndroid Build Coastguard Worker    call    SYMBOL($routine)
478*795d594fSAndroid Build Coastguard Worker    mov     LOCAL1(%esp), rINST             # restore rINST/%ebx
479*795d594fSAndroid Build Coastguard Worker    SET_VREG_HIGH rIBASE, rINST
480*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST
481*795d594fSAndroid Build Coastguard Worker    mov     LOCAL0(%esp), rIBASE            # restore rIBASE/%edx
482*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
483*795d594fSAndroid Build Coastguard Worker
484*795d594fSAndroid Build Coastguard Worker%def op_int_to_byte():
485*795d594fSAndroid Build Coastguard Worker%  unop(instr="movsbl  %al, %eax")
486*795d594fSAndroid Build Coastguard Worker
487*795d594fSAndroid Build Coastguard Worker%def op_int_to_char():
488*795d594fSAndroid Build Coastguard Worker%  unop(instr="movzwl  %ax,%eax")
489*795d594fSAndroid Build Coastguard Worker
490*795d594fSAndroid Build Coastguard Worker%def op_int_to_long():
491*795d594fSAndroid Build Coastguard Worker    /* int to long vA, vB */
492*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl, %eax                   # eax <- +A
493*795d594fSAndroid Build Coastguard Worker    sarl    $$4, %eax                       # eax <- B
494*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax                     # eax <- vB
495*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, rINSTbl                  # rINST <- A
496*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, %ecx                    # cltd trashes rIBASE/edx
497*795d594fSAndroid Build Coastguard Worker    cltd                                    # rINST:eax<- sssssssBBBBBBBB
498*795d594fSAndroid Build Coastguard Worker    SET_VREG_HIGH rIBASE, rINST             # v[A+1] <- rIBASE
499*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST                    # v[A+0] <- %eax
500*795d594fSAndroid Build Coastguard Worker    movl    %ecx, rIBASE
501*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
502*795d594fSAndroid Build Coastguard Worker
503*795d594fSAndroid Build Coastguard Worker
504*795d594fSAndroid Build Coastguard Worker%def op_int_to_short():
505*795d594fSAndroid Build Coastguard Worker%  unop(instr="movswl %ax, %eax")
506*795d594fSAndroid Build Coastguard Worker
507*795d594fSAndroid Build Coastguard Worker%def op_long_to_int():
508*795d594fSAndroid Build Coastguard Worker/* we ignore the high word, making this equivalent to a 32-bit reg move */
509*795d594fSAndroid Build Coastguard Worker%  op_move()
510*795d594fSAndroid Build Coastguard Worker
511*795d594fSAndroid Build Coastguard Worker%def op_mul_int():
512*795d594fSAndroid Build Coastguard Worker    /*
513*795d594fSAndroid Build Coastguard Worker     * 32-bit binary multiplication.
514*795d594fSAndroid Build Coastguard Worker     */
515*795d594fSAndroid Build Coastguard Worker    /* mul vAA, vBB, vCC */
516*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- BB
517*795d594fSAndroid Build Coastguard Worker    movzbl  3(rPC), %ecx                    # ecx <- CC
518*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax                     # eax <- vBB
519*795d594fSAndroid Build Coastguard Worker    mov     rIBASE, LOCAL0(%esp)
520*795d594fSAndroid Build Coastguard Worker    imull   VREG_ADDRESS(%ecx), %eax        # trashes rIBASE/edx
521*795d594fSAndroid Build Coastguard Worker    mov     LOCAL0(%esp), rIBASE
522*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST
523*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
524*795d594fSAndroid Build Coastguard Worker
525*795d594fSAndroid Build Coastguard Worker%def op_mul_int_2addr():
526*795d594fSAndroid Build Coastguard Worker    /* mul vA, vB */
527*795d594fSAndroid Build Coastguard Worker    movzx   rINSTbl, %ecx                   # ecx <- A+
528*795d594fSAndroid Build Coastguard Worker    sarl    $$4, rINST                      # rINST <- B
529*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, rINST                    # eax <- vB
530*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, %cl                      # ecx <- A
531*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, rINST
532*795d594fSAndroid Build Coastguard Worker    imull   VREG_ADDRESS(%ecx), %eax        # trashes rIBASE/edx
533*795d594fSAndroid Build Coastguard Worker    movl    rINST, rIBASE
534*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, %ecx
535*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
536*795d594fSAndroid Build Coastguard Worker
537*795d594fSAndroid Build Coastguard Worker%def op_mul_int_lit16():
538*795d594fSAndroid Build Coastguard Worker    /* mul/lit16 vA, vB, #+CCCC */
539*795d594fSAndroid Build Coastguard Worker    /* Need A in rINST, ssssCCCC in ecx, vB in eax */
540*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl, %eax                   # eax <- 000000BA
541*795d594fSAndroid Build Coastguard Worker    sarl    $$4, %eax                       # eax <- B
542*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax                     # eax <- vB
543*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, %ecx
544*795d594fSAndroid Build Coastguard Worker    movswl  2(rPC), rIBASE                  # rIBASE <- ssssCCCC
545*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, rINSTbl                  # rINST <- A
546*795d594fSAndroid Build Coastguard Worker    imull   rIBASE, %eax                    # trashes rIBASE/edx
547*795d594fSAndroid Build Coastguard Worker    movl    %ecx, rIBASE
548*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST
549*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
550*795d594fSAndroid Build Coastguard Worker
551*795d594fSAndroid Build Coastguard Worker%def op_mul_int_lit8():
552*795d594fSAndroid Build Coastguard Worker    /* mul/lit8 vAA, vBB, #+CC */
553*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- BB
554*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, %ecx
555*795d594fSAndroid Build Coastguard Worker    GET_VREG  %eax, %eax                    # eax <- rBB
556*795d594fSAndroid Build Coastguard Worker    movsbl  3(rPC), rIBASE                  # rIBASE <- ssssssCC
557*795d594fSAndroid Build Coastguard Worker    imull   rIBASE, %eax                    # trashes rIBASE/edx
558*795d594fSAndroid Build Coastguard Worker    movl    %ecx, rIBASE
559*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST
560*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
561*795d594fSAndroid Build Coastguard Worker
562*795d594fSAndroid Build Coastguard Worker%def op_mul_long():
563*795d594fSAndroid Build Coastguard Worker/*
564*795d594fSAndroid Build Coastguard Worker * Signed 64-bit integer multiply.
565*795d594fSAndroid Build Coastguard Worker *
566*795d594fSAndroid Build Coastguard Worker * We could definately use more free registers for
567*795d594fSAndroid Build Coastguard Worker * this code.   We spill rINSTw (ebx),
568*795d594fSAndroid Build Coastguard Worker * giving us eax, ebc, ecx and edx as computational
569*795d594fSAndroid Build Coastguard Worker * temps.  On top of that, we'll spill edi (rFP)
570*795d594fSAndroid Build Coastguard Worker * for use as the vB pointer and esi (rPC) for use
571*795d594fSAndroid Build Coastguard Worker * as the vC pointer.  Yuck.
572*795d594fSAndroid Build Coastguard Worker *
573*795d594fSAndroid Build Coastguard Worker */
574*795d594fSAndroid Build Coastguard Worker    /* mul-long vAA, vBB, vCC */
575*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- B
576*795d594fSAndroid Build Coastguard Worker    movzbl  3(rPC), %ecx                    # ecx <- C
577*795d594fSAndroid Build Coastguard Worker    mov     rPC, LOCAL0(%esp)               # save Interpreter PC
578*795d594fSAndroid Build Coastguard Worker    mov     rFP, LOCAL1(%esp)               # save FP
579*795d594fSAndroid Build Coastguard Worker    mov     rIBASE, LOCAL2(%esp)            # save rIBASE
580*795d594fSAndroid Build Coastguard Worker    leal    (rFP,%eax,4), %esi              # esi <- &v[B]
581*795d594fSAndroid Build Coastguard Worker    leal    VREG_ADDRESS(%ecx), rFP         # rFP <- &v[C]
582*795d594fSAndroid Build Coastguard Worker    movl    4(%esi), %ecx                   # ecx <- Bmsw
583*795d594fSAndroid Build Coastguard Worker    imull   (rFP), %ecx                     # ecx <- (Bmsw*Clsw)
584*795d594fSAndroid Build Coastguard Worker    movl    4(rFP), %eax                    # eax <- Cmsw
585*795d594fSAndroid Build Coastguard Worker    imull   (%esi), %eax                    # eax <- (Cmsw*Blsw)
586*795d594fSAndroid Build Coastguard Worker    addl    %eax, %ecx                      # ecx <- (Bmsw*Clsw)+(Cmsw*Blsw)
587*795d594fSAndroid Build Coastguard Worker    movl    (rFP), %eax                     # eax <- Clsw
588*795d594fSAndroid Build Coastguard Worker    mull    (%esi)                          # eax <- (Clsw*Alsw)
589*795d594fSAndroid Build Coastguard Worker    mov     LOCAL0(%esp), rPC               # restore Interpreter PC
590*795d594fSAndroid Build Coastguard Worker    mov     LOCAL1(%esp), rFP               # restore FP
591*795d594fSAndroid Build Coastguard Worker    leal    (%ecx,rIBASE), rIBASE           # full result now in rIBASE:%eax
592*795d594fSAndroid Build Coastguard Worker    SET_VREG_HIGH rIBASE, rINST             # v[B+1] <- rIBASE
593*795d594fSAndroid Build Coastguard Worker    mov     LOCAL2(%esp), rIBASE            # restore IBASE
594*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST                    # v[B] <- eax
595*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
596*795d594fSAndroid Build Coastguard Worker
597*795d594fSAndroid Build Coastguard Worker%def op_mul_long_2addr():
598*795d594fSAndroid Build Coastguard Worker/*
599*795d594fSAndroid Build Coastguard Worker * Signed 64-bit integer multiply, 2-addr version
600*795d594fSAndroid Build Coastguard Worker *
601*795d594fSAndroid Build Coastguard Worker * We could definately use more free registers for
602*795d594fSAndroid Build Coastguard Worker * this code.  We must spill %edx (rIBASE) because it
603*795d594fSAndroid Build Coastguard Worker * is used by imul.  We'll also spill rINST (ebx),
604*795d594fSAndroid Build Coastguard Worker * giving us eax, ebc, ecx and rIBASE as computational
605*795d594fSAndroid Build Coastguard Worker * temps.  On top of that, we'll spill %esi (edi)
606*795d594fSAndroid Build Coastguard Worker * for use as the vA pointer and rFP (esi) for use
607*795d594fSAndroid Build Coastguard Worker * as the vB pointer.  Yuck.
608*795d594fSAndroid Build Coastguard Worker */
609*795d594fSAndroid Build Coastguard Worker    /* mul-long/2addr vA, vB */
610*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl, %eax                   # eax <- BA
611*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, %al                      # eax <- A
612*795d594fSAndroid Build Coastguard Worker    CLEAR_WIDE_REF %eax                     # clear refs in advance
613*795d594fSAndroid Build Coastguard Worker    sarl    $$4, rINST                      # rINST <- B
614*795d594fSAndroid Build Coastguard Worker    mov     rPC, LOCAL0(%esp)               # save Interpreter PC
615*795d594fSAndroid Build Coastguard Worker    mov     rFP, LOCAL1(%esp)               # save FP
616*795d594fSAndroid Build Coastguard Worker    mov     rIBASE, LOCAL2(%esp)            # save rIBASE
617*795d594fSAndroid Build Coastguard Worker    leal    (rFP,%eax,4), %esi              # esi <- &v[A]
618*795d594fSAndroid Build Coastguard Worker    leal    (rFP,rINST,4), rFP              # rFP <- &v[B]
619*795d594fSAndroid Build Coastguard Worker    movl    4(%esi), %ecx                   # ecx <- Amsw
620*795d594fSAndroid Build Coastguard Worker    imull   (rFP), %ecx                     # ecx <- (Amsw*Blsw)
621*795d594fSAndroid Build Coastguard Worker    movl    4(rFP), %eax                    # eax <- Bmsw
622*795d594fSAndroid Build Coastguard Worker    imull   (%esi), %eax                    # eax <- (Bmsw*Alsw)
623*795d594fSAndroid Build Coastguard Worker    addl    %eax, %ecx                      # ecx <- (Amsw*Blsw)+(Bmsw*Alsw)
624*795d594fSAndroid Build Coastguard Worker    movl    (rFP), %eax                     # eax <- Blsw
625*795d594fSAndroid Build Coastguard Worker    mull    (%esi)                          # eax <- (Blsw*Alsw)
626*795d594fSAndroid Build Coastguard Worker    leal    (%ecx,rIBASE), rIBASE           # full result now in %edx:%eax
627*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, 4(%esi)                 # v[A+1] <- rIBASE
628*795d594fSAndroid Build Coastguard Worker    movl    %eax, (%esi)                    # v[A] <- %eax
629*795d594fSAndroid Build Coastguard Worker    mov     LOCAL0(%esp), rPC               # restore Interpreter PC
630*795d594fSAndroid Build Coastguard Worker    mov     LOCAL2(%esp), rIBASE            # restore IBASE
631*795d594fSAndroid Build Coastguard Worker    mov     LOCAL1(%esp), rFP               # restore FP
632*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
633*795d594fSAndroid Build Coastguard Worker
634*795d594fSAndroid Build Coastguard Worker%def op_neg_int():
635*795d594fSAndroid Build Coastguard Worker%  unop(instr="negl    %eax")
636*795d594fSAndroid Build Coastguard Worker
637*795d594fSAndroid Build Coastguard Worker%def op_neg_long():
638*795d594fSAndroid Build Coastguard Worker    /* unop vA, vB */
639*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl, %ecx                   # ecx <- BA
640*795d594fSAndroid Build Coastguard Worker    sarl    $$4, %ecx                       # ecx <- B
641*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, rINSTbl                  # rINST <- A
642*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %ecx                     # eax <- v[B+0]
643*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH %ecx, %ecx                # ecx <- v[B+1]
644*795d594fSAndroid Build Coastguard Worker    negl    %eax
645*795d594fSAndroid Build Coastguard Worker    adcl    $$0, %ecx
646*795d594fSAndroid Build Coastguard Worker    negl    %ecx
647*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST                    # v[A+0] <- eax
648*795d594fSAndroid Build Coastguard Worker    SET_VREG_HIGH %ecx, rINST               # v[A+1] <- ecx
649*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
650*795d594fSAndroid Build Coastguard Worker
651*795d594fSAndroid Build Coastguard Worker
652*795d594fSAndroid Build Coastguard Worker%def op_not_int():
653*795d594fSAndroid Build Coastguard Worker%  unop(instr="notl %eax")
654*795d594fSAndroid Build Coastguard Worker
655*795d594fSAndroid Build Coastguard Worker%def op_not_long():
656*795d594fSAndroid Build Coastguard Worker    /* unop vA, vB */
657*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl, %ecx                   # ecx <- BA
658*795d594fSAndroid Build Coastguard Worker    sarl    $$4, %ecx                       # ecx <- B
659*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, rINSTbl                  # rINST <- A
660*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %ecx                     # eax <- v[B+0]
661*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH %ecx, %ecx                # ecx <- v[B+1]
662*795d594fSAndroid Build Coastguard Worker    notl    %eax
663*795d594fSAndroid Build Coastguard Worker    notl    %ecx
664*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST                    # v[A+0] <- eax
665*795d594fSAndroid Build Coastguard Worker    SET_VREG_HIGH %ecx, rINST               # v[A+1] <- ecx
666*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
667*795d594fSAndroid Build Coastguard Worker
668*795d594fSAndroid Build Coastguard Worker%def op_or_int():
669*795d594fSAndroid Build Coastguard Worker%  binop(instr="orl")
670*795d594fSAndroid Build Coastguard Worker
671*795d594fSAndroid Build Coastguard Worker%def op_or_int_2addr():
672*795d594fSAndroid Build Coastguard Worker%  binop2addr(instr="orl")
673*795d594fSAndroid Build Coastguard Worker
674*795d594fSAndroid Build Coastguard Worker%def op_or_int_lit16():
675*795d594fSAndroid Build Coastguard Worker%  binopLit16(instr="orl     %ecx, %eax")
676*795d594fSAndroid Build Coastguard Worker
677*795d594fSAndroid Build Coastguard Worker%def op_or_int_lit8():
678*795d594fSAndroid Build Coastguard Worker%  binopLit8(instr="orl     %ecx, %eax")
679*795d594fSAndroid Build Coastguard Worker
680*795d594fSAndroid Build Coastguard Worker%def op_or_long():
681*795d594fSAndroid Build Coastguard Worker%  binopWide(instr1="orl", instr2="orl")
682*795d594fSAndroid Build Coastguard Worker
683*795d594fSAndroid Build Coastguard Worker%def op_or_long_2addr():
684*795d594fSAndroid Build Coastguard Worker%  binopWide2addr(instr1="orl", instr2="orl")
685*795d594fSAndroid Build Coastguard Worker
686*795d594fSAndroid Build Coastguard Worker%def op_rem_int():
687*795d594fSAndroid Build Coastguard Worker%  bindiv(result="rIBASE", special="$0", rem="1")
688*795d594fSAndroid Build Coastguard Worker
689*795d594fSAndroid Build Coastguard Worker%def op_rem_int_2addr():
690*795d594fSAndroid Build Coastguard Worker%  bindiv2addr(result="rIBASE", special="$0")
691*795d594fSAndroid Build Coastguard Worker
692*795d594fSAndroid Build Coastguard Worker%def op_rem_int_lit16():
693*795d594fSAndroid Build Coastguard Worker%  bindivLit16(result="rIBASE", special="$0")
694*795d594fSAndroid Build Coastguard Worker
695*795d594fSAndroid Build Coastguard Worker%def op_rem_int_lit8():
696*795d594fSAndroid Build Coastguard Worker%  bindivLit8(result="rIBASE", special="$0")
697*795d594fSAndroid Build Coastguard Worker
698*795d594fSAndroid Build Coastguard Worker%def op_rem_long():
699*795d594fSAndroid Build Coastguard Worker%  op_div_long(routine="art_quick_lmod")
700*795d594fSAndroid Build Coastguard Worker
701*795d594fSAndroid Build Coastguard Worker%def op_rem_long_2addr():
702*795d594fSAndroid Build Coastguard Worker%  op_div_long_2addr(routine="art_quick_lmod")
703*795d594fSAndroid Build Coastguard Worker
704*795d594fSAndroid Build Coastguard Worker%def op_rsub_int():
705*795d594fSAndroid Build Coastguard Worker/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
706*795d594fSAndroid Build Coastguard Worker%  binopLit16(instr="subl    %eax, %ecx", result="%ecx")
707*795d594fSAndroid Build Coastguard Worker
708*795d594fSAndroid Build Coastguard Worker%def op_rsub_int_lit8():
709*795d594fSAndroid Build Coastguard Worker%  binopLit8(instr="subl    %eax, %ecx", result="%ecx")
710*795d594fSAndroid Build Coastguard Worker
711*795d594fSAndroid Build Coastguard Worker%def op_shl_int():
712*795d594fSAndroid Build Coastguard Worker%  binop1(instr="sall    %cl, %eax")
713*795d594fSAndroid Build Coastguard Worker
714*795d594fSAndroid Build Coastguard Worker%def op_shl_int_2addr():
715*795d594fSAndroid Build Coastguard Worker%  shop2addr(instr="sall    %cl, %eax")
716*795d594fSAndroid Build Coastguard Worker
717*795d594fSAndroid Build Coastguard Worker%def op_shl_int_lit8():
718*795d594fSAndroid Build Coastguard Worker%  binopLit8(instr="sall    %cl, %eax")
719*795d594fSAndroid Build Coastguard Worker
720*795d594fSAndroid Build Coastguard Worker%def op_shl_long():
721*795d594fSAndroid Build Coastguard Worker/*
722*795d594fSAndroid Build Coastguard Worker * Long integer shift.  This is different from the generic 32/64-bit
723*795d594fSAndroid Build Coastguard Worker * binary operations because vAA/vBB are 64-bit but vCC (the shift
724*795d594fSAndroid Build Coastguard Worker * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
725*795d594fSAndroid Build Coastguard Worker * 6 bits of the shift distance.  x86 shifts automatically mask off
726*795d594fSAndroid Build Coastguard Worker * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
727*795d594fSAndroid Build Coastguard Worker * case specially.
728*795d594fSAndroid Build Coastguard Worker */
729*795d594fSAndroid Build Coastguard Worker    /* shl-long vAA, vBB, vCC */
730*795d594fSAndroid Build Coastguard Worker    /* ecx gets shift count */
731*795d594fSAndroid Build Coastguard Worker    /* Need to spill rINST */
732*795d594fSAndroid Build Coastguard Worker    /* rINSTw gets AA */
733*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- BB
734*795d594fSAndroid Build Coastguard Worker    movzbl  3(rPC), %ecx                    # ecx <- CC
735*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, LOCAL0(%esp)
736*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH rIBASE, %eax              # ecx <- v[BB+1]
737*795d594fSAndroid Build Coastguard Worker    GET_VREG %ecx, %ecx                     # ecx <- vCC
738*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax                     # eax <- v[BB+0]
739*795d594fSAndroid Build Coastguard Worker    shldl   %eax,rIBASE
740*795d594fSAndroid Build Coastguard Worker    sall    %cl, %eax
741*795d594fSAndroid Build Coastguard Worker    testb   $$32, %cl
742*795d594fSAndroid Build Coastguard Worker    je      2f
743*795d594fSAndroid Build Coastguard Worker    movl    %eax, rIBASE
744*795d594fSAndroid Build Coastguard Worker    xorl    %eax, %eax
745*795d594fSAndroid Build Coastguard Worker2:
746*795d594fSAndroid Build Coastguard Worker    SET_VREG_HIGH rIBASE, rINST             # v[AA+1] <- rIBASE
747*795d594fSAndroid Build Coastguard Worker    movl    LOCAL0(%esp), rIBASE
748*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST                    # v[AA+0] <- %eax
749*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
750*795d594fSAndroid Build Coastguard Worker
751*795d594fSAndroid Build Coastguard Worker%def op_shl_long_2addr():
752*795d594fSAndroid Build Coastguard Worker/*
753*795d594fSAndroid Build Coastguard Worker * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
754*795d594fSAndroid Build Coastguard Worker * 32-bit shift distance.
755*795d594fSAndroid Build Coastguard Worker */
756*795d594fSAndroid Build Coastguard Worker    /* shl-long/2addr vA, vB */
757*795d594fSAndroid Build Coastguard Worker    /* ecx gets shift count */
758*795d594fSAndroid Build Coastguard Worker    /* Need to spill rIBASE */
759*795d594fSAndroid Build Coastguard Worker    /* rINSTw gets AA */
760*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl, %ecx                   # ecx <- BA
761*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, rINSTbl                  # rINST <- A
762*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, rINST                    # eax <- v[AA+0]
763*795d594fSAndroid Build Coastguard Worker    sarl    $$4, %ecx                       # ecx <- B
764*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, LOCAL0(%esp)
765*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH rIBASE, rINST             # rIBASE <- v[AA+1]
766*795d594fSAndroid Build Coastguard Worker    GET_VREG %ecx, %ecx                     # ecx <- vBB
767*795d594fSAndroid Build Coastguard Worker    shldl   %eax, rIBASE
768*795d594fSAndroid Build Coastguard Worker    sall    %cl, %eax
769*795d594fSAndroid Build Coastguard Worker    testb   $$32, %cl
770*795d594fSAndroid Build Coastguard Worker    je      2f
771*795d594fSAndroid Build Coastguard Worker    movl    %eax, rIBASE
772*795d594fSAndroid Build Coastguard Worker    xorl    %eax, %eax
773*795d594fSAndroid Build Coastguard Worker2:
774*795d594fSAndroid Build Coastguard Worker    SET_VREG_HIGH rIBASE, rINST             # v[AA+1] <- rIBASE
775*795d594fSAndroid Build Coastguard Worker    movl    LOCAL0(%esp), rIBASE
776*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST                    # v[AA+0] <- eax
777*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
778*795d594fSAndroid Build Coastguard Worker
779*795d594fSAndroid Build Coastguard Worker%def op_shr_int():
780*795d594fSAndroid Build Coastguard Worker%  binop1(instr="sarl    %cl, %eax")
781*795d594fSAndroid Build Coastguard Worker
782*795d594fSAndroid Build Coastguard Worker%def op_shr_int_2addr():
783*795d594fSAndroid Build Coastguard Worker%  shop2addr(instr="sarl    %cl, %eax")
784*795d594fSAndroid Build Coastguard Worker
785*795d594fSAndroid Build Coastguard Worker%def op_shr_int_lit8():
786*795d594fSAndroid Build Coastguard Worker%  binopLit8(instr="sarl    %cl, %eax")
787*795d594fSAndroid Build Coastguard Worker
788*795d594fSAndroid Build Coastguard Worker%def op_shr_long():
789*795d594fSAndroid Build Coastguard Worker/*
790*795d594fSAndroid Build Coastguard Worker * Long integer shift.  This is different from the generic 32/64-bit
791*795d594fSAndroid Build Coastguard Worker * binary operations because vAA/vBB are 64-bit but vCC (the shift
792*795d594fSAndroid Build Coastguard Worker * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
793*795d594fSAndroid Build Coastguard Worker * 6 bits of the shift distance.  x86 shifts automatically mask off
794*795d594fSAndroid Build Coastguard Worker * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
795*795d594fSAndroid Build Coastguard Worker * case specially.
796*795d594fSAndroid Build Coastguard Worker */
797*795d594fSAndroid Build Coastguard Worker    /* shr-long vAA, vBB, vCC */
798*795d594fSAndroid Build Coastguard Worker    /* ecx gets shift count */
799*795d594fSAndroid Build Coastguard Worker    /* Need to spill rIBASE */
800*795d594fSAndroid Build Coastguard Worker    /* rINSTw gets AA */
801*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- BB
802*795d594fSAndroid Build Coastguard Worker    movzbl  3(rPC), %ecx                    # ecx <- CC
803*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, LOCAL0(%esp)
804*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH rIBASE, %eax              # rIBASE<- v[BB+1]
805*795d594fSAndroid Build Coastguard Worker    GET_VREG %ecx, %ecx                     # ecx <- vCC
806*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax                     # eax <- v[BB+0]
807*795d594fSAndroid Build Coastguard Worker    shrdl   rIBASE, %eax
808*795d594fSAndroid Build Coastguard Worker    sarl    %cl, rIBASE
809*795d594fSAndroid Build Coastguard Worker    testb   $$32, %cl
810*795d594fSAndroid Build Coastguard Worker    je      2f
811*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, %eax
812*795d594fSAndroid Build Coastguard Worker    sarl    $$31, rIBASE
813*795d594fSAndroid Build Coastguard Worker2:
814*795d594fSAndroid Build Coastguard Worker    SET_VREG_HIGH rIBASE, rINST             # v[AA+1] <- rIBASE
815*795d594fSAndroid Build Coastguard Worker    movl    LOCAL0(%esp), rIBASE
816*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST                    # v[AA+0] <- eax
817*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
818*795d594fSAndroid Build Coastguard Worker
819*795d594fSAndroid Build Coastguard Worker%def op_shr_long_2addr():
820*795d594fSAndroid Build Coastguard Worker/*
821*795d594fSAndroid Build Coastguard Worker * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
822*795d594fSAndroid Build Coastguard Worker * 32-bit shift distance.
823*795d594fSAndroid Build Coastguard Worker */
824*795d594fSAndroid Build Coastguard Worker    /* shl-long/2addr vA, vB */
825*795d594fSAndroid Build Coastguard Worker    /* ecx gets shift count */
826*795d594fSAndroid Build Coastguard Worker    /* Need to spill rIBASE */
827*795d594fSAndroid Build Coastguard Worker    /* rINSTw gets AA */
828*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl, %ecx                   # ecx <- BA
829*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, rINSTbl                  # rINST <- A
830*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, rINST                    # eax <- v[AA+0]
831*795d594fSAndroid Build Coastguard Worker    sarl    $$4, %ecx                       # ecx <- B
832*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, LOCAL0(%esp)
833*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH rIBASE, rINST             # rIBASE <- v[AA+1]
834*795d594fSAndroid Build Coastguard Worker    GET_VREG %ecx, %ecx                     # ecx <- vBB
835*795d594fSAndroid Build Coastguard Worker    shrdl   rIBASE, %eax
836*795d594fSAndroid Build Coastguard Worker    sarl    %cl, rIBASE
837*795d594fSAndroid Build Coastguard Worker    testb   $$32, %cl
838*795d594fSAndroid Build Coastguard Worker    je      2f
839*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, %eax
840*795d594fSAndroid Build Coastguard Worker    sarl    $$31, rIBASE
841*795d594fSAndroid Build Coastguard Worker2:
842*795d594fSAndroid Build Coastguard Worker    SET_VREG_HIGH rIBASE, rINST             # v[AA+1] <- rIBASE
843*795d594fSAndroid Build Coastguard Worker    movl    LOCAL0(%esp), rIBASE
844*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST                    # v[AA+0] <- eax
845*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
846*795d594fSAndroid Build Coastguard Worker
847*795d594fSAndroid Build Coastguard Worker%def op_sub_int():
848*795d594fSAndroid Build Coastguard Worker%  binop(instr="subl")
849*795d594fSAndroid Build Coastguard Worker
850*795d594fSAndroid Build Coastguard Worker%def op_sub_int_2addr():
851*795d594fSAndroid Build Coastguard Worker%  binop2addr(instr="subl")
852*795d594fSAndroid Build Coastguard Worker
853*795d594fSAndroid Build Coastguard Worker%def op_sub_long():
854*795d594fSAndroid Build Coastguard Worker%  binopWide(instr1="subl", instr2="sbbl")
855*795d594fSAndroid Build Coastguard Worker
856*795d594fSAndroid Build Coastguard Worker%def op_sub_long_2addr():
857*795d594fSAndroid Build Coastguard Worker%  binopWide2addr(instr1="subl", instr2="sbbl")
858*795d594fSAndroid Build Coastguard Worker
859*795d594fSAndroid Build Coastguard Worker%def op_ushr_int():
860*795d594fSAndroid Build Coastguard Worker%  binop1(instr="shrl    %cl, %eax")
861*795d594fSAndroid Build Coastguard Worker
862*795d594fSAndroid Build Coastguard Worker%def op_ushr_int_2addr():
863*795d594fSAndroid Build Coastguard Worker%  shop2addr(instr="shrl    %cl, %eax")
864*795d594fSAndroid Build Coastguard Worker
865*795d594fSAndroid Build Coastguard Worker%def op_ushr_int_lit8():
866*795d594fSAndroid Build Coastguard Worker%  binopLit8(instr="shrl    %cl, %eax")
867*795d594fSAndroid Build Coastguard Worker
868*795d594fSAndroid Build Coastguard Worker%def op_ushr_long():
869*795d594fSAndroid Build Coastguard Worker/*
870*795d594fSAndroid Build Coastguard Worker * Long integer shift.  This is different from the generic 32/64-bit
871*795d594fSAndroid Build Coastguard Worker * binary operations because vAA/vBB are 64-bit but vCC (the shift
872*795d594fSAndroid Build Coastguard Worker * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
873*795d594fSAndroid Build Coastguard Worker * 6 bits of the shift distance.  x86 shifts automatically mask off
874*795d594fSAndroid Build Coastguard Worker * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
875*795d594fSAndroid Build Coastguard Worker * case specially.
876*795d594fSAndroid Build Coastguard Worker */
877*795d594fSAndroid Build Coastguard Worker    /* shr-long vAA, vBB, vCC */
878*795d594fSAndroid Build Coastguard Worker    /* ecx gets shift count */
879*795d594fSAndroid Build Coastguard Worker    /* Need to spill rIBASE */
880*795d594fSAndroid Build Coastguard Worker    /* rINSTw gets AA */
881*795d594fSAndroid Build Coastguard Worker    movzbl  2(rPC), %eax                    # eax <- BB
882*795d594fSAndroid Build Coastguard Worker    movzbl  3(rPC), %ecx                    # ecx <- CC
883*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, LOCAL0(%esp)
884*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH rIBASE, %eax              # rIBASE <- v[BB+1]
885*795d594fSAndroid Build Coastguard Worker    GET_VREG %ecx, %ecx                     # ecx <- vCC
886*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, %eax                     # eax <- v[BB+0]
887*795d594fSAndroid Build Coastguard Worker    shrdl   rIBASE, %eax
888*795d594fSAndroid Build Coastguard Worker    shrl    %cl, rIBASE
889*795d594fSAndroid Build Coastguard Worker    testb   $$32, %cl
890*795d594fSAndroid Build Coastguard Worker    je      2f
891*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, %eax
892*795d594fSAndroid Build Coastguard Worker    xorl    rIBASE, rIBASE
893*795d594fSAndroid Build Coastguard Worker2:
894*795d594fSAndroid Build Coastguard Worker    SET_VREG_HIGH rIBASE, rINST             # v[AA+1] <- rIBASE
895*795d594fSAndroid Build Coastguard Worker    movl    LOCAL0(%esp), rIBASE
896*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST                    # v[BB+0] <- eax
897*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
898*795d594fSAndroid Build Coastguard Worker
899*795d594fSAndroid Build Coastguard Worker%def op_ushr_long_2addr():
900*795d594fSAndroid Build Coastguard Worker/*
901*795d594fSAndroid Build Coastguard Worker * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
902*795d594fSAndroid Build Coastguard Worker * 32-bit shift distance.
903*795d594fSAndroid Build Coastguard Worker */
904*795d594fSAndroid Build Coastguard Worker    /* shl-long/2addr vA, vB */
905*795d594fSAndroid Build Coastguard Worker    /* ecx gets shift count */
906*795d594fSAndroid Build Coastguard Worker    /* Need to spill rIBASE */
907*795d594fSAndroid Build Coastguard Worker    /* rINSTw gets AA */
908*795d594fSAndroid Build Coastguard Worker    movzbl  rINSTbl, %ecx                   # ecx <- BA
909*795d594fSAndroid Build Coastguard Worker    andb    $$0xf, rINSTbl                  # rINST <- A
910*795d594fSAndroid Build Coastguard Worker    GET_VREG %eax, rINST                    # eax <- v[AA+0]
911*795d594fSAndroid Build Coastguard Worker    sarl    $$4, %ecx                       # ecx <- B
912*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, LOCAL0(%esp)
913*795d594fSAndroid Build Coastguard Worker    GET_VREG_HIGH rIBASE, rINST             # rIBASE <- v[AA+1]
914*795d594fSAndroid Build Coastguard Worker    GET_VREG %ecx, %ecx                     # ecx <- vBB
915*795d594fSAndroid Build Coastguard Worker    shrdl   rIBASE, %eax
916*795d594fSAndroid Build Coastguard Worker    shrl    %cl, rIBASE
917*795d594fSAndroid Build Coastguard Worker    testb   $$32, %cl
918*795d594fSAndroid Build Coastguard Worker    je      2f
919*795d594fSAndroid Build Coastguard Worker    movl    rIBASE, %eax
920*795d594fSAndroid Build Coastguard Worker    xorl    rIBASE, rIBASE
921*795d594fSAndroid Build Coastguard Worker2:
922*795d594fSAndroid Build Coastguard Worker    SET_VREG_HIGH rIBASE, rINST             # v[AA+1] <- rIBASE
923*795d594fSAndroid Build Coastguard Worker    movl    LOCAL0(%esp), rIBASE
924*795d594fSAndroid Build Coastguard Worker    SET_VREG %eax, rINST                    # v[AA+0] <- eax
925*795d594fSAndroid Build Coastguard Worker    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
926*795d594fSAndroid Build Coastguard Worker
927*795d594fSAndroid Build Coastguard Worker%def op_xor_int():
928*795d594fSAndroid Build Coastguard Worker%  binop(instr="xorl")
929*795d594fSAndroid Build Coastguard Worker
930*795d594fSAndroid Build Coastguard Worker%def op_xor_int_2addr():
931*795d594fSAndroid Build Coastguard Worker%  binop2addr(instr="xorl")
932*795d594fSAndroid Build Coastguard Worker
933*795d594fSAndroid Build Coastguard Worker%def op_xor_int_lit16():
934*795d594fSAndroid Build Coastguard Worker%  binopLit16(instr="xorl    %ecx, %eax")
935*795d594fSAndroid Build Coastguard Worker
936*795d594fSAndroid Build Coastguard Worker%def op_xor_int_lit8():
937*795d594fSAndroid Build Coastguard Worker%  binopLit8(instr="xorl    %ecx, %eax")
938*795d594fSAndroid Build Coastguard Worker
939*795d594fSAndroid Build Coastguard Worker%def op_xor_long():
940*795d594fSAndroid Build Coastguard Worker%  binopWide(instr1="xorl", instr2="xorl")
941*795d594fSAndroid Build Coastguard Worker
942*795d594fSAndroid Build Coastguard Worker%def op_xor_long_2addr():
943*795d594fSAndroid Build Coastguard Worker%  binopWide2addr(instr1="xorl", instr2="xorl")
944