1 /* 2 * Copyright (c) 2009, 2015, 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 org.graalvm.compiler.asm.amd64; 24 25 import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseIncDec; 26 import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmLoadAndClearUpper; 27 import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmRegToRegMoveAll; 28 29 import org.graalvm.compiler.asm.NumUtil; 30 31 import jdk.vm.ci.amd64.AMD64; 32 import jdk.vm.ci.amd64.AMD64Kind; 33 import jdk.vm.ci.code.Register; 34 import jdk.vm.ci.code.TargetDescription; 35 36 /** 37 * This class implements commonly used X86 code patterns. 38 */ 39 public class AMD64MacroAssembler extends AMD64Assembler { 40 41 public AMD64MacroAssembler(TargetDescription target) { 42 super(target); 43 } 44 45 public final void decrementq(Register reg, int value) { 46 if (value == Integer.MIN_VALUE) { 47 subq(reg, value); 48 return; 49 } 50 if (value < 0) { 51 incrementq(reg, -value); 52 return; 53 } 54 if (value == 0) { 55 return; 56 } 57 if (value == 1 && UseIncDec) { 58 decq(reg); 59 } else { 60 subq(reg, value); 61 } 62 } 63 64 public final void decrementq(AMD64Address dst, int value) { 65 if (value == Integer.MIN_VALUE) { 66 subq(dst, value); 67 return; 68 } 69 if (value < 0) { 70 incrementq(dst, -value); 71 return; 72 } 73 if (value == 0) { 74 return; 75 } 76 if (value == 1 && UseIncDec) { 77 decq(dst); 78 } else { 79 subq(dst, value); 80 } 81 } 82 83 public void incrementq(Register reg, int value) { 84 if (value == Integer.MIN_VALUE) { 85 addq(reg, value); 86 return; 87 } 88 if (value < 0) { 89 decrementq(reg, -value); 90 return; 91 } 92 if (value == 0) { 93 return; 94 } 95 if (value == 1 && UseIncDec) { 96 incq(reg); 97 } else { 98 addq(reg, value); 99 } 100 } 101 102 public final void incrementq(AMD64Address dst, int value) { 103 if (value == Integer.MIN_VALUE) { 104 addq(dst, value); 105 return; 106 } 107 if (value < 0) { 108 decrementq(dst, -value); 109 return; 110 } 111 if (value == 0) { 112 return; 113 } 114 if (value == 1 && UseIncDec) { 115 incq(dst); 116 } else { 117 addq(dst, value); 118 } 119 } 120 121 public final void movptr(Register dst, AMD64Address src) { 122 movq(dst, src); 123 } 124 125 public final void movptr(AMD64Address dst, Register src) { 126 movq(dst, src); 127 } 128 129 public final void movptr(AMD64Address dst, int src) { 130 movslq(dst, src); 131 } 132 133 public final void cmpptr(Register src1, Register src2) { 134 cmpq(src1, src2); 135 } 136 137 public final void cmpptr(Register src1, AMD64Address src2) { 138 cmpq(src1, src2); 139 } 140 141 public final void decrementl(Register reg, int value) { 142 if (value == Integer.MIN_VALUE) { 143 subl(reg, value); 144 return; 145 } 146 if (value < 0) { 147 incrementl(reg, -value); 148 return; 149 } 150 if (value == 0) { 151 return; 152 } 153 if (value == 1 && UseIncDec) { 154 decl(reg); 155 } else { 156 subl(reg, value); 157 } 158 } 159 160 public final void decrementl(AMD64Address dst, int value) { 161 if (value == Integer.MIN_VALUE) { 162 subl(dst, value); 163 return; 164 } 165 if (value < 0) { 166 incrementl(dst, -value); 167 return; 168 } 169 if (value == 0) { 170 return; 171 } 172 if (value == 1 && UseIncDec) { 173 decl(dst); 174 } else { 175 subl(dst, value); 176 } 177 } 178 179 public final void incrementl(Register reg, int value) { 180 if (value == Integer.MIN_VALUE) { 181 addl(reg, value); 182 return; 183 } 184 if (value < 0) { 185 decrementl(reg, -value); 186 return; 187 } 188 if (value == 0) { 189 return; 190 } 191 if (value == 1 && UseIncDec) { 192 incl(reg); 193 } else { 194 addl(reg, value); 195 } 196 } 197 198 public final void incrementl(AMD64Address dst, int value) { 199 if (value == Integer.MIN_VALUE) { 200 addl(dst, value); 201 return; 202 } 203 if (value < 0) { 204 decrementl(dst, -value); 205 return; 206 } 207 if (value == 0) { 208 return; 209 } 210 if (value == 1 && UseIncDec) { 211 incl(dst); 212 } else { 213 addl(dst, value); 214 } 215 } 216 217 public void movflt(Register dst, Register src) { 218 assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM); 219 if (UseXmmRegToRegMoveAll) { 220 movaps(dst, src); 221 } else { 222 movss(dst, src); 223 } 224 } 225 226 public void movflt(Register dst, AMD64Address src) { 227 assert dst.getRegisterCategory().equals(AMD64.XMM); 228 movss(dst, src); 229 } 230 231 public void movflt(AMD64Address dst, Register src) { 232 assert src.getRegisterCategory().equals(AMD64.XMM); 233 movss(dst, src); 234 } 235 236 public void movdbl(Register dst, Register src) { 237 assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM); 238 if (UseXmmRegToRegMoveAll) { 239 movapd(dst, src); 240 } else { 241 movsd(dst, src); 242 } 243 } 244 245 public void movdbl(Register dst, AMD64Address src) { 246 assert dst.getRegisterCategory().equals(AMD64.XMM); 247 if (UseXmmLoadAndClearUpper) { 248 movsd(dst, src); 249 } else { 250 movlpd(dst, src); 251 } 252 } 253 254 public void movdbl(AMD64Address dst, Register src) { 255 assert src.getRegisterCategory().equals(AMD64.XMM); 256 movsd(dst, src); 257 } 258 259 /** 260 * Non-atomic write of a 64-bit constant to memory. Do not use if the address might be a 261 * volatile field! 262 */ 263 public final void movlong(AMD64Address dst, long src) { 264 if (NumUtil.isInt(src)) { 265 AMD64MIOp.MOV.emit(this, OperandSize.QWORD, dst, (int) src); 266 } else { 267 AMD64Address high = new AMD64Address(dst.getBase(), dst.getIndex(), dst.getScale(), dst.getDisplacement() + 4); 268 movl(dst, (int) (src & 0xFFFFFFFF)); 269 movl(high, (int) (src >> 32)); 270 } 271 272 } 273 274 public final void flog(Register dest, Register value, boolean base10) { 275 if (base10) { 276 fldlg2(); 277 } else { 278 fldln2(); 279 } 280 AMD64Address tmp = trigPrologue(value); 281 fyl2x(); 282 trigEpilogue(dest, tmp); 283 } 284 285 public final void fsin(Register dest, Register value) { 286 AMD64Address tmp = trigPrologue(value); 287 fsin(); 288 trigEpilogue(dest, tmp); 289 } 290 291 public final void fcos(Register dest, Register value) { 292 AMD64Address tmp = trigPrologue(value); 293 fcos(); 294 trigEpilogue(dest, tmp); 295 } 296 297 public final void ftan(Register dest, Register value) { 298 AMD64Address tmp = trigPrologue(value); 299 fptan(); 300 fstp(0); // ftan pushes 1.0 in addition to the actual result, pop 301 trigEpilogue(dest, tmp); 302 } 303 304 public final void fpop() { 305 ffree(0); 306 fincstp(); 307 } 308 309 private AMD64Address trigPrologue(Register value) { 310 assert value.getRegisterCategory().equals(AMD64.XMM); 311 AMD64Address tmp = new AMD64Address(AMD64.rsp); 312 subq(AMD64.rsp, AMD64Kind.DOUBLE.getSizeInBytes()); 313 movdbl(tmp, value); 314 fldd(tmp); 315 return tmp; 316 } 317 318 private void trigEpilogue(Register dest, AMD64Address tmp) { 319 assert dest.getRegisterCategory().equals(AMD64.XMM); 320 fstpd(tmp); 321 movdbl(dest, tmp); 322 addq(AMD64.rsp, AMD64Kind.DOUBLE.getSizeInBytes()); 323 } 324 }