|
|
1.1 root 1: /* m68k-execute.c - executes m68k instructions: */
2:
3: /* $Id: m68k-execute.c,v 1.12 2003/05/09 17:44:27 fredette Exp $ */
4:
5: _TME_RCSID("$Id: m68k-execute.c,v 1.12 2003/05/09 17:44:27 fredette Exp $");
6:
7: /* includes: */
8: #include "m68k-auto.h"
9:
10: /* the m68k instruction executor: */
11: static void
12: _TME_M68K_EXECUTE_NAME(struct tme_m68k *ic)
13: {
14: #undef _TME_M68K_SEQUENCE_RESTARTING
15: #undef _TME_M68K_INSN_FETCH_SAVE
16: #ifdef _TME_M68K_EXECUTE_FAST
17: struct tme_m68k_tlb *tlb;
18: tme_uint8_t *emulator_load, *emulator_load_last;
19: tme_uint8_t *emulator_load_start;
20: unsigned int instruction_burst;
21: #define _TME_M68K_INSN_FETCH_SAVE \
22: do { \
23: ic->_tme_m68k_insn_buffer_fetch_total = emulator_load - emulator_load_start; \
24: ic->_tme_m68k_insn_buffer_fetch_sizes = insn_fetch_sizes; \
25: } while (/* CONSTCOND */ 0)
26: #define _TME_M68K_SEQUENCE_RESTARTING (FALSE)
27: #else /* !_TME_M68K_EXECUTE_FAST */
28: unsigned int exceptions;
29: tme_uint32_t linear_pc;
30: #define _TME_M68K_INSN_FETCH_SAVE \
31: do { \
32: ic->_tme_m68k_insn_buffer_fetch_total = linear_pc - ic->tme_m68k_ireg_pc; \
33: ic->_tme_m68k_insn_buffer_fetch_sizes = insn_fetch_sizes; \
34: } while (/* CONSTCOND */ 0)
35: #define _TME_M68K_SEQUENCE_RESTARTING TME_M68K_SEQUENCE_RESTARTING
36: #endif /* !_TME_M68K_EXECUTE_FAST */
37: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
38: unsigned int eai_function_code;
39: int ea_post_index;
40: unsigned int ea_i_is;
41: #else /* !TME_M68K_M68020 && !TME_M68K_M68030 */
42: #define eai_function_code ea_function_code
43: #endif /* !TME_M68K_M68020 && !TME_M68K_M68030 */
44: unsigned int function_code_program;
45: unsigned int function_code_data;
46: tme_uint16_t opw, extword;
47: const struct _tme_m68k_decoder_root *root_entry;
48: const struct _tme_m68k_decoder_submap *submap_entry;
49: const struct _tme_m68k_opcode *opcode;
50: void (*func) _TME_P((struct tme_m68k *, void *, void *));
51: int specop_type;
52: void *operand0, *operand1;
53: tme_uint16_t insn_fetch_sizes;
54: unsigned int first_ea_extword_offset;
55: int ea_size, ea_cycles;
56: unsigned int ea_mode;
57: int ea_reg, ea_pre_index;
58: unsigned int ea_index_long, ea_index_scale;
59: tme_uint32_t ea_address;
60: unsigned int ea_function_code;
61: tme_int32_t disp, ea_bd;
62: int imm_operand, imm_size;
63: tme_uint32_t imm32;
64: tme_uint16_t imm16;
65: tme_uint8_t imm8;
66: tme_uint16_t transfer_next_before;
67: int rc;
68:
69: /* get the function codes. if the privilege ever changes as a
70: result of any instruction, we must redispatch: */
71: if (TME_M68K_PRIV(ic)) {
72: function_code_program = TME_M68K_FC_SP;
73: function_code_data = TME_M68K_FC_SD;
74: }
75: else {
76: function_code_program = TME_M68K_FC_UP;
77: function_code_data = TME_M68K_FC_UD;
78: }
79:
80: #ifdef _TME_M68K_EXECUTE_FAST
81:
82: /* get our instruction TLB entry and reload it: */
83: tlb = TME_ATOMIC_READ(struct tme_m68k_tlb *, ic->_tme_m68k_itlb);
84: if (!TME_M68K_TLB_OK_FAST_READ(tlb, function_code_program, ic->tme_m68k_ireg_pc, ic->tme_m68k_ireg_pc)) {
85: tme_m68k_tlb_fill(ic, tlb,
86: function_code_program,
87: ic->tme_m68k_ireg_pc,
88: TME_BUS_CYCLE_READ);
89: }
90:
91: /* if we have to go slow, run the slow executor: */
92: if (TME_M68K_SEQUENCE_RESTARTING
93: || tme_m68k_go_slow(ic)) {
94: return (_TME_M68K_EXECUTE_SLOW(ic));
95: }
96:
97: /* set up to do fast reads from the instruction TLB entry: */
98: emulator_load_last = tlb->tme_m68k_tlb_emulator_off_read + TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_m68k_tlb_linear_last);
99: ic->_tme_m68k_group0_hook = tme_m68k_group0_hook_fast;
100: instruction_burst = ic->_tme_m68k_instruction_burst;
101: #else /* !_TME_M68K_EXECUTE_FAST */
102:
103: /* set up to do slow reads from the instruction TLB entry: */
104: ic->_tme_m68k_group0_hook = NULL;
105: #endif /* !_TME_M68K_EXECUTE_FAST */
106:
107: /* the execution loop: */
108: for (;;) {
109:
110: /* reset for this instruction: */
111: #ifdef _TME_M68K_EXECUTE_FAST
112: if (__tme_predict_false(TME_ATOMIC_READ(tme_bus_addr_t, tlb->tme_m68k_tlb_linear_last) == 0)) {
113: tme_m68k_redispatch(ic);
114: }
115: emulator_load_start = emulator_load = tlb->tme_m68k_tlb_emulator_off_read + ic->tme_m68k_ireg_pc;
116: assert(TME_M68K_TLB_OK_FAST_READ(tlb, function_code_program, ic->tme_m68k_ireg_pc, ic->tme_m68k_ireg_pc)
117: || (emulator_load - 1) == emulator_load_last);
118: tme_m68k_verify_begin(ic, emulator_load_start);
119: #else /* !_TME_M68K_EXECUTE_FAST */
120: linear_pc = ic->tme_m68k_ireg_pc;
121: ic->_tme_m68k_insn_buffer_off = 0;
122: exceptions = 0;
123: if (__tme_predict_false(TME_M68K_FLAG_T(ic->tme_m68k_ireg_sr) != 0)) {
124: exceptions |= TME_M68K_EXCEPTION_GROUP1_TRACE;
125: }
126: tme_m68k_verify_begin(ic, NULL);
127: #endif /* _TME_M68K_EXECUTE_FAST */
128: #ifdef _TME_M68K_VERIFY
129: if (ic->tme_m68k_ireg_pc == 0x6000) {
130: tme_m68k_verify_hook();
131: }
132: #endif
133: insn_fetch_sizes = 0;
134: first_ea_extword_offset = sizeof(opw);
135:
136: /* fetch and decode the first word of this instruction: */
137: _TME_M68K_EXECUTE_FETCH_U16(opw);
138: ic->_tme_m68k_insn_opcode = opw;
139: root_entry = ic->_tme_m68k_decoder_root
140: + TME_FIELD_EXTRACTU(opw, 6, 10);
141: submap_entry = root_entry->_tme_m68k_decoder_root_submap
142: + TME_FIELD_EXTRACTU(opw, 0, 6);
143: opcode = root_entry->_tme_m68k_decoder_root_opcode_map
144: + submap_entry->_tme_m68k_decoder_submap_opcode_map_index;
145:
146: /* set func: */
147: func = opcode->_tme_m68k_opcode_func;
148:
149: /* set operand 0: */
150: operand0 = submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_operand0;
151: if (operand0 == NULL)
152: operand0 = root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_operand0;
153:
154: /* set operand 1: */
155: operand1 = submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_operand1;
156: if (operand1 == NULL)
157: operand1 = root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_operand1;
158:
159: /* set ea_size: */
160: ea_size = submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_eax_size;
161: if (ea_size == TME_M68K_SIZE_SUBMAP_X)
162: ea_size = root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_eax_size;
163:
164: /* set imm_operand: */
165: imm_operand = submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_imm_operand;
166: imm_size = submap_entry->_tme_m68k_decoder_submap_gen._tme_m68k_decoder_gen_imm_size;
167: if (imm_operand == TME_M68K_OPNUM_SUBMAP_X) {
168: imm_operand = root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_imm_operand;
169: imm_size = root_entry->_tme_m68k_decoder_root_gen._tme_m68k_decoder_gen_imm_size;
170: }
171:
172: /* set ea_mode, ea_reg, ea_cycles and ea_function_code -
173: instructions or the EA itself may override these: */
174: ea_mode = TME_FIELD_EXTRACTU(opw, 3, 3);
175: ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(opw, 0, 3);
176: ea_cycles = opcode->_tme_m68k_opcode_eax_cycles;
177: ea_function_code = function_code_data;
178: assert(ea_size == TME_M68K_SIZE_UNDEF
179: || ea_size == TME_M68K_SIZE_UNSIZED
180: || ea_cycles != TME_BUS_CYCLE_UNDEF);
181:
182: /* dispatch on the special operand specifier type: */
183: specop_type = opcode->_tme_m68k_opcode_specop_type;
184: if (__tme_predict_false(specop_type != TME_M68K_SPECOP_UNDEF)) {
185: switch (specop_type) {
186:
187: /* a Bcc may have an extended displacement, and we need to
188: translate BF to BSR: */
189: case TME_M68K_SPECOP_BCC:
190: disp = TME_EXT_S8_S32((tme_int8_t) opw);
191: if (disp == 0) {
192: _TME_M68K_EXECUTE_FETCH_S16(disp);
193: }
194: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
195: else if (disp == -255) {
196: _TME_M68K_EXECUTE_FETCH_S32(disp);
197: }
198: #endif /* TME_M68K_M68020 || TME_M68K_M68030 */
199: imm32 = (tme_uint32_t) disp;
200: operand0 = &imm32;
201: if (TME_FIELD_EXTRACTU(opw, 8, 4) == TME_M68K_C_F) {
202: func = tme_m68k_bsr;
203: }
204: break;
205:
206: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
207: /* these are similar: */
208: case TME_M68K_SPECOP_DIVUL:
209: case TME_M68K_SPECOP_MULUL:
210: _TME_M68K_EXECUTE_FETCH_U16(specop);
211: first_ea_extword_offset = 4;
212: if (specop & TME_BIT(11)) {
213: /* this is really a signed operation, override
214: m68k-opmap-make.sh's guess that it is unsigned: */
215: func = ((opcode->_tme_m68k_opcode_specop_type == TME_M68K_SPECOP_DIVUL)
216: ? tme_m68k_divsl
217: : tme_m68k_mulsl);
218: }
219: break;
220: #endif /* TME_M68K_M68020 || TME_M68K_M68030 */
221:
222: #if (_TME_M68K_EXECUTE_CPU != TME_M68K_M68000)
223: /* moves: */
224: case TME_M68K_SPECOP_MOVES:
225:
226: /* fetch the remainder of the instruction and decide what EA
227: function code and cycles we need: */
228: _TME_M68K_EXECUTE_FETCH_U16(ic->_tme_m68k_insn_specop);
229: first_ea_extword_offset = 4;
230: if (ic->_tme_m68k_insn_specop & TME_BIT(11)) {
231: ea_cycles = TME_BUS_CYCLE_WRITE;
232: ea_function_code = ic->tme_m68k_ireg_dfc;
233: }
234: else {
235: ea_cycles = TME_BUS_CYCLE_READ;
236: ea_function_code = ic->tme_m68k_ireg_sfc;
237: }
238:
239: /* if we're not privileged, don't fetch any EA, and run the
240: priv function instead: */
241: if (!TME_M68K_PRIV(ic)) {
242: func = tme_m68k_priv;
243: ea_size = TME_M68K_SIZE_UNDEF;
244: }
245: break;
246: #endif /* !TME_M68K_M68000 */
247:
248: /* many instructions have a single special extension word: */
249: case TME_M68K_SPECOP_SPECOP16:
250: _TME_M68K_EXECUTE_FETCH_U16(ic->_tme_m68k_insn_specop);
251: first_ea_extword_offset = 4;
252: break;
253:
254: /* all of these always have two specop words: */
255: case TME_M68K_SPECOP_CAS2:
256: _TME_M68K_EXECUTE_FETCH_U16(ic->_tme_m68k_insn_specop);
257: _TME_M68K_EXECUTE_FETCH_U16(ic->_tme_m68k_insn_specop2);
258: first_ea_extword_offset = 6;
259: break;
260:
261: /* a memory-to-memory move instruction has additional ea mode
262: and reg fields, but we don't need to do anything for that
263: yet: */
264: case TME_M68K_SPECOP_MOVEMEMTOMEM:
265: break;
266:
267: /* a nonmemory-to-memory move instruction has additional ea
268: mode and reg fields, and we use them now: */
269: case TME_M68K_SPECOP_MOVENONMEMTOMEM:
270: ea_mode = TME_FIELD_EXTRACTU(opw, 6, 3);
271: ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(opw, 9, 3);
272: assert(ea_cycles == TME_BUS_CYCLE_WRITE);
273: break;
274:
275: /* the illegal specop makes sure not to fetch any EAs or
276: immediates: */
277: case TME_M68K_SPECOP_ILLEGAL:
278: ea_size = TME_M68K_SIZE_UNDEF;
279: imm_operand = TME_M68K_OPNUM_UNDEF;
280: break;
281:
282: default: abort();
283: }
284: }
285:
286: /* get any immediate operand: */
287: if (__tme_predict_false(imm_operand != TME_M68K_OPNUM_UNDEF)) {
288: switch (imm_size) {
289: case TME_M68K_SIZE_16:
290: _TME_M68K_EXECUTE_FETCH_U16(imm16);
291: if (imm_operand == 0) operand0 = &imm16; else operand1 = &imm16;
292: break;
293: case TME_M68K_SIZE_32:
294: _TME_M68K_EXECUTE_FETCH_U32(imm32);
295: if (imm_operand == 0) operand0 = &imm32; else operand1 = &imm32;
296: break;
297: case TME_M68K_SIZE_16S32:
298: _TME_M68K_EXECUTE_FETCH_S16(imm32);
299: if (imm_operand == 0) operand0 = &imm32; else operand1 = &imm32;
300: break;
301: case TME_M68K_SIZE_16U8:
302: _TME_M68K_EXECUTE_FETCH_U16(imm8);
303: if (imm_operand == 0) operand0 = &imm8; else operand1 = &imm8;
304: break;
305: default: assert(FALSE);
306: }
307: }
308:
309: /* loop over up to two effective addresses calculations. this
310: initializes for the normal, single effective address: */
311: while (ea_size != TME_M68K_SIZE_UNDEF) {
312:
313: /* this EA must have either no size, or be exactly one, two, or
314: four bytes: */
315: assert(ea_size == TME_M68K_SIZE_UNSIZED
316: || ea_size == TME_M68K_SIZE_8
317: || ea_size == TME_M68K_SIZE_16
318: || ea_size == TME_M68K_SIZE_32);
319:
320: /* for the effective address predecrement and postincrement
321: modes, we require that these size macros correspond exactly
322: to the number of bytes, that the %a7 register number be 15,
323: and that the ea reg not be greater than %a7: */
324: #if TME_M68K_SIZE_UNSIZED != 0
325: #error "TME_M68K_SIZE_UNSIZED must be 0"
326: #endif
327: #if TME_M68K_SIZE_8 != 1
328: #error "TME_M68K_SIZE_8 must be 1"
329: #endif
330: #if TME_M68K_SIZE_16 != 2
331: #error "TME_M68K_SIZE_16 must be 2"
332: #endif
333: #if TME_M68K_SIZE_32 != 4
334: #error "TME_M68K_SIZE_32 must be 4"
335: #endif
336: #if TME_M68K_IREG_A7 != 15
337: #error "TME_M68K_IREG_A7 must be 15"
338: #endif
339: assert(ea_reg <= TME_M68K_IREG_A7);
340: #define TME_M68K_AREG_INCREMENT(areg, size) \
341: (((((areg) + 1) / (TME_M68K_IREG_A7 + 1)) & (size)) + (size))
342:
343: /* initialize ea_address to silence -Wuninitialized: */
344: ea_address = 0;
345:
346: /* set the EA inner function code: */
347: eai_function_code = ea_function_code;
348:
349: /* dispatch on the mode: */
350: switch (ea_mode) {
351:
352: /* address register indirect: */
353: case 2:
354: ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
355: break;
356:
357: /* address register indirect postincrement: */
358: case 3:
359: /* if we are not restarting, set the effective address: */
360: if (!_TME_M68K_SEQUENCE_RESTARTING) {
361: ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
362: ic->tme_m68k_ireg_uint32(ea_reg) += TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
363: }
364: break;
365:
366: /* address register indirect predecrement: */
367: case 4:
368: /* if we are not restarting, set the effective address: */
369: if (!_TME_M68K_SEQUENCE_RESTARTING) {
370: ic->tme_m68k_ireg_uint32(ea_reg) -= TME_M68K_AREG_INCREMENT(ea_reg, ea_size);
371: ea_address = ic->tme_m68k_ireg_uint32(ea_reg);
372: }
373: break;
374:
375: /* address register indirect with 16-bit displacement: */
376: case 5:
377: _TME_M68K_EXECUTE_FETCH_S16(ea_bd);
378: ea_address = ic->tme_m68k_ireg_uint32(ea_reg) + ea_bd;
379: break;
380:
381: /* miscellaneous modes: */
382: case 7:
383:
384: /* absolute short addressing: */
385: if (ea_reg == TME_M68K_IREG_A0) {
386: _TME_M68K_EXECUTE_FETCH_S16(ea_address);
387: break;
388: }
389:
390: /* absolute long addressing: */
391: if (ea_reg == TME_M68K_IREG_A1) {
392: _TME_M68K_EXECUTE_FETCH_S32(ea_address);
393: break;
394: }
395:
396: /* program counter indirect with 16-bit displacement: */
397: if (ea_reg == TME_M68K_IREG_A2) {
398: _TME_M68K_EXECUTE_FETCH_S16(ea_bd);
399: /* XXX simulates preincremented pc: */
400: ea_address = ic->tme_m68k_ireg_pc + first_ea_extword_offset + ea_bd;
401: ea_function_code = function_code_program;
402: break;
403: }
404:
405: /* everything else is just like mode 6 except with the PC as
406: the base register: */
407: assert (ea_reg == TME_M68K_IREG_A3);
408: ea_reg = TME_M68K_IREG_PC;
409: eai_function_code = function_code_program;
410: /* FALLTHROUGH */
411:
412: /* various indexed modes: */
413: case 6:
414:
415: /* fetch the extension word and take it apart. the 68000 and
416: 68010 ignore the scale field in the extension word and always
417: behave as if it is zero: */
418: _TME_M68K_EXECUTE_FETCH_U16(extword);
419: ea_pre_index = TME_M68K_IREG_D0 + TME_FIELD_EXTRACTU(extword, 12, 4);
420: ea_index_long = (extword & TME_BIT(11));
421: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
422: ea_index_scale = TME_FIELD_EXTRACTU(extword, 9, 2);
423: #else /* !TME_M68K_M68020 && !TME_M68K_M68030 */
424: ea_index_scale = 0;
425: #endif /* !TME_M68K_M68020 && !TME_M68K_M68030 */
426:
427: /* if this is a full extension word: */
428: if (extword & TME_BIT(8)) {
429: #if (_TME_M68K_EXECUTE_CPU == TME_M68K_M68020) || (_TME_M68K_EXECUTE_CPU == TME_M68K_M68030)
430:
431: ea_i_is = TME_FIELD_EXTRACTU(extword, 0, 3);
432:
433: /* optionally suppress the base register: */
434: if (extword & TME_BIT(7)) {
435: ea_reg = TME_M68K_IREG_ZERO32;
436: }
437:
438: /* fetch any base displacement: */
439: switch (TME_FIELD_EXTRACTU(extword, 4, 2)) {
440: case 0: abort();
441: case 1: ea_bd = 0; break;
442: case 2: _TME_M68K_EXECUTE_FETCH_S16(ea_bd); break;
443: case 3: _TME_M68K_EXECUTE_FETCH_S32(ea_bd); break;
444: }
445:
446: /* optionally suppress the index register. this is also
447: where we check for combined IS-I/IS fields greater than
448: or equal to 0xc, which are reserved: */
449: if (extword & TME_BIT(6)) {
450: ea_pre_index = TME_M68K_IREG_ZERO32;
451: if (ea_i_is >= 0x4) {
452: abort();
453: }
454: }
455:
456: /* fetch any outer displacement: */
457: switch (ea_i_is & 3) {
458: case 0: case 1: ea_od = 0; break;
459: case 2: _TME_M68K_EXECUTE_FETCH_S16(ea_od); break;
460: case 3: _TME_M68K_EXECUTE_FETCH_S32(ea_od); break;
461: }
462:
463: /* dispatch on the I/IS fields: */
464: ea_post_index = TME_M68K_IREG_ZERO32;
465: switch (ea_i_is) {
466:
467: /* no memory indirect action: */
468: case 0x0:
469: ea_post_index = TME_M68K_IREG_UNDEF;
470: break;
471:
472: /* indirect preindexed with null outer displacement: */
473: /* indirect preindexed with word outer displacement: */
474: /* indirect preindexed with long outer displacement: */
475: case 0x1: case 0x2: case 0x3:
476: break;
477:
478: /* reserved: */
479: case 0x4: default: abort();
480:
481: /* indirect postindexed with null outer displacement: */
482: /* indirect postindexed with word outer displacement: */
483: /* indirect postindexed with long outer displacement: */
484: case 0x5: case 0x6: case 0x7:
485: ea_post_index = ea_pre_index;
486: ea_pre_index = TME_M68K_IREG_ZERO32;
487: break;
488: }
489:
490: /* preindex and base-displace the original address register
491: to arrive at the indirect EA: */
492: ea_address =
493: (ic->tme_m68k_ireg_uint32(ea_reg)
494: + ((ea_index_long
495: ? ic->tme_m68k_ireg_int32(ea_pre_index)
496: : ((tme_int32_t) ic->tme_m68k_ireg_int16(ea_pre_index << 1)))
497: << ea_index_scale)
498: + ea_bd
499: + (ea_reg == TME_M68K_IREG_PC
500: /* XXX simulates preincremented pc: */
501: ? first_ea_extword_offset
502: : 0));
503:
504: /* if this is a memory indirect, read the indirect EA.
505: don't disturb the EA in the IC state if we're restarting,
506: for two reasons:
507:
508: first, the value in the IC state may belong to some later
509: part of the instruction handling, in which case we must
510: (continue to) preserve it, and
511:
512: second, if the EA in the IC state *is* from this part of
513: the instruction handling, it's correct, while our EA may
514: *not* be correct, since it was generated from IC state
515: that may have changed since the instruction originally
516: started (i.e., address register changes by the user or by
517: our own postincrement/predecrement, or function code
518: register changes by the user): */
519: if (ea_post_index != TME_M68K_IREG_UNDEF) {
520: if (!_TME_M68K_SEQUENCE_RESTARTING) {
521: ic->_tme_m68k_ea_address = ea_address;
522: ic->_tme_m68k_ea_function_code = eai_function_code;
523: }
524: _TME_M68K_INSN_FETCH_SAVE;
525: tme_m68k_read_mem32(ic, TME_M68K_IREG_MEMY32);
526: ea_address =
527: (ic->tme_m68k_ireg_memy32
528: + ((ea_index_long
529: ? ic->tme_m68k_ireg_int32(ea_post_index)
530: : ((tme_int32_t) ic->tme_m68k_ireg_int16(ea_post_index << 1)))
531: << ea_index_scale)
532: + ea_od);
533: }
534: else {
535: ea_function_code = eai_function_code;
536: }
537:
538: #else /* !TME_M68K_M68020 && !TME_M68K_M68030 */
539: /* XXX - illegal instruction */
540: abort();
541: #endif /* !TME_M68K_M68020 && !TME_M68K_M68030 */
542: }
543:
544: /* otherwise, this is a brief extension word: */
545: else {
546: ea_address =
547: (ic->tme_m68k_ireg_uint32(ea_reg)
548: + ((tme_int32_t) ((tme_int8_t) (extword & 0xff)))
549: + ((ea_index_long
550: ? ic->tme_m68k_ireg_int32(ea_pre_index)
551: : ((tme_int32_t) ic->tme_m68k_ireg_int16(ea_pre_index << 1)))
552: << ea_index_scale)
553: + (ea_reg == TME_M68K_IREG_PC
554: /* XXX simulates preincremented pc: */
555: ? first_ea_extword_offset
556: : 0));
557: ea_function_code = eai_function_code;
558: }
559: break;
560:
561: default: assert(FALSE);
562: }
563:
564: /* we have calculated the effective address. we don't store it
565: if we're restarting, because it may have been calculated
566: using user-visible registers (address registers and even
567: function code registers!) that the user may have changed (or,
568: in the case of pre/postdecrement EAs, that *we* may have
569: changed) between the bus fault and the instruction restart.
570: when we restart an instruction we *always* want to use the
571: same effective address as before: */
572: if (!_TME_M68K_SEQUENCE_RESTARTING) {
573: ic->_tme_m68k_ea_address = ea_address;
574: ic->_tme_m68k_ea_function_code = eai_function_code;
575: }
576:
577: /* XXX XXX XXX - if we detect a store to program space, that's an illegal: */
578: /* XXX but maybe not for moves? */
579: if (ea_function_code == function_code_program
580: && (ea_cycles & TME_BUS_CYCLE_WRITE)) {
581: abort();
582: }
583:
584: /* if we're loading this operand: */
585: if (ea_cycles & TME_BUS_CYCLE_READ) {
586: _TME_M68K_INSN_FETCH_SAVE;
587: (*_tme_m68k_read_memx[ea_size])(ic);
588: }
589:
590: /* stop unless this is a memory-to-memory move: */
591: if (specop_type != TME_M68K_SPECOP_MOVEMEMTOMEM)
592: break;
593:
594: /* reload for the other memory EA at the same size: */
595: ea_mode = TME_FIELD_EXTRACTU(opw, 6, 3);
596: ea_reg = TME_M68K_IREG_A0 + TME_FIELD_EXTRACTU(opw, 9, 3);
597: ea_cycles = TME_BUS_CYCLE_WRITE;
598: ea_function_code = function_code_data;
599: specop_type = TME_M68K_SPECOP_UNDEF;
600: }
601:
602: /* we've fetched all of the instruction words: */
603: _TME_M68K_INSN_FETCH_SAVE;
604:
605: /* set the next PC: */
606: #ifdef _TME_M68K_EXECUTE_FAST
607: ic->tme_m68k_ireg_pc_next = ic->tme_m68k_ireg_pc + (emulator_load - emulator_load_start);
608: #else /* !_TME_M68K_EXECUTE_FAST */
609: ic->tme_m68k_ireg_pc_next = linear_pc;
610: #endif /* !_TME_M68K_EXECUTE_FAST */
611:
612: /* if we're not restarting, or if this instruction function can
613: fault, call the instruction function: */
614: if (!_TME_M68K_SEQUENCE_RESTARTING
615: || (ic->_tme_m68k_mode_flags & TME_M68K_EXECUTION_INST_CANFAULT)) {
616: transfer_next_before = ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next;
617: (*func)(ic, operand0, operand1);
618: assert(!(ic->_tme_m68k_mode_flags & TME_M68K_EXECUTION_INST_CANFAULT)
619: != (ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next
620: != transfer_next_before));
621: ic->_tme_m68k_mode_flags &= ~TME_M68K_EXECUTION_INST_CANFAULT;
622: }
623:
624: /* store up to one EA path: */
625: if (ea_size != TME_M68K_SIZE_UNDEF
626: && (ea_cycles & TME_BUS_CYCLE_WRITE)) {
627: (*_tme_m68k_write_memx[ea_size])(ic);
628: }
629:
630: /* an instruction has ended: */
631: tme_m68k_verify_end(ic, func);
632:
633: /* update the PC: */
634: ic->tme_m68k_ireg_pc = ic->tme_m68k_ireg_pc_next;
635: TME_M68K_SEQUENCE_START;
636:
637: #ifdef _TME_M68K_EXECUTE_FAST
638: /* if we haven't finished the instruction burst yet, continue: */
639: if (__tme_predict_true(--instruction_burst)) {
640: continue;
641: }
642: instruction_burst = ic->_tme_m68k_instruction_burst;
643: #endif /* _TME_M68K_EXECUTE_FAST */
644:
645: /* try to acquire the external mutex and check for external
646: resets, halts, or interrupts, and process them along
647: with any internal exceptions: */
648: rc = tme_mutex_trylock(&ic->tme_m68k_external_mutex);
649: if (TME_THREADS_ERRNO(rc) == TME_OK) {
650: tme_m68k_external_check(ic,
651: #ifdef _TME_M68K_EXECUTE_FAST
652: 0
653: #else /* !_TME_M68K_EXECUTE_FAST */
654: exceptions
655: #endif /* !_TME_M68K_EXECUTE_FAST */
656: );
657:
658: /* unlock the external mutex: */
659: tme_mutex_unlock(&ic->tme_m68k_external_mutex);
660: }
661:
662: #ifndef _TME_M68K_EXECUTE_FAST
663:
664: /* otherwise, if we have internal exceptions, process them: */
665: else if (exceptions) {
666: tme_m68k_exception(ic, exceptions);
667: }
668:
669: /* if we can go fast now, go fast: */
670: if (!tme_m68k_go_slow(ic)) {
671: tme_m68k_redispatch(ic);
672: }
673:
674: #else /* _TME_M68K_EXECUTE_FAST */
675:
676: /* if this is a cooperative threading system, yield: */
677: #ifdef TME_THREADS_COOPERATIVE
678: tme_thread_yield();
679: #endif /* TME_THREADS_COOPERATIVE */
680:
681: #endif /* _TME_M68K_EXECUTE_FAST */
682:
683: }
684: /* NOTREACHED */
685:
686: #ifdef _TME_M68K_EXECUTE_FAST
687:
688: /* if we get here, we "faulted" trying to fetch an instruction word
689: from host memory. it's possibly not a "real" fault, since this
690: instruction may simply cross a page boundary, but since the fast
691: executor can't restart instructions we have to treat this like a
692: group 0 fault: */
693: _tme_m68k_fast_fetch_failed:
694:
695: /* mimic a group 0 exception: */
696: _TME_M68K_INSN_FETCH_SAVE;
697: ic->_tme_m68k_group0_flags = TME_M68K_BUS_CYCLE_FETCH | TME_M68K_BUS_CYCLE_READ;
698: ic->_tme_m68k_group0_function_code = function_code_program;
699: ic->_tme_m68k_group0_address = ic->tme_m68k_ireg_pc + (emulator_load - emulator_load_start);
700: ic->_tme_m68k_group0_sequence = ic->_tme_m68k_sequence;
701: ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted_after = 0;
702: ic->_tme_m68k_group0_buffer_read_size = 0;
703: ic->_tme_m68k_group0_buffer_read_softrr = 0;
704: tme_m68k_group0_hook_fast(ic);
705: ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_faulted =
706: ic->_tme_m68k_group0_sequence._tme_m68k_sequence_transfer_next;
707:
708: /* mimic the rte: */
709: ic->_tme_m68k_sequence = ic->_tme_m68k_group0_sequence;
710: ic->_tme_m68k_sequence._tme_m68k_sequence_transfer_next = 1;
711: TME_M68K_SEQUENCE_RESTART;
712:
713: tme_m68k_redispatch(ic);
714: /* NOTREACHED */
715: #endif /* _TME_M68K_EXECUTE_FAST */
716: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.