4 * Copyright (C) 2003, 2004 Jonathan Campbell <jcampbell@mdjk.com>
6 * Decompiler and executioneer for MOV and XLAT 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 sx86_ubyte
op_mov8(softx86_ctx
* ctx
,sx86_ubyte src
,sx86_ubyte val
)
36 sx86_uword
op_mov16(softx86_ctx
* ctx
,sx86_uword src
,sx86_uword val
)
41 sx86_udword
op_mov32(softx86_ctx
* ctx
,sx86_udword src
,sx86_udword val
)
46 int Sfx86OpcodeExec_mov(sx86_ubyte opcode
,softx86_ctx
* ctx
)
51 if (!ctx
->state
->is_segment_override
)
52 seg
= ctx
->state
->segment_reg
[SX86_SREG_DS
].val
;
54 seg
= ctx
->state
->segment_override
;
56 if ((opcode
&0xFC) == 0x88) { // MOV reg,reg/mem or reg/mem,reg
58 sx86_ubyte w16
,opswap
;
59 sx86_ubyte mod
,reg
,rm
;
62 opswap
= (opcode
&2)>>1; // mov from reg to r/m UNLESS this bit it set (then it's the other way around)
63 x
= softx86_fetch_exec_byte(ctx
); // fetch mod/reg/rm
64 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
65 sx86_exec_full_modregrm_rw(ctx
,w16
,0,mod
,reg
,
66 rm
,opswap
,op_mov8
,op_mov16
,op_mov32
);
70 else if (opcode
== 0x8C || opcode
== 0x8E) { // MOV reg,reg/mem or reg/mem,reg
73 sx86_ubyte mod
,reg
,rm
;
75 opswap
= (opcode
&2)>>1; // mov from reg to r/m UNLESS this bit it set (then it's the other way around)
76 x
= softx86_fetch_exec_byte(ctx
); // fetch mod/reg/rm
77 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
78 sx86_exec_full_modsregrm_rw(ctx
,mod
,reg
,rm
,opswap
,op_mov16
);
82 else if ((opcode
&0xFE) == 0xA0) { // MOV AL/AX,[mem]
85 o
= softx86_fetch_exec_byte(ctx
);
86 o
|= softx86_fetch_exec_byte(ctx
)<<8;
87 lo
= sx86_far_to_linear(ctx
,seg
,o
);
92 softx86_fetch(ctx
,NULL
,lo
,&mem
,2);
93 SWAP_WORD_FROM_LE(mem
);
94 ctx
->state
->general_reg
[SX86_REG_AX
].w
.lo
= mem
;
99 softx86_fetch(ctx
,NULL
,lo
,&mem
,1);
100 ctx
->state
->general_reg
[SX86_REG_AX
].b
.lo
= mem
;
105 else if ((opcode
&0xFE) == 0xA2) { // MOV [mem],AL/AX
108 o
= softx86_fetch_exec_byte(ctx
);
109 o
|= softx86_fetch_exec_byte(ctx
)<<8;
110 lo
= sx86_far_to_linear(ctx
,seg
,o
);
115 mem
= ctx
->state
->general_reg
[SX86_REG_AX
].w
.lo
;
116 SWAP_WORD_TO_LE(mem
);
117 softx86_write(ctx
,NULL
,lo
,&mem
,2);
122 mem
= ctx
->state
->general_reg
[SX86_REG_AX
].b
.lo
;
123 softx86_write(ctx
,NULL
,lo
,&mem
,1);
128 else if ((opcode
&0xF8) == 0xB0) { // MOV [reg = (opcode-0xB0)],imm8
131 b
= softx86_fetch_exec_byte(ctx
);
132 *(ctx
->__private
->ptr_regs_8reg
[opcode
-0xB0]) = b
;
135 else if ((opcode
&0xF8) == 0xB8) { // MOV [reg = (opcode-0xB8)],imm16
138 w
= softx86_fetch_exec_byte(ctx
);
139 w
|= softx86_fetch_exec_byte(ctx
)<<8;
140 ctx
->state
->general_reg
[opcode
-0xB8].w
.lo
= w
;
147 int Sfx86OpcodeDec_mov(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
149 if ((opcode
&0xFC) == 0x88) { // MOV reg,reg/mem or reg/mem,reg
151 sx86_ubyte w16
,opswap
;
152 sx86_ubyte mod
,reg
,rm
;
155 opswap
= (opcode
&2)>>1; // mov from reg to r/m UNLESS this bit it set (then it's the other way around)
156 x
= softx86_fetch_dec_byte(ctx
); // fetch mod/reg/rm
157 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
158 sx86_dec_full_modregrm(ctx
,w16
,0,mod
,reg
,rm
,op1_tmp
,op2_tmp
);
160 if (opswap
) sprintf(buf
,"MOV %s,%s",op2_tmp
,op1_tmp
);
161 else sprintf(buf
,"MOV %s,%s",op1_tmp
,op2_tmp
);
164 else if (opcode
== 0x8C || opcode
== 0x8E) { // MOV reg,reg/mem or reg/mem,reg
167 sx86_ubyte mod
,reg
,rm
;
169 opswap
= (opcode
&2)>>1; // mov from reg to r/m UNLESS this bit it set (then it's the other way around)
170 x
= softx86_fetch_dec_byte(ctx
); // fetch mod/reg/rm
171 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
172 sx86_dec_full_modsregrm(ctx
,mod
,reg
,rm
,op1_tmp
,op2_tmp
);
174 if (opswap
) sprintf(buf
,"MOV %s,%s",op2_tmp
,op1_tmp
);
175 else sprintf(buf
,"MOV %s,%s",op1_tmp
,op2_tmp
);
178 else if ((opcode
&0xFE) == 0xA0) { // MOV AL/AX,[mem]
181 o
= softx86_fetch_dec_byte(ctx
);
182 o
|= softx86_fetch_dec_byte(ctx
)<<8;
183 sprintf(buf
,"MOV %s,[%04Xh]",opcode
== 0xA1 ? "AX" : "AL",o
);
186 else if ((opcode
&0xFE) == 0xA2) { // MOV [mem],AL/AX
189 o
= softx86_fetch_dec_byte(ctx
);
190 o
|= softx86_fetch_dec_byte(ctx
)<<8;
191 sprintf(buf
,"MOV [%04Xh],%s",o
,opcode
== 0xA3 ? "AX" : "AL");
194 else if ((opcode
&0xF8) == 0xB0) { // MOV [reg = (opcode-0xB0)],imm8
197 b
= softx86_fetch_dec_byte(ctx
);
198 sprintf(buf
,"MOV %s,%02Xh",sx86_regs8
[opcode
-0xB0],b
);
201 else if ((opcode
&0xF8) == 0xB8) { // MOV [reg = (opcode-0xB8)],imm16
204 w
= softx86_fetch_dec_byte(ctx
);
205 w
|= softx86_fetch_dec_byte(ctx
)<<8;
206 sprintf(buf
,"MOV %s,%04Xh",sx86_regs16
[opcode
-0xB8],w
);
213 int Sfx86OpcodeExec_xlat(sx86_ubyte opcode
,softx86_ctx
* ctx
)
217 if (!ctx
->state
->is_segment_override
)
218 seg
= ctx
->state
->segment_reg
[SX86_SREG_DS
].val
;
220 seg
= ctx
->state
->segment_override
;
222 if ((opcode
&0xFC) == 0xD7) { // MOV reg,reg/mem or reg/mem,reg
226 ofs
= (sx86_udword
)(ctx
->state
->general_reg
[SX86_REG_BX
].w
.lo
);
227 ofs
+= (sx86_udword
)(ctx
->state
->general_reg
[SX86_REG_AX
].b
.lo
);
229 ofs
= sx86_far_to_linear(ctx
,seg
,ofs
);
231 softx86_fetch(ctx
,NULL
,ofs
,&d
,1);
232 ctx
->state
->general_reg
[SX86_REG_AX
].b
.lo
= d
;
240 int Sfx86OpcodeDec_xlat(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
242 if ((opcode
&0xFC) == 0xD7) { // XLAT
250 sx86_uword
op_les16(softx86_ctx
* ctx
,sx86_uword seg
,sx86_uword ofs
)
252 softx86_setsegval(ctx
,SX86_SREG_ES
,seg
);
256 sx86_udword
op_les32(softx86_ctx
* ctx
,sx86_udword seg
,sx86_udword ofs
)
258 softx86_setsegval(ctx
,SX86_SREG_ES
,seg
);
262 sx86_uword
op_lds16(softx86_ctx
* ctx
,sx86_uword seg
,sx86_uword ofs
)
264 softx86_setsegval(ctx
,SX86_SREG_DS
,seg
);
268 sx86_udword
op_lds32(softx86_ctx
* ctx
,sx86_udword seg
,sx86_udword ofs
)
270 softx86_setsegval(ctx
,SX86_SREG_DS
,seg
);
274 int Sfx86OpcodeExec_les(sx86_ubyte opcode
,softx86_ctx
* ctx
)
276 if (opcode
== 0xC4) { // LES
278 sx86_ubyte mod
,reg
,rm
;
280 x
= softx86_fetch_exec_byte(ctx
); // fetch mod/reg/rm
281 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
282 sx86_exec_full_modregrm_far(ctx
,0,mod
,reg
,rm
,op_les16
,op_les32
);
285 if (opcode
== 0xC5) { // LDS
287 sx86_ubyte mod
,reg
,rm
;
289 x
= softx86_fetch_exec_byte(ctx
); // fetch mod/reg/rm
290 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
291 sx86_exec_full_modregrm_far(ctx
,0,mod
,reg
,rm
,op_lds16
,op_lds32
);
298 int Sfx86OpcodeDec_les(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
300 if (opcode
== 0xC4) { // LES
302 sx86_ubyte mod
,reg
,rm
;
304 x
= softx86_fetch_dec_byte(ctx
); // fetch mod/reg/rm
305 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
306 sx86_dec_full_modregrm(ctx
,1,0,mod
,reg
,rm
,op1_tmp
,op2_tmp
);
307 sprintf(buf
,"LES %s,%s",op2_tmp
,op1_tmp
);
310 if (opcode
== 0xC5) { // LDS
312 sx86_ubyte mod
,reg
,rm
;
314 x
= softx86_fetch_dec_byte(ctx
); // fetch mod/reg/rm
315 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
316 sx86_dec_full_modregrm(ctx
,1,0,mod
,reg
,rm
,op1_tmp
,op2_tmp
);
317 sprintf(buf
,"LDS %s,%s",op2_tmp
,op1_tmp
);
324 sx86_uword
op_lmsw16(softx86_ctx
* ctx
,sx86_uword src
)
326 /* bit 0 can only be set, not reset (80286 method of PM) */
327 ctx
->state
->reg_cr0
|= (src
& SX86_CR0FLAG_PE
);
328 /* bits 1-3 are only used here */
329 ctx
->state
->reg_cr0
&= ~SX86_CR0_LMSW_MASK
;
330 ctx
->state
->reg_cr0
|= (src
& SX86_CR0_LMSW_MASK
);
331 /* the return value doesn't matter */
335 sx86_uword
op_smsw16(softx86_ctx
* ctx
,sx86_uword src
)
337 return ((sx86_uword
)ctx
->state
->reg_cr0
);
340 int Sfx86OpcodeExec_lmsw286(sx86_ubyte opcode
,softx86_ctx
* ctx
)
342 if (opcode
== 0x01) { // LMSW [reg]
344 sx86_ubyte mod
,reg
,rm
;
346 x
= softx86_fetch_exec_byte(ctx
); // fetch mod/reg/rm
347 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
350 sx86_exec_full_modrmonly_rw(ctx
,1,0,mod
,rm
,NULL
,op_smsw16
,NULL
);
352 sx86_exec_full_modrmonly_ro(ctx
,1,0,mod
,rm
,NULL
,op_lmsw16
,NULL
);
362 int Sfx86OpcodeDec_lmsw286(sx86_ubyte opcode
,softx86_ctx
* ctx
,char buf
[128])
364 if (opcode
== 0x01) { // LMSW [reg]
367 sx86_ubyte mod
,reg
,rm
;
370 x
= softx86_fetch_dec_byte(ctx
); // fetch mod/reg/rm
371 sx86_modregrm_unpack(x
,mod
,reg
,rm
);
372 sx86_dec_full_modrmonly(ctx
,w16
,0,mod
,rm
,op1_tmp
);
375 sprintf(buf
,"SMSW %s",op1_tmp
);
377 sprintf(buf
,"LMSW %s",op1_tmp
);