diff --git a/src/arch/x86/isa/decoder/one_byte_opcodes.isa b/src/arch/x86/isa/decoder/one_byte_opcodes.isa index d129f20ef1..c47a9a3627 100644 --- a/src/arch/x86/isa/decoder/one_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/one_byte_opcodes.isa @@ -362,10 +362,12 @@ 0x3: RET_NEAR(); 0x4: decode MODE_SUBMODE { 0x0: UD2(); + 0x4: LES_REAL(Gz,Mz); default: WarnUnimpl::les_Gz_Mp(); } 0x5: decode MODE_SUBMODE { 0x0: UD2(); + 0x4: LDS_REAL(Gz,Mz); default: WarnUnimpl::lds_Gz_Mp(); } //0x6: group12_Eb_Ib(); diff --git a/src/arch/x86/isa/decoder/two_byte_opcodes.isa b/src/arch/x86/isa/decoder/two_byte_opcodes.isa index 8913ce7c7a..1a37c0ab6c 100644 --- a/src/arch/x86/isa/decoder/two_byte_opcodes.isa +++ b/src/arch/x86/isa/decoder/two_byte_opcodes.isa @@ -744,10 +744,19 @@ 0x16: decode OPCODE_OP_BOTTOM3 { 0x0: CMPXCHG(Eb,Gb); 0x1: CMPXCHG(Ev,Gv); - 0x2: WarnUnimpl::lss_Gz_Mp(); + 0x2: decode MODE_SUBMODE { + 0x4: LSS_REAL(Gz,Mz); + default: WarnUnimpl::lss_Gz_Mp(); + } 0x3: BTR(Ev,Gv); - 0x4: WarnUnimpl::lfs_Gz_Mp(); - 0x5: WarnUnimpl::lgs_Gz_Mp(); + 0x4: decode MODE_SUBMODE { + 0x4: LFS_REAL(Gz,Mz); + default: WarnUnimpl::lfs_Gz_Mp(); + } + 0x5: decode MODE_SUBMODE { + 0x4: LGS_REAL(Gz,Mz); + default: WarnUnimpl::lgs_Gz_Mp(); + } //The size of the second operand in these instructions //should really be "b" or "w", but it's set to v in order //to have a consistent register size. This shouldn't diff --git a/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py b/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py index e10c31f305..1967820114 100644 --- a/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py +++ b/src/arch/x86/isa/insts/general_purpose/load_segment_registers.py @@ -33,7 +33,121 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -microcode = "" +microcode = ''' + +# +# Real mode versions of the load far pointer instructions. +# + +def macroop LDS_REAL_R_M { + # Calculate the address of the pointer. + lea t1, seg, sib, disp, dataSize=asz + + # Load the selector into a temporary. + ld t2, seg, [1, t0, t1], dsz, dataSize=2 + # Load the offset. + ld reg, seg, [1, t0, t1], 0 + # Install the selector value. + wrsel ds, t2 + # Make sure there isn't any junk in the upper bits of the base. + mov t2, t0, t2 + # Compute and set the base. + slli t2, t2, 4, dataSize=8 + wrbase ds, t2, dataSize=8 +}; + +def macroop LES_REAL_R_M { + # Calculate the address of the pointer. + lea t1, seg, sib, disp, dataSize=asz + + # Load the selector into a temporary. + ld t2, seg, [1, t0, t1], dsz, dataSize=2 + # Load the offset. + ld reg, seg, [1, t0, t1], 0 + # Install the selector value. + wrsel es, t2 + # Make sure there isn't any junk in the upper bits of the base. + mov t2, t0, t2 + # Compute and set the base. + slli t2, t2, 4, dataSize=8 + wrbase es, t2, dataSize=8 +}; + +def macroop LFS_REAL_R_M { + # Calculate the address of the pointer. + lea t1, seg, sib, disp, dataSize=asz + + # Load the selector into a temporary. + ld t2, seg, [1, t0, t1], dsz, dataSize=2 + # Load the offset. + ld reg, seg, [1, t0, t1], 0 + # Install the selector value. + wrsel fs, t2 + # Make sure there isn't any junk in the upper bits of the base. + mov t2, t0, t2 + # Compute and set the base. + slli t2, t2, 4, dataSize=8 + wrbase fs, t2, dataSize=8 +}; + +def macroop LGS_REAL_R_M { + # Calculate the address of the pointer. + lea t1, seg, sib, disp, dataSize=asz + + # Load the selector into a temporary. + ld t2, seg, [1, t0, t1], dsz, dataSize=2 + # Load the offset. + ld reg, seg, [1, t0, t1], 0 + # Install the selector value. + wrsel gs, t2 + # Make sure there isn't any junk in the upper bits of the base. + mov t2, t0, t2 + # Compute and set the base. + slli t2, t2, 4, dataSize=8 + wrbase gs, t2, dataSize=8 +}; + +def macroop LSS_REAL_R_M { + # Calculate the address of the pointer. + lea t1, seg, sib, disp, dataSize=asz + + # Load the selector into a temporary. + ld t2, seg, [1, t0, t1], dsz, dataSize=2 + # Load the offset. + ld reg, seg, [1, t0, t1], 0 + # Install the selector value. + wrsel ss, t2 + # Make sure there isn't any junk in the upper bits of the base. + mov t2, t0, t2 + # Compute and set the base. + slli t2, t2, 4, dataSize=8 + wrbase ss, t2, dataSize=8 +}; + +# Versions for RIP relative addressing, even though these instructions are +# illegal in 64 bit mode, where RIP relative addressing is available. + +def macroop LDS_REAL_R_P { + panic "Real mode LDS doesn't support RIP relative addressing." +}; + +def macroop LES_REAL_R_P { + panic "Real mode LES doesn't support RIP relative addressing." +}; + +def macroop LFS_REAL_R_P { + panic "Real mode LFS doesn't support RIP relative addressing." +}; + +def macroop LGS_REAL_R_P { + panic "Real mode LGS doesn't support RIP relative addressing." +}; + +def macroop LSS_REAL_R_P { + panic "Real mode LSS doesn't support RIP relative addressing." +}; + +''' #let {{ # class LDS(Inst): # "GenFault ${new UnimpInstFault}"