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

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: 
1.1.1.3 ! root       18: #include <stdlib.h>
        !            19: #if defined _WIN32
        !            20: #undef mkdir
        !            21: #endif
        !            22: #include <unistd.h>
        !            23: 
        !            24: #include "i860.hpp"
        !            25: #include "dimension.hpp"
        !            26: #include "log.h"
1.1       root       27: 
                     28: extern "C" {
1.1.1.2   root       29:     static void i860_run_nop(int nHostCycles) {}
1.1.1.3 ! root       30: 
1.1.1.2   root       31:     i860_run_func i860_Run = i860_run_nop;
                     32: 
                     33:     static void i860_run_thread(int nHostCycles) {
                     34:         nd_nbic_interrupt();
                     35:     }
                     36: 
                     37:     static void i860_run_no_thread(int nHostCycles) {
1.1.1.3 ! root       38:         int cycles;
1.1.1.2   root       39:         
1.1.1.3 ! root       40:         FOR_EACH_SLOT(slot) {
        !            41:             IF_NEXT_DIMENSION(slot, nd) {
        !            42:                 nd->handle_msgs();
        !            43:                 
        !            44:                 if(nd->i860.is_halted()) return;
        !            45:                 
        !            46:                 cycles = nHostCycles * 33; // i860 @ 33MHz
        !            47:                 cycles /= ConfigureParams.System.nCpuFreq;
        !            48:                 while (cycles > 0) {
        !            49:                     nd->i860.run_cycle();
        !            50:                     cycles --;
        !            51:                 }
        !            52:             }
1.1.1.2   root       53:         }
                     54:         nd_nbic_interrupt();
1.1.1.3 ! root       55:     }    
1.1       root       56: }
                     57: 
1.1.1.3 ! root       58: i860_cpu_device::i860_cpu_device(NextDimension* nd) : nd(nd) {
1.1       root       59:     m_thread = NULL;
1.1.1.2   root       60:     m_halt   = true;
                     61:     
                     62:     for(int i = 0; i < 8192; i++) {
                     63:         int upper6 = i >> 7;
                     64:         switch (upper6) {
                     65:             case 0x12:
                     66:                 decoder_tbl[i] = fp_decode_tbl[i & 0x7f];
                     67:                 break;
                     68:             case 0x13:
                     69:                 decoder_tbl[i] = core_esc_decode_tbl[i&3];
                     70:                 break;
                     71:             default:
                     72:                 decoder_tbl[i] = decode_tbl[upper6];
                     73:         }
                     74:     }
1.1       root       75: }
                     76: 
1.1.1.3 ! root       77: int i860_cpu_device::thread(void* data) {
        !            78:     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_LOW);
        !            79:     ((i860_cpu_device*)data)->run();
        !            80:     return 0;
        !            81: }
        !            82: 
1.1       root       83: void i860_cpu_device::set_mem_access(bool be) {
                     84:     if(be) {
1.1.1.3 ! root       85:         rdmem[1]  = NextDimension::i860_rd8_be;
        !            86:         rdmem[2]  = NextDimension::i860_rd16_be;
        !            87:         rdmem[4]  = NextDimension::i860_rd32_be;
        !            88:         rdmem[8]  = NextDimension::i860_rd64_be;
        !            89:         rdmem[16] = NextDimension::i860_rd128_be;
        !            90:         
        !            91:         wrmem[1]  = NextDimension::i860_wr8_be;
        !            92:         wrmem[2]  = NextDimension::i860_wr16_be;
        !            93:         wrmem[4]  = NextDimension::i860_wr32_be;
        !            94:         wrmem[8]  = NextDimension::i860_wr64_be;
        !            95:         wrmem[16] = NextDimension::i860_wr128_be;
1.1       root       96:     } else {
1.1.1.3 ! root       97:         rdmem[1]  = NextDimension::i860_rd8_le;
        !            98:         rdmem[2]  = NextDimension::i860_rd16_le;
        !            99:         rdmem[4]  = NextDimension::i860_rd32_le;
        !           100:         rdmem[8]  = NextDimension::i860_rd64_le;
        !           101:         rdmem[16] = NextDimension::i860_rd128_le;
        !           102:         
        !           103:         wrmem[1]  = NextDimension::i860_wr8_le;
        !           104:         wrmem[2]  = NextDimension::i860_wr16_le;
        !           105:         wrmem[4]  = NextDimension::i860_wr32_le;
        !           106:         wrmem[8]  = NextDimension::i860_wr64_le;
        !           107:         wrmem[16] = NextDimension::i860_wr128_le;
1.1       root      108:     }
                    109: }
                    110: 
                    111: inline UINT8 i860_cpu_device::rdcs8(UINT32 addr) {
1.1.1.3 ! root      112:     return NextDimension::i860_cs8get(nd, addr);
1.1       root      113: }
                    114: 
                    115: inline UINT32 i860_cpu_device::get_iregval(int gr) {
                    116:     return m_iregs[gr];
                    117: }
                    118: 
                    119: inline void i860_cpu_device::set_iregval(int gr, UINT32 val) {
                    120:     m_iregs[gr] = val;
                    121:     m_iregs[0]  = 0; // make sure r0 is always 0
                    122: }
                    123: 
