Annotation of previous/src/dimension/i860.cpp, revision 1.1.1.1

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"

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.