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