1.1.1.2   root      124: inline FLOAT32 i860_cpu_device::get_fregval_s (int fr) {
                    125:     return *(FLOAT32*)(&m_fregs[fr * 4]);
1.1       root      126: }
                    127: 
1.1.1.2   root      128: inline void i860_cpu_device::set_fregval_s (int fr, FLOAT32 s) {
1.1       root      129:     if(fr > 1)
1.1.1.2   root      130:         *(FLOAT32*)(&m_fregs[fr * 4]) = s;
1.1       root      131: }
                    132: 
1.1.1.2   root      133: inline FLOAT64 i860_cpu_device::get_fregval_d (int fr) {
                    134:     return *(FLOAT64*)(&m_fregs[fr * 4]);
1.1       root      135: }
                    136: 
1.1.1.2   root      137: inline void i860_cpu_device::set_fregval_d (int fr, FLOAT64 d) {
1.1       root      138:     if(fr > 1)
1.1.1.2   root      139:         *(FLOAT64*)(&m_fregs[fr * 4]) = d;
1.1       root      140: }
                    141: 
                    142: inline void i860_cpu_device::SET_PSR_CC(int val) {
                    143:     if(!(m_dim_cc_valid))
                    144:         m_cregs[CR_PSR] = (m_cregs[CR_PSR] & ~(1 << 2)) | ((val & 1) << 2);
                    145: }
1.1.1.3 ! root      146: 
        !           147: const char* i860_cpu_device::trap_info() {
        !           148:     static char buffer[256];
        !           149:     buffer[0] = 0;
        !           150:     strcat(buffer, "TRAP");
        !           151:     if(m_flow & TRAP_NORMAL)        strcat(buffer, " [Normal]");
        !           152:     if(m_flow & TRAP_IN_DELAY_SLOT) strcat(buffer, " [Delay Slot]");
        !           153:     if(m_flow & TRAP_WAS_EXTERNAL)  strcat(buffer, " [External]");
        !           154:     if(!(GET_PSR_IT() || GET_PSR_FT() || GET_PSR_IAT() || GET_PSR_DAT() || GET_PSR_IN()))
        !           155:         strcat(buffer, " >Reset<");
        !           156:     else {
        !           157:         if(GET_PSR_IT())  strcat(buffer, " >Instruction Fault<");
        !           158:         if(GET_PSR_FT())  strcat(buffer, " >Floating Point Fault<");
        !           159:         if(GET_PSR_IAT()) strcat(buffer, " >Instruction Access Fault<");
        !           160:         if(GET_PSR_DAT()) strcat(buffer, " >Data Access Fault<");
        !           161:         if(GET_PSR_IN())  strcat(buffer, " >Interrupt<");
        !           162:     }
        !           163:     
        !           164:     return buffer;
        !           165: }
