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