aboutsummaryrefslogtreecommitdiff
path: root/target/loongarch/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/loongarch/translate.c')
-rw-r--r--target/loongarch/translate.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 3146a2d4ac..fd393ed76d 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -86,6 +86,10 @@ void generate_exception(DisasContext *ctx, int excp)
static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
{
+ if (ctx->va32) {
+ dest = (uint32_t) dest;
+ }
+
if (translator_use_goto_tb(&ctx->base, dest)) {
tcg_gen_goto_tb(n);
tcg_gen_movi_tl(cpu_pc, dest);
@@ -119,7 +123,13 @@ static void loongarch_tr_init_disas_context(DisasContextBase *dcbase,
ctx->vl = LSX_LEN;
}
+ ctx->la64 = is_la64(env);
+ ctx->va32 = (ctx->base.tb->flags & HW_FLAGS_VA32) != 0;
+
ctx->zero = tcg_constant_tl(0);
+
+ ctx->cpucfg1 = env->cpucfg[1];
+ ctx->cpucfg2 = env->cpucfg[2];
}
static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
@@ -205,6 +215,38 @@ static void set_fpr(int reg_num, TCGv val)
offsetof(CPULoongArchState, fpr[reg_num].vreg.D(0)));
}
+static TCGv make_address_x(DisasContext *ctx, TCGv base, TCGv addend)
+{
+ TCGv temp = NULL;
+
+ if (addend || ctx->va32) {
+ temp = tcg_temp_new();
+ }
+ if (addend) {
+ tcg_gen_add_tl(temp, base, addend);
+ base = temp;
+ }
+ if (ctx->va32) {
+ tcg_gen_ext32u_tl(temp, base);
+ base = temp;
+ }
+ return base;
+}
+
+static TCGv make_address_i(DisasContext *ctx, TCGv base, target_long ofs)
+{
+ TCGv addend = ofs ? tcg_constant_tl(ofs) : NULL;
+ return make_address_x(ctx, base, addend);
+}
+
+static uint64_t make_address_pc(DisasContext *ctx, uint64_t addr)
+{
+ if (ctx->va32) {
+ addr = (int32_t)addr;
+ }
+ return addr;
+}
+
#include "decode-insns.c.inc"
#include "insn_trans/trans_arith.c.inc"
#include "insn_trans/trans_shift.c.inc"
@@ -236,6 +278,10 @@ static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
}
ctx->base.pc_next += 4;
+
+ if (ctx->va32) {
+ ctx->base.pc_next = (uint32_t)ctx->base.pc_next;
+ }
}
static void loongarch_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)