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