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