OSDN Git Service

[VM][I386] Make some functions around address translation INLINE.
authorK.Ohta <whatisthis.sowhat@gmail.com>
Sun, 21 Apr 2019 20:44:12 +0000 (05:44 +0900)
committerK.Ohta <whatisthis.sowhat@gmail.com>
Sun, 21 Apr 2019 20:44:12 +0000 (05:44 +0900)
[VM][I386] Fix unexpected page fault when accessing memories.
[VM][I386] Try to call pseudo-bios even within protected mode (inside of i386_trap()).
[VM][UPD7220] Temporally disable some debug messages.

source/src/vm/i386.cpp
source/src/vm/mame/emu/cpu/i386/i386.c
source/src/vm/mame/emu/cpu/i386/i386ops.c
source/src/vm/mame/emu/cpu/i386/i386priv.h
source/src/vm/upd7220.cpp

index 79d98cd..2ba5fd7 100644 (file)
@@ -229,7 +229,7 @@ typedef UINT32      offs_t;
 
 //#ifdef I386_PSEUDO_BIOS
 #define BIOS_INT(num) if(cpustate->bios != NULL) { \
-               if(((cpustate->cr[0] & 0x0001) == 0) || (cpustate->VM != 0)) {  /* VM8086 or Not Protected */ \
+               /*if(((cpustate->cr[0] & 0x0001) == 0) || (cpustate->VM != 0)) */{      /* VM8086 or Not Protected */ \
                        uint16_t regs[10], sregs[4];                                                            \
                        regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
                        regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
@@ -253,6 +253,7 @@ if(cpustate->bios->bios_int_i86(num, regs, sregs, &ZeroFlag, &CarryFlag, &(cpust
                }                                                                                                                               \
        }
 
+
 #define BIOS_CALL_FAR(address) if(cpustate->bios != NULL) {                            \
                if(((cpustate->cr[0] & 0x0001) == 0) || (cpustate->VM != 0)) {  /* VM8086 or Not Protected */ \
                        uint16_t regs[10], sregs[4];                                                            \
@@ -277,6 +278,33 @@ if(cpustate->bios->bios_int_i86(num, regs, sregs, &ZeroFlag, &CarryFlag, &(cpust
                        }                                                                                                                       \
                }                                                                                                                               \
        }
+
+
+#define BIOS_TRAP(address,stat) if(cpustate->bios != NULL) {                           \
+               if(((cpustate->cr[0] & 0x0001) == 0) || (cpustate->VM != 0)) {  /* VM8086 or Not Protected */ \
+                       uint16_t regs[10], sregs[4];                                                            \
+                       regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
+                       regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
+                       regs[8] = 0x0000; regs[9] = 0x0000;                                                     \
+                       sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
+                       sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
+                       int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF;      \
+                       stat = 0;                                                                                                       \
+                       if(cpustate->bios->bios_call_far_i86(address, regs, sregs, &ZeroFlag, &CarryFlag, &(cpustate->cycles), &(cpustate->total_cycles))) { \
+                               REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
+                               REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
+                               cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
+                               /*CYCLES(cpustate,CYCLES_RET_INTERSEG);*/                               \
+                               if((regs[8] != 0x0000) || (regs[9] != 0x0000)) {                \
+                                       uint32_t hi = regs[9];                                                          \
+                                       uint32_t lo = regs[8];                                                          \
+                                       uint32_t addr = (hi << 16) | lo;                                        \
+                                       cpustate->eip = addr;                                                           \
+                               }                                                                                                               \
+                               stat = 1;                                                                                               \
+                       }                                                                                                                       \
+               }                                                                                                                               \
+       }
 //#endif
 
 static CPU_TRANSLATE(i386);
index 9f03d4e..d19e0b3 100644 (file)
@@ -524,7 +524,7 @@ static void i386_check_sreg_validity(i386_state* cpustate, int reg)
                i386_load_segment_descriptor(cpustate,reg);
        }
 }
-
+#if 0
 static int i386_limit_check(i386_state *cpustate, int seg, UINT32 offset, UINT32 size)
 {
        if(PROTECTED_MODE && !V8086_MODE)
@@ -549,7 +549,7 @@ static int i386_limit_check(i386_state *cpustate, int seg, UINT32 offset, UINT32
        }
        return 0;
 }
-
+#endif
 static void i386_sreg_load(i386_state *cpustate, UINT16 selector, UINT8 reg, bool *fault)
 {
        // Checks done when MOV changes a segment register in protected mode
@@ -1112,6 +1112,50 @@ static void i386_trap(i386_state *cpustate,int irq, int irq_gate, int trap_level
                //cpustate->eflags &= ~0xffc00002;
                cpustate->eflags = get_flags(cpustate);
                set_flags(cpustate, cpustate->eflags);
+#if 1          
+               if((irq >= 0x10) && (irq_gate == 1) && (cpustate->ext == 0)) {
+                       // Try to call pseudo bios
+                       i386_load_segment_descriptor(cpustate,CS);
+                       UINT32 tmp_pc = i386_translate(cpustate, CS, cpustate->eip, -1, 1 );
+                       int stat = 0;
+                       BIOS_TRAP(tmp_pc, stat);
+                       if(stat != 0) { // HIT
+                               try
+                               {
+                                       // this is ugly but the alternative is worse
+                                       if(/*type != 0x0e && type != 0x0f*/ (type & 0x08) == 0)  // if not 386 interrupt or trap gate
+                                       {
+                                               cpustate->eip = POP16(cpustate);
+                                               cpustate->sreg[CS].selector = POP16(cpustate);
+                                               UINT32 __flags = POP16(cpustate);
+                                               cpustate->eflags = (get_flags(cpustate) & 0xffff0000) | (__flags & 0x0000ffff);
+                                               set_flags(cpustate, cpustate->eflags);
+                                       }
+                                       else
+                                       {
+                                               cpustate->eip = POP32(cpustate);
+                                               UINT32 sel;
+                                               sel = POP32(cpustate);
+                                               cpustate->sreg[CS].selector = sel; // ToDo: POP32SEG()
+                                               UINT32 __flags = POP32(cpustate);
+                                               cpustate->eflags = (get_flags(cpustate) & 0xff000000) | (__flags & 0x00ffffff);
+                                               set_flags(cpustate, cpustate->eflags);
+                                       }
+                               }
+                               catch(UINT64 e)
+                               {
+                                       REG32(ESP) = tempSP;
+                                       logerror("THROWN EXCEPTION %08X at i386_trap() IRQ=%02x EIP=%08x V8086_MODE=%s line %d\n", e, irq, cpustate->eip, (V8086_MODE) ? "Yes" : "No", __LINE__);
+                                       throw e;
+                               }
+                               return;
+                       }
+                       // Not HIT
+                       CHANGE_PC(cpustate,cpustate->eip);
+                       return;
+               }
+#endif                         
+
        }
 
        i386_load_segment_descriptor(cpustate,CS);
@@ -3665,7 +3709,10 @@ static CPU_EXECUTE( i386 )
        while( cpustate->cycles > 0 && !cpustate->busreq )
        {
 //#ifdef USE_DEBUGGER
-               bool now_debugging = cpustate->debugger->now_debugging;
+               bool now_debugging = false;
+               if(cpustate->debugger != NULL) {
+                       now_debugging = cpustate->debugger->now_debugging;
+               }
                if(now_debugging) {
                        cpustate->debugger->check_break_points(cpustate->pc);
                        if(cpustate->debugger->now_suspended) {
@@ -3766,7 +3813,7 @@ static CPU_EXECUTE( i386 )
                        int old_tf = cpustate->TF;
 
 //#ifdef USE_DEBUGGER
-                       cpustate->debugger->add_cpu_trace(cpustate->pc);
+                       if(cpustate->debugger != NULL) cpustate->debugger->add_cpu_trace(cpustate->pc);
 //#endif
                        cpustate->segment_prefix = 0;
                        cpustate->prev_eip = cpustate->eip;
index b6e08e1..03bf376 100644 (file)
@@ -2523,19 +2523,19 @@ static void I386OP(int_16)(i386_state *cpustate)               // Opcode 0xcd
        CYCLES(cpustate,CYCLES_INT);
        if(V8086_MODE) {
                //logerror("INT %02xh @V8086(16bit) mode PC=%08X\n", interrupt, cpustate->pc - 1);
-               if((!cpustate->IOP1 || !cpustate->IOP2))
-               {
-                       logerror("IRQ (%08x): Is in Virtual 8086 mode and IOPL != 3.\n",cpustate->pc);
-                       FAULT(FAULT_GP,0);
-               } else {
+//             if((!cpustate->IOP1 || !cpustate->IOP2))
+//             {
+//                     logerror("IRQ (%08x): Is in Virtual 8086 mode and IOPL != 3.\n",cpustate->pc);
+//                     FAULT(FAULT_GP,0);
+//             } else {
                        BIOS_INT(interrupt);
-               }
+//             }
        } else {
                //logerror("INT %02xh @16bit mode PC=%08X\n", interrupt, cpustate->pc - 1);
-               UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
-               if(!(PROTECTED_MODE && (cpustate->CPL > IOPL))) {
+//             UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
+//             if(!(PROTECTED_MODE && (cpustate->CPL > IOPL))) {
                        BIOS_INT(interrupt);
-               }
+//             }
        }               
        cpustate->ext = 0; // not an external interrupt
        i386_trap(cpustate,interrupt, 1, 0);
@@ -2549,19 +2549,19 @@ static void I386OP(int_32)(i386_state *cpustate)               // Opcode 0xcd
 #if 1
        if(V8086_MODE) {
                //logerror("INT %02xh @V8086(32bit) mode PC=%08X\n", interrupt, cpustate->pc - 1);
-               if((!cpustate->IOP1 || !cpustate->IOP2))
-               {
-                       logerror("IRQ (%08x): Is in Virtual 8086 mode and IOPL != 3.\n",cpustate->pc);
-                       FAULT(FAULT_GP,0);
-               } else {
+//             if((!cpustate->IOP1 || !cpustate->IOP2))
+//             {
+//                     logerror("IRQ (%08x): Is in Virtual 8086 mode and IOPL != 3.\n",cpustate->pc);
+//                     FAULT(FAULT_GP,0);
+//             } else {
                        BIOS_INT(interrupt);
-               }
+//             }
        } else {
                //logerror("INT %02xh @32bit mode PC=%08X\n", interrupt, cpustate->pc - 1);
-               UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
-               if(!(PROTECTED_MODE && (cpustate->CPL > IOPL))) {
+//             UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
+//             if(!(PROTECTED_MODE && (cpustate->CPL > IOPL))) {
                        BIOS_INT(interrupt);
-               }
+//             }
        }
 #endif
        cpustate->ext = 0; // not an external interrupt
index 39dfd0d..f091b40 100644 (file)
@@ -561,7 +561,7 @@ struct i386_state
 };
 
 extern int i386_parity_table[256];
-static int i386_limit_check(i386_state *cpustate, int seg, UINT32 offset, UINT32 size);
+//static int i386_limit_check(i386_state *cpustate, int seg, UINT32 offset, UINT32 size);
 
 #define FAULT_THROW(fault,error) {                                                                     \
                /*logerror("FAULT_THROW(%s , %s)\n", #fault , #error );*/       \
@@ -664,6 +664,31 @@ extern MODRM_TABLE i386_MODRM_table[256];
 
 /***********************************************************************************/
 
+INLINE int i386_limit_check(i386_state *cpustate, int seg, UINT32 offset, UINT32 size)
+{
+       if(PROTECTED_MODE && !V8086_MODE)
+       {
+               if((cpustate->sreg[seg].flags & 0x0018) == 0x0010 && cpustate->sreg[seg].flags & 0x0004) // if expand-down data segment
+               {
+                       // compare if greater then 0xffffffff when we're passed the access size
+                       if(((offset + size - 1) <= cpustate->sreg[seg].limit) || ((cpustate->sreg[seg].d)?0:((offset + size - 1) > 0xffff)))
+                       {
+                               logerror("Limit check at 0x%08x failed. Segment %04x, limit %08x, offset %08x (expand-down)\n",cpustate->pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].limit,offset);
+                               return 1;
+                       }
+               }
+               else
+               {
+                       if((offset + size - 1) > cpustate->sreg[seg].limit)
+                       {
+                               logerror("Limit check at 0x%08x failed. Segment %04x, limit %08x, offset %08x\n",cpustate->pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].limit,offset);
+                               return 1;
+                       }
+               }
+       }
+       return 0;
+}
+
 INLINE UINT32 i386_translate(i386_state *cpustate, int segment, UINT32 ip, int rwn, UINT32 size)
 {
        // TODO: segment limit access size, execution permission, handle exception thrown from exception handler
@@ -693,7 +718,7 @@ INLINE vtlb_entry get_permissions(UINT32 pte, int wp)
        return ret;
 }
 
-static int i386_translate_address(i386_state *cpustate, int intention, offs_t *address, vtlb_entry *entry)
+INLINE int i386_translate_address(i386_state *cpustate, int intention, offs_t *address, vtlb_entry *entry)
 {
        UINT32 a = *address;
        UINT32 pdbr = cpustate->cr[3] & 0xfffff000;// I386_CR3_PD_MASK
@@ -781,7 +806,7 @@ static int i386_translate_address(i386_state *cpustate, int intention, offs_t *a
        return ret;
 }
 
-static int i386_translate_address_with_width(i386_state *cpustate, int intention, int width, offs_t *address, vtlb_entry *entry)
+INLINE int i386_translate_address_with_width(i386_state *cpustate, int intention, int width, offs_t *address, vtlb_entry *entry)
 {
        UINT32 a = *address;
        UINT32 pdbr = cpustate->cr[3] & 0xfffff000;// I386_CR3_PD_MASK
@@ -878,7 +903,7 @@ static int i386_translate_address_with_width(i386_state *cpustate, int intention
 
 //#define TEST_TLB
 
-static /*INLINE*/ int translate_address(i386_state *cpustate, int pl, int type, UINT32 *address, UINT32 *error)
+INLINE int translate_address(i386_state *cpustate, int pl, int type, UINT32 *address, UINT32 *error)
 {
        if(!(cpustate->cr[0] & I386_CR0_PG)) // Some (very few) old OS's won't work with this
                return TRUE;
@@ -921,7 +946,7 @@ static /*INLINE*/ int translate_address(i386_state *cpustate, int pl, int type,
 }
 
 
-static /*INLINE */int translate_address_with_width(i386_state *cpustate, int pl, int type, UINT32 width, UINT32 *address, UINT32 *error)
+INLINE int translate_address_with_width(i386_state *cpustate, int pl, int type, UINT32 width, UINT32 *address, UINT32 *error)
 {
        if(!(cpustate->cr[0] & I386_CR0_PG)) // Some (very few) old OS's won't work with this
                return TRUE;
@@ -971,8 +996,15 @@ INLINE void CHANGE_PC(i386_state *cpustate, UINT32 pc)
 INLINE void NEAR_BRANCH(i386_state *cpustate, INT32 offs)
 {
        /* TODO: limit */
-       cpustate->eip += offs;
+//     if(i386_limit_check(cpustate, CS, cpustate->eip + offs, 1) != 0) {
+//             FAULT_THROW(FAULT_GP, 0); //OK?
+//     }
+//     UINT32 mask = cpustate->a20_mask;
+//     cpustate->eip = (cpustate->eip + offs) & mask;
+       cpustate->eip = cpustate->eip + offs;
        cpustate->pc += offs;
+       // ToDo: Translate a20 mask
+//     cpustate->pc = i386_translate(cpustate, CS, cpustate->pc + offs, -1, 1 );
 }
 
 INLINE UINT8 FETCH(i386_state *cpustate)
@@ -998,15 +1030,16 @@ INLINE UINT16 FETCH16(i386_state *cpustate)
        UINT32 address = cpustate->pc, error;
 
        if( !WORD_ALIGNED(address) ) {       /* Unaligned read */
-               if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_FETCH,2,&address,&error))
-                       PF_THROW(error);
-               UINT32 mask = cpustate->a20_mask;
-               value  = ((cpustate->program->read_data8((address + 0) & mask)) << 0);
-               value |= ((cpustate->program->read_data8((address + 1) & mask)) << 8);
-               cpustate->eip += 2;
-               cpustate->pc += 2;
-               //value = (FETCH(cpustate) << 0);
-               //value |= (FETCH(cpustate) << 8);
+               if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_FETCH,2,&address,&error)) {
+                       value = (FETCH(cpustate) << 0);
+                       value |= (FETCH(cpustate) << 8);
+               } else {
+                       UINT32 mask = cpustate->a20_mask;
+                       value  = ((cpustate->program->read_data8((address + 0) & mask)) << 0);
+                       value |= ((cpustate->program->read_data8((address + 1) & mask)) << 8);
+                       cpustate->eip += 2;
+                       cpustate->pc += 2;
+               }
        } else {
                if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_FETCH,&address,&error))
                        PF_THROW(error);
@@ -1023,19 +1056,26 @@ INLINE UINT32 FETCH32(i386_state *cpustate)
        UINT32 address = cpustate->pc, error;
 
        if( !DWORD_ALIGNED(cpustate->pc) ) {      /* Unaligned read */
-               if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_FETCH,4,&address,&error))
-                       PF_THROW(error);
-               UINT32 mask = cpustate->a20_mask;
-               value  = ((cpustate->program->read_data8((address + 0) & mask)) << 0);
-               value |= ((cpustate->program->read_data8((address + 1) & mask)) << 8);
-               value |= ((cpustate->program->read_data8((address + 2) & mask)) << 16);
-               value |= ((cpustate->program->read_data8((address + 3) & mask)) << 24);
-               cpustate->eip += 4;
-               cpustate->pc += 4;
-               //value = (FETCH(cpustate) << 0);
-               //value |= (FETCH(cpustate) << 8);
-               //value |= (FETCH(cpustate) << 16);
-               //value |= (FETCH(cpustate) << 24);
+               if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_FETCH,4,&address,&error)) {
+                       value = (FETCH(cpustate) << 0);
+                       value |= (FETCH(cpustate) << 8);
+                       value |= (FETCH(cpustate) << 16);
+                       value |= (FETCH(cpustate) << 24);
+                       //      PF_THROW(error);
+               } else {
+                       UINT32 mask = cpustate->a20_mask;
+                       if(WORD_ALIGNED(cpustate->pc)) {
+                               value  = ((cpustate->program->read_data16((address + 0) & mask)) << 0);
+                               value |= ((cpustate->program->read_data16((address + 2) & mask)) << 16);
+                       } else {
+                               value  = ((cpustate->program->read_data8((address + 0) & mask)) << 0);
+                               value |= ((cpustate->program->read_data8((address + 1) & mask)) << 8);
+                               value |= ((cpustate->program->read_data8((address + 2) & mask)) << 16);
+                               value |= ((cpustate->program->read_data8((address + 3) & mask)) << 24);
+                       }
+                       cpustate->eip += 4;
+                       cpustate->pc += 4;
+               }
        } else {
                if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_FETCH,&address,&error))
                        PF_THROW(error);
