- compilation fixes for MSVC toolkit 2003
[bochs-mirror.git] / cpu / shift16.cc
blob0938577300c712c8bb7498216c98248e7bcc593e
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: shift16.cc,v 1.47 2008/08/08 09:22:48 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2001 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /////////////////////////////////////////////////////////////////////////
28 #define NEED_CPU_REG_SHORTCUTS 1
29 #include "bochs.h"
30 #include "cpu.h"
31 #define LOG_THIS BX_CPU_THIS_PTR
33 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHLD_EwGwM(bxInstruction_c *i)
35 Bit16u op1_16, op2_16, result_16;
36 Bit32u temp_32, result_32;
37 unsigned count;
38 unsigned of, cf;
40 /* op1:op2 << count. result stored in op1 */
41 if (i->b1() == 0xa4) // 0x1a4
42 count = i->Ib();
43 else // 0x1a5
44 count = CL;
46 count &= 0x1f; // use only 5 LSB's
48 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
50 /* pointer, segment address pair */
51 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
53 if (!count) return;
55 op2_16 = BX_READ_16BIT_REG(i->nnn());
57 /* count < 32, since only lower 5 bits used */
58 temp_32 = ((Bit32u)(op1_16) << 16) | (op2_16); // double formed by op1:op2
59 result_32 = temp_32 << count;
61 // hack to act like x86 SHLD when count > 16
62 if (count > 16) {
63 // when count > 16 actually shifting op1:op2:op2 << count,
64 // it is the same as shifting op2:op2 by count-16
65 result_32 |= (op1_16 << (count - 16));
68 result_16 = (Bit16u)(result_32 >> 16);
70 write_RMW_virtual_word(result_16);
72 SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle SF, ZF and AF flags */
74 cf = (temp_32 >> (32 - count)) & 0x1;
75 of = cf ^ (result_16 >> 15); // of = cf ^ result15
76 SET_FLAGS_OxxxxC(of, cf);
79 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHLD_EwGwR(bxInstruction_c *i)
81 Bit16u op1_16, op2_16, result_16;
82 Bit32u temp_32, result_32;
83 unsigned count;
84 unsigned of, cf;
86 /* op1:op2 << count. result stored in op1 */
87 if (i->b1() == 0xa4) // 0x1a4
88 count = i->Ib();
89 else // 0x1a5
90 count = CL;
92 count &= 0x1f; // use only 5 LSB's
94 if (!count) return;
96 op1_16 = BX_READ_16BIT_REG(i->rm());
97 op2_16 = BX_READ_16BIT_REG(i->nnn());
99 /* count < 32, since only lower 5 bits used */
100 temp_32 = ((Bit32u)(op1_16) << 16) | (op2_16); // double formed by op1:op2
101 result_32 = temp_32 << count;
103 // hack to act like x86 SHLD when count > 16
104 if (count > 16) {
105 // when count > 16 actually shifting op1:op2:op2 << count,
106 // it is the same as shifting op2:op2 by count-16
107 result_32 |= (op1_16 << (count - 16));
110 result_16 = (Bit16u)(result_32 >> 16);
112 BX_WRITE_16BIT_REG(i->rm(), result_16);
114 SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle SF, ZF and AF flags */
116 cf = (temp_32 >> (32 - count)) & 0x1;
117 of = cf ^ (result_16 >> 15); // of = cf ^ result15
118 SET_FLAGS_OxxxxC(of, cf);
121 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHRD_EwGwM(bxInstruction_c *i)
123 Bit16u op1_16, op2_16, result_16;
124 Bit32u temp_32, result_32;
125 unsigned count;
126 unsigned cf, of;
128 if (i->b1() == 0xac) // 0x1ac
129 count = i->Ib();
130 else // 0x1ad
131 count = CL;
133 count &= 0x1f; /* use only 5 LSB's */
135 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
137 /* pointer, segment address pair */
138 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
140 if (!count) return;
142 op2_16 = BX_READ_16BIT_REG(i->nnn());
144 /* count < 32, since only lower 5 bits used */
145 temp_32 = (op2_16 << 16) | op1_16; // double formed by op2:op1
146 result_32 = temp_32 >> count;
148 // hack to act like x86 SHRD when count > 16
149 if (count > 16) {
150 // when count > 16 actually shifting op2:op2:op1 >> count,
151 // it is the same as shifting op2:op2 by count-16
152 result_32 |= (op1_16 << (32 - count));
155 result_16 = (Bit16u) result_32;
157 write_RMW_virtual_word(result_16);
159 SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle SF, ZF and AF flags */
161 cf = (op1_16 >> (count - 1)) & 0x1;
162 of = ((result_16 << 1) ^ result_16) >> 15; // of = result14 ^ result15
163 SET_FLAGS_OxxxxC(of, cf);
166 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHRD_EwGwR(bxInstruction_c *i)
168 Bit16u op1_16, op2_16, result_16;
169 Bit32u temp_32, result_32;
170 unsigned count;
171 unsigned cf, of;
173 if (i->b1() == 0xac) // 0x1ac
174 count = i->Ib();
175 else // 0x1ad
176 count = CL;
178 count &= 0x1f; /* use only 5 LSB's */
180 if (!count) return;
182 op1_16 = BX_READ_16BIT_REG(i->rm());
183 op2_16 = BX_READ_16BIT_REG(i->nnn());
185 /* count < 32, since only lower 5 bits used */
186 temp_32 = (op2_16 << 16) | op1_16; // double formed by op2:op1
187 result_32 = temp_32 >> count;
189 // hack to act like x86 SHRD when count > 16
190 if (count > 16) {
191 // when count > 16 actually shifting op2:op2:op1 >> count,
192 // it is the same as shifting op2:op2 by count-16
193 result_32 |= (op1_16 << (32 - count));
196 result_16 = (Bit16u) result_32;
198 BX_WRITE_16BIT_REG(i->rm(), result_16);
200 SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle SF, ZF and AF flags */
202 cf = (op1_16 >> (count - 1)) & 0x1;
203 of = ((result_16 << 1) ^ result_16) >> 15; // of = result14 ^ result15
204 SET_FLAGS_OxxxxC(of, cf);
207 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROL_Ew(bxInstruction_c *i)
209 Bit16u op1_16, result_16;
210 unsigned count;
211 unsigned bit0, bit15;
213 if (i->b1() == 0xd3)
214 count = CL;
215 else // 0xc1 or 0xd1
216 count = i->Ib();
218 /* op1 is a register or memory reference */
219 if (i->modC0()) {
220 op1_16 = BX_READ_16BIT_REG(i->rm());
222 else {
223 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
224 /* pointer, segment address pair */
225 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
228 if ((count & 0x0f) == 0) {
229 if (count & 0x10) {
230 bit0 = (op1_16 & 0x1);
231 bit15 = (op1_16 >> 15);
232 // of = cf ^ result15
233 SET_FLAGS_OxxxxC(bit0 ^ bit15, bit0);
235 return;
238 count &= 0x0f; // only use bottom 4 bits
240 result_16 = (op1_16 << count) | (op1_16 >> (16 - count));
242 /* now write result back to destination */
243 if (i->modC0()) {
244 BX_WRITE_16BIT_REG(i->rm(), result_16);
246 else {
247 write_RMW_virtual_word(result_16);
250 bit0 = (result_16 & 0x1);
251 bit15 = (result_16 >> 15);
252 // of = cf ^ result15
253 SET_FLAGS_OxxxxC(bit0 ^ bit15, bit0);
256 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROR_Ew(bxInstruction_c *i)
258 Bit16u op1_16, result_16;
259 unsigned count;
260 unsigned bit14, bit15;
262 if (i->b1() == 0xd3)
263 count = CL;
264 else // 0xc1 or 0xd1
265 count = i->Ib();
267 /* op1 is a register or memory reference */
268 if (i->modC0()) {
269 op1_16 = BX_READ_16BIT_REG(i->rm());
271 else {
272 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
273 /* pointer, segment address pair */
274 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
277 if ((count & 0x0f) == 0) {
278 if (count & 0x10) {
279 bit14 = (op1_16 >> 14) & 1;
280 bit15 = (op1_16 >> 15) & 1;
281 // of = result14 ^ result15
282 SET_FLAGS_OxxxxC(bit14 ^ bit15, bit15);
284 return;
287 count &= 0x0f; // use only 4 LSB's
289 result_16 = (op1_16 >> count) | (op1_16 << (16 - count));
291 /* now write result back to destination */
292 if (i->modC0()) {
293 BX_WRITE_16BIT_REG(i->rm(), result_16);
295 else {
296 write_RMW_virtual_word(result_16);
299 bit14 = (result_16 >> 14) & 1;
300 bit15 = (result_16 >> 15) & 1;
301 // of = result14 ^ result15
302 SET_FLAGS_OxxxxC(bit14 ^ bit15, bit15);
305 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RCL_Ew(bxInstruction_c *i)
307 Bit16u op1_16, result_16;
308 unsigned count;
309 unsigned of, cf;
311 if (i->b1() == 0xd3)
312 count = CL;
313 else // 0xc1 or 0xd1
314 count = i->Ib();
316 count = (count & 0x1f) % 17;
318 /* op1 is a register or memory reference */
319 if (i->modC0()) {
320 op1_16 = BX_READ_16BIT_REG(i->rm());
322 else {
323 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
324 /* pointer, segment address pair */
325 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
328 if (!count) return;
330 if (count==1) {
331 result_16 = (op1_16 << 1) | getB_CF();
333 else if (count==16) {
334 result_16 = (getB_CF() << 15) | (op1_16 >> 1);
336 else { // 2..15
337 result_16 = (op1_16 << count) | (getB_CF() << (count - 1)) |
338 (op1_16 >> (17 - count));
341 /* now write result back to destination */
342 if (i->modC0()) {
343 BX_WRITE_16BIT_REG(i->rm(), result_16);
345 else {
346 write_RMW_virtual_word(result_16);
349 cf = (op1_16 >> (16 - count)) & 0x1;
350 of = cf ^ (result_16 >> 15); // of = cf ^ result15
351 SET_FLAGS_OxxxxC(of, cf);
354 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RCR_Ew(bxInstruction_c *i)
356 Bit16u op1_16, result_16;
357 unsigned count;
358 unsigned of, cf;
360 if (i->b1() == 0xd3)
361 count = CL;
362 else // 0xc1 or 0xd1
363 count = i->Ib();
365 count = (count & 0x1f) % 17;
367 /* op1 is a register or memory reference */
368 if (i->modC0()) {
369 op1_16 = BX_READ_16BIT_REG(i->rm());
371 else {
372 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
373 /* pointer, segment address pair */
374 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
377 if (! count) return;
379 result_16 = (op1_16 >> count) | (getB_CF() << (16 - count)) |
380 (op1_16 << (17 - count));
382 /* now write result back to destination */
383 if (i->modC0()) {
384 BX_WRITE_16BIT_REG(i->rm(), result_16);
386 else {
387 write_RMW_virtual_word(result_16);
390 cf = (op1_16 >> (count - 1)) & 0x1;
391 of = ((result_16 << 1) ^ result_16) >> 15; // of = result15 ^ result14
392 SET_FLAGS_OxxxxC(of, cf);
395 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHL_Ew(bxInstruction_c *i)
397 Bit16u op1_16, result_16;
398 unsigned count;
399 unsigned of = 0, cf = 0;
401 if (i->b1() == 0xd3)
402 count = CL;
403 else // 0xc1 or 0xd1
404 count = i->Ib();
406 count &= 0x1f; /* use only 5 LSB's */
408 /* op1 is a register or memory reference */
409 if (i->modC0()) {
410 op1_16 = BX_READ_16BIT_REG(i->rm());
412 else {
413 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
414 /* pointer, segment address pair */
415 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
418 if (!count) return;
420 if (count <= 16) {
421 result_16 = (op1_16 << count);
422 cf = (op1_16 >> (16 - count)) & 0x1;
423 of = cf ^ (result_16 >> 15); // of = cf ^ result15
425 else {
426 result_16 = 0;
429 /* now write result back to destination */
430 if (i->modC0()) {
431 BX_WRITE_16BIT_REG(i->rm(), result_16);
433 else {
434 write_RMW_virtual_word(result_16);
437 SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle SF, ZF and AF flags */
438 SET_FLAGS_OxxxxC(of, cf);
441 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHR_Ew(bxInstruction_c *i)
443 Bit16u op1_16, result_16;
444 unsigned count;
445 unsigned of, cf;
447 if (i->b1() == 0xd3)
448 count = CL;
449 else // 0xc1 or 0xd1
450 count = i->Ib();
452 count &= 0x1f; /* use only 5 LSB's */
454 /* op1 is a register or memory reference */
455 if (i->modC0()) {
456 op1_16 = BX_READ_16BIT_REG(i->rm());
458 else {
459 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
460 /* pointer, segment address pair */
461 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
464 if (!count) return;
466 result_16 = (op1_16 >> count);
468 /* now write result back to destination */
469 if (i->modC0()) {
470 BX_WRITE_16BIT_REG(i->rm(), result_16);
472 else {
473 write_RMW_virtual_word(result_16);
476 cf = (op1_16 >> (count - 1)) & 0x1;
477 // note, that of == result15 if count == 1 and
478 // of == 0 if count >= 2
479 of = ((result_16 << 1) ^ result_16) >> 15;
481 SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle SF, ZF and AF flags */
482 SET_FLAGS_OxxxxC(of, cf);
485 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SAR_Ew(bxInstruction_c *i)
487 Bit16u op1_16, result_16;
488 unsigned count, cf;
490 if (i->b1() == 0xd3)
491 count = CL;
492 else // 0xc1 or 0xd1
493 count = i->Ib();
495 count &= 0x1f; /* use only 5 LSB's */
497 /* op1 is a register or memory reference */
498 if (i->modC0()) {
499 op1_16 = BX_READ_16BIT_REG(i->rm());
501 else {
502 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
503 /* pointer, segment address pair */
504 op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
507 if (!count) return;
509 if (count < 16) {
510 if (op1_16 & 0x8000) {
511 result_16 = (op1_16 >> count) | (0xffff << (16 - count));
513 else {
514 result_16 = (op1_16 >> count);
517 cf = (op1_16 >> (count - 1)) & 0x1;
519 else {
520 if (op1_16 & 0x8000) {
521 result_16 = 0xffff;
523 else {
524 result_16 = 0;
527 cf = (result_16 & 0x1);
530 SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* handle SF, ZF and AF flags */
531 /* signed overflow cannot happen in SAR instruction */
532 SET_FLAGS_OxxxxC(0, cf);
534 /* now write result back to destination */
535 if (i->modC0()) {
536 BX_WRITE_16BIT_REG(i->rm(), result_16);
538 else {
539 write_RMW_virtual_word(result_16);