--- np2/i286c/v30patch.c 2003/11/28 08:01:32 1.4 +++ np2/i286c/v30patch.c 2005/03/26 07:48:36 1.11 @@ -1,13 +1,15 @@ #include "compiler.h" -#include "i286.h" +#include "cpucore.h" #include "i286c.h" #include "v30patch.h" -#include "memory.h" #include "pccore.h" #include "iocore.h" #include "bios.h" -#include "dmap.h" +#include "dmav30.h" #include "i286c.mcr" +#if defined(ENABLE_TRAP) +#include "steptrap.h" +#endif // victory30 patch @@ -25,15 +27,17 @@ typedef struct { UINT opnum; - void (*v30opcode)(void); + I286OP v30opcode; } V30PATCH; -static void (*v30op[256])(void); -static void (*v30op_repne[256])(void); -static void (*v30op_repe[256])(void); +static I286OP v30op[256]; +static I286OP v30op_repne[256]; +static I286OP v30op_repe[256]; +static I286OPF6 v30ope0xf6_table[8]; +static I286OPF6 v30ope0xf7_table[8]; -static const BYTE shiftbase16[256] = +static const UINT8 rotatebase16[256] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, @@ -51,7 +55,7 @@ static const BYTE shiftbase16[256] = 16, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15}; -static const BYTE shiftbase09[256] = +static const UINT8 rotatebase09[256] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, @@ -69,7 +73,7 @@ static const BYTE shiftbase09[256] = 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3}; -static const BYTE shiftbase17[256] = +static const UINT8 rotatebase17[256] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 16,17, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, 15,16,17, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13, @@ -97,13 +101,13 @@ I286FN v30segprefix_es(void) { // 26: SS_FIX = ES_BASE; DS_FIX = ES_BASE; - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op[op](); REMOVE_PREFIX - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); @@ -114,13 +118,13 @@ I286FN v30segprefix_cs(void) { // 2e: SS_FIX = CS_BASE; DS_FIX = CS_BASE; - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op[op](); REMOVE_PREFIX - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); @@ -131,13 +135,13 @@ I286FN v30segprefix_ss(void) { // 36: SS_FIX = SS_BASE; DS_FIX = SS_BASE; - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op[op](); REMOVE_PREFIX - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); @@ -148,13 +152,13 @@ I286FN v30segprefix_ds(void) { // 3e: SS_FIX = DS_BASE; DS_FIX = DS_BASE; - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op[op](); REMOVE_PREFIX - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); @@ -224,10 +228,10 @@ I286FN v30_popf(void) { // 9D: popf I286FN v30shift_ea8_data8(void) { // C0: shift EA8, DATA8 - BYTE *out; + UINT8 *out; UINT op; UINT32 madr; - BYTE cl; + REG8 cl; GET_PCBYTE(op) if (op >= 0xc0) { @@ -239,26 +243,36 @@ I286FN v30shift_ea8_data8(void) { // C madr = CALC_EA(op); if (madr >= I286_MEMWRITEMAX) { GET_PCBYTE(cl) - if ((op & 0x30) == 0x10) { // rotate with carry - cl = shiftbase09[cl]; + I286_WORKCLOCK(cl); + if (!(op & 0x20)) { // rotate + if (!(op & 0x10)) { + cl = rotatebase16[cl]; + } + else { // rotate with carry + cl = rotatebase09[cl]; + } } else { - cl = shiftbase16[cl]; + cl = max(cl, 9); } - I286_WORKCLOCK(cl); sft_e8cl_table[(op >> 3) & 7](madr, cl); return; } out = mem + madr; } GET_PCBYTE(cl) - if ((op & 0x30) == 0x10) { // rotate with carry - cl = shiftbase09[cl]; + I286_WORKCLOCK(cl); + if (!(op & 0x20)) { // rotate + if (!(op & 0x10)) { + cl = rotatebase16[cl]; + } + else { // rotate with carry + cl = rotatebase09[cl]; + } } else { - cl = shiftbase16[cl]; + cl = max(cl, 9); } - I286_WORKCLOCK(cl); sft_r8cl_table[(op >> 3) & 7](out, cl); } @@ -267,7 +281,7 @@ I286FN v30shift_ea16_data8(void) { // UINT16 *out; UINT op; UINT32 madr; - BYTE cl; + REG8 cl; GET_PCBYTE(op) if (op >= 0xc0) { @@ -279,35 +293,45 @@ I286FN v30shift_ea16_data8(void) { // madr = CALC_EA(op); if (INHIBIT_WORDP(madr)) { GET_PCBYTE(cl); - if ((op & 0x30) == 0x10) { // rotate with carry - cl = shiftbase17[cl]; + I286_WORKCLOCK(cl); + if (!(op & 0x20)) { // rotate + if (!(op & 0x10)) { + cl = rotatebase16[cl]; + } + else { // with carry + cl = rotatebase17[cl]; + } } - else { - cl = shiftbase16[cl]; + else { // shift + cl = max(cl, 17); } - I286_WORKCLOCK(cl); sft_e16cl_table[(op >> 3) & 7](madr, cl); return; } out = (UINT16 *)(mem + madr); } GET_PCBYTE(cl); - if ((op & 0x30) == 0x10) { // rotate with carry - cl = shiftbase17[cl]; + I286_WORKCLOCK(cl); + if (!(op & 0x20)) { // rotate + if (!(op & 0x10)) { + cl = rotatebase16[cl]; + } + else { // with carry + cl = rotatebase17[cl]; + } } - else { - cl = shiftbase16[cl]; + else { // shift + cl = max(cl, 17); } - I286_WORKCLOCK(cl); sft_r16cl_table[(op >> 3) & 7](out, cl); } I286FN v30shift_ea8_cl(void) { // D2: shift EA8, cl - BYTE *out; + UINT8 *out; UINT op; UINT32 madr; - BYTE cl; + REG8 cl; GET_PCBYTE(op) if (op >= 0xc0) { @@ -320,11 +344,16 @@ I286FN v30shift_ea8_cl(void) { // D2: if (madr >= I286_MEMWRITEMAX) { cl = I286_CL; I286_WORKCLOCK(cl); - if ((op & 0x30) == 0x10) { // rotate with carry - cl = shiftbase09[cl]; + if (!(op & 0x20)) { // rotate + if (!(op & 0x10)) { + cl = rotatebase16[cl]; + } + else { // rotate with carry + cl = rotatebase09[cl]; + } } else { - cl = shiftbase16[cl]; + cl = max(cl, 9); } sft_e8cl_table[(op >> 3) & 7](madr, cl); return; @@ -333,11 +362,16 @@ I286FN v30shift_ea8_cl(void) { // D2: } cl = I286_CL; I286_WORKCLOCK(cl); - if ((op & 0x30) == 0x10) { // rotate with carry - cl = shiftbase09[cl]; + if (!(op & 0x20)) { // rotate + if (!(op & 0x10)) { + cl = rotatebase16[cl]; + } + else { // rotate with carry + cl = rotatebase09[cl]; + } } else { - cl = shiftbase16[cl]; + cl = max(cl, 9); } sft_r8cl_table[(op >> 3) & 7](out, cl); } @@ -347,7 +381,7 @@ I286FN v30shift_ea16_cl(void) { // D3 UINT16 *out; UINT op; UINT32 madr; - BYTE cl; + REG8 cl; GET_PCBYTE(op) if (op >= 0xc0) { @@ -360,11 +394,16 @@ I286FN v30shift_ea16_cl(void) { // D3 if (INHIBIT_WORDP(madr)) { cl = I286_CL; I286_WORKCLOCK(cl); - if ((op & 0x30) == 0x10) { // rotate with carry - cl = shiftbase17[cl]; + if (!(op & 0x20)) { // rotate + if (!(op & 0x10)) { + cl = rotatebase16[cl]; + } + else { // with carry + cl = rotatebase17[cl]; + } } - else { - cl = shiftbase16[cl]; + else { // shift + cl = max(cl, 17); } sft_e16cl_table[(op >> 3) & 7](madr, cl); return; @@ -373,18 +412,23 @@ I286FN v30shift_ea16_cl(void) { // D3 } cl = I286_CL; I286_WORKCLOCK(cl); - if ((op & 0x30) == 0x10) { // rotate with carry - cl = shiftbase17[cl]; + if (!(op & 0x20)) { // rotate + if (!(op & 0x10)) { + cl = rotatebase16[cl]; + } + else { // with carry + cl = rotatebase17[cl]; + } } - else { - cl = shiftbase16[cl]; + else { // shift + cl = max(cl, 17); } sft_r16cl_table[(op >> 3) & 7](out, cl); } I286FN v30_aam(void) { // D4: AAM - BYTE al; + UINT8 al; I286_WORKCLOCK(16); I286_IP++; // is 10 @@ -399,7 +443,7 @@ I286FN v30_aad(void) { // D5: AAD I286_WORKCLOCK(14); I286_IP++; // is 10 - I286_AL += (BYTE)(I286_AH * 10); + I286_AL += (UINT8)(I286_AH * 10); I286_AH = 0; I286_FLAGL &= ~(S_FLAG | Z_FLAG | P_FLAG); I286_FLAGL |= BYTESZPF(I286_AL); @@ -413,12 +457,12 @@ I286FN v30_xlat(void) { // D6: xlat I286FN v30_repne(void) { // F2: repne - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op_repne[op](); - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); @@ -427,18 +471,132 @@ I286FN v30_repne(void) { // F2: repn I286FN v30_repe(void) { // F3: repe - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op_repe[op](); - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); } } +I286_F6 v30_div_ea8(UINT op) { + + UINT16 tmp; + UINT8 src; + + if (op >= 0xc0) { + I286_WORKCLOCK(14); + src = *(REG8_B20(op)); + } + else { + I286_WORKCLOCK(17); + src = i286_memoryread(CALC_EA(op)); + } + tmp = I286_AX; + if ((src) && (tmp < ((UINT16)src << 8))) { + I286_AL = tmp / src; + I286_AH = tmp % src; + } + else { + INT_NUM(0, I286_IP); // V30 + } +} + +I286_F6 v30_idiv_ea8(UINT op) { + + SINT16 tmp; + SINT16 r; + SINT8 src; + + if (op >= 0xc0) { + I286_WORKCLOCK(17); + src = *(REG8_B20(op)); + } + else { + I286_WORKCLOCK(20); + src = i286_memoryread(CALC_EA(op)); + } + tmp = (SINT16)I286_AX; + if (src) { + r = tmp / src; + if (!((r + 0x80) & 0xff00)) { + I286_AL = (UINT8)r; + I286_AH = tmp % src; + return; + } + } + INT_NUM(0, I286_IP); // V30 +} + +I286FN v30_ope0xf6(void) { // F6: + + UINT op; + + GET_PCBYTE(op); + v30ope0xf6_table[(op >> 3) & 7](op); +} + +I286_F6 v30_div_ea16(UINT op) { + + UINT32 tmp; + UINT32 src; + + if (op >= 0xc0) { + I286_WORKCLOCK(22); + src = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(25); + src = i286_memoryread_w(CALC_EA(op)); + } + tmp = (I286_DX << 16) + I286_AX; + if ((src) && (tmp < (src << 16))) { + I286_AX = tmp / src; + I286_DX = tmp % src; + } + else { + INT_NUM(0, I286_IP); // V30 + } +} + +I286_F6 v30_idiv_ea16(UINT op) { + + SINT32 tmp; + SINT32 r; + SINT16 src; + + if (op >= 0xc0) { + I286_WORKCLOCK(25); + src = *(REG16_B20(op)); + } + else { + I286_WORKCLOCK(28); + src = i286_memoryread_w(CALC_EA(op)); + } + tmp = (SINT32)((I286_DX << 16) + I286_AX); + if (src) { + r = tmp / src; + if (!((r + 0x8000) & 0xffff0000)) { + I286_AX = (SINT16)r; + I286_DX = tmp % src; + return; + } + } + INT_NUM(0, I286_IP); // V30 +} + +I286FN v30_ope0xf7(void) { // F7: + + UINT op; + + GET_PCBYTE(op); + v30ope0xf7_table[(op >> 3) & 7](op); +} + static const V30PATCH v30patch_op[] = { {0x26, v30segprefix_es}, // 26: es: {0x2e, v30segprefix_cs}, // 2E: cs: @@ -462,8 +620,9 @@ static const V30PATCH v30patch_op[] = { {0xd5, v30_aad}, // D5: AAD {0xd6, v30_xlat}, // D6: xlat (8086/V30) {0xf2, v30_repne}, // F2: repne - {0xf3, v30_repe} // F3: repe -}; + {0xf3, v30_repe}, // F3: repe + {0xf6, v30_ope0xf6}, // F6: + {0xf7, v30_ope0xf7}}; // F7: // ----------------------------------------------------------------- repe @@ -472,13 +631,13 @@ I286FN v30repe_segprefix_es(void) { DS_FIX = ES_BASE; SS_FIX = ES_BASE; - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op_repe[op](); REMOVE_PREFIX - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); @@ -489,13 +648,13 @@ I286FN v30repe_segprefix_cs(void) { DS_FIX = CS_BASE; SS_FIX = CS_BASE; - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op_repe[op](); REMOVE_PREFIX - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); @@ -506,13 +665,13 @@ I286FN v30repe_segprefix_ss(void) { DS_FIX = SS_BASE; SS_FIX = SS_BASE; - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op_repe[op](); REMOVE_PREFIX - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); @@ -523,13 +682,13 @@ I286FN v30repe_segprefix_ds(void) { DS_FIX = DS_BASE; SS_FIX = DS_BASE; - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op_repe[op](); REMOVE_PREFIX - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); @@ -559,8 +718,9 @@ static const V30PATCH v30patch_repe[] = {0xd5, v30_aad}, // D5: AAD {0xd6, v30_xlat}, // D6: xlat (8086/V30) {0xf2, v30_repne}, // F2: repne - {0xf3, v30_repe} // F3: repe -}; + {0xf3, v30_repe}, // F3: repe + {0xf6, v30_ope0xf6}, // F6: + {0xf7, v30_ope0xf7}}; // F7: // ----------------------------------------------------------------- repne @@ -569,13 +729,13 @@ I286FN v30repne_segprefix_es(void) { DS_FIX = ES_BASE; SS_FIX = ES_BASE; - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op_repne[op](); REMOVE_PREFIX - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); @@ -586,13 +746,13 @@ I286FN v30repne_segprefix_cs(void) { DS_FIX = CS_BASE; SS_FIX = CS_BASE; - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op_repne[op](); REMOVE_PREFIX - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); @@ -603,13 +763,13 @@ I286FN v30repne_segprefix_ss(void) { DS_FIX = SS_BASE; SS_FIX = SS_BASE; - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op_repne[op](); REMOVE_PREFIX - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); @@ -620,13 +780,13 @@ I286FN v30repne_segprefix_ds(void) { DS_FIX = DS_BASE; SS_FIX = DS_BASE; - i286reg.prefix++; - if (i286reg.prefix < MAX_PREFIX) { + I286_PREFIX++; + if (I286_PREFIX < MAX_PREFIX) { UINT op; GET_PCBYTE(op); v30op_repne[op](); REMOVE_PREFIX - i286reg.prefix = 0; + I286_PREFIX = 0; } else { INT_NUM(6, I286_IP); @@ -656,13 +816,14 @@ static const V30PATCH v30patch_repne[] = {0xd5, v30_aad}, // D5: AAD {0xd6, v30_xlat}, // D6: xlat (8086/V30) {0xf2, v30_repne}, // F2: repne - {0xf3, v30_repe} // F3: repe -}; + {0xf3, v30_repe}, // F3: repe + {0xf6, v30_ope0xf6}, // F6: + {0xf7, v30_ope0xf7}}; // F7: // --------------------------------------------------------------------------- -static void v30patching(void (*op[])(void), const V30PATCH *patch, int cnt) { +static void v30patching(I286OP *op, const V30PATCH *patch, int cnt) { do { op[patch->opnum] = patch->v30opcode; @@ -672,7 +833,7 @@ static void v30patching(void (*op[])(voi #define V30PATCHING(a, b) v30patching(a, b, sizeof(b)/sizeof(V30PATCH)) -void v30init(void) { +void v30cinit(void) { CopyMemory(v30op, i286op, sizeof(v30op)); V30PATCHING(v30op, v30patch_op); @@ -680,38 +841,53 @@ void v30init(void) { V30PATCHING(v30op_repne, v30patch_repne); CopyMemory(v30op_repe, i286op_repe, sizeof(v30op_repe)); V30PATCHING(v30op_repe, v30patch_repe); + CopyMemory(v30ope0xf6_table, c_ope0xf6_table, sizeof(v30ope0xf6_table)); + v30ope0xf6_table[6] = v30_div_ea8; + v30ope0xf6_table[7] = v30_idiv_ea8; + CopyMemory(v30ope0xf7_table, c_ope0xf7_table, sizeof(v30ope0xf7_table)); + v30ope0xf7_table[6] = v30_div_ea16; + v30ope0xf7_table[7] = v30_idiv_ea16; } -void v30(void) { +void v30c(void) { UINT opcode; if (I286_TRAP) { do { +#if defined(ENABLE_TRAP) + steptrap(CPU_CS, CPU_IP); +#endif GET_PCBYTE(opcode); v30op[opcode](); if (I286_TRAP) { - i286_interrupt(1); + i286c_interrupt(1); } - dmap_v30(); + dmav30(); } while(I286_REMCLOCK > 0); } else if (dmac.working) { do { +#if defined(ENABLE_TRAP) + steptrap(CPU_CS, CPU_IP); +#endif GET_PCBYTE(opcode); v30op[opcode](); - dmap_v30(); + dmav30(); } while(I286_REMCLOCK > 0); } else { do { +#if defined(ENABLE_TRAP) + steptrap(CPU_CS, CPU_IP); +#endif GET_PCBYTE(opcode); v30op[opcode](); } while(I286_REMCLOCK > 0); } } -void v30_step(void) { +void v30c_step(void) { UINT opcode; @@ -725,6 +901,6 @@ void v30_step(void) { if (I286_OV) { I286_FLAG |= (O_FLAG); } - dmap_v30(); + dmav30(); }