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