/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ /* desantis holmes a court (commenting) x86Opcode.cpp NOTE: This file is being phased out -- please do not add to it without speaking to simon */ #include "CatchAssert.h" #include "x86Opcode.h" #include "x86ArgumentList.h" // Not used anywhere // { 0x69, 0x00, "imul " } //iaMulImm 69 0000 0000 //================================================================================ /* Opcode Information Each OpcodeInfo consists of x86OpcodeInfo { oiBaseOpcode // generally the opcode, but can have additional info oiOpcodeInformation // additional info about opcode oiText // string for fake disassembly } Field bits are referred to as [7 6 5 4 3 2 1 0] -------------------------------------------------------------------------------- ImmediateArithType eg: 1000 00s1: 11 111 reg:immdata immediate with register 1000 00s1:mod 111 r/m:immdata immediate with memory oiBaseOpcode contains the opcode for the instruction 1 (Size) always 0 (assigned at format time) oiOpcodeInformation 7 set if two byte opcode 6 set if has an opcode extension [5 4 3] opcode extension of the instructrion 1 set if must take a 1-byte immediate 0 set if must take a 4-byte immediate others set to 0 */ x86OpcodeInfo iaInfo[] = { // ** * { 0x81, 0x40, "add " }, //iaAddImm 81/0 0100 0000 { 0x81, 0x78, "cmp " }, //iaCmpImm 81/7 0111 1000 { 0xe9, 0x40, "jmp " }, //iaJmp e9/0 0100 0000 { 0x68, 0x40, "push "}, //iaPushImm 68/0 0100 0000 { 0x81, 0x60, "and "}, //iaAndImm 81/4 0110 0000 { 0x81, 0x48, "or "}, //iaOrImm 81/1 0100 1000 { 0x81, 0x70, "xor "}, //iaXorImm 81/6 0111 0000 }; /*-------------------------------------------------------------------------------- ExtendedType eg 1100 0001: 11 111 reg:imm8data reg by immediate count 1100 0001:mod 111 r/m:imm8data memory by immediate count oiBaseOpcode contains the opcode for the instruction oiOpcodeInformation 7 set if two byte opcode [5 4 3] contain Regfield opcode extension 1 set if can take a 1-byte immediate 0 set if can take a 4-byte immediate others set to 0 */ x86OpcodeInfo eInfo[] = { // ** * { 0xf7, 0x38, "idiv eax, " }, //eIDiv f7/7 0011 1000 { 0xf7, 0x30, "div eax, " }, //eDiv f7/6 0011 0000 { 0xf7, 0x20, "div eax, " }, //eMul f7/4 0010 0000 { 0xc7, 0x01, "movImm " }, //eMoveImm c7/0 0000 0001 // used when won't be condensable { 0xff, 0x30, "push "}, //ePush ff/6 0011 0000 // FIX Peter? (what's wrong?) { 0xc1, 0x3a, "sar "}, //eSarImm c1/7 0011 1010 { 0xc1, 0x2a, "shr "}, //eShrImm c1/5 0010 1010 { 0xc1, 0x22, "shl "}, //eShlImm c1/4 0010 0010 { 0xd1, 7<<3, "sar(by1) "}, //eSar1 c1/7 0011 1000 { 0xd1, 5<<3, "shr(by1) "}, //eShr1 c1/5 0010 1000 { 0xd1, 4<<3, "shl(by1) "}, //eShl1 c1/4 0010 0000 { 0xd3, 7<<3, "sar(bycl) "}, //eSarCl c1/7 0011 1000 { 0xd3, 5<<3, "shr(bycl) "}, //eShrCl c1/5 0010 1000 { 0xd3, 4<<3, "shl(bycl) "}, //eShlCl c1/4 0010 0000 { 0xf7, 3<<3, "neg "}, //eNeg f7/3 0001 1000 }; /*-------------------------------------------------------------------------------- CondensableExtendedType Like ExtendedOpcodes but have alternate (condensed) encoding: 5-bit opcode + 3-bit reg operand eg 0100 0 rg reg (preferred encoding) 1111 1111:mod 000 r/m memory oiBaseOpcode contains the opcode for the instruction oiOpcodeInformation [7 6 5 4 3] register condensed form opcode [2 1 0] regfield extension in extended form NOTE: These opcodes cannot be two bytes and must take 4 BYTE IMMEDIATES */ x86OpcodeInfo ceInfo[] = { // norm condns { 0xff, 0x40, "inc " }, //ceInc ff/0 40+reg 0100 0000 { 0xff, 0x49, "dec " }, //ceDec ff/1 48+reg 0100 1001 { 0xc7, 0xb8, "movImm " }, //ceMoveImm c7/0 b8+reg 1011 1000 { 0xff, 0x46, "pop " } //cePop ff/0 40+reg 0101 0110 // 50+rd, ff/6 }; /*-------------------------------------------------------------------------------- SpecialRegMemType eg [cmp vrx, 0] is the same as [test vrx, vrx] but the latter saves a byte eg [mov vrx, 0] = [xor vrx, vrx] but the latter saves 4 bytes Optimisations like the above can only be applied to reg/reg oiBaseOpcode contains the opcode for the instruction oiOpcodeInformation 7 set if two byte opcode 6 0 means register (StandardType) form 1 means memory (ExtendedType) form [5 4 3] contain Regfield opcode extension for ExtendedType form 1 set if can take a 1-byte immediate 0 set if can take a 4-byte immediate Pairing register form followed by memory form */ x86OpcodeInfo srmInfo[] = { // cmp vrx, 0 = test vrx, vrx (save 1 byte) {0x85, 0x00, "test "}, //srmCmpImm0 85/r 0000 0000 (2 bytes) {0x83, 0x7a, "cmp "}, //srm1NOTUSED 83/7 0111 1010 (2+1 bytes) // mov vrx, 0 = xor vrx, vrx (save 4 bytes) {0x31, 0x00, "xor "}, //srmMoveImm0 31/r 0000 0000 (2 bytes) {0xc7, 0x41, "mov "} //srm3NOTUSED c7/0 0100 0001 (2+4 bytes) }; //================================================================================ // Member functions /*-------------------------------------------------------------------------------- x86Opcode_ImmArith -- encodes x86ImmediateArithType - Sign/size bit which specifies 8 or 32 bits operand - _possible_ three bit opcode extension (stored in the REG field of the MODR/M byte) */ void x86Opcode_ImmArith:: opFormatToMemory(void* inStart, x86ArgumentList& inAL, x86ArgListInstruction& /*inInsn*/ ) { Uint8* start = (Uint8*) inStart; if(opInfo->oiOpcodeInformation & kIs_2_Byte_Mask) *start++ = kPrefix_For_2_Byte; switch(inAL.alSizeOfImmediate()) { case(is4ByteImmediate): *start = opInfo->oiBaseOpcode; break; case(is1ByteImmediate): *start = opInfo->oiBaseOpcode | (0x02); break; default: assert(false); // FIX what other possibilities are there? break; } } //-------------------------------------------------------------------------------- //x86Opcode_Condensable_Reg -- encodes x86CondensableExtendedType void x86Opcode_Condensable_Reg:: opFormatToMemory(void* inStart, x86ArgumentList& inAL, x86ArgListInstruction& inInsn) { Uint8* start = (Uint8*) inStart; Uint8 reg = inAL.alGetRegisterOperand(inInsn); if(reg == NOT_A_REG) // Operand is not a register *start = opInfo->oiBaseOpcode; else *start = (opInfo->oiOpcodeInformation & kCondensed_Op_Mask) | reg; // 5-bit opcode + 3-bit reg } bool x86Opcode_Condensable_Reg:: opHasRegFieldExtension(x86ArgumentList& inAL, x86ArgListInstruction& inInsn) { Uint8 reg = inAL.alGetRegisterOperand( inInsn ); if(reg == NOT_A_REG) // Operand is not a register return true; return false; } //--------------------------------------------------------------------------------