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