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.core.common.NumUtil.isByte; 26 import static org.graalvm.compiler.core.common.NumUtil.isInt; 27 import static org.graalvm.compiler.core.common.NumUtil.isShiftCount; 28 import static org.graalvm.compiler.core.common.NumUtil.isUByte; 29 import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseAddressNop; 30 import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseNormalNop; 31 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.ADD; 32 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.AND; 33 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.CMP; 34 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.OR; 35 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.SBB; 36 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.SUB; 37 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.XOR; 38 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.DEC; 39 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.INC; 40 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.NEG; 41 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.NOT; 42 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.BYTE; 43 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD; 44 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PD; 45 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PS; 46 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; 47 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SD; 48 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SS; 49 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD; 50 import static jdk.vm.ci.amd64.AMD64.CPU; 51 import static jdk.vm.ci.amd64.AMD64.XMM; 52 import static jdk.vm.ci.amd64.AMD64.r12; 53 import static jdk.vm.ci.amd64.AMD64.r13; 54 import static jdk.vm.ci.amd64.AMD64.rbp; 55 import static jdk.vm.ci.amd64.AMD64.rip; 56 import static jdk.vm.ci.amd64.AMD64.rsp; 57 import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; 58 59 import org.graalvm.compiler.asm.Assembler; 60 import org.graalvm.compiler.asm.Label; 61 import org.graalvm.compiler.core.common.NumUtil; 62 import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; 63 64 import jdk.vm.ci.amd64.AMD64; 65 import jdk.vm.ci.amd64.AMD64.CPUFeature; 66 import jdk.vm.ci.code.Register; 67 import jdk.vm.ci.code.Register.RegisterCategory; 68 import jdk.vm.ci.code.TargetDescription; 69 70 /** 71 * This class implements an assembler that can encode most X86 instructions. 72 */ 73 public class AMD64Assembler extends Assembler { 74 75 private static final int MinEncodingNeedsRex = 8; 76 77 /** 78 * The x86 condition codes used for conditional jumps/moves. 79 */ 80 public enum ConditionFlag { 81 Zero(0x4, "|zero|"), 82 NotZero(0x5, "|nzero|"), 83 Equal(0x4, "="), 84 NotEqual(0x5, "!="), 85 Less(0xc, "<"), 86 LessEqual(0xe, "<="), 87 Greater(0xf, ">"), 88 GreaterEqual(0xd, ">="), 208 private static final int VEX_OPCODE_NONE = 0x0; 209 private static final int VEX_OPCODE_0F = 0x1; 210 private static final int VEX_OPCODE_0F_38 = 0x2; 211 private static final int VEX_OPCODE_0F_3A = 0x3; 212 } 213 214 private AMD64InstructionAttr curAttributes; 215 216 AMD64InstructionAttr getCurAttributes() { 217 return curAttributes; 218 } 219 220 void setCurAttributes(AMD64InstructionAttr attributes) { 221 curAttributes = attributes; 222 } 223 224 /** 225 * The x86 operand sizes. 226 */ 227 public enum OperandSize { 228 BYTE(1) { 229 @Override 230 protected void emitImmediate(AMD64Assembler asm, int imm) { 231 assert imm == (byte) imm; 232 asm.emitByte(imm); 233 } 234 235 @Override 236 protected int immediateSize() { 237 return 1; 238 } 239 }, 240 241 WORD(2, 0x66) { 242 @Override 243 protected void emitImmediate(AMD64Assembler asm, int imm) { 244 assert imm == (short) imm; 245 asm.emitShort(imm); 246 } 247 248 @Override 249 protected int immediateSize() { 250 return 2; 251 } 252 }, 253 254 DWORD(4) { 255 @Override 256 protected void emitImmediate(AMD64Assembler asm, int imm) { 257 asm.emitInt(imm); 258 } 259 260 @Override 261 protected int immediateSize() { 262 return 4; 263 } 264 }, 265 266 QWORD(8) { 267 @Override 268 protected void emitImmediate(AMD64Assembler asm, int imm) { 269 asm.emitInt(imm); 270 } 271 272 @Override 273 protected int immediateSize() { 274 return 4; 275 } 276 }, 277 278 SS(4, 0xF3, true), 279 280 SD(8, 0xF2, true), 281 282 PS(16, true), 283 284 PD(16, 0x66, true); 285 286 private final int sizePrefix; 287 288 private final int bytes; 289 private final boolean xmm; 290 291 OperandSize(int bytes) { 292 this(bytes, 0); 293 } 294 295 OperandSize(int bytes, int sizePrefix) { 296 this(bytes, sizePrefix, false); 297 } 298 299 OperandSize(int bytes, boolean xmm) { 300 this(bytes, 0, xmm); 301 } 302 303 OperandSize(int bytes, int sizePrefix, boolean xmm) { 304 this.sizePrefix = sizePrefix; 305 this.bytes = bytes; 306 this.xmm = xmm; 307 } 308 309 public int getBytes() { 310 return bytes; 311 } 312 313 public boolean isXmmType() { 314 return xmm; 315 } 316 317 /** 318 * Emit an immediate of this size. Note that immediate {@link #QWORD} operands are encoded 319 * as sign-extended 32-bit values. 320 * 321 * @param asm 322 * @param imm 323 */ 324 protected void emitImmediate(AMD64Assembler asm, int imm) { 325 throw new UnsupportedOperationException(); 326 } 327 328 protected int immediateSize() { 329 throw new UnsupportedOperationException(); 330 } 331 } 332 333 /** 334 * Operand size and register type constraints. 335 */ 336 private enum OpAssertion { 2213 prefix(dst); 2214 emitByte(0xC7); 2215 emitOperandHelper(0, dst, 2); 2216 emitShort(imm16); 2217 } 2218 2219 public final void movw(AMD64Address dst, Register src) { 2220 emitByte(0x66); 2221 prefix(dst, src); 2222 emitByte(0x89); 2223 emitOperandHelper(src, dst, 0); 2224 } 2225 2226 public final void movzbl(Register dst, AMD64Address src) { 2227 prefix(src, dst); 2228 emitByte(0x0F); 2229 emitByte(0xB6); 2230 emitOperandHelper(dst, src, 0); 2231 } 2232 2233 public final void movzwl(Register dst, AMD64Address src) { 2234 prefix(src, dst); 2235 emitByte(0x0F); 2236 emitByte(0xB7); 2237 emitOperandHelper(dst, src, 0); 2238 } 2239 2240 public final void negl(Register dst) { 2241 NEG.emit(this, DWORD, dst); 2242 } 2243 2244 public final void notl(Register dst) { 2245 NOT.emit(this, DWORD, dst); 2246 } 2247 2248 @Override 2249 public final void ensureUniquePC() { 2250 nop(); 2251 } 2252 3178 emitByte(0x0F); 3179 emitByte(0xBD); 3180 emitByte(0xC0 | encode); 3181 } 3182 3183 public final void bswapq(Register reg) { 3184 int encode = prefixqAndEncode(reg.encoding); 3185 emitByte(0x0F); 3186 emitByte(0xC8 | encode); 3187 } 3188 3189 public final void cdqq() { 3190 emitByte(Prefix.REXW); 3191 emitByte(0x99); 3192 } 3193 3194 public final void cmovq(ConditionFlag cc, Register dst, Register src) { 3195 int encode = prefixqAndEncode(dst.encoding, src.encoding); 3196 emitByte(0x0F); 3197 emitByte(0x40 | cc.getValue()); 3198 emitByte(0xC0 | encode); 3199 } 3200 3201 public final void cmovq(ConditionFlag cc, Register dst, AMD64Address src) { 3202 prefixq(src, dst); 3203 emitByte(0x0F); 3204 emitByte(0x40 | cc.getValue()); 3205 emitOperandHelper(dst, src, 0); 3206 } 3207 3208 public final void cmpq(Register dst, int imm32) { 3209 CMP.getMIOpcode(QWORD, isByte(imm32)).emit(this, QWORD, dst, imm32); 3210 } 3211 3212 public final void cmpq(Register dst, Register src) { 3213 CMP.rmOp.emit(this, QWORD, dst, src); 3214 } 3215 3216 public final void cmpq(Register dst, AMD64Address src) { 3217 CMP.rmOp.emit(this, QWORD, dst, src); | 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 jdk.vm.ci.amd64.AMD64.CPU; 26 import static jdk.vm.ci.amd64.AMD64.XMM; 27 import static jdk.vm.ci.amd64.AMD64.r12; 28 import static jdk.vm.ci.amd64.AMD64.r13; 29 import static jdk.vm.ci.amd64.AMD64.rbp; 30 import static jdk.vm.ci.amd64.AMD64.rip; 31 import static jdk.vm.ci.amd64.AMD64.rsp; 32 import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; 33 import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseAddressNop; 34 import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseNormalNop; 35 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.ADD; 36 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.AND; 37 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.CMP; 38 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.OR; 39 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.SBB; 40 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.SUB; 41 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.XOR; 42 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.DEC; 43 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.INC; 44 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.NEG; 45 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp.NOT; 46 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.BYTE; 47 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD; 48 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PD; 49 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PS; 50 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; 51 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SD; 52 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SS; 53 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD; 54 import static org.graalvm.compiler.core.common.NumUtil.isByte; 55 import static org.graalvm.compiler.core.common.NumUtil.isInt; 56 import static org.graalvm.compiler.core.common.NumUtil.isShiftCount; 57 import static org.graalvm.compiler.core.common.NumUtil.isUByte; 58 59 import org.graalvm.compiler.asm.Assembler; 60 import org.graalvm.compiler.asm.Label; 61 import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; 62 import org.graalvm.compiler.core.common.NumUtil; 63 import org.graalvm.compiler.debug.GraalError; 64 65 import jdk.vm.ci.amd64.AMD64; 66 import jdk.vm.ci.amd64.AMD64.CPUFeature; 67 import jdk.vm.ci.amd64.AMD64Kind; 68 import jdk.vm.ci.code.Register; 69 import jdk.vm.ci.code.Register.RegisterCategory; 70 import jdk.vm.ci.code.TargetDescription; 71 import jdk.vm.ci.meta.PlatformKind; 72 73 /** 74 * This class implements an assembler that can encode most X86 instructions. 75 */ 76 public class AMD64Assembler extends Assembler { 77 78 private static final int MinEncodingNeedsRex = 8; 79 80 /** 81 * The x86 condition codes used for conditional jumps/moves. 82 */ 83 public enum ConditionFlag { 84 Zero(0x4, "|zero|"), 85 NotZero(0x5, "|nzero|"), 86 Equal(0x4, "="), 87 NotEqual(0x5, "!="), 88 Less(0xc, "<"), 89 LessEqual(0xe, "<="), 90 Greater(0xf, ">"), 91 GreaterEqual(0xd, ">="), 211 private static final int VEX_OPCODE_NONE = 0x0; 212 private static final int VEX_OPCODE_0F = 0x1; 213 private static final int VEX_OPCODE_0F_38 = 0x2; 214 private static final int VEX_OPCODE_0F_3A = 0x3; 215 } 216 217 private AMD64InstructionAttr curAttributes; 218 219 AMD64InstructionAttr getCurAttributes() { 220 return curAttributes; 221 } 222 223 void setCurAttributes(AMD64InstructionAttr attributes) { 224 curAttributes = attributes; 225 } 226 227 /** 228 * The x86 operand sizes. 229 */ 230 public enum OperandSize { 231 BYTE(1, AMD64Kind.BYTE) { 232 @Override 233 protected void emitImmediate(AMD64Assembler asm, int imm) { 234 assert imm == (byte) imm; 235 asm.emitByte(imm); 236 } 237 238 @Override 239 protected int immediateSize() { 240 return 1; 241 } 242 }, 243 244 WORD(2, AMD64Kind.WORD, 0x66) { 245 @Override 246 protected void emitImmediate(AMD64Assembler asm, int imm) { 247 assert imm == (short) imm; 248 asm.emitShort(imm); 249 } 250 251 @Override 252 protected int immediateSize() { 253 return 2; 254 } 255 }, 256 257 DWORD(4, AMD64Kind.DWORD) { 258 @Override 259 protected void emitImmediate(AMD64Assembler asm, int imm) { 260 asm.emitInt(imm); 261 } 262 263 @Override 264 protected int immediateSize() { 265 return 4; 266 } 267 }, 268 269 QWORD(8, AMD64Kind.QWORD) { 270 @Override 271 protected void emitImmediate(AMD64Assembler asm, int imm) { 272 asm.emitInt(imm); 273 } 274 275 @Override 276 protected int immediateSize() { 277 return 4; 278 } 279 }, 280 281 SS(4, AMD64Kind.SINGLE, 0xF3, true), 282 283 SD(8, AMD64Kind.DOUBLE, 0xF2, true), 284 285 PS(16, AMD64Kind.V128_SINGLE, true), 286 287 PD(16, AMD64Kind.V128_DOUBLE, 0x66, true); 288 289 private final int sizePrefix; 290 private final int bytes; 291 private final boolean xmm; 292 private final AMD64Kind kind; 293 294 OperandSize(int bytes, AMD64Kind kind) { 295 this(bytes, kind, 0); 296 } 297 298 OperandSize(int bytes, AMD64Kind kind, int sizePrefix) { 299 this(bytes, kind, sizePrefix, false); 300 } 301 302 OperandSize(int bytes, AMD64Kind kind, boolean xmm) { 303 this(bytes, kind, 0, xmm); 304 } 305 306 OperandSize(int bytes, AMD64Kind kind, int sizePrefix, boolean xmm) { 307 this.sizePrefix = sizePrefix; 308 this.bytes = bytes; 309 this.kind = kind; 310 this.xmm = xmm; 311 } 312 313 public int getBytes() { 314 return bytes; 315 } 316 317 public boolean isXmmType() { 318 return xmm; 319 } 320 321 public AMD64Kind getKind() { 322 return kind; 323 } 324 325 public static OperandSize get(PlatformKind kind) { 326 for (OperandSize operandSize : OperandSize.values()) { 327 if (operandSize.kind.equals(kind)) { 328 return operandSize; 329 } 330 } 331 throw GraalError.shouldNotReachHere("Unexpected kind: " + kind.toString()); 332 } 333 334 /** 335 * Emit an immediate of this size. Note that immediate {@link #QWORD} operands are encoded 336 * as sign-extended 32-bit values. 337 * 338 * @param asm 339 * @param imm 340 */ 341 protected void emitImmediate(AMD64Assembler asm, int imm) { 342 throw new UnsupportedOperationException(); 343 } 344 345 protected int immediateSize() { 346 throw new UnsupportedOperationException(); 347 } 348 } 349 350 /** 351 * Operand size and register type constraints. 352 */ 353 private enum OpAssertion { 2230 prefix(dst); 2231 emitByte(0xC7); 2232 emitOperandHelper(0, dst, 2); 2233 emitShort(imm16); 2234 } 2235 2236 public final void movw(AMD64Address dst, Register src) { 2237 emitByte(0x66); 2238 prefix(dst, src); 2239 emitByte(0x89); 2240 emitOperandHelper(src, dst, 0); 2241 } 2242 2243 public final void movzbl(Register dst, AMD64Address src) { 2244 prefix(src, dst); 2245 emitByte(0x0F); 2246 emitByte(0xB6); 2247 emitOperandHelper(dst, src, 0); 2248 } 2249 2250 public final void movzbl(Register dst, Register src) { 2251 AMD64RMOp.MOVZXB.emit(this, OperandSize.DWORD, dst, src); 2252 } 2253 2254 public final void movzbq(Register dst, Register src) { 2255 AMD64RMOp.MOVZXB.emit(this, OperandSize.QWORD, dst, src); 2256 } 2257 2258 public final void movzwl(Register dst, AMD64Address src) { 2259 prefix(src, dst); 2260 emitByte(0x0F); 2261 emitByte(0xB7); 2262 emitOperandHelper(dst, src, 0); 2263 } 2264 2265 public final void negl(Register dst) { 2266 NEG.emit(this, DWORD, dst); 2267 } 2268 2269 public final void notl(Register dst) { 2270 NOT.emit(this, DWORD, dst); 2271 } 2272 2273 @Override 2274 public final void ensureUniquePC() { 2275 nop(); 2276 } 2277 3203 emitByte(0x0F); 3204 emitByte(0xBD); 3205 emitByte(0xC0 | encode); 3206 } 3207 3208 public final void bswapq(Register reg) { 3209 int encode = prefixqAndEncode(reg.encoding); 3210 emitByte(0x0F); 3211 emitByte(0xC8 | encode); 3212 } 3213 3214 public final void cdqq() { 3215 emitByte(Prefix.REXW); 3216 emitByte(0x99); 3217 } 3218 3219 public final void cmovq(ConditionFlag cc, Register dst, Register src) { 3220 int encode = prefixqAndEncode(dst.encoding, src.encoding); 3221 emitByte(0x0F); 3222 emitByte(0x40 | cc.getValue()); 3223 emitByte(0xC0 | encode); 3224 } 3225 3226 public final void setb(ConditionFlag cc, Register dst) { 3227 int encode = prefixAndEncode(dst.encoding, true); 3228 emitByte(0x0F); 3229 emitByte(0x90 | cc.getValue()); 3230 emitByte(0xC0 | encode); 3231 } 3232 3233 public final void cmovq(ConditionFlag cc, Register dst, AMD64Address src) { 3234 prefixq(src, dst); 3235 emitByte(0x0F); 3236 emitByte(0x40 | cc.getValue()); 3237 emitOperandHelper(dst, src, 0); 3238 } 3239 3240 public final void cmpq(Register dst, int imm32) { 3241 CMP.getMIOpcode(QWORD, isByte(imm32)).emit(this, QWORD, dst, imm32); 3242 } 3243 3244 public final void cmpq(Register dst, Register src) { 3245 CMP.rmOp.emit(this, QWORD, dst, src); 3246 } 3247 3248 public final void cmpq(Register dst, AMD64Address src) { 3249 CMP.rmOp.emit(this, QWORD, dst, src); |