diff options
| author | 2009-12-23 17:53:33 +0000 | |
|---|---|---|
| committer | 2009-12-23 17:53:33 +0000 | |
| commit | a825a2427fcf83f4a7f7ea9d0d94176f3e4616e5 (patch) | |
| tree | 6dbe7eda5cd23c8a978bade0ecd582fc95f8eb85 | |
| parent | de3ffd84b38becd43ea70af53f484ac90ef47b86 (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.c | 27 | ||||
| -rw-r--r-- | src/emu/cpu/i386/i386op32.c | 27 | ||||
| -rw-r--r-- | src/emu/cpu/i386/i386ops.c | 24 | ||||
| -rw-r--r-- | src/emu/cpu/i386/i386ops.h | 2 |
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), }, |
