1 /////////////////////////////////////////////////////////////////////////
2 // $Id: shift8.cc,v 1.38 2008/08/08 09:22:48 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
26 /////////////////////////////////////////////////////////////////////////
28 #define NEED_CPU_REG_SHORTCUTS 1
31 #define LOG_THIS BX_CPU_THIS_PTR
33 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROL_Eb(bxInstruction_c
*i
)
35 Bit8u op1_8
, result_8
;
44 /* op1 is a register or memory reference */
46 op1_8
= BX_READ_8BIT_REGx(i
->rm(), i
->extend8bitL());
49 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
50 /* pointer, segment address pair */
51 op1_8
= read_RMW_virtual_byte(i
->seg(), eaddr
);
54 if ((count
& 0x07) == 0) {
58 SET_FLAGS_OxxxxC(bit0
^ bit7
, bit0
);
63 count
&= 0x7; // use only lowest 3 bits
65 result_8
= (op1_8
<< count
) | (op1_8
>> (8 - count
));
67 /* now write result back to destination */
69 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
72 write_RMW_virtual_byte(result_8
);
76 * ROL count affects the following flags: C, O
79 bit0
= (result_8
& 1);
80 bit7
= (result_8
>> 7);
82 SET_FLAGS_OxxxxC(bit0
^ bit7
, bit0
);
85 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROR_Eb(bxInstruction_c
*i
)
87 Bit8u op1_8
, result_8
;
96 /* op1 is a register or memory reference */
98 op1_8
= BX_READ_8BIT_REGx(i
->rm(), i
->extend8bitL());
101 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
102 /* pointer, segment address pair */
103 op1_8
= read_RMW_virtual_byte(i
->seg(), eaddr
);
106 if ((count
& 0x07) == 0) {
108 bit6
= (op1_8
>> 6) & 1;
109 bit7
= (op1_8
>> 7) & 1;
111 SET_FLAGS_OxxxxC(bit6
^ bit7
, bit7
);
116 count
&= 0x7; /* use only bottom 3 bits */
118 result_8
= (op1_8
>> count
) | (op1_8
<< (8 - count
));
120 /* now write result back to destination */
122 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
125 write_RMW_virtual_byte(result_8
);
129 * ROR count affects the following flags: C, O
132 bit6
= (result_8
>> 6) & 1;
133 bit7
= (result_8
>> 7) & 1;
135 SET_FLAGS_OxxxxC(bit6
^ bit7
, bit7
);
138 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RCL_Eb(bxInstruction_c
*i
)
140 Bit8u op1_8
, result_8
;
149 /* op1 is a register or memory reference */
151 op1_8
= BX_READ_8BIT_REGx(i
->rm(), i
->extend8bitL());
154 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
155 /* pointer, segment address pair */
156 op1_8
= read_RMW_virtual_byte(i
->seg(), eaddr
);
159 count
= (count
& 0x1f) % 9;
164 result_8
= (op1_8
<< 1) | getB_CF();
167 result_8
= (op1_8
<< count
) | (getB_CF() << (count
- 1)) |
168 (op1_8
>> (9 - count
));
171 /* now write result back to destination */
173 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
176 write_RMW_virtual_byte(result_8
);
179 cf
= (op1_8
>> (8 - count
)) & 0x01;
180 of
= cf
^ (result_8
>> 7); // of = cf ^ result7
181 SET_FLAGS_OxxxxC(of
, cf
);
184 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RCR_Eb(bxInstruction_c
*i
)
186 Bit8u op1_8
, result_8
;
195 /* op1 is a register or memory reference */
197 op1_8
= BX_READ_8BIT_REGx(i
->rm(), i
->extend8bitL());
200 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
201 /* pointer, segment address pair */
202 op1_8
= read_RMW_virtual_byte(i
->seg(), eaddr
);
205 count
= (count
& 0x1f) % 9;
209 result_8
= (op1_8
>> count
) | (getB_CF() << (8 - count
)) |
210 (op1_8
<< (9 - count
));
212 /* now write result back to destination */
214 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
217 write_RMW_virtual_byte(result_8
);
220 cf
= (op1_8
>> (count
- 1)) & 0x1;
221 of
= ((result_8
<< 1) ^ result_8
) >> 7; // of = result6 ^ result7
222 SET_FLAGS_OxxxxC(of
, cf
);
225 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHL_Eb(bxInstruction_c
*i
)
227 Bit8u op1_8
, result_8
;
229 unsigned of
= 0, cf
= 0;
238 /* op1 is a register or memory reference */
240 op1_8
= BX_READ_8BIT_REGx(i
->rm(), i
->extend8bitL());
243 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
244 /* pointer, segment address pair */
245 op1_8
= read_RMW_virtual_byte(i
->seg(), eaddr
);
251 result_8
= (op1_8
<< count
);
252 cf
= (op1_8
>> (8 - count
)) & 0x1;
253 of
= cf
^ (result_8
>> 7);
259 /* now write result back to destination */
261 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
264 write_RMW_virtual_byte(result_8
);
267 SET_FLAGS_OSZAPC_LOGIC_8(result_8
); /* handle SF, ZF and AF flags */
268 SET_FLAGS_OxxxxC(of
, cf
);
271 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHR_Eb(bxInstruction_c
*i
)
273 Bit8u op1_8
, result_8
;
284 /* op1 is a register or memory reference */
286 op1_8
= BX_READ_8BIT_REGx(i
->rm(), i
->extend8bitL());
289 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
290 /* pointer, segment address pair */
291 op1_8
= read_RMW_virtual_byte(i
->seg(), eaddr
);
296 result_8
= (op1_8
>> count
);
298 /* now write result back to destination */
300 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
303 write_RMW_virtual_byte(result_8
);
306 cf
= (op1_8
>> (count
- 1)) & 0x1;
307 // note, that of == result7 if count == 1 and
308 // of == 0 if count >= 2
309 of
= ((result_8
<< 1) ^ result_8
) >> 7;
311 SET_FLAGS_OSZAPC_LOGIC_8(result_8
); /* handle SF, ZF and AF flags */
312 SET_FLAGS_OxxxxC(of
, cf
);
315 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SAR_Eb(bxInstruction_c
*i
)
317 Bit8u op1_8
, result_8
;
327 /* op1 is a register or memory reference */
329 op1_8
= BX_READ_8BIT_REGx(i
->rm(), i
->extend8bitL());
332 bx_address eaddr
= BX_CPU_CALL_METHODR(i
->ResolveModrm
, (i
));
333 /* pointer, segment address pair */
334 op1_8
= read_RMW_virtual_byte(i
->seg(), eaddr
);
341 result_8
= (op1_8
>> count
) | (0xff << (8 - count
));
344 result_8
= (op1_8
>> count
);
347 cf
= (op1_8
>> (count
- 1)) & 0x1;
357 cf
= (result_8
& 0x1);
360 SET_FLAGS_OSZAPC_LOGIC_8(result_8
); /* handle SF, ZF and AF flags */
361 /* signed overflow cannot happen in SAR instruction */
362 SET_FLAGS_OxxxxC(0, cf
);
364 /* now write result back to destination */
366 BX_WRITE_8BIT_REGx(i
->rm(), i
->extend8bitL(), result_8
);
369 write_RMW_virtual_byte(result_8
);