Fixes in 64-bit decoding

This commit is contained in:
Stanislav Shwartsman 2006-08-11 17:23:36 +00:00
parent 6d50341985
commit 3ce7764fce
5 changed files with 39 additions and 58 deletions

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: cpu.h,v 1.301 2006-06-25 21:44:46 sshwarts Exp $
// $Id: cpu.h,v 1.302 2006-08-11 17:23:36 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -2569,7 +2569,6 @@ public: // for now...
BX_SMF void Resolve64Mod0Rm9(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void Resolve64Mod0Rm10(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void Resolve64Mod0Rm11(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void Resolve64Mod0Rm12(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void Resolve64Mod0Rm13(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void Resolve64Mod0Rm14(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void Resolve64Mod0Rm15(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
@ -2585,7 +2584,6 @@ public: // for now...
BX_SMF void Resolve64Mod1or2Rm9(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void Resolve64Mod1or2Rm10(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void Resolve64Mod1or2Rm11(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void Resolve64Mod1or2Rm12(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void Resolve64Mod1or2Rm13(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void Resolve64Mod1or2Rm14(bxInstruction_c *) BX_CPP_AttrRegparmN(1);
BX_SMF void Resolve64Mod1or2Rm15(bxInstruction_c *) BX_CPP_AttrRegparmN(1);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: fetchdecode64.cc,v 1.99 2006-06-26 21:07:44 sshwarts Exp $
// $Id: fetchdecode64.cc,v 1.100 2006-08-11 17:23:36 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -125,7 +125,7 @@ static BxExecutePtr_tR BxResolve64Mod0[16] = {
&BX_CPU_C::Resolve64Mod0Rm9,
&BX_CPU_C::Resolve64Mod0Rm10,
&BX_CPU_C::Resolve64Mod0Rm11,
&BX_CPU_C::Resolve64Mod0Rm12,
NULL, // escape to 2-byte
&BX_CPU_C::Resolve64Mod0Rm13,
&BX_CPU_C::Resolve64Mod0Rm14,
&BX_CPU_C::Resolve64Mod0Rm15
@ -144,7 +144,7 @@ static BxExecutePtr_tR BxResolve64Mod1or2[16] = {
&BX_CPU_C::Resolve64Mod1or2Rm9,
&BX_CPU_C::Resolve64Mod1or2Rm10,
&BX_CPU_C::Resolve64Mod1or2Rm11,
&BX_CPU_C::Resolve64Mod1or2Rm12,
NULL, // escape to 2-byte
&BX_CPU_C::Resolve64Mod1or2Rm13,
&BX_CPU_C::Resolve64Mod1or2Rm14,
&BX_CPU_C::Resolve64Mod1or2Rm15
@ -2146,7 +2146,7 @@ BX_CPU_C::fetchDecode64(Bit8u *iptr, bxInstruction_c *instruction, unsigned rema
// remain must be at least 1
unsigned b1, b2, ilen=0, attr, lock=0;
unsigned imm_mode, offset, rex_r,rex_x,rex_b;
unsigned imm_mode, offset, rex_r = 0, rex_x = 0, rex_b = 0;
unsigned rm = 0, mod = 0, nnn = 0;
#if BX_SUPPORT_SSE >= 4
unsigned b3 = 0;
@ -2158,9 +2158,6 @@ BX_CPU_C::fetchDecode64(Bit8u *iptr, bxInstruction_c *instruction, unsigned rema
unsigned sse_prefix = SSE_PREFIX_NONE;
offset = 512*1;
rex_r = 0;
rex_x = 0;
rex_b = 0;
instruction->ResolveModrm = NULL;
instruction->initMetaInfo(BX_SEG_REG_NULL,
/*os32*/ 1, // operand size 32 override defaults to 1
@ -2306,7 +2303,7 @@ fetch_b1:
mod = b2 & 0xc0;
nnn = ((b2 >> 3) & 0x07) | rex_r;
rm = b2 & 0x07;
instruction->modRMForm.modRMData = (b2<<20);
instruction->modRMForm.modRMData = (b2<<20);
instruction->modRMForm.modRMData |= mod;
instruction->modRMForm.modRMData |= (nnn<<8);
@ -2325,12 +2322,12 @@ fetch_b1:
instruction->modRMForm.modRMData |= rm;
if (instruction->as64L()) {
// 64-bit addressing modes; note that mod==11b handled above
if (rm != 4) { // no s-i-b byte
if ((rm & 0x7) != 4) { // no s-i-b byte
if (mod == 0x00) { // mod == 00b
instruction->ResolveModrm = BxResolve64Mod0[rm];
if (BX_NULL_SEG_REG(instruction->seg()))
instruction->setSeg(BX_SEG_REG_DS);
if (rm == 5) {
if ((rm & 0x7) == 5) {
if ((ilen+3) < remain) {
instruction->modRMForm.displ32u = FetchDWORD(iptr);
iptr += 4;
@ -2377,7 +2374,7 @@ get_32bit_displ_1:
else {
return(0);
}
base = (sib & 0x07) | rex_b; sib >>= 3;
base = (sib & 0x07) | rex_b; sib >>= 3;
index = (sib & 0x07) | rex_x; sib >>= 3;
scale = sib;
instruction->modRMForm.modRMData |= (base<<12);
@ -2387,7 +2384,7 @@ get_32bit_displ_1:
instruction->ResolveModrm = BxResolve64Mod0Base[base];
if (BX_NULL_SEG_REG(instruction->seg()))
instruction->setSeg(BX_CPU_THIS_PTR sreg_mod0_base32[base]);
if (base == 0x05)
if ((base & 0x7) == 5)
goto get_32bit_displ_1;
// mod==00b, rm==4, base!=5
goto modrm_done;
@ -2406,13 +2403,13 @@ get_32bit_displ_1:
}
}
else {
// 32-bit addressing modes; note that mod==11b handled above
if (rm != 4) { // no s-i-b byte
// 32-bit addressing modes; note that mod==11b handled above
if ((rm & 0x7) != 4) { // no s-i-b byte
if (mod == 0x00) { // mod == 00b
instruction->ResolveModrm = BxResolve32Mod0[rm];
if (BX_NULL_SEG_REG(instruction->seg()))
instruction->setSeg(BX_SEG_REG_DS);
if (rm == 5) {
if ((rm & 0x7) == 5) {
if ((ilen+3) < remain) {
instruction->modRMForm.displ32u = FetchDWORD(iptr);
iptr += 4;
@ -2469,7 +2466,7 @@ get_32bit_displ:
instruction->ResolveModrm = BxResolve32Mod0Base[base];
if (BX_NULL_SEG_REG(instruction->seg()))
instruction->setSeg(BX_CPU_THIS_PTR sreg_mod0_base32[base]);
if (base == 0x05)
if ((base & 0x7) == 5)
goto get_32bit_displ;
// mod==00b, rm==4, base!=5
goto modrm_done;
@ -2511,10 +2508,10 @@ modrm_done:
switch(Group) {
case BxGroupN:
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn]);
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn & 0x7]);
break;
case BxRMGroup:
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[rm]);
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[rm & 0x7]);
break;
#if BX_SUPPORT_SSE >= 4
case Bx3ByteOpTable:
@ -2540,7 +2537,7 @@ modrm_done:
break;
case BxFPGroup:
if (mod != 0xc0) // mod != 11b
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn]);
OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn & 0x7]);
else
{
int index = (b1-0xD8)*64 + (0x3f & b2);

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: proc_ctrl.cc,v 1.155 2006-06-26 21:07:44 sshwarts Exp $
// $Id: proc_ctrl.cc,v 1.156 2006-08-11 17:23:36 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -95,7 +95,8 @@ void BX_CPU_C::HLT(bxInstruction_c *i)
BX_PANIC(("HALT instruction encountered in the BIOS ROM"));
if (!real_mode() && CPL!=0) {
BX_ERROR(("HLT: priveledge check failed, generate #GP(0)"));
BX_ERROR(("HLT: %s priveledge check failed, CPL=%d, generate #GP(0)",
cpu_mode_string(BX_CPU_THIS_PTR cpu_mode), CPL));
exception(BX_GP_EXCEPTION, 0, 0);
return;
}

View File

@ -1,5 +1,5 @@
/////////////////////////////////////////////////////////////////////////
// $Id: resolve64.cc,v 1.8 2006-03-06 22:03:02 sshwarts Exp $
// $Id: resolve64.cc,v 1.9 2006-08-11 17:23:36 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2001 MandrakeSoft S.A.
@ -90,22 +90,16 @@ BX_CPU_C::Resolve64Mod0Rm11(bxInstruction_c *i)
RMAddr(i) = R11;
}
void BX_CPP_AttrRegparmN(1)
BX_CPU_C::Resolve64Mod0Rm12(bxInstruction_c *i)
{
RMAddr(i) = R12;
}
void BX_CPP_AttrRegparmN(1)
BX_CPU_C::Resolve64Mod0Rm13(bxInstruction_c *i)
{
RMAddr(i) = R13;
// eip hasn't been bumped yet when this is called. must choose the saved value.
RMAddr(i) = BX_CPU_THIS_PTR prev_eip + i->ilen() + (Bit32s)i->displ32u();
}
void BX_CPP_AttrRegparmN(1)
BX_CPU_C::Resolve64Mod0Rm14(bxInstruction_c *i)
{
RMAddr(i) = R14;
}
void BX_CPP_AttrRegparmN(1)
BX_CPU_C::Resolve64Mod0Rm15(bxInstruction_c *i)
{
@ -169,11 +163,6 @@ BX_CPU_C::Resolve64Mod1or2Rm11(bxInstruction_c *i)
RMAddr(i) = R11 + (Bit32s) i->displ32u();
}
void BX_CPP_AttrRegparmN(1)
BX_CPU_C::Resolve64Mod1or2Rm12(bxInstruction_c *i)
{
RMAddr(i) = R12 + (Bit32s) i->displ32u();
}
void BX_CPP_AttrRegparmN(1)
BX_CPU_C::Resolve64Mod1or2Rm13(bxInstruction_c *i)
{
RMAddr(i) = R13 + (Bit32s) i->displ32u();
@ -190,7 +179,6 @@ BX_CPU_C::Resolve64Mod1or2Rm15(bxInstruction_c *i)
}
void BX_CPP_AttrRegparmN(1)
BX_CPU_C::Resolve64Mod0Base0(bxInstruction_c *i)
{
@ -234,9 +222,8 @@ BX_CPU_C::Resolve64Mod0Base4(bxInstruction_c *i)
void BX_CPP_AttrRegparmN(1)
BX_CPU_C::Resolve64Mod0Base5(bxInstruction_c *i)
{
if (i->sibIndex() != 4) {
if (i->sibIndex() != 4)
RMAddr(i) = (BX_READ_64BIT_REG(i->sibIndex()) << i->sibScale()) + (Bit32s) i->displ32u();
}
else
RMAddr(i) = (Bit32s) i->displ32u();
}

View File

@ -1,8 +1,9 @@
/////////////////////////////////////////////////////////////////////////
// $Id: resolve.cc,v 1.12 2006-06-26 21:06:26 sshwarts Exp $
// $Id: resolve.cc,v 1.13 2006-08-11 17:22:43 sshwarts Exp $
/////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <assert.h>
#include "disasm.h"
void disassembler::decode_modrm(x86_insn *insn)
@ -27,7 +28,7 @@ void disassembler::decode_modrm(x86_insn *insn)
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve64_mod0;
if (insn->rm == 5) /* no reg, 32-bit displacement */
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
insn->displacement.displ32 = fetch_dword();
break;
case 1:
@ -45,11 +46,13 @@ void disassembler::decode_modrm(x86_insn *insn)
else { /* rm == 4, s-i-b byte follows */
insn->sib = fetch_byte();
BX_DECODE_SIB(insn->sib, insn->scale, insn->index, insn->base);
insn->base |= insn->rex_b;
insn->index |= insn->rex_x;
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve64_mod0_rm4;
if (insn->base == 5)
if ((insn->base & 7) == 5)
insn->displacement.displ32 = fetch_dword();
break;
case 1:
@ -73,7 +76,7 @@ void disassembler::decode_modrm(x86_insn *insn)
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve32_mod0;
if (insn->rm == 5) /* no reg, 32-bit displacement */
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
insn->displacement.displ32 = fetch_dword();
break;
case 1:
@ -97,7 +100,7 @@ void disassembler::decode_modrm(x86_insn *insn)
switch (insn->mod) {
case 0:
resolve_modrm = &disassembler::resolve32_mod0_rm4;
if (insn->base == 5)
if ((insn->base & 7) == 5)
insn->displacement.displ32 = fetch_dword();
break;
case 1:
@ -112,6 +115,9 @@ void disassembler::decode_modrm(x86_insn *insn)
} /* s-i-b byte follows */
}
else {
assert(insn->rex_b == 0);
assert(insn->rex_x == 0);
assert(insn->rex_r == 0);
/* 16 bit addressing modes. */
switch (insn->mod) {
case 0:
@ -169,7 +175,7 @@ void disassembler::resolve32_mod0(const x86_insn *insn, unsigned mode)
else
seg = segment_name[DS_REG];
if (insn->rm == 5) /* no reg, 32-bit displacement */
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
print_memory_access(mode, seg, NULL, NULL, 0, insn->displacement.displ32);
else
print_memory_access(mode, seg, general_32bit_regname[insn->rm], NULL, 0, 0);
@ -198,15 +204,13 @@ void disassembler::resolve32_mod0_rm4(const x86_insn *insn, unsigned mode)
else
seg = sreg_mod00_base32[insn->base];
if (insn->base != 5)
if ((insn->base & 7) != 5)
base = general_32bit_regname[insn->base];
else
disp32 = insn->displacement.displ32;
if (insn->index != 4)
{
index = general_32bit_regname[insn->index];
}
print_memory_access(mode, seg, base, index, insn->scale, disp32);
}
@ -221,9 +225,7 @@ void disassembler::resolve32_mod1or2_rm4(const x86_insn *insn, unsigned mode)
seg = sreg_mod01or10_base32[insn->base];
if (insn->index != 4)
{
index = general_32bit_regname[insn->index];
}
print_memory_access(mode, seg,
general_32bit_regname[insn->base], index, insn->scale, insn->displacement.displ32);
@ -241,7 +243,7 @@ void disassembler::resolve64_mod0(const x86_insn *insn, unsigned mode)
if (intel_mode) rip_regname = "rip";
else rip_regname = "%rip";
if (insn->rm == 5) /* no reg, 32-bit displacement */
if ((insn->rm & 7) == 5) /* no reg, 32-bit displacement */
print_memory_access(mode, seg, rip_regname, NULL, 0, insn->displacement.displ32);
else
print_memory_access(mode, seg, general_64bit_regname[insn->rm], NULL, 0, 0);
@ -270,15 +272,13 @@ void disassembler::resolve64_mod0_rm4(const x86_insn *insn, unsigned mode)
else
seg = sreg_mod00_base32[insn->base];
if (insn->base != 5)
if ((insn->base & 7) != 5)
base = general_64bit_regname[insn->base];
else
disp32 = insn->displacement.displ32;
if (insn->index != 4)
{
index = general_64bit_regname[insn->index];
}
print_memory_access(mode, seg, base, index, insn->scale, disp32);
}
@ -293,9 +293,7 @@ void disassembler::resolve64_mod1or2_rm4(const x86_insn *insn, unsigned mode)
seg = sreg_mod01or10_base32[insn->base];
if (insn->index != 4)
{
index = general_64bit_regname[insn->index];
}
print_memory_access(mode, seg,
general_64bit_regname[insn->base], index, insn->scale, insn->displacement.displ32);