]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/hwinfo/src/x86emu/prim_ops.c
Kleiner netter neuer Versuch.
[people/pmueller/ipfire-2.x.git] / src / hwinfo / src / x86emu / prim_ops.c
1 /****************************************************************************
2 *
3 * Realmode X86 Emulator Library
4 *
5 * Copyright (C) 1996-1999 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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
806 u8 not_byte(u8 s)
807 {
808 return ~s;
809 }
810
811 /****************************************************************************
812 REMARKS:
813 Implements the NOT instruction and side effects.
814 ****************************************************************************/
815 u16 not_word(u16 s)
816 {
817 return ~s;
818 }
819
820 /****************************************************************************
821 REMARKS:
822 Implements the NOT instruction and side effects.
823 ****************************************************************************/
824 u32 not_long(u32 s)
825 {
826 return ~s;
827 }
828
829 /****************************************************************************
830 REMARKS:
831 Implements the RCL instruction and side effects.
832 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 ****************************************************************************/
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 u16 shld_word (u16 d, u16 fill, u8 s)
1646 {
1647 unsigned int cnt, res, cf;
1648
1649 if (s < 16) {
1650 cnt = s % 16;
1651 if (cnt > 0) {
1652 res = (d << cnt) | (fill >> (16-cnt));
1653 cf = d & (1 << (16 - cnt));
1654 CONDITIONAL_SET_FLAG(cf, F_CF);
1655 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1656 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1657 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1658 } else {
1659 res = d;
1660 }
1661 if (cnt == 1) {
1662 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1663 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1664 } else {
1665 CLEAR_FLAG(F_OF);
1666 }
1667 } else {
1668 res = 0;
1669 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1670 CLEAR_FLAG(F_OF);
1671 CLEAR_FLAG(F_SF);
1672 SET_FLAG(F_PF);
1673 SET_FLAG(F_ZF);
1674 }
1675 return (u16)res;
1676 }
1677
1678 /****************************************************************************
1679 REMARKS:
1680 Implements the SHLD instruction and side effects.
1681 ****************************************************************************/
1682 u32 shld_long (u32 d, u32 fill, u8 s)
1683 {
1684 unsigned int cnt, res, cf;
1685
1686 if (s < 32) {
1687 cnt = s % 32;
1688 if (cnt > 0) {
1689 res = (d << cnt) | (fill >> (32-cnt));
1690 cf = d & (1 << (32 - cnt));
1691 CONDITIONAL_SET_FLAG(cf, F_CF);
1692 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1693 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1694 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1695 } else {
1696 res = d;
1697 }
1698 if (cnt == 1) {
1699 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1700 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1701 } else {
1702 CLEAR_FLAG(F_OF);
1703 }
1704 } else {
1705 res = 0;
1706 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1707 CLEAR_FLAG(F_OF);
1708 CLEAR_FLAG(F_SF);
1709 SET_FLAG(F_PF);
1710 SET_FLAG(F_ZF);
1711 }
1712 return res;
1713 }
1714
1715 /****************************************************************************
1716 REMARKS:
1717 Implements the SHRD instruction and side effects.
1718 ****************************************************************************/
1719 u16 shrd_word (u16 d, u16 fill, u8 s)
1720 {
1721 unsigned int cnt, res, cf;
1722
1723 if (s < 16) {
1724 cnt = s % 16;
1725 if (cnt > 0) {
1726 cf = d & (1 << (cnt - 1));
1727 res = (d >> cnt) | (fill << (16 - cnt));
1728 CONDITIONAL_SET_FLAG(cf, F_CF);
1729 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1730 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1731 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1732 } else {
1733 res = d;
1734 }
1735
1736 if (cnt == 1) {
1737 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1738 } else {
1739 CLEAR_FLAG(F_OF);
1740 }
1741 } else {
1742 res = 0;
1743 CLEAR_FLAG(F_CF);
1744 CLEAR_FLAG(F_OF);
1745 SET_FLAG(F_ZF);
1746 CLEAR_FLAG(F_SF);
1747 CLEAR_FLAG(F_PF);
1748 }
1749 return (u16)res;
1750 }
1751
1752 /****************************************************************************
1753 REMARKS:
1754 Implements the SHRD instruction and side effects.
1755 ****************************************************************************/
1756 u32 shrd_long (u32 d, u32 fill, u8 s)
1757 {
1758 unsigned int cnt, res, cf;
1759
1760 if (s < 32) {
1761 cnt = s % 32;
1762 if (cnt > 0) {
1763 cf = d & (1 << (cnt - 1));
1764 res = (d >> cnt) | (fill << (32 - cnt));
1765 CONDITIONAL_SET_FLAG(cf, F_CF);
1766 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1767 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1768 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1769 } else {
1770 res = d;
1771 }
1772 if (cnt == 1) {
1773 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1774 } else {
1775 CLEAR_FLAG(F_OF);
1776 }
1777 } else {
1778 res = 0;
1779 CLEAR_FLAG(F_CF);
1780 CLEAR_FLAG(F_OF);
1781 SET_FLAG(F_ZF);
1782 CLEAR_FLAG(F_SF);
1783 CLEAR_FLAG(F_PF);
1784 }
1785 return res;
1786 }
1787
1788 /****************************************************************************
1789 REMARKS:
1790 Implements the SBB instruction and side effects.
1791 ****************************************************************************/
1792 u8 sbb_byte(u8 d, u8 s)
1793 {
1794 register u32 res; /* all operands in native machine order */
1795 register u32 bc;
1796
1797 if (ACCESS_FLAG(F_CF))
1798 res = d - s - 1;
1799 else
1800 res = d - s;
1801 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1802 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1803 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1804
1805 /* calculate the borrow chain. See note at top */
1806 bc = (res & (~d | s)) | (~d & s);
1807 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1808 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1809 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1810 return (u8)res;
1811 }
1812
1813 /****************************************************************************
1814 REMARKS:
1815 Implements the SBB instruction and side effects.
1816 ****************************************************************************/
1817 u16 sbb_word(u16 d, u16 s)
1818 {
1819 register u32 res; /* all operands in native machine order */
1820 register u32 bc;
1821
1822 if (ACCESS_FLAG(F_CF))
1823 res = d - s - 1;
1824 else
1825 res = d - s;
1826 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1827 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1828 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1829
1830 /* calculate the borrow chain. See note at top */
1831 bc = (res & (~d | s)) | (~d & s);
1832 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1833 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1834 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1835 return (u16)res;
1836 }
1837
1838 /****************************************************************************
1839 REMARKS:
1840 Implements the SBB instruction and side effects.
1841 ****************************************************************************/
1842 u32 sbb_long(u32 d, u32 s)
1843 {
1844 register u32 res; /* all operands in native machine order */
1845 register u32 bc;
1846
1847 if (ACCESS_FLAG(F_CF))
1848 res = d - s - 1;
1849 else
1850 res = d - s;
1851 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1852 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1853 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1854
1855 /* calculate the borrow chain. See note at top */
1856 bc = (res & (~d | s)) | (~d & s);
1857 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1858 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1859 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1860 return res;
1861 }
1862
1863 /****************************************************************************
1864 REMARKS:
1865 Implements the SUB instruction and side effects.
1866 ****************************************************************************/
1867 u8 sub_byte(u8 d, u8 s)
1868 {
1869 register u32 res; /* all operands in native machine order */
1870 register u32 bc;
1871
1872 res = d - s;
1873 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1874 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1875 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1876
1877 /* calculate the borrow chain. See note at top */
1878 bc = (res & (~d | s)) | (~d & s);
1879 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1880 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1881 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1882 return (u8)res;
1883 }
1884
1885 /****************************************************************************
1886 REMARKS:
1887 Implements the SUB instruction and side effects.
1888 ****************************************************************************/
1889 u16 sub_word(u16 d, u16 s)
1890 {
1891 register u32 res; /* all operands in native machine order */
1892 register u32 bc;
1893
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 SUB instruction and side effects.
1910 ****************************************************************************/
1911 u32 sub_long(u32 d, u32 s)
1912 {
1913 register u32 res; /* all operands in native machine order */
1914 register u32 bc;
1915
1916 res = d - s;
1917 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1918 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1919 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1920
1921 /* calculate the borrow chain. See note at top */
1922 bc = (res & (~d | s)) | (~d & s);
1923 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1924 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1925 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1926 return res;
1927 }
1928
1929 /****************************************************************************
1930 REMARKS:
1931 Implements the TEST instruction and side effects.
1932 ****************************************************************************/
1933 void test_byte(u8 d, u8 s)
1934 {
1935 register u32 res; /* all operands in native machine order */
1936
1937 res = d & s;
1938
1939 CLEAR_FLAG(F_OF);
1940 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1941 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1942 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1943 /* AF == dont care */
1944 CLEAR_FLAG(F_CF);
1945 }
1946
1947 /****************************************************************************
1948 REMARKS:
1949 Implements the TEST instruction and side effects.
1950 ****************************************************************************/
1951 void test_word(u16 d, u16 s)
1952 {
1953 register u32 res; /* all operands in native machine order */
1954
1955 res = d & s;
1956
1957 CLEAR_FLAG(F_OF);
1958 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1959 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1960 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1961 /* AF == dont care */
1962 CLEAR_FLAG(F_CF);
1963 }
1964
1965 /****************************************************************************
1966 REMARKS:
1967 Implements the TEST instruction and side effects.
1968 ****************************************************************************/
1969 void test_long(u32 d, u32 s)
1970 {
1971 register u32 res; /* all operands in native machine order */
1972
1973 res = d & s;
1974
1975 CLEAR_FLAG(F_OF);
1976 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1977 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1978 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1979 /* AF == dont care */
1980 CLEAR_FLAG(F_CF);
1981 }
1982
1983 /****************************************************************************
1984 REMARKS:
1985 Implements the XOR instruction and side effects.
1986 ****************************************************************************/
1987 u8 xor_byte(u8 d, u8 s)
1988 {
1989 register u8 res; /* all operands in native machine order */
1990
1991 res = d ^ s;
1992 CLEAR_FLAG(F_OF);
1993 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1994 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1995 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
1996 CLEAR_FLAG(F_CF);
1997 CLEAR_FLAG(F_AF);
1998 return res;
1999 }
2000
2001 /****************************************************************************
2002 REMARKS:
2003 Implements the XOR instruction and side effects.
2004 ****************************************************************************/
2005 u16 xor_word(u16 d, u16 s)
2006 {
2007 register u16 res; /* all operands in native machine order */
2008
2009 res = d ^ s;
2010 CLEAR_FLAG(F_OF);
2011 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
2012 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2013 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2014 CLEAR_FLAG(F_CF);
2015 CLEAR_FLAG(F_AF);
2016 return res;
2017 }
2018
2019 /****************************************************************************
2020 REMARKS:
2021 Implements the XOR instruction and side effects.
2022 ****************************************************************************/
2023 u32 xor_long(u32 d, u32 s)
2024 {
2025 register u32 res; /* all operands in native machine order */
2026
2027 res = d ^ s;
2028 CLEAR_FLAG(F_OF);
2029 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
2030 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2031 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2032 CLEAR_FLAG(F_CF);
2033 CLEAR_FLAG(F_AF);
2034 return res;
2035 }
2036
2037 /****************************************************************************
2038 REMARKS:
2039 Implements the IMUL instruction and side effects.
2040 ****************************************************************************/
2041 void imul_byte(u8 s)
2042 {
2043 s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
2044
2045 M.x86.R_AX = res;
2046 if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
2047 ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
2048 CLEAR_FLAG(F_CF);
2049 CLEAR_FLAG(F_OF);
2050 } else {
2051 SET_FLAG(F_CF);
2052 SET_FLAG(F_OF);
2053 }
2054 }
2055
2056 /****************************************************************************
2057 REMARKS:
2058 Implements the IMUL instruction and side effects.
2059 ****************************************************************************/
2060 void imul_word(u16 s)
2061 {
2062 s32 res = (s16)M.x86.R_AX * (s16)s;
2063
2064 M.x86.R_AX = (u16)res;
2065 M.x86.R_DX = (u16)(res >> 16);
2066 if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x00) ||
2067 ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFF)) {
2068 CLEAR_FLAG(F_CF);
2069 CLEAR_FLAG(F_OF);
2070 } else {
2071 SET_FLAG(F_CF);
2072 SET_FLAG(F_OF);
2073 }
2074 }
2075
2076 /****************************************************************************
2077 REMARKS:
2078 Implements the IMUL instruction and side effects.
2079 ****************************************************************************/
2080 void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
2081 {
2082 #ifdef __HAS_LONG_LONG__
2083 s64 res = (s32)d * (s32)s;
2084
2085 *res_lo = (u32)res;
2086 *res_hi = (u32)(res >> 32);
2087 #else
2088 u32 d_lo,d_hi,d_sign;
2089 u32 s_lo,s_hi,s_sign;
2090 u32 rlo_lo,rlo_hi,rhi_lo;
2091
2092 if ((d_sign = d & 0x80000000) != 0)
2093 d = -d;
2094 d_lo = d & 0xFFFF;
2095 d_hi = d >> 16;
2096 if ((s_sign = s & 0x80000000) != 0)
2097 s = -s;
2098 s_lo = s & 0xFFFF;
2099 s_hi = s >> 16;
2100 rlo_lo = d_lo * s_lo;
2101 rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
2102 rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
2103 *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2104 *res_hi = rhi_lo;
2105 if (d_sign != s_sign) {
2106 d = ~*res_lo;
2107 s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
2108 *res_lo = ~*res_lo+1;
2109 *res_hi = ~*res_hi+(s >> 16);
2110 }
2111 #endif
2112 }
2113
2114 /****************************************************************************
2115 REMARKS:
2116 Implements the IMUL instruction and side effects.
2117 ****************************************************************************/
2118 void imul_long(u32 s)
2119 {
2120 imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
2121 if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00) ||
2122 ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFF)) {
2123 CLEAR_FLAG(F_CF);
2124 CLEAR_FLAG(F_OF);
2125 } else {
2126 SET_FLAG(F_CF);
2127 SET_FLAG(F_OF);
2128 }
2129 }
2130
2131 /****************************************************************************
2132 REMARKS:
2133 Implements the MUL instruction and side effects.
2134 ****************************************************************************/
2135 void mul_byte(u8 s)
2136 {
2137 u16 res = (u16)(M.x86.R_AL * s);
2138
2139 M.x86.R_AX = res;
2140 if (M.x86.R_AH == 0) {
2141 CLEAR_FLAG(F_CF);
2142 CLEAR_FLAG(F_OF);
2143 } else {
2144 SET_FLAG(F_CF);
2145 SET_FLAG(F_OF);
2146 }
2147 }
2148
2149 /****************************************************************************
2150 REMARKS:
2151 Implements the MUL instruction and side effects.
2152 ****************************************************************************/
2153 void mul_word(u16 s)
2154 {
2155 u32 res = M.x86.R_AX * s;
2156
2157 M.x86.R_AX = (u16)res;
2158 M.x86.R_DX = (u16)(res >> 16);
2159 if (M.x86.R_DX == 0) {
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 MUL instruction and side effects.
2171 ****************************************************************************/
2172 void mul_long(u32 s)
2173 {
2174 #ifdef __HAS_LONG_LONG__
2175 u64 res = (u32)M.x86.R_EAX * (u32)s;
2176
2177 M.x86.R_EAX = (u32)res;
2178 M.x86.R_EDX = (u32)(res >> 32);
2179 #else
2180 u32 a,a_lo,a_hi;
2181 u32 s_lo,s_hi;
2182 u32 rlo_lo,rlo_hi,rhi_lo;
2183
2184 a = M.x86.R_EAX;
2185 a_lo = a & 0xFFFF;
2186 a_hi = a >> 16;
2187 s_lo = s & 0xFFFF;
2188 s_hi = s >> 16;
2189 rlo_lo = a_lo * s_lo;
2190 rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
2191 rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
2192 M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2193 M.x86.R_EDX = rhi_lo;
2194 #endif
2195
2196 if (M.x86.R_EDX == 0) {
2197 CLEAR_FLAG(F_CF);
2198 CLEAR_FLAG(F_OF);
2199 } else {
2200 SET_FLAG(F_CF);
2201 SET_FLAG(F_OF);
2202 }
2203 }
2204
2205 /****************************************************************************
2206 REMARKS:
2207 Implements the IDIV instruction and side effects.
2208 ****************************************************************************/
2209 void idiv_byte(u8 s)
2210 {
2211 s32 dvd, div, mod;
2212
2213 dvd = (s16)M.x86.R_AX;
2214 if (s == 0) {
2215 x86emu_intr_raise(0);
2216 return;
2217 }
2218 div = dvd / (s8)s;
2219 mod = dvd % (s8)s;
2220 if (abs(div) > 0x7f) {
2221 x86emu_intr_raise(0);
2222 return;
2223 }
2224 M.x86.R_AL = (s8) div;
2225 M.x86.R_AH = (s8) mod;
2226 }
2227
2228 /****************************************************************************
2229 REMARKS:
2230 Implements the IDIV instruction and side effects.
2231 ****************************************************************************/
2232 void idiv_word(u16 s)
2233 {
2234 s32 dvd, div, mod;
2235
2236 dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2237 if (s == 0) {
2238 x86emu_intr_raise(0);
2239 return;
2240 }
2241 div = dvd / (s16)s;
2242 mod = dvd % (s16)s;
2243 if (abs(div) > 0x7fff) {
2244 x86emu_intr_raise(0);
2245 return;
2246 }
2247 CLEAR_FLAG(F_CF);
2248 CLEAR_FLAG(F_SF);
2249 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2250 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2251
2252 M.x86.R_AX = (u16)div;
2253 M.x86.R_DX = (u16)mod;
2254 }
2255
2256 /****************************************************************************
2257 REMARKS:
2258 Implements the IDIV instruction and side effects.
2259 ****************************************************************************/
2260 void idiv_long(u32 s)
2261 {
2262 #ifdef __HAS_LONG_LONG__
2263 s64 dvd, div, mod;
2264
2265 dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2266 if (s == 0) {
2267 x86emu_intr_raise(0);
2268 return;
2269 }
2270 div = dvd / (s32)s;
2271 mod = dvd % (s32)s;
2272 if (abs(div) > 0x7fffffff) {
2273 x86emu_intr_raise(0);
2274 return;
2275 }
2276 #else
2277 s32 div = 0, mod;
2278 s32 h_dvd = M.x86.R_EDX;
2279 u32 l_dvd = M.x86.R_EAX;
2280 u32 abs_s = s & 0x7FFFFFFF;
2281 u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
2282 u32 h_s = abs_s >> 1;
2283 u32 l_s = abs_s << 31;
2284 int counter = 31;
2285 int carry;
2286
2287 if (s == 0) {
2288 x86emu_intr_raise(0);
2289 return;
2290 }
2291 do {
2292 div <<= 1;
2293 carry = (l_dvd >= l_s) ? 0 : 1;
2294
2295 if (abs_h_dvd < (h_s + carry)) {
2296 h_s >>= 1;
2297 l_s = abs_s << (--counter);
2298 continue;
2299 } else {
2300 abs_h_dvd -= (h_s + carry);
2301 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2302 : (l_dvd - l_s);
2303 h_s >>= 1;
2304 l_s = abs_s << (--counter);
2305 div |= 1;
2306 continue;
2307 }
2308
2309 } while (counter > -1);
2310 /* overflow */
2311 if (abs_h_dvd || (l_dvd > abs_s)) {
2312 x86emu_intr_raise(0);
2313 return;
2314 }
2315 /* sign */
2316 div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2317 mod = l_dvd;
2318
2319 #endif
2320 CLEAR_FLAG(F_CF);
2321 CLEAR_FLAG(F_AF);
2322 CLEAR_FLAG(F_SF);
2323 SET_FLAG(F_ZF);
2324 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2325
2326 M.x86.R_EAX = (u32)div;
2327 M.x86.R_EDX = (u32)mod;
2328 }
2329
2330 /****************************************************************************
2331 REMARKS:
2332 Implements the DIV instruction and side effects.
2333 ****************************************************************************/
2334 void div_byte(u8 s)
2335 {
2336 u32 dvd, div, mod;
2337
2338 dvd = M.x86.R_AX;
2339 if (s == 0) {
2340 x86emu_intr_raise(0);
2341 return;
2342 }
2343 div = dvd / (u8)s;
2344 mod = dvd % (u8)s;
2345 if (abs(div) > 0xff) {
2346 x86emu_intr_raise(0);
2347 return;
2348 }
2349 M.x86.R_AL = (u8)div;
2350 M.x86.R_AH = (u8)mod;
2351 }
2352
2353 /****************************************************************************
2354 REMARKS:
2355 Implements the DIV instruction and side effects.
2356 ****************************************************************************/
2357 void div_word(u16 s)
2358 {
2359 u32 dvd, div, mod;
2360
2361 dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2362 if (s == 0) {
2363 x86emu_intr_raise(0);
2364 return;
2365 }
2366 div = dvd / (u16)s;
2367 mod = dvd % (u16)s;
2368 if (abs(div) > 0xffff) {
2369 x86emu_intr_raise(0);
2370 return;
2371 }
2372 CLEAR_FLAG(F_CF);
2373 CLEAR_FLAG(F_SF);
2374 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2375 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2376
2377 M.x86.R_AX = (u16)div;
2378 M.x86.R_DX = (u16)mod;
2379 }
2380
2381 /****************************************************************************
2382 REMARKS:
2383 Implements the DIV instruction and side effects.
2384 ****************************************************************************/
2385 void div_long(u32 s)
2386 {
2387 #ifdef __HAS_LONG_LONG__
2388 u64 dvd, div, mod;
2389
2390 dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2391 if (s == 0) {
2392 x86emu_intr_raise(0);
2393 return;
2394 }
2395 div = dvd / (u32)s;
2396 mod = dvd % (u32)s;
2397 if (abs(div) > 0xffffffff) {
2398 x86emu_intr_raise(0);
2399 return;
2400 }
2401 #else
2402 s32 div = 0, mod;
2403 s32 h_dvd = M.x86.R_EDX;
2404 u32 l_dvd = M.x86.R_EAX;
2405
2406 u32 h_s = s;
2407 u32 l_s = 0;
2408 int counter = 32;
2409 int carry;
2410
2411 if (s == 0) {
2412 x86emu_intr_raise(0);
2413 return;
2414 }
2415 do {
2416 div <<= 1;
2417 carry = (l_dvd >= l_s) ? 0 : 1;
2418
2419 if (h_dvd < (h_s + carry)) {
2420 h_s >>= 1;
2421 l_s = s << (--counter);
2422 continue;
2423 } else {
2424 h_dvd -= (h_s + carry);
2425 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2426 : (l_dvd - l_s);
2427 h_s >>= 1;
2428 l_s = s << (--counter);
2429 div |= 1;
2430 continue;
2431 }
2432
2433 } while (counter > -1);
2434 /* overflow */
2435 if (h_dvd || (l_dvd > s)) {
2436 x86emu_intr_raise(0);
2437 return;
2438 }
2439 mod = l_dvd;
2440 #endif
2441 CLEAR_FLAG(F_CF);
2442 CLEAR_FLAG(F_AF);
2443 CLEAR_FLAG(F_SF);
2444 SET_FLAG(F_ZF);
2445 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2446
2447 M.x86.R_EAX = (u32)div;
2448 M.x86.R_EDX = (u32)mod;
2449 }
2450
2451 /****************************************************************************
2452 REMARKS:
2453 Implements the IN string instruction and side effects.
2454 ****************************************************************************/
2455 void ins(int size)
2456 {
2457 int inc = size;
2458
2459 if (ACCESS_FLAG(F_DF)) {
2460 inc = -size;
2461 }
2462 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2463 /* dont care whether REPE or REPNE */
2464 /* in until CX is ZERO. */
2465 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2466 M.x86.R_ECX : M.x86.R_CX);
2467 switch (size) {
2468 case 1:
2469 while (count--) {
2470 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2471 (*sys_inb)(M.x86.R_DX));
2472 M.x86.R_DI += inc;
2473 }
2474 break;
2475
2476 case 2:
2477 while (count--) {
2478 store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2479 (*sys_inw)(M.x86.R_DX));
2480 M.x86.R_DI += inc;
2481 }
2482 break;
2483 case 4:
2484 while (count--) {
2485 store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2486 (*sys_inl)(M.x86.R_DX));
2487 M.x86.R_DI += inc;
2488 break;
2489 }
2490 }
2491 M.x86.R_CX = 0;
2492 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2493 M.x86.R_ECX = 0;
2494 }
2495 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2496 } else {
2497 switch (size) {
2498 case 1:
2499 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2500 (*sys_inb)(M.x86.R_DX));
2501 break;
2502 case 2:
2503 store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2504 (*sys_inw)(M.x86.R_DX));
2505 break;
2506 case 4:
2507 store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2508 (*sys_inl)(M.x86.R_DX));
2509 break;
2510 }
2511 M.x86.R_DI += inc;
2512 }
2513 }
2514
2515 /****************************************************************************
2516 REMARKS:
2517 Implements the OUT string instruction and side effects.
2518 ****************************************************************************/
2519 void outs(int size)
2520 {
2521 int inc = size;
2522
2523 if (ACCESS_FLAG(F_DF)) {
2524 inc = -size;
2525 }
2526 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2527 /* dont care whether REPE or REPNE */
2528 /* out until CX is ZERO. */
2529 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2530 M.x86.R_ECX : M.x86.R_CX);
2531 switch (size) {
2532 case 1:
2533 while (count--) {
2534 (*sys_outb)(M.x86.R_DX,
2535 fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2536 M.x86.R_SI += inc;
2537 }
2538 break;
2539
2540 case 2:
2541 while (count--) {
2542 (*sys_outw)(M.x86.R_DX,
2543 fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2544 M.x86.R_SI += inc;
2545 }
2546 break;
2547 case 4:
2548 while (count--) {
2549 (*sys_outl)(M.x86.R_DX,
2550 fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2551 M.x86.R_SI += inc;
2552 break;
2553 }
2554 }
2555 M.x86.R_CX = 0;
2556 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2557 M.x86.R_ECX = 0;
2558 }
2559 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2560 } else {
2561 switch (size) {
2562 case 1:
2563 (*sys_outb)(M.x86.R_DX,
2564 fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2565 break;
2566 case 2:
2567 (*sys_outw)(M.x86.R_DX,
2568 fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2569 break;
2570 case 4:
2571 (*sys_outl)(M.x86.R_DX,
2572 fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2573 break;
2574 }
2575 M.x86.R_SI += inc;
2576 }
2577 }
2578
2579 /****************************************************************************
2580 PARAMETERS:
2581 addr - Address to fetch word from
2582
2583 REMARKS:
2584 Fetches a word from emulator memory using an absolute address.
2585 ****************************************************************************/
2586 u16 mem_access_word(int addr)
2587 {
2588 DB( if (CHECK_MEM_ACCESS())
2589 x86emu_check_mem_access(addr);)
2590 return (*sys_rdw)(addr);
2591 }
2592
2593 /****************************************************************************
2594 REMARKS:
2595 Pushes a word onto the stack.
2596
2597 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2598 ****************************************************************************/
2599 void push_word(u16 w)
2600 {
2601 DB( if (CHECK_SP_ACCESS())
2602 x86emu_check_sp_access();)
2603 M.x86.R_SP -= 2;
2604 (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2605 }
2606
2607 /****************************************************************************
2608 REMARKS:
2609 Pushes a long onto the stack.
2610
2611 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2612 ****************************************************************************/
2613 void push_long(u32 w)
2614 {
2615 DB( if (CHECK_SP_ACCESS())
2616 x86emu_check_sp_access();)
2617 M.x86.R_SP -= 4;
2618 (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2619 }
2620
2621 /****************************************************************************
2622 REMARKS:
2623 Pops a word from the stack.
2624
2625 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2626 ****************************************************************************/
2627 u16 pop_word(void)
2628 {
2629 register u16 res;
2630
2631 DB( if (CHECK_SP_ACCESS())
2632 x86emu_check_sp_access();)
2633 res = (*sys_rdw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
2634 M.x86.R_SP += 2;
2635 return res;
2636 }
2637
2638 /****************************************************************************
2639 REMARKS:
2640 Pops a long from the stack.
2641
2642 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2643 ****************************************************************************/
2644 u32 pop_long(void)
2645 {
2646 register u32 res;
2647
2648 DB( if (CHECK_SP_ACCESS())
2649 x86emu_check_sp_access();)
2650 res = (*sys_rdl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
2651 M.x86.R_SP += 4;
2652 return res;
2653 }
2654