From 4cb5ddd7f79fc6c8dd0f6dfddebff55340c446d3 Mon Sep 17 00:00:00 2001 From: SarahW Date: Fri, 28 Apr 2017 18:47:38 +0100 Subject: [PATCH] Implemented undocumented F6/1 and F7/1 TEST instructions. Implemented undocumented F1 LOCK and ICEBP instructions. Implemented missing 286 LOADALL functionality. SMSW now sets all 12 bits to 1 on 286. Patch from Greatpsycho. --- src/386_ops.h | 16 ++++++++-------- src/808x.c | 2 ++ src/x86_ops_int.h | 14 ++++++++++++++ src/x86_ops_misc.h | 35 +++++++++++++++++++++++++++++++++-- src/x86_ops_pmode.h | 6 ++++-- 5 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/386_ops.h b/src/386_ops.h index e66549c..43a7cfd 100644 --- a/src/386_ops.h +++ b/src/386_ops.h @@ -750,7 +750,7 @@ OpFn OP_TABLE(286)[1024] = /*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, /*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, /*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, -/*f0*/ opLOCK, ILLEGAL, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, +/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, /*32-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -772,7 +772,7 @@ OpFn OP_TABLE(286)[1024] = /*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, /*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, /*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, -/*f0*/ opLOCK, ILLEGAL, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, +/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, /*16-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -794,7 +794,7 @@ OpFn OP_TABLE(286)[1024] = /*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, /*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, /*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, -/*f0*/ opLOCK, ILLEGAL, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, +/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, /*32-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -816,7 +816,7 @@ OpFn OP_TABLE(286)[1024] = /*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET_286, /*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, /*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, -/*f0*/ opLOCK, ILLEGAL, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, +/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, }; OpFn OP_TABLE(386)[1024] = @@ -841,7 +841,7 @@ OpFn OP_TABLE(386)[1024] = /*c0*/ opC0_a16, opC1_w_a16, opRET_w_imm, opRET_w, opLES_w_a16, opLDS_w_a16, opMOV_b_imm_a16,opMOV_w_imm_a16,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET, /*d0*/ opD0_a16, opD1_w_a16, opD2_a16, opD3_w_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, /*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, -/*f0*/ opLOCK, ILLEGAL, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, +/*f0*/ opLOCK, opINT1, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16, /*32-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -863,7 +863,7 @@ OpFn OP_TABLE(386)[1024] = /*c0*/ opC0_a16, opC1_l_a16, opRET_l_imm, opRET_l, opLES_l_a16, opLDS_l_a16, opMOV_b_imm_a16,opMOV_l_imm_a16,opENTER_l, opLEAVE_l, opRETF_a32_imm, opRETF_a32, opINT3, opINT, opINTO, opIRETD, /*d0*/ opD0_a16, opD1_l_a16, opD2_a16, opD3_l_a16, opAAM, opAAD, opSETALC, opXLAT_a16, opESCAPE_d8_a16,opESCAPE_d9_a16,opESCAPE_da_a16,opESCAPE_db_a16,opESCAPE_dc_a16,opESCAPE_dd_a16,opESCAPE_de_a16,opESCAPE_df_a16, /*e0*/ opLOOPNE_w, opLOOPE_w, opLOOP_w, opJCXZ, opIN_AL_imm, opIN_EAX_imm, opOUT_AL_imm, opOUT_EAX_imm, opCALL_r32, opJMP_r32, opJMP_far_a32, opJMP_r8, opIN_AL_DX, opIN_EAX_DX, opOUT_AL_DX, opOUT_EAX_DX, -/*f0*/ opLOCK, ILLEGAL, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_l_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_l_a16, +/*f0*/ opLOCK, opINT1, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_l_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_l_a16, /*16-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -885,7 +885,7 @@ OpFn OP_TABLE(386)[1024] = /*c0*/ opC0_a32, opC1_w_a32, opRET_w_imm, opRET_w, opLES_w_a32, opLDS_w_a32, opMOV_b_imm_a32,opMOV_w_imm_a32,opENTER_w, opLEAVE_w, opRETF_a16_imm, opRETF_a16, opINT3, opINT, opINTO, opIRET, /*d0*/ opD0_a32, opD1_w_a32, opD2_a32, opD3_w_a32, opAAM, opAAD, opSETALC, opXLAT_a32, opESCAPE_d8_a32,opESCAPE_d9_a32,opESCAPE_da_a32,opESCAPE_db_a32,opESCAPE_dc_a32,opESCAPE_dd_a32,opESCAPE_de_a32,opESCAPE_df_a32, /*e0*/ opLOOPNE_l, opLOOPE_l, opLOOP_l, opJECXZ, opIN_AL_imm, opIN_AX_imm, opOUT_AL_imm, opOUT_AX_imm, opCALL_r16, opJMP_r16, opJMP_far_a16, opJMP_r8, opIN_AL_DX, opIN_AX_DX, opOUT_AL_DX, opOUT_AX_DX, -/*f0*/ opLOCK, ILLEGAL, opREPNE, opREPE, opHLT, opCMC, opF6_a32, opF7_w_a32, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a32, opFF_w_a32, +/*f0*/ opLOCK, opINT1, opREPNE, opREPE, opHLT, opCMC, opF6_a32, opF7_w_a32, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a32, opFF_w_a32, /*32-bit data, 32-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -907,7 +907,7 @@ OpFn OP_TABLE(386)[1024] = /*c0*/ opC0_a32, opC1_l_a32, opRET_l_imm, opRET_l, opLES_l_a32, opLDS_l_a32, opMOV_b_imm_a32,opMOV_l_imm_a32,opENTER_l, opLEAVE_l, opRETF_a32_imm, opRETF_a32, opINT3, opINT, opINTO, opIRETD, /*d0*/ opD0_a32, opD1_l_a32, opD2_a32, opD3_l_a32, opAAM, opAAD, opSETALC, opXLAT_a32, opESCAPE_d8_a32,opESCAPE_d9_a32,opESCAPE_da_a32,opESCAPE_db_a32,opESCAPE_dc_a32,opESCAPE_dd_a32,opESCAPE_de_a32,opESCAPE_df_a32, /*e0*/ opLOOPNE_l, opLOOPE_l, opLOOP_l, opJECXZ, opIN_AL_imm, opIN_EAX_imm, opOUT_AL_imm, opOUT_EAX_imm, opCALL_r32, opJMP_r32, opJMP_far_a32, opJMP_r8, opIN_AL_DX, opIN_EAX_DX, opOUT_AL_DX, opOUT_EAX_DX, -/*f0*/ opLOCK, ILLEGAL, opREPNE, opREPE, opHLT, opCMC, opF6_a32, opF7_l_a32, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a32, opFF_l_a32, +/*f0*/ opLOCK, opINT1, opREPNE, opREPE, opHLT, opCMC, opF6_a32, opF7_l_a32, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a32, opFF_l_a32, }; #include "x87_ops.h" diff --git a/src/808x.c b/src/808x.c index 6be3ed8..1ff61d0 100644 --- a/src/808x.c +++ b/src/808x.c @@ -3025,6 +3025,7 @@ void execx86(int cycs) switch (rmdat&0x38) { case 0x00: /*TEST b,#8*/ + case 0x08: temp2=FETCH(); temp&=temp2; setznp8(temp); @@ -3163,6 +3164,7 @@ void execx86(int cycs) switch (rmdat&0x38) { case 0x00: /*TEST w*/ + case 0x08: tempw2=getword(); setznp16(tempw&tempw2); flags&=~(C_FLAG|V_FLAG|A_FLAG); diff --git a/src/x86_ops_int.h b/src/x86_ops_int.h index 6dbb63a..f72ef60 100644 --- a/src/x86_ops_int.h +++ b/src/x86_ops_int.h @@ -12,6 +12,20 @@ static int opINT3(uint32_t fetchdat) return 1; } +static int opINT1(uint32_t fetchdat) +{ + int cycles_old = cycles; UNUSED(cycles_old); + if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3)) + { + x86gpf(NULL,0); + return 1; + } + x86_int_sw(1); + CLOCK_CYCLES((is486) ? 44 : 59); + PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,0,0,0, 0); + return 1; +} + static int opINT(uint32_t fetchdat) { int cycles_old = cycles; UNUSED(cycles_old); diff --git a/src/x86_ops_misc.h b/src/x86_ops_misc.h index 5ced32a..beee6bd 100644 --- a/src/x86_ops_misc.h +++ b/src/x86_ops_misc.h @@ -56,6 +56,7 @@ static int opF6_a16(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*TEST b,#8*/ + case 0x08: src = readmemb(cs, cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; setznp8(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -153,6 +154,7 @@ static int opF6_a32(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*TEST b,#8*/ + case 0x08: src = readmemb(cs, cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1; setznp8(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -253,6 +255,7 @@ static int opF7_w_a16(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*TEST w*/ + case 0x08: src = getword(); if (cpu_state.abrt) return 1; setznp16(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -346,6 +349,7 @@ static int opF7_w_a32(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*TEST w*/ + case 0x08: src = getword(); if (cpu_state.abrt) return 1; setznp16(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -439,6 +443,7 @@ static int opF7_l_a16(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*TEST l*/ + case 0x08: src = getlong(); if (cpu_state.abrt) return 1; setznp32(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -508,6 +513,7 @@ static int opF7_l_a32(uint32_t fetchdat) switch (rmdat & 0x38) { case 0x00: /*TEST l*/ + case 0x08: src = getlong(); if (cpu_state.abrt) return 1; setznp32(src & dst); if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); @@ -721,13 +727,19 @@ static int opWBINVD(uint32_t fetchdat) return 0; } - - static int opLOADALL(uint32_t fetchdat) { + if (CPL && (cr0&1)) + { + x86gpf(NULL,0); + return 1; + } + msw = readmemw(0, 0x806); flags = (readmemw(0, 0x818) & 0xffd5) | 2; flags_extract(); + tr.seg = readmemw(0, 0x816); cpu_state.pc = readmemw(0, 0x81A); + ldt.seg = readmemw(0, 0x81C); DS = readmemw(0, 0x81E); SS = readmemw(0, 0x820); CS = readmemw(0, 0x822); @@ -741,10 +753,29 @@ static int opLOADALL(uint32_t fetchdat) CX = readmemw(0, 0x832); AX = readmemw(0, 0x834); es = readmemw(0, 0x836) | (readmemb(0, 0x838) << 16); + _es.access = readmemb(0, 0x839); + _es.limit = readmemw(0, 0x83A); cs = readmemw(0, 0x83C) | (readmemb(0, 0x83E) << 16); + _cs.access = readmemb(0, 0x83F); + _cs.limit = readmemw(0, 0x840); ss = readmemw(0, 0x842) | (readmemb(0, 0x844) << 16); + _ss.access = readmemb(0, 0x845); + _ss.limit = readmemw(0, 0x846); ds = readmemw(0, 0x848) | (readmemb(0, 0x84A) << 16); + _ds.access = readmemb(0, 0x84B); + _ds.limit = readmemw(0, 0x84C); + gdt.base = readmemw(0, 0x84E) | (readmemb(0, 0x850) << 16); + gdt.limit = readmemw(0, 0x852); + ldt.base = readmemw(0, 0x854) | (readmemb(0, 0x856) << 16); + ldt.access = readmemb(0, 0x857); + ldt.limit = readmemw(0, 0x858); + idt.base = readmemw(0, 0x85A) | (readmemb(0, 0x85C) << 16); + idt.limit = readmemw(0, 0x85E); + tr.base = readmemw(0, 0x860) | (readmemb(0, 0x862) << 16); + tr.access = readmemb(0, 0x863); + tr.limit = readmemw(0, 0x864); CLOCK_CYCLES(195); + PREFETCH_RUN(195, 1, -1, 51,0,0,0, 0); return 0; } diff --git a/src/x86_ops_pmode.h b/src/x86_ops_pmode.h index bfd67c5..426776e 100644 --- a/src/x86_ops_pmode.h +++ b/src/x86_ops_pmode.h @@ -350,8 +350,9 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) break; case 0x20: /*SMSW*/ - if (is486) seteaw(msw); - else seteaw(msw | 0xFF00); + if (is486) seteaw(msw); + else if (is386) seteaw(msw | 0xFF00); + else seteaw(msw | 0xFFF0); CLOCK_CYCLES(2); PREFETCH_RUN(2, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); break; @@ -364,6 +365,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32) } tempw = geteaw(); if (cpu_state.abrt) return 1; if (msw & 1) tempw |= 1; + if (!is386) tempw &= 0xF; msw = tempw; PREFETCH_RUN(2, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32); break;