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

1.1       root        1: /***************************************************************************
                      2: 
                      3:     i860dec.inc
                      4: 
                      5:     Execution engine 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: /*
                     19:  * References:
                     20:  *  `i860 Microprocessor Programmer's Reference Manual', Intel, 1990.
                     21:  *
                     22:  * This code was originally written by Jason Eckhardt as part of an
                     23:  * emulator for some i860-based Unix workstations (early 1990's) such
                     24:  * as the Stardent Vistra 800 series and the OkiStation/i860 7300 series.
                     25:  * The code you are reading now is the i860 CPU portion only, which has
                     26:  * been adapted to (and simplified for) MAME.
                     27:  * MAME-specific notes:
                     28:  * - i860XR emulation only (i860XP unnecessary for MAME).
                     29:  * - No emulation of data and instruction caches (unnecessary for MAME version).
                     30:  * - No emulation of DIM mode or CS8 mode (unnecessary for MAME version).
                     31:  * - No BL/IL/locked sequences (unnecessary for MAME).
                     32:  * NeXTdimension specfic notes:
                     33:  * - (SC) Added support for i860's MSB/LSB-first mode (BE = 1/0).
                     34:  * - (SC) We assume that the host CPU is little endian (for now, will be fixed)
                     35:  * - (SC) Instruction cache implemented (not present in MAME version)
                     36:  * - (SC) Added dual-instruction-mode support (removed in MAME version)
                     37:  * - (SC) Added rounding mode support and insn_fix
                     38:  * Generic notes:
                     39:  * - There is some amount of code duplication (e.g., see the
                     40:  *   various insn_* routines for the branches and FP routines) that
                     41:  *   could be eliminated.
                     42:  * - The host's floating point types are used to emulate the i860's
                     43:  *   floating point.  Should probably be made machine independent by
                     44:  *   using an IEEE FP emulation library.  On the other hand, most machines
                     45:  *   today also use IEEE FP.
                     46:  *
                     47:  */
                     48: #include <math.h>
                     49: #include <fenv.h>
                     50: #include <assert.h>
                     51: 
                     52: #pragma STDC FENV_ACCESS on
                     53: 
                     54: #define DELAY_SLOT_PC() ((m_dim == DIM_FULL) ? 12 : 8)
                     55: #define DELAY_SLOT() do{\
                     56:     m_pc += 4; \
                     57:     UINT32 insn = ifetch(orig_pc+4);\
                     58:     decode_exec(insn); \
                     59:     if((m_dim == DIM_FULL) || (m_flow & DIM_OP)) {\
                     60:         m_pc += 4; \
                     61:         decode_exec(ifetch(orig_pc+8)); \
                     62:     } \
                     63:     m_pc = orig_pc;}while(0)
                     64: 
                     65: int i860_cpu_device::delay_slots(UINT32 insn) {
                     66:        int opc = (insn >> 26) & 0x3f;
                     67:        if (opc == 0x10 || opc == 0x1a || opc == 0x1b || opc == 0x1d ||
                     68:                opc == 0x1f || opc == 0x2d || (opc == 0x13 && (insn & 3) == 2))
                     69:         return m_dim ? 2 : 1;
                     70:     return 0;
                     71: }
                     72: 
                     73: void i860_cpu_device::intr() {
                     74:     m_flow |= EXT_INTR;
                     75: }
                     76: 
                     77: /* This is the external interface for indicating an external interrupt
                     78:    to the i860.  */
                     79: void i860_cpu_device::gen_interrupt()
                     80: {
                     81:        /* If interrupts are enabled, then set PSR.IN and prepare for trap.
                     82:           Otherwise, the external interrupt is ignored.  We also set
                     83:           bit EPSR.INT (which tracks the INT pin).  */
                     84:        if (GET_PSR_IM ()) {
                     85:                SET_PSR_IN (1);
                     86:                m_flow |= TRAP_WAS_EXTERNAL;
                     87:        }
                     88:     SET_EPSR_INT (1);
                     89: 
                     90: #if TRACE_EXT_INT
                     91:     Log_Printf(LOG_WARN, "[i860] i860_gen_interrupt: External interrupt received %s", GET_PSR_IM() ? "[PSR.IN set, preparing to trap]" : "[ignored (interrupts disabled)]");
                     92: #endif
                     93: #if ENABLE_PERF_COUNTERS
                     94:     m_intrs++;
                     95: #endif
                     96: }
                     97: 
                     98: 
                     99: /* This is the external interface for indicating an external interrupt
                    100:  to the i860.  */
                    101: void i860_cpu_device::clr_interrupt() {
                    102:     SET_EPSR_INT (0);
                    103: }
                    104: 
                    105: void i860_cpu_device::invalidate_icache() {
                    106:     memset(m_icache_vaddr, 0xff, sizeof(UINT32) * (1<<I860_ICACHE_SZ));
                    107: #if ENABLE_PERF_COUNTERS
                    108:     m_icache_inval++;
                    109: #endif
                    110: }
                    111: 
                    112: void i860_cpu_device::invalidate_tlb() {
                    113:     memset(m_tlb_vaddr, 0xff, sizeof(UINT32) * (1<<I860_TLB_SZ));
                    114: #if ENABLE_PERF_COUNTERS
                    115:     m_tlb_inval++;
                    116: #endif
                    117: }
                    118: 
                    119: UINT32 i860_cpu_device::ifetch_notrap(const UINT32 pc) {
                    120:     UINT32 before     = m_flow;
                    121:     m_flow &= ~TRAP_MASK;
                    122:     UINT32 result  = ifetch(pc);
                    123:     m_flow = before;
                    124:     return result;
                    125: }
                    126: 
                    127: UINT32 i860_cpu_device::ifetch(const UINT32 pc) {
                    128:     return pc & 4 ? ifetch64(pc) >> 32 : ifetch64(pc);
                    129: }
                    130: 
                    131: UINT64 i860_cpu_device::ifetch64(const UINT32 pc) {
                    132:     const UINT32 vaddr = pc & ~7;
                    133:     const int    cidx = (vaddr>>3) & I860_ICACHE_MASK;
                    134:     if(m_icache_vaddr[cidx] != vaddr) {
                    135: #if ENABLE_PERF_COUNTERS
                    136:         m_icache_miss++;
                    137: #endif
                    138:         UINT32 paddr;
                    139:         
                    140:         if (GET_DIRBASE_ATE ()) {
                    141:             paddr = get_address_translation (pc, 0  /* is_dataref */, 0 /* is_write */) & ~7;
                    142:             m_flow &= ~EXITING_IFETCH;
                    143:             if (PENDING_TRAP() && (GET_PSR_DAT () || GET_PSR_IAT ())) {
                    144:                 m_flow |= EXITING_IFETCH;
                    145:                 return 0xffeeffeeffeeffeeLL;
                    146:             }
                    147:         } else
                    148:             paddr = vaddr;
                    149:         
                    150:         m_icache_vaddr[cidx] = vaddr;
                    151:         UINT64 insn64;
                    152:         if (GET_DIRBASE_CS8()) {
                    153:             insn64  = rdcs8(paddr+7); insn64 <<= 8;
                    154:             insn64 |= rdcs8(paddr+6); insn64 <<= 8;
                    155:             insn64 |= rdcs8(paddr+5); insn64 <<= 8;
                    156:             insn64 |= rdcs8(paddr+4); insn64 <<= 8;
                    157:             insn64 |= rdcs8(paddr+3); insn64 <<= 8;
                    158:             insn64 |= rdcs8(paddr+2); insn64 <<= 8;
                    159:             insn64 |= rdcs8(paddr+1); insn64 <<= 8;
                    160:             insn64 |= rdcs8(paddr+0);
                    161:         } else {
                    162:             nd_board_rd64_be(paddr, (UINT32*)&insn64);
                    163:         }
                    164:         m_icache[cidx] = insn64;
                    165:         
                    166:         return insn64;
                    167:     } else {
                    168: #if ENABLE_PERF_COUNTERS
                    169:         m_icache_hit++;
                    170: #endif
                    171:         return m_icache[cidx];
                    172:     }
                    173: }
                    174: 
                    175: /* Given a virtual address, perform the i860 address translation and
                    176:    return the corresponding physical address.
                    177:      vaddr:      virtual address
                    178:      is_dataref: 1 = load/store, 0 = instruction fetch.
                    179:      is_write:   1 = writing to vaddr, 0 = reading from vaddr
                    180:    The last two arguments are only used to determine what types
                    181:    of traps should be taken.
                    182: 
                    183:    Page tables must always be in memory (not cached).  So the routine
                    184:    here only accesses memory.  
                    185:  
                    186:  (SC) added TLB support. Read access updates even entries, Write access updates odd entries.
                    187:  TLB lookup checks both entries. R/W separation is for DPS copy loops.
                    188:  */
                    189: UINT32 i860_cpu_device::get_address_translation (UINT32 vaddr, int is_dataref, int is_write)
                    190: {
                    191:     UINT32 voffset        = vaddr & I860_PAGE_OFF_MASK;
                    192:     UINT32 tlbidx         = ((vaddr << 1) | is_write) & I860_TLB_MASK;
                    193:     
                    194:     if(m_tlb_vaddr[tlbidx] == (vaddr & I860_PAGE_FRAME_MASK)) {
                    195: #if ENABLE_PERF_COUNTERS
                    196:         m_tlb_hit++;
                    197: #endif
                    198:         return (m_tlb_paddr[tlbidx] & I860_PAGE_FRAME_MASK) + voffset;
                    199:     }
                    200: 
                    201:     if(m_tlb_vaddr[tlbidx ^ 1] == (vaddr & I860_PAGE_FRAME_MASK)) {
                    202: #if ENABLE_PERF_COUNTERS
                    203:         m_tlb_hit++;
                    204: #endif
                    205:         return (m_tlb_paddr[tlbidx ^ 1] & I860_PAGE_FRAME_MASK) + voffset;
                    206:     }
                    207: 
                    208: #if ENABLE_PERF_COUNTERS
                    209:     m_tlb_miss++;
                    210: #endif
                    211: 
                    212:     UINT32 vpage          = (vaddr >> I860_PAGE_SZ) & 0x3ff;
                    213:     UINT32 vdir           = (vaddr >> 22) & 0x3ff;
                    214:        UINT32 dtb            = (m_cregs[CR_DIRBASE]) & I860_PAGE_FRAME_MASK;
                    215:        UINT32 pg_dir_entry_a = 0;
                    216:        UINT32 pg_dir_entry   = 0;
                    217:        UINT32 pg_tbl_entry_a = 0;
                    218:        UINT32 pg_tbl_entry   = 0;
                    219:        UINT32 pfa1           = 0;
                    220:        UINT32 pfa2           = 0;
                    221:        UINT32 ret            = 0;
                    222:        UINT32 ttpde          = 0;
                    223:        UINT32 ttpte          = 0;
                    224: 
                    225:        assert (GET_DIRBASE_ATE ());
                    226: 
                    227:        /* Get page directory entry at DTB:DIR:00.  */
                    228:        pg_dir_entry_a = dtb | (vdir << 2);
                    229:     nd_board_rd32_le(pg_dir_entry_a, &pg_dir_entry);
                    230: 
                    231:        /* Check for non-present PDE.  */
                    232:        if (!(pg_dir_entry & 1))
                    233:        {
                    234:                /* PDE is not present, generate DAT or IAT.  */
                    235:                if (is_dataref)
                    236:                        SET_PSR_DAT (1);
                    237:                else
                    238:                        SET_PSR_IAT (1);
                    239:                m_flow |= TRAP_NORMAL;
                    240: 
                    241:                /* Dummy return.  */
                    242:                return 0;
                    243:        }
                    244: 
                    245:        /* PDE Check for write protection violations.  */
                    246:        if (is_write && is_dataref
                    247:                && !(pg_dir_entry & 2)                  /* W = 0.  */
                    248:                && (GET_PSR_U () || GET_EPSR_WP ()))   /* PSR_U = 1 or EPSR_WP = 1.  */
                    249:        {
                    250:                SET_PSR_DAT (1);
                    251:         m_flow |= TRAP_NORMAL;
                    252:                /* Dummy return.  */
                    253:                return 0;
                    254:        }
                    255: 
                    256:        /* PDE Check for user-mode access to supervisor pages.  */
                    257:        if (GET_PSR_U ()
                    258:                && !(pg_dir_entry & 4))                 /* U = 0.  */
                    259:        {
                    260:                if (is_dataref)
                    261:                        SET_PSR_DAT (1);
                    262:                else
                    263:                        SET_PSR_IAT (1);
                    264:                m_flow |= TRAP_NORMAL;
                    265:                /* Dummy return.  */
                    266:                return 0;
                    267:        }
                    268: 
                    269:        /* FIXME: How exactly to handle A check/update?.  */
                    270: 
                    271:        /* Get page table entry at PFA1:PAGE:00.  */
                    272:        pfa1 = pg_dir_entry & I860_PAGE_FRAME_MASK;
                    273:        pg_tbl_entry_a = pfa1 | (vpage << 2);
                    274:     nd_board_rd32_le(pg_tbl_entry_a, &pg_tbl_entry);
                    275: 
                    276:        /* Check for non-present PTE.  */
                    277:        if (!(pg_tbl_entry & 1))
                    278:        {
                    279:                /* PTE is not present, generate DAT or IAT.  */
                    280:                if (is_dataref)
                    281:                        SET_PSR_DAT (1);
                    282:                else
                    283:                        SET_PSR_IAT (1);
                    284:                m_flow |= TRAP_NORMAL;
                    285: 
                    286:                /* Dummy return.  */
                    287:                return 0;
                    288:        }
                    289: 
                    290:        /* PTE Check for write protection violations.  */
                    291:        if (is_write && is_dataref
                    292:                && !(pg_tbl_entry & 2)                  /* W = 0.  */
                    293:                && (GET_PSR_U () || GET_EPSR_WP ()))   /* PSR_U = 1 or EPSR_WP = 1.  */
                    294:        {
                    295:                SET_PSR_DAT (1);
                    296:                m_flow |= TRAP_NORMAL;
                    297:                /* Dummy return.  */
                    298:                return 0;
                    299:        }
                    300: 
                    301:        /* PTE Check for user-mode access to supervisor pages.  */
                    302:        if (GET_PSR_U ()
                    303:                && !(pg_tbl_entry & 4))                 /* U = 0.  */
                    304:        {
                    305:                if (is_dataref)
                    306:                        SET_PSR_DAT (1);
                    307:                else
                    308:                        SET_PSR_IAT (1);
                    309:                m_flow |= TRAP_NORMAL;
                    310:                /* Dummy return.  */
                    311:                return 0;
                    312:        }
                    313: 
                    314:        /* Update A bit and check D bit.  */
                    315:        ttpde = pg_dir_entry | 0x20;
                    316:        ttpte = pg_tbl_entry | 0x20;
                    317:     nd_board_wr32_le(pg_dir_entry_a, &ttpde);
                    318:     nd_board_wr32_le(pg_tbl_entry_a, &ttpte);
                    319: 
                    320:        if (is_write && is_dataref && (pg_tbl_entry & 0x40) == 0)
                    321:        {
                    322:                /* Log_Printf(LOG_WARN, "[i860] DAT trap on write without dirty bit v%08X/p%08X\n",
                    323:                   vaddr, (pg_tbl_entry & ~0xfff)|voffset); */
                    324:                SET_PSR_DAT (1);
                    325:                m_flow |= TRAP_NORMAL;
                    326:                /* Dummy return.  */
                    327:                return 0;
                    328:        }
                    329: 
                    330:        pfa2 = (pg_tbl_entry & I860_PAGE_FRAME_MASK);
                    331:     
                    332:     m_tlb_vaddr[tlbidx] = vaddr & I860_PAGE_FRAME_MASK;
                    333:     m_tlb_paddr[tlbidx] = pfa2;
                    334:     
                    335:        ret = pfa2 | voffset;
                    336: 
                    337: #if TRACE_ADDR_TRANSLATION
                    338:        Log_Printf(LOG_WARN, "[i860] get_address_translation: virt(%08X) -> phys(%08X)\n", vaddr, ret);
                    339: #endif
                    340: 
                    341:        return ret;
                    342: }
                    343: 
                    344: /* Write memory emulation.
                    345:      addr = address to write.
                    346:      size = size of write in bytes.
                    347:      data = data to write.  */
                    348: void i860_cpu_device::writemem_emu (UINT32 addr, int size, UINT8 *data) {
                    349: #if TRACE_RDWR_MEM
                    350:        Log_Printf(LOG_WARN, "[i860] wrmem (ATE=%d) addr = %08X, size = %d, data = %08X\n", GET_DIRBASE_ATE (), addr, size, data); fflush(0);
                    351: #endif
                    352: 
                    353: #if ENABLE_DEBUGGER
                    354:     dbg_check_wr(addr, size, data);
                    355: #endif
                    356: 
                    357:        /* If virtual mode, do translation.  */
                    358:        if (GET_DIRBASE_ATE ())
                    359:        {
                    360:                UINT32 phys = get_address_translation (addr, 1 /* is_dataref */, 1 /* is_write */);
                    361:                if (PENDING_TRAP() && (GET_PSR_IAT () || GET_PSR_DAT ()))
                    362:                {
                    363: #if TRACE_PAGE_FAULT
                    364:             Log_Printf(LOG_WARN, "[i860] %08X: ## Page fault (writememi_emu) virt=%08X", m_pc, addr);
                    365: #endif
                    366:                        SET_EXITING_MEMRW(EXITING_WRITEMEM);
                    367:                        return;
                    368:                }
                    369:                addr = phys;
                    370:        }
                    371: 
                    372: #if ENABLE_I860_DB_BREAK
                    373:        /* First check for match to db register (before write).  */
                    374:        if (((addr & ~(size - 1)) == m_cregs[CR_DB]) && GET_PSR_BW ())
                    375:        {
                    376:                SET_PSR_DAT (1);
                    377:                m_flow |= TRAP_NORMAL;
                    378:                return;
                    379:        }
                    380: #endif
                    381:     
                    382:        /* Now do the actual write.  */
                    383:     wrmem[size](addr, (UINT32*)data);
                    384: }
                    385: 
                    386: 
                    387: /* Floating-point read mem routine.
                    388:      addr = address to read.
                    389:      size = size of read in bytes.
                    390:      dest = memory to put read data.  */
                    391: void i860_cpu_device::readmem_emu (UINT32 addr, int size, UINT8 *dest)
                    392: {
                    393: #if TRACE_RDWR_MEM
                    394:        Log_Printf(LOG_WARN, "[i860] fp_rdmem (ATE=%d) addr = %08X, size = %d\n", GET_DIRBASE_ATE (), addr, size); fflush(0);
                    395: #endif
                    396:     
                    397:        /* If virtual mode, do translation.  */
                    398:        if (GET_DIRBASE_ATE ())
                    399:        {
                    400:                UINT32 phys = get_address_translation (addr, 1 /* is_dataref */, 0 /* is_write */);
                    401:                if (PENDING_TRAP() && (GET_PSR_IAT () || GET_PSR_DAT ()))
                    402:                {
                    403: #if TRACE_PAGE_FAULT
                    404:                        Log_Printf(LOG_WARN, "[i860] %08X: ## Page fault (fp_readmem_emu) virt=%08X",m_pc,addr);
                    405: //            debugger();
                    406: #endif
                    407:                        SET_EXITING_MEMRW(EXITING_FPREADMEM);
                    408:                        return;
                    409:                }
                    410:                addr = phys;
                    411:        }
                    412: 
                    413: #if ENABLE_I860_DB_BREAK
                    414:        /* First check for match to db register (before read).  */
                    415:        if (((addr & ~(size - 1)) == m_cregs[CR_DB]) && GET_PSR_BR ())
                    416:        {
                    417:                SET_PSR_DAT (1);
                    418:                m_flow |= TRAP_NORMAL;
                    419:                return;
                    420:        }
                    421: #endif
                    422:     rdmem[size](addr, (UINT32*)dest);
                    423: }
                    424: 
                    425: 
                    426: /* Floating-point write mem routine.
                    427:      addr = address to write.
                    428:      size = size of write in bytes.
                    429:      data = pointer to the data.
                    430:      wmask = bit mask of bytes to write (only for pst.d).  */
                    431: void i860_cpu_device::writemem_emu (UINT32 addr, int size, UINT8 *data, UINT32 wmask)
                    432: {
                    433: #if TRACE_RDWR_MEM
                    434:        Log_Printf(LOG_WARN, "[i860] fp_wrmem (ATE=%d) addr = %08X, size = %d", GET_DIRBASE_ATE (), addr, size); fflush(0);
                    435: #endif
                    436: 
                    437:        /* If virtual mode, do translation.  */
                    438:        if (GET_DIRBASE_ATE ())
                    439:        {
                    440:                UINT32 phys = get_address_translation (addr, 1 /* is_dataref */, 1 /* is_write */);
                    441:                if (PENDING_TRAP() && GET_PSR_DAT ())
                    442:                {
                    443: #if TRACE_PAGE_FAULT
                    444:                        Log_Printf(LOG_WARN, "[i860] %08X: ## Page fault (fp_writememi_emu) virt=%08X", m_pc,addr);
                    445: //            debugger();
                    446: #endif
                    447:                        SET_EXITING_MEMRW(EXITING_WRITEMEM);
                    448:                        return;
                    449:                }
                    450:                addr = phys;
                    451:        }
                    452: 
                    453: #if ENABLE_I860_DB_BREAK
                    454:        /* First check for match to db register (before read).  */
                    455:        if (((addr & ~(size - 1)) == m_cregs[CR_DB]) && GET_PSR_BW ())
                    456:        {
                    457:                SET_PSR_DAT (1);
                    458:         m_flow |= TRAP_NORMAL;
                    459:                return;
                    460:        }
                    461: #endif
                    462:         
                    463:     if(size == 8 && wmask != 0xff) {
                    464:         if (wmask & 0x80) wrmem[1](addr+0, (UINT32*)&data[0]);
                    465:         if (wmask & 0x40) wrmem[1](addr+1, (UINT32*)&data[1]);
                    466:         if (wmask & 0x20) wrmem[1](addr+2, (UINT32*)&data[2]);
                    467:         if (wmask & 0x10) wrmem[1](addr+3, (UINT32*)&data[3]);
                    468:         if (wmask & 0x08) wrmem[1](addr+4, (UINT32*)&data[4]);
                    469:         if (wmask & 0x04) wrmem[1](addr+5, (UINT32*)&data[5]);
                    470:         if (wmask & 0x02) wrmem[1](addr+6, (UINT32*)&data[6]);
                    471:         if (wmask & 0x01) wrmem[1](addr+7, (UINT32*)&data[7]);
                    472:     } else {
                    473:         wrmem[size](addr, (UINT32*)data);
                    474:     }
                    475: }
                    476: 
                    477: /* Sign extend N-bit number.  */
                    478: inline INT32 sign_ext (UINT32 x, int n)
                    479: {
                    480:        INT32 t;
                    481:        t = x >> (n - 1);
                    482:        t = ((-t) << n) | x;
                    483:        return t;
                    484: }
                    485: 
                    486: 
                    487: void i860_cpu_device::unrecog_opcode (UINT32 pc, UINT32 insn) {
                    488:        debugger('d', "unrecognized opcode %08X pc=%08X", insn, pc);
                    489:     SET_PSR_IT (1);
                    490:     m_flow |= TRAP_NORMAL;
                    491: }
                    492: 
                    493: 
                    494: /* Execute "ld.c csrc2,idest" instruction.  */
                    495: void i860_cpu_device::insn_ld_ctrl (UINT32 insn)
                    496: {
                    497:        UINT32 csrc2 = get_creg (insn);
                    498:        UINT32 idest = get_idest (insn);
                    499: 
                    500: #if TRACE_UNDEFINED_I860
                    501:        if (csrc2 > 5)
                    502:        {
                    503:                /* Control register not between 0..5.  Undefined i860XR behavior.  */
                    504:                Log_Printf(LOG_WARN, "[i860:%08X] insn_ld_from_ctrl: bad creg in ld.c (ignored)", m_pc);
                    505:                return;
                    506:        }
                    507: #endif
                    508: 
                    509:        /* If this is a load of the fir, then there are two cases:
                    510:           1. First load of fir after a trap = usual value.
                    511:           2. Not first load of fir after a trap = address of the ld.c insn.  */
                    512:        if (csrc2 == CR_FIR)
                    513:        {
                    514:                if (m_flow & FIR_GETS_TRAP)
                    515:                        set_iregval (idest, m_cregs[csrc2]);
                    516:                else
                    517:                {
                    518:                        m_cregs[csrc2] = m_pc;
                    519:                        set_iregval (idest, m_cregs[csrc2]);
                    520:                }
                    521:         m_flow &= ~FIR_GETS_TRAP;
                    522:        }
                    523:        else
                    524:                set_iregval (idest, m_cregs[csrc2]);
                    525: }
                    526: 
                    527: 
                    528: /* Execute "st.c isrc1,csrc2" instruction.  */
                    529: void i860_cpu_device::insn_st_ctrl (UINT32 insn)
                    530: {
                    531:        UINT32 csrc2 = get_creg (insn);
                    532:        UINT32 isrc1 = get_isrc1 (insn);
                    533: 
                    534: #if TRACE_UNDEFINED_I860
                    535:        if (csrc2 > 5)
                    536:        {
                    537:                /* Control register not between 0..5.  Undefined i860XR behavior.  */
                    538:                Log_Printf(LOG_WARN, "[i860:%08X] insn_st_to_ctrl: bad creg in st.c (ignored)", m_pc);
                    539:                return;
                    540:        }
                    541: #endif
                    542: 
                    543:     /* Look for CS8 bit turned off).  */
                    544:     if (csrc2 == CR_DIRBASE && (get_iregval (isrc1) & 0x80) == 0 && GET_DIRBASE_CS8()) {
                    545:         Log_Printf(LOG_WARN, "[i860:%08X] Leaving CS8 mode", m_pc);
                    546:                Statusbar_SetNdLed(2);
                    547:     }
                    548:     
                    549:        /* Look for ITI bit turned on (but it never actually is written --
                    550:           it always appears to be 0).  */
                    551:        if (csrc2 == CR_DIRBASE && (get_iregval (isrc1) & 0x20))
                    552:        {
                    553:         invalidate_icache();
                    554:         invalidate_tlb();
                    555:         
                    556:                /* Make sure ITI isn't actually written.  */
                    557:                set_iregval (isrc1, (get_iregval (isrc1) & ~0x20));
                    558:        }
                    559: 
                    560:        if (csrc2 == CR_DIRBASE && (get_iregval (isrc1) & 1) && GET_DIRBASE_ATE () == 0){
                    561:                Log_Printf(LOG_WARN, "[i860:%08X]** Switching to virtual addressing (ATE=1)", m_pc);
                    562:        }
                    563: 
                    564:        /* Update the register -- unless it is fir which cannot be updated.  */
                    565:        if (csrc2 == CR_EPSR)
                    566:        {
                    567:                UINT32 enew = 0, tmp = 0;
                    568:                /* Make sure unchangeable EPSR bits stay unchanged (DCS, stepping,
                    569:                   and type).  Also, some bits are only writeable in supervisor
                    570:                   mode.  */
                    571:                if (GET_PSR_U ())
                    572:                {
                    573:                        enew = get_iregval (isrc1) & ~(0x003e1fff | 0x00c06000);
                    574:                        tmp = m_cregs[CR_EPSR] & (0x003e1fff | 0x00c06000);
                    575:                }
                    576:                else
                    577:                {
                    578:                        enew = get_iregval (isrc1) & ~0x003e1fff;
                    579:                        tmp = m_cregs[CR_EPSR] & 0x003e1fff;
                    580:                }
                    581:         if((enew ^ m_cregs[CR_EPSR]) & 0x00800000) { // BE/LE change
                    582:             set_mem_access((enew & 0x00800000) != 0);
                    583:         }
                    584:                m_cregs[CR_EPSR] = enew | tmp;
                    585:        }
                    586:        else if (csrc2 == CR_PSR)
                    587:        {
                    588:                /* Some PSR bits are only writeable in supervisor mode.  */
                    589:                if (GET_PSR_U ())
                    590:                {
                    591:                        UINT32 enew = get_iregval (isrc1) & ~PSR_SUPERVISOR_ONLY_MASK;
                    592:                        UINT32 tmp = m_cregs[CR_PSR] & PSR_SUPERVISOR_ONLY_MASK;
                    593:                        m_cregs[CR_PSR] = enew | tmp;
                    594:                }
                    595:                else
                    596:                        m_cregs[CR_PSR] = get_iregval (isrc1);
                    597:        }
                    598:        else if (csrc2 == CR_FSR)
                    599:        {
                    600:                /* I believe that only 21..17, 8..5, and 3..0 should be updated.  */
                    601:                UINT32 enew = get_iregval (isrc1) & 0x003e01ef;
                    602:                UINT32 tmp = m_cregs[CR_FSR] & ~0x003e01ef;
                    603:                m_cregs[CR_FSR] = enew | tmp;
                    604:         switch(GET_FSR_RM()) {
                    605:             case 0: fesetround(FE_TONEAREST);  break;
                    606:             case 1: fesetround(FE_DOWNWARD);   break;
                    607:             case 2: fesetround(FE_UPWARD);     break;
                    608:             case 3: fesetround(FE_TOWARDZERO); break;
                    609:         }
                    610:        }
                    611:        else if (csrc2 != CR_FIR)
                    612:                m_cregs[csrc2] = get_iregval (isrc1);
                    613: }
                    614: 
                    615: 
                    616: /* Execute "ld.{s,b,l} isrc1(isrc2),idest" or
                    617:    "ld.{s,b,l} #const(isrc2),idest".  */
                    618: void i860_cpu_device::insn_ldx (UINT32 insn)
                    619: {
                    620:        UINT32 isrc1 = get_isrc1 (insn);
                    621:        INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
                    622:        UINT32 isrc2 = get_isrc2 (insn);
                    623:        UINT32 idest = get_idest (insn);
                    624:        UINT32 eff = 0;
                    625:        /* Operand size, in bytes.  */
                    626:        int sizes[4] = { 1, 1, 2, 4};
                    627:        int size = 0;
                    628:        int form_disp_reg = 0;
                    629: 
                    630:        /* Bits 28 and 0 determine the operand size.  */
                    631:        size = sizes[((insn >> 27) & 2) | (insn & 1)];
                    632: 
                    633:        /* Bit 26 determines the addressing mode (reg+reg or disp+reg).  */
                    634:        form_disp_reg = (insn & 0x04000000);
                    635: 
                    636:        /* Get effective address depending on disp+reg or reg+reg form.  */
                    637:        if (form_disp_reg)
                    638:        {
                    639:                /* Chop off lower bits of displacement.  */
                    640:                immsrc1 &= ~(size - 1);
                    641:                eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2)));
                    642:        }
                    643:        else
                    644:                eff = get_iregval (isrc1) + get_iregval (isrc2);
                    645: 
                    646: #if TRACE_UNALIGNED_MEM
                    647:        if (eff & (size - 1))
                    648:        {
                    649:                Log_Printf(LOG_WARN, "[i860:%08X] Unaligned access detected (%08X)", m_pc, eff);
                    650:                SET_PSR_DAT (1);
                    651:                m_flow |= TRAP_NORMAL;
                    652:                return;
                    653:        }
                    654: #endif
                    655: 
                    656:        /* The i860 sign-extends 8- or 16-bit integer loads.
                    657: 
                    658:           Below, the readmemi_emu() needs to happen outside of the
                    659:           set_iregval macro (otherwise the readmem won't occur if r0
                    660:           is the target register).  */
                    661:        if (size < 4) {
                    662:         UINT32 readval = 0; readmem_emu(eff, size, (UINT8*)&readval);
                    663:         readval = sign_ext (readval, size * 8);
                    664:                /* Do not update register on page fault.  */
                    665:                if (GET_EXITING_MEMRW())
                    666:                {
                    667:                        return;
                    668:                }
                    669:                set_iregval (idest, readval);
                    670:        }
                    671:        else
                    672:        {
                    673:         UINT32 readval; readmem_emu(eff, size, (UINT8*)&readval);
                    674:                /* Do not update register on page fault.  */
                    675:                if (GET_EXITING_MEMRW())
                    676:                {
                    677:                        return;
                    678:                }
                    679:                set_iregval (idest, readval);
                    680:        }
                    681: }
                    682: 
                    683: 
                    684: /* Execute "st.x isrc1ni,#const(isrc2)" instruction (there is no
                    685:    (reg + reg form).  Store uses the split immediate, not the normal
                    686:    16-bit immediate as in ld.x.  */
                    687: void i860_cpu_device::insn_stx (UINT32 insn)
                    688: {
                    689:        INT32 immsrc = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
                    690:        UINT32 isrc1 = get_isrc1 (insn);
                    691:        UINT32 isrc2 = get_isrc2 (insn);
                    692:        UINT32 eff = 0;
                    693:        /* Operand size, in bytes.  */
                    694:        int sizes[4] = { 1, 1, 2, 4};
                    695:        int size = 0;
                    696: 
                    697:        /* Bits 28 and 0 determine the operand size.  */
                    698:        size = sizes[((insn >> 27) & 2) | (insn & 1)];
                    699: 
                    700:        /* FIXME: Do any necessary traps.  */
                    701: 
                    702:        /* Get effective address.  Chop off lower bits of displacement.  */
                    703:        immsrc &= ~(size - 1);
                    704:        eff = (UINT32)(immsrc + (INT32)get_iregval (isrc2));
                    705: 
                    706:        /* Write data (value of reg isrc1) to memory at eff.  */
                    707:     UINT32 tmp32 = get_iregval (isrc1);
                    708:        writemem_emu (eff, size, (UINT8*)&tmp32);
                    709:        if (GET_EXITING_MEMRW())
                    710:                return;
                    711: }
                    712: 
                    713: 
                    714: /* Execute "fst.y fdest,isrc1(isrc2)", "fst.y fdest,isrc1(isrc2)++",
                    715:            "fst.y fdest,#const(isrc2)" or "fst.y fdest,#const(isrc2)++"
                    716:    instruction.  */
                    717: void i860_cpu_device::insn_fsty (UINT32 insn)
                    718: {
                    719:        UINT32 isrc1 = get_isrc1 (insn);
                    720:        INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
                    721:        UINT32 isrc2 = get_isrc2 (insn);
                    722:        UINT32 fdest = get_fdest (insn);
                    723:        UINT32 eff = 0;
                    724:        /* Operand size, in bytes.  */
                    725:        int sizes[4] = { 8, 4, 16, 4};
                    726:        int size = 0;
                    727:        int form_disp_reg = 0;
                    728:        int auto_inc = (insn & 1);
                    729: 
                    730:        /* Bits 2 and 1 determine the operand size.  */
                    731:        size = sizes[((insn >> 1) & 3)];
                    732: 
                    733:        /* Bit 26 determines the addressing mode (reg+reg or disp+reg).  */
                    734:        form_disp_reg = (insn & 0x04000000);
                    735: 
                    736:        /* FIXME: Check for undefined behavior, non-even or non-quad
                    737:           register operands for fst.d and fst.q respectively.  */
                    738: 
                    739:        /* Get effective address depending on disp+reg or reg+reg form.  */
                    740:        if (form_disp_reg)
                    741:        {
                    742:                /* Chop off lower bits of displacement.  */
                    743:                immsrc1 &= ~(size - 1);
                    744:                eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2)));
                    745:        }
                    746:        else
                    747:                eff = get_iregval (isrc1) + get_iregval (isrc2);
                    748: 
                    749: #if TRACE_UNALIGNED_MEM
                    750:        if (eff & (size - 1))
                    751:        {
                    752:                Log_Printf(LOG_WARN, "[i860:%08X] Unaligned access detected (%08X)", m_pc, eff);
                    753:                SET_PSR_DAT (1);
                    754:                m_flow |= TRAP_NORMAL;
                    755:                return;
                    756:        }
                    757: #endif
                    758: 
                    759:        /* Do (post) auto-increment.  */
                    760:        if (auto_inc)
                    761:        {
                    762:                set_iregval (isrc2, eff);
                    763: #if TRACE_UNDEFINED_I860
                    764:                /* When auto-inc, isrc1 and isrc2 regs can't be the same.  */
                    765:                if (isrc1 == isrc2)
                    766:                {
                    767:                        /* Undefined i860XR behavior.  */
                    768:                        Log_Printf(LOG_WARN, "[i860:%08X] insn_fsty: isrc1 = isrc2 in fst with auto-inc (ignored)", m_pc);
                    769:                        return;
                    770:                }
                    771: #endif
                    772:        }
                    773: 
                    774:        /* Write data (value of freg fdest) to memory at eff.  */
                    775:        writemem_emu (eff, size, (UINT8 *)(&m_fregs[4 * fdest]), 0xff);
                    776: }
                    777: 
                    778: 
                    779: /* Execute "fld.y isrc1(isrc2),fdest", "fld.y isrc1(isrc2)++,idest",
                    780:            "fld.y #const(isrc2),fdest" or "fld.y #const(isrc2)++,idest".
                    781:    Where y = {l,d,q}.  Note, there is no pfld.q, though.  */
                    782: void i860_cpu_device::insn_fldy (UINT32 insn)
                    783: {
                    784:        UINT32 isrc1 = get_isrc1 (insn);
                    785:        INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
                    786:        UINT32 isrc2 = get_isrc2 (insn);
                    787:        UINT32 fdest = get_fdest (insn);
                    788:        UINT32 eff = 0;
                    789:        /* Operand size, in bytes.  */
                    790:        int sizes[4] = { 8, 4, 16, 4};
                    791:        int size = 0;
                    792:        int form_disp_reg = 0;
                    793:        int auto_inc = (insn & 1);
                    794:        int piped = (insn & 0x40000000);
                    795: 
                    796:        /* Bits 2 and 1 determine the operand size.  */
                    797:        size = sizes[((insn >> 1) & 3)];
                    798: 
                    799:        /* Bit 26 determines the addressing mode (reg+reg or disp+reg).  */
                    800:        form_disp_reg = (insn & 0x04000000);
                    801: 
                    802: #if TRACE_UNDEFINED_I860
                    803:        /* There is no pipelined load quad.  */
                    804:        if (piped && size == 16)
                    805:        {
                    806:                unrecog_opcode (m_pc, insn);
                    807:                return;
                    808:        }
                    809: #endif
                    810:     
                    811:        /* FIXME: Check for undefined behavior, non-even or non-quad
                    812:           register operands for fld.d and fld.q respectively.  */
                    813: 
                    814:        /* Get effective address depending on disp+reg or reg+reg form.  */
                    815:        if (form_disp_reg)
                    816:        {
                    817:                /* Chop off lower bits of displacement.  */
                    818:                immsrc1 &= ~(size - 1);
                    819:                eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2)));
                    820:        }
                    821:        else
                    822:                eff = get_iregval (isrc1) + get_iregval (isrc2);
                    823: 
                    824:        /* Do (post) auto-increment.  */
                    825:        if (auto_inc)
                    826:        {
                    827:                set_iregval (isrc2, eff);
                    828: #if TRACE_UNDEFINED_I860
                    829:                /* When auto-inc, isrc1 and isrc2 regs can't be the same.  */
                    830:                if (isrc1 == isrc2)
                    831:                {
                    832:                        /* Undefined i860XR behavior.  */
                    833:                        Log_Printf(LOG_WARN, "[i860:%08X] insn_fldy: isrc1 = isrc2 in fst with auto-inc (ignored)", m_pc);
                    834:                        return;
                    835:                }
                    836: #endif
                    837:        }
                    838: 
                    839: #if TRACE_UNALIGNED_MEM
                    840:        if (eff & (size - 1))
                    841:        {
                    842:                Log_Printf(LOG_WARN, "[i860:%08X] Unaligned access detected (%08X)", m_pc, eff);
                    843:                SET_PSR_DAT (1);
                    844:         m_flow |= TRAP_NORMAL;
                    845:                return;
                    846:        }
                    847: #endif
                    848: 
                    849:        /* Update the load pipe if necessary.  */
                    850:        /* FIXME: Copy result-status bits to fsr from last stage.  */
                    851:        if (!piped)
                    852:        {
                    853:                /* Scalar version writes the current result to fdest.  */
                    854:                /* Read data at 'eff' into freg 'fdest' (reads to f0 or f1 are
                    855:                   thrown away).  */
                    856:         readmem_emu(eff, size, (UINT8 *)&(m_fregs[4 * fdest]));
                    857:                if (fdest < 2) {
                    858:             // (SC) special case with fdest=fr0/fr1. fr0 & fr1 are overwritten with values from mem
                    859:             // but always read as zero. Fix it.
                    860:             m_fregs[0] = 0; m_fregs[1] = 0; m_fregs[2] = 0; m_fregs[3] = 0;
                    861:             m_fregs[4] = 0; m_fregs[5] = 0; m_fregs[6] = 0; m_fregs[7] = 0;
                    862:         }
                    863:        }
                    864:        else
                    865:        {
                    866:                /* Read the data into a temp space first.  This way we can test
                    867:                   for any traps before updating the pipeline.  The pipeline must
                    868:                   stay unaffected after a trap so that the instruction can be
                    869:                   properly restarted.  */
                    870:                UINT8 bebuf[8];
                    871:                readmem_emu (eff, size, bebuf);
                    872:                if (PENDING_TRAP() && GET_EXITING_MEMRW())
                    873:                        goto ab_op;
                    874: 
                    875:                /* Pipelined version writes fdest with the result from the last
                    876:                   stage of the pipeline, with precision specified by the LRP
                    877:                   bit of the stage's result-status bits.  */
                    878: #if 1 /* FIXME: WIP on FSR update.  This may not be correct.  */
                    879:                /* Copy 3rd stage LRP to FSR.  */
                    880:                if (m_L[1 /* 2 */].stat.lrp)
                    881:                        m_cregs[CR_FSR] |= 0x04000000;
                    882:                else
                    883:                        m_cregs[CR_FSR] &= ~0x04000000;
                    884: #endif
                    885:                if (m_L[2].stat.lrp)  /* 3rd (last) stage.  */
                    886:                        set_fregval_d (fdest, m_L[2].val.d);
                    887:                else
                    888:                        set_fregval_s (fdest, m_L[2].val.s);
                    889: 
                    890:                /* Now advance pipeline and write loaded data to first stage.  */
                    891:                m_L[2] = m_L[1];
                    892:                m_L[1] = m_L[0];
                    893:                if (size == 8) {
                    894:             m_L[0].val.d = *((double*)bebuf);
                    895:                        m_L[0].stat.lrp = 1;
                    896:                } else {
                    897:             m_L[0].val.s = *((float*)bebuf);
                    898:                        m_L[0].stat.lrp = 0;
                    899:                }
                    900:        }
                    901: 
                    902:        ab_op:;
                    903: }
                    904: 
                    905: 
                    906: /* Execute "pst.d fdest,#const(isrc2)" or "fst.d fdest,#const(isrc2)++"
                    907:    instruction.  */
                    908: void i860_cpu_device::insn_pstd (UINT32 insn)
                    909: {
                    910:        INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
                    911:        UINT32 isrc2 = get_isrc2 (insn);
                    912:        UINT32 fdest = get_fdest (insn);
                    913:        UINT32 eff = 0;
                    914:        int auto_inc = (insn & 1);
                    915:        int pm = GET_PSR_PM ();
                    916:        int i;
                    917:        UINT32 wmask;
                    918:        int orig_pm = pm;
                    919: 
                    920:        /* Get the pixel size, where:
                    921:           PS: 0 = 8 bits, 1 = 16 bits, 2 = 32-bits.  */
                    922:        int ps = GET_PSR_PS ();
                    923: 
                    924: #if TRACE_UNDEFINED_I860
                    925:        if (!(ps == 0 || ps == 1 || ps == 2))
                    926:                Log_Printf(LOG_WARN, "[i860:%08X] insn_pstd: Undefined i860XR behavior, invalid value %d for pixel size", m_pc, ps);
                    927: #endif
                    928: 
                    929: #if TRACE_UNDEFINED_I860
                    930:        /* Bits 2 and 1 determine the operand size, which must always be
                    931:           zero (indicating a 64-bit operand).  */
                    932:        if (insn & 0x6)
                    933:        {
                    934:                /* Undefined i860XR behavior.  */
                    935:                Log_Printf(LOG_WARN, "[i860:%08X] insn_pstd: bad operand size specifier", m_pc);
                    936:        }
                    937: #endif
                    938: 
                    939:        /* FIXME: Check for undefined behavior, non-even register operands.  */
                    940: 
                    941:        /* Get effective address.  Chop off lower bits of displacement.  */
                    942:        immsrc1 &= ~(8 - 1);
                    943:        eff = (UINT32)(immsrc1 + (INT32)(get_iregval (isrc2)));
                    944: 
                    945: #if TRACE_UNALIGNED_MEM
                    946:        if (eff & (8 - 1))
                    947:        {
                    948:                Log_Printf(LOG_WARN, "[i860:%08X] Unaligned access detected (%08X)", m_pc, eff);
                    949:                SET_PSR_DAT (1);
                    950:                m_flow |= TRAP_NORMAL;
                    951:                return;
                    952:        }
                    953: #endif
                    954: 
                    955:        /* Do (post) auto-increment.  */
                    956:        if (auto_inc)
                    957:                set_iregval (isrc2, eff);
                    958: 
                    959:        /* Update the pixel mask depending on the pixel size.  Shift PM
                    960:           right by 8/2^ps bits.  */
                    961:        if (ps == 0)
                    962:                pm = (pm >> 8) & 0x00;
                    963:        else if (ps == 1)
                    964:                pm = (pm >> 4) & 0x0f;
                    965:        else if (ps == 2)
                    966:                pm = (pm >> 2) & 0x3f;
                    967:        SET_PSR_PM (pm);
                    968: 
                    969:        /* Write data (value of freg fdest) to memory at eff-- but only those
                    970:           bytes that are enabled by the bits in PSR.PM.  Bit 0 of PM selects
                    971:           the pixel at the lowest address.  */
                    972:        wmask = 0;
                    973:        for (i = 0; i < 8; )
                    974:        {
                    975:                if (ps == 0)
                    976:                {
                    977:                        if (orig_pm & 0x80)
                    978:                                wmask |= 1 << (7-i);
                    979:                        i += 1;
                    980:                }
                    981:                else if (ps == 1)
                    982:                {
                    983:                        if (orig_pm & 0x08)
                    984:                                wmask |= 0x3 << (6-i);
                    985:                        i += 2;
                    986:                }
                    987:                else if (ps == 2)
                    988:                {
                    989:                        if (orig_pm & 0x02)
                    990:                                wmask |= 0xf << (4-i);
                    991:                        i += 4;
                    992:                }
                    993:                else
                    994:                {
                    995:                        wmask = 0xff;
                    996:                        break;
                    997:                }
                    998:                orig_pm <<= 1;
                    999:        }
                   1000:        writemem_emu (eff, 8, (UINT8 *)(&m_fregs[4 * fdest]), wmask);
                   1001: }
                   1002: 
                   1003: 
                   1004: /* Execute "ixfr isrc1ni,fdest" instruction.  */
                   1005: void i860_cpu_device::insn_ixfr (UINT32 insn)
                   1006: {
                   1007:        UINT32 isrc1 = get_isrc1 (insn);
                   1008:        UINT32 fdest = get_fdest (insn);
                   1009:        UINT32 iv = 0;
                   1010: 
                   1011:        /* This is a bit-pattern transfer, not a conversion.  */
                   1012:        iv = get_iregval (isrc1);
                   1013:        set_fregval_s (fdest, *(float *)&iv);
                   1014: }
                   1015: 
                   1016: 
                   1017: /* Execute "addu isrc1,isrc2,idest".  */
                   1018: void i860_cpu_device::insn_addu (UINT32 insn)
                   1019: {
                   1020:        UINT32 src1val;
                   1021:        UINT32 isrc2 = get_isrc2 (insn);
                   1022:        UINT32 idest = get_idest (insn);
                   1023:        UINT32 tmp_dest_val = 0;
                   1024:        UINT64 tmp = 0;
                   1025: 
                   1026:        src1val = get_iregval (get_isrc1 (insn));
                   1027: 
                   1028:        /* We don't update the actual idest register now because below we
                   1029:           need to test the original src1 and src2 if either happens to
                   1030:           be the destination register.  */
                   1031:        tmp_dest_val = src1val + get_iregval (isrc2);
                   1032: 
                   1033:        /* Set OF and CC flags.
                   1034:           For unsigned:
                   1035:             OF = bit 31 carry
                   1036:             CC = bit 31 carry.
                   1037:         */
                   1038:        tmp = (UINT64)src1val + (UINT64)(get_iregval (isrc2));
                   1039:        if ((tmp >> 32) & 1) {
                   1040:                SET_PSR_CC (1);
                   1041:                SET_EPSR_OF (1);
                   1042:        } else {
                   1043:                SET_PSR_CC (0);
                   1044:                SET_EPSR_OF (0);
                   1045:        }
                   1046: 
                   1047:        /* Now update the destination register.  */
                   1048:        set_iregval (idest, tmp_dest_val);
                   1049: }
                   1050: 
                   1051: 
                   1052: /* Execute "addu #const,isrc2,idest".  */
                   1053: void i860_cpu_device::insn_addu_imm (UINT32 insn)
                   1054: {
                   1055:        UINT32 src1val;
                   1056:        UINT32 isrc2 = get_isrc2 (insn);
                   1057:        UINT32 idest = get_idest (insn);
                   1058:        UINT32 tmp_dest_val = 0;
                   1059:        UINT64 tmp = 0;
                   1060: 
                   1061:        src1val = sign_ext (get_imm16 (insn), 16);
                   1062: 
                   1063:        /* We don't update the actual idest register now because below we
                   1064:           need to test the original src1 and src2 if either happens to
                   1065:           be the destination register.  */
                   1066:        tmp_dest_val = src1val + get_iregval (isrc2);
                   1067: 
                   1068:        /* Set OF and CC flags.
                   1069:           For unsigned:
                   1070:             OF = bit 31 carry
                   1071:             CC = bit 31 carry.
                   1072:         */
                   1073:        tmp = (UINT64)src1val + (UINT64)(get_iregval (isrc2));
                   1074:        if ((tmp >> 32) & 1)
                   1075:        {
                   1076:                SET_PSR_CC (1);
                   1077:                SET_EPSR_OF (1);
                   1078:        }
                   1079:        else
                   1080:        {
                   1081:                SET_PSR_CC (0);
                   1082:                SET_EPSR_OF (0);
                   1083:        }
                   1084: 
                   1085:        /* Now update the destination register.  */
                   1086:        set_iregval (idest, tmp_dest_val);
                   1087: }
                   1088: 
                   1089: 
                   1090: /* Execute "adds isrc1,isrc2,idest".  */
                   1091: void i860_cpu_device::insn_adds (UINT32 insn)
                   1092: {
                   1093:        UINT32 src1val;
                   1094:        UINT32 isrc2 = get_isrc2 (insn);
                   1095:        UINT32 idest = get_idest (insn);
                   1096:        UINT32 tmp_dest_val = 0;
                   1097:        int sa, sb, sres;
                   1098: 
                   1099:        src1val = get_iregval (get_isrc1 (insn));
                   1100: 
                   1101:        /* We don't update the actual idest register now because below we
                   1102:           need to test the original src1 and src2 if either happens to
                   1103:           be the destination register.  */
                   1104:        tmp_dest_val = src1val + get_iregval (isrc2);
                   1105: 
                   1106:        /* Set OF and CC flags.
                   1107:           For signed:
                   1108:             OF = standard signed overflow.
                   1109:             CC set   if isrc2 < -isrc1
                   1110:             CC clear if isrc2 >= -isrc1
                   1111:         */
                   1112:        sa = src1val & 0x80000000;
                   1113:        sb = get_iregval (isrc2) & 0x80000000;
                   1114:        sres = tmp_dest_val & 0x80000000;
                   1115:        if (sa != sb && sa != sres)
                   1116:                SET_EPSR_OF (1);
                   1117:        else
                   1118:                SET_EPSR_OF (0);
                   1119: 
                   1120:        if ((INT32)get_iregval (isrc2) < -(INT32)(src1val))
                   1121:                SET_PSR_CC (1);
                   1122:        else
                   1123:                SET_PSR_CC (0);
                   1124: 
                   1125:        /* Now update the destination register.  */
                   1126:        set_iregval (idest, tmp_dest_val);
                   1127: }
                   1128: 
                   1129: 
                   1130: /* Execute "adds #const,isrc2,idest".  */
                   1131: void i860_cpu_device::insn_adds_imm (UINT32 insn)
                   1132: {
                   1133:        UINT32 src1val;
                   1134:        UINT32 isrc2 = get_isrc2 (insn);
                   1135:        UINT32 idest = get_idest (insn);
                   1136:        UINT32 tmp_dest_val = 0;
                   1137:        int sa, sb, sres;
                   1138: 
                   1139:        src1val = sign_ext (get_imm16 (insn), 16);
                   1140: 
                   1141:        /* We don't update the actual idest register now because below we
                   1142:           need to test the original src1 and src2 if either happens to
                   1143:           be the destination register.  */
                   1144:        tmp_dest_val = src1val + get_iregval (isrc2);
                   1145: 
                   1146:        /* Set OF and CC flags.
                   1147:           For signed:
                   1148:             OF = standard signed overflow.
                   1149:             CC set   if isrc2 < -isrc1
                   1150:             CC clear if isrc2 >= -isrc1
                   1151:         */
                   1152:        sa = src1val & 0x80000000;
                   1153:        sb = get_iregval (isrc2) & 0x80000000;
                   1154:        sres = tmp_dest_val & 0x80000000;
                   1155:        if (sa != sb && sa != sres)
                   1156:                SET_EPSR_OF (1);
                   1157:        else
                   1158:                SET_EPSR_OF (0);
                   1159: 
                   1160:        if ((INT32)get_iregval (isrc2) < -(INT32)(src1val))
                   1161:                SET_PSR_CC (1);
                   1162:        else
                   1163:                SET_PSR_CC (0);
                   1164: 
                   1165:        /* Now update the destination register.  */
                   1166:        set_iregval (idest, tmp_dest_val);
                   1167: }
                   1168: 
                   1169: 
                   1170: /* Execute "subu isrc1,isrc2,idest".  */
                   1171: void i860_cpu_device::insn_subu (UINT32 insn)
                   1172: {
                   1173:        UINT32 src1val;
                   1174:        UINT32 isrc2 = get_isrc2 (insn);
                   1175:        UINT32 idest = get_idest (insn);
                   1176:        UINT32 tmp_dest_val = 0;
                   1177: 
                   1178:        src1val = get_iregval (get_isrc1 (insn));
                   1179: 
                   1180:        /* We don't update the actual idest register now because below we
                   1181:           need to test the original src1 and src2 if either happens to
                   1182:           be the destination register.  */
                   1183:        tmp_dest_val = src1val - get_iregval (isrc2);
                   1184: 
                   1185:        /* Set OF and CC flags.
                   1186:           For unsigned:
                   1187:             OF = NOT(bit 31 carry)
                   1188:             CC = bit 31 carry.
                   1189:             (i.e. CC set   if isrc2 <= isrc1
                   1190:                   CC clear if isrc2 > isrc1
                   1191:         */
                   1192:        if ((UINT32)get_iregval (isrc2) <= (UINT32)src1val)
                   1193:        {
                   1194:                SET_PSR_CC (1);
                   1195:                SET_EPSR_OF (0);
                   1196:        }
                   1197:        else
                   1198:        {
                   1199:                SET_PSR_CC (0);
                   1200:                SET_EPSR_OF (1);
                   1201:        }
                   1202: 
                   1203:        /* Now update the destination register.  */
                   1204:        set_iregval (idest, tmp_dest_val);
                   1205: }
                   1206: 
                   1207: 
                   1208: /* Execute "subu #const,isrc2,idest".  */
                   1209: void i860_cpu_device::insn_subu_imm (UINT32 insn)
                   1210: {
                   1211:        UINT32 src1val;
                   1212:        UINT32 isrc2 = get_isrc2 (insn);
                   1213:        UINT32 idest = get_idest (insn);
                   1214:        UINT32 tmp_dest_val = 0;
                   1215: 
                   1216:        src1val = sign_ext (get_imm16 (insn), 16);
                   1217: 
                   1218:        /* We don't update the actual idest register now because below we
                   1219:           need to test the original src1 and src2 if either happens to
                   1220:           be the destination register.  */
                   1221:        tmp_dest_val = src1val - get_iregval (isrc2);
                   1222: 
                   1223:        /* Set OF and CC flags.
                   1224:           For unsigned:
                   1225:             OF = NOT(bit 31 carry)
                   1226:             CC = bit 31 carry.
                   1227:             (i.e. CC set   if isrc2 <= isrc1
                   1228:                   CC clear if isrc2 > isrc1
                   1229:         */
                   1230:        if ((UINT32)get_iregval (isrc2) <= (UINT32)src1val)
                   1231:        {
                   1232:                SET_PSR_CC (1);
                   1233:                SET_EPSR_OF (0);
                   1234:        }
                   1235:        else
                   1236:        {
                   1237:                SET_PSR_CC (0);
                   1238:                SET_EPSR_OF (1);
                   1239:        }
                   1240: 
                   1241:        /* Now update the destination register.  */
                   1242:        set_iregval (idest, tmp_dest_val);
                   1243: }
                   1244: 
                   1245: 
                   1246: /* Execute "subs isrc1,isrc2,idest".  */
                   1247: void i860_cpu_device::insn_subs (UINT32 insn)
                   1248: {
                   1249:        UINT32 src1val;
                   1250:        UINT32 isrc2 = get_isrc2 (insn);
                   1251:        UINT32 idest = get_idest (insn);
                   1252:        UINT32 tmp_dest_val = 0;
                   1253:        int sa, sb, sres;
                   1254: 
                   1255:        src1val = get_iregval (get_isrc1 (insn));
                   1256: 
                   1257:        /* We don't update the actual idest register now because below we
                   1258:           need to test the original src1 and src2 if either happens to
                   1259:           be the destination register.  */
                   1260:        tmp_dest_val = src1val - get_iregval (isrc2);
                   1261: 
                   1262:        /* Set OF and CC flags.
                   1263:           For signed:
                   1264:             OF = standard signed overflow.
                   1265:             CC set   if isrc2 > isrc1
                   1266:             CC clear if isrc2 <= isrc1
                   1267:         */
                   1268:        sa = src1val & 0x80000000;
                   1269:        sb = get_iregval (isrc2) & 0x80000000;
                   1270:        sres = tmp_dest_val & 0x80000000;
                   1271:        if (sa != sb && sa != sres)
                   1272:                SET_EPSR_OF (1);
                   1273:        else
                   1274:                SET_EPSR_OF (0);
                   1275: 
                   1276:        if ((INT32)get_iregval (isrc2) > (INT32)(src1val))
                   1277:                SET_PSR_CC (1);
                   1278:        else
                   1279:                SET_PSR_CC (0);
                   1280: 
                   1281:        /* Now update the destination register.  */
                   1282:        set_iregval (idest, tmp_dest_val);
                   1283: }
                   1284: 
                   1285: 
                   1286: /* Execute "subs #const,isrc2,idest".  */
                   1287: void i860_cpu_device::insn_subs_imm (UINT32 insn)
                   1288: {
                   1289:        UINT32 src1val;
                   1290:        UINT32 isrc2 = get_isrc2 (insn);
                   1291:        UINT32 idest = get_idest (insn);
                   1292:        UINT32 tmp_dest_val = 0;
                   1293:        int sa, sb, sres;
                   1294: 
                   1295:        src1val = sign_ext (get_imm16 (insn), 16);
                   1296: 
                   1297:        /* We don't update the actual idest register now because below we
                   1298:           need to test the original src1 and src2 if either happens to
                   1299:           be the destination register.  */
                   1300:        tmp_dest_val = src1val - get_iregval (isrc2);
                   1301: 
                   1302:        /* Set OF and CC flags.
                   1303:           For signed:
                   1304:             OF = standard signed overflow.
                   1305:             CC set   if isrc2 > isrc1
                   1306:             CC clear if isrc2 <= isrc1
                   1307:         */
                   1308:        sa = src1val & 0x80000000;
                   1309:        sb = get_iregval (isrc2) & 0x80000000;
                   1310:        sres = tmp_dest_val & 0x80000000;
                   1311:        if (sa != sb && sa != sres)
                   1312:                SET_EPSR_OF (1);
                   1313:        else
                   1314:                SET_EPSR_OF (0);
                   1315: 
                   1316:        if ((INT32)get_iregval (isrc2) > (INT32)(src1val))
                   1317:                SET_PSR_CC (1);
                   1318:        else
                   1319:                SET_PSR_CC (0);
                   1320: 
                   1321:        /* Now update the destination register.  */
                   1322:        set_iregval (idest, tmp_dest_val);
                   1323: }
                   1324: 
                   1325: 
                   1326: /* Execute "shl isrc1,isrc2,idest".  */
                   1327: void i860_cpu_device::insn_shl (UINT32 insn)
                   1328: {
                   1329:        UINT32 src1val = 0;
                   1330:        UINT32 isrc2 = get_isrc2 (insn);
                   1331:        UINT32 idest = get_idest (insn);
                   1332: 
                   1333:        src1val = get_iregval (get_isrc1 (insn));
                   1334:        set_iregval (idest, get_iregval (isrc2) << src1val);
                   1335: }
                   1336: 
                   1337: 
                   1338: /* Execute "shl #const,isrc2,idest".  */
                   1339: void i860_cpu_device::insn_shl_imm (UINT32 insn)
                   1340: {
                   1341:        UINT32 src1val = 0;
                   1342:        UINT32 isrc2 = get_isrc2 (insn);
                   1343:        UINT32 idest = get_idest (insn);
                   1344: 
                   1345:        src1val = sign_ext (get_imm16 (insn), 16);
                   1346:        set_iregval (idest, get_iregval (isrc2) << src1val);
                   1347: }
                   1348: 
                   1349: 
                   1350: /* Execute "shr isrc1,isrc2,idest".  */
                   1351: void i860_cpu_device::insn_shr (UINT32 insn)
                   1352: {
                   1353:        UINT32 src1val = 0;
                   1354:        UINT32 isrc2 = get_isrc2 (insn);
                   1355:        UINT32 idest = get_idest (insn);
                   1356: 
                   1357:        src1val = get_iregval (get_isrc1 (insn));
                   1358: 
                   1359:        /* The iregs array is UINT32, so this is a logical shift.  */
                   1360:        set_iregval (idest, get_iregval (isrc2) >> src1val);
                   1361: 
                   1362:        /* shr also sets the SC in psr (shift count).  */
                   1363:        SET_PSR_SC (src1val);
                   1364: }
                   1365: 
                   1366: 
                   1367: /* Execute "shr #const,isrc2,idest".  */
                   1368: void i860_cpu_device::insn_shr_imm (UINT32 insn)
                   1369: {
                   1370:        UINT32 src1val = 0;
                   1371:        UINT32 isrc2 = get_isrc2 (insn);
                   1372:        UINT32 idest = get_idest (insn);
                   1373: 
                   1374:        src1val = sign_ext (get_imm16 (insn), 16);
                   1375: 
                   1376:        /* The iregs array is UINT32, so this is a logical shift.  */
                   1377:        set_iregval (idest, get_iregval (isrc2) >> src1val);
                   1378: 
                   1379:        /* shr also sets the SC in psr (shift count).  */
                   1380:        SET_PSR_SC (src1val);
                   1381: }
                   1382: 
                   1383: 
                   1384: /* Execute "shra isrc1,isrc2,idest".  */
                   1385: void i860_cpu_device::insn_shra (UINT32 insn)
                   1386: {
                   1387:        UINT32 src1val = 0;
                   1388:        UINT32 isrc2 = get_isrc2 (insn);
                   1389:        UINT32 idest = get_idest (insn);
                   1390: 
                   1391:        src1val = get_iregval (get_isrc1 (insn));
                   1392: 
                   1393:        /* The iregs array is UINT32, so cast isrc2 to get arithmetic shift.  */
                   1394:        set_iregval (idest, (INT32)get_iregval (isrc2) >> src1val);
                   1395: }
                   1396: 
                   1397: 
                   1398: /* Execute "shra #const,isrc2,idest".  */
                   1399: void i860_cpu_device::insn_shra_imm (UINT32 insn)
                   1400: {
                   1401:        UINT32 src1val = 0;
                   1402:        UINT32 isrc2 = get_isrc2 (insn);
                   1403:        UINT32 idest = get_idest (insn);
                   1404: 
                   1405:        src1val = sign_ext (get_imm16 (insn), 16);
                   1406: 
                   1407:        /* The iregs array is UINT32, so cast isrc2 to get arithmetic shift.  */
                   1408:        set_iregval (idest, (INT32)get_iregval (isrc2) >> src1val);
                   1409: }
                   1410: 
                   1411: 
                   1412: /* Execute "shrd isrc1ni,isrc2,idest" instruction.  */
                   1413: void i860_cpu_device::insn_shrd (UINT32 insn)
                   1414: {
                   1415:        UINT32 isrc1 = get_isrc1 (insn);
                   1416:        UINT32 isrc2 = get_isrc2 (insn);
                   1417:        UINT32 idest = get_idest (insn);
                   1418:        UINT32 sc = GET_PSR_SC ();
                   1419:        UINT32 tmp;
                   1420: 
                   1421:        /* Do the operation:
                   1422:           idest = low_32(isrc1ni:isrc2 >> sc).  */
                   1423:        if (sc == 0)
                   1424:                tmp = get_iregval (isrc2);
                   1425:        else
                   1426:        {
                   1427:                tmp = get_iregval (isrc1) << (32 - sc);
                   1428:                tmp |= (get_iregval (isrc2) >> sc);
                   1429:        }
                   1430:        set_iregval (idest, tmp);
                   1431: }
                   1432: 
                   1433: 
                   1434: /* Execute "and isrc1,isrc2,idest".  */
                   1435: void i860_cpu_device::insn_and (UINT32 insn)
                   1436: {
                   1437:        UINT32 isrc1 = get_isrc1 (insn);
                   1438:        UINT32 isrc2 = get_isrc2 (insn);
                   1439:        UINT32 idest = get_idest (insn);
                   1440:        UINT32 res = 0;
                   1441: 
                   1442:        /* Do the operation.  */
                   1443:        res = get_iregval (isrc1) & get_iregval (isrc2);
                   1444: 
                   1445:        /* Set flags.  */
                   1446:        if (res == 0)
                   1447:                SET_PSR_CC (1);
                   1448:        else
                   1449:                SET_PSR_CC (0);
                   1450: 
                   1451:        set_iregval (idest, res);
                   1452: }
                   1453: 
                   1454: 
                   1455: /* Execute "and #const,isrc2,idest".  */
                   1456: void i860_cpu_device::insn_and_imm (UINT32 insn)
                   1457: {
                   1458:        UINT32 src1val = 0;
                   1459:        UINT32 isrc2 = get_isrc2 (insn);
                   1460:        UINT32 idest = get_idest (insn);
                   1461:        UINT32 res = 0;
                   1462: 
                   1463:        /* Do the operation.  */
                   1464:        src1val = get_imm16 (insn);
                   1465:        res = src1val & get_iregval (isrc2);
                   1466: 
                   1467:        /* Set flags.  */
                   1468:        if (res == 0)
                   1469:                SET_PSR_CC (1);
                   1470:        else
                   1471:                SET_PSR_CC (0);
                   1472: 
                   1473:        set_iregval (idest, res);
                   1474: }
                   1475: 
                   1476: 
                   1477: /* Execute "andh #const,isrc2,idest".  */
                   1478: void i860_cpu_device::insn_andh_imm (UINT32 insn)
                   1479: {
                   1480:        UINT32 src1val = 0;
                   1481:        UINT32 isrc2 = get_isrc2 (insn);
                   1482:        UINT32 idest = get_idest (insn);
                   1483:        UINT32 res = 0;
                   1484: 
                   1485:        /* Do the operation.  */
                   1486:        src1val = get_imm16 (insn);
                   1487:        res = (src1val << 16) & get_iregval (isrc2);
                   1488: 
                   1489:        /* Set flags.  */
                   1490:        if (res == 0)
                   1491:                SET_PSR_CC (1);
                   1492:        else
                   1493:                SET_PSR_CC (0);
                   1494: 
                   1495:        set_iregval (idest, res);
                   1496: }
                   1497: 
                   1498: 
                   1499: /* Execute "andnot isrc1,isrc2,idest".  */
                   1500: void i860_cpu_device::insn_andnot (UINT32 insn)
                   1501: {
                   1502:        UINT32 isrc1 = get_isrc1 (insn);
                   1503:        UINT32 isrc2 = get_isrc2 (insn);
                   1504:        UINT32 idest = get_idest (insn);
                   1505:        UINT32 res = 0;
                   1506: 
                   1507:        /* Do the operation.  */
                   1508:        res = (~get_iregval (isrc1)) & get_iregval (isrc2);
                   1509: 
                   1510:        /* Set flags.  */
                   1511:        if (res == 0)
                   1512:                SET_PSR_CC (1);
                   1513:        else
                   1514:                SET_PSR_CC (0);
                   1515: 
                   1516:        set_iregval (idest, res);
                   1517: }
                   1518: 
                   1519: 
                   1520: /* Execute "andnot #const,isrc2,idest".  */
                   1521: void i860_cpu_device::insn_andnot_imm (UINT32 insn)
                   1522: {
                   1523:        UINT32 src1val = 0;
                   1524:        UINT32 isrc2 = get_isrc2 (insn);
                   1525:        UINT32 idest = get_idest (insn);
                   1526:        UINT32 res = 0;
                   1527: 
                   1528:        /* Do the operation.  */
                   1529:        src1val = get_imm16 (insn);
                   1530:        res = (~src1val) & get_iregval (isrc2);
                   1531: 
                   1532:        /* Set flags.  */
                   1533:        if (res == 0)
                   1534:                SET_PSR_CC (1);
                   1535:        else
                   1536:                SET_PSR_CC (0);
                   1537: 
                   1538:        set_iregval (idest, res);
                   1539: }
                   1540: 
                   1541: 
                   1542: /* Execute "andnoth #const,isrc2,idest".  */
                   1543: void i860_cpu_device::insn_andnoth_imm (UINT32 insn)
                   1544: {
                   1545:        UINT32 src1val = 0;
                   1546:        UINT32 isrc2 = get_isrc2 (insn);
                   1547:        UINT32 idest = get_idest (insn);
                   1548:        UINT32 res = 0;
                   1549: 
                   1550:        /* Do the operation.  */
                   1551:        src1val = get_imm16 (insn);
                   1552:        res = (~(src1val << 16)) & get_iregval (isrc2);
                   1553: 
                   1554:        /* Set flags.  */
                   1555:        if (res == 0)
                   1556:                SET_PSR_CC (1);
                   1557:        else
                   1558:                SET_PSR_CC (0);
                   1559: 
                   1560:        set_iregval (idest, res);
                   1561: }
                   1562: 
                   1563: 
                   1564: /* Execute "or isrc1,isrc2,idest".  */
                   1565: void i860_cpu_device::insn_or (UINT32 insn)
                   1566: {
                   1567:        UINT32 isrc1 = get_isrc1 (insn);
                   1568:        UINT32 isrc2 = get_isrc2 (insn);
                   1569:        UINT32 idest = get_idest (insn);
                   1570:        UINT32 res = 0;
                   1571: 
                   1572:        /* Do the operation.  */
                   1573:        res = get_iregval (isrc1) | get_iregval (isrc2);
                   1574: 
                   1575:        /* Set flags.  */
                   1576:        if (res == 0)
                   1577:                SET_PSR_CC (1);
                   1578:        else
                   1579:                SET_PSR_CC (0);
                   1580: 
                   1581:        set_iregval (idest, res);
                   1582: }
                   1583: 
                   1584: 
                   1585: /* Execute "or #const,isrc2,idest".  */
                   1586: void i860_cpu_device::insn_or_imm (UINT32 insn)
                   1587: {
                   1588:        UINT32 src1val = 0;
                   1589:        UINT32 isrc2 = get_isrc2 (insn);
                   1590:        UINT32 idest = get_idest (insn);
                   1591:        UINT32 res = 0;
                   1592: 
                   1593:        /* Do the operation.  */
                   1594:        src1val = get_imm16 (insn);
                   1595:        res = src1val | get_iregval (isrc2);
                   1596: 
                   1597:        /* Set flags.  */
                   1598:        if (res == 0)
                   1599:                SET_PSR_CC (1);
                   1600:        else
                   1601:                SET_PSR_CC (0);
                   1602: 
                   1603:        set_iregval (idest, res);
                   1604: }
                   1605: 
                   1606: 
                   1607: /* Execute "orh #const,isrc2,idest".  */
                   1608: void i860_cpu_device::insn_orh_imm (UINT32 insn)
                   1609: {
                   1610:        UINT32 src1val = 0;
                   1611:        UINT32 isrc2 = get_isrc2 (insn);
                   1612:        UINT32 idest = get_idest (insn);
                   1613:        UINT32 res = 0;
                   1614: 
                   1615:        /* Do the operation.  */
                   1616:        src1val = get_imm16 (insn);
                   1617:        res = (src1val << 16) | get_iregval (isrc2);
                   1618: 
                   1619:        /* Set flags.  */
                   1620:        if (res == 0)
                   1621:                SET_PSR_CC (1);
                   1622:        else
                   1623:                SET_PSR_CC (0);
                   1624: 
                   1625:        set_iregval (idest, res);
                   1626: }
                   1627: 
                   1628: 
                   1629: /* Execute "xor isrc1,isrc2,idest".  */
                   1630: void i860_cpu_device::insn_xor (UINT32 insn)
                   1631: {
                   1632:        UINT32 isrc1 = get_isrc1 (insn);
                   1633:        UINT32 isrc2 = get_isrc2 (insn);
                   1634:        UINT32 idest = get_idest (insn);
                   1635:        UINT32 res = 0;
                   1636: 
                   1637:        /* Do the operation.  */
                   1638:        res = get_iregval (isrc1) ^ get_iregval (isrc2);
                   1639: 
                   1640:        /* Set flags.  */
                   1641:        if (res == 0)
                   1642:                SET_PSR_CC (1);
                   1643:        else
                   1644:                SET_PSR_CC (0);
                   1645: 
                   1646:        set_iregval (idest, res);
                   1647: }
                   1648: 
                   1649: 
                   1650: /* Execute "xor #const,isrc2,idest".  */
                   1651: void i860_cpu_device::insn_xor_imm (UINT32 insn)
                   1652: {
                   1653:        UINT32 src1val = 0;
                   1654:        UINT32 isrc2 = get_isrc2 (insn);
                   1655:        UINT32 idest = get_idest (insn);
                   1656:        UINT32 res = 0;
                   1657: 
                   1658:        /* Do the operation.  */
                   1659:        src1val = get_imm16 (insn);
                   1660:        res = src1val ^ get_iregval (isrc2);
                   1661: 
                   1662:        /* Set flags.  */
                   1663:        if (res == 0)
                   1664:                SET_PSR_CC (1);
                   1665:        else
                   1666:                SET_PSR_CC (0);
                   1667: 
                   1668:        set_iregval (idest, res);
                   1669: }
                   1670: 
                   1671: 
                   1672: /* Execute "xorh #const,isrc2,idest".  */
                   1673: void i860_cpu_device::insn_xorh_imm (UINT32 insn)
                   1674: {
                   1675:        UINT32 src1val = 0;
                   1676:        UINT32 isrc2 = get_isrc2 (insn);
                   1677:        UINT32 idest = get_idest (insn);
                   1678:        UINT32 res = 0;
                   1679: 
                   1680:        /* Do the operation.  */
                   1681:        src1val = get_imm16 (insn);
                   1682:        res = (src1val << 16) ^ get_iregval (isrc2);
                   1683: 
                   1684:        /* Set flags.  */
                   1685:        if (res == 0)
                   1686:                SET_PSR_CC (1);
                   1687:        else
                   1688:                SET_PSR_CC (0);
                   1689: 
                   1690:        set_iregval (idest, res);
                   1691: }
                   1692: 
                   1693: 
                   1694: /* Execute "trap isrc1ni,isrc2,idest" instruction.  */
                   1695: void i860_cpu_device::insn_trap (UINT32 insn)
                   1696: {
                   1697:     debugger('d', "Software TRAP");
                   1698:        SET_PSR_IT (1);
                   1699:        m_flow |= TRAP_NORMAL;
                   1700: }
                   1701: 
                   1702: 
                   1703: /* Execute "intovr" instruction.  */
                   1704: void i860_cpu_device::insn_intovr (UINT32 insn)
                   1705: {
                   1706:        if (GET_EPSR_OF ())
                   1707:        {
                   1708:                SET_PSR_IT (1);
                   1709:                m_flow |= TRAP_NORMAL;
                   1710:        }
                   1711: }
                   1712: 
                   1713: 
                   1714: /* Execute "bte isrc1,isrc2,sbroff".  */
                   1715: void i860_cpu_device::insn_bte (UINT32 insn)
                   1716: {
                   1717:        UINT32 src1val = 0;
                   1718:        UINT32 isrc2 = get_isrc2 (insn);
                   1719:        UINT32 target_addr = 0;
                   1720:        INT32 sbroff = 0;
                   1721:        int res = 0;
                   1722: 
                   1723:        src1val = get_iregval (get_isrc1 (insn));
                   1724: 
                   1725:        /* Compute the target address from the sbroff field.  */
                   1726:        sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
                   1727:        target_addr = (INT32)m_pc + 4 + (sbroff << 2);
                   1728: 
                   1729:        /* Determine comparison result.  */
                   1730:        res = (src1val == get_iregval (isrc2));
                   1731: 
                   1732:        /* Branch routines always update the PC.  */
                   1733:        if (res)
                   1734:                m_pc = target_addr;
                   1735:        else
                   1736:                m_pc += 4;
                   1737: 
                   1738:        SET_PC_UPDATED();
                   1739: }
                   1740: 
                   1741: 
                   1742: /* Execute "bte #const5,isrc2,sbroff".  */
                   1743: void i860_cpu_device::insn_bte_imm (UINT32 insn)
                   1744: {
                   1745:        UINT32 src1val = 0;
                   1746:        UINT32 isrc2 = get_isrc2 (insn);
                   1747:        UINT32 target_addr = 0;
                   1748:        INT32 sbroff = 0;
                   1749:        int res = 0;
                   1750: 
                   1751:        src1val = (insn >> 11) & 0x1f;  /* 5-bit field, zero-extended.  */
                   1752: 
                   1753:        /* Compute the target address from the sbroff field.  */
                   1754:        sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
                   1755:        target_addr = (INT32)m_pc + 4 + (sbroff << 2);
                   1756: 
                   1757:        /* Determine comparison result.  */
                   1758:        res = (src1val == get_iregval (isrc2));
                   1759: 
                   1760:        /* Branch routines always update the PC.  */
                   1761:        if (res)
                   1762:                m_pc = target_addr;
                   1763:        else
                   1764:                m_pc += 4;
                   1765: 
                   1766:     SET_PC_UPDATED();
                   1767: }
                   1768: 
                   1769: 
                   1770: /* Execute "btne isrc1,isrc2,sbroff".  */
                   1771: void i860_cpu_device::insn_btne (UINT32 insn)
                   1772: {
                   1773:        UINT32 src1val = 0;
                   1774:        UINT32 isrc2 = get_isrc2 (insn);
                   1775:        UINT32 target_addr = 0;
                   1776:        INT32 sbroff = 0;
                   1777:        int res = 0;
                   1778: 
                   1779:        src1val = get_iregval (get_isrc1 (insn));
                   1780: 
                   1781:        /* Compute the target address from the sbroff field.  */
                   1782:        sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
                   1783:        target_addr = (INT32)m_pc + 4 + (sbroff << 2);
                   1784: 
                   1785:        /* Determine comparison result.  */
                   1786:        res = (src1val != get_iregval (isrc2));
                   1787: 
                   1788:        /* Branch routines always update the PC.  */
                   1789:        if (res)
                   1790:                m_pc = target_addr;
                   1791:        else
                   1792:                m_pc += 4;
                   1793: 
                   1794:     SET_PC_UPDATED();
                   1795: }
                   1796: 
                   1797: 
                   1798: /* Execute "btne #const5,isrc2,sbroff".  */
                   1799: void i860_cpu_device::insn_btne_imm (UINT32 insn)
                   1800: {
                   1801:        UINT32 src1val = 0;
                   1802:        UINT32 isrc2 = get_isrc2 (insn);
                   1803:        UINT32 target_addr = 0;
                   1804:        INT32 sbroff = 0;
                   1805:        int res = 0;
                   1806: 
                   1807:        src1val = (insn >> 11) & 0x1f;  /* 5-bit field, zero-extended.  */
                   1808: 
                   1809:        /* Compute the target address from the sbroff field.  */
                   1810:        sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
                   1811:        target_addr = (INT32)m_pc + 4 + (sbroff << 2);
                   1812: 
                   1813:        /* Determine comparison result.  */
                   1814:        res = (src1val != get_iregval (isrc2));
                   1815: 
                   1816:        /* Branch routines always update the PC.  */
                   1817:        if (res)
                   1818:                m_pc = target_addr;
                   1819:        else
                   1820:                m_pc += 4;
                   1821: 
                   1822:     SET_PC_UPDATED();
                   1823: }
                   1824: 
                   1825: 
                   1826: /* Execute "bc lbroff" instruction.  */
                   1827: void i860_cpu_device::insn_bc (UINT32 insn)
                   1828: {
                   1829:        UINT32 target_addr = 0;
                   1830:        INT32 lbroff = 0;
                   1831:        int res = 0;
                   1832: 
                   1833:        /* Compute the target address from the lbroff field.  */
                   1834:        lbroff = sign_ext ((insn & 0x03ffffff), 26);
                   1835:        target_addr = (INT32)m_pc + 4 + (lbroff << 2);
                   1836: 
                   1837:        /* Determine comparison result.  */
                   1838:     res = m_dim_cc_valid ? m_dim_cc : (GET_PSR_CC () == 1);
                   1839:     
                   1840:        /* Branch routines always update the PC.  */
                   1841:        if (res)
                   1842:                m_pc = target_addr;
                   1843:        else
                   1844:                m_pc += 4;
                   1845: 
                   1846:     SET_PC_UPDATED();
                   1847: }
                   1848: 
                   1849: 
                   1850: /* Execute "bnc lbroff" instruction.  */
                   1851: void i860_cpu_device::insn_bnc (UINT32 insn)
                   1852: {
                   1853:        UINT32 target_addr = 0;
                   1854:        INT32 lbroff = 0;
                   1855:        int res = 0;
                   1856: 
                   1857:        /* Compute the target address from the lbroff field.  */
                   1858:        lbroff = sign_ext ((insn & 0x03ffffff), 26);
                   1859:        target_addr = (INT32)m_pc + 4 + (lbroff << 2);
                   1860: 
                   1861:        /* Determine comparison result.  */
                   1862:     res = m_dim_cc_valid ? !(m_dim_cc) : (GET_PSR_CC () == 0);
                   1863: 
                   1864:        /* Branch routines always update the PC, since pc_updated is set
                   1865:           in the decode routine.  */
                   1866:        if (res)
                   1867:                m_pc = target_addr;
                   1868:        else
                   1869:                m_pc += 4;
                   1870: 
                   1871:     SET_PC_UPDATED();
                   1872: }
                   1873: 
                   1874: 
                   1875: /* Execute "bc.t lbroff" instruction.  */
                   1876: void i860_cpu_device::insn_bct (UINT32 insn)
                   1877: {
                   1878:        UINT32 target_addr = 0;
                   1879:        INT32 lbroff = 0;
                   1880:        int res = 0;
                   1881:        UINT32 orig_pc = m_pc;
                   1882: 
                   1883:        /* Compute the target address from the lbroff field.  */
                   1884:        lbroff = sign_ext ((insn & 0x03ffffff), 26);
                   1885:        target_addr = (INT32)m_pc + 4 + (lbroff << 2);
                   1886: 
                   1887:        /* Determine comparison result.  */
                   1888:        res = (GET_PSR_CC () == 1);
                   1889: 
                   1890:        /* Careful. Unlike bla, the delay slot instruction is only executed
                   1891:           if the branch is taken.  */
                   1892:        if (res)
                   1893:        {
                   1894:                /* Execute delay slot instruction.  */
                   1895:         DELAY_SLOT();
                   1896:                if (PENDING_TRAP() )
                   1897:                {
                   1898:                        m_flow |= TRAP_IN_DELAY_SLOT;
                   1899:                        goto ab_op;
                   1900:                }
                   1901:        }
                   1902: 
                   1903:        /* Since this branch is delayed, we must jump 2 or 3 instructions if
                   1904:           if isn't taken.  */
                   1905:        if (res)
                   1906:                m_pc = target_addr;
                   1907:        else
                   1908:         m_pc += DELAY_SLOT_PC();
                   1909: 
                   1910:     SET_PC_UPDATED();
                   1911: 
                   1912:        ab_op:
                   1913:        ;
                   1914: }
                   1915: 
                   1916: 
                   1917: /* Execute "bnc.t lbroff" instruction.  */
                   1918: void i860_cpu_device::insn_bnct (UINT32 insn)
                   1919: {
                   1920:        UINT32 target_addr = 0;
                   1921:        INT32 lbroff = 0;
                   1922:        int res = 0;
                   1923:        UINT32 orig_pc = m_pc;
                   1924: 
                   1925:        /* Compute the target address from the lbroff field.  */
                   1926:        lbroff = sign_ext ((insn & 0x03ffffff), 26);
                   1927:        target_addr = (INT32)m_pc + 4 + (lbroff << 2);
                   1928: 
                   1929:        /* Determine comparison result.  */
                   1930:     res = (GET_PSR_CC () == 0);
                   1931: 
                   1932:        /* Careful. Unlike bla, the delay slot instruction is only executed
                   1933:           if the branch is taken.  */
                   1934:        if (res)
                   1935:        {
                   1936:                /* Execute delay slot instruction.  */
                   1937:         DELAY_SLOT();
                   1938:                if (PENDING_TRAP() )
                   1939:                {
                   1940:                        m_flow |= TRAP_IN_DELAY_SLOT;
                   1941:                        goto ab_op;
                   1942:                }
                   1943:        }
                   1944: 
                   1945:        /* Since this branch is delayed, we must jump 2 or 3 instructions if if isn't taken.  */
                   1946:        if (res)
                   1947:                m_pc = target_addr;
                   1948:        else
                   1949:         m_pc += DELAY_SLOT_PC();
                   1950: 
                   1951:     SET_PC_UPDATED();
                   1952: 
                   1953:        ab_op:
                   1954:        ;
                   1955: }
                   1956: 
                   1957: 
                   1958: /* Execute "call lbroff" instruction.  */
                   1959: void i860_cpu_device::insn_call (UINT32 insn)
                   1960: {
                   1961:        UINT32 target_addr = 0;
                   1962:        INT32 lbroff = 0;
                   1963:        UINT32 orig_pc = m_pc;
                   1964: 
                   1965:        /* Compute the target address from the lbroff field.  */
                   1966:        lbroff = sign_ext ((insn & 0x03ffffff), 26);
                   1967:        target_addr = (INT32)m_pc + 4 + (lbroff << 2);
                   1968: 
                   1969:        /* Execute the delay slot instruction.  */
                   1970:     DELAY_SLOT();
                   1971:        if (PENDING_TRAP() )
                   1972:        {
                   1973:                m_flow |= TRAP_IN_DELAY_SLOT;
                   1974:                goto ab_op;
                   1975:        }
                   1976: 
                   1977:        /* Sets the return pointer (r1).  */
                   1978:        set_iregval (1, orig_pc + DELAY_SLOT_PC());
                   1979: 
                   1980:        /* New target.  */
                   1981:        m_pc = target_addr;
                   1982:     SET_PC_UPDATED();
                   1983: 
                   1984:        ab_op:;
                   1985: }
                   1986: 
                   1987: 
                   1988: /* Execute "br lbroff".  */
                   1989: void i860_cpu_device::insn_br (UINT32 insn)
                   1990: {
                   1991:        UINT32 target_addr = 0;
                   1992:        INT32 lbroff = 0;
                   1993:        UINT32 orig_pc = m_pc;
                   1994: 
                   1995:        /* Compute the target address from the lbroff field.  */
                   1996:        lbroff = sign_ext ((insn & 0x03ffffff), 26);
                   1997:        target_addr = (INT32)m_pc + 4 + (lbroff << 2);
                   1998: 
                   1999:        /* Execute the delay slot instruction.  */
                   2000:     DELAY_SLOT();
                   2001:        if (PENDING_TRAP() )
                   2002:        {
                   2003:                m_flow |= TRAP_IN_DELAY_SLOT;
                   2004:                goto ab_op;
                   2005:        }
                   2006: 
                   2007:        /* New target.  */
                   2008:        m_pc = target_addr;
                   2009:     SET_PC_UPDATED();
                   2010: 
                   2011:        ab_op:;
                   2012: }
                   2013: 
                   2014: 
                   2015: /* Execute "bri isrc1ni" instruction.
                   2016:    Note: I didn't merge this code with calli because bri must do
                   2017:    a lot of flag manipulation if any trap bits are set.  */
                   2018: void i860_cpu_device::insn_bri (UINT32 insn)
                   2019: {
                   2020:        UINT32 isrc1 = get_isrc1 (insn);
                   2021:        UINT32 orig_pc = m_pc;
                   2022:        UINT32 orig_psr = m_cregs[CR_PSR];
                   2023:        UINT32 orig_src1_val = get_iregval (isrc1);
                   2024: 
                   2025: #if 1 /* TURBO.  */
                   2026:        m_cregs[CR_PSR] &= ~PSR_ALL_TRAP_BITS_MASK;
                   2027: #endif
                   2028: 
                   2029:     if(m_dim && PENDING_TRAP())
                   2030:         goto ab_op;
                   2031:     
                   2032:        /* Execute the delay slot instruction.  */
                   2033:     DELAY_SLOT();
                   2034: 
                   2035:        /* Delay slot insn caused a trap, abort operation.  */
                   2036:        if (PENDING_TRAP() )
                   2037:        {
                   2038:                m_flow |= TRAP_IN_DELAY_SLOT;
                   2039:                goto ab_op;
                   2040:        }
                   2041: 
                   2042:        /* If any trap bits are set, we need to do the return from
                   2043:           trap work.  Note, we must use the PSR value that existed
                   2044:           before the delay slot instruction was executed since the
                   2045:           delay slot instruction might itself cause a trap bit to
                   2046:           be set.  */
                   2047:        if (orig_psr & PSR_ALL_TRAP_BITS_MASK)
                   2048:        {
                   2049:                /* Restore U and IM from their previous copies.  */
                   2050:                SET_PSR_U (GET_PSR_PU ());
                   2051:                SET_PSR_IM (GET_PSR_PIM ());
                   2052: 
                   2053:         ret_from_trap();
                   2054:        }
                   2055: 
                   2056:        /* Update PC.  */
                   2057:        m_pc = orig_src1_val;
                   2058: 
                   2059:     SET_PC_UPDATED();
                   2060:        ab_op:;
                   2061: }
                   2062: 
                   2063: /* Execute "calli isrc1ni" instruction.  */
                   2064: void i860_cpu_device::insn_calli (UINT32 insn)
                   2065: {
                   2066:        UINT32 isrc1 = get_isrc1 (insn);
                   2067:        UINT32 orig_pc = m_pc;
                   2068:        UINT32 orig_src1_val = get_iregval (isrc1);
                   2069: 
                   2070: #if TRACE_UNDEFINED_I860
                   2071:        /* Check for undefined behavior.  */
                   2072:        if (isrc1 == 1)
                   2073:        {
                   2074:                /* Src1 must not be r1.  */
                   2075:                Log_Printf(LOG_WARN, "[i860:%08X] insn_calli: isrc1 = r1 on a calli", m_pc);
                   2076:        }
                   2077: #endif
                   2078: 
                   2079:        /* Set return pointer before executing delay slot instruction.  */
                   2080:        set_iregval (1, m_pc + DELAY_SLOT_PC());
                   2081: 
                   2082:        /* Execute the delay slot instruction.  */
                   2083:     DELAY_SLOT();
                   2084:        if (PENDING_TRAP() )
                   2085:        {
                   2086:                set_iregval (1, orig_src1_val);
                   2087:                m_flow |= TRAP_IN_DELAY_SLOT;
                   2088:                goto ab_op;
                   2089:        }
                   2090: 
                   2091:        /* Set new PC.  */
                   2092:        m_pc = orig_src1_val;
                   2093:     SET_PC_UPDATED();
                   2094: 
                   2095:        ab_op:;
                   2096: }
                   2097: 
                   2098: 
                   2099: /* Execute "bla isrc1ni,isrc2,sbroff" instruction.  */
                   2100: void i860_cpu_device::insn_bla (UINT32 insn)
                   2101: {
                   2102:        UINT32 isrc1 = get_isrc1 (insn);
                   2103:        UINT32 isrc2 = get_isrc2 (insn);
                   2104:        UINT32 target_addr = 0;
                   2105:        INT32 sbroff = 0;
                   2106:        int lcc_tmp = 0;
                   2107:        UINT32 orig_pc = m_pc;
                   2108:        UINT32 orig_isrc2val = get_iregval (isrc2);
                   2109: 
                   2110: #if TRACE_UNDEFINED_I860
                   2111:        /* Check for undefined behavior.  */
                   2112:        if (isrc1 == isrc2)
                   2113:        {
                   2114:                /* Src1 and src2 the same is undefined i860XR behavior.  */
                   2115:                Log_Printf(LOG_WARN,  "[i860:%08X] insn_bla: isrc1 and isrc2 are the same (ignored)", m_pc);
                   2116:                return;
                   2117:        }
                   2118: #endif
                   2119: 
                   2120:        /* Compute the target address from the sbroff field.  */
                   2121:        sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
                   2122:        target_addr = (INT32)m_pc + 4 + (sbroff << 2);
                   2123: 
                   2124:        /* Determine comparison result based on opcode.  */
                   2125:        lcc_tmp = ((INT32)get_iregval (isrc2) >= -(INT32)get_iregval (isrc1));
                   2126: 
                   2127:        set_iregval (isrc2, get_iregval (isrc1) + orig_isrc2val);
                   2128: 
                   2129:        /* Execute the delay slot instruction.  */
                   2130:     DELAY_SLOT();
                   2131:        if (PENDING_TRAP() )
                   2132:        {
                   2133:                m_flow |= TRAP_IN_DELAY_SLOT;
                   2134:                goto ab_op;
                   2135:        }
                   2136: 
                   2137:        if (GET_PSR_LCC ())
                   2138:                m_pc = target_addr;
                   2139:        else
                   2140:        {
                   2141:                /* Since this branch is delayed, we must jump 2 or 3 instructions if if isn't taken.  */
                   2142:         m_pc += DELAY_SLOT_PC();
                   2143:        }
                   2144:        SET_PSR_LCC (lcc_tmp);
                   2145: 
                   2146:     SET_PC_UPDATED();
                   2147:        ab_op:;
                   2148: }
                   2149: 
                   2150: 
                   2151: /* Execute "flush #const(isrc2)" or "flush #const(isrc2)++" instruction.  */
                   2152: void i860_cpu_device::insn_flush (UINT32 insn)
                   2153: {
                   2154:        UINT32 src1val = sign_ext (get_imm16 (insn), 16);
                   2155:        UINT32 isrc2 = get_isrc2 (insn);
                   2156:        int auto_inc = (insn & 1);
                   2157:        UINT32 eff = 0;
                   2158: 
                   2159:        /* Technically, idest should be encoded as r0 because idest
                   2160:           is undefined after the instruction.  We don't currently
                   2161:           check for this.
                   2162: 
                   2163:           Flush D$ block at address #const+isrc2.  Block is undefined
                   2164:           after.  The effective address must be 16-byte aligned.
                   2165: 
                   2166:           FIXME: Need to examine RB and RC and do this right.
                   2167:          */
                   2168: 
                   2169:        /* Chop off lower bits of displacement to 16-byte alignment.  */
                   2170:        src1val &= ~(16-1);
                   2171:        eff = src1val + get_iregval (isrc2);
                   2172:        if (auto_inc)
                   2173:                set_iregval (isrc2, eff);
                   2174: 
                   2175:        /* In user mode, the flush is ignored.  */
                   2176:        if (GET_PSR_U () == 0)
                   2177:        {
                   2178:                /* If line is dirty, write it to memory and invalidate.
                   2179:                   NOTE: The actual dirty write is unimplemented in the MAME version
                   2180:                   as we don't emulate the dcache.  */
                   2181:        }
                   2182: }
                   2183: 
                   2184: 
                   2185: /* Execute "[p]fmul.{ss,sd,dd} fsrc1,fsrc2,fdest" instruction or
                   2186:    pfmul3.dd fsrc1,fsrc2,fdest.
                   2187: 
                   2188:    The pfmul3.dd differs from pfmul.dd in that it treats the pipeline
                   2189:    as 3 stages, even though it is a double precision multiply.  */
                   2190: void i860_cpu_device::insn_fmul (UINT32 insn)
                   2191: {
                   2192:        UINT32 fsrc1 = get_fsrc1 (insn);
                   2193:        UINT32 fsrc2 = get_fsrc2 (insn);
                   2194:        UINT32 fdest = get_fdest (insn);
                   2195:        int src_prec = insn & 0x100;     /* 1 = double, 0 = single.  */
                   2196:        int res_prec = insn & 0x080;     /* 1 = double, 0 = single.  */
                   2197:        int piped = insn & 0x400;        /* 1 = pipelined, 0 = scalar.  */
                   2198:        double dbl_tmp_dest = 0.0;
                   2199:        float sgl_tmp_dest = 0.0;
                   2200:        double dbl_last_stage_contents = 0.0;
                   2201:        float sgl_last_stage_contents = 0.0;
                   2202:        int is_pfmul3 = insn & 0x4;
                   2203:        int num_stages = (src_prec && !is_pfmul3) ? 2 : 3;
                   2204: 
                   2205: #if TRACE_UNDEFINED_I860
                   2206:        /* Only .dd is valid for pfmul.  */
                   2207:        if (is_pfmul3 && (insn & 0x180) != 0x180)
                   2208:        {
                   2209:                unrecog_opcode (m_pc, insn);
                   2210:                return;
                   2211:        }
                   2212: 
                   2213:        /* Check for invalid .ds combination.  */
                   2214:        if ((insn & 0x180) == 0x100)
                   2215:        {
                   2216:                unrecog_opcode (m_pc, insn);
                   2217:                return;
                   2218:        }
                   2219: #endif
                   2220:     
                   2221:        /* For pipelined version, retrieve the contents of the last stage
                   2222:           of the pipeline, whose precision is specified by the MRP bit
                   2223:           of the stage's result-status bits.  Note for pfmul, the number
                   2224:           of stages is determined by the source precision of the current
                   2225:           operation.  */
                   2226:        if (piped)
                   2227:        {
                   2228:                if (m_M[num_stages - 1].stat.mrp)
                   2229:                        dbl_last_stage_contents = m_M[num_stages - 1].val.d;
                   2230:                else
                   2231:                        sgl_last_stage_contents = m_M[num_stages - 1].val.s;
                   2232:        }
                   2233: 
                   2234:        /* Do the operation, being careful about source and result
                   2235:           precision.  */
                   2236:        if (src_prec)
                   2237:        {
                   2238:                double v1 = get_fregval_d (fsrc1);
                   2239:                double v2 = get_fregval_d (fsrc2);
                   2240: 
                   2241:                /* For pipelined mul, if fsrc2 is the same as fdest, then the last
                   2242:                   stage is bypassed to fsrc2 (rather than using the value in fsrc2).
                   2243:                   This bypass is not available for fsrc1, and is undefined behavior.  */
                   2244:                if (0 && piped && fdest != 0 && fsrc1 == fdest)
                   2245:                        v1 = dbl_last_stage_contents;
                   2246:                if (piped && fdest != 0 && fsrc2 == fdest)
                   2247:                        v2 = dbl_last_stage_contents;
                   2248: 
                   2249:                if (res_prec)
                   2250:                        dbl_tmp_dest = v1 * v2;
                   2251:                else
                   2252:                        sgl_tmp_dest = (float)(v1 * v2);
                   2253:        }
                   2254:        else
                   2255:        {
                   2256:                float v1 = get_fregval_s (fsrc1);
                   2257:                float v2 = get_fregval_s (fsrc2);
                   2258: 
                   2259:                /* For pipelined mul, if fsrc2 is the same as fdest, then the last
                   2260:                   stage is bypassed to fsrc2 (rather than using the value in fsrc2).
                   2261:                   This bypass is not available for fsrc1, and is undefined behavior.  */
                   2262:                if (0 && piped && fdest != 0 && fsrc1 == fdest)
                   2263:                        v1 = sgl_last_stage_contents;
                   2264:                if (piped && fdest != 0 && fsrc2 == fdest)
                   2265:                        v2 = sgl_last_stage_contents;
                   2266: 
                   2267:                if (res_prec)
                   2268:                        dbl_tmp_dest = (double)(v1 * v2);
                   2269:                else
                   2270:                        sgl_tmp_dest = v1 * v2;
                   2271:        }
                   2272: 
                   2273:        /* FIXME: Set result-status bits besides MRP. And copy to fsr from
                   2274:                  last stage.  */
                   2275:        /* FIXME: Scalar version flows through all stages.  */
                   2276:        /* FIXME: Mixed precision (only weird for pfmul).  */
                   2277:        if (!piped)
                   2278:        {
                   2279:                /* Scalar version writes the current calculation to the fdest
                   2280:                   register, with precision specified by the R bit.  */
                   2281:                if (res_prec)
                   2282:                        set_fregval_d (fdest, dbl_tmp_dest);
                   2283:                else
                   2284:                        set_fregval_s (fdest, sgl_tmp_dest);
                   2285:        }
                   2286:        else
                   2287:        {
                   2288:                /* Pipelined version writes fdest with the result from the last
                   2289:                   stage of the pipeline.  */
                   2290: #if 1 /* FIXME: WIP on FSR update.  This may not be correct.  */
                   2291:                /* Copy 3rd stage MRP to FSR.  */
                   2292:                if (m_M[num_stages - 2  /* 1 */].stat.mrp)
                   2293:                        m_cregs[CR_FSR] |= 0x10000000;
                   2294:                else
                   2295:                        m_cregs[CR_FSR] &= ~0x10000000;
                   2296: #endif
                   2297: 
                   2298:                if (m_M[num_stages - 1].stat.mrp)
                   2299:                        set_fregval_d (fdest, dbl_last_stage_contents);
                   2300:                else
                   2301:                        set_fregval_s (fdest, sgl_last_stage_contents);
                   2302: 
                   2303:                /* Now advance pipeline and write current calculation to
                   2304:                   first stage.  */
                   2305:                if (num_stages == 3)
                   2306:                {
                   2307:                        m_M[2] = m_M[1];
                   2308:                        m_M[1] = m_M[0];
                   2309:                }
                   2310:                else
                   2311:                        m_M[1]  = m_M[0];
                   2312: 
                   2313:                if (res_prec)
                   2314:                {
                   2315:                        m_M[0].val.d = dbl_tmp_dest;
                   2316:                        m_M[0].stat.mrp = 1;
                   2317:                }
                   2318:                else
                   2319:                {
                   2320:                        m_M[0].val.s = sgl_tmp_dest;
                   2321:                        m_M[0].stat.mrp = 0;
                   2322:                }
                   2323:        }
                   2324: }
                   2325: 
                   2326: 
                   2327: /* Execute "fmlow.dd fsrc1,fsrc2,fdest" instruction.  */
                   2328: void i860_cpu_device::insn_fmlow (UINT32 insn)
                   2329: {
                   2330:        UINT32 fsrc1 = get_fsrc1 (insn);
                   2331:        UINT32 fsrc2 = get_fsrc2 (insn);
                   2332:        UINT32 fdest = get_fdest (insn);
                   2333: 
                   2334:        double v1 = get_fregval_d (fsrc1);
                   2335:        double v2 = get_fregval_d (fsrc2);
                   2336:        INT64 i1 = *(UINT64 *)&v1;
                   2337:        INT64 i2 = *(UINT64 *)&v2;
                   2338:        INT64 tmp = 0;
                   2339: 
                   2340: #if TRACE_UNDEFINED_I860
                   2341:        /* Only .dd is valid for fmlow.  */
                   2342:        if ((insn & 0x180) != 0x180)
                   2343:        {
                   2344:                unrecog_opcode (m_pc, insn);
                   2345:                return;
                   2346:        }
                   2347: #endif
                   2348:     
                   2349:        /* The lower 32-bits are obvious.  What exactly goes in the upper
                   2350:           bits?
                   2351:           Technically, the upper-most 10 bits are undefined, but i'd like
                   2352:           to be undefined in the same way as the real i860 if possible.  */
                   2353: 
                   2354:        /* Keep lower 53 bits of multiply.  */
                   2355:     tmp = i1 * i2;
                   2356:        tmp &= 0x001fffffffffffffULL;
                   2357:        tmp |= (i1 & 0x8000000000000000LL) ^ (i2 & 0x8000000000000000LL);
                   2358:        set_fregval_d (fdest, *(double *)&tmp);
                   2359: }
                   2360: 
                   2361: 
                   2362: /* Execute [p]fadd.{ss,sd,dd} fsrc1,fsrc2,fdest (.ds disallowed above).  */
                   2363: void i860_cpu_device::insn_fadd_sub (UINT32 insn)
                   2364: {
                   2365:        UINT32 fsrc1 = get_fsrc1 (insn);
                   2366:        UINT32 fsrc2 = get_fsrc2 (insn);
                   2367:        UINT32 fdest = get_fdest (insn);
                   2368:        int src_prec = insn & 0x100;     /* 1 = double, 0 = single.  */
                   2369:        int res_prec = insn & 0x080;     /* 1 = double, 0 = single.  */
                   2370:        int piped = insn & 0x400;        /* 1 = pipelined, 0 = scalar.  */
                   2371:        int is_sub = insn & 1;           /* 1 = sub, 0 = add.  */
                   2372:        double dbl_tmp_dest = 0.0;
                   2373:        float sgl_tmp_dest = 0.0;
                   2374:        double dbl_last_stage_contents = 0.0;
                   2375:        float sgl_last_stage_contents = 0.0;
                   2376: 
                   2377: #if TRACE_UNDEFINED_I860
                   2378:        /* Check for invalid .ds combination.  */
                   2379:        if ((insn & 0x180) == 0x100)
                   2380:        {
                   2381:                unrecog_opcode (m_pc, insn);
                   2382:                return;
                   2383:        }
                   2384: #endif
                   2385:     
                   2386:        /* For pipelined version, retrieve the contents of the last stage
                   2387:           of the pipeline, whose precision is specified by the ARP bit
                   2388:           of the stage's result-status bits.  There are always three stages
                   2389:           for pfadd/pfsub.  */
                   2390:        if (piped)
                   2391:        {
                   2392:                if (m_A[2].stat.arp)
                   2393:                        dbl_last_stage_contents = m_A[2].val.d;
                   2394:                else
                   2395:                        sgl_last_stage_contents = m_A[2].val.s;
                   2396:        }
                   2397: 
                   2398:        /* Do the operation, being careful about source and result
                   2399:           precision.  */
                   2400:        if (src_prec)
                   2401:        {
                   2402:                double v1 = get_fregval_d (fsrc1);
                   2403:                double v2 = get_fregval_d (fsrc2);
                   2404: 
                   2405:                /* For pipelined add/sub, if fsrc1 is the same as fdest, then the last
                   2406:                   stage is bypassed to fsrc1 (rather than using the value in fsrc1).
                   2407:                   Likewise for fsrc2.  */
                   2408:                if (piped && fdest != 0 && fsrc1 == fdest)
                   2409:                        v1 = dbl_last_stage_contents;
                   2410:                if (piped && fdest != 0 && fsrc2 == fdest)
                   2411:                        v2 = dbl_last_stage_contents;
                   2412: 
                   2413:                if (res_prec)
                   2414:                        dbl_tmp_dest = is_sub ? v1 - v2 : v1 + v2;
                   2415:                else
                   2416:                        sgl_tmp_dest = is_sub ? (float)(v1 - v2) : (float)(v1 + v2);
                   2417:        }
                   2418:        else
                   2419:        {
                   2420:                float v1 = get_fregval_s (fsrc1);
                   2421:                float v2 = get_fregval_s (fsrc2);
                   2422: 
                   2423:                /* For pipelined add/sub, if fsrc1 is the same as fdest, then the last
                   2424:                   stage is bypassed to fsrc1 (rather than using the value in fsrc1).
                   2425:                   Likewise for fsrc2.  */
                   2426:                if (piped && fdest != 0 && fsrc1 == fdest)
                   2427:                        v1 = sgl_last_stage_contents;
                   2428:                if (piped && fdest != 0 && fsrc2 == fdest)
                   2429:                        v2 = sgl_last_stage_contents;
                   2430: 
                   2431:                if (res_prec)
                   2432:                        dbl_tmp_dest = is_sub ? (double)(v1 - v2) : (double)(v1 + v2);
                   2433:                else
                   2434:                        sgl_tmp_dest = is_sub ? v1 - v2 : v1 + v2;
                   2435:        }
                   2436: 
                   2437:        /* FIXME: Set result-status bits besides ARP. And copy to fsr from
                   2438:                  last stage.  */
                   2439:        /* FIXME: Scalar version flows through all stages.  */
                   2440:        if (!piped)
                   2441:        {
                   2442:                /* Scalar version writes the current calculation to the fdest
                   2443:                   register, with precision specified by the R bit.  */
                   2444:                if (res_prec)
                   2445:                        set_fregval_d (fdest, dbl_tmp_dest);
                   2446:                else
                   2447:                        set_fregval_s (fdest, sgl_tmp_dest);
                   2448:        }
                   2449:        else
                   2450:        {
                   2451:                /* Pipelined version writes fdest with the result from the last
                   2452:                   stage of the pipeline, with precision specified by the ARP
                   2453:                   bit of the stage's result-status bits.  */
                   2454: #if 1 /* FIXME: WIP on FSR update.  This may not be correct.  */
                   2455:                /* Copy 3rd stage ARP to FSR.  */
                   2456:                if (m_A[1 /* 2 */].stat.arp)
                   2457:                        m_cregs[CR_FSR] |= 0x20000000;
                   2458:                else
                   2459:                        m_cregs[CR_FSR] &= ~0x20000000;
                   2460: #endif
                   2461:                if (m_A[2].stat.arp)  /* 3rd (last) stage.  */
                   2462:                        set_fregval_d (fdest, dbl_last_stage_contents);
                   2463:                else
                   2464:                        set_fregval_s (fdest, sgl_last_stage_contents);
                   2465: 
                   2466:                /* Now advance pipeline and write current calculation to
                   2467:                   first stage.  */
                   2468:                m_A[2] = m_A[1];
                   2469:                m_A[1] = m_A[0];
                   2470:                if (res_prec)
                   2471:                {
                   2472:                        m_A[0].val.d = dbl_tmp_dest;
                   2473:                        m_A[0].stat.arp = 1;
                   2474:                }
                   2475:                else
                   2476:                {
                   2477:                        m_A[0].val.s = sgl_tmp_dest;
                   2478:                        m_A[0].stat.arp = 0;
                   2479:                }
                   2480:        }
                   2481: }
                   2482: 
                   2483: /* Execute 0x32, [p]fix.{ss,sd,dd}  (SC) added and implemented this */
                   2484: void i860_cpu_device::insn_fix(UINT32 insn) {
                   2485:     UINT32 fsrc1 = get_fsrc1 (insn);
                   2486:     UINT32 fdest = get_fdest (insn);
                   2487:     int src_prec = insn & 0x100;     /* 1 = double, 0 = single.  */
                   2488:     int res_prec = insn & 0x080;     /* 1 = double, 0 = single.  */
                   2489:     int piped = insn & 0x400;        /* 1 = pipelined, 0 = scalar.  */
                   2490:     
                   2491: #if TRACE_UNDEFINED_I860
                   2492:     /* Check for invalid .ds or .ss combinations.  */
                   2493:     if ((insn & 0x080) == 0) {
                   2494:         unrecog_opcode (m_pc, insn);
                   2495:         return;
                   2496:     }
                   2497: #endif
                   2498:     
                   2499:     /* Do the operation, being careful about source and result
                   2500:      precision.  Operation: fdest = integer part of fsrc1 in
                   2501:      lower 32-bits.  */
                   2502:     if (src_prec) {
                   2503:         double v1 = get_fregval_d (fsrc1);
                   2504:         INT32 iv = rint(v1);
                   2505:         /* We always write a single, since the lower 32-bits of fdest
                   2506:          get the result (and the even numbered reg is the lower).  */
                   2507:         set_fregval_s (fdest, *(float *)&iv);
                   2508:     }
                   2509:     else
                   2510:     {
                   2511:         float v1 = get_fregval_s (fsrc1);
                   2512:         INT32 iv = rint(v1);
                   2513:         /* We always write a single, since the lower 32-bits of fdest
                   2514:          get the result (and the even numbered reg is the lower).  */
                   2515:         set_fregval_s (fdest, *(float *)&iv);
                   2516:     }
                   2517:     
                   2518:     /* FIXME: Handle updating of pipestages for pfix.  */
                   2519:     /* Includes looking at ARP (add result precision.) */
                   2520:     if (piped)
                   2521:     {
                   2522:         Log_Printf(LOG_WARN, "[i860:%08X] insn_fix: FIXME: pipelined not functional yet", m_pc);
                   2523:         if (res_prec)
                   2524:             set_fregval_d (fdest, 0.0);
                   2525:         else
                   2526:             set_fregval_s (fdest, 0.0);
                   2527:     }
                   2528: }
                   2529: 
                   2530: /* Operand types for PFAM/PFMAM routine below.  */
                   2531: enum {
                   2532:        OP_SRC1     = 0,
                   2533:        OP_SRC2     = 1,
                   2534:        OP_KI       = 2,
                   2535:        OP_KR       = 4,
                   2536:        OP_T        = 8,
                   2537:        OP_MPIPE    = 16,
                   2538:        OP_APIPE    = 32,
                   2539:        FLAGM       = 64   /* Indicates PFMAM uses M rather than A pipe result.  */
                   2540: };
                   2541: 
                   2542: /* A table to map DPC value to source operands.
                   2543: 
                   2544:    The PFAM and PFMAM tables are nearly identical, and the only differences
                   2545:    are that every time PFAM uses the A pipe, PFMAM uses the M pipe instead.
                   2546:    So we only represent the PFAM table and use a special flag on any entry
                   2547:    where the PFMAM table would use the M pipe rather than the A pipe.
                   2548:    Also, entry 16 is not valid for PFMAM.  */
                   2549: static const struct
                   2550: {
                   2551:        int M_unit_op1;
                   2552:        int M_unit_op2;
                   2553:        int A_unit_op1;
                   2554:        int A_unit_op2;
                   2555:        int T_loaded;
                   2556:        int K_loaded;
                   2557: } src_opers[] = {
                   2558:        /* 0000 */ { OP_KR,   OP_SRC2,        OP_SRC1,        OP_MPIPE,       0, 0},
                   2559:        /* 0001 */ { OP_KR,   OP_SRC2,        OP_T,           OP_MPIPE,       0, 1},
                   2560:        /* 0010 */ { OP_KR,   OP_SRC2,        OP_SRC1,        OP_APIPE|FLAGM, 1, 0},
                   2561:        /* 0011 */ { OP_KR,   OP_SRC2,        OP_T,           OP_APIPE|FLAGM, 1, 1},
                   2562:        /* 0100 */ { OP_KI,   OP_SRC2,        OP_SRC1,        OP_MPIPE,       0, 0},
                   2563:        /* 0101 */ { OP_KI,   OP_SRC2,        OP_T,           OP_MPIPE,       0, 1},
                   2564:        /* 0110 */ { OP_KI,   OP_SRC2,        OP_SRC1,        OP_APIPE|FLAGM, 1, 0},
                   2565:        /* 0111 */ { OP_KI,   OP_SRC2,        OP_T,           OP_APIPE|FLAGM, 1, 1},
                   2566:        /* 1000 */ { OP_KR,   OP_APIPE|FLAGM, OP_SRC1,        OP_SRC2,        1, 0},
                   2567:        /* 1001 */ { OP_SRC1, OP_SRC2,        OP_APIPE|FLAGM, OP_MPIPE,       0, 0},
                   2568:        /* 1010 */ { OP_KR,   OP_APIPE|FLAGM, OP_SRC1,        OP_SRC2,        0, 0},
                   2569:        /* 1011 */ { OP_SRC1, OP_SRC2,        OP_T,           OP_APIPE|FLAGM, 1, 0},
                   2570:        /* 1100 */ { OP_KI,   OP_APIPE|FLAGM, OP_SRC1,        OP_SRC2,        1, 0},
                   2571:        /* 1101 */ { OP_SRC1, OP_SRC2,        OP_T,           OP_MPIPE,       0, 0},
                   2572:        /* 1110 */ { OP_KI,   OP_APIPE|FLAGM, OP_SRC1,        OP_SRC2,        0, 0},
                   2573:        /* 1111 */ { OP_SRC1, OP_SRC2,        OP_T,           OP_APIPE|FLAGM, 0, 0}
                   2574: };
                   2575: 
                   2576: float i860_cpu_device::get_fval_from_optype_s (UINT32 insn, int optype)
                   2577: {
                   2578:        float retval = 0.0;
                   2579:        UINT32 fsrc1 = get_fsrc1 (insn);
                   2580:        UINT32 fsrc2 = get_fsrc2 (insn);
                   2581: 
                   2582:        optype &= ~FLAGM;
                   2583:        switch (optype)
                   2584:        {
                   2585:        case OP_SRC1:
                   2586:                retval = get_fregval_s (fsrc1);
                   2587:                break;
                   2588:        case OP_SRC2:
                   2589:                retval = get_fregval_s (fsrc2);
                   2590:                break;
                   2591:        case OP_KI:
                   2592:                retval = m_KI.s;
                   2593:                break;
                   2594:        case OP_KR:
                   2595:                retval = m_KR.s;
                   2596:                break;
                   2597:        case OP_T:
                   2598:                retval = m_T.s;
                   2599:                break;
                   2600:        case OP_MPIPE:
                   2601:                /* Last stage is 3rd stage for single precision input.  */
                   2602:                retval = m_M[2].val.s;
                   2603:                break;
                   2604:        case OP_APIPE:
                   2605:                retval = m_A[2].val.s;
                   2606:                break;
                   2607:        default:
                   2608:                assert (0);
                   2609:        }
                   2610: 
                   2611:        return retval;
                   2612: }
                   2613: 
                   2614: 
                   2615: double i860_cpu_device::get_fval_from_optype_d (UINT32 insn, int optype)
                   2616: {
                   2617:        double retval = 0.0;
                   2618:        UINT32 fsrc1 = get_fsrc1 (insn);
                   2619:        UINT32 fsrc2 = get_fsrc2 (insn);
                   2620: 
                   2621:        optype &= ~FLAGM;
                   2622:        switch (optype)
                   2623:        {
                   2624:        case OP_SRC1:
                   2625:                retval = get_fregval_d (fsrc1);
                   2626:                break;
                   2627:        case OP_SRC2:
                   2628:                retval = get_fregval_d (fsrc2);
                   2629:                break;
                   2630:        case OP_KI:
                   2631:                retval = m_KI.d;
                   2632:                break;
                   2633:        case OP_KR:
                   2634:                retval = m_KR.d;
                   2635:                break;
                   2636:        case OP_T:
                   2637:                retval = m_T.d;
                   2638:                break;
                   2639:        case OP_MPIPE:
                   2640:                /* Last stage is 2nd stage for double precision input.  */
                   2641:                retval = m_M[1].val.d;
                   2642:                break;
                   2643:        case OP_APIPE:
                   2644:                retval = m_A[2].val.d;
                   2645:                break;
                   2646:        default:
                   2647:                assert (0);
                   2648:        }
                   2649: 
                   2650:        return retval;
                   2651: }
                   2652: 
                   2653: 
                   2654: /* Execute pf[m]{a,s}m.{ss,sd,dd} fsrc1,fsrc2,fdest (FP dual ops).
                   2655: 
                   2656:    Since these are always pipelined, the P bit is used to distinguish
                   2657:    family pfam (P=1) from family pfmam (P=0), and the lower 4 bits
                   2658:    of the extended opcode is the DPC.
                   2659: 
                   2660:    Note also that the S and R bits are slightly different than normal
                   2661:    floating point operations.  The S bit denotes the precision of the
                   2662:    multiplication source, while the R bit denotes the precision of
                   2663:    the addition source as well as precision of all results.  */
                   2664: void i860_cpu_device::insn_dualop (UINT32 insn)
                   2665: {
                   2666:        UINT32 fsrc1 = get_fsrc1 (insn);
                   2667:        UINT32 fsrc2 = get_fsrc2 (insn);
                   2668:        UINT32 fdest = get_fdest (insn);
                   2669:        int src_prec = insn & 0x100;     /* 1 = double, 0 = single.  */
                   2670:        int res_prec = insn & 0x080;     /* 1 = double, 0 = single.  */
                   2671:        int is_pfam = insn & 0x400;      /* 1 = pfam, 0 = pfmam.  */
                   2672:        int is_sub = insn & 0x10;        /* 1 = pf[m]sm, 0 = pf[m]am.  */
                   2673:        double dbl_tmp_dest_mul = 0.0;
                   2674:        float sgl_tmp_dest_mul = 0.0;
                   2675:        double dbl_tmp_dest_add = 0.0;
                   2676:        float sgl_tmp_dest_add = 0.0;
                   2677:        double dbl_last_Mstage_contents = 0.0;
                   2678:        float sgl_last_Mstage_contents = 0.0;
                   2679:        double dbl_last_Astage_contents = 0.0;
                   2680:        float sgl_last_Astage_contents = 0.0;
                   2681:        int num_mul_stages = src_prec ? 2 : 3;
                   2682: 
                   2683:        int dpc = insn & 0xf;
                   2684:        int M_unit_op1 = src_opers[dpc].M_unit_op1;
                   2685:        int M_unit_op2 = src_opers[dpc].M_unit_op2;
                   2686:        int A_unit_op1 = src_opers[dpc].A_unit_op1;
                   2687:        int A_unit_op2 = src_opers[dpc].A_unit_op2;
                   2688:        int T_loaded = src_opers[dpc].T_loaded;
                   2689:        int K_loaded = src_opers[dpc].K_loaded;
                   2690: 
                   2691: #if TRACE_UNDEFINED_I860
                   2692:        /* Check for invalid .ds combination.  */
                   2693:        if ((insn & 0x180) == 0x100)
                   2694:        {
                   2695:                unrecog_opcode (m_pc, insn);
                   2696:                return;
                   2697:        }
                   2698: #endif
                   2699:     
                   2700:        if (is_pfam == 0)
                   2701:        {
                   2702: #if TRACE_UNDEFINED_I860
                   2703:                /* Check for invalid DPC combination 16 for PFMAM.  */
                   2704:                if (dpc == 16)
                   2705:                {
                   2706:                        unrecog_opcode (m_pc, insn);
                   2707:                        return;
                   2708:                }
                   2709: #endif
                   2710:         
                   2711:                /* PFMAM table adjustments (M_unit_op1 is never a pipe stage,
                   2712:                   so no adjustment made for it).   */
                   2713:                M_unit_op2 = (M_unit_op2 & FLAGM) ? OP_MPIPE : M_unit_op2;
                   2714:                A_unit_op1 = (A_unit_op1 & FLAGM) ? OP_MPIPE : A_unit_op1;
                   2715:                A_unit_op2 = (A_unit_op2 & FLAGM) ? OP_MPIPE : A_unit_op2;
                   2716:        }
                   2717: 
                   2718:        /* FIXME: Check for fsrc1/fdest overlap for some mul DPC combinations.  */
                   2719: 
                   2720:        /* Retrieve the contents of the last stage of the multiplier pipeline,
                   2721:           whose precision is specified by the MRP bit of the stage's result-
                   2722:           status bits.  Note for multiply, the number of stages is determined
                   2723:           by the source precision of the current operation.  */
                   2724:        if (m_M[num_mul_stages - 1].stat.mrp)
                   2725:                dbl_last_Mstage_contents = m_M[num_mul_stages - 1].val.d;
                   2726:        else
                   2727:                sgl_last_Mstage_contents = m_M[num_mul_stages - 1].val.s;
                   2728: 
                   2729:        /* Similarly, retrieve the last stage of the adder pipe.  */
                   2730:        if (m_A[2].stat.arp)
                   2731:                dbl_last_Astage_contents = m_A[2].val.d;
                   2732:        else
                   2733:                sgl_last_Astage_contents = m_A[2].val.s;
                   2734: 
                   2735:        /* Do the mul operation, being careful about source and result
                   2736:           precision.  */
                   2737:        if (src_prec)
                   2738:        {
                   2739:                double v1 = get_fval_from_optype_d (insn, M_unit_op1);
                   2740:                double v2 = get_fval_from_optype_d (insn, M_unit_op2);
                   2741: 
                   2742:                /* For mul, if fsrc2 is the same as fdest, then the last stage
                   2743:                   is bypassed to fsrc2 (rather than using the value in fsrc2).
                   2744:                   This bypass is not available for fsrc1, and is undefined behavior.  */
                   2745:                if (0 && M_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest)
                   2746:                        v1 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents;
                   2747:                if (M_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest)
                   2748:                        v2 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents;
                   2749: 
                   2750:                if (res_prec)
                   2751:                        dbl_tmp_dest_mul = v1 * v2;
                   2752:                else
                   2753:                        sgl_tmp_dest_mul = (float)(v1 * v2);
                   2754:        }
                   2755:        else
                   2756:        {
                   2757:                float v1 = get_fval_from_optype_s (insn, M_unit_op1);
                   2758:                float v2 = get_fval_from_optype_s (insn, M_unit_op2);
                   2759: 
                   2760:                /* For mul, if fsrc2 is the same as fdest, then the last stage
                   2761:                   is bypassed to fsrc2 (rather than using the value in fsrc2).
                   2762:                   This bypass is not available for fsrc1, and is undefined behavior.  */
                   2763:                if (0 && M_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest)
                   2764:                        v1 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents;
                   2765:                if (M_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest)
                   2766:                        v2 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents;
                   2767: 
                   2768:                if (res_prec)
                   2769:                        dbl_tmp_dest_mul = (double)(v1 * v2);
                   2770:                else
                   2771:                        sgl_tmp_dest_mul = v1 * v2;
                   2772:        }
                   2773: 
                   2774:        /* Do the add operation, being careful about source and result
                   2775:           precision.  Remember, the R bit indicates source and result precision
                   2776:           here.  */
                   2777:        if (res_prec)
                   2778:        {
                   2779:                double v1 = get_fval_from_optype_d (insn, A_unit_op1);
                   2780:                double v2 = get_fval_from_optype_d (insn, A_unit_op2);
                   2781: 
                   2782:                /* For add/sub, if fsrc1 is the same as fdest, then the last stage
                   2783:                   is bypassed to fsrc1 (rather than using the value in fsrc1).
                   2784:                   Likewise for fsrc2.  */
                   2785:                if (A_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest)
                   2786:                        v1 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents;
                   2787:                if (A_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest)
                   2788:                        v2 = is_pfam ? dbl_last_Astage_contents : dbl_last_Mstage_contents;
                   2789: 
                   2790:                if (res_prec)
                   2791:                        dbl_tmp_dest_add = is_sub ? v1 - v2 : v1 + v2;
                   2792:                else
                   2793:                        sgl_tmp_dest_add = is_sub ? (float)(v1 - v2) : (float)(v1 + v2);
                   2794:        }
                   2795:        else
                   2796:        {
                   2797:                float v1 = get_fval_from_optype_s (insn, A_unit_op1);
                   2798:                float v2 = get_fval_from_optype_s (insn, A_unit_op2);
                   2799: 
                   2800:                /* For add/sub, if fsrc1 is the same as fdest, then the last stage
                   2801:                   is bypassed to fsrc1 (rather than using the value in fsrc1).
                   2802:                   Likewise for fsrc2.  */
                   2803:                if (A_unit_op1 == OP_SRC1 && fdest != 0 && fsrc1 == fdest)
                   2804:                        v1 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents;
                   2805:                if (A_unit_op2 == OP_SRC2 && fdest != 0 && fsrc2 == fdest)
                   2806:                        v2 = is_pfam ? sgl_last_Astage_contents : sgl_last_Mstage_contents;
                   2807: 
                   2808:                if (res_prec)
                   2809:                        dbl_tmp_dest_add = is_sub ? (double)(v1 - v2) : (double)(v1 + v2);
                   2810:                else
                   2811:                        sgl_tmp_dest_add = is_sub ? v1 - v2 : v1 + v2;
                   2812:        }
                   2813: 
                   2814:        /* If necessary, load T.  */
                   2815:        if (T_loaded)
                   2816:        {
                   2817:                /* T is loaded from the result of the last stage of the multiplier.  */
                   2818:                if (m_M[num_mul_stages - 1].stat.mrp)
                   2819:                        m_T.d = dbl_last_Mstage_contents;
                   2820:                else
                   2821:                        m_T.s = sgl_last_Mstage_contents;
                   2822:        }
                   2823: 
                   2824:        /* If necessary, load KR or KI.  */
                   2825:        if (K_loaded)
                   2826:        {
                   2827:                /* KI or KR is loaded from the first register input.  */
                   2828:                if (M_unit_op1 == OP_KI)
                   2829:                {
                   2830:                        if (src_prec)
                   2831:                                m_KI.d = get_fregval_d (fsrc1);
                   2832:                        else
                   2833:                                m_KI.s  = get_fregval_s (fsrc1);
                   2834:                }
                   2835:                else if (M_unit_op1 == OP_KR)
                   2836:                {
                   2837:                        if (src_prec)
                   2838:                                m_KR.d = get_fregval_d (fsrc1);
                   2839:                        else
                   2840:                                m_KR.s  = get_fregval_s (fsrc1);
                   2841:                }
                   2842:                else
                   2843:                        assert (0);
                   2844:        }
                   2845: 
                   2846:        /* Now update fdest (either from adder pipe or multiplier pipe,
                   2847:           depending on whether the instruction is pfam or pfmam).  */
                   2848:        if (is_pfam)
                   2849:        {
                   2850:                /* Update fdest with the result from the last stage of the
                   2851:                   adder pipeline, with precision specified by the ARP
                   2852:                   bit of the stage's result-status bits.  */
                   2853:                if (m_A[2].stat.arp)
                   2854:                        set_fregval_d (fdest, dbl_last_Astage_contents);
                   2855:                else
                   2856:                        set_fregval_s (fdest, sgl_last_Astage_contents);
                   2857:        }
                   2858:        else
                   2859:        {
                   2860:                /* Update fdest with the result from the last stage of the
                   2861:                   multiplier pipeline, with precision specified by the MRP
                   2862:                   bit of the stage's result-status bits.  */
                   2863:                if (m_M[num_mul_stages - 1].stat.mrp)
                   2864:                        set_fregval_d (fdest, dbl_last_Mstage_contents);
                   2865:                else
                   2866:                        set_fregval_s (fdest, sgl_last_Mstage_contents);
                   2867:        }
                   2868: 
                   2869:        /* FIXME: Set result-status bits besides MRP. And copy to fsr from
                   2870:                  last stage.  */
                   2871:        /* FIXME: Mixed precision (only weird for pfmul).  */
                   2872: #if 1 /* FIXME: WIP on FSR update.  This may not be correct.  */
                   2873:        /* Copy 3rd stage MRP to FSR.  */
                   2874:        if (m_M[num_mul_stages - 2  /* 1 */].stat.mrp)
                   2875:                m_cregs[CR_FSR] |= 0x10000000;
                   2876:        else
                   2877:                m_cregs[CR_FSR] &= ~0x10000000;
                   2878: #endif
                   2879: 
                   2880:        /* Now advance multiplier pipeline and write current calculation to
                   2881:           first stage.  */
                   2882:        if (num_mul_stages == 3)
                   2883:        {
                   2884:                m_M[2] = m_M[1];
                   2885:                m_M[1] = m_M[0];
                   2886:        }
                   2887:        else
                   2888:                m_M[1]  = m_M[0];
                   2889: 
                   2890:        if (res_prec)
                   2891:        {
                   2892:                m_M[0].val.d = dbl_tmp_dest_mul;
                   2893:                m_M[0].stat.mrp = 1;
                   2894:        }
                   2895:        else
                   2896:        {
                   2897:                m_M[0].val.s = sgl_tmp_dest_mul;
                   2898:                m_M[0].stat.mrp = 0;
                   2899:        }
                   2900: 
                   2901:        /* FIXME: Set result-status bits besides ARP. And copy to fsr from
                   2902:                  last stage.  */
                   2903: #if 1 /* FIXME: WIP on FSR update.  This may not be correct.  */
                   2904:        /* Copy 3rd stage ARP to FSR.  */
                   2905:        if (m_A[1 /* 2 */].stat.arp)
                   2906:                m_cregs[CR_FSR] |= 0x20000000;
                   2907:        else
                   2908:                m_cregs[CR_FSR] &= ~0x20000000;
                   2909: #endif
                   2910: 
                   2911:        /* Now advance adder pipeline and write current calculation to
                   2912:           first stage.  */
                   2913:        m_A[2] = m_A[1];
                   2914:        m_A[1] = m_A[0];
                   2915:        if (res_prec)
                   2916:        {
                   2917:                m_A[0].val.d = dbl_tmp_dest_add;
                   2918:                m_A[0].stat.arp = 1;
                   2919:        }
                   2920:        else
                   2921:        {
                   2922:                m_A[0].val.s = sgl_tmp_dest_add;
                   2923:                m_A[0].stat.arp = 0;
                   2924:        }
                   2925: }
                   2926: 
                   2927: 
                   2928: /* Execute frcp.{ss,sd,dd} fsrc2,fdest (.ds disallowed above).  */
                   2929: void i860_cpu_device::insn_frcp (UINT32 insn)
                   2930: {
                   2931:        UINT32 fsrc2 = get_fsrc2 (insn);
                   2932:        UINT32 fdest = get_fdest (insn);
                   2933:        int src_prec = insn & 0x100;     /* 1 = double, 0 = single.  */
                   2934:        int res_prec = insn & 0x080;     /* 1 = double, 0 = single.  */
                   2935: 
                   2936:        /* Do the operation, being careful about source and result
                   2937:           precision.  */
                   2938:        if (src_prec)
                   2939:        {
                   2940:                double v = get_fregval_d (fsrc2);
                   2941:                double res;
                   2942:                if (v == (double)0.0)
                   2943:                {
                   2944:                        /* Generate source-exception trap if fsrc2 is 0.  */
                   2945:                        if (0 /* && GET_FSR_FTE () */)
                   2946:                        {
                   2947:                                SET_PSR_FT (1);
                   2948:                                SET_FSR_SE (1);
                   2949:                                m_flow |= GET_FSR_FTE ();
                   2950:                        }
                   2951:                        /* Set fdest to INF or some other exceptional value here?  */
                   2952:                }
                   2953:                else
                   2954:                {
                   2955:                        /* Real i860 isn't a precise as a real divide, but this should
                   2956:                           be okay.  */
                   2957:                        SET_FSR_SE (0);
                   2958:                        *((UINT64 *)&v) &= 0xfffff00000000000ULL;
                   2959:                        res = (double)1.0/v;
                   2960:                        *((UINT64 *)&res) &= 0xfffff00000000000ULL;
                   2961:                        if (res_prec)
                   2962:                                set_fregval_d (fdest, res);
                   2963:                        else
                   2964:                                set_fregval_s (fdest, (float)res);
                   2965:                }
                   2966:        }
                   2967:        else
                   2968:        {
                   2969:                float v = get_fregval_s (fsrc2);
                   2970:                float res;
                   2971:                if (v == 0.0)
                   2972:                {
                   2973:                        /* Generate source-exception trap if fsrc2 is 0.  */
                   2974:                        if (0 /* GET_FSR_FTE () */)
                   2975:                        {
                   2976:                                SET_PSR_FT (1);
                   2977:                                SET_FSR_SE (1);
                   2978:                                m_flow |= GET_FSR_FTE ();
                   2979:                        }
                   2980:                        /* Set fdest to INF or some other exceptional value here?  */
                   2981:                }
                   2982:                else
                   2983:                {
                   2984:                        /* Real i860 isn't a precise as a real divide, but this should
                   2985:                           be okay.  */
                   2986:                        SET_FSR_SE (0);
                   2987:                        *((UINT32 *)&v) &= 0xffff8000;
                   2988:                        res = (float)1.0/v;
                   2989:                        *((UINT32 *)&res) &= 0xffff8000;
                   2990:                        if (res_prec)
                   2991:                                set_fregval_d (fdest, (double)res);
                   2992:                        else
                   2993:                                set_fregval_s (fdest, res);
                   2994:                }
                   2995:        }
                   2996: }
                   2997: 
                   2998: 
                   2999: /* Execute frsqr.{ss,sd,dd} fsrc2,fdest (.ds disallowed above).  */
                   3000: void i860_cpu_device::insn_frsqr (UINT32 insn)
                   3001: {
                   3002:        UINT32 fsrc2 = get_fsrc2 (insn);
                   3003:        UINT32 fdest = get_fdest (insn);
                   3004:        int src_prec = insn & 0x100;     /* 1 = double, 0 = single.  */
                   3005:        int res_prec = insn & 0x080;     /* 1 = double, 0 = single.  */
                   3006: 
                   3007: #if TRACE_UNDEFINED_I860
                   3008:        /* Check for invalid .ds combination.  */
                   3009:        if ((insn & 0x180) == 0x100)
                   3010:        {
                   3011:                unrecog_opcode (m_pc, insn);
                   3012:                return;
                   3013:        }
                   3014: 
                   3015:        /* Check for invalid .ds combination.  */
                   3016:        if ((insn & 0x180) == 0x100)
                   3017:        {
                   3018:                unrecog_opcode (m_pc, insn);
                   3019:                return;
                   3020:        }
                   3021: #endif
                   3022:     
                   3023:        /* Do the operation, being careful about source and result
                   3024:           precision.  */
                   3025:        if (src_prec)
                   3026:        {
                   3027:                double v = get_fregval_d (fsrc2);
                   3028:                double res;
                   3029:                if (v == 0.0 || v < 0.0)
                   3030:                {
                   3031:                        /* Generate source-exception trap if fsrc2 is 0 or negative.  */
                   3032:                        if (0 /* GET_FSR_FTE () */)
                   3033:                        {
                   3034:                                SET_PSR_FT (1);
                   3035:                                SET_FSR_SE (1);
                   3036:                                m_flow |= GET_FSR_FTE ();
                   3037:                        }
                   3038:                        /* Set fdest to INF or some other exceptional value here?  */
                   3039:                }
                   3040:                else
                   3041:                {
                   3042:                        SET_FSR_SE (0);
                   3043:                        *((UINT64 *)&v) &= 0xfffff00000000000ULL;
                   3044:                        res = (double)1.0/sqrt (v);
                   3045:                        *((UINT64 *)&res) &= 0xfffff00000000000ULL;
                   3046:                        if (res_prec)
                   3047:                                set_fregval_d (fdest, res);
                   3048:                        else
                   3049:                                set_fregval_s (fdest, (float)res);
                   3050:                }
                   3051:        }
                   3052:        else
                   3053:        {
                   3054:                float v = get_fregval_s (fsrc2);
                   3055:                float res;
                   3056:                if (v == 0.0 || v < 0.0)
                   3057:                {
                   3058:                        /* Generate source-exception trap if fsrc2 is 0 or negative.  */
                   3059:                        if (0 /* GET_FSR_FTE () */)
                   3060:                        {
                   3061:                                SET_PSR_FT (1);
                   3062:                                SET_FSR_SE (1);
                   3063:                                m_flow |= GET_FSR_FTE ();
                   3064:                        }
                   3065:                        /* Set fdest to INF or some other exceptional value here?  */
                   3066:                }
                   3067:                else
                   3068:                {
                   3069:                        SET_FSR_SE (0);
                   3070:                        *((UINT32 *)&v) &= 0xffff8000;
                   3071:                        res = (float)1.0/sqrt (v);
                   3072:                        *((UINT32 *)&res) &= 0xffff8000;
                   3073:                        if (res_prec)
                   3074:                                set_fregval_d (fdest, (double)res);
                   3075:                        else
                   3076:                                set_fregval_s (fdest, res);
                   3077:                }
                   3078:        }
                   3079: }
                   3080: 
                   3081: 
                   3082: /* Execute fxfr fsrc1,idest.  */
                   3083: void i860_cpu_device::insn_fxfr (UINT32 insn)
                   3084: {
                   3085:        UINT32 fsrc1 = get_fsrc1 (insn);
                   3086:        UINT32 idest = get_idest (insn);
                   3087:        float fv = 0;
                   3088: 
                   3089:        /* This is a bit-pattern transfer, not a conversion.  */
                   3090:        fv = get_fregval_s (fsrc1);
                   3091:        set_iregval (idest, *(UINT32 *)&fv);
                   3092: }
                   3093: 
                   3094: 
                   3095: /* Execute [p]ftrunc.{ss,sd,dd} fsrc1,idest.  */
                   3096: /* FIXME: Is .ss really a valid combination?  On the one hand,
                   3097:    the programmer's reference (1990) lists ftrunc.p where .p
                   3098:    is any of {ss,sd,dd}.  On the other hand, a paragraph on the
                   3099:    same page states that [p]ftrunc must specify double-precision
                   3100:    results.  Inconsistent.
                   3101:    Update: The vendor SVR4 assembler does not accept .ss combination,
                   3102:    so the latter sentence above appears to be the correct way.  */
                   3103: void i860_cpu_device::insn_ftrunc (UINT32 insn)
                   3104: {
                   3105:        UINT32 fsrc1 = get_fsrc1 (insn);
                   3106:        UINT32 fdest = get_fdest (insn);
                   3107:        int src_prec = insn & 0x100;     /* 1 = double, 0 = single.  */
                   3108:        int res_prec = insn & 0x080;     /* 1 = double, 0 = single.  */
                   3109:        int piped = insn & 0x400;        /* 1 = pipelined, 0 = scalar.  */
                   3110: 
                   3111: #if TRACE_UNDEFINED_I860
                   3112:        /* Check for invalid .ds or .ss combinations.  */
                   3113:        if ((insn & 0x080) == 0)
                   3114:        {
                   3115:                unrecog_opcode (m_pc, insn);
                   3116:                return;
                   3117:        }
                   3118: #endif
                   3119:     
                   3120:        /* Do the operation, being careful about source and result
                   3121:           precision.  Operation: fdest = integer part of fsrc1 in
                   3122:           lower 32-bits.  */
                   3123:        if (src_prec)
                   3124:        {
                   3125:                double v1 = get_fregval_d (fsrc1);
                   3126:                INT32 iv = (INT32)v1;
                   3127:                /* We always write a single, since the lower 32-bits of fdest
                   3128:                   get the result (and the even numbered reg is the lower).  */
                   3129:                set_fregval_s (fdest, *(float *)&iv);
                   3130:        }
                   3131:        else
                   3132:        {
                   3133:                float v1 = get_fregval_s (fsrc1);
                   3134:                INT32 iv = (INT32)v1;
                   3135:                /* We always write a single, since the lower 32-bits of fdest
                   3136:                   get the result (and the even numbered reg is the lower).  */
                   3137:                set_fregval_s (fdest, *(float *)&iv);
                   3138:        }
                   3139: 
                   3140:        /* FIXME: Handle updating of pipestages for pftrunc.  */
                   3141:        /* Includes looking at ARP (add result precision.) */
                   3142:        if (piped)
                   3143:        {
                   3144:                Log_Printf(LOG_WARN, "[i860:%08X] insn_ftrunc: FIXME: pipelined not functional yet", m_pc);
                   3145:                if (res_prec)
                   3146:                        set_fregval_d (fdest, 0.0);
                   3147:                else
                   3148:                        set_fregval_s (fdest, 0.0);
                   3149:        }
                   3150: }
                   3151: 
                   3152: 
                   3153: /* Execute [p]famov.{ss,sd,ds,dd} fsrc1,fdest.  */
                   3154: void i860_cpu_device::insn_famov (UINT32 insn)
                   3155: {
                   3156:        UINT32 fsrc1 = get_fsrc1 (insn);
                   3157:        UINT32 fdest = get_fdest (insn);
                   3158:        int src_prec = insn & 0x100;     /* 1 = double, 0 = single.  */
                   3159:        int res_prec = insn & 0x080;     /* 1 = double, 0 = single.  */
                   3160:        int piped = insn & 0x400;        /* 1 = pipelined, 0 = scalar.  */
                   3161:        double dbl_tmp_dest = 0.0;
                   3162:        double sgl_tmp_dest = 0.0;
                   3163: 
                   3164:        /* Do the operation, being careful about source and result
                   3165:           precision.  */
                   3166:        if (src_prec)
                   3167:        {
                   3168:                double v1 = get_fregval_d (fsrc1);
                   3169:                if (res_prec)
                   3170:                        dbl_tmp_dest = v1;
                   3171:                else
                   3172:                        sgl_tmp_dest = (float)v1;
                   3173:        }
                   3174:        else
                   3175:        {
                   3176:                float v1 = get_fregval_s (fsrc1);
                   3177:                if (res_prec)
                   3178:                        dbl_tmp_dest = (double)v1;
                   3179:                else
                   3180:                        sgl_tmp_dest = v1;
                   3181:        }
                   3182: 
                   3183:        /* FIXME: Set result-status bits besides ARP. And copy to fsr from
                   3184:                  last stage.  */
                   3185:        /* FIXME: Scalar version flows through all stages.  */
                   3186:        if (!piped)
                   3187:        {
                   3188:                /* Scalar version writes the current calculation to the fdest
                   3189:                   register, with precision specified by the R bit.  */
                   3190:                if (res_prec)
                   3191:                        set_fregval_d (fdest, dbl_tmp_dest);
                   3192:                else
                   3193:                        set_fregval_s (fdest, sgl_tmp_dest);
                   3194:        }
                   3195:        else
                   3196:        {
                   3197:                /* Pipelined version writes fdest with the result from the last
                   3198:                   stage of the pipeline, with precision specified by the ARP
                   3199:                   bit of the stage's result-status bits.  */
                   3200: #if 1 /* FIXME: WIP on FSR update.  This may not be correct.  */
                   3201:                /* Copy 3rd stage ARP to FSR.  */
                   3202:                if (m_A[1 /* 2 */].stat.arp)
                   3203:                        m_cregs[CR_FSR] |= 0x20000000;
                   3204:                else
                   3205:                        m_cregs[CR_FSR] &= ~0x20000000;
                   3206: #endif
                   3207:                if (m_A[2].stat.arp)  /* 3rd (last) stage.  */
                   3208:                        set_fregval_d (fdest, m_A[2].val.d);
                   3209:                else
                   3210:                        set_fregval_s (fdest, m_A[2].val.s);
                   3211: 
                   3212:                /* Now advance pipeline and write current calculation to
                   3213:                   first stage.  */
                   3214:                m_A[2] = m_A[1];
                   3215:                m_A[1] = m_A[0];
                   3216:                if (res_prec)
                   3217:                {
                   3218:                        m_A[0].val.d = dbl_tmp_dest;
                   3219:                        m_A[0].stat.arp = 1;
                   3220:                }
                   3221:                else
                   3222:                {
                   3223:                        m_A[0].val.s = sgl_tmp_dest;
                   3224:                        m_A[0].stat.arp = 0;
                   3225:                }
                   3226:        }
                   3227: }
                   3228: 
                   3229: 
                   3230: /* Execute [p]fiadd/sub.{ss,dd} fsrc1,fsrc2,fdest.  */
                   3231: void i860_cpu_device::insn_fiadd_sub (UINT32 insn)
                   3232: {
                   3233:        UINT32 fsrc1 = get_fsrc1 (insn);
                   3234:        UINT32 fsrc2 = get_fsrc2 (insn);
                   3235:        UINT32 fdest = get_fdest (insn);
                   3236:        int src_prec = insn & 0x100;     /* 1 = double, 0 = single.  */
                   3237:        int res_prec = insn & 0x080;     /* 1 = double, 0 = single.  */
                   3238:        int piped = insn & 0x400;        /* 1 = pipelined, 0 = scalar.  */
                   3239:        int is_sub = insn & 0x4;         /* 1 = sub, 0 = add.  */
                   3240:        double dbl_tmp_dest = 0.0;
                   3241:        float sgl_tmp_dest = 0.0;
                   3242: 
                   3243: #if TRACE_UNDEFINED_I860
                   3244:        /* Check for invalid .ds and .sd combinations.  */
                   3245:        if ((insn & 0x180) == 0x100 || (insn & 0x180) == 0x080)
                   3246:        {
                   3247:                unrecog_opcode (m_pc, insn);
                   3248:                return;
                   3249:        }
                   3250: #endif
                   3251:     
                   3252:        /* Do the operation, being careful about source and result
                   3253:           precision.  */
                   3254:        if (src_prec)
                   3255:        {
                   3256:                double v1 = get_fregval_d (fsrc1);
                   3257:                double v2 = get_fregval_d (fsrc2);
                   3258:                UINT64 iv1 = *(UINT64 *)&v1;
                   3259:                UINT64 iv2 = *(UINT64 *)&v2;
                   3260:                UINT64 r;
                   3261:                if (is_sub)
                   3262:                        r = iv1 - iv2;
                   3263:                else
                   3264:                        r = iv1 + iv2;
                   3265:                if (res_prec)
                   3266:                        dbl_tmp_dest = *(double *)&r;
                   3267:                else
                   3268:                        assert (0);    /* .ds not allowed.  */
                   3269:        }
                   3270:        else
                   3271:        {
                   3272:                float v1 = get_fregval_s (fsrc1);
                   3273:                float v2 = get_fregval_s (fsrc2);
                   3274:                UINT64 iv1 = (UINT64)(*(UINT32 *)&v1);
                   3275:                UINT64 iv2 = (UINT64)(*(UINT32 *)&v2);
                   3276:                UINT32 r;
                   3277:                if (is_sub)
                   3278:                        r = (UINT32)(iv1 - iv2);
                   3279:                else
                   3280:                        r = (UINT32)(iv1 + iv2);
                   3281:                if (res_prec)
                   3282:                        assert (0);    /* .sd not allowed.  */
                   3283:                else
                   3284:                        sgl_tmp_dest = *(float *)&r;
                   3285:        }
                   3286: 
                   3287:        /* FIXME: Copy result-status bit IRP to fsr from last stage.  */
                   3288:        /* FIXME: Scalar version flows through all stages.  */
                   3289:        if (!piped)
                   3290:        {
                   3291:                /* Scalar version writes the current calculation to the fdest
                   3292:                   register, with precision specified by the R bit.  */
                   3293:                if (res_prec)
                   3294:                        set_fregval_d (fdest, dbl_tmp_dest);
                   3295:                else
                   3296:                        set_fregval_s (fdest, sgl_tmp_dest);
                   3297:        }
                   3298:        else
                   3299:        {
                   3300:                /* Pipelined version writes fdest with the result from the last
                   3301:                   stage of the pipeline, with precision specified by the IRP
                   3302:                   bit of the stage's result-status bits.  */
                   3303: #if 1 /* FIXME: WIP on FSR update.  This may not be correct.  */
                   3304:                /* Copy stage IRP to FSR.  */
                   3305:                if (res_prec)
                   3306:                        m_cregs[CR_FSR] |= 0x08000000;
                   3307:                else
                   3308:                        m_cregs[CR_FSR] &= ~0x08000000;
                   3309: #endif
                   3310:                if (m_G.stat.irp)   /* 1st (and last) stage.  */
                   3311:                        set_fregval_d (fdest, m_G.val.d);
                   3312:                else
                   3313:                        set_fregval_s (fdest, m_G.val.s);
                   3314: 
                   3315:                /* Now write current calculation to first and only stage.  */
                   3316:                if (res_prec)
                   3317:                {
                   3318:                        m_G.val.d = dbl_tmp_dest;
                   3319:                        m_G.stat.irp = 1;
                   3320:                }
                   3321:                else
                   3322:                {
                   3323:                        m_G.val.s = sgl_tmp_dest;
                   3324:                        m_G.stat.irp = 0;
                   3325:                }
                   3326:        }
                   3327: }
                   3328: 
                   3329: 
                   3330: /* Execute pf{gt,le,eq}.{ss,dd} fsrc1,fsrc2,fdest.
                   3331:    Opcode pfgt has R bit cleared; pfle has R bit set.  */
                   3332: void i860_cpu_device::insn_fcmp (UINT32 insn) {
                   3333:        UINT32 fsrc1 = get_fsrc1 (insn);
                   3334:        UINT32 fsrc2 = get_fsrc2 (insn);
                   3335:        UINT32 fdest = get_fdest (insn);
                   3336:        int src_prec = insn & 0x100;     /* 1 = double, 0 = single.  */
                   3337:        double dbl_tmp_dest = 0.0;
                   3338:        double sgl_tmp_dest = 0.0;
                   3339:        /* int is_eq = insn & 1; */
                   3340:        int is_gt = ((insn & 0x81) == 0x00);
                   3341:        int is_le = ((insn & 0x81) == 0x80);
                   3342: 
                   3343:     /* Save the CC for DIM bc/bnc */
                   3344:     m_dim_cc       = GET_PSR_CC();
                   3345:     m_dim_cc_valid = m_dim != DIM_NONE;
                   3346:     
                   3347:        /* Do the operation.  Source and result precision must be the same.
                   3348:             pfgt: CC set     if fsrc1 > fsrc2, else cleared.
                   3349:             pfle: CC cleared if fsrc1 <= fsrc2, else set.
                   3350:             pfeq: CC set     if fsrc1 = fsrc2, else cleared.
                   3351: 
                   3352:           Note that the compares write an undefined (but non-exceptional)
                   3353:           result into the first stage of the adder pipeline.  We'll model
                   3354:           this by just pushing in dbl_ or sgl_tmp_dest which equal 0.0.  */
                   3355:        if (src_prec) {
                   3356:                double v1 = get_fregval_d (fsrc1);
                   3357:                double v2 = get_fregval_d (fsrc2);
                   3358:                if (is_gt)                /* gt.  */
                   3359:                        SET_PSR_CC_F (v1 > v2 ? 1 : 0);
                   3360:                else if (is_le)           /* le.  */
                   3361:                        SET_PSR_CC_F (v1 <= v2 ? 0 : 1);
                   3362:                else                      /* eq.  */
                   3363:                        SET_PSR_CC_F (v1 == v2 ? 1 : 0);
                   3364:        } else {
                   3365:                float v1 = get_fregval_s (fsrc1);
                   3366:                float v2 = get_fregval_s (fsrc2);
                   3367:                if (is_gt)                /* gt.  */
                   3368:                        SET_PSR_CC_F (v1 > v2 ? 1 : 0);
                   3369:                else if (is_le)           /* le.  */
                   3370:                        SET_PSR_CC_F (v1 <= v2 ? 0 : 1);
                   3371:                else                      /* eq.  */
                   3372:                        SET_PSR_CC_F (v1 == v2 ? 1 : 0);
                   3373:        }
                   3374: 
                   3375:        /* FIXME: Set result-status bits besides ARP. And copy to fsr from
                   3376:                  last stage.  */
                   3377:        /* These write fdest with the result from the last
                   3378:           stage of the pipeline, with precision specified by the ARP
                   3379:           bit of the stage's result-status bits.  */
                   3380: #if 1 /* FIXME: WIP on FSR update.  This may not be correct.  */
                   3381:        /* Copy 3rd stage ARP to FSR.  */
                   3382:        if (m_A[1 /* 2 */].stat.arp)
                   3383:                m_cregs[CR_FSR] |= 0x20000000;
                   3384:        else
                   3385:                m_cregs[CR_FSR] &= ~0x20000000;
                   3386: #endif
                   3387:        if (m_A[2].stat.arp)  /* 3rd (last) stage.  */
                   3388:                set_fregval_d (fdest, m_A[2].val.d);
                   3389:        else
                   3390:                set_fregval_s (fdest, m_A[2].val.s);
                   3391: 
                   3392:        /* Now advance pipeline and write current calculation to
                   3393:           first stage.  */
                   3394:        m_A[2] = m_A[1];
                   3395:        m_A[1] = m_A[0];
                   3396:        if (src_prec) {
                   3397:                m_A[0].val.d = dbl_tmp_dest;
                   3398:                m_A[0].stat.arp = 1;
                   3399:        } else {
                   3400:                m_A[0].val.s = sgl_tmp_dest;
                   3401:                m_A[0].stat.arp = 0;
                   3402:        }
                   3403: }
                   3404: 
                   3405: 
                   3406: /* Execute [p]fzchk{l,s} fsrc1,fsrc2,fdest.
                   3407:    The fzchk instructions have S and R bits set.  */
                   3408: void i860_cpu_device::insn_fzchk (UINT32 insn)
                   3409: {
                   3410:        UINT32 fsrc1 = get_fsrc1 (insn);
                   3411:        UINT32 fsrc2 = get_fsrc2 (insn);
                   3412:        UINT32 fdest = get_fdest (insn);
                   3413:        int piped = insn & 0x400;        /* 1 = pipelined, 0 = scalar.  */
                   3414:        int is_fzchks = insn & 8;        /* 1 = fzchks, 0 = fzchkl.  */
                   3415:        double dbl_tmp_dest = 0.0;
                   3416:        int i;
                   3417:        double v1 = get_fregval_d (fsrc1);
                   3418:        double v2 = get_fregval_d (fsrc2);
                   3419:        UINT64 iv1 = *(UINT64 *)&v1;
                   3420:        UINT64 iv2 = *(UINT64 *)&v2;
                   3421:        UINT64 r = 0;
                   3422:        char pm = GET_PSR_PM ();
                   3423: 
                   3424: #if TRACE_UNDEFINED_I860
                   3425:        /* Check for S and R bits set.  */
                   3426:        if ((insn & 0x180) != 0x180)
                   3427:        {
                   3428:                unrecog_opcode (m_pc, insn);
                   3429:                return;
                   3430:        }
                   3431: #endif
                   3432:     
                   3433:        /* Do the operation.  The fzchks version operates in parallel on
                   3434:           four 16-bit pixels, while the fzchkl operates on two 32-bit
                   3435:           pixels (pixels are unsigned ordinals in this context).  */
                   3436:        if (is_fzchks)
                   3437:        {
                   3438:                pm = (pm >> 4) & 0x0f;
                   3439:                for (i = 3; i >= 0; i--)
                   3440:                {
                   3441:                        UINT16 ps1 = (iv1 >> (i * 16)) & 0xffff;
                   3442:                        UINT16 ps2 = (iv2 >> (i * 16)) & 0xffff;
                   3443:                        if (ps2 <= ps1)
                   3444:                        {
                   3445:                                r |= ((UINT64)ps2 << (i * 16));
                   3446:                                pm |= (1 << (7 - (3 - i)));
                   3447:                        }
                   3448:                        else
                   3449:                        {
                   3450:                                r |= ((UINT64)ps1 << (i * 16));
                   3451:                                pm &= ~(1 << (7 - (3 - i)));
                   3452:                        }
                   3453:                }
                   3454:        }
                   3455:        else
                   3456:        {
                   3457:                pm = (pm >> 2) & 0x3f;
                   3458:                for (i = 1; i >= 0; i--)
                   3459:                {
                   3460:                        UINT32 ps1 = (iv1 >> (i * 32)) & 0xffffffff;
                   3461:                        UINT32 ps2 = (iv2 >> (i * 32)) & 0xffffffff;
                   3462:                        if (ps2 <= ps1)
                   3463:                        {
                   3464:                                r |= ((UINT64)ps2 << (i * 32));
                   3465:                                pm |= (1 << (7 - (1 - i)));
                   3466:                        }
                   3467:                        else
                   3468:                        {
                   3469:                                r |= ((UINT64)ps1 << (i * 32));
                   3470:                                pm &= ~(1 << (7 - (1 - i)));
                   3471:                        }
                   3472:                }
                   3473:        }
                   3474: 
                   3475:        dbl_tmp_dest = *(double *)&r;
                   3476:        SET_PSR_PM (pm);
                   3477:     m_merge = 0;
                   3478: 
                   3479:        /* FIXME: Copy result-status bit IRP to fsr from last stage.  */
                   3480:        /* FIXME: Scalar version flows through all stages.  */
                   3481:        if (!piped)
                   3482:        {
                   3483:                /* Scalar version writes the current calculation to the fdest
                   3484:                   register, always with double precision.  */
                   3485:                set_fregval_d (fdest, dbl_tmp_dest);
                   3486:        }
                   3487:        else
                   3488:        {
                   3489:                /* Pipelined version writes fdest with the result from the last
                   3490:                   stage of the pipeline, with precision specified by the IRP
                   3491:                   bit of the stage's result-status bits.  */
                   3492:                if (m_G.stat.irp)   /* 1st (and last) stage.  */
                   3493:                        set_fregval_d (fdest, m_G.val.d);
                   3494:                else
                   3495:                        set_fregval_s (fdest, m_G.val.s);
                   3496: 
                   3497:                /* Now write current calculation to first and only stage.  */
                   3498:                m_G.val.d = dbl_tmp_dest;
                   3499:                m_G.stat.irp = 1;
                   3500:        }
                   3501: }
                   3502: 
                   3503: 
                   3504: /* Execute [p]form.dd fsrc1,fdest.
                   3505:    The form.dd instructions have S and R bits set.  */
                   3506: void i860_cpu_device::insn_form (UINT32 insn)
                   3507: {
                   3508:        UINT32 fsrc1 = get_fsrc1 (insn);
                   3509:        UINT32 fdest = get_fdest (insn);
                   3510:        int piped = insn & 0x400;        /* 1 = pipelined, 0 = scalar.  */
                   3511:        double dbl_tmp_dest = 0.0;
                   3512:        double v1 = get_fregval_d (fsrc1);
                   3513:        UINT64 iv1 = *(UINT64 *)&v1;
                   3514: 
                   3515: #if TRACE_UNDEFINED_I860
                   3516:        /* Check for S and R bits set.  */
                   3517:        if ((insn & 0x180) != 0x180)
                   3518:        {
                   3519:                unrecog_opcode (m_pc, insn);
                   3520:                return;
                   3521:        }
                   3522: #endif
                   3523:     
                   3524:        iv1 |= m_merge;
                   3525:        dbl_tmp_dest = *(double *)&iv1;
                   3526:        m_merge = 0;
                   3527: 
                   3528:        /* FIXME: Copy result-status bit IRP to fsr from last stage.  */
                   3529:        /* FIXME: Scalar version flows through all stages.  */
                   3530:        if (!piped)
                   3531:        {
                   3532:                /* Scalar version writes the current calculation to the fdest
                   3533:                   register, always with double precision.  */
                   3534:                set_fregval_d (fdest, dbl_tmp_dest);
                   3535:        }
                   3536:        else
                   3537:        {
                   3538:                /* Pipelined version writes fdest with the result from the last
                   3539:                   stage of the pipeline, with precision specified by the IRP
                   3540:                   bit of the stage's result-status bits.  */
                   3541:                if (m_G.stat.irp)   /* 1st (and last) stage.  */
                   3542:                        set_fregval_d (fdest, m_G.val.d);
                   3543:                else
                   3544:                        set_fregval_s (fdest, m_G.val.s);
                   3545: 
                   3546:                /* Now write current calculation to first and only stage.  */
                   3547:                m_G.val.d = dbl_tmp_dest;
                   3548:                m_G.stat.irp = 1;
                   3549:        }
                   3550: }
                   3551: 
                   3552: 
                   3553: /* Execute [p]faddp fsrc1,fsrc2,fdest.  */
                   3554: void i860_cpu_device::insn_faddp (UINT32 insn)
                   3555: {
                   3556:        UINT32 fsrc1 = get_fsrc1 (insn);
                   3557:        UINT32 fsrc2 = get_fsrc2 (insn);
                   3558:        UINT32 fdest = get_fdest (insn);
                   3559:        int piped = insn & 0x400;        /* 1 = pipelined, 0 = scalar.  */
                   3560:        double dbl_tmp_dest = 0.0;
                   3561:        double v1 = get_fregval_d (fsrc1);
                   3562:        double v2 = get_fregval_d (fsrc2);
                   3563:        UINT64 iv1 = *(UINT64 *)&v1;
                   3564:        UINT64 iv2 = *(UINT64 *)&v2;
                   3565:        UINT64 r = 0;
                   3566:        int ps = GET_PSR_PS ();
                   3567: 
                   3568:        r = iv1 + iv2;
                   3569:        dbl_tmp_dest = *(double *)&r;
                   3570:     
                   3571:        /* Update the merge register depending on the pixel size.
                   3572:           PS: 0 = 8 bits, 1 = 16 bits, 2 = 32-bits.  */
                   3573:        if (ps == 0)
                   3574:        {
                   3575:                m_merge = ((m_merge >> 8) & ~0xff00ff00ff00ff00ULL);
                   3576:                m_merge |= (r & 0xff00ff00ff00ff00ULL);
                   3577:        }
                   3578:        else if (ps == 1)
                   3579:        {
                   3580:                m_merge = ((m_merge >> 6) & ~0xfc00fc00fc00fc00ULL);
                   3581:                m_merge |= (r & 0xfc00fc00fc00fc00ULL);
                   3582:        }
                   3583:        else if (ps == 2)
                   3584:        {
                   3585:                m_merge = ((m_merge >> 8) & ~0xff000000ff000000ULL);
                   3586:                m_merge |= (r & 0xff000000ff000000ULL);
                   3587:        }
                   3588: #if TRACE_UNDEFINED_I860
                   3589:        else
                   3590:                Log_Printf(LOG_WARN, "[i860:%08X] insn_faddp: Undefined i860XR behavior, invalid value %d for pixel size", m_pc, ps);
                   3591: #endif
                   3592: 
                   3593:        /* FIXME: Copy result-status bit IRP to fsr from last stage.  */
                   3594:        /* FIXME: Scalar version flows through all stages.  */
                   3595:        if (!piped)
                   3596:        {
                   3597:                /* Scalar version writes the current calculation to the fdest
                   3598:                   register, always with double precision.  */
                   3599:                set_fregval_d (fdest, dbl_tmp_dest);
                   3600:        }
                   3601:        else
                   3602:        {
                   3603:                /* Pipelined version writes fdest with the result from the last
                   3604:                   stage of the pipeline, with precision specified by the IRP
                   3605:                   bit of the stage's result-status bits.  */
                   3606:                if (m_G.stat.irp)   /* 1st (and last) stage.  */
                   3607:                        set_fregval_d (fdest, m_G.val.d);
                   3608:                else
                   3609:                        set_fregval_s (fdest, m_G.val.s);
                   3610: 
                   3611:                /* Now write current calculation to first and only stage.  */
                   3612:                m_G.val.d = dbl_tmp_dest;
                   3613:                m_G.stat.irp = 1;
                   3614:        }
                   3615: }
                   3616: 
                   3617: 
                   3618: /* Execute [p]faddz fsrc1,fsrc2,fdest.  */
                   3619: void i860_cpu_device::insn_faddz (UINT32 insn)
                   3620: {
                   3621:        UINT32 fsrc1 = get_fsrc1 (insn);
                   3622:        UINT32 fsrc2 = get_fsrc2 (insn);
                   3623:        UINT32 fdest = get_fdest (insn);
                   3624:        int piped = insn & 0x400;        /* 1 = pipelined, 0 = scalar.  */
                   3625:        double dbl_tmp_dest = 0.0;
                   3626:        double v1 = get_fregval_d (fsrc1);
                   3627:        double v2 = get_fregval_d (fsrc2);
                   3628:        UINT64 iv1 = *(UINT64 *)&v1;
                   3629:        UINT64 iv2 = *(UINT64 *)&v2;
                   3630:        UINT64 r = 0;
                   3631: 
                   3632:        r = iv1 + iv2;
                   3633:        dbl_tmp_dest = *(double *)&r;
                   3634: 
                   3635:        /* Update the merge register.  */
                   3636:        m_merge = ((m_merge >> 16) & ~0xffff0000ffff0000ULL);
                   3637:        m_merge |= (r & 0xffff0000ffff0000ULL);
                   3638: 
                   3639:        /* FIXME: Copy result-status bit IRP to fsr from last stage.  */
                   3640:        /* FIXME: Scalar version flows through all stages.  */
                   3641:        if (!piped)
                   3642:        {
                   3643:                /* Scalar version writes the current calculation to the fdest
                   3644:                   register, always with double precision.  */
                   3645:                set_fregval_d (fdest, dbl_tmp_dest);
                   3646:        }
                   3647:        else
                   3648:        {
                   3649:                /* Pipelined version writes fdest with the result from the last
                   3650:                   stage of the pipeline, with precision specified by the IRP
                   3651:                   bit of the stage's result-status bits.  */
                   3652:                if (m_G.stat.irp)   /* 1st (and last) stage.  */
                   3653:                        set_fregval_d (fdest, m_G.val.d);
                   3654:                else
                   3655:                        set_fregval_s (fdest, m_G.val.s);
                   3656: 
                   3657:                /* Now write current calculation to first and only stage.  */
                   3658:                m_G.val.d = dbl_tmp_dest;
                   3659:                m_G.stat.irp = 1;
                   3660:        }
                   3661: }
                   3662: 
                   3663: 
                   3664: /* Flags for the decode table.  */
                   3665: enum {
                   3666:        DEC_MORE    = 1,    /* More decoding necessary.  */
                   3667:        DEC_DECODED = 2     /* Fully decoded, go.  */
                   3668: };
                   3669: 
                   3670: 
                   3671: /* First-level decode table (i.e., for the 6 primary opcode bits).  */
                   3672: const i860_cpu_device::decode_tbl_t i860_cpu_device::decode_tbl[64] = {
                   3673:        /* A slight bit of decoding for loads and stores is done in the
                   3674:           execution routines (operand size and addressing mode), which
                   3675:           is why their respective entries are identical.  */
                   3676:        { &i860_cpu_device::insn_ldx,         DEC_DECODED}, /* ld.b isrc1(isrc2),idest.  */
                   3677:        { &i860_cpu_device::insn_ldx,         DEC_DECODED}, /* ld.b #const(isrc2),idest.  */
                   3678:        { &i860_cpu_device::insn_ixfr,        DEC_DECODED}, /* ixfr isrc1ni,fdest.  */
                   3679:        { &i860_cpu_device::insn_stx,         DEC_DECODED}, /* st.b isrc1ni,#const(isrc2).  */
                   3680:        { &i860_cpu_device::insn_ldx,         DEC_DECODED}, /* ld.{s,l} isrc1(isrc2),idest.  */
                   3681:        { &i860_cpu_device::insn_ldx,         DEC_DECODED}, /* ld.{s,l} #const(isrc2),idest.  */
                   3682:        { 0,                0},
                   3683:        { &i860_cpu_device::insn_stx,         DEC_DECODED}, /* st.{s,l} isrc1ni,#const(isrc2),idest.*/
                   3684:        { &i860_cpu_device::insn_fldy,        DEC_DECODED}, /* fld.{l,d,q} isrc1(isrc2)[++],fdest. */
                   3685:        { &i860_cpu_device::insn_fldy,        DEC_DECODED}, /* fld.{l,d,q} #const(isrc2)[++],fdest. */
                   3686:        { &i860_cpu_device::insn_fsty,        DEC_DECODED}, /* fst.{l,d,q} fdest,isrc1(isrc2)[++] */
                   3687:        { &i860_cpu_device::insn_fsty,        DEC_DECODED}, /* fst.{l,d,q} fdest,#const(isrc2)[++] */
                   3688:        { &i860_cpu_device::insn_ld_ctrl,     DEC_DECODED}, /* ld.c csrc2,idest.  */
                   3689:        { &i860_cpu_device::insn_flush,       DEC_DECODED}, /* flush #const(isrc2) (or autoinc).  */
                   3690:        { &i860_cpu_device::insn_st_ctrl,     DEC_DECODED}, /* st.c isrc1,csrc2.  */
                   3691:        { &i860_cpu_device::insn_pstd,        DEC_DECODED}, /* pst.d fdest,#const(isrc2)[++].  */
                   3692:        { &i860_cpu_device::insn_bri,         DEC_DECODED}, /* bri isrc1ni.  */
                   3693:        { &i860_cpu_device::insn_trap,        DEC_DECODED}, /* trap isrc1ni,isrc2,idest.   */
                   3694:        { 0,                DEC_MORE}, /* FP ESCAPE FORMAT, more decode.  */
                   3695:        { 0,                DEC_MORE}, /* CORE ESCAPE FORMAT, more decode.  */
                   3696:        { &i860_cpu_device::insn_btne,        DEC_DECODED}, /* btne isrc1,isrc2,sbroff.  */
                   3697:        { &i860_cpu_device::insn_btne_imm,    DEC_DECODED}, /* btne #const,isrc2,sbroff.  */
                   3698:        { &i860_cpu_device::insn_bte,         DEC_DECODED}, /* bte isrc1,isrc2,sbroff.  */
                   3699:        { &i860_cpu_device::insn_bte_imm,     DEC_DECODED}, /* bte #const5,isrc2,idest.  */
                   3700:        { &i860_cpu_device::insn_fldy,        DEC_DECODED}, /* pfld.{l,d,q} isrc1(isrc2)[++],fdest.*/
                   3701:        { &i860_cpu_device::insn_fldy,        DEC_DECODED}, /* pfld.{l,d,q} #const(isrc2)[++],fdest.*/
                   3702:        { &i860_cpu_device::insn_br,          DEC_DECODED}, /* br lbroff.  */
                   3703:        { &i860_cpu_device::insn_call,        DEC_DECODED}, /* call lbroff .  */
                   3704:        { &i860_cpu_device::insn_bc,          DEC_DECODED}, /* bc lbroff.  */
                   3705:        { &i860_cpu_device::insn_bct,         DEC_DECODED}, /* bc.t lbroff.  */
                   3706:        { &i860_cpu_device::insn_bnc,         DEC_DECODED}, /* bnc lbroff.  */
                   3707:        { &i860_cpu_device::insn_bnct,        DEC_DECODED}, /* bnc.t lbroff.  */
                   3708:        { &i860_cpu_device::insn_addu,        DEC_DECODED}, /* addu isrc1,isrc2,idest.  */
                   3709:        { &i860_cpu_device::insn_addu_imm,    DEC_DECODED}, /* addu #const,isrc2,idest.  */
                   3710:        { &i860_cpu_device::insn_subu,        DEC_DECODED}, /* subu isrc1,isrc2,idest.  */
                   3711:        { &i860_cpu_device::insn_subu_imm,    DEC_DECODED}, /* subu #const,isrc2,idest.  */
                   3712:        { &i860_cpu_device::insn_adds,        DEC_DECODED}, /* adds isrc1,isrc2,idest.  */
                   3713:        { &i860_cpu_device::insn_adds_imm,    DEC_DECODED}, /* adds #const,isrc2,idest.  */
                   3714:        { &i860_cpu_device::insn_subs,        DEC_DECODED}, /* subs isrc1,isrc2,idest.  */
                   3715:        { &i860_cpu_device::insn_subs_imm,    DEC_DECODED}, /* subs #const,isrc2,idest.  */
                   3716:        { &i860_cpu_device::insn_shl,         DEC_DECODED}, /* shl isrc1,isrc2,idest.  */
                   3717:        { &i860_cpu_device::insn_shl_imm,     DEC_DECODED}, /* shl #const,isrc2,idest.  */
                   3718:        { &i860_cpu_device::insn_shr,         DEC_DECODED}, /* shr isrc1,isrc2,idest.  */
                   3719:        { &i860_cpu_device::insn_shr_imm,     DEC_DECODED}, /* shr #const,isrc2,idest.  */
                   3720:        { &i860_cpu_device::insn_shrd,        DEC_DECODED}, /* shrd isrc1ni,isrc2,idest.  */
                   3721:        { &i860_cpu_device::insn_bla,         DEC_DECODED}, /* bla isrc1ni,isrc2,sbroff.  */
                   3722:        { &i860_cpu_device::insn_shra,        DEC_DECODED}, /* shra isrc1,isrc2,idest.  */
                   3723:        { &i860_cpu_device::insn_shra_imm,    DEC_DECODED}, /* shra #const,isrc2,idest.  */
                   3724:        { &i860_cpu_device::insn_and,         DEC_DECODED}, /* and isrc1,isrc2,idest.  */
                   3725:        { &i860_cpu_device::insn_and_imm,     DEC_DECODED}, /* and #const,isrc2,idest.  */
                   3726:        { 0,                0},
                   3727:        { &i860_cpu_device::insn_andh_imm,    DEC_DECODED}, /* andh #const,isrc2,idest.  */
                   3728:        { &i860_cpu_device::insn_andnot,      DEC_DECODED}, /* andnot isrc1,isrc2,idest.  */
                   3729:        { &i860_cpu_device::insn_andnot_imm,  DEC_DECODED}, /* andnot #const,isrc2,idest.  */
                   3730:        { 0,                0},
                   3731:        { &i860_cpu_device::insn_andnoth_imm, DEC_DECODED}, /* andnoth #const,isrc2,idest.  */
                   3732:        { &i860_cpu_device::insn_or,          DEC_DECODED}, /* or isrc1,isrc2,idest.  */
                   3733:        { &i860_cpu_device::insn_or_imm,      DEC_DECODED}, /* or #const,isrc2,idest.  */
                   3734:        { 0,                0},
                   3735:        { &i860_cpu_device::insn_orh_imm,     DEC_DECODED}, /* orh #const,isrc2,idest.  */
                   3736:        { &i860_cpu_device::insn_xor,         DEC_DECODED}, /* xor isrc1,isrc2,idest.  */
                   3737:        { &i860_cpu_device::insn_xor_imm,     DEC_DECODED}, /* xor #const,isrc2,idest.  */
                   3738:        { 0,                0},
                   3739:        { &i860_cpu_device::insn_xorh_imm,    DEC_DECODED}, /* xorh #const,isrc2,idest.  */
                   3740: };
                   3741: 
                   3742: 
                   3743: /* Second-level decode table (i.e., for the 3 core escape opcode bits).  */
                   3744: const i860_cpu_device::decode_tbl_t i860_cpu_device::core_esc_decode_tbl[8] = {
                   3745:        { 0,                0},
                   3746:        { 0,                0}, /* lock  (FIXME: unimplemented).  */
                   3747:        { &i860_cpu_device::insn_calli,       DEC_DECODED}, /* calli isrc1ni.                 */
                   3748:        { 0,                0},
                   3749:        { &i860_cpu_device::insn_intovr,      DEC_DECODED}, /* intovr.                        */
                   3750:        { 0,                0},
                   3751:        { 0,                0},
                   3752:        { 0,                0}, /* unlock (FIXME: unimplemented). */
                   3753: };
                   3754: 
                   3755: 
                   3756: /* Second-level decode table (i.e., for the 7 FP extended opcode bits).  */
                   3757: const i860_cpu_device::decode_tbl_t i860_cpu_device::fp_decode_tbl[128] = {
                   3758:        /* Floating point instructions.  The least significant 7 bits are
                   3759:           the (extended) opcode and bits 10:7 are P,D,S,R respectively
                   3760:           ([p]ipelined, [d]ual, [s]ource prec., [r]esult prec.).
                   3761:           For some operations, I defer decoding the P,S,R bits to the
                   3762:           emulation routine for them.  */
                   3763:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x00 pf[m]am */
                   3764:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x01 pf[m]am */
                   3765:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x02 pf[m]am */
                   3766:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x03 pf[m]am */
                   3767:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x04 pf[m]am */
                   3768:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x05 pf[m]am */
                   3769:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x06 pf[m]am */
                   3770:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x07 pf[m]am */
                   3771:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x08 pf[m]am */
                   3772:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x09 pf[m]am */
                   3773:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x0A pf[m]am */
                   3774:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x0B pf[m]am */
                   3775:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x0C pf[m]am */
                   3776:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x0D pf[m]am */
                   3777:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x0E pf[m]am */
                   3778:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x0F pf[m]am */
                   3779:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x10 pf[m]sm */
                   3780:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x11 pf[m]sm */
                   3781:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x12 pf[m]sm */
                   3782:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x13 pf[m]sm */
                   3783:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x14 pf[m]sm */
                   3784:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x15 pf[m]sm */
                   3785:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x16 pf[m]sm */
                   3786:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x17 pf[m]sm */
                   3787:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x18 pf[m]sm */
                   3788:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x19 pf[m]sm */
                   3789:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x1A pf[m]sm */
                   3790:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x1B pf[m]sm */
                   3791:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x1C pf[m]sm */
                   3792:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x1D pf[m]sm */
                   3793:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x1E pf[m]sm */
                   3794:        { &i860_cpu_device::insn_dualop,      DEC_DECODED}, /* 0x1F pf[m]sm */
                   3795:        { &i860_cpu_device::insn_fmul,        DEC_DECODED}, /* 0x20 [p]fmul */
                   3796:        { &i860_cpu_device::insn_fmlow,       DEC_DECODED}, /* 0x21 fmlow.dd */
                   3797:        { &i860_cpu_device::insn_frcp,        DEC_DECODED}, /* 0x22 frcp.{ss,sd,dd} */
                   3798:        { &i860_cpu_device::insn_frsqr,       DEC_DECODED}, /* 0x23 frsqr.{ss,sd,dd} */
                   3799:        { &i860_cpu_device::insn_fmul,        DEC_DECODED}, /* 0x24 pfmul3.dd */
                   3800:        { 0,                0}, /* 0x25 */
                   3801:        { 0,                0}, /* 0x26 */
                   3802:        { 0,                0}, /* 0x27 */
                   3803:        { 0,                0}, /* 0x28 */
                   3804:        { 0,                0}, /* 0x29 */
                   3805:        { 0,                0}, /* 0x2A */
                   3806:        { 0,                0}, /* 0x2B */
                   3807:        { 0,                0}, /* 0x2C */
                   3808:        { 0,                0}, /* 0x2D */
                   3809:        { 0,                0}, /* 0x2E */
                   3810:        { 0,                0}, /* 0x2F */
                   3811:        { &i860_cpu_device::insn_fadd_sub,    DEC_DECODED}, /* 0x30, [p]fadd.{ss,sd,dd} */
                   3812:        { &i860_cpu_device::insn_fadd_sub,    DEC_DECODED}, /* 0x31, [p]fsub.{ss,sd,dd} */
                   3813:        { &i860_cpu_device::insn_fix,         DEC_DECODED}, /* 0x32, [p]fix.{ss,sd,dd} */
                   3814:        { &i860_cpu_device::insn_famov,       DEC_DECODED}, /* 0x33, [p]famov.{ss,sd,ds,dd} */
                   3815:        { &i860_cpu_device::insn_fcmp,        DEC_DECODED}, /* 0x34, pf{gt,le}.{ss,dd} */
                   3816:        { &i860_cpu_device::insn_fcmp,        DEC_DECODED}, /* 0x35, pfeq.{ss,dd} */
                   3817:        { 0,                0}, /* 0x36 */
                   3818:        { 0,                0}, /* 0x37 */
                   3819:        { 0,                0}, /* 0x38 */
                   3820:        { 0,                0}, /* 0x39 */
                   3821:        { &i860_cpu_device::insn_ftrunc,      DEC_DECODED}, /* 0x3A, [p]ftrunc.{ss,sd,dd} */
                   3822:        { 0,                0}, /* 0x3B */
                   3823:        { 0,                0}, /* 0x3C */
                   3824:        { 0,                0}, /* 0x3D */
                   3825:        { 0,                0}, /* 0x3E */
                   3826:        { 0,                0}, /* 0x3F */
                   3827:        { &i860_cpu_device::insn_fxfr,        DEC_DECODED}, /* 0x40, fxfr */
                   3828:        { 0,                0}, /* 0x41 */
                   3829:        { 0,                0}, /* 0x42 */
                   3830:        { 0,                0}, /* 0x43 */
                   3831:        { 0,                0}, /* 0x44 */
                   3832:        { 0,                0}, /* 0x45 */
                   3833:        { 0,                0}, /* 0x46 */
                   3834:        { 0,                0}, /* 0x47 */
                   3835:        { 0,                0}, /* 0x48 */
                   3836:        { &i860_cpu_device::insn_fiadd_sub,   DEC_DECODED}, /* 0x49, [p]fiadd.{ss,dd} */
                   3837:        { 0,                0}, /* 0x4A */
                   3838:        { 0,                0}, /* 0x4B */
                   3839:        { 0,                0}, /* 0x4C */
                   3840:        { &i860_cpu_device::insn_fiadd_sub,   DEC_DECODED}, /* 0x4D, [p]fisub.{ss,dd} */
                   3841:        { 0,                0}, /* 0x4E */
                   3842:        { 0,                0}, /* 0x4F */
                   3843:        { &i860_cpu_device::insn_faddp,       DEC_DECODED}, /* 0x50, [p]faddp */
                   3844:        { &i860_cpu_device::insn_faddz,       DEC_DECODED}, /* 0x51, [p]faddz */
                   3845:        { 0,                0}, /* 0x52 */
                   3846:        { 0,                0}, /* 0x53 */
                   3847:        { 0,                0}, /* 0x54 */
                   3848:        { 0,                0}, /* 0x55 */
                   3849:        { 0,                0}, /* 0x56 */
                   3850:        { &i860_cpu_device::insn_fzchk,       DEC_DECODED}, /* 0x57, [p]fzchkl */
                   3851:        { 0,                0}, /* 0x58 */
                   3852:        { 0,                0}, /* 0x59 */
                   3853:        { &i860_cpu_device::insn_form,        DEC_DECODED}, /* 0x5A, [p]form.dd */
                   3854:        { 0,                0}, /* 0x5B */
                   3855:        { 0,                0}, /* 0x5C */
                   3856:        { 0,                0}, /* 0x5D */
                   3857:        { 0,                0}, /* 0x5E */
                   3858:        { &i860_cpu_device::insn_fzchk,       DEC_DECODED}, /* 0x5F, [p]fzchks */
                   3859:        { 0,                0}, /* 0x60 */
                   3860:        { 0,                0}, /* 0x61 */
                   3861:        { 0,                0}, /* 0x62 */
                   3862:        { 0,                0}, /* 0x63 */
                   3863:        { 0,                0}, /* 0x64 */
                   3864:        { 0,                0}, /* 0x65 */
                   3865:        { 0,                0}, /* 0x66 */
                   3866:        { 0,                0}, /* 0x67 */
                   3867:        { 0,                0}, /* 0x68 */
                   3868:        { 0,                0}, /* 0x69 */
                   3869:        { 0,                0}, /* 0x6A */
                   3870:        { 0,                0}, /* 0x6B */
                   3871:        { 0,                0}, /* 0x6C */
                   3872:        { 0,                0}, /* 0x6D */
                   3873:        { 0,                0}, /* 0x6E */
                   3874:        { 0,                0}, /* 0x6F */
                   3875:        { 0,                0}, /* 0x70 */
                   3876:        { 0,                0}, /* 0x71 */
                   3877:        { 0,                0}, /* 0x72 */
                   3878:        { 0,                0}, /* 0x73 */
                   3879:        { 0,                0}, /* 0x74 */
                   3880:        { 0,                0}, /* 0x75 */
                   3881:        { 0,                0}, /* 0x76 */
                   3882:        { 0,                0}, /* 0x77 */
                   3883:        { 0,                0}, /* 0x78 */
                   3884:        { 0,                0}, /* 0x79 */
                   3885:        { 0,                0}, /* 0x7A */
                   3886:        { 0,                0}, /* 0x7B */
                   3887:        { 0,                0}, /* 0x7C */
                   3888:        { 0,                0}, /* 0x7D */
                   3889:        { 0,                0}, /* 0x7E */
                   3890:        { 0,                0}, /* 0x7F */
                   3891: };
                   3892: 
                   3893: /*
                   3894:  * Main decoder driver.
                   3895:  *  insn = instruction at the current PC to execute.
                   3896:  *  non_shadow = This insn is not in the shadow of a delayed branch - (SC) unused, removed).
                   3897:  */
                   3898: void i860_cpu_device::decode_exec (UINT32 insn) {
                   3899:     if(m_flow & EXITING_IFETCH) return;
                   3900:     
                   3901: #if ENABLE_PERF_COUNTERS
                   3902:     m_insn_decoded++;
                   3903: #endif
                   3904:     
                   3905: #if ENABLE_DEBUGGER
                   3906:     m_traceback[m_traceback_idx++] = m_pc;
                   3907:     if(m_traceback_idx >= (sizeof(m_traceback) / sizeof(m_traceback[0])))
                   3908:         m_traceback_idx = 0;
                   3909: #endif
                   3910:     
                   3911:     int unrecognized = 1;
                   3912:        const int  upper_6bits = (insn >> 26) & 0x3f;
                   3913:        const char flags = decode_tbl[upper_6bits].flags;
                   3914:        if (flags & DEC_DECODED) {
                   3915:                (this->*decode_tbl[upper_6bits].insn_exec)(insn);
                   3916:                unrecognized = 0;
                   3917:        } else if (flags & DEC_MORE) {
                   3918:                if (upper_6bits == 0x12) {
                   3919:                        /* FP instruction format handled here.  */
                   3920:                        if (fp_decode_tbl[insn & 0x7f].flags & DEC_DECODED) {
                   3921:                                (this->*fp_decode_tbl[insn & 0x7f].insn_exec)(insn);
                   3922:                                unrecognized = 0;
                   3923:                        }
                   3924:                } else if (upper_6bits == 0x13) {
                   3925:                        /* Core escape instruction format handled here.  */
                   3926:                        if (core_esc_decode_tbl[insn & 0x3].flags & DEC_DECODED) {
                   3927:                                (this->*core_esc_decode_tbl[insn & 0x3].insn_exec)(insn);
                   3928:                                unrecognized = 0;
                   3929:                        }
                   3930:                }
                   3931:        }
                   3932:     
                   3933:        if (unrecognized)
                   3934:                unrecog_opcode (m_pc, insn);
                   3935: }
                   3936: 
                   3937: 
                   3938: /* Set-up all the default power-on/reset values.  */
                   3939: void i860_cpu_device::reset() {
                   3940:     UINT32 UNDEF_VAL = 0x55aa5500;
                   3941:     
                   3942:        int i;
                   3943:        /* On power-up/reset, i860 has values:
                   3944:             PC = 0xffffff00.
                   3945:             Integer registers: r0 = 0, others = undefined.
                   3946:             FP registers:      f0:f1 = 0, others undefined.
                   3947:             psr: U = IM = BR = BW = 0; others = undefined.
                   3948:             epsr: IL = WP = PBM = BE = 0; processor type, stepping, and
                   3949:                   DCS are proper and read-only; others = undefined.
                   3950:             db: undefined.
                   3951:             dirbase: DPS, BL, ATE = 0
                   3952:             fir, fsr, KR, KI, MERGE: undefined. (what about T?)
                   3953: 
                   3954:             I$: flushed.
                   3955:             D$: undefined (all modified bits = 0).
                   3956:             TLB: flushed.
                   3957: 
                   3958:           Note that any undefined values are set to UNDEF_VAL patterns to
                   3959:           try to detect defective i860 software.  */
                   3960: 
                   3961:        /* PC is at trap address after reset.  */
                   3962:        m_pc = 0xffffff00;
                   3963: 
                   3964:        /* Set grs and frs to undefined/nonsense values, except r0.  */
                   3965:        for (i = 0; i < 32; i++){
                   3966:         set_iregval (i, UNDEF_VAL | i);
                   3967:                set_fregval_s (i, 0.0);
                   3968:        }
                   3969:        set_iregval (0, 0);
                   3970:        set_fregval_s (0, 0.0);
                   3971:        set_fregval_s (1, 0.0);
                   3972: 
                   3973:        /* Set whole psr to 0.  This sets the proper bits to 0 as specified
                   3974:           above, and zeroes the undefined bits.  */
                   3975:        m_cregs[CR_PSR] = 0;
                   3976: 
                   3977:        /* Set most of the epsr bits to 0 (as specified above), leaving
                   3978:           undefined as zero as well.  Then properly set processor type,
                   3979:           step, and DCS. Type = EPSR[7..0], step = EPSR[12..8],
                   3980:           DCS = EPSR[21..18] (2^[12+dcs] = cache size).
                   3981:           We'll pretend to be stepping D0, since it has the fewest bugs
                   3982:           (and I don't want to emulate the many defects in the earlier
                   3983:           steppings).
                   3984:           Proc type: 1 = XR, 2 = XP   (XR has 8KB data cache -> DCS = 1).
                   3985:           Steppings (XR): 3,4,5,6,7 = (B2, C0, B3, C1, D0 respectively).
                   3986:           Steppings (XP): 0, 2, 3, 4 = (A0, B0, B1, B2) (any others?).  */
                   3987:        m_cregs[CR_EPSR] = 0x00040701;
                   3988: 
                   3989:        /* Set DPS, BL, ATE = 0 and the undefined parts also to 0. But CS8 mode to 1 */
                   3990:        m_cregs[CR_DIRBASE] = 0x00000080;
                   3991: 
                   3992:        /* Set fir, fsr, KR, KI, MERGE, T to undefined.  */
                   3993:        m_cregs[CR_FIR] = UNDEF_VAL;
                   3994:        m_cregs[CR_FSR] = UNDEF_VAL;
                   3995:        m_KR.d          = 0.0;
                   3996:        m_KI.d          = 0.0;
                   3997:        m_T.d           = 0.0;
                   3998:        m_merge         = 0;
                   3999:        m_flow          = 0;
                   4000:     
                   4001:     /* dual instruction mode is off after reset */
                   4002:     m_dim           = DIM_NONE;
                   4003:     m_dim_cc_valid  = false;
                   4004:     
                   4005:     /* invalidate caches */
                   4006:     invalidate_icache();
                   4007:     invalidate_tlb();
                   4008:     
                   4009:     /* memory access is little endian */
                   4010:     set_mem_access(false);
                   4011:     
                   4012:     halt(false);
                   4013: }

unix.superglobalmegacorp.com

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