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