1 /////////////////////////////////////////////////////////////////////////
2 // $Id: bit32.cc 14086 2021-01-30 08:35:35Z sshwarts $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //  Copyright (C) 2001-2018  The Bochs Project
6 //
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Lesser General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2 of the License, or (at your option) any later version.
11 //
12 //  This library is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  Lesser General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Lesser General Public
18 //  License along with this library; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
20 /////////////////////////////////////////////////////////////////////////
21 
22 #define NEED_CPU_REG_SHORTCUTS 1
23 #include "bochs.h"
24 #include "cpu.h"
25 #define LOG_THIS BX_CPU_THIS_PTR
26 
27 #if BX_CPU_LEVEL >= 3
28 
29 #include "scalar_arith.h"
30 
BSF_GdEdR(bxInstruction_c * i)31 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BSF_GdEdR(bxInstruction_c *i)
32 {
33   Bit32u op2_32 = BX_READ_32BIT_REG(i->src());
34 
35   if (op2_32 == 0) {
36     assert_ZF(); /* op1_32 undefined */
37   }
38   else {
39     Bit32u op1_32 = tzcntd(op2_32);
40     SET_FLAGS_OSZAPC_LOGIC_32(op1_32);
41     clear_ZF();
42 
43     BX_WRITE_32BIT_REGZ(i->dst(), op1_32);
44   }
45 
46   BX_NEXT_INSTR(i);
47 }
48 
BSR_GdEdR(bxInstruction_c * i)49 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BSR_GdEdR(bxInstruction_c *i)
50 {
51   Bit32u op2_32 = BX_READ_32BIT_REG(i->src());
52 
53   if (op2_32 == 0) {
54     assert_ZF(); /* op1_32 undefined */
55   }
56   else {
57     Bit32u op1_32 = 31;
58     while ((op2_32 & 0x80000000) == 0) {
59       op1_32--;
60       op2_32 <<= 1;
61     }
62 
63     SET_FLAGS_OSZAPC_LOGIC_32(op1_32);
64     clear_ZF();
65 
66     BX_WRITE_32BIT_REGZ(i->dst(), op1_32);
67   }
68 
69   BX_NEXT_INSTR(i);
70 }
71 
BT_EdGdM(bxInstruction_c * i)72 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EdGdM(bxInstruction_c *i)
73 {
74   bx_address op1_addr;
75   Bit32u op1_32, op2_32, index;
76   Bit32s displacement32;
77 
78   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
79 
80   op2_32 = BX_READ_32BIT_REG(i->src());
81   index = op2_32 & 0x1f;
82   displacement32 = ((Bit32s) (op2_32&0xffffffe0)) / 32;
83   op1_addr = eaddr + 4 * displacement32;
84 
85   /* pointer, segment address pair */
86   op1_32 = read_virtual_dword(i->seg(), op1_addr & i->asize_mask());
87 
88   set_CF((op1_32 >> index) & 0x01);
89 
90   BX_NEXT_INSTR(i);
91 }
92 
BT_EdGdR(bxInstruction_c * i)93 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EdGdR(bxInstruction_c *i)
94 {
95   Bit32u op1_32, op2_32;
96 
97   op1_32 = BX_READ_32BIT_REG(i->dst());
98   op2_32 = BX_READ_32BIT_REG(i->src());
99   op2_32 &= 0x1f;
100 
101   set_CF((op1_32 >> op2_32) & 0x01);
102 
103   BX_NEXT_INSTR(i);
104 }
105 
BTS_EdGdM(bxInstruction_c * i)106 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EdGdM(bxInstruction_c *i)
107 {
108   bx_address op1_addr;
109   Bit32u op1_32, op2_32, index;
110   Bit32s displacement32;
111   bool bit_i;
112 
113   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
114 
115   op2_32 = BX_READ_32BIT_REG(i->src());
116   index = op2_32 & 0x1f;
117   displacement32 = ((Bit32s) (op2_32&0xffffffe0)) / 32;
118   op1_addr = eaddr + 4 * displacement32;
119 
120   /* pointer, segment address pair */
121   op1_32 = read_RMW_virtual_dword(i->seg(), op1_addr & i->asize_mask());
122 
123   bit_i = (op1_32 >> index) & 0x01;
124   op1_32 |= (1 << index);
125 
126   write_RMW_linear_dword(op1_32);
127 
128   set_CF(bit_i);
129 
130   BX_NEXT_INSTR(i);
131 }
132 
BTS_EdGdR(bxInstruction_c * i)133 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EdGdR(bxInstruction_c *i)
134 {
135   Bit32u op1_32, op2_32;
136 
137   op1_32 = BX_READ_32BIT_REG(i->dst());
138   op2_32 = BX_READ_32BIT_REG(i->src());
139   op2_32 &= 0x1f;
140   set_CF((op1_32 >> op2_32) & 0x01);
141   op1_32 |= (1 << op2_32);
142 
143   /* now write result back to the destination */
144   BX_WRITE_32BIT_REGZ(i->dst(), op1_32);
145 
146   BX_NEXT_INSTR(i);
147 }
148 
BTR_EdGdM(bxInstruction_c * i)149 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EdGdM(bxInstruction_c *i)
150 {
151   bx_address op1_addr;
152   Bit32u op1_32, op2_32, index;
153   Bit32s displacement32;
154 
155   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
156 
157   op2_32 = BX_READ_32BIT_REG(i->src());
158   index = op2_32 & 0x1f;
159   displacement32 = ((Bit32s) (op2_32&0xffffffe0)) / 32;
160   op1_addr = eaddr + 4 * displacement32;
161 
162   /* pointer, segment address pair */
163   op1_32 = read_RMW_virtual_dword(i->seg(), op1_addr & i->asize_mask());
164 
165   bool temp_cf = (op1_32 >> index) & 0x01;
166   op1_32 &= ~(1 << index);
167 
168   /* now write back to destination */
169   write_RMW_linear_dword(op1_32);
170 
171   set_CF(temp_cf);
172 
173   BX_NEXT_INSTR(i);
174 }
175 
BTR_EdGdR(bxInstruction_c * i)176 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EdGdR(bxInstruction_c *i)
177 {
178   Bit32u op1_32, op2_32;
179 
180   op1_32 = BX_READ_32BIT_REG(i->dst());
181   op2_32 = BX_READ_32BIT_REG(i->src());
182   op2_32 &= 0x1f;
183   set_CF((op1_32 >> op2_32) & 0x01);
184   op1_32 &= ~(1 << op2_32);
185 
186   /* now write result back to the destination */
187   BX_WRITE_32BIT_REGZ(i->dst(), op1_32);
188 
189   BX_NEXT_INSTR(i);
190 }
191 
BTC_EdGdM(bxInstruction_c * i)192 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EdGdM(bxInstruction_c *i)
193 {
194   bx_address op1_addr;
195   Bit32u op1_32, op2_32, index_32;
196   Bit32s displacement32;
197 
198   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
199 
200   op2_32 = BX_READ_32BIT_REG(i->src());
201   index_32 = op2_32 & 0x1f;
202 
203   displacement32 = ((Bit32s) (op2_32 & 0xffffffe0)) / 32;
204   op1_addr = eaddr + 4 * displacement32;
205 
206   op1_32 = read_RMW_virtual_dword(i->seg(), op1_addr & i->asize_mask());
207   bool temp_CF = (op1_32 >> index_32) & 0x01;
208   op1_32 ^= (1 << index_32);  /* toggle bit */
209   set_CF(temp_CF);
210 
211   write_RMW_linear_dword(op1_32);
212 
213   BX_NEXT_INSTR(i);
214 }
215 
BTC_EdGdR(bxInstruction_c * i)216 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EdGdR(bxInstruction_c *i)
217 {
218   Bit32u op1_32, op2_32;
219 
220   op1_32 = BX_READ_32BIT_REG(i->dst());
221   op2_32 = BX_READ_32BIT_REG(i->src());
222   op2_32 &= 0x1f;
223 
224   bool temp_CF = (op1_32 >> op2_32) & 0x01;
225   op1_32 ^= (1 << op2_32);  /* toggle bit */
226   set_CF(temp_CF);
227 
228   BX_WRITE_32BIT_REGZ(i->dst(), op1_32);
229 
230   BX_NEXT_INSTR(i);
231 }
232 
BT_EdIbM(bxInstruction_c * i)233 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EdIbM(bxInstruction_c *i)
234 {
235   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
236 
237   Bit32u op1_32 = read_virtual_dword(i->seg(), eaddr);
238   Bit8u  op2_8  = i->Ib() & 0x1f;
239 
240   set_CF((op1_32 >> op2_8) & 0x01);
241 
242   BX_NEXT_INSTR(i);
243 }
244 
BT_EdIbR(bxInstruction_c * i)245 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EdIbR(bxInstruction_c *i)
246 {
247   Bit32u op1_32 = BX_READ_32BIT_REG(i->dst());
248   Bit8u  op2_8  = i->Ib() & 0x1f;
249 
250   set_CF((op1_32 >> op2_8) & 0x01);
251 
252   BX_NEXT_INSTR(i);
253 }
254 
BTS_EdIbM(bxInstruction_c * i)255 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EdIbM(bxInstruction_c *i)
256 {
257   Bit8u op2_8 = i->Ib() & 0x1f;
258 
259   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
260 
261   Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr);
262   bool temp_CF = (op1_32 >> op2_8) & 0x01;
263   op1_32 |= (1 << op2_8);
264   write_RMW_linear_dword(op1_32);
265 
266   set_CF(temp_CF);
267 
268   BX_NEXT_INSTR(i);
269 }
270 
BTS_EdIbR(bxInstruction_c * i)271 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EdIbR(bxInstruction_c *i)
272 {
273   Bit8u op2_8 = i->Ib() & 0x1f;
274 
275   Bit32u op1_32 = BX_READ_32BIT_REG(i->dst());
276   bool temp_CF = (op1_32 >> op2_8) & 0x01;
277   op1_32 |= (1 << op2_8);
278   BX_WRITE_32BIT_REGZ(i->dst(), op1_32);
279 
280   set_CF(temp_CF);
281 
282   BX_NEXT_INSTR(i);
283 }
284 
BTC_EdIbM(bxInstruction_c * i)285 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EdIbM(bxInstruction_c *i)
286 {
287   Bit8u op2_8 = i->Ib() & 0x1f;
288 
289   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
290 
291   Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr);
292   bool temp_CF = (op1_32 >> op2_8) & 0x01;
293   op1_32 ^= (1 << op2_8);  /* toggle bit */
294   write_RMW_linear_dword(op1_32);
295 
296   set_CF(temp_CF);
297 
298   BX_NEXT_INSTR(i);
299 }
300 
BTC_EdIbR(bxInstruction_c * i)301 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EdIbR(bxInstruction_c *i)
302 {
303   Bit8u op2_8 = i->Ib() & 0x1f;
304 
305   Bit32u op1_32 = BX_READ_32BIT_REG(i->dst());
306   bool temp_CF = (op1_32 >> op2_8) & 0x01;
307   op1_32 ^= (1 << op2_8);  /* toggle bit */
308   BX_WRITE_32BIT_REGZ(i->dst(), op1_32);
309 
310   set_CF(temp_CF);
311 
312   BX_NEXT_INSTR(i);
313 }
314 
BTR_EdIbM(bxInstruction_c * i)315 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EdIbM(bxInstruction_c *i)
316 {
317   Bit8u op2_8 = i->Ib() & 0x1f;
318 
319   bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
320 
321   Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr);
322   bool temp_CF = (op1_32 >> op2_8) & 0x01;
323   op1_32 &= ~(1 << op2_8);
324   write_RMW_linear_dword(op1_32);
325 
326   set_CF(temp_CF);
327 
328   BX_NEXT_INSTR(i);
329 }
330 
BTR_EdIbR(bxInstruction_c * i)331 void BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EdIbR(bxInstruction_c *i)
332 {
333   Bit8u op2_8 = i->Ib() & 0x1f;
334 
335   Bit32u op1_32 = BX_READ_32BIT_REG(i->dst());
336   bool temp_CF = (op1_32 >> op2_8) & 0x01;
337   op1_32 &= ~(1 << op2_8);
338   BX_WRITE_32BIT_REGZ(i->dst(), op1_32);
339 
340   set_CF(temp_CF);
341 
342   BX_NEXT_INSTR(i);
343 }
344 
345 /* F3 0F B8 */
POPCNT_GdEdR(bxInstruction_c * i)346 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POPCNT_GdEdR(bxInstruction_c *i)
347 {
348   Bit32u op_32 = popcntd(BX_READ_32BIT_REG(i->src()));
349 
350   clearEFlagsOSZAPC();
351   if (! op_32) assert_ZF();
352 
353   BX_WRITE_32BIT_REGZ(i->dst(), op_32);
354 
355   BX_NEXT_INSTR(i);
356 }
357 
358 /* F3 0F BC */
TZCNT_GdEdR(bxInstruction_c * i)359 void BX_CPP_AttrRegparmN(1) BX_CPU_C::TZCNT_GdEdR(bxInstruction_c *i)
360 {
361   Bit32u op1_32 = BX_READ_32BIT_REG(i->src());
362   Bit32u result_32 = tzcntd(op1_32);
363 
364   set_CF(! op1_32);
365   set_ZF(! result_32);
366 
367   BX_WRITE_32BIT_REGZ(i->dst(), result_32);
368 
369   BX_NEXT_INSTR(i);
370 }
371 
372 /* F3 0F BD */
LZCNT_GdEdR(bxInstruction_c * i)373 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LZCNT_GdEdR(bxInstruction_c *i)
374 {
375   Bit32u op1_32 = BX_READ_32BIT_REG(i->src());
376   Bit32u result_32 = lzcntd(op1_32);
377 
378   set_CF(! op1_32);
379   set_ZF(! result_32);
380 
381   BX_WRITE_32BIT_REGZ(i->dst(), result_32);
382 
383   BX_NEXT_INSTR(i);
384 }
385 
386 #endif // (BX_CPU_LEVEL >= 3)
387