diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 33313f120..84865d36d 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -140,6 +140,7 @@ static inline void fetch_ea_32_long(uint32_t rmdat) if (writelookup2[addr >> 12] != -1) eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); } + cpu_state.last_ea = eaaddr; } static inline void fetch_ea_16_long(uint32_t rmdat) @@ -182,6 +183,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat) if (writelookup2[addr >> 12] != -1) eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); } + cpu_state.last_ea = eaaddr; } #define fetch_ea_16(rmdat) cpu_state.pc++; mod=(rmdat >> 6) & 3; reg=(rmdat >> 3) & 7; rm = rmdat & 7; if (mod != 3) { fetch_ea_16_long(rmdat); if (abrt) return 1; } diff --git a/src/386_dynarec_ops.c b/src/386_dynarec_ops.c index bfa316488..a3101a828 100644 --- a/src/386_dynarec_ops.c +++ b/src/386_dynarec_ops.c @@ -28,6 +28,7 @@ static inline void fetch_ea_32_long(uint32_t rmdat) if (writelookup2[addr >> 12] != -1) eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); } + cpu_state.last_ea = eaaddr; } static inline void fetch_ea_16_long(uint32_t rmdat) @@ -43,6 +44,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat) if (writelookup2[addr >> 12] != -1) eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr); } + cpu_state.last_ea = eaaddr; } #define fetch_ea_16(rmdat) cpu_state.pc++; if (mod != 3) fetch_ea_16_long(rmdat); diff --git a/src/386_ops.h b/src/386_ops.h index 2aee7194c..d55f58265 100644 --- a/src/386_ops.h +++ b/src/386_ops.h @@ -18,11 +18,13 @@ static inline void PUSH_W(uint16_t val) { writememw(ss, ESP - 2, val); if (abrt) return; ESP -= 2; + cpu_state.last_ea = ESP; } else { writememw(ss, (SP - 2) & 0xFFFF, val); if (abrt) return; SP -= 2; + cpu_state.last_ea = SP; } } @@ -32,11 +34,13 @@ static inline void PUSH_L(uint32_t val) { writememl(ss, ESP - 4, val); if (abrt) return; ESP -= 4; + cpu_state.last_ea = ESP; } else { writememl(ss, (SP - 4) & 0xFFFF, val); if (abrt) return; SP -= 4; + cpu_state.last_ea = SP; } } @@ -47,11 +51,13 @@ static inline uint16_t POP_W() { ret = readmemw(ss, ESP); if (abrt) return 0; ESP += 2; + cpu_state.last_ea = ESP; } else { ret = readmemw(ss, SP); if (abrt) return 0; SP += 2; + cpu_state.last_ea = SP; } return ret; } @@ -63,11 +69,13 @@ static inline uint32_t POP_L() { ret = readmeml(ss, ESP); if (abrt) return 0; ESP += 4; + cpu_state.last_ea = ESP; } else { ret = readmeml(ss, SP); if (abrt) return 0; SP += 4; + cpu_state.last_ea = SP; } return ret; } @@ -79,11 +87,13 @@ static inline uint16_t POP_W_seg(uint32_t seg) { ret = readmemw(seg, ESP); if (abrt) return 0; ESP += 2; + cpu_state.last_ea = ESP; } else { ret = readmemw(seg, SP); if (abrt) return 0; SP += 2; + cpu_state.last_ea = SP; } return ret; } @@ -95,11 +105,13 @@ static inline uint32_t POP_L_seg(uint32_t seg) { ret = readmeml(seg, ESP); if (abrt) return 0; ESP += 4; + cpu_state.last_ea = ESP; } else { ret = readmeml(seg, SP); if (abrt) return 0; SP += 4; + cpu_state.last_ea = SP; } return ret; } diff --git a/src/808x.c b/src/808x.c index 4034e90dd..3d94ed733 100644 --- a/src/808x.c +++ b/src/808x.c @@ -383,11 +383,15 @@ static void fetcheal() if (rm&4) FETCHADD(9); else FETCHADD(11+slowrm[rm]); break; + case 3: + if (!(rm&4)) FETCHADD(2+slowrm[rm]); + return; } eaaddr+=(*mod1add[0][rm])+(*mod1add[1][rm]); easeg=*mod1seg[rm]; eaaddr&=0xFFFF; } + last_ea = eaaddr; } static inline uint8_t geteab() @@ -1173,6 +1177,7 @@ void execx86(int cycs) if (ssegs) ss=oldss; writememw(ss,((SP-2)&0xFFFF),ES); SP-=2; + cpu_state.last_ea = SP; cycles-=14; break; case 0x07: /*POP ES*/ @@ -1180,6 +1185,7 @@ void execx86(int cycs) tempw=readmemw(ss,SP); loadseg(tempw,&_es); SP+=2; + cpu_state.last_ea = SP; cycles-=12; break; @@ -1236,6 +1242,7 @@ void execx86(int cycs) if (ssegs) ss=oldss; writememw(ss,((SP-2)&0xFFFF),CS); SP-=2; + cpu_state.last_ea = SP; cycles-=14; break; case 0x0F: /*POP CS - 8088/8086 only*/ @@ -1243,6 +1250,7 @@ void execx86(int cycs) tempw=readmemw(ss,SP); loadseg(tempw,&_cs); SP+=2; + cpu_state.last_ea = SP; cycles-=12; break; @@ -1296,12 +1304,14 @@ void execx86(int cycs) writememw(ss,((SP-2)&0xFFFF),SS); SP-=2; cycles-=14; + cpu_state.last_ea = SP; break; case 0x17: /*POP SS*/ if (ssegs) ss=oldss; tempw=readmemw(ss,SP); loadseg(tempw,&_ss); SP+=2; + cpu_state.last_ea = SP; noint=1; cycles-=12; // output=1; @@ -1360,6 +1370,7 @@ void execx86(int cycs) if (ssegs) ss=oldss; writememw(ss,((SP-2)&0xFFFF),DS); SP-=2; + cpu_state.last_ea = SP; cycles-=14; break; case 0x1F: /*POP DS*/ @@ -1368,6 +1379,7 @@ void execx86(int cycs) loadseg(tempw,&_ds); if (ssegs) oldds=ds; SP+=2; + cpu_state.last_ea = SP; cycles-=12; break; @@ -1672,6 +1684,7 @@ void execx86(int cycs) case 0x54: case 0x55: case 0x56: case 0x57: if (ssegs) ss=oldss; SP-=2; + cpu_state.last_ea = SP; writememw(ss,SP,cpu_state.regs[opcode&7].w); cycles-=15; break; @@ -1679,6 +1692,7 @@ void execx86(int cycs) case 0x5C: case 0x5D: case 0x5E: case 0x5F: if (ssegs) ss=oldss; SP+=2; + cpu_state.last_ea = SP; cpu_state.regs[opcode&7].w=readmemw(ss,(SP-2)&0xFFFF); cycles-=12; break; @@ -2059,7 +2073,7 @@ void execx86(int cycs) case 0x8D: /*LEA*/ fetchea(); - cpu_state.regs[reg].w=eaaddr; + cpu_state.regs[reg].w=(mod == 3)?cpu_state.last_ea:eaaddr; cycles-=2; break; @@ -2100,6 +2114,7 @@ void execx86(int cycs) if (ssegs) ss=oldss; tempw=readmemw(ss,SP); SP+=2; + cpu_state.last_ea = SP; seteaw(tempw); cycles-=25; break; @@ -2136,6 +2151,7 @@ void execx86(int cycs) writememw(ss,(SP-2)&0xFFFF,tempw3); writememw(ss,(SP-4)&0xFFFF,tempw4); SP-=4; + cpu_state.last_ea = SP; cycles-=36; FETCHCLEAR(); break; @@ -2146,12 +2162,14 @@ void execx86(int cycs) if (ssegs) ss=oldss; writememw(ss,((SP-2)&0xFFFF),flags|0xF000); SP-=2; + cpu_state.last_ea = SP; cycles-=14; break; case 0x9D: /*POPF*/ if (ssegs) ss=oldss; flags=readmemw(ss,SP)&0xFFF; SP+=2; + cpu_state.last_ea = SP; cycles-=12; break; case 0x9E: /*SAHF*/ @@ -2881,6 +2899,7 @@ void execx86(int cycs) break; case 0xD7: /*XLAT*/ addr=BX+AL; + cpu_state.last_ea = addr; AL=readmemb(ds+addr); cycles-=11; break; @@ -2945,6 +2964,7 @@ void execx86(int cycs) // writememb(ss+((SP-1)&0xFFFF),pc>>8); writememw(ss,((SP-2)&0xFFFF),cpu_state.pc); SP-=2; + cpu_state.last_ea = SP; cpu_state.pc+=tempw; cycles-=23; FETCHCLEAR(); @@ -3346,6 +3366,7 @@ void execx86(int cycs) if (ssegs) ss=oldss; writememw(ss,(SP-2)&0xFFFF,cpu_state.pc); SP-=2; + cpu_state.last_ea = SP; cpu_state.pc=tempw; // printf("FF 10\n"); cycles-=((mod==3)?20:29); @@ -3363,6 +3384,7 @@ void execx86(int cycs) writememw(ss,(SP-2)&0xFFFF,tempw3); writememw(ss,((SP-4)&0xFFFF),tempw4); SP-=4; + cpu_state.last_ea = SP; cycles-=53; FETCHCLEAR(); break; @@ -3387,6 +3409,7 @@ void execx86(int cycs) if (ssegs) ss=oldss; writememw(ss,((SP-2)&0xFFFF),tempw); SP-=2; + cpu_state.last_ea = SP; cycles-=((mod==3)?15:24); break; diff --git a/src/ibm.h b/src/ibm.h index 417e00f82..0188d960e 100644 --- a/src/ibm.h +++ b/src/ibm.h @@ -108,6 +108,7 @@ struct uint32_t flags_op1, flags_op2; uint32_t pc; + uint32_t last_ea; } cpu_state; /*x86reg regs[8];*/ diff --git a/src/x86_ops_mov.h b/src/x86_ops_mov.h index 079a41f9f..f82004930 100644 --- a/src/x86_ops_mov.h +++ b/src/x86_ops_mov.h @@ -329,16 +329,16 @@ static int opMOV_a32_EAX(uint32_t fetchdat) static int opLEA_w_a16(uint32_t fetchdat) { fetch_ea_16(fetchdat); - ILLEGAL_ON(mod == 3); - cpu_state.regs[reg].w = eaaddr; + // ILLEGAL_ON(mod == 3); + cpu_state.regs[reg].w = (mod == 3) ? (cpu_state.last_ea & 0xffff) : eaaddr; CLOCK_CYCLES(timing_rr); return 0; } static int opLEA_w_a32(uint32_t fetchdat) { fetch_ea_32(fetchdat); - ILLEGAL_ON(mod == 3); - cpu_state.regs[reg].w = eaaddr; + // ILLEGAL_ON(mod == 3); + cpu_state.regs[reg].w = (mod == 3) ? (cpu_state.last_ea & 0xffff) : eaaddr; CLOCK_CYCLES(timing_rr); return 0; } @@ -346,16 +346,16 @@ static int opLEA_w_a32(uint32_t fetchdat) static int opLEA_l_a16(uint32_t fetchdat) { fetch_ea_16(fetchdat); - ILLEGAL_ON(mod == 3); - cpu_state.regs[reg].l = eaaddr & 0xffff; + // ILLEGAL_ON(mod == 3); + cpu_state.regs[reg].l = ((mod == 3) ? cpu_state.last_ea : eaaddr) & 0xffff; CLOCK_CYCLES(timing_rr); return 0; } static int opLEA_l_a32(uint32_t fetchdat) { fetch_ea_32(fetchdat); - ILLEGAL_ON(mod == 3); - cpu_state.regs[reg].l = eaaddr; + // ILLEGAL_ON(mod == 3); + cpu_state.regs[reg].l = (mod == 3) ? cpu_state.last_ea : eaaddr; CLOCK_CYCLES(timing_rr); return 0; } @@ -366,6 +366,7 @@ static int opXLAT_a16(uint32_t fetchdat) { uint32_t addr = (BX + AL)&0xFFFF; uint8_t temp; + last_ea = addr; temp = readmemb(ea_seg->base, addr); if (abrt) return 1; AL = temp; @@ -376,6 +377,7 @@ static int opXLAT_a32(uint32_t fetchdat) { uint32_t addr = EBX + AL; uint8_t temp; + last_ea = addr; temp = readmemb(ea_seg->base, addr); if (abrt) return 1; AL = temp; diff --git a/src/x86seg.c b/src/x86seg.c index c9eac419d..eb2aa079f 100644 --- a/src/x86seg.c +++ b/src/x86seg.c @@ -145,7 +145,6 @@ void x86_doabrt(int x86_abrt) } void x86gpf(char *s, uint16_t error) { - if (error == 0x82) return; pclog("GPF %04X : %s\n", error, s); abrt = ABRT_GPF; abrt_error = error;