1 #include "disasm-glue.h"
2
3 /* for debug output only */
4 #ifdef CPU_i386
5 #define REG_RIP_NAME "eip"
6 #endif
7 #ifdef CPU_x86_64
8 #define REG_RIP_NAME "rip"
9 #endif
10
11 enum transfer_type_t {
12 TYPE_UNKNOWN,
13 TYPE_LOAD,
14 TYPE_STORE
15 };
16
17 #ifdef USE_JIT
18 extern void compiler_status();
19 # ifdef JIT_DEBUG
20 extern void compiler_dumpstate();
21 # endif
22 #endif
23
24 int in_handler = 0;
25 // #define HW_SIGSEGV_STATISTICS 1
26 #ifdef HW_SIGSEGV_STATISTICS
27 static unsigned long x86_opcodes[256];
28 #endif
29
30 enum instruction_t {
31 INSTR_UNKNOWN,
32 INSTR_MOVZX8,
33 INSTR_MOVZX16,
34 INSTR_MOVSX8,
35 INSTR_MOVSX16,
36 #ifdef CPU_x86_64
37 INSTR_MOVSX32,
38 #endif
39 INSTR_MOV8,
40 INSTR_MOV32,
41 INSTR_MOVIMM8,
42 INSTR_MOVIMM32,
43 INSTR_ORMEM,
44 INSTR_ADDIMM8,
45 INSTR_ORIMM8,
46 INSTR_ANDIMM8,
47 INSTR_SUBIMM8,
48 INSTR_XORIMM8,
49 INSTR_CMPIMM8,
50 INSTR_ADDIMM32,
51 INSTR_ORIMM32,
52 INSTR_ANDIMM32,
53 INSTR_SUBIMM32,
54 INSTR_XORIMM32,
55 INSTR_CMPIMM32,
56 INSTR_ADDLIMM8,
57 INSTR_ORLIMM8,
58 INSTR_ANDLIMM8,
59 INSTR_SUBLIMM8,
60 INSTR_XORLIMM8,
61 INSTR_CMPLIMM8,
62 INSTR_ANDMEM,
63 INSTR_ADDMEM,
64 INSTR_SUBMEM,
65 INSTR_CMPMEM,
66 INSTR_DIV8,
67 INSTR_IDIV8,
68 INSTR_MUL8,
69 INSTR_IMUL8,
70 INSTR_NEGMEM,
71 INSTR_NOTMEM,
72 INSTR_TESTIMM8,
73 INSTR_XORMEM
74 };
75
76
get_instr_size_add(const uint8 * p)77 static inline int get_instr_size_add(const uint8 *p)
78 {
79 int mod = (p[0] & 0xC0);
80 int rm = p[0] & 7;
81 int offset = 0;
82
83 // ModR/M Byte
84 switch (mod) {
85 case 0: // [reg]
86 if (rm == 5) return 4; // disp32
87 break;
88 case 0x40: // disp8[reg]
89 offset = 1;
90 break;
91 case 0x80: // disp32[reg]
92 offset = 4;
93 break;
94 case 0xc0: // register
95 return 0;
96 }
97
98 // SIB Byte
99 if (rm == 4) {
100 if (mod == 0 && (p[1] & 7) == 5)
101 offset = 5; // disp32[index]
102 else
103 offset++;
104 }
105
106 return offset;
107 }
108
109 /* MJ - AF and OF not tested, also CF for 32 bit */
set_byte_eflags(int i,CONTEXT_ATYPE CONTEXT_NAME)110 static inline void set_byte_eflags(int i, CONTEXT_ATYPE CONTEXT_NAME) {
111 if ((i > 255) || (i < 0)) CONTEXT_AEFLAGS |= 0x1; // CF
112 else CONTEXT_AEFLAGS &= ~0x1;
113
114 if (i > 127) CONTEXT_AEFLAGS |= 0x80; // SF
115 else CONTEXT_AEFLAGS &= ~0x80;
116
117 if ((i % 2) == 0) CONTEXT_AEFLAGS |= 0x4; // PF
118 else CONTEXT_AEFLAGS &= ~0x4;
119
120 if (i == 0) CONTEXT_AEFLAGS |= 0x40; // ZF
121 else CONTEXT_AEFLAGS &= ~0x40;
122 }
123
124 /* MJ - AF and OF not tested, also CF for 32 bit */
set_word_eflags(int i,CONTEXT_ATYPE CONTEXT_NAME)125 static inline void set_word_eflags(int i, CONTEXT_ATYPE CONTEXT_NAME) {
126 if ((i > 65535) || (i < 0)) CONTEXT_AEFLAGS |= 0x1; // CF
127 else CONTEXT_AEFLAGS &= ~0x1;
128
129 if (i > 32767) CONTEXT_AEFLAGS |= 0x80; // SF
130 else CONTEXT_AEFLAGS &= ~0x80;
131
132 if ((i % 2) == 0) CONTEXT_AEFLAGS |= 0x4; // PF
133 else CONTEXT_AEFLAGS &= ~0x4;
134
135 if (i == 0) CONTEXT_AEFLAGS |= 0x40; // ZF
136 else CONTEXT_AEFLAGS &= ~0x40;
137 }
138
139 /* MJ - AF and OF not tested, also CF for 32 bit */
set_long_eflags(int i,CONTEXT_ATYPE CONTEXT_NAME)140 static inline void set_long_eflags(int i, CONTEXT_ATYPE CONTEXT_NAME) {
141 if (i > 2147483647) CONTEXT_AEFLAGS |= 0x80; // SF
142 else CONTEXT_AEFLAGS &= ~0x80;
143
144 if ((i % 2) == 0) CONTEXT_AEFLAGS |= 0x4; // PF
145 else CONTEXT_AEFLAGS &= ~0x4;
146
147 if (i == 0) CONTEXT_AEFLAGS |= 0x40; // ZF
148 else CONTEXT_AEFLAGS &= ~0x40;
149 }
150
151 static
152 #if DEBUG
153 __attribute_noinline__
154 #else
155 inline
156 #endif
unknown_instruction()157 void unknown_instruction() {
158 #ifdef USE_JIT
159 compiler_status();
160 # ifdef JIT_DEBUG
161 compiler_dumpstate();
162 # endif
163 #endif
164 abort();
165 }
166
167 /**
168 Opcode register id list:
169
170 8 Bit
171 0: AL
172 1: CL
173 2: DL
174 3: BL
175 4: AH (SPL, if REX)
176 5: CH (BPL, if REX)
177 6: DH (SIL, if REX)
178 7: BH (DIL, if REX)
179 8: R8L
180 9: R9L
181 10: R10L
182 11: R11L
183 12: R12L
184 13: R13L
185 14: R14L
186 15: R15L
187
188 16 Bit:
189 0: AX
190 1: CX
191 2: DX
192 3: BX
193 4: SP
194 5: BP
195 6: SI
196 7: DI
197 8: R8W
198 9: R9W
199 10: R10W
200 11: R11W
201 12: R12W
202 13: R13W
203 14: R14W
204 15: R15W
205
206 32 Bit:
207 0: EAX
208 1: ECX
209 2: EDX
210 3: EBX
211 4: ESP
212 5: EBP
213 6: ESI
214 7: EDI
215 8: R8D
216 9: R9D
217 10: R10D
218 11: R11D
219 12: R12D
220 13: R13D
221 14: R14D
222 15: R15D
223
224 **/
225
226 #ifdef NO_NESTED_SIGSEGV
handle_access_fault2(CONTEXT_ATYPE CONTEXT_NAME,memptr faultaddr)227 static __attribute_noinline__ void handle_access_fault2(CONTEXT_ATYPE CONTEXT_NAME, memptr faultaddr)
228 #else
229 static __attribute_noinline__ void handle_access_fault(CONTEXT_ATYPE CONTEXT_NAME, memptr faultaddr)
230 #endif
231 {
232 memptr addr = faultaddr;
233 const uint8 *ainstr = (const uint8 *)CONTEXT_AEIP;
234 const uint8 *addr_instr = ainstr;
235 int reg = -1;
236 int len = 0;
237 transfer_type_t transfer_type = TYPE_UNKNOWN;
238 int size = 4;
239 uae_u32 imm = 0;
240 int pom1, pom2;
241 instruction_t instruction = INSTR_UNKNOWN;
242 volatile void *preg;
243
244 static const int x86_reg_map[] = {
245 REG_RAX, REG_RCX, REG_RDX, REG_RBX,
246 REG_RSP, REG_RBP, REG_RSI, REG_RDI,
247 #ifdef CPU_x86_64
248 REG_R8, REG_R9, REG_R10, REG_R11,
249 REG_R12, REG_R13, REG_R14, REG_R15,
250 #endif
251 };
252
253 if (in_handler > 0) {
254 panicbug("Segmentation fault in handler :-(, faultaddr=0x%08x", faultaddr);
255 abort();
256 }
257 in_handler += 1;
258
259 #ifdef USE_JIT /* does not compile with default configure */
260 D(compiler_status());
261 #endif
262 D(bug("[%08x] BUS ERROR fault address is %08x", m68k_getpc(), addr));
263
264 #ifdef HW_SIGSEGV
265
266 /* segment override not handled */
267 #if DEBUG
268 if (addr_instr[0] == 0x2e ||
269 addr_instr[0] == 0x3e ||
270 addr_instr[0] == 0x26 ||
271 addr_instr[0] == 0x64 ||
272 addr_instr[0] == 0x65 ||
273 addr_instr[0] == 0x36)
274 {
275 D(panicbug("segment override prefix"));
276 addr_instr++;
277 len++;
278 }
279 #endif
280
281 if (addr_instr[0] == 0x67) { // address size override prefix
282 #ifdef CPU_i386
283 D(panicbug("address size override prefix in 32bit-mode"));
284 #endif
285 addr_instr++; // Skip prefix, seems to be enough
286 len++;
287 }
288
289 if (addr_instr[0] == 0x66) { // operand size override prefix
290 addr_instr++;
291 len++;
292 size = 2;
293 D(bug("Word instr:"));
294 }
295
296 if (addr_instr[0] == 0xf0) { // lock prefix
297 addr_instr++;
298 len++;
299 D(bug("Lock:"));
300 }
301
302 /* Repeat prefix not handled */
303 if (addr_instr[0] == 0xf3 ||
304 addr_instr[0] == 0xf2)
305 {
306 panicbug("repeat prefix");
307 addr_instr++;
308 len++;
309 }
310
311 #ifdef CPU_x86_64
312 // REX prefix
313 struct rex_t {
314 unsigned char W;
315 unsigned char R;
316 unsigned char X;
317 unsigned char B;
318 };
319 rex_t rex = { 0, 0, 0, 0 };
320 bool has_rex = false;
321 if ((*addr_instr & 0xf0) == 0x40) {
322 has_rex = true;
323 const unsigned char b = *addr_instr;
324 rex.W = b & (1 << 3);
325 rex.R = b & (1 << 2);
326 rex.X = b & (1 << 1);
327 rex.B = b & (1 << 0);
328 addr_instr++;
329 len++;
330 if (rex.W)
331 size = 8;
332 }
333 #endif
334
335 #ifdef HW_SIGSEGV_STATISTICS
336 x86_opcodes[addr_instr[0]]++;
337 #endif
338
339 switch (addr_instr[0]) {
340 case 0x00:
341 D(bug("ADD m8, r8"));
342 size = 1;
343 transfer_type = TYPE_STORE;
344 instruction = INSTR_ADDMEM;
345 reg = (addr_instr[1] >> 3) & 7;
346 len += 2 + get_instr_size_add(addr_instr + 1);
347 break;
348 case 0x01:
349 if (size == 8)
350 {
351 D(bug("ADD m64, r64"));
352 } else if (size == 2)
353 {
354 D(bug("ADD m16, r16"));
355 } else /* if (size == 4) */
356 {
357 D(bug("ADD m32, r32"));
358 }
359 instruction = INSTR_ADDMEM;
360 transfer_type = TYPE_STORE;
361 reg = (addr_instr[1] >> 3) & 7;
362 len += 2 + get_instr_size_add(addr_instr + 1);
363 break;
364 case 0x02:
365 D(bug("ADD r8, m8"));
366 size = 1;
367 transfer_type = TYPE_LOAD;
368 instruction = INSTR_ADDMEM;
369 reg = (addr_instr[1] >> 3) & 7;
370 len += 2 + get_instr_size_add(addr_instr + 1);
371 break;
372 case 0x03:
373 if (size == 8)
374 {
375 D(bug("ADD r64, m64"));
376 } else if (size == 2)
377 {
378 D(bug("ADD r16, m16"));
379 } else if (size == 4)
380 {
381 D(bug("ADD r32, m32"));
382 }
383 instruction = INSTR_ADDMEM;
384 transfer_type = TYPE_LOAD;
385 reg = (addr_instr[1] >> 3) & 7;
386 len += 2 + get_instr_size_add(addr_instr + 1);
387 break;
388 case 0x28:
389 D(bug("SUB m8, r8"));
390 size = 1;
391 transfer_type = TYPE_STORE;
392 instruction = INSTR_SUBMEM;
393 reg = (addr_instr[1] >> 3) & 7;
394 len += 2 + get_instr_size_add(addr_instr + 1);
395 break;
396 case 0x29:
397 if (size == 8)
398 {
399 D(bug("SUB m64, r64"));
400 } else if (size == 2)
401 {
402 D(bug("SUB m16, r16"));
403 } else /* if (size == 4) */
404 {
405 D(bug("SUB m32, r32"));
406 }
407 instruction = INSTR_SUBMEM;
408 transfer_type = TYPE_STORE;
409 reg = (addr_instr[1] >> 3) & 7;
410 len += 2 + get_instr_size_add(addr_instr + 1);
411 break;
412 case 0x2A:
413 D(bug("SUB r8, m8"));
414 size = 1;
415 transfer_type = TYPE_LOAD;
416 instruction = INSTR_SUBMEM;
417 reg = (addr_instr[1] >> 3) & 7;
418 len += 2 + get_instr_size_add(addr_instr + 1);
419 break;
420 case 0x2b:
421 if (size == 8)
422 {
423 D(bug("SUB r64, m64"));
424 } else if (size == 2)
425 {
426 D(bug("SUB r16, m16"));
427 } else if (size == 4)
428 {
429 D(bug("SUB r32, m32"));
430 }
431 instruction = INSTR_SUBMEM;
432 transfer_type = TYPE_LOAD;
433 reg = (addr_instr[1] >> 3) & 7;
434 len += 2 + get_instr_size_add(addr_instr + 1);
435 break;
436 case 0x08:
437 D(bug("OR m8, r8"));
438 size = 1;
439 transfer_type = TYPE_STORE;
440 instruction = INSTR_ORMEM;
441 reg = (addr_instr[1] >> 3) & 7;
442 len += 2 + get_instr_size_add(addr_instr + 1);
443 break;
444 case 0x09:
445 if (size == 8)
446 {
447 D(bug("OR m64, r64"));
448 } else if (size == 2)
449 {
450 D(bug("OR m16, r16"));
451 } else /* if (size == 4) */
452 {
453 D(bug("OR m32, r32"));
454 }
455 instruction = INSTR_ORMEM;
456 transfer_type = TYPE_STORE;
457 reg = (addr_instr[1] >> 3) & 7;
458 len += 2 + get_instr_size_add(addr_instr + 1);
459 break;
460 case 0x0a:
461 D(bug("OR r8, m8"));
462 size = 1;
463 transfer_type = TYPE_LOAD;
464 instruction = INSTR_ORMEM;
465 reg = (addr_instr[1] >> 3) & 7;
466 len += 2 + get_instr_size_add(addr_instr + 1);
467 break;
468 case 0x0b:
469 if (size == 8)
470 {
471 D(bug("OR r64, m64"));
472 } else if (size == 2)
473 {
474 D(bug("OR r16, m16"));
475 } else if (size == 4)
476 {
477 D(bug("OR r32, m32"));
478 }
479 instruction = INSTR_ORMEM;
480 transfer_type = TYPE_LOAD;
481 reg = (addr_instr[1] >> 3) & 7;
482 len += 2 + get_instr_size_add(addr_instr + 1);
483 break;
484 case 0x0f:
485 switch (addr_instr[1])
486 {
487 case 0xb6:
488 D(bug("MOVZX r32, m8"));
489 transfer_type = TYPE_LOAD;
490 instruction = INSTR_MOVZX8;
491 reg = (addr_instr[2] >> 3 ) & 7;
492 len += 3 + get_instr_size_add(addr_instr + 2);
493 break;
494 case 0xb7:
495 D(bug("MOVZX r32, m16"));
496 size = 2;
497 transfer_type = TYPE_LOAD;
498 instruction = INSTR_MOVZX16;
499 reg = (addr_instr[2] >> 3 ) & 7;
500 len += 3 + get_instr_size_add(addr_instr + 2);
501 break;
502 case 0xbe:
503 D(bug("MOVSX r32, m8"));
504 transfer_type = TYPE_LOAD;
505 instruction = INSTR_MOVSX8;
506 reg = (addr_instr[2] >> 3 ) & 7;
507 len += 3 + get_instr_size_add(addr_instr + 2);
508 break;
509 case 0xbf:
510 D(bug("MOVSX r32, m16"));
511 transfer_type = TYPE_LOAD;
512 instruction = INSTR_MOVSX16;
513 reg = (addr_instr[2] >> 3 ) & 7;
514 len += 3 + get_instr_size_add(addr_instr + 2);
515 break;
516 #ifdef CPU_x86_64
517 case 0x63:
518 D(bug("MOVSX r64, m32"));
519 transfer_type = TYPE_LOAD;
520 instruction = INSTR_MOVSX32;
521 reg = (addr_instr[2] >> 3 ) & 7;
522 len += 3 + get_instr_size_add(addr_instr + 2);
523 break;
524 #endif
525 default:
526 instruction = INSTR_UNKNOWN;
527 panicbug("MOVSX - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
528 unknown_instruction();
529 break;
530 }
531 break;
532 case 0x20:
533 D(bug("AND m8, r8"));
534 size = 1;
535 transfer_type = TYPE_STORE;
536 instruction = INSTR_ANDMEM;
537 reg = (addr_instr[1] >> 3) & 7;
538 len += 2 + get_instr_size_add(addr_instr + 1);
539 break;
540 case 0x21:
541 if (size == 8)
542 {
543 D(bug("AND m64, r64"));
544 } else if (size == 2)
545 {
546 D(bug("AND m16, r16"));
547 } else /* if (size == 4) */
548 {
549 D(bug("AND m32, r32"));
550 }
551 instruction = INSTR_ANDMEM;
552 transfer_type = TYPE_STORE;
553 reg = (addr_instr[1] >> 3) & 7;
554 len += 2 + get_instr_size_add(addr_instr + 1);
555 break;
556 case 0x22:
557 D(bug("AND r8, m8"));
558 size = 1;
559 transfer_type = TYPE_LOAD;
560 instruction = INSTR_ANDMEM;
561 reg = (addr_instr[1] >> 3) & 7;
562 len += 2 + get_instr_size_add(addr_instr + 1);
563 break;
564 case 0x23:
565 if (size == 8)
566 {
567 D(bug("AND r64, m64"));
568 } else if (size == 2)
569 {
570 D(bug("AND r16, m16"));
571 } else /* if (size == 4) */
572 {
573 D(bug("AND r32, m32"));
574 }
575 instruction = INSTR_ANDMEM;
576 transfer_type = TYPE_STORE;
577 reg = (addr_instr[1] >> 3) & 7;
578 len += 2 + get_instr_size_add(addr_instr + 1);
579 break;
580 case 0x30:
581 D(bug("XOR m8, r8"));
582 size = 1;
583 transfer_type = TYPE_STORE;
584 instruction = INSTR_XORMEM;
585 reg = (addr_instr[1] >> 3) & 7;
586 len += 2 + get_instr_size_add(addr_instr + 1);
587 break;
588 case 0x31:
589 if (size == 8)
590 {
591 D(bug("XOR m64, r64"));
592 } else if (size == 2)
593 {
594 D(bug("XOR m16, r16"));
595 } else /* if (size == 4) */
596 {
597 D(bug("XOR m32, r32"));
598 }
599 instruction = INSTR_XORMEM;
600 transfer_type = TYPE_STORE;
601 reg = (addr_instr[1] >> 3) & 7;
602 len += 2 + get_instr_size_add(addr_instr + 1);
603 break;
604 case 0x32:
605 D(bug("XOR r8,m8"));
606 size = 1;
607 transfer_type = TYPE_LOAD;
608 instruction = INSTR_XORMEM;
609 reg = (addr_instr[1] >> 3) & 7;
610 len += 2 + get_instr_size_add(addr_instr + 1);
611 break;
612 case 0x33:
613 if (size == 8)
614 {
615 D(bug("XOR r64, m64"));
616 } else if (size == 2)
617 {
618 D(bug("XOR r16, m16"));
619 } else /* if (size == 4) */
620 {
621 D(bug("XOR r32, m32"));
622 }
623 instruction = INSTR_XORMEM;
624 transfer_type = TYPE_LOAD;
625 reg = (addr_instr[1] >> 3) & 7;
626 len += 2 + get_instr_size_add(addr_instr + 1);
627 break;
628 case 0x38:
629 D(bug("CMP m8, r8"));
630 size = 1;
631 transfer_type = TYPE_STORE;
632 instruction = INSTR_CMPMEM;
633 reg = (addr_instr[1] >> 3) & 7;
634 len += 2 + get_instr_size_add(addr_instr + 1);
635 break;
636 case 0x39:
637 if (size == 8)
638 {
639 D(bug("CMP m64, r64"));
640 } else if (size == 2)
641 {
642 D(bug("CMP m16, r16"));
643 } else /* if (size == 4) */
644 {
645 D(bug("CMP m32, r32"));
646 }
647 transfer_type = TYPE_STORE;
648 instruction = INSTR_CMPMEM;
649 reg = (addr_instr[1] >> 3) & 7;
650 len += 2 + get_instr_size_add(addr_instr + 1);
651 break;
652 case 0x3a:
653 D(bug("CMP r8, m8"));
654 size = 1;
655 transfer_type = TYPE_LOAD;
656 instruction = INSTR_CMPMEM;
657 reg = (addr_instr[1] >> 3) & 7;
658 len += 2 + get_instr_size_add(addr_instr + 1);
659 break;
660 case 0x3b:
661 if (size == 8)
662 {
663 D(bug("CMP r64, m64"));
664 } else if (size == 2)
665 {
666 D(bug("CMP r16, m16"));
667 } else /* if (size == 4) */
668 {
669 D(bug("CMP r32, m32"));
670 }
671 transfer_type = TYPE_LOAD;
672 instruction = INSTR_CMPMEM;
673 reg = (addr_instr[1] >> 3) & 7;
674 len += 2 + get_instr_size_add(addr_instr + 1);
675 break;
676 case 0x80:
677 size = 1;
678 transfer_type = TYPE_STORE;
679 switch ((addr_instr[1] >> 3) & 7)
680 {
681 case 0:
682 D(bug("ADD m8, imm8"));
683 instruction = INSTR_ADDIMM8;
684 break;
685 case 1:
686 D(bug("OR m8, imm8"));
687 instruction = INSTR_ORIMM8;
688 break;
689 case 4:
690 D(bug("AND m8, imm8"));
691 instruction = INSTR_ANDIMM8;
692 break;
693 case 5:
694 D(bug("SUB m8, imm8"));
695 instruction = INSTR_SUBIMM8;
696 break;
697 case 6:
698 D(bug("XOR m8, imm8"));
699 instruction = INSTR_XORIMM8;
700 break;
701 case 7:
702 D(bug("CMP m8, imm8"));
703 instruction = INSTR_CMPIMM8;
704 break;
705
706 case 2: /* ADC */
707 case 3: /* SBB */
708 default:
709 instruction = INSTR_UNKNOWN;
710 panicbug("ADD m8, imm8 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
711 unknown_instruction();
712 break;
713 }
714 len += 2 + get_instr_size_add(addr_instr + 1);
715 imm = *((uae_u8 *)(ainstr + len));
716 len++;
717 break;
718 case 0x81:
719 transfer_type = TYPE_STORE;
720 switch ((addr_instr[1] >> 3) & 7)
721 {
722 case 0:
723 D(bug("ADD m32, imm32"));
724 instruction = INSTR_ADDIMM32;
725 break;
726 case 1:
727 D(bug("OR m32, imm32"));
728 instruction = INSTR_ORIMM32;
729 break;
730 case 4:
731 D(bug("AND m32, imm32"));
732 instruction = INSTR_ANDIMM32;
733 break;
734 case 5:
735 D(bug("SUB m32, imm32"));
736 instruction = INSTR_SUBIMM32;
737 break;
738 case 6:
739 D(bug("XOR m32, imm32"));
740 instruction = INSTR_XORIMM32;
741 break;
742 case 7:
743 D(bug("CMP m32, imm32"));
744 instruction = INSTR_CMPIMM32;
745 break;
746
747 case 2: /* ADC */
748 case 3: /* SBB */
749 default:
750 instruction = INSTR_UNKNOWN;
751 panicbug("ADD m32, imm32 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
752 unknown_instruction();
753 break;
754 }
755 len += 2 + get_instr_size_add(addr_instr + 1);
756 if (size == 2)
757 {
758 imm = *((uae_u16 *)(ainstr + len));
759 len += 2;
760 } else
761 {
762 imm = *((uae_u32 *)(ainstr + len));
763 len += 4;
764 }
765 break;
766 case 0x83:
767 transfer_type = TYPE_STORE;
768 switch ((addr_instr[1] >> 3) & 7)
769 {
770 case 0:
771 D(bug("ADDL m32, imm8"));
772 instruction = INSTR_ADDLIMM8;
773 break;
774 case 1:
775 D(bug("ORL m32, imm8"));
776 instruction = INSTR_ORLIMM8;
777 break;
778 case 4:
779 D(bug("ANDL m32, imm8"));
780 instruction = INSTR_ANDLIMM8;
781 break;
782 case 5:
783 D(bug("SUBL m32, imm8"));
784 instruction = INSTR_SUBLIMM8;
785 break;
786 case 6:
787 D(bug("XORL m32, imm8"));
788 instruction = INSTR_XORLIMM8;
789 break;
790 case 7:
791 D(bug("CMPL m32, imm8"));
792 instruction = INSTR_CMPLIMM8;
793 break;
794
795 case 2: /* ADC */
796 case 3: /* SBB */
797 default:
798 instruction = INSTR_UNKNOWN;
799 panicbug("ADD m8, imm8 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
800 unknown_instruction();
801 break;
802 }
803 len += 2 + get_instr_size_add(addr_instr + 1);
804 imm = *((uae_s8 *)(ainstr + len));
805 len++;
806 break;
807 case 0x88:
808 D(bug("MOV m8, r8"));
809 size = 1;
810 transfer_type = TYPE_STORE;
811 instruction = INSTR_MOV8;
812 reg = (addr_instr[1] >> 3) & 7;
813 len += 2 + get_instr_size_add(addr_instr + 1);
814 break;
815 case 0x89:
816 D(bug("MOV m32, r32"));
817 transfer_type = TYPE_STORE;
818 instruction = INSTR_MOV32;
819 reg = (addr_instr[1] >> 3) & 7;
820 len += 2 + get_instr_size_add(addr_instr + 1);
821 break;
822 case 0x8a:
823 D(bug("MOV r8, m8"));
824 size = 1;
825 transfer_type = TYPE_LOAD;
826 instruction = INSTR_MOV8;
827 reg = (addr_instr[1] >> 3) & 7;
828 len += 2 + get_instr_size_add(addr_instr + 1);
829 break;
830 case 0x8b:
831 D(bug("MOV r32, m32"));
832 transfer_type = TYPE_LOAD;
833 instruction = INSTR_MOV32;
834 reg = (addr_instr[1] >> 3) & 7;
835 len += 2 + get_instr_size_add(addr_instr + 1);
836 break;
837 case 0xc6:
838 D(bug("MOV m8, imm8"));
839 size = 1;
840 transfer_type = TYPE_STORE;
841 instruction = INSTR_MOVIMM8;
842 reg = (addr_instr[1] >> 3) & 7;
843 len += 2 + get_instr_size_add(addr_instr + 1);
844 imm = *((uae_u8 *)(ainstr + len));
845 len++;
846 break;
847 case 0xc7:
848 D(bug("MOV m32, imm32"));
849 transfer_type = TYPE_STORE;
850 instruction = INSTR_MOVIMM32;
851 reg = (addr_instr[1] >> 3) & 7;
852 len += 2 + get_instr_size_add(addr_instr + 1);
853 if (size == 2)
854 {
855 imm = *((uae_u16 *)(ainstr + len));
856 len += 2;
857 } else
858 {
859 imm = *((uae_u32 *)(ainstr + len));
860 len += 4;
861 }
862 break;
863 case 0xf6:
864 size = 1;
865 /* fall through */
866 case 0xf7:
867 len += 2 + get_instr_size_add(addr_instr + 1);
868 switch ((addr_instr[1] >> 3) & 7)
869 {
870 case 0:
871 D(bug("TEST m8, imm8"));
872 transfer_type = TYPE_STORE;
873 instruction = INSTR_TESTIMM8;
874 imm = *((uae_u8 *)(ainstr + len));
875 len++;
876 break;
877 case 2:
878 D(bug("NOT m8"));
879 transfer_type = TYPE_STORE;
880 instruction = INSTR_NOTMEM;
881 break;
882 case 3:
883 D(bug("NEG m8"));
884 transfer_type = TYPE_STORE;
885 instruction = INSTR_NEGMEM;
886 break;
887 case 4:
888 D(bug("MUL m8"));
889 transfer_type = TYPE_LOAD;
890 instruction = INSTR_MUL8;
891 reg = 0; /* always EAX */
892 break;
893 case 5:
894 D(bug("IMUL m8"));
895 transfer_type = TYPE_LOAD;
896 instruction = INSTR_IMUL8;
897 reg = 0; /* always EAX */
898 break;
899 case 6:
900 D(bug("DIV m8"));
901 transfer_type = TYPE_LOAD;
902 instruction = INSTR_DIV8;
903 reg = 0; /* always EAX */
904 break;
905 case 7:
906 D(bug("IDIV m8"));
907 transfer_type = TYPE_LOAD;
908 instruction = INSTR_IDIV8;
909 reg = 0; /* always EAX */
910 break;
911 default:
912 instruction = INSTR_UNKNOWN;
913 panicbug("TEST m8, imm8 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
914 unknown_instruction();
915 break;
916 }
917 break;
918 default:
919 instruction = INSTR_UNKNOWN;
920 panicbug("unsupported instruction: i[0-6]=%02x %02x %02x %02x %02x %02x %02x", addr_instr[0], addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
921 unknown_instruction();
922 break;
923 }
924
925 #if DEBUG
926 {
927 const uint8 *a = ainstr;
928 int i;
929 char scratch[1024];
930
931 strcpy(scratch, "instruction is");
932 for (i = 0; i < len && i < 7; i++)
933 sprintf(scratch + strlen(scratch), " %02x", a[i]);
934 if (i > 7)
935 strcat(scratch, "...");
936 sprintf(scratch + strlen(scratch), ", len %d", len);
937 D(bug("%s", scratch));
938 }
939 #ifdef HAVE_DISASM_X86
940 {
941 char buf[256];
942
943 x86_disasm(ainstr, buf, 1);
944 bug("%s", buf);
945 }
946 #endif
947 #endif
948
949 if (addr >= 0xff000000)
950 addr &= 0x00ffffff;
951
952 if ((addr < 0x00f00000) || (addr > 0x00ffffff))
953 goto buserr;
954
955 #ifdef CPU_x86_64
956 if (rex.R) {
957 reg += 8;
958 D2(bug("Extended register %d", reg));
959 }
960 #endif
961
962 if (reg >= 0)
963 {
964 // Get register pointer
965 if (size == 1) {
966 if (
967 #ifdef CPU_x86_64
968 has_rex ||
969 #endif
970 reg < 4)
971 {
972 preg = &(CONTEXT_REGS[x86_reg_map[reg]]);
973 } else {
974 preg = (uae_u8*)(&(CONTEXT_REGS[x86_reg_map[reg - 4]])) + 1; // AH, BH, CH, DH
975 }
976 } else {
977 preg = &(CONTEXT_REGS[x86_reg_map[reg]]);
978 }
979 } else
980 {
981 preg = NULL;
982 }
983
984 D2(bug("Register %d, place %08x, address %08x", reg, (unsigned int)((const char *)preg - (const char *)CONTEXT_REGS), addr));
985
986 if (transfer_type == TYPE_LOAD) {
987 D(bug("LOAD instruction %X", instruction));
988 switch (instruction) {
989 case INSTR_MOVZX16:
990 #ifdef CPU_x86_64
991 if (rex.W)
992 *((uae_u64 *)preg) = (uae_u16)SDL_SwapBE16(HWget_w(addr));
993 else
994 #endif
995 *((uae_u32 *)preg) = (uae_u16)SDL_SwapBE16(HWget_w(addr));
996 break;
997 case INSTR_MOV8:
998 *((uae_u8 *)preg) = HWget_b(addr);
999 break;
1000 case INSTR_MOV32:
1001 #ifdef CPU_x86_64
1002 if (size == 8)
1003 {
1004 /* TODO: needs HWget_q */
1005 panicbug("MOV r64, m32 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1006 unknown_instruction();
1007 } else
1008 #endif
1009 if (size == 4)
1010 *((uae_u32 *)preg) = SDL_SwapBE32(HWget_l(addr));
1011 else
1012 *((uae_u16 *)preg) = SDL_SwapBE16(HWget_w(addr));
1013 break;
1014 case INSTR_ORMEM:
1015 #ifdef CPU_x86_64
1016 if (size == 8)
1017 {
1018 /* TODO: needs HWget_q */
1019 panicbug("OR r64, m64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1020 unknown_instruction();
1021 } else
1022 #endif
1023 if (size == 1)
1024 {
1025 *((uae_u8 *)preg) |= HWget_b(addr);
1026 set_byte_eflags(*((uae_u8 *)preg), CONTEXT_NAME);
1027 } else if (size == 2)
1028 {
1029 *((uae_u16 *)preg) |= SDL_SwapBE16(HWget_w(addr));
1030 set_word_eflags(*((uae_u16 *)preg), CONTEXT_NAME);
1031 } else /* if (size == 4) */
1032 {
1033 *((uae_u32 *)preg) |= SDL_SwapBE32(HWget_l(addr));
1034 set_long_eflags(*((uae_u32 *)preg), CONTEXT_NAME);
1035 }
1036 break;
1037 case INSTR_ANDMEM:
1038 #ifdef CPU_x86_64
1039 if (size == 8)
1040 {
1041 /* TODO: needs HWget_q */
1042 panicbug("AND r64, m64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1043 unknown_instruction();
1044 } else
1045 #endif
1046 if (size == 1)
1047 {
1048 *((uae_u8 *)preg) &= HWget_b(addr);
1049 set_byte_eflags(*((uae_u8 *)preg), CONTEXT_NAME);
1050 } else if (size == 2)
1051 {
1052 *((uae_u16 *)preg) &= SDL_SwapBE16(HWget_w(addr));
1053 set_word_eflags(*((uae_u16 *)preg), CONTEXT_NAME);
1054 } else /* if (size == 4) */
1055 {
1056 *((uae_u32 *)preg) &= SDL_SwapBE32(HWget_l(addr));
1057 set_long_eflags(*((uae_u32 *)preg), CONTEXT_NAME);
1058 }
1059 break;
1060 case INSTR_XORMEM:
1061 #ifdef CPU_x86_64
1062 if (size == 8)
1063 {
1064 /* TODO: needs HWget_q */
1065 panicbug("XOR r64, m64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1066 unknown_instruction();
1067 } else
1068 #endif
1069 if (size == 1)
1070 {
1071 *((uae_u8 *)preg) ^= HWget_b(addr);
1072 set_byte_eflags(*((uae_u8 *)preg), CONTEXT_NAME);
1073 } else if (size == 2)
1074 {
1075 *((uae_u16 *)preg) ^= SDL_SwapBE16(HWget_w(addr));
1076 set_word_eflags(*((uae_u16 *)preg), CONTEXT_NAME);
1077 } else /* if (size == 4) */
1078 {
1079 *((uae_u32 *)preg) ^= SDL_SwapBE32(HWget_l(addr));
1080 set_long_eflags(*((uae_u32 *)preg), CONTEXT_NAME);
1081 }
1082 break;
1083 case INSTR_MOVZX8:
1084 #ifdef CPU_x86_64
1085 if (rex.W)
1086 *((uae_u64 *)preg) = (uae_u8)HWget_b(addr);
1087 else
1088 #endif
1089 if (size == 4)
1090 *((uae_u32 *)preg) = (uae_u8)HWget_b(addr);
1091 else
1092 *((uae_u16 *)preg) = (uae_u8)HWget_b(addr);
1093 break;
1094 case INSTR_MOVSX8:
1095 #ifdef CPU_x86_64
1096 if (rex.W)
1097 *((uae_s64 *)preg) = (uae_s8)HWget_b(addr);
1098 else
1099 #endif
1100 if (size == 4)
1101 *((uae_s32 *)preg) = (uae_s8)HWget_b(addr);
1102 else
1103 *((uae_s16 *)preg) = (uae_s8)HWget_b(addr);
1104 break;
1105 case INSTR_MOVSX16:
1106 #ifdef CPU_x86_64
1107 if (rex.W)
1108 *((uae_s64 *)preg) = (uae_s16)SDL_SwapBE16(HWget_w(addr));
1109 else
1110 #endif
1111 *((uae_s32 *)preg) = (uae_s16)SDL_SwapBE16(HWget_w(addr));
1112 break;
1113 #ifdef CPU_x86_64
1114 case INSTR_MOVSX32:
1115 *((uae_s64 *)preg) = (uae_s32)SDL_SwapBE32(HWget_l(addr));
1116 break;
1117 #endif
1118 case INSTR_ADDMEM:
1119 #ifdef CPU_x86_64
1120 if (size == 8)
1121 {
1122 /* TODO: needs HWget_q */
1123 panicbug("ADD r64, m64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1124 unknown_instruction();
1125 } else
1126 #endif
1127 if (size == 1)
1128 {
1129 *((uae_u8 *)preg) += HWget_b(addr);
1130 set_byte_eflags(*((uae_u8 *)preg), CONTEXT_NAME);
1131 } else if (size == 2)
1132 {
1133 *((uae_u16 *)preg) += SDL_SwapBE16(HWget_w(addr));
1134 set_byte_eflags(*((uae_u16 *)preg), CONTEXT_NAME);
1135 } else /* if (size == 4) */
1136 {
1137 *((uae_u32 *)preg) += SDL_SwapBE32(HWget_l(addr));
1138 set_byte_eflags(*((uae_u32 *)preg), CONTEXT_NAME);
1139 }
1140 break;
1141 case INSTR_SUBMEM:
1142 #ifdef CPU_x86_64
1143 if (size == 8)
1144 {
1145 /* TODO: needs HWget_q */
1146 panicbug("SUB r64, m64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1147 unknown_instruction();
1148 } else
1149 #endif
1150 if (size == 1)
1151 {
1152 *((uae_u8 *)preg) -= HWget_b(addr);
1153 set_byte_eflags(*((uae_u8 *)preg), CONTEXT_NAME);
1154 } else if (size == 2)
1155 {
1156 *((uae_u16 *)preg) -= SDL_SwapBE16(HWget_w(addr));
1157 set_word_eflags(*((uae_u16 *)preg), CONTEXT_NAME);
1158 } else /* if (size == 4) */
1159 {
1160 *((uae_u32 *)preg) -= SDL_SwapBE32(HWget_l(addr));
1161 set_long_eflags(*((uae_u32 *)preg), CONTEXT_NAME);
1162 }
1163 break;
1164 case INSTR_CMPMEM:
1165 #ifdef CPU_x86_64
1166 if (size == 8)
1167 {
1168 /* TODO: needs HWget_q */
1169 panicbug("CMP r64, m64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1170 unknown_instruction();
1171 } else
1172 #endif
1173 if (size == 1)
1174 {
1175 imm = *((uae_u8 *)preg);
1176 imm -= HWget_b(addr);
1177 set_byte_eflags(imm, CONTEXT_NAME);
1178 } else if (size == 2)
1179 {
1180 imm = *((uae_u16 *)preg);
1181 imm -= SDL_SwapBE16(HWget_w(addr));
1182 set_word_eflags(imm, CONTEXT_NAME);
1183 } else /* if (size == 4) */
1184 {
1185 imm = *((uae_u32 *)preg);
1186 imm -= SDL_SwapBE32(HWget_l(addr));
1187 set_long_eflags(imm, CONTEXT_NAME);
1188 }
1189 break;
1190 case INSTR_DIV8:
1191 pom1 = CONTEXT_AEAX & 0xffffUL;
1192 pom2 = HWget_b(addr);
1193 CONTEXT_AEAX = (CONTEXT_AEAX & ~0xffffUL) + ((pom1 % pom2) << 8) + (pom1 / pom2);
1194 break;
1195 case INSTR_IDIV8:
1196 pom1 = CONTEXT_AEAX & 0xffffUL;
1197 pom2 = HWget_b(addr);
1198 CONTEXT_AEAX = (CONTEXT_AEAX & ~0xffffUL) + (((uae_s8)pom1 % (uae_s8)pom2) << 8) + ((uae_s8)pom1 / (uae_s8)pom2);
1199 break;
1200 case INSTR_MUL8:
1201 pom1 = CONTEXT_AEAX & 0xff;
1202 pom2 = HWget_b(addr);
1203 CONTEXT_AEAX = (CONTEXT_AEAX & ~0xffffUL) + pom1 * pom2;
1204 if ((CONTEXT_AEAX & 0xff00) == 0)
1205 CONTEXT_AEFLAGS &= ~0x401; // CF + OF
1206 else
1207 CONTEXT_AEFLAGS |= 0x401;
1208 break;
1209 case INSTR_IMUL8:
1210 pom1 = CONTEXT_AEAX & 0xff;
1211 pom2 = HWget_b(addr);
1212 CONTEXT_AEAX = (CONTEXT_AEAX & ~0xffffUL) + (uae_s8)pom1 * (uae_s8)pom2;
1213 if ((CONTEXT_AEAX & 0xff00) == 0)
1214 CONTEXT_AEFLAGS &= ~0x401; // CF + OF
1215 else
1216 CONTEXT_AEFLAGS |= 0x401;
1217 break;
1218 default:
1219 D2(panicbug("Unknown load instruction %X", instruction));
1220 abort();
1221 }
1222 } else {
1223 D(bug("WRITE instruction %X", instruction));
1224 switch (instruction) {
1225 case INSTR_MOV8:
1226 D2(bug("MOV value = $%x", *((uae_u8 *)preg)));
1227 HWput_b(addr, *((uae_u8 *)preg));
1228 break;
1229 case INSTR_MOV32:
1230 #ifdef CPU_x86_64
1231 if (rex.W)
1232 {
1233 /* TODO: needs HWput_q */
1234 panicbug("MOV m32, r64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1235 unknown_instruction();
1236 } else
1237 #endif
1238 if (size == 4)
1239 HWput_l(addr, SDL_SwapBE32(*((uae_u32 *)preg)));
1240 else
1241 HWput_w(addr, SDL_SwapBE16(*((uae_u16 *)preg)));
1242 break;
1243 case INSTR_ANDMEM:
1244 imm = HWget_b(addr);
1245 imm &= *((uae_u8 *)preg);
1246 HWput_b(addr, imm);
1247 set_byte_eflags(imm, CONTEXT_NAME);
1248 break;
1249 case INSTR_ADDMEM:
1250 #ifdef CPU_x86_64
1251 if (size == 8)
1252 {
1253 /* TODO: needs HWput_q */
1254 panicbug("ADD m64, r64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1255 unknown_instruction();
1256 } else
1257 #endif
1258 if (size == 1)
1259 {
1260 imm = HWget_b(addr);
1261 imm += *((uae_u8 *)preg);
1262 HWput_b(addr, imm);
1263 set_byte_eflags(imm, CONTEXT_NAME);
1264 } else if (size == 2)
1265 {
1266 imm = SDL_SwapBE16(HWget_w(addr));
1267 imm += *((uae_u16 *)preg);
1268 HWput_w(addr, SDL_SwapBE16(imm));
1269 set_word_eflags(SDL_SwapBE16(imm), CONTEXT_NAME);
1270 } else /* if (size == 4) */
1271 {
1272 imm = SDL_SwapBE32(HWget_l(addr));
1273 imm += *((uae_u32 *)preg);
1274 HWput_l(addr, SDL_SwapBE32(imm));
1275 set_long_eflags(imm, CONTEXT_NAME);
1276 }
1277 break;
1278 case INSTR_SUBMEM:
1279 #ifdef CPU_x86_64
1280 if (size == 8)
1281 {
1282 /* TODO: needs HWput_q */
1283 panicbug("SUB m64, r64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1284 unknown_instruction();
1285 } else
1286 #endif
1287 if (size == 1)
1288 {
1289 imm = HWget_b(addr);
1290 imm -= *((uae_u8 *)preg);
1291 HWput_b(addr, imm);
1292 set_byte_eflags(imm, CONTEXT_NAME);
1293 } else if (size == 2)
1294 {
1295 imm = SDL_SwapBE16(HWget_w(addr));
1296 imm -= *((uae_u16 *)preg);
1297 HWput_w(addr, SDL_SwapBE16(imm));
1298 set_word_eflags(imm, CONTEXT_NAME);
1299 } else /* if (size == 4) */
1300 {
1301 imm = SDL_SwapBE32(HWget_l(addr));
1302 imm -= *((uae_u32 *)preg);
1303 HWput_l(addr, SDL_SwapBE32(imm));
1304 set_long_eflags(imm, CONTEXT_NAME);
1305 }
1306 break;
1307 case INSTR_CMPMEM:
1308 #ifdef CPU_x86_64
1309 if (size == 8)
1310 {
1311 /* TODO: needs HWget_q */
1312 panicbug("CMP m64, r64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1313 unknown_instruction();
1314 } else
1315 #endif
1316 if (size == 1)
1317 {
1318 imm = HWget_b(addr);
1319 imm -= *((uae_u8 *)preg);
1320 set_byte_eflags(imm, CONTEXT_NAME);
1321 } else if (size == 2)
1322 {
1323 imm = SDL_SwapBE16(HWget_w(addr));
1324 imm -= *((uae_u16 *)preg);
1325 set_word_eflags(imm, CONTEXT_NAME);
1326 } else /* if (size == 4) */
1327 {
1328 imm = SDL_SwapBE32(HWget_l(addr));
1329 imm -= *((uae_u32 *)preg);
1330 set_long_eflags(imm, CONTEXT_NAME);
1331 }
1332 break;
1333 case INSTR_XORMEM:
1334 #ifdef CPU_x86_64
1335 if (size == 8)
1336 {
1337 /* TODO: needs HWput_q */
1338 panicbug("XOR m64, r64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1339 unknown_instruction();
1340 } else
1341 #endif
1342 if (size == 1)
1343 {
1344 imm = HWget_b(addr);
1345 imm ^= *((uae_u8 *)preg);
1346 HWput_b(addr, imm);
1347 set_byte_eflags(imm, CONTEXT_NAME);
1348 } else if (size == 2)
1349 {
1350 imm = SDL_SwapBE16(HWget_w(addr));
1351 imm ^= *((uae_u16 *)preg);
1352 HWput_w(addr, SDL_SwapBE16(imm));
1353 set_word_eflags(imm, CONTEXT_NAME);
1354 } else /* if (size == 4) */
1355 {
1356 imm = SDL_SwapBE32(HWget_l(addr));
1357 imm ^= *((uae_u32 *)preg);
1358 HWput_l(addr, SDL_SwapBE32(imm));
1359 set_long_eflags(imm, CONTEXT_NAME);
1360 }
1361 break;
1362 case INSTR_ORMEM:
1363 #ifdef CPU_x86_64
1364 if (size == 8)
1365 {
1366 /* TODO: needs HWput_q */
1367 panicbug("OR m64, r64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1368 unknown_instruction();
1369 } else
1370 #endif
1371 if (size == 1)
1372 {
1373 imm = HWget_b(addr);
1374 imm |= *((uae_u8 *)preg);
1375 HWput_b(addr, imm);
1376 set_byte_eflags(imm, CONTEXT_NAME);
1377 } else if (size == 2)
1378 {
1379 imm = SDL_SwapBE16(HWget_w(addr));
1380 imm |= *((uae_u16 *)preg);
1381 HWput_w(addr, SDL_SwapBE16(imm));
1382 set_word_eflags(imm, CONTEXT_NAME);
1383 } else /* if (size == 4) */
1384 {
1385 imm = SDL_SwapBE32(HWget_l(addr));
1386 imm |= *((uae_u32 *)preg);
1387 HWput_l(addr, SDL_SwapBE32(imm));
1388 set_long_eflags(imm, CONTEXT_NAME);
1389 }
1390 break;
1391 case INSTR_ADDIMM8:
1392 imm += HWget_b(addr);
1393 HWput_b(addr, imm);
1394 set_byte_eflags(imm, CONTEXT_NAME);
1395 break;
1396 case INSTR_ORIMM8:
1397 imm |= HWget_b(addr);
1398 HWput_b(addr, imm);
1399 set_byte_eflags(imm, CONTEXT_NAME);
1400 break;
1401 case INSTR_ANDIMM8:
1402 imm &= HWget_b(addr);
1403 HWput_b(addr, imm);
1404 set_byte_eflags(imm, CONTEXT_NAME);
1405 break;
1406 case INSTR_SUBIMM8:
1407 imm = HWget_b(addr) - imm;
1408 HWput_b(addr, imm);
1409 set_byte_eflags(imm, CONTEXT_NAME);
1410 break;
1411 case INSTR_XORIMM8:
1412 imm ^= HWget_b(addr);
1413 HWput_b(addr, imm);
1414 set_byte_eflags(imm, CONTEXT_NAME);
1415 break;
1416 case INSTR_CMPIMM8:
1417 imm = HWget_b(addr) - imm;
1418 set_byte_eflags(imm, CONTEXT_NAME);
1419 break;
1420 case INSTR_ADDIMM32:
1421 #ifdef CPU_x86_64
1422 if (rex.W)
1423 {
1424 /* TODO: needs HWput_q */
1425 panicbug("ADD m64, imm32 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1426 unknown_instruction();
1427 } else
1428 #endif
1429 if (size == 4)
1430 {
1431 imm += SDL_SwapBE32(HWget_l(addr));
1432 HWput_l(addr, SDL_SwapBE32(imm));
1433 set_long_eflags(imm, CONTEXT_NAME);
1434 } else
1435 {
1436 imm += SDL_SwapBE16(HWget_w(addr));
1437 HWput_w(addr, SDL_SwapBE16(imm));
1438 set_word_eflags(imm, CONTEXT_NAME);
1439 }
1440 break;
1441 case INSTR_ORIMM32:
1442 #ifdef CPU_x86_64
1443 if (rex.W)
1444 {
1445 /* TODO: needs HWput_q */
1446 panicbug("OR m64, imm32 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1447 unknown_instruction();
1448 } else
1449 #endif
1450 if (size == 4)
1451 {
1452 imm |= SDL_SwapBE32(HWget_l(addr));
1453 HWput_l(addr, SDL_SwapBE32(imm));
1454 set_long_eflags(imm, CONTEXT_NAME);
1455 } else
1456 {
1457 imm |= SDL_SwapBE16(HWget_w(addr));
1458 HWput_w(addr, SDL_SwapBE16(imm));
1459 set_word_eflags(imm, CONTEXT_NAME);
1460 }
1461 break;
1462 case INSTR_ANDIMM32:
1463 #ifdef CPU_x86_64
1464 if (rex.W)
1465 {
1466 /* TODO: needs HWput_q */
1467 panicbug("AND m64, imm32 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1468 unknown_instruction();
1469 } else
1470 #endif
1471 if (size == 4)
1472 {
1473 imm &= SDL_SwapBE32(HWget_l(addr));
1474 HWput_l(addr, SDL_SwapBE32(imm));
1475 set_long_eflags(imm, CONTEXT_NAME);
1476 } else
1477 {
1478 imm &= SDL_SwapBE16(HWget_w(addr));
1479 HWput_w(addr, SDL_SwapBE16(imm));
1480 set_word_eflags(imm, CONTEXT_NAME);
1481 }
1482 break;
1483 case INSTR_SUBIMM32:
1484 #ifdef CPU_x86_64
1485 if (rex.W)
1486 {
1487 /* TODO: needs HWput_q */
1488 panicbug("SUB m64, imm32 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1489 unknown_instruction();
1490 } else
1491 #endif
1492 if (size == 4)
1493 {
1494 imm = SDL_SwapBE32(HWget_l(addr)) - imm;
1495 HWput_l(addr, SDL_SwapBE32(imm));
1496 set_long_eflags(imm, CONTEXT_NAME);
1497 } else
1498 {
1499 imm = SDL_SwapBE16(HWget_w(addr)) - imm;
1500 HWput_w(addr, SDL_SwapBE16(imm));
1501 set_word_eflags(imm, CONTEXT_NAME);
1502 }
1503 break;
1504 case INSTR_XORIMM32:
1505 #ifdef CPU_x86_64
1506 if (rex.W)
1507 {
1508 /* TODO: needs HWput_q */
1509 panicbug("XOR m64, imm32 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1510 unknown_instruction();
1511 } else
1512 #endif
1513 if (size == 4)
1514 {
1515 imm ^= SDL_SwapBE32(HWget_l(addr));
1516 HWput_l(addr, SDL_SwapBE32(imm));
1517 set_long_eflags(imm, CONTEXT_NAME);
1518 } else
1519 {
1520 imm ^= SDL_SwapBE16(HWget_w(addr));
1521 HWput_w(addr, SDL_SwapBE16(imm));
1522 set_word_eflags(imm, CONTEXT_NAME);
1523 }
1524 break;
1525 case INSTR_CMPIMM32:
1526 #ifdef CPU_x86_64
1527 if (rex.W)
1528 {
1529 /* TODO: needs HWput_q */
1530 panicbug("CMP m64, imm32 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1531 unknown_instruction();
1532 } else
1533 #endif
1534 if (size == 4)
1535 {
1536 imm = SDL_SwapBE32(HWget_l(addr)) - imm;
1537 set_long_eflags(imm, CONTEXT_NAME);
1538 } else
1539 {
1540 imm = SDL_SwapBE16(HWget_w(addr)) - imm;
1541 set_word_eflags(imm, CONTEXT_NAME);
1542 }
1543 break;
1544 case INSTR_ADDLIMM8:
1545 #ifdef CPU_x86_64
1546 if (rex.W)
1547 {
1548 /* TODO: needs HWput_q */
1549 panicbug("ADDL m64, imm8 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1550 unknown_instruction();
1551 } else
1552 #endif
1553 if (size == 4)
1554 {
1555 imm += (uae_s32)SDL_SwapBE32(HWget_l(addr));
1556 HWput_l(addr, SDL_SwapBE32(imm));
1557 set_long_eflags(imm, CONTEXT_NAME);
1558 } else
1559 {
1560 imm += (uae_s16)SDL_SwapBE16(HWget_w(addr));
1561 HWput_w(addr, SDL_SwapBE16(imm));
1562 set_word_eflags(imm, CONTEXT_NAME);
1563 }
1564 break;
1565 case INSTR_ORLIMM8:
1566 #ifdef CPU_x86_64
1567 if (rex.W)
1568 {
1569 /* TODO: needs HWput_q */
1570 panicbug("ORL m64, imm8 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1571 unknown_instruction();
1572 } else
1573 #endif
1574 if (size == 4)
1575 {
1576 imm |= (uae_s32)SDL_SwapBE32(HWget_l(addr));
1577 HWput_l(addr, SDL_SwapBE32(imm));
1578 set_long_eflags(imm, CONTEXT_NAME);
1579 } else
1580 {
1581 imm |= (uae_s16)SDL_SwapBE16(HWget_w(addr));
1582 HWput_w(addr, SDL_SwapBE16(imm));
1583 set_word_eflags(imm, CONTEXT_NAME);
1584 }
1585 break;
1586 case INSTR_ANDLIMM8:
1587 #ifdef CPU_x86_64
1588 if (rex.W)
1589 {
1590 /* TODO: needs HWput_q */
1591 panicbug("ANDL m64, imm8 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1592 unknown_instruction();
1593 } else
1594 #endif
1595 if (size == 4)
1596 {
1597 imm &= (uae_s32)SDL_SwapBE32(HWget_l(addr));
1598 HWput_l(addr, SDL_SwapBE32(imm));
1599 set_long_eflags(imm, CONTEXT_NAME);
1600 } else
1601 {
1602 imm &= (uae_s16)SDL_SwapBE16(HWget_w(addr));
1603 HWput_w(addr, SDL_SwapBE16(imm));
1604 set_word_eflags(imm, CONTEXT_NAME);
1605 }
1606 break;
1607 case INSTR_SUBLIMM8:
1608 #ifdef CPU_x86_64
1609 if (rex.W)
1610 {
1611 /* TODO: needs HWput_q */
1612 panicbug("SUBL m64, imm8 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1613 unknown_instruction();
1614 } else
1615 #endif
1616 if (size == 4)
1617 {
1618 imm = (uae_s32)SDL_SwapBE32(HWget_l(addr)) - imm;
1619 HWput_l(addr, SDL_SwapBE32(imm));
1620 set_long_eflags(imm, CONTEXT_NAME);
1621 } else
1622 {
1623 imm = (uae_s16)SDL_SwapBE16(HWget_w(addr)) - imm;
1624 HWput_w(addr, SDL_SwapBE16(imm));
1625 set_word_eflags(imm, CONTEXT_NAME);
1626 }
1627 break;
1628 case INSTR_XORLIMM8:
1629 #ifdef CPU_x86_64
1630 if (rex.W)
1631 {
1632 /* TODO: needs HWput_q */
1633 panicbug("ANDL m64, imm8 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1634 unknown_instruction();
1635 } else
1636 #endif
1637 if (size == 4)
1638 {
1639 imm ^= (uae_s32)SDL_SwapBE32(HWget_l(addr));
1640 HWput_l(addr, SDL_SwapBE32(imm));
1641 set_long_eflags(imm, CONTEXT_NAME);
1642 } else
1643 {
1644 imm ^= (uae_s16)SDL_SwapBE16(HWget_w(addr));
1645 HWput_w(addr, SDL_SwapBE16(imm));
1646 set_word_eflags(imm, CONTEXT_NAME);
1647 }
1648 break;
1649 case INSTR_CMPLIMM8:
1650 #ifdef CPU_x86_64
1651 if (rex.W)
1652 {
1653 /* TODO: needs HWput_q */
1654 panicbug("CMP m64, imm8 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1655 unknown_instruction();
1656 } else
1657 #endif
1658 if (size == 4)
1659 {
1660 imm = (uae_s32)SDL_SwapBE32(HWget_l(addr)) - imm;
1661 set_long_eflags(imm, CONTEXT_NAME);
1662 } else
1663 {
1664 imm = (uae_s16)SDL_SwapBE16(HWget_w(addr)) - imm;
1665 set_word_eflags(imm, CONTEXT_NAME);
1666 }
1667 break;
1668 case INSTR_MOVIMM8:
1669 HWput_b(addr, (uae_u8)imm);
1670 break;
1671 case INSTR_MOVIMM32:
1672 if (size == 2)
1673 HWput_w(addr, (uae_u16)SDL_SwapBE16(imm));
1674 else
1675 HWput_l(addr, (uae_u32)SDL_SwapBE32(imm));
1676 break;
1677 case INSTR_TESTIMM8:
1678 imm &= HWget_b(addr);
1679 set_byte_eflags(imm, CONTEXT_NAME);
1680 break;
1681 case INSTR_NOTMEM:
1682 #ifdef CPU_x86_64
1683 if (size == 8)
1684 {
1685 /* TODO: needs HWput_q */
1686 panicbug("NOT m64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1687 unknown_instruction();
1688 } else
1689 #endif
1690 if (size == 1)
1691 {
1692 HWput_b(addr, ~(uae_u8)HWget_b(addr));
1693 } else if (size == 2)
1694 {
1695 HWput_w(addr, SDL_SwapBE16(~(uae_u16)SDL_SwapBE16(HWget_w(addr))));
1696 } else /* if (size == 4) */
1697 {
1698 HWput_l(addr, SDL_SwapBE32(~(uae_u32)SDL_SwapBE32(HWget_l(addr))));
1699 }
1700 /* eflags not affected */
1701 break;
1702 case INSTR_NEGMEM:
1703 #ifdef CPU_x86_64
1704 if (size == 8)
1705 {
1706 /* TODO: needs HWput_q */
1707 panicbug("NEG m64 - unsupported mode: i[1-6]=%02x %02x %02x %02x %02x %02x", addr_instr[1], addr_instr[2], addr_instr[3], addr_instr[4], addr_instr[5], addr_instr[6]);
1708 unknown_instruction();
1709 } else
1710 #endif
1711 if (size == 1)
1712 {
1713 imm = ~(uae_u8)HWget_b(addr) + 1;
1714 HWput_b(addr, imm);
1715 set_byte_eflags(imm, CONTEXT_NAME);
1716 } else if (size == 2)
1717 {
1718 imm = ~(uae_u16)SDL_SwapBE16(HWget_w(addr)) + 1;
1719 HWput_w(addr, SDL_SwapBE16(imm));
1720 set_word_eflags(imm, CONTEXT_NAME);
1721 } else /* if (size == 4) */
1722 {
1723 imm = ~(uae_u32)SDL_SwapBE32(HWget_l(addr)) + 1;
1724 HWput_l(addr, SDL_SwapBE32(imm));
1725 set_long_eflags(imm, CONTEXT_NAME);
1726 }
1727 if (imm == 0)
1728 CONTEXT_AEFLAGS &= ~0x1;
1729 else
1730 CONTEXT_AEFLAGS |= 0x1;
1731 break;
1732 default:
1733 abort();
1734 }
1735 }
1736
1737 D(bug("Access handled"));
1738 CONTEXT_AEIP += len;
1739 #ifdef CPU_x86_64
1740 D2(bug("Next instruction on 0x%016lx", (uintptr)CONTEXT_AEIP));
1741 #else
1742 D2(bug("Next instruction on 0x%08x", (uintptr)CONTEXT_AEIP));
1743 #endif
1744
1745 in_handler -= 1;
1746 return;
1747 buserr:
1748
1749 #endif /* HW_SIGSEGV */
1750
1751 BUS_ERROR(addr);
1752 }
1753
1754 #ifdef NO_NESTED_SIGSEGV
1755
1756 JMP_BUF sigsegv_env;
1757
1758 static void
1759 __attribute__((__noreturn__))
atari_bus_fault(void)1760 atari_bus_fault(void)
1761 {
1762 breakpt();
1763 THROW(2);
1764 }
1765
handle_access_fault(CONTEXT_ATYPE CONTEXT_NAME,volatile memptr faultaddr)1766 static __attribute_noinline__ void handle_access_fault(CONTEXT_ATYPE CONTEXT_NAME, volatile memptr faultaddr)
1767 {
1768 if (SETJMP(sigsegv_env) != 0)
1769 {
1770 /*
1771 * we get back here by a LONGJMP in BUS_ERROR,
1772 * triggered by one of the HWget_x/HWput_x calls
1773 * in the handler above
1774 */
1775 D(bug("Atari bus error (%s)", (regs.mmu_fault_addr < 0x00f00000) || (regs.mmu_fault_addr > 0x00ffffff) ? "mem" : "hw"));
1776 CONTEXT_AEIP = (uintptr)atari_bus_fault;
1777 return;
1778 }
1779
1780 handle_access_fault2(CONTEXT_NAME, faultaddr);
1781 }
1782 #endif /* NO_NESTED_SIGSEGV */
1783