2020-11-27 07:32:52 +01:00
|
|
|
#include "qemu/osdep.h"
|
|
|
|
#include "qemu/log.h"
|
|
|
|
#include "qemu/timer.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
#include "exec/exec-all.h"
|
|
|
|
#include "qemu/host-utils.h"
|
|
|
|
#include "exec/helper-proto.h"
|
|
|
|
|
2021-03-05 17:47:33 +01:00
|
|
|
uint64_t HELPER(sxt)(uint64_t x, uint32_t y)
|
2020-11-27 07:32:52 +01:00
|
|
|
{
|
|
|
|
int size;
|
|
|
|
|
|
|
|
switch (x & 3) {
|
|
|
|
case 0:
|
|
|
|
size = 8;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
size = 16;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
size = 32;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x & 4) {
|
|
|
|
return y & GEN_MASK(0, size);
|
|
|
|
} else {
|
|
|
|
return (((int64_t) y) << (64 - size) >> (64 - size));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-12 10:15:58 +01:00
|
|
|
static uint64_t cr_read(CPUE2KState *env, size_t offset)
|
2020-11-27 07:32:52 +01:00
|
|
|
{
|
2021-02-12 10:15:58 +01:00
|
|
|
target_ulong addr = env->pcsp.base + env->pcsp.index + offset;
|
|
|
|
return cpu_ldq_le_data(env, addr);
|
2020-12-01 13:00:12 +01:00
|
|
|
}
|
|
|
|
|
2021-03-05 17:47:33 +01:00
|
|
|
uint64_t HELPER(rrd)(CPUE2KState *env, int idx)
|
2020-12-01 13:00:12 +01:00
|
|
|
{
|
|
|
|
switch (idx) {
|
2020-12-14 23:12:18 +01:00
|
|
|
case 0x01: return e2k_state_wd(env); /* %wd */
|
2021-02-20 13:17:37 +01:00
|
|
|
case 0x07: return e2k_state_psp_hi(env); /* %psp.hi */
|
|
|
|
case 0x09: return e2k_state_psp_lo(env); /* %psp.lo */
|
2020-12-14 23:12:18 +01:00
|
|
|
case 0x0d: return e2k_state_pcsp_hi(env); /* %pcsp.hi */
|
2021-02-20 13:17:37 +01:00
|
|
|
case 0x0f: return e2k_state_pcsp_lo(env); /* %pcsp.lo */
|
2021-02-12 10:15:58 +01:00
|
|
|
case 0x13: return 0; /* %pcshtp */
|
2020-12-14 23:12:18 +01:00
|
|
|
case 0x2c: return env->usd.hi; /* %usd.hi */
|
|
|
|
case 0x2d: return env->usd.lo; /* %usd.lo */
|
2021-02-12 10:15:58 +01:00
|
|
|
case 0x51: return cr_read(env, offsetof(E2KCrs, cr0_hi)); /* %cr0.hi */
|
|
|
|
case 0x53: return cr_read(env, offsetof(E2KCrs, cr0_lo)); /* %cr0.lo */
|
|
|
|
case 0x55: return cr_read(env, offsetof(E2KCrs, cr1.hi)); /* %cr1.hi */
|
|
|
|
case 0x57: return cr_read(env, offsetof(E2KCrs, cr1.lo)); /* %cr1.lo */
|
|
|
|
case 0x80: return env->upsr; /* %upsr */
|
2020-12-14 23:12:18 +01:00
|
|
|
case 0x81: return env->ip; /* %ip */
|
2021-02-13 19:02:34 +01:00
|
|
|
case 0x83: /* %lsr */
|
|
|
|
{
|
|
|
|
uint64_t lsr = env->lsr;
|
|
|
|
lsr = deposit64(lsr, LSR_LCNT_OFF, LSR_LCNT_LEN, env->lsr_lcnt);
|
|
|
|
lsr = deposit64(lsr, LSR_ECNT_OFF, LSR_ECNT_LEN, env->lsr_ecnt);
|
|
|
|
lsr = deposit64(lsr, LSR_VLC_OFF, 1, env->lsr_vlc);
|
|
|
|
lsr = deposit64(lsr, LSR_OVER_OFF, 1, env->lsr_over);
|
|
|
|
lsr = deposit64(lsr, LSR_PCNT_OFF, LSR_PCNT_LEN, env->lsr_pcnt);
|
|
|
|
lsr = deposit64(lsr, LSR_STRMD_OFF, LSR_STRMD_LEN, env->lsr_strmd);
|
|
|
|
return lsr;
|
|
|
|
}
|
2021-02-22 15:05:10 +01:00
|
|
|
case 0x84: return env->pfpfr.raw; /* %pfpfr */
|
2020-12-16 14:02:00 +01:00
|
|
|
case 0x85: return env->fpcr.raw; /* %fpcr */
|
|
|
|
case 0x86: return env->fpsr.raw; /* %fpsr */
|
2020-12-14 23:12:18 +01:00
|
|
|
case 0x8a: return env->idr; /* %idr */
|
|
|
|
case 0x90: return cpu_get_host_ticks(); /* %clkr */
|
2021-03-11 15:12:10 +01:00
|
|
|
case 0xc3: return env->lsr_lcnt; /* %lsr1 */
|
2021-02-12 10:15:58 +01:00
|
|
|
default:
|
|
|
|
qemu_log_mask(LOG_UNIMP, "read unknown state register 0x%x\n", idx);
|
|
|
|
return 0;
|
2020-12-01 13:00:12 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-05 17:47:33 +01:00
|
|
|
void HELPER(rwd)(CPUE2KState *env, int idx, uint64_t val)
|
2020-12-01 13:00:12 +01:00
|
|
|
{
|
2020-12-16 14:02:00 +01:00
|
|
|
switch(idx) {
|
2021-02-12 10:15:58 +01:00
|
|
|
case 0x80: /* %upsr */
|
|
|
|
env->upsr = val;
|
|
|
|
break;
|
2021-01-21 23:20:49 +01:00
|
|
|
case 0x83: /* %lsr */
|
|
|
|
env->lsr = val;
|
|
|
|
env->lsr_lcnt = extract64(val, LSR_LCNT_OFF, LSR_LCNT_LEN);
|
|
|
|
env->lsr_ecnt = extract64(val, LSR_ECNT_OFF, LSR_ECNT_LEN);
|
|
|
|
env->lsr_vlc = extract64(val, LSR_VLC_OFF, 1);
|
|
|
|
env->lsr_over = extract64(val, LSR_OVER_OFF, 1);
|
|
|
|
env->lsr_pcnt = extract64(val, LSR_PCNT_OFF, LSR_PCNT_LEN);
|
|
|
|
env->lsr_strmd = extract64(val, LSR_STRMD_OFF, LSR_STRMD_LEN);
|
|
|
|
break;
|
2021-02-04 01:02:56 +01:00
|
|
|
case 0x84: /* %pfpfr */
|
2021-02-22 15:05:10 +01:00
|
|
|
env->pfpfr.raw = val;
|
|
|
|
e2k_update_fp_status(env);
|
2021-02-04 01:02:56 +01:00
|
|
|
break;
|
2020-12-16 14:02:00 +01:00
|
|
|
case 0x85: /* %fpcr */
|
|
|
|
env->fpcr.raw = val;
|
2021-02-22 15:05:10 +01:00
|
|
|
e2k_update_fx_status(env);
|
2020-12-16 14:02:00 +01:00
|
|
|
break;
|
|
|
|
case 0x86: env->fpsr.raw = val; break; /* %fpsr */
|
2021-03-11 15:12:10 +01:00
|
|
|
case 0xc3: env->lsr_lcnt = val; break; /* %lsr1 */
|
2021-02-12 10:15:58 +01:00
|
|
|
default:
|
|
|
|
qemu_log_mask(LOG_UNIMP, "rwd unknown state register 0x%x\n", idx);
|
2020-12-16 14:02:00 +01:00
|
|
|
break;
|
|
|
|
}
|
2020-11-27 07:32:52 +01:00
|
|
|
}
|
|
|
|
|
2021-03-05 17:47:33 +01:00
|
|
|
void HELPER(rws)(CPUE2KState *env, int idx, uint32_t val)
|
2020-11-27 07:32:52 +01:00
|
|
|
{
|
2020-12-16 14:02:00 +01:00
|
|
|
switch (idx) {
|
2021-02-12 10:15:58 +01:00
|
|
|
case 0x80: /* %upsr */
|
|
|
|
env->upsr = deposit64(env->upsr, 0, 32, val);
|
|
|
|
break;
|
2021-01-21 23:20:49 +01:00
|
|
|
case 0x83: /* %lsr */
|
|
|
|
env->lsr_lcnt = val;
|
|
|
|
break;
|
2021-02-04 01:02:56 +01:00
|
|
|
case 0x84: /* %pfpfr */
|
2021-02-22 15:05:10 +01:00
|
|
|
env->pfpfr.raw = val;
|
|
|
|
e2k_update_fp_status(env);
|
2021-02-04 01:02:56 +01:00
|
|
|
break;
|
2020-12-16 14:02:00 +01:00
|
|
|
case 0x85: /* %fpcr */
|
|
|
|
env->fpcr.raw = val;
|
2021-02-22 15:05:10 +01:00
|
|
|
e2k_update_fx_status(env);
|
2020-12-16 14:02:00 +01:00
|
|
|
break;
|
|
|
|
case 0x86: env->fpsr.raw = val; break; /* %fpsr */
|
2021-02-12 10:15:58 +01:00
|
|
|
default:
|
|
|
|
qemu_log_mask(LOG_UNIMP, "rws unknown state register 0x%x\n", idx);
|
2020-12-16 14:02:00 +01:00
|
|
|
break;
|
|
|
|
}
|
2020-11-27 07:32:52 +01:00
|
|
|
}
|
|
|
|
|
2021-03-05 17:47:33 +01:00
|
|
|
uint64_t HELPER(getsp)(CPUE2KState *env, uint32_t src2)
|
2020-12-11 08:37:23 +01:00
|
|
|
{
|
|
|
|
int32_t s2 = src2 & ~0xf;
|
2020-11-27 07:32:52 +01:00
|
|
|
|
2020-12-11 08:37:23 +01:00
|
|
|
env->usd.base += s2;
|
2020-12-14 23:12:18 +01:00
|
|
|
env->usd.size -= s2;
|
2020-11-27 07:32:52 +01:00
|
|
|
|
2020-12-11 08:37:23 +01:00
|
|
|
return env->usd.base;
|
2020-11-27 07:32:52 +01:00
|
|
|
}
|
2020-12-15 16:16:37 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2021-03-13 14:22:02 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|