PCem
view src/386.c @ 142:bd46c39a78e8
Implemented selector limits on some instructions - fixes LBA2.
GPFs in real mode now work.
Selectors correctly zeroed on far return to lower privilege.
| author | TomW |
|---|---|
| date | Wed Aug 13 20:33:56 2014 +0100 |
| parents | 07168c9bdd22 |
| children | d0d530adce12 |
line source
1 #include <stdio.h>
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include "ibm.h"
5 #include "x86.h"
6 #include "x87.h"
7 #include "mem.h"
8 #include "cpu.h"
9 #include "fdc.h"
10 #include "timer.h"
11 #include "video.h"
14 x86seg *ea_seg;
16 int nmi_enable = 1;
18 int inscounts[256];
19 uint32_t oldpc2;
21 int trap;
23 #define check_io_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \
24 { \
25 int tempi = checkio(port); \
26 if (abrt) return 0; \
27 if (tempi) \
28 { \
29 x86gpf(NULL,0); \
30 return 0; \
31 } \
32 }
34 #define checkio_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \
35 { \
36 tempi = checkio(port); \
37 if (abrt) break; \
38 if (tempi) \
39 { \
40 x86gpf(NULL,0); \
41 break; \
42 } \
43 }
45 #define CHECK_READ(seg, low, high) \
46 if ((low < (seg)->limit_low) || (high > (seg)->limit_high)) \
47 { \
48 x86gpf("Limit check", 0); \
49 return 0; \
50 }
52 #define CHECK_WRITE(seg, low, high) \
53 if ((low < (seg)->limit_low) || (high > (seg)->limit_high)) \
54 { \
55 x86gpf("Limit check", 0); \
56 return 0; \
57 }
59 #define CHECK_WRITE_REP(seg, low, high) \
60 if ((low < (seg)->limit_low) || (high > (seg)->limit_high)) \
61 { \
62 x86gpf("Limit check", 0); \
63 break; \
64 }
67 int cpl_override=0;
69 int has_fpu;
70 int fpucount=0;
71 int times;
72 uint16_t rds;
73 uint16_t ea_rseg;
75 int is486;
76 int cgate32;
78 #undef readmemb
79 #undef writememb
82 #define readmemb(s,a) ((readlookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF)?readmemb386l(s,a): *(uint8_t *)(readlookup2[((s)+(a))>>12] + (s) + (a)) )
84 #define writememb(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememb386l(s,a,v); else *(uint8_t *)(writelookup2[((s) + (a)) >> 12] + (s) + (a)) = v
86 #define writememw(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFE) writememwl(s,a,v); else *(uint16_t *)(writelookup2[((s) + (a)) >> 12] + (s) + (a)) = v
87 #define writememl(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF || (((s)+(a))&0xFFF)>0xFFC) writememll(s,a,v); else *(uint32_t *)(writelookup2[((s) + (a)) >> 12] + (s) + (a)) = v
90 uint8_t romext[32768];
91 uint8_t *ram,*rom;
92 uint16_t biosmask;
94 uint32_t rmdat32;
95 #define rmdat rmdat32
96 #define fetchdat rmdat32
97 uint32_t backupregs[16];
98 int oddeven=0;
99 int inttype,abrt;
102 uint32_t oldcs2;
103 uint32_t oldecx;
104 uint32_t op32;
106 static inline uint8_t fastreadb(uint32_t a)
107 {
108 if ((a >> 12) == pccache)
109 return *((uint8_t *)&pccache2[a]);
110 pccache2 = getpccache(a);
111 if (abrt)
112 return;
113 pccache = a >> 12;
114 return *((uint8_t *)&pccache2[a]);
115 }
117 static inline uint16_t fastreadw(uint32_t a)
118 {
119 uint32_t t;
120 if ((a&0xFFF)>0xFFE)
121 {
122 t=readmemb(0,a);
123 t|=(readmemb(0,a+1)<<8);
124 return t;
125 }
126 if ((a>>12)==pccache) return *((uint16_t *)&pccache2[a]);
127 pccache2=getpccache(a);
128 if (abrt)
129 return;
130 pccache=a>>12;
131 return *((uint16_t *)&pccache2[a]);
132 }
134 static inline uint32_t fastreadl(uint32_t a)
135 {
136 uint8_t *t;
137 uint32_t val;
138 if ((a&0xFFF)<0xFFD)
139 {
140 if ((a>>12)!=pccache)
141 {
142 t = getpccache(a);
143 if (abrt) return 0;
144 pccache2 = t;
145 pccache=a>>12;
146 //return *((uint32_t *)&pccache2[a]);
147 }
148 return *((uint32_t *)&pccache2[a]);
149 }
150 val =readmemb(0,a);
151 val |=(readmemb(0,a+1)<<8);
152 val |=(readmemb(0,a+2)<<16);
153 val |=(readmemb(0,a+3)<<24);
154 return val;
155 }
158 static inline uint8_t getbyte()
159 {
160 pc++;
161 return fastreadb(cs + (pc - 1));
162 }
164 static inline uint16_t getword()
165 {
166 pc+=2;
167 return fastreadw(cs+(pc-2));
168 }
170 static inline uint32_t getlong()
171 {
172 pc+=4;
173 return fastreadl(cs+(pc-4));
174 }
176 uint32_t *eal_r, *eal_w;
177 static inline uint8_t geteab()
178 {
179 if (mod==3)
180 return (rm&4)?regs[rm&3].b.h:regs[rm&3].b.l;
181 if (eal_r) return *(uint8_t *)eal_r;
182 return readmemb(easeg,eaaddr);
183 }
185 static inline uint16_t geteaw()
186 {
187 if (mod==3)
188 return regs[rm].w;
189 // cycles-=3;
190 if (eal_r) return *(uint16_t *)eal_r;
191 return readmemw(easeg,eaaddr);
192 }
194 static inline uint32_t geteal()
195 {
196 if (mod==3)
197 return regs[rm].l;
198 // cycles-=3;
199 if (eal_r) return *eal_r;
200 return readmeml(easeg,eaaddr);
201 }
203 static inline uint8_t geteab_mem()
204 {
205 if (eal_r) return *(uint8_t *)eal_r;
206 return readmemb(easeg,eaaddr);
207 }
208 static inline uint16_t geteaw_mem()
209 {
210 if (eal_r) return *(uint16_t *)eal_r;
211 return readmemw(easeg,eaaddr);
212 }
213 static inline uint32_t geteal_mem()
214 {
215 if (eal_r) return *eal_r;
216 return readmeml(easeg,eaaddr);
217 }
219 #define seteab(v) if (mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,eaaddr,v); } else if (rm&4) regs[rm&3].b.h=v; else regs[rm].b.l=v
220 #define seteaw(v) if (mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,eaaddr,v); } else regs[rm].w=v
221 #define seteal(v) if (mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg,eaaddr,v); } else regs[rm].l=v
223 #define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,eaaddr,v);
224 #define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,eaaddr,v);
225 #define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg,eaaddr,v);
227 uint16_t *mod1add[2][8];
228 uint32_t *mod1seg[8];
230 static inline void fetch_ea_32_long(uint32_t rmdat)
231 {
232 eal_r = eal_w = NULL;
233 easeg = ea_seg->base;
234 ea_rseg = ea_seg->seg;
235 if (rm == 4)
236 {
237 uint8_t sib = rmdat >> 8;
239 switch (mod)
240 {
241 case 0:
242 eaaddr = regs[sib & 7].l;
243 pc++;
244 break;
245 case 1:
246 pc++;
247 eaaddr = ((uint32_t)(int8_t)getbyte()) + regs[sib & 7].l;
248 // pc++;
249 break;
250 case 2:
251 eaaddr = (fastreadl(cs + pc + 1)) + regs[sib & 7].l;
252 pc += 5;
253 break;
254 }
255 /*SIB byte present*/
256 if ((sib & 7) == 5 && !mod)
257 eaaddr = getlong();
258 else if ((sib & 6) == 4 && !ssegs)
259 {
260 easeg = ss;
261 ea_rseg = SS;
262 ea_seg = &_ss;
263 }
264 if (((sib >> 3) & 7) != 4)
265 eaaddr += regs[(sib >> 3) & 7].l << (sib >> 6);
266 }
267 else
268 {
269 eaaddr = regs[rm].l;
270 if (mod)
271 {
272 if (rm == 5 && !ssegs)
273 {
274 easeg = ss;
275 ea_rseg = SS;
276 ea_seg = &_ss;
277 }
278 if (mod == 1)
279 {
280 eaaddr += ((uint32_t)(int8_t)(rmdat >> 8));
281 pc++;
282 }
283 else
284 {
285 eaaddr += getlong();
286 }
287 }
288 else if (rm == 5)
289 {
290 eaaddr = getlong();
291 }
292 }
293 if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC)
294 {
295 if ( readlookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF)
296 eal_r = (uint32_t *)(readlookup2[(easeg + eaaddr) >> 12] + easeg + eaaddr);
297 if (writelookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF)
298 eal_w = (uint32_t *)(writelookup2[(easeg + eaaddr) >> 12] + easeg + eaaddr);
299 }
300 }
302 static inline void fetch_ea_16_long(uint32_t rmdat)
303 {
304 eal_r = eal_w = NULL;
305 easeg = ea_seg->base;
306 ea_rseg = ea_seg->seg;
307 if (!mod && rm == 6)
308 {
309 eaaddr = getword();
310 }
311 else
312 {
313 switch (mod)
314 {
315 case 0:
316 eaaddr = 0;
317 break;
318 case 1:
319 eaaddr = (uint16_t)(int8_t)(rmdat >> 8); pc++;
320 break;
321 case 2:
322 eaaddr = getword();
323 break;
324 }
325 eaaddr += (*mod1add[0][rm]) + (*mod1add[1][rm]);
326 if (mod1seg[rm] == &ss && !ssegs)
327 {
328 easeg = ss;
329 ea_rseg = SS;
330 ea_seg = &_ss;
331 }
332 eaaddr &= 0xFFFF;
333 }
334 if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC)
335 {
336 if ( readlookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF)
337 eal_r = (uint32_t *)(readlookup2[(easeg + eaaddr) >> 12] + easeg + eaaddr);
338 if (writelookup2[(easeg + eaaddr) >> 12] != 0xFFFFFFFF)
339 eal_w = (uint32_t *)(writelookup2[(easeg + eaaddr) >> 12] + easeg + eaaddr);
340 }
341 }
343 #define fetch_ea_16(rmdat) pc++; mod=(rmdat >> 6) & 3; reg=(rmdat >> 3) & 7; rm = rmdat & 7; if (mod != 3) { fetch_ea_16_long(rmdat); if (abrt) return 0; }
344 #define fetch_ea_32(rmdat) pc++; mod=(rmdat >> 6) & 3; reg=(rmdat >> 3) & 7; rm = rmdat & 7; if (mod != 3) { fetch_ea_32_long(rmdat); } if (abrt) return 0
346 #include "x86_flags.h"
348 void x86_int(int num)
349 {
350 uint32_t addr;
351 // pclog("x86_int\n");
352 flags_rebuild();
353 pc=oldpc;
354 if (msw&1)
355 {
356 pmodeint(num,0);
357 }
358 else
359 {
360 if (stack32)
361 {
362 writememw(ss,ESP-2,flags);
363 writememw(ss,ESP-4,CS);
364 writememw(ss,ESP-6,pc);
365 ESP-=6;
366 }
367 else
368 {
369 writememw(ss,((SP-2)&0xFFFF),flags);
370 writememw(ss,((SP-4)&0xFFFF),CS);
371 writememw(ss,((SP-6)&0xFFFF),pc);
372 SP-=6;
373 }
374 addr = (num << 2) + idt.base;
376 flags&=~I_FLAG;
377 flags&=~T_FLAG;
378 oxpc=pc;
379 pc=readmemw(0,addr);
380 loadcs(readmemw(0,addr+2));
381 }
382 cycles-=70;
383 }
385 void x86_int_sw(int num)
386 {
387 uint32_t addr;
388 // pclog("x86_int\n");
389 flags_rebuild();
390 if (msw&1)
391 {
392 pmodeint(num,1);
393 }
394 else
395 {
396 if (stack32)
397 {
398 writememw(ss,ESP-2,flags);
399 writememw(ss,ESP-4,CS);
400 writememw(ss,ESP-6,pc);
401 ESP-=6;
402 }
403 else
404 {
405 writememw(ss,((SP-2)&0xFFFF),flags);
406 writememw(ss,((SP-4)&0xFFFF),CS);
407 writememw(ss,((SP-6)&0xFFFF),pc);
408 SP-=6;
409 }
410 addr = (num << 2) + idt.base;
412 flags&=~I_FLAG;
413 flags&=~T_FLAG;
414 oxpc=pc;
415 pc=readmemw(0,addr);
416 loadcs(readmemw(0,addr+2));
417 }
418 cycles-=70;
419 trap = 0;
420 }
422 void x86illegal()
423 {
424 uint16_t addr;
425 pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode);
426 // if (output)
427 // {
428 // dumpregs();
429 // exit(-1);
430 // }
431 x86_int(6);
432 }
435 #define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\
436 { \
437 x86_int(6); \
438 break; \
439 }
441 void rep386(int fv)
442 {
443 uint8_t temp;
444 uint32_t c;//=CX;
445 uint8_t temp2;
446 uint16_t tempw,tempw2,of;
447 uint32_t ipc=oldpc;//pc-1;
448 uint32_t oldds;
449 uint32_t rep32=op32;
450 uint32_t templ,templ2;
451 int tempz;
452 int tempi;
454 flags_rebuild();
455 of = flags;
456 // if (output) pclog("REP32 %04X %04X ",use32,rep32);
457 startrep:
458 temp=opcode2=readmemb(cs,pc); pc++;
459 // if (firstrepcycle && temp==0xA5) pclog("REP MOVSW %06X:%04X %06X:%04X\n",ds,SI,es,DI);
460 // if (output) pclog("REP %02X %04X\n",temp,ipc);
461 c=(rep32&0x200)?ECX:CX;
462 /* if (rep32 && (msw&1))
463 {
464 if (temp!=0x67 && temp!=0x66 && (rep32|temp)!=0x1AB && (rep32|temp)!=0x3AB) pclog("32-bit REP %03X %08X %04X:%06X\n",temp|rep32,c,CS,pc);
465 }*/
466 switch (temp|rep32)
467 {
468 case 0xC3: case 0x1C3: case 0x2C3: case 0x3C3:
469 pc--;
470 break;
471 case 0x08:
472 pc=ipc+1;
473 break;
474 case 0x26: case 0x126: case 0x226: case 0x326: /*ES:*/
475 ea_seg = &_es;
476 goto startrep;
477 break;
478 case 0x2E: case 0x12E: case 0x22E: case 0x32E: /*CS:*/
479 ea_seg = &_cs;
480 goto startrep;
481 case 0x36: case 0x136: case 0x236: case 0x336: /*SS:*/
482 ea_seg = &_ss;
483 goto startrep;
484 case 0x3E: case 0x13E: case 0x23E: case 0x33E: /*DS:*/
485 ea_seg = &_ds;
486 goto startrep;
487 case 0x64: case 0x164: case 0x264: case 0x364: /*FS:*/
488 ea_seg = &_fs;
489 goto startrep;
490 case 0x65: case 0x165: case 0x265: case 0x365: /*GS:*/
491 ea_seg = &_gs;
492 goto startrep;
493 case 0x66: case 0x166: case 0x266: case 0x366: /*Data size prefix*/
494 rep32^=0x100;
495 goto startrep;
496 case 0x67: case 0x167: case 0x267: case 0x367: /*Address size prefix*/
497 rep32^=0x200;
498 goto startrep;
499 case 0x6C: case 0x16C: /*REP INSB*/
500 if (c>0)
501 {
502 checkio_perm(DX);
503 temp2=inb(DX);
504 writememb(es,DI,temp2);
505 if (abrt) break;
506 if (flags&D_FLAG) DI--;
507 else DI++;
508 c--;
509 cycles-=15;
510 }
511 if (c>0) { firstrepcycle=0; pc=ipc; }
512 else firstrepcycle=1;
513 break;
514 case 0x26C: case 0x36C: /*REP INSB*/
515 if (c>0)
516 {
517 checkio_perm(DX);
518 temp2=inb(DX);
519 writememb(es,EDI,temp2);
520 if (abrt) break;
521 if (flags&D_FLAG) EDI--;
522 else EDI++;
523 c--;
524 cycles-=15;
525 }
526 if (c>0) { firstrepcycle=0; pc=ipc; }
527 else firstrepcycle=1;
528 break;
529 case 0x6D: /*REP INSW*/
530 if (c>0)
531 {
532 tempw=inw(DX);
533 writememw(es,DI,tempw);
534 if (abrt) break;
535 if (flags&D_FLAG) DI-=2;
536 else DI+=2;
537 c--;
538 cycles-=15;
539 }
540 if (c>0) { firstrepcycle=0; pc=ipc; }
541 else firstrepcycle=1;
542 break;
543 case 0x16D: /*REP INSL*/
544 if (c>0)
545 {
546 templ=inl(DX);
547 writememl(es,DI,templ);
548 if (abrt) break;
549 if (flags&D_FLAG) DI-=4;
550 else DI+=4;
551 c--;
552 cycles-=15;
553 }
554 if (c>0) { firstrepcycle=0; pc=ipc; }
555 else firstrepcycle=1;
556 break;
557 case 0x26D: /*REP INSW*/
558 if (c>0)
559 {
560 tempw=inw(DX);
561 writememw(es,EDI,tempw);
562 if (abrt) break;
563 if (flags&D_FLAG) EDI-=2;
564 else EDI+=2;
565 c--;
566 cycles-=15;
567 }
568 if (c>0) { firstrepcycle=0; pc=ipc; }
569 else firstrepcycle=1;
570 break;
571 case 0x36D: /*REP INSL*/
572 if (c>0)
573 {
574 templ=inl(DX);
575 writememl(es,EDI,templ);
576 if (abrt) break;
577 if (flags&D_FLAG) EDI-=4;
578 else EDI+=4;
579 c--;
580 cycles-=15;
581 }
582 if (c>0) { firstrepcycle=0; pc=ipc; }
583 else firstrepcycle=1;
584 break;
585 case 0x6E: case 0x16E: /*REP OUTSB*/
586 if (c>0)
587 {
588 temp2 = readmemb(ea_seg->base, SI);
589 if (abrt) break;
590 checkio_perm(DX);
591 outb(DX,temp2);
592 if (flags&D_FLAG) SI--;
593 else SI++;
594 c--;
595 cycles-=14;
596 }
597 if (c>0) { firstrepcycle=0; pc=ipc; }
598 else firstrepcycle=1;
599 break;
600 case 0x26E: case 0x36E: /*REP OUTSB*/
601 if (c>0)
602 {
603 temp2 = readmemb(ea_seg->base, ESI);
604 if (abrt) break;
605 checkio_perm(DX);
606 outb(DX,temp2);
607 if (flags&D_FLAG) ESI--;
608 else ESI++;
609 c--;
610 cycles-=14;
611 }
612 if (c>0) { firstrepcycle=0; pc=ipc; }
613 else firstrepcycle=1;
614 break;
615 case 0x6F: /*REP OUTSW*/
616 if (c>0)
617 {
618 tempw = readmemw(ea_seg->base, SI);
619 if (abrt) break;
620 // pclog("OUTSW %04X -> %04X\n",SI,tempw);
621 outw(DX,tempw);
622 if (flags&D_FLAG) SI-=2;
623 else SI+=2;
624 c--;
625 cycles-=14;
626 }
627 if (c>0) { firstrepcycle=0; pc=ipc; }
628 else firstrepcycle=1;
629 break;
630 case 0x16F: /*REP OUTSL*/
631 if (c > 0)
632 {
633 templ = readmeml(ea_seg->base, SI);
634 if (abrt) break;
635 outl(DX, templ);
636 if (flags & D_FLAG) SI -= 4;
637 else SI += 4;
638 c--;
639 cycles -= 14;
640 }
641 if (c > 0) { firstrepcycle = 0; pc = ipc; }
642 else firstrepcycle = 1;
643 break;
644 case 0x26F: /*REP OUTSW*/
645 if (c>0)
646 {
647 tempw = readmemw(ea_seg->base, ESI);
648 if (abrt) break;
649 outw(DX,tempw);
650 if (flags&D_FLAG) ESI-=2;
651 else ESI+=2;
652 c--;
653 cycles-=14;
654 }
655 if (c>0) { firstrepcycle=0; pc=ipc; }
656 else firstrepcycle=1;
657 break;
658 case 0x36F: /*REP OUTSL*/
659 if (c > 0)
660 {
661 templ = readmeml(ea_seg->base, ESI);
662 if (abrt) break;
663 outl(DX, templ);
664 if (flags & D_FLAG) ESI -= 4;
665 else ESI += 4;
666 c--;
667 cycles -= 14;
668 }
669 if (c > 0) { firstrepcycle = 0; pc = ipc; }
670 else firstrepcycle = 1;
671 break;
672 case 0x90: case 0x190: /*REP NOP*/
673 case 0x290: case 0x390:
674 break;
675 case 0xA4: case 0x1A4: /*REP MOVSB*/
676 if (c>0)
677 {
678 CHECK_WRITE_REP(&_es, DI, DI);
679 temp2 = readmemb(ea_seg->base, SI); if (abrt) break;
680 writememb(es,DI,temp2); if (abrt) break;
681 // if (output==3) pclog("MOVSB %08X:%04X -> %08X:%04X %02X\n",ds,SI,es,DI,temp2);
682 if (flags&D_FLAG) { DI--; SI--; }
683 else { DI++; SI++; }
684 c--;
685 cycles-=(is486)?3:4;
686 }
687 if (c>0) { firstrepcycle=0; pc=ipc; }
688 else firstrepcycle=1;
689 break;
690 case 0x2A4: case 0x3A4: /*REP MOVSB*/
691 if (c>0)
692 {
693 CHECK_WRITE_REP(&_es, EDI, EDI);
694 temp2 = readmemb(ea_seg->base, ESI); if (abrt) break;
695 writememb(es,EDI,temp2); if (abrt) break;
696 if (flags&D_FLAG) { EDI--; ESI--; }
697 else { EDI++; ESI++; }
698 c--;
699 cycles-=(is486)?3:4;
700 }
701 if (c>0) { firstrepcycle=0; pc=ipc; }
702 else firstrepcycle=1;
703 break;
704 case 0xA5: /*REP MOVSW*/
705 if (c>0)
706 {
707 CHECK_WRITE_REP(&_es, DI, DI+1);
708 tempw = readmemw(ea_seg->base, SI); if (abrt) break;
709 writememw(es,DI,tempw); if (abrt) break;
710 if (flags&D_FLAG) { DI-=2; SI-=2; }
711 else { DI+=2; SI+=2; }
712 c--;
713 cycles-=(is486)?3:4;
714 }
715 if (c>0) { firstrepcycle=0; pc=ipc; }
716 else firstrepcycle=1;
717 break;
718 case 0x1A5: /*REP MOVSL*/
719 if (c>0)
720 {
721 CHECK_WRITE_REP(&_es, DI, DI+3);
722 templ = readmeml(ea_seg->base, SI); if (abrt) break;
723 // pclog("MOVSD %08X from %08X to %08X (%04X:%08X)\n", templ, ds+SI, es+DI, CS, pc);
724 writememl(es,DI,templ); if (abrt) break;
725 if (flags&D_FLAG) { DI-=4; SI-=4; }
726 else { DI+=4; SI+=4; }
727 c--;
728 cycles-=(is486)?3:4;
729 }
730 if (c>0) { firstrepcycle=0; pc=ipc; }
731 else firstrepcycle=1;
732 break;
733 case 0x2A5: /*REP MOVSW*/
734 if (c>0)
735 {
736 CHECK_WRITE_REP(&_es, EDI, EDI+1);
737 tempw = readmemw(ea_seg->base, ESI); if (abrt) break;
738 writememw(es,EDI,tempw); if (abrt) break;
739 // if (output) pclog("Written %04X from %08X to %08X %i %08X %04X %08X %04X\n",tempw,ds+ESI,es+EDI,c,ds,ES,es,ES);
740 if (flags&D_FLAG) { EDI-=2; ESI-=2; }
741 else { EDI+=2; ESI+=2; }
742 c--;
743 cycles-=(is486)?3:4;
744 }
745 if (c>0) { firstrepcycle=0; pc=ipc; }
746 else firstrepcycle=1;
747 break;
748 case 0x3A5: /*REP MOVSL*/
749 if (c>0)
750 {
751 CHECK_WRITE_REP(&_es, EDI, EDI+3);
752 templ = readmeml(ea_seg->base, ESI); if (abrt) break;
753 // if ((EDI&0xFFFF0000)==0xA0000) cycles-=12;
754 writememl(es,EDI,templ); if (abrt) break;
755 // if (output) pclog("Load %08X from %08X to %08X %04X %08X %04X %08X\n",templ,ESI,EDI,DS,ds,ES,es);
756 if (flags&D_FLAG) { EDI-=4; ESI-=4; }
757 else { EDI+=4; ESI+=4; }
758 c--;
759 cycles-=(is486)?3:4;
760 }
761 if (c>0) { firstrepcycle=0; pc=ipc; }
762 else firstrepcycle=1;
763 break;
764 case 0xA6: case 0x1A6: /*REP CMPSB*/
765 tempz = (fv) ? 1 : 0;
766 if ((c>0) && (fv==tempz))
767 {
768 temp = readmemb(ea_seg->base, SI);
769 temp2=readmemb(es,DI);
770 if (abrt) { flags=of; break; }
771 if (flags&D_FLAG) { DI--; SI--; }
772 else { DI++; SI++; }
773 c--;
774 cycles-=(is486)?7:9;
775 setsub8(temp,temp2);
776 tempz = (ZF_SET()) ? 1 : 0;
777 }
778 if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
779 else firstrepcycle=1;
780 break;
781 case 0x2A6: case 0x3A6: /*REP CMPSB*/
782 tempz = (fv) ? 1 : 0;
783 if ((c>0) && (fv==tempz))
784 {
785 temp = readmemb(ea_seg->base, ESI);
786 temp2=readmemb(es,EDI);
787 if (abrt) { flags=of; break; }
788 if (flags&D_FLAG) { EDI--; ESI--; }
789 else { EDI++; ESI++; }
790 c--;
791 cycles-=(is486)?7:9;
792 setsub8(temp,temp2);
793 tempz = (ZF_SET()) ? 1 : 0;
794 }
795 if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
796 else firstrepcycle=1;
797 break;
798 case 0xA7: /*REP CMPSW*/
799 tempz = (fv) ? 1 : 0;
800 if ((c>0) && (fv==tempz))
801 {
802 // pclog("CMPSW %05X %05X %08X %08X ", ds+SI, es+DI, readlookup2[(ds+SI)>>12], readlookup2[(es+DI)>>12]);
803 tempw = readmemw(ea_seg->base, SI);
804 tempw2=readmemw(es,DI);
805 // pclog("%04X %04X %02X\n", tempw, tempw2, ram[8]);
807 if (abrt) { flags=of; break; }
808 if (flags&D_FLAG) { DI-=2; SI-=2; }
809 else { DI+=2; SI+=2; }
810 c--;
811 cycles-=(is486)?7:9;
812 setsub16(tempw,tempw2);
813 tempz = (ZF_SET()) ? 1 : 0;
814 }
815 if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
816 else firstrepcycle=1;
817 break;
818 case 0x1A7: /*REP CMPSL*/
819 tempz = (fv) ? 1 : 0;
820 if ((c>0) && (fv==tempz))
821 {
822 templ = readmeml(ea_seg->base, SI);
823 templ2=readmeml(es,DI);
824 if (abrt) { flags=of; break; }
825 if (flags&D_FLAG) { DI-=4; SI-=4; }
826 else { DI+=4; SI+=4; }
827 c--;
828 cycles-=(is486)?7:9;
829 setsub32(templ,templ2);
830 tempz = (ZF_SET()) ? 1 : 0;
831 }
832 if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
833 else firstrepcycle=1;
834 break;
835 case 0x2A7: /*REP CMPSW*/
836 tempz = (fv) ? 1 : 0;
837 if ((c>0) && (fv==tempz))
838 {
839 tempw = readmemw(ea_seg->base, ESI);
840 tempw2=readmemw(es,EDI);
841 if (abrt) { flags=of; break; }
842 if (flags&D_FLAG) { EDI-=2; ESI-=2; }
843 else { EDI+=2; ESI+=2; }
844 c--;
845 cycles-=(is486)?7:9;
846 setsub16(tempw,tempw2);
847 tempz = (ZF_SET()) ? 1 : 0;
848 }
849 if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
850 else firstrepcycle=1;
851 break;
852 case 0x3A7: /*REP CMPSL*/
853 tempz = (fv) ? 1 : 0;
854 if ((c>0) && (fv==tempz))
855 {
856 templ = readmeml(ea_seg->base, ESI);
857 templ2=readmeml(es,EDI);
858 if (abrt) { flags=of; break; }
859 if (flags&D_FLAG) { EDI-=4; ESI-=4; }
860 else { EDI+=4; ESI+=4; }
861 c--;
862 cycles-=(is486)?7:9;
863 setsub32(templ,templ2);
864 tempz = (ZF_SET()) ? 1 : 0;
865 }
866 if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
867 else firstrepcycle=1;
868 break;
870 case 0xAA: case 0x1AA: /*REP STOSB*/
871 if (c>0)
872 {
873 CHECK_WRITE_REP(&_es, DI, DI);
874 writememb(es,DI,AL);
875 if (abrt) break;
876 if (flags&D_FLAG) DI--;
877 else DI++;
878 c--;
879 cycles-=(is486)?4:5;
880 }
881 if (c>0) { firstrepcycle=0; pc=ipc; }
882 else firstrepcycle=1;
883 break;
884 case 0x2AA: case 0x3AA: /*REP STOSB*/
885 if (c>0)
886 {
887 CHECK_WRITE_REP(&_es, EDI, EDI);
888 writememb(es,EDI,AL);
889 if (abrt) break;
890 if (flags&D_FLAG) EDI--;
891 else EDI++;
892 c--;
893 cycles-=(is486)?4:5;
894 }
895 if (c>0) { firstrepcycle=0; pc=ipc; }
896 else firstrepcycle=1;
897 break;
898 case 0xAB: /*REP STOSW*/
899 if (c>0)
900 {
901 CHECK_WRITE_REP(&_es, DI, DI+1);
902 writememw(es,DI,AX);
903 if (abrt) break;
904 if (flags&D_FLAG) DI-=2;
905 else DI+=2;
906 c--;
907 cycles-=(is486)?4:5;
908 }
909 if (c>0) { firstrepcycle=0; pc=ipc; }
910 else firstrepcycle=1;
911 break;
912 case 0x2AB: /*REP STOSW*/
913 if (c>0)
914 {
915 CHECK_WRITE_REP(&_es, EDI, EDI+1);
916 writememw(es,EDI,AX);
917 if (abrt) break;
918 if (flags&D_FLAG) EDI-=2;
919 else EDI+=2;
920 c--;
921 cycles-=(is486)?4:5;
922 }
923 if (c>0) { firstrepcycle=0; pc=ipc; }
924 else firstrepcycle=1;
925 break;
926 case 0x1AB: /*REP STOSL*/
927 if (c>0)
928 {
929 CHECK_WRITE_REP(&_es, DI, DI+3);
930 writememl(es,DI,EAX);
931 if (abrt) break;
932 if (flags&D_FLAG) DI-=4;
933 else DI+=4;
934 c--;
935 cycles-=(is486)?4:5;
936 }
937 if (c>0) { firstrepcycle=0; pc=ipc; }
938 else firstrepcycle=1;
939 break;
940 case 0x3AB: /*REP STOSL*/
941 if (c>0)
942 {
943 CHECK_WRITE_REP(&_es, EDI, EDI+3);
944 writememl(es,EDI,EAX);
945 if (abrt) break;
946 if (flags&D_FLAG) EDI-=4;
947 else EDI+=4;
948 c--;
949 cycles-=(is486)?4:5;
950 }
951 if (c>0) { firstrepcycle=0; pc=ipc; }
952 else firstrepcycle=1;
953 break;
954 case 0xAC: case 0x1AC: /*REP LODSB*/
955 // if (ds==0xFFFFFFFF) pclog("Null selector REP LODSB %04X(%06X):%06X\n",CS,cs,pc);
956 if (c>0)
957 {
958 AL = readmemb(ea_seg->base, SI);
959 if (abrt) break;
960 if (flags&D_FLAG) SI--;
961 else SI++;
962 c--;
963 cycles-=5;
964 }
965 if (c>0) { firstrepcycle=0; pc=ipc; }
966 else firstrepcycle=1;
967 break;
968 case 0x2AC: case 0x3AC: /*REP LODSB*/
969 // if (ds==0xFFFFFFFF) pclog("Null selector REP LODSB %04X(%06X):%06X\n",CS,cs,pc);
970 if (c>0)
971 {
972 AL = readmemb(ea_seg->base, ESI);
973 if (abrt) break;
974 if (flags&D_FLAG) ESI--;
975 else ESI++;
976 c--;
977 cycles-=5;
978 }
979 if (c>0) { firstrepcycle=0; pc=ipc; }
980 else firstrepcycle=1;
981 break;
982 case 0xAD: /*REP LODSW*/
983 // if (ds==0xFFFFFFFF) pclog("Null selector REP LODSW %04X(%06X):%06X\n",CS,cs,pc);
984 if (c>0)
985 {
986 AX = readmemw(ea_seg->base, SI);
987 if (abrt) break;
988 if (flags&D_FLAG) SI-=2;
989 else SI+=2;
990 c--;
991 cycles-=5;
992 }
993 if (c>0) { firstrepcycle=0; pc=ipc; }
994 else firstrepcycle=1;
995 break;
996 case 0x1AD: /*REP LODSL*/
997 // if (ds==0xFFFFFFFF) pclog("Null selector REP LODSL %04X(%06X):%06X\n",CS,cs,pc);
998 if (c>0)
999 {
1000 EAX = readmeml(ea_seg->base, SI);
1001 if (abrt) break;
1002 if (flags&D_FLAG) SI-=4;
1003 else SI+=4;
1004 c--;
1005 cycles-=5;
1006 }
1007 if (c>0) { firstrepcycle=0; pc=ipc; }
1008 else firstrepcycle=1;
1009 break;
1010 case 0x2AD: /*REP LODSW*/
1011 // if (ds==0xFFFFFFFF) pclog("Null selector REP LODSW %04X(%06X):%06X\n",CS,cs,pc);
1012 if (c>0)
1013 {
1014 AX = readmemw(ea_seg->base, ESI);
1015 if (abrt) break;
1016 if (flags&D_FLAG) ESI-=2;
1017 else ESI+=2;
1018 c--;
1019 cycles-=5;
1020 }
1021 if (c>0) { firstrepcycle=0; pc=ipc; }
1022 else firstrepcycle=1;
1023 break;
1024 case 0x3AD: /*REP LODSL*/
1025 // if (ds==0xFFFFFFFF) pclog("Null selector REP LODSL %04X(%06X):%06X\n",CS,cs,pc);
1026 if (c>0)
1027 {
1028 EAX = readmeml(ea_seg->base, ESI);
1029 if (abrt) break;
1030 if (flags&D_FLAG) ESI-=4;
1031 else ESI+=4;
1032 c--;
1033 cycles-=5;
1034 }
1035 if (c>0) { firstrepcycle=0; pc=ipc; }
1036 else firstrepcycle=1;
1037 break;
1038 case 0xAE: case 0x1AE: /*REP SCASB*/
1039 // if (es==0xFFFFFFFF) pclog("Null selector REP SCASB %04X(%06X):%06X\n",CS,cs,pc);
1040 // tempz=(fv)?1:0;
1041 tempz = (fv) ? 1 : 0;
1042 if ((c>0) && (fv==tempz))
1043 {
1044 temp2=readmemb(es,DI);
1045 if (abrt) { flags=of; break; }
1046 setsub8(AL,temp2);
1047 tempz = (ZF_SET()) ? 1 : 0;
1048 if (flags&D_FLAG) DI--;
1049 else DI++;
1050 c--;
1051 cycles-=(is486)?5:8;
1052 }
1053 if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
1054 else firstrepcycle=1;
1055 break;
1056 case 0x2AE: case 0x3AE: /*REP SCASB*/
1057 // if (es==0xFFFFFFFF) pclog("Null selector REP SCASB %04X(%06X):%06X\n",CS,cs,pc);
1058 // tempz=(fv)?1:0;
1059 tempz = (fv) ? 1 : 0;
1060 if ((c>0) && (fv==tempz))
1061 {
1062 temp2=readmemb(es,EDI);
1063 if (abrt) { flags=of; break; }
1064 // if (output) pclog("Compare %02X,%02X\n",temp2,AL);
1065 setsub8(AL,temp2);
1066 tempz = (ZF_SET()) ? 1 : 0;
1067 if (flags&D_FLAG) EDI--;
1068 else EDI++;
1069 c--;
1070 cycles-=(is486)?5:8;
1071 }
1072 if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
1073 else firstrepcycle=1;
1074 break;
1075 case 0xAF: /*REP SCASW*/
1076 // if (es==0xFFFFFFFF) pclog("Null selector REP SCASW %04X(%06X):%06X\n",CS,cs,pc);
1077 tempz = (fv) ? 1 : 0;
1078 if ((c>0) && (fv==tempz))
1079 {
1080 tempw=readmemw(es,DI);
1081 if (abrt) { flags=of; break; }
1082 setsub16(AX,tempw);
1083 tempz = (ZF_SET()) ? 1 : 0;
1084 if (flags&D_FLAG) DI-=2;
1085 else DI+=2;
1086 c--;
1087 cycles-=(is486)?5:8;
1088 }
1089 if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
1090 else firstrepcycle=1;
1091 break;
1092 case 0x1AF: /*REP SCASL*/
1093 // if (es==0xFFFFFFFF) pclog("Null selector REP SCASL %04X(%06X):%06X\n",CS,cs,pc);
1094 tempz = (fv) ? 1 : 0;
1095 if ((c>0) && (fv==tempz))
1096 {
1097 templ=readmeml(es,DI);
1098 if (abrt) { flags=of; break; }
1099 setsub32(EAX,templ);
1100 tempz = (ZF_SET()) ? 1 : 0;
1101 if (flags&D_FLAG) DI-=4;
1102 else DI+=4;
1103 c--;
1104 cycles-=(is486)?5:8;
1105 }
1106 if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
1107 else firstrepcycle=1;
1108 break;
1109 case 0x2AF: /*REP SCASW*/
1110 // if (es==0xFFFFFFFF) pclog("Null selector REP SCASW %04X(%06X):%06X\n",CS,cs,pc);
1111 tempz = (fv) ? 1 : 0;
1112 if ((c>0) && (fv==tempz))
1113 {
1114 tempw=readmemw(es,EDI);
1115 if (abrt) { flags=of; break; }
1116 setsub16(AX,tempw);
1117 tempz = (ZF_SET()) ? 1 : 0;
1118 if (flags&D_FLAG) EDI-=2;
1119 else EDI+=2;
1120 c--;
1121 cycles-=(is486)?5:8;
1122 }
1123 if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
1124 else firstrepcycle=1;
1125 break;
1126 case 0x3AF: /*REP SCASL*/
1127 // if (es==0xFFFFFFFF) pclog("Null selector REP SCASL %04X(%06X):%06X\n",CS,cs,pc);
1128 tempz = (fv) ? 1 : 0;
1129 if ((c>0) && (fv==tempz))
1130 {
1131 templ=readmeml(es,EDI);
1132 if (abrt) { flags=of; break; }
1133 setsub32(EAX,templ);
1134 tempz = (ZF_SET()) ? 1 : 0;
1135 if (flags&D_FLAG) EDI-=4;
1136 else EDI+=4;
1137 c--;
1138 cycles-=(is486)?5:8;
1139 }
1140 if ((c>0) && (fv==tempz)) { pc=ipc; firstrepcycle=0; }
1141 else firstrepcycle=1;
1142 break;
1145 default:
1146 pc=ipc;
1147 cycles-=20;
1148 pclog("Bad REP %02X %i\n", temp, rep32 >> 8);
1149 x86illegal();
1150 }
1151 if (rep32&0x200) ECX=c;
1152 else CX=c;
1153 // if (output) pclog("%03X %03X\n",rep32,use32);
1154 }
1156 int checkio(int port)
1157 {
1158 uint16_t t;
1159 uint8_t d;
1160 cpl_override = 1;
1161 t = readmemw(tr.base, 0x66);
1162 cpl_override = 0;
1163 // pclog("CheckIO 1 %08X\n",tr.base);
1164 if (abrt) return 0;
1165 // pclog("CheckIO %04X %01X %01X %02X %04X %04X %08X ",CS,CPL,IOPL,port,t,t+(port>>3),tr.base+t+(port>>3));
1166 if ((t+(port>>3))>tr.limit) return 1;
1167 cpl_override = 1;
1168 d = readmemb386l(0, tr.base + t + (port >> 3));
1169 // d=readmemb(tr.base,t+(port>>3));
1170 cpl_override = 0;
1171 // pclog("%02X %02X\n",d,d&(1<<(port&7)));
1172 return d&(1<<(port&7));
1173 }
1175 #define getbytef() ((uint8_t)(fetchdat)); pc++
1176 #define getwordf() ((uint16_t)(fetchdat)); pc+=2
1177 #define getbyte2f() ((uint8_t)(fetchdat>>8)); pc++
1178 #define getword2f() ((uint16_t)(fetchdat>>8)); pc+=2
1179 int xout=0;
1182 #define divexcp() { \
1183 pclog("Divide exception at %04X(%06X):%04X\n",CS,cs,pc); \
1184 x86_int(0); \
1185 }
1187 void divl(uint32_t val)
1188 {
1189 if (val==0)
1190 {
1191 divexcp();
1192 return;
1193 }
1194 uint64_t num=(((uint64_t)EDX)<<32)|EAX;
1195 uint64_t quo=num/val;
1196 uint32_t rem=num%val;
1197 uint32_t quo32=(uint32_t)(quo&0xFFFFFFFF);
1198 if (quo!=(uint64_t)quo32)
1199 {
1200 divexcp();
1201 return;
1202 }
1203 EDX=rem;
1204 EAX=quo32;
1205 }
1206 void idivl(int32_t val)
1207 {
1208 if (val==0)
1209 {
1210 divexcp();
1211 return;
1212 }
1213 int64_t num=(((uint64_t)EDX)<<32)|EAX;
1214 int64_t quo=num/val;
1215 int32_t rem=num%val;
1216 int32_t quo32=(int32_t)(quo&0xFFFFFFFF);
1217 if (quo!=(int64_t)quo32)
1218 {
1219 divexcp();
1220 return;
1221 }
1222 EDX=rem;
1223 EAX=quo32;
1224 }
1227 void cpu_386_flags_extract()
1228 {
1229 flags_extract();
1230 }
1231 void cpu_386_flags_rebuild()
1232 {
1233 flags_rebuild();
1234 }
1236 int oldi;
1238 uint32_t testr[9];
1239 int dontprint=0;
1241 #undef NOTRM
1242 #define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\
1243 { \
1244 x86_int(6); \
1245 return 0; \
1246 }
1248 #include "386_ops.h"
1250 #undef NOTRM
1251 #define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\
1252 { \
1253 x86_int(6); \
1254 break; \
1255 }
1257 void exec386(int cycs)
1258 {
1259 uint8_t temp;
1260 uint32_t addr;
1261 int tempi;
1262 int cycdiff;
1263 int oldcyc;
1265 cycles+=cycs;
1266 // output=3;
1267 while (cycles>0)
1268 {
1269 cycdiff=0;
1270 oldcyc=cycles;
1271 timer_start_period(cycles);
1272 // pclog("%i %02X\n", ins, ram[8]);
1273 while (cycdiff<100)
1274 {
1275 /* testr[0]=EAX; testr[1]=EBX; testr[2]=ECX; testr[3]=EDX;
1276 testr[4]=ESI; testr[5]=EDI; testr[6]=EBP; testr[7]=ESP;*/
1277 /* testr[8]=flags;*/
1278 // oldcs2=oldcs;
1279 // oldpc2=oldpc;
1280 opcode_realstart:
1281 oldcs=CS;
1282 oldpc=pc;
1283 oldcpl=CPL;
1284 op32=use32;
1286 dontprint=0;
1288 ea_seg = &_ds;
1289 ssegs = 0;
1291 opcodestart:
1292 fetchdat = fastreadl(cs + pc);
1294 if (!abrt)
1295 {
1296 tempc = CF_SET();
1297 trap = flags & T_FLAG;
1298 opcode = fetchdat & 0xFF;
1299 fetchdat >>= 8;
1301 if (output == 3)
1302 {
1303 pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X %02X%02X %02X\n",CS,cs,pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0xB270+0x3F5], ram[0xB270+0x3F4], ram[0xB270+0x3F7], ram[0xB270+0x3F6], ram[0xB270+0x3F9], ram[0xB270+0x3F8], ram[0x4430+0x0D49]);
1304 }
1305 pc++;
1306 if (x86_opcodes[(opcode | op32) & 0x3ff](fetchdat))
1307 goto opcodestart;
1308 }
1310 if (!use32) pc &= 0xffff;
1312 if (abrt)
1313 {
1314 flags_rebuild();
1315 // pclog("Abort\n");
1316 // if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,abrt);
1317 /* if (testr[0]!=EAX) pclog("EAX corrupted %08X\n",pc);
1318 if (testr[1]!=EBX) pclog("EBX corrupted %08X\n",pc);
1319 if (testr[2]!=ECX) pclog("ECX corrupted %08X\n",pc);
1320 if (testr[3]!=EDX) pclog("EDX corrupted %08X\n",pc);
1321 if (testr[4]!=ESI) pclog("ESI corrupted %08X\n",pc);
1322 if (testr[5]!=EDI) pclog("EDI corrupted %08X\n",pc);
1323 if (testr[6]!=EBP) pclog("EBP corrupted %08X\n",pc);
1324 if (testr[7]!=ESP) pclog("ESP corrupted %08X\n",pc);*/
1325 /* if (testr[8]!=flags) pclog("FLAGS corrupted %08X\n",pc);*/
1326 tempi = abrt;
1327 abrt = 0;
1328 x86_doabrt(tempi);
1329 if (abrt)
1330 {
1331 abrt = 0;
1332 CS = oldcs;
1333 pc = oldpc;
1334 pclog("Double fault %i\n", ins);
1335 pmodeint(8, 0);
1336 if (abrt)
1337 {
1338 abrt = 0;
1339 softresetx86();
1340 pclog("Triple fault - reset\n");
1341 }
1342 }
1343 }
1344 cycdiff=oldcyc-cycles;
1346 if (trap)
1347 {
1348 flags_rebuild();
1349 // oldpc=pc;
1350 // oldcs=CS;
1351 if (msw&1)
1352 {
1353 pmodeint(1,0);
1354 }
1355 else
1356 {
1357 writememw(ss,(SP-2)&0xFFFF,flags);
1358 writememw(ss,(SP-4)&0xFFFF,CS);
1359 writememw(ss,(SP-6)&0xFFFF,pc);
1360 SP-=6;
1361 addr = (1 << 2) + idt.base;
1362 flags&=~I_FLAG;
1363 flags&=~T_FLAG;
1364 pc=readmemw(0,addr);
1365 loadcs(readmemw(0,addr+2));
1366 }
1367 }
1368 else if (nmi && nmi_enable)
1369 {
1370 oldpc = pc;
1371 oldcs = CS;
1372 // pclog("NMI\n");
1373 x86_int(2);
1374 nmi_enable = 0;
1375 }
1376 else if ((flags&I_FLAG) && pic_intpending)
1377 {
1378 temp=picinterrupt();
1379 if (temp!=0xFF)
1380 {
1381 // if (temp == 0x54) pclog("Take int 54\n");
1382 // if (output) output=3;
1383 // if (temp == 0xd) pclog("Hardware int %02X %i %04X(%08X):%08X\n",temp,ins, CS,cs,pc);
1384 // if (temp==0x54) output=3;
1385 flags_rebuild();
1386 if (msw&1)
1387 {
1388 pmodeint(temp,0);
1389 }
1390 else
1391 {
1392 writememw(ss,(SP-2)&0xFFFF,flags);
1393 writememw(ss,(SP-4)&0xFFFF,CS);
1394 writememw(ss,(SP-6)&0xFFFF,pc);
1395 SP-=6;
1396 addr = (temp << 2) + idt.base;
1397 flags&=~I_FLAG;
1398 flags&=~T_FLAG;
1399 oxpc=pc;
1400 pc=readmemw(0,addr);
1401 loadcs(readmemw(0,addr+2));
1402 // if (temp==0x76) pclog("INT to %04X:%04X\n",CS,pc);
1403 }
1404 // pclog("Now at %04X(%08X):%08X\n", CS, cs, pc);
1405 }
1406 }
1408 ins++;
1409 insc++;
1411 if (timetolive)
1412 {
1413 timetolive--;
1414 if (!timetolive)
1415 fatal("Life expired\n");
1416 }
1417 }
1419 tsc += cycdiff;
1421 timer_end_period(cycles);
1422 }
1423 }
