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