fur%netscape.com 8a43aa3ae0 Initial check-in of ElectricalFire, a Java JIT compiler.
git-svn-id: svn://10.0.0.236/trunk@15719 18797224-902f-48f8-a5cc-f745e15eee43
1998-12-03 21:10:47 +00:00

231 lines
7.4 KiB
C++

/* -*- 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.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
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 <cond><x>
{ 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;
}
//--------------------------------------------------------------------------------