Mercurial > hg > truffle
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 } |