|
Packit Service |
706eca |
/* rx.c --- opcode semantics for stand-alone RX simulator.
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
Copyright (C) 2008-2018 Free Software Foundation, Inc.
|
|
Packit Service |
706eca |
Contributed by Red Hat, Inc.
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
This file is part of the GNU simulators.
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
This program is free software; you can redistribute it and/or modify
|
|
Packit Service |
706eca |
it under the terms of the GNU General Public License as published by
|
|
Packit Service |
706eca |
the Free Software Foundation; either version 3 of the License, or
|
|
Packit Service |
706eca |
(at your option) any later version.
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
This program is distributed in the hope that it will be useful,
|
|
Packit Service |
706eca |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
706eca |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
706eca |
GNU General Public License for more details.
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
You should have received a copy of the GNU General Public License
|
|
Packit Service |
706eca |
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#include "config.h"
|
|
Packit Service |
706eca |
#include <stdio.h>
|
|
Packit Service |
706eca |
#include <stdlib.h>
|
|
Packit Service |
706eca |
#include <string.h>
|
|
Packit Service |
706eca |
#include <signal.h>
|
|
Packit Service |
706eca |
#include "libiberty.h"
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#include "opcode/rx.h"
|
|
Packit Service |
706eca |
#include "cpu.h"
|
|
Packit Service |
706eca |
#include "mem.h"
|
|
Packit Service |
706eca |
#include "syscalls.h"
|
|
Packit Service |
706eca |
#include "fpu.h"
|
|
Packit Service |
706eca |
#include "err.h"
|
|
Packit Service |
706eca |
#include "misc.h"
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
static const char * id_names[] = {
|
|
Packit Service |
706eca |
"RXO_unknown",
|
|
Packit Service |
706eca |
"RXO_mov", /* d = s (signed) */
|
|
Packit Service |
706eca |
"RXO_movbi", /* d = [s,s2] (signed) */
|
|
Packit Service |
706eca |
"RXO_movbir", /* [s,s2] = d (signed) */
|
|
Packit Service |
706eca |
"RXO_pushm", /* s..s2 */
|
|
Packit Service |
706eca |
"RXO_popm", /* s..s2 */
|
|
Packit Service |
706eca |
"RXO_xchg", /* s <-> d */
|
|
Packit Service |
706eca |
"RXO_stcc", /* d = s if cond(s2) */
|
|
Packit Service |
706eca |
"RXO_rtsd", /* rtsd, 1=imm, 2-0 = reg if reg type */
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
/* These are all either d OP= s or, if s2 is set, d = s OP s2. Note
|
|
Packit Service |
706eca |
that d may be "None". */
|
|
Packit Service |
706eca |
"RXO_and",
|
|
Packit Service |
706eca |
"RXO_or",
|
|
Packit Service |
706eca |
"RXO_xor",
|
|
Packit Service |
706eca |
"RXO_add",
|
|
Packit Service |
706eca |
"RXO_sub",
|
|
Packit Service |
706eca |
"RXO_mul",
|
|
Packit Service |
706eca |
"RXO_div",
|
|
Packit Service |
706eca |
"RXO_divu",
|
|
Packit Service |
706eca |
"RXO_shll",
|
|
Packit Service |
706eca |
"RXO_shar",
|
|
Packit Service |
706eca |
"RXO_shlr",
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
"RXO_adc", /* d = d + s + carry */
|
|
Packit Service |
706eca |
"RXO_sbb", /* d = d - s - ~carry */
|
|
Packit Service |
706eca |
"RXO_abs", /* d = |s| */
|
|
Packit Service |
706eca |
"RXO_max", /* d = max(d,s) */
|
|
Packit Service |
706eca |
"RXO_min", /* d = min(d,s) */
|
|
Packit Service |
706eca |
"RXO_emul", /* d:64 = d:32 * s */
|
|
Packit Service |
706eca |
"RXO_emulu", /* d:64 = d:32 * s (unsigned) */
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
"RXO_rolc", /* d <<= 1 through carry */
|
|
Packit Service |
706eca |
"RXO_rorc", /* d >>= 1 through carry*/
|
|
Packit Service |
706eca |
"RXO_rotl", /* d <<= #s without carry */
|
|
Packit Service |
706eca |
"RXO_rotr", /* d >>= #s without carry*/
|
|
Packit Service |
706eca |
"RXO_revw", /* d = revw(s) */
|
|
Packit Service |
706eca |
"RXO_revl", /* d = revl(s) */
|
|
Packit Service |
706eca |
"RXO_branch", /* pc = d if cond(s) */
|
|
Packit Service |
706eca |
"RXO_branchrel",/* pc += d if cond(s) */
|
|
Packit Service |
706eca |
"RXO_jsr", /* pc = d */
|
|
Packit Service |
706eca |
"RXO_jsrrel", /* pc += d */
|
|
Packit Service |
706eca |
"RXO_rts",
|
|
Packit Service |
706eca |
"RXO_nop",
|
|
Packit Service |
706eca |
"RXO_nop2",
|
|
Packit Service |
706eca |
"RXO_nop3",
|
|
Packit Service |
706eca |
"RXO_nop4",
|
|
Packit Service |
706eca |
"RXO_nop5",
|
|
Packit Service |
706eca |
"RXO_nop6",
|
|
Packit Service |
706eca |
"RXO_nop7",
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
"RXO_scmpu",
|
|
Packit Service |
706eca |
"RXO_smovu",
|
|
Packit Service |
706eca |
"RXO_smovb",
|
|
Packit Service |
706eca |
"RXO_suntil",
|
|
Packit Service |
706eca |
"RXO_swhile",
|
|
Packit Service |
706eca |
"RXO_smovf",
|
|
Packit Service |
706eca |
"RXO_sstr",
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
"RXO_rmpa",
|
|
Packit Service |
706eca |
"RXO_mulhi",
|
|
Packit Service |
706eca |
"RXO_mullo",
|
|
Packit Service |
706eca |
"RXO_machi",
|
|
Packit Service |
706eca |
"RXO_maclo",
|
|
Packit Service |
706eca |
"RXO_mvtachi",
|
|
Packit Service |
706eca |
"RXO_mvtaclo",
|
|
Packit Service |
706eca |
"RXO_mvfachi",
|
|
Packit Service |
706eca |
"RXO_mvfacmi",
|
|
Packit Service |
706eca |
"RXO_mvfaclo",
|
|
Packit Service |
706eca |
"RXO_racw",
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
"RXO_sat", /* sat(d) */
|
|
Packit Service |
706eca |
"RXO_satr",
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
"RXO_fadd", /* d op= s */
|
|
Packit Service |
706eca |
"RXO_fcmp",
|
|
Packit Service |
706eca |
"RXO_fsub",
|
|
Packit Service |
706eca |
"RXO_ftoi",
|
|
Packit Service |
706eca |
"RXO_fmul",
|
|
Packit Service |
706eca |
"RXO_fdiv",
|
|
Packit Service |
706eca |
"RXO_round",
|
|
Packit Service |
706eca |
"RXO_itof",
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
"RXO_bset", /* d |= (1<
|
|
Packit Service |
706eca |
"RXO_bclr", /* d &= ~(1<
|
|
Packit Service |
706eca |
"RXO_btst", /* s & (1<
|
|
Packit Service |
706eca |
"RXO_bnot", /* d ^= (1<
|
|
Packit Service |
706eca |
"RXO_bmcc", /* d<s> = cond(s2) */
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
"RXO_clrpsw", /* flag index in d */
|
|
Packit Service |
706eca |
"RXO_setpsw", /* flag index in d */
|
|
Packit Service |
706eca |
"RXO_mvtipl", /* new IPL in s */
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
"RXO_rtfi",
|
|
Packit Service |
706eca |
"RXO_rte",
|
|
Packit Service |
706eca |
"RXO_rtd", /* undocumented */
|
|
Packit Service |
706eca |
"RXO_brk",
|
|
Packit Service |
706eca |
"RXO_dbt", /* undocumented */
|
|
Packit Service |
706eca |
"RXO_int", /* vector id in s */
|
|
Packit Service |
706eca |
"RXO_stop",
|
|
Packit Service |
706eca |
"RXO_wait",
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
"RXO_sccnd", /* d = cond(s) ? 1 : 0 */
|
|
Packit Service |
706eca |
};
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static const char * optype_names[] = {
|
|
Packit Service |
706eca |
" - ",
|
|
Packit Service |
706eca |
"#Imm", /* #addend */
|
|
Packit Service |
706eca |
" Rn ", /* Rn */
|
|
Packit Service |
706eca |
"[Rn]", /* [Rn + addend] */
|
|
Packit Service |
706eca |
"Ps++", /* [Rn+] */
|
|
Packit Service |
706eca |
"--Pr", /* [-Rn] */
|
|
Packit Service |
706eca |
" cc ", /* eq, gtu, etc */
|
|
Packit Service |
706eca |
"Flag", /* [UIOSZC] */
|
|
Packit Service |
706eca |
"RbRi" /* [Rb + scale * Ri] */
|
|
Packit Service |
706eca |
};
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define N_RXO ARRAY_SIZE (id_names)
|
|
Packit Service |
706eca |
#define N_RXT ARRAY_SIZE (optype_names)
|
|
Packit Service |
706eca |
#define N_MAP 90
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static unsigned long long benchmark_start_cycle;
|
|
Packit Service |
706eca |
static unsigned long long benchmark_end_cycle;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int op_cache[N_RXT][N_RXT][N_RXT];
|
|
Packit Service |
706eca |
static int op_cache_rev[N_MAP];
|
|
Packit Service |
706eca |
static int op_cache_idx = 0;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
op_lookup (int a, int b, int c)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
if (op_cache[a][b][c])
|
|
Packit Service |
706eca |
return op_cache[a][b][c];
|
|
Packit Service |
706eca |
op_cache_idx ++;
|
|
Packit Service |
706eca |
if (op_cache_idx >= N_MAP)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
printf("op_cache_idx exceeds %d\n", N_MAP);
|
|
Packit Service |
706eca |
exit(1);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
op_cache[a][b][c] = op_cache_idx;
|
|
Packit Service |
706eca |
op_cache_rev[op_cache_idx] = (a<<8) | (b<<4) | c;
|
|
Packit Service |
706eca |
return op_cache_idx;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static char *
|
|
Packit Service |
706eca |
op_cache_string (int map)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
static int ci;
|
|
Packit Service |
706eca |
static char cb[5][20];
|
|
Packit Service |
706eca |
int a, b, c;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
map = op_cache_rev[map];
|
|
Packit Service |
706eca |
a = (map >> 8) & 15;
|
|
Packit Service |
706eca |
b = (map >> 4) & 15;
|
|
Packit Service |
706eca |
c = (map >> 0) & 15;
|
|
Packit Service |
706eca |
ci = (ci + 1) % 5;
|
|
Packit Service |
706eca |
sprintf(cb[ci], "%s %s %s", optype_names[a], optype_names[b], optype_names[c]);
|
|
Packit Service |
706eca |
return cb[ci];
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static unsigned long long cycles_per_id[N_RXO][N_MAP];
|
|
Packit Service |
706eca |
static unsigned long long times_per_id[N_RXO][N_MAP];
|
|
Packit Service |
706eca |
static unsigned long long memory_stalls;
|
|
Packit Service |
706eca |
static unsigned long long register_stalls;
|
|
Packit Service |
706eca |
static unsigned long long branch_stalls;
|
|
Packit Service |
706eca |
static unsigned long long branch_alignment_stalls;
|
|
Packit Service |
706eca |
static unsigned long long fast_returns;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static unsigned long times_per_pair[N_RXO][N_MAP][N_RXO][N_MAP];
|
|
Packit Service |
706eca |
static int prev_opcode_id = RXO_unknown;
|
|
Packit Service |
706eca |
static int po0;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define STATS(x) x
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#else
|
|
Packit Service |
706eca |
#define STATS(x)
|
|
Packit Service |
706eca |
#endif /* CYCLE_STATS */
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int new_rt = -1;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
/* Number of cycles to add if an insn spans an 8-byte boundary. */
|
|
Packit Service |
706eca |
static int branch_alignment_penalty = 0;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int running_benchmark = 1;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define tprintf if (trace && running_benchmark) printf
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
jmp_buf decode_jmp_buf;
|
|
Packit Service |
706eca |
unsigned int rx_cycles = 0;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
/* If nonzero, memory was read at some point and cycle latency might
|
|
Packit Service |
706eca |
take effect. */
|
|
Packit Service |
706eca |
static int memory_source = 0;
|
|
Packit Service |
706eca |
/* If nonzero, memory was written and extra cycles might be
|
|
Packit Service |
706eca |
needed. */
|
|
Packit Service |
706eca |
static int memory_dest = 0;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static void
|
|
Packit Service |
706eca |
cycles (int throughput)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
tprintf("%d cycles\n", throughput);
|
|
Packit Service |
706eca |
regs.cycle_count += throughput;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
/* Number of execution (E) cycles the op uses. For memory sources, we
|
|
Packit Service |
706eca |
include the load micro-op stall as two extra E cycles. */
|
|
Packit Service |
706eca |
#define E(c) cycles (memory_source ? c + 2 : c)
|
|
Packit Service |
706eca |
#define E1 cycles (1)
|
|
Packit Service |
706eca |
#define E2 cycles (2)
|
|
Packit Service |
706eca |
#define EBIT cycles (memory_source ? 2 : 1)
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
/* Check to see if a read latency must be applied for a given register. */
|
|
Packit Service |
706eca |
#define RL(r) \
|
|
Packit Service |
706eca |
if (regs.rt == r ) \
|
|
Packit Service |
706eca |
{ \
|
|
Packit Service |
706eca |
tprintf("register %d load stall\n", r); \
|
|
Packit Service |
706eca |
regs.cycle_count ++; \
|
|
Packit Service |
706eca |
STATS(register_stalls ++); \
|
|
Packit Service |
706eca |
regs.rt = -1; \
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define RLD(r) \
|
|
Packit Service |
706eca |
if (memory_source) \
|
|
Packit Service |
706eca |
{ \
|
|
Packit Service |
706eca |
tprintf ("Rt now %d\n", r); \
|
|
Packit Service |
706eca |
new_rt = r; \
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
lsb_count (unsigned long v, int is_signed)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int i, lsb;
|
|
Packit Service |
706eca |
if (is_signed && (v & 0x80000000U))
|
|
Packit Service |
706eca |
v = (unsigned long)(long)(-v);
|
|
Packit Service |
706eca |
for (i=31; i>=0; i--)
|
|
Packit Service |
706eca |
if (v & (1 << i))
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
/* v is 0..31, we want 1=1-2, 2=3-4, 3=5-6, etc. */
|
|
Packit Service |
706eca |
lsb = (i + 2) / 2;
|
|
Packit Service |
706eca |
return lsb;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
return 0;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
divu_cycles(unsigned long num, unsigned long den)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int nb = lsb_count (num, 0);
|
|
Packit Service |
706eca |
int db = lsb_count (den, 0);
|
|
Packit Service |
706eca |
int rv;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
if (nb < db)
|
|
Packit Service |
706eca |
rv = 2;
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
rv = 3 + nb - db;
|
|
Packit Service |
706eca |
E (rv);
|
|
Packit Service |
706eca |
return rv;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
div_cycles(long num, long den)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int nb = lsb_count ((unsigned long)num, 1);
|
|
Packit Service |
706eca |
int db = lsb_count ((unsigned long)den, 1);
|
|
Packit Service |
706eca |
int rv;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
if (nb < db)
|
|
Packit Service |
706eca |
rv = 3;
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
rv = 5 + nb - db;
|
|
Packit Service |
706eca |
E (rv);
|
|
Packit Service |
706eca |
return rv;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#else /* !CYCLE_ACCURATE */
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define cycles(t)
|
|
Packit Service |
706eca |
#define E(c)
|
|
Packit Service |
706eca |
#define E1
|
|
Packit Service |
706eca |
#define E2
|
|
Packit Service |
706eca |
#define EBIT
|
|
Packit Service |
706eca |
#define RL(r)
|
|
Packit Service |
706eca |
#define RLD(r)
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define divu_cycles(n,d)
|
|
Packit Service |
706eca |
#define div_cycles(n,d)
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#endif /* else CYCLE_ACCURATE */
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int size2bytes[] = {
|
|
Packit Service |
706eca |
4, 1, 1, 1, 2, 2, 2, 3, 4
|
|
Packit Service |
706eca |
};
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
typedef struct {
|
|
Packit Service |
706eca |
unsigned long dpc;
|
|
Packit Service |
706eca |
} RX_Data;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define rx_abort() _rx_abort(__FILE__, __LINE__)
|
|
Packit Service |
706eca |
static void
|
|
Packit Service |
706eca |
_rx_abort (const char *file, int line)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
if (strrchr (file, '/'))
|
|
Packit Service |
706eca |
file = strrchr (file, '/') + 1;
|
|
Packit Service |
706eca |
fprintf(stderr, "abort at %s:%d\n", file, line);
|
|
Packit Service |
706eca |
abort();
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static unsigned char *get_byte_base;
|
|
Packit Service |
706eca |
static RX_Opcode_Decoded **decode_cache_base;
|
|
Packit Service |
706eca |
static SI get_byte_page;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
void
|
|
Packit Service |
706eca |
reset_decoder (void)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
get_byte_base = 0;
|
|
Packit Service |
706eca |
decode_cache_base = 0;
|
|
Packit Service |
706eca |
get_byte_page = 0;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static inline void
|
|
Packit Service |
706eca |
maybe_get_mem_page (SI tpc)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
if (((tpc ^ get_byte_page) & NONPAGE_MASK) || enable_counting)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
get_byte_page = tpc & NONPAGE_MASK;
|
|
Packit Service |
706eca |
get_byte_base = rx_mem_ptr (get_byte_page, MPA_READING) - get_byte_page;
|
|
Packit Service |
706eca |
decode_cache_base = rx_mem_decode_cache (get_byte_page) - get_byte_page;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
/* This gets called a *lot* so optimize it. */
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
rx_get_byte (void *vdata)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
RX_Data *rx_data = (RX_Data *)vdata;
|
|
Packit Service |
706eca |
SI tpc = rx_data->dpc;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
/* See load.c for an explanation of this. */
|
|
Packit Service |
706eca |
if (rx_big_endian)
|
|
Packit Service |
706eca |
tpc ^= 3;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
maybe_get_mem_page (tpc);
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
rx_data->dpc ++;
|
|
Packit Service |
706eca |
return get_byte_base [tpc];
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
get_op (const RX_Opcode_Decoded *rd, int i)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
const RX_Opcode_Operand *o = rd->op + i;
|
|
Packit Service |
706eca |
int addr, rv = 0;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
switch (o->type)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
case RX_Operand_None:
|
|
Packit Service |
706eca |
rx_abort ();
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Operand_Immediate: /* #addend */
|
|
Packit Service |
706eca |
return o->addend;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Operand_Register: /* Rn */
|
|
Packit Service |
706eca |
RL (o->reg);
|
|
Packit Service |
706eca |
rv = get_reg (o->reg);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Operand_Predec: /* [-Rn] */
|
|
Packit Service |
706eca |
put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
|
|
Packit Service |
706eca |
/* fall through */
|
|
Packit Service |
706eca |
case RX_Operand_Postinc: /* [Rn+] */
|
|
Packit Service |
706eca |
case RX_Operand_Zero_Indirect: /* [Rn + 0] */
|
|
Packit Service |
706eca |
case RX_Operand_Indirect: /* [Rn + addend] */
|
|
Packit Service |
706eca |
case RX_Operand_TwoReg: /* [Rn + scale * R2] */
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
RL (o->reg);
|
|
Packit Service |
706eca |
if (o->type == RX_Operand_TwoReg)
|
|
Packit Service |
706eca |
RL (rd->op[2].reg);
|
|
Packit Service |
706eca |
regs.rt = -1;
|
|
Packit Service |
706eca |
if (regs.m2m == M2M_BOTH)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
tprintf("src memory stall\n");
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
memory_stalls ++;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
regs.cycle_count ++;
|
|
Packit Service |
706eca |
regs.m2m = 0;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
memory_source = 1;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
if (o->type == RX_Operand_TwoReg)
|
|
Packit Service |
706eca |
addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
addr = get_reg (o->reg) + o->addend;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
switch (o->size)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
default:
|
|
Packit Service |
706eca |
case RX_AnySize:
|
|
Packit Service |
706eca |
rx_abort ();
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Byte: /* undefined extension */
|
|
Packit Service |
706eca |
case RX_UByte:
|
|
Packit Service |
706eca |
case RX_SByte:
|
|
Packit Service |
706eca |
rv = mem_get_qi (addr);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Word: /* undefined extension */
|
|
Packit Service |
706eca |
case RX_UWord:
|
|
Packit Service |
706eca |
case RX_SWord:
|
|
Packit Service |
706eca |
rv = mem_get_hi (addr);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_3Byte:
|
|
Packit Service |
706eca |
rv = mem_get_psi (addr);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Long:
|
|
Packit Service |
706eca |
rv = mem_get_si (addr);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
if (o->type == RX_Operand_Postinc)
|
|
Packit Service |
706eca |
put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Operand_Condition: /* eq, gtu, etc */
|
|
Packit Service |
706eca |
return condition_true (o->reg);
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Operand_Flag: /* [UIOSZC] */
|
|
Packit Service |
706eca |
return (regs.r_psw & (1 << o->reg)) ? 1 : 0;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
/* if we've gotten here, we need to clip/extend the value according
|
|
Packit Service |
706eca |
to the size. */
|
|
Packit Service |
706eca |
switch (o->size)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
default:
|
|
Packit Service |
706eca |
case RX_AnySize:
|
|
Packit Service |
706eca |
rx_abort ();
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Byte: /* undefined extension */
|
|
Packit Service |
706eca |
rv |= 0xdeadbe00; /* keep them honest */
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_UByte:
|
|
Packit Service |
706eca |
rv &= 0xff;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_SByte:
|
|
Packit Service |
706eca |
rv = sign_ext (rv, 8);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Word: /* undefined extension */
|
|
Packit Service |
706eca |
rv |= 0xdead0000; /* keep them honest */
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_UWord:
|
|
Packit Service |
706eca |
rv &= 0xffff;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_SWord:
|
|
Packit Service |
706eca |
rv = sign_ext (rv, 16);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_3Byte:
|
|
Packit Service |
706eca |
rv &= 0xffffff;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Long:
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
return rv;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static void
|
|
Packit Service |
706eca |
put_op (const RX_Opcode_Decoded *rd, int i, int v)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
const RX_Opcode_Operand *o = rd->op + i;
|
|
Packit Service |
706eca |
int addr;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
switch (o->size)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
default:
|
|
Packit Service |
706eca |
case RX_AnySize:
|
|
Packit Service |
706eca |
if (o->type != RX_Operand_Register)
|
|
Packit Service |
706eca |
rx_abort ();
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Byte: /* undefined extension */
|
|
Packit Service |
706eca |
v |= 0xdeadbe00; /* keep them honest */
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_UByte:
|
|
Packit Service |
706eca |
v &= 0xff;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_SByte:
|
|
Packit Service |
706eca |
v = sign_ext (v, 8);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Word: /* undefined extension */
|
|
Packit Service |
706eca |
v |= 0xdead0000; /* keep them honest */
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_UWord:
|
|
Packit Service |
706eca |
v &= 0xffff;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_SWord:
|
|
Packit Service |
706eca |
v = sign_ext (v, 16);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_3Byte:
|
|
Packit Service |
706eca |
v &= 0xffffff;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Long:
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
switch (o->type)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
case RX_Operand_None:
|
|
Packit Service |
706eca |
/* Opcodes like TST and CMP use this. */
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Operand_Immediate: /* #addend */
|
|
Packit Service |
706eca |
case RX_Operand_Condition: /* eq, gtu, etc */
|
|
Packit Service |
706eca |
rx_abort ();
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Operand_Register: /* Rn */
|
|
Packit Service |
706eca |
put_reg (o->reg, v);
|
|
Packit Service |
706eca |
RLD (o->reg);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Operand_Predec: /* [-Rn] */
|
|
Packit Service |
706eca |
put_reg (o->reg, get_reg (o->reg) - size2bytes[o->size]);
|
|
Packit Service |
706eca |
/* fall through */
|
|
Packit Service |
706eca |
case RX_Operand_Postinc: /* [Rn+] */
|
|
Packit Service |
706eca |
case RX_Operand_Zero_Indirect: /* [Rn + 0] */
|
|
Packit Service |
706eca |
case RX_Operand_Indirect: /* [Rn + addend] */
|
|
Packit Service |
706eca |
case RX_Operand_TwoReg: /* [Rn + scale * R2] */
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
if (regs.m2m == M2M_BOTH)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
tprintf("dst memory stall\n");
|
|
Packit Service |
706eca |
regs.cycle_count ++;
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
memory_stalls ++;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
regs.m2m = 0;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
memory_dest = 1;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
if (o->type == RX_Operand_TwoReg)
|
|
Packit Service |
706eca |
addr = get_reg (o->reg) * size2bytes[rd->size] + get_reg (rd->op[2].reg);
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
addr = get_reg (o->reg) + o->addend;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
switch (o->size)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
default:
|
|
Packit Service |
706eca |
case RX_AnySize:
|
|
Packit Service |
706eca |
rx_abort ();
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Byte: /* undefined extension */
|
|
Packit Service |
706eca |
case RX_UByte:
|
|
Packit Service |
706eca |
case RX_SByte:
|
|
Packit Service |
706eca |
mem_put_qi (addr, v);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Word: /* undefined extension */
|
|
Packit Service |
706eca |
case RX_UWord:
|
|
Packit Service |
706eca |
case RX_SWord:
|
|
Packit Service |
706eca |
mem_put_hi (addr, v);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_3Byte:
|
|
Packit Service |
706eca |
mem_put_psi (addr, v);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Long:
|
|
Packit Service |
706eca |
mem_put_si (addr, v);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
if (o->type == RX_Operand_Postinc)
|
|
Packit Service |
706eca |
put_reg (o->reg, get_reg (o->reg) + size2bytes[o->size]);
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RX_Operand_Flag: /* [UIOSZC] */
|
|
Packit Service |
706eca |
if (v)
|
|
Packit Service |
706eca |
regs.r_psw |= (1 << o->reg);
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
regs.r_psw &= ~(1 << o->reg);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define PD(x) put_op (opcode, 0, x)
|
|
Packit Service |
706eca |
#define PS(x) put_op (opcode, 1, x)
|
|
Packit Service |
706eca |
#define PS2(x) put_op (opcode, 2, x)
|
|
Packit Service |
706eca |
#define GD() get_op (opcode, 0)
|
|
Packit Service |
706eca |
#define GS() get_op (opcode, 1)
|
|
Packit Service |
706eca |
#define GS2() get_op (opcode, 2)
|
|
Packit Service |
706eca |
#define DSZ() size2bytes[opcode->op[0].size]
|
|
Packit Service |
706eca |
#define SSZ() size2bytes[opcode->op[0].size]
|
|
Packit Service |
706eca |
#define S2SZ() size2bytes[opcode->op[0].size]
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
/* "Universal" sources. */
|
|
Packit Service |
706eca |
#define US1() ((opcode->op[2].type == RX_Operand_None) ? GD() : GS())
|
|
Packit Service |
706eca |
#define US2() ((opcode->op[2].type == RX_Operand_None) ? GS() : GS2())
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static void
|
|
Packit Service |
706eca |
push(int val)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int rsp = get_reg (sp);
|
|
Packit Service |
706eca |
rsp -= 4;
|
|
Packit Service |
706eca |
put_reg (sp, rsp);
|
|
Packit Service |
706eca |
mem_put_si (rsp, val);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
/* Just like the above, but tag the memory as "pushed pc" so if anyone
|
|
Packit Service |
706eca |
tries to write to it, it will cause an error. */
|
|
Packit Service |
706eca |
static void
|
|
Packit Service |
706eca |
pushpc(int val)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int rsp = get_reg (sp);
|
|
Packit Service |
706eca |
rsp -= 4;
|
|
Packit Service |
706eca |
put_reg (sp, rsp);
|
|
Packit Service |
706eca |
mem_put_si (rsp, val);
|
|
Packit Service |
706eca |
mem_set_content_range (rsp, rsp+3, MC_PUSHED_PC);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
pop()
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int rv;
|
|
Packit Service |
706eca |
int rsp = get_reg (sp);
|
|
Packit Service |
706eca |
rv = mem_get_si (rsp);
|
|
Packit Service |
706eca |
rsp += 4;
|
|
Packit Service |
706eca |
put_reg (sp, rsp);
|
|
Packit Service |
706eca |
return rv;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
poppc()
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int rv;
|
|
Packit Service |
706eca |
int rsp = get_reg (sp);
|
|
Packit Service |
706eca |
if (mem_get_content_type (rsp) != MC_PUSHED_PC)
|
|
Packit Service |
706eca |
execution_error (SIM_ERR_CORRUPT_STACK, rsp);
|
|
Packit Service |
706eca |
rv = mem_get_si (rsp);
|
|
Packit Service |
706eca |
mem_set_content_range (rsp, rsp+3, MC_UNINIT);
|
|
Packit Service |
706eca |
rsp += 4;
|
|
Packit Service |
706eca |
put_reg (sp, rsp);
|
|
Packit Service |
706eca |
return rv;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define MATH_OP(vop,c) \
|
|
Packit Service |
706eca |
{ \
|
|
Packit Service |
706eca |
umb = US2(); \
|
|
Packit Service |
706eca |
uma = US1(); \
|
|
Packit Service |
706eca |
ll = (unsigned long long) uma vop (unsigned long long) umb vop c; \
|
|
Packit Service |
706eca |
tprintf ("0x%x " #vop " 0x%x " #vop " 0x%x = 0x%llx\n", uma, umb, c, ll); \
|
|
Packit Service |
706eca |
ma = sign_ext (uma, DSZ() * 8); \
|
|
Packit Service |
706eca |
mb = sign_ext (umb, DSZ() * 8); \
|
|
Packit Service |
706eca |
sll = (long long) ma vop (long long) mb vop c; \
|
|
Packit Service |
706eca |
tprintf ("%d " #vop " %d " #vop " %d = %lld\n", ma, mb, c, sll); \
|
|
Packit Service |
706eca |
set_oszc (sll, DSZ(), (long long) ll > ((1 vop 1) ? (long long) b2mask[DSZ()] : (long long) -1)); \
|
|
Packit Service |
706eca |
PD (sll); \
|
|
Packit Service |
706eca |
E (1); \
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define LOGIC_OP(vop) \
|
|
Packit Service |
706eca |
{ \
|
|
Packit Service |
706eca |
mb = US2(); \
|
|
Packit Service |
706eca |
ma = US1(); \
|
|
Packit Service |
706eca |
v = ma vop mb; \
|
|
Packit Service |
706eca |
tprintf("0x%x " #vop " 0x%x = 0x%x\n", ma, mb, v); \
|
|
Packit Service |
706eca |
set_sz (v, DSZ()); \
|
|
Packit Service |
706eca |
PD(v); \
|
|
Packit Service |
706eca |
E (1); \
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define SHIFT_OP(val, type, count, OP, carry_mask) \
|
|
Packit Service |
706eca |
{ \
|
|
Packit Service |
706eca |
int i, c=0; \
|
|
Packit Service |
706eca |
count = US2(); \
|
|
Packit Service |
706eca |
val = (type)US1(); \
|
|
Packit Service |
706eca |
tprintf("%lld " #OP " %d\n", val, count); \
|
|
Packit Service |
706eca |
for (i = 0; i < count; i ++) \
|
|
Packit Service |
706eca |
{ \
|
|
Packit Service |
706eca |
c = val & carry_mask; \
|
|
Packit Service |
706eca |
val OP 1; \
|
|
Packit Service |
706eca |
} \
|
|
Packit Service |
706eca |
set_oszc (val, 4, c); \
|
|
Packit Service |
706eca |
PD (val); \
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
typedef union {
|
|
Packit Service |
706eca |
int i;
|
|
Packit Service |
706eca |
float f;
|
|
Packit Service |
706eca |
} FloatInt;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static inline int
|
|
Packit Service |
706eca |
float2int (float f)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
FloatInt fi;
|
|
Packit Service |
706eca |
fi.f = f;
|
|
Packit Service |
706eca |
return fi.i;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static inline float
|
|
Packit Service |
706eca |
int2float (int i)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
FloatInt fi;
|
|
Packit Service |
706eca |
fi.i = i;
|
|
Packit Service |
706eca |
return fi.f;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
fop_fadd (fp_t s1, fp_t s2, fp_t *d)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
*d = rxfp_add (s1, s2);
|
|
Packit Service |
706eca |
return 1;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
fop_fmul (fp_t s1, fp_t s2, fp_t *d)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
*d = rxfp_mul (s1, s2);
|
|
Packit Service |
706eca |
return 1;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
fop_fdiv (fp_t s1, fp_t s2, fp_t *d)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
*d = rxfp_div (s1, s2);
|
|
Packit Service |
706eca |
return 1;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
fop_fsub (fp_t s1, fp_t s2, fp_t *d)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
*d = rxfp_sub (s1, s2);
|
|
Packit Service |
706eca |
return 1;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define FPPENDING() (regs.r_fpsw & (FPSWBITS_CE | (FPSWBITS_FMASK & (regs.r_fpsw << FPSW_EFSH))))
|
|
Packit Service |
706eca |
#define FPCLEAR() regs.r_fpsw &= FPSWBITS_CLEAR
|
|
Packit Service |
706eca |
#define FPCHECK() \
|
|
Packit Service |
706eca |
if (FPPENDING()) \
|
|
Packit Service |
706eca |
return do_fp_exception (opcode_pc)
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define FLOAT_OP(func) \
|
|
Packit Service |
706eca |
{ \
|
|
Packit Service |
706eca |
int do_store; \
|
|
Packit Service |
706eca |
fp_t fa, fb, fc; \
|
|
Packit Service |
706eca |
FPCLEAR(); \
|
|
Packit Service |
706eca |
fb = GS (); \
|
|
Packit Service |
706eca |
fa = GD (); \
|
|
Packit Service |
706eca |
do_store = fop_##func (fa, fb, &fc); \
|
|
Packit Service |
706eca |
tprintf("%g " #func " %g = %g %08x\n", int2float(fa), int2float(fb), int2float(fc), fc); \
|
|
Packit Service |
706eca |
FPCHECK(); \
|
|
Packit Service |
706eca |
if (do_store) \
|
|
Packit Service |
706eca |
PD (fc); \
|
|
Packit Service |
706eca |
mb = 0; \
|
|
Packit Service |
706eca |
if ((fc & 0x80000000UL) != 0) \
|
|
Packit Service |
706eca |
mb |= FLAGBIT_S; \
|
|
Packit Service |
706eca |
if ((fc & 0x7fffffffUL) == 0) \
|
|
Packit Service |
706eca |
mb |= FLAGBIT_Z; \
|
|
Packit Service |
706eca |
set_flags (FLAGBIT_S | FLAGBIT_Z, mb); \
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define carry (FLAG_C ? 1 : 0)
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static struct {
|
|
Packit Service |
706eca |
unsigned long vaddr;
|
|
Packit Service |
706eca |
const char *str;
|
|
Packit Service |
706eca |
int signal;
|
|
Packit Service |
706eca |
} exception_info[] = {
|
|
Packit Service |
706eca |
{ 0xFFFFFFD0UL, "priviledged opcode", SIGILL },
|
|
Packit Service |
706eca |
{ 0xFFFFFFD4UL, "access violation", SIGSEGV },
|
|
Packit Service |
706eca |
{ 0xFFFFFFDCUL, "undefined opcode", SIGILL },
|
|
Packit Service |
706eca |
{ 0xFFFFFFE4UL, "floating point", SIGFPE }
|
|
Packit Service |
706eca |
};
|
|
Packit Service |
706eca |
#define EX_PRIVILEDGED 0
|
|
Packit Service |
706eca |
#define EX_ACCESS 1
|
|
Packit Service |
706eca |
#define EX_UNDEFINED 2
|
|
Packit Service |
706eca |
#define EX_FLOATING 3
|
|
Packit Service |
706eca |
#define EXCEPTION(n) \
|
|
Packit Service |
706eca |
return generate_exception (n, opcode_pc)
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define PRIVILEDGED() \
|
|
Packit Service |
706eca |
if (FLAG_PM) \
|
|
Packit Service |
706eca |
EXCEPTION (EX_PRIVILEDGED)
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
generate_exception (unsigned long type, SI opcode_pc)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
SI old_psw, old_pc, new_pc;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
new_pc = mem_get_si (exception_info[type].vaddr);
|
|
Packit Service |
706eca |
/* 0x00020000 is the value used to initialise the known
|
|
Packit Service |
706eca |
exception vectors (see rx.ld), but it is a reserved
|
|
Packit Service |
706eca |
area of memory so do not try to access it, and if the
|
|
Packit Service |
706eca |
value has not been changed by the program then the
|
|
Packit Service |
706eca |
vector has not been installed. */
|
|
Packit Service |
706eca |
if (new_pc == 0 || new_pc == 0x00020000)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
if (rx_in_gdb)
|
|
Packit Service |
706eca |
return RX_MAKE_STOPPED (exception_info[type].signal);
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
fprintf(stderr, "Unhandled %s exception at pc = %#lx\n",
|
|
Packit Service |
706eca |
exception_info[type].str, (unsigned long) opcode_pc);
|
|
Packit Service |
706eca |
if (type == EX_FLOATING)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int mask = FPPENDING ();
|
|
Packit Service |
706eca |
fprintf (stderr, "Pending FP exceptions:");
|
|
Packit Service |
706eca |
if (mask & FPSWBITS_FV)
|
|
Packit Service |
706eca |
fprintf(stderr, " Invalid");
|
|
Packit Service |
706eca |
if (mask & FPSWBITS_FO)
|
|
Packit Service |
706eca |
fprintf(stderr, " Overflow");
|
|
Packit Service |
706eca |
if (mask & FPSWBITS_FZ)
|
|
Packit Service |
706eca |
fprintf(stderr, " Division-by-zero");
|
|
Packit Service |
706eca |
if (mask & FPSWBITS_FU)
|
|
Packit Service |
706eca |
fprintf(stderr, " Underflow");
|
|
Packit Service |
706eca |
if (mask & FPSWBITS_FX)
|
|
Packit Service |
706eca |
fprintf(stderr, " Inexact");
|
|
Packit Service |
706eca |
if (mask & FPSWBITS_CE)
|
|
Packit Service |
706eca |
fprintf(stderr, " Unimplemented");
|
|
Packit Service |
706eca |
fprintf(stderr, "\n");
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
return RX_MAKE_EXITED (1);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
tprintf ("Triggering %s exception\n", exception_info[type].str);
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
old_psw = regs.r_psw;
|
|
Packit Service |
706eca |
regs.r_psw &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
|
|
Packit Service |
706eca |
old_pc = opcode_pc;
|
|
Packit Service |
706eca |
regs.r_pc = new_pc;
|
|
Packit Service |
706eca |
pushpc (old_psw);
|
|
Packit Service |
706eca |
pushpc (old_pc);
|
|
Packit Service |
706eca |
return RX_MAKE_STEPPED ();
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
void
|
|
Packit Service |
706eca |
generate_access_exception (void)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int rv;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
rv = generate_exception (EX_ACCESS, regs.r_pc);
|
|
Packit Service |
706eca |
if (RX_EXITED (rv))
|
|
Packit Service |
706eca |
longjmp (decode_jmp_buf, rv);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
do_fp_exception (unsigned long opcode_pc)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
while (FPPENDING())
|
|
Packit Service |
706eca |
EXCEPTION (EX_FLOATING);
|
|
Packit Service |
706eca |
return RX_MAKE_STEPPED ();
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
static int
|
|
Packit Service |
706eca |
op_is_memory (const RX_Opcode_Decoded *rd, int i)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
switch (rd->op[i].type)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
case RX_Operand_Predec:
|
|
Packit Service |
706eca |
case RX_Operand_Postinc:
|
|
Packit Service |
706eca |
case RX_Operand_Indirect:
|
|
Packit Service |
706eca |
return 1;
|
|
Packit Service |
706eca |
default:
|
|
Packit Service |
706eca |
return 0;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#define OM(i) op_is_memory (opcode, i)
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#define DO_RETURN(x) { longjmp (decode_jmp_buf, x); }
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
int
|
|
Packit Service |
706eca |
decode_opcode ()
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
unsigned int uma=0, umb=0;
|
|
Packit Service |
706eca |
int ma=0, mb=0;
|
|
Packit Service |
706eca |
int opcode_size, v;
|
|
Packit Service |
706eca |
unsigned long long ll;
|
|
Packit Service |
706eca |
long long sll;
|
|
Packit Service |
706eca |
unsigned long opcode_pc;
|
|
Packit Service |
706eca |
RX_Data rx_data;
|
|
Packit Service |
706eca |
const RX_Opcode_Decoded *opcode;
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
unsigned long long prev_cycle_count;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
unsigned int tx;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
prev_cycle_count = regs.cycle_count;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
memory_source = 0;
|
|
Packit Service |
706eca |
memory_dest = 0;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
rx_cycles ++;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
maybe_get_mem_page (regs.r_pc);
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
opcode_pc = regs.r_pc;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
/* Note that we don't word-swap this point, there's no point. */
|
|
Packit Service |
706eca |
if (decode_cache_base[opcode_pc] == NULL)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
RX_Opcode_Decoded *opcode_w;
|
|
Packit Service |
706eca |
rx_data.dpc = opcode_pc;
|
|
Packit Service |
706eca |
opcode_w = decode_cache_base[opcode_pc] = calloc (1, sizeof (RX_Opcode_Decoded));
|
|
Packit Service |
706eca |
opcode_size = rx_decode_opcode (opcode_pc, opcode_w,
|
|
Packit Service |
706eca |
rx_get_byte, &rx_data);
|
|
Packit Service |
706eca |
opcode = opcode_w;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
opcode = decode_cache_base[opcode_pc];
|
|
Packit Service |
706eca |
opcode_size = opcode->n_bytes;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
if (branch_alignment_penalty)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
if ((regs.r_pc ^ (regs.r_pc + opcode_size - 1)) & ~7)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
tprintf("1 cycle branch alignment penalty\n");
|
|
Packit Service |
706eca |
cycles (branch_alignment_penalty);
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
branch_alignment_stalls ++;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
branch_alignment_penalty = 0;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
regs.r_pc += opcode_size;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
rx_flagmask = opcode->flags_s;
|
|
Packit Service |
706eca |
rx_flagand = ~(int)opcode->flags_0;
|
|
Packit Service |
706eca |
rx_flagor = opcode->flags_1;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
switch (opcode->id)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
case RXO_abs:
|
|
Packit Service |
706eca |
sll = GS ();
|
|
Packit Service |
706eca |
tprintf("|%lld| = ", sll);
|
|
Packit Service |
706eca |
if (sll < 0)
|
|
Packit Service |
706eca |
sll = -sll;
|
|
Packit Service |
706eca |
tprintf("%lld\n", sll);
|
|
Packit Service |
706eca |
PD (sll);
|
|
Packit Service |
706eca |
set_osz (sll, 4);
|
|
Packit Service |
706eca |
E (1);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_adc:
|
|
Packit Service |
706eca |
MATH_OP (+,carry);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_add:
|
|
Packit Service |
706eca |
MATH_OP (+,0);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_and:
|
|
Packit Service |
706eca |
LOGIC_OP (&);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_bclr:
|
|
Packit Service |
706eca |
ma = GD ();
|
|
Packit Service |
706eca |
mb = GS ();
|
|
Packit Service |
706eca |
if (opcode->op[0].type == RX_Operand_Register)
|
|
Packit Service |
706eca |
mb &= 0x1f;
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
mb &= 0x07;
|
|
Packit Service |
706eca |
ma &= ~(1 << mb);
|
|
Packit Service |
706eca |
PD (ma);
|
|
Packit Service |
706eca |
EBIT;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_bmcc:
|
|
Packit Service |
706eca |
ma = GD ();
|
|
Packit Service |
706eca |
mb = GS ();
|
|
Packit Service |
706eca |
if (opcode->op[0].type == RX_Operand_Register)
|
|
Packit Service |
706eca |
mb &= 0x1f;
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
mb &= 0x07;
|
|
Packit Service |
706eca |
if (GS2 ())
|
|
Packit Service |
706eca |
ma |= (1 << mb);
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
ma &= ~(1 << mb);
|
|
Packit Service |
706eca |
PD (ma);
|
|
Packit Service |
706eca |
EBIT;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_bnot:
|
|
Packit Service |
706eca |
ma = GD ();
|
|
Packit Service |
706eca |
mb = GS ();
|
|
Packit Service |
706eca |
if (opcode->op[0].type == RX_Operand_Register)
|
|
Packit Service |
706eca |
mb &= 0x1f;
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
mb &= 0x07;
|
|
Packit Service |
706eca |
ma ^= (1 << mb);
|
|
Packit Service |
706eca |
PD (ma);
|
|
Packit Service |
706eca |
EBIT;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_branch:
|
|
Packit Service |
706eca |
if (opcode->op[1].type == RX_Operand_None || GS())
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
SI old_pc = regs.r_pc;
|
|
Packit Service |
706eca |
int delta;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
regs.r_pc = GD();
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
delta = regs.r_pc - old_pc;
|
|
Packit Service |
706eca |
if (delta >= 0 && delta < 16
|
|
Packit Service |
706eca |
&& opcode_size > 1)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
tprintf("near forward branch bonus\n");
|
|
Packit Service |
706eca |
cycles (2);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
cycles (3);
|
|
Packit Service |
706eca |
branch_alignment_penalty = 1;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
branch_stalls ++;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
cycles (1);
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_branchrel:
|
|
Packit Service |
706eca |
if (opcode->op[1].type == RX_Operand_None || GS())
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int delta = GD();
|
|
Packit Service |
706eca |
regs.r_pc = opcode_pc + delta;
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
/* Note: specs say 3, chip says 2. */
|
|
Packit Service |
706eca |
if (delta >= 0 && delta < 16
|
|
Packit Service |
706eca |
&& opcode_size > 1)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
tprintf("near forward branch bonus\n");
|
|
Packit Service |
706eca |
cycles (2);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
cycles (3);
|
|
Packit Service |
706eca |
branch_alignment_penalty = 1;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
branch_stalls ++;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
cycles (1);
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_brk:
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int old_psw = regs.r_psw;
|
|
Packit Service |
706eca |
if (rx_in_gdb)
|
|
Packit Service |
706eca |
DO_RETURN (RX_MAKE_HIT_BREAK ());
|
|
Packit Service |
706eca |
if (regs.r_intb == 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
tprintf("BREAK hit, no vector table.\n");
|
|
Packit Service |
706eca |
DO_RETURN (RX_MAKE_EXITED(1));
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
|
|
Packit Service |
706eca |
pushpc (old_psw);
|
|
Packit Service |
706eca |
pushpc (regs.r_pc);
|
|
Packit Service |
706eca |
regs.r_pc = mem_get_si (regs.r_intb);
|
|
Packit Service |
706eca |
cycles(6);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_bset:
|
|
Packit Service |
706eca |
ma = GD ();
|
|
Packit Service |
706eca |
mb = GS ();
|
|
Packit Service |
706eca |
if (opcode->op[0].type == RX_Operand_Register)
|
|
Packit Service |
706eca |
mb &= 0x1f;
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
mb &= 0x07;
|
|
Packit Service |
706eca |
ma |= (1 << mb);
|
|
Packit Service |
706eca |
PD (ma);
|
|
Packit Service |
706eca |
EBIT;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_btst:
|
|
Packit Service |
706eca |
ma = GS ();
|
|
Packit Service |
706eca |
mb = GS2 ();
|
|
Packit Service |
706eca |
if (opcode->op[1].type == RX_Operand_Register)
|
|
Packit Service |
706eca |
mb &= 0x1f;
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
mb &= 0x07;
|
|
Packit Service |
706eca |
umb = ma & (1 << mb);
|
|
Packit Service |
706eca |
set_zc (! umb, umb);
|
|
Packit Service |
706eca |
EBIT;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_clrpsw:
|
|
Packit Service |
706eca |
v = 1 << opcode->op[0].reg;
|
|
Packit Service |
706eca |
if (FLAG_PM
|
|
Packit Service |
706eca |
&& (v == FLAGBIT_I
|
|
Packit Service |
706eca |
|| v == FLAGBIT_U))
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
regs.r_psw &= ~v;
|
|
Packit Service |
706eca |
cycles (1);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_div: /* d = d / s */
|
|
Packit Service |
706eca |
ma = GS();
|
|
Packit Service |
706eca |
mb = GD();
|
|
Packit Service |
706eca |
tprintf("%d / %d = ", mb, ma);
|
|
Packit Service |
706eca |
if (ma == 0 || (ma == -1 && (unsigned int) mb == 0x80000000))
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
tprintf("#NAN\n");
|
|
Packit Service |
706eca |
set_flags (FLAGBIT_O, FLAGBIT_O);
|
|
Packit Service |
706eca |
cycles (3);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
v = mb/ma;
|
|
Packit Service |
706eca |
tprintf("%d\n", v);
|
|
Packit Service |
706eca |
set_flags (FLAGBIT_O, 0);
|
|
Packit Service |
706eca |
PD (v);
|
|
Packit Service |
706eca |
div_cycles (mb, ma);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_divu: /* d = d / s */
|
|
Packit Service |
706eca |
uma = GS();
|
|
Packit Service |
706eca |
umb = GD();
|
|
Packit Service |
706eca |
tprintf("%u / %u = ", umb, uma);
|
|
Packit Service |
706eca |
if (uma == 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
tprintf("#NAN\n");
|
|
Packit Service |
706eca |
set_flags (FLAGBIT_O, FLAGBIT_O);
|
|
Packit Service |
706eca |
cycles (2);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
v = umb / uma;
|
|
Packit Service |
706eca |
tprintf("%u\n", v);
|
|
Packit Service |
706eca |
set_flags (FLAGBIT_O, 0);
|
|
Packit Service |
706eca |
PD (v);
|
|
Packit Service |
706eca |
divu_cycles (umb, uma);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_emul:
|
|
Packit Service |
706eca |
ma = GD ();
|
|
Packit Service |
706eca |
mb = GS ();
|
|
Packit Service |
706eca |
sll = (long long)ma * (long long)mb;
|
|
Packit Service |
706eca |
tprintf("%d * %d = %lld\n", ma, mb, sll);
|
|
Packit Service |
706eca |
put_reg (opcode->op[0].reg, sll);
|
|
Packit Service |
706eca |
put_reg (opcode->op[0].reg + 1, sll >> 32);
|
|
Packit Service |
706eca |
E2;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_emulu:
|
|
Packit Service |
706eca |
uma = GD ();
|
|
Packit Service |
706eca |
umb = GS ();
|
|
Packit Service |
706eca |
ll = (long long)uma * (long long)umb;
|
|
Packit Service |
706eca |
tprintf("%#x * %#x = %#llx\n", uma, umb, ll);
|
|
Packit Service |
706eca |
put_reg (opcode->op[0].reg, ll);
|
|
Packit Service |
706eca |
put_reg (opcode->op[0].reg + 1, ll >> 32);
|
|
Packit Service |
706eca |
E2;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_fadd:
|
|
Packit Service |
706eca |
FLOAT_OP (fadd);
|
|
Packit Service |
706eca |
E (4);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_fcmp:
|
|
Packit Service |
706eca |
ma = GD();
|
|
Packit Service |
706eca |
mb = GS();
|
|
Packit Service |
706eca |
FPCLEAR ();
|
|
Packit Service |
706eca |
rxfp_cmp (ma, mb);
|
|
Packit Service |
706eca |
FPCHECK ();
|
|
Packit Service |
706eca |
E (1);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_fdiv:
|
|
Packit Service |
706eca |
FLOAT_OP (fdiv);
|
|
Packit Service |
706eca |
E (16);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_fmul:
|
|
Packit Service |
706eca |
FLOAT_OP (fmul);
|
|
Packit Service |
706eca |
E (3);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_rtfi:
|
|
Packit Service |
706eca |
PRIVILEDGED ();
|
|
Packit Service |
706eca |
regs.r_psw = regs.r_bpsw;
|
|
Packit Service |
706eca |
regs.r_pc = regs.r_bpc;
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
regs.fast_return = 0;
|
|
Packit Service |
706eca |
cycles(3);
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_fsub:
|
|
Packit Service |
706eca |
FLOAT_OP (fsub);
|
|
Packit Service |
706eca |
E (4);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_ftoi:
|
|
Packit Service |
706eca |
ma = GS ();
|
|
Packit Service |
706eca |
FPCLEAR ();
|
|
Packit Service |
706eca |
mb = rxfp_ftoi (ma, FPRM_ZERO);
|
|
Packit Service |
706eca |
FPCHECK ();
|
|
Packit Service |
706eca |
PD (mb);
|
|
Packit Service |
706eca |
tprintf("(int) %g = %d\n", int2float(ma), mb);
|
|
Packit Service |
706eca |
set_sz (mb, 4);
|
|
Packit Service |
706eca |
E (2);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_int:
|
|
Packit Service |
706eca |
v = GS ();
|
|
Packit Service |
706eca |
if (v == 255)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int rc = rx_syscall (regs.r[5]);
|
|
Packit Service |
706eca |
if (! RX_STEPPED (rc))
|
|
Packit Service |
706eca |
DO_RETURN (rc);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int old_psw = regs.r_psw;
|
|
Packit Service |
706eca |
regs.r_psw &= ~(FLAGBIT_I | FLAGBIT_U | FLAGBIT_PM);
|
|
Packit Service |
706eca |
pushpc (old_psw);
|
|
Packit Service |
706eca |
pushpc (regs.r_pc);
|
|
Packit Service |
706eca |
regs.r_pc = mem_get_si (regs.r_intb + 4 * v);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
cycles (6);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_itof:
|
|
Packit Service |
706eca |
ma = GS ();
|
|
Packit Service |
706eca |
FPCLEAR ();
|
|
Packit Service |
706eca |
mb = rxfp_itof (ma, regs.r_fpsw);
|
|
Packit Service |
706eca |
FPCHECK ();
|
|
Packit Service |
706eca |
tprintf("(float) %d = %x\n", ma, mb);
|
|
Packit Service |
706eca |
PD (mb);
|
|
Packit Service |
706eca |
set_sz (ma, 4);
|
|
Packit Service |
706eca |
E (2);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_jsr:
|
|
Packit Service |
706eca |
case RXO_jsrrel:
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
int delta;
|
|
Packit Service |
706eca |
regs.m2m = 0;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
v = GD ();
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
regs.link_register = regs.r_pc;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
pushpc (get_reg (pc));
|
|
Packit Service |
706eca |
if (opcode->id == RXO_jsrrel)
|
|
Packit Service |
706eca |
v += regs.r_pc;
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
delta = v - regs.r_pc;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
put_reg (pc, v);
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
/* Note: docs say 3, chip says 2 */
|
|
Packit Service |
706eca |
if (delta >= 0 && delta < 16)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
tprintf ("near forward jsr bonus\n");
|
|
Packit Service |
706eca |
cycles (2);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
branch_alignment_penalty = 1;
|
|
Packit Service |
706eca |
cycles (3);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
regs.fast_return = 1;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_machi:
|
|
Packit Service |
706eca |
ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(GS2 () >> 16);
|
|
Packit Service |
706eca |
ll <<= 16;
|
|
Packit Service |
706eca |
put_reg64 (acc64, ll + regs.r_acc);
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_maclo:
|
|
Packit Service |
706eca |
ll = (long long)(signed short)(GS()) * (long long)(signed short)(GS2 ());
|
|
Packit Service |
706eca |
ll <<= 16;
|
|
Packit Service |
706eca |
put_reg64 (acc64, ll + regs.r_acc);
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_max:
|
|
Packit Service |
706eca |
mb = GS();
|
|
Packit Service |
706eca |
ma = GD();
|
|
Packit Service |
706eca |
if (ma > mb)
|
|
Packit Service |
706eca |
PD (ma);
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
PD (mb);
|
|
Packit Service |
706eca |
E (1);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_min:
|
|
Packit Service |
706eca |
mb = GS();
|
|
Packit Service |
706eca |
ma = GD();
|
|
Packit Service |
706eca |
if (ma < mb)
|
|
Packit Service |
706eca |
PD (ma);
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
PD (mb);
|
|
Packit Service |
706eca |
E (1);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_mov:
|
|
Packit Service |
706eca |
v = GS ();
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
if (opcode->op[1].type == RX_Operand_Register
|
|
Packit Service |
706eca |
&& opcode->op[1].reg == 17 /* PC */)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
/* Special case. We want the address of the insn, not the
|
|
Packit Service |
706eca |
address of the next insn. */
|
|
Packit Service |
706eca |
v = opcode_pc;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
if (opcode->op[0].type == RX_Operand_Register
|
|
Packit Service |
706eca |
&& opcode->op[0].reg == 16 /* PSW */)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
/* Special case, LDC and POPC can't ever modify PM. */
|
|
Packit Service |
706eca |
int pm = regs.r_psw & FLAGBIT_PM;
|
|
Packit Service |
706eca |
v &= ~ FLAGBIT_PM;
|
|
Packit Service |
706eca |
v |= pm;
|
|
Packit Service |
706eca |
if (pm)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
|
|
Packit Service |
706eca |
v |= pm;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
if (FLAG_PM)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
/* various things can't be changed in user mode. */
|
|
Packit Service |
706eca |
if (opcode->op[0].type == RX_Operand_Register)
|
|
Packit Service |
706eca |
if (opcode->op[0].reg == 32)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
v &= ~ (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
|
|
Packit Service |
706eca |
v |= regs.r_psw & (FLAGBIT_I | FLAGBIT_U | FLAGBITS_IPL);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
if (opcode->op[0].reg == 34 /* ISP */
|
|
Packit Service |
706eca |
|| opcode->op[0].reg == 37 /* BPSW */
|
|
Packit Service |
706eca |
|| opcode->op[0].reg == 39 /* INTB */
|
|
Packit Service |
706eca |
|| opcode->op[0].reg == 38 /* VCT */)
|
|
Packit Service |
706eca |
/* These are ignored. */
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
if (OM(0) && OM(1))
|
|
Packit Service |
706eca |
cycles (2);
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
cycles (1);
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
PD (v);
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
if ((opcode->op[0].type == RX_Operand_Predec
|
|
Packit Service |
706eca |
&& opcode->op[1].type == RX_Operand_Register)
|
|
Packit Service |
706eca |
|| (opcode->op[0].type == RX_Operand_Postinc
|
|
Packit Service |
706eca |
&& opcode->op[1].type == RX_Operand_Register))
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
/* Special case: push reg doesn't cause a memory stall. */
|
|
Packit Service |
706eca |
memory_dest = 0;
|
|
Packit Service |
706eca |
tprintf("push special case\n");
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
set_sz (v, DSZ());
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_movbi:
|
|
Packit Service |
706eca |
PD (GS ());
|
|
Packit Service |
706eca |
cycles (1);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_movbir:
|
|
Packit Service |
706eca |
PS (GD ());
|
|
Packit Service |
706eca |
cycles (1);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_mul:
|
|
Packit Service |
706eca |
v = US2 ();
|
|
Packit Service |
706eca |
ll = (unsigned long long) US1() * (unsigned long long) v;
|
|
Packit Service |
706eca |
PD(ll);
|
|
Packit Service |
706eca |
E (1);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_mulhi:
|
|
Packit Service |
706eca |
v = GS2 ();
|
|
Packit Service |
706eca |
ll = (long long)(signed short)(GS() >> 16) * (long long)(signed short)(v >> 16);
|
|
Packit Service |
706eca |
ll <<= 16;
|
|
Packit Service |
706eca |
put_reg64 (acc64, ll);
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_mullo:
|
|
Packit Service |
706eca |
v = GS2 ();
|
|
Packit Service |
706eca |
ll = (long long)(signed short)(GS()) * (long long)(signed short)(v);
|
|
Packit Service |
706eca |
ll <<= 16;
|
|
Packit Service |
706eca |
put_reg64 (acc64, ll);
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_mvfachi:
|
|
Packit Service |
706eca |
PD (get_reg (acchi));
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_mvfaclo:
|
|
Packit Service |
706eca |
PD (get_reg (acclo));
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_mvfacmi:
|
|
Packit Service |
706eca |
PD (get_reg (accmi));
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_mvtachi:
|
|
Packit Service |
706eca |
put_reg (acchi, GS ());
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_mvtaclo:
|
|
Packit Service |
706eca |
put_reg (acclo, GS ());
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_mvtipl:
|
|
Packit Service |
706eca |
regs.r_psw &= ~ FLAGBITS_IPL;
|
|
Packit Service |
706eca |
regs.r_psw |= (GS () << FLAGSHIFT_IPL) & FLAGBITS_IPL;
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_nop:
|
|
Packit Service |
706eca |
case RXO_nop2:
|
|
Packit Service |
706eca |
case RXO_nop3:
|
|
Packit Service |
706eca |
case RXO_nop4:
|
|
Packit Service |
706eca |
case RXO_nop5:
|
|
Packit Service |
706eca |
case RXO_nop6:
|
|
Packit Service |
706eca |
case RXO_nop7:
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_or:
|
|
Packit Service |
706eca |
LOGIC_OP (|);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_popm:
|
|
Packit Service |
706eca |
/* POPM cannot pop R0 (sp). */
|
|
Packit Service |
706eca |
if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
|
|
Packit Service |
706eca |
EXCEPTION (EX_UNDEFINED);
|
|
Packit Service |
706eca |
if (opcode->op[1].reg >= opcode->op[2].reg)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
regs.r_pc = opcode_pc;
|
|
Packit Service |
706eca |
DO_RETURN (RX_MAKE_STOPPED (SIGILL));
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
for (v = opcode->op[1].reg; v <= opcode->op[2].reg; v++)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
cycles (1);
|
|
Packit Service |
706eca |
RLD (v);
|
|
Packit Service |
706eca |
put_reg (v, pop ());
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_pushm:
|
|
Packit Service |
706eca |
/* PUSHM cannot push R0 (sp). */
|
|
Packit Service |
706eca |
if (opcode->op[1].reg == 0 || opcode->op[2].reg == 0)
|
|
Packit Service |
706eca |
EXCEPTION (EX_UNDEFINED);
|
|
Packit Service |
706eca |
if (opcode->op[1].reg >= opcode->op[2].reg)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
regs.r_pc = opcode_pc;
|
|
Packit Service |
706eca |
return RX_MAKE_STOPPED (SIGILL);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
for (v = opcode->op[2].reg; v >= opcode->op[1].reg; v--)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
RL (v);
|
|
Packit Service |
706eca |
push (get_reg (v));
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
cycles (opcode->op[2].reg - opcode->op[1].reg + 1);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_racw:
|
|
Packit Service |
706eca |
ll = get_reg64 (acc64) << GS ();
|
|
Packit Service |
706eca |
ll += 0x80000000ULL;
|
|
Packit Service |
706eca |
if ((signed long long)ll > (signed long long)0x00007fff00000000ULL)
|
|
Packit Service |
706eca |
ll = 0x00007fff00000000ULL;
|
|
Packit Service |
706eca |
else if ((signed long long)ll < (signed long long)0xffff800000000000ULL)
|
|
Packit Service |
706eca |
ll = 0xffff800000000000ULL;
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
ll &= 0xffffffff00000000ULL;
|
|
Packit Service |
706eca |
put_reg64 (acc64, ll);
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_rte:
|
|
Packit Service |
706eca |
PRIVILEDGED ();
|
|
Packit Service |
706eca |
regs.r_pc = poppc ();
|
|
Packit Service |
706eca |
regs.r_psw = poppc ();
|
|
Packit Service |
706eca |
if (FLAG_PM)
|
|
Packit Service |
706eca |
regs.r_psw |= FLAGBIT_U;
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
regs.fast_return = 0;
|
|
Packit Service |
706eca |
cycles (6);
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_revl:
|
|
Packit Service |
706eca |
uma = GS ();
|
|
Packit Service |
706eca |
umb = (((uma >> 24) & 0xff)
|
|
Packit Service |
706eca |
| ((uma >> 8) & 0xff00)
|
|
Packit Service |
706eca |
| ((uma << 8) & 0xff0000)
|
|
Packit Service |
706eca |
| ((uma << 24) & 0xff000000UL));
|
|
Packit Service |
706eca |
PD (umb);
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_revw:
|
|
Packit Service |
706eca |
uma = GS ();
|
|
Packit Service |
706eca |
umb = (((uma >> 8) & 0x00ff00ff)
|
|
Packit Service |
706eca |
| ((uma << 8) & 0xff00ff00UL));
|
|
Packit Service |
706eca |
PD (umb);
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_rmpa:
|
|
Packit Service |
706eca |
RL(4);
|
|
Packit Service |
706eca |
RL(5);
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx = regs.r[3];
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
while (regs.r[3] != 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
long long tmp;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
switch (opcode->size)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
case RX_Long:
|
|
Packit Service |
706eca |
ma = mem_get_si (regs.r[1]);
|
|
Packit Service |
706eca |
mb = mem_get_si (regs.r[2]);
|
|
Packit Service |
706eca |
regs.r[1] += 4;
|
|
Packit Service |
706eca |
regs.r[2] += 4;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
case RX_Word:
|
|
Packit Service |
706eca |
ma = sign_ext (mem_get_hi (regs.r[1]), 16);
|
|
Packit Service |
706eca |
mb = sign_ext (mem_get_hi (regs.r[2]), 16);
|
|
Packit Service |
706eca |
regs.r[1] += 2;
|
|
Packit Service |
706eca |
regs.r[2] += 2;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
case RX_Byte:
|
|
Packit Service |
706eca |
ma = sign_ext (mem_get_qi (regs.r[1]), 8);
|
|
Packit Service |
706eca |
mb = sign_ext (mem_get_qi (regs.r[2]), 8);
|
|
Packit Service |
706eca |
regs.r[1] += 1;
|
|
Packit Service |
706eca |
regs.r[2] += 1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
default:
|
|
Packit Service |
706eca |
abort ();
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
/* We do the multiply as a signed value. */
|
|
Packit Service |
706eca |
sll = (long long)ma * (long long)mb;
|
|
Packit Service |
706eca |
tprintf(" %016llx = %d * %d\n", sll, ma, mb);
|
|
Packit Service |
706eca |
/* but we do the sum as unsigned, while sign extending the operands. */
|
|
Packit Service |
706eca |
tmp = regs.r[4] + (sll & 0xffffffffUL);
|
|
Packit Service |
706eca |
regs.r[4] = tmp & 0xffffffffUL;
|
|
Packit Service |
706eca |
tmp >>= 32;
|
|
Packit Service |
706eca |
sll >>= 32;
|
|
Packit Service |
706eca |
tmp += regs.r[5] + (sll & 0xffffffffUL);
|
|
Packit Service |
706eca |
regs.r[5] = tmp & 0xffffffffUL;
|
|
Packit Service |
706eca |
tmp >>= 32;
|
|
Packit Service |
706eca |
sll >>= 32;
|
|
Packit Service |
706eca |
tmp += regs.r[6] + (sll & 0xffffffffUL);
|
|
Packit Service |
706eca |
regs.r[6] = tmp & 0xffffffffUL;
|
|
Packit Service |
706eca |
tprintf("%08lx\033[36m%08lx\033[0m%08lx\n",
|
|
Packit Service |
706eca |
(unsigned long) regs.r[6],
|
|
Packit Service |
706eca |
(unsigned long) regs.r[5],
|
|
Packit Service |
706eca |
(unsigned long) regs.r[4]);
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
if (regs.r[6] & 0x00008000)
|
|
Packit Service |
706eca |
regs.r[6] |= 0xffff0000UL;
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
regs.r[6] &= 0x0000ffff;
|
|
Packit Service |
706eca |
ma = (regs.r[6] & 0x80000000UL) ? FLAGBIT_S : 0;
|
|
Packit Service |
706eca |
if (regs.r[6] != 0 && regs.r[6] != 0xffffffffUL)
|
|
Packit Service |
706eca |
set_flags (FLAGBIT_O|FLAGBIT_S, ma | FLAGBIT_O);
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
set_flags (FLAGBIT_O|FLAGBIT_S, ma);
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
switch (opcode->size)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
case RX_Long:
|
|
Packit Service |
706eca |
cycles (6 + 4 * tx);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
case RX_Word:
|
|
Packit Service |
706eca |
cycles (6 + 5 * (tx / 2) + 4 * (tx % 2));
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
case RX_Byte:
|
|
Packit Service |
706eca |
cycles (6 + 7 * (tx / 4) + 4 * (tx % 4));
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
default:
|
|
Packit Service |
706eca |
abort ();
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_rolc:
|
|
Packit Service |
706eca |
v = GD ();
|
|
Packit Service |
706eca |
ma = v & 0x80000000UL;
|
|
Packit Service |
706eca |
v <<= 1;
|
|
Packit Service |
706eca |
v |= carry;
|
|
Packit Service |
706eca |
set_szc (v, 4, ma);
|
|
Packit Service |
706eca |
PD (v);
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_rorc:
|
|
Packit Service |
706eca |
uma = GD ();
|
|
Packit Service |
706eca |
mb = uma & 1;
|
|
Packit Service |
706eca |
uma >>= 1;
|
|
Packit Service |
706eca |
uma |= (carry ? 0x80000000UL : 0);
|
|
Packit Service |
706eca |
set_szc (uma, 4, mb);
|
|
Packit Service |
706eca |
PD (uma);
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_rotl:
|
|
Packit Service |
706eca |
mb = GS ();
|
|
Packit Service |
706eca |
uma = GD ();
|
|
Packit Service |
706eca |
if (mb)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
uma = (uma << mb) | (uma >> (32-mb));
|
|
Packit Service |
706eca |
mb = uma & 1;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
set_szc (uma, 4, mb);
|
|
Packit Service |
706eca |
PD (uma);
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_rotr:
|
|
Packit Service |
706eca |
mb = GS ();
|
|
Packit Service |
706eca |
uma = GD ();
|
|
Packit Service |
706eca |
if (mb)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
uma = (uma >> mb) | (uma << (32-mb));
|
|
Packit Service |
706eca |
mb = uma & 0x80000000;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
set_szc (uma, 4, mb);
|
|
Packit Service |
706eca |
PD (uma);
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_round:
|
|
Packit Service |
706eca |
ma = GS ();
|
|
Packit Service |
706eca |
FPCLEAR ();
|
|
Packit Service |
706eca |
mb = rxfp_ftoi (ma, regs.r_fpsw);
|
|
Packit Service |
706eca |
FPCHECK ();
|
|
Packit Service |
706eca |
PD (mb);
|
|
Packit Service |
706eca |
tprintf("(int) %g = %d\n", int2float(ma), mb);
|
|
Packit Service |
706eca |
set_sz (mb, 4);
|
|
Packit Service |
706eca |
E (2);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_rts:
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
int cyc = 5;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
regs.r_pc = poppc ();
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
/* Note: specs say 5, chip says 3. */
|
|
Packit Service |
706eca |
if (regs.fast_return && regs.link_register == regs.r_pc)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
fast_returns ++;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
tprintf("fast return bonus\n");
|
|
Packit Service |
706eca |
cyc -= 2;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
cycles (cyc);
|
|
Packit Service |
706eca |
regs.fast_return = 0;
|
|
Packit Service |
706eca |
branch_alignment_penalty = 1;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_rtsd:
|
|
Packit Service |
706eca |
if (opcode->op[2].type == RX_Operand_Register)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int i;
|
|
Packit Service |
706eca |
/* RTSD cannot pop R0 (sp). */
|
|
Packit Service |
706eca |
put_reg (0, get_reg (0) + GS() - (opcode->op[0].reg-opcode->op[2].reg+1)*4);
|
|
Packit Service |
706eca |
if (opcode->op[2].reg == 0)
|
|
Packit Service |
706eca |
EXCEPTION (EX_UNDEFINED);
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx = opcode->op[0].reg - opcode->op[2].reg + 1;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
for (i = opcode->op[2].reg; i <= opcode->op[0].reg; i ++)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
RLD (i);
|
|
Packit Service |
706eca |
put_reg (i, pop ());
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx = 0;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
put_reg (0, get_reg (0) + GS());
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
put_reg (pc, poppc());
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
if (regs.fast_return && regs.link_register == regs.r_pc)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
tprintf("fast return bonus\n");
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
fast_returns ++;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
cycles (tx < 3 ? 3 : tx + 1);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
cycles (tx < 5 ? 5 : tx + 1);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
regs.fast_return = 0;
|
|
Packit Service |
706eca |
branch_alignment_penalty = 1;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_sat:
|
|
Packit Service |
706eca |
if (FLAG_O && FLAG_S)
|
|
Packit Service |
706eca |
PD (0x7fffffffUL);
|
|
Packit Service |
706eca |
else if (FLAG_O && ! FLAG_S)
|
|
Packit Service |
706eca |
PD (0x80000000UL);
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_satr:
|
|
Packit Service |
706eca |
if (FLAG_O && ! FLAG_S)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
put_reg (6, 0x0);
|
|
Packit Service |
706eca |
put_reg (5, 0x7fffffff);
|
|
Packit Service |
706eca |
put_reg (4, 0xffffffff);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
else if (FLAG_O && FLAG_S)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
put_reg (6, 0xffffffff);
|
|
Packit Service |
706eca |
put_reg (5, 0x80000000);
|
|
Packit Service |
706eca |
put_reg (4, 0x0);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_sbb:
|
|
Packit Service |
706eca |
MATH_OP (-, ! carry);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_sccnd:
|
|
Packit Service |
706eca |
if (GS())
|
|
Packit Service |
706eca |
PD (1);
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
PD (0);
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_scmpu:
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx = regs.r[3];
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
while (regs.r[3] != 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
uma = mem_get_qi (regs.r[1] ++);
|
|
Packit Service |
706eca |
umb = mem_get_qi (regs.r[2] ++);
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
if (uma != umb || uma == 0)
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
if (uma == umb)
|
|
Packit Service |
706eca |
set_zc (1, 1);
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
set_zc (0, ((int)uma - (int)umb) >= 0);
|
|
Packit Service |
706eca |
cycles (2 + 4 * (tx / 4) + 4 * (tx % 4));
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_setpsw:
|
|
Packit Service |
706eca |
v = 1 << opcode->op[0].reg;
|
|
Packit Service |
706eca |
if (FLAG_PM
|
|
Packit Service |
706eca |
&& (v == FLAGBIT_I
|
|
Packit Service |
706eca |
|| v == FLAGBIT_U))
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
regs.r_psw |= v;
|
|
Packit Service |
706eca |
cycles (1);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_smovb:
|
|
Packit Service |
706eca |
RL (3);
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx = regs.r[3];
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
while (regs.r[3])
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
uma = mem_get_qi (regs.r[2] --);
|
|
Packit Service |
706eca |
mem_put_qi (regs.r[1]--, uma);
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
if (tx > 3)
|
|
Packit Service |
706eca |
cycles (6 + 3 * (tx / 4) + 3 * (tx % 4));
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
cycles (2 + 3 * (tx % 4));
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_smovf:
|
|
Packit Service |
706eca |
RL (3);
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx = regs.r[3];
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
while (regs.r[3])
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
uma = mem_get_qi (regs.r[2] ++);
|
|
Packit Service |
706eca |
mem_put_qi (regs.r[1]++, uma);
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_smovu:
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx = regs.r[3];
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
while (regs.r[3] != 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
uma = mem_get_qi (regs.r[2] ++);
|
|
Packit Service |
706eca |
mem_put_qi (regs.r[1]++, uma);
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
if (uma == 0)
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
cycles (2 + 3 * (int)(tx / 4) + 3 * (tx % 4));
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_shar: /* d = ma >> mb */
|
|
Packit Service |
706eca |
SHIFT_OP (sll, int, mb, >>=, 1);
|
|
Packit Service |
706eca |
E (1);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_shll: /* d = ma << mb */
|
|
Packit Service |
706eca |
SHIFT_OP (ll, int, mb, <<=, 0x80000000UL);
|
|
Packit Service |
706eca |
E (1);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_shlr: /* d = ma >> mb */
|
|
Packit Service |
706eca |
SHIFT_OP (ll, unsigned int, mb, >>=, 1);
|
|
Packit Service |
706eca |
E (1);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_sstr:
|
|
Packit Service |
706eca |
RL (3);
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx = regs.r[3];
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
switch (opcode->size)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
case RX_Long:
|
|
Packit Service |
706eca |
while (regs.r[3] != 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
mem_put_si (regs.r[1], regs.r[2]);
|
|
Packit Service |
706eca |
regs.r[1] += 4;
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
cycles (2 + tx);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
case RX_Word:
|
|
Packit Service |
706eca |
while (regs.r[3] != 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
mem_put_hi (regs.r[1], regs.r[2]);
|
|
Packit Service |
706eca |
regs.r[1] += 2;
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
cycles (2 + (int)(tx / 2) + tx % 2);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
case RX_Byte:
|
|
Packit Service |
706eca |
while (regs.r[3] != 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
mem_put_qi (regs.r[1], regs.r[2]);
|
|
Packit Service |
706eca |
regs.r[1] ++;
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
cycles (2 + (int)(tx / 4) + tx % 4);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
default:
|
|
Packit Service |
706eca |
abort ();
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_stcc:
|
|
Packit Service |
706eca |
if (GS2())
|
|
Packit Service |
706eca |
PD (GS ());
|
|
Packit Service |
706eca |
E1;
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_stop:
|
|
Packit Service |
706eca |
PRIVILEDGED ();
|
|
Packit Service |
706eca |
regs.r_psw |= FLAGBIT_I;
|
|
Packit Service |
706eca |
DO_RETURN (RX_MAKE_STOPPED(0));
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_sub:
|
|
Packit Service |
706eca |
MATH_OP (-, 0);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_suntil:
|
|
Packit Service |
706eca |
RL(3);
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx = 0;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
if (regs.r[3] == 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
cycles (3);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
switch (opcode->size)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
case RX_Long:
|
|
Packit Service |
706eca |
uma = get_reg (2);
|
|
Packit Service |
706eca |
while (regs.r[3] != 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
umb = mem_get_si (get_reg (1));
|
|
Packit Service |
706eca |
regs.r[1] += 4;
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx ++;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
if (umb == uma)
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
cycles (3 + 3 * tx);
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
case RX_Word:
|
|
Packit Service |
706eca |
uma = get_reg (2) & 0xffff;
|
|
Packit Service |
706eca |
while (regs.r[3] != 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
umb = mem_get_hi (get_reg (1));
|
|
Packit Service |
706eca |
regs.r[1] += 2;
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx ++;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
if (umb == uma)
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
case RX_Byte:
|
|
Packit Service |
706eca |
uma = get_reg (2) & 0xff;
|
|
Packit Service |
706eca |
while (regs.r[3] != 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
umb = mem_get_qi (regs.r[1]);
|
|
Packit Service |
706eca |
regs.r[1] += 1;
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx ++;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
if (umb == uma)
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
default:
|
|
Packit Service |
706eca |
abort();
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
if (uma == umb)
|
|
Packit Service |
706eca |
set_zc (1, 1);
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
set_zc (0, ((int)uma - (int)umb) >= 0);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_swhile:
|
|
Packit Service |
706eca |
RL(3);
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx = 0;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
if (regs.r[3] == 0)
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
switch (opcode->size)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
case RX_Long:
|
|
Packit Service |
706eca |
uma = get_reg (2);
|
|
Packit Service |
706eca |
while (regs.r[3] != 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
umb = mem_get_si (get_reg (1));
|
|
Packit Service |
706eca |
regs.r[1] += 4;
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx ++;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
if (umb != uma)
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
cycles (3 + 3 * tx);
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
case RX_Word:
|
|
Packit Service |
706eca |
uma = get_reg (2) & 0xffff;
|
|
Packit Service |
706eca |
while (regs.r[3] != 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
umb = mem_get_hi (get_reg (1));
|
|
Packit Service |
706eca |
regs.r[1] += 2;
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx ++;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
if (umb != uma)
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
cycles (3 + 3 * (tx / 2) + 3 * (tx % 2));
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
case RX_Byte:
|
|
Packit Service |
706eca |
uma = get_reg (2) & 0xff;
|
|
Packit Service |
706eca |
while (regs.r[3] != 0)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
regs.r[3] --;
|
|
Packit Service |
706eca |
umb = mem_get_qi (regs.r[1]);
|
|
Packit Service |
706eca |
regs.r[1] += 1;
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
tx ++;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
if (umb != uma)
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
cycles (3 + 3 * (tx / 4) + 3 * (tx % 4));
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
default:
|
|
Packit Service |
706eca |
abort();
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
if (uma == umb)
|
|
Packit Service |
706eca |
set_zc (1, 1);
|
|
Packit Service |
706eca |
else
|
|
Packit Service |
706eca |
set_zc (0, ((int)uma - (int)umb) >= 0);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_wait:
|
|
Packit Service |
706eca |
PRIVILEDGED ();
|
|
Packit Service |
706eca |
regs.r_psw |= FLAGBIT_I;
|
|
Packit Service |
706eca |
DO_RETURN (RX_MAKE_STOPPED(0));
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_xchg:
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
regs.m2m = 0;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
v = GS (); /* This is the memory operand, if any. */
|
|
Packit Service |
706eca |
PS (GD ()); /* and this may change the address register. */
|
|
Packit Service |
706eca |
PD (v);
|
|
Packit Service |
706eca |
E2;
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
/* all M cycles happen during xchg's cycles. */
|
|
Packit Service |
706eca |
memory_dest = 0;
|
|
Packit Service |
706eca |
memory_source = 0;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
case RXO_xor:
|
|
Packit Service |
706eca |
LOGIC_OP (^);
|
|
Packit Service |
706eca |
break;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
default:
|
|
Packit Service |
706eca |
EXCEPTION (EX_UNDEFINED);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
regs.m2m = 0;
|
|
Packit Service |
706eca |
if (memory_source)
|
|
Packit Service |
706eca |
regs.m2m |= M2M_SRC;
|
|
Packit Service |
706eca |
if (memory_dest)
|
|
Packit Service |
706eca |
regs.m2m |= M2M_DST;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
regs.rt = new_rt;
|
|
Packit Service |
706eca |
new_rt = -1;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
if (prev_cycle_count == regs.cycle_count)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
printf("Cycle count not updated! id %s\n", id_names[opcode->id]);
|
|
Packit Service |
706eca |
abort ();
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
if (running_benchmark)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
int omap = op_lookup (opcode->op[0].type, opcode->op[1].type, opcode->op[2].type);
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
cycles_per_id[opcode->id][omap] += regs.cycle_count - prev_cycle_count;
|
|
Packit Service |
706eca |
times_per_id[opcode->id][omap] ++;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
times_per_pair[prev_opcode_id][po0][opcode->id][omap] ++;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
prev_opcode_id = opcode->id;
|
|
Packit Service |
706eca |
po0 = omap;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
return RX_MAKE_STEPPED ();
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
void
|
|
Packit Service |
706eca |
reset_pipeline_stats (void)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
memset (cycles_per_id, 0, sizeof(cycles_per_id));
|
|
Packit Service |
706eca |
memset (times_per_id, 0, sizeof(times_per_id));
|
|
Packit Service |
706eca |
memory_stalls = 0;
|
|
Packit Service |
706eca |
register_stalls = 0;
|
|
Packit Service |
706eca |
branch_stalls = 0;
|
|
Packit Service |
706eca |
branch_alignment_stalls = 0;
|
|
Packit Service |
706eca |
fast_returns = 0;
|
|
Packit Service |
706eca |
memset (times_per_pair, 0, sizeof(times_per_pair));
|
|
Packit Service |
706eca |
running_benchmark = 1;
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
benchmark_start_cycle = regs.cycle_count;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
void
|
|
Packit Service |
706eca |
halt_pipeline_stats (void)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
running_benchmark = 0;
|
|
Packit Service |
706eca |
benchmark_end_cycle = regs.cycle_count;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
void
|
|
Packit Service |
706eca |
pipeline_stats (void)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
int i, o1;
|
|
Packit Service |
706eca |
int p, p1;
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_ACCURATE
|
|
Packit Service |
706eca |
if (verbose == 1)
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
printf ("cycles: %llu\n", regs.cycle_count);
|
|
Packit Service |
706eca |
return;
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
printf ("cycles: %13s\n", comma (regs.cycle_count));
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
#ifdef CYCLE_STATS
|
|
Packit Service |
706eca |
if (benchmark_start_cycle)
|
|
Packit Service |
706eca |
printf ("bmark: %13s\n", comma (benchmark_end_cycle - benchmark_start_cycle));
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
printf("\n");
|
|
Packit Service |
706eca |
for (i = 0; i < N_RXO; i++)
|
|
Packit Service |
706eca |
for (o1 = 0; o1 < N_MAP; o1 ++)
|
|
Packit Service |
706eca |
if (times_per_id[i][o1])
|
|
Packit Service |
706eca |
printf("%13s %13s %7.2f %s %s\n",
|
|
Packit Service |
706eca |
comma (cycles_per_id[i][o1]),
|
|
Packit Service |
706eca |
comma (times_per_id[i][o1]),
|
|
Packit Service |
706eca |
(double)cycles_per_id[i][o1] / times_per_id[i][o1],
|
|
Packit Service |
706eca |
op_cache_string(o1),
|
|
Packit Service |
706eca |
id_names[i]+4);
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
printf("\n");
|
|
Packit Service |
706eca |
for (p = 0; p < N_RXO; p ++)
|
|
Packit Service |
706eca |
for (p1 = 0; p1 < N_MAP; p1 ++)
|
|
Packit Service |
706eca |
for (i = 0; i < N_RXO; i ++)
|
|
Packit Service |
706eca |
for (o1 = 0; o1 < N_MAP; o1 ++)
|
|
Packit Service |
706eca |
if (times_per_pair[p][p1][i][o1])
|
|
Packit Service |
706eca |
{
|
|
Packit Service |
706eca |
printf("%13s %s %-9s -> %s %s\n",
|
|
Packit Service |
706eca |
comma (times_per_pair[p][p1][i][o1]),
|
|
Packit Service |
706eca |
op_cache_string(p1),
|
|
Packit Service |
706eca |
id_names[p]+4,
|
|
Packit Service |
706eca |
op_cache_string(o1),
|
|
Packit Service |
706eca |
id_names[i]+4);
|
|
Packit Service |
706eca |
}
|
|
Packit Service |
706eca |
|
|
Packit Service |
706eca |
printf("\n");
|
|
Packit Service |
706eca |
printf("%13s memory stalls\n", comma (memory_stalls));
|
|
Packit Service |
706eca |
printf("%13s register stalls\n", comma (register_stalls));
|
|
Packit Service |
706eca |
printf("%13s branches taken (non-return)\n", comma (branch_stalls));
|
|
Packit Service |
706eca |
printf("%13s branch alignment stalls\n", comma (branch_alignment_stalls));
|
|
Packit Service |
706eca |
printf("%13s fast returns\n", comma (fast_returns));
|
|
Packit Service |
706eca |
#endif
|
|
Packit Service |
706eca |
}
|