OSDN Git Service

[General] Tracking to upstream, rev 2015-01-14.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mame / emu / cpu / i86 / instr86.c
1 /****************************************************************************\r
2 *             real mode i286 emulator v1.4 by Fabrice Frances               *\r
3 *               (initial work based on David Hedley's pcemu)                *\r
4 ****************************************************************************/\r
5 \r
6 /*\r
7  * file will be included in all cpu variants\r
8  * put non i86 instructions in own files (i286, i386, nec)\r
9  * function renaming will be added when necessary\r
10  * timing value should move to separate array\r
11  */\r
12 \r
13 /*\r
14     PHS - 2010-12-29\r
15 \r
16     Moved several instruction stubs so that they are compiled separately for\r
17     the 8086 and 80186. The instructions affected are :\r
18 \r
19     _pop_ss, _es, _cs, _ss, _ds, _mov_sregw and _sti\r
20 \r
21     This is because they call the next instruction directly as it cannot be\r
22     interrupted. If they are not compiled separately when executing on an\r
23     80186, the wrong set of instructions are used (the 8086 set). This has\r
24     the serious effect of ignoring the next instruction, as invalid, *IF*\r
25     it is an 80186 specific instruction.\r
26 \r
27 */\r
28 \r
29 #undef ICOUNT\r
30 \r
31 #define ICOUNT cpustate->icount\r
32 \r
33 \r
34 #if !defined(I80186)\r
35 static void PREFIX86(_interrupt)(i8086_state *cpustate, unsigned int_num)\r
36 {\r
37         unsigned dest_seg, dest_off;\r
38         WORD ip = cpustate->pc - cpustate->base[CS];\r
39 \r
40         if (int_num == -1)\r
41                 int_num = cpustate->pic->intr_ack();\r
42 \r
43 #ifdef I80286\r
44         if (PM) {\r
45                 i80286_interrupt_descriptor(cpustate, int_num, 0, 0);\r
46         } else {\r
47 #endif\r
48                 dest_off = ReadWord(int_num*4);\r
49                 dest_seg = ReadWord(int_num*4+2);\r
50 \r
51                 PREFIX(_pushf(cpustate));\r
52                 cpustate->TF = cpustate->IF = 0;\r
53                 PUSH(cpustate->sregs[CS]);\r
54                 PUSH(ip);\r
55                 cpustate->sregs[CS] = (WORD)dest_seg;\r
56                 cpustate->base[CS] = SegBase(CS);\r
57                 cpustate->pc = (cpustate->base[CS] + dest_off) & AMASK;\r
58                 CHANGE_PC(cpustate->pc);\r
59 #ifdef I80286\r
60         }\r
61 #endif\r
62         cpustate->extra_cycles += timing.exception;\r
63 }\r
64 \r
65 static void PREFIX86(_trap)(i8086_state *cpustate)\r
66 {\r
67         PREFIX(_instruction)[FETCHOP](cpustate);\r
68         PREFIX(_interrupt)(cpustate, 1);\r
69 }\r
70 #endif\r
71 \r
72 #ifndef I80186\r
73 static void PREFIX86(_rotate_shift_Byte)(i8086_state *cpustate, unsigned ModRM, unsigned count, unsigned src)\r
74 {\r
75 //  unsigned src = (unsigned)GetRMByte(ModRM);\r
76         unsigned dst=src;\r
77 \r
78         if (count==0)\r
79         {\r
80                 ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m8_base;\r
81         }\r
82         else if (count==1)\r
83         {\r
84                 ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m8_1;\r
85 \r
86                 switch (ModRM & 0x38)\r
87                 {\r
88                 case 0x00:  /* ROL eb,1 */\r
89                         cpustate->CarryVal = src & 0x80;\r
90                         dst=(src<<1)+CF;\r
91                         PutbackRMByte(ModRM,dst);\r
92                         cpustate->OverVal = (src^dst)&0x80;\r
93                         break;\r
94                 case 0x08:  /* ROR eb,1 */\r
95                         cpustate->CarryVal = src & 0x01;\r
96                         dst = ((CF<<8)+src) >> 1;\r
97                         PutbackRMByte(ModRM,dst);\r
98                         cpustate->OverVal = (src^dst)&0x80;\r
99                         break;\r
100                 case 0x10:  /* RCL eb,1 */\r
101                         dst=(src<<1)+CF;\r
102                         PutbackRMByte(ModRM,dst);\r
103                         SetCFB(dst);\r
104                         cpustate->OverVal = (src^dst)&0x80;\r
105                         break;\r
106                 case 0x18:  /* RCR eb,1 */\r
107                         dst = ((CF<<8)+src) >> 1;\r
108                         PutbackRMByte(ModRM,dst);\r
109                         cpustate->CarryVal = src & 0x01;\r
110                         cpustate->OverVal = (src^dst)&0x80;\r
111                         break;\r
112                 case 0x20:  /* SHL eb,1 */\r
113                 case 0x30:\r
114                         dst = src << 1;\r
115                         PutbackRMByte(ModRM,dst);\r
116                         SetCFB(dst);\r
117                         cpustate->OverVal = (src^dst)&0x80;\r
118                         cpustate->AuxVal = 1;\r
119                         SetSZPF_Byte(dst);\r
120                         break;\r
121                 case 0x28:  /* SHR eb,1 */\r
122                         dst = src >> 1;\r
123                         PutbackRMByte(ModRM,dst);\r
124                         cpustate->CarryVal = src & 0x01;\r
125                         cpustate->OverVal = src & 0x80;\r
126                         cpustate->AuxVal = 1;\r
127                         SetSZPF_Byte(dst);\r
128                         break;\r
129                 case 0x38:  /* SAR eb,1 */\r
130                         dst = ((INT8)src) >> 1;\r
131                         PutbackRMByte(ModRM,dst);\r
132                         cpustate->CarryVal = src & 0x01;\r
133                         cpustate->OverVal = 0;\r
134                         cpustate->AuxVal = 1;\r
135                         SetSZPF_Byte(dst);\r
136                         break;\r
137                 }\r
138         }\r
139         else\r
140         {\r
141                 int tmpcf = CF;\r
142                 ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base + (timing.rot_reg_bit * count) : timing.rot_m8_base + (timing.rot_m8_bit * count);\r
143 \r
144                 switch (ModRM & 0x38)\r
145                 {\r
146                 case 0x00:  /* ROL eb,count */\r
147                         for (; count > 0; count--)\r
148                         {\r
149                                 cpustate->CarryVal = dst & 0x80;\r
150                                 dst = (dst << 1) + CF;\r
151                         }\r
152                         PutbackRMByte(ModRM,(BYTE)dst);\r
153                         break;\r
154                 case 0x08:  /* ROR eb,count */\r
155                         for (; count > 0; count--)\r
156                         {\r
157                                 cpustate->CarryVal = dst & 0x01;\r
158                                 dst = (dst >> 1) + (CF << 7);\r
159                         }\r
160                         PutbackRMByte(ModRM,(BYTE)dst);\r
161                         break;\r
162                 case 0x10:  /* RCL eb,count */\r
163                         for (; count > 0; count--)\r
164                         {\r
165                                 dst = (dst << 1) + tmpcf;\r
166                                 tmpcf = (int)((dst & 0x100) != 0);\r
167                         }\r
168                         PutbackRMByte(ModRM,(BYTE)dst);\r
169                         cpustate->CarryVal = tmpcf;\r
170                         break;\r
171                 case 0x18:  /* RCR eb,count */\r
172                         for (; count > 0; count--)\r
173                         {\r
174                                 dst = (tmpcf<<8)+dst;\r
175                                 tmpcf = dst & 0x01;\r
176                                 dst >>= 1;\r
177                         }\r
178                         PutbackRMByte(ModRM,(BYTE)dst);\r
179                         cpustate->CarryVal = tmpcf;\r
180                         break;\r
181                 case 0x20:\r
182                 case 0x30:  /* SHL eb,count */\r
183                         for(int i=0;i<count;i++) dst<<= 1;\r
184                         SetCFB(dst);\r
185                         cpustate->AuxVal = 1;\r
186                         SetSZPF_Byte(dst);\r
187                         PutbackRMByte(ModRM,(BYTE)dst);\r
188                         break;\r
189                 case 0x28:  /* SHR eb,count */\r
190                         for(int i=0;i<count-1;i++) dst>>= 1;\r
191                         cpustate->CarryVal = dst & 0x1;\r
192                         dst >>= 1;\r
193                         SetSZPF_Byte(dst);\r
194                         cpustate->AuxVal = 1;\r
195                         PutbackRMByte(ModRM,(BYTE)dst);\r
196                         break;\r
197                 case 0x38:  /* SAR eb,count */\r
198                         for(int i=0;i<count-1;i++) dst = ((INT8)dst) >> 1;\r
199                         cpustate->CarryVal = dst & 0x1;\r
200                         dst = ((INT8)((BYTE)dst)) >> 1;\r
201                         SetSZPF_Byte(dst);\r
202                         cpustate->AuxVal = 1;\r
203                         PutbackRMByte(ModRM,(BYTE)dst);\r
204                         break;\r
205                 }\r
206         }\r
207 }\r
208 \r
209 static void PREFIX86(_rotate_shift_Word)(i8086_state *cpustate, unsigned ModRM, unsigned count, unsigned src)\r
210 {\r
211 //  unsigned src = GetRMWord(ModRM);\r
212         unsigned dst=src;\r
213 \r
214         if (count==0)\r
215         {\r
216                 ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base : timing.rot_m16_base;\r
217         }\r
218         else if (count==1)\r
219         {\r
220                 ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_1 : timing.rot_m16_1;\r
221 \r
222                 switch (ModRM & 0x38)\r
223                 {\r
224 #if 0\r
225                 case 0x00:  /* ROL ew,1 */\r
226                         tmp2 = (tmp << 1) + CF;\r
227                         SetCFW(tmp2);\r
228                         cpustate->OverVal = !(!(tmp & 0x4000)) != CF;\r
229                         PutbackRMWord(ModRM,tmp2);\r
230                         break;\r
231                 case 0x08:  /* ROR ew,1 */\r
232                         cpustate->CarryVal = tmp & 0x01;\r
233                         tmp2 = (tmp >> 1) + ((unsigned)CF << 15);\r
234                         cpustate->OverVal = !(!(tmp & 0x8000)) != CF;\r
235                         PutbackRMWord(ModRM,tmp2);\r
236                         break;\r
237                 case 0x10:  /* RCL ew,1 */\r
238                         tmp2 = (tmp << 1) + CF;\r
239                         SetCFW(tmp2);\r
240                         cpustate->OverVal = (tmp ^ (tmp << 1)) & 0x8000;\r
241                         PutbackRMWord(ModRM,tmp2);\r
242                         break;\r
243                 case 0x18:  /* RCR ew,1 */\r
244                         tmp2 = (tmp >> 1) + ((unsigned)CF << 15);\r
245                         cpustate->OverVal = !(!(tmp & 0x8000)) != CF;\r
246                         cpustate->CarryVal = tmp & 0x01;\r
247                         PutbackRMWord(ModRM,tmp2);\r
248                         break;\r
249                 case 0x20:  /* SHL ew,1 */\r
250                 case 0x30:\r
251                         tmp <<= 1;\r
252 \r
253                         SetCFW(tmp);\r
254                         SetOFW_Add(tmp,tmp2,tmp2);\r
255                         cpustate->AuxVal = 1;\r
256                         SetSZPF_Word(tmp);\r
257 \r
258                         PutbackRMWord(ModRM,tmp);\r
259                         break;\r
260                 case 0x28:  /* SHR ew,1 */\r
261                         cpustate->CarryVal = tmp & 0x01;\r
262                         cpustate->OverVal = tmp & 0x8000;\r
263 \r
264                         tmp2 = tmp >> 1;\r
265 \r
266                         SetSZPF_Word(tmp2);\r
267                         cpustate->AuxVal = 1;\r
268                         PutbackRMWord(ModRM,tmp2);\r
269                         break;\r
270                         case 0x38:  /* SAR ew,1 */\r
271                         cpustate->CarryVal = tmp & 0x01;\r
272                         cpustate->OverVal = 0;\r
273 \r
274                         tmp2 = (tmp >> 1) | (tmp & 0x8000);\r
275 \r
276                         SetSZPF_Word(tmp2);\r
277                         cpustate->AuxVal = 1;\r
278                         PutbackRMWord(ModRM,tmp2);\r
279                         break;\r
280 #else\r
281                 case 0x00:  /* ROL ew,1 */\r
282                         cpustate->CarryVal = src & 0x8000;\r
283                         dst=(src<<1)+CF;\r
284                         PutbackRMWord(ModRM,dst);\r
285                         cpustate->OverVal = (src^dst)&0x8000;\r
286                         break;\r
287                 case 0x08:  /* ROR ew,1 */\r
288                         cpustate->CarryVal = src & 0x01;\r
289                         dst = ((CF<<16)+src) >> 1;\r
290                         PutbackRMWord(ModRM,dst);\r
291                         cpustate->OverVal = (src^dst)&0x8000;\r
292                         break;\r
293                 case 0x10:  /* RCL ew,1 */\r
294                         dst=(src<<1)+CF;\r
295                         PutbackRMWord(ModRM,dst);\r
296                         SetCFW(dst);\r
297                         cpustate->OverVal = (src^dst)&0x8000;\r
298                         break;\r
299                 case 0x18:  /* RCR ew,1 */\r
300                         dst = ((CF<<16)+src) >> 1;\r
301                         PutbackRMWord(ModRM,dst);\r
302                         cpustate->CarryVal = src & 0x01;\r
303                         cpustate->OverVal = (src^dst)&0x8000;\r
304                         break;\r
305                 case 0x20:  /* SHL ew,1 */\r
306                 case 0x30:\r
307                         dst = src << 1;\r
308                         PutbackRMWord(ModRM,dst);\r
309                         SetCFW(dst);\r
310                         cpustate->OverVal = (src^dst)&0x8000;\r
311                         cpustate->AuxVal = 1;\r
312                         SetSZPF_Word(dst);\r
313                         break;\r
314                 case 0x28:  /* SHR ew,1 */\r
315                         dst = src >> 1;\r
316                         PutbackRMWord(ModRM,dst);\r
317                         cpustate->CarryVal = src & 0x01;\r
318                         cpustate->OverVal = src & 0x8000;\r
319                         cpustate->AuxVal = 1;\r
320                         SetSZPF_Word(dst);\r
321                         break;\r
322                 case 0x38:  /* SAR ew,1 */\r
323                         dst = ((INT16)src) >> 1;\r
324                         PutbackRMWord(ModRM,dst);\r
325                         cpustate->CarryVal = src & 0x01;\r
326                         cpustate->OverVal = 0;\r
327                         cpustate->AuxVal = 1;\r
328                         SetSZPF_Word(dst);\r
329                         break;\r
330 #endif\r
331                 }\r
332         }\r
333         else\r
334         {\r
335                 int tmpcf = CF;\r
336                 ICOUNT -= (ModRM >= 0xc0) ? timing.rot_reg_base + (timing.rot_reg_bit * count) : timing.rot_m8_base + (timing.rot_m16_bit * count);\r
337 \r
338                 switch (ModRM & 0x38)\r
339                 {\r
340                 case 0x00:  /* ROL ew,count */\r
341                         for (; count > 0; count--)\r
342                         {\r
343                                 cpustate->CarryVal = dst & 0x8000;\r
344                                 dst = (dst << 1) + CF;\r
345                         }\r
346                         PutbackRMWord(ModRM,dst);\r
347                         break;\r
348                 case 0x08:  /* ROR ew,count */\r
349                         for (; count > 0; count--)\r
350                         {\r
351                                 cpustate->CarryVal = dst & 0x01;\r
352                                 dst = (dst >> 1) + (CF << 15);\r
353                         }\r
354                         PutbackRMWord(ModRM,dst);\r
355                         break;\r
356                 case 0x10:  /* RCL ew,count */\r
357                         for (; count > 0; count--)\r
358                         {\r
359                                 dst = (dst << 1) + tmpcf;\r
360                                 tmpcf = (int)((dst & 0x10000) != 0);\r
361                         }\r
362                         PutbackRMWord(ModRM,dst);\r
363                         cpustate->CarryVal = tmpcf;\r
364                         break;\r
365                 case 0x18:  /* RCR ew,count */\r
366                         for (; count > 0; count--)\r
367                         {\r
368                                 dst = dst + (tmpcf << 16);\r
369                                 tmpcf = dst & 0x01;\r
370                                 dst >>= 1;\r
371                         }\r
372                         PutbackRMWord(ModRM,dst);\r
373                         cpustate->CarryVal = tmpcf;\r
374                         break;\r
375                 case 0x20:\r
376                 case 0x30:  /* SHL ew,count */\r
377                         for(int i=0;i<count;i++) dst<<= 1;\r
378                         SetCFW(dst);\r
379                         cpustate->AuxVal = 1;\r
380                         SetSZPF_Word(dst);\r
381                         PutbackRMWord(ModRM,dst);\r
382                         break;\r
383                 case 0x28:  /* SHR ew,count */\r
384                         for(int i=0;i<count-1;i++) dst>>= 1;\r
385                         cpustate->CarryVal = dst & 0x1;\r
386                         dst >>= 1;\r
387                         SetSZPF_Word(dst);\r
388                         cpustate->AuxVal = 1;\r
389                         PutbackRMWord(ModRM,dst);\r
390                         break;\r
391                 case 0x38:  /* SAR ew,count */\r
392                         for(int i=0;i<count-1;i++) dst = ((INT16)dst) >> 1;\r
393                         cpustate->CarryVal = dst & 0x01;\r
394                         dst = ((INT16)((WORD)dst)) >> 1;\r
395                         SetSZPF_Word(dst);\r
396                         cpustate->AuxVal = 1;\r
397                         PutbackRMWord(ModRM,dst);\r
398                         break;\r
399                 }\r
400         }\r
401 }\r
402 #endif\r
403 \r
404 static void PREFIX(rep)(i8086_state *cpustate,int flagval)\r
405 {\r
406         /* Handles rep- and repnz- prefixes. flagval is the value of ZF for the\r
407              loop  to continue for CMPS and SCAS instructions. */\r
408 \r
409         unsigned next = FETCHOP;\r
410 \r
411         switch(next)\r
412         {\r
413         case 0x26:  /* ES: */\r
414                 cpustate->seg_prefix = TRUE;\r
415                 cpustate->prefix_seg = ES;\r
416                 if (!cpustate->rep_in_progress)\r
417                         ICOUNT -= timing.override;\r
418                 PREFIX(rep)(cpustate, flagval);\r
419                 break;\r
420         case 0x2e:  /* CS: */\r
421                 cpustate->seg_prefix = TRUE;\r
422                 cpustate->prefix_seg = CS;\r
423                 if (!cpustate->rep_in_progress)\r
424                         ICOUNT -= timing.override;\r
425                 PREFIX(rep)(cpustate, flagval);\r
426                 break;\r
427         case 0x36:  /* SS: */\r
428                 cpustate->seg_prefix = TRUE;\r
429                 cpustate->prefix_seg = SS;\r
430                 if (!cpustate->rep_in_progress)\r
431                         ICOUNT -= timing.override;\r
432                 PREFIX(rep)(cpustate, flagval);\r
433                 break;\r
434         case 0x3e:  /* DS: */\r
435                 cpustate->seg_prefix = TRUE;\r
436                 cpustate->prefix_seg = DS;\r
437                 if (!cpustate->rep_in_progress)\r
438                         ICOUNT -= timing.override;\r
439                 PREFIX(rep)(cpustate, flagval);\r
440                 break;\r
441 #ifndef I8086\r
442         case 0x6c:  /* REP INSB */\r
443 #ifdef I80286\r
444                 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);\r
445 #endif\r
446                 if (!cpustate->rep_in_progress)\r
447                         ICOUNT -= timing.rep_ins8_base;\r
448                 cpustate->rep_in_progress = FALSE;\r
449                 while(cpustate->regs.w[CX])\r
450                 {\r
451 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
452                         PutMemB(ES,cpustate->regs.w[DI],read_port_byte(cpustate->regs.w[DX]));\r
453                         cpustate->regs.w[CX]--;\r
454                         cpustate->regs.w[DI] += cpustate->DirVal;\r
455                         ICOUNT -= timing.rep_ins8_count;\r
456                 }\r
457                 break;\r
458         case 0x6d:  /* REP INSW */\r
459 #ifdef I80286\r
460                 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);\r
461 #endif\r
462                 if (!cpustate->rep_in_progress)\r
463                         ICOUNT -= timing.rep_ins16_base;\r
464                 cpustate->rep_in_progress = FALSE;\r
465                 while(cpustate->regs.w[CX])\r
466                 {\r
467 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
468                         PutMemW(ES,cpustate->regs.w[DI],read_port_word(cpustate->regs.w[DX]));\r
469                         cpustate->regs.w[CX]--;\r
470                         cpustate->regs.w[DI] += 2 * cpustate->DirVal;\r
471                         ICOUNT -= timing.rep_ins16_count;\r
472                 }\r
473                 break;\r
474         case 0x6e:  /* REP OUTSB */\r
475 #ifdef I80286\r
476                 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);\r
477 #endif\r
478                 if (!cpustate->rep_in_progress)\r
479                         ICOUNT -= timing.rep_outs8_base;\r
480                 cpustate->rep_in_progress = FALSE;\r
481                 while(cpustate->regs.w[CX])\r
482                 {\r
483 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
484                         write_port_byte(cpustate->regs.w[DX],GetMemB(DS,cpustate->regs.w[SI]));\r
485                         cpustate->regs.w[CX]--;\r
486                         cpustate->regs.w[SI] += cpustate->DirVal; /* GOL 11/27/01 */\r
487                         ICOUNT -= timing.rep_outs8_count;\r
488                 }\r
489                 break;\r
490         case 0x6f:  /* REP OUTSW */\r
491 #ifdef I80286\r
492                 if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);\r
493 #endif\r
494                 if (!cpustate->rep_in_progress)\r
495                         ICOUNT -= timing.rep_outs16_base;\r
496                 cpustate->rep_in_progress = FALSE;\r
497                 while(cpustate->regs.w[CX])\r
498                 {\r
499 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
500                         write_port_word(cpustate->regs.w[DX],GetMemW(DS,cpustate->regs.w[SI]));\r
501                         cpustate->regs.w[CX]--;\r
502                         cpustate->regs.w[SI] += 2 * cpustate->DirVal; /* GOL 11/27/01 */\r
503                         ICOUNT -= timing.rep_outs16_count;\r
504                 }\r
505                 break;\r
506 #endif\r
507         case 0xa4:  /* REP MOVSB */\r
508                 if (!cpustate->rep_in_progress)\r
509                         ICOUNT -= timing.rep_movs8_base;\r
510                 cpustate->rep_in_progress = FALSE;\r
511                 while(cpustate->regs.w[CX])\r
512                 {\r
513                         BYTE tmp;\r
514 \r
515 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
516                         tmp = GetMemB(DS,cpustate->regs.w[SI]);\r
517                         PutMemB(ES,cpustate->regs.w[DI], tmp);\r
518                         cpustate->regs.w[CX]--;\r
519                         cpustate->regs.w[DI] += cpustate->DirVal;\r
520                         cpustate->regs.w[SI] += cpustate->DirVal;\r
521                         ICOUNT -= timing.rep_movs8_count;\r
522                 }\r
523                 break;\r
524         case 0xa5:  /* REP MOVSW */\r
525                 if (!cpustate->rep_in_progress)\r
526                         ICOUNT -= timing.rep_movs16_base;\r
527                 cpustate->rep_in_progress = FALSE;\r
528                 while(cpustate->regs.w[CX])\r
529                 {\r
530                         WORD tmp;\r
531 \r
532 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
533                         tmp = GetMemW(DS,cpustate->regs.w[SI]);\r
534                         PutMemW(ES,cpustate->regs.w[DI], tmp);\r
535                         cpustate->regs.w[CX]--;\r
536                         cpustate->regs.w[DI] += 2 * cpustate->DirVal;\r
537                         cpustate->regs.w[SI] += 2 * cpustate->DirVal;\r
538                         ICOUNT -= timing.rep_movs16_count;\r
539                 }\r
540                 break;\r
541         case 0xa6:  /* REP(N)E CMPSB */\r
542                 if (!cpustate->rep_in_progress)\r
543                         ICOUNT -= timing.rep_cmps8_base;\r
544                 cpustate->rep_in_progress = FALSE;\r
545                 cpustate->ZeroVal = !flagval;\r
546                 while(cpustate->regs.w[CX] && (ZF == flagval))\r
547                 {\r
548                         unsigned dst, src;\r
549 \r
550 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
551                         dst = GetMemB(ES, cpustate->regs.w[DI]);\r
552                         src = GetMemB(DS, cpustate->regs.w[SI]);\r
553                         SUBB(src,dst); /* opposite of the usual convention */\r
554                         cpustate->regs.w[CX]--;\r
555                         cpustate->regs.w[DI] += cpustate->DirVal;\r
556                         cpustate->regs.w[SI] += cpustate->DirVal;\r
557                         ICOUNT -= timing.rep_cmps8_count;\r
558                 }\r
559                 break;\r
560         case 0xa7:  /* REP(N)E CMPSW */\r
561                 if (!cpustate->rep_in_progress)\r
562                         ICOUNT -= timing.rep_cmps16_base;\r
563                 cpustate->rep_in_progress = FALSE;\r
564                 cpustate->ZeroVal = !flagval;\r
565                 while(cpustate->regs.w[CX] && (ZF == flagval))\r
566                 {\r
567                         unsigned dst, src;\r
568 \r
569 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
570                         dst = GetMemW(ES, cpustate->regs.w[DI]);\r
571                         src = GetMemW(DS, cpustate->regs.w[SI]);\r
572                         SUBW(src,dst); /* opposite of the usual convention */\r
573                         cpustate->regs.w[CX]--;\r
574                         cpustate->regs.w[DI] += 2 * cpustate->DirVal;\r
575                         cpustate->regs.w[SI] += 2 * cpustate->DirVal;\r
576                         ICOUNT -= timing.rep_cmps16_count;\r
577                 }\r
578                 break;\r
579         case 0xaa:  /* REP STOSB */\r
580                 if (!cpustate->rep_in_progress)\r
581                         ICOUNT -= timing.rep_stos8_base;\r
582                 cpustate->rep_in_progress = FALSE;\r
583                 while(cpustate->regs.w[CX])\r
584                 {\r
585 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
586                         PutMemB(ES,cpustate->regs.w[DI],cpustate->regs.b[AL]);\r
587                         cpustate->regs.w[CX]--;\r
588                         cpustate->regs.w[DI] += cpustate->DirVal;\r
589                         ICOUNT -= timing.rep_stos8_count;\r
590                 }\r
591                 break;\r
592         case 0xab:  /* REP STOSW */\r
593                 if (!cpustate->rep_in_progress)\r
594                         ICOUNT -= timing.rep_stos16_base;\r
595                 cpustate->rep_in_progress = FALSE;\r
596                 while(cpustate->regs.w[CX])\r
597                 {\r
598 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
599                         PutMemW(ES,cpustate->regs.w[DI],cpustate->regs.w[AX]);\r
600                         cpustate->regs.w[CX]--;\r
601                         cpustate->regs.w[DI] += 2 * cpustate->DirVal;\r
602                         ICOUNT -= timing.rep_stos16_count;\r
603                 }\r
604                 break;\r
605         case 0xac:  /* REP LODSB */\r
606                 if (!cpustate->rep_in_progress)\r
607                         ICOUNT -= timing.rep_lods8_base;\r
608                 cpustate->rep_in_progress = FALSE;\r
609                 while(cpustate->regs.w[CX])\r
610                 {\r
611 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
612                         cpustate->regs.b[AL] = GetMemB(DS,cpustate->regs.w[SI]);\r
613                         cpustate->regs.w[CX]--;\r
614                         cpustate->regs.w[SI] += cpustate->DirVal;\r
615                         ICOUNT -= timing.rep_lods8_count;\r
616                 }\r
617                 break;\r
618         case 0xad:  /* REP LODSW */\r
619                 if (!cpustate->rep_in_progress)\r
620                         ICOUNT -= timing.rep_lods16_base;\r
621                 cpustate->rep_in_progress = FALSE;\r
622                 while(cpustate->regs.w[CX])\r
623                 {\r
624 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
625                         cpustate->regs.w[AX] = GetMemW(DS,cpustate->regs.w[SI]);\r
626                         cpustate->regs.w[CX]--;\r
627                         cpustate->regs.w[SI] += 2 * cpustate->DirVal;\r
628                         ICOUNT -= timing.rep_lods16_count;\r
629                 }\r
630                 break;\r
631         case 0xae:  /* REP(N)E SCASB */\r
632                 if (!cpustate->rep_in_progress)\r
633                         ICOUNT -= timing.rep_scas8_base;\r
634                 cpustate->rep_in_progress = FALSE;\r
635                 cpustate->ZeroVal = !flagval;\r
636                 while(cpustate->regs.w[CX] && (ZF == flagval))\r
637                 {\r
638                         unsigned src, dst;\r
639 \r
640 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
641                         src = GetMemB(ES, cpustate->regs.w[DI]);\r
642                         dst = cpustate->regs.b[AL];\r
643                         SUBB(dst,src);\r
644                         cpustate->regs.w[CX]--;\r
645                         cpustate->regs.w[DI] += cpustate->DirVal;\r
646                         ICOUNT -= timing.rep_scas8_count;\r
647                 }\r
648                 break;\r
649         case 0xaf:  /* REP(N)E SCASW */\r
650                 if (!cpustate->rep_in_progress)\r
651                         ICOUNT -= timing.rep_scas16_base;\r
652                 cpustate->rep_in_progress = FALSE;\r
653                 cpustate->ZeroVal = !flagval;\r
654                 while(cpustate->regs.w[CX] && (ZF == flagval))\r
655                 {\r
656                         unsigned src, dst;\r
657 \r
658 //                      if (ICOUNT <= 0) { cpustate->pc = cpustate->prevpc; cpustate->rep_in_progress = TRUE; break; }\r
659                         src = GetMemW(ES, cpustate->regs.w[DI]);\r
660                         dst = cpustate->regs.w[AX];\r
661                         SUBW(dst,src);\r
662                         cpustate->regs.w[CX]--;\r
663                         cpustate->regs.w[DI] += 2 * cpustate->DirVal;\r
664                         ICOUNT -= timing.rep_scas16_count;\r
665                 }\r
666                 break;\r
667         default:\r
668                 PREFIX(_instruction)[next](cpustate);\r
669         }\r
670 }\r
671 \r
672 #ifndef I80186\r
673 static void PREFIX86(_add_br8)(i8086_state *cpustate)    /* Opcode 0x00 */\r
674 {\r
675         DEF_br8(dst,src);\r
676         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;\r
677         ADDB(dst,src);\r
678         PutbackRMByte(ModRM,dst);\r
679 }\r
680 \r
681 static void PREFIX86(_add_wr16)(i8086_state *cpustate)    /* Opcode 0x01 */\r
682 {\r
683         DEF_wr16(dst,src);\r
684         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;\r
685         ADDW(dst,src);\r
686         PutbackRMWord(ModRM,dst);\r
687 }\r
688 \r
689 static void PREFIX86(_add_r8b)(i8086_state *cpustate)    /* Opcode 0x02 */\r
690 {\r
691         DEF_r8b(dst,src);\r
692         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;\r
693         ADDB(dst,src);\r
694         RegByte(ModRM)=dst;\r
695 }\r
696 \r
697 static void PREFIX86(_add_r16w)(i8086_state *cpustate)    /* Opcode 0x03 */\r
698 {\r
699         DEF_r16w(dst,src);\r
700         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;\r
701         ADDW(dst,src);\r
702         RegWord(ModRM)=dst;\r
703 }\r
704 \r
705 \r
706 static void PREFIX86(_add_ald8)(i8086_state *cpustate)    /* Opcode 0x04 */\r
707 {\r
708         DEF_ald8(dst,src);\r
709         ICOUNT -= timing.alu_ri8;\r
710         ADDB(dst,src);\r
711         cpustate->regs.b[AL]=dst;\r
712 }\r
713 \r
714 \r
715 static void PREFIX86(_add_axd16)(i8086_state *cpustate)    /* Opcode 0x05 */\r
716 {\r
717         DEF_axd16(dst,src);\r
718         ICOUNT -= timing.alu_ri16;\r
719         ADDW(dst,src);\r
720         cpustate->regs.w[AX]=dst;\r
721 }\r
722 \r
723 \r
724 static void PREFIX86(_push_es)(i8086_state *cpustate)    /* Opcode 0x06 */\r
725 {\r
726         ICOUNT -= timing.push_seg;\r
727         PUSH(cpustate->sregs[ES]);\r
728 }\r
729 \r
730 \r
731 static void PREFIX86(_pop_es)(i8086_state *cpustate)    /* Opcode 0x07 */\r
732 {\r
733 #ifdef I80286\r
734         i80286_pop_seg(cpustate,ES);\r
735 #else\r
736         POP(cpustate->sregs[ES]);\r
737         cpustate->base[ES] = SegBase(ES);\r
738 #endif\r
739         ICOUNT -= timing.pop_seg;\r
740 }\r
741 \r
742 static void PREFIX86(_or_br8)(i8086_state *cpustate)    /* Opcode 0x08 */\r
743 {\r
744         DEF_br8(dst,src);\r
745         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;\r
746         ORB(dst,src);\r
747         PutbackRMByte(ModRM,dst);\r
748 }\r
749 \r
750 static void PREFIX86(_or_wr16)(i8086_state *cpustate)    /* Opcode 0x09 */\r
751 {\r
752         DEF_wr16(dst,src);\r
753         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;\r
754         ORW(dst,src);\r
755         PutbackRMWord(ModRM,dst);\r
756 }\r
757 \r
758 static void PREFIX86(_or_r8b)(i8086_state *cpustate)    /* Opcode 0x0a */\r
759 {\r
760         DEF_r8b(dst,src);\r
761         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;\r
762         ORB(dst,src);\r
763         RegByte(ModRM)=dst;\r
764 }\r
765 \r
766 static void PREFIX86(_or_r16w)(i8086_state *cpustate)    /* Opcode 0x0b */\r
767 {\r
768         DEF_r16w(dst,src);\r
769         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;\r
770         ORW(dst,src);\r
771         RegWord(ModRM)=dst;\r
772 }\r
773 \r
774 static void PREFIX86(_or_ald8)(i8086_state *cpustate)    /* Opcode 0x0c */\r
775 {\r
776         DEF_ald8(dst,src);\r
777         ICOUNT -= timing.alu_ri8;\r
778         ORB(dst,src);\r
779         cpustate->regs.b[AL]=dst;\r
780 }\r
781 \r
782 static void PREFIX86(_or_axd16)(i8086_state *cpustate)    /* Opcode 0x0d */\r
783 {\r
784         DEF_axd16(dst,src);\r
785         ICOUNT -= timing.alu_ri16;\r
786         ORW(dst,src);\r
787         cpustate->regs.w[AX]=dst;\r
788 }\r
789 \r
790 static void PREFIX86(_push_cs)(i8086_state *cpustate)    /* Opcode 0x0e */\r
791 {\r
792         ICOUNT -= timing.push_seg;\r
793         PUSH(cpustate->sregs[CS]);\r
794 }\r
795 \r
796 #ifndef I80286\r
797 static void PREFIX86(_pop_cs)(i8086_state *cpustate)    /* Opcode 0x0f */\r
798 {\r
799         int ip = cpustate->pc - cpustate->base[CS];\r
800         ICOUNT -= timing.push_seg;\r
801         POP(cpustate->sregs[CS]);\r
802         cpustate->base[CS] = SegBase(CS);\r
803         cpustate->pc = (ip + cpustate->base[CS]) & AMASK;\r
804         CHANGE_PC(cpustate->pc);\r
805 }\r
806 #endif\r
807 \r
808 static void PREFIX86(_adc_br8)(i8086_state *cpustate)    /* Opcode 0x10 */\r
809 {\r
810         int tmpcf;\r
811         DEF_br8(dst,src);\r
812         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;\r
813         src+=CF;\r
814         ADCB(dst,src,tmpcf);\r
815         PutbackRMByte(ModRM,dst);\r
816         cpustate->CarryVal = tmpcf;\r
817 }\r
818 \r
819 static void PREFIX86(_adc_wr16)(i8086_state *cpustate)    /* Opcode 0x11 */\r
820 {\r
821         int tmpcf;\r
822         DEF_wr16(dst,src);\r
823         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;\r
824         src+=CF;\r
825         ADCW(dst,src,tmpcf);\r
826         PutbackRMWord(ModRM,dst);\r
827         cpustate->CarryVal = tmpcf;\r
828 }\r
829 \r
830 static void PREFIX86(_adc_r8b)(i8086_state *cpustate)    /* Opcode 0x12 */\r
831 {\r
832         DEF_r8b(dst,src);\r
833         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;\r
834         src+=CF;\r
835         ADDB(dst,src);\r
836         RegByte(ModRM)=dst;\r
837 }\r
838 \r
839 static void PREFIX86(_adc_r16w)(i8086_state *cpustate)    /* Opcode 0x13 */\r
840 {\r
841         DEF_r16w(dst,src);\r
842         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;\r
843         src+=CF;\r
844         ADDW(dst,src);\r
845         RegWord(ModRM)=dst;\r
846 }\r
847 \r
848 static void PREFIX86(_adc_ald8)(i8086_state *cpustate)    /* Opcode 0x14 */\r
849 {\r
850         DEF_ald8(dst,src);\r
851         ICOUNT -= timing.alu_ri8;\r
852         src+=CF;\r
853         ADDB(dst,src);\r
854         cpustate->regs.b[AL] = dst;\r
855 }\r
856 \r
857 static void PREFIX86(_adc_axd16)(i8086_state *cpustate)    /* Opcode 0x15 */\r
858 {\r
859         DEF_axd16(dst,src);\r
860         ICOUNT -= timing.alu_ri16;\r
861         src+=CF;\r
862         ADDW(dst,src);\r
863         cpustate->regs.w[AX]=dst;\r
864 }\r
865 \r
866 static void PREFIX86(_push_ss)(i8086_state *cpustate)    /* Opcode 0x16 */\r
867 {\r
868         PUSH(cpustate->sregs[SS]);\r
869         ICOUNT -= timing.push_seg;\r
870 }\r
871 \r
872 static void PREFIX86(_sbb_br8)(i8086_state *cpustate)    /* Opcode 0x18 */\r
873 {\r
874         int tmpcf;\r
875         DEF_br8(dst,src);\r
876         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;\r
877         src+=CF;\r
878         SBBB(dst,src,tmpcf);\r
879         PutbackRMByte(ModRM,dst);\r
880         cpustate->CarryVal = tmpcf;\r
881 }\r
882 \r
883 static void PREFIX86(_sbb_wr16)(i8086_state *cpustate)    /* Opcode 0x19 */\r
884 {\r
885         int tmpcf;\r
886         DEF_wr16(dst,src);\r
887         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;\r
888         src+=CF;\r
889         SBBW(dst,src,tmpcf);\r
890         PutbackRMWord(ModRM,dst);\r
891         cpustate->CarryVal = tmpcf;\r
892 }\r
893 \r
894 static void PREFIX86(_sbb_r8b)(i8086_state *cpustate)    /* Opcode 0x1a */\r
895 {\r
896         DEF_r8b(dst,src);\r
897         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;\r
898         src+=CF;\r
899         SUBB(dst,src);\r
900         RegByte(ModRM)=dst;\r
901 }\r
902 \r
903 static void PREFIX86(_sbb_r16w)(i8086_state *cpustate)    /* Opcode 0x1b */\r
904 {\r
905         DEF_r16w(dst,src);\r
906         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;\r
907         src+=CF;\r
908         SUBW(dst,src);\r
909         RegWord(ModRM)= dst;\r
910 }\r
911 \r
912 static void PREFIX86(_sbb_ald8)(i8086_state *cpustate)    /* Opcode 0x1c */\r
913 {\r
914         DEF_ald8(dst,src);\r
915         ICOUNT -= timing.alu_ri8;\r
916         src+=CF;\r
917         SUBB(dst,src);\r
918         cpustate->regs.b[AL] = dst;\r
919 }\r
920 \r
921 static void PREFIX86(_sbb_axd16)(i8086_state *cpustate)    /* Opcode 0x1d */\r
922 {\r
923         DEF_axd16(dst,src);\r
924         ICOUNT -= timing.alu_ri16;\r
925         src+=CF;\r
926         SUBW(dst,src);\r
927         cpustate->regs.w[AX]=dst;\r
928 }\r
929 \r
930 static void PREFIX86(_push_ds)(i8086_state *cpustate)    /* Opcode 0x1e */\r
931 {\r
932         PUSH(cpustate->sregs[DS]);\r
933         ICOUNT -= timing.push_seg;\r
934 }\r
935 \r
936 static void PREFIX86(_pop_ds)(i8086_state *cpustate)    /* Opcode 0x1f */\r
937 {\r
938 #ifdef I80286\r
939         i80286_pop_seg(cpustate,DS);\r
940 #else\r
941         POP(cpustate->sregs[DS]);\r
942         cpustate->base[DS] = SegBase(DS);\r
943 #endif\r
944         ICOUNT -= timing.push_seg;\r
945 }\r
946 \r
947 static void PREFIX86(_and_br8)(i8086_state *cpustate)    /* Opcode 0x20 */\r
948 {\r
949         DEF_br8(dst,src);\r
950         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;\r
951         ANDB(dst,src);\r
952         PutbackRMByte(ModRM,dst);\r
953 }\r
954 \r
955 static void PREFIX86(_and_wr16)(i8086_state *cpustate)    /* Opcode 0x21 */\r
956 {\r
957         DEF_wr16(dst,src);\r
958         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;\r
959         ANDW(dst,src);\r
960         PutbackRMWord(ModRM,dst);\r
961 }\r
962 \r
963 static void PREFIX86(_and_r8b)(i8086_state *cpustate)    /* Opcode 0x22 */\r
964 {\r
965         DEF_r8b(dst,src);\r
966         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;\r
967         ANDB(dst,src);\r
968         RegByte(ModRM)=dst;\r
969 }\r
970 \r
971 static void PREFIX86(_and_r16w)(i8086_state *cpustate)    /* Opcode 0x23 */\r
972 {\r
973         DEF_r16w(dst,src);\r
974         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;\r
975         ANDW(dst,src);\r
976         RegWord(ModRM)=dst;\r
977 }\r
978 \r
979 static void PREFIX86(_and_ald8)(i8086_state *cpustate)    /* Opcode 0x24 */\r
980 {\r
981         DEF_ald8(dst,src);\r
982         ICOUNT -= timing.alu_ri8;\r
983         ANDB(dst,src);\r
984         cpustate->regs.b[AL] = dst;\r
985 }\r
986 \r
987 static void PREFIX86(_and_axd16)(i8086_state *cpustate)    /* Opcode 0x25 */\r
988 {\r
989         DEF_axd16(dst,src);\r
990         ICOUNT -= timing.alu_ri16;\r
991         ANDW(dst,src);\r
992         cpustate->regs.w[AX]=dst;\r
993 }\r
994 \r
995 static void PREFIX86(_daa)(i8086_state *cpustate)    /* Opcode 0x27 */\r
996 {\r
997         if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))\r
998         {\r
999                 int tmp;\r
1000                 cpustate->regs.b[AL] = tmp = cpustate->regs.b[AL] + 6;\r
1001                 cpustate->AuxVal = 1;\r
1002                 cpustate->CarryVal |= tmp & 0x100;\r
1003         }\r
1004 \r
1005         if (CF || (cpustate->regs.b[AL] > 0x9f))\r
1006         {\r
1007                 cpustate->regs.b[AL] += 0x60;\r
1008                 cpustate->CarryVal = 1;\r
1009         }\r
1010 \r
1011         SetSZPF_Byte(cpustate->regs.b[AL]);\r
1012         ICOUNT -= timing.daa;\r
1013 }\r
1014 \r
1015 static void PREFIX86(_sub_br8)(i8086_state *cpustate)    /* Opcode 0x28 */\r
1016 {\r
1017         DEF_br8(dst,src);\r
1018         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;\r
1019         SUBB(dst,src);\r
1020         PutbackRMByte(ModRM,dst);\r
1021 }\r
1022 \r
1023 static void PREFIX86(_sub_wr16)(i8086_state *cpustate)    /* Opcode 0x29 */\r
1024 {\r
1025         DEF_wr16(dst,src);\r
1026         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;\r
1027         SUBW(dst,src);\r
1028         PutbackRMWord(ModRM,dst);\r
1029 }\r
1030 \r
1031 static void PREFIX86(_sub_r8b)(i8086_state *cpustate)    /* Opcode 0x2a */\r
1032 {\r
1033         DEF_r8b(dst,src);\r
1034         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;\r
1035         SUBB(dst,src);\r
1036         RegByte(ModRM)=dst;\r
1037 }\r
1038 \r
1039 static void PREFIX86(_sub_r16w)(i8086_state *cpustate)    /* Opcode 0x2b */\r
1040 {\r
1041         DEF_r16w(dst,src);\r
1042         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;\r
1043         SUBW(dst,src);\r
1044         RegWord(ModRM)=dst;\r
1045 }\r
1046 \r
1047 static void PREFIX86(_sub_ald8)(i8086_state *cpustate)    /* Opcode 0x2c */\r
1048 {\r
1049         DEF_ald8(dst,src);\r
1050         ICOUNT -= timing.alu_ri8;\r
1051         SUBB(dst,src);\r
1052         cpustate->regs.b[AL] = dst;\r
1053 }\r
1054 \r
1055 static void PREFIX86(_sub_axd16)(i8086_state *cpustate)    /* Opcode 0x2d */\r
1056 {\r
1057         DEF_axd16(dst,src);\r
1058         ICOUNT -= timing.alu_ri16;\r
1059         SUBW(dst,src);\r
1060         cpustate->regs.w[AX]=dst;\r
1061 }\r
1062 \r
1063 static void PREFIX86(_das)(i8086_state *cpustate)    /* Opcode 0x2f */\r
1064 {\r
1065         UINT8 tmpAL=cpustate->regs.b[AL];\r
1066         if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))\r
1067         {\r
1068                 int tmp;\r
1069                 cpustate->regs.b[AL] = tmp = cpustate->regs.b[AL] - 6;\r
1070                 cpustate->AuxVal = 1;\r
1071                 cpustate->CarryVal |= tmp & 0x100;\r
1072         }\r
1073 \r
1074         if (CF || (tmpAL > 0x9f))\r
1075         {\r
1076                 cpustate->regs.b[AL] -= 0x60;\r
1077                 cpustate->CarryVal = 1;\r
1078         }\r
1079 \r
1080         SetSZPF_Byte(cpustate->regs.b[AL]);\r
1081         ICOUNT -= timing.das;\r
1082 }\r
1083 \r
1084 static void PREFIX86(_xor_br8)(i8086_state *cpustate)    /* Opcode 0x30 */\r
1085 {\r
1086         DEF_br8(dst,src);\r
1087         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_mr8;\r
1088         XORB(dst,src);\r
1089         PutbackRMByte(ModRM,dst);\r
1090 }\r
1091 \r
1092 static void PREFIX86(_xor_wr16)(i8086_state *cpustate)    /* Opcode 0x31 */\r
1093 {\r
1094         DEF_wr16(dst,src);\r
1095         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_mr16;\r
1096         XORW(dst,src);\r
1097         PutbackRMWord(ModRM,dst);\r
1098 }\r
1099 \r
1100 static void PREFIX86(_xor_r8b)(i8086_state *cpustate)    /* Opcode 0x32 */\r
1101 {\r
1102         DEF_r8b(dst,src);\r
1103         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;\r
1104         XORB(dst,src);\r
1105         RegByte(ModRM)=dst;\r
1106 }\r
1107 \r
1108 static void PREFIX86(_xor_r16w)(i8086_state *cpustate)    /* Opcode 0x33 */\r
1109 {\r
1110         DEF_r16w(dst,src);\r
1111         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;\r
1112         XORW(dst,src);\r
1113         RegWord(ModRM)=dst;\r
1114 }\r
1115 \r
1116 static void PREFIX86(_xor_ald8)(i8086_state *cpustate)    /* Opcode 0x34 */\r
1117 {\r
1118         DEF_ald8(dst,src);\r
1119         ICOUNT -= timing.alu_ri8;\r
1120         XORB(dst,src);\r
1121         cpustate->regs.b[AL] = dst;\r
1122 }\r
1123 \r
1124 static void PREFIX86(_xor_axd16)(i8086_state *cpustate)    /* Opcode 0x35 */\r
1125 {\r
1126         DEF_axd16(dst,src);\r
1127         ICOUNT -= timing.alu_ri16;\r
1128         XORW(dst,src);\r
1129         cpustate->regs.w[AX]=dst;\r
1130 }\r
1131 \r
1132 static void PREFIX86(_aaa)(i8086_state *cpustate)    /* Opcode 0x37 */\r
1133 {\r
1134         UINT8 ALcarry=1;\r
1135         if (cpustate->regs.b[AL]>0xf9) ALcarry=2;\r
1136 \r
1137         if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))\r
1138         {\r
1139                 cpustate->regs.b[AL] += 6;\r
1140                 cpustate->regs.b[AH] += ALcarry;\r
1141                 cpustate->AuxVal = 1;\r
1142                 cpustate->CarryVal = 1;\r
1143         }\r
1144         else\r
1145         {\r
1146                 cpustate->AuxVal = 0;\r
1147                 cpustate->CarryVal = 0;\r
1148         }\r
1149         cpustate->regs.b[AL] &= 0x0F;\r
1150         ICOUNT -= timing.aaa;\r
1151 }\r
1152 \r
1153 static void PREFIX86(_cmp_br8)(i8086_state *cpustate)    /* Opcode 0x38 */\r
1154 {\r
1155         DEF_br8(dst,src);\r
1156         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;\r
1157         SUBB(dst,src);\r
1158 }\r
1159 \r
1160 static void PREFIX86(_cmp_wr16)(i8086_state *cpustate)    /* Opcode 0x39 */\r
1161 {\r
1162         DEF_wr16(dst,src);\r
1163         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;\r
1164         SUBW(dst,src);\r
1165 }\r
1166 \r
1167 static void PREFIX86(_cmp_r8b)(i8086_state *cpustate)    /* Opcode 0x3a */\r
1168 {\r
1169         DEF_r8b(dst,src);\r
1170         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;\r
1171         SUBB(dst,src);\r
1172 }\r
1173 \r
1174 static void PREFIX86(_cmp_r16w)(i8086_state *cpustate)    /* Opcode 0x3b */\r
1175 {\r
1176         DEF_r16w(dst,src);\r
1177         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;\r
1178         SUBW(dst,src);\r
1179 }\r
1180 \r
1181 static void PREFIX86(_cmp_ald8)(i8086_state *cpustate)    /* Opcode 0x3c */\r
1182 {\r
1183         DEF_ald8(dst,src);\r
1184         ICOUNT -= timing.alu_ri8;\r
1185         SUBB(dst,src);\r
1186 }\r
1187 \r
1188 static void PREFIX86(_cmp_axd16)(i8086_state *cpustate)    /* Opcode 0x3d */\r
1189 {\r
1190         DEF_axd16(dst,src);\r
1191         ICOUNT -= timing.alu_ri16;\r
1192         SUBW(dst,src);\r
1193 }\r
1194 \r
1195 static void PREFIX86(_aas)(i8086_state *cpustate)    /* Opcode 0x3f */\r
1196 {\r
1197 //  UINT8 ALcarry=1;\r
1198 //  if (cpustate->regs.b[AL]>0xf9) ALcarry=2;\r
1199 \r
1200         if (AF || ((cpustate->regs.b[AL] & 0xf) > 9))\r
1201         {\r
1202                 cpustate->regs.b[AL] -= 6;\r
1203                 cpustate->regs.b[AH] -= 1;\r
1204                 cpustate->AuxVal = 1;\r
1205                 cpustate->CarryVal = 1;\r
1206         }\r
1207         else\r
1208         {\r
1209                 cpustate->AuxVal = 0;\r
1210                 cpustate->CarryVal = 0;\r
1211         }\r
1212         cpustate->regs.b[AL] &= 0x0F;\r
1213         ICOUNT -= timing.aas;\r
1214 }\r
1215 \r
1216 #define IncWordReg(Reg)                     \\r
1217 {                                           \\r
1218         unsigned tmp = (unsigned)cpustate->regs.w[Reg]; \\r
1219         unsigned tmp1 = tmp+1;                  \\r
1220         SetOFW_Add(tmp1,tmp,1);                 \\r
1221         SetAF(tmp1,tmp,1);                      \\r
1222         SetSZPF_Word(tmp1);                     \\r
1223         cpustate->regs.w[Reg]=tmp1;                     \\r
1224         ICOUNT -= timing.incdec_r16;            \\r
1225 }\r
1226 \r
1227 static void PREFIX86(_inc_ax)(i8086_state *cpustate)    /* Opcode 0x40 */\r
1228 {\r
1229         IncWordReg(AX);\r
1230 }\r
1231 \r
1232 static void PREFIX86(_inc_cx)(i8086_state *cpustate)    /* Opcode 0x41 */\r
1233 {\r
1234         IncWordReg(CX);\r
1235 }\r
1236 \r
1237 static void PREFIX86(_inc_dx)(i8086_state *cpustate)    /* Opcode 0x42 */\r
1238 {\r
1239         IncWordReg(DX);\r
1240 }\r
1241 \r
1242 static void PREFIX(_inc_bx)(i8086_state *cpustate)    /* Opcode 0x43 */\r
1243 {\r
1244         IncWordReg(BX);\r
1245 }\r
1246 \r
1247 static void PREFIX86(_inc_sp)(i8086_state *cpustate)    /* Opcode 0x44 */\r
1248 {\r
1249         IncWordReg(SP);\r
1250 }\r
1251 \r
1252 static void PREFIX86(_inc_bp)(i8086_state *cpustate)    /* Opcode 0x45 */\r
1253 {\r
1254         IncWordReg(BP);\r
1255 }\r
1256 \r
1257 static void PREFIX86(_inc_si)(i8086_state *cpustate)    /* Opcode 0x46 */\r
1258 {\r
1259         IncWordReg(SI);\r
1260 }\r
1261 \r
1262 static void PREFIX86(_inc_di)(i8086_state *cpustate)    /* Opcode 0x47 */\r
1263 {\r
1264         IncWordReg(DI);\r
1265 }\r
1266 \r
1267 #define DecWordReg(Reg)                     \\r
1268 {                                           \\r
1269         unsigned tmp = (unsigned)cpustate->regs.w[Reg]; \\r
1270         unsigned tmp1 = tmp-1;                  \\r
1271         SetOFW_Sub(tmp1,1,tmp);                 \\r
1272         SetAF(tmp1,tmp,1);                      \\r
1273         SetSZPF_Word(tmp1);                     \\r
1274         cpustate->regs.w[Reg]=tmp1;                     \\r
1275         ICOUNT -= timing.incdec_r16;            \\r
1276 }\r
1277 \r
1278 static void PREFIX86(_dec_ax)(i8086_state *cpustate)    /* Opcode 0x48 */\r
1279 {\r
1280         DecWordReg(AX);\r
1281 }\r
1282 \r
1283 static void PREFIX86(_dec_cx)(i8086_state *cpustate)    /* Opcode 0x49 */\r
1284 {\r
1285         DecWordReg(CX);\r
1286 }\r
1287 \r
1288 static void PREFIX86(_dec_dx)(i8086_state *cpustate)    /* Opcode 0x4a */\r
1289 {\r
1290         DecWordReg(DX);\r
1291 }\r
1292 \r
1293 static void PREFIX86(_dec_bx)(i8086_state *cpustate)    /* Opcode 0x4b */\r
1294 {\r
1295         DecWordReg(BX);\r
1296 }\r
1297 \r
1298 static void PREFIX86(_dec_sp)(i8086_state *cpustate)    /* Opcode 0x4c */\r
1299 {\r
1300         DecWordReg(SP);\r
1301 }\r
1302 \r
1303 static void PREFIX86(_dec_bp)(i8086_state *cpustate)    /* Opcode 0x4d */\r
1304 {\r
1305         DecWordReg(BP);\r
1306 }\r
1307 \r
1308 static void PREFIX86(_dec_si)(i8086_state *cpustate)    /* Opcode 0x4e */\r
1309 {\r
1310         DecWordReg(SI);\r
1311 }\r
1312 \r
1313 static void PREFIX86(_dec_di)(i8086_state *cpustate)    /* Opcode 0x4f */\r
1314 {\r
1315         DecWordReg(DI);\r
1316 }\r
1317 \r
1318 static void PREFIX86(_push_ax)(i8086_state *cpustate)    /* Opcode 0x50 */\r
1319 {\r
1320         ICOUNT -= timing.push_r16;\r
1321         PUSH(cpustate->regs.w[AX]);\r
1322 }\r
1323 \r
1324 static void PREFIX86(_push_cx)(i8086_state *cpustate)    /* Opcode 0x51 */\r
1325 {\r
1326         ICOUNT -= timing.push_r16;\r
1327         PUSH(cpustate->regs.w[CX]);\r
1328 }\r
1329 \r
1330 static void PREFIX86(_push_dx)(i8086_state *cpustate)    /* Opcode 0x52 */\r
1331 {\r
1332         ICOUNT -= timing.push_r16;\r
1333         PUSH(cpustate->regs.w[DX]);\r
1334 }\r
1335 \r
1336 static void PREFIX86(_push_bx)(i8086_state *cpustate)    /* Opcode 0x53 */\r
1337 {\r
1338         ICOUNT -= timing.push_r16;\r
1339         PUSH(cpustate->regs.w[BX]);\r
1340 }\r
1341 \r
1342 static void PREFIX86(_push_sp)(i8086_state *cpustate)    /* Opcode 0x54 */\r
1343 {\r
1344         ICOUNT -= timing.push_r16;\r
1345 #ifdef I80286\r
1346         PUSH(cpustate->regs.w[SP]+2);\r
1347 #else\r
1348         PUSH(cpustate->regs.w[SP]);\r
1349 #endif\r
1350 }\r
1351 \r
1352 static void PREFIX86(_push_bp)(i8086_state *cpustate)    /* Opcode 0x55 */\r
1353 {\r
1354         ICOUNT -= timing.push_r16;\r
1355         PUSH(cpustate->regs.w[BP]);\r
1356 }\r
1357 \r
1358 \r
1359 static void PREFIX86(_push_si)(i8086_state *cpustate)    /* Opcode 0x56 */\r
1360 {\r
1361         ICOUNT -= timing.push_r16;\r
1362         PUSH(cpustate->regs.w[SI]);\r
1363 }\r
1364 \r
1365 static void PREFIX86(_push_di)(i8086_state *cpustate)    /* Opcode 0x57 */\r
1366 {\r
1367         ICOUNT -= timing.push_r16;\r
1368         PUSH(cpustate->regs.w[DI]);\r
1369 }\r
1370 \r
1371 static void PREFIX86(_pop_ax)(i8086_state *cpustate)    /* Opcode 0x58 */\r
1372 {\r
1373         ICOUNT -= timing.pop_r16;\r
1374         POP(cpustate->regs.w[AX]);\r
1375 }\r
1376 \r
1377 static void PREFIX86(_pop_cx)(i8086_state *cpustate)    /* Opcode 0x59 */\r
1378 {\r
1379         ICOUNT -= timing.pop_r16;\r
1380         POP(cpustate->regs.w[CX]);\r
1381 }\r
1382 \r
1383 static void PREFIX86(_pop_dx)(i8086_state *cpustate)    /* Opcode 0x5a */\r
1384 {\r
1385         ICOUNT -= timing.pop_r16;\r
1386         POP(cpustate->regs.w[DX]);\r
1387 }\r
1388 \r
1389 static void PREFIX86(_pop_bx)(i8086_state *cpustate)    /* Opcode 0x5b */\r
1390 {\r
1391         ICOUNT -= timing.pop_r16;\r
1392         POP(cpustate->regs.w[BX]);\r
1393 }\r
1394 \r
1395 static void PREFIX86(_pop_sp)(i8086_state *cpustate)    /* Opcode 0x5c */\r
1396 {\r
1397         ICOUNT -= timing.pop_r16;\r
1398         POP(cpustate->regs.w[SP]);\r
1399 }\r
1400 \r
1401 static void PREFIX86(_pop_bp)(i8086_state *cpustate)    /* Opcode 0x5d */\r
1402 {\r
1403         ICOUNT -= timing.pop_r16;\r
1404         POP(cpustate->regs.w[BP]);\r
1405 }\r
1406 \r
1407 static void PREFIX86(_pop_si)(i8086_state *cpustate)    /* Opcode 0x5e */\r
1408 {\r
1409         ICOUNT -= timing.pop_r16;\r
1410         POP(cpustate->regs.w[SI]);\r
1411 }\r
1412 \r
1413 static void PREFIX86(_pop_di)(i8086_state *cpustate)    /* Opcode 0x5f */\r
1414 {\r
1415         ICOUNT -= timing.pop_r16;\r
1416         POP(cpustate->regs.w[DI]);\r
1417 }\r
1418 \r
1419 static void PREFIX86(_jo)(i8086_state *cpustate)    /* Opcode 0x70 */\r
1420 {\r
1421         int tmp = (int)((INT8)FETCH);\r
1422         if (OF)\r
1423         {\r
1424                 cpustate->pc += tmp;\r
1425                 ICOUNT -= timing.jcc_t;\r
1426 /* ASG - can probably assume this is safe\r
1427         CHANGE_PC(cpustate->pc);*/\r
1428         } else ICOUNT -= timing.jcc_nt;\r
1429 }\r
1430 \r
1431 static void PREFIX86(_jno)(i8086_state *cpustate)    /* Opcode 0x71 */\r
1432 {\r
1433         int tmp = (int)((INT8)FETCH);\r
1434         if (!OF) {\r
1435                 cpustate->pc += tmp;\r
1436                 ICOUNT -= timing.jcc_t;\r
1437 /* ASG - can probably assume this is safe\r
1438         CHANGE_PC(cpustate->pc);*/\r
1439         } else ICOUNT -= timing.jcc_nt;\r
1440 }\r
1441 \r
1442 static void PREFIX86(_jb)(i8086_state *cpustate)    /* Opcode 0x72 */\r
1443 {\r
1444         int tmp = (int)((INT8)FETCH);\r
1445         if (CF) {\r
1446                 cpustate->pc += tmp;\r
1447                 ICOUNT -= timing.jcc_t;\r
1448 /* ASG - can probably assume this is safe\r
1449         CHANGE_PC(cpustate->pc);*/\r
1450         } else ICOUNT -= timing.jcc_nt;\r
1451 }\r
1452 \r
1453 static void PREFIX86(_jnb)(i8086_state *cpustate)    /* Opcode 0x73 */\r
1454 {\r
1455         int tmp = (int)((INT8)FETCH);\r
1456         if (!CF) {\r
1457                 cpustate->pc += tmp;\r
1458                 ICOUNT -= timing.jcc_t;\r
1459 /* ASG - can probably assume this is safe\r
1460         CHANGE_PC(cpustate->pc);*/\r
1461         } else ICOUNT -= timing.jcc_nt;\r
1462 }\r
1463 \r
1464 static void PREFIX86(_jz)(i8086_state *cpustate)    /* Opcode 0x74 */\r
1465 {\r
1466         int tmp = (int)((INT8)FETCH);\r
1467         if (ZF) {\r
1468                 cpustate->pc += tmp;\r
1469                 ICOUNT -= timing.jcc_t;\r
1470 /* ASG - can probably assume this is safe\r
1471         CHANGE_PC(cpustate->pc);*/\r
1472         } else ICOUNT -= timing.jcc_nt;\r
1473 }\r
1474 \r
1475 static void PREFIX86(_jnz)(i8086_state *cpustate)    /* Opcode 0x75 */\r
1476 {\r
1477         int tmp = (int)((INT8)FETCH);\r
1478         if (!ZF) {\r
1479                 cpustate->pc += tmp;\r
1480                 ICOUNT -= timing.jcc_t;\r
1481 /* ASG - can probably assume this is safe\r
1482         CHANGE_PC(cpustate->pc);*/\r
1483         } else ICOUNT -= timing.jcc_nt;\r
1484 }\r
1485 \r
1486 static void PREFIX86(_jbe)(i8086_state *cpustate)    /* Opcode 0x76 */\r
1487 {\r
1488         int tmp = (int)((INT8)FETCH);\r
1489         if (CF || ZF) {\r
1490                 cpustate->pc += tmp;\r
1491                 ICOUNT -= timing.jcc_t;\r
1492 /* ASG - can probably assume this is safe\r
1493         CHANGE_PC(cpustate->pc);*/\r
1494         } else ICOUNT -= timing.jcc_nt;\r
1495 }\r
1496 \r
1497 static void PREFIX86(_jnbe)(i8086_state *cpustate)    /* Opcode 0x77 */\r
1498 {\r
1499         int tmp = (int)((INT8)FETCH);\r
1500         if (!(CF || ZF)) {\r
1501                 cpustate->pc += tmp;\r
1502                 ICOUNT -= timing.jcc_t;\r
1503 /* ASG - can probably assume this is safe\r
1504         CHANGE_PC(cpustate->pc);*/\r
1505         } else ICOUNT -= timing.jcc_nt;\r
1506 }\r
1507 \r
1508 static void PREFIX86(_js)(i8086_state *cpustate)    /* Opcode 0x78 */\r
1509 {\r
1510         int tmp = (int)((INT8)FETCH);\r
1511         if (SF) {\r
1512                 cpustate->pc += tmp;\r
1513                 ICOUNT -= timing.jcc_t;\r
1514 /* ASG - can probably assume this is safe\r
1515         CHANGE_PC(cpustate->pc);*/\r
1516         } else ICOUNT -= timing.jcc_nt;\r
1517 }\r
1518 \r
1519 static void PREFIX86(_jns)(i8086_state *cpustate)    /* Opcode 0x79 */\r
1520 {\r
1521         int tmp = (int)((INT8)FETCH);\r
1522         if (!SF) {\r
1523                 cpustate->pc += tmp;\r
1524                 ICOUNT -= timing.jcc_t;\r
1525 /* ASG - can probably assume this is safe\r
1526         CHANGE_PC(cpustate->pc);*/\r
1527         } else ICOUNT -= timing.jcc_nt;\r
1528 }\r
1529 \r
1530 static void PREFIX86(_jp)(i8086_state *cpustate)    /* Opcode 0x7a */\r
1531 {\r
1532         int tmp = (int)((INT8)FETCH);\r
1533         if (PF) {\r
1534                 cpustate->pc += tmp;\r
1535                 ICOUNT -= timing.jcc_t;\r
1536 /* ASG - can probably assume this is safe\r
1537         CHANGE_PC(cpustate->pc);*/\r
1538         } else ICOUNT -= timing.jcc_nt;\r
1539 }\r
1540 \r
1541 static void PREFIX86(_jnp)(i8086_state *cpustate)    /* Opcode 0x7b */\r
1542 {\r
1543         int tmp = (int)((INT8)FETCH);\r
1544         if (!PF) {\r
1545                 cpustate->pc += tmp;\r
1546                 ICOUNT -= timing.jcc_t;\r
1547 /* ASG - can probably assume this is safe\r
1548         CHANGE_PC(cpustate->pc);*/\r
1549         } else ICOUNT -= timing.jcc_nt;\r
1550 }\r
1551 \r
1552 static void PREFIX86(_jl)(i8086_state *cpustate)    /* Opcode 0x7c */\r
1553 {\r
1554         int tmp = (int)((INT8)FETCH);\r
1555         if ((SF!=OF)&&!ZF) {\r
1556                 cpustate->pc += tmp;\r
1557                 ICOUNT -= timing.jcc_t;\r
1558 /* ASG - can probably assume this is safe\r
1559         CHANGE_PC(cpustate->pc);*/\r
1560         } else ICOUNT -= timing.jcc_nt;\r
1561 }\r
1562 \r
1563 static void PREFIX86(_jnl)(i8086_state *cpustate)    /* Opcode 0x7d */\r
1564 {\r
1565         int tmp = (int)((INT8)FETCH);\r
1566         if (ZF||(SF==OF)) {\r
1567                 cpustate->pc += tmp;\r
1568                 ICOUNT -= timing.jcc_t;\r
1569 /* ASG - can probably assume this is safe\r
1570         CHANGE_PC(cpustate->pc);*/\r
1571         } else ICOUNT -= timing.jcc_nt;\r
1572 }\r
1573 \r
1574 static void PREFIX86(_jle)(i8086_state *cpustate)    /* Opcode 0x7e */\r
1575 {\r
1576         int tmp = (int)((INT8)FETCH);\r
1577         if (ZF||(SF!=OF)) {\r
1578                 cpustate->pc += tmp;\r
1579                 ICOUNT -= timing.jcc_t;\r
1580 /* ASG - can probably assume this is safe\r
1581         CHANGE_PC(cpustate->pc);*/\r
1582         } else ICOUNT -= timing.jcc_nt;\r
1583 }\r
1584 \r
1585 static void PREFIX86(_jnle)(i8086_state *cpustate)    /* Opcode 0x7f */\r
1586 {\r
1587         int tmp = (int)((INT8)FETCH);\r
1588         if ((SF==OF)&&!ZF) {\r
1589                 cpustate->pc += tmp;\r
1590                 ICOUNT -= timing.jcc_t;\r
1591 /* ASG - can probably assume this is safe\r
1592         CHANGE_PC(cpustate->pc);*/\r
1593         } else ICOUNT -= timing.jcc_nt;\r
1594 }\r
1595 \r
1596 static void PREFIX86(_80pre)(i8086_state *cpustate)    /* Opcode 0x80 */\r
1597 {\r
1598         unsigned ModRM = FETCHOP;\r
1599         unsigned dst = GetRMByte(ModRM);\r
1600         unsigned src = FETCH;\r
1601         int tmpcf;\r
1602 \r
1603         switch (ModRM & 0x38)\r
1604         {\r
1605         case 0x00:  /* ADD eb,d8 */\r
1606                 ADDB(dst,src);\r
1607                 PutbackRMByte(ModRM,dst);\r
1608                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1609                 break;\r
1610         case 0x08:  /* OR eb,d8 */\r
1611                 ORB(dst,src);\r
1612                 PutbackRMByte(ModRM,dst);\r
1613                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1614                 break;\r
1615         case 0x10:  /* ADC eb,d8 */\r
1616                 src+=CF;\r
1617                 ADCB(dst,src,tmpcf);\r
1618                 PutbackRMByte(ModRM,dst);\r
1619                 cpustate->CarryVal = tmpcf;\r
1620                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1621                 break;\r
1622         case 0x18:  /* SBB eb,b8 */\r
1623                 src+=CF;\r
1624                 SBBB(dst,src,tmpcf);\r
1625                 PutbackRMByte(ModRM,dst);\r
1626                 cpustate->CarryVal = tmpcf;\r
1627                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1628                 break;\r
1629         case 0x20:  /* AND eb,d8 */\r
1630                 ANDB(dst,src);\r
1631                 PutbackRMByte(ModRM,dst);\r
1632                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1633                 break;\r
1634         case 0x28:  /* SUB eb,d8 */\r
1635                 SUBB(dst,src);\r
1636                 PutbackRMByte(ModRM,dst);\r
1637                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1638                 break;\r
1639         case 0x30:  /* XOR eb,d8 */\r
1640                 XORB(dst,src);\r
1641                 PutbackRMByte(ModRM,dst);\r
1642                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1643                 break;\r
1644         case 0x38:  /* CMP eb,d8 */\r
1645                 SUBB(dst,src);\r
1646                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;\r
1647                 break;\r
1648         }\r
1649 }\r
1650 \r
1651 \r
1652 static void PREFIX86(_81pre)(i8086_state *cpustate)    /* Opcode 0x81 */\r
1653 {\r
1654         unsigned ModRM = FETCH;\r
1655         unsigned dst = GetRMWord(ModRM);\r
1656         unsigned src = FETCH;\r
1657         int tmpcf;\r
1658         src+= (FETCH << 8);\r
1659 \r
1660         switch (ModRM & 0x38)\r
1661         {\r
1662         case 0x00:  /* ADD ew,d16 */\r
1663                 ADDW(dst,src);\r
1664                 PutbackRMWord(ModRM,dst);\r
1665                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;\r
1666                 break;\r
1667         case 0x08:  /* OR ew,d16 */\r
1668                 ORW(dst,src);\r
1669                 PutbackRMWord(ModRM,dst);\r
1670                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;\r
1671                 break;\r
1672         case 0x10:  /* ADC ew,d16 */\r
1673                 src+=CF;\r
1674                 ADCW(dst,src,tmpcf);\r
1675                 PutbackRMWord(ModRM,dst);\r
1676                 cpustate->CarryVal = tmpcf;\r
1677                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;\r
1678                 break;\r
1679         case 0x18:  /* SBB ew,d16 */\r
1680                 src+=CF;\r
1681                 SBBW(dst,src,tmpcf);\r
1682                 PutbackRMWord(ModRM,dst);\r
1683                 cpustate->CarryVal = tmpcf;\r
1684                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;\r
1685                 break;\r
1686         case 0x20:  /* AND ew,d16 */\r
1687                 ANDW(dst,src);\r
1688                 PutbackRMWord(ModRM,dst);\r
1689                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;\r
1690                 break;\r
1691         case 0x28:  /* SUB ew,d16 */\r
1692                 SUBW(dst,src);\r
1693                 PutbackRMWord(ModRM,dst);\r
1694                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;\r
1695                 break;\r
1696         case 0x30:  /* XOR ew,d16 */\r
1697                 XORW(dst,src);\r
1698                 PutbackRMWord(ModRM,dst);\r
1699                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16;\r
1700                 break;\r
1701         case 0x38:  /* CMP ew,d16 */\r
1702                 SUBW(dst,src);\r
1703                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;\r
1704                 break;\r
1705         }\r
1706 }\r
1707 \r
1708 static void PREFIX86(_82pre)(i8086_state *cpustate)  /* Opcode 0x82 */\r
1709 {\r
1710         unsigned ModRM = FETCH;\r
1711         unsigned dst = GetRMByte(ModRM);\r
1712         unsigned src = FETCH;\r
1713         int tmpcf;\r
1714 \r
1715         switch (ModRM & 0x38)\r
1716         {\r
1717         case 0x00:  /* ADD eb,d8 */\r
1718                 ADDB(dst,src);\r
1719                 PutbackRMByte(ModRM,dst);\r
1720                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1721                 break;\r
1722         case 0x08:  /* OR eb,d8 */\r
1723                 ORB(dst,src);\r
1724                 PutbackRMByte(ModRM,dst);\r
1725                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1726                 break;\r
1727         case 0x10:  /* ADC eb,d8 */\r
1728                 src+=CF;\r
1729                 ADCB(dst,src,tmpcf);\r
1730                 PutbackRMByte(ModRM,dst);\r
1731                 cpustate->CarryVal = tmpcf;\r
1732                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1733                 break;\r
1734         case 0x18:  /* SBB eb,d8 */\r
1735                 src+=CF;\r
1736                 SBBB(dst,src,tmpcf);\r
1737                 PutbackRMByte(ModRM,dst);\r
1738                 cpustate->CarryVal = tmpcf;\r
1739                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1740                 break;\r
1741         case 0x20:  /* AND eb,d8 */\r
1742                 ANDB(dst,src);\r
1743                 PutbackRMByte(ModRM,dst);\r
1744                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1745                 break;\r
1746         case 0x28:  /* SUB eb,d8 */\r
1747                 SUBB(dst,src);\r
1748                 PutbackRMByte(ModRM,dst);\r
1749                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1750                 break;\r
1751         case 0x30:  /* XOR eb,d8 */\r
1752                 XORB(dst,src);\r
1753                 PutbackRMByte(ModRM,dst);\r
1754                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8;\r
1755                 break;\r
1756         case 0x38:  /* CMP eb,d8 */\r
1757                 SUBB(dst,src);\r
1758                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;\r
1759                 break;\r
1760         }\r
1761 }\r
1762 \r
1763 static void PREFIX86(_83pre)(i8086_state *cpustate)    /* Opcode 0x83 */\r
1764 {\r
1765         unsigned ModRM = FETCH;\r
1766         unsigned dst = GetRMWord(ModRM);\r
1767         unsigned src = (WORD)((INT16)((INT8)FETCH));\r
1768         int tmpcf;\r
1769 \r
1770         switch (ModRM & 0x38)\r
1771         {\r
1772         case 0x00:  /* ADD ew,d16 */\r
1773                 ADDW(dst,src);\r
1774                 PutbackRMWord(ModRM,dst);\r
1775                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;\r
1776                 break;\r
1777         case 0x08:  /* OR ew,d16 */\r
1778                 ORW(dst,src);\r
1779                 PutbackRMWord(ModRM,dst);\r
1780                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;\r
1781                 break;\r
1782         case 0x10:  /* ADC ew,d16 */\r
1783                 src+=CF;\r
1784                 ADCW(dst,src,tmpcf);\r
1785                 PutbackRMWord(ModRM,dst);\r
1786                 cpustate->CarryVal = tmpcf;\r
1787                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;\r
1788                 break;\r
1789         case 0x18:  /* SBB ew,d16 */\r
1790                 src+=CF;\r
1791                 SBBW(dst,src,tmpcf);\r
1792                 PutbackRMWord(ModRM,dst);\r
1793                 cpustate->CarryVal = tmpcf;\r
1794                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;\r
1795                 break;\r
1796         case 0x20:  /* AND ew,d16 */\r
1797                 ANDW(dst,src);\r
1798                 PutbackRMWord(ModRM,dst);\r
1799                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;\r
1800                 break;\r
1801         case 0x28:  /* SUB ew,d16 */\r
1802                 SUBW(dst,src);\r
1803                 PutbackRMWord(ModRM,dst);\r
1804                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;\r
1805                 break;\r
1806         case 0x30:  /* XOR ew,d16 */\r
1807                 XORW(dst,src);\r
1808                 PutbackRMWord(ModRM,dst);\r
1809                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8;\r
1810                 break;\r
1811         case 0x38:  /* CMP ew,d16 */\r
1812                 SUBW(dst,src);\r
1813                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_r16i8 : timing.alu_m16i8_ro;\r
1814                 break;\r
1815         }\r
1816 }\r
1817 \r
1818 static void PREFIX86(_test_br8)(i8086_state *cpustate)    /* Opcode 0x84 */\r
1819 {\r
1820         DEF_br8(dst,src);\r
1821         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr8 : timing.alu_rm8;\r
1822         ANDB(dst,src);\r
1823 }\r
1824 \r
1825 static void PREFIX86(_test_wr16)(i8086_state *cpustate)    /* Opcode 0x85 */\r
1826 {\r
1827         DEF_wr16(dst,src);\r
1828         ICOUNT -= (ModRM >= 0xc0) ? timing.alu_rr16 : timing.alu_rm16;\r
1829         ANDW(dst,src);\r
1830 }\r
1831 \r
1832 static void PREFIX86(_xchg_br8)(i8086_state *cpustate)    /* Opcode 0x86 */\r
1833 {\r
1834         DEF_br8(dst,src);\r
1835         ICOUNT -= (ModRM >= 0xc0) ? timing.xchg_rr8 : timing.xchg_rm8;\r
1836         PutbackRMByte(ModRM,src);\r
1837         RegByte(ModRM)=dst;\r
1838 }\r
1839 \r
1840 static void PREFIX86(_xchg_wr16)(i8086_state *cpustate)    /* Opcode 0x87 */\r
1841 {\r
1842         DEF_wr16(dst,src);\r
1843         ICOUNT -= (ModRM >= 0xc0) ? timing.xchg_rr16 : timing.xchg_rm16;\r
1844         PutbackRMWord(ModRM,src);\r
1845         RegWord(ModRM)=dst;\r
1846 }\r
1847 \r
1848 static void PREFIX86(_mov_br8)(i8086_state *cpustate)    /* Opcode 0x88 */\r
1849 {\r
1850         unsigned ModRM = FETCH;\r
1851         BYTE src = RegByte(ModRM);\r
1852         ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_mr8;\r
1853         PutRMByte(ModRM,src);\r
1854 }\r
1855 \r
1856 static void PREFIX86(_mov_wr16)(i8086_state *cpustate)    /* Opcode 0x89 */\r
1857 {\r
1858         unsigned ModRM = FETCH;\r
1859         WORD src = RegWord(ModRM);\r
1860         ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr16 : timing.mov_mr16;\r
1861         PutRMWord(ModRM,src);\r
1862 }\r
1863 \r
1864 static void PREFIX86(_mov_r8b)(i8086_state *cpustate)    /* Opcode 0x8a */\r
1865 {\r
1866         unsigned ModRM = FETCH;\r
1867         BYTE src = GetRMByte(ModRM);\r
1868         ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm8;\r
1869         RegByte(ModRM)=src;\r
1870 }\r
1871 \r
1872 static void PREFIX86(_mov_r16w)(i8086_state *cpustate)    /* Opcode 0x8b */\r
1873 {\r
1874         unsigned ModRM = FETCH;\r
1875         WORD src = GetRMWord(ModRM);\r
1876         ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rr8 : timing.mov_rm16;\r
1877         RegWord(ModRM)=src;\r
1878 }\r
1879 \r
1880 static void PREFIX86(_mov_wsreg)(i8086_state *cpustate)    /* Opcode 0x8c */\r
1881 {\r
1882         unsigned ModRM = FETCH;\r
1883         ICOUNT -= (ModRM >= 0xc0) ? timing.mov_rs : timing.mov_ms;\r
1884         if (ModRM & 0x20) { /* HJB 12/13/98 1xx is invalid */\r
1885                 cpustate->pc = cpustate->prevpc;\r
1886                 return PREFIX86(_invalid)(cpustate);\r
1887         }\r
1888 \r
1889         PutRMWord(ModRM,cpustate->sregs[(ModRM & 0x38) >> 3]);\r
1890 }\r
1891 \r
1892 static void PREFIX86(_lea)(i8086_state *cpustate)    /* Opcode 0x8d */\r
1893 {\r
1894         unsigned ModRM = FETCH;\r
1895         ICOUNT -= timing.lea;\r
1896         (void)(*GetEA[ModRM])(cpustate);\r
1897         RegWord(ModRM)=cpustate->eo;    /* HJB 12/13/98 effective offset (no segment part) */\r
1898 }\r
1899 \r
1900 static void PREFIX86(_popw)(i8086_state *cpustate)    /* Opcode 0x8f */\r
1901 {\r
1902         unsigned ModRM = FETCH;\r
1903                 WORD tmp;\r
1904         tmp = ReadWord(cpustate->base[SS] + cpustate->regs.w[SP]);\r
1905         ICOUNT -= (ModRM >= 0xc0) ? timing.pop_r16 : timing.pop_m16;\r
1906         PutRMWord(ModRM,tmp);\r
1907         cpustate->regs.w[SP] += 2;\r
1908 }\r
1909 \r
1910 \r
1911 #define XchgAXReg(Reg)              \\r
1912 {                                   \\r
1913         WORD tmp;                       \\r
1914         tmp = cpustate->regs.w[Reg];            \\r
1915         cpustate->regs.w[Reg] = cpustate->regs.w[AX];   \\r
1916         cpustate->regs.w[AX] = tmp;             \\r
1917         ICOUNT -= timing.xchg_ar16;     \\r
1918 }\r
1919 \r
1920 \r
1921 static void PREFIX86(_nop)(i8086_state *cpustate)    /* Opcode 0x90 */\r
1922 {\r
1923         /* this is XchgAXReg(AX); */\r
1924         ICOUNT -= timing.nop;\r
1925 }\r
1926 \r
1927 static void PREFIX86(_xchg_axcx)(i8086_state *cpustate)    /* Opcode 0x91 */\r
1928 {\r
1929         XchgAXReg(CX);\r
1930 }\r
1931 \r
1932 static void PREFIX86(_xchg_axdx)(i8086_state *cpustate)    /* Opcode 0x92 */\r
1933 {\r
1934         XchgAXReg(DX);\r
1935 }\r
1936 \r
1937 static void PREFIX86(_xchg_axbx)(i8086_state *cpustate)    /* Opcode 0x93 */\r
1938 {\r
1939         XchgAXReg(BX);\r
1940 }\r
1941 \r
1942 static void PREFIX86(_xchg_axsp)(i8086_state *cpustate)    /* Opcode 0x94 */\r
1943 {\r
1944         XchgAXReg(SP);\r
1945 }\r
1946 \r
1947 static void PREFIX86(_xchg_axbp)(i8086_state *cpustate)    /* Opcode 0x95 */\r
1948 {\r
1949         XchgAXReg(BP);\r
1950 }\r
1951 \r
1952 static void PREFIX86(_xchg_axsi)(i8086_state *cpustate)    /* Opcode 0x96 */\r
1953 {\r
1954         XchgAXReg(SI);\r
1955 }\r
1956 \r
1957 static void PREFIX86(_xchg_axdi)(i8086_state *cpustate)    /* Opcode 0x97 */\r
1958 {\r
1959         XchgAXReg(DI);\r
1960 }\r
1961 \r
1962 static void PREFIX86(_cbw)(i8086_state *cpustate)    /* Opcode 0x98 */\r
1963 {\r
1964         ICOUNT -= timing.cbw;\r
1965         cpustate->regs.b[AH] = (cpustate->regs.b[AL] & 0x80) ? 0xff : 0;\r
1966 }\r
1967 \r
1968 static void PREFIX86(_cwd)(i8086_state *cpustate)    /* Opcode 0x99 */\r
1969 {\r
1970         ICOUNT -= timing.cwd;\r
1971         cpustate->regs.w[DX] = (cpustate->regs.b[AH] & 0x80) ? 0xffff : 0;\r
1972 }\r
1973 \r
1974 static void PREFIX86(_call_far)(i8086_state *cpustate)\r
1975 {\r
1976         unsigned int tmp, tmp2;\r
1977         WORD cs, ip;\r
1978 \r
1979         tmp = FETCH;\r
1980         tmp += FETCH << 8;\r
1981 \r
1982         tmp2 = FETCH;\r
1983         tmp2 += FETCH << 8;\r
1984 \r
1985 #ifdef I86_BIOS_CALL\r
1986         if(cpustate->bios != NULL && cpustate->bios->bios_call(((tmp2 << 4) + tmp) & AMASK, cpustate->regs.w, cpustate->sregs, &cpustate->ZeroVal, &cpustate->CarryVal)) {\r
1987                 ICOUNT -= timing.call_far;\r
1988                 return;\r
1989         }\r
1990 #endif\r
1991 \r
1992         ip = cpustate->pc - cpustate->base[CS];\r
1993         cs = cpustate->sregs[CS];\r
1994 \r
1995 #ifdef I80286\r
1996         i80286_code_descriptor(cpustate, tmp2, tmp, 2);\r
1997 #else\r
1998         cpustate->sregs[CS] = (WORD)tmp2;\r
1999         cpustate->base[CS] = SegBase(CS);\r
2000         cpustate->pc = (cpustate->base[CS] + (WORD)tmp) & AMASK;\r
2001 #endif\r
2002         PUSH(cs);\r
2003         PUSH(ip);\r
2004         ICOUNT -= timing.call_far;\r
2005         CHANGE_PC(cpustate->pc);\r
2006 }\r
2007 \r
2008 static void PREFIX86(_wait)(i8086_state *cpustate)    /* Opcode 0x9b */\r
2009 {\r
2010 #ifdef I80286\r
2011         if ((cpustate->msw&0x0a) == 0x0a) throw TRAP(FPU_UNAVAILABLE,-1);\r
2012 #endif\r
2013         if (cpustate->test_state)\r
2014         {\r
2015                 ICOUNT = 0;\r
2016                 cpustate->pc--;\r
2017         }\r
2018         else\r
2019                 ICOUNT -= timing.wait;\r
2020 }\r
2021 \r
2022 static void PREFIX86(_pushf)(i8086_state *cpustate)    /* Opcode 0x9c */\r
2023 {\r
2024         unsigned tmp;\r
2025         ICOUNT -= timing.pushf;\r
2026 \r
2027         tmp = CompressFlags();\r
2028 #ifdef I80286\r
2029         if(!PM) ( tmp &= ~0xf000 );\r
2030 #endif\r
2031         PUSH( tmp );\r
2032 }\r
2033 \r
2034 #ifndef I80286\r
2035 static void PREFIX86(_popf)(i8086_state *cpustate)    /* Opcode 0x9d */\r
2036 {\r
2037         unsigned tmp;\r
2038         POP(tmp);\r
2039         ICOUNT -= timing.popf;\r
2040 \r
2041         ExpandFlags(tmp);\r
2042         cpustate->flags = tmp;\r
2043         cpustate->flags = CompressFlags();\r
2044 \r
2045         if (cpustate->TF) PREFIX(_trap)(cpustate);\r
2046 \r
2047         /* if the IF is set, and an interrupt is pending, signal an interrupt */\r
2048         if (cpustate->IF && cpustate->irq_state) {\r
2049                 PREFIX(_interrupt)(cpustate, (UINT32)-1);\r
2050                 cpustate->irq_state = 0;\r
2051         }\r
2052 }\r
2053 #endif\r
2054 \r
2055 static void PREFIX86(_sahf)(i8086_state *cpustate)    /* Opcode 0x9e */\r
2056 {\r
2057         unsigned tmp = (CompressFlags() & 0xff00) | (cpustate->regs.b[AH] & 0xd5);\r
2058         ICOUNT -= timing.sahf;\r
2059         ExpandFlags(tmp);\r
2060 }\r
2061 \r
2062 static void PREFIX86(_lahf)(i8086_state *cpustate)    /* Opcode 0x9f */\r
2063 {\r
2064         cpustate->regs.b[AH] = CompressFlags() & 0xff;\r
2065         ICOUNT -= timing.lahf;\r
2066 }\r
2067 \r
2068 \r
2069 static void PREFIX86(_mov_aldisp)(i8086_state *cpustate)    /* Opcode 0xa0 */\r
2070 {\r
2071         unsigned addr;\r
2072 \r
2073         addr = FETCH;\r
2074         addr += FETCH << 8;\r
2075 \r
2076         ICOUNT -= timing.mov_am8;\r
2077         cpustate->regs.b[AL] = GetMemB(DS, addr);\r
2078 }\r
2079 \r
2080 static void PREFIX86(_mov_axdisp)(i8086_state *cpustate)    /* Opcode 0xa1 */\r
2081 {\r
2082         unsigned addr;\r
2083 \r
2084         addr = FETCH;\r
2085         addr += FETCH << 8;\r
2086 \r
2087         ICOUNT -= timing.mov_am16;\r
2088         cpustate->regs.w[AX] = GetMemW(DS, addr);\r
2089 }\r
2090 \r
2091 static void PREFIX86(_mov_dispal)(i8086_state *cpustate)    /* Opcode 0xa2 */\r
2092 {\r
2093         unsigned addr;\r
2094 \r
2095         addr = FETCH;\r
2096         addr += FETCH << 8;\r
2097 \r
2098         ICOUNT -= timing.mov_ma8;\r
2099         PutMemB(DS, addr, cpustate->regs.b[AL]);\r
2100 }\r
2101 \r
2102 static void PREFIX86(_mov_dispax)(i8086_state *cpustate)    /* Opcode 0xa3 */\r
2103 {\r
2104         unsigned addr;\r
2105 \r
2106         addr = FETCH;\r
2107         addr += FETCH << 8;\r
2108 \r
2109         ICOUNT -= timing.mov_ma16;\r
2110         PutMemW(DS, addr, cpustate->regs.w[AX]);\r
2111 }\r
2112 \r
2113 static void PREFIX86(_movsb)(i8086_state *cpustate)    /* Opcode 0xa4 */\r
2114 {\r
2115         BYTE tmp = GetMemB(DS,cpustate->regs.w[SI]);\r
2116         PutMemB(ES,cpustate->regs.w[DI], tmp);\r
2117         cpustate->regs.w[DI] += cpustate->DirVal;\r
2118         cpustate->regs.w[SI] += cpustate->DirVal;\r
2119         ICOUNT -= timing.movs8;\r
2120 }\r
2121 \r
2122 static void PREFIX86(_movsw)(i8086_state *cpustate)    /* Opcode 0xa5 */\r
2123 {\r
2124         WORD tmp = GetMemW(DS,cpustate->regs.w[SI]);\r
2125         PutMemW(ES,cpustate->regs.w[DI], tmp);\r
2126         cpustate->regs.w[DI] += 2 * cpustate->DirVal;\r
2127         cpustate->regs.w[SI] += 2 * cpustate->DirVal;\r
2128         ICOUNT -= timing.movs16;\r
2129 }\r
2130 \r
2131 static void PREFIX86(_cmpsb)(i8086_state *cpustate)    /* Opcode 0xa6 */\r
2132 {\r
2133         unsigned dst = GetMemB(ES, cpustate->regs.w[DI]);\r
2134         unsigned src = GetMemB(DS, cpustate->regs.w[SI]);\r
2135         SUBB(src,dst); /* opposite of the usual convention */\r
2136         cpustate->regs.w[DI] += cpustate->DirVal;\r
2137         cpustate->regs.w[SI] += cpustate->DirVal;\r
2138         ICOUNT -= timing.cmps8;\r
2139 }\r
2140 \r
2141 static void PREFIX86(_cmpsw)(i8086_state *cpustate)    /* Opcode 0xa7 */\r
2142 {\r
2143         unsigned dst = GetMemW(ES, cpustate->regs.w[DI]);\r
2144         unsigned src = GetMemW(DS, cpustate->regs.w[SI]);\r
2145         SUBW(src,dst); /* opposite of the usual convention */\r
2146         cpustate->regs.w[DI] += 2 * cpustate->DirVal;\r
2147         cpustate->regs.w[SI] += 2 * cpustate->DirVal;\r
2148         ICOUNT -= timing.cmps16;\r
2149 }\r
2150 \r
2151 static void PREFIX86(_test_ald8)(i8086_state *cpustate)    /* Opcode 0xa8 */\r
2152 {\r
2153         DEF_ald8(dst,src);\r
2154         ICOUNT -= timing.alu_ri8;\r
2155         ANDB(dst,src);\r
2156 }\r
2157 \r
2158 static void PREFIX86(_test_axd16)(i8086_state *cpustate)    /* Opcode 0xa9 */\r
2159 {\r
2160         DEF_axd16(dst,src);\r
2161         ICOUNT -= timing.alu_ri16;\r
2162         ANDW(dst,src);\r
2163 }\r
2164 \r
2165 static void PREFIX86(_stosb)(i8086_state *cpustate)    /* Opcode 0xaa */\r
2166 {\r
2167         PutMemB(ES,cpustate->regs.w[DI],cpustate->regs.b[AL]);\r
2168         cpustate->regs.w[DI] += cpustate->DirVal;\r
2169         ICOUNT -= timing.stos8;\r
2170 }\r
2171 \r
2172 static void PREFIX86(_stosw)(i8086_state *cpustate)    /* Opcode 0xab */\r
2173 {\r
2174         PutMemW(ES,cpustate->regs.w[DI],cpustate->regs.w[AX]);\r
2175         cpustate->regs.w[DI] += 2 * cpustate->DirVal;\r
2176         ICOUNT -= timing.stos16;\r
2177 }\r
2178 \r
2179 static void PREFIX86(_lodsb)(i8086_state *cpustate)    /* Opcode 0xac */\r
2180 {\r
2181         cpustate->regs.b[AL] = GetMemB(DS,cpustate->regs.w[SI]);\r
2182         cpustate->regs.w[SI] += cpustate->DirVal;\r
2183         ICOUNT -= timing.lods8;\r
2184 }\r
2185 \r
2186 static void PREFIX86(_lodsw)(i8086_state *cpustate)    /* Opcode 0xad */\r
2187 {\r
2188         cpustate->regs.w[AX] = GetMemW(DS,cpustate->regs.w[SI]);\r
2189         cpustate->regs.w[SI] += 2 * cpustate->DirVal;\r
2190         ICOUNT -= timing.lods16;\r
2191 }\r
2192 \r
2193 static void PREFIX86(_scasb)(i8086_state *cpustate)    /* Opcode 0xae */\r
2194 {\r
2195         unsigned src = GetMemB(ES, cpustate->regs.w[DI]);\r
2196         unsigned dst = cpustate->regs.b[AL];\r
2197         SUBB(dst,src);\r
2198         cpustate->regs.w[DI] += cpustate->DirVal;\r
2199         ICOUNT -= timing.scas8;\r
2200 }\r
2201 \r
2202 static void PREFIX86(_scasw)(i8086_state *cpustate)    /* Opcode 0xaf */\r
2203 {\r
2204         unsigned src = GetMemW(ES, cpustate->regs.w[DI]);\r
2205         unsigned dst = cpustate->regs.w[AX];\r
2206         SUBW(dst,src);\r
2207         cpustate->regs.w[DI] += 2 * cpustate->DirVal;\r
2208         ICOUNT -= timing.scas16;\r
2209 }\r
2210 \r
2211 static void PREFIX86(_mov_ald8)(i8086_state *cpustate)    /* Opcode 0xb0 */\r
2212 {\r
2213         cpustate->regs.b[AL] = FETCH;\r
2214         ICOUNT -= timing.mov_ri8;\r
2215 }\r
2216 \r
2217 static void PREFIX86(_mov_cld8)(i8086_state *cpustate)    /* Opcode 0xb1 */\r
2218 {\r
2219         cpustate->regs.b[CL] = FETCH;\r
2220         ICOUNT -= timing.mov_ri8;\r
2221 }\r
2222 \r
2223 static void PREFIX86(_mov_dld8)(i8086_state *cpustate)    /* Opcode 0xb2 */\r
2224 {\r
2225         cpustate->regs.b[DL] = FETCH;\r
2226         ICOUNT -= timing.mov_ri8;\r
2227 }\r
2228 \r
2229 static void PREFIX86(_mov_bld8)(i8086_state *cpustate)    /* Opcode 0xb3 */\r
2230 {\r
2231         cpustate->regs.b[BL] = FETCH;\r
2232         ICOUNT -= timing.mov_ri8;\r
2233 }\r
2234 \r
2235 static void PREFIX86(_mov_ahd8)(i8086_state *cpustate)    /* Opcode 0xb4 */\r
2236 {\r
2237         cpustate->regs.b[AH] = FETCH;\r
2238         ICOUNT -= timing.mov_ri8;\r
2239 }\r
2240 \r
2241 static void PREFIX86(_mov_chd8)(i8086_state *cpustate)    /* Opcode 0xb5 */\r
2242 {\r
2243         cpustate->regs.b[CH] = FETCH;\r
2244         ICOUNT -= timing.mov_ri8;\r
2245 }\r
2246 \r
2247 static void PREFIX86(_mov_dhd8)(i8086_state *cpustate)    /* Opcode 0xb6 */\r
2248 {\r
2249         cpustate->regs.b[DH] = FETCH;\r
2250         ICOUNT -= timing.mov_ri8;\r
2251 }\r
2252 \r
2253 static void PREFIX86(_mov_bhd8)(i8086_state *cpustate)    /* Opcode 0xb7 */\r
2254 {\r
2255         cpustate->regs.b[BH] = FETCH;\r
2256         ICOUNT -= timing.mov_ri8;\r
2257 }\r
2258 \r
2259 static void PREFIX86(_mov_axd16)(i8086_state *cpustate)    /* Opcode 0xb8 */\r
2260 {\r
2261         cpustate->regs.b[AL] = FETCH;\r
2262         cpustate->regs.b[AH] = FETCH;\r
2263         ICOUNT -= timing.mov_ri16;\r
2264 }\r
2265 \r
2266 static void PREFIX86(_mov_cxd16)(i8086_state *cpustate)    /* Opcode 0xb9 */\r
2267 {\r
2268         cpustate->regs.b[CL] = FETCH;\r
2269         cpustate->regs.b[CH] = FETCH;\r
2270         ICOUNT -= timing.mov_ri16;\r
2271 }\r
2272 \r
2273 static void PREFIX86(_mov_dxd16)(i8086_state *cpustate)    /* Opcode 0xba */\r
2274 {\r
2275         cpustate->regs.b[DL] = FETCH;\r
2276         cpustate->regs.b[DH] = FETCH;\r
2277         ICOUNT -= timing.mov_ri16;\r
2278 }\r
2279 \r
2280 static void PREFIX86(_mov_bxd16)(i8086_state *cpustate)    /* Opcode 0xbb */\r
2281 {\r
2282         cpustate->regs.b[BL] = FETCH;\r
2283         cpustate->regs.b[BH] = FETCH;\r
2284         ICOUNT -= timing.mov_ri16;\r
2285 }\r
2286 \r
2287 static void PREFIX86(_mov_spd16)(i8086_state *cpustate)    /* Opcode 0xbc */\r
2288 {\r
2289         cpustate->regs.b[SPL] = FETCH;\r
2290         cpustate->regs.b[SPH] = FETCH;\r
2291         ICOUNT -= timing.mov_ri16;\r
2292 }\r
2293 \r
2294 static void PREFIX86(_mov_bpd16)(i8086_state *cpustate)    /* Opcode 0xbd */\r
2295 {\r
2296         cpustate->regs.b[BPL] = FETCH;\r
2297         cpustate->regs.b[BPH] = FETCH;\r
2298         ICOUNT -= timing.mov_ri16;\r
2299 }\r
2300 \r
2301 static void PREFIX86(_mov_sid16)(i8086_state *cpustate)    /* Opcode 0xbe */\r
2302 {\r
2303         cpustate->regs.b[SIL] = FETCH;\r
2304         cpustate->regs.b[SIH] = FETCH;\r
2305         ICOUNT -= timing.mov_ri16;\r
2306 }\r
2307 \r
2308 static void PREFIX86(_mov_did16)(i8086_state *cpustate)    /* Opcode 0xbf */\r
2309 {\r
2310         cpustate->regs.b[DIL] = FETCH;\r
2311         cpustate->regs.b[DIH] = FETCH;\r
2312         ICOUNT -= timing.mov_ri16;\r
2313 }\r
2314 \r
2315 static void PREFIX86(_ret_d16)(i8086_state *cpustate)    /* Opcode 0xc2 */\r
2316 {\r
2317         unsigned count = FETCH;\r
2318         count += FETCH << 8;\r
2319         POP(cpustate->pc);\r
2320         cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;\r
2321         cpustate->regs.w[SP]+=count;\r
2322         ICOUNT -= timing.ret_near_imm;\r
2323         CHANGE_PC(cpustate->pc);\r
2324 }\r
2325 \r
2326 static void PREFIX86(_ret)(i8086_state *cpustate)    /* Opcode 0xc3 */\r
2327 {\r
2328         POP(cpustate->pc);\r
2329         cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;\r
2330         ICOUNT -= timing.ret_near;\r
2331         CHANGE_PC(cpustate->pc);\r
2332 }\r
2333 \r
2334 static void PREFIX86(_les_dw)(i8086_state *cpustate)    /* Opcode 0xc4 */\r
2335 {\r
2336         unsigned ModRM = FETCH;\r
2337         WORD tmp = GetRMWord(ModRM);\r
2338 \r
2339 #ifdef I80286\r
2340         i80286_data_descriptor(cpustate,ES,GetnextRMWord);\r
2341 #else\r
2342         cpustate->sregs[ES] = GetnextRMWord;\r
2343         cpustate->base[ES] = SegBase(ES);\r
2344 #endif\r
2345         RegWord(ModRM)= tmp;\r
2346         ICOUNT -= timing.load_ptr;\r
2347 }\r
2348 \r
2349 static void PREFIX86(_lds_dw)(i8086_state *cpustate)    /* Opcode 0xc5 */\r
2350 {\r
2351         unsigned ModRM = FETCH;\r
2352         WORD tmp = GetRMWord(ModRM);\r
2353 \r
2354 #ifdef I80286\r
2355         i80286_data_descriptor(cpustate,DS,GetnextRMWord);\r
2356 #else\r
2357         cpustate->sregs[DS] = GetnextRMWord;\r
2358         cpustate->base[DS] = SegBase(DS);\r
2359 #endif\r
2360         RegWord(ModRM)=tmp;\r
2361         ICOUNT -= timing.load_ptr;\r
2362 }\r
2363 \r
2364 static void PREFIX86(_mov_bd8)(i8086_state *cpustate)    /* Opcode 0xc6 */\r
2365 {\r
2366         unsigned ModRM = FETCH;\r
2367         ICOUNT -= (ModRM >= 0xc0) ? timing.mov_ri8 : timing.mov_mi8;\r
2368         PutImmRMByte(ModRM);\r
2369 }\r
2370 \r
2371 static void PREFIX86(_mov_wd16)(i8086_state *cpustate)    /* Opcode 0xc7 */\r
2372 {\r
2373         unsigned ModRM = FETCH;\r
2374         ICOUNT -= (ModRM >= 0xc0) ? timing.mov_ri16 : timing.mov_mi16;\r
2375         PutImmRMWord(ModRM);\r
2376 }\r
2377 \r
2378 #ifndef I80286\r
2379 static void PREFIX86(_retf_d16)(i8086_state *cpustate)    /* Opcode 0xca */\r
2380 {\r
2381         unsigned count = FETCH;\r
2382         count += FETCH << 8;\r
2383 \r
2384         POP(cpustate->pc);\r
2385         POP(cpustate->sregs[CS]);\r
2386         cpustate->base[CS] = SegBase(CS);\r
2387         cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;\r
2388         cpustate->regs.w[SP]+=count;\r
2389         ICOUNT -= timing.ret_far_imm;\r
2390         CHANGE_PC(cpustate->pc);\r
2391 }\r
2392 \r
2393 static void PREFIX86(_retf)(i8086_state *cpustate)    /* Opcode 0xcb */\r
2394 {\r
2395         POP(cpustate->pc);\r
2396         POP(cpustate->sregs[CS]);\r
2397         cpustate->base[CS] = SegBase(CS);\r
2398         cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;\r
2399         ICOUNT -= timing.ret_far;\r
2400         CHANGE_PC(cpustate->pc);\r
2401 }\r
2402 #endif\r
2403 \r
2404 static void PREFIX86(_int3)(i8086_state *cpustate)    /* Opcode 0xcc */\r
2405 {\r
2406         ICOUNT -= timing.int3;\r
2407         PREFIX(_interrupt)(cpustate, 3);\r
2408 }\r
2409 \r
2410 static void PREFIX86(_int)(i8086_state *cpustate)    /* Opcode 0xcd */\r
2411 {\r
2412         unsigned int_num = FETCH;\r
2413         ICOUNT -= timing.int_imm;\r
2414 #ifdef I86_BIOS_CALL\r
2415         if(cpustate->bios != NULL && cpustate->bios->bios_int(int_num, cpustate->regs.w, cpustate->sregs, &cpustate->ZeroVal, &cpustate->CarryVal)) {\r
2416                 return;\r
2417         }\r
2418 #endif\r
2419         PREFIX(_interrupt)(cpustate, int_num);\r
2420 }\r
2421 \r
2422 static void PREFIX86(_into)(i8086_state *cpustate)    /* Opcode 0xce */\r
2423 {\r
2424         if (OF) {\r
2425                 ICOUNT -= timing.into_t;\r
2426                 PREFIX(_interrupt)(cpustate, 4);\r
2427         } else ICOUNT -= timing.into_nt;\r
2428 }\r
2429 \r
2430 #ifndef I80286\r
2431 static void PREFIX86(_iret)(i8086_state *cpustate)    /* Opcode 0xcf */\r
2432 {\r
2433         ICOUNT -= timing.iret;\r
2434         POP(cpustate->pc);\r
2435         POP(cpustate->sregs[CS]);\r
2436         cpustate->base[CS] = SegBase(CS);\r
2437         cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;\r
2438                 PREFIX(_popf)(cpustate);\r
2439         CHANGE_PC(cpustate->pc);\r
2440 \r
2441         /* if the IF is set, and an interrupt is pending, signal an interrupt */\r
2442         if (cpustate->IF && cpustate->irq_state) {\r
2443                 PREFIX(_interrupt)(cpustate, (UINT32)-1);\r
2444                 cpustate->irq_state = 0;\r
2445         }\r
2446 }\r
2447 #endif\r
2448 \r
2449 static void PREFIX86(_rotshft_b)(i8086_state *cpustate)    /* Opcode 0xd0 */\r
2450 {\r
2451         unsigned ModRM = FETCHOP;\r
2452         PREFIX(_rotate_shift_Byte)(cpustate,ModRM,1,GetRMByte(ModRM));\r
2453 }\r
2454 \r
2455 \r
2456 static void PREFIX86(_rotshft_w)(i8086_state *cpustate)    /* Opcode 0xd1 */\r
2457 {\r
2458         unsigned ModRM = FETCHOP;\r
2459         PREFIX(_rotate_shift_Word)(cpustate,ModRM,1,GetRMWord(ModRM));\r
2460 }\r
2461 \r
2462 \r
2463 #ifdef I8086\r
2464 static void PREFIX86(_rotshft_bcl)(i8086_state *cpustate)    /* Opcode 0xd2 */\r
2465 {\r
2466         unsigned ModRM = FETCHOP;\r
2467         PREFIX(_rotate_shift_Byte)(cpustate,ModRM,cpustate->regs.b[CL],GetRMByte(ModRM));\r
2468 }\r
2469 \r
2470 static void PREFIX86(_rotshft_wcl)(i8086_state *cpustate)    /* Opcode 0xd3 */\r
2471 {\r
2472         unsigned ModRM = FETCHOP;\r
2473         PREFIX(_rotate_shift_Word)(cpustate,ModRM,cpustate->regs.b[CL],GetRMWord(ModRM));\r
2474 }\r
2475 #endif\r
2476 \r
2477 /* OB: Opcode works on NEC V-Series but not the Variants              */\r
2478 /*     one could specify any byte value as operand but the NECs */\r
2479 /*     always substitute 0x0a.              */\r
2480 static void PREFIX86(_aam)(i8086_state *cpustate)    /* Opcode 0xd4 */\r
2481 {\r
2482         unsigned mult = FETCH;\r
2483 \r
2484         ICOUNT -= timing.aam;\r
2485         if (mult == 0)\r
2486                 PREFIX(_interrupt)(cpustate, 0);\r
2487         else\r
2488         {\r
2489                 cpustate->regs.b[AH] = cpustate->regs.b[AL] / mult;\r
2490                 cpustate->regs.b[AL] %= mult;\r
2491 \r
2492                 SetSZPF_Word(cpustate->regs.w[AX]);\r
2493         }\r
2494 }\r
2495 \r
2496 static void PREFIX86(_aad)(i8086_state *cpustate)    /* Opcode 0xd5 */\r
2497 {\r
2498         unsigned mult = FETCH;\r
2499 \r
2500         ICOUNT -= timing.aad;\r
2501 \r
2502         cpustate->regs.b[AL] = cpustate->regs.b[AH] * mult + cpustate->regs.b[AL];\r
2503         cpustate->regs.b[AH] = 0;\r
2504 \r
2505         SetZF(cpustate->regs.b[AL]);\r
2506         SetPF(cpustate->regs.b[AL]);\r
2507         cpustate->SignVal = 0;\r
2508 }\r
2509 \r
2510 \r
2511 static void PREFIX86(_xlat)(i8086_state *cpustate)    /* Opcode 0xd7 */\r
2512 {\r
2513         unsigned dest = cpustate->regs.w[BX]+cpustate->regs.b[AL];\r
2514 \r
2515         ICOUNT -= timing.xlat;\r
2516         cpustate->regs.b[AL] = GetMemB(DS, dest);\r
2517 }\r
2518 \r
2519 #ifndef I80286\r
2520 static void PREFIX86(_escape)(i8086_state *cpustate)    /* Opcodes 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde and 0xdf */\r
2521 {\r
2522         unsigned ModRM = FETCH;\r
2523         ICOUNT -= timing.nop;\r
2524         GetRMByte(ModRM);\r
2525 }\r
2526 #endif\r
2527 \r
2528 static void PREFIX86(_loopne)(i8086_state *cpustate)    /* Opcode 0xe0 */\r
2529 {\r
2530         int disp = (int)((INT8)FETCH);\r
2531         unsigned tmp = cpustate->regs.w[CX]-1;\r
2532 \r
2533         cpustate->regs.w[CX]=tmp;\r
2534 \r
2535         if (!ZF && tmp) {\r
2536                 ICOUNT -= timing.loop_t;\r
2537                 cpustate->pc += disp;\r
2538 /* ASG - can probably assume this is safe\r
2539         CHANGE_PC(cpustate->pc);*/\r
2540         } else ICOUNT -= timing.loop_nt;\r
2541 }\r
2542 \r
2543 static void PREFIX86(_loope)(i8086_state *cpustate)    /* Opcode 0xe1 */\r
2544 {\r
2545         int disp = (int)((INT8)FETCH);\r
2546         unsigned tmp = cpustate->regs.w[CX]-1;\r
2547 \r
2548         cpustate->regs.w[CX]=tmp;\r
2549 \r
2550         if (ZF && tmp) {\r
2551                 ICOUNT -= timing.loope_t;\r
2552                         cpustate->pc += disp;\r
2553 /* ASG - can probably assume this is safe\r
2554          CHANGE_PC(cpustate->pc);*/\r
2555         } else ICOUNT -= timing.loope_nt;\r
2556 }\r
2557 \r
2558 static void PREFIX86(_loop)(i8086_state *cpustate)    /* Opcode 0xe2 */\r
2559 {\r
2560         int disp = (int)((INT8)FETCH);\r
2561         unsigned tmp = cpustate->regs.w[CX]-1;\r
2562 \r
2563         cpustate->regs.w[CX]=tmp;\r
2564 \r
2565         if (tmp) {\r
2566                 ICOUNT -= timing.loop_t;\r
2567                 cpustate->pc += disp;\r
2568 /* ASG - can probably assume this is safe\r
2569         CHANGE_PC(cpustate->pc);*/\r
2570         } else ICOUNT -= timing.loop_nt;\r
2571 }\r
2572 \r
2573 static void PREFIX86(_jcxz)(i8086_state *cpustate)    /* Opcode 0xe3 */\r
2574 {\r
2575         int disp = (int)((INT8)FETCH);\r
2576 \r
2577         if (cpustate->regs.w[CX] == 0) {\r
2578                 ICOUNT -= timing.jcxz_t;\r
2579                 cpustate->pc += disp;\r
2580 /* ASG - can probably assume this is safe\r
2581         CHANGE_PC(cpustate->pc);*/\r
2582         } else\r
2583                 ICOUNT -= timing.jcxz_nt;\r
2584 }\r
2585 \r
2586 static void PREFIX86(_inal)(i8086_state *cpustate)    /* Opcode 0xe4 */\r
2587 {\r
2588         unsigned port;\r
2589 #ifdef I80286\r
2590         if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);\r
2591 #endif\r
2592         port = FETCH;\r
2593 \r
2594         ICOUNT -= timing.in_imm8;\r
2595         cpustate->regs.b[AL] = read_port_byte(port);\r
2596 }\r
2597 \r
2598 static void PREFIX86(_inax)(i8086_state *cpustate)    /* Opcode 0xe5 */\r
2599 {\r
2600         unsigned port;\r
2601 #ifdef I80286\r
2602         if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);\r
2603 #endif\r
2604         port = FETCH;\r
2605 \r
2606         ICOUNT -= timing.in_imm16;\r
2607         cpustate->regs.w[AX] = read_port_word(port);\r
2608 }\r
2609 \r
2610 static void PREFIX86(_outal)(i8086_state *cpustate)    /* Opcode 0xe6 */\r
2611 {\r
2612         unsigned port;\r
2613 #ifdef I80286\r
2614         if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);\r
2615 #endif\r
2616         port = FETCH;\r
2617 \r
2618         ICOUNT -= timing.out_imm8;\r
2619         write_port_byte(port, cpustate->regs.b[AL]);\r
2620 }\r
2621 \r
2622 static void PREFIX86(_outax)(i8086_state *cpustate)    /* Opcode 0xe7 */\r
2623 {\r
2624         unsigned port;\r
2625 #ifdef I80286\r
2626         if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);\r
2627 #endif\r
2628         port = FETCH;\r
2629 \r
2630         ICOUNT -= timing.out_imm16;\r
2631         write_port_word(port, cpustate->regs.w[AX]);\r
2632 }\r
2633 \r
2634 static void PREFIX86(_call_d16)(i8086_state *cpustate)    /* Opcode 0xe8 */\r
2635 {\r
2636         WORD ip, tmp;\r
2637 \r
2638         FETCHWORD(tmp);\r
2639 #ifdef I86_BIOS_CALL\r
2640         if(cpustate->bios != NULL && cpustate->bios->bios_call((cpustate->pc + tmp) & AMASK, cpustate->regs.w, cpustate->sregs, &cpustate->ZeroVal, &cpustate->CarryVal)) {\r
2641                 ICOUNT -= timing.call_near;\r
2642                 return;\r
2643         }\r
2644 #endif\r
2645         ip = cpustate->pc - cpustate->base[CS];\r
2646         PUSH(ip);\r
2647         ip += tmp;\r
2648         cpustate->pc = (ip + cpustate->base[CS]) & AMASK;\r
2649         ICOUNT -= timing.call_near;\r
2650         CHANGE_PC(cpustate->pc);\r
2651 }\r
2652 \r
2653 static void PREFIX86(_jmp_d16)(i8086_state *cpustate)    /* Opcode 0xe9 */\r
2654 {\r
2655         WORD ip, tmp;\r
2656 \r
2657         FETCHWORD(tmp);\r
2658         ip = cpustate->pc - cpustate->base[CS] + tmp;\r
2659         cpustate->pc = (ip + cpustate->base[CS]) & AMASK;\r
2660         ICOUNT -= timing.jmp_near;\r
2661         CHANGE_PC(cpustate->pc);\r
2662 }\r
2663 \r
2664 static void PREFIX86(_jmp_far)(i8086_state *cpustate)    /* Opcode 0xea */\r
2665 {\r
2666         unsigned tmp,tmp1;\r
2667 \r
2668         tmp = FETCH;\r
2669         tmp += FETCH << 8;\r
2670 \r
2671         tmp1 = FETCH;\r
2672         tmp1 += FETCH << 8;\r
2673 \r
2674 #ifdef I80286\r
2675         i80286_code_descriptor(cpustate, tmp1,tmp, 1);\r
2676 #else\r
2677         cpustate->sregs[CS] = (WORD)tmp1;\r
2678         cpustate->base[CS] = SegBase(CS);\r
2679         cpustate->pc = (cpustate->base[CS] + tmp) & AMASK;\r
2680 #endif\r
2681         ICOUNT -= timing.jmp_far;\r
2682         CHANGE_PC(cpustate->pc);\r
2683 }\r
2684 \r
2685 static void PREFIX86(_jmp_d8)(i8086_state *cpustate)    /* Opcode 0xeb */\r
2686 {\r
2687         int tmp = (int)((INT8)FETCH);\r
2688         cpustate->pc += tmp;\r
2689 /* ASG - can probably assume this is safe\r
2690     CHANGE_PC(cpustate->pc);*/\r
2691         ICOUNT -= timing.jmp_short;\r
2692 }\r
2693 \r
2694 static void PREFIX86(_inaldx)(i8086_state *cpustate)    /* Opcode 0xec */\r
2695 {\r
2696 #ifdef I80286\r
2697         if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);\r
2698 #endif\r
2699         ICOUNT -= timing.in_dx8;\r
2700         cpustate->regs.b[AL] = read_port_byte(cpustate->regs.w[DX]);\r
2701 }\r
2702 \r
2703 static void PREFIX86(_inaxdx)(i8086_state *cpustate)    /* Opcode 0xed */\r
2704 {\r
2705         unsigned port = cpustate->regs.w[DX];\r
2706 #ifdef I80286\r
2707         if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);\r
2708 #endif\r
2709         ICOUNT -= timing.in_dx16;\r
2710         cpustate->regs.w[AX] = read_port_word(port);\r
2711 }\r
2712 \r
2713 static void PREFIX86(_outdxal)(i8086_state *cpustate)    /* Opcode 0xee */\r
2714 {\r
2715 #ifdef I80286\r
2716         if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);\r
2717 #endif\r
2718         ICOUNT -= timing.out_dx8;\r
2719         write_port_byte(cpustate->regs.w[DX], cpustate->regs.b[AL]);\r
2720 }\r
2721 \r
2722 static void PREFIX86(_outdxax)(i8086_state *cpustate)    /* Opcode 0xef */\r
2723 {\r
2724         unsigned port = cpustate->regs.w[DX];\r
2725 #ifdef I80286\r
2726         if (PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT, 0);\r
2727 #endif\r
2728         ICOUNT -= timing.out_dx16;\r
2729         write_port_word(port, cpustate->regs.w[AX]);\r
2730 }\r
2731 \r
2732 /* I think thats not a V20 instruction...*/\r
2733 static void PREFIX86(_lock)(i8086_state *cpustate)    /* Opcode 0xf0 */\r
2734 {\r
2735 #ifdef I80286\r
2736         if(PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT,0);\r
2737 #endif\r
2738         ICOUNT -= timing.nop;\r
2739         PREFIX(_instruction)[FETCHOP](cpustate);  /* un-interruptible */\r
2740 }\r
2741 #endif\r
2742 \r
2743 static void PREFIX(_pop_ss)(i8086_state *cpustate)    /* Opcode 0x17 */\r
2744 {\r
2745 #ifdef I80286\r
2746         i80286_pop_seg(cpustate, SS);\r
2747 #else\r
2748         POP(cpustate->sregs[SS]);\r
2749         cpustate->base[SS] = SegBase(SS);\r
2750 #endif\r
2751         ICOUNT -= timing.pop_seg;\r
2752         PREFIX(_instruction)[FETCHOP](cpustate); /* no interrupt before next instruction */\r
2753 }\r
2754 \r
2755 static void PREFIX(_es)(i8086_state *cpustate)    /* Opcode 0x26 */\r
2756 {\r
2757         cpustate->seg_prefix = TRUE;\r
2758         cpustate->prefix_seg = ES;\r
2759         ICOUNT -= timing.override;\r
2760         PREFIX(_instruction)[FETCHOP](cpustate);\r
2761 }\r
2762 \r
2763 static void PREFIX(_cs)(i8086_state *cpustate)    /* Opcode 0x2e */\r
2764 {\r
2765         cpustate->seg_prefix = TRUE;\r
2766         cpustate->prefix_seg = CS;\r
2767         ICOUNT -= timing.override;\r
2768         PREFIX(_instruction)[FETCHOP](cpustate);\r
2769 }\r
2770 \r
2771 static void PREFIX(_ss)(i8086_state *cpustate)    /* Opcode 0x36 */\r
2772 {\r
2773         cpustate->seg_prefix = TRUE;\r
2774         cpustate->prefix_seg = SS;\r
2775         ICOUNT -= timing.override;\r
2776         PREFIX(_instruction)[FETCHOP](cpustate);\r
2777 }\r
2778 \r
2779 static void PREFIX(_ds)(i8086_state *cpustate)    /* Opcode 0x3e */\r
2780 {\r
2781         cpustate->seg_prefix = TRUE;\r
2782         cpustate->prefix_seg = DS;\r
2783         ICOUNT -= timing.override;\r
2784         PREFIX(_instruction)[FETCHOP](cpustate);\r
2785 }\r
2786 \r
2787 static void PREFIX(_mov_sregw)(i8086_state *cpustate)    /* Opcode 0x8e */\r
2788 {\r
2789         unsigned ModRM = FETCH;\r
2790         WORD src = GetRMWord(ModRM);\r
2791 \r
2792         ICOUNT -= (ModRM >= 0xc0) ? timing.mov_sr : timing.mov_sm;\r
2793 #ifdef I80286\r
2794         switch (ModRM & 0x38)\r
2795         {\r
2796         case 0x00:  /* mov es,ew */\r
2797                 i80286_data_descriptor(cpustate,ES,src);\r
2798                 break;\r
2799         case 0x18:  /* mov ds,ew */\r
2800                 i80286_data_descriptor(cpustate,DS,src);\r
2801                 break;\r
2802         case 0x10:  /* mov ss,ew */\r
2803                 i80286_data_descriptor(cpustate,SS,src);\r
2804                 cpustate->seg_prefix = FALSE;\r
2805                 PREFIX(_instruction)[FETCHOP](cpustate);\r
2806                 break;\r
2807         case 0x08:  /* mov cs,ew */\r
2808                 PREFIX(_invalid)(cpustate);\r
2809                 break;  /* doesn't do a jump far */\r
2810         }\r
2811 #else\r
2812         switch (ModRM & 0x38)\r
2813         {\r
2814         case 0x00:  /* mov es,ew */\r
2815                 cpustate->sregs[ES] = src;\r
2816                 cpustate->base[ES] = SegBase(ES);\r
2817                 break;\r
2818         case 0x18:  /* mov ds,ew */\r
2819                 cpustate->sregs[DS] = src;\r
2820                 cpustate->base[DS] = SegBase(DS);\r
2821                 break;\r
2822         case 0x10:  /* mov ss,ew */\r
2823                 cpustate->sregs[SS] = src;\r
2824                 cpustate->base[SS] = SegBase(SS); /* no interrupt allowed before next instr */\r
2825                 cpustate->seg_prefix = FALSE;\r
2826                 PREFIX(_instruction)[FETCHOP](cpustate);\r
2827                 break;\r
2828         case 0x08:  /* mov cs,ew */\r
2829 #ifndef I80186\r
2830                 int ip = cpustate->pc - cpustate->base[CS];\r
2831                 cpustate->sregs[CS] = src;\r
2832                 cpustate->base[CS] = SegBase(CS);\r
2833                 cpustate->pc = (ip + cpustate->base[CS]) & AMASK;\r
2834                 CHANGE_PC(cpustate->pc);\r
2835 #endif\r
2836                 break;\r
2837         }\r
2838 #endif\r
2839 }\r
2840 \r
2841 static void PREFIX(_repne)(i8086_state *cpustate)    /* Opcode 0xf2 */\r
2842 {\r
2843                 PREFIX(rep)(cpustate, 0);\r
2844 }\r
2845 \r
2846 static void PREFIX(_repe)(i8086_state *cpustate)    /* Opcode 0xf3 */\r
2847 {\r
2848         PREFIX(rep)(cpustate, 1);\r
2849 }\r
2850 \r
2851 static void PREFIX(_sti)(i8086_state *cpustate)    /* Opcode 0xfb */\r
2852 {\r
2853 #ifdef I80286\r
2854         if(PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT,0);\r
2855 #endif\r
2856         ICOUNT -= timing.flag_ops;\r
2857         SetIF(1);\r
2858         PREFIX(_instruction)[FETCHOP](cpustate); /* no interrupt before next instruction */\r
2859 \r
2860         /* if an interrupt is pending, signal an interrupt */\r
2861         if (cpustate->irq_state) {\r
2862 #ifdef I80286\r
2863                 i80286_interrupt_descriptor(cpustate, cpustate->pic->intr_ack(), 2, -1);\r
2864 #else\r
2865                 PREFIX86(_interrupt)(cpustate, (UINT32)-1);\r
2866 #endif\r
2867                 cpustate->irq_state = 0;\r
2868         }\r
2869 }\r
2870 \r
2871 #ifndef I80186\r
2872 static void PREFIX86(_hlt)(i8086_state *cpustate)    /* Opcode 0xf4 */\r
2873 {\r
2874 #ifdef I80286\r
2875         if(PM && (CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0);\r
2876 #endif\r
2877         cpustate->halted=1;\r
2878         ICOUNT = 0;\r
2879 }\r
2880 \r
2881 static void PREFIX86(_cmc)(i8086_state *cpustate)    /* Opcode 0xf5 */\r
2882 {\r
2883         ICOUNT -= timing.flag_ops;\r
2884         cpustate->CarryVal = !CF;\r
2885 }\r
2886 \r
2887 static void PREFIX86(_f6pre)(i8086_state *cpustate)\r
2888 {\r
2889         /* Opcode 0xf6 */\r
2890         unsigned ModRM = FETCH;\r
2891         unsigned tmp = (unsigned)GetRMByte(ModRM);\r
2892         unsigned tmp2;\r
2893 \r
2894 \r
2895         switch (ModRM & 0x38)\r
2896         {\r
2897         case 0x00:  /* TEST Eb, data8 */\r
2898         case 0x08:  /* ??? */\r
2899                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri8 : timing.alu_mi8_ro;\r
2900                 tmp &= FETCH;\r
2901 \r
2902                 cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0;\r
2903                 SetSZPF_Byte(tmp);\r
2904                 break;\r
2905 \r
2906         case 0x10:  /* NOT Eb */\r
2907                 ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;\r
2908                 PutbackRMByte(ModRM,~tmp);\r
2909                 break;\r
2910 \r
2911                 case 0x18:  /* NEG Eb */\r
2912                 ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r8 : timing.negnot_m8;\r
2913                 tmp2=0;\r
2914                 SUBB(tmp2,tmp);\r
2915                 PutbackRMByte(ModRM,tmp2);\r
2916                 break;\r
2917         case 0x20:  /* MUL AL, Eb */\r
2918                 ICOUNT -= (ModRM >= 0xc0) ? timing.mul_r8 : timing.mul_m8;\r
2919                 {\r
2920                         UINT16 result;\r
2921                         tmp2 = cpustate->regs.b[AL];\r
2922 \r
2923                         SetSF((INT8)tmp2);\r
2924                         SetPF(tmp2);\r
2925 \r
2926                         result = (UINT16)tmp2*tmp;\r
2927                         cpustate->regs.w[AX]=(WORD)result;\r
2928 \r
2929                         SetZF(cpustate->regs.w[AX]);\r
2930                         cpustate->CarryVal = cpustate->OverVal = (cpustate->regs.b[AH] != 0);\r
2931                 }\r
2932                 break;\r
2933                 case 0x28:  /* IMUL AL, Eb */\r
2934                 ICOUNT -= (ModRM >= 0xc0) ? timing.imul_r8 : timing.imul_m8;\r
2935                 {\r
2936                         INT16 result;\r
2937 \r
2938                         tmp2 = (unsigned)cpustate->regs.b[AL];\r
2939 \r
2940                         SetSF((INT8)tmp2);\r
2941                         SetPF(tmp2);\r
2942 \r
2943                         result = (INT16)((INT8)tmp2)*(INT16)((INT8)tmp);\r
2944                         cpustate->regs.w[AX]=(WORD)result;\r
2945 \r
2946                         SetZF(cpustate->regs.w[AX]);\r
2947 \r
2948                         cpustate->CarryVal = cpustate->OverVal = (result >> 7 != 0) && (result >> 7 != -1);\r
2949                 }\r
2950                 break;\r
2951         case 0x30:  /* DIV AL, Ew */\r
2952                 ICOUNT -= (ModRM >= 0xc0) ? timing.div_r8 : timing.div_m8;\r
2953                 {\r
2954                         UINT16 result;\r
2955 \r
2956                         result = cpustate->regs.w[AX];\r
2957 \r
2958                         if (tmp)\r
2959                         {\r
2960                                 if ((result / tmp) > 0xff)\r
2961                                 {\r
2962                                         PREFIX(_interrupt)(cpustate, 0);\r
2963                                         break;\r
2964                                 }\r
2965                                 else\r
2966                                 {\r
2967                                         cpustate->regs.b[AH] = result % tmp;\r
2968                                         cpustate->regs.b[AL] = result / tmp;\r
2969                                 }\r
2970                         }\r
2971                         else\r
2972                         {\r
2973                                 PREFIX(_interrupt)(cpustate, 0);\r
2974                                 break;\r
2975                         }\r
2976                 }\r
2977                 break;\r
2978         case 0x38:  /* IDIV AL, Ew */\r
2979                 ICOUNT -= (ModRM >= 0xc0) ? timing.idiv_r8 : timing.idiv_m8;\r
2980                 {\r
2981 \r
2982                         INT16 result;\r
2983 \r
2984                         result = cpustate->regs.w[AX];\r
2985 \r
2986                         if (tmp)\r
2987                         {\r
2988                                 tmp2 = result % (INT16)((INT8)tmp);\r
2989 \r
2990                                 if ((result /= (INT16)((INT8)tmp)) > 0xff)\r
2991                                 {\r
2992                                         PREFIX(_interrupt)(cpustate, 0);\r
2993                                         break;\r
2994                                 }\r
2995                                 else\r
2996                                 {\r
2997                                         cpustate->regs.b[AL] = result;\r
2998                                         cpustate->regs.b[AH] = tmp2;\r
2999                                 }\r
3000                         }\r
3001                         else\r
3002                         {\r
3003                                 PREFIX(_interrupt)(cpustate, 0);\r
3004                                 break;\r
3005                         }\r
3006                 }\r
3007                 break;\r
3008         }\r
3009 }\r
3010 \r
3011 \r
3012 static void PREFIX86(_f7pre)(i8086_state *cpustate)\r
3013 {\r
3014         /* Opcode 0xf7 */\r
3015         unsigned ModRM = FETCH;\r
3016                 unsigned tmp = GetRMWord(ModRM);\r
3017         unsigned tmp2;\r
3018 \r
3019 \r
3020         switch (ModRM & 0x38)\r
3021         {\r
3022         case 0x00:  /* TEST Ew, data16 */\r
3023         case 0x08:  /* ??? */\r
3024                 ICOUNT -= (ModRM >= 0xc0) ? timing.alu_ri16 : timing.alu_mi16_ro;\r
3025                 tmp2 = FETCH;\r
3026                 tmp2 += FETCH << 8;\r
3027 \r
3028                 tmp &= tmp2;\r
3029 \r
3030                 cpustate->CarryVal = cpustate->OverVal = cpustate->AuxVal = 0;\r
3031                 SetSZPF_Word(tmp);\r
3032                 break;\r
3033 \r
3034         case 0x10:  /* NOT Ew */\r
3035                 ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;\r
3036                 tmp = ~tmp;\r
3037                 PutbackRMWord(ModRM,tmp);\r
3038                 break;\r
3039 \r
3040         case 0x18:  /* NEG Ew */\r
3041                 ICOUNT -= (ModRM >= 0xc0) ? timing.negnot_r16 : timing.negnot_m16;\r
3042                 tmp2 = 0;\r
3043                 SUBW(tmp2,tmp);\r
3044                 PutbackRMWord(ModRM,tmp2);\r
3045                 break;\r
3046         case 0x20:  /* MUL AX, Ew */\r
3047                 ICOUNT -= (ModRM >= 0xc0) ? timing.mul_r16 : timing.mul_m16;\r
3048                 {\r
3049                         UINT32 result;\r
3050                         tmp2 = cpustate->regs.w[AX];\r
3051 \r
3052                         SetSF((INT16)tmp2);\r
3053                         SetPF(tmp2);\r
3054 \r
3055                         result = (UINT32)tmp2*tmp;\r
3056                         cpustate->regs.w[AX]=(WORD)result;\r
3057                         result >>= 16;\r
3058                         cpustate->regs.w[DX]=result;\r
3059 \r
3060                         SetZF(cpustate->regs.w[AX] | cpustate->regs.w[DX]);\r
3061                         cpustate->CarryVal = cpustate->OverVal = (cpustate->regs.w[DX] != 0);\r
3062                 }\r
3063                 break;\r
3064 \r
3065         case 0x28:  /* IMUL AX, Ew */\r
3066                 ICOUNT -= (ModRM >= 0xc0) ? timing.imul_r16 : timing.imul_m16;\r
3067                 {\r
3068                         INT32 result;\r
3069 \r
3070                         tmp2 = cpustate->regs.w[AX];\r
3071 \r
3072                         SetSF((INT16)tmp2);\r
3073                         SetPF(tmp2);\r
3074 \r
3075                         result = (INT32)((INT16)tmp2)*(INT32)((INT16)tmp);\r
3076                         cpustate->CarryVal = cpustate->OverVal = (result >> 15 != 0) && (result >> 15 != -1);\r
3077 \r
3078                         cpustate->regs.w[AX]=(WORD)result;\r
3079                         result = (WORD)(result >> 16);\r
3080                         cpustate->regs.w[DX]=result;\r
3081 \r
3082                         SetZF(cpustate->regs.w[AX] | cpustate->regs.w[DX]);\r
3083                 }\r
3084                 break;\r
3085                 case 0x30:  /* DIV AX, Ew */\r
3086                 ICOUNT -= (ModRM >= 0xc0) ? timing.div_r16 : timing.div_m16;\r
3087                 {\r
3088                         UINT32 result;\r
3089 \r
3090                         result = (cpustate->regs.w[DX] << 16) + cpustate->regs.w[AX];\r
3091 \r
3092                         if (tmp)\r
3093                         {\r
3094                                 tmp2 = result % tmp;\r
3095                                 if ((result / tmp) > 0xffff)\r
3096                                 {\r
3097                                         PREFIX(_interrupt)(cpustate, 0);\r
3098                                         break;\r
3099                                 }\r
3100                                 else\r
3101                                 {\r
3102                                         cpustate->regs.w[DX]=tmp2;\r
3103                                         result /= tmp;\r
3104                                         cpustate->regs.w[AX]=result;\r
3105                                 }\r
3106                         }\r
3107                         else\r
3108                         {\r
3109                                 PREFIX(_interrupt)(cpustate, 0);\r
3110                                 break;\r
3111                         }\r
3112                 }\r
3113                 break;\r
3114         case 0x38:  /* IDIV AX, Ew */\r
3115                 ICOUNT -= (ModRM >= 0xc0) ? timing.idiv_r16 : timing.idiv_m16;\r
3116                 {\r
3117                         INT32 result;\r
3118 \r
3119                         result = (cpustate->regs.w[DX] << 16) + cpustate->regs.w[AX];\r
3120 \r
3121                         if (tmp)\r
3122                         {\r
3123                                 tmp2 = result % (INT32)((INT16)tmp);\r
3124                                 if ((result /= (INT32)((INT16)tmp)) > 0xffff)\r
3125                                 {\r
3126                                         PREFIX(_interrupt)(cpustate, 0);\r
3127                                         break;\r
3128                                 }\r
3129                                 else\r
3130                                 {\r
3131                                         cpustate->regs.w[AX]=result;\r
3132                                         cpustate->regs.w[DX]=tmp2;\r
3133                                 }\r
3134                         }\r
3135                         else\r
3136                         {\r
3137                                 PREFIX(_interrupt)(cpustate, 0);\r
3138                                 break;\r
3139                         }\r
3140                 }\r
3141                 break;\r
3142         }\r
3143 }\r
3144 \r
3145 \r
3146 static void PREFIX86(_clc)(i8086_state *cpustate)    /* Opcode 0xf8 */\r
3147 {\r
3148         ICOUNT -= timing.flag_ops;\r
3149         cpustate->CarryVal = 0;\r
3150 }\r
3151 \r
3152 static void PREFIX86(_stc)(i8086_state *cpustate)    /* Opcode 0xf9 */\r
3153 {\r
3154         ICOUNT -= timing.flag_ops;\r
3155         cpustate->CarryVal = 1;\r
3156 }\r
3157 \r
3158 static void PREFIX86(_cli)(i8086_state *cpustate)    /* Opcode 0xfa */\r
3159 {\r
3160 #ifdef I80286\r
3161         if(PM && (CPL>IOPL)) throw TRAP(GENERAL_PROTECTION_FAULT,0);\r
3162 #endif\r
3163         ICOUNT -= timing.flag_ops;\r
3164         SetIF(0);\r
3165 }\r
3166 \r
3167 static void PREFIX86(_cld)(i8086_state *cpustate)    /* Opcode 0xfc */\r
3168 {\r
3169         ICOUNT -= timing.flag_ops;\r
3170         SetDF(0);\r
3171 }\r
3172 \r
3173 static void PREFIX86(_std)(i8086_state *cpustate)    /* Opcode 0xfd */\r
3174 {\r
3175         ICOUNT -= timing.flag_ops;\r
3176         SetDF(1);\r
3177 }\r
3178 \r
3179 static void PREFIX86(_fepre)(i8086_state *cpustate)    /* Opcode 0xfe */\r
3180 {\r
3181         unsigned ModRM = FETCH;\r
3182         unsigned tmp = GetRMByte(ModRM);\r
3183         unsigned tmp1;\r
3184 \r
3185         ICOUNT -= (ModRM >= 0xc0) ? timing.incdec_r8 : timing.incdec_m8;\r
3186         if ((ModRM & 0x38) == 0)  /* INC eb */\r
3187         {\r
3188                 tmp1 = tmp+1;\r
3189                 SetOFB_Add(tmp1,tmp,1);\r
3190         }\r
3191         else  /* DEC eb */\r
3192         {\r
3193                 tmp1 = tmp-1;\r
3194                 SetOFB_Sub(tmp1,1,tmp);\r
3195         }\r
3196 \r
3197         SetAF(tmp1,tmp,1);\r
3198         SetSZPF_Byte(tmp1);\r
3199 \r
3200         PutbackRMByte(ModRM,(BYTE)tmp1);\r
3201 }\r
3202 \r
3203 \r
3204 static void PREFIX86(_ffpre)(i8086_state *cpustate)    /* Opcode 0xff */\r
3205 {\r
3206         unsigned ModRM = FETCHOP;\r
3207         unsigned tmp;\r
3208         unsigned tmp1, tmp2;\r
3209         WORD ip;\r
3210 \r
3211         switch(ModRM & 0x38)\r
3212         {\r
3213         case 0x00:  /* INC ew */\r
3214                 ICOUNT -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;\r
3215                 tmp = GetRMWord(ModRM);\r
3216                 tmp1 = tmp+1;\r
3217 \r
3218                 SetOFW_Add(tmp1,tmp,1);\r
3219                 SetAF(tmp1,tmp,1);\r
3220                 SetSZPF_Word(tmp1);\r
3221 \r
3222                 PutbackRMWord(ModRM,(WORD)tmp1);\r
3223                 break;\r
3224 \r
3225         case 0x08:  /* DEC ew */\r
3226                 ICOUNT -= (ModRM >= 0xc0) ? timing.incdec_r16 : timing.incdec_m16;\r
3227                 tmp = GetRMWord(ModRM);\r
3228                 tmp1 = tmp-1;\r
3229 \r
3230                 SetOFW_Sub(tmp1,1,tmp);\r
3231                 SetAF(tmp1,tmp,1);\r
3232                 SetSZPF_Word(tmp1);\r
3233 \r
3234                 PutbackRMWord(ModRM,(WORD)tmp1);\r
3235                 break;\r
3236 \r
3237         case 0x10:  /* CALL ew */\r
3238                 ICOUNT -= (ModRM >= 0xc0) ? timing.call_r16 : timing.call_m16;\r
3239                 tmp = GetRMWord(ModRM);\r
3240 #ifdef I86_BIOS_CALL\r
3241                 if(cpustate->bios != NULL && cpustate->bios->bios_call((cpustate->base[CS] + (WORD)tmp) & AMASK, cpustate->regs.w, cpustate->sregs, &cpustate->ZeroVal, &cpustate->CarryVal)) {\r
3242                         ICOUNT -= timing.call_far;\r
3243                         return;\r
3244                 }\r
3245 #endif\r
3246                 ip = cpustate->pc - cpustate->base[CS];\r
3247                 PUSH(ip);\r
3248                 cpustate->pc = (cpustate->base[CS] + (WORD)tmp) & AMASK;\r
3249                 CHANGE_PC(cpustate->pc);\r
3250                 break;\r
3251 \r
3252         case 0x18:  /* CALL FAR ea */\r
3253                 ICOUNT -= timing.call_m32;\r
3254                 tmp = cpustate->sregs[CS];  /* HJB 12/13/98 need to skip displacements of cpustate->ea */\r
3255                 tmp1 = GetRMWord(ModRM);\r
3256                 tmp2 = GetnextRMWord;\r
3257 #ifdef I86_BIOS_CALL\r
3258                 if(cpustate->bios != NULL && cpustate->bios->bios_call(((tmp2 << 4) + tmp1) & AMASK, cpustate->regs.w, cpustate->sregs, &cpustate->ZeroVal, &cpustate->CarryVal)) {\r
3259                         return;\r
3260                 }\r
3261 #endif\r
3262                 ip = cpustate->pc - cpustate->base[CS];\r
3263 #ifdef I80286\r
3264                 i80286_code_descriptor(cpustate, tmp2, tmp1, 2);\r
3265 #else\r
3266                 cpustate->sregs[CS] = tmp2;\r
3267                 cpustate->base[CS] = SegBase(CS);\r
3268                 cpustate->pc = (cpustate->base[CS] + tmp1) & AMASK;\r
3269 #endif\r
3270                 PUSH(tmp);\r
3271                 PUSH(ip);\r
3272                 CHANGE_PC(cpustate->pc);\r
3273                 break;\r
3274 \r
3275         case 0x20:  /* JMP ea */\r
3276                 ICOUNT -= (ModRM >= 0xc0) ? timing.jmp_r16 : timing.jmp_m16;\r
3277                 ip = GetRMWord(ModRM);\r
3278                 cpustate->pc = (cpustate->base[CS] + ip) & AMASK;\r
3279                 CHANGE_PC(cpustate->pc);\r
3280                 break;\r
3281 \r
3282         case 0x28:  /* JMP FAR ea */\r
3283                 ICOUNT -= timing.jmp_m32;\r
3284 \r
3285 #ifdef I80286\r
3286                 tmp = GetRMWord(ModRM);\r
3287                 i80286_code_descriptor(cpustate, GetnextRMWord, tmp, 1);\r
3288 #else\r
3289                 cpustate->pc = GetRMWord(ModRM);\r
3290                 cpustate->sregs[CS] = GetnextRMWord;\r
3291                 cpustate->base[CS] = SegBase(CS);\r
3292                 cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK;\r
3293 #endif\r
3294                 CHANGE_PC(cpustate->pc);\r
3295                 break;\r
3296 \r
3297         case 0x30:  /* PUSH ea */\r
3298                 ICOUNT -= (ModRM >= 0xc0) ? timing.push_r16 : timing.push_m16;\r
3299                 tmp = GetRMWord(ModRM);\r
3300                 PUSH(tmp);\r
3301                 break;\r
3302         default:\r
3303                 tmp = GetRMWord(ModRM);  // 286 doesn't matter but 8086?\r
3304                 return PREFIX(_invalid)(cpustate);\r
3305         }\r
3306 }\r
3307 \r
3308 \r
3309 static void PREFIX86(_invalid)(i8086_state *cpustate)\r
3310 {\r
3311         logerror("illegal instruction %.2x at %.5x\n",PEEKBYTE(cpustate->pc-1), cpustate->pc);\r
3312 #ifdef I80286\r
3313         throw TRAP(ILLEGAL_INSTRUCTION,-1);\r
3314 #else\r
3315         /* i8086/i8088 ignore an invalid opcode. */\r
3316         /* i80186/i80188 probably also ignore an invalid opcode. */\r
3317         ICOUNT -= 10;\r
3318 #endif\r
3319 }\r
3320 \r
3321 #ifndef I80286\r
3322 static void PREFIX86(_invalid_2b)(i8086_state *cpustate)\r
3323 {\r
3324         unsigned ModRM = FETCH;\r
3325         GetRMByte(ModRM);\r
3326         logerror("illegal 2 byte instruction %.2x at %.5x\n",PEEKBYTE(cpustate->pc-2), cpustate->pc-2);\r
3327         ICOUNT -= 10;\r
3328 }\r
3329 #endif\r
3330 #endif\r