comparison graal/com.oracle.max.asm.amd64/src/com/oracle/max/asm/amd64/AMD64MacroAssembler.java @ 6493:85c1b84f8fd9

moved ADM64-specific assembler code into separate project
author Doug Simon <doug.simon@oracle.com>
date Tue, 02 Oct 2012 22:22:06 +0200
parents graal/com.oracle.max.asm/src/com/oracle/max/asm/target/amd64/AMD64MacroAssembler.java@92bc58dc5b5e
children
comparison
equal deleted inserted replaced
6492:dc409418cc2c 6493:85c1b84f8fd9
1 /*
2 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.oracle.max.asm.amd64;
24
25 import static com.oracle.max.asm.amd64.AMD64AsmOptions.*;
26
27 import com.oracle.graal.api.code.*;
28 import com.oracle.graal.api.meta.*;
29 import com.oracle.max.asm.*;
30
31 /**
32 * This class implements commonly used X86 code patterns.
33 */
34 public class AMD64MacroAssembler extends AMD64Assembler {
35
36 public AMD64MacroAssembler(TargetDescription target, RegisterConfig registerConfig) {
37 super(target, registerConfig);
38 }
39
40 public void pushptr(Address src) {
41 pushq(src);
42 }
43
44 public void popptr(Address src) {
45 popq(src);
46 }
47
48 public void xorptr(Register dst, Register src) {
49 xorq(dst, src);
50 }
51
52 public void xorptr(Register dst, Address src) {
53 xorq(dst, src);
54 }
55
56 // 64 bit versions
57
58
59 public void decrementq(Register reg, int value) {
60 if (value == Integer.MIN_VALUE) {
61 subq(reg, value);
62 return;
63 }
64 if (value < 0) {
65 incrementq(reg, -value);
66 return;
67 }
68 if (value == 0) {
69 return;
70 }
71 if (value == 1 && UseIncDec) {
72 decq(reg);
73 } else {
74 subq(reg, value);
75 }
76 }
77
78 public void incrementq(Register reg, int value) {
79 if (value == Integer.MIN_VALUE) {
80 addq(reg, value);
81 return;
82 }
83 if (value < 0) {
84 decrementq(reg, -value);
85 return;
86 }
87 if (value == 0) {
88 return;
89 }
90 if (value == 1 && UseIncDec) {
91 incq(reg);
92 } else {
93 addq(reg, value);
94 }
95 }
96
97 // These are mostly for initializing null
98 public void movptr(Address dst, int src) {
99 movslq(dst, src);
100 }
101
102 public final void cmp32(Register src1, int imm) {
103 cmpl(src1, imm);
104 }
105
106 public final void cmp32(Register src1, Address src2) {
107 cmpl(src1, src2);
108 }
109
110 public void cmpsd2int(Register opr1, Register opr2, Register dst, boolean unorderedIsLess) {
111 assert opr1.isFpu() && opr2.isFpu();
112 ucomisd(opr1, opr2);
113
114 Label l = new Label();
115 if (unorderedIsLess) {
116 movl(dst, -1);
117 jcc(AMD64Assembler.ConditionFlag.parity, l);
118 jcc(AMD64Assembler.ConditionFlag.below, l);
119 movl(dst, 0);
120 jcc(AMD64Assembler.ConditionFlag.equal, l);
121 incrementl(dst, 1);
122 } else { // unordered is greater
123 movl(dst, 1);
124 jcc(AMD64Assembler.ConditionFlag.parity, l);
125 jcc(AMD64Assembler.ConditionFlag.above, l);
126 movl(dst, 0);
127 jcc(AMD64Assembler.ConditionFlag.equal, l);
128 decrementl(dst, 1);
129 }
130 bind(l);
131 }
132
133 public void cmpss2int(Register opr1, Register opr2, Register dst, boolean unorderedIsLess) {
134 assert opr1.isFpu();
135 assert opr2.isFpu();
136 ucomiss(opr1, opr2);
137
138 Label l = new Label();
139 if (unorderedIsLess) {
140 movl(dst, -1);
141 jcc(AMD64Assembler.ConditionFlag.parity, l);
142 jcc(AMD64Assembler.ConditionFlag.below, l);
143 movl(dst, 0);
144 jcc(AMD64Assembler.ConditionFlag.equal, l);
145 incrementl(dst, 1);
146 } else { // unordered is greater
147 movl(dst, 1);
148 jcc(AMD64Assembler.ConditionFlag.parity, l);
149 jcc(AMD64Assembler.ConditionFlag.above, l);
150 movl(dst, 0);
151 jcc(AMD64Assembler.ConditionFlag.equal, l);
152 decrementl(dst, 1);
153 }
154 bind(l);
155 }
156
157 public void cmpptr(Register src1, Register src2) {
158 cmpq(src1, src2);
159 }
160
161 public void cmpptr(Register src1, Address src2) {
162 cmpq(src1, src2);
163 }
164
165 public void cmpptr(Register src1, int src2) {
166 cmpq(src1, src2);
167 }
168
169 public void cmpptr(Address src1, int src2) {
170 cmpq(src1, src2);
171 }
172
173 public void decrementl(Register reg, int value) {
174 if (value == Integer.MIN_VALUE) {
175 subl(reg, value);
176 return;
177 }
178 if (value < 0) {
179 incrementl(reg, -value);
180 return;
181 }
182 if (value == 0) {
183 return;
184 }
185 if (value == 1 && UseIncDec) {
186 decl(reg);
187 } else {
188 subl(reg, value);
189 }
190 }
191
192 public void decrementl(Address dst, int value) {
193 if (value == Integer.MIN_VALUE) {
194 subl(dst, value);
195 return;
196 }
197 if (value < 0) {
198 incrementl(dst, -value);
199 return;
200 }
201 if (value == 0) {
202 return;
203 }
204 if (value == 1 && UseIncDec) {
205 decl(dst);
206 } else {
207 subl(dst, value);
208 }
209 }
210
211 public void incrementl(Register reg, int value) {
212 if (value == Integer.MIN_VALUE) {
213 addl(reg, value);
214 return;
215 }
216 if (value < 0) {
217 decrementl(reg, -value);
218 return;
219 }
220 if (value == 0) {
221 return;
222 }
223 if (value == 1 && UseIncDec) {
224 incl(reg);
225 } else {
226 addl(reg, value);
227 }
228 }
229
230 public void incrementl(Address dst, int value) {
231 if (value == Integer.MIN_VALUE) {
232 addl(dst, value);
233 return;
234 }
235 if (value < 0) {
236 decrementl(dst, -value);
237 return;
238 }
239 if (value == 0) {
240 return;
241 }
242 if (value == 1 && UseIncDec) {
243 incl(dst);
244 } else {
245 addl(dst, value);
246 }
247 }
248
249 public void signExtendByte(Register reg) {
250 if (reg.isByte()) {
251 movsxb(reg, reg); // movsxb
252 } else {
253 shll(reg, 24);
254 sarl(reg, 24);
255 }
256 }
257
258 public void signExtendShort(Register reg) {
259 movsxw(reg, reg); // movsxw
260 }
261
262 // Support optimal SSE move instructions.
263 public void movflt(Register dst, Register src) {
264 assert dst.isFpu() && src.isFpu();
265 if (UseXmmRegToRegMoveAll) {
266 movaps(dst, src);
267 } else {
268 movss(dst, src);
269 }
270 }
271
272 public void movflt(Register dst, Address src) {
273 assert dst.isFpu();
274 movss(dst, src);
275 }
276
277 public void movflt(Address dst, Register src) {
278 assert src.isFpu();
279 movss(dst, src);
280 }
281
282 public void movdbl(Register dst, Register src) {
283 assert dst.isFpu() && src.isFpu();
284 if (UseXmmRegToRegMoveAll) {
285 movapd(dst, src);
286 } else {
287 movsd(dst, src);
288 }
289 }
290
291 public void movdbl(Register dst, Address src) {
292 assert dst.isFpu();
293 if (UseXmmLoadAndClearUpper) {
294 movsd(dst, src);
295 } else {
296 movlpd(dst, src);
297 }
298 }
299
300 public void movdbl(Address dst, Register src) {
301 assert src.isFpu();
302 movsd(dst, src);
303 }
304
305 /**
306 * Non-atomic write of a 64-bit constant to memory. Do not use
307 * if the address might be a volatile field!
308 */
309 public void movlong(Address dst, long src) {
310 Address high = new Address(dst.getKind(), dst.getBase(), dst.getIndex(), dst.getScale(), dst.getDisplacement() + 4);
311 movl(dst, (int) (src & 0xFFFFFFFF));
312 movl(high, (int) (src >> 32));
313 }
314
315 public void xchgptr(Register src1, Register src2) {
316 xchgq(src1, src2);
317 }
318
319 public void flog(Register dest, Register value, boolean base10) {
320 assert value.spillSlotSize == dest.spillSlotSize;
321
322 Address tmp = new Address(Kind.Double, AMD64.RSP);
323 if (base10) {
324 fldlg2();
325 } else {
326 fldln2();
327 }
328 subq(AMD64.rsp, value.spillSlotSize);
329 movsd(tmp, value);
330 fld(tmp);
331 fyl2x();
332 fstp(tmp);
333 movsd(dest, tmp);
334 addq(AMD64.rsp, dest.spillSlotSize);
335 }
336
337 public void fsin(Register dest, Register value) {
338 ftrig(dest, value, 's');
339 }
340
341 public void fcos(Register dest, Register value) {
342 ftrig(dest, value, 'c');
343 }
344
345 public void ftan(Register dest, Register value) {
346 ftrig(dest, value, 't');
347 }
348
349 private void ftrig(Register dest, Register value, char op) {
350 assert value.spillSlotSize == dest.spillSlotSize;
351
352 Address tmp = new Address(Kind.Double, AMD64.RSP);
353 subq(AMD64.rsp, value.spillSlotSize);
354 movsd(tmp, value);
355 fld(tmp);
356 if (op == 's') {
357 fsin();
358 } else if (op == 'c') {
359 fcos();
360 } else if (op == 't') {
361 fptan();
362 fstp(0); // ftan pushes 1.0 in addition to the actual result, pop
363 } else {
364 throw new InternalError("should not reach here");
365 }
366 fstp(tmp);
367 movsd(dest, tmp);
368 addq(AMD64.rsp, dest.spillSlotSize);
369 }
370
371 /**
372 * Emit code to save a given set of callee save registers in the
373 * {@linkplain CalleeSaveLayout CSA} within the frame.
374 * @param csl the description of the CSA
375 * @param frameToCSA offset from the frame pointer to the CSA
376 */
377 public void save(CalleeSaveLayout csl, int frameToCSA) {
378 RegisterValue frame = frameRegister.asValue();
379 for (Register r : csl.registers) {
380 int offset = csl.offsetOf(r);
381 movq(new Address(target.wordKind, frame, frameToCSA + offset), r);
382 }
383 }
384
385 public void restore(CalleeSaveLayout csl, int frameToCSA) {
386 RegisterValue frame = frameRegister.asValue();
387 for (Register r : csl.registers) {
388 int offset = csl.offsetOf(r);
389 movq(r, new Address(target.wordKind, frame, frameToCSA + offset));
390 }
391 }
392 }