Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / x86emu / prim_ops.c
CommitLineData
a09e091a
JB
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
113static 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/****************************************************************************
130REMARKS:
131Implements the AAA instruction and side effects.
132****************************************************************************/
133u16
134aaa_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/****************************************************************************
156REMARKS:
157Implements the AAA instruction and side effects.
158****************************************************************************/
159u16
160aas_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/****************************************************************************
182REMARKS:
183Implements the AAD instruction and side effects.
184****************************************************************************/
185u16
186aad_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/****************************************************************************
205REMARKS:
206Implements the AAM instruction and side effects.
207****************************************************************************/
208u16
209aam_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/****************************************************************************
227REMARKS:
228Implements the ADC instruction and side effects.
229****************************************************************************/
230u8
231adc_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/****************************************************************************
254REMARKS:
255Implements the ADC instruction and side effects.
256****************************************************************************/
257u16
258adc_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/****************************************************************************
281REMARKS:
282Implements the ADC instruction and side effects.
283****************************************************************************/
284u32
285adc_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/****************************************************************************
315REMARKS:
316Implements the ADD instruction and side effects.
317****************************************************************************/
318u8
319add_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/****************************************************************************
338REMARKS:
339Implements the ADD instruction and side effects.
340****************************************************************************/
341u16
342add_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/****************************************************************************
361REMARKS:
362Implements the ADD instruction and side effects.
363****************************************************************************/
364u32
365add_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/****************************************************************************
390REMARKS:
391Implements the AND instruction and side effects.
392****************************************************************************/
393u8
394and_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/****************************************************************************
411REMARKS:
412Implements the AND instruction and side effects.
413****************************************************************************/
414u16
415and_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/****************************************************************************
432REMARKS:
433Implements the AND instruction and side effects.
434****************************************************************************/
435u32
436and_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/****************************************************************************
453REMARKS:
454Implements the CMP instruction and side effects.
455****************************************************************************/
456u8
457cmp_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/****************************************************************************
477REMARKS:
478Implements the CMP instruction and side effects.
479****************************************************************************/
480u16
481cmp_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/****************************************************************************
500REMARKS:
501Implements the CMP instruction and side effects.
502****************************************************************************/
503u32
504cmp_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/****************************************************************************
523REMARKS:
524Implements the DAA instruction and side effects.
525****************************************************************************/
526u8
527daa_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/****************************************************************************
546REMARKS:
547Implements the DAS instruction and side effects.
548****************************************************************************/
549u8
550das_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/****************************************************************************
567REMARKS:
568Implements the DEC instruction and side effects.
569****************************************************************************/
570u8
571dec_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/****************************************************************************
591REMARKS:
592Implements the DEC instruction and side effects.
593****************************************************************************/
594u16
595dec_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/****************************************************************************
615REMARKS:
616Implements the DEC instruction and side effects.
617****************************************************************************/
618u32
619dec_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/****************************************************************************
639REMARKS:
640Implements the INC instruction and side effects.
641****************************************************************************/
642u8
643inc_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/****************************************************************************
661REMARKS:
662Implements the INC instruction and side effects.
663****************************************************************************/
664u16
665inc_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/****************************************************************************
683REMARKS:
684Implements the INC instruction and side effects.
685****************************************************************************/
686u32
687inc_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/****************************************************************************
705REMARKS:
706Implements the OR instruction and side effects.
707****************************************************************************/
708u8
709or_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/****************************************************************************
724REMARKS:
725Implements the OR instruction and side effects.
726****************************************************************************/
727u16
728or_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/****************************************************************************
744REMARKS:
745Implements the OR instruction and side effects.
746****************************************************************************/
747u32
748or_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/****************************************************************************
765REMARKS:
766Implements the OR instruction and side effects.
767****************************************************************************/
768u8
769neg_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/****************************************************************************
791REMARKS:
792Implements the OR instruction and side effects.
793****************************************************************************/
794u16
795neg_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/****************************************************************************
818REMARKS:
819Implements the OR instruction and side effects.
820****************************************************************************/
821u32
822neg_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/****************************************************************************
845REMARKS:
846Implements the NOT instruction and side effects.
847****************************************************************************/
848u8
849not_byte(u8 s)
850{
851 return ~s;
852}
853
854/****************************************************************************
855REMARKS:
856Implements the NOT instruction and side effects.
857****************************************************************************/
858u16
859not_word(u16 s)
860{
861 return ~s;
862}
863
864/****************************************************************************
865REMARKS:
866Implements the NOT instruction and side effects.
867****************************************************************************/
868u32
869not_long(u32 s)
870{
871 return ~s;
872}
873
874/****************************************************************************
875REMARKS:
876Implements the RCL instruction and side effects.
877****************************************************************************/
878u8
879rcl_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/****************************************************************************
948REMARKS:
949Implements the RCL instruction and side effects.
950****************************************************************************/
951u16
952rcl_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/****************************************************************************
972REMARKS:
973Implements the RCL instruction and side effects.
974****************************************************************************/
975u32
976rcl_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/****************************************************************************
996REMARKS:
997Implements the RCR instruction and side effects.
998****************************************************************************/
999u8
1000rcr_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/****************************************************************************
1081REMARKS:
1082Implements the RCR instruction and side effects.
1083****************************************************************************/
1084u16
1085rcr_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/****************************************************************************
1114REMARKS:
1115Implements the RCR instruction and side effects.
1116****************************************************************************/
1117u32
1118rcr_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/****************************************************************************
1148REMARKS:
1149Implements the ROL instruction and side effects.
1150****************************************************************************/
1151u8
1152rol_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/****************************************************************************
1198REMARKS:
1199Implements the ROL instruction and side effects.
1200****************************************************************************/
1201u16
1202rol_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/****************************************************************************
1224REMARKS:
1225Implements the ROL instruction and side effects.
1226****************************************************************************/
1227u32
1228rol_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/****************************************************************************
1250REMARKS:
1251Implements the ROR instruction and side effects.
1252****************************************************************************/
1253u8
1254ror_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/****************************************************************************
1298REMARKS:
1299Implements the ROR instruction and side effects.
1300****************************************************************************/
1301u16
1302ror_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/****************************************************************************
1323REMARKS:
1324Implements the ROR instruction and side effects.
1325****************************************************************************/
1326u32
1327ror_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/****************************************************************************
1348REMARKS:
1349Implements the SHL instruction and side effects.
1350****************************************************************************/
1351u8
1352shl_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/****************************************************************************
1395REMARKS:
1396Implements the SHL instruction and side effects.
1397****************************************************************************/
1398u16
1399shl_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/****************************************************************************
1437REMARKS:
1438Implements the SHL instruction and side effects.
1439****************************************************************************/
1440u32
1441shl_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/****************************************************************************
1478REMARKS:
1479Implements the SHR instruction and side effects.
1480****************************************************************************/
1481u8
1482shr_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/****************************************************************************
1519REMARKS:
1520Implements the SHR instruction and side effects.
1521****************************************************************************/
1522u16
1523shr_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/****************************************************************************
1560REMARKS:
1561Implements the SHR instruction and side effects.
1562****************************************************************************/
1563u32
1564shr_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/****************************************************************************
1600REMARKS:
1601Implements the SAR instruction and side effects.
1602****************************************************************************/
1603u8
1604sar_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/****************************************************************************
1643REMARKS:
1644Implements the SAR instruction and side effects.
1645****************************************************************************/
1646u16
1647sar_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/****************************************************************************
1686REMARKS:
1687Implements the SAR instruction and side effects.
1688****************************************************************************/
1689u32
1690sar_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/****************************************************************************
1729REMARKS:
1730Implements the SHLD instruction and side effects.
1731****************************************************************************/
1732u16
1733shld_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/****************************************************************************
1770REMARKS:
1771Implements the SHLD instruction and side effects.
1772****************************************************************************/
1773u32
1774shld_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/****************************************************************************
1811REMARKS:
1812Implements the SHRD instruction and side effects.
1813****************************************************************************/
1814u16
1815shrd_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/****************************************************************************
1852REMARKS:
1853Implements the SHRD instruction and side effects.
1854****************************************************************************/
1855u32
1856shrd_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/****************************************************************************
1892REMARKS:
1893Implements the SBB instruction and side effects.
1894****************************************************************************/
1895u8
1896sbb_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/****************************************************************************
1918REMARKS:
1919Implements the SBB instruction and side effects.
1920****************************************************************************/
1921u16
1922sbb_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/****************************************************************************
1944REMARKS:
1945Implements the SBB instruction and side effects.
1946****************************************************************************/
1947u32
1948sbb_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/****************************************************************************
1970REMARKS:
1971Implements the SUB instruction and side effects.
1972****************************************************************************/
1973u8
1974sub_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/****************************************************************************
1993REMARKS:
1994Implements the SUB instruction and side effects.
1995****************************************************************************/
1996u16
1997sub_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/****************************************************************************
2016REMARKS:
2017Implements the SUB instruction and side effects.
2018****************************************************************************/
2019u32
2020sub_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/****************************************************************************
2039REMARKS:
2040Implements the TEST instruction and side effects.
2041****************************************************************************/
2042void
2043test_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/****************************************************************************
2058REMARKS:
2059Implements the TEST instruction and side effects.
2060****************************************************************************/
2061void
2062test_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/****************************************************************************
2077REMARKS:
2078Implements the TEST instruction and side effects.
2079****************************************************************************/
2080void
2081test_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/****************************************************************************
2096REMARKS:
2097Implements the XOR instruction and side effects.
2098****************************************************************************/
2099u8
2100xor_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/****************************************************************************
2115REMARKS:
2116Implements the XOR instruction and side effects.
2117****************************************************************************/
2118u16
2119xor_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/****************************************************************************
2134REMARKS:
2135Implements the XOR instruction and side effects.
2136****************************************************************************/
2137u32
2138xor_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/****************************************************************************
2153REMARKS:
2154Implements the IMUL instruction and side effects.
2155****************************************************************************/
2156void
2157imul_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/****************************************************************************
2174REMARKS:
2175Implements the IMUL instruction and side effects.
2176****************************************************************************/
2177void
2178imul_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/****************************************************************************
2196REMARKS:
2197Implements the IMUL instruction and side effects.
2198****************************************************************************/
2199void
2200imul_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/****************************************************************************
2235REMARKS:
2236Implements the IMUL instruction and side effects.
2237****************************************************************************/
2238void
2239imul_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/****************************************************************************
2254REMARKS:
2255Implements the MUL instruction and side effects.
2256****************************************************************************/
2257void
2258mul_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/****************************************************************************
2274REMARKS:
2275Implements the MUL instruction and side effects.
2276****************************************************************************/
2277void
2278mul_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/****************************************************************************
2295REMARKS:
2296Implements the MUL instruction and side effects.
2297****************************************************************************/
2298void
2299mul_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/****************************************************************************
2334REMARKS:
2335Implements the IDIV instruction and side effects.
2336****************************************************************************/
2337void
2338idiv_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/****************************************************************************
2358REMARKS:
2359Implements the IDIV instruction and side effects.
2360****************************************************************************/
2361void
2362idiv_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/****************************************************************************
2387REMARKS:
2388Implements the IDIV instruction and side effects.
2389****************************************************************************/
2390void
2391idiv_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/****************************************************************************
2463REMARKS:
2464Implements the DIV instruction and side effects.
2465****************************************************************************/
2466void
2467div_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/****************************************************************************
2487REMARKS:
2488Implements the DIV instruction and side effects.
2489****************************************************************************/
2490void
2491div_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/****************************************************************************
2516REMARKS:
2517Implements the DIV instruction and side effects.
2518****************************************************************************/
2519void
2520div_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/****************************************************************************
2588REMARKS:
2589Implements the IN string instruction and side effects.
2590****************************************************************************/
2591void
2592ins(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/****************************************************************************
2654REMARKS:
2655Implements the OUT string instruction and side effects.
2656****************************************************************************/
2657void
2658outs(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/****************************************************************************
2720PARAMETERS:
2721addr - Address to fetch word from
2722
2723REMARKS:
2724Fetches a word from emulator memory using an absolute address.
2725****************************************************************************/
2726u16
2727mem_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/****************************************************************************
2735REMARKS:
2736Pushes a word onto the stack.
2737
2738NOTE: Do not inline this, as (*sys_wrX) is already inline!
2739****************************************************************************/
2740void
2741push_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/****************************************************************************
2750REMARKS:
2751Pushes a long onto the stack.
2752
2753NOTE: Do not inline this, as (*sys_wrX) is already inline!
2754****************************************************************************/
2755void
2756push_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/****************************************************************************
2765REMARKS:
2766Pops a word from the stack.
2767
2768NOTE: Do not inline this, as (*sys_rdX) is already inline!
2769****************************************************************************/
2770u16
2771pop_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/****************************************************************************
2783REMARKS:
2784Pops a long from the stack.
2785
2786NOTE: Do not inline this, as (*sys_rdX) is already inline!
2787****************************************************************************/
2788u32
2789pop_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/****************************************************************************
2801REMARKS:
2802CPUID takes EAX/ECX as inputs, writes EAX/EBX/ECX/EDX as output
2803****************************************************************************/
2804void
2805cpuid(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}