]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/rx/rx.c
* rx.c (SHIFT_OP): A shift by zero still sets the condition codes.
[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 } \
7f77d948 735 set_oszc (val, 4, c); \
4f8d4a38
DD
736 PD (val); \
737}
738
739typedef union {
740 int i;
741 float f;
742} FloatInt;
743
744static inline int
745float2int (float f)
746{
747 FloatInt fi;
748 fi.f = f;
749 return fi.i;
750}
751
752static inline float
753int2float (int i)
754{
755 FloatInt fi;
756 fi.i = i;
757 return fi.f;
758}
759
760static int
761fop_fadd (fp_t s1, fp_t s2, fp_t *d)
762{
763 *d = rxfp_add (s1, s2);
764 return 1;
765}
766
767static int
768fop_fmul (fp_t s1, fp_t s2, fp_t *d)
769{
770 *d = rxfp_mul (s1, s2);
771 return 1;
772}
773
774static int
775fop_fdiv (fp_t s1, fp_t s2, fp_t *d)
776{
777 *d = rxfp_div (s1, s2);
778 return 1;
779}
780
781static int
782fop_fsub (fp_t s1, fp_t s2, fp_t *d)
783{
784 *d = rxfp_sub (s1, s2);
785 return 1;
786}
787
788#define FPPENDING() (regs.r_fpsw & (FPSWBITS_CE | (FPSWBITS_FMASK & (regs.r_fpsw << FPSW_EFSH))))
789#define FPCLEAR() regs.r_fpsw &= FPSWBITS_CLEAR
790#define FPCHECK() \
791 if (FPPENDING()) \
792 return do_fp_exception (opcode_pc)
793
794#define FLOAT_OP(func) \
795{ \
796 int do_store; \
797 fp_t fa, fb, fc; \
798 FPCLEAR(); \
4f8d4a38 799 fb = GS (); \
93378652 800 fa = GD (); \
4f8d4a38
DD
801 do_store = fop_##func (fa, fb, &fc); \
802 tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
803 FPCHECK(); \
804 if (do_store) \
805 PD (fc); \
806 mb = 0; \
807 if ((fc & 0x80000000UL) != 0) \
808 mb |= FLAGBIT_S; \
809 if ((fc & 0x7fffffffUL) == 0) \
810 mb |= FLAGBIT_Z; \
811 set_flags (FLAGBIT_S | FLAGBIT_Z, mb); \
812}
813
814#define carry (FLAG_C ? 1 : 0)
815
816static struct {
817 unsigned long vaddr;
818 const char *str;
819 int signal;
820} exception_info[] = {
821 { 0xFFFFFFD0UL, "priviledged opcode", SIGILL },
822 { 0xFFFFFFD4UL, "access violation", SIGSEGV },
823 { 0xFFFFFFDCUL, "undefined opcode", SIGILL },
824 { 0xFFFFFFE4UL, "floating point", SIGFPE }
825};
826#define EX_PRIVILEDGED 0
827#define EX_ACCESS 1
828#define EX_UNDEFINED 2
829#define EX_FLOATING 3
830#define EXCEPTION(n) \
831 return generate_exception (n, opcode_pc)
832
833#define PRIVILEDGED() \
834 if (FLAG_PM) \
835 EXCEPTION (EX_PRIVILEDGED)
836
837static int
838generate_exception (unsigned long type, SI opcode_pc)
839{
840 SI old_psw, old_pc, new_pc;
841
842 new_pc = mem_get_si (exception_info[type].vaddr);
843 /* 0x00020000 is the value used to initialise the known
844 exception vectors (see rx.ld), but it is a reserved
845 area of memory so do not try to access it, and if the
846 value has not been changed by the program then the
847 vector has not been installed. */
848 if (new_pc == 0 || new_pc == 0x00020000)
849 {
850 if (rx_in_gdb)
851 return RX_MAKE_STOPPED (exception_info[type].signal);
852
853 fprintf(stderr, "Unhandled %s exception at pc = %#lx\n",
854 exception_info[type].str, (unsigned long) opcode_pc);
855 if (type == EX_FLOATING)
856 {
857 int mask = FPPENDING ();
858 fprintf (stderr, "Pending FP exceptions:");
859 if (mask & FPSWBITS_FV)
860 fprintf(stderr, " Invalid");
861 if (mask & FPSWBITS_FO)
862 fprintf(stderr, " Overflow");
863 if (mask & FPSWBITS_FZ)
864 fprintf(stderr, " Division-by-zero");
865 if (mask & FPSWBITS_FU)
866 fprintf(stderr, " Underflow");
867 if (mask & FPSWBITS_FX)
868 fprintf(stderr, " Inexact");
869 if (mask & FPSWBITS_CE)
870 fprintf(stderr, " Unimplemented");
871 fprintf(stderr, "\n");
872 }
873 return RX_MAKE_EXITED (1);
874 }
875
876 tprintf ("Triggering %s exception\n", exception_info[type].str);
877
878 old_psw = regs.r_psw;
879 regs.r_psw &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
880 old_pc = opcode_pc;
881 regs.r_pc = new_pc;
882 pushpc (old_psw);
883 pushpc (old_pc);
884 return RX_MAKE_STEPPED ();
885}
886
887void
888generate_access_exception (void)
889{
890 int rv;
891
892 rv = generate_exception (EX_ACCESS, regs.r_pc);
893 if (RX_EXITED (rv))
894 longjmp (decode_jmp_buf, rv);
895}
896
897static int
898do_fp_exception (unsigned long opcode_pc)
899{
900 while (FPPENDING())
901 EXCEPTION (EX_FLOATING);
902 return RX_MAKE_STEPPED ();
903}
904
93378652 905static int
f9c7014e 906op_is_memory (const RX_Opcode_Decoded *rd, int i)
93378652
DD
907{
908 switch (rd->op[i].type)
909 {
910 case RX_Operand_Predec:
911 case RX_Operand_Postinc:
912 case RX_Operand_Indirect:
913 return 1;
914 default:
915 return 0;
916 }
917}
f9c7014e
DD
918#define OM(i) op_is_memory (opcode, i)
919
920#define DO_RETURN(x) { longjmp (decode_jmp_buf, x); }
93378652 921
4f8d4a38
DD
922int
923decode_opcode ()
924{
925 unsigned int uma=0, umb=0;
926 int ma=0, mb=0;
927 int opcode_size, v;
928 unsigned long long ll;
929 long long sll;
930 unsigned long opcode_pc;
931 RX_Data rx_data;
f9c7014e 932 const RX_Opcode_Decoded *opcode;
93378652
DD
933#ifdef CYCLE_STATS
934 unsigned long long prev_cycle_count;
935#endif
936#ifdef CYCLE_ACCURATE
6607c80d 937 unsigned int tx;
93378652 938#endif
4f8d4a38 939
93378652
DD
940#ifdef CYCLE_STATS
941 prev_cycle_count = regs.cycle_count;
942#endif
943
944#ifdef CYCLE_ACCURATE
945 memory_source = 0;
946 memory_dest = 0;
947#endif
948
4f8d4a38
DD
949 rx_cycles ++;
950
f9c7014e
DD
951 maybe_get_mem_page (regs.r_pc);
952
953 opcode_pc = regs.r_pc;
954
955 /* Note that we don't word-swap this point, there's no point. */
956 if (decode_cache_base[opcode_pc] == NULL)
957 {
958 RX_Opcode_Decoded *opcode_w;
959 rx_data.dpc = opcode_pc;
960 opcode_w = decode_cache_base[opcode_pc] = calloc (1, sizeof (RX_Opcode_Decoded));
961 opcode_size = rx_decode_opcode (opcode_pc, opcode_w,
962 rx_get_byte, &rx_data);
963 opcode = opcode_w;
964 }
965 else
966 {
967 opcode = decode_cache_base[opcode_pc];
968 opcode_size = opcode->n_bytes;
969 }
93378652
DD
970
971#ifdef CYCLE_ACCURATE
972 if (branch_alignment_penalty)
973 {
974 if ((regs.r_pc ^ (regs.r_pc + opcode_size - 1)) & ~7)
975 {
976 tprintf("1 cycle branch alignment penalty\n");
977 cycles (branch_alignment_penalty);
978#ifdef CYCLE_STATS
979 branch_alignment_stalls ++;
980#endif
981 }
982 branch_alignment_penalty = 0;
983 }
984#endif
985
4f8d4a38
DD
986 regs.r_pc += opcode_size;
987
f9c7014e
DD
988 rx_flagmask = opcode->flags_s;
989 rx_flagand = ~(int)opcode->flags_0;
990 rx_flagor = opcode->flags_1;
4f8d4a38 991
f9c7014e 992 switch (opcode->id)
4f8d4a38
DD
993 {
994 case RXO_abs:
995 sll = GS ();
996 tprintf("|%lld| = ", sll);
997 if (sll < 0)
998 sll = -sll;
999 tprintf("%lld\n", sll);
1000 PD (sll);
1001 set_osz (sll, 4);
93378652 1002 E (1);
4f8d4a38
DD
1003 break;
1004
1005 case RXO_adc:
1006 MATH_OP (+,carry);
1007 break;
1008
1009 case RXO_add:
1010 MATH_OP (+,0);
1011 break;
1012
1013 case RXO_and:
1014 LOGIC_OP (&);
1015 break;
1016
1017 case RXO_bclr:
1018 ma = GD ();
1019 mb = GS ();
f9c7014e 1020 if (opcode->op[0].type == RX_Operand_Register)
4f8d4a38
DD
1021 mb &= 0x1f;
1022 else
1023 mb &= 0x07;
1024 ma &= ~(1 << mb);
1025 PD (ma);
93378652 1026 EBIT;
4f8d4a38
DD
1027 break;
1028
1029 case RXO_bmcc:
1030 ma = GD ();
1031 mb = GS ();
f9c7014e 1032 if (opcode->op[0].type == RX_Operand_Register)
4f8d4a38
DD
1033 mb &= 0x1f;
1034 else
1035 mb &= 0x07;
1036 if (GS2 ())
1037 ma |= (1 << mb);
1038 else
1039 ma &= ~(1 << mb);
1040 PD (ma);
93378652 1041 EBIT;
4f8d4a38
DD
1042 break;
1043
1044 case RXO_bnot:
1045 ma = GD ();
1046 mb = GS ();
f9c7014e 1047 if (opcode->op[0].type == RX_Operand_Register)
4f8d4a38
DD
1048 mb &= 0x1f;
1049 else
1050 mb &= 0x07;
1051 ma ^= (1 << mb);
1052 PD (ma);
93378652 1053 EBIT;
4f8d4a38
DD
1054 break;
1055
1056 case RXO_branch:
f9c7014e 1057 if (opcode->op[1].type == RX_Operand_None || GS())
93378652
DD
1058 {
1059#ifdef CYCLE_ACCURATE
1060 SI old_pc = regs.r_pc;
1061 int delta;
1062#endif
1063 regs.r_pc = GD();
1064#ifdef CYCLE_ACCURATE
1065 delta = regs.r_pc - old_pc;
1066 if (delta >= 0 && delta < 16
1067 && opcode_size > 1)
1068 {
1069 tprintf("near forward branch bonus\n");
1070 cycles (2);
1071 }
1072 else
1073 {
1074 cycles (3);
1075 branch_alignment_penalty = 1;
1076 }
1077#ifdef CYCLE_STATS
1078 branch_stalls ++;
93378652
DD
1079#endif
1080#endif
1081 }
1082#ifdef CYCLE_ACCURATE
1083 else
1084 cycles (1);
1085#endif
4f8d4a38
DD
1086 break;
1087
1088 case RXO_branchrel:
45eb4d47 1089 if (opcode->op[1].type == RX_Operand_None || GS())
93378652
DD
1090 {
1091 int delta = GD();
45eb4d47 1092 regs.r_pc = opcode_pc + delta;
93378652
DD
1093#ifdef CYCLE_ACCURATE
1094 /* Note: specs say 3, chip says 2. */
1095 if (delta >= 0 && delta < 16
1096 && opcode_size > 1)
1097 {
1098 tprintf("near forward branch bonus\n");
1099 cycles (2);
1100 }
1101 else
1102 {
1103 cycles (3);
1104 branch_alignment_penalty = 1;
1105 }
1106#ifdef CYCLE_STATS
1107 branch_stalls ++;
1108#endif
1109#endif
1110 }
1111#ifdef CYCLE_ACCURATE
1112 else
1113 cycles (1);
1114#endif
4f8d4a38
DD
1115 break;
1116
1117 case RXO_brk:
1118 {
1119 int old_psw = regs.r_psw;
1120 if (rx_in_gdb)
f9c7014e 1121 DO_RETURN (RX_MAKE_HIT_BREAK ());
4f8d4a38
DD
1122 if (regs.r_intb == 0)
1123 {
1124 tprintf("BREAK hit, no vector table.\n");
f9c7014e 1125 DO_RETURN (RX_MAKE_EXITED(1));
4f8d4a38
DD
1126 }
1127 regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
1128 pushpc (old_psw);
1129 pushpc (regs.r_pc);
1130 regs.r_pc = mem_get_si (regs.r_intb);
93378652 1131 cycles(6);
4f8d4a38
DD
1132 }
1133 break;
1134
1135 case RXO_bset:
1136 ma = GD ();
1137 mb = GS ();
f9c7014e 1138 if (opcode->op[0].type == RX_Operand_Register)
4f8d4a38
DD
1139 mb &= 0x1f;
1140 else
1141 mb &= 0x07;
1142 ma |= (1 << mb);
1143 PD (ma);
93378652 1144 EBIT;
4f8d4a38
DD
1145 break;
1146
1147 case RXO_btst:
1148 ma = GS ();
1149 mb = GS2 ();
f9c7014e 1150 if (opcode->op[1].type == RX_Operand_Register)
4f8d4a38
DD
1151 mb &= 0x1f;
1152 else
1153 mb &= 0x07;
1154 umb = ma & (1 << mb);
1155 set_zc (! umb, umb);
93378652 1156 EBIT;
4f8d4a38
DD
1157 break;
1158
1159 case RXO_clrpsw:
f9c7014e 1160 v = 1 << opcode->op[0].reg;
4f8d4a38
DD
1161 if (FLAG_PM
1162 && (v == FLAGBIT_I
1163 || v == FLAGBIT_U))
1164 break;
1165 regs.r_psw &= ~v;
93378652 1166 cycles (1);
4f8d4a38
DD
1167 break;
1168
1169 case RXO_div: /* d = d / s */
1170 ma = GS();
1171 mb = GD();
1172 tprintf("%d / %d = ", mb, ma);
1173 if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
1174 {
1175 tprintf("#NAN\n");
1176 set_flags (FLAGBIT_O, FLAGBIT_O);
5cbc4f2e 1177 cycles (3);
4f8d4a38
DD
1178 }
1179 else
1180 {
1181 v = mb/ma;
1182 tprintf("%d\n", v);
1183 set_flags (FLAGBIT_O, 0);
1184 PD (v);
5cbc4f2e 1185 div_cycles (mb, ma);
4f8d4a38
DD
1186 }
1187 break;
1188
1189 case RXO_divu: /* d = d / s */
1190 uma = GS();
1191 umb = GD();
1192 tprintf("%u / %u = ", umb, uma);
1193 if (uma == 0)
1194 {
1195 tprintf("#NAN\n");
1196 set_flags (FLAGBIT_O, FLAGBIT_O);
5cbc4f2e 1197 cycles (2);
4f8d4a38
DD
1198 }
1199 else
1200 {
1201 v = umb / uma;
1202 tprintf("%u\n", v);
1203 set_flags (FLAGBIT_O, 0);
1204 PD (v);
5cbc4f2e 1205 divu_cycles (umb, uma);
4f8d4a38
DD
1206 }
1207 break;
1208
4f8d4a38
DD
1209 case RXO_emul:
1210 ma = GD ();
1211 mb = GS ();
1212 sll = (long long)ma * (long long)mb;
1213 tprintf("%d * %d = %lld\n", ma, mb, sll);
f9c7014e
DD
1214 put_reg (opcode->op[0].reg, sll);
1215 put_reg (opcode->op[0].reg + 1, sll >> 32);
93378652 1216 E2;
4f8d4a38
DD
1217 break;
1218
1219 case RXO_emulu:
1220 uma = GD ();
1221 umb = GS ();
1222 ll = (long long)uma * (long long)umb;
1223 tprintf("%#x * %#x = %#llx\n", uma, umb, ll);
f9c7014e
DD
1224 put_reg (opcode->op[0].reg, ll);
1225 put_reg (opcode->op[0].reg + 1, ll >> 32);
93378652 1226 E2;
4f8d4a38
DD
1227 break;
1228
1229 case RXO_fadd:
1230 FLOAT_OP (fadd);
93378652 1231 E (4);
4f8d4a38
DD
1232 break;
1233
1234 case RXO_fcmp:
1235 ma = GD();
1236 mb = GS();
1237 FPCLEAR ();
1238 rxfp_cmp (ma, mb);
1239 FPCHECK ();
93378652 1240 E (1);
4f8d4a38
DD
1241 break;
1242
1243 case RXO_fdiv:
1244 FLOAT_OP (fdiv);
93378652 1245 E (16);
4f8d4a38
DD
1246 break;
1247
1248 case RXO_fmul:
1249 FLOAT_OP (fmul);
93378652 1250 E (3);
4f8d4a38
DD
1251 break;
1252
1253 case RXO_rtfi:
1254 PRIVILEDGED ();
1255 regs.r_psw = regs.r_bpsw;
1256 regs.r_pc = regs.r_bpc;
93378652
DD
1257#ifdef CYCLE_ACCURATE
1258 regs.fast_return = 0;
1259 cycles(3);
1260#endif
4f8d4a38
DD
1261 break;
1262
1263 case RXO_fsub:
1264 FLOAT_OP (fsub);
93378652 1265 E (4);
4f8d4a38
DD
1266 break;
1267
1268 case RXO_ftoi:
1269 ma = GS ();
1270 FPCLEAR ();
1271 mb = rxfp_ftoi (ma, FPRM_ZERO);
1272 FPCHECK ();
1273 PD (mb);
1274 tprintf("(int) %g = %d\n", int2float(ma), mb);
1275 set_sz (mb, 4);
93378652 1276 E (2);
4f8d4a38
DD
1277 break;
1278
1279 case RXO_int:
1280 v = GS ();
1281 if (v == 255)
1282 {
5f79eb72
NC
1283 int rc = rx_syscall (regs.r[5]);
1284 if (! RX_STEPPED (rc))
1285 DO_RETURN (rc);
4f8d4a38
DD
1286 }
1287 else
1288 {
1289 int old_psw = regs.r_psw;
1290 regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
1291 pushpc (old_psw);
1292 pushpc (regs.r_pc);
1293 regs.r_pc = mem_get_si (regs.r_intb + 4 * v);
1294 }
93378652 1295 cycles (6);
4f8d4a38
DD
1296 break;
1297
1298 case RXO_itof:
1299 ma = GS ();
1300 FPCLEAR ();
1301 mb = rxfp_itof (ma, regs.r_fpsw);
1302 FPCHECK ();
1303 tprintf("(float) %d = %x\n", ma, mb);
1304 PD (mb);
1305 set_sz (ma, 4);
93378652 1306 E (2);
4f8d4a38
DD
1307 break;
1308
1309 case RXO_jsr:
1310 case RXO_jsrrel:
93378652
DD
1311 {
1312#ifdef CYCLE_ACCURATE
1313 int delta;
1314 regs.m2m = 0;
1315#endif
1316 v = GD ();
1317#ifdef CYCLE_ACCURATE
1318 regs.link_register = regs.r_pc;
1319#endif
1320 pushpc (get_reg (pc));
f9c7014e 1321 if (opcode->id == RXO_jsrrel)
93378652
DD
1322 v += regs.r_pc;
1323#ifdef CYCLE_ACCURATE
1324 delta = v - regs.r_pc;
1325#endif
1326 put_reg (pc, v);
1327#ifdef CYCLE_ACCURATE
1328 /* Note: docs say 3, chip says 2 */
1329 if (delta >= 0 && delta < 16)
1330 {
1331 tprintf ("near forward jsr bonus\n");
1332 cycles (2);
1333 }
1334 else
1335 {
1336 branch_alignment_penalty = 1;
1337 cycles (3);
1338 }
1339 regs.fast_return = 1;
1340#endif
1341 }
4f8d4a38
DD
1342 break;
1343
1344 case RXO_machi:
1345 ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
1346 ll <<= 16;
1347 put_reg64 (acc64, ll + regs.r_acc);
93378652 1348 E1;
4f8d4a38
DD
1349 break;
1350
1351 case RXO_maclo:
1352 ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
1353 ll <<= 16;
1354 put_reg64 (acc64, ll + regs.r_acc);
93378652 1355 E1;
4f8d4a38
DD
1356 break;
1357
1358 case RXO_max:
4f8d4a38 1359 mb = GS();
93378652 1360 ma = GD();
4f8d4a38
DD
1361 if (ma > mb)
1362 PD (ma);
1363 else
1364 PD (mb);
93378652 1365 E (1);
4f8d4a38
DD
1366 break;
1367
1368 case RXO_min:
4f8d4a38 1369 mb = GS();
93378652 1370 ma = GD();
4f8d4a38
DD
1371 if (ma < mb)
1372 PD (ma);
1373 else
1374 PD (mb);
93378652 1375 E (1);
4f8d4a38
DD
1376 break;
1377
1378 case RXO_mov:
1379 v = GS ();
93378652 1380
29cfc22f
DD
1381 if (opcode->op[1].type == RX_Operand_Register
1382 && opcode->op[1].reg == 17 /* PC */)
1383 {
1384 /* Special case. We want the address of the insn, not the
1385 address of the next insn. */
1386 v = opcode_pc;
1387 }
1388
f9c7014e
DD
1389 if (opcode->op[0].type == RX_Operand_Register
1390 && opcode->op[0].reg == 16 /* PSW */)
4f8d4a38
DD
1391 {
1392 /* Special case, LDC and POPC can't ever modify PM. */
1393 int pm = regs.r_psw & FLAGBIT_PM;
1394 v &= ~ FLAGBIT_PM;
1395 v |= pm;
1396 if (pm)
1397 {
1398 v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
1399 v |= pm;
1400 }
1401 }
1402 if (FLAG_PM)
1403 {
1404 /* various things can't be changed in user mode. */
f9c7014e
DD
1405 if (opcode->op[0].type == RX_Operand_Register)
1406 if (opcode->op[0].reg == 32)
4f8d4a38
DD
1407 {
1408 v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
1409 v |= regs.r_psw & (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
1410 }
f9c7014e
DD
1411 if (opcode->op[0].reg == 34 /* ISP */
1412 || opcode->op[0].reg == 37 /* BPSW */
1413 || opcode->op[0].reg == 39 /* INTB */
1414 || opcode->op[0].reg == 38 /* VCT */)
4f8d4a38
DD
1415 /* These are ignored. */
1416 break;
1417 }
93378652
DD
1418 if (OM(0) && OM(1))
1419 cycles (2);
1420 else
1421 cycles (1);
1422
4f8d4a38 1423 PD (v);
93378652
DD
1424
1425#ifdef CYCLE_ACCURATE
f9c7014e
DD
1426 if ((opcode->op[0].type == RX_Operand_Predec
1427 && opcode->op[1].type == RX_Operand_Register)
1428 || (opcode->op[0].type == RX_Operand_Postinc
1429 && opcode->op[1].type == RX_Operand_Register))
93378652
DD
1430 {
1431 /* Special case: push reg doesn't cause a memory stall. */
1432 memory_dest = 0;
1433 tprintf("push special case\n");
1434 }
1435#endif
1436
4f8d4a38
DD
1437 set_sz (v, DSZ());
1438 break;
1439
1440 case RXO_movbi:
4f8d4a38 1441 PD (GS ());
93378652 1442 cycles (1);
4f8d4a38
DD
1443 break;
1444
1445 case RXO_movbir:
4f8d4a38 1446 PS (GD ());
93378652 1447 cycles (1);
4f8d4a38
DD
1448 break;
1449
1450 case RXO_mul:
93378652
DD
1451 v = US2 ();
1452 ll = (unsigned long long) US1() * (unsigned long long) v;
4f8d4a38 1453 PD(ll);
93378652 1454 E (1);
4f8d4a38
DD
1455 break;
1456
1457 case RXO_mulhi:
93378652
DD
1458 v = GS2 ();
1459 ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v >> 16);
4f8d4a38
DD
1460 ll <<= 16;
1461 put_reg64 (acc64, ll);
93378652 1462 E1;
4f8d4a38
DD
1463 break;
1464
1465 case RXO_mullo:
93378652
DD
1466 v = GS2 ();
1467 ll = (long long)(signed short)(GS()) * (long long)(signed short)(v);
4f8d4a38
DD
1468 ll <<= 16;
1469 put_reg64 (acc64, ll);
93378652 1470 E1;
4f8d4a38
DD
1471 break;
1472
1473 case RXO_mvfachi:
1474 PD (get_reg (acchi));
93378652 1475 E1;
4f8d4a38
DD
1476 break;
1477
1478 case RXO_mvfaclo:
1479 PD (get_reg (acclo));
93378652 1480 E1;
4f8d4a38
DD
1481 break;
1482
1483 case RXO_mvfacmi:
1484 PD (get_reg (accmi));
93378652 1485 E1;
4f8d4a38
DD
1486 break;
1487
1488 case RXO_mvtachi:
1489 put_reg (acchi, GS ());
93378652 1490 E1;
4f8d4a38
DD
1491 break;
1492
1493 case RXO_mvtaclo:
1494 put_reg (acclo, GS ());
93378652 1495 E1;
4f8d4a38
DD
1496 break;
1497
1498 case RXO_mvtipl:
1499 regs.r_psw &= ~ FLAGBITS_IPL;
1500 regs.r_psw |= (GS () << FLAGSHIFT_IPL) & FLAGBITS_IPL;
93378652 1501 E1;
4f8d4a38
DD
1502 break;
1503
1504 case RXO_nop:
f9c7014e
DD
1505 case RXO_nop2:
1506 case RXO_nop3:
93378652 1507 E1;
4f8d4a38
DD
1508 break;
1509
1510 case RXO_or:
1511 LOGIC_OP (|);
1512 break;
1513
1514 case RXO_popm:
1515 /* POPM cannot pop R0 (sp). */
f9c7014e 1516 if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
4f8d4a38 1517 EXCEPTION (EX_UNDEFINED);
f9c7014e 1518 if (opcode->op[1].reg >= opcode->op[2].reg)
4f8d4a38
DD
1519 {
1520 regs.r_pc = opcode_pc;
f9c7014e 1521 DO_RETURN (RX_MAKE_STOPPED (SIGILL));
4f8d4a38 1522 }
f9c7014e 1523 for (v = opcode->op[1].reg; v <= opcode->op[2].reg; v++)
93378652
DD
1524 {
1525 cycles (1);
1526 RLD (v);
1527 put_reg (v, pop ());
1528 }
4f8d4a38
DD
1529 break;
1530
1531 case RXO_pushm:
1532 /* PUSHM cannot push 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;
1538 return RX_MAKE_STOPPED (SIGILL);
1539 }
f9c7014e 1540 for (v = opcode->op[2].reg; v >= opcode->op[1].reg; v--)
93378652
DD
1541 {
1542 RL (v);
1543 push (get_reg (v));
1544 }
f9c7014e 1545 cycles (opcode->op[2].reg - opcode->op[1].reg + 1);
4f8d4a38
DD
1546 break;
1547
1548 case RXO_racw:
1549 ll = get_reg64 (acc64) << GS ();
1550 ll += 0x80000000ULL;
1551 if ((signed long long)ll > (signed long long)0x00007fff00000000ULL)
1552 ll = 0x00007fff00000000ULL;
1553 else if ((signed long long)ll < (signed long long)0xffff800000000000ULL)
1554 ll = 0xffff800000000000ULL;
1555 else
1556 ll &= 0xffffffff00000000ULL;
1557 put_reg64 (acc64, ll);
93378652 1558 E1;
4f8d4a38
DD
1559 break;
1560
1561 case RXO_rte:
1562 PRIVILEDGED ();
1563 regs.r_pc = poppc ();
1564 regs.r_psw = poppc ();
1565 if (FLAG_PM)
1566 regs.r_psw |= FLAGBIT_U;
93378652
DD
1567#ifdef CYCLE_ACCURATE
1568 regs.fast_return = 0;
1569 cycles (6);
1570#endif
4f8d4a38
DD
1571 break;
1572
1573 case RXO_revl:
1574 uma = GS ();
1575 umb = (((uma >> 24) & 0xff)
1576 | ((uma >> 8) & 0xff00)
1577 | ((uma << 8) & 0xff0000)
1578 | ((uma << 24) & 0xff000000UL));
1579 PD (umb);
93378652 1580 E1;
4f8d4a38
DD
1581 break;
1582
1583 case RXO_revw:
1584 uma = GS ();
1585 umb = (((uma >> 8) & 0x00ff00ff)
1586 | ((uma << 8) & 0xff00ff00UL));
1587 PD (umb);
93378652 1588 E1;
4f8d4a38
DD
1589 break;
1590
1591 case RXO_rmpa:
93378652
DD
1592 RL(4);
1593 RL(5);
1594#ifdef CYCLE_ACCURATE
1595 tx = regs.r[3];
1596#endif
1597
4f8d4a38
DD
1598 while (regs.r[3] != 0)
1599 {
1600 long long tmp;
1601
f9c7014e 1602 switch (opcode->size)
4f8d4a38
DD
1603 {
1604 case RX_Long:
1605 ma = mem_get_si (regs.r[1]);
1606 mb = mem_get_si (regs.r[2]);
1607 regs.r[1] += 4;
1608 regs.r[2] += 4;
1609 break;
1610 case RX_Word:
1611 ma = sign_ext (mem_get_hi (regs.r[1]), 16);
1612 mb = sign_ext (mem_get_hi (regs.r[2]), 16);
1613 regs.r[1] += 2;
1614 regs.r[2] += 2;
1615 break;
1616 case RX_Byte:
1617 ma = sign_ext (mem_get_qi (regs.r[1]), 8);
1618 mb = sign_ext (mem_get_qi (regs.r[2]), 8);
1619 regs.r[1] += 1;
1620 regs.r[2] += 1;
1621 break;
1622 default:
1623 abort ();
1624 }
1625 /* We do the multiply as a signed value. */
1626 sll = (long long)ma * (long long)mb;
1627 tprintf(" %016llx = %d * %d\n", sll, ma, mb);
1628 /* but we do the sum as unsigned, while sign extending the operands. */
1629 tmp = regs.r[4] + (sll & 0xffffffffUL);
1630 regs.r[4] = tmp & 0xffffffffUL;
1631 tmp >>= 32;
1632 sll >>= 32;
1633 tmp += regs.r[5] + (sll & 0xffffffffUL);
1634 regs.r[5] = tmp & 0xffffffffUL;
1635 tmp >>= 32;
1636 sll >>= 32;
1637 tmp += regs.r[6] + (sll & 0xffffffffUL);
1638 regs.r[6] = tmp & 0xffffffffUL;
1639 tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
1640 (unsigned long) regs.r[6],
1641 (unsigned long) regs.r[5],
1642 (unsigned long) regs.r[4]);
1643
1644 regs.r[3] --;
1645 }
1646 if (regs.r[6] & 0x00008000)
1647 regs.r[6] |= 0xffff0000UL;
1648 else
1649 regs.r[6] &= 0x0000ffff;
1650 ma = (regs.r[6] & 0x80000000UL) ? FLAGBIT_S : 0;
1651 if (regs.r[6] != 0 && regs.r[6] != 0xffffffffUL)
1652 set_flags (FLAGBIT_O|FLAGBIT_S, ma | FLAGBIT_O);
1653 else
1654 set_flags (FLAGBIT_O|FLAGBIT_S, ma);
93378652 1655#ifdef CYCLE_ACCURATE
f9c7014e 1656 switch (opcode->size)
93378652
DD
1657 {
1658 case RX_Long:
1659 cycles (6 + 4 * tx);
1660 break;
1661 case RX_Word:
1662 cycles (6 + 5 * (tx / 2) + 4 * (tx % 2));
1663 break;
1664 case RX_Byte:
1665 cycles (6 + 7 * (tx / 4) + 4 * (tx % 4));
1666 break;
1667 default:
1668 abort ();
1669 }
1670#endif
4f8d4a38
DD
1671 break;
1672
1673 case RXO_rolc:
1674 v = GD ();
1675 ma = v & 0x80000000UL;
1676 v <<= 1;
1677 v |= carry;
1678 set_szc (v, 4, ma);
1679 PD (v);
93378652 1680 E1;
4f8d4a38
DD
1681 break;
1682
1683 case RXO_rorc:
1684 uma = GD ();
1685 mb = uma & 1;
1686 uma >>= 1;
1687 uma |= (carry ? 0x80000000UL : 0);
1688 set_szc (uma, 4, mb);
1689 PD (uma);
93378652 1690 E1;
4f8d4a38
DD
1691 break;
1692
1693 case RXO_rotl:
1694 mb = GS ();
1695 uma = GD ();
1696 if (mb)
1697 {
1698 uma = (uma << mb) | (uma >> (32-mb));
1699 mb = uma & 1;
1700 }
1701 set_szc (uma, 4, mb);
1702 PD (uma);
93378652 1703 E1;
4f8d4a38
DD
1704 break;
1705
1706 case RXO_rotr:
1707 mb = GS ();
1708 uma = GD ();
1709 if (mb)
1710 {
1711 uma = (uma >> mb) | (uma << (32-mb));
1712 mb = uma & 0x80000000;
1713 }
1714 set_szc (uma, 4, mb);
1715 PD (uma);
93378652 1716 E1;
4f8d4a38
DD
1717 break;
1718
1719 case RXO_round:
1720 ma = GS ();
1721 FPCLEAR ();
1722 mb = rxfp_ftoi (ma, regs.r_fpsw);
1723 FPCHECK ();
1724 PD (mb);
1725 tprintf("(int) %g = %d\n", int2float(ma), mb);
1726 set_sz (mb, 4);
93378652 1727 E (2);
4f8d4a38
DD
1728 break;
1729
1730 case RXO_rts:
93378652
DD
1731 {
1732#ifdef CYCLE_ACCURATE
1733 int cyc = 5;
1734#endif
1735 regs.r_pc = poppc ();
1736#ifdef CYCLE_ACCURATE
1737 /* Note: specs say 5, chip says 3. */
1738 if (regs.fast_return && regs.link_register == regs.r_pc)
1739 {
1740#ifdef CYCLE_STATS
1741 fast_returns ++;
1742#endif
1743 tprintf("fast return bonus\n");
1744 cyc -= 2;
1745 }
1746 cycles (cyc);
1747 regs.fast_return = 0;
1748 branch_alignment_penalty = 1;
1749#endif
1750 }
4f8d4a38
DD
1751 break;
1752
1753 case RXO_rtsd:
f9c7014e 1754 if (opcode->op[2].type == RX_Operand_Register)
4f8d4a38
DD
1755 {
1756 int i;
1757 /* RTSD cannot pop R0 (sp). */
f9c7014e
DD
1758 put_reg (0, get_reg (0) + GS() - (opcode->op[0].reg-opcode->op[2].reg+1)*4);
1759 if (opcode->op[2].reg == 0)
4f8d4a38 1760 EXCEPTION (EX_UNDEFINED);
93378652 1761#ifdef CYCLE_ACCURATE
f9c7014e 1762 tx = opcode->op[0].reg - opcode->op[2].reg + 1;
93378652 1763#endif
f9c7014e 1764 for (i = opcode->op[2].reg; i <= opcode->op[0].reg; i ++)
93378652
DD
1765 {
1766 RLD (i);
1767 put_reg (i, pop ());
1768 }
1769 }
1770 else
1771 {
1772#ifdef CYCLE_ACCURATE
1773 tx = 0;
1774#endif
1775 put_reg (0, get_reg (0) + GS());
1776 }
1777 put_reg (pc, poppc());
1778#ifdef CYCLE_ACCURATE
1779 if (regs.fast_return && regs.link_register == regs.r_pc)
1780 {
1781 tprintf("fast return bonus\n");
1782#ifdef CYCLE_STATS
1783 fast_returns ++;
1784#endif
1785 cycles (tx < 3 ? 3 : tx + 1);
4f8d4a38
DD
1786 }
1787 else
93378652
DD
1788 {
1789 cycles (tx < 5 ? 5 : tx + 1);
1790 }
1791 regs.fast_return = 0;
1792 branch_alignment_penalty = 1;
1793#endif
4f8d4a38
DD
1794 break;
1795
1796 case RXO_sat:
1797 if (FLAG_O && FLAG_S)
1798 PD (0x7fffffffUL);
1799 else if (FLAG_O && ! FLAG_S)
1800 PD (0x80000000UL);
93378652 1801 E1;
4f8d4a38
DD
1802 break;
1803
04e65a62
NC
1804 case RXO_satr:
1805 if (FLAG_O && ! FLAG_S)
1806 {
1807 put_reg (6, 0x0);
1808 put_reg (5, 0x7fffffff);
1809 put_reg (4, 0xffffffff);
1810 }
1811 else if (FLAG_O && FLAG_S)
1812 {
1813 put_reg (6, 0xffffffff);
1814 put_reg (5, 0x80000000);
1815 put_reg (4, 0x0);
1816 }
1817 E1;
1818 break;
1819
4f8d4a38
DD
1820 case RXO_sbb:
1821 MATH_OP (-, ! carry);
1822 break;
1823
1824 case RXO_sccnd:
1825 if (GS())
1826 PD (1);
1827 else
1828 PD (0);
93378652 1829 E1;
4f8d4a38
DD
1830 break;
1831
1832 case RXO_scmpu:
93378652
DD
1833#ifdef CYCLE_ACCURATE
1834 tx = regs.r[3];
1835#endif
4f8d4a38
DD
1836 while (regs.r[3] != 0)
1837 {
1838 uma = mem_get_qi (regs.r[1] ++);
1839 umb = mem_get_qi (regs.r[2] ++);
1840 regs.r[3] --;
1841 if (uma != umb || uma == 0)
1842 break;
1843 }
1844 if (uma == umb)
1845 set_zc (1, 1);
1846 else
1847 set_zc (0, ((int)uma - (int)umb) >= 0);
93378652 1848 cycles (2 + 4 * (tx / 4) + 4 * (tx % 4));
4f8d4a38
DD
1849 break;
1850
1851 case RXO_setpsw:
f9c7014e 1852 v = 1 << opcode->op[0].reg;
4f8d4a38
DD
1853 if (FLAG_PM
1854 && (v == FLAGBIT_I
1855 || v == FLAGBIT_U))
1856 break;
1857 regs.r_psw |= v;
93378652 1858 cycles (1);
4f8d4a38
DD
1859 break;
1860
1861 case RXO_smovb:
93378652
DD
1862 RL (3);
1863#ifdef CYCLE_ACCURATE
1864 tx = regs.r[3];
1865#endif
4f8d4a38
DD
1866 while (regs.r[3])
1867 {
1868 uma = mem_get_qi (regs.r[2] --);
1869 mem_put_qi (regs.r[1]--, uma);
1870 regs.r[3] --;
1871 }
93378652
DD
1872#ifdef CYCLE_ACCURATE
1873 if (tx > 3)
1874 cycles (6 + 3 * (tx / 4) + 3 * (tx % 4));
1875 else
1876 cycles (2 + 3 * (tx % 4));
1877#endif
4f8d4a38
DD
1878 break;
1879
1880 case RXO_smovf:
93378652
DD
1881 RL (3);
1882#ifdef CYCLE_ACCURATE
1883 tx = regs.r[3];
1884#endif
4f8d4a38
DD
1885 while (regs.r[3])
1886 {
1887 uma = mem_get_qi (regs.r[2] ++);
1888 mem_put_qi (regs.r[1]++, uma);
1889 regs.r[3] --;
1890 }
93378652 1891 cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
4f8d4a38
DD
1892 break;
1893
1894 case RXO_smovu:
e5379772
KB
1895#ifdef CYCLE_ACCURATE
1896 tx = regs.r[3];
1897#endif
4f8d4a38
DD
1898 while (regs.r[3] != 0)
1899 {
1900 uma = mem_get_qi (regs.r[2] ++);
1901 mem_put_qi (regs.r[1]++, uma);
1902 regs.r[3] --;
1903 if (uma == 0)
1904 break;
1905 }
e5379772 1906 cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
4f8d4a38
DD
1907 break;
1908
1909 case RXO_shar: /* d = ma >> mb */
1910 SHIFT_OP (sll, int, mb, >>=, 1);
93378652 1911 E (1);
4f8d4a38
DD
1912 break;
1913
1914 case RXO_shll: /* d = ma << mb */
1915 SHIFT_OP (ll, int, mb, <<=, 0x80000000UL);
93378652 1916 E (1);
4f8d4a38
DD
1917 break;
1918
1919 case RXO_shlr: /* d = ma >> mb */
1920 SHIFT_OP (ll, unsigned int, mb, >>=, 1);
93378652 1921 E (1);
4f8d4a38
DD
1922 break;
1923
1924 case RXO_sstr:
93378652
DD
1925 RL (3);
1926#ifdef CYCLE_ACCURATE
1927 tx = regs.r[3];
1928#endif
f9c7014e 1929 switch (opcode->size)
4f8d4a38
DD
1930 {
1931 case RX_Long:
1932 while (regs.r[3] != 0)
1933 {
1934 mem_put_si (regs.r[1], regs.r[2]);
1935 regs.r[1] += 4;
1936 regs.r[3] --;
1937 }
93378652 1938 cycles (2 + tx);
4f8d4a38
DD
1939 break;
1940 case RX_Word:
1941 while (regs.r[3] != 0)
1942 {
1943 mem_put_hi (regs.r[1], regs.r[2]);
1944 regs.r[1] += 2;
1945 regs.r[3] --;
1946 }
93378652 1947 cycles (2 + (int)(tx / 2) + tx % 2);
4f8d4a38
DD
1948 break;
1949 case RX_Byte:
1950 while (regs.r[3] != 0)
1951 {
1952 mem_put_qi (regs.r[1], regs.r[2]);
1953 regs.r[1] ++;
1954 regs.r[3] --;
1955 }
93378652 1956 cycles (2 + (int)(tx / 4) + tx % 4);
4f8d4a38
DD
1957 break;
1958 default:
1959 abort ();
1960 }
1961 break;
1962
1963 case RXO_stcc:
1964 if (GS2())
1965 PD (GS ());
93378652 1966 E1;
4f8d4a38
DD
1967 break;
1968
1969 case RXO_stop:
1970 PRIVILEDGED ();
1971 regs.r_psw |= FLAGBIT_I;
f9c7014e 1972 DO_RETURN (RX_MAKE_STOPPED(0));
4f8d4a38
DD
1973
1974 case RXO_sub:
1975 MATH_OP (-, 0);
1976 break;
1977
1978 case RXO_suntil:
93378652
DD
1979 RL(3);
1980#ifdef CYCLE_ACCURATE
5cbc4f2e 1981 tx = 0;
93378652 1982#endif
4f8d4a38 1983 if (regs.r[3] == 0)
93378652
DD
1984 {
1985 cycles (3);
1986 break;
1987 }
f9c7014e 1988 switch (opcode->size)
4f8d4a38
DD
1989 {
1990 case RX_Long:
1991 uma = get_reg (2);
1992 while (regs.r[3] != 0)
1993 {
1994 regs.r[3] --;
1995 umb = mem_get_si (get_reg (1));
1996 regs.r[1] += 4;
5cbc4f2e
DD
1997#ifdef CYCLE_ACCURATE
1998 tx ++;
1999#endif
4f8d4a38
DD
2000 if (umb == uma)
2001 break;
2002 }
5cbc4f2e 2003#ifdef CYCLE_ACCURATE
93378652 2004 cycles (3 + 3 * tx);
5cbc4f2e 2005#endif
4f8d4a38
DD
2006 break;
2007 case RX_Word:
2008 uma = get_reg (2) & 0xffff;
2009 while (regs.r[3] != 0)
2010 {
2011 regs.r[3] --;
2012 umb = mem_get_hi (get_reg (1));
2013 regs.r[1] += 2;
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 / 2) + 3 * (tx % 2));
5cbc4f2e 2022#endif
4f8d4a38
DD
2023 break;
2024 case RX_Byte:
2025 uma = get_reg (2) & 0xff;
2026 while (regs.r[3] != 0)
2027 {
2028 regs.r[3] --;
2029 umb = mem_get_qi (regs.r[1]);
2030 regs.r[1] += 1;
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 / 4) + 3 * (tx % 4));
5cbc4f2e 2039#endif
4f8d4a38
DD
2040 break;
2041 default:
2042 abort();
2043 }
2044 if (uma == umb)
2045 set_zc (1, 1);
2046 else
2047 set_zc (0, ((int)uma - (int)umb) >= 0);
2048 break;
2049
2050 case RXO_swhile:
93378652
DD
2051 RL(3);
2052#ifdef CYCLE_ACCURATE
5cbc4f2e 2053 tx = 0;
93378652 2054#endif
4f8d4a38
DD
2055 if (regs.r[3] == 0)
2056 break;
f9c7014e 2057 switch (opcode->size)
4f8d4a38
DD
2058 {
2059 case RX_Long:
2060 uma = get_reg (2);
2061 while (regs.r[3] != 0)
2062 {
2063 regs.r[3] --;
2064 umb = mem_get_si (get_reg (1));
117f2c0d 2065 regs.r[1] += 4;
5cbc4f2e
DD
2066#ifdef CYCLE_ACCURATE
2067 tx ++;
2068#endif
4f8d4a38
DD
2069 if (umb != uma)
2070 break;
4f8d4a38 2071 }
5cbc4f2e 2072#ifdef CYCLE_ACCURATE
93378652 2073 cycles (3 + 3 * tx);
5cbc4f2e 2074#endif
4f8d4a38
DD
2075 break;
2076 case RX_Word:
2077 uma = get_reg (2) & 0xffff;
2078 while (regs.r[3] != 0)
2079 {
2080 regs.r[3] --;
2081 umb = mem_get_hi (get_reg (1));
117f2c0d 2082 regs.r[1] += 2;
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 / 2) + 3 * (tx % 2));
5cbc4f2e 2091#endif
4f8d4a38
DD
2092 break;
2093 case RX_Byte:
2094 uma = get_reg (2) & 0xff;
2095 while (regs.r[3] != 0)
2096 {
2097 regs.r[3] --;
2098 umb = mem_get_qi (regs.r[1]);
117f2c0d 2099 regs.r[1] += 1;
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 / 4) + 3 * (tx % 4));
5cbc4f2e 2108#endif
4f8d4a38
DD
2109 break;
2110 default:
2111 abort();
2112 }
2113 if (uma == umb)
2114 set_zc (1, 1);
2115 else
2116 set_zc (0, ((int)uma - (int)umb) >= 0);
2117 break;
2118
2119 case RXO_wait:
2120 PRIVILEDGED ();
2121 regs.r_psw |= FLAGBIT_I;
f9c7014e 2122 DO_RETURN (RX_MAKE_STOPPED(0));
4f8d4a38
DD
2123
2124 case RXO_xchg:
93378652
DD
2125#ifdef CYCLE_ACCURATE
2126 regs.m2m = 0;
2127#endif
4f8d4a38
DD
2128 v = GS (); /* This is the memory operand, if any. */
2129 PS (GD ()); /* and this may change the address register. */
2130 PD (v);
93378652
DD
2131 E2;
2132#ifdef CYCLE_ACCURATE
2133 /* all M cycles happen during xchg's cycles. */
2134 memory_dest = 0;
2135 memory_source = 0;
2136#endif
4f8d4a38
DD
2137 break;
2138
2139 case RXO_xor:
2140 LOGIC_OP (^);
2141 break;
2142
2143 default:
2144 EXCEPTION (EX_UNDEFINED);
2145 }
2146
93378652
DD
2147#ifdef CYCLE_ACCURATE
2148 regs.m2m = 0;
2149 if (memory_source)
2150 regs.m2m |= M2M_SRC;
2151 if (memory_dest)
2152 regs.m2m |= M2M_DST;
2153
2154 regs.rt = new_rt;
2155 new_rt = -1;
2156#endif
2157
2158#ifdef CYCLE_STATS
2159 if (prev_cycle_count == regs.cycle_count)
2160 {
f9c7014e 2161 printf("Cycle count not updated! id %s\n", id_names[opcode->id]);
93378652
DD
2162 abort ();
2163 }
2164#endif
2165
2166#ifdef CYCLE_STATS
2167 if (running_benchmark)
2168 {
f9c7014e 2169 int omap = op_lookup (opcode->op[0].type, opcode->op[1].type, opcode->op[2].type);
93378652
DD
2170
2171
f9c7014e
DD
2172 cycles_per_id[opcode->id][omap] += regs.cycle_count - prev_cycle_count;
2173 times_per_id[opcode->id][omap] ++;
93378652 2174
f9c7014e 2175 times_per_pair[prev_opcode_id][po0][opcode->id][omap] ++;
93378652 2176
f9c7014e 2177 prev_opcode_id = opcode->id;
93378652
DD
2178 po0 = omap;
2179 }
2180#endif
2181
4f8d4a38
DD
2182 return RX_MAKE_STEPPED ();
2183}
93378652
DD
2184
2185#ifdef CYCLE_STATS
2186void
2187reset_pipeline_stats (void)
2188{
2189 memset (cycles_per_id, 0, sizeof(cycles_per_id));
2190 memset (times_per_id, 0, sizeof(times_per_id));
2191 memory_stalls = 0;
2192 register_stalls = 0;
2193 branch_stalls = 0;
2194 branch_alignment_stalls = 0;
2195 fast_returns = 0;
2196 memset (times_per_pair, 0, sizeof(times_per_pair));
2197 running_benchmark = 1;
2198
2199 benchmark_start_cycle = regs.cycle_count;
2200}
2201
2202void
2203halt_pipeline_stats (void)
2204{
2205 running_benchmark = 0;
2206 benchmark_end_cycle = regs.cycle_count;
2207}
2208#endif
2209
2210void
2211pipeline_stats (void)
2212{
2213#ifdef CYCLE_STATS
2214 int i, o1;
2215 int p, p1;
2216#endif
2217
2218#ifdef CYCLE_ACCURATE
2219 if (verbose == 1)
2220 {
2221 printf ("cycles: %llu\n", regs.cycle_count);
2222 return;
2223 }
2224
2225 printf ("cycles: %13s\n", comma (regs.cycle_count));
2226#endif
2227
2228#ifdef CYCLE_STATS
2229 if (benchmark_start_cycle)
2230 printf ("bmark: %13s\n", comma (benchmark_end_cycle - benchmark_start_cycle));
2231
2232 printf("\n");
2233 for (i = 0; i < N_RXO; i++)
2234 for (o1 = 0; o1 < N_MAP; o1 ++)
2235 if (times_per_id[i][o1])
2236 printf("%13s %13s %7.2f %s %s\n",
2237 comma (cycles_per_id[i][o1]),
2238 comma (times_per_id[i][o1]),
2239 (double)cycles_per_id[i][o1] / times_per_id[i][o1],
2240 op_cache_string(o1),
2241 id_names[i]+4);
2242
2243 printf("\n");
2244 for (p = 0; p < N_RXO; p ++)
2245 for (p1 = 0; p1 < N_MAP; p1 ++)
2246 for (i = 0; i < N_RXO; i ++)
2247 for (o1 = 0; o1 < N_MAP; o1 ++)
2248 if (times_per_pair[p][p1][i][o1])
2249 {
2250 printf("%13s %s %-9s -> %s %s\n",
2251 comma (times_per_pair[p][p1][i][o1]),
2252 op_cache_string(p1),
2253 id_names[p]+4,
2254 op_cache_string(o1),
2255 id_names[i]+4);
2256 }
2257
2258 printf("\n");
2259 printf("%13s memory stalls\n", comma (memory_stalls));
2260 printf("%13s register stalls\n", comma (register_stalls));
2261 printf("%13s branches taken (non-return)\n", comma (branch_stalls));
2262 printf("%13s branch alignment stalls\n", comma (branch_alignment_stalls));
2263 printf("%13s fast returns\n", comma (fast_returns));
2264#endif
2265}