1.1       root      166: 
                    167: void i860_cpu_device::handle_trap(UINT32 savepc) {
                    168:     if(!(m_single_stepping) && !((GET_PSR_IAT() || GET_PSR_DAT() || GET_PSR_IN())))
1.1.1.3 ! root      169:         debugger('d', trap_info());
1.1       root      170:     
                    171:     if(m_dim)
1.1.1.3 ! root      172:         Log_Printf(LOG_WARN, "[i860] Trap while DIM %s pc=%08X m_flow=%08X", trap_info(), savepc, m_flow);
1.1       root      173: 
                    174:     /* If we need to trap, change PC to trap address.
                    175:      Also set supervisor mode, copy U and IM to their
                    176:      previous versions, clear IM.  */
                    177:     if(m_flow & TRAP_WAS_EXTERNAL) {
                    178:         if (GET_PC_UPDATED()) {
                    179:             m_cregs[CR_FIR] = m_pc;
                    180:         } else {
                    181:             m_cregs[CR_FIR] = savepc + 4;
                    182:         }
                    183:     }
                    184:     else if (m_flow & TRAP_IN_DELAY_SLOT) {
                    185:         m_cregs[CR_FIR] = savepc + 4;
                    186:     }
                    187:     else
                    188:         m_cregs[CR_FIR] = savepc;
                    189:     
                    190:     m_flow |= FIR_GETS_TRAP;
                    191:     SET_PSR_PU (GET_PSR_U ());
                    192:     SET_PSR_PIM (GET_PSR_IM ());
                    193:     SET_PSR_U (0);
                    194:     SET_PSR_IM (0);
                    195:     SET_PSR_DIM (0);
                    196:     SET_PSR_DS (0);
                    197:     
                    198:     m_save_flow     = m_flow & DIM_OP;
                    199:     m_save_dim      = m_dim;
                    200:     m_save_cc       = m_dim_cc;
                    201:     m_save_cc_valid = m_dim_cc_valid;
                    202:     
                    203:     m_dim           = DIM_NONE;
                    204:     m_dim_cc        = false;
                    205:     m_dim_cc_valid  = false;
                    206:     
                    207:     m_pc = 0xffffff00;
                    208: }
                    209: 
                    210: void i860_cpu_device::ret_from_trap() {
                    211:     m_flow          |= m_save_flow & ~DIM_OP;
                    212:     m_dim            = m_save_dim;
                    213:     m_flow          &= ~FIR_GETS_TRAP;
                    214:     m_dim_cc         = m_save_cc;
                    215:     m_dim_cc_valid   = m_save_cc_valid;
                    216: }
                    217: 
                    218: void i860_cpu_device::run_cycle() {
                    219:     CLEAR_FLOW();
                    220:     m_dim_cc_valid = false;
                    221:     m_flow        &= ~DIM_OP;
                    222:     UINT64 insn64  = ifetch64(m_pc);
                    223:     
                    224:     if(!(m_pc & 4)) {
                    225:         UINT32 savepc  = m_pc;
                    226:         
                    227: #if ENABLE_DEBUGGER
                    228:         if(m_single_stepping) debugger(0,0);
                    229: #endif
                    230:         
                    231:         UINT32 insnLow = insn64;
                    232:         if(insnLow == INSN_FNOP_DIM) {
                    233:             if(m_dim) m_flow |=  DIM_OP;
                    234:             else      m_flow &= ~DIM_OP;
                    235:         } else if((insnLow & INSN_MASK_DIM) == INSN_FP_DIM)
                    236:             m_flow |= DIM_OP;
                    237:         
                    238:         decode_exec(insnLow);
                    239:         
                    240:         if (PENDING_TRAP()) {
                    241:             handle_trap(savepc);
                    242:             goto done;
                    243:         } else if(GET_PC_UPDATED()) {
                    244:             goto done;
                    245:         } else {
                    246:             // If the PC wasn't updated by a control flow instruction, just bump to next sequential instruction.
                    247:             m_pc   += 4;
                    248:             CLEAR_FLOW();
                    249:         }
                    250:     }
                    251:     
                    252:     if(m_pc & 4) {
                    253:         UINT32 savepc  = m_pc;
                    254:         
                    255: #if ENABLE_DEBUGGER
                    256:         if(m_single_stepping && !(m_dim)) debugger(0,0);
                    257: #endif
                    258: 
                    259:         UINT32 insnHigh= insn64 >> 32;
                    260:         decode_exec(insnHigh);
                    261:         
                    262:         // only check for external interrupts
                    263:         // - on high-word (speedup)
                    264:         // - not DIM (safety :-)
                    265:         // - when no other traps are pending
                    266:         if(!(m_dim) && !(PENDING_TRAP())) {
                    267:             if(m_flow & EXT_INTR) {
                    268:                 m_flow &= ~EXT_INTR;
                    269:                 gen_interrupt();
                    270:             } else
                    271:                 clr_interrupt();
                    272:         }
                    273:         
                    274:         if (PENDING_TRAP()) {
                    275:             handle_trap(savepc);
                    276:         } else if (GET_PC_UPDATED()) {
                    277:             goto done;
                    278:         } else {
                    279:             // If the PC wasn't updated by a control flow instruction, just bump to next sequential instruction.
                    280:             m_pc += 4;
                    281:         }
                    282:     }
                    283: done:
                    284:     switch (m_dim) {
                    285:         case DIM_NONE:
                    286:             if(m_flow & DIM_OP)
                    287:                 m_dim = DIM_TEMP;
                    288:             break;
                    289:         case DIM_TEMP:
                    290:             m_dim = m_flow & DIM_OP ? DIM_FULL : DIM_NONE;
                    291:             break;
                    292:         case DIM_FULL:
                    293:             if(!(m_flow & DIM_OP))
                    294:                 m_dim = DIM_TEMP;
                    295:             break;
                    296:     }
                    297: }
                    298: 
                    299: int i860_cpu_device::memtest(bool be) {
                    300:     const UINT32 P_TEST_ADDR = 0x28000000; // assume ND in slot 2
                    301:     
                    302:     m_cregs[CR_DIRBASE] = 0; // turn VM off
                    303: 
                    304:     const UINT8  uint8  = 0x01;
                    305:     const UINT16 uint16 = 0x0123;
                    306:     const UINT32 uint32 = 0x01234567;
                    307:     const UINT64 uint64 = 0x0123456789ABCDEFLL;
                    308:     
                    309:     UINT8  tmp8;
                    310:     UINT16 tmp16;
                    311:     UINT32 tmp32;
                    312:     
                    313:     int err = be ? 20000 : 30000;
                    314:     
                    315:     // intel manual example
                    316:     SET_EPSR_BE(0);
                    317:     set_mem_access(false);
                    318:     
1.1.1.3 ! root      319:     tmp8 = 'A'; wrmem[1](nd, P_TEST_ADDR+0, (UINT32*)&tmp8);
        !           320:     tmp8 = 'B'; wrmem[1](nd, P_TEST_ADDR+1, (UINT32*)&tmp8);
        !           321:     tmp8 = 'C'; wrmem[1](nd, P_TEST_ADDR+2, (UINT32*)&tmp8);
        !           322:     tmp8 = 'D'; wrmem[1](nd, P_TEST_ADDR+3, (UINT32*)&tmp8);
        !           323:     tmp8 = 'E'; wrmem[1](nd, P_TEST_ADDR+4, (UINT32*)&tmp8);
        !           324:     tmp8 = 'F'; wrmem[1](nd, P_TEST_ADDR+5, (UINT32*)&tmp8);
        !           325:     tmp8 = 'G'; wrmem[1](nd, P_TEST_ADDR+6, (UINT32*)&tmp8);
        !           326:     tmp8 = 'H'; wrmem[1](nd, P_TEST_ADDR+7, (UINT32*)&tmp8);
        !           327:     
        !           328:     rdmem[1](nd, P_TEST_ADDR+0, (UINT32*)&tmp8); if(tmp8 != 'A') return err + 100;
        !           329:     rdmem[1](nd, P_TEST_ADDR+1, (UINT32*)&tmp8); if(tmp8 != 'B') return err + 101;
        !           330:     rdmem[1](nd, P_TEST_ADDR+2, (UINT32*)&tmp8); if(tmp8 != 'C') return err + 102;
        !           331:     rdmem[1](nd, P_TEST_ADDR+3, (UINT32*)&tmp8); if(tmp8 != 'D') return err + 103;
        !           332:     rdmem[1](nd, P_TEST_ADDR+4, (UINT32*)&tmp8); if(tmp8 != 'E') return err + 104;
        !           333:     rdmem[1](nd, P_TEST_ADDR+5, (UINT32*)&tmp8); if(tmp8 != 'F') return err + 105;
        !           334:     rdmem[1](nd, P_TEST_ADDR+6, (UINT32*)&tmp8); if(tmp8 != 'G') return err + 106;
        !           335:     rdmem[1](nd, P_TEST_ADDR+7, (UINT32*)&tmp8); if(tmp8 != 'H') return err + 107;
        !           336:     
        !           337:     rdmem[2](nd, P_TEST_ADDR+0, (UINT32*)&tmp16); if(tmp16 != (('B'<<8)|('A'))) return err + 110;
        !           338:     rdmem[2](nd, P_TEST_ADDR+2, (UINT32*)&tmp16); if(tmp16 != (('D'<<8)|('C'))) return err + 111;
        !           339:     rdmem[2](nd, P_TEST_ADDR+4, (UINT32*)&tmp16); if(tmp16 != (('F'<<8)|('E'))) return err + 112;
        !           340:     rdmem[2](nd, P_TEST_ADDR+6, (UINT32*)&tmp16); if(tmp16 != (('H'<<8)|('G'))) return err + 113;
1.1       root      341: 
1.1.1.3 ! root      342:     rdmem[4](nd, P_TEST_ADDR+0, &tmp32); if(tmp32 != (('D'<<24)|('C'<<16)|('B'<<8)|('A'))) return err + 120;
        !           343:     rdmem[4](nd, P_TEST_ADDR+4, &tmp32); if(tmp32 != (('H'<<24)|('G'<<16)|('F'<<8)|('E'))) return err + 121;
1.1       root      344: 
                    345:     SET_EPSR_BE(1);
                    346:     set_mem_access(true);
                    347: 
1.1.1.3 ! root      348:     rdmem[1](nd, P_TEST_ADDR+0, (UINT32*)&tmp8); if(tmp8 != 'H') return err + 200;
        !           349:     rdmem[1](nd, P_TEST_ADDR+1, (UINT32*)&tmp8); if(tmp8 != 'G') return err + 201;
        !           350:     rdmem[1](nd, P_TEST_ADDR+2, (UINT32*)&tmp8); if(tmp8 != 'F') return err + 202;
        !           351:     rdmem[1](nd, P_TEST_ADDR+3, (UINT32*)&tmp8); if(tmp8 != 'E') return err + 203;
        !           352:     rdmem[1](nd, P_TEST_ADDR+4, (UINT32*)&tmp8); if(tmp8  != 'D') return err + 204;
        !           353:     rdmem[1](nd, P_TEST_ADDR+5, (UINT32*)&tmp8); if(tmp8  != 'C') return err + 205;
        !           354:     rdmem[1](nd, P_TEST_ADDR+6, (UINT32*)&tmp8); if(tmp8  != 'B') return err + 206;
        !           355:     rdmem[1](nd, P_TEST_ADDR+7, (UINT32*)&tmp8); if(tmp8  != 'A') return err + 207;
        !           356:     
        !           357:     rdmem[2](nd, P_TEST_ADDR+0, (UINT32*)&tmp16); if(tmp16 != (('H'<<8)|('G'))) return err + 210;
        !           358:     rdmem[2](nd, P_TEST_ADDR+2, (UINT32*)&tmp16); if(tmp16 != (('F'<<8)|('E'))) return err + 211;
        !           359:     rdmem[2](nd, P_TEST_ADDR+4, (UINT32*)&tmp16); if(tmp16 != (('D'<<8)|('C'))) return err + 212;
        !           360:     rdmem[2](nd, P_TEST_ADDR+6, (UINT32*)&tmp16); if(tmp16 != (('B'<<8)|('A'))) return err + 213;
1.1       root      361:     
1.1.1.3 ! root      362:     rdmem[4](nd, P_TEST_ADDR+0, &tmp32); if(tmp32 != (('H'<<24)|('G'<<16)|('F'<<8)|('E'))) return err + 220;
        !           363:     rdmem[4](nd, P_TEST_ADDR+4, &tmp32); if(tmp32 != (('D'<<24)|('C'<<16)|('B'<<8)|('A'))) return err + 221;
1.1       root      364:     
                    365:     // some register and mem r/w tests
                    366:     
                    367:     SET_EPSR_BE(be);
                    368:     set_mem_access(be);
                    369: 
1.1.1.3 ! root      370:     wrmem[1](nd, P_TEST_ADDR, (UINT32*)&uint8);
        !           371:     rdmem[1](nd, P_TEST_ADDR, (UINT32*)&tmp8);
1.1       root      372:     if(tmp8 != 0x01) return err;
                    373:     
1.1.1.3 ! root      374:     wrmem[2](nd, P_TEST_ADDR, (UINT32*)&uint16);
        !           375:     rdmem[2](nd, P_TEST_ADDR, (UINT32*)&tmp16);
1.1       root      376:     if(tmp16 != 0x0123) return err+1;
                    377:     
1.1.1.3 ! root      378:     wrmem[4](nd, P_TEST_ADDR, &uint32);
        !           379:     rdmem[4](nd, P_TEST_ADDR, &tmp32); if(tmp32 != 0x01234567) return err+2;
1.1       root      380:     
                    381:     readmem_emu(P_TEST_ADDR, 4, (UINT8*)&uint32);
                    382:     if(uint32 != 0x01234567) return err+3;
                    383:     
                    384:     writemem_emu(P_TEST_ADDR, 4, (UINT8*)&uint32, 0xff);
1.1.1.3 ! root      385:     rdmem[4](nd, P_TEST_ADDR+0, &tmp32); if(tmp32 != 0x01234567) return err+4;
1.1       root      386:     
                    387:     UINT8* uint8p = (UINT8*)&uint64;
1.1.1.2   root      388:     set_fregval_d(2, *((FLOAT64*)uint8p));
1.1       root      389:     writemem_emu(P_TEST_ADDR, 8, &m_fregs[8], 0xff);
                    390:     readmem_emu (P_TEST_ADDR, 8, &m_fregs[8]);
1.1.1.2   root      391:     *((FLOAT64*)&uint64) = get_fregval_d(2);
1.1       root      392:     if(uint64 != 0x0123456789ABCDEFLL) return err+5;
                    393: 
                    394:     UINT32 lo;
                    395:     UINT32 hi;
                    396: 
1.1.1.3 ! root      397:     rdmem[4](nd, P_TEST_ADDR+0, &lo);
        !           398:     rdmem[4](nd, P_TEST_ADDR+4, &hi);
1.1       root      399:     
                    400:     if(lo != 0x01234567) return err+6;
                    401:     if(hi != 0x89ABCDEF) return err+7;
                    402:     
                    403:     return 0;
                    404: }
                    405: 
