/* * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.max.asm.gen.cisc.amd64; import static com.sun.max.asm.amd64.AMD64GeneralRegister16.*; import static com.sun.max.asm.amd64.AMD64GeneralRegister32.*; import static com.sun.max.asm.amd64.AMD64GeneralRegister64.*; import static com.sun.max.asm.amd64.AMD64GeneralRegister8.*; import static com.sun.max.asm.gen.cisc.amd64.AMD64ModRMGroup.*; import static com.sun.max.asm.gen.cisc.x86.AddressingMethodCode.*; import static com.sun.max.asm.gen.cisc.x86.HexByte.*; import static com.sun.max.asm.gen.cisc.x86.OperandCode.*; import static com.sun.max.asm.gen.cisc.x86.OperandTypeCode.*; import static com.sun.max.asm.gen.cisc.x86.RegisterOperandCode.*; import static com.sun.max.asm.gen.cisc.x86.X86Opcode.*; import com.sun.max.asm.amd64.*; import com.sun.max.asm.gen.cisc.x86.*; import com.sun.max.lang.*; /** */ public class OneByteOpcodeMap extends X86InstructionDescriptionCreator { /** * Refer to "Table A-1. One-Byte Opcodes, Low Nibble 0-7h" */ private void create_low() { define(_00, "ADD", Eb, Gb); define(_01, "ADD", Ev, Gv); define(_02, "ADD", Gb, Eb); define(_03, "ADD", Gv, Ev); define(_04, "ADD", AL, Ib); define(_05, "ADD", rAX, Iz.externalRange(0, Integer.MAX_VALUE)); define(_10, "ADC", Eb, Gb); define(_11, "ADC", Ev, Gv); define(_12, "ADC", Gb, Eb); define(_13, "ADC", Gv, Ev); define(_14, "ADC", AL, Ib); define(_15, "ADC", rAX, Iz.externalRange(0, Integer.MAX_VALUE)); define(_20, "AND", Eb, Gb); define(_21, "AND", Ev, Gv); define(_22, "AND", Gb, Eb); define(_23, "AND", Gv, Ev); define(_24, "AND", AL, Ib); define(_25, "AND", rAX, Iz.externalRange(0, Integer.MAX_VALUE)); define(_30, "XOR", Eb, Gb); define(_31, "XOR", Ev, Gv); define(_32, "XOR", Gb, Eb); define(_33, "XOR", Gv, Ev); define(_34, "XOR", AL, Ib); define(_35, "XOR", rAX, Iz.externalRange(0, Integer.MAX_VALUE)); define(_50, "PUSH", Nv).setDefaultOperandSize(WordWidth.BITS_64); define(_63, "MOVSXD", Gq, Ed).requireOperandSize(WordWidth.BITS_64).beNotExternallyTestable(); // REX.W == 1, gas does not seem to know it define(_63, "MOVZXD", Gq, Ed).requireOperandSize(WordWidth.BITS_32).beNotExternallyTestable(); // REX.W == 0, we made this extra mnemonic up define(SEG_FS, "SEG_FS").beNotExternallyTestable(); // prefix define(SEG_GS, "SEG_GS").beNotExternallyTestable(); // prefix define(OPERAND_SIZE, "OPERAND_SIZE").beNotDisassemblable().beNotExternallyTestable(); // prefix define(ADDRESS_SIZE, "ADDRESS_SIZE").beNotDisassemblable().beNotExternallyTestable(); // prefix define(_70, "JO", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_71, "JNO", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_72, "JB", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_73, "JNB", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_74, "JZ", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_75, "JNZ", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_76, "JBE", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_77, "JNBE", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_80, GROUP_1, b, Eb.excludeExternalTestArguments(AL), Ib); define(_81, GROUP_1, v, Ev.excludeExternalTestArguments(AX, EAX, RAX), Iz.externalRange(0, Integer.MAX_VALUE)); define(_83, GROUP_1, v, Ev, Ib).beNotExternallyTestable(); define(_84, "TEST", Eb, Gb).revertExternalOperandOrdering(); define(_85, "TEST", Ev, Gv).revertExternalOperandOrdering(); define(_86, "XCHG", Eb, Gb); define(_87, "XCHG", Ev.excludeExternalTestArguments(AX, EAX, RAX), Gv.excludeExternalTestArguments(AX, EAX, RAX)); define(_90, "NOP"); define(_90, "XCHG", Nv.excludeDisassemblerTestArguments(AX, EAX, RAX), rAX).beNotExternallyTestable(); define(_A0, "MOV", AL, Ob).beNotExternallyTestable(); define(_A1, "MOV", rAX, Ov).beNotExternallyTestable(); define(_A2, "MOV", Ob, AL).beNotExternallyTestable(); define(_A3, "MOV", Ov, rAX).beNotExternallyTestable(); define(_A4, "MOVS", Yb, Xb); define(_A5, "MOVS", Yv, Xv); define(_A6, "CMPS", Yb, Xb); define(_A7, "CMPS", Yv, Xv); define(_B0, "MOV", Nb, Ib); define(_C0, GROUP_2, b, Eb, Ib); define(_C1, GROUP_2, v, Ev, Ib); define(_C2, "RET", Iw).setDefaultOperandSize(WordWidth.BITS_64); define(_C3, "RET").setDefaultOperandSize(WordWidth.BITS_64); define(_C6, "MOV", b, Eb.excludeExternalTestArguments(AMD64GeneralRegister8.ENUMERATOR), Ib); define(_C7, "MOV", v, Ev.excludeExternalTestArguments(AMD64GeneralRegister16.ENUMERATOR, AMD64GeneralRegister32.ENUMERATOR), Iz.externalRange(0, Integer.MAX_VALUE)); define(_D0, GROUP_2, b, Eb, 1); define(_D1, GROUP_2, v, Ev, 1); define(_D2, GROUP_2, b, Eb, CL); define(_D3, GROUP_2, v, Ev, CL); define(_D7, "XLAT"); define(_E0, "LOOPNE", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_E1, "LOOPE", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_E2, "LOOP", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_E3, "JECXZ", Jb).requireAddressSize(WordWidth.BITS_32); define(_E3, "JRCXZ", Jb).requireAddressSize(WordWidth.BITS_64); define(_E4, "IN", AL, Ib); define(_E5, "IN", eAX, Ib); define(_E6, "OUT", Ib, AL); define(_E7, "OUT", Ib, eAX); define(LOCK, "LOCK").beNotExternallyTestable(); // prefix define(_F1, "INT", 1).beNotExternallyTestable(); // is this correct? - gas uses 0xCD define(REPNE, "REPNE").beNotExternallyTestable(); // prefix define(REPE, "REPE").beNotExternallyTestable(); // prefix define(_F4, "HLT"); define(_F5, "CMC"); define(_F6, GROUP_3b, b); define(_F7, GROUP_3v, v); } /** * Refer to "Table A-2. One-Byte Opcodes, Low Nibble 8-Fh" */ private void create_high() { define(_08, "OR", Eb, Gb); define(_09, "OR", Ev, Gv); define(_0A, "OR", Gb, Eb); define(_0B, "OR", Gv, Ev); define(_0C, "OR", AL, Ib); define(_0D, "OR", rAX, Iz.externalRange(0, Integer.MAX_VALUE)); define(_18, "SBB", Eb, Gb); define(_19, "SBB", Ev, Gv); define(_1A, "SBB", Gb, Eb); define(_1B, "SBB", Gv, Ev); define(_1C, "SBB", AL, Ib); define(_1D, "SBB", rAX, Iz.externalRange(0, Integer.MAX_VALUE)); define(_28, "SUB", Eb, Gb); define(_29, "SUB", Ev, Gv); define(_2A, "SUB", Gb, Eb); define(_2B, "SUB", Gv, Ev); define(_2C, "SUB", AL, Ib); define(_2D, "SUB", rAX, Iz.externalRange(0, Integer.MAX_VALUE)); define(SEG_CS, "SEG_CS").beNotExternallyTestable(); // prefix define(_2F, "DAS").beNotExternallyTestable(); // not defined in 64 bit mode and so 'as -64' rejects it define(_38, "CMP", Eb, Gb); define(_39, "CMP", Ev, Gv); define(_3A, "CMP", Gb, Eb); define(_3B, "CMP", Gv, Ev); define(_3C, "CMP", AL, Ib); define(_3D, "CMP", rAX, Iz.externalRange(0, Integer.MAX_VALUE)); define(_58, "POP", Nv).setDefaultOperandSize(WordWidth.BITS_64); define(_68, "PUSH", Iz.externalRange(Short.MAX_VALUE + 1, Integer.MAX_VALUE)).setDefaultOperandSize(WordWidth.BITS_64); // cannot test 16-bit version, because gas does not generate it define(_69, "IMUL", Gv, Ev, Iz.externalRange(0, Integer.MAX_VALUE)); define(_6A, "PUSH", Ib.externalRange(0, 0x7f)).setDefaultOperandSize(WordWidth.BITS_64); define(_6B, "IMUL", Gv, Ev, Ib.externalRange(0, 0x7f)); define(_6C, "INS", Yb); define(_6D, "INS", Yz); define(_6E, "OUTS", Xb); define(_6F, "OUTS", Xz); define(_78, "JS", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_79, "JNS", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_7A, "JP", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_7B, "JNP", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_7C, "JL", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_7D, "JNL", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_7E, "JLE", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_7F, "JNLE", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_88, "MOV", Eb, Gb.excludeExternalTestArguments(AL)); define(_89, "MOV", Ev, Gv.excludeExternalTestArguments(AX, EAX)); define(_8A, "MOV", Gb.excludeExternalTestArguments(AL), Eb); define(_8B, "MOV", Gv.excludeExternalTestArguments(AX, EAX), Ev); define(_8C, "MOV", Ew.excludeExternalTestArguments(AMD64GeneralRegister16.ENUMERATOR), Sw); // gas may needlessly insert OPERAND_SIZE prefix define(_8D, "LEA", Gv, M); define(_8E, "MOV", Sw, Ew.excludeExternalTestArguments(AX, CX, DX, BX, SP, BP, SI, DI)); // gas may needlessly insert OPERAND_SIZE prefix define(_8F, "POP", Ev.excludeExternalTestArguments(AX, CX, DX, BX, SP, BP, SI, DI)).setDefaultOperandSize(WordWidth.BITS_64); define(_98, "CWDE").requireOperandSize(WordWidth.BITS_32); define(_98, "CDQE").requireOperandSize(WordWidth.BITS_64); define(_99, "CDQ").requireOperandSize(WordWidth.BITS_32); define(_99, "CQO").requireOperandSize(WordWidth.BITS_64); define(FWAIT, "FWAIT"); // 'wait' is a Java keyword, so we use the alternate mnemonic, which is more accurately named anyhow define(_9C, "PUSHF", v, Fv).setDefaultOperandSize(WordWidth.BITS_64); define(_9D, "POPF", v, Fv).setDefaultOperandSize(WordWidth.BITS_64); define(_9E, "SAHF").beNotExternallyTestable(); // not available by gas, depends on CPUID define(_9F, "LAHF").beNotExternallyTestable(); // not available by gas, depends on CPUID define(_A8, "TEST", AL, Ib); define(_A9, "TEST", rAX, Iz.externalRange(0, Integer.MAX_VALUE)); define(_AA, "STOS", Yb); define(_AB, "STOS", Yv); define(_AC, "LODS", Xb); define(_AD, "LODS", Xv); define(_AE, "SCAS", Yb); define(_AF, "SCAS", Yv); define(_B8, "MOV", Nv, Iv); define(_C8, "ENTER", Iw, Ib).setDefaultOperandSize(WordWidth.BITS_64).revertExternalOperandOrdering(); define(_C9, "LEAVE").setDefaultOperandSize(WordWidth.BITS_64); define(_CA, "RETF", Iw).beNotExternallyTestable(); // gas does not support segments define(_CB, "RETF").beNotExternallyTestable(); // gas does not support segments define(_CC, "INT", 3); define(_CD, "INTb", Ib).setExternalName("int"); // suffix "b" to avoid clashing with Java keyword "int" define(_CF, "IRET"); define(_D8, FP_D8); define(_D9, FP_D9); define(_DA, FP_DA); define(_DB, FP_DB); define(_DC, FP_DC); define(_DD, FP_DD); define(_DE, FP_DE); define(_DF, FP_DF); // We found out that '_66 _E8 ...' is NOT supported by our Opteron CPUs, despite footnote 6 on page 418 of the General Purpose Instruction Manual for AMD64: define(_E8, "CALL", Jz).setDefaultOperandSize(WordWidth.BITS_64).requireOperandSize(WordWidth.BITS_64); // disabling 0x66 prefix define(_E9, "JMP", Jz).setDefaultOperandSize(WordWidth.BITS_64); define(_EB, "JMP", Jb).setDefaultOperandSize(WordWidth.BITS_64); define(_EC, "IN", AL, DX); define(_ED, "IN", eAX, DX); define(_EE, "OUT", DX, AL); define(_EF, "OUT", DX, eAX); define(_F8, "CLC"); define(_F9, "STC"); define(_FA, "CLI"); define(_FB, "STI"); define(_FC, "CLD"); define(_FD, "STD"); define(_FE, GROUP_4, b, Eb); define(_FF, GROUP_5a); define(_FF, GROUP_5b).setDefaultOperandSize(WordWidth.BITS_64); } OneByteOpcodeMap() { super(AMD64Assembly.ASSEMBLY); create_low(); create_high(); } }