1 1.1 christos /* rx.c --- opcode semantics for stand-alone RX simulator. 2 1.1 christos 3 1.1.1.11 christos Copyright (C) 2008-2025 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