///////////////////////////////////////////////////////////////////////// // $Id: decode32.cc,v 1.5 2001-10-03 13:10:37 bdenney Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. // // MandrakeSoft S.A. // 43, rue d'Aboukir // 75002 Paris - France // http://www.linux-mandrake.com/ // http://www.mandrakesoft.com/ // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #define LOG_THIS BX_CPU_THIS_PTR void BX_CPU_C::decode_exgx32(unsigned modrm) { unsigned mod, rm, ss; unsigned sib, base, index; Bit32u displ32, index_reg_val, base_reg_val; Bit8u displ8; /* NOTES: * seg_reg_mod01_base & mod10_base aren't correct??? */ /* use 32bit addressing modes. orthogonal base & index registers, scaling available, etc. */ BX_INSTR_MODRM32(modrm); mod = modrm & 0xc0; rm = modrm & 0x07; i->nnn = (modrm>>3) & 0x07; if (mod == 0xc0) { /* mod, reg, reg */ i->rm_addr = rm; BX_CPU_THIS_PTR rm_type = BX_REGISTER_REF; #if BX_WEIRDISMS i->seg_reg = NULL; #endif } else { /* mod != 3 */ BX_CPU_THIS_PTR rm_type = BX_MEMORY_REF; if (rm != 4) { /* rm != 100b, no s-i-b byte */ // one byte modrm if (mod == 0x00) { if (i->seg_reg) i->seg_reg = i->seg_reg; else i->seg_reg = & BX_CPU_THIS_PTR ds; if (rm == 5) { // no reg, 32-bit displacement i->rm_addr = fetch_next_dword(); } else { // else reg indirect, no displacement i->rm_addr = BX_READ_32BIT_REG(rm); } return; } if (mod == 0x40) { if (i->seg_reg) i->seg_reg = i->seg_reg; else i->seg_reg = BX_CPU_THIS_PTR sreg_mod01_rm32[rm]; // reg, 8-bit displacement, sign extend displ8 = fetch_next_byte(); i->rm_addr = BX_READ_32BIT_REG(rm); i->rm_addr += ((Bit8s) displ8); return; } // mod == 0x80 if (i->seg_reg) i->seg_reg = i->seg_reg; else i->seg_reg = BX_CPU_THIS_PTR sreg_mod10_rm32[rm]; // reg, 32-bit displacement displ32 = fetch_next_dword(); i->rm_addr = BX_READ_32BIT_REG(rm); i->rm_addr += displ32; return; } else { /* rm == 4, s-i-b byte follows */ sib = fetch_next_byte(); BX_INSTR_SIB32(sib); base = sib & 0x07; sib >>= 3; index = sib & 0x07; sib >>= 3; ss = sib; if (mod == 0x00) { if (i->seg_reg) i->seg_reg = i->seg_reg; else i->seg_reg = BX_CPU_THIS_PTR sreg_mod00_base32[base]; if (base != 5) /* base != 101b, no displacement */ base_reg_val = BX_READ_32BIT_REG(base); else { BX_INSTR_SIB_mod0_base5(ss); base_reg_val = fetch_next_dword(); } index_reg_val = 0; if (index != 4) { index_reg_val = BX_READ_32BIT_REG(index); index_reg_val <<= ss; } #ifdef BX_INSTR_SIB_MOD0_IND4 else { BX_INSTR_SIB_MOD0_IND4(); } #endif i->rm_addr = base_reg_val + index_reg_val; return; } if (mod == 0x40) { if (i->seg_reg) i->seg_reg = i->seg_reg; else i->seg_reg = BX_CPU_THIS_PTR sreg_mod01_base32[base]; displ8 = fetch_next_byte(); base_reg_val = BX_READ_32BIT_REG(base); index_reg_val = 0; if (index != 4) { index_reg_val = BX_READ_32BIT_REG(index); index_reg_val <<= ss; } #ifdef BX_INSTR_SIB_MOD1_IND4 else { BX_INSTR_SIB_MOD1_IND4(); } #endif i->rm_addr = base_reg_val + index_reg_val + (Bit8s) displ8; return; } // mod == 0x80 if (i->seg_reg) i->seg_reg = i->seg_reg; else i->seg_reg = BX_CPU_THIS_PTR sreg_mod10_base32[base]; displ32 = fetch_next_dword(); base_reg_val = BX_READ_32BIT_REG(base); index_reg_val = 0; if (index != 4) { index_reg_val = BX_READ_32BIT_REG(index); index_reg_val <<= ss; } #ifdef BX_INSTR_SIB_MOD2_IND4 else { BX_INSTR_SIB_MOD2_IND4(); } #endif i->rm_addr = base_reg_val + index_reg_val + displ32; return; } } /* if (mod != 3) */ }