Line data Source code
1 : /* $OpenBSD: x86emu.c,v 1.9 2014/06/15 11:04:49 pirofti Exp $ */
2 : /* $NetBSD: x86emu.c,v 1.7 2009/02/03 19:26:29 joerg Exp $ */
3 :
4 : /*
5 : *
6 : * Realmode X86 Emulator Library
7 : *
8 : * Copyright (C) 1996-1999 SciTech Software, Inc.
9 : * Copyright (C) David Mosberger-Tang
10 : * Copyright (C) 1999 Egbert Eich
11 : * Copyright (C) 2007 Joerg Sonnenberger
12 : *
13 : * ========================================================================
14 : *
15 : * Permission to use, copy, modify, distribute, and sell this software and
16 : * its documentation for any purpose is hereby granted without fee,
17 : * provided that the above copyright notice appear in all copies and that
18 : * both that copyright notice and this permission notice appear in
19 : * supporting documentation, and that the name of the authors not be used
20 : * in advertising or publicity pertaining to distribution of the software
21 : * without specific, written prior permission. The authors makes no
22 : * representations about the suitability of this software for any purpose.
23 : * It is provided "as is" without express or implied warranty.
24 : *
25 : * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
26 : * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
27 : * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
28 : * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
29 : * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
30 : * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
31 : * PERFORMANCE OF THIS SOFTWARE.
32 : *
33 : */
34 :
35 : #include <dev/x86emu/x86emu.h>
36 : #include <dev/x86emu/x86emu_regs.h>
37 :
38 : static void x86emu_intr_raise (struct x86emu *, uint8_t type);
39 :
40 : static void x86emu_exec_one_byte(struct x86emu *);
41 : static void x86emu_exec_two_byte(struct x86emu *);
42 :
43 : static void fetch_decode_modrm (struct x86emu *);
44 : static uint8_t fetch_byte_imm (struct x86emu *);
45 : static uint16_t fetch_word_imm (struct x86emu *);
46 : static uint32_t fetch_long_imm (struct x86emu *);
47 : static uint8_t fetch_data_byte (struct x86emu *, uint32_t offset);
48 : static uint8_t fetch_byte (struct x86emu *, uint segment, uint32_t offset);
49 : static uint16_t fetch_data_word (struct x86emu *, uint32_t offset);
50 : static uint16_t fetch_word (struct x86emu *, uint32_t segment, uint32_t offset);
51 : static uint32_t fetch_data_long (struct x86emu *, uint32_t offset);
52 : static uint32_t fetch_long (struct x86emu *, uint32_t segment, uint32_t offset);
53 : static void store_data_byte (struct x86emu *, uint32_t offset, uint8_t val);
54 : static void store_byte (struct x86emu *, uint32_t segment, uint32_t offset, uint8_t val);
55 : static void store_data_word (struct x86emu *, uint32_t offset, uint16_t val);
56 : static void store_word (struct x86emu *, uint32_t segment, uint32_t offset, uint16_t val);
57 : static void store_data_long (struct x86emu *, uint32_t offset, uint32_t val);
58 : static void store_long (struct x86emu *, uint32_t segment, uint32_t offset, uint32_t val);
59 : static uint8_t* decode_rl_byte_register(struct x86emu *);
60 : static uint16_t* decode_rl_word_register(struct x86emu *);
61 : static uint32_t* decode_rl_long_register(struct x86emu *);
62 : static uint8_t* decode_rh_byte_register(struct x86emu *);
63 : static uint16_t* decode_rh_word_register(struct x86emu *);
64 : static uint32_t* decode_rh_long_register(struct x86emu *);
65 : static uint16_t* decode_rh_seg_register(struct x86emu *);
66 : static uint32_t decode_rl_address(struct x86emu *);
67 :
68 : static uint8_t decode_and_fetch_byte(struct x86emu *);
69 : static uint16_t decode_and_fetch_word(struct x86emu *);
70 : static uint32_t decode_and_fetch_long(struct x86emu *);
71 :
72 : static uint8_t decode_and_fetch_byte_imm8(struct x86emu *, uint8_t *);
73 : static uint16_t decode_and_fetch_word_imm8(struct x86emu *, uint8_t *);
74 : static uint32_t decode_and_fetch_long_imm8(struct x86emu *, uint8_t *);
75 :
76 : static uint16_t decode_and_fetch_word_disp(struct x86emu *, int16_t);
77 : static uint32_t decode_and_fetch_long_disp(struct x86emu *, int16_t);
78 :
79 : static void write_back_byte(struct x86emu *, uint8_t);
80 : static void write_back_word(struct x86emu *, uint16_t);
81 : static void write_back_long(struct x86emu *, uint32_t);
82 :
83 : static uint16_t aaa_word (struct x86emu *, uint16_t d);
84 : static uint16_t aas_word (struct x86emu *, uint16_t d);
85 : static uint16_t aad_word (struct x86emu *, uint16_t d);
86 : static uint16_t aam_word (struct x86emu *, uint8_t d);
87 : static uint8_t adc_byte (struct x86emu *, uint8_t d, uint8_t s);
88 : static uint16_t adc_word (struct x86emu *, uint16_t d, uint16_t s);
89 : static uint32_t adc_long (struct x86emu *, uint32_t d, uint32_t s);
90 : static uint8_t add_byte (struct x86emu *, uint8_t d, uint8_t s);
91 : static uint16_t add_word (struct x86emu *, uint16_t d, uint16_t s);
92 : static uint32_t add_long (struct x86emu *, uint32_t d, uint32_t s);
93 : static uint8_t and_byte (struct x86emu *, uint8_t d, uint8_t s);
94 : static uint16_t and_word (struct x86emu *, uint16_t d, uint16_t s);
95 : static uint32_t and_long (struct x86emu *, uint32_t d, uint32_t s);
96 : static uint8_t cmp_byte (struct x86emu *, uint8_t d, uint8_t s);
97 : static uint16_t cmp_word (struct x86emu *, uint16_t d, uint16_t s);
98 : static uint32_t cmp_long (struct x86emu *, uint32_t d, uint32_t s);
99 : static void cmp_byte_no_return (struct x86emu *, uint8_t d, uint8_t s);
100 : static void cmp_word_no_return (struct x86emu *, uint16_t d, uint16_t s);
101 : static void cmp_long_no_return (struct x86emu *, uint32_t d, uint32_t s);
102 : static uint8_t daa_byte (struct x86emu *, uint8_t d);
103 : static uint8_t das_byte (struct x86emu *, uint8_t d);
104 : static uint8_t dec_byte (struct x86emu *, uint8_t d);
105 : static uint16_t dec_word (struct x86emu *, uint16_t d);
106 : static uint32_t dec_long (struct x86emu *, uint32_t d);
107 : static uint8_t inc_byte (struct x86emu *, uint8_t d);
108 : static uint16_t inc_word (struct x86emu *, uint16_t d);
109 : static uint32_t inc_long (struct x86emu *, uint32_t d);
110 : static uint8_t or_byte (struct x86emu *, uint8_t d, uint8_t s);
111 : static uint16_t or_word (struct x86emu *, uint16_t d, uint16_t s);
112 : static uint32_t or_long (struct x86emu *, uint32_t d, uint32_t s);
113 : static uint8_t neg_byte (struct x86emu *, uint8_t s);
114 : static uint16_t neg_word (struct x86emu *, uint16_t s);
115 : static uint32_t neg_long (struct x86emu *, uint32_t s);
116 : static uint8_t rcl_byte (struct x86emu *, uint8_t d, uint8_t s);
117 : static uint16_t rcl_word (struct x86emu *, uint16_t d, uint8_t s);
118 : static uint32_t rcl_long (struct x86emu *, uint32_t d, uint8_t s);
119 : static uint8_t rcr_byte (struct x86emu *, uint8_t d, uint8_t s);
120 : static uint16_t rcr_word (struct x86emu *, uint16_t d, uint8_t s);
121 : static uint32_t rcr_long (struct x86emu *, uint32_t d, uint8_t s);
122 : static uint8_t rol_byte (struct x86emu *, uint8_t d, uint8_t s);
123 : static uint16_t rol_word (struct x86emu *, uint16_t d, uint8_t s);
124 : static uint32_t rol_long (struct x86emu *, uint32_t d, uint8_t s);
125 : static uint8_t ror_byte (struct x86emu *, uint8_t d, uint8_t s);
126 : static uint16_t ror_word (struct x86emu *, uint16_t d, uint8_t s);
127 : static uint32_t ror_long (struct x86emu *, uint32_t d, uint8_t s);
128 : static uint8_t shl_byte (struct x86emu *, uint8_t d, uint8_t s);
129 : static uint16_t shl_word (struct x86emu *, uint16_t d, uint8_t s);
130 : static uint32_t shl_long (struct x86emu *, uint32_t d, uint8_t s);
131 : static uint8_t shr_byte (struct x86emu *, uint8_t d, uint8_t s);
132 : static uint16_t shr_word (struct x86emu *, uint16_t d, uint8_t s);
133 : static uint32_t shr_long (struct x86emu *, uint32_t d, uint8_t s);
134 : static uint8_t sar_byte (struct x86emu *, uint8_t d, uint8_t s);
135 : static uint16_t sar_word (struct x86emu *, uint16_t d, uint8_t s);
136 : static uint32_t sar_long (struct x86emu *, uint32_t d, uint8_t s);
137 : static uint16_t shld_word (struct x86emu *, uint16_t d, uint16_t fill, uint8_t s);
138 : static uint32_t shld_long (struct x86emu *, uint32_t d, uint32_t fill, uint8_t s);
139 : static uint16_t shrd_word (struct x86emu *, uint16_t d, uint16_t fill, uint8_t s);
140 : static uint32_t shrd_long (struct x86emu *, uint32_t d, uint32_t fill, uint8_t s);
141 : static uint8_t sbb_byte (struct x86emu *, uint8_t d, uint8_t s);
142 : static uint16_t sbb_word (struct x86emu *, uint16_t d, uint16_t s);
143 : static uint32_t sbb_long (struct x86emu *, uint32_t d, uint32_t s);
144 : static uint8_t sub_byte (struct x86emu *, uint8_t d, uint8_t s);
145 : static uint16_t sub_word (struct x86emu *, uint16_t d, uint16_t s);
146 : static uint32_t sub_long (struct x86emu *, uint32_t d, uint32_t s);
147 : static void test_byte (struct x86emu *, uint8_t d, uint8_t s);
148 : static void test_word (struct x86emu *, uint16_t d, uint16_t s);
149 : static void test_long (struct x86emu *, uint32_t d, uint32_t s);
150 : static uint8_t xor_byte (struct x86emu *, uint8_t d, uint8_t s);
151 : static uint16_t xor_word (struct x86emu *, uint16_t d, uint16_t s);
152 : static uint32_t xor_long (struct x86emu *, uint32_t d, uint32_t s);
153 : static void imul_byte (struct x86emu *, uint8_t s);
154 : static void imul_word (struct x86emu *, uint16_t s);
155 : static void imul_long (struct x86emu *, uint32_t s);
156 : static void mul_byte (struct x86emu *, uint8_t s);
157 : static void mul_word (struct x86emu *, uint16_t s);
158 : static void mul_long (struct x86emu *, uint32_t s);
159 : static void idiv_byte (struct x86emu *, uint8_t s);
160 : static void idiv_word (struct x86emu *, uint16_t s);
161 : static void idiv_long (struct x86emu *, uint32_t s);
162 : static void div_byte (struct x86emu *, uint8_t s);
163 : static void div_word (struct x86emu *, uint16_t s);
164 : static void div_long (struct x86emu *, uint32_t s);
165 : static void ins (struct x86emu *, int size);
166 : static void outs (struct x86emu *, int size);
167 : static void push_word (struct x86emu *, uint16_t w);
168 : static void push_long (struct x86emu *, uint32_t w);
169 : static uint16_t pop_word (struct x86emu *);
170 : static uint32_t pop_long (struct x86emu *);
171 :
172 : /*
173 : * REMARKS:
174 : * Handles any pending asychronous interrupts.
175 : */
176 : static void
177 0 : x86emu_intr_dispatch(struct x86emu *emu, uint8_t intno)
178 : {
179 0 : if (emu->_x86emu_intrTab[intno]) {
180 0 : (*emu->_x86emu_intrTab[intno]) (emu, intno);
181 0 : } else {
182 0 : push_word(emu, (uint16_t) emu->x86.R_FLG);
183 0 : CLEAR_FLAG(F_IF);
184 0 : CLEAR_FLAG(F_TF);
185 0 : push_word(emu, emu->x86.R_CS);
186 0 : emu->x86.R_CS = fetch_word(emu, 0, intno * 4 + 2);
187 0 : push_word(emu, emu->x86.R_IP);
188 0 : emu->x86.R_IP = fetch_word(emu, 0, intno * 4);
189 : }
190 0 : }
191 :
192 : static void
193 0 : x86emu_intr_handle(struct x86emu *emu)
194 : {
195 : uint8_t intno;
196 :
197 0 : if (emu->x86.intr & INTR_SYNCH) {
198 0 : intno = emu->x86.intno;
199 0 : emu->x86.intr = 0;
200 0 : x86emu_intr_dispatch(emu, intno);
201 0 : }
202 0 : }
203 :
204 : /*
205 : * PARAMETERS:
206 : * intrnum - Interrupt number to raise
207 : *
208 : * REMARKS:
209 : * Raise the specified interrupt to be handled before the execution of the
210 : * next instruction.
211 : */
212 : void
213 0 : x86emu_intr_raise(struct x86emu *emu, uint8_t intrnum)
214 : {
215 0 : emu->x86.intno = intrnum;
216 0 : emu->x86.intr |= INTR_SYNCH;
217 0 : }
218 :
219 : /*
220 : * REMARKS:
221 : * Main execution loop for the emulator. We return from here when the system
222 : * halts, which is normally caused by a stack fault when we return from the
223 : * original real mode call.
224 : */
225 : void
226 0 : x86emu_exec(struct x86emu *emu)
227 : {
228 0 : emu->x86.intr = 0;
229 :
230 : #ifdef _KERNEL
231 0 : if (setjmp(&emu->exec_state))
232 : return;
233 : #else
234 : if (setjmp(emu->exec_state))
235 : return;
236 : #endif
237 :
238 0 : for (;;) {
239 0 : if (emu->x86.intr) {
240 0 : if (((emu->x86.intr & INTR_SYNCH) &&
241 0 : (emu->x86.intno == 0 || emu->x86.intno == 2)) ||
242 0 : !ACCESS_FLAG(F_IF)) {
243 0 : x86emu_intr_handle(emu);
244 0 : }
245 : }
246 0 : if (emu->x86.R_CS == 0 && emu->x86.R_IP == 0)
247 : return;
248 0 : x86emu_exec_one_byte(emu);
249 0 : ++emu->cur_cycles;
250 : }
251 0 : }
252 :
253 : void
254 0 : x86emu_exec_call(struct x86emu *emu, uint16_t seg, uint16_t off)
255 : {
256 0 : push_word(emu, 0);
257 0 : push_word(emu, 0);
258 0 : emu->x86.R_CS = seg;
259 0 : emu->x86.R_IP = off;
260 :
261 0 : x86emu_exec(emu);
262 0 : }
263 :
264 : void
265 0 : x86emu_exec_intr(struct x86emu *emu, uint8_t intr)
266 : {
267 0 : push_word(emu, emu->x86.R_FLG);
268 0 : CLEAR_FLAG(F_IF);
269 0 : CLEAR_FLAG(F_TF);
270 0 : push_word(emu, 0);
271 0 : push_word(emu, 0);
272 0 : emu->x86.R_CS = (*emu->emu_rdw)(emu, intr * 4 + 2);
273 0 : emu->x86.R_IP = (*emu->emu_rdw)(emu, intr * 4);
274 0 : emu->x86.intr = 0;
275 :
276 0 : x86emu_exec(emu);
277 0 : }
278 :
279 : /*
280 : * REMARKS:
281 : * Halts the system by setting the halted system flag.
282 : */
283 : void
284 0 : x86emu_halt_sys(struct x86emu *emu)
285 : {
286 : #ifdef _KERNEL
287 0 : longjmp(&emu->exec_state);
288 : #else
289 : longjmp(emu->exec_state, 1);
290 : #endif
291 : }
292 :
293 : /*
294 : * PARAMETERS:
295 : * mod - Mod value from decoded byte
296 : * regh - Reg h value from decoded byte
297 : * regl - Reg l value from decoded byte
298 : *
299 : * REMARKS:
300 : * Raise the specified interrupt to be handled before the execution of the
301 : * next instruction.
302 : *
303 : * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
304 : */
305 : static void
306 0 : fetch_decode_modrm(struct x86emu *emu)
307 : {
308 : int fetched;
309 :
310 0 : fetched = fetch_byte_imm(emu);
311 0 : emu->cur_mod = (fetched >> 6) & 0x03;
312 0 : emu->cur_rh = (fetched >> 3) & 0x07;
313 0 : emu->cur_rl = (fetched >> 0) & 0x07;
314 0 : }
315 :
316 : /*
317 : * RETURNS:
318 : * Immediate byte value read from instruction queue
319 : *
320 : * REMARKS:
321 : * This function returns the immediate byte from the instruction queue, and
322 : * moves the instruction pointer to the next value.
323 : *
324 : * NOTE: Do not inline this function, as (*emu->emu_rdb) is already inline!
325 : */
326 : static uint8_t
327 0 : fetch_byte_imm(struct x86emu *emu)
328 : {
329 : uint8_t fetched;
330 :
331 0 : fetched = fetch_byte(emu, emu->x86.R_CS, emu->x86.R_IP);
332 0 : emu->x86.R_IP++;
333 0 : return fetched;
334 : }
335 :
336 : /*
337 : * RETURNS:
338 : * Immediate word value read from instruction queue
339 : *
340 : * REMARKS:
341 : * This function returns the immediate byte from the instruction queue, and
342 : * moves the instruction pointer to the next value.
343 : *
344 : * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
345 : */
346 : static uint16_t
347 0 : fetch_word_imm(struct x86emu *emu)
348 : {
349 : uint16_t fetched;
350 :
351 0 : fetched = fetch_word(emu, emu->x86.R_CS, emu->x86.R_IP);
352 0 : emu->x86.R_IP += 2;
353 0 : return fetched;
354 : }
355 :
356 : /*
357 : * RETURNS:
358 : * Immediate lone value read from instruction queue
359 : *
360 : * REMARKS:
361 : * This function returns the immediate byte from the instruction queue, and
362 : * moves the instruction pointer to the next value.
363 : *
364 : * NOTE: Do not inline this function, as (*emu->emu_rdw) is already inline!
365 : */
366 : static uint32_t
367 0 : fetch_long_imm(struct x86emu *emu)
368 : {
369 : uint32_t fetched;
370 :
371 0 : fetched = fetch_long(emu, emu->x86.R_CS, emu->x86.R_IP);
372 0 : emu->x86.R_IP += 4;
373 0 : return fetched;
374 : }
375 :
376 : /*
377 : * RETURNS:
378 : * Value of the default data segment
379 : *
380 : * REMARKS:
381 : * Inline function that returns the default data segment for the current
382 : * instruction.
383 : *
384 : * On the x86 processor, the default segment is not always DS if there is
385 : * no segment override. Address modes such as -3[BP] or 10[BP+SI] all refer to
386 : * addresses relative to SS (ie: on the stack). So, at the minimum, all
387 : * decodings of addressing modes would have to set/clear a bit describing
388 : * whether the access is relative to DS or SS. That is the function of the
389 : * cpu-state-varible emu->x86.mode. There are several potential states:
390 : *
391 : * repe prefix seen (handled elsewhere)
392 : * repne prefix seen (ditto)
393 : *
394 : * cs segment override
395 : * ds segment override
396 : * es segment override
397 : * fs segment override
398 : * gs segment override
399 : * ss segment override
400 : *
401 : * ds/ss select (in absense of override)
402 : *
403 : * Each of the above 7 items are handled with a bit in the mode field.
404 : */
405 : static uint32_t
406 0 : get_data_segment(struct x86emu *emu)
407 : {
408 0 : switch (emu->x86.mode & SYSMODE_SEGMASK) {
409 : case 0: /* default case: use ds register */
410 : case SYSMODE_SEGOVR_DS:
411 : case SYSMODE_SEGOVR_DS | SYSMODE_SEG_DS_SS:
412 0 : return emu->x86.R_DS;
413 : case SYSMODE_SEG_DS_SS:/* non-overridden, use ss register */
414 0 : return emu->x86.R_SS;
415 : case SYSMODE_SEGOVR_CS:
416 : case SYSMODE_SEGOVR_CS | SYSMODE_SEG_DS_SS:
417 0 : return emu->x86.R_CS;
418 : case SYSMODE_SEGOVR_ES:
419 : case SYSMODE_SEGOVR_ES | SYSMODE_SEG_DS_SS:
420 0 : return emu->x86.R_ES;
421 : case SYSMODE_SEGOVR_FS:
422 : case SYSMODE_SEGOVR_FS | SYSMODE_SEG_DS_SS:
423 0 : return emu->x86.R_FS;
424 : case SYSMODE_SEGOVR_GS:
425 : case SYSMODE_SEGOVR_GS | SYSMODE_SEG_DS_SS:
426 0 : return emu->x86.R_GS;
427 : case SYSMODE_SEGOVR_SS:
428 : case SYSMODE_SEGOVR_SS | SYSMODE_SEG_DS_SS:
429 0 : return emu->x86.R_SS;
430 : }
431 0 : x86emu_halt_sys(emu);
432 0 : }
433 :
434 : /*
435 : * PARAMETERS:
436 : * offset - Offset to load data from
437 : *
438 : * RETURNS:
439 : * Byte value read from the absolute memory location.
440 : *
441 : * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
442 : */
443 : static uint8_t
444 0 : fetch_data_byte(struct x86emu *emu, uint32_t offset)
445 : {
446 0 : return fetch_byte(emu, get_data_segment(emu), offset);
447 : }
448 :
449 : /*
450 : * PARAMETERS:
451 : * offset - Offset to load data from
452 : *
453 : * RETURNS:
454 : * Word value read from the absolute memory location.
455 : *
456 : * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
457 : */
458 : static uint16_t
459 0 : fetch_data_word(struct x86emu *emu, uint32_t offset)
460 : {
461 0 : return fetch_word(emu, get_data_segment(emu), offset);
462 : }
463 :
464 : /*
465 : * PARAMETERS:
466 : * offset - Offset to load data from
467 : *
468 : * RETURNS:
469 : * Long value read from the absolute memory location.
470 : *
471 : * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
472 : */
473 : static uint32_t
474 0 : fetch_data_long(struct x86emu *emu, uint32_t offset)
475 : {
476 0 : return fetch_long(emu, get_data_segment(emu), offset);
477 : }
478 :
479 : /*
480 : * PARAMETERS:
481 : * segment - Segment to load data from
482 : * offset - Offset to load data from
483 : *
484 : * RETURNS:
485 : * Byte value read from the absolute memory location.
486 : *
487 : * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
488 : */
489 : static uint8_t
490 0 : fetch_byte(struct x86emu *emu, uint32_t segment, uint32_t offset)
491 : {
492 0 : return (*emu->emu_rdb) (emu, ((uint32_t) segment << 4) + offset);
493 : }
494 :
495 : /*
496 : * PARAMETERS:
497 : * segment - Segment to load data from
498 : * offset - Offset to load data from
499 : *
500 : * RETURNS:
501 : * Word value read from the absolute memory location.
502 : *
503 : * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
504 : */
505 : static uint16_t
506 0 : fetch_word(struct x86emu *emu, uint32_t segment, uint32_t offset)
507 : {
508 0 : return (*emu->emu_rdw) (emu, ((uint32_t) segment << 4) + offset);
509 : }
510 :
511 : /*
512 : * PARAMETERS:
513 : * segment - Segment to load data from
514 : * offset - Offset to load data from
515 : *
516 : * RETURNS:
517 : * Long value read from the absolute memory location.
518 : *
519 : * NOTE: Do not inline this function as (*emu->emu_rdX) is already inline!
520 : */
521 : static uint32_t
522 0 : fetch_long(struct x86emu *emu, uint32_t segment, uint32_t offset)
523 : {
524 0 : return (*emu->emu_rdl) (emu, ((uint32_t) segment << 4) + offset);
525 : }
526 :
527 : /*
528 : * PARAMETERS:
529 : * offset - Offset to store data at
530 : * val - Value to store
531 : *
532 : * REMARKS:
533 : * Writes a word value to an segmented memory location. The segment used is
534 : * the current 'default' segment, which may have been overridden.
535 : *
536 : * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
537 : */
538 : static void
539 0 : store_data_byte(struct x86emu *emu, uint32_t offset, uint8_t val)
540 : {
541 0 : store_byte(emu, get_data_segment(emu), offset, val);
542 0 : }
543 :
544 : /*
545 : * PARAMETERS:
546 : * offset - Offset to store data at
547 : * val - Value to store
548 : *
549 : * REMARKS:
550 : * Writes a word value to an segmented memory location. The segment used is
551 : * the current 'default' segment, which may have been overridden.
552 : *
553 : * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
554 : */
555 : static void
556 0 : store_data_word(struct x86emu *emu, uint32_t offset, uint16_t val)
557 : {
558 0 : store_word(emu, get_data_segment(emu), offset, val);
559 0 : }
560 :
561 : /*
562 : * PARAMETERS:
563 : * offset - Offset to store data at
564 : * val - Value to store
565 : *
566 : * REMARKS:
567 : * Writes a long value to an segmented memory location. The segment used is
568 : * the current 'default' segment, which may have been overridden.
569 : *
570 : * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
571 : */
572 : static void
573 0 : store_data_long(struct x86emu *emu, uint32_t offset, uint32_t val)
574 : {
575 0 : store_long(emu, get_data_segment(emu), offset, val);
576 0 : }
577 :
578 : /*
579 : * PARAMETERS:
580 : * segment - Segment to store data at
581 : * offset - Offset to store data at
582 : * val - Value to store
583 : *
584 : * REMARKS:
585 : * Writes a byte value to an absolute memory location.
586 : *
587 : * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
588 : */
589 : static void
590 0 : store_byte(struct x86emu *emu, uint32_t segment, uint32_t offset, uint8_t val)
591 : {
592 0 : (*emu->emu_wrb) (emu, ((uint32_t) segment << 4) + offset, val);
593 0 : }
594 :
595 : /*
596 : * PARAMETERS:
597 : * segment - Segment to store data at
598 : * offset - Offset to store data at
599 : * val - Value to store
600 : *
601 : * REMARKS:
602 : * Writes a word value to an absolute memory location.
603 : *
604 : * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
605 : */
606 : static void
607 0 : store_word(struct x86emu *emu, uint32_t segment, uint32_t offset, uint16_t val)
608 : {
609 0 : (*emu->emu_wrw) (emu, ((uint32_t) segment << 4) + offset, val);
610 0 : }
611 :
612 : /*
613 : * PARAMETERS:
614 : * segment - Segment to store data at
615 : * offset - Offset to store data at
616 : * val - Value to store
617 : *
618 : * REMARKS:
619 : * Writes a long value to an absolute memory location.
620 : *
621 : * NOTE: Do not inline this function as (*emu->emu_wrX) is already inline!
622 : */
623 : static void
624 0 : store_long(struct x86emu *emu, uint32_t segment, uint32_t offset, uint32_t val)
625 : {
626 0 : (*emu->emu_wrl) (emu, ((uint32_t) segment << 4) + offset, val);
627 0 : }
628 :
629 : /*
630 : * PARAMETERS:
631 : * reg - Register to decode
632 : *
633 : * RETURNS:
634 : * Pointer to the appropriate register
635 : *
636 : * REMARKS:
637 : * Return a pointer to the register given by the R/RM field of the
638 : * modrm byte, for byte operands. Also enables the decoding of instructions.
639 : */
640 : static uint8_t *
641 0 : decode_rm_byte_register(struct x86emu *emu, int reg)
642 : {
643 0 : switch (reg) {
644 : case 0:
645 0 : return &emu->x86.R_AL;
646 : case 1:
647 0 : return &emu->x86.R_CL;
648 : case 2:
649 0 : return &emu->x86.R_DL;
650 : case 3:
651 0 : return &emu->x86.R_BL;
652 : case 4:
653 0 : return &emu->x86.R_AH;
654 : case 5:
655 0 : return &emu->x86.R_CH;
656 : case 6:
657 0 : return &emu->x86.R_DH;
658 : case 7:
659 0 : return &emu->x86.R_BH;
660 : default:
661 0 : x86emu_halt_sys(emu);
662 : }
663 0 : }
664 :
665 : static uint8_t *
666 0 : decode_rl_byte_register(struct x86emu *emu)
667 : {
668 0 : return decode_rm_byte_register(emu, emu->cur_rl);
669 : }
670 :
671 : static uint8_t *
672 0 : decode_rh_byte_register(struct x86emu *emu)
673 : {
674 0 : return decode_rm_byte_register(emu, emu->cur_rh);
675 : }
676 :
677 : /*
678 : * PARAMETERS:
679 : * reg - Register to decode
680 : *
681 : * RETURNS:
682 : * Pointer to the appropriate register
683 : *
684 : * REMARKS:
685 : * Return a pointer to the register given by the R/RM field of the
686 : * modrm byte, for word operands. Also enables the decoding of instructions.
687 : */
688 : static uint16_t *
689 0 : decode_rm_word_register(struct x86emu *emu, int reg)
690 : {
691 0 : switch (reg) {
692 : case 0:
693 0 : return &emu->x86.R_AX;
694 : case 1:
695 0 : return &emu->x86.R_CX;
696 : case 2:
697 0 : return &emu->x86.R_DX;
698 : case 3:
699 0 : return &emu->x86.R_BX;
700 : case 4:
701 0 : return &emu->x86.R_SP;
702 : case 5:
703 0 : return &emu->x86.R_BP;
704 : case 6:
705 0 : return &emu->x86.R_SI;
706 : case 7:
707 0 : return &emu->x86.R_DI;
708 : default:
709 0 : x86emu_halt_sys(emu);
710 : }
711 0 : }
712 :
713 : static uint16_t *
714 0 : decode_rl_word_register(struct x86emu *emu)
715 : {
716 0 : return decode_rm_word_register(emu, emu->cur_rl);
717 : }
718 :
719 : static uint16_t *
720 0 : decode_rh_word_register(struct x86emu *emu)
721 : {
722 0 : return decode_rm_word_register(emu, emu->cur_rh);
723 : }
724 :
725 : /*
726 : * PARAMETERS:
727 : * reg - Register to decode
728 : *
729 : * RETURNS:
730 : * Pointer to the appropriate register
731 : *
732 : * REMARKS:
733 : * Return a pointer to the register given by the R/RM field of the
734 : * modrm byte, for dword operands. Also enables the decoding of instructions.
735 : */
736 : static uint32_t *
737 0 : decode_rm_long_register(struct x86emu *emu, int reg)
738 : {
739 0 : switch (reg) {
740 : case 0:
741 0 : return &emu->x86.R_EAX;
742 : case 1:
743 0 : return &emu->x86.R_ECX;
744 : case 2:
745 0 : return &emu->x86.R_EDX;
746 : case 3:
747 0 : return &emu->x86.R_EBX;
748 : case 4:
749 0 : return &emu->x86.R_ESP;
750 : case 5:
751 0 : return &emu->x86.R_EBP;
752 : case 6:
753 0 : return &emu->x86.R_ESI;
754 : case 7:
755 0 : return &emu->x86.R_EDI;
756 : default:
757 0 : x86emu_halt_sys(emu);
758 : }
759 0 : }
760 :
761 : static uint32_t *
762 0 : decode_rl_long_register(struct x86emu *emu)
763 : {
764 0 : return decode_rm_long_register(emu, emu->cur_rl);
765 : }
766 :
767 : static uint32_t *
768 0 : decode_rh_long_register(struct x86emu *emu)
769 : {
770 0 : return decode_rm_long_register(emu, emu->cur_rh);
771 : }
772 :
773 :
774 : /*
775 : * PARAMETERS:
776 : * reg - Register to decode
777 : *
778 : * RETURNS:
779 : * Pointer to the appropriate register
780 : *
781 : * REMARKS:
782 : * Return a pointer to the register given by the R/RM field of the
783 : * modrm byte, for word operands, modified from above for the weirdo
784 : * special case of segreg operands. Also enables the decoding of instructions.
785 : */
786 : static uint16_t *
787 0 : decode_rh_seg_register(struct x86emu *emu)
788 : {
789 0 : switch (emu->cur_rh) {
790 : case 0:
791 0 : return &emu->x86.R_ES;
792 : case 1:
793 0 : return &emu->x86.R_CS;
794 : case 2:
795 0 : return &emu->x86.R_SS;
796 : case 3:
797 0 : return &emu->x86.R_DS;
798 : case 4:
799 0 : return &emu->x86.R_FS;
800 : case 5:
801 0 : return &emu->x86.R_GS;
802 : default:
803 0 : x86emu_halt_sys(emu);
804 : }
805 0 : }
806 :
807 : /*
808 : * Return offset from the SIB Byte.
809 : */
810 : static uint32_t
811 0 : decode_sib_address(struct x86emu *emu, int sib, int mod)
812 : {
813 : uint32_t base = 0, i = 0, scale = 1;
814 :
815 0 : switch (sib & 0x07) {
816 : case 0:
817 0 : base = emu->x86.R_EAX;
818 0 : break;
819 : case 1:
820 0 : base = emu->x86.R_ECX;
821 :
822 0 : break;
823 : case 2:
824 0 : base = emu->x86.R_EDX;
825 0 : break;
826 : case 3:
827 0 : base = emu->x86.R_EBX;
828 0 : break;
829 : case 4:
830 0 : base = emu->x86.R_ESP;
831 0 : emu->x86.mode |= SYSMODE_SEG_DS_SS;
832 0 : break;
833 : case 5:
834 0 : if (mod == 0) {
835 0 : base = fetch_long_imm(emu);
836 0 : } else {
837 0 : base = emu->x86.R_EBP;
838 0 : emu->x86.mode |= SYSMODE_SEG_DS_SS;
839 : }
840 : break;
841 : case 6:
842 0 : base = emu->x86.R_ESI;
843 0 : break;
844 : case 7:
845 0 : base = emu->x86.R_EDI;
846 0 : break;
847 : }
848 0 : switch ((sib >> 3) & 0x07) {
849 : case 0:
850 0 : i = emu->x86.R_EAX;
851 0 : break;
852 : case 1:
853 0 : i = emu->x86.R_ECX;
854 0 : break;
855 : case 2:
856 0 : i = emu->x86.R_EDX;
857 0 : break;
858 : case 3:
859 0 : i = emu->x86.R_EBX;
860 0 : break;
861 : case 4:
862 : i = 0;
863 0 : break;
864 : case 5:
865 0 : i = emu->x86.R_EBP;
866 0 : break;
867 : case 6:
868 0 : i = emu->x86.R_ESI;
869 0 : break;
870 : case 7:
871 0 : i = emu->x86.R_EDI;
872 0 : break;
873 : }
874 0 : scale = 1 << ((sib >> 6) & 0x03);
875 0 : return base + (i * scale);
876 : }
877 :
878 : /*
879 : * PARAMETERS:
880 : * rm - RM value to decode
881 : *
882 : * RETURNS:
883 : * Offset in memory for the address decoding
884 : *
885 : * REMARKS:
886 : * Return the offset given by mod=00, mod=01 or mod=10 addressing.
887 : * Also enables the decoding of instructions.
888 : */
889 : static uint32_t
890 0 : decode_rl_address(struct x86emu *emu)
891 : {
892 0 : if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
893 : uint32_t offset, sib;
894 : /* 32-bit addressing */
895 0 : switch (emu->cur_rl) {
896 : case 0:
897 0 : offset = emu->x86.R_EAX;
898 0 : break;
899 : case 1:
900 0 : offset = emu->x86.R_ECX;
901 0 : break;
902 : case 2:
903 0 : offset = emu->x86.R_EDX;
904 0 : break;
905 : case 3:
906 0 : offset = emu->x86.R_EBX;
907 0 : break;
908 : case 4:
909 0 : sib = fetch_byte_imm(emu);
910 0 : offset = decode_sib_address(emu, sib, 0);
911 0 : break;
912 : case 5:
913 0 : if (emu->cur_mod == 0) {
914 0 : offset = fetch_long_imm(emu);
915 0 : } else {
916 0 : emu->x86.mode |= SYSMODE_SEG_DS_SS;
917 0 : offset = emu->x86.R_EBP;
918 : }
919 : break;
920 : case 6:
921 0 : offset = emu->x86.R_ESI;
922 0 : break;
923 : case 7:
924 0 : offset = emu->x86.R_EDI;
925 0 : break;
926 : default:
927 : x86emu_halt_sys(emu);
928 : }
929 0 : if (emu->cur_mod == 1)
930 0 : offset += (int8_t)fetch_byte_imm(emu);
931 0 : else if (emu->cur_mod == 2)
932 0 : offset += fetch_long_imm(emu);
933 : return offset;
934 : } else {
935 : uint16_t offset;
936 :
937 : /* 16-bit addressing */
938 0 : switch (emu->cur_rl) {
939 : case 0:
940 0 : offset = emu->x86.R_BX + emu->x86.R_SI;
941 0 : break;
942 : case 1:
943 0 : offset = emu->x86.R_BX + emu->x86.R_DI;
944 0 : break;
945 : case 2:
946 0 : emu->x86.mode |= SYSMODE_SEG_DS_SS;
947 0 : offset = emu->x86.R_BP + emu->x86.R_SI;
948 0 : break;
949 : case 3:
950 0 : emu->x86.mode |= SYSMODE_SEG_DS_SS;
951 0 : offset = emu->x86.R_BP + emu->x86.R_DI;
952 0 : break;
953 : case 4:
954 0 : offset = emu->x86.R_SI;
955 0 : break;
956 : case 5:
957 0 : offset = emu->x86.R_DI;
958 0 : break;
959 : case 6:
960 0 : if (emu->cur_mod == 0) {
961 0 : offset = fetch_word_imm(emu);
962 0 : } else {
963 0 : emu->x86.mode |= SYSMODE_SEG_DS_SS;
964 0 : offset = emu->x86.R_BP;
965 : }
966 : break;
967 : case 7:
968 0 : offset = emu->x86.R_BX;
969 0 : break;
970 : default:
971 : x86emu_halt_sys(emu);
972 : }
973 0 : if (emu->cur_mod == 1)
974 0 : offset += (int8_t)fetch_byte_imm(emu);
975 0 : else if (emu->cur_mod == 2)
976 0 : offset += fetch_word_imm(emu);
977 0 : return offset;
978 : }
979 0 : }
980 :
981 : static uint8_t
982 0 : decode_and_fetch_byte(struct x86emu *emu)
983 : {
984 0 : if (emu->cur_mod != 3) {
985 0 : emu->cur_offset = decode_rl_address(emu);
986 0 : return fetch_data_byte(emu, emu->cur_offset);
987 : } else {
988 0 : return *decode_rl_byte_register(emu);
989 : }
990 0 : }
991 :
992 : static uint16_t
993 0 : decode_and_fetch_word_disp(struct x86emu *emu, int16_t disp)
994 : {
995 0 : if (emu->cur_mod != 3) {
996 : /* TODO: A20 gate emulation */
997 0 : emu->cur_offset = decode_rl_address(emu) + disp;
998 0 : if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
999 0 : emu->cur_offset &= 0xffff;
1000 0 : return fetch_data_word(emu, emu->cur_offset);
1001 : } else {
1002 0 : return *decode_rl_word_register(emu);
1003 : }
1004 0 : }
1005 :
1006 : static uint32_t
1007 0 : decode_and_fetch_long_disp(struct x86emu *emu, int16_t disp)
1008 : {
1009 0 : if (emu->cur_mod != 3) {
1010 : /* TODO: A20 gate emulation */
1011 0 : emu->cur_offset = decode_rl_address(emu) + disp;
1012 0 : if ((emu->x86.mode & SYSMODE_PREFIX_ADDR) == 0)
1013 0 : emu->cur_offset &= 0xffff;
1014 0 : return fetch_data_long(emu, emu->cur_offset);
1015 : } else {
1016 0 : return *decode_rl_long_register(emu);
1017 : }
1018 0 : }
1019 :
1020 : uint16_t
1021 0 : decode_and_fetch_word(struct x86emu *emu)
1022 : {
1023 0 : return decode_and_fetch_word_disp(emu, 0);
1024 : }
1025 :
1026 : uint32_t
1027 0 : decode_and_fetch_long(struct x86emu *emu)
1028 : {
1029 0 : return decode_and_fetch_long_disp(emu, 0);
1030 : }
1031 :
1032 : uint8_t
1033 0 : decode_and_fetch_byte_imm8(struct x86emu *emu, uint8_t *imm)
1034 : {
1035 0 : if (emu->cur_mod != 3) {
1036 0 : emu->cur_offset = decode_rl_address(emu);
1037 0 : *imm = fetch_byte_imm(emu);
1038 0 : return fetch_data_byte(emu, emu->cur_offset);
1039 : } else {
1040 0 : *imm = fetch_byte_imm(emu);
1041 0 : return *decode_rl_byte_register(emu);
1042 : }
1043 0 : }
1044 :
1045 : static uint16_t
1046 0 : decode_and_fetch_word_imm8(struct x86emu *emu, uint8_t *imm)
1047 : {
1048 0 : if (emu->cur_mod != 3) {
1049 0 : emu->cur_offset = decode_rl_address(emu);
1050 0 : *imm = fetch_byte_imm(emu);
1051 0 : return fetch_data_word(emu, emu->cur_offset);
1052 : } else {
1053 0 : *imm = fetch_byte_imm(emu);
1054 0 : return *decode_rl_word_register(emu);
1055 : }
1056 0 : }
1057 :
1058 : static uint32_t
1059 0 : decode_and_fetch_long_imm8(struct x86emu *emu, uint8_t *imm)
1060 : {
1061 0 : if (emu->cur_mod != 3) {
1062 0 : emu->cur_offset = decode_rl_address(emu);
1063 0 : *imm = fetch_byte_imm(emu);
1064 0 : return fetch_data_long(emu, emu->cur_offset);
1065 : } else {
1066 0 : *imm = fetch_byte_imm(emu);
1067 0 : return *decode_rl_long_register(emu);
1068 : }
1069 0 : }
1070 :
1071 : static void
1072 0 : write_back_byte(struct x86emu *emu, uint8_t val)
1073 : {
1074 0 : if (emu->cur_mod != 3)
1075 0 : store_data_byte(emu, emu->cur_offset, val);
1076 : else
1077 0 : *decode_rl_byte_register(emu) = val;
1078 0 : }
1079 :
1080 : static void
1081 0 : write_back_word(struct x86emu *emu, uint16_t val)
1082 : {
1083 0 : if (emu->cur_mod != 3)
1084 0 : store_data_word(emu, emu->cur_offset, val);
1085 : else
1086 0 : *decode_rl_word_register(emu) = val;
1087 0 : }
1088 :
1089 : static void
1090 0 : write_back_long(struct x86emu *emu, uint32_t val)
1091 : {
1092 0 : if (emu->cur_mod != 3)
1093 0 : store_data_long(emu, emu->cur_offset, val);
1094 : else
1095 0 : *decode_rl_long_register(emu) = val;
1096 0 : }
1097 :
1098 : static void
1099 0 : common_inc_word_long(struct x86emu *emu, union x86emu_register *reg)
1100 : {
1101 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1102 0 : reg->I32_reg.e_reg = inc_long(emu, reg->I32_reg.e_reg);
1103 : else
1104 0 : reg->I16_reg.x_reg = inc_word(emu, reg->I16_reg.x_reg);
1105 0 : }
1106 :
1107 : static void
1108 0 : common_dec_word_long(struct x86emu *emu, union x86emu_register *reg)
1109 : {
1110 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1111 0 : reg->I32_reg.e_reg = dec_long(emu, reg->I32_reg.e_reg);
1112 : else
1113 0 : reg->I16_reg.x_reg = dec_word(emu, reg->I16_reg.x_reg);
1114 0 : }
1115 :
1116 : static void
1117 0 : common_binop_byte_rm_r(struct x86emu *emu,
1118 : uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
1119 : {
1120 : uint32_t destoffset;
1121 : uint8_t *destreg, srcval;
1122 : uint8_t destval;
1123 :
1124 0 : fetch_decode_modrm(emu);
1125 0 : srcval = *decode_rh_byte_register(emu);
1126 0 : if (emu->cur_mod != 3) {
1127 0 : destoffset = decode_rl_address(emu);
1128 0 : destval = fetch_data_byte(emu, destoffset);
1129 0 : destval = (*binop)(emu, destval, srcval);
1130 0 : store_data_byte(emu, destoffset, destval);
1131 0 : } else {
1132 0 : destreg = decode_rl_byte_register(emu);
1133 0 : *destreg = (*binop)(emu, *destreg, srcval);
1134 : }
1135 0 : }
1136 :
1137 : static void
1138 0 : common_binop_ns_byte_rm_r(struct x86emu *emu,
1139 : void (*binop)(struct x86emu *, uint8_t, uint8_t))
1140 : {
1141 : uint32_t destoffset;
1142 : uint8_t destval, srcval;
1143 :
1144 0 : fetch_decode_modrm(emu);
1145 0 : srcval = *decode_rh_byte_register(emu);
1146 0 : if (emu->cur_mod != 3) {
1147 0 : destoffset = decode_rl_address(emu);
1148 0 : destval = fetch_data_byte(emu, destoffset);
1149 0 : } else {
1150 0 : destval = *decode_rl_byte_register(emu);
1151 : }
1152 0 : (*binop)(emu, destval, srcval);
1153 0 : }
1154 :
1155 : static void
1156 0 : common_binop_word_rm_r(struct x86emu *emu,
1157 : uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t))
1158 : {
1159 : uint32_t destoffset;
1160 : uint16_t destval, *destreg, srcval;
1161 :
1162 0 : fetch_decode_modrm(emu);
1163 0 : srcval = *decode_rh_word_register(emu);
1164 0 : if (emu->cur_mod != 3) {
1165 0 : destoffset = decode_rl_address(emu);
1166 0 : destval = fetch_data_word(emu, destoffset);
1167 0 : destval = (*binop)(emu, destval, srcval);
1168 0 : store_data_word(emu, destoffset, destval);
1169 0 : } else {
1170 0 : destreg = decode_rl_word_register(emu);
1171 0 : *destreg = (*binop)(emu, *destreg, srcval);
1172 : }
1173 0 : }
1174 :
1175 : static void
1176 0 : common_binop_byte_r_rm(struct x86emu *emu,
1177 : uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
1178 : {
1179 : uint8_t *destreg, srcval;
1180 : uint32_t srcoffset;
1181 :
1182 0 : fetch_decode_modrm(emu);
1183 0 : destreg = decode_rh_byte_register(emu);
1184 0 : if (emu->cur_mod != 3) {
1185 0 : srcoffset = decode_rl_address(emu);
1186 0 : srcval = fetch_data_byte(emu, srcoffset);
1187 0 : } else {
1188 0 : srcval = *decode_rl_byte_register(emu);
1189 : }
1190 0 : *destreg = (*binop)(emu, *destreg, srcval);
1191 0 : }
1192 :
1193 : static void
1194 0 : common_binop_long_rm_r(struct x86emu *emu,
1195 : uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t))
1196 : {
1197 : uint32_t destoffset;
1198 : uint32_t destval, *destreg, srcval;
1199 :
1200 0 : fetch_decode_modrm(emu);
1201 0 : srcval = *decode_rh_long_register(emu);
1202 0 : if (emu->cur_mod != 3) {
1203 0 : destoffset = decode_rl_address(emu);
1204 0 : destval = fetch_data_long(emu, destoffset);
1205 0 : destval = (*binop)(emu, destval, srcval);
1206 0 : store_data_long(emu, destoffset, destval);
1207 0 : } else {
1208 0 : destreg = decode_rl_long_register(emu);
1209 0 : *destreg = (*binop)(emu, *destreg, srcval);
1210 : }
1211 0 : }
1212 :
1213 : static void
1214 0 : common_binop_word_long_rm_r(struct x86emu *emu,
1215 : uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t),
1216 : uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
1217 : {
1218 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1219 0 : common_binop_long_rm_r(emu, binop32);
1220 : else
1221 0 : common_binop_word_rm_r(emu, binop16);
1222 0 : }
1223 :
1224 : static void
1225 0 : common_binop_ns_word_rm_r(struct x86emu *emu,
1226 : void (*binop)(struct x86emu *, uint16_t, uint16_t))
1227 : {
1228 : uint32_t destoffset;
1229 : uint16_t destval, srcval;
1230 :
1231 0 : fetch_decode_modrm(emu);
1232 0 : srcval = *decode_rh_word_register(emu);
1233 0 : if (emu->cur_mod != 3) {
1234 0 : destoffset = decode_rl_address(emu);
1235 0 : destval = fetch_data_word(emu, destoffset);
1236 0 : } else {
1237 0 : destval = *decode_rl_word_register(emu);
1238 : }
1239 0 : (*binop)(emu, destval, srcval);
1240 0 : }
1241 :
1242 :
1243 : static void
1244 0 : common_binop_ns_long_rm_r(struct x86emu *emu,
1245 : void (*binop)(struct x86emu *, uint32_t, uint32_t))
1246 : {
1247 : uint32_t destoffset;
1248 : uint32_t destval, srcval;
1249 :
1250 0 : fetch_decode_modrm(emu);
1251 0 : srcval = *decode_rh_long_register(emu);
1252 0 : if (emu->cur_mod != 3) {
1253 0 : destoffset = decode_rl_address(emu);
1254 0 : destval = fetch_data_long(emu, destoffset);
1255 0 : } else {
1256 0 : destval = *decode_rl_long_register(emu);
1257 : }
1258 0 : (*binop)(emu, destval, srcval);
1259 0 : }
1260 :
1261 : static void
1262 0 : common_binop_ns_word_long_rm_r(struct x86emu *emu,
1263 : void (*binop16)(struct x86emu *, uint16_t, uint16_t),
1264 : void (*binop32)(struct x86emu *, uint32_t, uint32_t))
1265 : {
1266 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1267 0 : common_binop_ns_long_rm_r(emu, binop32);
1268 : else
1269 0 : common_binop_ns_word_rm_r(emu, binop16);
1270 0 : }
1271 :
1272 : static void
1273 0 : common_binop_long_r_rm(struct x86emu *emu,
1274 : uint32_t (*binop)(struct x86emu *, uint32_t, uint32_t))
1275 : {
1276 : uint32_t srcoffset;
1277 : uint32_t *destreg, srcval;
1278 :
1279 0 : fetch_decode_modrm(emu);
1280 0 : destreg = decode_rh_long_register(emu);
1281 0 : if (emu->cur_mod != 3) {
1282 0 : srcoffset = decode_rl_address(emu);
1283 0 : srcval = fetch_data_long(emu, srcoffset);
1284 0 : } else {
1285 0 : srcval = *decode_rl_long_register(emu);
1286 : }
1287 0 : *destreg = (*binop)(emu, *destreg, srcval);
1288 0 : }
1289 :
1290 : static void
1291 0 : common_binop_word_r_rm(struct x86emu *emu,
1292 : uint16_t (*binop)(struct x86emu *, uint16_t, uint16_t))
1293 : {
1294 : uint32_t srcoffset;
1295 : uint16_t *destreg, srcval;
1296 :
1297 0 : fetch_decode_modrm(emu);
1298 0 : destreg = decode_rh_word_register(emu);
1299 0 : if (emu->cur_mod != 3) {
1300 0 : srcoffset = decode_rl_address(emu);
1301 0 : srcval = fetch_data_word(emu, srcoffset);
1302 0 : } else {
1303 0 : srcval = *decode_rl_word_register(emu);
1304 : }
1305 0 : *destreg = (*binop)(emu, *destreg, srcval);
1306 0 : }
1307 :
1308 : static void
1309 0 : common_binop_word_long_r_rm(struct x86emu *emu,
1310 : uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t),
1311 : uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
1312 : {
1313 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1314 0 : common_binop_long_r_rm(emu, binop32);
1315 : else
1316 0 : common_binop_word_r_rm(emu, binop16);
1317 0 : }
1318 :
1319 : static void
1320 0 : common_binop_byte_imm(struct x86emu *emu,
1321 : uint8_t (*binop)(struct x86emu *, uint8_t, uint8_t))
1322 : {
1323 : uint8_t srcval;
1324 :
1325 0 : srcval = fetch_byte_imm(emu);
1326 0 : emu->x86.R_AL = (*binop)(emu, emu->x86.R_AL, srcval);
1327 0 : }
1328 :
1329 : static void
1330 0 : common_binop_word_long_imm(struct x86emu *emu,
1331 : uint16_t (*binop16)(struct x86emu *, uint16_t, uint16_t),
1332 : uint32_t (*binop32)(struct x86emu *, uint32_t, uint32_t))
1333 : {
1334 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1335 : uint32_t srcval;
1336 :
1337 0 : srcval = fetch_long_imm(emu);
1338 0 : emu->x86.R_EAX = (*binop32)(emu, emu->x86.R_EAX, srcval);
1339 0 : } else {
1340 : uint16_t srcval;
1341 :
1342 0 : srcval = fetch_word_imm(emu);
1343 0 : emu->x86.R_AX = (*binop16)(emu, emu->x86.R_AX, srcval);
1344 : }
1345 0 : }
1346 :
1347 : static void
1348 0 : common_push_word_long(struct x86emu *emu, union x86emu_register *reg)
1349 : {
1350 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1351 0 : push_long(emu, reg->I32_reg.e_reg);
1352 : else
1353 0 : push_word(emu, reg->I16_reg.x_reg);
1354 0 : }
1355 :
1356 : static void
1357 0 : common_pop_word_long(struct x86emu *emu, union x86emu_register *reg)
1358 : {
1359 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1360 0 : reg->I32_reg.e_reg = pop_long(emu);
1361 : else
1362 0 : reg->I16_reg.x_reg = pop_word(emu);
1363 0 : }
1364 :
1365 : static void
1366 0 : common_imul_long_IMM(struct x86emu *emu, int byte_imm)
1367 : {
1368 : uint32_t srcoffset;
1369 : uint32_t *destreg, srcval;
1370 : int32_t imm;
1371 : uint64_t res;
1372 :
1373 0 : fetch_decode_modrm(emu);
1374 0 : destreg = decode_rh_long_register(emu);
1375 0 : if (emu->cur_mod != 3) {
1376 0 : srcoffset = decode_rl_address(emu);
1377 0 : srcval = fetch_data_long(emu, srcoffset);
1378 0 : } else {
1379 0 : srcval = *decode_rl_long_register(emu);
1380 : }
1381 :
1382 0 : if (byte_imm)
1383 0 : imm = (int8_t)fetch_byte_imm(emu);
1384 : else
1385 0 : imm = fetch_long_imm(emu);
1386 0 : res = (int32_t)srcval * imm;
1387 :
1388 0 : if (res > 0xffffffff) {
1389 0 : SET_FLAG(F_CF);
1390 0 : SET_FLAG(F_OF);
1391 0 : } else {
1392 0 : CLEAR_FLAG(F_CF);
1393 0 : CLEAR_FLAG(F_OF);
1394 : }
1395 0 : *destreg = (uint32_t)res;
1396 0 : }
1397 :
1398 : static void
1399 0 : common_imul_word_IMM(struct x86emu *emu, int byte_imm)
1400 : {
1401 : uint32_t srcoffset;
1402 : uint16_t *destreg, srcval;
1403 : int16_t imm;
1404 : uint32_t res;
1405 :
1406 0 : fetch_decode_modrm(emu);
1407 0 : destreg = decode_rh_word_register(emu);
1408 0 : if (emu->cur_mod != 3) {
1409 0 : srcoffset = decode_rl_address(emu);
1410 0 : srcval = fetch_data_word(emu, srcoffset);
1411 0 : } else {
1412 0 : srcval = *decode_rl_word_register(emu);
1413 : }
1414 :
1415 0 : if (byte_imm)
1416 0 : imm = (int8_t)fetch_byte_imm(emu);
1417 : else
1418 0 : imm = fetch_word_imm(emu);
1419 0 : res = (int16_t)srcval * imm;
1420 :
1421 0 : if (res > 0xffff) {
1422 0 : SET_FLAG(F_CF);
1423 0 : SET_FLAG(F_OF);
1424 0 : } else {
1425 0 : CLEAR_FLAG(F_CF);
1426 0 : CLEAR_FLAG(F_OF);
1427 : }
1428 0 : *destreg = (uint16_t) res;
1429 0 : }
1430 :
1431 : static void
1432 0 : common_imul_imm(struct x86emu *emu, int byte_imm)
1433 : {
1434 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1435 0 : common_imul_long_IMM(emu, byte_imm);
1436 : else
1437 0 : common_imul_word_IMM(emu, byte_imm);
1438 0 : }
1439 :
1440 : static void
1441 0 : common_jmp_near(struct x86emu *emu, int cond)
1442 : {
1443 : int8_t offset;
1444 : uint16_t target;
1445 :
1446 0 : offset = (int8_t) fetch_byte_imm(emu);
1447 0 : target = (uint16_t) (emu->x86.R_IP + (int16_t) offset);
1448 0 : if (cond)
1449 0 : emu->x86.R_IP = target;
1450 0 : }
1451 :
1452 : static void
1453 0 : common_load_far_pointer(struct x86emu *emu, uint16_t *seg)
1454 : {
1455 : uint16_t *dstreg;
1456 : uint32_t srcoffset;
1457 :
1458 0 : fetch_decode_modrm(emu);
1459 0 : if (emu->cur_mod == 3)
1460 0 : x86emu_halt_sys(emu);
1461 :
1462 0 : dstreg = decode_rh_word_register(emu);
1463 0 : srcoffset = decode_rl_address(emu);
1464 0 : *dstreg = fetch_data_word(emu, srcoffset);
1465 0 : *seg = fetch_data_word(emu, srcoffset + 2);
1466 0 : }
1467 :
1468 : /* Implementation */
1469 :
1470 : /*
1471 : * REMARKS:
1472 : * Handles opcode 0x3a
1473 : */
1474 : static void
1475 0 : x86emuOp_cmp_byte_R_RM(struct x86emu *emu)
1476 : {
1477 : uint8_t *destreg, srcval;
1478 :
1479 0 : fetch_decode_modrm(emu);
1480 0 : destreg = decode_rh_byte_register(emu);
1481 0 : srcval = decode_and_fetch_byte(emu);
1482 0 : cmp_byte(emu, *destreg, srcval);
1483 0 : }
1484 :
1485 : /*
1486 : * REMARKS:
1487 : *
1488 : * Handles opcode 0x3b
1489 : */
1490 : static void
1491 0 : x86emuOp32_cmp_word_R_RM(struct x86emu *emu)
1492 : {
1493 : uint32_t srcval, *destreg;
1494 :
1495 0 : fetch_decode_modrm(emu);
1496 0 : destreg = decode_rh_long_register(emu);
1497 0 : srcval = decode_and_fetch_long(emu);
1498 0 : cmp_long(emu, *destreg, srcval);
1499 0 : }
1500 :
1501 : static void
1502 0 : x86emuOp16_cmp_word_R_RM(struct x86emu *emu)
1503 : {
1504 : uint16_t srcval, *destreg;
1505 :
1506 0 : fetch_decode_modrm(emu);
1507 0 : destreg = decode_rh_word_register(emu);
1508 0 : srcval = decode_and_fetch_word(emu);
1509 0 : cmp_word(emu, *destreg, srcval);
1510 0 : }
1511 :
1512 : static void
1513 0 : x86emuOp_cmp_word_R_RM(struct x86emu *emu)
1514 : {
1515 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1516 0 : x86emuOp32_cmp_word_R_RM(emu);
1517 : else
1518 0 : x86emuOp16_cmp_word_R_RM(emu);
1519 0 : }
1520 :
1521 : /*
1522 : * REMARKS:
1523 : * Handles opcode 0x3c
1524 : */
1525 : static void
1526 0 : x86emuOp_cmp_byte_AL_IMM(struct x86emu *emu)
1527 : {
1528 : uint8_t srcval;
1529 :
1530 0 : srcval = fetch_byte_imm(emu);
1531 0 : cmp_byte(emu, emu->x86.R_AL, srcval);
1532 0 : }
1533 :
1534 : /*
1535 : * REMARKS:
1536 : * Handles opcode 0x3d
1537 : */
1538 : static void
1539 0 : x86emuOp32_cmp_word_AX_IMM(struct x86emu *emu)
1540 : {
1541 : uint32_t srcval;
1542 :
1543 0 : srcval = fetch_long_imm(emu);
1544 0 : cmp_long(emu, emu->x86.R_EAX, srcval);
1545 0 : }
1546 :
1547 : static void
1548 0 : x86emuOp16_cmp_word_AX_IMM(struct x86emu *emu)
1549 : {
1550 : uint16_t srcval;
1551 :
1552 0 : srcval = fetch_word_imm(emu);
1553 0 : cmp_word(emu, emu->x86.R_AX, srcval);
1554 0 : }
1555 :
1556 : static void
1557 0 : x86emuOp_cmp_word_AX_IMM(struct x86emu *emu)
1558 : {
1559 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1560 0 : x86emuOp32_cmp_word_AX_IMM(emu);
1561 : else
1562 0 : x86emuOp16_cmp_word_AX_IMM(emu);
1563 0 : }
1564 :
1565 : /*
1566 : * REMARKS:
1567 : * Handles opcode 0x60
1568 : */
1569 : static void
1570 0 : x86emuOp_push_all(struct x86emu *emu)
1571 : {
1572 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1573 0 : uint32_t old_sp = emu->x86.R_ESP;
1574 :
1575 0 : push_long(emu, emu->x86.R_EAX);
1576 0 : push_long(emu, emu->x86.R_ECX);
1577 0 : push_long(emu, emu->x86.R_EDX);
1578 0 : push_long(emu, emu->x86.R_EBX);
1579 0 : push_long(emu, old_sp);
1580 0 : push_long(emu, emu->x86.R_EBP);
1581 0 : push_long(emu, emu->x86.R_ESI);
1582 0 : push_long(emu, emu->x86.R_EDI);
1583 0 : } else {
1584 0 : uint16_t old_sp = emu->x86.R_SP;
1585 :
1586 0 : push_word(emu, emu->x86.R_AX);
1587 0 : push_word(emu, emu->x86.R_CX);
1588 0 : push_word(emu, emu->x86.R_DX);
1589 0 : push_word(emu, emu->x86.R_BX);
1590 0 : push_word(emu, old_sp);
1591 0 : push_word(emu, emu->x86.R_BP);
1592 0 : push_word(emu, emu->x86.R_SI);
1593 0 : push_word(emu, emu->x86.R_DI);
1594 : }
1595 0 : }
1596 :
1597 : /*
1598 : * REMARKS:
1599 : * Handles opcode 0x61
1600 : */
1601 : static void
1602 0 : x86emuOp_pop_all(struct x86emu *emu)
1603 : {
1604 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1605 0 : emu->x86.R_EDI = pop_long(emu);
1606 0 : emu->x86.R_ESI = pop_long(emu);
1607 0 : emu->x86.R_EBP = pop_long(emu);
1608 0 : emu->x86.R_ESP += 4; /* skip ESP */
1609 0 : emu->x86.R_EBX = pop_long(emu);
1610 0 : emu->x86.R_EDX = pop_long(emu);
1611 0 : emu->x86.R_ECX = pop_long(emu);
1612 0 : emu->x86.R_EAX = pop_long(emu);
1613 0 : } else {
1614 0 : emu->x86.R_DI = pop_word(emu);
1615 0 : emu->x86.R_SI = pop_word(emu);
1616 0 : emu->x86.R_BP = pop_word(emu);
1617 0 : emu->x86.R_SP += 2;/* skip SP */
1618 0 : emu->x86.R_BX = pop_word(emu);
1619 0 : emu->x86.R_DX = pop_word(emu);
1620 0 : emu->x86.R_CX = pop_word(emu);
1621 0 : emu->x86.R_AX = pop_word(emu);
1622 : }
1623 0 : }
1624 : /*opcode 0x62 ILLEGAL OP, calls x86emuOp_illegal_op() */
1625 : /*opcode 0x63 ILLEGAL OP, calls x86emuOp_illegal_op() */
1626 :
1627 :
1628 : /*
1629 : * REMARKS:
1630 : * Handles opcode 0x68
1631 : */
1632 : static void
1633 0 : x86emuOp_push_word_IMM(struct x86emu *emu)
1634 : {
1635 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1636 : uint32_t imm;
1637 :
1638 0 : imm = fetch_long_imm(emu);
1639 0 : push_long(emu, imm);
1640 0 : } else {
1641 : uint16_t imm;
1642 :
1643 0 : imm = fetch_word_imm(emu);
1644 0 : push_word(emu, imm);
1645 : }
1646 0 : }
1647 :
1648 : /*
1649 : * REMARKS:
1650 : * Handles opcode 0x6a
1651 : */
1652 : static void
1653 0 : x86emuOp_push_byte_IMM(struct x86emu *emu)
1654 : {
1655 : int16_t imm;
1656 :
1657 0 : imm = (int8_t) fetch_byte_imm(emu);
1658 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1659 0 : push_long(emu, (int32_t) imm);
1660 0 : } else {
1661 0 : push_word(emu, imm);
1662 : }
1663 0 : }
1664 :
1665 : /*
1666 : * REMARKS:
1667 : * Handles opcode 0x6c and 0x6d
1668 : */
1669 : static void
1670 0 : x86emuOp_ins_word(struct x86emu *emu)
1671 : {
1672 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1673 0 : ins(emu, 4);
1674 0 : } else {
1675 0 : ins(emu, 2);
1676 : }
1677 0 : }
1678 :
1679 : /*
1680 : * REMARKS:
1681 : * Handles opcode 0x6f
1682 : */
1683 : static void
1684 0 : x86emuOp_outs_word(struct x86emu *emu)
1685 : {
1686 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
1687 0 : outs(emu, 4);
1688 0 : } else {
1689 0 : outs(emu, 2);
1690 : }
1691 0 : }
1692 :
1693 : /*
1694 : * REMARKS:
1695 : * Handles opcode 0x7c
1696 : */
1697 : static void
1698 0 : x86emuOp_jump_near_L(struct x86emu *emu)
1699 : {
1700 : int sf, of;
1701 :
1702 0 : sf = ACCESS_FLAG(F_SF) != 0;
1703 0 : of = ACCESS_FLAG(F_OF) != 0;
1704 :
1705 0 : common_jmp_near(emu, sf != of);
1706 0 : }
1707 :
1708 : /*
1709 : * REMARKS:
1710 : * Handles opcode 0x7d
1711 : */
1712 : static void
1713 0 : x86emuOp_jump_near_NL(struct x86emu *emu)
1714 : {
1715 : int sf, of;
1716 :
1717 0 : sf = ACCESS_FLAG(F_SF) != 0;
1718 0 : of = ACCESS_FLAG(F_OF) != 0;
1719 :
1720 0 : common_jmp_near(emu, sf == of);
1721 0 : }
1722 :
1723 : /*
1724 : * REMARKS:
1725 : * Handles opcode 0x7e
1726 : */
1727 : static void
1728 0 : x86emuOp_jump_near_LE(struct x86emu *emu)
1729 : {
1730 : int sf, of;
1731 :
1732 0 : sf = ACCESS_FLAG(F_SF) != 0;
1733 0 : of = ACCESS_FLAG(F_OF) != 0;
1734 :
1735 0 : common_jmp_near(emu, sf != of || ACCESS_FLAG(F_ZF));
1736 0 : }
1737 :
1738 : /*
1739 : * REMARKS:
1740 : * Handles opcode 0x7f
1741 : */
1742 : static void
1743 0 : x86emuOp_jump_near_NLE(struct x86emu *emu)
1744 : {
1745 : int sf, of;
1746 :
1747 0 : sf = ACCESS_FLAG(F_SF) != 0;
1748 0 : of = ACCESS_FLAG(F_OF) != 0;
1749 :
1750 0 : common_jmp_near(emu, sf == of && !ACCESS_FLAG(F_ZF));
1751 0 : }
1752 :
1753 : static
1754 : uint8_t(*const opc80_byte_operation[]) (struct x86emu *, uint8_t d, uint8_t s) =
1755 : {
1756 : add_byte, /* 00 */
1757 : or_byte, /* 01 */
1758 : adc_byte, /* 02 */
1759 : sbb_byte, /* 03 */
1760 : and_byte, /* 04 */
1761 : sub_byte, /* 05 */
1762 : xor_byte, /* 06 */
1763 : cmp_byte, /* 07 */
1764 : };
1765 :
1766 : /*
1767 : * REMARKS:
1768 : * Handles opcode 0x80
1769 : */
1770 : static void
1771 0 : x86emuOp_opc80_byte_RM_IMM(struct x86emu *emu)
1772 : {
1773 : uint8_t imm, destval;
1774 :
1775 : /*
1776 : * Weirdo special case instruction format. Part of the opcode
1777 : * held below in "RH". Doubly nested case would result, except
1778 : * that the decoded instruction
1779 : */
1780 0 : fetch_decode_modrm(emu);
1781 0 : destval = decode_and_fetch_byte(emu);
1782 0 : imm = fetch_byte_imm(emu);
1783 0 : destval = (*opc80_byte_operation[emu->cur_rh]) (emu, destval, imm);
1784 0 : if (emu->cur_rh != 7)
1785 0 : write_back_byte(emu, destval);
1786 0 : }
1787 :
1788 : static
1789 : uint16_t(* const opc81_word_operation[])
1790 : (struct x86emu *, uint16_t d, uint16_t s) =
1791 : {
1792 : add_word, /* 00 */
1793 : or_word, /* 01 */
1794 : adc_word, /* 02 */
1795 : sbb_word, /* 03 */
1796 : and_word, /* 04 */
1797 : sub_word, /* 05 */
1798 : xor_word, /* 06 */
1799 : cmp_word, /* 07 */
1800 : };
1801 :
1802 : static
1803 : uint32_t(* const opc81_long_operation[])
1804 : (struct x86emu *, uint32_t d, uint32_t s) =
1805 : {
1806 : add_long, /* 00 */
1807 : or_long, /* 01 */
1808 : adc_long, /* 02 */
1809 : sbb_long, /* 03 */
1810 : and_long, /* 04 */
1811 : sub_long, /* 05 */
1812 : xor_long, /* 06 */
1813 : cmp_long, /* 07 */
1814 : };
1815 :
1816 : /*
1817 : * REMARKS:
1818 : * Handles opcode 0x81
1819 : */
1820 : static void
1821 0 : x86emuOp32_opc81_word_RM_IMM(struct x86emu *emu)
1822 : {
1823 : uint32_t destval, imm;
1824 :
1825 : /*
1826 : * Weirdo special case instruction format. Part of the opcode
1827 : * held below in "RH". Doubly nested case would result, except
1828 : * that the decoded instruction
1829 : */
1830 0 : fetch_decode_modrm(emu);
1831 0 : destval = decode_and_fetch_long(emu);
1832 0 : imm = fetch_long_imm(emu);
1833 0 : destval = (*opc81_long_operation[emu->cur_rh]) (emu, destval, imm);
1834 0 : if (emu->cur_rh != 7)
1835 0 : write_back_long(emu, destval);
1836 0 : }
1837 :
1838 : static void
1839 0 : x86emuOp16_opc81_word_RM_IMM(struct x86emu *emu)
1840 : {
1841 : uint16_t destval, imm;
1842 :
1843 : /*
1844 : * Weirdo special case instruction format. Part of the opcode
1845 : * held below in "RH". Doubly nested case would result, except
1846 : * that the decoded instruction
1847 : */
1848 0 : fetch_decode_modrm(emu);
1849 0 : destval = decode_and_fetch_word(emu);
1850 0 : imm = fetch_word_imm(emu);
1851 0 : destval = (*opc81_word_operation[emu->cur_rh]) (emu, destval, imm);
1852 0 : if (emu->cur_rh != 7)
1853 0 : write_back_word(emu, destval);
1854 0 : }
1855 :
1856 : static void
1857 0 : x86emuOp_opc81_word_RM_IMM(struct x86emu *emu)
1858 : {
1859 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1860 0 : x86emuOp32_opc81_word_RM_IMM(emu);
1861 : else
1862 0 : x86emuOp16_opc81_word_RM_IMM(emu);
1863 0 : }
1864 :
1865 : static
1866 : uint8_t(* const opc82_byte_operation[])
1867 : (struct x86emu *, uint8_t s, uint8_t d) =
1868 : {
1869 : add_byte, /* 00 */
1870 : or_byte, /* 01 *//* YYY UNUSED ???? */
1871 : adc_byte, /* 02 */
1872 : sbb_byte, /* 03 */
1873 : and_byte, /* 04 *//* YYY UNUSED ???? */
1874 : sub_byte, /* 05 */
1875 : xor_byte, /* 06 *//* YYY UNUSED ???? */
1876 : cmp_byte, /* 07 */
1877 : };
1878 :
1879 : /*
1880 : * REMARKS:
1881 : * Handles opcode 0x82
1882 : */
1883 : static void
1884 0 : x86emuOp_opc82_byte_RM_IMM(struct x86emu *emu)
1885 : {
1886 : uint8_t imm, destval;
1887 :
1888 : /*
1889 : * Weirdo special case instruction format. Part of the opcode
1890 : * held below in "RH". Doubly nested case would result, except
1891 : * that the decoded instruction Similar to opcode 81, except that
1892 : * the immediate byte is sign extended to a word length.
1893 : */
1894 0 : fetch_decode_modrm(emu);
1895 0 : destval = decode_and_fetch_byte(emu);
1896 0 : imm = fetch_byte_imm(emu);
1897 0 : destval = (*opc82_byte_operation[emu->cur_rh]) (emu, destval, imm);
1898 0 : if (emu->cur_rh != 7)
1899 0 : write_back_byte(emu, destval);
1900 0 : }
1901 :
1902 : static
1903 : uint16_t(* const opc83_word_operation[])
1904 : (struct x86emu *, uint16_t s, uint16_t d) =
1905 : {
1906 : add_word, /* 00 */
1907 : or_word, /* 01 *//* YYY UNUSED ???? */
1908 : adc_word, /* 02 */
1909 : sbb_word, /* 03 */
1910 : and_word, /* 04 *//* YYY UNUSED ???? */
1911 : sub_word, /* 05 */
1912 : xor_word, /* 06 *//* YYY UNUSED ???? */
1913 : cmp_word, /* 07 */
1914 : };
1915 :
1916 : static
1917 : uint32_t(* const opc83_long_operation[])
1918 : (struct x86emu *, uint32_t s, uint32_t d) =
1919 : {
1920 : add_long, /* 00 */
1921 : or_long, /* 01 *//* YYY UNUSED ???? */
1922 : adc_long, /* 02 */
1923 : sbb_long, /* 03 */
1924 : and_long, /* 04 *//* YYY UNUSED ???? */
1925 : sub_long, /* 05 */
1926 : xor_long, /* 06 *//* YYY UNUSED ???? */
1927 : cmp_long, /* 07 */
1928 : };
1929 :
1930 : /*
1931 : * REMARKS:
1932 : * Handles opcode 0x83
1933 : */
1934 : static void
1935 0 : x86emuOp32_opc83_word_RM_IMM(struct x86emu *emu)
1936 : {
1937 : uint32_t destval, imm;
1938 :
1939 0 : fetch_decode_modrm(emu);
1940 0 : destval = decode_and_fetch_long(emu);
1941 0 : imm = (int8_t) fetch_byte_imm(emu);
1942 0 : destval = (*opc83_long_operation[emu->cur_rh]) (emu, destval, imm);
1943 0 : if (emu->cur_rh != 7)
1944 0 : write_back_long(emu, destval);
1945 0 : }
1946 :
1947 : static void
1948 0 : x86emuOp16_opc83_word_RM_IMM(struct x86emu *emu)
1949 : {
1950 : uint16_t destval, imm;
1951 :
1952 0 : fetch_decode_modrm(emu);
1953 0 : destval = decode_and_fetch_word(emu);
1954 0 : imm = (int8_t) fetch_byte_imm(emu);
1955 0 : destval = (*opc83_word_operation[emu->cur_rh]) (emu, destval, imm);
1956 0 : if (emu->cur_rh != 7)
1957 0 : write_back_word(emu, destval);
1958 0 : }
1959 :
1960 : static void
1961 0 : x86emuOp_opc83_word_RM_IMM(struct x86emu *emu)
1962 : {
1963 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
1964 0 : x86emuOp32_opc83_word_RM_IMM(emu);
1965 : else
1966 0 : x86emuOp16_opc83_word_RM_IMM(emu);
1967 0 : }
1968 :
1969 : /*
1970 : * REMARKS:
1971 : * Handles opcode 0x86
1972 : */
1973 : static void
1974 0 : x86emuOp_xchg_byte_RM_R(struct x86emu *emu)
1975 : {
1976 : uint8_t *srcreg, destval, tmp;
1977 :
1978 0 : fetch_decode_modrm(emu);
1979 0 : destval = decode_and_fetch_byte(emu);
1980 0 : srcreg = decode_rh_byte_register(emu);
1981 : tmp = destval;
1982 0 : destval = *srcreg;
1983 0 : *srcreg = tmp;
1984 0 : write_back_byte(emu, destval);
1985 0 : }
1986 :
1987 : /*
1988 : * REMARKS:
1989 : * Handles opcode 0x87
1990 : */
1991 : static void
1992 0 : x86emuOp32_xchg_word_RM_R(struct x86emu *emu)
1993 : {
1994 : uint32_t *srcreg, destval, tmp;
1995 :
1996 0 : fetch_decode_modrm(emu);
1997 0 : destval = decode_and_fetch_long(emu);
1998 0 : srcreg = decode_rh_long_register(emu);
1999 : tmp = destval;
2000 0 : destval = *srcreg;
2001 0 : *srcreg = tmp;
2002 0 : write_back_long(emu, destval);
2003 0 : }
2004 :
2005 : static void
2006 0 : x86emuOp16_xchg_word_RM_R(struct x86emu *emu)
2007 : {
2008 : uint16_t *srcreg, destval, tmp;
2009 :
2010 0 : fetch_decode_modrm(emu);
2011 0 : destval = decode_and_fetch_word(emu);
2012 0 : srcreg = decode_rh_word_register(emu);
2013 : tmp = destval;
2014 0 : destval = *srcreg;
2015 0 : *srcreg = tmp;
2016 0 : write_back_word(emu, destval);
2017 0 : }
2018 :
2019 : static void
2020 0 : x86emuOp_xchg_word_RM_R(struct x86emu *emu)
2021 : {
2022 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2023 0 : x86emuOp32_xchg_word_RM_R(emu);
2024 : else
2025 0 : x86emuOp16_xchg_word_RM_R(emu);
2026 0 : }
2027 :
2028 : /*
2029 : * REMARKS:
2030 : * Handles opcode 0x88
2031 : */
2032 : static void
2033 0 : x86emuOp_mov_byte_RM_R(struct x86emu *emu)
2034 : {
2035 : uint8_t *destreg, *srcreg;
2036 : uint32_t destoffset;
2037 :
2038 0 : fetch_decode_modrm(emu);
2039 0 : srcreg = decode_rh_byte_register(emu);
2040 0 : if (emu->cur_mod != 3) {
2041 0 : destoffset = decode_rl_address(emu);
2042 0 : store_data_byte(emu, destoffset, *srcreg);
2043 0 : } else {
2044 0 : destreg = decode_rl_byte_register(emu);
2045 0 : *destreg = *srcreg;
2046 : }
2047 0 : }
2048 :
2049 : /*
2050 : * REMARKS:
2051 : * Handles opcode 0x89
2052 : */
2053 : static void
2054 0 : x86emuOp32_mov_word_RM_R(struct x86emu *emu)
2055 : {
2056 : uint32_t destoffset;
2057 : uint32_t *destreg, srcval;
2058 :
2059 0 : fetch_decode_modrm(emu);
2060 0 : srcval = *decode_rh_long_register(emu);
2061 0 : if (emu->cur_mod != 3) {
2062 0 : destoffset = decode_rl_address(emu);
2063 0 : store_data_long(emu, destoffset, srcval);
2064 0 : } else {
2065 0 : destreg = decode_rl_long_register(emu);
2066 0 : *destreg = srcval;
2067 : }
2068 0 : }
2069 :
2070 : static void
2071 0 : x86emuOp16_mov_word_RM_R(struct x86emu *emu)
2072 : {
2073 : uint32_t destoffset;
2074 : uint16_t *destreg, srcval;
2075 :
2076 0 : fetch_decode_modrm(emu);
2077 0 : srcval = *decode_rh_word_register(emu);
2078 0 : if (emu->cur_mod != 3) {
2079 0 : destoffset = decode_rl_address(emu);
2080 0 : store_data_word(emu, destoffset, srcval);
2081 0 : } else {
2082 0 : destreg = decode_rl_word_register(emu);
2083 0 : *destreg = srcval;
2084 : }
2085 0 : }
2086 :
2087 : static void
2088 0 : x86emuOp_mov_word_RM_R(struct x86emu *emu)
2089 : {
2090 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2091 0 : x86emuOp32_mov_word_RM_R(emu);
2092 : else
2093 0 : x86emuOp16_mov_word_RM_R(emu);
2094 0 : }
2095 :
2096 : /*
2097 : * REMARKS:
2098 : * Handles opcode 0x8a
2099 : */
2100 : static void
2101 0 : x86emuOp_mov_byte_R_RM(struct x86emu *emu)
2102 : {
2103 : uint8_t *destreg;
2104 :
2105 0 : fetch_decode_modrm(emu);
2106 0 : destreg = decode_rh_byte_register(emu);
2107 0 : *destreg = decode_and_fetch_byte(emu);
2108 0 : }
2109 :
2110 : /*
2111 : * REMARKS:
2112 : * Handles opcode 0x8b
2113 : */
2114 : static void
2115 0 : x86emuOp_mov_word_R_RM(struct x86emu *emu)
2116 : {
2117 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2118 : uint32_t *destreg;
2119 :
2120 0 : fetch_decode_modrm(emu);
2121 0 : destreg = decode_rh_long_register(emu);
2122 0 : *destreg = decode_and_fetch_long(emu);
2123 0 : } else {
2124 : uint16_t *destreg;
2125 :
2126 0 : fetch_decode_modrm(emu);
2127 0 : destreg = decode_rh_word_register(emu);
2128 0 : *destreg = decode_and_fetch_word(emu);
2129 : }
2130 0 : }
2131 :
2132 : /*
2133 : * REMARKS:
2134 : * Handles opcode 0x8c
2135 : */
2136 : static void
2137 0 : x86emuOp_mov_word_RM_SR(struct x86emu *emu)
2138 : {
2139 : uint16_t *destreg, srcval;
2140 : uint32_t destoffset;
2141 :
2142 0 : fetch_decode_modrm(emu);
2143 0 : srcval = *decode_rh_seg_register(emu);
2144 0 : if (emu->cur_mod != 3) {
2145 0 : destoffset = decode_rl_address(emu);
2146 0 : store_data_word(emu, destoffset, srcval);
2147 0 : } else {
2148 0 : destreg = decode_rl_word_register(emu);
2149 0 : *destreg = srcval;
2150 : }
2151 0 : }
2152 :
2153 : /*
2154 : * REMARKS:
2155 : * Handles opcode 0x8d
2156 : */
2157 : static void
2158 0 : x86emuOp_lea_word_R_M(struct x86emu *emu)
2159 : {
2160 : uint32_t destoffset;
2161 :
2162 0 : fetch_decode_modrm(emu);
2163 0 : if (emu->cur_mod == 3)
2164 0 : x86emu_halt_sys(emu);
2165 :
2166 0 : destoffset = decode_rl_address(emu);
2167 0 : if (emu->x86.mode & SYSMODE_PREFIX_ADDR) {
2168 : uint32_t *srcreg;
2169 :
2170 0 : srcreg = decode_rh_long_register(emu);
2171 0 : *srcreg = (uint32_t) destoffset;
2172 0 : } else {
2173 : uint16_t *srcreg;
2174 :
2175 0 : srcreg = decode_rh_word_register(emu);
2176 0 : *srcreg = (uint16_t) destoffset;
2177 : }
2178 0 : }
2179 :
2180 : /*
2181 : * REMARKS:
2182 : * Handles opcode 0x8e
2183 : */
2184 : static void
2185 0 : x86emuOp_mov_word_SR_RM(struct x86emu *emu)
2186 : {
2187 : uint16_t *destreg;
2188 :
2189 0 : fetch_decode_modrm(emu);
2190 0 : destreg = decode_rh_seg_register(emu);
2191 0 : *destreg = decode_and_fetch_word(emu);
2192 : /*
2193 : * Clean up, and reset all the R_xSP pointers to the correct
2194 : * locations. This is about 3x too much overhead (doing all the
2195 : * segreg ptrs when only one is needed, but this instruction
2196 : * *cannot* be that common, and this isn't too much work anyway.
2197 : */
2198 0 : }
2199 :
2200 : /*
2201 : * REMARKS:
2202 : * Handles opcode 0x8f
2203 : */
2204 : static void
2205 0 : x86emuOp32_pop_RM(struct x86emu *emu)
2206 : {
2207 : uint32_t destoffset;
2208 : uint32_t destval, *destreg;
2209 :
2210 0 : fetch_decode_modrm(emu);
2211 0 : if (emu->cur_mod != 3) {
2212 0 : destoffset = decode_rl_address(emu);
2213 0 : destval = pop_long(emu);
2214 0 : store_data_long(emu, destoffset, destval);
2215 0 : } else {
2216 0 : destreg = decode_rl_long_register(emu);
2217 0 : *destreg = pop_long(emu);
2218 : }
2219 0 : }
2220 :
2221 : static void
2222 0 : x86emuOp16_pop_RM(struct x86emu *emu)
2223 : {
2224 : uint32_t destoffset;
2225 : uint16_t destval, *destreg;
2226 :
2227 0 : fetch_decode_modrm(emu);
2228 0 : if (emu->cur_mod != 3) {
2229 0 : destoffset = decode_rl_address(emu);
2230 0 : destval = pop_word(emu);
2231 0 : store_data_word(emu, destoffset, destval);
2232 0 : } else {
2233 0 : destreg = decode_rl_word_register(emu);
2234 0 : *destreg = pop_word(emu);
2235 : }
2236 0 : }
2237 :
2238 : static void
2239 0 : x86emuOp_pop_RM(struct x86emu *emu)
2240 : {
2241 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2242 0 : x86emuOp32_pop_RM(emu);
2243 : else
2244 0 : x86emuOp16_pop_RM(emu);
2245 0 : }
2246 :
2247 : /*
2248 : * REMARKS:
2249 : * Handles opcode 0x91
2250 : */
2251 : static void
2252 0 : x86emuOp_xchg_word_AX_CX(struct x86emu *emu)
2253 : {
2254 : uint32_t tmp;
2255 :
2256 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2257 0 : tmp = emu->x86.R_EAX;
2258 0 : emu->x86.R_EAX = emu->x86.R_ECX;
2259 0 : emu->x86.R_ECX = tmp;
2260 0 : } else {
2261 0 : tmp = emu->x86.R_AX;
2262 0 : emu->x86.R_AX = emu->x86.R_CX;
2263 0 : emu->x86.R_CX = (uint16_t) tmp;
2264 : }
2265 0 : }
2266 :
2267 : /*
2268 : * REMARKS:
2269 : * Handles opcode 0x92
2270 : */
2271 : static void
2272 0 : x86emuOp_xchg_word_AX_DX(struct x86emu *emu)
2273 : {
2274 : uint32_t tmp;
2275 :
2276 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2277 0 : tmp = emu->x86.R_EAX;
2278 0 : emu->x86.R_EAX = emu->x86.R_EDX;
2279 0 : emu->x86.R_EDX = tmp;
2280 0 : } else {
2281 0 : tmp = emu->x86.R_AX;
2282 0 : emu->x86.R_AX = emu->x86.R_DX;
2283 0 : emu->x86.R_DX = (uint16_t) tmp;
2284 : }
2285 0 : }
2286 :
2287 : /*
2288 : * REMARKS:
2289 : * Handles opcode 0x93
2290 : */
2291 : static void
2292 0 : x86emuOp_xchg_word_AX_BX(struct x86emu *emu)
2293 : {
2294 : uint32_t tmp;
2295 :
2296 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2297 0 : tmp = emu->x86.R_EAX;
2298 0 : emu->x86.R_EAX = emu->x86.R_EBX;
2299 0 : emu->x86.R_EBX = tmp;
2300 0 : } else {
2301 0 : tmp = emu->x86.R_AX;
2302 0 : emu->x86.R_AX = emu->x86.R_BX;
2303 0 : emu->x86.R_BX = (uint16_t) tmp;
2304 : }
2305 0 : }
2306 :
2307 : /*
2308 : * REMARKS:
2309 : * Handles opcode 0x94
2310 : */
2311 : static void
2312 0 : x86emuOp_xchg_word_AX_SP(struct x86emu *emu)
2313 : {
2314 : uint32_t tmp;
2315 :
2316 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2317 0 : tmp = emu->x86.R_EAX;
2318 0 : emu->x86.R_EAX = emu->x86.R_ESP;
2319 0 : emu->x86.R_ESP = tmp;
2320 0 : } else {
2321 0 : tmp = emu->x86.R_AX;
2322 0 : emu->x86.R_AX = emu->x86.R_SP;
2323 0 : emu->x86.R_SP = (uint16_t) tmp;
2324 : }
2325 0 : }
2326 :
2327 : /*
2328 : * REMARKS:
2329 : * Handles opcode 0x95
2330 : */
2331 : static void
2332 0 : x86emuOp_xchg_word_AX_BP(struct x86emu *emu)
2333 : {
2334 : uint32_t tmp;
2335 :
2336 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2337 0 : tmp = emu->x86.R_EAX;
2338 0 : emu->x86.R_EAX = emu->x86.R_EBP;
2339 0 : emu->x86.R_EBP = tmp;
2340 0 : } else {
2341 0 : tmp = emu->x86.R_AX;
2342 0 : emu->x86.R_AX = emu->x86.R_BP;
2343 0 : emu->x86.R_BP = (uint16_t) tmp;
2344 : }
2345 0 : }
2346 :
2347 : /*
2348 : * REMARKS:
2349 : * Handles opcode 0x96
2350 : */
2351 : static void
2352 0 : x86emuOp_xchg_word_AX_SI(struct x86emu *emu)
2353 : {
2354 : uint32_t tmp;
2355 :
2356 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2357 0 : tmp = emu->x86.R_EAX;
2358 0 : emu->x86.R_EAX = emu->x86.R_ESI;
2359 0 : emu->x86.R_ESI = tmp;
2360 0 : } else {
2361 0 : tmp = emu->x86.R_AX;
2362 0 : emu->x86.R_AX = emu->x86.R_SI;
2363 0 : emu->x86.R_SI = (uint16_t) tmp;
2364 : }
2365 0 : }
2366 :
2367 : /*
2368 : * REMARKS:
2369 : * Handles opcode 0x97
2370 : */
2371 : static void
2372 0 : x86emuOp_xchg_word_AX_DI(struct x86emu *emu)
2373 : {
2374 : uint32_t tmp;
2375 :
2376 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2377 0 : tmp = emu->x86.R_EAX;
2378 0 : emu->x86.R_EAX = emu->x86.R_EDI;
2379 0 : emu->x86.R_EDI = tmp;
2380 0 : } else {
2381 0 : tmp = emu->x86.R_AX;
2382 0 : emu->x86.R_AX = emu->x86.R_DI;
2383 0 : emu->x86.R_DI = (uint16_t) tmp;
2384 : }
2385 0 : }
2386 :
2387 : /*
2388 : * REMARKS:
2389 : * Handles opcode 0x98
2390 : */
2391 : static void
2392 0 : x86emuOp_cbw(struct x86emu *emu)
2393 : {
2394 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2395 0 : if (emu->x86.R_AX & 0x8000) {
2396 0 : emu->x86.R_EAX |= 0xffff0000;
2397 0 : } else {
2398 0 : emu->x86.R_EAX &= 0x0000ffff;
2399 : }
2400 : } else {
2401 0 : if (emu->x86.R_AL & 0x80) {
2402 0 : emu->x86.R_AH = 0xff;
2403 0 : } else {
2404 0 : emu->x86.R_AH = 0x0;
2405 : }
2406 : }
2407 0 : }
2408 :
2409 : /*
2410 : * REMARKS:
2411 : * Handles opcode 0x99
2412 : */
2413 : static void
2414 0 : x86emuOp_cwd(struct x86emu *emu)
2415 : {
2416 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2417 0 : if (emu->x86.R_EAX & 0x80000000) {
2418 0 : emu->x86.R_EDX = 0xffffffff;
2419 0 : } else {
2420 0 : emu->x86.R_EDX = 0x0;
2421 : }
2422 : } else {
2423 0 : if (emu->x86.R_AX & 0x8000) {
2424 0 : emu->x86.R_DX = 0xffff;
2425 0 : } else {
2426 0 : emu->x86.R_DX = 0x0;
2427 : }
2428 : }
2429 0 : }
2430 :
2431 : /*
2432 : * REMARKS:
2433 : * Handles opcode 0x9a
2434 : */
2435 : static void
2436 0 : x86emuOp_call_far_IMM(struct x86emu *emu)
2437 : {
2438 : uint16_t farseg, faroff;
2439 :
2440 0 : faroff = fetch_word_imm(emu);
2441 0 : farseg = fetch_word_imm(emu);
2442 : /* XXX
2443 : *
2444 : * Hooked interrupt vectors calling into our "BIOS" will cause problems
2445 : * unless all intersegment stuff is checked for BIOS access. Check
2446 : * needed here. For moment, let it alone. */
2447 0 : push_word(emu, emu->x86.R_CS);
2448 0 : emu->x86.R_CS = farseg;
2449 0 : push_word(emu, emu->x86.R_IP);
2450 0 : emu->x86.R_IP = faroff;
2451 0 : }
2452 :
2453 : /*
2454 : * REMARKS:
2455 : * Handles opcode 0x9c
2456 : */
2457 : static void
2458 0 : x86emuOp_pushf_word(struct x86emu *emu)
2459 : {
2460 : uint32_t flags;
2461 :
2462 : /* clear out *all* bits not representing flags, and turn on real bits */
2463 0 : flags = (emu->x86.R_EFLG & F_MSK) | F_ALWAYS_ON;
2464 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2465 0 : push_long(emu, flags);
2466 0 : } else {
2467 0 : push_word(emu, (uint16_t) flags);
2468 : }
2469 0 : }
2470 :
2471 : /*
2472 : * REMARKS:
2473 : * Handles opcode 0x9d
2474 : */
2475 : static void
2476 0 : x86emuOp_popf_word(struct x86emu *emu)
2477 : {
2478 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2479 0 : emu->x86.R_EFLG = pop_long(emu);
2480 0 : } else {
2481 0 : emu->x86.R_FLG = pop_word(emu);
2482 : }
2483 0 : }
2484 :
2485 : /*
2486 : * REMARKS:
2487 : * Handles opcode 0x9e
2488 : */
2489 : static void
2490 0 : x86emuOp_sahf(struct x86emu *emu)
2491 : {
2492 : /* clear the lower bits of the flag register */
2493 0 : emu->x86.R_FLG &= 0xffffff00;
2494 : /* or in the AH register into the flags register */
2495 0 : emu->x86.R_FLG |= emu->x86.R_AH;
2496 0 : }
2497 :
2498 : /*
2499 : * REMARKS:
2500 : * Handles opcode 0x9f
2501 : */
2502 : static void
2503 0 : x86emuOp_lahf(struct x86emu *emu)
2504 : {
2505 0 : emu->x86.R_AH = (uint8_t) (emu->x86.R_FLG & 0xff);
2506 : /* undocumented TC++ behavior??? Nope. It's documented, but you have
2507 : * too look real hard to notice it. */
2508 0 : emu->x86.R_AH |= 0x2;
2509 0 : }
2510 :
2511 : /*
2512 : * REMARKS:
2513 : * Handles opcode 0xa0
2514 : */
2515 : static void
2516 0 : x86emuOp_mov_AL_M_IMM(struct x86emu *emu)
2517 : {
2518 : uint16_t offset;
2519 :
2520 0 : offset = fetch_word_imm(emu);
2521 0 : emu->x86.R_AL = fetch_data_byte(emu, offset);
2522 0 : }
2523 :
2524 : /*
2525 : * REMARKS:
2526 : * Handles opcode 0xa1
2527 : */
2528 : static void
2529 0 : x86emuOp_mov_AX_M_IMM(struct x86emu *emu)
2530 : {
2531 : uint16_t offset;
2532 :
2533 0 : offset = fetch_word_imm(emu);
2534 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2535 0 : emu->x86.R_EAX = fetch_data_long(emu, offset);
2536 0 : } else {
2537 0 : emu->x86.R_AX = fetch_data_word(emu, offset);
2538 : }
2539 0 : }
2540 :
2541 : /*
2542 : * REMARKS:
2543 : * Handles opcode 0xa2
2544 : */
2545 : static void
2546 0 : x86emuOp_mov_M_AL_IMM(struct x86emu *emu)
2547 : {
2548 : uint16_t offset;
2549 :
2550 0 : offset = fetch_word_imm(emu);
2551 0 : store_data_byte(emu, offset, emu->x86.R_AL);
2552 0 : }
2553 :
2554 : /*
2555 : * REMARKS:
2556 : * Handles opcode 0xa3
2557 : */
2558 : static void
2559 0 : x86emuOp_mov_M_AX_IMM(struct x86emu *emu)
2560 : {
2561 : uint16_t offset;
2562 :
2563 0 : offset = fetch_word_imm(emu);
2564 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2565 0 : store_data_long(emu, offset, emu->x86.R_EAX);
2566 0 : } else {
2567 0 : store_data_word(emu, offset, emu->x86.R_AX);
2568 : }
2569 0 : }
2570 :
2571 : /*
2572 : * REMARKS:
2573 : * Handles opcode 0xa4
2574 : */
2575 : static void
2576 0 : x86emuOp_movs_byte(struct x86emu *emu)
2577 : {
2578 : uint8_t val;
2579 : uint32_t count;
2580 : int inc;
2581 :
2582 0 : if (ACCESS_FLAG(F_DF)) /* down */
2583 0 : inc = -1;
2584 : else
2585 : inc = 1;
2586 : count = 1;
2587 0 : if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2588 : /* dont care whether REPE or REPNE */
2589 : /* move them until CX is ZERO. */
2590 0 : count = emu->x86.R_CX;
2591 0 : emu->x86.R_CX = 0;
2592 0 : emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2593 0 : }
2594 0 : while (count--) {
2595 0 : val = fetch_data_byte(emu, emu->x86.R_SI);
2596 0 : store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2597 0 : emu->x86.R_SI += inc;
2598 0 : emu->x86.R_DI += inc;
2599 : }
2600 0 : }
2601 :
2602 : /*
2603 : * REMARKS:
2604 : * Handles opcode 0xa5
2605 : */
2606 : static void
2607 0 : x86emuOp_movs_word(struct x86emu *emu)
2608 : {
2609 : uint32_t val;
2610 : int inc;
2611 : uint32_t count;
2612 :
2613 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2614 0 : inc = 4;
2615 : else
2616 : inc = 2;
2617 :
2618 0 : if (ACCESS_FLAG(F_DF)) /* down */
2619 0 : inc = -inc;
2620 :
2621 : count = 1;
2622 0 : if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2623 : /* dont care whether REPE or REPNE */
2624 : /* move them until CX is ZERO. */
2625 0 : count = emu->x86.R_CX;
2626 0 : emu->x86.R_CX = 0;
2627 0 : emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2628 0 : }
2629 0 : while (count--) {
2630 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2631 0 : val = fetch_data_long(emu, emu->x86.R_SI);
2632 0 : store_long(emu, emu->x86.R_ES, emu->x86.R_DI, val);
2633 0 : } else {
2634 0 : val = fetch_data_word(emu, emu->x86.R_SI);
2635 0 : store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
2636 : (uint16_t) val);
2637 : }
2638 0 : emu->x86.R_SI += inc;
2639 0 : emu->x86.R_DI += inc;
2640 : }
2641 0 : }
2642 :
2643 : /*
2644 : * REMARKS:
2645 : * Handles opcode 0xa6
2646 : */
2647 : static void
2648 0 : x86emuOp_cmps_byte(struct x86emu *emu)
2649 : {
2650 : int8_t val1, val2;
2651 : int inc;
2652 :
2653 0 : if (ACCESS_FLAG(F_DF)) /* down */
2654 0 : inc = -1;
2655 : else
2656 : inc = 1;
2657 :
2658 0 : if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2659 : /* REPE */
2660 : /* move them until CX is ZERO. */
2661 0 : while (emu->x86.R_CX != 0) {
2662 0 : val1 = fetch_data_byte(emu, emu->x86.R_SI);
2663 0 : val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2664 0 : cmp_byte(emu, val1, val2);
2665 0 : emu->x86.R_CX -= 1;
2666 0 : emu->x86.R_SI += inc;
2667 0 : emu->x86.R_DI += inc;
2668 0 : if (ACCESS_FLAG(F_ZF) == 0)
2669 : break;
2670 : }
2671 0 : emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2672 0 : } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2673 : /* REPNE */
2674 : /* move them until CX is ZERO. */
2675 0 : while (emu->x86.R_CX != 0) {
2676 0 : val1 = fetch_data_byte(emu, emu->x86.R_SI);
2677 0 : val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2678 0 : cmp_byte(emu, val1, val2);
2679 0 : emu->x86.R_CX -= 1;
2680 0 : emu->x86.R_SI += inc;
2681 0 : emu->x86.R_DI += inc;
2682 0 : if (ACCESS_FLAG(F_ZF))
2683 : break; /* zero flag set means equal */
2684 : }
2685 0 : emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2686 0 : } else {
2687 0 : val1 = fetch_data_byte(emu, emu->x86.R_SI);
2688 0 : val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2689 0 : cmp_byte(emu, val1, val2);
2690 0 : emu->x86.R_SI += inc;
2691 0 : emu->x86.R_DI += inc;
2692 : }
2693 0 : }
2694 :
2695 : /*
2696 : * REMARKS:
2697 : * Handles opcode 0xa7
2698 : */
2699 : static void
2700 0 : x86emuOp_cmps_word(struct x86emu *emu)
2701 : {
2702 : uint32_t val1, val2;
2703 : int inc;
2704 :
2705 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2706 0 : if (ACCESS_FLAG(F_DF)) /* down */
2707 0 : inc = -4;
2708 : else
2709 : inc = 4;
2710 : } else {
2711 0 : if (ACCESS_FLAG(F_DF)) /* down */
2712 0 : inc = -2;
2713 : else
2714 : inc = 2;
2715 : }
2716 0 : if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2717 : /* REPE */
2718 : /* move them until CX is ZERO. */
2719 0 : while (emu->x86.R_CX != 0) {
2720 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2721 0 : val1 = fetch_data_long(emu, emu->x86.R_SI);
2722 0 : val2 = fetch_long(emu, emu->x86.R_ES,
2723 0 : emu->x86.R_DI);
2724 0 : cmp_long(emu, val1, val2);
2725 0 : } else {
2726 0 : val1 = fetch_data_word(emu, emu->x86.R_SI);
2727 0 : val2 = fetch_word(emu, emu->x86.R_ES,
2728 0 : emu->x86.R_DI);
2729 0 : cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2730 : }
2731 0 : emu->x86.R_CX -= 1;
2732 0 : emu->x86.R_SI += inc;
2733 0 : emu->x86.R_DI += inc;
2734 0 : if (ACCESS_FLAG(F_ZF) == 0)
2735 : break;
2736 : }
2737 0 : emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2738 0 : } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2739 : /* REPNE */
2740 : /* move them until CX is ZERO. */
2741 0 : while (emu->x86.R_CX != 0) {
2742 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2743 0 : val1 = fetch_data_long(emu, emu->x86.R_SI);
2744 0 : val2 = fetch_long(emu, emu->x86.R_ES,
2745 0 : emu->x86.R_DI);
2746 0 : cmp_long(emu, val1, val2);
2747 0 : } else {
2748 0 : val1 = fetch_data_word(emu, emu->x86.R_SI);
2749 0 : val2 = fetch_word(emu, emu->x86.R_ES,
2750 0 : emu->x86.R_DI);
2751 0 : cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2752 : }
2753 0 : emu->x86.R_CX -= 1;
2754 0 : emu->x86.R_SI += inc;
2755 0 : emu->x86.R_DI += inc;
2756 0 : if (ACCESS_FLAG(F_ZF))
2757 : break; /* zero flag set means equal */
2758 : }
2759 0 : emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2760 0 : } else {
2761 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2762 0 : val1 = fetch_data_long(emu, emu->x86.R_SI);
2763 0 : val2 = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
2764 0 : cmp_long(emu, val1, val2);
2765 0 : } else {
2766 0 : val1 = fetch_data_word(emu, emu->x86.R_SI);
2767 0 : val2 = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
2768 0 : cmp_word(emu, (uint16_t) val1, (uint16_t) val2);
2769 : }
2770 0 : emu->x86.R_SI += inc;
2771 0 : emu->x86.R_DI += inc;
2772 : }
2773 0 : }
2774 :
2775 : /*
2776 : * REMARKS:
2777 : * Handles opcode 0xa9
2778 : */
2779 : static void
2780 0 : x86emuOp_test_AX_IMM(struct x86emu *emu)
2781 : {
2782 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2783 0 : test_long(emu, emu->x86.R_EAX, fetch_long_imm(emu));
2784 0 : } else {
2785 0 : test_word(emu, emu->x86.R_AX, fetch_word_imm(emu));
2786 : }
2787 0 : }
2788 :
2789 : /*
2790 : * REMARKS:
2791 : * Handles opcode 0xaa
2792 : */
2793 : static void
2794 0 : x86emuOp_stos_byte(struct x86emu *emu)
2795 : {
2796 : int inc;
2797 :
2798 0 : if (ACCESS_FLAG(F_DF)) /* down */
2799 0 : inc = -1;
2800 : else
2801 : inc = 1;
2802 0 : if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2803 : /* dont care whether REPE or REPNE */
2804 : /* move them until CX is ZERO. */
2805 0 : while (emu->x86.R_CX != 0) {
2806 0 : store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
2807 0 : emu->x86.R_AL);
2808 0 : emu->x86.R_CX -= 1;
2809 0 : emu->x86.R_DI += inc;
2810 : }
2811 0 : emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2812 0 : } else {
2813 0 : store_byte(emu, emu->x86.R_ES, emu->x86.R_DI, emu->x86.R_AL);
2814 0 : emu->x86.R_DI += inc;
2815 : }
2816 0 : }
2817 :
2818 : /*
2819 : * REMARKS:
2820 : * Handles opcode 0xab
2821 : */
2822 : static void
2823 0 : x86emuOp_stos_word(struct x86emu *emu)
2824 : {
2825 : int inc;
2826 : uint32_t count;
2827 :
2828 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2829 0 : inc = 4;
2830 : else
2831 : inc = 2;
2832 :
2833 0 : if (ACCESS_FLAG(F_DF)) /* down */
2834 0 : inc = -inc;
2835 :
2836 : count = 1;
2837 0 : if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2838 : /* dont care whether REPE or REPNE */
2839 : /* move them until CX is ZERO. */
2840 0 : count = emu->x86.R_CX;
2841 0 : emu->x86.R_CX = 0;
2842 0 : emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2843 0 : }
2844 0 : while (count--) {
2845 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2846 0 : store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
2847 0 : emu->x86.R_EAX);
2848 0 : } else {
2849 0 : store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
2850 0 : emu->x86.R_AX);
2851 : }
2852 0 : emu->x86.R_DI += inc;
2853 : }
2854 0 : }
2855 :
2856 : /*
2857 : * REMARKS:
2858 : * Handles opcode 0xac
2859 : */
2860 : static void
2861 0 : x86emuOp_lods_byte(struct x86emu *emu)
2862 : {
2863 : int inc;
2864 :
2865 0 : if (ACCESS_FLAG(F_DF)) /* down */
2866 0 : inc = -1;
2867 : else
2868 : inc = 1;
2869 0 : if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2870 : /* dont care whether REPE or REPNE */
2871 : /* move them until CX is ZERO. */
2872 0 : while (emu->x86.R_CX != 0) {
2873 0 : emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2874 0 : emu->x86.R_CX -= 1;
2875 0 : emu->x86.R_SI += inc;
2876 : }
2877 0 : emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2878 0 : } else {
2879 0 : emu->x86.R_AL = fetch_data_byte(emu, emu->x86.R_SI);
2880 0 : emu->x86.R_SI += inc;
2881 : }
2882 0 : }
2883 :
2884 : /*
2885 : * REMARKS:
2886 : * Handles opcode 0xad
2887 : */
2888 : static void
2889 0 : x86emuOp_lods_word(struct x86emu *emu)
2890 : {
2891 : int inc;
2892 : uint32_t count;
2893 :
2894 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2895 0 : inc = 4;
2896 : else
2897 : inc = 2;
2898 :
2899 0 : if (ACCESS_FLAG(F_DF)) /* down */
2900 0 : inc = -inc;
2901 :
2902 : count = 1;
2903 0 : if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
2904 : /* dont care whether REPE or REPNE */
2905 : /* move them until CX is ZERO. */
2906 0 : count = emu->x86.R_CX;
2907 0 : emu->x86.R_CX = 0;
2908 0 : emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
2909 0 : }
2910 0 : while (count--) {
2911 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2912 0 : emu->x86.R_EAX = fetch_data_long(emu, emu->x86.R_SI);
2913 0 : } else {
2914 0 : emu->x86.R_AX = fetch_data_word(emu, emu->x86.R_SI);
2915 : }
2916 0 : emu->x86.R_SI += inc;
2917 : }
2918 0 : }
2919 :
2920 : /*
2921 : * REMARKS:
2922 : * Handles opcode 0xae
2923 : */
2924 : static void
2925 0 : x86emuOp_scas_byte(struct x86emu *emu)
2926 : {
2927 : int8_t val2;
2928 : int inc;
2929 :
2930 0 : if (ACCESS_FLAG(F_DF)) /* down */
2931 0 : inc = -1;
2932 : else
2933 : inc = 1;
2934 0 : if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2935 : /* REPE */
2936 : /* move them until CX is ZERO. */
2937 0 : while (emu->x86.R_CX != 0) {
2938 0 : val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2939 0 : cmp_byte(emu, emu->x86.R_AL, val2);
2940 0 : emu->x86.R_CX -= 1;
2941 0 : emu->x86.R_DI += inc;
2942 0 : if (ACCESS_FLAG(F_ZF) == 0)
2943 : break;
2944 : }
2945 0 : emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
2946 0 : } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
2947 : /* REPNE */
2948 : /* move them until CX is ZERO. */
2949 0 : while (emu->x86.R_CX != 0) {
2950 0 : val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2951 0 : cmp_byte(emu, emu->x86.R_AL, val2);
2952 0 : emu->x86.R_CX -= 1;
2953 0 : emu->x86.R_DI += inc;
2954 0 : if (ACCESS_FLAG(F_ZF))
2955 : break; /* zero flag set means equal */
2956 : }
2957 0 : emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
2958 0 : } else {
2959 0 : val2 = fetch_byte(emu, emu->x86.R_ES, emu->x86.R_DI);
2960 0 : cmp_byte(emu, emu->x86.R_AL, val2);
2961 0 : emu->x86.R_DI += inc;
2962 : }
2963 0 : }
2964 :
2965 : /*
2966 : * REMARKS:
2967 : * Handles opcode 0xaf
2968 : */
2969 : static void
2970 0 : x86emuOp_scas_word(struct x86emu *emu)
2971 : {
2972 : int inc;
2973 : uint32_t val;
2974 :
2975 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
2976 0 : inc = 4;
2977 : else
2978 : inc = 2;
2979 :
2980 0 : if (ACCESS_FLAG(F_DF)) /* down */
2981 0 : inc = -inc;
2982 :
2983 0 : if (emu->x86.mode & SYSMODE_PREFIX_REPE) {
2984 : /* REPE */
2985 : /* move them until CX is ZERO. */
2986 0 : while (emu->x86.R_CX != 0) {
2987 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
2988 0 : val = fetch_long(emu, emu->x86.R_ES,
2989 : emu->x86.R_DI);
2990 0 : cmp_long(emu, emu->x86.R_EAX, val);
2991 0 : } else {
2992 0 : val = fetch_word(emu, emu->x86.R_ES,
2993 : emu->x86.R_DI);
2994 0 : cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
2995 : }
2996 0 : emu->x86.R_CX -= 1;
2997 0 : emu->x86.R_DI += inc;
2998 0 : if (ACCESS_FLAG(F_ZF) == 0)
2999 : break;
3000 : }
3001 0 : emu->x86.mode &= ~SYSMODE_PREFIX_REPE;
3002 0 : } else if (emu->x86.mode & SYSMODE_PREFIX_REPNE) {
3003 : /* REPNE */
3004 : /* move them until CX is ZERO. */
3005 0 : while (emu->x86.R_CX != 0) {
3006 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3007 0 : val = fetch_long(emu, emu->x86.R_ES,
3008 : emu->x86.R_DI);
3009 0 : cmp_long(emu, emu->x86.R_EAX, val);
3010 0 : } else {
3011 0 : val = fetch_word(emu, emu->x86.R_ES,
3012 : emu->x86.R_DI);
3013 0 : cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
3014 : }
3015 0 : emu->x86.R_CX -= 1;
3016 0 : emu->x86.R_DI += inc;
3017 0 : if (ACCESS_FLAG(F_ZF))
3018 : break; /* zero flag set means equal */
3019 : }
3020 0 : emu->x86.mode &= ~SYSMODE_PREFIX_REPNE;
3021 0 : } else {
3022 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3023 0 : val = fetch_long(emu, emu->x86.R_ES, emu->x86.R_DI);
3024 0 : cmp_long(emu, emu->x86.R_EAX, val);
3025 0 : } else {
3026 0 : val = fetch_word(emu, emu->x86.R_ES, emu->x86.R_DI);
3027 0 : cmp_word(emu, emu->x86.R_AX, (uint16_t) val);
3028 : }
3029 0 : emu->x86.R_DI += inc;
3030 : }
3031 0 : }
3032 :
3033 : /*
3034 : * REMARKS:
3035 : * Handles opcode 0xb8
3036 : */
3037 : static void
3038 0 : x86emuOp_mov_word_AX_IMM(struct x86emu *emu)
3039 : {
3040 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3041 0 : emu->x86.R_EAX = fetch_long_imm(emu);
3042 : else
3043 0 : emu->x86.R_AX = fetch_word_imm(emu);
3044 0 : }
3045 :
3046 : /*
3047 : * REMARKS:
3048 : * Handles opcode 0xb9
3049 : */
3050 : static void
3051 0 : x86emuOp_mov_word_CX_IMM(struct x86emu *emu)
3052 : {
3053 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3054 0 : emu->x86.R_ECX = fetch_long_imm(emu);
3055 : else
3056 0 : emu->x86.R_CX = fetch_word_imm(emu);
3057 0 : }
3058 :
3059 : /*
3060 : * REMARKS:
3061 : * Handles opcode 0xba
3062 : */
3063 : static void
3064 0 : x86emuOp_mov_word_DX_IMM(struct x86emu *emu)
3065 : {
3066 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3067 0 : emu->x86.R_EDX = fetch_long_imm(emu);
3068 : else
3069 0 : emu->x86.R_DX = fetch_word_imm(emu);
3070 0 : }
3071 :
3072 : /*
3073 : * REMARKS:
3074 : * Handles opcode 0xbb
3075 : */
3076 : static void
3077 0 : x86emuOp_mov_word_BX_IMM(struct x86emu *emu)
3078 : {
3079 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3080 0 : emu->x86.R_EBX = fetch_long_imm(emu);
3081 : else
3082 0 : emu->x86.R_BX = fetch_word_imm(emu);
3083 0 : }
3084 :
3085 : /*
3086 : * REMARKS:
3087 : * Handles opcode 0xbc
3088 : */
3089 : static void
3090 0 : x86emuOp_mov_word_SP_IMM(struct x86emu *emu)
3091 : {
3092 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3093 0 : emu->x86.R_ESP = fetch_long_imm(emu);
3094 : else
3095 0 : emu->x86.R_SP = fetch_word_imm(emu);
3096 0 : }
3097 :
3098 : /*
3099 : * REMARKS:
3100 : * Handles opcode 0xbd
3101 : */
3102 : static void
3103 0 : x86emuOp_mov_word_BP_IMM(struct x86emu *emu)
3104 : {
3105 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3106 0 : emu->x86.R_EBP = fetch_long_imm(emu);
3107 : else
3108 0 : emu->x86.R_BP = fetch_word_imm(emu);
3109 0 : }
3110 :
3111 : /*
3112 : * REMARKS:
3113 : * Handles opcode 0xbe
3114 : */
3115 : static void
3116 0 : x86emuOp_mov_word_SI_IMM(struct x86emu *emu)
3117 : {
3118 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3119 0 : emu->x86.R_ESI = fetch_long_imm(emu);
3120 : else
3121 0 : emu->x86.R_SI = fetch_word_imm(emu);
3122 0 : }
3123 :
3124 : /*
3125 : * REMARKS:
3126 : * Handles opcode 0xbf
3127 : */
3128 : static void
3129 0 : x86emuOp_mov_word_DI_IMM(struct x86emu *emu)
3130 : {
3131 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3132 0 : emu->x86.R_EDI = fetch_long_imm(emu);
3133 : else
3134 0 : emu->x86.R_DI = fetch_word_imm(emu);
3135 0 : }
3136 : /* used by opcodes c0, d0, and d2. */
3137 : static
3138 : uint8_t(* const opcD0_byte_operation[])
3139 : (struct x86emu *, uint8_t d, uint8_t s) =
3140 : {
3141 : rol_byte,
3142 : ror_byte,
3143 : rcl_byte,
3144 : rcr_byte,
3145 : shl_byte,
3146 : shr_byte,
3147 : shl_byte, /* sal_byte === shl_byte by definition */
3148 : sar_byte,
3149 : };
3150 :
3151 : /*
3152 : * REMARKS:
3153 : * Handles opcode 0xc0
3154 : */
3155 : static void
3156 0 : x86emuOp_opcC0_byte_RM_MEM(struct x86emu *emu)
3157 : {
3158 0 : uint8_t destval, amt;
3159 :
3160 : /*
3161 : * Yet another weirdo special case instruction format. Part of
3162 : * the opcode held below in "RH". Doubly nested case would
3163 : * result, except that the decoded instruction
3164 : */
3165 0 : fetch_decode_modrm(emu);
3166 : /* know operation, decode the mod byte to find the addressing mode. */
3167 0 : destval = decode_and_fetch_byte_imm8(emu, &amt);
3168 0 : destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, amt);
3169 0 : write_back_byte(emu, destval);
3170 0 : }
3171 : /* used by opcodes c1, d1, and d3. */
3172 : static
3173 : uint16_t(* const opcD1_word_operation[])
3174 : (struct x86emu *, uint16_t s, uint8_t d) =
3175 : {
3176 : rol_word,
3177 : ror_word,
3178 : rcl_word,
3179 : rcr_word,
3180 : shl_word,
3181 : shr_word,
3182 : shl_word, /* sal_byte === shl_byte by definition */
3183 : sar_word,
3184 : };
3185 : /* used by opcodes c1, d1, and d3. */
3186 : static
3187 : uint32_t(* const opcD1_long_operation[])
3188 : (struct x86emu *, uint32_t s, uint8_t d) =
3189 : {
3190 : rol_long,
3191 : ror_long,
3192 : rcl_long,
3193 : rcr_long,
3194 : shl_long,
3195 : shr_long,
3196 : shl_long, /* sal_byte === shl_byte by definition */
3197 : sar_long,
3198 : };
3199 :
3200 : /*
3201 : * REMARKS:
3202 : * Handles opcode 0xc1
3203 : */
3204 : static void
3205 0 : x86emuOp_opcC1_word_RM_MEM(struct x86emu *emu)
3206 : {
3207 0 : uint8_t amt;
3208 :
3209 : /*
3210 : * Yet another weirdo special case instruction format. Part of
3211 : * the opcode held below in "RH". Doubly nested case would
3212 : * result, except that the decoded instruction
3213 : */
3214 0 : fetch_decode_modrm(emu);
3215 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3216 : uint32_t destval;
3217 :
3218 0 : destval = decode_and_fetch_long_imm8(emu, &amt);
3219 0 : destval = (*opcD1_long_operation[emu->cur_rh])
3220 0 : (emu, destval, amt);
3221 0 : write_back_long(emu, destval);
3222 0 : } else {
3223 : uint16_t destval;
3224 :
3225 0 : destval = decode_and_fetch_word_imm8(emu, &amt);
3226 0 : destval = (*opcD1_word_operation[emu->cur_rh])
3227 0 : (emu, destval, amt);
3228 0 : write_back_word(emu, destval);
3229 : }
3230 0 : }
3231 :
3232 : /*
3233 : * REMARKS:
3234 : * Handles opcode 0xc2
3235 : */
3236 : static void
3237 0 : x86emuOp_ret_near_IMM(struct x86emu *emu)
3238 : {
3239 : uint16_t imm;
3240 :
3241 0 : imm = fetch_word_imm(emu);
3242 0 : emu->x86.R_IP = pop_word(emu);
3243 0 : emu->x86.R_SP += imm;
3244 0 : }
3245 :
3246 : /*
3247 : * REMARKS:
3248 : * Handles opcode 0xc6
3249 : */
3250 : static void
3251 0 : x86emuOp_mov_byte_RM_IMM(struct x86emu *emu)
3252 : {
3253 : uint8_t *destreg;
3254 : uint32_t destoffset;
3255 : uint8_t imm;
3256 :
3257 0 : fetch_decode_modrm(emu);
3258 0 : if (emu->cur_rh != 0)
3259 0 : x86emu_halt_sys(emu);
3260 0 : if (emu->cur_mod != 3) {
3261 0 : destoffset = decode_rl_address(emu);
3262 0 : imm = fetch_byte_imm(emu);
3263 0 : store_data_byte(emu, destoffset, imm);
3264 0 : } else {
3265 0 : destreg = decode_rl_byte_register(emu);
3266 0 : imm = fetch_byte_imm(emu);
3267 0 : *destreg = imm;
3268 : }
3269 0 : }
3270 :
3271 : /*
3272 : * REMARKS:
3273 : * Handles opcode 0xc7
3274 : */
3275 : static void
3276 0 : x86emuOp32_mov_word_RM_IMM(struct x86emu *emu)
3277 : {
3278 : uint32_t destoffset;
3279 : uint32_t imm, *destreg;
3280 :
3281 0 : fetch_decode_modrm(emu);
3282 0 : if (emu->cur_rh != 0)
3283 0 : x86emu_halt_sys(emu);
3284 :
3285 0 : if (emu->cur_mod != 3) {
3286 0 : destoffset = decode_rl_address(emu);
3287 0 : imm = fetch_long_imm(emu);
3288 0 : store_data_long(emu, destoffset, imm);
3289 0 : } else {
3290 0 : destreg = decode_rl_long_register(emu);
3291 0 : imm = fetch_long_imm(emu);
3292 0 : *destreg = imm;
3293 : }
3294 0 : }
3295 :
3296 : static void
3297 0 : x86emuOp16_mov_word_RM_IMM(struct x86emu *emu)
3298 : {
3299 : uint32_t destoffset;
3300 : uint16_t imm, *destreg;
3301 :
3302 0 : fetch_decode_modrm(emu);
3303 0 : if (emu->cur_rh != 0)
3304 0 : x86emu_halt_sys(emu);
3305 :
3306 0 : if (emu->cur_mod != 3) {
3307 0 : destoffset = decode_rl_address(emu);
3308 0 : imm = fetch_word_imm(emu);
3309 0 : store_data_word(emu, destoffset, imm);
3310 0 : } else {
3311 0 : destreg = decode_rl_word_register(emu);
3312 0 : imm = fetch_word_imm(emu);
3313 0 : *destreg = imm;
3314 : }
3315 0 : }
3316 :
3317 : static void
3318 0 : x86emuOp_mov_word_RM_IMM(struct x86emu *emu)
3319 : {
3320 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
3321 0 : x86emuOp32_mov_word_RM_IMM(emu);
3322 : else
3323 0 : x86emuOp16_mov_word_RM_IMM(emu);
3324 0 : }
3325 :
3326 : /*
3327 : * REMARKS:
3328 : * Handles opcode 0xc8
3329 : */
3330 : static void
3331 0 : x86emuOp_enter(struct x86emu *emu)
3332 : {
3333 : uint16_t local, frame_pointer;
3334 : uint8_t nesting;
3335 : int i;
3336 :
3337 0 : local = fetch_word_imm(emu);
3338 0 : nesting = fetch_byte_imm(emu);
3339 0 : push_word(emu, emu->x86.R_BP);
3340 0 : frame_pointer = emu->x86.R_SP;
3341 0 : if (nesting > 0) {
3342 0 : for (i = 1; i < nesting; i++) {
3343 0 : emu->x86.R_BP -= 2;
3344 0 : push_word(emu, fetch_word(emu, emu->x86.R_SS,
3345 0 : emu->x86.R_BP));
3346 : }
3347 0 : push_word(emu, frame_pointer);
3348 0 : }
3349 0 : emu->x86.R_BP = frame_pointer;
3350 0 : emu->x86.R_SP = (uint16_t) (emu->x86.R_SP - local);
3351 0 : }
3352 :
3353 : /*
3354 : * REMARKS:
3355 : * Handles opcode 0xc9
3356 : */
3357 : static void
3358 0 : x86emuOp_leave(struct x86emu *emu)
3359 : {
3360 0 : emu->x86.R_SP = emu->x86.R_BP;
3361 0 : emu->x86.R_BP = pop_word(emu);
3362 0 : }
3363 :
3364 : /*
3365 : * REMARKS:
3366 : * Handles opcode 0xca
3367 : */
3368 : static void
3369 0 : x86emuOp_ret_far_IMM(struct x86emu *emu)
3370 : {
3371 : uint16_t imm;
3372 :
3373 0 : imm = fetch_word_imm(emu);
3374 0 : emu->x86.R_IP = pop_word(emu);
3375 0 : emu->x86.R_CS = pop_word(emu);
3376 0 : emu->x86.R_SP += imm;
3377 0 : }
3378 :
3379 : /*
3380 : * REMARKS:
3381 : * Handles opcode 0xcb
3382 : */
3383 : static void
3384 0 : x86emuOp_ret_far(struct x86emu *emu)
3385 : {
3386 0 : emu->x86.R_IP = pop_word(emu);
3387 0 : emu->x86.R_CS = pop_word(emu);
3388 0 : }
3389 :
3390 : /*
3391 : * REMARKS:
3392 : * Handles opcode 0xcc
3393 : */
3394 : static void
3395 0 : x86emuOp_int3(struct x86emu *emu)
3396 : {
3397 0 : x86emu_intr_dispatch(emu, 3);
3398 0 : }
3399 :
3400 : /*
3401 : * REMARKS:
3402 : * Handles opcode 0xcd
3403 : */
3404 : static void
3405 0 : x86emuOp_int_IMM(struct x86emu *emu)
3406 : {
3407 : uint8_t intnum;
3408 :
3409 0 : intnum = fetch_byte_imm(emu);
3410 0 : x86emu_intr_dispatch(emu, intnum);
3411 0 : }
3412 :
3413 : /*
3414 : * REMARKS:
3415 : * Handles opcode 0xce
3416 : */
3417 : static void
3418 0 : x86emuOp_into(struct x86emu *emu)
3419 : {
3420 0 : if (ACCESS_FLAG(F_OF))
3421 0 : x86emu_intr_dispatch(emu, 4);
3422 0 : }
3423 :
3424 : /*
3425 : * REMARKS:
3426 : * Handles opcode 0xcf
3427 : */
3428 : static void
3429 0 : x86emuOp_iret(struct x86emu *emu)
3430 : {
3431 0 : emu->x86.R_IP = pop_word(emu);
3432 0 : emu->x86.R_CS = pop_word(emu);
3433 0 : emu->x86.R_FLG = pop_word(emu);
3434 0 : }
3435 :
3436 : /*
3437 : * REMARKS:
3438 : * Handles opcode 0xd0
3439 : */
3440 : static void
3441 0 : x86emuOp_opcD0_byte_RM_1(struct x86emu *emu)
3442 : {
3443 : uint8_t destval;
3444 :
3445 0 : fetch_decode_modrm(emu);
3446 0 : destval = decode_and_fetch_byte(emu);
3447 0 : destval = (*opcD0_byte_operation[emu->cur_rh]) (emu, destval, 1);
3448 0 : write_back_byte(emu, destval);
3449 0 : }
3450 :
3451 : /*
3452 : * REMARKS:
3453 : * Handles opcode 0xd1
3454 : */
3455 : static void
3456 0 : x86emuOp_opcD1_word_RM_1(struct x86emu *emu)
3457 : {
3458 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3459 : uint32_t destval;
3460 :
3461 0 : fetch_decode_modrm(emu);
3462 0 : destval = decode_and_fetch_long(emu);
3463 0 : destval = (*opcD1_long_operation[emu->cur_rh])(emu, destval, 1);
3464 0 : write_back_long(emu, destval);
3465 0 : } else {
3466 : uint16_t destval;
3467 :
3468 0 : fetch_decode_modrm(emu);
3469 0 : destval = decode_and_fetch_word(emu);
3470 0 : destval = (*opcD1_word_operation[emu->cur_rh])(emu, destval, 1);
3471 0 : write_back_word(emu, destval);
3472 : }
3473 0 : }
3474 :
3475 : /*
3476 : * REMARKS:
3477 : * Handles opcode 0xd2
3478 : */
3479 : static void
3480 0 : x86emuOp_opcD2_byte_RM_CL(struct x86emu *emu)
3481 : {
3482 : uint8_t destval;
3483 :
3484 0 : fetch_decode_modrm(emu);
3485 0 : destval = decode_and_fetch_byte(emu);
3486 0 : destval = (*opcD0_byte_operation[emu->cur_rh])
3487 0 : (emu, destval, emu->x86.R_CL);
3488 0 : write_back_byte(emu, destval);
3489 0 : }
3490 :
3491 : /*
3492 : * REMARKS:
3493 : * Handles opcode 0xd3
3494 : */
3495 : static void
3496 0 : x86emuOp_opcD3_word_RM_CL(struct x86emu *emu)
3497 : {
3498 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3499 : uint32_t destval;
3500 :
3501 0 : fetch_decode_modrm(emu);
3502 0 : destval = decode_and_fetch_long(emu);
3503 0 : destval = (*opcD1_long_operation[emu->cur_rh])
3504 0 : (emu, destval, emu->x86.R_CL);
3505 0 : write_back_long(emu, destval);
3506 0 : } else {
3507 : uint16_t destval;
3508 :
3509 0 : fetch_decode_modrm(emu);
3510 0 : destval = decode_and_fetch_word(emu);
3511 0 : destval = (*opcD1_word_operation[emu->cur_rh])
3512 0 : (emu, destval, emu->x86.R_CL);
3513 0 : write_back_word(emu, destval);
3514 : }
3515 0 : }
3516 :
3517 : /*
3518 : * REMARKS:
3519 : * Handles opcode 0xd4
3520 : */
3521 : static void
3522 0 : x86emuOp_aam(struct x86emu *emu)
3523 : {
3524 : uint8_t a;
3525 :
3526 0 : a = fetch_byte_imm(emu); /* this is a stupid encoding. */
3527 0 : if (a != 10) {
3528 : /* fix: add base decoding aam_word(uint8_t val, int base a) */
3529 0 : x86emu_halt_sys(emu);
3530 : }
3531 : /* note the type change here --- returning AL and AH in AX. */
3532 0 : emu->x86.R_AX = aam_word(emu, emu->x86.R_AL);
3533 0 : }
3534 :
3535 : /*
3536 : * REMARKS:
3537 : * Handles opcode 0xd5
3538 : */
3539 : static void
3540 0 : x86emuOp_aad(struct x86emu *emu)
3541 : {
3542 : uint8_t a;
3543 :
3544 0 : a = fetch_byte_imm(emu);
3545 0 : if (a != 10) {
3546 : /* fix: add base decoding aad_word(uint16_t val, int base a) */
3547 0 : x86emu_halt_sys(emu);
3548 : }
3549 0 : emu->x86.R_AX = aad_word(emu, emu->x86.R_AX);
3550 0 : }
3551 : /* opcode 0xd6 ILLEGAL OPCODE */
3552 :
3553 :
3554 : /*
3555 : * REMARKS:
3556 : * Handles opcode 0xd7
3557 : */
3558 : static void
3559 0 : x86emuOp_xlat(struct x86emu *emu)
3560 : {
3561 : uint16_t addr;
3562 :
3563 0 : addr = (uint16_t) (emu->x86.R_BX + (uint8_t) emu->x86.R_AL);
3564 0 : emu->x86.R_AL = fetch_data_byte(emu, addr);
3565 0 : }
3566 :
3567 : /* opcode=0xd8 */
3568 : static void
3569 0 : x86emuOp_esc_coprocess_d8(struct x86emu *emu)
3570 : {
3571 0 : }
3572 : /* opcode=0xd9 */
3573 : static void
3574 0 : x86emuOp_esc_coprocess_d9(struct x86emu *emu)
3575 : {
3576 0 : fetch_decode_modrm(emu);
3577 0 : if (emu->cur_mod != 3)
3578 0 : decode_rl_address(emu);
3579 0 : }
3580 : /* opcode=0xda */
3581 : static void
3582 0 : x86emuOp_esc_coprocess_da(struct x86emu *emu)
3583 : {
3584 0 : fetch_decode_modrm(emu);
3585 0 : if (emu->cur_mod != 3)
3586 0 : decode_rl_address(emu);
3587 0 : }
3588 : /* opcode=0xdb */
3589 : static void
3590 0 : x86emuOp_esc_coprocess_db(struct x86emu *emu)
3591 : {
3592 0 : fetch_decode_modrm(emu);
3593 0 : if (emu->cur_mod != 3)
3594 0 : decode_rl_address(emu);
3595 0 : }
3596 : /* opcode=0xdc */
3597 : static void
3598 0 : x86emuOp_esc_coprocess_dc(struct x86emu *emu)
3599 : {
3600 0 : fetch_decode_modrm(emu);
3601 0 : if (emu->cur_mod != 3)
3602 0 : decode_rl_address(emu);
3603 0 : }
3604 : /* opcode=0xdd */
3605 : static void
3606 0 : x86emuOp_esc_coprocess_dd(struct x86emu *emu)
3607 : {
3608 0 : fetch_decode_modrm(emu);
3609 0 : if (emu->cur_mod != 3)
3610 0 : decode_rl_address(emu);
3611 0 : }
3612 : /* opcode=0xde */
3613 : static void
3614 0 : x86emuOp_esc_coprocess_de(struct x86emu *emu)
3615 : {
3616 0 : fetch_decode_modrm(emu);
3617 0 : if (emu->cur_mod != 3)
3618 0 : decode_rl_address(emu);
3619 0 : }
3620 : /* opcode=0xdf */
3621 : static void
3622 0 : x86emuOp_esc_coprocess_df(struct x86emu *emu)
3623 : {
3624 0 : fetch_decode_modrm(emu);
3625 0 : if (emu->cur_mod != 3)
3626 0 : decode_rl_address(emu);
3627 0 : }
3628 :
3629 :
3630 : /*
3631 : * REMARKS:
3632 : * Handles opcode 0xe0
3633 : */
3634 : static void
3635 0 : x86emuOp_loopne(struct x86emu *emu)
3636 : {
3637 : int16_t ip;
3638 :
3639 0 : ip = (int8_t) fetch_byte_imm(emu);
3640 0 : ip += (int16_t) emu->x86.R_IP;
3641 0 : emu->x86.R_CX -= 1;
3642 0 : if (emu->x86.R_CX != 0 && !ACCESS_FLAG(F_ZF)) /* CX != 0 and !ZF */
3643 0 : emu->x86.R_IP = ip;
3644 0 : }
3645 :
3646 : /*
3647 : * REMARKS:
3648 : * Handles opcode 0xe1
3649 : */
3650 : static void
3651 0 : x86emuOp_loope(struct x86emu *emu)
3652 : {
3653 : int16_t ip;
3654 :
3655 0 : ip = (int8_t) fetch_byte_imm(emu);
3656 0 : ip += (int16_t) emu->x86.R_IP;
3657 0 : emu->x86.R_CX -= 1;
3658 0 : if (emu->x86.R_CX != 0 && ACCESS_FLAG(F_ZF)) /* CX != 0 and ZF */
3659 0 : emu->x86.R_IP = ip;
3660 0 : }
3661 :
3662 : /*
3663 : * REMARKS:
3664 : * Handles opcode 0xe2
3665 : */
3666 : static void
3667 0 : x86emuOp_loop(struct x86emu *emu)
3668 : {
3669 : int16_t ip;
3670 :
3671 0 : ip = (int8_t) fetch_byte_imm(emu);
3672 0 : ip += (int16_t) emu->x86.R_IP;
3673 0 : emu->x86.R_CX -= 1;
3674 0 : if (emu->x86.R_CX != 0)
3675 0 : emu->x86.R_IP = ip;
3676 0 : }
3677 :
3678 : /*
3679 : * REMARKS:
3680 : * Handles opcode 0xe3
3681 : */
3682 : static void
3683 0 : x86emuOp_jcxz(struct x86emu *emu)
3684 : {
3685 : uint16_t target;
3686 : int8_t offset;
3687 :
3688 : /* jump to byte offset if overflow flag is set */
3689 0 : offset = (int8_t) fetch_byte_imm(emu);
3690 0 : target = (uint16_t) (emu->x86.R_IP + offset);
3691 0 : if (emu->x86.R_CX == 0)
3692 0 : emu->x86.R_IP = target;
3693 0 : }
3694 :
3695 : /*
3696 : * REMARKS:
3697 : * Handles opcode 0xe4
3698 : */
3699 : static void
3700 0 : x86emuOp_in_byte_AL_IMM(struct x86emu *emu)
3701 : {
3702 : uint8_t port;
3703 :
3704 0 : port = (uint8_t) fetch_byte_imm(emu);
3705 0 : emu->x86.R_AL = (*emu->emu_inb) (emu, port);
3706 0 : }
3707 :
3708 : /*
3709 : * REMARKS:
3710 : * Handles opcode 0xe5
3711 : */
3712 : static void
3713 0 : x86emuOp_in_word_AX_IMM(struct x86emu *emu)
3714 : {
3715 : uint8_t port;
3716 :
3717 0 : port = (uint8_t) fetch_byte_imm(emu);
3718 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3719 0 : emu->x86.R_EAX = (*emu->emu_inl) (emu, port);
3720 0 : } else {
3721 0 : emu->x86.R_AX = (*emu->emu_inw) (emu, port);
3722 : }
3723 0 : }
3724 :
3725 : /*
3726 : * REMARKS:
3727 : * Handles opcode 0xe6
3728 : */
3729 : static void
3730 0 : x86emuOp_out_byte_IMM_AL(struct x86emu *emu)
3731 : {
3732 : uint8_t port;
3733 :
3734 0 : port = (uint8_t) fetch_byte_imm(emu);
3735 0 : (*emu->emu_outb) (emu, port, emu->x86.R_AL);
3736 0 : }
3737 :
3738 : /*
3739 : * REMARKS:
3740 : * Handles opcode 0xe7
3741 : */
3742 : static void
3743 0 : x86emuOp_out_word_IMM_AX(struct x86emu *emu)
3744 : {
3745 : uint8_t port;
3746 :
3747 0 : port = (uint8_t) fetch_byte_imm(emu);
3748 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3749 0 : (*emu->emu_outl) (emu, port, emu->x86.R_EAX);
3750 0 : } else {
3751 0 : (*emu->emu_outw) (emu, port, emu->x86.R_AX);
3752 : }
3753 0 : }
3754 :
3755 : /*
3756 : * REMARKS:
3757 : * Handles opcode 0xe8
3758 : */
3759 : static void
3760 0 : x86emuOp_call_near_IMM(struct x86emu *emu)
3761 : {
3762 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3763 : int32_t ip;
3764 0 : ip = (int32_t) fetch_long_imm(emu);
3765 0 : ip += (int32_t) emu->x86.R_EIP;
3766 0 : push_long(emu, emu->x86.R_EIP);
3767 0 : emu->x86.R_EIP = ip;
3768 0 : } else {
3769 : int16_t ip;
3770 0 : ip = (int16_t) fetch_word_imm(emu);
3771 0 : ip += (int16_t) emu->x86.R_IP; /* CHECK SIGN */
3772 0 : push_word(emu, emu->x86.R_IP);
3773 0 : emu->x86.R_IP = ip;
3774 : }
3775 0 : }
3776 :
3777 : /*
3778 : * REMARKS:
3779 : * Handles opcode 0xe9
3780 : */
3781 : static void
3782 0 : x86emuOp_jump_near_IMM(struct x86emu *emu)
3783 : {
3784 : int ip;
3785 :
3786 0 : ip = (int16_t) fetch_word_imm(emu);
3787 0 : ip += (int16_t) emu->x86.R_IP;
3788 0 : emu->x86.R_IP = (uint16_t) ip;
3789 0 : }
3790 :
3791 : /*
3792 : * REMARKS:
3793 : * Handles opcode 0xea
3794 : */
3795 : static void
3796 0 : x86emuOp_jump_far_IMM(struct x86emu *emu)
3797 : {
3798 : uint16_t cs, ip;
3799 :
3800 0 : ip = fetch_word_imm(emu);
3801 0 : cs = fetch_word_imm(emu);
3802 0 : emu->x86.R_IP = ip;
3803 0 : emu->x86.R_CS = cs;
3804 0 : }
3805 :
3806 : /*
3807 : * REMARKS:
3808 : * Handles opcode 0xeb
3809 : */
3810 : static void
3811 0 : x86emuOp_jump_byte_IMM(struct x86emu *emu)
3812 : {
3813 : uint16_t target;
3814 : int8_t offset;
3815 :
3816 0 : offset = (int8_t) fetch_byte_imm(emu);
3817 0 : target = (uint16_t) (emu->x86.R_IP + offset);
3818 0 : emu->x86.R_IP = target;
3819 0 : }
3820 :
3821 : /*
3822 : * REMARKS:
3823 : * Handles opcode 0xec
3824 : */
3825 : static void
3826 0 : x86emuOp_in_byte_AL_DX(struct x86emu *emu)
3827 : {
3828 0 : emu->x86.R_AL = (*emu->emu_inb) (emu, emu->x86.R_DX);
3829 0 : }
3830 :
3831 : /*
3832 : * REMARKS:
3833 : * Handles opcode 0xed
3834 : */
3835 : static void
3836 0 : x86emuOp_in_word_AX_DX(struct x86emu *emu)
3837 : {
3838 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3839 0 : emu->x86.R_EAX = (*emu->emu_inl) (emu, emu->x86.R_DX);
3840 0 : } else {
3841 0 : emu->x86.R_AX = (*emu->emu_inw) (emu, emu->x86.R_DX);
3842 : }
3843 0 : }
3844 :
3845 : /*
3846 : * REMARKS:
3847 : * Handles opcode 0xee
3848 : */
3849 : static void
3850 0 : x86emuOp_out_byte_DX_AL(struct x86emu *emu)
3851 : {
3852 0 : (*emu->emu_outb) (emu, emu->x86.R_DX, emu->x86.R_AL);
3853 0 : }
3854 :
3855 : /*
3856 : * REMARKS:
3857 : * Handles opcode 0xef
3858 : */
3859 : static void
3860 0 : x86emuOp_out_word_DX_AX(struct x86emu *emu)
3861 : {
3862 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
3863 0 : (*emu->emu_outl) (emu, emu->x86.R_DX, emu->x86.R_EAX);
3864 0 : } else {
3865 0 : (*emu->emu_outw) (emu, emu->x86.R_DX, emu->x86.R_AX);
3866 : }
3867 0 : }
3868 :
3869 : /*
3870 : * REMARKS:
3871 : * Handles opcode 0xf0
3872 : */
3873 : static void
3874 0 : x86emuOp_lock(struct x86emu *emu)
3875 : {
3876 0 : }
3877 : /*opcode 0xf1 ILLEGAL OPERATION */
3878 :
3879 :
3880 : /*
3881 : * REMARKS:
3882 : * Handles opcode 0xf5
3883 : */
3884 : static void
3885 0 : x86emuOp_cmc(struct x86emu *emu)
3886 : {
3887 0 : if (ACCESS_FLAG(F_CF))
3888 0 : CLEAR_FLAG(F_CF);
3889 : else
3890 0 : SET_FLAG(F_CF);
3891 0 : }
3892 :
3893 : /*
3894 : * REMARKS:
3895 : * Handles opcode 0xf6
3896 : */
3897 : static void
3898 0 : x86emuOp_opcF6_byte_RM(struct x86emu *emu)
3899 : {
3900 0 : uint8_t destval, srcval;
3901 :
3902 : /* long, drawn out code follows. Double switch for a total of 32
3903 : * cases. */
3904 0 : fetch_decode_modrm(emu);
3905 0 : if (emu->cur_rh == 1)
3906 0 : x86emu_halt_sys(emu);
3907 :
3908 0 : if (emu->cur_rh == 0) {
3909 0 : destval = decode_and_fetch_byte_imm8(emu, &srcval);
3910 0 : test_byte(emu, destval, srcval);
3911 0 : return;
3912 : }
3913 0 : destval = decode_and_fetch_byte(emu);
3914 0 : switch (emu->cur_rh) {
3915 : case 2:
3916 0 : destval = ~destval;
3917 0 : write_back_byte(emu, destval);
3918 0 : break;
3919 : case 3:
3920 0 : destval = neg_byte(emu, destval);
3921 0 : write_back_byte(emu, destval);
3922 0 : break;
3923 : case 4:
3924 0 : mul_byte(emu, destval);
3925 0 : break;
3926 : case 5:
3927 0 : imul_byte(emu, destval);
3928 0 : break;
3929 : case 6:
3930 0 : div_byte(emu, destval);
3931 0 : break;
3932 : case 7:
3933 0 : idiv_byte(emu, destval);
3934 0 : break;
3935 : }
3936 0 : }
3937 :
3938 : /*
3939 : * REMARKS:
3940 : * Handles opcode 0xf7
3941 : */
3942 : static void
3943 0 : x86emuOp32_opcF7_word_RM(struct x86emu *emu)
3944 : {
3945 : uint32_t destval, srcval;
3946 :
3947 : /* long, drawn out code follows. Double switch for a total of 32
3948 : * cases. */
3949 0 : fetch_decode_modrm(emu);
3950 0 : if (emu->cur_rh == 1)
3951 0 : x86emu_halt_sys(emu);
3952 :
3953 0 : if (emu->cur_rh == 0) {
3954 0 : if (emu->cur_mod != 3) {
3955 : uint32_t destoffset;
3956 :
3957 0 : destoffset = decode_rl_address(emu);
3958 0 : srcval = fetch_long_imm(emu);
3959 0 : destval = fetch_data_long(emu, destoffset);
3960 0 : } else {
3961 0 : srcval = fetch_long_imm(emu);
3962 0 : destval = *decode_rl_long_register(emu);
3963 : }
3964 0 : test_long(emu, destval, srcval);
3965 0 : return;
3966 : }
3967 0 : destval = decode_and_fetch_long(emu);
3968 0 : switch (emu->cur_rh) {
3969 : case 2:
3970 0 : destval = ~destval;
3971 0 : write_back_long(emu, destval);
3972 0 : break;
3973 : case 3:
3974 0 : destval = neg_long(emu, destval);
3975 0 : write_back_long(emu, destval);
3976 0 : break;
3977 : case 4:
3978 0 : mul_long(emu, destval);
3979 0 : break;
3980 : case 5:
3981 0 : imul_long(emu, destval);
3982 0 : break;
3983 : case 6:
3984 0 : div_long(emu, destval);
3985 0 : break;
3986 : case 7:
3987 0 : idiv_long(emu, destval);
3988 0 : break;
3989 : }
3990 0 : }
3991 : static void
3992 0 : x86emuOp16_opcF7_word_RM(struct x86emu *emu)
3993 : {
3994 : uint16_t destval, srcval;
3995 :
3996 : /* long, drawn out code follows. Double switch for a total of 32
3997 : * cases. */
3998 0 : fetch_decode_modrm(emu);
3999 0 : if (emu->cur_rh == 1)
4000 0 : x86emu_halt_sys(emu);
4001 :
4002 0 : if (emu->cur_rh == 0) {
4003 0 : if (emu->cur_mod != 3) {
4004 : uint32_t destoffset;
4005 :
4006 0 : destoffset = decode_rl_address(emu);
4007 0 : srcval = fetch_word_imm(emu);
4008 0 : destval = fetch_data_word(emu, destoffset);
4009 0 : } else {
4010 0 : srcval = fetch_word_imm(emu);
4011 0 : destval = *decode_rl_word_register(emu);
4012 : }
4013 0 : test_word(emu, destval, srcval);
4014 0 : return;
4015 : }
4016 0 : destval = decode_and_fetch_word(emu);
4017 0 : switch (emu->cur_rh) {
4018 : case 2:
4019 0 : destval = ~destval;
4020 0 : write_back_word(emu, destval);
4021 0 : break;
4022 : case 3:
4023 0 : destval = neg_word(emu, destval);
4024 0 : write_back_word(emu, destval);
4025 0 : break;
4026 : case 4:
4027 0 : mul_word(emu, destval);
4028 0 : break;
4029 : case 5:
4030 0 : imul_word(emu, destval);
4031 0 : break;
4032 : case 6:
4033 0 : div_word(emu, destval);
4034 0 : break;
4035 : case 7:
4036 0 : idiv_word(emu, destval);
4037 0 : break;
4038 : }
4039 0 : }
4040 : static void
4041 0 : x86emuOp_opcF7_word_RM(struct x86emu *emu)
4042 : {
4043 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4044 0 : x86emuOp32_opcF7_word_RM(emu);
4045 : else
4046 0 : x86emuOp16_opcF7_word_RM(emu);
4047 0 : }
4048 :
4049 : /*
4050 : * REMARKS:
4051 : * Handles opcode 0xfe
4052 : */
4053 : static void
4054 0 : x86emuOp_opcFE_byte_RM(struct x86emu *emu)
4055 : {
4056 : uint8_t destval;
4057 : uint32_t destoffset;
4058 : uint8_t *destreg;
4059 :
4060 : /* Yet another special case instruction. */
4061 0 : fetch_decode_modrm(emu);
4062 0 : if (emu->cur_mod != 3) {
4063 0 : destoffset = decode_rl_address(emu);
4064 0 : switch (emu->cur_rh) {
4065 : case 0: /* inc word ptr ... */
4066 0 : destval = fetch_data_byte(emu, destoffset);
4067 0 : destval = inc_byte(emu, destval);
4068 0 : store_data_byte(emu, destoffset, destval);
4069 0 : break;
4070 : case 1: /* dec word ptr ... */
4071 0 : destval = fetch_data_byte(emu, destoffset);
4072 0 : destval = dec_byte(emu, destval);
4073 0 : store_data_byte(emu, destoffset, destval);
4074 0 : break;
4075 : }
4076 : } else {
4077 0 : destreg = decode_rl_byte_register(emu);
4078 0 : switch (emu->cur_rh) {
4079 : case 0:
4080 0 : *destreg = inc_byte(emu, *destreg);
4081 0 : break;
4082 : case 1:
4083 0 : *destreg = dec_byte(emu, *destreg);
4084 0 : break;
4085 : }
4086 : }
4087 0 : }
4088 :
4089 : /*
4090 : * REMARKS:
4091 : * Handles opcode 0xff
4092 : */
4093 : static void
4094 0 : x86emuOp32_opcFF_word_RM(struct x86emu *emu)
4095 : {
4096 : uint32_t destoffset = 0;
4097 : uint32_t destval, *destreg;
4098 :
4099 0 : if (emu->cur_mod != 3) {
4100 0 : destoffset = decode_rl_address(emu);
4101 0 : destval = fetch_data_long(emu, destoffset);
4102 0 : switch (emu->cur_rh) {
4103 : case 0: /* inc word ptr ... */
4104 0 : destval = inc_long(emu, destval);
4105 0 : store_data_long(emu, destoffset, destval);
4106 0 : break;
4107 : case 1: /* dec word ptr ... */
4108 0 : destval = dec_long(emu, destval);
4109 0 : store_data_long(emu, destoffset, destval);
4110 0 : break;
4111 : case 6: /* push word ptr ... */
4112 0 : push_long(emu, destval);
4113 0 : break;
4114 : }
4115 : } else {
4116 0 : destreg = decode_rl_long_register(emu);
4117 0 : switch (emu->cur_rh) {
4118 : case 0:
4119 0 : *destreg = inc_long(emu, *destreg);
4120 0 : break;
4121 : case 1:
4122 0 : *destreg = dec_long(emu, *destreg);
4123 0 : break;
4124 : case 6:
4125 0 : push_long(emu, *destreg);
4126 0 : break;
4127 : }
4128 : }
4129 0 : }
4130 :
4131 : static void
4132 0 : x86emuOp16_opcFF_word_RM(struct x86emu *emu)
4133 : {
4134 : uint32_t destoffset = 0;
4135 : uint16_t *destreg;
4136 : uint16_t destval;
4137 :
4138 0 : if (emu->cur_mod != 3) {
4139 0 : destoffset = decode_rl_address(emu);
4140 0 : destval = fetch_data_word(emu, destoffset);
4141 0 : switch (emu->cur_rh) {
4142 : case 0:
4143 0 : destval = inc_word(emu, destval);
4144 0 : store_data_word(emu, destoffset, destval);
4145 0 : break;
4146 : case 1: /* dec word ptr ... */
4147 0 : destval = dec_word(emu, destval);
4148 0 : store_data_word(emu, destoffset, destval);
4149 0 : break;
4150 : case 6: /* push word ptr ... */
4151 0 : push_word(emu, destval);
4152 0 : break;
4153 : }
4154 : } else {
4155 0 : destreg = decode_rl_word_register(emu);
4156 0 : switch (emu->cur_rh) {
4157 : case 0:
4158 0 : *destreg = inc_word(emu, *destreg);
4159 0 : break;
4160 : case 1:
4161 0 : *destreg = dec_word(emu, *destreg);
4162 0 : break;
4163 : case 6:
4164 0 : push_word(emu, *destreg);
4165 0 : break;
4166 : }
4167 : }
4168 0 : }
4169 :
4170 : static void
4171 0 : x86emuOp_opcFF_word_RM(struct x86emu *emu)
4172 : {
4173 : uint32_t destoffset = 0;
4174 : uint16_t destval, destval2;
4175 :
4176 : /* Yet another special case instruction. */
4177 0 : fetch_decode_modrm(emu);
4178 0 : if ((emu->cur_mod == 3 && (emu->cur_rh == 3 || emu->cur_rh == 5)) ||
4179 0 : emu->cur_rh == 7)
4180 0 : x86emu_halt_sys(emu);
4181 0 : if (emu->cur_rh == 0 || emu->cur_rh == 1 || emu->cur_rh == 6) {
4182 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
4183 0 : x86emuOp32_opcFF_word_RM(emu);
4184 : else
4185 0 : x86emuOp16_opcFF_word_RM(emu);
4186 0 : return;
4187 : }
4188 :
4189 0 : if (emu->cur_mod != 3) {
4190 0 : destoffset = decode_rl_address(emu);
4191 0 : destval = fetch_data_word(emu, destoffset);
4192 0 : switch (emu->cur_rh) {
4193 : case 3: /* call far ptr ... */
4194 0 : destval2 = fetch_data_word(emu, destoffset + 2);
4195 0 : push_word(emu, emu->x86.R_CS);
4196 0 : emu->x86.R_CS = destval2;
4197 0 : push_word(emu, emu->x86.R_IP);
4198 0 : emu->x86.R_IP = destval;
4199 0 : break;
4200 : case 5: /* jmp far ptr ... */
4201 0 : destval2 = fetch_data_word(emu, destoffset + 2);
4202 0 : emu->x86.R_IP = destval;
4203 0 : emu->x86.R_CS = destval2;
4204 0 : break;
4205 : }
4206 : } else {
4207 0 : destval = *decode_rl_word_register(emu);
4208 : }
4209 :
4210 0 : switch (emu->cur_rh) {
4211 : case 2: /* call word ptr */
4212 0 : push_word(emu, emu->x86.R_IP);
4213 0 : emu->x86.R_IP = destval;
4214 0 : break;
4215 : case 4: /* jmp */
4216 0 : emu->x86.R_IP = destval;
4217 0 : break;
4218 : }
4219 0 : }
4220 :
4221 : /*
4222 : * * Single byte operation code table:
4223 : */
4224 : static void
4225 0 : x86emu_exec_one_byte(struct x86emu * emu)
4226 : {
4227 : uint8_t op1;
4228 :
4229 0 : op1 = fetch_byte_imm(emu);
4230 :
4231 0 : switch (op1) {
4232 : case 0x00:
4233 0 : common_binop_byte_rm_r(emu, add_byte);
4234 0 : break;
4235 : case 0x01:
4236 0 : common_binop_word_long_rm_r(emu, add_word, add_long);
4237 0 : break;
4238 : case 0x02:
4239 0 : common_binop_byte_r_rm(emu, add_byte);
4240 0 : break;
4241 : case 0x03:
4242 0 : common_binop_word_long_r_rm(emu, add_word, add_long);
4243 0 : break;
4244 : case 0x04:
4245 0 : common_binop_byte_imm(emu, add_byte);
4246 0 : break;
4247 : case 0x05:
4248 0 : common_binop_word_long_imm(emu, add_word, add_long);
4249 0 : break;
4250 : case 0x06:
4251 0 : push_word(emu, emu->x86.R_ES);
4252 0 : break;
4253 : case 0x07:
4254 0 : emu->x86.R_ES = pop_word(emu);
4255 0 : break;
4256 :
4257 : case 0x08:
4258 0 : common_binop_byte_rm_r(emu, or_byte);
4259 0 : break;
4260 : case 0x09:
4261 0 : common_binop_word_long_rm_r(emu, or_word, or_long);
4262 0 : break;
4263 : case 0x0a:
4264 0 : common_binop_byte_r_rm(emu, or_byte);
4265 0 : break;
4266 : case 0x0b:
4267 0 : common_binop_word_long_r_rm(emu, or_word, or_long);
4268 0 : break;
4269 : case 0x0c:
4270 0 : common_binop_byte_imm(emu, or_byte);
4271 0 : break;
4272 : case 0x0d:
4273 0 : common_binop_word_long_imm(emu, or_word, or_long);
4274 0 : break;
4275 : case 0x0e:
4276 0 : push_word(emu, emu->x86.R_CS);
4277 0 : break;
4278 : case 0x0f:
4279 0 : x86emu_exec_two_byte(emu);
4280 0 : break;
4281 :
4282 : case 0x10:
4283 0 : common_binop_byte_rm_r(emu, adc_byte);
4284 0 : break;
4285 : case 0x11:
4286 0 : common_binop_word_long_rm_r(emu, adc_word, adc_long);
4287 0 : break;
4288 : case 0x12:
4289 0 : common_binop_byte_r_rm(emu, adc_byte);
4290 0 : break;
4291 : case 0x13:
4292 0 : common_binop_word_long_r_rm(emu, adc_word, adc_long);
4293 0 : break;
4294 : case 0x14:
4295 0 : common_binop_byte_imm(emu, adc_byte);
4296 0 : break;
4297 : case 0x15:
4298 0 : common_binop_word_long_imm(emu, adc_word, adc_long);
4299 0 : break;
4300 : case 0x16:
4301 0 : push_word(emu, emu->x86.R_SS);
4302 0 : break;
4303 : case 0x17:
4304 0 : emu->x86.R_SS = pop_word(emu);
4305 0 : break;
4306 :
4307 : case 0x18:
4308 0 : common_binop_byte_rm_r(emu, sbb_byte);
4309 0 : break;
4310 : case 0x19:
4311 0 : common_binop_word_long_rm_r(emu, sbb_word, sbb_long);
4312 0 : break;
4313 : case 0x1a:
4314 0 : common_binop_byte_r_rm(emu, sbb_byte);
4315 0 : break;
4316 : case 0x1b:
4317 0 : common_binop_word_long_r_rm(emu, sbb_word, sbb_long);
4318 0 : break;
4319 : case 0x1c:
4320 0 : common_binop_byte_imm(emu, sbb_byte);
4321 0 : break;
4322 : case 0x1d:
4323 0 : common_binop_word_long_imm(emu, sbb_word, sbb_long);
4324 0 : break;
4325 : case 0x1e:
4326 0 : push_word(emu, emu->x86.R_DS);
4327 0 : break;
4328 : case 0x1f:
4329 0 : emu->x86.R_DS = pop_word(emu);
4330 0 : break;
4331 :
4332 : case 0x20:
4333 0 : common_binop_byte_rm_r(emu, and_byte);
4334 0 : break;
4335 : case 0x21:
4336 0 : common_binop_word_long_rm_r(emu, and_word, and_long);
4337 0 : break;
4338 : case 0x22:
4339 0 : common_binop_byte_r_rm(emu, and_byte);
4340 0 : break;
4341 : case 0x23:
4342 0 : common_binop_word_long_r_rm(emu, and_word, and_long);
4343 0 : break;
4344 : case 0x24:
4345 0 : common_binop_byte_imm(emu, and_byte);
4346 0 : break;
4347 : case 0x25:
4348 0 : common_binop_word_long_imm(emu, and_word, and_long);
4349 0 : break;
4350 : case 0x26:
4351 0 : emu->x86.mode |= SYSMODE_SEGOVR_ES;
4352 0 : break;
4353 : case 0x27:
4354 0 : emu->x86.R_AL = daa_byte(emu, emu->x86.R_AL);
4355 0 : break;
4356 :
4357 : case 0x28:
4358 0 : common_binop_byte_rm_r(emu, sub_byte);
4359 0 : break;
4360 : case 0x29:
4361 0 : common_binop_word_long_rm_r(emu, sub_word, sub_long);
4362 0 : break;
4363 : case 0x2a:
4364 0 : common_binop_byte_r_rm(emu, sub_byte);
4365 0 : break;
4366 : case 0x2b:
4367 0 : common_binop_word_long_r_rm(emu, sub_word, sub_long);
4368 0 : break;
4369 : case 0x2c:
4370 0 : common_binop_byte_imm(emu, sub_byte);
4371 0 : break;
4372 : case 0x2d:
4373 0 : common_binop_word_long_imm(emu, sub_word, sub_long);
4374 0 : break;
4375 : case 0x2e:
4376 0 : emu->x86.mode |= SYSMODE_SEGOVR_CS;
4377 0 : break;
4378 : case 0x2f:
4379 0 : emu->x86.R_AL = das_byte(emu, emu->x86.R_AL);
4380 0 : break;
4381 :
4382 : case 0x30:
4383 0 : common_binop_byte_rm_r(emu, xor_byte);
4384 0 : break;
4385 : case 0x31:
4386 0 : common_binop_word_long_rm_r(emu, xor_word, xor_long);
4387 0 : break;
4388 : case 0x32:
4389 0 : common_binop_byte_r_rm(emu, xor_byte);
4390 0 : break;
4391 : case 0x33:
4392 0 : common_binop_word_long_r_rm(emu, xor_word, xor_long);
4393 0 : break;
4394 : case 0x34:
4395 0 : common_binop_byte_imm(emu, xor_byte);
4396 0 : break;
4397 : case 0x35:
4398 0 : common_binop_word_long_imm(emu, xor_word, xor_long);
4399 0 : break;
4400 : case 0x36:
4401 0 : emu->x86.mode |= SYSMODE_SEGOVR_SS;
4402 0 : break;
4403 : case 0x37:
4404 0 : emu->x86.R_AX = aaa_word(emu, emu->x86.R_AX);
4405 0 : break;
4406 :
4407 : case 0x38:
4408 0 : common_binop_ns_byte_rm_r(emu, cmp_byte_no_return);
4409 0 : break;
4410 : case 0x39:
4411 0 : common_binop_ns_word_long_rm_r(emu, cmp_word_no_return,
4412 : cmp_long_no_return);
4413 0 : break;
4414 : case 0x3a:
4415 0 : x86emuOp_cmp_byte_R_RM(emu);
4416 0 : break;
4417 : case 0x3b:
4418 0 : x86emuOp_cmp_word_R_RM(emu);
4419 0 : break;
4420 : case 0x3c:
4421 0 : x86emuOp_cmp_byte_AL_IMM(emu);
4422 0 : break;
4423 : case 0x3d:
4424 0 : x86emuOp_cmp_word_AX_IMM(emu);
4425 0 : break;
4426 : case 0x3e:
4427 0 : emu->x86.mode |= SYSMODE_SEGOVR_DS;
4428 0 : break;
4429 : case 0x3f:
4430 0 : emu->x86.R_AX = aas_word(emu, emu->x86.R_AX);
4431 0 : break;
4432 :
4433 : case 0x40:
4434 0 : common_inc_word_long(emu, &emu->x86.register_a);
4435 0 : break;
4436 : case 0x41:
4437 0 : common_inc_word_long(emu, &emu->x86.register_c);
4438 0 : break;
4439 : case 0x42:
4440 0 : common_inc_word_long(emu, &emu->x86.register_d);
4441 0 : break;
4442 : case 0x43:
4443 0 : common_inc_word_long(emu, &emu->x86.register_b);
4444 0 : break;
4445 : case 0x44:
4446 0 : common_inc_word_long(emu, &emu->x86.register_sp);
4447 0 : break;
4448 : case 0x45:
4449 0 : common_inc_word_long(emu, &emu->x86.register_bp);
4450 0 : break;
4451 : case 0x46:
4452 0 : common_inc_word_long(emu, &emu->x86.register_si);
4453 0 : break;
4454 : case 0x47:
4455 0 : common_inc_word_long(emu, &emu->x86.register_di);
4456 0 : break;
4457 :
4458 : case 0x48:
4459 0 : common_dec_word_long(emu, &emu->x86.register_a);
4460 0 : break;
4461 : case 0x49:
4462 0 : common_dec_word_long(emu, &emu->x86.register_c);
4463 0 : break;
4464 : case 0x4a:
4465 0 : common_dec_word_long(emu, &emu->x86.register_d);
4466 0 : break;
4467 : case 0x4b:
4468 0 : common_dec_word_long(emu, &emu->x86.register_b);
4469 0 : break;
4470 : case 0x4c:
4471 0 : common_dec_word_long(emu, &emu->x86.register_sp);
4472 0 : break;
4473 : case 0x4d:
4474 0 : common_dec_word_long(emu, &emu->x86.register_bp);
4475 0 : break;
4476 : case 0x4e:
4477 0 : common_dec_word_long(emu, &emu->x86.register_si);
4478 0 : break;
4479 : case 0x4f:
4480 0 : common_dec_word_long(emu, &emu->x86.register_di);
4481 0 : break;
4482 :
4483 : case 0x50:
4484 0 : common_push_word_long(emu, &emu->x86.register_a);
4485 0 : break;
4486 : case 0x51:
4487 0 : common_push_word_long(emu, &emu->x86.register_c);
4488 0 : break;
4489 : case 0x52:
4490 0 : common_push_word_long(emu, &emu->x86.register_d);
4491 0 : break;
4492 : case 0x53:
4493 0 : common_push_word_long(emu, &emu->x86.register_b);
4494 0 : break;
4495 : case 0x54:
4496 0 : common_push_word_long(emu, &emu->x86.register_sp);
4497 0 : break;
4498 : case 0x55:
4499 0 : common_push_word_long(emu, &emu->x86.register_bp);
4500 0 : break;
4501 : case 0x56:
4502 0 : common_push_word_long(emu, &emu->x86.register_si);
4503 0 : break;
4504 : case 0x57:
4505 0 : common_push_word_long(emu, &emu->x86.register_di);
4506 0 : break;
4507 :
4508 : case 0x58:
4509 0 : common_pop_word_long(emu, &emu->x86.register_a);
4510 0 : break;
4511 : case 0x59:
4512 0 : common_pop_word_long(emu, &emu->x86.register_c);
4513 0 : break;
4514 : case 0x5a:
4515 0 : common_pop_word_long(emu, &emu->x86.register_d);
4516 0 : break;
4517 : case 0x5b:
4518 0 : common_pop_word_long(emu, &emu->x86.register_b);
4519 0 : break;
4520 : case 0x5c:
4521 0 : common_pop_word_long(emu, &emu->x86.register_sp);
4522 0 : break;
4523 : case 0x5d:
4524 0 : common_pop_word_long(emu, &emu->x86.register_bp);
4525 0 : break;
4526 : case 0x5e:
4527 0 : common_pop_word_long(emu, &emu->x86.register_si);
4528 0 : break;
4529 : case 0x5f:
4530 0 : common_pop_word_long(emu, &emu->x86.register_di);
4531 0 : break;
4532 :
4533 : case 0x60:
4534 0 : x86emuOp_push_all(emu);
4535 0 : break;
4536 : case 0x61:
4537 0 : x86emuOp_pop_all(emu);
4538 0 : break;
4539 : /* 0x62 bound */
4540 : /* 0x63 arpl */
4541 : case 0x64:
4542 0 : emu->x86.mode |= SYSMODE_SEGOVR_FS;
4543 0 : break;
4544 : case 0x65:
4545 0 : emu->x86.mode |= SYSMODE_SEGOVR_GS;
4546 0 : break;
4547 : case 0x66:
4548 0 : emu->x86.mode |= SYSMODE_PREFIX_DATA;
4549 0 : break;
4550 : case 0x67:
4551 0 : emu->x86.mode |= SYSMODE_PREFIX_ADDR;
4552 0 : break;
4553 :
4554 : case 0x68:
4555 0 : x86emuOp_push_word_IMM(emu);
4556 0 : break;
4557 : case 0x69:
4558 0 : common_imul_imm(emu, 0);
4559 0 : break;
4560 : case 0x6a:
4561 0 : x86emuOp_push_byte_IMM(emu);
4562 0 : break;
4563 : case 0x6b:
4564 0 : common_imul_imm(emu, 1);
4565 0 : break;
4566 : case 0x6c:
4567 0 : ins(emu, 1);
4568 0 : break;
4569 : case 0x6d:
4570 0 : x86emuOp_ins_word(emu);
4571 0 : break;
4572 : case 0x6e:
4573 0 : outs(emu, 1);
4574 0 : break;
4575 : case 0x6f:
4576 0 : x86emuOp_outs_word(emu);
4577 0 : break;
4578 :
4579 : case 0x70:
4580 0 : common_jmp_near(emu, ACCESS_FLAG(F_OF));
4581 0 : break;
4582 : case 0x71:
4583 0 : common_jmp_near(emu, !ACCESS_FLAG(F_OF));
4584 0 : break;
4585 : case 0x72:
4586 0 : common_jmp_near(emu, ACCESS_FLAG(F_CF));
4587 0 : break;
4588 : case 0x73:
4589 0 : common_jmp_near(emu, !ACCESS_FLAG(F_CF));
4590 0 : break;
4591 : case 0x74:
4592 0 : common_jmp_near(emu, ACCESS_FLAG(F_ZF));
4593 0 : break;
4594 : case 0x75:
4595 0 : common_jmp_near(emu, !ACCESS_FLAG(F_ZF));
4596 0 : break;
4597 : case 0x76:
4598 0 : common_jmp_near(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
4599 0 : break;
4600 : case 0x77:
4601 0 : common_jmp_near(emu, !ACCESS_FLAG(F_CF) && !ACCESS_FLAG(F_ZF));
4602 0 : break;
4603 :
4604 : case 0x78:
4605 0 : common_jmp_near(emu, ACCESS_FLAG(F_SF));
4606 0 : break;
4607 : case 0x79:
4608 0 : common_jmp_near(emu, !ACCESS_FLAG(F_SF));
4609 0 : break;
4610 : case 0x7a:
4611 0 : common_jmp_near(emu, ACCESS_FLAG(F_PF));
4612 0 : break;
4613 : case 0x7b:
4614 0 : common_jmp_near(emu, !ACCESS_FLAG(F_PF));
4615 0 : break;
4616 : case 0x7c:
4617 0 : x86emuOp_jump_near_L(emu);
4618 0 : break;
4619 : case 0x7d:
4620 0 : x86emuOp_jump_near_NL(emu);
4621 0 : break;
4622 : case 0x7e:
4623 0 : x86emuOp_jump_near_LE(emu);
4624 0 : break;
4625 : case 0x7f:
4626 0 : x86emuOp_jump_near_NLE(emu);
4627 0 : break;
4628 :
4629 : case 0x80:
4630 0 : x86emuOp_opc80_byte_RM_IMM(emu);
4631 0 : break;
4632 : case 0x81:
4633 0 : x86emuOp_opc81_word_RM_IMM(emu);
4634 0 : break;
4635 : case 0x82:
4636 0 : x86emuOp_opc82_byte_RM_IMM(emu);
4637 0 : break;
4638 : case 0x83:
4639 0 : x86emuOp_opc83_word_RM_IMM(emu);
4640 0 : break;
4641 : case 0x84:
4642 0 : common_binop_ns_byte_rm_r(emu, test_byte);
4643 0 : break;
4644 : case 0x85:
4645 0 : common_binop_ns_word_long_rm_r(emu, test_word, test_long);
4646 0 : break;
4647 : case 0x86:
4648 0 : x86emuOp_xchg_byte_RM_R(emu);
4649 0 : break;
4650 : case 0x87:
4651 0 : x86emuOp_xchg_word_RM_R(emu);
4652 0 : break;
4653 :
4654 : case 0x88:
4655 0 : x86emuOp_mov_byte_RM_R(emu);
4656 0 : break;
4657 : case 0x89:
4658 0 : x86emuOp_mov_word_RM_R(emu);
4659 0 : break;
4660 : case 0x8a:
4661 0 : x86emuOp_mov_byte_R_RM(emu);
4662 0 : break;
4663 : case 0x8b:
4664 0 : x86emuOp_mov_word_R_RM(emu);
4665 0 : break;
4666 : case 0x8c:
4667 0 : x86emuOp_mov_word_RM_SR(emu);
4668 0 : break;
4669 : case 0x8d:
4670 0 : x86emuOp_lea_word_R_M(emu);
4671 0 : break;
4672 : case 0x8e:
4673 0 : x86emuOp_mov_word_SR_RM(emu);
4674 0 : break;
4675 : case 0x8f:
4676 0 : x86emuOp_pop_RM(emu);
4677 0 : break;
4678 :
4679 : case 0x90:
4680 : /* nop */
4681 : break;
4682 : case 0x91:
4683 0 : x86emuOp_xchg_word_AX_CX(emu);
4684 0 : break;
4685 : case 0x92:
4686 0 : x86emuOp_xchg_word_AX_DX(emu);
4687 0 : break;
4688 : case 0x93:
4689 0 : x86emuOp_xchg_word_AX_BX(emu);
4690 0 : break;
4691 : case 0x94:
4692 0 : x86emuOp_xchg_word_AX_SP(emu);
4693 0 : break;
4694 : case 0x95:
4695 0 : x86emuOp_xchg_word_AX_BP(emu);
4696 0 : break;
4697 : case 0x96:
4698 0 : x86emuOp_xchg_word_AX_SI(emu);
4699 0 : break;
4700 : case 0x97:
4701 0 : x86emuOp_xchg_word_AX_DI(emu);
4702 0 : break;
4703 :
4704 : case 0x98:
4705 0 : x86emuOp_cbw(emu);
4706 0 : break;
4707 : case 0x99:
4708 0 : x86emuOp_cwd(emu);
4709 0 : break;
4710 : case 0x9a:
4711 0 : x86emuOp_call_far_IMM(emu);
4712 0 : break;
4713 : case 0x9b:
4714 : /* wait */
4715 : break;
4716 : case 0x9c:
4717 0 : x86emuOp_pushf_word(emu);
4718 0 : break;
4719 : case 0x9d:
4720 0 : x86emuOp_popf_word(emu);
4721 0 : break;
4722 : case 0x9e:
4723 0 : x86emuOp_sahf(emu);
4724 0 : break;
4725 : case 0x9f:
4726 0 : x86emuOp_lahf(emu);
4727 0 : break;
4728 :
4729 : case 0xa0:
4730 0 : x86emuOp_mov_AL_M_IMM(emu);
4731 0 : break;
4732 : case 0xa1:
4733 0 : x86emuOp_mov_AX_M_IMM(emu);
4734 0 : break;
4735 : case 0xa2:
4736 0 : x86emuOp_mov_M_AL_IMM(emu);
4737 0 : break;
4738 : case 0xa3:
4739 0 : x86emuOp_mov_M_AX_IMM(emu);
4740 0 : break;
4741 : case 0xa4:
4742 0 : x86emuOp_movs_byte(emu);
4743 0 : break;
4744 : case 0xa5:
4745 0 : x86emuOp_movs_word(emu);
4746 0 : break;
4747 : case 0xa6:
4748 0 : x86emuOp_cmps_byte(emu);
4749 0 : break;
4750 : case 0xa7:
4751 0 : x86emuOp_cmps_word(emu);
4752 0 : break;
4753 :
4754 : case 0xa8:
4755 0 : test_byte(emu, emu->x86.R_AL, fetch_byte_imm(emu));
4756 0 : break;
4757 : case 0xa9:
4758 0 : x86emuOp_test_AX_IMM(emu);
4759 0 : break;
4760 : case 0xaa:
4761 0 : x86emuOp_stos_byte(emu);
4762 0 : break;
4763 : case 0xab:
4764 0 : x86emuOp_stos_word(emu);
4765 0 : break;
4766 : case 0xac:
4767 0 : x86emuOp_lods_byte(emu);
4768 0 : break;
4769 : case 0xad:
4770 0 : x86emuOp_lods_word(emu);
4771 0 : break;
4772 : case 0xae:
4773 0 : x86emuOp_scas_byte(emu);
4774 0 : break;
4775 : case 0xaf:
4776 0 : x86emuOp_scas_word(emu);
4777 0 : break;
4778 :
4779 : case 0xb0:
4780 0 : emu->x86.R_AL = fetch_byte_imm(emu);
4781 0 : break;
4782 : case 0xb1:
4783 0 : emu->x86.R_CL = fetch_byte_imm(emu);
4784 0 : break;
4785 : case 0xb2:
4786 0 : emu->x86.R_DL = fetch_byte_imm(emu);
4787 0 : break;
4788 : case 0xb3:
4789 0 : emu->x86.R_BL = fetch_byte_imm(emu);
4790 0 : break;
4791 : case 0xb4:
4792 0 : emu->x86.R_AH = fetch_byte_imm(emu);
4793 0 : break;
4794 : case 0xb5:
4795 0 : emu->x86.R_CH = fetch_byte_imm(emu);
4796 0 : break;
4797 : case 0xb6:
4798 0 : emu->x86.R_DH = fetch_byte_imm(emu);
4799 0 : break;
4800 : case 0xb7:
4801 0 : emu->x86.R_BH = fetch_byte_imm(emu);
4802 0 : break;
4803 :
4804 : case 0xb8:
4805 0 : x86emuOp_mov_word_AX_IMM(emu);
4806 0 : break;
4807 : case 0xb9:
4808 0 : x86emuOp_mov_word_CX_IMM(emu);
4809 0 : break;
4810 : case 0xba:
4811 0 : x86emuOp_mov_word_DX_IMM(emu);
4812 0 : break;
4813 : case 0xbb:
4814 0 : x86emuOp_mov_word_BX_IMM(emu);
4815 0 : break;
4816 : case 0xbc:
4817 :
4818 0 : x86emuOp_mov_word_SP_IMM(emu);
4819 0 : break;
4820 : case 0xbd:
4821 0 : x86emuOp_mov_word_BP_IMM(emu);
4822 0 : break;
4823 : case 0xbe:
4824 0 : x86emuOp_mov_word_SI_IMM(emu);
4825 0 : break;
4826 : case 0xbf:
4827 0 : x86emuOp_mov_word_DI_IMM(emu);
4828 0 : break;
4829 :
4830 : case 0xc0:
4831 0 : x86emuOp_opcC0_byte_RM_MEM(emu);
4832 0 : break;
4833 : case 0xc1:
4834 0 : x86emuOp_opcC1_word_RM_MEM(emu);
4835 0 : break;
4836 : case 0xc2:
4837 0 : x86emuOp_ret_near_IMM(emu);
4838 0 : break;
4839 : case 0xc3:
4840 0 : emu->x86.R_IP = pop_word(emu);
4841 0 : break;
4842 : case 0xc4:
4843 0 : common_load_far_pointer(emu, &emu->x86.R_ES);
4844 0 : break;
4845 : case 0xc5:
4846 0 : common_load_far_pointer(emu, &emu->x86.R_DS);
4847 0 : break;
4848 : case 0xc6:
4849 0 : x86emuOp_mov_byte_RM_IMM(emu);
4850 0 : break;
4851 : case 0xc7:
4852 0 : x86emuOp_mov_word_RM_IMM(emu);
4853 0 : break;
4854 : case 0xc8:
4855 0 : x86emuOp_enter(emu);
4856 0 : break;
4857 : case 0xc9:
4858 0 : x86emuOp_leave(emu);
4859 0 : break;
4860 : case 0xca:
4861 0 : x86emuOp_ret_far_IMM(emu);
4862 0 : break;
4863 : case 0xcb:
4864 0 : x86emuOp_ret_far(emu);
4865 0 : break;
4866 : case 0xcc:
4867 0 : x86emuOp_int3(emu);
4868 0 : break;
4869 : case 0xcd:
4870 0 : x86emuOp_int_IMM(emu);
4871 0 : break;
4872 : case 0xce:
4873 0 : x86emuOp_into(emu);
4874 0 : break;
4875 : case 0xcf:
4876 0 : x86emuOp_iret(emu);
4877 0 : break;
4878 :
4879 : case 0xd0:
4880 0 : x86emuOp_opcD0_byte_RM_1(emu);
4881 0 : break;
4882 : case 0xd1:
4883 0 : x86emuOp_opcD1_word_RM_1(emu);
4884 0 : break;
4885 : case 0xd2:
4886 0 : x86emuOp_opcD2_byte_RM_CL(emu);
4887 0 : break;
4888 : case 0xd3:
4889 0 : x86emuOp_opcD3_word_RM_CL(emu);
4890 0 : break;
4891 : case 0xd4:
4892 0 : x86emuOp_aam(emu);
4893 0 : break;
4894 : case 0xd5:
4895 0 : x86emuOp_aad(emu);
4896 0 : break;
4897 : /* 0xd6 Undocumented SETALC instruction */
4898 : case 0xd7:
4899 0 : x86emuOp_xlat(emu);
4900 0 : break;
4901 : case 0xd8:
4902 0 : x86emuOp_esc_coprocess_d8(emu);
4903 0 : break;
4904 : case 0xd9:
4905 0 : x86emuOp_esc_coprocess_d9(emu);
4906 0 : break;
4907 : case 0xda:
4908 0 : x86emuOp_esc_coprocess_da(emu);
4909 0 : break;
4910 : case 0xdb:
4911 0 : x86emuOp_esc_coprocess_db(emu);
4912 0 : break;
4913 : case 0xdc:
4914 0 : x86emuOp_esc_coprocess_dc(emu);
4915 0 : break;
4916 : case 0xdd:
4917 0 : x86emuOp_esc_coprocess_dd(emu);
4918 0 : break;
4919 : case 0xde:
4920 0 : x86emuOp_esc_coprocess_de(emu);
4921 0 : break;
4922 : case 0xdf:
4923 0 : x86emuOp_esc_coprocess_df(emu);
4924 0 : break;
4925 :
4926 : case 0xe0:
4927 0 : x86emuOp_loopne(emu);
4928 0 : break;
4929 : case 0xe1:
4930 0 : x86emuOp_loope(emu);
4931 0 : break;
4932 : case 0xe2:
4933 0 : x86emuOp_loop(emu);
4934 0 : break;
4935 : case 0xe3:
4936 0 : x86emuOp_jcxz(emu);
4937 0 : break;
4938 : case 0xe4:
4939 0 : x86emuOp_in_byte_AL_IMM(emu);
4940 0 : break;
4941 : case 0xe5:
4942 0 : x86emuOp_in_word_AX_IMM(emu);
4943 0 : break;
4944 : case 0xe6:
4945 0 : x86emuOp_out_byte_IMM_AL(emu);
4946 0 : break;
4947 : case 0xe7:
4948 0 : x86emuOp_out_word_IMM_AX(emu);
4949 0 : break;
4950 :
4951 : case 0xe8:
4952 0 : x86emuOp_call_near_IMM(emu);
4953 0 : break;
4954 : case 0xe9:
4955 0 : x86emuOp_jump_near_IMM(emu);
4956 0 : break;
4957 : case 0xea:
4958 0 : x86emuOp_jump_far_IMM(emu);
4959 0 : break;
4960 : case 0xeb:
4961 0 : x86emuOp_jump_byte_IMM(emu);
4962 0 : break;
4963 : case 0xec:
4964 0 : x86emuOp_in_byte_AL_DX(emu);
4965 0 : break;
4966 : case 0xed:
4967 0 : x86emuOp_in_word_AX_DX(emu);
4968 0 : break;
4969 : case 0xee:
4970 0 : x86emuOp_out_byte_DX_AL(emu);
4971 0 : break;
4972 : case 0xef:
4973 0 : x86emuOp_out_word_DX_AX(emu);
4974 0 : break;
4975 :
4976 : case 0xf0:
4977 0 : x86emuOp_lock(emu);
4978 0 : break;
4979 : case 0xf2:
4980 0 : emu->x86.mode |= SYSMODE_PREFIX_REPNE;
4981 0 : break;
4982 : case 0xf3:
4983 0 : emu->x86.mode |= SYSMODE_PREFIX_REPE;
4984 0 : break;
4985 : case 0xf4:
4986 0 : x86emu_halt_sys(emu);
4987 : break;
4988 : case 0xf5:
4989 0 : x86emuOp_cmc(emu);
4990 0 : break;
4991 : case 0xf6:
4992 0 : x86emuOp_opcF6_byte_RM(emu);
4993 0 : break;
4994 : case 0xf7:
4995 0 : x86emuOp_opcF7_word_RM(emu);
4996 0 : break;
4997 :
4998 : case 0xf8:
4999 0 : CLEAR_FLAG(F_CF);
5000 0 : break;
5001 : case 0xf9:
5002 0 : SET_FLAG(F_CF);
5003 0 : break;
5004 : case 0xfa:
5005 0 : CLEAR_FLAG(F_IF);
5006 0 : break;
5007 : case 0xfb:
5008 0 : SET_FLAG(F_IF);
5009 0 : break;
5010 : case 0xfc:
5011 0 : CLEAR_FLAG(F_DF);
5012 0 : break;
5013 : case 0xfd:
5014 0 : SET_FLAG(F_DF);
5015 0 : break;
5016 : case 0xfe:
5017 0 : x86emuOp_opcFE_byte_RM(emu);
5018 0 : break;
5019 : case 0xff:
5020 0 : x86emuOp_opcFF_word_RM(emu);
5021 0 : break;
5022 : default:
5023 0 : x86emu_halt_sys(emu);
5024 : break;
5025 : }
5026 0 : if (op1 != 0x26 && op1 != 0x2e && op1 != 0x36 && op1 != 0x3e &&
5027 0 : (op1 | 3) != 0x67)
5028 0 : emu->x86.mode &= ~SYSMODE_CLRMASK;
5029 0 : }
5030 :
5031 : static void
5032 0 : common_jmp_long(struct x86emu *emu, int cond)
5033 : {
5034 : int16_t target;
5035 :
5036 0 : target = (int16_t) fetch_word_imm(emu);
5037 0 : target += (int16_t) emu->x86.R_IP;
5038 0 : if (cond)
5039 0 : emu->x86.R_IP = (uint16_t) target;
5040 0 : }
5041 :
5042 : static void
5043 0 : common_set_byte(struct x86emu *emu, int cond)
5044 : {
5045 : uint32_t destoffset;
5046 : uint8_t *destreg, destval;
5047 :
5048 0 : fetch_decode_modrm(emu);
5049 0 : destval = cond ? 0x01 : 0x00;
5050 0 : if (emu->cur_mod != 3) {
5051 0 : destoffset = decode_rl_address(emu);
5052 0 : store_data_byte(emu, destoffset, destval);
5053 0 : } else {
5054 0 : destreg = decode_rl_byte_register(emu);
5055 0 : *destreg = destval;
5056 : }
5057 0 : }
5058 :
5059 : static void
5060 0 : common_bitstring32(struct x86emu *emu, int op)
5061 : {
5062 : int bit;
5063 : uint32_t srcval, *shiftreg, mask;
5064 :
5065 0 : fetch_decode_modrm(emu);
5066 0 : shiftreg = decode_rh_long_register(emu);
5067 0 : srcval = decode_and_fetch_long_disp(emu, (int16_t) *shiftreg >> 5);
5068 0 : bit = *shiftreg & 0x1F;
5069 0 : mask = 0x1 << bit;
5070 0 : CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5071 :
5072 0 : switch (op) {
5073 : case 0:
5074 : break;
5075 : case 1:
5076 0 : write_back_long(emu, srcval | mask);
5077 0 : break;
5078 : case 2:
5079 0 : write_back_long(emu, srcval & ~mask);
5080 0 : break;
5081 : case 3:
5082 0 : write_back_long(emu, srcval ^ mask);
5083 0 : break;
5084 : }
5085 0 : }
5086 :
5087 : static void
5088 0 : common_bitstring16(struct x86emu *emu, int op)
5089 : {
5090 : int bit;
5091 : uint16_t srcval, *shiftreg, mask;
5092 :
5093 0 : fetch_decode_modrm(emu);
5094 0 : shiftreg = decode_rh_word_register(emu);
5095 0 : srcval = decode_and_fetch_word_disp(emu, (int16_t) *shiftreg >> 4);
5096 0 : bit = *shiftreg & 0xF;
5097 0 : mask = 0x1 << bit;
5098 0 : CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5099 :
5100 0 : switch (op) {
5101 : case 0:
5102 : break;
5103 : case 1:
5104 0 : write_back_word(emu, srcval | mask);
5105 0 : break;
5106 : case 2:
5107 0 : write_back_word(emu, srcval & ~mask);
5108 0 : break;
5109 : case 3:
5110 0 : write_back_word(emu, srcval ^ mask);
5111 0 : break;
5112 : }
5113 0 : }
5114 :
5115 : static void
5116 0 : common_bitstring(struct x86emu *emu, int op)
5117 : {
5118 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5119 0 : common_bitstring32(emu, op);
5120 : else
5121 0 : common_bitstring16(emu, op);
5122 0 : }
5123 :
5124 : static void
5125 0 : common_bitsearch32(struct x86emu *emu, int diff)
5126 : {
5127 : uint32_t srcval, *dstreg;
5128 :
5129 0 : fetch_decode_modrm(emu);
5130 0 : dstreg = decode_rh_long_register(emu);
5131 0 : srcval = decode_and_fetch_long(emu);
5132 0 : CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5133 0 : for (*dstreg = 0; *dstreg < 32; *dstreg += diff) {
5134 0 : if ((srcval >> *dstreg) & 1)
5135 : break;
5136 : }
5137 0 : }
5138 :
5139 : static void
5140 0 : common_bitsearch16(struct x86emu *emu, int diff)
5141 : {
5142 : uint16_t srcval, *dstreg;
5143 :
5144 0 : fetch_decode_modrm(emu);
5145 0 : dstreg = decode_rh_word_register(emu);
5146 0 : srcval = decode_and_fetch_word(emu);
5147 0 : CONDITIONAL_SET_FLAG(srcval == 0, F_ZF);
5148 0 : for (*dstreg = 0; *dstreg < 16; *dstreg += diff) {
5149 0 : if ((srcval >> *dstreg) & 1)
5150 : break;
5151 : }
5152 0 : }
5153 :
5154 : static void
5155 0 : common_bitsearch(struct x86emu *emu, int diff)
5156 : {
5157 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5158 0 : common_bitsearch32(emu, diff);
5159 : else
5160 0 : common_bitsearch16(emu, diff);
5161 0 : }
5162 :
5163 : static void
5164 0 : common_shift32(struct x86emu *emu, int shift_left, int use_cl)
5165 : {
5166 0 : uint8_t shift;
5167 : uint32_t destval, *shiftreg;
5168 :
5169 0 : fetch_decode_modrm(emu);
5170 0 : shiftreg = decode_rh_long_register(emu);
5171 0 : if (use_cl) {
5172 0 : destval = decode_and_fetch_long(emu);
5173 0 : shift = emu->x86.R_CL;
5174 0 : } else {
5175 0 : destval = decode_and_fetch_long_imm8(emu, &shift);
5176 : }
5177 0 : if (shift_left)
5178 0 : destval = shld_long(emu, destval, *shiftreg, shift);
5179 : else
5180 0 : destval = shrd_long(emu, destval, *shiftreg, shift);
5181 0 : write_back_long(emu, destval);
5182 0 : }
5183 :
5184 : static void
5185 0 : common_shift16(struct x86emu *emu, int shift_left, int use_cl)
5186 : {
5187 0 : uint8_t shift;
5188 : uint16_t destval, *shiftreg;
5189 :
5190 0 : fetch_decode_modrm(emu);
5191 0 : shiftreg = decode_rh_word_register(emu);
5192 0 : if (use_cl) {
5193 0 : destval = decode_and_fetch_word(emu);
5194 0 : shift = emu->x86.R_CL;
5195 0 : } else {
5196 0 : destval = decode_and_fetch_word_imm8(emu, &shift);
5197 : }
5198 0 : if (shift_left)
5199 0 : destval = shld_word(emu, destval, *shiftreg, shift);
5200 : else
5201 0 : destval = shrd_word(emu, destval, *shiftreg, shift);
5202 0 : write_back_word(emu, destval);
5203 0 : }
5204 :
5205 : static void
5206 0 : common_shift(struct x86emu *emu, int shift_left, int use_cl)
5207 : {
5208 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5209 0 : common_shift32(emu, shift_left, use_cl);
5210 : else
5211 0 : common_shift16(emu, shift_left, use_cl);
5212 0 : }
5213 :
5214 : /*
5215 : * Implementation
5216 : */
5217 : #define xorl(a,b) ((a) && !(b)) || (!(a) && (b))
5218 :
5219 :
5220 : /*
5221 : * REMARKS:
5222 : * Handles opcode 0x0f,0x31
5223 : */
5224 : static void
5225 0 : x86emuOp2_rdtsc(struct x86emu *emu)
5226 : {
5227 0 : emu->x86.R_EAX = emu->cur_cycles & 0xffffffff;
5228 0 : emu->x86.R_EDX = emu->cur_cycles >> 32;
5229 0 : }
5230 :
5231 : /*
5232 : * REMARKS:
5233 : * Handles opcode 0x0f,0xa0
5234 : */
5235 : static void
5236 0 : x86emuOp2_push_FS(struct x86emu *emu)
5237 : {
5238 0 : push_word(emu, emu->x86.R_FS);
5239 0 : }
5240 :
5241 : /*
5242 : * REMARKS:
5243 : * Handles opcode 0x0f,0xa1
5244 : */
5245 : static void
5246 0 : x86emuOp2_pop_FS(struct x86emu *emu)
5247 : {
5248 0 : emu->x86.R_FS = pop_word(emu);
5249 0 : }
5250 :
5251 : /*
5252 : * REMARKS:
5253 : * Handles opcode 0x0f,0xa1
5254 : */
5255 : #if defined(__i386__) || defined(__amd64__)
5256 : static void
5257 0 : hw_cpuid(uint32_t *a, uint32_t *b, uint32_t *c, uint32_t *d)
5258 : {
5259 0 : __asm__ volatile("cpuid"
5260 : : "=a" (*a), "=b" (*b),
5261 : "=c" (*c), "=d" (*d)
5262 0 : : "a" (*a), "c" (*c)
5263 : : "cc");
5264 0 : }
5265 : #endif
5266 : static void
5267 0 : x86emuOp2_cpuid(struct x86emu *emu)
5268 : {
5269 : #if defined(__i386__) || defined(__amd64__)
5270 0 : hw_cpuid(&emu->x86.R_EAX, &emu->x86.R_EBX, &emu->x86.R_ECX,
5271 0 : &emu->x86.R_EDX);
5272 : #endif
5273 0 : switch (emu->x86.R_EAX) {
5274 : case 0:
5275 0 : emu->x86.R_EAX = 1;
5276 : #if !defined(__i386__) && !defined(__amd64__)
5277 : /* "GenuineIntel" */
5278 : emu->x86.R_EBX = 0x756e6547;
5279 : emu->x86.R_EDX = 0x49656e69;
5280 : emu->x86.R_ECX = 0x6c65746e;
5281 : #endif
5282 0 : break;
5283 : case 1:
5284 : #if !defined(__i386__) && !defined(__amd64__)
5285 : emu->x86.R_EAX = 0x00000480;
5286 : emu->x86.R_EBX = emu->x86.R_ECX = 0;
5287 : emu->x86.R_EDX = 0x00000002;
5288 : #else
5289 0 : emu->x86.R_EDX &= 0x00000012;
5290 : #endif
5291 0 : break;
5292 : default:
5293 0 : emu->x86.R_EAX = emu->x86.R_EBX = emu->x86.R_ECX =
5294 0 : emu->x86.R_EDX = 0;
5295 0 : break;
5296 : }
5297 0 : }
5298 :
5299 : /*
5300 : * REMARKS:
5301 : * Handles opcode 0x0f,0xa3
5302 : */
5303 : static void
5304 0 : x86emuOp2_bt_R(struct x86emu *emu)
5305 : {
5306 0 : common_bitstring(emu, 0);
5307 0 : }
5308 :
5309 : /*
5310 : * REMARKS:
5311 : * Handles opcode 0x0f,0xa4
5312 : */
5313 : static void
5314 0 : x86emuOp2_shld_IMM(struct x86emu *emu)
5315 : {
5316 0 : common_shift(emu, 1, 0);
5317 0 : }
5318 :
5319 : /*
5320 : * REMARKS:
5321 : * Handles opcode 0x0f,0xa5
5322 : */
5323 : static void
5324 0 : x86emuOp2_shld_CL(struct x86emu *emu)
5325 : {
5326 0 : common_shift(emu, 1, 1);
5327 0 : }
5328 :
5329 : /*
5330 : * REMARKS:
5331 : * Handles opcode 0x0f,0xa8
5332 : */
5333 : static void
5334 0 : x86emuOp2_push_GS(struct x86emu *emu)
5335 : {
5336 0 : push_word(emu, emu->x86.R_GS);
5337 0 : }
5338 :
5339 : /*
5340 : * REMARKS:
5341 : * Handles opcode 0x0f,0xa9
5342 : */
5343 : static void
5344 0 : x86emuOp2_pop_GS(struct x86emu *emu)
5345 : {
5346 0 : emu->x86.R_GS = pop_word(emu);
5347 0 : }
5348 :
5349 : /*
5350 : * REMARKS:
5351 : * Handles opcode 0x0f,0xab
5352 : */
5353 : static void
5354 0 : x86emuOp2_bts_R(struct x86emu *emu)
5355 : {
5356 0 : common_bitstring(emu, 1);
5357 0 : }
5358 :
5359 : /*
5360 : * REMARKS:
5361 : * Handles opcode 0x0f,0xac
5362 : */
5363 : static void
5364 0 : x86emuOp2_shrd_IMM(struct x86emu *emu)
5365 : {
5366 0 : common_shift(emu, 0, 0);
5367 0 : }
5368 :
5369 : /*
5370 : * REMARKS:
5371 : * Handles opcode 0x0f,0xad
5372 : */
5373 : static void
5374 0 : x86emuOp2_shrd_CL(struct x86emu *emu)
5375 : {
5376 0 : common_shift(emu, 0, 1);
5377 0 : }
5378 :
5379 : /*
5380 : * REMARKS:
5381 : * Handles opcode 0x0f,0xaf
5382 : */
5383 : static void
5384 0 : x86emuOp2_32_imul_R_RM(struct x86emu *emu)
5385 : {
5386 : uint32_t *destreg, srcval;
5387 : uint64_t res;
5388 :
5389 0 : fetch_decode_modrm(emu);
5390 0 : destreg = decode_rh_long_register(emu);
5391 0 : srcval = decode_and_fetch_long(emu);
5392 0 : res = (int32_t) *destreg * (int32_t)srcval;
5393 0 : if (res > 0xffffffff) {
5394 0 : SET_FLAG(F_CF);
5395 0 : SET_FLAG(F_OF);
5396 0 : } else {
5397 0 : CLEAR_FLAG(F_CF);
5398 0 : CLEAR_FLAG(F_OF);
5399 : }
5400 0 : *destreg = (uint32_t) res;
5401 0 : }
5402 :
5403 : static void
5404 0 : x86emuOp2_16_imul_R_RM(struct x86emu *emu)
5405 : {
5406 : uint16_t *destreg, srcval;
5407 : uint32_t res;
5408 :
5409 0 : fetch_decode_modrm(emu);
5410 0 : destreg = decode_rh_word_register(emu);
5411 0 : srcval = decode_and_fetch_word(emu);
5412 0 : res = (int16_t) * destreg * (int16_t)srcval;
5413 0 : if (res > 0xFFFF) {
5414 0 : SET_FLAG(F_CF);
5415 0 : SET_FLAG(F_OF);
5416 0 : } else {
5417 0 : CLEAR_FLAG(F_CF);
5418 0 : CLEAR_FLAG(F_OF);
5419 : }
5420 0 : *destreg = (uint16_t) res;
5421 0 : }
5422 :
5423 : static void
5424 0 : x86emuOp2_imul_R_RM(struct x86emu *emu)
5425 : {
5426 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5427 0 : x86emuOp2_32_imul_R_RM(emu);
5428 : else
5429 0 : x86emuOp2_16_imul_R_RM(emu);
5430 0 : }
5431 :
5432 : /*
5433 : * REMARKS:
5434 : * Handles opcode 0x0f,0xb2
5435 : */
5436 : static void
5437 0 : x86emuOp2_lss_R_IMM(struct x86emu *emu)
5438 : {
5439 0 : common_load_far_pointer(emu, &emu->x86.R_SS);
5440 0 : }
5441 :
5442 : /*
5443 : * REMARKS:
5444 : * Handles opcode 0x0f,0xb3
5445 : */
5446 : static void
5447 0 : x86emuOp2_btr_R(struct x86emu *emu)
5448 : {
5449 0 : common_bitstring(emu, 2);
5450 0 : }
5451 :
5452 : /*
5453 : * REMARKS:
5454 : * Handles opcode 0x0f,0xb4
5455 : */
5456 : static void
5457 0 : x86emuOp2_lfs_R_IMM(struct x86emu *emu)
5458 : {
5459 0 : common_load_far_pointer(emu, &emu->x86.R_FS);
5460 0 : }
5461 :
5462 : /*
5463 : * REMARKS:
5464 : * Handles opcode 0x0f,0xb5
5465 : */
5466 : static void
5467 0 : x86emuOp2_lgs_R_IMM(struct x86emu *emu)
5468 : {
5469 0 : common_load_far_pointer(emu, &emu->x86.R_GS);
5470 0 : }
5471 :
5472 : /*
5473 : * REMARKS:
5474 : * Handles opcode 0x0f,0xb6
5475 : */
5476 : static void
5477 0 : x86emuOp2_32_movzx_byte_R_RM(struct x86emu *emu)
5478 : {
5479 : uint32_t *destreg;
5480 :
5481 0 : fetch_decode_modrm(emu);
5482 0 : destreg = decode_rh_long_register(emu);
5483 0 : *destreg = decode_and_fetch_byte(emu);
5484 0 : }
5485 :
5486 : static void
5487 0 : x86emuOp2_16_movzx_byte_R_RM(struct x86emu *emu)
5488 : {
5489 : uint16_t *destreg;
5490 :
5491 0 : fetch_decode_modrm(emu);
5492 0 : destreg = decode_rh_word_register(emu);
5493 0 : *destreg = decode_and_fetch_byte(emu);
5494 0 : }
5495 :
5496 : static void
5497 0 : x86emuOp2_movzx_byte_R_RM(struct x86emu *emu)
5498 : {
5499 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5500 0 : x86emuOp2_32_movzx_byte_R_RM(emu);
5501 : else
5502 0 : x86emuOp2_16_movzx_byte_R_RM(emu);
5503 0 : }
5504 :
5505 : /*
5506 : * REMARKS:
5507 : * Handles opcode 0x0f,0xb7
5508 : */
5509 : static void
5510 0 : x86emuOp2_movzx_word_R_RM(struct x86emu *emu)
5511 : {
5512 : uint32_t *destreg;
5513 :
5514 0 : fetch_decode_modrm(emu);
5515 0 : destreg = decode_rh_long_register(emu);
5516 0 : *destreg = decode_and_fetch_word(emu);
5517 0 : }
5518 :
5519 : /*
5520 : * REMARKS:
5521 : * Handles opcode 0x0f,0xba
5522 : */
5523 : static void
5524 0 : x86emuOp2_32_btX_I(struct x86emu *emu)
5525 : {
5526 : int bit;
5527 : uint32_t srcval, mask;
5528 0 : uint8_t shift;
5529 :
5530 0 : fetch_decode_modrm(emu);
5531 0 : if (emu->cur_rh < 4)
5532 0 : x86emu_halt_sys(emu);
5533 :
5534 0 : srcval = decode_and_fetch_long_imm8(emu, &shift);
5535 0 : bit = shift & 0x1F;
5536 0 : mask = (0x1 << bit);
5537 :
5538 0 : switch (emu->cur_rh) {
5539 : case 5:
5540 0 : write_back_long(emu, srcval | mask);
5541 0 : break;
5542 : case 6:
5543 0 : write_back_long(emu, srcval & ~mask);
5544 0 : break;
5545 : case 7:
5546 0 : write_back_long(emu, srcval ^ mask);
5547 0 : break;
5548 : }
5549 0 : CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5550 0 : }
5551 :
5552 : static void
5553 0 : x86emuOp2_16_btX_I(struct x86emu *emu)
5554 : {
5555 : int bit;
5556 :
5557 : uint16_t srcval, mask;
5558 0 : uint8_t shift;
5559 :
5560 0 : fetch_decode_modrm(emu);
5561 0 : if (emu->cur_rh < 4)
5562 0 : x86emu_halt_sys(emu);
5563 :
5564 0 : srcval = decode_and_fetch_word_imm8(emu, &shift);
5565 0 : bit = shift & 0xF;
5566 0 : mask = (0x1 << bit);
5567 0 : switch (emu->cur_rh) {
5568 : case 5:
5569 0 : write_back_word(emu, srcval | mask);
5570 0 : break;
5571 : case 6:
5572 0 : write_back_word(emu, srcval & ~mask);
5573 0 : break;
5574 : case 7:
5575 0 : write_back_word(emu, srcval ^ mask);
5576 0 : break;
5577 : }
5578 0 : CONDITIONAL_SET_FLAG(srcval & mask, F_CF);
5579 0 : }
5580 :
5581 : static void
5582 0 : x86emuOp2_btX_I(struct x86emu *emu)
5583 : {
5584 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5585 0 : x86emuOp2_32_btX_I(emu);
5586 : else
5587 0 : x86emuOp2_16_btX_I(emu);
5588 0 : }
5589 :
5590 : /*
5591 : * REMARKS:
5592 : * Handles opcode 0x0f,0xbb
5593 : */
5594 : static void
5595 0 : x86emuOp2_btc_R(struct x86emu *emu)
5596 : {
5597 0 : common_bitstring(emu, 3);
5598 0 : }
5599 :
5600 : /*
5601 : * REMARKS:
5602 : * Handles opcode 0x0f,0xbc
5603 : */
5604 : static void
5605 0 : x86emuOp2_bsf(struct x86emu *emu)
5606 : {
5607 0 : common_bitsearch(emu, +1);
5608 0 : }
5609 :
5610 : /*
5611 : * REMARKS:
5612 : * Handles opcode 0x0f,0xbd
5613 : */
5614 : static void
5615 0 : x86emuOp2_bsr(struct x86emu *emu)
5616 : {
5617 0 : common_bitsearch(emu, -1);
5618 0 : }
5619 :
5620 : /*
5621 : * REMARKS:
5622 : * Handles opcode 0x0f,0xbe
5623 : */
5624 : static void
5625 0 : x86emuOp2_32_movsx_byte_R_RM(struct x86emu *emu)
5626 : {
5627 : uint32_t *destreg;
5628 :
5629 0 : fetch_decode_modrm(emu);
5630 0 : destreg = decode_rh_long_register(emu);
5631 0 : *destreg = (int32_t)(int8_t)decode_and_fetch_byte(emu);
5632 0 : }
5633 :
5634 : static void
5635 0 : x86emuOp2_16_movsx_byte_R_RM(struct x86emu *emu)
5636 : {
5637 : uint16_t *destreg;
5638 :
5639 0 : fetch_decode_modrm(emu);
5640 0 : destreg = decode_rh_word_register(emu);
5641 0 : *destreg = (int16_t)(int8_t)decode_and_fetch_byte(emu);
5642 0 : }
5643 :
5644 : static void
5645 0 : x86emuOp2_movsx_byte_R_RM(struct x86emu *emu)
5646 : {
5647 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA)
5648 0 : x86emuOp2_32_movsx_byte_R_RM(emu);
5649 : else
5650 0 : x86emuOp2_16_movsx_byte_R_RM(emu);
5651 0 : }
5652 :
5653 : /*
5654 : * REMARKS:
5655 : * Handles opcode 0x0f,0xbf
5656 : */
5657 : static void
5658 0 : x86emuOp2_movsx_word_R_RM(struct x86emu *emu)
5659 : {
5660 : uint32_t *destreg;
5661 :
5662 0 : fetch_decode_modrm(emu);
5663 0 : destreg = decode_rh_long_register(emu);
5664 0 : *destreg = (int32_t)(int16_t)decode_and_fetch_word(emu);
5665 0 : }
5666 :
5667 : static void
5668 0 : x86emu_exec_two_byte(struct x86emu * emu)
5669 : {
5670 : uint8_t op2;
5671 :
5672 0 : op2 = fetch_byte_imm(emu);
5673 :
5674 0 : switch (op2) {
5675 : /* 0x00 Group F (ring 0 PM) */
5676 : /* 0x01 Group G (ring 0 PM) */
5677 : /* 0x02 lar (ring 0 PM) */
5678 : /* 0x03 lsl (ring 0 PM) */
5679 : /* 0x05 loadall (undocumented) */
5680 : /* 0x06 clts (ring 0 PM) */
5681 : /* 0x07 loadall (undocumented) */
5682 : /* 0x08 invd (ring 0 PM) */
5683 : /* 0x09 wbinvd (ring 0 PM) */
5684 :
5685 : /* 0x20 mov reg32(op2); break;creg (ring 0 PM) */
5686 : /* 0x21 mov reg32(op2); break;dreg (ring 0 PM) */
5687 : /* 0x22 mov creg(op2); break;reg32 (ring 0 PM) */
5688 : /* 0x23 mov dreg(op2); break;reg32 (ring 0 PM) */
5689 : /* 0x24 mov reg32(op2); break;treg (ring 0 PM) */
5690 : /* 0x26 mov treg(op2); break;reg32 (ring 0 PM) */
5691 :
5692 : case 0x31:
5693 0 : x86emuOp2_rdtsc(emu);
5694 0 : break;
5695 :
5696 : case 0x80:
5697 0 : common_jmp_long(emu, ACCESS_FLAG(F_OF));
5698 0 : break;
5699 : case 0x81:
5700 0 : common_jmp_long(emu, !ACCESS_FLAG(F_OF));
5701 0 : break;
5702 : case 0x82:
5703 0 : common_jmp_long(emu, ACCESS_FLAG(F_CF));
5704 0 : break;
5705 : case 0x83:
5706 0 : common_jmp_long(emu, !ACCESS_FLAG(F_CF));
5707 0 : break;
5708 : case 0x84:
5709 0 : common_jmp_long(emu, ACCESS_FLAG(F_ZF));
5710 0 : break;
5711 : case 0x85:
5712 0 : common_jmp_long(emu, !ACCESS_FLAG(F_ZF));
5713 0 : break;
5714 : case 0x86:
5715 0 : common_jmp_long(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5716 0 : break;
5717 : case 0x87:
5718 0 : common_jmp_long(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5719 0 : break;
5720 : case 0x88:
5721 0 : common_jmp_long(emu, ACCESS_FLAG(F_SF));
5722 0 : break;
5723 : case 0x89:
5724 0 : common_jmp_long(emu, !ACCESS_FLAG(F_SF));
5725 0 : break;
5726 : case 0x8a:
5727 0 : common_jmp_long(emu, ACCESS_FLAG(F_PF));
5728 0 : break;
5729 : case 0x8b:
5730 0 : common_jmp_long(emu, !ACCESS_FLAG(F_PF));
5731 0 : break;
5732 : case 0x8c:
5733 0 : common_jmp_long(emu, xorl(ACCESS_FLAG(F_SF),
5734 : ACCESS_FLAG(F_OF)));
5735 0 : break;
5736 : case 0x8d:
5737 0 : common_jmp_long(emu, !(xorl(ACCESS_FLAG(F_SF),
5738 : ACCESS_FLAG(F_OF))));
5739 0 : break;
5740 : case 0x8e:
5741 0 : common_jmp_long(emu, (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF))
5742 0 : || ACCESS_FLAG(F_ZF)));
5743 0 : break;
5744 : case 0x8f:
5745 0 : common_jmp_long(emu,
5746 0 : !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5747 0 : ACCESS_FLAG(F_ZF)));
5748 0 : break;
5749 :
5750 : case 0x90:
5751 0 : common_set_byte(emu, ACCESS_FLAG(F_OF));
5752 0 : break;
5753 : case 0x91:
5754 0 : common_set_byte(emu, !ACCESS_FLAG(F_OF));
5755 0 : break;
5756 : case 0x92:
5757 0 : common_set_byte(emu, ACCESS_FLAG(F_CF));
5758 0 : break;
5759 : case 0x93:
5760 0 : common_set_byte(emu, !ACCESS_FLAG(F_CF));
5761 0 : break;
5762 : case 0x94:
5763 0 : common_set_byte(emu, ACCESS_FLAG(F_ZF));
5764 0 : break;
5765 : case 0x95:
5766 0 : common_set_byte(emu, !ACCESS_FLAG(F_ZF));
5767 0 : break;
5768 : case 0x96:
5769 0 : common_set_byte(emu, ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF));
5770 0 : break;
5771 : case 0x97:
5772 0 : common_set_byte(emu, !(ACCESS_FLAG(F_CF) || ACCESS_FLAG(F_ZF)));
5773 0 : break;
5774 : case 0x98:
5775 0 : common_set_byte(emu, ACCESS_FLAG(F_SF));
5776 0 : break;
5777 : case 0x99:
5778 0 : common_set_byte(emu, !ACCESS_FLAG(F_SF));
5779 0 : break;
5780 : case 0x9a:
5781 0 : common_set_byte(emu, ACCESS_FLAG(F_PF));
5782 0 : break;
5783 : case 0x9b:
5784 0 : common_set_byte(emu, !ACCESS_FLAG(F_PF));
5785 0 : break;
5786 : case 0x9c:
5787 0 : common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
5788 : ACCESS_FLAG(F_OF)));
5789 0 : break;
5790 : case 0x9d:
5791 0 : common_set_byte(emu, xorl(ACCESS_FLAG(F_SF),
5792 : ACCESS_FLAG(F_OF)));
5793 0 : break;
5794 : case 0x9e:
5795 0 : common_set_byte(emu,
5796 0 : (xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5797 0 : ACCESS_FLAG(F_ZF)));
5798 0 : break;
5799 : case 0x9f:
5800 0 : common_set_byte(emu,
5801 0 : !(xorl(ACCESS_FLAG(F_SF), ACCESS_FLAG(F_OF)) ||
5802 0 : ACCESS_FLAG(F_ZF)));
5803 0 : break;
5804 :
5805 : case 0xa0:
5806 0 : x86emuOp2_push_FS(emu);
5807 0 : break;
5808 : case 0xa1:
5809 0 : x86emuOp2_pop_FS(emu);
5810 0 : break;
5811 : case 0xa2:
5812 0 : x86emuOp2_cpuid(emu);
5813 0 : break;
5814 : case 0xa3:
5815 0 : x86emuOp2_bt_R(emu);
5816 0 : break;
5817 : case 0xa4:
5818 0 : x86emuOp2_shld_IMM(emu);
5819 0 : break;
5820 : case 0xa5:
5821 0 : x86emuOp2_shld_CL(emu);
5822 0 : break;
5823 : case 0xa8:
5824 0 : x86emuOp2_push_GS(emu);
5825 0 : break;
5826 : case 0xa9:
5827 0 : x86emuOp2_pop_GS(emu);
5828 0 : break;
5829 : case 0xab:
5830 0 : x86emuOp2_bts_R(emu);
5831 0 : break;
5832 : case 0xac:
5833 0 : x86emuOp2_shrd_IMM(emu);
5834 0 : break;
5835 : case 0xad:
5836 0 : x86emuOp2_shrd_CL(emu);
5837 0 : break;
5838 : case 0xaf:
5839 0 : x86emuOp2_imul_R_RM(emu);
5840 0 : break;
5841 :
5842 : /* 0xb0 TODO: cmpxchg */
5843 : /* 0xb1 TODO: cmpxchg */
5844 : case 0xb2:
5845 0 : x86emuOp2_lss_R_IMM(emu);
5846 0 : break;
5847 : case 0xb3:
5848 0 : x86emuOp2_btr_R(emu);
5849 0 : break;
5850 : case 0xb4:
5851 0 : x86emuOp2_lfs_R_IMM(emu);
5852 0 : break;
5853 : case 0xb5:
5854 0 : x86emuOp2_lgs_R_IMM(emu);
5855 0 : break;
5856 : case 0xb6:
5857 0 : x86emuOp2_movzx_byte_R_RM(emu);
5858 0 : break;
5859 : case 0xb7:
5860 0 : x86emuOp2_movzx_word_R_RM(emu);
5861 0 : break;
5862 : case 0xba:
5863 0 : x86emuOp2_btX_I(emu);
5864 0 : break;
5865 : case 0xbb:
5866 0 : x86emuOp2_btc_R(emu);
5867 0 : break;
5868 : case 0xbc:
5869 0 : x86emuOp2_bsf(emu);
5870 0 : break;
5871 : case 0xbd:
5872 0 : x86emuOp2_bsr(emu);
5873 0 : break;
5874 : case 0xbe:
5875 0 : x86emuOp2_movsx_byte_R_RM(emu);
5876 0 : break;
5877 : case 0xbf:
5878 0 : x86emuOp2_movsx_word_R_RM(emu);
5879 0 : break;
5880 :
5881 : /* 0xc0 TODO: xadd */
5882 : /* 0xc1 TODO: xadd */
5883 : /* 0xc8 TODO: bswap */
5884 : /* 0xc9 TODO: bswap */
5885 : /* 0xca TODO: bswap */
5886 : /* 0xcb TODO: bswap */
5887 : /* 0xcc TODO: bswap */
5888 : /* 0xcd TODO: bswap */
5889 : /* 0xce TODO: bswap */
5890 : /* 0xcf TODO: bswap */
5891 :
5892 : default:
5893 0 : x86emu_halt_sys(emu);
5894 : break;
5895 : }
5896 0 : }
5897 :
5898 : /*
5899 : * Carry Chain Calculation
5900 : *
5901 : * This represents a somewhat expensive calculation which is
5902 : * apparently required to emulate the setting of the OF and AF flag.
5903 : * The latter is not so important, but the former is. The overflow
5904 : * flag is the XOR of the top two bits of the carry chain for an
5905 : * addition (similar for subtraction). Since we do not want to
5906 : * simulate the addition in a bitwise manner, we try to calculate the
5907 : * carry chain given the two operands and the result.
5908 : *
5909 : * So, given the following table, which represents the addition of two
5910 : * bits, we can derive a formula for the carry chain.
5911 : *
5912 : * a b cin r cout
5913 : * 0 0 0 0 0
5914 : * 0 0 1 1 0
5915 : * 0 1 0 1 0
5916 : * 0 1 1 0 1
5917 : * 1 0 0 1 0
5918 : * 1 0 1 0 1
5919 : * 1 1 0 0 1
5920 : * 1 1 1 1 1
5921 : *
5922 : * Construction of table for cout:
5923 : *
5924 : * ab
5925 : * r \ 00 01 11 10
5926 : * |------------------
5927 : * 0 | 0 1 1 1
5928 : * 1 | 0 0 1 0
5929 : *
5930 : * By inspection, one gets: cc = ab + r'(a + b)
5931 : *
5932 : * That represents alot of operations, but NO CHOICE....
5933 : *
5934 : * Borrow Chain Calculation.
5935 : *
5936 : * The following table represents the subtraction of two bits, from
5937 : * which we can derive a formula for the borrow chain.
5938 : *
5939 : * a b bin r bout
5940 : * 0 0 0 0 0
5941 : * 0 0 1 1 1
5942 : * 0 1 0 1 1
5943 : * 0 1 1 0 1
5944 : * 1 0 0 1 0
5945 : * 1 0 1 0 0
5946 : * 1 1 0 0 0
5947 : * 1 1 1 1 1
5948 : *
5949 : * Construction of table for cout:
5950 : *
5951 : * ab
5952 : * r \ 00 01 11 10
5953 : * |------------------
5954 : * 0 | 0 1 0 0
5955 : * 1 | 1 1 1 0
5956 : *
5957 : * By inspection, one gets: bc = a'b + r(a' + b)
5958 : *
5959 : */
5960 :
5961 : /*
5962 : * Global Variables
5963 : */
5964 :
5965 : static uint32_t x86emu_parity_tab[8] =
5966 : {
5967 : 0x96696996,
5968 : 0x69969669,
5969 : 0x69969669,
5970 : 0x96696996,
5971 : 0x69969669,
5972 : 0x96696996,
5973 : 0x96696996,
5974 : 0x69969669,
5975 : };
5976 : #define PARITY(x) (((x86emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0)
5977 : #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1)
5978 :
5979 :
5980 : /*
5981 : * REMARKS:
5982 : * Implements the AAA instruction and side effects.
5983 : */
5984 : static uint16_t
5985 0 : aaa_word(struct x86emu *emu, uint16_t d)
5986 : {
5987 : uint16_t res;
5988 0 : if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
5989 0 : d += 0x6;
5990 0 : d += 0x100;
5991 0 : SET_FLAG(F_AF);
5992 0 : SET_FLAG(F_CF);
5993 0 : } else {
5994 0 : CLEAR_FLAG(F_CF);
5995 0 : CLEAR_FLAG(F_AF);
5996 : }
5997 0 : res = (uint16_t) (d & 0xFF0F);
5998 0 : CLEAR_FLAG(F_SF);
5999 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6000 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6001 0 : return res;
6002 : }
6003 :
6004 : /*
6005 : * REMARKS:
6006 : * Implements the AAA instruction and side effects.
6007 : */
6008 : static uint16_t
6009 0 : aas_word(struct x86emu *emu, uint16_t d)
6010 : {
6011 : uint16_t res;
6012 0 : if ((d & 0xf) > 0x9 || ACCESS_FLAG(F_AF)) {
6013 0 : d -= 0x6;
6014 0 : d -= 0x100;
6015 0 : SET_FLAG(F_AF);
6016 0 : SET_FLAG(F_CF);
6017 0 : } else {
6018 0 : CLEAR_FLAG(F_CF);
6019 0 : CLEAR_FLAG(F_AF);
6020 : }
6021 0 : res = (uint16_t) (d & 0xFF0F);
6022 0 : CLEAR_FLAG(F_SF);
6023 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6024 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6025 0 : return res;
6026 : }
6027 :
6028 : /*
6029 : * REMARKS:
6030 : * Implements the AAD instruction and side effects.
6031 : */
6032 : static uint16_t
6033 0 : aad_word(struct x86emu *emu, uint16_t d)
6034 : {
6035 : uint16_t l;
6036 : uint8_t hb, lb;
6037 :
6038 0 : hb = (uint8_t) ((d >> 8) & 0xff);
6039 0 : lb = (uint8_t) ((d & 0xff));
6040 0 : l = (uint16_t) ((lb + 10 * hb) & 0xFF);
6041 :
6042 0 : CLEAR_FLAG(F_CF);
6043 0 : CLEAR_FLAG(F_AF);
6044 0 : CLEAR_FLAG(F_OF);
6045 0 : CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
6046 0 : CONDITIONAL_SET_FLAG(l == 0, F_ZF);
6047 0 : CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
6048 0 : return l;
6049 : }
6050 :
6051 : /*
6052 : * REMARKS:
6053 : * Implements the AAM instruction and side effects.
6054 : */
6055 : static uint16_t
6056 0 : aam_word(struct x86emu *emu, uint8_t d)
6057 : {
6058 : uint16_t h, l;
6059 :
6060 0 : h = (uint16_t) (d / 10);
6061 0 : l = (uint16_t) (d % 10);
6062 0 : l |= (uint16_t) (h << 8);
6063 :
6064 0 : CLEAR_FLAG(F_CF);
6065 0 : CLEAR_FLAG(F_AF);
6066 0 : CLEAR_FLAG(F_OF);
6067 0 : CONDITIONAL_SET_FLAG(l & 0x80, F_SF);
6068 0 : CONDITIONAL_SET_FLAG(l == 0, F_ZF);
6069 0 : CONDITIONAL_SET_FLAG(PARITY(l & 0xff), F_PF);
6070 0 : return l;
6071 : }
6072 :
6073 : /*
6074 : * REMARKS:
6075 : * Implements the ADC instruction and side effects.
6076 : */
6077 : static uint8_t
6078 0 : adc_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6079 : {
6080 : uint32_t res; /* all operands in native machine order */
6081 : uint32_t cc;
6082 :
6083 0 : if (ACCESS_FLAG(F_CF))
6084 0 : res = 1 + d + s;
6085 : else
6086 0 : res = d + s;
6087 :
6088 0 : CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6089 0 : CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6090 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6091 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6092 :
6093 : /* calculate the carry chain SEE NOTE AT TOP. */
6094 0 : cc = (s & d) | ((~res) & (s | d));
6095 0 : CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6096 0 : CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6097 0 : return (uint8_t) res;
6098 : }
6099 :
6100 : /*
6101 : * REMARKS:
6102 : * Implements the ADC instruction and side effects.
6103 : */
6104 : static uint16_t
6105 0 : adc_word(struct x86emu *emu, uint16_t d, uint16_t s)
6106 : {
6107 : uint32_t res; /* all operands in native machine order */
6108 : uint32_t cc;
6109 :
6110 0 : if (ACCESS_FLAG(F_CF))
6111 0 : res = 1 + d + s;
6112 : else
6113 0 : res = d + s;
6114 :
6115 0 : CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6116 0 : CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6117 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6118 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6119 :
6120 : /* calculate the carry chain SEE NOTE AT TOP. */
6121 0 : cc = (s & d) | ((~res) & (s | d));
6122 0 : CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6123 0 : CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6124 0 : return (uint16_t) res;
6125 : }
6126 :
6127 : /*
6128 : * REMARKS:
6129 : * Implements the ADC instruction and side effects.
6130 : */
6131 : static uint32_t
6132 0 : adc_long(struct x86emu *emu, uint32_t d, uint32_t s)
6133 : {
6134 : uint32_t lo; /* all operands in native machine order */
6135 : uint32_t hi;
6136 : uint32_t res;
6137 : uint32_t cc;
6138 :
6139 0 : if (ACCESS_FLAG(F_CF)) {
6140 0 : lo = 1 + (d & 0xFFFF) + (s & 0xFFFF);
6141 0 : res = 1 + d + s;
6142 0 : } else {
6143 0 : lo = (d & 0xFFFF) + (s & 0xFFFF);
6144 0 : res = d + s;
6145 : }
6146 0 : hi = (lo >> 16) + (d >> 16) + (s >> 16);
6147 :
6148 0 : CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6149 0 : CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6150 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6151 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6152 :
6153 : /* calculate the carry chain SEE NOTE AT TOP. */
6154 0 : cc = (s & d) | ((~res) & (s | d));
6155 0 : CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6156 0 : CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6157 0 : return res;
6158 : }
6159 :
6160 : /*
6161 : * REMARKS:
6162 : * Implements the ADD instruction and side effects.
6163 : */
6164 : static uint8_t
6165 0 : add_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6166 : {
6167 : uint32_t res; /* all operands in native machine order */
6168 : uint32_t cc;
6169 :
6170 0 : res = d + s;
6171 0 : CONDITIONAL_SET_FLAG(res & 0x100, F_CF);
6172 0 : CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6173 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6174 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6175 :
6176 : /* calculate the carry chain SEE NOTE AT TOP. */
6177 0 : cc = (s & d) | ((~res) & (s | d));
6178 0 : CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6179 0 : CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6180 0 : return (uint8_t) res;
6181 : }
6182 :
6183 : /*
6184 : * REMARKS:
6185 : * Implements the ADD instruction and side effects.
6186 : */
6187 : static uint16_t
6188 0 : add_word(struct x86emu *emu, uint16_t d, uint16_t s)
6189 : {
6190 : uint32_t res; /* all operands in native machine order */
6191 : uint32_t cc;
6192 :
6193 0 : res = d + s;
6194 0 : CONDITIONAL_SET_FLAG(res & 0x10000, F_CF);
6195 0 : CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6196 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6197 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6198 :
6199 : /* calculate the carry chain SEE NOTE AT TOP. */
6200 0 : cc = (s & d) | ((~res) & (s | d));
6201 0 : CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6202 0 : CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6203 0 : return (uint16_t) res;
6204 : }
6205 :
6206 : /*
6207 : * REMARKS:
6208 : * Implements the ADD instruction and side effects.
6209 : */
6210 : static uint32_t
6211 0 : add_long(struct x86emu *emu, uint32_t d, uint32_t s)
6212 : {
6213 : uint32_t lo; /* all operands in native machine order */
6214 : uint32_t hi;
6215 : uint32_t res;
6216 : uint32_t cc;
6217 :
6218 0 : lo = (d & 0xFFFF) + (s & 0xFFFF);
6219 0 : res = d + s;
6220 0 : hi = (lo >> 16) + (d >> 16) + (s >> 16);
6221 :
6222 0 : CONDITIONAL_SET_FLAG(hi & 0x10000, F_CF);
6223 0 : CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6224 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6225 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6226 :
6227 : /* calculate the carry chain SEE NOTE AT TOP. */
6228 0 : cc = (s & d) | ((~res) & (s | d));
6229 0 : CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6230 0 : CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6231 :
6232 0 : return res;
6233 : }
6234 :
6235 : /*
6236 : * REMARKS:
6237 : * Implements the AND instruction and side effects.
6238 : */
6239 : static uint8_t
6240 0 : and_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6241 : {
6242 : uint8_t res; /* all operands in native machine order */
6243 :
6244 0 : res = d & s;
6245 :
6246 : /* set the flags */
6247 0 : CLEAR_FLAG(F_OF);
6248 0 : CLEAR_FLAG(F_CF);
6249 0 : CLEAR_FLAG(F_AF);
6250 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6251 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6252 0 : CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6253 0 : return res;
6254 : }
6255 :
6256 : /*
6257 : * REMARKS:
6258 : * Implements the AND instruction and side effects.
6259 : */
6260 : static uint16_t
6261 0 : and_word(struct x86emu *emu, uint16_t d, uint16_t s)
6262 : {
6263 : uint16_t res; /* all operands in native machine order */
6264 :
6265 0 : res = d & s;
6266 :
6267 : /* set the flags */
6268 0 : CLEAR_FLAG(F_OF);
6269 0 : CLEAR_FLAG(F_CF);
6270 0 : CLEAR_FLAG(F_AF);
6271 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6272 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6273 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6274 0 : return res;
6275 : }
6276 :
6277 : /*
6278 : * REMARKS:
6279 : * Implements the AND instruction and side effects.
6280 : */
6281 : static uint32_t
6282 0 : and_long(struct x86emu *emu, uint32_t d, uint32_t s)
6283 : {
6284 : uint32_t res; /* all operands in native machine order */
6285 :
6286 0 : res = d & s;
6287 :
6288 : /* set the flags */
6289 0 : CLEAR_FLAG(F_OF);
6290 0 : CLEAR_FLAG(F_CF);
6291 0 : CLEAR_FLAG(F_AF);
6292 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6293 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6294 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6295 0 : return res;
6296 : }
6297 :
6298 : /*
6299 : * REMARKS:
6300 : * Implements the CMP instruction and side effects.
6301 : */
6302 : static uint8_t
6303 0 : cmp_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6304 : {
6305 : uint32_t res; /* all operands in native machine order */
6306 : uint32_t bc;
6307 :
6308 0 : res = d - s;
6309 0 : CLEAR_FLAG(F_CF);
6310 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6311 0 : CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6312 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6313 :
6314 : /* calculate the borrow chain. See note at top */
6315 0 : bc = (res & (~d | s)) | (~d & s);
6316 0 : CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
6317 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6318 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6319 0 : return d;
6320 : }
6321 :
6322 : static void
6323 0 : cmp_byte_no_return(struct x86emu *emu, uint8_t d, uint8_t s)
6324 : {
6325 0 : cmp_byte(emu, d, s);
6326 0 : }
6327 :
6328 : /*
6329 : * REMARKS:
6330 : * Implements the CMP instruction and side effects.
6331 : */
6332 : static uint16_t
6333 0 : cmp_word(struct x86emu *emu, uint16_t d, uint16_t s)
6334 : {
6335 : uint32_t res; /* all operands in native machine order */
6336 : uint32_t bc;
6337 :
6338 0 : res = d - s;
6339 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6340 0 : CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6341 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6342 :
6343 : /* calculate the borrow chain. See note at top */
6344 0 : bc = (res & (~d | s)) | (~d & s);
6345 0 : CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
6346 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6347 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6348 0 : return d;
6349 : }
6350 :
6351 : static void
6352 0 : cmp_word_no_return(struct x86emu *emu, uint16_t d, uint16_t s)
6353 : {
6354 0 : cmp_word(emu, d, s);
6355 0 : }
6356 :
6357 : /*
6358 : * REMARKS:
6359 : * Implements the CMP instruction and side effects.
6360 : */
6361 : static uint32_t
6362 0 : cmp_long(struct x86emu *emu, uint32_t d, uint32_t s)
6363 : {
6364 : uint32_t res; /* all operands in native machine order */
6365 : uint32_t bc;
6366 :
6367 0 : res = d - s;
6368 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6369 0 : CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6370 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6371 :
6372 : /* calculate the borrow chain. See note at top */
6373 0 : bc = (res & (~d | s)) | (~d & s);
6374 0 : CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
6375 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6376 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6377 0 : return d;
6378 : }
6379 :
6380 : static void
6381 0 : cmp_long_no_return(struct x86emu *emu, uint32_t d, uint32_t s)
6382 : {
6383 0 : cmp_long(emu, d, s);
6384 0 : }
6385 :
6386 : /*
6387 : * REMARKS:
6388 : * Implements the DAA instruction and side effects.
6389 : */
6390 : static uint8_t
6391 0 : daa_byte(struct x86emu *emu, uint8_t d)
6392 : {
6393 0 : uint32_t res = d;
6394 0 : if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6395 0 : res += 6;
6396 0 : SET_FLAG(F_AF);
6397 0 : }
6398 0 : if (res > 0x9F || ACCESS_FLAG(F_CF)) {
6399 0 : res += 0x60;
6400 0 : SET_FLAG(F_CF);
6401 0 : }
6402 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6403 0 : CONDITIONAL_SET_FLAG((res & 0xFF) == 0, F_ZF);
6404 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6405 0 : return (uint8_t) res;
6406 : }
6407 :
6408 : /*
6409 : * REMARKS:
6410 : * Implements the DAS instruction and side effects.
6411 : */
6412 : static uint8_t
6413 0 : das_byte(struct x86emu *emu, uint8_t d)
6414 : {
6415 0 : if ((d & 0xf) > 9 || ACCESS_FLAG(F_AF)) {
6416 0 : d -= 6;
6417 0 : SET_FLAG(F_AF);
6418 0 : }
6419 0 : if (d > 0x9F || ACCESS_FLAG(F_CF)) {
6420 0 : d -= 0x60;
6421 0 : SET_FLAG(F_CF);
6422 0 : }
6423 0 : CONDITIONAL_SET_FLAG(d & 0x80, F_SF);
6424 0 : CONDITIONAL_SET_FLAG(d == 0, F_ZF);
6425 0 : CONDITIONAL_SET_FLAG(PARITY(d & 0xff), F_PF);
6426 0 : return d;
6427 : }
6428 :
6429 : /*
6430 : * REMARKS:
6431 : * Implements the DEC instruction and side effects.
6432 : */
6433 : static uint8_t
6434 0 : dec_byte(struct x86emu *emu, uint8_t d)
6435 : {
6436 : uint32_t res; /* all operands in native machine order */
6437 : uint32_t bc;
6438 :
6439 0 : res = d - 1;
6440 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6441 0 : CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6442 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6443 :
6444 : /* calculate the borrow chain. See note at top */
6445 : /* based on sub_byte, uses s==1. */
6446 0 : bc = (res & (~d | 1)) | (~d & 1);
6447 : /* carry flag unchanged */
6448 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6449 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6450 0 : return (uint8_t) res;
6451 : }
6452 :
6453 : /*
6454 : * REMARKS:
6455 : * Implements the DEC instruction and side effects.
6456 : */
6457 : static uint16_t
6458 0 : dec_word(struct x86emu *emu, uint16_t d)
6459 : {
6460 : uint32_t res; /* all operands in native machine order */
6461 : uint32_t bc;
6462 :
6463 0 : res = d - 1;
6464 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6465 0 : CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6466 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6467 :
6468 : /* calculate the borrow chain. See note at top */
6469 : /* based on the sub_byte routine, with s==1 */
6470 0 : bc = (res & (~d | 1)) | (~d & 1);
6471 : /* carry flag unchanged */
6472 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6473 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6474 0 : return (uint16_t) res;
6475 : }
6476 :
6477 : /*
6478 : * REMARKS:
6479 : * Implements the DEC instruction and side effects.
6480 : */
6481 : static uint32_t
6482 0 : dec_long(struct x86emu *emu, uint32_t d)
6483 : {
6484 : uint32_t res; /* all operands in native machine order */
6485 : uint32_t bc;
6486 :
6487 0 : res = d - 1;
6488 :
6489 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6490 0 : CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6491 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6492 :
6493 : /* calculate the borrow chain. See note at top */
6494 0 : bc = (res & (~d | 1)) | (~d & 1);
6495 : /* carry flag unchanged */
6496 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6497 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6498 0 : return res;
6499 : }
6500 :
6501 : /*
6502 : * REMARKS:
6503 : * Implements the INC instruction and side effects.
6504 : */
6505 : static uint8_t
6506 0 : inc_byte(struct x86emu *emu, uint8_t d)
6507 : {
6508 : uint32_t res; /* all operands in native machine order */
6509 : uint32_t cc;
6510 :
6511 0 : res = d + 1;
6512 0 : CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6513 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6514 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6515 :
6516 : /* calculate the carry chain SEE NOTE AT TOP. */
6517 0 : cc = ((1 & d) | (~res)) & (1 | d);
6518 0 : CONDITIONAL_SET_FLAG(XOR2(cc >> 6), F_OF);
6519 0 : CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6520 0 : return (uint8_t) res;
6521 : }
6522 :
6523 : /*
6524 : * REMARKS:
6525 : * Implements the INC instruction and side effects.
6526 : */
6527 : static uint16_t
6528 0 : inc_word(struct x86emu *emu, uint16_t d)
6529 : {
6530 : uint32_t res; /* all operands in native machine order */
6531 : uint32_t cc;
6532 :
6533 0 : res = d + 1;
6534 0 : CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6535 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6536 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6537 :
6538 : /* calculate the carry chain SEE NOTE AT TOP. */
6539 0 : cc = (1 & d) | ((~res) & (1 | d));
6540 0 : CONDITIONAL_SET_FLAG(XOR2(cc >> 14), F_OF);
6541 0 : CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6542 0 : return (uint16_t) res;
6543 : }
6544 :
6545 : /*
6546 : * REMARKS:
6547 : * Implements the INC instruction and side effects.
6548 : */
6549 : static uint32_t
6550 0 : inc_long(struct x86emu *emu, uint32_t d)
6551 : {
6552 : uint32_t res; /* all operands in native machine order */
6553 : uint32_t cc;
6554 :
6555 0 : res = d + 1;
6556 0 : CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6557 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6558 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6559 :
6560 : /* calculate the carry chain SEE NOTE AT TOP. */
6561 0 : cc = (1 & d) | ((~res) & (1 | d));
6562 0 : CONDITIONAL_SET_FLAG(XOR2(cc >> 30), F_OF);
6563 0 : CONDITIONAL_SET_FLAG(cc & 0x8, F_AF);
6564 0 : return res;
6565 : }
6566 :
6567 : /*
6568 : * REMARKS:
6569 : * Implements the OR instruction and side effects.
6570 : */
6571 : static uint8_t
6572 0 : or_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6573 : {
6574 : uint8_t res; /* all operands in native machine order */
6575 :
6576 0 : res = d | s;
6577 0 : CLEAR_FLAG(F_OF);
6578 0 : CLEAR_FLAG(F_CF);
6579 0 : CLEAR_FLAG(F_AF);
6580 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6581 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6582 0 : CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6583 0 : return res;
6584 : }
6585 :
6586 : /*
6587 : * REMARKS:
6588 : * Implements the OR instruction and side effects.
6589 : */
6590 : static uint16_t
6591 0 : or_word(struct x86emu *emu, uint16_t d, uint16_t s)
6592 : {
6593 : uint16_t res; /* all operands in native machine order */
6594 :
6595 0 : res = d | s;
6596 : /* set the carry flag to be bit 8 */
6597 0 : CLEAR_FLAG(F_OF);
6598 0 : CLEAR_FLAG(F_CF);
6599 0 : CLEAR_FLAG(F_AF);
6600 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6601 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6602 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6603 0 : return res;
6604 : }
6605 :
6606 : /*
6607 : * REMARKS:
6608 : * Implements the OR instruction and side effects.
6609 : */
6610 : static uint32_t
6611 0 : or_long(struct x86emu *emu, uint32_t d, uint32_t s)
6612 : {
6613 : uint32_t res; /* all operands in native machine order */
6614 :
6615 0 : res = d | s;
6616 :
6617 : /* set the carry flag to be bit 8 */
6618 0 : CLEAR_FLAG(F_OF);
6619 0 : CLEAR_FLAG(F_CF);
6620 0 : CLEAR_FLAG(F_AF);
6621 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6622 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
6623 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6624 0 : return res;
6625 : }
6626 :
6627 : /*
6628 : * REMARKS:
6629 : * Implements the OR instruction and side effects.
6630 : */
6631 : static uint8_t
6632 0 : neg_byte(struct x86emu *emu, uint8_t s)
6633 : {
6634 : uint8_t res;
6635 : uint8_t bc;
6636 :
6637 0 : CONDITIONAL_SET_FLAG(s != 0, F_CF);
6638 0 : res = (uint8_t) - s;
6639 0 : CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
6640 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
6641 0 : CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
6642 : /* calculate the borrow chain --- modified such that d=0.
6643 : * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6644 : * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6645 : * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6646 : * result is: */
6647 0 : bc = res | s;
6648 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
6649 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6650 0 : return res;
6651 : }
6652 :
6653 : /*
6654 : * REMARKS:
6655 : * Implements the OR instruction and side effects.
6656 : */
6657 : static uint16_t
6658 0 : neg_word(struct x86emu *emu, uint16_t s)
6659 : {
6660 : uint16_t res;
6661 : uint16_t bc;
6662 :
6663 0 : CONDITIONAL_SET_FLAG(s != 0, F_CF);
6664 0 : res = (uint16_t) - s;
6665 0 : CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
6666 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
6667 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6668 :
6669 : /* calculate the borrow chain --- modified such that d=0.
6670 : * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6671 : * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6672 : * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6673 : * result is: */
6674 0 : bc = res | s;
6675 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
6676 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6677 0 : return res;
6678 : }
6679 :
6680 : /*
6681 : * REMARKS:
6682 : * Implements the OR instruction and side effects.
6683 : */
6684 : static uint32_t
6685 0 : neg_long(struct x86emu *emu, uint32_t s)
6686 : {
6687 : uint32_t res;
6688 : uint32_t bc;
6689 :
6690 0 : CONDITIONAL_SET_FLAG(s != 0, F_CF);
6691 0 : res = (uint32_t) - s;
6692 0 : CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
6693 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
6694 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
6695 :
6696 : /* calculate the borrow chain --- modified such that d=0.
6697 : * substitutiing d=0 into bc= res&(~d|s)|(~d&s); (the one used for
6698 : * sub) and simplifying, since ~d=0xff..., ~d|s == 0xffff..., and
6699 : * res&0xfff... == res. Similarly ~d&s == s. So the simplified
6700 : * result is: */
6701 0 : bc = res | s;
6702 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
6703 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
6704 0 : return res;
6705 : }
6706 :
6707 : /*
6708 : * REMARKS:
6709 : * Implements the RCL instruction and side effects.
6710 : */
6711 : static uint8_t
6712 0 : rcl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6713 : {
6714 : unsigned int res, cnt, mask, cf;
6715 :
6716 : /* s is the rotate distance. It varies from 0 - 8. */
6717 : /* have
6718 : *
6719 : * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6720 : *
6721 : * want to rotate through the carry by "s" bits. We could loop, but
6722 : * that's inefficient. So the width is 9, and we split into three
6723 : * parts:
6724 : *
6725 : * The new carry flag (was B_n) the stuff in B_n-1 .. B_0 the stuff
6726 : * in B_7 .. B_n+1
6727 : *
6728 : * The new rotate is done mod 9, and given this, for a rotation of n
6729 : * bits (mod 9) the new carry flag is then located n bits from the MSB.
6730 : * The low part is then shifted up cnt bits, and the high part is or'd
6731 : * in. Using CAPS for new values, and lowercase for the original
6732 : * values, this can be expressed as:
6733 : *
6734 : * IF n > 0 1) CF <- b_(8-n) 2) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
6735 : * 3) B_(n-1) <- cf 4) B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
6736 : */
6737 0 : res = d;
6738 0 : if ((cnt = s % 9) != 0) {
6739 : /* extract the new CARRY FLAG. */
6740 : /* CF <- b_(8-n) */
6741 0 : cf = (d >> (8 - cnt)) & 0x1;
6742 :
6743 : /*
6744 : * Get the low stuff which rotated into the range B_7 .. B_cnt
6745 : * B_(7) .. B_(n) <- b_(8-(n+1)) .. b_0
6746 : * note that the right hand side done by the mask.
6747 : */
6748 0 : res = (d << cnt) & 0xff;
6749 :
6750 : /*
6751 : * now the high stuff which rotated around into the positions
6752 : * B_cnt-2 .. B_0
6753 : * B_(n-2) .. B_0 <- b_7 .. b_(8-(n-1))
6754 : * shift it downward, 7-(n-2) = 9-n positions. and mask off
6755 : * the result before or'ing in.
6756 : */
6757 0 : mask = (1 << (cnt - 1)) - 1;
6758 0 : res |= (d >> (9 - cnt)) & mask;
6759 :
6760 : /* if the carry flag was set, or it in. */
6761 0 : if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6762 : /* B_(n-1) <- cf */
6763 0 : res |= 1 << (cnt - 1);
6764 0 : }
6765 : /* set the new carry flag, based on the variable "cf" */
6766 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
6767 : /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6768 : * the most significant bit. Blecck. */
6769 : /* parenthesized this expression since it appears to be
6770 : * causing OF to be misset */
6771 0 : CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 6) & 0x2)),
6772 : F_OF);
6773 :
6774 : }
6775 0 : return (uint8_t) res;
6776 : }
6777 :
6778 : /*
6779 : * REMARKS:
6780 : * Implements the RCL instruction and side effects.
6781 : */
6782 : static uint16_t
6783 0 : rcl_word(struct x86emu *emu, uint16_t d, uint8_t s)
6784 : {
6785 : unsigned int res, cnt, mask, cf;
6786 :
6787 0 : res = d;
6788 0 : if ((cnt = s % 17) != 0) {
6789 0 : cf = (d >> (16 - cnt)) & 0x1;
6790 0 : res = (d << cnt) & 0xffff;
6791 0 : mask = (1 << (cnt - 1)) - 1;
6792 0 : res |= (d >> (17 - cnt)) & mask;
6793 0 : if (ACCESS_FLAG(F_CF)) {
6794 0 : res |= 1 << (cnt - 1);
6795 0 : }
6796 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
6797 0 : CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 14) & 0x2)),
6798 : F_OF);
6799 : }
6800 0 : return (uint16_t) res;
6801 : }
6802 :
6803 : /*
6804 : * REMARKS:
6805 : * Implements the RCL instruction and side effects.
6806 : */
6807 : static uint32_t
6808 0 : rcl_long(struct x86emu *emu, uint32_t d, uint8_t s)
6809 : {
6810 : uint32_t res, cnt, mask, cf;
6811 :
6812 : res = d;
6813 0 : if ((cnt = s % 33) != 0) {
6814 0 : cf = (d >> (32 - cnt)) & 0x1;
6815 0 : res = (d << cnt) & 0xffffffff;
6816 0 : mask = (1 << (cnt - 1)) - 1;
6817 0 : res |= (d >> (33 - cnt)) & mask;
6818 0 : if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6819 0 : res |= 1 << (cnt - 1);
6820 0 : }
6821 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
6822 0 : CONDITIONAL_SET_FLAG(cnt == 1 && XOR2(cf + ((res >> 30) & 0x2)),
6823 : F_OF);
6824 : }
6825 0 : return res;
6826 : }
6827 :
6828 : /*
6829 : * REMARKS:
6830 : * Implements the RCR instruction and side effects.
6831 : */
6832 : static uint8_t
6833 0 : rcr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6834 : {
6835 : uint32_t res, cnt;
6836 : uint32_t mask, cf, ocf = 0;
6837 :
6838 : /* rotate right through carry */
6839 : /* s is the rotate distance. It varies from 0 - 8. d is the byte
6840 : * object rotated.
6841 : *
6842 : * have
6843 : *
6844 : * CF B_7 B_6 B_5 B_4 B_3 B_2 B_1 B_0
6845 : *
6846 : * The new rotate is done mod 9, and given this, for a rotation of n
6847 : * bits (mod 9) the new carry flag is then located n bits from the LSB.
6848 : * The low part is then shifted up cnt bits, and the high part is or'd
6849 : * in. Using CAPS for new values, and lowercase for the original
6850 : * values, this can be expressed as:
6851 : *
6852 : * IF n > 0
6853 : * 1) CF <- b_(n-1)
6854 : * 2) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n)
6855 : * 3) B_(8-n) <- cf 4) B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0)
6856 : */
6857 0 : res = d;
6858 0 : if ((cnt = s % 9) != 0) {
6859 : /* extract the new CARRY FLAG. */
6860 : /* CF <- b_(n-1) */
6861 0 : if (cnt == 1) {
6862 0 : cf = d & 0x1;
6863 : /* note hackery here. Access_flag(..) evaluates to
6864 : * either 0 if flag not set non-zero if flag is set.
6865 : * doing access_flag(..) != 0 casts that into either
6866 : * 0..1 in any representation of the flags register
6867 : * (i.e. packed bit array or unpacked.) */
6868 0 : ocf = ACCESS_FLAG(F_CF) != 0;
6869 0 : } else
6870 0 : cf = (d >> (cnt - 1)) & 0x1;
6871 :
6872 : /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_n */
6873 : /* note that the right hand side done by the mask This is
6874 : * effectively done by shifting the object to the right. The
6875 : * result must be masked, in case the object came in and was
6876 : * treated as a negative number. Needed??? */
6877 :
6878 0 : mask = (1 << (8 - cnt)) - 1;
6879 0 : res = (d >> cnt) & mask;
6880 :
6881 : /* now the high stuff which rotated around into the positions
6882 : * B_cnt-2 .. B_0 */
6883 : /* B_(7) .. B_(8-(n-1)) <- b_(n-2) .. b_(0) */
6884 : /* shift it downward, 7-(n-2) = 9-n positions. and mask off
6885 : * the result before or'ing in. */
6886 0 : res |= (d << (9 - cnt));
6887 :
6888 : /* if the carry flag was set, or it in. */
6889 0 : if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6890 : /* B_(8-n) <- cf */
6891 0 : res |= 1 << (8 - cnt);
6892 0 : }
6893 : /* set the new carry flag, based on the variable "cf" */
6894 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
6895 : /* OVERFLOW is set *IFF* cnt==1, then it is the xor of CF and
6896 : * the most significant bit. Blecck. */
6897 : /* parenthesized... */
6898 0 : if (cnt == 1) {
6899 0 : CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 6) & 0x2)),
6900 : F_OF);
6901 : }
6902 : }
6903 0 : return (uint8_t) res;
6904 : }
6905 :
6906 : /*
6907 : * REMARKS:
6908 : * Implements the RCR instruction and side effects.
6909 : */
6910 : static uint16_t
6911 0 : rcr_word(struct x86emu *emu, uint16_t d, uint8_t s)
6912 : {
6913 : uint32_t res, cnt;
6914 : uint32_t mask, cf, ocf = 0;
6915 :
6916 : /* rotate right through carry */
6917 0 : res = d;
6918 0 : if ((cnt = s % 17) != 0) {
6919 0 : if (cnt == 1) {
6920 0 : cf = d & 0x1;
6921 0 : ocf = ACCESS_FLAG(F_CF) != 0;
6922 0 : } else
6923 0 : cf = (d >> (cnt - 1)) & 0x1;
6924 0 : mask = (1 << (16 - cnt)) - 1;
6925 0 : res = (d >> cnt) & mask;
6926 0 : res |= (d << (17 - cnt));
6927 0 : if (ACCESS_FLAG(F_CF)) {
6928 0 : res |= 1 << (16 - cnt);
6929 0 : }
6930 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
6931 0 : if (cnt == 1) {
6932 0 : CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 14) & 0x2)),
6933 : F_OF);
6934 : }
6935 : }
6936 0 : return (uint16_t) res;
6937 : }
6938 :
6939 : /*
6940 : * REMARKS:
6941 : * Implements the RCR instruction and side effects.
6942 : */
6943 : static uint32_t
6944 0 : rcr_long(struct x86emu *emu, uint32_t d, uint8_t s)
6945 : {
6946 : uint32_t res, cnt;
6947 : uint32_t mask, cf, ocf = 0;
6948 :
6949 : /* rotate right through carry */
6950 : res = d;
6951 0 : if ((cnt = s % 33) != 0) {
6952 0 : if (cnt == 1) {
6953 0 : cf = d & 0x1;
6954 0 : ocf = ACCESS_FLAG(F_CF) != 0;
6955 0 : } else
6956 0 : cf = (d >> (cnt - 1)) & 0x1;
6957 0 : mask = (1 << (32 - cnt)) - 1;
6958 0 : res = (d >> cnt) & mask;
6959 0 : if (cnt != 1)
6960 0 : res |= (d << (33 - cnt));
6961 0 : if (ACCESS_FLAG(F_CF)) { /* carry flag is set */
6962 0 : res |= 1 << (32 - cnt);
6963 0 : }
6964 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
6965 0 : if (cnt == 1) {
6966 0 : CONDITIONAL_SET_FLAG(XOR2(ocf + ((d >> 30) & 0x2)),
6967 : F_OF);
6968 : }
6969 : }
6970 0 : return res;
6971 : }
6972 :
6973 : /*
6974 : * REMARKS:
6975 : * Implements the ROL instruction and side effects.
6976 : */
6977 : static uint8_t
6978 0 : rol_byte(struct x86emu *emu, uint8_t d, uint8_t s)
6979 : {
6980 : unsigned int res, cnt, mask;
6981 :
6982 : /* rotate left */
6983 : /* s is the rotate distance. It varies from 0 - 8. d is the byte
6984 : * object rotated.
6985 : *
6986 : * have
6987 : *
6988 : * CF B_7 ... B_0
6989 : *
6990 : * The new rotate is done mod 8. Much simpler than the "rcl" or "rcr"
6991 : * operations.
6992 : *
6993 : * IF n > 0 1) B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) 2) B_(n-1) ..
6994 : * B_(0) <- b_(7) .. b_(8-n) */
6995 0 : res = d;
6996 0 : if ((cnt = s % 8) != 0) {
6997 : /* B_(7) .. B_(n) <- b_(8-(n+1)) .. b_(0) */
6998 0 : res = (d << cnt);
6999 :
7000 : /* B_(n-1) .. B_(0) <- b_(7) .. b_(8-n) */
7001 0 : mask = (1 << cnt) - 1;
7002 0 : res |= (d >> (8 - cnt)) & mask;
7003 :
7004 : /* set the new carry flag, Note that it is the low order bit
7005 : * of the result!!! */
7006 0 : CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7007 : /* OVERFLOW is set *IFF* s==1, then it is the xor of CF and
7008 : * the most significant bit. Blecck. */
7009 0 : CONDITIONAL_SET_FLAG(s == 1 &&
7010 : XOR2((res & 0x1) + ((res >> 6) & 0x2)),
7011 : F_OF);
7012 0 : } if (s != 0) {
7013 : /* set the new carry flag, Note that it is the low order bit
7014 : * of the result!!! */
7015 0 : CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7016 : }
7017 0 : return (uint8_t) res;
7018 : }
7019 :
7020 : /*
7021 : * REMARKS:
7022 : * Implements the ROL instruction and side effects.
7023 : */
7024 : static uint16_t
7025 0 : rol_word(struct x86emu *emu, uint16_t d, uint8_t s)
7026 : {
7027 : unsigned int res, cnt, mask;
7028 :
7029 0 : res = d;
7030 0 : if ((cnt = s % 16) != 0) {
7031 0 : res = (d << cnt);
7032 0 : mask = (1 << cnt) - 1;
7033 0 : res |= (d >> (16 - cnt)) & mask;
7034 0 : CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7035 0 : CONDITIONAL_SET_FLAG(s == 1 &&
7036 : XOR2((res & 0x1) + ((res >> 14) & 0x2)),
7037 : F_OF);
7038 0 : } if (s != 0) {
7039 : /* set the new carry flag, Note that it is the low order bit
7040 : * of the result!!! */
7041 0 : CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7042 : }
7043 0 : return (uint16_t) res;
7044 : }
7045 :
7046 : /*
7047 : * REMARKS:
7048 : * Implements the ROL instruction and side effects.
7049 : */
7050 : static uint32_t
7051 0 : rol_long(struct x86emu *emu, uint32_t d, uint8_t s)
7052 : {
7053 : uint32_t res, cnt, mask;
7054 :
7055 : res = d;
7056 0 : if ((cnt = s % 32) != 0) {
7057 0 : res = (d << cnt);
7058 0 : mask = (1 << cnt) - 1;
7059 0 : res |= (d >> (32 - cnt)) & mask;
7060 0 : CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7061 0 : CONDITIONAL_SET_FLAG(s == 1 &&
7062 : XOR2((res & 0x1) + ((res >> 30) & 0x2)),
7063 : F_OF);
7064 0 : } if (s != 0) {
7065 : /* set the new carry flag, Note that it is the low order bit
7066 : * of the result!!! */
7067 0 : CONDITIONAL_SET_FLAG(res & 0x1, F_CF);
7068 : }
7069 0 : return res;
7070 : }
7071 :
7072 : /*
7073 : * REMARKS:
7074 : * Implements the ROR instruction and side effects.
7075 : */
7076 : static uint8_t
7077 0 : ror_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7078 : {
7079 : unsigned int res, cnt, mask;
7080 :
7081 : /* rotate right */
7082 : /* s is the rotate distance. It varies from 0 - 8. d is the byte
7083 : * object rotated.
7084 : *
7085 : * have
7086 : *
7087 : * B_7 ... B_0
7088 : *
7089 : * The rotate is done mod 8.
7090 : *
7091 : * IF n > 0 1) B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) 2) B_(7) ..
7092 : * B_(8-n) <- b_(n-1) .. b_(0) */
7093 0 : res = d;
7094 0 : if ((cnt = s % 8) != 0) { /* not a typo, do nada if cnt==0 */
7095 : /* B_(7) .. B_(8-n) <- b_(n-1) .. b_(0) */
7096 0 : res = (d << (8 - cnt));
7097 :
7098 : /* B_(8-(n+1)) .. B_(0) <- b_(7) .. b_(n) */
7099 0 : mask = (1 << (8 - cnt)) - 1;
7100 0 : res |= (d >> (cnt)) & mask;
7101 :
7102 : /* set the new carry flag, Note that it is the low order bit
7103 : * of the result!!! */
7104 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
7105 : /* OVERFLOW is set *IFF* s==1, then it is the xor of the two
7106 : * most significant bits. Blecck. */
7107 0 : CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 6), F_OF);
7108 0 : } else if (s != 0) {
7109 : /* set the new carry flag, Note that it is the low order bit
7110 : * of the result!!! */
7111 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_CF);
7112 : }
7113 0 : return (uint8_t) res;
7114 : }
7115 :
7116 : /*
7117 : * REMARKS:
7118 : * Implements the ROR instruction and side effects.
7119 : */
7120 : static uint16_t
7121 0 : ror_word(struct x86emu *emu, uint16_t d, uint8_t s)
7122 : {
7123 : unsigned int res, cnt, mask;
7124 :
7125 0 : res = d;
7126 0 : if ((cnt = s % 16) != 0) {
7127 0 : res = (d << (16 - cnt));
7128 0 : mask = (1 << (16 - cnt)) - 1;
7129 0 : res |= (d >> (cnt)) & mask;
7130 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
7131 0 : CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 14), F_OF);
7132 0 : } else if (s != 0) {
7133 : /* set the new carry flag, Note that it is the low order bit
7134 : * of the result!!! */
7135 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_CF);
7136 : }
7137 0 : return (uint16_t) res;
7138 : }
7139 :
7140 : /*
7141 : * REMARKS:
7142 : * Implements the ROR instruction and side effects.
7143 : */
7144 : static uint32_t
7145 0 : ror_long(struct x86emu *emu, uint32_t d, uint8_t s)
7146 : {
7147 : uint32_t res, cnt, mask;
7148 :
7149 : res = d;
7150 0 : if ((cnt = s % 32) != 0) {
7151 0 : res = (d << (32 - cnt));
7152 0 : mask = (1 << (32 - cnt)) - 1;
7153 0 : res |= (d >> (cnt)) & mask;
7154 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
7155 0 : CONDITIONAL_SET_FLAG(s == 1 && XOR2(res >> 30), F_OF);
7156 0 : } else if (s != 0) {
7157 : /* set the new carry flag, Note that it is the low order bit
7158 : * of the result!!! */
7159 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_CF);
7160 : }
7161 0 : return res;
7162 : }
7163 :
7164 : /*
7165 : * REMARKS:
7166 : * Implements the SHL instruction and side effects.
7167 : */
7168 : static uint8_t
7169 0 : shl_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7170 : {
7171 : unsigned int cnt, res, cf;
7172 :
7173 0 : if (s < 8) {
7174 0 : cnt = s % 8;
7175 :
7176 : /* last bit shifted out goes into carry flag */
7177 0 : if (cnt > 0) {
7178 0 : res = d << cnt;
7179 0 : cf = d & (1 << (8 - cnt));
7180 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
7181 0 : CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7182 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7183 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7184 : } else {
7185 : res = (uint8_t) d;
7186 : }
7187 :
7188 0 : if (cnt == 1) {
7189 : /* Needs simplification. */
7190 0 : CONDITIONAL_SET_FLAG(
7191 : (((res & 0x80) == 0x80) ^
7192 : (ACCESS_FLAG(F_CF) != 0)),
7193 : /* was (emu->x86.R_FLG&F_CF)==F_CF)), */
7194 : F_OF);
7195 : } else {
7196 0 : CLEAR_FLAG(F_OF);
7197 : }
7198 : } else {
7199 : res = 0;
7200 0 : CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80, F_CF);
7201 0 : CLEAR_FLAG(F_OF);
7202 0 : CLEAR_FLAG(F_SF);
7203 0 : SET_FLAG(F_PF);
7204 0 : SET_FLAG(F_ZF);
7205 : }
7206 0 : return (uint8_t) res;
7207 : }
7208 :
7209 : /*
7210 : * REMARKS:
7211 : * Implements the SHL instruction and side effects.
7212 : */
7213 : static uint16_t
7214 0 : shl_word(struct x86emu *emu, uint16_t d, uint8_t s)
7215 : {
7216 : unsigned int cnt, res, cf;
7217 :
7218 0 : if (s < 16) {
7219 0 : cnt = s % 16;
7220 0 : if (cnt > 0) {
7221 0 : res = d << cnt;
7222 0 : cf = d & (1 << (16 - cnt));
7223 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
7224 0 : CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7225 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7226 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7227 : } else {
7228 : res = (uint16_t) d;
7229 : }
7230 :
7231 0 : if (cnt == 1) {
7232 0 : CONDITIONAL_SET_FLAG(
7233 : (((res & 0x8000) == 0x8000) ^
7234 : (ACCESS_FLAG(F_CF) != 0)),
7235 : F_OF);
7236 : } else {
7237 0 : CLEAR_FLAG(F_OF);
7238 : }
7239 : } else {
7240 : res = 0;
7241 0 : CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7242 0 : CLEAR_FLAG(F_OF);
7243 0 : CLEAR_FLAG(F_SF);
7244 0 : SET_FLAG(F_PF);
7245 0 : SET_FLAG(F_ZF);
7246 : }
7247 0 : return (uint16_t) res;
7248 : }
7249 :
7250 : /*
7251 : * REMARKS:
7252 : * Implements the SHL instruction and side effects.
7253 : */
7254 : static uint32_t
7255 0 : shl_long(struct x86emu *emu, uint32_t d, uint8_t s)
7256 : {
7257 : unsigned int cnt, res, cf;
7258 :
7259 0 : if (s < 32) {
7260 0 : cnt = s % 32;
7261 0 : if (cnt > 0) {
7262 0 : res = d << cnt;
7263 0 : cf = d & (1 << (32 - cnt));
7264 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
7265 0 : CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7266 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7267 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7268 : } else {
7269 : res = d;
7270 : }
7271 0 : if (cnt == 1) {
7272 0 : CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
7273 : ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
7274 : } else {
7275 0 : CLEAR_FLAG(F_OF);
7276 : }
7277 : } else {
7278 : res = 0;
7279 0 : CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7280 0 : CLEAR_FLAG(F_OF);
7281 0 : CLEAR_FLAG(F_SF);
7282 0 : SET_FLAG(F_PF);
7283 0 : SET_FLAG(F_ZF);
7284 : }
7285 0 : return res;
7286 : }
7287 :
7288 : /*
7289 : * REMARKS:
7290 : * Implements the SHR instruction and side effects.
7291 : */
7292 : static uint8_t
7293 0 : shr_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7294 : {
7295 : unsigned int cnt, res, cf;
7296 :
7297 0 : if (s < 8) {
7298 0 : cnt = s % 8;
7299 0 : if (cnt > 0) {
7300 0 : cf = d & (1 << (cnt - 1));
7301 0 : res = d >> cnt;
7302 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
7303 0 : CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7304 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7305 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7306 : } else {
7307 : res = (uint8_t) d;
7308 : }
7309 :
7310 0 : if (cnt == 1) {
7311 0 : CONDITIONAL_SET_FLAG(XOR2(res >> 6), F_OF);
7312 : } else {
7313 0 : CLEAR_FLAG(F_OF);
7314 : }
7315 : } else {
7316 : res = 0;
7317 0 : CONDITIONAL_SET_FLAG((d >> (s - 1)) & 0x1, F_CF);
7318 0 : CLEAR_FLAG(F_OF);
7319 0 : CLEAR_FLAG(F_SF);
7320 0 : SET_FLAG(F_PF);
7321 0 : SET_FLAG(F_ZF);
7322 : }
7323 0 : return (uint8_t) res;
7324 : }
7325 :
7326 : /*
7327 : * REMARKS:
7328 : * Implements the SHR instruction and side effects.
7329 : */
7330 : static uint16_t
7331 0 : shr_word(struct x86emu *emu, uint16_t d, uint8_t s)
7332 : {
7333 : unsigned int cnt, res, cf;
7334 :
7335 0 : if (s < 16) {
7336 0 : cnt = s % 16;
7337 0 : if (cnt > 0) {
7338 0 : cf = d & (1 << (cnt - 1));
7339 0 : res = d >> cnt;
7340 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
7341 0 : CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7342 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7343 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7344 : } else {
7345 : res = d;
7346 : }
7347 :
7348 0 : if (cnt == 1) {
7349 0 : CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7350 : } else {
7351 0 : CLEAR_FLAG(F_OF);
7352 : }
7353 : } else {
7354 : res = 0;
7355 0 : CLEAR_FLAG(F_CF);
7356 0 : CLEAR_FLAG(F_OF);
7357 0 : SET_FLAG(F_ZF);
7358 0 : CLEAR_FLAG(F_SF);
7359 0 : CLEAR_FLAG(F_PF);
7360 : }
7361 0 : return (uint16_t) res;
7362 : }
7363 :
7364 : /*
7365 : * REMARKS:
7366 : * Implements the SHR instruction and side effects.
7367 : */
7368 : static uint32_t
7369 0 : shr_long(struct x86emu *emu, uint32_t d, uint8_t s)
7370 : {
7371 : unsigned int cnt, res, cf;
7372 :
7373 0 : if (s < 32) {
7374 0 : cnt = s % 32;
7375 0 : if (cnt > 0) {
7376 0 : cf = d & (1 << (cnt - 1));
7377 0 : res = d >> cnt;
7378 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
7379 0 : CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7380 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7381 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7382 : } else {
7383 : res = d;
7384 : }
7385 0 : if (cnt == 1) {
7386 0 : CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7387 : } else {
7388 0 : CLEAR_FLAG(F_OF);
7389 : }
7390 : } else {
7391 : res = 0;
7392 0 : CLEAR_FLAG(F_CF);
7393 0 : CLEAR_FLAG(F_OF);
7394 0 : SET_FLAG(F_ZF);
7395 0 : CLEAR_FLAG(F_SF);
7396 0 : CLEAR_FLAG(F_PF);
7397 : }
7398 0 : return res;
7399 : }
7400 :
7401 : /*
7402 : * REMARKS:
7403 : * Implements the SAR instruction and side effects.
7404 : */
7405 : static uint8_t
7406 0 : sar_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7407 : {
7408 : unsigned int cnt, res, cf, mask, sf;
7409 :
7410 0 : res = d;
7411 0 : sf = d & 0x80;
7412 0 : cnt = s % 8;
7413 0 : if (cnt > 0 && cnt < 8) {
7414 0 : mask = (1 << (8 - cnt)) - 1;
7415 0 : cf = d & (1 << (cnt - 1));
7416 0 : res = (d >> cnt) & mask;
7417 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
7418 0 : if (sf) {
7419 0 : res |= ~mask;
7420 0 : }
7421 0 : CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7422 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7423 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7424 0 : } else if (cnt >= 8) {
7425 0 : if (sf) {
7426 : res = 0xff;
7427 0 : SET_FLAG(F_CF);
7428 0 : CLEAR_FLAG(F_ZF);
7429 0 : SET_FLAG(F_SF);
7430 0 : SET_FLAG(F_PF);
7431 0 : } else {
7432 : res = 0;
7433 0 : CLEAR_FLAG(F_CF);
7434 0 : SET_FLAG(F_ZF);
7435 0 : CLEAR_FLAG(F_SF);
7436 0 : CLEAR_FLAG(F_PF);
7437 : }
7438 : }
7439 0 : return (uint8_t) res;
7440 : }
7441 :
7442 : /*
7443 : * REMARKS:
7444 : * Implements the SAR instruction and side effects.
7445 : */
7446 : static uint16_t
7447 0 : sar_word(struct x86emu *emu, uint16_t d, uint8_t s)
7448 : {
7449 : unsigned int cnt, res, cf, mask, sf;
7450 :
7451 0 : sf = d & 0x8000;
7452 0 : cnt = s % 16;
7453 : res = d;
7454 0 : if (cnt > 0 && cnt < 16) {
7455 0 : mask = (1 << (16 - cnt)) - 1;
7456 0 : cf = d & (1 << (cnt - 1));
7457 0 : res = (d >> cnt) & mask;
7458 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
7459 0 : if (sf) {
7460 0 : res |= ~mask;
7461 0 : }
7462 0 : CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7463 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7464 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7465 0 : } else if (cnt >= 16) {
7466 0 : if (sf) {
7467 : res = 0xffff;
7468 0 : SET_FLAG(F_CF);
7469 0 : CLEAR_FLAG(F_ZF);
7470 0 : SET_FLAG(F_SF);
7471 0 : SET_FLAG(F_PF);
7472 0 : } else {
7473 : res = 0;
7474 0 : CLEAR_FLAG(F_CF);
7475 0 : SET_FLAG(F_ZF);
7476 0 : CLEAR_FLAG(F_SF);
7477 0 : CLEAR_FLAG(F_PF);
7478 : }
7479 : }
7480 0 : return (uint16_t) res;
7481 : }
7482 :
7483 : /*
7484 : * REMARKS:
7485 : * Implements the SAR instruction and side effects.
7486 : */
7487 : static uint32_t
7488 0 : sar_long(struct x86emu *emu, uint32_t d, uint8_t s)
7489 : {
7490 : uint32_t cnt, res, cf, mask, sf;
7491 :
7492 0 : sf = d & 0x80000000;
7493 0 : cnt = s % 32;
7494 : res = d;
7495 0 : if (cnt > 0 && cnt < 32) {
7496 0 : mask = (1 << (32 - cnt)) - 1;
7497 0 : cf = d & (1 << (cnt - 1));
7498 0 : res = (d >> cnt) & mask;
7499 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
7500 0 : if (sf) {
7501 0 : res |= ~mask;
7502 0 : }
7503 0 : CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7504 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7505 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7506 0 : } else if (cnt >= 32) {
7507 0 : if (sf) {
7508 : res = 0xffffffff;
7509 0 : SET_FLAG(F_CF);
7510 0 : CLEAR_FLAG(F_ZF);
7511 0 : SET_FLAG(F_SF);
7512 0 : SET_FLAG(F_PF);
7513 0 : } else {
7514 : res = 0;
7515 0 : CLEAR_FLAG(F_CF);
7516 0 : SET_FLAG(F_ZF);
7517 0 : CLEAR_FLAG(F_SF);
7518 0 : CLEAR_FLAG(F_PF);
7519 : }
7520 : }
7521 0 : return res;
7522 : }
7523 :
7524 : /*
7525 : * REMARKS:
7526 : * Implements the SHLD instruction and side effects.
7527 : */
7528 : static uint16_t
7529 0 : shld_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7530 : {
7531 : unsigned int cnt, res, cf;
7532 :
7533 0 : if (s < 16) {
7534 0 : cnt = s % 16;
7535 0 : if (cnt > 0) {
7536 0 : res = (d << cnt) | (fill >> (16 - cnt));
7537 0 : cf = d & (1 << (16 - cnt));
7538 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
7539 0 : CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7540 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7541 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7542 : } else {
7543 : res = d;
7544 : }
7545 0 : if (cnt == 1) {
7546 0 : CONDITIONAL_SET_FLAG((((res & 0x8000) == 0x8000) ^
7547 : (ACCESS_FLAG(F_CF) != 0)), F_OF);
7548 : } else {
7549 0 : CLEAR_FLAG(F_OF);
7550 : }
7551 : } else {
7552 : res = 0;
7553 0 : CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x8000, F_CF);
7554 0 : CLEAR_FLAG(F_OF);
7555 0 : CLEAR_FLAG(F_SF);
7556 0 : SET_FLAG(F_PF);
7557 0 : SET_FLAG(F_ZF);
7558 : }
7559 0 : return (uint16_t) res;
7560 : }
7561 :
7562 : /*
7563 : * REMARKS:
7564 : * Implements the SHLD instruction and side effects.
7565 : */
7566 : static uint32_t
7567 0 : shld_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7568 : {
7569 : unsigned int cnt, res, cf;
7570 :
7571 0 : if (s < 32) {
7572 0 : cnt = s % 32;
7573 0 : if (cnt > 0) {
7574 0 : res = (d << cnt) | (fill >> (32 - cnt));
7575 0 : cf = d & (1 << (32 - cnt));
7576 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
7577 0 : CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7578 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7579 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7580 : } else {
7581 : res = d;
7582 : }
7583 0 : if (cnt == 1) {
7584 0 : CONDITIONAL_SET_FLAG((((res & 0x80000000) == 0x80000000)
7585 : ^ (ACCESS_FLAG(F_CF) != 0)), F_OF);
7586 : } else {
7587 0 : CLEAR_FLAG(F_OF);
7588 : }
7589 : } else {
7590 : res = 0;
7591 0 : CONDITIONAL_SET_FLAG((d << (s - 1)) & 0x80000000, F_CF);
7592 0 : CLEAR_FLAG(F_OF);
7593 0 : CLEAR_FLAG(F_SF);
7594 0 : SET_FLAG(F_PF);
7595 0 : SET_FLAG(F_ZF);
7596 : }
7597 0 : return res;
7598 : }
7599 :
7600 : /*
7601 : * REMARKS:
7602 : * Implements the SHRD instruction and side effects.
7603 : */
7604 : static uint16_t
7605 0 : shrd_word(struct x86emu *emu, uint16_t d, uint16_t fill, uint8_t s)
7606 : {
7607 : unsigned int cnt, res, cf;
7608 :
7609 0 : if (s < 16) {
7610 0 : cnt = s % 16;
7611 0 : if (cnt > 0) {
7612 0 : cf = d & (1 << (cnt - 1));
7613 0 : res = (d >> cnt) | (fill << (16 - cnt));
7614 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
7615 0 : CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7616 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7617 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7618 : } else {
7619 : res = d;
7620 : }
7621 :
7622 0 : if (cnt == 1) {
7623 0 : CONDITIONAL_SET_FLAG(XOR2(res >> 14), F_OF);
7624 : } else {
7625 0 : CLEAR_FLAG(F_OF);
7626 : }
7627 : } else {
7628 : res = 0;
7629 0 : CLEAR_FLAG(F_CF);
7630 0 : CLEAR_FLAG(F_OF);
7631 0 : SET_FLAG(F_ZF);
7632 0 : CLEAR_FLAG(F_SF);
7633 0 : CLEAR_FLAG(F_PF);
7634 : }
7635 0 : return (uint16_t) res;
7636 : }
7637 :
7638 : /*
7639 : * REMARKS:
7640 : * Implements the SHRD instruction and side effects.
7641 : */
7642 : static uint32_t
7643 0 : shrd_long(struct x86emu *emu, uint32_t d, uint32_t fill, uint8_t s)
7644 : {
7645 : unsigned int cnt, res, cf;
7646 :
7647 0 : if (s < 32) {
7648 0 : cnt = s % 32;
7649 0 : if (cnt > 0) {
7650 0 : cf = d & (1 << (cnt - 1));
7651 0 : res = (d >> cnt) | (fill << (32 - cnt));
7652 0 : CONDITIONAL_SET_FLAG(cf, F_CF);
7653 0 : CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7654 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7655 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7656 : } else {
7657 : res = d;
7658 : }
7659 0 : if (cnt == 1) {
7660 0 : CONDITIONAL_SET_FLAG(XOR2(res >> 30), F_OF);
7661 : } else {
7662 0 : CLEAR_FLAG(F_OF);
7663 : }
7664 : } else {
7665 : res = 0;
7666 0 : CLEAR_FLAG(F_CF);
7667 0 : CLEAR_FLAG(F_OF);
7668 0 : SET_FLAG(F_ZF);
7669 0 : CLEAR_FLAG(F_SF);
7670 0 : CLEAR_FLAG(F_PF);
7671 : }
7672 0 : return res;
7673 : }
7674 :
7675 : /*
7676 : * REMARKS:
7677 : * Implements the SBB instruction and side effects.
7678 : */
7679 : static uint8_t
7680 0 : sbb_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7681 : {
7682 : uint32_t res; /* all operands in native machine order */
7683 : uint32_t bc;
7684 :
7685 0 : if (ACCESS_FLAG(F_CF))
7686 0 : res = d - s - 1;
7687 : else
7688 : res = d - s;
7689 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7690 0 : CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7691 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7692 :
7693 : /* calculate the borrow chain. See note at top */
7694 0 : bc = (res & (~d | s)) | (~d & s);
7695 0 : CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7696 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7697 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7698 0 : return (uint8_t) res;
7699 : }
7700 :
7701 : /*
7702 : * REMARKS:
7703 : * Implements the SBB instruction and side effects.
7704 : */
7705 : static uint16_t
7706 0 : sbb_word(struct x86emu *emu, uint16_t d, uint16_t s)
7707 : {
7708 : uint32_t res; /* all operands in native machine order */
7709 : uint32_t bc;
7710 :
7711 0 : if (ACCESS_FLAG(F_CF))
7712 0 : res = d - s - 1;
7713 : else
7714 : res = d - s;
7715 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7716 0 : CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7717 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7718 :
7719 : /* calculate the borrow chain. See note at top */
7720 0 : bc = (res & (~d | s)) | (~d & s);
7721 0 : CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7722 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7723 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7724 0 : return (uint16_t) res;
7725 : }
7726 :
7727 : /*
7728 : * REMARKS:
7729 : * Implements the SBB instruction and side effects.
7730 : */
7731 : static uint32_t
7732 0 : sbb_long(struct x86emu *emu, uint32_t d, uint32_t s)
7733 : {
7734 : uint32_t res; /* all operands in native machine order */
7735 : uint32_t bc;
7736 :
7737 0 : if (ACCESS_FLAG(F_CF))
7738 0 : res = d - s - 1;
7739 : else
7740 : res = d - s;
7741 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7742 0 : CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7743 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7744 :
7745 : /* calculate the borrow chain. See note at top */
7746 0 : bc = (res & (~d | s)) | (~d & s);
7747 0 : CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7748 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7749 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7750 0 : return res;
7751 : }
7752 :
7753 : /*
7754 : * REMARKS:
7755 : * Implements the SUB instruction and side effects.
7756 : */
7757 : static uint8_t
7758 0 : sub_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7759 : {
7760 : uint32_t res; /* all operands in native machine order */
7761 : uint32_t bc;
7762 :
7763 0 : res = d - s;
7764 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7765 0 : CONDITIONAL_SET_FLAG((res & 0xff) == 0, F_ZF);
7766 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7767 :
7768 : /* calculate the borrow chain. See note at top */
7769 0 : bc = (res & (~d | s)) | (~d & s);
7770 0 : CONDITIONAL_SET_FLAG(bc & 0x80, F_CF);
7771 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 6), F_OF);
7772 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7773 0 : return (uint8_t) res;
7774 : }
7775 :
7776 : /*
7777 : * REMARKS:
7778 : * Implements the SUB instruction and side effects.
7779 : */
7780 : static uint16_t
7781 0 : sub_word(struct x86emu *emu, uint16_t d, uint16_t s)
7782 : {
7783 : uint32_t res; /* all operands in native machine order */
7784 : uint32_t bc;
7785 :
7786 0 : res = d - s;
7787 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7788 0 : CONDITIONAL_SET_FLAG((res & 0xffff) == 0, F_ZF);
7789 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7790 :
7791 : /* calculate the borrow chain. See note at top */
7792 0 : bc = (res & (~d | s)) | (~d & s);
7793 0 : CONDITIONAL_SET_FLAG(bc & 0x8000, F_CF);
7794 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 14), F_OF);
7795 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7796 0 : return (uint16_t) res;
7797 : }
7798 :
7799 : /*
7800 : * REMARKS:
7801 : * Implements the SUB instruction and side effects.
7802 : */
7803 : static uint32_t
7804 0 : sub_long(struct x86emu *emu, uint32_t d, uint32_t s)
7805 : {
7806 : uint32_t res; /* all operands in native machine order */
7807 : uint32_t bc;
7808 :
7809 0 : res = d - s;
7810 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7811 0 : CONDITIONAL_SET_FLAG((res & 0xffffffff) == 0, F_ZF);
7812 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7813 :
7814 : /* calculate the borrow chain. See note at top */
7815 0 : bc = (res & (~d | s)) | (~d & s);
7816 0 : CONDITIONAL_SET_FLAG(bc & 0x80000000, F_CF);
7817 0 : CONDITIONAL_SET_FLAG(XOR2(bc >> 30), F_OF);
7818 0 : CONDITIONAL_SET_FLAG(bc & 0x8, F_AF);
7819 0 : return res;
7820 : }
7821 :
7822 : /*
7823 : * REMARKS:
7824 : * Implements the TEST instruction and side effects.
7825 : */
7826 : static void
7827 0 : test_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7828 : {
7829 : uint32_t res; /* all operands in native machine order */
7830 :
7831 0 : res = d & s;
7832 :
7833 0 : CLEAR_FLAG(F_OF);
7834 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7835 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7836 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7837 : /* AF == dont care */
7838 0 : CLEAR_FLAG(F_CF);
7839 0 : }
7840 :
7841 : /*
7842 : * REMARKS:
7843 : * Implements the TEST instruction and side effects.
7844 : */
7845 : static void
7846 0 : test_word(struct x86emu *emu, uint16_t d, uint16_t s)
7847 : {
7848 : uint32_t res; /* all operands in native machine order */
7849 :
7850 0 : res = d & s;
7851 :
7852 0 : CLEAR_FLAG(F_OF);
7853 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7854 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7855 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7856 : /* AF == dont care */
7857 0 : CLEAR_FLAG(F_CF);
7858 0 : }
7859 :
7860 : /*
7861 : * REMARKS:
7862 : * Implements the TEST instruction and side effects.
7863 : */
7864 : static void
7865 0 : test_long(struct x86emu *emu, uint32_t d, uint32_t s)
7866 : {
7867 : uint32_t res; /* all operands in native machine order */
7868 :
7869 0 : res = d & s;
7870 :
7871 0 : CLEAR_FLAG(F_OF);
7872 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7873 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7874 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7875 : /* AF == dont care */
7876 0 : CLEAR_FLAG(F_CF);
7877 0 : }
7878 :
7879 : /*
7880 : * REMARKS:
7881 : * Implements the XOR instruction and side effects.
7882 : */
7883 : static uint8_t
7884 0 : xor_byte(struct x86emu *emu, uint8_t d, uint8_t s)
7885 : {
7886 : uint8_t res; /* all operands in native machine order */
7887 :
7888 0 : res = d ^ s;
7889 0 : CLEAR_FLAG(F_OF);
7890 0 : CONDITIONAL_SET_FLAG(res & 0x80, F_SF);
7891 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7892 0 : CONDITIONAL_SET_FLAG(PARITY(res), F_PF);
7893 0 : CLEAR_FLAG(F_CF);
7894 0 : CLEAR_FLAG(F_AF);
7895 0 : return res;
7896 : }
7897 :
7898 : /*
7899 : * REMARKS:
7900 : * Implements the XOR instruction and side effects.
7901 : */
7902 : static uint16_t
7903 0 : xor_word(struct x86emu *emu, uint16_t d, uint16_t s)
7904 : {
7905 : uint16_t res; /* all operands in native machine order */
7906 :
7907 0 : res = d ^ s;
7908 0 : CLEAR_FLAG(F_OF);
7909 0 : CONDITIONAL_SET_FLAG(res & 0x8000, F_SF);
7910 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7911 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7912 0 : CLEAR_FLAG(F_CF);
7913 0 : CLEAR_FLAG(F_AF);
7914 0 : return res;
7915 : }
7916 :
7917 : /*
7918 : * REMARKS:
7919 : * Implements the XOR instruction and side effects.
7920 : */
7921 : static uint32_t
7922 0 : xor_long(struct x86emu *emu, uint32_t d, uint32_t s)
7923 : {
7924 : uint32_t res; /* all operands in native machine order */
7925 :
7926 0 : res = d ^ s;
7927 0 : CLEAR_FLAG(F_OF);
7928 0 : CONDITIONAL_SET_FLAG(res & 0x80000000, F_SF);
7929 0 : CONDITIONAL_SET_FLAG(res == 0, F_ZF);
7930 0 : CONDITIONAL_SET_FLAG(PARITY(res & 0xff), F_PF);
7931 0 : CLEAR_FLAG(F_CF);
7932 0 : CLEAR_FLAG(F_AF);
7933 0 : return res;
7934 : }
7935 :
7936 : /*
7937 : * REMARKS:
7938 : * Implements the IMUL instruction and side effects.
7939 : */
7940 : static void
7941 0 : imul_byte(struct x86emu *emu, uint8_t s)
7942 : {
7943 0 : int16_t res = (int16_t) ((int8_t) emu->x86.R_AL * (int8_t) s);
7944 :
7945 0 : emu->x86.R_AX = res;
7946 0 : if (((emu->x86.R_AL & 0x80) == 0 && emu->x86.R_AH == 0x00) ||
7947 0 : ((emu->x86.R_AL & 0x80) != 0 && emu->x86.R_AH == 0xFF)) {
7948 0 : CLEAR_FLAG(F_CF);
7949 0 : CLEAR_FLAG(F_OF);
7950 0 : } else {
7951 0 : SET_FLAG(F_CF);
7952 0 : SET_FLAG(F_OF);
7953 : }
7954 0 : }
7955 :
7956 : /*
7957 : * REMARKS:
7958 : * Implements the IMUL instruction and side effects.
7959 : */
7960 : static void
7961 0 : imul_word(struct x86emu *emu, uint16_t s)
7962 : {
7963 0 : int32_t res = (int16_t) emu->x86.R_AX * (int16_t) s;
7964 :
7965 0 : emu->x86.R_AX = (uint16_t) res;
7966 0 : emu->x86.R_DX = (uint16_t) (res >> 16);
7967 0 : if (((emu->x86.R_AX & 0x8000) == 0 && emu->x86.R_DX == 0x00) ||
7968 0 : ((emu->x86.R_AX & 0x8000) != 0 && emu->x86.R_DX == 0xFF)) {
7969 0 : CLEAR_FLAG(F_CF);
7970 0 : CLEAR_FLAG(F_OF);
7971 0 : } else {
7972 0 : SET_FLAG(F_CF);
7973 0 : SET_FLAG(F_OF);
7974 : }
7975 0 : }
7976 :
7977 : /*
7978 : * REMARKS:
7979 : * Implements the IMUL instruction and side effects.
7980 : */
7981 : static void
7982 0 : imul_long(struct x86emu *emu, uint32_t s)
7983 : {
7984 : int64_t res;
7985 :
7986 0 : res = (int64_t)(int32_t)emu->x86.R_EAX * (int32_t)s;
7987 0 : emu->x86.R_EAX = (uint32_t)res;
7988 0 : emu->x86.R_EDX = ((uint64_t)res) >> 32;
7989 0 : if (((emu->x86.R_EAX & 0x80000000) == 0 && emu->x86.R_EDX == 0x00) ||
7990 0 : ((emu->x86.R_EAX & 0x80000000) != 0 && emu->x86.R_EDX == 0xFF)) {
7991 0 : CLEAR_FLAG(F_CF);
7992 0 : CLEAR_FLAG(F_OF);
7993 0 : } else {
7994 0 : SET_FLAG(F_CF);
7995 0 : SET_FLAG(F_OF);
7996 : }
7997 0 : }
7998 :
7999 : /*
8000 : * REMARKS:
8001 : * Implements the MUL instruction and side effects.
8002 : */
8003 : static void
8004 0 : mul_byte(struct x86emu *emu, uint8_t s)
8005 : {
8006 0 : uint16_t res = (uint16_t) (emu->x86.R_AL * s);
8007 :
8008 0 : emu->x86.R_AX = res;
8009 0 : if (emu->x86.R_AH == 0) {
8010 0 : CLEAR_FLAG(F_CF);
8011 0 : CLEAR_FLAG(F_OF);
8012 0 : } else {
8013 0 : SET_FLAG(F_CF);
8014 0 : SET_FLAG(F_OF);
8015 : }
8016 0 : }
8017 :
8018 : /*
8019 : * REMARKS:
8020 : * Implements the MUL instruction and side effects.
8021 : */
8022 : static void
8023 0 : mul_word(struct x86emu *emu, uint16_t s)
8024 : {
8025 0 : uint32_t res = emu->x86.R_AX * s;
8026 :
8027 0 : emu->x86.R_AX = (uint16_t) res;
8028 0 : emu->x86.R_DX = (uint16_t) (res >> 16);
8029 0 : if (emu->x86.R_DX == 0) {
8030 0 : CLEAR_FLAG(F_CF);
8031 0 : CLEAR_FLAG(F_OF);
8032 0 : } else {
8033 0 : SET_FLAG(F_CF);
8034 0 : SET_FLAG(F_OF);
8035 : }
8036 0 : }
8037 :
8038 : /*
8039 : * REMARKS:
8040 : * Implements the MUL instruction and side effects.
8041 : */
8042 : static void
8043 0 : mul_long(struct x86emu *emu, uint32_t s)
8044 : {
8045 0 : uint64_t res = (uint64_t) emu->x86.R_EAX * s;
8046 :
8047 0 : emu->x86.R_EAX = (uint32_t) res;
8048 0 : emu->x86.R_EDX = (uint32_t) (res >> 32);
8049 :
8050 0 : if (emu->x86.R_EDX == 0) {
8051 0 : CLEAR_FLAG(F_CF);
8052 0 : CLEAR_FLAG(F_OF);
8053 0 : } else {
8054 0 : SET_FLAG(F_CF);
8055 0 : SET_FLAG(F_OF);
8056 : }
8057 0 : }
8058 :
8059 : /*
8060 : * REMARKS:
8061 : * Implements the IDIV instruction and side effects.
8062 : */
8063 : static void
8064 0 : idiv_byte(struct x86emu *emu, uint8_t s)
8065 : {
8066 : int32_t dvd, div, mod;
8067 :
8068 0 : dvd = (int16_t) emu->x86.R_AX;
8069 0 : if (s == 0) {
8070 0 : x86emu_intr_raise(emu, 8);
8071 0 : return;
8072 : }
8073 0 : div = dvd / (int8_t) s;
8074 0 : mod = dvd % (int8_t) s;
8075 0 : if (div > 0x7f || div < -0x7f) {
8076 0 : x86emu_intr_raise(emu, 8);
8077 0 : return;
8078 : }
8079 0 : emu->x86.R_AL = (int8_t) div;
8080 0 : emu->x86.R_AH = (int8_t) mod;
8081 0 : }
8082 :
8083 : /*
8084 : * REMARKS:
8085 : * Implements the IDIV instruction and side effects.
8086 : */
8087 : static void
8088 0 : idiv_word(struct x86emu *emu, uint16_t s)
8089 : {
8090 : int32_t dvd, div, mod;
8091 :
8092 0 : dvd = (((int32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8093 0 : if (s == 0) {
8094 0 : x86emu_intr_raise(emu, 8);
8095 0 : return;
8096 : }
8097 0 : div = dvd / (int16_t) s;
8098 0 : mod = dvd % (int16_t) s;
8099 0 : if (div > 0x7fff || div < -0x7fff) {
8100 0 : x86emu_intr_raise(emu, 8);
8101 0 : return;
8102 : }
8103 0 : CLEAR_FLAG(F_CF);
8104 0 : CLEAR_FLAG(F_SF);
8105 0 : CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8106 0 : CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8107 :
8108 0 : emu->x86.R_AX = (uint16_t) div;
8109 0 : emu->x86.R_DX = (uint16_t) mod;
8110 0 : }
8111 :
8112 : /*
8113 : * REMARKS:
8114 : * Implements the IDIV instruction and side effects.
8115 : */
8116 : static void
8117 0 : idiv_long(struct x86emu *emu, uint32_t s)
8118 : {
8119 : int64_t dvd, div, mod;
8120 :
8121 0 : dvd = (((int64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8122 0 : if (s == 0) {
8123 0 : x86emu_intr_raise(emu, 8);
8124 0 : return;
8125 : }
8126 0 : div = dvd / (int32_t) s;
8127 0 : mod = dvd % (int32_t) s;
8128 0 : if (div > 0x7fffffff || div < -0x7fffffff) {
8129 0 : x86emu_intr_raise(emu, 8);
8130 0 : return;
8131 : }
8132 0 : CLEAR_FLAG(F_CF);
8133 0 : CLEAR_FLAG(F_AF);
8134 0 : CLEAR_FLAG(F_SF);
8135 0 : SET_FLAG(F_ZF);
8136 0 : CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8137 :
8138 0 : emu->x86.R_EAX = (uint32_t) div;
8139 0 : emu->x86.R_EDX = (uint32_t) mod;
8140 0 : }
8141 :
8142 : /*
8143 : * REMARKS:
8144 : * Implements the DIV instruction and side effects.
8145 : */
8146 : static void
8147 0 : div_byte(struct x86emu *emu, uint8_t s)
8148 : {
8149 : uint32_t dvd, div, mod;
8150 :
8151 0 : dvd = emu->x86.R_AX;
8152 0 : if (s == 0) {
8153 0 : x86emu_intr_raise(emu, 8);
8154 0 : return;
8155 : }
8156 0 : div = dvd / (uint8_t) s;
8157 0 : mod = dvd % (uint8_t) s;
8158 0 : if (div > 0xff) {
8159 0 : x86emu_intr_raise(emu, 8);
8160 0 : return;
8161 : }
8162 0 : emu->x86.R_AL = (uint8_t) div;
8163 0 : emu->x86.R_AH = (uint8_t) mod;
8164 0 : }
8165 :
8166 : /*
8167 : * REMARKS:
8168 : * Implements the DIV instruction and side effects.
8169 : */
8170 : static void
8171 0 : div_word(struct x86emu *emu, uint16_t s)
8172 : {
8173 : uint32_t dvd, div, mod;
8174 :
8175 0 : dvd = (((uint32_t) emu->x86.R_DX) << 16) | emu->x86.R_AX;
8176 0 : if (s == 0) {
8177 0 : x86emu_intr_raise(emu, 8);
8178 0 : return;
8179 : }
8180 0 : div = dvd / (uint16_t) s;
8181 0 : mod = dvd % (uint16_t) s;
8182 0 : if (div > 0xffff) {
8183 0 : x86emu_intr_raise(emu, 8);
8184 0 : return;
8185 : }
8186 0 : CLEAR_FLAG(F_CF);
8187 0 : CLEAR_FLAG(F_SF);
8188 0 : CONDITIONAL_SET_FLAG(div == 0, F_ZF);
8189 0 : CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8190 :
8191 0 : emu->x86.R_AX = (uint16_t) div;
8192 0 : emu->x86.R_DX = (uint16_t) mod;
8193 0 : }
8194 :
8195 : /*
8196 : * REMARKS:
8197 : * Implements the DIV instruction and side effects.
8198 : */
8199 : static void
8200 0 : div_long(struct x86emu *emu, uint32_t s)
8201 : {
8202 : uint64_t dvd, div, mod;
8203 :
8204 0 : dvd = (((uint64_t) emu->x86.R_EDX) << 32) | emu->x86.R_EAX;
8205 0 : if (s == 0) {
8206 0 : x86emu_intr_raise(emu, 8);
8207 0 : return;
8208 : }
8209 0 : div = dvd / (uint32_t) s;
8210 0 : mod = dvd % (uint32_t) s;
8211 0 : if (div > 0xffffffff) {
8212 0 : x86emu_intr_raise(emu, 8);
8213 0 : return;
8214 : }
8215 0 : CLEAR_FLAG(F_CF);
8216 0 : CLEAR_FLAG(F_AF);
8217 0 : CLEAR_FLAG(F_SF);
8218 0 : SET_FLAG(F_ZF);
8219 0 : CONDITIONAL_SET_FLAG(PARITY(mod & 0xff), F_PF);
8220 :
8221 0 : emu->x86.R_EAX = (uint32_t) div;
8222 0 : emu->x86.R_EDX = (uint32_t) mod;
8223 0 : }
8224 :
8225 : /*
8226 : * REMARKS:
8227 : * Implements the IN string instruction and side effects.
8228 : */
8229 : static void
8230 0 : ins(struct x86emu *emu, int size)
8231 : {
8232 : int inc = size;
8233 :
8234 0 : if (ACCESS_FLAG(F_DF)) {
8235 0 : inc = -size;
8236 0 : }
8237 0 : if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8238 : /* dont care whether REPE or REPNE */
8239 : /* in until CX is ZERO. */
8240 0 : uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8241 0 : emu->x86.R_ECX : emu->x86.R_CX);
8242 0 : switch (size) {
8243 : case 1:
8244 0 : while (count--) {
8245 0 : store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8246 0 : (*emu->emu_inb) (emu, emu->x86.R_DX));
8247 0 : emu->x86.R_DI += inc;
8248 : }
8249 : break;
8250 :
8251 : case 2:
8252 0 : while (count--) {
8253 0 : store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8254 0 : (*emu->emu_inw) (emu, emu->x86.R_DX));
8255 0 : emu->x86.R_DI += inc;
8256 : }
8257 : break;
8258 : case 4:
8259 0 : while (count--) {
8260 0 : store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8261 0 : (*emu->emu_inl) (emu, emu->x86.R_DX));
8262 0 : emu->x86.R_DI += inc;
8263 0 : break;
8264 : }
8265 : }
8266 0 : emu->x86.R_CX = 0;
8267 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8268 0 : emu->x86.R_ECX = 0;
8269 0 : }
8270 0 : emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8271 0 : } else {
8272 0 : switch (size) {
8273 : case 1:
8274 0 : store_byte(emu, emu->x86.R_ES, emu->x86.R_DI,
8275 0 : (*emu->emu_inb) (emu, emu->x86.R_DX));
8276 0 : break;
8277 : case 2:
8278 0 : store_word(emu, emu->x86.R_ES, emu->x86.R_DI,
8279 0 : (*emu->emu_inw) (emu, emu->x86.R_DX));
8280 0 : break;
8281 : case 4:
8282 0 : store_long(emu, emu->x86.R_ES, emu->x86.R_DI,
8283 0 : (*emu->emu_inl) (emu, emu->x86.R_DX));
8284 0 : break;
8285 : }
8286 0 : emu->x86.R_DI += inc;
8287 : }
8288 0 : }
8289 :
8290 : /*
8291 : * REMARKS:
8292 : * Implements the OUT string instruction and side effects.
8293 : */
8294 : static void
8295 0 : outs(struct x86emu *emu, int size)
8296 : {
8297 : int inc = size;
8298 :
8299 0 : if (ACCESS_FLAG(F_DF)) {
8300 0 : inc = -size;
8301 0 : }
8302 0 : if (emu->x86.mode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE)) {
8303 : /* dont care whether REPE or REPNE */
8304 : /* out until CX is ZERO. */
8305 0 : uint32_t count = ((emu->x86.mode & SYSMODE_PREFIX_DATA) ?
8306 0 : emu->x86.R_ECX : emu->x86.R_CX);
8307 0 : switch (size) {
8308 : case 1:
8309 0 : while (count--) {
8310 0 : (*emu->emu_outb) (emu, emu->x86.R_DX,
8311 0 : fetch_byte(emu, emu->x86.R_ES,
8312 0 : emu->x86.R_SI));
8313 0 : emu->x86.R_SI += inc;
8314 : }
8315 : break;
8316 :
8317 : case 2:
8318 0 : while (count--) {
8319 0 : (*emu->emu_outw) (emu, emu->x86.R_DX,
8320 0 : fetch_word(emu, emu->x86.R_ES,
8321 0 : emu->x86.R_SI));
8322 0 : emu->x86.R_SI += inc;
8323 : }
8324 : break;
8325 : case 4:
8326 0 : while (count--) {
8327 0 : (*emu->emu_outl) (emu, emu->x86.R_DX,
8328 0 : fetch_long(emu, emu->x86.R_ES,
8329 0 : emu->x86.R_SI));
8330 0 : emu->x86.R_SI += inc;
8331 0 : break;
8332 : }
8333 : }
8334 0 : emu->x86.R_CX = 0;
8335 0 : if (emu->x86.mode & SYSMODE_PREFIX_DATA) {
8336 0 : emu->x86.R_ECX = 0;
8337 0 : }
8338 0 : emu->x86.mode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
8339 0 : } else {
8340 0 : switch (size) {
8341 : case 1:
8342 0 : (*emu->emu_outb) (emu, emu->x86.R_DX,
8343 0 : fetch_byte(emu, emu->x86.R_ES, emu->x86.R_SI));
8344 0 : break;
8345 : case 2:
8346 0 : (*emu->emu_outw) (emu, emu->x86.R_DX,
8347 0 : fetch_word(emu, emu->x86.R_ES, emu->x86.R_SI));
8348 0 : break;
8349 : case 4:
8350 0 : (*emu->emu_outl) (emu, emu->x86.R_DX,
8351 0 : fetch_long(emu, emu->x86.R_ES, emu->x86.R_SI));
8352 0 : break;
8353 : }
8354 0 : emu->x86.R_SI += inc;
8355 : }
8356 0 : }
8357 :
8358 : /*
8359 : * REMARKS:
8360 : * Pushes a word onto the stack.
8361 : *
8362 : * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8363 : */
8364 : static void
8365 0 : push_word(struct x86emu *emu, uint16_t w)
8366 : {
8367 0 : emu->x86.R_SP -= 2;
8368 0 : store_word(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8369 0 : }
8370 :
8371 : /*
8372 : * REMARKS:
8373 : * Pushes a long onto the stack.
8374 : *
8375 : * NOTE: Do not inline this, as (*emu->emu_wrX) is already inline!
8376 : */
8377 : static void
8378 0 : push_long(struct x86emu *emu, uint32_t w)
8379 : {
8380 0 : emu->x86.R_SP -= 4;
8381 0 : store_long(emu, emu->x86.R_SS, emu->x86.R_SP, w);
8382 0 : }
8383 :
8384 : /*
8385 : * REMARKS:
8386 : * Pops a word from the stack.
8387 : *
8388 : * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8389 : */
8390 : static uint16_t
8391 0 : pop_word(struct x86emu *emu)
8392 : {
8393 : uint16_t res;
8394 :
8395 0 : res = fetch_word(emu, emu->x86.R_SS, emu->x86.R_SP);
8396 0 : emu->x86.R_SP += 2;
8397 0 : return res;
8398 : }
8399 :
8400 : /*
8401 : * REMARKS:
8402 : * Pops a long from the stack.
8403 : *
8404 : * NOTE: Do not inline this, as (*emu->emu_rdX) is already inline!
8405 : */
8406 : static uint32_t
8407 0 : pop_long(struct x86emu *emu)
8408 : {
8409 : uint32_t res;
8410 :
8411 0 : res = fetch_long(emu, emu->x86.R_SS, emu->x86.R_SP);
8412 0 : emu->x86.R_SP += 4;
8413 0 : return res;
8414 : }
|