PCem
view src/808x.c @ 142:bd46c39a78e8
Implemented selector limits on some instructions - fixes LBA2.
GPFs in real mode now work.
Selectors correctly zeroed on far return to lower privilege.
| author | TomW |
|---|---|
| date | Wed Aug 13 20:33:56 2014 +0100 |
| parents | 912e602b3406 |
| children | 871b132c6158 |
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=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,_cs.limit,_cs.access, _cs.limit_low, _cs.limit_high);
592 printf("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,_ds.limit,_ds.access, _ds.limit_low, _ds.limit_high);
593 printf("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,_es.limit,_es.access, _es.limit_low, _es.limit_high);
594 if (is386)
595 {
596 printf("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",fs,_fs.limit,_fs.access, _fs.limit_low, _fs.limit_high);
597 printf("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,_gs.limit,_gs.access, _gs.limit_low, _gs.limit_high);
598 }
599 printf("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,_ss.limit,_ss.access, _ss.limit_low, _ss.limit_high);
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 x86seg_reset();
650 }
652 void softresetx86()
653 {
654 // dumpregs();
655 // exit(-1);
656 use32=0;
657 stack32=0;
658 // i86_Reset();
659 // cs=0xFFFF0;
660 pc=0;
661 msw=0;
662 cr0=0;
663 eflags=0;
664 cgate32=0;
665 loadcs(0xFFFF);
666 //rammask=0xFFFFFFFF;
667 flags=2;
668 idt.base = 0;
669 x86seg_reset();
670 }
672 static void setznp8(uint8_t val)
673 {
674 flags&=~0xC4;
675 flags|=znptable8[val];
676 }
678 static void setznp16(uint16_t val)
679 {
680 flags&=~0xC4;
681 flags|=znptable16[val];
682 }
684 static void setadd8(uint8_t a, uint8_t b)
685 {
686 uint16_t c=(uint16_t)a+(uint16_t)b;
687 flags&=~0x8D5;
688 flags|=znptable8[c&0xFF];
689 if (c&0x100) flags|=C_FLAG;
690 if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
691 if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
692 }
693 static void setadd8nc(uint8_t a, uint8_t b)
694 {
695 uint16_t c=(uint16_t)a+(uint16_t)b;
696 flags&=~0x8D4;
697 flags|=znptable8[c&0xFF];
698 if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
699 if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
700 }
701 static void setadc8(uint8_t a, uint8_t b)
702 {
703 uint16_t c=(uint16_t)a+(uint16_t)b+tempc;
704 flags&=~0x8D5;
705 flags|=znptable8[c&0xFF];
706 if (c&0x100) flags|=C_FLAG;
707 if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
708 if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
709 }
710 static void setadd16(uint16_t a, uint16_t b)
711 {
712 uint32_t c=(uint32_t)a+(uint32_t)b;
713 flags&=~0x8D5;
714 flags|=znptable16[c&0xFFFF];
715 if (c&0x10000) flags|=C_FLAG;
716 if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
717 if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
718 }
719 static void setadd16nc(uint16_t a, uint16_t b)
720 {
721 uint32_t c=(uint32_t)a+(uint32_t)b;
722 flags&=~0x8D4;
723 flags|=znptable16[c&0xFFFF];
724 if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
725 if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
726 }
727 static void setadc16(uint16_t a, uint16_t b)
728 {
729 uint32_t c=(uint32_t)a+(uint32_t)b+tempc;
730 flags&=~0x8D5;
731 flags|=znptable16[c&0xFFFF];
732 if (c&0x10000) flags|=C_FLAG;
733 if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
734 if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
735 }
737 static void setsub8(uint8_t a, uint8_t b)
738 {
739 uint16_t c=(uint16_t)a-(uint16_t)b;
740 flags&=~0x8D5;
741 flags|=znptable8[c&0xFF];
742 if (c&0x100) flags|=C_FLAG;
743 if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
744 if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
745 }
746 static void setsub8nc(uint8_t a, uint8_t b)
747 {
748 uint16_t c=(uint16_t)a-(uint16_t)b;
749 flags&=~0x8D4;
750 flags|=znptable8[c&0xFF];
751 if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
752 if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
753 }
754 static void setsbc8(uint8_t a, uint8_t b)
755 {
756 uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc);
757 flags&=~0x8D5;
758 flags|=znptable8[c&0xFF];
759 if (c&0x100) flags|=C_FLAG;
760 if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
761 if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
762 }
763 static void setsub16(uint16_t a, uint16_t b)
764 {
765 uint32_t c=(uint32_t)a-(uint32_t)b;
766 flags&=~0x8D5;
767 flags|=znptable16[c&0xFFFF];
768 if (c&0x10000) flags|=C_FLAG;
769 if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
770 // if (output) printf("%04X %04X %i\n",a^b,a^c,flags&V_FLAG);
771 if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
772 }
773 static void setsub16nc(uint16_t a, uint16_t b)
774 {
775 uint32_t c=(uint32_t)a-(uint32_t)b;
776 flags&=~0x8D4;
777 flags|=(znptable16[c&0xFFFF]&~4);
778 flags|=(znptable8[c&0xFF]&4);
779 if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
780 if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
781 }
782 static void setsbc16(uint16_t a, uint16_t b)
783 {
784 uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc);
785 flags&=~0x8D5;
786 flags|=(znptable16[c&0xFFFF]&~4);
787 flags|=(znptable8[c&0xFF]&4);
788 if (c&0x10000) flags|=C_FLAG;
789 if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
790 if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
791 }
793 int current_diff = 0;
794 void clockhardware()
795 {
796 int diff = cycdiff - cycles - current_diff;
798 current_diff += diff;
799 if (pit.running[0]) pit.c[0] -= diff;
800 if (pit.running[1]) pit.c[1] -= diff;
801 if (pit.running[2]) pit.c[2] -= diff;
802 if ((pit.c[0] < 1) || (pit.c[1] < 1) || (pit.c[2] < 1)) pit_poll();
804 timer_end_period(cycles);
805 }
807 static int takeint = 0;
810 int firstrepcycle=1;
812 void rep(int fv)
813 {
814 uint8_t temp;
815 int c=CX;
816 uint8_t temp2;
817 uint16_t tempw,tempw2;
818 uint16_t ipc=oldpc;//pc-1;
819 int changeds=0;
820 uint32_t oldds;
821 startrep:
822 temp=FETCH();
824 // if (firstrepcycle && temp==0xA5) printf("REP MOVSW %06X:%04X %06X:%04X\n",ds,SI,es,DI);
825 // if (output) printf("REP %02X %04X\n",temp,ipc);
826 switch (temp)
827 {
828 case 0x08:
829 pc=ipc+1;
830 cycles-=2;
831 FETCHCLEAR();
832 break;
833 case 0x26: /*ES:*/
834 oldds=ds;
835 ds=es;
836 changeds=1;
837 cycles-=2;
838 goto startrep;
839 break;
840 case 0x2E: /*CS:*/
841 oldds=ds;
842 ds=cs;
843 changeds=1;
844 cycles-=2;
845 goto startrep;
846 break;
847 case 0x36: /*SS:*/
848 oldds=ds;
849 ds=ss;
850 changeds=1;
851 cycles-=2;
852 goto startrep;
853 break;
854 case 0x6E: /*REP OUTSB*/
855 if (c>0)
856 {
857 temp2=readmemb(ds+SI);
858 outb(DX,temp2);
859 if (flags&D_FLAG) SI--;
860 else SI++;
861 c--;
862 cycles-=5;
863 }
864 if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
865 else firstrepcycle=1;
866 break;
867 case 0xA4: /*REP MOVSB*/
868 while (c>0 && !IRQTEST)
869 {
870 temp2=readmemb(ds+SI);
871 writememb(es+DI,temp2);
872 // if (output) printf("Moved %02X from %04X:%04X to %04X:%04X\n",temp2,ds>>4,SI,es>>4,DI);
873 if (flags&D_FLAG) { DI--; SI--; }
874 else { DI++; SI++; }
875 c--;
876 cycles-=17;
877 clockhardware();
878 FETCHADD(17-memcycs);
879 }
880 if (IRQTEST && c>0) pc=ipc;
881 // if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
882 // else firstrepcycle=1;
883 // }
884 break;
885 case 0xA5: /*REP MOVSW*/
886 while (c>0 && !IRQTEST)
887 {
888 memcycs=0;
889 tempw=readmemw(ds,SI);
890 writememw(es,DI,tempw);
891 if (flags&D_FLAG) { DI-=2; SI-=2; }
892 else { DI+=2; SI+=2; }
893 c--;
894 cycles-=17;
895 clockhardware();
896 FETCHADD(17 - memcycs);
897 }
898 if (IRQTEST && c>0) pc=ipc;
899 // if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
900 // else firstrepcycle=1;
901 // }
902 break;
903 case 0xA6: /*REP CMPSB*/
904 if (fv) flags|=Z_FLAG;
905 else flags&=~Z_FLAG;
906 while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST)
907 {
908 memcycs=0;
909 temp=readmemb(ds+SI);
910 temp2=readmemb(es+DI);
911 // printf("CMPSB %c %c %i %05X %05X %04X:%04X\n",temp,temp2,c,ds+SI,es+DI,cs>>4,pc);
912 if (flags&D_FLAG) { DI--; SI--; }
913 else { DI++; SI++; }
914 c--;
915 cycles -= 30;
916 setsub8(temp,temp2);
917 clockhardware();
918 FETCHADD(30 - memcycs);
919 }
920 if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) pc=ipc;
921 // if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
922 // else firstrepcycle=1;
923 break;
924 case 0xA7: /*REP CMPSW*/
925 if (fv) flags|=Z_FLAG;
926 else flags&=~Z_FLAG;
927 while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST)
928 {
929 memcycs=0;
930 tempw=readmemw(ds,SI);
931 tempw2=readmemw(es,DI);
932 if (flags&D_FLAG) { DI-=2; SI-=2; }
933 else { DI+=2; SI+=2; }
934 c--;
935 cycles -= 30;
936 setsub16(tempw,tempw2);
937 clockhardware();
938 FETCHADD(30 - memcycs);
939 }
940 if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) pc=ipc;
941 // if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
942 // else firstrepcycle=1;
943 // if (firstrepcycle) printf("REP CMPSW %06X:%04X %06X:%04X %04X %04X\n",ds,SI,es,DI,tempw,tempw2);
944 break;
945 case 0xAA: /*REP STOSB*/
946 while (c>0 && !IRQTEST)
947 {
948 memcycs=0;
949 writememb(es+DI,AL);
950 if (flags&D_FLAG) DI--;
951 else DI++;
952 c--;
953 cycles -= 10;
954 clockhardware();
955 FETCHADD(10 - memcycs);
956 }
957 if (IRQTEST && c>0) pc=ipc;
958 // if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
959 // else firstrepcycle=1;
960 break;
961 case 0xAB: /*REP STOSW*/
962 while (c>0 && !IRQTEST)
963 {
964 memcycs=0;
965 writememw(es,DI,AX);
966 if (flags&D_FLAG) DI-=2;
967 else DI+=2;
968 c--;
969 cycles -= 10;
970 clockhardware();
971 FETCHADD(10 - memcycs);
972 }
973 if (IRQTEST && c>0) pc=ipc;
974 // if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
975 // else firstrepcycle=1;
976 break;
977 case 0xAC: /*REP LODSB*/
978 if (c>0)
979 {
980 temp2=readmemb(ds+SI);
981 if (flags&D_FLAG) SI--;
982 else SI++;
983 c--;
984 cycles-=4;
985 }
986 if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
987 else firstrepcycle=1;
988 break;
989 case 0xAD: /*REP LODSW*/
990 if (c>0)
991 {
992 tempw2=readmemw(ds,SI);
993 if (flags&D_FLAG) SI-=2;
994 else SI+=2;
995 c--;
996 cycles-=4;
997 }
998 if (c>0) { firstrepcycle=0; pc=ipc; if (ssegs) ssegs++; FETCHCLEAR(); }
999 else firstrepcycle=1;
1000 break;
1001 case 0xAE: /*REP SCASB*/
1002 if (fv) flags|=Z_FLAG;
1003 else flags&=~Z_FLAG;
1004 if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
1005 {
1006 temp2=readmemb(es+DI);
1007 // if (output) printf("SCASB %02X %c %02X %05X ",temp2,temp2,AL,es+DI);
1008 setsub8(AL,temp2);
1009 // if (output && flags&Z_FLAG) printf("Match %02X %02X\n",AL,temp2);
1010 if (flags&D_FLAG) DI--;
1011 else DI++;
1012 c--;
1013 cycles -= 15;
1014 }
1015 //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))));
1016 if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
1017 else firstrepcycle=1;
1018 // cycles-=120;
1019 break;
1020 case 0xAF: /*REP SCASW*/
1021 if (fv) flags|=Z_FLAG;
1022 else flags&=~Z_FLAG;
1023 if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
1024 {
1025 tempw=readmemw(es,DI);
1026 setsub16(AX,tempw);
1027 if (flags&D_FLAG) DI-=2;
1028 else DI+=2;
1029 c--;
1030 cycles -= 15;
1031 }
1032 if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
1033 else firstrepcycle=1;
1034 break;
1035 default:
1036 pc=ipc;
1037 cycles-=20;
1038 FETCHCLEAR();
1039 // printf("Bad REP %02X\n",temp);
1040 // dumpregs();
1041 // exit(-1);
1042 }
1043 CX=c;
1044 if (changeds) ds=oldds;
1045 if (IRQTEST)
1046 takeint = 1;
1047 // if (pc==ipc) FETCHCLEAR();
1048 }
1051 int inhlt=0;
1052 uint16_t lastpc,lastcs;
1053 int firstrepcycle;
1054 int skipnextprint=0;
1056 int instime=0;
1057 //#if 0
1058 void execx86(int cycs)
1059 {
1060 uint8_t temp,temp2;
1061 uint16_t addr,tempw,tempw2,tempw3,tempw4;
1062 int8_t offset;
1063 int tempws;
1064 uint32_t templ;
1065 int c;
1066 int tempi;
1067 int trap;
1069 // printf("Run x86! %i %i\n",cycles,cycs);
1070 cycles+=cycs;
1071 // i86_Execute(cycs);
1072 // return;
1073 while (cycles>0)
1074 {
1075 // old83=old82;
1076 // old82=old8;
1077 // old8=oldpc|(oldcs<<16);
1078 // if (pc==0x96B && cs==0x9E040) { printf("Hit it\n"); output=1; timetolive=150; }
1079 // 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);
1080 cycdiff=cycles;
1081 timer_start_period(cycles);
1082 current_diff = 0;
1083 cycles-=nextcyc;
1084 // if (instime) pclog("Cycles %i %i\n",cycles,cycdiff);
1085 nextcyc=0;
1086 // if (output) printf("CLOCK %i %i\n",cycdiff,cycles);
1087 fetchclocks=0;
1088 oldcs=CS;
1089 oldpc=pc;
1090 opcodestart:
1091 opcode=FETCH();
1092 tempc=flags&C_FLAG;
1093 trap=flags&T_FLAG;
1094 pc--;
1095 // output=1;
1096 // 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);
1097 //#if 0
1098 if (output)
1099 {
1100 // if ((opcode!=0xF2 && opcode!=0xF3) || firstrepcycle)
1101 // {
1102 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]);
1103 skipnextprint=0;
1104 // ins++;
1105 // }
1106 }
1107 //#endif
1108 pc++;
1109 inhlt=0;
1110 // if (ins==500000) { dumpregs(); exit(0); }*/
1111 switch (opcode)
1112 {
1113 case 0x00: /*ADD 8,reg*/
1114 fetchea();
1115 /* if (!rmdat) pc--;
1116 if (!rmdat)
1117 {
1118 fatal("Crashed\n");
1119 // clear_keybuf();
1120 // readkey();
1121 }*/
1122 temp=geteab();
1123 setadd8(temp,getr8(reg));
1124 temp+=getr8(reg);
1125 seteab(temp);
1126 cycles-=((mod==3)?3:24);
1127 break;
1128 case 0x01: /*ADD 16,reg*/
1129 fetchea();
1130 tempw=geteaw();
1131 setadd16(tempw,regs[reg].w);
1132 tempw+=regs[reg].w;
1133 seteaw(tempw);
1134 cycles-=((mod==3)?3:24);
1135 break;
1136 case 0x02: /*ADD reg,8*/
1137 fetchea();
1138 temp=geteab();
1139 setadd8(getr8(reg),temp);
1140 setr8(reg,getr8(reg)+temp);
1141 cycles-=((mod==3)?3:13);
1142 break;
1143 case 0x03: /*ADD reg,16*/
1144 fetchea();
1145 tempw=geteaw();
1146 setadd16(regs[reg].w,tempw);
1147 regs[reg].w+=tempw;
1148 cycles-=((mod==3)?3:13);
1149 break;
1150 case 0x04: /*ADD AL,#8*/
1151 temp=FETCH();
1152 setadd8(AL,temp);
1153 AL+=temp;
1154 cycles-=4;
1155 break;
1156 case 0x05: /*ADD AX,#16*/
1157 tempw=getword();
1158 setadd16(AX,tempw);
1159 AX+=tempw;
1160 cycles-=4;
1161 break;
1163 case 0x06: /*PUSH ES*/
1164 if (ssegs) ss=oldss;
1165 writememw(ss,((SP-2)&0xFFFF),ES);
1166 SP-=2;
1167 cycles-=14;
1168 break;
1169 case 0x07: /*POP ES*/
1170 if (ssegs) ss=oldss;
1171 tempw=readmemw(ss,SP);
1172 loadseg(tempw,&_es);
1173 SP+=2;
1174 cycles-=12;
1175 break;
1177 case 0x08: /*OR 8,reg*/
1178 fetchea();
1179 temp=geteab();
1180 temp|=getr8(reg);
1181 setznp8(temp);
1182 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1183 seteab(temp);
1184 cycles-=((mod==3)?3:24);
1185 break;
1186 case 0x09: /*OR 16,reg*/
1187 fetchea();
1188 tempw=geteaw();
1189 tempw|=regs[reg].w;
1190 setznp16(tempw);
1191 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1192 seteaw(tempw);
1193 cycles-=((mod==3)?3:24);
1194 break;
1195 case 0x0A: /*OR reg,8*/
1196 fetchea();
1197 temp=geteab();
1198 temp|=getr8(reg);
1199 setznp8(temp);
1200 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1201 setr8(reg,temp);
1202 cycles-=((mod==3)?3:13);
1203 break;
1204 case 0x0B: /*OR reg,16*/
1205 fetchea();
1206 tempw=geteaw();
1207 tempw|=regs[reg].w;
1208 setznp16(tempw);
1209 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1210 regs[reg].w=tempw;
1211 cycles-=((mod==3)?3:13);
1212 break;
1213 case 0x0C: /*OR AL,#8*/
1214 AL|=FETCH();
1215 setznp8(AL);
1216 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1217 cycles-=4;
1218 break;
1219 case 0x0D: /*OR AX,#16*/
1220 AX|=getword();
1221 setznp16(AX);
1222 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1223 cycles-=4;
1224 break;
1226 case 0x0E: /*PUSH CS*/
1227 if (ssegs) ss=oldss;
1228 writememw(ss,((SP-2)&0xFFFF),CS);
1229 SP-=2;
1230 cycles-=14;
1231 break;
1232 case 0x0F: /*POP CS - 8088/8086 only*/
1233 if (ssegs) ss=oldss;
1234 tempw=readmemw(ss,SP);
1235 loadseg(tempw,&_cs);
1236 SP+=2;
1237 cycles-=12;
1238 break;
1240 case 0x10: /*ADC 8,reg*/
1241 fetchea();
1242 temp=geteab();
1243 temp2=getr8(reg);
1244 setadc8(temp,temp2);
1245 temp+=temp2+tempc;
1246 seteab(temp);
1247 cycles-=((mod==3)?3:24);
1248 break;
1249 case 0x11: /*ADC 16,reg*/
1250 fetchea();
1251 tempw=geteaw();
1252 tempw2=regs[reg].w;
1253 setadc16(tempw,tempw2);
1254 tempw+=tempw2+tempc;
1255 seteaw(tempw);
1256 cycles-=((mod==3)?3:24);
1257 break;
1258 case 0x12: /*ADC reg,8*/
1259 fetchea();
1260 temp=geteab();
1261 setadc8(getr8(reg),temp);
1262 setr8(reg,getr8(reg)+temp+tempc);
1263 cycles-=((mod==3)?3:13);
1264 break;
1265 case 0x13: /*ADC reg,16*/
1266 fetchea();
1267 tempw=geteaw();
1268 setadc16(regs[reg].w,tempw);
1269 regs[reg].w+=tempw+tempc;
1270 cycles-=((mod==3)?3:13);
1271 break;
1272 case 0x14: /*ADC AL,#8*/
1273 tempw=FETCH();
1274 setadc8(AL,tempw);
1275 AL+=tempw+tempc;
1276 cycles-=4;
1277 break;
1278 case 0x15: /*ADC AX,#16*/
1279 tempw=getword();
1280 setadc16(AX,tempw);
1281 AX+=tempw+tempc;
1282 cycles-=4;
1283 break;
1285 case 0x16: /*PUSH SS*/
1286 if (ssegs) ss=oldss;
1287 writememw(ss,((SP-2)&0xFFFF),SS);
1288 SP-=2;
1289 cycles-=14;
1290 break;
1291 case 0x17: /*POP SS*/
1292 if (ssegs) ss=oldss;
1293 tempw=readmemw(ss,SP);
1294 loadseg(tempw,&_ss);
1295 SP+=2;
1296 noint=1;
1297 cycles-=12;
1298 // output=1;
1299 break;
1301 case 0x18: /*SBB 8,reg*/
1302 fetchea();
1303 temp=geteab();
1304 temp2=getr8(reg);
1305 setsbc8(temp,temp2);
1306 temp-=(temp2+tempc);
1307 seteab(temp);
1308 cycles-=((mod==3)?3:24);
1309 break;
1310 case 0x19: /*SBB 16,reg*/
1311 fetchea();
1312 tempw=geteaw();
1313 tempw2=regs[reg].w;
1314 // printf("%04X:%04X SBB %04X-%04X,%i\n",cs>>4,pc,tempw,tempw2,tempc);
1315 setsbc16(tempw,tempw2);
1316 tempw-=(tempw2+tempc);
1317 seteaw(tempw);
1318 cycles-=((mod==3)?3:24);
1319 break;
1320 case 0x1A: /*SBB reg,8*/
1321 fetchea();
1322 temp=geteab();
1323 setsbc8(getr8(reg),temp);
1324 setr8(reg,getr8(reg)-(temp+tempc));
1325 cycles-=((mod==3)?3:13);
1326 break;
1327 case 0x1B: /*SBB reg,16*/
1328 fetchea();
1329 tempw=geteaw();
1330 tempw2=regs[reg].w;
1331 // printf("%04X:%04X SBB %04X-%04X,%i\n",cs>>4,pc,tempw,tempw2,tempc);
1332 setsbc16(tempw2,tempw);
1333 tempw2-=(tempw+tempc);
1334 regs[reg].w=tempw2;
1335 cycles-=((mod==3)?3:13);
1336 break;
1337 case 0x1C: /*SBB AL,#8*/
1338 temp=FETCH();
1339 setsbc8(AL,temp);
1340 AL-=(temp+tempc);
1341 cycles-=4;
1342 break;
1343 case 0x1D: /*SBB AX,#16*/
1344 tempw=getword();
1345 setsbc16(AX,tempw);
1346 AX-=(tempw+tempc);
1347 cycles-=4;
1348 break;
1350 case 0x1E: /*PUSH DS*/
1351 if (ssegs) ss=oldss;
1352 writememw(ss,((SP-2)&0xFFFF),DS);
1353 SP-=2;
1354 cycles-=14;
1355 break;
1356 case 0x1F: /*POP DS*/
1357 if (ssegs) ss=oldss;
1358 tempw=readmemw(ss,SP);
1359 loadseg(tempw,&_ds);
1360 if (ssegs) oldds=ds;
1361 SP+=2;
1362 cycles-=12;
1363 break;
1365 case 0x20: /*AND 8,reg*/
1366 fetchea();
1367 temp=geteab();
1368 temp&=getr8(reg);
1369 setznp8(temp);
1370 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1371 seteab(temp);
1372 cycles-=((mod==3)?3:24);
1373 break;
1374 case 0x21: /*AND 16,reg*/
1375 fetchea();
1376 tempw=geteaw();
1377 tempw&=regs[reg].w;
1378 setznp16(tempw);
1379 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1380 seteaw(tempw);
1381 cycles-=((mod==3)?3:24);
1382 break;
1383 case 0x22: /*AND reg,8*/
1384 fetchea();
1385 temp=geteab();
1386 temp&=getr8(reg);
1387 setznp8(temp);
1388 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1389 setr8(reg,temp);
1390 cycles-=((mod==3)?3:13);
1391 break;
1392 case 0x23: /*AND reg,16*/
1393 fetchea();
1394 tempw=geteaw();
1395 tempw&=regs[reg].w;
1396 setznp16(tempw);
1397 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1398 regs[reg].w=tempw;
1399 cycles-=((mod==3)?3:13);
1400 break;
1401 case 0x24: /*AND AL,#8*/
1402 AL&=FETCH();
1403 setznp8(AL);
1404 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1405 cycles-=4;
1406 break;
1407 case 0x25: /*AND AX,#16*/
1408 AX&=getword();
1409 setznp16(AX);
1410 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1411 cycles-=4;
1412 break;
1414 case 0x26: /*ES:*/
1415 oldss=ss;
1416 oldds=ds;
1417 ds=ss=es;
1418 ssegs=2;
1419 cycles-=4;
1420 goto opcodestart;
1421 // break;
1423 case 0x27: /*DAA*/
1424 if ((flags&A_FLAG) || ((AL&0xF)>9))
1425 {
1426 tempi=((uint16_t)AL)+6;
1427 AL+=6;
1428 flags|=A_FLAG;
1429 if (tempi&0x100) flags|=C_FLAG;
1430 }
1431 // else
1432 // flags&=~A_FLAG;
1433 if ((flags&C_FLAG) || (AL>0x9F))
1434 {
1435 AL+=0x60;
1436 flags|=C_FLAG;
1437 }
1438 // else
1439 // flags&=~C_FLAG;
1440 setznp8(AL);
1441 cycles-=4;
1442 break;
1444 case 0x28: /*SUB 8,reg*/
1445 fetchea();
1446 temp=geteab();
1447 setsub8(temp,getr8(reg));
1448 temp-=getr8(reg);
1449 seteab(temp);
1450 cycles-=((mod==3)?3:24);
1451 break;
1452 case 0x29: /*SUB 16,reg*/
1453 fetchea();
1454 tempw=geteaw();
1455 // printf("%04X:%04X %04X-%04X\n",cs>>4,pc,tempw,regs[reg].w);
1456 setsub16(tempw,regs[reg].w);
1457 tempw-=regs[reg].w;
1458 seteaw(tempw);
1459 cycles-=((mod==3)?3:24);
1460 break;
1461 case 0x2A: /*SUB reg,8*/
1462 fetchea();
1463 temp=geteab();
1464 setsub8(getr8(reg),temp);
1465 setr8(reg,getr8(reg)-temp);
1466 cycles-=((mod==3)?3:13);
1467 break;
1468 case 0x2B: /*SUB reg,16*/
1469 fetchea();
1470 tempw=geteaw();
1471 // printf("%04X:%04X %04X-%04X\n",cs>>4,pc,regs[reg].w,tempw);
1472 setsub16(regs[reg].w,tempw);
1473 regs[reg].w-=tempw;
1474 cycles-=((mod==3)?3:13);
1475 break;
1476 case 0x2C: /*SUB AL,#8*/
1477 temp=FETCH();
1478 setsub8(AL,temp);
1479 AL-=temp;
1480 cycles-=4;
1481 break;
1482 case 0x2D: /*SUB AX,#16*/
1483 // printf("INS %i\n",ins);
1484 // output=1;
1485 tempw=getword();
1486 setsub16(AX,tempw);
1487 AX-=tempw;
1488 cycles-=4;
1489 break;
1490 case 0x2E: /*CS:*/
1491 oldss=ss;
1492 oldds=ds;
1493 ds=ss=cs;
1494 ssegs=2;
1495 cycles-=4;
1496 goto opcodestart;
1497 case 0x2F: /*DAS*/
1498 if ((flags&A_FLAG)||((AL&0xF)>9))
1499 {
1500 tempi=((uint16_t)AL)-6;
1501 AL-=6;
1502 flags|=A_FLAG;
1503 if (tempi&0x100) flags|=C_FLAG;
1504 }
1505 // else
1506 // flags&=~A_FLAG;
1507 if ((flags&C_FLAG)||(AL>0x9F))
1508 {
1509 AL-=0x60;
1510 flags|=C_FLAG;
1511 }
1512 // else
1513 // flags&=~C_FLAG;
1514 setznp8(AL);
1515 cycles-=4;
1516 break;
1517 case 0x30: /*XOR 8,reg*/
1518 fetchea();
1519 temp=geteab();
1520 temp^=getr8(reg);
1521 setznp8(temp);
1522 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1523 seteab(temp);
1524 cycles-=((mod==3)?3:24);
1525 break;
1526 case 0x31: /*XOR 16,reg*/
1527 fetchea();
1528 tempw=geteaw();
1529 tempw^=regs[reg].w;
1530 setznp16(tempw);
1531 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1532 seteaw(tempw);
1533 cycles-=((mod==3)?3:24);
1534 break;
1535 case 0x32: /*XOR reg,8*/
1536 fetchea();
1537 temp=geteab();
1538 temp^=getr8(reg);
1539 setznp8(temp);
1540 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1541 setr8(reg,temp);
1542 cycles-=((mod==3)?3:13);
1543 break;
1544 case 0x33: /*XOR reg,16*/
1545 fetchea();
1546 tempw=geteaw();
1547 tempw^=regs[reg].w;
1548 setznp16(tempw);
1549 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1550 regs[reg].w=tempw;
1551 cycles-=((mod==3)?3:13);
1552 break;
1553 case 0x34: /*XOR AL,#8*/
1554 AL^=FETCH();
1555 setznp8(AL);
1556 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1557 cycles-=4;
1558 break;
1559 case 0x35: /*XOR AX,#16*/
1560 AX^=getword();
1561 setznp16(AX);
1562 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1563 cycles-=4;
1564 break;
1566 case 0x36: /*SS:*/
1567 oldss=ss;
1568 oldds=ds;
1569 ds=ss=ss;
1570 ssegs=2;
1571 cycles-=4;
1572 goto opcodestart;
1573 // break;
1575 case 0x37: /*AAA*/
1576 if ((flags&A_FLAG)||((AL&0xF)>9))
1577 {
1578 AL+=6;
1579 AH++;
1580 flags|=(A_FLAG|C_FLAG);
1581 }
1582 else
1583 flags&=~(A_FLAG|C_FLAG);
1584 AL&=0xF;
1585 cycles-=8;
1586 break;
1588 case 0x38: /*CMP 8,reg*/
1589 fetchea();
1590 temp=geteab();
1591 // if (output) printf("CMP %02X-%02X\n",temp,getr8(reg));
1592 setsub8(temp,getr8(reg));
1593 cycles-=((mod==3)?3:13);
1594 break;
1595 case 0x39: /*CMP 16,reg*/
1596 fetchea();
1597 tempw=geteaw();
1598 // if (output) printf("CMP %04X-%04X\n",tempw,regs[reg].w);
1599 setsub16(tempw,regs[reg].w);
1600 cycles-=((mod==3)?3:13);
1601 break;
1602 case 0x3A: /*CMP reg,8*/
1603 fetchea();
1604 temp=geteab();
1605 // if (output) printf("CMP %02X-%02X\n",getr8(reg),temp);
1606 setsub8(getr8(reg),temp);
1607 cycles-=((mod==3)?3:13);
1608 break;
1609 case 0x3B: /*CMP reg,16*/
1610 fetchea();
1611 tempw=geteaw();
1612 // printf("CMP %04X-%04X\n",regs[reg].w,tempw);
1613 setsub16(regs[reg].w,tempw);
1614 cycles-=((mod==3)?3:13);
1615 break;
1616 case 0x3C: /*CMP AL,#8*/
1617 temp=FETCH();
1618 setsub8(AL,temp);
1619 cycles-=4;
1620 break;
1621 case 0x3D: /*CMP AX,#16*/
1622 tempw=getword();
1623 setsub16(AX,tempw);
1624 cycles-=4;
1625 break;
1627 case 0x3E: /*DS:*/
1628 oldss=ss;
1629 oldds=ds;
1630 ds=ss=ds;
1631 ssegs=2;
1632 cycles-=4;
1633 goto opcodestart;
1634 // break;
1636 case 0x3F: /*AAS*/
1637 if ((flags&A_FLAG)||((AL&0xF)>9))
1638 {
1639 AL-=6;
1640 AH--;
1641 flags|=(A_FLAG|C_FLAG);
1642 }
1643 else
1644 flags&=~(A_FLAG|C_FLAG);
1645 AL&=0xF;
1646 cycles-=8;
1647 break;
1649 case 0x40: case 0x41: case 0x42: case 0x43: /*INC r16*/
1650 case 0x44: case 0x45: case 0x46: case 0x47:
1651 setadd16nc(regs[opcode&7].w,1);
1652 regs[opcode&7].w++;
1653 cycles-=3;
1654 break;
1655 case 0x48: case 0x49: case 0x4A: case 0x4B: /*DEC r16*/
1656 case 0x4C: case 0x4D: case 0x4E: case 0x4F:
1657 setsub16nc(regs[opcode&7].w,1);
1658 regs[opcode&7].w--;
1659 cycles-=3;
1660 break;
1662 case 0x50: case 0x51: case 0x52: case 0x53: /*PUSH r16*/
1663 case 0x54: case 0x55: case 0x56: case 0x57:
1664 if (ssegs) ss=oldss;
1665 SP-=2;
1666 writememw(ss,SP,regs[opcode&7].w);
1667 cycles-=15;
1668 break;
1669 case 0x58: case 0x59: case 0x5A: case 0x5B: /*POP r16*/
1670 case 0x5C: case 0x5D: case 0x5E: case 0x5F:
1671 if (ssegs) ss=oldss;
1672 SP+=2;
1673 regs[opcode&7].w=readmemw(ss,(SP-2)&0xFFFF);
1674 cycles-=12;
1675 break;
1678 case 0x70: /*JO*/
1679 offset=(int8_t)FETCH();
1680 if (flags&V_FLAG) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1681 cycles-=4;
1682 break;
1683 case 0x71: /*JNO*/
1684 offset=(int8_t)FETCH();
1685 if (!(flags&V_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1686 cycles-=4;
1687 break;
1688 case 0x72: /*JB*/
1689 offset=(int8_t)FETCH();
1690 if (flags&C_FLAG) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1691 cycles-=4;
1692 break;
1693 case 0x73: /*JNB*/
1694 offset=(int8_t)FETCH();
1695 if (!(flags&C_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1696 cycles-=4;
1697 break;
1698 case 0x74: /*JE*/
1699 offset=(int8_t)FETCH();
1700 if (flags&Z_FLAG) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1701 cycles-=4;
1702 break;
1703 case 0x75: /*JNE*/
1704 offset=(int8_t)FETCH();
1705 cycles-=4;
1706 if (!(flags&Z_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1707 break;
1708 case 0x76: /*JBE*/
1709 offset=(int8_t)FETCH();
1710 if (flags&(C_FLAG|Z_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1711 cycles-=4;
1712 break;
1713 case 0x77: /*JNBE*/
1714 offset=(int8_t)FETCH();
1715 if (!(flags&(C_FLAG|Z_FLAG))) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1716 cycles-=4;
1717 break;
1718 case 0x78: /*JS*/
1719 offset=(int8_t)FETCH();
1720 if (flags&N_FLAG) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1721 cycles-=4;
1722 break;
1723 case 0x79: /*JNS*/
1724 offset=(int8_t)FETCH();
1725 if (!(flags&N_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1726 cycles-=4;
1727 break;
1728 case 0x7A: /*JP*/
1729 offset=(int8_t)FETCH();
1730 if (flags&P_FLAG) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1731 cycles-=4;
1732 break;
1733 case 0x7B: /*JNP*/
1734 offset=(int8_t)FETCH();
1735 if (!(flags&P_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1736 cycles-=4;
1737 break;
1738 case 0x7C: /*JL*/
1739 offset=(int8_t)FETCH();
1740 temp=(flags&N_FLAG)?1:0;
1741 temp2=(flags&V_FLAG)?1:0;
1742 if (temp!=temp2) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1743 cycles-=4;
1744 break;
1745 case 0x7D: /*JNL*/
1746 offset=(int8_t)FETCH();
1747 temp=(flags&N_FLAG)?1:0;
1748 temp2=(flags&V_FLAG)?1:0;
1749 if (temp==temp2) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1750 cycles-=4;
1751 break;
1752 case 0x7E: /*JLE*/
1753 offset=(int8_t)FETCH();
1754 temp=(flags&N_FLAG)?1:0;
1755 temp2=(flags&V_FLAG)?1:0;
1756 if ((flags&Z_FLAG) || (temp!=temp2)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1757 cycles-=4;
1758 break;
1759 case 0x7F: /*JNLE*/
1760 offset=(int8_t)FETCH();
1761 temp=(flags&N_FLAG)?1:0;
1762 temp2=(flags&V_FLAG)?1:0;
1763 if (!((flags&Z_FLAG) || (temp!=temp2))) { pc+=offset; cycles-=12; FETCHCLEAR(); }
1764 cycles-=4;
1765 break;
1767 case 0x80: case 0x82:
1768 fetchea();
1769 temp=geteab();
1770 temp2=FETCH();
1771 switch (rmdat&0x38)
1772 {
1773 case 0x00: /*ADD b,#8*/
1774 setadd8(temp,temp2);
1775 seteab(temp+temp2);
1776 cycles-=((mod==3)?4:23);
1777 break;
1778 case 0x08: /*OR b,#8*/
1779 temp|=temp2;
1780 setznp8(temp);
1781 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1782 seteab(temp);
1783 cycles-=((mod==3)?4:23);
1784 break;
1785 case 0x10: /*ADC b,#8*/
1786 // temp2+=(flags&C_FLAG);
1787 setadc8(temp,temp2);
1788 seteab(temp+temp2+tempc);
1789 cycles-=((mod==3)?4:23);
1790 break;
1791 case 0x18: /*SBB b,#8*/
1792 // temp2+=(flags&C_FLAG);
1793 setsbc8(temp,temp2);
1794 seteab(temp-(temp2+tempc));
1795 cycles-=((mod==3)?4:23);
1796 break;
1797 case 0x20: /*AND b,#8*/
1798 temp&=temp2;
1799 setznp8(temp);
1800 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1801 seteab(temp);
1802 cycles-=((mod==3)?4:23);
1803 break;
1804 case 0x28: /*SUB b,#8*/
1805 setsub8(temp,temp2);
1806 seteab(temp-temp2);
1807 cycles-=((mod==3)?4:23);
1808 break;
1809 case 0x30: /*XOR b,#8*/
1810 temp^=temp2;
1811 setznp8(temp);
1812 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1813 seteab(temp);
1814 cycles-=((mod==3)?4:23);
1815 break;
1816 case 0x38: /*CMP b,#8*/
1817 setsub8(temp,temp2);
1818 cycles-=((mod==3)?4:14);
1819 break;
1821 // default:
1822 // printf("Bad 80 opcode %02X\n",rmdat&0x38);
1823 // dumpregs();
1824 // exit(-1);
1825 }
1826 break;
1828 case 0x81:
1829 fetchea();
1830 tempw=geteaw();
1831 tempw2=getword();
1832 switch (rmdat&0x38)
1833 {
1834 case 0x00: /*ADD w,#16*/
1835 setadd16(tempw,tempw2);
1836 tempw+=tempw2;
1837 seteaw(tempw);
1838 cycles-=((mod==3)?4:23);
1839 break;
1840 case 0x08: /*OR w,#16*/
1841 tempw|=tempw2;
1842 setznp16(tempw);
1843 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1844 seteaw(tempw);
1845 cycles-=((mod==3)?4:23);
1846 break;
1847 case 0x10: /*ADC w,#16*/
1848 // tempw2+=(flags&C_FLAG);
1849 setadc16(tempw,tempw2);
1850 tempw+=tempw2+tempc;
1851 seteaw(tempw);
1852 cycles-=((mod==3)?4:23);
1853 break;
1854 case 0x20: /*AND w,#16*/
1855 tempw&=tempw2;
1856 setznp16(tempw);
1857 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1858 seteaw(tempw);
1859 cycles-=((mod==3)?4:23);
1860 break;
1861 case 0x18: /*SBB w,#16*/
1862 // tempw2+=(flags&C_FLAG);
1863 setsbc16(tempw,tempw2);
1864 seteaw(tempw-(tempw2+tempc));
1865 cycles-=((mod==3)?4:23);
1866 break;
1867 case 0x28: /*SUB w,#16*/
1868 setsub16(tempw,tempw2);
1869 tempw-=tempw2;
1870 seteaw(tempw);
1871 cycles-=((mod==3)?4:23);
1872 break;
1873 case 0x30: /*XOR w,#16*/
1874 tempw^=tempw2;
1875 setznp16(tempw);
1876 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1877 seteaw(tempw);
1878 cycles-=((mod==3)?4:23);
1879 break;
1880 case 0x38: /*CMP w,#16*/
1881 // printf("CMP %04X %04X\n",tempw,tempw2);
1882 setsub16(tempw,tempw2);
1883 cycles-=((mod==3)?4:14);
1884 break;
1886 // default:
1887 // printf("Bad 81 opcode %02X\n",rmdat&0x38);
1888 // dumpregs();
1889 // exit(-1);
1890 }
1891 break;
1893 case 0x83:
1894 fetchea();
1895 tempw=geteaw();
1896 tempw2=FETCH();
1897 if (tempw2&0x80) tempw2|=0xFF00;
1898 switch (rmdat&0x38)
1899 {
1900 case 0x00: /*ADD w,#8*/
1901 setadd16(tempw,tempw2);
1902 tempw+=tempw2;
1903 seteaw(tempw);
1904 cycles-=((mod==3)?4:23);
1905 break;
1906 case 0x08: /*OR w,#8*/
1907 tempw|=tempw2;
1908 setznp16(tempw);
1909 seteaw(tempw);
1910 flags&=~(C_FLAG|A_FLAG|V_FLAG);
1911 cycles-=((mod==3)?4:23);
1912 break;
1913 case 0x10: /*ADC w,#8*/
1914 // tempw2+=(flags&C_FLAG);
1915 setadc16(tempw,tempw2);
1916 tempw+=tempw2+tempc;
1917 seteaw(tempw);
1918 cycles-=((mod==3)?4:23);
1919 break;
1920 case 0x18: /*SBB w,#8*/
1921 // tempw2+=(flags&C_FLAG);
1922 setsbc16(tempw,tempw2);
1923 tempw-=(tempw2+tempc);
1924 seteaw(tempw);
1925 cycles-=((mod==3)?4:23);
1926 break;
1927 case 0x20: /*AND w,#8*/
1928 tempw&=tempw2;
1929 setznp16(tempw);
1930 seteaw(tempw);
1931 cycles-=((mod==3)?4:23);
1932 flags&=~(C_FLAG|A_FLAG|V_FLAG);
1933 break;
1934 case 0x28: /*SUB w,#8*/
1935 setsub16(tempw,tempw2);
1936 tempw-=tempw2;
1937 seteaw(tempw);
1938 cycles-=((mod==3)?4:23);
1939 break;
1940 case 0x30: /*XOR w,#8*/
1941 tempw^=tempw2;
1942 setznp16(tempw);
1943 seteaw(tempw);
1944 cycles-=((mod==3)?4:23);
1945 flags&=~(C_FLAG|A_FLAG|V_FLAG);
1946 break;
1947 case 0x38: /*CMP w,#8*/
1948 setsub16(tempw,tempw2);
1949 cycles-=((mod==3)?4:14);
1950 break;
1952 // default:
1953 // printf("Bad 83 opcode %02X\n",rmdat&0x38);
1954 // dumpregs();
1955 // exit(-1);
1956 }
1957 break;
1959 case 0x84: /*TEST b,reg*/
1960 fetchea();
1961 temp=geteab();
1962 temp2=getr8(reg);
1963 setznp8(temp&temp2);
1964 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1965 cycles-=((mod==3)?3:13);
1966 break;
1967 case 0x85: /*TEST w,reg*/
1968 fetchea();
1969 tempw=geteaw();
1970 tempw2=regs[reg].w;
1971 setznp16(tempw&tempw2);
1972 flags&=~(C_FLAG|V_FLAG|A_FLAG);
1973 cycles-=((mod==3)?3:13);
1974 break;
1975 case 0x86: /*XCHG b,reg*/
1976 fetchea();
1977 temp=geteab();
1978 seteab(getr8(reg));
1979 setr8(reg,temp);
1980 cycles-=((mod==3)?4:25);
1981 break;
1982 case 0x87: /*XCHG w,reg*/
1983 fetchea();
1984 tempw=geteaw();
1985 seteaw(regs[reg].w);
1986 regs[reg].w=tempw;
1987 cycles-=((mod==3)?4:25);
1988 break;
1990 case 0x88: /*MOV b,reg*/
1991 fetchea();
1992 seteab(getr8(reg));
1993 cycles-=((mod==3)?2:13);
1994 break;
1995 case 0x89: /*MOV w,reg*/
1996 fetchea();
1997 seteaw(regs[reg].w);
1998 cycles-=((mod==3)?2:13);
1999 break;
2000 case 0x8A: /*MOV reg,b*/
2001 fetchea();
2002 temp=geteab();
2003 setr8(reg,temp);
2004 cycles-=((mod==3)?2:12);
2005 break;
2006 case 0x8B: /*MOV reg,w*/
2007 fetchea();
2008 tempw=geteaw();
2009 regs[reg].w=tempw;
2010 cycles-=((mod==3)?2:12);
2011 break;
2013 case 0x8C: /*MOV w,sreg*/
2014 fetchea();
2015 switch (rmdat&0x38)
2016 {
2017 case 0x00: /*ES*/
2018 seteaw(ES);
2019 break;
2020 case 0x08: /*CS*/
2021 seteaw(CS);
2022 break;
2023 case 0x18: /*DS*/
2024 if (ssegs) ds=oldds;
2025 seteaw(DS);
2026 break;
2027 case 0x10: /*SS*/
2028 if (ssegs) ss=oldss;
2029 seteaw(SS);
2030 break;
2031 }
2032 cycles-=((mod==3)?2:13);
2033 break;
2035 case 0x8D: /*LEA*/
2036 fetchea();
2037 regs[reg].w=eaaddr;
2038 cycles-=2;
2039 break;
2041 case 0x8E: /*MOV sreg,w*/
2042 // if (output) printf("MOV %04X ",pc);
2043 fetchea();
2044 // if (output) printf("%04X %02X\n",pc,rmdat);
2045 switch (rmdat&0x38)
2046 {
2047 case 0x00: /*ES*/
2048 tempw=geteaw();
2049 loadseg(tempw,&_es);
2050 break;
2051 case 0x08: /*CS - 8088/8086 only*/
2052 tempw=geteaw();
2053 loadseg(tempw,&_cs);
2054 break;
2055 case 0x18: /*DS*/
2056 tempw=geteaw();
2057 loadseg(tempw,&_ds);
2058 if (ssegs) oldds=ds;
2059 break;
2060 case 0x10: /*SS*/
2061 tempw=geteaw();
2062 loadseg(tempw,&_ss);
2063 if (ssegs) oldss=ss;
2064 // printf("LOAD SS %04X %04X\n",tempw,SS);
2065 // printf("SS loaded with %04X %04X:%04X %04X %04X %04X\n",ss>>4,cs>>4,pc,CX,DX,es>>4);
2066 break;
2067 }
2068 cycles-=((mod==3)?2:12);
2069 skipnextprint=1;
2070 noint=1;
2071 break;
2073 case 0x8F: /*POPW*/
2074 fetchea();
2075 if (ssegs) ss=oldss;
2076 tempw=readmemw(ss,SP);
2077 SP+=2;
2078 seteaw(tempw);
2079 cycles-=25;
2080 break;
2082 case 0x90: /*NOP*/
2083 cycles-=3;
2084 break;
2086 case 0x91: case 0x92: case 0x93: /*XCHG AX*/
2087 case 0x94: case 0x95: case 0x96: case 0x97:
2088 tempw=AX;
2089 AX=regs[opcode&7].w;
2090 regs[opcode&7].w=tempw;
2091 cycles-=3;
2092 break;
2094 case 0x98: /*CBW*/
2095 AH=(AL&0x80)?0xFF:0;
2096 cycles-=2;
2097 break;
2098 case 0x99: /*CWD*/
2099 DX=(AX&0x8000)?0xFFFF:0;
2100 cycles-=5;
2101 break;
2102 case 0x9A: /*CALL FAR*/
2103 tempw=getword();
2104 tempw2=getword();
2105 tempw3=CS;
2106 tempw4=pc;
2107 if (ssegs) ss=oldss;
2108 pc=tempw;
2109 // printf("0x9a");
2110 loadcs(tempw2);
2111 writememw(ss,(SP-2)&0xFFFF,tempw3);
2112 writememw(ss,(SP-4)&0xFFFF,tempw4);
2113 SP-=4;
2114 cycles-=36;
2115 FETCHCLEAR();
2116 break;
2117 case 0x9B: /*WAIT*/
2118 cycles-=4;
2119 break;
2120 case 0x9C: /*PUSHF*/
2121 if (ssegs) ss=oldss;
2122 writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
2123 SP-=2;
2124 cycles-=14;
2125 break;
2126 case 0x9D: /*POPF*/
2127 if (ssegs) ss=oldss;
2128 flags=readmemw(ss,SP)&0xFFF;
2129 SP+=2;
2130 cycles-=12;
2131 break;
2132 case 0x9E: /*SAHF*/
2133 flags=(flags&0xFF00)|AH;
2134 cycles-=4;
2135 break;
2136 case 0x9F: /*LAHF*/
2137 AH=flags&0xFF;
2138 cycles-=4;
2139 break;
2141 case 0xA0: /*MOV AL,(w)*/
2142 addr=getword();
2143 AL=readmemb(ds+addr);
2144 cycles-=14;
2145 break;
2146 case 0xA1: /*MOV AX,(w)*/
2147 addr=getword();
2148 // printf("Reading AX from %05X %04X:%04X\n",ds+addr,ds>>4,addr);
2149 AX=readmemw(ds,addr);
2150 cycles-=!4;
2151 break;
2152 case 0xA2: /*MOV (w),AL*/
2153 addr=getword();
2154 writememb(ds+addr,AL);
2155 cycles-=14;
2156 break;
2157 case 0xA3: /*MOV (w),AX*/
2158 addr=getword();
2159 // if (!addr) printf("Write !addr %04X:%04X\n",cs>>4,pc);
2160 writememw(ds,addr,AX);
2161 cycles-=14;
2162 break;
2164 case 0xA4: /*MOVSB*/
2165 temp=readmemb(ds+SI);
2166 writememb(es+DI,temp);
2167 if (flags&D_FLAG) { DI--; SI--; }
2168 else { DI++; SI++; }
2169 cycles-=18;
2170 break;
2171 case 0xA5: /*MOVSW*/
2172 tempw=readmemw(ds,SI);
2173 writememw(es,DI,tempw);
2174 if (flags&D_FLAG) { DI-=2; SI-=2; }
2175 else { DI+=2; SI+=2; }
2176 cycles-=18;
2177 break;
2178 case 0xA6: /*CMPSB*/
2179 temp =readmemb(ds+SI);
2180 temp2=readmemb(es+DI);
2181 setsub8(temp,temp2);
2182 if (flags&D_FLAG) { DI--; SI--; }
2183 else { DI++; SI++; }
2184 cycles-=30;
2185 break;
2186 case 0xA7: /*CMPSW*/
2187 tempw =readmemw(ds,SI);
2188 tempw2=readmemw(es,DI);
2189 // printf("CMPSW %04X %04X\n",tempw,tempw2);
2190 setsub16(tempw,tempw2);
2191 if (flags&D_FLAG) { DI-=2; SI-=2; }
2192 else { DI+=2; SI+=2; }
2193 cycles-=30;
2194 break;
2195 case 0xA8: /*TEST AL,#8*/
2196 temp=FETCH();
2197 setznp8(AL&temp);
2198 flags&=~(C_FLAG|V_FLAG|A_FLAG);
2199 cycles-=5;
2200 break;
2201 case 0xA9: /*TEST AX,#16*/
2202 tempw=getword();
2203 setznp16(AX&tempw);
2204 flags&=~(C_FLAG|V_FLAG|A_FLAG);
2205 cycles-=5;
2206 break;
2207 case 0xAA: /*STOSB*/
2208 writememb(es+DI,AL);
2209 if (flags&D_FLAG) DI--;
2210 else DI++;
2211 cycles-=11;
2212 break;
2213 case 0xAB: /*STOSW*/
2214 writememw(es,DI,AX);
2215 if (flags&D_FLAG) DI-=2;
2216 else DI+=2;
2217 cycles-=11;
2218 break;
2219 case 0xAC: /*LODSB*/
2220 AL=readmemb(ds+SI);
2221 // printf("LODSB %04X:%04X %02X %04X:%04X\n",cs>>4,pc,AL,ds>>4,SI);
2222 if (flags&D_FLAG) SI--;
2223 else SI++;
2224 cycles-=16;
2225 break;
2226 case 0xAD: /*LODSW*/
2227 // if (times) printf("LODSW %04X:%04X\n",cs>>4,pc);
2228 AX=readmemw(ds,SI);
2229 if (flags&D_FLAG) SI-=2;
2230 else SI+=2;
2231 cycles-=16;
2232 break;
2233 case 0xAE: /*SCASB*/
2234 temp=readmemb(es+DI);
2235 setsub8(AL,temp);
2236 if (flags&D_FLAG) DI--;
2237 else DI++;
2238 cycles-=19;
2239 break;
2240 case 0xAF: /*SCASW*/
2241 tempw=readmemw(es,DI);
2242 setsub16(AX,tempw);
2243 if (flags&D_FLAG) DI-=2;
2244 else DI+=2;
2245 cycles-=19;
2246 break;
2248 case 0xB0: /*MOV AL,#8*/
2249 AL=FETCH();
2250 cycles-=4;
2251 break;
2252 case 0xB1: /*MOV CL,#8*/
2253 CL=FETCH();
2254 cycles-=4;
2255 break;
2256 case 0xB2: /*MOV DL,#8*/
2257 DL=FETCH();
2258 cycles-=4;
2259 break;
2260 case 0xB3: /*MOV BL,#8*/
2261 BL=FETCH();
2262 cycles-=4;
2263 break;
2264 case 0xB4: /*MOV AH,#8*/
2265 AH=FETCH();
2266 cycles-=4;
2267 break;
2268 case 0xB5: /*MOV CH,#8*/
2269 CH=FETCH();
2270 cycles-=4;
2271 break;
2272 case 0xB6: /*MOV DH,#8*/
2273 DH=FETCH();
2274 cycles-=4;
2275 break;
2276 case 0xB7: /*MOV BH,#8*/
2277 BH=FETCH();
2278 cycles-=4;
2279 break;
2280 case 0xB8: case 0xB9: case 0xBA: case 0xBB: /*MOV reg,#16*/
2281 case 0xBC: case 0xBD: case 0xBE: case 0xBF:
2282 regs[opcode&7].w=getword();
2283 cycles-=4;
2284 break;
2286 case 0xC2: /*RET*/
2287 tempw=getword();
2288 if (ssegs) ss=oldss;
2289 pc=readmemw(ss,SP);
2290 // printf("C2\n");
2291 // printf("RET to %04X\n",pc);
2292 SP+=2+tempw;
2293 cycles-=24;
2294 FETCHCLEAR();
2295 break;
2296 case 0xC3: /*RET*/
2297 if (ssegs) ss=oldss;
2298 pc=readmemw(ss,SP);
2299 // printf("C3\n");
2300 // if (output) printf("RET to %04X %05X\n",pc,ss+SP);
2301 SP+=2;
2302 cycles-=20;
2303 FETCHCLEAR();
2304 break;
2305 case 0xC4: /*LES*/
2306 fetchea();
2307 regs[reg].w=readmemw(easeg,eaaddr); //geteaw();
2308 tempw=readmemw(easeg,(eaaddr+2)&0xFFFF); //geteaw2();
2309 loadseg(tempw,&_es);
2310 cycles-=24;
2311 break;
2312 case 0xC5: /*LDS*/
2313 fetchea();
2314 regs[reg].w=readmemw(easeg,eaaddr);
2315 tempw=readmemw(easeg,(eaaddr+2)&0xFFFF);
2316 loadseg(tempw,&_ds);
2317 if (ssegs) oldds=ds;
2318 cycles-=24;
2319 break;
2320 case 0xC6: /*MOV b,#8*/
2321 fetchea();
2322 temp=FETCH();
2323 seteab(temp);
2324 cycles-=((mod==3)?4:14);
2325 break;
2326 case 0xC7: /*MOV w,#16*/
2327 fetchea();
2328 tempw=getword();
2329 seteaw(tempw);
2330 cycles-=((mod==3)?4:14);
2331 break;
2333 case 0xCA: /*RETF*/
2334 tempw=getword();
2335 if (ssegs) ss=oldss;
2336 pc=readmemw(ss,SP);
2337 // printf("CA\n");
2338 loadcs(readmemw(ss,SP+2));
2339 SP+=4;
2340 SP+=tempw;
2341 cycles-=33;
2342 FETCHCLEAR();
2343 break;
2344 case 0xCB: /*RETF*/
2345 if (ssegs) ss=oldss;
2346 pc=readmemw(ss,SP);
2347 // printf("CB\n");
2348 loadcs(readmemw(ss,SP+2));
2349 SP+=4;
2350 cycles-=34;
2351 FETCHCLEAR();
2352 break;
2353 case 0xCC: /*INT 3*/
2354 if (ssegs) ss=oldss;
2355 writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
2356 writememw(ss,((SP-4)&0xFFFF),CS);
2357 writememw(ss,((SP-6)&0xFFFF),pc);
2358 SP-=6;
2359 addr=3<<2;
2360 flags&=~I_FLAG;
2361 flags&=~T_FLAG;
2362 // printf("CC %04X:%04X ",CS,pc);
2363 pc=readmemw(0,addr);
2364 loadcs(readmemw(0,addr+2));
2365 FETCHCLEAR();
2366 // printf("%04X:%04X\n",CS,pc);
2367 cycles-=72;
2368 break;
2369 case 0xCD: /*INT*/
2370 lastpc=pc;
2371 lastcs=CS;
2372 temp=FETCH();
2374 if (ssegs) ss=oldss;
2375 writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
2376 writememw(ss,((SP-4)&0xFFFF),CS);
2377 writememw(ss,((SP-6)&0xFFFF),pc);
2378 flags&=~T_FLAG;
2379 SP-=6;
2380 addr=temp<<2;
2381 pc=readmemw(0,addr);
2383 loadcs(readmemw(0,addr+2));
2384 FETCHCLEAR();
2386 cycles-=71;
2387 break;
2388 case 0xCF: /*IRET*/
2389 if (ssegs) ss=oldss;
2390 tempw=CS;
2391 tempw2=pc;
2392 pc=readmemw(ss,SP);
2393 // printf("CF\n");
2394 loadcs(readmemw(ss,((SP+2)&0xFFFF)));
2395 flags=readmemw(ss,((SP+4)&0xFFFF))&0xFFF;
2396 SP+=6;
2397 cycles-=44;
2398 FETCHCLEAR();
2399 nmi_enable = 1;
2400 break;
2401 case 0xD0:
2402 fetchea();
2403 temp=geteab();
2404 switch (rmdat&0x38)
2405 {
2406 case 0x00: /*ROL b,1*/
2407 if (temp&0x80) flags|=C_FLAG;
2408 else flags&=~C_FLAG;
2409 temp<<=1;
2410 if (flags&C_FLAG) temp|=1;
2411 seteab(temp);
2412 // setznp8(temp);
2413 if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
2414 else flags&=~V_FLAG;
2415 cycles-=((mod==3)?2:23);
2416 break;
2417 case 0x08: /*ROR b,1*/
2418 if (temp&1) flags|=C_FLAG;
2419 else flags&=~C_FLAG;
2420 temp>>=1;
2421 if (flags&C_FLAG) temp|=0x80;
2422 seteab(temp);
2423 // setznp8(temp);
2424 if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
2425 else flags&=~V_FLAG;
2426 cycles-=((mod==3)?2:23);
2427 break;
2428 case 0x10: /*RCL b,1*/
2429 temp2=flags&C_FLAG;
2430 if (temp&0x80) flags|=C_FLAG;
2431 else flags&=~C_FLAG;
2432 temp<<=1;
2433 if (temp2) temp|=1;
2434 seteab(temp);
2435 // setznp8(temp);
2436 if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
2437 else flags&=~V_FLAG;
2438 cycles-=((mod==3)?2:23);
2439 break;
2440 case 0x18: /*RCR b,1*/
2441 temp2=flags&C_FLAG;
2442 if (temp&1) flags|=C_FLAG;
2443 else flags&=~C_FLAG;
2444 temp>>=1;
2445 if (temp2) temp|=0x80;
2446 seteab(temp);
2447 // setznp8(temp);
2448 if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
2449 else flags&=~V_FLAG;
2450 cycles-=((mod==3)?2:23);
2451 break;
2452 case 0x20: case 0x30: /*SHL b,1*/
2453 if (temp&0x80) flags|=C_FLAG;
2454 else flags&=~C_FLAG;
2455 if ((temp^(temp<<1))&0x80) flags|=V_FLAG;
2456 else flags&=~V_FLAG;
2457 temp<<=1;
2458 seteab(temp);
2459 setznp8(temp);
2460 cycles-=((mod==3)?2:23);
2461 flags|=A_FLAG;
2462 break;
2463 case 0x28: /*SHR b,1*/
2464 if (temp&1) flags|=C_FLAG;
2465 else flags&=~C_FLAG;
2466 if (temp&0x80) flags|=V_FLAG;
2467 else flags&=~V_FLAG;
2468 temp>>=1;
2469 seteab(temp);
2470 setznp8(temp);
2471 cycles-=((mod==3)?2:23);
2472 flags|=A_FLAG;
2473 break;
2474 case 0x38: /*SAR b,1*/
2475 if (temp&1) flags|=C_FLAG;
2476 else flags&=~C_FLAG;
2477 temp>>=1;
2478 if (temp&0x40) temp|=0x80;
2479 seteab(temp);
2480 setznp8(temp);
2481 cycles-=((mod==3)?2:23);
2482 flags|=A_FLAG;
2483 flags&=~V_FLAG;
2484 break;
2486 // default:
2487 // printf("Bad D0 opcode %02X\n",rmdat&0x38);
2488 // dumpregs();
2489 // exit(-1);
2490 }
2491 break;
2493 case 0xD1:
2494 fetchea();
2495 tempw=geteaw();
2496 switch (rmdat&0x38)
2497 {
2498 case 0x00: /*ROL w,1*/
2499 if (tempw&0x8000) flags|=C_FLAG;
2500 else flags&=~C_FLAG;
2501 tempw<<=1;
2502 if (flags&C_FLAG) tempw|=1;
2503 seteaw(tempw);
2504 // setznp16(tempw);
2505 if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
2506 else flags&=~V_FLAG;
2507 cycles-=((mod==3)?2:23);
2508 break;
2509 case 0x08: /*ROR w,1*/
2510 if (tempw&1) flags|=C_FLAG;
2511 else flags&=~C_FLAG;
2512 tempw>>=1;
2513 if (flags&C_FLAG) tempw|=0x8000;
2514 seteaw(tempw);
2515 // setznp16(tempw);
2516 if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
2517 else flags&=~V_FLAG;
2518 cycles-=((mod==3)?2:23);
2519 break;
2520 case 0x10: /*RCL w,1*/
2521 temp2=flags&C_FLAG;
2522 if (tempw&0x8000) flags|=C_FLAG;
2523 else flags&=~C_FLAG;
2524 tempw<<=1;
2525 if (temp2) tempw|=1;
2526 seteaw(tempw);
2527 if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
2528 else flags&=~V_FLAG;
2529 cycles-=((mod==3)?2:23);
2530 break;
2531 case 0x18: /*RCR w,1*/
2532 temp2=flags&C_FLAG;
2533 if (tempw&1) flags|=C_FLAG;
2534 else flags&=~C_FLAG;
2535 tempw>>=1;
2536 if (temp2) tempw|=0x8000;
2537 seteaw(tempw);
2538 // setznp16(tempw);
2539 if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
2540 else flags&=~V_FLAG;
2541 cycles-=((mod==3)?2:23);
2542 break;
2543 case 0x20: case 0x30: /*SHL w,1*/
2544 if (tempw&0x8000) flags|=C_FLAG;
2545 else flags&=~C_FLAG;
2546 if ((tempw^(tempw<<1))&0x8000) flags|=V_FLAG;
2547 else flags&=~V_FLAG;
2548 tempw<<=1;
2549 seteaw(tempw);
2550 setznp16(tempw);
2551 cycles-=((mod==3)?2:23);
2552 flags|=A_FLAG;
2553 break;
2554 case 0x28: /*SHR w,1*/
2555 if (tempw&1) flags|=C_FLAG;
2556 else flags&=~C_FLAG;
2557 if (tempw&0x8000) flags|=V_FLAG;
2558 else flags&=~V_FLAG;
2559 tempw>>=1;
2560 seteaw(tempw);
2561 setznp16(tempw);
2562 cycles-=((mod==3)?2:23);
2563 flags|=A_FLAG;
2564 break;
2566 case 0x38: /*SAR w,1*/
2567 if (tempw&1) flags|=C_FLAG;
2568 else flags&=~C_FLAG;
2569 tempw>>=1;
2570 if (tempw&0x4000) tempw|=0x8000;
2571 seteaw(tempw);
2572 setznp16(tempw);
2573 cycles-=((mod==3)?2:23);
2574 flags|=A_FLAG;
2575 flags&=~V_FLAG;
2576 break;
2578 // default:
2579 // printf("Bad D1 opcode %02X\n",rmdat&0x38);
2580 // dumpregs();
2581 // exit(-1);
2582 }
2583 break;
2585 case 0xD2:
2586 fetchea();
2587 temp=geteab();
2588 c=CL;
2589 // cycles-=c;
2590 if (!c) break;
2591 // if (c>7) printf("Shiftb %i %02X\n",rmdat&0x38,c);
2592 switch (rmdat&0x38)
2593 {
2594 case 0x00: /*ROL b,CL*/
2595 while (c>0)
2596 {
2597 temp2=(temp&0x80)?1:0;
2598 temp=(temp<<1)|temp2;
2599 c--;
2600 cycles-=4;
2601 }
2602 if (temp2) flags|=C_FLAG;
2603 else flags&=~C_FLAG;
2604 seteab(temp);
2605 // setznp8(temp);
2606 if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
2607 else flags&=~V_FLAG;
2608 cycles-=((mod==3)?8:28);
2609 break;
2610 case 0x08: /*ROR b,CL*/
2611 while (c>0)
2612 {
2613 temp2=temp&1;
2614 temp>>=1;
2615 if (temp2) temp|=0x80;
2616 c--;
2617 cycles-=4;
2618 }
2619 if (temp2) flags|=C_FLAG;
2620 else flags&=~C_FLAG;
2621 seteab(temp);
2622 if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
2623 else flags&=~V_FLAG;
2624 cycles-=((mod==3)?8:28);
2625 break;
2626 case 0x10: /*RCL b,CL*/
2627 // printf("RCL %i %02X %02X\n",c,CL,temp);
2628 while (c>0)
2629 {
2630 templ=flags&C_FLAG;
2631 temp2=temp&0x80;
2632 temp<<=1;
2633 if (temp2) flags|=C_FLAG;
2634 else flags&=~C_FLAG;
2635 if (templ) temp|=1;
2636 c--;
2637 cycles-=4;
2638 }
2639 // printf("Now %02X\n",temp);
2640 seteab(temp);
2641 if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
2642 else flags&=~V_FLAG;
2643 cycles-=((mod==3)?8:28);
2644 break;
2645 case 0x18: /*RCR b,CL*/
2646 while (c>0)
2647 {
2648 templ=flags&C_FLAG;
2649 temp2=temp&1;
2650 temp>>=1;
2651 if (temp2) flags|=C_FLAG;
2652 else flags&=~C_FLAG;
2653 if (templ) temp|=0x80;
2654 c--;
2655 cycles-=4;
2656 }
2657 // if (temp2) flags|=C_FLAG;
2658 // else flags&=~C_FLAG;
2659 seteab(temp);
2660 if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
2661 else flags&=~V_FLAG;
2662 cycles-=((mod==3)?8:28);
2663 break;
2664 case 0x20: case 0x30: /*SHL b,CL*/
2665 if ((temp<<(c-1))&0x80) flags|=C_FLAG;
2666 else flags&=~C_FLAG;
2667 temp<<=c;
2668 seteab(temp);
2669 setznp8(temp);
2670 cycles-=(c*4);
2671 cycles-=((mod==3)?8:28);
2672 flags|=A_FLAG;
2673 break;
2674 case 0x28: /*SHR b,CL*/
2675 if ((temp>>(c-1))&1) flags|=C_FLAG;
2676 else flags&=~C_FLAG;
2677 temp>>=c;
2678 seteab(temp);
2679 setznp8(temp);
2680 cycles-=(c*4);
2681 cycles-=((mod==3)?8:28);
2682 flags|=A_FLAG;
2683 break;
2684 case 0x38: /*SAR b,CL*/
2685 if ((temp>>(c-1))&1) flags|=C_FLAG;
2686 else flags&=~C_FLAG;
2687 while (c>0)
2688 {
2689 temp>>=1;
2690 if (temp&0x40) temp|=0x80;
2691 c--;
2692 cycles-=4;
2693 }
2694 seteab(temp);
2695 setznp8(temp);
2696 cycles-=((mod==3)?8:28);
2697 flags|=A_FLAG;
2698 break;
2700 // default:
2701 // printf("Bad D2 opcode %02X\n",rmdat&0x38);
2702 // dumpregs();
2703 // exit(-1);
2704 }
2705 break;
2707 case 0xD3:
2708 fetchea();
2709 tempw=geteaw();
2710 c=CL;
2711 // cycles-=c;
2712 if (!c) break;
2713 // if (c>15) printf("Shiftw %i %02X\n",rmdat&0x38,c);
2714 switch (rmdat&0x38)
2715 {
2716 case 0x00: /*ROL w,CL*/
2717 while (c>0)
2718 {
2719 temp=(tempw&0x8000)?1:0;
2720 tempw=(tempw<<1)|temp;
2721 c--;
2722 cycles-=4;
2723 }
2724 if (temp) flags|=C_FLAG;
2725 else flags&=~C_FLAG;
2726 seteaw(tempw);
2727 if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
2728 else flags&=~V_FLAG;
2729 cycles-=((mod==3)?8:28);
2730 break;
2731 case 0x08: /*ROR w,CL*/
2732 while (c>0)
2733 {
2734 tempw2=(tempw&1)?0x8000:0;
2735 tempw=(tempw>>1)|tempw2;
2736 c--;
2737 cycles-=4;
2738 }
2739 if (tempw2) flags|=C_FLAG;
2740 else flags&=~C_FLAG;
2741 seteaw(tempw);
2742 if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
2743 else flags&=~V_FLAG;
2744 cycles-=((mod==3)?8:28);
2745 break;
2746 case 0x10: /*RCL w,CL*/
2747 while (c>0)
2748 {
2749 templ=flags&C_FLAG;
2750 if (tempw&0x8000) flags|=C_FLAG;
2751 else flags&=~C_FLAG;
2752 tempw=(tempw<<1)|templ;
2753 c--;
2754 cycles-=4;
2755 }
2756 if (temp) flags|=C_FLAG;
2757 else flags&=~C_FLAG;
2758 seteaw(tempw);
2759 if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
2760 else flags&=~V_FLAG;
2761 cycles-=((mod==3)?8:28);
2762 break;
2763 case 0x18: /*RCR w,CL*/
2764 while (c>0)
2765 {
2766 templ=flags&C_FLAG;
2767 tempw2=(templ&1)?0x8000:0;
2768 if (tempw&1) flags|=C_FLAG;
2769 else flags&=~C_FLAG;
2770 tempw=(tempw>>1)|tempw2;
2771 c--;
2772 cycles-=4;
2773 }
2774 if (tempw2) flags|=C_FLAG;
2775 else flags&=~C_FLAG;
2776 seteaw(tempw);
2777 if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
2778 else flags&=~V_FLAG;
2779 cycles-=((mod==3)?8:28);
2780 break;
2782 case 0x20: case 0x30: /*SHL w,CL*/
2783 if (c>16)
2784 {
2785 tempw=0;
2786 flags&=~C_FLAG;
2787 }
2788 else
2789 {
2790 if ((tempw<<(c-1))&0x8000) flags|=C_FLAG;
2791 else flags&=~C_FLAG;
2792 tempw<<=c;
2793 }
2794 seteaw(tempw);
2795 setznp16(tempw);
2796 cycles-=(c*4);
2797 cycles-=((mod==3)?8:28);
2798 flags|=A_FLAG;
2799 break;
2801 case 0x28: /*SHR w,CL*/
2802 if ((tempw>>(c-1))&1) flags|=C_FLAG;
2803 else flags&=~C_FLAG;
2804 tempw>>=c;
2805 seteaw(tempw);
2806 setznp16(tempw);
2807 cycles-=(c*4);
2808 cycles-=((mod==3)?8:28);
2809 flags|=A_FLAG;
2810 break;
2812 case 0x38: /*SAR w,CL*/
2813 tempw2=tempw&0x8000;
2814 if ((tempw>>(c-1))&1) flags|=C_FLAG;
2815 else flags&=~C_FLAG;
2816 while (c>0)
2817 {
2818 tempw=(tempw>>1)|tempw2;
2819 c--;
2820 cycles-=4;
2821 }
2822 seteaw(tempw);
2823 setznp16(tempw);
2824 cycles-=((mod==3)?8:28);
2825 flags|=A_FLAG;
2826 break;
2828 // default:
2829 // printf("Bad D3 opcode %02X\n",rmdat&0x38);
2830 // dumpregs();
2831 // exit(-1);
2832 }
2833 break;
2835 case 0xD4: /*AAM*/
2836 tempws=FETCH();
2837 AH=AL/tempws;
2838 AL%=tempws;
2839 setznp16(AX);
2840 cycles-=83;
2841 break;
2842 case 0xD5: /*AAD*/
2843 tempws=FETCH();
2844 AL=(AH*tempws)+AL;
2845 AH=0;
2846 setznp16(AX);
2847 cycles-=60;
2848 break;
2849 case 0xD7: /*XLAT*/
2850 addr=BX+AL;
2851 AL=readmemb(ds+addr);
2852 cycles-=11;
2853 break;
2854 case 0xD9: case 0xDA: case 0xDB: case 0xDD: /*ESCAPE*/
2855 case 0xDC: case 0xDE: case 0xDF: case 0xD8:
2856 fetchea();
2857 geteab();
2858 break;
2860 case 0xE0: /*LOOPNE*/
2861 offset=(int8_t)FETCH();
2862 CX--;
2863 if (CX && !(flags&Z_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
2864 cycles-=6;
2865 break;
2866 case 0xE1: /*LOOPE*/
2867 offset=(int8_t)FETCH();
2868 CX--;
2869 if (CX && (flags&Z_FLAG)) { pc+=offset; cycles-=12; FETCHCLEAR(); }
2870 cycles-=6;
2871 break;
2872 case 0xE2: /*LOOP*/
2873 // printf("LOOP start\n");
2874 offset=(int8_t)FETCH();
2875 CX--;
2876 if (CX) { pc+=offset; cycles-=12; FETCHCLEAR(); }
2877 cycles-=5;
2878 // printf("LOOP end!\n");
2879 break;
2880 case 0xE3: /*JCXZ*/
2881 offset=(int8_t)FETCH();
2882 if (!CX) { pc+=offset; cycles-=12; FETCHCLEAR(); }
2883 cycles-=6;
2884 break;
2886 case 0xE4: /*IN AL*/
2887 temp=FETCH();
2888 AL=inb(temp);
2889 cycles-=14;
2890 break;
2891 case 0xE5: /*IN AX*/
2892 temp=FETCH();
2893 AL=inb(temp);
2894 AH=inb(temp+1);
2895 cycles-=14;
2896 break;
2897 case 0xE6: /*OUT AL*/
2898 temp=FETCH();
2899 outb(temp,AL);
2900 cycles-=14;
2901 break;
2902 case 0xE7: /*OUT AX*/
2903 temp=FETCH();
2904 outb(temp,AL);
2905 outb(temp+1,AH);
2906 cycles-=14;
2907 break;
2909 case 0xE8: /*CALL rel 16*/
2910 tempw=getword();
2911 if (ssegs) ss=oldss;
2912 // writememb(ss+((SP-1)&0xFFFF),pc>>8);
2913 writememw(ss,((SP-2)&0xFFFF),pc);
2914 SP-=2;
2915 pc+=tempw;
2916 cycles-=23;
2917 FETCHCLEAR();
2918 break;
2919 case 0xE9: /*JMP rel 16*/
2920 // printf("PC was %04X\n",pc);
2921 pc+=getword();
2922 // printf("PC now %04X\n",pc);
2923 cycles-=15;
2924 FETCHCLEAR();
2925 break;
2926 case 0xEA: /*JMP far*/
2927 addr=getword();
2928 tempw=getword();
2929 pc=addr;
2930 // printf("EA\n");
2931 loadcs(tempw);
2932 // cs=loadcs(CS);
2933 // cs=CS<<4;
2934 cycles-=15;
2935 FETCHCLEAR();
2936 break;
2937 case 0xEB: /*JMP rel*/
2938 offset=(int8_t)FETCH();
2939 pc+=offset;
2940 cycles-=15;
2941 FETCHCLEAR();
2942 break;
2943 case 0xEC: /*IN AL,DX*/
2944 AL=inb(DX);
2945 cycles-=12;
2946 break;
2947 case 0xED: /*IN AX,DX*/
2948 AL=inb(DX);
2949 AH=inb(DX+1);
2950 cycles-=12;
2951 break;
2952 case 0xEE: /*OUT DX,AL*/
2953 outb(DX,AL);
2954 cycles-=12;
2955 break;
2956 case 0xEF: /*OUT DX,AX*/
2957 outb(DX,AL);
2958 outb(DX+1,AH);
2959 cycles-=12;
2960 break;
2962 case 0xF0: /*LOCK*/
2963 cycles-=4;
2964 break;
2966 case 0xF2: /*REPNE*/
2967 rep(0);
2968 break;
2969 case 0xF3: /*REPE*/
2970 rep(1);
2971 break;
2973 case 0xF4: /*HLT*/
2974 // printf("IN HLT!!!! %04X:%04X %08X %08X %08X\n",oldcs,oldpc,old8,old82,old83);
2975 /* if (!(flags & I_FLAG))
2976 {
2977 pclog("HLT\n");
2978 dumpregs();
2979 exit(-1);
2980 }*/
2981 inhlt=1;
2982 pc--;
2983 FETCHCLEAR();
2984 cycles-=2;
2985 break;
2986 case 0xF5: /*CMC*/
2987 flags^=C_FLAG;
2988 cycles-=2;
2989 break;
2991 case 0xF6:
2992 fetchea();
2993 temp=geteab();
2994 switch (rmdat&0x38)
2995 {
2996 case 0x00: /*TEST b,#8*/
2997 temp2=FETCH();
2998 temp&=temp2;
2999 setznp8(temp);
3000 flags&=~(C_FLAG|V_FLAG|A_FLAG);
3001 cycles-=((mod==3)?5:11);
3002 break;
3003 case 0x10: /*NOT b*/
3004 temp=~temp;
3005 seteab(temp);
3006 cycles-=((mod==3)?3:24);
3007 break;
3008 case 0x18: /*NEG b*/
3009 setsub8(0,temp);
3010 temp=0-temp;
3011 seteab(temp);
3012 cycles-=((mod==3)?3:24);
3013 break;
3014 case 0x20: /*MUL AL,b*/
3015 setznp8(AL);
3016 AX=AL*temp;
3017 if (AX) flags&=~Z_FLAG;
3018 else flags|=Z_FLAG;
3019 if (AH) flags|=(C_FLAG|V_FLAG);
3020 else flags&=~(C_FLAG|V_FLAG);
3021 cycles-=70;
3022 break;
3023 case 0x28: /*IMUL AL,b*/
3024 setznp8(AL);
3025 tempws=(int)((int8_t)AL)*(int)((int8_t)temp);
3026 AX=tempws&0xFFFF;
3027 if (AX) flags&=~Z_FLAG;
3028 else flags|=Z_FLAG;
3029 if (AH) flags|=(C_FLAG|V_FLAG);
3030 else flags&=~(C_FLAG|V_FLAG);
3031 cycles-=80;
3032 break;
3033 case 0x30: /*DIV AL,b*/
3034 tempw=AX;
3035 if (temp)
3036 {
3037 tempw2=tempw%temp;
3038 /* if (!tempw)
3039 {
3040 writememw((ss+SP)-2,flags|0xF000);
3041 writememw((ss+SP)-4,cs>>4);
3042 writememw((ss+SP)-6,pc);
3043 SP-=6;
3044 flags&=~I_FLAG;
3045 pc=readmemw(0);
3046 cs=readmemw(2)<<4;
3047 printf("Div by zero %04X:%04X\n",cs>>4,pc);
3048 // dumpregs();
3049 // exit(-1);
3050 }
3051 else
3052 {*/
3053 AH=tempw2;
3054 tempw/=temp;
3055 AL=tempw&0xFF;
3056 // }
3057 }
3058 else
3059 {
3060 printf("DIVb BY 0 %04X:%04X\n",cs>>4,pc);
3061 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3062 writememw(ss,(SP-4)&0xFFFF,CS);
3063 writememw(ss,(SP-6)&0xFFFF,pc);
3064 SP-=6;
3065 flags&=~I_FLAG;
3066 flags&=~T_FLAG;
3067 pc=readmemw(0,0);
3068 // printf("F6 30\n");
3069 loadcs(readmemw(0,2));
3070 FETCHCLEAR();
3071 // cs=loadcs(CS);
3072 // cs=CS<<4;
3073 // printf("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x30);
3074 // dumpregs();
3075 // exit(-1);
3076 }
3077 cycles-=80;
3078 break;
3079 case 0x38: /*IDIV AL,b*/
3080 tempws=(int)AX;
3081 if (temp)
3082 {
3083 tempw2=tempws%(int)((int8_t)temp);
3084 /* if (!tempw)
3085 {
3086 writememw((ss+SP)-2,flags|0xF000);
3087 writememw((ss+SP)-4,cs>>4);
3088 writememw((ss+SP)-6,pc);
3089 SP-=6;
3090 flags&=~I_FLAG;
3091 pc=readmemw(0);
3092 cs=readmemw(2)<<4;
3093 printf("Div by zero %04X:%04X\n",cs>>4,pc);
3094 }
3095 else
3096 {*/
3097 AH=tempw2&0xFF;
3098 tempws/=(int)((int8_t)temp);
3099 AL=tempws&0xFF;
3100 // }
3101 }
3102 else
3103 {
3104 printf("IDIVb BY 0 %04X:%04X\n",cs>>4,pc);
3105 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3106 writememw(ss,(SP-4)&0xFFFF,CS);
3107 writememw(ss,(SP-6)&0xFFFF,pc);
3108 SP-=6;
3109 flags&=~I_FLAG;
3110 flags&=~T_FLAG;
3111 pc=readmemw(0,0);
3112 // printf("F6 38\n");
3113 loadcs(readmemw(0,2));
3114 FETCHCLEAR();
3115 // cs=loadcs(CS);
3116 // cs=CS<<4;
3117 // printf("Div by zero %04X:%04X %02X %02X\n",cs>>4,pc,0xf6,0x38);
3118 }
3119 cycles-=101;
3120 break;
3122 // default:
3123 // printf("Bad F6 opcode %02X\n",rmdat&0x38);
3124 // dumpregs();
3125 // exit(-1);
3126 }
3127 break;
3129 case 0xF7:
3130 fetchea();
3131 tempw=geteaw();
3132 switch (rmdat&0x38)
3133 {
3134 case 0x00: /*TEST w*/
3135 tempw2=getword();
3136 setznp16(tempw&tempw2);
3137 flags&=~(C_FLAG|V_FLAG|A_FLAG);
3138 cycles-=((mod==3)?5:11);
3139 break;
3140 case 0x10: /*NOT w*/
3141 seteaw(~tempw);
3142 cycles-=((mod==3)?3:24);
3143 break;
3144 case 0x18: /*NEG w*/
3145 setsub16(0,tempw);
3146 tempw=0-tempw;
3147 seteaw(tempw);
3148 cycles-=((mod==3)?3:24);
3149 break;
3150 case 0x20: /*MUL AX,w*/
3151 setznp16(AX);
3152 templ=AX*tempw;
3153 // if (output) printf("%04X*%04X=%08X\n",AX,tempw,templ);
3154 AX=templ&0xFFFF;
3155 DX=templ>>16;
3156 if (AX|DX) flags&=~Z_FLAG;
3157 else flags|=Z_FLAG;
3158 if (DX) flags|=(C_FLAG|V_FLAG);
3159 else flags&=~(C_FLAG|V_FLAG);
3160 cycles-=118;
3161 break;
3162 case 0x28: /*IMUL AX,w*/
3163 setznp16(AX);
3164 // printf("IMUL %i %i ",(int)((int16_t)AX),(int)((int16_t)tempw));
3165 tempws=(int)((int16_t)AX)*(int)((int16_t)tempw);
3166 if ((tempws>>15) && ((tempws>>15)!=-1)) flags|=(C_FLAG|V_FLAG);
3167 else flags&=~(C_FLAG|V_FLAG);
3168 // printf("%i ",tempws);
3169 AX=tempws&0xFFFF;
3170 tempws=(uint16_t)(tempws>>16);
3171 DX=tempws&0xFFFF;
3172 // printf("%04X %04X\n",AX,DX);
3173 // dumpregs();
3174 // exit(-1);
3175 if (AX|DX) flags&=~Z_FLAG;
3176 else flags|=Z_FLAG;
3177 cycles-=128;
3178 break;
3179 case 0x30: /*DIV AX,w*/
3180 templ=(DX<<16)|AX;
3181 // printf("DIV %08X/%04X\n",templ,tempw);
3182 if (tempw)
3183 {
3184 tempw2=templ%tempw;
3185 DX=tempw2;
3186 templ/=tempw;
3187 AX=templ&0xFFFF;
3188 }
3189 else
3190 {
3191 printf("DIVw BY 0 %04X:%04X\n",cs>>4,pc);
3192 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3193 writememw(ss,(SP-4)&0xFFFF,CS);
3194 writememw(ss,(SP-6)&0xFFFF,pc);
3195 SP-=6;
3196 flags&=~I_FLAG;
3197 flags&=~T_FLAG;
3198 pc=readmemw(0,0);
3199 // printf("F7 30\n");
3200 loadcs(readmemw(0,2));
3201 FETCHCLEAR();
3202 }
3203 cycles-=144;
3204 break;
3205 case 0x38: /*IDIV AX,w*/
3206 tempws=(int)((DX<<16)|AX);
3207 // printf("IDIV %i %i ",tempws,tempw);
3208 if (tempw)
3209 {
3210 tempw2=tempws%(int)((int16_t)tempw);
3211 // printf("%04X ",tempw2);
3212 DX=tempw2;
3213 tempws/=(int)((int16_t)tempw);
3214 AX=tempws&0xFFFF;
3215 }
3216 else
3217 {
3218 printf("IDIVw BY 0 %04X:%04X\n",cs>>4,pc);
3219 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3220 writememw(ss,(SP-4)&0xFFFF,CS);
3221 writememw(ss,(SP-6)&0xFFFF,pc);
3222 SP-=6;
3223 flags&=~I_FLAG;
3224 flags&=~T_FLAG;
3225 pc=readmemw(0,0);
3226 // printf("F7 38\n");
3227 loadcs(readmemw(0,2));
3228 FETCHCLEAR();
3229 }
3230 cycles-=165;
3231 break;
3233 // default:
3234 // printf("Bad F7 opcode %02X\n",rmdat&0x38);
3235 // dumpregs();
3236 // exit(-1);
3237 }
3238 break;
3240 case 0xF8: /*CLC*/
3241 flags&=~C_FLAG;
3242 cycles-=2;
3243 break;
3244 case 0xF9: /*STC*/
3245 // printf("STC %04X\n",pc);
3246 flags|=C_FLAG;
3247 cycles-=2;
3248 break;
3249 case 0xFA: /*CLI*/
3250 flags&=~I_FLAG;
3251 // printf("CLI at %04X:%04X\n",cs>>4,pc);
3252 cycles-=3;
3253 break;
3254 case 0xFB: /*STI*/
3255 flags|=I_FLAG;
3256 // printf("STI at %04X:%04X\n",cs>>4,pc);
3257 cycles-=2;
3258 break;
3259 case 0xFC: /*CLD*/
3260 flags&=~D_FLAG;
3261 cycles-=2;
3262 break;
3263 case 0xFD: /*STD*/
3264 flags|=D_FLAG;
3265 cycles-=2;
3266 break;
3268 case 0xFE: /*INC/DEC b*/
3269 fetchea();
3270 temp=geteab();
3271 flags&=~V_FLAG;
3272 if (rmdat&0x38)
3273 {
3274 setsub8nc(temp,1);
3275 temp2=temp-1;
3276 if ((temp&0x80) && !(temp2&0x80)) flags|=V_FLAG;
3277 }
3278 else
3279 {
3280 setadd8nc(temp,1);
3281 temp2=temp+1;
3282 if ((temp2&0x80) && !(temp&0x80)) flags|=V_FLAG;
3283 }
3284 // setznp8(temp2);
3285 seteab(temp2);
3286 cycles-=((mod==3)?3:23);
3287 break;
3289 case 0xFF:
3290 fetchea();
3291 switch (rmdat&0x38)
3292 {
3293 case 0x00: /*INC w*/
3294 tempw=geteaw();
3295 setadd16nc(tempw,1);
3296 // setznp16(tempw+1);
3297 seteaw(tempw+1);
3298 cycles-=((mod==3)?3:23);
3299 break;
3300 case 0x08: /*DEC w*/
3301 tempw=geteaw();
3302 // setsub16(tempw,1);
3303 setsub16nc(tempw,1);
3304 // setznp16(tempw-1);
3305 seteaw(tempw-1);
3306 // if (output) printf("DEC - %04X\n",tempw);
3307 cycles-=((mod==3)?3:23);
3308 break;
3309 case 0x10: /*CALL*/
3310 tempw=geteaw();
3311 if (ssegs) ss=oldss;
3312 writememw(ss,(SP-2)&0xFFFF,pc);
3313 SP-=2;
3314 pc=tempw;
3315 // printf("FF 10\n");
3316 cycles-=((mod==3)?20:29);
3317 FETCHCLEAR();
3318 break;
3319 case 0x18: /*CALL far*/
3320 tempw=readmemw(easeg,eaaddr);
3321 tempw2=readmemw(easeg,(eaaddr+2)&0xFFFF); //geteaw2();
3322 tempw3=CS;
3323 tempw4=pc;
3324 if (ssegs) ss=oldss;
3325 pc=tempw;
3326 // printf("FF 18\n");
3327 loadcs(tempw2);
3328 writememw(ss,(SP-2)&0xFFFF,tempw3);
3329 writememw(ss,((SP-4)&0xFFFF),tempw4);
3330 SP-=4;
3331 cycles-=53;
3332 FETCHCLEAR();
3333 break;
3334 case 0x20: /*JMP*/
3335 pc=geteaw();
3336 // printf("FF 20\n");
3337 cycles-=((mod==3)?11:18);
3338 FETCHCLEAR();
3339 break;
3340 case 0x28: /*JMP far*/
3341 pc=readmemw(easeg,eaaddr); //geteaw();
3342 // printf("FF 28\n");
3343 loadcs(readmemw(easeg,(eaaddr+2)&0xFFFF)); //geteaw2();
3344 // cs=loadcs(CS);
3345 // cs=CS<<4;
3346 cycles-=24;
3347 FETCHCLEAR();
3348 break;
3349 case 0x30: /*PUSH w*/
3350 tempw=geteaw();
3351 // if (output) printf("PUSH %04X %i %02X %04X %04X %02X %02X\n",tempw,rm,rmdat,easeg,eaaddr,ram[0x22340+0x5638],ram[0x22340+0x5639]);
3352 if (ssegs) ss=oldss;
3353 writememw(ss,((SP-2)&0xFFFF),tempw);
3354 SP-=2;
3355 cycles-=((mod==3)?15:24);
3356 break;
3358 // default:
3359 // printf("Bad FF opcode %02X\n",rmdat&0x38);
3360 // dumpregs();
3361 // exit(-1);
3362 }
3363 break;
3365 default:
3366 FETCH();
3367 cycles-=8;
3368 break;
3370 /* printf("Bad opcode %02X at %04X:%04X from %04X:%04X %08X\n",opcode,cs>>4,pc,old8>>16,old8&0xFFFF,old82);
3371 dumpregs();
3372 exit(-1);*/
3373 }
3374 pc&=0xFFFF;
3376 /* if ((CS & 0xf000) == 0xa000)
3377 {
3378 dumpregs();
3379 exit(-1);
3380 }*/
3381 // output = 3;
3382 /* if (CS == 0xf000)
3383 {
3384 dumpregs();
3385 exit(-1);
3386 }
3387 output = 3;*/
3388 if (ssegs)
3389 {
3390 ds=oldds;
3391 ss=oldss;
3392 ssegs=0;
3393 }
3395 // output = 3;
3396 // if (instime) printf("%i %i %i %i\n",cycdiff,cycles,memcycs,fetchclocks);
3397 FETCHADD(((cycdiff-cycles)-memcycs)-fetchclocks);
3398 if ((cycdiff-cycles)<memcycs) cycles-=(memcycs-(cycdiff-cycles));
3399 if (romset==ROM_IBMPC)
3400 {
3401 if ((cs+pc)==0xFE4A7) /*You didn't seriously think I was going to emulate the cassette, did you?*/
3402 {
3403 CX=1;
3404 BX=0x500;
3405 }
3406 }
3407 memcycs=0;
3409 insc++;
3410 // output=(CS==0xEB9);
3411 clockhardware();
3414 if (trap && (flags&T_FLAG) && !noint)
3415 {
3416 // printf("TRAP!!! %04X:%04X\n",CS,pc);
3417 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3418 writememw(ss,(SP-4)&0xFFFF,CS);
3419 writememw(ss,(SP-6)&0xFFFF,pc);
3420 SP-=6;
3421 addr=1<<2;
3422 flags&=~I_FLAG;
3423 flags&=~T_FLAG;
3424 pc=readmemw(0,addr);
3425 loadcs(readmemw(0,addr+2));
3426 FETCHCLEAR();
3427 }
3428 else if (nmi && nmi_enable)
3429 {
3430 // output = 3;
3431 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3432 writememw(ss,(SP-4)&0xFFFF,CS);
3433 writememw(ss,(SP-6)&0xFFFF,pc);
3434 SP-=6;
3435 addr=2<<2;
3436 flags&=~I_FLAG;
3437 flags&=~T_FLAG;
3438 pc=readmemw(0,addr);
3439 loadcs(readmemw(0,addr+2));
3440 FETCHCLEAR();
3441 nmi_enable = 0;
3442 }
3443 else if (takeint && !ssegs && !noint)
3444 {
3445 temp=picinterrupt();
3446 if (temp!=0xFF)
3447 {
3448 if (inhlt) pc++;
3449 writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
3450 writememw(ss,(SP-4)&0xFFFF,CS);
3451 writememw(ss,(SP-6)&0xFFFF,pc);
3452 SP-=6;
3453 addr=temp<<2;
3454 flags&=~I_FLAG;
3455 flags&=~T_FLAG;
3456 pc=readmemw(0,addr);
3457 // printf("INT INT INT\n");
3458 loadcs(readmemw(0,addr+2));
3459 FETCHCLEAR();
3460 // printf("INTERRUPT\n");
3461 }
3462 }
3463 takeint = (flags&I_FLAG) && (pic.pend&~pic.mask);
3465 if (noint) noint=0;
3466 ins++;
3467 /* if (timetolive)
3468 {
3469 timetolive--;
3470 if (!timetolive) exit(-1); //output=0;
3471 }*/
3472 }
3473 }
