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