]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
PCem v17 merge
authorToni Wilen <twilen@winuae.net>
Thu, 26 Aug 2021 17:42:31 +0000 (20:42 +0300)
committerToni Wilen <twilen@winuae.net>
Thu, 26 Aug 2021 17:42:31 +0000 (20:42 +0300)
55 files changed:
gfxboard.cpp
pcem/386.cpp
pcem/386_common.cpp
pcem/386_common.h
pcem/386_dynarec.cpp
pcem/386_ops.h
pcem/808x.cpp
pcem/codegen.h
pcem/codegen_backend_x86-64.h
pcem/codegen_backend_x86.h
pcem/cpu.cpp
pcem/cpu.h
pcem/f82c710_upc.h [new file with mode: 0644]
pcem/i440bx.h [new file with mode: 0644]
pcem/ibm.h
pcem/keyboard_at.cpp
pcem/keyboard_at.h
pcem/mem.cpp
pcem/mem.h
pcem/mouse_ps2.cpp
pcem/nvr.cpp
pcem/paths.h
pcem/pcemglue.cpp
pcem/pic.cpp
pcem/serial.cpp
pcem/serial.h
pcem/vid_cl5429.cpp
pcem/vid_s3.cpp
pcem/vid_s3_virge.cpp
pcem/vid_svga.cpp
pcem/vid_svga.h
pcem/vid_svga_render.cpp
pcem/vid_svga_render.h
pcem/vid_svga_render_remap.h [new file with mode: 0644]
pcem/vid_voodoo.cpp
pcem/vid_voodoo_banshee.cpp
pcem/vid_voodoo_banshee.h
pcem/vid_voodoo_blitter.cpp
pcem/vid_voodoo_common.h
pcem/vid_voodoo_dither.h
pcem/vid_voodoo_regs.h
pcem/vid_voodoo_render.cpp
pcem/vid_voodoo_render.h
pcem/x86.h
pcem/x86_ops.h
pcem/x86_ops_cyrix.h [new file with mode: 0644]
pcem/x86_ops_flag.h
pcem/x86_ops_int.h
pcem/x86_ops_io.h
pcem/x86_ops_misc.h
pcem/x86_ops_mmx_mov.h
pcem/x86_ops_pmode.h
pcem/x86_ops_ret.h
pcem/x86seg.cpp
pcem/x87_ops_misc.h

index 72dab22ccdf6ef4a26b5d477566c951cdec1ab7b..14fe7ab70da5ff6ddd317713acdb607772669dab 100644 (file)
@@ -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) {
index e99ef1f68869604e8fbcb8ecda64813a8a9166ce..85b22f47422e232df65d03ff95887cc3f58305c4 100644 (file)
@@ -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--;
index 8919652e4fca93aab595856d1f4d8c1786c1513b..eecdaece76bac3164b9532156f074fc602fe5caf 100644 (file)
@@ -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;
index c01b9c70eaa7187da4f9c12b8a044bc8fd6e6e6b..a78b6e9a5239d3ed7541021873aea90ae644577d 100644 (file)
@@ -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; \
                                 } \
                         }
index dc87772ce53b1eb6fd6ab27ffdd2bcba4ac18f62..4fabbb26dbc88c35c4c148d1dbf87d598fcad796 100644 (file)
@@ -1,6 +1,9 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
+#if defined(__APPLE__) && defined(__aarch64__)
+#include <pthread.h>
+#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))
index 5c73ccb4159db4d34b3b3c1e6f90fec04ee07ffc..c48863bde9c7cffb935848cc1182ce5056471934 100644 (file)
@@ -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*/        
index 99eba41f522a2f245af86a4258d4c4288d503725..039f82e9310fc5092e01e7fe22b796d799352728 100644 (file)
@@ -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()
index d4f2563f65c40b4de4765bb0f843ff7179dcd6e1..ac5c0bc39c61f27ecf78f9f3f5ca0533f11bfc53 100644 (file)
@@ -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);
 
index 70e953a6bd267dccbe7dd058cfbed685b854d211..ccc526b30892f51464d6fb37c3d377cce2796b32 100644 (file)
@@ -10,3 +10,5 @@
 #define HASH(l) ((l) & 0x1ffff)
 
 #define BLOCK_MAX 0x3c0
+
+#define CODEGEN_BACKEND_HAS_MOV_IMM
index a5aec727c02d0b385539298e63ae695efb325f15..582e464304f72dc2c11547bb1230cac813fe65f0 100644 (file)
@@ -10,3 +10,5 @@
 #define HASH(l) ((l) & 0x1ffff)
 
 #define BLOCK_MAX 0x3c0
