1 /////////////////////////////////////////////////////////////////////////
2 // $Id: data_xfer16.cc 13466 2018-02-16 07:57:32Z sshwarts $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2001-2018 The Bochs Project
6 //
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Lesser General Public
9 // License as published by the Free Software Foundation; either
10 // version 2 of the License, or (at your option) any later version.
11 //
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // Lesser General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public
18 // License along with this library; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
20 /////////////////////////////////////////////////////////////////////////
21
22 #define NEED_CPU_REG_SHORTCUTS 1
23 #include "bochs.h"
24 #include "cpu.h"
25 #define LOG_THIS BX_CPU_THIS_PTR
26
MOV_EwIwM(bxInstruction_c * i)27 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EwIwM(bxInstruction_c *i)
28 {
29 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
30 write_virtual_word(i->seg(), eaddr, i->Iw());
31
32 BX_NEXT_INSTR(i);
33 }
34
MOV_EwIwR(bxInstruction_c * i)35 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EwIwR(bxInstruction_c *i)
36 {
37 BX_WRITE_16BIT_REG(i->dst(), i->Iw());
38
39 BX_NEXT_INSTR(i);
40 }
41
MOV_EwGwM(bxInstruction_c * i)42 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EwGwM(bxInstruction_c *i)
43 {
44 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
45
46 write_virtual_word(i->seg(), eaddr, BX_READ_16BIT_REG(i->src()));
47
48 BX_NEXT_INSTR(i);
49 }
50
MOV_GwEwR(bxInstruction_c * i)51 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_GwEwR(bxInstruction_c *i)
52 {
53 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
54
55 BX_NEXT_INSTR(i);
56 }
57
MOV_GwEwM(bxInstruction_c * i)58 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_GwEwM(bxInstruction_c *i)
59 {
60 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
61 Bit16u val16 = read_virtual_word(i->seg(), eaddr);
62 BX_WRITE_16BIT_REG(i->dst(), val16);
63
64 BX_NEXT_INSTR(i);
65 }
66
MOV_EwSwR(bxInstruction_c * i)67 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EwSwR(bxInstruction_c *i)
68 {
69 /* Illegal to use nonexisting segments */
70 if (i->src() >= 6) {
71 BX_INFO(("MOV_EwSw: using of nonexisting segment register %d", i->src()));
72 exception(BX_UD_EXCEPTION, 0);
73 }
74
75 Bit16u seg_reg = BX_CPU_THIS_PTR sregs[i->src()].selector.value;
76
77 if (i->os32L()) {
78 BX_WRITE_32BIT_REGZ(i->dst(), seg_reg);
79 }
80 else {
81 BX_WRITE_16BIT_REG(i->dst(), seg_reg);
82 }
83
84 BX_NEXT_INSTR(i);
85 }
86
MOV_EwSwM(bxInstruction_c * i)87 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EwSwM(bxInstruction_c *i)
88 {
89 /* Illegal to use nonexisting segments */
90 if (i->src() >= 6) {
91 BX_INFO(("MOV_EwSw: using of nonexisting segment register %d", i->src()));
92 exception(BX_UD_EXCEPTION, 0);
93 }
94
95 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
96
97 Bit16u seg_reg = BX_CPU_THIS_PTR sregs[i->src()].selector.value;
98 write_virtual_word(i->seg(), eaddr, seg_reg);
99
100 BX_NEXT_INSTR(i);
101 }
102
MOV_SwEw(bxInstruction_c * i)103 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_SwEw(bxInstruction_c *i)
104 {
105 Bit16u op2_16;
106
107 /* Attempt to load CS or nonexisting segment register */
108 if (i->dst() >= 6 || i->dst() == BX_SEG_REG_CS) {
109 BX_INFO(("MOV_EwSw: can't use this segment register %d", i->dst()));
110 exception(BX_UD_EXCEPTION, 0);
111 }
112
113 if (i->modC0()) {
114 op2_16 = BX_READ_16BIT_REG(i->src());
115 }
116 else {
117 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
118 /* pointer, segment address pair */
119 op2_16 = read_virtual_word(i->seg(), eaddr);
120 }
121
122 load_seg_reg(&BX_CPU_THIS_PTR sregs[i->dst()], op2_16);
123
124 if (i->dst() == BX_SEG_REG_SS) {
125 // MOV SS inhibits interrupts, debug exceptions and single-step
126 // trap exceptions until the execution boundary following the
127 // next instruction is reached.
128 // Same code as POP_SS()
129 inhibit_interrupts(BX_INHIBIT_INTERRUPTS_BY_MOVSS);
130 }
131
132 BX_NEXT_INSTR(i);
133 }
134
LEA_GwM(bxInstruction_c * i)135 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LEA_GwM(bxInstruction_c *i)
136 {
137 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
138
139 BX_WRITE_16BIT_REG(i->dst(), (Bit16u) eaddr);
140
141 BX_NEXT_INSTR(i);
142 }
143
MOV_AXOd(bxInstruction_c * i)144 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_AXOd(bxInstruction_c *i)
145 {
146 AX = read_virtual_word_32(i->seg(), i->Id());
147
148 BX_NEXT_INSTR(i);
149 }
150
MOV_OdAX(bxInstruction_c * i)151 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_OdAX(bxInstruction_c *i)
152 {
153 write_virtual_word_32(i->seg(), i->Id(), AX);
154
155 BX_NEXT_INSTR(i);
156 }
157
MOVZX_GwEbM(bxInstruction_c * i)158 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVZX_GwEbM(bxInstruction_c *i)
159 {
160 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
161
162 Bit8u op2_8 = read_virtual_byte(i->seg(), eaddr);
163
164 /* zero extend byte op2 into word op1 */
165 BX_WRITE_16BIT_REG(i->dst(), (Bit16u) op2_8);
166
167 BX_NEXT_INSTR(i);
168 }
169
MOVZX_GwEbR(bxInstruction_c * i)170 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVZX_GwEbR(bxInstruction_c *i)
171 {
172 Bit8u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL());
173
174 /* zero extend byte op2 into word op1 */
175 BX_WRITE_16BIT_REG(i->dst(), (Bit16u) op2_8);
176
177 BX_NEXT_INSTR(i);
178 }
179
MOVSX_GwEbM(bxInstruction_c * i)180 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GwEbM(bxInstruction_c *i)
181 {
182 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
183
184 Bit8u op2_8 = read_virtual_byte(i->seg(), eaddr);
185
186 /* sign extend byte op2 into word op1 */
187 BX_WRITE_16BIT_REG(i->dst(), (Bit8s) op2_8);
188
189 BX_NEXT_INSTR(i);
190 }
191
MOVSX_GwEbR(bxInstruction_c * i)192 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GwEbR(bxInstruction_c *i)
193 {
194 Bit8u op2_8 = BX_READ_8BIT_REGx(i->src(),i->extend8bitL());
195
196 /* sign extend byte op2 into word op1 */
197 BX_WRITE_16BIT_REG(i->dst(), (Bit8s) op2_8);
198
199 BX_NEXT_INSTR(i);
200 }
201
XCHG_EwGwM(bxInstruction_c * i)202 void BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_EwGwM(bxInstruction_c *i)
203 {
204 Bit16u op1_16, op2_16;
205
206 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
207
208 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
209 op2_16 = BX_READ_16BIT_REG(i->src());
210
211 write_RMW_linear_word(op2_16);
212 BX_WRITE_16BIT_REG(i->src(), op1_16);
213
214 BX_NEXT_INSTR(i);
215 }
216
XCHG_EwGwR(bxInstruction_c * i)217 void BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_EwGwR(bxInstruction_c *i)
218 {
219 Bit16u op1_16, op2_16;
220
221 #if BX_DEBUGGER
222 // Note for mortals: the instruction to trigger this is "xchgw %bx,%bx"
223 if (bx_dbg.magic_break_enabled && (i->src() == 3) && (i->dst() == 3))
224 {
225 BX_CPU_THIS_PTR magic_break = 1;
226 BX_NEXT_INSTR(i);
227 }
228 #endif
229
230 op1_16 = BX_READ_16BIT_REG(i->dst());
231 op2_16 = BX_READ_16BIT_REG(i->src());
232
233 BX_WRITE_16BIT_REG(i->src(), op1_16);
234 BX_WRITE_16BIT_REG(i->dst(), op2_16);
235
236 BX_NEXT_INSTR(i);
237 }
238
239 // Note: CMOV accesses a memory source operand (read), regardless
240 // of whether condition is true or not. Thus, exceptions may
241 // occur even if the MOV does not take place.
242
CMOVO_GwEwR(bxInstruction_c * i)243 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVO_GwEwR(bxInstruction_c *i)
244 {
245 if (get_OF())
246 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
247
248 BX_NEXT_INSTR(i);
249 }
250
CMOVNO_GwEwR(bxInstruction_c * i)251 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNO_GwEwR(bxInstruction_c *i)
252 {
253 if (!get_OF())
254 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
255
256 BX_NEXT_INSTR(i);
257 }
258
CMOVB_GwEwR(bxInstruction_c * i)259 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVB_GwEwR(bxInstruction_c *i)
260 {
261 if (get_CF())
262 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
263
264 BX_NEXT_INSTR(i);
265 }
266
CMOVNB_GwEwR(bxInstruction_c * i)267 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNB_GwEwR(bxInstruction_c *i)
268 {
269 if (!get_CF())
270 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
271
272 BX_NEXT_INSTR(i);
273 }
274
CMOVZ_GwEwR(bxInstruction_c * i)275 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVZ_GwEwR(bxInstruction_c *i)
276 {
277 if (get_ZF())
278 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
279
280 BX_NEXT_INSTR(i);
281 }
282
CMOVNZ_GwEwR(bxInstruction_c * i)283 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNZ_GwEwR(bxInstruction_c *i)
284 {
285 if (!get_ZF())
286 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
287
288 BX_NEXT_INSTR(i);
289 }
290
CMOVBE_GwEwR(bxInstruction_c * i)291 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVBE_GwEwR(bxInstruction_c *i)
292 {
293 if (get_CF() || get_ZF())
294 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
295
296 BX_NEXT_INSTR(i);
297 }
298
CMOVNBE_GwEwR(bxInstruction_c * i)299 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNBE_GwEwR(bxInstruction_c *i)
300 {
301 if (! (get_CF() || get_ZF()))
302 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
303
304 BX_NEXT_INSTR(i);
305 }
306
CMOVS_GwEwR(bxInstruction_c * i)307 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVS_GwEwR(bxInstruction_c *i)
308 {
309 if (get_SF())
310 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
311
312 BX_NEXT_INSTR(i);
313 }
314
CMOVNS_GwEwR(bxInstruction_c * i)315 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNS_GwEwR(bxInstruction_c *i)
316 {
317 if (!get_SF())
318 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
319
320 BX_NEXT_INSTR(i);
321 }
322
CMOVP_GwEwR(bxInstruction_c * i)323 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVP_GwEwR(bxInstruction_c *i)
324 {
325 if (get_PF())
326 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
327
328 BX_NEXT_INSTR(i);
329 }
330
CMOVNP_GwEwR(bxInstruction_c * i)331 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNP_GwEwR(bxInstruction_c *i)
332 {
333 if (!get_PF())
334 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
335
336 BX_NEXT_INSTR(i);
337 }
338
CMOVL_GwEwR(bxInstruction_c * i)339 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVL_GwEwR(bxInstruction_c *i)
340 {
341 if (getB_SF() != getB_OF())
342 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
343
344 BX_NEXT_INSTR(i);
345 }
346
CMOVNL_GwEwR(bxInstruction_c * i)347 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNL_GwEwR(bxInstruction_c *i)
348 {
349 if (getB_SF() == getB_OF())
350 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
351
352 BX_NEXT_INSTR(i);
353 }
354
CMOVLE_GwEwR(bxInstruction_c * i)355 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVLE_GwEwR(bxInstruction_c *i)
356 {
357 if (get_ZF() || (getB_SF() != getB_OF()))
358 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
359
360 BX_NEXT_INSTR(i);
361 }
362
CMOVNLE_GwEwR(bxInstruction_c * i)363 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNLE_GwEwR(bxInstruction_c *i)
364 {
365 if (! get_ZF() && (getB_SF() == getB_OF()))
366 BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src()));
367
368 BX_NEXT_INSTR(i);
369 }
370