1.1.1.3 ! root      406: void i860_cpu_device::set_run_func(void) {
        !           407:     i860_Run = ConfigureParams.Dimension.bI860Thread ? i860_run_thread : i860_run_no_thread;
        !           408: }
        !           409: 
        !           410: void i860_cpu_device::init(void) {
1.1       root      411:     /* Configurations - keep in sync with i860cfg.h */
                    412:     static const char* CFGS[8];
                    413:     for(int i = 0; i < 8; i++) CFGS[i] = "Unknown emulator configuration";
                    414:     CFGS[CONF_I860_SPEED]     = CONF_STR(CONF_I860_SPEED);
                    415:     CFGS[CONF_I860_DEV]       = CONF_STR(CONF_I860_DEV);
                    416:     CFGS[CONF_I860_NO_THREAD] = CONF_STR(CONF_I860_NO_THREAD);
1.1.1.2   root      417:     Log_Printf(LOG_WARN, "[i860] Emulator configured for %s, %d logical cores detected, %s",
                    418:                CFGS[CONF_I860], host_num_cpus(),
                    419:                ConfigureParams.Dimension.bI860Thread ? "using seperate thread for i860" : "i860 running on m68k thread. WARNING: expect slow emulation");
1.1       root      420:     
1.1.1.3 ! root      421:     reset_fpcs(&m_fpcs);
        !           422:     
1.1       root      423:     m_single_stepping   = 0;
                    424:     m_lastcmd           = 0;
                    425:     m_console_idx       = 0;
                    426:     m_break_on_next_msg = false;
                    427:     m_dim               = DIM_NONE;
                    428:     m_traceback_idx     = 0;
1.1.1.2   root      429:     
1.1       root      430:     set_mem_access(false);
                    431: 
                    432:     // some sanity checks for endianess
                    433:     int    err    = 0;
                    434:     {
                    435:         UINT32 uint32 = 0x01234567;
                    436:         UINT8* uint8p = (UINT8*)&uint32;
                    437:         if(uint8p[3] != 0x01) {err = 1; goto error;}
                    438:         if(uint8p[2] != 0x23) {err = 2; goto error;}
                    439:         if(uint8p[1] != 0x45) {err = 3; goto error;}
                    440:         if(uint8p[0] != 0x67) {err = 4; goto error;}
                    441:         
                    442:         for(int i = 0; i < 32; i++) {
                    443:             uint8p[3] = i;
1.1.1.2   root      444:             set_fregval_s(i, *((FLOAT32*)uint8p));
1.1       root      445:         }
                    446:         if(get_fregval_s(0) != 0)   {err = 198; goto error;}
                    447:         if(get_fregval_s(1) != 0)   {err = 199; goto error;}
                    448:         for(int i = 2; i < 32; i++) {
                    449:             uint8p[3] = i;
1.1.1.2   root      450:             if(get_fregval_s(i) != *((FLOAT32*)uint8p))
1.1       root      451:                 {err = 100+i; goto error;}
                    452:         }
                    453:         for(int i = 2; i < 32; i++) {
                    454:             if(m_fregs[i*4+3] != i)    {err = 200+i; goto error;}
                    455:             if(m_fregs[i*4+2] != 0x23) {err = 200+i; goto error;}
                    456:             if(m_fregs[i*4+1] != 0x45) {err = 200+i; goto error;}
                    457:             if(m_fregs[i*4+0] != 0x67) {err = 200+i; goto error;}
                    458:         }
                    459:     }
                    460:     
                    461:     {
                    462:         UINT64 uint64 = 0x0123456789ABCDEFLL;
                    463:         UINT8* uint8p = (UINT8*)&uint64;
                    464:         if(uint8p[7] != 0x01) {err = 10001; goto error;}
                    465:         if(uint8p[6] != 0x23) {err = 10002; goto error;}
                    466:         if(uint8p[5] != 0x45) {err = 10003; goto error;}
                    467:         if(uint8p[4] != 0x67) {err = 10004; goto error;}
                    468:         if(uint8p[3] != 0x89) {err = 10005; goto error;}
                    469:         if(uint8p[2] != 0xAB) {err = 10006; goto error;}
                    470:         if(uint8p[1] != 0xCD) {err = 10007; goto error;}
                    471:         if(uint8p[0] != 0xEF) {err = 10008; goto error;}
                    472:         
                    473:         for(int i = 0; i < 16; i++) {
                    474:             uint8p[7] = i;
1.1.1.2   root      475:             set_fregval_d(i*2, *((FLOAT64*)uint8p));
1.1       root      476:         }
                    477:         if(get_fregval_d(0) != 0)
                    478:             {err = 10199; goto error;}
                    479:         for(int i = 1; i < 16; i++) {
                    480:             uint8p[7] = i;
1.1.1.2   root      481:             if(get_fregval_d(i*2) != *((FLOAT64*)uint8p))
1.1       root      482:                 {err = 10100+i; goto error;}
                    483:         }
                    484:         for(int i = 2; i < 32; i += 2) {
1.1.1.2   root      485:             FLOAT32 hi = get_fregval_s(i+1);
                    486:             FLOAT32 lo = get_fregval_s(i+0);
1.1       root      487:             if((*(UINT32*)&hi) != (0x00234567 | (i<<23))) {err = 10100+i; goto error;}
                    488:             if((*(UINT32*)&lo) !=  0x89ABCDEF)            {err = 10100+i; goto error;}
                    489:         }
                    490:         for(int i = 1; i < 16; i++) {
                    491:             if(m_fregs[i*8+7] != i)    {err = 10200+i; goto error;}
                    492:             if(m_fregs[i*8+6] != 0x23) {err = 10200+i; goto error;}
                    493:             if(m_fregs[i*8+5] != 0x45) {err = 10200+i; goto error;}
                    494:             if(m_fregs[i*8+4] != 0x67) {err = 10200+i; goto error;}
                    495:             if(m_fregs[i*8+3] != 0x89) {err = 10200+i; goto error;}
                    496:             if(m_fregs[i*8+2] != 0xAB) {err = 10200+i; goto error;}
                    497:             if(m_fregs[i*8+1] != 0xCD) {err = 10200+i; goto error;}
                    498:             if(m_fregs[i*8+0] != 0xEF) {err = 10200+i; goto error;}
                    499:         }
                    500:     }
                    501:     
                    502:     err = memtest(true); if(err) goto error;
                    503:     err = memtest(false); if(err) goto error;
                    504:     
                    505: error:
                    506:     if(err) {
                    507:         fprintf(stderr, "NeXTdimension i860 emulator requires a little-endian host. This system seems to be big endian. Error %d. Exiting.\n", err);
                    508:         fflush(stderr);
                    509:         exit(err);
                    510:     }
                    511: 
1.1.1.3 ! root      512:     nd->send_msg(MSG_I860_RESET);
        !           513:     if(ConfigureParams.Dimension.bI860Thread) {
        !           514:         i860_Run = i860_run_thread;
        !           515:         m_thread = host_thread_create(i860_cpu_device::thread, this);
        !           516:     } else {
        !           517:         i860_Run = i860_run_no_thread;
        !           518:     }
1.1       root      519: }
                    520: 
                    521: void i860_cpu_device::uninit() {
                    522:        halt(true);
1.1.1.2   root      523: 
1.1       root      524:     if(m_thread) {
1.1.1.3 ! root      525:         nd->send_msg(MSG_I860_KILL);
1.1.1.2   root      526:         host_thread_wait(m_thread);
1.1       root      527:         m_thread = NULL;
                    528:     }
1.1.1.3 ! root      529:     nd->send_msg(MSG_NONE);
1.1       root      530: }
                    531: 
                    532: /* Message disaptcher - executed on i860 thread, safe to call i860 methods */
