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