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