4 * Copyright (C) 2003, 2004 Jonathan Campbell <jcampbell@mdjk.com>
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.
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.
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.
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 ************************************************************************************/
36 sx86_uword
op_ncall16(softx86_ctx
* ctx
,sx86_uword src
)
38 softx86_stack_pushw(ctx
,ctx
->state
->reg_ip
);
39 softx86_set_near_instruction_ptr(ctx
,src
);
43 sx86_udword
op_ncall32(softx86_ctx
* ctx
,sx86_udword src
)
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
);
51 sx86_uword
op_popmem16(softx86_ctx
* ctx
)
53 return softx86_stack_popw(ctx
);
56 sx86_udword
op_popmem32(softx86_ctx
* ctx
)
60 d
= ((sx86_udword
)softx86_stack_popw(ctx
));
61 d
|= ((sx86_udword
)softx86_stack_popw(ctx
))<<16;
65 sx86_uword
op_pushmem16(softx86_ctx
* ctx
,sx86_uword src
)
67 softx86_stack_pushw(ctx
,src
);
71 sx86_udword
op_pushmem32(softx86_ctx
* ctx
,sx86_udword src
)
73 softx86_stack_pushw(ctx
,(src
>>16)&0xFFFF);
74 softx86_stack_pushw(ctx
,src
&0xFFFF);
78 sx86_uword
op_njmp16(softx86_ctx
* ctx
,sx86_uword src
)
80 softx86_set_near_instruction_ptr(ctx
,src
);
84 sx86_udword
op_njmp32(softx86_ctx
* ctx
,sx86_udword src
)
86 softx86_set_near_instruction_ptr(ctx
,src
);
90 void op_fcall16(softx86_ctx
* ctx
,sx86_uword seg
,sx86_uword ofs
)
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
);
97 void op_fcall32(softx86_ctx
* ctx
,sx86_udword seg
,sx86_udword ofs
)
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
);
105 void op_fjmp16(softx86_ctx
* ctx
,sx86_uword seg
,sx86_uword ofs
)
107 softx86_set_instruction_ptr(ctx
,seg
,ofs
);
110 void op_fjmp32(softx86_ctx
* ctx
,sx86_udword seg
,sx86_udword ofs
)
112 softx86_set_instruction_ptr(ctx
,seg
,ofs
);
115 int Sfx86OpcodeExec_group80(sx86_ubyte opcode
,softx86_ctx
* ctx
)
117 if ((opcode
&0xFC) == 0x80) {
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
);
127 x
= softx86_fetch_exec_byte(ctx
); // fetch mod/reg/rm
128 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
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. */
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
);
177 sx86_exec_full_modrmonly_rw_imm(ctx
,w16
,0,mod
,rm
,op8
,op16
,op32
,sx
);
185 int Sfx86OpcodeDec_group80(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
187 if ((opcode
&0xFC) == 0x80) {
190 sx86_ubyte mod
,reg
,rm
;
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
);
199 imm16
= softx86_fetch_dec_byte(ctx
);
203 imm16
|= (imm16
&0x80) ? 0xFF80 : 0;
205 imm16
|= softx86_fetch_dec_byte(ctx
)<<8;
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
);
224 int Sfx86OpcodeExec_groupC0(sx86_ubyte opcode
,softx86_ctx
* ctx
)
226 if ((opcode
&0xFE) == 0xC0) {
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
);
235 x
= softx86_fetch_exec_byte(ctx
); // fetch mod/reg/rm
236 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
277 sx86_exec_full_modrmonly_rw_imm8(ctx
,w16
,0,mod
,rm
,op8
,op16
,op32
);
284 int Sfx86OpcodeDec_groupC0(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
286 if ((opcode
&0xFE) == 0xC0) {
289 sx86_ubyte mod
,reg
,rm
;
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
);
297 imm16
= softx86_fetch_dec_byte(ctx
);
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
);
314 int Sfx86OpcodeExec_groupD0(sx86_ubyte opcode
,softx86_ctx
* ctx
)
316 if ((opcode
&0xFE) == 0xD0 || (opcode
&0xFE) == 0xD2) {
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
);
325 x
= softx86_fetch_exec_byte(ctx
); // fetch mod/reg/rm
326 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
329 if ((opcode
&0xFE) == 0xD2) {
341 if ((opcode
&0xFE) == 0xD2) {
353 if ((opcode
&0xFE) == 0xD2) {
365 if ((opcode
&0xFE) == 0xD2) {
377 if ((opcode
&0xFE) == 0xD2) {
389 if ((opcode
&0xFE) == 0xD2) {
401 if ((opcode
&0xFE) == 0xD2) {
416 sx86_exec_full_modrmonly_rw(ctx
,w16
,0,mod
,rm
,op8
,op16
,op32
);
423 int Sfx86OpcodeDec_groupD0(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
425 if ((opcode
&0xFE) == 0xD0 || (opcode
&0xFE) == 0xD2) {
428 sx86_ubyte mod
,reg
,rm
;
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
);
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
);
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
);
462 int Sfx86OpcodeExec_groupC6(sx86_ubyte opcode
,softx86_ctx
* ctx
)
464 if ((opcode
&0xFE) == 0xC6) {
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
);
473 x
= softx86_fetch_exec_byte(ctx
); // fetch mod/reg/rm
474 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
485 sx86_exec_full_modrmonly_rw_imm(ctx
,w16
,0,mod
,rm
,op8
,op16
,op32
,0);
492 int Sfx86OpcodeDec_groupC6(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
494 if ((opcode
&0xFE) == 0xC6) {
497 sx86_ubyte mod
,reg
,rm
;
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
);
505 imm16
= softx86_fetch_dec_byte(ctx
);
506 if (w16
) imm16
|= softx86_fetch_dec_byte(ctx
)<<8;
508 if (reg
== 0) sprintf(buf
,"MOV %s,%04Xh",op1_tmp
,imm16
);
517 int Sfx86OpcodeExec_groupFE(sx86_ubyte opcode
,softx86_ctx
* ctx
)
519 if ((opcode
&0xFE) == 0xFE) {
522 sx86_ubyte mod
,reg
,rm
;
525 x
= softx86_fetch_exec_byte(ctx
); // fetch mod/reg/rm
526 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
529 sx86_exec_full_modrmonly_rw(ctx
,w16
,0,mod
,rm
,op_inc8
,op_inc16
,op_inc32
);
532 sx86_exec_full_modrmonly_rw(ctx
,w16
,0,mod
,rm
,op_dec8
,op_dec16
,op_dec32
);
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
);
541 /* you cannot have a far address in registers */
554 sx86_exec_full_modrmonly_callfar(ctx
,0,mod
,rm
,op16
,op32
);
557 sx86_uword (*op16
)(softx86_ctx
* ctx
,sx86_uword src
);
558 sx86_udword (*op32
)(softx86_ctx
* ctx
,sx86_udword src
);
576 sx86_exec_full_modrmonly_ro(ctx
,1,0,mod
,rm
,NULL
,op16
,op32
);
586 int Sfx86OpcodeDec_groupFE(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
588 if ((opcode
&0xFE) == 0xFE) {
591 sx86_ubyte mod
,reg
,rm
;
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
);
598 if (reg
== 0) sprintf(buf
,"INC %s",op1_tmp
);
599 else if (reg
== 1) sprintf(buf
,"DEC %s",op1_tmp
);
604 sprintf(buf
,"CALL %s",op1_tmp
);
606 sprintf(buf
,"CALL FAR %s",op1_tmp
);
608 sprintf(buf
,"JMP %s",op1_tmp
);
610 sprintf(buf
,"JMP FAR %s",op1_tmp
);
612 sprintf(buf
,"PUSH %s",op1_tmp
);
623 int Sfx86OpcodeExec_group8F(sx86_ubyte opcode
,softx86_ctx
* ctx
)
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
);
630 x
= softx86_fetch_exec_byte(ctx
); // fetch mod/reg/rm
631 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
641 sx86_exec_full_modrmonly_wo(ctx
,1,0,mod
,rm
,NULL
,op16
,op32
);
648 int Sfx86OpcodeDec_group8F(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
650 if (opcode
== 0x8F) {
652 sx86_ubyte mod
,reg
,rm
;
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
);
658 if (reg
== 0) sprintf(buf
,"POP %s",op1_tmp
);
667 int Sfx86OpcodeExec_groupF6(sx86_ubyte opcode
,softx86_ctx
* ctx
)
669 if ((opcode
&0xFE) == 0xF6) {
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
);
678 x
= softx86_fetch_exec_byte(ctx
); // fetch mod/reg/rm
679 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
682 /* taken care of later */
685 /* taken care of later */
688 /* taken care of later */
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. */
714 /* TEST does not modify the dest. register... */
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 */
719 sx86_exec_full_modrmonly_rw(ctx
,w16
,0,mod
,rm
,op_not8
,op_not16
,op_not32
);
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 */
724 sx86_exec_full_modrmonly_ro(ctx
,w16
,0,mod
,rm
,op8
,op16
,op32
);
732 int Sfx86OpcodeDec_groupF6(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
734 if ((opcode
&0xFE) == 0xF6) {
737 sx86_ubyte mod
,reg
,rm
;
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
);
746 imm16
= softx86_fetch_dec_byte(ctx
);
747 if (w16
) imm16
|= softx86_fetch_dec_byte(ctx
)<<8;
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
);