PCem
view src/808x.c @ 111:912e602b3406
Moved PIT to common timer API.
| author | TomW |
|---|---|
| date | Thu Jun 19 21:02:59 2014 +0100 |
| parents | eb624a751863 |
| children | bd46c39a78e8 |
line source
1 //1B64 - Vid_SetMode (Vid_Vesa.c)
2 //6689c - CONS_Printf
3 /*SHR AX,1
5 4 clocks - fetch opcode
6 4 clocks - fetch mod/rm
7 2 clocks - execute 2 clocks - fetch opcode 1
8 2 clocks - fetch opcode 2
9 4 clocks - fetch mod/rm
10 2 clocks - fetch opcode 1 2 clocks - execute
11 2 clocks - fetch opcode 2 etc*/
12 #include <stdio.h>
13 #include "ibm.h"
15 #include "cpu.h"
16 #include "keyboard.h"
17 #include "mem.h"
18 #include "pic.h"
19 #include "timer.h"
20 #include "x86.h"
22 int nmi = 0;
24 int nextcyc=0;
25 int cycdiff;
26 int is8086=0;
28 int memcycs;
29 int nopageerrors=0;
31 void FETCHCOMPLETE();
33 uint8_t readmembl(uint32_t addr);
34 void writemembl(uint32_t addr, uint8_t val);
35 uint16_t readmemwl(uint32_t seg, uint32_t addr);
36 void writememwl(uint32_t seg, uint32_t addr, uint16_t val);
37 uint32_t readmemll(uint32_t seg, uint32_t addr);
38 void writememll(uint32_t seg, uint32_t addr, uint32_t val);
40 #undef readmemb
41 #undef readmemw
42 uint8_t readmemb(uint32_t a)
43 {
44 if (a!=(cs+pc)) memcycs+=4;
45 if (readlookup2[(a)>>12]==0xFFFFFFFF) return readmembl(a);
46 else return *(uint8_t *)(readlookup2[(a) >> 12] + (a));
47 }
49 uint8_t readmembf(uint32_t a)
50 {
51 if (readlookup2[(a)>>12]==0xFFFFFFFF) return readmembl(a);
52 else return *(uint8_t *)(readlookup2[(a) >> 12] + (a));
53 }
55 uint16_t readmemw(uint32_t s, uint16_t a)
56 {
57 if (a!=(cs+pc)) memcycs+=(8>>is8086);
58 if ((readlookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF)) return readmemwl(s,a);
59 else return *(uint16_t *)(readlookup2[(s + a) >> 12] + s + a);
60 }
62 void refreshread() { /*pclog("Refreshread\n"); */FETCHCOMPLETE(); memcycs+=4; }
64 #undef fetchea
65 #define fetchea() { rmdat=FETCH(); \
66 reg=(rmdat>>3)&7; \
67 mod=(rmdat>>6)&3; \
68 rm=rmdat&7; \
69 if (mod!=3) fetcheal(); }
71 void writemembl(uint32_t addr, uint8_t val);
72 void writememb(uint32_t a, uint8_t v)
73 {
74 memcycs+=4;
75 if (writelookup2[(a)>>12]==0xFFFFFFFF) writemembl(a,v);
76 else *(uint8_t *)(writelookup2[a >> 12] + a) = v;
77 }
78 void writememwl(uint32_t seg, uint32_t addr, uint16_t val);
79 void writememw(uint32_t s, uint32_t a, uint16_t v)
80 {
81 memcycs+=(8>>is8086);
82 if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememwl(s,a,v);
83 else *(uint16_t *)(writelookup2[(s + a) >> 12] + s + a) = v;
84 }
85 void writememll(uint32_t seg, uint32_t addr, uint32_t val);
86 void writememl(uint32_t s, uint32_t a, uint32_t v)
87 {
88 if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememll(s,a,v);
89 else *(uint32_t *)(writelookup2[(s + a) >> 12] + s + a) = v;
90 }
93 void dumpregs();
94 uint16_t oldcs;
95 int oldcpl;
97 int tempc;
98 uint8_t opcode;
99 int times=0;
100 uint16_t pc2,pc3;
101 int noint=0;
103 int output=0;
105 int shadowbios=0;
107 int ins=0;
108 //#define readmemb(a) (((a)<0xA0000)?ram[a]:readmembl(a))
110 int ssegs;
112 int fetchcycles=0,memcycs,fetchclocks;
114 uint8_t prefetchqueue[6];
115 uint16_t prefetchpc;
116 int prefetchw=0;
117 inline uint8_t FETCH()
118 {
119 uint8_t temp;
120 /* temp=prefetchqueue[0];
121 prefetchqueue[0]=prefetchqueue[1];
122 prefetchqueue[1]=prefetchqueue[2];
123 prefetchqueue[2]=prefetchqueue[3];
124 prefetchqueue[3]=prefetchqueue[4];
125 prefetchqueue[4]=prefetchqueue[5];
126 if (prefetchw<=((is8086)?4:3))
127 {
128 prefetchqueue[prefetchw++]=readmembf(cs+prefetchpc); prefetchpc++;
129 if (is8086 && (prefetchpc&1))
130 {
131 prefetchqueue[prefetchw++]=readmembf(cs+prefetchpc); prefetchpc++;
132 }
133 }*/
135 // uint8_t temp=readmemb(cs+pc);
136 // if (output) printf("FETCH %04X %i\n",pc,fetchcycles);
137 if (prefetchw==0) //(fetchcycles<4)
138 {
139 cycles-=(4-(fetchcycles&3));
140 fetchclocks+=(4-(fetchcycles&3));
141 fetchcycles=4;
142 temp=readmembf(cs+pc);
143 prefetchpc=pc=pc+1;
144 // if (output) printf(" FETCH %04X:%04X %02X %04X %04X %i\n",CS,pc-1,temp,pc,prefetchpc,prefetchw);
145 if (is8086 && (pc&1))
146 {
147 prefetchqueue[0]=readmembf(cs+pc);
148 // if (output) printf(" PREFETCHED from %04X:%04X %02X 8086\n",CS,prefetchpc,prefetchqueue[prefetchw]);
149 prefetchpc++;
150 prefetchw++;
151 }
152 }
153 else
154 {
155 temp=prefetchqueue[0];
156 prefetchqueue[0]=prefetchqueue[1];
157 prefetchqueue[1]=prefetchqueue[2];
158 prefetchqueue[2]=prefetchqueue[3];
159 prefetchqueue[3]=prefetchqueue[4];
160 prefetchqueue[4]=prefetchqueue[5];
161 prefetchw--;
162 // if (output) printf("PREFETCH %04X:%04X %02X %04X %04X %i\n",CS,pc,temp,pc,prefetchpc,prefetchw);
163 fetchcycles-=4;
164 // fetchclocks+=4;
165 pc++;
166 }
167 // if (output) printf("%i\n",fetchcycles);
168 return temp;
169 }
171 inline void FETCHADD(int c)
172 {
173 int d;
174 // if (output) printf("FETCHADD %i\n",c);
175 if (c<0) return;
176 if (prefetchw>((is8086)?4:3)) return;
177 d=c+(fetchcycles&3);
178 while (d>3 && prefetchw<((is8086)?6:4))
179 {
180 d-=4;
181 if (is8086 && !(prefetchpc&1))
182 {
183 prefetchqueue[prefetchw]=readmembf(cs+prefetchpc);
184 // printf("PREFETCHED from %04X:%04X %02X 8086\n",CS,prefetchpc,prefetchqueue[prefetchw]);
185 prefetchpc++;
186 prefetchw++;
187 }
188 if (prefetchw<6)
189 {
190 prefetchqueue[prefetchw]=readmembf(cs+prefetchpc);
191 // printf("PREFETCHED from %04X:%04X %02X\n",CS,prefetchpc,prefetchqueue[prefetchw]);
192 prefetchpc++;
193 prefetchw++;
194 }
195 }
196 fetchcycles+=c;
197 if (fetchcycles>16) fetchcycles=16;
198 // if (fetchcycles>24) fetchcycles=24;
199 }
201 void FETCHCOMPLETE()
202 {
203 // pclog("Fetchcomplete %i %i %i\n",fetchcycles&3,fetchcycles,prefetchw);
204 if (!(fetchcycles&3)) return;
205 if (prefetchw>((is8086)?4:3)) return;
206 if (!prefetchw) nextcyc=(4-(fetchcycles&3));
207 cycles-=(4-(fetchcycles&3));
208 fetchclocks+=(4-(fetchcycles&3));
209 if (is8086 && !(prefetchpc&1))
210 {
211 prefetchqueue[prefetchw]=readmembf(cs+prefetchpc);
212 // printf("PREFETCHEDc from %04X:%04X %02X 8086\n",CS,prefetchpc,prefetchqueue[prefetchw]);
213 prefetchpc++;
214 prefetchw++;
215 }
216 if (prefetchw<6)
217 {
218 prefetchqueue[prefetchw]=readmembf(cs+prefetchpc);
219 // printf("PREFETCHEDc from %04X:%04X %02X\n",CS,prefetchpc,prefetchqueue[prefetchw]);
220 prefetchpc++;
221 prefetchw++;
222 }
223 fetchcycles+=(4-(fetchcycles&3));
224 }
226 inline void FETCHCLEAR()
227 {
228 /* int c;
229 fetchcycles=0;
230 prefetchpc=pc;
231 if (is8086 && (prefetchpc&1)) cycles-=4;
232 for (c=0;c<((is8086)?6:4);c++)
233 {
234 prefetchqueue[c]=readmembf(cs+prefetchpc);
235 if (!is8086 || !(prefetchpc&1)) cycles-=4;
236 prefetchpc++;
237 }
238 prefetchw=(is8086)?6:4;*/
239 // fetchcycles=0;
240 prefetchpc=pc;
241 prefetchw=0;
242 memcycs=cycdiff-cycles;
243 fetchclocks=0;
244 // memcycs=cycles;
245 /* prefetchqueue[0]=readmembf(cs+prefetchpc);
246 prefetchpc++;
247 prefetchw=1;
248 if (is8086 && prefetchpc&1)
249 {
250 prefetchqueue[1]=readmembf(cs+prefetchpc);
251 prefetchpc++;
252 }*/
253 }
255 static uint16_t getword()
256 {
257 uint8_t temp=FETCH();
258 return temp|(FETCH()<<8);
259 }
262 /*EA calculation*/
264 /*R/M - bits 0-2 - R/M bits 3-5 - Reg bits 6-7 - mod
265 From 386 programmers manual :
266 r8(/r) AL CL DL BL AH CH DH BH
267 r16(/r) AX CX DX BX SP BP SI DI
268 r32(/r) EAX ECX EDX EBX ESP EBP ESI EDI
269 /digit (Opcode) 0 1 2 3 4 5 6 7
270 REG = 000 001 010 011 100 101 110 111
271 ÚÄÄÄAddress
272 disp8 denotes an 8-bit displacement following the ModR/M byte, to be
273 sign-extended and added to the index. disp16 denotes a 16-bit displacement
274 following the ModR/M byte, to be added to the index. Default segment
275 register is SS for the effective addresses containing a BP index, DS for
276 other effective addresses.
277 ÄÄ¿ ÚMod R/M¿ ÚÄÄÄÄÄÄÄÄModR/M Values in HexadecimalÄÄÄÄÄÄÄÄ¿
279 [BX + SI] 000 00 08 10 18 20 28 30 38
280 [BX + DI] 001 01 09 11 19 21 29 31 39
281 [BP + SI] 010 02 0A 12 1A 22 2A 32 3A
282 [BP + DI] 011 03 0B 13 1B 23 2B 33 3B
283 [SI] 00 100 04 0C 14 1C 24 2C 34 3C
284 [DI] 101 05 0D 15 1D 25 2D 35 3D
285 disp16 110 06 0E 16 1E 26 2E 36 3E
286 [BX] 111 07 0F 17 1F 27 2F 37 3F
288 [BX+SI]+disp8 000 40 48 50 58 60 68 70 78
289 [BX+DI]+disp8 001 41 49 51 59 61 69 71 79
290 [BP+SI]+disp8 010 42 4A 52 5A 62 6A 72 7A
291 [BP+DI]+disp8 011 43 4B 53 5B 63 6B 73 7B
292 [SI]+disp8 01 100 44 4C 54 5C 64 6C 74 7C
293 [DI]+disp8 101 45 4D 55 5D 65 6D 75 7D
294 [BP]+disp8 110 46 4E 56 5E 66 6E 76 7E
295 [BX]+disp8 111 47 4F 57 5F 67 6F 77 7F
297 [BX+SI]+disp16 000 80 88 90 98 A0 A8 B0 B8
298 [BX+DI]+disp16 001 81 89 91 99 A1 A9 B1 B9
299 [BX+SI]+disp16 010 82 8A 92 9A A2 AA B2 BA
300 [BX+DI]+disp16 011 83 8B 93 9B A3 AB B3 BB
301 [SI]+disp16 10 100 84 8C 94 9C A4 AC B4 BC
302 [DI]+disp16 101 85 8D 95 9D A5 AD B5 BD
303 [BP]+disp16 110 86 8E 96 9E A6 AE B6 BE
304 [BX]+disp16 111 87 8F 97 9F A7 AF B7 BF
306 EAX/AX/AL 000 C0 C8 D0 D8 E0 E8 F0 F8
307 ECX/CX/CL 001 C1 C9 D1 D9 E1 E9 F1 F9
308 EDX/DX/DL 010 C2 CA D2 DA E2 EA F2 FA
309 EBX/BX/BL 011 C3 CB D3 DB E3 EB F3 FB
310 ESP/SP/AH 11 100 C4 CC D4 DC E4 EC F4 FC
311 EBP/BP/CH 101 C5 CD D5 DD E5 ED F5 FD
312 ESI/SI/DH 110 C6 CE D6 DE E6 EE F6 FE
313 EDI/DI/BH 111 C7 CF D7 DF E7 EF F7 FF
315 mod = 11 - register
316 10 - address + 16 bit displacement
317 01 - address + 8 bit displacement
318 00 - address
320 reg = If mod=11, (depending on data size, 16 bits/8 bits, 32 bits=extend 16 bit registers)
321 0=AX/AL 1=CX/CL 2=DX/DL 3=BX/BL
322 4=SP/AH 5=BP/CH 6=SI/DH 7=DI/BH
324 Otherwise, LSB selects SI/DI (0=SI), NMSB selects BX/BP (0=BX), and MSB
325 selects whether BX/BP are used at all (0=used).
327 mod=00 is an exception though
328 6=16 bit displacement only
329 7=[BX]
331 Usage varies with instructions.
333 MOV AL,BL has ModR/M as C3, for example.
334 mod=11, reg=0, r/m=3
335 MOV uses reg as dest, and r/m as src.
336 reg 0 is AL, reg 3 is BL
338 If BP or SP are in address calc, seg is SS, else DS
339 */
341 int cycles=0;
342 uint32_t easeg,eaaddr;
343 int rm,reg,mod,rmdat;
345 uint16_t zero=0;
346 uint16_t *mod1add[2][8];
347 uint32_t *mod1seg[8];
349 int slowrm[8];
351 void makemod1table()
352 {
353 mod1add[0][0]=&BX; mod1add[0][1]=&BX; mod1add[0][2]=&BP; mod1add[0][3]=&BP;
354 mod1add[0][4]=&SI; mod1add[0][5]=&DI; mod1add[0][6]=&BP; mod1add[0][7]=&BX;
355 mod1add[1][0]=&SI; mod1add[1][1]=&DI; mod1add[1][2]=&SI; mod1add[1][3]=&DI;
356 mod1add[1][4]=&zero; mod1add[1][5]=&zero; mod1add[1][6]=&zero; mod1add[1][7]=&zero;
357 slowrm[0]=0; slowrm[1]=1; slowrm[2]=1; slowrm[3]=0;
358 mod1seg[0]=&ds; mod1seg[1]=&ds; mod1seg[2]=&ss; mod1seg[3]=&ss;
359 mod1seg[4]=&ds; mod1seg[5]=&ds; mod1seg[6]=&ss; mod1seg[7]=&ds;
360 }
362 static void fetcheal()
363 {
364 if (!mod && rm==6) { eaaddr=getword(); easeg=ds; FETCHADD(6); }
365 else
366 {
367 switch (mod)
368 {
369 case 0:
370 eaaddr=0;
371 if (rm&4) FETCHADD(5);
372 else FETCHADD(7+slowrm[rm]);
373 break;
374 case 1:
375 eaaddr=(uint16_t)(int8_t)FETCH();
376 if (rm&4) FETCHADD(9);
377 else FETCHADD(11+slowrm[rm]);
378 break;
379 case 2:
380 eaaddr=getword();
381 if (rm&4) FETCHADD(9);
382 else FETCHADD(11+slowrm[rm]);
383 break;
384 }
385 eaaddr+=(*mod1add[0][rm])+(*mod1add[1][rm]);
386 easeg=*mod1seg[rm];
387 eaaddr&=0xFFFF;
388 }
389 }
391 static inline uint8_t geteab()
392 {
393 if (mod==3)
394 return (rm&4)?regs[rm&3].b.h:regs[rm&3].b.l;
395 return readmemb(easeg+eaaddr);
396 }
398 static inline uint16_t geteaw()
399 {
400 if (mod==3)
401 return regs[rm].w;
402 // if (output==3) printf("GETEAW %04X:%08X\n",easeg,eaaddr);
403 return readmemw(easeg,eaaddr);
404 }
406 static inline uint16_t geteaw2()
407 {
408 if (mod==3)
409 return regs[rm].w;
410 // printf("Getting addr from %04X:%04X %05X\n",easeg,eaaddr+2,easeg+eaaddr+2);
411 return readmemw(easeg,(eaaddr+2)&0xFFFF);
412 }
414 static inline void seteab(uint8_t val)
415 {
416 if (mod==3)
417 {
418 if (rm&4) regs[rm&3].b.h=val;
419 else regs[rm&3].b.l=val;
420 }
421 else
422 {
423 writememb(easeg+eaaddr,val);
424 }
425 }
427 static inline void seteaw(uint16_t val)
428 {
429 if (mod==3)
430 regs[rm].w=val;
431 else
432 {
433 writememw(easeg,eaaddr,val);
434 // writememb(easeg+eaaddr+1,val>>8);
435 }
436 }
438 #define getr8(r) ((r&4)?regs[r&3].b.h:regs[r&3].b.l)
440 #define setr8(r,v) if (r&4) regs[r&3].b.h=v; \
441 else regs[r&3].b.l=v;
444 /*Flags*/
445 uint8_t znptable8[256];
446 uint16_t znptable16[65536];
448 void makeznptable()
449 {
450 int c,d;
451 for (c=0;c<256;c++)
452 {
453 d=0;
454 if (c&1) d++;
455 if (c&2) d++;
456 if (c&4) d++;
457 if (c&8) d++;
458 if (c&16) d++;
459 if (c&32) d++;
460 if (c&64) d++;
461 if (c&128) d++;
462 if (d&1)
463 znptable8[c]=0;
464 else
465 znptable8[c]=P_FLAG;
466 if (c == 0xb1) pclog("znp8 b1 = %i %02X\n", d, znptable8[c]);
467 if (!c) znptable8[c]|=Z_FLAG;
468 if (c&0x80) znptable8[c]|=N_FLAG;
469 }
470 for (c=0;c<65536;c++)
471 {
472 d=0;
473 if (c&1) d++;
474 if (c&2) d++;
475 if (c&4) d++;
476 if (c&8) d++;
477 if (c&16) d++;
478 if (c&32) d++;
479 if (c&64) d++;
480 if (c&128) d++;
481 if (d&1)
482 znptable16[c]=0;
483 else
484 znptable16[c]=P_FLAG;
485 if (c == 0xb1) pclog("znp16 b1 = %i %02X\n", d, znptable16[c]);
486 if (c == 0x65b1) pclog("znp16 65b1 = %i %02X\n", d, znptable16[c]);
487 if (!c) znptable16[c]|=Z_FLAG;
488 if (c&0x8000) znptable16[c]|=N_FLAG;
489 }
491 // makemod1table();
492 }
493 int timetolive=0;
495 extern uint32_t oldcs2;
496 extern uint32_t oldpc2;
498 int indump = 0;
500 void dumpregs()
501 {
502 int c,d=0,e=0,ff;
503 #ifndef RELEASE_BUILD
504 FILE *f;
505 if (indump) return;
506 indump = 1;
507 // return;
508 output=0;
509 // return;
510 // savenvr();
511 // return;
512 chdir(pcempath);
513 nopageerrors=1;
514 /* f=fopen("rram3.dmp","wb");
515 for (c=0;c<0x8000000;c++) putc(readmemb(c+0x10000000),f);
516 fclose(f);*/
517 f=fopen("ram.dmp","wb");
518 fwrite(ram,mem_size*1024*1024,1,f);
519 fclose(f);
520 /* pclog("Dumping rram5.dmp\n");
521 f=fopen("rram5.dmp","wb");
522 for (c=0;c<0x1000000;c++) putc(readmemb(c+0x10150000),f);
523 fclose(f);*/
524 pclog("Dumping rram.dmp\n");
525 f=fopen("rram.dmp","wb");
526 for (c=0;c<0x1000000;c++) putc(readmemb(c),f);
527 fclose(f);
528 /* f=fopen("rram2.dmp","wb");
529 for (c=0;c<0x100000;c++) putc(readmemb(c+0xbff00000),f);
530 fclose(f);
531 f = fopen("stack.dmp","wb");
532 for (c = 0; c < 0x6000; c++) putc(readmemb(c+0xFFDFA000), f);
533 fclose(f);
534 f = fopen("tempx.dmp","wb");
535 for (c = 0; c < 0x10000; c++) putc(readmemb(c+0xFC816000), f);
536 fclose(f);
537 f = fopen("tempx2.dmp","wb");
538 for (c = 0; c < 0x10000; c++) putc(readmemb(c+0xFDEF5000), f);
539 fclose(f);*/
540 pclog("Dumping rram4.dmp\n");
541 f=fopen("rram4.dmp","wb");
542 for (c=0;c<0x0050000;c++)
543 {
544 abrt = 0;
545 putc(readmemb386l(0,c+0x80000000),f);
546 }
547 fclose(f);
548 pclog("Dumping done\n");
549 /* f=fopen("rram6.dmp","wb");
550 for (c=0;c<0x1000000;c++) putc(readmemb(c+0xBF000000),f);
551 fclose(f);*/
552 /* f=fopen("ram6.bin","wb");
553 fwrite(ram+0x10100,0xA000,1,f);
554 fclose(f);
555 f=fopen("boot.bin","wb");
556 fwrite(ram+0x7C00,0x200,1,f);
557 fclose(f);
558 f=fopen("ram7.bin","wb");
559 fwrite(ram+0x11100,0x2000,1,f);
560 fclose(f);
561 f=fopen("ram8.bin","wb");
562 fwrite(ram+0x3D210,0x200,1,f);
563 fclose(f); */
564 /* f=fopen("bios.dmp","wb");
565 fwrite(rom,0x20000,1,f);
566 fclose(f);*/
567 /* f=fopen("kernel.dmp","wb");
568 for (c=0;c<0x200000;c++) putc(readmemb(c+0xC0000000),f);
569 fclose(f);*/
570 /* f=fopen("rram.dmp","wb");
571 for (c=0;c<0x1500000;c++) putc(readmemb(c),f);
572 fclose(f);
573 if (!times)
574 {
575 f=fopen("thing.dmp","wb");
576 fwrite(ram+0x11E50,0x1000,1,f);
577 fclose(f);
578 }*/
579 #endif
580 if (is386)
581 printf("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n",EAX,EBX,ECX,EDX,EDI,ESI,EBP,ESP);
582 else
583 printf("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",AX,BX,CX,DX,DI,SI,BP,SP);
584 printf("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",pc,CS,DS,ES,SS,flags);
585 printf("%04X:%04X %04X:%04X\n",oldcs,oldpc, oldcs2, oldpc2);
586 printf("%i ins\n",ins);
587 if (is386)
588 printf("In %s mode\n",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real");
589 else
590 printf("In %s mode\n",(msw&1)?"protected":"real");
591 printf("CS : base=%06X limit=%04X access=%02X\n",cs,_cs.limit,_cs.access);
592 printf("DS : base=%06X limit=%04X access=%02X\n",ds,_ds.limit,_ds.access);
593 printf("ES : base=%06X limit=%04X access=%02X\n",es,_es.limit,_es.access);
594 if (is386)
595 {
596 printf("FS : base=%06X limit=%04X access=%02X\n",fs,_fs.limit,_fs.access);
597 printf("GS : base=%06X limit=%04X access=%02X\n",gs,_gs.limit,_gs.access);
598 }
599 printf("SS : base=%06X limit=%04X access=%02X\n",ss,_ss.limit,_ss.access);
600 printf("GDT : base=%06X limit=%04X\n",gdt.base,gdt.limit);
601 printf("LDT : base=%06X limit=%04X\n",ldt.base,ldt.limit);
602 printf("IDT : base=%06X limit=%04X\n",idt.base,idt.limit);
603 printf("TR : base=%06X limit=%04X\n", tr.base, tr.limit);
604 if (is386)
605 {
606 printf("386 in %s mode stack in %s mode\n",(use32)?"32-bit":"16-bit",(stack32)?"32-bit":"16-bit");
607 printf("CR0=%08X CR2=%08X CR3=%08X\n",cr0,cr2,cr3);
608 }
609 printf("Entries in readlookup : %i writelookup : %i\n",readlnum,writelnum);
610 for (c=0;c<1024*1024;c++)
611 {
612 if (readlookup2[c]!=0xFFFFFFFF) d++;
613 if (writelookup2[c]!=0xFFFFFFFF) e++;
614 }
615 printf("Entries in readlookup : %i writelookup : %i\n",d,e);
616 x87_dumpregs();
617 indump = 0;
618 }
620 int resets = 0;
621 void resetx86()
622 {
623 pclog("x86 reset\n");
624 resets++;
625 ins = 0;
626 use32=0;
627 stack32=0;
628 // i86_Reset();
629 // cs=0xFFFF0;
630 pc=0;
631 msw=0;
632 cr0=0;
633 eflags=0;
634 cgate32=0;
635 loadcs(0xFFFF);
636 rammask=0xFFFFFFFF;
637 idt.base = 0;
638 flags=2;
639 makeznptable();
640 resetreadlookup();
641 makemod1table();
642 resetmcr();
643 FETCHCLEAR();
644 x87_reset();
645 cpu_set_edx();
646 ESP=0;
647 mmu_perm=4;
648 memset(inscounts, 0, sizeof(inscounts));
649 }
651 void softresetx86()
652 {
653 // dumpregs();
654 // exit(-1);
655 use32=0;
656 stack32=0;
657 // i86_Reset();
658 // cs=0xFFFF0;
659 pc=0;
660 msw=0;
661 cr0=0;
662 eflags=0;
663 cgate32=0;
664 loadcs(0xFFFF);
665 //rammask=0xFFFFFFFF;
666 flags=2;
667 idt.base = 0;
668 }
670 static void setznp8(uint8_t val)
671 {
672 flags&=~0xC4;
673 flags|=znptable8[val];
674 }
676 static void setznp16(uint16_t val)
677 {
678 flags&=~0xC4;
679 flags|=znptable16[val];
680 }
682 static void setadd8(uint8_t a, uint8_t b)
683 {
684 uint16_t c=(uint16_t)a+(uint16_t)b;
685 flags&=~0x8D5;
686 flags|=znptable8[c&0xFF];
687 if (c&0x100) flags|=C_FLAG;
688 if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
689 if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
690 }
691 static void setadd8nc(uint8_t a, uint8_t b)
692 {
693 uint16_t c=(uint16_t)a+(uint16_t)b;
694 flags&=~0x8D4;
695 flags|=znptable8[c&0xFF];
696 if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
697 if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
698 }
699 static void setadc8(uint8_t a, uint8_t b)
700 {
701 uint16_t c=(uint16_t)a+(uint16_t)b+tempc;
702 flags&=~0x8D5;
703 flags|=znptable8[c&0xFF];
704 if (c&0x100) flags|=C_FLAG;
705 if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
706 if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
707 }
708 static void setadd16(uint16_t a, uint16_t b)
709 {
710 uint32_t c=(uint32_t)a+(uint32_t)b;
711 flags&=~0x8D5;
712 flags|=znptable16[c&0xFFFF];
713 if (c&0x10000) flags|=C_FLAG;
714 if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
715 if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
716 }
717 static void setadd16nc(uint16_t a, uint16_t b)
718 {
719 uint32_t c=(uint32_t)a+(uint32_t)b;
720 flags&=~0x8D4;
721 flags|=znptable16[c&0xFFFF];
722 if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
723 if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
724 }
725 static void setadc16(uint16_t a, uint16_t b)
726 {
727 uint32_t c=(uint32_t)a+(uint32_t)b+tempc;
728 flags&=~0x8D5;
729 flags|=znptable16[c&0xFFFF];
730 if (c&0x10000) flags|=C_FLAG;
731 if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
732 if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
733 }
735 static void setsub8(uint8_t a, uint8_t b)
736 {
737 uint16_t c=(uint16_t)a-(uint16_t)b;
738 flags&=~0x8D5;
739 flags|=znptable8[c&0xFF];
740 if (c&0x100) flags|=C_FLAG;
741 if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
742 if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
743 }
744 static void setsub8nc(uint8_t a, uint8_t b)
745 {
746 uint16_t c=(uint16_t)a-(uint16_t)b;
747 flags&=~0x8D4;
748 flags|=znptable8[c&0xFF];
749 if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
750 if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
751 }
752 static void setsbc8(uint8_t a, uint8_t b)
753 {
754 uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc);
755 flags&=~0x8D5;
756 flags|=znptable8[c&0xFF];
757 if (c&0x100) flags|=C_FLAG;
758 if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
759 if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
760 }
761 static void setsub16(uint16_t a, uint16_t b)
762 {
763 uint32_t c=(uint32_t)a-(uint32_t)b;
764 flags&=~0x8D5;
765 flags|=znptable16[c&0xFFFF];
766 if (c&0x10000) flags|=C_FLAG;
767 if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
768 // if (output) printf("%04X %04X %i\n",a^b,a^c,flags&V_FLAG);
769 if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
770 }
771 static void setsub16nc(uint16_t a, uint16_t b)
772 {
773 uint32_t c=(uint32_t)a-(uint32_t)b;
774 flags&=~0x8D4;
775 flags|=(znptable16[c&0xFFFF]&~4);
776 flags|=(znptable8[c&0xFF]&4);
777 if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
778 if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
779 }
780 static void setsbc16(uint16_t a, uint16_t b)
781 {
782 uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc);
783 flags&=~0x8D5;
784 flags|=(znptable16[c&0xFFFF]&~4);
785 flags|=(znptable8[c&0xFF]&4);
786 if (c&0x10000) flags|=C_FLAG;
787 if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
788 if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
789 }
791 int current_diff = 0;
792 void clockhardware()
793 {
794 int diff = cycdiff - cycles - current_diff;
796 current_diff += diff;
797 if (pit.running[0]) pit.c[0] -= diff;
798 if (pit.running[1]) pit.c[1] -= diff;
799 if (pit.running[2]) pit.c[2] -= diff;
800 if ((pit.c[0] < 1) || (pit.c[1] < 1) || (pit.c[2] < 1)) pit_poll();
802 timer_end_period(cycles);
803 }
805 static int takeint = 0;
808 int firstrepcycle=1;
810 void rep(int fv)
811 {
812 uint8_t temp;
813 int c=CX;
814 uint8_t temp2;
815 uint16_t tempw,tempw2;
816 uint16_t ipc=oldpc;//pc-1;
817 int changeds=0;
818 uint32_t oldds;
819 startrep:
820 temp=FETCH();
822 // if (firstrepcycle && temp==0xA5) printf("REP MOVSW %06X:%04X %06X:%04X\n",ds,SI,es,DI);
823 // if (output) printf("REP %02X %04X\n",temp,ipc);
824 switch (temp)
825 {
826 case 0x08:
827 pc=ipc+1;
828 cycles-=2;
829 FETCHCLEAR();
830 break;
831 case 0x26: /*ES:*/
832 oldds=ds;
833 ds=es;
834 changeds=1;
835 cycles-=2;
836 goto startrep;
837 break;
838 case 0x2E: /*CS:*/
839 oldds=ds;
840 ds=cs;
841 changeds=1;
842 cycles-=2;
843 goto startrep;
844 break;
845 case 0x36: /*SS:*/
846 oldds=ds;
847 ds=ss;
848 changeds=1;
849 cycles-=2;
850 goto startrep;
851 break;
852 case 0x6E: /*REP OUTSB*/
853 if (c>0)
854 {
855 temp2=readmemb(ds+SI);
856 outb(DX,temp2);
857 if (flags&D_FLAG) SI--;
858 else SI++;
859 c--;
860 cycles-=5;
861 }
862 if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
863 else firstrepcycle=1;
864 break;
865 case 0xA4: /*REP MOVSB*/
866 while (c>0 && !IRQTEST)
867 {
868 temp2=readmemb(ds+SI);
869 writememb(es+DI,temp2);
870 // if (output) printf("Moved %02X from %04X:%04X to %04X:%04X\n",temp2,ds>>4,SI,es>>4,DI);
871 if (flags&D_FLAG) { DI--; SI--; }
872 else { DI++; SI++; }
873 c--;
874 cycles-=17;
875 clockhardware();
876 FETCHADD(17-memcycs);
877 }
878 if (IRQTEST && c>0) pc=ipc;
879 // if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
880 // else firstrepcycle=1;
881 // }
882 break;
883 case 0xA5: /*REP MOVSW*/
884 while (c>0 && !IRQTEST)
885 {
886 memcycs=0;
887 tempw=readmemw(ds,SI);
888 writememw(es,DI,tempw);
889 if (flags&D_FLAG) { DI-=2; SI-=2; }
890 else { DI+=2; SI+=2; }
891 c--;
892 cycles-=17;
893 clockhardware();
894 FETCHADD(17 - memcycs);
895 }
896 if (IRQTEST && c>0) pc=ipc;
897 // if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
898 // else firstrepcycle=1;
899 // }
900 break;
901 case 0xA6: /*REP CMPSB*/
902 if (fv) flags|=Z_FLAG;
903 else flags&=~Z_FLAG;
904 while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST)
905 {
906 memcycs=0;
907 temp=readmemb(ds+SI);
908 temp2=readmemb(es+DI);
909 // printf("CMPSB %c %c %i %05X %05X %04X:%04X\n",temp,temp2,c,ds+SI,es+DI,cs>>4,pc);
910 if (flags&D_FLAG) { DI--; SI--; }
911 else { DI++; SI++; }
912 c--;
913 cycles -= 30;
914 setsub8(temp,temp2);
915 clockhardware();
916 FETCHADD(30 - memcycs);
917 }
918 if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) pc=ipc;
919 // if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
920 // else firstrepcycle=1;
921 break;
922 case 0xA7: /*REP CMPSW*/
923 if (fv) flags|=Z_FLAG;
924 else flags&=~Z_FLAG;
925 while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST)
926 {
927 memcycs=0;
928 tempw=readmemw(ds,SI);
929 tempw2=readmemw(es,DI);
930 if (flags&D_FLAG) { DI-=2; SI-=2; }
931 else { DI+=2; SI+=2; }
932 c--;
933 cycles -= 30;
934 setsub16(tempw,tempw2);
935 clockhardware();
936 FETCHADD(30 - memcycs);
937 }
938 if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) pc=ipc;
939 // if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
940 // else firstrepcycle=1;
941 // if (firstrepcycle) printf("REP CMPSW %06X:%04X %06X:%04X %04X %04X\n",ds,SI,es,DI,tempw,tempw2);
942 break;
943 case 0xAA: /*REP STOSB*/
944 while (c>0 && !IRQTEST)
945 {
946 memcycs=0;
947 writememb(es+DI,AL);
948 if (flags&D_FLAG) DI--;
949 else DI++;
950 c--;
951 cycles -= 10;
952 clockhardware();
953 FETCHADD(10 - memcycs);
954 }
955 if (IRQTEST && c>0) pc=ipc;
956 // if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
957 // else firstrepcycle=1;
958 break;
959 case 0xAB: /*REP STOSW*/
960 while (c>0 && !IRQTEST)
961 {
962 memcycs=0;
963 writememw(es,DI,AX);
964 if (flags&D_FLAG) DI-=2;
965 else DI+=2;
966 c--;
967 cycles -= 10;
968 clockhardware();
969 FETCHADD(10 - memcycs);
970 }
971 if (IRQTEST && c>0) pc=ipc;
972 // if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
973 // else firstrepcycle=1;
974 break;
975 case 0xAC: /*REP LODSB*/
976 if (c>0)
977 {
978 temp2=readmemb(ds+SI);
979 if (flags&D_FLAG) SI--;
980 else SI++;
981 c--;
982 cycles-=4;
983 }
984 if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
985 else firstrepcycle=1;
986 break;
987 case 0xAD: /*REP LODSW*/
988 if (c>0)
989 {
990 tempw2=readmemw(ds,SI);
991 if (flags&D_FLAG) SI-=2;
992 else SI+=2;
993 c--;
994 cycles-=4;
995 }
996 if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
997 else firstrepcycle=1;
998 break;
999 case 0xAE: /*REP SCASB*/
1000 if (fv) flags|=Z_FLAG;
1001 else flags&=~Z_FLAG;
1002 if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
1003 {
1004 temp2=readmemb(es+DI);
1005 // if (output) printf("SCASB %02X %c %02X %05X ",temp2,temp2,AL,es+DI);
1006 setsub8(AL,temp2);
1007 // if (output && flags&Z_FLAG) printf("Match %02X %02X\n",AL,temp2);
1008 if (flags&D_FLAG) DI--;
1009 else DI++;
1010 c--;
1011 cycles -= 15;
1012 }
1013 //if (output) printf("%i %i %i %i\n",c,(c>0),(fv==((flags&Z_FLAG)?1:0)),((c>0) && (fv==((flags&Z_FLAG)?1:0))));
1014 if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
1015 else firstrepcycle=1;
1016 // cycles-=120;
1017 break;
1018 case 0xAF: /*REP SCASW*/
1019 if (fv) flags|=Z_FLAG;
1020 else flags&=~Z_FLAG;
1021 if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
1022 {
1023 tempw=readmemw(es,DI);
1024 setsub16(AX,tempw);
1025 if (flags&D_FLAG) DI-=2;
1026 else DI+=2;
1027 c--;
1028 cycles -= 15;
1029 }
1030 if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
1031 else firstrepcycle=1;
1032 break;
1033 default:
1034 pc=ipc;
1035 cycles-=20;
1036 FETCHCLEAR();
1037 // printf("Bad REP %02X\n",temp);
1038 // dumpregs();
1039 // exit(-1);
1040 }
1041 CX=c;
1042 if (changeds) ds=oldds;
1043 if (IRQTEST)
1044 takeint = 1;
1045 // if (pc==ipc) FETCHCLEAR();
1046 }
1049 int inhlt=0;
1050 uint16_t lastpc,lastcs;
1051 int firstrepcycle;
1052 int skipnextprint=0;
1054 int instime=0;
1055 //#if 0
1056 void execx86(int cycs)
1057 {
1058 uint8_t temp,temp2;
1059 uint16_t addr,tempw,tempw2,tempw3,tempw4;
1060 int8_t offset;
1061 int tempws;
1062 uint32_t templ;
1063 int c;
1064 int tempi;
1065 int trap;
1067 // printf("Run x86! %i %i\n",cycles,cycs);
1068 cycles+=cycs;
1069 // i86_Execute(cycs);
1070 // return;
1071 while (cycles>0)
1072 {
1073 // old83=old82;
1074 // old82=old8;
1075 // old8=oldpc|(oldcs<<16);
1076 // if (pc==0x96B && cs==0x9E040) { printf("Hit it\n"); output=1; timetolive=150; }
1077 // if (pc<0x8000) printf("%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i\n",pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags,disctime);
1078 cycdiff=cycles;
1079 timer_start_period(cycles);
1080 current_diff = 0;
1081 cycles-=nextcyc;
1082 // if (instime) pclog("Cycles %i %i\n",cycles,cycdiff);
1083 nextcyc=0;
1084 // if (output) printf("CLOCK %i %i\n",cycdiff,cycles);
1085 fetchclocks=0;
1086 oldcs=CS;
1087 oldpc=pc;
1088 opcodestart:
1089 opcode=FETCH();
1090 tempc=flags&C_FLAG;
1091 trap=flags&T_FLAG;
1092 pc--;
1093 // output=1;
1094 // if (output) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X\n",cs>>4,pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags&~0x200,rmdat);
1095 //#if 0
1096 if (output)
1097 {
1098 // if ((opcode!=0xF2 && opcode!=0xF3) || firstrepcycle)
1099 // {
1100 if (!skipnextprint) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i %p %02X\n",cs,pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,flags, ins, ram, ram[0x1a925]);
1101 skipnextprint=0;
1102 // ins++;
1103 // }
1104 }
1105 //#endif
1106 pc++;
1107 inhlt=0;
1108 // if (ins==500000) { dumpregs(); exit(0); }*/
1109 switch (opcode)
1110 {
1111 case 0x00: /*ADD 8,reg*/
1112 fetchea();
1113 /* if (!rmdat) pc--;
1114 if (!rmdat)
1115 {
1116 fatal("Crashed\n");
1117 // clear_keybuf();
1118 // readkey();
1119 }*/
1120 temp=geteab();
1121 setadd8(temp,getr8(reg));
1122 temp+=getr8(reg);
1123 seteab(temp);
1124 cycles-=((mod==3)?3:24);
1125 break;
1126 case 0x01: /*ADD 16,reg*/
1127 fetchea();
1128 tempw=geteaw();
1129 setadd16(tempw,regs[reg].w);
1130 tempw+=regs[reg].w;
1131 seteaw(tempw);
1132 cycles-=((mod==3)?3:24);
1133 break;
1134 case 0x02: /*ADD reg,8*/
1135 fetchea();
1136 temp=geteab();
1137 setadd8(getr8(reg),temp);
1138 setr8(reg,getr8(reg)+temp);
1139 cycles-=((mod==3)?3:13);
1140 break;
1141 case 0x03: /*ADD reg,16*/
1142 fetchea();
1143 tempw=geteaw();
1144 setadd16(regs[reg].w,tempw);
1145 regs[reg].w+=tempw;
1146 cycles-=((mod==3)?3:13);
1147 break;
1148 case 0x04: /*ADD AL,#8*/
1149 temp=FETCH();
1150 setadd8(AL,temp);
1151 AL+=temp;
1152 cycles-=4;
1153 break;
1154 case 0x05: /*ADD AX,#16*/
1155 tempw=getword();
1156 setadd16(AX,tempw);
1157 AX+=tempw;
1158 cycles-=4;
1159 break;
1161 case 0x06: /*PUSH ES*/
1162 if (ssegs) ss=oldss;
1163 writememw(ss,((SP-2)&0xFFFF),ES);
1164 SP-=2;
1165 cycles-=14;
1166 break;
1167 case 0x07: /*POP ES*/
1168 if (ssegs) ss=oldss;
1169 tempw=readmemw(ss,SP);
1170 loadseg(tempw,&_es);
1171 SP+=2;
1172 cycles-=12;
1173 break;
1175 case 0x08: /*OR 8,reg*/
1176 fetchea();
1177 temp=geteab();
1178 temp|=getr8(reg);
1179 setznp8(temp);
1180 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1181 seteab(temp);
1182 cycles-=((mod==3)?3:24);
1183 break;
1184 case 0x09: /*OR 16,reg*/
1185 fetchea();
1186 tempw=geteaw();
1187 tempw|=regs[reg].w;
1188 setznp16(tempw);
1189 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1190 seteaw(tempw);
1191 cycles-=((mod==3)?3:24);
1192 break;
1193 case 0x0A: /*OR reg,8*/
1194 fetchea();
1195 temp=geteab();
1196 temp|=getr8(reg);
1197 setznp8(temp);
1198 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1199 setr8(reg,temp);
1200 cycles-=((mod==3)?3:13);
1201 break;
1202 case 0x0B: /*OR reg,16*/
1203 fetchea();
1204 tempw=geteaw();
1205 tempw|=regs[reg].w;
1206 setznp16(tempw);
1207 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1208 regs[reg].w=tempw;
1209 cycles-=((mod==3)?3:13);
1210 break;
1211 case 0x0C: /*OR AL,#8*/
1212 AL|=FETCH();
1213 setznp8(AL);
1214 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1215 cycles-=4;
1216 break;
1217 case 0x0D: /*OR AX,#16*/
1218 AX|=getword();
1219 setznp16(AX);
1220 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1221 cycles-=4;
1222 break;
1224 case 0x0E: /*PUSH CS*/
1225 if (ssegs) ss=oldss;
1226 writememw(ss,((SP-2)&0xFFFF),CS);
1227 SP-=2;
1228 cycles-=14;
1229 break;
1230 case 0x0F: /*POP CS - 8088/8086 only*/
1231 if (ssegs) ss=oldss;
1232 tempw=readmemw(ss,SP);
1233 loadseg(tempw,&_cs);
1234 SP+=2;
1235 cycles-=12;
1236 break;
1238 case 0x10: /*ADC 8,reg*/
1239 fetchea();
1240 temp=geteab();
1241 temp2=getr8(reg);
1242 setadc8(temp,temp2);
1243 temp+=temp2+tempc;
1244 seteab(temp);
1245 cycles-=((mod==3)?3:24);
1246 break;
1247 case 0x11: /*ADC 16,reg*/
1248 fetchea();
1249 tempw=geteaw();
1250 tempw2=regs[reg].w;
1251 setadc16(tempw,tempw2);
1252 tempw+=tempw2+tempc;
1253 seteaw(tempw);
1254 cycles-=((mod==3)?3:24);
1255 break;
1256 case 0x12: /*ADC reg,8*/
1257 fetchea();
1258 temp=geteab();
1259 setadc8(getr8(reg),temp);
1260 setr8(reg,getr8(reg)+temp+tempc);
1261 cycles-=((mod==3)?3:13);
1262 break;
1263 case 0x13: /*ADC reg,16*/
1264 fetchea();
1265 tempw=geteaw();
1266 setadc16(regs[reg].w,tempw);
1267 regs[reg].w+=tempw+tempc;
1268 cycles-=((mod==3)?3:13);
1269 break;
1270 case 0x14: /*ADC AL,#8*/
1271 tempw=FETCH();
1272 setadc8(AL,tempw);
1273 AL+=tempw+tempc;
1274 cycles-=4;
1275 break;
1276 case 0x15: /*ADC AX,#16*/
1277 tempw=getword();
1278 setadc16(AX,tempw);
1279 AX+=tempw+tempc;
1280 cycles-=4;
1281 break;
1283 case 0x16: /*PUSH SS*/
1284 if (ssegs) ss=oldss;
1285 writememw(ss,((SP-2)&0xFFFF),SS);
1286 SP-=2;
1287 cycles-=14;
1288 break;
1289 case 0x17: /*POP SS*/
1290 if (ssegs) ss=oldss;
1291 tempw=readmemw(ss,SP);
1292 loadseg(tempw,&_ss);
1293 SP+=2;
1294 noint=1;
1295 cycles-=12;
1296 // output=1;
1297 break;
1299 case 0x18: /*SBB 8,reg*/
1300 fetchea();
1301 temp=geteab();
1302 temp2=getr8(reg);
1303 setsbc8(temp,temp2);
1304 temp-=(temp2+tempc);
1305 seteab(temp);
1306 cycles-=((mod==3)?3:24);
1307 break;
1308 case 0x19: /*SBB 16,reg*/
1309 fetchea();
1310 tempw=geteaw();
1311 tempw2=regs[reg].w;
1312 // printf("%04X:%04X SBB %04X-%04X,%i\n",cs>>4,pc,tempw,tempw2,tempc);
1313 setsbc16(tempw,tempw2);
1314 tempw-=(tempw2+tempc);
1315 seteaw(tempw);
1316 cycles-=((mod==3)?3:24);
1317 break;
1318 case 0x1A: /*SBB reg,8*/
1319 fetchea();
1320 temp=geteab();
1321 setsbc8(getr8(reg),temp);
1322 setr8(reg,getr8(reg)-(temp+tempc));
1323 cycles-=((mod==3)?3:13);
1324 break;
1325 case 0x1B: /*SBB reg,16*/
1326 fetchea();
1327 tempw=geteaw();
1328 tempw2=regs[reg].w;
1329 // printf("%04X:%04X SBB %04X-%04X,%i\n",cs>>4,pc,tempw,tempw2,tempc);
1330 setsbc16(tempw2,tempw);
1331 tempw2-=(tempw+tempc);
1332 regs[reg].w=tempw2;
1333 cycles-=((mod==3)?3:13);
1334 break;
1335 case 0x1C: /*SBB AL,#8*/
1336 temp=FETCH();
1337 setsbc8(AL,temp);
1338 AL-=(temp+tempc);
1339 cycles-=4;
1340 break;
1341 case 0x1D: /*SBB AX,#16*/
1342 tempw=getword();
1343 setsbc16(AX,tempw);
1344 AX-=(tempw+tempc);
1345 cycles-=4;
1346 break;
1348 case 0x1E: /*PUSH DS*/
1349 if (ssegs) ss=oldss;
1350 writememw(ss,((SP-2)&0xFFFF),DS);
1351 SP-=2;
1352 cycles-=14;
1353 break;
1354 case 0x1F: /*POP DS*/
1355 if (ssegs) ss=oldss;
1356 tempw=readmemw(ss,SP);
1357 loadseg(tempw,&_ds);
1358 if (ssegs) oldds=ds;
1359 SP+=2;
1360 cycles-=12;
1361 break;
1363 case 0x20: /*AND 8,reg*/
1364 fetchea();
1365 temp=geteab();
1366 temp&=getr8(reg);
1367 setznp8(temp);
1368 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1369 seteab(temp);
1370 cycles-=((mod==3)?3:24);
1371 break;
1372 case 0x21: /*AND 16,reg*/
1373 fetchea();
1374 tempw=geteaw();
1375 tempw&=regs[reg].w;
1376 setznp16(tempw);
1377 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1378 seteaw(tempw);
1379 cycles-=((mod==3)?3:24);
1380 break;
1381 case 0x22: /*AND reg,8*/
1382 fetchea();
1383 temp=geteab();
1384 temp&=getr8(reg);
1385 setznp8(temp);
1386 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1387 setr8(reg,temp);
1388 cycles-=((mod==3)?3:13);
1389 break;
1390 case 0x23: /*AND reg,16*/
1391 fetchea();
1392 tempw=geteaw();
1393 tempw&=regs[reg].w;
1394 setznp16(tempw);
1395 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1396 regs[reg].w=tempw;
1397 cycles-=((mod==3)?3:13);
1398 break;
1399 case 0x24: /*AND AL,#8*/
1400 AL&=FETCH();
1401 setznp8(AL);
1402 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1403 cycles-=4;
1404 break;
1405 case 0x25: /*AND AX,#16*/
1406 AX&=getword();
1407 setznp16(AX);
1408 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1409 cycles-=4;
1410 break;
1412 case 0x26: /*ES:*/
1413 oldss=ss;
1414 oldds=ds;
1415 ds=ss=es;
1416 ssegs=2;
1417 cycles-=4;
1418 goto opcodestart;
1419 // break;
1421 case 0x27: /*DAA*/
1422 if ((flags&A_FLAG) || ((AL&0xF)>9))
1423 {
1424 tempi=((uint16_t)AL)+6;
1425 AL+=6;
1426 flags|=A_FLAG;
1427 if (tempi&0x100) flags|=C_FLAG;
1428 }
1429 // else
1430 // flags&=~A_FLAG;
1431 if ((flags&C_FLAG) || (AL>0x9F))
1432 {
1433 AL+=0x60;
1434 flags|=C_FLAG;
1435 }
1436 // else
1437 // flags&=~C_FLAG;
1438 setznp8(AL);
1439 cycles-=4;
1440 break;
1442 case 0x28: /*SUB 8,reg*/
1443 fetchea();
1444 temp=geteab();
1445 setsub8(temp,getr8(reg));
1446 temp-=getr8(reg);
1447 seteab(temp);
1448 cycles-=((mod==3)?3:24);
1449 break;
1450 case 0x29: /*SUB 16,reg*/
1451 fetchea();
1452 tempw=geteaw();
1453 // printf("%04X:%04X %04X-%04X\n",cs>>4,pc,tempw,regs[reg].w);
1454 setsub16(tempw,regs[reg].w);
1455 tempw-=regs[reg].w;
1456 seteaw(tempw);
1457 cycles-=((mod==3)?3:24);
1458 break;
1459 case 0x2A: /*SUB reg,8*/
1460 fetchea();
1461 temp=geteab();
1462 setsub8(getr8(reg),temp);
1463 setr8(reg,getr8(reg)-temp);
1464 cycles-=((mod==3)?3:13);
1465 break;
1466 case 0x2B: /*SUB reg,16*/
1467 fetchea();
1468 tempw=geteaw();
1469 // printf("%04X:%04X %04X-%04X\n",cs>>4,pc,regs[reg].w,tempw);
1470 setsub16(regs[reg].w,tempw);
1471 regs[reg].w-=tempw;
1472 cycles-=((mod==3)?3:13);
1473 break;
1474 case 0x2C: /*SUB AL,#8*/
1475 temp=FETCH();
1476 setsub8(AL,temp);
1477 AL-=temp;
1478 cycles-=4;
1479 break;
1480 case 0x2D: /*SUB AX,#16*/
1481 // printf("INS %i\n",ins);
1482 // output=1;
1483 tempw=getword();
1484 setsub16(AX,tempw);
1485 AX-=tempw;
1486 cycles-=4;
1487 break;
1488 case 0x2E: /*CS:*/
1489 oldss=ss;
1490 oldds=ds;
1491 ds=ss=cs;
1492 ssegs=2;
1493 cycles-=4;
1494 goto opcodestart;
1495 case 0x2F: /*DAS*/
1496 if ((flags&A_FLAG)||((AL&0xF)>9))
1497 {
1498 tempi=((uint16_t)AL)-6;
1499 AL-=6;
1500 flags|=A_FLAG;
1501 if (tempi&0x100) flags|=C_FLAG;
1502 }
1503 // else
1504 // flags&=~A_FLAG;
1505 if ((flags&C_FLAG)||(AL>0x9F))
1506 {
1507 AL-=0x60;
1508 flags|=C_FLAG;
1509 }
1510 // else
1511 // flags&=~C_FLAG;
1512 setznp8(AL);
1513 cycles-=4;
1514 break;
1515 case 0x30: /*XOR 8,reg*/
1516 fetchea();
1517 temp=geteab();
1518 temp^=getr8(reg);
1519 setznp8(temp);
1520 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1521 seteab(temp);
1522 cycles-=((mod==3)?3:24);
1523 break;
1524 case 0x31: /*XOR 16,reg*/
1525 fetchea();
1526 tempw=geteaw();
1527 tempw^=regs[reg].w;
1528 setznp16(tempw);
1529 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1530 seteaw(tempw);
1531 cycles-=((mod==3)?3:24);
1532 break;
1533 case 0x32: /*XOR reg,8*/
1534 fetchea();
1535 temp=geteab();
1536 temp^=getr8(reg);
1537 setznp8(temp);
1538 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1539 setr8(reg,temp);
1540 cycles-=((mod==3)?3:13);
1541 break;
1542 case 0x33: /*XOR reg,16*/
1543 fetchea();
1544 tempw=geteaw();
1545 tempw^=regs[reg].w;
1546 setznp16(tempw);
1547 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1548 regs[reg].w=tempw;
1549 cycles-=((mod==3)?3:13);
1550 break;
1551 case 0x34: /*XOR AL,#8*/
1552 AL^=FETCH();
1553 setznp8(AL);
1554 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1555 cycles-=4;
1556 break;
1557 case 0x35: /*XOR AX,#16*/
1558 AX^=getword();
1559 setznp16(AX);
1560 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1561 cycles-=4;
1562 break;
1564 case 0x36: /*SS:*/
1565 oldss=ss;
1566 oldds=ds;
1567 ds=ss=ss;
1568 ssegs=2;
1569 cycles-=4;
1570 goto opcodestart;
1571 // break;
1573 case 0x37: /*AAA*/
1574 if ((flags&A_FLAG)||((AL&0xF)>9))
1575 {
1576 AL+=6;
1577 AH++;
1578 flags|=(A_FLAG|C_FLAG);
1579 }
1580 else
1581 flags&=~(A_FLAG|C_FLAG);
1582 AL&=0xF;
1583 cycles-=8;
1584 break;
1586 case 0x38: /*CMP 8,reg*/
1587 fetchea();
1588 temp=geteab();
1589 // if (output) printf("CMP %02X-%02X\n",temp,getr8(reg));
1590 setsub8(temp,getr8(reg));
1591 cycles-=((mod==3)?3:13);
1592 break;
1593 case 0x39: /*CMP 16,reg*/
1594 fetchea();
1595 tempw=geteaw();
1596 // if (output) printf("CMP %04X-%04X\n",tempw,regs[reg].w);
1597 setsub16(tempw,regs[reg].w);
1598 cycles-=((mod==3)?3:13);
1599 break;
1600 case 0x3A: /*CMP reg,8*/
1601 fetchea();
1602 temp=geteab();
1603 // if (output) printf("CMP %02X-%02X\n",getr8(reg),temp);
1604 setsub8(getr8(reg),temp);
1605 cycles-=((mod==3)?3:13);
1606 break;
1607 case 0x3B: /*CMP reg,16*/
1608 fetchea();
1609 tempw=geteaw();
1610 // printf("CMP %04X-%04X\n",regs[reg].w,tempw);
1611 setsub16(regs[reg].w,tempw);
1612 cycles-=((mod==3)?3:13);
1613 break;
1614 case 0x3C: /*CMP AL,#8*/
1615 temp=FETCH();
1616 setsub8(AL,temp);
1617 cycles-=4;
1618 break;
1619 case 0x3D: /*CMP AX,#16*/
1620 tempw=getword();
1621 setsub16(AX,tempw);
1622 cycles-=4;
1623 break;
1625 case 0x3E: /*DS:*/
1626 oldss=ss;
1627 oldds=ds;
1628 ds=ss=ds;
1629 ssegs=2;
1630 cycles-=4;
1631 goto opcodestart;
1632 // break;
1634 case 0x3F: /*AAS*/
1635 if ((flags&A_FLAG)||((AL&0xF)>9))
1636 {
1637 AL-=6;
1638 AH--;
1639 flags|=(A_FLAG|C_FLAG);
1640 }
1641 else
1642 flags&=~(A_FLAG|C_FLAG);
1643 AL&=0xF;
1644 cycles-=8;
1645 break;
1647 case 0x40: case 0x41: case 0x42: case 0x43: /*INC r16*/
1648 case 0x44: case 0x45: case 0x46: case 0x47:
1649 setadd16nc(regs[opcode&7].w,1);
1650 regs[opcode&7].w++;
1651 cycles-=3;
1652 break;
1653 case 0x48: case 0x49: case 0x4A: case 0x4B: /*DEC r16*/
1654 case 0x4C: case 0x4D: case 0x4E: case 0x4F:
1655 setsub16nc(regs[opcode&7].w,1);
1656 regs[opcode&7].w--;
1657 cycles-=3;
1658 break;
1660 case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/
1661 case 0x54: case 0x55: case 0x56: case 0x57:
1662 if (ssegs) ss=oldss;
1663 SP-=2;
1664 writememw(ss,SP,regs[opcode&7].w);
1665 cycles-=15;
1666 break;
1667 case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/
1668 case 0x5C: case 0x5D: case 0x5E: case 0x5F:
1669 if (ssegs) ss=oldss;
1670 SP+=2;
1671 regs[opcode&7].w=readmemw(ss,(SP-2)&0xFFFF);
1672 cycles-=12;
1673 break;
1676 case 0x70: /*JO*/
1677 offset=(int8_t)FETCH();
1678 if (flags&V_FLAG) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1679 cycles-=4;
1680 break;
1681 case 0x71: /*JNO*/
1682 offset=(int8_t)FETCH();
1683 if (!(flags&V_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1684 cycles-=4;
1685 break;
1686 case 0x72: /*JB*/
1687 offset=(int8_t)FETCH();
1688 if (flags&C_FLAG) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1689 cycles-=4;
1690 break;
1691 case 0x73: /*JNB*/
1692 offset=(int8_t)FETCH();
1693 if (!(flags&C_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1694 cycles-=4;
1695 break;
1696 case 0x74: /*JE*/
1697 offset=(int8_t)FETCH();
1698 if (flags&Z_FLAG) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1699 cycles-=4;
1700 break;
1701 case 0x75: /*JNE*/
1702 offset=(int8_t)FETCH();
1703 cycles-=4;
1704 if (!(flags&Z_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1705 break;
1706 case 0x76: /*JBE*/
1707 offset=(int8_t)FETCH();
1708 if (flags&(C_FLAG|Z_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1709 cycles-=4;
1710 break;
1711 case 0x77: /*JNBE*/
1712 offset=(int8_t)FETCH();
1713 if (!(flags&(C_FLAG|Z_FLAG))) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1714 cycles-=4;
1715 break;
1716 case 0x78: /*JS*/
1717 offset=(int8_t)FETCH();
1718 if (flags&N_FLAG) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1719 cycles-=4;
1720 break;
1721 case 0x79: /*JNS*/
1722 offset=(int8_t)FETCH();
1723 if (!(flags&N_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1724 cycles-=4;
1725 break;
1726 case 0x7A: /*JP*/
1727 offset=(int8_t)FETCH();
1728 if (flags&P_FLAG) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1729 cycles-=4;
1730 break;
1731 case 0x7B: /*JNP*/
1732 offset=(int8_t)FETCH();
1733 if (!(flags&P_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1734 cycles-=4;
1735 break;
1736 case 0x7C: /*JL*/
1737 offset=(int8_t)FETCH();
1738 temp=(flags&N_FLAG)?1:0;
1739 temp2=(flags&V_FLAG)?1:0;
1740 if (temp!=temp2) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1741 cycles-=4;
1742 break;
1743 case 0x7D: /*JNL*/
1744 offset=(int8_t)FETCH();
1745 temp=(flags&N_FLAG)?1:0;
1746 temp2=(flags&V_FLAG)?1:0;
1747 if (temp==temp2) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1748 cycles-=4;
1749 break;
1750 case 0x7E: /*JLE*/
1751 offset=(int8_t)FETCH();
1752 temp=(flags&N_FLAG)?1:0;
1753 temp2=(flags&V_FLAG)?1:0;
1754 if ((flags&Z_FLAG) || (temp!=temp2)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1755 cycles-=4;
1756 break;
1757 case 0x7F: /*JNLE*/
1758 offset=(int8_t)FETCH();
1759 temp=(flags&N_FLAG)?1:0;
1760 temp2=(flags&V_FLAG)?1:0;
1761 if (!((flags&Z_FLAG) || (temp!=temp2))) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1762 cycles-=4;
1763 break;
1765 case 0x80: case 0x82:
1766 fetchea();
1767 temp=geteab();
1768 temp2=FETCH();
1769 switch (rmdat&0x38)
1770 {
1771 case 0x00: /*ADD b,#8*/
1772 setadd8(temp,temp2);
1773 seteab(temp+temp2);
1774 cycles-=((mod==3)?4:23);
1775 break;
1776 case 0x08: /*OR b,#8*/
1777 temp|=temp2;
1778 setznp8(temp);
1779 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1780 seteab(temp);
1781 cycles-=((mod==3)?4:23);
1782 break;
1783 case 0x10: /*ADC b,#8*/
1784 // temp2+=(flags&C_FLAG);
1785 setadc8(temp,temp2);
1786 seteab(temp+temp2+tempc);
1787 cycles-=((mod==3)?4:23);
1788 break;
1789 case 0x18: /*SBB b,#8*/
1790 // temp2+=(flags&C_FLAG);
1791 setsbc8(temp,temp2);
1792 seteab(temp-(temp2+tempc));
1793 cycles-=((mod==3)?4:23);
1794 break;
1795 case 0x20: /*AND b,#8*/
1796 temp&=temp2;
1797 setznp8(temp);
1798 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1799 seteab(temp);
1800 cycles-=((mod==3)?4:23);
1801 break;
1802 case 0x28: /*SUB b,#8*/
1803 setsub8(temp,temp2);
1804 seteab(temp-temp2);
1805 cycles-=((mod==3)?4:23);
1806 break;
1807 case 0x30: /*XOR b,#8*/
1808 temp^=temp2;
1809 setznp8(temp);
1810 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1811 seteab(temp);
1812 cycles-=((mod==3)?4:23);
1813 break;
1814 case 0x38: /*CMP b,#8*/
1815 setsub8(temp,temp2);
1816 cycles-=((mod==3)?4:14);
1817 break;
1819 // default:
1820 // printf("Bad 80 opcode %02X\n",rmdat&0x38);
1821 // dumpregs();
1822 // exit(-1);
1823 }
1824 break;
1826 case 0x81:
1827 fetchea();
1828 tempw=geteaw();
1829 tempw2=getword();
1830 switch (rmdat&0x38)
1831 {
1832 case 0x00: /*ADD w,#16*/
1833 setadd16(tempw,tempw2);
1834 tempw+=tempw2;
1835 seteaw(tempw);
1836 cycles-=((mod==3)?4:23);
1837 break;
1838 case 0x08: /*OR w,#16*/
1839 tempw|=tempw2;
1840 setznp16(tempw);
1841 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1842 seteaw(tempw);
1843 cycles-=((mod==3)?4:23);
1844 break;
1845 case 0x10: /*ADC w,#16*/
1846 // tempw2+=(flags&C_FLAG);
1847 setadc16(tempw,tempw2);
1848 tempw+=tempw2+tempc;
1849 seteaw(tempw);
1850 cycles-=((mod==3)?4:23);
1851 break;
1852 case 0x20: /*AND w,#16*/
1853 tempw&=tempw2;
1854 setznp16(tempw);
1855 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1856 seteaw(tempw);
1857 cycles-=((mod==3)?4:23);
1858 break;
1859 case 0x18: /*SBB w,#16*/
1860 // tempw2+=(flags&C_FLAG);
1861 setsbc16(tempw,tempw2);
1862 seteaw(tempw-(tempw2+tempc));
1863 cycles-=((mod==3)?4:23);
1864 break;
1865 case 0x28: /*SUB w,#16*/
1866 setsub16(tempw,tempw2);
1867 tempw-=tempw2;
1868 seteaw(tempw);
1869 cycles-=((mod==3)?4:23);
1870 break;
1871 case 0x30: /*XOR w,#16*/
1872 tempw^=tempw2;
1873 setznp16(tempw);
1874 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1875 seteaw(tempw);
1876 cycles-=((mod==3)?4:23);
1877 break;
1878 case 0x38: /*CMP w,#16*/
1879 // printf("CMP %04X %04X\n",tempw,tempw2);
1880 setsub16(tempw,tempw2);
1881 cycles-=((mod==3)?4:14);
1882 break;
1884 // default:
1885 // printf("Bad 81 opcode %02X\n",rmdat&0x38);
1886 // dumpregs();
1887 // exit(-1);
1888 }
1889 break;
1891 case 0x83:
1892 fetchea();
1893 tempw=geteaw();
1894 tempw2=FETCH();
1895 if (tempw2&0x80) tempw2|=0xFF00;
1896 switch (rmdat&0x38)
1897 {
1898 case 0x00: /*ADD w,#8*/
1899 setadd16(tempw,tempw2);
1900 tempw+=tempw2;
1901 seteaw(tempw);
1902 cycles-=((mod==3)?4:23);
1903 break;
1904 case 0x08: /*OR w,#8*/
1905 tempw|=tempw2;
1906 setznp16(tempw);
1907 seteaw(tempw);
1908 flags&=~(C_FLAG|A_FLAG|V_FLAG);
1909 cycles-=((mod==3)?4:23);
1910 break;
1911 case 0x10: /*ADC w,#8*/
1912 // tempw2+=(flags&C_FLAG);
1913 setadc16(tempw,tempw2);
1914 tempw+=tempw2+tempc;
1915 seteaw(tempw);
1916 cycles-=((mod==3)?4:23);
1917 break;
1918 case 0x18: /*SBB w,#8*/
1919 // tempw2+=(flags&C_FLAG);
1920 setsbc16(tempw,tempw2);
1921 tempw-=(tempw2+tempc);
1922 seteaw(tempw);
1923 cycles-=((mod==3)?4:23);
1924 break;
1925 case 0x20: /*AND w,#8*/
1926 tempw&=tempw2;
1927 setznp16(tempw);
1928 seteaw(tempw);
1929 cycles-=((mod==3)?4:23);
1930 flags&=~(C_FLAG|A_FLAG|V_FLAG);
1931 break;
1932 case 0x28: /*SUB w,#8*/
1933 setsub16(tempw,tempw2);
1934 tempw-=tempw2;
1935 seteaw(tempw);
1936 cycles-=((mod==3)?4:23);
1937 break;
1938 case 0x30: /*XOR w,#8*/
1939 tempw^=tempw2;
1940 setznp16(tempw);
1941 seteaw(tempw);
1942 cycles-=((mod==3)?4:23);
1943 flags&=~(C_FLAG|A_FLAG|V_FLAG);
1944 break;
1945 case 0x38: /*CMP w,#8*/
1946 setsub16(tempw,tempw2);
1947 cycles-=((mod==3)?4:14);
1948 break;
1950 // default:
1951 // printf("Bad 83 opcode %02X\n",rmdat&0x38);
1952 // dumpregs();
1953 // exit(-1);
1954 }
1955 break;
1957 case 0x84: /*TEST b,reg*/
1958 fetchea();
1959 temp=geteab();
1960 temp2=getr8(reg);
1961 setznp8(temp&temp2);
1962 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1963 cycles-=((mod==3)?3:13);
1964 break;
1965 case 0x85: /*TEST w,reg*/
1966 fetchea();
1967 tempw=geteaw();
1968 tempw2=regs[reg].w;
1969 setznp16(tempw&tempw2);
1970 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1971 cycles-=((mod==3)?3:13);
1972 break;
1973 case 0x86: /*XCHG b,reg*/
1974 fetchea();
1975 temp=geteab();
1976 seteab(getr8(reg));
1977 setr8(reg,temp);
1978 cycles-=((mod==3)?4:25);
1979 break;
1980 case 0x87: /*XCHG w,reg*/
1981 fetchea();
1982 tempw=geteaw();
1983 seteaw(regs[reg].w);
1984 regs[reg].w=tempw;
1985 cycles-=((mod==3)?4:25);
1986 break;
1988 case 0x88: /*MOV b,reg*/
1989 fetchea();
1990 seteab(getr8(reg));
1991 cycles-=((mod==3)?2:13);
1992 break;
1993 case 0x89: /*MOV w,reg*/
1994 fetchea();
1995 seteaw(regs[reg].w);
1996 cycles-=((mod==3)?2:13);
1997 break;
1998 case 0x8A: /*MOV reg,b*/
1999 fetchea();
2000 temp=geteab();
2001 setr8(reg,temp);
2002 cycles-=((mod==3)?2:12);
2003 break;
2004 case 0x8B: /*MOV reg,w*/
2005 fetchea();
2006 tempw=geteaw();
2007 regs[reg].w=tempw;
2008 cycles-=((mod==3)?2:12);
2009 break;
2011 case 0x8C: /*MOV w,sreg*/
2012 fetchea();
2013 switch (rmdat&0x38)
2014 {
2015 case 0x00: /*ES*/
2016 seteaw(ES);
2017 break;
2018 case 0x08: /*CS*/
2019 seteaw(CS);
2020 break;
2021 case 0x18: /*DS*/
2022 if (ssegs) ds=oldds;
2023 seteaw(DS);
2024 break;
2025 case 0x10: /*SS*/
2026 if (ssegs) ss=oldss;
2027 seteaw(SS);
2028 break;
2029 }
2030 cycles-=((mod==3)?2:13);
2031 break;
2033 case 0x8D: /*LEA*/
2034 fetchea();
2035 regs[reg].w=eaaddr;
2036 cycles-=2;
2037 break;
2039 case 0x8E: /*MOV sreg,w*/
2040 // if (output) printf("MOV %04X ",pc);
2041 fetchea();
2042 // if (output) printf("%04X %02X\n",pc,rmdat);
2043 switch (rmdat&0x38)
2044 {
2045 case 0x00: /*ES*/
2046 tempw=geteaw();
2047 loadseg(tempw,&_es);
2048 break;
2049 case 0x08: /*CS - 8088/8086 only*/
2050 tempw=geteaw();
2051 loadseg(tempw,&_cs);
2052 break;
2053 case 0x18: /*DS*/
2054 tempw=geteaw();
2055 loadseg(tempw,&_ds);
2056 if (ssegs) oldds=ds;
2057 break;
2058 case 0x10: /*SS*/
2059 tempw=geteaw();
2060 loadseg(tempw,&_ss);
2061 if (ssegs) oldss=ss;
2062 // printf("LOAD SS %04X %04X\n",tempw,SS);
2063 // printf("SS loaded with %04X %04X:%04X %04X %04X %04X\n",ss>>4,cs>>4,pc,CX,DX,es>>4);
2064 break;
2065 }
2066 cycles-=((mod==3)?2:12);
2067 skipnextprint=1;
2068 noint=1;
2069 break;
2071 case 0x8F: /*POPW*/
2072 fetchea();
2073 if (ssegs) ss=oldss;
2074 tempw=readmemw(ss,SP);
2075 SP+=2;
2076 seteaw(tempw);
2077 cycles-=25;
2078 break;
2080 case 0x90: /*NOP*/
2081 cycles-=3;
2082 break;
2084 case 0x91: case 0x92: case 0x93: /*XCHG AX*/
2085 case 0x94: case 0x95: case 0x96: case 0x97:
2086 tempw=AX;
2087 AX=regs[opcode&7].w;
2088 regs[opcode&7].w=tempw;
2089 cycles-=3;
2090 break;
2092 case 0x98: /*CBW*/
2093 AH=(AL&0x80)?0xFF:0;
2094 cycles-=2;
2095 break;
2096 case 0x99: /*CWD*/
2097 DX=(AX&0x8000)?0xFFFF:0;
2098 cycles-=5;
2099 break;
2100 case 0x9A: /*CALL FAR*/
2101 tempw=getword();
2102 tempw2=getword();
2103 tempw3=CS;
2104 tempw4=pc;
2105 if (ssegs) ss=oldss;
2106 pc=tempw;
2107 // printf("0x9a");
2108 loadcs(tempw2);
2109 writememw(ss,(SP-2)&0xFFFF,tempw3);
2110 writememw(ss,(SP-4)&0xFFFF,tempw4);
2111 SP-=4;
2112 cycles-=36;
2113 FETCHCLEAR();
2114 break;
2115 case 0x9B: /*WAIT*/
2116 cycles-=4;
2117 break;
2118 case 0x9C: /*PUSHF*/
2119 if (ssegs) ss=oldss;
2120 writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
2121 SP-=2;
2122 cycles-=14;
2123 break;
2124 case 0x9D: /*POPF*/
2125 if (ssegs) ss=oldss;
2126 flags=readmemw(ss,SP)&0xFFF;
2127 SP+=2;
2128 cycles-=12;
2129 break;
2130 case 0x9E: /*SAHF*/
2131 flags=(flags&0xFF00)|AH;
2132 cycles-=4;
2133 break;
2134 case 0x9F: /*LAHF*/
2135 AH=flags&0xFF;
2136 cycles-=4;
2137 break;
2139 case 0xA0: /*MOV AL,(w)*/
2140 addr=getword();
2141 AL=readmemb(ds+addr);
2142 cycles-=14;
2143 break;
2144 case 0xA1: /*MOV AX,(w)*/
2145 addr=getword();
2146 // printf("Reading AX from %05X %04X:%04X\n",ds+addr,ds>>4,addr);
2147 AX=readmemw(ds,addr);
2148 cycles-=!4;
2149 break;
2150 case 0xA2: /*MOV (w),AL*/
2151 addr=getword();
2152 writememb(ds+addr,AL);
2153 cycles-=14;
2154 break;
2155 case 0xA3: /*MOV (w),AX*/
2156 addr=getword();
2157 // if (!addr) printf("Write !addr %04X:%04X\n",cs>>4,pc);
2158 writememw(ds,addr,AX);
2159 cycles-=14;
2160 break;
2162 case 0xA4: /*MOVSB*/
2163 temp=readmemb(ds+SI);
2164 writememb(es+DI,temp);
2165 if (flags&D_FLAG) { DI--; SI--; }
2166 else { DI++; SI++; }
2167 cycles-=18;
2168 break;
2169 case 0xA5: /*MOVSW*/
2170 tempw=readmemw(ds,SI);
2171 writememw(es,DI,tempw);
2172 if (flags&D_FLAG) { DI-=2; SI-=2; }
2173 else { DI+=2; SI+=2; }
2174 cycles-=18;
2175 break;
2176 case 0xA6: /*CMPSB*/
2177 temp =readmemb(ds+SI);
2178 temp2=readmemb(es+DI);
2179 setsub8(temp,temp2);
2180 if (flags&D_FLAG) { DI--; SI--; }
2181 else { DI++; SI++; }
2182 cycles-=30;
2183 break;
2184 case 0xA7: /*CMPSW*/
2185 tempw =readmemw(ds,SI);
2186 tempw2=readmemw(es,DI);
2187 // printf("CMPSW %04X %04X\n",tempw,tempw2);
2188 setsub16(tempw,tempw2);
2189 if (flags&D_FLAG) { DI-=2; SI-=2; }
2190 else { DI+=2; SI+=2; }
2191 cycles-=30;
2192 break;
2193 case 0xA8: /*TEST AL,#8*/
2194 temp=FETCH();
2195 setznp8(AL&temp);
2196 flags&=~(C_FLAG|V_FLAG|A_FLAG);
2197 cycles-=5;
2198 break;
2199 case 0xA9: /*TEST AX,#16*/
2200 tempw=getword();
2201 setznp16(AX&tempw);
2202 flags&=~(C_FLAG|V_FLAG|A_FLAG);
2203 cycles-=5;
2204 break;
2205 case 0xAA: /*STOSB*/
2206 writememb(es+DI,AL);
2207 if (flags&D_FLAG) DI--;
2208 else DI++;
2209 cycles-=11;
2210 break;
2211 case 0xAB: /*STOSW*/
2212 writememw(es,DI,AX);
2213 if (flags&D_FLAG) DI-=2;
2214 else DI+=2;
2215 cycles-=11;
2216 break;
2217 case 0xAC: /*LODSB*/
2218 AL=readmemb(ds+SI);
2219 // printf("LODSB %04X:%04X %02X %04X:%04X\n",cs>>4,pc,AL,ds>>4,SI);
2220 if (flags&D_FLAG) SI--;
2221 else SI++;
2222 cycles-=16;
2223 break;
2224 case 0xAD: /*LODSW*/
2225 // if (times) printf("LODSW %04X:%04X\n",cs>>4,pc);
2226 AX=readmemw(ds,SI);
2227 if (flags&D_FLAG) SI-=2;
2228 else SI+=2;
2229 cycles-=16;
2230 break;
2231 case 0xAE: /*SCASB*/
2232 temp=readmemb(es+DI);
2233 setsub8(AL,temp);
2234 if (flags&D_FLAG) DI--;
2235 else DI++;
2236 cycles-=19;
2237 break;
2238 case 0xAF: /*SCASW*/
2239 tempw=readmemw(es,DI);
2240 setsub16(AX,tempw);
2241 if (flags&D_FLAG) DI-=2;
2242 else DI+=2;
2243 cycles-=19;
2244 break;
2246 case 0xB0: /*MOV AL,#8*/
2247 AL=FETCH();
2248 cycles-=4;
2249 break;
2250 case 0xB1: /*MOV CL,#8*/
2251 CL=FETCH();
2252 cycles-=4;
2253 break;
2254 case 0xB2: /*MOV DL,#8*/
2255 DL=FETCH();
2256 cycles-=4;
2257 break;
2258 case 0xB3: /*MOV BL,#8*/
2259 BL=FETCH();
2260 cycles-=4;
2261 break;
2262 case 0xB4: /*MOV AH,#8*/
2263 AH=FETCH();
2264 cycles-=4;
2265 break;
2266 case 0xB5: /*MOV CH,#8*/
2267 CH=FETCH();
2268 cycles-=4;
2269 break;
2270 case 0xB6: /*MOV DH,#8*/
2271 DH=FETCH();
2272 cycles-=4;
2273 break;
2274 case 0xB7: /*MOV BH,#8*/
2275 BH=FETCH();
2276 cycles-=4;
2277 break;
2278 case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV reg,#16*/
2279 case 0xBC: case 0xBD: case 0xBE: case 0xBF:
2280 regs[opcode&7].w=getword();
2281 cycles-=4;
2282 break;
2284 case 0xC2: /*RET*/
2285 tempw=getword();
2286 if (ssegs) ss=oldss;
2287 pc=readmemw(ss,SP);
2288 // printf("C2\n");
2289 // printf("RET to %04X\n",pc);
2290 SP+=2+tempw;
2291 cycles-=24;
2292 FETCHCLEAR();
2293 break;
2294 case 0xC3: /*RET*/
2295 if (ssegs) ss=oldss;
2296 pc=readmemw(ss,SP);
2297 // printf("C3\n");
2298 // if (output) printf("RET to %04X %05X\n",pc,ss+SP);
2299 SP+=2;
2300 cycles-=20;
2301 FETCHCLEAR();
2302 break;
2303 case 0xC4: /*LES*/
2304 fetchea();
2305 regs[reg].w=readmemw(easeg,eaaddr); //geteaw();
2306 tempw=readmemw(easeg,(eaaddr+2)&0xFFFF); //geteaw2();
2307 loadseg(tempw,&_es);
2308 cycles-=24;
2309 break;
2310 case 0xC5: /*LDS*/
2311 fetchea();
2312 regs[reg].w=readmemw(easeg,eaaddr);
2313 tempw=readmemw(easeg,(eaaddr+2)&0xFFFF);
2314 loadseg(tempw,&_ds);
2315 if (ssegs) oldds=ds;
2316 cycles-=24;
2317 break;
2318 case 0xC6: /*MOV b,#8*/
2319 fetchea();
2320 temp=FETCH();
2321 seteab(temp);
2322 cycles-=((mod==3)?4:14);
2323 break;
2324 case 0xC7: /*MOV w,#16*/
2325 fetchea();
2326 tempw=getword();
2327 seteaw(tempw);
2328 cycles-=((mod==3)?4:14);
2329 break;
2331 case 0xCA: /*RETF*/
2332 tempw=getword();
2333 if (ssegs) ss=oldss;
2334 pc=readmemw(ss,SP);
2335 // printf("CA\n");
2336 loadcs(readmemw(ss,SP+2));
2337 SP+=4;
2338 SP+=tempw;
2339 cycles-=33;
2340 FETCHCLEAR();
2341 break;
2342 case 0xCB: /*RETF*/
2343 if (ssegs) ss=oldss;
2344 pc=readmemw(ss,SP);
2345 // printf("CB\n");
2346 loadcs(readmemw(ss,SP+2));
2347 SP+=4;
2348 cycles-=34;
2349 FETCHCLEAR();
2350 break;
2351 case 0xCC: /*INT 3*/
2352 if (ssegs) ss=oldss;
2353 writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
2354 writememw(ss,((SP-4)&0xFFFF),CS);
2355 writememw(ss,((SP-6)&0xFFFF),pc);
2356 SP-=6;
2357 addr=3<<2;
2358 flags&=~I_FLAG;
2359 flags&=~T_FLAG;
2360 // printf("CC %04X:%04X ",CS,pc);
2361 pc=readmemw(0,addr);
2362 loadcs(readmemw(0,addr+2));
2363 FETCHCLEAR();
2364 // printf("%04X:%04X\n",CS,pc);
2365 cycles-=72;
2366 break;
2367 case 0xCD: /*INT*/
2368 lastpc=pc;
2369 lastcs=CS;
2370 temp=FETCH();
2372 if (ssegs) ss=oldss;
2373 writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
2374 writememw(ss,((SP-4)&0xFFFF),CS);
2375 writememw(ss,((SP-6)&0xFFFF),pc);
2376 flags&=~T_FLAG;
2377 SP-=6;
2378 addr=temp<<2;
2379 pc=readmemw(0,addr);
2381 loadcs(readmemw(0,addr+2));
2382 FETCHCLEAR();
2384 cycles-=71;
2385 break;
2386 case 0xCF: /*IRET*/
2387 if (ssegs) ss=oldss;
2388 tempw=CS;
2389 tempw2=pc;
2390 pc=readmemw(ss,SP);
2391 // printf("CF\n");
2392 loadcs(readmemw(ss,((SP+2)&0xFFFF)));
2393 flags=readmemw(ss,((SP+4)&0xFFFF))&0xFFF;
2394 SP+=6;
2395 cycles-=44;
2396 FETCHCLEAR();
2397 nmi_enable = 1;
2398 break;
2399 case 0xD0:
2400 fetchea();
2401 temp=geteab();
2402 switch (rmdat&0x38)
2403 {
2404 case 0x00: /*ROL b,1*/
2405 if (temp&0x80) flags|=C_FLAG;
2406 else flags&=~C_FLAG;
2407 temp<<=1;
2408 if (flags&C_FLAG) temp|=1;
2409 seteab(temp);
2410 // setznp8(temp);
2411 if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
2412 else flags&=~V_FLAG;
2413 cycles-=((mod==3)?2:23);
2414 break;
2415 case 0x08: /*ROR b,1*/
2416 if (temp&1) flags|=C_FLAG;
2417 else flags&=~C_FLAG;
2418 temp>>=1;
2419 if (flags&C_FLAG) temp|=0x80;
2420 seteab(temp);
2421 // setznp8(temp);
2422 if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
2423 else flags&=~V_FLAG;
2424 cycles-=((mod==3)?2:23);
2425 break;
2426 case 0x10: /*RCL b,1*/
2427 temp2=flags&C_FLAG;
2428 if (temp&0x80) flags|=C_FLAG;
2429 else flags&=~C_FLAG;
2430 temp<<=1;
2431 if (temp2) temp|=1;
2432 seteab(temp);
2433 // setznp8(temp);
2434 if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
2435 else flags&=~V_FLAG;
2436 cycles-=((mod==3)?2:23);
2437 break;
2438 case 0x18: /*RCR b,1*/
2439 temp2=flags&C_FLAG;
2440 if (temp&1) flags|=C_FLAG;
2441 else flags&=~C_FLAG;
2442 temp>>=1;
2443 if (temp2) temp|=0x80;
2444 seteab(temp);
2445 // setznp8(temp);
2446 if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
2447 else flags&=~V_FLAG;
2448 cycles-=((mod==3)?2:23);
2449 break;
2450 case 0x20: case 0x30: /*SHL b,1*/
2451 if (temp&0x80) flags|=C_FLAG;
2452 else flags&=~C_FLAG;
2453 if ((temp^(temp<<1))&0x80) flags|=V_FLAG;
2454 else flags&=~V_FLAG;
2455 temp<<=1;
2456 seteab(temp);
2457 setznp8(temp);
2458 cycles-=((mod==3)?2:23);
2459 flags|=A_FLAG;
2460 break;
2461 case 0x28: /*SHR b,1*/
2462 if (temp&1) flags|=C_FLAG;
2463 else flags&=~C_FLAG;
2464 if (temp&0x80) flags|=V_FLAG;
2465 else flags&=~V_FLAG;
2466 temp>>=1;
2467 seteab(temp);
2468 setznp8(temp);
2469 cycles-=((mod==3)?2:23);
2470 flags|=A_FLAG;
2471 break;
2472 case 0x38: /*SAR b,1*/
2473 if (temp&1) flags|=C_FLAG;
2474 else flags&=~C_FLAG;
2475 temp>>=1;
2476 if (temp&0x40) temp|=0x80;
2477 seteab(temp);
2478 setznp8(temp);
2479 cycles-=((mod==3)?2:23);
2480 flags|=A_FLAG;
2481 flags&=~V_FLAG;
2482 break;
2484 // default:
2485 // printf("Bad D0 opcode %02X\n",rmdat&0x38);
2486 // dumpregs();
2487 // exit(-1);
2488 }
2489 break;
2491 case 0xD1:
2492 fetchea();
2493 tempw=geteaw();
2494 switch (rmdat&0x38)
2495 {
2496 case 0x00: /*ROL w,1*/
2497 if (tempw&0x8000) flags|=C_FLAG;
2498 else flags&=~C_FLAG;
2499 tempw<<=1;
2500 if (flags&C_FLAG) tempw|=1;
2501 seteaw(tempw);
2502 // setznp16(tempw);
2503 if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
2504 else flags&=~V_FLAG;
2505 cycles-=((mod==3)?2:23);
2506 break;
2507 case 0x08: /*ROR w,1*/
2508 if (tempw&1) flags|=C_FLAG;
2509 else flags&=~C_FLAG;
2510 tempw>>=1;
2511 if (flags&C_FLAG) tempw|=0x8000;
2512 seteaw(tempw);
2513 // setznp16(tempw);
2514 if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
2515 else flags&=~V_FLAG;
2516 cycles-=((mod==3)?2:23);
2517 break;
2518 case 0x10: /*RCL w,1*/
2519 temp2=flags&C_FLAG;
2520 if (tempw&0x8000) flags|=C_FLAG;
2521 else flags&=~C_FLAG;
2522 tempw<<=1;
2523 if (temp2) tempw|=1;
2524 seteaw(tempw);
2525 if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
2526 else flags&=~V_FLAG;
2527 cycles-=((mod==3)?2:23);
2528 break;
2529 case 0x18: /*RCR w,1*/
2530 temp2=flags&C_FLAG;
2531 if (tempw&1) flags|=C_FLAG;
2532 else flags&=~C_FLAG;
2533 tempw>>=1;
2534 if (temp2) tempw|=0x8000;
2535 seteaw(tempw);
2536 // setznp16(tempw);
2537 if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
2538 else flags&=~V_FLAG;
2539 cycles-=((mod==3)?2:23);
2540 break;
2541 case 0x20: case 0x30: /*SHL w,1*/
2542 if (tempw&0x8000) flags|=C_FLAG;
2543 else flags&=~C_FLAG;
2544 if ((tempw^(tempw<<1))&0x8000) flags|=V_FLAG;
2545 else flags&=~V_FLAG;
2546 tempw<<=1;
2547 seteaw(tempw);
2548 setznp16(tempw);
2549 cycles-=((mod==3)?2:23);
2550 flags|=A_FLAG;
2551 break;
2552 case 0x28: /*SHR w,1*/
2553 if (tempw&1) flags|=C_FLAG;
2554 else flags&=~C_FLAG;
2555 if (tempw&0x8000) flags|=V_FLAG;
2556 else flags&=~V_FLAG;
2557 tempw>>=1;
2558 seteaw(tempw);
2559 setznp16(tempw);
2560 cycles-=((mod==3)?2:23);
2561 flags|=A_FLAG;
2562 break;
2564 case 0x38: /*SAR w,1*/
2565 if (tempw&1) flags|=C_FLAG;
2566 else flags&=~C_FLAG;
2567 tempw>>=1;
2568 if (tempw&0x4000) tempw|=0x8000;
2569 seteaw(tempw);
2570 setznp16(tempw);
2571 cycles-=((mod==3)?2:23);
2572 flags|=A_FLAG;
2573 flags&=~V_FLAG;
2574 break;
2576 // default:
2577 // printf("Bad D1 opcode %02X\n",rmdat&0x38);
2578 // dumpregs();
2579 // exit(-1);
2580 }
2581 break;
2583 case 0xD2:
2584 fetchea();
2585 temp=geteab();
2586 c=CL;
2587 // cycles-=c;
2588 if (!c) break;
2589 // if (c>7) printf("Shiftb %i %02X\n",rmdat&0x38,c);
2590 switch (rmdat&0x38)
2591 {
2592 case 0x00: /*ROL b,CL*/
2593 while (c>0)
2594 {
2595 temp2=(temp&0x80)?1:0;
2596 temp=(temp<<1)|temp2;
2597 c--;
2598 cycles-=4;
2599 }
2600 if (temp2) flags|=C_FLAG;
2601 else flags&=~C_FLAG;
2602 seteab(temp);
2603 // setznp8(temp);
2604 if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
2605 else flags&=~V_FLAG;
2606 cycles-=((mod==3)?8:28);
2607 break;
2608 case 0x08: /*ROR b,CL*/
2609 while (c>0)
2610 {
2611 temp2=temp&1;
2612 temp>>=1;
2613 if (temp2) temp|=0x80;
2614 c--;
2615 cycles-=4;
2616 }
2617 if (temp2) flags|=C_FLAG;
2618 else flags&=~C_FLAG;
2619 seteab(temp);
2620 if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
2621 else flags&=~V_FLAG;
2622 cycles-=((mod==3)?8:28);
2623 break;
2624 case 0x10: /*RCL b,CL*/
2625 // printf("RCL %i %02X %02X\n",c,CL,temp);
2626 while (c>0)
2627 {
2628 templ=flags&C_FLAG;
2629 temp2=temp&0x80;
2630 temp<<=1;
2631 if (temp2) flags|=C_FLAG;
2632 else flags&=~C_FLAG;
2633 if (templ) temp|=1;
2634 c--;
2635 cycles-=4;
2636 }
2637 // printf("Now %02X\n",temp);
2638 seteab(temp);
2639 if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
2640 else flags&=~V_FLAG;
2641 cycles-=((mod==3)?8:28);
2642 break;
2643 case 0x18: /*RCR b,CL*/
2644 while (c>0)
2645 {
2646 templ=flags&C_FLAG;
2647 temp2=temp&1;
2648 temp>>=1;
2649 if (temp2) flags|=C_FLAG;
2650 else flags&=~C_FLAG;
2651 if (templ) temp|=0x80;
2652 c--;
2653 cycles-=4;
2654 }
2655 // if (temp2) flags|=C_FLAG;
2656 // else flags&=~C_FLAG;
2657 seteab(temp);
2658 if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
2659 else flags&=~V_FLAG;
2660 cycles-=((mod==3)?8:28);
2661 break;
2662 case 0x20: case 0x30: /*SHL b,CL*/
2663 if ((temp<<(c-1))&0x80) flags|=C_FLAG;
2664 else flags&=~C_FLAG;
2665 temp<<=c;
2666 seteab(temp);
2667 setznp8(temp);
2668 cycles-=(c*4);
2669 cycles-=((mod==3)?8:28);
2670 flags|=A_FLAG;
2671 break;
2672 case 0x28: /*SHR b,CL*/
2673 if ((temp>>(c-1))&1) flags|=C_FLAG;
2674 else flags&=~C_FLAG;
2675 temp>>=c;
2676 seteab(temp);
2677 setznp8(temp);
2678 cycles-=(c*4);
2679 cycles-=((mod==3)?8:28);
2680 flags|=A_FLAG;
2681 break;
2682 case 0x38: /*SAR b,CL*/
2683 if ((temp>>(c-1))&1) flags|=C_FLAG;
2684 else flags&=~C_FLAG;
2685 while (c>0)
2686 {
2687 temp>>=1;
2688 if (temp&0x40) temp|=0x80;
2689 c--;
2690 cycles-=4;
2691 }
2692 seteab(temp);
2693 setznp8(temp);
2694 cycles-=((mod==3)?8:28);
2695 flags|=A_FLAG;
2696 break;
2698 // default:
2699 // printf("Bad D2 opcode %02X\n",rmdat&0x38);
2700 // dumpregs();
2701 // exit(-1);
2702 }
2703 break;
2705 case 0xD3:
2706 fetchea();
2707 tempw=geteaw();
2708 c=CL;
2709 // cycles-=c;
2710 if (!c) break;
2711 // if (c>15) printf("Shiftw %i %02X\n",rmdat&0x38,c);
2712 switch (rmdat&0x38)
2713 {
2714 case 0x00: /*ROL w,CL*/
2715 while (c>0)
2716 {
2717 temp=(tempw&0x8000)?1:0;
2718 tempw=(tempw<<1)|temp;
2719 c--;
2720 cycles-=4;
2721 }
2722 if (temp) flags|=C_FLAG;
2723 else flags&=~C_FLAG;
2724 seteaw(tempw);
2725 if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
2726 else flags&=~V_FLAG;
2727 cycles-=((mod==3)?8:28);
2728 break;
2729 case 0x08: /*ROR w,CL*/
2730 while (c>0)
2731 {
2732 tempw2=(tempw&1)?0x8000:0;
2733 tempw=(tempw>>1)|tempw2;
2734 c--;
2735 cycles-=4;
2736 }
2737 if (tempw2) flags|=C_FLAG;
2738 else flags&=~C_FLAG;
2739 seteaw(tempw);
2740 if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
2741 else flags&=~V_FLAG;
2742 cycles-=((mod==3)?8:28);
2743 break;
2744 case 0x10: /*RCL w,CL*/
2745 while (c>0)
2746 {
2747 templ=flags&C_FLAG;
2748 if (tempw&0x8000) flags|=C_FLAG;
2749 else flags&=~C_FLAG;
2750 tempw=(tempw<<1)|templ;
2751 c--;
2752 cycles-=4;
2753 }
2754 if (temp) flags|=C_FLAG;
2755 else flags&=~C_FLAG;
2756 seteaw(tempw);
2757 if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
2758 else flags&=~V_FLAG;
2759 cycles-=((mod==3)?8:28);
2760 break;
2761 case 0x18: /*RCR w,CL*/
2762 while (c>0)
2763 {
2764 templ=flags&C_FLAG;
2765 tempw2=(templ&1)?0x8000:0;
2766 if (tempw&1) flags|=C_FLAG;
2767 else flags&=~C_FLAG;
2768 tempw=(tempw>>1)|tempw2;
2769 c--;
2770 cycles-=4;
2771 }
2772 if (tempw2) flags|=C_FLAG;
2773 else flags&=~C_FLAG;
2774 seteaw(tempw);
2775 if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
2776 else flags&=~V_FLAG;
2777 cycles-=((mod==3)?8:28);
2778 break;
2780 case 0x20: case 0x30: /*SHL w,CL*/
2781 if (c>16)
2782 {
2783 tempw=0;
2784 flags&=~C_FLAG;
2785 }
2786 else
2787 {
2788 if ((tempw<<(c-1))&0x8000) flags|=C_FLAG;
2789 else flags&=~C_FLAG;
2790 tempw<<=c;
2791 }
2792 seteaw(tempw);
2793 setznp16(tempw);
2794 cycles-=(c*4);
2795 cycles-=((mod==3)?8:28);
2796 flags|=A_FLAG;
2797 break;
2799 case 0x28: /*SHR w,CL*/
2800 if ((tempw>>(c-1))&1) flags|=C_FLAG;
2801 else flags&=~C_FLAG;
2802 tempw>>=c;
2803 seteaw(tempw);
2804 setznp16(tempw);
2805 cycles-=(c*4);
2806 cycles-=((mod==3)?8:28);
2807 flags|=A_FLAG;
2808 break;
2810 case 0x38: /*SAR w,CL*/
2811 tempw2=tempw&0x8000;
2812 if ((tempw>>(c-1))&1) flags|=C_FLAG;
2813 else flags&=~C_FLAG;
2814 while (c>0)
2815 {
2816 tempw=(tempw>>1)|tempw2;
2817 c--;
2818 cycles-=4;
2819 }
2820 seteaw(tempw);
2821 setznp16(tempw);
2822 cycles-=((mod==3)?8:28);
2823 flags|=A_FLAG;
2824 break;
2826 // default:
2827 // printf("Bad D3 opcode %02X\n",rmdat&0x38);
2828 // dumpregs();
2829 // exit(-1);
2830 }
2831 break;
2833 case 0xD4: /*AAM*/
2834 tempws=FETCH();
2835 AH=AL/tempws;
2836 AL%=tempws;
2837 setznp16(AX);
2838 cycles-=83;
2839 break;
2840 case 0xD5: /*AAD*/
2841 tempws=FETCH();
2842 AL=(AH*tempws)+AL;
2843 AH=0;
2844 setznp16(AX);
2845 cycles-=60;
2846 break;
2847 case 0xD7: /*XLAT*/
2848 addr=BX+AL;
2849 AL=readmemb(ds+addr);
2850 cycles-=11;
2851 break;
2852 case 0xD9: case 0xDA: case 0xDB: case 0xDD: /*ESCAPE*/
2853 case 0xDC: case 0xDE: case 0xDF: case 0xD8:
2854 fetchea();
2855 geteab();
2856 break;
2858 case 0xE0: /*LOOPNE*/
2859 offset=(int8_t)FETCH();
2860 CX--;
2861 if (CX && !(flags&Z_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
2862 cycles-=6;
2863 break;
2864 case 0xE1: /*LOOPE*/
2865 offset=(int8_t)FETCH();
2866 CX--;
2867 if (CX && (flags&Z_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
2868 cycles-=6;
2869 break;
2870 case 0xE2: /*LOOP*/
2871 // printf("LOOP start\n");
2872 offset=(int8_t)FETCH();
2873 CX--;
2874 if (CX) { pc+=offset; cycles-=12; FETCHCLEAR(); }
2875 cycles-=5;
2876 // printf("LOOP end!\n");
2877 break;
2878 case 0xE3: /*JCXZ*/
2879 offset=(int8_t)FETCH();
2880 if (!CX) { pc+=offset; cycles-=12; FETCHCLEAR(); }
2881 cycles-=6;
2882 break;
2884 case 0xE4: /*IN AL*/
2885 temp=FETCH();
2886 AL=inb(temp);
2887 cycles-=14;
2888 break;
2889 case 0xE5: /*IN AX*/
2890 temp=FETCH();
2891 AL=inb(temp);
2892 AH=inb(temp+1);
2893 cycles-=14;
2894 break;
2895 case 0xE6: /*OUT AL*/
2896 temp=FETCH();
2897 outb(temp,AL);
2898 cycles-=14;
2899 break;
2900 case 0xE7: /*OUT AX*/
2901 temp=FETCH();
2902 outb(temp,AL);
2903 outb(temp+1,AH);
2904 cycles-=14;
2905 break;
2907 case 0xE8: /*CALL rel 16*/
2908 tempw=getword();
2909 if (ssegs) ss=oldss;
2910 // writememb(ss+((SP-1)&0xFFFF),pc>>8);
2911 writememw(ss,((SP-2)&0xFFFF),pc);
2912 SP-=2;
2913 pc+=tempw;
2914 cycles-=23;
2915 FETCHCLEAR();
2916 break;
2917 case 0xE9: /*JMP rel 16*/
2918 // printf("PC was %04X\n",pc);
2919 pc+=getword();
2920 // printf("PC now %04X\n",pc);
2921 cycles-=15;
2922 FETCHCLEAR();
2923 break;
2924 case 0xEA: /*JMP far*/
2925 addr=getword();
2926 tempw=getword();
2927 pc=addr;
2928 // printf("EA\n");
2929 loadcs(tempw);
2930 // cs=loadcs(CS);
2931 // cs=CS<<4;
2932 cycles-=15;
2933 FETCHCLEAR();
2934 break;
2935 case 0xEB: /*JMP rel*/
2936 offset=(int8_t)FETCH();
2937 pc+=offset;
2938 cycles-=15;
2939 FETCHCLEAR();
2940 break;
2941 case 0xEC: /*IN AL,DX*/
2942 AL=inb(DX);
2943 cycles-=12;
2944 break;
2945 case 0xED: /*IN AX,DX*/
2946 AL=inb(DX);
2947 AH=inb(DX+1);
2948 cycles-=12;
2949 break;
2950 case 0xEE: /*OUT DX,AL*/
2951 outb(DX,AL);
2952 cycles-=12;
2953 break;
2954 case 0xEF: /*OUT DX,AX*/
2955 outb(DX,AL);
2956 outb(DX+1,AH);
2957 cycles-=12;
2958 break;
2960 case 0xF0: /*LOCK*/
2961 cycles-=4;
2962 break;
2964 case 0xF2: /*REPNE*/
2965 rep(0);
2966 break;
2967 case 0xF3: /*REPE*/
2968 rep(1);
2969 break;
2971 case 0xF4: /*HLT*/
2972 // printf("IN HLT!!!! %04X:%04X %08X %08X %08X\n",oldcs,oldpc,old8,old82,old83);
2973 /* if (!(flags & I_FLAG))
2974 {
2975 pclog("HLT\n");
2976 dumpregs();
2977 exit(-1);
2978 }*/
2979 inhlt=1;
2980 pc--;
2981 FETCHCLEAR();
2982 cycles-=2;
2983 break;
2984 case 0xF5: /*CMC*/
2985 flags^=C_FLAG;
2986 cycles-=2;
2987 break;
2989 case 0xF6:
2990 fetchea();
2991 temp=geteab();
2992 switch (rmdat&0x38)
2993 {
2994 case 0x00: /*TEST b,#8*/
2995 temp2=FETCH();
2996 temp&=temp2;
2997 setznp8(temp);
2998 flags&=~(C_FLAG|V_FLAG|A_FLAG);
2999 cycles-=((mod==3)?5:11);
3000 break;
3001 case 0x10: /*NOT b*/
3002 temp=~temp;
3003 seteab(temp);
3004 cycles-=((mod==3)?3:24);
3005 break;
3006 case 0x18: /*NEG b*/
3007 setsub8(0,temp);
3008 temp=0-temp;
3009 seteab(temp);
3010 cycles-=((mod==3)?3:24);
3011 break;
3012 case 0x20: /*MUL AL,b*/
3013 setznp8(AL);
3014 AX=AL*temp;
3015 if (AX) flags&=~Z_FLAG;
3016 else flags|=Z_FLAG;
3017 if (AH) flags|=(C_FLAG|V_FLAG);
3018 else flags&=~(C_FLAG|V_FLAG);
3019 cycles-=70;
3020 break;
3021 case 0x28: /*IMUL AL,b*/
3022 setznp8(AL);
3023 tempws=(int)((int8_t)AL)*(int)((int8_t)temp);
3024 AX=tempws&0xFFFF;
3025 if (AX) flags&=~Z_FLAG;
3026 else flags|=Z_FLAG;
3027 if (AH) flags|=(C_FLAG|V_FLAG);
3028 else flags&=~(C_FLAG|V_FLAG);
3029 cycles-=80;
3030 break;
3031 case 0x30: /*DIV AL,b*/
3032 tempw=AX;
3033 if (temp)
3034 {
3035 tempw2=tempw%temp;
3036 /* if (!tempw)
3037 {
3038 writememw((ss+SP)-2,flags|0xF000);
3039 writememw((ss+SP)-4,cs>>4);
3040 writememw((ss+SP)-6,pc);
3041 SP-=6;
3042 flags&=~I_FLAG;
3043 pc=readmemw(0);
3044 cs=readmemw(2)<<4;
3045 printf("Div by zero %04X:%04X\n",cs>>4,pc);
3046 // dumpregs();
3047 // exit(-1);
3048 }
3049 else
3050 {*/
3051 AH=tempw2;
3052 tempw/=temp;
3053 AL=tempw&0xFF;
3054 // }
3055 }
3056 else
3057 {
3058 printf("DIVb BY 0 %04X:%04X\n",cs>>4,pc);
3059 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3060 writememw(ss,(SP-4)&0xFFFF,CS);
3061 writememw(ss,(SP-6)&0xFFFF,pc);
3062 SP-=6;
3063 flags&=~I_FLAG;
3064 flags&=~T_FLAG;
3065 pc=readmemw(0,0);
3066 // printf("F6 30\n");
3067 loadcs(readmemw(0,2));
3068 FETCHCLEAR();
3069 // cs=loadcs(CS);
3070 // cs=CS<<4;
3071 // printf("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x30);
3072 // dumpregs();
3073 // exit(-1);
3074 }
3075 cycles-=80;
3076 break;
3077 case 0x38: /*IDIV AL,b*/
3078 tempws=(int)AX;
3079 if (temp)
3080 {
3081 tempw2=tempws%(int)((int8_t)temp);
3082 /* if (!tempw)
3083 {
3084 writememw((ss+SP)-2,flags|0xF000);
3085 writememw((ss+SP)-4,cs>>4);
3086 writememw((ss+SP)-6,pc);
3087 SP-=6;
3088 flags&=~I_FLAG;
3089 pc=readmemw(0);
3090 cs=readmemw(2)<<4;
3091 printf("Div by zero %04X:%04X\n",cs>>4,pc);
3092 }
3093 else
3094 {*/
3095 AH=tempw2&0xFF;
3096 tempws/=(int)((int8_t)temp);
3097 AL=tempws&0xFF;
3098 // }
3099 }
3100 else
3101 {
3102 printf("IDIVb BY 0 %04X:%04X\n",cs>>4,pc);
3103 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3104 writememw(ss,(SP-4)&0xFFFF,CS);
3105 writememw(ss,(SP-6)&0xFFFF,pc);
3106 SP-=6;
3107 flags&=~I_FLAG;
3108 flags&=~T_FLAG;
3109 pc=readmemw(0,0);
3110 // printf("F6 38\n");
3111 loadcs(readmemw(0,2));
3112 FETCHCLEAR();
3113 // cs=loadcs(CS);
3114 // cs=CS<<4;
3115 // printf("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x38);
3116 }
3117 cycles-=101;
3118 break;
3120 // default:
3121 // printf("Bad F6 opcode %02X\n",rmdat&0x38);
3122 // dumpregs();
3123 // exit(-1);
3124 }
3125 break;
3127 case 0xF7:
3128 fetchea();
3129 tempw=geteaw();
3130 switch (rmdat&0x38)
3131 {
3132 case 0x00: /*TEST w*/
3133 tempw2=getword();
3134 setznp16(tempw&tempw2);
3135 flags&=~(C_FLAG|V_FLAG|A_FLAG);
3136 cycles-=((mod==3)?5:11);
3137 break;
3138 case 0x10: /*NOT w*/
3139 seteaw(~tempw);
3140 cycles-=((mod==3)?3:24);
3141 break;
3142 case 0x18: /*NEG w*/
3143 setsub16(0,tempw);
3144 tempw=0-tempw;
3145 seteaw(tempw);
3146 cycles-=((mod==3)?3:24);
3147 break;
3148 case 0x20: /*MUL AX,w*/
3149 setznp16(AX);
3150 templ=AX*tempw;
3151 // if (output) printf("%04X*%04X=%08X\n",AX,tempw,templ);
3152 AX=templ&0xFFFF;
3153 DX=templ>>16;
3154 if (AX|DX) flags&=~Z_FLAG;
3155 else flags|=Z_FLAG;
3156 if (DX) flags|=(C_FLAG|V_FLAG);
3157 else flags&=~(C_FLAG|V_FLAG);
3158 cycles-=118;
3159 break;
3160 case 0x28: /*IMUL AX,w*/
3161 setznp16(AX);
3162 // printf("IMUL %i %i ",(int)((int16_t)AX),(int)((int16_t)tempw));
3163 tempws=(int)((int16_t)AX)*(int)((int16_t)tempw);
3164 if ((tempws>>15) && ((tempws>>15)!=-1)) flags|=(C_FLAG|V_FLAG);
3165 else flags&=~(C_FLAG|V_FLAG);
3166 // printf("%i ",tempws);
3167 AX=tempws&0xFFFF;
3168 tempws=(uint16_t)(tempws>>16);
3169 DX=tempws&0xFFFF;
3170 // printf("%04X %04X\n",AX,DX);
3171 // dumpregs();
3172 // exit(-1);
3173 if (AX|DX) flags&=~Z_FLAG;
3174 else flags|=Z_FLAG;
3175 cycles-=128;
3176 break;
3177 case 0x30: /*DIV AX,w*/
3178 templ=(DX<<16)|AX;
3179 // printf("DIV %08X/%04X\n",templ,tempw);
3180 if (tempw)
3181 {
3182 tempw2=templ%tempw;
3183 DX=tempw2;
3184 templ/=tempw;
3185 AX=templ&0xFFFF;
3186 }
3187 else
3188 {
3189 printf("DIVw BY 0 %04X:%04X\n",cs>>4,pc);
3190 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3191 writememw(ss,(SP-4)&0xFFFF,CS);
3192 writememw(ss,(SP-6)&0xFFFF,pc);
3193 SP-=6;
3194 flags&=~I_FLAG;
3195 flags&=~T_FLAG;
3196 pc=readmemw(0,0);
3197 // printf("F7 30\n");
3198 loadcs(readmemw(0,2));
3199 FETCHCLEAR();
3200 }
3201 cycles-=144;
3202 break;
3203 case 0x38: /*IDIV AX,w*/
3204 tempws=(int)((DX<<16)|AX);
3205 // printf("IDIV %i %i ",tempws,tempw);
3206 if (tempw)
3207 {
3208 tempw2=tempws%(int)((int16_t)tempw);
3209 // printf("%04X ",tempw2);
3210 DX=tempw2;
3211 tempws/=(int)((int16_t)tempw);
3212 AX=tempws&0xFFFF;
3213 }
3214 else
3215 {
3216 printf("IDIVw BY 0 %04X:%04X\n",cs>>4,pc);
3217 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3218 writememw(ss,(SP-4)&0xFFFF,CS);
3219 writememw(ss,(SP-6)&0xFFFF,pc);
3220 SP-=6;
3221 flags&=~I_FLAG;
3222 flags&=~T_FLAG;
3223 pc=readmemw(0,0);
3224 // printf("F7 38\n");
3225 loadcs(readmemw(0,2));
3226 FETCHCLEAR();
3227 }
3228 cycles-=165;
3229 break;
3231 // default:
3232 // printf("Bad F7 opcode %02X\n",rmdat&0x38);
3233 // dumpregs();
3234 // exit(-1);
3235 }
3236 break;
3238 case 0xF8: /*CLC*/
3239 flags&=~C_FLAG;
3240 cycles-=2;
3241 break;
3242 case 0xF9: /*STC*/
3243 // printf("STC %04X\n",pc);
3244 flags|=C_FLAG;
3245 cycles-=2;
3246 break;
3247 case 0xFA: /*CLI*/
3248 flags&=~I_FLAG;
3249 // printf("CLI at %04X:%04X\n",cs>>4,pc);
3250 cycles-=3;
3251 break;
3252 case 0xFB: /*STI*/
3253 flags|=I_FLAG;
3254 // printf("STI at %04X:%04X\n",cs>>4,pc);
3255 cycles-=2;
3256 break;
3257 case 0xFC: /*CLD*/
3258 flags&=~D_FLAG;
3259 cycles-=2;
3260 break;
3261 case 0xFD: /*STD*/
3262 flags|=D_FLAG;
3263 cycles-=2;
3264 break;
3266 case 0xFE: /*INC/DEC b*/
3267 fetchea();
3268 temp=geteab();
3269 flags&=~V_FLAG;
3270 if (rmdat&0x38)
3271 {
3272 setsub8nc(temp,1);
3273 temp2=temp-1;
3274 if ((temp&0x80) && !(temp2&0x80)) flags|=V_FLAG;
3275 }
3276 else
3277 {
3278 setadd8nc(temp,1);
3279 temp2=temp+1;
3280 if ((temp2&0x80) && !(temp&0x80)) flags|=V_FLAG;
3281 }
3282 // setznp8(temp2);
3283 seteab(temp2);
3284 cycles-=((mod==3)?3:23);
3285 break;
3287 case 0xFF:
3288 fetchea();
3289 switch (rmdat&0x38)
3290 {
3291 case 0x00: /*INC w*/
3292 tempw=geteaw();
3293 setadd16nc(tempw,1);
3294 // setznp16(tempw+1);
3295 seteaw(tempw+1);
3296 cycles-=((mod==3)?3:23);
3297 break;
3298 case 0x08: /*DEC w*/
3299 tempw=geteaw();
3300 // setsub16(tempw,1);
3301 setsub16nc(tempw,1);
3302 // setznp16(tempw-1);
3303 seteaw(tempw-1);
3304 // if (output) printf("DEC - %04X\n",tempw);
3305 cycles-=((mod==3)?3:23);
3306 break;
3307 case 0x10: /*CALL*/
3308 tempw=geteaw();
3309 if (ssegs) ss=oldss;
3310 writememw(ss,(SP-2)&0xFFFF,pc);
3311 SP-=2;
3312 pc=tempw;
3313 // printf("FF 10\n");
3314 cycles-=((mod==3)?20:29);
3315 FETCHCLEAR();
3316 break;
3317 case 0x18: /*CALL far*/
3318 tempw=readmemw(easeg,eaaddr);
3319 tempw2=readmemw(easeg,(eaaddr+2)&0xFFFF); //geteaw2();
3320 tempw3=CS;
3321 tempw4=pc;
3322 if (ssegs) ss=oldss;
3323 pc=tempw;
3324 // printf("FF 18\n");
3325 loadcs(tempw2);
3326 writememw(ss,(SP-2)&0xFFFF,tempw3);
3327 writememw(ss,((SP-4)&0xFFFF),tempw4);
3328 SP-=4;
3329 cycles-=53;
3330 FETCHCLEAR();
3331 break;
3332 case 0x20: /*JMP*/
3333 pc=geteaw();
3334 // printf("FF 20\n");
3335 cycles-=((mod==3)?11:18);
3336 FETCHCLEAR();
3337 break;
3338 case 0x28: /*JMP far*/
3339 pc=readmemw(easeg,eaaddr); //geteaw();
3340 // printf("FF 28\n");
3341 loadcs(readmemw(easeg,(eaaddr+2)&0xFFFF)); //geteaw2();
3342 // cs=loadcs(CS);
3343 // cs=CS<<4;
3344 cycles-=24;
3345 FETCHCLEAR();
3346 break;
3347 case 0x30: /*PUSH w*/
3348 tempw=geteaw();
3349 // if (output) printf("PUSH %04X %i %02X %04X %04X %02X %02X\n",tempw,rm,rmdat,easeg,eaaddr,ram[0x22340+0x5638],ram[0x22340+0x5639]);
3350 if (ssegs) ss=oldss;
3351 writememw(ss,((SP-2)&0xFFFF),tempw);
3352 SP-=2;
3353 cycles-=((mod==3)?15:24);
3354 break;
3356 // default:
3357 // printf("Bad FF opcode %02X\n",rmdat&0x38);
3358 // dumpregs();
3359 // exit(-1);
3360 }
3361 break;
3363 default:
3364 FETCH();
3365 cycles-=8;
3366 break;
3368 /* printf("Bad opcode %02X at %04X:%04X from %04X:%04X %08X\n",opcode,cs>>4,pc,old8>>16,old8&0xFFFF,old82);
3369 dumpregs();
3370 exit(-1);*/
3371 }
3372 pc&=0xFFFF;
3374 /* if ((CS & 0xf000) == 0xa000)
3375 {
3376 dumpregs();
3377 exit(-1);
3378 }*/
3379 // output = 3;
3380 /* if (CS == 0xf000)
3381 {
3382 dumpregs();
3383 exit(-1);
3384 }
3385 output = 3;*/
3386 if (ssegs)
3387 {
3388 ds=oldds;
3389 ss=oldss;
3390 ssegs=0;
3391 }
3393 // output = 3;
3394 // if (instime) printf("%i %i %i %i\n",cycdiff,cycles,memcycs,fetchclocks);
3395 FETCHADD(((cycdiff-cycles)-memcycs)-fetchclocks);
3396 if ((cycdiff-cycles)<memcycs) cycles-=(memcycs-(cycdiff-cycles));
3397 if (romset==ROM_IBMPC)
3398 {
3399 if ((cs+pc)==0xFE4A7) /*You didn't seriously think I was going to emulate the cassette, did you?*/
3400 {
3401 CX=1;
3402 BX=0x500;
3403 }
3404 }
3405 memcycs=0;
3407 insc++;
3408 // output=(CS==0xEB9);
3409 clockhardware();
3412 if (trap && (flags&T_FLAG) && !noint)
3413 {
3414 // printf("TRAP!!! %04X:%04X\n",CS,pc);
3415 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3416 writememw(ss,(SP-4)&0xFFFF,CS);
3417 writememw(ss,(SP-6)&0xFFFF,pc);
3418 SP-=6;
3419 addr=1<<2;
3420 flags&=~I_FLAG;
3421 flags&=~T_FLAG;
3422 pc=readmemw(0,addr);
3423 loadcs(readmemw(0,addr+2));
3424 FETCHCLEAR();
3425 }
3426 else if (nmi && nmi_enable)
3427 {
3428 // output = 3;
3429 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3430 writememw(ss,(SP-4)&0xFFFF,CS);
3431 writememw(ss,(SP-6)&0xFFFF,pc);
3432 SP-=6;
3433 addr=2<<2;
3434 flags&=~I_FLAG;
3435 flags&=~T_FLAG;
3436 pc=readmemw(0,addr);
3437 loadcs(readmemw(0,addr+2));
3438 FETCHCLEAR();
3439 nmi_enable = 0;
3440 }
3441 else if (takeint && !ssegs && !noint)
3442 {
3443 temp=picinterrupt();
3444 if (temp!=0xFF)
3445 {
3446 if (inhlt) pc++;
3447 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3448 writememw(ss,(SP-4)&0xFFFF,CS);
3449 writememw(ss,(SP-6)&0xFFFF,pc);
3450 SP-=6;
3451 addr=temp<<2;
3452 flags&=~I_FLAG;
3453 flags&=~T_FLAG;
3454 pc=readmemw(0,addr);
3455 // printf("INT INT INT\n");
3456 loadcs(readmemw(0,addr+2));
3457 FETCHCLEAR();
3458 // printf("INTERRUPT\n");
3459 }
3460 }
3461 takeint = (flags&I_FLAG) && (pic.pend&~pic.mask);
3463 if (noint) noint=0;
3464 ins++;
3465 /* if (timetolive)
3466 {
3467 timetolive--;
3468 if (!timetolive) exit(-1); //output=0;
3469 }*/
3470 }
3471 }
