cbeb73cf1b3b42aa78f15d2b34c3da7040aeb6e2
[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 if (sx)
202 imm16 |= (imm16&0x80) ? 0xFF80 : 0;
203 else
204 imm16 |= softx86_fetch_dec_byte(ctx)<<8;
205
206 if (reg == 0) sprintf(buf,"ADD %s,%04Xh",op1_tmp,imm16);
207 else if (reg == 1) sprintf(buf,"OR %s,%04Xh",op1_tmp,imm16);
208 else if (reg == 2) sprintf(buf,"ADC %s,%04Xh",op1_tmp,imm16);
209 else if (reg == 3) sprintf(buf,"SBB %s,%04Xh",op1_tmp,imm16);
210 else if (reg == 4) sprintf(buf,"AND %s,%04Xh",op1_tmp,imm16);
211 else if (reg == 5) sprintf(buf,"SUB %s,%04Xh",op1_tmp,imm16);
212 else if (reg == 6) sprintf(buf,"XOR %s,%04Xh",op1_tmp,imm16);
213 else if (reg == 7) sprintf(buf,"CMP %s,%04Xh",op1_tmp,imm16);
214 else return 0;
215
216 return 1;
217 }
218
219 return 0;
220 }
221
222 int Sfx86OpcodeExec_groupC0(sx86_ubyte opcode,softx86_ctx* ctx)
223 {
224 if ((opcode&0xFE) == 0xC0) {
225 sx86_ubyte x;
226 sx86_ubyte w16;
227 sx86_ubyte mod,reg,rm;
228 sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val);
229 sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val);
230 sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val);
231
232 w16 = (opcode&1);
233 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
234 sx86_modregrm_unpack(x,mod,reg,rm);
235
236 if (reg == 0) {
237 op8 = op_rol8;
238 op16 = op_rol16;
239 op32 = op_rol32;
240 }
241 else if (reg == 1) {
242 op8 = op_ror8;
243 op16 = op_ror16;
244 op32 = op_ror32;
245 }
246 else if (reg == 2) {
247 op8 = op_rcl8;
248 op16 = op_rcl16;
249 op32 = op_rcl32;
250 }
251 else if (reg == 3) {
252 op8 = op_rcr8;
253 op16 = op_rcr16;
254 op32 = op_rcr32;
255 }
256 else if (reg == 4) {
257 op8 = op_shl8;
258 op16 = op_shl16;
259 op32 = op_shl32;
260 }
261 else if (reg == 5) {
262 op8 = op_shr8;
263 op16 = op_shr16;
264 op32 = op_shr32;
265 }
266 else if (reg == 7) {
267 op8 = op_sar8;
268 op16 = op_sar16;
269 op32 = op_sar32;
270 }
271 else {
272 return 0;
273 }
274
275 sx86_exec_full_modrmonly_rw_imm8(ctx,w16,0,mod,rm,op8,op16,op32);
276 return 1;
277 }
278
279 return 0;
280 }
281
282 int Sfx86OpcodeDec_groupC0(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
283 {
284 if ((opcode&0xFE) == 0xC0) {
285 sx86_ubyte x;
286 sx86_ubyte w16;
287 sx86_ubyte mod,reg,rm;
288 sx86_uword imm16;
289
290 w16 = (opcode&1);
291 x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm
292 sx86_modregrm_unpack(x,mod,reg,rm);
293 sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp);
294
295 imm16 = softx86_fetch_dec_byte(ctx);
296
297 if (reg == 0) sprintf(buf,"ROL %s,%04Xh",op1_tmp,imm16);
298 else if (reg == 1) sprintf(buf,"ROR %s,%04Xh",op1_tmp,imm16);
299 else if (reg == 2) sprintf(buf,"RCL %s,%04Xh",op1_tmp,imm16);
300 else if (reg == 3) sprintf(buf,"RCR %s,%04Xh",op1_tmp,imm16);
301 else if (reg == 4) sprintf(buf,"SHL %s,%04Xh",op1_tmp,imm16);
302 else if (reg == 5) sprintf(buf,"SHR %s,%04Xh",op1_tmp,imm16);
303 else if (reg == 7) sprintf(buf,"SAR %s,%04Xh",op1_tmp,imm16);
304 else return 0;
305
306 return 1;
307 }
308
309 return 0;
310 }
311
312 int Sfx86OpcodeExec_groupD0(sx86_ubyte opcode,softx86_ctx* ctx)
313 {
314 if ((opcode&0xFE) == 0xD0 || (opcode&0xFE) == 0xD2) {
315 sx86_ubyte x;
316 sx86_ubyte w16;
317 sx86_ubyte mod,reg,rm;
318 sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src);
319 sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src);
320 sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src);
321
322 w16 = (opcode&1);
323 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
324 sx86_modregrm_unpack(x,mod,reg,rm);
325
326 if (reg == 0) {
327 if ((opcode&0xFE) == 0xD2) {
328 op8 = op_rol_cl_8;
329 op16 = op_rol_cl_16;
330 op32 = op_rol_cl_32;
331 }
332 else {
333 op8 = op_rol1_8;
334 op16 = op_rol1_16;
335 op32 = op_rol1_32;
336 }
337 }
338 else if (reg == 1) {
339 if ((opcode&0xFE) == 0xD2) {
340 op8 = op_ror_cl_8;
341 op16 = op_ror_cl_16;
342 op32 = op_ror_cl_32;
343 }
344 else {
345 op8 = op_ror1_8;
346 op16 = op_ror1_16;
347 op32 = op_ror1_32;
348 }
349 }
350 else if (reg == 2) {
351 if ((opcode&0xFE) == 0xD2) {
352 op8 = op_rcl_cl_8;
353 op16 = op_rcl_cl_16;
354 op32 = op_rcl_cl_32;
355 }
356 else {
357 op8 = op_rcl1_8;
358 op16 = op_rcl1_16;
359 op32 = op_rcl1_32;
360 }
361 }
362 else if (reg == 3) {
363 if ((opcode&0xFE) == 0xD2) {
364 op8 = op_rcr_cl_8;
365 op16 = op_rcr_cl_16;
366 op32 = op_rcr_cl_32;
367 }
368 else {
369 op8 = op_rcr1_8;
370 op16 = op_rcr1_16;
371 op32 = op_rcr1_32;
372 }
373 }
374 else if (reg == 4) {
375 if ((opcode&0xFE) == 0xD2) {
376 op8 = op_shl_cl_8;
377 op16 = op_shl_cl_16;
378 op32 = op_shl_cl_32;
379 }
380 else {
381 op8 = op_shl1_8;
382 op16 = op_shl1_16;
383 op32 = op_shl1_32;
384 }
385 }
386 else if (reg == 5) {
387 if ((opcode&0xFE) == 0xD2) {
388 op8 = op_shr_cl_8;
389 op16 = op_shr_cl_16;
390 op32 = op_shr_cl_32;
391 }
392 else {
393 op8 = op_shr1_8;
394 op16 = op_shr1_16;
395 op32 = op_shr1_32;
396 }
397 }
398 else if (reg == 7) {
399 if ((opcode&0xFE) == 0xD2) {
400 op8 = op_sar_cl_8;
401 op16 = op_sar_cl_16;
402 op32 = op_sar_cl_32;
403 }
404 else {
405 op8 = op_sar1_8;
406 op16 = op_sar1_16;
407 op32 = op_sar1_32;
408 }
409 }
410 else {
411 return 0;
412 }
413
414 sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op8,op16,op32);
415 return 1;
416 }
417
418 return 0;
419 }
420
421 int Sfx86OpcodeDec_groupD0(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
422 {
423 if ((opcode&0xFE) == 0xD0 || (opcode&0xFE) == 0xD2) {
424 sx86_ubyte x;
425 sx86_ubyte w16;
426 sx86_ubyte mod,reg,rm;
427
428 w16 = (opcode&1);
429 x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm
430 sx86_modregrm_unpack(x,mod,reg,rm);
431 sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp);
432
433 if ((opcode&0xFE) == 0xD2) {
434 if (reg == 0) sprintf(buf,"ROL %s,CL",op1_tmp);
435 else if (reg == 1) sprintf(buf,"ROR %s,CL",op1_tmp);
436 else if (reg == 2) sprintf(buf,"RCL %s,CL",op1_tmp);
437 else if (reg == 3) sprintf(buf,"RCR %s,CL",op1_tmp);
438 else if (reg == 4) sprintf(buf,"SHL %s,CL",op1_tmp);
439 else if (reg == 5) sprintf(buf,"SHR %s,CL",op1_tmp);
440 else if (reg == 7) sprintf(buf,"SAR %s,CL",op1_tmp);
441 else return 0;
442 }
443 else {
444 if (reg == 0) sprintf(buf,"ROL %s,1",op1_tmp);
445 else if (reg == 1) sprintf(buf,"ROR %s,1",op1_tmp);
446 else if (reg == 2) sprintf(buf,"RCL %s,1",op1_tmp);
447 else if (reg == 3) sprintf(buf,"RCR %s,1",op1_tmp);
448 else if (reg == 4) sprintf(buf,"SHL %s,1",op1_tmp);
449 else if (reg == 5) sprintf(buf,"SHR %s,1",op1_tmp);
450 else if (reg == 7) sprintf(buf,"SAR %s,1",op1_tmp);
451 else return 0;
452 }
453
454 return 1;
455 }
456
457 return 0;
458 }
459
460 int Sfx86OpcodeExec_groupC6(sx86_ubyte opcode,softx86_ctx* ctx)
461 {
462 if ((opcode&0xFE) == 0xC6) {
463 sx86_ubyte x;
464 sx86_ubyte w16;
465 sx86_ubyte mod,reg,rm;
466 sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val);
467 sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val);
468 sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val);
469
470 w16 = (opcode&1);
471 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
472 sx86_modregrm_unpack(x,mod,reg,rm);
473
474 if (reg == 0) {
475 op8 = op_mov8;
476 op16 = op_mov16;
477 op32 = op_mov32;
478 }
479 else {
480 return 0;
481 }
482
483 sx86_exec_full_modrmonly_rw_imm(ctx,w16,0,mod,rm,op8,op16,op32,0);
484 return 1;
485 }
486
487 return 0;
488 }
489
490 int Sfx86OpcodeDec_groupC6(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
491 {
492 if ((opcode&0xFE) == 0xC6) {
493 sx86_ubyte x;
494 sx86_ubyte w16;
495 sx86_ubyte mod,reg,rm;
496 sx86_uword imm16;
497
498 w16 = (opcode&1);
499 x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm
500 sx86_modregrm_unpack(x,mod,reg,rm);
501 sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp);
502
503 imm16 = softx86_fetch_dec_byte(ctx);
504 if (w16) imm16 |= softx86_fetch_dec_byte(ctx)<<8;
505
506 if (reg == 0) sprintf(buf,"MOV %s,%04Xh",op1_tmp,imm16);
507 else return 0;
508
509 return 1;
510 }
511
512 return 0;
513 }
514
515 int Sfx86OpcodeExec_groupFE(sx86_ubyte opcode,softx86_ctx* ctx)
516 {
517 if ((opcode&0xFE) == 0xFE) {
518 sx86_ubyte x;
519 sx86_ubyte w16;
520 sx86_ubyte mod,reg,rm;
521
522 w16 = (opcode&1);
523 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
524 sx86_modregrm_unpack(x,mod,reg,rm);
525
526 if (reg == 0) {
527 sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op_inc8,op_inc16,op_inc32);
528 }
529 else if (reg == 1) {
530 sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op_dec8,op_dec16,op_dec32);
531 }
532 else if (reg >= 2) {
533 if (!w16) return 0;
534
535 if (reg == 3 || reg == 5) {
536 void (*op16)(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs);
537 void (*op32)(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs);
538
539 /* you cannot have a far address in registers */
540 if (mod == 3)
541 return 0;
542
543 if (reg == 3) {
544 op16 = op_fcall16;
545 op32 = op_fcall32;
546 }
547 else if (reg == 5) {
548 op16 = op_fjmp16;
549 op32 = op_fjmp32;
550 }
551
552 sx86_exec_full_modrmonly_callfar(ctx,0,mod,rm,op16,op32);
553 }
554 else {
555 sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src);
556 sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src);
557
558 if (reg == 2) {
559 op16 = op_ncall16;
560 op32 = op_ncall32;
561 }
562 else if (reg == 4) {
563 op16 = op_njmp16;
564 op32 = op_njmp32;
565 }
566 else if (reg == 6) {
567 op16 = op_pushmem16;
568 op32 = op_pushmem32;
569 }
570 else {
571 return 0;
572 }
573
574 sx86_exec_full_modrmonly_ro(ctx,1,0,mod,rm,NULL,op16,op32);
575 }
576 }
577
578 return 1;
579 }
580
581 return 0;
582 }
583
584 int Sfx86OpcodeDec_groupFE(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
585 {
586 if ((opcode&0xFE) == 0xFE) {
587 sx86_ubyte x;
588 sx86_ubyte w16;
589 sx86_ubyte mod,reg,rm;
590
591 w16 = (opcode&1);
592 x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm
593 sx86_modregrm_unpack(x,mod,reg,rm);
594 sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp);
595
596 if (reg == 0) sprintf(buf,"INC %s",op1_tmp);
597 else if (reg == 1) sprintf(buf,"DEC %s",op1_tmp);
598 else {
599 if (!w16)
600 return 0;
601 if (reg == 2)
602 sprintf(buf,"CALL %s",op1_tmp);
603 else if (reg == 3)
604 sprintf(buf,"CALL FAR %s",op1_tmp);
605 else if (reg == 4)
606 sprintf(buf,"JMP %s",op1_tmp);
607 else if (reg == 5)
608 sprintf(buf,"JMP FAR %s",op1_tmp);
609 else if (reg == 6)
610 sprintf(buf,"PUSH %s",op1_tmp);
611 else
612 return 0;
613 }
614
615 return 1;
616 }
617
618 return 0;
619 }
620
621 int Sfx86OpcodeExec_group8F(sx86_ubyte opcode,softx86_ctx* ctx)
622 {
623 if (opcode == 0x8F) {
624 sx86_ubyte x,mod,reg,rm;
625 sx86_uword (*op16)(softx86_ctx* ctx);
626 sx86_udword (*op32)(softx86_ctx* ctx);
627
628 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
629 sx86_modregrm_unpack(x,mod,reg,rm);
630
631 if (reg == 0) {
632 op16 = op_popmem16;
633 op32 = op_popmem32;
634 }
635 else {
636 return 0;
637 }
638
639 sx86_exec_full_modrmonly_wo(ctx,1,0,mod,rm,NULL,op16,op32);
640 return 1;
641 }
642
643 return 0;
644 }
645
646 int Sfx86OpcodeDec_group8F(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
647 {
648 if (opcode == 0x8F) {
649 sx86_ubyte x;
650 sx86_ubyte mod,reg,rm;
651
652 x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm
653 sx86_modregrm_unpack(x,mod,reg,rm);
654 sx86_dec_full_modrmonly(ctx,1,0,mod,rm,op1_tmp);
655
656 if (reg == 0) sprintf(buf,"POP %s",op1_tmp);
657 else return 0;
658
659 return 1;
660 }
661
662 return 0;
663 }
664
665 int Sfx86OpcodeExec_groupF6(sx86_ubyte opcode,softx86_ctx* ctx)
666 {
667 if ((opcode&0xFE) == 0xF6) {
668 sx86_ubyte x;
669 sx86_ubyte w16;
670 sx86_ubyte mod,reg,rm;
671 sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src);
672 sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src);
673 sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src);
674
675 w16 = (opcode&1);
676 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
677 sx86_modregrm_unpack(x,mod,reg,rm);
678
679 if (reg == 0) {
680 /* taken care of later */
681 }
682 else if (reg == 2) {
683 /* taken care of later */
684 }
685 else if (reg == 3) {
686 /* taken care of later */
687 }
688 else if (reg == 4) {
689 op8 = op_mul8;
690 op16 = op_mul16;
691 op32 = op_mul32;
692 }
693 else if (reg == 5) {
694 op8 = op_imul8;
695 op16 = op_imul16;
696 op32 = op_imul32;
697 }
698 else if (reg == 6) {
699 op8 = op_div8;
700 op16 = op_div16;
701 op32 = op_div32;
702 }
703 else if (reg == 7) {
704 op8 = op_idiv8; /* CMP is like SUB except that the result */
705 op16 = op_idiv16; /* ends up in a temporary register, leaving */
706 op32 = op_idiv32; /* the original data untouched. */
707 }
708 else {
709 return 0;
710 }
711
712 /* TEST does not modify the dest. register... */
713 if (reg == 0)
714 sx86_exec_full_modrmonly_ro_imm(ctx,w16,0,mod,rm,op_test8,op_test16,op_test32,0);
715 /* NOT and NEG only have one operand */
716 else if (reg == 2)
717 sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op_not8,op_not16,op_not32);
718 else if (reg == 3)
719 sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op_neg8,op_neg16,op_neg32);
720 /* everybody else (MUL/IMUL/DIV/IDIV) has one operand but modifies (E)AX */
721 else
722 sx86_exec_full_modrmonly_ro(ctx,w16,0,mod,rm,op8,op16,op32);
723
724 return 1;
725 }
726
727 return 0;
728 }
729
730 int Sfx86OpcodeDec_groupF6(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
731 {
732 if ((opcode&0xFE) == 0xF6) {
733 sx86_ubyte x;
734 sx86_ubyte w16;
735 sx86_ubyte mod,reg,rm;
736 sx86_uword imm16;
737
738 w16 = (opcode&1);
739 x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm
740 sx86_modregrm_unpack(x,mod,reg,rm);
741 sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp);
742
743 if (reg == 0) {
744 imm16 = softx86_fetch_dec_byte(ctx);
745 if (w16) imm16 |= softx86_fetch_dec_byte(ctx)<<8;
746 }
747
748 if (reg == 0) sprintf(buf,"TEST %s,%04Xh",op1_tmp,imm16);
749 else if (reg == 2) sprintf(buf,"NOT %s",op1_tmp);
750 else if (reg == 3) sprintf(buf,"NEG %s",op1_tmp);
751 else if (reg == 4) sprintf(buf,"MUL %s",op1_tmp);
752 else if (reg == 5) sprintf(buf,"IMUL %s",op1_tmp);
753 else if (reg == 6) sprintf(buf,"DIV %s",op1_tmp);
754 else if (reg == 7) sprintf(buf,"IDIV %s",op1_tmp);
755 else return 0;
756
757 return 1;
758 }
759
760 return 0;
761 }
762