[SOFTX86]
[reactos.git] / lib / 3rdparty / softx86 / softx86 / jumpy.c
1 /*
2 * jumpy.c
3 *
4 * Copyright (C) 2003, 2004 Jonathan Campbell <jcampbell@mdjk.com>
5 *
6 * Decompiler and executioneer for CALL/J<condition> instructions.
7 *
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.
13 *
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.
18 *
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 ************************************************************************************/
23
24 #include <softx86.h>
25 #include <memory.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include "optable.h"
29 #include "jumpy.h"
30
31 int Sfx86OpcodeExec_jc(sx86_ubyte opcode,softx86_ctx* ctx)
32 {
33 int tf;
34 sx86_udword rel;
35
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;
40
41 rel = (sx86_udword)softx86_fetch_exec_byte(ctx);
42 if (rel & 0x80) rel |= 0xFFFFFF00;
43 rel += ctx->state->reg_ip;
44 rel &= 0xFFFF;
45
46 /* JCXZ */
47 if (opcode == 0xE3)
48 tf = (ctx->state->general_reg[SX86_REG_CX].w.lo == 0);
49 /* JO */
50 else if (opcode == 0x70)
51 tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW);
52 /* JNO */
53 else if (opcode == 0x71)
54 tf = !(ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW);
55 /* JC */
56 else if (opcode == 0x72)
57 tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY);
58 /* JNC */
59 else if (opcode == 0x73)
60 tf = !(ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY);
61 /* JZ */
62 else if (opcode == 0x74)
63 tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO);
64 /* JNZ */
65 else if (opcode == 0x75)
66 tf = !(ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO);
67 /* JBE */
68 else if (opcode == 0x76)
69 tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO) ||
70 (ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY);
71 /* JA */
72 else if (opcode == 0x77)
73 tf = (!(ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO)) &&
74 (!(ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY));
75 /* JS */
76 else if (opcode == 0x78)
77 tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN);
78 /* JNS */
79 else if (opcode == 0x79)
80 tf = !(ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN);
81 /* JP */
82 else if (opcode == 0x7A)
83 tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_PARITY);
84 /* JNP */
85 else if (opcode == 0x7B)
86 tf = !(ctx->state->reg_flags.val & SX86_CPUFLAG_PARITY);
87 /* JL */
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));
91 /* JGE */
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);
95 /* JLE */
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));
100 /* JG */
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 !*/
106 else
107 return 0;
108
109 /* if condition met, go! */
110 if (tf)
111 softx86_set_instruction_ptr(ctx,ctx->state->segment_reg[SX86_SREG_CS].val,rel);
112
113 return 1;
114 }
115
116 int Sfx86OpcodeDec_jc(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
117 {
118 sx86_udword rel;
119
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;
124
125 rel = (sx86_udword)softx86_fetch_dec_byte(ctx);
126 if (rel & 0x80) rel |= 0xFFFFFF00;
127 rel += ctx->state->reg_ip_decompiler;
128 rel &= 0xFFFF;
129
130 if (opcode == 0xE3)
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 !*/
165 else
166 return 0;
167
168 return 1;
169 }
170
171 int Sfx86OpcodeExec_call(sx86_ubyte opcode,softx86_ctx* ctx)
172 {
173 if (opcode == 0x9A) { // CALL FAR seg:offs
174 sx86_uword seg,ofs;
175
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);
183 return 1;
184 }
185 else if (opcode == 0xE8) { // CALL rel16
186 int ofs;
187
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;
192 ofs &= 0xFFFF;
193 softx86_stack_pushw(ctx,ctx->state->reg_ip);
194 softx86_set_near_instruction_ptr(ctx,(sx86_udword)ofs);
195 return 1;
196 }
197
198 return 0;
199 }
200
201 int Sfx86OpcodeDec_call(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
202 {
203 if (opcode == 0x9A) { // CALL FAR seg:offs
204 sx86_uword seg,ofs;
205
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);
211 return 1;
212 }
213 else if (opcode == 0xE8) { // CALL rel16
214 int ofs;
215
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;
220 ofs &= 0xFFFF;
221 sprintf(buf,"CALL %04X",ofs);
222 return 1;
223 }
224
225 return 0;
226 }
227
228 int Sfx86OpcodeExec_jmp(sx86_ubyte opcode,softx86_ctx* ctx)
229 {
230 if (opcode == 0xE9) { // JMP rel16
231 int ofs;
232
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;
237 ofs &= 0xFFFF;
238 softx86_set_near_instruction_ptr(ctx,(sx86_udword)ofs);
239 return 1;
240 }
241 else if (opcode == 0xEA) { // JMP FAR seg:offs
242 sx86_uword seg,ofs;
243
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);
249 return 1;
250 }
251 else if (opcode == 0xEB) { // JMP rel8
252 int ofs;
253
254 ofs = (int)softx86_fetch_exec_byte(ctx);
255 if (ofs & 0x80) ofs -= 0x100;
256 ofs += ctx->state->reg_ip;
257 ofs &= 0xFFFF;
258 softx86_set_near_instruction_ptr(ctx,(sx86_udword)ofs);
259 return 1;
260 }
261
262 return 0;
263 }
264
265 int Sfx86OpcodeDec_jmp(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
266 {
267 if (opcode == 0xE9) { // JMP rel16
268 int ofs;
269
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;
274 ofs &= 0xFFFF;
275 sprintf(buf,"JMP %04X",ofs);
276 return 1;
277 }
278 else if (opcode == 0xEA) { // JMP FAR seg:offs
279 sx86_uword seg,ofs;
280
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);
286 return 1;
287 }
288 else if (opcode == 0xEB) { // JMP rel8
289 int ofs;
290
291 ofs = (int)softx86_fetch_dec_byte(ctx);
292 if (ofs & 0x80) ofs -= 0x100;
293 ofs += ctx->state->reg_ip_decompiler;
294 ofs &= 0xFFFF;
295 sprintf(buf,"JMP %04X",ofs);
296 return 1;
297 }
298
299 return 0;
300 }
301
302 int Sfx86OpcodeExec_loop(sx86_ubyte opcode,softx86_ctx* ctx)
303 {
304 int tf;
305 sx86_udword rel;
306
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;
311 rel &= 0xFFFF;
312
313 ctx->state->general_reg[SX86_REG_CX].w.lo--;
314
315 /* LOOP */
316 if (opcode == 0xE2)
317 tf = (ctx->state->general_reg[SX86_REG_CX].w.lo != 0);
318 /* LOOPZ */
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);
322 /* LOOPNZ */
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 !*/
327 else
328 return 0;
329
330 /* if condition met, go! */
331 if (tf)
332 softx86_set_instruction_ptr(ctx,ctx->state->segment_reg[SX86_SREG_CS].val,rel);
333
334 return 1;
335 }
336
337 int Sfx86OpcodeDec_loop(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
338 {
339 sx86_udword rel;
340
341 rel = (sx86_udword)softx86_fetch_dec_byte(ctx);
342 if (rel & 0x80) rel |= 0xFFFFFF00;
343 rel += ctx->state->reg_ip_decompiler;
344 rel &= 0xFFFF;
345
346 if (opcode == 0xE2)
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 !*/
353 else
354 return 0;
355
356 return 1;
357 }
358