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