OSDN Git Service

9fd57715b4d401aa5cead7efcf96b78fc08960cf
[csp-qt/common_source_project-fm7.git] / source / src / vm / libcpu_newdev / libcpu_i386 / i386_opdef.cpp
1 // license:BSD-3-Clause
2 // copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett
3 /*
4     Intel 386 emulator
5
6     Written by Ville Linde
7
8     Currently supports:
9         Intel 386
10         Intel 486
11         Intel Pentium
12         Cyrix MediaGX
13         Intel Pentium MMX
14         Intel Pentium Pro
15         Intel Pentium II
16         Intel Pentium III
17         Intel Pentium 4
18 */
19
20 #include "./i386_opdef.h"
21 #include "./i386ops.h"
22
23 /* seems to be defined on mingw-gcc */
24 #undef i386
25
26 #define FAULT(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,0,error); return;}
27 #define FAULT_EXP(fault,error) {cpustate->ext = 1; i386_trap_with_error(fault,0,trap_level+1,error); return;}
28
29 /*************************************************************************/
30
31 UINT32 I386_OPS_BASE::i386_load_protected_mode_segment( I386_SREG *seg, UINT64 *desc )
32 {
33         UINT32 v1,v2;
34         UINT32 base, limit;
35         int entry;
36
37         if(!seg->selector)
38         {
39                 seg->flags = 0;
40                 seg->base = 0;
41                 seg->limit = 0;
42                 seg->d = 0;
43                 seg->valid = false;
44                 return 0;
45         }
46
47         if ( seg->selector & 0x4 )
48         {
49                 base = cpustate->ldtr.base;
50                 limit = cpustate->ldtr.limit;
51         } else {
52                 base = cpustate->gdtr.base;
53                 limit = cpustate->gdtr.limit;
54         }
55
56         entry = seg->selector & ~0x7;
57         if ((limit == 0) || ((UINT32)(entry + 7) > limit))
58                 return 0;
59
60         v1 = READ32PL0(base + entry );
61         v2 = READ32PL0(base + entry + 4 );
62
63         seg->flags = (v2 >> 8) & 0xf0ff;
64         seg->base = (v2 & 0xff000000) | ((v2 & 0xff) << 16) | ((v1 >> 16) & 0xffff);
65         seg->limit = (v2 & 0xf0000) | (v1 & 0xffff);
66         if (seg->flags & 0x8000)
67                 seg->limit = (seg->limit << 12) | 0xfff;
68         seg->d = (seg->flags & 0x4000) ? 1 : 0;
69         seg->valid = true;
70
71         if(desc)
72                 *desc = ((UINT64)v2<<32)|v1;
73         return 1;
74 }
75
76 void I386_OPS_BASE::i386_load_call_gate(I386_CALL_GATE *gate)
77 {
78         UINT32 v1,v2;
79         UINT32 base,limit;
80         int entry;
81
82         if ( gate->segment & 0x4 )
83         {
84                 base = cpustate->ldtr.base;
85                 limit = cpustate->ldtr.limit;
86         } else {
87                 base = cpustate->gdtr.base;
88                 limit = cpustate->gdtr.limit;
89         }
90
91         entry = gate->segment & ~0x7;
92         if ((limit == 0) || ((UINT32)(entry + 7) > limit))
93                 return;
94
95         v1 = READ32PL0(base + entry );
96         v2 = READ32PL0(base + entry + 4 );
97
98         /* Note that for task gates, offset and dword_count are not used */
99         gate->selector = (v1 >> 16) & 0xffff;
100         gate->offset = (v1 & 0x0000ffff) | (v2 & 0xffff0000);
101         gate->ar = (v2 >> 8) & 0xff;
102         gate->dword_count = v2 & 0x001f;
103         gate->present = (gate->ar >> 7) & 0x01;
104         gate->dpl = (gate->ar >> 5) & 0x03;
105 }
106
107 void I386_OPS_BASE::i386_set_descriptor_accessed( UINT16 selector)
108 {
109         // assume the selector is valid, we don't need to check it again
110         UINT32 base, addr;
111         UINT8 rights;
112         if(!(selector & ~3))
113                 return;
114
115         if ( selector & 0x4 )
116                 base = cpustate->ldtr.base;
117         else
118                 base = cpustate->gdtr.base;
119
120         addr = base + (selector & ~7) + 5;
121         i386_translate_address(TRANSLATE_READ, &addr, NULL);
122         rights = cpustate->program->read_data8(addr);
123         // Should a fault be thrown if the table is read only?
124         cpustate->program->write_data8(addr, rights | 1);
125 }
126
127 void I386_OPS_BASE::i386_load_segment_descriptor( int segment )
128 {
129         if (PROTECTED_MODE)
130         {
131                 if (!V8086_MODE)
132                 {
133                         i386_load_protected_mode_segment(&cpustate->sreg[segment], NULL );
134                         {
135                                 i386_set_descriptor_accessed(cpustate, cpustate->sreg[segment].selector);
136                                 cpustate->sreg[segment].flags |= 0x0001;
137                         }
138                 }
139                 else
140                 {
141                         cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4;
142                         cpustate->sreg[segment].limit = 0xffff;
143                         cpustate->sreg[segment].flags = (segment == CS) ? 0x00fb : 0x00f3;
144                         cpustate->sreg[segment].d = 0;
145                         cpustate->sreg[segment].valid = true;
146                 }
147 //              if (segment == CS && cpustate->sreg[segment].flags != old_flags)
148 //                      debugger_privilege_hook();
149         }
150         else
151         {
152                 cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4;
153                 cpustate->sreg[segment].d = 0;
154                 cpustate->sreg[segment].valid = true;
155
156                 if( segment == CS )
157                 {
158                         if( !cpustate->performed_intersegment_jump )
159                                 cpustate->sreg[segment].base |= 0xfff00000;
160                         if(cpustate->cpu_version < 0x5000)
161                                 cpustate->sreg[segment].flags = 0x93;
162                 }
163         }
164 }
165
166 /* Retrieves the stack selector located in the current TSS */
167 UINT32 I386_OPS_BASE::i386_get_stack_segment(UINT8 privilege)
168 {
169         UINT32 ret;
170         if(privilege >= 3)
171                 return 0;
172
173         if(cpustate->task.flags & 8)
174                 ret = READ32PL0((cpustate->task.base+8) + (8*privilege));
175         else
176                 ret = READ16PL0((cpustate->task.base+4) + (4*privilege));
177
178         return ret;
179 }
180
181 /* Retrieves the stack pointer located in the current TSS */
182 UINT32 I386_OPS_BASE::i386_get_stack_ptr(UINT8 privilege)
183 {
184         UINT32 ret;
185         if(privilege >= 3)
186                 return 0;
187
188         if(cpustate->task.flags & 8)
189                 ret = READ32PL0((cpustate->task.base+4) + (8*privilege));
190         else
191                 ret = READ16PL0((cpustate->task.base+2) + (4*privilege));
192
193         return ret;
194 }
195
196 UINT32 I386_OPS_BASE::get_flags()
197 {
198         UINT32 f = 0x2;
199         f |= cpustate->CF;
200         f |= cpustate->PF << 2;
201         f |= cpustate->AF << 4;
202         f |= cpustate->ZF << 6;
203         f |= cpustate->SF << 7;
204         f |= cpustate->TF << 8;
205         f |= cpustate->IF << 9;
206         f |= cpustate->DF << 10;
207         f |= cpustate->OF << 11;
208         f |= cpustate->IOP1 << 12;
209         f |= cpustate->IOP2 << 13;
210         f |= cpustate->NT << 14;
211         f |= cpustate->RF << 16;
212         f |= cpustate->VM << 17;
213         f |= cpustate->AC << 18;
214         f |= cpustate->VIF << 19;
215         f |= cpustate->VIP << 20;
216         f |= cpustate->ID << 21;
217         return (cpustate->eflags & ~cpustate->eflags_mask) | (f & cpustate->eflags_mask);
218 }
219
220 void I386_OPS_BASE::set_flags( UINT32 f )
221 {
222         f &= cpustate->eflags_mask;;
223         cpustate->CF = (f & 0x1) ? 1 : 0;
224         cpustate->PF = (f & 0x4) ? 1 : 0;
225         cpustate->AF = (f & 0x10) ? 1 : 0;
226         cpustate->ZF = (f & 0x40) ? 1 : 0;
227         cpustate->SF = (f & 0x80) ? 1 : 0;
228         cpustate->TF = (f & 0x100) ? 1 : 0;
229         cpustate->IF = (f & 0x200) ? 1 : 0;
230         cpustate->DF = (f & 0x400) ? 1 : 0;
231         cpustate->OF = (f & 0x800) ? 1 : 0;
232         cpustate->IOP1 = (f & 0x1000) ? 1 : 0;
233         cpustate->IOP2 = (f & 0x2000) ? 1 : 0;
234         cpustate->NT = (f & 0x4000) ? 1 : 0;
235         cpustate->RF = (f & 0x10000) ? 1 : 0;
236         cpustate->VM = (f & 0x20000) ? 1 : 0;
237         cpustate->AC = (f & 0x40000) ? 1 : 0;
238         cpustate->VIF = (f & 0x80000) ? 1 : 0;
239         cpustate->VIP = (f & 0x100000) ? 1 : 0;
240         cpustate->ID = (f & 0x200000) ? 1 : 0;
241         cpustate->eflags = f;
242 }
243
244 void I386_OPS_BASE::sib_byte(UINT8 mod, UINT32* out_ea, UINT8* out_segment)
245 {
246         UINT32 ea = 0;
247         UINT8 segment = 0;
248         UINT8 scale, i, base;
249         UINT8 sib = FETCH();
250         scale = (sib >> 6) & 0x3;
251         i = (sib >> 3) & 0x7;
252         base = sib & 0x7;
253
254         switch( base )
255         {
256                 case 0: ea = REG32(EAX); segment = DS; break;
257                 case 1: ea = REG32(ECX); segment = DS; break;
258                 case 2: ea = REG32(EDX); segment = DS; break;
259                 case 3: ea = REG32(EBX); segment = DS; break;
260                 case 4: ea = REG32(ESP); segment = SS; break;
261                 case 5:
262                         if( mod == 0 ) {
263                                 ea = FETCH32();
264                                 segment = DS;
265                         } else if( mod == 1 ) {
266                                 ea = REG32(EBP);
267                                 segment = SS;
268                         } else if( mod == 2 ) {
269                                 ea = REG32(EBP);
270                                 segment = SS;
271                         }
272                         break;
273                 case 6: ea = REG32(ESI); segment = DS; break;
274                 case 7: ea = REG32(EDI); segment = DS; break;
275         }
276         switch( i )
277         {
278                 case 0: ea += REG32(EAX) * (1 << scale); break;
279                 case 1: ea += REG32(ECX) * (1 << scale); break;
280                 case 2: ea += REG32(EDX) * (1 << scale); break;
281                 case 3: ea += REG32(EBX) * (1 << scale); break;
282                 case 4: break;
283                 case 5: ea += REG32(EBP) * (1 << scale); break;
284                 case 6: ea += REG32(ESI) * (1 << scale); break;
285                 case 7: ea += REG32(EDI) * (1 << scale); break;
286         }
287         *out_ea = ea;
288         *out_segment = segment;
289 }
290
291 void I386_OPS_BASE::modrm_to_EA(UINT8 mod_rm, UINT32* out_ea, UINT8* out_segment)
292 {
293         INT8 disp8;
294         INT16 disp16;
295         INT32 disp32;
296         UINT8 mod = (mod_rm >> 6) & 0x3;
297         UINT8 rm = mod_rm & 0x7;
298         UINT32 ea;
299         UINT8 segment;
300
301         if( mod_rm >= 0xc0 )
302                 fatalerror("i386: Called modrm_to_EA with modrm value %02X!\n",mod_rm);
303
304
305         if( cpustate->address_size ) {
306                 switch( rm )
307                 {
308                         default:
309                         case 0: ea = REG32(EAX); segment = DS; break;
310                         case 1: ea = REG32(ECX); segment = DS; break;
311                         case 2: ea = REG32(EDX); segment = DS; break;
312                         case 3: ea = REG32(EBX); segment = DS; break;
313                         case 4: sib_byte(mod, &ea, &segment ); break;
314                         case 5:
315                                 if( mod == 0 ) {
316                                         ea = FETCH32(); segment = DS;
317                                 } else {
318                                         ea = REG32(EBP); segment = SS;
319                                 }
320                                 break;
321                         case 6: ea = REG32(ESI); segment = DS; break;
322                         case 7: ea = REG32(EDI); segment = DS; break;
323                 }
324                 if( mod == 1 ) {
325                         disp8 = FETCH();
326                         ea += (INT32)disp8;
327                 } else if( mod == 2 ) {
328                         disp32 = FETCH32();
329                         ea += disp32;
330                 }
331
332                 if( cpustate->segment_prefix )
333                         segment = cpustate->segment_override;
334
335                 *out_ea = ea;
336                 *out_segment = segment;
337
338         } else {
339                 switch( rm )
340                 {
341                         default:
342                         case 0: ea = REG16(BX) + REG16(SI); segment = DS; break;
343                         case 1: ea = REG16(BX) + REG16(DI); segment = DS; break;
344                         case 2: ea = REG16(BP) + REG16(SI); segment = SS; break;
345                         case 3: ea = REG16(BP) + REG16(DI); segment = SS; break;
346                         case 4: ea = REG16(SI); segment = DS; break;
347                         case 5: ea = REG16(DI); segment = DS; break;
348                         case 6:
349                                 if( mod == 0 ) {
350                                         ea = FETCH16(); segment = DS;
351                                 } else {
352                                         ea = REG16(BP); segment = SS;
353                                 }
354                                 break;
355                         case 7: ea = REG16(BX); segment = DS; break;
356                 }
357                 if( mod == 1 ) {
358                         disp8 = FETCH();
359                         ea += (INT32)disp8;
360                 } else if( mod == 2 ) {
361                         disp16 = FETCH16();
362                         ea += (INT32)disp16;
363                 }
364
365                 if( cpustate->segment_prefix )
366                         segment = cpustate->segment_override;
367
368                 *out_ea = ea & 0xffff;
369                 *out_segment = segment;
370         }
371 }
372
373 UINT32 I386_OPS_BASE::GetNonTranslatedEA(UINT8 modrm,UINT8 *seg)
374 {
375         UINT8 segment;
376         UINT32 ea;
377         modrm_to_EA(modrm, &ea, &segment );
378         if(seg) *seg = segment;
379         return ea;
380 }
381
382 UINT32 I386_OPS_BASE::GetEA(UINT8 modrm, int rwn, UINT32 size)
383 {
384         UINT8 segment;
385         UINT32 ea;
386         modrm_to_EA(modrm, &ea, &segment );
387         return i386_translate(segment, ea, rwn, size );
388 }
389
390 /* Check segment register for validity when changing privilege level after an RETF */
391 void I386_OPS_BASE::i386_check_sreg_validity(int reg)
392 {
393         UINT16 selector = cpustate->sreg[reg].selector;
394         UINT8 CPL = cpustate->CPL;
395         UINT8 DPL,RPL;
396         I386_SREG desc;
397         int invalid = 0;
398
399         memset(&desc, 0, sizeof(desc));
400         desc.selector = selector;
401         i386_load_protected_mode_segment(&desc,NULL);
402         DPL = (desc.flags >> 5) & 0x03;  // descriptor privilege level
403         RPL = selector & 0x03;
404
405         /* Must be within the relevant descriptor table limits */
406         if(selector & 0x04)
407         {
408                 if((selector & ~0x07) > cpustate->ldtr.limit)
409                         invalid = 1;
410         }
411         else
412         {
413                 if((selector & ~0x07) > cpustate->gdtr.limit)
414                         invalid = 1;
415         }
416
417         /* Must be either a data or readable code segment */
418         if(((desc.flags & 0x0018) == 0x0018 && (desc.flags & 0x0002)) || (desc.flags & 0x0018) == 0x0010)
419                 invalid = 0;
420         else
421                 invalid = 1;
422
423         /* If a data segment or non-conforming code segment, then either DPL >= CPL or DPL >= RPL */
424         if(((desc.flags & 0x0018) == 0x0018 && (desc.flags & 0x0004) == 0) || (desc.flags & 0x0018) == 0x0010)
425         {
426                 if((DPL < CPL) || (DPL < RPL))
427                         invalid = 1;
428         }
429
430         /* if segment is invalid, then segment register is nulled */
431         if(invalid != 0)
432         {
433                 cpustate->sreg[reg].selector = 0;
434                 i386_load_segment_descriptor(reg);
435         }
436 }
437
438 int I386_OPS_BASE::i386_limit_check( int seg, UINT32 offset, UINT32 size)
439 {
440         if(PROTECTED_MODE && !V8086_MODE)
441         {
442                 if((cpustate->sreg[seg].flags & 0x0018) == 0x0010 && cpustate->sreg[seg].flags & 0x0004) // if expand-down data segment
443                 {
444                         // compare if greater then 0xffffffff when we're passed the access size
445                         if((offset <= cpustate->sreg[seg].limit) || ((cpustate->sreg[seg].d)?0:((offset + size - 1) > 0xffff)))
446                         {
447                                 logerror("Limit check at 0x%08x failed. Segment %04x, limit %08x, offset %08x (expand-down)\n",cpustate->pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].limit,offset);
448                                 return 1;
449                         }
450                 }
451                 else
452                 {
453                         if((offset + size - 1) > cpustate->sreg[seg].limit)
454                         {
455                                 logerror("Limit check at 0x%08x failed. Segment %04x, limit %08x, offset %08x\n",cpustate->pc,cpustate->sreg[seg].selector,cpustate->sreg[seg].limit,offset);
456                                 return 1;
457                         }
458                 }
459         }
460         return 0;
461 }
462
463 void I386_OPS_BASE::i386_sreg_load( UINT16 selector, UINT8 reg, bool *fault)
464 {
465         // Checks done when MOV changes a segment register in protected mode
466         UINT8 CPL,RPL,DPL;
467
468         CPL = cpustate->CPL;
469         RPL = selector & 0x0003;
470
471         if(!PROTECTED_MODE || V8086_MODE)
472         {
473                 cpustate->sreg[reg].selector = selector;
474                 i386_load_segment_descriptor(reg);
475                 if(fault) *fault = false;
476                 return;
477         }
478
479         if(fault) *fault = true;
480         if(reg == SS)
481         {
482                 I386_SREG stack;
483
484                 memset(&stack, 0, sizeof(stack));
485                 stack.selector = selector;
486                 i386_load_protected_mode_segment(&stack,NULL);
487                 DPL = (stack.flags >> 5) & 0x03;
488
489                 if((selector & ~0x0003) == 0)
490                 {
491                         logerror("SReg Load (%08x): Selector is null.\n",cpustate->pc);
492                         FAULT(FAULT_GP,0)
493                 }
494                 if(selector & 0x0004)  // LDT
495                 {
496                         if((selector & ~0x0007) > cpustate->ldtr.limit)
497                         {
498                                 logerror("SReg Load (%08x): Selector is out of LDT bounds.\n",cpustate->pc);
499                                 FAULT(FAULT_GP,selector & ~0x03)
500                         }
501                 }
502                 else  // GDT
503                 {
504                         if((selector & ~0x0007) > cpustate->gdtr.limit)
505                         {
506                                 logerror("SReg Load (%08x): Selector is out of GDT bounds.\n",cpustate->pc);
507                                 FAULT(FAULT_GP,selector & ~0x03)
508                         }
509                 }
510                 if (RPL != CPL)
511                 {
512                         logerror("SReg Load (%08x): Selector RPL does not equal CPL.\n",cpustate->pc);
513                         FAULT(FAULT_GP,selector & ~0x03)
514                 }
515                 if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0)
516                 {
517                         logerror("SReg Load (%08x): Segment is not a writable data segment.\n",cpustate->pc);
518                         FAULT(FAULT_GP,selector & ~0x03)
519                 }
520                 if(DPL != CPL)
521                 {
522                         logerror("SReg Load (%08x): Segment DPL does not equal CPL.\n",cpustate->pc);
523                         FAULT(FAULT_GP,selector & ~0x03)
524                 }
525                 if(!(stack.flags & 0x0080))
526                 {
527                         logerror("SReg Load (%08x): Segment is not present.\n",cpustate->pc);
528                         FAULT(FAULT_SS,selector & ~0x03)
529                 }
530         }
531         if(reg == DS || reg == ES || reg == FS || reg == GS)
532         {
533                 I386_SREG desc;
534
535                 if((selector & ~0x0003) == 0)
536                 {
537                         cpustate->sreg[reg].selector = selector;
538                         i386_load_segment_descriptor(reg );
539                         if(fault) *fault = false;
540                         return;
541                 }
542
543                 memset(&desc, 0, sizeof(desc));
544                 desc.selector = selector;
545                 i386_load_protected_mode_segment(&desc,NULL);
546                 DPL = (desc.flags >> 5) & 0x03;
547
548                 if(selector & 0x0004)  // LDT
549                 {
550                         if((selector & ~0x0007) > cpustate->ldtr.limit)
551                         {
552                                 logerror("SReg Load (%08x): Selector is out of LDT bounds.\n",cpustate->pc);
553                                 FAULT(FAULT_GP,selector & ~0x03)
554                         }
555                 }
556                 else  // GDT
557                 {
558                         if((selector & ~0x0007) > cpustate->gdtr.limit)
559                         {
560                                 logerror("SReg Load (%08x): Selector is out of GDT bounds.\n",cpustate->pc);
561                                 FAULT(FAULT_GP,selector & ~0x03)
562                         }
563                 }
564                 if((desc.flags & 0x0018) != 0x10)
565                 {
566                         if((((desc.flags & 0x0002) != 0) && ((desc.flags & 0x0018) != 0x18)) || !(desc.flags & 0x10))
567                         {
568                                 logerror("SReg Load (%08x): Segment is not a data segment or readable code segment.\n",cpustate->pc);
569                                 FAULT(FAULT_GP,selector & ~0x03)
570                         }
571                 }
572                 if(((desc.flags & 0x0018) == 0x10) || ((!(desc.flags & 0x0004)) && ((desc.flags & 0x0018) == 0x18)))
573                 {
574                         // if data or non-conforming code segment
575                         if((RPL > DPL) || (CPL > DPL))
576                         {
577                                 logerror("SReg Load (%08x): Selector RPL or CPL is not less or equal to segment DPL.\n",cpustate->pc);
578                                 FAULT(FAULT_GP,selector & ~0x03)
579                         }
580                 }
581                 if(!(desc.flags & 0x0080))
582                 {
583                         logerror("SReg Load (%08x): Segment is not present.\n",cpustate->pc);
584                         FAULT(FAULT_NP,selector & ~0x03)
585                 }
586         }
587
588         cpustate->sreg[reg].selector = selector;
589         i386_load_segment_descriptor(reg );
590         if(fault) *fault = false;
591 }
592
593 void I386_OPS_BASE::i386_trap(int irq, int irq_gate, int trap_level)
594 {
595         /*  I386 Interrupts/Traps/Faults:
596          *
597          *  0x00    Divide by zero
598          *  0x01    Debug exception
599          *  0x02    NMI
600          *  0x03    Int3
601          *  0x04    Overflow
602          *  0x05    Array bounds check
603          *  0x06    Illegal Opcode
604          *  0x07    FPU not available
605          *  0x08    Double fault
606          *  0x09    Coprocessor segment overrun
607          *  0x0a    Invalid task state
608          *  0x0b    Segment not present
609          *  0x0c    Stack exception
610          *  0x0d    General Protection Fault
611          *  0x0e    Page fault
612          *  0x0f    Reserved
613          *  0x10    Coprocessor error
614          */
615         UINT32 v1, v2;
616         UINT32 offset, oldflags = get_flags();
617         UINT16 segment;
618         int entry = irq * (PROTECTED_MODE ? 8 : 4);
619         int SetRPL = 0;
620         cpustate->lock = false;
621
622         if( !(PROTECTED_MODE) )
623         {
624                 /* 16-bit */
625                 PUSH16(oldflags & 0xffff );
626                 PUSH16(cpustate->sreg[CS].selector );
627                 if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)
628                         PUSH16(cpustate->eip );
629                 else
630                         PUSH16(cpustate->prev_eip );
631
632                 cpustate->sreg[CS].selector = READ16(cpustate->idtr.base + entry + 2 );
633                 cpustate->eip = READ16(cpustate->idtr.base + entry );
634
635                 cpustate->TF = 0;
636                 cpustate->IF = 0;
637         }
638         else
639         {
640                 int type;
641                 UINT16 flags;
642                 I386_SREG desc;
643                 UINT8 CPL = cpustate->CPL, DPL = 0; //, RPL = 0;
644
645                 /* 32-bit */
646                 v1 = READ32PL0(cpustate->idtr.base + entry );
647                 v2 = READ32PL0(cpustate->idtr.base + entry + 4 );
648                 offset = (v2 & 0xffff0000) | (v1 & 0xffff);
649                 segment = (v1 >> 16) & 0xffff;
650                 type = (v2>>8) & 0x1F;
651                 flags = (v2>>8) & 0xf0ff;
652
653                 if(trap_level == 2)
654                 {
655                         logerror("IRQ: Double fault.\n");
656                         FAULT_EXP(FAULT_DF,0);
657                 }
658                 if(trap_level >= 3)
659                 {
660                         logerror("IRQ: Triple fault. CPU reset.\n");
661                         CPU_RESET_CALL(i386); //!
662                         cpustate->shutdown = 1;
663                         return;
664                 }
665
666                 /* segment privilege checks */
667                 if(entry >= cpustate->idtr.limit)
668                 {
669                         logerror("IRQ (%08x): Vector %02xh is past IDT limit.\n",cpustate->pc,entry);
670                         FAULT_EXP(FAULT_GP,entry+2)
671                 }
672                 /* segment must be interrupt gate, trap gate, or task gate */
673                 if(type != 0x05 && type != 0x06 && type != 0x07 && type != 0x0e && type != 0x0f)
674                 {
675                         logerror("IRQ#%02x (%08x): Vector segment %04x is not an interrupt, trap or task gate.\n",irq,cpustate->pc,segment);
676                         FAULT_EXP(FAULT_GP,entry+2)
677                 }
678
679                 if(cpustate->ext == 0) // if software interrupt (caused by INT/INTO/INT3)
680                 {
681                         if(((flags >> 5) & 0x03) < CPL)
682                         {
683                                 logerror("IRQ (%08x): Software IRQ - gate DPL is less than CPL.\n",cpustate->pc);
684                                 FAULT_EXP(FAULT_GP,entry+2)
685                         }
686                         if(V8086_MODE)
687                         {
688                                 if((!cpustate->IOP1 || !cpustate->IOP2) && (cpustate->opcode != 0xcc))
689                                 {
690                                         logerror("IRQ (%08x): Is in Virtual 8086 mode and IOPL != 3.\n",cpustate->pc);
691                                         FAULT(FAULT_GP,0)
692                                 }
693
694                         }
695                 }
696
697                 if((flags & 0x0080) == 0)
698                 {
699                         logerror("IRQ: Vector segment is not present.\n");
700                         FAULT_EXP(FAULT_NP,entry+2)
701                 }
702
703                 if(type == 0x05)
704                 {
705                         /* Task gate */
706                         memset(&desc, 0, sizeof(desc));
707                         desc.selector = segment;
708                         i386_load_protected_mode_segment(&desc,NULL);
709                         if(segment & 0x04)
710                         {
711                                 logerror("IRQ: Task gate: TSS is not in the GDT.\n");
712                                 FAULT_EXP(FAULT_TS,segment & ~0x03);
713                         }
714                         else
715                         {
716                                 if(segment > cpustate->gdtr.limit)
717                                 {
718                                         logerror("IRQ: Task gate: TSS is past GDT limit.\n");
719                                         FAULT_EXP(FAULT_TS,segment & ~0x03);
720                                 }
721                         }
722                         if((desc.flags & 0x000f) != 0x09 && (desc.flags & 0x000f) != 0x01)
723                         {
724                                 logerror("IRQ: Task gate: TSS is not an available TSS.\n");
725                                 FAULT_EXP(FAULT_TS,segment & ~0x03);
726                         }
727                         if((desc.flags & 0x0080) == 0)
728                         {
729                                 logerror("IRQ: Task gate: TSS is not present.\n");
730                                 FAULT_EXP(FAULT_NP,segment & ~0x03);
731                         }
732                         if(!(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1))
733                                 cpustate->eip = cpustate->prev_eip;
734                         if(desc.flags & 0x08)
735                                 i386_task_switch(desc.selector,1);
736                         else
737                                 i286_task_switch(desc.selector,1);
738                         return;
739                 }
740                 else
741                 {
742                         /* Interrupt or Trap gate */
743                         memset(&desc, 0, sizeof(desc));
744                         desc.selector = segment;
745                         i386_load_protected_mode_segment(&desc,NULL);
746                         CPL = cpustate->CPL;  // current privilege level
747                         DPL = (desc.flags >> 5) & 0x03;  // descriptor privilege level
748 //          RPL = segment & 0x03;  // requested privilege level
749
750                         if((segment & ~0x03) == 0)
751                         {
752                                 logerror("IRQ: Gate segment is null.\n");
753                                 FAULT_EXP(FAULT_GP,cpustate->ext)
754                         }
755                         if(segment & 0x04)
756                         {
757                                 if((segment & ~0x07) > cpustate->ldtr.limit)
758                                 {
759                                         logerror("IRQ: Gate segment is past LDT limit.\n");
760                                         FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext)
761                                 }
762                         }
763                         else
764                         {
765                                 if((segment & ~0x07) > cpustate->gdtr.limit)
766                                 {
767                                         logerror("IRQ: Gate segment is past GDT limit.\n");
768                                         FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext)
769                                 }
770                         }
771                         if((desc.flags & 0x0018) != 0x18)
772                         {
773                                 logerror("IRQ: Gate descriptor is not a code segment.\n");
774                                 FAULT_EXP(FAULT_GP,(segment & 0x03)+cpustate->ext)
775                         }
776                         if((desc.flags & 0x0080) == 0)
777                         {
778                                 logerror("IRQ: Gate segment is not present.\n");
779                                 FAULT_EXP(FAULT_NP,(segment & 0x03)+cpustate->ext)
780                         }
781                         if((desc.flags & 0x0004) == 0 && (DPL < CPL))
782                         {
783                                 /* IRQ to inner privilege */
784                                 I386_SREG stack;
785                                 UINT32 newESP,oldSS,oldESP;
786
787                                 if(V8086_MODE && DPL)
788                                 {
789                                         logerror("IRQ: Gate to CPL>0 from VM86 mode.\n");
790                                         FAULT_EXP(FAULT_GP,segment & ~0x03);
791                                 }
792                                 /* Check new stack segment in TSS */
793                                 memset(&stack, 0, sizeof(stack));
794                                 stack.selector = i386_get_stack_segment(DPL);
795                                 i386_load_protected_mode_segment(&stack,NULL);
796                                 oldSS = cpustate->sreg[SS].selector;
797                                 if(flags & 0x0008)
798                                         oldESP = REG32(ESP);
799                                 else
800                                         oldESP = REG16(SP);
801                                 if((stack.selector & ~0x03) == 0)
802                                 {
803                                         logerror("IRQ: New stack selector is null.\n");
804                                         FAULT_EXP(FAULT_GP,cpustate->ext)
805                                 }
806                                 if(stack.selector & 0x04)
807                                 {
808                                         if((stack.selector & ~0x07) > cpustate->ldtr.base)
809                                         {
810                                                 logerror("IRQ: New stack selector is past LDT limit.\n");
811                                                 FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext)
812                                         }
813                                 }
814                                 else
815                                 {
816                                         if((stack.selector & ~0x07) > cpustate->gdtr.base)
817                                         {
818                                                 logerror("IRQ: New stack selector is past GDT limit.\n");
819                                                 FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext)
820                                         }
821                                 }
822                                 if((stack.selector & 0x03) != DPL)
823                                 {
824                                         logerror("IRQ: New stack selector RPL is not equal to code segment DPL.\n");
825                                         FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext)
826                                 }
827                                 if(((stack.flags >> 5) & 0x03) != DPL)
828                                 {
829                                         logerror("IRQ: New stack segment DPL is not equal to code segment DPL.\n");
830                                         FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext)
831                                 }
832                                 if(((stack.flags & 0x0018) != 0x10) && (stack.flags & 0x0002) != 0)
833                                 {
834                                         logerror("IRQ: New stack segment is not a writable data segment.\n");
835                                         FAULT_EXP(FAULT_TS,(stack.selector & ~0x03)+cpustate->ext) // #TS(stack selector + EXT)
836                                 }
837                                 if((stack.flags & 0x0080) == 0)
838                                 {
839                                         logerror("IRQ: New stack segment is not present.\n");
840                                         FAULT_EXP(FAULT_SS,(stack.selector & ~0x03)+cpustate->ext) // #TS(stack selector + EXT)
841                                 }
842                                 newESP = i386_get_stack_ptr(DPL);
843                                 if(type & 0x08) // 32-bit gate
844                                 {
845                                         if(((newESP < (V8086_MODE?36:20)) && !(stack.flags & 0x4)) || ((~stack.limit < (~(newESP - 1) + (V8086_MODE?36:20))) && (stack.flags & 0x4)))
846                                         {
847                                                 logerror("IRQ: New stack has no space for return addresses.\n");
848                                                 FAULT_EXP(FAULT_SS,0)
849                                         }
850                                 }
851                                 else // 16-bit gate
852                                 {
853                                         newESP &= 0xffff;
854                                         if(((newESP < (V8086_MODE?18:10)) && !(stack.flags & 0x4)) || ((~stack.limit < (~(newESP - 1) + (V8086_MODE?18:10))) && (stack.flags & 0x4)))
855                                         {
856                                                 logerror("IRQ: New stack has no space for return addresses.\n");
857                                                 FAULT_EXP(FAULT_SS,0)
858                                         }
859                                 }
860                                 if(offset > desc.limit)
861                                 {
862                                         logerror("IRQ: New EIP is past code segment limit.\n");
863                                         FAULT_EXP(FAULT_GP,0)
864                                 }
865                                 /* change CPL before accessing the stack */
866                                 cpustate->CPL = DPL;
867                                 /* check for page fault at new stack TODO: check if stack frame crosses page boundary */
868                                 WRITE_TEST(stack.base+newESP-1);
869                                 /* Load new stack segment descriptor */
870                                 cpustate->sreg[SS].selector = stack.selector;
871                                 i386_load_protected_mode_segment(&cpustate->sreg[SS],NULL);
872                                 i386_set_descriptor_accessed(stack.selector);
873                                 REG32(ESP) = newESP;
874                                 if(V8086_MODE)
875                                 {
876                                         //logerror("IRQ (%08x): Interrupt during V8086 task\n",cpustate->pc);
877                                         if(type & 0x08)
878                                         {
879                                                 PUSH32SEG(cpustate->sreg[GS].selector & 0xffff);
880                                                 PUSH32SEG(cpustate->sreg[FS].selector & 0xffff);
881                                                 PUSH32SEG(cpustate->sreg[DS].selector & 0xffff);
882                                                 PUSH32SEG(cpustate->sreg[ES].selector & 0xffff);
883                                         }
884                                         else
885                                         {
886                                                 PUSH16(cpustate->sreg[GS].selector);
887                                                 PUSH16(cpustate->sreg[FS].selector);
888                                                 PUSH16(cpustate->sreg[DS].selector);
889                                                 PUSH16(cpustate->sreg[ES].selector);
890                                         }
891                                         cpustate->sreg[GS].selector = 0;
892                                         cpustate->sreg[FS].selector = 0;
893                                         cpustate->sreg[DS].selector = 0;
894                                         cpustate->sreg[ES].selector = 0;
895                                         cpustate->VM = 0;
896                                         i386_load_segment_descriptor(GS);
897                                         i386_load_segment_descriptor(FS);
898                                         i386_load_segment_descriptor(DS);
899                                         i386_load_segment_descriptor(ES);
900                                 }
901                                 if(type & 0x08)
902                                 {
903                                         // 32-bit gate
904                                         PUSH32SEG(oldSS);
905                                         PUSH32(oldESP);
906                                 }
907                                 else
908                                 {
909                                         // 16-bit gate
910                                         PUSH16(oldSS);
911                                         PUSH16(oldESP);
912                                 }
913                                 SetRPL = 1;
914                         }
915                         else
916                         {
917                                 int stack_limit;
918                                 if((desc.flags & 0x0004) || (DPL == CPL))
919                                 {
920                                         /* IRQ to same privilege */
921                                         if(V8086_MODE && !cpustate->ext)
922                                         {
923                                                 logerror("IRQ: Gate to same privilege from VM86 mode.\n");
924                                                 FAULT_EXP(FAULT_GP,segment & ~0x03);
925                                         }
926                                         if(type == 0x0e || type == 0x0f)  // 32-bit gate
927                                                 stack_limit = 10;
928                                         else
929                                                 stack_limit = 6;
930                                         // TODO: Add check for error code (2 extra bytes)
931                                         if((int)(REG32(ESP)) < stack_limit)
932                                         {
933                                                 logerror("IRQ: Stack has no space left (needs %i bytes).\n",stack_limit);
934                                                 FAULT_EXP(FAULT_SS,0)
935                                         }
936                                         if(offset > desc.limit)
937                                         {
938                                                 logerror("IRQ: Gate segment offset is past segment limit.\n");
939                                                 FAULT_EXP(FAULT_GP,0)
940                                         }
941                                         SetRPL = 1;
942                                 }
943                                 else
944                                 {
945                                         logerror("IRQ: Gate descriptor is non-conforming, and DPL does not equal CPL.\n");
946                                         FAULT_EXP(FAULT_GP,segment)
947                                 }
948                         }
949                 }
950                 UINT32 tempSP = REG32(ESP);
951                 try
952                 {
953                         // this is ugly but the alternative is worse
954                         if(type != 0x0e && type != 0x0f)  // if not 386 interrupt or trap gate
955                         {
956                                 PUSH16(oldflags & 0xffff );
957                                 PUSH16(cpustate->sreg[CS].selector );
958                                 if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)
959                                         PUSH16(cpustate->eip );
960                                 else
961                                         PUSH16(cpustate->prev_eip );
962                         }
963                         else
964                         {
965                                 PUSH32(oldflags & 0x00ffffff );
966                                 PUSH32SEG(cpustate->sreg[CS].selector );
967                                 if(irq == 3 || irq == 4 || irq == 9 || irq_gate == 1)
968                                         PUSH32(cpustate->eip );
969                                 else
970                                         PUSH32(cpustate->prev_eip );
971                         }
972                 }
973                 catch(UINT64 e)
974                 {
975                         REG32(ESP) = tempSP;
976                         throw e;
977                 }
978                 if(SetRPL != 0)
979                         segment = (segment & ~0x03) | cpustate->CPL;
980                 cpustate->sreg[CS].selector = segment;
981                 cpustate->eip = offset;
982
983                 if(type == 0x0e || type == 0x06)
984                         cpustate->IF = 0;
985                 cpustate->TF = 0;
986                 cpustate->NT = 0;
987         }
988
989         i386_load_segment_descriptor(CS);
990         CHANGE_PC(cpustate->eip);
991
992 }
993
994 void I386_OPS_BASE::i386_trap_with_error(int irq, int irq_gate, int trap_level, UINT32 error)
995 {
996         i386_trap(irq,irq_gate,trap_level);
997         if(irq == 8 || irq == 10 || irq == 11 || irq == 12 || irq == 13 || irq == 14)
998         {
999                 // for these exceptions, an error code is pushed onto the stack by the processor.
1000                 // no error code is pushed for software interrupts, either.
1001                 if(PROTECTED_MODE)
1002                 {
1003                         UINT32 entry = irq * 8;
1004                         UINT32 v2,type;
1005                         v2 = READ32PL0(cpustate->idtr.base + entry + 4 );
1006                         type = (v2>>8) & 0x1F;
1007                         if(type == 5)
1008                         {
1009                                 v2 = READ32PL0(cpustate->idtr.base + entry);
1010                                 v2 = READ32PL0(cpustate->gdtr.base + ((v2 >> 16) & 0xfff8) + 4);
1011                                 type = (v2>>8) & 0x1F;
1012                         }
1013                         if(type >= 9)
1014                                 PUSH32(error);
1015                         else
1016                                 PUSH16(error);
1017                 }
1018                 else
1019                         PUSH16(error);
1020         }
1021 }
1022
1023
1024 void I386_OPS_BASE::i286_task_switch( UINT16 selector, UINT8 nested)
1025 {
1026         UINT32 tss;
1027         I386_SREG seg;
1028         UINT16 old_task;
1029         UINT8 ar_byte;  // access rights byte
1030
1031         /* TODO: Task State Segment privilege checks */
1032
1033         /* For tasks that aren't nested, clear the busy bit in the task's descriptor */
1034         if(nested == 0)
1035         {
1036                 if(cpustate->task.segment & 0x0004)
1037                 {
1038                         ar_byte = READ8(cpustate->ldtr.base + (cpustate->task.segment & ~0x0007) + 5);
1039                         WRITE8(cpustate->ldtr.base + (cpustate->task.segment & ~0x0007) + 5,ar_byte & ~0x02);
1040                 }
1041                 else
1042                 {
1043                         ar_byte = READ8(cpustate->gdtr.base + (cpustate->task.segment & ~0x0007) + 5);
1044                         WRITE8(cpustate->gdtr.base + (cpustate->task.segment & ~0x0007) + 5,ar_byte & ~0x02);
1045                 }
1046         }
1047
1048         /* Save the state of the current task in the current TSS (TR register base) */
1049         tss = cpustate->task.base;
1050         WRITE16(tss+0x0e,cpustate->eip & 0x0000ffff);
1051         WRITE16(tss+0x10,get_flags() & 0x0000ffff);
1052         WRITE16(tss+0x12,REG16(AX));
1053         WRITE16(tss+0x14,REG16(CX));
1054         WRITE16(tss+0x16,REG16(DX));
1055         WRITE16(tss+0x18,REG16(BX));
1056         WRITE16(tss+0x1a,REG16(SP));
1057         WRITE16(tss+0x1c,REG16(BP));
1058         WRITE16(tss+0x1e,REG16(SI));
1059         WRITE16(tss+0x20,REG16(DI));
1060         WRITE16(tss+0x22,cpustate->sreg[ES].selector);
1061         WRITE16(tss+0x24,cpustate->sreg[CS].selector);
1062         WRITE16(tss+0x26,cpustate->sreg[SS].selector);
1063         WRITE16(tss+0x28,cpustate->sreg[DS].selector);
1064
1065         old_task = cpustate->task.segment;
1066
1067         /* Load task register with the selector of the incoming task */
1068         cpustate->task.segment = selector;
1069         memset(&seg, 0, sizeof(seg));
1070         seg.selector = cpustate->task.segment;
1071         i386_load_protected_mode_segment(&seg,NULL);
1072         cpustate->task.limit = seg.limit;
1073         cpustate->task.base = seg.base;
1074         cpustate->task.flags = seg.flags;
1075
1076         /* Set TS bit in CR0 */
1077         cpustate->cr[0] |= 0x08;
1078
1079         /* Load incoming task state from the new task's TSS */
1080         tss = cpustate->task.base;
1081         cpustate->ldtr.segment = READ16(tss+0x2a) & 0xffff;
1082         seg.selector = cpustate->ldtr.segment;
1083         i386_load_protected_mode_segment(&seg,NULL);
1084         cpustate->ldtr.limit = seg.limit;
1085         cpustate->ldtr.base = seg.base;
1086         cpustate->ldtr.flags = seg.flags;
1087         cpustate->eip = READ16(tss+0x0e);
1088         set_flags(READ16(tss+0x10));
1089         REG16(AX) = READ16(tss+0x12);
1090         REG16(CX) = READ16(tss+0x14);
1091         REG16(DX) = READ16(tss+0x16);
1092         REG16(BX) = READ16(tss+0x18);
1093         REG16(SP) = READ16(tss+0x1a);
1094         REG16(BP) = READ16(tss+0x1c);
1095         REG16(SI) = READ16(tss+0x1e);
1096         REG16(DI) = READ16(tss+0x20);
1097         cpustate->sreg[ES].selector = READ16(tss+0x22) & 0xffff;
1098         i386_load_segment_descriptor(ES);
1099         cpustate->sreg[CS].selector = READ16(tss+0x24) & 0xffff;
1100         i386_load_segment_descriptor(CS);
1101         cpustate->sreg[SS].selector = READ16(tss+0x26) & 0xffff;
1102         i386_load_segment_descriptor(SS);
1103         cpustate->sreg[DS].selector = READ16(tss+0x28) & 0xffff;
1104         i386_load_segment_descriptor(DS);
1105
1106         /* Set the busy bit in the new task's descriptor */
1107         if(selector & 0x0004)
1108         {
1109                 ar_byte = READ8(cpustate->ldtr.base + (selector & ~0x0007) + 5);
1110                 WRITE8(cpustate->ldtr.base + (selector & ~0x0007) + 5,ar_byte | 0x02);
1111         }
1112         else
1113         {
1114                 ar_byte = READ8(cpustate->gdtr.base + (selector & ~0x0007) + 5);
1115                 WRITE8(cpustate->gdtr.base + (selector & ~0x0007) + 5,ar_byte | 0x02);
1116         }
1117
1118         /* For nested tasks, we write the outgoing task's selector to the back-link field of the new TSS,
1119            and set the NT flag in the EFLAGS register */
1120         if(nested != 0)
1121         {
1122                 WRITE16(tss+0,old_task);
1123                 cpustate->NT = 1;
1124         }
1125         CHANGE_PC(cpustate->eip);
1126
1127         cpustate->CPL = (cpustate->sreg[SS].flags >> 5) & 3;
1128 //  printf("286 Task Switch from selector %04x to %04x\n",old_task,selector);
1129 }
1130
1131 void I386_OPS_BASE::i386_task_switch( UINT16 selector, UINT8 nested)
1132 {
1133         UINT32 tss;
1134         I386_SREG seg;
1135         UINT16 old_task;
1136         UINT8 ar_byte;  // access rights byte
1137         UINT32 oldcr3 = cpustate->cr[3];
1138
1139         /* TODO: Task State Segment privilege checks */
1140
1141         /* For tasks that aren't nested, clear the busy bit in the task's descriptor */
1142         if(nested == 0)
1143         {
1144                 if(cpustate->task.segment & 0x0004)
1145                 {
1146                         ar_byte = READ8(cpustate->ldtr.base + (cpustate->task.segment & ~0x0007) + 5);
1147                         WRITE8(cpustate->ldtr.base + (cpustate->task.segment & ~0x0007) + 5,ar_byte & ~0x02);
1148                 }
1149                 else
1150                 {
1151                         ar_byte = READ8(cpustate->gdtr.base + (cpustate->task.segment & ~0x0007) + 5);
1152                         WRITE8(cpustate->gdtr.base + (cpustate->task.segment & ~0x0007) + 5,ar_byte & ~0x02);
1153                 }
1154         }
1155
1156         /* Save the state of the current task in the current TSS (TR register base) */
1157         tss = cpustate->task.base;
1158         WRITE32(tss+0x1c,cpustate->cr[3]);  // correct?
1159         WRITE32(tss+0x20,cpustate->eip);
1160         WRITE32(tss+0x24,get_flags());
1161         WRITE32(tss+0x28,REG32(EAX));
1162         WRITE32(tss+0x2c,REG32(ECX));
1163         WRITE32(tss+0x30,REG32(EDX));
1164         WRITE32(tss+0x34,REG32(EBX));
1165         WRITE32(tss+0x38,REG32(ESP));
1166         WRITE32(tss+0x3c,REG32(EBP));
1167         WRITE32(tss+0x40,REG32(ESI));
1168         WRITE32(tss+0x44,REG32(EDI));
1169         WRITE32(tss+0x48,cpustate->sreg[ES].selector);
1170         WRITE32(tss+0x4c,cpustate->sreg[CS].selector);
1171         WRITE32(tss+0x50,cpustate->sreg[SS].selector);
1172         WRITE32(tss+0x54,cpustate->sreg[DS].selector);
1173         WRITE32(tss+0x58,cpustate->sreg[FS].selector);
1174         WRITE32(tss+0x5c,cpustate->sreg[GS].selector);
1175
1176         old_task = cpustate->task.segment;
1177
1178         /* Load task register with the selector of the incoming task */
1179         cpustate->task.segment = selector;
1180         memset(&seg, 0, sizeof(seg));
1181         seg.selector = cpustate->task.segment;
1182         i386_load_protected_mode_segment(&seg,NULL);
1183         cpustate->task.limit = seg.limit;
1184         cpustate->task.base = seg.base;
1185         cpustate->task.flags = seg.flags;
1186
1187         /* Set TS bit in CR0 */
1188         cpustate->cr[0] |= 0x08;
1189
1190         /* Load incoming task state from the new task's TSS */
1191         tss = cpustate->task.base;
1192         cpustate->ldtr.segment = READ32(tss+0x60) & 0xffff;
1193         seg.selector = cpustate->ldtr.segment;
1194         i386_load_protected_mode_segment(&seg,NULL);
1195         cpustate->ldtr.limit = seg.limit;
1196         cpustate->ldtr.base = seg.base;
1197         cpustate->ldtr.flags = seg.flags;
1198         cpustate->eip = READ32(tss+0x20);
1199         set_flags(READ32(tss+0x24));
1200         REG32(EAX) = READ32(tss+0x28);
1201         REG32(ECX) = READ32(tss+0x2c);
1202         REG32(EDX) = READ32(tss+0x30);
1203         REG32(EBX) = READ32(tss+0x34);
1204         REG32(ESP) = READ32(tss+0x38);
1205         REG32(EBP) = READ32(tss+0x3c);
1206         REG32(ESI) = READ32(tss+0x40);
1207         REG32(EDI) = READ32(tss+0x44);
1208         cpustate->sreg[ES].selector = READ32(tss+0x48) & 0xffff;
1209         i386_load_segment_descriptor(ES);
1210         cpustate->sreg[CS].selector = READ32(tss+0x4c) & 0xffff;
1211         i386_load_segment_descriptor(CS);
1212         cpustate->sreg[SS].selector = READ32(tss+0x50) & 0xffff;
1213         i386_load_segment_descriptor(SS);
1214         cpustate->sreg[DS].selector = READ32(tss+0x54) & 0xffff;
1215         i386_load_segment_descriptor(DS);
1216         cpustate->sreg[FS].selector = READ32(tss+0x58) & 0xffff;
1217         i386_load_segment_descriptor(FS);
1218         cpustate->sreg[GS].selector = READ32(tss+0x5c) & 0xffff;
1219         i386_load_segment_descriptor(GS);
1220         /* For nested tasks, we write the outgoing task's selector to the back-link field of the new TSS,
1221            and set the NT flag in the EFLAGS register before setting cr3 as the old tss address might be gone */
1222         if(nested != 0)
1223         {
1224                 WRITE32(tss+0,old_task);
1225                 cpustate->NT = 1;
1226         }
1227         cpustate->cr[3] = READ32(tss+0x1c);  // CR3 (PDBR)
1228         if(oldcr3 != cpustate->cr[3])
1229                 vtlb_flush_dynamic(cpustate->vtlb);
1230
1231         /* Set the busy bit in the new task's descriptor */
1232         if(selector & 0x0004)
1233         {
1234                 ar_byte = READ8(cpustate->ldtr.base + (selector & ~0x0007) + 5);
1235                 WRITE8(cpustate->ldtr.base + (selector & ~0x0007) + 5,ar_byte | 0x02);
1236         }
1237         else
1238         {
1239                 ar_byte = READ8(cpustate->gdtr.base + (selector & ~0x0007) + 5);
1240                 WRITE8(cpustate->gdtr.base + (selector & ~0x0007) + 5,ar_byte | 0x02);
1241         }
1242
1243         CHANGE_PC(cpustate->eip);
1244
1245         cpustate->CPL = (cpustate->sreg[SS].flags >> 5) & 3;
1246 //  printf("386 Task Switch from selector %04x to %04x\n",old_task,selector);
1247 }
1248
1249 void I386_OPS_BASE::i386_check_irq_line()
1250 {
1251         if(!cpustate->smm && cpustate->smi)
1252         {
1253                 pentium_smi();
1254                 return;
1255         }
1256
1257         /* Check if the interrupts are enabled */
1258         if ( (cpustate->irq_state) && cpustate->IF )
1259         {
1260                 cpustate->cycles -= 2;
1261                 i386_trap(cpustate->pic->get_intr_ack(), 1, 0);
1262                 cpustate->irq_state = 0;
1263         }
1264 }
1265
1266 void I386_OPS_BASE::i386_protected_mode_jump( UINT16 seg, UINT32 off, int indirect, int operand32)
1267 {
1268         I386_SREG desc;
1269         I386_CALL_GATE call_gate;
1270         UINT8 CPL,DPL,RPL;
1271         UINT8 SetRPL = 0;
1272         UINT16 segment = seg;
1273         UINT32 offset = off;
1274
1275         /* Check selector is not null */
1276         if((segment & ~0x03) == 0)
1277         {
1278                 logerror("JMP: Segment is null.\n");
1279                 FAULT(FAULT_GP,0)
1280         }
1281         /* Selector is within descriptor table limit */
1282         if((segment & 0x04) == 0)
1283         {
1284                 /* check GDT limit */
1285                 if((segment & ~0x07) > (cpustate->gdtr.limit))
1286                 {
1287                         logerror("JMP: Segment is past GDT limit.\n");
1288                         FAULT(FAULT_GP,segment & 0xfffc)
1289                 }
1290         }
1291         else
1292         {
1293                 /* check LDT limit */
1294                 if((segment & ~0x07) > (cpustate->ldtr.limit))
1295                 {
1296                         logerror("JMP: Segment is past LDT limit.\n");
1297                         FAULT(FAULT_GP,segment & 0xfffc)
1298                 }
1299         }
1300         /* Determine segment type */
1301         memset(&desc, 0, sizeof(desc));
1302         desc.selector = segment;
1303         i386_load_protected_mode_segment(&desc,NULL);
1304         CPL = cpustate->CPL;  // current privilege level
1305         DPL = (desc.flags >> 5) & 0x03;  // descriptor privilege level
1306         RPL = segment & 0x03;  // requested privilege level
1307         if((desc.flags & 0x0018) == 0x0018)
1308         {
1309                 /* code segment */
1310                 if((desc.flags & 0x0004) == 0)
1311                 {
1312                         /* non-conforming */
1313                         if(RPL > CPL)
1314                         {
1315                                 logerror("JMP: RPL %i is less than CPL %i\n",RPL,CPL);
1316                                 FAULT(FAULT_GP,segment & 0xfffc)
1317                         }
1318                         if(DPL != CPL)
1319                         {
1320                                 logerror("JMP: DPL %i is not equal CPL %i\n",DPL,CPL);
1321                                 FAULT(FAULT_GP,segment & 0xfffc)
1322                         }
1323                 }
1324                 else
1325                 {
1326                         /* conforming */
1327                         if(DPL > CPL)
1328                         {
1329                                 logerror("JMP: DPL %i is less than CPL %i\n",DPL,CPL);
1330                                 FAULT(FAULT_GP,segment & 0xfffc)
1331                         }
1332                 }
1333                 SetRPL = 1;
1334                 if((desc.flags & 0x0080) == 0)
1335                 {
1336                         logerror("JMP: Segment is not present\n");
1337                         FAULT(FAULT_NP,segment & 0xfffc)
1338                 }
1339                 if(offset > desc.limit)
1340                 {
1341                         logerror("JMP: Offset is past segment limit\n");
1342                         FAULT(FAULT_GP,0)
1343                 }
1344         }
1345         else
1346         {
1347                 if((desc.flags & 0x0010) != 0)
1348                 {
1349                         logerror("JMP: Segment is a data segment\n");
1350                         FAULT(FAULT_GP,segment & 0xfffc)  // #GP (cannot execute code in a data segment)
1351                 }
1352                 else
1353                 {
1354                         switch(desc.flags & 0x000f)
1355                         {
1356                         case 0x01:  // 286 Available TSS
1357                         case 0x09:  // 386 Available TSS
1358                                 logerror("JMP: Available 386 TSS at %08x\n",cpustate->pc);
1359                                 memset(&desc, 0, sizeof(desc));
1360                                 desc.selector = segment;
1361                                 i386_load_protected_mode_segment(&desc,NULL);
1362                                 DPL = (desc.flags >> 5) & 0x03;  // descriptor privilege level
1363                                 if(DPL < CPL)
1364                                 {
1365                                         logerror("JMP: TSS: DPL %i is less than CPL %i\n",DPL,CPL);
1366                                         FAULT(FAULT_GP,segment & 0xfffc)
1367                                 }
1368                                 if(DPL < RPL)
1369                                 {
1370                                         logerror("JMP: TSS: DPL %i is less than TSS RPL %i\n",DPL,RPL);
1371                                         FAULT(FAULT_GP,segment & 0xfffc)
1372                                 }
1373                                 if((desc.flags & 0x0080) == 0)
1374                                 {
1375                                         logerror("JMP: TSS: Segment is not present\n");
1376                                         FAULT(FAULT_GP,segment & 0xfffc)
1377                                 }
1378                                 if(desc.flags & 0x0008)
1379                                         i386_task_switch(desc.selector,0);
1380                                 else
1381                                         i286_task_switch(desc.selector,0);
1382                                 return;
1383                         case 0x04:  // 286 Call Gate
1384                         case 0x0c:  // 386 Call Gate
1385                                 //logerror("JMP: Call gate at %08x\n",cpustate->pc);
1386                                 SetRPL = 1;
1387                                 memset(&call_gate, 0, sizeof(call_gate));
1388                                 call_gate.segment = segment;
1389                                 i386_load_call_gate(&call_gate);
1390                                 DPL = call_gate.dpl;
1391                                 if(DPL < CPL)
1392                                 {
1393                                         logerror("JMP: Call Gate: DPL %i is less than CPL %i\n",DPL,CPL);
1394                                         FAULT(FAULT_GP,segment & 0xfffc)
1395                                 }
1396                                 if(DPL < RPL)
1397                                 {
1398                                         logerror("JMP: Call Gate: DPL %i is less than RPL %i\n",DPL,RPL);
1399                                         FAULT(FAULT_GP,segment & 0xfffc)
1400                                 }
1401                                 if((desc.flags & 0x0080) == 0)
1402                                 {
1403                                         logerror("JMP: Call Gate: Segment is not present\n");
1404                                         FAULT(FAULT_NP,segment & 0xfffc)
1405                                 }
1406                                 /* Now we examine the segment that the call gate refers to */
1407                                 if(call_gate.selector == 0)
1408                                 {
1409                                         logerror("JMP: Call Gate: Gate selector is null\n");
1410                                         FAULT(FAULT_GP,0)
1411                                 }
1412                                 if(call_gate.selector & 0x04)
1413                                 {
1414                                         if((call_gate.selector & ~0x07) > cpustate->ldtr.limit)
1415                                         {
1416                                                 logerror("JMP: Call Gate: Gate Selector is past LDT segment limit\n");
1417                                                 FAULT(FAULT_GP,call_gate.selector & 0xfffc)
1418                                         }
1419                                 }
1420                                 else
1421                                 {
1422                                         if((call_gate.selector & ~0x07) > cpustate->gdtr.limit)
1423                                         {
1424                                                 logerror("JMP: Call Gate: Gate Selector is past GDT segment limit\n");
1425                                                 FAULT(FAULT_GP,call_gate.selector & 0xfffc)
1426                                         }
1427                                 }
1428                                 desc.selector = call_gate.selector;
1429                                 i386_load_protected_mode_segment(&desc,NULL);
1430                                 DPL = (desc.flags >> 5) & 0x03;
1431                                 if((desc.flags & 0x0018) != 0x18)
1432                                 {
1433                                         logerror("JMP: Call Gate: Gate does not point to a code segment\n");
1434                                         FAULT(FAULT_GP,call_gate.selector & 0xfffc)
1435                                 }
1436                                 if((desc.flags & 0x0004) == 0)
1437                                 {  // non-conforming
1438                                         if(DPL != CPL)
1439                                         {
1440                                                 logerror("JMP: Call Gate: Gate DPL does not equal CPL\n");
1441                                                 FAULT(FAULT_GP,call_gate.selector & 0xfffc)
1442                                         }
1443                                 }
1444                                 else
1445                                 {  // conforming
1446                                         if(DPL > CPL)
1447                                         {
1448                                                 logerror("JMP: Call Gate: Gate DPL is greater than CPL\n");
1449                                                 FAULT(FAULT_GP,call_gate.selector & 0xfffc)
1450                                         }
1451                                 }
1452                                 if((desc.flags & 0x0080) == 0)
1453                                 {
1454                                         logerror("JMP: Call Gate: Gate Segment is not present\n");
1455                                         FAULT(FAULT_NP,call_gate.selector & 0xfffc)
1456                                 }
1457                                 if(call_gate.offset > desc.limit)
1458                                 {
1459                                         logerror("JMP: Call Gate: Gate offset is past Gate segment limit\n");
1460                                         FAULT(FAULT_GP,call_gate.selector & 0xfffc)
1461                                 }
1462                                 segment = call_gate.selector;
1463                                 offset = call_gate.offset;
1464                                 break;
1465                         case 0x05:  // Task Gate
1466                                 logerror("JMP: Task gate at %08x\n",cpustate->pc);
1467                                 memset(&call_gate, 0, sizeof(call_gate));
1468                                 call_gate.segment = segment;
1469                                 i386_load_call_gate(&call_gate);
1470                                 DPL = call_gate.dpl;
1471                                 if(DPL < CPL)
1472                                 {
1473                                         logerror("JMP: Task Gate: Gate DPL %i is less than CPL %i\n",DPL,CPL);
1474                                         FAULT(FAULT_GP,segment & 0xfffc)
1475                                 }
1476                                 if(DPL < RPL)
1477                                 {
1478                                         logerror("JMP: Task Gate: Gate DPL %i is less than CPL %i\n",DPL,CPL);
1479                                         FAULT(FAULT_GP,segment & 0xfffc)
1480                                 }
1481                                 if(call_gate.present == 0)
1482                                 {
1483                                         logerror("JMP: Task Gate: Gate is not present.\n");
1484                                         FAULT(FAULT_GP,segment & 0xfffc)
1485                                 }
1486                                 /* Check the TSS that the task gate points to */
1487                                 desc.selector = call_gate.selector;
1488                                 i386_load_protected_mode_segment(&desc,NULL);
1489                                 DPL = (desc.flags >> 5) & 0x03;  // descriptor privilege level
1490                                 RPL = call_gate.selector & 0x03;  // requested privilege level
1491                                 if(call_gate.selector & 0x04)
1492                                 {
1493                                         logerror("JMP: Task Gate TSS: TSS must be global.\n");
1494                                         FAULT(FAULT_GP,call_gate.selector & 0xfffc)
1495                                 }
1496                                 else
1497                                 {
1498                                         if((call_gate.selector & ~0x07) > cpustate->gdtr.limit)
1499                                         {
1500                                                 logerror("JMP: Task Gate TSS: TSS is past GDT limit.\n");
1501                                                 FAULT(FAULT_GP,call_gate.selector & 0xfffc)
1502                                         }
1503                                 }
1504                                 if((call_gate.ar & 0x000f) == 0x0009 || (call_gate.ar & 0x000f) == 0x0001)
1505                                 {
1506                                         logerror("JMP: Task Gate TSS: Segment is not an available TSS.\n");
1507                                         FAULT(FAULT_GP,call_gate.selector & 0xfffc)
1508                                 }
1509                                 if(call_gate.present == 0)
1510                                 {
1511                                         logerror("JMP: Task Gate TSS: TSS is not present.\n");
1512                                         FAULT(FAULT_NP,call_gate.selector & 0xfffc)
1513                                 }
1514                                 if(call_gate.ar & 0x08)
1515                                         i386_task_switch(call_gate.selector,0);
1516                                 else
1517                                         i286_task_switch(call_gate.selector,0);
1518                                 return;
1519                         default:  // invalid segment type
1520                                 logerror("JMP: Invalid segment type (%i) to jump to.\n",desc.flags & 0x000f);
1521                                 FAULT(FAULT_GP,segment & 0xfffc)
1522                         }
1523                 }
1524         }
1525
1526         if(SetRPL != 0)
1527                 segment = (segment & ~0x03) | cpustate->CPL;
1528         if(operand32 == 0)
1529                 cpustate->eip = offset & 0x0000ffff;
1530         else
1531                 cpustate->eip = offset;
1532         cpustate->sreg[CS].selector = segment;
1533         cpustate->performed_intersegment_jump = 1;
1534         i386_load_segment_descriptor(CS);
1535         CHANGE_PC(cpustate->eip);
1536 }
1537
1538 void I386_OPS_BASE::i386_protected_mode_call( UINT16 seg, UINT32 off, int indirect, int operand32)
1539 {
1540         I386_SREG desc;
1541         I386_CALL_GATE gate;
1542         UINT8 SetRPL = 0;
1543         UINT8 CPL, DPL, RPL;
1544         UINT16 selector = seg;
1545         UINT32 offset = off;
1546         int x;
1547
1548         if((selector & ~0x03) == 0)
1549         {
1550                 logerror("CALL (%08x): Selector is null.\n",cpustate->pc);
1551                 FAULT(FAULT_GP,0)  // #GP(0)
1552         }
1553         if(selector & 0x04)
1554         {
1555                 if((selector & ~0x07) > cpustate->ldtr.limit)
1556                 {
1557                         logerror("CALL: Selector is past LDT limit.\n");
1558                         FAULT(FAULT_GP,selector & ~0x03)  // #GP(selector)
1559                 }
1560         }
1561         else
1562         {
1563                 if((selector & ~0x07) > cpustate->gdtr.limit)
1564                 {
1565                         logerror("CALL: Selector is past GDT limit.\n");
1566                         FAULT(FAULT_GP,selector & ~0x03)  // #GP(selector)
1567                 }
1568         }
1569
1570         /* Determine segment type */
1571         memset(&desc, 0, sizeof(desc));
1572         desc.selector = selector;
1573         i386_load_protected_mode_segment(&desc,NULL);
1574         CPL = cpustate->CPL;  // current privilege level
1575         DPL = (desc.flags >> 5) & 0x03;  // descriptor privilege level
1576         RPL = selector & 0x03;  // requested privilege level
1577         if((desc.flags & 0x0018) == 0x18)  // is a code segment
1578         {
1579                 if(desc.flags & 0x0004)
1580                 {
1581                         /* conforming */
1582                         if(DPL > CPL)
1583                         {
1584                                 logerror("CALL: Code segment DPL %i is greater than CPL %i\n",DPL,CPL);
1585                                 FAULT(FAULT_GP,selector & ~0x03)  // #GP(selector)
1586                         }
1587                 }
1588                 else
1589                 {
1590                         /* non-conforming */
1591                         if(RPL > CPL)
1592                         {
1593                                 logerror("CALL: RPL %i is greater than CPL %i\n",RPL,CPL);
1594                                 FAULT(FAULT_GP,selector & ~0x03)  // #GP(selector)
1595                         }
1596                         if(DPL != CPL)
1597                         {
1598                                 logerror("CALL: Code segment DPL %i is not equal to CPL %i\n",DPL,CPL);
1599                                 FAULT(FAULT_GP,selector & ~0x03)  // #GP(selector)
1600                         }
1601                 }
1602                 SetRPL = 1;
1603                 if((desc.flags & 0x0080) == 0)
1604                 {
1605                         logerror("CALL (%08x): Code segment is not present.\n",cpustate->pc);
1606                         FAULT(FAULT_NP,selector & ~0x03)  // #NP(selector)
1607                 }
1608                 if (operand32 != 0)  // if 32-bit
1609                 {
1610                         UINT32 offset = (STACK_32BIT ? REG32(ESP) - 8 : (REG16(SP) - 8) & 0xffff);
1611                         if(i386_limit_check(SS, offset, 8))
1612                         {
1613                                 logerror("CALL (%08x): Stack has no room for return address.\n",cpustate->pc);
1614                                 FAULT(FAULT_SS,0)  // #SS(0)
1615                         }
1616                 }
1617                 else
1618                 {
1619                         UINT32 offset = (STACK_32BIT ? REG32(ESP) - 4 : (REG16(SP) - 4) & 0xffff);
1620                         if(i386_limit_check(SS, offset, 4))
1621                         {
1622                                 logerror("CALL (%08x): Stack has no room for return address.\n",cpustate->pc);
1623                                 FAULT(FAULT_SS,0)  // #SS(0)
1624                         }
1625                 }
1626                 if(offset > desc.limit)
1627                 {
1628                         logerror("CALL: EIP is past segment limit.\n");
1629                         FAULT(FAULT_GP,0)  // #GP(0)
1630                 }
1631         }
1632         else
1633         {
1634                 /* special segment type */
1635                 if(desc.flags & 0x0010)
1636                 {
1637                         logerror("CALL: Segment is a data segment.\n");
1638                         FAULT(FAULT_GP,desc.selector & ~0x03)  // #GP(selector)
1639                 }
1640                 else
1641                 {
1642                         switch(desc.flags & 0x000f)
1643                         {
1644                         case 0x01:  // Available 286 TSS
1645                         case 0x09:  // Available 386 TSS
1646                                 logerror("CALL: Available TSS at %08x\n",cpustate->pc);
1647                                 if(DPL < CPL)
1648                                 {
1649                                         logerror("CALL: TSS: DPL is less than CPL.\n");
1650                                         FAULT(FAULT_TS,selector & ~0x03) // #TS(selector)
1651                                 }
1652                                 if(DPL < RPL)
1653                                 {
1654                                         logerror("CALL: TSS: DPL is less than RPL.\n");
1655                                         FAULT(FAULT_TS,selector & ~0x03) // #TS(selector)
1656                                 }
1657                                 if(desc.flags & 0x0002)
1658                                 {
1659                                         logerror("CALL: TSS: TSS is busy.\n");
1660                                         FAULT(FAULT_TS,selector & ~0x03) // #TS(selector)
1661                                 }
1662                                 if((desc.flags & 0x0080) == 0)
1663                                 {
1664                                         logerror("CALL: TSS: Segment %02x is not present.\n",selector);
1665                                         FAULT(FAULT_NP,selector & ~0x03) // #NP(selector)
1666                                 }
1667                                 if(desc.flags & 0x08)
1668                                         i386_task_switch(desc.selector,1);
1669                                 else
1670                                         i286_task_switch(desc.selector,1);
1671                                 return;
1672                         case 0x04:  // 286 call gate
1673                         case 0x0c:  // 386 call gate
1674                                 if((desc.flags & 0x000f) == 0x04)
1675                                         operand32 = 0;
1676                                 else
1677                                         operand32 = 1;
1678                                 memset(&gate, 0, sizeof(gate));
1679                                 gate.segment = selector;
1680                                 i386_load_call_gate(&gate);
1681                                 DPL = gate.dpl;
1682                                 //logerror("CALL: Call gate at %08x (%i parameters)\n",cpustate->pc,gate.dword_count);
1683                                 if(DPL < CPL)
1684                                 {
1685                                         logerror("CALL: Call gate DPL %i is less than CPL %i.\n",DPL,CPL);
1686                                         FAULT(FAULT_GP,desc.selector & ~0x03)  // #GP(selector)
1687                                 }
1688                                 if(DPL < RPL)
1689                                 {
1690                                         logerror("CALL: Call gate DPL %i is less than RPL %i.\n",DPL,RPL);
1691                                         FAULT(FAULT_GP,desc.selector & ~0x03)  // #GP(selector)
1692                                 }
1693                                 if(gate.present == 0)
1694                                 {
1695                                         logerror("CALL: Call gate is not present.\n");
1696                                         FAULT(FAULT_NP,desc.selector & ~0x03)  // #GP(selector)
1697                                 }
1698                                 desc.selector = gate.selector;
1699                                 if((gate.selector & ~0x03) == 0)
1700                                 {
1701                                         logerror("CALL: Call gate: Segment is null.\n");
1702                                         FAULT(FAULT_GP,0)  // #GP(0)
1703                                 }
1704                                 if(desc.selector & 0x04)
1705                                 {
1706                                         if((desc.selector & ~0x07) > cpustate->ldtr.limit)
1707                                         {
1708                                                 logerror("CALL: Call gate: Segment is past LDT limit\n");
1709                                                 FAULT(FAULT_GP,desc.selector & ~0x03)  // #GP(selector)
1710                                         }
1711                                 }
1712                                 else
1713                                 {
1714                                         if((desc.selector & ~0x07) > cpustate->gdtr.limit)
1715                                         {
1716                                                 logerror("CALL: Call gate: Segment is past GDT limit\n");
1717                                                 FAULT(FAULT_GP,desc.selector & ~0x03)  // #GP(selector)
1718                                         }
1719                                 }
1720                                 i386_load_protected_mode_segment(&desc,NULL);
1721                                 if((desc.flags & 0x0018) != 0x18)
1722                                 {
1723                                         logerror("CALL: Call gate: Segment is not a code segment.\n");
1724                                         FAULT(FAULT_GP,desc.selector & ~0x03)  // #GP(selector)
1725                                 }
1726                                 DPL = ((desc.flags >> 5) & 0x03);
1727                                 if(DPL > CPL)
1728                                 {
1729                                         logerror("CALL: Call gate: Segment DPL %i is greater than CPL %i.\n",DPL,CPL);
1730                                         FAULT(FAULT_GP,desc.selector & ~0x03)  // #GP(selector)
1731                                 }
1732                                 if((desc.flags & 0x0080) == 0)
1733                                 {
1734                                         logerror("CALL (%08x): Code segment is not present.\n",cpustate->pc);
1735                                         FAULT(FAULT_NP,desc.selector & ~0x03)  // #NP(selector)
1736                                 }
1737                                 if(DPL < CPL && (desc.flags & 0x0004) == 0)
1738                                 {
1739                                         I386_SREG stack;
1740                                         I386_SREG temp;
1741                                         UINT32 oldSS,oldESP;
1742                                         /* more privilege */
1743                                         /* Check new SS segment for privilege level from TSS */
1744                                         memset(&stack, 0, sizeof(stack));
1745                                         stack.selector = i386_get_stack_segment(DPL);
1746                                         i386_load_protected_mode_segment(&stack,NULL);
1747                                         if((stack.selector & ~0x03) == 0)
1748                                         {
1749                                                 logerror("CALL: Call gate: TSS selector is null\n");
1750                                                 FAULT(FAULT_TS,0)  // #TS(0)
1751                                         }
1752                                         if(stack.selector & 0x04)
1753                                         {
1754                                                 if((stack.selector & ~0x07) > cpustate->ldtr.limit)
1755                                                 {
1756                                                         logerror("CALL: Call gate: TSS selector is past LDT limit\n");
1757                                                         FAULT(FAULT_TS,stack.selector)  // #TS(SS selector)
1758                                                 }
1759                                         }
1760                                         else
1761                                         {
1762                                                 if((stack.selector & ~0x07) > cpustate->gdtr.limit)
1763                                                 {
1764                                                         logerror("CALL: Call gate: TSS selector is past GDT limit\n");
1765                                                         FAULT(FAULT_TS,stack.selector)  // #TS(SS selector)
1766                                                 }
1767                                         }
1768                                         if((stack.selector & 0x03) != DPL)
1769                                         {
1770                                                 logerror("CALL: Call gate: Stack selector RPL does not equal code segment DPL %i\n",DPL);
1771                                                 FAULT(FAULT_TS,stack.selector)  // #TS(SS selector)
1772                                         }
1773                                         if(((stack.flags >> 5) & 0x03) != DPL)
1774                                         {
1775                                                 logerror("CALL: Call gate: Stack DPL does not equal code segment DPL %i\n",DPL);
1776                                                 FAULT(FAULT_TS,stack.selector)  // #TS(SS selector)
1777                                         }
1778                                         if((stack.flags & 0x0018) != 0x10 && (stack.flags & 0x0002))
1779                                         {
1780                                                 logerror("CALL: Call gate: Stack segment is not a writable data segment\n");
1781                                                 FAULT(FAULT_TS,stack.selector)  // #TS(SS selector)
1782                                         }
1783                                         if((stack.flags & 0x0080) == 0)
1784                                         {
1785                                                 logerror("CALL: Call gate: Stack segment is not present\n");
1786                                                 FAULT(FAULT_SS,stack.selector)  // #SS(SS selector)
1787                                         }
1788                                         UINT32 newESP = i386_get_stack_ptr(DPL);
1789                                         if(!stack.d)
1790                                         {
1791                                                 newESP &= 0xffff;
1792                                         }
1793                                         if(operand32 != 0)
1794                                         {
1795                                                 if(newESP < (UINT32)((gate.dword_count & 0x1f) + 16))
1796                                                 {
1797                                                         logerror("CALL: Call gate: New stack has no room for 32-bit return address and parameters.\n");
1798                                                         FAULT(FAULT_SS,0) // #SS(0)
1799                                                 }
1800                                                 if(gate.offset > desc.limit)
1801                                                 {
1802                                                         logerror("CALL: Call gate: EIP is past segment limit.\n");
1803                                                         FAULT(FAULT_GP,0) // #GP(0)
1804                                                 }
1805                                         }
1806                                         else
1807                                         {
1808                                                 if(newESP < (UINT32)((gate.dword_count & 0x1f) + 8))
1809                                                 {
1810                                                         logerror("CALL: Call gate: New stack has no room for 16-bit return address and parameters.\n");
1811                                                         FAULT(FAULT_SS,0) // #SS(0)
1812                                                 }
1813                                                 if((gate.offset & 0xffff) > desc.limit)
1814                                                 {
1815                                                         logerror("CALL: Call gate: IP is past segment limit.\n");
1816                                                         FAULT(FAULT_GP,0) // #GP(0)
1817                                                 }
1818                                         }
1819                                         selector = gate.selector;
1820                                         offset = gate.offset;
1821
1822                                         cpustate->CPL = (stack.flags >> 5) & 0x03;
1823                                         /* check for page fault at new stack */
1824                                         WRITE_TEST(stack.base+newESP-1);
1825                                         /* switch to new stack */
1826                                         oldSS = cpustate->sreg[SS].selector;
1827                                         cpustate->sreg[SS].selector = i386_get_stack_segment(cpustate->CPL);
1828                                         if(operand32 != 0)
1829                                         {
1830                                                 oldESP = REG32(ESP);
1831                                         }
1832                                         else
1833                                         {
1834                                                 oldESP = REG16(SP);
1835                                         }
1836                                         i386_load_segment_descriptor(SS );
1837                                         REG32(ESP) = newESP;
1838
1839                                         if(operand32 != 0)
1840                                         {
1841                                                 PUSH32SEG(oldSS);
1842                                                 PUSH32(oldESP);
1843                                         }
1844                                         else
1845                                         {
1846                                                 PUSH16(oldSS);
1847                                                 PUSH16(oldESP & 0xffff);
1848                                         }
1849
1850                                         memset(&temp, 0, sizeof(temp));
1851                                         temp.selector = oldSS;
1852                                         i386_load_protected_mode_segment(&temp,NULL);
1853                                         /* copy parameters from old stack to new stack */
1854                                         for(x=(gate.dword_count & 0x1f)-1;x>=0;x--)
1855                                         {
1856                                                 UINT32 addr = oldESP + (operand32?(x*4):(x*2));
1857                                                 addr = temp.base + (temp.d?addr:(addr&0xffff));
1858                                                 if(operand32)
1859                                                         PUSH32(READ32(addr));
1860                                                 else
1861                                                         PUSH16(READ16(addr));
1862                                         }
1863                                         SetRPL = 1;
1864                                 }
1865                                 else
1866                                 {
1867                                         /* same privilege */
1868                                         if (operand32 != 0)  // if 32-bit
1869                                         {
1870                                                 UINT32 stkoff = (STACK_32BIT ? REG32(ESP) - 8 : (REG16(SP) - 8) & 0xffff);
1871                                                 if(i386_limit_check(SS, stkoff, 8))
1872                                                 {
1873                                                         logerror("CALL: Stack has no room for return address.\n");
1874                                                         FAULT(FAULT_SS,0) // #SS(0)
1875                                                 }
1876                                                 selector = gate.selector;
1877                                                 offset = gate.offset;
1878                                         }
1879                                         else
1880                                         {
1881                                                 UINT32 stkoff = (STACK_32BIT ? REG32(ESP) - 4 : (REG16(SP) - 4) & 0xffff);
1882                                                 if(i386_limit_check(SS, stkoff, 4))
1883                                                 {
1884                                                         logerror("CALL: Stack has no room for return address.\n");
1885                                                         FAULT(FAULT_SS,0) // #SS(0)
1886                                                 }
1887                                                 selector = gate.selector;
1888                                                 offset = gate.offset & 0xffff;
1889                                         }
1890                                         if(offset > desc.limit)
1891                                         {
1892                                                 logerror("CALL: EIP is past segment limit.\n");
1893                                                 FAULT(FAULT_GP,0) // #GP(0)
1894                                         }
1895                                         SetRPL = 1;
1896                                 }
1897                                 break;
1898                         case 0x05:  // task gate
1899                                 logerror("CALL: Task gate at %08x\n",cpustate->pc);
1900                                 memset(&gate, 0, sizeof(gate));
1901                                 gate.segment = selector;
1902                                 i386_load_call_gate(&gate);
1903                                 DPL = gate.dpl;
1904                                 if(DPL < CPL)
1905                                 {
1906                                         logerror("CALL: Task Gate: Gate DPL is less than CPL.\n");
1907                                         FAULT(FAULT_TS,selector & ~0x03) // #TS(selector)
1908                                 }
1909                                 if(DPL < RPL)
1910                                 {
1911                                         logerror("CALL: Task Gate: Gate DPL is less than RPL.\n");
1912                                         FAULT(FAULT_TS,selector & ~0x03) // #TS(selector)
1913                                 }
1914                                 if((gate.ar & 0x0080) == 0)
1915                                 {
1916                                         logerror("CALL: Task Gate: Gate is not present.\n");
1917                                         FAULT(FAULT_NP,selector & ~0x03) // #NP(selector)
1918                                 }
1919                                 /* Check the TSS that the task gate points to */
1920                                 desc.selector = gate.selector;
1921                                 i386_load_protected_mode_segment(&desc,NULL);
1922                                 if(gate.selector & 0x04)
1923                                 {
1924                                         logerror("CALL: Task Gate: TSS is not global.\n");
1925                                         FAULT(FAULT_TS,gate.selector & ~0x03) // #TS(selector)
1926                                 }
1927                                 else
1928                                 {
1929                                         if((gate.selector & ~0x07) > cpustate->gdtr.limit)
1930                                         {
1931                                                 logerror("CALL: Task Gate: TSS is past GDT limit.\n");
1932                                                 FAULT(FAULT_TS,gate.selector & ~0x03) // #TS(selector)
1933                                         }
1934                                 }
1935                                 if(desc.flags & 0x0002)
1936                                 {
1937                                         logerror("CALL: Task Gate: TSS is busy.\n");
1938                                         FAULT(FAULT_TS,gate.selector & ~0x03) // #TS(selector)
1939                                 }
1940                                 if((desc.flags & 0x0080) == 0)
1941                                 {
1942                                         logerror("CALL: Task Gate: TSS is not present.\n");
1943                                         FAULT(FAULT_NP,gate.selector & ~0x03) // #TS(selector)
1944                                 }
1945                                 if(desc.flags & 0x08)
1946                                         i386_task_switch(desc.selector,1);  // with nesting
1947                                 else
1948                                         i286_task_switch(desc.selector,1);
1949                                 return;
1950                         default:
1951                                 logerror("CALL: Invalid special segment type (%i) to jump to.\n",desc.flags & 0x000f);
1952                                 FAULT(FAULT_GP,selector & ~0x07)  // #GP(selector)
1953                         }
1954                 }
1955         }
1956
1957         if(SetRPL != 0)
1958                 selector = (selector & ~0x03) | cpustate->CPL;
1959
1960         UINT32 tempSP = REG32(ESP);
1961         try
1962         {
1963                 // this is ugly but the alternative is worse
1964                 if(operand32 == 0)
1965                 {
1966                         /* 16-bit operand size */
1967                         PUSH16(cpustate->sreg[CS].selector );
1968                         PUSH16(cpustate->eip & 0x0000ffff );
1969                         cpustate->sreg[CS].selector = selector;
1970                         cpustate->performed_intersegment_jump = 1;
1971                         cpustate->eip = offset;
1972                         i386_load_segment_descriptor(CS);
1973                 }
1974                 else
1975                 {
1976                         /* 32-bit operand size */
1977                         PUSH32SEG(cpustate->sreg[CS].selector );
1978                         PUSH32(cpustate->eip );
1979                         cpustate->sreg[CS].selector = selector;
1980                         cpustate->performed_intersegment_jump = 1;
1981                         cpustate->eip = offset;
1982                         i386_load_segment_descriptor(CS );
1983                 }
1984         }
1985         catch(UINT64 e)
1986         {
1987                 REG32(ESP) = tempSP;
1988                 throw e;
1989         }
1990
1991         CHANGE_PC(cpustate->eip);
1992 }
1993
1994 void I386_OPS_BASE::i386_protected_mode_retf(UINT8 count, UINT8 operand32)
1995 {
1996         UINT32 newCS, newEIP;
1997         I386_SREG desc;
1998         UINT8 CPL, RPL, DPL;
1999
2000         UINT32 ea = i386_translate(SS, (STACK_32BIT)?REG32(ESP):REG16(SP), 0, (operand32!=0) ? 8 : 4);
2001
2002         if(operand32 == 0)
2003         {
2004                 newEIP = READ16(ea) & 0xffff;
2005                 newCS = READ16(ea+2) & 0xffff;
2006         }
2007         else
2008         {
2009                 newEIP = READ32(ea);
2010                 newCS = READ32(ea+4) & 0xffff;
2011         }
2012
2013         memset(&desc, 0, sizeof(desc));
2014         desc.selector = newCS;
2015         i386_load_protected_mode_segment(&desc,NULL);
2016         CPL = cpustate->CPL;  // current privilege level
2017         DPL = (desc.flags >> 5) & 0x03;  // descriptor privilege level
2018         RPL = newCS & 0x03;
2019
2020         if(RPL < CPL)
2021         {
2022                 logerror("RETF (%08x): Return segment RPL is less than CPL.\n",cpustate->pc);
2023                 FAULT(FAULT_GP,newCS & ~0x03)
2024         }
2025
2026         if(RPL == CPL)
2027         {
2028                 /* same privilege level */
2029                 if((newCS & ~0x03) == 0)
2030                 {
2031                         logerror("RETF: Return segment is null.\n");
2032                         FAULT(FAULT_GP,0)
2033                 }
2034                 if(newCS & 0x04)
2035                 {
2036                         if((newCS & ~0x07) >= cpustate->ldtr.limit)
2037                         {
2038                                 logerror("RETF: Return segment is past LDT limit.\n");
2039                                 FAULT(FAULT_GP,newCS & ~0x03)
2040                         }
2041                 }
2042                 else
2043                 {
2044                         if((newCS & ~0x07) >= cpustate->gdtr.limit)
2045                         {
2046                                 logerror("RETF: Return segment is past GDT limit.\n");
2047                                 FAULT(FAULT_GP,newCS & ~0x03)
2048                         }
2049                 }
2050                 if((desc.flags & 0x0018) != 0x0018)
2051                 {
2052                         logerror("RETF: Return segment is not a code segment.\n");
2053                         FAULT(FAULT_GP,newCS & ~0x03)
2054                 }
2055                 if(desc.flags & 0x0004)
2056                 {
2057                         if(DPL > RPL)
2058                         {
2059                                 logerror("RETF: Conforming code segment DPL is greater than CS RPL.\n");
2060                                 FAULT(FAULT_GP,newCS & ~0x03)
2061                         }
2062                 }
2063                 else
2064                 {
2065                         if(DPL != RPL)
2066                         {
2067                                 logerror("RETF: Non-conforming code segment DPL does not equal CS RPL.\n");
2068                                 FAULT(FAULT_GP,newCS & ~0x03)
2069                         }
2070                 }
2071                 if((desc.flags & 0x0080) == 0)
2072                 {
2073                         logerror("RETF (%08x): Code segment is not present.\n",cpustate->pc);
2074                         FAULT(FAULT_NP,newCS & ~0x03)
2075                 }
2076                 if(newEIP > desc.limit)
2077                 {
2078                         logerror("RETF: EIP is past code segment limit.\n");
2079                         FAULT(FAULT_GP,0)
2080                 }
2081                 if(operand32 == 0)
2082                 {
2083                         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
2084                         if(i386_limit_check(SS, offset, count + 4) != 0)
2085                         {
2086                                 logerror("RETF (%08x): SP is past stack segment limit.\n",cpustate->pc);
2087                                 FAULT(FAULT_SS,0)
2088                         }
2089                 }
2090                 else
2091                 {
2092                         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
2093                         if(i386_limit_check(SS, offset, count + 8) != 0)
2094                         {
2095                                 logerror("RETF: ESP is past stack segment limit.\n");
2096                                 FAULT(FAULT_SS,0)
2097                         }
2098                 }
2099                 if(STACK_32BIT)
2100                         REG16(SP) += (4+count);
2101                 else
2102                         REG32(ESP) += (8+count);
2103         }
2104         else if(RPL > CPL)
2105         {
2106                 UINT32 newSS, newESP;  // when changing privilege
2107                 /* outer privilege level */
2108                 if(operand32 == 0)
2109                 {
2110                         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
2111                         if(i386_limit_check(SS, offset, count + 8) != 0)
2112                         {
2113                                 logerror("RETF (%08x): SP is past stack segment limit.\n",cpustate->pc);
2114                                 FAULT(FAULT_SS,0)
2115                         }
2116                 }
2117                 else
2118                 {
2119                         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
2120                         if(i386_limit_check(SS, offset, count + 16) != 0)
2121                         {
2122                                 logerror("RETF: ESP is past stack segment limit.\n");
2123                                 FAULT(FAULT_SS,0)
2124                         }
2125                 }
2126                 /* Check CS selector and descriptor */
2127                 if((newCS & ~0x03) == 0)
2128                 {
2129                         logerror("RETF: CS segment is null.\n");
2130                         FAULT(FAULT_GP,0)
2131                 }
2132                 if(newCS & 0x04)
2133                 {
2134                         if((newCS & ~0x07) >= cpustate->ldtr.limit)
2135                         {
2136                                 logerror("RETF: CS segment selector is past LDT limit.\n");
2137                                 FAULT(FAULT_GP,newCS & ~0x03)
2138                         }
2139                 }
2140                 else
2141                 {
2142                         if((newCS & ~0x07) >= cpustate->gdtr.limit)
2143                         {
2144                                 logerror("RETF: CS segment selector is past GDT limit.\n");
2145                                 FAULT(FAULT_GP,newCS & ~0x03)
2146                         }
2147                 }
2148                 if((desc.flags & 0x0018) != 0x0018)
2149                 {
2150                         logerror("RETF: CS segment is not a code segment.\n");
2151                         FAULT(FAULT_GP,newCS & ~0x03)
2152                 }
2153                 if(desc.flags & 0x0004)
2154                 {
2155                         if(DPL > RPL)
2156                         {
2157                                 logerror("RETF: Conforming CS segment DPL is greater than return selector RPL.\n");
2158                                 FAULT(FAULT_GP,newCS & ~0x03)
2159                         }
2160                 }
2161                 else
2162                 {
2163                         if(DPL != RPL)
2164                         {
2165                                 logerror("RETF: Non-conforming CS segment DPL is not equal to return selector RPL.\n");
2166                                 FAULT(FAULT_GP,newCS & ~0x03)
2167                         }
2168                 }
2169                 if((desc.flags & 0x0080) == 0)
2170                 {
2171                         logerror("RETF: CS segment is not present.\n");
2172                         FAULT(FAULT_NP,newCS & ~0x03)
2173                 }
2174                 if(newEIP > desc.limit)
2175                 {
2176                         logerror("RETF: EIP is past return CS segment limit.\n");
2177                         FAULT(FAULT_GP,0)
2178                 }
2179
2180                 if(operand32 == 0)
2181                 {
2182                         ea += count+4;
2183                         newESP = READ16(ea) & 0xffff;
2184                         newSS = READ16(ea+2) & 0xffff;
2185                 }
2186                 else
2187                 {
2188                         ea += count+8;
2189                         newESP = READ32(ea);
2190                         newSS = READ32(ea+4) & 0xffff;
2191                 }
2192
2193                 /* Check SS selector and descriptor */
2194                 desc.selector = newSS;
2195                 i386_load_protected_mode_segment(&desc,NULL);
2196                 DPL = (desc.flags >> 5) & 0x03;  // descriptor privilege level
2197                 if((newSS & ~0x07) == 0)
2198                 {
2199                         logerror("RETF: SS segment is null.\n");
2200                         FAULT(FAULT_GP,0)
2201                 }
2202                 if(newSS & 0x04)
2203                 {
2204                         if((newSS & ~0x07) > cpustate->ldtr.limit)
2205                         {
2206                                 logerror("RETF (%08x): SS segment selector is past LDT limit.\n",cpustate->pc);
2207                                 FAULT(FAULT_GP,newSS & ~0x03)
2208                         }
2209                 }
2210                 else
2211                 {
2212                         if((newSS & ~0x07) > cpustate->gdtr.limit)
2213                         {
2214                                 logerror("RETF (%08x): SS segment selector is past GDT limit.\n",cpustate->pc);
2215                                 FAULT(FAULT_GP,newSS & ~0x03)
2216                         }
2217                 }
2218                 if((newSS & 0x03) != RPL)
2219                 {
2220                         logerror("RETF: SS segment RPL is not equal to CS segment RPL.\n");
2221                         FAULT(FAULT_GP,newSS & ~0x03)
2222                 }
2223                 if((desc.flags & 0x0018) != 0x0010 || (desc.flags & 0x0002) == 0)
2224                 {
2225                         logerror("RETF: SS segment is not a writable data segment.\n");
2226                         FAULT(FAULT_GP,newSS & ~0x03)
2227                 }
2228                 if(((desc.flags >> 5) & 0x03) != RPL)
2229                 {
2230                         logerror("RETF: SS DPL is not equal to CS segment RPL.\n");
2231                         FAULT(FAULT_GP,newSS & ~0x03)
2232                 }
2233                 if((desc.flags & 0x0080) == 0)
2234                 {
2235                         logerror("RETF: SS segment is not present.\n");
2236                         FAULT(FAULT_GP,newSS & ~0x03)
2237                 }
2238                 cpustate->CPL = newCS & 0x03;
2239
2240                 /* Load new SS:(E)SP */
2241                 if(operand32 == 0)
2242                         REG16(SP) = (newESP+count) & 0xffff;
2243                 else
2244                         REG32(ESP) = newESP+count;
2245                 cpustate->sreg[SS].selector = newSS;
2246                 i386_load_segment_descriptor(SS );
2247
2248                 /* Check that DS, ES, FS and GS are valid for the new privilege level */
2249                 i386_check_sreg_validity(DS);
2250                 i386_check_sreg_validity(ES);
2251                 i386_check_sreg_validity(FS);
2252                 i386_check_sreg_validity(GS);
2253         }
2254
2255         /* Load new CS:(E)IP */
2256         if(operand32 == 0)
2257                 cpustate->eip = newEIP & 0xffff;
2258         else
2259                 cpustate->eip = newEIP;
2260         cpustate->sreg[CS].selector = newCS;
2261         i386_load_segment_descriptor(CS );
2262         CHANGE_PC(cpustate->eip);
2263 }
2264
2265 void I386_OPS_BASE::i386_protected_mode_iret(int operand32)
2266 {
2267         UINT32 newCS, newEIP;
2268         UINT32 newSS, newESP;  // when changing privilege
2269         I386_SREG desc,stack;
2270         UINT8 CPL, RPL, DPL;
2271         UINT32 newflags;
2272         UINT8 IOPL = cpustate->IOP1 | (cpustate->IOP2 << 1);
2273
2274         CPL = cpustate->CPL;
2275         UINT32 ea = i386_translate(SS, (STACK_32BIT)?REG32(ESP):REG16(SP), 0, (operand32 != 0) ? 12 : 6);
2276         if(operand32 == 0)
2277         {
2278                 newEIP = READ16(ea) & 0xffff;
2279                 newCS = READ16(ea+2) & 0xffff;
2280                 newflags = READ16(ea+4) & 0xffff;
2281         }
2282         else
2283         {
2284                 newEIP = READ32(ea);
2285                 newCS = READ32(ea+4) & 0xffff;
2286                 newflags = READ32(ea+8);
2287         }
2288
2289         if(V8086_MODE)
2290         {
2291                 UINT32 oldflags = get_flags();
2292                 if(IOPL != 3)
2293                 {
2294                         logerror("IRET (%08x): Is in Virtual 8086 mode and IOPL != 3.\n",cpustate->pc);
2295                         FAULT(FAULT_GP,0)
2296                 }
2297                 if(operand32 == 0)
2298                 {
2299                         cpustate->eip = newEIP & 0xffff;
2300                         cpustate->sreg[CS].selector = newCS & 0xffff;
2301                         newflags &= ~(3<<12);
2302                         newflags |= (((oldflags>>12)&3)<<12);  // IOPL cannot be changed in V86 mode
2303                         set_flags((newflags & 0xffff) | (oldflags & ~0xffff));
2304                         REG16(SP) += 6;
2305                 }
2306                 else
2307                 {
2308                         cpustate->eip = newEIP;
2309                         cpustate->sreg[CS].selector = newCS & 0xffff;
2310                         newflags &= ~(3<<12);
2311                         newflags |= 0x20000 | (((oldflags>>12)&3)<<12);  // IOPL and VM cannot be changed in V86 mode
2312                         set_flags(newflags);
2313                         REG32(ESP) += 12;
2314                 }
2315         }
2316         else if(NESTED_TASK)
2317         {
2318                 UINT32 task = READ32(cpustate->task.base);
2319                 /* Task Return */
2320                 logerror("IRET (%08x): Nested task return.\n",cpustate->pc);
2321                 /* Check back-link selector in TSS */
2322                 if(task & 0x04)
2323                 {
2324                         logerror("IRET: Task return: Back-linked TSS is not in GDT.\n");
2325                         FAULT(FAULT_TS,task & ~0x03)
2326                 }
2327                 if((task & ~0x07) >= cpustate->gdtr.limit)
2328                 {
2329                         logerror("IRET: Task return: Back-linked TSS is not in GDT.\n");
2330                         FAULT(FAULT_TS,task & ~0x03)
2331                 }
2332                 memset(&desc, 0, sizeof(desc));
2333                 desc.selector = task;
2334                 i386_load_protected_mode_segment(&desc,NULL);
2335                 if((desc.flags & 0x001f) != 0x000b)
2336                 {
2337                         logerror("IRET (%08x): Task return: Back-linked TSS is not a busy TSS.\n",cpustate->pc);
2338                         FAULT(FAULT_TS,task & ~0x03)
2339                 }
2340                 if((desc.flags & 0x0080) == 0)
2341                 {
2342                         logerror("IRET: Task return: Back-linked TSS is not present.\n");
2343                         FAULT(FAULT_NP,task & ~0x03)
2344                 }
2345                 if(desc.flags & 0x08)
2346                         i386_task_switch(desc.selector,0);
2347                 else
2348                         i286_task_switch(desc.selector,0);
2349                 return;
2350         }
2351         else
2352         {
2353                 if(newflags & 0x00020000) // if returning to virtual 8086 mode
2354                 {
2355                         // 16-bit iret can't reach here
2356                         newESP = READ32(ea+12);
2357                         newSS = READ32(ea+16) & 0xffff;
2358                         /* Return to v86 mode */
2359                         //logerror("IRET (%08x): Returning to Virtual 8086 mode.\n",cpustate->pc);
2360                         if(CPL != 0)
2361                         {
2362                                 UINT32 oldflags = get_flags();
2363                                 newflags = (newflags & ~0x00003000) | (oldflags & 0x00003000);
2364                                 if(CPL > IOPL)
2365                                         newflags = (newflags & ~0x200 ) | (oldflags & 0x200);
2366                         }
2367                         set_flags(newflags);
2368                         cpustate->eip = POP32() & 0xffff;  // high 16 bits are ignored
2369                         cpustate->sreg[CS].selector = POP32() & 0xffff;
2370                         POP32();  // already set flags
2371                         newESP = POP32();
2372                         newSS = POP32() & 0xffff;
2373                         cpustate->sreg[ES].selector = POP32() & 0xffff;
2374                         cpustate->sreg[DS].selector = POP32() & 0xffff;
2375                         cpustate->sreg[FS].selector = POP32() & 0xffff;
2376                         cpustate->sreg[GS].selector = POP32() & 0xffff;
2377                         REG32(ESP) = newESP;  // all 32 bits are loaded
2378                         cpustate->sreg[SS].selector = newSS;
2379                         i386_load_segment_descriptor(ES);
2380                         i386_load_segment_descriptor(DS);
2381                         i386_load_segment_descriptor(FS);
2382                         i386_load_segment_descriptor(GS);
2383                         i386_load_segment_descriptor(SS);
2384                         cpustate->CPL = 3;  // Virtual 8086 tasks are always run at CPL 3
2385                 }
2386                 else
2387                 {
2388                         if(operand32 == 0)
2389                         {
2390                                 UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
2391                                 if(i386_limit_check(SS, offset, 4) != 0)
2392                                 {
2393                                         logerror("IRET: Data on stack is past SS limit.\n");
2394                                         FAULT(FAULT_SS,0)
2395                                 }
2396                         }
2397                         else
2398                         {
2399                                 UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
2400                                 if(i386_limit_check(SS, offset, 8) != 0)
2401                                 {
2402                                         logerror("IRET: Data on stack is past SS limit.\n");
2403                                         FAULT(FAULT_SS,0)
2404                                 }
2405                         }
2406                         RPL = newCS & 0x03;
2407                         if(RPL < CPL)
2408                         {
2409                                 logerror("IRET (%08x): Return CS RPL is less than CPL.\n",cpustate->pc);
2410                                 FAULT(FAULT_GP,newCS & ~0x03)
2411                         }
2412                         if(RPL == CPL)
2413                         {
2414                                 /* return to same privilege level */
2415                                 if(operand32 == 0)
2416                                 {
2417                                         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
2418                                         if(i386_limit_check(SS, offset, 6) != 0)
2419                                         {
2420                                                 logerror("IRET (%08x): Data on stack is past SS limit.\n",cpustate->pc);
2421                                                 FAULT(FAULT_SS,0)
2422                                         }
2423                                 }
2424                                 else
2425                                 {
2426                                         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
2427                                         if(i386_limit_check(SS, offset, 12) != 0)
2428                                         {
2429                                                 logerror("IRET (%08x): Data on stack is past SS limit.\n",cpustate->pc);
2430                                                 FAULT(FAULT_SS,0)
2431                                         }
2432                                 }
2433                                 if((newCS & ~0x03) == 0)
2434                                 {
2435                                         logerror("IRET: Return CS selector is null.\n");
2436                                         FAULT(FAULT_GP,0)
2437                                 }
2438                                 if(newCS & 0x04)
2439                                 {
2440                                         if((newCS & ~0x07) >= cpustate->ldtr.limit)
2441                                         {
2442                                                 logerror("IRET: Return CS selector (%04x) is past LDT limit.\n",newCS);
2443                                                 FAULT(FAULT_GP,newCS & ~0x03)
2444                                         }
2445                                 }
2446                                 else
2447                                 {
2448                                         if((newCS & ~0x07) >= cpustate->gdtr.limit)
2449                                         {
2450                                                 logerror("IRET: Return CS selector is past GDT limit.\n");
2451                                                 FAULT(FAULT_GP,newCS & ~0x03)
2452                                         }
2453                                 }
2454                                 memset(&desc, 0, sizeof(desc));
2455                                 desc.selector = newCS;
2456                                 i386_load_protected_mode_segment(&desc,NULL);
2457                                 DPL = (desc.flags >> 5) & 0x03;  // descriptor privilege level
2458                                 RPL = newCS & 0x03;
2459                                 if((desc.flags & 0x0018) != 0x0018)
2460                                 {
2461                                         logerror("IRET (%08x): Return CS segment is not a code segment.\n",cpustate->pc);
2462                                         FAULT(FAULT_GP,newCS & ~0x07)
2463                                 }
2464                                 if(desc.flags & 0x0004)
2465                                 {
2466                                         if(DPL > RPL)
2467                                         {
2468                                                 logerror("IRET: Conforming return CS DPL is greater than CS RPL.\n");
2469                                                 FAULT(FAULT_GP,newCS & ~0x03)
2470                                         }
2471                                 }
2472                                 else
2473                                 {
2474                                         if(DPL != RPL)
2475                                         {
2476                                                 logerror("IRET: Non-conforming return CS DPL is not equal to CS RPL.\n");
2477                                                 FAULT(FAULT_GP,newCS & ~0x03)
2478                                         }
2479                                 }
2480                                 if((desc.flags & 0x0080) == 0)
2481                                 {
2482                                         logerror("IRET: (%08x) Return CS segment is not present.\n", cpustate->pc);
2483                                         FAULT(FAULT_NP,newCS & ~0x03)
2484                                 }
2485                                 if(newEIP > desc.limit)
2486                                 {
2487                                         logerror("IRET: Return EIP is past return CS limit.\n");
2488                                         FAULT(FAULT_GP,0)
2489                                 }
2490
2491                                 if(CPL != 0)
2492                                 {
2493                                         UINT32 oldflags = get_flags();
2494                                         newflags = (newflags & ~0x00003000) | (oldflags & 0x00003000);
2495                                 }
2496
2497                                 if(operand32 == 0)
2498                                 {
2499                                         cpustate->eip = newEIP;
2500                                         cpustate->sreg[CS].selector = newCS;
2501                                         set_flags(newflags);
2502                                         REG16(SP) += 6;
2503                                 }
2504                                 else
2505                                 {
2506                                         cpustate->eip = newEIP;
2507                                         cpustate->sreg[CS].selector = newCS & 0xffff;
2508                                         set_flags(newflags);
2509                                         REG32(ESP) += 12;
2510                                 }
2511                         }
2512                         else if(RPL > CPL)
2513                         {
2514                                 /* return to outer privilege level */
2515                                 memset(&desc, 0, sizeof(desc));
2516                                 desc.selector = newCS;
2517                                 i386_load_protected_mode_segment(&desc,NULL);
2518                                 DPL = (desc.flags >> 5) & 0x03;  // descriptor privilege level
2519                                 RPL = newCS & 0x03;
2520                                 if(operand32 == 0)
2521                                 {
2522                                         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
2523                                         if(i386_limit_check(SS, offset, 10) != 0)
2524                                         {
2525                                                 logerror("IRET: SP is past SS limit.\n");
2526                                                 FAULT(FAULT_SS,0)
2527                                         }
2528                                 }
2529                                 else
2530                                 {
2531                                         UINT32 offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
2532                                         if(i386_limit_check(SS, offset, 20) != 0)
2533                                         {
2534                                                 logerror("IRET: ESP is past SS limit.\n");
2535                                                 FAULT(FAULT_SS,0)
2536                                         }
2537                                 }
2538                                 /* Check CS selector and descriptor */
2539                                 if((newCS & ~0x03) == 0)
2540                                 {
2541                                         logerror("IRET: Return CS selector is null.\n");
2542                                         FAULT(FAULT_GP,0)
2543                                 }
2544                                 if(newCS & 0x04)
2545                                 {
2546                                         if((newCS & ~0x07) >= cpustate->ldtr.limit)
2547                                         {
2548                                                 logerror("IRET: Return CS selector is past LDT limit.\n");
2549                                                 FAULT(FAULT_GP,newCS & ~0x03);
2550                                         }
2551                                 }
2552                                 else
2553                                 {
2554                                         if((newCS & ~0x07) >= cpustate->gdtr.limit)
2555                                         {
2556                                                 logerror("IRET: Return CS selector is past GDT limit.\n");
2557                                                 FAULT(FAULT_GP,newCS & ~0x03);
2558                                         }
2559                                 }
2560                                 if((desc.flags & 0x0018) != 0x0018)
2561                                 {
2562                                         logerror("IRET: Return CS segment is not a code segment.\n");
2563                                         FAULT(FAULT_GP,newCS & ~0x03)
2564                                 }
2565                                 if(desc.flags & 0x0004)
2566                                 {
2567                                         if(DPL > RPL)
2568                                         {
2569                                                 logerror("IRET: Conforming return CS DPL is greater than CS RPL.\n");
2570                                                 FAULT(FAULT_GP,newCS & ~0x03)
2571                                         }
2572                                 }
2573                                 else
2574                                 {
2575                                         if(DPL != RPL)
2576                                         {
2577                                                 logerror("IRET: Non-conforming return CS DPL does not equal CS RPL.\n");
2578                                                 FAULT(FAULT_GP,newCS & ~0x03)
2579                                         }
2580                                 }
2581                                 if((desc.flags & 0x0080) == 0)
2582                                 {
2583                                         logerror("IRET: Return CS segment is not present.\n");
2584                                         FAULT(FAULT_NP,newCS & ~0x03)
2585                                 }
2586
2587                                 /* Check SS selector and descriptor */
2588                                 if(operand32 == 0)
2589                                 {
2590                                         newESP = READ16(ea+6) & 0xffff;
2591                                         newSS = READ16(ea+8) & 0xffff;
2592                                 }
2593                                 else
2594                                 {
2595                                         newESP = READ32(ea+12);
2596                                         newSS = READ32(ea+16) & 0xffff;
2597                                 }
2598                                 memset(&stack, 0, sizeof(stack));
2599                                 stack.selector = newSS;
2600                                 i386_load_protected_mode_segment(&stack,NULL);
2601                                 DPL = (stack.flags >> 5) & 0x03;
2602                                 if((newSS & ~0x03) == 0)
2603                                 {
2604                                         logerror("IRET: Return SS selector is null.\n");
2605                                         FAULT(FAULT_GP,0)
2606                                 }
2607                                 if(newSS & 0x04)
2608                                 {
2609                                         if((newSS & ~0x07) >= cpustate->ldtr.limit)
2610                                         {
2611                                                 logerror("IRET: Return SS selector is past LDT limit.\n");
2612                                                 FAULT(FAULT_GP,newSS & ~0x03);
2613                                         }
2614                                 }
2615                                 else
2616                                 {
2617                                         if((newSS & ~0x07) >= cpustate->gdtr.limit)
2618                                         {
2619                                                 logerror("IRET: Return SS selector is past GDT limit.\n");
2620                                                 FAULT(FAULT_GP,newSS & ~0x03);
2621                                         }
2622                                 }
2623                                 if((newSS & 0x03) != RPL)
2624                                 {
2625                                         logerror("IRET: Return SS RPL is not equal to return CS RPL.\n");
2626                                         FAULT(FAULT_GP,newSS & ~0x03)
2627                                 }
2628                                 if((stack.flags & 0x0018) != 0x0010)
2629                                 {
2630                                         logerror("IRET: Return SS segment is not a data segment.\n");
2631                                         FAULT(FAULT_GP,newSS & ~0x03)
2632                                 }
2633                                 if((stack.flags & 0x0002) == 0)
2634                                 {
2635                                         logerror("IRET: Return SS segment is not writable.\n");
2636                                         FAULT(FAULT_GP,newSS & ~0x03)
2637                                 }
2638                                 if(DPL != RPL)
2639                                 {
2640                                         logerror("IRET: Return SS DPL does not equal SS RPL.\n");
2641                                         FAULT(FAULT_GP,newSS & ~0x03)
2642                                 }
2643                                 if((stack.flags & 0x0080) == 0)
2644                                 {
2645                                         logerror("IRET: Return SS segment is not present.\n");
2646                                         FAULT(FAULT_NP,newSS & ~0x03)
2647                                 }
2648                                 if(newEIP > desc.limit)
2649                                 {
2650                                         logerror("IRET: EIP is past return CS limit.\n");
2651                                         FAULT(FAULT_GP,0)
2652                                 }
2653
2654 //              if(operand32 == 0)
2655 //                  REG16(SP) += 10;
2656 //              else
2657 //                  REG32(ESP) += 20;
2658
2659                                 // IOPL can only change if CPL is zero
2660                                 if(CPL != 0)
2661                                 {
2662                                         UINT32 oldflags = get_flags();
2663                                         newflags = (newflags & ~0x00003000) | (oldflags & 0x00003000);
2664                                         if(CPL > IOPL)
2665                                                 newflags = (newflags & ~0x200 ) | (oldflags & 0x200);
2666                                 }
2667
2668                                 if(operand32 == 0)
2669                                 {
2670                                         cpustate->eip = newEIP & 0xffff;
2671                                         cpustate->sreg[CS].selector = newCS;
2672                                         set_flags(newflags);
2673                                         REG16(SP) = newESP & 0xffff;
2674                                         cpustate->sreg[SS].selector = newSS;
2675                                 }
2676                                 else
2677                                 {
2678                                         cpustate->eip = newEIP;
2679                                         cpustate->sreg[CS].selector = newCS & 0xffff;
2680                                         set_flags(newflags);
2681                                         REG32(ESP) = newESP;
2682                                         cpustate->sreg[SS].selector = newSS & 0xffff;
2683                                 }
2684                                 cpustate->CPL = newCS & 0x03;
2685                                 i386_load_segment_descriptor(SS);
2686
2687                                 /* Check that DS, ES, FS and GS are valid for the new privilege level */
2688                                 i386_check_sreg_validity(DS);
2689                                 i386_check_sreg_validity(ES);
2690                                 i386_check_sreg_validity(FS);
2691                                 i386_check_sreg_validity(GS);
2692                         }
2693                 }
2694         }
2695
2696         i386_load_segment_descriptor(CS);
2697         CHANGE_PC(cpustate->eip);
2698 }
2699
2700 #include "cycles.h"
2701
2702 void I386_OPS_BASE::build_cycle_table()
2703 {
2704         uint32_t i, j;
2705         for (j=0; j < X86_NUM_CPUS; j++)
2706         {
2707 //              cycle_table_rm[j] = (UINT8 *)malloc(CYCLES_NUM_OPCODES);
2708 //              cycle_table_pm[j] = (UINT8 *)malloc(CYCLES_NUM_OPCODES);
2709
2710                 for (i=0; i < sizeof(x86_cycle_table)/sizeof(X86_CYCLE_TABLE); i++)
2711                 {
2712                         int opcode = x86_cycle_table[i].op;
2713                         cycle_table_rm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][0];
2714                         cycle_table_pm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][1];
2715                 }
2716         }
2717 }
2718
2719 void I386_OPS_BASE::report_invalid_opcode()
2720 {
2721 #ifndef DEBUG_MISSING_OPCODE
2722         logerror("i386: Invalid opcode %02X at %08X %s\n", cpustate->opcode, cpustate->pc - 1, cpustate->lock ? "with lock" : "");
2723 #else
2724         logerror("i386: Invalid opcode");
2725         for (int a = 0; a < cpustate->opcode_bytes_length; a++)
2726                 logerror(" %02X", cpustate->opcode_bytes[a]);
2727         logerror(" at %08X\n", cpustate->opcode_pc);
2728 #endif
2729 }
2730
2731 void I386_OPS_BASE::report_invalid_modrm( const char* opcode, UINT8 modrm)
2732 {
2733 #ifndef DEBUG_MISSING_OPCODE
2734         logerror("i386: Invalid %s modrm %01X at %08X\n", opcode, modrm, cpustate->pc - 2);
2735 #else
2736         logerror("i386: Invalid %s modrm %01X", opcode, modrm);
2737         for (int a = 0; a < cpustate->opcode_bytes_length; a++)
2738                 logerror(" %02X", cpustate->opcode_bytes[a]);
2739         logerror(" at %08X\n", cpustate->opcode_pc);
2740 #endif
2741         i386_trap(6, 0, 0);
2742 }
2743
2744 /* Forward declarations */
2745
2746
2747 void I386_OPS_BASE::I386OP(decode_opcode)()
2748 {
2749         cpustate->opcode = FETCH();
2750
2751         if(cpustate->lock && !cpustate->lock_table[0][cpustate->opcode])
2752                 return I386OP(invalid)();
2753
2754         if( cpustate->operand_size )
2755                 (this->*cpustate->opcode_table1_32[cpustate->opcode])();
2756         else
2757                 (this->*cpustate->opcode_table1_16[cpustate->opcode])();
2758 }
2759
2760 /* Two-byte opcode 0f xx */
2761 void I386_OPS_BASE::I386OP(decode_two_byte)()
2762 {
2763         cpustate->opcode = FETCH();
2764
2765         if(cpustate->lock && !cpustate->lock_table[1][cpustate->opcode])
2766                 return I386OP(invalid)();
2767
2768         if( cpustate->operand_size )
2769                 (this->*cpustate->opcode_table2_32[cpustate->opcode])();
2770         else
2771                 (this->*cpustate->opcode_table2_16[cpustate->opcode])();
2772 }
2773
2774 /* Three-byte opcode 0f 38 xx */
2775 void I386_OPS_BASE::I386OP(decode_three_byte38)()
2776 {
2777         cpustate->opcode = FETCH();
2778
2779         if (cpustate->operand_size)
2780                 (this->*cpustate->opcode_table338_32[cpustate->opcode])();
2781         else
2782                 (this->*cpustate->opcode_table338_16[cpustate->opcode])();
2783 }
2784
2785 /* Three-byte opcode 0f 3a xx */
2786 void I386_OPS_BASE::I386OP(decode_three_byte3a)()
2787 {
2788         cpustate->opcode = FETCH();
2789
2790         if (cpustate->operand_size)
2791                 (this->*cpustate->opcode_table33a_32[cpustate->opcode])();
2792         else
2793                 (this->*cpustate->opcode_table33a_16[cpustate->opcode])();
2794 }
2795
2796 /* Three-byte opcode prefix 66 0f xx */
2797 void I386_OPS_BASE::I386OP(decode_three_byte66)()
2798 {
2799         cpustate->opcode = FETCH();
2800         if( cpustate->operand_size )
2801                 (this->*cpustate->opcode_table366_32[cpustate->opcode])();
2802         else
2803                 (this->*cpustate->opcode_table366_16[cpustate->opcode])();
2804 }
2805
2806 /* Three-byte opcode prefix f2 0f xx */
2807 void I386_OPS_BASE::I386OP(decode_three_bytef2)()
2808 {
2809         cpustate->opcode = FETCH();
2810         if( cpustate->operand_size )
2811                 (this->*cpustate->opcode_table3f2_32[cpustate->opcode])();
2812         else
2813                 (this->*cpustate->opcode_table3f2_16[cpustate->opcode])();
2814 }
2815
2816 /* Three-byte opcode prefix f3 0f */
2817 void I386_OPS_BASE::I386OP(decode_three_bytef3)()
2818 {
2819         cpustate->opcode = FETCH();
2820         if( cpustate->operand_size )
2821                 (this->*cpustate->opcode_table3f3_32[cpustate->opcode])();
2822         else
2823                 (this->*cpustate->opcode_table3f3_16[cpustate->opcode])();
2824 }
2825
2826 /* Four-byte opcode prefix 66 0f 38 xx */
2827 void I386_OPS_BASE::I386OP(decode_four_byte3866)()
2828 {
2829         cpustate->opcode = FETCH();
2830         if (cpustate->operand_size)
2831                 (this->*cpustate->opcode_table46638_32[cpustate->opcode])();
2832         else
2833                 (this->*cpustate->opcode_table46638_16[cpustate->opcode])();
2834 }
2835
2836 /* Four-byte opcode prefix 66 0f 3a xx */
2837 void I386_OPS_BASE::I386OP(decode_four_byte3a66)()
2838 {
2839         cpustate->opcode = FETCH();
2840         if (cpustate->operand_size)
2841                 (this->*cpustate->opcode_table4663a_32[cpustate->opcode])();
2842         else
2843                 (this->*cpustate->opcode_table4663a_16[cpustate->opcode])();
2844 }
2845
2846 /* Four-byte opcode prefix f2 0f 38 xx */
2847 void I386_OPS_BASE::I386OP(decode_four_byte38f2)()
2848 {
2849         cpustate->opcode = FETCH();
2850         if (cpustate->operand_size)
2851                 (this->*cpustate->opcode_table4f238_32[cpustate->opcode])();
2852         else
2853                 (this->*cpustate->opcode_table4f238_16[cpustate->opcode])();
2854 }
2855
2856 /* Four-byte opcode prefix f2 0f 3a xx */
2857 void I386_OPS_BASE::I386OP(decode_four_byte3af2)()
2858 {
2859         cpustate->opcode = FETCH();
2860         if (cpustate->operand_size)
2861                 (this->*cpustate->opcode_table4f23a_32[cpustate->opcode])();
2862         else
2863                 (this->*cpustate->opcode_table4f23a_16[cpustate->opcode])();
2864 }
2865
2866 /* Four-byte opcode prefix f3 0f 38 xx */
2867 void I386_OPS_BASE::I386OP(decode_four_byte38f3)()
2868 {
2869         cpustate->opcode = FETCH();
2870         if (cpustate->operand_size)
2871                 (this->*cpustate->opcode_table4f338_32[cpustate->opcode])();
2872         else
2873                 (this->*cpustate->opcode_table4f338_16[cpustate->opcode])();
2874 }
2875
2876
2877 /*************************************************************************/
2878
2879 void I386_OPS_BASE::i386_postload()
2880 {
2881         int i;
2882         for (i = 0; i < 6; i++)
2883                 i386_load_segment_descriptor(i);
2884         CHANGE_PC(cpustate->eip);
2885 }
2886
2887 #include "./i386_ops_table.h"
2888
2889 i386_state *I386_OPS_BASE::i386_common_init(int tlbsize)
2890 {
2891         int i, j;
2892         static const int regs8[8] = {AL,CL,DL,BL,AH,CH,DH,BH};
2893         static const int regs16[8] = {AX,CX,DX,BX,SP,BP,SI,DI};
2894         static const int regs32[8] = {EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI};
2895         cpustate = &__cpustate;
2896         //cpustate = (i386_state *)malloc(sizeof(i386_state));
2897         //x86_cycle_table = _x86_cycle_table_real;
2898         //x86_opcode_table = _x86_opcode_table_fake;
2899
2900         assert((sizeof(XMM_REG)/sizeof(double)) == 2);
2901
2902         build_cycle_table();
2903
2904         for( i=0; i < 256; i++ ) {
2905                 int c=0;
2906                 for( j=0; j < 8; j++ ) {
2907                         if( i & (1 << j) )
2908                                 c++;
2909                 }
2910                 i386_parity_table[i] = ~(c & 0x1) & 0x1;
2911         }
2912
2913         for( i=0; i < 256; i++ ) {
2914                 i386_MODRM_table[i].reg.b = regs8[(i >> 3) & 0x7];
2915                 i386_MODRM_table[i].reg.w = regs16[(i >> 3) & 0x7];
2916                 i386_MODRM_table[i].reg.d = regs32[(i >> 3) & 0x7];
2917
2918                 i386_MODRM_table[i].rm.b = regs8[i & 0x7];
2919                 i386_MODRM_table[i].rm.w = regs16[i & 0x7];
2920                 i386_MODRM_table[i].rm.d = regs32[i & 0x7];
2921         }
2922
2923         cpustate->vtlb = vtlb_alloc((void *)cpustate, AS_PROGRAM, 0, tlbsize);
2924         cpustate->smi = false;
2925         cpustate->lock = false;
2926
2927 //      i386_interface *intf = (i386_interface *) device->static_config();
2928 //
2929 //      if (intf != NULL)
2930 //              cpustate->smiact.resolve(intf->smiact, *device);
2931 //      else
2932 //              memset(&cpustate->smiact, 0, sizeof(cpustate->smiact));
2933
2934         zero_state();
2935         cpustate->program = d_mem;
2936         cpustate->io = d_io;
2937         cpustate->pic = d_pic;
2938
2939         return cpustate;
2940 }
2941 void I386_OPS_BASE::i386_vtlb_free(void)
2942 {
2943         vtlb_free(cpustate->vtlb);
2944         cpustate->vtlb = NULL;
2945 }
2946
2947 void I386_OPS_BASE::i386_free_state(void)
2948 {
2949         //if(cpustate != NULL) free(cpustate);
2950 }
2951
2952 void *I386_OPS_BASE::cpu_init_i386(void)
2953 {
2954         i386_common_init(32);
2955         build_opcode_table(OP_I386);
2956         cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_I386];
2957         cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_I386];
2958         return cpustate;
2959 }
2960
2961
2962 void I386_OPS_BASE::process_state_SREG(I386_SREG* val, FILEIO* state_fio)
2963 {
2964         state_fio->StateValue(val->selector);
2965         state_fio->StateValue(val->flags);
2966         state_fio->StateValue(val->base);
2967         state_fio->StateValue(val->limit);
2968         state_fio->StateValue(val->d);
2969         state_fio->StateValue(val->valid);
2970 }
2971
2972 void I386_OPS_BASE::process_state_SYS_TABLE(I386_SYS_TABLE* val, FILEIO* state_fio)
2973 {
2974         state_fio->StateValue(val->base);
2975         state_fio->StateValue(val->limit);
2976 }
2977
2978 void I386_OPS_BASE::process_state_SEG_DESC(I386_SEG_DESC* val, FILEIO* state_fio)
2979 {
2980         state_fio->StateValue(val->segment);
2981         state_fio->StateValue(val->flags);
2982         state_fio->StateValue(val->base);
2983         state_fio->StateValue(val->limit);
2984 }
2985
2986 void I386_OPS_BASE::process_state_GPR(I386_GPR* val, FILEIO* state_fio)
2987 {
2988         state_fio->StateArray(val->d, sizeof(val->d), 1);
2989         state_fio->StateArray(val->w, sizeof(val->w), 1);
2990         state_fio->StateArray(val->b, sizeof(val->b), 1);
2991 }
2992
2993 void I386_OPS_BASE::process_state_floatx80(floatx80* val, FILEIO* state_fio)
2994 {
2995         state_fio->StateValue(val->high);
2996         state_fio->StateValue(val->low);
2997 }
2998
2999 void I386_OPS_BASE::process_state_XMM_REG(XMM_REG* val, FILEIO* state_fio)
3000 {
3001         state_fio->StateArray(val->b, sizeof(val->b), 1);
3002         state_fio->StateArray(val->w, sizeof(val->w), 1);
3003         state_fio->StateArray(val->d, sizeof(val->d), 1);
3004         state_fio->StateArray(val->q, sizeof(val->q), 1);
3005         state_fio->StateArray(val->c, sizeof(val->c), 1);
3006         state_fio->StateArray(val->s, sizeof(val->s), 1);
3007         state_fio->StateArray(val->i, sizeof(val->i), 1);
3008         state_fio->StateArray(val->l, sizeof(val->l), 1);
3009         state_fio->StateArray(val->f, sizeof(val->f), 1);
3010         state_fio->StateArray(val->f64, sizeof(val->f64), 1);
3011 }
3012
3013 void I386_OPS_BASE::process_state_vtlb(vtlb_state* val, FILEIO* state_fio)
3014 {
3015 //      state_fio->StateValue(val->space);
3016 //      state_fio->StateValue(val->dynamic);
3017 //      state_fio->StateValue(val->fixed);
3018         state_fio->StateValue(val->dynindex);
3019 //      state_fio->StateValue(val->pageshift);
3020 //      state_fio->StateValue(val->addrwidth);
3021         if(val->live != NULL) {
3022                 state_fio->StateArray(val->live, val->fixed + val->dynamic, 1);
3023         }
3024         if(val->fixedpages != NULL) {
3025                 state_fio->StateArray(val->fixedpages, val->fixed, 1);
3026         }
3027         if(val->table != NULL) {
3028                 state_fio->StateArray(val->table, (size_t) 1 << (val->addrwidth - val->pageshift), 1);
3029         }
3030 }
3031
3032
3033 bool I386_OPS_BASE::process_state(FILEIO *state_fio, bool loading)
3034 {
3035         // ToDo: Write endian
3036         vtlb_state *vtlb = cpustate->vtlb;
3037         void *cpudevice = NULL;
3038         offs_t *live = NULL;
3039         int live_size = 0;
3040         int *fixedpages = NULL;
3041         int fixedpages_size = 0;
3042         vtlb_entry *table = NULL;
3043         int table_size = 0;
3044 //      vtlb_entry *save = NULL;
3045 //      int save_size = 0;
3046
3047         
3048         process_state_GPR(&cpustate->reg, state_fio);
3049         for(int i = 0; i < (int)array_length(cpustate->sreg); i++) {
3050                 process_state_SREG(&cpustate->sreg[i], state_fio);
3051         }
3052         state_fio->StateValue(cpustate->eip);
3053         state_fio->StateValue(cpustate->pc);
3054         state_fio->StateValue(cpustate->prev_eip);
3055         state_fio->StateValue(cpustate->prev_pc);
3056         state_fio->StateValue(cpustate->eflags);
3057         state_fio->StateValue(cpustate->eflags_mask);
3058         state_fio->StateValue(cpustate->CF);
3059         state_fio->StateValue(cpustate->DF);
3060         state_fio->StateValue(cpustate->SF);
3061         state_fio->StateValue(cpustate->OF);
3062         state_fio->StateValue(cpustate->ZF);
3063         state_fio->StateValue(cpustate->PF);
3064         state_fio->StateValue(cpustate->AF);
3065         state_fio->StateValue(cpustate->IF);
3066         state_fio->StateValue(cpustate->TF);
3067         state_fio->StateValue(cpustate->IOP1);
3068         state_fio->StateValue(cpustate->IOP2);
3069         state_fio->StateValue(cpustate->NT);
3070         state_fio->StateValue(cpustate->RF);
3071         state_fio->StateValue(cpustate->VM);
3072         state_fio->StateValue(cpustate->AC);
3073         state_fio->StateValue(cpustate->VIF);
3074         state_fio->StateValue(cpustate->VIP);
3075         state_fio->StateValue(cpustate->ID);
3076         state_fio->StateValue(cpustate->CPL);
3077         state_fio->StateValue(cpustate->performed_intersegment_jump);
3078         state_fio->StateValue(cpustate->delayed_interrupt_enable);
3079         state_fio->StateArray(cpustate->cr, sizeof(cpustate->cr), 1);
3080         state_fio->StateArray(cpustate->dr, sizeof(cpustate->dr), 1);
3081         state_fio->StateArray(cpustate->tr, sizeof(cpustate->tr), 1);
3082         process_state_SYS_TABLE(&cpustate->gdtr, state_fio);
3083         process_state_SYS_TABLE(&cpustate->idtr, state_fio);
3084         process_state_SEG_DESC(&cpustate->task, state_fio);
3085         process_state_SEG_DESC(&cpustate->ldtr, state_fio);
3086         state_fio->StateValue(cpustate->ext);
3087         state_fio->StateValue(cpustate->halted);
3088         state_fio->StateValue(cpustate->busreq);
3089         state_fio->StateValue(cpustate->shutdown);
3090         state_fio->StateValue(cpustate->operand_size);
3091         state_fio->StateValue(cpustate->xmm_operand_size);
3092         state_fio->StateValue(cpustate->address_size);
3093         state_fio->StateValue(cpustate->operand_prefix);
3094         state_fio->StateValue(cpustate->address_prefix);
3095         state_fio->StateValue(cpustate->segment_prefix);
3096         state_fio->StateValue(cpustate->segment_override);
3097
3098         state_fio->StateValue(cpustate->total_cycles);
3099
3100         state_fio->StateValue(cpustate->cycles);
3101         state_fio->StateValue(cpustate->extra_cycles);
3102         state_fio->StateValue(cpustate->base_cycles);
3103         state_fio->StateValue(cpustate->opcode);
3104         state_fio->StateValue(cpustate->irq_state);
3105         state_fio->StateValue(cpustate->a20_mask);
3106         state_fio->StateValue(cpustate->cpuid_max_input_value_eax);
3107         state_fio->StateValue(cpustate->cpuid_id0);
3108         state_fio->StateValue(cpustate->cpuid_id1);
3109         state_fio->StateValue(cpustate->cpuid_id2);
3110         state_fio->StateValue(cpustate->cpu_version);
3111         state_fio->StateValue(cpustate->feature_flags);
3112         state_fio->StateValue(cpustate->tsc);
3113         state_fio->StateArray(cpustate->perfctr, sizeof(cpustate->perfctr), 1);
3114         for(int i = 0; i < array_length(cpustate->x87_reg); i++) {
3115                 process_state_floatx80(&cpustate->x87_reg[i], state_fio);
3116         }
3117         state_fio->StateValue(cpustate->x87_cw);
3118         state_fio->StateValue(cpustate->x87_sw);
3119         state_fio->StateValue(cpustate->x87_tw);
3120         state_fio->StateValue(cpustate->x87_data_ptr);
3121         state_fio->StateValue(cpustate->x87_inst_ptr);
3122         state_fio->StateValue(cpustate->x87_opcode);
3123         for(int i = 0; i < array_length(cpustate->sse_reg); i++) {
3124                 process_state_XMM_REG(&cpustate->sse_reg[i], state_fio);
3125         }
3126         state_fio->StateValue(cpustate->mxcsr);
3127         state_fio->StateArray(&cpustate->lock_table[0][0], sizeof(cpustate->lock_table), 1);
3128         
3129         if(cpustate->vtlb != NULL) {
3130                 process_state_vtlb(cpustate->vtlb, state_fio);
3131         }
3132         state_fio->StateValue(cpustate->smm);
3133         state_fio->StateValue(cpustate->smi);
3134         state_fio->StateValue(cpustate->smi_latched);
3135         state_fio->StateValue(cpustate->nmi_masked);
3136         state_fio->StateValue(cpustate->nmi_latched);
3137         state_fio->StateValue(cpustate->smbase);
3138 //      state_fio->StateValue(cpustate->smiact);
3139         state_fio->StateValue(cpustate->lock);
3140 #ifdef DEBUG_MISSING_OPCODE
3141         state_fio->StateArray(cpustate->opcode_bytes, sizeof(cpustate->opcode_bytes), 1);
3142         state_fio->StateValue(cpustate->opcode_pc);
3143         state_fio->StateValue(cpustate->opcode_bytes_length);
3144 #endif
3145
3146         return true;
3147 }
3148
3149 void I386_OPS_BASE::build_opcode_table(UINT32 features)
3150 {
3151         int i;
3152         i386_state *_cpustate = cpustate;
3153         for (i=0; i < 256; i++)
3154         {
3155                 _cpustate->opcode_table1_16[i] = &I386_OPS_BASE::I386OP(invalid);
3156                 _cpustate->opcode_table1_32[i] = &I386_OPS_BASE::I386OP(invalid);
3157                 _cpustate->opcode_table2_16[i] = &I386_OPS_BASE::I386OP(invalid);
3158                 _cpustate->opcode_table2_32[i] = &I386_OPS_BASE::I386OP(invalid);
3159                 _cpustate->opcode_table366_16[i] = &I386_OPS_BASE::I386OP(invalid);
3160                 _cpustate->opcode_table366_32[i] = &I386_OPS_BASE::I386OP(invalid);
3161                 _cpustate->opcode_table3f2_16[i] = &I386_OPS_BASE::I386OP(invalid);
3162                 _cpustate->opcode_table3f2_32[i] = &I386_OPS_BASE::I386OP(invalid);
3163                 _cpustate->opcode_table3f3_16[i] = &I386_OPS_BASE::I386OP(invalid);
3164                 _cpustate->opcode_table3f3_32[i] = &I386_OPS_BASE::I386OP(invalid);
3165                 _cpustate->lock_table[0][i] = false;
3166                 _cpustate->lock_table[1][i] = false;
3167         }
3168
3169         for (i=0; i < (int)(sizeof(x86_opcode_table) / sizeof(X86_OPCODE)); i++)
3170         {
3171                 const X86_OPCODE *op = &x86_opcode_table[i];
3172
3173                 if ((op->flags & features))
3174                 {
3175                         if (op->flags & OP_2BYTE)
3176                         {
3177                                 _cpustate->opcode_table2_32[op->opcode] = op->handler32;
3178                                 _cpustate->opcode_table2_16[op->opcode] = op->handler16;
3179                                 _cpustate->opcode_table366_32[op->opcode] = op->handler32;
3180                                 _cpustate->opcode_table366_16[op->opcode] = op->handler16;
3181                                 _cpustate->lock_table[1][op->opcode] = op->lockable;
3182                         }
3183                         else if (op->flags & OP_3BYTE66)
3184                         {
3185                                 _cpustate->opcode_table366_32[op->opcode] = op->handler32;
3186                                 _cpustate->opcode_table366_16[op->opcode] = op->handler16;
3187                         }
3188                         else if (op->flags & OP_3BYTEF2)
3189                         {
3190                                 _cpustate->opcode_table3f2_32[op->opcode] = op->handler32;
3191                                 _cpustate->opcode_table3f2_16[op->opcode] = op->handler16;
3192                         }
3193                         else if (op->flags & OP_3BYTEF3)
3194                         {
3195                                 _cpustate->opcode_table3f3_32[op->opcode] = op->handler32;
3196                                 _cpustate->opcode_table3f3_16[op->opcode] = op->handler16;
3197                         }
3198                         else if (op->flags & OP_3BYTE38)
3199                         {
3200                                 _cpustate->opcode_table338_32[op->opcode] = op->handler32;
3201                                 _cpustate->opcode_table338_16[op->opcode] = op->handler16;
3202                         }
3203                         else if (op->flags & OP_3BYTE3A)
3204                         {
3205                                 _cpustate->opcode_table33a_32[op->opcode] = op->handler32;
3206                                 _cpustate->opcode_table33a_16[op->opcode] = op->handler16;
3207                         }
3208                         else if (op->flags & OP_4BYTE3866)
3209                         {
3210                                 _cpustate->opcode_table46638_32[op->opcode] = op->handler32;
3211                                 _cpustate->opcode_table46638_16[op->opcode] = op->handler16;
3212                         }
3213                         else if (op->flags & OP_4BYTE3A66)
3214                         {
3215                                 _cpustate->opcode_table4663a_32[op->opcode] = op->handler32;
3216                                 _cpustate->opcode_table4663a_16[op->opcode] = op->handler16;
3217                         }
3218                         else if (op->flags & OP_4BYTE38F2)
3219                         {
3220                                 _cpustate->opcode_table4f238_32[op->opcode] = op->handler32;
3221                                 _cpustate->opcode_table4f238_16[op->opcode] = op->handler16;
3222                         }
3223                         else if (op->flags & OP_4BYTE3AF2)
3224                         {
3225                                 _cpustate->opcode_table4f23a_32[op->opcode] = op->handler32;
3226                                 _cpustate->opcode_table4f23a_16[op->opcode] = op->handler16;
3227                         }
3228                         else if (op->flags & OP_4BYTE38F3)
3229                         {
3230                                 _cpustate->opcode_table4f338_32[op->opcode] = op->handler32;
3231                                 _cpustate->opcode_table4f338_16[op->opcode] = op->handler16;
3232                         }
3233                         else
3234                         {
3235                                 _cpustate->opcode_table1_32[op->opcode] = op->handler32;
3236                                 _cpustate->opcode_table1_16[op->opcode] = op->handler16;
3237                                 _cpustate->lock_table[0][op->opcode] = op->lockable;
3238                         }
3239                 }
3240         }
3241
3242 }
3243
3244 void I386_OPS_BASE::zero_state()
3245 {
3246         memset( &cpustate->reg, 0, sizeof(cpustate->reg) );
3247         memset( cpustate->sreg, 0, sizeof(cpustate->sreg) );
3248
3249         cpustate->total_cycles = 0;
3250         cpustate->prev_total_cycles = 0;
3251         
3252         cpustate->eip = 0;
3253         cpustate->pc = 0;
3254         cpustate->prev_eip = 0;
3255         cpustate->eflags = 0;
3256         cpustate->eflags_mask = 0;
3257         cpustate->CF = 0;
3258         cpustate->DF = 0;
3259         cpustate->SF = 0;
3260         cpustate->OF = 0;
3261         cpustate->ZF = 0;
3262         cpustate->PF = 0;
3263         cpustate->AF = 0;
3264         cpustate->IF = 0;
3265         cpustate->TF = 0;
3266         cpustate->IOP1 = 0;
3267         cpustate->IOP2 = 0;
3268         cpustate->NT = 0;
3269         cpustate->RF = 0;
3270         cpustate->VM = 0;
3271         cpustate->AC = 0;
3272         cpustate->VIF = 0;
3273         cpustate->VIP = 0;
3274         cpustate->ID = 0;
3275         cpustate->CPL = 0;
3276         cpustate->performed_intersegment_jump = 0;
3277         cpustate->delayed_interrupt_enable = 0;
3278         memset( cpustate->cr, 0, sizeof(cpustate->cr) );
3279         memset( cpustate->dr, 0, sizeof(cpustate->dr) );
3280         memset( cpustate->tr, 0, sizeof(cpustate->tr) );
3281         memset( &cpustate->gdtr, 0, sizeof(cpustate->gdtr) );
3282         memset( &cpustate->idtr, 0, sizeof(cpustate->idtr) );
3283         memset( &cpustate->task, 0, sizeof(cpustate->task) );
3284         memset( &cpustate->ldtr, 0, sizeof(cpustate->ldtr) );
3285         cpustate->ext = 0;
3286         cpustate->halted = 0;
3287         cpustate->busreq = 0;
3288         cpustate->shutdown = 0;
3289         cpustate->operand_size = 0;
3290         cpustate->xmm_operand_size = 0;
3291         cpustate->address_size = 0;
3292         cpustate->operand_prefix = 0;
3293         cpustate->address_prefix = 0;
3294         cpustate->segment_prefix = 0;
3295         cpustate->segment_override = 0;
3296 //      cpustate->cycles = 0;
3297 //      cpustate->base_cycles = 0;
3298         cpustate->opcode = 0;
3299         cpustate->irq_state = 0;
3300         cpustate->a20_mask = 0;
3301         cpustate->cpuid_max_input_value_eax = 0;
3302         cpustate->cpuid_id0 = 0;
3303         cpustate->cpuid_id1 = 0;
3304         cpustate->cpuid_id2 = 0;
3305         cpustate->cpu_version = 0;
3306         cpustate->feature_flags = 0;
3307         cpustate->tsc = 0;
3308         cpustate->perfctr[0] = cpustate->perfctr[1] = 0;
3309         memset( cpustate->x87_reg, 0, sizeof(cpustate->x87_reg) );
3310         cpustate->x87_cw = 0;
3311         cpustate->x87_sw = 0;
3312         cpustate->x87_tw = 0;
3313         cpustate->x87_data_ptr = 0;
3314         cpustate->x87_inst_ptr = 0;
3315         cpustate->x87_opcode = 0;
3316         memset( cpustate->sse_reg, 0, sizeof(cpustate->sse_reg) );
3317         cpustate->mxcsr = 0;
3318         cpustate->smm = false;
3319         cpustate->smi = false;
3320         cpustate->smi_latched = false;
3321         cpustate->nmi_masked = false;
3322         cpustate->nmi_latched = false;
3323         cpustate->smbase = 0;
3324 #ifdef DEBUG_MISSING_OPCODE
3325         memset( cpustate->opcode_bytes, 0, sizeof(cpustate->opcode_bytes) );
3326         cpustate->opcode_pc = 0;
3327         cpustate->opcode_bytes_length = 0;
3328 #endif
3329 }
3330
3331 void I386_OPS_BASE::cpu_reset_i386(void)
3332 {
3333         zero_state();
3334         vtlb_flush_dynamic(cpustate->vtlb);
3335
3336         cpustate->sreg[CS].selector = 0xf000;
3337         cpustate->sreg[CS].base     = 0xffff0000;
3338         cpustate->sreg[CS].limit    = 0xffff;
3339         cpustate->sreg[CS].flags    = 0x93;
3340         cpustate->sreg[CS].valid    = true;
3341
3342         cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
3343         cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
3344         cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093;
3345         cpustate->sreg[DS].valid = cpustate->sreg[ES].valid = cpustate->sreg[FS].valid = cpustate->sreg[GS].valid = cpustate->sreg[SS].valid =true;
3346
3347         cpustate->idtr.base = 0;
3348         cpustate->idtr.limit = 0x3ff;
3349         cpustate->smm = false;
3350         cpustate->smi_latched = false;
3351         cpustate->nmi_masked = false;
3352         cpustate->nmi_latched = false;
3353
3354         cpustate->a20_mask = ~0;
3355
3356         cpustate->cr[0] = 0x7fffffe0; // reserved bits set to 1
3357         cpustate->eflags = 0;
3358         cpustate->eflags_mask = 0x00037fd7;
3359         cpustate->eip = 0xfff0;
3360
3361         // [11:8] Family
3362         // [ 7:4] Model
3363         // [ 3:0] Stepping ID
3364         // Family 3 (386), Model 0 (DX), Stepping 8 (D1)
3365         REG32(EAX) = 0;
3366         REG32(EDX) = (3 << 8) | (0 << 4) | (8);
3367
3368         cpustate->CPL = 0;
3369
3370         CHANGE_PC(cpustate->eip);
3371 }
3372
3373 void I386_OPS_BASE::pentium_smi()
3374 {
3375         UINT32 smram_state = cpustate->smbase + 0xfe00;
3376         UINT32 old_cr0 = cpustate->cr[0];
3377         UINT32 old_flags = get_flags();
3378
3379         if(cpustate->smm)
3380                 return;
3381
3382         cpustate->cr[0] &= ~(0x8000000d);
3383         set_flags(2);
3384 //      if(!cpustate->smiact.isnull())
3385 //              cpustate->smiact(true);
3386         cpustate->smm = true;
3387         cpustate->smi_latched = false;
3388
3389         // save state
3390         WRITE32(cpustate->cr[4], smram_state+SMRAM_IP5_CR4);
3391         WRITE32(cpustate->sreg[ES].limit, smram_state+SMRAM_IP5_ESLIM);
3392         WRITE32(cpustate->sreg[ES].base, smram_state+SMRAM_IP5_ESBASE);
3393         WRITE32(cpustate->sreg[ES].flags, smram_state+SMRAM_IP5_ESACC);
3394         WRITE32(cpustate->sreg[CS].limit, smram_state+SMRAM_IP5_CSLIM);
3395         WRITE32(cpustate->sreg[CS].base, smram_state+SMRAM_IP5_CSBASE);
3396         WRITE32(cpustate->sreg[CS].flags, smram_state+SMRAM_IP5_CSACC);
3397         WRITE32(cpustate->sreg[SS].limit, smram_state+SMRAM_IP5_SSLIM);
3398         WRITE32(cpustate->sreg[SS].base, smram_state+SMRAM_IP5_SSBASE);
3399         WRITE32(cpustate->sreg[SS].flags, smram_state+SMRAM_IP5_SSACC);
3400         WRITE32(cpustate->sreg[DS].limit, smram_state+SMRAM_IP5_DSLIM);
3401         WRITE32(cpustate->sreg[DS].base, smram_state+SMRAM_IP5_DSBASE);
3402         WRITE32(cpustate->sreg[DS].flags, smram_state+SMRAM_IP5_DSACC);
3403         WRITE32(cpustate->sreg[FS].limit, smram_state+SMRAM_IP5_FSLIM);
3404         WRITE32(cpustate->sreg[FS].base, smram_state+SMRAM_IP5_FSBASE);
3405         WRITE32(cpustate->sreg[FS].flags, smram_state+SMRAM_IP5_FSACC);
3406         WRITE32(cpustate->sreg[GS].limit, smram_state+SMRAM_IP5_GSLIM);
3407         WRITE32(cpustate->sreg[GS].base, smram_state+SMRAM_IP5_GSBASE);
3408         WRITE32(cpustate->sreg[GS].flags, smram_state+SMRAM_IP5_GSACC);
3409         WRITE32(cpustate->ldtr.flags, smram_state+SMRAM_IP5_LDTACC);
3410         WRITE32(cpustate->ldtr.limit, smram_state+SMRAM_IP5_LDTLIM);
3411         WRITE32(cpustate->ldtr.base, smram_state+SMRAM_IP5_LDTBASE);
3412         WRITE32(cpustate->gdtr.limit, smram_state+SMRAM_IP5_GDTLIM);
3413         WRITE32(cpustate->gdtr.base, smram_state+SMRAM_IP5_GDTBASE);
3414         WRITE32(cpustate->idtr.limit, smram_state+SMRAM_IP5_IDTLIM);
3415         WRITE32(cpustate->idtr.base, smram_state+SMRAM_IP5_IDTBASE);
3416         WRITE32(cpustate->task.limit, smram_state+SMRAM_IP5_TRLIM);
3417         WRITE32(cpustate->task.base, smram_state+SMRAM_IP5_TRBASE);
3418         WRITE32(cpustate->task.flags, smram_state+SMRAM_IP5_TRACC);
3419
3420         WRITE32(cpustate->sreg[ES].selector, smram_state+SMRAM_ES);
3421         WRITE32(cpustate->sreg[CS].selector, smram_state+SMRAM_CS);
3422         WRITE32(cpustate->sreg[SS].selector, smram_state+SMRAM_SS);
3423         WRITE32(cpustate->sreg[DS].selector, smram_state+SMRAM_DS);
3424         WRITE32(cpustate->sreg[FS].selector, smram_state+SMRAM_FS);
3425         WRITE32(cpustate->sreg[GS].selector, smram_state+SMRAM_GS);
3426         WRITE32(cpustate->ldtr.segment, smram_state+SMRAM_LDTR);
3427         WRITE32(cpustate->task.segment, smram_state+SMRAM_TR);
3428
3429         WRITE32(cpustate->dr[7], smram_state+SMRAM_DR7);
3430         WRITE32(cpustate->dr[6], smram_state+SMRAM_DR6);
3431         WRITE32(REG32(EAX), smram_state+SMRAM_EAX);
3432         WRITE32(REG32(ECX), smram_state+SMRAM_ECX);
3433         WRITE32(REG32(EDX), smram_state+SMRAM_EDX);
3434         WRITE32(REG32(EBX), smram_state+SMRAM_EBX);
3435         WRITE32(REG32(ESP), smram_state+SMRAM_ESP);
3436         WRITE32(REG32(EBP), smram_state+SMRAM_EBP);
3437         WRITE32(REG32(ESI), smram_state+SMRAM_ESI);
3438         WRITE32(REG32(EDI), smram_state+SMRAM_EDI);
3439         WRITE32(cpustate->eip, smram_state+SMRAM_EIP);
3440         WRITE32(old_flags, smram_state+SMRAM_EFLAGS);
3441         WRITE32(cpustate->cr[3], smram_state+SMRAM_CR3);
3442         WRITE32(old_cr0, smram_state+SMRAM_CR0);
3443
3444         cpustate->sreg[DS].selector = cpustate->sreg[ES].selector = cpustate->sreg[FS].selector = cpustate->sreg[GS].selector = cpustate->sreg[SS].selector = 0;
3445         cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
3446         cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffffffff;
3447         cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x8093;
3448         cpustate->sreg[DS].valid = cpustate->sreg[ES].valid = cpustate->sreg[FS].valid = cpustate->sreg[GS].valid = cpustate->sreg[SS].valid =true;
3449         cpustate->sreg[CS].selector = 0x3000; // pentium only, ppro sel = smbase >> 4
3450         cpustate->sreg[CS].base = cpustate->smbase;
3451         cpustate->sreg[CS].limit = 0xffffffff;
3452         cpustate->sreg[CS].flags = 0x8093;
3453         cpustate->sreg[CS].valid = true;
3454         cpustate->cr[4] = 0;
3455         cpustate->dr[7] = 0x400;
3456         cpustate->eip = 0x8000;
3457
3458         cpustate->nmi_masked = true;
3459         CHANGE_PC(cpustate->eip);
3460 }
3461
3462 void I386_OPS_BASE::i386_set_irq_line(int irqline, int state)
3463 {
3464     int first_cycles = cpustate->cycles;
3465
3466         if (state != CLEAR_LINE && cpustate->halted)
3467         {
3468                 cpustate->halted = 0;
3469         }
3470
3471         if ( irqline == INPUT_LINE_NMI )
3472         {
3473                 /* NMI (I do not think that this is 100% right) */
3474                 if(cpustate->nmi_masked)
3475                 {
3476                         cpustate->nmi_latched = true;
3477                         return;
3478                 }
3479                 if ( state )
3480                         i386_trap(2, 1, 0);
3481         }
3482         else
3483         {
3484                 cpustate->irq_state = state;
3485         }
3486         cpustate->extra_cycles += first_cycles - cpustate->cycles;
3487         cpustate->cycles = first_cycles;
3488 }
3489
3490 void I386_OPS_BASE::i386_set_a20_line(int state)
3491 {
3492         if (state)
3493         {
3494                 cpustate->a20_mask = ~0;
3495         }
3496         else
3497         {
3498                 cpustate->a20_mask = ~(1 << 20);
3499         }
3500         // TODO: how does A20M and the tlb interact
3501         vtlb_flush_dynamic(cpustate->vtlb);
3502 }
3503
3504 // BASE execution : EXECUTE without DMA, BIOS and debugger.
3505 #include "../../debugger.h"
3506 int I386_OPS_BASE::cpu_execute_i386(int cycles)
3507 {
3508         CHANGE_PC(cpustate->eip);
3509
3510         if (cpustate->halted || cpustate->busreq)
3511         {
3512                 if (cycles == -1) {
3513                         int passed_cycles = max(1, cpustate->extra_cycles);
3514                         // this is main cpu, cpustate->cycles is not used
3515                         /*cpustate->cycles = */cpustate->extra_cycles = 0;
3516                         cpustate->tsc += passed_cycles;
3517                         cpustate->total_cycles += passed_cycles;
3518                         return passed_cycles;
3519                 } else {
3520                         cpustate->cycles += cycles;
3521                         cpustate->base_cycles = cpustate->cycles;
3522
3523                         /* adjust for any interrupts that came in */
3524                         cpustate->cycles -= cpustate->extra_cycles;
3525                         cpustate->extra_cycles = 0;
3526
3527                         /* if busreq is raised, spin cpu while remained clock */
3528                         if (cpustate->cycles > 0) {
3529                                 cpustate->cycles = 0;
3530                         }
3531                         int passed_cycles = cpustate->base_cycles - cpustate->cycles;
3532                         cpustate->tsc += passed_cycles;
3533                         cpustate->total_cycles += passed_cycles;
3534                         return passed_cycles;
3535                 }
3536         }
3537
3538         if (cycles == -1) {
3539                 cpustate->cycles = 1;
3540         } else {
3541                 cpustate->cycles += cycles;
3542         }
3543         cpustate->base_cycles = cpustate->cycles;
3544
3545         /* adjust for any interrupts that came in */
3546         cpustate->cycles -= cpustate->extra_cycles;
3547         cpustate->extra_cycles = 0;
3548
3549         while( cpustate->cycles > 0 && !cpustate->busreq )
3550         {
3551                         int first_cycles = cpustate->cycles;
3552                         i386_check_irq_line();
3553                         cpustate->operand_size = cpustate->sreg[CS].d;
3554                         cpustate->xmm_operand_size = 0;
3555                         cpustate->address_size = cpustate->sreg[CS].d;
3556                         cpustate->operand_prefix = 0;
3557                         cpustate->address_prefix = 0;
3558
3559                         cpustate->ext = 1;
3560                         int old_tf = cpustate->TF;
3561
3562                         cpustate->debugger->add_cpu_trace(cpustate->pc);
3563                         cpustate->segment_prefix = 0;
3564                         cpustate->prev_eip = cpustate->eip;
3565                         cpustate->prev_pc = cpustate->pc;
3566
3567                         if(cpustate->delayed_interrupt_enable != 0)
3568                         {
3569                                 cpustate->IF = 1;
3570                                 cpustate->delayed_interrupt_enable = 0;
3571                         }
3572 #ifdef DEBUG_MISSING_OPCODE
3573                         cpustate->opcode_bytes_length = 0;
3574                         cpustate->opcode_pc = cpustate->pc;
3575 #endif
3576                         try
3577                         {
3578                                 I386OP(decode_opcode)();
3579                                 if(cpustate->TF && old_tf)
3580                                 {
3581                                         cpustate->prev_eip = cpustate->eip;
3582                                         cpustate->ext = 1;
3583                                         i386_trap(1,0,0);
3584                                 }
3585                                 if(cpustate->lock && (cpustate->opcode != 0xf0))
3586                                         cpustate->lock = false;
3587                         }
3588                         catch(UINT64 e)
3589                         {
3590                                 cpustate->ext = 1;
3591                                 i386_trap_with_error(e&0xffffffff,0,0,e>>32);
3592                         }
3593                         /* adjust for any interrupts that came in */
3594                         cpustate->cycles -= cpustate->extra_cycles;
3595                         cpustate->extra_cycles = 0;
3596                         cpustate->total_cycles += first_cycles - cpustate->cycles;
3597         }
3598
3599         /* if busreq is raised, spin cpu while remained clock */
3600         if (cpustate->cycles > 0 && cpustate->busreq) {
3601                 cpustate->total_cycles += cpustate->cycles;
3602                 cpustate->cycles = 0;
3603         }
3604         int passed_cycles = cpustate->base_cycles - cpustate->cycles;
3605         cpustate->tsc += passed_cycles;
3606         cpustate->total_cycles += passed_cycles;
3607         return passed_cycles;
3608 }
3609
3610 /*************************************************************************/
3611
3612 int I386_OPS_BASE::cpu_translate_i386(void *cpudevice, address_spacenum space, int intention, offs_t *address)
3613 {
3614         i386_state *cpu_state = (i386_state *)cpudevice;
3615         int ret = TRUE;
3616         if(space == AS_PROGRAM)
3617                 ret = i386_translate_address(intention, address, NULL);
3618         *address &= cpu_state->a20_mask;
3619         return ret;
3620 }
3621
3622 /*****************************************************************************/
3623 /* Intel 486 */
3624
3625
3626 void *I386_OPS_BASE::cpu_init_i486(void)
3627 {
3628         i386_common_init(32);
3629         build_opcode_table(OP_I386 | OP_FPU | OP_I486);
3630         build_x87_opcode_table();
3631         cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_I486];
3632         cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_I486];
3633         return cpustate;
3634 }
3635
3636 void I386_OPS_BASE::cpu_reset_i486(void)
3637 {
3638         zero_state();
3639         vtlb_flush_dynamic(cpustate->vtlb);
3640
3641         cpustate->sreg[CS].selector = 0xf000;
3642         cpustate->sreg[CS].base     = 0xffff0000;
3643         cpustate->sreg[CS].limit    = 0xffff;
3644         cpustate->sreg[CS].flags    = 0x0093;
3645
3646         cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
3647         cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
3648         cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093;
3649
3650         cpustate->idtr.base = 0;
3651         cpustate->idtr.limit = 0x3ff;
3652
3653         cpustate->a20_mask = ~0;
3654
3655         cpustate->cr[0] = 0x00000010;
3656         cpustate->eflags = 0;
3657         cpustate->eflags_mask = 0x00077fd7;
3658         cpustate->eip = 0xfff0;
3659         cpustate->smm = false;
3660         cpustate->smi_latched = false;
3661         cpustate->nmi_masked = false;
3662         cpustate->nmi_latched = false;
3663
3664         x87_reset();
3665
3666         // [11:8] Family
3667         // [ 7:4] Model
3668         // [ 3:0] Stepping ID
3669         // Family 4 (486), Model 0/1 (DX), Stepping 3
3670         REG32(EAX) = 0;
3671         REG32(EDX) = (4 << 8) | (0 << 4) | (3);
3672
3673         CHANGE_PC(cpustate->eip);
3674 }
3675
3676 /*****************************************************************************/
3677 /* Pentium */
3678
3679
3680 void *I386_OPS_BASE::cpu_init_pentium(void)
3681 {
3682         // 64 dtlb small, 8 dtlb large, 32 itlb
3683         i386_common_init(96);
3684         build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM);
3685         build_x87_opcode_table();
3686         cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM];
3687         cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM];
3688         return cpustate;
3689 }
3690
3691 void I386_OPS_BASE::cpu_reset_pentium(void)
3692 {
3693         zero_state();
3694         vtlb_flush_dynamic(cpustate->vtlb);
3695
3696         cpustate->sreg[CS].selector = 0xf000;
3697         cpustate->sreg[CS].base     = 0xffff0000;
3698         cpustate->sreg[CS].limit    = 0xffff;
3699         cpustate->sreg[CS].flags    = 0x0093;
3700
3701         cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
3702         cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
3703         cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093;
3704
3705         cpustate->idtr.base = 0;
3706         cpustate->idtr.limit = 0x3ff;
3707
3708         cpustate->a20_mask = ~0;
3709
3710         cpustate->cr[0] = 0x00000010;
3711         cpustate->eflags = 0x00200000;
3712         cpustate->eflags_mask = 0x003f7fd7;
3713         cpustate->eip = 0xfff0;
3714         cpustate->mxcsr = 0x1f80;
3715         cpustate->smm = false;
3716         cpustate->smi_latched = false;
3717         cpustate->smbase = 0x30000;
3718         cpustate->nmi_masked = false;
3719         cpustate->nmi_latched = false;
3720
3721         x87_reset();
3722
3723         // [11:8] Family
3724         // [ 7:4] Model
3725         // [ 3:0] Stepping ID
3726         // Family 5 (Pentium), Model 2 (75 - 200MHz), Stepping 5
3727         REG32(EAX) = 0;
3728         REG32(EDX) = (5 << 8) | (2 << 4) | (5);
3729
3730         cpustate->cpuid_id0 = 0x756e6547;   // Genu
3731         cpustate->cpuid_id1 = 0x49656e69;   // ineI
3732         cpustate->cpuid_id2 = 0x6c65746e;   // ntel
3733
3734         cpustate->cpuid_max_input_value_eax = 0x01;
3735         cpustate->cpu_version = REG32(EDX);
3736
3737         // [ 0:0] FPU on chip
3738         // [ 2:2] I/O breakpoints
3739         // [ 4:4] Time Stamp Counter
3740         // [ 5:5] Pentium CPU style model specific registers
3741         // [ 7:7] Machine Check Exception
3742         // [ 8:8] CMPXCHG8B instruction
3743         cpustate->feature_flags = 0x000001bf;
3744
3745         CHANGE_PC(cpustate->eip);
3746 }
3747
3748 /*****************************************************************************/
3749 /* Cyrix MediaGX */
3750
3751
3752 void *I386_OPS_BASE::cpu_init_mediagx(void)
3753 {
3754         // probably 32 unified
3755         i386_common_init(32);
3756         build_x87_opcode_table();
3757         build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_CYRIX);
3758         cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_MEDIAGX];
3759         cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_MEDIAGX];
3760         return cpustate;
3761 }
3762
3763 void I386_OPS_BASE::cpu_reset_mediagx(void)
3764 {
3765         zero_state();
3766         vtlb_flush_dynamic(cpustate->vtlb);
3767
3768         cpustate->sreg[CS].selector = 0xf000;
3769         cpustate->sreg[CS].base     = 0xffff0000;
3770         cpustate->sreg[CS].limit    = 0xffff;
3771         cpustate->sreg[CS].flags    = 0x0093;
3772
3773         cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
3774         cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
3775         cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093;
3776
3777         cpustate->idtr.base = 0;
3778         cpustate->idtr.limit = 0x3ff;
3779
3780         cpustate->a20_mask = ~0;
3781
3782         cpustate->cr[0] = 0x00000010;
3783         cpustate->eflags = 0x00200000;
3784         cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */
3785         cpustate->eip = 0xfff0;
3786         cpustate->smm = false;
3787         cpustate->smi_latched = false;
3788         cpustate->nmi_masked = false;
3789         cpustate->nmi_latched = false;
3790
3791         x87_reset();
3792
3793         // [11:8] Family
3794         // [ 7:4] Model
3795         // [ 3:0] Stepping ID
3796         // Family 4, Model 4 (MediaGX)
3797         REG32(EAX) = 0;
3798         REG32(EDX) = (4 << 8) | (4 << 4) | (1); /* TODO: is this correct? */
3799
3800         cpustate->cpuid_id0 = 0x69727943;   // Cyri
3801         cpustate->cpuid_id1 = 0x736e4978;   // xIns
3802         cpustate->cpuid_id2 = 0x6d616574;   // tead
3803
3804         cpustate->cpuid_max_input_value_eax = 0x01;
3805         cpustate->cpu_version = REG32(EDX);
3806
3807         // [ 0:0] FPU on chip
3808         cpustate->feature_flags = 0x00000001;
3809
3810         CHANGE_PC(cpustate->eip);
3811 }
3812
3813 /*****************************************************************************/
3814 /* Intel Pentium Pro */
3815
3816 void *I386_OPS_BASE::cpu_init_pentium_pro(void)
3817 {
3818         // 64 dtlb small, 32 itlb
3819         i386_common_init(96);
3820         build_x87_opcode_table();
3821         build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_PPRO);
3822         cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM];  // TODO: generate own cycle tables
3823         cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM];  // TODO: generate own cycle tables
3824         return cpustate;
3825 }
3826
3827 void I386_OPS_BASE::cpu_reset_pentium_pro(void)
3828 {
3829         zero_state();
3830         vtlb_flush_dynamic(cpustate->vtlb);
3831
3832         cpustate->sreg[CS].selector = 0xf000;
3833         cpustate->sreg[CS].base     = 0xffff0000;
3834         cpustate->sreg[CS].limit    = 0xffff;
3835         cpustate->sreg[CS].flags    = 0x0093;
3836
3837         cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
3838         cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
3839         cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093;
3840
3841         cpustate->idtr.base = 0;
3842         cpustate->idtr.limit = 0x3ff;
3843
3844         cpustate->a20_mask = ~0;
3845
3846         cpustate->cr[0] = 0x60000010;
3847         cpustate->eflags = 0x00200000;
3848         cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */
3849         cpustate->eip = 0xfff0;
3850         cpustate->mxcsr = 0x1f80;
3851         cpustate->smm = false;
3852         cpustate->smi_latched = false;
3853         cpustate->smbase = 0x30000;
3854         cpustate->nmi_masked = false;
3855         cpustate->nmi_latched = false;
3856
3857         x87_reset();
3858
3859         // [11:8] Family
3860         // [ 7:4] Model
3861         // [ 3:0] Stepping ID
3862         // Family 6, Model 1 (Pentium Pro)
3863         REG32(EAX) = 0;
3864         REG32(EDX) = (6 << 8) | (1 << 4) | (1); /* TODO: is this correct? */
3865
3866         cpustate->cpuid_id0 = 0x756e6547;   // Genu
3867         cpustate->cpuid_id1 = 0x49656e69;   // ineI
3868         cpustate->cpuid_id2 = 0x6c65746e;   // ntel
3869
3870         cpustate->cpuid_max_input_value_eax = 0x02;
3871         cpustate->cpu_version = REG32(EDX);
3872
3873         // [ 0:0] FPU on chip
3874         // [ 2:2] I/O breakpoints
3875         // [ 4:4] Time Stamp Counter
3876         // [ 5:5] Pentium CPU style model specific registers
3877         // [ 7:7] Machine Check Exception
3878         // [ 8:8] CMPXCHG8B instruction
3879         // [15:15] CMOV and FCMOV
3880         // No MMX
3881         cpustate->feature_flags = 0x000081bf;
3882
3883         CHANGE_PC(cpustate->eip);
3884 }
3885
3886 /*****************************************************************************/
3887 /* Intel Pentium MMX */
3888
3889 void *I386_OPS_BASE::cpu_init_pentium_mmx(void)
3890 {
3891         // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large
3892         i386_common_init(96);
3893         build_x87_opcode_table();
3894         build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_MMX);
3895         cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM];  // TODO: generate own cycle tables
3896         cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM];  // TODO: generate own cycle tables
3897         return cpustate;
3898 }
3899
3900 void I386_OPS_BASE::cpu_reset_pentium_mmx(void)
3901 {
3902         zero_state();
3903         vtlb_flush_dynamic(cpustate->vtlb);
3904
3905         cpustate->sreg[CS].selector = 0xf000;
3906         cpustate->sreg[CS].base     = 0xffff0000;
3907         cpustate->sreg[CS].limit    = 0xffff;
3908         cpustate->sreg[CS].flags    = 0x0093;
3909
3910         cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
3911         cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
3912         cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093;
3913
3914         cpustate->idtr.base = 0;
3915         cpustate->idtr.limit = 0x3ff;
3916
3917         cpustate->a20_mask = ~0;
3918
3919         cpustate->cr[0] = 0x60000010;
3920         cpustate->eflags = 0x00200000;
3921         cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */
3922         cpustate->eip = 0xfff0;
3923         cpustate->mxcsr = 0x1f80;
3924         cpustate->smm = false;
3925         cpustate->smi_latched = false;
3926         cpustate->smbase = 0x30000;
3927         cpustate->nmi_masked = false;
3928         cpustate->nmi_latched = false;
3929
3930         x87_reset();
3931
3932         // [11:8] Family
3933         // [ 7:4] Model
3934         // [ 3:0] Stepping ID
3935         // Family 5, Model 4 (P55C)
3936         REG32(EAX) = 0;
3937         REG32(EDX) = (5 << 8) | (4 << 4) | (1);
3938
3939         cpustate->cpuid_id0 = 0x756e6547;   // Genu
3940         cpustate->cpuid_id1 = 0x49656e69;   // ineI
3941         cpustate->cpuid_id2 = 0x6c65746e;   // ntel
3942
3943         cpustate->cpuid_max_input_value_eax = 0x01;
3944         cpustate->cpu_version = REG32(EDX);
3945
3946         // [ 0:0] FPU on chip
3947         // [ 2:2] I/O breakpoints
3948         // [ 4:4] Time Stamp Counter
3949         // [ 5:5] Pentium CPU style model specific registers
3950         // [ 7:7] Machine Check Exception
3951         // [ 8:8] CMPXCHG8B instruction
3952         // [23:23] MMX instructions
3953         cpustate->feature_flags = 0x008001bf;
3954
3955         CHANGE_PC(cpustate->eip);
3956 }
3957
3958 /*****************************************************************************/
3959 /* Intel Pentium II */
3960
3961 void *I386_OPS_BASE::cpu_init_pentium2(void)
3962 {
3963         // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large
3964         i386_common_init(96);
3965         build_x87_opcode_table();
3966         build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_PPRO | OP_MMX);
3967         cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM];  // TODO: generate own cycle tables
3968         cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM];  // TODO: generate own cycle tables
3969         return cpustate;
3970 }
3971
3972 void I386_OPS_BASE::cpu_reset_pentium2(void)
3973 {
3974         zero_state();
3975         vtlb_flush_dynamic(cpustate->vtlb);
3976
3977         cpustate->sreg[CS].selector = 0xf000;
3978         cpustate->sreg[CS].base     = 0xffff0000;
3979         cpustate->sreg[CS].limit    = 0xffff;
3980         cpustate->sreg[CS].flags    = 0x0093;
3981
3982         cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
3983         cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
3984         cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093;
3985
3986         cpustate->idtr.base = 0;
3987         cpustate->idtr.limit = 0x3ff;
3988
3989         cpustate->a20_mask = ~0;
3990
3991         cpustate->cr[0] = 0x60000010;
3992         cpustate->eflags = 0x00200000;
3993         cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */
3994         cpustate->eip = 0xfff0;
3995         cpustate->mxcsr = 0x1f80;
3996         cpustate->smm = false;
3997         cpustate->smi_latched = false;
3998         cpustate->smbase = 0x30000;
3999         cpustate->nmi_masked = false;
4000         cpustate->nmi_latched = false;
4001
4002         x87_reset();
4003
4004         // [11:8] Family
4005         // [ 7:4] Model
4006         // [ 3:0] Stepping ID
4007         // Family 6, Model 3 (Pentium II / Klamath)
4008         REG32(EAX) = 0;
4009         REG32(EDX) = (6 << 8) | (3 << 4) | (1); /* TODO: is this correct? */
4010
4011         cpustate->cpuid_id0 = 0x756e6547;   // Genu
4012         cpustate->cpuid_id1 = 0x49656e69;   // ineI
4013         cpustate->cpuid_id2 = 0x6c65746e;   // ntel
4014
4015         cpustate->cpuid_max_input_value_eax = 0x02;
4016         cpustate->cpu_version = REG32(EDX);
4017
4018         // [ 0:0] FPU on chip
4019         cpustate->feature_flags = 0x008081bf;       // TODO: enable relevant flags here
4020
4021         CHANGE_PC(cpustate->eip);
4022 }
4023
4024 /*****************************************************************************/
4025 /* Intel Pentium III */
4026
4027 void *I386_OPS_BASE::cpu_init_pentium3(void)
4028 {
4029         // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large
4030         i386_common_init(96);
4031         build_x87_opcode_table();
4032         build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_PPRO | OP_MMX | OP_SSE);
4033         cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM];  // TODO: generate own cycle tables
4034         cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM];  // TODO: generate own cycle tables
4035         return cpustate;
4036 }
4037
4038 void I386_OPS_BASE::cpu_reset_pentium3(void)
4039 {
4040         zero_state();
4041         vtlb_flush_dynamic(cpustate->vtlb);
4042
4043         cpustate->sreg[CS].selector = 0xf000;
4044         cpustate->sreg[CS].base     = 0xffff0000;
4045         cpustate->sreg[CS].limit    = 0xffff;
4046         cpustate->sreg[CS].flags    = 0x0093;
4047
4048         cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
4049         cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
4050         cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0093;
4051
4052         cpustate->idtr.base = 0;
4053         cpustate->idtr.limit = 0x3ff;
4054
4055         cpustate->a20_mask = ~0;
4056
4057         cpustate->cr[0] = 0x60000010;
4058         cpustate->eflags = 0x00200000;
4059         cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */
4060         cpustate->eip = 0xfff0;
4061         cpustate->mxcsr = 0x1f80;
4062         cpustate->smm = false;
4063         cpustate->smi_latched = false;
4064         cpustate->smbase = 0x30000;
4065         cpustate->nmi_masked = false;
4066         cpustate->nmi_latched = false;
4067
4068         x87_reset();
4069
4070         // [11:8] Family
4071         // [ 7:4] Model
4072         // [ 3:0] Stepping ID
4073         // Family 6, Model 8 (Pentium III / Coppermine)
4074         REG32(EAX) = 0;
4075         REG32(EDX) = (6 << 8) | (8 << 4) | (10);
4076
4077         cpustate->cpuid_id0 = 0x756e6547;   // Genu
4078         cpustate->cpuid_id1 = 0x49656e69;   // ineI
4079         cpustate->cpuid_id2 = 0x6c65746e;   // ntel
4080
4081         cpustate->cpuid_max_input_value_eax = 0x03;
4082         cpustate->cpu_version = REG32(EDX);
4083
4084         // [ 0:0] FPU on chip
4085         // [ 4:4] Time Stamp Counter
4086         // [ D:D] PTE Global Bit
4087         cpustate->feature_flags = 0x00002011;       // TODO: enable relevant flags here
4088
4089         CHANGE_PC(cpustate->eip);
4090 }
4091
4092 /*****************************************************************************/
4093 /* Intel Pentium 4 */
4094
4095 void *I386_OPS_BASE::cpu_init_pentium4(void)
4096 {
4097         // 128 dtlb, 64 itlb
4098         i386_common_init(196);
4099         build_x87_opcode_table();
4100         build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM | OP_PPRO | OP_MMX | OP_SSE | OP_SSE2);
4101         cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_PENTIUM];  // TODO: generate own cycle tables
4102         cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_PENTIUM];  // TODO: generate own cycle tables
4103         return cpustate;
4104 }
4105
4106 void I386_OPS_BASE::cpu_reset_pentium4(void)
4107 {
4108         zero_state();
4109         vtlb_flush_dynamic(cpustate->vtlb);
4110
4111         cpustate->sreg[CS].selector = 0xf000;
4112         cpustate->sreg[CS].base     = 0xffff0000;
4113         cpustate->sreg[CS].limit    = 0xffff;
4114         cpustate->sreg[CS].flags    = 0x009b;
4115
4116         cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
4117         cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
4118         cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0092;
4119
4120         cpustate->idtr.base = 0;
4121         cpustate->idtr.limit = 0x3ff;
4122
4123         cpustate->a20_mask = ~0;
4124
4125         cpustate->cr[0] = 0x60000010;
4126         cpustate->eflags = 0x00200000;
4127         cpustate->eflags_mask = 0x00277fd7; /* TODO: is this correct? */
4128         cpustate->eip = 0xfff0;
4129         cpustate->mxcsr = 0x1f80;
4130         cpustate->smm = false;
4131         cpustate->smi_latched = false;
4132         cpustate->smbase = 0x30000;
4133         cpustate->nmi_masked = false;
4134         cpustate->nmi_latched = false;
4135
4136         x87_reset();
4137
4138         // [27:20] Extended family
4139         // [19:16] Extended model
4140         // [13:12] Type
4141         // [11: 8] Family
4142         // [ 7: 4] Model
4143         // [ 3: 0] Stepping ID
4144         // Family 15, Model 0 (Pentium 4 / Willamette)
4145         REG32(EAX) = 0;
4146         REG32(EDX) = (0 << 20) | (0xf << 8) | (0 << 4) | (1);
4147
4148         cpustate->cpuid_id0 = 0x756e6547;   // Genu
4149         cpustate->cpuid_id1 = 0x49656e69;   // ineI
4150         cpustate->cpuid_id2 = 0x6c65746e;   // ntel
4151
4152         cpustate->cpuid_max_input_value_eax = 0x02;
4153         cpustate->cpu_version = REG32(EDX);
4154
4155         // [ 0:0] FPU on chip
4156         cpustate->feature_flags = 0x00000001;       // TODO: enable relevant flags here
4157
4158         CHANGE_PC(cpustate->eip);
4159 }
4160