qemu-e2k/linux-user/e2k/target_cpu.h

80 lines
2.1 KiB
C

#ifndef E2K_TARGET_CPU_H
#define E2K_TARGET_CPU_H
#include "qemu/log.h"
abi_long e2k_copy_from_user_crs(E2KCrs *crs, abi_ulong target_crs_addr);
abi_long e2k_copy_to_user_crs(abi_ulong target_crs_addr, E2KCrs *crs);
static inline void cpu_clone_regs_child(CPUE2KState *env, target_ulong newsp,
unsigned flags)
{
if (newsp) {
E2KPcsState pcs;
E2KPsState ps;
E2KCrs crs = { 0 };
uint64_t *ps_old, *ps_new;
size_t frame_size;
target_ulong pcs_base = env->pcsp.base + env->pcsp.index - sizeof(E2KCrs);
target_ulong ps_base = env->psp.base + env->psp.index;
int i;
// FIXME: what size must be?
env->usd.size = 0x20000;
env->usd.base = env->sbr = newsp & ~0xf;
env->usd.read = 1;
env->usd.write = 1;
e2k_pcs_new(&pcs);
e2k_ps_new(&ps);
// TODO: size checks and a way to report errors
e2k_copy_from_user_crs(&crs, pcs_base);
e2k_copy_to_user_crs(pcs.base, &crs);
pcs.index += sizeof(E2KCrs);
frame_size = crs.cr1.wbs * (crs.cr1.wfx ? 32 : 16);
ps_base -= frame_size;
ps.index += frame_size;
ps_old = lock_user(VERIFY_READ, ps_base, frame_size, 1);
ps_new = lock_user(VERIFY_WRITE, ps.base, frame_size, 0);
for (i = 0; i < frame_size / 8; i++) {
uint64_t tmp;
__get_user(tmp, &ps_old[i]);
__put_user(tmp, &ps_new[i]);
}
unlock_user_struct(ps_new, ps.base, 1);
unlock_user_struct(ps_old, ps_base, 0);
env->pcsp = pcs;
env->psp = ps;
}
env->restore_procedure = true;
env->regs[0] = 0;
env->tags[0] = 0;
}
static inline void cpu_clone_regs_parent(CPUE2KState *env, unsigned flags)
{
}
static inline void cpu_set_tls(CPUE2KState *env, target_ulong newtls)
{
env->regs[E2K_TLS_REG] = newtls;
}
static inline target_ulong cpu_get_tls(CPUE2KState *env)
{
return env->regs[E2K_TLS_REG];
}
static inline abi_ulong get_sp_from_cpustate(CPUE2KState *env)
{
return env->usd.base;
}
#endif /* E2K_TARGET_CPU_H */