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