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