/* -*- 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): */ /* x86Opcode.h desantis simon NOTE: This file is being phased out -- please do not add to it without speaking to simon */ #ifndef _X86OPCODE #define _X86OPCODE #include "CatchAssert.h" #include #include "Fundamentals.h" #include "LogModule.h" class x86ArgumentList; class x86ArgListInstruction; //================================================================================ // enums enum x86NoArgsCode { opCdq, opBreak, opSahf }; enum x86DoubleOpCode { opMul, opMovSxB, opMovSxH, opMovZxB, opMovZxH }; enum x86DoubleOpDirCode { raAdd, raAdc, raSub, raSbb, raAnd, raOr, raXor, raCmp, raLoadI, raCopyI, raStoreI, raSaveReg, raStoreB, raStoreH }; // Floating-point instructions in which one operand is a memory location. // If there is a second operand, then it is implicitly the top of the FPU stack. enum x86FloatMemoryType { fstp32, // TOS => 32-bit float memory. Pop FPU. fstp64, // TOS => 64-bit double memory. Pop FPU. fst32, // TOS => 32-bit float memory. (Don't pop FPU stack.) fst64, // TOS => 64-bit double memory. (Don't pop FPU stack.) fistp32, // Round(TOS) => 32-bit int memory. Pop FPU. fistp64, // Round(TOS) => 64-bit long memory. Pop FPU. fld32, // 32-bit float memory => Push on FPU stack fld64, // 64-bit float memory => Push on FPU stack fild32, // 32-bit int memory => convert to FP and push on FPU stack fild64, // 64-bit long memory => convert to FP and push on FPU stack fadd32, // Add TOS and 32-bit float memory => replace TOS fadd64, // Add TOS and 64-bit double memory => replace TOS fmul32, // Multiply TOS and 32-bit float memory => replace TOS fmul64, // Multiply TOS and 64-bit double memory => replace TOS fsub32, // Subtract TOS from 32-bit float memory => replace TOS fsub64, // Subtract TOS from 64-bit double memory => replace TOS fsubr32, // Subtract 32-bit float memory from TOS => replace TOS fsubr64, // Subtract 64-bit double memory from TOS => replace TOS fdiv32, // Divide TOS by 32-bit float memory => replace TOS fdiv64, // Divide TOS by 64-bit double memory => replace TOS fcomp32, // Compare TOS to 32-bit float memory, setting FPU flags, pop TOS fcomp64 // Compare TOS to 64-bit double memory, setting FPU flags, pop TOS }; // enums for the x96 conidtion code enum x86ConditionCode { ccJO = 0x00, ccJNO = 0x01, ccJB = 0x02, ccJNB = 0x03, ccJE = 0x04, ccJNE = 0x05, ccJBE = 0x06, ccJNBE = 0x07, ccJS = 0x08, ccJNS = 0x09, ccJP = 0x0a, ccJNP = 0x0b, ccJL = 0x0c, ccJNL = 0x0d, ccJLE = 0x0e, ccJNLE = 0x0f }; /*================================================================================ x86 Opcodes - Can be one byte or two bytes in length. If two bytes, the first byte is 0x0f. - Can have bits to control: - data flow direction(D), - sign extension(S) // FIX pete, isn't this 'size' not 'sign'? - conditions (cond), and - register field - opcode extensions (Reg). - Can have an alternate (condensed) encoding which allows a single register operand to be encoded in the opcode. */ enum x86GPR { EAX = 0, ECX = 1, EDX = 2, EBX = 3, ESP = 4, EBP = 5, ESI = 6, EDI = 7, NOT_A_REG = 255 }; // bit masks const int kRegfield_Mask = 0x38; // 0b00111000 const int kIs_Memory_Form_Mask = 0x40; // 0b01000000 const int kCondition_Code_Mask = 0x0f; // 0b00001111 const int kCondensed_Op_Mask = 0xf8; // 0b11111000 const int kIs_2_Byte_Mask = 0x80; // 0b10000000 const int kIs_16_Bit_Mask = 0x40; // 0b01000000 const int kExtension_Mask = 0x40; // 0b01000000 const int kPrefix_For_16_Bits = 0x66; const int kPrefix_For_2_Byte = 0x0f; // 0b00001111 /*-------------------------------------------------------------------------------- Opcode Information */ struct x86OpcodeInfo { uint8 oiBaseOpcode; // generally the opcode, but can have additional info uint8 oiOpcodeInformation; // additional info about opcode char* oiText; // string for fake disassembly }; extern x86OpcodeInfo iaInfo[]; enum x86ImmediateArithType { iaAddImm, iaCmpImm, iaJmp, iaPushImm, iaAndImm, iaOrImm, iaXorImm }; extern x86OpcodeInfo eInfo[]; enum x86ExtendedType { eIDiv, eDiv, eMul, eMoveImm, ePush, eSarImm, eShrImm, eShlImm, eSar1, eShr1, eShl1, eSarCl, eShrCl, eShlCl, eNeg }; extern x86OpcodeInfo ceInfo[]; enum x86CondensableExtendedType { ceInc, ceDec, ceMoveImm, cePop }; extern x86OpcodeInfo srmInfo[]; enum x86SpecialRegMemType { srmCmpImm0, srm1NOTUSED, srmMoveImm0, srm3NOTUSED }; //================================================================================ // Class Declarations /*-------------------------------------------------------------------------------- x86Opcode -- encodes x86StandardType Basic opcode - 8 or 16 bits - no toggable bits and - does NOT have a register field opcode extension or alternate encoding. */ class x86Opcode { public: virtual void opPrintPretty(LogModuleObject &f) { UT_OBJECTLOG(f, PR_LOG_ALWAYS, ("%-9s", opInfo->oiText)); } virtual uint8 opSize() { return( (opInfo->oiOpcodeInformation >> 7) + 1); } virtual void opFormatToMemory(void* inStart, x86ArgumentList& /*inAL*/, x86ArgListInstruction& /*inInsn*/); virtual bool opHasRegFieldExtension( x86ArgumentList& /*inAL*/, x86ArgListInstruction& /*inInsn*/ ) { return (false); } virtual uint8 opGetRegFieldExtension() { assert(false); return 0; } virtual bool opRegOperandCanBeCondensed() { return false; } virtual void opReverseOperands() { assert(false); } virtual void opSwitchToRegisterIndirect() { } virtual bool opCanAccept1ByteImmediate() { assert(false); return false; } virtual bool opCanAccept4ByteImmediate() { assert(false); return false; } protected: x86Opcode() {} x86Opcode( x86ImmediateArithType inType ) { opInfo = &(iaInfo[inType]); } x86Opcode( x86ExtendedType inType ) { opInfo = &(eInfo[inType]); } x86Opcode( x86CondensableExtendedType inType ) { opInfo = &(ceInfo[inType]); } x86Opcode( x86SpecialRegMemType inType ) { opInfo = &(srmInfo[inType]); } x86OpcodeInfo* opInfo; }; inline void x86Opcode:: opFormatToMemory(void* inStart, x86ArgumentList& /*inAL*/, x86ArgListInstruction& /*inInsn*/) { uint8* start = (uint8*) inStart; if(opInfo->oiOpcodeInformation & kIs_2_Byte_Mask) *start++ = kPrefix_For_2_Byte; *start = opInfo->oiBaseOpcode; } /*-------------------------------------------------------------------------------- x86Opcode_Reg -- encodes x86EntendedType - no switchable bits - three bit opcode extension (stored in the REG field of the MODR/M byte) */ class x86Opcode_Reg : public virtual x86Opcode { public: x86Opcode_Reg ( x86ExtendedType inInfo ) : x86Opcode(inInfo) { } virtual bool opHasRegFieldExtension( x86ArgumentList& /*inAL*/, x86ArgListInstruction& /*inInsn*/ ) { return true; } virtual uint8 opGetRegFieldExtension() { return (kRegfield_Mask & opInfo->oiOpcodeInformation); } virtual bool opCanAccept1ByteImmediate() { return ((0x02 & opInfo->oiOpcodeInformation) == 0x02); } virtual bool opCanAccept4ByteImmediate() { return ((0x01 & opInfo->oiOpcodeInformation) == 0x01); } protected: x86Opcode_Reg() { } }; /*-------------------------------------------------------------------------------- x86Opcode_Condensable_Reg -- encodes x86CondensableExtendedType - no switchable bits - three bit opcode extension (stored in the REG field of the MODR/M byte) - alternate encoding which has a 5-bit opcode + 3-bit register operand */ class x86Opcode_Condensable_Reg : public x86Opcode { public: x86Opcode_Condensable_Reg ( x86CondensableExtendedType inInfo ) : x86Opcode(inInfo) { } virtual bool opHasRegFieldExtension( x86ArgumentList& inAL, x86ArgListInstruction& inInsn ); virtual uint8 opGetRegFieldExtension() { return ((0x03 & opInfo->oiOpcodeInformation) << 3); } virtual bool opCanAccept1ByteImmediate() { return false; } virtual bool opCanAccept4ByteImmediate() { return true; } virtual bool opRegOperandCanBeCondensed(){ return true; } virtual uint8 opSize() { return 1; } virtual void opFormatToMemory(void* inStart, x86ArgumentList& inAL, x86ArgListInstruction& inInsn); }; /*-------------------------------------------------------------------------------- x86Opcode_ImmArith -- encodes x86ImmediateArithType - must have 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) */ class x86Opcode_ImmArith : public x86Opcode { public: x86Opcode_ImmArith( x86ImmediateArithType inInfo ) : x86Opcode( inInfo ) { } virtual void opFormatToMemory( void* inStart, x86ArgumentList& /*inAL*/, x86ArgListInstruction& /*inInsn*/); virtual bool opHasRegFieldExtension( x86ArgumentList& /*inAL*/, x86ArgListInstruction& /*inInsn*/ ) { return (bool)((opInfo->oiOpcodeInformation >> 6) && 1); } virtual uint8 opGetRegFieldExtension() { assert(kExtension_Mask & opInfo->oiOpcodeInformation); return (kRegfield_Mask & opInfo->oiOpcodeInformation); } virtual bool opCanAccept1ByteImmediate() { return true; } virtual bool opCanAccept4ByteImmediate() { return true; } virtual void opSwitchToRegisterIndirect() { } // FIX can't do this for imul ??? protected: x86Opcode_ImmArith() { } }; /*-------------------------------------------------------------------------------- x86Opcode_SpecialRegMem -- x86SpecialRegMemType - switches between x86Opcode_Reg when operand is a memory argument, and x86Opcode when operand is a register argument */ class x86Opcode_SpecialRegMem : public x86Opcode_Reg // note not x86Opcode! { public: x86Opcode_SpecialRegMem( x86SpecialRegMemType inType) : x86Opcode(inType) { } virtual bool opHasRegFieldExtension( x86ArgumentList& /*inAL*/, x86ArgListInstruction& /*inInsn*/ ) { return((kIs_Memory_Form_Mask & opInfo->oiOpcodeInformation) == kIs_Memory_Form_Mask); } virtual uint8 opGetRegFieldExtension() { assert(kIs_Memory_Form_Mask & opInfo->oiOpcodeInformation); return (kRegfield_Mask & opInfo->oiOpcodeInformation); } virtual void opSwitchToRegisterIndirect() { assert(!(kIs_Memory_Form_Mask & opInfo->oiOpcodeInformation)); opInfo++; } }; #endif // _X86OPCODE