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