[SOFTX86]
[reactos.git] / lib / 3rdparty / softx86 / softx86 / mov.c
1 /*
2 * add.c
3 *
4 * Copyright (C) 2003, 2004 Jonathan Campbell <jcampbell@mdjk.com>
5 *
6 * Decompiler and executioneer for MOV and XLAT 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 "mov.h"
30
31 sx86_ubyte op_mov8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val)
32 {
33 return val;
34 }
35
36 sx86_uword op_mov16(softx86_ctx* ctx,sx86_uword src,sx86_uword val)
37 {
38 return val;
39 }
40
41 sx86_udword op_mov32(softx86_ctx* ctx,sx86_udword src,sx86_udword val)
42 {
43 return val;
44 }
45
46 int Sfx86OpcodeExec_mov(sx86_ubyte opcode,softx86_ctx* ctx)
47 {
48 sx86_udword lo;
49 sx86_uword seg;
50
51 if (!ctx->state->is_segment_override)
52 seg = ctx->state->segment_reg[SX86_SREG_DS].val;
53 else
54 seg = ctx->state->segment_override;
55
56 if ((opcode&0xFC) == 0x88) { // MOV reg,reg/mem or reg/mem,reg
57 sx86_ubyte x;
58 sx86_ubyte w16,opswap;
59 sx86_ubyte mod,reg,rm;
60
61 w16 = (opcode&1);
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);
67
68 return 1;
69 }
70 else if (opcode == 0x8C || opcode == 0x8E) { // MOV reg,reg/mem or reg/mem,reg
71 sx86_ubyte x;
72 sx86_ubyte opswap;
73 sx86_ubyte mod,reg,rm;
74
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);
79
80 return 1;
81 }
82 else if ((opcode&0xFE) == 0xA0) { // MOV AL/AX,[mem]
83 sx86_uword o;
84
85 o = softx86_fetch_exec_byte(ctx);
86 o |= softx86_fetch_exec_byte(ctx)<<8;
87 lo = sx86_far_to_linear(ctx,seg,o);
88
89 if (opcode&1) {
90 sx86_uword mem;
91
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;
95 }
96 else {
97 sx86_ubyte mem;
98
99 softx86_fetch(ctx,NULL,lo,&mem,1);
100 ctx->state->general_reg[SX86_REG_AX].b.lo = mem;
101 }
102
103 return 1;
104 }
105 else if ((opcode&0xFE) == 0xA2) { // MOV [mem],AL/AX
106 sx86_uword o;
107
108 o = softx86_fetch_exec_byte(ctx);
109 o |= softx86_fetch_exec_byte(ctx)<<8;
110 lo = sx86_far_to_linear(ctx,seg,o);
111
112 if (opcode&1) {
113 sx86_uword mem;
114
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);
118 }
119 else {
120 sx86_ubyte mem;
121
122 mem = ctx->state->general_reg[SX86_REG_AX].b.lo;
123 softx86_write(ctx,NULL,lo,&mem,1);
124 }
125
126 return 1;
127 }
128 else if ((opcode&0xF8) == 0xB0) { // MOV [reg = (opcode-0xB0)],imm8
129 sx86_ubyte b;
130
131 b = softx86_fetch_exec_byte(ctx);
132 *(ctx->__private->ptr_regs_8reg[opcode-0xB0]) = b;
133 return 1;
134 }
135 else if ((opcode&0xF8) == 0xB8) { // MOV [reg = (opcode-0xB8)],imm16
136 sx86_uword w;
137
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;
141 return 1;
142 }
143
144 return 0;
145 }
146
147 int Sfx86OpcodeDec_mov(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
148 {
149 if ((opcode&0xFC) == 0x88) { // MOV reg,reg/mem or reg/mem,reg
150 sx86_ubyte x;
151 sx86_ubyte w16,opswap;
152 sx86_ubyte mod,reg,rm;
153
154 w16 = (opcode&1);
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);
159
160 if (opswap) sprintf(buf,"MOV %s,%s",op2_tmp,op1_tmp);
161 else sprintf(buf,"MOV %s,%s",op1_tmp,op2_tmp);
162 return 1;
163 }
164 else if (opcode == 0x8C || opcode == 0x8E) { // MOV reg,reg/mem or reg/mem,reg
165 sx86_ubyte x;
166 sx86_ubyte opswap;
167 sx86_ubyte mod,reg,rm;
168
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);
173
174 if (opswap) sprintf(buf,"MOV %s,%s",op2_tmp,op1_tmp);
175 else sprintf(buf,"MOV %s,%s",op1_tmp,op2_tmp);
176 return 1;
177 }
178 else if ((opcode&0xFE) == 0xA0) { // MOV AL/AX,[mem]
179 sx86_uword o;
180
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);
184 return 1;
185 }
186 else if ((opcode&0xFE) == 0xA2) { // MOV [mem],AL/AX
187 sx86_uword o;
188
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");
192 return 1;
193 }
194 else if ((opcode&0xF8) == 0xB0) { // MOV [reg = (opcode-0xB0)],imm8
195 sx86_ubyte b;
196
197 b = softx86_fetch_dec_byte(ctx);
198 sprintf(buf,"MOV %s,%02Xh",sx86_regs8[opcode-0xB0],b);
199 return 1;
200 }
201 else if ((opcode&0xF8) == 0xB8) { // MOV [reg = (opcode-0xB8)],imm16
202 sx86_uword w;
203
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);
207 return 1;
208 }
209
210 return 0;
211 }
212
213 int Sfx86OpcodeExec_xlat(sx86_ubyte opcode,softx86_ctx* ctx)
214 {
215 sx86_uword seg;
216
217 if (!ctx->state->is_segment_override)
218 seg = ctx->state->segment_reg[SX86_SREG_DS].val;
219 else
220 seg = ctx->state->segment_override;
221
222 if ((opcode&0xFC) == 0xD7) { // MOV reg,reg/mem or reg/mem,reg
223 sx86_ubyte d;
224 sx86_udword ofs;
225
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);
228 ofs &= 0xFFFF;
229 ofs = sx86_far_to_linear(ctx,seg,ofs);
230
231 softx86_fetch(ctx,NULL,ofs,&d,1);
232 ctx->state->general_reg[SX86_REG_AX].b.lo = d;
233
234 return 1;
235 }
236
237 return 0;
238 }
239
240 int Sfx86OpcodeDec_xlat(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
241 {
242 if ((opcode&0xFC) == 0xD7) { // XLAT
243 strcpy(buf,"XLAT");
244 return 1;
245 }
246
247 return 0;
248 }
249
250 sx86_uword op_les16(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs)
251 {
252 softx86_setsegval(ctx,SX86_SREG_ES,seg);
253 return ofs;
254 }
255
256 sx86_udword op_les32(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs)
257 {
258 softx86_setsegval(ctx,SX86_SREG_ES,seg);
259 return ofs;
260 }
261
262 sx86_uword op_lds16(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs)
263 {
264 softx86_setsegval(ctx,SX86_SREG_DS,seg);
265 return ofs;
266 }
267
268 sx86_udword op_lds32(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs)
269 {
270 softx86_setsegval(ctx,SX86_SREG_DS,seg);
271 return ofs;
272 }
273
274 int Sfx86OpcodeExec_les(sx86_ubyte opcode,softx86_ctx* ctx)
275 {
276 if (opcode == 0xC4) { // LES
277 sx86_ubyte x;
278 sx86_ubyte mod,reg,rm;
279
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);
283 return 1;
284 }
285 if (opcode == 0xC5) { // LDS
286 sx86_ubyte x;
287 sx86_ubyte mod,reg,rm;
288
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);
292 return 1;
293 }
294
295 return 0;
296 }
297
298 int Sfx86OpcodeDec_les(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
299 {
300 if (opcode == 0xC4) { // LES
301 sx86_ubyte x;
302 sx86_ubyte mod,reg,rm;
303
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);
308 return 1;
309 }
310 if (opcode == 0xC5) { // LDS
311 sx86_ubyte x;
312 sx86_ubyte mod,reg,rm;
313
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);
318 return 1;
319 }
320
321 return 0;
322 }
323
324 sx86_uword op_lmsw16(softx86_ctx* ctx,sx86_uword src)
325 {
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 */
332 return 0;
333 }
334
335 sx86_uword op_smsw16(softx86_ctx* ctx,sx86_uword src)
336 {
337 return ((sx86_uword)ctx->state->reg_cr0);
338 }
339
340 int Sfx86OpcodeExec_lmsw286(sx86_ubyte opcode,softx86_ctx* ctx)
341 {
342 if (opcode == 0x01) { // LMSW [reg]
343 sx86_ubyte x;
344 sx86_ubyte mod,reg,rm;
345
346 x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm
347 sx86_modregrm_unpack(x,mod,reg,rm);
348
349 if (reg == 4)
350 sx86_exec_full_modrmonly_rw(ctx,1,0,mod,rm,NULL,op_smsw16,NULL);
351 else if (reg == 6)
352 sx86_exec_full_modrmonly_ro(ctx,1,0,mod,rm,NULL,op_lmsw16,NULL);
353 else
354 return 0;
355
356 return 1;
357 }
358
359 return 0;
360 }
361
362 int Sfx86OpcodeDec_lmsw286(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128])
363 {
364 if (opcode == 0x01) { // LMSW [reg]
365 sx86_ubyte x;
366 sx86_ubyte w16;
367 sx86_ubyte mod,reg,rm;
368
369 w16 = (opcode&1);
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);
373
374 if (reg == 4)
375 sprintf(buf,"SMSW %s",op1_tmp);
376 else if (reg == 6)
377 sprintf(buf,"LMSW %s",op1_tmp);
378 else
379 return 0;
380
381 return 1;
382 }
383
384 return 0;
385 }