qemu-e2k/target/e2k/translate/state.c

237 lines
6.1 KiB
C
Raw Normal View History

2020-11-11 20:03:51 +01:00
#include "qemu/osdep.h"
#include "qemu.h"
#include "exec/log.h"
#include "translate.h"
2020-11-13 15:49:28 +01:00
static void gen_preg_offset(TCGv_i64 ret, int reg)
2020-11-11 20:03:51 +01:00
{
2020-11-13 15:49:28 +01:00
assert(reg < 32);
2020-11-14 12:49:48 +01:00
TCGv_i32 br = tcg_temp_new_i32();
2020-11-14 10:20:18 +01:00
TCGv_i32 pcur = tcg_temp_new_i32();
TCGv_i32 psz = tcg_temp_new_i32();
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 t2 = tcg_temp_new_i32();
2020-11-13 15:49:28 +01:00
2020-11-14 12:49:48 +01:00
e2k_gen_get_br(br);
tcg_gen_extract_i32(pcur, br, BR_PCUR_OFF, BR_PCUR_LEN);
tcg_gen_extract_i32(psz, br, BR_PSZ_OFF, BR_PSZ_LEN);
2020-11-14 10:20:18 +01:00
tcg_gen_addi_i32(t0, pcur, reg);
e2k_gen_wrap_i32(t1, t0, psz);
tcg_gen_shli_i32(t2, t1, 1);
tcg_gen_extu_i32_i64(ret, t2);
2020-11-13 15:49:28 +01:00
2020-11-14 10:20:18 +01:00
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(psz);
tcg_temp_free_i32(pcur);
2020-11-14 12:49:48 +01:00
tcg_temp_free_i32(br);
}
2020-11-13 15:49:28 +01:00
static void gen_preg_clear(TCGv_i64 ret, TCGv_i64 offset)
{
2020-11-13 15:49:28 +01:00
TCGv_i64 t0 = tcg_const_i64(3);
TCGv_i64 t1 = tcg_temp_new_i64();
TCGv_i64 t2 = tcg_temp_new_i64();
2020-11-13 21:47:31 +01:00
tcg_gen_shl_i64(t1, t0, offset);
2020-11-13 15:49:28 +01:00
tcg_gen_not_i64(t2, t1);
tcg_gen_and_i64(ret, t2, e2k_cs.pregs);
tcg_temp_free_i64(t2);
tcg_temp_free_i64(t1);
tcg_temp_free_i64(t0);
}
void e2k_gen_preg(TCGv_i64 ret, int reg)
{
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
gen_preg_offset(t0, reg);
tcg_gen_shri_i64(t1, e2k_cs.pregs, reg * 2);
tcg_gen_andi_i64(ret, t1, 0x01);
tcg_temp_free_i64(t1);
tcg_temp_free_i64(t0);
}
TCGv_i64 e2k_get_preg(DisasContext *dc, int reg)
{
TCGv_i64 ret = e2k_get_temp_i64(dc);
e2k_gen_preg(ret, reg);
2020-11-11 20:03:51 +01:00
return ret;
}
void e2k_gen_store_preg(int reg, TCGv_i64 val)
{
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
2020-11-13 15:49:28 +01:00
TCGv_i64 t2 = tcg_const_i64(1);
TCGv_i64 t3 = tcg_temp_new_i64();
gen_preg_offset(t0, reg);
gen_preg_clear(t1, t0);
tcg_gen_shl_i64(t3, t2, t0);
tcg_gen_or_i64(e2k_cs.pregs, t1, t3);
tcg_temp_free_i64(t3);
2020-11-11 20:03:51 +01:00
tcg_temp_free_i64(t2);
tcg_temp_free_i64(t1);
tcg_temp_free_i64(t0);
}
static inline void gen_wreg_offset(TCGv_i32 ret, int reg)
{
assert(reg < 64);
// TODO: exception (wsz * 2) <= reg_index
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
2020-11-13 21:47:31 +01:00
TCGv_i32 t2 = tcg_temp_new_i32();
TCGv_i32 t3 = tcg_const_i32(WREGS_SIZE);
2020-11-11 20:03:51 +01:00
2020-11-13 21:47:31 +01:00
tcg_gen_shli_i32(t0, e2k_cs.wbs, 1); // t = wbs * 2
tcg_gen_addi_i32(t1, t0, reg); // t = t + reg_index
e2k_gen_wrap_i32(t2, t1, t3); // t = t % WIN_REGS_COUNT
tcg_gen_muli_i32(ret, t2, REG_SIZE); // t = t * REG_SIZE_IN_BYTES
2020-11-11 20:03:51 +01:00
2020-11-13 21:47:31 +01:00
tcg_temp_free_i32(t3);
2020-11-11 20:03:51 +01:00
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
}
static inline void gen_wreg_ptr(TCGv_ptr ret, int reg)
{
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_ptr t1 = tcg_temp_new_ptr();
gen_wreg_offset(t0, reg);
tcg_gen_ext_i32_ptr(t1, t0);
tcg_gen_add_ptr(ret, e2k_cs.win_ptr, t1);
tcg_temp_free_ptr(t1);
tcg_temp_free_i32(t0);
}
TCGv_i64 e2k_get_wreg(DisasContext *dc, int reg)
{
TCGv_i64 ret = e2k_get_temp_i64(dc);
TCGv_ptr ptr = tcg_temp_new_ptr();
gen_wreg_ptr(ptr, reg);
tcg_gen_ld_i64(ret, ptr, 0);
tcg_temp_free_ptr(ptr);
return ret;
}
void e2k_gen_store_wreg(int reg, TCGv_i64 val)
{
TCGv_ptr ptr = tcg_temp_new_ptr();
gen_wreg_ptr(ptr, reg);
tcg_gen_st_i64(val, ptr, 0);
tcg_temp_free_ptr(ptr);
}
2020-11-14 12:49:48 +01:00
static inline void gen_breg_start(TCGv_i32 ret, TCGv_i32 br)
2020-11-13 21:47:31 +01:00
{
2020-11-14 10:20:18 +01:00
TCGv_i32 rbs = tcg_temp_new_i32();
2020-11-13 21:47:31 +01:00
TCGv_i32 t0 = tcg_temp_new_i32();
2020-11-14 12:49:48 +01:00
tcg_gen_extract_i32(rbs, br, BR_RBS_OFF, BR_RBS_LEN);
2020-11-14 10:20:18 +01:00
tcg_gen_add_i32(t0, e2k_cs.wbs, rbs);
2020-11-13 21:47:31 +01:00
tcg_gen_shli_i32(ret, t0, 1);
tcg_temp_free_i32(t0);
2020-11-14 10:20:18 +01:00
tcg_temp_free_i32(rbs);
2020-11-13 21:47:31 +01:00
}
2020-11-11 20:03:51 +01:00
static inline void gen_breg_offset(TCGv_i32 ret, int reg)
{
2020-11-14 12:49:48 +01:00
TCGv_i32 br = tcg_temp_new_i32();
2020-11-14 10:20:18 +01:00
TCGv_i32 rcur = tcg_temp_new_i32();
TCGv_i32 rsz = tcg_temp_new_i32();
2020-11-11 20:03:51 +01:00
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_i32 t1 = tcg_temp_new_i32();
TCGv_i32 t2 = tcg_temp_new_i32();
TCGv_i32 t3 = tcg_temp_new_i32();
TCGv_i32 t4 = tcg_temp_new_i32();
2020-11-13 21:47:31 +01:00
TCGv_i32 t5 = tcg_temp_new_i32();
2020-11-11 20:03:51 +01:00
TCGv_i32 t6 = tcg_temp_new_i32();
2020-11-13 21:47:31 +01:00
TCGv_i32 t7 = tcg_temp_new_i32();
2020-11-11 20:03:51 +01:00
2020-11-14 12:49:48 +01:00
e2k_gen_get_br(br);
2020-11-13 21:47:31 +01:00
/* TODO: exception: reg > (rsz * 2 + 2) */
/* t = (reg + rcur * 2) % (rsz * 2 + 2) */
2020-11-14 12:49:48 +01:00
tcg_gen_extract_i32(rcur, br, BR_RCUR_OFF, BR_RCUR_LEN);
tcg_gen_extract_i32(rsz, br, BR_RSZ_OFF, BR_RSZ_LEN);
2020-11-14 10:20:18 +01:00
tcg_gen_shli_i32(t0, rcur, 1);
2020-11-11 20:03:51 +01:00
tcg_gen_addi_i32(t1, t0, reg);
2020-11-14 10:20:18 +01:00
tcg_gen_addi_i32(t2, rsz, 1);
2020-11-13 21:47:31 +01:00
tcg_gen_shli_i32(t3, t2, 1);
e2k_gen_wrap_i32(t4, t1, t3);
2020-11-11 20:03:51 +01:00
2020-11-13 21:47:31 +01:00
/* TODO: exceptioon: (reg + rbs * 2) > (wsz * 2) */
/* t = (t + wbs * 2 + rbs * 2) % 192 */
2020-11-14 12:49:48 +01:00
gen_breg_start(t5, br);
2020-11-13 21:47:31 +01:00
tcg_gen_add_i32(t6, t4, t5);
e2k_gen_wrapi_i32(t7, t6, WREGS_SIZE);
2020-11-11 20:03:51 +01:00
2020-11-13 21:47:31 +01:00
/* ret = t * 8 */
tcg_gen_muli_i32(ret, t7, REG_SIZE);
2020-11-11 20:03:51 +01:00
2020-11-13 21:47:31 +01:00
tcg_temp_free_i32(t7);
2020-11-11 20:03:51 +01:00
tcg_temp_free_i32(t6);
tcg_temp_free_i32(t5);
tcg_temp_free_i32(t4);
tcg_temp_free_i32(t3);
tcg_temp_free_i32(t2);
tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0);
2020-11-14 10:20:18 +01:00
tcg_temp_free_i32(rsz);
tcg_temp_free_i32(rcur);
2020-11-14 12:49:48 +01:00
tcg_temp_free_i32(br);
2020-11-11 20:03:51 +01:00
}
static inline void gen_breg_ptr(TCGv_ptr ret, int reg)
{
TCGv_i32 t0 = tcg_temp_new_i32();
TCGv_ptr t1 = tcg_temp_new_ptr();
gen_breg_offset(t0, reg);
tcg_gen_ext_i32_ptr(t1, t0);
tcg_gen_add_ptr(ret, e2k_cs.win_ptr, t1);
tcg_temp_free_ptr(t1);
tcg_temp_free_i32(t0);
}
TCGv_i64 e2k_get_breg(DisasContext *dc, int reg)
{
TCGv_i64 ret = e2k_get_temp(dc);
TCGv_ptr ptr = tcg_temp_new_ptr();
gen_breg_ptr(ptr, reg);
tcg_gen_ld_i64(ret, ptr, 0);
tcg_temp_free_ptr(ptr);
return ret;
}
void e2k_gen_store_breg(int reg, TCGv_i64 val)
{
TCGv_ptr ptr = tcg_temp_new_ptr();
gen_breg_ptr(ptr, reg);
tcg_gen_st_i64(val, ptr, 0);
tcg_temp_free_ptr(ptr);
}
TCGv_i64 e2k_get_greg(DisasContext *dc, int reg)
{
// TODO: rotated gregs
assert(reg < 32);
return e2k_cs.gregs[reg];
}
void e2k_gen_store_greg(int reg, TCGv_i64 val)
{
// TODO: rotated gregs
tcg_gen_mov_i64(e2k_cs.gregs[reg], val);
}