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