summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2009-12-23 17:53:33 +0000
committer Aaron Giles <aaron@aarongiles.com>2009-12-23 17:53:33 +0000
commita825a2427fcf83f4a7f7ea9d0d94176f3e4616e5 (patch)
tree6dbe7eda5cd23c8a978bade0ecd582fc95f8eb85
parentde3ffd84b38becd43ea70af53f484ac90ef47b86 (diff)
---------- Forwarded message ----------
From: Barry Rodewald <bsr@xnet.co.nz> Date: Wed, Dec 23, 2009 at 2:37 AM Subject: Yet more i386 fixes To: submit@mamedev.org Hi, Here's two more small i386 fixes. First, is an implementation of the LSL protected mode instruction. While it's far from perfect (ie: it doesn't check for anything other than a null segment selector), it does help get a little bit further for some FM Towns applications. Second, is a fix for the REP instruction when used with a segment prefix. Essentially, it reverses the use of the segment_override and segment_prefix variables compared to other instructions. This fixes sprite data copied into sprite RAM on the FM Towns version of Raiden Trad. Thanks, Barry Rodewald mailto:bsr@xnet.co.nz
-rw-r--r--src/emu/cpu/i386/i386op16.c27
-rw-r--r--src/emu/cpu/i386/i386op32.c27
-rw-r--r--src/emu/cpu/i386/i386ops.c24
-rw-r--r--src/emu/cpu/i386/i386ops.h2
4 files changed, 67 insertions, 13 deletions
diff --git a/src/emu/cpu/i386/i386op16.c b/src/emu/cpu/i386/i386op16.c
index 24f2680ece8..66bc15587d9 100644
--- a/src/emu/cpu/i386/i386op16.c
+++ b/src/emu/cpu/i386/i386op16.c
@@ -3105,6 +3105,33 @@ static void I386OP(group0FBA_16)(i386_state *cpustate) // Opcode 0x0f ba
}
}
+static void I386OP(lsl_r16_rm16)(i386_state *cpustate) // Opcode 0x0f 0x03
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT32 limit;
+ I386_SREG seg;
+
+ if(PROTECTED_MODE)
+ {
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = LOAD_RM16(modrm);
+ if(seg.selector == 0)
+ {
+ SetZF(0); // not a valid segment
+ }
+ else
+ {
+ // TODO: check segment type
+ i386_load_protected_mode_segment(cpustate,&seg);
+ limit = seg.limit;
+ STORE_REG16(modrm,limit & 0x0000ffff);
+ SetZF(1);
+ }
+ }
+ else
+ i386_trap(cpustate,6, 0);
+}
+
static void I386OP(bound_r16_m16_m16)(i386_state *cpustate) // Opcode 0x62
{
UINT8 modrm;
diff --git a/src/emu/cpu/i386/i386op32.c b/src/emu/cpu/i386/i386op32.c
index c95d4276902..229067d8637 100644
--- a/src/emu/cpu/i386/i386op32.c
+++ b/src/emu/cpu/i386/i386op32.c
@@ -2923,6 +2923,33 @@ static void I386OP(group0FBA_32)(i386_state *cpustate) // Opcode 0x0f ba
}
}
+static void I386OP(lsl_r32_rm32)(i386_state *cpustate) // Opcode 0x0f 0x03
+{
+ UINT8 modrm = FETCH(cpustate);
+ UINT32 limit;
+ I386_SREG seg;
+
+ if(PROTECTED_MODE)
+ {
+ memset(&seg, 0, sizeof(seg));
+ seg.selector = LOAD_RM32(modrm);
+ if(seg.selector == 0)
+ {
+ SetZF(0); // not a valid segment
+ }
+ else
+ {
+ // TODO: check segment type
+ i386_load_protected_mode_segment(cpustate,&seg);
+ limit = seg.limit;
+ STORE_REG32(modrm,limit);
+ SetZF(1);
+ }
+ }
+ else
+ i386_trap(cpustate,6, 0);
+}
+
static void I386OP(bound_r32_m32_m32)(i386_state *cpustate) // Opcode 0x62
{
UINT8 modrm;
diff --git a/src/emu/cpu/i386/i386ops.c b/src/emu/cpu/i386/i386ops.c
index 89b668f3a54..f31204d198e 100644
--- a/src/emu/cpu/i386/i386ops.c
+++ b/src/emu/cpu/i386/i386ops.c
@@ -1030,28 +1030,28 @@ static void I386OP(repeat)(i386_state *cpustate, int invert_flag)
opcode = FETCH(cpustate);
switch(opcode) {
case 0x26:
- cpustate->segment_override=1;
- cpustate->segment_prefix=ES;
+ cpustate->segment_override=ES;
+ cpustate->segment_prefix=1;
break;
case 0x2e:
- cpustate->segment_override=1;
- cpustate->segment_prefix=CS;
+ cpustate->segment_override=CS;
+ cpustate->segment_prefix=1;
break;
case 0x36:
- cpustate->segment_override=1;
- cpustate->segment_prefix=SS;
+ cpustate->segment_override=SS;
+ cpustate->segment_prefix=1;
break;
case 0x3e:
- cpustate->segment_override=1;
- cpustate->segment_prefix=DS;
+ cpustate->segment_override=DS;
+ cpustate->segment_prefix=1;
break;
case 0x64:
- cpustate->segment_override=1;
- cpustate->segment_prefix=FS;
+ cpustate->segment_override=FS;
+ cpustate->segment_prefix=1;
break;
case 0x65:
- cpustate->segment_override=1;
- cpustate->segment_prefix=GS;
+ cpustate->segment_override=GS;
+ cpustate->segment_prefix=1;
break;
case 0x66:
cpustate->operand_size ^= 1;
diff --git a/src/emu/cpu/i386/i386ops.h b/src/emu/cpu/i386/i386ops.h
index 9f204422ac6..8a63193de55 100644
--- a/src/emu/cpu/i386/i386ops.h
+++ b/src/emu/cpu/i386/i386ops.h
@@ -288,7 +288,7 @@ static const X86_OPCODE x86_opcode_table[] =
{ 0x01, OP_2BYTE|OP_I386, I386OP(group0F01_16), I386OP(group0F01_32), },
{ 0x01, OP_2BYTE|OP_I486, I486OP(group0F01_16), I486OP(group0F01_32), },
{ 0x02, OP_2BYTE|OP_I386, I386OP(unimplemented), I386OP(unimplemented), },
- { 0x03, OP_2BYTE|OP_I386, I386OP(unimplemented), I386OP(unimplemented), },
+ { 0x03, OP_2BYTE|OP_I386, I386OP(lsl_r16_rm16), I386OP(lsl_r32_rm32), },
{ 0x06, OP_2BYTE|OP_I386, I386OP(clts), I386OP(clts), },
{ 0x08, OP_2BYTE|OP_I486, I486OP(invd), I486OP(invd), },
{ 0x09, OP_2BYTE|OP_I486, I486OP(wbinvd), I486OP(wbinvd), },