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