2010-09-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
[deliverable/binutils-gdb.git] / sim / rx / rx.c
1 /* rx.c --- opcode semantics for stand-alone RX simulator.
2
3 Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
5
6 This file is part of the GNU simulators.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21 #include "config.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <signal.h>
26
27 #include "opcode/rx.h"
28 #include "cpu.h"
29 #include "mem.h"
30 #include "syscalls.h"
31 #include "fpu.h"
32 #include "err.h"
33 #include "misc.h"
34
35 #ifdef CYCLE_STATS
36 static const char * id_names[] = {
37 "RXO_unknown",
38 "RXO_mov", /* d = s (signed) */
39 "RXO_movbi", /* d = [s,s2] (signed) */
40 "RXO_movbir", /* [s,s2] = d (signed) */
41 "RXO_pushm", /* s..s2 */
42 "RXO_popm", /* s..s2 */
43 "RXO_xchg", /* s <-> d */
44 "RXO_stcc", /* d = s if cond(s2) */
45 "RXO_rtsd", /* rtsd, 1=imm, 2-0 = reg if reg type */
46
47 /* These are all either d OP= s or, if s2 is set, d = s OP s2. Note
48 that d may be "None". */
49 "RXO_and",
50 "RXO_or",
51 "RXO_xor",
52 "RXO_add",
53 "RXO_sub",
54 "RXO_mul",
55 "RXO_div",
56 "RXO_divu",
57 "RXO_shll",
58 "RXO_shar",
59 "RXO_shlr",
60
61 "RXO_adc", /* d = d + s + carry */
62 "RXO_sbb", /* d = d - s - ~carry */
63 "RXO_abs", /* d = |s| */
64 "RXO_max", /* d = max(d,s) */
65 "RXO_min", /* d = min(d,s) */
66 "RXO_emul", /* d:64 = d:32 * s */
67 "RXO_emulu", /* d:64 = d:32 * s (unsigned) */
68
69 "RXO_rolc", /* d <<= 1 through carry */
70 "RXO_rorc", /* d >>= 1 through carry*/
71 "RXO_rotl", /* d <<= #s without carry */
72 "RXO_rotr", /* d >>= #s without carry*/
73 "RXO_revw", /* d = revw(s) */
74 "RXO_revl", /* d = revl(s) */
75 "RXO_branch", /* pc = d if cond(s) */
76 "RXO_branchrel",/* pc += d if cond(s) */
77 "RXO_jsr", /* pc = d */
78 "RXO_jsrrel", /* pc += d */
79 "RXO_rts",
80 "RXO_nop",
81 "RXO_nop2",
82 "RXO_nop3",
83
84 "RXO_scmpu",
85 "RXO_smovu",
86 "RXO_smovb",
87 "RXO_suntil",
88 "RXO_swhile",
89 "RXO_smovf",
90 "RXO_sstr",
91
92 "RXO_rmpa",
93 "RXO_mulhi",
94 "RXO_mullo",
95 "RXO_machi",
96 "RXO_maclo",
97 "RXO_mvtachi",
98 "RXO_mvtaclo",
99 "RXO_mvfachi",
100 "RXO_mvfacmi",
101 "RXO_mvfaclo",
102 "RXO_racw",
103
104 "RXO_sat", /* sat(d) */
105 "RXO_satr",
106
107 "RXO_fadd", /* d op= s */
108 "RXO_fcmp",
109 "RXO_fsub",
110 "RXO_ftoi",
111 "RXO_fmul",
112 "RXO_fdiv",
113 "RXO_round",
114 "RXO_itof",
115
116 "RXO_bset", /* d |= (1<<s) */
117 "RXO_bclr", /* d &= ~(1<<s) */
118 "RXO_btst", /* s & (1<<s2) */
119 "RXO_bnot", /* d ^= (1<<s) */
120 "RXO_bmcc", /* d<s> = cond(s2) */
121
122 "RXO_clrpsw", /* flag index in d */
123 "RXO_setpsw", /* flag index in d */
124 "RXO_mvtipl", /* new IPL in s */
125
126 "RXO_rtfi",
127 "RXO_rte",
128 "RXO_rtd", /* undocumented */
129 "RXO_brk",
130 "RXO_dbt", /* undocumented */
131 "RXO_int", /* vector id in s */
132 "RXO_stop",
133 "RXO_wait",
134
135 "RXO_sccnd", /* d = cond(s) ? 1 : 0 */
136 };
137
138 static const char * optype_names[] = {
139 " ",
140 "#Imm", /* #addend */
141 " Rn ", /* Rn */
142 "[Rn]", /* [Rn + addend] */
143 "Ps++", /* [Rn+] */
144 "--Pr", /* [-Rn] */
145 " cc ", /* eq, gtu, etc */
146 "Flag", /* [UIOSZC] */
147 "RbRi" /* [Rb + scale * Ri] */
148 };
149
150 #define N_RXO (sizeof(id_names)/sizeof(id_names[0]))
151 #define N_RXT (sizeof(optype_names)/sizeof(optype_names[0]))
152 #define N_MAP 30
153
154 static unsigned long long benchmark_start_cycle;
155 static unsigned long long benchmark_end_cycle;
156
157 static int op_cache[N_RXT][N_RXT][N_RXT];
158 static int op_cache_rev[N_MAP];
159 static int op_cache_idx = 0;
160
161 static int
162 op_lookup (int a, int b, int c)
163 {
164 if (op_cache[a][b][c])
165 return op_cache[a][b][c];
166 op_cache_idx ++;
167 if (op_cache_idx >= N_MAP)
168 {
169 printf("op_cache_idx exceeds %d\n", N_MAP);
170 exit(1);
171 }
172 op_cache[a][b][c] = op_cache_idx;
173 op_cache_rev[op_cache_idx] = (a<<8) | (b<<4) | c;
174 return op_cache_idx;
175 }
176
177 static char *
178 op_cache_string (int map)
179 {
180 static int ci;
181 static char cb[5][20];
182 int a, b, c;
183
184 map = op_cache_rev[map];
185 a = (map >> 8) & 15;
186 b = (map >> 4) & 15;
187 c = (map >> 0) & 15;
188 ci = (ci + 1) % 5;
189 sprintf(cb[ci], "%s %s %s", optype_names[a], optype_names[b], optype_names[c]);
190 return cb[ci];
191 }
192
193 static unsigned long long cycles_per_id[N_RXO][N_MAP];
194 static unsigned long long times_per_id[N_RXO][N_MAP];
195 static unsigned long long memory_stalls;
196 static unsigned long long register_stalls;
197 static unsigned long long branch_stalls;
198 static unsigned long long branch_alignment_stalls;
199 static unsigned long long fast_returns;
200
201 static unsigned long times_per_pair[N_RXO][N_MAP][N_RXO][N_MAP];
202 static int prev_opcode_id = RXO_unknown;
203 static int po0;
204
205 #define STATS(x) x
206
207 #else
208 #define STATS(x)
209 #endif /* CYCLE_STATS */
210
211
212 #ifdef CYCLE_ACCURATE
213
214 static int new_rt = -1;
215
216 /* Number of cycles to add if an insn spans an 8-byte boundary. */
217 static int branch_alignment_penalty = 0;
218
219 #endif
220
221 static int running_benchmark = 1;
222
223 #define tprintf if (trace && running_benchmark) printf
224
225 jmp_buf decode_jmp_buf;
226 unsigned int rx_cycles = 0;
227
228 #ifdef CYCLE_ACCURATE
229 /* If nonzero, memory was read at some point and cycle latency might
230 take effect. */
231 static int memory_source = 0;
232 /* If nonzero, memory was written and extra cycles might be
233 needed. */
234 static int memory_dest = 0;
235
236 static void
237 cycles (int throughput)
238 {
239 tprintf("%d cycles\n", throughput);
240 regs.cycle_count += throughput;
241 }
242
243 /* Number of execution (E) cycles the op uses. For memory sources, we
244 include the load micro-op stall as two extra E cycles. */
245 #define E(c) cycles (memory_source ? c + 2 : c)
246 #define E1 cycles (1)
247 #define E2 cycles (2)
248 #define EBIT cycles (memory_source ? 2 : 1)
249
250 /* Check to see if a read latency must be applied for a given register. */
251 #define RL(r) \
252 if (regs.rt == r ) \
253 { \
254 tprintf("register %d load stall\n", r); \
255 regs.cycle_count ++; \
256 STATS(register_stalls ++); \
257 regs.rt = -1; \
258 }
259
260 #define RLD(r) \
261 if (memory_source) \
262 { \
263 tprintf ("Rt now %d\n", r); \
264 new_rt = r; \
265 }
266
267 #else /* !CYCLE_ACCURATE */
268
269 #define cycles(t)
270 #define E(c)
271 #define E1
272 #define E2
273 #define EBIT
274 #define RL(r)
275 #define RLD(r)
276
277 #endif /* else CYCLE_ACCURATE */
278
279 static int size2bytes[] = {
280 4, 1, 1, 1, 2, 2, 2, 3, 4
281 };
282
283 typedef struct {
284 unsigned long dpc;
285 } RX_Data;
286
287 #define rx_abort() _rx_abort(__FILE__, __LINE__)
288 static void
289 _rx_abort (const char *file, int line)
290 {
291 if (strrchr (file, '/'))
292 file = strrchr (file, '/') + 1;
293 fprintf(stderr, "abort at %s:%d\n", file, line);
294 abort();
295 }
296
297 static unsigned char *get_byte_base;
298 static RX_Opcode_Decoded **decode_cache_base;
299 static SI get_byte_page;
300
301 void
302 reset_decoder (void)
303 {
304 get_byte_base = 0;
305 decode_cache_base = 0;
306 get_byte_page = 0;
307 }
308
309 static inline void
310 maybe_get_mem_page (SI tpc)
311 {
312 if (((tpc ^ get_byte_page) & NONPAGE_MASK) || enable_counting)
313 {
314 get_byte_page = tpc & NONPAGE_MASK;
315 get_byte_base = rx_mem_ptr (get_byte_page, MPA_READING) - get_byte_page;
316 decode_cache_base = rx_mem_decode_cache (get_byte_page) - get_byte_page;
317 }
318 }
319
320 /* This gets called a *lot* so optimize it. */
321 static int
322 rx_get_byte (void *vdata)
323 {
324 RX_Data *rx_data = (RX_Data *)vdata;
325 SI tpc = rx_data->dpc;
326
327 /* See load.c for an explanation of this. */
328 if (rx_big_endian)
329 tpc ^= 3;
330
331 maybe_get_mem_page (tpc);
332
333 rx_data->dpc ++;
334 return get_byte_base [tpc];
335 }
336
337 static int
338 get_op (const RX_Opcode_Decoded *rd, int i)
339 {
340 const RX_Opcode_Operand *o = rd->op + i;
341 int addr, rv = 0;
342
343 switch (o->type)
344 {
345 case RX_Operand_None:
346 rx_abort ();
347
348 case RX_Operand_Immediate: /* #addend */
349 return o->addend;
350
351 case RX_Operand_Register: /* Rn */
352 RL (o->reg);
353 rv = get_reg (o->reg);
354 break;
355
356 case RX_Operand_Predec: /* [-Rn] */
357 put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
358 /* fall through */
359 case RX_Operand_Postinc: /* [Rn+] */
360 case RX_Operand_Indirect: /* [Rn + addend] */
361 case RX_Operand_TwoReg: /* [Rn + scale * R2] */
362 #ifdef CYCLE_ACCURATE
363 RL (o->reg);
364 if (o->type == RX_Operand_TwoReg)
365 RL (rd->op[2].reg);
366 regs.rt = -1;
367 if (regs.m2m == M2M_BOTH)
368 {
369 tprintf("src memory stall\n");
370 #ifdef CYCLE_STATS
371 memory_stalls ++;
372 #endif
373 regs.cycle_count ++;
374 regs.m2m = 0;
375 }
376
377 memory_source = 1;
378 #endif
379
380 if (o->type == RX_Operand_TwoReg)
381 addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
382 else
383 addr = get_reg (o->reg) + o->addend;
384
385 switch (o->size)
386 {
387 case RX_AnySize:
388 rx_abort ();
389
390 case RX_Byte: /* undefined extension */
391 case RX_UByte:
392 case RX_SByte:
393 rv = mem_get_qi (addr);
394 break;
395
396 case RX_Word: /* undefined extension */
397 case RX_UWord:
398 case RX_SWord:
399 rv = mem_get_hi (addr);
400 break;
401
402 case RX_3Byte:
403 rv = mem_get_psi (addr);
404 break;
405
406 case RX_Long:
407 rv = mem_get_si (addr);
408 break;
409 }
410
411 if (o->type == RX_Operand_Postinc)
412 put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
413
414 break;
415
416 case RX_Operand_Condition: /* eq, gtu, etc */
417 return condition_true (o->reg);
418
419 case RX_Operand_Flag: /* [UIOSZC] */
420 return (regs.r_psw & (1 << o->reg)) ? 1 : 0;
421 }
422
423 /* if we've gotten here, we need to clip/extend the value according
424 to the size. */
425 switch (o->size)
426 {
427 case RX_AnySize:
428 rx_abort ();
429
430 case RX_Byte: /* undefined extension */
431 rv |= 0xdeadbe00; /* keep them honest */
432 break;
433
434 case RX_UByte:
435 rv &= 0xff;
436 break;
437
438 case RX_SByte:
439 rv = sign_ext (rv, 8);
440 break;
441
442 case RX_Word: /* undefined extension */
443 rv |= 0xdead0000; /* keep them honest */
444 break;
445
446 case RX_UWord:
447 rv &= 0xffff;
448 break;
449
450 case RX_SWord:
451 rv = sign_ext (rv, 16);
452 break;
453
454 case RX_3Byte:
455 rv &= 0xffffff;
456 break;
457
458 case RX_Long:
459 break;
460 }
461 return rv;
462 }
463
464 static void
465 put_op (const RX_Opcode_Decoded *rd, int i, int v)
466 {
467 const RX_Opcode_Operand *o = rd->op + i;
468 int addr;
469
470 switch (o->size)
471 {
472 case RX_AnySize:
473 if (o->type != RX_Operand_Register)
474 rx_abort ();
475 break;
476
477 case RX_Byte: /* undefined extension */
478 v |= 0xdeadbe00; /* keep them honest */
479 break;
480
481 case RX_UByte:
482 v &= 0xff;
483 break;
484
485 case RX_SByte:
486 v = sign_ext (v, 8);
487 break;
488
489 case RX_Word: /* undefined extension */
490 v |= 0xdead0000; /* keep them honest */
491 break;
492
493 case RX_UWord:
494 v &= 0xffff;
495 break;
496
497 case RX_SWord:
498 v = sign_ext (v, 16);
499 break;
500
501 case RX_3Byte:
502 v &= 0xffffff;
503 break;
504
505 case RX_Long:
506 break;
507 }
508
509 switch (o->type)
510 {
511 case RX_Operand_None:
512 /* Opcodes like TST and CMP use this. */
513 break;
514
515 case RX_Operand_Immediate: /* #addend */
516 case RX_Operand_Condition: /* eq, gtu, etc */
517 rx_abort ();
518
519 case RX_Operand_Register: /* Rn */
520 put_reg (o->reg, v);
521 RLD (o->reg);
522 break;
523
524 case RX_Operand_Predec: /* [-Rn] */
525 put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
526 /* fall through */
527 case RX_Operand_Postinc: /* [Rn+] */
528 case RX_Operand_Indirect: /* [Rn + addend] */
529 case RX_Operand_TwoReg: /* [Rn + scale * R2] */
530
531 #ifdef CYCLE_ACCURATE
532 if (regs.m2m == M2M_BOTH)
533 {
534 tprintf("dst memory stall\n");
535 regs.cycle_count ++;
536 #ifdef CYCLE_STATS
537 memory_stalls ++;
538 #endif
539 regs.m2m = 0;
540 }
541 memory_dest = 1;
542 #endif
543
544 if (o->type == RX_Operand_TwoReg)
545 addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
546 else
547 addr = get_reg (o->reg) + o->addend;
548
549 switch (o->size)
550 {
551 case RX_AnySize:
552 rx_abort ();
553
554 case RX_Byte: /* undefined extension */
555 case RX_UByte:
556 case RX_SByte:
557 mem_put_qi (addr, v);
558 break;
559
560 case RX_Word: /* undefined extension */
561 case RX_UWord:
562 case RX_SWord:
563 mem_put_hi (addr, v);
564 break;
565
566 case RX_3Byte:
567 mem_put_psi (addr, v);
568 break;
569
570 case RX_Long:
571 mem_put_si (addr, v);
572 break;
573 }
574
575 if (o->type == RX_Operand_Postinc)
576 put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
577
578 break;
579
580 case RX_Operand_Flag: /* [UIOSZC] */
581 if (v)
582 regs.r_psw |= (1 << o->reg);
583 else
584 regs.r_psw &= ~(1 << o->reg);
585 break;
586 }
587 }
588
589 #define PD(x) put_op (opcode, 0, x)
590 #define PS(x) put_op (opcode, 1, x)
591 #define PS2(x) put_op (opcode, 2, x)
592 #define GD() get_op (opcode, 0)
593 #define GS() get_op (opcode, 1)
594 #define GS2() get_op (opcode, 2)
595 #define DSZ() size2bytes[opcode->op[0].size]
596 #define SSZ() size2bytes[opcode->op[0].size]
597 #define S2SZ() size2bytes[opcode->op[0].size]
598
599 /* "Universal" sources. */
600 #define US1() ((opcode->op[2].type == RX_Operand_None) ? GD() : GS())
601 #define US2() ((opcode->op[2].type == RX_Operand_None) ? GS() : GS2())
602
603 static void
604 push(int val)
605 {
606 int rsp = get_reg (sp);
607 rsp -= 4;
608 put_reg (sp, rsp);
609 mem_put_si (rsp, val);
610 }
611
612 /* Just like the above, but tag the memory as "pushed pc" so if anyone
613 tries to write to it, it will cause an error. */
614 static void
615 pushpc(int val)
616 {
617 int rsp = get_reg (sp);
618 rsp -= 4;
619 put_reg (sp, rsp);
620 mem_put_si (rsp, val);
621 mem_set_content_range (rsp, rsp+3, MC_PUSHED_PC);
622 }
623
624 static int
625 pop()
626 {
627 int rv;
628 int rsp = get_reg (sp);
629 rv = mem_get_si (rsp);
630 rsp += 4;
631 put_reg (sp, rsp);
632 return rv;
633 }
634
635 static int
636 poppc()
637 {
638 int rv;
639 int rsp = get_reg (sp);
640 if (mem_get_content_type (rsp) != MC_PUSHED_PC)
641 execution_error (SIM_ERR_CORRUPT_STACK, rsp);
642 rv = mem_get_si (rsp);
643 mem_set_content_range (rsp, rsp+3, MC_UNINIT);
644 rsp += 4;
645 put_reg (sp, rsp);
646 return rv;
647 }
648
649 #define MATH_OP(vop,c) \
650 { \
651 umb = US2(); \
652 uma = US1(); \
653 ll = (unsigned long long) uma vop (unsigned long long) umb vop c; \
654 tprintf ("0x%x " #vop " 0x%x " #vop " 0x%x = 0x%llx\n", uma, umb, c, ll); \
655 ma = sign_ext (uma, DSZ() * 8); \
656 mb = sign_ext (umb, DSZ() * 8); \
657 sll = (long long) ma vop (long long) mb vop c; \
658 tprintf ("%d " #vop " %d " #vop " %d = %lld\n", ma, mb, c, sll); \
659 set_oszc (sll, DSZ(), (long long) ll > ((1 vop 1) ? (long long) b2mask[DSZ()] : (long long) -1)); \
660 PD (sll); \
661 E (1); \
662 }
663
664 #define LOGIC_OP(vop) \
665 { \
666 mb = US2(); \
667 ma = US1(); \
668 v = ma vop mb; \
669 tprintf("0x%x " #vop " 0x%x = 0x%x\n", ma, mb, v); \
670 set_sz (v, DSZ()); \
671 PD(v); \
672 E (1); \
673 }
674
675 #define SHIFT_OP(val, type, count, OP, carry_mask) \
676 { \
677 int i, c=0; \
678 count = US2(); \
679 val = (type)US1(); \
680 tprintf("%lld " #OP " %d\n", val, count); \
681 for (i = 0; i < count; i ++) \
682 { \
683 c = val & carry_mask; \
684 val OP 1; \
685 } \
686 if (count) \
687 set_oszc (val, 4, c); \
688 PD (val); \
689 }
690
691 typedef union {
692 int i;
693 float f;
694 } FloatInt;
695
696 static inline int
697 float2int (float f)
698 {
699 FloatInt fi;
700 fi.f = f;
701 return fi.i;
702 }
703
704 static inline float
705 int2float (int i)
706 {
707 FloatInt fi;
708 fi.i = i;
709 return fi.f;
710 }
711
712 static int
713 fop_fadd (fp_t s1, fp_t s2, fp_t *d)
714 {
715 *d = rxfp_add (s1, s2);
716 return 1;
717 }
718
719 static int
720 fop_fmul (fp_t s1, fp_t s2, fp_t *d)
721 {
722 *d = rxfp_mul (s1, s2);
723 return 1;
724 }
725
726 static int
727 fop_fdiv (fp_t s1, fp_t s2, fp_t *d)
728 {
729 *d = rxfp_div (s1, s2);
730 return 1;
731 }
732
733 static int
734 fop_fsub (fp_t s1, fp_t s2, fp_t *d)
735 {
736 *d = rxfp_sub (s1, s2);
737 return 1;
738 }
739
740 #define FPPENDING() (regs.r_fpsw & (FPSWBITS_CE | (FPSWBITS_FMASK & (regs.r_fpsw << FPSW_EFSH))))
741 #define FPCLEAR() regs.r_fpsw &= FPSWBITS_CLEAR
742 #define FPCHECK() \
743 if (FPPENDING()) \
744 return do_fp_exception (opcode_pc)
745
746 #define FLOAT_OP(func) \
747 { \
748 int do_store; \
749 fp_t fa, fb, fc; \
750 FPCLEAR(); \
751 fb = GS (); \
752 fa = GD (); \
753 do_store = fop_##func (fa, fb, &fc); \
754 tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
755 FPCHECK(); \
756 if (do_store) \
757 PD (fc); \
758 mb = 0; \
759 if ((fc & 0x80000000UL) != 0) \
760 mb |= FLAGBIT_S; \
761 if ((fc & 0x7fffffffUL) == 0) \
762 mb |= FLAGBIT_Z; \
763 set_flags (FLAGBIT_S | FLAGBIT_Z, mb); \
764 }
765
766 #define carry (FLAG_C ? 1 : 0)
767
768 static struct {
769 unsigned long vaddr;
770 const char *str;
771 int signal;
772 } exception_info[] = {
773 { 0xFFFFFFD0UL, "priviledged opcode", SIGILL },
774 { 0xFFFFFFD4UL, "access violation", SIGSEGV },
775 { 0xFFFFFFDCUL, "undefined opcode", SIGILL },
776 { 0xFFFFFFE4UL, "floating point", SIGFPE }
777 };
778 #define EX_PRIVILEDGED 0
779 #define EX_ACCESS 1
780 #define EX_UNDEFINED 2
781 #define EX_FLOATING 3
782 #define EXCEPTION(n) \
783 return generate_exception (n, opcode_pc)
784
785 #define PRIVILEDGED() \
786 if (FLAG_PM) \
787 EXCEPTION (EX_PRIVILEDGED)
788
789 static int
790 generate_exception (unsigned long type, SI opcode_pc)
791 {
792 SI old_psw, old_pc, new_pc;
793
794 new_pc = mem_get_si (exception_info[type].vaddr);
795 /* 0x00020000 is the value used to initialise the known
796 exception vectors (see rx.ld), but it is a reserved
797 area of memory so do not try to access it, and if the
798 value has not been changed by the program then the
799 vector has not been installed. */
800 if (new_pc == 0 || new_pc == 0x00020000)
801 {
802 if (rx_in_gdb)
803 return RX_MAKE_STOPPED (exception_info[type].signal);
804
805 fprintf(stderr, "Unhandled %s exception at pc = %#lx\n",
806 exception_info[type].str, (unsigned long) opcode_pc);
807 if (type == EX_FLOATING)
808 {
809 int mask = FPPENDING ();
810 fprintf (stderr, "Pending FP exceptions:");
811 if (mask & FPSWBITS_FV)
812 fprintf(stderr, " Invalid");
813 if (mask & FPSWBITS_FO)
814 fprintf(stderr, " Overflow");
815 if (mask & FPSWBITS_FZ)
816 fprintf(stderr, " Division-by-zero");
817 if (mask & FPSWBITS_FU)
818 fprintf(stderr, " Underflow");
819 if (mask & FPSWBITS_FX)
820 fprintf(stderr, " Inexact");
821 if (mask & FPSWBITS_CE)
822 fprintf(stderr, " Unimplemented");
823 fprintf(stderr, "\n");
824 }
825 return RX_MAKE_EXITED (1);
826 }
827
828 tprintf ("Triggering %s exception\n", exception_info[type].str);
829
830 old_psw = regs.r_psw;
831 regs.r_psw &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
832 old_pc = opcode_pc;
833 regs.r_pc = new_pc;
834 pushpc (old_psw);
835 pushpc (old_pc);
836 return RX_MAKE_STEPPED ();
837 }
838
839 void
840 generate_access_exception (void)
841 {
842 int rv;
843
844 rv = generate_exception (EX_ACCESS, regs.r_pc);
845 if (RX_EXITED (rv))
846 longjmp (decode_jmp_buf, rv);
847 }
848
849 static int
850 do_fp_exception (unsigned long opcode_pc)
851 {
852 while (FPPENDING())
853 EXCEPTION (EX_FLOATING);
854 return RX_MAKE_STEPPED ();
855 }
856
857 static int
858 op_is_memory (const RX_Opcode_Decoded *rd, int i)
859 {
860 switch (rd->op[i].type)
861 {
862 case RX_Operand_Predec:
863 case RX_Operand_Postinc:
864 case RX_Operand_Indirect:
865 return 1;
866 default:
867 return 0;
868 }
869 }
870 #define OM(i) op_is_memory (opcode, i)
871
872 #define DO_RETURN(x) { longjmp (decode_jmp_buf, x); }
873
874 int
875 decode_opcode ()
876 {
877 unsigned int uma=0, umb=0;
878 int ma=0, mb=0;
879 int opcode_size, v;
880 unsigned long long ll;
881 long long sll;
882 unsigned long opcode_pc;
883 RX_Data rx_data;
884 const RX_Opcode_Decoded *opcode;
885 #ifdef CYCLE_STATS
886 unsigned long long prev_cycle_count;
887 #endif
888 #ifdef CYCLE_ACCURATE
889 unsigned int tx;
890 #endif
891
892 #ifdef CYCLE_STATS
893 prev_cycle_count = regs.cycle_count;
894 #endif
895
896 #ifdef CYCLE_ACCURATE
897 memory_source = 0;
898 memory_dest = 0;
899 #endif
900
901 rx_cycles ++;
902
903 maybe_get_mem_page (regs.r_pc);
904
905 opcode_pc = regs.r_pc;
906
907 /* Note that we don't word-swap this point, there's no point. */
908 if (decode_cache_base[opcode_pc] == NULL)
909 {
910 RX_Opcode_Decoded *opcode_w;
911 rx_data.dpc = opcode_pc;
912 opcode_w = decode_cache_base[opcode_pc] = calloc (1, sizeof (RX_Opcode_Decoded));
913 opcode_size = rx_decode_opcode (opcode_pc, opcode_w,
914 rx_get_byte, &rx_data);
915 opcode = opcode_w;
916 }
917 else
918 {
919 opcode = decode_cache_base[opcode_pc];
920 opcode_size = opcode->n_bytes;
921 }
922
923 #ifdef CYCLE_ACCURATE
924 if (branch_alignment_penalty)
925 {
926 if ((regs.r_pc ^ (regs.r_pc + opcode_size - 1)) & ~7)
927 {
928 tprintf("1 cycle branch alignment penalty\n");
929 cycles (branch_alignment_penalty);
930 #ifdef CYCLE_STATS
931 branch_alignment_stalls ++;
932 #endif
933 }
934 branch_alignment_penalty = 0;
935 }
936 #endif
937
938 regs.r_pc += opcode_size;
939
940 rx_flagmask = opcode->flags_s;
941 rx_flagand = ~(int)opcode->flags_0;
942 rx_flagor = opcode->flags_1;
943
944 switch (opcode->id)
945 {
946 case RXO_abs:
947 sll = GS ();
948 tprintf("|%lld| = ", sll);
949 if (sll < 0)
950 sll = -sll;
951 tprintf("%lld\n", sll);
952 PD (sll);
953 set_osz (sll, 4);
954 E (1);
955 break;
956
957 case RXO_adc:
958 MATH_OP (+,carry);
959 break;
960
961 case RXO_add:
962 MATH_OP (+,0);
963 break;
964
965 case RXO_and:
966 LOGIC_OP (&);
967 break;
968
969 case RXO_bclr:
970 ma = GD ();
971 mb = GS ();
972 if (opcode->op[0].type == RX_Operand_Register)
973 mb &= 0x1f;
974 else
975 mb &= 0x07;
976 ma &= ~(1 << mb);
977 PD (ma);
978 EBIT;
979 break;
980
981 case RXO_bmcc:
982 ma = GD ();
983 mb = GS ();
984 if (opcode->op[0].type == RX_Operand_Register)
985 mb &= 0x1f;
986 else
987 mb &= 0x07;
988 if (GS2 ())
989 ma |= (1 << mb);
990 else
991 ma &= ~(1 << mb);
992 PD (ma);
993 EBIT;
994 break;
995
996 case RXO_bnot:
997 ma = GD ();
998 mb = GS ();
999 if (opcode->op[0].type == RX_Operand_Register)
1000 mb &= 0x1f;
1001 else
1002 mb &= 0x07;
1003 ma ^= (1 << mb);
1004 PD (ma);
1005 EBIT;
1006 break;
1007
1008 case RXO_branch:
1009 if (opcode->op[1].type == RX_Operand_None || GS())
1010 {
1011 #ifdef CYCLE_ACCURATE
1012 SI old_pc = regs.r_pc;
1013 int delta;
1014 #endif
1015 regs.r_pc = GD();
1016 #ifdef CYCLE_ACCURATE
1017 delta = regs.r_pc - old_pc;
1018 if (delta >= 0 && delta < 16
1019 && opcode_size > 1)
1020 {
1021 tprintf("near forward branch bonus\n");
1022 cycles (2);
1023 }
1024 else
1025 {
1026 cycles (3);
1027 branch_alignment_penalty = 1;
1028 }
1029 #ifdef CYCLE_STATS
1030 branch_stalls ++;
1031 #endif
1032 #endif
1033 }
1034 #ifdef CYCLE_ACCURATE
1035 else
1036 cycles (1);
1037 #endif
1038 break;
1039
1040 case RXO_branchrel:
1041 if (GS())
1042 {
1043 int delta = GD();
1044 regs.r_pc += delta;
1045 #ifdef CYCLE_ACCURATE
1046 /* Note: specs say 3, chip says 2. */
1047 if (delta >= 0 && delta < 16
1048 && opcode_size > 1)
1049 {
1050 tprintf("near forward branch bonus\n");
1051 cycles (2);
1052 }
1053 else
1054 {
1055 cycles (3);
1056 branch_alignment_penalty = 1;
1057 }
1058 #ifdef CYCLE_STATS
1059 branch_stalls ++;
1060 #endif
1061 #endif
1062 }
1063 #ifdef CYCLE_ACCURATE
1064 else
1065 cycles (1);
1066 #endif
1067 break;
1068
1069 case RXO_brk:
1070 {
1071 int old_psw = regs.r_psw;
1072 if (rx_in_gdb)
1073 DO_RETURN (RX_MAKE_HIT_BREAK ());
1074 if (regs.r_intb == 0)
1075 {
1076 tprintf("BREAK hit, no vector table.\n");
1077 DO_RETURN (RX_MAKE_EXITED(1));
1078 }
1079 regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
1080 pushpc (old_psw);
1081 pushpc (regs.r_pc);
1082 regs.r_pc = mem_get_si (regs.r_intb);
1083 cycles(6);
1084 }
1085 break;
1086
1087 case RXO_bset:
1088 ma = GD ();
1089 mb = GS ();
1090 if (opcode->op[0].type == RX_Operand_Register)
1091 mb &= 0x1f;
1092 else
1093 mb &= 0x07;
1094 ma |= (1 << mb);
1095 PD (ma);
1096 EBIT;
1097 break;
1098
1099 case RXO_btst:
1100 ma = GS ();
1101 mb = GS2 ();
1102 if (opcode->op[1].type == RX_Operand_Register)
1103 mb &= 0x1f;
1104 else
1105 mb &= 0x07;
1106 umb = ma & (1 << mb);
1107 set_zc (! umb, umb);
1108 EBIT;
1109 break;
1110
1111 case RXO_clrpsw:
1112 v = 1 << opcode->op[0].reg;
1113 if (FLAG_PM
1114 && (v == FLAGBIT_I
1115 || v == FLAGBIT_U))
1116 break;
1117 regs.r_psw &= ~v;
1118 cycles (1);
1119 break;
1120
1121 case RXO_div: /* d = d / s */
1122 ma = GS();
1123 mb = GD();
1124 tprintf("%d / %d = ", mb, ma);
1125 if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
1126 {
1127 tprintf("#NAN\n");
1128 set_flags (FLAGBIT_O, FLAGBIT_O);
1129 }
1130 else
1131 {
1132 v = mb/ma;
1133 tprintf("%d\n", v);
1134 set_flags (FLAGBIT_O, 0);
1135 PD (v);
1136 }
1137 /* Note: spec says 3 to 22 cycles, we are pessimistic. */
1138 cycles (22);
1139 break;
1140
1141 case RXO_divu: /* d = d / s */
1142 uma = GS();
1143 umb = GD();
1144 tprintf("%u / %u = ", umb, uma);
1145 if (uma == 0)
1146 {
1147 tprintf("#NAN\n");
1148 set_flags (FLAGBIT_O, FLAGBIT_O);
1149 }
1150 else
1151 {
1152 v = umb / uma;
1153 tprintf("%u\n", v);
1154 set_flags (FLAGBIT_O, 0);
1155 PD (v);
1156 }
1157 /* Note: spec says 2 to 20 cycles, we are pessimistic. */
1158 cycles (20);
1159 break;
1160
1161 case RXO_emul:
1162 ma = GD ();
1163 mb = GS ();
1164 sll = (long long)ma * (long long)mb;
1165 tprintf("%d * %d = %lld\n", ma, mb, sll);
1166 put_reg (opcode->op[0].reg, sll);
1167 put_reg (opcode->op[0].reg + 1, sll >> 32);
1168 E2;
1169 break;
1170
1171 case RXO_emulu:
1172 uma = GD ();
1173 umb = GS ();
1174 ll = (long long)uma * (long long)umb;
1175 tprintf("%#x * %#x = %#llx\n", uma, umb, ll);
1176 put_reg (opcode->op[0].reg, ll);
1177 put_reg (opcode->op[0].reg + 1, ll >> 32);
1178 E2;
1179 break;
1180
1181 case RXO_fadd:
1182 FLOAT_OP (fadd);
1183 E (4);
1184 break;
1185
1186 case RXO_fcmp:
1187 ma = GD();
1188 mb = GS();
1189 FPCLEAR ();
1190 rxfp_cmp (ma, mb);
1191 FPCHECK ();
1192 E (1);
1193 break;
1194
1195 case RXO_fdiv:
1196 FLOAT_OP (fdiv);
1197 E (16);
1198 break;
1199
1200 case RXO_fmul:
1201 FLOAT_OP (fmul);
1202 E (3);
1203 break;
1204
1205 case RXO_rtfi:
1206 PRIVILEDGED ();
1207 regs.r_psw = regs.r_bpsw;
1208 regs.r_pc = regs.r_bpc;
1209 #ifdef CYCLE_ACCURATE
1210 regs.fast_return = 0;
1211 cycles(3);
1212 #endif
1213 break;
1214
1215 case RXO_fsub:
1216 FLOAT_OP (fsub);
1217 E (4);
1218 break;
1219
1220 case RXO_ftoi:
1221 ma = GS ();
1222 FPCLEAR ();
1223 mb = rxfp_ftoi (ma, FPRM_ZERO);
1224 FPCHECK ();
1225 PD (mb);
1226 tprintf("(int) %g = %d\n", int2float(ma), mb);
1227 set_sz (mb, 4);
1228 E (2);
1229 break;
1230
1231 case RXO_int:
1232 v = GS ();
1233 if (v == 255)
1234 {
1235 DO_RETURN (rx_syscall (regs.r[5]));
1236 }
1237 else
1238 {
1239 int old_psw = regs.r_psw;
1240 regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
1241 pushpc (old_psw);
1242 pushpc (regs.r_pc);
1243 regs.r_pc = mem_get_si (regs.r_intb + 4 * v);
1244 }
1245 cycles (6);
1246 break;
1247
1248 case RXO_itof:
1249 ma = GS ();
1250 FPCLEAR ();
1251 mb = rxfp_itof (ma, regs.r_fpsw);
1252 FPCHECK ();
1253 tprintf("(float) %d = %x\n", ma, mb);
1254 PD (mb);
1255 set_sz (ma, 4);
1256 E (2);
1257 break;
1258
1259 case RXO_jsr:
1260 case RXO_jsrrel:
1261 {
1262 #ifdef CYCLE_ACCURATE
1263 int delta;
1264 regs.m2m = 0;
1265 #endif
1266 v = GD ();
1267 #ifdef CYCLE_ACCURATE
1268 regs.link_register = regs.r_pc;
1269 #endif
1270 pushpc (get_reg (pc));
1271 if (opcode->id == RXO_jsrrel)
1272 v += regs.r_pc;
1273 #ifdef CYCLE_ACCURATE
1274 delta = v - regs.r_pc;
1275 #endif
1276 put_reg (pc, v);
1277 #ifdef CYCLE_ACCURATE
1278 /* Note: docs say 3, chip says 2 */
1279 if (delta >= 0 && delta < 16)
1280 {
1281 tprintf ("near forward jsr bonus\n");
1282 cycles (2);
1283 }
1284 else
1285 {
1286 branch_alignment_penalty = 1;
1287 cycles (3);
1288 }
1289 regs.fast_return = 1;
1290 #endif
1291 }
1292 break;
1293
1294 case RXO_machi:
1295 ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
1296 ll <<= 16;
1297 put_reg64 (acc64, ll + regs.r_acc);
1298 E1;
1299 break;
1300
1301 case RXO_maclo:
1302 ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
1303 ll <<= 16;
1304 put_reg64 (acc64, ll + regs.r_acc);
1305 E1;
1306 break;
1307
1308 case RXO_max:
1309 mb = GS();
1310 ma = GD();
1311 if (ma > mb)
1312 PD (ma);
1313 else
1314 PD (mb);
1315 E (1);
1316 break;
1317
1318 case RXO_min:
1319 mb = GS();
1320 ma = GD();
1321 if (ma < mb)
1322 PD (ma);
1323 else
1324 PD (mb);
1325 E (1);
1326 break;
1327
1328 case RXO_mov:
1329 v = GS ();
1330
1331 if (opcode->op[0].type == RX_Operand_Register
1332 && opcode->op[0].reg == 16 /* PSW */)
1333 {
1334 /* Special case, LDC and POPC can't ever modify PM. */
1335 int pm = regs.r_psw & FLAGBIT_PM;
1336 v &= ~ FLAGBIT_PM;
1337 v |= pm;
1338 if (pm)
1339 {
1340 v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
1341 v |= pm;
1342 }
1343 }
1344 if (FLAG_PM)
1345 {
1346 /* various things can't be changed in user mode. */
1347 if (opcode->op[0].type == RX_Operand_Register)
1348 if (opcode->op[0].reg == 32)
1349 {
1350 v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
1351 v |= regs.r_psw & (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
1352 }
1353 if (opcode->op[0].reg == 34 /* ISP */
1354 || opcode->op[0].reg == 37 /* BPSW */
1355 || opcode->op[0].reg == 39 /* INTB */
1356 || opcode->op[0].reg == 38 /* VCT */)
1357 /* These are ignored. */
1358 break;
1359 }
1360 if (OM(0) && OM(1))
1361 cycles (2);
1362 else
1363 cycles (1);
1364
1365 PD (v);
1366
1367 #ifdef CYCLE_ACCURATE
1368 if ((opcode->op[0].type == RX_Operand_Predec
1369 && opcode->op[1].type == RX_Operand_Register)
1370 || (opcode->op[0].type == RX_Operand_Postinc
1371 && opcode->op[1].type == RX_Operand_Register))
1372 {
1373 /* Special case: push reg doesn't cause a memory stall. */
1374 memory_dest = 0;
1375 tprintf("push special case\n");
1376 }
1377 #endif
1378
1379 set_sz (v, DSZ());
1380 break;
1381
1382 case RXO_movbi:
1383 PD (GS ());
1384 cycles (1);
1385 break;
1386
1387 case RXO_movbir:
1388 PS (GD ());
1389 cycles (1);
1390 break;
1391
1392 case RXO_mul:
1393 v = US2 ();
1394 ll = (unsigned long long) US1() * (unsigned long long) v;
1395 PD(ll);
1396 E (1);
1397 break;
1398
1399 case RXO_mulhi:
1400 v = GS2 ();
1401 ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v >> 16);
1402 ll <<= 16;
1403 put_reg64 (acc64, ll);
1404 E1;
1405 break;
1406
1407 case RXO_mullo:
1408 v = GS2 ();
1409 ll = (long long)(signed short)(GS()) * (long long)(signed short)(v);
1410 ll <<= 16;
1411 put_reg64 (acc64, ll);
1412 E1;
1413 break;
1414
1415 case RXO_mvfachi:
1416 PD (get_reg (acchi));
1417 E1;
1418 break;
1419
1420 case RXO_mvfaclo:
1421 PD (get_reg (acclo));
1422 E1;
1423 break;
1424
1425 case RXO_mvfacmi:
1426 PD (get_reg (accmi));
1427 E1;
1428 break;
1429
1430 case RXO_mvtachi:
1431 put_reg (acchi, GS ());
1432 E1;
1433 break;
1434
1435 case RXO_mvtaclo:
1436 put_reg (acclo, GS ());
1437 E1;
1438 break;
1439
1440 case RXO_mvtipl:
1441 regs.r_psw &= ~ FLAGBITS_IPL;
1442 regs.r_psw |= (GS () << FLAGSHIFT_IPL) & FLAGBITS_IPL;
1443 E1;
1444 break;
1445
1446 case RXO_nop:
1447 case RXO_nop2:
1448 case RXO_nop3:
1449 E1;
1450 break;
1451
1452 case RXO_or:
1453 LOGIC_OP (|);
1454 break;
1455
1456 case RXO_popm:
1457 /* POPM cannot pop R0 (sp). */
1458 if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
1459 EXCEPTION (EX_UNDEFINED);
1460 if (opcode->op[1].reg >= opcode->op[2].reg)
1461 {
1462 regs.r_pc = opcode_pc;
1463 DO_RETURN (RX_MAKE_STOPPED (SIGILL));
1464 }
1465 for (v = opcode->op[1].reg; v <= opcode->op[2].reg; v++)
1466 {
1467 cycles (1);
1468 RLD (v);
1469 put_reg (v, pop ());
1470 }
1471 break;
1472
1473 case RXO_pushm:
1474 /* PUSHM cannot push R0 (sp). */
1475 if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
1476 EXCEPTION (EX_UNDEFINED);
1477 if (opcode->op[1].reg >= opcode->op[2].reg)
1478 {
1479 regs.r_pc = opcode_pc;
1480 return RX_MAKE_STOPPED (SIGILL);
1481 }
1482 for (v = opcode->op[2].reg; v >= opcode->op[1].reg; v--)
1483 {
1484 RL (v);
1485 push (get_reg (v));
1486 }
1487 cycles (opcode->op[2].reg - opcode->op[1].reg + 1);
1488 break;
1489
1490 case RXO_racw:
1491 ll = get_reg64 (acc64) << GS ();
1492 ll += 0x80000000ULL;
1493 if ((signed long long)ll > (signed long long)0x00007fff00000000ULL)
1494 ll = 0x00007fff00000000ULL;
1495 else if ((signed long long)ll < (signed long long)0xffff800000000000ULL)
1496 ll = 0xffff800000000000ULL;
1497 else
1498 ll &= 0xffffffff00000000ULL;
1499 put_reg64 (acc64, ll);
1500 E1;
1501 break;
1502
1503 case RXO_rte:
1504 PRIVILEDGED ();
1505 regs.r_pc = poppc ();
1506 regs.r_psw = poppc ();
1507 if (FLAG_PM)
1508 regs.r_psw |= FLAGBIT_U;
1509 #ifdef CYCLE_ACCURATE
1510 regs.fast_return = 0;
1511 cycles (6);
1512 #endif
1513 break;
1514
1515 case RXO_revl:
1516 uma = GS ();
1517 umb = (((uma >> 24) & 0xff)
1518 | ((uma >> 8) & 0xff00)
1519 | ((uma << 8) & 0xff0000)
1520 | ((uma << 24) & 0xff000000UL));
1521 PD (umb);
1522 E1;
1523 break;
1524
1525 case RXO_revw:
1526 uma = GS ();
1527 umb = (((uma >> 8) & 0x00ff00ff)
1528 | ((uma << 8) & 0xff00ff00UL));
1529 PD (umb);
1530 E1;
1531 break;
1532
1533 case RXO_rmpa:
1534 RL(4);
1535 RL(5);
1536 #ifdef CYCLE_ACCURATE
1537 tx = regs.r[3];
1538 #endif
1539
1540 while (regs.r[3] != 0)
1541 {
1542 long long tmp;
1543
1544 switch (opcode->size)
1545 {
1546 case RX_Long:
1547 ma = mem_get_si (regs.r[1]);
1548 mb = mem_get_si (regs.r[2]);
1549 regs.r[1] += 4;
1550 regs.r[2] += 4;
1551 break;
1552 case RX_Word:
1553 ma = sign_ext (mem_get_hi (regs.r[1]), 16);
1554 mb = sign_ext (mem_get_hi (regs.r[2]), 16);
1555 regs.r[1] += 2;
1556 regs.r[2] += 2;
1557 break;
1558 case RX_Byte:
1559 ma = sign_ext (mem_get_qi (regs.r[1]), 8);
1560 mb = sign_ext (mem_get_qi (regs.r[2]), 8);
1561 regs.r[1] += 1;
1562 regs.r[2] += 1;
1563 break;
1564 default:
1565 abort ();
1566 }
1567 /* We do the multiply as a signed value. */
1568 sll = (long long)ma * (long long)mb;
1569 tprintf(" %016llx = %d * %d\n", sll, ma, mb);
1570 /* but we do the sum as unsigned, while sign extending the operands. */
1571 tmp = regs.r[4] + (sll & 0xffffffffUL);
1572 regs.r[4] = tmp & 0xffffffffUL;
1573 tmp >>= 32;
1574 sll >>= 32;
1575 tmp += regs.r[5] + (sll & 0xffffffffUL);
1576 regs.r[5] = tmp & 0xffffffffUL;
1577 tmp >>= 32;
1578 sll >>= 32;
1579 tmp += regs.r[6] + (sll & 0xffffffffUL);
1580 regs.r[6] = tmp & 0xffffffffUL;
1581 tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
1582 (unsigned long) regs.r[6],
1583 (unsigned long) regs.r[5],
1584 (unsigned long) regs.r[4]);
1585
1586 regs.r[3] --;
1587 }
1588 if (regs.r[6] & 0x00008000)
1589 regs.r[6] |= 0xffff0000UL;
1590 else
1591 regs.r[6] &= 0x0000ffff;
1592 ma = (regs.r[6] & 0x80000000UL) ? FLAGBIT_S : 0;
1593 if (regs.r[6] != 0 && regs.r[6] != 0xffffffffUL)
1594 set_flags (FLAGBIT_O|FLAGBIT_S, ma | FLAGBIT_O);
1595 else
1596 set_flags (FLAGBIT_O|FLAGBIT_S, ma);
1597 #ifdef CYCLE_ACCURATE
1598 switch (opcode->size)
1599 {
1600 case RX_Long:
1601 cycles (6 + 4 * tx);
1602 break;
1603 case RX_Word:
1604 cycles (6 + 5 * (tx / 2) + 4 * (tx % 2));
1605 break;
1606 case RX_Byte:
1607 cycles (6 + 7 * (tx / 4) + 4 * (tx % 4));
1608 break;
1609 default:
1610 abort ();
1611 }
1612 #endif
1613 break;
1614
1615 case RXO_rolc:
1616 v = GD ();
1617 ma = v & 0x80000000UL;
1618 v <<= 1;
1619 v |= carry;
1620 set_szc (v, 4, ma);
1621 PD (v);
1622 E1;
1623 break;
1624
1625 case RXO_rorc:
1626 uma = GD ();
1627 mb = uma & 1;
1628 uma >>= 1;
1629 uma |= (carry ? 0x80000000UL : 0);
1630 set_szc (uma, 4, mb);
1631 PD (uma);
1632 E1;
1633 break;
1634
1635 case RXO_rotl:
1636 mb = GS ();
1637 uma = GD ();
1638 if (mb)
1639 {
1640 uma = (uma << mb) | (uma >> (32-mb));
1641 mb = uma & 1;
1642 }
1643 set_szc (uma, 4, mb);
1644 PD (uma);
1645 E1;
1646 break;
1647
1648 case RXO_rotr:
1649 mb = GS ();
1650 uma = GD ();
1651 if (mb)
1652 {
1653 uma = (uma >> mb) | (uma << (32-mb));
1654 mb = uma & 0x80000000;
1655 }
1656 set_szc (uma, 4, mb);
1657 PD (uma);
1658 E1;
1659 break;
1660
1661 case RXO_round:
1662 ma = GS ();
1663 FPCLEAR ();
1664 mb = rxfp_ftoi (ma, regs.r_fpsw);
1665 FPCHECK ();
1666 PD (mb);
1667 tprintf("(int) %g = %d\n", int2float(ma), mb);
1668 set_sz (mb, 4);
1669 E (2);
1670 break;
1671
1672 case RXO_rts:
1673 {
1674 #ifdef CYCLE_ACCURATE
1675 int cyc = 5;
1676 #endif
1677 regs.r_pc = poppc ();
1678 #ifdef CYCLE_ACCURATE
1679 /* Note: specs say 5, chip says 3. */
1680 if (regs.fast_return && regs.link_register == regs.r_pc)
1681 {
1682 #ifdef CYCLE_STATS
1683 fast_returns ++;
1684 #endif
1685 tprintf("fast return bonus\n");
1686 cyc -= 2;
1687 }
1688 cycles (cyc);
1689 regs.fast_return = 0;
1690 branch_alignment_penalty = 1;
1691 #endif
1692 }
1693 break;
1694
1695 case RXO_rtsd:
1696 if (opcode->op[2].type == RX_Operand_Register)
1697 {
1698 int i;
1699 /* RTSD cannot pop R0 (sp). */
1700 put_reg (0, get_reg (0) + GS() - (opcode->op[0].reg-opcode->op[2].reg+1)*4);
1701 if (opcode->op[2].reg == 0)
1702 EXCEPTION (EX_UNDEFINED);
1703 #ifdef CYCLE_ACCURATE
1704 tx = opcode->op[0].reg - opcode->op[2].reg + 1;
1705 #endif
1706 for (i = opcode->op[2].reg; i <= opcode->op[0].reg; i ++)
1707 {
1708 RLD (i);
1709 put_reg (i, pop ());
1710 }
1711 }
1712 else
1713 {
1714 #ifdef CYCLE_ACCURATE
1715 tx = 0;
1716 #endif
1717 put_reg (0, get_reg (0) + GS());
1718 }
1719 put_reg (pc, poppc());
1720 #ifdef CYCLE_ACCURATE
1721 if (regs.fast_return && regs.link_register == regs.r_pc)
1722 {
1723 tprintf("fast return bonus\n");
1724 #ifdef CYCLE_STATS
1725 fast_returns ++;
1726 #endif
1727 cycles (tx < 3 ? 3 : tx + 1);
1728 }
1729 else
1730 {
1731 cycles (tx < 5 ? 5 : tx + 1);
1732 }
1733 regs.fast_return = 0;
1734 branch_alignment_penalty = 1;
1735 #endif
1736 break;
1737
1738 case RXO_sat:
1739 if (FLAG_O && FLAG_S)
1740 PD (0x7fffffffUL);
1741 else if (FLAG_O && ! FLAG_S)
1742 PD (0x80000000UL);
1743 E1;
1744 break;
1745
1746 case RXO_sbb:
1747 MATH_OP (-, ! carry);
1748 break;
1749
1750 case RXO_sccnd:
1751 if (GS())
1752 PD (1);
1753 else
1754 PD (0);
1755 E1;
1756 break;
1757
1758 case RXO_scmpu:
1759 #ifdef CYCLE_ACCURATE
1760 tx = regs.r[3];
1761 #endif
1762 while (regs.r[3] != 0)
1763 {
1764 uma = mem_get_qi (regs.r[1] ++);
1765 umb = mem_get_qi (regs.r[2] ++);
1766 regs.r[3] --;
1767 if (uma != umb || uma == 0)
1768 break;
1769 }
1770 if (uma == umb)
1771 set_zc (1, 1);
1772 else
1773 set_zc (0, ((int)uma - (int)umb) >= 0);
1774 cycles (2 + 4 * (tx / 4) + 4 * (tx % 4));
1775 break;
1776
1777 case RXO_setpsw:
1778 v = 1 << opcode->op[0].reg;
1779 if (FLAG_PM
1780 && (v == FLAGBIT_I
1781 || v == FLAGBIT_U))
1782 break;
1783 regs.r_psw |= v;
1784 cycles (1);
1785 break;
1786
1787 case RXO_smovb:
1788 RL (3);
1789 #ifdef CYCLE_ACCURATE
1790 tx = regs.r[3];
1791 #endif
1792 while (regs.r[3])
1793 {
1794 uma = mem_get_qi (regs.r[2] --);
1795 mem_put_qi (regs.r[1]--, uma);
1796 regs.r[3] --;
1797 }
1798 #ifdef CYCLE_ACCURATE
1799 if (tx > 3)
1800 cycles (6 + 3 * (tx / 4) + 3 * (tx % 4));
1801 else
1802 cycles (2 + 3 * (tx % 4));
1803 #endif
1804 break;
1805
1806 case RXO_smovf:
1807 RL (3);
1808 #ifdef CYCLE_ACCURATE
1809 tx = regs.r[3];
1810 #endif
1811 while (regs.r[3])
1812 {
1813 uma = mem_get_qi (regs.r[2] ++);
1814 mem_put_qi (regs.r[1]++, uma);
1815 regs.r[3] --;
1816 }
1817 cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
1818 break;
1819
1820 case RXO_smovu:
1821 #ifdef CYCLE_ACCURATE
1822 tx = regs.r[3];
1823 #endif
1824 while (regs.r[3] != 0)
1825 {
1826 uma = mem_get_qi (regs.r[2] ++);
1827 mem_put_qi (regs.r[1]++, uma);
1828 regs.r[3] --;
1829 if (uma == 0)
1830 break;
1831 }
1832 cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
1833 break;
1834
1835 case RXO_shar: /* d = ma >> mb */
1836 SHIFT_OP (sll, int, mb, >>=, 1);
1837 E (1);
1838 break;
1839
1840 case RXO_shll: /* d = ma << mb */
1841 SHIFT_OP (ll, int, mb, <<=, 0x80000000UL);
1842 E (1);
1843 break;
1844
1845 case RXO_shlr: /* d = ma >> mb */
1846 SHIFT_OP (ll, unsigned int, mb, >>=, 1);
1847 E (1);
1848 break;
1849
1850 case RXO_sstr:
1851 RL (3);
1852 #ifdef CYCLE_ACCURATE
1853 tx = regs.r[3];
1854 #endif
1855 switch (opcode->size)
1856 {
1857 case RX_Long:
1858 while (regs.r[3] != 0)
1859 {
1860 mem_put_si (regs.r[1], regs.r[2]);
1861 regs.r[1] += 4;
1862 regs.r[3] --;
1863 }
1864 cycles (2 + tx);
1865 break;
1866 case RX_Word:
1867 while (regs.r[3] != 0)
1868 {
1869 mem_put_hi (regs.r[1], regs.r[2]);
1870 regs.r[1] += 2;
1871 regs.r[3] --;
1872 }
1873 cycles (2 + (int)(tx / 2) + tx % 2);
1874 break;
1875 case RX_Byte:
1876 while (regs.r[3] != 0)
1877 {
1878 mem_put_qi (regs.r[1], regs.r[2]);
1879 regs.r[1] ++;
1880 regs.r[3] --;
1881 }
1882 cycles (2 + (int)(tx / 4) + tx % 4);
1883 break;
1884 default:
1885 abort ();
1886 }
1887 break;
1888
1889 case RXO_stcc:
1890 if (GS2())
1891 PD (GS ());
1892 E1;
1893 break;
1894
1895 case RXO_stop:
1896 PRIVILEDGED ();
1897 regs.r_psw |= FLAGBIT_I;
1898 DO_RETURN (RX_MAKE_STOPPED(0));
1899
1900 case RXO_sub:
1901 MATH_OP (-, 0);
1902 break;
1903
1904 case RXO_suntil:
1905 RL(3);
1906 #ifdef CYCLE_ACCURATE
1907 tx = regs.r[3];
1908 #endif
1909 if (regs.r[3] == 0)
1910 {
1911 cycles (3);
1912 break;
1913 }
1914 switch (opcode->size)
1915 {
1916 case RX_Long:
1917 uma = get_reg (2);
1918 while (regs.r[3] != 0)
1919 {
1920 regs.r[3] --;
1921 umb = mem_get_si (get_reg (1));
1922 regs.r[1] += 4;
1923 if (umb == uma)
1924 break;
1925 }
1926 cycles (3 + 3 * tx);
1927 break;
1928 case RX_Word:
1929 uma = get_reg (2) & 0xffff;
1930 while (regs.r[3] != 0)
1931 {
1932 regs.r[3] --;
1933 umb = mem_get_hi (get_reg (1));
1934 regs.r[1] += 2;
1935 if (umb == uma)
1936 break;
1937 }
1938 cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
1939 break;
1940 case RX_Byte:
1941 uma = get_reg (2) & 0xff;
1942 while (regs.r[3] != 0)
1943 {
1944 regs.r[3] --;
1945 umb = mem_get_qi (regs.r[1]);
1946 regs.r[1] += 1;
1947 if (umb == uma)
1948 break;
1949 }
1950 cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
1951 break;
1952 default:
1953 abort();
1954 }
1955 if (uma == umb)
1956 set_zc (1, 1);
1957 else
1958 set_zc (0, ((int)uma - (int)umb) >= 0);
1959 break;
1960
1961 case RXO_swhile:
1962 RL(3);
1963 #ifdef CYCLE_ACCURATE
1964 tx = regs.r[3];
1965 #endif
1966 if (regs.r[3] == 0)
1967 break;
1968 switch (opcode->size)
1969 {
1970 case RX_Long:
1971 uma = get_reg (2);
1972 while (regs.r[3] != 0)
1973 {
1974 regs.r[3] --;
1975 umb = mem_get_si (get_reg (1));
1976 regs.r[1] += 4;
1977 if (umb != uma)
1978 break;
1979 }
1980 cycles (3 + 3 * tx);
1981 break;
1982 case RX_Word:
1983 uma = get_reg (2) & 0xffff;
1984 while (regs.r[3] != 0)
1985 {
1986 regs.r[3] --;
1987 umb = mem_get_hi (get_reg (1));
1988 regs.r[1] += 2;
1989 if (umb != uma)
1990 break;
1991 }
1992 cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
1993 break;
1994 case RX_Byte:
1995 uma = get_reg (2) & 0xff;
1996 while (regs.r[3] != 0)
1997 {
1998 regs.r[3] --;
1999 umb = mem_get_qi (regs.r[1]);
2000 regs.r[1] += 1;
2001 if (umb != uma)
2002 break;
2003 }
2004 cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
2005 break;
2006 default:
2007 abort();
2008 }
2009 if (uma == umb)
2010 set_zc (1, 1);
2011 else
2012 set_zc (0, ((int)uma - (int)umb) >= 0);
2013 break;
2014
2015 case RXO_wait:
2016 PRIVILEDGED ();
2017 regs.r_psw |= FLAGBIT_I;
2018 DO_RETURN (RX_MAKE_STOPPED(0));
2019
2020 case RXO_xchg:
2021 #ifdef CYCLE_ACCURATE
2022 regs.m2m = 0;
2023 #endif
2024 v = GS (); /* This is the memory operand, if any. */
2025 PS (GD ()); /* and this may change the address register. */
2026 PD (v);
2027 E2;
2028 #ifdef CYCLE_ACCURATE
2029 /* all M cycles happen during xchg's cycles. */
2030 memory_dest = 0;
2031 memory_source = 0;
2032 #endif
2033 break;
2034
2035 case RXO_xor:
2036 LOGIC_OP (^);
2037 break;
2038
2039 default:
2040 EXCEPTION (EX_UNDEFINED);
2041 }
2042
2043 #ifdef CYCLE_ACCURATE
2044 regs.m2m = 0;
2045 if (memory_source)
2046 regs.m2m |= M2M_SRC;
2047 if (memory_dest)
2048 regs.m2m |= M2M_DST;
2049
2050 regs.rt = new_rt;
2051 new_rt = -1;
2052 #endif
2053
2054 #ifdef CYCLE_STATS
2055 if (prev_cycle_count == regs.cycle_count)
2056 {
2057 printf("Cycle count not updated! id %s\n", id_names[opcode->id]);
2058 abort ();
2059 }
2060 #endif
2061
2062 #ifdef CYCLE_STATS
2063 if (running_benchmark)
2064 {
2065 int omap = op_lookup (opcode->op[0].type, opcode->op[1].type, opcode->op[2].type);
2066
2067
2068 cycles_per_id[opcode->id][omap] += regs.cycle_count - prev_cycle_count;
2069 times_per_id[opcode->id][omap] ++;
2070
2071 times_per_pair[prev_opcode_id][po0][opcode->id][omap] ++;
2072
2073 prev_opcode_id = opcode->id;
2074 po0 = omap;
2075 }
2076 #endif
2077
2078 return RX_MAKE_STEPPED ();
2079 }
2080
2081 #ifdef CYCLE_STATS
2082 void
2083 reset_pipeline_stats (void)
2084 {
2085 memset (cycles_per_id, 0, sizeof(cycles_per_id));
2086 memset (times_per_id, 0, sizeof(times_per_id));
2087 memory_stalls = 0;
2088 register_stalls = 0;
2089 branch_stalls = 0;
2090 branch_alignment_stalls = 0;
2091 fast_returns = 0;
2092 memset (times_per_pair, 0, sizeof(times_per_pair));
2093 running_benchmark = 1;
2094
2095 benchmark_start_cycle = regs.cycle_count;
2096 }
2097
2098 void
2099 halt_pipeline_stats (void)
2100 {
2101 running_benchmark = 0;
2102 benchmark_end_cycle = regs.cycle_count;
2103 }
2104 #endif
2105
2106 void
2107 pipeline_stats (void)
2108 {
2109 #ifdef CYCLE_STATS
2110 int i, o1;
2111 int p, p1;
2112 #endif
2113
2114 #ifdef CYCLE_ACCURATE
2115 if (verbose == 1)
2116 {
2117 printf ("cycles: %llu\n", regs.cycle_count);
2118 return;
2119 }
2120
2121 printf ("cycles: %13s\n", comma (regs.cycle_count));
2122 #endif
2123
2124 #ifdef CYCLE_STATS
2125 if (benchmark_start_cycle)
2126 printf ("bmark: %13s\n", comma (benchmark_end_cycle - benchmark_start_cycle));
2127
2128 printf("\n");
2129 for (i = 0; i < N_RXO; i++)
2130 for (o1 = 0; o1 < N_MAP; o1 ++)
2131 if (times_per_id[i][o1])
2132 printf("%13s %13s %7.2f %s %s\n",
2133 comma (cycles_per_id[i][o1]),
2134 comma (times_per_id[i][o1]),
2135 (double)cycles_per_id[i][o1] / times_per_id[i][o1],
2136 op_cache_string(o1),
2137 id_names[i]+4);
2138
2139 printf("\n");
2140 for (p = 0; p < N_RXO; p ++)
2141 for (p1 = 0; p1 < N_MAP; p1 ++)
2142 for (i = 0; i < N_RXO; i ++)
2143 for (o1 = 0; o1 < N_MAP; o1 ++)
2144 if (times_per_pair[p][p1][i][o1])
2145 {
2146 printf("%13s %s %-9s -> %s %s\n",
2147 comma (times_per_pair[p][p1][i][o1]),
2148 op_cache_string(p1),
2149 id_names[p]+4,
2150 op_cache_string(o1),
2151 id_names[i]+4);
2152 }
2153
2154 printf("\n");
2155 printf("%13s memory stalls\n", comma (memory_stalls));
2156 printf("%13s register stalls\n", comma (register_stalls));
2157 printf("%13s branches taken (non-return)\n", comma (branch_stalls));
2158 printf("%13s branch alignment stalls\n", comma (branch_alignment_stalls));
2159 printf("%13s fast returns\n", comma (fast_returns));
2160 #endif
2161 }
This page took 0.105808 seconds and 4 git commands to generate.