+
+#define CODEGEN_BACKEND_HAS_MOV_IMM
index 6dbd3406bb520087f7c555a1e9d866d37cd52dfd..37c6d51ffdc70ad5da3264e457662b6971f2bd7f 100644 (file)
@@ -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);
+        }
+}
index b4dc2b66004239c0274e19a16f1e7ab6b1680bbc..d4bea605fbac7f8559dc7444c2261ab531e2b0f4 100644 (file)
@@ -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 (file)
index 0000000..05764af
--- /dev/null
@@ -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 (file)
index 0000000..8ed559f
--- /dev/null
@@ -0,0 +1,2 @@
+void i440bx_init();
+void i440bx_reset();
index f984d4a7b9469c9b0ac0aeb57c16eb6ebd5bb6c9..c4afe4ddbf375fc3f20912fbdf24f14161a50686 100644 (file)
@@ -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);
index 64534ddf981bece699b224d44edfadf16b82100a..7b64520b48b7820535a43fe640a85582b8e9f335 100644 (file)
@@ -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;
index 5dafaca9e140346da7136089f37e8d8c0b8a444e..4c49c9888bbdca3d8143bbe616770eb6a9f5e3fe 100644 (file)
@@ -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;
index 43d2d958d8bf9502fed6e5b76fed033c58a48939..f2fcbb6c6b3b969b46b7252af8eab8f996d140cf 100644 (file)
@@ -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);
index 3c6a0f5e47de8850c7796b67439ade343041dd99..866ae11b549943d75c368d8d0c225419f41272da 100644 (file)
@@ -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
index 4df123105858ba12f9023c5e26b4847ab1acd148..15fd484c2814a9c341c0fb2fa72c0c649994b069 100644 (file)
@@ -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;
 }
 
index 4fdda9ba97a291e627684ff57b2c210e63b2eca6..7668a80ace82f4dd9a19b0370b7de3617bf8be20 100644 (file)
@@ -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;
index 2aceeecdd6423fc7d4d4895943cd66043bef852d..4c0538f30966eac0c3b23f814b18e27fb667c7d6 100644 (file)
@@ -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);
index 987af7c655cb92993f56dac3fbace4b2d818ae9d..b279f94c383c5e5ecf80a0fa6f853b8f94c3dfc1 100644 (file)
@@ -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)
+{
+}
index 79124296868a025523f81f584592d6250b447fa9..27ed7bb4b77b404a0be08492e3e63f10345c7faa 100644 (file)
@@ -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<<c);
                         pic_update_mask(&pic.mask2, pic.ins);
 
-                        if (c == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2)
+                        if ((AT || romset == ROM_XI8088) && c == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2)
                                 pic.pend |= (1 << 2);
 
                         pic_updatepending();
@@ -341,14 +347,13 @@ void picint(uint16_t num)
         if ((AT || romset == ROM_XI8088) && num == (1 << 2))
                 num = 1 << 9;
 //        pclog("picint : %04X\n", num);
-//        if (num == 0x10) pclog("PICINT 10\n");
-        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;
         }
@@ -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;
                 }
         }
index 8d2947bbfb867f1965afb9b85e59ad6f48357783..570da45fa0cd38a576a4a95c089a8aa75587c521 100644 (file)
@@ -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);
index 4818423fedb4e5c780f47719c80a0826af79c3e2..0bf88f10365993a3268b2c65949ac39e36b7cfa6 100644 (file)
@@ -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();
index 730b4ff9dbafb57b4262ca5aaf2ec40e7fd15c44..bce75e850847b2417004e459fbab264267e72e07 100644 (file)
@@ -1,4 +1,5 @@
 /*Cirrus Logic CL-GD5429 emulation*/
+//SR7.0 = "true packed-pixel memory addressing"
 #include <stdlib.h>
 #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);
index 7b7054c5744b33d5c1a3dfb160d71147677c15ee..d41bd328fa6830dc84d7376138942fecd71e8579 100644 (file)
@@ -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);
 }
 
index 1acab18e8296bd332e25414db49ebfee931e1283..b36823a3aee02157f02c9ede3185e7fcbda03478 100644 (file)
@@ -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;
 }
 
