- added instructions how to update the online documentation
[bochs-mirror.git] / cpu / shift8.cc
blob078b7377ecbf9393ed44e9e794bda5b193d98d3f
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: shift8.cc,v 1.38 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::ROL_Eb(bxInstruction_c *i)
35 Bit8u op1_8, result_8;
36 unsigned count;
37 unsigned bit0, bit7;
39 if (i->b1() == 0xd2)
40 count = CL;
41 else // 0xc0 or 0xd0
42 count = i->Ib();
44 /* op1 is a register or memory reference */
45 if (i->modC0()) {
46 op1_8 = BX_READ_8BIT_REGx(i->rm(), i->extend8bitL());
48 else {
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) {
55 if (count & 0x18) {
56 bit0 = (op1_8 & 1);
57 bit7 = (op1_8 >> 7);
58 SET_FLAGS_OxxxxC(bit0 ^ bit7, bit0);
60 return;
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 */
68 if (i->modC0()) {
69 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
71 else {
72 write_RMW_virtual_byte(result_8);
75 /* set eflags:
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;
88 unsigned count;
89 unsigned bit6, bit7;
91 if (i->b1() == 0xd2)
92 count = CL;
93 else // 0xc0 or 0xd0
94 count = i->Ib();
96 /* op1 is a register or memory reference */
97 if (i->modC0()) {
98 op1_8 = BX_READ_8BIT_REGx(i->rm(), i->extend8bitL());
100 else {
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) {
107 if (count & 0x18) {
108 bit6 = (op1_8 >> 6) & 1;
109 bit7 = (op1_8 >> 7) & 1;
111 SET_FLAGS_OxxxxC(bit6 ^ bit7, bit7);
113 return;
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 */
121 if (i->modC0()) {
122 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
124 else {
125 write_RMW_virtual_byte(result_8);
128 /* set eflags:
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;
141 unsigned count;
142 unsigned of, cf;
144 if (i->b1() == 0xd2)
145 count = CL;
146 else // 0xc0 or 0xd0
147 count = i->Ib();
149 /* op1 is a register or memory reference */
150 if (i->modC0()) {
151 op1_8 = BX_READ_8BIT_REGx(i->rm(), i->extend8bitL());
153 else {
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;
161 if (! count) return;
163 if (count==1) {
164 result_8 = (op1_8 << 1) | getB_CF();
166 else {
167 result_8 = (op1_8 << count) | (getB_CF() << (count - 1)) |
168 (op1_8 >> (9 - count));
171 /* now write result back to destination */
172 if (i->modC0()) {
173 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
175 else {
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;
187 unsigned count;
188 unsigned cf, of;
190 if (i->b1() == 0xd2)
191 count = CL;
192 else // 0xc0 or 0xd0
193 count = i->Ib();
195 /* op1 is a register or memory reference */
196 if (i->modC0()) {
197 op1_8 = BX_READ_8BIT_REGx(i->rm(), i->extend8bitL());
199 else {
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;
207 if (! count) return;
209 result_8 = (op1_8 >> count) | (getB_CF() << (8 - count)) |
210 (op1_8 << (9 - count));
212 /* now write result back to destination */
213 if (i->modC0()) {
214 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
216 else {
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;
228 unsigned count;
229 unsigned of = 0, cf = 0;
231 if (i->b1() == 0xd2)
232 count = CL;
233 else // 0xc0 or 0xd0
234 count = i->Ib();
236 count &= 0x1f;
238 /* op1 is a register or memory reference */
239 if (i->modC0()) {
240 op1_8 = BX_READ_8BIT_REGx(i->rm(), i->extend8bitL());
242 else {
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);
248 if (!count) return;
250 if (count <= 8) {
251 result_8 = (op1_8 << count);
252 cf = (op1_8 >> (8 - count)) & 0x1;
253 of = cf ^ (result_8 >> 7);
255 else {
256 result_8 = 0;
259 /* now write result back to destination */
260 if (i->modC0()) {
261 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
263 else {
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;
274 unsigned count;
275 unsigned cf, of;
277 if (i->b1() == 0xd2)
278 count = CL;
279 else // 0xc0 or 0xd0
280 count = i->Ib();
282 count &= 0x1f;
284 /* op1 is a register or memory reference */
285 if (i->modC0()) {
286 op1_8 = BX_READ_8BIT_REGx(i->rm(), i->extend8bitL());
288 else {
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);
294 if (!count) return;
296 result_8 = (op1_8 >> count);
298 /* now write result back to destination */
299 if (i->modC0()) {
300 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
302 else {
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;
318 unsigned count, cf;
320 if (i->b1() == 0xd2)
321 count = CL;
322 else // 0xc0 or 0xd0
323 count = i->Ib();
325 count &= 0x1f;
327 /* op1 is a register or memory reference */
328 if (i->modC0()) {
329 op1_8 = BX_READ_8BIT_REGx(i->rm(), i->extend8bitL());
331 else {
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);
337 if (!count) return;
339 if (count < 8) {
340 if (op1_8 & 0x80) {
341 result_8 = (op1_8 >> count) | (0xff << (8 - count));
343 else {
344 result_8 = (op1_8 >> count);
347 cf = (op1_8 >> (count - 1)) & 0x1;
349 else {
350 if (op1_8 & 0x80) {
351 result_8 = 0xff;
353 else {
354 result_8 = 0;
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 */
365 if (i->modC0()) {
366 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
368 else {
369 write_RMW_virtual_byte(result_8);