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