@@ -1064,13 +1104,15 @@ INLINE UINT16 READ16(i386_state *cpustate,UINT32 ea)
        UINT32 address = ea, error;
 
        if( !WORD_ALIGNED(ea) ) {        /* Unaligned read */
-               if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_READ,2,&address,&error))
-                       PF_THROW(error);
-               UINT32 mask = cpustate->a20_mask;
-               value  = ((cpustate->program->read_data8((address + 0) & mask)) << 0);
-               value |= ((cpustate->program->read_data8((address + 1) & mask)) << 8);
-               //value = (READ8( cpustate, address+0 ) << 0);
-               //value |= (READ8( cpustate, address+1 ) << 8);
+               if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_READ,2,&address,&error)) {
+               //      PF_THROW(error);
+                       value = (READ8( cpustate, address+0 ) << 0);
+                       value |= (READ8( cpustate, address+1 ) << 8);
+               } else {
+                       UINT32 mask = cpustate->a20_mask;
+                       value  = ((cpustate->program->read_data8((address + 0) & mask)) << 0);
+                       value |= ((cpustate->program->read_data8((address + 1) & mask)) << 8);
+               }
        } else {
                if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address,&error))
                        PF_THROW(error);
@@ -1086,17 +1128,23 @@ INLINE UINT32 READ32(i386_state *cpustate,UINT32 ea)
        UINT32 address = ea, error;
 
        if( !DWORD_ALIGNED(ea) ) {        /* Unaligned read */
-               if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_READ,4,&address,&error))
-                       PF_THROW(error);
-               UINT32 mask = cpustate->a20_mask;
-               value  = ((cpustate->program->read_data8((address + 0) & mask)) << 0);
-               value |= ((cpustate->program->read_data8((address + 1) & mask)) << 8);
-               value |= ((cpustate->program->read_data8((address + 2) & mask)) << 16);
-               value |= ((cpustate->program->read_data8((address + 3) & mask)) << 24);
-               //value = (READ8( cpustate, address+0 ) << 0);
-               //value |= (READ8( cpustate, address+1 ) << 8);
-               //value |= (READ8( cpustate, address+2 ) << 16),
-               //value |= (READ8( cpustate, address+3 ) << 24);
+               if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_READ,4,&address,&error)) {
+                       value  = (READ8( cpustate, address+0 ) << 0);
+                       value |= (READ8( cpustate, address+1 ) << 8);
+                       value |= (READ8( cpustate, address+2 ) << 16);
+                       value |= (READ8( cpustate, address+3 ) << 24);
+               } else {
+                       UINT32 mask = cpustate->a20_mask;
+                       if(WORD_ALIGNED(ea)) {
+                               value  = ((cpustate->program->read_data16((address + 0) & mask)) << 0);
+                               value |= ((cpustate->program->read_data16((address + 2) & mask)) << 16);
+                       } else {
+                               value  = ((cpustate->program->read_data8((address + 0) & mask)) << 0);
+                               value |= ((cpustate->program->read_data8((address + 1) & mask)) << 8);
+                               value |= ((cpustate->program->read_data8((address + 2) & mask)) << 16);
+                               value |= ((cpustate->program->read_data8((address + 3) & mask)) << 24);
+                       }
+               }
        } else {
                if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address,&error))
                        PF_THROW(error);
