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