1 /****************************************************************************
2 *
3 *                       Realmode X86 Emulator Library
4 *
5 *               Copyright (C) 1991-2004 SciTech Software, Inc.
6 *                    Copyright (C) David Mosberger-Tang
7 *                      Copyright (C) 1999 Egbert Eich
8 *
9 *  ========================================================================
10 *
11 *  Permission to use, copy, modify, distribute, and sell this software and
12 *  its documentation for any purpose is hereby granted without fee,
13 *  provided that the above copyright notice appear in all copies and that
14 *  both that copyright notice and this permission notice appear in
15 *  supporting documentation, and that the name of the authors not be used
16 *  in advertising or publicity pertaining to distribution of the software
17 *  without specific, written prior permission.  The authors makes no
18 *  representations about the suitability of this software for any purpose.
19 *  It is provided "as is" without express or implied warranty.
20 *
21 *  THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
22 *  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
23 *  EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
24 *  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
25 *  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26 *  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27 *  PERFORMANCE OF THIS SOFTWARE.
28 *
29 *  ========================================================================
30 *
31 * Language:     ANSI C
32 * Environment:  Any
33 * Developer:    Kendall Bennett
34 *
35 * Description:  This file contains the code to implement the primitive
36 *               machine operations used by the emulation code in ops.c
37 *
38 * Carry Chain Calculation
39 *
40 * This represents a somewhat expensive calculation which is
41 * apparently required to emulate the setting of the OF and AF flag.
42 * The latter is not so important, but the former is.  The overflow
43 * flag is the XOR of the top two bits of the carry chain for an
44 * addition (similar for subtraction).  Since we do not want to
45 * simulate the addition in a bitwise manner, we try to calculate the
46 * carry chain given the two operands and the result.
47 *
48 * So, given the following table, which represents the addition of two
49 * bits, we can derive a formula for the carry chain.
50 *
51 * a   b   cin   r     cout
52 * 0   0   0     0     0
53 * 0   0   1     1     0
54 * 0   1   0     1     0
55 * 0   1   1     0     1
56 * 1   0   0     1     0
57 * 1   0   1     0     1
58 * 1   1   0     0     1
59 * 1   1   1     1     1
60 *
61 * Construction of table for cout:
62 *
63 * ab
64 * r  \  00   01   11  10
65 * |------------------
66 * 0  |   0    1    1   1
67 * 1  |   0    0    1   0
68 *
69 * By inspection, one gets:  cc = ab +  r'(a + b)
70 *
71 * That represents alot of operations, but NO CHOICE....
72 *
73 * Borrow Chain Calculation.
74 *
75 * The following table represents the subtraction of two bits, from
76 * which we can derive a formula for the borrow chain.
77 *
78 * a   b   bin   r     bout
79 * 0   0   0     0     0
80 * 0   0   1     1     1
81 * 0   1   0     1     1
82 * 0   1   1     0     1
83 * 1   0   0     1     0
84 * 1   0   1     0     0
85 * 1   1   0     0     0
86 * 1   1   1     1     1
87 *
88 * Construction of table for cout:
89 *
90 * ab
91 * r  \  00   01   11  10
92 * |------------------
93 * 0  |   0    1    0   0
94 * 1  |   1    1    1   0
95 *
96 * By inspection, one gets:  bc = a'b +  r(a' + b)
97 *
98 ****************************************************************************/
99 
100 #define PRIM_OPS_NO_REDEFINE_ASM
101 #include "x86emu/x86emui.h"
102 
103 /*------------------------- Global Variables ------------------------------*/
104 
105 static u32 x86emu_parity_tab[8] =
106 {
107     0x96696996,
108     0x69969669,
109     0x69969669,
110     0x96696996,
111     0x69969669,
112     0x96696996,
113     0x96696996,
114     0x69969669,
115 };
116 
117 #define PARITY(x)   (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
118 #define XOR2(x)     (((x) ^ ((x)>>1)) & 0x1)
119 
120 /*----------------------------- Implementation ----------------------------*/
121 
122 /****************************************************************************
123 REMARKS:
124 Implements the AAA instruction and side effects.
125 ****************************************************************************/
aaa_word(u16 d)126 u16 aaa_word(u16 d)
127 {
128     u16 res;
129     if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
130         d += 0x6;
131         d += 0x100;
132         SET_FLAG(F_AF);
133         SET_FLAG(F_CF);
134     } else {
135         CLEAR_FLAG(F_CF);
136         CLEAR_FLAG(F_AF);
137     }
138     res = (u16)(d & 0xFF0F);
139     CLEAR_FLAG(F_SF);
140     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
141     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
142     return res;
143 }
144 
145 /****************************************************************************
146 REMARKS:
147 Implements the AAA instruction and side effects.
148 ****************************************************************************/
aas_word(u16 d)149 u16 aas_word(u16 d)
150 {
151     u16 res;
152     if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
153         d -= 0x6;
154         d -= 0x100;
155         SET_FLAG(F_AF);
156         SET_FLAG(F_CF);
157     } else {
158         CLEAR_FLAG(F_CF);
159         CLEAR_FLAG(F_AF);
160     }
161     res = (u16)(d & 0xFF0F);
162     CLEAR_FLAG(F_SF);
163     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
164     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
165     return res;
166 }
167 
168 /****************************************************************************
169 REMARKS:
170 Implements the AAD instruction and side effects.
171 ****************************************************************************/
aad_word(u16 d)172 u16 aad_word(u16 d)
173 {
174     u16 l;
175     u8 hb, lb;
176 
177     hb = (u8)((d >> 8) & 0xff);
178     lb = (u8)((d & 0xff));
179     l = (u16)((lb + 10 * hb) & 0xFF);
180 
181     CLEAR_FLAG(F_CF);
182     CLEAR_FLAG(F_AF);
183     CLEAR_FLAG(F_OF);
184     CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
185     CONDITIONAL_SET_FLAG(l == 0, F_ZF);
186     CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
187     return l;
188 }
189 
190 /****************************************************************************
191 REMARKS:
192 Implements the AAM instruction and side effects.
193 ****************************************************************************/
aam_word(u8 d)194 u16 aam_word(u8 d)
195 {
196     u16 h, l;
197 
198     h = (u16)(d / 10);
199     l = (u16)(d % 10);
200     l |= (u16)(h << 8);
201 
202     CLEAR_FLAG(F_CF);
203     CLEAR_FLAG(F_AF);
204     CLEAR_FLAG(F_OF);
205     CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
206     CONDITIONAL_SET_FLAG(l == 0, F_ZF);
207     CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
208     return l;
209 }
210 
211 /****************************************************************************
212 REMARKS:
213 Implements the ADC instruction and side effects.
214 ****************************************************************************/
adc_byte(u8 d,u8 s)215 u8 adc_byte(u8 d, u8 s)
216 {
217     register u32 res;   /* all operands in native machine order */
218     register u32 cc;
219 
220     if (ACCESS_FLAG(F_CF))
221         res = 1 + d + s;
222     else
223         res = d + s;
224 
225     CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
226     CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
227     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
228     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
229 
230     /* calculate the carry chain  SEE NOTE AT TOP. */
231     cc = (s & d) | ((~res) & (s | d));
232     CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
233     CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
234     return (u8)res;
235 }
236 
237 /****************************************************************************
238 REMARKS:
239 Implements the ADC instruction and side effects.
240 ****************************************************************************/
adc_word(u16 d,u16 s)241 u16 adc_word(u16 d, u16 s)
242 {
243     register u32 res;   /* all operands in native machine order */
244     register u32 cc;
245 
246     if (ACCESS_FLAG(F_CF))
247         res = 1 + d + s;
248     else
249         res = d + s;
250 
251     CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
252     CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
253     CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
254     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
255 
256     /* calculate the carry chain  SEE NOTE AT TOP. */
257     cc = (s & d) | ((~res) & (s | d));
258     CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
259     CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
260     return (u16)res;
261 }
262 
263 /****************************************************************************
264 REMARKS:
265 Implements the ADC instruction and side effects.
266 ****************************************************************************/
adc_long(u32 d,u32 s)267 u32 adc_long(u32 d, u32 s)
268 {
269     register u32 lo;    /* all operands in native machine order */
270     register u32 hi;
271     register u32 res;
272     register u32 cc;
273 
274     if (ACCESS_FLAG(F_CF)) {
275         lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
276         res = 1 + d + s;
277         }
278     else {
279         lo = (d & 0xFFFF) + (s & 0xFFFF);
280         res = d + s;
281         }
282     hi = (lo >> 16) + (d >> 16) + (s >> 16);
283 
284     CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
285     CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
286     CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
287     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
288 
289     /* calculate the carry chain  SEE NOTE AT TOP. */
290     cc = (s & d) | ((~res) & (s | d));
291     CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
292     CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
293     return res;
294 }
295 
296 /****************************************************************************
297 REMARKS:
298 Implements the ADD instruction and side effects.
299 ****************************************************************************/
add_byte(u8 d,u8 s)300 u8 add_byte(u8 d, u8 s)
301 {
302     register u32 res;   /* all operands in native machine order */
303     register u32 cc;
304 
305     res = d + s;
306     CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
307     CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
308     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
309     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
310 
311     /* calculate the carry chain  SEE NOTE AT TOP. */
312     cc = (s & d) | ((~res) & (s | d));
313     CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
314     CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
315     return (u8)res;
316 }
317 
318 /****************************************************************************
319 REMARKS:
320 Implements the ADD instruction and side effects.
321 ****************************************************************************/
add_word(u16 d,u16 s)322 u16 add_word(u16 d, u16 s)
323 {
324     register u32 res;   /* all operands in native machine order */
325     register u32 cc;
326 
327     res = d + s;
328     CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
329     CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
330     CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
331     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
332 
333     /* calculate the carry chain  SEE NOTE AT TOP. */
334     cc = (s & d) | ((~res) & (s | d));
335     CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
336     CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
337     return (u16)res;
338 }
339 
340 /****************************************************************************
341 REMARKS:
342 Implements the ADD instruction and side effects.
343 ****************************************************************************/
add_long(u32 d,u32 s)344 u32 add_long(u32 d, u32 s)
345 {
346     register u32 lo;    /* all operands in native machine order */
347     register u32 hi;
348     register u32 res;
349     register u32 cc;
350 
351     lo = (d & 0xFFFF) + (s & 0xFFFF);
352     res = d + s;
353     hi = (lo >> 16) + (d >> 16) + (s >> 16);
354 
355     CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
356     CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
357     CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
358     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
359 
360     /* calculate the carry chain  SEE NOTE AT TOP. */
361     cc = (s & d) | ((~res) & (s | d));
362     CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
363     CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
364 
365     return res;
366 }
367 
368 /****************************************************************************
369 REMARKS:
370 Implements the AND instruction and side effects.
371 ****************************************************************************/
and_byte(u8 d,u8 s)372 u8 and_byte(u8 d, u8 s)
373 {
374     register u8 res;    /* all operands in native machine order */
375 
376     res = d & s;
377 
378     /* set the flags  */
379     CLEAR_FLAG(F_OF);
380     CLEAR_FLAG(F_CF);
381     CLEAR_FLAG(F_AF);
382     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
383     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
384     CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
385     return res;
386 }
387 
388 /****************************************************************************
389 REMARKS:
390 Implements the AND instruction and side effects.
391 ****************************************************************************/
and_word(u16 d,u16 s)392 u16 and_word(u16 d, u16 s)
393 {
394     register u16 res;   /* all operands in native machine order */
395 
396     res = d & s;
397 
398     /* set the flags  */
399     CLEAR_FLAG(F_OF);
400     CLEAR_FLAG(F_CF);
401     CLEAR_FLAG(F_AF);
402     CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
403     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
404     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
405     return res;
406 }
407 
408 /****************************************************************************
409 REMARKS:
410 Implements the AND instruction and side effects.
411 ****************************************************************************/
and_long(u32 d,u32 s)412 u32 and_long(u32 d, u32 s)
413 {
414     register u32 res;   /* all operands in native machine order */
415 
416     res = d & s;
417 
418     /* set the flags  */
419     CLEAR_FLAG(F_OF);
420     CLEAR_FLAG(F_CF);
421     CLEAR_FLAG(F_AF);
422     CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
423     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
424     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
425     return res;
426 }
427 
428 /****************************************************************************
429 REMARKS:
430 Implements the CMP instruction and side effects.
431 ****************************************************************************/
cmp_byte(u8 d,u8 s)432 u8 cmp_byte(u8 d, u8 s)
433 {
434     register u32 res;   /* all operands in native machine order */
435     register u32 bc;
436 
437     res = d - s;
438     CLEAR_FLAG(F_CF);
439     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
440     CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
441     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
442 
443     /* calculate the borrow chain.  See note at top */
444     bc = (res & (~d | s)) | (~d & s);
445     CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
446     CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
447     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
448     return d;
449 }
450 
451 /****************************************************************************
452 REMARKS:
453 Implements the CMP instruction and side effects.
454 ****************************************************************************/
cmp_word(u16 d,u16 s)455 u16 cmp_word(u16 d, u16 s)
456 {
457     register u32 res;   /* all operands in native machine order */
458     register u32 bc;
459 
460     res = d - s;
461     CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
462     CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
463     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
464 
465     /* calculate the borrow chain.  See note at top */
466     bc = (res & (~d | s)) | (~d & s);
467     CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
468     CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
469     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
470     return d;
471 }
472 
473 /****************************************************************************
474 REMARKS:
475 Implements the CMP instruction and side effects.
476 ****************************************************************************/
cmp_long(u32 d,u32 s)477 u32 cmp_long(u32 d, u32 s)
478 {
479     register u32 res;   /* all operands in native machine order */
480     register u32 bc;
481 
482     res = d - s;
483     CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
484     CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
485     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
486 
487     /* calculate the borrow chain.  See note at top */
488     bc = (res & (~d | s)) | (~d & s);
489     CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
490     CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
491     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
492     return d;
493 }
494 
495 /****************************************************************************
496 REMARKS:
497 Implements the DAA instruction and side effects.
498 ****************************************************************************/
daa_byte(u8 d)499 u8 daa_byte(u8 d)
500 {
501     u32 res = d;
502     if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
503         res += 6;
504         SET_FLAG(F_AF);
505     }
506     if (res > 0x9F || ACCESS_FLAG(F_CF)) {
507         res += 0x60;
508         SET_FLAG(F_CF);
509     }
510     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
511     CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
512     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
513     return (u8)res;
514 }
515 
516 /****************************************************************************
517 REMARKS:
518 Implements the DAS instruction and side effects.
519 ****************************************************************************/
das_byte(u8 d)520 u8 das_byte(u8 d)
521 {
522     if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
523         d -= 6;
524         SET_FLAG(F_AF);
525     }
526     if (d > 0x9F || ACCESS_FLAG(F_CF)) {
527         d -= 0x60;
528         SET_FLAG(F_CF);
529     }
530     CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
531     CONDITIONAL_SET_FLAG(d == 0, F_ZF);
532     CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
533     return d;
534 }
535 
536 /****************************************************************************
537 REMARKS:
538 Implements the DEC instruction and side effects.
539 ****************************************************************************/
dec_byte(u8 d)540 u8 dec_byte(u8 d)
541 {
542     register u32 res;   /* all operands in native machine order */
543     register u32 bc;
544 
545     res = d - 1;
546     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
547     CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
548     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
549 
550     /* calculate the borrow chain.  See note at top */
551     /* based on sub_byte, uses s==1.  */
552     bc = (res & (~d | 1)) | (~d & 1);
553     /* carry flag unchanged */
554     CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
555     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
556     return (u8)res;
557 }
558 
559 /****************************************************************************
560 REMARKS:
561 Implements the DEC instruction and side effects.
562 ****************************************************************************/
dec_word(u16 d)563 u16 dec_word(u16 d)
564 {
565     register u32 res;   /* all operands in native machine order */
566     register u32 bc;
567 
568     res = d - 1;
569     CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
570     CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
571     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
572 
573     /* calculate the borrow chain.  See note at top */
574     /* based on the sub_byte routine, with s==1 */
575     bc = (res & (~d | 1)) | (~d & 1);
576     /* carry flag unchanged */
577     CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
578     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
579     return (u16)res;
580 }
581 
582 /****************************************************************************
583 REMARKS:
584 Implements the DEC instruction and side effects.
585 ****************************************************************************/
dec_long(u32 d)586 u32 dec_long(u32 d)
587 {
588     register u32 res;   /* all operands in native machine order */
589     register u32 bc;
590 
591     res = d - 1;
592 
593     CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
594     CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
595     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
596 
597     /* calculate the borrow chain.  See note at top */
598     bc = (res & (~d | 1)) | (~d & 1);
599     /* carry flag unchanged */
600     CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
601     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
602     return res;
603 }
604 
605 /****************************************************************************
606 REMARKS:
607 Implements the INC instruction and side effects.
608 ****************************************************************************/
inc_byte(u8 d)609 u8 inc_byte(u8 d)
610 {
611     register u32 res;   /* all operands in native machine order */
612     register u32 cc;
613 
614     res = d + 1;
615     CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
616     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
617     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
618 
619     /* calculate the carry chain  SEE NOTE AT TOP. */
620     cc = ((1 & d) | (~res)) & (1 | d);
621     CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
622     CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
623     return (u8)res;
624 }
625 
626 /****************************************************************************
627 REMARKS:
628 Implements the INC instruction and side effects.
629 ****************************************************************************/
inc_word(u16 d)630 u16 inc_word(u16 d)
631 {
632     register u32 res;   /* all operands in native machine order */
633     register u32 cc;
634 
635     res = d + 1;
636     CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
637     CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
638     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
639 
640     /* calculate the carry chain  SEE NOTE AT TOP. */
641     cc = (1 & d) | ((~res) & (1 | d));
642     CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
643     CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
644     return (u16)res;
645 }
646 
647 /****************************************************************************
648 REMARKS:
649 Implements the INC instruction and side effects.
650 ****************************************************************************/
inc_long(u32 d)651 u32 inc_long(u32 d)
652 {
653     register u32 res;   /* all operands in native machine order */
654     register u32 cc;
655 
656     res = d + 1;
657     CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
658     CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
659     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
660 
661     /* calculate the carry chain  SEE NOTE AT TOP. */
662     cc = (1 & d) | ((~res) & (1 | d));
663     CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
664     CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
665     return res;
666 }
667 
668 /****************************************************************************
669 REMARKS:
670 Implements the OR instruction and side effects.
671 ****************************************************************************/
or_byte(u8 d,u8 s)672 u8 or_byte(u8 d, u8 s)
673 {
674     register u8 res;    /* all operands in native machine order */
675 
676     res = d | s;
677     CLEAR_FLAG(F_OF);
678     CLEAR_FLAG(F_CF);
679     CLEAR_FLAG(F_AF);
680     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
681     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
682     CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
683     return res;
684 }
685 
686 /****************************************************************************
687 REMARKS:
688 Implements the OR instruction and side effects.
689 ****************************************************************************/
or_word(u16 d,u16 s)690 u16 or_word(u16 d, u16 s)
691 {
692     register u16 res;   /* all operands in native machine order */
693 
694     res = d | s;
695     /* set the carry flag to be bit 8 */
696     CLEAR_FLAG(F_OF);
697     CLEAR_FLAG(F_CF);
698     CLEAR_FLAG(F_AF);
699     CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
700     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
701     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
702     return res;
703 }
704 
705 /****************************************************************************
706 REMARKS:
707 Implements the OR instruction and side effects.
708 ****************************************************************************/
or_long(u32 d,u32 s)709 u32 or_long(u32 d, u32 s)
710 {
711     register u32 res;   /* all operands in native machine order */
712 
713     res = d | s;
714 
715     /* set the carry flag to be bit 8 */
716     CLEAR_FLAG(F_OF);
717     CLEAR_FLAG(F_CF);
718     CLEAR_FLAG(F_AF);
719     CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
720     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
721     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
722     return res;
723 }
724 
725 /****************************************************************************
726 REMARKS:
727 Implements the OR instruction and side effects.
728 ****************************************************************************/
neg_byte(u8 s)729 u8 neg_byte(u8 s)
730 {
731     register u8 res;
732     register u8 bc;
733 
734     CONDITIONAL_SET_FLAG(s != 0, F_CF);
735     res = (u8)-s;
736     CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
737     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
738     CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
739     /* calculate the borrow chain --- modified such that d=0.
740        substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
741        (the one used for sub) and simplifying, since ~d=0xff...,
742        ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
743        ~d&s == s.  So the simplified result is: */
744     bc = res | s;
745     CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
746     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
747     return res;
748 }
749 
750 /****************************************************************************
751 REMARKS:
752 Implements the OR instruction and side effects.
753 ****************************************************************************/
neg_word(u16 s)754 u16 neg_word(u16 s)
755 {
756     register u16 res;
757     register u16 bc;
758 
759     CONDITIONAL_SET_FLAG(s != 0, F_CF);
760     res = (u16)-s;
761     CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
762     CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
763     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
764 
765     /* calculate the borrow chain --- modified such that d=0.
766        substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
767        (the one used for sub) and simplifying, since ~d=0xff...,
768        ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
769        ~d&s == s.  So the simplified result is: */
770     bc = res | s;
771     CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
772     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
773     return res;
774 }
775 
776 /****************************************************************************
777 REMARKS:
778 Implements the OR instruction and side effects.
779 ****************************************************************************/
neg_long(u32 s)780 u32 neg_long(u32 s)
781 {
782     register u32 res;
783     register u32 bc;
784 
785     CONDITIONAL_SET_FLAG(s != 0, F_CF);
786     res = (u32)-s;
787     CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
788     CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
789     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
790 
791     /* calculate the borrow chain --- modified such that d=0.
792        substitutiing d=0 into     bc= res&(~d|s)|(~d&s);
793        (the one used for sub) and simplifying, since ~d=0xff...,
794        ~d|s == 0xffff..., and res&0xfff... == res.  Similarly
795        ~d&s == s.  So the simplified result is: */
796     bc = res | s;
797     CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
798     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
799     return res;
800 }
801 
802 /****************************************************************************
803 REMARKS:
804 Implements the NOT instruction and side effects.
805 ****************************************************************************/
not_byte(u8 s)806 u8 not_byte(u8 s)
807 {
808     return ~s;
809 }
810 
811 /****************************************************************************
812 REMARKS:
813 Implements the NOT instruction and side effects.
814 ****************************************************************************/
not_word(u16 s)815 u16 not_word(u16 s)
816 {
817     return ~s;
818 }
819 
820 /****************************************************************************
821 REMARKS:
822 Implements the NOT instruction and side effects.
823 ****************************************************************************/
not_long(u32 s)824 u32 not_long(u32 s)
825 {
826     return ~s;
827 }
828 
829 /****************************************************************************
830 REMARKS:
831 Implements the RCL instruction and side effects.
832 ****************************************************************************/
rcl_byte(u8 d,u8 s)833 u8 rcl_byte(u8 d, u8 s)
834 {
835     register unsigned int res, cnt, mask, cf;
836 
837     /* s is the rotate distance.  It varies from 0 - 8. */
838     /* have
839 
840        CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
841 
842        want to rotate through the carry by "s" bits.  We could
843        loop, but that's inefficient.  So the width is 9,
844        and we split into three parts:
845 
846        The new carry flag   (was B_n)
847        the stuff in B_n-1 .. B_0
848        the stuff in B_7 .. B_n+1
849 
850        The new rotate is done mod 9, and given this,
851        for a rotation of n bits (mod 9) the new carry flag is
852        then located n bits from the MSB.  The low part is
853        then shifted up cnt bits, and the high part is or'd
854        in.  Using CAPS for new values, and lowercase for the
855        original values, this can be expressed as:
856 
857        IF n > 0
858        1) CF <-  b_(8-n)
859        2) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0
860        3) B_(n-1) <- cf
861        4) B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1))
862      */
863     res = d;
864     if ((cnt = s % 9) != 0) {
865         /* extract the new CARRY FLAG. */
866         /* CF <-  b_(8-n)             */
867         cf = (d >> (8 - cnt)) & 0x1;
868 
869         /* get the low stuff which rotated
870            into the range B_7 .. B_cnt */
871         /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_0  */
872         /* note that the right hand side done by the mask */
873         res = (d << cnt) & 0xff;
874 
875         /* now the high stuff which rotated around
876            into the positions B_cnt-2 .. B_0 */
877         /* B_(n-2) .. B_0 <-  b_7 .. b_(8-(n-1)) */
878         /* shift it downward, 7-(n-2) = 9-n positions.
879            and mask off the result before or'ing in.
880          */
881         mask = (1 << (cnt - 1)) - 1;
882         res |= (d >> (9 - cnt)) & mask;
883 
884         /* if the carry flag was set, or it in.  */
885         if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
886             /*  B_(n-1) <- cf */
887             res |= 1 << (cnt - 1);
888         }
889         /* set the new carry flag, based on the variable "cf" */
890         CONDITIONAL_SET_FLAG(cf, F_CF);
891         /* OVERFLOW is set *IFF* cnt==1, then it is the
892            xor of CF and the most significant bit.  Blecck. */
893         /* parenthesized this expression since it appears to
894            be causing OF to be misset */
895         CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
896                              F_OF);
897 
898     }
899     return (u8)res;
900 }
901 
902 /****************************************************************************
903 REMARKS:
904 Implements the RCL instruction and side effects.
905 ****************************************************************************/
rcl_word(u16 d,u8 s)906 u16 rcl_word(u16 d, u8 s)
907 {
908     register unsigned int res, cnt, mask, cf;
909 
910     res = d;
911     if ((cnt = s % 17) != 0) {
912         cf = (d >> (16 - cnt)) & 0x1;
913         res = (d << cnt) & 0xffff;
914         mask = (1 << (cnt - 1)) - 1;
915         res |= (d >> (17 - cnt)) & mask;
916         if (ACCESS_FLAG(F_CF)) {
917             res |= 1 << (cnt - 1);
918         }
919         CONDITIONAL_SET_FLAG(cf, F_CF);
920         CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
921                              F_OF);
922     }
923     return (u16)res;
924 }
925 
926 /****************************************************************************
927 REMARKS:
928 Implements the RCL instruction and side effects.
929 ****************************************************************************/
rcl_long(u32 d,u8 s)930 u32 rcl_long(u32 d, u8 s)
931 {
932     register u32 res, cnt, mask, cf;
933 
934     res = d;
935     if ((cnt = s % 33) != 0) {
936         cf = (d >> (32 - cnt)) & 0x1;
937         res = (d << cnt) & 0xffffffff;
938         mask = (1 << (cnt - 1)) - 1;
939         res |= (d >> (33 - cnt)) & mask;
940         if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
941             res |= 1 << (cnt - 1);
942         }
943         CONDITIONAL_SET_FLAG(cf, F_CF);
944         CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
945                              F_OF);
946     }
947     return res;
948 }
949 
950 /****************************************************************************
951 REMARKS:
952 Implements the RCR instruction and side effects.
953 ****************************************************************************/
rcr_byte(u8 d,u8 s)954 u8 rcr_byte(u8 d, u8 s)
955 {
956     u32 res, cnt;
957     u32 mask, cf, ocf = 0;
958 
959     /* rotate right through carry */
960     /*
961        s is the rotate distance.  It varies from 0 - 8.
962        d is the byte object rotated.
963 
964        have
965 
966        CF  B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
967 
968        The new rotate is done mod 9, and given this,
969        for a rotation of n bits (mod 9) the new carry flag is
970        then located n bits from the LSB.  The low part is
971        then shifted up cnt bits, and the high part is or'd
972        in.  Using CAPS for new values, and lowercase for the
973        original values, this can be expressed as:
974 
975        IF n > 0
976        1) CF <-  b_(n-1)
977        2) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
978        3) B_(8-n) <- cf
979        4) B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0)
980      */
981     res = d;
982     if ((cnt = s % 9) != 0) {
983         /* extract the new CARRY FLAG. */
984         /* CF <-  b_(n-1)              */
985         if (cnt == 1) {
986             cf = d & 0x1;
987             /* note hackery here.  Access_flag(..) evaluates to either
988                0 if flag not set
989                non-zero if flag is set.
990                doing access_flag(..) != 0 casts that into either
991                0..1 in any representation of the flags register
992                (i.e. packed bit array or unpacked.)
993              */
994             ocf = ACCESS_FLAG(F_CF) != 0;
995         } else
996             cf = (d >> (cnt - 1)) & 0x1;
997 
998         /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_n  */
999         /* note that the right hand side done by the mask
1000            This is effectively done by shifting the
1001            object to the right.  The result must be masked,
1002            in case the object came in and was treated
1003            as a negative number.  Needed??? */
1004 
1005         mask = (1 << (8 - cnt)) - 1;
1006         res = (d >> cnt) & mask;
1007 
1008         /* now the high stuff which rotated around
1009            into the positions B_cnt-2 .. B_0 */
1010         /* B_(7) .. B_(8-(n-1)) <-  b_(n-2) .. b_(0) */
1011         /* shift it downward, 7-(n-2) = 9-n positions.
1012            and mask off the result before or'ing in.
1013          */
1014         res |= (d << (9 - cnt));
1015 
1016         /* if the carry flag was set, or it in.  */
1017         if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
1018             /*  B_(8-n) <- cf */
1019             res |= 1 << (8 - cnt);
1020         }
1021         /* set the new carry flag, based on the variable "cf" */
1022         CONDITIONAL_SET_FLAG(cf, F_CF);
1023         /* OVERFLOW is set *IFF* cnt==1, then it is the
1024            xor of CF and the most significant bit.  Blecck. */
1025         /* parenthesized... */
1026         if (cnt == 1) {
1027             CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
1028                                  F_OF);
1029         }
1030     }
1031     return (u8)res;
1032 }
1033 
1034 /****************************************************************************
1035 REMARKS:
1036 Implements the RCR instruction and side effects.
1037 ****************************************************************************/
rcr_word(u16 d,u8 s)1038 u16 rcr_word(u16 d, u8 s)
1039 {
1040     u32 res, cnt;
1041     u32 mask, cf, ocf = 0;
1042 
1043     /* rotate right through carry */
1044     res = d;
1045     if ((cnt = s % 17) != 0) {
1046         if (cnt == 1) {
1047             cf = d & 0x1;
1048             ocf = ACCESS_FLAG(F_CF) != 0;
1049         } else
1050             cf = (d >> (cnt - 1)) & 0x1;
1051         mask = (1 << (16 - cnt)) - 1;
1052         res = (d >> cnt) & mask;
1053         res |= (d << (17 - cnt));
1054         if (ACCESS_FLAG(F_CF)) {
1055             res |= 1 << (16 - cnt);
1056         }
1057         CONDITIONAL_SET_FLAG(cf, F_CF);
1058         if (cnt == 1) {
1059             CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
1060                                  F_OF);
1061         }
1062     }
1063     return (u16)res;
1064 }
1065 
1066 /****************************************************************************
1067 REMARKS:
1068 Implements the RCR instruction and side effects.
1069 ****************************************************************************/
rcr_long(u32 d,u8 s)1070 u32 rcr_long(u32 d, u8 s)
1071 {
1072     u32 res, cnt;
1073     u32 mask, cf, ocf = 0;
1074 
1075     /* rotate right through carry */
1076     res = d;
1077     if ((cnt = s % 33) != 0) {
1078         if (cnt == 1) {
1079             cf = d & 0x1;
1080             ocf = ACCESS_FLAG(F_CF) != 0;
1081         } else
1082             cf = (d >> (cnt - 1)) & 0x1;
1083         mask = (1 << (32 - cnt)) - 1;
1084         res = (d >> cnt) & mask;
1085         if (cnt != 1)
1086             res |= (d << (33 - cnt));
1087         if (ACCESS_FLAG(F_CF)) {     /* carry flag is set */
1088             res |= 1 << (32 - cnt);
1089         }
1090         CONDITIONAL_SET_FLAG(cf, F_CF);
1091         if (cnt == 1) {
1092             CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
1093                                  F_OF);
1094         }
1095     }
1096     return res;
1097 }
1098 
1099 /****************************************************************************
1100 REMARKS:
1101 Implements the ROL instruction and side effects.
1102 ****************************************************************************/
rol_byte(u8 d,u8 s)1103 u8 rol_byte(u8 d, u8 s)
1104 {
1105     register unsigned int res, cnt, mask;
1106 
1107     /* rotate left */
1108     /*
1109        s is the rotate distance.  It varies from 0 - 8.
1110        d is the byte object rotated.
1111 
1112        have
1113 
1114        CF  B_7 ... B_0
1115 
1116        The new rotate is done mod 8.
1117        Much simpler than the "rcl" or "rcr" operations.
1118 
1119        IF n > 0
1120        1) B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0)
1121        2) B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n)
1122      */
1123     res = d;
1124     if ((cnt = s % 8) != 0) {
1125         /* B_(7) .. B_(n)  <-  b_(8-(n+1)) .. b_(0) */
1126         res = (d << cnt);
1127 
1128         /* B_(n-1) .. B_(0) <-  b_(7) .. b_(8-n) */
1129         mask = (1 << cnt) - 1;
1130         res |= (d >> (8 - cnt)) & mask;
1131 
1132         /* set the new carry flag, Note that it is the low order
1133            bit of the result!!!                               */
1134         CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1135         /* OVERFLOW is set *IFF* s==1, then it is the
1136            xor of CF and the most significant bit.  Blecck. */
1137         CONDITIONAL_SET_FLAG(s == 1 &&
1138                              XOR2((res & 0x1) + ((res >> 6) & 0x2)),
1139                              F_OF);
1140     } if (s != 0) {
1141         /* set the new carry flag, Note that it is the low order
1142            bit of the result!!!                               */
1143         CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1144     }
1145     return (u8)res;
1146 }
1147 
1148 /****************************************************************************
1149 REMARKS:
1150 Implements the ROL instruction and side effects.
1151 ****************************************************************************/
rol_word(u16 d,u8 s)1152 u16 rol_word(u16 d, u8 s)
1153 {
1154     register unsigned int res, cnt, mask;
1155 
1156     res = d;
1157     if ((cnt = s % 16) != 0) {
1158         res = (d << cnt);
1159         mask = (1 << cnt) - 1;
1160         res |= (d >> (16 - cnt)) & mask;
1161         CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1162         CONDITIONAL_SET_FLAG(s == 1 &&
1163                              XOR2((res & 0x1) + ((res >> 14) & 0x2)),
1164                              F_OF);
1165     } if (s != 0) {
1166         /* set the new carry flag, Note that it is the low order
1167            bit of the result!!!                               */
1168         CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1169     }
1170     return (u16)res;
1171 }
1172 
1173 /****************************************************************************
1174 REMARKS:
1175 Implements the ROL instruction and side effects.
1176 ****************************************************************************/
rol_long(u32 d,u8 s)1177 u32 rol_long(u32 d, u8 s)
1178 {
1179     register u32 res, cnt, mask;
1180 
1181     res = d;
1182     if ((cnt = s % 32) != 0) {
1183         res = (d << cnt);
1184         mask = (1 << cnt) - 1;
1185         res |= (d >> (32 - cnt)) & mask;
1186         CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1187         CONDITIONAL_SET_FLAG(s == 1 &&
1188                              XOR2((res & 0x1) + ((res >> 30) & 0x2)),
1189                              F_OF);
1190     } if (s != 0) {
1191         /* set the new carry flag, Note that it is the low order
1192            bit of the result!!!                               */
1193         CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1194     }
1195     return res;
1196 }
1197 
1198 /****************************************************************************
1199 REMARKS:
1200 Implements the ROR instruction and side effects.
1201 ****************************************************************************/
ror_byte(u8 d,u8 s)1202 u8 ror_byte(u8 d, u8 s)
1203 {
1204     register unsigned int res, cnt, mask;
1205 
1206     /* rotate right */
1207     /*
1208        s is the rotate distance.  It varies from 0 - 8.
1209        d is the byte object rotated.
1210 
1211        have
1212 
1213        B_7 ... B_0
1214 
1215        The rotate is done mod 8.
1216 
1217        IF n > 0
1218        1) B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n)
1219        2) B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0)
1220      */
1221     res = d;
1222     if ((cnt = s % 8) != 0) {           /* not a typo, do nada if cnt==0 */
1223         /* B_(7) .. B_(8-n) <-  b_(n-1) .. b_(0) */
1224         res = (d << (8 - cnt));
1225 
1226         /* B_(8-(n+1)) .. B_(0)  <-  b_(7) .. b_(n) */
1227         mask = (1 << (8 - cnt)) - 1;
1228         res |= (d >> (cnt)) & mask;
1229 
1230         /* set the new carry flag, Note that it is the low order
1231            bit of the result!!!                               */
1232         CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1233         /* OVERFLOW is set *IFF* s==1, then it is the
1234            xor of the two most significant bits.  Blecck. */
1235         CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
1236     } else if (s != 0) {
1237         /* set the new carry flag, Note that it is the low order
1238            bit of the result!!!                               */
1239         CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1240     }
1241     return (u8)res;
1242 }
1243 
1244 /****************************************************************************
1245 REMARKS:
1246 Implements the ROR instruction and side effects.
1247 ****************************************************************************/
ror_word(u16 d,u8 s)1248 u16 ror_word(u16 d, u8 s)
1249 {
1250     register unsigned int res, cnt, mask;
1251 
1252     res = d;
1253     if ((cnt = s % 16) != 0) {
1254         res = (d << (16 - cnt));
1255         mask = (1 << (16 - cnt)) - 1;
1256         res |= (d >> (cnt)) & mask;
1257         CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1258         CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
1259     } else if (s != 0) {
1260         /* set the new carry flag, Note that it is the low order
1261            bit of the result!!!                               */
1262         CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1263     }
1264     return (u16)res;
1265 }
1266 
1267 /****************************************************************************
1268 REMARKS:
1269 Implements the ROR instruction and side effects.
1270 ****************************************************************************/
ror_long(u32 d,u8 s)1271 u32 ror_long(u32 d, u8 s)
1272 {
1273     register u32 res, cnt, mask;
1274 
1275     res = d;
1276     if ((cnt = s % 32) != 0) {
1277         res = (d << (32 - cnt));
1278         mask = (1 << (32 - cnt)) - 1;
1279         res |= (d >> (cnt)) & mask;
1280         CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1281         CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
1282     } else if (s != 0) {
1283         /* set the new carry flag, Note that it is the low order
1284            bit of the result!!!                               */
1285         CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1286     }
1287     return res;
1288 }
1289 
1290 /****************************************************************************
1291 REMARKS:
1292 Implements the SHL instruction and side effects.
1293 ****************************************************************************/
shl_byte(u8 d,u8 s)1294 u8 shl_byte(u8 d, u8 s)
1295 {
1296     unsigned int cnt, res, cf;
1297 
1298     if (s < 8) {
1299         cnt = s % 8;
1300 
1301         /* last bit shifted out goes into carry flag */
1302         if (cnt > 0) {
1303             res = d << cnt;
1304             cf = d & (1 << (8 - cnt));
1305             CONDITIONAL_SET_FLAG(cf, F_CF);
1306             CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1307             CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1308             CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1309         } else {
1310             res = (u8) d;
1311         }
1312 
1313         if (cnt == 1) {
1314             /* Needs simplification. */
1315             CONDITIONAL_SET_FLAG(
1316                                     (((res & 0x80) == 0x80) ^
1317                                      (ACCESS_FLAG(F_CF) != 0)),
1318             /* was (M.x86.R_FLG&F_CF)==F_CF)), */
1319                                     F_OF);
1320         } else {
1321             CLEAR_FLAG(F_OF);
1322         }
1323     } else {
1324         res = 0;
1325         CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
1326         CLEAR_FLAG(F_OF);
1327         CLEAR_FLAG(F_SF);
1328         SET_FLAG(F_PF);
1329         SET_FLAG(F_ZF);
1330     }
1331     return (u8)res;
1332 }
1333 
1334 /****************************************************************************
1335 REMARKS:
1336 Implements the SHL instruction and side effects.
1337 ****************************************************************************/
shl_word(u16 d,u8 s)1338 u16 shl_word(u16 d, u8 s)
1339 {
1340     unsigned int cnt, res, cf;
1341 
1342     if (s < 16) {
1343         cnt = s % 16;
1344         if (cnt > 0) {
1345             res = d << cnt;
1346             cf = d & (1 << (16 - cnt));
1347             CONDITIONAL_SET_FLAG(cf, F_CF);
1348             CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1349             CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1350             CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1351         } else {
1352             res = (u16) d;
1353         }
1354 
1355         if (cnt == 1) {
1356             CONDITIONAL_SET_FLAG(
1357                                     (((res & 0x8000) == 0x8000) ^
1358                                      (ACCESS_FLAG(F_CF) != 0)),
1359                                     F_OF);
1360         } else {
1361             CLEAR_FLAG(F_OF);
1362         }
1363     } else {
1364         res = 0;
1365         CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1366         CLEAR_FLAG(F_OF);
1367         CLEAR_FLAG(F_SF);
1368         SET_FLAG(F_PF);
1369         SET_FLAG(F_ZF);
1370     }
1371     return (u16)res;
1372 }
1373 
1374 /****************************************************************************
1375 REMARKS:
1376 Implements the SHL instruction and side effects.
1377 ****************************************************************************/
shl_long(u32 d,u8 s)1378 u32 shl_long(u32 d, u8 s)
1379 {
1380     unsigned int cnt, res, cf;
1381 
1382     if (s < 32) {
1383         cnt = s % 32;
1384         if (cnt > 0) {
1385             res = d << cnt;
1386             cf = d & (1 << (32 - cnt));
1387             CONDITIONAL_SET_FLAG(cf, F_CF);
1388             CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1389             CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1390             CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1391         } else {
1392             res = d;
1393         }
1394         if (cnt == 1) {
1395             CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1396                                   (ACCESS_FLAG(F_CF) != 0)), F_OF);
1397         } else {
1398             CLEAR_FLAG(F_OF);
1399         }
1400     } else {
1401         res = 0;
1402         CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1403         CLEAR_FLAG(F_OF);
1404         CLEAR_FLAG(F_SF);
1405         SET_FLAG(F_PF);
1406         SET_FLAG(F_ZF);
1407     }
1408     return res;
1409 }
1410 
1411 /****************************************************************************
1412 REMARKS:
1413 Implements the SHR instruction and side effects.
1414 ****************************************************************************/
shr_byte(u8 d,u8 s)1415 u8 shr_byte(u8 d, u8 s)
1416 {
1417     unsigned int cnt, res, cf;
1418 
1419     if (s < 8) {
1420         cnt = s % 8;
1421         if (cnt > 0) {
1422             cf = d & (1 << (cnt - 1));
1423             res = d >> cnt;
1424             CONDITIONAL_SET_FLAG(cf, F_CF);
1425             CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1426             CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1427             CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1428         } else {
1429             res = (u8) d;
1430         }
1431 
1432         if (cnt == 1) {
1433             CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1434         } else {
1435             CLEAR_FLAG(F_OF);
1436         }
1437     } else {
1438         res = 0;
1439         CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
1440         CLEAR_FLAG(F_OF);
1441         CLEAR_FLAG(F_SF);
1442         SET_FLAG(F_PF);
1443         SET_FLAG(F_ZF);
1444     }
1445     return (u8)res;
1446 }
1447 
1448 /****************************************************************************
1449 REMARKS:
1450 Implements the SHR instruction and side effects.
1451 ****************************************************************************/
shr_word(u16 d,u8 s)1452 u16 shr_word(u16 d, u8 s)
1453 {
1454     unsigned int cnt, res, cf;
1455 
1456     if (s < 16) {
1457         cnt = s % 16;
1458         if (cnt > 0) {
1459             cf = d & (1 << (cnt - 1));
1460             res = d >> cnt;
1461             CONDITIONAL_SET_FLAG(cf, F_CF);
1462             CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1463             CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1464             CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1465         } else {
1466             res = d;
1467         }
1468 
1469         if (cnt == 1) {
1470             CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1471         } else {
1472             CLEAR_FLAG(F_OF);
1473         }
1474     } else {
1475         res = 0;
1476         CLEAR_FLAG(F_CF);
1477         CLEAR_FLAG(F_OF);
1478         SET_FLAG(F_ZF);
1479         CLEAR_FLAG(F_SF);
1480         CLEAR_FLAG(F_PF);
1481     }
1482     return (u16)res;
1483 }
1484 
1485 /****************************************************************************
1486 REMARKS:
1487 Implements the SHR instruction and side effects.
1488 ****************************************************************************/
shr_long(u32 d,u8 s)1489 u32 shr_long(u32 d, u8 s)
1490 {
1491     unsigned int cnt, res, cf;
1492 
1493     if (s < 32) {
1494         cnt = s % 32;
1495         if (cnt > 0) {
1496             cf = d & (1 << (cnt - 1));
1497             res = d >> cnt;
1498             CONDITIONAL_SET_FLAG(cf, F_CF);
1499             CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1500             CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1501             CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1502         } else {
1503             res = d;
1504         }
1505         if (cnt == 1) {
1506             CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1507         } else {
1508             CLEAR_FLAG(F_OF);
1509         }
1510     } else {
1511         res = 0;
1512         CLEAR_FLAG(F_CF);
1513         CLEAR_FLAG(F_OF);
1514         SET_FLAG(F_ZF);
1515         CLEAR_FLAG(F_SF);
1516         CLEAR_FLAG(F_PF);
1517     }
1518     return res;
1519 }
1520 
1521 /****************************************************************************
1522 REMARKS:
1523 Implements the SAR instruction and side effects.
1524 ****************************************************************************/
sar_byte(u8 d,u8 s)1525 u8 sar_byte(u8 d, u8 s)
1526 {
1527     unsigned int cnt, res, cf, mask, sf;
1528 
1529     res = d;
1530     sf = d & 0x80;
1531     cnt = s % 8;
1532     if (cnt > 0 && cnt < 8) {
1533         mask = (1 << (8 - cnt)) - 1;
1534         cf = d & (1 << (cnt - 1));
1535         res = (d >> cnt) & mask;
1536         CONDITIONAL_SET_FLAG(cf, F_CF);
1537         if (sf) {
1538             res |= ~mask;
1539         }
1540         CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1541         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1542         CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1543     } else if (cnt >= 8) {
1544         if (sf) {
1545             res = 0xff;
1546             SET_FLAG(F_CF);
1547             CLEAR_FLAG(F_ZF);
1548             SET_FLAG(F_SF);
1549             SET_FLAG(F_PF);
1550         } else {
1551             res = 0;
1552             CLEAR_FLAG(F_CF);
1553             SET_FLAG(F_ZF);
1554             CLEAR_FLAG(F_SF);
1555             CLEAR_FLAG(F_PF);
1556         }
1557     }
1558     return (u8)res;
1559 }
1560 
1561 /****************************************************************************
1562 REMARKS:
1563 Implements the SAR instruction and side effects.
1564 ****************************************************************************/
sar_word(u16 d,u8 s)1565 u16 sar_word(u16 d, u8 s)
1566 {
1567     unsigned int cnt, res, cf, mask, sf;
1568 
1569     sf = d & 0x8000;
1570     cnt = s % 16;
1571     res = d;
1572     if (cnt > 0 && cnt < 16) {
1573         mask = (1 << (16 - cnt)) - 1;
1574         cf = d & (1 << (cnt - 1));
1575         res = (d >> cnt) & mask;
1576         CONDITIONAL_SET_FLAG(cf, F_CF);
1577         if (sf) {
1578             res |= ~mask;
1579         }
1580         CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1581         CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1582         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1583     } else if (cnt >= 16) {
1584         if (sf) {
1585             res = 0xffff;
1586             SET_FLAG(F_CF);
1587             CLEAR_FLAG(F_ZF);
1588             SET_FLAG(F_SF);
1589             SET_FLAG(F_PF);
1590         } else {
1591             res = 0;
1592             CLEAR_FLAG(F_CF);
1593             SET_FLAG(F_ZF);
1594             CLEAR_FLAG(F_SF);
1595             CLEAR_FLAG(F_PF);
1596         }
1597     }
1598     return (u16)res;
1599 }
1600 
1601 /****************************************************************************
1602 REMARKS:
1603 Implements the SAR instruction and side effects.
1604 ****************************************************************************/
sar_long(u32 d,u8 s)1605 u32 sar_long(u32 d, u8 s)
1606 {
1607     u32 cnt, res, cf, mask, sf;
1608 
1609     sf = d & 0x80000000;
1610     cnt = s % 32;
1611     res = d;
1612     if (cnt > 0 && cnt < 32) {
1613         mask = (1 << (32 - cnt)) - 1;
1614         cf = d & (1 << (cnt - 1));
1615         res = (d >> cnt) & mask;
1616         CONDITIONAL_SET_FLAG(cf, F_CF);
1617         if (sf) {
1618             res |= ~mask;
1619         }
1620         CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1621         CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1622         CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1623     } else if (cnt >= 32) {
1624         if (sf) {
1625             res = 0xffffffff;
1626             SET_FLAG(F_CF);
1627             CLEAR_FLAG(F_ZF);
1628             SET_FLAG(F_SF);
1629             SET_FLAG(F_PF);
1630         } else {
1631             res = 0;
1632             CLEAR_FLAG(F_CF);
1633             SET_FLAG(F_ZF);
1634             CLEAR_FLAG(F_SF);
1635             CLEAR_FLAG(F_PF);
1636         }
1637     }
1638     return res;
1639 }
1640 
1641 /****************************************************************************
1642 REMARKS:
1643 Implements the SHLD instruction and side effects.
1644 ****************************************************************************/
1645 #if 0
1646 u16 shld_word (u16 d, u16 fill, u8 s)
1647 {
1648     unsigned int cnt, res, cf;
1649 
1650     if (s < 16) {
1651         cnt = s % 16;
1652         if (cnt > 0) {
1653             res = (d << cnt) | (fill >> (16-cnt));
1654             cf = d & (1 << (16 - cnt));
1655             CONDITIONAL_SET_FLAG(cf, F_CF);
1656             CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1657             CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1658             CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1659         } else {
1660             res = d;
1661         }
1662         if (cnt == 1) {
1663             CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1664                                   (ACCESS_FLAG(F_CF) != 0)), F_OF);
1665         } else {
1666             CLEAR_FLAG(F_OF);
1667         }
1668     } else {
1669         res = 0;
1670         CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1671         CLEAR_FLAG(F_OF);
1672         CLEAR_FLAG(F_SF);
1673         SET_FLAG(F_PF);
1674         SET_FLAG(F_ZF);
1675     }
1676     return (u16)res;
1677 }
1678 #endif
1679 /****************************************************************************
1680 REMARKS:
1681 Implements the SHLD instruction and side effects.
1682 ****************************************************************************/
shld_long(u32 d,u32 fill,u8 s)1683 u32 shld_long (u32 d, u32 fill, u8 s)
1684 {
1685     unsigned int cnt, res, cf;
1686 
1687     if (s < 32) {
1688         cnt = s % 32;
1689         if (cnt > 0) {
1690             res = (d << cnt) | (fill >> (32-cnt));
1691             cf = d & (1 << (32 - cnt));
1692             CONDITIONAL_SET_FLAG(cf, F_CF);
1693             CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1694             CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1695             CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1696         } else {
1697             res = d;
1698         }
1699         if (cnt == 1) {
1700             CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1701                                   (ACCESS_FLAG(F_CF) != 0)), F_OF);
1702         } else {
1703             CLEAR_FLAG(F_OF);
1704         }
1705     } else {
1706         res = 0;
1707         CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1708         CLEAR_FLAG(F_OF);
1709         CLEAR_FLAG(F_SF);
1710         SET_FLAG(F_PF);
1711         SET_FLAG(F_ZF);
1712     }
1713     return res;
1714 }
1715 
1716 /****************************************************************************
1717 REMARKS:
1718 Implements the SHRD instruction and side effects.
1719 ****************************************************************************/
1720 #if 0
1721 u16 shrd_word (u16 d, u16 fill, u8 s)
1722 {
1723     unsigned int cnt, res, cf;
1724 
1725     if (s < 16) {
1726         cnt = s % 16;
1727         if (cnt > 0) {
1728             cf = d & (1 << (cnt - 1));
1729             res = (d >> cnt) | (fill << (16 - cnt));
1730             CONDITIONAL_SET_FLAG(cf, F_CF);
1731             CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1732             CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1733             CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1734         } else {
1735             res = d;
1736         }
1737 
1738         if (cnt == 1) {
1739             CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1740         } else {
1741             CLEAR_FLAG(F_OF);
1742         }
1743     } else {
1744         res = 0;
1745         CLEAR_FLAG(F_CF);
1746         CLEAR_FLAG(F_OF);
1747         SET_FLAG(F_ZF);
1748         CLEAR_FLAG(F_SF);
1749         CLEAR_FLAG(F_PF);
1750     }
1751     return (u16)res;
1752 }
1753 #endif
1754 /****************************************************************************
1755 REMARKS:
1756 Implements the SHRD instruction and side effects.
1757 ****************************************************************************/
shrd_long(u32 d,u32 fill,u8 s)1758 u32 shrd_long (u32 d, u32 fill, u8 s)
1759 {
1760     unsigned int cnt, res, cf;
1761 
1762     if (s < 32) {
1763         cnt = s % 32;
1764         if (cnt > 0) {
1765             cf = d & (1 << (cnt - 1));
1766             res = (d >> cnt) | (fill << (32 - cnt));
1767             CONDITIONAL_SET_FLAG(cf, F_CF);
1768             CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1769             CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1770             CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1771         } else {
1772             res = d;
1773         }
1774         if (cnt == 1) {
1775             CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1776         } else {
1777             CLEAR_FLAG(F_OF);
1778         }
1779     } else {
1780         res = 0;
1781         CLEAR_FLAG(F_CF);
1782         CLEAR_FLAG(F_OF);
1783         SET_FLAG(F_ZF);
1784         CLEAR_FLAG(F_SF);
1785         CLEAR_FLAG(F_PF);
1786     }
1787     return res;
1788 }
1789 
1790 
1791 
1792 
1793 
1794 
1795 
shld_word(u16 d,u16 fill,u8 s)1796 u16 shld_word (u16 d, u16 fill, u8 s)
1797 {
1798     unsigned int cnt, res, cf;
1799 
1800     if (s < 32) {
1801         cnt = s % 32;
1802         if (cnt > 0) {
1803             if (cnt > 15) {
1804                 res = (unsigned int)fill << (cnt - 16);
1805                 if (cnt == 16)
1806                     cf = d & 0x1;
1807                 else
1808                     cf = res & 0x10000;
1809             }
1810             else {
1811                 res = (d << cnt) | (fill >> (16-cnt));
1812                 cf = d & (1 << (16 - cnt));
1813             }
1814             CONDITIONAL_SET_FLAG(cf, F_CF);
1815             CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1816             CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1817             CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1818         } else {
1819             res = d;
1820         }
1821         if (cnt == 1) {
1822             CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1823                                   (ACCESS_FLAG(F_CF) != 0)), F_OF);
1824         } else {
1825             CLEAR_FLAG(F_OF);
1826         }
1827     } else {
1828         res = 0;
1829         CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1830         CLEAR_FLAG(F_OF);
1831         CLEAR_FLAG(F_SF);
1832         SET_FLAG(F_PF);
1833         SET_FLAG(F_ZF);
1834     }
1835     return (u16)res;
1836 }
1837 
1838 
shrd_word(u16 d,u16 fill,u8 s)1839 u16 shrd_word (u16 d, u16 fill, u8 s)
1840 {
1841     unsigned int cnt, res, cf;
1842 
1843     if (s < 32) {
1844         cnt = s % 32;
1845         if (cnt > 0) {
1846             if (cnt > 15) {
1847                 if (cnt == 16)
1848                     cf = d & 0x8000;
1849                 else
1850                     cf = fill & (1 << (cnt - 17));
1851                 res = fill >> (cnt - 16);
1852             } else {
1853                 cf = d & (1 << (cnt - 1));
1854                 res = (d >> cnt) | (fill << (16 - cnt));
1855             }
1856             CONDITIONAL_SET_FLAG(cf, F_CF);
1857             CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1858             CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1859             CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1860         } else {
1861             res = d;
1862         }
1863 
1864         if (cnt == 1) {
1865             CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1866         } else {
1867             CLEAR_FLAG(F_OF);
1868         }
1869     } else {
1870         res = 0;
1871         CLEAR_FLAG(F_CF);
1872         CLEAR_FLAG(F_OF);
1873         SET_FLAG(F_ZF);
1874         CLEAR_FLAG(F_SF);
1875         CLEAR_FLAG(F_PF);
1876     }
1877     return (u16)res;
1878 }
1879 
1880 /***************************************************************************
1881 REMARKS:
1882 Implements the SBB instruction and side effects.
1883 ****************************************************************************/
sbb_byte(u8 d,u8 s)1884 u8 sbb_byte(u8 d, u8 s)
1885 {
1886     register u32 res;   /* all operands in native machine order */
1887     register u32 bc;
1888 
1889     if (ACCESS_FLAG(F_CF))
1890         res = d - s - 1;
1891     else
1892         res = d - s;
1893     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1894     CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1895     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1896 
1897     /* calculate the borrow chain.  See note at top */
1898     bc = (res & (~d | s)) | (~d & s);
1899     CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1900     CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1901     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1902     return (u8)res;
1903 }
1904 
1905 /****************************************************************************
1906 REMARKS:
1907 Implements the SBB instruction and side effects.
1908 ****************************************************************************/
sbb_word(u16 d,u16 s)1909 u16 sbb_word(u16 d, u16 s)
1910 {
1911     register u32 res;   /* all operands in native machine order */
1912     register u32 bc;
1913 
1914     if (ACCESS_FLAG(F_CF))
1915         res = d - s - 1;
1916     else
1917         res = d - s;
1918     CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1919     CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1920     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1921 
1922     /* calculate the borrow chain.  See note at top */
1923     bc = (res & (~d | s)) | (~d & s);
1924     CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1925     CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1926     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1927     return (u16)res;
1928 }
1929 
1930 /****************************************************************************
1931 REMARKS:
1932 Implements the SBB instruction and side effects.
1933 ****************************************************************************/
sbb_long(u32 d,u32 s)1934 u32 sbb_long(u32 d, u32 s)
1935 {
1936     register u32 res;   /* all operands in native machine order */
1937     register u32 bc;
1938 
1939     if (ACCESS_FLAG(F_CF))
1940         res = d - s - 1;
1941     else
1942         res = d - s;
1943     CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1944     CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1945     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1946 
1947     /* calculate the borrow chain.  See note at top */
1948     bc = (res & (~d | s)) | (~d & s);
1949     CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1950     CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1951     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1952     return res;
1953 }
1954 
1955 /****************************************************************************
1956 REMARKS:
1957 Implements the SUB instruction and side effects.
1958 ****************************************************************************/
sub_byte(u8 d,u8 s)1959 u8 sub_byte(u8 d, u8 s)
1960 {
1961     register u32 res;   /* all operands in native machine order */
1962     register u32 bc;
1963 
1964     res = d - s;
1965     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1966     CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1967     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1968 
1969     /* calculate the borrow chain.  See note at top */
1970     bc = (res & (~d | s)) | (~d & s);
1971     CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1972     CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1973     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1974     return (u8)res;
1975 }
1976 
1977 /****************************************************************************
1978 REMARKS:
1979 Implements the SUB instruction and side effects.
1980 ****************************************************************************/
sub_word(u16 d,u16 s)1981 u16 sub_word(u16 d, u16 s)
1982 {
1983     register u32 res;   /* all operands in native machine order */
1984     register u32 bc;
1985 
1986     res = d - s;
1987     CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1988     CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1989     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1990 
1991     /* calculate the borrow chain.  See note at top */
1992     bc = (res & (~d | s)) | (~d & s);
1993     CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1994     CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1995     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1996     return (u16)res;
1997 }
1998 
1999 /****************************************************************************
2000 REMARKS:
2001 Implements the SUB instruction and side effects.
2002 ****************************************************************************/
sub_long(u32 d,u32 s)2003 u32 sub_long(u32 d, u32 s)
2004 {
2005     register u32 res;   /* all operands in native machine order */
2006     register u32 bc;
2007 
2008     res = d - s;
2009     CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
2010     CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
2011     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2012 
2013     /* calculate the borrow chain.  See note at top */
2014     bc = (res & (~d | s)) | (~d & s);
2015     CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
2016     CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
2017     CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
2018     return res;
2019 }
2020 
2021 /****************************************************************************
2022 REMARKS:
2023 Implements the TEST instruction and side effects.
2024 ****************************************************************************/
test_byte(u8 d,u8 s)2025 void test_byte(u8 d, u8 s)
2026 {
2027     register u32 res;   /* all operands in native machine order */
2028 
2029     res = d & s;
2030 
2031     CLEAR_FLAG(F_OF);
2032     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
2033     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2034     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2035     /* AF == dont care */
2036     CLEAR_FLAG(F_CF);
2037 }
2038 
2039 /****************************************************************************
2040 REMARKS:
2041 Implements the TEST instruction and side effects.
2042 ****************************************************************************/
test_word(u16 d,u16 s)2043 void test_word(u16 d, u16 s)
2044 {
2045     register u32 res;   /* all operands in native machine order */
2046 
2047     res = d & s;
2048 
2049     CLEAR_FLAG(F_OF);
2050     CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
2051     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2052     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2053     /* AF == dont care */
2054     CLEAR_FLAG(F_CF);
2055 }
2056 
2057 /****************************************************************************
2058 REMARKS:
2059 Implements the TEST instruction and side effects.
2060 ****************************************************************************/
test_long(u32 d,u32 s)2061 void test_long(u32 d, u32 s)
2062 {
2063     register u32 res;   /* all operands in native machine order */
2064 
2065     res = d & s;
2066 
2067     CLEAR_FLAG(F_OF);
2068     CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
2069     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2070     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2071     /* AF == dont care */
2072     CLEAR_FLAG(F_CF);
2073 }
2074 
2075 /****************************************************************************
2076 REMARKS:
2077 Implements the XOR instruction and side effects.
2078 ****************************************************************************/
xor_byte(u8 d,u8 s)2079 u8 xor_byte(u8 d, u8 s)
2080 {
2081     register u8 res;    /* all operands in native machine order */
2082 
2083     res = d ^ s;
2084     CLEAR_FLAG(F_OF);
2085     CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
2086     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2087     CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
2088     CLEAR_FLAG(F_CF);
2089     CLEAR_FLAG(F_AF);
2090     return res;
2091 }
2092 
2093 /****************************************************************************
2094 REMARKS:
2095 Implements the XOR instruction and side effects.
2096 ****************************************************************************/
xor_word(u16 d,u16 s)2097 u16 xor_word(u16 d, u16 s)
2098 {
2099     register u16 res;   /* all operands in native machine order */
2100 
2101     res = d ^ s;
2102     CLEAR_FLAG(F_OF);
2103     CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
2104     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2105     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2106     CLEAR_FLAG(F_CF);
2107     CLEAR_FLAG(F_AF);
2108     return res;
2109 }
2110 
2111 /****************************************************************************
2112 REMARKS:
2113 Implements the XOR instruction and side effects.
2114 ****************************************************************************/
xor_long(u32 d,u32 s)2115 u32 xor_long(u32 d, u32 s)
2116 {
2117     register u32 res;   /* all operands in native machine order */
2118 
2119     res = d ^ s;
2120     CLEAR_FLAG(F_OF);
2121     CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
2122     CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2123     CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2124     CLEAR_FLAG(F_CF);
2125     CLEAR_FLAG(F_AF);
2126     return res;
2127 }
2128 
2129 /****************************************************************************
2130 REMARKS:
2131 Implements the IMUL instruction and side effects.
2132 ****************************************************************************/
imul_byte(u8 s)2133 void imul_byte(u8 s)
2134 {
2135     s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
2136 
2137     M.x86.R_AX = res;
2138     if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
2139         ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
2140         CLEAR_FLAG(F_CF);
2141         CLEAR_FLAG(F_OF);
2142     } else {
2143         SET_FLAG(F_CF);
2144         SET_FLAG(F_OF);
2145     }
2146 }
2147 
2148 /****************************************************************************
2149 REMARKS:
2150 Implements the IMUL instruction and side effects.
2151 ****************************************************************************/
imul_word(u16 s)2152 void imul_word(u16 s)
2153 {
2154     s32 res = (s16)M.x86.R_AX * (s16)s;
2155 
2156     M.x86.R_AX = (u16)res;
2157     M.x86.R_DX = (u16)(res >> 16);
2158     if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x0000) ||
2159         ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFFFF)) {
2160         CLEAR_FLAG(F_CF);
2161         CLEAR_FLAG(F_OF);
2162     } else {
2163         SET_FLAG(F_CF);
2164         SET_FLAG(F_OF);
2165     }
2166 }
2167 
2168 /****************************************************************************
2169 REMARKS:
2170 Implements the IMUL instruction and side effects.
2171 ****************************************************************************/
imul_long_direct(u32 * res_lo,u32 * res_hi,u32 d,u32 s)2172 void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
2173 {
2174 #ifdef  __HAS_LONG_LONG__
2175     s64 res = (s32)d * (s32)s;
2176 
2177     *res_lo = (u32)res;
2178     *res_hi = (u32)(res >> 32);
2179 #else
2180     u32 d_lo,d_hi,d_sign;
2181     u32 s_lo,s_hi,s_sign;
2182     u32 rlo_lo,rlo_hi,rhi_lo;
2183 
2184     if ((d_sign = d & 0x80000000) != 0)
2185         d = -d;
2186     d_lo = d & 0xFFFF;
2187     d_hi = d >> 16;
2188     if ((s_sign = s & 0x80000000) != 0)
2189         s = -s;
2190     s_lo = s & 0xFFFF;
2191     s_hi = s >> 16;
2192     rlo_lo = d_lo * s_lo;
2193     rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
2194     rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
2195     *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2196     *res_hi = rhi_lo;
2197     if (d_sign != s_sign) {
2198         d = ~*res_lo;
2199         s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
2200         *res_lo = ~*res_lo+1;
2201         *res_hi = ~*res_hi+(s >> 16);
2202         }
2203 #endif
2204 }
2205 
2206 /****************************************************************************
2207 REMARKS:
2208 Implements the IMUL instruction and side effects.
2209 ****************************************************************************/
imul_long(u32 s)2210 void imul_long(u32 s)
2211 {
2212     imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
2213     if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00000000) ||
2214         ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFFFFFFFF)) {
2215         CLEAR_FLAG(F_CF);
2216         CLEAR_FLAG(F_OF);
2217     } else {
2218         SET_FLAG(F_CF);
2219         SET_FLAG(F_OF);
2220     }
2221 }
2222 
2223 /****************************************************************************
2224 REMARKS:
2225 Implements the MUL instruction and side effects.
2226 ****************************************************************************/
mul_byte(u8 s)2227 void mul_byte(u8 s)
2228 {
2229     u16 res = (u16)(M.x86.R_AL * s);
2230 
2231     M.x86.R_AX = res;
2232     if (M.x86.R_AH == 0) {
2233         CLEAR_FLAG(F_CF);
2234         CLEAR_FLAG(F_OF);
2235     } else {
2236         SET_FLAG(F_CF);
2237         SET_FLAG(F_OF);
2238     }
2239 }
2240 
2241 /****************************************************************************
2242 REMARKS:
2243 Implements the MUL instruction and side effects.
2244 ****************************************************************************/
mul_word(u16 s)2245 void mul_word(u16 s)
2246 {
2247     u32 res = M.x86.R_AX * s;
2248 
2249     M.x86.R_AX = (u16)res;
2250     M.x86.R_DX = (u16)(res >> 16);
2251     if (M.x86.R_DX == 0) {
2252         CLEAR_FLAG(F_CF);
2253         CLEAR_FLAG(F_OF);
2254     } else {
2255         SET_FLAG(F_CF);
2256         SET_FLAG(F_OF);
2257     }
2258 }
2259 
2260 /****************************************************************************
2261 REMARKS:
2262 Implements the MUL instruction and side effects.
2263 ****************************************************************************/
mul_long(u32 s)2264 void mul_long(u32 s)
2265 {
2266 #ifdef  __HAS_LONG_LONG__
2267     u64 res = (u32)M.x86.R_EAX * (u32)s;
2268 
2269     M.x86.R_EAX = (u32)res;
2270     M.x86.R_EDX = (u32)(res >> 32);
2271 #else
2272     u32 a,a_lo,a_hi;
2273     u32 s_lo,s_hi;
2274     u32 rlo_lo,rlo_hi,rhi_lo;
2275 
2276     a = M.x86.R_EAX;
2277     a_lo = a & 0xFFFF;
2278     a_hi = a >> 16;
2279     s_lo = s & 0xFFFF;
2280     s_hi = s >> 16;
2281     rlo_lo = a_lo * s_lo;
2282     rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
2283     rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
2284     M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2285     M.x86.R_EDX = rhi_lo;
2286 #endif
2287     if (M.x86.R_EDX == 0) {
2288         CLEAR_FLAG(F_CF);
2289         CLEAR_FLAG(F_OF);
2290     } else {
2291         SET_FLAG(F_CF);
2292         SET_FLAG(F_OF);
2293     }
2294 }
2295 
2296 /****************************************************************************
2297 REMARKS:
2298 Implements the IDIV instruction and side effects.
2299 ****************************************************************************/
idiv_byte(u8 s)2300 void idiv_byte(u8 s)
2301 {
2302     s32 dvd, div, mod;
2303 
2304     dvd = (s16)M.x86.R_AX;
2305     if (s == 0) {
2306         x86emu_intr_raise(0);
2307         return;
2308     }
2309     div = dvd / (s8)s;
2310     mod = dvd % (s8)s;
2311     if (abs(div) > 0x7f) {
2312         x86emu_intr_raise(0);
2313         return;
2314     }
2315     M.x86.R_AL = (s8) div;
2316     M.x86.R_AH = (s8) mod;
2317 }
2318 
2319 /****************************************************************************
2320 REMARKS:
2321 Implements the IDIV instruction and side effects.
2322 ****************************************************************************/
idiv_word(u16 s)2323 void idiv_word(u16 s)
2324 {
2325     s32 dvd, div, mod;
2326 
2327     dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2328     if (s == 0) {
2329         x86emu_intr_raise(0);
2330         return;
2331     }
2332     div = dvd / (s16)s;
2333     mod = dvd % (s16)s;
2334     if (abs(div) > 0x7fff) {
2335         x86emu_intr_raise(0);
2336         return;
2337     }
2338     CLEAR_FLAG(F_CF);
2339     CLEAR_FLAG(F_SF);
2340     CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2341     CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2342 
2343     M.x86.R_AX = (u16)div;
2344     M.x86.R_DX = (u16)mod;
2345 }
2346 
2347 /****************************************************************************
2348 REMARKS:
2349 Implements the IDIV instruction and side effects.
2350 ****************************************************************************/
idiv_long(u32 s)2351 void idiv_long(u32 s)
2352 {
2353 #ifdef  __HAS_LONG_LONG__
2354     s64 dvd, div, mod;
2355 
2356     dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2357     if (s == 0) {
2358         x86emu_intr_raise(0);
2359         return;
2360     }
2361     div = dvd / (s32)s;
2362     mod = dvd % (s32)s;
2363     if (abs(div) > 0x7fffffff) {
2364         x86emu_intr_raise(0);
2365         return;
2366     }
2367 #else
2368     s32 div = 0, mod;
2369     s32 h_dvd = M.x86.R_EDX;
2370     u32 l_dvd = M.x86.R_EAX;
2371     u32 abs_s = s & 0x7FFFFFFF;
2372     u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
2373     u32 h_s = abs_s >> 1;
2374     u32 l_s = abs_s << 31;
2375     int counter = 31;
2376     int carry;
2377 
2378     if (s == 0) {
2379         x86emu_intr_raise(0);
2380         return;
2381     }
2382     do {
2383         div <<= 1;
2384         carry = (l_dvd >= l_s) ? 0 : 1;
2385 
2386         if (abs_h_dvd < (h_s + carry)) {
2387             h_s >>= 1;
2388             l_s = abs_s << (--counter);
2389             continue;
2390         } else {
2391             abs_h_dvd -= (h_s + carry);
2392             l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2393                 : (l_dvd - l_s);
2394             h_s >>= 1;
2395             l_s = abs_s << (--counter);
2396             div |= 1;
2397             continue;
2398         }
2399 
2400     } while (counter > -1);
2401     /* overflow */
2402     if (abs_h_dvd || (l_dvd > abs_s)) {
2403         x86emu_intr_raise(0);
2404         return;
2405     }
2406     /* sign */
2407     div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2408     mod = l_dvd;
2409 
2410 #endif
2411     CLEAR_FLAG(F_CF);
2412     CLEAR_FLAG(F_AF);
2413     CLEAR_FLAG(F_SF);
2414     SET_FLAG(F_ZF);
2415     CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2416 
2417     M.x86.R_EAX = (u32)div;
2418     M.x86.R_EDX = (u32)mod;
2419 }
2420 
2421 /****************************************************************************
2422 REMARKS:
2423 Implements the DIV instruction and side effects.
2424 ****************************************************************************/
div_byte(u8 s)2425 void div_byte(u8 s)
2426 {
2427     u32 dvd, div, mod;
2428 
2429     dvd = M.x86.R_AX;
2430     if (s == 0) {
2431         x86emu_intr_raise(0);
2432         return;
2433     }
2434     div = dvd / (u8)s;
2435     mod = dvd % (u8)s;
2436     if (abs(div) > 0xff) {
2437         x86emu_intr_raise(0);
2438         return;
2439     }
2440     M.x86.R_AL = (u8)div;
2441     M.x86.R_AH = (u8)mod;
2442 }
2443 
2444 /****************************************************************************
2445 REMARKS:
2446 Implements the DIV instruction and side effects.
2447 ****************************************************************************/
div_word(u16 s)2448 void div_word(u16 s)
2449 {
2450     u32 dvd, div, mod;
2451 
2452     dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2453     if (s == 0) {
2454         x86emu_intr_raise(0);
2455         return;
2456     }
2457     div = dvd / (u16)s;
2458     mod = dvd % (u16)s;
2459     if (abs(div) > 0xffff) {
2460         x86emu_intr_raise(0);
2461         return;
2462     }
2463     CLEAR_FLAG(F_CF);
2464     CLEAR_FLAG(F_SF);
2465     CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2466     CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2467 
2468     M.x86.R_AX = (u16)div;
2469     M.x86.R_DX = (u16)mod;
2470 }
2471 
2472 /****************************************************************************
2473 REMARKS:
2474 Implements the DIV instruction and side effects.
2475 ****************************************************************************/
div_long(u32 s)2476 void div_long(u32 s)
2477 {
2478 #ifdef  __HAS_LONG_LONG__
2479     u64 dvd, div, mod;
2480 
2481     dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2482     if (s == 0) {
2483         x86emu_intr_raise(0);
2484         return;
2485     }
2486     div = dvd / (u32)s;
2487     mod = dvd % (u32)s;
2488     if (abs(div) > 0xffffffff) {
2489         x86emu_intr_raise(0);
2490         return;
2491     }
2492 #else
2493     s32 div = 0, mod;
2494     s32 h_dvd = M.x86.R_EDX;
2495     u32 l_dvd = M.x86.R_EAX;
2496 
2497     u32 h_s = s;
2498     u32 l_s = 0;
2499     int counter = 32;
2500     int carry;
2501 
2502     if (s == 0) {
2503         x86emu_intr_raise(0);
2504         return;
2505     }
2506     do {
2507         div <<= 1;
2508         carry = (l_dvd >= l_s) ? 0 : 1;
2509 
2510         if (h_dvd < (h_s + carry)) {
2511             h_s >>= 1;
2512             l_s = s << (--counter);
2513             continue;
2514         } else {
2515             h_dvd -= (h_s + carry);
2516             l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2517                 : (l_dvd - l_s);
2518             h_s >>= 1;
2519             l_s = s << (--counter);
2520             div |= 1;
2521             continue;
2522         }
2523 
2524     } while (counter > -1);
2525     /* overflow */
2526     if (h_dvd || (l_dvd > s)) {
2527         x86emu_intr_raise(0);
2528         return;
2529     }
2530     mod = l_dvd;
2531 #endif
2532     CLEAR_FLAG(F_CF);
2533     CLEAR_FLAG(F_AF);
2534     CLEAR_FLAG(F_SF);
2535     SET_FLAG(F_ZF);
2536     CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2537 
2538     M.x86.R_EAX = (u32)div;
2539     M.x86.R_EDX = (u32)mod;
2540 }
2541 
2542 /****************************************************************************
2543 REMARKS:
2544 Implements the IN string instruction and side effects.
2545 ****************************************************************************/
ins(int size)2546 void ins(int size)
2547 {
2548     int inc = size;
2549 
2550     if (ACCESS_FLAG(F_DF)) {
2551         inc = -size;
2552     }
2553     if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2554         /* dont care whether REPE or REPNE */
2555         /* in until CX is ZERO. */
2556         u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2557                      M.x86.R_ECX : M.x86.R_CX);
2558         switch (size) {
2559           case 1:
2560             while (count--) {
2561                 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2562                                     (*sys_inb)(M.x86.R_DX));
2563                 M.x86.R_DI += inc;
2564             }
2565             break;
2566 
2567           case 2:
2568             while (count--) {
2569                 store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2570                                     (*sys_inw)(M.x86.R_DX));
2571                 M.x86.R_DI += inc;
2572             }
2573             break;
2574           case 4:
2575             while (count--) {
2576                 store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2577                                     (*sys_inl)(M.x86.R_DX));
2578                 M.x86.R_DI += inc;
2579                 break;
2580             }
2581         }
2582         M.x86.R_CX = 0;
2583         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2584             M.x86.R_ECX = 0;
2585         }
2586         M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2587     } else {
2588         switch (size) {
2589           case 1:
2590             store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2591                                 (*sys_inb)(M.x86.R_DX));
2592             break;
2593           case 2:
2594             store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2595                                 (*sys_inw)(M.x86.R_DX));
2596             break;
2597           case 4:
2598             store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2599                                 (*sys_inl)(M.x86.R_DX));
2600             break;
2601         }
2602         M.x86.R_DI += inc;
2603     }
2604 }
2605 
2606 /****************************************************************************
2607 REMARKS:
2608 Implements the OUT string instruction and side effects.
2609 ****************************************************************************/
outs(int size)2610 void outs(int size)
2611 {
2612     int inc = size;
2613 
2614     if (ACCESS_FLAG(F_DF)) {
2615         inc = -size;
2616     }
2617     if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2618         /* dont care whether REPE or REPNE */
2619         /* out until CX is ZERO. */
2620         u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2621                      M.x86.R_ECX : M.x86.R_CX);
2622         switch (size) {
2623           case 1:
2624             while (count--) {
2625                 (*sys_outb)(M.x86.R_DX,
2626                          fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2627                 M.x86.R_SI += inc;
2628             }
2629             break;
2630 
2631           case 2:
2632             while (count--) {
2633                 (*sys_outw)(M.x86.R_DX,
2634                          fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2635                 M.x86.R_SI += inc;
2636             }
2637             break;
2638           case 4:
2639             while (count--) {
2640                 (*sys_outl)(M.x86.R_DX,
2641                          fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2642                 M.x86.R_SI += inc;
2643                 break;
2644             }
2645         }
2646         M.x86.R_CX = 0;
2647         if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2648             M.x86.R_ECX = 0;
2649         }
2650         M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2651     } else {
2652         switch (size) {
2653           case 1:
2654             (*sys_outb)(M.x86.R_DX,
2655                      fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2656             break;
2657           case 2:
2658             (*sys_outw)(M.x86.R_DX,
2659                      fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2660             break;
2661           case 4:
2662             (*sys_outl)(M.x86.R_DX,
2663                      fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2664             break;
2665         }
2666         M.x86.R_SI += inc;
2667     }
2668 }
2669 
2670 /****************************************************************************
2671 PARAMETERS:
2672 addr    - Address to fetch word from
2673 
2674 REMARKS:
2675 Fetches a word from emulator memory using an absolute address.
2676 ****************************************************************************/
mem_access_word(int addr)2677 u16 mem_access_word(int addr)
2678 {
2679 DB( if (CHECK_MEM_ACCESS())
2680       x86emu_check_mem_access(addr);)
2681     return (*sys_rdw)(addr);
2682 }
2683 
2684 /****************************************************************************
2685 REMARKS:
2686 Pushes a word onto the stack.
2687 
2688 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2689 ****************************************************************************/
push_word(u16 w)2690 void push_word(u16 w)
2691 {
2692 DB( if (CHECK_SP_ACCESS())
2693       x86emu_check_sp_access();)
2694     M.x86.R_SP -= 2;
2695     (*sys_wrw)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP, w);
2696 }
2697 
2698 /****************************************************************************
2699 REMARKS:
2700 Pushes a long onto the stack.
2701 
2702 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2703 ****************************************************************************/
push_long(u32 w)2704 void push_long(u32 w)
2705 {
2706 DB( if (CHECK_SP_ACCESS())
2707       x86emu_check_sp_access();)
2708     M.x86.R_SP -= 4;
2709     (*sys_wrl)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP, w);
2710 }
2711 
2712 /****************************************************************************
2713 REMARKS:
2714 Pops a word from the stack.
2715 
2716 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2717 ****************************************************************************/
pop_word(void)2718 u16 pop_word(void)
2719 {
2720     register u16 res;
2721 
2722 DB( if (CHECK_SP_ACCESS())
2723       x86emu_check_sp_access();)
2724     res = (*sys_rdw)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP);
2725     M.x86.R_SP += 2;
2726     return res;
2727 }
2728 
2729 /****************************************************************************
2730 REMARKS:
2731 Pops a long from the stack.
2732 
2733 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2734 ****************************************************************************/
pop_long(void)2735 u32 pop_long(void)
2736 {
2737     register u32 res;
2738 
2739 DB( if (CHECK_SP_ACCESS())
2740       x86emu_check_sp_access();)
2741     res = (*sys_rdl)(((u32)M.x86.R_SS << 4)  + M.x86.R_SP);
2742     M.x86.R_SP += 4;
2743     return res;
2744 }
2745 
2746