1%def fpcmp(suff="d", nanval="pos"):
2/*
3 * Compare two floating-point values.  Puts 0, 1, or -1 into the
4 * destination register based on the results of the comparison.
5 *
6 * int compare(x, y) {
7 *     if (x == y) {
8 *         return 0;
9 *     } else if (x < y) {
10 *         return -1;
11 *     } else if (x > y) {
12 *         return 1;
13 *     } else {
14 *         return nanval ? 1 : -1;
15 *     }
16 * }
17 */
18    /* op vAA, vBB, vCC */
19    movzbq  3(rPC), %rcx                    # ecx<- CC
20    movzbq  2(rPC), %rax                    # eax<- BB
21    GET_VREG_XMM${suff} %xmm0, %rax
22    xor     %eax, %eax
23    ucomis${suff} VREG_ADDRESS(%rcx), %xmm0
24    jp      .L${opcode}_nan_is_${nanval}
25    je      .L${opcode}_finish
26    jb      .L${opcode}_less
27.L${opcode}_nan_is_pos:
28    addb    $$1, %al
29    jmp     .L${opcode}_finish
30.L${opcode}_nan_is_neg:
31.L${opcode}_less:
32    movl    $$-1, %eax
33.L${opcode}_finish:
34    SET_VREG %eax, rINSTq
35    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
36
37%def fpcvt(source_suffix="", dest_suffix="", wide=""):
38/*
39 * Generic 32-bit FP conversion operation.
40 */
41    /* unop vA, vB */
42    movl    rINST, %ecx                     # rcx <- A+
43    sarl    $$4, rINST                      # rINST <- B
44    andb    $$0xf, %cl                      # ecx <- A
45    cvts${source_suffix}2s${dest_suffix}    VREG_ADDRESS(rINSTq), %xmm0
46    .if $wide
47    SET_VREG_XMMd %xmm0, %rcx
48    CLEAR_WIDE_REF %rcx
49    .else
50    SET_VREG_XMMs %xmm0, %rcx
51    CLEAR_REF %rcx
52    .endif
53    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
54
55%def sseBinop(instr="", suff=""):
56    movzbq  2(rPC), %rcx                    # ecx <- BB
57    movzbq  3(rPC), %rax                    # eax <- CC
58    GET_VREG_XMM${suff} %xmm0, %rcx         # %xmm0 <- 1st src
59#ifdef MTERP_USE_AVX
60    v${instr}${suff} VREG_ADDRESS(%rax), %xmm0, %xmm0
61    SET_VREG_XMM${suff} %xmm0, rINSTq       # vAA <- %xmm0
62    vpxor    %xmm0, %xmm0, %xmm0
63    vmovs${suff}   %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
64#else
65    ${instr}${suff} VREG_ADDRESS(%rax), %xmm0
66    SET_VREG_XMM${suff} %xmm0, rINSTq       # vAA <- %xmm0
67    pxor    %xmm0, %xmm0
68    movs${suff}   %xmm0, VREG_REF_ADDRESS(rINSTq) # clear ref
69#endif
70    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
71
72%def sseBinop2Addr(instr="", suff=""):
73    movl    rINST, %ecx                     # ecx <- A+
74    andl    $$0xf, %ecx                     # ecx <- A
75    GET_VREG_XMM${suff} %xmm0, %rcx         # %xmm0 <- 1st src
76    sarl    $$4, rINST                      # rINST<- B
77#ifdef MTERP_USE_AVX
78    v${instr}${suff} VREG_ADDRESS(rINSTq), %xmm0, %xmm0
79    SET_VREG_XMM${suff} %xmm0, %rcx         # vAA <- %xmm0
80    vpxor    %xmm0, %xmm0, %xmm0
81    vmovs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq)  # clear ref
82#else
83    ${instr}${suff} VREG_ADDRESS(rINSTq), %xmm0
84    SET_VREG_XMM${suff} %xmm0, %rcx         # vAA <- %xmm0
85    pxor    %xmm0, %xmm0
86    movs${suff} %xmm0, VREG_REF_ADDRESS(rINSTq)  # clear ref
87#endif
88    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
89
90%def op_add_double():
91%  sseBinop(instr="adds", suff="d")
92
93%def op_add_double_2addr():
94%  sseBinop2Addr(instr="adds", suff="d")
95
96%def op_add_float():
97%  sseBinop(instr="adds", suff="s")
98
99%def op_add_float_2addr():
100%  sseBinop2Addr(instr="adds", suff="s")
101
102%def op_cmpg_double():
103%  fpcmp(suff="d", nanval="pos")
104
105%def op_cmpg_float():
106%  fpcmp(suff="s", nanval="pos")
107
108%def op_cmpl_double():
109%  fpcmp(suff="d", nanval="neg")
110
111%def op_cmpl_float():
112%  fpcmp(suff="s", nanval="neg")
113
114%def op_div_double():
115%  sseBinop(instr="divs", suff="d")
116
117%def op_div_double_2addr():
118%  sseBinop2Addr(instr="divs", suff="d")
119
120%def op_div_float():
121%  sseBinop(instr="divs", suff="s")
122
123%def op_div_float_2addr():
124%  sseBinop2Addr(instr="divs", suff="s")
125
126%def op_double_to_float():
127%  fpcvt(source_suffix="d", dest_suffix="s", wide="0")
128
129%def op_double_to_int():
130%  cvtfp_int(fp_suffix="d", i_suffix="l", max_const="$0x7fffffff", result_reg="%eax", wide="0")
131
132%def op_double_to_long():
133%  cvtfp_int(fp_suffix="d", i_suffix="q", max_const="$0x7fffffffffffffff", result_reg="%rax", wide="1")
134
135%def op_float_to_double():
136%  fpcvt(source_suffix="s", dest_suffix="d", wide="1")
137
138%def op_float_to_int():
139%  cvtfp_int(fp_suffix="s", i_suffix="l", max_const="$0x7fffffff", result_reg="%eax", wide="0")
140
141%def op_float_to_long():
142%  cvtfp_int(fp_suffix="s", i_suffix="q", max_const="$0x7fffffffffffffff", result_reg="%rax", wide="1")
143
144%def op_int_to_double():
145%  fpcvt(source_suffix="i", dest_suffix="dl", wide="1")
146
147%def op_int_to_float():
148%  fpcvt(source_suffix="i", dest_suffix="sl", wide="0")
149
150%def op_long_to_double():
151%  fpcvt(source_suffix="i", dest_suffix="dq", wide="1")
152
153%def op_long_to_float():
154%  fpcvt(source_suffix="i", dest_suffix="sq", wide="0")
155
156%def op_mul_double():
157%  sseBinop(instr="muls", suff="d")
158
159%def op_mul_double_2addr():
160%  sseBinop2Addr(instr="muls", suff="d")
161
162%def op_mul_float():
163%  sseBinop(instr="muls", suff="s")
164
165%def op_mul_float_2addr():
166%  sseBinop2Addr(instr="muls", suff="s")
167
168%def op_neg_double():
169%  unop(preinstr="    movq    $0x8000000000000000, %rsi", instr="    xorq    %rsi, %rax", wide="1")
170
171%def op_neg_float():
172%  unop(instr="    xorl    $0x80000000, %eax")
173
174%def op_rem_double():
175    /* rem_double vAA, vBB, vCC */
176    movzbq  3(rPC), %rcx                    # ecx <- BB
177    movzbq  2(rPC), %rax                    # eax <- CC
178    fldl    VREG_ADDRESS(%rcx)              # %st1 <- fp[vBB]
179    fldl    VREG_ADDRESS(%rax)              # %st0 <- fp[vCC]
1801:
181    fprem
182    fstsw   %ax
183    sahf
184    jp      1b
185    fstp    %st(1)
186    fstpl   VREG_ADDRESS(rINSTq)            # fp[vAA] <- %st
187    CLEAR_WIDE_REF rINSTq
188    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
189
190%def op_rem_double_2addr():
191    /* rem_double/2addr vA, vB */
192    movzbq  rINSTbl, %rcx                   # ecx <- A+
193    sarl    $$4, rINST                      # rINST <- B
194    fldl    VREG_ADDRESS(rINSTq)            # vB to fp stack
195    andb    $$0xf, %cl                      # ecx <- A
196    fldl    VREG_ADDRESS(%rcx)              # vA to fp stack
1971:
198    fprem
199    fstsw   %ax
200    sahf
201    jp      1b
202    fstp    %st(1)
203    fstpl   VREG_ADDRESS(%rcx)              # %st to vA
204    CLEAR_WIDE_REF %rcx
205    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
206
207%def op_rem_float():
208    /* rem_float vAA, vBB, vCC */
209    movzbq  3(rPC), %rcx                    # ecx <- BB
210    movzbq  2(rPC), %rax                    # eax <- CC
211    flds    VREG_ADDRESS(%rcx)              # vBB to fp stack
212    flds    VREG_ADDRESS(%rax)              # vCC to fp stack
2131:
214    fprem
215    fstsw   %ax
216    sahf
217    jp      1b
218    fstp    %st(1)
219    fstps   VREG_ADDRESS(rINSTq)            # %st to vAA
220    CLEAR_REF rINSTq
221    ADVANCE_PC_FETCH_AND_GOTO_NEXT 2
222
223%def op_rem_float_2addr():
224    /* rem_float/2addr vA, vB */
225    movzbq  rINSTbl, %rcx                   # ecx <- A+
226    sarl    $$4, rINST                      # rINST <- B
227    flds    VREG_ADDRESS(rINSTq)            # vB to fp stack
228    andb    $$0xf, %cl                      # ecx <- A
229    flds    VREG_ADDRESS(%rcx)              # vA to fp stack
2301:
231    fprem
232    fstsw   %ax
233    sahf
234    jp      1b
235    fstp    %st(1)
236    fstps   VREG_ADDRESS(%rcx)              # %st to vA
237    CLEAR_REF %rcx
238    ADVANCE_PC_FETCH_AND_GOTO_NEXT 1
239
240%def op_sub_double():
241%  sseBinop(instr="subs", suff="d")
242
243%def op_sub_double_2addr():
244%  sseBinop2Addr(instr="subs", suff="d")
245
246%def op_sub_float():
247%  sseBinop(instr="subs", suff="s")
248
249%def op_sub_float_2addr():
250%  sseBinop2Addr(instr="subs", suff="s")
251