Annotation of previous_trunk/src/dimension/i860dec.cpp, revision 1.1

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

unix.superglobalmegacorp.com

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