1%def bindiv(result="", second="", tmp="", wide="", suffix="", rem="0", ext="cdq"):
2/*
3 * 32-bit binary div/rem operation.  Handles special case of op1=-1.
4 */
5    /* div/rem vAA, vBB, vCC */
6    movzbq  2(rPC), %rax                    # rax <- BB
7    movzbq  3(rPC), %rcx                    # rcx <- CC
8    .if $wide
9    GET_WIDE_VREG %rax, %rax                # eax <- vBB
10    GET_WIDE_VREG $second, %rcx             # ecx <- vCC
11    .else
12    GET_VREG %eax, %rax                     # eax <- vBB
13    GET_VREG $second, %rcx                  # ecx <- vCC
14    .endif
15    test${suffix}   $second, $second
16    jz      common_errDivideByZero
17    cmp${suffix}  $$-1, $second
18    je      2f
19    cmp${suffix}  $$2, $second
20    je 3f
21    $ext                                    # rdx:rax <- sign-extended of rax
22    idiv${suffix}   $second
231:
24    .if $wide
25    SET_WIDE_VREG $result, rINSTq           # eax <- vBB
26    .else
27    SET_VREG $result, rINSTq                # eax <- vBB
28    .endif
29    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
302:
31    .if $rem
32    xor${suffix} $result, $result
33    .else
34    neg${suffix} $result
35    .endif
36    jmp     1b
373:
38    .if $rem
39    mov${suffix} $tmp, $result
40    .if $wide
41    shr${suffix} $$63, $result
42    .else
43    shr${suffix} $$31, $result
44    .endif
45    add${suffix} $tmp, $result
46    and${suffix} $$-2, $result
47    sub${suffix} $result, $tmp
48    mov${suffix} $tmp, $result
49    .else
50    mov${suffix} $result, $tmp
51    .if $wide
52    shr${suffix} $$63, $tmp
53    .else
54    shr${suffix} $$31, $tmp
55    .endif
56    add${suffix} $tmp, $result
57    sar${suffix} $result
58    .endif
59    jmp     1b
60
61%def bindiv2addr(result="", second="", tmp="", wide="", suffix="", rem="0", ext="cdq"):
62/*
63 * 32-bit binary div/rem operation.  Handles special case of op1=-1.
64 */
65    /* div/rem/2addr vA, vB */
66    movl    rINST, %ecx                     # rcx <- BA
67    sarl    $$4, %ecx                       # rcx <- B
68    andb    $$0xf, rINSTbl                  # rINST <- A
69    .if $wide
70    GET_WIDE_VREG %rax, rINSTq              # eax <- vA
71    GET_WIDE_VREG $second, %rcx             # ecx <- vB
72    .else
73    GET_VREG %eax, rINSTq                   # eax <- vA
74    GET_VREG $second, %rcx                  # ecx <- vB
75    .endif
76    test${suffix}   $second, $second
77    jz      common_errDivideByZero
78    cmp${suffix}  $$-1, $second
79    je      2f
80    cmp${suffix}  $$2, $second
81    je      3f
82    $ext                                    # rdx:rax <- sign-extended of rax
83    idiv${suffix}   $second
841:
85    .if $wide
86    SET_WIDE_VREG $result, rINSTq           # vA <- result
87    .else
88    SET_VREG $result, rINSTq                # vA <- result
89    .endif
90    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
912:
92    .if $rem
93    xor${suffix} $result, $result
94    .else
95    neg${suffix} $result
96    .endif
97    jmp     1b
983:
99    .if $rem
100    mov${suffix} $tmp, $result
101    .if $wide
102    shr${suffix} $$63, $result
103    .else
104    shr${suffix} $$31, $result
105    .endif
106    add${suffix} $tmp, $result
107    and${suffix} $$-2, $result
108    sub${suffix} $result, $tmp
109    mov${suffix} $tmp, $result
110    .else
111    mov${suffix} $result, $tmp
112    .if $wide
113    shr${suffix} $$63, $tmp
114    .else
115    shr${suffix} $$31, $tmp
116    .endif
117    add${suffix} $tmp, $result
118    sar${suffix} $result
119    .endif
120    jmp     1b
121
122%def bindivLit16(result="", rem="0"):
123/*
124 * 32-bit binary div/rem operation.  Handles special case of op1=-1.
125 */
126    /* div/rem/lit16 vA, vB, #+CCCC */
127    /* Need A in rINST, ssssCCCC in ecx, vB in eax */
128    movl    rINST, %eax                     # rax <- 000000BA
129    sarl    $$4, %eax                       # eax <- B
130    GET_VREG %eax, %rax                     # eax <- vB
131    movswl  2(rPC), %ecx                    # ecx <- ssssCCCC
132    andb    $$0xf, rINSTbl                  # rINST <- A
133    testl   %ecx, %ecx
134    jz      common_errDivideByZero
135    cmpl    $$-1, %ecx
136    je      2f
137    cdq                                     # rax <- sign-extended of eax
138    idivl   %ecx
1391:
140    SET_VREG $result, rINSTq                # vA <- result
141    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
1422:
143    .if $rem
144    xorl    $result, $result
145    .else
146    negl    $result
147    .endif
148    jmp     1b
149
150%def bindivLit8(result="", rem="0"):
151/*
152 * 32-bit div/rem "lit8" binary operation.  Handles special case of
153 * op0=minint & op1=-1
154 */
155    /* div/rem/lit8 vAA, vBB, #+CC */
156    movzbq  2(rPC), %rax                    # eax <- BB
157    movsbl  3(rPC), %ecx                    # ecx <- ssssssCC
158    GET_VREG  %eax, %rax                    # eax <- rBB
159    testl   %ecx, %ecx
160    je      common_errDivideByZero
161    cmpl    $$-1, %ecx
162    je      2f
163    cdq                                     # rax <- sign-extended of eax
164    idivl   %ecx
1651:
166    SET_VREG $result, rINSTq                # vA <- result
167    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
1682:
169    .if $rem
170    xorl    $result, $result
171    .else
172    negl    $result
173    .endif
174    jmp     1b
175
176%def binop(result="%eax", instr=""):
177/*
178 * Generic 32-bit binary operation.  Provide an "instr" line that
179 * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
180 * This could be an x86 instruction or a function call.  (If the result
181 * comes back in a register other than eax, you can override "result".)
182 *
183 * For: add-int, sub-int, and-int, or-int,
184 *      xor-int, shl-int, shr-int, ushr-int
185 */
186    /* binop vAA, vBB, vCC */
187    movzbq  2(rPC), %rax                    # rax <- BB
188    movzbq  3(rPC), %rcx                    # rcx <- CC
189    GET_VREG %eax, %rax                     # eax <- vBB
190    $instr VREG_ADDRESS(%rcx),%eax
191    SET_VREG $result, rINSTq
192    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
193
194%def binop1(wide="0", instr=""):
195/*
196 * Generic 32-bit binary operation in which both operands loaded to
197 * registers (op0 in eax, op1 in ecx).
198 */
199    /* binop vAA, vBB, vCC */
200    movzbq  2(rPC), %rax                    # eax <- BB
201    movzbq  3(rPC), %rcx                    # ecx <- CC
202    GET_VREG %ecx, %rcx                     # eax <- vCC
203    .if $wide
204    GET_WIDE_VREG %rax, %rax                # rax <- vBB
205    $instr                                  # ex: addl    %ecx,%eax
206    SET_WIDE_VREG %rax, rINSTq
207    .else
208    GET_VREG %eax, %rax                     # eax <- vBB
209    $instr                                  # ex: addl    %ecx,%eax
210    SET_VREG %eax, rINSTq
211    .endif
212    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
213
214%def binop2addr(result="%eax", instr=""):
215/*
216 * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
217 * that specifies an instruction that performs "result = r0 op r1".
218 * This could be an instruction or a function call.
219 *
220 * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
221 *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
222 *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
223 *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
224 */
225    /* binop/2addr vA, vB */
226    movl    rINST, %ecx                     # rcx <- A+
227    sarl    $$4, rINST                      # rINST <- B
228    andb    $$0xf, %cl                      # ecx <- A
229    GET_VREG %eax, rINSTq                   # eax <- vB
230    $instr %eax, VREG_ADDRESS(%rcx)
231    CLEAR_REF %rcx
232    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
233
234%def binopLit16(result="%eax", instr=""):
235/*
236 * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
237 * that specifies an instruction that performs "result = eax op ecx".
238 * This could be an x86 instruction or a function call.  (If the result
239 * comes back in a register other than eax, you can override "result".)
240 *
241 * For: add-int/lit16, rsub-int,
242 *      and-int/lit16, or-int/lit16, xor-int/lit16
243 */
244    /* binop/lit16 vA, vB, #+CCCC */
245    movl    rINST, %eax                     # rax <- 000000BA
246    sarl    $$4, %eax                       # eax <- B
247    GET_VREG %eax, %rax                     # eax <- vB
248    andb    $$0xf, rINSTbl                  # rINST <- A
249    movswl  2(rPC), %ecx                    # ecx <- ssssCCCC
250    $instr                                  # for example: addl %ecx, %eax
251    SET_VREG $result, rINSTq
252    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
253
254%def binopLit8(result="%eax", instr=""):
255/*
256 * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
257 * that specifies an instruction that performs "result = eax op ecx".
258 * This could be an x86 instruction or a function call.  (If the result
259 * comes back in a register other than r0, you can override "result".)
260 *
261 * For: add-int/lit8, rsub-int/lit8
262 *      and-int/lit8, or-int/lit8, xor-int/lit8,
263 *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
264 */
265    /* binop/lit8 vAA, vBB, #+CC */
266    movzbq  2(rPC), %rax                    # rax <- BB
267    movsbl  3(rPC), %ecx                    # rcx <- ssssssCC
268    GET_VREG %eax, %rax                     # eax <- rBB
269    $instr                                  # ex: addl %ecx,%eax
270    SET_VREG $result, rINSTq
271    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
272
273%def binopWide(instr=""):
274/*
275 * Generic 64-bit binary operation.
276 */
277    /* binop vAA, vBB, vCC */
278    movzbq  2(rPC), %rax                    # eax <- BB
279    movzbq  3(rPC), %rcx                    # ecx <- CC
280    GET_WIDE_VREG %rax, %rax                # rax <- v[BB]
281    $instr VREG_ADDRESS(%rcx),%rax
282    SET_WIDE_VREG %rax, rINSTq              # v[AA] <- rax
283    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
284
285%def binopWide2addr(instr=""):
286/*
287 * Generic 64-bit binary operation.
288 */
289    /* binop/2addr vA, vB */
290    movl    rINST, %ecx                     # rcx <- A+
291    sarl    $$4, rINST                      # rINST <- B
292    andb    $$0xf, %cl                      # ecx <- A
293    GET_WIDE_VREG %rax, rINSTq              # rax <- vB
294    $instr %rax,VREG_ADDRESS(%rcx)
295    CLEAR_WIDE_REF %rcx
296    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
297
298%def cvtfp_int(fp_suffix="", i_suffix="", max_const="", result_reg="", wide=""):
299/* On fp to int conversions, Java requires that
300 * if the result > maxint, it should be clamped to maxint.  If it is less
301 * than minint, it should be clamped to minint.  If it is a nan, the result
302 * should be zero.  Further, the rounding mode is to truncate.
303 */
304    /* float/double to int/long vA, vB */
305    movl    rINST, %ecx                     # rcx <- A+
306    sarl    $$4, rINST                      # rINST <- B
307    andb    $$0xf, %cl                      # ecx <- A
308    GET_VREG_XMM${fp_suffix} %xmm0, rINSTq
309    mov${i_suffix}  ${max_const}, ${result_reg}
310    cvtsi2s${fp_suffix}${i_suffix} ${result_reg}, %xmm1
311    comis${fp_suffix}    %xmm1, %xmm0
312    jae     1f
313    jp      2f
314    cvtts${fp_suffix}2si${i_suffix}  %xmm0, ${result_reg}
315    jmp     1f
3162:
317    xor${i_suffix}    ${result_reg}, ${result_reg}
3181:
319    .if $wide
320    SET_WIDE_VREG ${result_reg}, %rcx
321    .else
322    SET_VREG ${result_reg}, %rcx
323    .endif
324    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
325
326%def shop2addr(wide="0", instr=""):
327/*
328 * Generic 32-bit "shift/2addr" operation.
329 */
330    /* shift/2addr vA, vB */
331    movl    rINST, %ecx                     # ecx <- BA
332    sarl    $$4, %ecx                       # ecx <- B
333    GET_VREG %ecx, %rcx                     # ecx <- vBB
334    andb    $$0xf, rINSTbl                  # rINST <- A
335    .if $wide
336    GET_WIDE_VREG %rax, rINSTq              # rax <- vAA
337    $instr                                  # ex: sarl %cl, %eax
338    SET_WIDE_VREG %rax, rINSTq
339    .else
340    GET_VREG %eax, rINSTq                   # eax <- vAA
341    $instr                                  # ex: sarl %cl, %eax
342    SET_VREG %eax, rINSTq
343    .endif
344    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
345
346%def unop(preinstr="", instr="", wide="0"):
347/*
348 * Generic 32/64-bit unary operation.  Provide an "instr" line that
349 * specifies an instruction that performs "result = op eax".
350 */
351    /* unop vA, vB */
352    movl    rINST, %ecx                     # rcx <- A+
353    sarl    $$4,rINST                       # rINST <- B
354    .if ${wide}
355    GET_WIDE_VREG %rax, rINSTq              # rax <- vB
356    .else
357    GET_VREG %eax, rINSTq                   # eax <- vB
358    .endif
359    andb    $$0xf,%cl                       # ecx <- A
360$preinstr
361$instr
362    .if ${wide}
363    SET_WIDE_VREG %rax, %rcx
364    .else
365    SET_VREG %eax, %rcx
366    .endif
367    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
368
369%def op_add_int():
370%  binop(instr="addl")
371
372%def op_add_int_2addr():
373%  binop2addr(instr="addl")
374
375%def op_add_int_lit16():
376%  binopLit16(instr="addl    %ecx, %eax")
377
378%def op_add_int_lit8():
379%  binopLit8(instr="addl    %ecx, %eax")
380
381%def op_add_long():
382%  binopWide(instr="addq")
383
384%def op_add_long_2addr():
385%  binopWide2addr(instr="addq")
386
387%def op_and_int():
388%  binop(instr="andl")
389
390%def op_and_int_2addr():
391%  binop2addr(instr="andl")
392
393%def op_and_int_lit16():
394%  binopLit16(instr="andl    %ecx, %eax")
395
396%def op_and_int_lit8():
397%  binopLit8(instr="andl    %ecx, %eax")
398
399%def op_and_long():
400%  binopWide(instr="andq")
401
402%def op_and_long_2addr():
403%  binopWide2addr(instr="andq")
404
405%def op_cmp_long():
406/*
407 * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
408 * register based on the results of the comparison.
409 */
410    /* cmp-long vAA, vBB, vCC */
411    movzbq  2(rPC), %rdx                    # edx <- BB
412    movzbq  3(rPC), %rcx                    # ecx <- CC
413    GET_WIDE_VREG %rdx, %rdx                # rdx <- v[BB]
414    xorl    %eax, %eax
415    xorl    %edi, %edi
416    addb    $$1, %al
417    movl    $$-1, %esi
418    cmpq    VREG_ADDRESS(%rcx), %rdx
419    cmovl   %esi, %edi
420    cmovg   %eax, %edi
421    SET_VREG %edi, rINSTq
422    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
423
424%def op_div_int():
425%  bindiv(result="%eax", second="%ecx", tmp="%edx", wide="0", suffix="l")
426
427%def op_div_int_2addr():
428%  bindiv2addr(result="%eax", second="%ecx", tmp="%edx", wide="0", suffix="l")
429
430%def op_div_int_lit16():
431%  bindivLit16(result="%eax")
432
433%def op_div_int_lit8():
434%  bindivLit8(result="%eax")
435
436%def op_div_long():
437%  bindiv(result="%rax", second="%rcx", tmp="%rdx", wide="1", suffix="q", ext="cqo")
438
439%def op_div_long_2addr():
440%  bindiv2addr(result="%rax", second="%rcx", tmp="%rdx", wide="1", suffix="q", ext="cqo")
441
442%def op_int_to_byte():
443%  unop(instr="movsbl  %al, %eax")
444
445%def op_int_to_char():
446%  unop(instr="movzwl  %ax,%eax")
447
448%def op_int_to_long():
449    /* int to long vA, vB */
450    movzbq  rINSTbl, %rax                   # rax <- +A
451    sarl    $$4, %eax                       # eax <- B
452    andb    $$0xf, rINSTbl                  # rINST <- A
453    movslq  VREG_ADDRESS(%rax), %rax
454    SET_WIDE_VREG %rax, rINSTq              # v[A] <- %rax
455    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
456
457
458%def op_int_to_short():
459%  unop(instr="movswl %ax, %eax")
460
461%def op_long_to_int():
462/* we ignore the high word, making this equivalent to a 32-bit reg move */
463%  op_move()
464
465%def op_mul_int():
466%  binop(instr="imull")
467
468%def op_mul_int_2addr():
469    /* mul vA, vB */
470    movl    rINST, %ecx                     # rcx <- A+
471    sarl    $$4, rINST                      # rINST <- B
472    andb    $$0xf, %cl                      # ecx <- A
473    GET_VREG %eax, %rcx                     # eax <- vA
474    imull   (rFP,rINSTq,4), %eax
475    SET_VREG %eax, %rcx
476    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
477
478%def op_mul_int_lit16():
479%  binopLit16(instr="imull   %ecx, %eax")
480
481%def op_mul_int_lit8():
482%  binopLit8(instr="imull   %ecx, %eax")
483
484%def op_mul_long():
485%  binopWide(instr="imulq")
486
487%def op_mul_long_2addr():
488    /* mul vA, vB */
489    movl    rINST, %ecx                     # rcx <- A+
490    sarl    $$4, rINST                      # rINST <- B
491    andb    $$0xf, %cl                      # ecx <- A
492    GET_WIDE_VREG %rax, %rcx                # rax <- vA
493    imulq   (rFP,rINSTq,4), %rax
494    SET_WIDE_VREG %rax, %rcx
495    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
496
497%def op_neg_int():
498%  unop(instr="    negl    %eax")
499
500%def op_neg_long():
501%  unop(instr="    negq    %rax", wide="1")
502
503%def op_not_int():
504%  unop(instr="    notl    %eax")
505
506%def op_not_long():
507%  unop(instr="    notq    %rax", wide="1")
508
509%def op_or_int():
510%  binop(instr="orl")
511
512%def op_or_int_2addr():
513%  binop2addr(instr="orl")
514
515%def op_or_int_lit16():
516%  binopLit16(instr="orl     %ecx, %eax")
517
518%def op_or_int_lit8():
519%  binopLit8(instr="orl     %ecx, %eax")
520
521%def op_or_long():
522%  binopWide(instr="orq")
523
524%def op_or_long_2addr():
525%  binopWide2addr(instr="orq")
526
527%def op_rem_int():
528%  bindiv(result="%edx", second="%ecx", tmp="%eax", wide="0", suffix="l", rem="1")
529
530%def op_rem_int_2addr():
531%  bindiv2addr(result="%edx", second="%ecx", tmp="%eax", wide="0", suffix="l", rem="1")
532
533%def op_rem_int_lit16():
534%  bindivLit16(result="%edx", rem="1")
535
536%def op_rem_int_lit8():
537%  bindivLit8(result="%edx", rem="1")
538
539%def op_rem_long():
540%  bindiv(result="%rdx", second="%rcx", tmp="%rax", wide="1", suffix="q", ext="cqo", rem="1")
541
542%def op_rem_long_2addr():
543%  bindiv2addr(result="%rdx", second="%rcx", tmp="%rax", wide="1", suffix="q", rem="1", ext="cqo")
544
545%def op_rsub_int():
546/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
547%  binopLit16(instr="subl    %eax, %ecx", result="%ecx")
548
549%def op_rsub_int_lit8():
550%  binopLit8(instr="subl    %eax, %ecx", result="%ecx")
551
552%def op_shl_int():
553%  binop1(instr="sall    %cl, %eax")
554
555%def op_shl_int_2addr():
556%  shop2addr(instr="sall    %cl, %eax")
557
558%def op_shl_int_lit8():
559%  binopLit8(instr="sall    %cl, %eax")
560
561%def op_shl_long():
562%  binop1(instr="salq    %cl, %rax", wide="1")
563
564%def op_shl_long_2addr():
565%  shop2addr(instr="salq    %cl, %rax", wide="1")
566
567%def op_shr_int():
568%  binop1(instr="sarl    %cl, %eax")
569
570%def op_shr_int_2addr():
571%  shop2addr(instr="sarl    %cl, %eax")
572
573%def op_shr_int_lit8():
574%  binopLit8(instr="sarl    %cl, %eax")
575
576%def op_shr_long():
577%  binop1(instr="sarq    %cl, %rax", wide="1")
578
579%def op_shr_long_2addr():
580%  shop2addr(instr="sarq    %cl, %rax", wide="1")
581
582%def op_sub_int():
583%  binop(instr="subl")
584
585%def op_sub_int_2addr():
586%  binop2addr(instr="subl")
587
588%def op_sub_long():
589%  binopWide(instr="subq")
590
591%def op_sub_long_2addr():
592%  binopWide2addr(instr="subq")
593
594%def op_ushr_int():
595%  binop1(instr="shrl    %cl, %eax")
596
597%def op_ushr_int_2addr():
598%  shop2addr(instr="shrl    %cl, %eax")
599
600%def op_ushr_int_lit8():
601%  binopLit8(instr="shrl    %cl, %eax")
602
603%def op_ushr_long():
604%  binop1(instr="shrq    %cl, %rax", wide="1")
605
606%def op_ushr_long_2addr():
607%  shop2addr(instr="shrq    %cl, %rax", wide="1")
608
609%def op_xor_int():
610%  binop(instr="xorl")
611
612%def op_xor_int_2addr():
613%  binop2addr(instr="xorl")
614
615%def op_xor_int_lit16():
616%  binopLit16(instr="xorl    %ecx, %eax")
617
618%def op_xor_int_lit8():
619%  binopLit8(instr="xorl    %ecx, %eax")
620
621%def op_xor_long():
622%  binopWide(instr="xorq")
623
624%def op_xor_long_2addr():
625%  binopWide2addr(instr="xorq")
626