@@ -1113,30 +1161,39 @@ INLINE UINT64 READ64(i386_state *cpustate,UINT32 ea)
        UINT32 address = ea, error;
 
        if( !QWORD_ALIGNED(ea) ) {        /* Unaligned read */
-               if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_READ,8,&address,&error))
-                       PF_THROW(error);
-               UINT32 mask = cpustate->a20_mask;
-               if(!DWORD_ALIGNED(ea)) {
-                       value  = (((UINT64)cpustate->program->read_data8((address + 0) & mask)) << 0);
-                       value |= (((UINT64)cpustate->program->read_data8((address + 1) & mask)) << 8);
-                       value |= (((UINT64)cpustate->program->read_data8((address + 2) & mask)) << 16);
-                       value |= (((UINT64)cpustate->program->read_data8((address + 3) & mask)) << 24);
-                       value |= (((UINT64)cpustate->program->read_data8((address + 4) & mask)) << 32);
-                       value |= (((UINT64)cpustate->program->read_data8((address + 5) & mask)) << 40);
-                       value |= (((UINT64)cpustate->program->read_data8((address + 6) & mask)) << 48);
-                       value |= (((UINT64)cpustate->program->read_data8((address + 7) & mask)) << 56);
-               } else { // Align of 4
-                       value = (((UINT64) cpustate->program->read_data32( (address+0) & mask )) << 0);
-                       value |= (((UINT64) cpustate->program->read_data32( (address+4) & mask )) << 32);
-               }                       
-//             value = (((UINT64) READ8( cpustate, address+0 )) << 0);
-//             value |= (((UINT64) READ8( cpustate, address+1 )) << 8);
-//             value |= (((UINT64) READ8( cpustate, address+2 )) << 16);
-//             value |= (((UINT64) READ8( cpustate, address+3 )) << 24);
-//             value |= (((UINT64) READ8( cpustate, address+4 )) << 32);
-//             value |= (((UINT64) READ8( cpustate, address+5 )) << 40);
-//             value |= (((UINT64) READ8( cpustate, address+6 )) << 48);
-//             value |= (((UINT64) READ8( cpustate, address+7 )) << 56);
+               if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_READ,8,&address,&error)) {
+                       value = (((UINT64) READ8( cpustate, address+0 )) << 0);
+                       value |= (((UINT64) READ8( cpustate, address+1 )) << 8);
+                       value |= (((UINT64) READ8( cpustate, address+2 )) << 16);
+                       value |= (((UINT64) READ8( cpustate, address+3 )) << 24);
+                       value |= (((UINT64) READ8( cpustate, address+4 )) << 32);
+                       value |= (((UINT64) READ8( cpustate, address+5 )) << 40);
+                       value |= (((UINT64) READ8( cpustate, address+6 )) << 48);
+                       value |= (((UINT64) READ8( cpustate, address+7 )) << 56);
+               } else {
+                       //      PF_THROW(error);
+                       UINT32 mask = cpustate->a20_mask;
+                       if(!DWORD_ALIGNED(ea)) {
+                               if(WORD_ALIGNED(ea)) { // Aligned by 2
+                                       value  = (((UINT64)cpustate->program->read_data16((address + 0) & mask)) << 0);
+                                       value |= (((UINT64)cpustate->program->read_data16((address + 2) & mask)) << 16);
+                                       value |= (((UINT64)cpustate->program->read_data16((address + 4) & mask)) << 32);
+                                       value |= (((UINT64)cpustate->program->read_data16((address + 6) & mask)) << 48);
+                               } else { // never aligned
+                                       value  = (((UINT64)cpustate->program->read_data8((address + 0) & mask)) << 0);
+                                       value |= (((UINT64)cpustate->program->read_data8((address + 1) & mask)) << 8);
+                                       value |= (((UINT64)cpustate->program->read_data8((address + 2) & mask)) << 16);
+                                       value |= (((UINT64)cpustate->program->read_data8((address + 3) & mask)) << 24);
+                                       value |= (((UINT64)cpustate->program->read_data8((address + 4) & mask)) << 32);
+                                       value |= (((UINT64)cpustate->program->read_data8((address + 5) & mask)) << 40);
+                                       value |= (((UINT64)cpustate->program->read_data8((address + 6) & mask)) << 48);
+                                       value |= (((UINT64)cpustate->program->read_data8((address + 7) & mask)) << 56);
+                               }
+                       } else { // Align of 4
+                               value = (((UINT64) cpustate->program->read_data32( (address+0) & mask )) << 0);
+                               value |= (((UINT64) cpustate->program->read_data32( (address+4) & mask )) << 32);
+                       }
+               }
        } else {
                if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address,&error))
                        PF_THROW(error);
