[SOFTX86]
[reactos.git] / lib / 3rdparty / softx86 / softx86 / groupies.c
1 /*
2 * groupies.c
3 *
4 * Copyright (C) 2003, 2004 Jonathan Campbell <jcampbell@mdjk.com>
5 *
6 * Decompiler and executioneer for instruction opcodes grouped by a common
7 * opcode and specified by the reg portion of the mod/reg/rm byte.
8 *
9 ***********************************************************************************
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 ************************************************************************************/
24
25 #include <softx86.h>
26 #include <memory.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include "groupies.h"
30 #include "optable.h"
31 #include "binops.h"
32 #include "add.h"
33 #include "mov.h"
34 #include "inc.h"
35
36 sx86_uword op_ncall16(softx86_ctx* ctx,sx86_uword src)
37 {
38 softx86_stack_pushw(ctx,ctx->state->reg_ip);
39 softx86_set_near_instruction_ptr(ctx,src);
40 return src;
41 }
42
43 sx86_udword op_ncall32(softx86_ctx* ctx,sx86_udword src)
44 {
45 softx86_stack_pushw(ctx,(ctx->state->reg_ip>>16)&0xFFFF);
46 softx86_stack_pushw(ctx,ctx->state->reg_ip&0xFFFF);
47 softx86_set_near_instruction_ptr(ctx,src);
48 return src;
49 }
50
51 sx86_uword op_popmem16(softx86_ctx* ctx)
52 {
53 return softx86_stack_popw(ctx);
54 }
55
56 sx86_udword op_popmem32(softx86_ctx* ctx)
57 {
58 sx86_udword d;
59
60 d = ((sx86_udword)softx86_stack_popw(ctx));
61 d |= ((sx86_udword)softx86_stack_popw(ctx))<<16;
62 return d;
63 }
64
65 sx86_uword op_pushmem16(softx86_ctx* ctx,sx86_uword src)
66 {
67 softx86_stack_pushw(ctx,src);
68 return src;
69 }
70
71 sx86_udword op_pushmem32(softx86_ctx* ctx,sx86_udword src)
72 {
73 softx86_stack_pushw(ctx,(src>>16)&0xFFFF);
74 softx86_stack_pushw(ctx,src&0xFFFF);
75 return src;
76 }
77
78 sx86_uword op_njmp16(softx86_ctx* ctx,sx86_uword src)
79 {
80 softx86_set_near_instruction_ptr(ctx,src);
81 return src;
82 }
83
84 sx86_udword op_njmp32(softx86_ctx* ctx,sx86_udword src)
85 {
86 softx86_set_near_instruction_ptr(ctx,src);
87 return src;
88 }
89
90 void op_fcall16(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs)
91 {
92 softx86_stack_pushw(ctx,ctx->state->segment_reg[SX86_SREG_CS].val);
93 softx86_stack_pushw(ctx,ctx->state->reg_ip);
94 softx86_set_instruction_ptr(ctx,seg,ofs);
95 }
96
97 void op_fcall32(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs)
98 {
99 softx86_stack_pushw(ctx,ctx->state->segment_reg[SX86_SREG_CS].val);
100 softx86_stack_pushw(ctx,ctx->state->reg_ip&0xFFFF);
101 softx86_stack_pushw(ctx,(ctx->state->reg_ip>>16)&0xFFFF);
102 softx86_set_instruction_ptr(ctx,seg,ofs);
103 }
104
105 void op_fjmp16(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs)
106 {
107 softx86_set_instruction_ptr(ctx,seg,ofs);
108 }
109
110 void op_fjmp32(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs)
111 {
112 softx86_set_instruction_ptr(ctx,seg,ofs);
113 }
114
115 int Sfx86OpcodeExec_group80(sx86_ubyte opcode,softx86_ctx* ctx)
116 {
117 if ((opcode&0xFC) == 0x80) {
118 sx86_ubyte x;
119 sx86_ubyte w16,sx;
120 sx86_ubyte mod,reg,rm;
121 sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val);
122 sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val);
123 sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val);
124
125 w16 = opcode&1;
126 sx = (opcode>>1)&1;
127 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
128 sx86_modregrm_unpack(x,mod,reg,rm);
129
130 if (reg == 0) {
131 op8 = op_add8;
132 op16 = op_add16;
133 op32 = op_add32;
134 }
135 else if (reg == 1) {
136 op8 = op_or8;
137 op16 = op_or16;
138 op32 = op_or32;
139 }
140 else if (reg == 2) {
141 op8 = op_adc8;
142 op16 = op_adc16;
143 op32 = op_adc32;
144 }
145 else if (reg == 3) {
146 op8 = op_sbb8;
147 op16 = op_sbb16;
148 op32 = op_sbb32;
149 }
150 else if (reg == 4) {
151 op8 = op_and8;
152 op16 = op_and16;
153 op32 = op_and32;
154 }
155 else if (reg == 5) {
156 op8 = op_sub8;
157 op16 = op_sub16;
158 op32 = op_sub32;
159 }
160 else if (reg == 6) {
161 op8 = op_xor8;
162 op16 = op_xor16;
163 op32 = op_xor32;
164 }
165 else if (reg == 7) {
166 op8 = op_sub8; /* CMP is like SUB except that the result */
167 op16 = op_sub16; /* ends up in a temporary register, leaving */
168 op32 = op_sub32; /* the original data untouched. */
169 }
170 else {
171 return 0;
172 }
173
174 if (reg == 7) /* CMP doesn't modify the dest. register... */
175 sx86_exec_full_modrmonly_ro_imm(ctx,w16,0,mod,rm,op8,op16,op32,sx);
176 else
177 sx86_exec_full_modrmonly_rw_imm(ctx,w16,0,mod,rm,op8,op16,op32,sx);
178
179 return 1;
180 }
181
182 return 0;
183 }
184
185 int Sfx86OpcodeDec_group80(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
186 {
187 if ((opcode&0xFC) == 0x80) {
188 sx86_ubyte x;
189 sx86_ubyte w16,sx;
190 sx86_ubyte mod,reg,rm;
191 sx86_uword imm16;
192
193 w16 = opcode&1;
194 sx = (opcode>>1)&1;
195 x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm
196 sx86_modregrm_unpack(x,mod,reg,rm);
197 sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp);
198
199 imm16 = softx86_fetch_dec_byte(ctx);
200 if (w16)
201 {
202 if (sx)
203 imm16 |= (imm16&0x80) ? 0xFF80 : 0;
204 else
205 imm16 |= softx86_fetch_dec_byte(ctx)<<8;
206 }
207
208 if (reg == 0) sprintf(buf,"ADD %s,%04Xh",op1_tmp,imm16);
209 else if (reg == 1) sprintf(buf,"OR %s,%04Xh",op1_tmp,imm16);
210 else if (reg == 2) sprintf(buf,"ADC %s,%04Xh",op1_tmp,imm16);
211 else if (reg == 3) sprintf(buf,"SBB %s,%04Xh",op1_tmp,imm16);
212 else if (reg == 4) sprintf(buf,"AND %s,%04Xh",op1_tmp,imm16);
213 else if (reg == 5) sprintf(buf,"SUB %s,%04Xh",op1_tmp,imm16);
214 else if (reg == 6) sprintf(buf,"XOR %s,%04Xh",op1_tmp,imm16);
215 else if (reg == 7) sprintf(buf,"CMP %s,%04Xh",op1_tmp,imm16);
216 else return 0;
217
218 return 1;
219 }
220
221 return 0;
222 }
223
224 int Sfx86OpcodeExec_groupC0(sx86_ubyte opcode,softx86_ctx* ctx)
225 {
226 if ((opcode&0xFE) == 0xC0) {
227 sx86_ubyte x;
228 sx86_ubyte w16;
229 sx86_ubyte mod,reg,rm;
230 sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val);
231 sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val);
232 sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val);
233
234 w16 = (opcode&1);
235 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
236 sx86_modregrm_unpack(x,mod,reg,rm);
237
238 if (reg == 0) {
239 op8 = op_rol8;
240 op16 = op_rol16;
241 op32 = op_rol32;
242 }
243 else if (reg == 1) {
244 op8 = op_ror8;
245 op16 = op_ror16;
246 op32 = op_ror32;
247 }
248 else if (reg == 2) {
249 op8 = op_rcl8;
250 op16 = op_rcl16;
251 op32 = op_rcl32;
252 }
253 else if (reg == 3) {
254 op8 = op_rcr8;
255 op16 = op_rcr16;
256 op32 = op_rcr32;
257 }
258 else if (reg == 4) {
259 op8 = op_shl8;
260 op16 = op_shl16;
261 op32 = op_shl32;
262 }
263 else if (reg == 5) {
264 op8 = op_shr8;
265 op16 = op_shr16;
266 op32 = op_shr32;
267 }
268 else if (reg == 7) {
269 op8 = op_sar8;
270 op16 = op_sar16;
271 op32 = op_sar32;
272 }
273 else {
274 return 0;
275 }
276
277 sx86_exec_full_modrmonly_rw_imm8(ctx,w16,0,mod,rm,op8,op16,op32);
278 return 1;
279 }
280
281 return 0;
282 }
283
284 int Sfx86OpcodeDec_groupC0(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
285 {
286 if ((opcode&0xFE) == 0xC0) {
287 sx86_ubyte x;
288 sx86_ubyte w16;
289 sx86_ubyte mod,reg,rm;
290 sx86_uword imm16;
291
292 w16 = (opcode&1);
293 x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm
294 sx86_modregrm_unpack(x,mod,reg,rm);
295 sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp);
296
297 imm16 = softx86_fetch_dec_byte(ctx);
298
299 if (reg == 0) sprintf(buf,"ROL %s,%04Xh",op1_tmp,imm16);
300 else if (reg == 1) sprintf(buf,"ROR %s,%04Xh",op1_tmp,imm16);
301 else if (reg == 2) sprintf(buf,"RCL %s,%04Xh",op1_tmp,imm16);
302 else if (reg == 3) sprintf(buf,"RCR %s,%04Xh",op1_tmp,imm16);
303 else if (reg == 4) sprintf(buf,"SHL %s,%04Xh",op1_tmp,imm16);
304 else if (reg == 5) sprintf(buf,"SHR %s,%04Xh",op1_tmp,imm16);
305 else if (reg == 7) sprintf(buf,"SAR %s,%04Xh",op1_tmp,imm16);
306 else return 0;
307
308 return 1;
309 }
310
311 return 0;
312 }
313
314 int Sfx86OpcodeExec_groupD0(sx86_ubyte opcode,softx86_ctx* ctx)
315 {
316 if ((opcode&0xFE) == 0xD0 || (opcode&0xFE) == 0xD2) {
317 sx86_ubyte x;
318 sx86_ubyte w16;
319 sx86_ubyte mod,reg,rm;
320 sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src);
321 sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src);
322 sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src);
323
324 w16 = (opcode&1);
325 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
326 sx86_modregrm_unpack(x,mod,reg,rm);
327
328 if (reg == 0) {
329 if ((opcode&0xFE) == 0xD2) {
330 op8 = op_rol_cl_8;
331 op16 = op_rol_cl_16;
332 op32 = op_rol_cl_32;
333 }
334 else {
335 op8 = op_rol1_8;
336 op16 = op_rol1_16;
337 op32 = op_rol1_32;
338 }
339 }
340 else if (reg == 1) {
341 if ((opcode&0xFE) == 0xD2) {
342 op8 = op_ror_cl_8;
343 op16 = op_ror_cl_16;
344 op32 = op_ror_cl_32;
345 }
346 else {
347 op8 = op_ror1_8;
348 op16 = op_ror1_16;
349 op32 = op_ror1_32;
350 }
351 }
352 else if (reg == 2) {
353 if ((opcode&0xFE) == 0xD2) {
354 op8 = op_rcl_cl_8;
355 op16 = op_rcl_cl_16;
356 op32 = op_rcl_cl_32;
357 }
358 else {
359 op8 = op_rcl1_8;
360 op16 = op_rcl1_16;
361 op32 = op_rcl1_32;
362 }
363 }
364 else if (reg == 3) {
365 if ((opcode&0xFE) == 0xD2) {
366 op8 = op_rcr_cl_8;
367 op16 = op_rcr_cl_16;
368 op32 = op_rcr_cl_32;
369 }
370 else {
371 op8 = op_rcr1_8;
372 op16 = op_rcr1_16;
373 op32 = op_rcr1_32;
374 }
375 }
376 else if (reg == 4) {
377 if ((opcode&0xFE) == 0xD2) {
378 op8 = op_shl_cl_8;
379 op16 = op_shl_cl_16;
380 op32 = op_shl_cl_32;
381 }
382 else {
383 op8 = op_shl1_8;
384 op16 = op_shl1_16;
385 op32 = op_shl1_32;
386 }
387 }
388 else if (reg == 5) {
389 if ((opcode&0xFE) == 0xD2) {
390 op8 = op_shr_cl_8;
391 op16 = op_shr_cl_16;
392 op32 = op_shr_cl_32;
393 }
394 else {
395 op8 = op_shr1_8;
396 op16 = op_shr1_16;
397 op32 = op_shr1_32;
398 }
399 }
400 else if (reg == 7) {
401 if ((opcode&0xFE) == 0xD2) {
402 op8 = op_sar_cl_8;
403 op16 = op_sar_cl_16;
404 op32 = op_sar_cl_32;
405 }
406 else {
407 op8 = op_sar1_8;
408 op16 = op_sar1_16;
409 op32 = op_sar1_32;
410 }
411 }
412 else {
413 return 0;
414 }
415
416 sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op8,op16,op32);
417 return 1;
418 }
419
420 return 0;
421 }
422
423 int Sfx86OpcodeDec_groupD0(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
424 {
425 if ((opcode&0xFE) == 0xD0 || (opcode&0xFE) == 0xD2) {
426 sx86_ubyte x;
427 sx86_ubyte w16;
428 sx86_ubyte mod,reg,rm;
429
430 w16 = (opcode&1);
431 x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm
432 sx86_modregrm_unpack(x,mod,reg,rm);
433 sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp);
434
435 if ((opcode&0xFE) == 0xD2) {
436 if (reg == 0) sprintf(buf,"ROL %s,CL",op1_tmp);
437 else if (reg == 1) sprintf(buf,"ROR %s,CL",op1_tmp);
438 else if (reg == 2) sprintf(buf,"RCL %s,CL",op1_tmp);
439 else if (reg == 3) sprintf(buf,"RCR %s,CL",op1_tmp);
440 else if (reg == 4) sprintf(buf,"SHL %s,CL",op1_tmp);
441 else if (reg == 5) sprintf(buf,"SHR %s,CL",op1_tmp);
442 else if (reg == 7) sprintf(buf,"SAR %s,CL",op1_tmp);
443 else return 0;
444 }
445 else {
446 if (reg == 0) sprintf(buf,"ROL %s,1",op1_tmp);
447 else if (reg == 1) sprintf(buf,"ROR %s,1",op1_tmp);
448 else if (reg == 2) sprintf(buf,"RCL %s,1",op1_tmp);
449 else if (reg == 3) sprintf(buf,"RCR %s,1",op1_tmp);
450 else if (reg == 4) sprintf(buf,"SHL %s,1",op1_tmp);
451 else if (reg == 5) sprintf(buf,"SHR %s,1",op1_tmp);
452 else if (reg == 7) sprintf(buf,"SAR %s,1",op1_tmp);
453 else return 0;
454 }
455
456 return 1;
457 }
458
459 return 0;
460 }
461
462 int Sfx86OpcodeExec_groupC6(sx86_ubyte opcode,softx86_ctx* ctx)
463 {
464 if ((opcode&0xFE) == 0xC6) {
465 sx86_ubyte x;
466 sx86_ubyte w16;
467 sx86_ubyte mod,reg,rm;
468 sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val);
469 sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val);
470 sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val);
471
472 w16 = (opcode&1);
473 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
474 sx86_modregrm_unpack(x,mod,reg,rm);
475
476 if (reg == 0) {
477 op8 = op_mov8;
478 op16 = op_mov16;
479 op32 = op_mov32;
480 }
481 else {
482 return 0;
483 }
484
485 sx86_exec_full_modrmonly_rw_imm(ctx,w16,0,mod,rm,op8,op16,op32,0);
486 return 1;
487 }
488
489 return 0;
490 }
491
492 int Sfx86OpcodeDec_groupC6(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
493 {
494 if ((opcode&0xFE) == 0xC6) {
495 sx86_ubyte x;
496 sx86_ubyte w16;
497 sx86_ubyte mod,reg,rm;
498 sx86_uword imm16;
499
500 w16 = (opcode&1);
501 x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm
502 sx86_modregrm_unpack(x,mod,reg,rm);
503 sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp);
504
505 imm16 = softx86_fetch_dec_byte(ctx);
506 if (w16) imm16 |= softx86_fetch_dec_byte(ctx)<<8;
507
508 if (reg == 0) sprintf(buf,"MOV %s,%04Xh",op1_tmp,imm16);
509 else return 0;
510
511 return 1;
512 }
513
514 return 0;
515 }
516
517 int Sfx86OpcodeExec_groupFE(sx86_ubyte opcode,softx86_ctx* ctx)
518 {
519 if ((opcode&0xFE) == 0xFE) {
520 sx86_ubyte x;
521 sx86_ubyte w16;
522 sx86_ubyte mod,reg,rm;
523
524 w16 = (opcode&1);
525 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
526 sx86_modregrm_unpack(x,mod,reg,rm);
527
528 if (reg == 0) {
529 sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op_inc8,op_inc16,op_inc32);
530 }
531 else if (reg == 1) {
532 sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op_dec8,op_dec16,op_dec32);
533 }
534 else if (reg >= 2) {
535 if (!w16) return 0;
536
537 if (reg == 3 || reg == 5) {
538 void (*op16)(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs);
539 void (*op32)(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs);
540
541 /* you cannot have a far address in registers */
542 if (mod == 3)
543 return 0;
544
545 if (reg == 3) {
546 op16 = op_fcall16;
547 op32 = op_fcall32;
548 }
549 else if (reg == 5) {
550 op16 = op_fjmp16;
551 op32 = op_fjmp32;
552 }
553
554 sx86_exec_full_modrmonly_callfar(ctx,0,mod,rm,op16,op32);
555 }
556 else {
557 sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src);
558 sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src);
559
560 if (reg == 2) {
561 op16 = op_ncall16;
562 op32 = op_ncall32;
563 }
564 else if (reg == 4) {
565 op16 = op_njmp16;
566 op32 = op_njmp32;
567 }
568 else if (reg == 6) {
569 op16 = op_pushmem16;
570 op32 = op_pushmem32;
571 }
572 else {
573 return 0;
574 }
575
576 sx86_exec_full_modrmonly_ro(ctx,1,0,mod,rm,NULL,op16,op32);
577 }
578 }
579
580 return 1;
581 }
582
583 return 0;
584 }
585
586 int Sfx86OpcodeDec_groupFE(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
587 {
588 if ((opcode&0xFE) == 0xFE) {
589 sx86_ubyte x;
590 sx86_ubyte w16;
591 sx86_ubyte mod,reg,rm;
592
593 w16 = (opcode&1);
594 x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm
595 sx86_modregrm_unpack(x,mod,reg,rm);
596 sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp);
597
598 if (reg == 0) sprintf(buf,"INC %s",op1_tmp);
599 else if (reg == 1) sprintf(buf,"DEC %s",op1_tmp);
600 else {
601 if (!w16)
602 return 0;
603 if (reg == 2)
604 sprintf(buf,"CALL %s",op1_tmp);
605 else if (reg == 3)
606 sprintf(buf,"CALL FAR %s",op1_tmp);
607 else if (reg == 4)
608 sprintf(buf,"JMP %s",op1_tmp);
609 else if (reg == 5)
610 sprintf(buf,"JMP FAR %s",op1_tmp);
611 else if (reg == 6)
612 sprintf(buf,"PUSH %s",op1_tmp);
613 else
614 return 0;
615 }
616
617 return 1;
618 }
619
620 return 0;
621 }
622
623 int Sfx86OpcodeExec_group8F(sx86_ubyte opcode,softx86_ctx* ctx)
624 {
625 if (opcode == 0x8F) {
626 sx86_ubyte x,mod,reg,rm;
627 sx86_uword (*op16)(softx86_ctx* ctx);
628 sx86_udword (*op32)(softx86_ctx* ctx);
629
630 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
631 sx86_modregrm_unpack(x,mod,reg,rm);
632
633 if (reg == 0) {
634 op16 = op_popmem16;
635 op32 = op_popmem32;
636 }
637 else {
638 return 0;
639 }
640
641 sx86_exec_full_modrmonly_wo(ctx,1,0,mod,rm,NULL,op16,op32);
642 return 1;
643 }
644
645 return 0;
646 }
647
648 int Sfx86OpcodeDec_group8F(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
649 {
650 if (opcode == 0x8F) {
651 sx86_ubyte x;
652 sx86_ubyte mod,reg,rm;
653
654 x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm
655 sx86_modregrm_unpack(x,mod,reg,rm);
656 sx86_dec_full_modrmonly(ctx,1,0,mod,rm,op1_tmp);
657
658 if (reg == 0) sprintf(buf,"POP %s",op1_tmp);
659 else return 0;
660
661 return 1;
662 }
663
664 return 0;
665 }
666
667 int Sfx86OpcodeExec_groupF6(sx86_ubyte opcode,softx86_ctx* ctx)
668 {
669 if ((opcode&0xFE) == 0xF6) {
670 sx86_ubyte x;
671 sx86_ubyte w16;
672 sx86_ubyte mod,reg,rm;
673 sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src);
674 sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src);
675 sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src);
676
677 w16 = (opcode&1);
678 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
679 sx86_modregrm_unpack(x,mod,reg,rm);
680
681 if (reg == 0) {
682 /* taken care of later */
683 }
684 else if (reg == 2) {
685 /* taken care of later */
686 }
687 else if (reg == 3) {
688 /* taken care of later */
689 }
690 else if (reg == 4) {
691 op8 = op_mul8;
692 op16 = op_mul16;
693 op32 = op_mul32;
694 }
695 else if (reg == 5) {
696 op8 = op_imul8;
697 op16 = op_imul16;
698 op32 = op_imul32;
699 }
700 else if (reg == 6) {
701 op8 = op_div8;
702 op16 = op_div16;
703 op32 = op_div32;
704 }
705 else if (reg == 7) {
706 op8 = op_idiv8; /* CMP is like SUB except that the result */
707 op16 = op_idiv16; /* ends up in a temporary register, leaving */
708 op32 = op_idiv32; /* the original data untouched. */
709 }
710 else {
711 return 0;
712 }
713
714 /* TEST does not modify the dest. register... */
715 if (reg == 0)
716 sx86_exec_full_modrmonly_ro_imm(ctx,w16,0,mod,rm,op_test8,op_test16,op_test32,0);
717 /* NOT and NEG only have one operand */
718 else if (reg == 2)
719 sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op_not8,op_not16,op_not32);
720 else if (reg == 3)
721 sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op_neg8,op_neg16,op_neg32);
722 /* everybody else (MUL/IMUL/DIV/IDIV) has one operand but modifies (E)AX */
723 else
724 sx86_exec_full_modrmonly_ro(ctx,w16,0,mod,rm,op8,op16,op32);
725
726 return 1;
727 }
728
729 return 0;
730 }
731
732 int Sfx86OpcodeDec_groupF6(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
733 {
734 if ((opcode&0xFE) == 0xF6) {
735 sx86_ubyte x;
736 sx86_ubyte w16;
737 sx86_ubyte mod,reg,rm;
738 sx86_uword imm16;
739
740 w16 = (opcode&1);
741 x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm
742 sx86_modregrm_unpack(x,mod,reg,rm);
743 sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp);
744
745 if (reg == 0) {
746 imm16 = softx86_fetch_dec_byte(ctx);
747 if (w16) imm16 |= softx86_fetch_dec_byte(ctx)<<8;
748 }
749
750 if (reg == 0) sprintf(buf,"TEST %s,%04Xh",op1_tmp,imm16);
751 else if (reg == 2) sprintf(buf,"NOT %s",op1_tmp);
752 else if (reg == 3) sprintf(buf,"NEG %s",op1_tmp);
753 else if (reg == 4) sprintf(buf,"MUL %s",op1_tmp);
754 else if (reg == 5) sprintf(buf,"IMUL %s",op1_tmp);
755 else if (reg == 6) sprintf(buf,"DIV %s",op1_tmp);
756 else if (reg == 7) sprintf(buf,"IDIV %s",op1_tmp);
757 else return 0;
758
759 return 1;
760 }
761
762 return 0;
763 }
764