3 * Copyright (C) 1991 Jim Hudgens
6 * The file is part of GDE.
8 * GDE is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 1, or (at your option)
13 * GDE is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with GDE; see the file COPYING. If not, write to
20 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "altairz80_defs.h"
27 extern uint32
GetBYTEExtended(register uint32 Addr
);
28 extern void PutBYTEExtended(register uint32 Addr
, const register uint32 Value
);
30 /* $Log: i86_prim_ops.c,v $
31 * Revision 0.9 2003-01-10 23:33:10 jce
32 * fixed some more warnings under gcc -Wall
34 * Revision 0.8 1992/04/11 21:58:13 hudgens
35 * fixed some code causing warnings under gcc -Wall
37 * Revision 0.7 1991/07/30 02:04:34 hudgens
40 * Revision 0.6 1991/07/21 16:50:37 hudgens
41 * fixed all flags in the bit shift and rotate instructions so that they
43 * Also fixed the flags associated with IMUL and MUL instructions.
45 * Revision 0.5 1991/07/21 01:28:16 hudgens
46 * added support for aad and aam primitives.
48 * Revision 0.4 1991/07/20 22:26:25 hudgens
49 * fixed problem with sign extension in subroutine mem_access_word.
51 * Revision 0.3 1991/07/17 03:48:22 hudgens
52 * fixed bugs having to do with the setting of flags in the
53 * shift and rotate operations. Also, fixed sign extension problem
54 * with push_word and pop_word.
56 * Revision 0.2 1991/04/01 02:36:00 hudgens
57 * Fixed several nasty bugs dealing with flag setting in the subroutines
58 * sub_byte, sub_word, sbb_byte, sbb_word, and test_word. The results
59 * now agree with the PC on both of the testaopb and testaopw tests.
61 * Revision 0.1 1991/03/30 21:13:37 hudgens
67 /* [JCE] Stop gcc -Wall complaining */
68 void i86_intr_raise(PC_ENV
*m
, uint8 intrnum
);
70 /* the following table was generated using the following
71 code (running on an IBM AT, Turbo C++ 2.0), for all values of i
72 between 0 and 255. AL is loaded with i's value, and then the
73 operation "and al,al" sets the parity flag. The flags are pushed
74 onto the stack, and then popped back into AX. Then AX is
75 returned. So the value of each table entry represents the
76 parity of its index into the table. This results in a somewhat
77 faster mechanism for parity calculations than the straightforward
79 andflags(i,res) int *res; {
81 _AX = i; asm and al,al; asm pushf; *res = _AX;
82 asm pop ax; flags = _AX; return flags;
87 /*0*/ 1, /*1*/ 0, /*2*/ 0, /*3*/ 1,
88 /*4*/ 0, /*5*/ 1, /*6*/ 1, /*7*/ 0,
89 /*8*/ 0, /*9*/ 1, /*a*/ 1, /*b*/ 0,
90 /*c*/ 1, /*d*/ 0, /*e*/ 0, /*f*/ 1,
91 /*10*/ 0, /*11*/ 1, /*12*/ 1, /*13*/ 0,
92 /*14*/ 1, /*15*/ 0, /*16*/ 0, /*17*/ 1,
93 /*18*/ 1, /*19*/ 0, /*1a*/ 0, /*1b*/ 1,
94 /*1c*/ 0, /*1d*/ 1, /*1e*/ 1, /*1f*/ 0,
95 /*20*/ 0, /*21*/ 1, /*22*/ 1, /*23*/ 0,
96 /*24*/ 1, /*25*/ 0, /*26*/ 0, /*27*/ 1,
97 /*28*/ 1, /*29*/ 0, /*2a*/ 0, /*2b*/ 1,
98 /*2c*/ 0, /*2d*/ 1, /*2e*/ 1, /*2f*/ 0,
99 /*30*/ 1, /*31*/ 0, /*32*/ 0, /*33*/ 1,
100 /*34*/ 0, /*35*/ 1, /*36*/ 1, /*37*/ 0,
101 /*38*/ 0, /*39*/ 1, /*3a*/ 1, /*3b*/ 0,
102 /*3c*/ 1, /*3d*/ 0, /*3e*/ 0, /*3f*/ 1,
103 /*40*/ 0, /*41*/ 1, /*42*/ 1, /*43*/ 0,
104 /*44*/ 1, /*45*/ 0, /*46*/ 0, /*47*/ 1,
105 /*48*/ 1, /*49*/ 0, /*4a*/ 0, /*4b*/ 1,
106 /*4c*/ 0, /*4d*/ 1, /*4e*/ 1, /*4f*/ 0,
107 /*50*/ 1, /*51*/ 0, /*52*/ 0, /*53*/ 1,
108 /*54*/ 0, /*55*/ 1, /*56*/ 1, /*57*/ 0,
109 /*58*/ 0, /*59*/ 1, /*5a*/ 1, /*5b*/ 0,
110 /*5c*/ 1, /*5d*/ 0, /*5e*/ 0, /*5f*/ 1,
111 /*60*/ 1, /*61*/ 0, /*62*/ 0, /*63*/ 1,
112 /*64*/ 0, /*65*/ 1, /*66*/ 1, /*67*/ 0,
113 /*68*/ 0, /*69*/ 1, /*6a*/ 1, /*6b*/ 0,
114 /*6c*/ 1, /*6d*/ 0, /*6e*/ 0, /*6f*/ 1,
115 /*70*/ 0, /*71*/ 1, /*72*/ 1, /*73*/ 0,
116 /*74*/ 1, /*75*/ 0, /*76*/ 0, /*77*/ 1,
117 /*78*/ 1, /*79*/ 0, /*7a*/ 0, /*7b*/ 1,
118 /*7c*/ 0, /*7d*/ 1, /*7e*/ 1, /*7f*/ 0,
119 /*80*/ 0, /*81*/ 1, /*82*/ 1, /*83*/ 0,
120 /*84*/ 1, /*85*/ 0, /*86*/ 0, /*87*/ 1,
121 /*88*/ 1, /*89*/ 0, /*8a*/ 0, /*8b*/ 1,
122 /*8c*/ 0, /*8d*/ 1, /*8e*/ 1, /*8f*/ 0,
123 /*90*/ 1, /*91*/ 0, /*92*/ 0, /*93*/ 1,
124 /*94*/ 0, /*95*/ 1, /*96*/ 1, /*97*/ 0,
125 /*98*/ 0, /*99*/ 1, /*9a*/ 1, /*9b*/ 0,
126 /*9c*/ 1, /*9d*/ 0, /*9e*/ 0, /*9f*/ 1,
127 /*a0*/ 1, /*a1*/ 0, /*a2*/ 0, /*a3*/ 1,
128 /*a4*/ 0, /*a5*/ 1, /*a6*/ 1, /*a7*/ 0,
129 /*a8*/ 0, /*a9*/ 1, /*aa*/ 1, /*ab*/ 0,
130 /*ac*/ 1, /*ad*/ 0, /*ae*/ 0, /*af*/ 1,
131 /*b0*/ 0, /*b1*/ 1, /*b2*/ 1, /*b3*/ 0,
132 /*b4*/ 1, /*b5*/ 0, /*b6*/ 0, /*b7*/ 1,
133 /*b8*/ 1, /*b9*/ 0, /*ba*/ 0, /*bb*/ 1,
134 /*bc*/ 0, /*bd*/ 1, /*be*/ 1, /*bf*/ 0,
135 /*c0*/ 1, /*c1*/ 0, /*c2*/ 0, /*c3*/ 1,
136 /*c4*/ 0, /*c5*/ 1, /*c6*/ 1, /*c7*/ 0,
137 /*c8*/ 0, /*c9*/ 1, /*ca*/ 1, /*cb*/ 0,
138 /*cc*/ 1, /*cd*/ 0, /*ce*/ 0, /*cf*/ 1,
139 /*d0*/ 0, /*d1*/ 1, /*d2*/ 1, /*d3*/ 0,
140 /*d4*/ 1, /*d5*/ 0, /*d6*/ 0, /*d7*/ 1,
141 /*d8*/ 1, /*d9*/ 0, /*da*/ 0, /*db*/ 1,
142 /*dc*/ 0, /*dd*/ 1, /*de*/ 1, /*df*/ 0,
143 /*e0*/ 0, /*e1*/ 1, /*e2*/ 1, /*e3*/ 0,
144 /*e4*/ 1, /*e5*/ 0, /*e6*/ 0, /*e7*/ 1,
145 /*e8*/ 1, /*e9*/ 0, /*ea*/ 0, /*eb*/ 1,
146 /*ec*/ 0, /*ed*/ 1, /*ee*/ 1, /*ef*/ 0,
147 /*f0*/ 1, /*f1*/ 0, /*f2*/ 0, /*f3*/ 1,
148 /*f4*/ 0, /*f5*/ 1, /*f6*/ 1, /*f7*/ 0,
149 /*f8*/ 0, /*f9*/ 1, /*fa*/ 1, /*fb*/ 0,
150 /*fc*/ 1, /*fd*/ 0, /*fe*/ 0, /*ff*/ 1,
153 char xor_0x3_tab
[] = { 0, 1, 1, 0 };
155 /* CARRY CHAIN CALCULATION.
156 This represents a somewhat expensive calculation which is
157 apparently required to emulate the setting of the OF and
158 AF flag. The latter is not so important, but the former is.
159 The overflow flag is the XOR of the top two bits of the
160 carry chain for an addition (similar for subtraction).
161 Since we do not want to simulate the addition in a bitwise
162 manner, we try to calculate the carry chain given the
163 two operands and the result.
165 So, given the following table, which represents the
166 addition of two bits, we can derive a formula for
179 Construction of table for cout:
187 By inspection, one gets: cc = ab + r'(a + b)
189 That represents alot of operations, but NO CHOICE....
191 BORROW CHAIN CALCULATION.
192 The following table represents the
193 subtraction of two bits, from which we can derive a formula for
206 Construction of table for cout:
214 By inspection, one gets: bc = a'b + r(a' + b)
218 uint8
aad_word(PC_ENV
*m
, uint16 d
)
225 CONDITIONAL_SET_FLAG(l
& 0x80, m
, F_SF
);
226 CONDITIONAL_SET_FLAG(l
== 0, m
, F_ZF
);
227 CONDITIONAL_SET_FLAG(parity_tab
[l
& 0xff], m
, F_PF
);
231 uint16
aam_word(PC_ENV
*m
, uint8 d
)
237 CONDITIONAL_SET_FLAG(l
& 0x80, m
, F_SF
);
238 CONDITIONAL_SET_FLAG(l
== 0, m
, F_ZF
);
239 CONDITIONAL_SET_FLAG(parity_tab
[l
& 0xff], m
, F_PF
);
243 uint8
adc_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
245 register uint16 res
; /* all operands in native machine order */
247 if (ACCESS_FLAG(m
,F_CF
) )
251 CONDITIONAL_SET_FLAG(res
& 0x100, m
, F_CF
);
252 CONDITIONAL_SET_FLAG((res
&0xff)==0, m
, F_ZF
);
253 CONDITIONAL_SET_FLAG(res
& 0x80, m
, F_SF
);
254 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
255 /* calculate the carry chain SEE NOTE AT TOP.*/
256 cc
= (s
& d
) | ((~res
) & (s
| d
));
257 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(cc
>>6)&0x3], m
, F_OF
);
258 CONDITIONAL_SET_FLAG(cc
&0x8, m
, F_AF
);
262 uint16
adc_word(PC_ENV
*m
, uint16 d
, uint16 s
)
264 register uint32 res
; /* all operands in native machine order */
266 if (ACCESS_FLAG(m
,F_CF
) )
270 /* set the carry flag to be bit 8 */
271 CONDITIONAL_SET_FLAG(res
& 0x10000, m
, F_CF
);
272 CONDITIONAL_SET_FLAG((res
&0xffff)==0, m
, F_ZF
);
273 CONDITIONAL_SET_FLAG(res
& 0x8000, m
, F_SF
);
274 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
275 /* calculate the carry chain SEE NOTE AT TOP.*/
276 cc
= (s
& d
) | ((~res
) & (s
| d
));
277 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(cc
>>14)&0x3], m
, F_OF
);
278 CONDITIONAL_SET_FLAG(cc
&0x8, m
, F_AF
);
282 /* Given flags=f, and bytes d (dest) and s (source)
283 perform the add and set the flags and the result back to
284 *d. USE NATIVE MACHINE ORDER...
286 uint8
add_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
288 register uint16 res
; /* all operands in native machine order */
291 /* set the carry flag to be bit 8 */
292 CONDITIONAL_SET_FLAG(res
& 0x100, m
, F_CF
);
293 CONDITIONAL_SET_FLAG((res
&0xff)==0, m
, F_ZF
);
294 CONDITIONAL_SET_FLAG(res
& 0x80, m
, F_SF
);
295 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
296 /* calculate the carry chain SEE NOTE AT TOP.*/
297 cc
= (s
& d
) | ((~res
) & (s
| d
));
298 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(cc
>>6)&0x3], m
, F_OF
);
299 CONDITIONAL_SET_FLAG(cc
&0x8, m
, F_AF
);
303 /* Given flags=f, and bytes d (dest) and s (source)
304 perform the add and set the flags and the result back to
305 *d. USE NATIVE MACHINE ORDER...
307 uint16
add_word(PC_ENV
*m
, uint16 d
, uint16 s
)
309 register uint32 res
; /* all operands in native machine order */
312 /* set the carry flag to be bit 8 */
313 CONDITIONAL_SET_FLAG(res
& 0x10000, m
, F_CF
);
314 CONDITIONAL_SET_FLAG((res
&0xffff)==0, m
, F_ZF
);
315 CONDITIONAL_SET_FLAG(res
& 0x8000, m
, F_SF
);
316 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
317 /* calculate the carry chain SEE NOTE AT TOP.*/
318 cc
= (s
& d
) | ((~res
) & (s
| d
));
319 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(cc
>>14)&0x3], m
, F_OF
);
320 CONDITIONAL_SET_FLAG(cc
&0x8, m
, F_AF
);
325 Flags m->R_FLG, dest *d, source *s, do a bitwise and of the
326 source and destination, and then store back to the
327 destination. Size=byte.
329 uint8
and_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
331 register uint8 res
; /* all operands in native machine order */
336 CONDITIONAL_SET_FLAG(res
&0x80, m
, F_SF
);
337 CONDITIONAL_SET_FLAG(res
==0, m
, F_ZF
);
338 CONDITIONAL_SET_FLAG(parity_tab
[res
], m
, F_PF
);
343 Flags m->R_FLG, dest *d, source *s, do a bitwise and of the
344 source and destination, and then store back to the
345 destination. Size=byte.
347 uint16
and_word(PC_ENV
*m
, uint16 d
, uint16 s
)
349 register uint16 res
; /* all operands in native machine order */
354 CONDITIONAL_SET_FLAG(res
&0x8000, m
, F_SF
);
355 CONDITIONAL_SET_FLAG(res
==0, m
, F_ZF
);
356 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
360 uint8
cmp_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
362 register uint32 res
; /* all operands in native machine order */
366 CONDITIONAL_SET_FLAG(res
&0x80, m
, F_SF
);
367 CONDITIONAL_SET_FLAG((res
&0xff)==0, m
, F_ZF
);
368 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
369 /* calculate the borrow chain. See note at top */
370 bc
= (res
&(~d
|s
))|(~d
&s
);
371 CONDITIONAL_SET_FLAG(bc
&0x80,m
, F_CF
);
372 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(bc
>>6)&0x3], m
, F_OF
);
373 CONDITIONAL_SET_FLAG(bc
&0x8, m
, F_AF
);
374 return d
; /* long story why this is needed. Look at opcode
375 0x80 in ops.c, for an idea why this is necessary.*/
378 uint16
cmp_word(PC_ENV
*m
, uint16 d
, uint16 s
)
380 register uint32 res
; /* all operands in native machine order */
383 CONDITIONAL_SET_FLAG(res
&0x8000, m
, F_SF
);
384 CONDITIONAL_SET_FLAG((res
&0xffff)==0, m
, F_ZF
);
385 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
386 /* calculate the borrow chain. See note at top */
387 bc
= (res
&(~d
|s
))|(~d
&s
);
388 CONDITIONAL_SET_FLAG(bc
&0x8000,m
, F_CF
);
389 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(bc
>>14)&0x3], m
, F_OF
);
390 CONDITIONAL_SET_FLAG(bc
&0x8, m
, F_AF
);
394 uint8
dec_byte(PC_ENV
*m
, uint8 d
)
396 register uint32 res
; /* all operands in native machine order */
399 CONDITIONAL_SET_FLAG(res
&0x80, m
, F_SF
);
400 CONDITIONAL_SET_FLAG((res
&0xff)==0, m
, F_ZF
);
401 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
402 /* calculate the borrow chain. See note at top */
403 /* based on sub_byte, uses s==1. */
404 bc
= (res
&(~d
|1))|(~d
&1);
405 /* carry flag unchanged */
406 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(bc
>>6)&0x3], m
, F_OF
);
407 CONDITIONAL_SET_FLAG(bc
&0x8, m
, F_AF
);
411 uint16
dec_word(PC_ENV
*m
, uint16 d
)
413 register uint32 res
; /* all operands in native machine order */
416 CONDITIONAL_SET_FLAG(res
&0x8000, m
, F_SF
);
417 CONDITIONAL_SET_FLAG((res
&0xffff)==0, m
, F_ZF
);
418 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
419 /* calculate the borrow chain. See note at top */
420 /* based on the sub_byte routine, with s==1 */
421 bc
= (res
&(~d
|1))|(~d
&1);
422 /* carry flag unchanged */
423 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(bc
>>14)&0x3], m
, F_OF
);
424 CONDITIONAL_SET_FLAG(bc
&0x8, m
, F_AF
);
428 /* Given flags=f, and byte d (dest)
429 perform the inc and set the flags and the result back to
430 d. USE NATIVE MACHINE ORDER...
432 uint8
inc_byte(PC_ENV
*m
, uint8 d
)
434 register uint32 res
; /* all operands in native machine order */
437 CONDITIONAL_SET_FLAG((res
&0xff)==0, m
, F_ZF
);
438 CONDITIONAL_SET_FLAG(res
& 0x80, m
, F_SF
);
439 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
440 /* calculate the carry chain SEE NOTE AT TOP.*/
441 cc
= ((1 & d
) | (~res
)) & (1 | d
);
442 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(cc
>>6)&0x3], m
, F_OF
);
443 CONDITIONAL_SET_FLAG(cc
&0x8, m
, F_AF
);
447 /* Given flags=f, and byte d (dest)
448 perform the inc and set the flags and the result back to
449 *d. USE NATIVE MACHINE ORDER...
451 uint16
inc_word(PC_ENV
*m
, uint16 d
)
453 register uint32 res
; /* all operands in native machine order */
456 CONDITIONAL_SET_FLAG((res
&0xffff)==0, m
, F_ZF
);
457 CONDITIONAL_SET_FLAG(res
& 0x8000, m
, F_SF
);
458 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
459 /* calculate the carry chain SEE NOTE AT TOP.*/
460 cc
= (1 & d
) | ((~res
) & (1 | d
));
461 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(cc
>>14)&0x3], m
, F_OF
);
462 CONDITIONAL_SET_FLAG(cc
&0x8, m
, F_AF
);
466 uint8
or_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
468 register uint8 res
; /* all operands in native machine order */
472 CONDITIONAL_SET_FLAG(res
&0x80, m
, F_SF
);
473 CONDITIONAL_SET_FLAG(res
==0, m
, F_ZF
);
474 CONDITIONAL_SET_FLAG(parity_tab
[res
], m
, F_PF
);
478 uint16
or_word(PC_ENV
*m
, uint16 d
, uint16 s
)
480 register uint16 res
; /* all operands in native machine order */
482 /* set the carry flag to be bit 8 */
485 CONDITIONAL_SET_FLAG(res
&0x8000, m
, F_SF
);
486 CONDITIONAL_SET_FLAG(res
==0, m
, F_ZF
);
487 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
491 uint8
neg_byte(PC_ENV
*m
, uint8 s
)
495 CONDITIONAL_SET_FLAG(s
!=0, m
, F_CF
);
497 CONDITIONAL_SET_FLAG((res
&0xff)==0, m
, F_ZF
);
498 CONDITIONAL_SET_FLAG(res
& 0x80, m
, F_SF
);
499 CONDITIONAL_SET_FLAG(parity_tab
[res
], m
, F_PF
);
500 /* calculate the borrow chain --- modified such that d=0.
501 substitutiing d=0 into bc= res&(~d|s)|(~d&s);
502 (the one used for sub) and simplifying, since ~d=0xff...,
503 ~d|s == 0xffff..., and res&0xfff... == res. Similarly
504 ~d&s == s. So the simplified result is:*/
506 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(bc
>>6)&0x3], m
, F_OF
);
507 CONDITIONAL_SET_FLAG(bc
&0x8, m
, F_AF
);
511 uint16
neg_word(PC_ENV
*m
, uint16 s
)
515 CONDITIONAL_SET_FLAG(s
!=0, m
, F_CF
);
517 CONDITIONAL_SET_FLAG((res
&0xffff)==0, m
, F_ZF
);
518 CONDITIONAL_SET_FLAG(res
& 0x8000, m
, F_SF
);
519 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
520 /* calculate the borrow chain --- modified such that d=0.
521 substitutiing d=0 into bc= res&(~d|s)|(~d&s);
522 (the one used for sub) and simplifying, since ~d=0xff...,
523 ~d|s == 0xffff..., and res&0xfff... == res. Similarly
524 ~d&s == s. So the simplified result is:*/
526 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(bc
>>6)&0x3], m
, F_OF
);
527 CONDITIONAL_SET_FLAG(bc
&0x8, m
, F_AF
);
531 uint8
not_byte(PC_ENV
*m
, uint8 s
)
536 uint16
not_word(PC_ENV
*m
, uint16 s
)
541 /* access stuff from absolute location in memory.
542 no segment registers are involved.
544 uint16
mem_access_word(PC_ENV
*m
, int addr
)
546 /* Load in two steps. Native byte order independent */
547 return GetBYTEExtended(addr
) | (GetBYTEExtended(addr
+ 1) << 8);
550 /* given the register_set r, and memory descriptor m,
551 and word w, push w onto the stack.
552 w ASSUMED IN NATIVE MACHINE ORDER. Doesn't matter in this case???
554 void push_word(PC_ENV
*m
, uint16 w
)
557 PutBYTEExtended((m
->R_SS
<< 4) + m
->R_SP
, w
>> 8);
559 PutBYTEExtended((m
->R_SS
<< 4) + m
->R_SP
, w
& 0xff);
562 /* given the memory descriptor m,
563 and word w, pop word from the stack.
565 uint16
pop_word(PC_ENV
*m
)
568 res
= GetBYTEExtended((m
->R_SS
<< 4) + m
->R_SP
);
570 res
|= GetBYTEExtended((m
->R_SS
<< 4) + m
->R_SP
) << 8;
575 /*****************************************************************
576 BEGIN region consisting of bit shifts and rotates,
577 much of which may be wrong. Large hirsute factor.
578 *****************************************************************/
579 uint8
rcl_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
581 register uint32 res
, cnt
, mask
,cf
;
582 /* s is the rotate distance. It varies from 0 - 8. */
584 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
585 want to rotate through the carry by "s" bits. We could
586 loop, but that's inefficient. So the width is 9,
587 and we split into three parts:
588 The new carry flag (was B_n)
589 the stuff in B_n-1 .. B_0
590 the stuff in B_7 .. B_n+1
591 The new rotate is done mod 9, and given this,
592 for a rotation of n bits (mod 9) the new carry flag is
593 then located n bits from the MSB. The low part is
594 then shifted up cnt bits, and the high part is or'd
595 in. Using CAPS for new values, and lowercase for the
596 original values, this can be expressed as:
599 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
601 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
602 I think this is correct.
605 /* [JCE] Extra brackets to stop gcc -Wall moaning */
606 if ((cnt
= s
% 9)) /* not a typo, do nada if cnt==0 */
608 /* extract the new CARRY FLAG. */
610 cf
= (d
>> (8-cnt
)) & 0x1;
611 /* get the low stuff which rotated
612 into the range B_7 .. B_cnt */
613 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0 */
614 /* note that the right hand side done by the mask */
615 res
= (d
<< cnt
) & 0xff;
616 /* now the high stuff which rotated around
617 into the positions B_cnt-2 .. B_0 */
618 /* B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1)) */
619 /* shift it downward, 7-(n-2) = 9-n positions.
620 and mask off the result before or'ing in.
622 mask
= (1<<(cnt
-1)) - 1;
623 res
|= (d
>> (9-cnt
)) & mask
;
624 /* if the carry flag was set, or it in. */
625 if (ACCESS_FLAG(m
,F_CF
)) /* carry flag is set */
630 /* set the new carry flag, based on the variable "cf" */
631 CONDITIONAL_SET_FLAG(cf
, m
, F_CF
);
632 /* OVERFLOW is set *IFF* cnt==1, then it is the
633 xor of CF and the most significant bit. Blecck. */
634 /* parenthesized this expression since it appears to
635 be causing OF to be misset */
636 CONDITIONAL_SET_FLAG(cnt
==1&&
637 xor_0x3_tab
[cf
+((res
>>6)&0x2)],
643 uint16
rcl_word(PC_ENV
*m
, uint16 d
, uint16 s
)
645 register uint32 res
, cnt
, mask
,cf
;
646 /* see analysis above. */
647 /* width here is 16 bits + carry bit */
649 /* [JCE] Extra brackets to stop gcc -Wall moaning */
650 if ((cnt
= s
% 17)) /* not a typo, do nada if cnt==0 */
652 /* extract the new CARRY FLAG. */
654 cf
= (d
>> (16-cnt
)) & 0x1;
655 /* get the low stuff which rotated
656 into the range B_15 .. B_cnt */
657 /* B_(15) .. B_(n) <- b_(16-(n+1)) .. b_0 */
658 /* note that the right hand side done by the mask */
659 res
= (d
<< cnt
) & 0xffff;
660 /* now the high stuff which rotated around
661 into the positions B_cnt-2 .. B_0 */
662 /* B_(n-2) .. B_0 <- b_15 .. b_(16-(n-1)) */
663 /* shift it downward, 15-(n-2) = 17-n positions.
664 and mask off the result before or'ing in.
666 mask
= (1<<(cnt
-1)) - 1;
667 res
|= (d
>> (17-cnt
)) & mask
;
668 /* if the carry flag was set, or it in. */
669 if (ACCESS_FLAG(m
, F_CF
)) /* carry flag is set */
674 /* set the new carry flag, based on the variable "cf" */
675 CONDITIONAL_SET_FLAG(cf
, m
, F_CF
);
676 /* OVERFLOW is set *IFF* cnt==1, then it is the
677 xor of CF and the most significant bit. Blecck.
678 Note that we're forming a 2 bit word here to index
679 into the table. The expression cf+(res>>14)&0x2
680 represents the two bit word b_15 CF.
682 /* parenthesized following expression... */
683 CONDITIONAL_SET_FLAG(cnt
==1&&xor_0x3_tab
[cf
+((res
>>14)&0x2)],
689 uint8
rcr_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
692 uint8 mask
, cf
, ocf
= 0;
693 /* rotate right through carry */
695 s is the rotate distance. It varies from 0 - 8.
696 d is the byte object rotated.
698 CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
699 The new rotate is done mod 9, and given this,
700 for a rotation of n bits (mod 9) the new carry flag is
701 then located n bits from the LSB. The low part is
702 then shifted up cnt bits, and the high part is or'd
703 in. Using CAPS for new values, and lowercase for the
704 original values, this can be expressed as:
707 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
709 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
710 I think this is correct.
713 /* [JCE] Extra brackets to stop gcc -Wall moaning */
714 if ((cnt
= s
% 9)) /* not a typo, do nada if cnt==0 */
716 /* extract the new CARRY FLAG. */
721 /* note hackery here. Access_flag(..) evaluates to either
723 non-zero if flag is set.
724 doing access_flag(..) != 0 casts that into either
725 0..1 in any representation of the flags register
726 (i.e. packed bit array or unpacked.)
728 ocf
= ACCESS_FLAG(m
,F_CF
) != 0;
731 cf
= (d
>> (cnt
-1)) & 0x1;
732 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
733 /* note that the right hand side done by the mask
734 This is effectively done by shifting the
735 object to the right. The result must be masked,
736 in case the object came in and was treated
737 as a negative number. Needed???*/
738 mask
= (1<<(8-cnt
))-1;
739 res
= (d
>> cnt
) & mask
;
740 /* now the high stuff which rotated around
741 into the positions B_cnt-2 .. B_0 */
742 /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
743 /* shift it downward, 7-(n-2) = 9-n positions.
744 and mask off the result before or'ing in.
746 res
|= (d
<< (9-cnt
));
747 /* if the carry flag was set, or it in. */
748 if (ACCESS_FLAG(m
,F_CF
)) /* carry flag is set */
751 res
|= 1 << (8 - cnt
);
753 /* set the new carry flag, based on the variable "cf" */
754 CONDITIONAL_SET_FLAG(cf
, m
, F_CF
);
755 /* OVERFLOW is set *IFF* cnt==1, then it is the
756 xor of CF and the most significant bit. Blecck. */
757 /* parenthesized... */
759 { /* [JCE] Explicit braces to stop gcc -Wall moaning */
760 CONDITIONAL_SET_FLAG(xor_0x3_tab
[ocf
+((d
>>6)&0x2)],
767 uint16
rcr_word(PC_ENV
*m
, uint16 d
, uint16 s
)
770 uint16 mask
, cf
, ocf
= 0;
771 /* rotate right through carry */
773 s is the rotate distance. It varies from 0 - 8.
774 d is the byte object rotated.
777 The new rotate is done mod 17, and given this,
778 for a rotation of n bits (mod 17) the new carry flag is
779 then located n bits from the LSB. The low part is
780 then shifted up cnt bits, and the high part is or'd
781 in. Using CAPS for new values, and lowercase for the
782 original values, this can be expressed as:
785 2) B_(16-(n+1)) .. B_(0) <- b_(15) .. b_(n)
787 4) B_(15) .. B_(16-(n-1)) <- b_(n-2) .. b_(0)
788 I think this is correct.
791 /* [JCE] Extra brackets to stop gcc -Wall moaning */
792 if ((cnt
= s
% 17)) /* not a typo, do nada if cnt==0 */
794 /* extract the new CARRY FLAG. */
799 /* see note above on teh byte version */
800 ocf
= ACCESS_FLAG(m
,F_CF
) != 0;
803 cf
= (d
>> (cnt
-1)) & 0x1;
804 /* B_(16-(n+1)) .. B_(0) <- b_(15) .. b_n */
805 /* note that the right hand side done by the mask
806 This is effectively done by shifting the
807 object to the right. The result must be masked,
808 in case the object came in and was treated
809 as a negative number. Needed???*/
810 mask
= (1<<(16-cnt
))-1;
811 res
= (d
>> cnt
) & mask
;
812 /* now the high stuff which rotated around
813 into the positions B_cnt-2 .. B_0 */
814 /* B_(15) .. B_(16-(n-1)) <- b_(n-2) .. b_(0) */
815 /* shift it downward, 15-(n-2) = 17-n positions.
816 and mask off the result before or'ing in.
818 res
|= (d
<< (17-cnt
));
819 /* if the carry flag was set, or it in. */
820 if (ACCESS_FLAG(m
,F_CF
)) /* carry flag is set */
823 res
|= 1 << (16 - cnt
);
825 /* set the new carry flag, based on the variable "cf" */
826 CONDITIONAL_SET_FLAG(cf
, m
, F_CF
);
827 /* OVERFLOW is set *IFF* cnt==1, then it is the
828 xor of CF and the most significant bit. Blecck. */
830 { /* [JCE] Explicit braces to stop gcc -Wall moaning */
831 CONDITIONAL_SET_FLAG(xor_0x3_tab
[ocf
+((d
>>14)&0x2)],
838 uint8
rol_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
840 register uint32 res
, cnt
, mask
;
843 s is the rotate distance. It varies from 0 - 8.
844 d is the byte object rotated.
847 The new rotate is done mod 8.
848 Much simpler than the "rcl" or "rcr" operations.
850 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0)
851 2) B_(n-1) .. B_(0) <- b_(7) .. b_(8-n)
852 I think this is correct.
855 /* [JCE] Extra brackets to stop gcc -Wall moaning */
856 if ((cnt
= s
% 8)) /* not a typo, do nada if cnt==0 */
858 /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
860 /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
861 mask
= (1 << cnt
) - 1;
862 res
|= (d
>> (8-cnt
)) & mask
;
863 /* set the new carry flag, Note that it is the low order
864 bit of the result!!! */
865 CONDITIONAL_SET_FLAG(res
&0x1, m
, F_CF
);
866 /* OVERFLOW is set *IFF* cnt==1, then it is the
867 xor of CF and the most significant bit. Blecck. */
868 CONDITIONAL_SET_FLAG(cnt
==1 &&
869 xor_0x3_tab
[(res
&0x1)+((res
>>6)&0x2)],
875 uint16
rol_word(PC_ENV
*m
, uint16 d
, uint16 s
)
877 register uint32 res
, cnt
, mask
;
880 s is the rotate distance. It varies from 0 - 8.
881 d is the byte object rotated.
884 The new rotate is done mod 8.
885 Much simpler than the "rcl" or "rcr" operations.
887 1) B_(15) .. B_(n) <- b_(16-(n+1)) .. b_(0)
888 2) B_(n-1) .. B_(0) <- b_(16) .. b_(16-n)
889 I think this is correct.
892 /* [JCE] Extra brackets to stop gcc -Wall moaning */
893 if ((cnt
= s
% 16)) /* not a typo, do nada if cnt==0 */
895 /* B_(16) .. B_(n) <- b_(16-(n+1)) .. b_(0) */
897 /* B_(n-1) .. B_(0) <- b_(15) .. b_(16-n) */
898 mask
= (1 << cnt
) - 1;
899 res
|= (d
>> (16-cnt
)) & mask
;
900 /* set the new carry flag, Note that it is the low order
901 bit of the result!!! */
902 CONDITIONAL_SET_FLAG(res
&0x1, m
, F_CF
);
903 /* OVERFLOW is set *IFF* cnt==1, then it is the
904 xor of CF and the most significant bit. Blecck. */
905 CONDITIONAL_SET_FLAG(cnt
==1 &&
906 xor_0x3_tab
[(res
&0x1)+((res
>>14)&0x2)],
912 uint8
ror_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
914 register uint32 res
, cnt
, mask
;
917 s is the rotate distance. It varies from 0 - 8.
918 d is the byte object rotated.
921 The rotate is done mod 8.
923 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
924 2) B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)
927 /* [JCE] Extra brackets to stop gcc -Wall moaning */
928 if ((cnt
= s
% 8)) /* not a typo, do nada if cnt==0 */
930 /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0)*/
931 res
= (d
<< (8-cnt
));
932 /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
933 mask
= (1 << (8-cnt
)) - 1;
934 res
|= (d
>> (cnt
)) & mask
;
935 /* set the new carry flag, Note that it is the low order
936 bit of the result!!! */
937 CONDITIONAL_SET_FLAG(res
&0x80, m
, F_CF
);
938 /* OVERFLOW is set *IFF* cnt==1, then it is the
939 xor of the two most significant bits. Blecck. */
940 CONDITIONAL_SET_FLAG(cnt
==1 &&
941 xor_0x3_tab
[(res
>>6)&0x3],
947 uint16
ror_word(PC_ENV
*m
, uint16 d
, uint16 s
)
949 register uint32 res
, cnt
, mask
;
952 s is the rotate distance. It varies from 0 - 8.
953 d is the byte object rotated.
956 The rotate is done mod 16.
958 1) B_(16-(n+1)) .. B_(0) <- b_(15) .. b_(n)
959 2) B_(15) .. B_(16-n) <- b_(n-1) .. b_(0)
960 I think this is correct.
963 /* [JCE] Extra brackets to stop gcc -Wall moaning */
964 if ((cnt
= s
% 16)) /* not a typo, do nada if cnt==0 */
966 /* B_(15) .. B_(16-n) <- b_(n-1) .. b_(0)*/
967 res
= (d
<< (16-cnt
));
968 /* B_(16-(n+1)) .. B_(0) <- b_(15) .. b_(n) */
969 mask
= (1 << (16-cnt
)) - 1;
970 res
|= (d
>> (cnt
)) & mask
;
971 /* set the new carry flag, Note that it is the low order
972 bit of the result!!! */
973 CONDITIONAL_SET_FLAG(res
&0x8000, m
, F_CF
);
974 /* OVERFLOW is set *IFF* cnt==1, then it is the
975 xor of CF and the most significant bit. Blecck. */
976 CONDITIONAL_SET_FLAG(cnt
==1 &&
977 xor_0x3_tab
[(res
>>14)&0x3],
983 uint8
shl_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
989 /* last bit shifted out goes into carry flag */
993 cf
= d
& (1<<(8-cnt
));
994 CONDITIONAL_SET_FLAG(cf
, m
, F_CF
);
995 CONDITIONAL_SET_FLAG((res
&0xff)==0, m
, F_ZF
);
996 CONDITIONAL_SET_FLAG(res
& 0x80, m
, F_SF
);
997 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
1005 /* Needs simplification. */
1006 CONDITIONAL_SET_FLAG(
1007 (((res
&0x80)==0x80) ^
1008 (ACCESS_FLAG(m
,F_CF
) != 0)) ,
1009 /* was (m->R_FLG&F_CF)==F_CF)), */
1029 uint16
shl_word(PC_ENV
*m
, uint16 d
, uint16 s
)
1038 /* last bit shifted out goes into carry flag */
1039 cf
= d
& (1<<(16-cnt
));
1040 CONDITIONAL_SET_FLAG(cf
, m
, F_CF
);
1041 CONDITIONAL_SET_FLAG((res
&0xffff)==0, m
, F_ZF
);
1042 CONDITIONAL_SET_FLAG(res
& 0x8000, m
, F_SF
);
1043 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
1051 /* Needs simplification. */
1052 CONDITIONAL_SET_FLAG(
1053 (((res
&0x8000)==0x8000) ^
1054 (ACCESS_FLAG(m
,F_CF
) != 0)),
1055 /*((m&F_CF)==F_CF)),*/
1075 uint8
shr_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
1077 uint32 cnt
,res
,cf
,mask
;
1083 mask
= (1<<(8-cnt
))-1;
1084 cf
= d
& (1<<(cnt
-1));
1085 res
= (d
>> cnt
) & mask
;
1086 CONDITIONAL_SET_FLAG(cf
, m
, F_CF
);
1087 CONDITIONAL_SET_FLAG((res
&0xff)==0, m
, F_ZF
);
1088 CONDITIONAL_SET_FLAG(res
& 0x80, m
, F_SF
);
1089 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
1097 CONDITIONAL_SET_FLAG(
1098 xor_0x3_tab
[(res
>>6)&0x3], m
, F_OF
);
1117 uint16
shr_word(PC_ENV
*m
, uint16 d
, uint16 s
)
1119 uint32 cnt
,res
,cf
,mask
;
1126 mask
= (1<<(16-cnt
))-1;
1127 cf
= d
& (1<<(cnt
-1));
1128 res
= (d
>> cnt
) & mask
;
1129 CONDITIONAL_SET_FLAG(cf
, m
, F_CF
);
1130 CONDITIONAL_SET_FLAG((res
&0xffff)==0, m
, F_ZF
);
1131 CONDITIONAL_SET_FLAG(res
& 0x8000, m
, F_SF
);
1132 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
1140 CONDITIONAL_SET_FLAG(
1141 xor_0x3_tab
[(res
>>14)&0x3], m
, F_OF
);
1160 /* XXXX ??? flags may be wrong??? */
1161 uint8
sar_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
1163 uint32 cnt
,res
,cf
,mask
,sf
;
1167 if(cnt
> 0 && cnt
< 8)
1169 mask
= (1<<(8-cnt
))-1;
1170 cf
= d
& (1<<(cnt
-1));
1171 res
= (d
>> cnt
) & mask
;
1172 CONDITIONAL_SET_FLAG(cf
, m
, F_CF
);
1177 CONDITIONAL_SET_FLAG((res
&0xff)==0, m
, F_ZF
);
1178 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
1179 CONDITIONAL_SET_FLAG(res
& 0x80, m
, F_SF
);
1196 CLEAR_FLAG(m
, F_SF
);
1197 CLEAR_FLAG(m
, F_PF
);
1203 uint16
sar_word(PC_ENV
*m
, uint16 d
, uint16 s
)
1205 uint32 cnt
, res
, cf
, mask
, sf
;
1209 if (cnt
> 0 && cnt
< 16)
1211 mask
= (1<<(16-cnt
))-1;
1212 cf
= d
& (1<<(cnt
-1));
1213 res
= (d
>> cnt
) & mask
;
1214 CONDITIONAL_SET_FLAG(cf
, m
, F_CF
);
1219 CONDITIONAL_SET_FLAG((res
&0xffff)==0, m
, F_ZF
);
1220 CONDITIONAL_SET_FLAG(res
& 0x8000, m
, F_SF
);
1221 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
1238 CLEAR_FLAG(m
, F_SF
);
1239 CLEAR_FLAG(m
, F_PF
);
1245 uint8
sbb_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
1247 register uint32 res
; /* all operands in native machine order */
1249 if (ACCESS_FLAG(m
,F_CF
) )
1253 CONDITIONAL_SET_FLAG(res
&0x80, m
, F_SF
);
1254 CONDITIONAL_SET_FLAG((res
&0xff)==0, m
, F_ZF
);
1255 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
1256 /* calculate the borrow chain. See note at top */
1257 bc
= (res
&(~d
|s
))|(~d
&s
);
1258 CONDITIONAL_SET_FLAG(bc
&0x80,m
, F_CF
);
1259 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(bc
>>6)&0x3], m
, F_OF
);
1260 CONDITIONAL_SET_FLAG(bc
&0x8, m
, F_AF
);
1264 uint16
sbb_word(PC_ENV
*m
, uint16 d
, uint16 s
)
1266 register uint32 res
; /* all operands in native machine order */
1268 if (ACCESS_FLAG(m
,F_CF
))
1272 CONDITIONAL_SET_FLAG(res
&0x8000, m
, F_SF
);
1273 CONDITIONAL_SET_FLAG((res
&0xffff)==0, m
, F_ZF
);
1274 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
1275 /* calculate the borrow chain. See note at top */
1276 bc
= (res
&(~d
|s
))|(~d
&s
);
1277 CONDITIONAL_SET_FLAG(bc
&0x8000,m
, F_CF
);
1278 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(bc
>>14)&0x3], m
, F_OF
);
1279 CONDITIONAL_SET_FLAG(bc
&0x8, m
, F_AF
);
1280 return res
& 0xffff;
1283 uint8
sub_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
1285 register uint32 res
; /* all operands in native machine order */
1288 CONDITIONAL_SET_FLAG(res
&0x80, m
, F_SF
);
1289 CONDITIONAL_SET_FLAG((res
&0xff)==0, m
, F_ZF
);
1290 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
1291 /* calculate the borrow chain. See note at top */
1292 bc
= (res
&(~d
|s
))|(~d
&s
);
1293 CONDITIONAL_SET_FLAG(bc
&0x80,m
, F_CF
);
1294 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(bc
>>6)&0x3], m
, F_OF
);
1295 CONDITIONAL_SET_FLAG(bc
&0x8, m
, F_AF
);
1299 uint16
sub_word(PC_ENV
*m
, uint16 d
, uint16 s
)
1301 register uint32 res
; /* all operands in native machine order */
1304 CONDITIONAL_SET_FLAG(res
&0x8000, m
, F_SF
);
1305 CONDITIONAL_SET_FLAG((res
&0xffff)==0, m
, F_ZF
);
1306 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
1307 /* calculate the borrow chain. See note at top */
1308 bc
= (res
&(~d
|s
))|(~d
&s
);
1309 CONDITIONAL_SET_FLAG(bc
&0x8000,m
, F_CF
);
1310 CONDITIONAL_SET_FLAG(xor_0x3_tab
[(bc
>>14)&0x3], m
, F_OF
);
1311 CONDITIONAL_SET_FLAG(bc
&0x8, m
, F_AF
);
1312 return res
& 0xffff;
1315 void test_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
1317 register uint32 res
; /* all operands in native machine order */
1319 CLEAR_FLAG(m
, F_OF
);
1320 CONDITIONAL_SET_FLAG(res
&0x80, m
, F_SF
);
1321 CONDITIONAL_SET_FLAG(res
==0, m
, F_ZF
);
1322 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
1323 /* AF == dont care*/
1324 CLEAR_FLAG(m
, F_CF
);
1327 void test_word(PC_ENV
*m
, uint16 d
, uint16 s
)
1329 register uint32 res
; /* all operands in native machine order */
1331 CLEAR_FLAG(m
, F_OF
);
1332 CONDITIONAL_SET_FLAG(res
&0x8000, m
, F_SF
);
1333 CONDITIONAL_SET_FLAG(res
==0, m
, F_ZF
);
1334 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
1335 /* AF == dont care*/
1336 CLEAR_FLAG(m
, F_CF
);
1339 uint8
xor_byte(PC_ENV
*m
, uint8 d
, uint8 s
)
1341 register uint8 res
; /* all operands in native machine order */
1343 CLEAR_FLAG(m
, F_OF
);
1344 CONDITIONAL_SET_FLAG(res
&0x80, m
, F_SF
);
1345 CONDITIONAL_SET_FLAG(res
==0, m
, F_ZF
);
1346 CONDITIONAL_SET_FLAG(parity_tab
[res
], m
, F_PF
);
1347 CLEAR_FLAG(m
, F_CF
);
1351 uint16
xor_word(PC_ENV
*m
, uint16 d
, uint16 s
)
1353 register uint16 res
; /* all operands in native machine order */
1355 /* set the carry flag to be bit 8 */
1356 CLEAR_FLAG(m
, F_OF
);
1357 CONDITIONAL_SET_FLAG(res
&0x8000, m
, F_SF
);
1358 CONDITIONAL_SET_FLAG(res
==0, m
, F_ZF
);
1359 CONDITIONAL_SET_FLAG(parity_tab
[res
&0xff], m
, F_PF
);
1360 CLEAR_FLAG(m
, F_CF
);
1364 void imul_byte(PC_ENV
*m
, uint8 s
)
1366 int16 res
= (int8
)m
->R_AL
* (int8
)s
;
1368 /* Undef --- Can't hurt */
1369 CONDITIONAL_SET_FLAG(res
&0x8000,m
,F_SF
);
1370 CONDITIONAL_SET_FLAG(res
==0,m
,F_ZF
);
1371 if (m
->R_AH
== 0 || m
->R_AH
== 0xff)
1373 CLEAR_FLAG(m
, F_CF
);
1374 CLEAR_FLAG(m
, F_OF
);
1383 void imul_word(PC_ENV
*m
, uint16 s
)
1385 int32 res
= (int16
)m
->R_AX
* (int16
)s
;
1386 m
->R_AX
= res
& 0xffff;
1387 m
->R_DX
= (res
>> 16) & 0xffff;
1388 /* Undef --- Can't hurt */
1389 CONDITIONAL_SET_FLAG(res
&0x80000000,m
,F_SF
);
1390 CONDITIONAL_SET_FLAG(res
==0,m
,F_ZF
);
1391 if (m
->R_DX
== 0 || m
->R_DX
== 0xffff)
1393 CLEAR_FLAG(m
, F_CF
);
1394 CLEAR_FLAG(m
, F_OF
);
1403 void mul_byte(PC_ENV
*m
, uint8 s
)
1405 uint16 res
= m
->R_AL
* s
;
1407 /* Undef --- Can't hurt */
1409 CONDITIONAL_SET_FLAG(res
==0,m
,F_ZF
);
1412 CLEAR_FLAG(m
, F_CF
);
1413 CLEAR_FLAG(m
, F_OF
);
1422 void mul_word(PC_ENV
*m
, uint16 s
)
1424 uint32 res
= m
->R_AX
* s
;
1425 /* Undef --- Can't hurt */
1427 CONDITIONAL_SET_FLAG(res
==0,m
,F_ZF
);
1428 m
->R_AX
= res
& 0xffff;
1429 m
->R_DX
= (res
>> 16) & 0xffff;
1432 CLEAR_FLAG(m
, F_CF
);
1433 CLEAR_FLAG(m
, F_OF
);
1442 void idiv_byte(PC_ENV
*m
, uint8 s
)
1445 dvd
= (int16
)m
->R_AX
;
1448 i86_intr_raise(m
,0);
1451 div
= dvd
/ (int8
)s
;
1452 mod
= dvd
% (int8
)s
;
1453 if (abs(div
) > 0x7f)
1455 i86_intr_raise(m
,0);
1458 /* Undef --- Can't hurt */
1459 CONDITIONAL_SET_FLAG(div
&0x80,m
,F_SF
);
1460 CONDITIONAL_SET_FLAG(div
==0,m
,F_ZF
);
1461 m
->R_AL
= (int8
)div
;
1462 m
->R_AH
= (int8
)mod
;
1465 void idiv_word(PC_ENV
*m
, uint16 s
)
1467 int32 dvd
,dvs
,div
,mod
;
1469 dvd
= (dvd
<< 16) | m
->R_AX
;
1472 i86_intr_raise(m
,0);
1478 if (abs(div
) > 0x7fff)
1480 i86_intr_raise(m
,0);
1483 /* Undef --- Can't hurt */
1484 CONDITIONAL_SET_FLAG(div
&0x8000,m
,F_SF
);
1485 CONDITIONAL_SET_FLAG(div
==0,m
,F_ZF
);
1486 /* debug_printf(m, "\n%d/%d=%d,%d\n",dvd,dvs,div,mod); */
1491 void div_byte(PC_ENV
*m
, uint8 s
)
1493 uint32 dvd
,dvs
,div
,mod
;
1498 i86_intr_raise(m
,0);
1503 if (abs(div
) > 0xff)
1505 i86_intr_raise(m
,0);
1508 /* Undef --- Can't hurt */
1510 CONDITIONAL_SET_FLAG(div
==0,m
,F_ZF
);
1511 m
->R_AL
= (uint8
)div
;
1512 m
->R_AH
= (uint8
)mod
;
1515 void div_word(PC_ENV
*m
, uint16 s
)
1517 uint32 dvd
,dvs
,div
,mod
;
1519 dvd
= (dvd
<< 16) | m
->R_AX
;
1523 i86_intr_raise(m
,0);
1528 /* printf("dvd=%x dvs=%x -> div=%x mod=%x\n",dvd, dvs,div, mod);*/
1529 if (abs(div
) > 0xffff)
1531 i86_intr_raise(m
,0);
1534 /* Undef --- Can't hurt */
1536 CONDITIONAL_SET_FLAG(div
==0,m
,F_ZF
);