1.1.1.3 ! root      533: bool i860_cpu_device::handle_msgs(int msg) {
1.1       root      534:     if(msg & MSG_I860_KILL)
                    535:         return false;
1.1.1.2   root      536:     
1.1       root      537:     if(msg & MSG_I860_RESET)
                    538:         reset();
                    539:     else if(msg & MSG_INTR)
                    540:         intr();
                    541:     if(msg & MSG_DBG_BREAK)
                    542:         debugger('d', "BREAK at pc=%08X", m_pc);
                    543:     return true;
                    544: }
                    545: 
                    546: void i860_cpu_device::run() {
1.1.1.3 ! root      547:     while(nd->handle_msgs()) {
1.1       root      548:         
                    549:         /* Sleep a bit if halted */
                    550:         if(is_halted()) {
1.1.1.2   root      551:             host_sleep_ms(100);
1.1       root      552:             continue;
                    553:         }
                    554:         
1.1.1.3 ! root      555:         if (i860cycles > 0) {
        !           556:             /* Run some i860 cycles before re-checking messages */
        !           557:             for(int i = 16; --i >= 0;)
        !           558:                 run_cycle();
        !           559:             
        !           560:             i860cycles -= 16;
        !           561:         } else {
        !           562:             host_sleep_ms(1);
        !           563:         }
1.1       root      564:     }
                    565: }
                    566: 
