|
|
1.1 root 1: /***************************************************************************
2:
3: i860.c
4:
5: Interface file for the Intel i860 emulator.
6:
7: Copyright (C) 1995-present Jason Eckhardt ([email protected])
8: Released for general non-commercial use under the MAME license
9: with the additional requirement that you are free to use and
10: redistribute this code in modified or unmodified form, provided
11: you list me in the credits.
12: Visit http://mamedev.org for licensing and usage restrictions.
13:
14: Changes for previous/NeXTdimension by Simon Schubiger (SC)
15:
16: ***************************************************************************/
17:
18: #include <stdio.h>
19: #include <stdlib.h>
20: #include <string.h>
21: #include <math.h>
22: #include <assert.h>
23: #include "i860.hpp"
24:
25: static i860_cpu_device nd_i860;
26:
27: extern "C" {
28: void nd_i860_init() {
29: nd_i860.init();
30: }
31:
32: void nd_i860_uninit() {
33: nd_i860.uninit();
34: }
35:
36: int nd_speed_hack;
37:
38: void nd_set_speed_hack(int state) {
39: nd_speed_hack = state;
40: }
41:
42: void nd_start_debugger(void) {
43: nd_i860.send_msg(MSG_DBG_BREAK);
44: }
45:
46: static int checklock_cnt = 0;
47: void i860_Run(int nHostCycles) {
48: #if ENABLE_PERF_COUNTERS
49: nd_i860.m_m68k_cylces += nHostCycles;
50: #endif
51: #if ENABLE_I860_THREAD
52: if(nd_speed_hack) {
53: // while spped-hack is on, slow down m68k a bit
54: for(int i = 10; --i >= 0;)
55: checklock(&nd_i860.m_debugger_lock);
56: }
57: if(checklock_cnt <= 0) {
58: checklock(&nd_i860.m_debugger_lock);
59: // optimzation: check the debugger lock only all 10000 cycles
60: checklock_cnt = 10000;
61: }
62: else
63: checklock_cnt -= nHostCycles;
64: #else
65: nd_i860.handle_msgs();
66:
67: if(nd_i860.is_halted()) return;
68:
69: if (nd_speed_hack) {
70: while(nHostCycles) {
71: nd_i860.run_cycle();
72: nHostCycles -= 2;
73: }
74: } else
75: nd_i860.run_cycle();
76: #endif
77: nd_nbic_interrupt();
78: }
79:
80: int i860_thread(void* data) {
81: ((i860_cpu_device*)data)->run();
82: return 0;
83: }
84:
85: void i860_reset() {
86: nd_i860.send_msg(MSG_I860_RESET);
87: }
88:
89: void i860_tick(bool intr) {
90: nd_i860.tick(intr);
91: }
92: }
93:
94: i860_cpu_device::i860_cpu_device() {
95: #if ENABLE_I860_THREAD
96: m_thread = NULL;
97: #endif
98: #if ENABLE_PERF_COUNTERS
99: dump_reset_perfc();
100: #endif
101: m_halt = true;
102: }
103:
104: void i860_cpu_device::set_mem_access(bool be) {
105: if(be) {
106: rdmem[1] = nd_board_rd8_be;
107: rdmem[2] = nd_board_rd16_be;
108: rdmem[4] = nd_board_rd32_be;
109: rdmem[8] = nd_board_rd64_be;
110: rdmem[16] = nd_board_rd128_be;
111:
112: wrmem[1] = nd_board_wr8_be;
113: wrmem[2] = nd_board_wr16_be;
114: wrmem[4] = nd_board_wr32_be;
115: wrmem[8] = nd_board_wr64_be;
116: wrmem[16] = nd_board_wr128_be;
117: } else {
118: rdmem[1] = nd_board_rd8_le;
119: rdmem[2] = nd_board_rd16_le;
120: rdmem[4] = nd_board_rd32_le;
121: rdmem[8] = nd_board_rd64_le;
122: rdmem[16] = nd_board_rd128_le;
123:
124: wrmem[1] = nd_board_wr8_le;
125: wrmem[2] = nd_board_wr16_le;
126: wrmem[4] = nd_board_wr32_le;
127: wrmem[8] = nd_board_wr64_le;
128: wrmem[16] = nd_board_wr128_le;
129: }
130: }
131:
132: inline UINT8 i860_cpu_device::rdcs8(UINT32 addr) {
133: return nd_board_cs8get(addr);
134: }
135:
136: inline UINT32 i860_cpu_device::get_iregval(int gr) {
137: return m_iregs[gr];
138: }
139:
140: inline void i860_cpu_device::set_iregval(int gr, UINT32 val) {
141: m_iregs[gr] = val;
142: m_iregs[0] = 0; // make sure r0 is always 0
143: }
144:
145: inline float i860_cpu_device::get_fregval_s (int fr) {
146: return *(float*)(&m_fregs[fr * 4]);
147: }
148:
149: inline void i860_cpu_device::set_fregval_s (int fr, float s) {
150: if(fr > 1)
151: *(float*)(&m_fregs[fr * 4]) = s;
152: }
153:
154: inline double i860_cpu_device::get_fregval_d (int fr) {
155: return *(double*)(&m_fregs[fr * 4]);
156: }
157:
158: inline void i860_cpu_device::set_fregval_d (int fr, double d) {
159: if(fr > 1)
160: *(double*)(&m_fregs[fr * 4]) = d;
161: }
162:
163: inline void i860_cpu_device::SET_PSR_CC(int val) {
164: if(!(m_dim_cc_valid))
165: m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 2)) | ((val & 1) << 2);
166: }
167:
168: void i860_cpu_device::send_msg(int msg) {
169: lock(&m_port_lock);
170: m_port |= msg;
171: unlock(&m_port_lock);
172: }
173:
174: void i860_cpu_device::handle_trap(UINT32 savepc) {
175: static char buffer[256];
176: buffer[0] = 0;
177: strcat(buffer, "TRAP");
178: if(m_flow & TRAP_NORMAL) strcat(buffer, " [Normal]");
179: if(m_flow & TRAP_IN_DELAY_SLOT) strcat(buffer, " [Delay Slot]");
180: if(m_flow & TRAP_WAS_EXTERNAL) strcat(buffer, " [External]");
181: if(!(GET_PSR_IT() || GET_PSR_FT() || GET_PSR_IAT() || GET_PSR_DAT() || GET_PSR_IN()))
182: strcat(buffer, " >Reset<");
183: else {
184: if(GET_PSR_IT()) strcat(buffer, " >Instruction Fault<");
185: if(GET_PSR_FT()) strcat(buffer, " >Floating Point Fault<");
186: if(GET_PSR_IAT()) strcat(buffer, " >Instruction Access Fault<");
187: if(GET_PSR_DAT()) strcat(buffer, " >Data Access Fault<");
188: if(GET_PSR_IN()) strcat(buffer, " >Interrupt<");
189: }
190:
191: if(!(m_single_stepping) && !((GET_PSR_IAT() || GET_PSR_DAT() || GET_PSR_IN())))
192: debugger('d', buffer);
193:
194: if(m_dim)
195: Log_Printf(LOG_WARN, "[i860] Trap while DIM %s pc=%08X m_flow=%08X", buffer, savepc, m_flow);
196:
197: /* If we need to trap, change PC to trap address.
198: Also set supervisor mode, copy U and IM to their
199: previous versions, clear IM. */
200: if(m_flow & TRAP_WAS_EXTERNAL) {
201: if (GET_PC_UPDATED()) {
202: m_cregs[CR_FIR] = m_pc;
203: } else {
204: m_cregs[CR_FIR] = savepc + 4;
205: }
206: }
207: else if (m_flow & TRAP_IN_DELAY_SLOT) {
208: m_cregs[CR_FIR] = savepc + 4;
209: }
210: else
211: m_cregs[CR_FIR] = savepc;
212:
213: m_flow |= FIR_GETS_TRAP;
214: SET_PSR_PU (GET_PSR_U ());
215: SET_PSR_PIM (GET_PSR_IM ());
216: SET_PSR_U (0);
217: SET_PSR_IM (0);
218: SET_PSR_DIM (0);
219: SET_PSR_DS (0);
220:
221: m_save_flow = m_flow & DIM_OP;
222: m_save_dim = m_dim;
223: m_save_cc = m_dim_cc;
224: m_save_cc_valid = m_dim_cc_valid;
225:
226: m_dim = DIM_NONE;
227: m_dim_cc = false;
228: m_dim_cc_valid = false;
229:
230: m_pc = 0xffffff00;
231: }
232:
233: void i860_cpu_device::ret_from_trap() {
234: m_flow |= m_save_flow & ~DIM_OP;
235: m_dim = m_save_dim;
236: m_flow &= ~FIR_GETS_TRAP;
237: m_dim_cc = m_save_cc;
238: m_dim_cc_valid = m_save_cc_valid;
239: }
240:
241: void i860_cpu_device::run_cycle() {
242: CLEAR_FLOW();
243: m_dim_cc_valid = false;
244: m_flow &= ~DIM_OP;
245: UINT64 insn64 = ifetch64(m_pc);
246:
247: if(!(m_pc & 4)) {
248: UINT32 savepc = m_pc;
249:
250: #if ENABLE_DEBUGGER
251: if(m_single_stepping) debugger(0,0);
252: #endif
253:
254: UINT32 insnLow = insn64;
255: if(insnLow == INSN_FNOP_DIM) {
256: if(m_dim) m_flow |= DIM_OP;
257: else m_flow &= ~DIM_OP;
258: } else if((insnLow & INSN_MASK_DIM) == INSN_FP_DIM)
259: m_flow |= DIM_OP;
260:
261: decode_exec(insnLow);
262:
263: if (PENDING_TRAP()) {
264: handle_trap(savepc);
265: goto done;
266: } else if(GET_PC_UPDATED()) {
267: goto done;
268: } else {
269: // If the PC wasn't updated by a control flow instruction, just bump to next sequential instruction.
270: m_pc += 4;
271: CLEAR_FLOW();
272: }
273: }
274:
275: if(m_pc & 4) {
276: UINT32 savepc = m_pc;
277:
278: #if ENABLE_DEBUGGER
279: if(m_single_stepping && !(m_dim)) debugger(0,0);
280: #endif
281:
282: UINT32 insnHigh= insn64 >> 32;
283: decode_exec(insnHigh);
284:
285: // only check for external interrupts
286: // - on high-word (speedup)
287: // - not DIM (safety :-)
288: // - when no other traps are pending
289: if(!(m_dim) && !(PENDING_TRAP())) {
290: if(m_flow & EXT_INTR) {
291: m_flow &= ~EXT_INTR;
292: gen_interrupt();
293: } else
294: clr_interrupt();
295: }
296:
297: if (PENDING_TRAP()) {
298: handle_trap(savepc);
299: } else if (GET_PC_UPDATED()) {
300: goto done;
301: } else {
302: // If the PC wasn't updated by a control flow instruction, just bump to next sequential instruction.
303: m_pc += 4;
304: }
305: }
306: done:
307: switch (m_dim) {
308: case DIM_NONE:
309: if(m_flow & DIM_OP)
310: m_dim = DIM_TEMP;
311: break;
312: case DIM_TEMP:
313: m_dim = m_flow & DIM_OP ? DIM_FULL : DIM_NONE;
314: break;
315: case DIM_FULL:
316: if(!(m_flow & DIM_OP))
317: m_dim = DIM_TEMP;
318: break;
319: }
320: }
321:
322: int i860_cpu_device::memtest(bool be) {
323: const UINT32 P_TEST_ADDR = 0x28000000; // assume ND in slot 2
324:
325: m_cregs[CR_DIRBASE] = 0; // turn VM off
326:
327: const UINT8 uint8 = 0x01;
328: const UINT16 uint16 = 0x0123;
329: const UINT32 uint32 = 0x01234567;
330: const UINT64 uint64 = 0x0123456789ABCDEFLL;
331:
332: UINT8 tmp8;
333: UINT16 tmp16;
334: UINT32 tmp32;
335:
336: int err = be ? 20000 : 30000;
337:
338: // intel manual example
339: SET_EPSR_BE(0);
340: set_mem_access(false);
341:
342: tmp8 = 'A'; wrmem[1](P_TEST_ADDR+0, (UINT32*)&tmp8);
343: tmp8 = 'B'; wrmem[1](P_TEST_ADDR+1, (UINT32*)&tmp8);
344: tmp8 = 'C'; wrmem[1](P_TEST_ADDR+2, (UINT32*)&tmp8);
345: tmp8 = 'D'; wrmem[1](P_TEST_ADDR+3, (UINT32*)&tmp8);
346: tmp8 = 'E'; wrmem[1](P_TEST_ADDR+4, (UINT32*)&tmp8);
347: tmp8 = 'F'; wrmem[1](P_TEST_ADDR+5, (UINT32*)&tmp8);
348: tmp8 = 'G'; wrmem[1](P_TEST_ADDR+6, (UINT32*)&tmp8);
349: tmp8 = 'H'; wrmem[1](P_TEST_ADDR+7, (UINT32*)&tmp8);
350:
351: rdmem[1](P_TEST_ADDR+0, (UINT32*)&tmp8); if(tmp8 != 'A') return err + 100;
352: rdmem[1](P_TEST_ADDR+1, (UINT32*)&tmp8); if(tmp8 != 'B') return err + 101;
353: rdmem[1](P_TEST_ADDR+2, (UINT32*)&tmp8); if(tmp8 != 'C') return err + 102;
354: rdmem[1](P_TEST_ADDR+3, (UINT32*)&tmp8); if(tmp8 != 'D') return err + 103;
355: rdmem[1](P_TEST_ADDR+4, (UINT32*)&tmp8); if(tmp8 != 'E') return err + 104;
356: rdmem[1](P_TEST_ADDR+5, (UINT32*)&tmp8); if(tmp8 != 'F') return err + 105;
357: rdmem[1](P_TEST_ADDR+6, (UINT32*)&tmp8); if(tmp8 != 'G') return err + 106;
358: rdmem[1](P_TEST_ADDR+7, (UINT32*)&tmp8); if(tmp8 != 'H') return err + 107;
359:
360: rdmem[2](P_TEST_ADDR+0, (UINT32*)&tmp16); if(tmp16 != (('B'<<8)|('A'))) return err + 110;
361: rdmem[2](P_TEST_ADDR+2, (UINT32*)&tmp16); if(tmp16 != (('D'<<8)|('C'))) return err + 111;
362: rdmem[2](P_TEST_ADDR+4, (UINT32*)&tmp16); if(tmp16 != (('F'<<8)|('E'))) return err + 112;
363: rdmem[2](P_TEST_ADDR+6, (UINT32*)&tmp16); if(tmp16 != (('H'<<8)|('G'))) return err + 113;
364:
365: rdmem[4](P_TEST_ADDR+0, &tmp32); if(tmp32 != (('D'<<24)|('C'<<16)|('B'<<8)|('A'))) return err + 120;
366: rdmem[4](P_TEST_ADDR+4, &tmp32); if(tmp32 != (('H'<<24)|('G'<<16)|('F'<<8)|('E'))) return err + 121;
367:
368: SET_EPSR_BE(1);
369: set_mem_access(true);
370:
371: rdmem[1](P_TEST_ADDR+0, (UINT32*)&tmp8); if(tmp8 != 'H') return err + 200;
372: rdmem[1](P_TEST_ADDR+1, (UINT32*)&tmp8); if(tmp8 != 'G') return err + 201;
373: rdmem[1](P_TEST_ADDR+2, (UINT32*)&tmp8); if(tmp8 != 'F') return err + 202;
374: rdmem[1](P_TEST_ADDR+3, (UINT32*)&tmp8); if(tmp8 != 'E') return err + 203;
375: rdmem[1](P_TEST_ADDR+4, (UINT32*)&tmp8); if(tmp8 != 'D') return err + 204;
376: rdmem[1](P_TEST_ADDR+5, (UINT32*)&tmp8); if(tmp8 != 'C') return err + 205;
377: rdmem[1](P_TEST_ADDR+6, (UINT32*)&tmp8); if(tmp8 != 'B') return err + 206;
378: rdmem[1](P_TEST_ADDR+7, (UINT32*)&tmp8); if(tmp8 != 'A') return err + 207;
379:
380: rdmem[2](P_TEST_ADDR+0, (UINT32*)&tmp16); if(tmp16 != (('H'<<8)|('G'))) return err + 210;
381: rdmem[2](P_TEST_ADDR+2, (UINT32*)&tmp16); if(tmp16 != (('F'<<8)|('E'))) return err + 211;
382: rdmem[2](P_TEST_ADDR+4, (UINT32*)&tmp16); if(tmp16 != (('D'<<8)|('C'))) return err + 212;
383: rdmem[2](P_TEST_ADDR+6, (UINT32*)&tmp16); if(tmp16 != (('B'<<8)|('A'))) return err + 213;
384:
385: rdmem[4](P_TEST_ADDR+0, &tmp32); if(tmp32 != (('H'<<24)|('G'<<16)|('F'<<8)|('E'))) return err + 220;
386: rdmem[4](P_TEST_ADDR+4, &tmp32); if(tmp32 != (('D'<<24)|('C'<<16)|('B'<<8)|('A'))) return err + 221;
387:
388: // some register and mem r/w tests
389:
390: SET_EPSR_BE(be);
391: set_mem_access(be);
392:
393: wrmem[1](P_TEST_ADDR, (UINT32*)&uint8);
394: rdmem[1](P_TEST_ADDR, (UINT32*)&tmp8);
395: if(tmp8 != 0x01) return err;
396:
397: wrmem[2](P_TEST_ADDR, (UINT32*)&uint16);
398: rdmem[2](P_TEST_ADDR, (UINT32*)&tmp16);
399: if(tmp16 != 0x0123) return err+1;
400:
401: wrmem[4](P_TEST_ADDR, &uint32);
402: rdmem[4](P_TEST_ADDR, &tmp32); if(tmp32 != 0x01234567) return err+2;
403:
404: readmem_emu(P_TEST_ADDR, 4, (UINT8*)&uint32);
405: if(uint32 != 0x01234567) return err+3;
406:
407: writemem_emu(P_TEST_ADDR, 4, (UINT8*)&uint32, 0xff);
408: rdmem[4](P_TEST_ADDR+0, &tmp32); if(tmp32 != 0x01234567) return err+4;
409:
410: UINT8* uint8p = (UINT8*)&uint64;
411: set_fregval_d(2, *((double*)uint8p));
412: writemem_emu(P_TEST_ADDR, 8, &m_fregs[8], 0xff);
413: readmem_emu (P_TEST_ADDR, 8, &m_fregs[8]);
414: *((double*)&uint64) = get_fregval_d(2);
415: if(uint64 != 0x0123456789ABCDEFLL) return err+5;
416:
417: UINT32 lo;
418: UINT32 hi;
419:
420: rdmem[4](P_TEST_ADDR+0, &lo);
421: rdmem[4](P_TEST_ADDR+4, &hi);
422:
423: if(lo != 0x01234567) return err+6;
424: if(hi != 0x89ABCDEF) return err+7;
425:
426: return 0;
427: }
428:
429: void i860_cpu_device::init() {
430: /* Configurations - keep in sync with i860cfg.h */
431: static const char* CFGS[8];
432: for(int i = 0; i < 8; i++) CFGS[i] = "Unknown emulator configuration";
433: CFGS[CONF_I860_SPEED] = CONF_STR(CONF_I860_SPEED);
434: CFGS[CONF_I860_DEV] = CONF_STR(CONF_I860_DEV);
435: CFGS[CONF_I860_NO_THREAD] = CONF_STR(CONF_I860_NO_THREAD);
436: Log_Printf(LOG_WARN, "[i860] Emulator configured for %s", CFGS[CONF_I860]);
437:
438: m_single_stepping = 0;
439: m_lastcmd = 0;
440: m_console_idx = 0;
441: m_break_on_next_msg = false;
442: m_dim = DIM_NONE;
443: m_traceback_idx = 0;
444:
445: set_mem_access(false);
446:
447: // some sanity checks for endianess
448: int err = 0;
449: {
450: UINT32 uint32 = 0x01234567;
451: UINT8* uint8p = (UINT8*)&uint32;
452: if(uint8p[3] != 0x01) {err = 1; goto error;}
453: if(uint8p[2] != 0x23) {err = 2; goto error;}
454: if(uint8p[1] != 0x45) {err = 3; goto error;}
455: if(uint8p[0] != 0x67) {err = 4; goto error;}
456:
457: for(int i = 0; i < 32; i++) {
458: uint8p[3] = i;
459: set_fregval_s(i, *((float*)uint8p));
460: }
461: if(get_fregval_s(0) != 0) {err = 198; goto error;}
462: if(get_fregval_s(1) != 0) {err = 199; goto error;}
463: for(int i = 2; i < 32; i++) {
464: uint8p[3] = i;
465: if(get_fregval_s(i) != *((float*)uint8p))
466: {err = 100+i; goto error;}
467: }
468: for(int i = 2; i < 32; i++) {
469: if(m_fregs[i*4+3] != i) {err = 200+i; goto error;}
470: if(m_fregs[i*4+2] != 0x23) {err = 200+i; goto error;}
471: if(m_fregs[i*4+1] != 0x45) {err = 200+i; goto error;}
472: if(m_fregs[i*4+0] != 0x67) {err = 200+i; goto error;}
473: }
474: }
475:
476: {
477: UINT64 uint64 = 0x0123456789ABCDEFLL;
478: UINT8* uint8p = (UINT8*)&uint64;
479: if(uint8p[7] != 0x01) {err = 10001; goto error;}
480: if(uint8p[6] != 0x23) {err = 10002; goto error;}
481: if(uint8p[5] != 0x45) {err = 10003; goto error;}
482: if(uint8p[4] != 0x67) {err = 10004; goto error;}
483: if(uint8p[3] != 0x89) {err = 10005; goto error;}
484: if(uint8p[2] != 0xAB) {err = 10006; goto error;}
485: if(uint8p[1] != 0xCD) {err = 10007; goto error;}
486: if(uint8p[0] != 0xEF) {err = 10008; goto error;}
487:
488: for(int i = 0; i < 16; i++) {
489: uint8p[7] = i;
490: set_fregval_d(i*2, *((double*)uint8p));
491: }
492: if(get_fregval_d(0) != 0)
493: {err = 10199; goto error;}
494: for(int i = 1; i < 16; i++) {
495: uint8p[7] = i;
496: if(get_fregval_d(i*2) != *((double*)uint8p))
497: {err = 10100+i; goto error;}
498: }
499: for(int i = 2; i < 32; i += 2) {
500: float hi = get_fregval_s(i+1);
501: float lo = get_fregval_s(i+0);
502: if((*(UINT32*)&hi) != (0x00234567 | (i<<23))) {err = 10100+i; goto error;}
503: if((*(UINT32*)&lo) != 0x89ABCDEF) {err = 10100+i; goto error;}
504: }
505: for(int i = 1; i < 16; i++) {
506: if(m_fregs[i*8+7] != i) {err = 10200+i; goto error;}
507: if(m_fregs[i*8+6] != 0x23) {err = 10200+i; goto error;}
508: if(m_fregs[i*8+5] != 0x45) {err = 10200+i; goto error;}
509: if(m_fregs[i*8+4] != 0x67) {err = 10200+i; goto error;}
510: if(m_fregs[i*8+3] != 0x89) {err = 10200+i; goto error;}
511: if(m_fregs[i*8+2] != 0xAB) {err = 10200+i; goto error;}
512: if(m_fregs[i*8+1] != 0xCD) {err = 10200+i; goto error;}
513: if(m_fregs[i*8+0] != 0xEF) {err = 10200+i; goto error;}
514: }
515: }
516:
517: err = memtest(true); if(err) goto error;
518: err = memtest(false); if(err) goto error;
519:
520: error:
521: if(err) {
522: fprintf(stderr, "NeXTdimension i860 emulator requires a little-endian host. This system seems to be big endian. Error %d. Exiting.\n", err);
523: fflush(stderr);
524: exit(err);
525: }
526:
527: send_msg(MSG_I860_RESET);
528: #if ENABLE_I860_THREAD
529: m_thread = thread_create(i860_thread, this);
530: #endif
531: }
532:
533: void i860_cpu_device::uninit() {
534: if(is_halted()) return;
535:
536: halt(true);
537: send_msg(MSG_I860_KILL);
538: #if ENABLE_I860_THREAD
539: if(m_thread) {
540: thread_wait(m_thread);
541: m_thread = NULL;
542: }
543: send_msg(MSG_NONE);
544: #endif
545: }
546:
547: /* Message disaptcher - executed on i860 thread, safe to call i860 methods */
548: bool i860_cpu_device::handle_msgs() {
549: lock(&m_port_lock);
550: int msg = m_port;
551: m_port = 0;
552: unlock(&m_port_lock);
553:
554: if(msg & MSG_I860_KILL)
555: return false;
556: if(msg & MSG_I860_RESET)
557: reset();
558: else if(msg & MSG_INTR)
559: intr();
560: if(msg & MSG_DBG_BREAK)
561: debugger('d', "BREAK at pc=%08X", m_pc);
562: return true;
563: }
564:
565: void i860_cpu_device::run() {
566: while(handle_msgs()) {
567:
568: /* Sleep a bit if halted */
569: if(is_halted()) {
570: sleep_ms(100);
571: continue;
572: }
573:
574: /* Run some i860 cycles before re-checking messages*/
575: for(int i = 10; --i >= 0;)
576: run_cycle();
577: }
578: }
579:
580: void i860_cpu_device::tick(bool intr) {
581: if(intr) send_msg(MSG_INTR);
582: #if ENABLE_PERF_COUNTERS
583: UINT32 now = time_ms();
584: m_time_delta_ms += now - m_abs_time_ms;
585: m_abs_time_ms = now;
586: if(m_time_delta_ms > 5000)
587: dump_reset_perfc();
588: #endif
589: }
590:
591: #if ENABLE_PERF_COUNTERS
592: void i860_cpu_device::dump_reset_perfc() {
593: static bool dump = false;
594: if(dump) {
595: UINT32 dt = m_time_delta_ms;
596: if(dt) {
597: if(trylock(&m_debugger_lock)) {
598: Log_Printf(LOG_WARN, "[i860] Stats: MIPS=%lld.%lld icache_hit=%lld%% tlb_hit=%lld%% icach_inval/s=%lld tlb_inval/s=%lld intr/s=%lld",
599: (m_insn_decoded / (dt * 100)) / 10, (m_insn_decoded / (dt * 100)) % 10,
600: m_icache_hit+m_icache_miss == 0 ? 0 : (100 * m_icache_hit) / (m_icache_hit+m_icache_miss) ,
601: m_tlb_hit+m_tlb_miss == 0 ? 0 : (100 * m_tlb_hit) / (m_tlb_hit+m_tlb_miss),
602: (1000*m_icache_inval)/dt,
603: (1000*m_tlb_inval)/dt,
604: (1000*m_intrs)/dt
605: );
606: Log_Printf(LOG_WARN, "[m68k] Stats: Mcycles/s=%lld.%lld",
607: (m_m68k_cylces / (dt * 100)) / 10, (m_insn_decoded / (dt * 100)) % 10);
608:
609: m_m68k_cylces = 0;
610: m_insn_decoded = 0;
611: m_icache_hit = 0;
612: m_icache_miss = 0;
613: m_icache_inval = 0;
614: m_tlb_hit = 0;
615: m_tlb_miss = 0;
616: m_tlb_inval = 0;
617: m_time_delta_ms = 0;
618: m_intrs = 0;
619:
620: unlock(&m_debugger_lock);
621: }
622: }
623: }
624:
625: dump = true;
626: }
627: #endif
628:
629: offs_t i860_cpu_device::disasm(char* buffer, offs_t pc) {
630: return pc + i860_disassembler(pc, ifetch_notrap(pc), buffer);
631: }
632:
633: /**************************************************************************
634: * The actual decode and execute code.
635: **************************************************************************/
636: #include "i860dec.cpp"
637:
638: /**************************************************************************
639: * The debugger code.
640: **************************************************************************/
641: #include "i860dbg.cpp"
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.