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