@@ -1164,10 +1221,13 @@ INLINE UINT16 READ16PL0(i386_state *cpustate,UINT32 ea)
 
        if( !WORD_ALIGNED(ea) ) {        /* Unaligned read */
                UINT32 mask = cpustate->a20_mask;
-               if(!translate_address_with_width(cpustate,0,TRANSLATE_READ,2,&address,&error))
-                       PF_THROW(error);
-               value  = cpustate->program->read_data8((address + 0) & mask);
-               value |= (cpustate->program->read_data8((address + 1) & mask) << 8);
+               if(!translate_address_with_width(cpustate,0,TRANSLATE_READ,2,&address,&error)) {
+                       value  =  READ8PL0(cpustate, ea + 0);
+                       value |= (READ8PL0(cpustate, ea + 1) << 8);
+               } else {                        
+                       value  = cpustate->program->read_data8((address + 0) & mask);
+                       value |= (cpustate->program->read_data8((address + 1) & mask) << 8);
+               }
        } else {
                if(!translate_address(cpustate,0,TRANSLATE_READ,&address,&error))
                        PF_THROW(error);
@@ -1185,12 +1245,22 @@ INLINE UINT32 READ32PL0(i386_state *cpustate,UINT32 ea)
 
        if( !DWORD_ALIGNED(ea) ) {        /* Unaligned read */
                UINT32 mask = cpustate->a20_mask;
-               if(!translate_address_with_width(cpustate,0,TRANSLATE_READ,4,&address,&error))
-                       PF_THROW(error);
-               value  = cpustate->program->read_data8((address + 0) & mask);
-               value |= (cpustate->program->read_data8((address + 1) & mask) << 8);
-               value |= (cpustate->program->read_data8((address + 2) & mask) << 16);
-               value |= (cpustate->program->read_data8((address + 3) & mask) << 24);
+               if(!translate_address_with_width(cpustate,0,TRANSLATE_READ,4,&address,&error)) {
+                       value  =  READ8PL0(cpustate, ea + 0);
+                       value |= (READ8PL0(cpustate, ea + 1) << 8);
+                       value |= (READ8PL0(cpustate, ea + 2) << 16);
+                       value |= (READ8PL0(cpustate, ea + 3) << 24);
+               } else {
+                       if(WORD_ALIGNED(ea)) {
+                               value  = cpustate->program->read_data16((address + 0) & mask);
+                               value |= (cpustate->program->read_data16((address + 2) & mask) << 16);
+                       } else {
+                               value  = cpustate->program->read_data8((address + 0) & mask);
+                               value |= (cpustate->program->read_data8((address + 1) & mask) << 8);
+                               value |= (cpustate->program->read_data8((address + 2) & mask) << 16);
+                               value |= (cpustate->program->read_data8((address + 3) & mask) << 24);
+                       }
+               }
        } else {
                if(!translate_address(cpustate,0,TRANSLATE_READ,&address,&error))
                        PF_THROW(error);
@@ -1223,8 +1293,14 @@ INLINE void WRITE16(i386_state *cpustate,UINT32 ea, UINT16 value)
        UINT32 address = ea, error;
 
        if( !WORD_ALIGNED(ea) ) {        /* Unaligned write */
-               WRITE8( cpustate, address+0, value & 0xff );
-               WRITE8( cpustate, address+1, (value >> 8) & 0xff );
+               if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_WRITE,2,&address,&error)) {
+                       WRITE8( cpustate, address+0, value & 0xff );
+                       WRITE8( cpustate, address+1, (value >> 8) & 0xff );
+               } else {
+                       uint32_t mask = cpustate->a20_mask;
+                       cpustate->program->write_data8((address + 0) & mask, value & 0xff);
+                       cpustate->program->write_data8((address + 1) & mask, (value >> 8) & 0xff);
+               }
        } else {
                if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
                        PF_THROW(error);
@@ -1238,10 +1314,23 @@ INLINE void WRITE32(i386_state *cpustate,UINT32 ea, UINT32 value)
        UINT32 address = ea, error;
 
        if( !DWORD_ALIGNED(ea) ) {        /* Unaligned write */
-               WRITE8( cpustate, address+0, value & 0xff );
-               WRITE8( cpustate, address+1, (value >> 8) & 0xff );
-               WRITE8( cpustate, address+2, (value >> 16) & 0xff );
-               WRITE8( cpustate, address+3, (value >> 24) & 0xff );
+               if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_WRITE,4,&address,&error)) {
+                       WRITE8( cpustate, address+0, value & 0xff );
+                       WRITE8( cpustate, address+1, (value >> 8) & 0xff );
+                       WRITE8( cpustate, address+2, (value >> 16) & 0xff );
+                       WRITE8( cpustate, address+3, (value >> 24) & 0xff );
+               } else {
+                       uint32_t mask = cpustate->a20_mask;
+                       if(!WORD_ALIGNED(ea)) {
+                               cpustate->program->write_data8((address + 0) & mask, value & 0xff);
+                               cpustate->program->write_data8((address + 1) & mask, (value >> 8) & 0xff);
+                               cpustate->program->write_data8((address + 2) & mask, (value >> 16) & 0xff);
+                               cpustate->program->write_data8((address + 3) & mask, (value >> 24) & 0xff);
+                       } else { // Aligned by 2
+                               cpustate->program->write_data16((address + 0) & mask, value & 0xffff);
+                               cpustate->program->write_data16((address + 2) & mask, (value >> 16) & 0xffff);
+                       }
+               }
        } else {
                if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
                        PF_THROW(error);
@@ -1256,14 +1345,36 @@ INLINE void WRITE64(i386_state *cpustate,UINT32 ea, UINT64 value)
        UINT32 address = ea, error;
 
        if( !QWORD_ALIGNED(ea) ) {        /* Unaligned write */
-               WRITE8( cpustate, address+0, value & 0xff );
-               WRITE8( cpustate, address+1, (value >> 8) & 0xff );
-               WRITE8( cpustate, address+2, (value >> 16) & 0xff );
-               WRITE8( cpustate, address+3, (value >> 24) & 0xff );
-               WRITE8( cpustate, address+4, (value >> 32) & 0xff );
-               WRITE8( cpustate, address+5, (value >> 40) & 0xff );
-               WRITE8( cpustate, address+6, (value >> 48) & 0xff );
-               WRITE8( cpustate, address+7, (value >> 56) & 0xff );
+               if(!translate_address_with_width(cpustate,cpustate->CPL,TRANSLATE_WRITE,8,&address,&error)) {
+                       WRITE8( cpustate, address+0, value & 0xff );
+                       WRITE8( cpustate, address+1, (value >> 8) & 0xff );
+                       WRITE8( cpustate, address+2, (value >> 16) & 0xff );
+                       WRITE8( cpustate, address+3, (value >> 24) & 0xff );
+                       WRITE8( cpustate, address+4, (value >> 32) & 0xff );
+                       WRITE8( cpustate, address+5, (value >> 40) & 0xff );
+                       WRITE8( cpustate, address+6, (value >> 48) & 0xff );
+                       WRITE8( cpustate, address+7, (value >> 56) & 0xff );
+               } else {
+                       uint32_t mask = cpustate->a20_mask;
+                       if(DWORD_ALIGNED(ea)) { // Aligned by 4
+                               cpustate->program->write_data32((address + 0) & mask, value & 0xffffffff);
+                               cpustate->program->write_data32((address + 4) & mask, (value >> 32) & 0xffffffff);
+                       } else if(!WORD_ALIGNED(ea)) { // Never aligned
+                               cpustate->program->write_data8((address + 0) & mask, value & 0xff);
+                               cpustate->program->write_data8((address + 1) & mask, (value >> 8) & 0xff);
+                               cpustate->program->write_data8((address + 2) & mask, (value >> 16) & 0xff);
+                               cpustate->program->write_data8((address + 3) & mask, (value >> 24) & 0xff);
+                               cpustate->program->write_data8((address + 4) & mask, (value >> 32) & 0xff);
+                               cpustate->program->write_data8((address + 5) & mask, (value >> 40) & 0xff);
+                               cpustate->program->write_data8((address + 6) & mask, (value >> 48) & 0xff);
+                               cpustate->program->write_data8((address + 7) & mask, (value >> 56) & 0xff);
+                       } else { // Aligned by 2
+                               cpustate->program->write_data16((address + 0) & mask, value & 0xffff);
+                               cpustate->program->write_data16((address + 2) & mask, (value >> 16) & 0xffff);
+                               cpustate->program->write_data16((address + 4) & mask, (value >> 32) & 0xffff);
+                               cpustate->program->write_data16((address + 6) & mask, (value >> 48) & 0xffff);
+                       }
+               }
        } else {
                if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
                        PF_THROW(error);
index aaace54..f2ac081 100644 (file)
@@ -582,7 +582,7 @@ void UPD7220::write_io8(uint32_t addr, uint32_t data)
 {
        switch(addr & 3) {
        case 0: // set parameter
-               this->out_debug_log(_T("\tPARAM = %2x\n"), data);
+               //this->out_debug_log(_T("\tPARAM = %2x\n"), data);
                //if(cmd_ready) { // OK?
                if(cmdreg != -1) {
                        cmd_fifo->write(data & 0xff);
@@ -605,7 +605,7 @@ void UPD7220::write_io8(uint32_t addr, uint32_t data)
                vectw_ptr = 0;
                csrw_ptr = 0;
                cmdreg = (int)data & 0xff;
-               this->out_debug_log(_T("CMDREG = %2x\n"), cmdreg);
+               //this->out_debug_log(_T("CMDREG = %2x\n"), cmdreg);
 //             params_count = 0;
                cmd_fifo->clear(); // OK?
                check_cmd();
@@ -1252,7 +1252,7 @@ void UPD7220::draw_vectl()
 {
        pattern = ra[8] | (ra[9] << 8);
        
-       out_debug_log(_T("DRAW VECTL: X=%d Y=%d to DC=%d DIR=%d PATTERN=%04x MODE=%d\n"), dx, dy, dc, dir, pattern, mod); 
+       //out_debug_log(_T("DRAW VECTL: X=%d Y=%d to DC=%d DIR=%d PATTERN=%04x MODE=%d\n"), dx, dy, dc, dir, pattern, mod); 
        if(dc) {
                int x = dx;
                int y = dy;