|
|
1.1 root 1: /* $Id: m68020.c,v 1.6 2005/04/30 15:14:37 fredette Exp $ */
2:
3: /* ic/m68k/m68020.c - implementation of Motorola 68020 emulation: */
4:
5: /*
6: * Copyright (c) 2002, 2003, 2004 Matt Fredette
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
19: * This product includes software developed by Matt Fredette.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
27: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33: * POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: #include <tme/common.h>
37: _TME_RCSID("$Id: m68020.c,v 1.6 2005/04/30 15:14:37 fredette Exp $");
38:
39: /* includes: */
40: #include "m68k-impl.h"
41:
42: /* macros: */
43: #define TME_M68K_SSWB_FC (0x8000)
44: #define TME_M68K_SSWB_FB (0x4000)
45: #define TME_M68K_SSWB_RC (0x2000)
46: #define TME_M68K_SSWB_RB (0x1000)
47: #define TME_M68K_SSWB_DF (0x0100)
48: #define TME_M68K_SSWB_RM (0x0080)
49: #define TME_M68K_SSWB_RW (0x0040)
50: #define TME_M68K_SSWB_SIZE_MASK (0x0030)
51: #define TME_M68K_SSWB_SIZE_4 (0x0000)
52: #define TME_M68K_SSWB_SIZE_1 (0x0010)
53: #define TME_M68K_SSWB_SIZE_2 (0x0020)
54: #define TME_M68K_SSWB_SIZE_3 (0x0030)
55:
56: /* structures: */
57:
58: /* the format 0xB stack frame: */
59: /* XXX we assume that this will pack: */
60: struct tme_m68k_fmtB {
61:
62: /* an unused word: */
63: tme_uint8_t tme_m68k_fmtB_state0[1 * sizeof(tme_uint16_t)];
64:
65: /* the special status word: */
66: tme_uint16_t tme_m68k_fmtB_ssw;
67:
68: /* the instruction pipe stage C: */
69: tme_uint16_t tme_m68k_fmtB_ipipe_C;
70:
71: /* the instruction pipe stage B: */
72: tme_uint16_t tme_m68k_fmtB_ipipe_B;
73:
74: /* the data cycle fault address: */
75: tme_uint32_t tme_m68k_fmtB_addr;
76:
77: /* two unused words: */
78: tme_uint8_t tme_m68k_fmtB_state1[2 * sizeof(tme_uint16_t)];
79:
80: /* the data output buffer: */
81: tme_uint8_t tme_m68k_fmtB_dob[4];
82:
83: /* four unused words: */
84: tme_uint8_t tme_m68k_fmtB_state2[4 * sizeof(tme_uint16_t)];
85:
86: /* the stage B address: */
87: tme_uint32_t tme_m68k_fmtB_addr_B;
88:
89: /* two unused words: */
90: tme_uint8_t tme_m68k_fmtB_state3[2 * sizeof(tme_uint16_t)];
91:
92: /* the data input buffer: */
93: tme_uint8_t tme_m68k_fmtB_dib[4];
94:
95: /* three unused words: */
96: tme_uint8_t tme_m68k_fmtB_state4[3 * sizeof(tme_uint16_t)];
97:
98: /* the version number and internal information: */
99: tme_uint16_t tme_m68k_fmtB_version_info;
100:
101: /* eighteen unused words: */
102: tme_uint8_t tme_m68k_fmtB_state5[18 * sizeof(tme_uint16_t)];
103: };
104:
105: /* both executors are for the 68020: */
106: #define _TME_M68K_EXECUTE_CPU TME_M68K_M68020
107: #define _TME_M68K_EXECUTE_OPMAP tme_m68k_opcodes_m68020
108:
109: /* create the slow executor: */
110: #define _TME_M68K_EXECUTE_NAME _tme_m68020_execute_slow
111: #undef _TME_M68K_EXECUTE_FAST
112: #undef _TME_M68K_EXECUTE_SLOW
113: #include "m68k-execute.c"
114: #undef _TME_M68K_EXECUTE_NAME
115: #undef _TME_M68K_EXECUTE_FAST
116: #undef _TME_M68K_EXECUTE_SLOW
117:
118: /* create the fast executor: */
119: #define _TME_M68K_EXECUTE_NAME _tme_m68020_execute
120: #define _TME_M68K_EXECUTE_FAST
121: #define _TME_M68K_EXECUTE_SLOW _tme_m68020_execute_slow
122: #include "m68k-execute.c"
123: #undef _TME_M68K_EXECUTE_NAME
124: #undef _TME_M68K_EXECUTE_FAST
125: #undef _TME_M68K_EXECUTE_SLOW
126:
127: #undef _TME_M68K_EXECUTE_CPU
128:
129: /* m68020 exception processing: */
130: static void
131: _tme_m68020_exception(struct tme_m68k *ic)
132: {
133: tme_uint32_t exceptions;
134: /* one 16-bit word for each 16-bit internal register word in the format 0xB frame: */
135: tme_uint8_t raw_state[(1 + 2 + 4 + 2 + 3 + 18) * sizeof(tme_uint16_t)], *raw;
136: unsigned int raw_avail, raw_used;
137: struct tme_m68k_fmtB fmtB;
138: unsigned int flags;
139: tme_uint8_t function_code;
140: tme_uint16_t ssw;
141:
142: /* get the set of exceptions: */
143: exceptions = ic->_tme_m68k_exceptions;
144:
145: /* a reset exception: */
146: if (exceptions & TME_M68K_EXCEPTION_RESET) {
147:
148: /* do the common reset processing: */
149: tme_m68k_do_reset(ic);
150: /* NOTREACHED */
151: }
152:
153: /* an address or bus error: */
154: else if (exceptions & (TME_M68K_EXCEPTION_AERR
155: | TME_M68K_EXCEPTION_BERR)) {
156:
157: /* start the exception processing: */
158: tme_m68k_exception_process_start(ic, 0);
159:
160: /* start assembling the raw data: */
161: raw = raw_state;
162: raw_avail = sizeof(raw_state);
163: #define RAW_PUT(v) \
164: do { \
165: assert(raw_avail >= sizeof(v)); \
166: memcpy(raw, &v, sizeof(v)); \
167: raw += sizeof(v); \
168: raw_avail -= sizeof(v); \
169: } while (/* CONSTCOND */ 0)
170:
171: /* put in the sequence: */
172: raw_used = tme_m68k_sequence_empty(ic, raw, raw_avail);
173: raw += raw_used;
174: raw_avail -= raw_used;
175:
176: /* dispatch on the mode: */
177: switch (ic->_tme_m68k_group0_sequence._tme_m68k_sequence_mode) {
178:
179: case TME_M68K_MODE_EXECUTION:
180:
181: /* put in the instruction buffer: */
182: raw_used = tme_m68k_insn_buffer_empty(ic, raw, raw_avail);
183: raw += raw_used;
184: raw_avail -= raw_used;
185:
186: /* put in the EA address: */
187: function_code = ic->_tme_m68k_ea_function_code;
188: RAW_PUT(function_code);
189: RAW_PUT(ic->_tme_m68k_ea_address);
190:
191: /* put in the memory X, Y, and Z buffers: */
192: RAW_PUT(ic->tme_m68k_ireg_memx32);
193: RAW_PUT(ic->tme_m68k_ireg_memy32);
194: RAW_PUT(ic->tme_m68k_ireg_memz32);
195:
196: /* done: */
197: break;
198:
199: case TME_M68K_MODE_EXCEPTION:
200:
201: /* put in the exceptions set: */
202: RAW_PUT(ic->_tme_m68k_exceptions);
203:
204: /* put in the shadow status register: */
205: RAW_PUT(ic->tme_m68k_ireg_shadow_sr);
206:
207: /* put in the last PC: */
208: RAW_PUT(ic->tme_m68k_ireg_pc_last);
209:
210: /* done: */
211: break;
212:
213: case TME_M68K_MODE_RTE:
214:
215: /* put in the shadow status register: */
216: RAW_PUT(ic->tme_m68k_ireg_shadow_sr);
217:
218: /* put in the next program counter: */
219: RAW_PUT(ic->tme_m68k_ireg_pc_next);
220:
221: /* put in the format/offset word: */
222: RAW_PUT(ic->tme_m68k_ireg_format_offset);
223:
224: break;
225:
226: default: abort();
227: }
228:
229: /* put in the internal state: */
230: raw_avail = raw - raw_state;
231: raw = raw_state;
232: #undef RAW_PUT
233: #define RAW_PUT(f) \
234: do { \
235: raw_used = TME_MIN(sizeof(f), raw_avail); \
236: memcpy(f, raw, raw_used); \
237: raw += raw_used; \
238: raw_avail -= raw_used; \
239: } while (/* CONSTCOND */ 0)
240:
241: /* use all of the reserved regions: */
242: RAW_PUT(fmtB.tme_m68k_fmtB_state0);
243: RAW_PUT(fmtB.tme_m68k_fmtB_state1);
244: RAW_PUT(fmtB.tme_m68k_fmtB_state2);
245: RAW_PUT(fmtB.tme_m68k_fmtB_state3);
246: RAW_PUT(fmtB.tme_m68k_fmtB_state4);
247: RAW_PUT(fmtB.tme_m68k_fmtB_state5);
248: #undef RAW_PUT
249:
250: /* put in the special status word and the data output buffer: */
251: ssw = 0;
252: flags = ic->_tme_m68k_group0_flags;
253:
254: /* if this was an instruction fetch: */
255: if (flags & TME_M68K_BUS_CYCLE_FETCH) {
256:
257: /* we always ask for a rerun of at least the stage C word, so we
258: associate the fault address with the stage C word. the
259: address of the stage C word is the address of the stage B
260: word minus sizeof(stage C word): */
261: ssw |= TME_M68K_SSWB_RC;
262: fmtB.tme_m68k_fmtB_addr_B = tme_htobe_u32(ic->_tme_m68k_group0_address + sizeof(fmtB.tme_m68k_fmtB_ipipe_C));
263:
264: /* if this is an address fault: */
265: if (exceptions & TME_M68K_EXCEPTION_AERR) {
266:
267: /* nothing to do */
268: }
269:
270: /* otherwise, this is a bus fault: */
271: else {
272:
273: /* mark stage C as faulted: */
274: ssw |= TME_M68K_SSWB_FC;
275:
276: /* if this is a 32-bit fetch: */
277: if (ic->_tme_m68k_group0_buffer_read_size == sizeof(tme_uint32_t)) {
278:
279: /* a 32-bit fetch additionally faults "prefetching" the stage B word: */
280: ssw |= (TME_M68K_SSWB_FB | TME_M68K_SSWB_RB);
281: }
282: }
283: }
284:
285: /* otherwise, this was not an instruction fetch: */
286: else {
287:
288: /* this is a data fault: */
289: ssw |= TME_M68K_SSWB_DF;
290:
291: /* put in the function code and address: */
292: ssw |= ic->_tme_m68k_group0_function_code;
293: fmtB.tme_m68k_fmtB_addr = tme_htobe_u32(ic->_tme_m68k_group0_address);
294:
295: /* if this was part of a read/modify/write cycle: */
296: if (flags & TME_M68K_BUS_CYCLE_RMW) {
297: ssw |= TME_M68K_SSWB_RM;
298: }
299:
300: /* if this was a read: */
301: if (flags & TME_M68K_BUS_CYCLE_READ) {
302: ssw |= TME_M68K_SSWB_RW;
303:
304: /* put in the size indication: */
305: switch (ic->_tme_m68k_group0_buffer_read_size) {
306: default: assert(FALSE);
307: case 1: ssw |= TME_M68K_SSWB_SIZE_1; break;
308: case 2: ssw |= TME_M68K_SSWB_SIZE_2; break;
309: case 3: ssw |= TME_M68K_SSWB_SIZE_3; break;
310: case 4: ssw |= TME_M68K_SSWB_SIZE_4; break;
311: }
312:
313: }
314:
315: /* otherwise, this is a write: */
316: else {
317:
318: /* put in the size indication: */
319: switch (ic->_tme_m68k_group0_buffer_write_size) {
320: default: assert(FALSE);
321: case 1: ssw |= TME_M68K_SSWB_SIZE_1; break;
322: case 2: ssw |= TME_M68K_SSWB_SIZE_2; break;
323: case 3: ssw |= TME_M68K_SSWB_SIZE_3; break;
324: case 4: ssw |= TME_M68K_SSWB_SIZE_4; break;
325: }
326:
327: /* put in the data output buffer: */
328: memcpy(fmtB.tme_m68k_fmtB_dob
329: + sizeof(fmtB.tme_m68k_fmtB_dob)
330: - ic->_tme_m68k_group0_buffer_write_size,
331: ic->_tme_m68k_group0_buffer_write,
332: ic->_tme_m68k_group0_buffer_write_size);
333: }
334: }
335:
336: /* put in the SSW: */
337: fmtB.tme_m68k_fmtB_ssw = tme_htobe_u16(ssw);
338:
339: /* push the format 0xB contents. we don't need to worry about
340: restarting here, because any fault is a double fault: */
341: ic->tme_m68k_ireg_a7 -= sizeof(fmtB);
342: ic->_tme_m68k_ea_address = ic->tme_m68k_ireg_a7;
343: ic->_tme_m68k_ea_function_code = TME_M68K_FC_SD; /* XXX right? */
344: tme_m68k_write_mem(ic, (tme_uint8_t *) &fmtB, sizeof(fmtB));
345:
346: /* now finish the processing for this exception: */
347: tme_m68k_exception_process_finish(ic, TME_M68K_FORMAT_B,
348: ((exceptions & TME_M68K_EXCEPTION_BERR)
349: ? TME_M68K_VECTOR_BERR
350: : TME_M68K_VECTOR_AERR));
351: ic->_tme_m68k_exceptions = (exceptions &= ~ (TME_M68K_EXCEPTION_AERR
352: | TME_M68K_EXCEPTION_BERR));
353: }
354:
355: /* do normal exception processing: */
356: tme_m68020_exception_process(ic);
357: /* NOTREACHED */
358: }
359:
360: /* m68020 RTE processing: */
361: static void
362: _tme_m68020_rte(struct tme_m68k *ic)
363: {
364: tme_uint16_t format;
365: struct tme_m68k_fmtB fmtB;
366: tme_uint32_t fmtB_address;
367: /* one 16-bit word for each 16-bit internal register word in the format 0xB frame: */
368: tme_uint8_t raw_state[(1 + 2 + 4 + 2 + 3 + 18) * sizeof(tme_uint16_t)], *raw;
369: unsigned int raw_avail, raw_used;
370: tme_uint8_t function_code;
371: tme_uint16_t ssw;
372: unsigned int flags;
373: const tme_uint8_t *ib;
374: unsigned int buffer_size;
375:
376: /* start the RTE: */
377: format = tme_m68k_rte_start(ic);
378:
379: /* if this is a format 0 or format two stack frame, finish it now: */
380: if (format == TME_M68K_FORMAT_0
381: || format == TME_M68K_FORMAT_2) {
382: ic->_tme_m68k_mode = TME_M68K_MODE_EXECUTION;
383: TME_M68K_SEQUENCE_START;
384: tme_m68k_rte_finish(ic, (format == TME_M68K_FORMAT_2
385: ? sizeof(ic->tme_m68k_ireg_pc_last)
386: : 0));
387: /* NOTREACHED */
388: }
389:
390: /* if this is a format one stack frame: */
391: if (format == TME_M68K_FORMAT_1) {
392:
393: /* "For the throwaway four-word frame, the processor reads the SR
394: value from the frame, increments the active stack pointer by 8,
395: updates the SR with the value read from the stack, and then
396: begins RTE processing again" */
397: ic->tme_m68k_ireg_a7 += 8;
398: tme_m68k_change_sr(ic, ic->tme_m68k_ireg_shadow_sr);
399: TME_M68K_SEQUENCE_START;
400: tme_m68k_redispatch(ic);
401: /* NOTREACHED */
402: }
403:
404: /* whenever we detect a format error, begin exception processing
405: for a format error. we have to back the PC up by the size of the
406: RTE instruction so the PC points to it: */
407: #define FORMAT_ERROR_IF(e) \
408: do { \
409: if (e) { \
410: ic->tme_m68k_ireg_pc -= sizeof(tme_uint16_t); \
411: tme_m68k_exception(ic, TME_M68K_EXCEPTION_INST(TME_M68K_VECTOR_FORMAT));\
412: /* NOTREACHED */ \
413: } \
414: } while (/* CONSTCOND */ 0)
415:
416: /* this frame must be a format 0xB frame: */
417: FORMAT_ERROR_IF(format != TME_M68K_FORMAT_B);
418:
419: /* do a read of the last word in the stack frame to determine
420: accessibility. we rely on tme_m68k_rte_start leaving
421: ic->_tme_m68k_ea_address pointing after the format/offset word: */
422: fmtB_address = ic->_tme_m68k_ea_address;
423: ic->_tme_m68k_ea_address += sizeof(fmtB) - sizeof(tme_uint32_t);
424: tme_m68k_read_memx32(ic);
425:
426: /* read in the format 0xB information. if we get a bus error
427: during this operation it's a double fault: */
428: assert(ic->_tme_m68k_exceptions == 0);
429: ic->_tme_m68k_exceptions = TME_M68K_EXCEPTION_BERR;
430: ic->_tme_m68k_ea_address = fmtB_address;
431: tme_m68k_read_mem(ic, (tme_uint8_t *) &fmtB, sizeof(fmtB));
432: ic->_tme_m68k_exceptions = 0;
433:
434: /* reset the input and output buffers: */
435: ic->_tme_m68k_group0_buffer_read_size = 0;
436: ic->_tme_m68k_group0_buffer_read_softrr = 0;
437: ic->_tme_m68k_group0_buffer_write_size = 0;
438: ic->_tme_m68k_group0_buffer_write_softrr = 0;
439:
440: /* get out the SSW: */
441: ssw = tme_betoh_u16(fmtB.tme_m68k_fmtB_ssw);
442:
443: /* initialize the flags: */
444: flags = 0;
445:
446: /* initialize the buffer size: */
447: buffer_size = 0;
448:
449: /* initialize the input buffer: */
450: ib = NULL;
451:
452: /* if this was an instruction fetch: */
453: if (ssw & (TME_M68K_SSWB_FC | TME_M68K_SSWB_FB)) {
454:
455: /* we don't generate bus errors that only fault on stage B: */
456: if ((ssw & (TME_M68K_SSWB_FC | TME_M68K_SSWB_FB)) == TME_M68K_SSWB_FB) {
457: abort();
458: }
459:
460: /* if we faulted on both stages, we must be rerunning both or not
461: rerunning both. since we already know we either faulted only on
462: stage C, or we faulted on both, if we faulted on stage B check
463: that both RB and RC have the same value: */
464: if ((ssw & TME_M68K_SSWB_FB)
465: && !(ssw & TME_M68K_SSWB_RC) != !(ssw & TME_M68K_SSWB_RB)) {
466: abort();
467: }
468:
469: /* note that this was an instruction fetch: */
470: flags |= TME_M68K_BUS_CYCLE_FETCH;
471:
472: /* get out the function code: */
473: ic->_tme_m68k_group0_function_code
474: = ((ic->tme_m68k_ireg_shadow_sr & TME_M68K_FLAG_S)
475: ? TME_M68K_FC_SP
476: : TME_M68K_FC_UP);
477:
478: /* get out the fault address: */
479: ic->_tme_m68k_group0_address = tme_betoh_u32(fmtB.tme_m68k_fmtB_addr_B) - sizeof(fmtB.tme_m68k_fmtB_ipipe_C);
480:
481: /* if the user reran this cycle: */
482: if (!(ssw & TME_M68K_SSWB_RC)) {
483:
484: /* set the input buffer pointer: */
485: /* NB that for 32-bit fetches, this relies on the fact that the
486: stage B word comes immediately after the stage C word in the
487: frame: */
488: ib = (const tme_uint8_t *) &fmtB.tme_m68k_fmtB_ipipe_C;
489: }
490:
491: /* if this is a fault only on stage C: */
492: if (!(ssw & TME_M68K_SSWB_FB)) {
493:
494: /* set the input buffer size: */
495: buffer_size = sizeof(tme_uint16_t);
496: }
497:
498: /* otherwise, if this is a fault on stages C and B: */
499: else {
500:
501: /* set the input buffer size: */
502: buffer_size = sizeof(tme_uint32_t);
503: }
504: }
505:
506: /* otherwise, this was a data access: */
507: else {
508:
509: /* get out the function code: */
510: ic->_tme_m68k_group0_function_code = ssw & TME_M68K_FC_7;
511:
512: /* get out the fault address: */
513: ic->_tme_m68k_group0_address = tme_betoh_u32(fmtB.tme_m68k_fmtB_addr);
514:
515: /* get out the size: */
516: switch (ssw & TME_M68K_SSWB_SIZE_MASK) {
517: case TME_M68K_SSWB_SIZE_1: buffer_size = 1; break;
518: case TME_M68K_SSWB_SIZE_2: buffer_size = 2; break;
519: case TME_M68K_SSWB_SIZE_3: buffer_size = 3; break;
520: case TME_M68K_SSWB_SIZE_4: buffer_size = 4; break;
521: }
522:
523: /* if this was a read cycle: */
524: if (ssw & TME_M68K_SSWB_RW) {
525:
526: /* mark that this was a read cycle: */
527: flags |= TME_M68K_BUS_CYCLE_READ;
528:
529: /* if the user reran this cycle: */
530: if (!(ssw & TME_M68K_SSWB_DF)) {
531:
532: /* set the input buffer pointer: */
533: ib = &fmtB.tme_m68k_fmtB_dib[0];
534: }
535: }
536:
537: /* otherwise, this was a write cycle: */
538: else {
539:
540: /* if the user reran this cycle, note that, otherwise
541: copy in the data output buffer: */
542: if (!(ssw & TME_M68K_SSWB_DF)) {
543: ic->_tme_m68k_group0_buffer_write_softrr = buffer_size;
544: }
545: else {
546: memcpy(ic->_tme_m68k_group0_buffer_write,
547: fmtB.tme_m68k_fmtB_dob + sizeof(fmtB.tme_m68k_fmtB_dob) - buffer_size,
548: buffer_size);
549: ic->_tme_m68k_group0_buffer_write_size = buffer_size;
550: }
551: }
552: }
553:
554: /* if the user reran this instruction fetch or data read cycle, read
555: in the appropriate input buffer: */
556: if (ib != NULL) {
557: memcpy(ic->_tme_m68k_group0_buffer_read,
558: ib + sizeof(fmtB.tme_m68k_fmtB_dib) - buffer_size,
559: buffer_size);
560: ic->_tme_m68k_group0_buffer_read_softrr = buffer_size;
561: ic->_tme_m68k_group0_buffer_read_size = buffer_size;
562: }
563:
564: /* get out our internal state: */
565: raw = raw_state;
566: raw_avail = sizeof(raw_state);
567: #define RAW_GET(f) \
568: do { \
569: raw_used = TME_MIN(sizeof(f), raw_avail); \
570: memcpy(raw, f, raw_used); \
571: raw += raw_used; \
572: raw_avail -= raw_used; \
573: } while (/* CONSTCOND */ 0)
574:
575: /* use all of the reserved regions: */
576: RAW_GET(fmtB.tme_m68k_fmtB_state0);
577: RAW_GET(fmtB.tme_m68k_fmtB_state1);
578: RAW_GET(fmtB.tme_m68k_fmtB_state2);
579: RAW_GET(fmtB.tme_m68k_fmtB_state3);
580: RAW_GET(fmtB.tme_m68k_fmtB_state4);
581: RAW_GET(fmtB.tme_m68k_fmtB_state5);
582: #undef RAW_GET
583:
584: /* take apart the internal state: */
585: raw = raw_state;
586: raw_avail = sizeof(raw_state) - raw_avail;
587: #define RAW_GET(v) \
588: do { \
589: FORMAT_ERROR_IF(raw_avail < sizeof(v)); \
590: memcpy(&v, raw, sizeof(v)); \
591: raw += sizeof(v); \
592: raw_avail -= sizeof(v); \
593: } while (/* CONSTCOND */ 0)
594:
595: /* get out the sequence: */
596: raw_used = tme_m68k_sequence_fill(ic, raw, raw_avail);
597: FORMAT_ERROR_IF(raw_used < 0);
598: raw += raw_used;
599: raw_avail -= raw_used;
600:
601: /* dispatch on the mode: */
602: switch (ic->_tme_m68k_group0_sequence._tme_m68k_sequence_mode) {
603:
604: case TME_M68K_MODE_EXECUTION:
605:
606: /* get out the instruction buffer: */
607: raw_used = tme_m68k_insn_buffer_fill(ic, raw, raw_avail);
608: FORMAT_ERROR_IF(raw_used < 0);
609: raw += raw_used;
610: raw_avail -= raw_used;
611:
612: /* get out the EA address: */
613: RAW_GET(function_code);
614: ic->_tme_m68k_ea_function_code = function_code;
615: RAW_GET(ic->_tme_m68k_ea_address);
616:
617: /* get out the memory X, Y, and Z buffers: */
618: RAW_GET(ic->tme_m68k_ireg_memx32);
619: RAW_GET(ic->tme_m68k_ireg_memy32);
620: RAW_GET(ic->tme_m68k_ireg_memz32);
621:
622: /* done: */
623: break;
624:
625: case TME_M68K_MODE_EXCEPTION:
626:
627: /* get out the exceptions set: */
628: RAW_GET(ic->_tme_m68k_exceptions);
629:
630: /* get out the shadow status register: */
631: RAW_GET(ic->tme_m68k_ireg_shadow_sr);
632:
633: /* get out the last PC: */
634: RAW_GET(ic->tme_m68k_ireg_pc_last);
635:
636: /* done: */
637: break;
638:
639: case TME_M68K_MODE_RTE:
640:
641: /* get out the shadow status register: */
642: RAW_GET(ic->tme_m68k_ireg_shadow_sr);
643:
644: /* get out the next program counter: */
645: RAW_GET(ic->tme_m68k_ireg_pc_next);
646:
647: /* get out the format/offset word: */
648: RAW_GET(ic->tme_m68k_ireg_format_offset);
649:
650: break;
651:
652: default: FORMAT_ERROR_IF(TRUE);
653: }
654:
655: /* finish the RTE: */
656: ic->_tme_m68k_sequence = ic->_tme_m68k_group0_sequence;
657: TME_M68K_SEQUENCE_RESTART;
658: tme_m68k_rte_finish(ic, sizeof(fmtB));
659: /* NOTREACHED */
660: }
661:
662: /* this creates and returns a new m68020: */
663: TME_ELEMENT_X_NEW_DECL(tme_ic_,m68k,m68020) {
664: struct tme_m68k *ic;
665:
666: /* allocate the m68k structure: */
667: ic = tme_new0(struct tme_m68k, 1);
668: ic->tme_m68k_element = element;
669:
670: /* fill in the m68020-specific parts of the structure: */
671: ic->tme_m68k_type = TME_M68K_M68020;
672: ic->_tme_m68k_mode_execute = _tme_m68020_execute;
673: ic->_tme_m68k_mode_exception = _tme_m68020_exception;
674: ic->_tme_m68k_mode_rte = _tme_m68020_rte;
675: tme_m68k_opcodes_init_m68020(tme_m68k_opcodes_m68020);
676:
677: /* call the common m68k new function: */
678: return (tme_m68k_new(ic, args, extra, _output));
679: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.