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