Add preliminary support for the x86emu backend.
[v86d.git] / libs / x86emu / prim_ops.c
blob461e09e3e2f100c4f01afec59360cafcad0e4d5e
1 /****************************************************************************
3 * Realmode X86 Emulator Library
5 * Copyright (C) 1996-1999 SciTech Software, Inc.
6 * Copyright (C) David Mosberger-Tang
7 * Copyright (C) 1999 Egbert Eich
9 * ========================================================================
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.
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.
29 * ========================================================================
31 * Language: ANSI C
32 * Environment: Any
33 * Developer: Kendall Bennett
35 * Description: This file contains the code to implement the primitive
36 * machine operations used by the emulation code in ops.c
38 * Carry Chain Calculation
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.
48 * So, given the following table, which represents the addition of two
49 * bits, we can derive a formula for the carry chain.
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
61 * Construction of table for cout:
63 * ab
64 * r \ 00 01 11 10
65 * |------------------
66 * 0 | 0 1 1 1
67 * 1 | 0 0 1 0
69 * By inspection, one gets: cc = ab + r'(a + b)
71 * That represents alot of operations, but NO CHOICE....
73 * Borrow Chain Calculation.
75 * The following table represents the subtraction of two bits, from
76 * which we can derive a formula for the borrow chain.
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
88 * Construction of table for cout:
90 * ab
91 * r \ 00 01 11 10
92 * |------------------
93 * 0 | 0 1 0 0
94 * 1 | 1 1 1 0
96 * By inspection, one gets: bc = a'b + r(a' + b)
98 ****************************************************************************/
100 #include <stdlib.h>
102 #define PRIM_OPS_NO_REDEFINE_ASM
103 #include "x86emu/x86emui.h"
105 /*------------------------- Global Variables ------------------------------*/
107 static u32 x86emu_parity_tab[8] =
109 0x96696996,
110 0x69969669,
111 0x69969669,
112 0x96696996,
113 0x69969669,
114 0x96696996,
115 0x96696996,
116 0x69969669,
119 #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
120 #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
122 /*----------------------------- Implementation ----------------------------*/
124 /****************************************************************************
125 REMARKS:
126 Implements the AAA instruction and side effects.
127 ****************************************************************************/
128 u16 aaa_word(u16 d)
130 u16 res;
131 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
132 d += 0x6;
133 d += 0x100;
134 SET_FLAG(F_AF);
135 SET_FLAG(F_CF);
136 } else {
137 CLEAR_FLAG(F_CF);
138 CLEAR_FLAG(F_AF);
140 res = (u16)(d & 0xFF0F);
141 CLEAR_FLAG(F_SF);
142 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
143 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
144 return res;
147 /****************************************************************************
148 REMARKS:
149 Implements the AAA instruction and side effects.
150 ****************************************************************************/
151 u16 aas_word(u16 d)
153 u16 res;
154 if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
155 d -= 0x6;
156 d -= 0x100;
157 SET_FLAG(F_AF);
158 SET_FLAG(F_CF);
159 } else {
160 CLEAR_FLAG(F_CF);
161 CLEAR_FLAG(F_AF);
163 res = (u16)(d & 0xFF0F);
164 CLEAR_FLAG(F_SF);
165 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
166 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
167 return res;
170 /****************************************************************************
171 REMARKS:
172 Implements the AAD instruction and side effects.
173 ****************************************************************************/
174 u16 aad_word(u16 d)
176 u16 l;
177 u8 hb, lb;
179 hb = (u8)((d >> 8) & 0xff);
180 lb = (u8)((d & 0xff));
181 l = (u16)((lb + 10 * hb) & 0xFF);
183 CLEAR_FLAG(F_CF);
184 CLEAR_FLAG(F_AF);
185 CLEAR_FLAG(F_OF);
186 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
187 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
188 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
189 return l;
192 /****************************************************************************
193 REMARKS:
194 Implements the AAM instruction and side effects.
195 ****************************************************************************/
196 u16 aam_word(u8 d)
198 u16 h, l;
200 h = (u16)(d / 10);
201 l = (u16)(d % 10);
202 l |= (u16)(h << 8);
204 CLEAR_FLAG(F_CF);
205 CLEAR_FLAG(F_AF);
206 CLEAR_FLAG(F_OF);
207 CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
208 CONDITIONAL_SET_FLAG(l == 0, F_ZF);
209 CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
210 return l;
213 /****************************************************************************
214 REMARKS:
215 Implements the ADC instruction and side effects.
216 ****************************************************************************/
217 u8 adc_byte(u8 d, u8 s)
219 register u32 res; /* all operands in native machine order */
220 register u32 cc;
222 if (ACCESS_FLAG(F_CF))
223 res = 1 + d + s;
224 else
225 res = d + s;
227 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
228 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
229 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
230 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
232 /* calculate the carry chain SEE NOTE AT TOP. */
233 cc = (s & d) | ((~res) & (s | d));
234 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
235 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
236 return (u8)res;
239 /****************************************************************************
240 REMARKS:
241 Implements the ADC instruction and side effects.
242 ****************************************************************************/
243 u16 adc_word(u16 d, u16 s)
245 register u32 res; /* all operands in native machine order */
246 register u32 cc;
248 if (ACCESS_FLAG(F_CF))
249 res = 1 + d + s;
250 else
251 res = d + s;
253 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
254 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
255 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
256 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
258 /* calculate the carry chain SEE NOTE AT TOP. */
259 cc = (s & d) | ((~res) & (s | d));
260 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
261 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
262 return (u16)res;
265 /****************************************************************************
266 REMARKS:
267 Implements the ADC instruction and side effects.
268 ****************************************************************************/
269 u32 adc_long(u32 d, u32 s)
271 register u32 lo; /* all operands in native machine order */
272 register u32 hi;
273 register u32 res;
274 register u32 cc;
276 if (ACCESS_FLAG(F_CF)) {
277 lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
278 res = 1 + d + s;
280 else {
281 lo = (d & 0xFFFF) + (s & 0xFFFF);
282 res = d + s;
284 hi = (lo >> 16) + (d >> 16) + (s >> 16);
286 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
287 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
288 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
289 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
291 /* calculate the carry chain SEE NOTE AT TOP. */
292 cc = (s & d) | ((~res) & (s | d));
293 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
294 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
295 return res;
298 /****************************************************************************
299 REMARKS:
300 Implements the ADD instruction and side effects.
301 ****************************************************************************/
302 u8 add_byte(u8 d, u8 s)
304 register u32 res; /* all operands in native machine order */
305 register u32 cc;
307 res = d + s;
308 CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
309 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
310 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
311 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
313 /* calculate the carry chain SEE NOTE AT TOP. */
314 cc = (s & d) | ((~res) & (s | d));
315 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
316 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
317 return (u8)res;
320 /****************************************************************************
321 REMARKS:
322 Implements the ADD instruction and side effects.
323 ****************************************************************************/
324 u16 add_word(u16 d, u16 s)
326 register u32 res; /* all operands in native machine order */
327 register u32 cc;
329 res = d + s;
330 CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
331 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
332 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
333 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
335 /* calculate the carry chain SEE NOTE AT TOP. */
336 cc = (s & d) | ((~res) & (s | d));
337 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
338 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
339 return (u16)res;
342 /****************************************************************************
343 REMARKS:
344 Implements the ADD instruction and side effects.
345 ****************************************************************************/
346 u32 add_long(u32 d, u32 s)
348 register u32 lo; /* all operands in native machine order */
349 register u32 hi;
350 register u32 res;
351 register u32 cc;
353 lo = (d & 0xFFFF) + (s & 0xFFFF);
354 res = d + s;
355 hi = (lo >> 16) + (d >> 16) + (s >> 16);
357 CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
358 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
359 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
360 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
362 /* calculate the carry chain SEE NOTE AT TOP. */
363 cc = (s & d) | ((~res) & (s | d));
364 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
365 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
367 return res;
370 /****************************************************************************
371 REMARKS:
372 Implements the AND instruction and side effects.
373 ****************************************************************************/
374 u8 and_byte(u8 d, u8 s)
376 register u8 res; /* all operands in native machine order */
378 res = d & s;
380 /* set the flags */
381 CLEAR_FLAG(F_OF);
382 CLEAR_FLAG(F_CF);
383 CLEAR_FLAG(F_AF);
384 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
385 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
386 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
387 return res;
390 /****************************************************************************
391 REMARKS:
392 Implements the AND instruction and side effects.
393 ****************************************************************************/
394 u16 and_word(u16 d, u16 s)
396 register u16 res; /* all operands in native machine order */
398 res = d & s;
400 /* set the flags */
401 CLEAR_FLAG(F_OF);
402 CLEAR_FLAG(F_CF);
403 CLEAR_FLAG(F_AF);
404 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
405 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
406 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
407 return res;
410 /****************************************************************************
411 REMARKS:
412 Implements the AND instruction and side effects.
413 ****************************************************************************/
414 u32 and_long(u32 d, u32 s)
416 register u32 res; /* all operands in native machine order */
418 res = d & s;
420 /* set the flags */
421 CLEAR_FLAG(F_OF);
422 CLEAR_FLAG(F_CF);
423 CLEAR_FLAG(F_AF);
424 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
425 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
426 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
427 return res;
430 /****************************************************************************
431 REMARKS:
432 Implements the CMP instruction and side effects.
433 ****************************************************************************/
434 u8 cmp_byte(u8 d, u8 s)
436 register u32 res; /* all operands in native machine order */
437 register u32 bc;
439 res = d - s;
440 CLEAR_FLAG(F_CF);
441 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
442 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
443 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
445 /* calculate the borrow chain. See note at top */
446 bc = (res & (~d | s)) | (~d & s);
447 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
448 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
449 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
450 return d;
453 /****************************************************************************
454 REMARKS:
455 Implements the CMP instruction and side effects.
456 ****************************************************************************/
457 u16 cmp_word(u16 d, u16 s)
459 register u32 res; /* all operands in native machine order */
460 register u32 bc;
462 res = d - s;
463 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
464 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
465 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
467 /* calculate the borrow chain. See note at top */
468 bc = (res & (~d | s)) | (~d & s);
469 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
470 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
471 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
472 return d;
475 /****************************************************************************
476 REMARKS:
477 Implements the CMP instruction and side effects.
478 ****************************************************************************/
479 u32 cmp_long(u32 d, u32 s)
481 register u32 res; /* all operands in native machine order */
482 register u32 bc;
484 res = d - s;
485 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
486 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
487 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
489 /* calculate the borrow chain. See note at top */
490 bc = (res & (~d | s)) | (~d & s);
491 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
492 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
493 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
494 return d;
497 /****************************************************************************
498 REMARKS:
499 Implements the DAA instruction and side effects.
500 ****************************************************************************/
501 u8 daa_byte(u8 d)
503 u32 res = d;
504 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
505 res += 6;
506 SET_FLAG(F_AF);
508 if (res > 0x9F || ACCESS_FLAG(F_CF)) {
509 res += 0x60;
510 SET_FLAG(F_CF);
512 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
513 CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
514 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
515 return (u8)res;
518 /****************************************************************************
519 REMARKS:
520 Implements the DAS instruction and side effects.
521 ****************************************************************************/
522 u8 das_byte(u8 d)
524 if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
525 d -= 6;
526 SET_FLAG(F_AF);
528 if (d > 0x9F || ACCESS_FLAG(F_CF)) {
529 d -= 0x60;
530 SET_FLAG(F_CF);
532 CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
533 CONDITIONAL_SET_FLAG(d == 0, F_ZF);
534 CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
535 return d;
538 /****************************************************************************
539 REMARKS:
540 Implements the DEC instruction and side effects.
541 ****************************************************************************/
542 u8 dec_byte(u8 d)
544 register u32 res; /* all operands in native machine order */
545 register u32 bc;
547 res = d - 1;
548 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
549 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
550 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
552 /* calculate the borrow chain. See note at top */
553 /* based on sub_byte, uses s==1. */
554 bc = (res & (~d | 1)) | (~d & 1);
555 /* carry flag unchanged */
556 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
557 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
558 return (u8)res;
561 /****************************************************************************
562 REMARKS:
563 Implements the DEC instruction and side effects.
564 ****************************************************************************/
565 u16 dec_word(u16 d)
567 register u32 res; /* all operands in native machine order */
568 register u32 bc;
570 res = d - 1;
571 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
572 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
573 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
575 /* calculate the borrow chain. See note at top */
576 /* based on the sub_byte routine, with s==1 */
577 bc = (res & (~d | 1)) | (~d & 1);
578 /* carry flag unchanged */
579 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
580 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
581 return (u16)res;
584 /****************************************************************************
585 REMARKS:
586 Implements the DEC instruction and side effects.
587 ****************************************************************************/
588 u32 dec_long(u32 d)
590 register u32 res; /* all operands in native machine order */
591 register u32 bc;
593 res = d - 1;
595 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
596 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
597 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
599 /* calculate the borrow chain. See note at top */
600 bc = (res & (~d | 1)) | (~d & 1);
601 /* carry flag unchanged */
602 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
603 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
604 return res;
607 /****************************************************************************
608 REMARKS:
609 Implements the INC instruction and side effects.
610 ****************************************************************************/
611 u8 inc_byte(u8 d)
613 register u32 res; /* all operands in native machine order */
614 register u32 cc;
616 res = d + 1;
617 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
618 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
619 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
621 /* calculate the carry chain SEE NOTE AT TOP. */
622 cc = ((1 & d) | (~res)) & (1 | d);
623 CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
624 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
625 return (u8)res;
628 /****************************************************************************
629 REMARKS:
630 Implements the INC instruction and side effects.
631 ****************************************************************************/
632 u16 inc_word(u16 d)
634 register u32 res; /* all operands in native machine order */
635 register u32 cc;
637 res = d + 1;
638 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
639 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
640 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
642 /* calculate the carry chain SEE NOTE AT TOP. */
643 cc = (1 & d) | ((~res) & (1 | d));
644 CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
645 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
646 return (u16)res;
649 /****************************************************************************
650 REMARKS:
651 Implements the INC instruction and side effects.
652 ****************************************************************************/
653 u32 inc_long(u32 d)
655 register u32 res; /* all operands in native machine order */
656 register u32 cc;
658 res = d + 1;
659 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
660 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
661 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
663 /* calculate the carry chain SEE NOTE AT TOP. */
664 cc = (1 & d) | ((~res) & (1 | d));
665 CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
666 CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
667 return res;
670 /****************************************************************************
671 REMARKS:
672 Implements the OR instruction and side effects.
673 ****************************************************************************/
674 u8 or_byte(u8 d, u8 s)
676 register u8 res; /* all operands in native machine order */
678 res = d | s;
679 CLEAR_FLAG(F_OF);
680 CLEAR_FLAG(F_CF);
681 CLEAR_FLAG(F_AF);
682 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
683 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
684 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
685 return res;
688 /****************************************************************************
689 REMARKS:
690 Implements the OR instruction and side effects.
691 ****************************************************************************/
692 u16 or_word(u16 d, u16 s)
694 register u16 res; /* all operands in native machine order */
696 res = d | s;
697 /* set the carry flag to be bit 8 */
698 CLEAR_FLAG(F_OF);
699 CLEAR_FLAG(F_CF);
700 CLEAR_FLAG(F_AF);
701 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
702 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
703 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
704 return res;
707 /****************************************************************************
708 REMARKS:
709 Implements the OR instruction and side effects.
710 ****************************************************************************/
711 u32 or_long(u32 d, u32 s)
713 register u32 res; /* all operands in native machine order */
715 res = d | s;
717 /* set the carry flag to be bit 8 */
718 CLEAR_FLAG(F_OF);
719 CLEAR_FLAG(F_CF);
720 CLEAR_FLAG(F_AF);
721 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
722 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
723 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
724 return res;
727 /****************************************************************************
728 REMARKS:
729 Implements the OR instruction and side effects.
730 ****************************************************************************/
731 u8 neg_byte(u8 s)
733 register u8 res;
734 register u8 bc;
736 CONDITIONAL_SET_FLAG(s != 0, F_CF);
737 res = (u8)-s;
738 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
739 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
740 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
741 /* calculate the borrow chain --- modified such that d=0.
742 substitutiing d=0 into bc= res&(~d|s)|(~d&s);
743 (the one used for sub) and simplifying, since ~d=0xff...,
744 ~d|s == 0xffff..., and res&0xfff... == res. Similarly
745 ~d&s == s. So the simplified result is: */
746 bc = res | s;
747 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
748 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
749 return res;
752 /****************************************************************************
753 REMARKS:
754 Implements the OR instruction and side effects.
755 ****************************************************************************/
756 u16 neg_word(u16 s)
758 register u16 res;
759 register u16 bc;
761 CONDITIONAL_SET_FLAG(s != 0, F_CF);
762 res = (u16)-s;
763 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
764 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
765 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
767 /* calculate the borrow chain --- modified such that d=0.
768 substitutiing d=0 into bc= res&(~d|s)|(~d&s);
769 (the one used for sub) and simplifying, since ~d=0xff...,
770 ~d|s == 0xffff..., and res&0xfff... == res. Similarly
771 ~d&s == s. So the simplified result is: */
772 bc = res | s;
773 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
774 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
775 return res;
778 /****************************************************************************
779 REMARKS:
780 Implements the OR instruction and side effects.
781 ****************************************************************************/
782 u32 neg_long(u32 s)
784 register u32 res;
785 register u32 bc;
787 CONDITIONAL_SET_FLAG(s != 0, F_CF);
788 res = (u32)-s;
789 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
790 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
791 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
793 /* calculate the borrow chain --- modified such that d=0.
794 substitutiing d=0 into bc= res&(~d|s)|(~d&s);
795 (the one used for sub) and simplifying, since ~d=0xff...,
796 ~d|s == 0xffff..., and res&0xfff... == res. Similarly
797 ~d&s == s. So the simplified result is: */
798 bc = res | s;
799 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
800 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
801 return res;
804 /****************************************************************************
805 REMARKS:
806 Implements the NOT instruction and side effects.
807 ****************************************************************************/
808 u8 not_byte(u8 s)
810 return ~s;
813 /****************************************************************************
814 REMARKS:
815 Implements the NOT instruction and side effects.
816 ****************************************************************************/
817 u16 not_word(u16 s)
819 return ~s;
822 /****************************************************************************
823 REMARKS:
824 Implements the NOT instruction and side effects.
825 ****************************************************************************/
826 u32 not_long(u32 s)
828 return ~s;
831 /****************************************************************************
832 REMARKS:
833 Implements the RCL instruction and side effects.
834 ****************************************************************************/
835 u8 rcl_byte(u8 d, u8 s)
837 register unsigned int res, cnt, mask, cf;
839 /* s is the rotate distance. It varies from 0 - 8. */
840 /* have
842 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
844 want to rotate through the carry by "s" bits. We could
845 loop, but that's inefficient. So the width is 9,
846 and we split into three parts:
848 The new carry flag (was B_n)
849 the stuff in B_n-1 .. B_0
850 the stuff in B_7 .. B_n+1
852 The new rotate is done mod 9, and given this,
853 for a rotation of n bits (mod 9) the new carry flag is
854 then located n bits from the MSB. The low part is
855 then shifted up cnt bits, and the high part is or'd
856 in. Using CAPS for new values, and lowercase for the
857 original values, this can be expressed as:
859 IF n > 0
860 1) CF <- b_(8-n)
861 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
862 3) B_(n-1) <- cf
863 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
865 res = d;
866 if ((cnt = s % 9) != 0) {
867 /* extract the new CARRY FLAG. */
868 /* CF <- b_(8-n) */
869 cf = (d >> (8 - cnt)) & 0x1;
871 /* get the low stuff which rotated
872 into the range B_7 .. B_cnt */
873 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
874 /* note that the right hand side done by the mask */
875 res = (d << cnt) & 0xff;
877 /* now the high stuff which rotated around
878 into the positions B_cnt-2 .. B_0 */
879 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
880 /* shift it downward, 7-(n-2) = 9-n positions.
881 and mask off the result before or'ing in.
883 mask = (1 << (cnt - 1)) - 1;
884 res |= (d >> (9 - cnt)) & mask;
886 /* if the carry flag was set, or it in. */
887 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
888 /* B_(n-1) <- cf */
889 res |= 1 << (cnt - 1);
891 /* set the new carry flag, based on the variable "cf" */
892 CONDITIONAL_SET_FLAG(cf, F_CF);
893 /* OVERFLOW is set *IFF* cnt==1, then it is the
894 xor of CF and the most significant bit. Blecck. */
895 /* parenthesized this expression since it appears to
896 be causing OF to be misset */
897 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
898 F_OF);
901 return (u8)res;
904 /****************************************************************************
905 REMARKS:
906 Implements the RCL instruction and side effects.
907 ****************************************************************************/
908 u16 rcl_word(u16 d, u8 s)
910 register unsigned int res, cnt, mask, cf;
912 res = d;
913 if ((cnt = s % 17) != 0) {
914 cf = (d >> (16 - cnt)) & 0x1;
915 res = (d << cnt) & 0xffff;
916 mask = (1 << (cnt - 1)) - 1;
917 res |= (d >> (17 - cnt)) & mask;
918 if (ACCESS_FLAG(F_CF)) {
919 res |= 1 << (cnt - 1);
921 CONDITIONAL_SET_FLAG(cf, F_CF);
922 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
923 F_OF);
925 return (u16)res;
928 /****************************************************************************
929 REMARKS:
930 Implements the RCL instruction and side effects.
931 ****************************************************************************/
932 u32 rcl_long(u32 d, u8 s)
934 register u32 res, cnt, mask, cf;
936 res = d;
937 if ((cnt = s % 33) != 0) {
938 cf = (d >> (32 - cnt)) & 0x1;
939 res = (d << cnt) & 0xffffffff;
940 mask = (1 << (cnt - 1)) - 1;
941 res |= (d >> (33 - cnt)) & mask;
942 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
943 res |= 1 << (cnt - 1);
945 CONDITIONAL_SET_FLAG(cf, F_CF);
946 CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
947 F_OF);
949 return res;
952 /****************************************************************************
953 REMARKS:
954 Implements the RCR instruction and side effects.
955 ****************************************************************************/
956 u8 rcr_byte(u8 d, u8 s)
958 u32 res, cnt;
959 u32 mask, cf, ocf = 0;
961 /* rotate right through carry */
963 s is the rotate distance. It varies from 0 - 8.
964 d is the byte object rotated.
966 have
968 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
970 The new rotate is done mod 9, and given this,
971 for a rotation of n bits (mod 9) the new carry flag is
972 then located n bits from the LSB. The low part is
973 then shifted up cnt bits, and the high part is or'd
974 in. Using CAPS for new values, and lowercase for the
975 original values, this can be expressed as:
977 IF n > 0
978 1) CF <- b_(n-1)
979 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
980 3) B_(8-n) <- cf
981 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
983 res = d;
984 if ((cnt = s % 9) != 0) {
985 /* extract the new CARRY FLAG. */
986 /* CF <- b_(n-1) */
987 if (cnt == 1) {
988 cf = d & 0x1;
989 /* note hackery here. Access_flag(..) evaluates to either
990 0 if flag not set
991 non-zero if flag is set.
992 doing access_flag(..) != 0 casts that into either
993 0..1 in any representation of the flags register
994 (i.e. packed bit array or unpacked.)
996 ocf = ACCESS_FLAG(F_CF) != 0;
997 } else
998 cf = (d >> (cnt - 1)) & 0x1;
1000 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
1001 /* note that the right hand side done by the mask
1002 This is effectively done by shifting the
1003 object to the right. The result must be masked,
1004 in case the object came in and was treated
1005 as a negative number. Needed??? */
1007 mask = (1 << (8 - cnt)) - 1;
1008 res = (d >> cnt) & mask;
1010 /* now the high stuff which rotated around
1011 into the positions B_cnt-2 .. B_0 */
1012 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
1013 /* shift it downward, 7-(n-2) = 9-n positions.
1014 and mask off the result before or'ing in.
1016 res |= (d << (9 - cnt));
1018 /* if the carry flag was set, or it in. */
1019 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
1020 /* B_(8-n) <- cf */
1021 res |= 1 << (8 - cnt);
1023 /* set the new carry flag, based on the variable "cf" */
1024 CONDITIONAL_SET_FLAG(cf, F_CF);
1025 /* OVERFLOW is set *IFF* cnt==1, then it is the
1026 xor of CF and the most significant bit. Blecck. */
1027 /* parenthesized... */
1028 if (cnt == 1) {
1029 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
1030 F_OF);
1033 return (u8)res;
1036 /****************************************************************************
1037 REMARKS:
1038 Implements the RCR instruction and side effects.
1039 ****************************************************************************/
1040 u16 rcr_word(u16 d, u8 s)
1042 u32 res, cnt;
1043 u32 mask, cf, ocf = 0;
1045 /* rotate right through carry */
1046 res = d;
1047 if ((cnt = s % 17) != 0) {
1048 if (cnt == 1) {
1049 cf = d & 0x1;
1050 ocf = ACCESS_FLAG(F_CF) != 0;
1051 } else
1052 cf = (d >> (cnt - 1)) & 0x1;
1053 mask = (1 << (16 - cnt)) - 1;
1054 res = (d >> cnt) & mask;
1055 res |= (d << (17 - cnt));
1056 if (ACCESS_FLAG(F_CF)) {
1057 res |= 1 << (16 - cnt);
1059 CONDITIONAL_SET_FLAG(cf, F_CF);
1060 if (cnt == 1) {
1061 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
1062 F_OF);
1065 return (u16)res;
1068 /****************************************************************************
1069 REMARKS:
1070 Implements the RCR instruction and side effects.
1071 ****************************************************************************/
1072 u32 rcr_long(u32 d, u8 s)
1074 u32 res, cnt;
1075 u32 mask, cf, ocf = 0;
1077 /* rotate right through carry */
1078 res = d;
1079 if ((cnt = s % 33) != 0) {
1080 if (cnt == 1) {
1081 cf = d & 0x1;
1082 ocf = ACCESS_FLAG(F_CF) != 0;
1083 } else
1084 cf = (d >> (cnt - 1)) & 0x1;
1085 mask = (1 << (32 - cnt)) - 1;
1086 res = (d >> cnt) & mask;
1087 if (cnt != 1)
1088 res |= (d << (33 - cnt));
1089 if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
1090 res |= 1 << (32 - cnt);
1092 CONDITIONAL_SET_FLAG(cf, F_CF);
1093 if (cnt == 1) {
1094 CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
1095 F_OF);
1098 return res;
1101 /****************************************************************************
1102 REMARKS:
1103 Implements the ROL instruction and side effects.
1104 ****************************************************************************/
1105 u8 rol_byte(u8 d, u8 s)
1107 register unsigned int res, cnt, mask;
1109 /* rotate left */
1111 s is the rotate distance. It varies from 0 - 8.
1112 d is the byte object rotated.
1114 have
1116 CF B_7 ... B_0
1118 The new rotate is done mod 8.
1119 Much simpler than the "rcl" or "rcr" operations.
1121 IF n > 0
1122 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
1123 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
1125 res = d;
1126 if ((cnt = s % 8) != 0) {
1127 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
1128 res = (d << cnt);
1130 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
1131 mask = (1 << cnt) - 1;
1132 res |= (d >> (8 - cnt)) & mask;
1134 /* set the new carry flag, Note that it is the low order
1135 bit of the result!!! */
1136 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1137 /* OVERFLOW is set *IFF* s==1, then it is the
1138 xor of CF and the most significant bit. Blecck. */
1139 CONDITIONAL_SET_FLAG(s == 1 &&
1140 XOR2((res & 0x1) + ((res >> 6) & 0x2)),
1141 F_OF);
1142 } if (s != 0) {
1143 /* set the new carry flag, Note that it is the low order
1144 bit of the result!!! */
1145 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1147 return (u8)res;
1150 /****************************************************************************
1151 REMARKS:
1152 Implements the ROL instruction and side effects.
1153 ****************************************************************************/
1154 u16 rol_word(u16 d, u8 s)
1156 register unsigned int res, cnt, mask;
1158 res = d;
1159 if ((cnt = s % 16) != 0) {
1160 res = (d << cnt);
1161 mask = (1 << cnt) - 1;
1162 res |= (d >> (16 - cnt)) & mask;
1163 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1164 CONDITIONAL_SET_FLAG(s == 1 &&
1165 XOR2((res & 0x1) + ((res >> 14) & 0x2)),
1166 F_OF);
1167 } if (s != 0) {
1168 /* set the new carry flag, Note that it is the low order
1169 bit of the result!!! */
1170 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1172 return (u16)res;
1175 /****************************************************************************
1176 REMARKS:
1177 Implements the ROL instruction and side effects.
1178 ****************************************************************************/
1179 u32 rol_long(u32 d, u8 s)
1181 register u32 res, cnt, mask;
1183 res = d;
1184 if ((cnt = s % 32) != 0) {
1185 res = (d << cnt);
1186 mask = (1 << cnt) - 1;
1187 res |= (d >> (32 - cnt)) & mask;
1188 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1189 CONDITIONAL_SET_FLAG(s == 1 &&
1190 XOR2((res & 0x1) + ((res >> 30) & 0x2)),
1191 F_OF);
1192 } if (s != 0) {
1193 /* set the new carry flag, Note that it is the low order
1194 bit of the result!!! */
1195 CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
1197 return res;
1200 /****************************************************************************
1201 REMARKS:
1202 Implements the ROR instruction and side effects.
1203 ****************************************************************************/
1204 u8 ror_byte(u8 d, u8 s)
1206 register unsigned int res, cnt, mask;
1208 /* rotate right */
1210 s is the rotate distance. It varies from 0 - 8.
1211 d is the byte object rotated.
1213 have
1215 B_7 ... B_0
1217 The rotate is done mod 8.
1219 IF n > 0
1220 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
1221 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
1223 res = d;
1224 if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
1225 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
1226 res = (d << (8 - cnt));
1228 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
1229 mask = (1 << (8 - cnt)) - 1;
1230 res |= (d >> (cnt)) & mask;
1232 /* set the new carry flag, Note that it is the low order
1233 bit of the result!!! */
1234 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1235 /* OVERFLOW is set *IFF* s==1, then it is the
1236 xor of the two most significant bits. Blecck. */
1237 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
1238 } else if (s != 0) {
1239 /* set the new carry flag, Note that it is the low order
1240 bit of the result!!! */
1241 CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
1243 return (u8)res;
1246 /****************************************************************************
1247 REMARKS:
1248 Implements the ROR instruction and side effects.
1249 ****************************************************************************/
1250 u16 ror_word(u16 d, u8 s)
1252 register unsigned int res, cnt, mask;
1254 res = d;
1255 if ((cnt = s % 16) != 0) {
1256 res = (d << (16 - cnt));
1257 mask = (1 << (16 - cnt)) - 1;
1258 res |= (d >> (cnt)) & mask;
1259 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1260 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
1261 } else if (s != 0) {
1262 /* set the new carry flag, Note that it is the low order
1263 bit of the result!!! */
1264 CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
1266 return (u16)res;
1269 /****************************************************************************
1270 REMARKS:
1271 Implements the ROR instruction and side effects.
1272 ****************************************************************************/
1273 u32 ror_long(u32 d, u8 s)
1275 register u32 res, cnt, mask;
1277 res = d;
1278 if ((cnt = s % 32) != 0) {
1279 res = (d << (32 - cnt));
1280 mask = (1 << (32 - cnt)) - 1;
1281 res |= (d >> (cnt)) & mask;
1282 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1283 CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
1284 } else if (s != 0) {
1285 /* set the new carry flag, Note that it is the low order
1286 bit of the result!!! */
1287 CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
1289 return res;
1292 /****************************************************************************
1293 REMARKS:
1294 Implements the SHL instruction and side effects.
1295 ****************************************************************************/
1296 u8 shl_byte(u8 d, u8 s)
1298 unsigned int cnt, res, cf;
1300 if (s < 8) {
1301 cnt = s % 8;
1303 /* last bit shifted out goes into carry flag */
1304 if (cnt > 0) {
1305 res = d << cnt;
1306 cf = d & (1 << (8 - cnt));
1307 CONDITIONAL_SET_FLAG(cf, F_CF);
1308 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1309 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1310 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1311 } else {
1312 res = (u8) d;
1315 if (cnt == 1) {
1316 /* Needs simplification. */
1317 CONDITIONAL_SET_FLAG(
1318 (((res & 0x80) == 0x80) ^
1319 (ACCESS_FLAG(F_CF) != 0)),
1320 /* was (M.x86.R_FLG&F_CF)==F_CF)), */
1321 F_OF);
1322 } else {
1323 CLEAR_FLAG(F_OF);
1325 } else {
1326 res = 0;
1327 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80, F_CF);
1328 CLEAR_FLAG(F_OF);
1329 CLEAR_FLAG(F_SF);
1330 SET_FLAG(F_PF);
1331 SET_FLAG(F_ZF);
1333 return (u8)res;
1336 /****************************************************************************
1337 REMARKS:
1338 Implements the SHL instruction and side effects.
1339 ****************************************************************************/
1340 u16 shl_word(u16 d, u8 s)
1342 unsigned int cnt, res, cf;
1344 if (s < 16) {
1345 cnt = s % 16;
1346 if (cnt > 0) {
1347 res = d << cnt;
1348 cf = d & (1 << (16 - cnt));
1349 CONDITIONAL_SET_FLAG(cf, F_CF);
1350 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1351 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1352 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1353 } else {
1354 res = (u16) d;
1357 if (cnt == 1) {
1358 CONDITIONAL_SET_FLAG(
1359 (((res & 0x8000) == 0x8000) ^
1360 (ACCESS_FLAG(F_CF) != 0)),
1361 F_OF);
1362 } else {
1363 CLEAR_FLAG(F_OF);
1365 } else {
1366 res = 0;
1367 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1368 CLEAR_FLAG(F_OF);
1369 CLEAR_FLAG(F_SF);
1370 SET_FLAG(F_PF);
1371 SET_FLAG(F_ZF);
1373 return (u16)res;
1376 /****************************************************************************
1377 REMARKS:
1378 Implements the SHL instruction and side effects.
1379 ****************************************************************************/
1380 u32 shl_long(u32 d, u8 s)
1382 unsigned int cnt, res, cf;
1384 if (s < 32) {
1385 cnt = s % 32;
1386 if (cnt > 0) {
1387 res = d << cnt;
1388 cf = d & (1 << (32 - cnt));
1389 CONDITIONAL_SET_FLAG(cf, F_CF);
1390 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1391 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1392 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1393 } else {
1394 res = d;
1396 if (cnt == 1) {
1397 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1398 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1399 } else {
1400 CLEAR_FLAG(F_OF);
1402 } else {
1403 res = 0;
1404 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1405 CLEAR_FLAG(F_OF);
1406 CLEAR_FLAG(F_SF);
1407 SET_FLAG(F_PF);
1408 SET_FLAG(F_ZF);
1410 return res;
1413 /****************************************************************************
1414 REMARKS:
1415 Implements the SHR instruction and side effects.
1416 ****************************************************************************/
1417 u8 shr_byte(u8 d, u8 s)
1419 unsigned int cnt, res, cf;
1421 if (s < 8) {
1422 cnt = s % 8;
1423 if (cnt > 0) {
1424 cf = d & (1 << (cnt - 1));
1425 res = d >> cnt;
1426 CONDITIONAL_SET_FLAG(cf, F_CF);
1427 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1428 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1429 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1430 } else {
1431 res = (u8) d;
1434 if (cnt == 1) {
1435 CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
1436 } else {
1437 CLEAR_FLAG(F_OF);
1439 } else {
1440 res = 0;
1441 CONDITIONAL_SET_FLAG((d >> (s-1)) & 0x1, F_CF);
1442 CLEAR_FLAG(F_OF);
1443 CLEAR_FLAG(F_SF);
1444 SET_FLAG(F_PF);
1445 SET_FLAG(F_ZF);
1447 return (u8)res;
1450 /****************************************************************************
1451 REMARKS:
1452 Implements the SHR instruction and side effects.
1453 ****************************************************************************/
1454 u16 shr_word(u16 d, u8 s)
1456 unsigned int cnt, res, cf;
1458 if (s < 16) {
1459 cnt = s % 16;
1460 if (cnt > 0) {
1461 cf = d & (1 << (cnt - 1));
1462 res = d >> cnt;
1463 CONDITIONAL_SET_FLAG(cf, F_CF);
1464 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1465 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1466 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1467 } else {
1468 res = d;
1471 if (cnt == 1) {
1472 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1473 } else {
1474 CLEAR_FLAG(F_OF);
1476 } else {
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);
1484 return (u16)res;
1487 /****************************************************************************
1488 REMARKS:
1489 Implements the SHR instruction and side effects.
1490 ****************************************************************************/
1491 u32 shr_long(u32 d, u8 s)
1493 unsigned int cnt, res, cf;
1495 if (s < 32) {
1496 cnt = s % 32;
1497 if (cnt > 0) {
1498 cf = d & (1 << (cnt - 1));
1499 res = d >> cnt;
1500 CONDITIONAL_SET_FLAG(cf, F_CF);
1501 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1502 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1503 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1504 } else {
1505 res = d;
1507 if (cnt == 1) {
1508 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1509 } else {
1510 CLEAR_FLAG(F_OF);
1512 } else {
1513 res = 0;
1514 CLEAR_FLAG(F_CF);
1515 CLEAR_FLAG(F_OF);
1516 SET_FLAG(F_ZF);
1517 CLEAR_FLAG(F_SF);
1518 CLEAR_FLAG(F_PF);
1520 return res;
1523 /****************************************************************************
1524 REMARKS:
1525 Implements the SAR instruction and side effects.
1526 ****************************************************************************/
1527 u8 sar_byte(u8 d, u8 s)
1529 unsigned int cnt, res, cf, mask, sf;
1531 res = d;
1532 sf = d & 0x80;
1533 cnt = s % 8;
1534 if (cnt > 0 && cnt < 8) {
1535 mask = (1 << (8 - cnt)) - 1;
1536 cf = d & (1 << (cnt - 1));
1537 res = (d >> cnt) & mask;
1538 CONDITIONAL_SET_FLAG(cf, F_CF);
1539 if (sf) {
1540 res |= ~mask;
1542 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1543 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1544 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1545 } else if (cnt >= 8) {
1546 if (sf) {
1547 res = 0xff;
1548 SET_FLAG(F_CF);
1549 CLEAR_FLAG(F_ZF);
1550 SET_FLAG(F_SF);
1551 SET_FLAG(F_PF);
1552 } else {
1553 res = 0;
1554 CLEAR_FLAG(F_CF);
1555 SET_FLAG(F_ZF);
1556 CLEAR_FLAG(F_SF);
1557 CLEAR_FLAG(F_PF);
1560 return (u8)res;
1563 /****************************************************************************
1564 REMARKS:
1565 Implements the SAR instruction and side effects.
1566 ****************************************************************************/
1567 u16 sar_word(u16 d, u8 s)
1569 unsigned int cnt, res, cf, mask, sf;
1571 sf = d & 0x8000;
1572 cnt = s % 16;
1573 res = d;
1574 if (cnt > 0 && cnt < 16) {
1575 mask = (1 << (16 - cnt)) - 1;
1576 cf = d & (1 << (cnt - 1));
1577 res = (d >> cnt) & mask;
1578 CONDITIONAL_SET_FLAG(cf, F_CF);
1579 if (sf) {
1580 res |= ~mask;
1582 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1583 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1584 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1585 } else if (cnt >= 16) {
1586 if (sf) {
1587 res = 0xffff;
1588 SET_FLAG(F_CF);
1589 CLEAR_FLAG(F_ZF);
1590 SET_FLAG(F_SF);
1591 SET_FLAG(F_PF);
1592 } else {
1593 res = 0;
1594 CLEAR_FLAG(F_CF);
1595 SET_FLAG(F_ZF);
1596 CLEAR_FLAG(F_SF);
1597 CLEAR_FLAG(F_PF);
1600 return (u16)res;
1603 /****************************************************************************
1604 REMARKS:
1605 Implements the SAR instruction and side effects.
1606 ****************************************************************************/
1607 u32 sar_long(u32 d, u8 s)
1609 u32 cnt, res, cf, mask, sf;
1611 sf = d & 0x80000000;
1612 cnt = s % 32;
1613 res = d;
1614 if (cnt > 0 && cnt < 32) {
1615 mask = (1 << (32 - cnt)) - 1;
1616 cf = d & (1 << (cnt - 1));
1617 res = (d >> cnt) & mask;
1618 CONDITIONAL_SET_FLAG(cf, F_CF);
1619 if (sf) {
1620 res |= ~mask;
1622 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1623 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1624 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1625 } else if (cnt >= 32) {
1626 if (sf) {
1627 res = 0xffffffff;
1628 SET_FLAG(F_CF);
1629 CLEAR_FLAG(F_ZF);
1630 SET_FLAG(F_SF);
1631 SET_FLAG(F_PF);
1632 } else {
1633 res = 0;
1634 CLEAR_FLAG(F_CF);
1635 SET_FLAG(F_ZF);
1636 CLEAR_FLAG(F_SF);
1637 CLEAR_FLAG(F_PF);
1640 return res;
1643 /****************************************************************************
1644 REMARKS:
1645 Implements the SHLD instruction and side effects.
1646 ****************************************************************************/
1647 u16 shld_word (u16 d, u16 fill, u8 s)
1649 unsigned int cnt, res, cf;
1651 if (s < 16) {
1652 cnt = s % 16;
1653 if (cnt > 0) {
1654 res = (d << cnt) | (fill >> (16-cnt));
1655 cf = d & (1 << (16 - cnt));
1656 CONDITIONAL_SET_FLAG(cf, F_CF);
1657 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1658 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1659 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1660 } else {
1661 res = d;
1663 if (cnt == 1) {
1664 CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
1665 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1666 } else {
1667 CLEAR_FLAG(F_OF);
1669 } else {
1670 res = 0;
1671 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x8000, F_CF);
1672 CLEAR_FLAG(F_OF);
1673 CLEAR_FLAG(F_SF);
1674 SET_FLAG(F_PF);
1675 SET_FLAG(F_ZF);
1677 return (u16)res;
1680 /****************************************************************************
1681 REMARKS:
1682 Implements the SHLD instruction and side effects.
1683 ****************************************************************************/
1684 u32 shld_long (u32 d, u32 fill, u8 s)
1686 unsigned int cnt, res, cf;
1688 if (s < 32) {
1689 cnt = s % 32;
1690 if (cnt > 0) {
1691 res = (d << cnt) | (fill >> (32-cnt));
1692 cf = d & (1 << (32 - cnt));
1693 CONDITIONAL_SET_FLAG(cf, F_CF);
1694 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1695 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1696 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1697 } else {
1698 res = d;
1700 if (cnt == 1) {
1701 CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000) ^
1702 (ACCESS_FLAG(F_CF) != 0)), F_OF);
1703 } else {
1704 CLEAR_FLAG(F_OF);
1706 } else {
1707 res = 0;
1708 CONDITIONAL_SET_FLAG((d << (s-1)) & 0x80000000, F_CF);
1709 CLEAR_FLAG(F_OF);
1710 CLEAR_FLAG(F_SF);
1711 SET_FLAG(F_PF);
1712 SET_FLAG(F_ZF);
1714 return res;
1717 /****************************************************************************
1718 REMARKS:
1719 Implements the SHRD instruction and side effects.
1720 ****************************************************************************/
1721 u16 shrd_word (u16 d, u16 fill, u8 s)
1723 unsigned int cnt, res, cf;
1725 if (s < 16) {
1726 cnt = s % 16;
1727 if (cnt > 0) {
1728 cf = d & (1 << (cnt - 1));
1729 res = (d >> cnt) | (fill << (16 - cnt));
1730 CONDITIONAL_SET_FLAG(cf, F_CF);
1731 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1732 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1733 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1734 } else {
1735 res = d;
1738 if (cnt == 1) {
1739 CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
1740 } else {
1741 CLEAR_FLAG(F_OF);
1743 } else {
1744 res = 0;
1745 CLEAR_FLAG(F_CF);
1746 CLEAR_FLAG(F_OF);
1747 SET_FLAG(F_ZF);
1748 CLEAR_FLAG(F_SF);
1749 CLEAR_FLAG(F_PF);
1751 return (u16)res;
1754 /****************************************************************************
1755 REMARKS:
1756 Implements the SHRD instruction and side effects.
1757 ****************************************************************************/
1758 u32 shrd_long (u32 d, u32 fill, u8 s)
1760 unsigned int cnt, res, cf;
1762 if (s < 32) {
1763 cnt = s % 32;
1764 if (cnt > 0) {
1765 cf = d & (1 << (cnt - 1));
1766 res = (d >> cnt) | (fill << (32 - cnt));
1767 CONDITIONAL_SET_FLAG(cf, F_CF);
1768 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1769 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1770 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1771 } else {
1772 res = d;
1774 if (cnt == 1) {
1775 CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
1776 } else {
1777 CLEAR_FLAG(F_OF);
1779 } else {
1780 res = 0;
1781 CLEAR_FLAG(F_CF);
1782 CLEAR_FLAG(F_OF);
1783 SET_FLAG(F_ZF);
1784 CLEAR_FLAG(F_SF);
1785 CLEAR_FLAG(F_PF);
1787 return res;
1790 /****************************************************************************
1791 REMARKS:
1792 Implements the SBB instruction and side effects.
1793 ****************************************************************************/
1794 u8 sbb_byte(u8 d, u8 s)
1796 register u32 res; /* all operands in native machine order */
1797 register u32 bc;
1799 if (ACCESS_FLAG(F_CF))
1800 res = d - s - 1;
1801 else
1802 res = d - s;
1803 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1804 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1805 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1807 /* calculate the borrow chain. See note at top */
1808 bc = (res & (~d | s)) | (~d & s);
1809 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1810 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1811 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1812 return (u8)res;
1815 /****************************************************************************
1816 REMARKS:
1817 Implements the SBB instruction and side effects.
1818 ****************************************************************************/
1819 u16 sbb_word(u16 d, u16 s)
1821 register u32 res; /* all operands in native machine order */
1822 register u32 bc;
1824 if (ACCESS_FLAG(F_CF))
1825 res = d - s - 1;
1826 else
1827 res = d - s;
1828 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1829 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1830 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1832 /* calculate the borrow chain. See note at top */
1833 bc = (res & (~d | s)) | (~d & s);
1834 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1835 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1836 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1837 return (u16)res;
1840 /****************************************************************************
1841 REMARKS:
1842 Implements the SBB instruction and side effects.
1843 ****************************************************************************/
1844 u32 sbb_long(u32 d, u32 s)
1846 register u32 res; /* all operands in native machine order */
1847 register u32 bc;
1849 if (ACCESS_FLAG(F_CF))
1850 res = d - s - 1;
1851 else
1852 res = d - s;
1853 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1854 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1855 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1857 /* calculate the borrow chain. See note at top */
1858 bc = (res & (~d | s)) | (~d & s);
1859 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1860 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1861 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1862 return res;
1865 /****************************************************************************
1866 REMARKS:
1867 Implements the SUB instruction and side effects.
1868 ****************************************************************************/
1869 u8 sub_byte(u8 d, u8 s)
1871 register u32 res; /* all operands in native machine order */
1872 register u32 bc;
1874 res = d - s;
1875 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1876 CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
1877 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1879 /* calculate the borrow chain. See note at top */
1880 bc = (res & (~d | s)) | (~d & s);
1881 CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
1882 CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
1883 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1884 return (u8)res;
1887 /****************************************************************************
1888 REMARKS:
1889 Implements the SUB instruction and side effects.
1890 ****************************************************************************/
1891 u16 sub_word(u16 d, u16 s)
1893 register u32 res; /* all operands in native machine order */
1894 register u32 bc;
1896 res = d - s;
1897 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1898 CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
1899 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1901 /* calculate the borrow chain. See note at top */
1902 bc = (res & (~d | s)) | (~d & s);
1903 CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
1904 CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
1905 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1906 return (u16)res;
1909 /****************************************************************************
1910 REMARKS:
1911 Implements the SUB instruction and side effects.
1912 ****************************************************************************/
1913 u32 sub_long(u32 d, u32 s)
1915 register u32 res; /* all operands in native machine order */
1916 register u32 bc;
1918 res = d - s;
1919 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1920 CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
1921 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1923 /* calculate the borrow chain. See note at top */
1924 bc = (res & (~d | s)) | (~d & s);
1925 CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
1926 CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
1927 CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
1928 return res;
1931 /****************************************************************************
1932 REMARKS:
1933 Implements the TEST instruction and side effects.
1934 ****************************************************************************/
1935 void test_byte(u8 d, u8 s)
1937 register u32 res; /* all operands in native machine order */
1939 res = d & s;
1941 CLEAR_FLAG(F_OF);
1942 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1943 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1944 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1945 /* AF == dont care */
1946 CLEAR_FLAG(F_CF);
1949 /****************************************************************************
1950 REMARKS:
1951 Implements the TEST instruction and side effects.
1952 ****************************************************************************/
1953 void test_word(u16 d, u16 s)
1955 register u32 res; /* all operands in native machine order */
1957 res = d & s;
1959 CLEAR_FLAG(F_OF);
1960 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
1961 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1962 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1963 /* AF == dont care */
1964 CLEAR_FLAG(F_CF);
1967 /****************************************************************************
1968 REMARKS:
1969 Implements the TEST instruction and side effects.
1970 ****************************************************************************/
1971 void test_long(u32 d, u32 s)
1973 register u32 res; /* all operands in native machine order */
1975 res = d & s;
1977 CLEAR_FLAG(F_OF);
1978 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
1979 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1980 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
1981 /* AF == dont care */
1982 CLEAR_FLAG(F_CF);
1985 /****************************************************************************
1986 REMARKS:
1987 Implements the XOR instruction and side effects.
1988 ****************************************************************************/
1989 u8 xor_byte(u8 d, u8 s)
1991 register u8 res; /* all operands in native machine order */
1993 res = d ^ s;
1994 CLEAR_FLAG(F_OF);
1995 CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
1996 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
1997 CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
1998 CLEAR_FLAG(F_CF);
1999 CLEAR_FLAG(F_AF);
2000 return res;
2003 /****************************************************************************
2004 REMARKS:
2005 Implements the XOR instruction and side effects.
2006 ****************************************************************************/
2007 u16 xor_word(u16 d, u16 s)
2009 register u16 res; /* all operands in native machine order */
2011 res = d ^ s;
2012 CLEAR_FLAG(F_OF);
2013 CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
2014 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2015 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2016 CLEAR_FLAG(F_CF);
2017 CLEAR_FLAG(F_AF);
2018 return res;
2021 /****************************************************************************
2022 REMARKS:
2023 Implements the XOR instruction and side effects.
2024 ****************************************************************************/
2025 u32 xor_long(u32 d, u32 s)
2027 register u32 res; /* all operands in native machine order */
2029 res = d ^ s;
2030 CLEAR_FLAG(F_OF);
2031 CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
2032 CONDITIONAL_SET_FLAG(res == 0, F_ZF);
2033 CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
2034 CLEAR_FLAG(F_CF);
2035 CLEAR_FLAG(F_AF);
2036 return res;
2039 /****************************************************************************
2040 REMARKS:
2041 Implements the IMUL instruction and side effects.
2042 ****************************************************************************/
2043 void imul_byte(u8 s)
2045 s16 res = (s16)((s8)M.x86.R_AL * (s8)s);
2047 M.x86.R_AX = res;
2048 if (((M.x86.R_AL & 0x80) == 0 && M.x86.R_AH == 0x00) ||
2049 ((M.x86.R_AL & 0x80) != 0 && M.x86.R_AH == 0xFF)) {
2050 CLEAR_FLAG(F_CF);
2051 CLEAR_FLAG(F_OF);
2052 } else {
2053 SET_FLAG(F_CF);
2054 SET_FLAG(F_OF);
2058 /****************************************************************************
2059 REMARKS:
2060 Implements the IMUL instruction and side effects.
2061 ****************************************************************************/
2062 void imul_word(u16 s)
2064 s32 res = (s16)M.x86.R_AX * (s16)s;
2066 M.x86.R_AX = (u16)res;
2067 M.x86.R_DX = (u16)(res >> 16);
2068 if (((M.x86.R_AX & 0x8000) == 0 && M.x86.R_DX == 0x00) ||
2069 ((M.x86.R_AX & 0x8000) != 0 && M.x86.R_DX == 0xFF)) {
2070 CLEAR_FLAG(F_CF);
2071 CLEAR_FLAG(F_OF);
2072 } else {
2073 SET_FLAG(F_CF);
2074 SET_FLAG(F_OF);
2078 /****************************************************************************
2079 REMARKS:
2080 Implements the IMUL instruction and side effects.
2081 ****************************************************************************/
2082 void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s)
2084 #ifdef __HAS_LONG_LONG__
2085 s64 res = (s32)d * (s32)s;
2087 *res_lo = (u32)res;
2088 *res_hi = (u32)(res >> 32);
2089 #else
2090 u32 d_lo,d_hi,d_sign;
2091 u32 s_lo,s_hi,s_sign;
2092 u32 rlo_lo,rlo_hi,rhi_lo;
2094 if ((d_sign = d & 0x80000000) != 0)
2095 d = -d;
2096 d_lo = d & 0xFFFF;
2097 d_hi = d >> 16;
2098 if ((s_sign = s & 0x80000000) != 0)
2099 s = -s;
2100 s_lo = s & 0xFFFF;
2101 s_hi = s >> 16;
2102 rlo_lo = d_lo * s_lo;
2103 rlo_hi = (d_hi * s_lo + d_lo * s_hi) + (rlo_lo >> 16);
2104 rhi_lo = d_hi * s_hi + (rlo_hi >> 16);
2105 *res_lo = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2106 *res_hi = rhi_lo;
2107 if (d_sign != s_sign) {
2108 d = ~*res_lo;
2109 s = (((d & 0xFFFF) + 1) >> 16) + (d >> 16);
2110 *res_lo = ~*res_lo+1;
2111 *res_hi = ~*res_hi+(s >> 16);
2113 #endif
2116 /****************************************************************************
2117 REMARKS:
2118 Implements the IMUL instruction and side effects.
2119 ****************************************************************************/
2120 void imul_long(u32 s)
2122 imul_long_direct(&M.x86.R_EAX,&M.x86.R_EDX,M.x86.R_EAX,s);
2123 if (((M.x86.R_EAX & 0x80000000) == 0 && M.x86.R_EDX == 0x00) ||
2124 ((M.x86.R_EAX & 0x80000000) != 0 && M.x86.R_EDX == 0xFF)) {
2125 CLEAR_FLAG(F_CF);
2126 CLEAR_FLAG(F_OF);
2127 } else {
2128 SET_FLAG(F_CF);
2129 SET_FLAG(F_OF);
2133 /****************************************************************************
2134 REMARKS:
2135 Implements the MUL instruction and side effects.
2136 ****************************************************************************/
2137 void mul_byte(u8 s)
2139 u16 res = (u16)(M.x86.R_AL * s);
2141 M.x86.R_AX = res;
2142 if (M.x86.R_AH == 0) {
2143 CLEAR_FLAG(F_CF);
2144 CLEAR_FLAG(F_OF);
2145 } else {
2146 SET_FLAG(F_CF);
2147 SET_FLAG(F_OF);
2151 /****************************************************************************
2152 REMARKS:
2153 Implements the MUL instruction and side effects.
2154 ****************************************************************************/
2155 void mul_word(u16 s)
2157 u32 res = M.x86.R_AX * s;
2159 M.x86.R_AX = (u16)res;
2160 M.x86.R_DX = (u16)(res >> 16);
2161 if (M.x86.R_DX == 0) {
2162 CLEAR_FLAG(F_CF);
2163 CLEAR_FLAG(F_OF);
2164 } else {
2165 SET_FLAG(F_CF);
2166 SET_FLAG(F_OF);
2170 /****************************************************************************
2171 REMARKS:
2172 Implements the MUL instruction and side effects.
2173 ****************************************************************************/
2174 void mul_long(u32 s)
2176 #ifdef __HAS_LONG_LONG__
2177 u64 res = (u32)M.x86.R_EAX * (u32)s;
2179 M.x86.R_EAX = (u32)res;
2180 M.x86.R_EDX = (u32)(res >> 32);
2181 #else
2182 u32 a,a_lo,a_hi;
2183 u32 s_lo,s_hi;
2184 u32 rlo_lo,rlo_hi,rhi_lo;
2186 a = M.x86.R_EAX;
2187 a_lo = a & 0xFFFF;
2188 a_hi = a >> 16;
2189 s_lo = s & 0xFFFF;
2190 s_hi = s >> 16;
2191 rlo_lo = a_lo * s_lo;
2192 rlo_hi = (a_hi * s_lo + a_lo * s_hi) + (rlo_lo >> 16);
2193 rhi_lo = a_hi * s_hi + (rlo_hi >> 16);
2194 M.x86.R_EAX = (rlo_hi << 16) | (rlo_lo & 0xFFFF);
2195 M.x86.R_EDX = rhi_lo;
2196 #endif
2198 if (M.x86.R_EDX == 0) {
2199 CLEAR_FLAG(F_CF);
2200 CLEAR_FLAG(F_OF);
2201 } else {
2202 SET_FLAG(F_CF);
2203 SET_FLAG(F_OF);
2207 /****************************************************************************
2208 REMARKS:
2209 Implements the IDIV instruction and side effects.
2210 ****************************************************************************/
2211 void idiv_byte(u8 s)
2213 s32 dvd, div, mod;
2215 dvd = (s16)M.x86.R_AX;
2216 if (s == 0) {
2217 x86emu_intr_raise(0);
2218 return;
2220 div = dvd / (s8)s;
2221 mod = dvd % (s8)s;
2222 if (abs(div) > 0x7f) {
2223 x86emu_intr_raise(0);
2224 return;
2226 M.x86.R_AL = (s8) div;
2227 M.x86.R_AH = (s8) mod;
2230 /****************************************************************************
2231 REMARKS:
2232 Implements the IDIV instruction and side effects.
2233 ****************************************************************************/
2234 void idiv_word(u16 s)
2236 s32 dvd, div, mod;
2238 dvd = (((s32)M.x86.R_DX) << 16) | M.x86.R_AX;
2239 if (s == 0) {
2240 x86emu_intr_raise(0);
2241 return;
2243 div = dvd / (s16)s;
2244 mod = dvd % (s16)s;
2245 if (abs(div) > 0x7fff) {
2246 x86emu_intr_raise(0);
2247 return;
2249 CLEAR_FLAG(F_CF);
2250 CLEAR_FLAG(F_SF);
2251 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2252 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2254 M.x86.R_AX = (u16)div;
2255 M.x86.R_DX = (u16)mod;
2258 /****************************************************************************
2259 REMARKS:
2260 Implements the IDIV instruction and side effects.
2261 ****************************************************************************/
2262 void idiv_long(u32 s)
2264 #ifdef __HAS_LONG_LONG__
2265 s64 dvd, div, mod;
2267 dvd = (((s64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2268 if (s == 0) {
2269 x86emu_intr_raise(0);
2270 return;
2272 div = dvd / (s32)s;
2273 mod = dvd % (s32)s;
2274 if (abs(div) > 0x7fffffff) {
2275 x86emu_intr_raise(0);
2276 return;
2278 #else
2279 s32 div = 0, mod;
2280 s32 h_dvd = M.x86.R_EDX;
2281 u32 l_dvd = M.x86.R_EAX;
2282 u32 abs_s = s & 0x7FFFFFFF;
2283 u32 abs_h_dvd = h_dvd & 0x7FFFFFFF;
2284 u32 h_s = abs_s >> 1;
2285 u32 l_s = abs_s << 31;
2286 int counter = 31;
2287 int carry;
2289 if (s == 0) {
2290 x86emu_intr_raise(0);
2291 return;
2293 do {
2294 div <<= 1;
2295 carry = (l_dvd >= l_s) ? 0 : 1;
2297 if (abs_h_dvd < (h_s + carry)) {
2298 h_s >>= 1;
2299 l_s = abs_s << (--counter);
2300 continue;
2301 } else {
2302 abs_h_dvd -= (h_s + carry);
2303 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2304 : (l_dvd - l_s);
2305 h_s >>= 1;
2306 l_s = abs_s << (--counter);
2307 div |= 1;
2308 continue;
2311 } while (counter > -1);
2312 /* overflow */
2313 if (abs_h_dvd || (l_dvd > abs_s)) {
2314 x86emu_intr_raise(0);
2315 return;
2317 /* sign */
2318 div |= ((h_dvd & 0x10000000) ^ (s & 0x10000000));
2319 mod = l_dvd;
2321 #endif
2322 CLEAR_FLAG(F_CF);
2323 CLEAR_FLAG(F_AF);
2324 CLEAR_FLAG(F_SF);
2325 SET_FLAG(F_ZF);
2326 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2328 M.x86.R_EAX = (u32)div;
2329 M.x86.R_EDX = (u32)mod;
2332 /****************************************************************************
2333 REMARKS:
2334 Implements the DIV instruction and side effects.
2335 ****************************************************************************/
2336 void div_byte(u8 s)
2338 u32 dvd, div, mod;
2340 dvd = M.x86.R_AX;
2341 if (s == 0) {
2342 x86emu_intr_raise(0);
2343 return;
2345 div = dvd / (u8)s;
2346 mod = dvd % (u8)s;
2347 if (abs(div) > 0xff) {
2348 x86emu_intr_raise(0);
2349 return;
2351 M.x86.R_AL = (u8)div;
2352 M.x86.R_AH = (u8)mod;
2355 /****************************************************************************
2356 REMARKS:
2357 Implements the DIV instruction and side effects.
2358 ****************************************************************************/
2359 void div_word(u16 s)
2361 u32 dvd, div, mod;
2363 dvd = (((u32)M.x86.R_DX) << 16) | M.x86.R_AX;
2364 if (s == 0) {
2365 x86emu_intr_raise(0);
2366 return;
2368 div = dvd / (u16)s;
2369 mod = dvd % (u16)s;
2370 if (abs(div) > 0xffff) {
2371 x86emu_intr_raise(0);
2372 return;
2374 CLEAR_FLAG(F_CF);
2375 CLEAR_FLAG(F_SF);
2376 CONDITIONAL_SET_FLAG(div == 0, F_ZF);
2377 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2379 M.x86.R_AX = (u16)div;
2380 M.x86.R_DX = (u16)mod;
2383 /****************************************************************************
2384 REMARKS:
2385 Implements the DIV instruction and side effects.
2386 ****************************************************************************/
2387 void div_long(u32 s)
2389 #ifdef __HAS_LONG_LONG__
2390 u64 dvd, div, mod;
2392 dvd = (((u64)M.x86.R_EDX) << 32) | M.x86.R_EAX;
2393 if (s == 0) {
2394 x86emu_intr_raise(0);
2395 return;
2397 div = dvd / (u32)s;
2398 mod = dvd % (u32)s;
2399 if (abs(div) > 0xffffffff) {
2400 x86emu_intr_raise(0);
2401 return;
2403 #else
2404 s32 div = 0, mod;
2405 s32 h_dvd = M.x86.R_EDX;
2406 u32 l_dvd = M.x86.R_EAX;
2408 u32 h_s = s;
2409 u32 l_s = 0;
2410 int counter = 32;
2411 int carry;
2413 if (s == 0) {
2414 x86emu_intr_raise(0);
2415 return;
2417 do {
2418 div <<= 1;
2419 carry = (l_dvd >= l_s) ? 0 : 1;
2421 if (h_dvd < (h_s + carry)) {
2422 h_s >>= 1;
2423 l_s = s << (--counter);
2424 continue;
2425 } else {
2426 h_dvd -= (h_s + carry);
2427 l_dvd = carry ? ((0xFFFFFFFF - l_s) + l_dvd + 1)
2428 : (l_dvd - l_s);
2429 h_s >>= 1;
2430 l_s = s << (--counter);
2431 div |= 1;
2432 continue;
2435 } while (counter > -1);
2436 /* overflow */
2437 if (h_dvd || (l_dvd > s)) {
2438 x86emu_intr_raise(0);
2439 return;
2441 mod = l_dvd;
2442 #endif
2443 CLEAR_FLAG(F_CF);
2444 CLEAR_FLAG(F_AF);
2445 CLEAR_FLAG(F_SF);
2446 SET_FLAG(F_ZF);
2447 CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
2449 M.x86.R_EAX = (u32)div;
2450 M.x86.R_EDX = (u32)mod;
2453 /****************************************************************************
2454 REMARKS:
2455 Implements the IN string instruction and side effects.
2456 ****************************************************************************/
2457 void ins(int size)
2459 int inc = size;
2461 if (ACCESS_FLAG(F_DF)) {
2462 inc = -size;
2464 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2465 /* dont care whether REPE or REPNE */
2466 /* in until CX is ZERO. */
2467 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2468 M.x86.R_ECX : M.x86.R_CX);
2469 switch (size) {
2470 case 1:
2471 while (count--) {
2472 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2473 (*sys_inb)(M.x86.R_DX));
2474 M.x86.R_DI += inc;
2476 break;
2478 case 2:
2479 while (count--) {
2480 store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2481 (*sys_inw)(M.x86.R_DX));
2482 M.x86.R_DI += inc;
2484 break;
2485 case 4:
2486 while (count--) {
2487 store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2488 (*sys_inl)(M.x86.R_DX));
2489 M.x86.R_DI += inc;
2490 break;
2493 M.x86.R_CX = 0;
2494 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2495 M.x86.R_ECX = 0;
2497 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2498 } else {
2499 switch (size) {
2500 case 1:
2501 store_data_byte_abs(M.x86.R_ES, M.x86.R_DI,
2502 (*sys_inb)(M.x86.R_DX));
2503 break;
2504 case 2:
2505 store_data_word_abs(M.x86.R_ES, M.x86.R_DI,
2506 (*sys_inw)(M.x86.R_DX));
2507 break;
2508 case 4:
2509 store_data_long_abs(M.x86.R_ES, M.x86.R_DI,
2510 (*sys_inl)(M.x86.R_DX));
2511 break;
2513 M.x86.R_DI += inc;
2517 /****************************************************************************
2518 REMARKS:
2519 Implements the OUT string instruction and side effects.
2520 ****************************************************************************/
2521 void outs(int size)
2523 int inc = size;
2525 if (ACCESS_FLAG(F_DF)) {
2526 inc = -size;
2528 if (M.x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2529 /* dont care whether REPE or REPNE */
2530 /* out until CX is ZERO. */
2531 u32 count = ((M.x86.mode & SYSMODE_PREFIX_DATA) ?
2532 M.x86.R_ECX : M.x86.R_CX);
2533 switch (size) {
2534 case 1:
2535 while (count--) {
2536 (*sys_outb)(M.x86.R_DX,
2537 fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2538 M.x86.R_SI += inc;
2540 break;
2542 case 2:
2543 while (count--) {
2544 (*sys_outw)(M.x86.R_DX,
2545 fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2546 M.x86.R_SI += inc;
2548 break;
2549 case 4:
2550 while (count--) {
2551 (*sys_outl)(M.x86.R_DX,
2552 fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2553 M.x86.R_SI += inc;
2554 break;
2557 M.x86.R_CX = 0;
2558 if (M.x86.mode & SYSMODE_PREFIX_DATA) {
2559 M.x86.R_ECX = 0;
2561 M.x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2562 } else {
2563 switch (size) {
2564 case 1:
2565 (*sys_outb)(M.x86.R_DX,
2566 fetch_data_byte_abs(M.x86.R_ES, M.x86.R_SI));
2567 break;
2568 case 2:
2569 (*sys_outw)(M.x86.R_DX,
2570 fetch_data_word_abs(M.x86.R_ES, M.x86.R_SI));
2571 break;
2572 case 4:
2573 (*sys_outl)(M.x86.R_DX,
2574 fetch_data_long_abs(M.x86.R_ES, M.x86.R_SI));
2575 break;
2577 M.x86.R_SI += inc;
2581 /****************************************************************************
2582 PARAMETERS:
2583 addr - Address to fetch word from
2585 REMARKS:
2586 Fetches a word from emulator memory using an absolute address.
2587 ****************************************************************************/
2588 u16 mem_access_word(int addr)
2590 DB( if (CHECK_MEM_ACCESS())
2591 x86emu_check_mem_access(addr);)
2592 return (*sys_rdw)(addr);
2595 /****************************************************************************
2596 REMARKS:
2597 Pushes a word onto the stack.
2599 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2600 ****************************************************************************/
2601 void push_word(u16 w)
2603 DB( if (CHECK_SP_ACCESS())
2604 x86emu_check_sp_access();)
2605 M.x86.R_SP -= 2;
2606 (*sys_wrw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2609 /****************************************************************************
2610 REMARKS:
2611 Pushes a long onto the stack.
2613 NOTE: Do not inline this, as (*sys_wrX) is already inline!
2614 ****************************************************************************/
2615 void push_long(u32 w)
2617 DB( if (CHECK_SP_ACCESS())
2618 x86emu_check_sp_access();)
2619 M.x86.R_SP -= 4;
2620 (*sys_wrl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP, w);
2623 /****************************************************************************
2624 REMARKS:
2625 Pops a word from the stack.
2627 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2628 ****************************************************************************/
2629 u16 pop_word(void)
2631 register u16 res;
2633 DB( if (CHECK_SP_ACCESS())
2634 x86emu_check_sp_access();)
2635 res = (*sys_rdw)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
2636 M.x86.R_SP += 2;
2637 return res;
2640 /****************************************************************************
2641 REMARKS:
2642 Pops a long from the stack.
2644 NOTE: Do not inline this, as (*sys_rdX) is already inline!
2645 ****************************************************************************/
2646 u32 pop_long(void)
2648 register u32 res;
2650 DB( if (CHECK_SP_ACCESS())
2651 x86emu_check_sp_access();)
2652 res = (*sys_rdl)(((u32)M.x86.R_SS << 4) + M.x86.R_SP);
2653 M.x86.R_SP += 4;
2654 return res;