4 * Copyright (C) 2003, 2004 Jonathan Campbell <jcampbell@mdjk.com>
6 * Decompiler and executioneer for CALL/J<condition> instructions.
8 ***********************************************************************************
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 ************************************************************************************/
31 int Sfx86OpcodeExec_jc(sx86_ubyte opcode
,softx86_ctx
* ctx
)
36 /* Intel's tendancy to sort the instructions in their documentation alphabetically
37 by name instead of by opcode tends to distort the fact that all of these
38 opcodes (except for JCXZ) lie between 0x70 and 0x7F. */
39 if (!(opcode
== 0xE3 || ((opcode
&0xF0) == 0x70))) return 0;
41 rel
= (sx86_udword
)softx86_fetch_exec_byte(ctx
);
42 if (rel
& 0x80) rel
|= 0xFFFFFF00;
43 rel
+= ctx
->state
->reg_ip
;
48 tf
= (ctx
->state
->general_reg
[SX86_REG_CX
].w
.lo
== 0);
50 else if (opcode
== 0x70)
51 tf
= (ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_OVERFLOW
);
53 else if (opcode
== 0x71)
54 tf
= !(ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_OVERFLOW
);
56 else if (opcode
== 0x72)
57 tf
= (ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_CARRY
);
59 else if (opcode
== 0x73)
60 tf
= !(ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_CARRY
);
62 else if (opcode
== 0x74)
63 tf
= (ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_ZERO
);
65 else if (opcode
== 0x75)
66 tf
= !(ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_ZERO
);
68 else if (opcode
== 0x76)
69 tf
= (ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_ZERO
) ||
70 (ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_CARRY
);
72 else if (opcode
== 0x77)
73 tf
= (!(ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_ZERO
)) &&
74 (!(ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_CARRY
));
76 else if (opcode
== 0x78)
77 tf
= (ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_SIGN
);
79 else if (opcode
== 0x79)
80 tf
= !(ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_SIGN
);
82 else if (opcode
== 0x7A)
83 tf
= (ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_PARITY
);
85 else if (opcode
== 0x7B)
86 tf
= !(ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_PARITY
);
88 else if (opcode
== 0x7C)
89 tf
= (((ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_SIGN
) ? 1 : 0) !=
90 ((ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_OVERFLOW
) ? 1 : 0));
92 else if (opcode
== 0x7D)
93 tf
= ((ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_SIGN
) ? 1 : 0) ==
94 ((ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_OVERFLOW
) ? 1 : 0);
96 else if (opcode
== 0x7E)
97 tf
= (((ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_SIGN
) ? 1 : 0) !=
98 ((ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_OVERFLOW
) ? 1 : 0) ||
99 (ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_ZERO
));
101 else if (opcode
== 0x7F)
102 tf
= (((ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_SIGN
) ? 1 : 0) ==
103 ((ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_OVERFLOW
) ? 1 : 0) &&
104 (!(ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_ZERO
)));
105 /* should NOT be here !*/
109 /* if condition met, go! */
111 softx86_set_instruction_ptr(ctx
,ctx
->state
->segment_reg
[SX86_SREG_CS
].val
,rel
);
116 int Sfx86OpcodeDec_jc(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
120 /* Intel's tendancy to sort the instructions in their documentation alphabetically
121 by name instead of by opcode tends to distort the fact that all of these
122 opcodes (except for JCXZ) lie between 0x70 and 0x7F. */
123 if (!(opcode
== 0xE3 || ((opcode
&0xF0) == 0x70))) return 0;
125 rel
= (sx86_udword
)softx86_fetch_dec_byte(ctx
);
126 if (rel
& 0x80) rel
|= 0xFFFFFF00;
127 rel
+= ctx
->state
->reg_ip_decompiler
;
131 sprintf(buf
,"JCXZ %04Xh",rel
);
132 else if (opcode
== 0x70)
133 sprintf(buf
,"JO %04Xh",rel
);
134 else if (opcode
== 0x71)
135 sprintf(buf
,"JNO %04Xh",rel
);
136 else if (opcode
== 0x72)
137 sprintf(buf
,"JC %04Xh",rel
);
138 else if (opcode
== 0x73)
139 sprintf(buf
,"JNC %04Xh",rel
);
140 else if (opcode
== 0x74)
141 sprintf(buf
,"JZ %04Xh",rel
);
142 else if (opcode
== 0x75)
143 sprintf(buf
,"JNZ %04Xh",rel
);
144 else if (opcode
== 0x76)
145 sprintf(buf
,"JBE %04Xh",rel
);
146 else if (opcode
== 0x77)
147 sprintf(buf
,"JA %04Xh",rel
);
148 else if (opcode
== 0x78)
149 sprintf(buf
,"JS %04Xh",rel
);
150 else if (opcode
== 0x79)
151 sprintf(buf
,"JNS %04Xh",rel
);
152 else if (opcode
== 0x7A)
153 sprintf(buf
,"JP %04Xh",rel
);
154 else if (opcode
== 0x7B)
155 sprintf(buf
,"JNP %04Xh",rel
);
156 else if (opcode
== 0x7C)
157 sprintf(buf
,"JL %04Xh",rel
);
158 else if (opcode
== 0x7D)
159 sprintf(buf
,"JGE %04Xh",rel
);
160 else if (opcode
== 0x7E)
161 sprintf(buf
,"JLE %04Xh",rel
);
162 else if (opcode
== 0x7F)
163 sprintf(buf
,"JG %04Xh",rel
);
164 /* should NOT be here !*/
171 int Sfx86OpcodeExec_call(sx86_ubyte opcode
,softx86_ctx
* ctx
)
173 if (opcode
== 0x9A) { // CALL FAR seg:offs
176 ofs
= (sx86_uword
)softx86_fetch_exec_byte(ctx
);
177 ofs
|= ((sx86_uword
)softx86_fetch_exec_byte(ctx
))<<8;
178 seg
= (sx86_uword
)softx86_fetch_exec_byte(ctx
);
179 seg
|= ((sx86_uword
)softx86_fetch_exec_byte(ctx
))<<8;
180 softx86_stack_pushw(ctx
,ctx
->state
->segment_reg
[SX86_SREG_CS
].val
);
181 softx86_stack_pushw(ctx
,ctx
->state
->reg_ip
);
182 softx86_set_instruction_ptr(ctx
,seg
,ofs
);
185 else if (opcode
== 0xE8) { // CALL rel16
188 ofs
= (int)softx86_fetch_exec_byte(ctx
);
189 ofs
|= ((int)softx86_fetch_exec_byte(ctx
))<<8;
190 if (ofs
& 0x8000) ofs
-= 0x10000;
191 ofs
+= ctx
->state
->reg_ip
;
193 softx86_stack_pushw(ctx
,ctx
->state
->reg_ip
);
194 softx86_set_near_instruction_ptr(ctx
,(sx86_udword
)ofs
);
201 int Sfx86OpcodeDec_call(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
203 if (opcode
== 0x9A) { // CALL FAR seg:offs
206 ofs
= (sx86_uword
)softx86_fetch_dec_byte(ctx
);
207 ofs
|= ((sx86_uword
)softx86_fetch_dec_byte(ctx
))<<8;
208 seg
= (sx86_uword
)softx86_fetch_dec_byte(ctx
);
209 seg
|= ((sx86_uword
)softx86_fetch_dec_byte(ctx
))<<8;
210 sprintf(buf
,"CALL FAR %04X:%04X",seg
,ofs
);
213 else if (opcode
== 0xE8) { // CALL rel16
216 ofs
= (int)softx86_fetch_dec_byte(ctx
);
217 ofs
|= ((int)softx86_fetch_dec_byte(ctx
))<<8;
218 if (ofs
& 0x8000) ofs
-= 0x10000;
219 ofs
+= ctx
->state
->reg_ip_decompiler
;
221 sprintf(buf
,"CALL %04X",ofs
);
228 int Sfx86OpcodeExec_jmp(sx86_ubyte opcode
,softx86_ctx
* ctx
)
230 if (opcode
== 0xE9) { // JMP rel16
233 ofs
= (int)softx86_fetch_exec_byte(ctx
);
234 ofs
|= ((int)softx86_fetch_exec_byte(ctx
))<<8;
235 if (ofs
& 0x8000) ofs
-= 0x10000;
236 ofs
+= ctx
->state
->reg_ip
;
238 softx86_set_near_instruction_ptr(ctx
,(sx86_udword
)ofs
);
241 else if (opcode
== 0xEA) { // JMP FAR seg:offs
244 ofs
= (sx86_uword
)softx86_fetch_exec_byte(ctx
);
245 ofs
|= ((sx86_uword
)softx86_fetch_exec_byte(ctx
))<<8;
246 seg
= (sx86_uword
)softx86_fetch_exec_byte(ctx
);
247 seg
|= ((sx86_uword
)softx86_fetch_exec_byte(ctx
))<<8;
248 softx86_set_instruction_ptr(ctx
,seg
,ofs
);
251 else if (opcode
== 0xEB) { // JMP rel8
254 ofs
= (int)softx86_fetch_exec_byte(ctx
);
255 if (ofs
& 0x80) ofs
-= 0x100;
256 ofs
+= ctx
->state
->reg_ip
;
258 softx86_set_near_instruction_ptr(ctx
,(sx86_udword
)ofs
);
265 int Sfx86OpcodeDec_jmp(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
267 if (opcode
== 0xE9) { // JMP rel16
270 ofs
= (int)softx86_fetch_dec_byte(ctx
);
271 ofs
|= ((int)softx86_fetch_dec_byte(ctx
))<<8;
272 if (ofs
& 0x8000) ofs
-= 0x10000;
273 ofs
+= ctx
->state
->reg_ip_decompiler
;
275 sprintf(buf
,"JMP %04X",ofs
);
278 else if (opcode
== 0xEA) { // JMP FAR seg:offs
281 ofs
= (sx86_uword
)softx86_fetch_dec_byte(ctx
);
282 ofs
|= ((sx86_uword
)softx86_fetch_dec_byte(ctx
))<<8;
283 seg
= (sx86_uword
)softx86_fetch_dec_byte(ctx
);
284 seg
|= ((sx86_uword
)softx86_fetch_dec_byte(ctx
))<<8;
285 sprintf(buf
,"JMP FAR %04X:%04X",seg
,ofs
);
288 else if (opcode
== 0xEB) { // JMP rel8
291 ofs
= (int)softx86_fetch_dec_byte(ctx
);
292 if (ofs
& 0x80) ofs
-= 0x100;
293 ofs
+= ctx
->state
->reg_ip_decompiler
;
295 sprintf(buf
,"JMP %04X",ofs
);
302 int Sfx86OpcodeExec_loop(sx86_ubyte opcode
,softx86_ctx
* ctx
)
307 if (opcode
< 0xE0 || opcode
> 0xE2) return 0;
308 rel
= (sx86_udword
)softx86_fetch_exec_byte(ctx
);
309 if (rel
& 0x80) rel
|= 0xFFFFFF00;
310 rel
+= ctx
->state
->reg_ip
;
313 ctx
->state
->general_reg
[SX86_REG_CX
].w
.lo
--;
317 tf
= (ctx
->state
->general_reg
[SX86_REG_CX
].w
.lo
!= 0);
319 else if (opcode
== 0xE1)
320 tf
= (ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_ZERO
) &&
321 (ctx
->state
->general_reg
[SX86_REG_CX
].w
.lo
!= 0);
323 else if (opcode
== 0xE0)
324 tf
= ((ctx
->state
->reg_flags
.val
& SX86_CPUFLAG_ZERO
) == 0) &&
325 (ctx
->state
->general_reg
[SX86_REG_CX
].w
.lo
!= 0);
326 /* should NOT be here !*/
330 /* if condition met, go! */
332 softx86_set_instruction_ptr(ctx
,ctx
->state
->segment_reg
[SX86_SREG_CS
].val
,rel
);
337 int Sfx86OpcodeDec_loop(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
341 rel
= (sx86_udword
)softx86_fetch_dec_byte(ctx
);
342 if (rel
& 0x80) rel
|= 0xFFFFFF00;
343 rel
+= ctx
->state
->reg_ip_decompiler
;
347 sprintf(buf
,"LOOP %04Xh",rel
);
348 else if (opcode
== 0xE1)
349 sprintf(buf
,"LOOPZ %04Xh",rel
);
350 else if (opcode
== 0xE0)
351 sprintf(buf
,"LOOPNZ %04Xh",rel
);
352 /* should NOT be here !*/