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

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

unix.superglobalmegacorp.com

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