Annotation of previous/src/dimension/i860.cpp, revision 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.