index f75d48d4e2c374be64141b4a15206588213b15ec..c925b3257f5b5670a8899ef736354a8529f43038 100644 (file)
@@ -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 ");
index e0d6900d43fff915bddd1792df1d6b7851aebe7b..df5c0f88c52b41acdd5ce6f12a409d512322a13e 100644 (file)
@@ -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;
 
index a2609cd0e6bdfee8fb1e1328738a5e49265bf9ae..1fc0fc1b503eb34f31f3aacaed8ce34d4dbd89cc 100644 (file)
@@ -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_tsvga)
+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;
         }
 }
index 06e5097ea35bc578b243e46a109f9f549ac92128..e0f81e5eae962974464172a768ccf52d70aca58b 100644 (file)
@@ -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 (file)
index 0000000..189f846
--- /dev/null
@@ -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];
+}
index 4f5fcacb6b4072ff96ea5b8329b02042c983eeeb..3726074141f9a12172924a97580ef37507bfe116 100644 (file)
@@ -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",
index f84376ce09c5236b8892aa858f8157210a70a741..784e6e23e3bd00f06a6be499b7bf3fa3cc10d015 100644 (file)
@@ -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
-};
index 20c8808e185f1743e3c3a7bbc44b47e553461af6..ddd7e3fda031599e7a5d9309631b77d270fa671f 100644 (file)
@@ -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);
index 01048f9a58c80d9329a43f5d4dd95d4a0cce27d7..af7e2046f173248375fdf22117f732316caed6f5 100644 (file)
@@ -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
         {
index df261af79880b4d3b679931eb1cb6eea7fbfa621..bfd0f7f467de6e2e464577db12987199b096d48c 100644 (file)
@@ -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;
index 67d483883319f661b2246295b47b758580d4dd81..dc7c415e46a295336531fd9929e8fb03d5dbe9ea 100644 (file)
@@ -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},
+      },
+};
+
index f7ab208990b002b6219d486aaca8e4222994b9a3..e99241f6f4a829f119df4c9e2af00811f28f468c 100644 (file)
@@ -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)
+
index 777d9cc39038662c3ba22bcf0b4915c4471b4ff4..f8ad7a4fe3f08a30a543cd146e090a9c8cfdb8b5 100644 (file)
@@ -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)
                                 {
index 54a9be422ee03a1ca0a51c43a55c64f1f55de867..9ba73dc635cad4db86d6228b845b7954fa4a2822 100644 (file)
@@ -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
index d761d69a2da3b1291aa4c14a56e4f06e4f977221..822d079671c355ce2a5ba3805699b03630c234eb 100644 (file)
@@ -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
index ad4f0706bdfbe8a5fcaacd0c1c7a56bbe11b235d..67f6fb927faa3e88844b68195e4f579439403c21 100644 (file)
@@ -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 (file)
index 0000000..e6464ce
--- /dev/null
@@ -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;
+}
index d21408c8bf440d25032786b69e7d40276ac10a4c..2f420f41a49368c0d08a86a0e71b2fce30ba31a9 100644 (file)
@@ -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;
index 97793405ce007b39b56fe41334968e07799be176..7c5ada6d797d6d372f2cfee5c4aef923c2989d99 100644 (file)
@@ -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);
index dd1f7da86f13267cdf24be2f941555f6e1d650f2..600090b2cd31b0f48e0e54e08b993cd2606813c7 100644 (file)
@@ -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;
index 9e281f2e540d55ef08c19531198980ac7eb06bbf..847201207551293867c88faf2ce9626d97068d1a 100644 (file)
@@ -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;
+}
index f598d5b24ed6218eaafee0097d2cb33aff69df10..f61bdfeafdfa4bbe36a4009d5e954b197c8e2824 100644 (file)
@@ -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)
index 7afd6c8bfeac2888cb63ebde73938c488d3c541e..0589ba01c7323a99b1a8c673f0c2acee5771e1e0 100644 (file)
@@ -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;
+}
index 271da6e575c4dd43532ff3f0321f95100cb08ac3..e2899d078cfb0df14eec264f589a3c3c9d7d9e34 100644 (file)
@@ -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)
index 7c39a9cf132a0ce5e982a1efc38c9563101bc7f1..4165625386dd86b21655c9196b452c6e7b08ea9e 100644 (file)
@@ -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<CPL && soft)
@@ -2884,3 +2899,370 @@ void taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
         tr.access=segdat[2]>>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");
+}
index 61a9919a753d0319df8b43a06fc0a87fdb22f965..e23d470916b769a2eaebc0caef3f76a882c19b5b 100644 (file)
@@ -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*/