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