From c322cbdb63d3b8e034296130f14123d5de71fa61 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Thu, 26 Aug 2021 20:42:31 +0300 Subject: [PATCH] PCem v17 merge --- gfxboard.cpp | 1 + pcem/386.cpp | 18 +- pcem/386_common.cpp | 3 + pcem/386_common.h | 5 +- pcem/386_dynarec.cpp | 666 ++--- pcem/386_ops.h | 332 ++- pcem/808x.cpp | 4 +- pcem/codegen.h | 2 + pcem/codegen_backend_x86-64.h | 2 + pcem/codegen_backend_x86.h | 2 + pcem/cpu.cpp | 373 ++- pcem/cpu.h | 29 +- pcem/f82c710_upc.h | 6 + pcem/i440bx.h | 2 + pcem/ibm.h | 20 +- pcem/keyboard_at.cpp | 33 +- pcem/keyboard_at.h | 1 + pcem/mem.cpp | 62 +- pcem/mem.h | 5 +- pcem/mouse_ps2.cpp | 11 +- pcem/nvr.cpp | 8 + pcem/paths.h | 2 + pcem/pcemglue.cpp | 14 +- pcem/pic.cpp | 89 +- pcem/serial.cpp | 8 + pcem/serial.h | 2 + pcem/vid_cl5429.cpp | 47 +- pcem/vid_s3.cpp | 55 +- pcem/vid_s3_virge.cpp | 58 +- pcem/vid_svga.cpp | 50 +- pcem/vid_svga.h | 15 +- pcem/vid_svga_render.cpp | 674 +++-- pcem/vid_svga_render.h | 4 +- pcem/vid_svga_render_remap.h | 129 + pcem/vid_voodoo.cpp | 9 + pcem/vid_voodoo_banshee.cpp | 57 +- pcem/vid_voodoo_banshee.h | 1 - pcem/vid_voodoo_blitter.cpp | 6 +- pcem/vid_voodoo_common.h | 3 + pcem/vid_voodoo_dither.h | 5144 +++++++++++++++++++++++++++++++++ pcem/vid_voodoo_regs.h | 3 + pcem/vid_voodoo_render.cpp | 19 +- pcem/vid_voodoo_render.h | 1 - pcem/x86.h | 48 +- pcem/x86_ops.h | 7 + pcem/x86_ops_cyrix.h | 274 ++ pcem/x86_ops_flag.h | 6 +- pcem/x86_ops_int.h | 2 +- pcem/x86_ops_io.h | 26 +- pcem/x86_ops_misc.h | 36 + pcem/x86_ops_mmx_mov.h | 48 +- pcem/x86_ops_pmode.h | 19 +- pcem/x86_ops_ret.h | 4 +- pcem/x86seg.cpp | 390 ++- pcem/x87_ops_misc.h | 5 +- 55 files changed, 8051 insertions(+), 789 deletions(-) create mode 100644 pcem/f82c710_upc.h create mode 100644 pcem/i440bx.h create mode 100644 pcem/vid_svga_render_remap.h create mode 100644 pcem/x86_ops_cyrix.h diff --git a/gfxboard.cpp b/gfxboard.cpp index 72dab22c..14fe7ab7 100644 --- a/gfxboard.cpp +++ b/gfxboard.cpp @@ -3090,6 +3090,7 @@ static void gfxboard_free_board(struct rtggfxboard *gb) if (gb->pcemobject) { gb->pcemdev->close(gb->pcemobject); gb->pcemobject = NULL; + gb->pcemobject2 = NULL; } } if (gb->vram && gb->gfxmem_bank->baseaddr) { diff --git a/pcem/386.cpp b/pcem/386.cpp index e99ef1f6..85b22f47 100644 --- a/pcem/386.cpp +++ b/pcem/386.cpp @@ -196,7 +196,7 @@ void exec386(int cycs) flags_rebuild(); // pclog("Abort\n"); // if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,abrt); - tempi = cpu_state.abrt; + tempi = cpu_state.abrt & ABRT_MASK; cpu_state.abrt = 0; x86_doabrt(tempi); if (cpu_state.abrt) @@ -214,12 +214,13 @@ void exec386(int cycs) } } } - ins_cycles -= cycles; - tsc += ins_cycles; - - cycdiff=oldcyc-cycles; - if (trap) + if (cpu_state.smi_pending) + { + cpu_state.smi_pending = 0; + x86_smi_enter(); + } + else if (trap) { flags_rebuild(); // oldpc=pc; @@ -286,6 +287,11 @@ void exec386(int cycs) ins++; insc++; + ins_cycles -= cycles; + tsc += ins_cycles; + + cycdiff=oldcyc-cycles; + if (timetolive) { timetolive--; diff --git a/pcem/386_common.cpp b/pcem/386_common.cpp index 8919652e..eecdaece 100644 --- a/pcem/386_common.cpp +++ b/pcem/386_common.cpp @@ -9,6 +9,9 @@ x86seg gdt, ldt, idt, tr; uint32_t cr2, cr3, cr4; uint32_t dr[8]; +uint16_t sysenter_cs; +uint32_t sysenter_eip, sysenter_esp; + uint32_t use32; int stack32; int optype; diff --git a/pcem/386_common.h b/pcem/386_common.h index c01b9c70..a78b6e9a 100644 --- a/pcem/386_common.h +++ b/pcem/386_common.h @@ -19,7 +19,10 @@ int checkio(int port); if (cpu_state.abrt) return 1; \ if (tempi) \ { \ - x86gpf(NULL,0); \ + if (cpu_state.eflags & VM_FLAG) \ + x86gpf_expected(NULL,0); \ + else \ + x86gpf(NULL,0); \ return 1; \ } \ } diff --git a/pcem/386_dynarec.cpp b/pcem/386_dynarec.cpp index dc87772c..4fabbb26 100644 --- a/pcem/386_dynarec.cpp +++ b/pcem/386_dynarec.cpp @@ -1,6 +1,9 @@ #include #include #include +#if defined(__APPLE__) && defined(__aarch64__) +#include +#endif #include "ibm.h" #include "x86.h" #include "x86_ops.h" @@ -238,326 +241,370 @@ static void prefetch_flush() #define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG)) //#define CACHE_ON() 0 -static int cycles_main = 0; -void exec386_dynarec(int cycs) +int cpu_end_block_after_ins = 0; + + +static inline void exec_interpreter(void) { - uint8_t temp; - uint32_t addr; - int tempi; - int cycdiff; - int oldcyc; - int cyc_period = cycs / 2000; /*5us*/ + cpu_block_end = 0; + x86_was_reset = 0; +// if (output) pclog("Interpret block at %04x:%04x %04x %04x %04x %04x %04x %04x %04x\n", CS, pc, AX, BX, CX, DX, SI, DI, SP); + while (!cpu_block_end) + { + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; - cycles_main += cycs; - while (cycles_main > 0) + cpu_state.ea_seg = &cpu_state.seg_ds; + cpu_state.ssegs = 0; + + fetchdat = fastreadl(cs + cpu_state.pc); + + if (!cpu_state.abrt) + { + uint8_t opcode = fetchdat & 0xFF; + fetchdat >>= 8; + trap = cpu_state.flags & T_FLAG; + +// if (output == 3) +// pclog("int %04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0x8f13f], ram[0x8f13e], ram[0x8f141], ram[0x8f140]); + + cpu_state.pc++; + x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); + } + + if (((cs + cpu_state.pc) >> 12) != pccache) + CPU_BLOCK_END(); + + if (cpu_state.abrt) + CPU_BLOCK_END(); + if (cpu_state.smi_pending) + CPU_BLOCK_END(); + if (trap) + CPU_BLOCK_END(); + if (nmi && nmi_enable && nmi_mask) + CPU_BLOCK_END(); + if (cpu_end_block_after_ins) + { + cpu_end_block_after_ins--; + if (!cpu_end_block_after_ins) + CPU_BLOCK_END(); + } + + ins++; + insc++; + } + + if (trap) { - int cycles_start; - - cycles += cyc_period; - cycles_start = cycles; + trap = 0; + cpu_state.oldpc = cpu_state.pc; + x86_int(1); + } - while (cycles>0) + cpu_end_block_after_ins = 0; +} + +static inline void exec_recompiler(void) +{ + uint32_t phys_addr = get_phys(cs+cpu_state.pc); + int hash = HASH(phys_addr); + codeblock_t *block = &codeblock[codeblock_hash[hash]]; + int valid_block = 0; + + if (!cpu_state.abrt) + { + page_t *page = &pages[phys_addr >> 12]; + + /*Block must match current CS, PC, code segment size, + and physical address. The physical address check will + also catch any page faults at this stage*/ + valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) && + (block->phys == phys_addr) && !((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && + ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)); + if (!valid_block) { - oldcyc=cycles; -// if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x\n", CS, pc, SS,ESP); - if (!CACHE_ON()) /*Interpret block*/ + uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); + int byte_offset = (phys_addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; + uint64_t byte_mask = 1ull << (PAGE_BYTE_MASK_MASK & 0x3f); + + if ((page->code_present_mask & mask) || (page->byte_code_present_mask[byte_offset] & byte_mask)) { - cpu_block_end = 0; - x86_was_reset = 0; -// if (output) pclog("Interpret block at %04x:%04x %04x %04x %04x %04x %04x %04x %04x\n", CS, pc, AX, BX, CX, DX, SI, DI, SP); - while (!cpu_block_end) + /*Walk page tree to see if we find the correct block*/ + codeblock_t *new_block = codeblock_tree_find(phys_addr, cs); + if (new_block) { - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; + valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) && + (new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && + ((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)); + if (valid_block) + { + block = new_block; + codeblock_hash[hash] = get_block_nr(block); + } + } + } + } - cpu_state.ea_seg = &cpu_state.seg_ds; - cpu_state.ssegs = 0; - - fetchdat = fastreadl(cs + cpu_state.pc); + if (valid_block && (block->page_mask & *block->dirty_mask)) + { + codegen_check_flush(page, page->dirty_mask, phys_addr); + if (block->pc == BLOCK_PC_INVALID) + valid_block = 0; + else if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + block->flags &= ~CODEBLOCK_WAS_RECOMPILED; + } + if (valid_block && block->page_mask2) + { + /*We don't want the second page to cause a page + fault at this stage - that would break any + code crossing a page boundary where the first + page is present but the second isn't. Instead + allow the first page to be interpreted and for + the page fault to occur when the page boundary + is actually crossed.*/ + uint32_t phys_addr_2 = get_phys_noabrt(block->pc + ((block->flags & CODEBLOCK_BYTE_MASK) ? 0x40 : 0x400)); + page_t *page_2 = &pages[phys_addr_2 >> 12]; + if ((block->phys_2 ^ phys_addr_2) & ~0xfff) + valid_block = 0; + else if (block->page_mask2 & *block->dirty_mask2) + { + codegen_check_flush(page_2, page_2->dirty_mask, phys_addr_2); + if (block->pc == BLOCK_PC_INVALID) + valid_block = 0; + else if (block->flags & CODEBLOCK_IN_DIRTY_LIST) + block->flags &= ~CODEBLOCK_WAS_RECOMPILED; + } + } + if (valid_block && (block->flags & CODEBLOCK_IN_DIRTY_LIST)) + { + block->flags &= ~CODEBLOCK_WAS_RECOMPILED; + if (block->flags & CODEBLOCK_BYTE_MASK) + block->flags |= CODEBLOCK_NO_IMMEDIATES; + else + block->flags |= CODEBLOCK_BYTE_MASK; + } + if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7)) + { + /*FPU top-of-stack does not match the value this block was compiled + with, re-compile using dynamic top-of-stack*/ + block->flags &= ~(CODEBLOCK_STATIC_TOP | CODEBLOCK_WAS_RECOMPILED); + } + } - if (!cpu_state.abrt) - { - uint8_t opcode = fetchdat & 0xFF; - fetchdat >>= 8; - trap = cpu_state.flags & T_FLAG; + if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED)) + { + void (*code)() = (void(*)(void)) & block->data[BLOCK_START]; -// if (output == 3) -// pclog("int %04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0x8f13f], ram[0x8f13e], ram[0x8f141], ram[0x8f140]); +// if (output) pclog("Run block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%08x %04x %08x %08x %016llx %08x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, get_phys(cs+pc), block->phys, block->page_mask, block->endpc); - cpu_state.pc++; - x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); - } + inrecomp=1; + code(); + inrecomp=0; - if (((cs + cpu_state.pc) >> 12) != pccache) - CPU_BLOCK_END(); + cpu_recomp_blocks++; + } + else if (valid_block && !cpu_state.abrt) + { + uint32_t start_pc = cs+cpu_state.pc; + const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000; - if (cpu_state.abrt) - CPU_BLOCK_END(); - if (trap) - CPU_BLOCK_END(); - if (nmi && nmi_enable && nmi_mask) - CPU_BLOCK_END(); - - ins++; - insc++; - } + cpu_block_end = 0; + x86_was_reset = 0; + + cpu_new_blocks++; + +#if defined(__APPLE__) && defined(__aarch64__) + pthread_jit_write_protect_np(0); +#endif + codegen_block_start_recompile(block); + codegen_in_recompile = 1; + +// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]); + while (!cpu_block_end) + { + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; + + cpu_state.ea_seg = &cpu_state.seg_ds; + cpu_state.ssegs = 0; + + fetchdat = fastreadl(cs + cpu_state.pc); + + if (!cpu_state.abrt) + { + uint8_t opcode = fetchdat & 0xFF; + fetchdat >>= 8; + +// if (output == 3) +// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache); + + cpu_state.pc++; + + codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc-1); + + x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); + + if (x86_was_reset) + break; } - else + + /*Cap source code at 4000 bytes per block; this + will prevent any block from spanning more than + 2 pages. In practice this limit will never be + hit, as host block size is only 2kB*/ + if (((cs+cpu_state.pc) - start_pc) >= max_block_size) + CPU_BLOCK_END(); + if (cpu_state.flags & T_FLAG) + CPU_BLOCK_END(); + if (cpu_state.smi_pending) + CPU_BLOCK_END(); + if (nmi && nmi_enable && nmi_mask) + CPU_BLOCK_END(); + + if (cpu_end_block_after_ins) { - uint32_t phys_addr = get_phys(cs+cpu_state.pc); - int hash = HASH(phys_addr); - codeblock_t *block = &codeblock[codeblock_hash[hash]]; - int valid_block = 0; + cpu_end_block_after_ins--; + if (!cpu_end_block_after_ins) + CPU_BLOCK_END(); + } - if (!cpu_state.abrt) - { - page_t *page = &pages[phys_addr >> 12]; - - /*Block must match current CS, PC, code segment size, - and physical address. The physical address check will - also catch any page faults at this stage*/ - valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) && - (block->phys == phys_addr) && !((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && - ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)); - if (!valid_block) - { - uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK); - int byte_offset = (phys_addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK; - uint64_t byte_mask = 1ull << (PAGE_BYTE_MASK_MASK & 0x3f); - - if ((page->code_present_mask & mask) || (page->byte_code_present_mask[byte_offset] & byte_mask)) - { - /*Walk page tree to see if we find the correct block*/ - codeblock_t *new_block = codeblock_tree_find(phys_addr, cs); - if (new_block) - { - valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) && - (new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) && - ((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)); - if (valid_block) - { - block = new_block; - codeblock_hash[hash] = get_block_nr(block); - } - } - } - } + if (cpu_state.abrt) + { + if (!(cpu_state.abrt & ABRT_EXPECTED)) + codegen_block_remove(); + CPU_BLOCK_END(); + } - if (valid_block && (block->page_mask & *block->dirty_mask)) - { - codegen_check_flush(page, page->dirty_mask, phys_addr); - if (block->pc == BLOCK_PC_INVALID) - valid_block = 0; - else if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - block->flags &= ~CODEBLOCK_WAS_RECOMPILED; - } - if (valid_block && block->page_mask2) - { - /*We don't want the second page to cause a page - fault at this stage - that would break any - code crossing a page boundary where the first - page is present but the second isn't. Instead - allow the first page to be interpreted and for - the page fault to occur when the page boundary - is actually crossed.*/ - uint32_t phys_addr_2 = get_phys_noabrt(block->pc + ((block->flags & CODEBLOCK_BYTE_MASK) ? 0x40 : 0x400)); - page_t *page_2 = &pages[phys_addr_2 >> 12]; - if ((block->phys_2 ^ phys_addr_2) & ~0xfff) - valid_block = 0; - else if (block->page_mask2 & *block->dirty_mask2) - { - codegen_check_flush(page_2, page_2->dirty_mask, phys_addr_2); - if (block->pc == BLOCK_PC_INVALID) - valid_block = 0; - else if (block->flags & CODEBLOCK_IN_DIRTY_LIST) - block->flags &= ~CODEBLOCK_WAS_RECOMPILED; - } - } - if (valid_block && (block->flags & CODEBLOCK_IN_DIRTY_LIST)) - { - block->flags &= ~CODEBLOCK_WAS_RECOMPILED; - if (block->flags & CODEBLOCK_BYTE_MASK) - block->flags |= CODEBLOCK_NO_IMMEDIATES; - else - block->flags |= CODEBLOCK_BYTE_MASK; - } - if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7)) - { - /*FPU top-of-stack does not match the value this block was compiled - with, re-compile using dynamic top-of-stack*/ - block->flags &= ~(CODEBLOCK_STATIC_TOP | CODEBLOCK_WAS_RECOMPILED); - } - } + ins++; + insc++; + } + cpu_end_block_after_ins = 0; - if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED)) - { - void (*code)() = (void(*)(void))&block->data[BLOCK_START]; + if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset) + codegen_block_end_recompile(block); -// if (output) pclog("Run block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%08x %04x %08x %08x %016llx %08x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, get_phys(cs+pc), block->phys, block->page_mask, block->endpc); + if (x86_was_reset) + codegen_reset(); - inrecomp=1; - code(); - inrecomp=0; + codegen_in_recompile = 0; +#if defined(__APPLE__) && defined(__aarch64__) + pthread_jit_write_protect_np(1); +#endif + } + else if (!cpu_state.abrt) + { + /*Mark block but do not recompile*/ + uint32_t start_pc = cs+cpu_state.pc; + const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000; - cpu_recomp_blocks++; - } - else if (valid_block && !cpu_state.abrt) - { - uint32_t start_pc = cs+cpu_state.pc; - const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000; - - cpu_block_end = 0; - x86_was_reset = 0; - - cpu_new_blocks++; - - codegen_block_start_recompile(block); - codegen_in_recompile = 1; - -// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]); - while (!cpu_block_end) - { - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; + cpu_block_end = 0; + x86_was_reset = 0; - cpu_state.ea_seg = &cpu_state.seg_ds; - cpu_state.ssegs = 0; - - fetchdat = fastreadl(cs + cpu_state.pc); - - if (!cpu_state.abrt) - { - uint8_t opcode = fetchdat & 0xFF; - fetchdat >>= 8; - - trap = cpu_state.flags & T_FLAG; - -// if (output == 3) -// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache); - - cpu_state.pc++; - - codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc-1); - - x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); - - if (x86_was_reset) - break; - } - - /*Cap source code at 4000 bytes per block; this - will prevent any block from spanning more than - 2 pages. In practice this limit will never be - hit, as host block size is only 2kB*/ - if (((cs+cpu_state.pc) - start_pc) >= max_block_size) - CPU_BLOCK_END(); - - if (trap) - CPU_BLOCK_END(); - - if (nmi && nmi_enable && nmi_mask) - CPU_BLOCK_END(); - - if (cpu_state.abrt) - { - codegen_block_remove(); - CPU_BLOCK_END(); - } - - ins++; - insc++; - } - - if (!cpu_state.abrt && !x86_was_reset) - codegen_block_end_recompile(block); - - if (x86_was_reset) - codegen_reset(); - - codegen_in_recompile = 0; - } - else if (!cpu_state.abrt) - { - /*Mark block but do not recompile*/ - uint32_t start_pc = cs+cpu_state.pc; - const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000; + codegen_block_init(phys_addr); - cpu_block_end = 0; - x86_was_reset = 0; +// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]); + while (!cpu_block_end) + { + cpu_state.oldpc = cpu_state.pc; + cpu_state.op32 = use32; - codegen_block_init(phys_addr); + cpu_state.ea_seg = &cpu_state.seg_ds; + cpu_state.ssegs = 0; -// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]); - while (!cpu_block_end) - { - cpu_state.oldpc = cpu_state.pc; - cpu_state.op32 = use32; + codegen_endpc = (cs + cpu_state.pc) + 8; + fetchdat = fastreadl(cs + cpu_state.pc); - cpu_state.ea_seg = &cpu_state.seg_ds; - cpu_state.ssegs = 0; - - codegen_endpc = (cs + cpu_state.pc) + 8; - fetchdat = fastreadl(cs + cpu_state.pc); - - if (!cpu_state.abrt) - { - uint8_t opcode = fetchdat & 0xFF; - fetchdat >>= 8; - - trap = cpu_state.flags & T_FLAG; - -// if (output == 3) -// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache); - - cpu_state.pc++; - - x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); - - if (x86_was_reset) - break; - } - - /*Cap source code at 4000 bytes per block; this - will prevent any block from spanning more than - 2 pages. In practice this limit will never be - hit, as host block size is only 2kB*/ - if (((cs+cpu_state.pc) - start_pc) >= max_block_size) - CPU_BLOCK_END(); - - if (trap) - CPU_BLOCK_END(); - - if (nmi && nmi_enable && nmi_mask) - CPU_BLOCK_END(); - - if (cpu_state.abrt) - { - codegen_block_remove(); - CPU_BLOCK_END(); - } - - ins++; - insc++; - } - - if (!cpu_state.abrt && !x86_was_reset) - codegen_block_end(); - - if (x86_was_reset) - codegen_reset(); - } - else - cpu_state.oldpc = cpu_state.pc; + if (!cpu_state.abrt) + { + uint8_t opcode = fetchdat & 0xFF; + fetchdat >>= 8; +// if (output == 3) +// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, cs+pc, pccache); + + cpu_state.pc++; + + x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat); + + if (x86_was_reset) + break; } - cycdiff=oldcyc-cycles; - tsc += cycdiff; + /*Cap source code at 4000 bytes per block; this + will prevent any block from spanning more than + 2 pages. In practice this limit will never be + hit, as host block size is only 2kB*/ + if (((cs+cpu_state.pc) - start_pc) >= max_block_size) + CPU_BLOCK_END(); + if (cpu_state.flags & T_FLAG) + CPU_BLOCK_END(); + if (cpu_state.smi_pending) + CPU_BLOCK_END(); + if (nmi && nmi_enable && nmi_mask) + CPU_BLOCK_END(); + + if (cpu_end_block_after_ins) + { + cpu_end_block_after_ins--; + if (!cpu_end_block_after_ins) + CPU_BLOCK_END(); + } + + if (cpu_state.abrt) + { + if (!(cpu_state.abrt & ABRT_EXPECTED)) + codegen_block_remove(); + CPU_BLOCK_END(); + } + + ins++; + insc++; + } + cpu_end_block_after_ins = 0; + +// if (!cpu_state.abrt && !x86_was_reset) + if ((!cpu_state.abrt || (cpu_state.abrt & ABRT_EXPECTED)) && !x86_was_reset) + codegen_block_end(); + + if (x86_was_reset) + codegen_reset(); + } + else + cpu_state.oldpc = cpu_state.pc; + +} + + +int cycles_main = 0; +void exec386_dynarec(int cycs) +{ + uint8_t temp; + int tempi; + int cycdiff; + int oldcyc; + int cyc_period = cycs / 2000; /*5us*/ + + cycles_main += cycs; + while (cycles_main > 0) + { + int cycles_start; + + cycles += cyc_period; + cycles_start = cycles; + + while (cycles>0) + { + oldcyc=cycles; +// if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x\n", CS, pc, SS,ESP); + if (!CACHE_ON()) /*Interpret block*/ + exec_interpreter(); + else + exec_recompiler(); if (cpu_state.abrt) { flags_rebuild(); - tempi = cpu_state.abrt; + tempi = cpu_state.abrt & ABRT_MASK; cpu_state.abrt = 0; x86_doabrt(tempi); if (cpu_state.abrt) @@ -576,26 +623,10 @@ void exec386_dynarec(int cycs) } } - if (trap) + if (cpu_state.smi_pending) { - trap = 0; - flags_rebuild(); - if (msw&1) - { - pmodeint(1,0); - } - else - { - writememw(ss,(SP-2)&0xFFFF,cpu_state.flags); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - addr = (1 << 2) + idt.base; - cpu_state.flags &= ~I_FLAG; - cpu_state.flags &= ~T_FLAG; - cpu_state.pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - } + cpu_state.smi_pending = 0; + x86_smi_enter(); } else if (nmi && nmi_enable && nmi_mask) { @@ -614,27 +645,14 @@ void exec386_dynarec(int cycs) temp=picinterrupt(); if (temp!=0xFF) { + cpu_state.oldpc = cpu_state.pc; + x86_int(temp); // pclog("IRQ %02X %04X:%04X %04X:%04X\n", temp, SS, SP, CS, pc); - CPU_BLOCK_END(); - flags_rebuild(); - if (msw&1) - { - pmodeint(temp,0); - } - else - { - writememw(ss,(SP-2)&0xFFFF,cpu_state.flags); - writememw(ss,(SP-4)&0xFFFF,CS); - writememw(ss,(SP-6)&0xFFFF,cpu_state.pc); - SP-=6; - addr=temp<<2; - cpu_state.flags &= ~I_FLAG; - cpu_state.flags &= ~T_FLAG; - cpu_state.pc=readmemw(0,addr); - loadcs(readmemw(0,addr+2)); - } } } + + cycdiff=oldcyc-cycles; + tsc += cycdiff; } if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc)) diff --git a/pcem/386_ops.h b/pcem/386_ops.h index 5c73ccb4..c48863bd 100644 --- a/pcem/386_ops.h +++ b/pcem/386_ops.h @@ -119,6 +119,7 @@ static int ILLEGAL(uint32_t fetchdat) #include "x86_ops_bit.h" #include "x86_ops_bitscan.h" #include "x86_ops_call.h" +#include "x86_ops_cyrix.h" #include "x86_ops_flag.h" #include "x86_ops_fpu.h" #include "x86_ops_inc_dec.h" @@ -381,7 +382,7 @@ OpFn OP_TABLE(winchip_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -403,7 +404,7 @@ OpFn OP_TABLE(winchip_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -425,7 +426,7 @@ OpFn OP_TABLE(winchip_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -447,7 +448,7 @@ OpFn OP_TABLE(winchip_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -472,7 +473,7 @@ OpFn OP_TABLE(winchip2_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -494,7 +495,7 @@ OpFn OP_TABLE(winchip2_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -516,7 +517,7 @@ OpFn OP_TABLE(winchip2_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -538,7 +539,7 @@ OpFn OP_TABLE(winchip2_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -563,7 +564,7 @@ OpFn OP_TABLE(pentium_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -585,7 +586,7 @@ OpFn OP_TABLE(pentium_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -607,7 +608,7 @@ OpFn OP_TABLE(pentium_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -629,7 +630,98 @@ OpFn OP_TABLE(pentium_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, + +/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; + +OpFn OP_TABLE(c6x86_0f)[1024] = +{ + /*16-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, + +/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opSMINT, ILLEGAL, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, + +/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*16-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opSMINT, ILLEGAL, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, + +/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opSMINT, ILLEGAL, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -638,7 +730,7 @@ OpFn OP_TABLE(pentium_0f)[1024] = /*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, }; -OpFn OP_TABLE(pentiummmx_0f)[1024] = +OpFn OP_TABLE(pentiummmx_0f)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ @@ -654,7 +746,7 @@ OpFn OP_TABLE(pentiummmx_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -676,7 +768,7 @@ OpFn OP_TABLE(pentiummmx_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -698,7 +790,7 @@ OpFn OP_TABLE(pentiummmx_0f)[1024] = /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -720,7 +812,7 @@ OpFn OP_TABLE(pentiummmx_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -736,16 +828,16 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] = /*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_w_a16, opCMOVNO_w_a16, opCMOVB_w_a16, opCMOVNB_w_a16, opCMOVE_w_a16, opCMOVNE_w_a16, opCMOVBE_w_a16, opCMOVNBE_w_a16,opCMOVS_w_a16, opCMOVNS_w_a16, opCMOVP_w_a16, opCMOVNP_w_a16, opCMOVL_w_a16, opCMOVNL_w_a16, opCMOVLE_w_a16, opCMOVNLE_w_a16, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a16_cx,opMOVQ_mm_q_a16, /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, /*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -758,16 +850,16 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] = /*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a16, opWRSHR_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_l_a16, opCMOVNO_l_a16, opCMOVB_l_a16, opCMOVNB_l_a16, opCMOVE_l_a16, opCMOVNE_l_a16, opCMOVBE_l_a16, opCMOVNBE_l_a16,opCMOVS_l_a16, opCMOVNS_l_a16, opCMOVP_l_a16, opCMOVNP_l_a16, opCMOVL_l_a16, opCMOVNL_l_a16, opCMOVLE_l_a16, opCMOVNLE_l_a16, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a16_cx,opMOVQ_mm_q_a16, /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, /*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, /*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -780,16 +872,16 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] = /*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_w_a32, opCMOVNO_w_a32, opCMOVB_w_a32, opCMOVNB_w_a32, opCMOVE_w_a32, opCMOVNE_w_a32, opCMOVBE_w_a32, opCMOVNBE_w_a32,opCMOVS_w_a32, opCMOVNS_w_a32, opCMOVP_w_a32, opCMOVNP_w_a32, opCMOVL_w_a32, opCMOVNL_w_a32, opCMOVLE_w_a32, opCMOVNLE_w_a32, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, -/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, opSVDC_a32, opRSDC_a32, opSVLDT_a32, opRSLDT_a32, opSVTS_a32, opRSTS_a32, opMOVD_mm_l_a32_cx,opMOVQ_mm_q_a32, /*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, /*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -802,7 +894,189 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] = /*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, -/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, ILLEGAL, ILLEGAL, opRDSHR_a32, opWRSHR_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ opCMOVO_l_a32, opCMOVNO_l_a32, opCMOVB_l_a32, opCMOVNB_l_a32, opCMOVE_l_a32, opCMOVNE_l_a32, opCMOVBE_l_a32, opCMOVNBE_l_a32,opCMOVS_l_a32, opCMOVNS_l_a32, opCMOVP_l_a32, opCMOVNP_l_a32, opCMOVL_l_a32, opCMOVNL_l_a32, opCMOVLE_l_a32, opCMOVNLE_l_a32, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, opSVDC_a16, opRSDC_a16, opSVLDT_a16, opRSLDT_a16, opSVTS_a16, opRSTS_a16, opMOVD_mm_l_a32_cx,opMOVQ_mm_q_a32, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, + +/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, +/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, +/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, +}; + +OpFn OP_TABLE(pentiumpro_0f)[1024] = +{ + /*16-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ opCMOVO_w_a16, opCMOVNO_w_a16, opCMOVB_w_a16, opCMOVNB_w_a16, opCMOVE_w_a16, opCMOVNE_w_a16, opCMOVBE_w_a16, opCMOVNBE_w_a16,opCMOVS_w_a16, opCMOVNS_w_a16, opCMOVP_w_a16, opCMOVNP_w_a16, opCMOVL_w_a16, opCMOVNL_w_a16, opCMOVLE_w_a16, opCMOVNLE_w_a16, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, + +/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ opCMOVO_l_a16, opCMOVNO_l_a16, opCMOVB_l_a16, opCMOVNB_l_a16, opCMOVE_l_a16, opCMOVNE_l_a16, opCMOVBE_l_a16, opCMOVNBE_l_a16,opCMOVS_l_a16, opCMOVNS_l_a16, opCMOVP_l_a16, opCMOVNP_l_a16, opCMOVL_l_a16, opCMOVNL_l_a16, opCMOVLE_l_a16, opCMOVNLE_l_a16, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, + +/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*16-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ opCMOVO_w_a32, opCMOVNO_w_a32, opCMOVB_w_a32, opCMOVNB_w_a32, opCMOVE_w_a32, opCMOVNE_w_a32, opCMOVBE_w_a32, opCMOVNBE_w_a32,opCMOVS_w_a32, opCMOVNS_w_a32, opCMOVP_w_a32, opCMOVNP_w_a32, opCMOVL_w_a32, opCMOVNL_w_a32, opCMOVLE_w_a32, opCMOVNLE_w_a32, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, + +/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + + /*32-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ opCMOVO_l_a32, opCMOVNO_l_a32, opCMOVB_l_a32, opCMOVNB_l_a32, opCMOVE_l_a32, opCMOVNE_l_a32, opCMOVBE_l_a32, opCMOVNBE_l_a32,opCMOVS_l_a32, opCMOVNS_l_a32, opCMOVP_l_a32, opCMOVNP_l_a32, opCMOVL_l_a32, opCMOVNL_l_a32, opCMOVLE_l_a32, opCMOVNLE_l_a32, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, + +/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +}; + +OpFn OP_TABLE(pentium2_0f)[1024] = +{ + /*16-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ opCMOVO_w_a16, opCMOVNO_w_a16, opCMOVB_w_a16, opCMOVNB_w_a16, opCMOVE_w_a16, opCMOVNE_w_a16, opCMOVBE_w_a16, opCMOVNBE_w_a16,opCMOVS_w_a16, opCMOVNS_w_a16, opCMOVP_w_a16, opCMOVNP_w_a16, opCMOVL_w_a16, opCMOVNL_w_a16, opCMOVLE_w_a16, opCMOVNLE_w_a16, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL, + +/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, +/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, +/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, + + /*32-bit data, 16-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, opHINTNOP_a16, +/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ opCMOVO_l_a16, opCMOVNO_l_a16, opCMOVB_l_a16, opCMOVNB_l_a16, opCMOVE_l_a16, opCMOVNE_l_a16, opCMOVBE_l_a16, opCMOVNBE_l_a16,opCMOVS_l_a16, opCMOVNS_l_a16, opCMOVP_l_a16, opCMOVNP_l_a16, opCMOVL_l_a16, opCMOVNL_l_a16, opCMOVLE_l_a16, opCMOVNLE_l_a16, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16, + +/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, +/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16, +/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16, + +/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16, +/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16, +/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL, + + /*16-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, + +/*40*/ opCMOVO_w_a32, opCMOVNO_w_a32, opCMOVB_w_a32, opCMOVNB_w_a32, opCMOVE_w_a32, opCMOVNE_w_a32, opCMOVBE_w_a32, opCMOVNBE_w_a32,opCMOVS_w_a32, opCMOVNS_w_a32, opCMOVP_w_a32, opCMOVNP_w_a32, opCMOVL_w_a32, opCMOVNL_w_a32, opCMOVLE_w_a32, opCMOVNLE_w_a32, +/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32, +/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32, + +/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w, +/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, +/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, opRSM, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32, +/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL, + +/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, +/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32, +/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32, +/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, + + /*32-bit data, 32-bit addr*/ +/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ +/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, opHINTNOP_a32, +/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, +/*30*/ opWRMSR, opRDTSC, opRDMSR, opRDPMC, opSYSENTER, opSYSEXIT, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, /*40*/ opCMOVO_l_a32, opCMOVNO_l_a32, opCMOVB_l_a32, opCMOVNB_l_a32, opCMOVE_l_a32, opCMOVNE_l_a32, opCMOVBE_l_a32, opCMOVNBE_l_a32,opCMOVS_l_a32, opCMOVNS_l_a32, opCMOVP_l_a32, opCMOVNP_l_a32, opCMOVL_l_a32, opCMOVNL_l_a32, opCMOVLE_l_a32, opCMOVNLE_l_a32, /*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, @@ -811,7 +1085,7 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] = /*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l, /*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32, -/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, +/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, opRSM, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32, /*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32, /*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI, @@ -820,7 +1094,7 @@ OpFn OP_TABLE(c6x86mx_0f)[1024] = /*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL, }; -OpFn OP_TABLE(286)[1024] = +OpFn OP_TABLE(286)[1024] = { /*16-bit data, 16-bit addr*/ /* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/ diff --git a/pcem/808x.cpp b/pcem/808x.cpp index 99eba41f..039f82e9 100644 --- a/pcem/808x.cpp +++ b/pcem/808x.cpp @@ -524,7 +524,7 @@ void dumpregs() putc(readmembl(c+0x80000000),f); } fclose(f); - pclog("Dumping done\n"); + pclog("Dumping done\n"); /* f=fopen("rram6.dmp","wb"); for (c=0;c<0x1000000;c++) putc(readmemb(c+0xBF000000),f); fclose(f);*/ @@ -584,6 +584,7 @@ void dumpregs() { printf("386 in %s mode stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit"); printf("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n",cr0,cr2,cr3, cr4); + pclog("SMBASE=%08x\n", cpu_state.smbase); } printf("Entries in readlookup : %i writelookup : %i\n",readlnum,writelnum); for (c=0;c<1024*1024;c++) @@ -644,6 +645,7 @@ void resetx86() x86seg_reset(); codegen_reset(); x86_was_reset = 1; + cpu_state.smbase = 0x30000; } void softresetx86() diff --git a/pcem/codegen.h b/pcem/codegen.h index d4f2563f..ac5c0bc3 100644 --- a/pcem/codegen.h +++ b/pcem/codegen.h @@ -374,7 +374,9 @@ extern codegen_timing_t codegen_timing_686; extern codegen_timing_t codegen_timing_486; extern codegen_timing_t codegen_timing_winchip; extern codegen_timing_t codegen_timing_winchip2; +extern codegen_timing_t codegen_timing_cyrixiii; extern codegen_timing_t codegen_timing_k6; +extern codegen_timing_t codegen_timing_p6; void codegen_timing_set(codegen_timing_t *timing); diff --git a/pcem/codegen_backend_x86-64.h b/pcem/codegen_backend_x86-64.h index 70e953a6..ccc526b3 100644 --- a/pcem/codegen_backend_x86-64.h +++ b/pcem/codegen_backend_x86-64.h @@ -10,3 +10,5 @@ #define HASH(l) ((l) & 0x1ffff) #define BLOCK_MAX 0x3c0 + +#define CODEGEN_BACKEND_HAS_MOV_IMM diff --git a/pcem/codegen_backend_x86.h b/pcem/codegen_backend_x86.h index a5aec727..582e4643 100644 --- a/pcem/codegen_backend_x86.h +++ b/pcem/codegen_backend_x86.h @@ -10,3 +10,5 @@ #define HASH(l) ((l) & 0x1ffff) #define BLOCK_MAX 0x3c0 + +#define CODEGEN_BACKEND_HAS_MOV_IMM diff --git a/pcem/cpu.cpp b/pcem/cpu.cpp index 6dbd3406..37c6d51f 100644 --- a/pcem/cpu.cpp +++ b/pcem/cpu.cpp @@ -73,6 +73,7 @@ enum CPUID_TSC = (1 << 4), CPUID_MSR = (1 << 5), CPUID_CMPXCHG8B = (1 << 8), + CPUID_SEP = (1 << 11), CPUID_CMOV = (1 << 15), CPUID_MMX = (1 << 23) }; @@ -350,6 +351,7 @@ void cpu_set() timing_misaligned = 0; cpu_cyrix_alignment = 0; + cpu_CR4_mask = 0; switch (cpu_s->cpu_type) { @@ -810,7 +812,7 @@ void cpu_set() break; case CPU_Cx6x86: - x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f); + x86_setopcodes(ops_386, ops_c6x86_0f, dynarec_ops_386, dynarec_ops_c6x86_0f); timing_rr = 1; /*register dest - register src*/ timing_rm = 1; /*register dest - memory src*/ timing_mr = 2; /*memory dest - register src*/ @@ -1029,6 +1031,144 @@ void cpu_set() codegen_timing_set(&codegen_timing_k6); break; + case CPU_PENTIUMPRO: + x86_setopcodes(ops_386, ops_pentiumpro_0f, dynarec_ops_386, dynarec_ops_pentiumpro_0f); + x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; + x86_opcodes_da_a16 = ops_fpu_686_da_a16; + x86_opcodes_da_a32 = ops_fpu_686_da_a32; + x86_opcodes_db_a16 = ops_fpu_686_db_a16; + x86_opcodes_db_a32 = ops_fpu_686_db_a32; + x86_opcodes_df_a16 = ops_fpu_686_df_a16; + x86_opcodes_df_a32 = ops_fpu_686_df_a32; + timing_rr = 1; /*register dest - register src*/ + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 3; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 3; /*memory dest - register src long*/ + timing_mml = 3; + timing_bt = 0; /*branch taken*/ + timing_bnt = 2; /*branch not taken*/ + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; + timing_iret_rm = 7; + timing_iret_v86 = 27; /*unknown*/ + timing_iret_pm = 10; + timing_iret_pm_outer = 27; + timing_call_rm = 4; + timing_call_pm = 4; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; + timing_retf_rm = 4; + timing_retf_pm = 4; + timing_retf_pm_outer = 23; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; + timing_misaligned = 3; + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_CX8 | CPU_FEATURE_SYSCALL; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; + codegen_timing_set(&codegen_timing_p6); + break; + + case CPU_PENTIUM_2: + case CPU_CELERON: + case CPU_CELERON_A: + x86_setopcodes(ops_386, ops_pentium2_0f, dynarec_ops_386, dynarec_ops_pentium2_0f); + x86_dynarec_opcodes_da_a16 = dynarec_ops_fpu_686_da_a16; + x86_dynarec_opcodes_da_a32 = dynarec_ops_fpu_686_da_a32; + x86_dynarec_opcodes_db_a16 = dynarec_ops_fpu_686_db_a16; + x86_dynarec_opcodes_db_a32 = dynarec_ops_fpu_686_db_a32; + x86_dynarec_opcodes_df_a16 = dynarec_ops_fpu_686_df_a16; + x86_dynarec_opcodes_df_a32 = dynarec_ops_fpu_686_df_a32; + x86_opcodes_da_a16 = ops_fpu_686_da_a16; + x86_opcodes_da_a32 = ops_fpu_686_da_a32; + x86_opcodes_db_a16 = ops_fpu_686_db_a16; + x86_opcodes_db_a32 = ops_fpu_686_db_a32; + x86_opcodes_df_a16 = ops_fpu_686_df_a16; + x86_opcodes_df_a32 = ops_fpu_686_df_a32; + timing_rr = 1; /*register dest - register src*/ + timing_rm = 2; /*register dest - memory src*/ + timing_mr = 3; /*memory dest - register src*/ + timing_mm = 3; + timing_rml = 2; /*register dest - memory src long*/ + timing_mrl = 3; /*memory dest - register src long*/ + timing_mml = 3; + timing_bt = 0; /*branch taken*/ + timing_bnt = 2; /*branch not taken*/ + timing_int = 6; + timing_int_rm = 11; + timing_int_v86 = 54; + timing_int_pm = 25; + timing_int_pm_outer = 42; + timing_iret_rm = 7; + timing_iret_v86 = 27; /*unknown*/ + timing_iret_pm = 10; + timing_iret_pm_outer = 27; + timing_call_rm = 4; + timing_call_pm = 4; + timing_call_pm_gate = 22; + timing_call_pm_gate_inner = 44; + timing_retf_rm = 4; + timing_retf_pm = 4; + timing_retf_pm_outer = 23; + timing_jmp_rm = 3; + timing_jmp_pm = 3; + timing_jmp_pm_gate = 18; + timing_misaligned = 3; + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_CX8 | CPU_FEATURE_MMX | CPU_FEATURE_SYSCALL; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21); + cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE; + codegen_timing_set(&codegen_timing_p6); + break; + + case CPU_CYRIX_III: + x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f); + timing_rr = 1; /*register dest - register src*/ + timing_rm = 1; /*register dest - memory src*/ + timing_mr = 1; /*memory dest - register src*/ + timing_mm = 1; + timing_rml = 1; /*register dest - memory src long*/ + timing_mrl = 1; /*memory dest - register src long*/ + timing_mml = 1; + timing_bt = 1; /*branch taken*/ + timing_bnt = 1; /*branch not taken*/ + cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_3DNOW; + msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21); + cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE; + /*unknown*/ + timing_int_rm = 26; + timing_int_v86 = 82; + timing_int_pm = 44; + timing_int_pm_outer = 71; + timing_iret_rm = 7; + timing_iret_v86 = 26; + timing_iret_pm = 10; + timing_iret_pm_outer = 26; + timing_call_rm = 4; + timing_call_pm = 15; + timing_call_pm_gate = 26; + timing_call_pm_gate_inner = 35; + timing_retf_rm = 4; + timing_retf_pm = 7; + timing_retf_pm_outer = 23; + timing_jmp_rm = 5; + timing_jmp_pm = 7; + timing_jmp_pm_gate = 17; + timing_misaligned = 2; + cpu_cyrix_alignment = 1; + codegen_timing_set(&codegen_timing_cyrixiii); + break; + #endif default: @@ -1552,6 +1692,132 @@ void cpu_CPUID() break; } break; + + case CPU_PENTIUMPRO: + if (!EAX) + { + EAX = 0x00000002; + EBX = 0x756e6547; + EDX = 0x49656e69; + ECX = 0x6c65746e; + } + else if (EAX == 1) + { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_SEP; + } + else if (EAX == 2) + { + EAX = 0x03020101; + EBX = 0; + ECX = 0; + EDX = 0x06040a42; + } + else + EAX = EBX = ECX = EDX = 0; + break; + + case CPU_PENTIUM_2: + case CPU_CELERON: + case CPU_CELERON_A: + if (!EAX) + { + EAX = 0x00000002; + EBX = 0x756e6547; + EDX = 0x49656e69; + ECX = 0x6c65746e; + } + else if (EAX == 1) + { + EAX = CPUID; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_CMOV | CPUID_MMX | CPUID_SEP; + } + else if (EAX == 2) + { + EAX = 0x03020101; + EBX = 0; + ECX = 0; + if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_PENTIUM_2) + EDX = 0x08040c43; /*512kb L2 cache*/ + else if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_CELERON) + EDX = 0x08040c40; /*No L2 cache*/ + else + EDX = 0x08040c41; /*128kb L2 cache*/ + } + else + EAX = EBX = ECX = EDX = 0; + break; + + case CPU_CYRIX_III: + switch (EAX) + { + case 0: + EAX = 1; + EBX = 0x746e6543; /*CentaurHauls*/ + ECX = 0x736c7561; + EDX = 0x48727561; + break; + case 1: + EAX = models[model].cpu[cpu_manufacturer].cpus[cpu].cpuid_model; + EBX = ECX = 0; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; + if (cpu_has_feature(CPU_FEATURE_CX8)) + EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 9)) + EDX |= CPUID_MMX; + break; + case 0x80000000: + EAX = 0x80000006; + break; + case 0x80000001: + EAX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset; + EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR; + if (cpu_has_feature(CPU_FEATURE_CX8)) + EDX |= CPUID_CMPXCHG8B; + if (msr.fcr & (1 << 9)) + EDX |= CPUID_MMX; + if (cpu_has_feature(CPU_FEATURE_3DNOW)) + EDX |= CPUID_3DNOW; + break; + + case 0x80000002: /*Processor name string*/ + if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpuid_model >= 0x670) + { + EAX = 0x20414956; /*VIA Samuel 2*/ + EBX = 0x756d6153; + ECX = 0x32206c65; + EDX = 0x00000000; + } + else + { + EAX = 0x20414956; /*VIA SamuelM*/ + EBX = 0x756d6153; + ECX = 0x004d6c65; + EDX = 0x00000000; + } + break; + + case 0x80000005: /*Cache information*/ + EBX = 0x08800880; /*TLBs*/ + ECX = 0x40040120; /*L1 data cache*/ + EDX = 0x40020120; /*L1 instruction cache*/ + break; + + case 0x80000006: /*L2 Cache information*/ + if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpuid_model >= 0x670) + ECX = 0x40040120; /*L2 cache*/ + else + ECX = 0; + EAX = EBX = EDX = 0; + break; + + default: + EAX = EBX = ECX = EDX = 0; + break; + } + break; } } @@ -1561,6 +1827,7 @@ void cpu_RDMSR() { case CPU_WINCHIP: case CPU_WINCHIP2: + case CPU_CYRIX_III: EAX = EDX = 0; switch (ECX) { @@ -1627,6 +1894,32 @@ void cpu_RDMSR() break; } break; + case CPU_PENTIUMPRO: + case CPU_PENTIUM_2: + case CPU_CELERON: + case CPU_CELERON_A: + EAX = EDX = 0; + switch (ECX) + { + case 0x10: + EAX = tsc & 0xffffffff; + EDX = tsc >> 32; + break; + + case 0x174: + EAX = sysenter_cs; + EDX = 0; + break; + case 0x175: + EAX = sysenter_esp; + EDX = 0; + break; + case 0x176: + EAX = sysenter_eip; + EDX = 0; + break; + } + break; } } @@ -1636,6 +1929,7 @@ void cpu_WRMSR() { case CPU_WINCHIP: case CPU_WINCHIP2: + case CPU_CYRIX_III: switch (ECX) { case 0x02: @@ -1710,11 +2004,39 @@ void cpu_WRMSR() break; } break; + case CPU_PENTIUMPRO: + case CPU_PENTIUM_2: + case CPU_CELERON: + case CPU_CELERON_A: + switch (ECX) + { + case 0x10: + tsc = EAX | ((uint64_t)EDX << 32); + break; + + case 0x174: + sysenter_cs = EAX & 0xffff; + break; + case 0x175: + sysenter_esp = EAX; + break; + case 0x176: + sysenter_eip = EAX; + break; + } + break; } } static int cyrix_addr; +#define CCR1_USE_SMI (1 << 1) +#define CCR1_SMAC (1 << 2) +#define CCR1_SM3 (1 << 7) + +#define CCR3_SMI_LOCK (1 << 0) +#define CCR3_NMI_EN (1 << 1) + void cyrix_write(uint16_t addr, uint8_t val, void *priv) { if (!(addr & 1)) @@ -1725,14 +2047,46 @@ void cyrix_write(uint16_t addr, uint8_t val, void *priv) ccr0 = val; break; case 0xc1: /*CCR1*/ + if ((ccr3 & CCR3_SMI_LOCK) && !(cpu_cur_status & CPU_STATUS_SMM)) + val = (val & ~(CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)) | (ccr1 & (CCR1_USE_SMI | CCR1_SMAC | CCR1_SM3)); ccr1 = val; break; case 0xc2: /*CCR2*/ ccr2 = val; break; case 0xc3: /*CCR3*/ + if ((ccr3 & CCR3_SMI_LOCK) && !(cpu_cur_status & CPU_STATUS_SMM)) + val = (val & ~(CCR3_NMI_EN)) | (ccr3 & CCR3_NMI_EN) | CCR3_SMI_LOCK; ccr3 = val; break; + case 0xcd: + if (!(ccr3 & CCR3_SMI_LOCK) || (cpu_cur_status & CPU_STATUS_SMM)) + { + cyrix.arr[3].base = (cyrix.arr[3].base & ~0xff000000) | (val << 24); + cyrix.smhr &= ~SMHR_VALID; + } + break; + case 0xce: + if (!(ccr3 & CCR3_SMI_LOCK) || (cpu_cur_status & CPU_STATUS_SMM)) + { + cyrix.arr[3].base = (cyrix.arr[3].base & ~0x00ff0000) | (val << 16); + cyrix.smhr &= ~SMHR_VALID; + } + break; + case 0xcf: + if (!(ccr3 & CCR3_SMI_LOCK) || (cpu_cur_status & CPU_STATUS_SMM)) + { + cyrix.arr[3].base = (cyrix.arr[3].base & ~0x0000f000) | ((val & 0xf0) << 8); + if ((val & 0xf) == 0xf) + cyrix.arr[3].size = 1ull << 32; /*4 GB*/ + else if (val & 0xf) + cyrix.arr[3].size = 2048 << (val & 0xf); + else + cyrix.arr[3].size = 0; /*Disabled*/ + cyrix.smhr &= ~SMHR_VALID; + } + break; + case 0xe8: /*CCR4*/ if ((ccr3 & 0xf0) == 0x10) { @@ -1773,7 +2127,6 @@ uint8_t cyrix_read(uint16_t addr, void *priv) case 0xfe: return models[model].cpu[cpu_manufacturer].cpus[cpu].cyrix_id & 0xff; case 0xff: return models[model].cpu[cpu_manufacturer].cpus[cpu].cyrix_id >> 8; } - if ((cyrix_addr & ~0xf0) == 0xc0) return 0xff; if (cyrix_addr == 0x20 && models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_Cx5x86) return 0xff; } return 0xff; @@ -1854,9 +2207,25 @@ void cpu_set_turbo(int turbo) } } +int cpu_get_turbo() +{ + return cpu_turbo; +} + int cpu_get_speed() { if (cpu_turbo) return cpu_turbo_speed; return cpu_nonturbo_speed; } + +void cpu_set_nonturbo_divider(int divider) +{ + if (divider < 2) + cpu_set_turbo(1); + else + { + cpu_nonturbo_speed = cpu_turbo_speed / divider; + cpu_set_turbo(0); + } +} diff --git a/pcem/cpu.h b/pcem/cpu.h index b4dc2b66..d4bea605 100644 --- a/pcem/cpu.h +++ b/pcem/cpu.h @@ -41,11 +41,17 @@ extern int fpu_type; #define CPU_K6_3 25 #define CPU_K6_2P 26 #define CPU_K6_3P 27 +#define CPU_PENTIUMPRO 28 +#define CPU_PENTIUM_2 29 +#define CPU_CELERON 30 +#define CPU_CELERON_A 31 +#define CPU_CYRIX_III 32 #define MANU_INTEL 0 #define MANU_AMD 1 #define MANU_CYRIX 2 #define MANU_IDT 3 +#define MANU_VIA 4 extern int timing_rr; extern int timing_mr, timing_mrl; @@ -96,6 +102,8 @@ typedef struct int atclk_div; } CPU; +extern CPU *cpu_s; + extern CPU cpus_8088[]; extern CPU cpus_8086[]; extern CPU cpus_286[]; @@ -117,6 +125,9 @@ extern CPU cpus_6x86[]; extern CPU cpus_6x86_SS7[]; extern CPU cpus_K6_S7[]; extern CPU cpus_K6_SS7[]; +extern CPU cpus_PentiumPro[]; +extern CPU cpus_Slot1_100MHz[]; +extern CPU cpus_VIA_100MHz[]; extern CPU cpus_pcjr[]; extern CPU cpus_europc[]; @@ -135,13 +146,14 @@ extern int cpu_multi; /*Cyrix 5x86/6x86 only has data misalignment penalties when crossing 8-byte boundaries*/ extern int cpu_cyrix_alignment; -#define CPU_FEATURE_RDTSC (1 << 0) -#define CPU_FEATURE_MSR (1 << 1) -#define CPU_FEATURE_MMX (1 << 2) -#define CPU_FEATURE_CR4 (1 << 3) -#define CPU_FEATURE_VME (1 << 4) -#define CPU_FEATURE_CX8 (1 << 5) -#define CPU_FEATURE_3DNOW (1 << 6) +#define CPU_FEATURE_RDTSC (1 << 0) +#define CPU_FEATURE_MSR (1 << 1) +#define CPU_FEATURE_MMX (1 << 2) +#define CPU_FEATURE_CR4 (1 << 3) +#define CPU_FEATURE_VME (1 << 4) +#define CPU_FEATURE_CX8 (1 << 5) +#define CPU_FEATURE_3DNOW (1 << 6) +#define CPU_FEATURE_SYSCALL (1 << 7) extern uint32_t cpu_features; static inline int cpu_has_feature(int feature) @@ -184,10 +196,13 @@ extern uint64_t xt_cpu_multi; extern int isa_cycles; #define ISA_CYCLES(x) (x * isa_cycles) +#define CPU_CLOCK_DIVIDER_MAX 16384 void cpu_update_waitstates(); void cpu_set(); void cpu_set_edx(); void cpu_set_turbo(int turbo); +int cpu_get_turbo(); +void cpu_set_nonturbo_divider(int divider); int cpu_get_speed(); extern int has_vlb; diff --git a/pcem/f82c710_upc.h b/pcem/f82c710_upc.h new file mode 100644 index 00000000..05764aff --- /dev/null +++ b/pcem/f82c710_upc.h @@ -0,0 +1,6 @@ +#include "device.h" + +void upc_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p); + +extern device_t f82c710_upc_device; + diff --git a/pcem/i440bx.h b/pcem/i440bx.h new file mode 100644 index 00000000..8ed559ff --- /dev/null +++ b/pcem/i440bx.h @@ -0,0 +1,2 @@ +void i440bx_init(); +void i440bx_reset(); diff --git a/pcem/ibm.h b/pcem/ibm.h index f984d4a7..c4afe4dd 100644 --- a/pcem/ibm.h +++ b/pcem/ibm.h @@ -215,7 +215,7 @@ enum ROM_PC200, ROM_PC1640, ROM_PC2086, - ROM_PC3086, + ROM_PC3086, ROM_AMIXT, /*XT Clone with AMI BIOS*/ ROM_LTXT, ROM_LXT3, @@ -243,6 +243,8 @@ enum ROM_MEGAPC, ROM_AMA932J, ROM_AMI386SX, + ROM_SPC6000A, + ROM_SPC6033P, ROM_AMI486, ROM_WIN486, ROM_PCI486, @@ -294,6 +296,10 @@ enum ROM_LEDGE_MODELM, ROM_HYUNDAI_SUPER286TR, ROM_ITAUTEC_INFOWAYM, + ROM_DESKPRO, + ROM_VS440FX, + ROM_GA686BX, + ROM_PC5086, ROM_MAX }; @@ -317,13 +323,14 @@ enum GFX_EGA, /*Using IBM EGA BIOS*/ GFX_TVGA, /*Using Trident TVGA8900D BIOS*/ GFX_ET4000, /*Tseng ET4000*/ + GFX_KASAN16VGA, /*Kasan Hangulmadang-16 (Tseng ET4000AX)*/ GFX_TGKOREANVGA, /*Trigem Korean VGA(Tseng ET4000AX)*/ GFX_ET4000W32, /*Tseng ET4000/W32p (Diamond Stealth 32)*/ GFX_BAHAMAS64, /*S3 Vision864 (Paradise Bahamas 64)*/ GFX_N9_9FX, /*S3 764/Trio64 (Number Nine 9FX)*/ GFX_VIRGE, /*S3 Virge*/ GFX_TGUI9440, /*Trident TGUI9440*/ - GFX_VGA, /*IBM VGA*/ + GFX_VGA, /*IBM VGA*/ GFX_VGAEDGE16, /*ATI VGA Edge-16 (18800-1)*/ GFX_ATIKOREANVGA, /*ATI Korean VGA (28800-5)*/ GFX_VGACHARGER, /*ATI VGA Charger (28800-5)*/ @@ -333,7 +340,7 @@ enum GFX_VIRGEDX, /*S3 Virge/DX*/ GFX_PHOENIX_TRIO32, /*S3 732/Trio32 (Phoenix)*/ GFX_PHOENIX_TRIO64, /*S3 764/Trio64 (Phoenix)*/ - GFX_INCOLOR, /* Hercules InColor */ + GFX_INCOLOR, /* Hercules InColor */ GFX_COLORPLUS, /* Plantronics ColorPlus */ GFX_WY700, /* Wyse 700 */ GFX_GENIUS, /* MDSI Genius */ @@ -352,6 +359,11 @@ enum GFX_AVGA2, /*Acumos AVGA2 / Cirrus Logic CL-GD5402*/ GFX_CL_GD5428, /*Cirrus Logic CL-GD5428*/ GFX_IBM_GD5428, /*IBM 1MB SVGA Adapter/A*/ + GFX_TVGA9000B, /*Trident TVGA9000B*/ + GFX_BANSHEE, /*Voodoo Banshee - reference PCI board with SGRAM*/ + GFX_CL_BANSHEE, /*Creative Labs Voodoo Blaster Banshee PCI - with SDRAM*/ + GFX_VOODOO_3_2000, /*Voodoo 3 2000*/ + GFX_VOODOO_3_3000, /*Voodoo 3 3000*/ GFX_MAX }; @@ -494,3 +506,5 @@ void saveconfig_global_only(); #define MIN(a, b) ((a) < (b) ? (a) : (b)) void ide_padstr(char *str, const char *src, int len); + +void stop_emulation_now(void); diff --git a/pcem/keyboard_at.cpp b/pcem/keyboard_at.cpp index 64534ddf..7b64520b 100644 --- a/pcem/keyboard_at.cpp +++ b/pcem/keyboard_at.cpp @@ -320,6 +320,10 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) keyboard_at.output_port = val; break; + case 0xd2: /*Write to keyboard output buffer*/ + keyboard_at_adddata(val); + break; + case 0xd3: /*Write to mouse output buffer*/ #ifdef UAE if (ps2_mouse_supported) @@ -617,6 +621,11 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) keyboard_at.want60 = 1; break; + case 0xba: + if (romset == ROM_ENDEAVOR || romset == ROM_ZAPPA || romset == ROM_ITAUTEC_INFOWAYM) + keyboard_at_adddata(0); + break; + /* T3100e commands not implemented: * 0xB7: Emulate PS/2 keyboard * 0xB8: Emulate AT keyboard */ @@ -659,7 +668,10 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) break; case 0xca: /*AMI - read keyboard mode*/ - keyboard_at_adddata(0x00); /*ISA mode*/ + if (romset == ROM_GA686BX) /*TODO*/ + keyboard_at_adddata(0x01); /*PS2 mode*/ + else + keyboard_at_adddata(0x00); /*ISA mode*/ break; case 0xcb: /*AMI - set keyboard mode*/ @@ -696,17 +708,14 @@ void keyboard_at_write(uint16_t port, uint8_t val, void *priv) keyboard_at_adddata(0x00); break; - case 0xe8: /* Super-286TR: turbo ON */ - // TODO: 0xe8 is always followed by 0xba - // TODO: I don't know where to call cpu_set_turbo(1) to avoid slow POST after ctrl-alt-del when on low speed (if this is the real behavior!) - if (romset == ROM_HYUNDAI_SUPER286TR) - cpu_set_turbo(1); // 12 MHz - break; - - case 0xe9: /* Super-286TR: turbo OFF */ - if (romset == ROM_HYUNDAI_SUPER286TR) - cpu_set_turbo(0); // 8 MHz - break; + // AWARD BIOS: called after turbo ON/OFF in the + // Hyundai Super-286TR and probably other AWARD 286 + // bioses. Related to the Turbo LEDs. Exact function + // can't be confirmed because the system in question + // has no such leds. + //case 0xe8: /* Turbo ON, always followed by 0xba */ + //case 0xe9: /* Turbo OFF */ + //break; case 0xef: /*??? - sent by AMI486*/ break; diff --git a/pcem/keyboard_at.h b/pcem/keyboard_at.h index 5dafaca9..4c49c988 100644 --- a/pcem/keyboard_at.h +++ b/pcem/keyboard_at.h @@ -5,5 +5,6 @@ void keyboard_at_poll(); void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p); void keyboard_at_adddata_mouse(uint8_t val); +extern uint8_t mouse_queue[16]; extern int mouse_queue_start, mouse_queue_end; extern int mouse_scan; diff --git a/pcem/mem.cpp b/pcem/mem.cpp index 43d2d958..f2fcbb6c 100644 --- a/pcem/mem.cpp +++ b/pcem/mem.cpp @@ -33,7 +33,7 @@ mem_mapping_t ram_high_mapping; mem_mapping_t ram_mid_mapping; mem_mapping_t ram_remapped_mapping; mem_mapping_t bios_mapping[8]; -mem_mapping_t bios_high_mapping[8]; +mem_mapping_t bios_high_mapping[9]; static mem_mapping_t romext_mapping; static uint8_t ff_array[0x1000]; @@ -51,6 +51,9 @@ uint64_t *byte_code_present_mask; uint32_t mem_logical_addr; +void (*smram_enable)(void); +void (*smram_disable)(void); + int mmuflush=0; int mmu_perm=4; @@ -1343,24 +1346,26 @@ void mem_add_bios() { if (AT || (romset == ROM_XI8088 && xi8088_bios_128kb())) { - mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom, MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x4000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[2], 0xe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x8000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[3], 0xec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0xc000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_mapping[0], 0xe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x20000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_mapping[1], 0xe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x24000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_mapping[2], 0xe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x28000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_mapping[3], 0xec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x2c000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); } - mem_mapping_add(&bios_mapping[4], 0xf0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x10000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[5], 0xf4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x14000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[6], 0xf8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x18000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_mapping[7], 0xfc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x1c000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); - - mem_mapping_add(&bios_high_mapping[0], (AT && cpu_16bitbus) ? 0xfe0000 : 0xfffe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom, MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[1], (AT && cpu_16bitbus) ? 0xfe4000 : 0xfffe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x4000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[2], (AT && cpu_16bitbus) ? 0xfe8000 : 0xfffe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x8000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[3], (AT && cpu_16bitbus) ? 0xfec000 : 0xfffec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0xc000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[4], (AT && cpu_16bitbus) ? 0xff0000 : 0xffff0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x10000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[5], (AT && cpu_16bitbus) ? 0xff4000 : 0xffff4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x14000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[6], (AT && cpu_16bitbus) ? 0xff8000 : 0xffff8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x18000 & biosmask), MEM_MAPPING_ROM, 0); - mem_mapping_add(&bios_high_mapping[7], (AT && cpu_16bitbus) ? 0xffc000 : 0xffffc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x1c000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_mapping[4], 0xf0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x30000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_mapping[5], 0xf4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x34000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_mapping[6], 0xf8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x38000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_mapping[7], 0xfc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x3c000 & biosmask), MEM_MAPPING_EXTERNAL|MEM_MAPPING_ROM, 0); + + mem_mapping_add(&bios_high_mapping[0], (AT && cpu_16bitbus) ? 0xfe0000 : 0xfffe0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x20000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[1], (AT && cpu_16bitbus) ? 0xfe4000 : 0xfffe4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x24000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[2], (AT && cpu_16bitbus) ? 0xfe8000 : 0xfffe8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x28000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[3], (AT && cpu_16bitbus) ? 0xfec000 : 0xfffec000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x2c000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[4], (AT && cpu_16bitbus) ? 0xff0000 : 0xffff0000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x30000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[5], (AT && cpu_16bitbus) ? 0xff4000 : 0xffff4000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x34000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[6], (AT && cpu_16bitbus) ? 0xff8000 : 0xffff8000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x38000 & biosmask), MEM_MAPPING_ROM, 0); + mem_mapping_add(&bios_high_mapping[7], (AT && cpu_16bitbus) ? 0xffc000 : 0xffffc000, 0x04000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom + (0x3c000 & biosmask), MEM_MAPPING_ROM, 0); + if (biosmask == 0x3ffff) + mem_mapping_add(&bios_high_mapping[8], (AT && cpu_16bitbus) ? 0xfc0000 : 0xfffc0000, 0x20000, mem_read_bios, mem_read_biosw, mem_read_biosl, mem_write_null, mem_write_nullw, mem_write_nulll, rom, MEM_MAPPING_ROM, 0); } int mem_a20_key = 0, mem_a20_alt = 0; @@ -1480,7 +1485,22 @@ void mem_alloc() memset(_mem_state, 0, sizeof(_mem_state)); mem_set_mem_state(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL); - mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + if (romset == ROM_XI8088) + { + // Xi 8088 UMBs are selected by DIP Switches + mem_set_mem_state(0x0a0000, 0x20000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + mem_set_mem_state(0x0c0000, 0x08000, model_get_config_int("umb_c0000h_c7fff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + mem_set_mem_state(0x0c8000, 0x08000, model_get_config_int("umb_c8000h_cffff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + mem_set_mem_state(0x0d0000, 0x08000, model_get_config_int("umb_d0000h_d7fff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + mem_set_mem_state(0x0d8000, 0x08000, model_get_config_int("umb_d8000h_dffff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + mem_set_mem_state(0x0e0000, 0x08000, model_get_config_int("umb_e0000h_e7fff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + mem_set_mem_state(0x0e8000, 0x08000, model_get_config_int("umb_e8000h_effff") ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL)); + mem_set_mem_state(0x0f0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } + else + { + mem_set_mem_state(0x0a0000, 0x60000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL); + } mem_mapping_add(&ram_low_mapping, 0x00000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram, MEM_MAPPING_INTERNAL, NULL); if (mem_size > 1024) @@ -1496,8 +1516,8 @@ void mem_alloc() mem_mapping_add(&ram_high_mapping, 0x100000, ((mem_size - 1024) * 1024), mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0x100000, MEM_MAPPING_INTERNAL, NULL); } } - if (mem_size > 768) - mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL); + if (mem_size > 768) // 640k - 768k is graphics RAM + mem_mapping_add(&ram_mid_mapping, 0xa0000, 0x60000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL); if (romset == ROM_IBMPS1_2011) mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL); diff --git a/pcem/mem.h b/pcem/mem.h index 3c6a0f5e..866ae11b 100644 --- a/pcem/mem.h +++ b/pcem/mem.h @@ -134,7 +134,7 @@ void mem_write_nulll(uint32_t addr, uint32_t val, void *p); FILE *romfopen(char *fn, char *mode); extern mem_mapping_t bios_mapping[8]; -extern mem_mapping_t bios_high_mapping[8]; +extern mem_mapping_t bios_high_mapping[9]; extern mem_mapping_t ram_high_mapping; extern mem_mapping_t ram_remapped_mapping; @@ -266,4 +266,7 @@ void mmu_invalidate(uint32_t addr); int loadbios(); extern int purgeable_page_count; + +extern void (*smram_enable)(void); +extern void (*smram_disable)(void); #endif diff --git a/pcem/mouse_ps2.cpp b/pcem/mouse_ps2.cpp index 4df12310..15fd484c 100644 --- a/pcem/mouse_ps2.cpp +++ b/pcem/mouse_ps2.cpp @@ -4,6 +4,8 @@ #include "mouse.h" #include "mouse_ps2.h" #include "plat-mouse.h" +#include "x86.h" +#include "f82c710_upc.h" int mouse_scan = 0; @@ -175,7 +177,7 @@ void mouse_ps2_poll(int x, int y, int z, int b, void *p) { mouse_ps2_t *mouse = (mouse_ps2_t *)p; uint8_t packet[3] = {0x08, 0, 0}; - + if (!x && !y && !z && b == mouse->b) return; @@ -236,8 +238,11 @@ void *mouse_ps2_init() mouse->flags = 0; mouse->mode = MOUSE_STREAM; - keyboard_at_set_mouse(mouse_ps2_write, mouse); - + if(romset == ROM_PC5086) + upc_set_mouse(mouse_ps2_write, mouse); + else + keyboard_at_set_mouse(mouse_ps2_write, mouse); + return mouse; } diff --git a/pcem/nvr.cpp b/pcem/nvr.cpp index 4fdda9ba..7668a80a 100644 --- a/pcem/nvr.cpp +++ b/pcem/nvr.cpp @@ -296,6 +296,7 @@ void loadnvr() case ROM_PC200: f = nvrfopen("pc200.nvr", "rb"); break; case ROM_PC2086: f = nvrfopen("pc2086.nvr", "rb"); break; case ROM_PC3086: f = nvrfopen("pc3086.nvr", "rb"); break; + case ROM_PC5086: f = nvrfopen("pc5086.nvr", "rb"); break; case ROM_PPC512: f = nvrfopen("ppc512.nvr", "rb"); break; case ROM_IBMAT: f = nvrfopen("at.nvr", "rb"); break; case ROM_IBMXT286: f = nvrfopen("ibmxt286.nvr", "rb"); break; @@ -315,6 +316,8 @@ void loadnvr() case ROM_SPC4200P: f = nvrfopen("spc4200p.nvr", "rb"); nvrmask = 127; break; case ROM_SPC4216P: f = nvrfopen("spc4216p.nvr", "rb"); nvrmask = 127; break; case ROM_SPC4620P: f = nvrfopen("spc4620p.nvr", "rb"); nvrmask = 127; break; + case ROM_SPC6000A: f = nvrfopen("spc6000a.nvr", "rb"); nvrmask = 127; break; + case ROM_SPC6033P: f = nvrfopen("spc6033p.nvr", "rb"); nvrmask = 127; break; case ROM_DELL200: f = nvrfopen("dell200.nvr", "rb"); nvrmask = 127; break; case ROM_IBMAT386: f = nvrfopen("at386.nvr", "rb"); nvrmask = 127; break; case ROM_DESKPRO_386: f = nvrfopen("deskpro386.nvr", "rb"); break; @@ -366,6 +369,8 @@ void loadnvr() case ROM_CBM_SL386SX25: f = nvrfopen("cbm_sl386sx25.nvr", "rb"); nvrmask = 127; break; case ROM_IBMPS1_2133_451: f = nvrfopen("ibmps1_2133.nvr", "rb"); nvrmask = 127; break; case ROM_ECS_386_32: f = nvrfopen("ecs_386_32.nvr", "rb"); nvrmask = 127; break; + case ROM_VS440FX: f = nvrfopen("vs440fx.nvr", "rb"); nvrmask = 127; break; + case ROM_GA686BX: f = nvrfopen("ga686bx.nvr", "rb"); nvrmask = 127; break; default: return; } @@ -404,6 +409,7 @@ void savenvr() case ROM_PC200: f = nvrfopen("pc200.nvr", "wb"); break; case ROM_PC2086: f = nvrfopen("pc2086.nvr", "wb"); break; case ROM_PC3086: f = nvrfopen("pc3086.nvr", "wb"); break; + case ROM_PC5086: f = nvrfopen("pc5086.nvr", "wb"); break; case ROM_PPC512: f = nvrfopen("ppc512.nvr", "wb"); break; case ROM_IBMAT: f = nvrfopen("at.nvr", "wb"); break; case ROM_IBMXT286: f = nvrfopen("ibmxt286.nvr", "wb"); break; @@ -423,6 +429,8 @@ void savenvr() case ROM_SPC4200P: f = nvrfopen("spc4200p.nvr", "wb"); break; case ROM_SPC4216P: f = nvrfopen("spc4216p.nvr", "wb"); break; case ROM_SPC4620P: f = nvrfopen("spc4620p.nvr", "wb"); break; + case ROM_SPC6000A: f = nvrfopen("spc6000a.nvr", "wb"); break; + case ROM_SPC6033P: f = nvrfopen("spc6033p.nvr", "wb"); break; case ROM_DELL200: f = nvrfopen("dell200.nvr", "wb"); break; case ROM_IBMAT386: f = nvrfopen("at386.nvr", "wb"); break; case ROM_DESKPRO_386: f = nvrfopen("deskpro386.nvr", "wb"); break; diff --git a/pcem/paths.h b/pcem/paths.h index 2aceeecd..4c0538f3 100644 --- a/pcem/paths.h +++ b/pcem/paths.h @@ -4,8 +4,10 @@ extern char configs_path[512]; extern char nvr_path[512]; extern char logs_path[512]; extern char screenshots_path[512]; +extern char nvr_default_path[512]; void get_pcem_path(char *s, int size); +void get_pcem_base_path(char *s, int size); char get_path_separator(); void paths_init(); int dir_exists(char* path); diff --git a/pcem/pcemglue.cpp b/pcem/pcemglue.cpp index 987af7c6..b279f94c 100644 --- a/pcem/pcemglue.cpp +++ b/pcem/pcemglue.cpp @@ -1086,4 +1086,16 @@ void pcem_linear_mark(int offset) return; uae_u16 w = pcem_linear_read_w(offset, pcem_mapping_linear_priv); pcem_linear_write_w(offset, w, pcem_mapping_linear_priv); -} \ No newline at end of file +} + +int model_get_config_int(const char *s) +{ + return 0; +} +char *model_get_config_string(const char *s) +{ + return NULL; +} +void upc_set_mouse(void (*mouse_write)(uint8_t, void*), void *p) +{ +} diff --git a/pcem/pic.cpp b/pcem/pic.cpp index 79124296..27ed7bb4 100644 --- a/pcem/pic.cpp +++ b/pcem/pic.cpp @@ -14,13 +14,19 @@ int pic_intpending; void pic_updatepending() { - if ((pic2.pend&~pic2.mask)&~pic2.mask2) - pic.pend |= (1 << 2); + if (AT || romset == ROM_XI8088) + { + if ((pic2.pend&~pic2.mask)&~pic2.mask2) + pic.pend |= (1 << 2); + else + pic.pend &= ~(1 << 2); + pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2; + if (!((pic.mask | pic.mask2) & (1 << 2))) + pic_intpending |= ((pic2.pend&~pic2.mask)&~pic2.mask2); + } else - pic.pend &= ~(1 << 2); - pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2; - if (!((pic.mask | pic.mask2) & (1 << 2))) - pic_intpending |= ((pic2.pend&~pic2.mask)&~pic2.mask2); + pic_intpending = (pic.pend & ~pic.mask) & ~pic.mask2; + /* pclog("pic_intpending = %i %02X %02X %02X %02X\n", pic_intpending, pic.ins, pic.pend, pic.mask, pic.mask2); pclog(" %02X %02X %02X %02X %i %i\n", pic2.ins, pic2.pend, pic2.mask, pic2.mask2, ((pic.mask | pic.mask2) & (1 << 2)), ((pic2.pend&~pic2.mask)&~pic2.mask2));*/ } @@ -68,7 +74,7 @@ static void pic_autoeoi() pic.ins&=~(1<0xFF) + if ((AT || romset == ROM_XI8088) && num>0xFF) { pic2.pend|=(num>>8); if ((pic2.pend&~pic2.mask)&~pic2.mask2) pic.pend |= (1 << 2); } - else + else if (num <= 0xff) { pic.pend|=num; } @@ -394,13 +399,13 @@ void picintc(uint16_t num) // pclog("INTC %04X %i\n", num, c); pic_current[c]=0; - if (num > 0xff) + if ((AT || romset == ROM_XI8088) && num > 0xff) { pic2.pend &= ~(num >> 8); if (!((pic2.pend&~pic2.mask)&~pic2.mask2)) pic.pend &= ~(1 << 2); } - else + else if(num <= 0xff) { pic.pend&=~num; } @@ -411,54 +416,35 @@ uint8_t picinterrupt() { uint8_t temp=pic.pend&~pic.mask; int c; - for (c = 0; c < 2; c++) - { - if (temp & (1 << c)) - { - if (!(pic.level_sensitive & (1 << c))) - pic.pend &= ~(1 << c); - pic.ins |= (1 << c); - pic_update_mask(&pic.mask2, pic.ins); - - pic_updatepending(); - if (!c) - pit_set_gate(&pit2, 0, 0); - - if (pic.icw4 & 0x02) - pic_autoeoi(); - - return c+pic.vector; - } - } - if (temp & (1 << 2)) + for (c = 0; c < 8; c++) { - uint8_t temp2 = pic2.pend & ~pic2.mask; - for (c = 0; c < 8; c++) + if ((AT || romset == ROM_XI8088) && (temp & (1 << 2))) { - if (temp2 & (1 << c)) + uint8_t temp2 = pic2.pend & ~pic2.mask; + for (c = 0; c < 8; c++) { - if (!(pic2.level_sensitive & (1 << c))) - pic2.pend &= ~(1 << c); - pic2.ins |= (1 << c); - pic_update_mask(&pic2.mask2, pic2.ins); + if (temp2 & (1 << c)) + { + if (!(pic2.level_sensitive & (1 << c))) + pic2.pend &= ~(1 << c); + pic2.ins |= (1 << c); + pic_update_mask(&pic2.mask2, pic2.ins); - if (!(pic2.level_sensitive & (1 << c))) - pic.pend &= ~(1 << c); - pic.ins |= (1 << 2); /*Cascade IRQ*/ - pic_update_mask(&pic.mask2, pic.ins); + if (!(pic2.level_sensitive & (1 << c))) + pic.pend &= ~(1 << c); + pic.ins |= (1 << 2); /*Cascade IRQ*/ + pic_update_mask(&pic.mask2, pic.ins); - pic_updatepending(); + pic_updatepending(); - if (pic2.icw4 & 0x02) - pic2_autoeoi(); + if (pic2.icw4 & 0x02) + pic2_autoeoi(); - return c+pic2.vector; + return c+pic2.vector; + } } } - } - for (c = 3; c < 8; c++) - { - if (temp & (1 << c)) + else if (temp & (1 << c)) { if (!(pic.level_sensitive & (1 << c))) pic.pend &= ~(1 << c); @@ -468,7 +454,6 @@ uint8_t picinterrupt() if (pic.icw4 & 0x02) pic_autoeoi(); - return c+pic.vector; } } diff --git a/pcem/serial.cpp b/pcem/serial.cpp index 8d2947bb..570da45f 100644 --- a/pcem/serial.cpp +++ b/pcem/serial.cpp @@ -265,6 +265,10 @@ void serial1_set(uint16_t addr, int irq) serial1.irq = irq; serial1.addr = addr; } +void serial1_set_has_fifo(int has_fifo) +{ + serial1.has_fifo = has_fifo; +} void serial1_remove() { io_removehandler(serial1.addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1); @@ -287,6 +291,10 @@ void serial2_set(uint16_t addr, int irq) serial2.irq = irq; serial2.addr = addr; } +void serial2_set_has_fifo(int has_fifo) +{ + serial2.has_fifo = has_fifo; +} void serial2_remove() { io_removehandler(serial2.addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2); diff --git a/pcem/serial.h b/pcem/serial.h index 4818423f..0bf88f10 100644 --- a/pcem/serial.h +++ b/pcem/serial.h @@ -4,6 +4,8 @@ void serial1_init(uint16_t addr, int irq, int has_fifo); void serial2_init(uint16_t addr, int irq, int has_fifo); void serial1_set(uint16_t addr, int irq); void serial2_set(uint16_t addr, int irq); +void serial1_set_has_fifo(int has_fifo); +void serial2_set_has_fifo(int has_fifo); void serial1_remove(); void serial2_remove(); void serial_reset(); diff --git a/pcem/vid_cl5429.cpp b/pcem/vid_cl5429.cpp index 730b4ff9..bce75e85 100644 --- a/pcem/vid_cl5429.cpp +++ b/pcem/vid_cl5429.cpp @@ -1,4 +1,5 @@ /*Cirrus Logic CL-GD5429 emulation*/ +//SR7.0 = "true packed-pixel memory addressing" #include #include "ibm.h" #include "cpu.h" @@ -128,9 +129,10 @@ typedef struct gd5429_t int vidsys_ena; } gd5429_t; -#define GRB_X8_ADDRESSING (1 << 1) -#define GRB_WRITEMODE_EXT (1 << 2) -#define GRB_8B_LATCHES (1 << 3) +#define GRB_X8_ADDRESSING (1 << 1) +#define GRB_WRITEMODE_EXT (1 << 2) +#define GRB_8B_LATCHES (1 << 3) +#define GRB_ENHANCED_16BIT (1 << 4) static void gd5429_mmio_write(uint32_t addr, uint8_t val, void *p); static void gd5429_mmio_writew(uint32_t addr, uint16_t val, void *p); @@ -554,8 +556,11 @@ void gd5429_out(uint16_t addr, uint8_t val, void *p) break; case 0x07: - if (gd5429->type >= CL_TYPE_GD5429) + if (gd5429->type >= CL_TYPE_GD5429) { svga->set_reset_disabled = svga->seqregs[7] & 1; + } + svga->packed_chain4 = svga->seqregs[7] & 1; + svga_recalctimings(svga); case 0x0f: case 0x17: //UAE @@ -1411,13 +1416,20 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p) if (!(svga->gdcreg[6] & 1)) svga->fullchange = 2; - if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING) + if (svga->gdcreg[0xb] & GRB_ENHANCED_16BIT) + addr <<= 4; + else if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING) addr <<= 3; - else if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4)) + else if (((svga->chain4 && svga->packed_chain4) || svga->fb_only) && (svga->writemode < 4)) { writemask2 = 1 << (addr & 3); addr &= ~3; } + else if (svga->chain4) + { + writemask2 = 1 << (addr & 3); + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); + } else if (svga->chain2_write) { writemask2 &= ~0xa; @@ -1430,22 +1442,19 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p) { addr <<= 2; } - addr &= svga->decode_mask; if (addr >= svga->vram_max) return; addr &= svga->vram_mask; // if (svga_output) pclog("%08X\n", addr); - svga->changedvram[addr >> 12] = changeframecount; switch (svga->writemode) { case 4: - if (svga->gdcreg[0xb] & 0x10) + if (svga->gdcreg[0xb] & GRB_ENHANCED_16BIT) { // pclog("Writemode 4 : %X ", addr); - addr <<= 2; svga->changedvram[addr >> 12] = changeframecount; // pclog("%X %X %02x\n", addr, val, svga->gdcreg[0xb]); if (val & svga->seqregs[2] & 0x80) @@ -1514,10 +1523,9 @@ void gd5429_write_linear(uint32_t addr, uint8_t val, void *p) break; case 5: - if (svga->gdcreg[0xb] & 0x10) + if (svga->gdcreg[0xb] & GRB_ENHANCED_16BIT) { // pclog("Writemode 5 : %X ", addr); - addr <<= 2; svga->changedvram[addr >> 12] = changeframecount; // pclog("%X %X %02x\n", addr, val, svga->gdcreg[0xb]); if (svga->seqregs[2] & 0x80) @@ -1759,20 +1767,29 @@ uint8_t gd5429_read_linear(uint32_t addr, void *p) egareads++; #endif - if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING) + if (svga->gdcreg[0xb] & GRB_ENHANCED_16BIT) + latch_addr = (addr << 4) & svga->decode_mask; + else if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING) latch_addr = (addr << 3) & svga->decode_mask; else latch_addr = (addr << 2) & svga->decode_mask; - if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING) + if (svga->gdcreg[0xb] & GRB_ENHANCED_16BIT) + addr <<= 4; + else if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING) addr <<= 3; - else if (svga->chain4 || svga->fb_only) + else if ((svga->chain4 && svga->packed_chain4) || svga->fb_only) { addr &= svga->decode_mask; if (addr >= svga->vram_max) return 0xff; return svga->vram[addr & svga->vram_mask]; } + else if (svga->chain4) + { + readplane = addr & 3; + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); + } else if (svga->chain2_read) { readplane = (readplane & 2) | (addr & 1); diff --git a/pcem/vid_s3.cpp b/pcem/vid_s3.cpp index 7b7054c5..d41bd328 100644 --- a/pcem/vid_s3.cpp +++ b/pcem/vid_s3.cpp @@ -1027,8 +1027,11 @@ void s3_out(uint16_t addr, uint8_t val, void *p) return; if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80)) val = (svga->crtc[7] & ~0x10) | (val & 0x10); - if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) - return; + if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && svga->crtcreg != 0x39 && (svga->crtc[0x38] & 0xcc) != 0x48) + { + if (!((svga->crtc[0x39] & 0xe0) == 0xa0 && svga->crtcreg >= 0x40 && svga->crtcreg <= 0x6d)) + return; + } old = svga->crtc[svga->crtcreg]; svga->crtc[svga->crtcreg] = val; switch (svga->crtcreg) @@ -1047,6 +1050,7 @@ void s3_out(uint16_t addr, uint8_t val, void *p) case 0x31: s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4); + svga->force_dword_mode = val & 0x08; break; case 0x32: svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask; @@ -1710,15 +1714,29 @@ static void polygon_setup(s3_t *s3) } } -#define READ_SRC(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \ - else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ - else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; \ +/*Remap address for chain-4/doubleword style layout*/ +static inline uint32_t dword_remap(uint32_t in_addr) +{ + return in_addr; +} +static inline uint32_t dword_remap_w(uint32_t in_addr) +{ + return in_addr; +} +static inline uint32_t dword_remap_l(uint32_t in_addr) +{ + return in_addr; +} + +#define READ_SRC(addr, dat) if (s3->bpp == 0) dat = svga->vram[ dword_remap(addr) & s3->vram_mask]; \ + else if (s3->bpp == 1) dat = vram_w[dword_remap_w(addr) & (s3->vram_mask >> 1)]; \ + else dat = vram_l[dword_remap_l(addr) & (s3->vram_mask >> 2)]; \ if (vram_mask) \ dat = ((dat & rd_mask) == rd_mask); -#define READ_DST(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \ - else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \ - else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; +#define READ_DST(addr, dat) if (s3->bpp == 0) dat = svga->vram[ dword_remap(addr) & s3->vram_mask]; \ + else if (s3->bpp == 1) dat = vram_w[dword_remap_w(addr) & (s3->vram_mask >> 1)]; \ + else dat = vram_l[dword_remap_l(addr) & (s3->vram_mask >> 2)]; #define MIX { \ uint32_t old_dest_dat = dest_dat; \ @@ -1747,18 +1765,18 @@ static void polygon_setup(s3_t *s3) #define WRITE(addr) if (s3->bpp == 0) \ { \ - svga->vram[(addr) & s3->vram_mask] = dest_dat; \ - svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \ + svga->vram[dword_remap(addr) & s3->vram_mask] = dest_dat; \ + svga->changedvram[(dword_remap(addr) & s3->vram_mask) >> 12] = changeframecount; \ } \ else if (s3->bpp == 1) \ { \ - vram_w[(addr) & (s3->vram_mask >> 1)] = dest_dat; \ - svga->changedvram[((addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \ + vram_w[dword_remap_w(addr) & (s3->vram_mask >> 1)] = dest_dat; \ + svga->changedvram[(dword_remap_w(addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \ } \ else \ { \ - vram_l[(addr) & (s3->vram_mask >> 2)] = dest_dat; \ - svga->changedvram[((addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \ + vram_l[dword_remap_l(addr) & (s3->vram_mask >> 2)] = dest_dat; \ + svga->changedvram[(dword_remap_l(addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \ } void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3) @@ -2576,8 +2594,10 @@ void s3_hwcursor_draw(svga_t *svga, int displine) // pclog("HWcursor %i %i\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y); for (x = 0; x < 64; x += 16) { - dat[0] = (svga->vram[svga->hwcursor_latch.addr & svga->vram_display_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 1) & svga->vram_display_mask]; - dat[1] = (svga->vram[(svga->hwcursor_latch.addr + 2) & svga->vram_display_mask] << 8) | svga->vram[(svga->hwcursor_latch.addr + 3) & svga->vram_display_mask]; + uint32_t remapped_addr = dword_remap(svga->hwcursor_latch.addr); + + dat[0] = (svga->vram[remapped_addr] << 8) | svga->vram[remapped_addr + 1]; + dat[1] = (svga->vram[remapped_addr + 2] << 8) | svga->vram[remapped_addr + 3]; for (xx = 0; xx < 16; xx++) { if (offset >= svga->hwcursor_latch.x) @@ -2621,7 +2641,8 @@ static void s3_io_remove(s3_t *s3) io_removehandlerx(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandlerx(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandlerx(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); - io_removehandlerx(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandlerx(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); + io_removehandlerx(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3); io_removehandlerx(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3); } diff --git a/pcem/vid_s3_virge.cpp b/pcem/vid_s3_virge.cpp index 1acab18e..b36823a3 100644 --- a/pcem/vid_s3_virge.cpp +++ b/pcem/vid_s3_virge.cpp @@ -237,6 +237,9 @@ typedef struct virge_t int virge_busy; uint8_t subsys_stat, subsys_cntl; + + uint8_t serialport; + uint32_t advfunc; int vblank_irq; } virge_t; @@ -310,6 +313,11 @@ enum #define INT_3DF_EMP (1 << 6) #define INT_MASK 0xff +#define SERIAL_PORT_SCW (1 << 0) +#define SERIAL_PORT_SDW (1 << 1) +#define SERIAL_PORT_SCR (1 << 2) +#define SERIAL_PORT_SDR (1 << 3) + static int virge_vga_vsync_enabled(virge_t *virge) { if ((virge->svga.crtc[0x32] & 0x10) && !(virge->svga.crtc[0x11] & 0x20) && virge->vblank_irq > 0) @@ -786,14 +794,12 @@ static void s3_virge_updatemapping(virge_t *virge) } else mem_mapping_set_addrx(&virge->linear_mapping, virge->linear_base, virge->linear_size); - if (svga->fb_only >= 0) - svga->fb_only = 1; + svga->fb_only = 1; } else { mem_mapping_disablex(&virge->linear_mapping); - if (svga->fb_only >= 0) - svga->fb_only = 0; + svga->fb_only = 0; } pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18); @@ -865,6 +871,16 @@ static uint8_t s3_virge_mmio_read(uint32_t addr, void *p) case 0x83d8: case 0x83d9: case 0x83da: case 0x83db: case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: return s3_virge_in(addr & 0x3ff, p); + +#if 0 + case 0xff20: case 0xff21: + ret = virge->serialport & ~(SERIAL_PORT_SCR | SERIAL_PORT_SDR); + if ((virge->serialport & SERIAL_PORT_SCW) && ddc_read_clock()) + ret |= SERIAL_PORT_SCR; + if ((virge->serialport & SERIAL_PORT_SDW) && ddc_read_data()) + ret |= SERIAL_PORT_SDR; + return ret; +#endif } return 0xff; } @@ -1060,7 +1076,7 @@ static void fifo_thread(void *param) if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000) { if (virge->s3d.cmd_set & CMD_SET_MS) - ((val >> 8) | (val << 8)) << 16; + val = ((val >> 8) | (val << 8)) << 16; // if ((virge->svga.crtc[0x54] & 3) == 1) // ((val >> 8) | (val << 8)) << 16; s3_virge_bitblt(virge, 16, val); @@ -1440,9 +1456,12 @@ static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p) case 0x83dc: case 0x83dd: case 0x83de: case 0x83df: s3_virge_out(addr & 0x3ff, val, p); break; - } - + case 0xff20: + virge->serialport = val; + //ddc_i2c_change((val & SERIAL_PORT_SCW) ? 1 : 0, (val & SERIAL_PORT_SDW) ? 1 : 0); + break; + } } static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p) { @@ -1453,10 +1472,16 @@ static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p) { s3_virge_queue(virge, addr, val, FIFO_WRITE_WORD); } - else + else switch (addr & 0xfffe) { + default: s3_virge_mmio_write(addr, val, p); s3_virge_mmio_write(addr + 1, val >> 8, p); + break; + + case 0xff20: + s3_virge_mmio_write(addr, val, p); + break; } } static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) @@ -1905,6 +1930,10 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p) // s3_virge_triangle(virge); break; + + case 0xff20: + s3_virge_mmio_write(addr, val, p); + break; } } @@ -4009,6 +4038,10 @@ static void *s3_virge_init() virge->fifo_not_full_event = thread_create_event(); virge->fifo_thread = thread_create(fifo_thread, virge); + //ddc_init(); + + //TODO ViRGE does not use packed chain4 + virge->svga.packed_chain4 = 1; return virge; } @@ -4093,8 +4126,6 @@ static void *s3_virge_375_init() virge->svga.crtc[0x6c] = 0x01; - virge->svga.fb_only = -1; - virge->is_375 = 1; virge->card = pci_add(s3_virge_pci_read, s3_virge_pci_write, virge); @@ -4107,7 +4138,12 @@ static void *s3_virge_375_init() virge->wake_fifo_thread = thread_create_event(); virge->fifo_not_full_event = thread_create_event(); virge->fifo_thread = thread_create(fifo_thread, virge); - + + //ddc_init(); + + //TODO ViRGE does not use packed chain4 + virge->svga.packed_chain4 = 1; + return virge; } diff --git a/pcem/vid_svga.cpp b/pcem/vid_svga.cpp index f75d48d4..c925b325 100644 --- a/pcem/vid_svga.cpp +++ b/pcem/vid_svga.cpp @@ -45,7 +45,6 @@ svga_t *svga_get_pri() { return svga_pri; } - void svga_set_override(svga_t *svga, int val) { if (svga->override && !val) @@ -137,7 +136,8 @@ void svga_out(uint16_t addr, uint8_t val, void *p) case 4: svga->chain2_write = !(val & 4); svga->chain4 = val & 8; - svga->fast = ((svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4) || svga->fb_only < 0; + svga->fast = ((svga->gdcreg[8] == 0xff || svga->gdcreg[8] == 0) && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && + ((svga->chain4 && svga->packed_chain4) || svga->fb_only); break; } break; @@ -224,7 +224,8 @@ void svga_out(uint16_t addr, uint8_t val, void *p) case 7: svga->colournocare=val; break; } svga->gdcreg[svga->gdcaddr & 15] = val; - svga->fast = ((svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4) || svga->fb_only < 0;; + svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && + ((svga->chain4 && svga->packed_chain4) || svga->fb_only); if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1)) svga_recalctimings(svga); break; @@ -509,11 +510,12 @@ void svga_recalctimings(svga_t *svga) if (svga->dispofftime < TIMER_USEC) svga->dispofftime = TIMER_USEC; -// pclog("SVGA horiz total %i display end %i vidclock %f\n",svga->crtc[0],svga->crtc[1],svga->clock); -// pclog("SVGA vert total %i display end %i max row %i vsync %i\n",svga->vtotal,svga->dispend,(svga->crtc[9]&31)+1,svga->vsyncstart); -// pclog("total %f on %i cycles off %i cycles frame %i sec %i %02X\n",disptime*crtcconst,svga->dispontime,svga->dispofftime,(svga->dispontime+svga->dispofftime)*svga->vtotal,(svga->dispontime+svga->dispofftime)*svga->vtotal*70,svga->seqregs[1]); + svga_recalc_remap_func(svga); +/* printf("SVGA horiz total %i display end %i vidclock %f\n",svga->crtc[0],svga->crtc[1],svga->clock); + printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga->vtotal,svga->dispend,(svga->crtc[9]&31)+1,svga->vsyncstart); + printf("total %f on %i cycles off %i cycles frame %i sec %i %02X\n",disptime*crtcconst,svga->dispontime,svga->dispofftime,(svga->dispontime+svga->dispofftime)*svga->vtotal,(svga->dispontime+svga->dispofftime)*svga->vtotal*70,svga->seqregs[1]); -// pclog("svga->render %08X\n", svga->render); + pclog("svga->render %08X\n", svga->render);*/ } extern int cyc_total; @@ -862,6 +864,7 @@ int svga_init(svga_t *svga, void *p, int memsize, svga->hwcursor_draw = hwcursor_draw; svga->overlay_draw = overlay_draw; svga->hwcursor.ysize = 64; + svga->ksc5601_english_font_type = 0; svga_recalctimings(svga); mem_mapping_addx(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, MEM_MAPPING_EXTERNAL, svga); @@ -905,11 +908,17 @@ void svga_write(uint32_t addr, uint8_t val, void *p) addr += svga->write_bank; if (!(svga->gdcreg[6] & 1)) svga->fullchange=2; - if (svga->chain4 || svga->fb_only) + if ((svga->chain4 && svga->packed_chain4) || svga->fb_only) { writemask2=1<<(addr&3); addr&=~3; } + else if (svga->chain4) + { + writemask2 = 1 << (addr & 3); + addr &= ~3; + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); + } else if (svga->chain2_write) { writemask2 &= ~0xa; @@ -1098,7 +1107,7 @@ uint8_t svga_read(uint32_t addr, void *p) // pclog("%05X %i %04X:%04X %02X %02X %i\n",addr,svga->chain4,CS,pc, vram[addr & 0x7fffff], vram[(addr << 2) & 0x7fffff], svga->readmode); // pclog("%i\n", svga->readmode); - if (svga->chain4 || svga->fb_only) + if ((svga->chain4 && svga->packed_chain4) || svga->fb_only) { addr &= svga->decode_mask; if (addr >= svga->vram_max) @@ -1110,6 +1119,11 @@ uint8_t svga_read(uint32_t addr, void *p) svga->ld = svga->vram[latch_addr | 0x3]; return svga->vram[addr & svga->vram_mask]; } + else if (svga->chain4) + { + readplane = addr & 3; + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); + } else if (svga->chain2_read) { readplane = (readplane & 2) | (addr & 1); @@ -1176,11 +1190,16 @@ void svga_write_linear(uint32_t addr, uint8_t val, void *p) if (!(svga->gdcreg[6] & 1)) svga->fullchange = 2; - if (svga->chain4 || svga->fb_only) + if ((svga->chain4 && svga->packed_chain4) || svga->fb_only) { writemask2=1<<(addr&3); addr&=~3; } + else if (svga->chain4) + { + writemask2 = 1 << (addr & 3); + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); + } else if (svga->chain2_write) { writemask2 &= ~0xa; @@ -1358,13 +1377,18 @@ uint8_t svga_read_linear(uint32_t addr, void *p) egareads++; #endif - if (svga->chain4 || svga->fb_only) + if ((svga->chain4 && svga->packed_chain4) || svga->fb_only) { addr &= svga->decode_mask; if (addr >= svga->vram_max) return 0xff; return svga->vram[addr & svga->vram_mask]; } + else if (svga->chain4) + { + readplane = addr & 3; + addr = ((addr & 0xfffc) << 2) | ((addr & 0x30000) >> 14) | (addr & ~0x3ffff); + } else if (svga->chain2_read) { readplane = (readplane & 2) | (addr & 1); @@ -1657,8 +1681,8 @@ void svga_add_status_info(char *s, int max_len, void *p) svga_t *svga = (svga_t *)p; char temps[128]; - if (svga->chain4) strcpy(temps, "SVGA chained "); - else strcpy(temps, "SVGA unchained "); + if (svga->chain4) strcpy(temps, "SVGA chained (possibly mode 13h) "); + else strcpy(temps, "SVGA unchained (possibly mode-X) "); strncat(s, temps, max_len); if (!svga->video_bpp) strcpy(temps, "SVGA in text mode "); diff --git a/pcem/vid_svga.h b/pcem/vid_svga.h index e0d6900d..df5c0f88 100644 --- a/pcem/vid_svga.h +++ b/pcem/vid_svga.h @@ -140,13 +140,26 @@ typedef struct svga_t void *p; uint8_t ksc5601_sbyte_mask; - + uint8_t ksc5601_udc_area_msb[2]; + int ksc5601_swap_mode; + uint16_t ksc5601_english_font_type; + int vertical_linedbl; int horizontal_linedbl; /*Used to implement CRTC[0x17] bit 2 hsync divisor*/ int hsync_divisor; + /*Tseng-style chain4 mode - CRTC dword mode is the same as byte mode, chain4 + addresses are shifted to match*/ + int packed_chain4; + + /*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/ + int force_dword_mode; + + int remap_required; + uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr); + bool swaprb; } svga_t; diff --git a/pcem/vid_svga_render.cpp b/pcem/vid_svga_render.cpp index a2609cd0..1fc0fc1b 100644 --- a/pcem/vid_svga_render.cpp +++ b/pcem/vid_svga_render.cpp @@ -3,12 +3,13 @@ #include "video.h" #include "vid_svga.h" #include "vid_svga_render.h" +#include "vid_svga_render_remap.h" -void svga_render_null(svga_t* svga) +void svga_render_null(svga_t *svga) { - if (svga->firstline_draw == 4000) - svga->firstline_draw = svga->displine; - svga->lastline_draw = svga->displine; + if (svga->firstline_draw == 4000) + svga->firstline_draw = svga->displine; + svga->lastline_draw = svga->displine; } void svga_render_blank(svga_t *svga) @@ -58,9 +59,12 @@ void svga_render_text_40(svga_t *svga) for (x = 0; x < svga->hdisp; x += xinc) { + uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; + drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); - chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; - attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + chr = svga->vram[addr]; + attr = svga->vram[addr+1]; + if (attr & 8) charaddr = svga->charsetb + (chr * 128); else charaddr = svga->charseta + (chr * 128); @@ -122,9 +126,12 @@ void svga_render_text_80(svga_t *svga) for (x = 0; x < svga->hdisp; x += xinc) { + uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; + drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); - chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; - attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + chr = svga->vram[addr]; + attr = svga->vram[addr+1]; + if (attr & 8) charaddr = svga->charsetb + (chr * 128); else charaddr = svga->charseta + (chr * 128); @@ -186,10 +193,12 @@ void svga_render_text_80_ksc5601(svga_t *svga) for (x = 0; x < svga->hdisp; x += xinc) { + uint32_t addr = svga->remap_func(svga, svga->ma) & svga->vram_display_mask; + drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron); - chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask]; - nextchr = svga->vram[((svga->ma + 4) << 1) & svga->vram_display_mask]; - attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask]; + chr = svga->vram[addr]; + nextchr = svga->vram[addr + 8]; + attr = svga->vram[addr + 1]; if (drawcursor) { @@ -210,10 +219,17 @@ void svga_render_text_80_ksc5601(svga_t *svga) if(x + xinc < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80)) { - if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff)) - dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc]; + if((chr == svga->ksc5601_udc_area_msb[0] || chr == svga->ksc5601_udc_area_msb[1]) && (nextchr > 0xa0 && nextchr < 0xff)) + dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc]; else if(nextchr & 0x80) + { + if(svga->ksc5601_swap_mode == 1 && (nextchr > 0xa0 && nextchr < 0xff)) + { + if(chr >= 0x80 && chr < 0x99) chr += 0x30; + else if(chr >= 0xB0 && chr < 0xC9) chr -= 0x30; + } dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)][svga->sc]; + } else dat = 0xFF; } @@ -222,7 +238,8 @@ void svga_render_text_80_ksc5601(svga_t *svga) if (attr & 8) charaddr = svga->charsetb + (chr * 128); else charaddr = svga->charseta + (chr * 128); - dat = svga->vram[charaddr + (svga->sc << 2)]; + if ((svga->ksc5601_english_font_type >> 8) == 1) dat = fontdatksc5601[((svga->ksc5601_english_font_type & 0x7F) << 7) | (chr >> 1)][((chr & 1) << 4) | svga->sc]; + else dat = svga->vram[charaddr + (svga->sc << 2)]; } if (svga->seqregs[1] & 1) { @@ -262,10 +279,12 @@ void svga_render_text_80_ksc5601(svga_t *svga) } } - if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff)) - dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc + 16]; + if((chr == svga->ksc5601_udc_area_msb[0] || chr == svga->ksc5601_udc_area_msb[1]) && (nextchr > 0xa0 && nextchr < 0xff)) + dat = fontdatksc5601_user[(chr == svga->ksc5601_udc_area_msb[1] ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc + 16]; else if(nextchr & 0x80) + { dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)][svga->sc + 16]; + } else dat = 0xFF; if (svga->seqregs[1] & 1) @@ -294,11 +313,9 @@ void svga_render_text_80_ksc5601(svga_t *svga) void svga_render_2bpp_lowres(svga_t *svga) { - int changed_offset; - - changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; + uint32_t changed_addr = svga->remap_func(svga, svga->ma); - if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = ((8 - svga->scrollcache) << 1) + 16; @@ -308,12 +325,13 @@ void svga_render_2bpp_lowres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 16) + for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 16) { + uint32_t addr = svga->remap_func(svga, svga->ma); uint8_t dat[2]; - dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]; - dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1]; + dat[0] = svga->vram[addr]; + dat[1] = svga->vram[addr + 1]; svga->ma += 4; svga->ma &= svga->vram_display_mask; @@ -333,11 +351,9 @@ void svga_render_2bpp_lowres(svga_t *svga) void svga_render_2bpp_highres(svga_t *svga) { - int changed_offset; - - changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; - - if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = (8 - svga->scrollcache) + 24; @@ -349,30 +365,31 @@ void svga_render_2bpp_highres(svga_t *svga) for (x = 0; x <= svga->hdisp; x += 8) { + uint32_t addr = svga->remap_func(svga, svga->ma); uint8_t dat[2]; - dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]; - dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1]; + dat[0] = svga->vram[addr]; + dat[1] = svga->vram[addr + 1]; svga->ma += 4; svga->ma &= svga->vram_display_mask; - p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; - p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; - p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; - p[3] = svga->pallook[svga->egapal[dat[0] & 3]]; - p[4] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; - p[5] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; - p[6] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; - p[7] = svga->pallook[svga->egapal[dat[1] & 3]]; - - p += 8; + *p++ = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]]; + *p++ = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]]; + *p++ = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]]; + *p++ = svga->pallook[svga->egapal[dat[0] & 3]]; + *p++ = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]]; + *p++ = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]]; + *p++ = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]]; + *p++ = svga->pallook[svga->egapal[dat[1] & 3]]; } } } void svga_render_4bpp_lowres(svga_t *svga) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = ((8 - svga->scrollcache) << 1) + 16; @@ -386,8 +403,9 @@ void svga_render_4bpp_lowres(svga_t *svga) { uint8_t edat[4]; uint8_t dat; + uint32_t addr = svga->remap_func(svga, svga->ma); - *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma]); + *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[addr]); svga->ma += 4; svga->ma &= svga->vram_display_mask; @@ -411,11 +429,9 @@ void svga_render_4bpp_lowres(svga_t *svga) void svga_render_4bpp_highres(svga_t *svga) { - int changed_offset; - - changed_offset = (svga->ma + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12; - - if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = (8 - svga->scrollcache) + 24; @@ -429,32 +445,33 @@ void svga_render_4bpp_highres(svga_t *svga) { uint8_t edat[4]; uint8_t dat; + uint32_t addr = svga->remap_func(svga, svga->ma); - *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma | ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]); + *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[addr]); svga->ma += 4; svga->ma &= svga->vram_display_mask; dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2); - p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + *p++ = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + *p++ = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2); - p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + *p++ = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + *p++ = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2); - p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; + *p++ = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + *p++ = svga->pallook[svga->egapal[dat & svga->plane_mask]]; dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2); - p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; - p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]]; - - p += 8; + *p++ = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]]; + *p++ = svga->pallook[svga->egapal[dat & svga->plane_mask]]; } } } void svga_render_8bpp_lowres(svga_t *svga) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = (8 - (svga->scrollcache & 6)) + 24; @@ -464,17 +481,36 @@ void svga_render_8bpp_lowres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 8) + if (!svga->remap_required) { - uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - - p[0] = p[1] = svga->pallook[dat & 0xff]; - p[2] = p[3] = svga->pallook[(dat >> 8) & 0xff]; - p[4] = p[5] = svga->pallook[(dat >> 16) & 0xff]; - p[6] = p[7] = svga->pallook[(dat >> 24) & 0xff]; - - svga->ma += 4; - p += 8; + for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 8) + { + uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); + + p[0] = p[1] = svga->pallook[dat & 0xff]; + p[2] = p[3] = svga->pallook[(dat >> 8) & 0xff]; + p[4] = p[5] = svga->pallook[(dat >> 16) & 0xff]; + p[6] = p[7] = svga->pallook[(dat >> 24) & 0xff]; + + svga->ma += 4; + p += 8; + } + } + else + { + for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 8) + { + uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + + p[0] = p[1] = svga->pallook[dat & 0xff]; + p[2] = p[3] = svga->pallook[(dat >> 8) & 0xff]; + p[4] = p[5] = svga->pallook[(dat >> 16) & 0xff]; + p[6] = p[7] = svga->pallook[(dat >> 24) & 0xff]; + + svga->ma += 4; + p += 8; + } } svga->ma &= svga->vram_display_mask; } @@ -482,41 +518,62 @@ void svga_render_8bpp_lowres(svga_t *svga) void svga_render_8bpp_highres(svga_t *svga) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset]; - if (svga->firstline_draw == 4000) + if (svga->firstline_draw == 4000) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 8) + if (!svga->remap_required) + { + for (x = 0; x <= svga->hdisp; x += 8) + { + uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); + *p++ = svga->pallook[dat & 0xff]; + *p++ = svga->pallook[(dat >> 8) & 0xff]; + *p++ = svga->pallook[(dat >> 16) & 0xff]; + *p++ = svga->pallook[(dat >> 24) & 0xff]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma+4) & svga->vram_display_mask]); + *p++ = svga->pallook[dat & 0xff]; + *p++ = svga->pallook[(dat >> 8) & 0xff]; + *p++ = svga->pallook[(dat >> 16) & 0xff]; + *p++ = svga->pallook[(dat >> 24) & 0xff]; + + svga->ma += 8; + } + } + else { - uint32_t dat; - dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[0] = svga->pallook[dat & 0xff]; - p[1] = svga->pallook[(dat >> 8) & 0xff]; - p[2] = svga->pallook[(dat >> 16) & 0xff]; - p[3] = svga->pallook[(dat >> 24) & 0xff]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); - p[4] = svga->pallook[dat & 0xff]; - p[5] = svga->pallook[(dat >> 8) & 0xff]; - p[6] = svga->pallook[(dat >> 16) & 0xff]; - p[7] = svga->pallook[(dat >> 24) & 0xff]; + for (x = 0; x <= svga->hdisp; x += 4) + { + uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + + svga->ma += 4; - svga->ma += 8; - p += 8; + *p++ = svga->pallook[dat & 0xff]; + *p++ = svga->pallook[(dat >> 8) & 0xff]; + *p++ = svga->pallook[(dat >> 16) & 0xff]; + *p++ = svga->pallook[(dat >> 24) & 0xff]; + } } + svga->ma &= svga->vram_display_mask; } } void svga_render_15bpp_lowres(svga_t *svga) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = (8 - (svga->scrollcache & 6)) + 24; @@ -526,21 +583,44 @@ void svga_render_15bpp_lowres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 4) + if (!svga->remap_required) { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + x) & svga->vram_display_mask]); + for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 4) + { + uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; - p[x] = p[x + 1] = video_15to32[dat & 0xffff]; - p[x + 2] = p[x + 3] = video_15to32[dat >> 16]; + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; + } + svga->ma += x << 1; + } + else + { + for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 2) + { + uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; + + svga->ma += 4; + } } - svga->ma += x << 1; svga->ma &= svga->vram_display_mask; } } void svga_render_15bpp_highres(svga_t *svga) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; @@ -550,32 +630,51 @@ void svga_render_15bpp_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 8) + if (!svga->remap_required) { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = video_15to32[dat & 0xffff]; - p[x + 1] = video_15to32[dat >> 16]; + for (x = 0; x <= svga->hdisp; x += 8) + { + uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x + 2] = video_15to32[dat & 0xffff]; - p[x + 3] = video_15to32[dat >> 16]; + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); - p[x + 4] = video_15to32[dat & 0xffff]; - p[x + 5] = video_15to32[dat >> 16]; + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; + } - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); - p[x + 6] = video_15to32[dat & 0xffff]; - p[x + 7] = video_15to32[dat >> 16]; + svga->ma += x << 1; + } + else + { + for (x = 0; x <= svga->hdisp; x += 2) + { + uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + + *p++ = video_15to32[dat & 0xffff]; + *p++ = video_15to32[dat >> 16]; + + svga->ma += 4; + } } - svga->ma += x << 1; svga->ma &= svga->vram_display_mask; } } void svga_render_16bpp_lowres(svga_t *svga) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = (8 - (svga->scrollcache & 6)) + 24; @@ -585,21 +684,44 @@ void svga_render_16bpp_lowres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 4) + if (!svga->remap_required) { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + x) & svga->vram_display_mask]); + for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 4) + { + uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x] = p[x + 1] = video_16to32[dat & 0xffff]; - p[x + 2] = p[x + 3] = video_16to32[dat >> 16]; + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + } + svga->ma += x << 1; + } + else + { + for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 2) + { + uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + + svga->ma += 4; + } } - svga->ma += x << 1; svga->ma &= svga->vram_display_mask; } } void svga_render_16bpp_highres(svga_t *svga) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; @@ -609,64 +731,124 @@ void svga_render_16bpp_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x += 8) + if (!svga->remap_required) { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); - p[x] = video_16to32[dat & 0xffff]; - p[x + 1] = video_16to32[dat >> 16]; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); - p[x + 2] = video_16to32[dat & 0xffff]; - p[x + 3] = video_16to32[dat >> 16]; + for (x = 0; x <= svga->hdisp; x += 8) + { + uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]); + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]); + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]); - p[x + 4] = video_16to32[dat & 0xffff]; - p[x + 5] = video_16to32[dat >> 16]; + dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + } - dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]); - p[x + 6] = video_16to32[dat & 0xffff]; - p[x + 7] = video_16to32[dat >> 16]; + svga->ma += x << 1; + } + else + { + for (x = 0; x <= svga->hdisp; x += 2) + { + uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + + *p++ = video_16to32[dat & 0xffff]; + *p++ = video_16to32[dat >> 16]; + + svga->ma += 4; + } } - svga->ma += x << 1; svga->ma &= svga->vram_display_mask; } } void svga_render_24bpp_lowres(svga_t *svga) { - int x, offset; - uint32_t fg; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + int x; + int offset = (8 - (svga->scrollcache & 6)) + 24; + uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset]; + if (svga->firstline_draw == 4000) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - offset = (8 - (svga->scrollcache & 6)) + 24; - - if (svga->swaprb) { - for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++) { - fg = svga->vram[svga->ma + 2] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 0] << 16); - svga->ma += 3; - svga->ma &= svga->vram_display_mask; - ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg; - } - } else { - for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++) - { - fg = svga->vram[svga->ma] | (svga->vram[(svga->ma + 1) & svga->vram_display_mask] << 8) | (svga->vram[(svga->ma + 2) & svga->vram_display_mask] << 16); - svga->ma += 3; - svga->ma &= svga->vram_display_mask; - ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg; - } + if (!svga->remap_required) + { + if (svga->swaprb) { + + for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++) + { + uint32_t fg = svga->vram[svga->ma + 2] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 0] << 16); + svga->ma += 3; + svga->ma &= svga->vram_display_mask; + p[0] = p[1] = fg; + + svga->ma += 12; + p += 8; + } + + } else { + + for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++) + { + uint32_t dat0 = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); + uint32_t dat1 = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); + uint32_t dat2 = *(uint32_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); + + p[0] = p[1] = dat0 & 0xffffff; + p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8); + p[4] = p[5] = (dat1 >> 16) | ((dat2 & 0xff) << 16); + p[6] = p[7] = dat2 >> 8; + + svga->ma += 12; + p += 8; + } + } + } + else + { + for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x += 4) + { + uint32_t dat0, dat1, dat2; + uint32_t addr; + + addr = svga->remap_func(svga, svga->ma); + dat0 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + addr = svga->remap_func(svga, svga->ma + 4); + dat1 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + addr = svga->remap_func(svga, svga->ma + 8); + dat2 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + + p[0] = p[1] = dat0 & 0xffffff; + p[2] = p[3] = (dat0 >> 24) | ((dat1 & 0xffff) << 8); + p[4] = p[5] = (dat1 >> 16) | ((dat2 & 0xff) << 16); + p[6] = p[7] = dat2 >> 8; + + svga->ma += 12; + p += 8; + } } } } void svga_render_24bpp_highres(svga_t *svga) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; @@ -676,41 +858,43 @@ void svga_render_24bpp_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - if (svga->swaprb) { - uint32_t dat; - for (x = 0; x <= svga->hdisp; x++) - { - dat = svga->vram[(svga->ma + 2) &svga->vram_display_mask] | (svga->vram[(svga->ma + 1) & svga->vram_display_mask] << 8) | (svga->vram[svga->ma + 0] << 16); - p[x] = dat; - svga->ma += 3; - svga->ma &= svga->vram_display_mask; - } - } else { - if ((svga->ma & svga->vram_display_mask) + svga->hdisp * 3 + 3 > svga->vram_display_mask) { - for (x = 0; x <= svga->hdisp; x++) { - uint32_t dat = (svga->vram[(svga->ma + 0) & svga->vram_display_mask] << 0) | - (svga->vram[(svga->ma + 1) & svga->vram_display_mask] << 8) | - (svga->vram[(svga->ma + 2) & svga->vram_display_mask] << 16); - p[x] = dat; - svga->ma += 3; - } - } else { - for (x = 0; x <= svga->hdisp; x += 4) { - uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); - p[x] = dat & 0xffffff; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + 3) & svga->vram_display_mask]); - p[x + 1] = dat & 0xffffff; - - dat = *(uint32_t *)(&svga->vram[(svga->ma + 6) & svga->vram_display_mask]); - p[x + 2] = dat & 0xffffff; + if (!svga->remap_required) + { + for (x = 0; x <= svga->hdisp; x += 4) + { + uint32_t dat0 = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]); + uint32_t dat1 = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]); + uint32_t dat2 = *(uint32_t *)(&svga->vram[(svga->ma + 8) & svga->vram_display_mask]); - dat = *(uint32_t *)(&svga->vram[(svga->ma + 9) & svga->vram_display_mask]); - p[x + 3] = dat & 0xffffff; + *p++ = dat0 & 0xffffff; + *p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8); + *p++ = (dat1 >> 16) | ((dat2 & 0xff) << 16); + *p++ = dat2 >> 8; - svga->ma += 12; + svga->ma += 12; + } + } + else + { + for (x = 0; x <= svga->hdisp; x += 4) + { + uint32_t dat0, dat1, dat2; + uint32_t addr; + + addr = svga->remap_func(svga, svga->ma); + dat0 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + addr = svga->remap_func(svga, svga->ma + 4); + dat1 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + addr = svga->remap_func(svga, svga->ma + 8); + dat2 = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + + *p++ = dat0 & 0xffffff; + *p++ = (dat0 >> 24) | ((dat1 & 0xffff) << 8); + *p++ = (dat1 >> 16) | ((dat2 & 0xff) << 16); + *p++ = dat2 >> 8; + + svga->ma += 12; } - } } svga->ma &= svga->vram_display_mask; } @@ -718,24 +902,40 @@ void svga_render_24bpp_highres(svga_t *svga) void svga_render_32bpp_lowres(svga_t *svga) { - int x, offset; - uint32_t fg; - - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { + int x; + int offset = (8 - (svga->scrollcache & 6)) + 24; + uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset]; + if (svga->firstline_draw == 4000) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - offset = (8 - (svga->scrollcache & 6)) + 24; - - for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++) + if (!svga->remap_required) { - fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16); - svga->ma += 4; - svga->ma &= svga->vram_display_mask; - ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg; + for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++) + { + uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + *p++ = dat & 0xffffff; + *p++ = dat & 0xffffff; + } + svga->ma += x * 4; + } + else + { + for (x = 0; x <= svga->hdisp << svga->horizontal_linedbl; x++) + { + uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t dat = *(uint32_t *)(&svga->vram[addr]); + *p++ = dat & 0xffffff; + *p++ = dat & 0xffffff; + svga->ma += 4; + } } + svga->ma &= svga->vram_display_mask; } } @@ -743,7 +943,9 @@ void svga_render_32bpp_lowres(svga_t *svga) 91%*/ void svga_render_32bpp_highres(svga_t *svga) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; @@ -753,56 +955,102 @@ void svga_render_32bpp_highres(svga_t *svga) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x++) + if (!svga->remap_required) + { + for (x = 0; x <= svga->hdisp; x++) + { + uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + *p++ = dat & 0xffffff; + } + svga->ma += x * 4; + } + else { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - p[x] = dat & 0xffffff; + for (x = 0; x <= svga->hdisp; x++) + { + uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + *p++ = dat & 0xffffff; + svga->ma += 4; + } } - svga->ma += 4; + svga->ma &= svga->vram_display_mask; } } void svga_render_ABGR8888_highres(svga_t *svga) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset]; - - if (svga->firstline_draw == 4000) + + if (svga->firstline_draw == 4000) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x++) + if (!svga->remap_required) { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + for (x = 0; x <= svga->hdisp; x++) + { + uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + *p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + } + svga->ma += x * 4; } - svga->ma += 4; + else + { + for (x = 0; x <= svga->hdisp; x++) + { + uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + *p++ = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16); + svga->ma += 4; + } + } + svga->ma &= svga->vram_display_mask; } } void svga_render_RGBA8888_highres(svga_t *svga) { - if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange) + uint32_t changed_addr = svga->remap_func(svga, svga->ma); + + if (svga->changedvram[changed_addr >> 12] || svga->changedvram[(changed_addr >> 12) + 1] || svga->fullchange) { int x; int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24; uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset]; - - if (svga->firstline_draw == 4000) + + if (svga->firstline_draw == 4000) svga->firstline_draw = svga->displine; svga->lastline_draw = svga->displine; - for (x = 0; x <= svga->hdisp; x++) + if (!svga->remap_required) + { + for (x = 0; x <= svga->hdisp; x++) + { + uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); + *p++ = dat >> 8; + } + svga->ma += x * 4; + } + else { - uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]); - p[x] = dat >> 8; + for (x = 0; x <= svga->hdisp; x++) + { + uint32_t addr = svga->remap_func(svga, svga->ma); + uint32_t dat = *(uint32_t *)(&svga->vram[addr & svga->vram_display_mask]); + *p++ = dat >> 8; + svga->ma += 4; + } } - svga->ma += 4; + svga->ma &= svga->vram_display_mask; } } diff --git a/pcem/vid_svga_render.h b/pcem/vid_svga_render.h index 06e5097e..e0f81e5e 100644 --- a/pcem/vid_svga_render.h +++ b/pcem/vid_svga_render.h @@ -9,7 +9,9 @@ extern int scrollcache; extern uint8_t edatlookup[4][4]; -void svga_render_null(svga_t* svga); +void svga_recalc_remap_func(svga_t *svga); + +void svga_render_null(svga_t *svga); void svga_render_blank(svga_t *svga); void svga_render_text_40(svga_t *svga); void svga_render_text_80(svga_t *svga); diff --git a/pcem/vid_svga_render_remap.h b/pcem/vid_svga_render_remap.h new file mode 100644 index 00000000..189f8466 --- /dev/null +++ b/pcem/vid_svga_render_remap.h @@ -0,0 +1,129 @@ +/*Variables : + byte/word/doubleword mode + word has MA13/MA15->MA0 + ET4000 treats doubleword as byte + row 0 -> MA13 + row 1 -> MA14 +*/ + +//S3 - enhanced mode mappings CR31.3 can force doubleword mode +//Cirrus Logic handles SVGA writes seperately +//S3, CL, TGUI blitters need checking + +//CL, S3, Mach64, ET4000, Banshee, TGUI all okay +//Still to check - ViRGE, HT216 +#define VAR_BYTE_MODE (0 << 0) +#define VAR_WORD_MODE_MA13 (1 << 0) +#define VAR_WORD_MODE_MA15 (2 << 0) +#define VAR_DWORD_MODE (3 << 0) +#define VAR_MODE_MASK (3 << 0) +#define VAR_ROW0_MA13 (1 << 2) +#define VAR_ROW1_MA14 (1 << 3) + +#define ADDRESS_REMAP_FUNC(nr) \ + static uint32_t address_remap_func_ ## nr(svga_t *svga, uint32_t in_addr) \ + { \ + uint32_t out_addr; \ + \ + switch (nr & VAR_MODE_MASK) \ + { \ + case VAR_BYTE_MODE: \ + out_addr = in_addr; \ + break; \ + \ + case VAR_WORD_MODE_MA13: \ + out_addr = ((in_addr << 1) & 0x1fff8) | \ + ((in_addr >> 13) & 0x4) | \ + (in_addr & ~0x1ffff); \ + break; \ + \ + case VAR_WORD_MODE_MA15: \ + out_addr = ((in_addr << 1) & 0x1fff8) | \ + ((in_addr >> 15) & 0x4) | \ + (in_addr & ~0x1ffff); \ + break; \ + \ + case VAR_DWORD_MODE: \ + out_addr = ((in_addr << 2) & 0x3fff0) | \ + ((in_addr >> 14) & 0xc) | \ + (in_addr & ~0x3ffff); \ + break; \ + } \ + \ + if (nr & VAR_ROW0_MA13) \ + out_addr = (out_addr & ~(1 << (13+2))) | \ + ((svga->sc & 1) ? (1 << (13+2)) : 0); \ + if (nr & VAR_ROW1_MA14) \ + out_addr = (out_addr & ~(1 << (14+2))) | \ + ((svga->sc & 2) ? (1 << (14+2)) : 0); \ + \ + return out_addr; \ + } + +ADDRESS_REMAP_FUNC(0) +ADDRESS_REMAP_FUNC(1) +ADDRESS_REMAP_FUNC(2) +ADDRESS_REMAP_FUNC(3) +ADDRESS_REMAP_FUNC(4) +ADDRESS_REMAP_FUNC(5) +ADDRESS_REMAP_FUNC(6) +ADDRESS_REMAP_FUNC(7) +ADDRESS_REMAP_FUNC(8) +ADDRESS_REMAP_FUNC(9) +ADDRESS_REMAP_FUNC(10) +ADDRESS_REMAP_FUNC(11) +ADDRESS_REMAP_FUNC(12) +ADDRESS_REMAP_FUNC(13) +ADDRESS_REMAP_FUNC(14) +ADDRESS_REMAP_FUNC(15) + +static uint32_t (*address_remap_funcs[16])(svga_t *svga, uint32_t in_addr) = +{ + address_remap_func_0, + address_remap_func_1, + address_remap_func_2, + address_remap_func_3, + address_remap_func_4, + address_remap_func_5, + address_remap_func_6, + address_remap_func_7, + address_remap_func_8, + address_remap_func_9, + address_remap_func_10, + address_remap_func_11, + address_remap_func_12, + address_remap_func_13, + address_remap_func_14, + address_remap_func_15 +}; + +void svga_recalc_remap_func(svga_t *svga) +{ + int func_nr; + + if (svga->fb_only) + func_nr = 0; + else + { + if (svga->force_dword_mode) + func_nr = VAR_DWORD_MODE; + else if (svga->crtc[0x14] & (1 << 6)) + func_nr = svga->packed_chain4 ? VAR_BYTE_MODE : VAR_DWORD_MODE; + else if (svga->crtc[0x17] & (1 << 6)) + func_nr = VAR_BYTE_MODE; + else if (svga->crtc[0x17] & (1 << 5)) + func_nr = VAR_WORD_MODE_MA15; + else + func_nr = VAR_WORD_MODE_MA13; + + if (!(svga->crtc[0x17] & (1 << 0))) + func_nr |= VAR_ROW0_MA13; + if (!(svga->crtc[0x17] & (1 << 1))) + func_nr |= VAR_ROW1_MA14; + } + +// pclog("svga_recalc_remap_func: fb_only=%i chain4=%i packed_chain4=%i crtc[14]=%02x crtc[17]=%02x func_nr=%i\n", +// svga->fb_only, svga->chain4, svga->packed_chain4, svga->crtc[0x14], svga->crtc[0x17], func_nr); + svga->remap_required = (func_nr != 0); + svga->remap_func = address_remap_funcs[func_nr]; +} diff --git a/pcem/vid_voodoo.cpp b/pcem/vid_voodoo.cpp index 4f5fcacb..37260741 100644 --- a/pcem/vid_voodoo.cpp +++ b/pcem/vid_voodoo.cpp @@ -952,6 +952,7 @@ void *voodoo_card_init() memset(voodoo, 0, sizeof(voodoo_t)); voodoo->bilinear_enabled = device_get_config_int("bilinear"); + voodoo->dithersub_enabled = device_get_config_int("dithersub"); voodoo->scrfilter = device_get_config_int("dacfilter"); voodoo->texture_size = device_get_config_int("texture_memory"); voodoo->texture_mask = (voodoo->texture_size << 20) - 1; @@ -1100,8 +1101,10 @@ void *voodoo_2d3d_card_init(int type) memset(voodoo, 0, sizeof(voodoo_t)); voodoo->bilinear_enabled = device_get_config_int("bilinear"); + voodoo->dithersub_enabled = device_get_config_int("dithersub"); voodoo->scrfilter = device_get_config_int("dacfilter"); voodoo->render_threads = device_get_config_int("render_threads"); + voodoo->odd_even_mask = voodoo->render_threads - 1; #ifndef NO_CODEGEN voodoo->use_recompiler = device_get_config_int("recompiler"); @@ -1410,6 +1413,12 @@ static device_config_t voodoo_config[] = .type = CONFIG_BINARY, .default_int = 1 }, + { + .name = "dithersub", + .description = "Dither subtraction", + .type = CONFIG_BINARY, + .default_int = 1 + }, { .name = "dacfilter", .description = "Screen Filter", diff --git a/pcem/vid_voodoo_banshee.cpp b/pcem/vid_voodoo_banshee.cpp index f84376ce..784e6e23 100644 --- a/pcem/vid_voodoo_banshee.cpp +++ b/pcem/vid_voodoo_banshee.cpp @@ -32,8 +32,7 @@ enum { TYPE_BANSHEE = 0, TYPE_V3_2000, - TYPE_V3_3000, - TYPE_V5_5500 + TYPE_V3_3000 }; typedef struct banshee_t @@ -150,7 +149,7 @@ enum #define VGAINIT0_EXTENDED_SHIFT_OUT (1 << 12) -#define VIDPROCCFG_VIDPROCON (1 << 0) +#define VIDPROCCFG_VIDPROC_ENABLE (1 << 0) #define VIDPROCCFG_CURSOR_MODE (1 << 1) #define VIDPROCCFG_INTERLACE (1 << 3) #define VIDPROCCFG_HALF_MODE (1 << 4) @@ -209,6 +208,9 @@ enum #define VIDSERIAL_I2C_SCK_R (1 << 26) #define VIDSERIAL_I2C_SDA_R (1 << 27) +#define MISCINIT0_Y_ORIGIN_SWAP_SHIFT (18) +#define MISCINIT0_Y_ORIGIN_SWAP_MASK (0xfff << MISCINIT0_Y_ORIGIN_SWAP_SHIFT) + static int banshee_vga_vsync_enabled(banshee_t *banshee) { if (!(banshee->svga.crtc[0x11] & 0x20) && (banshee->svga.crtc[0x11] & 0x10) && ((banshee->pciInit0 >> 18) & 1) != 0) @@ -433,7 +435,7 @@ static void banshee_recalctimings(svga_t *svga) svga->interlace = 0; // if (banshee->vgaInit0 & VGAINIT0_EXTENDED_SHIFT_OUT) - if (banshee->vidProcCfg & VIDPROCCFG_VIDPROCON) + if (banshee->vidProcCfg & VIDPROCCFG_VIDPROC_ENABLE) { // this is some VGA-only feature? G-REX driver sets it and still expects normal 640x480 display. svga->lowres = 0; @@ -529,6 +531,8 @@ static void banshee_recalctimings(svga_t *svga) svga->video_res_override = 0; } + svga->fb_only = (banshee->vidProcCfg & VIDPROCCFG_VIDPROC_ENABLE); + svga->horizontal_linedbl = svga->dispend * 9 / 10 >= svga->hdisp; if (((svga->miscout >> 2) & 3) == 3) @@ -656,7 +660,7 @@ static void banshee_ext_outl(uint16_t addr, uint32_t val, void *p) case Video_vidProcCfg: banshee->vidProcCfg = val; - //pclog("vidProcCfg=%08x\n", val); +// pclog("vidProcCfg=%08x\n", val); banshee->overlay_pix_fmt = (val & VIDPROCCFG_OVERLAY_PIX_FORMAT_MASK) >> VIDPROCCFG_OVERLAY_PIX_FORMAT_SHIFT; svga->hwcursor.ena = val & VIDPROCCFG_HWCURSOR_ENA; svga->fullchange = changeframecount; @@ -2426,7 +2430,7 @@ static uint8_t banshee_pci_read(int func, int addr, void *p) case 0x00: ret = 0x1a; break; /*3DFX*/ case 0x01: ret = 0x12; break; - case 0x02: ret = (banshee->type == TYPE_BANSHEE) ? 0x03 : (banshee->type == TYPE_V5_5500 ? 0x09 : 0x05); break; + case 0x02: ret = (banshee->type == TYPE_BANSHEE) ? 0x03 : 0x05; break; case 0x03: ret = 0x00; break; case 0x04: ret = banshee->pci_regs[0x04] & 0x27; break; @@ -2483,7 +2487,7 @@ static void banshee_pci_write(int func, int addr, uint8_t val, void *p) { banshee_t *banshee = (banshee_t *)p; // svga_t *svga = &banshee->svga; - uint32_t basemask = banshee->type == TYPE_V5_5500 ? 0xfc : 0xfe; + uint32_t basemask = 0xfe; if (func) return; @@ -2600,6 +2604,12 @@ static device_config_t banshee_sgram_config[] = .type = CONFIG_BINARY, .default_int = 1 }, + { + .name = "dithersub", + .description = "Dither subtraction", + .type = CONFIG_BINARY, + .default_int = 1 + }, { .name = "dacfilter", .description = "Screen Filter", @@ -2651,6 +2661,12 @@ static device_config_t banshee_sdram_config[] = .type = CONFIG_BINARY, .default_int = 1 }, + { + .name = "dithersub", + .description = "Dither subtraction", + .type = CONFIG_BINARY, + .default_int = 1 + }, { .name = "dacfilter", .description = "Screen Filter", @@ -2821,14 +2837,6 @@ static void *banshee_init_common(char *fn, int has_sgram, int type, int voodoo_t banshee->pci_regs[0x2e] = 0x3a; banshee->pci_regs[0x2f] = 0x00; break; - - case TYPE_V5_5500: - banshee->pci_regs[0x2c] = 0x1a; - banshee->pci_regs[0x2d] = 0x12; - banshee->pci_regs[0x2e] = 0x09; - banshee->pci_regs[0x2f] = 0x00; - break; - } banshee->svga.vblank_start = banshee_vblank_start; @@ -2850,11 +2858,7 @@ static void *v3_2000_init() } static void *v3_3000_init() { - return banshee_init_common("voodoo3_3000/3k12sd.rom", 0, TYPE_V3_3000, VOODOO_3); -} -static void *v5_5500_init() -{ - return banshee_init_common("voodoo3_3000/3k12sd.rom", 0, TYPE_V5_5500, VOODOO_3); + return banshee_init_common("voodoo3_3000/3k12sd.rom", 0, TYPE_V3_3000, VOODOO_3); } static int banshee_available() @@ -3039,16 +3043,3 @@ device_t voodoo_3_3000_device = banshee_add_status_info, banshee_sdram_config }; - -device_t voodoo_5_5500_device = -{ - "Voodoo 5 5500 PCI", - DEVICE_PCI, - v5_5500_init, - banshee_close, - v3_3000_available, - banshee_speed_changed, - banshee_force_redraw, - banshee_add_status_info, - banshee_sdram_config -}; diff --git a/pcem/vid_voodoo_banshee.h b/pcem/vid_voodoo_banshee.h index 20c8808e..ddd7e3fd 100644 --- a/pcem/vid_voodoo_banshee.h +++ b/pcem/vid_voodoo_banshee.h @@ -2,6 +2,5 @@ extern device_t voodoo_banshee_device; extern device_t creative_voodoo_banshee_device; extern device_t voodoo_3_2000_device; extern device_t voodoo_3_3000_device; -extern device_t voodoo_5_5500_device; void banshee_set_overlay_addr(void *p, uint32_t addr); diff --git a/pcem/vid_voodoo_blitter.cpp b/pcem/vid_voodoo_blitter.cpp index 01048f9a..af7e2046 100644 --- a/pcem/vid_voodoo_blitter.cpp +++ b/pcem/vid_voodoo_blitter.cpp @@ -409,8 +409,10 @@ void voodoo_fastfill(voodoo_t *voodoo, voodoo_params_t *params) if (params->fbzMode & (1 << 17)) { - high_y = voodoo->v_disp - params->clipLowY; - low_y = voodoo->v_disp - params->clipHighY; + int y_origin = (voodoo->type >= VOODOO_BANSHEE) ? (voodoo->y_origin_swap+1) : voodoo->v_disp; + + high_y = y_origin - params->clipLowY; + low_y = y_origin - params->clipHighY; } else { diff --git a/pcem/vid_voodoo_common.h b/pcem/vid_voodoo_common.h index df261af7..bfd0f7f4 100644 --- a/pcem/vid_voodoo_common.h +++ b/pcem/vid_voodoo_common.h @@ -283,6 +283,7 @@ typedef struct voodoo_t int swap_pending; int bilinear_enabled; + int dithersub_enabled; int fb_size; uint32_t fb_mask; @@ -456,6 +457,8 @@ typedef struct voodoo_t uint32_t tile_base, tile_stride; int tile_stride_shift, tile_x, tile_x_real; + int y_origin_swap; + int read_time, write_time, burst_time; pc_timer_t wake_timer; diff --git a/pcem/vid_voodoo_dither.h b/pcem/vid_voodoo_dither.h index 67d48388..dc7c415e 100644 --- a/pcem/vid_voodoo_dither.h +++ b/pcem/vid_voodoo_dither.h @@ -5134,3 +5134,5147 @@ static const uint8_t dither_g2x2[256][2][2] = }, }; + + +/* Dither subtraction */ + +static const uint8_t dithersub_rb[256][4][4] = +{ + { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + }, + { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + }, + { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + }, + { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + }, + { + {9, 5, 8, 4}, + {3, 7, 2, 6}, + {7, 3, 8, 4}, + {1, 5, 2, 6}, + }, + { + {10, 6, 9, 5}, + {4, 8, 3, 7}, + {8, 4, 9, 5}, + {2, 6, 3, 7}, + }, + { + {11, 7, 10, 6}, + {5, 9, 4, 8}, + {9, 5, 10, 6}, + {3, 7, 4, 8}, + }, + { + {12, 8, 11, 7}, + {6, 10, 5, 9}, + {10, 6, 11, 7}, + {4, 8, 5, 9}, + }, + { + {13, 9, 12, 8}, + {7, 11, 6, 10}, + {11, 7, 12, 8}, + {5, 9, 6, 10}, + }, + { + {14, 10, 13, 9}, + {8, 12, 7, 11}, + {12, 8, 13, 9}, + {6, 10, 7, 11}, + }, + { + {15, 11, 14, 10}, + {9, 13, 8, 12}, + {13, 9, 14, 10}, + {7, 11, 8, 12}, + }, + { + {16, 12, 15, 11}, + {10, 14, 9, 13}, + {14, 10, 15, 11}, + {8, 12, 9, 13}, + }, + { + {17, 13, 16, 12}, + {11, 15, 10, 14}, + {15, 11, 16, 12}, + {9, 13, 10, 14}, + }, + { + {18, 14, 17, 13}, + {12, 16, 11, 15}, + {16, 12, 17, 13}, + {10, 14, 11, 15}, + }, + { + {19, 15, 18, 14}, + {13, 17, 12, 16}, + {17, 13, 18, 14}, + {11, 15, 12, 16}, + }, + { + {20, 16, 19, 15}, + {14, 18, 13, 17}, + {18, 14, 19, 15}, + {12, 16, 13, 17}, + }, + { + {21, 17, 20, 16}, + {15, 19, 14, 18}, + {19, 15, 20, 16}, + {13, 17, 14, 18}, + }, + { + {22, 18, 21, 17}, + {16, 20, 15, 19}, + {20, 16, 21, 17}, + {14, 18, 15, 19}, + }, + { + {23, 19, 22, 18}, + {17, 21, 16, 20}, + {21, 17, 22, 18}, + {15, 19, 16, 20}, + }, + { + {24, 20, 23, 19}, + {18, 22, 17, 21}, + {22, 18, 23, 19}, + {16, 20, 17, 21}, + }, + { + {25, 21, 24, 20}, + {19, 23, 18, 22}, + {23, 19, 24, 20}, + {17, 21, 18, 22}, + }, + { + {26, 22, 25, 21}, + {20, 24, 19, 23}, + {24, 20, 25, 21}, + {18, 22, 19, 23}, + }, + { + {27, 23, 26, 22}, + {21, 25, 20, 24}, + {25, 21, 26, 22}, + {19, 23, 20, 24}, + }, + { + {28, 24, 27, 23}, + {22, 26, 21, 25}, + {26, 22, 27, 23}, + {20, 24, 21, 25}, + }, + { + {29, 25, 28, 24}, + {23, 27, 22, 26}, + {27, 23, 28, 24}, + {21, 25, 22, 26}, + }, + { + {30, 26, 29, 25}, + {24, 28, 23, 27}, + {28, 24, 29, 25}, + {22, 26, 23, 27}, + }, + { + {31, 27, 30, 26}, + {25, 29, 24, 28}, + {29, 25, 30, 26}, + {23, 27, 24, 28}, + }, + { + {32, 28, 31, 27}, + {26, 30, 25, 29}, + {30, 26, 31, 27}, + {24, 28, 25, 29}, + }, + { + {33, 29, 32, 28}, + {27, 31, 26, 30}, + {31, 27, 32, 28}, + {25, 29, 26, 30}, + }, + { + {34, 30, 33, 29}, + {28, 32, 27, 31}, + {32, 28, 33, 29}, + {26, 30, 27, 31}, + }, + { + {35, 31, 34, 30}, + {29, 33, 28, 32}, + {33, 29, 34, 30}, + {27, 31, 28, 32}, + }, + { + {36, 32, 35, 31}, + {30, 34, 29, 33}, + {34, 30, 35, 31}, + {28, 32, 29, 33}, + }, + { + {37, 33, 36, 32}, + {31, 35, 30, 34}, + {35, 31, 36, 32}, + {29, 33, 30, 34}, + }, + { + {38, 34, 37, 33}, + {32, 36, 31, 35}, + {36, 32, 37, 33}, + {30, 34, 31, 35}, + }, + { + {39, 35, 38, 34}, + {33, 37, 32, 36}, + {37, 33, 38, 34}, + {31, 35, 32, 36}, + }, + { + {40, 36, 39, 35}, + {34, 38, 33, 37}, + {38, 34, 39, 35}, + {32, 36, 33, 37}, + }, + { + {41, 37, 40, 36}, + {35, 39, 34, 38}, + {39, 35, 40, 36}, + {33, 37, 34, 38}, + }, + { + {42, 38, 41, 37}, + {36, 40, 35, 39}, + {40, 36, 41, 37}, + {34, 38, 35, 39}, + }, + { + {43, 39, 42, 38}, + {37, 41, 36, 40}, + {41, 37, 42, 38}, + {35, 39, 36, 40}, + }, + { + {44, 40, 43, 39}, + {38, 42, 37, 41}, + {42, 38, 43, 39}, + {36, 40, 37, 41}, + }, + { + {45, 41, 44, 40}, + {39, 43, 38, 42}, + {43, 39, 44, 40}, + {37, 41, 38, 42}, + }, + { + {46, 42, 45, 41}, + {40, 44, 39, 43}, + {44, 40, 45, 41}, + {38, 42, 39, 43}, + }, + { + {47, 43, 46, 42}, + {41, 45, 40, 44}, + {45, 41, 46, 42}, + {39, 43, 40, 44}, + }, + { + {48, 44, 47, 43}, + {42, 46, 41, 45}, + {46, 42, 47, 43}, + {40, 44, 41, 45}, + }, + { + {49, 45, 48, 44}, + {43, 47, 42, 46}, + {47, 43, 48, 44}, + {41, 45, 42, 46}, + }, + { + {50, 46, 49, 45}, + {44, 48, 43, 47}, + {48, 44, 49, 45}, + {42, 46, 43, 47}, + }, + { + {51, 47, 50, 46}, + {45, 49, 44, 48}, + {49, 45, 50, 46}, + {43, 47, 44, 48}, + }, + { + {52, 48, 51, 47}, + {46, 50, 45, 49}, + {50, 46, 51, 47}, + {44, 48, 45, 49}, + }, + { + {53, 49, 52, 48}, + {47, 51, 46, 50}, + {51, 47, 52, 48}, + {45, 49, 46, 50}, + }, + { + {54, 50, 53, 49}, + {48, 52, 47, 51}, + {52, 48, 53, 49}, + {46, 50, 47, 51}, + }, + { + {55, 51, 54, 50}, + {49, 53, 48, 52}, + {53, 49, 54, 50}, + {47, 51, 48, 52}, + }, + { + {56, 52, 55, 51}, + {50, 54, 49, 53}, + {54, 50, 55, 51}, + {48, 52, 49, 53}, + }, + { + {57, 53, 56, 52}, + {51, 55, 50, 54}, + {55, 51, 56, 52}, + {49, 53, 50, 54}, + }, + { + {58, 54, 57, 53}, + {52, 56, 51, 55}, + {56, 52, 57, 53}, + {50, 54, 51, 55}, + }, + { + {59, 55, 58, 54}, + {53, 57, 52, 56}, + {57, 53, 58, 54}, + {51, 55, 52, 56}, + }, + { + {60, 56, 59, 55}, + {54, 58, 53, 57}, + {58, 54, 59, 55}, + {52, 56, 53, 57}, + }, + { + {61, 57, 60, 56}, + {55, 59, 54, 58}, + {59, 55, 60, 56}, + {53, 57, 54, 58}, + }, + { + {62, 58, 61, 57}, + {56, 60, 55, 59}, + {60, 56, 61, 57}, + {54, 58, 55, 59}, + }, + { + {63, 59, 62, 58}, + {57, 61, 56, 60}, + {61, 57, 62, 58}, + {55, 59, 56, 60}, + }, + { + {64, 60, 63, 59}, + {58, 62, 57, 61}, + {62, 58, 63, 59}, + {56, 60, 57, 61}, + }, + { + {65, 61, 64, 60}, + {59, 63, 58, 62}, + {63, 59, 64, 60}, + {57, 61, 58, 62}, + }, + { + {66, 62, 65, 61}, + {60, 64, 59, 63}, + {64, 60, 65, 61}, + {58, 62, 59, 63}, + }, + { + {67, 63, 66, 62}, + {61, 65, 60, 64}, + {65, 61, 66, 62}, + {59, 63, 60, 64}, + }, + { + {68, 64, 67, 63}, + {62, 66, 61, 65}, + {66, 62, 67, 63}, + {60, 64, 61, 65}, + }, + { + {69, 65, 68, 64}, + {63, 67, 62, 66}, + {67, 63, 68, 64}, + {61, 65, 62, 66}, + }, + { + {70, 66, 69, 65}, + {64, 68, 63, 67}, + {68, 64, 69, 65}, + {62, 66, 63, 67}, + }, + { + {71, 67, 70, 66}, + {65, 69, 64, 68}, + {69, 65, 70, 66}, + {63, 67, 64, 68}, + }, + { + {72, 68, 71, 67}, + {66, 70, 65, 69}, + {70, 66, 71, 67}, + {64, 68, 65, 69}, + }, + { + {73, 69, 72, 68}, + {67, 71, 66, 70}, + {71, 67, 72, 68}, + {65, 69, 66, 70}, + }, + { + {74, 70, 73, 69}, + {68, 72, 67, 71}, + {72, 68, 73, 69}, + {66, 70, 67, 71}, + }, + { + {75, 71, 74, 70}, + {69, 73, 68, 72}, + {73, 69, 74, 70}, + {67, 71, 68, 72}, + }, + { + {76, 72, 75, 71}, + {70, 74, 69, 73}, + {74, 70, 75, 71}, + {68, 72, 69, 73}, + }, + { + {77, 73, 76, 72}, + {71, 75, 70, 74}, + {75, 71, 76, 72}, + {69, 73, 70, 74}, + }, + { + {78, 74, 77, 73}, + {72, 76, 71, 75}, + {76, 72, 77, 73}, + {70, 74, 71, 75}, + }, + { + {79, 75, 78, 74}, + {73, 77, 72, 76}, + {77, 73, 78, 74}, + {71, 75, 72, 76}, + }, + { + {80, 76, 79, 75}, + {74, 78, 73, 77}, + {78, 74, 79, 75}, + {72, 76, 73, 77}, + }, + { + {81, 77, 80, 76}, + {75, 79, 74, 78}, + {79, 75, 80, 76}, + {73, 77, 74, 78}, + }, + { + {82, 78, 81, 77}, + {76, 80, 75, 79}, + {80, 76, 81, 77}, + {74, 78, 75, 79}, + }, + { + {83, 79, 82, 78}, + {77, 81, 76, 80}, + {81, 77, 82, 78}, + {75, 79, 76, 80}, + }, + { + {84, 80, 83, 79}, + {78, 82, 77, 81}, + {82, 78, 83, 79}, + {76, 80, 77, 81}, + }, + { + {85, 81, 84, 80}, + {79, 83, 78, 82}, + {83, 79, 84, 80}, + {77, 81, 78, 82}, + }, + { + {86, 82, 85, 81}, + {80, 84, 79, 83}, + {84, 80, 85, 81}, + {78, 82, 79, 83}, + }, + { + {87, 83, 86, 82}, + {81, 85, 80, 84}, + {85, 81, 86, 82}, + {79, 83, 80, 84}, + }, + { + {88, 84, 87, 83}, + {82, 86, 81, 85}, + {86, 82, 87, 83}, + {80, 84, 81, 85}, + }, + { + {89, 85, 88, 84}, + {83, 87, 82, 86}, + {87, 83, 88, 84}, + {81, 85, 82, 86}, + }, + { + {90, 86, 89, 85}, + {84, 88, 83, 87}, + {88, 84, 89, 85}, + {82, 86, 83, 87}, + }, + { + {91, 87, 90, 86}, + {85, 89, 84, 88}, + {89, 85, 90, 86}, + {83, 87, 84, 88}, + }, + { + {92, 88, 91, 87}, + {86, 90, 85, 89}, + {90, 86, 91, 87}, + {84, 88, 85, 89}, + }, + { + {93, 89, 92, 88}, + {87, 91, 86, 90}, + {91, 87, 92, 88}, + {85, 89, 86, 90}, + }, + { + {94, 90, 93, 89}, + {88, 92, 87, 91}, + {92, 88, 93, 89}, + {86, 90, 87, 91}, + }, + { + {95, 91, 94, 90}, + {89, 93, 88, 92}, + {93, 89, 94, 90}, + {87, 91, 88, 92}, + }, + { + {96, 92, 95, 91}, + {90, 94, 89, 93}, + {94, 90, 95, 91}, + {88, 92, 89, 93}, + }, + { + {97, 93, 96, 92}, + {91, 95, 90, 94}, + {95, 91, 96, 92}, + {89, 93, 90, 94}, + }, + { + {98, 94, 97, 93}, + {92, 96, 91, 95}, + {96, 92, 97, 93}, + {90, 94, 91, 95}, + }, + { + {99, 95, 98, 94}, + {93, 97, 92, 96}, + {97, 93, 98, 94}, + {91, 95, 92, 96}, + }, + { + {100, 96, 99, 95}, + {94, 98, 93, 97}, + {98, 94, 99, 95}, + {92, 96, 93, 97}, + }, + { + {101, 97, 100, 96}, + {95, 99, 94, 98}, + {99, 95, 100, 96}, + {93, 97, 94, 98}, + }, + { + {102, 98, 101, 97}, + {96, 100, 95, 99}, + {100, 96, 101, 97}, + {94, 98, 95, 99}, + }, + { + {103, 99, 102, 98}, + {97, 101, 96, 100}, + {101, 97, 102, 98}, + {95, 99, 96, 100}, + }, + { + {104, 100, 103, 99}, + {98, 102, 97, 101}, + {102, 98, 103, 99}, + {96, 100, 97, 101}, + }, + { + {105, 101, 104, 100}, + {99, 103, 98, 102}, + {103, 99, 104, 100}, + {97, 101, 98, 102}, + }, + { + {106, 102, 105, 101}, + {100, 104, 99, 103}, + {104, 100, 105, 101}, + {98, 102, 99, 103}, + }, + { + {107, 103, 106, 102}, + {101, 105, 100, 104}, + {105, 101, 106, 102}, + {99, 103, 100, 104}, + }, + { + {108, 104, 107, 103}, + {102, 106, 101, 105}, + {106, 102, 107, 103}, + {100, 104, 101, 105}, + }, + { + {109, 105, 108, 104}, + {103, 107, 102, 106}, + {107, 103, 108, 104}, + {101, 105, 102, 106}, + }, + { + {110, 106, 109, 105}, + {104, 108, 103, 107}, + {108, 104, 109, 105}, + {102, 106, 103, 107}, + }, + { + {111, 107, 110, 106}, + {105, 109, 104, 108}, + {109, 105, 110, 106}, + {103, 107, 104, 108}, + }, + { + {112, 108, 111, 107}, + {106, 110, 105, 109}, + {110, 106, 111, 107}, + {104, 108, 105, 109}, + }, + { + {113, 109, 112, 108}, + {107, 111, 106, 110}, + {111, 107, 112, 108}, + {105, 109, 106, 110}, + }, + { + {114, 110, 113, 109}, + {108, 112, 107, 111}, + {112, 108, 113, 109}, + {106, 110, 107, 111}, + }, + { + {115, 111, 114, 110}, + {109, 113, 108, 112}, + {113, 109, 114, 110}, + {107, 111, 108, 112}, + }, + { + {116, 112, 115, 111}, + {110, 114, 109, 113}, + {114, 110, 115, 111}, + {108, 112, 109, 113}, + }, + { + {117, 113, 116, 112}, + {111, 115, 110, 114}, + {115, 111, 116, 112}, + {109, 113, 110, 114}, + }, + { + {118, 114, 117, 113}, + {112, 116, 111, 115}, + {116, 112, 117, 113}, + {110, 114, 111, 115}, + }, + { + {119, 115, 118, 114}, + {113, 117, 112, 116}, + {117, 113, 118, 114}, + {111, 115, 112, 116}, + }, + { + {120, 116, 119, 115}, + {114, 118, 113, 117}, + {118, 114, 119, 115}, + {112, 116, 113, 117}, + }, + { + {121, 117, 120, 116}, + {115, 119, 114, 118}, + {119, 115, 120, 116}, + {113, 117, 114, 118}, + }, + { + {122, 118, 121, 117}, + {116, 120, 115, 119}, + {120, 116, 121, 117}, + {114, 118, 115, 119}, + }, + { + {123, 119, 122, 118}, + {117, 121, 116, 120}, + {121, 117, 122, 118}, + {115, 119, 116, 120}, + }, + { + {124, 120, 123, 119}, + {118, 122, 117, 121}, + {122, 118, 123, 119}, + {116, 120, 117, 121}, + }, + { + {125, 121, 124, 120}, + {119, 123, 118, 122}, + {123, 119, 124, 120}, + {117, 121, 118, 122}, + }, + { + {126, 122, 125, 121}, + {120, 124, 119, 123}, + {124, 120, 125, 121}, + {118, 122, 119, 123}, + }, + { + {127, 123, 126, 122}, + {121, 125, 120, 124}, + {125, 121, 126, 122}, + {119, 123, 120, 124}, + }, + { + {128, 124, 127, 123}, + {122, 126, 121, 125}, + {126, 122, 127, 123}, + {120, 124, 121, 125}, + }, + { + {129, 125, 128, 124}, + {123, 127, 122, 126}, + {127, 123, 128, 124}, + {121, 125, 122, 126}, + }, + { + {130, 126, 129, 125}, + {124, 128, 123, 127}, + {128, 124, 129, 125}, + {122, 126, 123, 127}, + }, + { + {131, 127, 130, 126}, + {125, 129, 124, 128}, + {129, 125, 130, 126}, + {123, 127, 124, 128}, + }, + { + {132, 128, 131, 127}, + {126, 130, 125, 129}, + {130, 126, 131, 127}, + {124, 128, 125, 129}, + }, + { + {133, 129, 132, 128}, + {127, 131, 126, 130}, + {131, 127, 132, 128}, + {125, 129, 126, 130}, + }, + { + {134, 130, 133, 129}, + {128, 132, 127, 131}, + {132, 128, 133, 129}, + {126, 130, 127, 131}, + }, + { + {135, 131, 134, 130}, + {129, 133, 128, 132}, + {133, 129, 134, 130}, + {127, 131, 128, 132}, + }, + { + {136, 132, 135, 131}, + {130, 134, 129, 133}, + {134, 130, 135, 131}, + {128, 132, 129, 133}, + }, + { + {137, 133, 136, 132}, + {131, 135, 130, 134}, + {135, 131, 136, 132}, + {129, 133, 130, 134}, + }, + { + {138, 134, 137, 133}, + {132, 136, 131, 135}, + {136, 132, 137, 133}, + {130, 134, 131, 135}, + }, + { + {139, 135, 138, 134}, + {133, 137, 132, 136}, + {137, 133, 138, 134}, + {131, 135, 132, 136}, + }, + { + {140, 136, 139, 135}, + {134, 138, 133, 137}, + {138, 134, 139, 135}, + {132, 136, 133, 137}, + }, + { + {141, 137, 140, 136}, + {135, 139, 134, 138}, + {139, 135, 140, 136}, + {133, 137, 134, 138}, + }, + { + {142, 138, 141, 137}, + {136, 140, 135, 139}, + {140, 136, 141, 137}, + {134, 138, 135, 139}, + }, + { + {143, 139, 142, 138}, + {137, 141, 136, 140}, + {141, 137, 142, 138}, + {135, 139, 136, 140}, + }, + { + {144, 140, 143, 139}, + {138, 142, 137, 141}, + {142, 138, 143, 139}, + {136, 140, 137, 141}, + }, + { + {145, 141, 144, 140}, + {139, 143, 138, 142}, + {143, 139, 144, 140}, + {137, 141, 138, 142}, + }, + { + {146, 142, 145, 141}, + {140, 144, 139, 143}, + {144, 140, 145, 141}, + {138, 142, 139, 143}, + }, + { + {147, 143, 146, 142}, + {141, 145, 140, 144}, + {145, 141, 146, 142}, + {139, 143, 140, 144}, + }, + { + {148, 144, 147, 143}, + {142, 146, 141, 145}, + {146, 142, 147, 143}, + {140, 144, 141, 145}, + }, + { + {149, 145, 148, 144}, + {143, 147, 142, 146}, + {147, 143, 148, 144}, + {141, 145, 142, 146}, + }, + { + {150, 146, 149, 145}, + {144, 148, 143, 147}, + {148, 144, 149, 145}, + {142, 146, 143, 147}, + }, + { + {151, 147, 150, 146}, + {145, 149, 144, 148}, + {149, 145, 150, 146}, + {143, 147, 144, 148}, + }, + { + {152, 148, 151, 147}, + {146, 150, 145, 149}, + {150, 146, 151, 147}, + {144, 148, 145, 149}, + }, + { + {153, 149, 152, 148}, + {147, 151, 146, 150}, + {151, 147, 152, 148}, + {145, 149, 146, 150}, + }, + { + {154, 150, 153, 149}, + {148, 152, 147, 151}, + {152, 148, 153, 149}, + {146, 150, 147, 151}, + }, + { + {155, 151, 154, 150}, + {149, 153, 148, 152}, + {153, 149, 154, 150}, + {147, 151, 148, 152}, + }, + { + {156, 152, 155, 151}, + {150, 154, 149, 153}, + {154, 150, 155, 151}, + {148, 152, 149, 153}, + }, + { + {157, 153, 156, 152}, + {151, 155, 150, 154}, + {155, 151, 156, 152}, + {149, 153, 150, 154}, + }, + { + {158, 154, 157, 153}, + {152, 156, 151, 155}, + {156, 152, 157, 153}, + {150, 154, 151, 155}, + }, + { + {159, 155, 158, 154}, + {153, 157, 152, 156}, + {157, 153, 158, 154}, + {151, 155, 152, 156}, + }, + { + {160, 156, 159, 155}, + {154, 158, 153, 157}, + {158, 154, 159, 155}, + {152, 156, 153, 157}, + }, + { + {161, 157, 160, 156}, + {155, 159, 154, 158}, + {159, 155, 160, 156}, + {153, 157, 154, 158}, + }, + { + {162, 158, 161, 157}, + {156, 160, 155, 159}, + {160, 156, 161, 157}, + {154, 158, 155, 159}, + }, + { + {163, 159, 162, 158}, + {157, 161, 156, 160}, + {161, 157, 162, 158}, + {155, 159, 156, 160}, + }, + { + {164, 160, 163, 159}, + {158, 162, 157, 161}, + {162, 158, 163, 159}, + {156, 160, 157, 161}, + }, + { + {165, 161, 164, 160}, + {159, 163, 158, 162}, + {163, 159, 164, 160}, + {157, 161, 158, 162}, + }, + { + {166, 162, 165, 161}, + {160, 164, 159, 163}, + {164, 160, 165, 161}, + {158, 162, 159, 163}, + }, + { + {167, 163, 166, 162}, + {161, 165, 160, 164}, + {165, 161, 166, 162}, + {159, 163, 160, 164}, + }, + { + {168, 164, 167, 163}, + {162, 166, 161, 165}, + {166, 162, 167, 163}, + {160, 164, 161, 165}, + }, + { + {169, 165, 168, 164}, + {163, 167, 162, 166}, + {167, 163, 168, 164}, + {161, 165, 162, 166}, + }, + { + {170, 166, 169, 165}, + {164, 168, 163, 167}, + {168, 164, 169, 165}, + {162, 166, 163, 167}, + }, + { + {171, 167, 170, 166}, + {165, 169, 164, 168}, + {169, 165, 170, 166}, + {163, 167, 164, 168}, + }, + { + {172, 168, 171, 167}, + {166, 170, 165, 169}, + {170, 166, 171, 167}, + {164, 168, 165, 169}, + }, + { + {173, 169, 172, 168}, + {167, 171, 166, 170}, + {171, 167, 172, 168}, + {165, 169, 166, 170}, + }, + { + {174, 170, 173, 169}, + {168, 172, 167, 171}, + {172, 168, 173, 169}, + {166, 170, 167, 171}, + }, + { + {175, 171, 174, 170}, + {169, 173, 168, 172}, + {173, 169, 174, 170}, + {167, 171, 168, 172}, + }, + { + {176, 172, 175, 171}, + {170, 174, 169, 173}, + {174, 170, 175, 171}, + {168, 172, 169, 173}, + }, + { + {177, 173, 176, 172}, + {171, 175, 170, 174}, + {175, 171, 176, 172}, + {169, 173, 170, 174}, + }, + { + {178, 174, 177, 173}, + {172, 176, 171, 175}, + {176, 172, 177, 173}, + {170, 174, 171, 175}, + }, + { + {179, 175, 178, 174}, + {173, 177, 172, 176}, + {177, 173, 178, 174}, + {171, 175, 172, 176}, + }, + { + {180, 176, 179, 175}, + {174, 178, 173, 177}, + {178, 174, 179, 175}, + {172, 176, 173, 177}, + }, + { + {181, 177, 180, 176}, + {175, 179, 174, 178}, + {179, 175, 180, 176}, + {173, 177, 174, 178}, + }, + { + {182, 178, 181, 177}, + {176, 180, 175, 179}, + {180, 176, 181, 177}, + {174, 178, 175, 179}, + }, + { + {183, 179, 182, 178}, + {177, 181, 176, 180}, + {181, 177, 182, 178}, + {175, 179, 176, 180}, + }, + { + {184, 180, 183, 179}, + {178, 182, 177, 181}, + {182, 178, 183, 179}, + {176, 180, 177, 181}, + }, + { + {185, 181, 184, 180}, + {179, 183, 178, 182}, + {183, 179, 184, 180}, + {177, 181, 178, 182}, + }, + { + {186, 182, 185, 181}, + {180, 184, 179, 183}, + {184, 180, 185, 181}, + {178, 182, 179, 183}, + }, + { + {187, 183, 186, 182}, + {181, 185, 180, 184}, + {185, 181, 186, 182}, + {179, 183, 180, 184}, + }, + { + {188, 184, 187, 183}, + {182, 186, 181, 185}, + {186, 182, 187, 183}, + {180, 184, 181, 185}, + }, + { + {189, 185, 188, 184}, + {183, 187, 182, 186}, + {187, 183, 188, 184}, + {181, 185, 182, 186}, + }, + { + {190, 186, 189, 185}, + {184, 188, 183, 187}, + {188, 184, 189, 185}, + {182, 186, 183, 187}, + }, + { + {191, 187, 190, 186}, + {185, 189, 184, 188}, + {189, 185, 190, 186}, + {183, 187, 184, 188}, + }, + { + {192, 188, 191, 187}, + {186, 190, 185, 189}, + {190, 186, 191, 187}, + {184, 188, 185, 189}, + }, + { + {193, 189, 192, 188}, + {187, 191, 186, 190}, + {191, 187, 192, 188}, + {185, 189, 186, 190}, + }, + { + {194, 190, 193, 189}, + {188, 192, 187, 191}, + {192, 188, 193, 189}, + {186, 190, 187, 191}, + }, + { + {195, 191, 194, 190}, + {189, 193, 188, 192}, + {193, 189, 194, 190}, + {187, 191, 188, 192}, + }, + { + {196, 192, 195, 191}, + {190, 194, 189, 193}, + {194, 190, 195, 191}, + {188, 192, 189, 193}, + }, + { + {197, 193, 196, 192}, + {191, 195, 190, 194}, + {195, 191, 196, 192}, + {189, 193, 190, 194}, + }, + { + {198, 194, 197, 193}, + {192, 196, 191, 195}, + {196, 192, 197, 193}, + {190, 194, 191, 195}, + }, + { + {199, 195, 198, 194}, + {193, 197, 192, 196}, + {197, 193, 198, 194}, + {191, 195, 192, 196}, + }, + { + {200, 196, 199, 195}, + {194, 198, 193, 197}, + {198, 194, 199, 195}, + {192, 196, 193, 197}, + }, + { + {201, 197, 200, 196}, + {195, 199, 194, 198}, + {199, 195, 200, 196}, + {193, 197, 194, 198}, + }, + { + {202, 198, 201, 197}, + {196, 200, 195, 199}, + {200, 196, 201, 197}, + {194, 198, 195, 199}, + }, + { + {203, 199, 202, 198}, + {197, 201, 196, 200}, + {201, 197, 202, 198}, + {195, 199, 196, 200}, + }, + { + {204, 200, 203, 199}, + {198, 202, 197, 201}, + {202, 198, 203, 199}, + {196, 200, 197, 201}, + }, + { + {205, 201, 204, 200}, + {199, 203, 198, 202}, + {203, 199, 204, 200}, + {197, 201, 198, 202}, + }, + { + {206, 202, 205, 201}, + {200, 204, 199, 203}, + {204, 200, 205, 201}, + {198, 202, 199, 203}, + }, + { + {207, 203, 206, 202}, + {201, 205, 200, 204}, + {205, 201, 206, 202}, + {199, 203, 200, 204}, + }, + { + {208, 204, 207, 203}, + {202, 206, 201, 205}, + {206, 202, 207, 203}, + {200, 204, 201, 205}, + }, + { + {209, 205, 208, 204}, + {203, 207, 202, 206}, + {207, 203, 208, 204}, + {201, 205, 202, 206}, + }, + { + {210, 206, 209, 205}, + {204, 208, 203, 207}, + {208, 204, 209, 205}, + {202, 206, 203, 207}, + }, + { + {211, 207, 210, 206}, + {205, 209, 204, 208}, + {209, 205, 210, 206}, + {203, 207, 204, 208}, + }, + { + {212, 208, 211, 207}, + {206, 210, 205, 209}, + {210, 206, 211, 207}, + {204, 208, 205, 209}, + }, + { + {213, 209, 212, 208}, + {207, 211, 206, 210}, + {211, 207, 212, 208}, + {205, 209, 206, 210}, + }, + { + {214, 210, 213, 209}, + {208, 212, 207, 211}, + {212, 208, 213, 209}, + {206, 210, 207, 211}, + }, + { + {215, 211, 214, 210}, + {209, 213, 208, 212}, + {213, 209, 214, 210}, + {207, 211, 208, 212}, + }, + { + {216, 212, 215, 211}, + {210, 214, 209, 213}, + {214, 210, 215, 211}, + {208, 212, 209, 213}, + }, + { + {217, 213, 216, 212}, + {211, 215, 210, 214}, + {215, 211, 216, 212}, + {209, 213, 210, 214}, + }, + { + {218, 214, 217, 213}, + {212, 216, 211, 215}, + {216, 212, 217, 213}, + {210, 214, 211, 215}, + }, + { + {219, 215, 218, 214}, + {213, 217, 212, 216}, + {217, 213, 218, 214}, + {211, 215, 212, 216}, + }, + { + {220, 216, 219, 215}, + {214, 218, 213, 217}, + {218, 214, 219, 215}, + {212, 216, 213, 217}, + }, + { + {221, 217, 220, 216}, + {215, 219, 214, 218}, + {219, 215, 220, 216}, + {213, 217, 214, 218}, + }, + { + {222, 218, 221, 217}, + {216, 220, 215, 219}, + {220, 216, 221, 217}, + {214, 218, 215, 219}, + }, + { + {223, 219, 222, 218}, + {217, 221, 216, 220}, + {221, 217, 222, 218}, + {215, 219, 216, 220}, + }, + { + {224, 220, 223, 219}, + {218, 222, 217, 221}, + {222, 218, 223, 219}, + {216, 220, 217, 221}, + }, + { + {225, 221, 224, 220}, + {219, 223, 218, 222}, + {223, 219, 224, 220}, + {217, 221, 218, 222}, + }, + { + {226, 222, 225, 221}, + {220, 224, 219, 223}, + {224, 220, 225, 221}, + {218, 222, 219, 223}, + }, + { + {227, 223, 226, 222}, + {221, 225, 220, 224}, + {225, 221, 226, 222}, + {219, 223, 220, 224}, + }, + { + {228, 224, 227, 223}, + {222, 226, 221, 225}, + {226, 222, 227, 223}, + {220, 224, 221, 225}, + }, + { + {229, 225, 228, 224}, + {223, 227, 222, 226}, + {227, 223, 228, 224}, + {221, 225, 222, 226}, + }, + { + {230, 226, 229, 225}, + {224, 228, 223, 227}, + {228, 224, 229, 225}, + {222, 226, 223, 227}, + }, + { + {231, 227, 230, 226}, + {225, 229, 224, 228}, + {229, 225, 230, 226}, + {223, 227, 224, 228}, + }, + { + {232, 228, 231, 227}, + {226, 230, 225, 229}, + {230, 226, 231, 227}, + {224, 228, 225, 229}, + }, + { + {233, 229, 232, 228}, + {227, 231, 226, 230}, + {231, 227, 232, 228}, + {225, 229, 226, 230}, + }, + { + {234, 230, 233, 229}, + {228, 232, 227, 231}, + {232, 228, 233, 229}, + {226, 230, 227, 231}, + }, + { + {235, 231, 234, 230}, + {229, 233, 228, 232}, + {233, 229, 234, 230}, + {227, 231, 228, 232}, + }, + { + {236, 232, 235, 231}, + {230, 234, 229, 233}, + {234, 230, 235, 231}, + {228, 232, 229, 233}, + }, + { + {237, 233, 236, 232}, + {231, 235, 230, 234}, + {235, 231, 236, 232}, + {229, 233, 230, 234}, + }, + { + {238, 234, 237, 233}, + {232, 236, 231, 235}, + {236, 232, 237, 233}, + {230, 234, 231, 235}, + }, + { + {239, 235, 238, 234}, + {233, 237, 232, 236}, + {237, 233, 238, 234}, + {231, 235, 232, 236}, + }, + { + {240, 236, 239, 235}, + {234, 238, 233, 237}, + {238, 234, 239, 235}, + {232, 236, 233, 237}, + }, + { + {241, 237, 240, 236}, + {235, 239, 234, 238}, + {239, 235, 240, 236}, + {233, 237, 234, 238}, + }, + { + {242, 238, 241, 237}, + {236, 240, 235, 239}, + {240, 236, 241, 237}, + {234, 238, 235, 239}, + }, + { + {243, 239, 242, 238}, + {237, 241, 236, 240}, + {241, 237, 242, 238}, + {235, 239, 236, 240}, + }, + { + {244, 240, 243, 239}, + {238, 242, 237, 241}, + {242, 238, 243, 239}, + {236, 240, 237, 241}, + }, + { + {245, 241, 244, 240}, + {239, 243, 238, 242}, + {243, 239, 244, 240}, + {237, 241, 238, 242}, + }, + { + {246, 242, 245, 241}, + {240, 244, 239, 243}, + {244, 240, 245, 241}, + {238, 242, 239, 243}, + }, + { + {247, 243, 246, 242}, + {241, 245, 240, 244}, + {245, 241, 246, 242}, + {239, 243, 240, 244}, + }, + { + {248, 244, 247, 243}, + {242, 246, 241, 245}, + {246, 242, 247, 243}, + {240, 244, 241, 245}, + }, + { + {249, 245, 248, 244}, + {243, 247, 242, 246}, + {247, 243, 248, 244}, + {241, 245, 242, 246}, + }, + { + {250, 246, 249, 245}, + {244, 248, 243, 247}, + {248, 244, 249, 245}, + {242, 246, 243, 247}, + }, + { + {251, 247, 250, 246}, + {245, 249, 244, 248}, + {249, 245, 250, 246}, + {243, 247, 244, 248}, + }, + { + {252, 248, 251, 247}, + {246, 250, 245, 249}, + {250, 246, 251, 247}, + {244, 248, 245, 249}, + }, + { + {253, 249, 252, 248}, + {247, 251, 246, 250}, + {251, 247, 252, 248}, + {245, 249, 246, 250}, + }, + { + {254, 250, 253, 249}, + {248, 252, 247, 251}, + {252, 248, 253, 249}, + {246, 250, 247, 251}, + }, + { + {255, 251, 254, 250}, + {249, 253, 248, 252}, + {253, 249, 254, 250}, + {247, 251, 248, 252}, + }, + { + {255, 252, 255, 251}, + {250, 254, 249, 253}, + {254, 250, 255, 251}, + {248, 252, 249, 253}, + }, + { + {255, 253, 255, 252}, + {251, 255, 250, 254}, + {255, 251, 255, 252}, + {249, 253, 250, 254}, + }, + { + {255, 254, 255, 253}, + {252, 255, 251, 255}, + {255, 252, 255, 253}, + {250, 254, 251, 255}, + }, + { + {255, 255, 255, 254}, + {253, 255, 252, 255}, + {255, 253, 255, 254}, + {251, 255, 252, 255}, + }, + { + {255, 255, 255, 255}, + {254, 255, 253, 255}, + {255, 254, 255, 255}, + {252, 255, 253, 255}, + }, +}; + +static const uint8_t dithersub_g[256][4][4] = +{ + { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + }, + { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + }, + { + {5, 3, 4, 2}, + {2, 4, 1, 3}, + {4, 2, 4, 2}, + {1, 3, 1, 3}, + }, + { + {6, 4, 5, 3}, + {3, 5, 2, 4}, + {5, 3, 5, 3}, + {2, 4, 2, 4}, + }, + { + {7, 5, 6, 4}, + {4, 6, 3, 5}, + {6, 4, 6, 4}, + {3, 5, 3, 5}, + }, + { + {8, 6, 7, 5}, + {5, 7, 4, 6}, + {7, 5, 7, 5}, + {4, 6, 4, 6}, + }, + { + {9, 7, 8, 6}, + {6, 8, 5, 7}, + {8, 6, 8, 6}, + {5, 7, 5, 7}, + }, + { + {10, 8, 9, 7}, + {7, 9, 6, 8}, + {9, 7, 9, 7}, + {6, 8, 6, 8}, + }, + { + {11, 9, 10, 8}, + {8, 10, 7, 9}, + {10, 8, 10, 8}, + {7, 9, 7, 9}, + }, + { + {12, 10, 11, 9}, + {9, 11, 8, 10}, + {11, 9, 11, 9}, + {8, 10, 8, 10}, + }, + { + {13, 11, 12, 10}, + {10, 12, 9, 11}, + {12, 10, 12, 10}, + {9, 11, 9, 11}, + }, + { + {14, 12, 13, 11}, + {11, 13, 10, 12}, + {13, 11, 13, 11}, + {10, 12, 10, 12}, + }, + { + {15, 13, 14, 12}, + {12, 14, 11, 13}, + {14, 12, 14, 12}, + {11, 13, 11, 13}, + }, + { + {16, 14, 15, 13}, + {13, 15, 12, 14}, + {15, 13, 15, 13}, + {12, 14, 12, 14}, + }, + { + {17, 15, 16, 14}, + {14, 16, 13, 15}, + {16, 14, 16, 14}, + {13, 15, 13, 15}, + }, + { + {18, 16, 17, 15}, + {15, 17, 14, 16}, + {17, 15, 17, 15}, + {14, 16, 14, 16}, + }, + { + {19, 17, 18, 16}, + {16, 18, 15, 17}, + {18, 16, 18, 16}, + {15, 17, 15, 17}, + }, + { + {20, 18, 19, 17}, + {17, 19, 16, 18}, + {19, 17, 19, 17}, + {16, 18, 16, 18}, + }, + { + {21, 19, 20, 18}, + {18, 20, 17, 19}, + {20, 18, 20, 18}, + {17, 19, 17, 19}, + }, + { + {22, 20, 21, 19}, + {19, 21, 18, 20}, + {21, 19, 21, 19}, + {18, 20, 18, 20}, + }, + { + {23, 21, 22, 20}, + {20, 22, 19, 21}, + {22, 20, 22, 20}, + {19, 21, 19, 21}, + }, + { + {24, 22, 23, 21}, + {21, 23, 20, 22}, + {23, 21, 23, 21}, + {20, 22, 20, 22}, + }, + { + {25, 23, 24, 22}, + {22, 24, 21, 23}, + {24, 22, 24, 22}, + {21, 23, 21, 23}, + }, + { + {26, 24, 25, 23}, + {23, 25, 22, 24}, + {25, 23, 25, 23}, + {22, 24, 22, 24}, + }, + { + {27, 25, 26, 24}, + {24, 26, 23, 25}, + {26, 24, 26, 24}, + {23, 25, 23, 25}, + }, + { + {28, 26, 27, 25}, + {25, 27, 24, 26}, + {27, 25, 27, 25}, + {24, 26, 24, 26}, + }, + { + {29, 27, 28, 26}, + {26, 28, 25, 27}, + {28, 26, 28, 26}, + {25, 27, 25, 27}, + }, + { + {30, 28, 29, 27}, + {27, 29, 26, 28}, + {29, 27, 29, 27}, + {26, 28, 26, 28}, + }, + { + {31, 29, 30, 28}, + {28, 30, 27, 29}, + {30, 28, 30, 28}, + {27, 29, 27, 29}, + }, + { + {32, 30, 31, 29}, + {29, 31, 28, 30}, + {31, 29, 31, 29}, + {28, 30, 28, 30}, + }, + { + {33, 31, 32, 30}, + {30, 32, 29, 31}, + {32, 30, 32, 30}, + {29, 31, 29, 31}, + }, + { + {34, 32, 33, 31}, + {31, 33, 30, 32}, + {33, 31, 33, 31}, + {30, 32, 30, 32}, + }, + { + {35, 33, 34, 32}, + {32, 34, 31, 33}, + {34, 32, 34, 32}, + {31, 33, 31, 33}, + }, + { + {36, 34, 35, 33}, + {33, 35, 32, 34}, + {35, 33, 35, 33}, + {32, 34, 32, 34}, + }, + { + {37, 35, 36, 34}, + {34, 36, 33, 35}, + {36, 34, 36, 34}, + {33, 35, 33, 35}, + }, + { + {38, 36, 37, 35}, + {35, 37, 34, 36}, + {37, 35, 37, 35}, + {34, 36, 34, 36}, + }, + { + {39, 37, 38, 36}, + {36, 38, 35, 37}, + {38, 36, 38, 36}, + {35, 37, 35, 37}, + }, + { + {40, 38, 39, 37}, + {37, 39, 36, 38}, + {39, 37, 39, 37}, + {36, 38, 36, 38}, + }, + { + {41, 39, 40, 38}, + {38, 40, 37, 39}, + {40, 38, 40, 38}, + {37, 39, 37, 39}, + }, + { + {42, 40, 41, 39}, + {39, 41, 38, 40}, + {41, 39, 41, 39}, + {38, 40, 38, 40}, + }, + { + {43, 41, 42, 40}, + {40, 42, 39, 41}, + {42, 40, 42, 40}, + {39, 41, 39, 41}, + }, + { + {44, 42, 43, 41}, + {41, 43, 40, 42}, + {43, 41, 43, 41}, + {40, 42, 40, 42}, + }, + { + {45, 43, 44, 42}, + {42, 44, 41, 43}, + {44, 42, 44, 42}, + {41, 43, 41, 43}, + }, + { + {46, 44, 45, 43}, + {43, 45, 42, 44}, + {45, 43, 45, 43}, + {42, 44, 42, 44}, + }, + { + {47, 45, 46, 44}, + {44, 46, 43, 45}, + {46, 44, 46, 44}, + {43, 45, 43, 45}, + }, + { + {48, 46, 47, 45}, + {45, 47, 44, 46}, + {47, 45, 47, 45}, + {44, 46, 44, 46}, + }, + { + {49, 47, 48, 46}, + {46, 48, 45, 47}, + {48, 46, 48, 46}, + {45, 47, 45, 47}, + }, + { + {50, 48, 49, 47}, + {47, 49, 46, 48}, + {49, 47, 49, 47}, + {46, 48, 46, 48}, + }, + { + {51, 49, 50, 48}, + {48, 50, 47, 49}, + {50, 48, 50, 48}, + {47, 49, 47, 49}, + }, + { + {52, 50, 51, 49}, + {49, 51, 48, 50}, + {51, 49, 51, 49}, + {48, 50, 48, 50}, + }, + { + {53, 51, 52, 50}, + {50, 52, 49, 51}, + {52, 50, 52, 50}, + {49, 51, 49, 51}, + }, + { + {54, 52, 53, 51}, + {51, 53, 50, 52}, + {53, 51, 53, 51}, + {50, 52, 50, 52}, + }, + { + {55, 53, 54, 52}, + {52, 54, 51, 53}, + {54, 52, 54, 52}, + {51, 53, 51, 53}, + }, + { + {56, 54, 55, 53}, + {53, 55, 52, 54}, + {55, 53, 55, 53}, + {52, 54, 52, 54}, + }, + { + {57, 55, 56, 54}, + {54, 56, 53, 55}, + {56, 54, 56, 54}, + {53, 55, 53, 55}, + }, + { + {58, 56, 57, 55}, + {55, 57, 54, 56}, + {57, 55, 57, 55}, + {54, 56, 54, 56}, + }, + { + {59, 57, 58, 56}, + {56, 58, 55, 57}, + {58, 56, 58, 56}, + {55, 57, 55, 57}, + }, + { + {60, 58, 59, 57}, + {57, 59, 56, 58}, + {59, 57, 59, 57}, + {56, 58, 56, 58}, + }, + { + {61, 59, 60, 58}, + {58, 60, 57, 59}, + {60, 58, 60, 58}, + {57, 59, 57, 59}, + }, + { + {62, 60, 61, 59}, + {59, 61, 58, 60}, + {61, 59, 61, 59}, + {58, 60, 58, 60}, + }, + { + {63, 61, 62, 60}, + {60, 62, 59, 61}, + {62, 60, 62, 60}, + {59, 61, 59, 61}, + }, + { + {64, 62, 63, 61}, + {61, 63, 60, 62}, + {63, 61, 63, 61}, + {60, 62, 60, 62}, + }, + { + {65, 63, 64, 62}, + {62, 64, 61, 63}, + {64, 62, 64, 62}, + {61, 63, 61, 63}, + }, + { + {66, 64, 65, 63}, + {63, 65, 62, 64}, + {65, 63, 65, 63}, + {62, 64, 62, 64}, + }, + { + {67, 65, 66, 64}, + {64, 66, 63, 65}, + {66, 64, 66, 64}, + {63, 65, 63, 65}, + }, + { + {68, 66, 67, 65}, + {65, 67, 64, 66}, + {67, 65, 67, 65}, + {64, 66, 64, 66}, + }, + { + {69, 67, 68, 66}, + {66, 68, 65, 67}, + {68, 66, 68, 66}, + {65, 67, 65, 67}, + }, + { + {70, 68, 69, 67}, + {67, 69, 66, 68}, + {69, 67, 69, 67}, + {66, 68, 66, 68}, + }, + { + {71, 69, 70, 68}, + {68, 70, 67, 69}, + {70, 68, 70, 68}, + {67, 69, 67, 69}, + }, + { + {72, 70, 71, 69}, + {69, 71, 68, 70}, + {71, 69, 71, 69}, + {68, 70, 68, 70}, + }, + { + {73, 71, 72, 70}, + {70, 72, 69, 71}, + {72, 70, 72, 70}, + {69, 71, 69, 71}, + }, + { + {74, 72, 73, 71}, + {71, 73, 70, 72}, + {73, 71, 73, 71}, + {70, 72, 70, 72}, + }, + { + {75, 73, 74, 72}, + {72, 74, 71, 73}, + {74, 72, 74, 72}, + {71, 73, 71, 73}, + }, + { + {76, 74, 75, 73}, + {73, 75, 72, 74}, + {75, 73, 75, 73}, + {72, 74, 72, 74}, + }, + { + {77, 75, 76, 74}, + {74, 76, 73, 75}, + {76, 74, 76, 74}, + {73, 75, 73, 75}, + }, + { + {78, 76, 77, 75}, + {75, 77, 74, 76}, + {77, 75, 77, 75}, + {74, 76, 74, 76}, + }, + { + {79, 77, 78, 76}, + {76, 78, 75, 77}, + {78, 76, 78, 76}, + {75, 77, 75, 77}, + }, + { + {80, 78, 79, 77}, + {77, 79, 76, 78}, + {79, 77, 79, 77}, + {76, 78, 76, 78}, + }, + { + {81, 79, 80, 78}, + {78, 80, 77, 79}, + {80, 78, 80, 78}, + {77, 79, 77, 79}, + }, + { + {82, 80, 81, 79}, + {79, 81, 78, 80}, + {81, 79, 81, 79}, + {78, 80, 78, 80}, + }, + { + {83, 81, 82, 80}, + {80, 82, 79, 81}, + {82, 80, 82, 80}, + {79, 81, 79, 81}, + }, + { + {84, 82, 83, 81}, + {81, 83, 80, 82}, + {83, 81, 83, 81}, + {80, 82, 80, 82}, + }, + { + {85, 83, 84, 82}, + {82, 84, 81, 83}, + {84, 82, 84, 82}, + {81, 83, 81, 83}, + }, + { + {86, 84, 85, 83}, + {83, 85, 82, 84}, + {85, 83, 85, 83}, + {82, 84, 82, 84}, + }, + { + {87, 85, 86, 84}, + {84, 86, 83, 85}, + {86, 84, 86, 84}, + {83, 85, 83, 85}, + }, + { + {88, 86, 87, 85}, + {85, 87, 84, 86}, + {87, 85, 87, 85}, + {84, 86, 84, 86}, + }, + { + {89, 87, 88, 86}, + {86, 88, 85, 87}, + {88, 86, 88, 86}, + {85, 87, 85, 87}, + }, + { + {90, 88, 89, 87}, + {87, 89, 86, 88}, + {89, 87, 89, 87}, + {86, 88, 86, 88}, + }, + { + {91, 89, 90, 88}, + {88, 90, 87, 89}, + {90, 88, 90, 88}, + {87, 89, 87, 89}, + }, + { + {92, 90, 91, 89}, + {89, 91, 88, 90}, + {91, 89, 91, 89}, + {88, 90, 88, 90}, + }, + { + {93, 91, 92, 90}, + {90, 92, 89, 91}, + {92, 90, 92, 90}, + {89, 91, 89, 91}, + }, + { + {94, 92, 93, 91}, + {91, 93, 90, 92}, + {93, 91, 93, 91}, + {90, 92, 90, 92}, + }, + { + {95, 93, 94, 92}, + {92, 94, 91, 93}, + {94, 92, 94, 92}, + {91, 93, 91, 93}, + }, + { + {96, 94, 95, 93}, + {93, 95, 92, 94}, + {95, 93, 95, 93}, + {92, 94, 92, 94}, + }, + { + {97, 95, 96, 94}, + {94, 96, 93, 95}, + {96, 94, 96, 94}, + {93, 95, 93, 95}, + }, + { + {98, 96, 97, 95}, + {95, 97, 94, 96}, + {97, 95, 97, 95}, + {94, 96, 94, 96}, + }, + { + {99, 97, 98, 96}, + {96, 98, 95, 97}, + {98, 96, 98, 96}, + {95, 97, 95, 97}, + }, + { + {100, 98, 99, 97}, + {97, 99, 96, 98}, + {99, 97, 99, 97}, + {96, 98, 96, 98}, + }, + { + {101, 99, 100, 98}, + {98, 100, 97, 99}, + {100, 98, 100, 98}, + {97, 99, 97, 99}, + }, + { + {102, 100, 101, 99}, + {99, 101, 98, 100}, + {101, 99, 101, 99}, + {98, 100, 98, 100}, + }, + { + {103, 101, 102, 100}, + {100, 102, 99, 101}, + {102, 100, 102, 100}, + {99, 101, 99, 101}, + }, + { + {104, 102, 103, 101}, + {101, 103, 100, 102}, + {103, 101, 103, 101}, + {100, 102, 100, 102}, + }, + { + {105, 103, 104, 102}, + {102, 104, 101, 103}, + {104, 102, 104, 102}, + {101, 103, 101, 103}, + }, + { + {106, 104, 105, 103}, + {103, 105, 102, 104}, + {105, 103, 105, 103}, + {102, 104, 102, 104}, + }, + { + {107, 105, 106, 104}, + {104, 106, 103, 105}, + {106, 104, 106, 104}, + {103, 105, 103, 105}, + }, + { + {108, 106, 107, 105}, + {105, 107, 104, 106}, + {107, 105, 107, 105}, + {104, 106, 104, 106}, + }, + { + {109, 107, 108, 106}, + {106, 108, 105, 107}, + {108, 106, 108, 106}, + {105, 107, 105, 107}, + }, + { + {110, 108, 109, 107}, + {107, 109, 106, 108}, + {109, 107, 109, 107}, + {106, 108, 106, 108}, + }, + { + {111, 109, 110, 108}, + {108, 110, 107, 109}, + {110, 108, 110, 108}, + {107, 109, 107, 109}, + }, + { + {112, 110, 111, 109}, + {109, 111, 108, 110}, + {111, 109, 111, 109}, + {108, 110, 108, 110}, + }, + { + {113, 111, 112, 110}, + {110, 112, 109, 111}, + {112, 110, 112, 110}, + {109, 111, 109, 111}, + }, + { + {114, 112, 113, 111}, + {111, 113, 110, 112}, + {113, 111, 113, 111}, + {110, 112, 110, 112}, + }, + { + {115, 113, 114, 112}, + {112, 114, 111, 113}, + {114, 112, 114, 112}, + {111, 113, 111, 113}, + }, + { + {116, 114, 115, 113}, + {113, 115, 112, 114}, + {115, 113, 115, 113}, + {112, 114, 112, 114}, + }, + { + {117, 115, 116, 114}, + {114, 116, 113, 115}, + {116, 114, 116, 114}, + {113, 115, 113, 115}, + }, + { + {118, 116, 117, 115}, + {115, 117, 114, 116}, + {117, 115, 117, 115}, + {114, 116, 114, 116}, + }, + { + {119, 117, 118, 116}, + {116, 118, 115, 117}, + {118, 116, 118, 116}, + {115, 117, 115, 117}, + }, + { + {120, 118, 119, 117}, + {117, 119, 116, 118}, + {119, 117, 119, 117}, + {116, 118, 116, 118}, + }, + { + {121, 119, 120, 118}, + {118, 120, 117, 119}, + {120, 118, 120, 118}, + {117, 119, 117, 119}, + }, + { + {122, 120, 121, 119}, + {119, 121, 118, 120}, + {121, 119, 121, 119}, + {118, 120, 118, 120}, + }, + { + {123, 121, 122, 120}, + {120, 122, 119, 121}, + {122, 120, 122, 120}, + {119, 121, 119, 121}, + }, + { + {124, 122, 123, 121}, + {121, 123, 120, 122}, + {123, 121, 123, 121}, + {120, 122, 120, 122}, + }, + { + {125, 123, 124, 122}, + {122, 124, 121, 123}, + {124, 122, 124, 122}, + {121, 123, 121, 123}, + }, + { + {126, 124, 125, 123}, + {123, 125, 122, 124}, + {125, 123, 125, 123}, + {122, 124, 122, 124}, + }, + { + {127, 125, 126, 124}, + {124, 126, 123, 125}, + {126, 124, 126, 124}, + {123, 125, 123, 125}, + }, + { + {128, 126, 127, 125}, + {125, 127, 124, 126}, + {127, 125, 127, 125}, + {124, 126, 124, 126}, + }, + { + {129, 127, 128, 126}, + {126, 128, 125, 127}, + {128, 126, 128, 126}, + {125, 127, 125, 127}, + }, + { + {130, 128, 129, 127}, + {127, 129, 126, 128}, + {129, 127, 129, 127}, + {126, 128, 126, 128}, + }, + { + {131, 129, 130, 128}, + {128, 130, 127, 129}, + {130, 128, 130, 128}, + {127, 129, 127, 129}, + }, + { + {132, 130, 131, 129}, + {129, 131, 128, 130}, + {131, 129, 131, 129}, + {128, 130, 128, 130}, + }, + { + {133, 131, 132, 130}, + {130, 132, 129, 131}, + {132, 130, 132, 130}, + {129, 131, 129, 131}, + }, + { + {134, 132, 133, 131}, + {131, 133, 130, 132}, + {133, 131, 133, 131}, + {130, 132, 130, 132}, + }, + { + {135, 133, 134, 132}, + {132, 134, 131, 133}, + {134, 132, 134, 132}, + {131, 133, 131, 133}, + }, + { + {136, 134, 135, 133}, + {133, 135, 132, 134}, + {135, 133, 135, 133}, + {132, 134, 132, 134}, + }, + { + {137, 135, 136, 134}, + {134, 136, 133, 135}, + {136, 134, 136, 134}, + {133, 135, 133, 135}, + }, + { + {138, 136, 137, 135}, + {135, 137, 134, 136}, + {137, 135, 137, 135}, + {134, 136, 134, 136}, + }, + { + {139, 137, 138, 136}, + {136, 138, 135, 137}, + {138, 136, 138, 136}, + {135, 137, 135, 137}, + }, + { + {140, 138, 139, 137}, + {137, 139, 136, 138}, + {139, 137, 139, 137}, + {136, 138, 136, 138}, + }, + { + {141, 139, 140, 138}, + {138, 140, 137, 139}, + {140, 138, 140, 138}, + {137, 139, 137, 139}, + }, + { + {142, 140, 141, 139}, + {139, 141, 138, 140}, + {141, 139, 141, 139}, + {138, 140, 138, 140}, + }, + { + {143, 141, 142, 140}, + {140, 142, 139, 141}, + {142, 140, 142, 140}, + {139, 141, 139, 141}, + }, + { + {144, 142, 143, 141}, + {141, 143, 140, 142}, + {143, 141, 143, 141}, + {140, 142, 140, 142}, + }, + { + {145, 143, 144, 142}, + {142, 144, 141, 143}, + {144, 142, 144, 142}, + {141, 143, 141, 143}, + }, + { + {146, 144, 145, 143}, + {143, 145, 142, 144}, + {145, 143, 145, 143}, + {142, 144, 142, 144}, + }, + { + {147, 145, 146, 144}, + {144, 146, 143, 145}, + {146, 144, 146, 144}, + {143, 145, 143, 145}, + }, + { + {148, 146, 147, 145}, + {145, 147, 144, 146}, + {147, 145, 147, 145}, + {144, 146, 144, 146}, + }, + { + {149, 147, 148, 146}, + {146, 148, 145, 147}, + {148, 146, 148, 146}, + {145, 147, 145, 147}, + }, + { + {150, 148, 149, 147}, + {147, 149, 146, 148}, + {149, 147, 149, 147}, + {146, 148, 146, 148}, + }, + { + {151, 149, 150, 148}, + {148, 150, 147, 149}, + {150, 148, 150, 148}, + {147, 149, 147, 149}, + }, + { + {152, 150, 151, 149}, + {149, 151, 148, 150}, + {151, 149, 151, 149}, + {148, 150, 148, 150}, + }, + { + {153, 151, 152, 150}, + {150, 152, 149, 151}, + {152, 150, 152, 150}, + {149, 151, 149, 151}, + }, + { + {154, 152, 153, 151}, + {151, 153, 150, 152}, + {153, 151, 153, 151}, + {150, 152, 150, 152}, + }, + { + {155, 153, 154, 152}, + {152, 154, 151, 153}, + {154, 152, 154, 152}, + {151, 153, 151, 153}, + }, + { + {156, 154, 155, 153}, + {153, 155, 152, 154}, + {155, 153, 155, 153}, + {152, 154, 152, 154}, + }, + { + {157, 155, 156, 154}, + {154, 156, 153, 155}, + {156, 154, 156, 154}, + {153, 155, 153, 155}, + }, + { + {158, 156, 157, 155}, + {155, 157, 154, 156}, + {157, 155, 157, 155}, + {154, 156, 154, 156}, + }, + { + {159, 157, 158, 156}, + {156, 158, 155, 157}, + {158, 156, 158, 156}, + {155, 157, 155, 157}, + }, + { + {160, 158, 159, 157}, + {157, 159, 156, 158}, + {159, 157, 159, 157}, + {156, 158, 156, 158}, + }, + { + {161, 159, 160, 158}, + {158, 160, 157, 159}, + {160, 158, 160, 158}, + {157, 159, 157, 159}, + }, + { + {162, 160, 161, 159}, + {159, 161, 158, 160}, + {161, 159, 161, 159}, + {158, 160, 158, 160}, + }, + { + {163, 161, 162, 160}, + {160, 162, 159, 161}, + {162, 160, 162, 160}, + {159, 161, 159, 161}, + }, + { + {164, 162, 163, 161}, + {161, 163, 160, 162}, + {163, 161, 163, 161}, + {160, 162, 160, 162}, + }, + { + {165, 163, 164, 162}, + {162, 164, 161, 163}, + {164, 162, 164, 162}, + {161, 163, 161, 163}, + }, + { + {166, 164, 165, 163}, + {163, 165, 162, 164}, + {165, 163, 165, 163}, + {162, 164, 162, 164}, + }, + { + {167, 165, 166, 164}, + {164, 166, 163, 165}, + {166, 164, 166, 164}, + {163, 165, 163, 165}, + }, + { + {168, 166, 167, 165}, + {165, 167, 164, 166}, + {167, 165, 167, 165}, + {164, 166, 164, 166}, + }, + { + {169, 167, 168, 166}, + {166, 168, 165, 167}, + {168, 166, 168, 166}, + {165, 167, 165, 167}, + }, + { + {170, 168, 169, 167}, + {167, 169, 166, 168}, + {169, 167, 169, 167}, + {166, 168, 166, 168}, + }, + { + {171, 169, 170, 168}, + {168, 170, 167, 169}, + {170, 168, 170, 168}, + {167, 169, 167, 169}, + }, + { + {172, 170, 171, 169}, + {169, 171, 168, 170}, + {171, 169, 171, 169}, + {168, 170, 168, 170}, + }, + { + {173, 171, 172, 170}, + {170, 172, 169, 171}, + {172, 170, 172, 170}, + {169, 171, 169, 171}, + }, + { + {174, 172, 173, 171}, + {171, 173, 170, 172}, + {173, 171, 173, 171}, + {170, 172, 170, 172}, + }, + { + {175, 173, 174, 172}, + {172, 174, 171, 173}, + {174, 172, 174, 172}, + {171, 173, 171, 173}, + }, + { + {176, 174, 175, 173}, + {173, 175, 172, 174}, + {175, 173, 175, 173}, + {172, 174, 172, 174}, + }, + { + {177, 175, 176, 174}, + {174, 176, 173, 175}, + {176, 174, 176, 174}, + {173, 175, 173, 175}, + }, + { + {178, 176, 177, 175}, + {175, 177, 174, 176}, + {177, 175, 177, 175}, + {174, 176, 174, 176}, + }, + { + {179, 177, 178, 176}, + {176, 178, 175, 177}, + {178, 176, 178, 176}, + {175, 177, 175, 177}, + }, + { + {180, 178, 179, 177}, + {177, 179, 176, 178}, + {179, 177, 179, 177}, + {176, 178, 176, 178}, + }, + { + {181, 179, 180, 178}, + {178, 180, 177, 179}, + {180, 178, 180, 178}, + {177, 179, 177, 179}, + }, + { + {182, 180, 181, 179}, + {179, 181, 178, 180}, + {181, 179, 181, 179}, + {178, 180, 178, 180}, + }, + { + {183, 181, 182, 180}, + {180, 182, 179, 181}, + {182, 180, 182, 180}, + {179, 181, 179, 181}, + }, + { + {184, 182, 183, 181}, + {181, 183, 180, 182}, + {183, 181, 183, 181}, + {180, 182, 180, 182}, + }, + { + {185, 183, 184, 182}, + {182, 184, 181, 183}, + {184, 182, 184, 182}, + {181, 183, 181, 183}, + }, + { + {186, 184, 185, 183}, + {183, 185, 182, 184}, + {185, 183, 185, 183}, + {182, 184, 182, 184}, + }, + { + {187, 185, 186, 184}, + {184, 186, 183, 185}, + {186, 184, 186, 184}, + {183, 185, 183, 185}, + }, + { + {188, 186, 187, 185}, + {185, 187, 184, 186}, + {187, 185, 187, 185}, + {184, 186, 184, 186}, + }, + { + {189, 187, 188, 186}, + {186, 188, 185, 187}, + {188, 186, 188, 186}, + {185, 187, 185, 187}, + }, + { + {190, 188, 189, 187}, + {187, 189, 186, 188}, + {189, 187, 189, 187}, + {186, 188, 186, 188}, + }, + { + {191, 189, 190, 188}, + {188, 190, 187, 189}, + {190, 188, 190, 188}, + {187, 189, 187, 189}, + }, + { + {192, 190, 191, 189}, + {189, 191, 188, 190}, + {191, 189, 191, 189}, + {188, 190, 188, 190}, + }, + { + {193, 191, 192, 190}, + {190, 192, 189, 191}, + {192, 190, 192, 190}, + {189, 191, 189, 191}, + }, + { + {194, 192, 193, 191}, + {191, 193, 190, 192}, + {193, 191, 193, 191}, + {190, 192, 190, 192}, + }, + { + {195, 193, 194, 192}, + {192, 194, 191, 193}, + {194, 192, 194, 192}, + {191, 193, 191, 193}, + }, + { + {196, 194, 195, 193}, + {193, 195, 192, 194}, + {195, 193, 195, 193}, + {192, 194, 192, 194}, + }, + { + {197, 195, 196, 194}, + {194, 196, 193, 195}, + {196, 194, 196, 194}, + {193, 195, 193, 195}, + }, + { + {198, 196, 197, 195}, + {195, 197, 194, 196}, + {197, 195, 197, 195}, + {194, 196, 194, 196}, + }, + { + {199, 197, 198, 196}, + {196, 198, 195, 197}, + {198, 196, 198, 196}, + {195, 197, 195, 197}, + }, + { + {200, 198, 199, 197}, + {197, 199, 196, 198}, + {199, 197, 199, 197}, + {196, 198, 196, 198}, + }, + { + {201, 199, 200, 198}, + {198, 200, 197, 199}, + {200, 198, 200, 198}, + {197, 199, 197, 199}, + }, + { + {202, 200, 201, 199}, + {199, 201, 198, 200}, + {201, 199, 201, 199}, + {198, 200, 198, 200}, + }, + { + {203, 201, 202, 200}, + {200, 202, 199, 201}, + {202, 200, 202, 200}, + {199, 201, 199, 201}, + }, + { + {204, 202, 203, 201}, + {201, 203, 200, 202}, + {203, 201, 203, 201}, + {200, 202, 200, 202}, + }, + { + {205, 203, 204, 202}, + {202, 204, 201, 203}, + {204, 202, 204, 202}, + {201, 203, 201, 203}, + }, + { + {206, 204, 205, 203}, + {203, 205, 202, 204}, + {205, 203, 205, 203}, + {202, 204, 202, 204}, + }, + { + {207, 205, 206, 204}, + {204, 206, 203, 205}, + {206, 204, 206, 204}, + {203, 205, 203, 205}, + }, + { + {208, 206, 207, 205}, + {205, 207, 204, 206}, + {207, 205, 207, 205}, + {204, 206, 204, 206}, + }, + { + {209, 207, 208, 206}, + {206, 208, 205, 207}, + {208, 206, 208, 206}, + {205, 207, 205, 207}, + }, + { + {210, 208, 209, 207}, + {207, 209, 206, 208}, + {209, 207, 209, 207}, + {206, 208, 206, 208}, + }, + { + {211, 209, 210, 208}, + {208, 210, 207, 209}, + {210, 208, 210, 208}, + {207, 209, 207, 209}, + }, + { + {212, 210, 211, 209}, + {209, 211, 208, 210}, + {211, 209, 211, 209}, + {208, 210, 208, 210}, + }, + { + {213, 211, 212, 210}, + {210, 212, 209, 211}, + {212, 210, 212, 210}, + {209, 211, 209, 211}, + }, + { + {214, 212, 213, 211}, + {211, 213, 210, 212}, + {213, 211, 213, 211}, + {210, 212, 210, 212}, + }, + { + {215, 213, 214, 212}, + {212, 214, 211, 213}, + {214, 212, 214, 212}, + {211, 213, 211, 213}, + }, + { + {216, 214, 215, 213}, + {213, 215, 212, 214}, + {215, 213, 215, 213}, + {212, 214, 212, 214}, + }, + { + {217, 215, 216, 214}, + {214, 216, 213, 215}, + {216, 214, 216, 214}, + {213, 215, 213, 215}, + }, + { + {218, 216, 217, 215}, + {215, 217, 214, 216}, + {217, 215, 217, 215}, + {214, 216, 214, 216}, + }, + { + {219, 217, 218, 216}, + {216, 218, 215, 217}, + {218, 216, 218, 216}, + {215, 217, 215, 217}, + }, + { + {220, 218, 219, 217}, + {217, 219, 216, 218}, + {219, 217, 219, 217}, + {216, 218, 216, 218}, + }, + { + {221, 219, 220, 218}, + {218, 220, 217, 219}, + {220, 218, 220, 218}, + {217, 219, 217, 219}, + }, + { + {222, 220, 221, 219}, + {219, 221, 218, 220}, + {221, 219, 221, 219}, + {218, 220, 218, 220}, + }, + { + {223, 221, 222, 220}, + {220, 222, 219, 221}, + {222, 220, 222, 220}, + {219, 221, 219, 221}, + }, + { + {224, 222, 223, 221}, + {221, 223, 220, 222}, + {223, 221, 223, 221}, + {220, 222, 220, 222}, + }, + { + {225, 223, 224, 222}, + {222, 224, 221, 223}, + {224, 222, 224, 222}, + {221, 223, 221, 223}, + }, + { + {226, 224, 225, 223}, + {223, 225, 222, 224}, + {225, 223, 225, 223}, + {222, 224, 222, 224}, + }, + { + {227, 225, 226, 224}, + {224, 226, 223, 225}, + {226, 224, 226, 224}, + {223, 225, 223, 225}, + }, + { + {228, 226, 227, 225}, + {225, 227, 224, 226}, + {227, 225, 227, 225}, + {224, 226, 224, 226}, + }, + { + {229, 227, 228, 226}, + {226, 228, 225, 227}, + {228, 226, 228, 226}, + {225, 227, 225, 227}, + }, + { + {230, 228, 229, 227}, + {227, 229, 226, 228}, + {229, 227, 229, 227}, + {226, 228, 226, 228}, + }, + { + {231, 229, 230, 228}, + {228, 230, 227, 229}, + {230, 228, 230, 228}, + {227, 229, 227, 229}, + }, + { + {232, 230, 231, 229}, + {229, 231, 228, 230}, + {231, 229, 231, 229}, + {228, 230, 228, 230}, + }, + { + {233, 231, 232, 230}, + {230, 232, 229, 231}, + {232, 230, 232, 230}, + {229, 231, 229, 231}, + }, + { + {234, 232, 233, 231}, + {231, 233, 230, 232}, + {233, 231, 233, 231}, + {230, 232, 230, 232}, + }, + { + {235, 233, 234, 232}, + {232, 234, 231, 233}, + {234, 232, 234, 232}, + {231, 233, 231, 233}, + }, + { + {236, 234, 235, 233}, + {233, 235, 232, 234}, + {235, 233, 235, 233}, + {232, 234, 232, 234}, + }, + { + {237, 235, 236, 234}, + {234, 236, 233, 235}, + {236, 234, 236, 234}, + {233, 235, 233, 235}, + }, + { + {238, 236, 237, 235}, + {235, 237, 234, 236}, + {237, 235, 237, 235}, + {234, 236, 234, 236}, + }, + { + {239, 237, 238, 236}, + {236, 238, 235, 237}, + {238, 236, 238, 236}, + {235, 237, 235, 237}, + }, + { + {240, 238, 239, 237}, + {237, 239, 236, 238}, + {239, 237, 239, 237}, + {236, 238, 236, 238}, + }, + { + {241, 239, 240, 238}, + {238, 240, 237, 239}, + {240, 238, 240, 238}, + {237, 239, 237, 239}, + }, + { + {242, 240, 241, 239}, + {239, 241, 238, 240}, + {241, 239, 241, 239}, + {238, 240, 238, 240}, + }, + { + {243, 241, 242, 240}, + {240, 242, 239, 241}, + {242, 240, 242, 240}, + {239, 241, 239, 241}, + }, + { + {244, 242, 243, 241}, + {241, 243, 240, 242}, + {243, 241, 243, 241}, + {240, 242, 240, 242}, + }, + { + {245, 243, 244, 242}, + {242, 244, 241, 243}, + {244, 242, 244, 242}, + {241, 243, 241, 243}, + }, + { + {246, 244, 245, 243}, + {243, 245, 242, 244}, + {245, 243, 245, 243}, + {242, 244, 242, 244}, + }, + { + {247, 245, 246, 244}, + {244, 246, 243, 245}, + {246, 244, 246, 244}, + {243, 245, 243, 245}, + }, + { + {248, 246, 247, 245}, + {245, 247, 244, 246}, + {247, 245, 247, 245}, + {244, 246, 244, 246}, + }, + { + {249, 247, 248, 246}, + {246, 248, 245, 247}, + {248, 246, 248, 246}, + {245, 247, 245, 247}, + }, + { + {250, 248, 249, 247}, + {247, 249, 246, 248}, + {249, 247, 249, 247}, + {246, 248, 246, 248}, + }, + { + {251, 249, 250, 248}, + {248, 250, 247, 249}, + {250, 248, 250, 248}, + {247, 249, 247, 249}, + }, + { + {252, 250, 251, 249}, + {249, 251, 248, 250}, + {251, 249, 251, 249}, + {248, 250, 248, 250}, + }, + { + {253, 251, 252, 250}, + {250, 252, 249, 251}, + {252, 250, 252, 250}, + {249, 251, 249, 251}, + }, + { + {254, 252, 253, 251}, + {251, 253, 250, 252}, + {253, 251, 253, 251}, + {250, 252, 250, 252}, + }, + { + {255, 253, 254, 252}, + {252, 254, 251, 253}, + {254, 252, 254, 252}, + {251, 253, 251, 253}, + }, + { + {255, 254, 255, 253}, + {253, 255, 252, 254}, + {255, 253, 255, 253}, + {252, 254, 252, 254}, + }, + { + {255, 255, 255, 254}, + {254, 255, 253, 255}, + {255, 254, 255, 254}, + {253, 255, 253, 255}, + }, + { + {255, 255, 255, 255}, + {255, 255, 254, 255}, + {255, 255, 255, 255}, + {254, 255, 254, 255}, + }, +}; + + + + +static const uint8_t dithersub_g2x2[256][2][2] = +{ + { + {0, 0}, + {0, 0}, + }, + { + {0, 0}, + {0, 0}, + }, + { + {4, 2}, + {1, 3}, + }, + { + {5, 3}, + {2, 4}, + }, + { + {6, 4}, + {3, 5}, + }, + { + {7, 5}, + {4, 6}, + }, + { + {8, 6}, + {5, 7}, + }, + { + {9, 7}, + {6, 8}, + }, + { + {10, 8}, + {7, 9}, + }, + { + {11, 9}, + {8, 10}, + }, + { + {12, 10}, + {9, 11}, + }, + { + {13, 11}, + {10, 12}, + }, + { + {14, 12}, + {11, 13}, + }, + { + {15, 13}, + {12, 14}, + }, + { + {16, 14}, + {13, 15}, + }, + { + {17, 15}, + {14, 16}, + }, + { + {18, 16}, + {15, 17}, + }, + { + {19, 17}, + {16, 18}, + }, + { + {20, 18}, + {17, 19}, + }, + { + {21, 19}, + {18, 20}, + }, + { + {22, 20}, + {19, 21}, + }, + { + {23, 21}, + {20, 22}, + }, + { + {24, 22}, + {21, 23}, + }, + { + {25, 23}, + {22, 24}, + }, + { + {26, 24}, + {23, 25}, + }, + { + {27, 25}, + {24, 26}, + }, + { + {28, 26}, + {25, 27}, + }, + { + {29, 27}, + {26, 28}, + }, + { + {30, 28}, + {27, 29}, + }, + { + {31, 29}, + {28, 30}, + }, + { + {32, 30}, + {29, 31}, + }, + { + {33, 31}, + {30, 32}, + }, + { + {34, 32}, + {31, 33}, + }, + { + {35, 33}, + {32, 34}, + }, + { + {36, 34}, + {33, 35}, + }, + { + {37, 35}, + {34, 36}, + }, + { + {38, 36}, + {35, 37}, + }, + { + {39, 37}, + {36, 38}, + }, + { + {40, 38}, + {37, 39}, + }, + { + {41, 39}, + {38, 40}, + }, + { + {42, 40}, + {39, 41}, + }, + { + {43, 41}, + {40, 42}, + }, + { + {44, 42}, + {41, 43}, + }, + { + {45, 43}, + {42, 44}, + }, + { + {46, 44}, + {43, 45}, + }, + { + {47, 45}, + {44, 46}, + }, + { + {48, 46}, + {45, 47}, + }, + { + {49, 47}, + {46, 48}, + }, + { + {50, 48}, + {47, 49}, + }, + { + {51, 49}, + {48, 50}, + }, + { + {52, 50}, + {49, 51}, + }, + { + {53, 51}, + {50, 52}, + }, + { + {54, 52}, + {51, 53}, + }, + { + {55, 53}, + {52, 54}, + }, + { + {56, 54}, + {53, 55}, + }, + { + {57, 55}, + {54, 56}, + }, + { + {58, 56}, + {55, 57}, + }, + { + {59, 57}, + {56, 58}, + }, + { + {60, 58}, + {57, 59}, + }, + { + {61, 59}, + {58, 60}, + }, + { + {62, 60}, + {59, 61}, + }, + { + {63, 61}, + {60, 62}, + }, + { + {64, 62}, + {61, 63}, + }, + { + {65, 63}, + {62, 64}, + }, + { + {66, 64}, + {63, 65}, + }, + { + {67, 65}, + {64, 66}, + }, + { + {68, 66}, + {65, 67}, + }, + { + {69, 67}, + {66, 68}, + }, + { + {70, 68}, + {67, 69}, + }, + { + {71, 69}, + {68, 70}, + }, + { + {72, 70}, + {69, 71}, + }, + { + {73, 71}, + {70, 72}, + }, + { + {74, 72}, + {71, 73}, + }, + { + {75, 73}, + {72, 74}, + }, + { + {76, 74}, + {73, 75}, + }, + { + {77, 75}, + {74, 76}, + }, + { + {78, 76}, + {75, 77}, + }, + { + {79, 77}, + {76, 78}, + }, + { + {80, 78}, + {77, 79}, + }, + { + {81, 79}, + {78, 80}, + }, + { + {82, 80}, + {79, 81}, + }, + { + {83, 81}, + {80, 82}, + }, + { + {84, 82}, + {81, 83}, + }, + { + {85, 83}, + {82, 84}, + }, + { + {86, 84}, + {83, 85}, + }, + { + {87, 85}, + {84, 86}, + }, + { + {88, 86}, + {85, 87}, + }, + { + {89, 87}, + {86, 88}, + }, + { + {90, 88}, + {87, 89}, + }, + { + {91, 89}, + {88, 90}, + }, + { + {92, 90}, + {89, 91}, + }, + { + {93, 91}, + {90, 92}, + }, + { + {94, 92}, + {91, 93}, + }, + { + {95, 93}, + {92, 94}, + }, + { + {96, 94}, + {93, 95}, + }, + { + {97, 95}, + {94, 96}, + }, + { + {98, 96}, + {95, 97}, + }, + { + {99, 97}, + {96, 98}, + }, + { + {100, 98}, + {97, 99}, + }, + { + {101, 99}, + {98, 100}, + }, + { + {102, 100}, + {99, 101}, + }, + { + {103, 101}, + {100, 102}, + }, + { + {104, 102}, + {101, 103}, + }, + { + {105, 103}, + {102, 104}, + }, + { + {106, 104}, + {103, 105}, + }, + { + {107, 105}, + {104, 106}, + }, + { + {108, 106}, + {105, 107}, + }, + { + {109, 107}, + {106, 108}, + }, + { + {110, 108}, + {107, 109}, + }, + { + {111, 109}, + {108, 110}, + }, + { + {112, 110}, + {109, 111}, + }, + { + {113, 111}, + {110, 112}, + }, + { + {114, 112}, + {111, 113}, + }, + { + {115, 113}, + {112, 114}, + }, + { + {116, 114}, + {113, 115}, + }, + { + {117, 115}, + {114, 116}, + }, + { + {118, 116}, + {115, 117}, + }, + { + {119, 117}, + {116, 118}, + }, + { + {120, 118}, + {117, 119}, + }, + { + {121, 119}, + {118, 120}, + }, + { + {122, 120}, + {119, 121}, + }, + { + {123, 121}, + {120, 122}, + }, + { + {124, 122}, + {121, 123}, + }, + { + {125, 123}, + {122, 124}, + }, + { + {126, 124}, + {123, 125}, + }, + { + {127, 125}, + {124, 126}, + }, + { + {128, 126}, + {125, 127}, + }, + { + {129, 127}, + {126, 128}, + }, + { + {130, 128}, + {127, 129}, + }, + { + {131, 129}, + {128, 130}, + }, + { + {132, 130}, + {129, 131}, + }, + { + {133, 131}, + {130, 132}, + }, + { + {134, 132}, + {131, 133}, + }, + { + {135, 133}, + {132, 134}, + }, + { + {136, 134}, + {133, 135}, + }, + { + {137, 135}, + {134, 136}, + }, + { + {138, 136}, + {135, 137}, + }, + { + {139, 137}, + {136, 138}, + }, + { + {140, 138}, + {137, 139}, + }, + { + {141, 139}, + {138, 140}, + }, + { + {142, 140}, + {139, 141}, + }, + { + {143, 141}, + {140, 142}, + }, + { + {144, 142}, + {141, 143}, + }, + { + {145, 143}, + {142, 144}, + }, + { + {146, 144}, + {143, 145}, + }, + { + {147, 145}, + {144, 146}, + }, + { + {148, 146}, + {145, 147}, + }, + { + {149, 147}, + {146, 148}, + }, + { + {150, 148}, + {147, 149}, + }, + { + {151, 149}, + {148, 150}, + }, + { + {152, 150}, + {149, 151}, + }, + { + {153, 151}, + {150, 152}, + }, + { + {154, 152}, + {151, 153}, + }, + { + {155, 153}, + {152, 154}, + }, + { + {156, 154}, + {153, 155}, + }, + { + {157, 155}, + {154, 156}, + }, + { + {158, 156}, + {155, 157}, + }, + { + {159, 157}, + {156, 158}, + }, + { + {160, 158}, + {157, 159}, + }, + { + {161, 159}, + {158, 160}, + }, + { + {162, 160}, + {159, 161}, + }, + { + {163, 161}, + {160, 162}, + }, + { + {164, 162}, + {161, 163}, + }, + { + {165, 163}, + {162, 164}, + }, + { + {166, 164}, + {163, 165}, + }, + { + {167, 165}, + {164, 166}, + }, + { + {168, 166}, + {165, 167}, + }, + { + {169, 167}, + {166, 168}, + }, + { + {170, 168}, + {167, 169}, + }, + { + {171, 169}, + {168, 170}, + }, + { + {172, 170}, + {169, 171}, + }, + { + {173, 171}, + {170, 172}, + }, + { + {174, 172}, + {171, 173}, + }, + { + {175, 173}, + {172, 174}, + }, + { + {176, 174}, + {173, 175}, + }, + { + {177, 175}, + {174, 176}, + }, + { + {178, 176}, + {175, 177}, + }, + { + {179, 177}, + {176, 178}, + }, + { + {180, 178}, + {177, 179}, + }, + { + {181, 179}, + {178, 180}, + }, + { + {182, 180}, + {179, 181}, + }, + { + {183, 181}, + {180, 182}, + }, + { + {184, 182}, + {181, 183}, + }, + { + {185, 183}, + {182, 184}, + }, + { + {186, 184}, + {183, 185}, + }, + { + {187, 185}, + {184, 186}, + }, + { + {188, 186}, + {185, 187}, + }, + { + {189, 187}, + {186, 188}, + }, + { + {190, 188}, + {187, 189}, + }, + { + {191, 189}, + {188, 190}, + }, + { + {192, 190}, + {189, 191}, + }, + { + {193, 191}, + {190, 192}, + }, + { + {194, 192}, + {191, 193}, + }, + { + {195, 193}, + {192, 194}, + }, + { + {196, 194}, + {193, 195}, + }, + { + {197, 195}, + {194, 196}, + }, + { + {198, 196}, + {195, 197}, + }, + { + {199, 197}, + {196, 198}, + }, + { + {200, 198}, + {197, 199}, + }, + { + {201, 199}, + {198, 200}, + }, + { + {202, 200}, + {199, 201}, + }, + { + {203, 201}, + {200, 202}, + }, + { + {204, 202}, + {201, 203}, + }, + { + {205, 203}, + {202, 204}, + }, + { + {206, 204}, + {203, 205}, + }, + { + {207, 205}, + {204, 206}, + }, + { + {208, 206}, + {205, 207}, + }, + { + {209, 207}, + {206, 208}, + }, + { + {210, 208}, + {207, 209}, + }, + { + {211, 209}, + {208, 210}, + }, + { + {212, 210}, + {209, 211}, + }, + { + {213, 211}, + {210, 212}, + }, + { + {214, 212}, + {211, 213}, + }, + { + {215, 213}, + {212, 214}, + }, + { + {216, 214}, + {213, 215}, + }, + { + {217, 215}, + {214, 216}, + }, + { + {218, 216}, + {215, 217}, + }, + { + {219, 217}, + {216, 218}, + }, + { + {220, 218}, + {217, 219}, + }, + { + {221, 219}, + {218, 220}, + }, + { + {222, 220}, + {219, 221}, + }, + { + {223, 221}, + {220, 222}, + }, + { + {224, 222}, + {221, 223}, + }, + { + {225, 223}, + {222, 224}, + }, + { + {226, 224}, + {223, 225}, + }, + { + {227, 225}, + {224, 226}, + }, + { + {228, 226}, + {225, 227}, + }, + { + {229, 227}, + {226, 228}, + }, + { + {230, 228}, + {227, 229}, + }, + { + {231, 229}, + {228, 230}, + }, + { + {232, 230}, + {229, 231}, + }, + { + {233, 231}, + {230, 232}, + }, + { + {234, 232}, + {231, 233}, + }, + { + {235, 233}, + {232, 234}, + }, + { + {236, 234}, + {233, 235}, + }, + { + {237, 235}, + {234, 236}, + }, + { + {238, 236}, + {235, 237}, + }, + { + {239, 237}, + {236, 238}, + }, + { + {240, 238}, + {237, 239}, + }, + { + {241, 239}, + {238, 240}, + }, + { + {242, 240}, + {239, 241}, + }, + { + {243, 241}, + {240, 242}, + }, + { + {244, 242}, + {241, 243}, + }, + { + {245, 243}, + {242, 244}, + }, + { + {246, 244}, + {243, 245}, + }, + { + {247, 245}, + {244, 246}, + }, + { + {248, 246}, + {245, 247}, + }, + { + {249, 247}, + {246, 248}, + }, + { + {250, 248}, + {247, 249}, + }, + { + {251, 249}, + {248, 250}, + }, + { + {252, 250}, + {249, 251}, + }, + { + {253, 251}, + {250, 252}, + }, + { + {254, 252}, + {251, 253}, + }, + { + {255, 253}, + {252, 254}, + }, + { + {255, 254}, + {253, 255}, + }, + { + {255, 255}, + {254, 255}, + }, +}; + + +static const uint8_t dithersub_rb2x2[256][2][2] = +{ + { + {0, 0}, + {0, 0}, + }, + { + {0, 0}, + {0, 0}, + }, + { + {0, 0}, + {0, 0}, + }, + { + {0, 0}, + {0, 0}, + }, + { + {8, 4}, + {2, 6}, + }, + { + {9, 5}, + {3, 7}, + }, + { + {10, 6}, + {4, 8}, + }, + { + {11, 7}, + {5, 9}, + }, + { + {12, 8}, + {6, 10}, + }, + { + {13, 9}, + {7, 11}, + }, + { + {14, 10}, + {8, 12}, + }, + { + {15, 11}, + {9, 13}, + }, + { + {16, 12}, + {10, 14}, + }, + { + {17, 13}, + {11, 15}, + }, + { + {18, 14}, + {12, 16}, + }, + { + {19, 15}, + {13, 17}, + }, + { + {20, 16}, + {14, 18}, + }, + { + {21, 17}, + {15, 19}, + }, + { + {22, 18}, + {16, 20}, + }, + { + {23, 19}, + {17, 21}, + }, + { + {24, 20}, + {18, 22}, + }, + { + {25, 21}, + {19, 23}, + }, + { + {26, 22}, + {20, 24}, + }, + { + {27, 23}, + {21, 25}, + }, + { + {28, 24}, + {22, 26}, + }, + { + {29, 25}, + {23, 27}, + }, + { + {30, 26}, + {24, 28}, + }, + { + {31, 27}, + {25, 29}, + }, + { + {32, 28}, + {26, 30}, + }, + { + {33, 29}, + {27, 31}, + }, + { + {34, 30}, + {28, 32}, + }, + { + {35, 31}, + {29, 33}, + }, + { + {36, 32}, + {30, 34}, + }, + { + {37, 33}, + {31, 35}, + }, + { + {38, 34}, + {32, 36}, + }, + { + {39, 35}, + {33, 37}, + }, + { + {40, 36}, + {34, 38}, + }, + { + {41, 37}, + {35, 39}, + }, + { + {42, 38}, + {36, 40}, + }, + { + {43, 39}, + {37, 41}, + }, + { + {44, 40}, + {38, 42}, + }, + { + {45, 41}, + {39, 43}, + }, + { + {46, 42}, + {40, 44}, + }, + { + {47, 43}, + {41, 45}, + }, + { + {48, 44}, + {42, 46}, + }, + { + {49, 45}, + {43, 47}, + }, + { + {50, 46}, + {44, 48}, + }, + { + {51, 47}, + {45, 49}, + }, + { + {52, 48}, + {46, 50}, + }, + { + {53, 49}, + {47, 51}, + }, + { + {54, 50}, + {48, 52}, + }, + { + {55, 51}, + {49, 53}, + }, + { + {56, 52}, + {50, 54}, + }, + { + {57, 53}, + {51, 55}, + }, + { + {58, 54}, + {52, 56}, + }, + { + {59, 55}, + {53, 57}, + }, + { + {60, 56}, + {54, 58}, + }, + { + {61, 57}, + {55, 59}, + }, + { + {62, 58}, + {56, 60}, + }, + { + {63, 59}, + {57, 61}, + }, + { + {64, 60}, + {58, 62}, + }, + { + {65, 61}, + {59, 63}, + }, + { + {66, 62}, + {60, 64}, + }, + { + {67, 63}, + {61, 65}, + }, + { + {68, 64}, + {62, 66}, + }, + { + {69, 65}, + {63, 67}, + }, + { + {70, 66}, + {64, 68}, + }, + { + {71, 67}, + {65, 69}, + }, + { + {72, 68}, + {66, 70}, + }, + { + {73, 69}, + {67, 71}, + }, + { + {74, 70}, + {68, 72}, + }, + { + {75, 71}, + {69, 73}, + }, + { + {76, 72}, + {70, 74}, + }, + { + {77, 73}, + {71, 75}, + }, + { + {78, 74}, + {72, 76}, + }, + { + {79, 75}, + {73, 77}, + }, + { + {80, 76}, + {74, 78}, + }, + { + {81, 77}, + {75, 79}, + }, + { + {82, 78}, + {76, 80}, + }, + { + {83, 79}, + {77, 81}, + }, + { + {84, 80}, + {78, 82}, + }, + { + {85, 81}, + {79, 83}, + }, + { + {86, 82}, + {80, 84}, + }, + { + {87, 83}, + {81, 85}, + }, + { + {88, 84}, + {82, 86}, + }, + { + {89, 85}, + {83, 87}, + }, + { + {90, 86}, + {84, 88}, + }, + { + {91, 87}, + {85, 89}, + }, + { + {92, 88}, + {86, 90}, + }, + { + {93, 89}, + {87, 91}, + }, + { + {94, 90}, + {88, 92}, + }, + { + {95, 91}, + {89, 93}, + }, + { + {96, 92}, + {90, 94}, + }, + { + {97, 93}, + {91, 95}, + }, + { + {98, 94}, + {92, 96}, + }, + { + {99, 95}, + {93, 97}, + }, + { + {100, 96}, + {94, 98}, + }, + { + {101, 97}, + {95, 99}, + }, + { + {102, 98}, + {96, 100}, + }, + { + {103, 99}, + {97, 101}, + }, + { + {104, 100}, + {98, 102}, + }, + { + {105, 101}, + {99, 103}, + }, + { + {106, 102}, + {100, 104}, + }, + { + {107, 103}, + {101, 105}, + }, + { + {108, 104}, + {102, 106}, + }, + { + {109, 105}, + {103, 107}, + }, + { + {110, 106}, + {104, 108}, + }, + { + {111, 107}, + {105, 109}, + }, + { + {112, 108}, + {106, 110}, + }, + { + {113, 109}, + {107, 111}, + }, + { + {114, 110}, + {108, 112}, + }, + { + {115, 111}, + {109, 113}, + }, + { + {116, 112}, + {110, 114}, + }, + { + {117, 113}, + {111, 115}, + }, + { + {118, 114}, + {112, 116}, + }, + { + {119, 115}, + {113, 117}, + }, + { + {120, 116}, + {114, 118}, + }, + { + {121, 117}, + {115, 119}, + }, + { + {122, 118}, + {116, 120}, + }, + { + {123, 119}, + {117, 121}, + }, + { + {124, 120}, + {118, 122}, + }, + { + {125, 121}, + {119, 123}, + }, + { + {126, 122}, + {120, 124}, + }, + { + {127, 123}, + {121, 125}, + }, + { + {128, 124}, + {122, 126}, + }, + { + {129, 125}, + {123, 127}, + }, + { + {130, 126}, + {124, 128}, + }, + { + {131, 127}, + {125, 129}, + }, + { + {132, 128}, + {126, 130}, + }, + { + {133, 129}, + {127, 131}, + }, + { + {134, 130}, + {128, 132}, + }, + { + {135, 131}, + {129, 133}, + }, + { + {136, 132}, + {130, 134}, + }, + { + {137, 133}, + {131, 135}, + }, + { + {138, 134}, + {132, 136}, + }, + { + {139, 135}, + {133, 137}, + }, + { + {140, 136}, + {134, 138}, + }, + { + {141, 137}, + {135, 139}, + }, + { + {142, 138}, + {136, 140}, + }, + { + {143, 139}, + {137, 141}, + }, + { + {144, 140}, + {138, 142}, + }, + { + {145, 141}, + {139, 143}, + }, + { + {146, 142}, + {140, 144}, + }, + { + {147, 143}, + {141, 145}, + }, + { + {148, 144}, + {142, 146}, + }, + { + {149, 145}, + {143, 147}, + }, + { + {150, 146}, + {144, 148}, + }, + { + {151, 147}, + {145, 149}, + }, + { + {152, 148}, + {146, 150}, + }, + { + {153, 149}, + {147, 151}, + }, + { + {154, 150}, + {148, 152}, + }, + { + {155, 151}, + {149, 153}, + }, + { + {156, 152}, + {150, 154}, + }, + { + {157, 153}, + {151, 155}, + }, + { + {158, 154}, + {152, 156}, + }, + { + {159, 155}, + {153, 157}, + }, + { + {160, 156}, + {154, 158}, + }, + { + {161, 157}, + {155, 159}, + }, + { + {162, 158}, + {156, 160}, + }, + { + {163, 159}, + {157, 161}, + }, + { + {164, 160}, + {158, 162}, + }, + { + {165, 161}, + {159, 163}, + }, + { + {166, 162}, + {160, 164}, + }, + { + {167, 163}, + {161, 165}, + }, + { + {168, 164}, + {162, 166}, + }, + { + {169, 165}, + {163, 167}, + }, + { + {170, 166}, + {164, 168}, + }, + { + {171, 167}, + {165, 169}, + }, + { + {172, 168}, + {166, 170}, + }, + { + {173, 169}, + {167, 171}, + }, + { + {174, 170}, + {168, 172}, + }, + { + {175, 171}, + {169, 173}, + }, + { + {176, 172}, + {170, 174}, + }, + { + {177, 173}, + {171, 175}, + }, + { + {178, 174}, + {172, 176}, + }, + { + {179, 175}, + {173, 177}, + }, + { + {180, 176}, + {174, 178}, + }, + { + {181, 177}, + {175, 179}, + }, + { + {182, 178}, + {176, 180}, + }, + { + {183, 179}, + {177, 181}, + }, + { + {184, 180}, + {178, 182}, + }, + { + {185, 181}, + {179, 183}, + }, + { + {186, 182}, + {180, 184}, + }, + { + {187, 183}, + {181, 185}, + }, + { + {188, 184}, + {182, 186}, + }, + { + {189, 185}, + {183, 187}, + }, + { + {190, 186}, + {184, 188}, + }, + { + {191, 187}, + {185, 189}, + }, + { + {192, 188}, + {186, 190}, + }, + { + {193, 189}, + {187, 191}, + }, + { + {194, 190}, + {188, 192}, + }, + { + {195, 191}, + {189, 193}, + }, + { + {196, 192}, + {190, 194}, + }, + { + {197, 193}, + {191, 195}, + }, + { + {198, 194}, + {192, 196}, + }, + { + {199, 195}, + {193, 197}, + }, + { + {200, 196}, + {194, 198}, + }, + { + {201, 197}, + {195, 199}, + }, + { + {202, 198}, + {196, 200}, + }, + { + {203, 199}, + {197, 201}, + }, + { + {204, 200}, + {198, 202}, + }, + { + {205, 201}, + {199, 203}, + }, + { + {206, 202}, + {200, 204}, + }, + { + {207, 203}, + {201, 205}, + }, + { + {208, 204}, + {202, 206}, + }, + { + {209, 205}, + {203, 207}, + }, + { + {210, 206}, + {204, 208}, + }, + { + {211, 207}, + {205, 209}, + }, + { + {212, 208}, + {206, 210}, + }, + { + {213, 209}, + {207, 211}, + }, + { + {214, 210}, + {208, 212}, + }, + { + {215, 211}, + {209, 213}, + }, + { + {216, 212}, + {210, 214}, + }, + { + {217, 213}, + {211, 215}, + }, + { + {218, 214}, + {212, 216}, + }, + { + {219, 215}, + {213, 217}, + }, + { + {220, 216}, + {214, 218}, + }, + { + {221, 217}, + {215, 219}, + }, + { + {222, 218}, + {216, 220}, + }, + { + {223, 219}, + {217, 221}, + }, + { + {224, 220}, + {218, 222}, + }, + { + {225, 221}, + {219, 223}, + }, + { + {226, 222}, + {220, 224}, + }, + { + {227, 223}, + {221, 225}, + }, + { + {228, 224}, + {222, 226}, + }, + { + {229, 225}, + {223, 227}, + }, + { + {230, 226}, + {224, 228}, + }, + { + {231, 227}, + {225, 229}, + }, + { + {232, 228}, + {226, 230}, + }, + { + {233, 229}, + {227, 231}, + }, + { + {234, 230}, + {228, 232}, + }, + { + {235, 231}, + {229, 233}, + }, + { + {236, 232}, + {230, 234}, + }, + { + {237, 233}, + {231, 235}, + }, + { + {238, 234}, + {232, 236}, + }, + { + {239, 235}, + {233, 237}, + }, + { + {240, 236}, + {234, 238}, + }, + { + {241, 237}, + {235, 239}, + }, + { + {242, 238}, + {236, 240}, + }, + { + {243, 239}, + {237, 241}, + }, + { + {244, 240}, + {238, 242}, + }, + { + {245, 241}, + {239, 243}, + }, + { + {246, 242}, + {240, 244}, + }, + { + {247, 243}, + {241, 245}, + }, + { + {248, 244}, + {242, 246}, + }, + { + {249, 245}, + {243, 247}, + }, + { + {250, 246}, + {244, 248}, + }, + { + {251, 247}, + {245, 249}, + }, + { + {252, 248}, + {246, 250}, + }, + { + {253, 249}, + {247, 251}, + }, + { + {254, 250}, + {248, 252}, + }, + { + {255, 251}, + {249, 253}, + }, + { + {255, 252}, + {250, 254}, + }, + { + {255, 253}, + {251, 255}, + }, + { + {255, 254}, + {252, 255}, + }, + { + {255, 255}, + {253, 255}, + }, +}; + diff --git a/pcem/vid_voodoo_regs.h b/pcem/vid_voodoo_regs.h index f7ab2089..e99241f6 100644 --- a/pcem/vid_voodoo_regs.h +++ b/pcem/vid_voodoo_regs.h @@ -370,6 +370,7 @@ enum FBZ_DEPTH_BIAS = (1 << 16), + FBZ_DITHER_SUB = (1 << 19), FBZ_DEPTH_SOURCE = (1 << 20), FBZ_PARAM_ADJUST = (1 << 26) @@ -689,3 +690,5 @@ enum #define depth_op ( (params->fbzMode >> 5) & 7) #define dither ( params->fbzMode & FBZ_DITHER) #define dither2x2 (params->fbzMode & FBZ_DITHER_2x2) +#define dithersub (params->fbzMode & FBZ_DITHER_SUB) + diff --git a/pcem/vid_voodoo_render.cpp b/pcem/vid_voodoo_render.cpp index 777d9cc3..f8ad7a4f 100644 --- a/pcem/vid_voodoo_render.cpp +++ b/pcem/vid_voodoo_render.cpp @@ -685,6 +685,7 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood uint8_t (__cdecl *voodoo_draw)(voodoo_state_t *state, voodoo_params_t *params, int x, int real_y); #endif int y_diff = SLI_ENABLED ? 2 : 1; + int y_origin = (voodoo->type >= VOODOO_BANSHEE) ? voodoo->y_origin_swap : (voodoo->v_disp-1); if ((params->textureMode[0] & TEXTUREMODE_MASK) == TEXTUREMODE_PASSTHROUGH || (params->textureMode[0] & TEXTUREMODE_LOCAL_MASK) == TEXTUREMODE_LOCAL) @@ -749,7 +750,7 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood int test_y; if (params->fbzMode & (1 << 17)) - test_y = (voodoo->v_disp-1) - state->y; + test_y = y_origin - state->y; else test_y = state->y; @@ -815,7 +816,7 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood x2 = (state->vertexBx << 12) + ((state->dxBC * (real_y - state->vertexBy)) >> 4); if (params->fbzMode & (1 << 17)) - real_y = (voodoo->v_disp-1) - (real_y >> 4); + real_y = y_origin - (real_y >> 4); else real_y >>= 4; @@ -1284,7 +1285,21 @@ static void voodoo_half_triangle(voodoo_t *voodoo, voodoo_params_t *params, vood ALPHA_TEST(src_a); if (params->alphaMode & (1 << 4)) + { + if (dithersub && !dither2x2 && voodoo->dithersub_enabled) + { + dest_r = dithersub_rb[dest_r][real_y & 3][x & 3]; + dest_g = dithersub_g [dest_g][real_y & 3][x & 3]; + dest_b = dithersub_rb[dest_b][real_y & 3][x & 3]; + } + if (dithersub && dither2x2 && voodoo->dithersub_enabled) + { + dest_r = dithersub_rb2x2[dest_r][real_y & 1][x & 1]; + dest_g = dithersub_g2x2 [dest_g][real_y & 1][x & 1]; + dest_b = dithersub_rb2x2[dest_b][real_y & 1][x & 1]; + } ALPHA_BLEND(src_r, src_g, src_b, src_a); + } if (update) { diff --git a/pcem/vid_voodoo_render.h b/pcem/vid_voodoo_render.h index 54a9be42..9ba73dc6 100644 --- a/pcem/vid_voodoo_render.h +++ b/pcem/vid_voodoo_render.h @@ -1,4 +1,3 @@ - #if !(defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32) && !(defined __amd64__) #define NO_CODEGEN #endif diff --git a/pcem/x86.h b/pcem/x86.h index d761d69a..822d0796 100644 --- a/pcem/x86.h +++ b/pcem/x86.h @@ -39,8 +39,8 @@ typedef union typedef struct { uint32_t base; - uint32_t limit; - uint8_t access; + uint32_t limit, limit_raw; + uint8_t access, access2; uint16_t seg; uint32_t limit_low, limit_high; int checked; /*Non-zero if selector is known to be valid*/ @@ -90,6 +90,7 @@ typedef struct int8_t ssegs; int8_t ismmx; int8_t abrt; + int8_t smi_pending; int _cycles; int cpu_recomp_ins; @@ -118,6 +119,8 @@ typedef struct } CR0; uint16_t flags, eflags; + + uint32_t smbase; } CPU_STATE; extern CPU_STATE cpu_state; @@ -125,6 +128,7 @@ extern CPU_STATE cpu_state; #define cpu_state_offset(MEMBER) ((uintptr_t)&cpu_state.MEMBER - (uintptr_t)&cpu_state - 128) #define cycles cpu_state._cycles +extern int cycles_main; #define cr0 cpu_state.CR0.l #define msw cpu_state.CR0.w @@ -177,6 +181,9 @@ extern x86seg gdt, ldt, idt, tr; extern uint32_t cr2, cr3, cr4; extern uint32_t dr[8]; +extern uint16_t sysenter_cs; +extern uint32_t sysenter_eip, sysenter_esp; + extern uint16_t cpu_cur_status; @@ -186,6 +193,7 @@ extern uint16_t cpu_cur_status; #define CPU_STATUS_STACK32 (1 << 1) #define CPU_STATUS_PMODE (1 << 2) #define CPU_STATUS_V86 (1 << 3) +#define CPU_STATUS_SMM (1 << 4) #define CPU_STATUS_FLAGS 0xff /*If the flags below are set in cpu_cur_status, they must be set in block->status. @@ -260,6 +268,16 @@ enum ABRT_PF = 0xE }; +#define ABRT_MASK 0x7f +/*An 'expected' exception is one that would be expected to occur on every execution + of this code path; eg a GPF due to being in v86 mode. An 'unexpected' exception is + one that would be unlikely to occur on the next exception, eg a page fault may be + fixed up by the exception handler and the next execution would not hit it. + + This distinction is used by the dynarec; a block that hits an 'expected' exception + would be compiled, a block that hits an 'unexpected' exception would be rejected so + that we don't end up with an unnecessarily short block*/ +#define ABRT_EXPECTED 0x80 extern uint32_t abrt_error; void x86_doabrt(int x86_abrt); @@ -274,6 +292,7 @@ void x86illegal(); void x86seg_reset(); void x86gpf(const char *s, uint16_t error); +void x86gpf_expected(const char *s, uint16_t error); void resetx86(); void softresetx86(); @@ -296,7 +315,32 @@ void x86_int(int num); void x86_int_sw(int num); int x86_int_sw_rm(int num); +void sysenter(void); +void sysexit(void); + int divl(uint32_t val); int idivl(int32_t val); +extern int cpu_end_block_after_ins; + +void x86_smi_trigger(void); +void x86_smi_enter(void); +void x86_smi_leave(void); + +void cyrix_load_seg_descriptor(uint32_t addr, x86seg *seg); +void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg); + +#define SMHR_VALID (1 << 0) +#define SMHR_ADDR_MASK (0xfffffffc) + +struct +{ + struct + { + uint32_t base; + uint64_t size; + } arr[8]; + uint32_t smhr; +} cyrix; + #endif diff --git a/pcem/x86_ops.h b/pcem/x86_ops.h index ad4f0706..67f6fb92 100644 --- a/pcem/x86_ops.h +++ b/pcem/x86_ops.h @@ -38,6 +38,10 @@ extern OpFn dynarec_ops_winchip2_0f[1024]; extern OpFn dynarec_ops_pentium_0f[1024]; extern OpFn dynarec_ops_pentiummmx_0f[1024]; +extern OpFn dynarec_ops_pentiumpro_0f[1024]; +extern OpFn dynarec_ops_pentium2_0f[1024]; + +extern OpFn dynarec_ops_c6x86_0f[1024]; extern OpFn dynarec_ops_c6x86mx_0f[1024]; extern OpFn dynarec_ops_fpu_d8_a16[32]; @@ -104,7 +108,10 @@ extern OpFn ops_winchip2_0f[1024]; extern OpFn ops_pentium_0f[1024]; extern OpFn ops_pentiummmx_0f[1024]; +extern OpFn ops_pentiumpro_0f[1024]; +extern OpFn ops_pentium2_0f[1024]; +extern OpFn ops_c6x86_0f[1024]; extern OpFn ops_c6x86mx_0f[1024]; extern OpFn ops_fpu_d8_a16[32]; diff --git a/pcem/x86_ops_cyrix.h b/pcem/x86_ops_cyrix.h new file mode 100644 index 00000000..e6464ce8 --- /dev/null +++ b/pcem/x86_ops_cyrix.h @@ -0,0 +1,274 @@ +/*Cyrix-only instructions*/ +/*System Management Mode*/ +static void opSVDC_common(uint32_t fetchdat) +{ + switch (rmdat & 0x38) + { + case 0x00: /*ES*/ + cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_es); + writememw(0, easeg+cpu_state.eaaddr+8, ES); + break; + case 0x08: /*CS*/ + cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_cs); + writememw(0, easeg+cpu_state.eaaddr+8, CS); + break; + case 0x18: /*DS*/ + cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_ds); + writememw(0, easeg+cpu_state.eaaddr+8, DS); + break; + case 0x10: /*SS*/ + cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_ss); + writememw(0, easeg+cpu_state.eaaddr+8, SS); + break; + case 0x20: /*FS*/ + cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_fs); + writememw(0, easeg+cpu_state.eaaddr+8, FS); + break; + case 0x28: /*GS*/ + cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_gs); + writememw(0, easeg+cpu_state.eaaddr+8, GS); + break; + default: + pclog("opSVDC: unknown rmdat %02x\n", rmdat); + x86illegal(); + } +} +static int opSVDC_a16(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + { + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + opSVDC_common(fetchdat); + } + else + x86illegal(); + + return cpu_state.abrt; +} +static int opSVDC_a32(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + { + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + opSVDC_common(fetchdat); + } + else + x86illegal(); + + return cpu_state.abrt; +} + +static void opRSDC_common(uint32_t fetchdat) +{ + switch (rmdat & 0x38) + { + case 0x00: /*ES*/ + cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_es); + break; + case 0x18: /*DS*/ + cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_ds); + break; + case 0x10: /*SS*/ + cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_ss); + break; + case 0x20: /*FS*/ + cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_fs); + break; + case 0x28: /*GS*/ + cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &cpu_state.seg_gs); + break; + default: + pclog("opRSDC: unknown rmdat %02x\n", rmdat); + x86illegal(); + } +} +static int opRSDC_a16(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + { + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + opRSDC_common(fetchdat); + } + else + x86illegal(); + + return cpu_state.abrt; +} +static int opRSDC_a32(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + { + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + opRSDC_common(fetchdat); + } + else + x86illegal(); + + return cpu_state.abrt; +} + +static int opSVLDT_a16(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + { + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &ldt); + writememw(0, easeg+cpu_state.eaaddr+8, ldt.seg); + } + else + x86illegal(); + + return cpu_state.abrt; +} +static int opSVLDT_a32(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + { + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &ldt); + writememw(0, easeg+cpu_state.eaaddr+8, ldt.seg); + } + else + x86illegal(); + + return cpu_state.abrt; +} + +static int opRSLDT_a16(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + { + fetch_ea_16(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &ldt); + } + else + x86illegal(); + + return cpu_state.abrt; +} +static int opRSLDT_a32(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + { + fetch_ea_32(fetchdat); + SEG_CHECK_READ(cpu_state.ea_seg); + cyrix_load_seg_descriptor(easeg+cpu_state.eaaddr, &ldt); + } + else + x86illegal(); + + return cpu_state.abrt; +} + +static int opSVTS_a16(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + { + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &tr); + writememw(0, easeg+cpu_state.eaaddr+8, tr.seg); + } + else + x86illegal(); + + return cpu_state.abrt; +} +static int opSVTS_a32(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + { + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &tr); + writememw(0, easeg+cpu_state.eaaddr+8, tr.seg); + } + else + x86illegal(); + + return cpu_state.abrt; +} + +static int opRSTS_a16(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + { + fetch_ea_16(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &tr); + writememw(0, easeg+cpu_state.eaaddr+8, tr.seg); + } + else + x86illegal(); + + return cpu_state.abrt; +} +static int opRSTS_a32(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + { + fetch_ea_32(fetchdat); + SEG_CHECK_WRITE(cpu_state.ea_seg); + cyrix_write_seg_descriptor(easeg+cpu_state.eaaddr, &tr); + writememw(0, easeg+cpu_state.eaaddr+8, tr.seg); + } + else + x86illegal(); + + return cpu_state.abrt; +} + +static int opSMINT(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + fatal("opSMINT\n"); + else + x86illegal(); + + return 1; +} + +static int opRDSHR_a16(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + fatal("opRDSHR_a16\n"); + else + x86illegal(); + + return 1; +} +static int opRDSHR_a32(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + fatal("opRDSHR_a32\n"); + else + x86illegal(); + + return 1; +} + +static int opWRSHR_a16(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + fatal("opWRSHR_a16\n"); + else + x86illegal(); + + return 1; +} +static int opWRSHR_a32(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + fatal("opWRSHR_a32\n"); + else + x86illegal(); + + return 1; +} diff --git a/pcem/x86_ops_flag.h b/pcem/x86_ops_flag.h index d21408c8..2f420f41 100644 --- a/pcem/x86_ops_flag.h +++ b/pcem/x86_ops_flag.h @@ -85,8 +85,10 @@ static int opSTI(uint32_t fetchdat) else cpu_state.flags |= I_FLAG; - CPU_BLOCK_END(); - + /*First instruction after STI will always execute, regardless of whether + there is a pending interrupt*/ + cpu_end_block_after_ins = 2; + CLOCK_CYCLES(2); PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0); return 0; diff --git a/pcem/x86_ops_int.h b/pcem/x86_ops_int.h index 97793405..7c5ada6d 100644 --- a/pcem/x86_ops_int.h +++ b/pcem/x86_ops_int.h @@ -59,7 +59,7 @@ static int opINT(uint32_t fetchdat) } } } - x86gpf(NULL,0); + x86gpf_expected(NULL,0); return 1; } // /*if (temp == 0x10 && AH == 0xe) */pclog("INT %02X : %04X %04X %04X %04X %c %04X:%04X\n", temp, AX, BX, CX, DX, (AL < 32) ? ' ' : AL, CS, pc); diff --git a/pcem/x86_ops_io.h b/pcem/x86_ops_io.h index dd1f7da8..600090b2 100644 --- a/pcem/x86_ops_io.h +++ b/pcem/x86_ops_io.h @@ -5,6 +5,8 @@ static int opIN_AL_imm(uint32_t fetchdat) AL = inb(port); CLOCK_CYCLES(12); PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0); + if (cpu_state.smi_pending) + return 1; if (nmi && nmi_enable && nmi_mask) return 1; return 0; @@ -17,6 +19,8 @@ static int opIN_AX_imm(uint32_t fetchdat) AX = inw(port); CLOCK_CYCLES(12); PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0); + if (cpu_state.smi_pending) + return 1; if (nmi && nmi_enable && nmi_mask) return 1; return 0; @@ -43,10 +47,12 @@ static int opOUT_AL_imm(uint32_t fetchdat) outb(port, AL); CLOCK_CYCLES(10); PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0); - if (port == 0x64) - return x86_was_reset; + if (cpu_state.smi_pending) + return 1; if (nmi && nmi_enable && nmi_mask) return 1; + if (port == 0x64) + return x86_was_reset; return 0; } static int opOUT_AX_imm(uint32_t fetchdat) @@ -57,6 +63,8 @@ static int opOUT_AX_imm(uint32_t fetchdat) outw(port, AX); CLOCK_CYCLES(10); PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0); + if (cpu_state.smi_pending) + return 1; if (nmi && nmi_enable && nmi_mask) return 1; return 0; @@ -71,6 +79,8 @@ static int opOUT_EAX_imm(uint32_t fetchdat) outl(port, EAX); CLOCK_CYCLES(10); PREFETCH_RUN(10, 2, -1, 0,0,0,1, 0); + if (cpu_state.smi_pending) + return 1; if (nmi && nmi_enable && nmi_mask) return 1; return 0; @@ -82,6 +92,8 @@ static int opIN_AL_DX(uint32_t fetchdat) AL = inb(DX); CLOCK_CYCLES(12); PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0); + if (cpu_state.smi_pending) + return 1; if (nmi && nmi_enable && nmi_mask) return 1; return 0; @@ -93,6 +105,8 @@ static int opIN_AX_DX(uint32_t fetchdat) AX = inw(DX); CLOCK_CYCLES(12); PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0); + if (cpu_state.smi_pending) + return 1; if (nmi && nmi_enable && nmi_mask) return 1; return 0; @@ -106,6 +120,8 @@ static int opIN_EAX_DX(uint32_t fetchdat) EAX = inl(DX); CLOCK_CYCLES(12); PREFETCH_RUN(12, 1, -1, 0,1,0,0, 0); + if (cpu_state.smi_pending) + return 1; if (nmi && nmi_enable && nmi_mask) return 1; return 0; @@ -117,6 +133,8 @@ static int opOUT_AL_DX(uint32_t fetchdat) outb(DX, AL); CLOCK_CYCLES(11); PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0); + if (cpu_state.smi_pending) + return 1; if (nmi && nmi_enable && nmi_mask) return 1; return x86_was_reset; @@ -129,6 +147,8 @@ static int opOUT_AX_DX(uint32_t fetchdat) outw(DX, AX); CLOCK_CYCLES(11); PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0); + if (cpu_state.smi_pending) + return 1; if (nmi && nmi_enable && nmi_mask) return 1; return 0; @@ -141,6 +161,8 @@ static int opOUT_EAX_DX(uint32_t fetchdat) check_io_perm(DX + 3); outl(DX, EAX); PREFETCH_RUN(11, 1, -1, 0,0,0,1, 0); + if (cpu_state.smi_pending) + return 1; if (nmi && nmi_enable && nmi_mask) return 1; return 0; diff --git a/pcem/x86_ops_misc.h b/pcem/x86_ops_misc.h index 9e281f2e..84720120 100644 --- a/pcem/x86_ops_misc.h +++ b/pcem/x86_ops_misc.h @@ -970,3 +970,39 @@ static int opWRMSR(uint32_t fetchdat) return 1; } +static int opSYSENTER(uint32_t fetchdat) +{ + if (!(cr0 & 1) || !(sysenter_cs & 0xfffc)) + { + x86gpf(NULL,0); + return 1; + } +// pclog("opSYSENTER: CS=%04x EIP=%08x ESP=%08x %04x:%08x %i\n", sysenter_cs, sysenter_eip, sysenter_esp, CS,cpu_state.pc, times); + sysenter(); + CPU_BLOCK_END(); + return 0; +} + +static int opSYSEXIT(uint32_t fetchdat) +{ + if (!(cr0 & 1) || !(sysenter_cs & 0xfffc) || CPL) + { + x86gpf(NULL,0); + return 1; + } +// pclog("opSYSEXIT\n"); + sysexit(); + CPU_BLOCK_END(); + return 0; +} + +static int opHINTNOP_a16(uint32_t fetchdat) +{ + fetch_ea_16(fetchdat); + return 0; +} +static int opHINTNOP_a32(uint32_t fetchdat) +{ + fetch_ea_32(fetchdat); + return 0; +} diff --git a/pcem/x86_ops_mmx_mov.h b/pcem/x86_ops_mmx_mov.h index f598d5b2..f61bdfea 100644 --- a/pcem/x86_ops_mmx_mov.h +++ b/pcem/x86_ops_mmx_mov.h @@ -50,7 +50,7 @@ static int opMOVD_l_mm_a32(uint32_t fetchdat) static int opMOVD_mm_l_a16(uint32_t fetchdat) { MMX_ENTER(); - + fetch_ea_16(fetchdat); if (cpu_mod == 3) { @@ -69,6 +69,52 @@ static int opMOVD_mm_l_a16(uint32_t fetchdat) static int opMOVD_mm_l_a32(uint32_t fetchdat) { MMX_ENTER(); + + fetch_ea_32(fetchdat); + if (cpu_mod == 3) + { + cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0]; + CLOCK_CYCLES(1); + } + else + { + SEG_CHECK_WRITE(cpu_state.ea_seg); + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); + writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); if (cpu_state.abrt) return 1; + CLOCK_CYCLES(2); + } + return 0; +} + +/*Cyrix maps both MOVD and SMINT to the same opcode*/ +static int opMOVD_mm_l_a16_cx(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + return opSMINT(fetchdat); + + MMX_ENTER(); + + fetch_ea_16(fetchdat); + if (cpu_mod == 3) + { + cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0]; + CLOCK_CYCLES(1); + } + else + { + SEG_CHECK_WRITE(cpu_state.ea_seg); + CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); + writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); if (cpu_state.abrt) return 1; + CLOCK_CYCLES(2); + } + return 0; +} +static int opMOVD_mm_l_a32_cx(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + return opSMINT(fetchdat); + + MMX_ENTER(); fetch_ea_32(fetchdat); if (cpu_mod == 3) diff --git a/pcem/x86_ops_pmode.h b/pcem/x86_ops_pmode.h index 7afd6c8b..0589ba01 100644 --- a/pcem/x86_ops_pmode.h +++ b/pcem/x86_ops_pmode.h @@ -165,7 +165,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) int dpl, valid, granularity; uint32_t addr, base, limit; uint16_t desc, sel; - uint8_t access; + uint8_t access, access2; // pclog("op0F00 %02X %04X:%04X\n", rmdat & 0x38, CS, pc); switch (rmdat & 0x38) @@ -198,10 +198,13 @@ static int op0F00_common(uint32_t fetchdat, int ea32) limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16); base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24); access = readmemb(0, addr + 5); + access2 = readmemb(0, addr + 6); granularity = readmemb(0, addr + 6) & 0x80; if (cpu_state.abrt) return 1; ldt.limit = limit; + ldt.limit_raw = limit; ldt.access = access; + ldt.access2 = access2; if (granularity) { ldt.limit <<= 12; @@ -226,6 +229,7 @@ static int op0F00_common(uint32_t fetchdat, int ea32) limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16); base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24); access = readmemb(0, addr + 5); + access2 = readmemb(0, addr + 6); granularity = readmemb(0, addr + 6) & 0x80; if (cpu_state.abrt) return 1; access |= 2; @@ -233,7 +237,9 @@ static int op0F00_common(uint32_t fetchdat, int ea32) if (cpu_state.abrt) return 1; tr.seg = sel; tr.limit = limit; + tr.limit_raw = limit; tr.access = access; + tr.access2 = access2; if (granularity) { tr.limit <<= 12; @@ -470,3 +476,14 @@ static int op0F01_286(uint32_t fetchdat) return op0F01_common(fetchdat, 0, 1, 0); } + + +static int opRSM(uint32_t fetchdat) +{ + if (cpu_cur_status & CPU_STATUS_SMM) + x86_smi_leave(); + else + x86illegal(); + + return 1; +} diff --git a/pcem/x86_ops_ret.h b/pcem/x86_ops_ret.h index 271da6e5..e2899d07 100644 --- a/pcem/x86_ops_ret.h +++ b/pcem/x86_ops_ret.h @@ -166,7 +166,7 @@ static int opIRET(uint32_t fetchdat) } else { - x86gpf(NULL,0); + x86gpf_expected(NULL,0); return 1; } } @@ -214,7 +214,7 @@ static int opIRETD(uint32_t fetchdat) if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3)) { - x86gpf(NULL,0); + x86gpf_expected(NULL,0); return 1; } if (msw & 1) diff --git a/pcem/x86seg.cpp b/pcem/x86seg.cpp index 7c39a9cf..41656253 100644 --- a/pcem/x86seg.cpp +++ b/pcem/x86seg.cpp @@ -10,6 +10,7 @@ #include "cpu.h" #include "config.h" #include "paths.h" +#include "i440bx.h" /*Controls whether the accessed bit in a descriptor is set when CS is loaded.*/ #define CS_ACCESSED @@ -72,6 +73,7 @@ void x86abort(const char *format, ...) static void seg_reset(x86seg *s) { s->access = (0 << 5) | 2; + s->access2 = 0; s->limit = 0xFFFF; s->limit_low = 0; s->limit_high = 0xffff; @@ -172,11 +174,17 @@ void x86_doabrt(int x86_abrt) } void x86gpf(const char *s, uint16_t error) { -// pclog("GPF %04X\n", error); +// pclog("GPF %04X %04x(%08x):%08x\n", error, CS,cs,cpu_state.pc); cpu_state.abrt = ABRT_GPF; abrt_error = error; } -void x86ss(const char *s, uint16_t error) +void x86gpf_expected(const char *s, uint16_t error) +{ +// pclog("GPF_v86 %04X %04x(%08x):%08x\n", error, CS,cs,cpu_state.pc); + cpu_state.abrt = ABRT_GPF | ABRT_EXPECTED; + abrt_error = error; +} +void x86ss(char *s, uint16_t error) { // pclog("SS %04X\n", error); cpu_state.abrt = ABRT_SS; @@ -222,12 +230,14 @@ static void set_use32(int u) static void do_seg_load(x86seg *s, uint16_t *segdat) { s->limit = segdat[0] | ((segdat[3] & 0xF) << 16); + s->limit_raw = s->limit; if (segdat[3] & 0x80) s->limit = (s->limit << 12) | 0xFFF; s->base = segdat[1] | ((segdat[2] & 0xFF) << 16); if (is386) s->base |= ((segdat[3] >> 8) << 24); s->access = segdat[2] >> 8; + s->access2 = segdat[3] & 0xf0; if ((segdat[2] & 0x1800) != 0x1000 || !(segdat[2] & (1 << 10))) /*expand-down*/ { @@ -260,6 +270,7 @@ static void do_seg_load(x86seg *s, uint16_t *segdat) static void do_seg_v86_init(x86seg *s) { s->access = (3 << 5) | 2; + s->access2 = 0; s->limit = 0xffff; s->limit_low = 0; s->limit_high = 0xffff; @@ -464,6 +475,7 @@ int loadseg(uint16_t seg, x86seg *s) else { s->access = (3 << 5) | 2; + s->access2 = 0; s->base = seg << 4; s->seg = seg; s->checked = 1; @@ -1726,8 +1738,11 @@ void pmodeint(int num, int soft) if (output) pclog("Addr %08X seg %04X %04X %04X %04X\n",addr,segdat[0],segdat[1],segdat[2],segdat[3]); if (!(segdat[2]&0x1F00)) { - //pclog("No seg\n"); - x86gpf(NULL,(num*8)+2); +// pclog("No seg\n"); + if (cpu_state.eflags & VM_FLAG) /*This fires on all V86 interrupts in EMM386. Mark as expected to prevent code churn*/ + x86gpf_expected(NULL,(num*8)+2); + else + x86gpf(NULL,(num*8)+2); return; } if (DPL>8; } + +void sysenter(void) +{ + cpu_state.eflags &= ~VM_FLAG; + cpu_state.flags &= ~I_FLAG; + + ESP = sysenter_esp; + cpu_state.pc = sysenter_eip; + + cpu_state.seg_cs.seg = sysenter_cs & 0xfffc; + cpu_state.seg_cs.base = 0; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit = 0xffffffff; + cpu_state.seg_cs.limit_high = 0xffffffff; + cpu_state.seg_cs.access = 0x1b; + cpu_state.seg_cs.checked = 1; + oldcpl = 0; + + cpu_state.seg_ss.seg = (sysenter_cs & 0xfffc) + 8; + cpu_state.seg_ss.base = 0; + cpu_state.seg_ss.limit_low = 0; + cpu_state.seg_ss.limit = 0xffffffff; + cpu_state.seg_ss.limit_high = 0xffffffff; + cpu_state.seg_ss.access = 0x13; + cpu_state.seg_ss.checked = 1; + + cpu_cur_status &= ~(CPU_STATUS_NOTFLATSS | CPU_STATUS_V86); + cpu_cur_status |= (CPU_STATUS_USE32 | CPU_STATUS_STACK32 | CPU_STATUS_PMODE); + set_use32(1); + set_stack32(1); + +// pclog("syscall to %04x:%08x %04x:%08x\n", CS, cpu_state.pc, SS, ESP); +} + +void sysexit(void) +{ + ESP = ECX; + cpu_state.pc = EDX; + + cpu_state.seg_cs.seg = (sysenter_cs | 3) + 16; + cpu_state.seg_cs.base = 0; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit = 0xffffffff; + cpu_state.seg_cs.limit_high = 0xffffffff; + cpu_state.seg_cs.access = 0x7b; + cpu_state.seg_cs.checked = 1; + oldcpl = 3; + + cpu_state.seg_ss.seg = (sysenter_cs | 3) + 24; + cpu_state.seg_ss.base = 0; + cpu_state.seg_ss.limit_low = 0; + cpu_state.seg_ss.limit = 0xffffffff; + cpu_state.seg_ss.limit_high = 0xffffffff; + cpu_state.seg_ss.access = 0x73; + cpu_state.seg_ss.checked = 1; + + cpu_cur_status &= ~(CPU_STATUS_NOTFLATSS | CPU_STATUS_V86); + cpu_cur_status |= (CPU_STATUS_USE32 | CPU_STATUS_STACK32 | CPU_STATUS_PMODE); + flushmmucache_cr3(); + set_use32(1); + set_stack32(1); + +// pclog("sysexit to %04x:%08x %04x:%08x\n", CS, cpu_state.pc, SS, ESP); +} + +void x86_smi_trigger(void) +{ + cpu_state.smi_pending = 1; +} + +static void smi_write_descriptor_cache(uint32_t addr, x86seg *seg) +{ + writememl(0, addr + 8, seg->seg | (seg->access << 16) | (seg->access2 << 24)); + writememl(0, addr + 4, seg->base); + writememl(0, addr, seg->limit); +} +static void smi_load_descriptor_cache(uint32_t addr, x86seg *seg) +{ + uint32_t temp; + + temp = readmeml(0, addr + 8); + seg->base = readmeml(0, addr + 4); + seg->limit = readmeml(0, addr); + seg->seg = temp & 0xffff; + seg->access = temp >> 16; + seg->access2 = temp >> 24; + if ((seg->access & 0x18) != 0x10 || !(seg->access & (1 << 2))) /*expand-down*/ + { + seg->limit_high = seg->limit; + seg->limit_low = 0; + } + else + { + seg->limit_high = (seg->access2 & 0x40) ? 0xffffffff : 0xffff; + seg->limit_low = seg->limit + 1; + } +} + +static void smi_load_smi_selector(x86seg *seg) +{ + seg->seg = 0; + seg->base = 0; + seg->limit = 0xffffffff; + seg->limit_low = 0; + seg->limit_high = 0xffffffff; + seg->access = (3 << 5) | 2; + seg->access2 = 0; +} + +void cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg) +{ + writememl(0, addr, (seg->limit_raw & 0xffff) | (seg->base << 16)); + writememl(0, addr+4, ((seg->base >> 16) & 0xff) | + (seg->access << 8) | + (seg->limit_raw & 0xf0000) | + (seg->access2 << 16) | + (seg->base & 0xff000000)); +} + +void cyrix_load_seg_descriptor(uint32_t addr, x86seg *seg) +{ + uint16_t segdat[4], selector; + + segdat[0] = readmemw(0, addr); + segdat[1] = readmemw(0, addr+2); + segdat[2] = readmemw(0, addr+4); + segdat[3] = readmemw(0, addr+6); + selector = readmemw(0, addr+8); + + if (!cpu_state.abrt) + { + do_seg_load(seg, segdat); + seg->seg = selector; + seg->checked = 0; + if (seg == &cpu_state.seg_ds) + { + if (seg->base == 0 && seg->limit_low == 0 && seg->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATDS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATDS; + codegen_flat_ds = 0; + } + if (seg == &cpu_state.seg_ss) + { + if (seg->base == 0 && seg->limit_low == 0 && seg->limit_high == 0xffffffff) + cpu_cur_status &= ~CPU_STATUS_NOTFLATSS; + else + cpu_cur_status |= CPU_STATUS_NOTFLATSS; + set_stack32((segdat[3] & 0x40) ? 1 : 0); + codegen_flat_ss = 0; + } + } +} + +void x86_smi_enter(void) +{ + uint32_t old_cr0 = cr0; + + if (smram_enable) + smram_enable(); + flushmmucache(); + + cpu_386_flags_rebuild(); + cpl_override = 1; + cr0 = 0; /*Disable MMU*/ + + if (cpu_iscyrix) + { + uint32_t base; + + if (!(cyrix.smhr & SMHR_VALID)) + cyrix.smhr = (cyrix.arr[3].base + cyrix.arr[3].size) | SMHR_VALID; + base = cyrix.smhr & SMHR_ADDR_MASK; + + writememl(0, base-4, dr[7]); + writememl(0, base-8, cpu_state.flags | (cpu_state.eflags << 16)); + writememl(0, base-0xc, old_cr0); + writememl(0, base-0x10, cpu_state.oldpc); + writememl(0, base-0x14, cpu_state.pc); + writememl(0, base-0x18, CS | (CPL << 21)); + cyrix_write_seg_descriptor(base-0x20, &cpu_state.seg_cs); + writememl(0, base-0x24, 0); + + cpl_override = 0; + + cpu_cur_status = CPU_STATUS_SMM; + cpu_state.flags = 2; + cpu_state.eflags = 0; + cpu_state.pc = 0; + cr0 &= ~((1 << 0) | (1 << 2) | (1 << 3) | (1 << 31)); + dr[7] = 0x400; + cpu_state.seg_cs.seg = cyrix.arr[3].base >> 4; /*Guess*/ + cpu_state.seg_cs.base = cyrix.arr[3].base; + cpu_state.seg_cs.limit = 0xffffffff; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffffffff; + cpu_state.seg_cs.access = (0 << 5) | 2; + + use32 = 0; + stack32 = 0; + } + else + { + writememl(0, cpu_state.smbase + 0x8000 + 0x7ffc, old_cr0); + writememl(0, cpu_state.smbase + 0x8000 + 0x7ff8, cr3); + writememl(0, cpu_state.smbase + 0x8000 + 0x7ff4, cpu_state.flags | (cpu_state.eflags << 16)); + writememl(0, cpu_state.smbase + 0x8000 + 0x7ff0, cpu_state.pc); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fec, EDI); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fe8, ESI); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fe4, EBP); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fe0, ESP); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fdc, EBX); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fd8, EDX); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fd4, ECX); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fd0, EAX); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fcc, dr[6]); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fc8, dr[7]); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fc4, tr.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fc0, ldt.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fbc, cpu_state.seg_gs.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fb8, cpu_state.seg_fs.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fb4, cpu_state.seg_ds.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fb0, cpu_state.seg_ss.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fac, cpu_state.seg_cs.seg); + writememl(0, cpu_state.smbase + 0x8000 + 0x7fa8, cpu_state.seg_es.seg); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f9c, &tr); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f90, &idt); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f84, &gdt); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f78, &ldt); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f6c, &cpu_state.seg_gs); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f60, &cpu_state.seg_fs); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f54, &cpu_state.seg_ds); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f48, &cpu_state.seg_ss); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f3c, &cpu_state.seg_cs); + smi_write_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f30, &cpu_state.seg_es); + writememl(0, cpu_state.smbase + 0x8000 + 0x7f28, cr4); + writememl(0, cpu_state.smbase + 0x8000 + 0x7ef8, cpu_state.smbase); + writememl(0, cpu_state.smbase + 0x8000 + 0x7efc, 0x00020000); + cpl_override = 0; + + cpu_cur_status = CPU_STATUS_SMM; + cpu_state.flags = 2; + cpu_state.eflags = 0; + cpu_state.pc = 0x8000; + cr0 &= ~((1 << 0) | (1 << 2) | (1 << 3) | (1 << 31)); + dr[7] = 0x400; + smi_load_smi_selector(&cpu_state.seg_ds); + smi_load_smi_selector(&cpu_state.seg_es); + smi_load_smi_selector(&cpu_state.seg_fs); + smi_load_smi_selector(&cpu_state.seg_gs); + smi_load_smi_selector(&cpu_state.seg_ss); + cpu_state.seg_cs.seg = 0x3000; + cpu_state.seg_cs.base = cpu_state.smbase; + cpu_state.seg_cs.limit = 0xffffffff; + cpu_state.seg_cs.limit_low = 0; + cpu_state.seg_cs.limit_high = 0xffffffff; + cpu_state.seg_cs.access = (0 << 5) | 2; + + use32 = 0; + stack32 = 0; + } + + oldcpl = 0; + +// pclog("x86_smi_enter\n"); +} + +void x86_smi_leave(void) +{ + uint32_t temp; + uint32_t new_cr0; + + if (cpu_iscyrix) + { + uint32_t base = cyrix.smhr & SMHR_ADDR_MASK; + + cpl_override = 1; + dr[7] = readmeml(0, base-4); + temp = readmeml(0, base-8); + cpu_state.flags = temp & 0xffff; + cpu_state.eflags = temp >> 16; + new_cr0 = readmeml(0, base-0xc); + cpu_state.pc = readmeml(0, base-0x14); + cyrix_load_seg_descriptor(base-0x20, &cpu_state.seg_cs); + cpl_override = 0; + + cr0 = new_cr0; + } + else + { + cpl_override = 1; + new_cr0 = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ffc); + cr3 = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ff8); + temp = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ff4); + cpu_state.flags = temp & 0xffff; + cpu_state.eflags = temp >> 16; + cpu_state.pc = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ff0); + EDI = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fec); + ESI = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fe8); + EBP = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fe4); + ESP = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fe0); + EBX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fdc); + EDX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fd8); + ECX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fd4); + EAX = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fd0); + dr[6] = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fcc); + dr[7] = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fc8); + tr.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fc4); + ldt.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fc0); + cpu_state.seg_gs.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fbc); + cpu_state.seg_fs.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fb8); + cpu_state.seg_ds.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fb4); + cpu_state.seg_ss.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fb0); + cpu_state.seg_cs.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fac); + cpu_state.seg_es.seg = readmeml(0, cpu_state.smbase + 0x8000 + 0x7fa8); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f9c, &tr); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f90, &idt); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f84, &gdt); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f78, &ldt); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f6c, &cpu_state.seg_gs); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f60, &cpu_state.seg_fs); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f54, &cpu_state.seg_ds); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f48, &cpu_state.seg_ss); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f3c, &cpu_state.seg_cs); + smi_load_descriptor_cache(cpu_state.smbase + 0x8000 + 0x7f30, &cpu_state.seg_es); + cr4 = readmeml(0, cpu_state.smbase + 0x8000 + 0x7f28); + cpu_state.smbase = readmeml(0, cpu_state.smbase + 0x8000 + 0x7ef8); + cpl_override = 0; + + cr0 = new_cr0; + } + + cpu_386_flags_extract(); + cpu_cur_status = 0; + use32 = stack32 = 0; + if (cr0 & 1) + { + cpu_cur_status |= CPU_STATUS_PMODE; + if (cpu_state.eflags & VM_FLAG) + cpu_cur_status |= CPU_STATUS_V86; + else + { + if (cpu_state.seg_cs.access2 & 0x40) + { + cpu_cur_status |= CPU_STATUS_USE32; + use32 = 0x300; + } + if (cpu_state.seg_ss.access2 & 0x40) + { + cpu_cur_status |= CPU_STATUS_STACK32; + stack32 = 1; + } + } + } + if (!(cpu_state.seg_ds.base == 0 && cpu_state.seg_ds.limit_low == 0 && cpu_state.seg_ds.limit_high == 0xffffffff)) + cpu_cur_status |= CPU_STATUS_NOTFLATDS; + if (!(cpu_state.seg_ss.base == 0 && cpu_state.seg_ss.limit_low == 0 && cpu_state.seg_ss.limit_high == 0xffffffff)) + cpu_cur_status |= CPU_STATUS_NOTFLATSS; + + if (smram_disable) + smram_disable(); + flushmmucache(); + + oldcpl = CPL; + +// pclog("x86_smi_leave\n"); +} diff --git a/pcem/x87_ops_misc.h b/pcem/x87_ops_misc.h index 61a9919a..e23d4709 100644 --- a/pcem/x87_ops_misc.h +++ b/pcem/x87_ops_misc.h @@ -673,7 +673,8 @@ static int opFSCALE(uint32_t fetchdat) cpu_state.pc++; if (fplog) pclog("FSCALE\n"); temp64 = (int64_t)ST(1); - ST(0) = ST(0) * pow(2.0, (double)temp64); + if (ST(0) != 0.0) + ST(0) = ST(0) * pow(2.0, (double)temp64); cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; CLOCK_CYCLES(x87_timings.fscale); return 0; @@ -781,6 +782,8 @@ static int FSTENV() { FP_ENTER(); if (fplog) pclog("FSTENV %08X:%08X\n", easeg, cpu_state.eaaddr); + cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | ((cpu_state.TOP & 7) << 11); + switch ((cr0 & 1) | (cpu_state.op32 & 0x100)) { case 0x000: /*16-bit real mode*/ -- 2.47.3