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