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