First Commit of my working state
[simh.git] / AltairZ80 / i86_ops.c
1 /*
2 * Dos/PC Emulator
3 * Copyright (C) 1991 Jim Hudgens
4 *
5 *
6 * The file is part of GDE.
7 *
8 * GDE is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 1, or (at your option)
11 * any later version.
12 *
13 * GDE is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with GDE; see the file COPYING. If not, write to
20 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23
24 #include "altairz80_defs.h"
25 #include "i86.h"
26
27 extern void out(const uint32 Port, const uint32 Value);
28 extern uint32 in(const uint32 Port);
29
30 /* $Log: i86_ops.c,v $
31 * Revision 0.11 1991/07/30 02:02:04 hudgens
32 * added copyright.
33 *
34 * Revision 0.10 1991/07/21 18:22:08 hudgens
35 * Fixed problem with scans, which was the result of the loop break
36 * condition being incorrect when used in conjunction with the repe
37 * or repne prefixes. Eureka. pkzip/pkunzip now compress/decompress
38 * correctly.
39 *
40 * Revision 0.9 1991/07/21 03:33:18 hudgens
41 * fixed popf so that it appears to be the same as an 8088 popf, and always
42 * sets the high 4 bits of the flags.
43 *
44 * Revision 0.8 1991/07/21 01:44:11 hudgens
45 * fixed aad and aam instructions.
46 *
47 * Revision 0.7 1991/07/21 00:31:24 hudgens
48 * Fixed iret so that it works correctly.
49 *
50 * Revision 0.6 1991/07/20 16:54:50 hudgens
51 * removed the 8087 coprocessor operations. Moved to i87_ops.c
52 *
53 * Revision 0.5 1991/07/17 03:50:10 hudgens
54 * Minor modifications.
55 *
56 * Revision 0.4 1991/06/18 02:48:41 hudgens
57 * Fixed a problem with scasb and scasw.
58 *
59 * Revision 0.3 1991/06/03 01:01:10 hudgens
60 * fixed minor problems due to unsigned to signed short integer
61 * promotions.
62 *
63 * Revision 0.2 1991/03/31 01:32:10 hudgens
64 * fixed segment handling. Added calls to DECODE_CLEAR_SEGOVR in
65 * many places in the code. Should work much better now.
66 *
67 * Revision 0.1 1991/03/30 21:15:48 hudgens
68 * Initial checkin to RCS.
69 *
70 *
71 */
72
73 /* 2/23/91 fixed decode for operand x87. */
74
75 /* partially mechanically generated file....(based on the optable) */
76 /*
77 There are approximately 250 subroutines in here, which correspond
78 to the 256 byte-"opcodes" found on the 8086. The table which
79 dispatches this is found in the files optab.[ch].
80
81 Each opcode proc has a comment preceeding it which gives it's table
82 address. Several opcodes are missing (undefined) in the table.
83
84 Each proc includes information for decoding (DECODE_PRINTF and
85 and misc functions (
86 Many of the procedures are *VERY* similar in coding. This has
87 allowed for a very large amount of code to be generated in a fairly
88 short amount of time (i.e. cut, paste, and modify).
89 The result is that much of the code below could
90 have been folded into subroutines for a large reduction in size of
91 this file. The downside would be that there would be a penalty in
92 execution speed. The file could also have been *MUCH* larger by
93 inlining certain functions which were called. This could have
94 resulted even faster execution. The prime directive I used to decide
95 whether to inline the code or to modularize it, was basically: 1) no
96 unnecessary subroutine calls, 2) no routines more than about 200 lines
97 in size, and 3) modularize any code that I might not get right the first
98 time. The fetch_* subroutines fall into the latter category. The
99 The decode_* fall into the second category. The coding of the
100 "switch(mod){ .... }" in many of the subroutines below falls into the
101 first category. Especially, the coding of {add,and,or,sub,...}_{byte,word}
102 subroutines are an especially glaring case of the third guideline.
103 Since so much of the code is cloned from other modules (compare
104 opcode #00 to opcode #01), making the basic operations subroutine calls
105 is especially important; otherwise mistakes in coding an "add"
106 would represent a nightmare in maintenance.
107
108 So, without further ado, ...
109 */
110
111 extern char parity_tab[];
112
113 static void i86op_illegal_op(PC_ENV *m)
114 {
115 intr |= INTR_ILLEGAL_OPCODE;
116 }
117
118 /*opcode=0x00*/
119 static void i86op_add_byte_RM_R(PC_ENV *m)
120 {
121 uint16 mod,rl,rh;
122 uint8 *destreg,*srcreg;
123 uint16 destoffset;
124 uint8 destval;
125 FETCH_DECODE_MODRM(m,mod,rh,rl);
126 switch (mod)
127 {
128 case 0:
129 destoffset=decode_rm00_address(m,rl);
130 destval = fetch_data_byte(m,destoffset);
131 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
132 destval = add_byte(m, destval, *srcreg);
133 store_data_byte(m,destoffset,destval);
134 break;
135 case 1:
136 destoffset=decode_rm01_address(m,rl);
137 destval = fetch_data_byte(m,destoffset);
138 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
139 destval = add_byte(m, destval, *srcreg);
140 store_data_byte(m,destoffset,destval);
141 break;
142 case 2:
143 destoffset=decode_rm10_address(m,rl);
144 destval = fetch_data_byte(m,destoffset);
145 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
146 destval = add_byte(m, destval, *srcreg);
147 store_data_byte(m,destoffset,destval);
148 break;
149 case 3: /* register to register */
150 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
151 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
152 *destreg = add_byte(m, *destreg, *srcreg);
153 break;
154 }
155 DECODE_CLEAR_SEGOVR(m);
156 }
157
158 /*opcode=0x01*/
159 static void i86op_add_word_RM_R(PC_ENV *m)
160 {
161 uint16 mod,rl,rh;
162 uint16 *destreg,*srcreg;
163 uint16 destoffset;
164 uint16 destval;
165 FETCH_DECODE_MODRM(m,mod,rh,rl);
166 switch (mod)
167 {
168 case 0:
169 destoffset=decode_rm00_address(m,rl);
170 destval = fetch_data_word(m,destoffset);
171 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
172 destval = add_word(m, destval, *srcreg);
173 store_data_word(m,destoffset,destval);
174 break;
175 case 1:
176 destoffset=decode_rm01_address(m,rl);
177 destval = fetch_data_word(m,destoffset);
178 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
179 destval = add_word(m, destval, *srcreg);
180 store_data_word(m,destoffset,destval);
181 break;
182 case 2:
183 destoffset=decode_rm10_address(m,rl);
184 destval = fetch_data_word(m,destoffset);
185 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
186 destval = add_word(m, destval, *srcreg);
187 store_data_word(m,destoffset,destval);
188 break;
189 case 3: /* register to register */
190 destreg = DECODE_RM_WORD_REGISTER(m,rl);
191 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
192 *destreg = add_word(m, *destreg, *srcreg);
193 break;
194 }
195 DECODE_CLEAR_SEGOVR(m);
196 }
197
198 /*opcode=0x02*/
199 static void i86op_add_byte_R_RM(PC_ENV *m)
200 {
201 uint16 mod,rl,rh;
202 uint8 *destreg,*srcreg;
203 uint16 srcoffset;
204 uint8 srcval;
205 FETCH_DECODE_MODRM(m,mod,rh,rl);
206 switch (mod)
207 {
208 case 0:
209 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
210 srcoffset=decode_rm00_address(m,rl);
211 srcval = fetch_data_byte(m,srcoffset);
212 *destreg = add_byte(m, *destreg, srcval);
213 break;
214 case 1:
215 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
216 srcoffset=decode_rm01_address(m,rl);
217 srcval = fetch_data_byte(m,srcoffset);
218 *destreg = add_byte(m, *destreg, srcval);
219 break;
220 case 2:
221 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
222 srcoffset=decode_rm10_address(m,rl);
223 srcval = fetch_data_byte(m,srcoffset);
224 *destreg = add_byte(m, * destreg, srcval);
225 break;
226 case 3: /* register to register */
227 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
228 srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
229 *destreg = add_byte(m, *destreg, *srcreg);
230 break;
231 }
232 DECODE_CLEAR_SEGOVR(m);
233 }
234
235 /*opcode=0x03*/
236 static void i86op_add_word_R_RM(PC_ENV *m)
237 {
238 uint16 mod,rl,rh;
239 uint16 *destreg,*srcreg;
240 uint16 srcoffset;
241 uint16 srcval;
242 FETCH_DECODE_MODRM(m,mod,rh,rl);
243 switch (mod)
244 {
245 case 0:
246 destreg = DECODE_RM_WORD_REGISTER(m,rh);
247 srcoffset=decode_rm00_address(m,rl);
248 srcval = fetch_data_word(m,srcoffset);
249 *destreg = add_word(m, *destreg, srcval);
250 break;
251 case 1:
252 destreg = DECODE_RM_WORD_REGISTER(m,rh);
253 srcoffset=decode_rm01_address(m,rl);
254 srcval = fetch_data_word(m,srcoffset);
255 *destreg = add_word(m, *destreg, srcval);
256 break;
257 case 2:
258 destreg = DECODE_RM_WORD_REGISTER(m,rh);
259 srcoffset=decode_rm10_address(m,rl);
260 srcval = fetch_data_word(m,srcoffset);
261 *destreg = add_word(m, *destreg, srcval);
262 break;
263 case 3: /* register to register */
264 destreg = DECODE_RM_WORD_REGISTER(m,rh);
265 srcreg = DECODE_RM_WORD_REGISTER(m,rl);
266 *destreg = add_word(m, *destreg, *srcreg);
267 break;
268 }
269 DECODE_CLEAR_SEGOVR(m);
270 }
271
272 /*opcode=0x04*/
273 static void i86op_add_byte_AL_IMM(PC_ENV *m)
274 {
275 uint8 srcval;
276 srcval = fetch_byte_imm(m);
277 m->R_AL = add_byte(m, m->R_AL, srcval);
278 DECODE_CLEAR_SEGOVR(m);
279 }
280
281 /*opcode=0x05*/
282 static void i86op_add_word_AX_IMM(PC_ENV *m)
283 {
284 uint16 srcval;
285 srcval = fetch_word_imm(m);
286 m->R_AX = add_word(m, m->R_AX, srcval);
287 DECODE_CLEAR_SEGOVR(m);
288 }
289
290 /*opcode=0x06*/
291 static void i86op_push_ES(PC_ENV *m)
292 {
293 push_word(m,m->R_ES);
294 DECODE_CLEAR_SEGOVR(m);
295 }
296
297 /*opcode=0x07*/
298 static void i86op_pop_ES(PC_ENV *m)
299 {
300 m->R_ES = pop_word(m);
301 DECODE_CLEAR_SEGOVR(m);
302 }
303
304 /*opcode=0x08*/
305 static void i86op_or_byte_RM_R(PC_ENV *m)
306 {
307 uint16 mod,rl,rh;
308 uint8 *destreg,*srcreg;
309 uint16 destoffset;
310 uint8 destval;
311 FETCH_DECODE_MODRM(m,mod,rh,rl);
312 switch (mod)
313 {
314 case 0:
315 destoffset=decode_rm00_address(m,rl);
316 destval = fetch_data_byte(m,destoffset);
317 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
318 destval = or_byte(m, destval, *srcreg);
319 store_data_byte(m,destoffset,destval);
320 break;
321 case 1:
322 destoffset=decode_rm01_address(m,rl);
323 destval = fetch_data_byte(m,destoffset);
324 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
325 destval = or_byte(m, destval, *srcreg);
326 store_data_byte(m,destoffset,destval);
327 break;
328 case 2:
329 destoffset=decode_rm10_address(m,rl);
330 destval = fetch_data_byte(m,destoffset);
331 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
332 destval = or_byte(m, destval, *srcreg);
333 store_data_byte(m,destoffset,destval);
334 break;
335 case 3: /* register to register */
336 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
337 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
338 *destreg = or_byte(m, *destreg, *srcreg);
339 break;
340 }
341 DECODE_CLEAR_SEGOVR(m);
342 }
343
344 /*opcode=0x09*/
345 static void i86op_or_word_RM_R(PC_ENV *m)
346 {
347 uint16 mod,rl,rh;
348 uint16 *destreg,*srcreg;
349 uint16 destoffset;
350 uint16 destval;
351 FETCH_DECODE_MODRM(m,mod,rh,rl);
352 switch (mod)
353 {
354 case 0:
355 destoffset=decode_rm00_address(m,rl);
356 destval = fetch_data_word(m,destoffset);
357 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
358 destval = or_word(m, destval, *srcreg);
359 store_data_word(m,destoffset,destval);
360 break;
361 case 1:
362 destoffset=decode_rm01_address(m,rl);
363 destval = fetch_data_word(m,destoffset);
364 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
365 destval = or_word(m, destval, *srcreg);
366 store_data_word(m,destoffset,destval);
367 break;
368 case 2:
369 destoffset=decode_rm10_address(m,rl);
370 destval = fetch_data_word(m,destoffset);
371 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
372 destval = or_word(m, destval, *srcreg);
373 store_data_word(m,destoffset,destval);
374 break;
375 case 3: /* register to register */
376 destreg = DECODE_RM_WORD_REGISTER(m,rl);
377 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
378 *destreg = or_word(m, *destreg, *srcreg);
379 break;
380 }
381 DECODE_CLEAR_SEGOVR(m);
382 }
383
384 /*opcode=0x0a*/
385 static void i86op_or_byte_R_RM(PC_ENV *m)
386 {
387 uint16 mod,rl,rh;
388 uint8 *destreg,*srcreg;
389 uint16 srcoffset;
390 uint8 srcval;
391 FETCH_DECODE_MODRM(m,mod,rh,rl);
392 switch (mod)
393 {
394 case 0:
395 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
396 srcoffset=decode_rm00_address(m,rl);
397 srcval = fetch_data_byte(m,srcoffset);
398 *destreg = or_byte(m, *destreg, srcval);
399 break;
400 case 1:
401 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
402 srcoffset=decode_rm01_address(m,rl);
403 srcval = fetch_data_byte(m,srcoffset);
404 *destreg = or_byte(m, *destreg, srcval);
405 break;
406 case 2:
407 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
408 srcoffset=decode_rm10_address(m,rl);
409 srcval = fetch_data_byte(m,srcoffset);
410 *destreg = or_byte(m, * destreg, srcval);
411 break;
412 case 3: /* register to register */
413 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
414 srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
415 *destreg = or_byte(m, *destreg, *srcreg);
416 break;
417 }
418 DECODE_CLEAR_SEGOVR(m);
419 }
420
421 /*opcode=0x0b*/
422 static void i86op_or_word_R_RM(PC_ENV *m)
423 {
424 uint16 mod,rl,rh;
425 uint16 *destreg,*srcreg;
426 uint16 srcoffset;
427 uint16 srcval;
428 FETCH_DECODE_MODRM(m,mod,rh,rl);
429 switch (mod)
430 {
431 case 0:
432 destreg = DECODE_RM_WORD_REGISTER(m,rh);
433 srcoffset=decode_rm00_address(m,rl);
434 srcval = fetch_data_word(m,srcoffset);
435 *destreg = or_word(m, *destreg, srcval);
436 break;
437 case 1:
438 destreg = DECODE_RM_WORD_REGISTER(m,rh);
439 srcoffset=decode_rm01_address(m,rl);
440 srcval = fetch_data_word(m,srcoffset);
441 *destreg = or_word(m, *destreg, srcval);
442 break;
443 case 2:
444 destreg = DECODE_RM_WORD_REGISTER(m,rh);
445 srcoffset=decode_rm10_address(m,rl);
446 srcval = fetch_data_word(m,srcoffset);
447 *destreg = or_word(m, *destreg, srcval);
448 break;
449 case 3: /* register to register */
450 destreg = DECODE_RM_WORD_REGISTER(m,rh);
451 srcreg = DECODE_RM_WORD_REGISTER(m,rl);
452 *destreg = or_word(m, *destreg, *srcreg);
453 break;
454 }
455 DECODE_CLEAR_SEGOVR(m);
456 }
457
458 /*opcode=0x0c*/
459 static void i86op_or_byte_AL_IMM(PC_ENV *m)
460 {
461 uint8 srcval;
462 srcval = fetch_byte_imm(m);
463 m->R_AL = or_byte(m, m->R_AL, srcval);
464 DECODE_CLEAR_SEGOVR(m);
465 }
466
467 /*opcode=0x0d*/
468 static void i86op_or_word_AX_IMM(PC_ENV *m)
469 {
470 uint16 srcval;
471 srcval = fetch_word_imm(m);
472 m->R_AX = or_word(m, m->R_AX, srcval);
473 DECODE_CLEAR_SEGOVR(m);
474 }
475
476 /*opcode=0x0e*/
477 static void i86op_push_CS(PC_ENV *m)
478 {
479 push_word(m,m->R_CS);
480 DECODE_CLEAR_SEGOVR(m);
481 }
482
483 /*opcode=0x0f === ILLEGAL OP*/
484
485 /*opcode=0x10*/
486 static void i86op_adc_byte_RM_R(PC_ENV *m)
487 {
488 uint16 mod,rl,rh;
489 uint8 *destreg,*srcreg;
490 uint16 destoffset;
491 uint8 destval;
492 FETCH_DECODE_MODRM(m,mod,rh,rl);
493 switch (mod)
494 {
495 case 0:
496 destoffset=decode_rm00_address(m,rl);
497 destval = fetch_data_byte(m,destoffset);
498 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
499 destval = adc_byte(m, destval, *srcreg);
500 store_data_byte(m,destoffset,destval);
501 break;
502 case 1:
503 destoffset=decode_rm01_address(m,rl);
504 destval = fetch_data_byte(m,destoffset);
505 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
506 destval = adc_byte(m, destval, *srcreg);
507 store_data_byte(m,destoffset,destval);
508 break;
509 case 2:
510 destoffset=decode_rm10_address(m,rl);
511 destval = fetch_data_byte(m,destoffset);
512 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
513 destval = adc_byte(m, destval, *srcreg);
514 store_data_byte(m,destoffset,destval);
515 break;
516 case 3: /* register to register */
517 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
518 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
519 *destreg = adc_byte(m, *destreg, *srcreg);
520 break;
521 }
522 DECODE_CLEAR_SEGOVR(m);
523 }
524
525 /*opcode=0x11*/
526 static void i86op_adc_word_RM_R(PC_ENV *m)
527 {
528 uint16 mod,rl,rh;
529 uint16 *destreg,*srcreg;
530 uint16 destoffset;
531 uint16 destval;
532 FETCH_DECODE_MODRM(m,mod,rh,rl);
533 switch (mod)
534 {
535 case 0:
536 destoffset=decode_rm00_address(m,rl);
537 destval = fetch_data_word(m,destoffset);
538 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
539 destval = adc_word(m, destval, *srcreg);
540 store_data_word(m,destoffset,destval);
541 break;
542 case 1:
543 destoffset=decode_rm01_address(m,rl);
544 destval = fetch_data_word(m,destoffset);
545 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
546 destval = adc_word(m, destval, *srcreg);
547 store_data_word(m,destoffset,destval);
548 break;
549 case 2:
550 destoffset=decode_rm10_address(m,rl);
551 destval = fetch_data_word(m,destoffset);
552 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
553 destval = adc_word(m, destval, *srcreg);
554 store_data_word(m,destoffset,destval);
555 break;
556 case 3: /* register to register */
557 destreg = DECODE_RM_WORD_REGISTER(m,rl);
558 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
559 *destreg = adc_word(m, *destreg, *srcreg);
560 break;
561 }
562 DECODE_CLEAR_SEGOVR(m);
563 }
564
565 /*opcode=0x12*/
566 static void i86op_adc_byte_R_RM(PC_ENV *m)
567 {
568 uint16 mod,rl,rh;
569 uint8 *destreg,*srcreg;
570 uint16 srcoffset;
571 uint8 srcval;
572 FETCH_DECODE_MODRM(m,mod,rh,rl);
573 switch (mod)
574 {
575 case 0:
576 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
577 srcoffset=decode_rm00_address(m,rl);
578 srcval = fetch_data_byte(m,srcoffset);
579 *destreg = adc_byte(m, *destreg, srcval);
580 break;
581 case 1:
582 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
583 srcoffset=decode_rm01_address(m,rl);
584 srcval = fetch_data_byte(m,srcoffset);
585 *destreg = adc_byte(m, *destreg, srcval);
586 break;
587 case 2:
588 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
589 srcoffset=decode_rm10_address(m,rl);
590 srcval = fetch_data_byte(m,srcoffset);
591 *destreg = adc_byte(m, * destreg, srcval);
592 break;
593 case 3: /* register to register */
594 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
595 srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
596 *destreg = adc_byte(m, *destreg, *srcreg);
597 break;
598 }
599 DECODE_CLEAR_SEGOVR(m);
600 }
601
602 /*opcode=0x13*/
603 static void i86op_adc_word_R_RM(PC_ENV *m)
604 {
605 uint16 mod,rl,rh;
606 uint16 *destreg,*srcreg;
607 uint16 srcoffset;
608 uint16 srcval;
609 FETCH_DECODE_MODRM(m,mod,rh,rl);
610 switch (mod)
611 {
612 case 0:
613 destreg = DECODE_RM_WORD_REGISTER(m,rh);
614 srcoffset=decode_rm00_address(m,rl);
615 srcval = fetch_data_word(m,srcoffset);
616 *destreg = adc_word(m, *destreg, srcval);
617 break;
618 case 1:
619 destreg = DECODE_RM_WORD_REGISTER(m,rh);
620 srcoffset=decode_rm01_address(m,rl);
621 srcval = fetch_data_word(m,srcoffset);
622 *destreg = adc_word(m, *destreg, srcval);
623 break;
624 case 2:
625 destreg = DECODE_RM_WORD_REGISTER(m,rh);
626 srcoffset=decode_rm10_address(m,rl);
627 srcval = fetch_data_word(m,srcoffset);
628 *destreg = adc_word(m, *destreg, srcval);
629 break;
630 case 3: /* register to register */
631 destreg = DECODE_RM_WORD_REGISTER(m,rh);
632 srcreg = DECODE_RM_WORD_REGISTER(m,rl);
633 *destreg = adc_word(m, *destreg, *srcreg);
634 break;
635 }
636 DECODE_CLEAR_SEGOVR(m);
637 }
638
639 /*opcode=0x14*/
640 static void i86op_adc_byte_AL_IMM(PC_ENV *m)
641 {
642 uint8 srcval;
643 srcval = fetch_byte_imm(m);
644 m->R_AL = adc_byte(m, m->R_AL, srcval);
645 DECODE_CLEAR_SEGOVR(m);
646 }
647
648 /*opcode=0x15*/
649 static void i86op_adc_word_AX_IMM(PC_ENV *m)
650 {
651 uint16 srcval;
652 srcval = fetch_word_imm(m);
653 m->R_AX = adc_word(m, m->R_AX, srcval);
654 DECODE_CLEAR_SEGOVR(m);
655 }
656
657 /*opcode=0x16*/
658 static void i86op_push_SS(PC_ENV *m)
659 {
660 push_word(m,m->R_SS);
661 DECODE_CLEAR_SEGOVR(m);
662 }
663
664 /*opcode=0x17*/
665 static void i86op_pop_SS(PC_ENV *m)
666 {
667 m->R_SS = pop_word(m);
668 DECODE_CLEAR_SEGOVR(m);
669 }
670
671 /*opcode=0x18*/
672 static void i86op_sbb_byte_RM_R(PC_ENV *m)
673 {
674 uint16 mod,rl,rh;
675 uint8 *destreg,*srcreg;
676 uint16 destoffset;
677 uint8 destval;
678 FETCH_DECODE_MODRM(m,mod,rh,rl);
679 switch (mod)
680 {
681 case 0:
682 destoffset=decode_rm00_address(m,rl);
683 destval = fetch_data_byte(m,destoffset);
684 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
685 destval = sbb_byte(m, destval, *srcreg);
686 store_data_byte(m,destoffset,destval);
687 break;
688 case 1:
689 destoffset=decode_rm01_address(m,rl);
690 destval = fetch_data_byte(m,destoffset);
691 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
692 destval = sbb_byte(m, destval, *srcreg);
693 store_data_byte(m,destoffset,destval);
694 break;
695 case 2:
696 destoffset=decode_rm10_address(m,rl);
697 destval = fetch_data_byte(m,destoffset);
698 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
699 destval = sbb_byte(m, destval, *srcreg);
700 store_data_byte(m,destoffset,destval);
701 break;
702 case 3: /* register to register */
703 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
704 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
705 *destreg = sbb_byte(m, *destreg, *srcreg);
706 break;
707 }
708 DECODE_CLEAR_SEGOVR(m);
709 }
710
711 /*opcode=0x19*/
712 static void i86op_sbb_word_RM_R(PC_ENV *m)
713 {
714 uint16 mod,rl,rh;
715 uint16 *destreg,*srcreg;
716 uint16 destoffset;
717 uint16 destval;
718 FETCH_DECODE_MODRM(m,mod,rh,rl);
719 switch (mod)
720 {
721 case 0:
722 destoffset=decode_rm00_address(m,rl);
723 destval = fetch_data_word(m,destoffset);
724 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
725 destval = sbb_word(m, destval, *srcreg);
726 store_data_word(m,destoffset,destval);
727 break;
728 case 1:
729 destoffset=decode_rm01_address(m,rl);
730 destval = fetch_data_word(m,destoffset);
731 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
732 destval = sbb_word(m, destval, *srcreg);
733 store_data_word(m,destoffset,destval);
734 break;
735 case 2:
736 destoffset=decode_rm10_address(m,rl);
737 destval = fetch_data_word(m,destoffset);
738 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
739 destval = sbb_word(m, destval, *srcreg);
740 store_data_word(m,destoffset,destval);
741 break;
742 case 3: /* register to register */
743 destreg = DECODE_RM_WORD_REGISTER(m,rl);
744 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
745 *destreg = sbb_word(m, *destreg, *srcreg);
746 break;
747 }
748 DECODE_CLEAR_SEGOVR(m);
749 }
750
751 /*opcode=0x1a*/
752 static void i86op_sbb_byte_R_RM(PC_ENV *m)
753 {
754 uint16 mod,rl,rh;
755 uint8 *destreg,*srcreg;
756 uint16 srcoffset;
757 uint8 srcval;
758 FETCH_DECODE_MODRM(m,mod,rh,rl);
759 switch (mod)
760 {
761 case 0:
762 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
763 srcoffset=decode_rm00_address(m,rl);
764 srcval = fetch_data_byte(m,srcoffset);
765 *destreg = sbb_byte(m, *destreg, srcval);
766 break;
767 case 1:
768 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
769 srcoffset=decode_rm01_address(m,rl);
770 srcval = fetch_data_byte(m,srcoffset);
771 *destreg = sbb_byte(m, *destreg, srcval);
772 break;
773 case 2:
774 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
775 srcoffset=decode_rm10_address(m,rl);
776 srcval = fetch_data_byte(m,srcoffset);
777 *destreg = sbb_byte(m, * destreg, srcval);
778 break;
779 case 3: /* register to register */
780 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
781 srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
782 *destreg = sbb_byte(m, *destreg, *srcreg);
783 break;
784 }
785 DECODE_CLEAR_SEGOVR(m);
786 }
787
788 /*opcode=0x1b*/
789 static void i86op_sbb_word_R_RM(PC_ENV *m)
790 {
791 uint16 mod,rl,rh;
792 uint16 *destreg,*srcreg;
793 uint16 srcoffset;
794 uint16 srcval;
795 FETCH_DECODE_MODRM(m,mod,rh,rl);
796 switch (mod)
797 {
798 case 0:
799 destreg = DECODE_RM_WORD_REGISTER(m,rh);
800 srcoffset=decode_rm00_address(m,rl);
801 srcval = fetch_data_word(m,srcoffset);
802 *destreg = sbb_word(m, *destreg, srcval);
803 break;
804 case 1:
805 destreg = DECODE_RM_WORD_REGISTER(m,rh);
806 srcoffset=decode_rm01_address(m,rl);
807 srcval = fetch_data_word(m,srcoffset);
808 *destreg = sbb_word(m, *destreg, srcval);
809 break;
810 case 2:
811 destreg = DECODE_RM_WORD_REGISTER(m,rh);
812 srcoffset=decode_rm10_address(m,rl);
813 srcval = fetch_data_word(m,srcoffset);
814 *destreg = sbb_word(m, *destreg, srcval);
815 break;
816 case 3: /* register to register */
817 destreg = DECODE_RM_WORD_REGISTER(m,rh);
818 srcreg = DECODE_RM_WORD_REGISTER(m,rl);
819 *destreg = sbb_word(m, *destreg, *srcreg);
820 break;
821 }
822 DECODE_CLEAR_SEGOVR(m);
823 }
824
825 /*opcode=0x1c*/
826 static void i86op_sbb_byte_AL_IMM(PC_ENV *m)
827 {
828 uint8 srcval;
829 srcval = fetch_byte_imm(m);
830 m->R_AL = sbb_byte(m, m->R_AL, srcval);
831 DECODE_CLEAR_SEGOVR(m);
832 }
833
834 /*opcode=0x1d*/
835 static void i86op_sbb_word_AX_IMM(PC_ENV *m)
836 {
837 uint16 srcval;
838 srcval = fetch_word_imm(m);
839 m->R_AX = sbb_word(m, m->R_AX, srcval);
840 DECODE_CLEAR_SEGOVR(m);
841 }
842
843 /*opcode=0x1e*/
844 static void i86op_push_DS(PC_ENV *m)
845 {
846 push_word(m,m->R_DS);
847 DECODE_CLEAR_SEGOVR(m);
848 }
849
850 /*opcode=0x1f*/
851 static void i86op_pop_DS(PC_ENV *m)
852 {
853 m->R_DS = pop_word(m);
854 DECODE_CLEAR_SEGOVR(m);
855 }
856
857 /*opcode=0x20*/
858 static void i86op_and_byte_RM_R(PC_ENV *m)
859 {
860 uint16 mod,rl,rh;
861 uint8 *destreg,*srcreg;
862 uint16 destoffset;
863 uint8 destval;
864 FETCH_DECODE_MODRM(m,mod,rh,rl);
865 switch (mod)
866 {
867 case 0:
868 destoffset=decode_rm00_address(m,rl);
869 destval = fetch_data_byte(m,destoffset);
870 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
871 destval = and_byte(m, destval, *srcreg);
872 store_data_byte(m,destoffset,destval);
873 break;
874 case 1:
875 destoffset=decode_rm01_address(m,rl);
876 destval = fetch_data_byte(m,destoffset);
877 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
878 destval = and_byte(m, destval, *srcreg);
879 store_data_byte(m,destoffset,destval);
880 break;
881 case 2:
882 destoffset=decode_rm10_address(m,rl);
883 destval = fetch_data_byte(m,destoffset);
884 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
885 destval = and_byte(m, destval, *srcreg);
886 store_data_byte(m,destoffset,destval);
887 break;
888 case 3: /* register to register */
889 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
890 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
891 *destreg = and_byte(m, *destreg, *srcreg);
892 break;
893 }
894 DECODE_CLEAR_SEGOVR(m);
895 }
896
897 /*opcode=0x21*/
898 static void i86op_and_word_RM_R(PC_ENV *m)
899 {
900 uint16 mod,rl,rh;
901 uint16 *destreg,*srcreg;
902 uint16 destoffset;
903 uint16 destval;
904 FETCH_DECODE_MODRM(m,mod,rh,rl);
905 switch (mod)
906 {
907 case 0:
908 destoffset=decode_rm00_address(m,rl);
909 destval = fetch_data_word(m,destoffset);
910 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
911 destval = and_word(m, destval, *srcreg);
912 store_data_word(m,destoffset,destval);
913 break;
914 case 1:
915 destoffset=decode_rm01_address(m,rl);
916 destval = fetch_data_word(m,destoffset);
917 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
918 destval = and_word(m, destval, *srcreg);
919 store_data_word(m,destoffset,destval);
920 break;
921 case 2:
922 destoffset=decode_rm10_address(m,rl);
923 destval = fetch_data_word(m,destoffset);
924 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
925 destval = and_word(m, destval, *srcreg);
926 store_data_word(m,destoffset,destval);
927 break;
928 case 3: /* register to register */
929 destreg = DECODE_RM_WORD_REGISTER(m,rl);
930 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
931 *destreg = and_word(m, *destreg, *srcreg);
932 break;
933 }
934 DECODE_CLEAR_SEGOVR(m);
935 }
936
937 /*opcode=0x22*/
938 static void i86op_and_byte_R_RM(PC_ENV *m)
939 {
940 uint16 mod,rl,rh;
941 uint8 *destreg,*srcreg;
942 uint16 srcoffset;
943 uint8 srcval;
944 FETCH_DECODE_MODRM(m,mod,rh,rl);
945 switch (mod)
946 {
947 case 0:
948 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
949 srcoffset=decode_rm00_address(m,rl);
950 srcval = fetch_data_byte(m,srcoffset);
951 *destreg = and_byte(m, *destreg, srcval);
952 break;
953 case 1:
954 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
955 srcoffset=decode_rm01_address(m,rl);
956 srcval = fetch_data_byte(m,srcoffset);
957 *destreg = and_byte(m, *destreg, srcval);
958 break;
959 case 2:
960 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
961 srcoffset=decode_rm10_address(m,rl);
962 srcval = fetch_data_byte(m,srcoffset);
963 *destreg = and_byte(m, * destreg, srcval);
964 break;
965 case 3: /* register to register */
966 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
967 srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
968 *destreg = and_byte(m, *destreg, *srcreg);
969 break;
970 }
971 DECODE_CLEAR_SEGOVR(m);
972 }
973
974 /*opcode=0x23*/
975 static void i86op_and_word_R_RM(PC_ENV *m)
976 {
977 uint16 mod,rl,rh;
978 uint16 *destreg,*srcreg;
979 uint16 srcoffset;
980 uint16 srcval;
981 FETCH_DECODE_MODRM(m,mod,rh,rl);
982 switch (mod)
983 {
984 case 0:
985 destreg = DECODE_RM_WORD_REGISTER(m,rh);
986 srcoffset=decode_rm00_address(m,rl);
987 srcval = fetch_data_word(m,srcoffset);
988 *destreg = and_word(m, *destreg, srcval);
989 break;
990 case 1:
991 destreg = DECODE_RM_WORD_REGISTER(m,rh);
992 srcoffset=decode_rm01_address(m,rl);
993 srcval = fetch_data_word(m,srcoffset);
994 *destreg = and_word(m, *destreg, srcval);
995 break;
996 case 2:
997 destreg = DECODE_RM_WORD_REGISTER(m,rh);
998 srcoffset=decode_rm10_address(m,rl);
999 srcval = fetch_data_word(m,srcoffset);
1000 *destreg = and_word(m, *destreg, srcval);
1001 break;
1002 case 3: /* register to register */
1003 destreg = DECODE_RM_WORD_REGISTER(m,rh);
1004 srcreg = DECODE_RM_WORD_REGISTER(m,rl);
1005 *destreg = and_word(m, *destreg, *srcreg);
1006 break;
1007 }
1008 DECODE_CLEAR_SEGOVR(m);
1009 }
1010
1011 /*opcode=0x24*/
1012 static void i86op_and_byte_AL_IMM(PC_ENV *m)
1013 {
1014 uint8 srcval;
1015 srcval = fetch_byte_imm(m);
1016 m->R_AL = and_byte(m, m->R_AL, srcval);
1017 DECODE_CLEAR_SEGOVR(m);
1018 }
1019
1020 /*opcode=0x25*/
1021 static void i86op_and_word_AX_IMM(PC_ENV *m)
1022 {
1023 uint16 srcval;
1024 srcval = fetch_word_imm(m);
1025 m->R_AX = and_word(m, m->R_AX, srcval);
1026 DECODE_CLEAR_SEGOVR(m);
1027 }
1028
1029 /*opcode=0x26*/
1030 static void i86op_segovr_ES(PC_ENV *m)
1031 {
1032 m->sysmode |= SYSMODE_SEGOVR_ES;
1033 /* note the lack of DECODE_CLEAR_SEGOVR(r)
1034 since, here is one of 4 opcode subroutines we do not
1035 want to do this.
1036 */
1037 }
1038
1039 /*opcode=0x27*/
1040 static void i86op_daa(PC_ENV *m)
1041 {
1042 uint16 dbyte;
1043 dbyte = m->R_AL;
1044 if (ACCESS_FLAG(m,F_AF)|| (dbyte&0xf) > 9)
1045 {
1046 dbyte += 6;
1047 if (dbyte&0x100)
1048 SET_FLAG(m, F_CF);
1049 SET_FLAG(m, F_AF);
1050 }
1051 else
1052 CLEAR_FLAG(m, F_AF);
1053 if (ACCESS_FLAG(m,F_CF) || (dbyte&0xf0) > 0x90)
1054 {
1055 dbyte += 0x60;
1056 SET_FLAG(m, F_CF);
1057 }
1058 else
1059 CLEAR_FLAG(m, F_CF);
1060 m->R_AL = (uint8) dbyte;
1061 CONDITIONAL_SET_FLAG((m->R_AL & 0x80),m,F_SF);
1062 CONDITIONAL_SET_FLAG((m->R_AL == 0), m,F_ZF);
1063 CONDITIONAL_SET_FLAG((parity_tab[m->R_AL]),m,F_PF);
1064 DECODE_CLEAR_SEGOVR(m);
1065 }
1066
1067 /*opcode=0x28*/
1068 static void i86op_sub_byte_RM_R(PC_ENV *m)
1069 {
1070 uint16 mod,rl,rh;
1071 uint8 *destreg,*srcreg;
1072 uint16 destoffset;
1073 uint8 destval;
1074 FETCH_DECODE_MODRM(m,mod,rh,rl);
1075 switch (mod)
1076 {
1077 case 0:
1078 destoffset=decode_rm00_address(m,rl);
1079 destval = fetch_data_byte(m,destoffset);
1080 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
1081 destval = sub_byte(m, destval, *srcreg);
1082 store_data_byte(m,destoffset,destval);
1083 break;
1084 case 1:
1085 destoffset=decode_rm01_address(m,rl);
1086 destval = fetch_data_byte(m,destoffset);
1087 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
1088 destval = sub_byte(m, destval, *srcreg);
1089 store_data_byte(m,destoffset,destval);
1090 break;
1091 case 2:
1092 destoffset=decode_rm10_address(m,rl);
1093 destval = fetch_data_byte(m,destoffset);
1094 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
1095 destval = sub_byte(m, destval, *srcreg);
1096 store_data_byte(m,destoffset,destval);
1097 break;
1098 case 3: /* register to register */
1099 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
1100 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
1101 *destreg = sub_byte(m, *destreg, *srcreg);
1102 break;
1103 }
1104 DECODE_CLEAR_SEGOVR(m);
1105 }
1106
1107 /*opcode=0x29*/
1108 static void i86op_sub_word_RM_R(PC_ENV *m)
1109 {
1110 uint16 mod,rl,rh;
1111 uint16 *destreg,*srcreg;
1112 uint16 destoffset;
1113 uint16 destval;
1114 FETCH_DECODE_MODRM(m,mod,rh,rl);
1115 switch (mod)
1116 {
1117 case 0:
1118 destoffset=decode_rm00_address(m,rl);
1119 destval = fetch_data_word(m,destoffset);
1120 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
1121 destval = sub_word(m, destval, *srcreg);
1122 store_data_word(m,destoffset,destval);
1123 break;
1124 case 1:
1125 destoffset=decode_rm01_address(m,rl);
1126 destval = fetch_data_word(m,destoffset);
1127 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
1128 destval = sub_word(m, destval, *srcreg);
1129 store_data_word(m,destoffset,destval);
1130 break;
1131 case 2:
1132 destoffset=decode_rm10_address(m,rl);
1133 destval = fetch_data_word(m,destoffset);
1134 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
1135 destval = sub_word(m, destval, *srcreg);
1136 store_data_word(m,destoffset,destval);
1137 break;
1138 case 3: /* register to register */
1139 destreg = DECODE_RM_WORD_REGISTER(m,rl);
1140 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
1141 *destreg = sub_word(m, *destreg, *srcreg);
1142 break;
1143 }
1144 DECODE_CLEAR_SEGOVR(m);
1145 }
1146
1147 /*opcode=0x2a*/
1148 static void i86op_sub_byte_R_RM(PC_ENV *m)
1149 {
1150 uint16 mod,rl,rh;
1151 uint8 *destreg,*srcreg;
1152 uint16 srcoffset;
1153 uint8 srcval;
1154 FETCH_DECODE_MODRM(m,mod,rh,rl);
1155 switch (mod)
1156 {
1157 case 0:
1158 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
1159 srcoffset=decode_rm00_address(m,rl);
1160 srcval = fetch_data_byte(m,srcoffset);
1161 *destreg = sub_byte(m, *destreg, srcval);
1162 break;
1163 case 1:
1164 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
1165 srcoffset=decode_rm01_address(m,rl);
1166 srcval = fetch_data_byte(m,srcoffset);
1167 *destreg = sub_byte(m, *destreg, srcval);
1168 break;
1169 case 2:
1170 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
1171 srcoffset=decode_rm10_address(m,rl);
1172 srcval = fetch_data_byte(m,srcoffset);
1173 *destreg = sub_byte(m, * destreg, srcval);
1174 break;
1175 case 3: /* register to register */
1176 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
1177 srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
1178 *destreg = sub_byte(m, *destreg, *srcreg);
1179 break;
1180 }
1181 DECODE_CLEAR_SEGOVR(m);
1182 }
1183
1184 /*opcode=0x2b*/
1185 static void i86op_sub_word_R_RM(PC_ENV *m)
1186 {
1187 uint16 mod,rl,rh;
1188 uint16 *destreg,*srcreg;
1189 uint16 srcoffset;
1190 uint16 srcval;
1191 FETCH_DECODE_MODRM(m,mod,rh,rl);
1192 switch (mod)
1193 {
1194 case 0:
1195 destreg = DECODE_RM_WORD_REGISTER(m,rh);
1196 srcoffset=decode_rm00_address(m,rl);
1197 srcval = fetch_data_word(m,srcoffset);
1198 *destreg = sub_word(m, *destreg, srcval);
1199 break;
1200 case 1:
1201 destreg = DECODE_RM_WORD_REGISTER(m,rh);
1202 srcoffset=decode_rm01_address(m,rl);
1203 srcval = fetch_data_word(m,srcoffset);
1204 *destreg = sub_word(m, *destreg, srcval);
1205 break;
1206 case 2:
1207 destreg = DECODE_RM_WORD_REGISTER(m,rh);
1208 srcoffset=decode_rm10_address(m,rl);
1209 srcval = fetch_data_word(m,srcoffset);
1210 *destreg = sub_word(m, *destreg, srcval);
1211 break;
1212 case 3: /* register to register */
1213 destreg = DECODE_RM_WORD_REGISTER(m,rh);
1214 srcreg = DECODE_RM_WORD_REGISTER(m,rl);
1215 *destreg = sub_word(m, *destreg, *srcreg);
1216 break;
1217 }
1218 DECODE_CLEAR_SEGOVR(m);
1219 }
1220
1221 /*opcode=0x2c*/
1222 static void i86op_sub_byte_AL_IMM(PC_ENV *m)
1223 {
1224 uint8 srcval;
1225 srcval = fetch_byte_imm(m);
1226 m->R_AL = sub_byte(m, m->R_AL, srcval);
1227 DECODE_CLEAR_SEGOVR(m);
1228 }
1229
1230 /*opcode=0x2d*/
1231 static void i86op_sub_word_AX_IMM(PC_ENV *m)
1232 {
1233 uint16 srcval;
1234 srcval = fetch_word_imm(m);
1235 m->R_AX = sub_word(m, m->R_AX, srcval);
1236 DECODE_CLEAR_SEGOVR(m);
1237 }
1238
1239 /*opcode=0x2e*/
1240 static void i86op_segovr_CS(PC_ENV *m)
1241 {
1242 m->sysmode |= SYSMODE_SEGOVR_CS;
1243 /* note no DECODE_CLEAR_SEGOVER here. */
1244 }
1245
1246 /*opcode=0x2f*/
1247 static void i86op_das(PC_ENV *m)
1248 {
1249 uint16 dbyte;
1250 dbyte = m->R_AL;
1251 if ( ACCESS_FLAG(m,F_AF) || (dbyte&0xf) > 9)
1252 {
1253 dbyte -= 6;
1254 if (dbyte&0x100) /* XXXXX --- this is WRONG */
1255 SET_FLAG(m, F_CF);
1256 SET_FLAG(m, F_AF);
1257 }
1258 else
1259 CLEAR_FLAG(m, F_AF);
1260 if (ACCESS_FLAG(m,F_CF) || (dbyte&0xf0) > 0x90)
1261 {
1262 dbyte -= 0x60;
1263 SET_FLAG(m, F_CF);
1264 }
1265 else
1266 CLEAR_FLAG(m, F_CF);
1267 m->R_AL = (uint8) dbyte;
1268 CONDITIONAL_SET_FLAG(m->R_AL & 0x80,m,F_SF);
1269 CONDITIONAL_SET_FLAG(m->R_AL == 0,m,F_ZF);
1270 CONDITIONAL_SET_FLAG(parity_tab[m->R_AL],m,F_PF);
1271 DECODE_CLEAR_SEGOVR(m);
1272 }
1273
1274 /*opcode=0x30*/
1275 static void i86op_xor_byte_RM_R(PC_ENV *m)
1276 {
1277 uint16 mod,rl,rh;
1278 uint8 *destreg,*srcreg;
1279 uint16 destoffset;
1280 uint8 destval;
1281 FETCH_DECODE_MODRM(m,mod,rh,rl);
1282 switch (mod)
1283 {
1284 case 0:
1285 destoffset=decode_rm00_address(m,rl);
1286 destval = fetch_data_byte(m,destoffset);
1287 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
1288 destval = xor_byte(m, destval, *srcreg);
1289 store_data_byte(m,destoffset,destval);
1290 break;
1291 case 1:
1292 destoffset=decode_rm01_address(m,rl);
1293 destval = fetch_data_byte(m,destoffset);
1294 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
1295 destval = xor_byte(m, destval, *srcreg);
1296 store_data_byte(m,destoffset,destval);
1297 break;
1298 case 2:
1299 destoffset=decode_rm10_address(m,rl);
1300 destval = fetch_data_byte(m,destoffset);
1301 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
1302 destval = xor_byte(m, destval, *srcreg);
1303 store_data_byte(m,destoffset,destval);
1304 break;
1305 case 3: /* register to register */
1306 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
1307 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
1308 *destreg = xor_byte(m, *destreg, *srcreg);
1309 break;
1310 }
1311 DECODE_CLEAR_SEGOVR(m);
1312 }
1313
1314 /*opcode=0x31*/
1315 static void i86op_xor_word_RM_R(PC_ENV *m)
1316 {
1317 uint16 mod,rl,rh;
1318 uint16 *destreg,*srcreg;
1319 uint16 destoffset;
1320 uint16 destval;
1321 FETCH_DECODE_MODRM(m,mod,rh,rl);
1322 switch (mod)
1323 {
1324 case 0:
1325 destoffset=decode_rm00_address(m,rl);
1326 destval = fetch_data_word(m,destoffset);
1327 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
1328 destval = xor_word(m, destval, *srcreg);
1329 store_data_word(m,destoffset,destval);
1330 break;
1331 case 1:
1332 destoffset=decode_rm01_address(m,rl);
1333 destval = fetch_data_word(m,destoffset);
1334 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
1335 destval = xor_word(m, destval, *srcreg);
1336 store_data_word(m,destoffset,destval);
1337 break;
1338 case 2:
1339 destoffset=decode_rm10_address(m,rl);
1340 destval = fetch_data_word(m,destoffset);
1341 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
1342 destval = xor_word(m, destval, *srcreg);
1343 store_data_word(m,destoffset,destval);
1344 break;
1345 case 3: /* register to register */
1346 destreg = DECODE_RM_WORD_REGISTER(m,rl);
1347 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
1348 *destreg = xor_word(m, *destreg, *srcreg);
1349 break;
1350 }
1351 DECODE_CLEAR_SEGOVR(m);
1352 }
1353
1354 /*opcode=0x32*/
1355 static void i86op_xor_byte_R_RM(PC_ENV *m)
1356 {
1357 uint16 mod,rl,rh;
1358 uint8 *destreg,*srcreg;
1359 uint16 srcoffset;
1360 uint8 srcval;
1361 FETCH_DECODE_MODRM(m,mod,rh,rl);
1362 switch (mod)
1363 {
1364 case 0:
1365 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
1366 srcoffset=decode_rm00_address(m,rl);
1367 srcval = fetch_data_byte(m,srcoffset);
1368 *destreg = xor_byte(m, *destreg, srcval);
1369 break;
1370 case 1:
1371 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
1372 srcoffset=decode_rm01_address(m,rl);
1373 srcval = fetch_data_byte(m,srcoffset);
1374 *destreg = xor_byte(m, *destreg, srcval);
1375 break;
1376 case 2:
1377 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
1378 srcoffset=decode_rm10_address(m,rl);
1379 srcval = fetch_data_byte(m,srcoffset);
1380 *destreg = xor_byte(m, *destreg, srcval);
1381 break;
1382 case 3: /* register to register */
1383 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
1384 srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
1385 *destreg = xor_byte(m, *destreg, *srcreg);
1386 break;
1387 }
1388 DECODE_CLEAR_SEGOVR(m);
1389 }
1390
1391 /*opcode=0x33*/
1392 static void i86op_xor_word_R_RM(PC_ENV *m)
1393 {
1394 uint16 mod,rl,rh;
1395 uint16 *destreg,*srcreg;
1396 uint16 srcoffset;
1397 uint16 srcval;
1398 FETCH_DECODE_MODRM(m,mod,rh,rl);
1399 switch (mod)
1400 {
1401 case 0:
1402 destreg = DECODE_RM_WORD_REGISTER(m,rh);
1403 srcoffset=decode_rm00_address(m,rl);
1404 srcval = fetch_data_word(m,srcoffset);
1405 *destreg = xor_word(m, *destreg, srcval);
1406 break;
1407 case 1:
1408 destreg = DECODE_RM_WORD_REGISTER(m,rh);
1409 srcoffset=decode_rm01_address(m,rl);
1410 srcval = fetch_data_word(m,srcoffset);
1411 *destreg = xor_word(m, *destreg, srcval);
1412 break;
1413 case 2:
1414 destreg = DECODE_RM_WORD_REGISTER(m,rh);
1415 srcoffset=decode_rm10_address(m,rl);
1416 srcval = fetch_data_word(m,srcoffset);
1417 *destreg = xor_word(m, *destreg, srcval);
1418 break;
1419 case 3: /* register to register */
1420 destreg = DECODE_RM_WORD_REGISTER(m,rh);
1421 srcreg = DECODE_RM_WORD_REGISTER(m,rl);
1422 *destreg = xor_word(m, *destreg, *srcreg);
1423 break;
1424 }
1425 DECODE_CLEAR_SEGOVR(m);
1426 }
1427
1428 /*opcode=0x34*/
1429 static void i86op_xor_byte_AL_IMM(PC_ENV *m)
1430 {
1431 uint8 srcval;
1432 srcval = fetch_byte_imm(m);
1433 m->R_AL = xor_byte(m, m->R_AL, srcval);
1434 DECODE_CLEAR_SEGOVR(m);
1435 }
1436
1437 /*opcode=0x35*/
1438 static void i86op_xor_word_AX_IMM(PC_ENV *m)
1439 {
1440 uint16 srcval;
1441 srcval = fetch_word_imm(m);
1442 m->R_AX = xor_word(m, m->R_AX, srcval);
1443 DECODE_CLEAR_SEGOVR(m);
1444 }
1445
1446 /*opcode=0x36*/
1447 static void i86op_segovr_SS(PC_ENV *m)
1448 {
1449 m->sysmode |= SYSMODE_SEGOVR_SS;
1450 /* no DECODE_CLEAR_SEGOVER ! */
1451 }
1452
1453 /*opcode=0x37*/
1454 static void i86op_aaa(PC_ENV *m)
1455 {
1456 if ( (m->R_AL & 0xf) > 0x9 || ACCESS_FLAG(m,F_AF))
1457 {
1458 m->R_AL += 0x6;
1459 m->R_AH += 1;
1460 SET_FLAG(m, F_AF);
1461 SET_FLAG(m, F_CF);
1462 }
1463 else
1464 {
1465 CLEAR_FLAG(m, F_CF);
1466 CLEAR_FLAG(m, F_AF);
1467 }
1468 m->R_AL &= 0xf;
1469 DECODE_CLEAR_SEGOVR(m);
1470 }
1471
1472 /*opcode=0x38*/
1473 static void i86op_cmp_byte_RM_R(PC_ENV *m)
1474 {
1475 uint16 mod,rl,rh;
1476 uint8 *destreg,*srcreg;
1477 uint16 destoffset;
1478 uint8 destval;
1479 FETCH_DECODE_MODRM(m,mod,rh,rl);
1480 switch (mod)
1481 {
1482 case 0:
1483 destoffset=decode_rm00_address(m,rl);
1484 destval = fetch_data_byte(m,destoffset);
1485 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
1486 cmp_byte(m, destval, *srcreg);
1487 break;
1488 case 1:
1489 destoffset=decode_rm01_address(m,rl);
1490 destval = fetch_data_byte(m,destoffset);
1491 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
1492 cmp_byte(m, destval, *srcreg);
1493 break;
1494 case 2:
1495 destoffset=decode_rm10_address(m,rl);
1496 destval = fetch_data_byte(m,destoffset);
1497 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
1498 cmp_byte(m, destval, *srcreg);
1499 break;
1500 case 3: /* register to register */
1501 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
1502 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
1503 cmp_byte(m, *destreg, *srcreg);
1504 break;
1505 }
1506 DECODE_CLEAR_SEGOVR(m);
1507 }
1508
1509 /*opcode=0x39*/
1510 static void i86op_cmp_word_RM_R(PC_ENV *m)
1511 {
1512 uint16 mod,rl,rh;
1513 uint16 *destreg,*srcreg;
1514 uint16 destoffset;
1515 uint16 destval;
1516 FETCH_DECODE_MODRM(m,mod,rh,rl);
1517 switch (mod)
1518 {
1519 case 0:
1520 destoffset=decode_rm00_address(m,rl);
1521 destval = fetch_data_word(m,destoffset);
1522 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
1523 cmp_word(m, destval, *srcreg);
1524 break;
1525 case 1:
1526 destoffset=decode_rm01_address(m,rl);
1527 destval = fetch_data_word(m,destoffset);
1528 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
1529 cmp_word(m, destval, *srcreg);
1530 break;
1531 case 2:
1532 destoffset=decode_rm10_address(m,rl);
1533 destval = fetch_data_word(m,destoffset);
1534 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
1535 cmp_word(m, destval, *srcreg);
1536 break;
1537 case 3: /* register to register */
1538 destreg = DECODE_RM_WORD_REGISTER(m,rl);
1539 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
1540 cmp_word(m, *destreg, *srcreg);
1541 break;
1542 }
1543 DECODE_CLEAR_SEGOVR(m);
1544 }
1545
1546 /*opcode=0x3a*/
1547 static void i86op_cmp_byte_R_RM(PC_ENV *m)
1548 {
1549 uint16 mod,rl,rh;
1550 uint8 *destreg,*srcreg;
1551 uint16 srcoffset;
1552 uint8 srcval;
1553 FETCH_DECODE_MODRM(m,mod,rh,rl);
1554 switch (mod)
1555 {
1556 case 0:
1557 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
1558 srcoffset=decode_rm00_address(m,rl);
1559 srcval = fetch_data_byte(m,srcoffset);
1560 cmp_byte(m, *destreg, srcval);
1561 break;
1562 case 1:
1563 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
1564 srcoffset=decode_rm01_address(m,rl);
1565 srcval = fetch_data_byte(m,srcoffset);
1566 cmp_byte(m, *destreg, srcval);
1567 break;
1568 case 2:
1569 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
1570 srcoffset=decode_rm10_address(m,rl);
1571 srcval = fetch_data_byte(m,srcoffset);
1572 cmp_byte(m, * destreg, srcval);
1573 break;
1574 case 3: /* register to register */
1575 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
1576 srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
1577 cmp_byte(m, *destreg, *srcreg);
1578 break;
1579 }
1580 DECODE_CLEAR_SEGOVR(m);
1581 }
1582
1583 /*opcode=0x3b*/
1584 static void i86op_cmp_word_R_RM(PC_ENV *m)
1585 {
1586 uint16 mod,rl,rh;
1587 uint16 *destreg,*srcreg;
1588 uint16 srcoffset;
1589 uint16 srcval;
1590 FETCH_DECODE_MODRM(m,mod,rh,rl);
1591 switch (mod)
1592 {
1593 case 0:
1594 destreg = DECODE_RM_WORD_REGISTER(m,rh);
1595 srcoffset=decode_rm00_address(m,rl);
1596 srcval = fetch_data_word(m,srcoffset);
1597 cmp_word(m, *destreg, srcval);
1598 break;
1599 case 1:
1600 destreg = DECODE_RM_WORD_REGISTER(m,rh);
1601 srcoffset=decode_rm01_address(m,rl);
1602 srcval = fetch_data_word(m,srcoffset);
1603 cmp_word(m, *destreg, srcval);
1604 break;
1605 case 2:
1606 destreg = DECODE_RM_WORD_REGISTER(m,rh);
1607 srcoffset=decode_rm10_address(m,rl);
1608 srcval = fetch_data_word(m,srcoffset);
1609 cmp_word(m, *destreg, srcval);
1610 break;
1611 case 3: /* register to register */
1612 destreg = DECODE_RM_WORD_REGISTER(m,rh);
1613 srcreg = DECODE_RM_WORD_REGISTER(m,rl);
1614 cmp_word(m, *destreg, *srcreg);
1615 break;
1616 }
1617 DECODE_CLEAR_SEGOVR(m);
1618 }
1619
1620 /*opcode=0x3c*/
1621 static void i86op_cmp_byte_AL_IMM(PC_ENV *m)
1622 {
1623 uint8 srcval;
1624 srcval = fetch_byte_imm(m);
1625 cmp_byte(m, m->R_AL, srcval);
1626 DECODE_CLEAR_SEGOVR(m);
1627 }
1628
1629 /*opcode=0x3d*/
1630 static void i86op_cmp_word_AX_IMM(PC_ENV *m)
1631 {
1632 uint16 srcval;
1633 srcval = fetch_word_imm(m);
1634 cmp_word(m, m->R_AX, srcval);
1635 DECODE_CLEAR_SEGOVR(m);
1636 }
1637
1638 /*opcode=0x3e*/
1639 static void i86op_segovr_DS(PC_ENV *m)
1640 {
1641 m->sysmode |= SYSMODE_SEGOVR_DS;
1642 /* NO DECODE_CLEAR_SEGOVR! */
1643 }
1644
1645 /*opcode=0x3f*/
1646 static void i86op_aas(PC_ENV *m)
1647 {
1648 /* ???? Check out the subtraction here. Will this ?ever? cause
1649 the contents of R_AL or R_AH to be affected incorrectly since
1650 they are being subtracted from *and* are unsigned.
1651 Should put an assertion in here.
1652 */
1653 if ( (m->R_AL & 0xf) > 0x9 || ACCESS_FLAG(m,F_AF))
1654 {
1655 m->R_AL -= 0x6;
1656 m->R_AH -= 1;
1657 SET_FLAG(m, F_AF);
1658 SET_FLAG(m, F_CF);
1659 }
1660 else
1661 {
1662 CLEAR_FLAG(m, F_CF);
1663 CLEAR_FLAG(m, F_AF);
1664 }
1665 m->R_AL &= 0xf;
1666 DECODE_CLEAR_SEGOVR(m);
1667 }
1668
1669 /*opcode=0x40*/
1670 static void i86op_inc_AX(PC_ENV *m)
1671 {
1672 m->R_AX = inc_word(m,m->R_AX);
1673 DECODE_CLEAR_SEGOVR(m);
1674 }
1675
1676 /*opcode=0x41*/
1677 static void i86op_inc_CX(PC_ENV *m)
1678 {
1679 m->R_CX = inc_word(m,m->R_CX);
1680 DECODE_CLEAR_SEGOVR(m);
1681 }
1682
1683 /*opcode=0x42*/
1684 static void i86op_inc_DX(PC_ENV *m)
1685 {
1686 m->R_DX = inc_word(m,m->R_DX);
1687 DECODE_CLEAR_SEGOVR(m);
1688 }
1689
1690 /*opcode=0x43*/
1691 static void i86op_inc_BX(PC_ENV *m)
1692 {
1693 m->R_BX = inc_word(m,m->R_BX);
1694 DECODE_CLEAR_SEGOVR(m);
1695 }
1696
1697 /*opcode=0x44*/
1698 static void i86op_inc_SP(PC_ENV *m)
1699 {
1700 m->R_SP = inc_word(m,m->R_SP);
1701 DECODE_CLEAR_SEGOVR(m);
1702 }
1703
1704 /*opcode=0x45*/
1705 static void i86op_inc_BP(PC_ENV *m)
1706 {
1707 m->R_BP = inc_word(m,m->R_BP);
1708 DECODE_CLEAR_SEGOVR(m);
1709 }
1710
1711 /*opcode=0x46*/
1712 static void i86op_inc_SI(PC_ENV *m)
1713 {
1714 m->R_SI = inc_word(m,m->R_SI);
1715 DECODE_CLEAR_SEGOVR(m);
1716 }
1717
1718 /*opcode=0x47*/
1719 static void i86op_inc_DI(PC_ENV *m)
1720 {
1721 m->R_DI = inc_word(m,m->R_DI);
1722 DECODE_CLEAR_SEGOVR(m);
1723 }
1724
1725 /*opcode=0x48*/
1726 static void i86op_dec_AX(PC_ENV *m)
1727 {
1728 m->R_AX = dec_word(m,m->R_AX);
1729 DECODE_CLEAR_SEGOVR(m);
1730 }
1731
1732 /*opcode=0x49*/
1733 static void i86op_dec_CX(PC_ENV *m)
1734 {
1735 m->R_CX = dec_word(m,m->R_CX);
1736 DECODE_CLEAR_SEGOVR(m);
1737 }
1738
1739 /*opcode=0x4a*/
1740 static void i86op_dec_DX(PC_ENV *m)
1741 {
1742 m->R_DX = dec_word(m,m->R_DX);
1743 DECODE_CLEAR_SEGOVR(m);
1744 }
1745
1746 /*opcode=0x4b*/
1747 static void i86op_dec_BX(PC_ENV *m)
1748 {
1749 m->R_BX = dec_word(m,m->R_BX);
1750 DECODE_CLEAR_SEGOVR(m);
1751 }
1752
1753 /*opcode=0x4c*/
1754 static void i86op_dec_SP(PC_ENV *m)
1755 {
1756 m->R_SP = dec_word(m,m->R_SP);
1757 DECODE_CLEAR_SEGOVR(m);
1758 }
1759
1760 /*opcode=0x4d*/
1761 static void i86op_dec_BP(PC_ENV *m)
1762 {
1763 m->R_BP = dec_word(m,m->R_BP);
1764 DECODE_CLEAR_SEGOVR(m);
1765 }
1766
1767 /*opcode=0x4e*/
1768 static void i86op_dec_SI(PC_ENV *m)
1769 {
1770 m->R_SI = dec_word(m,m->R_SI);
1771 DECODE_CLEAR_SEGOVR(m);
1772 }
1773
1774 /*opcode=0x4f*/
1775 static void i86op_dec_DI(PC_ENV *m)
1776 {
1777 m->R_DI = dec_word(m,m->R_DI);
1778 DECODE_CLEAR_SEGOVR(m);
1779 }
1780
1781 /*opcode=0x50*/
1782 static void i86op_push_AX(PC_ENV *m)
1783 {
1784 push_word(m,m->R_AX);
1785 DECODE_CLEAR_SEGOVR(m);
1786 }
1787
1788 /*opcode=0x51*/
1789 static void i86op_push_CX(PC_ENV *m)
1790 {
1791 push_word(m,m->R_CX);
1792 DECODE_CLEAR_SEGOVR(m);
1793 }
1794
1795 /*opcode=0x52*/
1796 static void i86op_push_DX(PC_ENV *m)
1797 {
1798 push_word(m,m->R_DX);
1799 DECODE_CLEAR_SEGOVR(m);
1800 }
1801
1802 /*opcode=0x53*/
1803 static void i86op_push_BX(PC_ENV *m)
1804 {
1805 push_word(m,m->R_BX);
1806 DECODE_CLEAR_SEGOVR(m);
1807 }
1808
1809 /*opcode=0x54*/
1810 static void i86op_push_SP(PC_ENV *m)
1811 {
1812 /* .... Note this weirdness: One book I have access to
1813 claims that the value pushed here is actually sp-2. I.e.
1814 it decrements the stackpointer, and then pushes it. The 286
1815 I have does it this way. Changing this causes many problems.*/
1816 /* changed to push SP-2, since this *IS* how a 8088 does this */
1817 push_word(m,m->R_SP-2);
1818 DECODE_CLEAR_SEGOVR(m);
1819 }
1820
1821 /*opcode=0x55*/
1822 static void i86op_push_BP(PC_ENV *m)
1823 {
1824 push_word(m,m->R_BP);
1825 DECODE_CLEAR_SEGOVR(m);
1826 }
1827
1828 /*opcode=0x56*/
1829 static void i86op_push_SI(PC_ENV *m)
1830 {
1831 push_word(m,m->R_SI);
1832 DECODE_CLEAR_SEGOVR(m);
1833 }
1834
1835 /*opcode=0x57*/
1836 static void i86op_push_DI(PC_ENV *m)
1837 {
1838 push_word(m,m->R_DI);
1839 DECODE_CLEAR_SEGOVR(m);
1840 }
1841
1842 /*opcode=0x58*/
1843 static void i86op_pop_AX(PC_ENV *m)
1844 {
1845 m->R_AX = pop_word(m);
1846 DECODE_CLEAR_SEGOVR(m);
1847 }
1848
1849 /*opcode=0x59*/
1850 static void i86op_pop_CX(PC_ENV *m)
1851 {
1852 m->R_CX = pop_word(m);
1853 DECODE_CLEAR_SEGOVR(m);
1854 }
1855
1856 /*opcode=0x5a*/
1857 static void i86op_pop_DX(PC_ENV *m)
1858 {
1859 m->R_DX = pop_word(m);
1860 DECODE_CLEAR_SEGOVR(m);
1861 }
1862
1863 /*opcode=0x5b*/
1864 static void i86op_pop_BX(PC_ENV *m)
1865 {
1866 m->R_BX = pop_word(m);
1867 DECODE_CLEAR_SEGOVR(m);
1868 }
1869
1870 /*opcode=0x5c*/
1871 static void i86op_pop_SP(PC_ENV *m)
1872 {
1873 m->R_SP = pop_word(m);
1874 DECODE_CLEAR_SEGOVR(m);
1875 }
1876
1877 /*opcode=0x5d*/
1878 static void i86op_pop_BP(PC_ENV *m)
1879 {
1880 m->R_BP = pop_word(m);
1881 DECODE_CLEAR_SEGOVR(m);
1882 }
1883
1884 /*opcode=0x5e*/
1885 static void i86op_pop_SI(PC_ENV *m)
1886 {
1887 m->R_SI = pop_word(m);
1888 DECODE_CLEAR_SEGOVR(m);
1889 }
1890
1891 /*opcode=0x5f*/
1892 static void i86op_pop_DI(PC_ENV *m)
1893 {
1894 m->R_DI = pop_word(m);
1895 DECODE_CLEAR_SEGOVR(m);
1896 }
1897
1898 /*opcode=0x60 ILLEGAL OP, calls i86op_illegal_op() */
1899 /*opcode=0x61 ILLEGAL OP, calls i86op_illegal_op() */
1900 /*opcode=0x62 ILLEGAL OP, calls i86op_illegal_op() */
1901 /*opcode=0x63 ILLEGAL OP, calls i86op_illegal_op() */
1902 /*opcode=0x64 ILLEGAL OP, calls i86op_illegal_op() */
1903 /*opcode=0x65 ILLEGAL OP, calls i86op_illegal_op() */
1904 /*opcode=0x66 ILLEGAL OP, calls i86op_illegal_op() */
1905 /*opcode=0x67 ILLEGAL OP, calls i86op_illegal_op() */
1906 /*opcode=0x68 ILLEGAL OP, calls i86op_illegal_op() */
1907 /*opcode=0x69 ILLEGAL OP, calls i86op_illegal_op() */
1908 /*opcode=0x6a ILLEGAL OP, calls i86op_illegal_op() */
1909 /*opcode=0x6b ILLEGAL OP, calls i86op_illegal_op() */
1910 /*opcode=0x6c ILLEGAL OP, calls i86op_illegal_op() */
1911 /*opcode=0x6d ILLEGAL OP, calls i86op_illegal_op() */
1912 /*opcode=0x6e ILLEGAL OP, calls i86op_illegal_op() */
1913 /*opcode=0x6f ILLEGAL OP, calls i86op_illegal_op() */
1914
1915 /*opcode=0x70*/
1916 static void i86op_jump_near_O(PC_ENV *m)
1917 {
1918 int8 offset;
1919 uint16 target;
1920 /* jump to byte offset if overflow flag is set */
1921 offset = (int8) fetch_byte_imm(m);
1922 target = (int16)(m->R_IP) + offset;
1923 if (ACCESS_FLAG(m,F_OF))
1924 m->R_IP = target;
1925 DECODE_CLEAR_SEGOVR(m);
1926 }
1927
1928 /*opcode=0x71*/
1929 static void i86op_jump_near_NO(PC_ENV *m)
1930 {
1931 int8 offset;
1932 uint16 target;
1933 /* jump to byte offset if overflow is not set */
1934 offset = (int8) fetch_byte_imm(m);
1935 target = (int16)(m->R_IP) + offset;
1936 if (!ACCESS_FLAG(m,F_OF))
1937 m->R_IP = target;
1938 DECODE_CLEAR_SEGOVR(m);
1939 }
1940
1941 /*opcode=0x72*/
1942 static void i86op_jump_near_B(PC_ENV *m)
1943 {
1944 int8 offset;
1945 uint16 target;
1946 /* jump to byte offset if carry flag is set. */
1947 offset = (int8)fetch_byte_imm(m); /* sign extended ??? */
1948 target = (int16)(m->R_IP) + offset;
1949 if (ACCESS_FLAG(m, F_CF))
1950 m->R_IP = target;
1951 DECODE_CLEAR_SEGOVR(m);
1952 }
1953
1954 /*opcode=0x73*/
1955 static void i86op_jump_near_NB(PC_ENV *m)
1956 {
1957 int8 offset;
1958 uint16 target;
1959 /* jump to byte offset if carry flag is clear. */
1960 offset = (int8)fetch_byte_imm(m); /* sign extended ??? */
1961 target = (int16)(m->R_IP) + offset;
1962 if (!ACCESS_FLAG(m,F_CF))
1963 m->R_IP = target;
1964 DECODE_CLEAR_SEGOVR(m);
1965 }
1966
1967 /*opcode=0x74*/
1968 static void i86op_jump_near_Z(PC_ENV *m)
1969 {
1970 int8 offset;
1971 uint16 target;
1972 /* jump to byte offset if zero flag is set. */
1973 offset = (int8)fetch_byte_imm(m);
1974 target = (int16)(m->R_IP) + offset;
1975 if (ACCESS_FLAG(m, F_ZF))
1976 m->R_IP = target;
1977 DECODE_CLEAR_SEGOVR(m);
1978 }
1979
1980 /*opcode=0x75*/
1981 static void i86op_jump_near_NZ(PC_ENV *m)
1982 {
1983 int8 offset;
1984 uint16 target;
1985 /* jump to byte offset if zero flag is clear. */
1986 offset = (int8)fetch_byte_imm(m);
1987 target = (int16)(m->R_IP) + offset;
1988 if (!ACCESS_FLAG(m, F_ZF))
1989 m->R_IP = target;
1990 DECODE_CLEAR_SEGOVR(m);
1991 }
1992
1993 /*opcode=0x76*/
1994 static void i86op_jump_near_BE(PC_ENV *m)
1995 {
1996 int8 offset;
1997 uint16 target;
1998 /* jump to byte offset if carry flag is set or if the zero
1999 flag is set. */
2000 offset = (int8)fetch_byte_imm(m);
2001 target = (int16)(m->R_IP) + offset;
2002 if (ACCESS_FLAG(m,F_CF) || ACCESS_FLAG(m,F_ZF))
2003 m->R_IP = target;
2004 DECODE_CLEAR_SEGOVR(m);
2005 }
2006
2007 /*opcode=0x77*/
2008 static void i86op_jump_near_NBE(PC_ENV *m)
2009 {
2010 int8 offset;
2011 uint16 target;
2012 /* jump to byte offset if carry flag is clear and if the zero
2013 flag is clear */
2014 offset = (int8)fetch_byte_imm(m);
2015 target = (int16)(m->R_IP) + offset;
2016 if (!(ACCESS_FLAG(m,F_CF)||ACCESS_FLAG(m,F_ZF)))
2017 m->R_IP = target;
2018 DECODE_CLEAR_SEGOVR(m);
2019 }
2020
2021 /*opcode=0x78*/
2022 static void i86op_jump_near_S(PC_ENV *m)
2023 {
2024 int8 offset;
2025 uint16 target;
2026 /* jump to byte offset if sign flag is set */
2027 offset = (int8)fetch_byte_imm(m);
2028 target = (int16)(m->R_IP) + offset;
2029 if (ACCESS_FLAG(m,F_SF))
2030 m->R_IP = target;
2031 DECODE_CLEAR_SEGOVR(m);
2032 }
2033
2034 /*opcode=0x79*/
2035 static void i86op_jump_near_NS(PC_ENV *m)
2036 {
2037 int8 offset;
2038 uint16 target;
2039 /* jump to byte offset if sign flag is clear */
2040 offset = (int8)fetch_byte_imm(m);
2041 target = (int16)(m->R_IP) + offset;
2042 if (!ACCESS_FLAG(m,F_SF))
2043 m->R_IP = target;
2044 DECODE_CLEAR_SEGOVR(m);
2045 }
2046
2047 /*opcode=0x7a*/
2048 static void i86op_jump_near_P(PC_ENV *m)
2049 {
2050 int8 offset;
2051 uint16 target;
2052 /* jump to byte offset if parity flag is set (even parity) */
2053 offset = (int8)fetch_byte_imm(m);
2054 target = (int16)(m->R_IP) + offset;
2055 if (ACCESS_FLAG(m, F_PF))
2056 m->R_IP = target;
2057 DECODE_CLEAR_SEGOVR(m);
2058 }
2059
2060 /*opcode=0x7b*/
2061 static void i86op_jump_near_NP(PC_ENV *m)
2062 {
2063 int8 offset;
2064 uint16 target;
2065 /* jump to byte offset if parity flag is clear (odd parity) */
2066 offset = (int8)fetch_byte_imm(m);
2067 target = (int16)(m->R_IP) + offset;
2068 if (!ACCESS_FLAG(m, F_PF))
2069 m->R_IP = target;
2070 DECODE_CLEAR_SEGOVR(m);
2071 }
2072
2073 /* JHH fixed till here... */
2074
2075 /*opcode=0x7c*/
2076 static void i86op_jump_near_L(PC_ENV *m)
2077 {
2078 int8 offset;
2079 uint16 target;
2080 int sf,of;
2081 /* jump to byte offset if sign flag not equal to overflow flag. */
2082 offset = (int8)fetch_byte_imm(m);
2083 target = (int16)(m->R_IP) + offset;
2084 /* note:
2085 * this is the simplest expression i could think of which
2086 * expresses SF != OF. m->R_FLG&F_SF either equals x80 or x00.
2087 * Similarly m->R_FLG&F_OF either equals x800 or x000.
2088 * The former shifted right by 7 puts a 1 or 0 in bit 0.
2089 * The latter shifter right by 11 puts a 1 or 0 in bit 0.
2090 * if the two expressions are the same, i.e. equal, then
2091 * a zero results from the xor. If they are not equal,
2092 * then a 1 results, and the jump is taken.
2093 */
2094 sf = ACCESS_FLAG(m,F_SF) != 0;
2095 of = ACCESS_FLAG(m,F_OF) != 0;
2096 /* was: if ( ((m->R_FLG & F_SF)>>7) ^ ((m->R_FLG & F_OF) >> 11))*/
2097 if (sf ^ of)
2098 m->R_IP = target;
2099 DECODE_CLEAR_SEGOVR(m);
2100 }
2101
2102 /*opcode=0x7d*/
2103 static void i86op_jump_near_NL(PC_ENV *m)
2104 {
2105 int8 offset;
2106 uint16 target;
2107 int sf,of;
2108 /* jump to byte offset if sign flag not equal to overflow flag. */
2109 offset = (int8)fetch_byte_imm(m);
2110 target = (int16)(m->R_IP) + offset;
2111 sf = ACCESS_FLAG(m,F_SF) != 0;
2112 of = ACCESS_FLAG(m,F_OF) != 0;
2113 /* note: inverse of above, but using == instead of xor. */
2114 /* was: if (((m->R_FLG & F_SF)>>7) == ((m->R_FLG & F_OF) >> 11))*/
2115 if (sf == of)
2116 m->R_IP = target;
2117 DECODE_CLEAR_SEGOVR(m);
2118 }
2119
2120 /*opcode=0x7e*/
2121 static void i86op_jump_near_LE(PC_ENV *m)
2122 {
2123 int8 offset;
2124 uint16 target;
2125 int sf,of;
2126 /* jump to byte offset if sign flag not equal to overflow flag
2127 or the zero flag is set */
2128 offset = (int8)fetch_byte_imm(m);
2129 target = (int16)(m->R_IP) + offset;
2130 sf = ACCESS_FLAG(m,F_SF) != 0;
2131 of = ACCESS_FLAG(m,F_OF) != 0;
2132 /* note: modification of JL */
2133 /* sf != of */
2134 /* was: if ((((m->R_FLG & F_SF)>>7) ^ ((m->R_FLG & F_OF) >> 11))
2135 || (m->R_FLG & F_ZF) ) */
2136 if ( (sf ^ of) || ACCESS_FLAG(m,F_ZF))
2137 m->R_IP = target;
2138 DECODE_CLEAR_SEGOVR(m);
2139 }
2140
2141 /*opcode=0x7f*/
2142 static void i86op_jump_near_NLE(PC_ENV *m)
2143 {
2144 int8 offset;
2145 uint16 target;
2146 int sf,of;
2147 /* jump to byte offset if sign flag equal to overflow flag.
2148 and the zero flag is clear*/
2149 offset = (int8)fetch_byte_imm(m);
2150 target = (int16)(m->R_IP) + offset;
2151 sf = ACCESS_FLAG(m,F_SF) != 0;
2152 of = ACCESS_FLAG(m,F_OF) != 0;
2153
2154 /* if (((m->R_FLG & F_SF)>>7) == ((m->R_FLG & F_OF) >> 11)
2155 && (!(m->R_FLG & F_ZF))) */
2156 if ( ( sf == of ) && !ACCESS_FLAG(m,F_ZF))
2157 m->R_IP = target;
2158 DECODE_CLEAR_SEGOVR(m);
2159 }
2160
2161 static uint8 (*opc80_byte_operation[])(PC_ENV *m,uint8 d,uint8 s) =
2162 {
2163 add_byte,/*00*/
2164 or_byte, /*01*/
2165 adc_byte,/*02*/
2166 sbb_byte,/*03*/
2167 and_byte,/*04*/
2168 sub_byte,/*05*/
2169 xor_byte,/*06*/
2170 cmp_byte,/*07*/
2171 };
2172
2173 /*opcode=0x80*/
2174 static void i86op_opc80_byte_RM_IMM(PC_ENV *m)
2175 {
2176 uint16 mod,rl,rh;
2177 uint8 *destreg;
2178 uint16 destoffset;
2179 uint8 imm;
2180 uint8 destval;
2181 /* weirdo special case instruction format. Part of the
2182 opcode held below in "RH". Doubly nested case would
2183 result, except that the decoded instruction
2184 */
2185 FETCH_DECODE_MODRM(m,mod,rh,rl);
2186 /* know operation, decode the mod byte to find the addressing
2187 mode. */
2188 switch (mod)
2189 {
2190 case 0:
2191 destoffset=decode_rm00_address(m,rl);
2192 destval = fetch_data_byte(m,destoffset);
2193 imm = fetch_byte_imm(m);
2194 destval = (*opc80_byte_operation[rh])(m, destval, imm);
2195 if (rh != 7) store_data_byte(m,destoffset,destval);
2196 break;
2197 case 1:
2198 destoffset=decode_rm01_address(m,rl);
2199 destval = fetch_data_byte(m,destoffset);
2200 imm = fetch_byte_imm(m);
2201 destval = (*opc80_byte_operation[rh])(m, destval, imm);
2202 if (rh != 7) store_data_byte(m,destoffset,destval);
2203 break;
2204 case 2:
2205 destoffset=decode_rm10_address(m,rl);
2206 destval = fetch_data_byte(m,destoffset);
2207 imm = fetch_byte_imm(m);
2208 destval = (*opc80_byte_operation[rh])(m, destval, imm);
2209 if (rh != 7) store_data_byte(m,destoffset,destval);
2210 break;
2211 case 3: /* register to register */
2212 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
2213 imm = fetch_byte_imm(m);
2214 destval = (*opc80_byte_operation[rh])(m, *destreg, imm);
2215 if (rh != 7) *destreg = destval;
2216 break;
2217 }
2218 DECODE_CLEAR_SEGOVR(m);
2219 }
2220
2221 static uint16 (*opc81_word_operation[])(PC_ENV *m,uint16 d,uint16 s) =
2222 { add_word,/*00*/
2223 or_word, /*01*/
2224 adc_word,/*02*/
2225 sbb_word,/*03*/
2226 and_word,/*04*/
2227 sub_word,/*05*/
2228 xor_word,/*06*/
2229 cmp_word,/*07*/
2230 };
2231
2232 /*opcode=0x81*/
2233 static void i86op_opc81_word_RM_IMM(PC_ENV *m)
2234 {
2235 uint16 mod,rl,rh;
2236 uint16 *destreg;
2237 uint16 destoffset;
2238 uint16 imm;
2239 uint16 destval;
2240 /* weirdo special case instruction format. Part of the
2241 opcode held below in "RH". Doubly nested case would
2242 result, except that the decoded instruction
2243 */
2244 FETCH_DECODE_MODRM(m,mod,rh,rl);
2245 /* know operation, decode the mod byte to find the addressing
2246 mode. */
2247 switch (mod)
2248 {
2249 case 0:
2250 destoffset=decode_rm00_address(m,rl);
2251 destval = fetch_data_word(m,destoffset);
2252 imm = fetch_word_imm(m);
2253 destval = (*opc81_word_operation[rh])(m, destval, imm);
2254 if (rh != 7) store_data_word(m,destoffset,destval);
2255 break;
2256 case 1:
2257 destoffset=decode_rm01_address(m,rl);
2258 destval = fetch_data_word(m,destoffset);
2259 imm = fetch_word_imm(m);
2260 destval = (*opc81_word_operation[rh])(m, destval, imm);
2261 if (rh != 7) store_data_word(m,destoffset,destval);
2262 break;
2263 case 2:
2264 destoffset=decode_rm10_address(m,rl);
2265 destval = fetch_data_word(m,destoffset);
2266 imm = fetch_word_imm(m);
2267 destval = (*opc81_word_operation[rh])(m, destval, imm);
2268 if (rh != 7) store_data_word(m,destoffset,destval);
2269 break;
2270 case 3: /* register to register */
2271 destreg = DECODE_RM_WORD_REGISTER(m,rl);
2272 imm = fetch_word_imm(m);
2273 destval = (*opc81_word_operation[rh])(m, *destreg, imm);
2274 if (rh != 7) *destreg = destval;
2275 break;
2276 }
2277 DECODE_CLEAR_SEGOVR(m);
2278 }
2279
2280 static uint8 (*opc82_byte_operation[])(PC_ENV *m,uint8 s,uint8 d) =
2281 {
2282 add_byte,/*00*/
2283 or_byte, /*01*/ /*YYY UNUSED ????*/
2284 adc_byte,/*02*/
2285 sbb_byte,/*03*/
2286 and_byte,/*04*/ /*YYY UNUSED ????*/
2287 sub_byte,/*05*/
2288 xor_byte,/*06*/ /*YYY UNUSED ????*/
2289 cmp_byte,/*07*/
2290 };
2291
2292 /*opcode=0x82*/
2293 static void i86op_opc82_byte_RM_IMM(PC_ENV *m)
2294 {
2295 uint16 mod,rl,rh;
2296 uint8 *destreg;
2297 uint16 destoffset;
2298 uint8 imm;
2299 uint8 destval;
2300 /* weirdo special case instruction format. Part of the
2301 opcode held below in "RH". Doubly nested case would
2302 result, except that the decoded instruction
2303 Similar to opcode 81, except that the immediate byte
2304 is sign extended to a word length.
2305 */
2306 FETCH_DECODE_MODRM(m,mod,rh,rl);
2307 /* know operation, decode the mod byte to find the addressing
2308 mode. */
2309 switch (mod)
2310 {
2311 case 0:
2312 destoffset=decode_rm00_address(m,rl);
2313 destval = fetch_data_byte(m,destoffset);
2314 imm = fetch_byte_imm(m);
2315 destval = (*opc82_byte_operation[rh])(m, destval, imm);
2316 if (rh != 7) store_data_byte(m,destoffset,destval);
2317 break;
2318 case 1:
2319 destoffset=decode_rm01_address(m,rl);
2320 destval = fetch_data_byte(m,destoffset);
2321 imm = fetch_byte_imm(m);
2322 destval = (*opc82_byte_operation[rh])(m, destval, imm);
2323 if (rh != 7) store_data_byte(m,destoffset,destval);
2324 break;
2325 case 2:
2326 destoffset=decode_rm10_address(m,rl);
2327 destval = fetch_data_byte(m,destoffset);
2328 imm = fetch_byte_imm(m);
2329 destval = (*opc82_byte_operation[rh])(m, destval, imm);
2330 if (rh != 7) store_data_byte(m,destoffset,destval);
2331 break;
2332 case 3: /* register to register */
2333 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
2334 imm = fetch_byte_imm(m);
2335 destval = (*opc82_byte_operation[rh])(m, *destreg, imm);
2336 if (rh != 7) *destreg = destval;
2337 break;
2338 }
2339 DECODE_CLEAR_SEGOVR(m);
2340 }
2341
2342 static uint16 (*opc83_word_operation[])(PC_ENV *m,uint16 s,uint16 d) =
2343 {
2344 add_word,/*00*/
2345 or_word, /*01*/ /*YYY UNUSED ????*/
2346 adc_word,/*02*/
2347 sbb_word,/*03*/
2348 and_word,/*04*/ /*YYY UNUSED ????*/
2349 sub_word,/*05*/
2350 xor_word,/*06*/ /*YYY UNUSED ????*/
2351 cmp_word,/*07*/
2352 };
2353
2354 /*opcode=0x83*/
2355 static void i86op_opc83_word_RM_IMM(PC_ENV *m)
2356 {
2357 uint16 mod,rl,rh;
2358 uint16 *destreg;
2359 uint16 destoffset;
2360 uint16 imm;
2361 uint16 destval;
2362 /* weirdo special case instruction format. Part of the
2363 opcode held below in "RH". Doubly nested case would
2364 result, except that the decoded instruction
2365 Similar to opcode 81, except that the immediate byte
2366 is sign extended to a word length.
2367 */
2368 FETCH_DECODE_MODRM(m,mod,rh,rl);
2369 /* know operation, decode the mod byte to find the addressing
2370 mode. */
2371 switch (mod)
2372 {
2373 case 0:
2374 destoffset=decode_rm00_address(m,rl);
2375 destval = fetch_data_word(m,destoffset);
2376 imm = (int8)fetch_byte_imm(m);
2377 destval = (*opc83_word_operation[rh])(m, destval, imm);
2378 if (rh != 7) store_data_word(m,destoffset,destval);
2379 break;
2380 case 1:
2381 destoffset=decode_rm01_address(m,rl);
2382 destval = fetch_data_word(m,destoffset);
2383 imm = (int8)fetch_byte_imm(m);
2384 destval = (*opc83_word_operation[rh])(m, destval, imm);
2385 if (rh != 7) store_data_word(m,destoffset,destval);
2386 break;
2387 case 2:
2388 destoffset=decode_rm10_address(m,rl);
2389 destval = fetch_data_word(m,destoffset);
2390 imm = (int8) fetch_byte_imm(m);
2391 destval = (*opc83_word_operation[rh])(m, destval, imm);
2392 if (rh != 7) store_data_word(m,destoffset,destval);
2393 break;
2394 case 3: /* register to register */
2395 destreg = DECODE_RM_WORD_REGISTER(m,rl);
2396 imm = (int8) fetch_byte_imm(m);
2397 destval = (*opc83_word_operation[rh])(m, *destreg, imm);
2398 if (rh != 7) *destreg = destval;
2399 break;
2400 }
2401 DECODE_CLEAR_SEGOVR(m);
2402 }
2403
2404 /*opcode=0x84*/
2405 static void i86op_test_byte_RM_R(PC_ENV *m)
2406 {
2407 uint16 mod,rl,rh;
2408 uint8 *destreg,*srcreg;
2409 uint16 destoffset;
2410 uint8 destval;
2411 FETCH_DECODE_MODRM(m,mod,rh,rl);
2412 switch (mod)
2413 {
2414 case 0:
2415 destoffset=decode_rm00_address(m,rl);
2416 destval = fetch_data_byte(m,destoffset);
2417 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
2418 test_byte(m, destval, *srcreg);
2419 break;
2420 case 1:
2421 destoffset=decode_rm01_address(m,rl);
2422 destval = fetch_data_byte(m,destoffset);
2423 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
2424 test_byte(m, destval, *srcreg);
2425 break;
2426 case 2:
2427 destoffset=decode_rm10_address(m,rl);
2428 destval = fetch_data_byte(m,destoffset);
2429 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
2430 test_byte(m, destval, *srcreg);
2431 break;
2432 case 3: /* register to register */
2433 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
2434 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
2435 test_byte(m, *destreg, *srcreg);
2436 break;
2437 }
2438 DECODE_CLEAR_SEGOVR(m);
2439 }
2440
2441 /*opcode=0x85*/
2442 static void i86op_test_word_RM_R(PC_ENV *m)
2443 {
2444 uint16 mod,rl,rh;
2445 uint16 *destreg,*srcreg;
2446 uint16 destoffset;
2447 uint16 destval;
2448 FETCH_DECODE_MODRM(m,mod,rh,rl);
2449 switch (mod)
2450 {
2451 case 0:
2452 destoffset=decode_rm00_address(m,rl);
2453 destval = fetch_data_word(m,destoffset);
2454 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2455 test_word(m, destval, *srcreg);
2456 break;
2457 case 1:
2458 destoffset=decode_rm01_address(m,rl);
2459 destval = fetch_data_word(m,destoffset);
2460 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2461 test_word(m, destval, *srcreg);
2462 break;
2463 case 2:
2464 destoffset=decode_rm10_address(m,rl);
2465 destval = fetch_data_word(m,destoffset);
2466 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2467 test_word(m, destval, *srcreg);
2468 break;
2469 case 3: /* register to register */
2470 destreg = DECODE_RM_WORD_REGISTER(m,rl);
2471 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2472 test_word(m, *destreg, *srcreg);
2473 break;
2474 }
2475 DECODE_CLEAR_SEGOVR(m);
2476 }
2477
2478 /*opcode=0x86*/
2479 static void i86op_xchg_byte_RM_R(PC_ENV *m)
2480 {
2481 uint16 mod,rl,rh;
2482 uint8 *destreg,*srcreg;
2483 uint16 destoffset;
2484 uint8 destval;
2485 uint8 tmp;
2486 FETCH_DECODE_MODRM(m,mod,rh,rl);
2487 switch (mod)
2488 {
2489 case 0:
2490 destoffset=decode_rm00_address(m,rl);
2491 destval = fetch_data_byte(m,destoffset);
2492 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
2493 tmp = *srcreg;
2494 *srcreg = destval;
2495 destval = tmp;
2496 store_data_byte(m,destoffset,destval);
2497 break;
2498 case 1:
2499 destoffset=decode_rm01_address(m,rl);
2500 destval = fetch_data_byte(m,destoffset);
2501 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
2502 tmp = *srcreg;
2503 *srcreg = destval;
2504 destval = tmp;
2505 store_data_byte(m,destoffset,destval);
2506 break;
2507 case 2:
2508 destoffset=decode_rm10_address(m,rl);
2509 destval = fetch_data_byte(m,destoffset);
2510 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
2511 tmp = *srcreg;
2512 *srcreg = destval;
2513 destval = tmp;
2514 store_data_byte(m,destoffset,destval);
2515 break;
2516 case 3: /* register to register */
2517 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
2518 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
2519 tmp = *srcreg;
2520 *srcreg = *destreg;
2521 *destreg = tmp;
2522 break;
2523 }
2524 DECODE_CLEAR_SEGOVR(m);
2525 }
2526
2527 /*opcode=0x87*/
2528 static void i86op_xchg_word_RM_R(PC_ENV *m)
2529 {
2530 uint16 mod,rl,rh;
2531 uint16 *destreg,*srcreg;
2532 uint16 destoffset;
2533 uint16 destval;
2534 uint16 tmp;
2535 FETCH_DECODE_MODRM(m,mod,rh,rl);
2536 switch (mod)
2537 {
2538 case 0:
2539 destoffset=decode_rm00_address(m,rl);
2540 destval = fetch_data_word(m,destoffset);
2541 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2542 tmp = *srcreg;
2543 *srcreg = destval;
2544 destval = tmp;
2545 store_data_word(m,destoffset,destval);
2546 break;
2547 case 1:
2548 destoffset=decode_rm01_address(m,rl);
2549 destval = fetch_data_word(m,destoffset);
2550 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2551 tmp = *srcreg;
2552 *srcreg = destval;
2553 destval = tmp;
2554 store_data_word(m,destoffset,destval);
2555 break;
2556 case 2:
2557 destoffset=decode_rm10_address(m,rl);
2558 destval = fetch_data_word(m,destoffset);
2559 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2560 tmp = *srcreg;
2561 *srcreg = destval;
2562 destval = tmp;
2563 store_data_word(m,destoffset,destval);
2564 break;
2565 case 3: /* register to register */
2566 destreg = DECODE_RM_WORD_REGISTER(m,rl);
2567 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2568 tmp = *srcreg;
2569 *srcreg = *destreg;
2570 *destreg = tmp;
2571 break;
2572 }
2573 DECODE_CLEAR_SEGOVR(m);
2574 }
2575
2576 /*opcode=0x88*/
2577 static void i86op_mov_byte_RM_R(PC_ENV *m)
2578 {
2579 uint16 mod,rl,rh;
2580 uint8 *destreg,*srcreg;
2581 uint16 destoffset;
2582 FETCH_DECODE_MODRM(m,mod,rh,rl);
2583 switch (mod)
2584 {
2585 case 0:
2586 destoffset=decode_rm00_address(m,rl);
2587 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
2588 store_data_byte(m,destoffset,*srcreg);
2589 break;
2590 case 1:
2591 destoffset=decode_rm01_address(m,rl);
2592 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
2593 store_data_byte(m,destoffset,*srcreg);
2594 break;
2595 case 2:
2596 destoffset=decode_rm10_address(m,rl);
2597 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
2598 store_data_byte(m,destoffset,*srcreg);
2599 break;
2600 case 3: /* register to register */
2601 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
2602 srcreg = DECODE_RM_BYTE_REGISTER(m,rh);
2603 *destreg = *srcreg;
2604 break;
2605 }
2606 DECODE_CLEAR_SEGOVR(m);
2607 }
2608
2609 /*opcode=0x89*/
2610 static void i86op_mov_word_RM_R(PC_ENV *m)
2611 {
2612 uint16 mod,rl,rh;
2613 uint16 *destreg,*srcreg;
2614 uint16 destoffset;
2615 FETCH_DECODE_MODRM(m,mod,rh,rl);
2616 switch (mod)
2617 {
2618 case 0:
2619 destoffset=decode_rm00_address(m,rl);
2620 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2621 store_data_word(m,destoffset,*srcreg);
2622 break;
2623 case 1:
2624 destoffset=decode_rm01_address(m,rl);
2625 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2626 store_data_word(m,destoffset,*srcreg);
2627 break;
2628 case 2:
2629 destoffset=decode_rm10_address(m,rl);
2630 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2631 store_data_word(m,destoffset,*srcreg);
2632 break;
2633 case 3: /* register to register */
2634 destreg = DECODE_RM_WORD_REGISTER(m,rl);
2635 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2636 *destreg = *srcreg;
2637 break;
2638 }
2639 DECODE_CLEAR_SEGOVR(m);
2640 }
2641
2642 /*opcode=0x8a*/
2643 static void i86op_mov_byte_R_RM(PC_ENV *m)
2644 {
2645 uint16 mod,rl,rh;
2646 uint8 *destreg,*srcreg;
2647 uint16 srcoffset;
2648 uint8 srcval;
2649 FETCH_DECODE_MODRM(m,mod,rh,rl);
2650 switch (mod)
2651 {
2652 case 0:
2653 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
2654 srcoffset=decode_rm00_address(m,rl);
2655 srcval = fetch_data_byte(m,srcoffset);
2656 *destreg = srcval;
2657 break;
2658 case 1:
2659 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
2660 srcoffset=decode_rm01_address(m,rl);
2661 srcval = fetch_data_byte(m,srcoffset);
2662 *destreg = srcval;
2663 break;
2664 case 2:
2665 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
2666 srcoffset=decode_rm10_address(m,rl);
2667 srcval = fetch_data_byte(m,srcoffset);
2668 *destreg = srcval;
2669 break;
2670 case 3: /* register to register */
2671 destreg = DECODE_RM_BYTE_REGISTER(m,rh);
2672 srcreg = DECODE_RM_BYTE_REGISTER(m,rl);
2673 *destreg = *srcreg;
2674 break;
2675 }
2676 DECODE_CLEAR_SEGOVR(m);
2677 }
2678
2679 /*opcode=0x8b*/
2680 static void i86op_mov_word_R_RM(PC_ENV *m)
2681 {
2682 uint16 mod,rl,rh;
2683 uint16 *destreg,*srcreg;
2684 uint16 srcoffset;
2685 uint16 srcval;
2686 FETCH_DECODE_MODRM(m,mod,rh,rl);
2687 switch (mod)
2688 {
2689 case 0:
2690 destreg = DECODE_RM_WORD_REGISTER(m,rh);
2691 srcoffset=decode_rm00_address(m,rl);
2692 srcval = fetch_data_word(m,srcoffset);
2693 *destreg = srcval;
2694 break;
2695 case 1:
2696 destreg = DECODE_RM_WORD_REGISTER(m,rh);
2697 srcoffset=decode_rm01_address(m,rl);
2698 srcval = fetch_data_word(m,srcoffset);
2699 *destreg = srcval;
2700 break;
2701 case 2:
2702 destreg = DECODE_RM_WORD_REGISTER(m,rh);
2703 srcoffset=decode_rm10_address(m,rl);
2704 srcval = fetch_data_word(m,srcoffset);
2705 *destreg = srcval;
2706 break;
2707 case 3: /* register to register */
2708 destreg = DECODE_RM_WORD_REGISTER(m,rh);
2709 srcreg = DECODE_RM_WORD_REGISTER(m,rl);
2710 *destreg = *srcreg;
2711 break;
2712 }
2713 DECODE_CLEAR_SEGOVR(m);
2714 }
2715
2716 /*opcode=0x8c*/
2717 static void i86op_mov_word_RM_SR(PC_ENV *m)
2718 {
2719 uint16 mod,rl,rh;
2720 uint16 *destreg,*srcreg;
2721 uint16 destoffset;
2722 uint16 destval;
2723 FETCH_DECODE_MODRM(m,mod,rh,rl);
2724 switch (mod)
2725 {
2726 case 0:
2727 destoffset=decode_rm00_address(m,rl);
2728 srcreg = decode_rm_seg_register(m,rh);
2729 destval = *srcreg;
2730 store_data_word(m,destoffset,destval);
2731 break;
2732 case 1:
2733 destoffset=decode_rm01_address(m,rl);
2734 srcreg = decode_rm_seg_register(m,rh);
2735 destval = *srcreg;
2736 store_data_word(m,destoffset,destval);
2737 break;
2738 case 2:
2739 destoffset=decode_rm10_address(m,rl);
2740 srcreg = decode_rm_seg_register(m,rh);
2741 destval = *srcreg;
2742 store_data_word(m,destoffset,destval);
2743 break;
2744 case 3: /* register to register */
2745 destreg = DECODE_RM_WORD_REGISTER(m,rl);
2746 srcreg = decode_rm_seg_register(m,rh);
2747 *destreg = *srcreg;
2748 break;
2749 }
2750 DECODE_CLEAR_SEGOVR(m);
2751 }
2752
2753 /*opcode=0x8d*/
2754 static void i86op_lea_word_R_M(PC_ENV *m)
2755 {
2756 uint16 mod,rl,rh;
2757 uint16 *srcreg;
2758 uint16 destoffset;
2759 FETCH_DECODE_MODRM(m,mod,rh,rl);
2760 switch (mod)
2761 {
2762 case 0:
2763 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2764 destoffset=decode_rm00_address(m,rl);
2765 *srcreg = destoffset;
2766 break;
2767 case 1:
2768 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2769 destoffset=decode_rm01_address(m,rl);
2770 *srcreg = destoffset;
2771 break;
2772 case 2:
2773 srcreg = DECODE_RM_WORD_REGISTER(m,rh);
2774 destoffset=decode_rm10_address(m,rl);
2775 *srcreg = destoffset;
2776 break;
2777 case 3: /* register to register */
2778 /* undefined. Do nothing. */
2779 break;
2780 }
2781 DECODE_CLEAR_SEGOVR(m);
2782 }
2783
2784 /*opcode=0x8e*/
2785 static void i86op_mov_word_SR_RM(PC_ENV *m)
2786 {
2787 uint16 mod,rl,rh;
2788 uint16 *destreg,*srcreg;
2789 uint16 srcoffset;
2790 uint16 srcval;
2791 FETCH_DECODE_MODRM(m,mod,rh,rl);
2792 switch (mod)
2793 {
2794 case 0:
2795 destreg = decode_rm_seg_register(m,rh);
2796 srcoffset=decode_rm00_address(m,rl);
2797 srcval = fetch_data_word(m,srcoffset);
2798 *destreg = srcval;
2799 break;
2800 case 1:
2801 destreg = decode_rm_seg_register(m,rh);
2802 srcoffset=decode_rm01_address(m,rl);
2803 srcval = fetch_data_word(m,srcoffset);
2804 *destreg = srcval;
2805 break;
2806 case 2:
2807 destreg = decode_rm_seg_register(m,rh);
2808 srcoffset = decode_rm10_address(m,rl);
2809 srcval = fetch_data_word(m,srcoffset);
2810 *destreg = srcval;
2811 break;
2812 case 3: /* register to register */
2813 destreg = decode_rm_seg_register(m,rh);
2814 srcreg = DECODE_RM_WORD_REGISTER(m,rl);
2815 *destreg = *srcreg;
2816 break;
2817 }
2818 /*\
2819 * clean up, and reset all the R_xSP pointers to the correct
2820 * locations. This is about 3x too much overhead (doing all the
2821 * segreg ptrs when only one is needed, but this instruction
2822 * *cannot* be that common, and this isn't too much work anyway.
2823 \*/
2824 DECODE_CLEAR_SEGOVR(m);
2825 }
2826
2827 /*opcode=0x8f*/
2828 static void i86op_pop_RM(PC_ENV *m)
2829 {
2830 uint16 mod,rl,rh;
2831 uint16 *destreg;
2832 uint16 destoffset;
2833 uint16 destval;
2834 FETCH_DECODE_MODRM(m,mod,rh,rl);
2835 if (rh != 0)
2836 {
2837 halt_sys(m);
2838 }
2839 switch (mod)
2840 {
2841 case 0:
2842 destoffset=decode_rm00_address(m,rl);
2843 destval = pop_word( m);
2844 store_data_word(m,destoffset,destval);
2845 break;
2846 case 1:
2847 destoffset=decode_rm01_address(m,rl);
2848 destval = pop_word(m);
2849 store_data_word(m,destoffset,destval);
2850 break;
2851 case 2:
2852 destoffset=decode_rm10_address(m,rl);
2853 destval = pop_word(m);
2854 store_data_word(m,destoffset,destval);
2855 break;
2856 case 3: /* register to register */
2857 destreg = DECODE_RM_WORD_REGISTER(m,rl);
2858 *destreg = pop_word(m);
2859 break;
2860 }
2861 DECODE_CLEAR_SEGOVR(m);
2862 }
2863
2864 /*opcode=0x90*/
2865 static void i86op_nop(PC_ENV *m)
2866 {
2867 DECODE_CLEAR_SEGOVR(m);
2868 }
2869
2870 /*opcode=0x91*/
2871 static void i86op_xchg_word_AX_CX(PC_ENV *m)
2872 {
2873 uint16 tmp;
2874 tmp = m->R_AX;
2875 m->R_AX = m->R_CX;
2876 m->R_CX = tmp;
2877 DECODE_CLEAR_SEGOVR(m);
2878 }
2879
2880 /*opcode=0x92*/
2881 static void i86op_xchg_word_AX_DX(PC_ENV *m)
2882 {
2883 uint16 tmp;
2884 tmp = m->R_AX;
2885 m->R_AX = m->R_DX;
2886 m->R_DX = tmp;
2887 DECODE_CLEAR_SEGOVR(m);
2888 }
2889
2890 /*opcode=0x93*/
2891 static void i86op_xchg_word_AX_BX(PC_ENV *m)
2892 {
2893 uint16 tmp;
2894 tmp = m->R_AX;
2895 m->R_AX = m->R_BX;
2896 m->R_BX = tmp;
2897 DECODE_CLEAR_SEGOVR(m);
2898 }
2899
2900 /*opcode=0x94*/
2901 static void i86op_xchg_word_AX_SP(PC_ENV *m)
2902 {
2903 uint16 tmp;
2904 tmp = m->R_AX;
2905 m->R_AX = m->R_SP;
2906 m->R_SP = tmp;
2907 DECODE_CLEAR_SEGOVR(m);
2908 }
2909
2910 /*opcode=0x95*/
2911 static void i86op_xchg_word_AX_BP(PC_ENV *m)
2912 {
2913 uint16 tmp;
2914 tmp = m->R_AX;
2915 m->R_AX = m->R_BP;
2916 m->R_BP = tmp;
2917 DECODE_CLEAR_SEGOVR(m);
2918 }
2919
2920 /*opcode=0x96*/
2921 static void i86op_xchg_word_AX_SI(PC_ENV *m)
2922 {
2923 uint16 tmp;
2924 tmp = m->R_AX;
2925 m->R_AX = m->R_SI;
2926 m->R_SI = tmp;
2927 DECODE_CLEAR_SEGOVR(m);
2928 }
2929
2930 /*opcode=0x97*/
2931 static void i86op_xchg_word_AX_DI(PC_ENV *m)
2932 {
2933 uint16 tmp;
2934 tmp = m->R_AX;
2935 m->R_AX = m->R_DI;
2936 m->R_DI = tmp;
2937 DECODE_CLEAR_SEGOVR(m);
2938 }
2939
2940 /*opcode=0x98*/
2941 static void i86op_cbw(PC_ENV *m)
2942 {
2943 if (m->R_AL & 0x80)
2944 {
2945 m->R_AH = 0xff;
2946 }
2947 else
2948 {
2949 m->R_AH = 0x0;
2950 }
2951 DECODE_CLEAR_SEGOVR(m);
2952 }
2953
2954 /*opcode=0x99*/
2955 static void i86op_cwd(PC_ENV *m)
2956 {
2957 if (m->R_AX & 0x8000)
2958 {
2959 m->R_DX = 0xffff;
2960 }
2961 else
2962 {
2963 m->R_DX = 0x0;
2964 }
2965 DECODE_CLEAR_SEGOVR(m);
2966 }
2967
2968 /*opcode=0x9a*/
2969 static void i86op_call_far_IMM(PC_ENV *m)
2970 {
2971 uint16 farseg,faroff;
2972 faroff = fetch_word_imm(m);
2973 farseg = fetch_word_imm(m);
2974 /* XXX
2975 HOOKED INTERRUPT VECTORS CALLING INTO OUR "BIOS"
2976 WILL CAUSE PROBLEMS UNLESS ALL INTERSEGMENT STUFF IS
2977 CHECKED FOR BIOS ACCESS. CHECK NEEDED HERE.
2978 FOR MOMENT, LET IT ALONE.
2979 */
2980 push_word(m,m->R_CS);
2981 m->R_CS = farseg;
2982 push_word(m,m->R_IP);
2983 m->R_IP = faroff;
2984 DECODE_CLEAR_SEGOVR(m);
2985 }
2986
2987 /*opcode=0x9b*/
2988 static void i86op_wait(PC_ENV *m)
2989 {
2990 /* NADA. */
2991 DECODE_CLEAR_SEGOVR(m);
2992 }
2993
2994 /*opcode=0x9c*/
2995 static void i86op_pushf_word(PC_ENV *m)
2996 {
2997 uint16 flags;
2998 flags = m->R_FLG;
2999 /* clear out *all* bits not representing flags */
3000 flags &= F_MSK;
3001 /* TURN ON CHARACTERISTIC BITS OF FLAG FOR 8088 */
3002 flags |= F_ALWAYS_ON;
3003 push_word(m,flags);
3004 DECODE_CLEAR_SEGOVR(m);
3005 }
3006
3007 /*opcode=0x9d*/
3008 static void i86op_popf_word(PC_ENV *m)
3009 {
3010 m->R_FLG = pop_word(m);
3011 DECODE_CLEAR_SEGOVR(m);
3012 }
3013
3014 /*opcode=0x9e*/
3015 static void i86op_sahf(PC_ENV *m)
3016 {
3017 /* clear the lower bits of the flag register */
3018 m->R_FLG &= 0xffffff00;
3019 /* or in the AH register into the flags register */
3020 m->R_FLG |= m->R_AH;
3021 DECODE_CLEAR_SEGOVR(m);
3022 }
3023
3024 /*opcode=0x9f*/
3025 static void i86op_lahf(PC_ENV *m)
3026 {
3027 m->R_AH = m->R_FLG & 0xff;
3028 /*undocumented TC++ behavior??? Nope. It's documented, but
3029 you have too look real hard to notice it. */
3030 m->R_AH |= 0x2;
3031 DECODE_CLEAR_SEGOVR(m);
3032 }
3033
3034 /*opcode=0xa0*/
3035 static void i86op_mov_AL_M_IMM(PC_ENV *m)
3036 {
3037 uint16 offset;
3038 uint8 destval;
3039 offset = fetch_word_imm(m);
3040 destval = fetch_data_byte(m,offset);
3041 m->R_AL = destval;
3042 DECODE_CLEAR_SEGOVR(m);
3043 }
3044
3045 /*opcode=0xa1*/
3046 static void i86op_mov_AX_M_IMM(PC_ENV *m)
3047 {
3048 uint16 offset;
3049 uint16 destval;
3050 offset = fetch_word_imm(m);
3051 destval = fetch_data_word(m,offset);
3052 m->R_AX = destval;
3053 DECODE_CLEAR_SEGOVR(m);
3054 }
3055
3056 /*opcode=0xa2*/
3057 static void i86op_mov_M_AL_IMM(PC_ENV *m)
3058 {
3059 uint16 offset;
3060 offset = fetch_word_imm(m);
3061 store_data_byte(m,offset,m->R_AL);
3062 DECODE_CLEAR_SEGOVR(m);
3063 }
3064
3065 /*opcode=0xa3*/
3066 static void i86op_mov_M_AX_IMM(PC_ENV *m)
3067 {
3068 uint16 offset;
3069 offset = fetch_word_imm(m);
3070 store_data_word(m,offset,m->R_AX);
3071 DECODE_CLEAR_SEGOVR(m);
3072 }
3073
3074 /* JHH CLEANED */
3075
3076 /*opcode=0xa4*/
3077 static void i86op_movs_byte(PC_ENV *m)
3078 {
3079 uint8 val;
3080 int inc;
3081 if (ACCESS_FLAG(m,F_DF)) /* down */
3082 inc = -1;
3083 else
3084 inc = 1;
3085 if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE))
3086 {
3087 /* dont care whether REPE or REPNE */
3088 /* move them until CX is ZERO. */
3089 while (m->R_CX != 0)
3090 {
3091 val = fetch_data_byte(m,m->R_SI);
3092 store_data_byte_abs(m,m->R_ES,m->R_DI,val);
3093 m->R_CX -= 1;
3094 m->R_SI += inc;
3095 m->R_DI += inc;
3096 }
3097 m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
3098 }
3099 else
3100 {
3101 val = fetch_data_byte(m,m->R_SI);
3102 store_data_byte_abs(m,m->R_ES,m->R_DI,val);
3103 m->R_SI += inc;
3104 m->R_DI += inc;
3105 }
3106 DECODE_CLEAR_SEGOVR(m);
3107 }
3108
3109 /*opcode=0xa5*/
3110 static void i86op_movs_word(PC_ENV *m)
3111 {
3112 int16 val;
3113 int inc;
3114 if (ACCESS_FLAG(m, F_DF)) /* down */
3115 inc = -2;
3116 else
3117 inc = 2;
3118 if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE))
3119 {
3120 /* dont care whether REPE or REPNE */
3121 /* move them until CX is ZERO. */
3122 while (m->R_CX != 0)
3123 {
3124 val = fetch_data_word(m,m->R_SI);
3125 store_data_word_abs(m,m->R_ES,m->R_DI,val);
3126 m->R_CX -= 1;
3127 m->R_SI += inc;
3128 m->R_DI += inc;
3129 }
3130 m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
3131 }
3132 else
3133 {
3134 val = fetch_data_word(m,m->R_SI);
3135 store_data_word_abs(m,m->R_ES,m->R_DI,val);
3136 m->R_SI += inc;
3137 m->R_DI += inc;
3138 }
3139 DECODE_CLEAR_SEGOVR(m);
3140 }
3141
3142 /*opcode=0xa6*/
3143 static void i86op_cmps_byte(PC_ENV *m)
3144 {
3145 int8 val1,val2;
3146 int inc;
3147 if (ACCESS_FLAG(m,F_DF)) /* down */
3148 inc = -1;
3149 else
3150 inc = 1;
3151 if (m->sysmode & SYSMODE_PREFIX_REPE)
3152 {
3153 /* REPE */
3154 /* move them until CX is ZERO. */
3155 while (m->R_CX != 0)
3156 {
3157 val1 = fetch_data_byte(m,m->R_SI);
3158 val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI);
3159 cmp_byte(m, val1,val2);
3160 m->R_CX -= 1;
3161 m->R_SI += inc;
3162 m->R_DI += inc;
3163 if (ACCESS_FLAG(m,F_ZF)==0) break;
3164 }
3165 m->sysmode &= ~SYSMODE_PREFIX_REPE;
3166 }
3167 else if (m->sysmode & SYSMODE_PREFIX_REPNE)
3168 {
3169 /* REPNE */
3170 /* move them until CX is ZERO. */
3171 while (m->R_CX != 0)
3172 {
3173 val1 = fetch_data_byte(m,m->R_SI);
3174 val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI);
3175 cmp_byte(m, val1,val2);
3176 m->R_CX -= 1;
3177 m->R_SI += inc;
3178 m->R_DI += inc;
3179 if (ACCESS_FLAG(m,F_ZF)) break; /* zero flag set means equal */
3180 }
3181 m->sysmode &= ~SYSMODE_PREFIX_REPNE;
3182 }
3183 else
3184 {
3185 val1 = fetch_data_byte(m,m->R_SI);
3186 val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI);
3187 cmp_byte(m, val1,val2);
3188 m->R_SI += inc;
3189 m->R_DI += inc;
3190 }
3191 DECODE_CLEAR_SEGOVR(m);
3192 }
3193
3194 /*opcode=0xa7*/
3195 static void i86op_cmps_word(PC_ENV *m)
3196 {
3197 int16 val1,val2;
3198 int inc;
3199 if (ACCESS_FLAG(m,F_DF)) /* down */
3200 inc = -2;
3201 else
3202 inc = 2;
3203 if (m->sysmode & SYSMODE_PREFIX_REPE)
3204 {
3205 /* REPE */
3206 /* move them until CX is ZERO. */
3207 while (m->R_CX != 0)
3208 {
3209 val1 = fetch_data_word(m,m->R_SI);
3210 val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI);
3211 cmp_word(m, val1,val2);
3212 m->R_CX -= 1;
3213 m->R_SI += inc;
3214 m->R_DI += inc;
3215 if (ACCESS_FLAG(m,F_ZF)==0) break;
3216 }
3217 m->sysmode &= ~SYSMODE_PREFIX_REPE;
3218 }
3219 else if (m->sysmode & SYSMODE_PREFIX_REPNE)
3220 {
3221 /* REPNE */
3222 /* move them until CX is ZERO. */
3223 while (m->R_CX != 0)
3224 {
3225 val1 = fetch_data_word(m,m->R_SI);
3226 val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI);
3227 cmp_word(m, val1,val2);
3228 m->R_CX -= 1;
3229 m->R_SI += inc;
3230 m->R_DI += inc;
3231 if (ACCESS_FLAG(m,F_ZF)) break; /* zero flag set means equal */
3232 }
3233 m->sysmode &= ~SYSMODE_PREFIX_REPNE;
3234 }
3235 else
3236 {
3237 val1 = fetch_data_word(m,m->R_SI);
3238 val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI);
3239 cmp_word(m, val1,val2);
3240 m->R_SI += inc;
3241 m->R_DI += inc;
3242 }
3243 DECODE_CLEAR_SEGOVR(m);
3244 }
3245
3246 /*opcode=0xa8*/
3247 static void i86op_test_AL_IMM(PC_ENV *m)
3248 {
3249 int imm;
3250 imm = fetch_byte_imm(m);
3251 test_byte(m, m->R_AL, imm);
3252 DECODE_CLEAR_SEGOVR(m);
3253 }
3254
3255 /*opcode=0xa9*/
3256 static void i86op_test_AX_IMM(PC_ENV *m)
3257 {
3258 int imm;
3259 imm = fetch_word_imm(m);
3260 test_word(m, m->R_AX, imm);
3261 DECODE_CLEAR_SEGOVR(m);
3262 }
3263
3264 /*opcode=0xaa*/
3265 static void i86op_stos_byte(PC_ENV *m)
3266 {
3267 int inc;
3268 if (ACCESS_FLAG(m, F_DF)) /* down */
3269 inc = -1;
3270 else
3271 inc = 1;
3272 if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE))
3273 {
3274 /* dont care whether REPE or REPNE */
3275 /* move them until CX is ZERO. */
3276 while (m->R_CX != 0)
3277 {
3278 store_data_byte_abs(m,m->R_ES,m->R_DI,m->R_AL);
3279 m->R_CX -= 1;
3280 m->R_DI += inc;
3281 }
3282 m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
3283 }
3284 else
3285 {
3286 store_data_byte_abs(m,m->R_ES,m->R_DI,m->R_AL);
3287 m->R_DI += inc;
3288 }
3289 DECODE_CLEAR_SEGOVR(m);
3290 }
3291
3292 /*opcode=0xab*/
3293 static void i86op_stos_word(PC_ENV *m)
3294 {
3295 int inc;
3296 if (ACCESS_FLAG(m, F_DF)) /* down */
3297 inc = -2;
3298 else
3299 inc = 2;
3300 if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE))
3301 {
3302 /* dont care whether REPE or REPNE */
3303 /* move them until CX is ZERO. */
3304 while (m->R_CX != 0)
3305 {
3306 store_data_word_abs(m,m->R_ES,m->R_DI,m->R_AX);
3307 m->R_CX -= 1;
3308 m->R_DI += inc;
3309 }
3310 m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
3311 }
3312 else
3313 {
3314 store_data_word_abs(m,m->R_ES,m->R_DI,m->R_AX);
3315 m->R_DI += inc;
3316 }
3317 DECODE_CLEAR_SEGOVR(m);
3318 }
3319
3320 /*opcode=0xac*/
3321 static void i86op_lods_byte(PC_ENV *m)
3322 {
3323 int inc;
3324 if (ACCESS_FLAG(m,F_DF)) /* down */
3325 inc = -1;
3326 else
3327 inc = 1;
3328 if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE))
3329 {
3330 /* dont care whether REPE or REPNE */
3331 /* move them until CX is ZERO. */
3332 while (m->R_CX != 0)
3333 {
3334 m->R_AL = fetch_data_byte(m,m->R_SI);
3335 m->R_CX -= 1;
3336 m->R_SI += inc;
3337 }
3338 m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
3339 }
3340 else
3341 {
3342 m->R_AL = fetch_data_byte(m,m->R_SI);
3343 m->R_SI += inc;
3344 }
3345 DECODE_CLEAR_SEGOVR(m);
3346 }
3347
3348 /*opcode=0xad*/
3349 static void i86op_lods_word(PC_ENV *m)
3350 {
3351 int inc;
3352 if (ACCESS_FLAG(m,F_DF)) /* down */
3353 inc = -2;
3354 else
3355 inc = 2;
3356 if (m->sysmode & (SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE))
3357 {
3358 /* dont care whether REPE or REPNE */
3359 /* move them until CX is ZERO. */
3360 while (m->R_CX != 0)
3361 {
3362 m->R_AX = fetch_data_word(m,m->R_SI);
3363 m->R_CX -= 1;
3364 m->R_SI += inc;
3365 }
3366 m->sysmode &= ~(SYSMODE_PREFIX_REPE | SYSMODE_PREFIX_REPNE);
3367 }
3368 else
3369 {
3370 m->R_AX = fetch_data_word(m,m->R_SI);
3371 m->R_SI += inc;
3372 }
3373 DECODE_CLEAR_SEGOVR(m);
3374 }
3375
3376 /*opcode=0xae*/
3377 static void i86op_scas_byte(PC_ENV *m)
3378 {
3379 int8 val2;
3380 int inc;
3381 if (ACCESS_FLAG(m,F_DF)) /* down */
3382 inc = -1;
3383 else
3384 inc = 1;
3385 if (m->sysmode & SYSMODE_PREFIX_REPE)
3386 {
3387 /* REPE */
3388 /* move them until CX is ZERO. */
3389 while (m->R_CX != 0)
3390 {
3391 val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI);
3392 cmp_byte(m, m->R_AL,val2);
3393 m->R_CX -= 1;
3394 m->R_DI += inc;
3395 if (ACCESS_FLAG(m,F_ZF)==0) break;
3396 }
3397 m->sysmode &= ~SYSMODE_PREFIX_REPE;
3398 }
3399 else if (m->sysmode & SYSMODE_PREFIX_REPNE)
3400 {
3401 /* REPNE */
3402 /* move them until CX is ZERO. */
3403 while (m->R_CX != 0)
3404 {
3405 val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI);
3406 cmp_byte(m, m->R_AL,val2);
3407 m->R_CX -= 1;
3408 m->R_DI += inc;
3409 if (ACCESS_FLAG(m,F_ZF)) break; /* zero flag set means equal */
3410 }
3411 m->sysmode &= ~SYSMODE_PREFIX_REPNE;
3412 }
3413 else
3414 {
3415 val2 = fetch_data_byte_abs(m,m->R_ES,m->R_DI);
3416 cmp_byte(m, m->R_AL,val2);
3417 m->R_DI += inc;
3418 }
3419 DECODE_CLEAR_SEGOVR(m);
3420 }
3421
3422 /*opcode=0xaf*/
3423 static void i86op_scas_word(PC_ENV *m)
3424 {
3425 int16 val2;
3426 int inc;
3427 if (ACCESS_FLAG(m, F_DF)) /* down */
3428 inc = -2;
3429 else
3430 inc = 2;
3431 if (m->sysmode & SYSMODE_PREFIX_REPE)
3432 {
3433 /* REPE */
3434 /* move them until CX is ZERO. */
3435 while (m->R_CX != 0)
3436 {
3437 val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI);
3438 cmp_word(m,m->R_AX,val2);
3439 m->R_CX -= 1;
3440 m->R_DI += inc;
3441 if (ACCESS_FLAG(m,F_ZF)==0) break;
3442 }
3443 m->sysmode &= ~SYSMODE_PREFIX_REPE;
3444 }
3445 else if (m->sysmode & SYSMODE_PREFIX_REPNE)
3446 {
3447 /* REPNE */
3448 /* move them until CX is ZERO. */
3449 while (m->R_CX != 0)
3450 {
3451 val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI);
3452 cmp_word(m, m->R_AX,val2);
3453 m->R_CX -= 1;
3454 m->R_DI += inc;
3455 if (ACCESS_FLAG(m,F_ZF)) break; /* zero flag set means equal */
3456 }
3457 m->sysmode &= ~SYSMODE_PREFIX_REPNE;
3458 }
3459 else
3460 {
3461 val2 = fetch_data_word_abs(m,m->R_ES,m->R_DI);
3462 cmp_word(m, m->R_AX,val2);
3463 m->R_DI += inc;
3464 }
3465 DECODE_CLEAR_SEGOVR(m);
3466 }
3467
3468 /*opcode=0xb0*/
3469 static void i86op_mov_byte_AL_IMM(PC_ENV *m)
3470 {
3471 uint8 imm;
3472 imm = fetch_byte_imm(m);
3473 m->R_AL = imm;
3474 DECODE_CLEAR_SEGOVR(m);
3475 }
3476
3477 /*opcode=0xb1*/
3478 static void i86op_mov_byte_CL_IMM(PC_ENV *m)
3479 {
3480 uint8 imm;
3481 imm = fetch_byte_imm(m);
3482 m->R_CL = imm;
3483 DECODE_CLEAR_SEGOVR(m);
3484 }
3485
3486 /*opcode=0xb2*/
3487 static void i86op_mov_byte_DL_IMM(PC_ENV *m)
3488 {
3489 uint8 imm;
3490 imm = fetch_byte_imm(m);
3491 m->R_DL = imm;
3492 DECODE_CLEAR_SEGOVR(m);
3493 }
3494
3495 /*opcode=0xb3*/
3496 static void i86op_mov_byte_BL_IMM(PC_ENV *m)
3497 {
3498 uint8 imm;
3499 imm = fetch_byte_imm(m);
3500 m->R_BL = imm;
3501 DECODE_CLEAR_SEGOVR(m);
3502 }
3503
3504 /*opcode=0xb4*/
3505 static void i86op_mov_byte_AH_IMM(PC_ENV *m)
3506 {
3507 uint8 imm;
3508 imm = fetch_byte_imm(m);
3509 m->R_AH = imm;
3510 DECODE_CLEAR_SEGOVR(m);
3511 }
3512
3513 /*opcode=0xb5*/
3514 static void i86op_mov_byte_CH_IMM(PC_ENV *m)
3515 {
3516 uint8 imm;
3517 imm = fetch_byte_imm(m);
3518 m->R_CH = imm;
3519 DECODE_CLEAR_SEGOVR(m);
3520 }
3521
3522 /*opcode=0xb6*/
3523 static void i86op_mov_byte_DH_IMM(PC_ENV *m)
3524 {
3525 uint8 imm;
3526 imm = fetch_byte_imm(m);
3527 m->R_DH = imm;
3528 DECODE_CLEAR_SEGOVR(m);
3529 }
3530
3531 /*opcode=0xb7*/
3532 static void i86op_mov_byte_BH_IMM(PC_ENV *m)
3533 {
3534 uint8 imm;
3535 imm = fetch_byte_imm(m);
3536 m->R_BH = imm;
3537 DECODE_CLEAR_SEGOVR(m);
3538 }
3539
3540 /*opcode=0xb8*/
3541 static void i86op_mov_word_AX_IMM(PC_ENV *m)
3542 {
3543 uint16 imm;
3544 imm = fetch_word_imm(m);
3545 m->R_AX = imm;
3546 DECODE_CLEAR_SEGOVR(m);
3547 }
3548
3549 /*opcode=0xb9*/
3550 static void i86op_mov_word_CX_IMM(PC_ENV *m)
3551 {
3552 uint16 imm;
3553 imm = fetch_word_imm(m);
3554 m->R_CX = imm;
3555 DECODE_CLEAR_SEGOVR(m);
3556 }
3557
3558 /*opcode=0xba*/
3559 static void i86op_mov_word_DX_IMM(PC_ENV *m)
3560 {
3561 uint16 imm;
3562 imm = fetch_word_imm(m);
3563 m->R_DX = imm;
3564 DECODE_CLEAR_SEGOVR(m);
3565 }
3566
3567 /*opcode=0xbb*/
3568 static void i86op_mov_word_BX_IMM(PC_ENV *m)
3569 {
3570 uint16 imm;
3571 imm = fetch_word_imm(m);
3572 m->R_BX = imm;
3573 DECODE_CLEAR_SEGOVR(m);
3574 }
3575
3576 /*opcode=0xbc*/
3577 static void i86op_mov_word_SP_IMM(PC_ENV *m)
3578 {
3579 uint16 imm;
3580 imm = fetch_word_imm(m);
3581 m->R_SP = imm;
3582 DECODE_CLEAR_SEGOVR(m);
3583 }
3584
3585 /*opcode=0xbd*/
3586 static void i86op_mov_word_BP_IMM(PC_ENV *m)
3587 {
3588 uint16 imm;
3589 imm = fetch_word_imm(m);
3590 m->R_BP = imm;
3591 DECODE_CLEAR_SEGOVR(m);
3592 }
3593
3594 /*opcode=0xbe*/
3595 static void i86op_mov_word_SI_IMM(PC_ENV *m)
3596 {
3597 uint16 imm;
3598 imm = fetch_word_imm(m);
3599 m->R_SI = imm;
3600 DECODE_CLEAR_SEGOVR(m);
3601 }
3602
3603 /*opcode=0xbf*/
3604 static void i86op_mov_word_DI_IMM(PC_ENV *m)
3605 {
3606 uint16 imm;
3607 imm = fetch_word_imm(m);
3608 m->R_DI = imm;
3609 DECODE_CLEAR_SEGOVR(m);
3610 }
3611
3612 /* c0 === ILLEGAL OPERAND */
3613 /* c1 === ILLEGAL OPERAND */
3614
3615 /*opcode=0xc2*/
3616 static void i86op_ret_near_IMM(PC_ENV *m)
3617 {
3618 uint16 imm;
3619 imm = fetch_word_imm(m);
3620 m->R_IP = pop_word(m);
3621 m->R_SP += imm;
3622 DECODE_CLEAR_SEGOVR(m);
3623 }
3624
3625 /*opcode=0xc3*/
3626 static void i86op_ret_near(PC_ENV *m)
3627 {
3628 m->R_IP = pop_word(m);
3629 DECODE_CLEAR_SEGOVR(m);
3630 }
3631
3632 /*opcode=0xc4*/
3633 static void i86op_les_R_IMM(PC_ENV *m)
3634 {
3635 uint16 mod,rh,rl;
3636 uint16 *dstreg;
3637 uint16 srcoffset;
3638 FETCH_DECODE_MODRM(m,mod,rh,rl);
3639 switch (mod)
3640 {
3641 case 0:
3642 dstreg = DECODE_RM_WORD_REGISTER(m,rh);
3643 srcoffset=decode_rm00_address(m,rl);
3644 *dstreg = fetch_data_word(m,srcoffset);
3645 m->R_ES = fetch_data_word(m,srcoffset+2);
3646 break;
3647 case 1:
3648 dstreg = DECODE_RM_WORD_REGISTER(m,rh);
3649 srcoffset=decode_rm01_address(m,rl);
3650 *dstreg = fetch_data_word(m,srcoffset);
3651 m->R_ES = fetch_data_word(m,srcoffset+2);
3652 break;
3653 case 2:
3654 dstreg = DECODE_RM_WORD_REGISTER(m,rh);
3655 srcoffset=decode_rm10_address(m,rl);
3656 *dstreg = fetch_data_word(m,srcoffset);
3657 m->R_ES = fetch_data_word(m,srcoffset+2);
3658 break;
3659 case 3: /* register to register */
3660 /* UNDEFINED! */
3661 ;
3662 }
3663 DECODE_CLEAR_SEGOVR(m);
3664 }
3665
3666 /*opcode=0xc5*/
3667 static void i86op_lds_R_IMM(PC_ENV *m)
3668 {
3669 uint16 mod,rh,rl;
3670 uint16 *dstreg;
3671 uint16 srcoffset;
3672 FETCH_DECODE_MODRM(m,mod,rh,rl);
3673 switch (mod)
3674 {
3675 case 0:
3676 dstreg = DECODE_RM_WORD_REGISTER(m,rh);
3677 srcoffset=decode_rm00_address(m,rl);
3678 *dstreg = fetch_data_word(m,srcoffset);
3679 m->R_DS = fetch_data_word(m,srcoffset+2);
3680 break;
3681 case 1:
3682 dstreg = DECODE_RM_WORD_REGISTER(m,rh);
3683 srcoffset=decode_rm01_address(m,rl);
3684 *dstreg = fetch_data_word(m,srcoffset);
3685 m->R_DS = fetch_data_word(m,srcoffset+2);
3686 break;
3687 case 2:
3688 dstreg = DECODE_RM_WORD_REGISTER(m,rh);
3689 srcoffset=decode_rm10_address(m,rl);
3690 *dstreg = fetch_data_word(m,srcoffset);
3691 m->R_DS = fetch_data_word(m,srcoffset+2);
3692 break;
3693 case 3: /* register to register */
3694 /* UNDEFINED! */
3695 ;
3696 }
3697 DECODE_CLEAR_SEGOVR(m);
3698 }
3699
3700 /*opcode=0xc6*/
3701 static void i86op_mov_byte_RM_IMM(PC_ENV *m)
3702 {
3703 uint16 mod,rl,rh;
3704 uint8 *destreg;
3705 uint16 destoffset;
3706 uint8 imm;
3707 FETCH_DECODE_MODRM(m,mod,rh,rl);
3708 if (rh != 0)
3709 {
3710 halt_sys(m);
3711 }
3712 switch (mod)
3713 {
3714 case 0:
3715 destoffset=decode_rm00_address(m,rl);
3716 imm = fetch_byte_imm(m);
3717 store_data_byte(m,destoffset,imm);
3718 break;
3719 case 1:
3720 destoffset=decode_rm01_address(m,rl);
3721 imm = fetch_byte_imm(m);
3722 store_data_byte(m,destoffset,imm);
3723 break;
3724 case 2:
3725 destoffset=decode_rm10_address(m,rl);
3726 imm = fetch_byte_imm(m);
3727 store_data_byte(m,destoffset,imm);
3728 break;
3729 case 3: /* register to register */
3730 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
3731 imm = fetch_byte_imm(m);
3732 *destreg = imm;
3733 break;
3734 }
3735 DECODE_CLEAR_SEGOVR(m);
3736 }
3737
3738 /*opcode=0xc7*/
3739 static void i86op_mov_word_RM_IMM(PC_ENV *m)
3740 {
3741 uint16 mod,rl,rh;
3742 uint16 *destreg;
3743 uint16 destoffset;
3744 uint16 imm;
3745 FETCH_DECODE_MODRM(m,mod,rh,rl);
3746 if (rh != 0)
3747 {
3748 halt_sys(m);
3749 }
3750 switch (mod)
3751 {
3752 case 0:
3753 destoffset=decode_rm00_address(m,rl);
3754 imm = fetch_word_imm(m);
3755 store_data_word(m,destoffset,imm);
3756 break;
3757 case 1:
3758 destoffset=decode_rm01_address(m,rl);
3759 imm = fetch_word_imm(m);
3760 store_data_word(m,destoffset,imm);
3761 break;
3762 case 2:
3763 destoffset=decode_rm10_address(m,rl);
3764 imm = fetch_word_imm(m);
3765 store_data_word(m,destoffset,imm);
3766 break;
3767 case 3: /* register to register */
3768 destreg = DECODE_RM_WORD_REGISTER(m,rl);
3769 imm = fetch_word_imm(m);
3770 *destreg = imm;
3771 break;
3772 }
3773 DECODE_CLEAR_SEGOVR(m);
3774 }
3775
3776 /*opcode=0xc8 ILLEGAL OP*/
3777 /*opcode=0xc9 ILLEGAL OP*/
3778
3779 /*opcode=0xca*/
3780 static void i86op_ret_far_IMM(PC_ENV *m)
3781 {
3782 uint16 imm;
3783 imm = fetch_word_imm(m);
3784 m->R_IP = pop_word(m);
3785 m->R_CS = pop_word(m);
3786 m->R_SP += imm;
3787 DECODE_CLEAR_SEGOVR(m);
3788 }
3789
3790 /*opcode=0xcb*/
3791 static void i86op_ret_far(PC_ENV *m)
3792 {
3793 m->R_IP = pop_word(m);
3794 m->R_CS = pop_word(m);
3795 DECODE_CLEAR_SEGOVR(m);
3796 }
3797
3798 /* opcode=0xcc*/
3799 static void i86op_int3(PC_ENV *m)
3800 {
3801 uint16 tmp;
3802 tmp = (uint16) mem_access_word(m, 3 * 4);
3803 /* access the segment register */
3804 {
3805 tmp = m->R_FLG;
3806 push_word(m, tmp);
3807 CLEAR_FLAG(m, F_IF);
3808 CLEAR_FLAG(m, F_TF);
3809 /* [JCE] If we're interrupting between a segment override (or REP override)
3810 * and the following instruction, decrease IP to get back to the prefix */
3811 if (m->sysmode & (SYSMODE_SEGMASK |
3812 SYSMODE_PREFIX_REPE |
3813 SYSMODE_PREFIX_REPNE))
3814 {
3815 --m->R_IP;
3816 }
3817 push_word(m, m->R_CS);
3818 push_word(m, m->R_IP);
3819 /* [JCE] CS and IP were the wrong way round... */
3820 tmp = mem_access_word(m, 3 * 4);
3821 m->R_IP = tmp;
3822 tmp = mem_access_word(m, 3 * 4 + 2);
3823 m->R_CS = tmp;
3824 }
3825 DECODE_CLEAR_SEGOVR(m);
3826 }
3827
3828 /* opcode=0xcd*/
3829 static void i86op_int_IMM(PC_ENV *m)
3830 {
3831 uint16 tmp;
3832 uint8 intnum;
3833 intnum = fetch_byte_imm(m);
3834 tmp = mem_access_word(m, intnum * 4);
3835 {
3836 tmp = m->R_FLG;
3837 push_word(m, tmp);
3838 CLEAR_FLAG(m, F_IF);
3839 CLEAR_FLAG(m, F_TF);
3840 /* [JCE] If we're interrupting between a segment override (or REP override)
3841 * and the following instruction, decrease IP to get back to the prefix */
3842 if (m->sysmode & (SYSMODE_SEGMASK |
3843 SYSMODE_PREFIX_REPE |
3844 SYSMODE_PREFIX_REPNE))
3845 {
3846 --m->R_IP;
3847 }
3848 push_word(m, m->R_CS);
3849 push_word(m, m->R_IP);
3850 /* [JCE] CS and IP were the wrong way round... */
3851 tmp = mem_access_word(m, intnum * 4);
3852 m->R_IP = tmp;
3853 tmp = mem_access_word(m, intnum * 4 + 2);
3854 m->R_CS = tmp;
3855 }
3856 DECODE_CLEAR_SEGOVR(m);
3857 }
3858
3859 /* opcode=0xce*/
3860 static void i86op_into(PC_ENV *m)
3861 {
3862 uint16 tmp;
3863 if (ACCESS_FLAG(m,F_OF))
3864 {
3865 tmp = mem_access_word(m, 4 * 4);
3866 {
3867 tmp = m->R_FLG;
3868 push_word(m, tmp);
3869 CLEAR_FLAG(m, F_IF);
3870 CLEAR_FLAG(m, F_TF);
3871 /* [JCE] If we're interrupting between a segment override (or REP override)
3872 * and the following instruction, decrease IP to get back to the prefix */
3873 if (m->sysmode & (SYSMODE_SEGMASK |
3874 SYSMODE_PREFIX_REPE |
3875 SYSMODE_PREFIX_REPNE))
3876 {
3877 --m->R_IP;
3878 }
3879 push_word(m, m->R_CS);
3880 push_word(m, m->R_IP);
3881 /* [JCE] CS and IP were the wrong way round... */
3882 tmp = mem_access_word(m, 4 * 4);
3883 m->R_IP = tmp;
3884 tmp = mem_access_word(m, 4 * 4 + 2);
3885 m->R_CS = tmp;
3886 }
3887 }
3888 DECODE_CLEAR_SEGOVR(m);
3889 }
3890
3891 /* opcode=0xcf*/
3892 static void i86op_iret(PC_ENV *m)
3893 {
3894 m->R_IP = pop_word(m);
3895 m->R_CS = pop_word(m);
3896 m->R_FLG = pop_word(m);
3897 DECODE_CLEAR_SEGOVR(m);
3898 }
3899
3900 static uint8 (*opcD0_byte_operation[])(PC_ENV *m,uint8 d, uint8 s) =
3901 /* used by opcodes d0 and d2. */
3902 {
3903 rol_byte,
3904 ror_byte,
3905 rcl_byte,
3906 rcr_byte,
3907 shl_byte,
3908 shr_byte,
3909 shl_byte, /* sal_byte === shl_byte by definition */
3910 sar_byte,
3911 };
3912
3913 /* opcode=0xd0*/
3914 static void i86op_opcD0_byte_RM_1(PC_ENV *m)
3915 {
3916 uint16 mod,rl,rh;
3917 uint8 *destreg;
3918 uint16 destoffset;
3919 uint8 destval;
3920 /* Yet another weirdo special case instruction format. Part of the
3921 opcode held below in "RH". Doubly nested case would
3922 result, except that the decoded instruction
3923 */
3924 FETCH_DECODE_MODRM(m,mod,rh,rl);
3925 /* know operation, decode the mod byte to find the addressing
3926 mode. */
3927 switch (mod)
3928 {
3929 case 0:
3930 destoffset=decode_rm00_address(m,rl);
3931 destval = fetch_data_byte(m,destoffset);
3932 destval = (*opcD0_byte_operation[rh])(m, destval,1);
3933 store_data_byte(m,destoffset,destval);
3934 break;
3935 case 1:
3936 destoffset=decode_rm01_address(m,rl);
3937 destval = fetch_data_byte(m,destoffset);
3938 destval = (*opcD0_byte_operation[rh])(m, destval, 1);
3939 store_data_byte(m,destoffset,destval);
3940 break;
3941 case 2:
3942 destoffset=decode_rm10_address(m,rl);
3943 destval = fetch_data_byte(m,destoffset);
3944 destval = (*opcD0_byte_operation[rh])(m, destval, 1);
3945 store_data_byte(m,destoffset,destval);
3946 break;
3947 case 3: /* register to register */
3948 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
3949 destval = (*opcD0_byte_operation[rh])(m, *destreg, 1);
3950 *destreg = destval;
3951 break;
3952 }
3953 DECODE_CLEAR_SEGOVR(m);
3954 }
3955
3956 static uint16 (*opcD1_word_operation[])(PC_ENV *m,uint16 s,uint16 d) =
3957 /* used by opcodes d1 and d3. */
3958 { rol_word,
3959 ror_word,
3960 rcl_word,
3961 rcr_word,
3962 shl_word,
3963 shr_word,
3964 shl_word, /* sal_byte === shl_byte by definition */
3965 sar_word,
3966 };
3967
3968 /* opcode=0xd1*/
3969 static void i86op_opcD1_word_RM_1(PC_ENV *m)
3970 {
3971 uint16 mod,rl,rh;
3972 uint16 *destreg;
3973 uint16 destoffset;
3974 uint16 destval;
3975 /* Yet another weirdo special case instruction format. Part of the
3976 opcode held below in "RH". Doubly nested case would
3977 result, except that the decoded instruction
3978 */
3979 FETCH_DECODE_MODRM(m,mod,rh,rl);
3980 /* know operation, decode the mod byte to find the addressing
3981 mode. */
3982 switch (mod)
3983 {
3984 case 0:
3985 destoffset=decode_rm00_address(m,rl);
3986 destval = fetch_data_word(m,destoffset);
3987 destval = (*opcD1_word_operation[rh])(m, destval,1);
3988 store_data_word(m,destoffset,destval);
3989 break;
3990 case 1:
3991 destoffset=decode_rm01_address(m,rl);
3992 destval = fetch_data_word(m,destoffset);
3993 destval = (*opcD1_word_operation[rh])(m, destval, 1);
3994 store_data_word(m,destoffset,destval);
3995 break;
3996 case 2:
3997 destoffset=decode_rm10_address(m,rl);
3998 destval = fetch_data_word(m,destoffset);
3999 destval = (*opcD1_word_operation[rh])(m, destval, 1);
4000 store_data_word(m,destoffset,destval);
4001 break;
4002 case 3: /* register to register */
4003 destreg = DECODE_RM_WORD_REGISTER(m,rl);
4004 destval = (*opcD1_word_operation[rh])(m, *destreg, 1);
4005 *destreg = destval;
4006 break;
4007 }
4008 DECODE_CLEAR_SEGOVR(m);
4009 }
4010
4011 /* opcode=0xd2*/
4012 static void i86op_opcD2_byte_RM_CL(PC_ENV *m)
4013 {
4014 uint16 mod,rl,rh;
4015 uint8 *destreg;
4016 uint16 destoffset;
4017 uint8 destval;
4018 uint8 amt;
4019 /* Yet another weirdo special case instruction format. Part of the
4020 opcode held below in "RH". Doubly nested case would
4021 result, except that the decoded instruction
4022 */
4023 FETCH_DECODE_MODRM(m,mod,rh,rl);
4024 amt = m->R_CL;
4025 /* know operation, decode the mod byte to find the addressing
4026 mode. */
4027 switch (mod)
4028 {
4029 case 0:
4030 destoffset=decode_rm00_address(m,rl);
4031 destval = fetch_data_byte(m,destoffset);
4032 destval = (*opcD0_byte_operation[rh])(m, destval,amt);
4033 store_data_byte(m,destoffset,destval);
4034 break;
4035 case 1:
4036 destoffset=decode_rm01_address(m,rl);
4037 destval = fetch_data_byte(m,destoffset);
4038 destval = (*opcD0_byte_operation[rh])(m, destval, amt);
4039 store_data_byte(m,destoffset,destval);
4040 break;
4041 case 2:
4042 destoffset=decode_rm10_address(m,rl);
4043 destval = fetch_data_byte(m,destoffset);
4044 destval = (*opcD0_byte_operation[rh])(m, destval, amt);
4045 store_data_byte(m,destoffset,destval);
4046 break;
4047 case 3: /* register to register */
4048 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
4049 destval = (*opcD0_byte_operation[rh])(m, *destreg, amt);
4050 *destreg = destval;
4051 break;
4052 }
4053 DECODE_CLEAR_SEGOVR(m);
4054 }
4055
4056 /* opcode=0xd3*/
4057 static void i86op_opcD3_word_RM_CL(PC_ENV *m)
4058 {
4059 uint16 mod,rl,rh;
4060 uint16 *destreg;
4061 uint16 destoffset;
4062 uint16 destval;
4063 uint8 amt;
4064 /* Yet another weirdo special case instruction format. Part of the
4065 opcode held below in "RH". Doubly nested case would
4066 result, except that the decoded instruction
4067 */
4068 FETCH_DECODE_MODRM(m,mod,rh,rl);
4069 amt = m->R_CL;
4070 /* know operation, decode the mod byte to find the addressing
4071 mode. */
4072 switch (mod)
4073 {
4074 case 0:
4075 destoffset=decode_rm00_address(m,rl);
4076 destval = fetch_data_word(m,destoffset);
4077 destval = (*opcD1_word_operation[rh])(m, destval, amt);
4078 store_data_word(m,destoffset,destval);
4079 break;
4080 case 1:
4081 destoffset=decode_rm01_address(m,rl);
4082 destval = fetch_data_word(m,destoffset);
4083 destval = (*opcD1_word_operation[rh])(m, destval, amt);
4084 store_data_word(m,destoffset,destval);
4085 break;
4086 case 2:
4087 destoffset=decode_rm10_address(m,rl);
4088 destval = fetch_data_word(m,destoffset);
4089 destval = (*opcD1_word_operation[rh])(m, destval, amt);
4090 store_data_word(m,destoffset,destval);
4091 break;
4092 case 3: /* register to register */
4093 destreg = DECODE_RM_WORD_REGISTER(m,rl);
4094 *destreg = (*opcD1_word_operation[rh])(m, *destreg, amt);
4095 break;
4096 }
4097 DECODE_CLEAR_SEGOVR(m);
4098 }
4099
4100 static void sys_fatal(int error, char *fmt, ...)
4101 {
4102 va_list p;
4103 va_start(p, fmt);
4104 fprintf(stderr, "Fatal error: ");
4105 if (error != 0)
4106 {
4107 fprintf(stderr, "<%d>",error);
4108 fprintf(stderr,"%s",strerror(error));
4109 }
4110 vfprintf(stderr, fmt, p);
4111 va_end(p);
4112 fprintf(stderr, NLP "Exiting..." NLP);
4113 exit(1);
4114 }
4115
4116 /* opcode=0xd4*/
4117 static void i86op_aam(PC_ENV *m)
4118 { uint8 a;
4119 a = fetch_byte_imm(m); /* this is a stupid encoding. */
4120 if (a != 10) sys_fatal(0,"error decoding aam" NLP);
4121 /* note the type change here --- returning AL and AH in AX. */
4122 m->R_AX = aam_word(m,m->R_AL);
4123 DECODE_CLEAR_SEGOVR(m);
4124 }
4125
4126 /* opcode=0xd5*/
4127 static void i86op_aad(PC_ENV *m)
4128 { uint8 a;
4129 a = fetch_byte_imm(m);
4130 m->R_AX = aad_word(m,m->R_AX);
4131 DECODE_CLEAR_SEGOVR(m);
4132 }
4133
4134 /* opcode=0xd6 ILLEGAL OPCODE */
4135
4136 /* opcode=0xd7 */
4137 static void i86op_xlat(PC_ENV *m)
4138 {
4139 uint16 addr;
4140 addr = m->R_BX + (uint8)m->R_AL;
4141 m->R_AL = fetch_data_byte(m,addr);
4142 DECODE_CLEAR_SEGOVR(m);
4143 }
4144
4145 /*opcode=0xe0*/
4146 static void i86op_loopne(PC_ENV *m)
4147 {
4148 int16 ip;
4149 ip = (int8)fetch_byte_imm(m);
4150 ip += (int16)m->R_IP;
4151 m->R_CX -= 1;
4152 if (m->R_CX != 0 && !ACCESS_FLAG(m,F_ZF)) /* CX != 0 and !ZF */
4153 m->R_IP = ip;
4154 DECODE_CLEAR_SEGOVR(m);
4155 }
4156
4157 /*opcode=0xe1*/
4158 static void i86op_loope(PC_ENV *m)
4159 {
4160 int16 ip;
4161 ip = (int8)fetch_byte_imm(m);
4162 ip += (int16)m->R_IP;
4163 m->R_CX -= 1;
4164 if (m->R_CX != 0 && ACCESS_FLAG(m,F_ZF)) /* CX != 0 and ZF */
4165 m->R_IP = ip;
4166 DECODE_CLEAR_SEGOVR(m);
4167 }
4168
4169 /*opcode=0xe2*/
4170 static void i86op_loop(PC_ENV *m)
4171 {
4172 int16 ip;
4173 ip = (int8)fetch_byte_imm(m);
4174 ip += (int16)m->R_IP;
4175 m->R_CX -= 1;
4176 if (m->R_CX != 0)
4177 m->R_IP = ip;
4178 DECODE_CLEAR_SEGOVR(m);
4179 }
4180
4181 /*opcode=0xe3*/
4182 static void i86op_jcxz(PC_ENV *m)
4183 {
4184 int16 offset,target;
4185 /* jump to byte offset if overflow flag is set */
4186 offset = (int8)fetch_byte_imm(m); /* sign extended ??? */
4187 target = (int16)m->R_IP + offset;
4188 if (m->R_CX == 0)
4189 m->R_IP = target;
4190 DECODE_CLEAR_SEGOVR(m);
4191 }
4192
4193 /*opcode=0xe4*/
4194 static void i86op_in_byte_AL_IMM(PC_ENV *m)
4195 {
4196 uint8 port;
4197 port = (uint8)fetch_byte_imm(m);
4198 m->R_AL = in(port);
4199 DECODE_CLEAR_SEGOVR(m);
4200 }
4201
4202 /*opcode=0xe5*/
4203 static void i86op_in_word_AX_IMM(PC_ENV *m)
4204 {
4205 uint8 port;
4206 port = (uint8)fetch_byte_imm(m);
4207 m->R_AX = in(port);
4208 DECODE_CLEAR_SEGOVR(m);
4209 }
4210
4211 /*opcode=0xe6*/
4212 static void i86op_out_byte_IMM_AL(PC_ENV *m)
4213 {
4214 uint8 port;
4215 port = (uint8)fetch_byte_imm(m);
4216 out(port, m->R_AL);
4217 DECODE_CLEAR_SEGOVR(m);
4218 }
4219
4220 /*opcode=0xe7*/
4221 static void i86op_out_word_IMM_AX(PC_ENV *m)
4222 {
4223 uint8 port;
4224 port = (uint8)fetch_byte_imm(m);
4225 out(port, m->R_AX);
4226 DECODE_CLEAR_SEGOVR(m);
4227 }
4228
4229 /*opcode=0xe8*/
4230 static void i86op_call_near_IMM(PC_ENV *m)
4231 {
4232 int16 ip;
4233 /* weird. Thought this was a signed disp! */
4234 ip = (int16)fetch_word_imm(m);
4235 ip += (int16)m->R_IP; /* CHECK SIGN */
4236 push_word(m,m->R_IP);
4237 m->R_IP = ip;
4238 DECODE_CLEAR_SEGOVR(m);
4239 }
4240
4241 /*opcode=0xe9*/
4242 static void i86op_jump_near_IMM(PC_ENV *m)
4243 {
4244 int ip;
4245 /* weird. Thought this was a signed disp too! */
4246 ip = (int16)fetch_word_imm(m);
4247 ip += (int16)m->R_IP; /* CHECK SIGN */
4248 m->R_IP = ip;
4249 DECODE_CLEAR_SEGOVR(m);
4250 }
4251
4252 /*opcode=0xea*/
4253 static void i86op_jump_far_IMM(PC_ENV *m)
4254 {
4255 uint16 cs,ip;
4256 ip = fetch_word_imm(m);
4257 cs = fetch_word_imm(m);
4258 m->R_IP = ip;
4259 m->R_CS = cs;
4260 DECODE_CLEAR_SEGOVR(m);
4261 }
4262
4263 /*opcode=0xeb*/
4264 static void i86op_jump_byte_IMM(PC_ENV *m)
4265 {
4266 int8 offset;
4267 uint16 target;
4268 offset = (int8) fetch_byte_imm(m); /* CHECK */
4269 /* printf("jump byte imm offset=%d\n",offset);*/
4270 target = (int16) m->R_IP + offset;
4271 m->R_IP = target;
4272 DECODE_CLEAR_SEGOVR(m);
4273 }
4274
4275 /*opcode=0xec*/
4276 static void i86op_in_byte_AL_DX(PC_ENV *m)
4277 {
4278 m->R_AL = in(m->R_DX);
4279 DECODE_CLEAR_SEGOVR(m);
4280 }
4281
4282 /*opcode=0xed*/
4283 static void i86op_in_word_AX_DX(PC_ENV *m)
4284 {
4285 m->R_AX = in(m->R_DX);
4286 DECODE_CLEAR_SEGOVR(m);
4287 }
4288
4289 /*opcode=0xee*/
4290 static void i86op_out_byte_DX_AL(PC_ENV *m)
4291 {
4292 out(m->R_DX, m->R_AL);
4293 DECODE_CLEAR_SEGOVR(m);
4294 }
4295
4296 /*opcode=0xef*/
4297 static void i86op_out_word_DX_AX(PC_ENV *m)
4298 {
4299 out(m->R_DX, m->R_AX);
4300 DECODE_CLEAR_SEGOVR(m);
4301 }
4302
4303 /*opcode=0xf0*/
4304 static void i86op_lock(PC_ENV *m)
4305 {
4306 DECODE_CLEAR_SEGOVR(m);
4307 }
4308
4309 /*opcode=0xf1 ILLEGAL OPERATION*/
4310
4311 /*opcode=0xf2*/
4312 static void i86op_repne(PC_ENV *m)
4313 {
4314 m->sysmode |= SYSMODE_PREFIX_REPNE;
4315 DECODE_CLEAR_SEGOVR(m);
4316 }
4317
4318 /*opcode=0xf3*/
4319 static void i86op_repe(PC_ENV *m)
4320 {
4321 m->sysmode |= SYSMODE_PREFIX_REPE;
4322 DECODE_CLEAR_SEGOVR(m);
4323 }
4324
4325 /*opcode=0xf4*/
4326 static void i86op_halt(PC_ENV *m)
4327 {
4328 halt_sys(m);
4329 DECODE_CLEAR_SEGOVR(m);
4330 }
4331
4332 /*opcode=0xf5*/
4333 static void i86op_cmc(PC_ENV *m)
4334 {
4335 /* complement the carry flag. */
4336 TOGGLE_FLAG(m,F_CF);
4337 DECODE_CLEAR_SEGOVR(m);
4338 }
4339
4340 /*opcode=0xf6*/
4341 static void i86op_opcF6_byte_RM(PC_ENV *m)
4342 {
4343 uint16 mod,rl,rh;
4344 uint8 *destreg;
4345 uint16 destoffset;
4346 uint8 destval,srcval;
4347 /* long, drawn out code follows. Double switch for a total
4348 of 32 cases. */
4349 FETCH_DECODE_MODRM(m,mod,rh,rl);
4350 switch (mod)
4351 {
4352 case 0: /* mod=00 */
4353 switch(rh)
4354 {
4355 case 0: /* test byte imm */
4356 destoffset=decode_rm00_address(m,rl);
4357 srcval = fetch_byte_imm(m);
4358 destval = fetch_data_byte(m,destoffset);
4359 test_byte(m, destval, srcval);
4360 break;
4361 case 1:
4362 halt_sys(m);
4363 break;
4364 case 2:
4365 destoffset=decode_rm00_address(m,rl);
4366 destval = fetch_data_byte(m,destoffset);
4367 destval = not_byte(m, destval);
4368 store_data_byte(m,destoffset,destval);
4369 break;
4370 case 3:
4371 destoffset=decode_rm00_address(m,rl);
4372 destval = fetch_data_byte(m,destoffset);
4373 destval = neg_byte(m, destval);
4374 store_data_byte(m,destoffset,destval);
4375 break;
4376 case 4:
4377 destoffset=decode_rm00_address(m,rl);
4378 destval = fetch_data_byte(m,destoffset);
4379 mul_byte(m, destval);
4380 break;
4381 case 5:
4382 destoffset=decode_rm00_address(m,rl);
4383 destval = fetch_data_byte(m,destoffset);
4384 imul_byte(m, destval);
4385 break;
4386 case 6:
4387 destoffset=decode_rm00_address(m,rl);
4388 destval = fetch_data_byte(m,destoffset);
4389 div_byte(m, destval);
4390 break;
4391 case 7:
4392 destoffset=decode_rm00_address(m,rl);
4393 destval = fetch_data_byte(m,destoffset);
4394 idiv_byte(m, destval);
4395 break;
4396 }
4397 break; /* end mod==00 */
4398 case 1: /* mod=01 */
4399 switch(rh)
4400 {
4401 case 0: /* test byte imm */
4402 destoffset=decode_rm01_address(m,rl);
4403 srcval = fetch_byte_imm(m);
4404 destval = fetch_data_byte(m,destoffset);
4405 test_byte(m, destval, srcval);
4406 break;
4407 case 1:
4408 halt_sys(m);
4409 break;
4410 case 2:
4411 destoffset=decode_rm01_address(m,rl);
4412 destval = fetch_data_byte(m,destoffset);
4413 destval = not_byte(m, destval);
4414 store_data_byte(m,destoffset,destval);
4415 break;
4416 case 3:
4417 destoffset=decode_rm01_address(m,rl);
4418 destval = fetch_data_byte(m,destoffset);
4419 destval = neg_byte(m, destval);
4420 store_data_byte(m,destoffset,destval);
4421 break;
4422 case 4:
4423 destoffset=decode_rm01_address(m,rl);
4424 destval = fetch_data_byte(m,destoffset);
4425 mul_byte(m, destval);
4426 break;
4427 case 5:
4428 destoffset=decode_rm01_address(m,rl);
4429 destval = fetch_data_byte(m,destoffset);
4430 imul_byte(m, destval);
4431 break;
4432 case 6:
4433 destoffset=decode_rm01_address(m,rl);
4434 destval = fetch_data_byte(m,destoffset);
4435 div_byte(m, destval);
4436 break;
4437 case 7:
4438 destoffset=decode_rm01_address(m,rl);
4439 destval = fetch_data_byte(m,destoffset);
4440 idiv_byte(m, destval);
4441 break;
4442 }
4443 break; /* end mod==01 */
4444 case 2: /* mod=10 */
4445 switch(rh)
4446 {
4447 case 0: /* test byte imm */
4448 destoffset=decode_rm10_address(m,rl);
4449 srcval = fetch_byte_imm(m);
4450 destval = fetch_data_byte(m,destoffset);
4451 test_byte(m, destval, srcval);
4452 break;
4453 case 1:
4454 halt_sys(m);
4455 break;
4456 case 2:
4457 destoffset=decode_rm10_address(m,rl);
4458 destval = fetch_data_byte(m,destoffset);
4459 destval = not_byte(m, destval);
4460 store_data_byte(m,destoffset,destval);
4461 break;
4462 case 3:
4463 destoffset=decode_rm10_address(m,rl);
4464 destval = fetch_data_byte(m,destoffset);
4465 destval = neg_byte(m, destval);
4466 store_data_byte(m,destoffset,destval);
4467 break;
4468 case 4:
4469 destoffset=decode_rm10_address(m,rl);
4470 destval = fetch_data_byte(m,destoffset);
4471 mul_byte(m, destval);
4472 break;
4473 case 5:
4474 destoffset=decode_rm10_address(m,rl);
4475 destval = fetch_data_byte(m,destoffset);
4476 imul_byte(m, destval);
4477 break;
4478 case 6:
4479 destoffset=decode_rm10_address(m,rl);
4480 destval = fetch_data_byte(m,destoffset);
4481 div_byte(m, destval);
4482 break;
4483 case 7:
4484 destoffset=decode_rm10_address(m,rl);
4485 destval = fetch_data_byte(m,destoffset);
4486 idiv_byte(m, destval);
4487 break;
4488 }
4489 break; /* end mod==10 */
4490 case 3: /* mod=11 */
4491 switch(rh)
4492 {
4493 case 0: /* test byte imm */
4494 destreg=DECODE_RM_BYTE_REGISTER(m,rl);
4495 srcval = fetch_byte_imm(m);
4496 test_byte(m, *destreg, srcval);
4497 break;
4498 case 1:
4499 halt_sys(m);
4500 break;
4501 case 2:
4502 destreg=DECODE_RM_BYTE_REGISTER(m,rl);
4503 *destreg = not_byte(m, *destreg);
4504 break;
4505 case 3:
4506 destreg=DECODE_RM_BYTE_REGISTER(m,rl);
4507 *destreg = neg_byte(m, *destreg);
4508 break;
4509 case 4:
4510 destreg=DECODE_RM_BYTE_REGISTER(m,rl);
4511 mul_byte(m, *destreg); /*!!! */
4512 break;
4513 case 5:
4514 destreg=DECODE_RM_BYTE_REGISTER(m,rl);
4515 imul_byte(m, *destreg);
4516 break;
4517 case 6:
4518 destreg=DECODE_RM_BYTE_REGISTER(m,rl);
4519 div_byte(m, *destreg);
4520 break;
4521 case 7:
4522 destreg=DECODE_RM_BYTE_REGISTER(m,rl);
4523 idiv_byte(m, *destreg);
4524 break;
4525 }
4526 break; /* end mod==11 */
4527 }
4528 DECODE_CLEAR_SEGOVR(m);
4529 }
4530
4531 /*opcode=0xf7*/
4532 static void i86op_opcF7_word_RM(PC_ENV *m)
4533 {
4534 uint16 mod,rl,rh;
4535 uint16 *destreg;
4536 uint16 destoffset;
4537 uint16 destval,srcval;
4538 /* long, drawn out code follows. Double switch for a total
4539 of 32 cases. */
4540 FETCH_DECODE_MODRM(m,mod,rh,rl);
4541 switch (mod)
4542 {
4543 case 0: /* mod=00 */
4544 switch(rh)
4545 {
4546 case 0: /* test word imm */
4547 destoffset=decode_rm00_address(m,rl);
4548 srcval = fetch_word_imm(m);
4549 destval = fetch_data_word(m,destoffset);
4550 test_word(m, destval, srcval);
4551 break;
4552 case 1:
4553 halt_sys(m);
4554 break;
4555 case 2:
4556 destoffset=decode_rm00_address(m,rl);
4557 destval = fetch_data_word(m,destoffset);
4558 destval = not_word(m, destval);
4559 store_data_word(m,destoffset,destval);
4560 break;
4561 case 3:
4562 destoffset=decode_rm00_address(m,rl);
4563 destval = fetch_data_word(m,destoffset);
4564 destval = neg_word(m, destval);
4565 store_data_word(m,destoffset,destval);
4566 break;
4567 case 4:
4568 destoffset=decode_rm00_address(m,rl);
4569 destval = fetch_data_word(m,destoffset);
4570 mul_word(m, destval);
4571 break;
4572 case 5:
4573 destoffset=decode_rm00_address(m,rl);
4574 destval = fetch_data_word(m,destoffset);
4575 imul_word(m, destval);
4576 break;
4577 case 6:
4578 destoffset=decode_rm00_address(m,rl);
4579 destval = fetch_data_word(m,destoffset);
4580 div_word(m, destval);
4581 break;
4582 case 7:
4583 destoffset=decode_rm00_address(m,rl);
4584 destval = fetch_data_word(m,destoffset);
4585 idiv_word(m, destval);
4586 break;
4587 }
4588 break; /* end mod==00 */
4589 case 1: /* mod=01 */
4590 switch(rh)
4591 {
4592 case 0: /* test word imm */
4593 destoffset=decode_rm01_address(m,rl);
4594 srcval = fetch_word_imm(m);
4595 destval = fetch_data_word(m,destoffset);
4596 test_word(m, destval, srcval);
4597 break;
4598 case 1:
4599 halt_sys(m);
4600 break;
4601 case 2:
4602 destoffset=decode_rm01_address(m,rl);
4603 destval = fetch_data_word(m,destoffset);
4604 destval = not_word(m, destval);
4605 store_data_word(m,destoffset,destval);
4606 break;
4607 case 3:
4608 destoffset=decode_rm01_address(m,rl);
4609 destval = fetch_data_word(m,destoffset);
4610 destval = neg_word(m, destval);
4611 store_data_word(m,destoffset,destval);
4612 break;
4613 case 4:
4614 destoffset=decode_rm01_address(m,rl);
4615 destval = fetch_data_word(m,destoffset);
4616 mul_word(m, destval);
4617 break;
4618 case 5:
4619 destoffset=decode_rm01_address(m,rl);
4620 destval = fetch_data_word(m,destoffset);
4621 imul_word(m, destval);
4622 break;
4623 case 6:
4624 destoffset=decode_rm01_address(m,rl);
4625 destval = fetch_data_word(m,destoffset);
4626 div_word(m, destval);
4627 break;
4628 case 7:
4629 destoffset=decode_rm01_address(m,rl);
4630 destval = fetch_data_word(m,destoffset);
4631 idiv_word(m, destval);
4632 break;
4633 }
4634 break; /* end mod==01 */
4635 case 2: /* mod=10 */
4636 switch(rh)
4637 {
4638 case 0: /* test word imm */
4639 destoffset=decode_rm10_address(m,rl);
4640 srcval = fetch_word_imm(m);
4641 destval = fetch_data_word(m,destoffset);
4642 test_word(m, destval, srcval);
4643 break;
4644 case 1:
4645 halt_sys(m);
4646 break;
4647 case 2:
4648 destoffset=decode_rm10_address(m,rl);
4649 destval = fetch_data_word(m,destoffset);
4650 destval = not_word(m, destval);
4651 store_data_word(m,destoffset,destval);
4652 break;
4653 case 3:
4654 destoffset=decode_rm10_address(m,rl);
4655 destval = fetch_data_word(m,destoffset);
4656 destval = neg_word(m, destval);
4657 store_data_word(m,destoffset,destval);
4658 break;
4659 case 4:
4660 destoffset=decode_rm10_address(m,rl);
4661 destval = fetch_data_word(m,destoffset);
4662 mul_word(m, destval);
4663 break;
4664 case 5:
4665 destoffset=decode_rm10_address(m,rl);
4666 destval = fetch_data_word(m,destoffset);
4667 imul_word(m, destval);
4668 break;
4669 case 6:
4670 destoffset=decode_rm10_address(m,rl);
4671 destval = fetch_data_word(m,destoffset);
4672 div_word(m, destval);
4673 break;
4674 case 7:
4675 destoffset=decode_rm10_address(m,rl);
4676 destval = fetch_data_word(m,destoffset);
4677 idiv_word(m, destval);
4678 break;
4679 }
4680 break; /* end mod==10 */
4681 case 3: /* mod=11 */
4682 switch(rh)
4683 {
4684 case 0: /* test word imm */
4685 destreg=DECODE_RM_WORD_REGISTER(m,rl);
4686 srcval = fetch_word_imm(m);
4687 test_word(m, *destreg, srcval);
4688 break;
4689 case 1:
4690 halt_sys(m);
4691 break;
4692 case 2:
4693 destreg=DECODE_RM_WORD_REGISTER(m,rl);
4694 *destreg = not_word(m, *destreg);
4695 break;
4696 case 3:
4697 destreg=DECODE_RM_WORD_REGISTER(m,rl);
4698 *destreg = neg_word(m, *destreg);
4699 break;
4700 case 4:
4701 destreg=DECODE_RM_WORD_REGISTER(m,rl);
4702 mul_word(m, *destreg); /*!!! */
4703 break;
4704 case 5:
4705 destreg=DECODE_RM_WORD_REGISTER(m,rl);
4706 imul_word(m, *destreg);
4707 break;
4708 case 6:
4709 destreg=DECODE_RM_WORD_REGISTER(m,rl);
4710 div_word(m, *destreg);
4711 break;
4712 case 7:
4713 destreg=DECODE_RM_WORD_REGISTER(m,rl);
4714 idiv_word(m, *destreg);
4715 break;
4716 }
4717 break; /* end mod==11 */
4718 }
4719 DECODE_CLEAR_SEGOVR(m);
4720 }
4721
4722 /*opcode=0xf8*/
4723 static void i86op_clc(PC_ENV *m)
4724 {
4725 /* clear the carry flag. */
4726 CLEAR_FLAG(m, F_CF);
4727 DECODE_CLEAR_SEGOVR(m);
4728 }
4729
4730 /*opcode=0xf9*/
4731 static void i86op_stc(PC_ENV *m)
4732 {
4733 /* set the carry flag. */
4734 SET_FLAG(m, F_CF);
4735 DECODE_CLEAR_SEGOVR(m);
4736 }
4737
4738 /*opcode=0xfa*/
4739 static void i86op_cli(PC_ENV *m)
4740 {
4741 /* clear interrupts. */
4742 CLEAR_FLAG(m, F_IF);
4743 DECODE_CLEAR_SEGOVR(m);
4744 }
4745
4746 /*opcode=0xfb*/
4747 static void i86op_sti(PC_ENV *m)
4748 {
4749 /* enable interrupts. */
4750 SET_FLAG(m, F_IF);
4751 DECODE_CLEAR_SEGOVR(m);
4752 }
4753
4754 /*opcode=0xfc*/
4755 static void i86op_cld(PC_ENV *m)
4756 {
4757 /* clear interrupts. */
4758 CLEAR_FLAG(m, F_DF);
4759 DECODE_CLEAR_SEGOVR(m);
4760 }
4761
4762 /*opcode=0xfd*/
4763 static void i86op_std(PC_ENV *m)
4764 {
4765 /* clear interrupts. */
4766 SET_FLAG(m, F_DF);
4767 DECODE_CLEAR_SEGOVR(m);
4768 }
4769
4770 /*opcode=0xfe*/
4771 static void i86op_opcFE_byte_RM(PC_ENV *m)
4772 {
4773 /* Yet another damned special case instruction. */
4774 uint16 mod,rh,rl;
4775 uint8 destval;
4776 uint16 destoffset;
4777 uint8 *destreg;
4778 /* ARRGH, ANOTHER GODDAMN SPECIAL CASE INSTRUCTION!!! */
4779 FETCH_DECODE_MODRM(m,mod,rh,rl);
4780 switch (mod)
4781 {
4782 case 0:
4783 destoffset=decode_rm00_address(m,rl);
4784 switch (rh)
4785 {
4786 case 0: /* inc word ptr ... */
4787 destval = fetch_data_byte(m,destoffset);
4788 destval = inc_byte(m,destval);
4789 store_data_byte(m,destoffset,destval);
4790 break;
4791 case 1: /* dec word ptr ... */
4792 destval = fetch_data_byte(m,destoffset);
4793 destval = dec_byte(m,destval);
4794 store_data_byte(m,destoffset,destval);
4795 break;
4796 }
4797 break;
4798 case 1:
4799 destoffset=decode_rm01_address(m,rl);
4800 switch (rh)
4801 {
4802 case 0:
4803 destval = fetch_data_byte(m,destoffset);
4804 destval = inc_byte(m,destval);
4805 store_data_byte(m,destoffset,destval);
4806 break;
4807 case 1:
4808 destval = fetch_data_byte(m,destoffset);
4809 destval = dec_byte(m,destval);
4810 store_data_byte(m,destoffset,destval);
4811 break;
4812 }
4813 break;
4814 case 2:
4815 destoffset=decode_rm10_address(m,rl);
4816 switch (rh)
4817 {
4818 case 0:
4819 destval = fetch_data_byte(m,destoffset);
4820 destval = inc_byte(m,destval);
4821 store_data_byte(m,destoffset,destval);
4822 break;
4823 case 1:
4824 destval = fetch_data_byte(m,destoffset);
4825 destval = dec_byte(m,destval);
4826 store_data_byte(m,destoffset,destval);
4827 break;
4828 }
4829 break;
4830 case 3:
4831 destreg = DECODE_RM_BYTE_REGISTER(m,rl);
4832 switch (rh)
4833 {
4834 case 0:
4835 *destreg = inc_byte(m,*destreg);
4836 break;
4837 case 1:
4838 *destreg = dec_byte(m,*destreg);
4839 break;
4840 }
4841 break;
4842 }
4843 DECODE_CLEAR_SEGOVR(m);
4844 }
4845
4846 /*opcode=0xff*/
4847 static void i86op_opcFF_word_RM(PC_ENV *m)
4848 {
4849 uint16 mod,rh,rl;
4850 uint16 destval,destval2;
4851 uint16 destoffset;
4852 uint16 *destreg;
4853 /* ANOTHER DAMN SPECIAL CASE INSTRUCTION!!! */
4854 FETCH_DECODE_MODRM(m,mod,rh,rl);
4855 switch (mod)
4856 {
4857 case 0:
4858 destoffset=decode_rm00_address(m,rl);
4859 switch (rh)
4860 {
4861 case 0: /* inc word ptr ... */
4862 destval = fetch_data_word(m,destoffset);
4863 destval = inc_word(m,destval);
4864 store_data_word(m,destoffset,destval);
4865 break;
4866 case 1: /* dec word ptr ... */
4867 destval = fetch_data_word(m,destoffset);
4868 destval = dec_word(m,destval);
4869 store_data_word(m,destoffset,destval);
4870 break;
4871 case 2: /* call word ptr ... */
4872 destval = fetch_data_word(m,destoffset);
4873 push_word(m,m->R_IP);
4874 m->R_IP = destval;
4875 break;
4876 case 3: /* call far ptr ... */
4877 destval = fetch_data_word(m,destoffset);
4878 destval2 = fetch_data_word(m,destoffset+2);
4879 push_word(m,m->R_CS);
4880 m->R_CS = destval2;
4881 push_word(m,m->R_IP);
4882 m->R_IP = destval;
4883 break;
4884 case 4: /* jmp word ptr ... */
4885 destval = fetch_data_word(m,destoffset);
4886 m->R_IP = destval;
4887 break;
4888 case 5: /* jmp far ptr ... */
4889 destval = fetch_data_word(m,destoffset);
4890 destval2 = fetch_data_word(m,destoffset+2);
4891 m->R_IP = destval;
4892 m->R_CS = destval2;
4893 break;
4894 case 6: /* push word ptr ... */
4895 destval = fetch_data_word(m,destoffset);
4896 push_word(m,destval);
4897 break;
4898 }
4899 break;
4900 case 1:
4901 destoffset=decode_rm01_address(m,rl);
4902 switch (rh)
4903 {
4904 case 0:
4905 destval = fetch_data_word(m,destoffset);
4906 destval = inc_word(m,destval);
4907 store_data_word(m,destoffset,destval);
4908 break;
4909 case 1:
4910 destval = fetch_data_word(m,destoffset);
4911 destval = dec_word(m,destval);
4912 store_data_word(m,destoffset,destval);
4913 break;
4914 case 2: /* call word ptr ... */
4915 destval = fetch_data_word(m,destoffset);
4916 push_word(m,m->R_IP);
4917 m->R_IP = destval;
4918 break;
4919 case 3: /* call far ptr ... */
4920 destval = fetch_data_word(m,destoffset);
4921 destval2 = fetch_data_word(m,destoffset+2);
4922 push_word(m,m->R_CS);
4923 m->R_CS = destval2;
4924 push_word(m,m->R_IP);
4925 m->R_IP = destval;
4926 break;
4927 case 4: /* jmp word ptr ... */
4928 destval = fetch_data_word(m,destoffset);
4929 m->R_IP = destval;
4930 break;
4931 case 5: /* jmp far ptr ... */
4932 destval = fetch_data_word(m,destoffset);
4933 destval2 = fetch_data_word(m,destoffset+2);
4934 m->R_IP = destval;
4935 m->R_CS = destval2;
4936 break;
4937 case 6: /* push word ptr ... */
4938 destval = fetch_data_word(m,destoffset);
4939 push_word(m,destval);
4940 break;
4941 }
4942 break;
4943 case 2:
4944 destoffset=decode_rm10_address(m,rl);
4945 switch (rh)
4946 {
4947 case 0:
4948 destval = fetch_data_word(m,destoffset);
4949 destval = inc_word(m,destval);
4950 store_data_word(m,destoffset,destval);
4951 break;
4952 case 1:
4953 destval = fetch_data_word(m,destoffset);
4954 destval = dec_word(m,destval);
4955 store_data_word(m,destoffset,destval);
4956 break;
4957 case 2: /* call word ptr ... */
4958 destval = fetch_data_word(m,destoffset);
4959 push_word(m,m->R_IP);
4960 m->R_IP = destval;
4961 break;
4962 case 3: /* call far ptr ... */
4963 destval = fetch_data_word(m,destoffset);
4964 destval2 = fetch_data_word(m,destoffset+2);
4965 push_word(m,m->R_CS);
4966 m->R_CS = destval2;
4967 push_word(m,m->R_IP);
4968 m->R_IP = destval;
4969 break;
4970 case 4: /* jmp word ptr ... */
4971 destval = fetch_data_word(m,destoffset);
4972 m->R_IP = destval;
4973 break;
4974 case 5: /* jmp far ptr ... */
4975 destval = fetch_data_word(m,destoffset);
4976 destval2 = fetch_data_word(m,destoffset+2);
4977 m->R_IP = destval;
4978 m->R_CS = destval2;
4979 break;
4980 case 6: /* push word ptr ... */
4981 destval = fetch_data_word(m,destoffset);
4982 push_word(m,destval);
4983 break;
4984 }
4985 break;
4986 case 3:
4987 destreg = DECODE_RM_WORD_REGISTER(m,rl);
4988 switch (rh)
4989 {
4990 case 0:
4991 *destreg = inc_word(m,*destreg);
4992 break;
4993 case 1:
4994 *destreg = dec_word(m,*destreg);
4995 break;
4996 case 2: /* call word ptr ... */
4997 push_word(m,m->R_IP);
4998 m->R_IP = *destreg;
4999 break;
5000 case 3: /* jmp far ptr ... */
5001 halt_sys(m);
5002 break;
5003 case 4: /* jmp ... */
5004 m->R_IP = (uint16)(*destreg);
5005 break;
5006 case 5: /* jmp far ptr ... */
5007 halt_sys(m);
5008 break;
5009 case 6:
5010 push_word(m,*destreg);
5011 break;
5012 }
5013 break;
5014 }
5015 DECODE_CLEAR_SEGOVR(m);
5016 }
5017
5018 /* opcode=0xd8*/
5019 static void i86op_esc_coprocess_d8(PC_ENV *m)
5020 {
5021 DECODE_CLEAR_SEGOVR(m);
5022 }
5023
5024 /* opcode=0xd9*/
5025 static void i86op_esc_coprocess_d9(PC_ENV *m)
5026 {
5027 uint16 mod,rl,rh;
5028 uint16 destoffset;
5029 uint8 stkelem;
5030 FETCH_DECODE_MODRM(m,mod,rh,rl);
5031 switch (mod)
5032 {
5033 case 0:
5034 destoffset=decode_rm00_address(m,rl);
5035 break;
5036 case 1:
5037 destoffset=decode_rm01_address(m,rl);
5038 break;
5039 case 2:
5040 destoffset=decode_rm10_address(m,rl);
5041 break;
5042 case 3: /* register to register */
5043 stkelem = (uint8) rl;
5044 break;
5045 }
5046 DECODE_CLEAR_SEGOVR(m);
5047 }
5048
5049 /* opcode=0xda*/
5050 static void i86op_esc_coprocess_da(PC_ENV *m)
5051 {
5052 uint16 mod,rl,rh;
5053 uint16 destoffset;
5054 uint8 stkelem;
5055 FETCH_DECODE_MODRM(m,mod,rh,rl);
5056 switch (mod)
5057 {
5058 case 0:
5059 destoffset=decode_rm00_address(m,rl);
5060 break;
5061 case 1:
5062 destoffset=decode_rm01_address(m,rl);
5063 break;
5064 case 2:
5065 destoffset=decode_rm10_address(m,rl);
5066 break;
5067 case 3: /* register to register */
5068 stkelem = (uint8) rl;
5069 break;
5070 }
5071 DECODE_CLEAR_SEGOVR(m);
5072 }
5073
5074 /* opcode=0xdb*/
5075 static void i86op_esc_coprocess_db(PC_ENV *m)
5076 {
5077 uint16 mod,rl,rh;
5078 uint16 destoffset;
5079 /* uint8 stkelem;*/
5080 FETCH_DECODE_MODRM(m,mod,rh,rl);
5081 switch (mod)
5082 {
5083 case 0:
5084 destoffset=decode_rm00_address(m,rl);
5085 break;
5086 case 1:
5087 destoffset=decode_rm01_address(m,rl);
5088 break;
5089 case 2:
5090 destoffset=decode_rm10_address(m,rl);
5091 break;
5092 case 3: /* register to register */
5093 break;
5094 }
5095 DECODE_CLEAR_SEGOVR(m);
5096 }
5097
5098 /* opcode=0xdc*/
5099 static void i86op_esc_coprocess_dc(PC_ENV *m)
5100 {
5101 uint16 mod,rl,rh;
5102 uint16 destoffset;
5103 uint8 stkelem;
5104 FETCH_DECODE_MODRM(m,mod,rh,rl);
5105 switch (mod)
5106 {
5107 case 0:
5108 destoffset=decode_rm00_address(m,rl);
5109 break;
5110 case 1:
5111 destoffset=decode_rm01_address(m,rl);
5112 break;
5113 case 2:
5114 destoffset=decode_rm10_address(m,rl);
5115 break;
5116 case 3: /* register to register */
5117 stkelem = (uint8) rl;
5118 break;
5119 }
5120 DECODE_CLEAR_SEGOVR(m);
5121 }
5122
5123 /* opcode=0xdd*/
5124 static void i86op_esc_coprocess_dd(PC_ENV *m)
5125 {
5126 uint16 mod,rl,rh;
5127 uint16 destoffset;
5128 uint8 stkelem;
5129 FETCH_DECODE_MODRM(m,mod,rh,rl);
5130 switch (mod)
5131 {
5132 case 0:
5133 destoffset=decode_rm00_address(m,rl);
5134 break;
5135 case 1:
5136 destoffset=decode_rm01_address(m,rl);
5137 break;
5138 case 2:
5139 destoffset=decode_rm10_address(m,rl);
5140 break;
5141 case 3: /* register to register */
5142 stkelem = (uint8) rl;
5143 break;
5144 }
5145 DECODE_CLEAR_SEGOVR(m);
5146 }
5147
5148 /* opcode=0xde*/
5149 static void i86op_esc_coprocess_de(PC_ENV *m)
5150 {
5151 uint16 mod,rl,rh;
5152 uint16 destoffset;
5153 uint8 stkelem;
5154 FETCH_DECODE_MODRM(m,mod,rh,rl);
5155 switch (mod)
5156 {
5157 case 0:
5158 destoffset=decode_rm00_address(m,rl);
5159 break;
5160 case 1:
5161 destoffset=decode_rm01_address(m,rl);
5162 break;
5163 case 2:
5164 destoffset=decode_rm10_address(m,rl);
5165 break;
5166 case 3: /* register to register */
5167 stkelem = (uint8) rl;
5168 break;
5169 }
5170 DECODE_CLEAR_SEGOVR(m);
5171 }
5172
5173 /* opcode=0xdf*/
5174 static void i86op_esc_coprocess_df(PC_ENV *m)
5175 {
5176 uint16 mod,rl,rh;
5177 uint16 destoffset;
5178 uint8 stkelem;
5179 FETCH_DECODE_MODRM(m,mod,rh,rl);
5180 switch (mod)
5181 {
5182 case 0:
5183 destoffset=decode_rm00_address(m,rl);
5184 break;
5185 case 1:
5186 destoffset=decode_rm01_address(m,rl);
5187 break;
5188 case 2:
5189 destoffset=decode_rm10_address(m,rl);
5190 break;
5191 case 3: /* register to register */
5192 stkelem = (uint8) rl;
5193 break;
5194 }
5195 DECODE_CLEAR_SEGOVR(m);
5196 }
5197
5198 /* OPERAND TABLE */
5199
5200 OP i86_optab[256] = {
5201
5202 /* 0x00 */ i86op_add_byte_RM_R,
5203 /* 0x01 */ i86op_add_word_RM_R,
5204 /* 0x02 */ i86op_add_byte_R_RM,
5205 /* 0x03 */ i86op_add_word_R_RM,
5206 /* 0x04 */ i86op_add_byte_AL_IMM,
5207 /* 0x05 */ i86op_add_word_AX_IMM,
5208 /* 0x06 */ i86op_push_ES,
5209 /* 0x07 */ i86op_pop_ES,
5210
5211 /* 0x08 */ i86op_or_byte_RM_R,
5212 /* 0x09 */ i86op_or_word_RM_R,
5213 /* 0x0a */ i86op_or_byte_R_RM,
5214 /* 0x0b */ i86op_or_word_R_RM,
5215 /* 0x0c */ i86op_or_byte_AL_IMM,
5216 /* 0x0d */ i86op_or_word_AX_IMM,
5217 /* 0x0e */ i86op_push_CS,
5218 /* 0x0f */ i86op_illegal_op,
5219
5220 /* 0x10 */ i86op_adc_byte_RM_R,
5221 /* 0x11 */ i86op_adc_word_RM_R,
5222 /* 0x12 */ i86op_adc_byte_R_RM,
5223 /* 0x13 */ i86op_adc_word_R_RM,
5224 /* 0x14 */ i86op_adc_byte_AL_IMM,
5225 /* 0x15 */ i86op_adc_word_AX_IMM,
5226 /* 0x16 */ i86op_push_SS,
5227 /* 0x17 */ i86op_pop_SS,
5228
5229 /* 0x18 */ i86op_sbb_byte_RM_R,
5230 /* 0x19 */ i86op_sbb_word_RM_R,
5231 /* 0x1a */ i86op_sbb_byte_R_RM,
5232 /* 0x1b */ i86op_sbb_word_R_RM,
5233 /* 0x1c */ i86op_sbb_byte_AL_IMM,
5234 /* 0x1d */ i86op_sbb_word_AX_IMM,
5235 /* 0x1e */ i86op_push_DS,
5236 /* 0x1f */ i86op_pop_DS,
5237
5238 /* 0x20 */ i86op_and_byte_RM_R,
5239 /* 0x21 */ i86op_and_word_RM_R,
5240 /* 0x22 */ i86op_and_byte_R_RM,
5241 /* 0x23 */ i86op_and_word_R_RM,
5242 /* 0x24 */ i86op_and_byte_AL_IMM,
5243 /* 0x25 */ i86op_and_word_AX_IMM,
5244 /* 0x26 */ i86op_segovr_ES,
5245 /* 0x27 */ i86op_daa,
5246
5247 /* 0x28 */ i86op_sub_byte_RM_R,
5248 /* 0x29 */ i86op_sub_word_RM_R,
5249 /* 0x2a */ i86op_sub_byte_R_RM,
5250 /* 0x2b */ i86op_sub_word_R_RM,
5251 /* 0x2c */ i86op_sub_byte_AL_IMM,
5252 /* 0x2d */ i86op_sub_word_AX_IMM,
5253 /* 0x2e */ i86op_segovr_CS,
5254 /* 0x2f */ i86op_das,
5255
5256 /* 0x30 */ i86op_xor_byte_RM_R,
5257 /* 0x31 */ i86op_xor_word_RM_R,
5258 /* 0x32 */ i86op_xor_byte_R_RM,
5259 /* 0x33 */ i86op_xor_word_R_RM,
5260 /* 0x34 */ i86op_xor_byte_AL_IMM,
5261 /* 0x35 */ i86op_xor_word_AX_IMM,
5262 /* 0x36 */ i86op_segovr_SS,
5263 /* 0x37 */ i86op_aaa,
5264
5265 /* 0x38 */ i86op_cmp_byte_RM_R,
5266 /* 0x39 */ i86op_cmp_word_RM_R,
5267 /* 0x3a */ i86op_cmp_byte_R_RM,
5268 /* 0x3b */ i86op_cmp_word_R_RM,
5269 /* 0x3c */ i86op_cmp_byte_AL_IMM,
5270 /* 0x3d */ i86op_cmp_word_AX_IMM,
5271 /* 0x3e */ i86op_segovr_DS,
5272 /* 0x3f */ i86op_aas,
5273
5274 /* 0x40 */ i86op_inc_AX,
5275 /* 0x41 */ i86op_inc_CX,
5276 /* 0x42 */ i86op_inc_DX,
5277 /* 0x43 */ i86op_inc_BX,
5278 /* 0x44 */ i86op_inc_SP,
5279 /* 0x45 */ i86op_inc_BP,
5280 /* 0x46 */ i86op_inc_SI,
5281 /* 0x47 */ i86op_inc_DI,
5282
5283 /* 0x48 */ i86op_dec_AX,
5284 /* 0x49 */ i86op_dec_CX,
5285 /* 0x4a */ i86op_dec_DX,
5286 /* 0x4b */ i86op_dec_BX,
5287 /* 0x4c */ i86op_dec_SP,
5288 /* 0x4d */ i86op_dec_BP,
5289 /* 0x4e */ i86op_dec_SI,
5290 /* 0x4f */ i86op_dec_DI,
5291
5292 /* 0x50 */ i86op_push_AX,
5293 /* 0x51 */ i86op_push_CX,
5294 /* 0x52 */ i86op_push_DX,
5295 /* 0x53 */ i86op_push_BX,
5296 /* 0x54 */ i86op_push_SP,
5297 /* 0x55 */ i86op_push_BP,
5298 /* 0x56 */ i86op_push_SI,
5299 /* 0x57 */ i86op_push_DI,
5300
5301 /* 0x58 */ i86op_pop_AX,
5302 /* 0x59 */ i86op_pop_CX,
5303 /* 0x5a */ i86op_pop_DX,
5304 /* 0x5b */ i86op_pop_BX,
5305 /* 0x5c */ i86op_pop_SP,
5306 /* 0x5d */ i86op_pop_BP,
5307 /* 0x5e */ i86op_pop_SI,
5308 /* 0x5f */ i86op_pop_DI,
5309
5310 /* 0x60 */ i86op_illegal_op,
5311 /* 0x61 */ i86op_illegal_op,
5312 /* 0x62 */ i86op_illegal_op,
5313 /* 0x63 */ i86op_illegal_op,
5314 /* 0x64 */ i86op_illegal_op,
5315 /* 0x65 */ i86op_illegal_op,
5316 /* 0x66 */ i86op_illegal_op,
5317 /* 0x67 */ i86op_illegal_op,
5318
5319 /* 0x68 */ i86op_illegal_op,
5320 /* 0x69 */ i86op_illegal_op,
5321 /* 0x6a */ i86op_illegal_op,
5322 /* 0x6b */ i86op_illegal_op,
5323 /* 0x6c */ i86op_illegal_op,
5324 /* 0x6d */ i86op_illegal_op,
5325 /* 0x6e */ i86op_illegal_op,
5326 /* 0x6f */ i86op_illegal_op,
5327
5328 /* 0x70 */ i86op_jump_near_O,
5329 /* 0x71 */ i86op_jump_near_NO,
5330 /* 0x72 */ i86op_jump_near_B,
5331 /* 0x73 */ i86op_jump_near_NB,
5332 /* 0x74 */ i86op_jump_near_Z,
5333 /* 0x75 */ i86op_jump_near_NZ,
5334 /* 0x76 */ i86op_jump_near_BE,
5335 /* 0x77 */ i86op_jump_near_NBE,
5336
5337 /* 0x78 */ i86op_jump_near_S,
5338 /* 0x79 */ i86op_jump_near_NS,
5339 /* 0x7a */ i86op_jump_near_P,
5340 /* 0x7b */ i86op_jump_near_NP,
5341 /* 0x7c */ i86op_jump_near_L,
5342 /* 0x7d */ i86op_jump_near_NL,
5343 /* 0x7e */ i86op_jump_near_LE,
5344 /* 0x7f */ i86op_jump_near_NLE,
5345
5346 /* 0x80 */ i86op_opc80_byte_RM_IMM,
5347 /* 0x81 */ i86op_opc81_word_RM_IMM,
5348 /* 0x82 */ i86op_opc82_byte_RM_IMM,
5349 /* 0x83 */ i86op_opc83_word_RM_IMM,
5350 /* 0x84 */ i86op_test_byte_RM_R,
5351 /* 0x85 */ i86op_test_word_RM_R,
5352 /* 0x86 */ i86op_xchg_byte_RM_R,
5353 /* 0x87 */ i86op_xchg_word_RM_R,
5354
5355 /* 0x88 */ i86op_mov_byte_RM_R,
5356 /* 0x89 */ i86op_mov_word_RM_R,
5357 /* 0x8a */ i86op_mov_byte_R_RM,
5358 /* 0x8b */ i86op_mov_word_R_RM,
5359 /* 0x8c */ i86op_mov_word_RM_SR,
5360 /* 0x8d */ i86op_lea_word_R_M,
5361 /* 0x8e */ i86op_mov_word_SR_RM,
5362 /* 0x8f */ i86op_pop_RM,
5363
5364 /* 0x90 */ i86op_nop,
5365 /* 0x91 */ i86op_xchg_word_AX_CX,
5366 /* 0x92 */ i86op_xchg_word_AX_DX,
5367 /* 0x93 */ i86op_xchg_word_AX_BX,
5368 /* 0x94 */ i86op_xchg_word_AX_SP,
5369 /* 0x95 */ i86op_xchg_word_AX_BP ,
5370 /* 0x96 */ i86op_xchg_word_AX_SI ,
5371 /* 0x97 */ i86op_xchg_word_AX_DI ,
5372
5373 /* 0x98 */ i86op_cbw,
5374 /* 0x99 */ i86op_cwd,
5375 /* 0x9a */ i86op_call_far_IMM,
5376 /* 0x9b */ i86op_wait,
5377 /* 0x9c */ i86op_pushf_word,
5378 /* 0x9d */ i86op_popf_word,
5379 /* 0x9e */ i86op_sahf,
5380 /* 0x9f */ i86op_lahf,
5381
5382 /* 0xa0 */ i86op_mov_AL_M_IMM,
5383 /* 0xa1 */ i86op_mov_AX_M_IMM,
5384 /* 0xa2 */ i86op_mov_M_AL_IMM,
5385 /* 0xa3 */ i86op_mov_M_AX_IMM,
5386 /* 0xa4 */ i86op_movs_byte,
5387 /* 0xa5 */ i86op_movs_word,
5388 /* 0xa6 */ i86op_cmps_byte,
5389 /* 0xa7 */ i86op_cmps_word,
5390 /* 0xa8 */ i86op_test_AL_IMM,
5391 /* 0xa9 */ i86op_test_AX_IMM,
5392 /* 0xaa */ i86op_stos_byte,
5393 /* 0xab */ i86op_stos_word,
5394 /* 0xac */ i86op_lods_byte,
5395 /* 0xad */ i86op_lods_word,
5396 /* 0xac */ i86op_scas_byte,
5397 /* 0xad */ i86op_scas_word,
5398
5399 /* 0xb0 */ i86op_mov_byte_AL_IMM,
5400 /* 0xb1 */ i86op_mov_byte_CL_IMM,
5401 /* 0xb2 */ i86op_mov_byte_DL_IMM,
5402 /* 0xb3 */ i86op_mov_byte_BL_IMM,
5403 /* 0xb4 */ i86op_mov_byte_AH_IMM,
5404 /* 0xb5 */ i86op_mov_byte_CH_IMM,
5405 /* 0xb6 */ i86op_mov_byte_DH_IMM,
5406 /* 0xb7 */ i86op_mov_byte_BH_IMM,
5407
5408 /* 0xb8 */ i86op_mov_word_AX_IMM,
5409 /* 0xb9 */ i86op_mov_word_CX_IMM,
5410 /* 0xba */ i86op_mov_word_DX_IMM,
5411 /* 0xbb */ i86op_mov_word_BX_IMM,
5412 /* 0xbc */ i86op_mov_word_SP_IMM,
5413 /* 0xbd */ i86op_mov_word_BP_IMM,
5414 /* 0xbe */ i86op_mov_word_SI_IMM,
5415 /* 0xbf */ i86op_mov_word_DI_IMM,
5416
5417 /* 0xc0 */ i86op_illegal_op,
5418 /* 0xc1 */ i86op_illegal_op,
5419 /* 0xc2 */ i86op_ret_near_IMM,
5420 /* 0xc3 */ i86op_ret_near,
5421 /* 0xc4 */ i86op_les_R_IMM,
5422 /* 0xc5 */ i86op_lds_R_IMM,
5423 /* 0xc6 */ i86op_mov_byte_RM_IMM,
5424 /* 0xc7 */ i86op_mov_word_RM_IMM,
5425 /* 0xc8 */ i86op_illegal_op,
5426 /* 0xc9 */ i86op_illegal_op,
5427 /* 0xca */ i86op_ret_far_IMM,
5428 /* 0xcb */ i86op_ret_far,
5429 /* 0xcc */ i86op_int3,
5430 /* 0xcd */ i86op_int_IMM,
5431 /* 0xce */ i86op_into,
5432 /* 0xcf */ i86op_iret,
5433
5434 /* 0xd0 */ i86op_opcD0_byte_RM_1,
5435 /* 0xd1 */ i86op_opcD1_word_RM_1,
5436 /* 0xd2 */ i86op_opcD2_byte_RM_CL,
5437 /* 0xd3 */ i86op_opcD3_word_RM_CL,
5438 /* 0xd4 */ i86op_aam,
5439 /* 0xd5 */ i86op_aad,
5440 /* 0xd6 */ i86op_illegal_op,
5441 /* 0xd7 */ i86op_xlat,
5442 /* 0xd8 */ i86op_esc_coprocess_d8,
5443 /* 0xd9 */ i86op_esc_coprocess_d9,
5444 /* 0xda */ i86op_esc_coprocess_da,
5445 /* 0xdb */ i86op_esc_coprocess_db,
5446 /* 0xdc */ i86op_esc_coprocess_dc,
5447 /* 0xdd */ i86op_esc_coprocess_dd,
5448 /* 0xde */ i86op_esc_coprocess_de,
5449 /* 0xdf */ i86op_esc_coprocess_df,
5450
5451 /* 0xe0 */ i86op_loopne,
5452 /* 0xe1 */ i86op_loope,
5453 /* 0xe2 */ i86op_loop,
5454 /* 0xe3 */ i86op_jcxz,
5455 /* 0xe4 */ i86op_in_byte_AL_IMM,
5456 /* 0xe5 */ i86op_in_word_AX_IMM,
5457 /* 0xe6 */ i86op_out_byte_IMM_AL,
5458 /* 0xe7 */ i86op_out_word_IMM_AX,
5459
5460 /* 0xe8 */ i86op_call_near_IMM,
5461 /* 0xe9 */ i86op_jump_near_IMM,
5462 /* 0xea */ i86op_jump_far_IMM,
5463 /* 0xeb */ i86op_jump_byte_IMM,
5464 /* 0xec */ i86op_in_byte_AL_DX,
5465 /* 0xed */ i86op_in_word_AX_DX,
5466 /* 0xee */ i86op_out_byte_DX_AL,
5467 /* 0xef */ i86op_out_word_DX_AX,
5468
5469 /* 0xf0 */ i86op_lock,
5470 /* 0xf1 */ i86op_illegal_op,
5471 /* 0xf2 */ i86op_repne,
5472 /* 0xf3 */ i86op_repe,
5473 /* 0xf4 */ i86op_halt,
5474 /* 0xf5 */ i86op_cmc,
5475 /* 0xf6 */ i86op_opcF6_byte_RM,
5476 /* 0xf7 */ i86op_opcF7_word_RM,
5477
5478 /* 0xf8 */ i86op_clc,
5479 /* 0xf9 */ i86op_stc,
5480 /* 0xfa */ i86op_cli,
5481 /* 0xfb */ i86op_sti,
5482 /* 0xfc */ i86op_cld,
5483 /* 0xfd */ i86op_std,
5484 /* 0xfe */ i86op_opcFE_byte_RM,
5485 /* 0xff */ i86op_opcFF_word_RM,
5486
5487 };