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