OSDN Git Service

[VM][DEVICE][I386] Add bios_call_far_ia32() and bios_int_ia32() because BIOS calling...
[csp-qt/common_source_project-fm7.git] / source / src / vm / i386.cpp
1 /*
2         Skelton for retropc emulator
3
4         Origin : MAME i386 core
5         Author : Takeda.Toshiya
6         Date  : 2009.06.08-
7
8         [ i386/i486/Pentium/MediaGX ]
9 */
10
11 #include "i386.h"
12 //#ifdef USE_DEBUGGER
13 #include "debugger.h"
14 //#endif
15
16 /* ----------------------------------------------------------------------------
17         MAME i386
18 ---------------------------------------------------------------------------- */
19 // Note:
20 // API of bios_int_i86() / bios_caii_i86() has changed.
21 // regs[8] regs[9] are added.These entries set redirect-address by PSEUDO-BIOS.
22 // If need, will add more entries for cycle#.
23 // - 20181126 K.O
24
25 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
26 #pragma warning( disable : 4018 )
27 #pragma warning( disable : 4065 )
28 #pragma warning( disable : 4146 )
29 #pragma warning( disable : 4244 )
30 #pragma warning( disable : 4996 )
31 #endif
32
33 #if 0
34 #if defined(HAS_I386)
35         #define CPU_MODEL i386
36 #elif defined(HAS_I486)
37         #define CPU_MODEL i486
38 #elif defined(HAS_PENTIUM)
39         #define CPU_MODEL pentium
40 #elif defined(HAS_MEDIAGX)
41         #define CPU_MODEL mediagx
42 #elif defined(HAS_PENTIUM_PRO)
43         #define CPU_MODEL pentium_pro
44 #elif defined(HAS_PENTIUM_MMX)
45         #define CPU_MODEL pentium_mmx
46 #elif defined(HAS_PENTIUM2)
47         #define CPU_MODEL pentium2
48 #elif defined(HAS_PENTIUM3)
49         #define CPU_MODEL pentium3
50 #elif defined(HAS_PENTIUM4)
51         #define CPU_MODEL pentium4
52 #endif
53 #endif
54
55 #ifndef __BIG_ENDIAN__
56 #define LSB_FIRST
57 #endif
58
59 #ifndef INLINE
60 #define INLINE inline
61 #endif
62
63 #define U64(v) UINT64(v)
64
65 #define fatalerror(...) exit(1)
66
67 #define logdebug(...)                                           \
68         { \
69           if(cpustate != NULL) {                                                                          \
70                   if(cpustate->parent_device != NULL) {                                                 \
71                           cpustate->parent_device->out_debug_log(__VA_ARGS__); \
72                   }                                                                                                                             \
73           }                                                                                                                                     \
74         }
75
76 #define loginfo(...)                                            \
77         { \
78           if(cpustate != NULL) {                                                                          \
79                   if(cpustate->parent_device != NULL) {                                                 \
80                           cpustate->parent_device->out_debug_log(__VA_ARGS__); \
81                   }                                                                                                                             \
82           }                                                                                                                                     \
83         }
84
85 #if 0
86 #define logerror(...)
87 #else
88
89 #define logerror(...)                                           \
90         { \
91           if(cpustate != NULL) {                                                                          \
92                   if(cpustate->parent_device != NULL) {                                                 \
93                           cpustate->parent_device->out_debug_log(__VA_ARGS__); \
94                   }                                                                                                                             \
95           }                                                                                                                                     \
96         }
97
98 #endif
99 #define popmessage(...)
100
101 /*****************************************************************************/
102 /* src/emu/devcpu.h */
103
104 // CPU interface functions
105 #define CPU_INIT_NAME(name)                     cpu_init_##name
106 #define CPU_INIT(name)                          void* CPU_INIT_NAME(name)()
107 #define CPU_INIT_CALL(name)                     CPU_INIT_NAME(name)()
108
109 #define CPU_RESET_NAME(name)                    cpu_reset_##name
110 #define CPU_RESET(name)                         void CPU_RESET_NAME(name)(i386_state *cpustate)
111 #define CPU_RESET_CALL(name)                    CPU_RESET_NAME(name)(cpustate)
112
113 #define CPU_EXECUTE_NAME(name)                  cpu_execute_##name
114 #define CPU_EXECUTE(name)                       int CPU_EXECUTE_NAME(name)(i386_state *cpustate, int cycles)
115 #define CPU_EXECUTE_CALL(name)                  CPU_EXECUTE_NAME(name)(cpustate, cycles)
116
117 #define CPU_TRANSLATE_NAME(name)                cpu_translate_##name
118 #define CPU_TRANSLATE(name)                     int CPU_TRANSLATE_NAME(name)(void *cpudevice, address_spacenum space, int intention, offs_t *address)
119 #define CPU_TRANSLATE_CALL(name)                CPU_TRANSLATE_NAME(name)(cpudevice, space, intention, address)
120
121 #define CPU_DISASSEMBLE_NAME(name)              cpu_disassemble_##name
122 #define CPU_DISASSEMBLE(name)                   int CPU_DISASSEMBLE_NAME(name)(_TCHAR *buffer, offs_t eip, const UINT8 *oprom)
123 #define CPU_DISASSEMBLE_CALL(name)              CPU_DISASSEMBLE_NAME(name)(buffer, eip, oprom)
124
125 /*****************************************************************************/
126 /* src/emu/didisasm.h */
127
128 // Disassembler constants
129 const UINT32 DASMFLAG_SUPPORTED     = 0x80000000;   // are disassembly flags supported?
130 const UINT32 DASMFLAG_STEP_OUT      = 0x40000000;   // this instruction should be the end of a step out sequence
131 const UINT32 DASMFLAG_STEP_OVER     = 0x20000000;   // this instruction should be stepped over by setting a breakpoint afterwards
132 const UINT32 DASMFLAG_OVERINSTMASK  = 0x18000000;   // number of extra instructions to skip when stepping over
133 const UINT32 DASMFLAG_OVERINSTSHIFT = 27;           // bits to shift after masking to get the value
134 const UINT32 DASMFLAG_LENGTHMASK    = 0x0000ffff;   // the low 16-bits contain the actual length
135
136 /*****************************************************************************/
137 /* src/emu/diexec.h */
138
139 // I/O line states
140 enum line_state
141 {
142         CLEAR_LINE = 0,                         // clear (a fired or held) line
143         ASSERT_LINE,                            // assert an interrupt immediately
144         HOLD_LINE,                              // hold interrupt line until acknowledged
145         PULSE_LINE                              // pulse interrupt line instantaneously (only for NMI, RESET)
146 };
147
148 enum
149 {
150         INPUT_LINE_IRQ = 0,
151         INPUT_LINE_NMI
152 };
153
154 /*****************************************************************************/
155 /* src/emu/dimemory.h */
156
157 // Translation intentions
158 const int TRANSLATE_TYPE_MASK       = 0x03;     // read write or fetch
159 const int TRANSLATE_USER_MASK       = 0x04;     // user mode or fully privileged
160 const int TRANSLATE_DEBUG_MASK      = 0x08;     // debug mode (no side effects)
161
162 const int TRANSLATE_READ            = 0;        // translate for read
163 const int TRANSLATE_WRITE           = 1;        // translate for write
164 const int TRANSLATE_FETCH           = 2;        // translate for instruction fetch
165 const int TRANSLATE_READ_USER       = (TRANSLATE_READ | TRANSLATE_USER_MASK);
166 const int TRANSLATE_WRITE_USER      = (TRANSLATE_WRITE | TRANSLATE_USER_MASK);
167 const int TRANSLATE_FETCH_USER      = (TRANSLATE_FETCH | TRANSLATE_USER_MASK);
168 const int TRANSLATE_READ_DEBUG      = (TRANSLATE_READ | TRANSLATE_DEBUG_MASK);
169 const int TRANSLATE_WRITE_DEBUG     = (TRANSLATE_WRITE | TRANSLATE_DEBUG_MASK);
170 const int TRANSLATE_FETCH_DEBUG     = (TRANSLATE_FETCH | TRANSLATE_DEBUG_MASK);
171
172 /*****************************************************************************/
173 /* src/emu/emucore.h */
174
175 // constants for expression endianness
176 enum endianness_t
177 {
178         ENDIANNESS_LITTLE,
179         ENDIANNESS_BIG
180 };
181
182 // declare native endianness to be one or the other
183 #ifdef LSB_FIRST
184 const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_LITTLE;
185 #else
186 const endianness_t ENDIANNESS_NATIVE = ENDIANNESS_BIG;
187 #endif
188 // endian-based value: first value is if 'endian' is little-endian, second is if 'endian' is big-endian
189 #define ENDIAN_VALUE_LE_BE(endian,leval,beval)  (((endian) == ENDIANNESS_LITTLE) ? (leval) : (beval))
190 // endian-based value: first value is if native endianness is little-endian, second is if native is big-endian
191 #define NATIVE_ENDIAN_VALUE_LE_BE(leval,beval)  ENDIAN_VALUE_LE_BE(ENDIANNESS_NATIVE, leval, beval)
192 // endian-based value: first value is if 'endian' matches native, second is if 'endian' doesn't match native
193 #define ENDIAN_VALUE_NE_NNE(endian,leval,beval) (((endian) == ENDIANNESS_NATIVE) ? (neval) : (nneval))
194
195 /*****************************************************************************/
196 /* src/emu/emumem.h */
197
198 // helpers for checking address alignment
199 #define WORD_ALIGNED(a)                 (((a) & 1) == 0)
200 #define DWORD_ALIGNED(a)                (((a) & 3) == 0)
201 #define QWORD_ALIGNED(a)                (((a) & 7) == 0)
202
203 /*****************************************************************************/
204 /* src/emu/memory.h */
205
206 // address spaces
207 enum address_spacenum
208 {
209         AS_0,                           // first address space
210         AS_1,                           // second address space
211         AS_2,                           // third address space
212         AS_3,                           // fourth address space
213         ADDRESS_SPACES,                 // maximum number of address spaces
214
215         // alternate address space names for common use
216         AS_PROGRAM = AS_0,              // program address space
217         AS_DATA = AS_1,                 // data address space
218         AS_IO = AS_2                    // I/O address space
219 };
220
221 // offsets and addresses are 32-bit (for now...)
222 typedef UINT32  offs_t;
223
224 /*****************************************************************************/
225 /* src/osd/osdcomm.h */
226
227 /* Highly useful macro for compile-time knowledge of an array size */
228 #define ARRAY_LENGTH(x)     (sizeof(x) / sizeof(x[0]))
229
230 //#ifdef I386_PSEUDO_BIOS
231 #define BIOS_INT(num) if(cpustate->bios != NULL) { \
232                 /*if(((cpustate->cr[0] & 0x0001) == 0) || (cpustate->VM != 0)) */{      /* VM8086 or Not Protected */ \
233                         uint16_t regs[10], sregs[4];                                                            \
234                         regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
235                         regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
236                         regs[8] = 0x0000; regs[9] = 0x0000;                                                     \
237                         sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
238                         sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
239                         int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF;      \
240 if(cpustate->bios->bios_int_i86(num, regs, sregs, &ZeroFlag, &CarryFlag, &(cpustate->cycles), &(cpustate->total_cycles))) { \
241                                 REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
242                                 REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
243                                 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
244                                 CYCLES(cpustate,CYCLES_IRET);                                                   \
245                                 if((regs[8] != 0x0000) || (regs[9] != 0x0000)) {                \
246                                         uint32_t hi = regs[9];                                                          \
247                                         uint32_t lo = regs[8];                                                          \
248                                         uint32_t addr = (hi << 16) | lo;                                        \
249                                         cpustate->eip = addr;                                                           \
250                                 }                                                                                                               \
251                                 return;                                                                                                 \
252                         }                                                                                                                       \
253                 }                                                                                                                               \
254         }
255
256 #define BIOS_INT32(num) if(cpustate->bios != NULL) { \
257                 /*if(((cpustate->cr[0] & 0x0001) == 0) || (cpustate->VM != 0)) */{      /* VM8086 or Not Protected */ \
258                         uint32_t regs[10];                                                                                      \
259                         uint16_t sregs[4];                                                                                              \
260                         regs[0] = REG32(EAX); regs[1] = REG32(ECX); regs[2] = REG32(EDX); regs[3] = REG32(EBX); \
261                         regs[4] = REG32(ESP); regs[5] = REG32(EBP); regs[6] = REG32(ESI); regs[7] = REG32(EDI); \
262                         regs[8] = 0x0000; regs[9] = 0x0000;                                                     \
263                         sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
264                         sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
265                         int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF;      \
266 if(cpustate->bios->bios_int_ia32(num, regs, sregs, &ZeroFlag, &CarryFlag, &(cpustate->cycles), &(cpustate->total_cycles))) { \
267                                 REG32(EAX) = regs[0]; REG32(ECX) = regs[1]; REG32(EDX) = regs[2]; REG32(EBX) = regs[3]; \
268                                 REG32(ESP) = regs[4]; REG32(EBP) = regs[5]; REG32(ESI) = regs[6]; REG32(EDI) = regs[7]; \
269                                 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
270                                 CYCLES(cpustate,CYCLES_IRET);                                                   \
271                                 if((regs[8] != 0x0000) || (regs[9] != 0x0000)) {                \
272                                         uint32_t hi = regs[9];                                                          \
273                                         uint32_t lo = regs[8];                                                          \
274                                         uint32_t addr = (hi << 16) | lo;                                        \
275                                         cpustate->eip = addr;                                                           \
276                                 }                                                                                                               \
277                                 return;                                                                                                 \
278                         }                                                                                                                       \
279                 }                                                                                                                               \
280         }
281
282 #define BIOS_CALL_FAR(address) if(cpustate->bios != NULL) {                             \
283                 if(((cpustate->cr[0] & 0x0001) == 0) || (cpustate->VM != 0)) {  /* VM8086 or Not Protected */ \
284                         uint16_t regs[10], sregs[4];                                                            \
285                         regs[0] = REG16(AX); regs[1] = REG16(CX); regs[2] = REG16(DX); regs[3] = REG16(BX); \
286                         regs[4] = REG16(SP); regs[5] = REG16(BP); regs[6] = REG16(SI); regs[7] = REG16(DI); \
287                         regs[8] = 0x0000; regs[9] = 0x0000;                                                     \
288                         sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
289                         sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
290                         int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF;      \
291                         if(cpustate->bios->bios_call_far_i86(address, regs, sregs, &ZeroFlag, &CarryFlag, &(cpustate->cycles), &(cpustate->total_cycles))) { \
292                                 REG16(AX) = regs[0]; REG16(CX) = regs[1]; REG16(DX) = regs[2]; REG16(BX) = regs[3]; \
293                                 REG16(SP) = regs[4]; REG16(BP) = regs[5]; REG16(SI) = regs[6]; REG16(DI) = regs[7]; \
294                                 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
295                                 CYCLES(cpustate,CYCLES_RET_INTERSEG);                                   \
296                                 if((regs[8] != 0x0000) || (regs[9] != 0x0000)) {                \
297                                         uint32_t hi = regs[9];                                                          \
298                                         uint32_t lo = regs[8];                                                          \
299                                         uint32_t addr = (hi << 16) | lo;                                        \
300                                         cpustate->eip = addr;                                                           \
301                                 }                                                                                                               \
302                                 return;                                                                                                 \
303                         }                                                                                                                       \
304                 }                                                                                                                               \
305         }
306
307 #define BIOS_CALL_FAR32(address) if(cpustate->bios != NULL) {                           \
308                 if(((cpustate->cr[0] & 0x0001) == 0) || (cpustate->VM != 0)) {  /* VM8086 or Not Protected */ \
309                         uint32_t regs[10];                                                                                      \
310                         uint16_t sregs[4];                                                                                                      \
311                         regs[0] = REG32(EAX); regs[1] = REG32(ECX); regs[2] = REG32(EDX); regs[3] = REG32(EBX); \
312                         regs[4] = REG32(ESP); regs[5] = REG32(EBP); regs[6] = REG32(ESI); regs[7] = REG32(EDI); \
313                         regs[8] = 0x0000; regs[9] = 0x0000;                                                     \
314                         sregs[0] = cpustate->sreg[ES].selector; sregs[1] = cpustate->sreg[CS].selector; \
315                         sregs[2] = cpustate->sreg[SS].selector; sregs[3] = cpustate->sreg[DS].selector; \
316                         int32_t ZeroFlag = cpustate->ZF, CarryFlag = cpustate->CF;      \
317                         if(cpustate->bios->bios_call_far_ia32(address, regs, sregs, &ZeroFlag, &CarryFlag, &(cpustate->cycles), &(cpustate->total_cycles))) { \
318                                 REG32(EAX) = regs[0]; REG32(ECX) = regs[1]; REG32(EDX) = regs[2]; REG32(EBX) = regs[3]; \
319                                 REG32(ESP) = regs[4]; REG32(EBP) = regs[5]; REG32(ESI) = regs[6]; REG32(EDI) = regs[7]; \
320                                 cpustate->ZF = (UINT8)ZeroFlag; cpustate->CF = (UINT8)CarryFlag; \
321                                 CYCLES(cpustate,CYCLES_RET_INTERSEG);                                   \
322                                 if((regs[8] != 0x0000) || (regs[9] != 0x0000)) {                \
323                                         uint32_t hi = regs[9];                                                          \
324                                         uint32_t lo = regs[8];                                                          \
325                                         uint32_t addr = (hi << 16) | lo;                                        \
326                                         cpustate->eip = addr;                                                           \
327                                 }                                                                                                               \
328                                 return;                                                                                                 \
329                         }                                                                                                                       \
330                 }                                                                                                                               \
331         }
332
333 //#endif
334
335 static CPU_TRANSLATE(i386);
336 void terminate()
337 {
338         printf("WARN: unexpected exception\n");
339 }
340
341 #include "mame/lib/softfloat/softfloat.c"
342 #include "mame/lib/softfloat/fsincos.c"
343 #include "mame/emu/cpu/vtlb.c"
344 #include "mame/emu/cpu/i386/i386.c"
345 //#ifdef USE_DEBUGGER
346 #include "mame/emu/cpu/i386/i386dasm.c"
347 //#endif
348
349 void I386::initialize()
350 {
351         DEVICE::initialize();
352         uint32_t n_cpu_type = N_CPU_TYPE_I386;
353         if(osd->check_feature("HAS_I386")) {
354                 n_cpu_type = N_CPU_TYPE_I386;
355         } else if(osd->check_feature("HAS_I486")) {
356                 n_cpu_type = N_CPU_TYPE_I486;
357         } else if(osd->check_feature("HAS_PENTIUM")) {
358                 n_cpu_type = N_CPU_TYPE_PENTIUM;
359         } else if(osd->check_feature("HAS_MEDIAGX")) {
360                 n_cpu_type = N_CPU_TYPE_MEDIAGX;
361         } else if(osd->check_feature("HAS_PENTIUM_PRO")) {
362                 n_cpu_type = N_CPU_TYPE_PENTIUM_PRO;
363         } else if(osd->check_feature("HAS_PENTIUM_MMX")) {
364                 n_cpu_type = N_CPU_TYPE_PENTIUM_MMX;
365         } else if(osd->check_feature("HAS_PENTIUM2")) {
366                 n_cpu_type = N_CPU_TYPE_PENTIUM2;
367         } else if(osd->check_feature("HAS_PENTIUM3")) {
368                 n_cpu_type = N_CPU_TYPE_PENTIUM3;
369         } else if(osd->check_feature("HAS_PENTIUM4")) {
370                 n_cpu_type = N_CPU_TYPE_PENTIUM4;
371         }
372         switch(n_cpu_type) {
373         case N_CPU_TYPE_I386:
374                 set_device_name(_T("i80386 CPU"));
375                 opaque = CPU_INIT_CALL( i386 );
376                 break;
377         case N_CPU_TYPE_I486:
378                 set_device_name(_T("i80486 CPU"));
379                 opaque = CPU_INIT_CALL( i486 );
380                 break;
381         case N_CPU_TYPE_PENTIUM:
382                 set_device_name(_T("Pentium CPU"));
383                 opaque = CPU_INIT_CALL( pentium );
384                 break;
385         case N_CPU_TYPE_MEDIAGX:
386                 set_device_name(_T("Media GX CPU"));
387                 opaque = CPU_INIT_CALL( mediagx );
388                 break;
389         case N_CPU_TYPE_PENTIUM_PRO:
390                 set_device_name(_T("Pentium PRO CPU"));
391                 opaque = CPU_INIT_CALL( pentium_pro );
392                 break;
393         case N_CPU_TYPE_PENTIUM_MMX:
394                 set_device_name(_T("Pentium MMX CPU"));
395                 opaque = CPU_INIT_CALL( pentium_mmx );
396                 break;
397         case N_CPU_TYPE_PENTIUM2:
398                 set_device_name(_T("Pentium2 CPU"));
399                 opaque = CPU_INIT_CALL( pentium2 );
400                 break;
401         case N_CPU_TYPE_PENTIUM3:
402                 set_device_name(_T("Pentium3 CPU"));
403                 opaque = CPU_INIT_CALL( pentium3 );
404                 break;
405         case N_CPU_TYPE_PENTIUM4:
406                 set_device_name(_T("Pentium4 CPU"));
407                 opaque = CPU_INIT_CALL( pentium4 );
408                 break;
409         default: // ???
410                 set_device_name(_T("i80386 CPU"));
411                 opaque = CPU_INIT_CALL( i386 );
412                 break;
413         }
414         
415         i386_state *cpustate = (i386_state *)opaque;
416         cpustate->pic = d_pic;
417         cpustate->program = d_mem;
418         cpustate->io = d_io;
419 //#ifdef I386_PSEUDO_BIOS
420         cpustate->bios = d_bios;
421 //#endif
422 //#ifdef SINGLE_MODE_DMA
423         cpustate->dma = d_dma;
424 //#endif
425 //#ifdef USE_DEBUGGER
426         cpustate->emu = emu;
427         cpustate->debugger = d_debugger;
428         cpustate->program_stored = d_mem;
429         cpustate->io_stored = d_io;
430         
431         d_debugger->set_context_mem(d_mem);
432         d_debugger->set_context_io(d_io);
433 //#endif
434         cpustate->parent_device = this; // This aims to log.
435         cpustate->cpu_type = n_cpu_type; // check cpu type
436         cpustate->shutdown = 0;
437 }
438
439 void I386::release()
440 {
441         i386_state *cpustate = (i386_state *)opaque;
442         vtlb_free(cpustate->vtlb);
443         free(opaque);
444 }
445
446 void I386::reset()
447 {
448         i386_state *cpustate = (i386_state *)opaque;
449         logerror(_T("I386::reset()"));
450         cpu_reset_generic(cpustate);
451         write_signals(&outputs_extreset, 0xffffffff);
452 }
453
454 int I386::run(int cycles)
455 {
456         i386_state *cpustate = (i386_state *)opaque;
457         return CPU_EXECUTE_CALL(i386); // OK?
458 }
459
460 void I386::write_signal(int id, uint32_t data, uint32_t mask)
461 {
462         i386_state *cpustate = (i386_state *)opaque;
463         
464         if(id == SIG_CPU_NMI) {
465                 i386_set_irq_line(cpustate, INPUT_LINE_NMI, (data & mask) ? HOLD_LINE : CLEAR_LINE);
466         } else if(id == SIG_CPU_IRQ) {
467                 i386_set_irq_line(cpustate, INPUT_LINE_IRQ, (data & mask) ? HOLD_LINE : CLEAR_LINE);
468         } else if(id == SIG_CPU_BUSREQ) {
469                 cpustate->busreq = (data & mask) ? 1 : 0;
470         } else if(id == SIG_I386_A20) {
471                 i386_set_a20_line(cpustate, data & mask);
472         } else if(id == SIG_I386_NOTIFY_RESET) {
473                 write_signals(&outputs_extreset, ((data & mask == 0) ? 0x00000000 : 0xffffffff));
474         }
475 }
476
477 void I386::set_intr_line(bool line, bool pending, uint32_t bit)
478 {
479         i386_state *cpustate = (i386_state *)opaque;
480         i386_set_irq_line(cpustate, INPUT_LINE_IRQ, line ? HOLD_LINE : CLEAR_LINE);
481 }
482
483 void I386::set_extra_clock(int cycles)
484 {
485         i386_state *cpustate = (i386_state *)opaque;
486         cpustate->extra_cycles += cycles;
487 }
488
489 int I386::get_extra_clock()
490 {
491         i386_state *cpustate = (i386_state *)opaque;
492         return cpustate->extra_cycles;
493 }
494
495 uint32_t I386::get_pc()
496 {
497         i386_state *cpustate = (i386_state *)opaque;
498         return cpustate->prev_pc;
499 }
500
501 uint32_t I386::get_next_pc()
502 {
503         i386_state *cpustate = (i386_state *)opaque;
504         return cpustate->pc;
505 }
506
507 //#ifdef USE_DEBUGGER
508 void I386::write_debug_data8(uint32_t addr, uint32_t data)
509 {
510         int wait;
511         d_mem->write_data8w(addr, data, &wait);
512 }
513
514 uint32_t I386::translate_address(int segment, uint32_t offset)
515 {
516         i386_state *cpustate = (i386_state *)opaque;
517         uint32_t addr = 0;
518         if((segment >= 0) && (segment <= GS)) {
519                 addr = cpustate->sreg[segment].base + offset;
520                 // addr = (((uint32_t)(cpustate->sreg[segment].selector)) << 4) + offset;
521         }
522         return addr;
523 }
524
525 uint32_t I386::read_debug_data8(uint32_t addr)
526 {
527         int wait;
528         return d_mem->read_data8w(addr, &wait);
529 }
530
531 void I386::write_debug_data16(uint32_t addr, uint32_t data)
532 {
533         int wait;
534         d_mem->write_data16w(addr, data, &wait);
535 }
536
537 uint32_t I386::read_debug_data16(uint32_t addr)
538 {
539         int wait;
540         return d_mem->read_data16w(addr, &wait);
541 }
542
543 void I386::write_debug_data32(uint32_t addr, uint32_t data)
544 {
545         int wait;
546         d_mem->write_data32w(addr, data, &wait);
547 }
548
549 uint32_t I386::read_debug_data32(uint32_t addr)
550 {
551         int wait;
552         return d_mem->read_data32w(addr, &wait);
553 }
554
555 void I386::write_debug_io8(uint32_t addr, uint32_t data)
556 {
557         int wait;
558         d_io->write_io8w(addr, data, &wait);
559 }
560
561 uint32_t I386::read_debug_io8(uint32_t addr) {
562         int wait;
563         return d_io->read_io8w(addr, &wait);
564 }
565
566 void I386::write_debug_io16(uint32_t addr, uint32_t data)
567 {
568         int wait;
569         d_io->write_io16w(addr, data, &wait);
570 }
571
572 uint32_t I386::read_debug_io16(uint32_t addr) {
573         int wait;
574         return d_io->read_io16w(addr, &wait);
575 }
576
577 void I386::write_debug_io32(uint32_t addr, uint32_t data)
578 {
579         int wait;
580         d_io->write_io32w(addr, data, &wait);
581 }
582
583 uint32_t I386::read_debug_io32(uint32_t addr) {
584         int wait;
585         return d_io->read_io32w(addr, &wait);
586 }
587
588 bool I386::write_debug_reg(const _TCHAR *reg, uint32_t data)
589 {
590         i386_state *cpustate = (i386_state *)opaque;
591         if(_tcsicmp(reg, _T("IP")) == 0) {
592                 cpustate->eip = data & 0xffff;
593                 CHANGE_PC(cpustate, cpustate->eip);
594         } else if(_tcsicmp(reg, _T("EIP")) == 0) {
595                 cpustate->eip = data;
596                 CHANGE_PC(cpustate, cpustate->eip);
597         } else if(_tcsicmp(reg, _T("EAX")) == 0) {
598                 REG32(EAX) = data;
599         } else if(_tcsicmp(reg, _T("EBX")) == 0) {
600                 REG32(EBX) = data;
601         } else if(_tcsicmp(reg, _T("ECX")) == 0) {
602                 REG32(ECX) = data;
603         } else if(_tcsicmp(reg, _T("EDX")) == 0) {
604                 REG32(EDX) = data;
605         } else if(_tcsicmp(reg, _T("ESP")) == 0) {
606                 REG32(ESP) = data;
607         } else if(_tcsicmp(reg, _T("EBP")) == 0) {
608                 REG32(EBP) = data;
609         } else if(_tcsicmp(reg, _T("ESI")) == 0) {
610                 REG32(ESI) = data;
611         } else if(_tcsicmp(reg, _T("EDI")) == 0) {
612                 REG32(EDI) = data;
613         } else if(_tcsicmp(reg, _T("AX")) == 0) {
614                 REG16(AX) = data;
615         } else if(_tcsicmp(reg, _T("BX")) == 0) {
616                 REG16(BX) = data;
617         } else if(_tcsicmp(reg, _T("CX")) == 0) {
618                 REG16(CX) = data;
619         } else if(_tcsicmp(reg, _T("DX")) == 0) {
620                 REG16(DX) = data;
621         } else if(_tcsicmp(reg, _T("SP")) == 0) {
622                 REG16(SP) = data;
623         } else if(_tcsicmp(reg, _T("BP")) == 0) {
624                 REG16(BP) = data;
625         } else if(_tcsicmp(reg, _T("SI")) == 0) {
626                 REG16(SI) = data;
627         } else if(_tcsicmp(reg, _T("DI")) == 0) {
628                 REG16(DI) = data;
629         } else if(_tcsicmp(reg, _T("AL")) == 0) {
630                 REG8(AL) = data;
631         } else if(_tcsicmp(reg, _T("AH")) == 0) {
632                 REG8(AH) = data;
633         } else if(_tcsicmp(reg, _T("BL")) == 0) {
634                 REG8(BL) = data;
635         } else if(_tcsicmp(reg, _T("BH")) == 0) {
636                 REG8(BH) = data;
637         } else if(_tcsicmp(reg, _T("CL")) == 0) {
638                 REG8(CL) = data;
639         } else if(_tcsicmp(reg, _T("CH")) == 0) {
640                 REG8(CH) = data;
641         } else if(_tcsicmp(reg, _T("DL")) == 0) {
642                 REG8(DL) = data;
643         } else if(_tcsicmp(reg, _T("DH")) == 0) {
644                 REG8(DH) = data;
645         } else {
646                 return false;
647         }
648         return true;
649 }
650
651 uint32_t I386::read_debug_reg(const _TCHAR *reg)
652 {
653         i386_state *cpustate = (i386_state *)opaque;
654         if(_tcsicmp(reg, _T("EIP")) == 0) {
655                 return cpustate->eip;
656         } else if(_tcsicmp(reg, _T("IP")) == 0) {
657                 return cpustate->eip & 0xffff;
658         }  else if(_tcsicmp(reg, _T("EAX")) == 0) {
659                 return REG32(EAX);
660         } else if(_tcsicmp(reg, _T("EBX")) == 0) {
661                 return REG32(EBX);
662         } else if(_tcsicmp(reg, _T("ECX")) == 0) {
663                 return REG32(ECX);
664         } else if(_tcsicmp(reg, _T("EDX")) == 0) {
665                 return REG32(EDX);
666         } else if(_tcsicmp(reg, _T("ESP")) == 0) {
667                 return REG32(ESP);
668         } else if(_tcsicmp(reg, _T("EBP")) == 0) {
669                 return REG32(EBP);
670         } else if(_tcsicmp(reg, _T("ESI")) == 0) {
671                 return REG32(ESI);
672         } else if(_tcsicmp(reg, _T("EDI")) == 0) {
673                 return REG32(EDI);
674         } else if(_tcsicmp(reg, _T("AX")) == 0) {
675                 return REG16(AX);
676         } else if(_tcsicmp(reg, _T("BX")) == 0) {
677                 return REG16(BX);
678         } else if(_tcsicmp(reg, _T("CX")) == 0) {
679                 return REG16(CX);
680         } else if(_tcsicmp(reg, _T("DX")) == 0) {
681                 return REG16(DX);
682         } else if(_tcsicmp(reg, _T("SP")) == 0) {
683                 return REG16(SP);
684         } else if(_tcsicmp(reg, _T("BP")) == 0) {
685                 return REG16(BP);
686         } else if(_tcsicmp(reg, _T("SI")) == 0) {
687                 return REG16(SI);
688         } else if(_tcsicmp(reg, _T("DI")) == 0) {
689                 return REG16(DI);
690         } else if(_tcsicmp(reg, _T("AL")) == 0) {
691                 return REG8(AL);
692         } else if(_tcsicmp(reg, _T("AH")) == 0) {
693                 return REG8(AH);
694         } else if(_tcsicmp(reg, _T("BL")) == 0) {
695                 return REG8(BL);
696         } else if(_tcsicmp(reg, _T("BH")) == 0) {
697                 return REG8(BH);
698         } else if(_tcsicmp(reg, _T("CL")) == 0) {
699                 return REG8(CL);
700         } else if(_tcsicmp(reg, _T("CH")) == 0) {
701                 return REG8(CH);
702         } else if(_tcsicmp(reg, _T("DL")) == 0) {
703                 return REG8(DL);
704         } else if(_tcsicmp(reg, _T("DH")) == 0) {
705                 return REG8(DH);
706         }
707         return 0;
708 }
709
710 bool I386::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
711 {
712         i386_state *cpustate = (i386_state *)opaque;
713
714         if(cpustate->operand_size) {
715                 my_stprintf_s(buffer, buffer_len,
716                                           _T("MODE=%s PC=%08X PREV_PC=%08X SP(REAL)=%08X\n")
717                                           _T("CR[0-4]=%08X %08X %08X %08X %08X IOPL=%d CPL=%d\n")         
718                                           _T("EAX=%08X  EBX=%08X ECX=%08X EDX=%08X ESP=%08X  EBP=%08X  ESI=%08X  EDI=%08X\n")
719                                           _T("DS=%04X  ES=%04X SS=%04X CS=%04X FS=%04X GS=%04X\n")
720                                           _T("A20_MASK=%08X EIP=%08X  EFLAGS=%08X FLAG=[%c%c%c%c%c%c%c%c%c]\n")
721                                           _T("Clocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
722                                           (PROTECTED_MODE != 0) ? ((V8086_MODE) ? _T("PROTECTED V8086(32bit)") : _T("PROTECTED 32bit")) : ((V8086_MODE) ? _T("V8086(32bit)") : _T("32bit")),
723                                           cpustate->pc, cpustate->prev_pc, cpustate->sreg[SS].base + ((uint32_t)REG32(ESP)),
724                                           cpustate->cr[0] ,cpustate->cr[1], cpustate->cr[2], cpustate->cr[3], cpustate->cr[4], (cpustate->IOP1) | (cpustate->IOP2 << 1), cpustate->CPL,
725                                           REG32(EAX), REG32(EBX), REG32(ECX), REG32(EDX), REG32(ESP), REG32(EBP), REG32(ESI), REG32(EDI),
726                                           cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->sreg[FS].selector, cpustate->sreg[GS].selector, cpustate->a20_mask, cpustate->eip, cpustate->eflags,
727                                           cpustate->OF ? _T('O') : _T('-'), cpustate->DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
728                                           cpustate->SF ? _T('S') : _T('-'), cpustate->ZF ? _T('Z') : _T('-'), cpustate->AF ? _T('A') : _T('-'), cpustate->PF ? _T('P') : _T('-'), cpustate->CF ? _T('C') : _T('-'),
729                                           cpustate->total_cycles, cpustate->total_cycles - cpustate->prev_total_cycles,
730                                           get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame());
731         } else {
732                 if((PROTECTED_MODE) != 0) {
733                         if((V8086_MODE)) {
734                                 my_stprintf_s(buffer, buffer_len,
735                                           _T("MODE=V8086 (PROTECTED) PC=%08X PREV_PC=%08X SP(REAL)=%08X\n")
736                                           _T("CR[0-4]=%08X %08X %08X %08X %08X IOP=%d CPL=%d\n")          
737                                           _T("AX=%04X  BX=%04X CX=%04X DX=%04X SP=%04X  BP=%04X  SI=%04X  DI=%04X\n")
738                                           _T("DS=%04X  ES=%04X SS=%04X CS=%04X FS=%04X GS=%04X A20_MASK=%08X IP=%04X  FLAG=[%c%c%c%c%c%c%c%c%c]\n")
739                                           _T("Clocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
740                                           cpustate->pc, cpustate->prev_pc, cpustate->sreg[SS].base + ((uint32_t)REG32(ESP) & 0xffff),
741                                           cpustate->cr[0] ,cpustate->cr[1], cpustate->cr[2], cpustate->cr[3], cpustate->cr[4], (cpustate->IOP1) | (cpustate->IOP2 << 1), cpustate->CPL,
742                                           REG16(AX), REG16(BX), REG16(CX), REG16(DX), REG16(SP), REG16(BP), REG16(SI), REG16(DI),
743                                                           cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->sreg[FS].selector, cpustate->sreg[GS].selector, cpustate->a20_mask, cpustate->eip,
744                                           cpustate->OF ? _T('O') : _T('-'), cpustate->DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
745                                           cpustate->SF ? _T('S') : _T('-'), cpustate->ZF ? _T('Z') : _T('-'), cpustate->AF ? _T('A') : _T('-'), cpustate->PF ? _T('P') : _T('-'), cpustate->CF ? _T('C') : _T('-'),
746                                           cpustate->total_cycles, cpustate->total_cycles - cpustate->prev_total_cycles,
747                                           get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame());
748                         } else {
749                                 my_stprintf_s(buffer, buffer_len,
750                           _T("MODE=PROTECTED 16bit PC=%08X PREV_PC=%08X SP(REAL)=%08X\n")
751                           _T("CR[0-4]=%08X %08X %08X %08X %08X IOP=%d CPL=%d\n")          
752                           _T("AX=%04X  BX=%04X CX=%04X DX=%04X SP=%04X  BP=%04X  SI=%04X  DI=%04X\n")
753                           _T("DS=%04X  ES=%04X SS=%04X CS=%04X FS=%04X GS=%04X A20_MASK=%08X IP=%04X  EFLAGS=%08X FLAG=[%c%c%c%c%c%c%c%c%c]\n")
754                           _T("Clocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
755                                                           cpustate->pc, cpustate->prev_pc, cpustate->sreg[SS].base + ((uint32_t)REG32(ESP)),
756                           cpustate->cr[0] ,cpustate->cr[1], cpustate->cr[2], cpustate->cr[3], cpustate->cr[4], (cpustate->IOP1) | (cpustate->IOP2 << 1), cpustate->CPL,
757                           REG16(AX), REG16(BX), REG16(CX), REG16(DX), REG16(SP), REG16(BP), REG16(SI), REG16(DI),
758                           cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->sreg[FS].selector, cpustate->sreg[GS].selector, cpustate->a20_mask, cpustate->eip, cpustate->eflags,
759                           cpustate->OF ? _T('O') : _T('-'), cpustate->DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
760                           cpustate->SF ? _T('S') : _T('-'), cpustate->ZF ? _T('Z') : _T('-'), cpustate->AF ? _T('A') : _T('-'), cpustate->PF ? _T('P') : _T('-'), cpustate->CF ? _T('C') : _T('-'),
761                           cpustate->total_cycles, cpustate->total_cycles - cpustate->prev_total_cycles,
762                           get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame());
763                         }
764                 } else {
765                                 my_stprintf_s(buffer, buffer_len,
766                           _T("MODE=16bit PC=%08X PREV_PC=%08X SP(REAL)=%08X\n")
767                           _T("CR[0-4]=%08X %08X %08X %08X %08X IOP=%d CPL=%d\n")          
768                           _T("AX=%04X  BX=%04X CX=%04X DX=%04X SP=%04X  BP=%04X  SI=%04X  DI=%04X\n")
769                           _T("DS=%04X  ES=%04X SS=%04X CS=%04X FS=%04X GS=%04X A20_MASK=%08X IP=%04X EFLAGS=%08X FLAG=[%c%c%c%c%c%c%c%c%c]\n")
770                           _T("Clocks = %llu (%llu) Since Scanline = %d/%d (%d/%d)"),
771                                                           cpustate->pc, cpustate->prev_pc, cpustate->sreg[SS].base + ((uint32_t)REG16(SP) & 0xffff),
772                           cpustate->cr[0] ,cpustate->cr[1], cpustate->cr[2], cpustate->cr[3], cpustate->cr[4], (cpustate->IOP1) | (cpustate->IOP2 << 1), cpustate->CPL,
773                           REG16(AX), REG16(BX), REG16(CX), REG16(DX), REG16(SP), REG16(BP), REG16(SI), REG16(DI),
774                           cpustate->sreg[DS].selector, cpustate->sreg[ES].selector, cpustate->sreg[SS].selector, cpustate->sreg[CS].selector, cpustate->sreg[FS].selector, cpustate->sreg[GS].selector, cpustate->a20_mask, cpustate->eip, cpustate->eflags,
775                           cpustate->OF ? _T('O') : _T('-'), cpustate->DF ? _T('D') : _T('-'), cpustate->IF ? _T('I') : _T('-'), cpustate->TF ? _T('T') : _T('-'),
776                           cpustate->SF ? _T('S') : _T('-'), cpustate->ZF ? _T('Z') : _T('-'), cpustate->AF ? _T('A') : _T('-'), cpustate->PF ? _T('P') : _T('-'), cpustate->CF ? _T('C') : _T('-'),
777                           cpustate->total_cycles, cpustate->total_cycles - cpustate->prev_total_cycles,
778                           get_passed_clock_since_vline(), get_cur_vline_clocks(), get_cur_vline(), get_lines_per_frame());
779                 }                       
780         }
781         cpustate->prev_total_cycles = cpustate->total_cycles;
782         return true;
783 }
784
785 int I386::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
786 {
787         i386_state *cpustate = (i386_state *)opaque;
788         UINT64 eip = pc - cpustate->sreg[CS].base;
789         UINT8 ops[16];
790         for(int i = 0; i < 16; i++) {
791                 int wait;
792                 ops[i] = d_mem->read_data8w(pc + i, &wait);
793         }
794         UINT8 *oprom = ops;
795         
796         if(cpustate->operand_size) {
797                 return CPU_DISASSEMBLE_CALL(x86_32) & DASMFLAG_LENGTHMASK;
798         } else {
799                 return CPU_DISASSEMBLE_CALL(x86_16) & DASMFLAG_LENGTHMASK;
800         }
801 }
802 //#endif
803
804 void I386::set_address_mask(uint32_t mask)
805 {
806         i386_state *cpustate = (i386_state *)opaque;
807         cpustate->a20_mask = mask;
808         
809         // TODO: how does A20M and the tlb interact
810         vtlb_flush_dynamic(cpustate->vtlb);
811 }
812
813 uint32_t I386::get_address_mask()
814 {
815         i386_state *cpustate = (i386_state *)opaque;
816         return cpustate->a20_mask;
817 }
818
819 void I386::set_shutdown_flag(int shutdown)
820 {
821         i386_state *cpustate = (i386_state *)opaque;
822         cpustate->shutdown = shutdown;
823 }
824
825 int I386::get_shutdown_flag()
826 {
827         i386_state *cpustate = (i386_state *)opaque;
828         return cpustate->shutdown;
829 }
830
831 #define STATE_VERSION   5
832
833 void process_state_SREG(I386_SREG* val, FILEIO* state_fio)
834 {
835         state_fio->StateValue(val->selector);
836         state_fio->StateValue(val->flags);
837         state_fio->StateValue(val->base);
838         state_fio->StateValue(val->limit);
839         state_fio->StateValue(val->d);
840         state_fio->StateValue(val->valid);
841 }
842
843 void process_state_SYS_TABLE(I386_SYS_TABLE* val, FILEIO* state_fio)
844 {
845         state_fio->StateValue(val->base);
846         state_fio->StateValue(val->limit);
847 }
848
849 void process_state_SEG_DESC(I386_SEG_DESC* val, FILEIO* state_fio)
850 {
851         state_fio->StateValue(val->segment);
852         state_fio->StateValue(val->flags);
853         state_fio->StateValue(val->base);
854         state_fio->StateValue(val->limit);
855 }
856
857 void process_state_GPR(I386_GPR* val, FILEIO* state_fio)
858 {
859         state_fio->StateArray(val->d, sizeof(val->d), 1);
860         state_fio->StateArray(val->w, sizeof(val->w), 1);
861         state_fio->StateArray(val->b, sizeof(val->b), 1);
862 }
863
864 void process_state_floatx80(floatx80* val, FILEIO* state_fio)
865 {
866         state_fio->StateValue(val->high);
867         state_fio->StateValue(val->low);
868 }
869
870 void process_state_XMM_REG(XMM_REG* val, FILEIO* state_fio)
871 {
872         state_fio->StateArray(val->b, sizeof(val->b), 1);
873         state_fio->StateArray(val->w, sizeof(val->w), 1);
874         state_fio->StateArray(val->d, sizeof(val->d), 1);
875         state_fio->StateArray(val->q, sizeof(val->q), 1);
876         state_fio->StateArray(val->c, sizeof(val->c), 1);
877         state_fio->StateArray(val->s, sizeof(val->s), 1);
878         state_fio->StateArray(val->i, sizeof(val->i), 1);
879         state_fio->StateArray(val->l, sizeof(val->l), 1);
880         state_fio->StateArray(val->f, sizeof(val->f), 1);
881         state_fio->StateArray(val->f64, sizeof(val->f64), 1);
882 }
883
884 void process_state_vtlb(vtlb_state* val, FILEIO* state_fio)
885 {
886 //      state_fio->StateValue(val->space);
887 //      state_fio->StateValue(val->dynamic);
888 //      state_fio->StateValue(val->fixed);
889         state_fio->StateValue(val->dynindex);
890 //      state_fio->StateValue(val->pageshift);
891 //      state_fio->StateValue(val->addrwidth);
892         if(val->live != NULL) {
893                 state_fio->StateArray(val->live, val->fixed + val->dynamic, 1);
894         }
895         if(val->fixedpages != NULL) {
896                 state_fio->StateArray(val->fixedpages, val->fixed, 1);
897         }
898         if(val->table != NULL) {
899                 state_fio->StateArray(val->table, (size_t) 1 << (val->addrwidth - val->pageshift), 1);
900         }
901 }
902
903 bool I386::process_state(FILEIO* state_fio, bool loading)
904 {
905         i386_state *cpustate = (i386_state *)opaque;
906         
907         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
908                 return false;
909         }
910         if(!state_fio->StateCheckInt32(this_device_id)) {
911                 return false;
912         }
913         process_state_GPR(&cpustate->reg, state_fio);
914         for(int i = 0; i < array_length(cpustate->sreg); i++) {
915                 process_state_SREG(&cpustate->sreg[i], state_fio);
916         }
917         state_fio->StateValue(cpustate->eip);
918         state_fio->StateValue(cpustate->pc);
919         state_fio->StateValue(cpustate->prev_eip);
920         state_fio->StateValue(cpustate->prev_pc);
921         state_fio->StateValue(cpustate->eflags);
922         state_fio->StateValue(cpustate->eflags_mask);
923         state_fio->StateValue(cpustate->CF);
924         state_fio->StateValue(cpustate->DF);
925         state_fio->StateValue(cpustate->SF);
926         state_fio->StateValue(cpustate->OF);
927         state_fio->StateValue(cpustate->ZF);
928         state_fio->StateValue(cpustate->PF);
929         state_fio->StateValue(cpustate->AF);
930         state_fio->StateValue(cpustate->IF);
931         state_fio->StateValue(cpustate->TF);
932         state_fio->StateValue(cpustate->IOP1);
933         state_fio->StateValue(cpustate->IOP2);
934         state_fio->StateValue(cpustate->NT);
935         state_fio->StateValue(cpustate->RF);
936         state_fio->StateValue(cpustate->VM);
937         state_fio->StateValue(cpustate->AC);
938         state_fio->StateValue(cpustate->VIF);
939         state_fio->StateValue(cpustate->VIP);
940         state_fio->StateValue(cpustate->ID);
941         state_fio->StateValue(cpustate->CPL);
942         state_fio->StateValue(cpustate->performed_intersegment_jump);
943         state_fio->StateValue(cpustate->delayed_interrupt_enable);
944         state_fio->StateArray(cpustate->cr, sizeof(cpustate->cr), 1);
945         state_fio->StateArray(cpustate->dr, sizeof(cpustate->dr), 1);
946         state_fio->StateArray(cpustate->tr, sizeof(cpustate->tr), 1);
947         process_state_SYS_TABLE(&cpustate->gdtr, state_fio);
948         process_state_SYS_TABLE(&cpustate->idtr, state_fio);
949         process_state_SEG_DESC(&cpustate->task, state_fio);
950         process_state_SEG_DESC(&cpustate->ldtr, state_fio);
951         state_fio->StateValue(cpustate->ext);
952         state_fio->StateValue(cpustate->halted);
953         state_fio->StateValue(cpustate->busreq);
954         state_fio->StateValue(cpustate->shutdown);
955         state_fio->StateValue(cpustate->operand_size);
956         state_fio->StateValue(cpustate->xmm_operand_size);
957         state_fio->StateValue(cpustate->address_size);
958         state_fio->StateValue(cpustate->operand_prefix);
959         state_fio->StateValue(cpustate->address_prefix);
960         state_fio->StateValue(cpustate->segment_prefix);
961         state_fio->StateValue(cpustate->segment_override);
962 //#ifdef USE_DEBUGGER
963         state_fio->StateValue(cpustate->total_cycles);
964 //#endif
965         state_fio->StateValue(cpustate->cycles);
966         state_fio->StateValue(cpustate->extra_cycles);
967         state_fio->StateValue(cpustate->base_cycles);
968         state_fio->StateValue(cpustate->opcode);
969         state_fio->StateValue(cpustate->irq_state);
970         state_fio->StateValue(cpustate->a20_mask);
971         state_fio->StateValue(cpustate->cpuid_max_input_value_eax);
972         state_fio->StateValue(cpustate->cpuid_id0);
973         state_fio->StateValue(cpustate->cpuid_id1);
974         state_fio->StateValue(cpustate->cpuid_id2);
975         state_fio->StateValue(cpustate->cpu_version);
976         state_fio->StateValue(cpustate->feature_flags);
977         state_fio->StateValue(cpustate->tsc);
978         state_fio->StateArray(cpustate->perfctr, sizeof(cpustate->perfctr), 1);
979         for(int i = 0; i < array_length(cpustate->x87_reg); i++) {
980                 process_state_floatx80(&cpustate->x87_reg[i], state_fio);
981         }
982         state_fio->StateValue(cpustate->x87_cw);
983         state_fio->StateValue(cpustate->x87_sw);
984         state_fio->StateValue(cpustate->x87_tw);
985         state_fio->StateValue(cpustate->x87_data_ptr);
986         state_fio->StateValue(cpustate->x87_inst_ptr);
987         state_fio->StateValue(cpustate->x87_opcode);
988         for(int i = 0; i < array_length(cpustate->sse_reg); i++) {
989                 process_state_XMM_REG(&cpustate->sse_reg[i], state_fio);
990         }
991         state_fio->StateValue(cpustate->mxcsr);
992         state_fio->StateArray(&cpustate->lock_table[0][0], sizeof(cpustate->lock_table), 1);
993         if(cpustate->vtlb != NULL) {
994                 process_state_vtlb(cpustate->vtlb, state_fio);
995         }
996         state_fio->StateValue(cpustate->smm);
997         state_fio->StateValue(cpustate->smi);
998         state_fio->StateValue(cpustate->smi_latched);
999         state_fio->StateValue(cpustate->nmi_masked);
1000         state_fio->StateValue(cpustate->nmi_latched);
1001         state_fio->StateValue(cpustate->smbase);
1002 //      state_fio->StateValue(cpustate->smiact);
1003         state_fio->StateValue(cpustate->lock);
1004 #ifdef DEBUG_MISSING_OPCODE
1005         state_fio->StateArray(cpustate->opcode_bytes, sizeof(cpustate->opcode_bytes), 1);
1006         state_fio->StateValue(cpustate->opcode_pc);
1007         state_fio->StateValue(cpustate->opcode_bytes_length);
1008 #endif
1009         
1010 //#ifdef USE_DEBUGGER
1011         // post process
1012         if(loading) {
1013                 cpustate->prev_total_cycles = cpustate->total_cycles;
1014         }
1015 //#endif
1016         return true;
1017 }
1018