fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/cpu/e8086/opcodes.c *
7 * Created: 1996-04-28 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 1996-2021 Hampa Hug <hampa@hampa.ch> *
9 *****************************************************************************/
10
11/*****************************************************************************
12 * This program is free software. You can redistribute it and / or modify it *
13 * under the terms of the GNU General Public License version 2 as published *
14 * by the Free Software Foundation. *
15 * *
16 * This program is distributed in the hope that it will be useful, but *
17 * WITHOUT ANY WARRANTY, without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
19 * Public License for more details. *
20 *****************************************************************************/
21
22
23#include "e8086.h"
24#include "internal.h"
25
26
27void e86_push (e8086_t *c, unsigned short val)
28{
29 e86_set_sp (c, e86_get_sp (c) - 2);
30
31 e86_set_mem16 (c, e86_get_ss (c), e86_get_sp (c), val);
32}
33
34unsigned short e86_pop (e8086_t *c)
35{
36 unsigned short sp;
37
38 sp = e86_get_sp (c);
39
40 e86_set_sp (c, sp + 2);
41
42 return (e86_get_mem16 (c, e86_get_ss (c), sp));
43}
44
45
46/**************************************************************************
47 * Microcode functions
48 **************************************************************************/
49
50/* Handle an undefined opcode */
51static
52unsigned op_ud (e8086_t *c)
53{
54 e86_set_clk (c, 1);
55
56 return (e86_undefined (c));
57}
58
59static
60unsigned op_divide_error (e8086_t *c)
61{
62 e86_set_clk_ea (c, 16, 20);
63
64 e86_set_ip (c, e86_get_ip (c) + c->ea.cnt + 1);
65 e86_trap (c, 0);
66
67 return (0);
68}
69
70/* OP 00: ADD r/m8, reg8 */
71static
72unsigned op_00 (e8086_t *c)
73{
74 unsigned short s1, s2, d;
75
76 e86_get_ea_ptr (c, c->pq + 1);
77
78 s1 = e86_get_ea8 (c);
79 s2 = e86_get_reg8 (c, (c->pq[1] >> 3) & 7);
80
81 d = s1 + s2;
82
83 e86_set_ea8 (c, d);
84 e86_set_flg_add_8 (c, s1, s2);
85 e86_set_clk_ea (c, 3, 16);
86
87 return (c->ea.cnt + 1);
88}
89
90/* OP 01: ADD r/m16, reg16 */
91static
92unsigned op_01 (e8086_t *c)
93{
94 unsigned long s1, s2, d;
95
96 e86_get_ea_ptr (c, c->pq + 1);
97
98 s1 = e86_get_ea16 (c);
99 s2 = e86_get_reg16 (c, (c->pq[1] >> 3) & 7);
100
101 d = s1 + s2;
102
103 e86_set_ea16 (c, d);
104 e86_set_flg_add_16 (c, s1, s2);
105 e86_set_clk_ea (clk, 3, 16);
106
107 return (c->ea.cnt + 1);
108}
109
110/* OP 02: ADD reg8, r/m8 */
111static
112unsigned op_02 (e8086_t *c)
113{
114 unsigned reg;
115 unsigned short s1, s2, d;
116
117 reg = (c->pq[1] >> 3) & 7;
118
119 e86_get_ea_ptr (c, c->pq + 1);
120
121 s1 = e86_get_reg8 (c, reg);
122 s2 = e86_get_ea8 (c);
123
124 d = s1 + s2;
125
126 e86_set_reg8 (c, reg, d);
127 e86_set_flg_add_8 (c, s1, s2);
128 e86_set_clk_ea (c, 3, 9);
129
130 return (c->ea.cnt + 1);
131}
132
133/* OP 03: ADD reg16, r/m16 */
134static
135unsigned op_03 (e8086_t *c)
136{
137 unsigned reg;
138 unsigned long s1, s2, d;
139
140 reg = (c->pq[1] >> 3) & 7;
141
142 e86_get_ea_ptr (c, c->pq + 1);
143
144 s1 = e86_get_reg16 (c, reg);
145 s2 = e86_get_ea16 (c);
146
147 d = s1 + s2;
148
149 e86_set_reg16 (c, reg, d);
150 e86_set_flg_add_16 (c, s1, s2);
151 e86_set_clk_ea (c, 3, 9);
152
153 return (c->ea.cnt + 1);
154}
155
156/* OP 04: ADD AL, data8 */
157static
158unsigned op_04 (e8086_t *c)
159{
160 unsigned short s1, s2, d;
161
162 s1 = e86_get_al (c);
163 s2 = c->pq[1];
164
165 d = s1 + s2;
166
167 e86_set_al (c, d);
168 e86_set_flg_add_8 (c, s1, s2);
169 e86_set_clk (c, 4);
170
171 return (2);
172}
173
174/* OP 05: ADD AX, data16 */
175static
176unsigned op_05 (e8086_t *c)
177{
178 unsigned long s1, s2, d;
179
180 s1 = e86_get_ax (c);
181 s2 = e86_mk_uint16 (c->pq[1], c->pq[2]);
182
183 d = s1 + s2;
184
185 e86_set_ax (c, d);
186 e86_set_flg_add_16 (c, s1, s2);
187 e86_set_clk (c, 4);
188
189 return (3);
190}
191
192/* OP 06: PUSH ES */
193static
194unsigned op_06 (e8086_t *c)
195{
196 e86_push (c, e86_get_es (c));
197 e86_set_clk (c, 10);
198
199 return (1);
200}
201
202/* OP 07: POP ES */
203static
204unsigned op_07 (e8086_t *c)
205{
206 e86_set_es (c, e86_pop (c));
207 e86_set_clk (c, 8);
208
209 return (1);
210}
211
212/* OP 08: OR r/m8, reg8 */
213static
214unsigned op_08 (e8086_t *c)
215{
216 unsigned short s1, s2, d;
217
218 e86_get_ea_ptr (c, c->pq + 1);
219
220 s1 = e86_get_ea8 (c);
221 s2 = e86_get_reg8 (c, (c->pq[1] >> 3) & 7);
222
223 d = s1 | s2;
224
225 e86_set_ea8 (c, d);
226 e86_set_flg_log_8 (c, d);
227 e86_set_clk_ea (c, 3, 16);
228
229 return (c->ea.cnt + 1);
230}
231
232/* OP 09: OR r/m16, reg16 */
233static
234unsigned op_09 (e8086_t *c)
235{
236 unsigned long s1, s2, d;
237
238 e86_get_ea_ptr (c, c->pq + 1);
239
240 s1 = e86_get_ea16 (c);
241 s2 = e86_get_reg16 (c, (c->pq[1] >> 3) & 7);
242
243 d = s1 | s2;
244
245 e86_set_ea16 (c, d);
246 e86_set_flg_log_16 (c, d);
247 e86_set_clk_ea (c, 3, 16);
248
249 return (c->ea.cnt + 1);
250}
251
252/* OP 0A: OR reg8, r/m8 */
253static
254unsigned op_0a (e8086_t *c)
255{
256 unsigned reg;
257 unsigned short s1, s2, d;
258
259 reg = (c->pq[1] >> 3) & 7;
260
261 e86_get_ea_ptr (c, c->pq + 1);
262
263 s1 = e86_get_reg8 (c, reg);
264 s2 = e86_get_ea8 (c);
265
266 d = s1 | s2;
267
268 e86_set_reg8 (c, reg, d);
269 e86_set_flg_log_8 (c, d);
270 e86_set_clk_ea (c, 3, 9);
271
272 return (c->ea.cnt + 1);
273}
274
275/* OP 0B: OR reg16, r/m16 */
276static
277unsigned op_0b (e8086_t *c)
278{
279 unsigned reg;
280 unsigned long s1, s2, d;
281
282 reg = (c->pq[1] >> 3) & 7;
283
284 e86_get_ea_ptr (c, c->pq + 1);
285
286 s1 = e86_get_reg16 (c, reg);
287 s2 = e86_get_ea16 (c);
288
289 d = s1 | s2;
290
291 e86_set_reg16 (c, reg, d);
292 e86_set_flg_log_16 (c, d);
293 e86_set_clk_ea (c, 3, 9);
294
295 return (c->ea.cnt + 1);
296}
297
298/* OP 0C: OR AL, data8 */
299static
300unsigned op_0c (e8086_t *c)
301{
302 unsigned short s1, s2, d;
303
304 s1 = e86_get_al (c);
305 s2 = c->pq[1];
306
307 d = s1 | s2;
308
309 e86_set_al (c, d);
310 e86_set_flg_log_8 (c, d);
311 e86_set_clk (c, 4);
312
313 return (2);
314}
315
316/* OP 0D: OR AX, data16 */
317static
318unsigned op_0d (e8086_t *c)
319{
320 unsigned long s1, s2, d;
321
322 s1 = e86_get_ax (c);
323 s2 = e86_mk_uint16 (c->pq[1], c->pq[2]);
324
325 d = s1 | s2;
326
327 e86_set_ax (c, d);
328 e86_set_flg_log_16 (c, d);
329 e86_set_clk (c, 4);
330
331 return (3);
332}
333
334/* OP 0E: PUSH CS */
335static
336unsigned op_0e (e8086_t *c)
337{
338 e86_push (c, e86_get_cs (c));
339 e86_set_clk (c, 10);
340
341 return (1);
342}
343
344/* OP 0F: POP CS */
345static
346unsigned op_0f (e8086_t *c)
347{
348 e86_set_cs (c, e86_pop (c));
349 e86_pq_init (c);
350
351 return (1);
352}
353
354/* OP 10: ADC r/m8, reg8 */
355static
356unsigned op_10 (e8086_t *c)
357{
358 unsigned short s1, s2, s3, d;
359
360 e86_get_ea_ptr (c, c->pq + 1);
361
362 s1 = e86_get_ea8 (c);
363 s2 = e86_get_reg8 (c, (c->pq[1] >> 3) & 7);
364 s3 = e86_get_cf (c);
365
366 d = s1 + s2 + s3;
367
368 e86_set_ea8 (c, d);
369 e86_set_flg_adc_8 (c, s1, s2, s3);
370 e86_set_clk_ea (c, 3, 16);
371
372 return (c->ea.cnt + 1);
373}
374
375/* OP 11: ADC r/m16, reg16 */
376static
377unsigned op_11 (e8086_t *c)
378{
379 unsigned long s1, s2, s3, d;
380
381 e86_get_ea_ptr (c, c->pq + 1);
382
383 s1 = e86_get_ea16 (c);
384 s2 = e86_get_reg16 (c, (c->pq[1] >> 3) & 7);
385 s3 = e86_get_cf (c);
386
387 d = s1 + s2 + s3;
388
389 e86_set_ea16 (c, d);
390 e86_set_flg_adc_16 (c, s1, s2, s3);
391 e86_set_clk_ea (c, 3, 16);
392
393 return (c->ea.cnt + 1);
394}
395
396/* OP 12: ADC reg8, r/m8 */
397static
398unsigned op_12 (e8086_t *c)
399{
400 unsigned reg;
401 unsigned short s1, s2, s3, d;
402
403 reg = (c->pq[1] >> 3) & 7;
404
405 e86_get_ea_ptr (c, c->pq + 1);
406
407 s1 = e86_get_reg8 (c, reg);
408 s2 = e86_get_ea8 (c);
409 s3 = e86_get_cf (c);
410
411 d = s1 + s2 + s3;
412
413 e86_set_reg8 (c, reg, d);
414 e86_set_flg_adc_8 (c, s1, s2, s3);
415 e86_set_clk_ea (c, 3, 9);
416
417 return (c->ea.cnt + 1);
418}
419
420/* OP 13: ADC reg16, r/m16 */
421static
422unsigned op_13 (e8086_t *c)
423{
424 unsigned reg;
425 unsigned long s1, s2, s3, d;
426
427 reg = (c->pq[1] >> 3) & 7;
428
429 e86_get_ea_ptr (c, c->pq + 1);
430
431 s1 = e86_get_reg16 (c, reg);
432 s2 = e86_get_ea16 (c);
433 s3 = e86_get_cf (c);
434
435 d = s1 + s2 + s3;
436
437 e86_set_reg16 (c, reg, d);
438 e86_set_flg_adc_16 (c, s1, s2, s3);
439 e86_set_clk_ea (c, 3, 9);
440
441 return (c->ea.cnt + 1);
442}
443
444/* OP 14: ADC AL, data8 */
445static
446unsigned op_14 (e8086_t *c)
447{
448 unsigned short s1, s2, s3, d;
449
450 s1 = e86_get_al (c);
451 s2 = c->pq[1];
452 s3 = e86_get_cf (c);
453
454 d = s1 + s2 + s3;
455
456 e86_set_al (c, d);
457 e86_set_flg_adc_8 (c, s1, s2, s3);
458 e86_set_clk (c, 4);
459
460 return (2);
461}
462
463/* OP 15: ADC AX, data16 */
464static
465unsigned op_15 (e8086_t *c)
466{
467 unsigned long s1, s2, s3, d;
468
469 s1 = e86_get_ax (c);
470 s2 = e86_mk_uint16 (c->pq[1], c->pq[2]);
471 s3 = e86_get_cf (c);
472
473 d = s1 + s2 + s3;
474
475 e86_set_ax (c, d);
476 e86_set_flg_adc_16 (c, s1, s2, s3);
477 e86_set_clk (c, 4);
478
479 return (3);
480}
481
482/* OP 16: PUSH SS */
483static
484unsigned op_16 (e8086_t *c)
485{
486 e86_push (c, e86_get_ss (c));
487 e86_set_clk (c, 10);
488
489 return (1);
490}
491
492/* OP 17: POP SS */
493static
494unsigned op_17 (e8086_t *c)
495{
496 e86_set_ss (c, e86_pop (c));
497 e86_set_clk (c, 8);
498
499 c->save_flags &= ~E86_FLG_I;
500
501 return (1);
502}
503
504/* OP 18: SBB r/m8, reg8 */
505static
506unsigned op_18 (e8086_t *c)
507{
508 unsigned short s1, s2, s3, d;
509
510 e86_get_ea_ptr (c, c->pq + 1);
511
512 s1 = e86_get_ea8 (c);
513 s2 = e86_get_reg8 (c, (c->pq[1] >> 3) & 7);
514 s3 = e86_get_cf (c);
515
516 d = s1 - s2 - s3;
517
518 e86_set_ea8 (c, d);
519 e86_set_flg_sbb_8 (c, s1, s2, s3);
520 e86_set_clk_ea (c, 3, 16);
521
522 return (c->ea.cnt + 1);
523}
524
525/* OP 19: SBB r/m16, reg16 "" */
526static
527unsigned op_19 (e8086_t *c)
528{
529 unsigned long s1, s2, s3, d;
530
531 e86_get_ea_ptr (c, c->pq + 1);
532
533 s1 = e86_get_ea16 (c);
534 s2 = e86_get_reg16 (c, (c->pq[1] >> 3) & 7);
535 s3 = e86_get_cf (c);
536
537 d = s1 - s2 - s3;
538
539 e86_set_ea16 (c, d);
540 e86_set_flg_sbb_16 (c, s1, s2, s3);
541 e86_set_clk_ea (c, 3, 16);
542
543 return (c->ea.cnt + 1);
544}
545
546/* OP 1A: SBB reg8, r/m8 */
547static
548unsigned op_1a (e8086_t *c)
549{
550 unsigned reg;
551 unsigned short s1, s2, s3, d;
552
553 reg = (c->pq[1] >> 3) & 7;
554
555 e86_get_ea_ptr (c, c->pq + 1);
556
557 s1 = e86_get_reg8 (c, reg);
558 s2 = e86_get_ea8 (c);
559 s3 = e86_get_cf (c);
560
561 d = s1 - s2 - s3;
562
563 e86_set_reg8 (c, reg, d);
564 e86_set_flg_sbb_8 (c, s1, s2, s3);
565 e86_set_clk_ea (c, 3, 9);
566
567 return (c->ea.cnt + 1);
568}
569
570/* OP 1B: SBB reg16, r/m16 */
571static
572unsigned op_1b (e8086_t *c)
573{
574 unsigned reg;
575 unsigned long s1, s2, s3, d;
576
577 reg = (c->pq[1] >> 3) & 7;
578
579 e86_get_ea_ptr (c, c->pq + 1);
580
581 s1 = e86_get_reg16 (c, reg);
582 s2 = e86_get_ea16 (c);
583 s3 = e86_get_cf (c);
584
585 d = s1 - s2 - s3;
586
587 e86_set_reg16 (c, reg, d);
588 e86_set_flg_sbb_16 (c, s1, s2, s3);
589 e86_set_clk_ea (c, 3, 9);
590
591 return (c->ea.cnt + 1);
592}
593
594/* OP 1C: SBB AL, data8 */
595static
596unsigned op_1c (e8086_t *c)
597{
598 unsigned short s1, s2, s3, d;
599
600 s1 = e86_get_al (c);
601 s2 = c->pq[1];
602 s3 = e86_get_cf (c);
603
604 d = s1 - s2 - s3;
605
606 e86_set_al (c, d);
607 e86_set_flg_sbb_8 (c, s1, s2, s3);
608 e86_set_clk (c, 4);
609
610 return (2);
611}
612
613/* OP 1D: SBB AX, data16 */
614static
615unsigned op_1d (e8086_t *c)
616{
617 unsigned long s1, s2, s3, d;
618
619 s1 = e86_get_ax (c);
620 s2 = e86_mk_uint16 (c->pq[1], c->pq[2]);
621 s3 = e86_get_cf (c);
622
623 d = s1 - s2 - s3;
624
625 e86_set_ax (c, d);
626 e86_set_flg_sbb_16 (c, s1, s2, s3);
627 e86_set_clk (c, 4);
628
629 return (3);
630}
631
632/* OP 1E: PUSH DS */
633static
634unsigned op_1e (e8086_t *c)
635{
636 e86_push (c, e86_get_ds (c));
637 e86_set_clk (c, 10);
638
639 return (1);
640}
641
642/* OP 1F: POP DS */
643static
644unsigned op_1f (e8086_t *c)
645{
646 e86_set_ds (c, e86_pop (c));
647 e86_set_clk (c, 8);
648
649 return (1);
650}
651
652/* OP 20: AND r/m8, reg8 */
653static
654unsigned op_20 (e8086_t *c)
655{
656 unsigned short s1, s2, d;
657
658 e86_get_ea_ptr (c, c->pq + 1);
659
660 s1 = e86_get_ea8 (c);
661 s2 = e86_get_reg8 (c, (c->pq[1] >> 3) & 7);
662
663 d = s1 & s2;
664
665 e86_set_ea8 (c, d);
666 e86_set_flg_log_8 (c, d);
667 e86_set_clk_ea (c, 3, 16);
668
669 return (c->ea.cnt + 1);
670}
671
672/* OP 21: AND r/m16, reg16 */
673static
674unsigned op_21 (e8086_t *c)
675{
676 unsigned long s1, s2, d;
677
678 e86_get_ea_ptr (c, c->pq + 1);
679
680 s1 = e86_get_ea16 (c);
681 s2 = e86_get_reg16 (c, (c->pq[1] >> 3) & 7);
682
683 d = s1 & s2;
684
685 e86_set_ea16 (c, d);
686 e86_set_flg_log_16 (c, d);
687 e86_set_clk_ea (c, 3, 16);
688
689 return (c->ea.cnt + 1);
690}
691
692/* OP 22: AND reg8, r/m8 */
693static unsigned op_22 (e8086_t *c)
694{
695 unsigned reg;
696 unsigned short s1, s2, d;
697
698 reg = (c->pq[1] >> 3) & 7;
699
700 e86_get_ea_ptr (c, c->pq + 1);
701
702 s1 = e86_get_reg8 (c, reg);
703 s2 = e86_get_ea8 (c);
704
705 d = s1 & s2;
706
707 e86_set_reg8 (c, reg, d);
708 e86_set_flg_log_8 (c, d);
709 e86_set_clk_ea (c, 3, 9);
710
711 return (c->ea.cnt + 1);
712}
713
714/* OP 23: AND reg16, r/m16 */
715static
716unsigned op_23 (e8086_t *c)
717{
718 unsigned reg;
719 unsigned long s1, s2, d;
720
721 reg = (c->pq[1] >> 3) & 7;
722
723 e86_get_ea_ptr (c, c->pq + 1);
724
725 s1 = e86_get_reg16 (c, reg);
726 s2 = e86_get_ea16 (c);
727
728 d = s1 & s2;
729
730 e86_set_reg16 (c, reg, d);
731 e86_set_flg_log_16 (c, d);
732 e86_set_clk_ea (c, 3, 9);
733
734 return (c->ea.cnt + 1);
735}
736
737/* OP 24: AND AL, data8 */
738static
739unsigned op_24 (e8086_t *c)
740{
741 unsigned short s1, s2, d;
742
743 s1 = e86_get_al (c);
744 s2 = c->pq[1];
745
746 d = s1 & s2;
747
748 e86_set_al (c, d);
749 e86_set_flg_log_8 (c, d);
750 e86_set_clk (c, 4);
751
752 return (2);
753}
754
755/* OP 25: AND AX, data16 */
756static
757unsigned op_25 (e8086_t *c)
758{
759 unsigned long s1, s2, d;
760
761 s1 = e86_get_ax (c);
762 s2 = e86_mk_uint16 (c->pq[1], c->pq[2]);
763
764 d = s1 & s2;
765
766 e86_set_ax (c, d);
767 e86_set_flg_log_16 (c, d);
768 e86_set_clk (c, 4);
769
770 return (3);
771}
772
773/* OP 26: ES: */
774static
775unsigned op_26 (e8086_t *c)
776{
777 c->prefix |= (E86_PREFIX_NEW | E86_PREFIX_SEG);
778
779 c->seg_override = c->sreg[E86_REG_ES];
780
781 return (1);
782}
783
784/* OP 27: DAA */
785static
786unsigned op_27 (e8086_t *c)
787{
788 unsigned al, cf;
789
790 al = e86_get_al (c);
791 cf = e86_get_cf (c);
792
793 if (((al & 0x0f) > 9) || e86_get_af (c)) {
794 al += 6;
795 cf |= ((al & 0xff00) != 0);
796 e86_set_af (c, 1);
797 }
798 else {
799 e86_set_af (c, 0);
800 }
801
802 if (((al & 0xf0) > 0x90) || cf) {
803 al += 0x60;
804 e86_set_cf (c, 1);
805 }
806 else {
807 e86_set_cf (c, 0);
808 }
809
810 e86_set_al (c, al);
811 e86_set_flg_szp_8 (c, al);
812 e86_set_clk (c, 4);
813
814 return (1);
815}
816
817/* OP 28: SUB r/m8, reg8 */
818static
819unsigned op_28 (e8086_t *c)
820{
821 unsigned short s1, s2, d;
822
823 e86_get_ea_ptr (c, c->pq + 1);
824
825 s1 = e86_get_ea8 (c);
826 s2 = e86_get_reg8 (c, (c->pq[1] >> 3) & 7);
827
828 d = s1 - s2;
829
830 e86_set_ea8 (c, d);
831 e86_set_flg_sub_8 (c, s1, s2);
832 e86_set_clk_ea (c, 3, 16);
833
834 return (c->ea.cnt + 1);
835}
836
837/* OP 29: SUB r/m16, reg16 */
838static
839unsigned op_29 (e8086_t *c)
840{
841 unsigned long s1, s2, d;
842
843 e86_get_ea_ptr (c, c->pq + 1);
844
845 s1 = e86_get_ea16 (c);
846 s2 = e86_get_reg16 (c, (c->pq[1] >> 3) & 7);
847
848 d = s1 - s2;
849
850 e86_set_ea16 (c, d);
851 e86_set_flg_sub_16 (c, s1, s2);
852 e86_set_clk_ea (c, 3, 16);
853
854 return (c->ea.cnt + 1);
855}
856
857/* OP 2A: SUB reg8, r/m8 */
858static
859unsigned op_2a (e8086_t *c)
860{
861 unsigned reg;
862 unsigned short s1, s2, d;
863
864 reg = (c->pq[1] >> 3) & 7;
865
866 e86_get_ea_ptr (c, c->pq + 1);
867
868 s1 = e86_get_reg8 (c, reg);
869 s2 = e86_get_ea8 (c);
870
871 d = s1 - s2;
872
873 e86_set_reg8 (c, reg, d);
874 e86_set_flg_sub_8 (c, s1, s2);
875 e86_set_clk_ea (c, 3, 9);
876
877 return (c->ea.cnt + 1);
878}
879
880/* OP 2B: SUB reg16, r/m16 */
881static
882unsigned op_2b (e8086_t *c)
883{
884 unsigned reg;
885 unsigned long s1, s2, d;
886
887 reg = (c->pq[1] >> 3) & 7;
888
889 e86_get_ea_ptr (c, c->pq + 1);
890
891 s1 = e86_get_reg16 (c, reg);
892 s2 = e86_get_ea16 (c);
893
894 d = s1 - s2;
895
896 e86_set_reg16 (c, reg, d);
897 e86_set_flg_sub_16 (c, s1, s2);
898 e86_set_clk_ea (c, 3, 9);
899
900 return (c->ea.cnt + 1);
901}
902
903/* OP 2C: SUB AL, data8 */
904static
905unsigned op_2c (e8086_t *c)
906{
907 unsigned short s1, s2, d;
908
909 s1 = e86_get_al (c);
910 s2 = c->pq[1];
911
912 d = s1 - s2;
913
914 e86_set_al (c, d);
915 e86_set_flg_sub_8 (c, s1, s2);
916 e86_set_clk (c, 4);
917
918 return (2);
919}
920
921/* OP 2D: SUB AX, data16 */
922static
923unsigned op_2d (e8086_t *c)
924{
925 unsigned long s1, s2, d;
926
927 s1 = e86_get_ax (c);
928 s2 = e86_mk_uint16 (c->pq[1], c->pq[2]);
929
930 d = s1 - s2;
931
932 e86_set_ax (c, d);
933 e86_set_flg_sub_16 (c, s1, s2);
934 e86_set_clk (c, 4);
935
936 return (3);
937}
938
939/* OP 2E: CS: */
940static
941unsigned op_2e (e8086_t *c)
942{
943 c->prefix |= (E86_PREFIX_NEW | E86_PREFIX_SEG);
944
945 c->seg_override = c->sreg[E86_REG_CS];
946
947 return (1);
948}
949
950/* OP 2F: DAS */
951static
952unsigned op_2f (e8086_t *c)
953{
954 unsigned al, cf;
955
956 al = e86_get_al (c);
957 cf = e86_get_cf (c);
958
959 if (((al & 0x0f) > 9) || e86_get_af (c)) {
960 al -= 6;
961 cf |= ((al & 0xff00) != 0);
962 e86_set_af (c, 1);
963 }
964 else {
965 e86_set_af (c, 0);
966 }
967
968 if (((al & 0xf0) > 0x90) || cf) {
969 al -= 0x60;
970 e86_set_cf (c, 1);
971 }
972 else {
973 e86_set_cf (c, 0);
974 }
975
976 e86_set_al (c, al);
977 e86_set_flg_szp_8 (c, al);
978 e86_set_clk (c, 4);
979
980 return (1);
981}
982
983/* OP 30: XOR r/m8, reg8 */
984static
985unsigned op_30 (e8086_t *c)
986{
987 unsigned short s1, s2, d;
988
989 e86_get_ea_ptr (c, c->pq + 1);
990
991 s1 = e86_get_ea8 (c);
992 s2 = e86_get_reg8 (c, (c->pq[1] >> 3) & 7);
993
994 d = s1 ^ s2;
995
996 e86_set_ea8 (c, d);
997 e86_set_flg_log_8 (c, d);
998 e86_set_clk_ea (c, 3, 16);
999
1000 return (c->ea.cnt + 1);
1001}
1002
1003/* OP 31: XOR r/m16, reg16 */
1004static
1005unsigned op_31 (e8086_t *c)
1006{
1007 unsigned long s1, s2, d;
1008
1009 e86_get_ea_ptr (c, c->pq + 1);
1010
1011 s1 = e86_get_ea16 (c);
1012 s2 = e86_get_reg16 (c, (c->pq[1] >> 3) & 7);
1013
1014 d = s1 ^ s2;
1015
1016 e86_set_ea16 (c, d);
1017 e86_set_flg_log_16 (c, d);
1018 e86_set_clk_ea (c, 3, 16);
1019
1020 return (c->ea.cnt + 1);
1021}
1022
1023/* OP 32: XOR reg8, r/m8 */
1024static
1025unsigned op_32 (e8086_t *c)
1026{
1027 unsigned reg;
1028 unsigned short s1, s2, d;
1029
1030 reg = (c->pq[1] >> 3) & 7;
1031
1032 e86_get_ea_ptr (c, c->pq + 1);
1033
1034 s1 = e86_get_reg8 (c, reg);
1035 s2 = e86_get_ea8 (c);
1036
1037 d = s1 ^ s2;
1038
1039 e86_set_reg8 (c, reg, d);
1040 e86_set_flg_log_8 (c, d);
1041 e86_set_clk_ea (c, 3, 9);
1042
1043 return (c->ea.cnt + 1);
1044}
1045
1046/* OP 33: XOR reg16, r/m16 */
1047static
1048unsigned op_33 (e8086_t *c)
1049{
1050 unsigned reg;
1051 unsigned long s1, s2, d;
1052
1053 reg = (c->pq[1] >> 3) & 7;
1054
1055 e86_get_ea_ptr (c, c->pq + 1);
1056
1057 s1 = e86_get_reg16 (c, reg);
1058 s2 = e86_get_ea16 (c);
1059
1060 d = s1 ^ s2;
1061
1062 e86_set_reg16 (c, reg, d);
1063 e86_set_flg_log_16 (c, d);
1064 e86_set_clk_ea (c, 3, 9);
1065
1066 return (c->ea.cnt + 1);
1067}
1068
1069/* OP 34: XOR AL, data8 */
1070static
1071unsigned op_34 (e8086_t *c)
1072{
1073 unsigned short s1, s2, d;
1074
1075 s1 = e86_get_al (c);
1076 s2 = c->pq[1];
1077
1078 d = s1 ^ s2;
1079
1080 e86_set_al (c, d);
1081 e86_set_flg_log_8 (c, d);
1082 e86_set_clk (c, 4);
1083
1084 return (2);
1085}
1086
1087/* OP 35: XOR AX, data16 */
1088static
1089unsigned op_35 (e8086_t *c)
1090{
1091 unsigned long s1, s2, d;
1092
1093 s1 = e86_get_ax (c);
1094 s2 = e86_mk_uint16 (c->pq[1], c->pq[2]);
1095
1096 d = s1 ^ s2;
1097
1098 e86_set_ax (c, d);
1099 e86_set_flg_log_16 (c, d);
1100 e86_set_clk (c, 4);
1101
1102 return (3);
1103}
1104
1105/* OP 36: SS: */
1106static
1107unsigned op_36 (e8086_t *c)
1108{
1109 c->prefix |= (E86_PREFIX_NEW | E86_PREFIX_SEG);
1110
1111 c->seg_override = c->sreg[E86_REG_SS];
1112
1113 return (1);
1114}
1115
1116/* OP 37: AAA */
1117static
1118unsigned op_37 (e8086_t *c)
1119{
1120 unsigned ah, al;
1121
1122 al = e86_get_al (c);
1123 ah = e86_get_ah (c);
1124
1125 if (((al & 0x0f) > 9) || e86_get_af (c)) {
1126 al += 6;
1127 ah += 1;
1128 c->flg |= (E86_FLG_A | E86_FLG_C);
1129 }
1130 else {
1131 c->flg &= ~(E86_FLG_A | E86_FLG_C);
1132 }
1133
1134 e86_set_ax (c, ((ah & 0xff) << 8) | (al & 0x0f));
1135
1136 e86_set_clk (c, 8);
1137
1138 return (1);
1139}
1140
1141/* OP 38: CMP r/m8, reg8 */
1142static
1143unsigned op_38 (e8086_t *c)
1144{
1145 unsigned short s1, s2;
1146
1147 e86_get_ea_ptr (c, c->pq + 1);
1148
1149 s1 = e86_get_ea8 (c);
1150 s2 = e86_get_reg8 (c, (c->pq[1] >> 3) & 7);
1151
1152 e86_set_flg_sub_8 (c, s1, s2);
1153 e86_set_clk_ea (c, 3, 9);
1154
1155 return (c->ea.cnt + 1);
1156}
1157
1158/* OP 39: CMP r/m16, reg16 */
1159static
1160unsigned op_39 (e8086_t *c)
1161{
1162 unsigned long s1, s2;
1163
1164 e86_get_ea_ptr (c, c->pq + 1);
1165
1166 s1 = e86_get_ea16 (c);
1167 s2 = e86_get_reg16 (c, (c->pq[1] >> 3) & 7);
1168
1169 e86_set_flg_sub_16 (c, s1, s2);
1170 e86_set_clk_ea (c, 3, 9);
1171
1172 return (c->ea.cnt + 1);
1173}
1174
1175/* OP 3A: CMP reg8, r/m8 */
1176static unsigned op_3a (e8086_t *c)
1177{
1178 unsigned short s1, s2;
1179
1180 e86_get_ea_ptr (c, c->pq + 1);
1181
1182 s1 = e86_get_reg8 (c, (c->pq[1] >> 3) & 7);
1183 s2 = e86_get_ea8 (c);
1184
1185 e86_set_flg_sub_8 (c, s1, s2);
1186 e86_set_clk_ea (c, 3, 9);
1187
1188 return (c->ea.cnt + 1);
1189}
1190
1191/* OP 3B: CMP reg16, r/m16 */
1192static
1193unsigned op_3b (e8086_t *c)
1194{
1195 unsigned long s1, s2;
1196
1197 e86_get_ea_ptr (c, c->pq + 1);
1198
1199 s1 = e86_get_reg16 (c, (c->pq[1] >> 3) & 7);
1200 s2 = e86_get_ea16 (c);
1201
1202 e86_set_flg_sub_16 (c, s1, s2);
1203 e86_set_clk_ea (c, 3, 9);
1204
1205 return (c->ea.cnt + 1);
1206}
1207
1208/* OP 3C: CMP AL, data8 */
1209static
1210unsigned op_3c (e8086_t *c)
1211{
1212 unsigned short s1, s2;
1213
1214 s1 = e86_get_al (c);
1215 s2 = c->pq[1];
1216
1217 e86_set_flg_sub_8 (c, s1, s2);
1218 e86_set_clk (c, 4);
1219
1220 return (2);
1221}
1222
1223/* OP 3D: CMP AX, data16 */
1224static
1225unsigned op_3d (e8086_t *c)
1226{
1227 unsigned long s1, s2;
1228
1229 s1 = e86_get_ax (c);
1230 s2 = e86_mk_uint16 (c->pq[1], c->pq[2]);
1231
1232 e86_set_flg_sub_16 (c, s1, s2);
1233 e86_set_clk (c, 4);
1234
1235 return (3);
1236}
1237
1238/* OP 3E: DS: */
1239static
1240unsigned op_3e (e8086_t *c)
1241{
1242 c->prefix |= (E86_PREFIX_NEW | E86_PREFIX_SEG);
1243
1244 c->seg_override = c->sreg[E86_REG_DS];
1245
1246 return (1);
1247}
1248
1249/* OP 3F: AAS */
1250static
1251unsigned op_3f (e8086_t *c)
1252{
1253 unsigned ah, al;
1254
1255 al = e86_get_al (c);
1256 ah = e86_get_ah (c);
1257
1258 if (((al & 0x0f) > 9) || e86_get_af (c)) {
1259 al -= 6;
1260 ah -= 1;
1261 c->flg |= (E86_FLG_A | E86_FLG_C);
1262 }
1263 else {
1264 c->flg &= ~(E86_FLG_A | E86_FLG_C);
1265 }
1266
1267 e86_set_ax (c, ((ah & 0xff) << 8) | (al & 0x0f));
1268
1269 e86_set_clk (c, 8);
1270
1271 return (1);
1272}
1273
1274/* OP 4x: INC reg16 */
1275static
1276unsigned op_40 (e8086_t *c)
1277{
1278 unsigned r;
1279 unsigned short cf;
1280 unsigned long s;
1281
1282 r = c->pq[0] & 7;
1283 s = c->dreg[r];
1284 c->dreg[r] = (s + 1) & 0xffff;
1285
1286 cf = c->flg;
1287 e86_set_flg_add_16 (c, s, 1);
1288 c->flg ^= (c->flg ^ cf) & E86_FLG_C;
1289
1290 e86_set_clk (c, 3);
1291
1292 return (1);
1293}
1294
1295/* OP 4x: DEC reg16 */
1296static
1297unsigned op_48 (e8086_t *c)
1298{
1299 unsigned r;
1300 unsigned short cf;
1301 unsigned long s;
1302
1303 r = c->pq[0] & 7;
1304 s = c->dreg[r];
1305 c->dreg[r] = (s - 1) & 0xffff;
1306
1307 cf = c->flg;
1308 e86_set_flg_sub_16 (c, s, 1);
1309 c->flg ^= (c->flg ^ cf) & E86_FLG_C;
1310
1311 e86_set_clk (c, 3);
1312
1313 return (1);
1314}
1315
1316/* OP 5x: PUSH reg16 */
1317static
1318unsigned op_50 (e8086_t *c)
1319{
1320 unsigned reg;
1321
1322 reg = c->pq[0] & 7;
1323
1324 if ((reg == E86_REG_SP) && ((c->cpu & E86_CPU_PUSH_FIRST) == 0)) {
1325 e86_push (c, e86_get_sp (c) - 2);
1326 }
1327 else {
1328 e86_push (c, e86_get_reg16 (c, reg));
1329 }
1330
1331 e86_set_clk (c, 10);
1332
1333 return (1);
1334}
1335
1336/* OP 5x: POP reg16 */
1337static
1338unsigned op_58 (e8086_t *c)
1339{
1340 unsigned short val;
1341
1342 val = e86_pop (c);
1343 e86_set_reg16 (c, c->pq[0] & 7, val);
1344 e86_set_clk (c, 8);
1345
1346 return (1);
1347}
1348
1349/* OP 66: hook */
1350static
1351unsigned op_66 (e8086_t *c)
1352{
1353 unsigned short cs, ip;
1354
1355 if (c->pq[1] != 0x66) {
1356 return (op_ud (c));
1357 }
1358
1359 cs = e86_get_cs (c);
1360 ip = e86_get_ip (c);
1361
1362 if (c->op_hook != NULL) {
1363 c->op_hook (c->op_ext, c->pq[2], c->pq[3]);
1364 }
1365
1366 e86_set_clk (c, 16);
1367
1368 if ((e86_get_cs (c) != cs) || (e86_get_ip (c) != ip)) {
1369 return (0);
1370 }
1371
1372 return (4);
1373}
1374
1375/* OP 70: JO imm8 */
1376static
1377unsigned op_70 (e8086_t *c)
1378{
1379 if (e86_get_of (c)) {
1380 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1381 e86_pq_init (c);
1382 e86_set_clk (c, 16);
1383 return (0);
1384 }
1385
1386 e86_set_clk (c, 4);
1387
1388 return (2);
1389}
1390
1391/* OP 71: JNO imm8 */
1392static
1393unsigned op_71 (e8086_t *c)
1394{
1395 if (!e86_get_of (c)) {
1396 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1397 e86_pq_init (c);
1398 e86_set_clk (c, 16);
1399 return (0);
1400 }
1401
1402 e86_set_clk (c, 4);
1403
1404 return (2);
1405}
1406
1407/* OP 72: JB imm8 */
1408static
1409unsigned op_72 (e8086_t *c)
1410{
1411 if (e86_get_cf (c)) {
1412 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1413 e86_pq_init (c);
1414 e86_set_clk (c, 16);
1415 return (0);
1416 }
1417
1418 e86_set_clk (c, 4);
1419
1420 return (2);
1421}
1422
1423/* OP 73: JAE imm8 */
1424static
1425unsigned op_73 (e8086_t *c)
1426{
1427 if (!e86_get_cf (c)) {
1428 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1429 e86_pq_init (c);
1430 e86_set_clk (c, 16);
1431 return (0);
1432 }
1433
1434 e86_set_clk (c, 4);
1435
1436 return (2);
1437}
1438
1439/* OP 74: JE imm8 */
1440static
1441unsigned op_74 (e8086_t *c)
1442{
1443 if (e86_get_zf (c)) {
1444 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1445 e86_pq_init (c);
1446 e86_set_clk (c, 16);
1447 return (0);
1448 }
1449
1450 e86_set_clk (c, 4);
1451
1452 return (2);
1453}
1454
1455/* OP 75: JNE imm8 */
1456static
1457unsigned op_75 (e8086_t *c)
1458{
1459 if (!e86_get_zf (c)) {
1460 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1461 e86_pq_init (c);
1462 e86_set_clk (c, 16);
1463 return (0);
1464 }
1465
1466 e86_set_clk (c, 4);
1467
1468 return (2);
1469}
1470
1471/* OP 76: JBE imm8 */
1472static
1473unsigned op_76 (e8086_t *c)
1474{
1475 if (e86_get_zf (c) || e86_get_cf (c)) {
1476 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1477 e86_pq_init (c);
1478 e86_set_clk (c, 16);
1479 return (0);
1480 }
1481
1482 e86_set_clk (c, 4);
1483
1484 return (2);
1485}
1486
1487/* OP 77: JA imm8 */
1488static
1489unsigned op_77 (e8086_t *c)
1490{
1491 if (!(e86_get_zf (c) || e86_get_cf (c))) {
1492 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1493 e86_pq_init (c);
1494 e86_set_clk (c, 16);
1495 return (0);
1496 }
1497
1498 e86_set_clk (c, 4);
1499
1500 return (2);
1501}
1502
1503/* OP 78: JS imm8 */
1504static
1505unsigned op_78 (e8086_t *c)
1506{
1507 if (e86_get_sf (c)) {
1508 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1509 e86_pq_init (c);
1510 e86_set_clk (c, 16);
1511 return (0);
1512 }
1513
1514 e86_set_clk (c, 4);
1515
1516 return (2);
1517}
1518
1519/* OP 79: JNS imm8 */
1520static
1521unsigned op_79 (e8086_t *c)
1522{
1523 if (!e86_get_sf (c)) {
1524 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1525 e86_pq_init (c);
1526 e86_set_clk (c, 16);
1527 return (0);
1528 }
1529
1530 e86_set_clk (c, 4);
1531
1532 return (2);
1533}
1534
1535/* OP 7A: JPE imm8 */
1536static
1537unsigned op_7a (e8086_t *c)
1538{
1539 if (e86_get_pf (c)) {
1540 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1541 e86_pq_init (c);
1542 e86_set_clk (c, 16);
1543 return (0);
1544 }
1545
1546 e86_set_clk (c, 4);
1547
1548 return (2);
1549}
1550
1551/* OP 7B: JPO imm8 */
1552static
1553unsigned op_7b (e8086_t *c)
1554{
1555 if (!e86_get_pf (c)) {
1556 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1557 e86_pq_init (c);
1558 e86_set_clk (c, 16);
1559 return (0);
1560 }
1561
1562 e86_set_clk (c, 4);
1563
1564 return (2);
1565}
1566
1567/* OP 7C: JL imm8 */
1568static
1569unsigned op_7c (e8086_t *c)
1570{
1571 if (e86_get_sf (c) != e86_get_of (c)) {
1572 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1573 e86_pq_init (c);
1574 e86_set_clk (c, 16);
1575 return (0);
1576 }
1577
1578 e86_set_clk (c, 4);
1579
1580 return (2);
1581}
1582
1583/* OP 7D: JGE imm8 */
1584static
1585unsigned op_7d (e8086_t *c)
1586{
1587 if (e86_get_sf (c) == e86_get_of (c)) {
1588 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1589 e86_pq_init (c);
1590 e86_set_clk (c, 16);
1591 return (0);
1592 }
1593
1594 e86_set_clk (c, 4);
1595
1596 return (2);
1597}
1598
1599/* OP 7E: JLE imm8 */
1600static
1601unsigned op_7e (e8086_t *c)
1602{
1603 if ((e86_get_sf (c) != e86_get_of (c)) || e86_get_zf (c)) {
1604 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1605 e86_pq_init (c);
1606 e86_set_clk (c, 16);
1607 return (0);
1608 }
1609
1610 e86_set_clk (c, 4);
1611
1612 return (2);
1613}
1614
1615/* OP 7F: JG imm8 */
1616static
1617unsigned op_7f (e8086_t *c)
1618{
1619 if ((e86_get_sf (c) == e86_get_of (c)) && (!e86_get_zf (c))) {
1620 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
1621 e86_pq_init (c);
1622 e86_set_clk (c, 16);
1623 return (0);
1624 }
1625
1626 e86_set_clk (c, 4);
1627
1628 return (2);
1629}
1630
1631/* OP 80 00: ADD r/m8, imm8 */
1632static
1633unsigned op_80_00 (e8086_t *c)
1634{
1635 unsigned short s1, s2, d;
1636
1637 e86_get_ea_ptr (c, c->pq + 1);
1638
1639 s1 = e86_get_ea8 (c);
1640 s2 = c->pq[c->ea.cnt + 1];
1641
1642 d = s1 + s2;
1643
1644 e86_set_ea8 (c, d & 0xff);
1645 e86_set_flg_add_8 (c, s1, s2);
1646 e86_set_clk_ea (c, 4, 17);
1647
1648 return (2 + c->ea.cnt);
1649}
1650
1651/* OP 80 01: OR r/m8, imm8 */
1652static
1653unsigned op_80_01 (e8086_t *c)
1654{
1655 unsigned short s1, s2, d;
1656
1657 e86_get_ea_ptr (c, c->pq + 1);
1658
1659 s1 = e86_get_ea8 (c);
1660 s2 = c->pq[c->ea.cnt + 1];
1661
1662 d = s1 | s2;
1663
1664 e86_set_ea8 (c, d & 0xff);
1665 e86_set_flg_log_8 (c, d);
1666 e86_set_clk_ea (c, 4, 17);
1667
1668 return (2 + c->ea.cnt);
1669}
1670
1671/* OP 80 02: ADC r/m8, imm8 */
1672static
1673unsigned op_80_02 (e8086_t *c)
1674{
1675 unsigned short s1, s2, s3, d;
1676
1677 e86_get_ea_ptr (c, c->pq + 1);
1678
1679 s1 = e86_get_ea8 (c);
1680 s2 = c->pq[c->ea.cnt + 1];
1681 s3 = e86_get_cf (c);
1682
1683 d = s1 + s2 + s3;
1684
1685 e86_set_ea8 (c, d & 0xff);
1686 e86_set_flg_adc_8 (c, s1, s2, s3);
1687 e86_set_clk_ea (c, 4, 17);
1688
1689 return (2 + c->ea.cnt);
1690}
1691
1692/* OP 80 03: SBB r/m8, imm8 */
1693static
1694unsigned op_80_03 (e8086_t *c)
1695{
1696 unsigned short s1, s2, s3, d;
1697
1698 e86_get_ea_ptr (c, c->pq + 1);
1699
1700 s1 = e86_get_ea8 (c);
1701 s2 = c->pq[c->ea.cnt + 1];
1702 s3 = e86_get_cf (c);
1703
1704 d = s1 - s2 - s3;
1705
1706 e86_set_ea8 (c, d & 0xff);
1707 e86_set_flg_sbb_8 (c, s1, s2, s3);
1708 e86_set_clk_ea (c, 4, 17);
1709
1710 return (2 + c->ea.cnt);
1711}
1712
1713/* OP 80 04: AND r/m8, imm8 */
1714static
1715unsigned op_80_04 (e8086_t *c)
1716{
1717 unsigned short s1, s2, d;
1718
1719 e86_get_ea_ptr (c, c->pq + 1);
1720
1721 s1 = e86_get_ea8 (c);
1722 s2 = c->pq[c->ea.cnt + 1];
1723
1724 d = s1 & s2;
1725
1726 e86_set_ea8 (c, d);
1727 e86_set_flg_log_8 (c, d);
1728 e86_set_clk_ea (c, 4, 17);
1729
1730 return (2 + c->ea.cnt);
1731}
1732
1733/* OP 80 05: SUB r/m8, imm8 */
1734static
1735unsigned op_80_05 (e8086_t *c)
1736{
1737 unsigned short s1, s2, d;
1738
1739 e86_get_ea_ptr (c, c->pq + 1);
1740
1741 s1 = e86_get_ea8 (c);
1742 s2 = c->pq[c->ea.cnt + 1];
1743
1744 d = s1 - s2;
1745
1746 e86_set_ea8 (c, d & 0xff);
1747 e86_set_flg_sub_8 (c, s1, s2);
1748 e86_set_clk_ea (c, 4, 17);
1749
1750 return (2 + c->ea.cnt);
1751}
1752
1753/* OP 80 06: XOR r/m8, imm8 */
1754static
1755unsigned op_80_06 (e8086_t *c)
1756{
1757 unsigned short s1, s2, d;
1758
1759 e86_get_ea_ptr (c, c->pq + 1);
1760
1761 s1 = e86_get_ea8 (c);
1762 s2 = c->pq[c->ea.cnt + 1];
1763
1764 d = s1 ^ s2;
1765
1766 e86_set_ea8 (c, d);
1767 e86_set_flg_log_8 (c, d);
1768 e86_set_clk_ea (c, 4, 17);
1769
1770 return (2 + c->ea.cnt);
1771}
1772
1773/* OP 80 07: CMP r/m8, imm8 */
1774static
1775unsigned op_80_07 (e8086_t *c)
1776{
1777 unsigned short s1, s2;
1778
1779 e86_get_ea_ptr (c, c->pq + 1);
1780
1781 s1 = e86_get_ea8 (c);
1782 s2 = c->pq[c->ea.cnt + 1];
1783
1784 e86_set_flg_sub_8 (c, s1, s2);
1785 e86_set_clk_ea (c, 4, 10);
1786
1787 return (2 + c->ea.cnt);
1788}
1789
1790static
1791e86_opcode_f e86_opcodes_80[8] = {
1792 &op_80_00, &op_80_01, &op_80_02, &op_80_03,
1793 &op_80_04, &op_80_05, &op_80_06, &op_80_07,
1794};
1795
1796/* OP 80: xxx r/m8, imm8 */
1797static
1798unsigned op_80 (e8086_t *c)
1799{
1800 unsigned xop;
1801
1802 xop = (c->pq[1] >> 3) & 7;
1803
1804 return (e86_opcodes_80[xop] (c));
1805}
1806
1807/* OP 81 00: ADD r/m16, imm16 */
1808static
1809unsigned op_81_00 (e8086_t *c)
1810{
1811 unsigned long s1, s2, d;
1812
1813 e86_get_ea_ptr (c, c->pq + 1);
1814
1815 s1 = e86_get_ea16 (c);
1816 s2 = e86_mk_uint16 (c->pq[c->ea.cnt + 1], c->pq[c->ea.cnt + 2]);
1817
1818 d = s1 + s2;
1819
1820 e86_set_ea16 (c, d & 0xffff);
1821 e86_set_flg_add_16 (c, s1, s2);
1822 e86_set_clk_ea (c, 4, 17);
1823
1824 return (3 + c->ea.cnt);
1825}
1826
1827/* OP 81 01: OR r/m16, imm16 */
1828static
1829unsigned op_81_01 (e8086_t *c)
1830{
1831 unsigned long s1, s2, d;
1832
1833 e86_get_ea_ptr (c, c->pq + 1);
1834
1835 s1 = e86_get_ea16 (c);
1836 s2 = e86_mk_uint16 (c->pq[c->ea.cnt + 1], c->pq[c->ea.cnt + 2]);
1837
1838 d = s1 | s2;
1839
1840 e86_set_ea16 (c, d & 0xffff);
1841 e86_set_flg_log_16 (c, d);
1842 e86_set_clk_ea (c, 4, 17);
1843
1844 return (3 + c->ea.cnt);
1845}
1846
1847/* OP 81 02: ADC r/m16, imm16 */
1848static
1849unsigned op_81_02 (e8086_t *c)
1850{
1851 unsigned long s1, s2, s3, d;
1852
1853 e86_get_ea_ptr (c, c->pq + 1);
1854
1855 s1 = e86_get_ea16 (c);
1856 s2 = e86_mk_uint16 (c->pq[c->ea.cnt + 1], c->pq[c->ea.cnt + 2]);
1857 s3 = e86_get_cf (c);
1858
1859 d = s1 + s2 + s3;
1860
1861 e86_set_ea16 (c, d & 0xffff);
1862 e86_set_flg_adc_16 (c, s1, s2, s3);
1863 e86_set_clk_ea (c, 4, 17);
1864
1865 return (3 + c->ea.cnt);
1866}
1867
1868/* OP 81 03: SBB r/m16, imm16 */
1869static
1870unsigned op_81_03 (e8086_t *c)
1871{
1872 unsigned long s1, s2, s3, d;
1873
1874 e86_get_ea_ptr (c, c->pq + 1);
1875
1876 s1 = e86_get_ea16 (c);
1877 s2 = e86_mk_uint16 (c->pq[c->ea.cnt + 1], c->pq[c->ea.cnt + 2]);
1878 s3 = e86_get_cf (c);
1879
1880 d = s1 - s2 - s3;
1881
1882 e86_set_ea16 (c, d & 0xffff);
1883 e86_set_flg_sbb_16 (c, s1, s2, s3);
1884 e86_set_clk_ea (c, 4, 17);
1885
1886 return (3 + c->ea.cnt);
1887}
1888
1889/* OP 81 04: AND r/m16, imm16 */
1890static
1891unsigned op_81_04 (e8086_t *c)
1892{
1893 unsigned long s1, s2, d;
1894
1895 e86_get_ea_ptr (c, c->pq + 1);
1896
1897 s1 = e86_get_ea16 (c);
1898 s2 = e86_mk_uint16 (c->pq[c->ea.cnt + 1], c->pq[c->ea.cnt + 2]);
1899
1900 d = s1 & s2;
1901
1902 e86_set_ea16 (c, d);
1903 e86_set_flg_log_16 (c, d);
1904 e86_set_clk_ea (c, 4, 17);
1905
1906 return (3 + c->ea.cnt);
1907}
1908
1909/* OP 81 05: SUB r/m16, imm16 */
1910static
1911unsigned op_81_05 (e8086_t *c)
1912{
1913 unsigned long s1, s2, d;
1914
1915 e86_get_ea_ptr (c, c->pq + 1);
1916
1917 s1 = e86_get_ea16 (c);
1918 s2 = e86_mk_uint16 (c->pq[c->ea.cnt + 1], c->pq[c->ea.cnt + 2]);
1919
1920 d = s1 - s2;
1921
1922 e86_set_ea16 (c, d & 0xffff);
1923 e86_set_flg_sub_16 (c, s1, s2);
1924 e86_set_clk_ea (c, 4, 17);
1925
1926 return (3 + c->ea.cnt);
1927}
1928
1929/* OP 81 06: XOR r/m16, imm16 */
1930static
1931unsigned op_81_06 (e8086_t *c)
1932{
1933 unsigned long s1, s2, d;
1934
1935 e86_get_ea_ptr (c, c->pq + 1);
1936
1937 s1 = e86_get_ea16 (c);
1938 s2 = e86_mk_uint16 (c->pq[c->ea.cnt + 1], c->pq[c->ea.cnt + 2]);
1939
1940 d = s1 ^ s2;
1941
1942 e86_set_ea16 (c, d);
1943 e86_set_flg_log_16 (c, d);
1944 e86_set_clk_ea (c, 4, 17);
1945
1946 return (3 + c->ea.cnt);
1947}
1948
1949/* OP 81 07: CMP r/m16, imm16 */
1950static
1951unsigned op_81_07 (e8086_t *c)
1952{
1953 unsigned long s1, s2;
1954
1955 e86_get_ea_ptr (c, c->pq + 1);
1956
1957 s1 = e86_get_ea16 (c);
1958 s2 = e86_mk_uint16 (c->pq[c->ea.cnt + 1], c->pq[c->ea.cnt + 2]);
1959
1960 e86_set_flg_sub_16 (c, s1, s2);
1961 e86_set_clk_ea (c, 4, 10);
1962
1963 return (3 + c->ea.cnt);
1964}
1965
1966static
1967e86_opcode_f e86_opcodes_81[8] = {
1968 &op_81_00, &op_81_01, &op_81_02, &op_81_03,
1969 &op_81_04, &op_81_05, &op_81_06, &op_81_07,
1970};
1971
1972/* OP 81: xxx r/m16, imm16 */
1973static
1974unsigned op_81 (e8086_t *c)
1975{
1976 unsigned xop;
1977
1978 xop = (c->pq[1] >> 3) & 7;
1979
1980 return (e86_opcodes_81[xop] (c));
1981}
1982
1983/* OP 83 00: ADD r/m16, imm8 */
1984static
1985unsigned op_83_00 (e8086_t *c)
1986{
1987 unsigned long s1, s2, d;
1988
1989 e86_get_ea_ptr (c, c->pq + 1);
1990
1991 s1 = e86_get_ea16 (c);
1992 s2 = e86_mk_sint16 (c->pq[c->ea.cnt + 1]);
1993
1994 d = s1 + s2;
1995
1996 e86_set_ea16 (c, d);
1997 e86_set_flg_add_16 (c, s1, s2);
1998 e86_set_clk_ea (c, 4, 17);
1999
2000 return (2 + c->ea.cnt);
2001}
2002
2003/* OP 83 01: OR r/m16, imm8 */
2004static
2005unsigned op_83_01 (e8086_t *c)
2006{
2007 unsigned long s1, s2, d;
2008
2009 e86_get_ea_ptr (c, c->pq + 1);
2010
2011 s1 = e86_get_ea16 (c);
2012 s2 = e86_mk_sint16 (c->pq[c->ea.cnt + 1]);
2013
2014 d = s1 | s2;
2015
2016 e86_set_ea16 (c, d);
2017 e86_set_flg_log_16 (c, d);
2018 e86_set_clk_ea (c, 4, 17);
2019
2020 return (2 + c->ea.cnt);
2021}
2022
2023/* OP 83 02: ADC r/m16, imm8 */
2024static
2025unsigned op_83_02 (e8086_t *c)
2026{
2027 unsigned long s1, s2, s3, d;
2028
2029 e86_get_ea_ptr (c, c->pq + 1);
2030
2031 s1 = e86_get_ea16 (c);
2032 s2 = e86_mk_sint16 (c->pq[c->ea.cnt + 1]);
2033 s3 = e86_get_cf (c);
2034
2035 d = s1 + s2 + s3;
2036
2037 e86_set_ea16 (c, d);
2038 e86_set_flg_adc_16 (c, s1, s2, s3);
2039 e86_set_clk_ea (c, 4, 17);
2040
2041 return (2 + c->ea.cnt);
2042}
2043
2044/* OP 83 03: SBB r/m16, imm8 */
2045static
2046unsigned op_83_03 (e8086_t *c)
2047{
2048 unsigned long s1, s2, s3, d;
2049
2050 e86_get_ea_ptr (c, c->pq + 1);
2051
2052 s1 = e86_get_ea16 (c);
2053 s2 = e86_mk_sint16 (c->pq[c->ea.cnt + 1]);
2054 s3 = e86_get_cf (c);
2055
2056 d = s1 - s2 - s3;
2057
2058 e86_set_ea16 (c, d);
2059 e86_set_flg_sbb_16 (c, s1, s2, s3);
2060 e86_set_clk_ea (c, 4, 17);
2061
2062 return (2 + c->ea.cnt);
2063}
2064
2065/* OP 83 04: AND r/m16, imm8 */
2066static
2067unsigned op_83_04 (e8086_t *c)
2068{
2069 unsigned long s1, s2, d;
2070
2071 e86_get_ea_ptr (c, c->pq + 1);
2072
2073 s1 = e86_get_ea16 (c);
2074 s2 = e86_mk_sint16 (c->pq[c->ea.cnt + 1]);
2075
2076 d = s1 & s2;
2077
2078 e86_set_ea16 (c, d);
2079 e86_set_flg_log_16 (c, d);
2080 e86_set_clk_ea (c, 4, 17);
2081
2082 return (2 + c->ea.cnt);
2083}
2084
2085/* OP 83 05: SUB r/m16, imm8 */
2086static
2087unsigned op_83_05 (e8086_t *c)
2088{
2089 unsigned long s1, s2, d;
2090
2091 e86_get_ea_ptr (c, c->pq + 1);
2092
2093 s1 = e86_get_ea16 (c);
2094 s2 = e86_mk_sint16 (c->pq[c->ea.cnt + 1]);
2095
2096 d = s1 - s2;
2097
2098 e86_set_ea16 (c, d);
2099 e86_set_flg_sub_16 (c, s1, s2);
2100 e86_set_clk_ea (c, 4, 17);
2101
2102 return (2 + c->ea.cnt);
2103}
2104
2105/* OP 83 06: XOR r/m16, imm8 */
2106static
2107unsigned op_83_06 (e8086_t *c)
2108{
2109 unsigned long s1, s2, d;
2110
2111 e86_get_ea_ptr (c, c->pq + 1);
2112
2113 s1 = e86_get_ea16 (c);
2114 s2 = e86_mk_sint16 (c->pq[c->ea.cnt + 1]);
2115
2116 d = s1 ^ s2;
2117
2118 e86_set_ea16 (c, d);
2119 e86_set_flg_log_16 (c, d);
2120 e86_set_clk_ea (c, 4, 17);
2121
2122 return (2 + c->ea.cnt);
2123}
2124
2125/* OP 83 07: CMP r/m16, imm8 */
2126static
2127unsigned op_83_07 (e8086_t *c)
2128{
2129 unsigned long s1, s2;
2130
2131 e86_get_ea_ptr (c, c->pq + 1);
2132
2133 s1 = e86_get_ea16 (c);
2134 s2 = e86_mk_sint16 (c->pq[c->ea.cnt + 1]);
2135
2136 e86_set_flg_sub_16 (c, s1, s2);
2137 e86_set_clk_ea (c, 4, 10);
2138
2139 return (2 + c->ea.cnt);
2140}
2141
2142static
2143e86_opcode_f e86_opcodes_83[8] = {
2144 &op_83_00, &op_83_01, &op_83_02, &op_83_03,
2145 &op_83_04, &op_83_05, &op_83_06, &op_83_07,
2146};
2147
2148/* OP 83: xxx r/m16, imm8 */
2149static
2150unsigned op_83 (e8086_t *c)
2151{
2152 unsigned xop;
2153
2154 xop = (c->pq[1] >> 3) & 7;
2155
2156 return (e86_opcodes_83[xop] (c));
2157}
2158
2159/* OP 84: TEST r/m8, reg8 */
2160static
2161unsigned op_84 (e8086_t *c)
2162{
2163 unsigned short s1, s2;
2164
2165 e86_get_ea_ptr (c, c->pq + 1);
2166
2167 s1 = e86_get_ea8 (c);
2168 s2 = e86_get_reg8 (c, (c->pq[1] >> 3) & 7);
2169
2170 e86_set_flg_log_8 (c, s1 & s2);
2171 e86_set_clk_ea (c, 3, 9);
2172
2173 return (c->ea.cnt + 1);
2174}
2175
2176/* OP 85: TEST r/m16, reg16 */
2177static
2178unsigned op_85 (e8086_t *c)
2179{
2180 unsigned long s1, s2;
2181
2182 e86_get_ea_ptr (c, c->pq + 1);
2183
2184 s1 = e86_get_ea16 (c);
2185 s2 = e86_get_reg16 (c, (c->pq[1] >> 3) & 7);
2186
2187 e86_set_flg_log_16 (c, s1 & s2);
2188 e86_set_clk_ea (c, 3, 9);
2189
2190 return (c->ea.cnt + 1);
2191}
2192
2193/* OP 86: XCHG r/m8, reg8 */
2194static
2195unsigned op_86 (e8086_t *c)
2196{
2197 unsigned reg;
2198 unsigned short s1, s2;
2199
2200 reg = (c->pq[1] >> 3) & 7;
2201
2202 e86_get_ea_ptr (c, c->pq + 1);
2203
2204 s1 = e86_get_ea8 (c);
2205 s2 = e86_get_reg8 (c, reg);
2206
2207 e86_set_ea8 (c, s2);
2208 e86_set_reg8 (c, reg, s1);
2209 e86_set_clk_ea (c, 4, 17);
2210
2211 return (c->ea.cnt + 1);
2212}
2213
2214/* OP 87: XCHG r/m16, reg16 */
2215static
2216unsigned op_87 (e8086_t *c)
2217{
2218 unsigned reg;
2219 unsigned long s1, s2;
2220
2221 reg = (c->pq[1] >> 3) & 7;
2222
2223 e86_get_ea_ptr (c, c->pq + 1);
2224
2225 s1 = e86_get_ea16 (c);
2226 s2 = e86_get_reg16 (c, reg);
2227
2228 e86_set_ea16 (c, s2);
2229 e86_set_reg16 (c, reg, s1);
2230 e86_set_clk_ea (c, 4, 17);
2231
2232 return (c->ea.cnt + 1);
2233}
2234
2235/* OP 88: MOV r/m8, reg8 */
2236static
2237unsigned op_88 (e8086_t *c)
2238{
2239 unsigned char val;
2240 unsigned reg;
2241
2242 e86_get_ea_ptr (c, c->pq + 1);
2243
2244 reg = (c->pq[1] >> 3) & 7;
2245 val = e86_get_reg8 (c, reg);
2246
2247 e86_set_ea8 (c, val);
2248 e86_set_clk_ea (c, 2, 9);
2249
2250 return (c->ea.cnt + 1);
2251}
2252
2253/* OP 89: MOV r/m16, reg16 */
2254static
2255unsigned op_89 (e8086_t *c)
2256{
2257 unsigned short val;
2258 unsigned reg;
2259
2260 e86_get_ea_ptr (c, c->pq + 1);
2261
2262 reg = (c->pq[1] >> 3) & 7;
2263 val = e86_get_reg16 (c, reg);
2264
2265 e86_set_ea16 (c, val);
2266 e86_set_clk_ea (c, 2, 9);
2267
2268 return (c->ea.cnt + 1);
2269}
2270
2271/* OP 8A: MOV reg8, r/m8 */
2272static
2273unsigned op_8a (e8086_t *c)
2274{
2275 unsigned char val;
2276 unsigned reg;
2277
2278 e86_get_ea_ptr (c, c->pq + 1);
2279
2280 reg = (c->pq[1] >> 3) & 7;
2281 val = e86_get_ea8 (c);
2282
2283 e86_set_reg8 (c, reg, val);
2284 e86_set_clk_ea (c, 2, 8);
2285
2286 return (c->ea.cnt + 1);
2287}
2288
2289/* OP 8B: MOV reg16, r/m16 */
2290static
2291unsigned op_8b (e8086_t *c)
2292{
2293 unsigned short val;
2294 unsigned reg;
2295
2296 e86_get_ea_ptr (c, c->pq + 1);
2297
2298 reg = (c->pq[1] >> 3) & 7;
2299 val = e86_get_ea16 (c);
2300
2301 e86_set_reg16 (c, reg, val);
2302 e86_set_clk_ea (c, 2, 8);
2303
2304 return (c->ea.cnt + 1);
2305}
2306
2307/* OP 8C: MOV r/m16, sreg */
2308static
2309unsigned op_8c (e8086_t *c)
2310{
2311 e86_get_ea_ptr (c, c->pq + 1);
2312 e86_set_ea16 (c, c->sreg[(c->pq[1] >> 3) & 3]);
2313 e86_set_clk_ea (c, 2, 9);
2314
2315 return (c->ea.cnt + 1);
2316}
2317
2318/* OP 8D: LEA reg16, r/m16 */
2319static
2320unsigned op_8d (e8086_t *c)
2321{
2322 e86_get_ea_ptr (c, c->pq + 1);
2323
2324 if (c->ea.is_mem) {
2325 e86_set_reg16 (c, (c->pq[1] >> 3) & 7, c->ea.ofs);
2326 e86_set_clk (c, 2);
2327 }
2328 else {
2329 if (e86_undefined (c) == 0) {
2330 return (0);
2331 }
2332 }
2333
2334 return (c->ea.cnt + 1);
2335}
2336
2337/* OP 8E: MOV sreg, r/m16 */
2338static
2339unsigned op_8e (e8086_t *c)
2340{
2341 unsigned reg;
2342
2343 reg = (c->pq[1] >> 3) & 3;
2344
2345 e86_get_ea_ptr (c, c->pq + 1);
2346 e86_set_sreg (c, reg, e86_get_ea16 (c));
2347 e86_set_clk_ea (c, 2, 8);
2348
2349 if (reg == E86_REG_CS) {
2350 e86_pq_init (c);
2351 }
2352 else if (reg == E86_REG_SS) {
2353 c->save_flags &= ~E86_FLG_I;
2354 }
2355
2356 return (c->ea.cnt + 1);
2357}
2358
2359/* OP 8F: POP r/m16 */
2360static
2361unsigned op_8f (e8086_t *c)
2362{
2363 e86_get_ea_ptr (c, c->pq + 1);
2364 e86_set_ea16 (c, e86_pop (c));
2365 e86_set_clk_ea (c, 8, 17);
2366
2367 return (c->ea.cnt + 1);
2368}
2369
2370/* OP 9x: XCHG AX, reg16 */
2371static
2372unsigned op_90 (e8086_t *c)
2373{
2374 unsigned reg;
2375 unsigned short val;
2376
2377 reg = c->pq[0] & 7;
2378
2379 val = e86_get_ax (c);
2380 e86_set_ax (c, e86_get_reg16 (c, reg));
2381 e86_set_reg16 (c, reg, val);
2382 e86_set_clk (c, 3);
2383
2384 return (1);
2385}
2386
2387/* OP 98: CBW */
2388static
2389unsigned op_98 (e8086_t *c)
2390{
2391 e86_set_ax (c, e86_mk_sint16 (e86_get_al (c)));
2392 e86_set_clk (c, 2);
2393
2394 return (1);
2395}
2396
2397/* OP 99: CWD */
2398static
2399unsigned op_99 (e8086_t *c)
2400{
2401 e86_set_dx (c, (e86_get_ax (c) & 0x8000) ? 0xffff : 0x0000);
2402 e86_set_clk (c, 5);
2403
2404 return (1);
2405}
2406
2407/* OP 9A: CALL seg:ofs */
2408static
2409unsigned op_9a (e8086_t *c)
2410{
2411 e86_push (c, e86_get_cs (c));
2412 e86_push (c, e86_get_ip (c) + 5);
2413
2414 e86_set_ip (c, e86_mk_uint16 (c->pq[1], c->pq[2]));
2415 e86_set_cs (c, e86_mk_uint16 (c->pq[3], c->pq[4]));
2416
2417 e86_pq_init (c);
2418
2419 e86_set_clk (c, 28);
2420
2421 return (0);
2422}
2423
2424/* OP 9B: WAIT */
2425static
2426unsigned op_9b (e8086_t *c)
2427{
2428 e86_set_clk (c, 4);
2429
2430 return (1);
2431}
2432
2433/* OP 9C: PUSHF */
2434static
2435unsigned op_9c (e8086_t *c)
2436{
2437 if (c->cpu & E86_CPU_FLAGS286) {
2438 e86_push (c, c->flg & 0x0fd5);
2439 }
2440 else {
2441 e86_push (c, (c->flg & 0x0fd5) | 0xf002);
2442 }
2443
2444 e86_set_clk (c, 10);
2445
2446 return (1);
2447}
2448
2449/* OP 9D: POPF */
2450static
2451unsigned op_9d (e8086_t *c)
2452{
2453 c->flg = (e86_pop (c) & 0x0fd5) | 0xf002;
2454 e86_set_clk (c, 8);
2455
2456 return (1);
2457}
2458
2459/* OP 9E: SAHF */
2460static
2461unsigned op_9e (e8086_t *c)
2462{
2463 c->flg &= 0xff00;
2464 c->flg |= e86_get_ah (c) & 0xd5;
2465 c->flg |= 0x02;
2466
2467 e86_set_clk (c, 4);
2468
2469 return (1);
2470}
2471
2472/* OP 9F: LAHF */
2473static
2474unsigned op_9f (e8086_t *c)
2475{
2476 e86_set_ah (c, (c->flg & 0xd5) | 0x02);
2477 e86_set_clk (c, 4);
2478
2479 return (1);
2480}
2481
2482/* OP A0: MOV AL, [data16] */
2483static
2484unsigned op_a0 (e8086_t *c)
2485{
2486 unsigned short seg, ofs;
2487 unsigned char val;
2488
2489 seg = e86_get_seg (c, E86_REG_DS);
2490 ofs = e86_mk_uint16 (c->pq[1], c->pq[2]);
2491 val = e86_get_mem8 (c, seg, ofs);
2492
2493 e86_set_al (c, val);
2494 e86_set_clk (c, 10);
2495
2496 return (3);
2497}
2498
2499/* OP A1: MOV AX, [data16] */
2500static
2501unsigned op_a1 (e8086_t *c)
2502{
2503 unsigned short seg, ofs;
2504
2505 seg = e86_get_seg (c, E86_REG_DS);
2506 ofs = e86_mk_uint16 (c->pq[1], c->pq[2]);
2507
2508 e86_set_ax (c, e86_get_mem16 (c, seg, ofs));
2509 e86_set_clk (c, 10);
2510
2511 return (3);
2512}
2513
2514/* OP A2: MOV [data16], AL */
2515static
2516unsigned op_a2 (e8086_t *c)
2517{
2518 unsigned short seg, ofs;
2519
2520 seg = e86_get_seg (c, E86_REG_DS);
2521 ofs = e86_mk_uint16 (c->pq[1], c->pq[2]);
2522
2523 e86_set_mem8 (c, seg, ofs, c->dreg[E86_REG_AX] & 0xff);
2524 e86_set_clk (c, 10);
2525
2526 return (3);
2527}
2528
2529/* OP A3: MOV [data16], AX */
2530static
2531unsigned op_a3 (e8086_t *c)
2532{
2533 unsigned short seg, ofs;
2534
2535 seg = e86_get_seg (c, E86_REG_DS);
2536 ofs = e86_mk_uint16 (c->pq[1], c->pq[2]);
2537
2538 e86_set_mem16 (c, seg, ofs, c->dreg[E86_REG_AX]);
2539 e86_set_clk (c, 10);
2540
2541 return (3);
2542}
2543
2544/* OP A4: MOVSB */
2545static
2546unsigned op_a4 (e8086_t *c)
2547{
2548 unsigned char val;
2549 unsigned short seg1, seg2;
2550 unsigned short inc;
2551
2552 seg1 = e86_get_seg (c, E86_REG_DS);
2553 seg2 = e86_get_es (c);
2554 inc = e86_get_df (c) ? 0xffff : 0x0001;
2555
2556 if (c->prefix & (E86_PREFIX_REP | E86_PREFIX_REPN)) {
2557 if (e86_get_cx (c) != 0) {
2558 val = e86_get_mem8 (c, seg1, e86_get_si (c));
2559 e86_set_mem8 (c, seg2, e86_get_di (c), val);
2560
2561 e86_set_si (c, e86_get_si (c) + inc);
2562 e86_set_di (c, e86_get_di (c) + inc);
2563 e86_set_cx (c, e86_get_cx (c) - 1);
2564 }
2565
2566 e86_set_clk (c, 18);
2567
2568 if (e86_get_cx (c) == 0) {
2569 c->prefix &= ~E86_PREFIX_KEEP;
2570 return (1);
2571 }
2572
2573 c->prefix |= E86_PREFIX_KEEP;
2574
2575 return (0);
2576 }
2577 else {
2578 val = e86_get_mem8 (c, seg1, e86_get_si (c));
2579 e86_set_mem8 (c, seg2, e86_get_di (c), val);
2580
2581 e86_set_si (c, e86_get_si (c) + inc);
2582 e86_set_di (c, e86_get_di (c) + inc);
2583
2584 e86_set_clk (c, 18);
2585 }
2586
2587 return (1);
2588}
2589
2590/* OP A5: MOVSW */
2591static
2592unsigned op_a5 (e8086_t *c)
2593{
2594 unsigned short val;
2595 unsigned short seg1, seg2;
2596 unsigned short inc;
2597
2598 seg1 = e86_get_seg (c, E86_REG_DS);
2599 seg2 = e86_get_es (c);
2600 inc = e86_get_df (c) ? 0xfffe : 0x0002;
2601
2602 if (c->prefix & (E86_PREFIX_REP | E86_PREFIX_REPN)) {
2603 if (e86_get_cx (c) != 0) {
2604 val = e86_get_mem16 (c, seg1, e86_get_si (c));
2605 e86_set_mem16 (c, seg2, e86_get_di (c), val);
2606
2607 e86_set_si (c, e86_get_si (c) + inc);
2608 e86_set_di (c, e86_get_di (c) + inc);
2609 e86_set_cx (c, e86_get_cx (c) - 1);
2610 }
2611
2612 e86_set_clk (c, 18);
2613
2614 if (e86_get_cx (c) == 0) {
2615 c->prefix &= ~E86_PREFIX_KEEP;
2616 return (1);
2617 }
2618
2619 c->prefix |= E86_PREFIX_KEEP;
2620
2621 return (0);
2622 }
2623 else {
2624 val = e86_get_mem16 (c, seg1, e86_get_si (c));
2625 e86_set_mem16 (c, seg2, e86_get_di (c), val);
2626
2627 e86_set_si (c, e86_get_si (c) + inc);
2628 e86_set_di (c, e86_get_di (c) + inc);
2629
2630 e86_set_clk (c, 18);
2631 }
2632
2633 return (1);
2634}
2635
2636/* Opcode A6: CMPSB */
2637static
2638unsigned op_a6 (e8086_t *c)
2639{
2640 unsigned short s1, s2;
2641 unsigned short seg1, seg2;
2642 unsigned short inc;
2643 int z;
2644
2645 seg1 = e86_get_seg (c, E86_REG_DS);
2646 seg2 = e86_get_es (c);
2647
2648 inc = e86_get_df (c) ? 0xffff : 0x0001;
2649
2650 if (c->prefix & (E86_PREFIX_REP | E86_PREFIX_REPN)) {
2651 if (e86_get_cx (c) != 0) {
2652 s1 = e86_get_mem8 (c, seg1, e86_get_si (c));
2653 s2 = e86_get_mem8 (c, seg2, e86_get_di (c));
2654
2655 e86_set_si (c, e86_get_si (c) + inc);
2656 e86_set_di (c, e86_get_di (c) + inc);
2657 e86_set_cx (c, e86_get_cx (c) - 1);
2658
2659 e86_set_flg_sub_8 (c, s1, s2);
2660 }
2661
2662 e86_set_clk (c, 22);
2663
2664 z = (c->prefix & E86_PREFIX_REP) ? 1 : 0;
2665
2666 if ((e86_get_cx (c) == 0) || (e86_get_zf (c) != z)) {
2667 c->prefix &= ~E86_PREFIX_KEEP;
2668 return (1);
2669 }
2670
2671 c->prefix |= E86_PREFIX_KEEP;
2672
2673 return (0);
2674 }
2675 else {
2676 s1 = e86_get_mem8 (c, seg1, e86_get_si (c));
2677 s2 = e86_get_mem8 (c, seg2, e86_get_di (c));
2678
2679 e86_set_si (c, e86_get_si (c) + inc);
2680 e86_set_di (c, e86_get_di (c) + inc);
2681
2682 e86_set_flg_sub_8 (c, s1, s2);
2683
2684 e86_set_clk (c, 22);
2685 }
2686
2687 return (1);
2688}
2689
2690/* Opcode A7: CMPSW */
2691static
2692unsigned op_a7 (e8086_t *c)
2693{
2694 unsigned long s1, s2;
2695 unsigned short seg1, seg2;
2696 unsigned short inc;
2697 int z;
2698
2699 seg1 = e86_get_seg (c, E86_REG_DS);
2700 seg2 = e86_get_es (c);
2701
2702 inc = e86_get_df (c) ? 0xfffe : 0x0002;
2703
2704 if (c->prefix & (E86_PREFIX_REP | E86_PREFIX_REPN)) {
2705 if (e86_get_cx (c) != 0) {
2706 s1 = e86_get_mem16 (c, seg1, e86_get_si (c));
2707 s2 = e86_get_mem16 (c, seg2, e86_get_di (c));
2708
2709 e86_set_si (c, e86_get_si (c) + inc);
2710 e86_set_di (c, e86_get_di (c) + inc);
2711 e86_set_cx (c, e86_get_cx (c) - 1);
2712
2713 e86_set_flg_sub_16 (c, s1, s2);
2714 }
2715
2716 e86_set_clk (c, 22);
2717
2718 z = (c->prefix & E86_PREFIX_REP) ? 1 : 0;
2719
2720 if ((e86_get_cx (c) == 0) || (e86_get_zf (c) != z)) {
2721 c->prefix &= ~E86_PREFIX_KEEP;
2722 return (1);
2723 }
2724
2725 c->prefix |= E86_PREFIX_KEEP;
2726
2727 return (0);
2728 }
2729 else {
2730 s1 = e86_get_mem16 (c, seg1, e86_get_si (c));
2731 s2 = e86_get_mem16 (c, seg2, e86_get_di (c));
2732
2733 e86_set_si (c, e86_get_si (c) + inc);
2734 e86_set_di (c, e86_get_di (c) + inc);
2735
2736 e86_set_flg_sub_16 (c, s1, s2);
2737
2738 e86_set_clk (c, 22);
2739 }
2740
2741 return (1);
2742}
2743
2744/* Opcode A8: TEST AL, data8 */
2745static
2746unsigned op_a8 (e8086_t *c)
2747{
2748 unsigned short s1, s2;
2749
2750 s1 = e86_get_al (c);
2751 s2 = c->pq[1];
2752
2753 e86_set_flg_log_8 (c, s1 & s2);
2754 e86_set_clk (c, 4);
2755
2756 return (2);
2757}
2758
2759/* Opcode A9: TEST AX, data16 */
2760static
2761unsigned op_a9 (e8086_t *c)
2762{
2763 unsigned long s1, s2;
2764
2765 s1 = e86_get_ax (c);
2766 s2 = e86_mk_uint16 (c->pq[1], c->pq[2]);
2767
2768 e86_set_flg_log_16 (c, s1 & s2);
2769 e86_set_clk (c, 4);
2770
2771 return (3);
2772}
2773
2774/* Opcode AA: STOSB */
2775static
2776unsigned op_aa (e8086_t *c)
2777{
2778 unsigned short seg;
2779 unsigned short inc;
2780
2781 seg = e86_get_es (c);
2782 inc = e86_get_df (c) ? 0xffff : 0x0001;
2783
2784 if (c->prefix & (E86_PREFIX_REP | E86_PREFIX_REPN)) {
2785 if (e86_get_cx (c) != 0) {
2786 e86_set_mem8 (c, seg, e86_get_di (c), e86_get_al (c));
2787
2788 e86_set_di (c, e86_get_di (c) + inc);
2789 e86_set_cx (c, e86_get_cx (c) - 1);
2790 }
2791
2792 e86_set_clk (c, 11);
2793
2794 if (e86_get_cx (c) == 0) {
2795 c->prefix &= ~E86_PREFIX_KEEP;
2796 return (1);
2797 }
2798
2799 c->prefix |= E86_PREFIX_KEEP;
2800
2801 return (0);
2802 }
2803 else {
2804 e86_set_mem8 (c, seg, e86_get_di (c), e86_get_al (c));
2805 e86_set_di (c, e86_get_di (c) + inc);
2806
2807 e86_set_clk (c, 11);
2808 }
2809
2810 return (1);
2811}
2812
2813/* Opcode AB: STOSW */
2814static
2815unsigned op_ab (e8086_t *c)
2816{
2817 unsigned short seg;
2818 unsigned short inc;
2819
2820 seg = e86_get_es (c);
2821 inc = e86_get_df (c) ? 0xfffe : 0x0002;
2822
2823 if (c->prefix & (E86_PREFIX_REP | E86_PREFIX_REPN)) {
2824 if (e86_get_cx (c) != 0) {
2825 e86_set_mem16 (c, seg, e86_get_di (c), e86_get_ax (c));
2826
2827 e86_set_di (c, e86_get_di (c) + inc);
2828 e86_set_cx (c, e86_get_cx (c) - 1);
2829 }
2830
2831 e86_set_clk (c, 11);
2832
2833 if (e86_get_cx (c) == 0) {
2834 c->prefix &= ~E86_PREFIX_KEEP;
2835 return (1);
2836 }
2837
2838 c->prefix |= E86_PREFIX_KEEP;
2839
2840 return (0);
2841 }
2842 else {
2843 e86_set_mem16 (c, seg, e86_get_di (c), e86_get_ax (c));
2844 e86_set_di (c, e86_get_di (c) + inc);
2845
2846 e86_set_clk (c, 11);
2847 }
2848
2849 return (1);
2850}
2851
2852/* Opcode AC: LODSB */
2853static
2854unsigned op_ac (e8086_t *c)
2855{
2856 unsigned short seg;
2857 unsigned short inc;
2858
2859 seg = e86_get_seg (c, E86_REG_DS);
2860 inc = e86_get_df (c) ? 0xffff : 0x0001;
2861
2862 if (c->prefix & (E86_PREFIX_REP | E86_PREFIX_REPN)) {
2863 if (e86_get_cx (c) != 0) {
2864 e86_set_al (c, e86_get_mem8 (c, seg, e86_get_si (c)));
2865 e86_set_si (c, e86_get_si (c) + inc);
2866 e86_set_cx (c, e86_get_cx (c) - 1);
2867 }
2868
2869 e86_set_clk (c, 12);
2870
2871 if (e86_get_cx (c) == 0) {
2872 c->prefix &= ~E86_PREFIX_KEEP;
2873 return (1);
2874 }
2875
2876 c->prefix |= E86_PREFIX_KEEP;
2877
2878 return (0);
2879 }
2880 else {
2881 e86_set_al (c, e86_get_mem8 (c, seg, e86_get_si (c)));
2882 e86_set_si (c, e86_get_si (c) + inc);
2883 e86_set_clk (c, 12);
2884 }
2885
2886 return (1);
2887}
2888
2889/* Opcode AD: LODSW */
2890static
2891unsigned op_ad (e8086_t *c)
2892{
2893 unsigned short seg;
2894 unsigned short inc;
2895
2896 seg = e86_get_seg (c, E86_REG_DS);
2897 inc = e86_get_df (c) ? 0xfffe : 0x0002;
2898
2899 if (c->prefix & (E86_PREFIX_REP | E86_PREFIX_REPN)) {
2900 if (e86_get_cx (c) != 0) {
2901 e86_set_ax (c, e86_get_mem16 (c, seg, e86_get_si (c)));
2902 e86_set_si (c, e86_get_si (c) + inc);
2903 e86_set_cx (c, e86_get_cx (c) - 1);
2904 }
2905
2906 e86_set_clk (c, 12);
2907
2908 if (e86_get_cx (c) == 0) {
2909 c->prefix &= ~E86_PREFIX_KEEP;
2910 return (1);
2911 }
2912
2913 c->prefix |= E86_PREFIX_KEEP;
2914
2915 return (0);
2916 }
2917 else {
2918 e86_set_ax (c, e86_get_mem16 (c, seg, e86_get_si (c)));
2919 e86_set_si (c, e86_get_si (c) + inc);
2920 e86_set_clk (c, 12);
2921 }
2922
2923 return (1);
2924}
2925
2926/* Opcode AE: SCASB */
2927static
2928unsigned op_ae (e8086_t *c)
2929{
2930 unsigned short s1, s2;
2931 unsigned short seg;
2932 unsigned short inc;
2933 int z;
2934
2935 seg = e86_get_es (c);
2936 inc = e86_get_df (c) ? 0xffff : 0x0001;
2937
2938 if (c->prefix & (E86_PREFIX_REP | E86_PREFIX_REPN)) {
2939 if (e86_get_cx (c) != 0) {
2940 s1 = e86_get_al (c);
2941 s2 = e86_get_mem8 (c, seg, e86_get_di (c));
2942
2943 e86_set_di (c, e86_get_di (c) + inc);
2944 e86_set_cx (c, e86_get_cx (c) - 1);
2945
2946 e86_set_flg_sub_8 (c, s1, s2);
2947 }
2948
2949 e86_set_clk (c, 15);
2950
2951 z = (c->prefix & E86_PREFIX_REP) ? 1 : 0;
2952
2953 if ((e86_get_cx (c) == 0) || (e86_get_zf (c) != z)) {
2954 c->prefix &= ~E86_PREFIX_KEEP;
2955 return (1);
2956 }
2957
2958 c->prefix |= E86_PREFIX_KEEP;
2959
2960 return (0);
2961 }
2962 else {
2963 s1 = e86_get_al (c);
2964 s2 = e86_get_mem8 (c, seg, e86_get_di (c));
2965
2966 e86_set_di (c, e86_get_di (c) + inc);
2967
2968 e86_set_flg_sub_8 (c, s1, s2);
2969 e86_set_clk (c, 15);
2970 }
2971
2972 return (1);
2973}
2974
2975/* Opcode AF: SCASW */
2976static
2977unsigned op_af (e8086_t *c)
2978{
2979 unsigned long s1, s2;
2980 unsigned short seg;
2981 unsigned short inc;
2982 int z;
2983
2984 seg = e86_get_es (c);
2985 inc = e86_get_df (c) ? 0xfffe : 0x0002;
2986
2987 if (c->prefix & (E86_PREFIX_REP | E86_PREFIX_REPN)) {
2988 if (e86_get_cx (c) != 0) {
2989 s1 = e86_get_ax (c);
2990 s2 = e86_get_mem16 (c, seg, e86_get_di (c));
2991
2992 e86_set_di (c, e86_get_di (c) + inc);
2993 e86_set_cx (c, e86_get_cx (c) - 1);
2994
2995 e86_set_flg_sub_16 (c, s1, s2);
2996 }
2997
2998 e86_set_clk (c, 15);
2999
3000 z = (c->prefix & E86_PREFIX_REP) ? 1 : 0;
3001
3002 if ((e86_get_cx (c) == 0) || (e86_get_zf (c) != z)) {
3003 c->prefix &= ~E86_PREFIX_KEEP;
3004 return (1);
3005 }
3006
3007 c->prefix |= E86_PREFIX_KEEP;
3008
3009 return (0);
3010 }
3011 else {
3012 s1 = e86_get_ax (c);
3013 s2 = e86_get_mem16 (c, seg, e86_get_di (c));
3014
3015 e86_set_di (c, e86_get_di (c) + inc);
3016
3017 e86_set_flg_sub_16 (c, s1, s2);
3018 e86_set_clk (c, 15);
3019 }
3020
3021 return (1);
3022}
3023
3024/* OP B0: MOV AL, imm8 */
3025static
3026unsigned op_b0 (e8086_t *c)
3027{
3028 e86_set_al (c, c->pq[1]);
3029 e86_set_clk (c, 4);
3030
3031 return (2);
3032}
3033
3034/* OP B1: MOV CL, imm8 */
3035static
3036unsigned op_b1 (e8086_t *c)
3037{
3038 e86_set_cl (c, c->pq[1]);
3039 e86_set_clk (c, 4);
3040
3041 return (2);
3042}
3043
3044/* OP B2: MOV DL, imm8 */
3045static
3046unsigned op_b2 (e8086_t *c)
3047{
3048 e86_set_dl (c, c->pq[1]);
3049 e86_set_clk (c, 4);
3050
3051 return (2);
3052}
3053
3054/* OP B3: MOV BL, imm8 */
3055static
3056unsigned op_b3 (e8086_t *c)
3057{
3058 e86_set_bl (c, c->pq[1]);
3059 e86_set_clk (c, 4);
3060
3061 return (2);
3062}
3063
3064/* OP B4: MOV AH, imm8 */
3065static
3066unsigned op_b4 (e8086_t *c)
3067{
3068 e86_set_ah (c, c->pq[1]);
3069 e86_set_clk (c, 4);
3070
3071 return (2);
3072}
3073
3074/* OP B5: MOV CH, imm8 */
3075static
3076unsigned op_b5 (e8086_t *c)
3077{
3078 e86_set_ch (c, c->pq[1]);
3079 e86_set_clk (c, 4);
3080
3081 return (2);
3082}
3083
3084/* OP B6: MOV DH, imm8 */
3085static
3086unsigned op_b6 (e8086_t *c)
3087{
3088 e86_set_dh (c, c->pq[1]);
3089 e86_set_clk (c, 4);
3090
3091 return (2);
3092}
3093
3094/* OP B7: MOV BH, imm8 */
3095static
3096unsigned op_b7 (e8086_t *c)
3097{
3098 e86_set_bh (c, c->pq[1]);
3099 e86_set_clk (c, 4);
3100
3101 return (2);
3102}
3103
3104/* OP B8: MOV AX, imm16 */
3105static
3106unsigned op_b8 (e8086_t *c)
3107{
3108 e86_set_ax (c, e86_mk_uint16 (c->pq[1], c->pq[2]));
3109 e86_set_clk (c, 4);
3110
3111 return (3);
3112}
3113
3114/* OP B9: MOV CX, imm16 */
3115static
3116unsigned op_b9 (e8086_t *c)
3117{
3118 e86_set_cx (c, e86_mk_uint16 (c->pq[1], c->pq[2]));
3119 e86_set_clk (c, 4);
3120
3121 return (3);
3122}
3123
3124/* OP BA: MOV DX, imm16 */
3125static
3126unsigned op_ba (e8086_t *c)
3127{
3128 e86_set_dx (c, e86_mk_uint16 (c->pq[1], c->pq[2]));
3129 e86_set_clk (c, 4);
3130
3131 return (3);
3132}
3133
3134/* OP BB: MOV BX, imm16 */
3135static
3136unsigned op_bb (e8086_t *c)
3137{
3138 e86_set_bx (c, e86_mk_uint16 (c->pq[1], c->pq[2]));
3139 e86_set_clk (c, 4);
3140
3141 return (3);
3142}
3143
3144/* OP BC: MOV SP, imm16 */
3145static
3146unsigned op_bc (e8086_t *c)
3147{
3148 e86_set_sp (c, e86_mk_uint16 (c->pq[1], c->pq[2]));
3149 e86_set_clk (c, 4);
3150
3151 return (3);
3152}
3153
3154/* OP BD: MOV BP, imm16 */
3155static
3156unsigned op_bd (e8086_t *c)
3157{
3158 e86_set_bp (c, e86_mk_uint16 (c->pq[1], c->pq[2]));
3159 e86_set_clk (c, 4);
3160
3161 return (3);
3162}
3163
3164/* OP BE: MOV SI, imm16 */
3165static
3166unsigned op_be (e8086_t *c)
3167{
3168 e86_set_si (c, e86_mk_uint16 (c->pq[1], c->pq[2]));
3169 e86_set_clk (c, 4);
3170
3171 return (3);
3172}
3173
3174/* OP BF: MOV DI, imm16 */
3175static
3176unsigned op_bf (e8086_t *c)
3177{
3178 e86_set_di (c, e86_mk_uint16 (c->pq[1], c->pq[2]));
3179 e86_set_clk (c, 4);
3180
3181 return (3);
3182}
3183
3184/* OP C2: RET imm16 */
3185static
3186unsigned op_c2 (e8086_t *c)
3187{
3188 e86_set_ip (c, e86_pop (c));
3189 e86_set_sp (c, e86_get_sp (c) + e86_mk_uint16 (c->pq[1], c->pq[2]));
3190 e86_pq_init (c);
3191 e86_set_clk (c, 20);
3192
3193 return (0);
3194}
3195
3196/* OP C3: RET */
3197static
3198unsigned op_c3 (e8086_t *c)
3199{
3200 e86_set_ip (c, e86_pop (c));
3201 e86_pq_init (c);
3202 e86_set_clk (c, 16);
3203
3204 return (0);
3205}
3206
3207/* OP C4: LES reg16, r/m16 */
3208static
3209unsigned op_c4 (e8086_t *c)
3210{
3211 unsigned short val1, val2;
3212
3213 e86_get_ea_ptr (c, c->pq + 1);
3214
3215 if (c->ea.is_mem) {
3216 val1 = e86_get_mem16 (c, c->ea.seg, c->ea.ofs);
3217 val2 = e86_get_mem16 (c, c->ea.seg, c->ea.ofs + 2);
3218
3219 e86_set_reg16 (c, (c->pq[1] >> 3) & 7, val1);
3220 e86_set_es (c, val2);
3221
3222 e86_set_clk (c, 16);
3223 }
3224
3225 return (c->ea.cnt + 1);
3226}
3227
3228/* OP C5: LDS reg16, r/m16 */
3229static
3230unsigned op_c5 (e8086_t *c)
3231{
3232 unsigned short val1, val2;
3233
3234 e86_get_ea_ptr (c, c->pq + 1);
3235
3236 if (c->ea.is_mem) {
3237 val1 = e86_get_mem16 (c, c->ea.seg, c->ea.ofs);
3238 val2 = e86_get_mem16 (c, c->ea.seg, c->ea.ofs + 2);
3239
3240 e86_set_reg16 (c, (c->pq[1] >> 3) & 7, val1);
3241 e86_set_ds (c, val2);
3242
3243 e86_set_clk (c, 16);
3244 }
3245
3246 return (c->ea.cnt + 1);
3247}
3248
3249/* OP C6: MOV r/m8, data8 */
3250static
3251unsigned op_c6 (e8086_t *c)
3252{
3253 e86_get_ea_ptr (c, c->pq + 1);
3254 e86_set_ea8 (c, c->pq[c->ea.cnt + 1]);
3255 e86_set_clk_ea (c, 4, 10);
3256
3257 return (c->ea.cnt + 2);
3258}
3259
3260/* OP C7: MOV r/m16, data16 */
3261static
3262unsigned op_c7 (e8086_t *c)
3263{
3264 e86_get_ea_ptr (c, c->pq + 1);
3265 e86_set_ea16 (c, e86_mk_uint16 (c->pq[c->ea.cnt + 1], c->pq[c->ea.cnt + 2]));
3266 e86_set_clk_ea (c, 4, 10);
3267
3268 return (c->ea.cnt + 3);
3269}
3270
3271/* OP CA: RETF data16 */
3272static
3273unsigned op_ca (e8086_t *c)
3274{
3275 e86_set_ip (c, e86_pop (c));
3276 e86_set_cs (c, e86_pop (c));
3277 e86_set_sp (c, e86_get_sp (c) + e86_mk_uint16 (c->pq[1], c->pq[2]));
3278 e86_pq_init (c);
3279 e86_set_clk (c, 25);
3280
3281 return (0);
3282}
3283
3284/* OP CB: RETF */
3285static
3286unsigned op_cb (e8086_t *c)
3287{
3288 e86_set_ip (c, e86_pop (c));
3289 e86_set_cs (c, e86_pop (c));
3290 e86_pq_init (c);
3291 e86_set_clk (c, 26);
3292
3293 return (0);
3294}
3295
3296/* OP CC: INT 3 */
3297static
3298unsigned op_cc (e8086_t *c)
3299{
3300 if (c->trap != NULL) {
3301 if (c->trap (c->trap_ext, 3) == 0) {
3302 e86_set_clk (c, 4);
3303 return (1);
3304 }
3305 }
3306
3307 e86_set_ip (c, e86_get_ip (c) + 1);
3308 e86_trap (c, 3);
3309
3310 e86_pq_init (c);
3311
3312 e86_set_clk (c, 52);
3313
3314 return (0);
3315}
3316
3317/* OP CD: INT imm8 */
3318static
3319unsigned op_cd (e8086_t *c)
3320{
3321 if (c->trap != NULL) {
3322 if (c->trap (c->trap_ext, c->pq[1]) == 0) {
3323 e86_set_clk (c, 4);
3324 return (2);
3325 }
3326 }
3327
3328 e86_set_ip (c, e86_get_ip (c) + 2);
3329 e86_trap (c, c->pq[1]);
3330
3331 e86_pq_init (c);
3332
3333 e86_set_clk (c, 51);
3334
3335 return (0);
3336}
3337
3338/* OP CE: INTO */
3339static
3340unsigned op_ce (e8086_t *c)
3341{
3342 if (e86_get_of (c) == 0) {
3343 e86_set_clk (c, 4);
3344 return (1);
3345 }
3346
3347 if (c->trap != NULL) {
3348 if (c->trap (c->trap_ext, 4) == 0) {
3349 e86_set_clk (c, 4);
3350 return (1);
3351 }
3352 }
3353
3354 e86_set_ip (c, e86_get_ip (c) + 1);
3355 e86_trap (c, 4);
3356
3357 e86_pq_init (c);
3358
3359 e86_set_clk (c, 53);
3360
3361 return (0);
3362}
3363
3364/* OP CF: IRET */
3365static
3366unsigned op_cf (e8086_t *c)
3367{
3368 e86_set_ip (c, e86_pop (c));
3369 e86_set_cs (c, e86_pop (c));
3370 c->flg = e86_pop (c);
3371
3372 e86_pq_init (c);
3373
3374 e86_set_clk (c, 32);
3375
3376 return (0);
3377}
3378
3379/* OP D0: ROL, ROR, RCL, RCR, SHL, SHR, SAR r/m8, 1 */
3380static
3381unsigned op_d0 (e8086_t *c)
3382{
3383 unsigned xop;
3384 unsigned short d, s;
3385
3386 xop = (c->pq[1] >> 3) & 7;
3387
3388 e86_get_ea_ptr (c, c->pq + 1);
3389 s = e86_get_ea8 (c);
3390
3391 switch (xop) {
3392 case 0: /* ROL r/m8, 1 */
3393 d = (s << 1) | (s >> 7);
3394 e86_set_cf (c, s & 0x80);
3395 break;
3396
3397 case 1: /* ROR r/m8, 1 */
3398 d = (s >> 1) | (s << 7);
3399 e86_set_cf (c, s & 1);
3400 break;
3401
3402 case 2: /* RCL r/m8, 1 */
3403 d = (s << 1) | e86_get_cf (c);
3404 e86_set_cf (c, s & 0x80);
3405 break;
3406
3407 case 3: /* RCR r/m8, 1 */
3408 d = (s >> 1) | (e86_get_cf (c) << 7);
3409 e86_set_cf (c, s & 1);
3410 break;
3411
3412 case 4: /* SHL r/m8, 1 */
3413 d = s << 1;
3414 e86_set_flg_szp_8 (c, d);
3415 e86_set_cf (c, s & 0x80);
3416 break;
3417
3418 case 5: /* SHR r/m8, 1 */
3419 d = s >> 1;
3420 e86_set_flg_szp_8 (c, d);
3421 e86_set_cf (c, s & 1);
3422 break;
3423
3424 case 7: /* SAR r/m8, 1 */
3425 d = (s >> 1) | (s & 0x80);
3426 e86_set_flg_szp_8 (c, d);
3427 e86_set_cf (c, s & 1);
3428 break;
3429
3430 default:
3431 return (op_ud (c));
3432 }
3433
3434 e86_set_of (c, (d ^ s) & 0x80);
3435
3436 e86_set_ea8 (c, d & 0xff);
3437 e86_set_clk_ea (c, 2, 15);
3438
3439 return (c->ea.cnt + 1);
3440}
3441
3442/* OP D1: ROL, ROR, RCL, RCR, SHL, SHR, SAR r/m16, 1 */
3443static
3444unsigned op_d1 (e8086_t *c)
3445{
3446 unsigned xop;
3447 unsigned long d, s;
3448
3449 xop = (c->pq[1] >> 3) & 7;
3450
3451 e86_get_ea_ptr (c, c->pq + 1);
3452 s = e86_get_ea16 (c);
3453
3454 switch (xop) {
3455 case 0: /* ROL r/m16, 1 */
3456 d = (s << 1) | (s >> 15);
3457 e86_set_cf (c, s & 0x8000);
3458 break;
3459
3460 case 1: /* ROR r/m16, 1 */
3461 d = (s >> 1) | (s << 15);
3462 e86_set_cf (c, s & 1);
3463 break;
3464
3465 case 2: /* RCL r/m16, 1 */
3466 d = (s << 1) | e86_get_cf (c);
3467 e86_set_cf (c, s & 0x8000);
3468 break;
3469
3470 case 3: /* RCR r/m16, 1 */
3471 d = (s >> 1) | (e86_get_cf (c) << 15);
3472 e86_set_cf (c, s & 1);
3473 break;
3474
3475 case 4: /* SHL r/m16, 1 */
3476 d = s << 1;
3477 e86_set_flg_szp_16 (c, d);
3478 e86_set_cf (c, s & 0x8000);
3479 break;
3480
3481 case 5: /* SHR r/m16, 1 */
3482 d = s >> 1;
3483 e86_set_flg_szp_16 (c, d);
3484 e86_set_cf (c, s & 1);
3485 break;
3486
3487 case 7: /* SAR r/m16, 1 */
3488 d = (s >> 1) | (s & 0x8000);
3489 e86_set_flg_szp_16 (c, d);
3490 e86_set_cf (c, s & 1);
3491 break;
3492
3493 default:
3494 return (op_ud (c));
3495 }
3496
3497 e86_set_of (c, (d ^ s) & 0x8000);
3498
3499 e86_set_ea16 (c, d & 0xffff);
3500 e86_set_clk_ea (c, 2, 15);
3501
3502 return (c->ea.cnt + 1);
3503}
3504
3505/* OP D2: ROL, ROR, RCL, RCR, SHL, SHR, SAR r/m8, CL */
3506static
3507unsigned op_d2 (e8086_t *c)
3508{
3509 unsigned xop;
3510 unsigned cnt;
3511 unsigned short d, s;
3512
3513 xop = (c->pq[1] >> 3) & 7;
3514
3515 e86_get_ea_ptr (c, c->pq + 1);
3516 s = e86_get_ea8 (c);
3517
3518 cnt = e86_get_cl (c);
3519
3520 if (c->cpu & E86_CPU_MASK_SHIFT) {
3521 cnt &= 0x1f;
3522 }
3523
3524 if (cnt == 0) {
3525 e86_set_clk_ea (c, 8, 20);
3526 return (c->ea.cnt + 1);
3527 }
3528
3529 switch (xop) {
3530 case 0: /* ROL r/m8, CL */
3531 d = (s << (cnt & 7)) | (s >> (8 - (cnt & 7)));
3532 e86_set_cf (c, d & 1);
3533 break;
3534
3535 case 1: /* ROR r/m8, CL */
3536 d = (s >> (cnt & 7)) | (s << (8 - (cnt & 7)));
3537 e86_set_cf (c, d & 0x80);
3538 break;
3539
3540 case 2: /* RCL r/m8, CL */
3541 s |= e86_get_cf (c) << 8;
3542 d = (s << (cnt % 9)) | (s >> (9 - (cnt % 9)));
3543 e86_set_cf (c, d & 0x100);
3544 break;
3545
3546 case 3: /* RCR r/m8, CL */
3547 s |= e86_get_cf (c) << 8;
3548 d = (s >> (cnt % 9)) | (s << (9 - (cnt % 9)));
3549 e86_set_cf (c, d & 0x100);
3550 break;
3551
3552 case 4: /* SHL r/m8, CL */
3553 d = (cnt > 8) ? 0 : (s << cnt);
3554 e86_set_flg_szp_8 (c, d);
3555 e86_set_cf (c, d & 0x100);
3556 break;
3557
3558 case 5: /* SHR r/m8, CL */
3559 d = (cnt > 8) ? 0 : (s >> (cnt - 1));
3560 e86_set_cf (c, d & 1);
3561 d = d >> 1;
3562 e86_set_flg_szp_8 (c, d);
3563 break;
3564
3565 case 7: /* SAR r/m8, CL */
3566 s |= (s & 0x80) ? 0xff00 : 0x0000;
3567 d = s >> ((cnt >= 8) ? 7 : (cnt - 1));
3568 e86_set_cf (c, d & 1);
3569 d = (d >> 1) & 0xff;
3570 e86_set_flg_szp_8 (c, d);
3571 break;
3572
3573 default:
3574 return (op_ud (c));
3575 }
3576
3577 e86_set_of (c, (d ^ s) & 0x80);
3578
3579 e86_set_ea8 (c, d & 0xff);
3580 e86_set_clk_ea (c, 8 + 4 * cnt, 20 + 4 * cnt);
3581
3582 return (c->ea.cnt + 1);
3583}
3584
3585/* OP D3: ROL, ROR, RCL, RCR, SHL, SHR, SAR r/m16, CL */
3586static
3587unsigned op_d3 (e8086_t *c)
3588{
3589 unsigned xop;
3590 unsigned cnt;
3591 unsigned long d, s;
3592
3593 xop = (c->pq[1] >> 3) & 7;
3594
3595 e86_get_ea_ptr (c, c->pq + 1);
3596 s = e86_get_ea16 (c);
3597
3598 cnt = e86_get_cl (c);
3599
3600 if (c->cpu & E86_CPU_MASK_SHIFT) {
3601 cnt &= 0x1f;
3602 }
3603
3604 if (cnt == 0) {
3605 e86_set_clk_ea (c, 8, 20);
3606 return (c->ea.cnt + 1);
3607 }
3608
3609 switch (xop) {
3610 case 0: /* ROL r/m16, CL */
3611 d = (s << (cnt & 15)) | (s >> (16 - (cnt & 15)));
3612 e86_set_cf (c, d & 1);
3613 break;
3614
3615 case 1: /* ROR r/m16, CL */
3616 d = (s >> (cnt & 15)) | (s << (16 - (cnt & 15)));
3617 e86_set_cf (c, d & 0x8000);
3618 break;
3619
3620 case 2: /* RCL r/m16, CL */
3621 s |= (unsigned long) e86_get_cf (c) << 16;
3622 d = (s << (cnt % 17)) | (s >> (17 - (cnt % 17)));
3623 e86_set_cf (c, d & 0x10000);
3624 break;
3625
3626 case 3: /* RCR r/m16, CL */
3627 s |= (unsigned long) e86_get_cf (c) << 16;
3628 d = (s >> (cnt % 17)) | (s << (17 - (cnt % 17)));
3629 e86_set_cf (c, d & 0x10000);
3630 break;
3631
3632 case 4: /* SHL r/m16, CL */
3633 d = (cnt > 16) ? 0 : (s << cnt);
3634 e86_set_flg_szp_16 (c, d);
3635 e86_set_cf (c, d & 0x10000);
3636 break;
3637
3638 case 5: /* SHR r/m16, CL */
3639 d = (cnt > 16) ? 0 : (s >> (cnt - 1));
3640 e86_set_cf (c, d & 1);
3641 d = d >> 1;
3642 e86_set_flg_szp_16 (c, d);
3643 break;
3644
3645 case 7: /* SAR r/m16, CL */
3646 s |= (s & 0x8000) ? 0xffff0000 : 0x00000000;
3647 d = s >> ((cnt >= 16) ? 15 : (cnt - 1));
3648 e86_set_cf (c, d & 1);
3649 d = (d >> 1) & 0xffff;
3650 e86_set_flg_szp_16 (c, d);
3651 break;
3652
3653 default:
3654 return (op_ud (c));
3655 }
3656
3657 e86_set_of (c, (d ^ s) & 0x8000);
3658
3659 e86_set_ea16 (c, d);
3660 e86_set_clk_ea (c, 8 + 4 * cnt, 20 + 4 * cnt);
3661
3662 return (c->ea.cnt + 1);
3663}
3664
3665/* OP D4: AAM imm8 */
3666static
3667unsigned op_d4 (e8086_t *c)
3668{
3669 unsigned short s, d;
3670 unsigned short div;
3671
3672 div = c->pq[1];
3673
3674 /* check for division by zero */
3675 if (div == 0) {
3676 e86_trap (c, 0);
3677 return (0);
3678 }
3679
3680 s = e86_get_al (c);
3681 d = (((s / div) & 0xff) << 8) | ((s % div) & 0xff);
3682
3683 e86_set_ax (c, d);
3684
3685 e86_set_flg_szp_16 (c, d);
3686 e86_set_clk (c, 83);
3687
3688 return (2);
3689}
3690
3691/* OP D5: AAD imm8 */
3692static
3693unsigned op_d5 (e8086_t *c)
3694{
3695 unsigned short s1, s2, d;
3696 unsigned short mul;
3697
3698 mul = c->pq[1];
3699
3700 if (mul == 0) {
3701 if (e86_hook (c) == 0) {
3702 e86_set_clk (c, 4);
3703 return (2);
3704 }
3705 }
3706
3707 s1 = e86_get_ah (c);
3708 s2 = e86_get_al (c);
3709
3710 d = mul * s1 + s2;
3711
3712 e86_set_ax (c, d & 0xff);
3713 e86_set_flg_szp_16 (c, d);
3714 e86_set_clk (c, 60);
3715
3716 return (2);
3717}
3718
3719/* OP D6: SALC */
3720static
3721unsigned op_d6 (e8086_t *c)
3722{
3723 unsigned short s1;
3724
3725 s1 = e86_get_cf (c);
3726
3727 e86_set_al (c, -s1);
3728 e86_set_clk (c, 3);
3729
3730 return (1);
3731}
3732
3733/* OP D7: XLAT */
3734static
3735unsigned op_d7 (e8086_t *c)
3736{
3737 unsigned short seg, ofs;
3738
3739 seg = e86_get_seg (c, E86_REG_DS);
3740 ofs = e86_get_bx (c) + e86_get_al (c);
3741
3742 e86_set_al (c, e86_get_mem8 (c, seg, ofs));
3743 e86_set_clk (c, 11);
3744
3745 return (1);
3746}
3747
3748/* OP D8: ESC */
3749static
3750unsigned op_d8 (e8086_t *c)
3751{
3752 if (c->cpu & E86_CPU_INT7) {
3753 e86_trap (c, 7);
3754 e86_set_clk (c, 50);
3755 return (0);
3756 }
3757
3758 e86_get_ea_ptr (c, c->pq + 1);
3759 e86_set_clk (c, 2);
3760
3761 return (1 + c->ea.cnt);
3762}
3763
3764/* OP E0: LOOPNZ imm8 */
3765static
3766unsigned op_e0 (e8086_t *c)
3767{
3768 e86_set_cx (c, e86_get_cx (c) - 1);
3769
3770 if ((e86_get_cx (c) != 0) && (e86_get_zf (c) == 0)) {
3771 e86_set_ip (c, e86_add_sint8 (c->ip, c->pq[1]) + 2);
3772 e86_pq_init (c);
3773 e86_set_clk (c, 19);
3774
3775 return (0);
3776 }
3777
3778 e86_set_clk (c, 5);
3779
3780 return (2);
3781}
3782
3783/* OP E1: LOOPZ imm8 */
3784static
3785unsigned op_e1 (e8086_t *c)
3786{
3787 e86_set_cx (c, e86_get_cx (c) - 1);
3788
3789 if ((e86_get_cx (c) != 0) && (e86_get_zf (c) != 0)) {
3790 e86_set_ip (c, e86_add_sint8 (c->ip, c->pq[1]) + 2);
3791 e86_pq_init (c);
3792 e86_set_clk (c, 18);
3793
3794 return (0);
3795 }
3796
3797 e86_set_clk (c, 5);
3798
3799 return (2);
3800}
3801
3802/* OP E2: LOOP imm8 */
3803static
3804unsigned op_e2 (e8086_t *c)
3805{
3806 e86_set_cx (c, e86_get_cx (c) - 1);
3807
3808 if (e86_get_cx (c) != 0) {
3809 e86_set_ip (c, e86_add_sint8 (c->ip, c->pq[1]) + 2);
3810 e86_pq_init (c);
3811 e86_set_clk (c, 18);
3812
3813 return (0);
3814 }
3815
3816 e86_set_clk (c, 5);
3817
3818 return (2);
3819}
3820
3821/* OP E3: JCXZ imm8 */
3822static
3823unsigned op_e3 (e8086_t *c)
3824{
3825 if (e86_get_cx (c) == 0) {
3826 e86_set_ip (c, e86_add_sint8 (c->ip + 2, c->pq[1]));
3827 e86_pq_init (c);
3828 e86_set_clk (c, 18);
3829 return (0);
3830 }
3831
3832 e86_set_clk (c, 6);
3833
3834 return (2);
3835}
3836
3837/* OP E4: IN AL, imm8 */
3838static
3839unsigned op_e4 (e8086_t *c)
3840{
3841 e86_set_al (c, e86_get_prt8 (c, c->pq[1]));
3842 e86_set_clk (c, 11);
3843
3844 return (2);
3845}
3846
3847/* OP E5: IN AX, imm8 */
3848static
3849unsigned op_e5 (e8086_t *c)
3850{
3851 e86_set_ax (c, e86_get_prt16 (c, c->pq[1]));
3852 e86_set_clk (c, 15);
3853
3854 return (2);
3855}
3856
3857/* OP E6: OUT imm8, AL */
3858static
3859unsigned op_e6 (e8086_t *c)
3860{
3861 e86_set_prt8 (c, c->pq[1], e86_get_al (c));
3862 e86_set_clk (c, 11);
3863
3864 return (2);
3865}
3866
3867/* OP E7: OUT imm8, AX */
3868static
3869unsigned op_e7 (e8086_t *c)
3870{
3871 e86_set_prt16 (c, c->pq[1], e86_get_ax (c));
3872 e86_set_clk (c, 11);
3873
3874 return (2);
3875}
3876
3877/* OP E8: CALL imm16 */
3878static
3879unsigned op_e8 (e8086_t *c)
3880{
3881 e86_push (c, e86_get_ip (c) + 3);
3882 e86_set_ip (c, e86_get_ip (c) + 3 + e86_mk_uint16 (c->pq[1], c->pq[2]));
3883
3884 e86_pq_init (c);
3885
3886 e86_set_clk (c, 19);
3887
3888 return (0);
3889}
3890
3891/* OP E9: JMP imm16 */
3892static
3893unsigned op_e9 (e8086_t *c)
3894{
3895 e86_set_ip (c, c->ip + e86_mk_uint16 (c->pq[1], c->pq[2]) + 3);
3896 e86_pq_init (c);
3897 e86_set_clk (c, 15);
3898
3899 return (0);
3900}
3901
3902/* OP EA: JMP imm32 */
3903static
3904unsigned op_ea (e8086_t *c)
3905{
3906 e86_set_ip (c, e86_mk_uint16 (c->pq[1], c->pq[2]));
3907 e86_set_cs (c, e86_mk_uint16 (c->pq[3], c->pq[4]));
3908 e86_pq_init (c);
3909 e86_set_clk (c, 15);
3910
3911 return (0);
3912}
3913
3914/* OP EB: JMP imm8 */
3915static
3916unsigned op_eb (e8086_t *c)
3917{
3918 e86_set_ip (c, e86_add_sint8 (c->ip, c->pq[1]) + 2);
3919 e86_pq_init (c);
3920 e86_set_clk (c, 15);
3921
3922 return (0);
3923}
3924
3925/* OP EC: IN AL, DX */
3926static
3927unsigned op_ec (e8086_t *c)
3928{
3929 e86_set_al (c, e86_get_prt8 (c, e86_get_dx (c)));
3930 e86_set_clk (c, 9);
3931
3932 return (1);
3933}
3934
3935/* OP ED: IN AX, DX */
3936static
3937unsigned op_ed (e8086_t *c)
3938{
3939 e86_set_ax (c, e86_get_prt16 (c, e86_get_dx (c)));
3940 e86_set_clk (c, 13);
3941
3942 return (1);
3943}
3944
3945/* OP EE: OUT DX, AL */
3946static
3947unsigned op_ee (e8086_t *c)
3948{
3949 e86_set_prt8 (c, e86_get_dx (c), e86_get_al (c));
3950 e86_set_clk (c, 9);
3951
3952 return (1);
3953}
3954
3955/* OP EF: OUT DX, AX */
3956static
3957unsigned op_ef (e8086_t *c)
3958{
3959 e86_set_prt16 (c, e86_get_dx (c), e86_get_ax (c));
3960 e86_set_clk (c, 9);
3961
3962 return (1);
3963}
3964
3965/* OP F0: LOCK */
3966static
3967unsigned op_f0 (e8086_t *c)
3968{
3969 c->prefix |= (E86_PREFIX_NEW | E86_PREFIX_LOCK);
3970
3971 e86_set_clk (c, 2);
3972
3973 return (1);
3974}
3975
3976/* OP F2: REPNE */
3977static
3978unsigned op_f2 (e8086_t *c)
3979{
3980 c->prefix |= (E86_PREFIX_NEW | E86_PREFIX_REPN);
3981 e86_set_clk (c, 2);
3982
3983 return (1);
3984}
3985
3986/* OP F3: REP */
3987static
3988unsigned op_f3 (e8086_t *c)
3989{
3990 c->prefix |= (E86_PREFIX_NEW | E86_PREFIX_REP);
3991 e86_set_clk (c, 2);
3992
3993 return (1);
3994}
3995
3996/* OP F4: HLT */
3997static
3998unsigned op_f4 (e8086_t *c)
3999{
4000 c->state |= E86_STATE_HALT;
4001
4002 e86_set_clk (c, 2);
4003
4004 return (1);
4005}
4006
4007/* OP F5: CMC */
4008static
4009unsigned op_f5 (e8086_t *c)
4010{
4011 c->flg ^= E86_FLG_C;
4012 e86_set_clk (c, 2);
4013
4014 return (1);
4015}
4016
4017/* OP F6 00: TEST r/m8, imm8 */
4018static
4019unsigned op_f6_00 (e8086_t *c)
4020{
4021 unsigned short s1, s2;
4022
4023 e86_get_ea_ptr (c, c->pq + 1);
4024
4025 s1 = e86_get_ea8 (c);
4026 s2 = c->pq[c->ea.cnt + 1];
4027
4028 e86_set_flg_log_8 (c, s1 & s2);
4029 e86_set_clk_ea (c, 5, 11);
4030
4031 return (c->ea.cnt + 2);
4032}
4033
4034/* OP F6 02: NOT r/m8 */
4035static
4036unsigned op_f6_02 (e8086_t *c)
4037{
4038 unsigned short d, s;
4039
4040 e86_get_ea_ptr (c, c->pq + 1);
4041
4042 s = e86_get_ea8 (c);
4043 d = ~s & 0xff;
4044
4045 e86_set_ea8 (c, d);
4046 e86_set_clk_ea (c, 3, 16);
4047
4048 return (c->ea.cnt + 1);
4049}
4050
4051/* OP F6 03: NEG r/m8 */
4052static
4053unsigned op_f6_03 (e8086_t *c)
4054{
4055 unsigned short d, s;
4056
4057 e86_get_ea_ptr (c, c->pq + 1);
4058
4059 s = e86_get_ea8 (c);
4060 d = (~s + 1) & 0xff;
4061
4062 e86_set_ea8 (c, d);
4063 e86_set_flg_sub_8 (c, 0, s);
4064 e86_set_clk_ea (c, 3, 16);
4065
4066 return (c->ea.cnt + 1);
4067}
4068
4069/* OP F6 04: MUL r/m8 */
4070static
4071unsigned op_f6_04 (e8086_t *c)
4072{
4073 unsigned short d;
4074
4075 e86_get_ea_ptr (c, c->pq + 1);
4076
4077 d = e86_get_ea8 (c) * e86_get_al (c);
4078
4079 e86_set_ax (c, d);
4080 e86_set_f (c, E86_FLG_O | E86_FLG_C, d & 0xff00);
4081 e86_set_f (c, E86_FLG_Z, d == 0);
4082 e86_set_clk_ea (c, (70 + 77) / 2, (76 + 83) / 2);
4083
4084 return (c->ea.cnt + 1);
4085}
4086
4087/* OP F6 05: IMUL r/m8 */
4088static
4089unsigned op_f6_05 (e8086_t *c)
4090{
4091 unsigned short s;
4092 unsigned long d;
4093
4094 e86_get_ea_ptr (c, c->pq + 1);
4095
4096 s = e86_get_ea8 (c);
4097
4098 d = (unsigned long) e86_mk_sint16 (s);
4099 d *= (unsigned long) e86_mk_sint16 (e86_get_al (c));
4100 d &= 0xffff;
4101
4102 e86_set_ax (c, d);
4103
4104 d &= 0xff80;
4105
4106 e86_set_f (c, E86_FLG_C | E86_FLG_O, (d != 0xff80) && (d != 0x0000));
4107
4108 e86_set_clk_ea (c, (80 + 98) / 2, (86 + 104) / 2);
4109
4110 return (c->ea.cnt + 1);
4111}
4112
4113/* OP F6 06: DIV r/m8 */
4114static
4115unsigned op_f6_06 (e8086_t *c)
4116{
4117 unsigned short s, d;
4118
4119 e86_get_ea_ptr (c, c->pq + 1);
4120
4121 s = e86_get_ea8 (c);
4122
4123 /* check for division by zero */
4124 if (s == 0) {
4125 return (op_divide_error (c));
4126 }
4127
4128 d = e86_get_ax (c) / s;
4129
4130 /* check for overflow */
4131 if (d & 0xff00) {
4132 return (op_divide_error (c));
4133 }
4134
4135 e86_set_ax (c, ((e86_get_ax (c) % s) << 8) | d);
4136
4137 e86_set_clk_ea (c, (80 + 90) / 2, (86 + 96) / 2);
4138
4139 return (c->ea.cnt + 1);
4140}
4141
4142/* OP F6 07: IDIV r/m8 */
4143static
4144unsigned op_f6_07 (e8086_t *c)
4145{
4146 unsigned short s1, s2, d1, d2;
4147 int sign1, sign2;
4148
4149 e86_get_ea_ptr (c, c->pq + 1);
4150
4151 s1 = e86_get_ax (c);
4152 s2 = e86_mk_sint16 (e86_get_ea8 (c));
4153
4154 /* check for division by zero */
4155 if (s2 == 0) {
4156 return (op_divide_error (c));
4157 }
4158
4159 sign1 = (s1 & 0x8000) != 0;
4160 sign2 = (s2 & 0x8000) != 0;
4161
4162 s1 = sign1 ? ((~s1 + 1) & 0xffff) : s1;
4163 s2 = sign2 ? ((~s2 + 1) & 0xffff) : s2;
4164
4165 d1 = s1 / s2;
4166 d2 = s1 % s2;
4167
4168 if (sign1 != sign2) {
4169 if (d1 > 0x80) {
4170 return (op_divide_error (c));
4171 }
4172
4173 d1 = (~d1 + 1) & 0xff;
4174 }
4175 else {
4176 if (d1 > 0x7f) {
4177 return (op_divide_error (c));
4178 }
4179 }
4180
4181 if (sign1) {
4182 d2 = (~d2 + 1) & 0xff;
4183 }
4184
4185 e86_set_ax (c, (d2 << 8) | d1);
4186
4187 e86_set_clk_ea (c, (101 + 112) / 2, (107 + 118) / 2);
4188
4189 return (c->ea.cnt + 1);
4190}
4191
4192static
4193e86_opcode_f e86_opcodes_f6[8] = {
4194 &op_f6_00, &op_ud, &op_f6_02, &op_f6_03,
4195 &op_f6_04, &op_f6_05, &op_f6_06, &op_f6_07,
4196};
4197
4198/* OP F6: xxx r/m8 */
4199static
4200unsigned op_f6 (e8086_t *c)
4201{
4202 unsigned xop;
4203
4204 xop = (c->pq[1] >> 3) & 7;
4205
4206 return (e86_opcodes_f6[xop] (c));
4207}
4208
4209/* OP F7 00: TEST r/m16, imm16 */
4210static
4211unsigned op_f7_00 (e8086_t *c)
4212{
4213 unsigned long s1, s2;
4214
4215 e86_get_ea_ptr (c, c->pq + 1);
4216
4217 s1 = e86_get_ea16 (c);
4218 s2 = e86_mk_uint16 (c->pq[c->ea.cnt + 1], c->pq[c->ea.cnt + 2]);
4219
4220 e86_set_flg_log_16 (c, s1 & s2);
4221 e86_set_clk_ea (c, 5, 11);
4222
4223 return (c->ea.cnt + 3);
4224}
4225
4226/* OP F7 02: NOT r/m16 */
4227static
4228unsigned op_f7_02 (e8086_t *c)
4229{
4230 unsigned long d, s;
4231
4232 e86_get_ea_ptr (c, c->pq + 1);
4233
4234 s = e86_get_ea16 (c);
4235 d = ~s & 0xffff;
4236
4237 e86_set_ea16 (c, d);
4238 e86_set_clk_ea (c, 3, 16);
4239
4240 return (c->ea.cnt + 1);
4241}
4242
4243/* OP F7 03: NEG r/m16 */
4244static
4245unsigned op_f7_03 (e8086_t *c)
4246{
4247 unsigned long d, s;
4248
4249 e86_get_ea_ptr (c, c->pq + 1);
4250
4251 s = e86_get_ea16 (c);
4252 d = (~s + 1) & 0xffff;
4253
4254 e86_set_ea16 (c, d);
4255 e86_set_flg_sub_16 (c, 0, s);
4256 e86_set_clk_ea (c, 3, 16);
4257
4258 return (c->ea.cnt + 1);
4259}
4260
4261/* OP F7 04: MUL r/m16 */
4262static
4263unsigned op_f7_04 (e8086_t *c)
4264{
4265 unsigned long d;
4266
4267 e86_get_ea_ptr (c, c->pq + 1);
4268
4269 d = e86_get_ea16 (c) * e86_get_ax (c);
4270
4271 e86_set_ax (c, d & 0xffff);
4272 e86_set_dx (c, d >> 16);
4273 e86_set_f (c, E86_FLG_C | E86_FLG_O, d & 0xffff0000);
4274 e86_set_f (c, E86_FLG_Z, d == 0);
4275 e86_set_clk_ea (c, (118 + 113) / 2, (124 + 139) / 2);
4276
4277 return (c->ea.cnt + 1);
4278}
4279
4280/* OP F7 05: IMUL r/m16 */
4281static
4282unsigned op_f7_05 (e8086_t *c)
4283{
4284 unsigned long s1, s2, d;
4285
4286 e86_get_ea_ptr (c, c->pq + 1);
4287
4288 s1 = e86_get_ax (c);
4289 s2 = e86_get_ea16 (c);
4290
4291 s1 = (s1 & 0x8000) ? (s1 | 0xffff0000) : s1;
4292 s2 = (s2 & 0x8000) ? (s2 | 0xffff0000) : s2;
4293
4294 d = (s1 * s2) & 0xffffffff;
4295
4296 e86_set_ax (c, d & 0xffff);
4297 e86_set_dx (c, d >> 16);
4298
4299 d &= 0xffff8000;
4300
4301 e86_set_f (c, E86_FLG_C | E86_FLG_O, (d != 0xffff8000) && (d != 0x00000000));
4302
4303 e86_set_clk_ea (c, (128 + 154) / 2, (134 + 160) / 2);
4304
4305 return (c->ea.cnt + 1);
4306}
4307
4308/* OP F7 06: DIV r/m16 */
4309static
4310unsigned op_f7_06 (e8086_t *c)
4311{
4312 unsigned long s1, s2, d;
4313
4314 e86_get_ea_ptr (c, c->pq + 1);
4315
4316 s2 = e86_get_ea16 (c);
4317
4318 /* check for division by zero */
4319 if (s2 == 0) {
4320 return (op_divide_error (c));
4321 }
4322
4323 s1 = ((unsigned long) e86_get_dx (c) << 16) | e86_get_ax (c);
4324
4325 d = s1 / s2;
4326
4327 /* check for overflow */
4328 if (d & 0xffff0000) {
4329 return (op_divide_error (c));
4330 }
4331
4332 e86_set_ax (c, d);
4333 e86_set_dx (c, s1 % s2);
4334
4335 e86_set_clk_ea (c, (144 + 162) / 2, (150 + 168) / 2);
4336
4337 return (c->ea.cnt + 1);
4338}
4339
4340/* OP F7 07: IDIV r/m16 */
4341static
4342unsigned op_f7_07 (e8086_t *c)
4343{
4344 unsigned long s1, s2, d1, d2;
4345 int sign1, sign2;
4346
4347 e86_get_ea_ptr (c, c->pq + 1);
4348
4349 s1 = ((unsigned long) e86_get_dx (c) << 16) | e86_get_ax (c);
4350 s2 = e86_get_ea16 (c);
4351 s2 = (s2 & 0x8000) ? (s2 | 0xffff0000) : s2;
4352
4353 if (s2 == 0) {
4354 return (op_divide_error (c));
4355 }
4356
4357 sign1 = (s1 & 0x80000000) != 0;
4358 sign2 = (s2 & 0x80000000) != 0;
4359
4360 s1 = sign1 ? ((~s1 + 1) & 0xffffffff) : s1;
4361 s2 = sign2 ? ((~s2 + 1) & 0xffffffff) : s2;
4362
4363 d1 = s1 / s2;
4364 d2 = s1 % s2;
4365
4366 if (sign1 != sign2) {
4367 if (d1 > 0x8000) {
4368 return (op_divide_error (c));
4369 }
4370
4371 d1 = (~d1 + 1) & 0xffff;
4372 }
4373 else {
4374 if (d1 > 0x7fff) {
4375 return (op_divide_error (c));
4376 }
4377 }
4378
4379 if (sign1) {
4380 d2 = (~d2 + 1) & 0xffff;
4381 }
4382
4383 e86_set_ax (c, d1);
4384 e86_set_dx (c, d2);
4385
4386 e86_set_clk_ea (c, (165 + 184) / 2, (171 + 190) / 2);
4387
4388 return (c->ea.cnt + 1);
4389}
4390
4391static
4392e86_opcode_f e86_opcodes_f7[8] = {
4393 &op_f7_00, &op_ud, &op_f7_02, &op_f7_03,
4394 &op_f7_04, &op_f7_05, &op_f7_06, &op_f7_07,
4395};
4396
4397/* OP F7: xxx r/m16 */
4398static
4399unsigned op_f7 (e8086_t *c)
4400{
4401 unsigned xop;
4402
4403 xop = (c->pq[1] >> 3) & 7;
4404
4405 return (e86_opcodes_f7[xop] (c));
4406}
4407
4408/* OP F8: CLC */
4409static
4410unsigned op_f8 (e8086_t *c)
4411{
4412 e86_set_cf (c, 0);
4413 e86_set_clk (c, 2);
4414
4415 return (1);
4416}
4417
4418/* OP F9: STC */
4419static
4420unsigned op_f9 (e8086_t *c)
4421{
4422 e86_set_cf (c, 1);
4423 e86_set_clk (c, 2);
4424
4425 return (1);
4426}
4427
4428/* OP FA: CLI */
4429static
4430unsigned op_fa (e8086_t *c)
4431{
4432 e86_set_if (c, 0);
4433 e86_set_clk (c, 2);
4434
4435 return (1);
4436}
4437
4438/* OP FB: STI */
4439static
4440unsigned op_fb (e8086_t *c)
4441{
4442 e86_set_if (c, 1);
4443 e86_set_clk (c, 2);
4444
4445 return (1);
4446}
4447
4448/* OP FC: CLD */
4449static
4450unsigned op_fc (e8086_t *c)
4451{
4452 e86_set_df (c, 0);
4453 e86_set_clk (c, 2);
4454
4455 return (1);
4456}
4457
4458/* OP FD: STD */
4459static
4460unsigned op_fd (e8086_t *c)
4461{
4462 e86_set_df (c, 1);
4463 e86_set_clk (c, 2);
4464
4465 return (1);
4466}
4467
4468/* OP FE: INC, DEC r/m8 */
4469static
4470unsigned op_fe (e8086_t *c)
4471{
4472 unsigned xop;
4473 unsigned short d, s;
4474 unsigned short cf;
4475
4476 xop = (c->pq[1] >> 3) & 7;
4477
4478 switch (xop) {
4479 case 0: /* INC r/m8 */
4480 e86_get_ea_ptr (c, c->pq + 1);
4481 s = e86_get_ea8 (c);
4482
4483 d = s + 1;
4484
4485 e86_set_ea8 (c, d);
4486
4487 cf = c->flg;
4488 e86_set_flg_add_8 (c, s, 1);
4489 c->flg ^= (c->flg ^ cf) & E86_FLG_C;
4490
4491 e86_set_clk_ea (c, 3, 15);
4492
4493 return (c->ea.cnt + 1);
4494
4495 case 1: /* DEC r/m8 */
4496 e86_get_ea_ptr (c, c->pq + 1);
4497 s = e86_get_ea8 (c);
4498
4499 d = s - 1;
4500
4501 e86_set_ea8 (c, d);
4502
4503 cf = c->flg;
4504 e86_set_flg_sub_8 (c, s, 1);
4505 c->flg ^= (c->flg ^ cf) & E86_FLG_C;
4506
4507 e86_set_clk_ea (c, 3, 15);
4508
4509 return (c->ea.cnt + 1);
4510
4511 default:
4512 return (op_ud (c));
4513 }
4514
4515 return (0);
4516}
4517
4518/* OP FF 00: INC r/m16 */
4519static
4520unsigned op_ff_00 (e8086_t *c)
4521{
4522 unsigned long s, d;
4523 unsigned short cf;
4524
4525 e86_get_ea_ptr (c, c->pq + 1);
4526
4527 s = e86_get_ea16 (c);
4528 d = s + 1;
4529
4530 e86_set_ea16 (c, d);
4531
4532 cf = c->flg;
4533 e86_set_flg_add_16 (c, s, 1);
4534 c->flg ^= (c->flg ^ cf) & E86_FLG_C;
4535
4536 e86_set_clk_ea (c, 3, 15);
4537
4538 return (c->ea.cnt + 1);
4539}
4540
4541/* OP FF 01: DEC r/m16 */
4542static
4543unsigned op_ff_01 (e8086_t *c)
4544{
4545 unsigned long s, d;
4546 unsigned short cf;
4547
4548 e86_get_ea_ptr (c, c->pq + 1);
4549
4550 s = e86_get_ea16 (c);
4551 d = s - 1;
4552
4553 e86_set_ea16 (c, d);
4554
4555 cf = c->flg;
4556 e86_set_flg_sub_16 (c, s, 1);
4557 c->flg ^= (c->flg ^ cf) & E86_FLG_C;
4558
4559 e86_set_clk_ea (c, 3, 15);
4560
4561 return (c->ea.cnt + 1);
4562}
4563
4564/* OP FF 02: CALL r/m16 */
4565static
4566unsigned op_ff_02 (e8086_t *c)
4567{
4568 e86_get_ea_ptr (c, c->pq + 1);
4569
4570 e86_push (c, e86_get_ip (c) + c->ea.cnt + 1);
4571 e86_set_ip (c, e86_get_ea16 (c));
4572
4573 e86_pq_init (c);
4574
4575 e86_set_clk_ea (c, 16, 21);
4576
4577 return (0);
4578}
4579
4580/* OP FF 03: CALL m32 */
4581static
4582unsigned op_ff_03 (e8086_t *c)
4583{
4584 unsigned short seg, ofs;
4585
4586 e86_get_ea_ptr (c, c->pq + 1);
4587
4588 if (!c->ea.is_mem) {
4589 return (c->ea.cnt + 1);
4590 }
4591
4592 e86_push (c, e86_get_cs (c));
4593 e86_push (c, e86_get_ip (c) + c->ea.cnt + 1);
4594
4595 seg = e86_get_sego (c, c->ea.seg);
4596 ofs = c->ea.ofs;
4597
4598 e86_set_ip (c, e86_get_mem16 (c, seg, ofs));
4599 e86_set_cs (c, e86_get_mem16 (c, seg, ofs + 2));
4600
4601 e86_pq_init (c);
4602
4603 e86_set_clk (c, 37);
4604
4605 return (0);
4606}
4607
4608/* OP FF 04: JMP r/m16 */
4609static
4610unsigned op_ff_04 (e8086_t *c)
4611{
4612 e86_get_ea_ptr (c, c->pq + 1);
4613 e86_set_ip (c, e86_get_ea16 (c));
4614 e86_pq_init (c);
4615 e86_set_clk_ea (c, 11, 18);
4616
4617 return (0);
4618}
4619
4620/* OP FF 05: JMP m32 */
4621static
4622unsigned op_ff_05 (e8086_t *c)
4623{
4624 e86_get_ea_ptr (c, c->pq + 1);
4625
4626 if (!c->ea.is_mem) {
4627 return (c->ea.cnt + 1);
4628 }
4629
4630 e86_set_ip (c, e86_get_mem16 (c, c->ea.seg, c->ea.ofs));
4631 e86_set_cs (c, e86_get_mem16 (c, c->ea.seg, c->ea.ofs + 2));
4632
4633 e86_pq_init (c);
4634
4635 e86_set_clk (c, 24);
4636
4637 return (0);
4638}
4639
4640/* OP FF 06: PUSH r/m16 */
4641static
4642unsigned op_ff_06 (e8086_t *c)
4643{
4644 e86_get_ea_ptr (c, c->pq + 1);
4645
4646 if ((c->ea.is_mem == 0) && (c->ea.ofs == E86_REG_SP) && ((c->cpu & E86_CPU_PUSH_FIRST) == 0)) {
4647 e86_push (c, e86_get_sp (c) - 2);
4648 }
4649 else {
4650 e86_push (c, e86_get_ea16 (c));
4651 }
4652
4653 e86_set_clk_ea (c, 10, 16);
4654
4655 return (c->ea.cnt + 1);
4656}
4657
4658static
4659e86_opcode_f e86_opcodes_ff[8] = {
4660 &op_ff_00, &op_ff_01, &op_ff_02, &op_ff_03,
4661 &op_ff_04, &op_ff_05, &op_ff_06, &op_ud
4662};
4663
4664/* OP FF: xxx r/m16 */
4665static
4666unsigned op_ff (e8086_t *c)
4667{
4668 unsigned xop;
4669
4670 xop = (c->pq[1] >> 3) & 7;
4671
4672 return (e86_opcodes_ff[xop] (c));
4673}
4674
4675e86_opcode_f e86_opcodes[256] = {
4676 &op_00, &op_01, &op_02, &op_03, &op_04, &op_05, &op_06, &op_07,
4677 &op_08, &op_09, &op_0a, &op_0b, &op_0c, &op_0d, &op_0e, &op_0f,
4678 &op_10, &op_11, &op_12, &op_13, &op_14, &op_15, &op_16, &op_17,
4679 &op_18, &op_19, &op_1a, &op_1b, &op_1c, &op_1d, &op_1e, &op_1f,
4680 &op_20, &op_21, &op_22, &op_23, &op_24, &op_25, &op_26, &op_27, /* 20 */
4681 &op_28, &op_29, &op_2a, &op_2b, &op_2c, &op_2d, &op_2e, &op_2f,
4682 &op_30, &op_31, &op_32, &op_33, &op_34, &op_35, &op_36, &op_37, /* 30 */
4683 &op_38, &op_39, &op_3a, &op_3b, &op_3c, &op_3d, &op_3e, &op_3f,
4684 &op_40, &op_40, &op_40, &op_40, &op_40, &op_40, &op_40, &op_40, /* 40 */
4685 &op_48, &op_48, &op_48, &op_48, &op_48, &op_48, &op_48, &op_48,
4686 &op_50, &op_50, &op_50, &op_50, &op_50, &op_50, &op_50, &op_50, /* 50 */
4687 &op_58, &op_58, &op_58, &op_58, &op_58, &op_58, &op_58, &op_58,
4688 &op_ud, &op_ud, &op_ud, &op_ud, &op_ud, &op_ud, &op_66, &op_ud, /* 60 */
4689 &op_ud, &op_ud, &op_ud, &op_ud, &op_ud, &op_ud, &op_ud, &op_ud,
4690 &op_70, &op_71, &op_72, &op_73, &op_74, &op_75, &op_76, &op_77, /* 70 */
4691 &op_78, &op_79, &op_7a, &op_7b, &op_7c, &op_7d, &op_7e, &op_7f,
4692 &op_80, &op_81, &op_80, &op_83, &op_84, &op_85, &op_86, &op_87, /* 80 */
4693 &op_88, &op_89, &op_8a, &op_8b, &op_8c, &op_8d, &op_8e, &op_8f,
4694 &op_90, &op_90, &op_90, &op_90, &op_90, &op_90, &op_90, &op_90, /* 90 */
4695 &op_98, &op_99, &op_9a, &op_9b, &op_9c, &op_9d, &op_9e, &op_9f,
4696 &op_a0, &op_a1, &op_a2, &op_a3, &op_a4, &op_a5, &op_a6, &op_a7, /* A0 */
4697 &op_a8, &op_a9, &op_aa, &op_ab, &op_ac, &op_ad, &op_ae, &op_af,
4698 &op_b0, &op_b1, &op_b2, &op_b3, &op_b4, &op_b5, &op_b6, &op_b7, /* B0 */
4699 &op_b8, &op_b9, &op_ba, &op_bb, &op_bc, &op_bd, &op_be, &op_bf,
4700 &op_ud, &op_ud, &op_c2, &op_c3, &op_c4, &op_c5, &op_c6, &op_c7, /* C0 */
4701 &op_ud, &op_ud, &op_ca, &op_cb, &op_cc, &op_cd, &op_ce, &op_cf,
4702 &op_d0, &op_d1, &op_d2, &op_d3, &op_d4, &op_d5, &op_d6, &op_d7, /* D0 */
4703 &op_d8, &op_d8, &op_d8, &op_d8, &op_d8, &op_d8, &op_d8, &op_d8,
4704 &op_e0, &op_e1, &op_e2, &op_e3, &op_e4, &op_e5, &op_e6, &op_e7, /* E0 */
4705 &op_e8, &op_e9, &op_ea, &op_eb, &op_ec, &op_ed, &op_ee, &op_ef,
4706 &op_f0, &op_ud, &op_f2, &op_f3, &op_f4, &op_f5, &op_f6, &op_f7, /* F0 */
4707 &op_f8, &op_f9, &op_fa, &op_fb, &op_fc, &op_fd, &op_fe, &op_ff
4708};