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