diff --git a/bochs/cpu/decoder/fetchdecode.cc b/bochs/cpu/decoder/fetchdecode.cc index 64f5fba71..06d494e7f 100644 --- a/bochs/cpu/decoder/fetchdecode.cc +++ b/bochs/cpu/decoder/fetchdecode.cc @@ -1273,6 +1273,151 @@ static const BxOpcodeInfo_t BxOpcodeInfo32[512*2] = { /* 0F FF /d */ { 0, BX_IA_ERROR } }; +const Bit8u *decodeModrm32(const Bit8u *iptr, unsigned &remain, bxInstruction_c *i, unsigned mod, unsigned nnn, unsigned rm) +{ + unsigned seg = BX_SEG_REG_DS; + + i->setSibBase(rm); // initialize with rm to use BxResolve32Base + i->setSibIndex(4); // no Index encoding by default + // initialize displ32 with zero to include cases with no diplacement + i->modRMForm.displ32u = 0; + + // note that mod==11b handled outside + + if (i->as32L()) { + if (rm != 4) { // no s-i-b byte + if (mod == 0x00) { // mod == 00b + if (rm == 5) { + i->setSibBase(BX_NIL_REGISTER); + if (remain > 3) { + i->modRMForm.displ32u = FetchDWORD(iptr); + iptr += 4; + remain -= 4; + } + else return NULL; + } + // mod==00b, rm!=4, rm!=5 + goto modrm_done; + } + seg = sreg_mod1or2_base32[rm]; + } + else { // mod!=11b, rm==4, s-i-b byte follows + unsigned sib, base, index, scale; + if (remain != 0) { + sib = *iptr++; + remain--; + } + else { + return NULL; + } + base = sib & 0x7; sib >>= 3; + index = sib & 0x7; sib >>= 3; + scale = sib; + + i->setSibScale(scale); + i->setSibBase(base); + // this part is a little tricky - assign index value always, + // it will be really used if the instruction is Gather. Others + // assume that resolve function will do the right thing. + i->setSibIndex(index); + + if (mod == 0x00) { // mod==00b, rm==4 + seg = sreg_mod0_base32[base]; + if (base == 5) { + i->setSibBase(BX_NIL_REGISTER); + if (remain > 3) { + i->modRMForm.displ32u = FetchDWORD(iptr); + iptr += 4; + remain -= 4; + } + else { + return NULL; + } + } + // mod==00b, rm==4, base!=5 + goto modrm_done; + } + else { + seg = sreg_mod1or2_base32[base]; + } + } + + if (mod == 0x40) { // mod==01b + if (remain != 0) { + // 8 sign extended to 32 + i->modRMForm.displ32u = (Bit8s) *iptr++; + remain--; + } + else { + return NULL; + } + } + else { + // (mod == 0x80), mod==10b + if (remain > 3) { + i->modRMForm.displ32u = FetchDWORD(iptr); + iptr += 4; + remain -= 4; + } + else { + return NULL; + } + } + } + else { + // 16-bit addressing modes, mod==11b handled above + i->setSibBase(Resolve16BaseReg[rm]); + i->setSibIndex(Resolve16IndexReg[rm]); + i->setSibScale(0); + + if (mod == 0x00) { // mod == 00b + seg = sreg_mod00_rm16[rm]; + if (rm == 6) { + i->setSibBase(BX_NIL_REGISTER); + if (remain > 1) { + i->modRMForm.displ32u = (Bit32s) (Bit16s) FetchWORD(iptr); + iptr += 2; + remain -= 2; + } + else { + return NULL; + } + } + goto modrm_done; + } + else { + seg = sreg_mod01or10_rm16[rm]; + } + + if (mod == 0x40) { // mod == 01b + if (remain != 0) { + // 8 sign extended to 16 + i->modRMForm.displ32u = (Bit32s) (Bit8s) *iptr++; + remain--; + } + else { + return NULL; + } + } + else { + // (mod == 0x80) mod == 10b + if (remain > 1) { + i->modRMForm.displ32u = (Bit32s) (Bit16s) FetchWORD(iptr); + iptr += 2; + remain -= 2; + } + else { + return NULL; + } + } + } + +modrm_done: + + i->setSeg(seg); + return iptr; +} + int fetchDecode32(const Bit8u *iptr, Bit32u fetchModeMask, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage) { if (remainingInPage > 15) remainingInPage = 15; @@ -1550,142 +1695,19 @@ fetch_b1: if (mod == 0xc0) { // mod == 11b i->assertModC0(); - goto modrm_done; - } - - mod_mem = 1; - i->setSibBase(rm); // initialize with rm to use BxResolve32Base - i->setSibIndex(4); // no Index encoding - // initialize displ32 with zero to include cases with no diplacement - i->modRMForm.displ32u = 0; - - if (i->as32L()) { - // 32-bit addressing modes; note that mod==11b handled above - if (rm != 4) { // no s-i-b byte - if (mod == 0x00) { // mod == 00b - if (rm == 5) { - i->setSibBase(BX_NIL_REGISTER); - if (remain > 3) { - i->modRMForm.displ32u = FetchDWORD(iptr); - iptr += 4; - remain -= 4; - } - else return(-1); - } - // mod==00b, rm!=4, rm!=5 - goto modrm_done; - } - seg = sreg_mod1or2_base32[rm]; - } - else { // mod!=11b, rm==4, s-i-b byte follows - unsigned sib, base, index, scale; - if (remain != 0) { - sib = *iptr++; - remain--; - } - else { - return(-1); - } - base = sib & 0x7; sib >>= 3; - index = sib & 0x7; sib >>= 3; - scale = sib; - i->setSibScale(scale); - i->setSibBase(base); - // this part is a little tricky - assign index value always, - // it will be really used if the instruction is Gather. Others - // assume that resolve function will do the right thing. - i->setSibIndex(index); - if (mod == 0x00) { // mod==00b, rm==4 - seg = sreg_mod0_base32[base]; - if (base == 5) { - i->setSibBase(BX_NIL_REGISTER); - if (remain > 3) { - i->modRMForm.displ32u = FetchDWORD(iptr); - iptr += 4; - remain -= 4; - } - else { - return(-1); - } - } - // mod==00b, rm==4, base!=5 - goto modrm_done; - } - seg = sreg_mod1or2_base32[base]; - } - - if (mod == 0x40) { // mod==01b - if (remain != 0) { - // 8 sign extended to 32 - i->modRMForm.displ32u = (Bit8s) *iptr++; -#if BX_SUPPORT_EVEX - displ8 = 1; -#endif - remain--; - goto modrm_done; - } - else { - return(-1); - } - } - - // (mod == 0x80), mod==10b - if (remain > 3) { - i->modRMForm.displ32u = FetchDWORD(iptr); - iptr += 4; - remain -= 4; - } - else { - return(-1); - } } else { - // 16-bit addressing modes, mod==11b handled above - i->setSibBase(Resolve16BaseReg[rm]); - i->setSibIndex(Resolve16IndexReg[rm]); - i->setSibScale(0); - if (mod == 0x00) { // mod == 00b - seg = sreg_mod00_rm16[rm]; - if (rm == 6) { - i->setSibBase(BX_NIL_REGISTER); - if (remain > 1) { - i->modRMForm.displ32u = (Bit32s) (Bit16s) FetchWORD(iptr); - iptr += 2; - remain -= 2; - goto modrm_done; - } - else return(-1); - } - goto modrm_done; - } - seg = sreg_mod01or10_rm16[rm]; - if (mod == 0x40) { // mod == 01b - if (remain != 0) { - // 8 sign extended to 16 - i->modRMForm.displ32u = (Bit32s) (Bit8s) *iptr++; -#if BX_SUPPORT_EVEX - displ8 = 1; -#endif - remain--; - goto modrm_done; - } - else { - return(-1); - } - } - // (mod == 0x80) mod == 10b - if (remain > 1) { - i->modRMForm.displ32u = (Bit32s) (Bit16s) FetchWORD(iptr); - iptr += 2; - remain -= 2; - } - else { + mod_mem = 1; + iptr = decodeModrm32(iptr, remain, i, mod, nnn, rm); + if (! iptr) return(-1); +#if BX_SUPPORT_EVEX + if (mod == 0x40) { // mod==01b + displ8 = 1; } +#endif } -modrm_done: - #if BX_SUPPORT_EVEX // EVEX.b in reg form implies 512-bit vector length if (i->modC0() && i->getEvexb()) { @@ -1710,6 +1732,7 @@ modrm_done: rm = b1 & 0x7; nnn = (b1 >> 3) & 0x7; i->assertModC0(); + i->setSeg(seg); } if (lock) { // lock prefix invalid opcode @@ -1933,8 +1956,7 @@ modrm_done: // assign memory segment override if (! BX_NULL_SEG_REG(seg_override)) - seg = seg_override; - i->setSeg(seg); + i->setSeg(seg_override); #if BX_SUPPORT_AVX if (had_vex_xop) { diff --git a/bochs/cpu/decoder/fetchdecode64.cc b/bochs/cpu/decoder/fetchdecode64.cc index a69502298..bcfe3e076 100644 --- a/bochs/cpu/decoder/fetchdecode64.cc +++ b/bochs/cpu/decoder/fetchdecode64.cc @@ -1690,6 +1690,92 @@ static const BxOpcodeInfo_t BxOpcodeInfo64[512*3] = { /* 0F FF /q */ { 0, BX_IA_ERROR } }; +const Bit8u *decodeModrm64(const Bit8u *iptr, unsigned &remain, bxInstruction_c *i, unsigned mod, unsigned nnn, unsigned rm, unsigned rex_r, unsigned rex_x, unsigned rex_b) +{ + unsigned seg = BX_SEG_REG_DS; + + i->setSibBase(rm & 0xf); // initialize with rm to use BxResolve64Base + i->setSibIndex(4); + // initialize displ32 with zero to include cases with no diplacement + i->modRMForm.displ32u = 0; + + // note that mod==11b handled outside + + if ((rm & 0x7) != 4) { // no s-i-b byte + if (mod == 0x00) { // mod == 00b + if ((rm & 0x7) == 5) { + i->setSibBase(BX_64BIT_REG_RIP); + goto get_32bit_displ; + } + // mod==00b, rm!=4, rm!=5 + goto modrm_done; + } + // (mod == 0x40), mod==01b or (mod == 0x80), mod==10b + seg = sreg_mod1or2_base32[rm & 0xf]; + } + else { // mod!=11b, rm==4, s-i-b byte follows + unsigned sib, base, index, scale; + if (remain != 0) { + sib = *iptr++; + remain--; + } + else { + return NULL; + } + base = (sib & 0x7) | rex_b; sib >>= 3; + index = (sib & 0x7) | rex_x; sib >>= 3; + scale = sib; + i->setSibScale(scale); + i->setSibBase(base & 0xf); + // this part is a little tricky - assign index value always, + // it will be really used if the instruction is Gather. Others + // assume that resolve function will do the right thing. + i->setSibIndex(index & 0xf); + if (mod == 0x00) { // mod==00b, rm==4 + seg = sreg_mod0_base32[base & 0xf]; + if ((base & 0x7) == 5) { + i->setSibBase(BX_NIL_REGISTER); + goto get_32bit_displ; + } + // mod==00b, rm==4, base!=5 + goto modrm_done; + } + // (mod == 0x40), mod==01b or (mod == 0x80), mod==10b + seg = sreg_mod1or2_base32[base & 0xf]; + } + + // (mod == 0x40), mod==01b + if (mod == 0x40) { + if (remain != 0) { + // 8 sign extended to 32 + i->modRMForm.displ32u = (Bit8s) *iptr++; + remain--; + } + else { + return NULL; + } + } + else { + +get_32bit_displ: + + // (mod == 0x80), mod==10b + if (remain > 3) { + i->modRMForm.displ32u = FetchDWORD(iptr); + iptr += 4; + remain -= 4; + } + else { + return NULL; + } + } + +modrm_done: + + i->setSeg(seg); + return iptr; +} + int fetchDecode64(const Bit8u *iptr, Bit32u fetchModeMask, bx_bool handle_lock_cr0, bxInstruction_c *i, unsigned remainingInPage) { if (remainingInPage > 15) remainingInPage = 15; @@ -2041,91 +2127,19 @@ fetch_b1: if (mod == 0xc0) { // mod == 11b i->assertModC0(); - goto modrm_done; - } - - mod_mem = 1; - i->setSibBase(rm & 0xf); // initialize with rm to use BxResolve64Base - i->setSibIndex(4); - // initialize displ32 with zero to include cases with no diplacement - i->modRMForm.displ32u = 0; - - // note that mod==11b handled above - - if ((rm & 0x7) != 4) { // no s-i-b byte - if (mod == 0x00) { // mod == 00b - if ((rm & 0x7) == 5) { - i->setSibBase(BX_64BIT_REG_RIP); - goto get_32bit_displ; - } - // mod==00b, rm!=4, rm!=5 - goto modrm_done; - } - // (mod == 0x40), mod==01b or (mod == 0x80), mod==10b - seg = sreg_mod1or2_base32[rm & 0xf]; - } - else { // mod!=11b, rm==4, s-i-b byte follows - unsigned sib, base, index, scale; - if (remain != 0) { - sib = *iptr++; - remain--; - } - else { - return(-1); - } - base = (sib & 0x7) | rex_b; sib >>= 3; - index = (sib & 0x7) | rex_x; sib >>= 3; - scale = sib; - i->setSibScale(scale); - i->setSibBase(base & 0xf); - // this part is a little tricky - assign index value always, - // it will be really used if the instruction is Gather. Others - // assume that resolve function will do the right thing. - i->setSibIndex(index & 0xf); - if (mod == 0x00) { // mod==00b, rm==4 - seg = sreg_mod0_base32[base & 0xf]; - if ((base & 0x7) == 5) { - i->setSibBase(BX_NIL_REGISTER); - goto get_32bit_displ; - } - // mod==00b, rm==4, base!=5 - goto modrm_done; - } - // (mod == 0x40), mod==01b or (mod == 0x80), mod==10b - seg = sreg_mod1or2_base32[base & 0xf]; - } - - // (mod == 0x40), mod==01b - if (mod == 0x40) { - if (remain != 0) { - // 8 sign extended to 32 - i->modRMForm.displ32u = (Bit8s) *iptr++; -#if BX_SUPPORT_EVEX - displ8 = 1; -#endif - remain--; - } - else { - return(-1); - } } else { - -get_32bit_displ: - - // (mod == 0x80), mod==10b - if (remain > 3) { - i->modRMForm.displ32u = FetchDWORD(iptr); - iptr += 4; - remain -= 4; - } - else { + mod_mem = 1; + iptr = decodeModrm64(iptr, remain, i, mod, nnn, rm, rex_r, rex_x, rex_b); + if (! iptr) return(-1); +#if BX_SUPPORT_EVEX + if (mod == 0x40) { // mod==01b + displ8 = 1; } +#endif } -modrm_done: - #if BX_SUPPORT_EVEX // EVEX.b in reg form implies 512-bit vector length if (i->modC0() && i->getEvexb()) {