1 /////////////////////////////////////////////////////////////////////////
2 // $Id: shift16.cc 13466 2018-02-16 07:57:32Z 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 #include "decoder/ia_opcodes.h"
28
SHLD_EwGwM(bxInstruction_c * i)29 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHLD_EwGwM(bxInstruction_c *i)
30 {
31 Bit32u temp_32, result_32;
32 unsigned count;
33 unsigned of, cf;
34
35 /* op1:op2 << count. result stored in op1 */
36 if (i->getIaOpcode() == BX_IA_SHLD_EwGw)
37 count = CL;
38 else // BX_IA_SHLD_EwGwIb
39 count = i->Ib();
40
41 count &= 0x1f; // use only 5 LSB's
42
43 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
44
45 Bit32u op1_16 = (Bit32u) read_RMW_virtual_word(i->seg(), eaddr);
46
47 if (count) {
48 Bit32u op2_16 = (Bit32u) BX_READ_16BIT_REG(i->src());
49
50 /* count < 32, since only lower 5 bits used */
51 temp_32 = (op1_16 << 16) | (op2_16); // double formed by op1:op2
52 result_32 = temp_32 << count;
53
54 // hack to act like x86 SHLD when count > 16
55 if (count > 16) {
56 // for Pentium processor, when count > 16, actually shifting op1:op2:op2 << count,
57 // it is the same as shifting op2:op2 by count-16
58 // For P6 and later (CPU_LEVEL >= 6), when count > 16, actually shifting op1:op2:op1 << count,
59 // which is the same as shifting op2:op1 by count-16
60 // The behavior is undefined so both ways are correct, we prefer P6 way of implementation
61 result_32 |= (op1_16 << (count - 16));
62 }
63
64 Bit16u result_16 = (Bit16u)(result_32 >> 16);
65
66 write_RMW_linear_word(result_16);
67
68 SET_FLAGS_OSZAPC_LOGIC_16(result_16);
69
70 cf = (temp_32 >> (32 - count)) & 0x1;
71 of = cf ^ (result_16 >> 15); // of = cf ^ result15
72 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(of, cf);
73 }
74
75 BX_NEXT_INSTR(i);
76 }
77
SHLD_EwGwR(bxInstruction_c * i)78 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHLD_EwGwR(bxInstruction_c *i)
79 {
80 Bit32u temp_32, result_32;
81 unsigned count;
82 unsigned of, cf;
83
84 /* op1:op2 << count. result stored in op1 */
85 if (i->getIaOpcode() == BX_IA_SHLD_EwGw)
86 count = CL;
87 else // BX_IA_SHLD_EwGwIb
88 count = i->Ib();
89
90 count &= 0x1f; // use only 5 LSB's
91
92 if (count) {
93 Bit32u op1_16 = (Bit32u) BX_READ_16BIT_REG(i->dst());
94 Bit32u op2_16 = (Bit32u) BX_READ_16BIT_REG(i->src());
95
96 /* count < 32, since only lower 5 bits used */
97 temp_32 = (op1_16 << 16) | (op2_16); // double formed by op1:op2
98 result_32 = temp_32 << count;
99
100 // hack to act like x86 SHLD when count > 16
101 if (count > 16) {
102 // for Pentium processor, when count > 16, actually shifting op1:op2:op2 << count,
103 // it is the same as shifting op2:op2 by count-16
104 // For P6 and later (CPU_LEVEL >= 6), when count > 16, actually shifting op1:op2:op1 << count,
105 // which is the same as shifting op2:op1 by count-16
106 // The behavior is undefined so both ways are correct, we prefer P6 way of implementation
107 result_32 |= (op1_16 << (count - 16));
108 }
109
110 Bit16u result_16 = (Bit16u)(result_32 >> 16);
111
112 BX_WRITE_16BIT_REG(i->dst(), result_16);
113
114 SET_FLAGS_OSZAPC_LOGIC_16(result_16);
115
116 cf = (temp_32 >> (32 - count)) & 0x1;
117 of = cf ^ (result_16 >> 15); // of = cf ^ result15
118 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(of, cf);
119 }
120
121 BX_NEXT_INSTR(i);
122 }
123
SHRD_EwGwM(bxInstruction_c * i)124 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHRD_EwGwM(bxInstruction_c *i)
125 {
126 Bit32u temp_32, result_32;
127 unsigned count;
128 unsigned cf, of;
129
130 if (i->getIaOpcode() == BX_IA_SHRD_EwGw)
131 count = CL;
132 else // BX_IA_SHRD_EwGwIb
133 count = i->Ib();
134
135 count &= 0x1f; /* use only 5 LSB's */
136
137 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
138
139 Bit32u op1_16 = (Bit32u) read_RMW_virtual_word(i->seg(), eaddr);
140
141 if (count) {
142 Bit32u op2_16 = (Bit32u) BX_READ_16BIT_REG(i->src());
143
144 /* count < 32, since only lower 5 bits used */
145 temp_32 = (op2_16 << 16) | op1_16; // double formed by op2:op1
146 result_32 = temp_32 >> count;
147
148 // hack to act like x86 SHRD when count > 16
149 if (count > 16) {
150 // for Pentium processor, when count > 16, actually shifting op2:op2:op1 >> count,
151 // it is the same as shifting op2:op2 by count-16
152 // For P6 and later (CPU_LEVEL >= 6), when count > 16, actually shifting op1:op2:op1 >> count,
153 // which is the same as shifting op1:op2 by count-16
154 // The behavior is undefined so both ways are correct, we prefer P6 way of implementation
155 result_32 |= (op1_16 << (32 - count));
156 }
157
158 Bit16u result_16 = (Bit16u) result_32;
159
160 write_RMW_linear_word(result_16);
161
162 SET_FLAGS_OSZAPC_LOGIC_16(result_16);
163
164 cf = (op1_16 >> (count - 1)) & 0x1;
165 of = ((Bit16u)((result_16 << 1) ^ result_16) >> 15) & 0x1; // of = result14 ^ result15
166 if (count > 16) cf = (op2_16 >> (count - 17)) & 0x1; // undefined flags behavior matching real HW
167 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(of, cf);
168 }
169
170 BX_NEXT_INSTR(i);
171 }
172
SHRD_EwGwR(bxInstruction_c * i)173 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHRD_EwGwR(bxInstruction_c *i)
174 {
175 Bit32u temp_32, result_32;
176 unsigned count;
177 unsigned cf, of;
178
179 if (i->getIaOpcode() == BX_IA_SHRD_EwGw)
180 count = CL;
181 else // BX_IA_SHRD_EwGwIb
182 count = i->Ib();
183
184 count &= 0x1f; /* use only 5 LSB's */
185
186 if (count) {
187 Bit32u op1_16 = (Bit32u) BX_READ_16BIT_REG(i->dst());
188 Bit32u op2_16 = (Bit32u) BX_READ_16BIT_REG(i->src());
189
190 /* count < 32, since only lower 5 bits used */
191 temp_32 = (op2_16 << 16) | op1_16; // double formed by op2:op1
192 result_32 = temp_32 >> count;
193
194 // hack to act like x86 SHRD when count > 16
195 if (count > 16) {
196 // for Pentium processor, when count > 16, actually shifting op2:op2:op1 >> count,
197 // it is the same as shifting op2:op2 by count-16
198 // For P6 and later (CPU_LEVEL >= 6), when count > 16, actually shifting op1:op2:op1 >> count,
199 // which is the same as shifting op1:op2 by count-16
200 // The behavior is undefined so both ways are correct, we prefer P6 way of implementation
201 result_32 |= (op1_16 << (32 - count));
202 }
203
204 Bit16u result_16 = (Bit16u) result_32;
205
206 BX_WRITE_16BIT_REG(i->dst(), result_16);
207
208 SET_FLAGS_OSZAPC_LOGIC_16(result_16);
209
210 cf = (op1_16 >> (count - 1)) & 0x1;
211 of = ((Bit16u)((result_16 << 1) ^ result_16) >> 15) & 0x1; // of = result14 ^ result15
212 if (count > 16) cf = (op2_16 >> (count - 17)) & 0x1; // undefined flags behavior matching real HW
213 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(of, cf);
214 }
215
216 BX_NEXT_INSTR(i);
217 }
218
ROL_EwM(bxInstruction_c * i)219 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROL_EwM(bxInstruction_c *i)
220 {
221 unsigned count;
222 unsigned bit0, bit15;
223
224 if (i->getIaOpcode() == BX_IA_ROL_Ew)
225 count = CL;
226 else
227 count = i->Ib();
228
229 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
230 /* pointer, segment address pair */
231 Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
232
233 if ((count & 0x0f) == 0) {
234 if (count & 0x10) {
235 bit0 = (op1_16 & 0x1);
236 bit15 = (op1_16 >> 15);
237 // of = cf ^ result15
238 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(bit0 ^ bit15, bit0);
239 }
240 }
241 else {
242 count &= 0x0f; // only use bottom 4 bits
243
244 Bit16u result_16 = (op1_16 << count) | (op1_16 >> (16 - count));
245
246 write_RMW_linear_word(result_16);
247
248 bit0 = (result_16 & 0x1);
249 bit15 = (result_16 >> 15);
250 // of = cf ^ result15
251 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(bit0 ^ bit15, bit0);
252 }
253
254 BX_NEXT_INSTR(i);
255 }
256
ROL_EwR(bxInstruction_c * i)257 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROL_EwR(bxInstruction_c *i)
258 {
259 unsigned count;
260 unsigned bit0, bit15;
261
262 if (i->getIaOpcode() == BX_IA_ROL_Ew)
263 count = CL;
264 else
265 count = i->Ib();
266
267 Bit16u op1_16 = BX_READ_16BIT_REG(i->dst());
268
269 if ((count & 0x0f) == 0) {
270 if (count & 0x10) {
271 bit0 = (op1_16 & 0x1);
272 bit15 = (op1_16 >> 15);
273 // of = cf ^ result15
274 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(bit0 ^ bit15, bit0);
275 }
276 }
277 else {
278 count &= 0x0f; // only use bottom 4 bits
279
280 Bit16u result_16 = (op1_16 << count) | (op1_16 >> (16 - count));
281
282 BX_WRITE_16BIT_REG(i->dst(), result_16);
283
284 bit0 = (result_16 & 0x1);
285 bit15 = (result_16 >> 15);
286 // of = cf ^ result15
287 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(bit0 ^ bit15, bit0);
288 }
289
290 BX_NEXT_INSTR(i);
291 }
292
ROR_EwM(bxInstruction_c * i)293 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROR_EwM(bxInstruction_c *i)
294 {
295 unsigned count;
296 unsigned bit14, bit15;
297
298 if (i->getIaOpcode() == BX_IA_ROR_Ew)
299 count = CL;
300 else
301 count = i->Ib();
302
303 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
304 /* pointer, segment address pair */
305 Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
306
307 if ((count & 0x0f) == 0) {
308 if (count & 0x10) {
309 bit14 = (op1_16 >> 14) & 1;
310 bit15 = (op1_16 >> 15) & 1;
311 // of = result14 ^ result15
312 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(bit14 ^ bit15, bit15);
313 }
314 }
315 else {
316 count &= 0x0f; // use only 4 LSB's
317
318 Bit16u result_16 = (op1_16 >> count) | (op1_16 << (16 - count));
319
320 write_RMW_linear_word(result_16);
321
322 bit14 = (result_16 >> 14) & 1;
323 bit15 = (result_16 >> 15) & 1;
324 // of = result14 ^ result15
325 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(bit14 ^ bit15, bit15);
326 }
327
328 BX_NEXT_INSTR(i);
329 }
330
ROR_EwR(bxInstruction_c * i)331 void BX_CPP_AttrRegparmN(1) BX_CPU_C::ROR_EwR(bxInstruction_c *i)
332 {
333 unsigned count;
334 unsigned bit14, bit15;
335
336 if (i->getIaOpcode() == BX_IA_ROR_Ew)
337 count = CL;
338 else
339 count = i->Ib();
340
341 Bit16u op1_16 = BX_READ_16BIT_REG(i->dst());
342
343 if ((count & 0x0f) == 0) {
344 if (count & 0x10) {
345 bit14 = (op1_16 >> 14) & 1;
346 bit15 = (op1_16 >> 15) & 1;
347 // of = result14 ^ result15
348 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(bit14 ^ bit15, bit15);
349 }
350 }
351 else {
352 count &= 0x0f; // use only 4 LSB's
353
354 Bit16u result_16 = (op1_16 >> count) | (op1_16 << (16 - count));
355
356 BX_WRITE_16BIT_REG(i->dst(), result_16);
357
358 bit14 = (result_16 >> 14) & 1;
359 bit15 = (result_16 >> 15) & 1;
360 // of = result14 ^ result15
361 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(bit14 ^ bit15, bit15);
362 }
363
364 BX_NEXT_INSTR(i);
365 }
366
RCL_EwM(bxInstruction_c * i)367 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RCL_EwM(bxInstruction_c *i)
368 {
369 Bit16u result_16;
370 unsigned count;
371 unsigned of, cf;
372
373 if (i->getIaOpcode() == BX_IA_RCL_Ew)
374 count = CL;
375 else
376 count = i->Ib();
377
378 count = (count & 0x1f) % 17;
379
380 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
381 /* pointer, segment address pair */
382 Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
383
384 unsigned temp_CF = getB_CF();
385
386 if (count) {
387 if (count==1) {
388 result_16 = (op1_16 << 1) | temp_CF;
389 }
390 else if (count==16) {
391 result_16 = (temp_CF << 15) | (op1_16 >> 1);
392 }
393 else { // 2..15
394 result_16 = (op1_16 << count) | (temp_CF << (count - 1)) |
395 (op1_16 >> (17 - count));
396 }
397
398 write_RMW_linear_word(result_16);
399
400 cf = (op1_16 >> (16 - count)) & 0x1;
401 of = cf ^ (result_16 >> 15); // of = cf ^ result15
402 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(of, cf);
403 }
404
405 BX_NEXT_INSTR(i);
406 }
407
RCL_EwR(bxInstruction_c * i)408 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RCL_EwR(bxInstruction_c *i)
409 {
410 Bit16u result_16;
411 unsigned count;
412 unsigned of, cf;
413
414 if (i->getIaOpcode() == BX_IA_RCL_Ew)
415 count = CL;
416 else
417 count = i->Ib();
418
419 count = (count & 0x1f) % 17;
420
421 unsigned temp_CF = getB_CF();
422
423 if (count) {
424 Bit16u op1_16 = BX_READ_16BIT_REG(i->dst());
425
426 if (count==1) {
427 result_16 = (op1_16 << 1) | temp_CF;
428 }
429 else if (count==16) {
430 result_16 = (temp_CF << 15) | (op1_16 >> 1);
431 }
432 else { // 2..15
433 result_16 = (op1_16 << count) | (temp_CF << (count - 1)) |
434 (op1_16 >> (17 - count));
435 }
436
437 BX_WRITE_16BIT_REG(i->dst(), result_16);
438
439 cf = (op1_16 >> (16 - count)) & 0x1;
440 of = cf ^ (result_16 >> 15); // of = cf ^ result15
441 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(of, cf);
442 }
443
444 BX_NEXT_INSTR(i);
445 }
446
RCR_EwM(bxInstruction_c * i)447 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RCR_EwM(bxInstruction_c *i)
448 {
449 unsigned count;
450 unsigned of, cf;
451
452 if (i->getIaOpcode() == BX_IA_RCR_Ew)
453 count = CL;
454 else
455 count = i->Ib();
456
457 count = (count & 0x1f) % 17;
458
459 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
460 /* pointer, segment address pair */
461 Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
462
463 if (count) {
464 unsigned temp_CF = getB_CF();
465
466 Bit16u result_16 = (op1_16 >> count) | (temp_CF << (16 - count)) |
467 (op1_16 << (17 - count));
468
469 write_RMW_linear_word(result_16);
470
471 cf = (op1_16 >> (count - 1)) & 0x1;
472 of = ((Bit16u)((result_16 << 1) ^ result_16) >> 15) & 0x1; // of = result15 ^ result14
473 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(of, cf);
474 }
475
476 BX_NEXT_INSTR(i);
477 }
478
RCR_EwR(bxInstruction_c * i)479 void BX_CPP_AttrRegparmN(1) BX_CPU_C::RCR_EwR(bxInstruction_c *i)
480 {
481 unsigned count;
482 unsigned of, cf;
483
484 if (i->getIaOpcode() == BX_IA_RCR_Ew)
485 count = CL;
486 else
487 count = i->Ib();
488
489 count = (count & 0x1f) % 17;
490
491 if (count) {
492 Bit16u op1_16 = BX_READ_16BIT_REG(i->dst());
493
494 unsigned temp_CF = getB_CF();
495
496 Bit16u result_16 = (op1_16 >> count) | (temp_CF << (16 - count)) |
497 (op1_16 << (17 - count));
498
499 BX_WRITE_16BIT_REG(i->dst(), result_16);
500
501 cf = (op1_16 >> (count - 1)) & 0x1;
502 of = ((Bit16u)((result_16 << 1) ^ result_16) >> 15) & 0x1; // of = result15 ^ result14
503 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(of, cf);
504 }
505
506 BX_NEXT_INSTR(i);
507 }
508
SHL_EwM(bxInstruction_c * i)509 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHL_EwM(bxInstruction_c *i)
510 {
511 Bit16u result_16;
512 unsigned count;
513 unsigned of = 0, cf = 0;
514
515 if (i->getIaOpcode() == BX_IA_SHL_Ew)
516 count = CL;
517 else
518 count = i->Ib();
519
520 count &= 0x1f; /* use only 5 LSB's */
521
522 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
523 /* pointer, segment address pair */
524 Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
525
526 if (count) {
527 if (count <= 16) {
528 result_16 = (op1_16 << count);
529 cf = (op1_16 >> (16 - count)) & 0x1;
530 of = cf ^ (result_16 >> 15); // of = cf ^ result15
531 }
532 else {
533 result_16 = 0;
534 }
535
536 write_RMW_linear_word(result_16);
537
538 SET_FLAGS_OSZAPC_LOGIC_16(result_16);
539 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(of, cf);
540 }
541
542 BX_NEXT_INSTR(i);
543 }
544
SHL_EwR(bxInstruction_c * i)545 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHL_EwR(bxInstruction_c *i)
546 {
547 Bit16u result_16;
548 unsigned count;
549 unsigned of = 0, cf = 0;
550
551 if (i->getIaOpcode() == BX_IA_SHL_Ew)
552 count = CL;
553 else
554 count = i->Ib();
555
556 count &= 0x1f; /* use only 5 LSB's */
557
558 if (count) {
559 Bit16u op1_16 = BX_READ_16BIT_REG(i->dst());
560
561 if (count <= 16) {
562 result_16 = (op1_16 << count);
563 cf = (op1_16 >> (16 - count)) & 0x1;
564 of = cf ^ (result_16 >> 15); // of = cf ^ result15
565 }
566 else {
567 result_16 = 0;
568 }
569
570 BX_WRITE_16BIT_REG(i->dst(), result_16);
571
572 SET_FLAGS_OSZAPC_LOGIC_16(result_16);
573 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(of, cf);
574 }
575
576 BX_NEXT_INSTR(i);
577 }
578
SHR_EwM(bxInstruction_c * i)579 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHR_EwM(bxInstruction_c *i)
580 {
581 unsigned count;
582 unsigned of, cf;
583
584 if (i->getIaOpcode() == BX_IA_SHR_Ew)
585 count = CL;
586 else
587 count = i->Ib();
588
589 count &= 0x1f; /* use only 5 LSB's */
590
591 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
592 /* pointer, segment address pair */
593 Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
594
595 if (count) {
596 Bit16u result_16 = (op1_16 >> count);
597
598 write_RMW_linear_word(result_16);
599
600 cf = (op1_16 >> (count - 1)) & 0x1;
601 // note, that of == result15 if count == 1 and
602 // of == 0 if count >= 2
603 of = ((Bit16u)((result_16 << 1) ^ result_16) >> 15) & 0x1;
604
605 SET_FLAGS_OSZAPC_LOGIC_16(result_16);
606 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(of, cf);
607 }
608
609 BX_NEXT_INSTR(i);
610 }
611
SHR_EwR(bxInstruction_c * i)612 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SHR_EwR(bxInstruction_c *i)
613 {
614 unsigned count;
615 unsigned of, cf;
616
617 if (i->getIaOpcode() == BX_IA_SHR_Ew)
618 count = CL;
619 else
620 count = i->Ib();
621
622 count &= 0x1f; /* use only 5 LSB's */
623
624 if (count) {
625 Bit16u op1_16 = BX_READ_16BIT_REG(i->dst());
626 Bit16u result_16 = (op1_16 >> count);
627 BX_WRITE_16BIT_REG(i->dst(), result_16);
628
629 cf = (op1_16 >> (count - 1)) & 0x1;
630 // note, that of == result15 if count == 1 and
631 // of == 0 if count >= 2
632 of = ((Bit16u)((result_16 << 1) ^ result_16) >> 15) & 0x1;
633
634 SET_FLAGS_OSZAPC_LOGIC_16(result_16);
635 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(of, cf);
636 }
637
638 BX_NEXT_INSTR(i);
639 }
640
SAR_EwM(bxInstruction_c * i)641 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SAR_EwM(bxInstruction_c *i)
642 {
643 unsigned count, cf;
644
645 if (i->getIaOpcode() == BX_IA_SAR_Ew)
646 count = CL;
647 else
648 count = i->Ib();
649
650 count &= 0x1f; /* use only 5 LSB's */
651
652 bx_address eaddr = BX_CPU_RESOLVE_ADDR(i);
653 Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr);
654
655 if (count) {
656 Bit16u result_16 = ((Bit16s) op1_16) >> count;
657
658 cf = (((Bit16s) op1_16) >> (count - 1)) & 0x1;
659
660 SET_FLAGS_OSZAPC_LOGIC_16(result_16);
661 /* signed overflow cannot happen in SAR instruction */
662 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(0, cf);
663
664 write_RMW_linear_word(result_16);
665 }
666
667 BX_NEXT_INSTR(i);
668 }
669
SAR_EwR(bxInstruction_c * i)670 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SAR_EwR(bxInstruction_c *i)
671 {
672 unsigned count, cf;
673
674 if (i->getIaOpcode() == BX_IA_SAR_Ew)
675 count = CL;
676 else
677 count = i->Ib();
678
679 count &= 0x1f; /* use only 5 LSB's */
680
681 if (count) {
682 Bit16u op1_16 = BX_READ_16BIT_REG(i->dst());
683 Bit16u result_16 = ((Bit16s) op1_16) >> count;
684 BX_WRITE_16BIT_REG(i->dst(), result_16);
685
686 cf = (((Bit16s) op1_16) >> (count - 1)) & 0x1;
687
688 SET_FLAGS_OSZAPC_LOGIC_16(result_16);
689 /* signed overflow cannot happen in SAR instruction */
690 BX_CPU_THIS_PTR oszapc.set_flags_OxxxxC(0, cf);
691 }
692
693 BX_NEXT_INSTR(i);
694 }
695