OSDN Git Service

[VM][General][Qt] Merge upstream 2015-12-31.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mame / emu / cpu / i386 / i386priv.h
1 // license:BSD-3-Clause
2 // copyright-holders:Ville Linde, Barry Rodewald, Carl, Phil Bennett
3 #pragma once
4
5 #ifndef __I386_H__
6 #define __I386_H__
7
8 //#include "i386.h"
9 #include "../../../lib/softfloat/milieu.h"
10 #include "../../../lib/softfloat/softfloat.h"
11 #include "../vtlb.h"
12
13 #if !defined(_MSC_VER)
14 #include <math.h>
15 #endif
16 //#define DEBUG_MISSING_OPCODE
17
18 #define I386OP(XX)      i386_##XX
19 #define I486OP(XX)      i486_##XX
20 #define PENTIUMOP(XX)   pentium_##XX
21 #define MMXOP(XX)       mmx_##XX
22 #define SSEOP(XX)       sse_##XX
23
24 extern int i386_dasm_one(_TCHAR *buffer, UINT32 pc, const UINT8 *oprom, int mode);
25
26 enum SREGS { ES, CS, SS, DS, FS, GS };
27
28 enum BREGS
29 {
30         AL = NATIVE_ENDIAN_VALUE_LE_BE(0,3),
31         AH = NATIVE_ENDIAN_VALUE_LE_BE(1,2),
32         CL = NATIVE_ENDIAN_VALUE_LE_BE(4,7),
33         CH = NATIVE_ENDIAN_VALUE_LE_BE(5,6),
34         DL = NATIVE_ENDIAN_VALUE_LE_BE(8,11),
35         DH = NATIVE_ENDIAN_VALUE_LE_BE(9,10),
36         BL = NATIVE_ENDIAN_VALUE_LE_BE(12,15),
37         BH = NATIVE_ENDIAN_VALUE_LE_BE(13,14)
38 };
39
40 enum WREGS
41 {
42         AX = NATIVE_ENDIAN_VALUE_LE_BE(0,1),
43         CX = NATIVE_ENDIAN_VALUE_LE_BE(2,3),
44         DX = NATIVE_ENDIAN_VALUE_LE_BE(4,5),
45         BX = NATIVE_ENDIAN_VALUE_LE_BE(6,7),
46         SP = NATIVE_ENDIAN_VALUE_LE_BE(8,9),
47         BP = NATIVE_ENDIAN_VALUE_LE_BE(10,11),
48         SI = NATIVE_ENDIAN_VALUE_LE_BE(12,13),
49         DI = NATIVE_ENDIAN_VALUE_LE_BE(14,15)
50 };
51
52 enum DREGS { EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI };
53
54 enum
55 {
56         I386_PC = 0,
57
58         /* 8-bit registers */
59         I386_AL,
60         I386_AH,
61         I386_BL,
62         I386_BH,
63         I386_CL,
64         I386_CH,
65         I386_DL,
66         I386_DH,
67
68         /* 16-bit registers */
69         I386_AX,
70         I386_BX,
71         I386_CX,
72         I386_DX,
73         I386_BP,
74         I386_SP,
75         I386_SI,
76         I386_DI,
77         I386_IP,
78
79         /* 32-bit registers */
80         I386_EAX,
81         I386_ECX,
82         I386_EDX,
83         I386_EBX,
84         I386_EBP,
85         I386_ESP,
86         I386_ESI,
87         I386_EDI,
88         I386_EIP,
89
90         /* segment registers */
91         I386_CS,
92         I386_CS_BASE,
93         I386_CS_LIMIT,
94         I386_CS_FLAGS,
95         I386_SS,
96         I386_SS_BASE,
97         I386_SS_LIMIT,
98         I386_SS_FLAGS,
99         I386_DS,
100         I386_DS_BASE,
101         I386_DS_LIMIT,
102         I386_DS_FLAGS,
103         I386_ES,
104         I386_ES_BASE,
105         I386_ES_LIMIT,
106         I386_ES_FLAGS,
107         I386_FS,
108         I386_FS_BASE,
109         I386_FS_LIMIT,
110         I386_FS_FLAGS,
111         I386_GS,
112         I386_GS_BASE,
113         I386_GS_LIMIT,
114         I386_GS_FLAGS,
115
116         /* other */
117         I386_EFLAGS,
118
119         I386_CR0,
120         I386_CR1,
121         I386_CR2,
122         I386_CR3,
123         I386_CR4,
124
125         I386_DR0,
126         I386_DR1,
127         I386_DR2,
128         I386_DR3,
129         I386_DR4,
130         I386_DR5,
131         I386_DR6,
132         I386_DR7,
133
134         I386_TR6,
135         I386_TR7,
136
137         I386_GDTR_BASE,
138         I386_GDTR_LIMIT,
139         I386_IDTR_BASE,
140         I386_IDTR_LIMIT,
141         I386_TR,
142         I386_TR_BASE,
143         I386_TR_LIMIT,
144         I386_TR_FLAGS,
145         I386_LDTR,
146         I386_LDTR_BASE,
147         I386_LDTR_LIMIT,
148         I386_LDTR_FLAGS,
149
150         I386_CPL,
151
152         X87_CTRL,
153         X87_STATUS,
154         X87_TAG,
155         X87_ST0,
156         X87_ST1,
157         X87_ST2,
158         X87_ST3,
159         X87_ST4,
160         X87_ST5,
161         X87_ST6,
162         X87_ST7,
163
164         SSE_XMM0,
165         SSE_XMM1,
166         SSE_XMM2,
167         SSE_XMM3,
168         SSE_XMM4,
169         SSE_XMM5,
170         SSE_XMM6,
171         SSE_XMM7
172 };
173
174 enum
175 {
176         /* mmx registers aliased to x87 ones */
177         MMX_MM0=X87_ST0,
178         MMX_MM1=X87_ST1,
179         MMX_MM2=X87_ST2,
180         MMX_MM3=X87_ST3,
181         MMX_MM4=X87_ST4,
182         MMX_MM5=X87_ST5,
183         MMX_MM6=X87_ST6,
184         MMX_MM7=X87_ST7
185 };
186
187 enum smram
188 {
189         SMRAM_SMBASE = 0xF8,
190         SMRAM_SMREV  = 0xFC,
191         SMRAM_IORSRT = 0x100,
192         SMRAM_AHALT  = 0x102,
193         SMRAM_IOEDI  = 0x104,
194         SMRAM_IOECX  = 0x108,
195         SMRAM_IOESI  = 0x10C,
196
197         SMRAM_ES     = 0x1A8,
198         SMRAM_CS     = 0x1AC,
199         SMRAM_SS     = 0x1B0,
200         SMRAM_DS     = 0x1B4,
201         SMRAM_FS     = 0x1B8,
202         SMRAM_GS     = 0x1BC,
203         SMRAM_LDTR   = 0x1C0,
204         SMRAM_TR     = 0x1C4,
205         SMRAM_DR7    = 0x1C8,
206         SMRAM_DR6    = 0x1CC,
207         SMRAM_EAX    = 0x1D0,
208         SMRAM_ECX    = 0x1D4,
209         SMRAM_EDX    = 0x1D8,
210         SMRAM_EBX    = 0x1DC,
211         SMRAM_ESP    = 0x1E0,
212         SMRAM_EBP    = 0x1E4,
213         SMRAM_ESI    = 0x1E8,
214         SMRAM_EDI    = 0x1EC,
215         SMRAM_EIP    = 0x1F0,
216         SMRAM_EFLAGS = 0x1F4,
217         SMRAM_CR3    = 0x1F8,
218         SMRAM_CR0    = 0x1FC,
219 };
220
221 enum smram_intel_p5
222 {
223         SMRAM_IP5_IOEIP   = 0x110,
224         SMRAM_IP5_CR4     = 0x128,
225         SMRAM_IP5_ESLIM   = 0x130,
226         SMRAM_IP5_ESBASE  = 0x134,
227         SMRAM_IP5_ESACC   = 0x138,
228         SMRAM_IP5_CSLIM   = 0x13C,
229         SMRAM_IP5_CSBASE  = 0x140,
230         SMRAM_IP5_CSACC   = 0x144,
231         SMRAM_IP5_SSLIM   = 0x148,
232         SMRAM_IP5_SSBASE  = 0x14C,
233         SMRAM_IP5_SSACC   = 0x150,
234         SMRAM_IP5_DSLIM   = 0x154,
235         SMRAM_IP5_DSBASE  = 0x158,
236         SMRAM_IP5_DSACC   = 0x15C,
237         SMRAM_IP5_FSLIM   = 0x160,
238         SMRAM_IP5_FSBASE  = 0x164,
239         SMRAM_IP5_FSACC   = 0x168,
240         SMRAM_IP5_GSLIM   = 0x16C,
241         SMRAM_IP5_GSBASE  = 0x170,
242         SMRAM_IP5_GSACC   = 0x174,
243         SMRAM_IP5_LDTLIM  = 0x178,
244         SMRAM_IP5_LDTBASE = 0x17C,
245         SMRAM_IP5_LDTACC  = 0x180,
246         SMRAM_IP5_GDTLIM  = 0x184,
247         SMRAM_IP5_GDTBASE = 0x188,
248         SMRAM_IP5_GDTACC  = 0x18C,
249         SMRAM_IP5_IDTLIM  = 0x190,
250         SMRAM_IP5_IDTBASE = 0x194,
251         SMRAM_IP5_IDTACC  = 0x198,
252         SMRAM_IP5_TRLIM   = 0x19C,
253         SMRAM_IP5_TRBASE  = 0x1A0,
254         SMRAM_IP5_TRACC   = 0x1A4,
255 };
256
257 /* Protected mode exceptions */
258 #define FAULT_UD 6   // Invalid Opcode
259 #define FAULT_NM 7   // Coprocessor not available
260 #define FAULT_DF 8   // Double Fault
261 #define FAULT_TS 10  // Invalid TSS
262 #define FAULT_NP 11  // Segment or Gate not present
263 #define FAULT_SS 12  // Stack fault
264 #define FAULT_GP 13  // General Protection Fault
265 #define FAULT_PF 14  // Page Fault
266 #define FAULT_MF 16  // Match (Coprocessor) Fault
267
268 /* MXCSR Control and Status Register */
269 #define MXCSR_IE  (1<<0)  // Invalid Operation Flag
270 #define MXCSR_DE  (1<<1)  // Denormal Flag
271 #define MXCSR_ZE  (1<<2)  // Divide-by-Zero Flag
272 #define MXCSR_OE  (1<<3)  // Overflow Flag
273 #define MXCSR_UE  (1<<4)  // Underflow Flag
274 #define MXCSR_PE  (1<<5)  // Precision Flag
275 #define MXCSR_DAZ (1<<6)  // Denormals Are Zeros
276 #define MXCSR_IM  (1<<7)  // Invalid Operation Mask
277 #define MXCSR_DM  (1<<8)  // Denormal Operation Mask
278 #define MXCSR_ZM  (1<<9)  // Divide-by-Zero Mask
279 #define MXCSR_OM  (1<<10) // Overflow Mask
280 #define MXCSR_UM  (1<<11) // Underflow Mask
281 #define MXCSR_PM  (1<<12) // Precision Mask
282 #define MXCSR_RC  (3<<13) // Rounding Control
283 #define MXCSR_FZ  (1<<15) // Flush to Zero
284
285 struct I386_SREG {
286         UINT16 selector;
287         UINT16 flags;
288         UINT32 base;
289         UINT32 limit;
290         int d;      // Operand size
291         bool valid;
292 };
293
294 struct I386_CALL_GATE
295 {
296         UINT16 segment;
297         UINT16 selector;
298         UINT32 offset;
299         UINT8 ar;  // access rights
300         UINT8 dpl;
301         UINT8 dword_count;
302         UINT8 present;
303 };
304
305 struct I386_SYS_TABLE {
306         UINT32 base;
307         UINT16 limit;
308 };
309
310 struct I386_SEG_DESC {
311         UINT16 segment;
312         UINT16 flags;
313         UINT32 base;
314         UINT32 limit;
315 };
316
317 union I386_GPR {
318         UINT32 d[8];
319         UINT16 w[16];
320         UINT8 b[32];
321 };
322
323 union MMX_REG {
324         UINT32 d[2];
325         INT32  i[2];
326         UINT16 w[4];
327         INT16  s[4];
328         UINT8  b[8];
329         INT8   c[8];
330         float  f[2];
331         UINT64 q;
332         INT64  l;
333 };
334
335 union XMM_REG {
336         UINT8  b[16];
337         UINT16 w[8];
338         UINT32 d[4];
339         UINT64 q[2];
340         INT8   c[16];
341         INT16  s[8];
342         INT32  i[4];
343         INT64  l[2];
344         float  f[4];
345         double  f64[2];
346 };
347
348 struct i386_state
349 {
350         I386_GPR reg;
351         I386_SREG sreg[6];
352         UINT32 eip;
353         UINT32 pc;
354         UINT32 prev_eip;
355         UINT32 prev_pc;
356         UINT32 eflags;
357         UINT32 eflags_mask;
358         UINT8 CF;
359         UINT8 DF;
360         UINT8 SF;
361         UINT8 OF;
362         UINT8 ZF;
363         UINT8 PF;
364         UINT8 AF;
365         UINT8 IF;
366         UINT8 TF;
367         UINT8 IOP1;
368         UINT8 IOP2;
369         UINT8 NT;
370         UINT8 RF;
371         UINT8 VM;
372         UINT8 AC;
373         UINT8 VIF;
374         UINT8 VIP;
375         UINT8 ID;
376
377         UINT8 CPL;  // current privilege level
378
379         UINT8 performed_intersegment_jump;
380         UINT8 delayed_interrupt_enable;
381
382         UINT32 cr[5];       // Control registers
383         UINT32 dr[8];       // Debug registers
384         UINT32 tr[8];       // Test registers
385
386         I386_SYS_TABLE gdtr;    // Global Descriptor Table Register
387         I386_SYS_TABLE idtr;    // Interrupt Descriptor Table Register
388         I386_SEG_DESC task;     // Task register
389         I386_SEG_DESC ldtr;     // Local Descriptor Table Register
390
391         UINT8 ext;  // external interrupt
392
393         int halted;
394         int busreq;
395         int shutdown;
396
397         int operand_size;
398         int xmm_operand_size;
399         int address_size;
400         int operand_prefix;
401         int address_prefix;
402
403         int segment_prefix;
404         int segment_override;
405
406         int cycles;
407         int extra_cycles;
408         int base_cycles;
409         UINT8 opcode;
410
411         UINT8 irq_state;
412         DEVICE *pic;
413         DEVICE *program;
414         DEVICE *io;
415 #ifdef I386_PSEUDO_BIOS
416         DEVICE *bios;
417 #endif
418 #ifdef SINGLE_MODE_DMA
419         DEVICE *dma;
420 #endif
421 #ifdef USE_DEBUGGER
422         EMU *emu;
423         DEBUGGER *debugger;
424         DEVICE *program_stored;
425         DEVICE *io_stored;
426 #endif
427         UINT32 a20_mask;
428
429         int cpuid_max_input_value_eax;
430         UINT32 cpuid_id0, cpuid_id1, cpuid_id2;
431         UINT32 cpu_version;
432         UINT32 feature_flags;
433         UINT64 tsc;
434         UINT64 perfctr[2];
435
436         // FPU
437         floatx80 x87_reg[8];
438
439         UINT16 x87_cw;
440         UINT16 x87_sw;
441         UINT16 x87_tw;
442         UINT64 x87_data_ptr;
443         UINT64 x87_inst_ptr;
444         UINT16 x87_opcode;
445
446         void (*opcode_table_x87_d8[256])(i386_state *cpustate, UINT8 modrm);
447         void (*opcode_table_x87_d9[256])(i386_state *cpustate, UINT8 modrm);
448         void (*opcode_table_x87_da[256])(i386_state *cpustate, UINT8 modrm);
449         void (*opcode_table_x87_db[256])(i386_state *cpustate, UINT8 modrm);
450         void (*opcode_table_x87_dc[256])(i386_state *cpustate, UINT8 modrm);
451         void (*opcode_table_x87_dd[256])(i386_state *cpustate, UINT8 modrm);
452         void (*opcode_table_x87_de[256])(i386_state *cpustate, UINT8 modrm);
453         void (*opcode_table_x87_df[256])(i386_state *cpustate, UINT8 modrm);
454
455         // SSE
456         XMM_REG sse_reg[8];
457         UINT32 mxcsr;
458
459         void (*opcode_table1_16[256])(i386_state *cpustate);
460         void (*opcode_table1_32[256])(i386_state *cpustate);
461         void (*opcode_table2_16[256])(i386_state *cpustate);
462         void (*opcode_table2_32[256])(i386_state *cpustate);
463         void (*opcode_table338_16[256])(i386_state *cpustate);
464         void (*opcode_table338_32[256])(i386_state *cpustate);
465         void (*opcode_table33a_16[256])(i386_state *cpustate);
466         void (*opcode_table33a_32[256])(i386_state *cpustate);
467         void (*opcode_table366_16[256])(i386_state *cpustate);
468         void (*opcode_table366_32[256])(i386_state *cpustate);
469         void (*opcode_table3f2_16[256])(i386_state *cpustate);
470         void (*opcode_table3f2_32[256])(i386_state *cpustate);
471         void (*opcode_table3f3_16[256])(i386_state *cpustate);
472         void (*opcode_table3f3_32[256])(i386_state *cpustate);
473         void (*opcode_table46638_16[256])(i386_state *cpustate);
474         void (*opcode_table46638_32[256])(i386_state *cpustate);
475         void (*opcode_table4f238_16[256])(i386_state *cpustate);
476         void (*opcode_table4f238_32[256])(i386_state *cpustate);
477         void (*opcode_table4f338_16[256])(i386_state *cpustate);
478         void (*opcode_table4f338_32[256])(i386_state *cpustate);
479         void (*opcode_table4663a_16[256])(i386_state *cpustate);
480         void (*opcode_table4663a_32[256])(i386_state *cpustate);
481         void (*opcode_table4f23a_16[256])(i386_state *cpustate);
482         void (*opcode_table4f23a_32[256])(i386_state *cpustate);
483
484         bool lock_table[2][256];
485
486         UINT8 *cycle_table_pm;
487         UINT8 *cycle_table_rm;
488
489         vtlb_state *vtlb;
490
491         bool smm;
492         bool smi;
493         bool smi_latched;
494         bool nmi_masked;
495         bool nmi_latched;
496         UINT32 smbase;
497 //      devcb_resolved_write_line smiact;
498         bool lock;
499
500         // bytes in current opcode, debug only
501 #ifdef DEBUG_MISSING_OPCODE
502         UINT8 opcode_bytes[16];
503         UINT32 opcode_pc;
504         int opcode_bytes_length;
505 #endif
506 };
507
508 extern int i386_parity_table[256];
509 static int i386_limit_check(i386_state *cpustate, int seg, UINT32 offset);
510
511 #define FAULT_THROW(fault,error) { throw (UINT64)(fault | (UINT64)error << 32); }
512 #define PF_THROW(error) { cpustate->cr[2] = address; FAULT_THROW(FAULT_PF,error); }
513
514 #define PROTECTED_MODE      (cpustate->cr[0] & 0x1)
515 #define STACK_32BIT         (cpustate->sreg[SS].d)
516 #define V8086_MODE          (cpustate->VM)
517 #define NESTED_TASK         (cpustate->NT)
518 #define WP                  (cpustate->cr[0] & 0x10000)
519
520 #define SetOF_Add32(r,s,d)  (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80000000) ? 1: 0)
521 #define SetOF_Add16(r,s,d)  (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x8000) ? 1 : 0)
522 #define SetOF_Add8(r,s,d)   (cpustate->OF = (((r) ^ (s)) & ((r) ^ (d)) & 0x80) ? 1 : 0)
523
524 #define SetOF_Sub32(r,s,d)  (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80000000) ? 1 : 0)
525 #define SetOF_Sub16(r,s,d)  (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x8000) ? 1 : 0)
526 #define SetOF_Sub8(r,s,d)   (cpustate->OF = (((d) ^ (s)) & ((d) ^ (r)) & 0x80) ? 1 : 0)
527
528 #define SetCF8(x)           {cpustate->CF = ((x) & 0x100) ? 1 : 0; }
529 #define SetCF16(x)          {cpustate->CF = ((x) & 0x10000) ? 1 : 0; }
530 #define SetCF32(x)          {cpustate->CF = ((x) & (((UINT64)1) << 32)) ? 1 : 0; }
531
532 #define SetSF(x)            (cpustate->SF = (x))
533 #define SetZF(x)            (cpustate->ZF = (x))
534 #define SetAF(x,y,z)        (cpustate->AF = (((x) ^ ((y) ^ (z))) & 0x10) ? 1 : 0)
535 #define SetPF(x)            (cpustate->PF = i386_parity_table[(x) & 0xFF])
536
537 #define SetSZPF8(x)         {cpustate->ZF = ((UINT8)(x)==0);  cpustate->SF = ((x)&0x80) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; }
538 #define SetSZPF16(x)        {cpustate->ZF = ((UINT16)(x)==0);  cpustate->SF = ((x)&0x8000) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; }
539 #define SetSZPF32(x)        {cpustate->ZF = ((UINT32)(x)==0);  cpustate->SF = ((x)&0x80000000) ? 1 : 0; cpustate->PF = i386_parity_table[x & 0xFF]; }
540
541 #define MMX(n)              (*((MMX_REG *)(&cpustate->x87_reg[(n)].low)))
542 #define XMM(n)              cpustate->sse_reg[(n)]
543
544 /***********************************************************************************/
545
546 struct MODRM_TABLE {
547         struct {
548                 int b;
549                 int w;
550                 int d;
551         } reg;
552         struct {
553                 int b;
554                 int w;
555                 int d;
556         } rm;
557 };
558
559 extern MODRM_TABLE i386_MODRM_table[256];
560
561 #define REG8(x)         (cpustate->reg.b[x])
562 #define REG16(x)        (cpustate->reg.w[x])
563 #define REG32(x)        (cpustate->reg.d[x])
564
565 #define LOAD_REG8(x)    (REG8(i386_MODRM_table[x].reg.b))
566 #define LOAD_REG16(x)   (REG16(i386_MODRM_table[x].reg.w))
567 #define LOAD_REG32(x)   (REG32(i386_MODRM_table[x].reg.d))
568 #define LOAD_RM8(x)     (REG8(i386_MODRM_table[x].rm.b))
569 #define LOAD_RM16(x)    (REG16(i386_MODRM_table[x].rm.w))
570 #define LOAD_RM32(x)    (REG32(i386_MODRM_table[x].rm.d))
571
572 #define STORE_REG8(x, value)    (REG8(i386_MODRM_table[x].reg.b) = value)
573 #define STORE_REG16(x, value)   (REG16(i386_MODRM_table[x].reg.w) = value)
574 #define STORE_REG32(x, value)   (REG32(i386_MODRM_table[x].reg.d) = value)
575 #define STORE_RM8(x, value)     (REG8(i386_MODRM_table[x].rm.b) = value)
576 #define STORE_RM16(x, value)    (REG16(i386_MODRM_table[x].rm.w) = value)
577 #define STORE_RM32(x, value)    (REG32(i386_MODRM_table[x].rm.d) = value)
578
579 #define SWITCH_ENDIAN_32(x) (((((x) << 24) & (0xff << 24)) | (((x) << 8) & (0xff << 16)) | (((x) >> 8) & (0xff << 8)) | (((x) >> 24) & (0xff << 0))))
580
581 /***********************************************************************************/
582
583 INLINE UINT32 i386_translate(i386_state *cpustate, int segment, UINT32 ip, int rwn)
584 {
585         // TODO: segment limit access size, execution permission, handle exception thrown from exception handler
586         if(PROTECTED_MODE && !V8086_MODE && (rwn != -1))
587         {
588                 if(!(cpustate->sreg[segment].valid))
589                         FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0);
590                 if(i386_limit_check(cpustate, segment, ip))
591                         FAULT_THROW((segment==SS)?FAULT_SS:FAULT_GP, 0);
592                 if((rwn == 0) && ((cpustate->sreg[segment].flags & 8) && !(cpustate->sreg[segment].flags & 2)))
593                         FAULT_THROW(FAULT_GP, 0);
594                 if((rwn == 1) && ((cpustate->sreg[segment].flags & 8) || !(cpustate->sreg[segment].flags & 2)))
595                         FAULT_THROW(FAULT_GP, 0);
596         }
597         return cpustate->sreg[segment].base + ip;
598 }
599
600 #define VTLB_FLAG_DIRTY 0x100
601
602 INLINE vtlb_entry get_permissions(UINT32 pte, int wp)
603 {
604         vtlb_entry ret = VTLB_READ_ALLOWED | ((pte & 4) ? VTLB_USER_READ_ALLOWED : 0);
605         if(!wp)
606                 ret |= VTLB_WRITE_ALLOWED;
607         if(pte & 2)
608                 ret |= VTLB_WRITE_ALLOWED | ((pte & 4) ? VTLB_USER_WRITE_ALLOWED : 0);
609         return ret;
610 }
611
612 static int i386_translate_address(i386_state *cpustate, int intention, offs_t *address, vtlb_entry *entry)
613 {
614         UINT32 a = *address;
615         UINT32 pdbr = cpustate->cr[3] & 0xfffff000;
616         UINT32 directory = (a >> 22) & 0x3ff;
617         UINT32 table = (a >> 12) & 0x3ff;
618         vtlb_entry perm = 0;
619         int ret = FALSE;
620         bool user = (intention & TRANSLATE_USER_MASK) ? true : false;
621         bool write = (intention & TRANSLATE_WRITE) ? true : false;
622         bool debug = (intention & TRANSLATE_DEBUG_MASK) ? true : false;
623
624         if(!(cpustate->cr[0] & 0x80000000))
625         {
626                 if(entry)
627                         *entry = 0x77;
628                 return TRUE;
629         }
630
631         UINT32 page_dir = cpustate->program->read_data32(pdbr + directory * 4);
632         if(page_dir & 1)
633         {
634                 if ((page_dir & 0x80) && (cpustate->cr[4] & 0x10))
635                 {
636                         a = (page_dir & 0xffc00000) | (a & 0x003fffff);
637                         if(debug)
638                         {
639                                 *address = a;
640                                 return TRUE;
641                         }
642                         perm = get_permissions(page_dir, WP);
643                         if(write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED))))
644                                 ret = FALSE;
645                         else if(user && !(perm & VTLB_USER_READ_ALLOWED))
646                                 ret = FALSE;
647                         else
648                         {
649                                 if(write)
650                                         perm |= VTLB_FLAG_DIRTY;
651                                 if(!(page_dir & 0x40) && write)
652                                         cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x60);
653                                 else if(!(page_dir & 0x20))
654                                         cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x20);
655                                 ret = TRUE;
656                         }
657                 }
658                 else
659                 {
660                         UINT32 page_entry = cpustate->program->read_data32((page_dir & 0xfffff000) + (table * 4));
661                         if(!(page_entry & 1))
662                                 ret = FALSE;
663                         else
664                         {
665                                 a = (page_entry & 0xfffff000) | (a & 0xfff);
666                                 if(debug)
667                                 {
668                                         *address = a;
669                                         return TRUE;
670                                 }
671                                 perm = get_permissions(page_entry, WP);
672                                 if(write && (!(perm & VTLB_WRITE_ALLOWED) || (user && !(perm & VTLB_USER_WRITE_ALLOWED))))
673                                         ret = FALSE;
674                                 else if(user && !(perm & VTLB_USER_READ_ALLOWED))
675                                         ret = FALSE;
676                                 else
677                                 {
678                                         if(write)
679                                                 perm |= VTLB_FLAG_DIRTY;
680                                         if(!(page_dir & 0x20))
681                                                 cpustate->program->write_data32(pdbr + directory * 4, page_dir | 0x20);
682                                         if(!(page_entry & 0x40) && write)
683                                                 cpustate->program->write_data32((page_dir & 0xfffff000) + (table * 4), page_entry | 0x60);
684                                         else if(!(page_entry & 0x20))
685                                                 cpustate->program->write_data32((page_dir & 0xfffff000) + (table * 4), page_entry | 0x20);
686                                         ret = TRUE;
687                                 }
688                         }
689                 }
690         }
691         else
692                 ret = FALSE;
693         if(entry)
694                 *entry = perm;
695         if(ret)
696                 *address = a;
697         return ret;
698 }
699
700 //#define TEST_TLB
701
702 INLINE int translate_address(i386_state *cpustate, int pl, int type, UINT32 *address, UINT32 *error)
703 {
704         if(!(cpustate->cr[0] & 0x80000000)) // Some (very few) old OS's won't work with this
705                 return TRUE;
706
707         const vtlb_entry *table = vtlb_table(cpustate->vtlb);
708         UINT32 index = *address >> 12;
709         vtlb_entry entry = table[index];
710         if(type == TRANSLATE_FETCH)
711                 type = TRANSLATE_READ;
712         if(pl == 3)
713                 type |= TRANSLATE_USER_MASK;
714 #ifdef TEST_TLB
715         UINT32 test_addr = *address;
716 #endif
717
718         if(!(entry & VTLB_FLAG_VALID) || ((type & TRANSLATE_WRITE) && !(entry & VTLB_FLAG_DIRTY)))
719         {
720                 if(!i386_translate_address(cpustate, type, address, &entry))
721                 {
722                         *error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((cpustate->CPL == 3) ? 4 : 0);
723                         if(entry)
724                                 *error |= 1;
725                         return FALSE;
726                 }
727                 vtlb_dynload(cpustate->vtlb, index, *address, entry);
728                 return TRUE;
729         }
730         if(!(entry & (1 << type)))
731         {
732                 *error = ((type & TRANSLATE_WRITE) ? 2 : 0) | ((cpustate->CPL == 3) ? 4 : 0) | 1;
733                 return FALSE;
734         }
735         *address = (entry & 0xfffff000) | (*address & 0xfff);
736 #ifdef TEST_TLB
737         int test_ret = i386_translate_address(cpustate, type | TRANSLATE_DEBUG_MASK, &test_addr, NULL);
738         if(!test_ret || (test_addr != *address))
739                 logerror("TLB-PTE mismatch! %06X %06X %06x\n", *address, test_addr, cpustate->pc);
740 #endif
741         return TRUE;
742 }
743
744 INLINE void CHANGE_PC(i386_state *cpustate, UINT32 pc)
745 {
746         cpustate->pc = i386_translate(cpustate, CS, pc, -1 );
747 }
748
749 INLINE void NEAR_BRANCH(i386_state *cpustate, INT32 offs)
750 {
751         /* TODO: limit */
752         cpustate->eip += offs;
753         cpustate->pc += offs;
754 }
755
756 INLINE UINT8 FETCH(i386_state *cpustate)
757 {
758         UINT8 value;
759         UINT32 address = cpustate->pc, error;
760
761         if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_FETCH,&address,&error))
762                 PF_THROW(error);
763
764         value = cpustate->program->read_data8(address & cpustate->a20_mask);
765 #ifdef DEBUG_MISSING_OPCODE
766         cpustate->opcode_bytes[cpustate->opcode_bytes_length] = value;
767         cpustate->opcode_bytes_length = (cpustate->opcode_bytes_length + 1) & 15;
768 #endif
769         cpustate->eip++;
770         cpustate->pc++;
771         return value;
772 }
773 INLINE UINT16 FETCH16(i386_state *cpustate)
774 {
775         UINT16 value;
776         UINT32 address = cpustate->pc, error;
777
778         if( address & 0x1 ) {       /* Unaligned read */
779                 value = (FETCH(cpustate) << 0);
780                 value |= (FETCH(cpustate) << 8);
781         } else {
782                 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_FETCH,&address,&error))
783                         PF_THROW(error);
784                 address &= cpustate->a20_mask;
785                 value = cpustate->program->read_data16(address);
786                 cpustate->eip += 2;
787                 cpustate->pc += 2;
788         }
789         return value;
790 }
791 INLINE UINT32 FETCH32(i386_state *cpustate)
792 {
793         UINT32 value;
794         UINT32 address = cpustate->pc, error;
795
796         if( cpustate->pc & 0x3 ) {      /* Unaligned read */
797                 value = (FETCH(cpustate) << 0);
798                 value |= (FETCH(cpustate) << 8);
799                 value |= (FETCH(cpustate) << 16);
800                 value |= (FETCH(cpustate) << 24);
801         } else {
802                 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_FETCH,&address,&error))
803                         PF_THROW(error);
804
805                 address &= cpustate->a20_mask;
806                 value = cpustate->program->read_data32(address);
807                 cpustate->eip += 4;
808                 cpustate->pc += 4;
809         }
810         return value;
811 }
812
813 INLINE UINT8 READ8(i386_state *cpustate,UINT32 ea)
814 {
815         UINT32 address = ea, error;
816
817         if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address, &error))
818                 PF_THROW(error);
819
820         address &= cpustate->a20_mask;
821         return cpustate->program->read_data8(address);
822 }
823 INLINE UINT16 READ16(i386_state *cpustate,UINT32 ea)
824 {
825         UINT16 value;
826         UINT32 address = ea, error;
827
828         if( ea & 0x1 ) {        /* Unaligned read */
829                 value = (READ8( cpustate, address+0 ) << 0);
830                 value |= (READ8( cpustate, address+1 ) << 8);
831         } else {
832                 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address,&error))
833                         PF_THROW(error);
834
835                 address &= cpustate->a20_mask;
836                 value = cpustate->program->read_data16( address );
837         }
838         return value;
839 }
840 INLINE UINT32 READ32(i386_state *cpustate,UINT32 ea)
841 {
842         UINT32 value;
843         UINT32 address = ea, error;
844
845         if( ea & 0x3 ) {        /* Unaligned read */
846                 value = (READ8( cpustate, address+0 ) << 0);
847                 value |= (READ8( cpustate, address+1 ) << 8);
848                 value |= (READ8( cpustate, address+2 ) << 16),
849                 value |= (READ8( cpustate, address+3 ) << 24);
850         } else {
851                 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address,&error))
852                         PF_THROW(error);
853
854                 address &= cpustate->a20_mask;
855                 value = cpustate->program->read_data32( address );
856         }
857         return value;
858 }
859
860 INLINE UINT64 READ64(i386_state *cpustate,UINT32 ea)
861 {
862         UINT64 value;
863         UINT32 address = ea, error;
864
865         if( ea & 0x7 ) {        /* Unaligned read */
866                 value = (((UINT64) READ8( cpustate, address+0 )) << 0);
867                 value |= (((UINT64) READ8( cpustate, address+1 )) << 8);
868                 value |= (((UINT64) READ8( cpustate, address+2 )) << 16);
869                 value |= (((UINT64) READ8( cpustate, address+3 )) << 24);
870                 value |= (((UINT64) READ8( cpustate, address+4 )) << 32);
871                 value |= (((UINT64) READ8( cpustate, address+5 )) << 40);
872                 value |= (((UINT64) READ8( cpustate, address+6 )) << 48);
873                 value |= (((UINT64) READ8( cpustate, address+7 )) << 56);
874         } else {
875                 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_READ,&address,&error))
876                         PF_THROW(error);
877
878                 address &= cpustate->a20_mask;
879                 value = (((UINT64) cpustate->program->read_data32( address+0 )) << 0);
880                 value |= (((UINT64) cpustate->program->read_data32( address+4 )) << 32);
881         }
882         return value;
883 }
884 INLINE UINT8 READ8PL0(i386_state *cpustate,UINT32 ea)
885 {
886         UINT32 address = ea, error;
887
888         if(!translate_address(cpustate,0,TRANSLATE_READ,&address,&error))
889                 PF_THROW(error);
890
891         address &= cpustate->a20_mask;
892         return cpustate->program->read_data8(address);
893 }
894 INLINE UINT16 READ16PL0(i386_state *cpustate,UINT32 ea)
895 {
896         UINT16 value;
897         UINT32 address = ea, error;
898
899         if( ea & 0x1 ) {        /* Unaligned read */
900                 value = (READ8PL0( cpustate, address+0 ) << 0);
901                 value |= (READ8PL0( cpustate, address+1 ) << 8);
902         } else {
903                 if(!translate_address(cpustate,0,TRANSLATE_READ,&address,&error))
904                         PF_THROW(error);
905
906                 address &= cpustate->a20_mask;
907                 value = cpustate->program->read_data16( address );
908         }
909         return value;
910 }
911
912 INLINE UINT32 READ32PL0(i386_state *cpustate,UINT32 ea)
913 {
914         UINT32 value;
915         UINT32 address = ea, error;
916
917         if( ea & 0x3 ) {        /* Unaligned read */
918                 value = (READ8PL0( cpustate, address+0 ) << 0);
919                 value |= (READ8PL0( cpustate, address+1 ) << 8);
920                 value |= (READ8PL0( cpustate, address+2 ) << 16);
921                 value |= (READ8PL0( cpustate, address+3 ) << 24);
922         } else {
923                 if(!translate_address(cpustate,0,TRANSLATE_READ,&address,&error))
924                         PF_THROW(error);
925
926                 address &= cpustate->a20_mask;
927                 value = cpustate->program->read_data32( address );
928         }
929         return value;
930 }
931
932 INLINE void WRITE_TEST(i386_state *cpustate,UINT32 ea)
933 {
934         UINT32 address = ea, error;
935         if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
936                 PF_THROW(error);
937 }
938
939 INLINE void WRITE8(i386_state *cpustate,UINT32 ea, UINT8 value)
940 {
941         UINT32 address = ea, error;
942
943         if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
944                 PF_THROW(error);
945
946         address &= cpustate->a20_mask;
947         cpustate->program->write_data8(address, value);
948 }
949 INLINE void WRITE16(i386_state *cpustate,UINT32 ea, UINT16 value)
950 {
951         UINT32 address = ea, error;
952
953         if( ea & 0x1 ) {        /* Unaligned write */
954                 WRITE8( cpustate, address+0, value & 0xff );
955                 WRITE8( cpustate, address+1, (value >> 8) & 0xff );
956         } else {
957                 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
958                         PF_THROW(error);
959
960                 address &= cpustate->a20_mask;
961                 cpustate->program->write_data16(address, value);
962         }
963 }
964 INLINE void WRITE32(i386_state *cpustate,UINT32 ea, UINT32 value)
965 {
966         UINT32 address = ea, error;
967
968         if( ea & 0x3 ) {        /* Unaligned write */
969                 WRITE8( cpustate, address+0, value & 0xff );
970                 WRITE8( cpustate, address+1, (value >> 8) & 0xff );
971                 WRITE8( cpustate, address+2, (value >> 16) & 0xff );
972                 WRITE8( cpustate, address+3, (value >> 24) & 0xff );
973         } else {
974                 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
975                         PF_THROW(error);
976
977                 ea &= cpustate->a20_mask;
978                 cpustate->program->write_data32(address, value);
979         }
980 }
981
982 INLINE void WRITE64(i386_state *cpustate,UINT32 ea, UINT64 value)
983 {
984         UINT32 address = ea, error;
985
986         if( ea & 0x7 ) {        /* Unaligned write */
987                 WRITE8( cpustate, address+0, value & 0xff );
988                 WRITE8( cpustate, address+1, (value >> 8) & 0xff );
989                 WRITE8( cpustate, address+2, (value >> 16) & 0xff );
990                 WRITE8( cpustate, address+3, (value >> 24) & 0xff );
991                 WRITE8( cpustate, address+4, (value >> 32) & 0xff );
992                 WRITE8( cpustate, address+5, (value >> 40) & 0xff );
993                 WRITE8( cpustate, address+6, (value >> 48) & 0xff );
994                 WRITE8( cpustate, address+7, (value >> 56) & 0xff );
995         } else {
996                 if(!translate_address(cpustate,cpustate->CPL,TRANSLATE_WRITE,&address,&error))
997                         PF_THROW(error);
998
999                 ea &= cpustate->a20_mask;
1000                 cpustate->program->write_data32(address+0, value & 0xffffffff);
1001                 cpustate->program->write_data32(address+4, (value >> 32) & 0xffffffff);
1002         }
1003 }
1004
1005 /***********************************************************************************/
1006
1007 INLINE UINT8 OR8(i386_state *cpustate,UINT8 dst, UINT8 src)
1008 {
1009         UINT8 res = dst | src;
1010         cpustate->CF = cpustate->OF = 0;
1011         SetSZPF8(res);
1012         return res;
1013 }
1014 INLINE UINT16 OR16(i386_state *cpustate,UINT16 dst, UINT16 src)
1015 {
1016         UINT16 res = dst | src;
1017         cpustate->CF = cpustate->OF = 0;
1018         SetSZPF16(res);
1019         return res;
1020 }
1021 INLINE UINT32 OR32(i386_state *cpustate,UINT32 dst, UINT32 src)
1022 {
1023         UINT32 res = dst | src;
1024         cpustate->CF = cpustate->OF = 0;
1025         SetSZPF32(res);
1026         return res;
1027 }
1028
1029 INLINE UINT8 AND8(i386_state *cpustate,UINT8 dst, UINT8 src)
1030 {
1031         UINT8 res = dst & src;
1032         cpustate->CF = cpustate->OF = 0;
1033         SetSZPF8(res);
1034         return res;
1035 }
1036 INLINE UINT16 AND16(i386_state *cpustate,UINT16 dst, UINT16 src)
1037 {
1038         UINT16 res = dst & src;
1039         cpustate->CF = cpustate->OF = 0;
1040         SetSZPF16(res);
1041         return res;
1042 }
1043 INLINE UINT32 AND32(i386_state *cpustate,UINT32 dst, UINT32 src)
1044 {
1045         UINT32 res = dst & src;
1046         cpustate->CF = cpustate->OF = 0;
1047         SetSZPF32(res);
1048         return res;
1049 }
1050
1051 INLINE UINT8 XOR8(i386_state *cpustate,UINT8 dst, UINT8 src)
1052 {
1053         UINT8 res = dst ^ src;
1054         cpustate->CF = cpustate->OF = 0;
1055         SetSZPF8(res);
1056         return res;
1057 }
1058 INLINE UINT16 XOR16(i386_state *cpustate,UINT16 dst, UINT16 src)
1059 {
1060         UINT16 res = dst ^ src;
1061         cpustate->CF = cpustate->OF = 0;
1062         SetSZPF16(res);
1063         return res;
1064 }
1065 INLINE UINT32 XOR32(i386_state *cpustate,UINT32 dst, UINT32 src)
1066 {
1067         UINT32 res = dst ^ src;
1068         cpustate->CF = cpustate->OF = 0;
1069         SetSZPF32(res);
1070         return res;
1071 }
1072
1073 #define SUB8(cpu, dst, src) SBB8(cpu, dst, src, 0)
1074 INLINE UINT8 SBB8(i386_state *cpustate,UINT8 dst, UINT8 src, UINT8 b)
1075 {
1076         UINT16 res = (UINT16)dst - (UINT16)src - (UINT8)b;
1077         SetCF8(res);
1078         SetOF_Sub8(res,src,dst);
1079         SetAF(res,src,dst);
1080         SetSZPF8(res);
1081         return (UINT8)res;
1082 }
1083
1084 #define SUB16(cpu, dst, src) SBB16(cpu, dst, src, 0)
1085 INLINE UINT16 SBB16(i386_state *cpustate,UINT16 dst, UINT16 src, UINT16 b)
1086 {
1087         UINT32 res = (UINT32)dst - (UINT32)src - (UINT32)b;
1088         SetCF16(res);
1089         SetOF_Sub16(res,src,dst);
1090         SetAF(res,src,dst);
1091         SetSZPF16(res);
1092         return (UINT16)res;
1093 }
1094
1095 #define SUB32(cpu, dst, src) SBB32(cpu, dst, src, 0)
1096 INLINE UINT32 SBB32(i386_state *cpustate,UINT32 dst, UINT32 src, UINT32 b)
1097 {
1098         UINT64 res = (UINT64)dst - (UINT64)src - (UINT64) b;
1099         SetCF32(res);
1100         SetOF_Sub32(res,src,dst);
1101         SetAF(res,src,dst);
1102         SetSZPF32(res);
1103         return (UINT32)res;
1104 }
1105
1106 #define ADD8(cpu, dst, src) ADC8(cpu, dst, src, 0)
1107 INLINE UINT8 ADC8(i386_state *cpustate,UINT8 dst, UINT8 src, UINT8 c)
1108 {
1109         UINT16 res = (UINT16)dst + (UINT16)src + (UINT16)c;
1110         SetCF8(res);
1111         SetOF_Add8(res,src,dst);
1112         SetAF(res,src,dst);
1113         SetSZPF8(res);
1114         return (UINT8)res;
1115 }
1116
1117 #define ADD16(cpu, dst, src) ADC16(cpu, dst, src, 0)
1118 INLINE UINT16 ADC16(i386_state *cpustate,UINT16 dst, UINT16 src, UINT8 c)
1119 {
1120         UINT32 res = (UINT32)dst + (UINT32)src + (UINT32)c;
1121         SetCF16(res);
1122         SetOF_Add16(res,src,dst);
1123         SetAF(res,src,dst);
1124         SetSZPF16(res);
1125         return (UINT16)res;
1126 }
1127
1128 #define ADD32(cpu, dst, src) ADC32(cpu, dst, src, 0)
1129 INLINE UINT32 ADC32(i386_state *cpustate,UINT32 dst, UINT32 src, UINT32 c)
1130 {
1131         UINT64 res = (UINT64)dst + (UINT64)src + (UINT64) c;
1132         SetCF32(res);
1133         SetOF_Add32(res,src,dst);
1134         SetAF(res,src,dst);
1135         SetSZPF32(res);
1136         return (UINT32)res;
1137 }
1138
1139 INLINE UINT8 INC8(i386_state *cpustate,UINT8 dst)
1140 {
1141         UINT16 res = (UINT16)dst + 1;
1142         SetOF_Add8(res,1,dst);
1143         SetAF(res,1,dst);
1144         SetSZPF8(res);
1145         return (UINT8)res;
1146 }
1147 INLINE UINT16 INC16(i386_state *cpustate,UINT16 dst)
1148 {
1149         UINT32 res = (UINT32)dst + 1;
1150         SetOF_Add16(res,1,dst);
1151         SetAF(res,1,dst);
1152         SetSZPF16(res);
1153         return (UINT16)res;
1154 }
1155 INLINE UINT32 INC32(i386_state *cpustate,UINT32 dst)
1156 {
1157         UINT64 res = (UINT64)dst + 1;
1158         SetOF_Add32(res,1,dst);
1159         SetAF(res,1,dst);
1160         SetSZPF32(res);
1161         return (UINT32)res;
1162 }
1163
1164 INLINE UINT8 DEC8(i386_state *cpustate,UINT8 dst)
1165 {
1166         UINT16 res = (UINT16)dst - 1;
1167         SetOF_Sub8(res,1,dst);
1168         SetAF(res,1,dst);
1169         SetSZPF8(res);
1170         return (UINT8)res;
1171 }
1172 INLINE UINT16 DEC16(i386_state *cpustate,UINT16 dst)
1173 {
1174         UINT32 res = (UINT32)dst - 1;
1175         SetOF_Sub16(res,1,dst);
1176         SetAF(res,1,dst);
1177         SetSZPF16(res);
1178         return (UINT16)res;
1179 }
1180 INLINE UINT32 DEC32(i386_state *cpustate,UINT32 dst)
1181 {
1182         UINT64 res = (UINT64)dst - 1;
1183         SetOF_Sub32(res,1,dst);
1184         SetAF(res,1,dst);
1185         SetSZPF32(res);
1186         return (UINT32)res;
1187 }
1188
1189
1190
1191 INLINE void PUSH16(i386_state *cpustate,UINT16 value)
1192 {
1193         UINT32 ea, new_esp;
1194         if( STACK_32BIT ) {
1195                 new_esp = REG32(ESP) - 2;
1196                 ea = i386_translate(cpustate, SS, new_esp, 1);
1197                 WRITE16(cpustate, ea, value );
1198                 REG32(ESP) = new_esp;
1199         } else {
1200                 new_esp = (REG16(SP) - 2) & 0xffff;
1201                 ea = i386_translate(cpustate, SS, new_esp, 1);
1202                 WRITE16(cpustate, ea, value );
1203                 REG16(SP) = new_esp;
1204         }
1205 }
1206 INLINE void PUSH32(i386_state *cpustate,UINT32 value)
1207 {
1208         UINT32 ea, new_esp;
1209         if( STACK_32BIT ) {
1210                 new_esp = REG32(ESP) - 4;
1211                 ea = i386_translate(cpustate, SS, new_esp, 1);
1212                 WRITE32(cpustate, ea, value );
1213                 REG32(ESP) = new_esp;
1214         } else {
1215                 new_esp = (REG16(SP) - 4) & 0xffff;
1216                 ea = i386_translate(cpustate, SS, new_esp, 1);
1217                 WRITE32(cpustate, ea, value );
1218                 REG16(SP) = new_esp;
1219         }
1220 }
1221 INLINE void PUSH8(i386_state *cpustate,UINT8 value)
1222 {
1223         if( cpustate->operand_size ) {
1224                 PUSH32(cpustate,(INT32)(INT8)value);
1225         } else {
1226                 PUSH16(cpustate,(INT16)(INT8)value);
1227         }
1228 }
1229
1230 INLINE UINT8 POP8(i386_state *cpustate)
1231 {
1232         UINT8 value;
1233         UINT32 ea, new_esp;
1234         if( STACK_32BIT ) {
1235                 new_esp = REG32(ESP) + 1;
1236                 ea = i386_translate(cpustate, SS, new_esp - 1, 0);
1237                 value = READ8(cpustate, ea );
1238                 REG32(ESP) = new_esp;
1239         } else {
1240                 new_esp = REG16(SP) + 1;
1241                 ea = i386_translate(cpustate, SS, (new_esp - 1) & 0xffff, 0);
1242                 value = READ8(cpustate, ea );
1243                 REG16(SP) = new_esp;
1244         }
1245         return value;
1246 }
1247 INLINE UINT16 POP16(i386_state *cpustate)
1248 {
1249         UINT16 value;
1250         UINT32 ea, new_esp;
1251         if( STACK_32BIT ) {
1252                 new_esp = REG32(ESP) + 2;
1253                 ea = i386_translate(cpustate, SS, new_esp - 2, 0);
1254                 value = READ16(cpustate, ea );
1255                 REG32(ESP) = new_esp;
1256         } else {
1257                 new_esp = REG16(SP) + 2;
1258                 ea = i386_translate(cpustate, SS, (new_esp - 2) & 0xffff, 0);
1259                 value = READ16(cpustate, ea );
1260                 REG16(SP) = new_esp;
1261         }
1262         return value;
1263 }
1264 INLINE UINT32 POP32(i386_state *cpustate)
1265 {
1266         UINT32 value;
1267         UINT32 ea, new_esp;
1268         if( STACK_32BIT ) {
1269                 new_esp = REG32(ESP) + 4;
1270                 ea = i386_translate(cpustate, SS, new_esp - 4, 0);
1271                 value = READ32(cpustate, ea );
1272                 REG32(ESP) = new_esp;
1273         } else {
1274                 new_esp = REG16(SP) + 4;
1275                 ea = i386_translate(cpustate, SS, (new_esp - 4) & 0xffff, 0);
1276                 value = READ32(cpustate, ea );
1277                 REG16(SP) = new_esp;
1278         }
1279         return value;
1280 }
1281
1282 INLINE void BUMP_SI(i386_state *cpustate,int adjustment)
1283 {
1284         if ( cpustate->address_size )
1285                 REG32(ESI) += ((cpustate->DF) ? -adjustment : +adjustment);
1286         else
1287                 REG16(SI) += ((cpustate->DF) ? -adjustment : +adjustment);
1288 }
1289
1290 INLINE void BUMP_DI(i386_state *cpustate,int adjustment)
1291 {
1292         if ( cpustate->address_size )
1293                 REG32(EDI) += ((cpustate->DF) ? -adjustment : +adjustment);
1294         else
1295                 REG16(DI) += ((cpustate->DF) ? -adjustment : +adjustment);
1296 }
1297
1298
1299
1300 /***********************************************************************************
1301     I/O ACCESS
1302 ***********************************************************************************/
1303
1304 INLINE void check_ioperm(i386_state *cpustate, offs_t port, UINT8 mask)
1305 {
1306         UINT8 IOPL, map;
1307         UINT16 IOPB;
1308         UINT32 address;
1309
1310         if(!PROTECTED_MODE)
1311                 return;
1312
1313         IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
1314         if(!V8086_MODE && (cpustate->CPL <= IOPL))
1315                 return;
1316
1317         if((cpustate->task.limit < 0x67) || ((cpustate->task.flags & 0xd) != 9))
1318                 FAULT_THROW(FAULT_GP,0);
1319
1320         address = cpustate->task.base;
1321         IOPB = READ16PL0(cpustate, address+0x66);
1322         if((IOPB+(port/8)) > cpustate->task.limit)
1323                 FAULT_THROW(FAULT_GP,0);
1324
1325         map = READ8PL0(cpustate, address+IOPB+(port/8));
1326         map >>= (port%8);
1327         if(map & mask)
1328                 FAULT_THROW(FAULT_GP,0);
1329 }
1330
1331 INLINE UINT8 READPORT8(i386_state *cpustate, offs_t port)
1332 {
1333         check_ioperm(cpustate, port, 1);
1334         return cpustate->io->read_io8(port);
1335 }
1336
1337 INLINE void WRITEPORT8(i386_state *cpustate, offs_t port, UINT8 value)
1338 {
1339         check_ioperm(cpustate, port, 1);
1340         cpustate->io->write_io8(port, value);
1341 }
1342
1343 INLINE UINT16 READPORT16(i386_state *cpustate, offs_t port)
1344 {
1345         if (port & 1)
1346         {
1347                 UINT16 value = READPORT8(cpustate, port);
1348                 value |= (READPORT8(cpustate, port + 1) << 8);
1349                 return value;
1350         }
1351         else
1352         {
1353                 check_ioperm(cpustate, port, 3);
1354                 return cpustate->io->read_io16(port);
1355         }
1356 }
1357
1358 INLINE void WRITEPORT16(i386_state *cpustate, offs_t port, UINT16 value)
1359 {
1360         if (port & 1)
1361         {
1362                 WRITEPORT8(cpustate, port, value & 0xff);
1363                 WRITEPORT8(cpustate, port + 1, (value >> 8) & 0xff);
1364         }
1365         else
1366         {
1367                 check_ioperm(cpustate, port, 3);
1368                 cpustate->io->write_io16(port, value);
1369         }
1370 }
1371
1372 INLINE UINT32 READPORT32(i386_state *cpustate, offs_t port)
1373 {
1374         if (port & 3)
1375         {
1376                 UINT32 value = READPORT8(cpustate, port);
1377                 value |= (READPORT8(cpustate, port + 1) << 8);
1378                 value |= (READPORT8(cpustate, port + 2) << 16);
1379                 value |= (READPORT8(cpustate, port + 3) << 24);
1380                 return value;
1381         }
1382         else
1383         {
1384                 check_ioperm(cpustate, port, 0xf);
1385                 return cpustate->io->read_io32(port);
1386         }
1387 }
1388
1389 INLINE void WRITEPORT32(i386_state *cpustate, offs_t port, UINT32 value)
1390 {
1391         if (port & 3)
1392         {
1393                 WRITEPORT8(cpustate, port, value & 0xff);
1394                 WRITEPORT8(cpustate, port + 1, (value >> 8) & 0xff);
1395                 WRITEPORT8(cpustate, port + 2, (value >> 16) & 0xff);
1396                 WRITEPORT8(cpustate, port + 3, (value >> 24) & 0xff);
1397         }
1398         else
1399         {
1400                 check_ioperm(cpustate, port, 0xf);
1401                 cpustate->io->write_io32(port, value);
1402         }
1403 }
1404
1405 /***********************************************************************************
1406     MSR ACCESS
1407 ***********************************************************************************/
1408
1409 // Pentium MSR handling
1410 UINT64 pentium_msr_read(i386_state *cpustate, UINT32 offset,UINT8 *valid_msr)
1411 {
1412         switch(offset)
1413         {
1414         // Machine Check Exception (TODO)
1415         case 0x00:
1416                 *valid_msr = 1;
1417                 popmessage("RDMSR: Reading P5_MC_ADDR");
1418                 return 0;
1419         case 0x01:
1420                 *valid_msr = 1;
1421                 popmessage("RDMSR: Reading P5_MC_TYPE");
1422                 return 0;
1423         // Time Stamp Counter
1424         case 0x10:
1425                 *valid_msr = 1;
1426                 popmessage("RDMSR: Reading TSC");
1427                 return cpustate->tsc;
1428         // Event Counters (TODO)
1429         case 0x11:  // CESR
1430                 *valid_msr = 1;
1431                 popmessage("RDMSR: Reading CESR");
1432                 return 0;
1433         case 0x12:  // CTR0
1434                 *valid_msr = 1;
1435                 return cpustate->perfctr[0];
1436         case 0x13:  // CTR1
1437                 *valid_msr = 1;
1438                 return cpustate->perfctr[1];
1439         default:
1440                 if(!(offset & ~0xf)) // 2-f are test registers
1441                 {
1442                         *valid_msr = 1;
1443                         logerror("RDMSR: Reading test MSR %x", offset);
1444                         return 0;
1445                 }
1446                 logerror("RDMSR: invalid P5 MSR read %08x at %08x\n",offset,cpustate->pc-2);
1447                 *valid_msr = 0;
1448                 return 0;
1449         }
1450         return -1;
1451 }
1452
1453 void pentium_msr_write(i386_state *cpustate, UINT32 offset, UINT64 data, UINT8 *valid_msr)
1454 {
1455         switch(offset)
1456         {
1457         // Machine Check Exception (TODO)
1458         case 0x00:
1459                 popmessage("WRMSR: Writing P5_MC_ADDR");
1460                 *valid_msr = 1;
1461                 break;
1462         case 0x01:
1463                 popmessage("WRMSR: Writing P5_MC_TYPE");
1464                 *valid_msr = 1;
1465                 break;
1466         // Time Stamp Counter
1467         case 0x10:
1468                 cpustate->tsc = data;
1469                 popmessage("WRMSR: Writing to TSC");
1470                 *valid_msr = 1;
1471                 break;
1472         // Event Counters (TODO)
1473         case 0x11:  // CESR
1474                 popmessage("WRMSR: Writing to CESR");
1475                 *valid_msr = 1;
1476                 break;
1477         case 0x12:  // CTR0
1478                 cpustate->perfctr[0] = data;
1479                 *valid_msr = 1;
1480                 break;
1481         case 0x13:  // CTR1
1482                 cpustate->perfctr[1] = data;
1483                 *valid_msr = 1;
1484                 break;
1485         default:
1486                 if(!(offset & ~0xf)) // 2-f are test registers
1487                 {
1488                         *valid_msr = 1;
1489                         logerror("WRMSR: Writing test MSR %x", offset);
1490                         break;
1491                 }
1492                 logerror("WRMSR: invalid MSR write %08x (%08x%08x) at %08x\n",offset,(UINT32)(data >> 32),(UINT32)data,cpustate->pc-2);
1493                 *valid_msr = 0;
1494                 break;
1495         }
1496 }
1497
1498 // P6 (Pentium Pro, Pentium II, Pentium III) MSR handling
1499 UINT64 p6_msr_read(i386_state *cpustate, UINT32 offset,UINT8 *valid_msr)
1500 {
1501         switch(offset)
1502         {
1503         // Machine Check Exception (TODO)
1504         case 0x00:
1505                 *valid_msr = 1;
1506                 popmessage("RDMSR: Reading P5_MC_ADDR");
1507                 return 0;
1508         case 0x01:
1509                 *valid_msr = 1;
1510                 popmessage("RDMSR: Reading P5_MC_TYPE");
1511                 return 0;
1512         // Time Stamp Counter
1513         case 0x10:
1514                 *valid_msr = 1;
1515                 popmessage("RDMSR: Reading TSC");
1516                 return cpustate->tsc;
1517         // Performance Counters (TODO)
1518         case 0xc1:  // PerfCtr0
1519                 *valid_msr = 1;
1520                 return cpustate->perfctr[0];
1521         case 0xc2:  // PerfCtr1
1522                 *valid_msr = 1;
1523                 return cpustate->perfctr[1];
1524         default:
1525                 logerror("RDMSR: unimplemented register called %08x at %08x\n",offset,cpustate->pc-2);
1526                 *valid_msr = 1;
1527                 return 0;
1528         }
1529         return -1;
1530 }
1531
1532 void p6_msr_write(i386_state *cpustate, UINT32 offset, UINT64 data, UINT8 *valid_msr)
1533 {
1534         switch(offset)
1535         {
1536         // Time Stamp Counter
1537         case 0x10:
1538                 cpustate->tsc = data;
1539                 popmessage("WRMSR: Writing to TSC");
1540                 *valid_msr = 1;
1541                 break;
1542         // Performance Counters (TODO)
1543         case 0xc1:  // PerfCtr0
1544                 cpustate->perfctr[0] = data;
1545                 *valid_msr = 1;
1546                 break;
1547         case 0xc2:  // PerfCtr1
1548                 cpustate->perfctr[1] = data;
1549                 *valid_msr = 1;
1550                 break;
1551         default:
1552                 logerror("WRMSR: unimplemented register called %08x (%08x%08x) at %08x\n",offset,(UINT32)(data >> 32),(UINT32)data,cpustate->pc-2);
1553                 *valid_msr = 1;
1554                 break;
1555         }
1556 }
1557
1558 // PIV (Pentium 4+)
1559 UINT64 piv_msr_read(i386_state *cpustate, UINT32 offset,UINT8 *valid_msr)
1560 {
1561         switch(offset)
1562         {
1563         default:
1564                 logerror("RDMSR: unimplemented register called %08x at %08x\n",offset,cpustate->pc-2);
1565                 *valid_msr = 1;
1566                 return 0;
1567         }
1568         return -1;
1569 }
1570
1571 void piv_msr_write(i386_state *cpustate, UINT32 offset, UINT64 data, UINT8 *valid_msr)
1572 {
1573         switch(offset)
1574         {
1575         default:
1576                 logerror("WRMSR: unimplemented register called %08x (%08x%08x) at %08x\n",offset,(UINT32)(data >> 32),(UINT32)data,cpustate->pc-2);
1577                 *valid_msr = 1;
1578                 break;
1579         }
1580 }
1581
1582 INLINE UINT64 MSR_READ(i386_state *cpustate, UINT32 offset,UINT8 *valid_msr)
1583 {
1584         UINT64 res;
1585         UINT8 cpu_type = (cpustate->cpu_version >> 8) & 0x0f;
1586
1587         *valid_msr = 0;
1588
1589         switch(cpu_type)
1590         {
1591         case 5:  // Pentium
1592                 res = pentium_msr_read(cpustate,offset,valid_msr);
1593                 break;
1594         case 6:  // Pentium Pro, Pentium II, Pentium III
1595                 res = p6_msr_read(cpustate,offset,valid_msr);
1596                 break;
1597         case 15:  // Pentium 4+
1598                 res = piv_msr_read(cpustate,offset,valid_msr);
1599                 break;
1600         default:
1601                 res = 0;
1602                 break;
1603         }
1604
1605         return res;
1606 }
1607
1608 INLINE void MSR_WRITE(i386_state *cpustate, UINT32 offset, UINT64 data, UINT8 *valid_msr)
1609 {
1610         *valid_msr = 0;
1611         UINT8 cpu_type = (cpustate->cpu_version >> 8) & 0x0f;
1612
1613         switch(cpu_type)
1614         {
1615         case 5:  // Pentium
1616                 pentium_msr_write(cpustate,offset,data,valid_msr);
1617                 break;
1618         case 6:  // Pentium Pro, Pentium II, Pentium III
1619                 p6_msr_write(cpustate,offset,data,valid_msr);
1620                 break;
1621         case 15:  // Pentium 4+
1622                 piv_msr_write(cpustate,offset,data,valid_msr);
1623                 break;
1624         }
1625 }
1626
1627 #endif /* __I386_H__ */