- added instructions how to update the online documentation
[bochs-mirror.git] / cpu / bit.cc
blobc436a14f031f8b10882ae708b0357f8fc19534cf
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: bit.cc,v 1.59 2008/08/11 18:53:23 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 #if BX_CPU_LEVEL >= 3
35 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETO_EbM(bxInstruction_c *i)
37 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
39 Bit8u result_8 = getB_OF();
40 write_virtual_byte(i->seg(), eaddr, result_8);
43 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETO_EbR(bxInstruction_c *i)
45 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), getB_OF());
48 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNO_EbM(bxInstruction_c *i)
50 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
52 Bit8u result_8 = !getB_OF();
53 write_virtual_byte(i->seg(), eaddr, result_8);
56 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNO_EbR(bxInstruction_c *i)
58 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), !getB_OF());
61 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETB_EbM(bxInstruction_c *i)
63 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
65 Bit8u result_8 = getB_CF();
66 write_virtual_byte(i->seg(), eaddr, result_8);
69 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETB_EbR(bxInstruction_c *i)
71 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), getB_CF());
74 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNB_EbM(bxInstruction_c *i)
76 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
78 Bit8u result_8 = !getB_CF();
79 write_virtual_byte(i->seg(), eaddr, result_8);
82 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNB_EbR(bxInstruction_c *i)
84 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), !getB_CF());
87 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETZ_EbM(bxInstruction_c *i)
89 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
91 Bit8u result_8 = getB_ZF();
92 write_virtual_byte(i->seg(), eaddr, result_8);
95 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETZ_EbR(bxInstruction_c *i)
97 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), getB_ZF());
100 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNZ_EbM(bxInstruction_c *i)
102 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
104 Bit8u result_8 = !getB_ZF();
105 write_virtual_byte(i->seg(), eaddr, result_8);
108 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNZ_EbR(bxInstruction_c *i)
110 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), !getB_ZF());
113 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETBE_EbM(bxInstruction_c *i)
115 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
117 Bit8u result_8 = (getB_CF() | getB_ZF());
118 write_virtual_byte(i->seg(), eaddr, result_8);
121 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETBE_EbR(bxInstruction_c *i)
123 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), (getB_CF() | getB_ZF()));
126 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNBE_EbM(bxInstruction_c *i)
128 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
130 Bit8u result_8 = !(getB_CF() | getB_ZF());
131 write_virtual_byte(i->seg(), eaddr, result_8);
134 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNBE_EbR(bxInstruction_c *i)
136 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), !(getB_CF() | getB_ZF()));
139 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETS_EbM(bxInstruction_c *i)
141 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
143 Bit8u result_8 = getB_SF();
144 write_virtual_byte(i->seg(), eaddr, result_8);
147 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETS_EbR(bxInstruction_c *i)
149 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), getB_SF());
152 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNS_EbM(bxInstruction_c *i)
154 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
156 Bit8u result_8 = !getB_SF();
157 write_virtual_byte(i->seg(), eaddr, result_8);
160 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNS_EbR(bxInstruction_c *i)
162 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), !getB_SF());
165 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETP_EbM(bxInstruction_c *i)
167 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
169 Bit8u result_8 = getB_PF();
170 write_virtual_byte(i->seg(), eaddr, result_8);
173 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETP_EbR(bxInstruction_c *i)
175 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), getB_PF());
178 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNP_EbM(bxInstruction_c *i)
180 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
182 Bit8u result_8 = !getB_PF();
183 write_virtual_byte(i->seg(), eaddr, result_8);
186 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNP_EbR(bxInstruction_c *i)
188 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), !getB_PF());
191 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETL_EbM(bxInstruction_c *i)
193 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
195 Bit8u result_8 = (getB_SF() ^ getB_OF());
196 write_virtual_byte(i->seg(), eaddr, result_8);
199 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETL_EbR(bxInstruction_c *i)
201 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), (getB_SF() ^ getB_OF()));
204 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNL_EbM(bxInstruction_c *i)
206 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
208 Bit8u result_8 = !(getB_SF() ^ getB_OF());
209 write_virtual_byte(i->seg(), eaddr, result_8);
212 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNL_EbR(bxInstruction_c *i)
214 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), !(getB_SF() ^ getB_OF()));
217 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETLE_EbM(bxInstruction_c *i)
219 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
221 Bit8u result_8 = getB_ZF() | (getB_SF() ^ getB_OF());
222 write_virtual_byte(i->seg(), eaddr, result_8);
225 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETLE_EbR(bxInstruction_c *i)
227 Bit8u result_8 = getB_ZF() | (getB_SF() ^ getB_OF());
228 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
231 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNLE_EbM(bxInstruction_c *i)
233 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
235 Bit8u result_8 = !(getB_ZF() | (getB_SF() ^ getB_OF()));
236 write_virtual_byte(i->seg(), eaddr, result_8);
239 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNLE_EbR(bxInstruction_c *i)
241 Bit8u result_8 = !(getB_ZF() | (getB_SF() ^ getB_OF()));
242 BX_WRITE_8BIT_REGx(i->rm(), i->extend8bitL(), result_8);
245 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BSWAP_ERX(bxInstruction_c *i)
247 #if BX_CPU_LEVEL >= 4
248 Bit32u val32, b0, b1, b2, b3;
250 if (i->os32L() == 0) {
251 BX_ERROR(("BSWAP with 16-bit opsize: undefined behavior !"));
254 val32 = BX_READ_32BIT_REG(i->opcodeReg());
255 b0 = val32 & 0xff; val32 >>= 8;
256 b1 = val32 & 0xff; val32 >>= 8;
257 b2 = val32 & 0xff; val32 >>= 8;
258 b3 = val32;
259 val32 = (b0<<24) | (b1<<16) | (b2<<8) | b3;
261 BX_WRITE_32BIT_REGZ(i->opcodeReg(), val32);
262 #else
263 BX_INFO(("BSWAP_ERX: required CPU >= 4, use --enable-cpu-level=4 option"));
264 exception(BX_UD_EXCEPTION, 0, 0);
265 #endif
268 #if BX_SUPPORT_X86_64
269 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BSWAP_RRX(bxInstruction_c *i)
271 Bit64u val64, b0, b1, b2, b3, b4, b5, b6, b7;
273 val64 = BX_READ_64BIT_REG(i->opcodeReg());
274 b0 = val64 & 0xff; val64 >>= 8;
275 b1 = val64 & 0xff; val64 >>= 8;
276 b2 = val64 & 0xff; val64 >>= 8;
277 b3 = val64 & 0xff; val64 >>= 8;
278 b4 = val64 & 0xff; val64 >>= 8;
279 b5 = val64 & 0xff; val64 >>= 8;
280 b6 = val64 & 0xff; val64 >>= 8;
281 b7 = val64;
282 val64 = (b0<<56) | (b1<<48) | (b2<<40) | (b3<<32) | (b4<<24) | (b4<<16) | (b4<<8) | b7;
284 BX_WRITE_64BIT_REG(i->opcodeReg(), val64);
286 #endif
288 // 3-byte opcodes
289 #if (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
291 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_GwEw(bxInstruction_c *i)
293 #if BX_SUPPORT_MOVBE
294 Bit16u val16, b0, b1;
296 if (i->modC0()) {
297 val16 = BX_READ_16BIT_REG(i->rm());
299 else {
300 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
301 val16 = read_virtual_word(i->seg(), eaddr);
304 b0 = val16 & 0xff; val16 >>= 8;
305 b1 = val16;
306 val16 = (b1<<8) | b0;
308 BX_WRITE_16BIT_REG(i->nnn(), val16);
309 #else
310 BX_INFO(("MOVBE_GwEw: required MOVBE support, use --enable-movbe option"));
311 exception(BX_UD_EXCEPTION, 0, 0);
312 #endif
315 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_EwGw(bxInstruction_c *i)
317 #if BX_SUPPORT_MOVBE
318 Bit16u val16 = BX_READ_16BIT_REG(i->nnn()), b0, b1;
320 b0 = val16 & 0xff; val16 >>= 8;
321 b1 = val16;
322 val16 = (b1<<8) | b0;
324 if (i->modC0()) {
325 BX_WRITE_16BIT_REG(i->rm(), val16);
327 else {
328 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
329 write_virtual_word(i->seg(), eaddr, val16);
331 #else
332 BX_INFO(("MOVBE_EwGw: required MOVBE support, use --enable-movbe option"));
333 exception(BX_UD_EXCEPTION, 0, 0);
334 #endif
337 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_GdEd(bxInstruction_c *i)
339 #if BX_SUPPORT_MOVBE
340 Bit32u val32, b0, b1, b2, b3;
342 if (i->modC0()) {
343 val32 = BX_READ_32BIT_REG(i->rm());
345 else {
346 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
347 val32 = read_virtual_dword(i->seg(), eaddr);
350 b0 = val32 & 0xff; val32 >>= 8;
351 b1 = val32 & 0xff; val32 >>= 8;
352 b2 = val32 & 0xff; val32 >>= 8;
353 b3 = val32;
354 val32 = (b0<<24) | (b1<<16) | (b2<<8) | b3;
356 BX_WRITE_32BIT_REGZ(i->nnn(), val32);
357 #else
358 BX_INFO(("MOVBE_GdEd: required MOVBE support, use --enable-movbe option"));
359 exception(BX_UD_EXCEPTION, 0, 0);
360 #endif
363 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_EdGd(bxInstruction_c *i)
365 #if BX_SUPPORT_MOVBE
366 Bit32u val32 = BX_READ_32BIT_REG(i->nnn()), b0, b1, b2, b3;
368 b0 = val32 & 0xff; val32 >>= 8;
369 b1 = val32 & 0xff; val32 >>= 8;
370 b2 = val32 & 0xff; val32 >>= 8;
371 b3 = val32;
372 val32 = (b0<<24) | (b1<<16) | (b2<<8) | b3;
374 if (i->modC0()) {
375 BX_WRITE_32BIT_REGZ(i->rm(), val32);
377 else {
378 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
379 write_virtual_dword(i->seg(), eaddr, val32);
381 #else
382 BX_INFO(("MOVBE_EdGd: required MOVBE support, use --enable-movbe option"));
383 exception(BX_UD_EXCEPTION, 0, 0);
384 #endif
387 #if BX_SUPPORT_X86_64
389 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_GqEq(bxInstruction_c *i)
391 #if BX_SUPPORT_MOVBE
392 Bit64u val64, b0, b1, b2, b3, b4, b5, b6, b7;
394 if (i->modC0()) {
395 val64 = BX_READ_64BIT_REG(i->rm());
397 else {
398 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
399 val64 = read_virtual_qword(i->seg(), eaddr);
402 b0 = val64 & 0xff; val64 >>= 8;
403 b1 = val64 & 0xff; val64 >>= 8;
404 b2 = val64 & 0xff; val64 >>= 8;
405 b3 = val64 & 0xff; val64 >>= 8;
406 b4 = val64 & 0xff; val64 >>= 8;
407 b5 = val64 & 0xff; val64 >>= 8;
408 b6 = val64 & 0xff; val64 >>= 8;
409 b7 = val64;
410 val64 = (b0<<56) | (b1<<48) | (b2<<40) | (b3<<32) | (b4<<24) | (b4<<16) | (b4<<8) | b7;
412 BX_WRITE_64BIT_REG(i->nnn(), val64);
413 #else
414 BX_INFO(("MOVBE_GqEq: required MOVBE support, use --enable-movbe option"));
415 exception(BX_UD_EXCEPTION, 0, 0);
416 #endif
419 void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_EqGq(bxInstruction_c *i)
421 #if BX_SUPPORT_MOVBE
422 Bit64u val64 = BX_READ_64BIT_REG(i->nnn());
423 Bit64u b0, b1, b2, b3, b4, b5, b6, b7;
425 b0 = val64 & 0xff; val64 >>= 8;
426 b1 = val64 & 0xff; val64 >>= 8;
427 b2 = val64 & 0xff; val64 >>= 8;
428 b3 = val64 & 0xff; val64 >>= 8;
429 b4 = val64 & 0xff; val64 >>= 8;
430 b5 = val64 & 0xff; val64 >>= 8;
431 b6 = val64 & 0xff; val64 >>= 8;
432 b7 = val64;
433 val64 = (b0<<56) | (b1<<48) | (b2<<40) | (b3<<32) | (b4<<24) | (b4<<16) | (b4<<8) | b7;
435 if (i->modC0()) {
436 BX_WRITE_64BIT_REG(i->rm(), val64);
438 else {
439 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i));
440 write_virtual_qword(i->seg(), eaddr, val64);
442 #else
443 BX_INFO(("MOVBE_EqGq: required MOVBE support, use --enable-movbe option"));
444 exception(BX_UD_EXCEPTION, 0, 0);
445 #endif
448 #endif // (BX_SUPPORT_X86_64)
450 #endif // (BX_SUPPORT_SSE >= 4) || (BX_SUPPORT_SSE >= 3 && BX_SUPPORT_SSE_EXTENSION > 0)
452 #endif // (BX_CPU_LEVEL >= 3)