1.1.1.2   root      567: const char* i860_cpu_device::reports(double realTime, double hostTime) {
                    568:     double dVT = hostTime - m_last_vt;
                    569:     
                    570:     if(is_halted()) {
                    571:         m_report[0] = 0;
                    572:     } else {
                    573:         if(dVT == 0) dVT = 0.0001;
                    574:         sprintf(m_report, "i860:{MIPS=%.1f icache_hit=%lld%% tlb_hit=%lld%% icach_inval/s=%.0f tlb_inval/s=%.0f intr/s=%0.f}",
                    575:                                (m_insn_decoded / (dVT*1000*1000)),
                    576:                                m_icache_hit+m_icache_miss == 0 ? 0 : (100 * m_icache_hit) / (m_icache_hit+m_icache_miss) ,
                    577:                                m_tlb_hit+m_tlb_miss       == 0 ? 0 : (100 * m_tlb_hit)    / (m_tlb_hit+m_tlb_miss),
                    578:                                (m_icache_inval)/dVT,
                    579:                                (m_tlb_inval)/dVT,
                    580:                                (m_intrs)/dVT
                    581:                                );
                    582:         
                    583:         m_insn_decoded  = 0;
                    584:         m_icache_hit    = 0;
                    585:         m_icache_miss   = 0;
                    586:         m_icache_inval  = 0;
                    587:         m_tlb_hit       = 0;
                    588:         m_tlb_miss      = 0;
                    589:         m_tlb_inval     = 0;
                    590:         m_intrs         = 0;
1.1       root      591: 
1.1.1.2   root      592:         m_last_rt = realTime;
                    593:         m_last_vt = hostTime;
1.1       root      594:     }
                    595:     
1.1.1.2   root      596:     return m_report;
1.1       root      597: }
                    598: 
                    599: offs_t i860_cpu_device::disasm(char* buffer, offs_t pc) {
                    600:     return pc + i860_disassembler(pc, ifetch_notrap(pc), buffer);
                    601: }
                    602: 
                    603: /**************************************************************************
                    604:  * The actual decode and execute code.
                    605:  **************************************************************************/
                    606: #include "i860dec.cpp"
                    607: 
                    608: /**************************************************************************
                    609:  * The debugger code.
                    610:  **************************************************************************/
1.1.1.3 ! root      611: #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.