qemu-e2k/target/e2k/helper_int.c

343 lines
8.7 KiB
C

#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/timer.h"
#include "cpu.h"
#include "helper-tcg.h"
#include "exec/exec-all.h"
#include "qemu/host-utils.h"
#include "exec/helper-proto.h"
uint64_t HELPER(sxt)(uint32_t s1, uint32_t s2)
{
int size = MIN(32, 8 << (s1 & 3));
return s1 & 4 ? extract32(s2, 0, size) : sextract64(s2, 0, size);
}
static uint64_t cr_read(CPUE2KState *env, size_t offset)
{
target_ulong addr = env->pcsp.base + env->pcsp.index + offset;
return cpu_ldq_le_data(env, addr);
}
uint64_t HELPER(state_reg_get)(CPUE2KState *env, int index)
{
switch (index) {
case SR_PSR: return env->psr;
case SR_WD: return env_wd_get(env);
case SR_CORE_MODE: return env->core_mode;
case SR_CWD: return 0; /* ignore */
case SR_PSP_HI: return env->psp.hi;
case SR_PSP_LO: return env->psp.lo;
case SR_PSHTP: return 0; /* ignore */
case SR_PCSP_HI: return env->pcsp.hi;
case SR_PCSP_LO: return env->pcsp.lo;
case SR_PCSHTP: return 0; /* ignore */
case SR_CTPR1: return env->ctprs[0].raw;
case SR_CTPR2: return env->ctprs[1].raw;
case SR_CTPR3: return env->ctprs[2].raw;
case SR_SBR: return env->sbr;
case SR_CUTD:
case SR_EIR:
case SR_TSD: goto todo;
case SR_CUIR: return env->cuir;
case SR_OSCUD_HI: return env->oscud.hi;
case SR_OSCUD_LO: return env->oscud.lo;
case SR_OSGD_HI: return env->osgd.hi;
case SR_OSGD_LO: return env->osgd.lo;
case SR_OSEM: goto todo;
case SR_USD_HI: return env->usd.hi;
case SR_USD_LO: return env->usd.lo;
case SR_TR: goto todo;
case SR_OSR0: return env->osr0;
case SR_CUD_HI: return env->cud.hi;
case SR_CUD_LO: return env->cud.lo;
case SR_GD_HI: return env->gd.hi;
case SR_GD_LO: return env->gd.lo;
case SR_CS_HI: return env->cs.hi;
case SR_CS_LO: return env->cs.lo;
case SR_DS_HI: return env->ds.hi;
case SR_DS_LO: return env->ds.lo;
case SR_ES_HI: return env->es.hi;
case SR_ES_LO: return env->es.lo;
case SR_FS_HI: return env->fs.hi;
case SR_FS_LO: return env->fs.lo;
case SR_GS_HI: return env->gs.hi;
case SR_GS_LO: return env->gs.lo;
case SR_SS_HI: return env->ss.hi;
case SR_SS_LO: return env->ss.lo;
case SR_DIBCR:
case SR_DIMCR:
case SR_DIBSR:
case SR_DTCR:
case SR_DIBAR0:
case SR_DIBAR1:
case SR_DIBAR2:
case SR_DIBAR3:
case SR_DIMAR0:
case SR_DIMAR1:
case SR_DTRAF:
case SR_DTART: goto todo;
case SR_CR0_HI: return cr_read(env, offsetof(E2KCrs, cr0_hi));
case SR_CR0_LO: return cr_read(env, offsetof(E2KCrs, cr0_lo));
case SR_CR1_HI: return cr_read(env, offsetof(E2KCrs, cr1.hi));
case SR_CR1_LO: return cr_read(env, offsetof(E2KCrs, cr1.lo));
case SR_SCLKM1:
case SR_SCLKM2:
case SR_CU_HW0: goto todo;
case SR_UPSR: return env->upsr;
case SR_IP: return env->ip;
case SR_NIP: return env->nip;
case SR_LSR: return env_lsr_get(env);
case SR_PFPFR: return env->pfpfr.raw;
case SR_FPCR: return env->fpcr.raw;
case SR_FPSR: return env->fpsr.raw;
case SR_ILCR: return env_ilcr_get(env);
case SR_BR: return env_br_get(env);
case SR_BGR: return env->bgr;
case SR_IDR: return env->idr;
case SR_CLKR: return cpu_get_host_ticks(); // FIXME
case SR_RNDPR:
case SR_SCLKR:
case SR_TIR_HI:
case SR_TIR_LO:
case SR_RPR:
case SR_SBBP:
case SR_RPR_HI:
case SR_UPSRM: goto todo;
case SR_LSR1: return env->lsr_lcnt;
case SR_ILCR1: return env->ilcr_lcnt;
default:
/* The index is checked during translation. */
g_assert_not_reached();
break;
}
todo:
qemu_log("reading a state register %#x is not implemented\n", index);
return 0;
}
#define CASE_RWAP_SET(e, f) \
case glue(e, _HI): \
env->f.hi = value; \
break; \
case glue(e, _LO): \
env->f.lo = value & E2K_RWAP_LO_MASK; \
break;
void HELPER(state_reg_set)(CPUE2KState *env, uint64_t value, int index)
{
switch (index) {
case SR_UPSR:
case SR_LSR:
case SR_ILCR:
case SR_PFPFR:
case SR_FPCR:
case SR_FPSR:
case SR_SCLKR:
case SR_TIR_HI:
case SR_TIR_LO:
case SR_RPR:
case SR_SBBP:
case SR_RPR_HI:
case SR_UPSRM:
case SR_LSR1:
case SR_ILCR1:
break;
case SR_CUIR:
raise_exception(env, EXCP_ILLEGAL_OPCODE); /* FIXME */
break;
default:
if ((env->psr & PSR_PM) == 0) {
raise_exception(env, EXCP_PRIV_ACTION);
}
break;
}
switch (index) {
case SR_PSR:
env->psr = value & PSR_MASK;
break;
case SR_WD:
env_wd_set(env, value);
break;
case SR_CORE_MODE:
// FIXME: core_mode
qemu_log("FIXME: core_mode is set to %#lx\n", value);
env->core_mode = value;
break;
case SR_CWD:
/* ignore */
break;
case SR_PSP_HI:
env->psp.hi = value;
break;
case SR_PSP_LO:
env->psp.lo = value & E2K_PSP_LO_MASK;
break;
case SR_PSHTP:
/* ignore */
break;
case SR_PCSP_HI:
env->pcsp.hi = value;
break;
case SR_PCSP_LO:
env->pcsp.lo = value & E2K_PSP_LO_MASK;
break;
case SR_PCSHTP:
/* ignore */
break;
case SR_CTPR1:
env->ctprs[0].raw = value;
break;
case SR_CTPR2:
env->ctprs[1].raw = value;
break;
case SR_CTPR3:
env->ctprs[2].raw = value;
break;
case SR_SBR:
env->sbr = value;
break;
case SR_CUTD:
case SR_EIR:
case SR_TSD:
goto todo;
case SR_CUIR:
env->cuir = value & CUIR_MASK;
break;
case SR_OSEM:
case SR_TR:
goto todo;
case SR_OSR0:
env->osr0 = value;
break;
CASE_RWAP_SET(SR_OSCUD, oscud)
CASE_RWAP_SET(SR_OSGD, osgd)
CASE_RWAP_SET(SR_USD, usd)
CASE_RWAP_SET(SR_CUD, cud)
CASE_RWAP_SET(SR_GD, gd)
CASE_RWAP_SET(SR_CS, cs)
CASE_RWAP_SET(SR_DS, ds)
CASE_RWAP_SET(SR_ES, es)
CASE_RWAP_SET(SR_FS, fs)
CASE_RWAP_SET(SR_GS, gs)
CASE_RWAP_SET(SR_SS, ss)
case SR_DIBCR:
case SR_DIMCR:
case SR_DIBSR:
case SR_DTCR:
case SR_DIBAR0:
case SR_DIBAR1:
case SR_DIBAR2:
case SR_DIBAR3:
case SR_DIMAR0:
case SR_DIMAR1:
case SR_DTRAF:
case SR_DTART:
case SR_CR0_HI:
case SR_CR0_LO:
case SR_CR1_HI:
case SR_CR1_LO:
case SR_SCLKM1:
case SR_SCLKM2:
case SR_CU_HW0:
goto todo;
case SR_UPSR:
env->upsr = value & UPSR_MASK;
break;
case SR_LSR:
env_lsr_set(env, value);
env_ilcr_set(env, value);
break;
case SR_PFPFR:
env->pfpfr.raw = value;
e2k_update_fp_status(env);
break;
case SR_FPCR:
env->fpcr.raw = value;
e2k_update_fx_status(env);
break;
case SR_FPSR:
env->fpsr.raw = value;
break;
case SR_ILCR:
env->ilcr = (value >> LSR_ECNT_OFF) & ILCR_MASK;
env->ilcr_lcnt = value & GEN_MASK(0, LSR_LCNT_LEN);
break;
case SR_BR:
env_br_set(env, value);
break;
case SR_BGR:
env->bgr = value & BGR_MASK;
break;
case SR_RNDPR:
case SR_SCLKR:
case SR_TIR_HI:
case SR_TIR_LO:
case SR_RPR:
case SR_SBBP:
case SR_RPR_HI:
case SR_UPSRM:
goto todo;
case SR_LSR1:
env->lsr_lcnt = value;
env->ilcr_lcnt = value;
break;
case SR_ILCR1:
env->ilcr_lcnt = value;
break;
default:
/* The index is checked during translation. */
g_assert_not_reached();
break;
}
return;
todo:
qemu_log("write to state register %#x is not implemented\n", index);
}
uint64_t HELPER(getsp)(CPUE2KState *env, uint32_t src2)
{
int32_t s2 = src2 & ~0xf;
env->usd.base += s2;
env->usd.size -= s2;
return env->usd.base;
}
void HELPER(dam_lock_addr)(CPUE2KState *env, uint64_t addr, int size, int reg)
{
// TODO: helper_dam_lock_addr
}
int HELPER(dam_unlock_addr)(CPUE2KState *env, uint64_t addr, int size, int reg)
{
// TODO: helper_dam_unlock_addr
return 1;
}
uint64_t HELPER(clmull)(uint64_t s1, uint64_t s2)
{
uint64_t r = 0;
for (; s1; s1 >>= 1, s2 <<= 1) {
r ^= s1 & 1 ? s2 : 0;
}
return r;
}
uint64_t HELPER(clmulh)(uint64_t s1, uint64_t s2)
{
uint64_t r = 0;
for (s2 >>= 1; s1; s1 <<= 1, s2 >>= 1) {
r ^= s1 & (1ULL << 63) ? s2 : 0;
}
return r;
}