1 // license:BSD-3-Clause
2 // copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett
i386_shift_rotate16(uint8_t modrm,uint32_t value,uint8_t shift)3 uint16_t i386_device::i386_shift_rotate16(uint8_t modrm, uint32_t value, uint8_t shift)
4 {
5 uint32_t src = value & 0xffff;
6 uint16_t dst = value;
7
8 if( shift == 0 ) {
9 CYCLES_RM(modrm, 3, 7);
10 } else if( shift == 1 ) {
11 switch( (modrm >> 3) & 0x7 )
12 {
13 case 0: /* ROL rm16, 1 */
14 m_CF = (src & 0x8000) ? 1 : 0;
15 dst = (src << 1) + m_CF;
16 m_OF = ((src ^ dst) & 0x8000) ? 1 : 0;
17 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
18 break;
19 case 1: /* ROR rm16, 1 */
20 m_CF = (src & 0x1) ? 1 : 0;
21 dst = (m_CF << 15) | (src >> 1);
22 m_OF = ((src ^ dst) & 0x8000) ? 1 : 0;
23 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
24 break;
25 case 2: /* RCL rm16, 1 */
26 dst = (src << 1) + m_CF;
27 m_CF = (src & 0x8000) ? 1 : 0;
28 m_OF = ((src ^ dst) & 0x8000) ? 1 : 0;
29 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
30 break;
31 case 3: /* RCR rm16, 1 */
32 dst = (m_CF << 15) | (src >> 1);
33 m_CF = src & 0x1;
34 m_OF = ((src ^ dst) & 0x8000) ? 1 : 0;
35 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
36 break;
37 case 4: /* SHL/SAL rm16, 1 */
38 case 6:
39 dst = src << 1;
40 m_CF = (src & 0x8000) ? 1 : 0;
41 m_OF = (((m_CF << 15) ^ dst) & 0x8000) ? 1 : 0;
42 SetSZPF16(dst);
43 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
44 break;
45 case 5: /* SHR rm16, 1 */
46 dst = src >> 1;
47 m_CF = src & 0x1;
48 m_OF = (dst & 0x8000) ? 1 : 0;
49 SetSZPF16(dst);
50 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
51 break;
52 case 7: /* SAR rm16, 1 */
53 dst = (int16_t)(src) >> 1;
54 m_CF = src & 0x1;
55 m_OF = 0;
56 SetSZPF16(dst);
57 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
58 break;
59 }
60 } else {
61 switch( (modrm >> 3) & 0x7 )
62 {
63 case 0: /* ROL rm16, i8 */
64 if(!(shift & 15))
65 {
66 if(shift & 16)
67 {
68 m_CF = src & 1;
69 m_OF = (src & 1) ^ ((src >> 15) & 1);
70 }
71 break;
72 }
73 shift &= 15;
74 dst = ((src & ((uint16_t)0xffff >> shift)) << shift) |
75 ((src & ((uint16_t)0xffff << (16-shift))) >> (16-shift));
76 m_CF = dst & 0x1;
77 m_OF = (dst & 1) ^ (dst >> 15);
78 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
79 break;
80 case 1: /* ROR rm16, i8 */
81 if(!(shift & 15))
82 {
83 if(shift & 16)
84 {
85 m_CF = (src >> 15) & 1;
86 m_OF = ((src >> 15) & 1) ^ ((src >> 14) & 1);
87 }
88 break;
89 }
90 shift &= 15;
91 dst = ((src & ((uint16_t)0xffff << shift)) >> shift) |
92 ((src & ((uint16_t)0xffff >> (16-shift))) << (16-shift));
93 m_CF = (dst >> 15) & 1;
94 m_OF = ((dst >> 15) ^ (dst >> 14)) & 1;
95 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
96 break;
97 case 2: /* RCL rm16, i8 */
98 shift %= 17;
99 dst = ((src & ((uint16_t)0xffff >> shift)) << shift) |
100 ((src & ((uint16_t)0xffff << (17-shift))) >> (17-shift)) |
101 (m_CF << (shift-1));
102 if(shift) m_CF = (src >> (16-shift)) & 0x1;
103 m_OF = m_CF ^ ((dst >> 15) & 1);
104 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
105 break;
106 case 3: /* RCR rm16, i8 */
107 shift %= 17;
108 dst = ((src & ((uint16_t)0xffff << shift)) >> shift) |
109 ((src & ((uint16_t)0xffff >> (16-shift))) << (17-shift)) |
110 (m_CF << (16-shift));
111 if(shift) m_CF = (src >> (shift-1)) & 0x1;
112 m_OF = ((dst >> 15) ^ (dst >> 14)) & 1;
113 CYCLES_RM(modrm, CYCLES_ROTATE_CARRY_REG, CYCLES_ROTATE_CARRY_MEM);
114 break;
115 case 4: /* SHL/SAL rm16, i8 */
116 case 6:
117 shift &= 31;
118 dst = src << shift;
119 m_CF = (shift <= 16) && (src & (1 << (16-shift)));
120 SetSZPF16(dst);
121 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
122 break;
123 case 5: /* SHR rm16, i8 */
124 shift &= 31;
125 dst = src >> shift;
126 m_CF = (src & (1 << (shift-1))) ? 1 : 0;
127 SetSZPF16(dst);
128 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
129 break;
130 case 7: /* SAR rm16, i8 */
131 shift &= 31;
132 dst = (int16_t)src >> shift;
133 m_CF = (src & (1 << (shift-1))) ? 1 : 0;
134 SetSZPF16(dst);
135 CYCLES_RM(modrm, CYCLES_ROTATE_REG, CYCLES_ROTATE_MEM);
136 break;
137 }
138
139 }
140 return dst;
141 }
142
143
144
i386_adc_rm16_r16()145 void i386_device::i386_adc_rm16_r16() // Opcode 0x11
146 {
147 uint16_t src, dst;
148 uint8_t modrm = FETCH();
149 if( modrm >= 0xc0 ) {
150 src = LOAD_REG16(modrm);
151 dst = LOAD_RM16(modrm);
152 dst = ADC16(dst, src, m_CF);
153 STORE_RM16(modrm, dst);
154 CYCLES(CYCLES_ALU_REG_REG);
155 } else {
156 uint32_t ea = GetEA(modrm,1);
157 src = LOAD_REG16(modrm);
158 dst = READ16(ea);
159 dst = ADC16(dst, src, m_CF);
160 WRITE16(ea, dst);
161 CYCLES(CYCLES_ALU_REG_MEM);
162 }
163 }
164
i386_adc_r16_rm16()165 void i386_device::i386_adc_r16_rm16() // Opcode 0x13
166 {
167 uint16_t src, dst;
168 uint8_t modrm = FETCH();
169 if( modrm >= 0xc0 ) {
170 src = LOAD_RM16(modrm);
171 dst = LOAD_REG16(modrm);
172 dst = ADC16(dst, src, m_CF);
173 STORE_REG16(modrm, dst);
174 CYCLES(CYCLES_ALU_REG_REG);
175 } else {
176 uint32_t ea = GetEA(modrm,0);
177 src = READ16(ea);
178 dst = LOAD_REG16(modrm);
179 dst = ADC16(dst, src, m_CF);
180 STORE_REG16(modrm, dst);
181 CYCLES(CYCLES_ALU_MEM_REG);
182 }
183 }
184
i386_adc_ax_i16()185 void i386_device::i386_adc_ax_i16() // Opcode 0x15
186 {
187 uint16_t src, dst;
188 src = FETCH16();
189 dst = REG16(AX);
190 dst = ADC16(dst, src, m_CF);
191 REG16(AX) = dst;
192 CYCLES(CYCLES_ALU_IMM_ACC);
193 }
194
i386_add_rm16_r16()195 void i386_device::i386_add_rm16_r16() // Opcode 0x01
196 {
197 uint16_t src, dst;
198 uint8_t modrm = FETCH();
199 if( modrm >= 0xc0 ) {
200 src = LOAD_REG16(modrm);
201 dst = LOAD_RM16(modrm);
202 dst = ADD16(dst, src);
203 STORE_RM16(modrm, dst);
204 CYCLES(CYCLES_ALU_REG_REG);
205 } else {
206 uint32_t ea = GetEA(modrm,1);
207 src = LOAD_REG16(modrm);
208 dst = READ16(ea);
209 dst = ADD16(dst, src);
210 WRITE16(ea, dst);
211 CYCLES(CYCLES_ALU_REG_MEM);
212 }
213 }
214
i386_add_r16_rm16()215 void i386_device::i386_add_r16_rm16() // Opcode 0x03
216 {
217 uint16_t src, dst;
218 uint8_t modrm = FETCH();
219 if( modrm >= 0xc0 ) {
220 src = LOAD_RM16(modrm);
221 dst = LOAD_REG16(modrm);
222 dst = ADD16(dst, src);
223 STORE_REG16(modrm, dst);
224 CYCLES(CYCLES_ALU_REG_REG);
225 } else {
226 uint32_t ea = GetEA(modrm,0);
227 src = READ16(ea);
228 dst = LOAD_REG16(modrm);
229 dst = ADD16(dst, src);
230 STORE_REG16(modrm, dst);
231 CYCLES(CYCLES_ALU_MEM_REG);
232 }
233 }
234
i386_add_ax_i16()235 void i386_device::i386_add_ax_i16() // Opcode 0x05
236 {
237 uint16_t src, dst;
238 src = FETCH16();
239 dst = REG16(AX);
240 dst = ADD16(dst, src);
241 REG16(AX) = dst;
242 CYCLES(CYCLES_ALU_IMM_ACC);
243 }
244
i386_and_rm16_r16()245 void i386_device::i386_and_rm16_r16() // Opcode 0x21
246 {
247 uint16_t src, dst;
248 uint8_t modrm = FETCH();
249 if( modrm >= 0xc0 ) {
250 src = LOAD_REG16(modrm);
251 dst = LOAD_RM16(modrm);
252 dst = AND16(dst, src);
253 STORE_RM16(modrm, dst);
254 CYCLES(CYCLES_ALU_REG_REG);
255 } else {
256 uint32_t ea = GetEA(modrm,1);
257 src = LOAD_REG16(modrm);
258 dst = READ16(ea);
259 dst = AND16(dst, src);
260 WRITE16(ea, dst);
261 CYCLES(CYCLES_ALU_REG_MEM);
262 }
263 }
264
i386_and_r16_rm16()265 void i386_device::i386_and_r16_rm16() // Opcode 0x23
266 {
267 uint16_t src, dst;
268 uint8_t modrm = FETCH();
269 if( modrm >= 0xc0 ) {
270 src = LOAD_RM16(modrm);
271 dst = LOAD_REG16(modrm);
272 dst = AND16(dst, src);
273 STORE_REG16(modrm, dst);
274 CYCLES(CYCLES_ALU_REG_REG);
275 } else {
276 uint32_t ea = GetEA(modrm,0);
277 src = READ16(ea);
278 dst = LOAD_REG16(modrm);
279 dst = AND16(dst, src);
280 STORE_REG16(modrm, dst);
281 CYCLES(CYCLES_ALU_MEM_REG);
282 }
283 }
284
i386_and_ax_i16()285 void i386_device::i386_and_ax_i16() // Opcode 0x25
286 {
287 uint16_t src, dst;
288 src = FETCH16();
289 dst = REG16(AX);
290 dst = AND16(dst, src);
291 REG16(AX) = dst;
292 CYCLES(CYCLES_ALU_IMM_ACC);
293 }
294
i386_bsf_r16_rm16()295 void i386_device::i386_bsf_r16_rm16() // Opcode 0x0f bc
296 {
297 uint16_t src, dst, temp;
298 uint8_t modrm = FETCH();
299
300 if( modrm >= 0xc0 ) {
301 src = LOAD_RM16(modrm);
302 } else {
303 uint32_t ea = GetEA(modrm,0);
304 src = READ16(ea);
305 }
306
307 dst = 0;
308
309 if( src == 0 ) {
310 m_ZF = 1;
311 } else {
312 m_ZF = 0;
313 temp = 0;
314 while( (src & (1 << temp)) == 0 ) {
315 temp++;
316 dst = temp;
317 CYCLES(CYCLES_BSF);
318 }
319 STORE_REG16(modrm, dst);
320 }
321 CYCLES(CYCLES_BSF_BASE);
322 }
323
i386_bsr_r16_rm16()324 void i386_device::i386_bsr_r16_rm16() // Opcode 0x0f bd
325 {
326 uint16_t src, dst, temp;
327 uint8_t modrm = FETCH();
328
329 if( modrm >= 0xc0 ) {
330 src = LOAD_RM16(modrm);
331 } else {
332 uint32_t ea = GetEA(modrm,0);
333 src = READ16(ea);
334 }
335
336 dst = 0;
337
338 if( src == 0 ) {
339 m_ZF = 1;
340 } else {
341 m_ZF = 0;
342 dst = temp = 15;
343 while( (src & (1 << temp)) == 0 ) {
344 temp--;
345 dst = temp;
346 CYCLES(CYCLES_BSR);
347 }
348 STORE_REG16(modrm, dst);
349 }
350 CYCLES(CYCLES_BSR_BASE);
351 }
352
353
i386_bt_rm16_r16()354 void i386_device::i386_bt_rm16_r16() // Opcode 0x0f a3
355 {
356 uint8_t modrm = FETCH();
357 if( modrm >= 0xc0 ) {
358 uint16_t dst = LOAD_RM16(modrm);
359 uint16_t bit = LOAD_REG16(modrm);
360
361 if( dst & (1 << (bit & 0xf)) )
362 m_CF = 1;
363 else
364 m_CF = 0;
365
366 CYCLES(CYCLES_BT_REG_REG);
367 } else {
368 uint8_t segment;
369 uint32_t ea = GetNonTranslatedEA(modrm,&segment);
370 uint16_t bit = LOAD_REG16(modrm);
371 ea += 2*(bit/16);
372 ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),0);
373 bit %= 16;
374 uint16_t dst = READ16(ea);
375
376 if( dst & (1 << bit) )
377 m_CF = 1;
378 else
379 m_CF = 0;
380
381 CYCLES(CYCLES_BT_REG_MEM);
382 }
383 }
384
i386_btc_rm16_r16()385 void i386_device::i386_btc_rm16_r16() // Opcode 0x0f bb
386 {
387 uint8_t modrm = FETCH();
388 if( modrm >= 0xc0 ) {
389 uint16_t dst = LOAD_RM16(modrm);
390 uint16_t bit = LOAD_REG16(modrm);
391
392 if( dst & (1 << (bit & 0xf)) )
393 m_CF = 1;
394 else
395 m_CF = 0;
396 dst ^= (1 << (bit & 0xf));
397
398 STORE_RM16(modrm, dst);
399 CYCLES(CYCLES_BTC_REG_REG);
400 } else {
401 uint8_t segment;
402 uint32_t ea = GetNonTranslatedEA(modrm,&segment);
403 uint16_t bit = LOAD_REG16(modrm);
404 ea += 2*(bit/16);
405 ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1);
406 bit %= 16;
407 uint16_t dst = READ16(ea);
408
409 if( dst & (1 << bit) )
410 m_CF = 1;
411 else
412 m_CF = 0;
413 dst ^= (1 << bit);
414
415 WRITE16(ea, dst);
416 CYCLES(CYCLES_BTC_REG_MEM);
417 }
418 }
419
i386_btr_rm16_r16()420 void i386_device::i386_btr_rm16_r16() // Opcode 0x0f b3
421 {
422 uint8_t modrm = FETCH();
423 if( modrm >= 0xc0 ) {
424 uint16_t dst = LOAD_RM16(modrm);
425 uint16_t bit = LOAD_REG16(modrm);
426
427 if( dst & (1 << (bit & 0xf)) )
428 m_CF = 1;
429 else
430 m_CF = 0;
431 dst &= ~(1 << (bit & 0xf));
432
433 STORE_RM16(modrm, dst);
434 CYCLES(CYCLES_BTR_REG_REG);
435 } else {
436 uint8_t segment;
437 uint32_t ea = GetNonTranslatedEA(modrm,&segment);
438 uint16_t bit = LOAD_REG16(modrm);
439 ea += 2*(bit/16);
440 ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1);
441 bit %= 16;
442 uint16_t dst = READ16(ea);
443
444 if( dst & (1 << bit) )
445 m_CF = 1;
446 else
447 m_CF = 0;
448 dst &= ~(1 << bit);
449
450 WRITE16(ea, dst);
451 CYCLES(CYCLES_BTR_REG_MEM);
452 }
453 }
454
i386_bts_rm16_r16()455 void i386_device::i386_bts_rm16_r16() // Opcode 0x0f ab
456 {
457 uint8_t modrm = FETCH();
458 if( modrm >= 0xc0 ) {
459 uint16_t dst = LOAD_RM16(modrm);
460 uint16_t bit = LOAD_REG16(modrm);
461
462 if( dst & (1 << (bit & 0xf)) )
463 m_CF = 1;
464 else
465 m_CF = 0;
466 dst |= (1 << (bit & 0xf));
467
468 STORE_RM16(modrm, dst);
469 CYCLES(CYCLES_BTS_REG_REG);
470 } else {
471 uint8_t segment;
472 uint32_t ea = GetNonTranslatedEA(modrm,&segment);
473 uint16_t bit = LOAD_REG16(modrm);
474 ea += 2*(bit/16);
475 ea = i386_translate(segment,(m_address_size)?ea:(ea&0xffff),1);
476 bit %= 16;
477 uint16_t dst = READ16(ea);
478
479 if( dst & (1 << bit) )
480 m_CF = 1;
481 else
482 m_CF = 0;
483 dst |= (1 << bit);
484
485 WRITE16(ea, dst);
486 CYCLES(CYCLES_BTS_REG_MEM);
487 }
488 }
489
i386_call_abs16()490 void i386_device::i386_call_abs16() // Opcode 0x9a
491 {
492 uint16_t offset = FETCH16();
493 uint16_t ptr = FETCH16();
494
495 if( PROTECTED_MODE && !V8086_MODE)
496 {
497 i386_protected_mode_call(ptr,offset,0,0);
498 }
499 else
500 {
501 PUSH16(m_sreg[CS].selector );
502 PUSH16(m_eip );
503 m_sreg[CS].selector = ptr;
504 m_performed_intersegment_jump = 1;
505 m_eip = offset;
506 i386_load_segment_descriptor(CS);
507 }
508 CYCLES(CYCLES_CALL_INTERSEG); /* TODO: Timing = 17 + m */
509 CHANGE_PC(m_eip);
510 }
511
i386_call_rel16()512 void i386_device::i386_call_rel16() // Opcode 0xe8
513 {
514 int16_t disp = FETCH16();
515
516 PUSH16(m_eip );
517 if (m_sreg[CS].d)
518 {
519 m_eip += disp;
520 }
521 else
522 {
523 m_eip = (m_eip + disp) & 0xffff;
524 }
525 CHANGE_PC(m_eip);
526 CYCLES(CYCLES_CALL); /* TODO: Timing = 7 + m */
527 }
528
i386_cbw()529 void i386_device::i386_cbw() // Opcode 0x98
530 {
531 REG16(AX) = (int16_t)((int8_t)REG8(AL));
532 CYCLES(CYCLES_CBW);
533 }
534
i386_cmp_rm16_r16()535 void i386_device::i386_cmp_rm16_r16() // Opcode 0x39
536 {
537 uint16_t src, dst;
538 uint8_t modrm = FETCH();
539 if( modrm >= 0xc0 ) {
540 src = LOAD_REG16(modrm);
541 dst = LOAD_RM16(modrm);
542 SUB16(dst, src);
543 CYCLES(CYCLES_CMP_REG_REG);
544 } else {
545 uint32_t ea = GetEA(modrm,0);
546 src = LOAD_REG16(modrm);
547 dst = READ16(ea);
548 SUB16(dst, src);
549 CYCLES(CYCLES_CMP_REG_MEM);
550 }
551 }
552
i386_cmp_r16_rm16()553 void i386_device::i386_cmp_r16_rm16() // Opcode 0x3b
554 {
555 uint16_t src, dst;
556 uint8_t modrm = FETCH();
557 if( modrm >= 0xc0 ) {
558 src = LOAD_RM16(modrm);
559 dst = LOAD_REG16(modrm);
560 SUB16(dst, src);
561 CYCLES(CYCLES_CMP_REG_REG);
562 } else {
563 uint32_t ea = GetEA(modrm,0);
564 src = READ16(ea);
565 dst = LOAD_REG16(modrm);
566 SUB16(dst, src);
567 CYCLES(CYCLES_CMP_MEM_REG);
568 }
569 }
570
i386_cmp_ax_i16()571 void i386_device::i386_cmp_ax_i16() // Opcode 0x3d
572 {
573 uint16_t src, dst;
574 src = FETCH16();
575 dst = REG16(AX);
576 SUB16(dst, src);
577 CYCLES(CYCLES_CMP_IMM_ACC);
578 }
579
i386_cmpsw()580 void i386_device::i386_cmpsw() // Opcode 0xa7
581 {
582 uint32_t eas, ead;
583 uint16_t src, dst;
584 if( m_segment_prefix ) {
585 eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 );
586 } else {
587 eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 );
588 }
589 ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 );
590 src = READ16(eas);
591 dst = READ16(ead);
592 SUB16(src,dst);
593 BUMP_SI(2);
594 BUMP_DI(2);
595 CYCLES(CYCLES_CMPS);
596 }
597
i386_cwd()598 void i386_device::i386_cwd() // Opcode 0x99
599 {
600 if( REG16(AX) & 0x8000 ) {
601 REG16(DX) = 0xffff;
602 } else {
603 REG16(DX) = 0x0000;
604 }
605 CYCLES(CYCLES_CWD);
606 }
607
i386_dec_ax()608 void i386_device::i386_dec_ax() // Opcode 0x48
609 {
610 REG16(AX) = DEC16(REG16(AX) );
611 CYCLES(CYCLES_DEC_REG);
612 }
613
i386_dec_cx()614 void i386_device::i386_dec_cx() // Opcode 0x49
615 {
616 REG16(CX) = DEC16(REG16(CX) );
617 CYCLES(CYCLES_DEC_REG);
618 }
619
i386_dec_dx()620 void i386_device::i386_dec_dx() // Opcode 0x4a
621 {
622 REG16(DX) = DEC16(REG16(DX) );
623 CYCLES(CYCLES_DEC_REG);
624 }
625
i386_dec_bx()626 void i386_device::i386_dec_bx() // Opcode 0x4b
627 {
628 REG16(BX) = DEC16(REG16(BX) );
629 CYCLES(CYCLES_DEC_REG);
630 }
631
i386_dec_sp()632 void i386_device::i386_dec_sp() // Opcode 0x4c
633 {
634 REG16(SP) = DEC16(REG16(SP) );
635 CYCLES(CYCLES_DEC_REG);
636 }
637
i386_dec_bp()638 void i386_device::i386_dec_bp() // Opcode 0x4d
639 {
640 REG16(BP) = DEC16(REG16(BP) );
641 CYCLES(CYCLES_DEC_REG);
642 }
643
i386_dec_si()644 void i386_device::i386_dec_si() // Opcode 0x4e
645 {
646 REG16(SI) = DEC16(REG16(SI) );
647 CYCLES(CYCLES_DEC_REG);
648 }
649
i386_dec_di()650 void i386_device::i386_dec_di() // Opcode 0x4f
651 {
652 REG16(DI) = DEC16(REG16(DI) );
653 CYCLES(CYCLES_DEC_REG);
654 }
655
i386_imul_r16_rm16()656 void i386_device::i386_imul_r16_rm16() // Opcode 0x0f af
657 {
658 uint8_t modrm = FETCH();
659 int32_t result;
660 int32_t src, dst;
661 if( modrm >= 0xc0 ) {
662 src = (int32_t)(int16_t)LOAD_RM16(modrm);
663 CYCLES(CYCLES_IMUL16_REG_REG); /* TODO: Correct multiply timing */
664 } else {
665 uint32_t ea = GetEA(modrm,0);
666 src = (int32_t)(int16_t)READ16(ea);
667 CYCLES(CYCLES_IMUL16_REG_MEM); /* TODO: Correct multiply timing */
668 }
669
670 dst = (int32_t)(int16_t)LOAD_REG16(modrm);
671 result = src * dst;
672
673 STORE_REG16(modrm, (uint16_t)result);
674
675 m_CF = m_OF = !(result == (int32_t)(int16_t)result);
676 }
677
i386_imul_r16_rm16_i16()678 void i386_device::i386_imul_r16_rm16_i16() // Opcode 0x69
679 {
680 uint8_t modrm = FETCH();
681 int32_t result;
682 int32_t src, dst;
683 if( modrm >= 0xc0 ) {
684 dst = (int32_t)(int16_t)LOAD_RM16(modrm);
685 CYCLES(CYCLES_IMUL16_REG_IMM_REG); /* TODO: Correct multiply timing */
686 } else {
687 uint32_t ea = GetEA(modrm,0);
688 dst = (int32_t)(int16_t)READ16(ea);
689 CYCLES(CYCLES_IMUL16_MEM_IMM_REG); /* TODO: Correct multiply timing */
690 }
691
692 src = (int32_t)(int16_t)FETCH16();
693 result = src * dst;
694
695 STORE_REG16(modrm, (uint16_t)result);
696
697 m_CF = m_OF = !(result == (int32_t)(int16_t)result);
698 }
699
i386_imul_r16_rm16_i8()700 void i386_device::i386_imul_r16_rm16_i8() // Opcode 0x6b
701 {
702 uint8_t modrm = FETCH();
703 int32_t result;
704 int32_t src, dst;
705 if( modrm >= 0xc0 ) {
706 dst = (int32_t)(int16_t)LOAD_RM16(modrm);
707 CYCLES(CYCLES_IMUL16_REG_IMM_REG); /* TODO: Correct multiply timing */
708 } else {
709 uint32_t ea = GetEA(modrm,0);
710 dst = (int32_t)(int16_t)READ16(ea);
711 CYCLES(CYCLES_IMUL16_MEM_IMM_REG); /* TODO: Correct multiply timing */
712 }
713
714 src = (int32_t)(int8_t)FETCH();
715 result = src * dst;
716
717 STORE_REG16(modrm, (uint16_t)result);
718
719 m_CF = m_OF = !(result == (int32_t)(int16_t)result);
720 }
721
i386_in_ax_i8()722 void i386_device::i386_in_ax_i8() // Opcode 0xe5
723 {
724 uint16_t port = FETCH();
725 uint16_t data = READPORT16(port);
726 REG16(AX) = data;
727 CYCLES(CYCLES_IN_VAR);
728 }
729
i386_in_ax_dx()730 void i386_device::i386_in_ax_dx() // Opcode 0xed
731 {
732 uint16_t port = REG16(DX);
733 uint16_t data = READPORT16(port);
734 REG16(AX) = data;
735 CYCLES(CYCLES_IN);
736 }
737
i386_inc_ax()738 void i386_device::i386_inc_ax() // Opcode 0x40
739 {
740 REG16(AX) = INC16(REG16(AX) );
741 CYCLES(CYCLES_INC_REG);
742 }
743
i386_inc_cx()744 void i386_device::i386_inc_cx() // Opcode 0x41
745 {
746 REG16(CX) = INC16(REG16(CX) );
747 CYCLES(CYCLES_INC_REG);
748 }
749
i386_inc_dx()750 void i386_device::i386_inc_dx() // Opcode 0x42
751 {
752 REG16(DX) = INC16(REG16(DX) );
753 CYCLES(CYCLES_INC_REG);
754 }
755
i386_inc_bx()756 void i386_device::i386_inc_bx() // Opcode 0x43
757 {
758 REG16(BX) = INC16(REG16(BX) );
759 CYCLES(CYCLES_INC_REG);
760 }
761
i386_inc_sp()762 void i386_device::i386_inc_sp() // Opcode 0x44
763 {
764 REG16(SP) = INC16(REG16(SP) );
765 CYCLES(CYCLES_INC_REG);
766 }
767
i386_inc_bp()768 void i386_device::i386_inc_bp() // Opcode 0x45
769 {
770 REG16(BP) = INC16(REG16(BP) );
771 CYCLES(CYCLES_INC_REG);
772 }
773
i386_inc_si()774 void i386_device::i386_inc_si() // Opcode 0x46
775 {
776 REG16(SI) = INC16(REG16(SI) );
777 CYCLES(CYCLES_INC_REG);
778 }
779
i386_inc_di()780 void i386_device::i386_inc_di() // Opcode 0x47
781 {
782 REG16(DI) = INC16(REG16(DI) );
783 CYCLES(CYCLES_INC_REG);
784 }
785
i386_iret16()786 void i386_device::i386_iret16() // Opcode 0xcf
787 {
788 if( PROTECTED_MODE )
789 {
790 i386_protected_mode_iret(0);
791 }
792 else
793 {
794 /* TODO: #SS(0) exception */
795 /* TODO: #GP(0) exception */
796 m_eip = POP16();
797 m_sreg[CS].selector = POP16();
798 set_flags(POP16() );
799 i386_load_segment_descriptor(CS);
800 CHANGE_PC(m_eip);
801 }
802 m_auto_clear_RF = false;
803 CYCLES(CYCLES_IRET);
804 }
805
i386_ja_rel16()806 void i386_device::i386_ja_rel16() // Opcode 0x0f 87
807 {
808 int16_t disp = FETCH16();
809 if( m_CF == 0 && m_ZF == 0 ) {
810 if (m_sreg[CS].d)
811 {
812 m_eip += disp;
813 }
814 else
815 {
816 m_eip = (m_eip + disp) & 0xffff;
817 }
818 CHANGE_PC(m_eip);
819 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
820 } else {
821 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
822 }
823 }
824
i386_jbe_rel16()825 void i386_device::i386_jbe_rel16() // Opcode 0x0f 86
826 {
827 int16_t disp = FETCH16();
828 if( m_CF != 0 || m_ZF != 0 ) {
829 if (m_sreg[CS].d)
830 {
831 m_eip += disp;
832 }
833 else
834 {
835 m_eip = (m_eip + disp) & 0xffff;
836 }
837 CHANGE_PC(m_eip);
838 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
839 } else {
840 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
841 }
842 }
843
i386_jc_rel16()844 void i386_device::i386_jc_rel16() // Opcode 0x0f 82
845 {
846 int16_t disp = FETCH16();
847 if( m_CF != 0 ) {
848 if (m_sreg[CS].d)
849 {
850 m_eip += disp;
851 }
852 else
853 {
854 m_eip = (m_eip + disp) & 0xffff;
855 }
856 CHANGE_PC(m_eip);
857 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
858 } else {
859 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
860 }
861 }
862
i386_jg_rel16()863 void i386_device::i386_jg_rel16() // Opcode 0x0f 8f
864 {
865 int16_t disp = FETCH16();
866 if( m_ZF == 0 && (m_SF == m_OF) ) {
867 if (m_sreg[CS].d)
868 {
869 m_eip += disp;
870 }
871 else
872 {
873 m_eip = (m_eip + disp) & 0xffff;
874 }
875 CHANGE_PC(m_eip);
876 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
877 } else {
878 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
879 }
880 }
881
i386_jge_rel16()882 void i386_device::i386_jge_rel16() // Opcode 0x0f 8d
883 {
884 int16_t disp = FETCH16();
885 if(m_SF == m_OF) {
886 if (m_sreg[CS].d)
887 {
888 m_eip += disp;
889 }
890 else
891 {
892 m_eip = (m_eip + disp) & 0xffff;
893 }
894 CHANGE_PC(m_eip);
895 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
896 } else {
897 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
898 }
899 }
900
i386_jl_rel16()901 void i386_device::i386_jl_rel16() // Opcode 0x0f 8c
902 {
903 int16_t disp = FETCH16();
904 if( (m_SF != m_OF) ) {
905 if (m_sreg[CS].d)
906 {
907 m_eip += disp;
908 }
909 else
910 {
911 m_eip = (m_eip + disp) & 0xffff;
912 }
913 CHANGE_PC(m_eip);
914 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
915 } else {
916 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
917 }
918 }
919
i386_jle_rel16()920 void i386_device::i386_jle_rel16() // Opcode 0x0f 8e
921 {
922 int16_t disp = FETCH16();
923 if( m_ZF != 0 || (m_SF != m_OF) ) {
924 if (m_sreg[CS].d)
925 {
926 m_eip += disp;
927 }
928 else
929 {
930 m_eip = (m_eip + disp) & 0xffff;
931 }
932 CHANGE_PC(m_eip);
933 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
934 } else {
935 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
936 }
937 }
938
i386_jnc_rel16()939 void i386_device::i386_jnc_rel16() // Opcode 0x0f 83
940 {
941 int16_t disp = FETCH16();
942 if( m_CF == 0 ) {
943 if (m_sreg[CS].d)
944 {
945 m_eip += disp;
946 }
947 else
948 {
949 m_eip = (m_eip + disp) & 0xffff;
950 }
951 CHANGE_PC(m_eip);
952 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
953 } else {
954 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
955 }
956 }
957
i386_jno_rel16()958 void i386_device::i386_jno_rel16() // Opcode 0x0f 81
959 {
960 int16_t disp = FETCH16();
961 if( m_OF == 0 ) {
962 if (m_sreg[CS].d)
963 {
964 m_eip += disp;
965 }
966 else
967 {
968 m_eip = (m_eip + disp) & 0xffff;
969 }
970 CHANGE_PC(m_eip);
971 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
972 } else {
973 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
974 }
975 }
976
i386_jnp_rel16()977 void i386_device::i386_jnp_rel16() // Opcode 0x0f 8b
978 {
979 int16_t disp = FETCH16();
980 if( m_PF == 0 ) {
981 if (m_sreg[CS].d)
982 {
983 m_eip += disp;
984 }
985 else
986 {
987 m_eip = (m_eip + disp) & 0xffff;
988 }
989 CHANGE_PC(m_eip);
990 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
991 } else {
992 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
993 }
994 }
995
i386_jns_rel16()996 void i386_device::i386_jns_rel16() // Opcode 0x0f 89
997 {
998 int16_t disp = FETCH16();
999 if( m_SF == 0 ) {
1000 if (m_sreg[CS].d)
1001 {
1002 m_eip += disp;
1003 }
1004 else
1005 {
1006 m_eip = (m_eip + disp) & 0xffff;
1007 }
1008 CHANGE_PC(m_eip);
1009 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
1010 } else {
1011 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
1012 }
1013 }
1014
i386_jnz_rel16()1015 void i386_device::i386_jnz_rel16() // Opcode 0x0f 85
1016 {
1017 int16_t disp = FETCH16();
1018 if( m_ZF == 0 ) {
1019 if (m_sreg[CS].d)
1020 {
1021 m_eip += disp;
1022 }
1023 else
1024 {
1025 m_eip = (m_eip + disp) & 0xffff;
1026 }
1027 CHANGE_PC(m_eip);
1028 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
1029 } else {
1030 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
1031 }
1032 }
1033
i386_jo_rel16()1034 void i386_device::i386_jo_rel16() // Opcode 0x0f 80
1035 {
1036 int16_t disp = FETCH16();
1037 if( m_OF != 0 ) {
1038 if (m_sreg[CS].d)
1039 {
1040 m_eip += disp;
1041 }
1042 else
1043 {
1044 m_eip = (m_eip + disp) & 0xffff;
1045 }
1046 CHANGE_PC(m_eip);
1047 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
1048 } else {
1049 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
1050 }
1051 }
1052
i386_jp_rel16()1053 void i386_device::i386_jp_rel16() // Opcode 0x0f 8a
1054 {
1055 int16_t disp = FETCH16();
1056 if( m_PF != 0 ) {
1057 if (m_sreg[CS].d)
1058 {
1059 m_eip += disp;
1060 }
1061 else
1062 {
1063 m_eip = (m_eip + disp) & 0xffff;
1064 }
1065 CHANGE_PC(m_eip);
1066 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
1067 } else {
1068 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
1069 }
1070 }
1071
i386_js_rel16()1072 void i386_device::i386_js_rel16() // Opcode 0x0f 88
1073 {
1074 int16_t disp = FETCH16();
1075 if( m_SF != 0 ) {
1076 if (m_sreg[CS].d)
1077 {
1078 m_eip += disp;
1079 }
1080 else
1081 {
1082 m_eip = (m_eip + disp) & 0xffff;
1083 }
1084 CHANGE_PC(m_eip);
1085 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
1086 } else {
1087 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
1088 }
1089 }
1090
i386_jz_rel16()1091 void i386_device::i386_jz_rel16() // Opcode 0x0f 84
1092 {
1093 int16_t disp = FETCH16();
1094 if( m_ZF != 0 ) {
1095 if (m_sreg[CS].d)
1096 {
1097 m_eip += disp;
1098 }
1099 else
1100 {
1101 m_eip = (m_eip + disp) & 0xffff;
1102 }
1103 CHANGE_PC(m_eip);
1104 CYCLES(CYCLES_JCC_FULL_DISP); /* TODO: Timing = 7 + m */
1105 } else {
1106 CYCLES(CYCLES_JCC_FULL_DISP_NOBRANCH);
1107 }
1108 }
1109
i386_jcxz16()1110 void i386_device::i386_jcxz16() // Opcode 0xe3
1111 {
1112 int8_t disp = FETCH();
1113 int val = (m_address_size)?(REG32(ECX) == 0):(REG16(CX) == 0);
1114 if( val ) {
1115 if (m_sreg[CS].d)
1116 {
1117 m_eip += disp;
1118 }
1119 else
1120 {
1121 m_eip = (m_eip + disp) & 0xffff;
1122 }
1123 CHANGE_PC(m_eip);
1124 CYCLES(CYCLES_JCXZ); /* TODO: Timing = 9 + m */
1125 } else {
1126 CYCLES(CYCLES_JCXZ_NOBRANCH);
1127 }
1128 }
1129
i386_jmp_rel16()1130 void i386_device::i386_jmp_rel16() // Opcode 0xe9
1131 {
1132 int16_t disp = FETCH16();
1133
1134 if (m_sreg[CS].d)
1135 {
1136 m_eip += disp;
1137 }
1138 else
1139 {
1140 m_eip = (m_eip + disp) & 0xffff;
1141 }
1142 CHANGE_PC(m_eip);
1143 CYCLES(CYCLES_JMP); /* TODO: Timing = 7 + m */
1144 }
1145
i386_jmp_abs16()1146 void i386_device::i386_jmp_abs16() // Opcode 0xea
1147 {
1148 uint16_t address = FETCH16();
1149 uint16_t segment = FETCH16();
1150
1151 if( PROTECTED_MODE && !V8086_MODE)
1152 {
1153 i386_protected_mode_jump(segment,address,0,0);
1154 }
1155 else
1156 {
1157 m_eip = address;
1158 m_sreg[CS].selector = segment;
1159 m_performed_intersegment_jump = 1;
1160 i386_load_segment_descriptor(CS);
1161 CHANGE_PC(m_eip);
1162 }
1163 CYCLES(CYCLES_JMP_INTERSEG);
1164 }
1165
i386_lea16()1166 void i386_device::i386_lea16() // Opcode 0x8d
1167 {
1168 uint8_t modrm = FETCH();
1169 uint32_t ea = GetNonTranslatedEA(modrm,nullptr);
1170 STORE_REG16(modrm, ea);
1171 CYCLES(CYCLES_LEA);
1172 }
1173
i386_enter16()1174 void i386_device::i386_enter16() // Opcode 0xc8
1175 {
1176 uint16_t framesize = FETCH16();
1177 uint8_t level = FETCH() % 32;
1178 uint8_t x;
1179 uint16_t frameptr;
1180 PUSH16(REG16(BP));
1181
1182 if(!STACK_32BIT)
1183 frameptr = REG16(SP);
1184 else
1185 frameptr = REG32(ESP);
1186
1187 if(level > 0)
1188 {
1189 for(x=1;x<=level-1;x++)
1190 {
1191 uint32_t addr;
1192 if(!STACK_32BIT)
1193 {
1194 REG16(BP) -= 2;
1195 addr = REG16(BP);
1196 }
1197 else
1198 {
1199 REG32(EBP) -= 2;
1200 addr = REG32(EBP);
1201 }
1202 PUSH16(READ16(i386_translate(SS, addr, 0)));
1203 }
1204 PUSH16(frameptr);
1205 }
1206 REG16(BP) = frameptr;
1207 if(!STACK_32BIT)
1208 REG16(SP) -= framesize;
1209 else
1210 REG32(ESP) -= framesize;
1211 CYCLES(CYCLES_ENTER);
1212 }
1213
i386_leave16()1214 void i386_device::i386_leave16() // Opcode 0xc9
1215 {
1216 if(!STACK_32BIT)
1217 REG16(SP) = REG16(BP);
1218 else
1219 REG32(ESP) = REG32(EBP);
1220 REG16(BP) = POP16();
1221 CYCLES(CYCLES_LEAVE);
1222 }
1223
i386_lodsw()1224 void i386_device::i386_lodsw() // Opcode 0xad
1225 {
1226 uint32_t eas;
1227 if( m_segment_prefix ) {
1228 eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 );
1229 } else {
1230 eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 );
1231 }
1232 REG16(AX) = READ16(eas);
1233 BUMP_SI(2);
1234 CYCLES(CYCLES_LODS);
1235 }
1236
i386_loop16()1237 void i386_device::i386_loop16() // Opcode 0xe2
1238 {
1239 int8_t disp = FETCH();
1240 int32_t val = (m_address_size)?(--REG32(ECX)):(--REG16(CX));
1241 if( val != 0 ) {
1242 if (m_sreg[CS].d)
1243 {
1244 m_eip += disp;
1245 }
1246 else
1247 {
1248 m_eip = (m_eip + disp) & 0xffff;
1249 }
1250 CHANGE_PC(m_eip);
1251 }
1252 CYCLES(CYCLES_LOOP); /* TODO: Timing = 11 + m */
1253 }
1254
i386_loopne16()1255 void i386_device::i386_loopne16() // Opcode 0xe0
1256 {
1257 int8_t disp = FETCH();
1258 int32_t val = (m_address_size)?(--REG32(ECX)):(--REG16(CX));
1259 if( val != 0 && m_ZF == 0 ) {
1260 if (m_sreg[CS].d)
1261 {
1262 m_eip += disp;
1263 }
1264 else
1265 {
1266 m_eip = (m_eip + disp) & 0xffff;
1267 }
1268 CHANGE_PC(m_eip);
1269 }
1270 CYCLES(CYCLES_LOOPNZ); /* TODO: Timing = 11 + m */
1271 }
1272
i386_loopz16()1273 void i386_device::i386_loopz16() // Opcode 0xe1
1274 {
1275 int8_t disp = FETCH();
1276 int32_t val = (m_address_size)?(--REG32(ECX)):(--REG16(CX));
1277 if( val != 0 && m_ZF != 0 ) {
1278 if (m_sreg[CS].d)
1279 {
1280 m_eip += disp;
1281 }
1282 else
1283 {
1284 m_eip = (m_eip + disp) & 0xffff;
1285 }
1286 CHANGE_PC(m_eip);
1287 }
1288 CYCLES(CYCLES_LOOPZ); /* TODO: Timing = 11 + m */
1289 }
1290
i386_mov_rm16_r16()1291 void i386_device::i386_mov_rm16_r16() // Opcode 0x89
1292 {
1293 uint16_t src;
1294 uint8_t modrm = FETCH();
1295 if( modrm >= 0xc0 ) {
1296 src = LOAD_REG16(modrm);
1297 STORE_RM16(modrm, src);
1298 CYCLES(CYCLES_MOV_REG_REG);
1299 } else {
1300 uint32_t ea = GetEA(modrm,1);
1301 src = LOAD_REG16(modrm);
1302 WRITE16(ea, src);
1303 CYCLES(CYCLES_MOV_REG_MEM);
1304 }
1305 }
1306
i386_mov_r16_rm16()1307 void i386_device::i386_mov_r16_rm16() // Opcode 0x8b
1308 {
1309 uint16_t src;
1310 uint8_t modrm = FETCH();
1311 if( modrm >= 0xc0 ) {
1312 src = LOAD_RM16(modrm);
1313 STORE_REG16(modrm, src);
1314 CYCLES(CYCLES_MOV_REG_REG);
1315 } else {
1316 uint32_t ea = GetEA(modrm,0);
1317 src = READ16(ea);
1318 STORE_REG16(modrm, src);
1319 CYCLES(CYCLES_MOV_MEM_REG);
1320 }
1321 }
1322
i386_mov_rm16_i16()1323 void i386_device::i386_mov_rm16_i16() // Opcode 0xc7
1324 {
1325 uint8_t modrm = FETCH();
1326 if( modrm >= 0xc0 ) {
1327 uint16_t value = FETCH16();
1328 STORE_RM16(modrm, value);
1329 CYCLES(CYCLES_MOV_IMM_REG);
1330 } else {
1331 uint32_t ea = GetEA(modrm,1);
1332 uint16_t value = FETCH16();
1333 WRITE16(ea, value);
1334 CYCLES(CYCLES_MOV_IMM_MEM);
1335 }
1336 }
1337
i386_mov_ax_m16()1338 void i386_device::i386_mov_ax_m16() // Opcode 0xa1
1339 {
1340 uint32_t offset, ea;
1341 if( m_address_size ) {
1342 offset = FETCH32();
1343 } else {
1344 offset = FETCH16();
1345 }
1346 /* TODO: Not sure if this is correct... */
1347 if( m_segment_prefix ) {
1348 ea = i386_translate(m_segment_override, offset, 0 );
1349 } else {
1350 ea = i386_translate(DS, offset, 0 );
1351 }
1352 REG16(AX) = READ16(ea);
1353 CYCLES(CYCLES_MOV_MEM_ACC);
1354 }
1355
i386_mov_m16_ax()1356 void i386_device::i386_mov_m16_ax() // Opcode 0xa3
1357 {
1358 uint32_t offset, ea;
1359 if( m_address_size ) {
1360 offset = FETCH32();
1361 } else {
1362 offset = FETCH16();
1363 }
1364 /* TODO: Not sure if this is correct... */
1365 if( m_segment_prefix ) {
1366 ea = i386_translate(m_segment_override, offset, 1 );
1367 } else {
1368 ea = i386_translate(DS, offset, 1 );
1369 }
1370 WRITE16(ea, REG16(AX) );
1371 CYCLES(CYCLES_MOV_ACC_MEM);
1372 }
1373
i386_mov_ax_i16()1374 void i386_device::i386_mov_ax_i16() // Opcode 0xb8
1375 {
1376 REG16(AX) = FETCH16();
1377 CYCLES(CYCLES_MOV_IMM_REG);
1378 }
1379
i386_mov_cx_i16()1380 void i386_device::i386_mov_cx_i16() // Opcode 0xb9
1381 {
1382 REG16(CX) = FETCH16();
1383 CYCLES(CYCLES_MOV_IMM_REG);
1384 }
1385
i386_mov_dx_i16()1386 void i386_device::i386_mov_dx_i16() // Opcode 0xba
1387 {
1388 REG16(DX) = FETCH16();
1389 CYCLES(CYCLES_MOV_IMM_REG);
1390 }
1391
i386_mov_bx_i16()1392 void i386_device::i386_mov_bx_i16() // Opcode 0xbb
1393 {
1394 REG16(BX) = FETCH16();
1395 CYCLES(CYCLES_MOV_IMM_REG);
1396 }
1397
i386_mov_sp_i16()1398 void i386_device::i386_mov_sp_i16() // Opcode 0xbc
1399 {
1400 REG16(SP) = FETCH16();
1401 CYCLES(CYCLES_MOV_IMM_REG);
1402 }
1403
i386_mov_bp_i16()1404 void i386_device::i386_mov_bp_i16() // Opcode 0xbd
1405 {
1406 REG16(BP) = FETCH16();
1407 CYCLES(CYCLES_MOV_IMM_REG);
1408 }
1409
i386_mov_si_i16()1410 void i386_device::i386_mov_si_i16() // Opcode 0xbe
1411 {
1412 REG16(SI) = FETCH16();
1413 CYCLES(CYCLES_MOV_IMM_REG);
1414 }
1415
i386_mov_di_i16()1416 void i386_device::i386_mov_di_i16() // Opcode 0xbf
1417 {
1418 REG16(DI) = FETCH16();
1419 CYCLES(CYCLES_MOV_IMM_REG);
1420 }
1421
i386_movsw()1422 void i386_device::i386_movsw() // Opcode 0xa5
1423 {
1424 uint32_t eas, ead;
1425 uint16_t v;
1426 if( m_segment_prefix ) {
1427 eas = i386_translate(m_segment_override, m_address_size ? REG32(ESI) : REG16(SI), 0 );
1428 } else {
1429 eas = i386_translate(DS, m_address_size ? REG32(ESI) : REG16(SI), 0 );
1430 }
1431 ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 );
1432 v = READ16(eas);
1433 WRITE16(ead, v);
1434 BUMP_SI(2);
1435 BUMP_DI(2);
1436 CYCLES(CYCLES_MOVS);
1437 }
1438
i386_movsx_r16_rm8()1439 void i386_device::i386_movsx_r16_rm8() // Opcode 0x0f be
1440 {
1441 uint8_t modrm = FETCH();
1442 if( modrm >= 0xc0 ) {
1443 int16_t src = (int8_t)LOAD_RM8(modrm);
1444 STORE_REG16(modrm, src);
1445 CYCLES(CYCLES_MOVSX_REG_REG);
1446 } else {
1447 uint32_t ea = GetEA(modrm,0);
1448 int16_t src = (int8_t)READ8(ea);
1449 STORE_REG16(modrm, src);
1450 CYCLES(CYCLES_MOVSX_MEM_REG);
1451 }
1452 }
1453
i386_movzx_r16_rm8()1454 void i386_device::i386_movzx_r16_rm8() // Opcode 0x0f b6
1455 {
1456 uint8_t modrm = FETCH();
1457 if( modrm >= 0xc0 ) {
1458 uint16_t src = (uint8_t)LOAD_RM8(modrm);
1459 STORE_REG16(modrm, src);
1460 CYCLES(CYCLES_MOVZX_REG_REG);
1461 } else {
1462 uint32_t ea = GetEA(modrm,0);
1463 uint16_t src = (uint8_t)READ8(ea);
1464 STORE_REG16(modrm, src);
1465 CYCLES(CYCLES_MOVZX_MEM_REG);
1466 }
1467 }
1468
i386_or_rm16_r16()1469 void i386_device::i386_or_rm16_r16() // Opcode 0x09
1470 {
1471 uint16_t src, dst;
1472 uint8_t modrm = FETCH();
1473 if( modrm >= 0xc0 ) {
1474 src = LOAD_REG16(modrm);
1475 dst = LOAD_RM16(modrm);
1476 dst = OR16(dst, src);
1477 STORE_RM16(modrm, dst);
1478 CYCLES(CYCLES_ALU_REG_REG);
1479 } else {
1480 uint32_t ea = GetEA(modrm,1);
1481 src = LOAD_REG16(modrm);
1482 dst = READ16(ea);
1483 dst = OR16(dst, src);
1484 WRITE16(ea, dst);
1485 CYCLES(CYCLES_ALU_REG_MEM);
1486 }
1487 }
1488
i386_or_r16_rm16()1489 void i386_device::i386_or_r16_rm16() // Opcode 0x0b
1490 {
1491 uint16_t src, dst;
1492 uint8_t modrm = FETCH();
1493 if( modrm >= 0xc0 ) {
1494 src = LOAD_RM16(modrm);
1495 dst = LOAD_REG16(modrm);
1496 dst = OR16(dst, src);
1497 STORE_REG16(modrm, dst);
1498 CYCLES(CYCLES_ALU_REG_REG);
1499 } else {
1500 uint32_t ea = GetEA(modrm,0);
1501 src = READ16(ea);
1502 dst = LOAD_REG16(modrm);
1503 dst = OR16(dst, src);
1504 STORE_REG16(modrm, dst);
1505 CYCLES(CYCLES_ALU_MEM_REG);
1506 }
1507 }
1508
i386_or_ax_i16()1509 void i386_device::i386_or_ax_i16() // Opcode 0x0d
1510 {
1511 uint16_t src, dst;
1512 src = FETCH16();
1513 dst = REG16(AX);
1514 dst = OR16(dst, src);
1515 REG16(AX) = dst;
1516 CYCLES(CYCLES_ALU_IMM_ACC);
1517 }
1518
i386_out_ax_i8()1519 void i386_device::i386_out_ax_i8() // Opcode 0xe7
1520 {
1521 uint16_t port = FETCH();
1522 uint16_t data = REG16(AX);
1523 WRITEPORT16(port, data);
1524 CYCLES(CYCLES_OUT_VAR);
1525 }
1526
i386_out_ax_dx()1527 void i386_device::i386_out_ax_dx() // Opcode 0xef
1528 {
1529 uint16_t port = REG16(DX);
1530 uint16_t data = REG16(AX);
1531 WRITEPORT16(port, data);
1532 CYCLES(CYCLES_OUT);
1533 }
1534
i386_pop_ax()1535 void i386_device::i386_pop_ax() // Opcode 0x58
1536 {
1537 uint32_t offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1538 if(i386_limit_check(SS,offset+1) == 0)
1539 REG16(AX) = POP16();
1540 else
1541 FAULT(FAULT_SS,0)
1542 CYCLES(CYCLES_POP_REG_SHORT);
1543 }
1544
i386_pop_cx()1545 void i386_device::i386_pop_cx() // Opcode 0x59
1546 {
1547 uint32_t offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1548 if(i386_limit_check(SS,offset+1) == 0)
1549 REG16(CX) = POP16();
1550 else
1551 FAULT(FAULT_SS,0)
1552 CYCLES(CYCLES_POP_REG_SHORT);
1553 }
1554
i386_pop_dx()1555 void i386_device::i386_pop_dx() // Opcode 0x5a
1556 {
1557 uint32_t offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1558 if(i386_limit_check(SS,offset+1) == 0)
1559 REG16(DX) = POP16();
1560 else
1561 FAULT(FAULT_SS,0)
1562 CYCLES(CYCLES_POP_REG_SHORT);
1563 }
1564
i386_pop_bx()1565 void i386_device::i386_pop_bx() // Opcode 0x5b
1566 {
1567 uint32_t offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1568 if(i386_limit_check(SS,offset+1) == 0)
1569 REG16(BX) = POP16();
1570 else
1571 FAULT(FAULT_SS,0)
1572 CYCLES(CYCLES_POP_REG_SHORT);
1573 }
1574
i386_pop_sp()1575 void i386_device::i386_pop_sp() // Opcode 0x5c
1576 {
1577 uint32_t offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1578 if(i386_limit_check(SS,offset+1) == 0)
1579 REG16(SP) = POP16();
1580 else
1581 FAULT(FAULT_SS,0)
1582 CYCLES(CYCLES_POP_REG_SHORT);
1583 }
1584
i386_pop_bp()1585 void i386_device::i386_pop_bp() // Opcode 0x5d
1586 {
1587 uint32_t offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1588 if(i386_limit_check(SS,offset+1) == 0)
1589 REG16(BP) = POP16();
1590 else
1591 FAULT(FAULT_SS,0)
1592 CYCLES(CYCLES_POP_REG_SHORT);
1593 }
1594
i386_pop_si()1595 void i386_device::i386_pop_si() // Opcode 0x5e
1596 {
1597 uint32_t offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1598 if(i386_limit_check(SS,offset+1) == 0)
1599 REG16(SI) = POP16();
1600 else
1601 FAULT(FAULT_SS,0)
1602 CYCLES(CYCLES_POP_REG_SHORT);
1603 }
1604
i386_pop_di()1605 void i386_device::i386_pop_di() // Opcode 0x5f
1606 {
1607 uint32_t offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1608 if(i386_limit_check(SS,offset+1) == 0)
1609 REG16(DI) = POP16();
1610 else
1611 FAULT(FAULT_SS,0)
1612 CYCLES(CYCLES_POP_REG_SHORT);
1613 }
1614
i386_pop_seg16(int segment)1615 bool i386_device::i386_pop_seg16(int segment)
1616 {
1617 uint32_t ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1618 uint16_t value;
1619 bool fault;
1620 if(i386_limit_check(SS,offset+1) == 0)
1621 {
1622 ea = i386_translate(SS, offset, 0);
1623 value = READ16(ea);
1624 i386_sreg_load(value, segment, &fault);
1625 if(fault) return false;
1626 if(STACK_32BIT)
1627 REG32(ESP) = offset + 2;
1628 else
1629 REG16(SP) = offset + 2;
1630 }
1631 else
1632 {
1633 m_ext = 1;
1634 i386_trap_with_error(FAULT_SS,0,0,0);
1635 return false;
1636 }
1637 CYCLES(CYCLES_POP_SREG);
1638 return true;
1639 }
1640
i386_pop_ds16()1641 void i386_device::i386_pop_ds16() // Opcode 0x1f
1642 {
1643 i386_pop_seg16(DS);
1644 }
1645
i386_pop_es16()1646 void i386_device::i386_pop_es16() // Opcode 0x07
1647 {
1648 i386_pop_seg16(ES);
1649 }
1650
i386_pop_fs16()1651 void i386_device::i386_pop_fs16() // Opcode 0x0f a1
1652 {
1653 i386_pop_seg16(FS);
1654 }
1655
i386_pop_gs16()1656 void i386_device::i386_pop_gs16() // Opcode 0x0f a9
1657 {
1658 i386_pop_seg16(GS);
1659 }
1660
i386_pop_ss16()1661 void i386_device::i386_pop_ss16() // Opcode 0x17
1662 {
1663 if(!i386_pop_seg16(SS)) return;
1664 if(m_IF != 0) // if external interrupts are enabled
1665 {
1666 m_IF = 0; // reset IF for the next instruction
1667 m_delayed_interrupt_enable = 1;
1668 }
1669 }
1670
i386_pop_rm16()1671 void i386_device::i386_pop_rm16() // Opcode 0x8f
1672 {
1673 uint8_t modrm = FETCH();
1674 uint16_t value;
1675 uint32_t ea, offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1676
1677 if(i386_limit_check(SS,offset+1) == 0)
1678 {
1679 uint32_t temp_sp = REG32(ESP);
1680 value = POP16();
1681
1682 if( modrm >= 0xc0 ) {
1683 STORE_RM16(modrm, value);
1684 } else {
1685 try
1686 {
1687 ea = GetEA(modrm,1);
1688 WRITE16(ea, value);
1689 }
1690 catch(uint64_t e)
1691 {
1692 REG32(ESP) = temp_sp;
1693 throw e;
1694 }
1695 }
1696 }
1697 else
1698 FAULT(FAULT_SS,0)
1699 CYCLES(CYCLES_POP_RM);
1700 }
1701
i386_popa()1702 void i386_device::i386_popa() // Opcode 0x61
1703 {
1704 uint32_t offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1705
1706 if(i386_limit_check(SS,offset+15) == 0)
1707 {
1708 REG16(DI) = POP16();
1709 REG16(SI) = POP16();
1710 REG16(BP) = POP16();
1711 REG16(SP) += 2;
1712 REG16(BX) = POP16();
1713 REG16(DX) = POP16();
1714 REG16(CX) = POP16();
1715 REG16(AX) = POP16();
1716 }
1717 else
1718 FAULT(FAULT_SS,0)
1719 CYCLES(CYCLES_POPA);
1720 }
1721
i386_popf()1722 void i386_device::i386_popf() // Opcode 0x9d
1723 {
1724 uint32_t value;
1725 uint32_t current = get_flags();
1726 uint8_t IOPL = (current >> 12) & 0x03;
1727 uint32_t mask = 0x7fd5;
1728 uint32_t offset = (STACK_32BIT ? REG32(ESP) : REG16(SP));
1729
1730 // IOPL can only change if CPL is 0
1731 if(m_CPL != 0)
1732 mask &= ~0x00003000;
1733
1734 // IF can only change if CPL is at least as privileged as IOPL
1735 if(m_CPL > IOPL)
1736 mask &= ~0x00000200;
1737
1738 if(V8086_MODE)
1739 {
1740 if(IOPL < 3)
1741 {
1742 logerror("POPFD(%08x): IOPL < 3 while in V86 mode.\n",m_pc);
1743 FAULT(FAULT_GP,0) // #GP(0)
1744 }
1745 mask &= ~0x00003000; // IOPL cannot be changed while in V8086 mode
1746 }
1747
1748 if(i386_limit_check(SS,offset+1) == 0)
1749 {
1750 value = POP16();
1751 set_flags((current & ~mask) | (value & mask)); // mask out reserved bits
1752 }
1753 else
1754 FAULT(FAULT_SS,0)
1755 CYCLES(CYCLES_POPF);
1756
1757 m_auto_clear_RF = false;
1758 }
1759
i386_push_ax()1760 void i386_device::i386_push_ax() // Opcode 0x50
1761 {
1762 uint32_t offset;
1763 if(STACK_32BIT)
1764 offset = REG32(ESP) - 2;
1765 else
1766 offset = (REG16(SP) - 2) & 0xffff;
1767 if(i386_limit_check(SS,offset) == 0)
1768 PUSH16(REG16(AX) );
1769 else
1770 FAULT(FAULT_SS,0)
1771 CYCLES(CYCLES_PUSH_REG_SHORT);
1772 }
1773
i386_push_cx()1774 void i386_device::i386_push_cx() // Opcode 0x51
1775 {
1776 uint32_t offset;
1777 if(STACK_32BIT)
1778 offset = REG32(ESP) - 2;
1779 else
1780 offset = (REG16(SP) - 2) & 0xffff;
1781 if(i386_limit_check(SS,offset) == 0)
1782 PUSH16(REG16(CX) );
1783 else
1784 FAULT(FAULT_SS,0)
1785 CYCLES(CYCLES_PUSH_REG_SHORT);
1786 }
1787
i386_push_dx()1788 void i386_device::i386_push_dx() // Opcode 0x52
1789 {
1790 uint32_t offset;
1791 if(STACK_32BIT)
1792 offset = REG32(ESP) - 2;
1793 else
1794 offset = (REG16(SP) - 2) & 0xffff;
1795 if(i386_limit_check(SS,offset) == 0)
1796 PUSH16(REG16(DX) );
1797 else
1798 FAULT(FAULT_SS,0)
1799 CYCLES(CYCLES_PUSH_REG_SHORT);
1800 }
1801
i386_push_bx()1802 void i386_device::i386_push_bx() // Opcode 0x53
1803 {
1804 uint32_t offset;
1805 if(STACK_32BIT)
1806 offset = REG32(ESP) - 2;
1807 else
1808 offset = (REG16(SP) - 2) & 0xffff;
1809 if(i386_limit_check(SS,offset) == 0)
1810 PUSH16(REG16(BX) );
1811 else
1812 FAULT(FAULT_SS,0)
1813 CYCLES(CYCLES_PUSH_REG_SHORT);
1814 }
1815
i386_push_sp()1816 void i386_device::i386_push_sp() // Opcode 0x54
1817 {
1818 uint32_t offset;
1819 if(STACK_32BIT)
1820 offset = REG32(ESP) - 2;
1821 else
1822 offset = (REG16(SP) - 2) & 0xffff;
1823 if(i386_limit_check(SS,offset) == 0)
1824 PUSH16(REG16(SP) );
1825 else
1826 FAULT(FAULT_SS,0)
1827 CYCLES(CYCLES_PUSH_REG_SHORT);
1828 }
1829
i386_push_bp()1830 void i386_device::i386_push_bp() // Opcode 0x55
1831 {
1832 uint32_t offset;
1833 if(STACK_32BIT)
1834 offset = REG32(ESP) - 2;
1835 else
1836 offset = (REG16(SP) - 2) & 0xffff;
1837 if(i386_limit_check(SS,offset) == 0)
1838 PUSH16(REG16(BP) );
1839 else
1840 FAULT(FAULT_SS,0)
1841 CYCLES(CYCLES_PUSH_REG_SHORT);
1842 }
1843
i386_push_si()1844 void i386_device::i386_push_si() // Opcode 0x56
1845 {
1846 uint32_t offset;
1847 if(STACK_32BIT)
1848 offset = REG32(ESP) - 2;
1849 else
1850 offset = (REG16(SP) - 2) & 0xffff;
1851 if(i386_limit_check(SS,offset) == 0)
1852 PUSH16(REG16(SI) );
1853 else
1854 FAULT(FAULT_SS,0)
1855 CYCLES(CYCLES_PUSH_REG_SHORT);
1856 }
1857
i386_push_di()1858 void i386_device::i386_push_di() // Opcode 0x57
1859 {
1860 uint32_t offset;
1861 if(STACK_32BIT)
1862 offset = REG32(ESP) - 2;
1863 else
1864 offset = (REG16(SP) - 2) & 0xffff;
1865 if(i386_limit_check(SS,offset) == 0)
1866 PUSH16(REG16(DI) );
1867 else
1868 FAULT(FAULT_SS,0)
1869 CYCLES(CYCLES_PUSH_REG_SHORT);
1870 }
1871
i386_push_cs16()1872 void i386_device::i386_push_cs16() // Opcode 0x0e
1873 {
1874 uint32_t offset;
1875 if(STACK_32BIT)
1876 offset = REG32(ESP) - 2;
1877 else
1878 offset = (REG16(SP) - 2) & 0xffff;
1879 if(i386_limit_check(SS,offset) == 0)
1880 PUSH16(m_sreg[CS].selector );
1881 else
1882 FAULT(FAULT_SS,0)
1883 CYCLES(CYCLES_PUSH_SREG);
1884 }
1885
i386_push_ds16()1886 void i386_device::i386_push_ds16() // Opcode 0x1e
1887 {
1888 uint32_t offset;
1889 if(STACK_32BIT)
1890 offset = REG32(ESP) - 2;
1891 else
1892 offset = (REG16(SP) - 2) & 0xffff;
1893 if(i386_limit_check(SS,offset) == 0)
1894 PUSH16(m_sreg[DS].selector );
1895 else
1896 FAULT(FAULT_SS,0)
1897 CYCLES(CYCLES_PUSH_SREG);
1898 }
1899
i386_push_es16()1900 void i386_device::i386_push_es16() // Opcode 0x06
1901 {
1902 uint32_t offset;
1903 if(STACK_32BIT)
1904 offset = REG32(ESP) - 2;
1905 else
1906 offset = (REG16(SP) - 2) & 0xffff;
1907 if(i386_limit_check(SS,offset) == 0)
1908 PUSH16(m_sreg[ES].selector );
1909 else
1910 FAULT(FAULT_SS,0)
1911 CYCLES(CYCLES_PUSH_SREG);
1912 }
1913
i386_push_fs16()1914 void i386_device::i386_push_fs16() // Opcode 0x0f a0
1915 {
1916 uint32_t offset;
1917 if(STACK_32BIT)
1918 offset = REG32(ESP) - 2;
1919 else
1920 offset = (REG16(SP) - 2) & 0xffff;
1921 if(i386_limit_check(SS,offset) == 0)
1922 PUSH16(m_sreg[FS].selector );
1923 else
1924 FAULT(FAULT_SS,0)
1925 CYCLES(CYCLES_PUSH_SREG);
1926 }
1927
i386_push_gs16()1928 void i386_device::i386_push_gs16() // Opcode 0x0f a8
1929 {
1930 uint32_t offset;
1931 if(STACK_32BIT)
1932 offset = REG32(ESP) - 2;
1933 else
1934 offset = (REG16(SP) - 2) & 0xffff;
1935 if(i386_limit_check(SS,offset) == 0)
1936 PUSH16(m_sreg[GS].selector );
1937 else
1938 FAULT(FAULT_SS,0)
1939 CYCLES(CYCLES_PUSH_SREG);
1940 }
1941
i386_push_ss16()1942 void i386_device::i386_push_ss16() // Opcode 0x16
1943 {
1944 uint32_t offset;
1945 if(STACK_32BIT)
1946 offset = REG32(ESP) - 2;
1947 else
1948 offset = (REG16(SP) - 2) & 0xffff;
1949 if(i386_limit_check(SS,offset) == 0)
1950 PUSH16(m_sreg[SS].selector );
1951 else
1952 FAULT(FAULT_SS,0)
1953 CYCLES(CYCLES_PUSH_SREG);
1954 }
1955
i386_push_i16()1956 void i386_device::i386_push_i16() // Opcode 0x68
1957 {
1958 uint16_t value = FETCH16();
1959 uint32_t offset;
1960 if(STACK_32BIT)
1961 offset = REG32(ESP) - 2;
1962 else
1963 offset = (REG16(SP) - 2) & 0xffff;
1964 if(i386_limit_check(SS,offset) == 0)
1965 PUSH16(value);
1966 else
1967 FAULT(FAULT_SS,0)
1968 CYCLES(CYCLES_PUSH_IMM);
1969 }
1970
i386_pusha()1971 void i386_device::i386_pusha() // Opcode 0x60
1972 {
1973 uint16_t temp = REG16(SP);
1974 uint32_t offset;
1975 if(STACK_32BIT)
1976 offset = REG32(ESP) - 16;
1977 else
1978 offset = (REG16(SP) - 16) & 0xffff;
1979 if(i386_limit_check(SS,offset) == 0)
1980 {
1981 PUSH16(REG16(AX) );
1982 PUSH16(REG16(CX) );
1983 PUSH16(REG16(DX) );
1984 PUSH16(REG16(BX) );
1985 PUSH16(temp );
1986 PUSH16(REG16(BP) );
1987 PUSH16(REG16(SI) );
1988 PUSH16(REG16(DI) );
1989 }
1990 else
1991 FAULT(FAULT_SS,0)
1992 CYCLES(CYCLES_PUSHA);
1993 }
1994
i386_pushf()1995 void i386_device::i386_pushf() // Opcode 0x9c
1996 {
1997 uint32_t offset;
1998 if(STACK_32BIT)
1999 offset = REG32(ESP) - 2;
2000 else
2001 offset = (REG16(SP) - 2) & 0xffff;
2002 if(i386_limit_check(SS,offset) == 0)
2003 PUSH16(get_flags() & 0xffff );
2004 else
2005 FAULT(FAULT_SS,0)
2006 CYCLES(CYCLES_PUSHF);
2007 }
2008
i386_ret_near16_i16()2009 void i386_device::i386_ret_near16_i16() // Opcode 0xc2
2010 {
2011 int16_t disp = FETCH16();
2012 m_eip = POP16();
2013 REG16(SP) += disp;
2014 CHANGE_PC(m_eip);
2015 CYCLES(CYCLES_RET_IMM); /* TODO: Timing = 10 + m */
2016 }
2017
i386_ret_near16()2018 void i386_device::i386_ret_near16() // Opcode 0xc3
2019 {
2020 m_eip = POP16();
2021 CHANGE_PC(m_eip);
2022 CYCLES(CYCLES_RET); /* TODO: Timing = 10 + m */
2023 }
2024
i386_sbb_rm16_r16()2025 void i386_device::i386_sbb_rm16_r16() // Opcode 0x19
2026 {
2027 uint16_t src, dst;
2028 uint8_t modrm = FETCH();
2029 if( modrm >= 0xc0 ) {
2030 src = LOAD_REG16(modrm);
2031 dst = LOAD_RM16(modrm);
2032 dst = SBB16(dst, src, m_CF);
2033 STORE_RM16(modrm, dst);
2034 CYCLES(CYCLES_ALU_REG_REG);
2035 } else {
2036 uint32_t ea = GetEA(modrm,1);
2037 src = LOAD_REG16(modrm);
2038 dst = READ16(ea);
2039 dst = SBB16(dst, src, m_CF);
2040 WRITE16(ea, dst);
2041 CYCLES(CYCLES_ALU_REG_MEM);
2042 }
2043 }
2044
i386_sbb_r16_rm16()2045 void i386_device::i386_sbb_r16_rm16() // Opcode 0x1b
2046 {
2047 uint16_t src, dst;
2048 uint8_t modrm = FETCH();
2049 if( modrm >= 0xc0 ) {
2050 src = LOAD_RM16(modrm);
2051 dst = LOAD_REG16(modrm);
2052 dst = SBB16(dst, src, m_CF);
2053 STORE_REG16(modrm, dst);
2054 CYCLES(CYCLES_ALU_REG_REG);
2055 } else {
2056 uint32_t ea = GetEA(modrm,0);
2057 src = READ16(ea);
2058 dst = LOAD_REG16(modrm);
2059 dst = SBB16(dst, src, m_CF);
2060 STORE_REG16(modrm, dst);
2061 CYCLES(CYCLES_ALU_MEM_REG);
2062 }
2063 }
2064
i386_sbb_ax_i16()2065 void i386_device::i386_sbb_ax_i16() // Opcode 0x1d
2066 {
2067 uint16_t src, dst;
2068 src = FETCH16();
2069 dst = REG16(AX);
2070 dst = SBB16(dst, src, m_CF);
2071 REG16(AX) = dst;
2072 CYCLES(CYCLES_ALU_IMM_ACC);
2073 }
2074
i386_scasw()2075 void i386_device::i386_scasw() // Opcode 0xaf
2076 {
2077 uint32_t eas;
2078 uint16_t src, dst;
2079 eas = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 0 );
2080 src = READ16(eas);
2081 dst = REG16(AX);
2082 SUB16(dst, src);
2083 BUMP_DI(2);
2084 CYCLES(CYCLES_SCAS);
2085 }
2086
i386_shld16_i8()2087 void i386_device::i386_shld16_i8() // Opcode 0x0f a4
2088 {
2089 uint8_t modrm = FETCH();
2090 if( modrm >= 0xc0 ) {
2091 uint16_t dst = LOAD_RM16(modrm);
2092 uint16_t upper = LOAD_REG16(modrm);
2093 uint8_t shift = FETCH();
2094 shift &= 31;
2095 if( shift == 0 ) {
2096 } else if( shift > 15 ) {
2097 m_CF = (upper & (1 << (16-shift))) ? 1 : 0;
2098 // ppro and above should be (dst >> (32-shift))
2099 dst = (upper << (shift-16)) | (upper >> (32-shift));
2100 m_OF = m_CF ^ (dst >> 15);
2101 SetSZPF16(dst);
2102 } else {
2103 m_CF = (dst & (1 << (16-shift))) ? 1 : 0;
2104 dst = (dst << shift) | (upper >> (16-shift));
2105 m_OF = m_CF ^ (dst >> 15);
2106 SetSZPF16(dst);
2107 }
2108 STORE_RM16(modrm, dst);
2109 CYCLES(CYCLES_SHLD_REG);
2110 } else {
2111 uint32_t ea = GetEA(modrm,1);
2112 uint16_t dst = READ16(ea);
2113 uint16_t upper = LOAD_REG16(modrm);
2114 uint8_t shift = FETCH();
2115 shift &= 31;
2116 if( shift == 0 ) {
2117 } else if( shift > 15 ) {
2118 m_CF = (upper & (1 << (16-shift))) ? 1 : 0;
2119 dst = (upper << (shift-16)) | (upper >> (32-shift));
2120 m_OF = m_CF ^ (dst >> 15);
2121 SetSZPF16(dst);
2122 } else {
2123 m_CF = (dst & (1 << (16-shift))) ? 1 : 0;
2124 dst = (dst << shift) | (upper >> (16-shift));
2125 m_OF = m_CF ^ (dst >> 15);
2126 SetSZPF16(dst);
2127 }
2128 WRITE16(ea, dst);
2129 CYCLES(CYCLES_SHLD_MEM);
2130 }
2131 }
2132
i386_shld16_cl()2133 void i386_device::i386_shld16_cl() // Opcode 0x0f a5
2134 {
2135 uint8_t modrm = FETCH();
2136 if( modrm >= 0xc0 ) {
2137 uint16_t dst = LOAD_RM16(modrm);
2138 uint16_t upper = LOAD_REG16(modrm);
2139 uint8_t shift = REG8(CL);
2140 shift &= 31;
2141 if( shift == 0 ) {
2142 } else if( shift > 15 ) {
2143 m_CF = (upper & (1 << (16-shift))) ? 1 : 0;
2144 dst = (upper << (shift-16)) | (upper >> (32-shift));
2145 m_OF = m_CF ^ (dst >> 15);
2146 SetSZPF16(dst);
2147 } else {
2148 m_CF = (dst & (1 << (16-shift))) ? 1 : 0;
2149 dst = (dst << shift) | (upper >> (16-shift));
2150 m_OF = m_CF ^ (dst >> 15);
2151 SetSZPF16(dst);
2152 }
2153 STORE_RM16(modrm, dst);
2154 CYCLES(CYCLES_SHLD_REG);
2155 } else {
2156 uint32_t ea = GetEA(modrm,1);
2157 uint16_t dst = READ16(ea);
2158 uint16_t upper = LOAD_REG16(modrm);
2159 uint8_t shift = REG8(CL);
2160 shift &= 31;
2161 if( shift == 0 ) {
2162 } else if( shift > 15 ) {
2163 m_CF = (upper & (1 << (16-shift))) ? 1 : 0;
2164 dst = (upper << (shift-16)) | (upper >> (32-shift));
2165 m_OF = m_CF ^ (dst >> 15);
2166 SetSZPF16(dst);
2167 } else {
2168 m_CF = (dst & (1 << (16-shift))) ? 1 : 0;
2169 dst = (dst << shift) | (upper >> (16-shift));
2170 m_OF = m_CF ^ (dst >> 15);
2171 SetSZPF16(dst);
2172 }
2173 WRITE16(ea, dst);
2174 CYCLES(CYCLES_SHLD_MEM);
2175 }
2176 }
2177
i386_shrd16_i8()2178 void i386_device::i386_shrd16_i8() // Opcode 0x0f ac
2179 {
2180 uint8_t modrm = FETCH();
2181 if( modrm >= 0xc0 ) {
2182 uint16_t dst = LOAD_RM16(modrm);
2183 uint16_t upper = LOAD_REG16(modrm);
2184 uint8_t shift = FETCH();
2185 shift &= 31;
2186 if( shift == 0) {
2187 } else if( shift > 15 ) {
2188 m_CF = (upper & (1 << (shift-1))) ? 1 : 0;
2189 dst = (upper >> (shift-16)) | (upper << (32-shift));
2190 m_OF = ((dst >> 15) ^ (dst >> 14)) & 1;
2191 SetSZPF16(dst);
2192 } else {
2193 m_CF = (dst & (1 << (shift-1))) ? 1 : 0;
2194 dst = (dst >> shift) | (upper << (16-shift));
2195 m_OF = ((dst >> 15) ^ (dst >> 14)) & 1;
2196 SetSZPF16(dst);
2197 }
2198 STORE_RM16(modrm, dst);
2199 CYCLES(CYCLES_SHRD_REG);
2200 } else {
2201 uint32_t ea = GetEA(modrm,1);
2202 uint16_t dst = READ16(ea);
2203 uint16_t upper = LOAD_REG16(modrm);
2204 uint8_t shift = FETCH();
2205 shift &= 31;
2206 if( shift == 0) {
2207 } else if( shift > 15 ) {
2208 m_CF = (upper & (1 << (shift-1))) ? 1 : 0;
2209 dst = (upper >> (shift-16)) | (upper << (32-shift));
2210 m_OF = ((dst >> 15) ^ (dst >> 14)) & 1;
2211 SetSZPF16(dst);
2212 } else {
2213 m_CF = (dst & (1 << (shift-1))) ? 1 : 0;
2214 dst = (dst >> shift) | (upper << (16-shift));
2215 m_OF = ((dst >> 15) ^ (dst >> 14)) & 1;
2216 SetSZPF16(dst);
2217 }
2218 WRITE16(ea, dst);
2219 CYCLES(CYCLES_SHRD_MEM);
2220 }
2221 }
2222
i386_shrd16_cl()2223 void i386_device::i386_shrd16_cl() // Opcode 0x0f ad
2224 {
2225 uint8_t modrm = FETCH();
2226 if( modrm >= 0xc0 ) {
2227 uint16_t dst = LOAD_RM16(modrm);
2228 uint16_t upper = LOAD_REG16(modrm);
2229 uint8_t shift = REG8(CL);
2230 shift &= 31;
2231 if( shift == 0) {
2232 } else if( shift > 15 ) {
2233 m_CF = (upper & (1 << (shift-1))) ? 1 : 0;
2234 dst = (upper >> (shift-16)) | (upper << (32-shift));
2235 m_OF = ((dst >> 15) ^ (dst >> 14)) & 1;
2236 SetSZPF16(dst);
2237 } else {
2238 m_CF = (dst & (1 << (shift-1))) ? 1 : 0;
2239 dst = (dst >> shift) | (upper << (16-shift));
2240 m_OF = ((dst >> 15) ^ (dst >> 14)) & 1;
2241 SetSZPF16(dst);
2242 }
2243 STORE_RM16(modrm, dst);
2244 CYCLES(CYCLES_SHRD_REG);
2245 } else {
2246 uint32_t ea = GetEA(modrm,1);
2247 uint16_t dst = READ16(ea);
2248 uint16_t upper = LOAD_REG16(modrm);
2249 uint8_t shift = REG8(CL);
2250 shift &= 31;
2251 if( shift == 0) {
2252 } else if( shift > 15 ) {
2253 m_CF = (upper & (1 << (shift-1))) ? 1 : 0;
2254 dst = (upper >> (shift-16)) | (upper << (32-shift));
2255 m_OF = ((dst >> 15) ^ (dst >> 14)) & 1;
2256 SetSZPF16(dst);
2257 } else {
2258 m_CF = (dst & (1 << (shift-1))) ? 1 : 0;
2259 dst = (dst >> shift) | (upper << (16-shift));
2260 m_OF = ((dst >> 15) ^ (dst >> 14)) & 1;
2261 SetSZPF16(dst);
2262 }
2263 WRITE16(ea, dst);
2264 CYCLES(CYCLES_SHRD_MEM);
2265 }
2266 }
2267
i386_stosw()2268 void i386_device::i386_stosw() // Opcode 0xab
2269 {
2270 uint32_t ead;
2271 ead = i386_translate(ES, m_address_size ? REG32(EDI) : REG16(DI), 1 );
2272 WRITE16(ead, REG16(AX));
2273 BUMP_DI(2);
2274 CYCLES(CYCLES_STOS);
2275 }
2276
i386_sub_rm16_r16()2277 void i386_device::i386_sub_rm16_r16() // Opcode 0x29
2278 {
2279 uint16_t src, dst;
2280 uint8_t modrm = FETCH();
2281 if( modrm >= 0xc0 ) {
2282 src = LOAD_REG16(modrm);
2283 dst = LOAD_RM16(modrm);
2284 dst = SUB16(dst, src);
2285 STORE_RM16(modrm, dst);
2286 CYCLES(CYCLES_ALU_REG_REG);
2287 } else {
2288 uint32_t ea = GetEA(modrm,1);
2289 src = LOAD_REG16(modrm);
2290 dst = READ16(ea);
2291 dst = SUB16(dst, src);
2292 WRITE16(ea, dst);
2293 CYCLES(CYCLES_ALU_REG_MEM);
2294 }
2295 }
2296
i386_sub_r16_rm16()2297 void i386_device::i386_sub_r16_rm16() // Opcode 0x2b
2298 {
2299 uint16_t src, dst;
2300 uint8_t modrm = FETCH();
2301 if( modrm >= 0xc0 ) {
2302 src = LOAD_RM16(modrm);
2303 dst = LOAD_REG16(modrm);
2304 dst = SUB16(dst, src);
2305 STORE_REG16(modrm, dst);
2306 CYCLES(CYCLES_ALU_REG_REG);
2307 } else {
2308 uint32_t ea = GetEA(modrm,0);
2309 src = READ16(ea);
2310 dst = LOAD_REG16(modrm);
2311 dst = SUB16(dst, src);
2312 STORE_REG16(modrm, dst);
2313 CYCLES(CYCLES_ALU_MEM_REG);
2314 }
2315 }
2316
i386_sub_ax_i16()2317 void i386_device::i386_sub_ax_i16() // Opcode 0x2d
2318 {
2319 uint16_t src, dst;
2320 src = FETCH16();
2321 dst = REG16(AX);
2322 dst = SUB16(dst, src);
2323 REG16(AX) = dst;
2324 CYCLES(CYCLES_ALU_IMM_ACC);
2325 }
2326
i386_test_ax_i16()2327 void i386_device::i386_test_ax_i16() // Opcode 0xa9
2328 {
2329 uint16_t src = FETCH16();
2330 uint16_t dst = REG16(AX);
2331 dst = src & dst;
2332 SetSZPF16(dst);
2333 m_CF = 0;
2334 m_OF = 0;
2335 CYCLES(CYCLES_TEST_IMM_ACC);
2336 }
2337
i386_test_rm16_r16()2338 void i386_device::i386_test_rm16_r16() // Opcode 0x85
2339 {
2340 uint16_t src, dst;
2341 uint8_t modrm = FETCH();
2342 if( modrm >= 0xc0 ) {
2343 src = LOAD_REG16(modrm);
2344 dst = LOAD_RM16(modrm);
2345 dst = src & dst;
2346 SetSZPF16(dst);
2347 m_CF = 0;
2348 m_OF = 0;
2349 CYCLES(CYCLES_TEST_REG_REG);
2350 } else {
2351 uint32_t ea = GetEA(modrm,0);
2352 src = LOAD_REG16(modrm);
2353 dst = READ16(ea);
2354 dst = src & dst;
2355 SetSZPF16(dst);
2356 m_CF = 0;
2357 m_OF = 0;
2358 CYCLES(CYCLES_TEST_REG_MEM);
2359 }
2360 }
2361
i386_xchg_ax_cx()2362 void i386_device::i386_xchg_ax_cx() // Opcode 0x91
2363 {
2364 uint16_t temp;
2365 temp = REG16(AX);
2366 REG16(AX) = REG16(CX);
2367 REG16(CX) = temp;
2368 CYCLES(CYCLES_XCHG_REG_REG);
2369 }
2370
i386_xchg_ax_dx()2371 void i386_device::i386_xchg_ax_dx() // Opcode 0x92
2372 {
2373 uint16_t temp;
2374 temp = REG16(AX);
2375 REG16(AX) = REG16(DX);
2376 REG16(DX) = temp;
2377 CYCLES(CYCLES_XCHG_REG_REG);
2378 }
2379
i386_xchg_ax_bx()2380 void i386_device::i386_xchg_ax_bx() // Opcode 0x93
2381 {
2382 uint16_t temp;
2383 temp = REG16(AX);
2384 REG16(AX) = REG16(BX);
2385 REG16(BX) = temp;
2386 CYCLES(CYCLES_XCHG_REG_REG);
2387 }
2388
i386_xchg_ax_sp()2389 void i386_device::i386_xchg_ax_sp() // Opcode 0x94
2390 {
2391 uint16_t temp;
2392 temp = REG16(AX);
2393 REG16(AX) = REG16(SP);
2394 REG16(SP) = temp;
2395 CYCLES(CYCLES_XCHG_REG_REG);
2396 }
2397
i386_xchg_ax_bp()2398 void i386_device::i386_xchg_ax_bp() // Opcode 0x95
2399 {
2400 uint16_t temp;
2401 temp = REG16(AX);
2402 REG16(AX) = REG16(BP);
2403 REG16(BP) = temp;
2404 CYCLES(CYCLES_XCHG_REG_REG);
2405 }
2406
i386_xchg_ax_si()2407 void i386_device::i386_xchg_ax_si() // Opcode 0x96
2408 {
2409 uint16_t temp;
2410 temp = REG16(AX);
2411 REG16(AX) = REG16(SI);
2412 REG16(SI) = temp;
2413 CYCLES(CYCLES_XCHG_REG_REG);
2414 }
2415
i386_xchg_ax_di()2416 void i386_device::i386_xchg_ax_di() // Opcode 0x97
2417 {
2418 uint16_t temp;
2419 temp = REG16(AX);
2420 REG16(AX) = REG16(DI);
2421 REG16(DI) = temp;
2422 CYCLES(CYCLES_XCHG_REG_REG);
2423 }
2424
i386_xchg_r16_rm16()2425 void i386_device::i386_xchg_r16_rm16() // Opcode 0x87
2426 {
2427 uint8_t modrm = FETCH();
2428 if( modrm >= 0xc0 ) {
2429 uint16_t src = LOAD_RM16(modrm);
2430 uint16_t dst = LOAD_REG16(modrm);
2431 STORE_REG16(modrm, src);
2432 STORE_RM16(modrm, dst);
2433 CYCLES(CYCLES_XCHG_REG_REG);
2434 } else {
2435 uint32_t ea = GetEA(modrm,1);
2436 uint16_t src = READ16(ea);
2437 uint16_t dst = LOAD_REG16(modrm);
2438 STORE_REG16(modrm, src);
2439 WRITE16(ea, dst);
2440 CYCLES(CYCLES_XCHG_REG_MEM);
2441 }
2442 }
2443
i386_xor_rm16_r16()2444 void i386_device::i386_xor_rm16_r16() // Opcode 0x31
2445 {
2446 uint16_t src, dst;
2447 uint8_t modrm = FETCH();
2448 if( modrm >= 0xc0 ) {
2449 src = LOAD_REG16(modrm);
2450 dst = LOAD_RM16(modrm);
2451 dst = XOR16(dst, src);
2452 STORE_RM16(modrm, dst);
2453 CYCLES(CYCLES_ALU_REG_REG);
2454 } else {
2455 uint32_t ea = GetEA(modrm,1);
2456 src = LOAD_REG16(modrm);
2457 dst = READ16(ea);
2458 dst = XOR16(dst, src);
2459 WRITE16(ea, dst);
2460 CYCLES(CYCLES_ALU_REG_MEM);
2461 }
2462 }
2463
i386_xor_r16_rm16()2464 void i386_device::i386_xor_r16_rm16() // Opcode 0x33
2465 {
2466 uint16_t src, dst;
2467 uint8_t modrm = FETCH();
2468 if( modrm >= 0xc0 ) {
2469 src = LOAD_RM16(modrm);
2470 dst = LOAD_REG16(modrm);
2471 dst = XOR16(dst, src);
2472 STORE_REG16(modrm, dst);
2473 CYCLES(CYCLES_ALU_REG_REG);
2474 } else {
2475 uint32_t ea = GetEA(modrm,0);
2476 src = READ16(ea);
2477 dst = LOAD_REG16(modrm);
2478 dst = XOR16(dst, src);
2479 STORE_REG16(modrm, dst);
2480 CYCLES(CYCLES_ALU_MEM_REG);
2481 }
2482 }
2483
i386_xor_ax_i16()2484 void i386_device::i386_xor_ax_i16() // Opcode 0x35
2485 {
2486 uint16_t src, dst;
2487 src = FETCH16();
2488 dst = REG16(AX);
2489 dst = XOR16(dst, src);
2490 REG16(AX) = dst;
2491 CYCLES(CYCLES_ALU_IMM_ACC);
2492 }
2493
2494
2495
i386_group81_16()2496 void i386_device::i386_group81_16() // Opcode 0x81
2497 {
2498 uint32_t ea;
2499 uint16_t src, dst;
2500 uint8_t modrm = FETCH();
2501
2502 switch( (modrm >> 3) & 0x7 )
2503 {
2504 case 0: // ADD Rm16, i16
2505 if( modrm >= 0xc0 ) {
2506 dst = LOAD_RM16(modrm);
2507 src = FETCH16();
2508 dst = ADD16(dst, src);
2509 STORE_RM16(modrm, dst);
2510 CYCLES(CYCLES_ALU_REG_REG);
2511 } else {
2512 ea = GetEA(modrm,1);
2513 dst = READ16(ea);
2514 src = FETCH16();
2515 dst = ADD16(dst, src);
2516 WRITE16(ea, dst);
2517 CYCLES(CYCLES_ALU_REG_MEM);
2518 }
2519 break;
2520 case 1: // OR Rm16, i16
2521 if( modrm >= 0xc0 ) {
2522 dst = LOAD_RM16(modrm);
2523 src = FETCH16();
2524 dst = OR16(dst, src);
2525 STORE_RM16(modrm, dst);
2526 CYCLES(CYCLES_ALU_REG_REG);
2527 } else {
2528 ea = GetEA(modrm,1);
2529 dst = READ16(ea);
2530 src = FETCH16();
2531 dst = OR16(dst, src);
2532 WRITE16(ea, dst);
2533 CYCLES(CYCLES_ALU_REG_MEM);
2534 }
2535 break;
2536 case 2: // ADC Rm16, i16
2537 if( modrm >= 0xc0 ) {
2538 dst = LOAD_RM16(modrm);
2539 src = FETCH16();
2540 dst = ADC16(dst, src, m_CF);
2541 STORE_RM16(modrm, dst);
2542 CYCLES(CYCLES_ALU_REG_REG);
2543 } else {
2544 ea = GetEA(modrm,1);
2545 dst = READ16(ea);
2546 src = FETCH16();
2547 dst = ADC16(dst, src, m_CF);
2548 WRITE16(ea, dst);
2549 CYCLES(CYCLES_ALU_REG_MEM);
2550 }
2551 break;
2552 case 3: // SBB Rm16, i16
2553 if( modrm >= 0xc0 ) {
2554 dst = LOAD_RM16(modrm);
2555 src = FETCH16();
2556 dst = SBB16(dst, src, m_CF);
2557 STORE_RM16(modrm, dst);
2558 CYCLES(CYCLES_ALU_REG_REG);
2559 } else {
2560 ea = GetEA(modrm,1);
2561 dst = READ16(ea);
2562 src = FETCH16();
2563 dst = SBB16(dst, src, m_CF);
2564 WRITE16(ea, dst);
2565 CYCLES(CYCLES_ALU_REG_MEM);
2566 }
2567 break;
2568 case 4: // AND Rm16, i16
2569 if( modrm >= 0xc0 ) {
2570 dst = LOAD_RM16(modrm);
2571 src = FETCH16();
2572 dst = AND16(dst, src);
2573 STORE_RM16(modrm, dst);
2574 CYCLES(CYCLES_ALU_REG_REG);
2575 } else {
2576 ea = GetEA(modrm,1);
2577 dst = READ16(ea);
2578 src = FETCH16();
2579 dst = AND16(dst, src);
2580 WRITE16(ea, dst);
2581 CYCLES(CYCLES_ALU_REG_MEM);
2582 }
2583 break;
2584 case 5: // SUB Rm16, i16
2585 if( modrm >= 0xc0 ) {
2586 dst = LOAD_RM16(modrm);
2587 src = FETCH16();
2588 dst = SUB16(dst, src);
2589 STORE_RM16(modrm, dst);
2590 CYCLES(CYCLES_ALU_REG_REG);
2591 } else {
2592 ea = GetEA(modrm,1);
2593 dst = READ16(ea);
2594 src = FETCH16();
2595 dst = SUB16(dst, src);
2596 WRITE16(ea, dst);
2597 CYCLES(CYCLES_ALU_REG_MEM);
2598 }
2599 break;
2600 case 6: // XOR Rm16, i16
2601 if( modrm >= 0xc0 ) {
2602 dst = LOAD_RM16(modrm);
2603 src = FETCH16();
2604 dst = XOR16(dst, src);
2605 STORE_RM16(modrm, dst);
2606 CYCLES(CYCLES_ALU_REG_REG);
2607 } else {
2608 ea = GetEA(modrm,1);
2609 dst = READ16(ea);
2610 src = FETCH16();
2611 dst = XOR16(dst, src);
2612 WRITE16(ea, dst);
2613 CYCLES(CYCLES_ALU_REG_MEM);
2614 }
2615 break;
2616 case 7: // CMP Rm16, i16
2617 if( modrm >= 0xc0 ) {
2618 dst = LOAD_RM16(modrm);
2619 src = FETCH16();
2620 SUB16(dst, src);
2621 CYCLES(CYCLES_CMP_REG_REG);
2622 } else {
2623 ea = GetEA(modrm,0);
2624 dst = READ16(ea);
2625 src = FETCH16();
2626 SUB16(dst, src);
2627 CYCLES(CYCLES_CMP_REG_MEM);
2628 }
2629 break;
2630 }
2631 }
2632
i386_group83_16()2633 void i386_device::i386_group83_16() // Opcode 0x83
2634 {
2635 uint32_t ea;
2636 uint16_t src, dst;
2637 uint8_t modrm = FETCH();
2638
2639 switch( (modrm >> 3) & 0x7 )
2640 {
2641 case 0: // ADD Rm16, i16
2642 if( modrm >= 0xc0 ) {
2643 dst = LOAD_RM16(modrm);
2644 src = (uint16_t)(int16_t)(int8_t)FETCH();
2645 dst = ADD16(dst, src);
2646 STORE_RM16(modrm, dst);
2647 CYCLES(CYCLES_ALU_REG_REG);
2648 } else {
2649 ea = GetEA(modrm,1);
2650 dst = READ16(ea);
2651 src = (uint16_t)(int16_t)(int8_t)FETCH();
2652 dst = ADD16(dst, src);
2653 WRITE16(ea, dst);
2654 CYCLES(CYCLES_ALU_REG_MEM);
2655 }
2656 break;
2657 case 1: // OR Rm16, i16
2658 if( modrm >= 0xc0 ) {
2659 dst = LOAD_RM16(modrm);
2660 src = (uint16_t)(int16_t)(int8_t)FETCH();
2661 dst = OR16(dst, src);
2662 STORE_RM16(modrm, dst);
2663 CYCLES(CYCLES_ALU_REG_REG);
2664 } else {
2665 ea = GetEA(modrm,1);
2666 dst = READ16(ea);
2667 src = (uint16_t)(int16_t)(int8_t)FETCH();
2668 dst = OR16(dst, src);
2669 WRITE16(ea, dst);
2670 CYCLES(CYCLES_ALU_REG_MEM);
2671 }
2672 break;
2673 case 2: // ADC Rm16, i16
2674 if( modrm >= 0xc0 ) {
2675 dst = LOAD_RM16(modrm);
2676 src = (uint16_t)(int16_t)(int8_t)FETCH();
2677 dst = ADC16(dst, src, m_CF);
2678 STORE_RM16(modrm, dst);
2679 CYCLES(CYCLES_ALU_REG_REG);
2680 } else {
2681 ea = GetEA(modrm,1);
2682 dst = READ16(ea);
2683 src = (uint16_t)(int16_t)(int8_t)FETCH();
2684 dst = ADC16(dst, src, m_CF);
2685 WRITE16(ea, dst);
2686 CYCLES(CYCLES_ALU_REG_MEM);
2687 }
2688 break;
2689 case 3: // SBB Rm16, i16
2690 if( modrm >= 0xc0 ) {
2691 dst = LOAD_RM16(modrm);
2692 src = ((uint16_t)(int16_t)(int8_t)FETCH());
2693 dst = SBB16(dst, src, m_CF);
2694 STORE_RM16(modrm, dst);
2695 CYCLES(CYCLES_ALU_REG_REG);
2696 } else {
2697 ea = GetEA(modrm,1);
2698 dst = READ16(ea);
2699 src = ((uint16_t)(int16_t)(int8_t)FETCH());
2700 dst = SBB16(dst, src, m_CF);
2701 WRITE16(ea, dst);
2702 CYCLES(CYCLES_ALU_REG_MEM);
2703 }
2704 break;
2705 case 4: // AND Rm16, i16
2706 if( modrm >= 0xc0 ) {
2707 dst = LOAD_RM16(modrm);
2708 src = (uint16_t)(int16_t)(int8_t)FETCH();
2709 dst = AND16(dst, src);
2710 STORE_RM16(modrm, dst);
2711 CYCLES(CYCLES_ALU_REG_REG);
2712 } else {
2713 ea = GetEA(modrm,1);
2714 dst = READ16(ea);
2715 src = (uint16_t)(int16_t)(int8_t)FETCH();
2716 dst = AND16(dst, src);
2717 WRITE16(ea, dst);
2718 CYCLES(CYCLES_ALU_REG_MEM);
2719 }
2720 break;
2721 case 5: // SUB Rm16, i16
2722 if( modrm >= 0xc0 ) {
2723 dst = LOAD_RM16(modrm);
2724 src = (uint16_t)(int16_t)(int8_t)FETCH();
2725 dst = SUB16(dst, src);
2726 STORE_RM16(modrm, dst);
2727 CYCLES(CYCLES_ALU_REG_REG);
2728 } else {
2729 ea = GetEA(modrm,1);
2730 dst = READ16(ea);
2731 src = (uint16_t)(int16_t)(int8_t)FETCH();
2732 dst = SUB16(dst, src);
2733 WRITE16(ea, dst);
2734 CYCLES(CYCLES_ALU_REG_MEM);
2735 }
2736 break;
2737 case 6: // XOR Rm16, i16
2738 if( modrm >= 0xc0 ) {
2739 dst = LOAD_RM16(modrm);
2740 src = (uint16_t)(int16_t)(int8_t)FETCH();
2741 dst = XOR16(dst, src);
2742 STORE_RM16(modrm, dst);
2743 CYCLES(CYCLES_ALU_REG_REG);
2744 } else {
2745 ea = GetEA(modrm,1);
2746 dst = READ16(ea);
2747 src = (uint16_t)(int16_t)(int8_t)FETCH();
2748 dst = XOR16(dst, src);
2749 WRITE16(ea, dst);
2750 CYCLES(CYCLES_ALU_REG_MEM);
2751 }
2752 break;
2753 case 7: // CMP Rm16, i16
2754 if( modrm >= 0xc0 ) {
2755 dst = LOAD_RM16(modrm);
2756 src = (uint16_t)(int16_t)(int8_t)FETCH();
2757 SUB16(dst, src);
2758 CYCLES(CYCLES_CMP_REG_REG);
2759 } else {
2760 ea = GetEA(modrm,0);
2761 dst = READ16(ea);
2762 src = (uint16_t)(int16_t)(int8_t)FETCH();
2763 SUB16(dst, src);
2764 CYCLES(CYCLES_CMP_REG_MEM);
2765 }
2766 break;
2767 }
2768 }
2769
i386_groupC1_16()2770 void i386_device::i386_groupC1_16() // Opcode 0xc1
2771 {
2772 uint16_t dst;
2773 uint8_t modrm = FETCH();
2774 uint8_t shift;
2775
2776 if( modrm >= 0xc0 ) {
2777 dst = LOAD_RM16(modrm);
2778 shift = FETCH() & 0x1f;
2779 dst = i386_shift_rotate16(modrm, dst, shift);
2780 STORE_RM16(modrm, dst);
2781 } else {
2782 uint32_t ea = GetEA(modrm,1);
2783 dst = READ16(ea);
2784 shift = FETCH() & 0x1f;
2785 dst = i386_shift_rotate16(modrm, dst, shift);
2786 WRITE16(ea, dst);
2787 }
2788 }
2789
i386_groupD1_16()2790 void i386_device::i386_groupD1_16() // Opcode 0xd1
2791 {
2792 uint16_t dst;
2793 uint8_t modrm = FETCH();
2794
2795 if( modrm >= 0xc0 ) {
2796 dst = LOAD_RM16(modrm);
2797 dst = i386_shift_rotate16(modrm, dst, 1);
2798 STORE_RM16(modrm, dst);
2799 } else {
2800 uint32_t ea = GetEA(modrm,1);
2801 dst = READ16(ea);
2802 dst = i386_shift_rotate16(modrm, dst, 1);
2803 WRITE16(ea, dst);
2804 }
2805 }
2806
i386_groupD3_16()2807 void i386_device::i386_groupD3_16() // Opcode 0xd3
2808 {
2809 uint16_t dst;
2810 uint8_t modrm = FETCH();
2811
2812 if( modrm >= 0xc0 ) {
2813 dst = LOAD_RM16(modrm);
2814 dst = i386_shift_rotate16(modrm, dst, REG8(CL));
2815 STORE_RM16(modrm, dst);
2816 } else {
2817 uint32_t ea = GetEA(modrm,1);
2818 dst = READ16(ea);
2819 dst = i386_shift_rotate16(modrm, dst, REG8(CL));
2820 WRITE16(ea, dst);
2821 }
2822 }
2823
i386_groupF7_16()2824 void i386_device::i386_groupF7_16() // Opcode 0xf7
2825 {
2826 uint8_t modrm = FETCH();
2827
2828 switch( (modrm >> 3) & 0x7 )
2829 {
2830 case 0: /* TEST Rm16, i16 */
2831 if( modrm >= 0xc0 ) {
2832 uint16_t dst = LOAD_RM16(modrm);
2833 uint16_t src = FETCH16();
2834 dst &= src;
2835 m_CF = m_OF = m_AF = 0;
2836 SetSZPF16(dst);
2837 CYCLES(CYCLES_TEST_IMM_REG);
2838 } else {
2839 uint32_t ea = GetEA(modrm,0);
2840 uint16_t dst = READ16(ea);
2841 uint16_t src = FETCH16();
2842 dst &= src;
2843 m_CF = m_OF = m_AF = 0;
2844 SetSZPF16(dst);
2845 CYCLES(CYCLES_TEST_IMM_MEM);
2846 }
2847 break;
2848 case 2: /* NOT Rm16 */
2849 if( modrm >= 0xc0 ) {
2850 uint16_t dst = LOAD_RM16(modrm);
2851 dst = ~dst;
2852 STORE_RM16(modrm, dst);
2853 CYCLES(CYCLES_NOT_REG);
2854 } else {
2855 uint32_t ea = GetEA(modrm,1);
2856 uint16_t dst = READ16(ea);
2857 dst = ~dst;
2858 WRITE16(ea, dst);
2859 CYCLES(CYCLES_NOT_MEM);
2860 }
2861 break;
2862 case 3: /* NEG Rm16 */
2863 if( modrm >= 0xc0 ) {
2864 uint16_t dst = LOAD_RM16(modrm);
2865 dst = SUB16(0, dst );
2866 STORE_RM16(modrm, dst);
2867 CYCLES(CYCLES_NEG_REG);
2868 } else {
2869 uint32_t ea = GetEA(modrm,1);
2870 uint16_t dst = READ16(ea);
2871 dst = SUB16(0, dst );
2872 WRITE16(ea, dst);
2873 CYCLES(CYCLES_NEG_MEM);
2874 }
2875 break;
2876 case 4: /* MUL AX, Rm16 */
2877 {
2878 uint32_t result;
2879 uint16_t src, dst;
2880 if( modrm >= 0xc0 ) {
2881 src = LOAD_RM16(modrm);
2882 CYCLES(CYCLES_MUL16_ACC_REG); /* TODO: Correct multiply timing */
2883 } else {
2884 uint32_t ea = GetEA(modrm,0);
2885 src = READ16(ea);
2886 CYCLES(CYCLES_MUL16_ACC_MEM); /* TODO: Correct multiply timing */
2887 }
2888
2889 dst = REG16(AX);
2890 result = (uint32_t)src * (uint32_t)dst;
2891 REG16(DX) = (uint16_t)(result >> 16);
2892 REG16(AX) = (uint16_t)result;
2893
2894 m_CF = m_OF = (REG16(DX) != 0);
2895 }
2896 break;
2897 case 5: /* IMUL AX, Rm16 */
2898 {
2899 int32_t result;
2900 int32_t src, dst;
2901 if( modrm >= 0xc0 ) {
2902 src = (int32_t)(int16_t)LOAD_RM16(modrm);
2903 CYCLES(CYCLES_IMUL16_ACC_REG); /* TODO: Correct multiply timing */
2904 } else {
2905 uint32_t ea = GetEA(modrm,0);
2906 src = (int32_t)(int16_t)READ16(ea);
2907 CYCLES(CYCLES_IMUL16_ACC_MEM); /* TODO: Correct multiply timing */
2908 }
2909
2910 dst = (int32_t)(int16_t)REG16(AX);
2911 result = src * dst;
2912
2913 REG16(DX) = (uint16_t)(result >> 16);
2914 REG16(AX) = (uint16_t)result;
2915
2916 m_CF = m_OF = !(result == (int32_t)(int16_t)result);
2917 }
2918 break;
2919 case 6: /* DIV AX, Rm16 */
2920 {
2921 uint32_t quotient, remainder, result;
2922 uint16_t src;
2923 if( modrm >= 0xc0 ) {
2924 src = LOAD_RM16(modrm);
2925 CYCLES(CYCLES_DIV16_ACC_REG);
2926 } else {
2927 uint32_t ea = GetEA(modrm,0);
2928 src = READ16(ea);
2929 CYCLES(CYCLES_DIV16_ACC_MEM);
2930 }
2931
2932 quotient = ((uint32_t)(REG16(DX)) << 16) | (uint32_t)(REG16(AX));
2933 if( src ) {
2934 remainder = quotient % (uint32_t)src;
2935 result = quotient / (uint32_t)src;
2936 if( result > 0xffff ) {
2937 /* TODO: Divide error */
2938 } else {
2939 REG16(DX) = (uint16_t)remainder;
2940 REG16(AX) = (uint16_t)result;
2941
2942 // this flag is actually undefined, enable on non-cyrix
2943 if (m_cpuid_id0 != 0x69727943)
2944 m_CF = 1;
2945 }
2946 } else {
2947 i386_trap(0, 0, 0);
2948 }
2949 }
2950 break;
2951 case 7: /* IDIV AX, Rm16 */
2952 {
2953 int32_t quotient, remainder, result;
2954 uint16_t src;
2955 if( modrm >= 0xc0 ) {
2956 src = LOAD_RM16(modrm);
2957 CYCLES(CYCLES_IDIV16_ACC_REG);
2958 } else {
2959 uint32_t ea = GetEA(modrm,0);
2960 src = READ16(ea);
2961 CYCLES(CYCLES_IDIV16_ACC_MEM);
2962 }
2963
2964 quotient = (((int32_t)REG16(DX)) << 16) | ((uint32_t)REG16(AX));
2965 if( src ) {
2966 remainder = quotient % (int32_t)(int16_t)src;
2967 result = quotient / (int32_t)(int16_t)src;
2968 if( result > 0xffff ) {
2969 /* TODO: Divide error */
2970 } else {
2971 REG16(DX) = (uint16_t)remainder;
2972 REG16(AX) = (uint16_t)result;
2973
2974 // this flag is actually undefined, enable on non-cyrix
2975 if (m_cpuid_id0 != 0x69727943)
2976 m_CF = 1;
2977 }
2978 } else {
2979 i386_trap(0, 0, 0);
2980 }
2981 }
2982 break;
2983 }
2984 }
2985
i386_groupFF_16()2986 void i386_device::i386_groupFF_16() // Opcode 0xff
2987 {
2988 uint8_t modrm = FETCH();
2989
2990 switch( (modrm >> 3) & 0x7 )
2991 {
2992 case 0: /* INC Rm16 */
2993 if( modrm >= 0xc0 ) {
2994 uint16_t dst = LOAD_RM16(modrm);
2995 dst = INC16(dst);
2996 STORE_RM16(modrm, dst);
2997 CYCLES(CYCLES_INC_REG);
2998 } else {
2999 uint32_t ea = GetEA(modrm,1);
3000 uint16_t dst = READ16(ea);
3001 dst = INC16(dst);
3002 WRITE16(ea, dst);
3003 CYCLES(CYCLES_INC_MEM);
3004 }
3005 break;
3006 case 1: /* DEC Rm16 */
3007 if( modrm >= 0xc0 ) {
3008 uint16_t dst = LOAD_RM16(modrm);
3009 dst = DEC16(dst);
3010 STORE_RM16(modrm, dst);
3011 CYCLES(CYCLES_DEC_REG);
3012 } else {
3013 uint32_t ea = GetEA(modrm,1);
3014 uint16_t dst = READ16(ea);
3015 dst = DEC16(dst);
3016 WRITE16(ea, dst);
3017 CYCLES(CYCLES_DEC_MEM);
3018 }
3019 break;
3020 case 2: /* CALL Rm16 */
3021 {
3022 uint16_t address;
3023 if( modrm >= 0xc0 ) {
3024 address = LOAD_RM16(modrm);
3025 CYCLES(CYCLES_CALL_REG); /* TODO: Timing = 7 + m */
3026 } else {
3027 uint32_t ea = GetEA(modrm,0);
3028 address = READ16(ea);
3029 CYCLES(CYCLES_CALL_MEM); /* TODO: Timing = 10 + m */
3030 }
3031 PUSH16(m_eip );
3032 m_eip = address;
3033 CHANGE_PC(m_eip);
3034 }
3035 break;
3036 case 3: /* CALL FAR Rm16 */
3037 {
3038 uint16_t address, selector;
3039 if( modrm >= 0xc0 )
3040 {
3041 report_invalid_modrm("groupFF_16", modrm);
3042 }
3043 else
3044 {
3045 uint32_t ea = GetEA(modrm,0);
3046 address = READ16(ea + 0);
3047 selector = READ16(ea + 2);
3048 CYCLES(CYCLES_CALL_MEM_INTERSEG); /* TODO: Timing = 10 + m */
3049
3050 if(PROTECTED_MODE && !V8086_MODE)
3051 {
3052 i386_protected_mode_call(selector,address,1,0);
3053 }
3054 else
3055 {
3056 PUSH16(m_sreg[CS].selector );
3057 PUSH16(m_eip );
3058 m_sreg[CS].selector = selector;
3059 m_performed_intersegment_jump = 1;
3060 i386_load_segment_descriptor(CS );
3061 m_eip = address;
3062 CHANGE_PC(m_eip);
3063 }
3064 }
3065 }
3066 break;
3067 case 4: /* JMP Rm16 */
3068 {
3069 uint16_t address;
3070 if( modrm >= 0xc0 ) {
3071 address = LOAD_RM16(modrm);
3072 CYCLES(CYCLES_JMP_REG); /* TODO: Timing = 7 + m */
3073 } else {
3074 uint32_t ea = GetEA(modrm,0);
3075 address = READ16(ea);
3076 CYCLES(CYCLES_JMP_MEM); /* TODO: Timing = 10 + m */
3077 }
3078 m_eip = address;
3079 CHANGE_PC(m_eip);
3080 }
3081 break;
3082 case 5: /* JMP FAR Rm16 */
3083 {
3084 uint16_t address, selector;
3085
3086 if( modrm >= 0xc0 )
3087 {
3088 report_invalid_modrm("groupFF_16", modrm);
3089 }
3090 else
3091 {
3092 uint32_t ea = GetEA(modrm,0);
3093 address = READ16(ea + 0);
3094 selector = READ16(ea + 2);
3095 CYCLES(CYCLES_JMP_MEM_INTERSEG); /* TODO: Timing = 10 + m */
3096 if(PROTECTED_MODE && !V8086_MODE)
3097 {
3098 i386_protected_mode_jump(selector,address,1,0);
3099 }
3100 else
3101 {
3102 m_sreg[CS].selector = selector;
3103 m_performed_intersegment_jump = 1;
3104 i386_load_segment_descriptor(CS );
3105 m_eip = address;
3106 CHANGE_PC(m_eip);
3107 }
3108 }
3109 }
3110 break;
3111 case 6: /* PUSH Rm16 */
3112 {
3113 uint16_t value;
3114 if( modrm >= 0xc0 ) {
3115 value = LOAD_RM16(modrm);
3116 } else {
3117 uint32_t ea = GetEA(modrm,0);
3118 value = READ16(ea);
3119 }
3120 PUSH16(value);
3121 CYCLES(CYCLES_PUSH_RM);
3122 }
3123 break;
3124 default:
3125 report_invalid_modrm("groupFF_16", modrm);
3126 break;
3127 }
3128 }
3129
i386_group0F00_16()3130 void i386_device::i386_group0F00_16() // Opcode 0x0f 00
3131 {
3132 uint32_t address, ea;
3133 uint8_t modrm = FETCH();
3134 I386_SREG seg;
3135 uint8_t result;
3136
3137 switch( (modrm >> 3) & 0x7 )
3138 {
3139 case 0: /* SLDT */
3140 if ( PROTECTED_MODE && !V8086_MODE )
3141 {
3142 if( modrm >= 0xc0 ) {
3143 STORE_RM16(modrm, m_ldtr.segment);
3144 CYCLES(CYCLES_SLDT_REG);
3145 } else {
3146 ea = GetEA(modrm,1);
3147 WRITE16(ea, m_ldtr.segment);
3148 CYCLES(CYCLES_SLDT_MEM);
3149 }
3150 }
3151 else
3152 {
3153 i386_trap(6, 0, 0);
3154 }
3155 break;
3156 case 1: /* STR */
3157 if ( PROTECTED_MODE && !V8086_MODE )
3158 {
3159 if( modrm >= 0xc0 ) {
3160 STORE_RM16(modrm, m_task.segment);
3161 CYCLES(CYCLES_STR_REG);
3162 } else {
3163 ea = GetEA(modrm,1);
3164 WRITE16(ea, m_task.segment);
3165 CYCLES(CYCLES_STR_MEM);
3166 }
3167 }
3168 else
3169 {
3170 i386_trap(6, 0, 0);
3171 }
3172 break;
3173 case 2: /* LLDT */
3174 if ( PROTECTED_MODE && !V8086_MODE )
3175 {
3176 if(m_CPL)
3177 FAULT(FAULT_GP,0)
3178 if( modrm >= 0xc0 ) {
3179 address = LOAD_RM16(modrm);
3180 m_ldtr.segment = address;
3181 CYCLES(CYCLES_LLDT_REG);
3182 } else {
3183 ea = GetEA(modrm,0);
3184 m_ldtr.segment = READ16(ea);
3185 CYCLES(CYCLES_LLDT_MEM);
3186 }
3187 memset(&seg, 0, sizeof(seg));
3188 seg.selector = m_ldtr.segment;
3189 i386_load_protected_mode_segment(&seg,nullptr);
3190 m_ldtr.limit = seg.limit;
3191 m_ldtr.base = seg.base;
3192 m_ldtr.flags = seg.flags;
3193 }
3194 else
3195 {
3196 i386_trap(6, 0, 0);
3197 }
3198 break;
3199
3200 case 3: /* LTR */
3201 if ( PROTECTED_MODE && !V8086_MODE )
3202 {
3203 if(m_CPL)
3204 FAULT(FAULT_GP,0)
3205 if( modrm >= 0xc0 ) {
3206 address = LOAD_RM16(modrm);
3207 m_task.segment = address;
3208 CYCLES(CYCLES_LTR_REG);
3209 } else {
3210 ea = GetEA(modrm,0);
3211 m_task.segment = READ16(ea);
3212 CYCLES(CYCLES_LTR_MEM);
3213 }
3214 memset(&seg, 0, sizeof(seg));
3215 seg.selector = m_task.segment;
3216 i386_load_protected_mode_segment(&seg,nullptr);
3217
3218 uint32_t addr = ((seg.selector & 4) ? m_ldtr.base : m_gdtr.base) + (seg.selector & ~7) + 5;
3219 i386_translate_address(TRANSLATE_READ, &addr, nullptr);
3220 m_program->write_byte(addr, (seg.flags & 0xff) | 2);
3221
3222 m_task.limit = seg.limit;
3223 m_task.base = seg.base;
3224 m_task.flags = seg.flags | 2;
3225 }
3226 else
3227 {
3228 i386_trap(6, 0, 0);
3229 }
3230 break;
3231
3232 case 4: /* VERR */
3233 if ( PROTECTED_MODE && !V8086_MODE )
3234 {
3235 result = 1;
3236 if( modrm >= 0xc0 ) {
3237 address = LOAD_RM16(modrm);
3238 CYCLES(CYCLES_VERR_REG);
3239 } else {
3240 ea = GetEA(modrm,0);
3241 address = READ16(ea);
3242 CYCLES(CYCLES_VERR_MEM);
3243 }
3244 memset(&seg, 0, sizeof(seg));
3245 seg.selector = address;
3246 result = i386_load_protected_mode_segment(&seg,nullptr);
3247 // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...)
3248 if(!(seg.flags & 0x10))
3249 result = 0;
3250 // check that the segment is readable
3251 if(seg.flags & 0x10) // is code or data segment
3252 {
3253 if(seg.flags & 0x08) // is code segment, so check if it's readable
3254 {
3255 if(!(seg.flags & 0x02))
3256 {
3257 result = 0;
3258 }
3259 else
3260 { // check if conforming, these are always readable, regardless of privilege
3261 if(!(seg.flags & 0x04))
3262 {
3263 // if not conforming, then we must check privilege levels (TODO: current privilege level check)
3264 if(((seg.flags >> 5) & 0x03) < (address & 0x03))
3265 result = 0;
3266 }
3267 }
3268 }
3269 }
3270 // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO)
3271 SetZF(result);
3272 }
3273 else
3274 {
3275 i386_trap(6, 0, 0);
3276 logerror("i386: VERR: Exception - Running in real mode or virtual 8086 mode.\n");
3277 }
3278 break;
3279
3280 case 5: /* VERW */
3281 if ( PROTECTED_MODE && !V8086_MODE )
3282 {
3283 result = 1;
3284 if( modrm >= 0xc0 ) {
3285 address = LOAD_RM16(modrm);
3286 CYCLES(CYCLES_VERW_REG);
3287 } else {
3288 ea = GetEA(modrm,0);
3289 address = READ16(ea);
3290 CYCLES(CYCLES_VERW_MEM);
3291 }
3292 memset(&seg, 0, sizeof(seg));
3293 seg.selector = address;
3294 result = i386_load_protected_mode_segment(&seg,nullptr);
3295 // check if the segment is a code or data segment (not a special segment type, like a TSS, gate, LDT...)
3296 if(!(seg.flags & 0x10))
3297 result = 0;
3298 // check that the segment is writable
3299 if(seg.flags & 0x10) // is code or data segment
3300 {
3301 if(seg.flags & 0x08) // is code segment (and thus, not writable)
3302 {
3303 result = 0;
3304 }
3305 else
3306 { // is data segment
3307 if(!(seg.flags & 0x02))
3308 result = 0;
3309 }
3310 }
3311 // check that the descriptor privilege is greater or equal to the selector's privilege level and the current privilege (TODO)
3312 if(((seg.flags >> 5) & 0x03) < (address & 0x03))
3313 result = 0;
3314 SetZF(result);
3315 }
3316 else
3317 {
3318 i386_trap(6, 0, 0);
3319 logerror("i386: VERW: Exception - Running in real mode or virtual 8086 mode.\n");
3320 }
3321 break;
3322
3323 default:
3324 report_invalid_modrm("group0F00_16", modrm);
3325 break;
3326 }
3327 }
3328
i386_group0F01_16()3329 void i386_device::i386_group0F01_16() // Opcode 0x0f 01
3330 {
3331 uint8_t modrm = FETCH();
3332 uint16_t address;
3333 uint32_t ea;
3334
3335 switch( (modrm >> 3) & 0x7 )
3336 {
3337 case 0: /* SGDT */
3338 {
3339 if( modrm >= 0xc0 ) {
3340 address = LOAD_RM16(modrm);
3341 ea = i386_translate(CS, address, 1 );
3342 } else {
3343 ea = GetEA(modrm,1);
3344 }
3345 WRITE16(ea, m_gdtr.limit);
3346 WRITE32(ea + 2, m_gdtr.base);
3347 CYCLES(CYCLES_SGDT);
3348 break;
3349 }
3350 case 1: /* SIDT */
3351 {
3352 if (modrm >= 0xc0)
3353 {
3354 address = LOAD_RM16(modrm);
3355 ea = i386_translate(CS, address, 1 );
3356 }
3357 else
3358 {
3359 ea = GetEA(modrm,1);
3360 }
3361 WRITE16(ea, m_idtr.limit);
3362 WRITE32(ea + 2, m_idtr.base);
3363 CYCLES(CYCLES_SIDT);
3364 break;
3365 }
3366 case 2: /* LGDT */
3367 {
3368 if(PROTECTED_MODE && m_CPL)
3369 FAULT(FAULT_GP,0)
3370 if( modrm >= 0xc0 ) {
3371 address = LOAD_RM16(modrm);
3372 ea = i386_translate(CS, address, 0 );
3373 } else {
3374 ea = GetEA(modrm,0);
3375 }
3376 m_gdtr.limit = READ16(ea);
3377 m_gdtr.base = READ32(ea + 2) & 0xffffff;
3378 CYCLES(CYCLES_LGDT);
3379 break;
3380 }
3381 case 3: /* LIDT */
3382 {
3383 if(PROTECTED_MODE && m_CPL)
3384 FAULT(FAULT_GP,0)
3385 if( modrm >= 0xc0 ) {
3386 address = LOAD_RM16(modrm);
3387 ea = i386_translate(CS, address, 0 );
3388 } else {
3389 ea = GetEA(modrm,0);
3390 }
3391 m_idtr.limit = READ16(ea);
3392 m_idtr.base = READ32(ea + 2) & 0xffffff;
3393 CYCLES(CYCLES_LIDT);
3394 break;
3395 }
3396 case 4: /* SMSW */
3397 {
3398 if( modrm >= 0xc0 ) {
3399 STORE_RM16(modrm, m_cr[0]);
3400 CYCLES(CYCLES_SMSW_REG);
3401 } else {
3402 ea = GetEA(modrm,1);
3403 WRITE16(ea, m_cr[0]);
3404 CYCLES(CYCLES_SMSW_MEM);
3405 }
3406 break;
3407 }
3408 case 6: /* LMSW */
3409 {
3410 if(PROTECTED_MODE && m_CPL)
3411 FAULT(FAULT_GP,0)
3412 uint16_t b;
3413 if( modrm >= 0xc0 ) {
3414 b = LOAD_RM16(modrm);
3415 CYCLES(CYCLES_LMSW_REG);
3416 } else {
3417 ea = GetEA(modrm,0);
3418 CYCLES(CYCLES_LMSW_MEM);
3419 b = READ16(ea);
3420 }
3421 if(PROTECTED_MODE)
3422 b |= 0x0001; // cannot return to real mode using this instruction.
3423 m_cr[0] &= ~0x0000000f;
3424 m_cr[0] |= b & 0x0000000f;
3425 break;
3426 }
3427 default:
3428 report_invalid_modrm("group0F01_16", modrm);
3429 break;
3430 }
3431 }
3432
i386_group0FBA_16()3433 void i386_device::i386_group0FBA_16() // Opcode 0x0f ba
3434 {
3435 uint8_t modrm = FETCH();
3436
3437 switch( (modrm >> 3) & 0x7 )
3438 {
3439 case 4: /* BT Rm16, i8 */
3440 if( modrm >= 0xc0 ) {
3441 uint16_t dst = LOAD_RM16(modrm);
3442 uint8_t bit = FETCH();
3443
3444 if( dst & (1 << bit) )
3445 m_CF = 1;
3446 else
3447 m_CF = 0;
3448
3449 CYCLES(CYCLES_BT_IMM_REG);
3450 } else {
3451 uint32_t ea = GetEA(modrm,0);
3452 uint16_t dst = READ16(ea);
3453 uint8_t bit = FETCH();
3454
3455 if( dst & (1 << bit) )
3456 m_CF = 1;
3457 else
3458 m_CF = 0;
3459
3460 CYCLES(CYCLES_BT_IMM_MEM);
3461 }
3462 break;
3463 case 5: /* BTS Rm16, i8 */
3464 if( modrm >= 0xc0 ) {
3465 uint16_t dst = LOAD_RM16(modrm);
3466 uint8_t bit = FETCH();
3467
3468 if( dst & (1 << bit) )
3469 m_CF = 1;
3470 else
3471 m_CF = 0;
3472 dst |= (1 << bit);
3473
3474 STORE_RM16(modrm, dst);
3475 CYCLES(CYCLES_BTS_IMM_REG);
3476 } else {
3477 uint32_t ea = GetEA(modrm,1);
3478 uint16_t dst = READ16(ea);
3479 uint8_t bit = FETCH();
3480
3481 if( dst & (1 << bit) )
3482 m_CF = 1;
3483 else
3484 m_CF = 0;
3485 dst |= (1 << bit);
3486
3487 WRITE16(ea, dst);
3488 CYCLES(CYCLES_BTS_IMM_MEM);
3489 }
3490 break;
3491 case 6: /* BTR Rm16, i8 */
3492 if( modrm >= 0xc0 ) {
3493 uint16_t dst = LOAD_RM16(modrm);
3494 uint8_t bit = FETCH();
3495
3496 if( dst & (1 << bit) )
3497 m_CF = 1;
3498 else
3499 m_CF = 0;
3500 dst &= ~(1 << bit);
3501
3502 STORE_RM16(modrm, dst);
3503 CYCLES(CYCLES_BTR_IMM_REG);
3504 } else {
3505 uint32_t ea = GetEA(modrm,1);
3506 uint16_t dst = READ16(ea);
3507 uint8_t bit = FETCH();
3508
3509 if( dst & (1 << bit) )
3510 m_CF = 1;
3511 else
3512 m_CF = 0;
3513 dst &= ~(1 << bit);
3514
3515 WRITE16(ea, dst);
3516 CYCLES(CYCLES_BTR_IMM_MEM);
3517 }
3518 break;
3519 case 7: /* BTC Rm16, i8 */
3520 if( modrm >= 0xc0 ) {
3521 uint16_t dst = LOAD_RM16(modrm);
3522 uint8_t bit = FETCH();
3523
3524 if( dst & (1 << bit) )
3525 m_CF = 1;
3526 else
3527 m_CF = 0;
3528 dst ^= (1 << bit);
3529
3530 STORE_RM16(modrm, dst);
3531 CYCLES(CYCLES_BTC_IMM_REG);
3532 } else {
3533 uint32_t ea = GetEA(modrm,1);
3534 uint16_t dst = READ16(ea);
3535 uint8_t bit = FETCH();
3536
3537 if( dst & (1 << bit) )
3538 m_CF = 1;
3539 else
3540 m_CF = 0;
3541 dst ^= (1 << bit);
3542
3543 WRITE16(ea, dst);
3544 CYCLES(CYCLES_BTC_IMM_MEM);
3545 }
3546 break;
3547 default:
3548 report_invalid_modrm("group0FBA_16", modrm);
3549 break;
3550 }
3551 }
3552
i386_lar_r16_rm16()3553 void i386_device::i386_lar_r16_rm16() // Opcode 0x0f 0x02
3554 {
3555 uint8_t modrm = FETCH();
3556 I386_SREG seg;
3557 uint8_t type;
3558
3559 if(PROTECTED_MODE && !V8086_MODE)
3560 {
3561 memset(&seg,0,sizeof(seg));
3562 if(modrm >= 0xc0)
3563 {
3564 seg.selector = LOAD_RM16(modrm);
3565 CYCLES(CYCLES_LAR_REG);
3566 }
3567 else
3568 {
3569 uint32_t ea = GetEA(modrm,0);
3570 seg.selector = READ16(ea);
3571 CYCLES(CYCLES_LAR_MEM);
3572 }
3573 if(seg.selector == 0)
3574 {
3575 SetZF(0); // not a valid segment
3576 // logerror("i386 (%08x): LAR: Selector %04x is invalid type.\n",m_pc,seg.selector);
3577 }
3578 else
3579 {
3580 if(!i386_load_protected_mode_segment(&seg,nullptr))
3581 {
3582 SetZF(0);
3583 return;
3584 }
3585 uint8_t DPL = (seg.flags >> 5) & 3;
3586 if(((DPL < m_CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c))
3587 {
3588 SetZF(0);
3589 return;
3590 }
3591 if(!(seg.flags & 0x10)) // special segment
3592 {
3593 // check for invalid segment types
3594 type = seg.flags & 0x000f;
3595 if(type == 0x00 || type == 0x08 || type == 0x0a || type == 0x0d)
3596 {
3597 SetZF(0); // invalid segment type
3598 }
3599 else
3600 {
3601 STORE_REG16(modrm,(seg.flags << 8) & 0xff00);
3602 SetZF(1);
3603 }
3604 }
3605 else
3606 { // data or code segment (both are valid for LAR)
3607 STORE_REG16(modrm,(seg.flags << 8) & 0xff00);
3608 SetZF(1);
3609 }
3610 }
3611 }
3612 else
3613 {
3614 // illegal opcode
3615 i386_trap(6,0, 0);
3616 logerror("i386: LAR: Exception - running in real mode or virtual 8086 mode.\n");
3617 }
3618 }
3619
i386_lsl_r16_rm16()3620 void i386_device::i386_lsl_r16_rm16() // Opcode 0x0f 0x03
3621 {
3622 uint8_t modrm = FETCH();
3623 uint32_t limit;
3624 I386_SREG seg;
3625
3626 if(PROTECTED_MODE && !V8086_MODE)
3627 {
3628 memset(&seg, 0, sizeof(seg));
3629 if(modrm >= 0xc0)
3630 {
3631 seg.selector = LOAD_RM16(modrm);
3632 }
3633 else
3634 {
3635 uint32_t ea = GetEA(modrm,0);
3636 seg.selector = READ16(ea);
3637 }
3638 if(seg.selector == 0)
3639 {
3640 SetZF(0); // not a valid segment
3641 }
3642 else
3643 {
3644 uint8_t type;
3645 if(!i386_load_protected_mode_segment(&seg,nullptr))
3646 {
3647 SetZF(0);
3648 return;
3649 }
3650 uint8_t DPL = (seg.flags >> 5) & 3;
3651 if(((DPL < m_CPL) || (DPL < (seg.selector & 3))) && ((seg.flags & 0x1c) != 0x1c))
3652 {
3653 SetZF(0);
3654 return;
3655 }
3656 type = seg.flags & 0x1f;
3657 switch(type)
3658 {
3659 case 0:
3660 case 4:
3661 case 5:
3662 case 6:
3663 case 7:
3664 case 8:
3665 case 10:
3666 case 12:
3667 case 13:
3668 case 14:
3669 case 15:
3670 SetZF(0);
3671 return;
3672 default:
3673 limit = seg.limit;
3674 STORE_REG16(modrm,limit & 0x0000ffff);
3675 SetZF(1);
3676 }
3677 }
3678 }
3679 else
3680 i386_trap(6, 0, 0);
3681 }
3682
i386_bound_r16_m16_m16()3683 void i386_device::i386_bound_r16_m16_m16() // Opcode 0x62
3684 {
3685 uint8_t modrm;
3686 int16_t val, low, high;
3687
3688 modrm = FETCH();
3689
3690 if (modrm >= 0xc0)
3691 {
3692 low = high = LOAD_RM16(modrm);
3693 }
3694 else
3695 {
3696 uint32_t ea = GetEA(modrm,0);
3697 low = READ16(ea + 0);
3698 high = READ16(ea + 2);
3699 }
3700 val = LOAD_REG16(modrm);
3701
3702 if ((val < low) || (val > high))
3703 {
3704 CYCLES(CYCLES_BOUND_OUT_RANGE);
3705 i386_trap(5, 0, 0);
3706 }
3707 else
3708 {
3709 CYCLES(CYCLES_BOUND_IN_RANGE);
3710 }
3711 }
3712
i386_retf16()3713 void i386_device::i386_retf16() // Opcode 0xcb
3714 {
3715 if(PROTECTED_MODE && !V8086_MODE)
3716 {
3717 i386_protected_mode_retf(0,0);
3718 }
3719 else
3720 {
3721 m_eip = POP16();
3722 m_sreg[CS].selector = POP16();
3723 i386_load_segment_descriptor(CS );
3724 CHANGE_PC(m_eip);
3725 }
3726
3727 CYCLES(CYCLES_RET_INTERSEG);
3728 }
3729
i386_retf_i16()3730 void i386_device::i386_retf_i16() // Opcode 0xca
3731 {
3732 uint16_t count = FETCH16();
3733
3734 if(PROTECTED_MODE && !V8086_MODE)
3735 {
3736 i386_protected_mode_retf(count,0);
3737 }
3738 else
3739 {
3740 m_eip = POP16();
3741 m_sreg[CS].selector = POP16();
3742 i386_load_segment_descriptor(CS );
3743 CHANGE_PC(m_eip);
3744 REG16(SP) += count;
3745 }
3746
3747 CYCLES(CYCLES_RET_IMM_INTERSEG);
3748 }
3749
i386_load_far_pointer16(int s)3750 bool i386_device::i386_load_far_pointer16(int s)
3751 {
3752 uint8_t modrm = FETCH();
3753 uint16_t selector;
3754
3755 if( modrm >= 0xc0 ) {
3756 //logerror("i386: load_far_pointer16 NYI\n"); // don't log, NT will use this a lot
3757 i386_trap(6, 0, 0);
3758 return false;
3759 } else {
3760 uint32_t ea = GetEA(modrm,0);
3761 STORE_REG16(modrm, READ16(ea + 0));
3762 selector = READ16(ea + 2);
3763 i386_sreg_load(selector,s,nullptr);
3764 }
3765 return true;
3766 }
3767
i386_lds16()3768 void i386_device::i386_lds16() // Opcode 0xc5
3769 {
3770 if(i386_load_far_pointer16(DS))
3771 CYCLES(CYCLES_LDS);
3772 }
3773
i386_lss16()3774 void i386_device::i386_lss16() // Opcode 0x0f 0xb2
3775 {
3776 if(i386_load_far_pointer16(SS))
3777 CYCLES(CYCLES_LSS);
3778 }
3779
i386_les16()3780 void i386_device::i386_les16() // Opcode 0xc4
3781 {
3782 if(i386_load_far_pointer16(ES))
3783 CYCLES(CYCLES_LES);
3784 }
3785
i386_lfs16()3786 void i386_device::i386_lfs16() // Opcode 0x0f 0xb4
3787 {
3788 if(i386_load_far_pointer16(FS))
3789 CYCLES(CYCLES_LFS);
3790 }
3791
i386_lgs16()3792 void i386_device::i386_lgs16() // Opcode 0x0f 0xb5
3793 {
3794 if(i386_load_far_pointer16(GS))
3795 CYCLES(CYCLES_LGS);
3796 }
3797