1 /////////////////////////////////////////////////////////////////////////
2 // $Id: shift32.cc,v 1.31 2006/03/26 18:58:01 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2001 MandrakeSoft S.A.
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
28 #define NEED_CPU_REG_SHORTCUTS 1
31 #define LOG_THIS BX_CPU_THIS_PTR
34 void BX_CPU_C::SHLD_EdGd(bxInstruction_c
*i
)
36 Bit32u op1_32
, op2_32
, result_32
;
39 /* op1:op2 << count. result stored in op1 */
42 count
= i
->Ib() & 0x1f;
46 /* op1 is a register or memory reference */
48 op1_32
= BX_READ_32BIT_REG(i
->rm());
51 /* pointer, segment address pair */
52 read_RMW_virtual_dword(i
->seg(), RMAddr(i
), &op1_32
);
57 op2_32
= BX_READ_32BIT_REG(i
->nnn());
59 result_32
= (op1_32
<< count
) | (op2_32
>> (32 - count
));
61 /* now write result back to destination */
63 BX_WRITE_32BIT_REGZ(i
->rm(), result_32
);
66 write_RMW_virtual_dword(result_32
);
70 * SHLD count affects the following flags: O,S,Z,A,P,C
72 SET_FLAGS_OSZAPC_32(op1_32
, count
, result_32
, BX_INSTR_SHL32
);
75 void BX_CPU_C::SHRD_EdGd(bxInstruction_c
*i
)
77 Bit32u op1_32
, op2_32
, result_32
;
81 count
= i
->Ib() & 0x1f;
85 /* op1 is a register or memory reference */
87 op1_32
= BX_READ_32BIT_REG(i
->rm());
90 /* pointer, segment address pair */
91 read_RMW_virtual_dword(i
->seg(), RMAddr(i
), &op1_32
);
96 op2_32
= BX_READ_32BIT_REG(i
->nnn());
98 result_32
= (op2_32
<< (32 - count
)) | (op1_32
>> count
);
100 /* now write result back to destination */
102 BX_WRITE_32BIT_REGZ(i
->rm(), result_32
);
105 write_RMW_virtual_dword(result_32
);
109 * SHRD count affects the following flags: O,S,Z,A,P,C
111 SET_FLAGS_OSZAPC_32(op1_32
, count
, result_32
, BX_INSTR_SHRD32
);
114 void BX_CPU_C::ROL_Ed(bxInstruction_c
*i
)
116 Bit32u op1_32
, result_32
;
120 count
= i
->Ib() & 0x1f;
121 else if (i
->b1() == 0xd1)
123 else // (i->b1() == 0xd3)
126 /* op1 is a register or memory reference */
128 op1_32
= BX_READ_32BIT_REG(i
->rm());
131 /* pointer, segment address pair */
132 read_RMW_virtual_dword(i
->seg(), RMAddr(i
), &op1_32
);
137 result_32
= (op1_32
<< count
) | (op1_32
>> (32 - count
));
139 /* now write result back to destination */
141 BX_WRITE_32BIT_REGZ(i
->rm(), result_32
);
144 write_RMW_virtual_dword(result_32
);
148 * ROL count affects the following flags: C, O
150 bx_bool temp_CF
= (result_32
& 0x01);
153 set_OF(temp_CF
^ (result_32
>> 31));
156 void BX_CPU_C::ROR_Ed(bxInstruction_c
*i
)
158 Bit32u op1_32
, result_32
;
162 count
= i
->Ib() & 0x1f;
163 else if (i
->b1() == 0xd1)
165 else // (i->b1() == 0xd3)
168 /* op1 is a register or memory reference */
170 op1_32
= BX_READ_32BIT_REG(i
->rm());
173 /* pointer, segment address pair */
174 read_RMW_virtual_dword(i
->seg(), RMAddr(i
), &op1_32
);
179 result_32
= (op1_32
>> count
) | (op1_32
<< (32 - count
));
181 /* now write result back to destination */
183 BX_WRITE_32BIT_REGZ(i
->rm(), result_32
);
186 write_RMW_virtual_dword(result_32
);
190 * ROR count affects the following flags: C, O
192 bx_bool result_b31
= (result_32
& 0x80000000) != 0;
193 bx_bool result_b30
= (result_32
& 0x40000000) != 0;
196 set_OF(result_b31
^ result_b30
);
199 void BX_CPU_C::RCL_Ed(bxInstruction_c
*i
)
201 Bit32u op1_32
, result_32
;
205 count
= i
->Ib() & 0x1f;
206 else if (i
->b1() == 0xd1)
208 else // (i->b1() == 0xd3)
211 /* op1 is a register or memory reference */
213 op1_32
= BX_READ_32BIT_REG(i
->rm());
216 /* pointer, segment address pair */
217 read_RMW_virtual_dword(i
->seg(), RMAddr(i
), &op1_32
);
223 result_32
= (op1_32
<< 1) | getB_CF();
226 result_32
= (op1_32
<< count
) | (getB_CF() << (count
- 1)) |
227 (op1_32
>> (33 - count
));
230 /* now write result back to destination */
232 BX_WRITE_32BIT_REGZ(i
->rm(), result_32
);
235 write_RMW_virtual_dword(result_32
);
239 * RCL count affects the following flags: C, O
241 bx_bool temp_CF
= (op1_32
>> (32 - count
)) & 0x01;
244 set_OF(temp_CF
^ (result_32
>> 31));
247 void BX_CPU_C::RCR_Ed(bxInstruction_c
*i
)
249 Bit32u op1_32
, result_32
;
253 count
= i
->Ib() & 0x1f;
254 else if (i
->b1() == 0xd1)
256 else // (i->b1() == 0xd3)
259 /* op1 is a register or memory reference */
261 op1_32
= BX_READ_32BIT_REG(i
->rm());
264 /* pointer, segment address pair */
265 read_RMW_virtual_dword(i
->seg(), RMAddr(i
), &op1_32
);
271 result_32
= (op1_32
>> 1) | (getB_CF() << 31);
274 result_32
= (op1_32
>> count
) | (getB_CF() << (32 - count
)) |
275 (op1_32
<< (33 - count
));
278 /* now write result back to destination */
280 BX_WRITE_32BIT_REGZ(i
->rm(), result_32
);
283 write_RMW_virtual_dword(result_32
);
287 * RCR count affects the following flags: C, O
290 set_CF((op1_32
>> (count
- 1)) & 0x01);
291 set_OF((((result_32
<< 1) ^ result_32
) & 0x80000000) > 0);
294 void BX_CPU_C::SHL_Ed(bxInstruction_c
*i
)
296 Bit32u op1_32
, result_32
;
300 count
= i
->Ib() & 0x1f;
301 else if (i
->b1() == 0xd1)
303 else // (i->b1() == 0xd3)
306 /* op1 is a register or memory reference */
308 op1_32
= BX_READ_32BIT_REG(i
->rm());
311 /* pointer, segment address pair */
312 read_RMW_virtual_dword(i
->seg(), RMAddr(i
), &op1_32
);
317 result_32
= (op1_32
<< count
);
319 /* now write result back to destination */
321 BX_WRITE_32BIT_REGZ(i
->rm(), result_32
);
324 write_RMW_virtual_dword(result_32
);
327 SET_FLAGS_OSZAPC_32(op1_32
, count
, result_32
, BX_INSTR_SHL32
);
330 void BX_CPU_C::SHR_Ed(bxInstruction_c
*i
)
332 Bit32u op1_32
, result_32
;
336 count
= i
->Ib() & 0x1f;
337 else if (i
->b1() == 0xd1)
339 else // (i->b1() == 0xd3)
342 /* op1 is a register or memory reference */
344 op1_32
= BX_READ_32BIT_REG(i
->rm());
347 /* pointer, segment address pair */
348 read_RMW_virtual_dword(i
->seg(), RMAddr(i
), &op1_32
);
353 #if defined(BX_HostAsm_Shr32)
355 asmShr32(result_32
, op1_32
, count
, flags32
);
356 setEFlagsOSZAPC(flags32
);
358 result_32
= (op1_32
>> count
);
359 SET_FLAGS_OSZAPC_32(op1_32
, count
, result_32
, BX_INSTR_SHR32
);
362 /* now write result back to destination */
364 BX_WRITE_32BIT_REGZ(i
->rm(), result_32
);
367 write_RMW_virtual_dword(result_32
);
371 void BX_CPU_C::SAR_Ed(bxInstruction_c
*i
)
373 Bit32u op1_32
, result_32
;
377 count
= i
->Ib() & 0x1f;
378 else if (i
->b1() == 0xd1)
380 else // (i->b1() == 0xd3)
383 /* op1 is a register or memory reference */
385 op1_32
= BX_READ_32BIT_REG(i
->rm());
388 /* pointer, segment address pair */
389 read_RMW_virtual_dword(i
->seg(), RMAddr(i
), &op1_32
);
394 /* count < 32, since only lower 5 bits used */
395 if (op1_32
& 0x80000000) {
396 result_32
= (op1_32
>> count
) | (0xffffffff << (32 - count
));
399 result_32
= (op1_32
>> count
);
402 /* now write result back to destination */
404 BX_WRITE_32BIT_REGZ(i
->rm(), result_32
);
407 write_RMW_virtual_dword(result_32
);
410 SET_FLAGS_OSZAPC_32(op1_32
, count
, result_32
, BX_INSTR_SAR32
);