aboutsummaryrefslogtreecommitdiff
path: root/target/loongarch/translate.c
diff options
context:
space:
mode:
authorSong Gao <gaosong@loongson.cn>2022-06-06 20:42:54 +0800
committerRichard Henderson <richard.henderson@linaro.org>2022-06-06 18:09:03 +0000
commit143d6785ef725aff6d09bc112c21119c32d9d0ae (patch)
tree7cf357432aa7df04d29554358067b8e38fff1d15 /target/loongarch/translate.c
parentf8da88d78f71da751f089913784fa884df31bd03 (diff)
target/loongarch: Add fixed point arithmetic instruction translation
This includes: - ADD.{W/D}, SUB.{W/D} - ADDI.{W/D}, ADDU16ID - ALSL.{W[U]/D} - LU12I.W, LU32I.D LU52I.D - SLT[U], SLT[U]I - PCADDI, PCADDU12I, PCADDU18I, PCALAU12I - AND, OR, NOR, XOR, ANDN, ORN - MUL.{W/D}, MULH.{W[U]/D[U]} - MULW.D.W[U] - DIV.{W[U]/D[U]}, MOD.{W[U]/D[U]} - ANDI, ORI, XORI Signed-off-by: Song Gao <gaosong@loongson.cn> Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20220606124333.2060567-5-yangxiaojuan@loongson.cn> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'target/loongarch/translate.c')
-rw-r--r--target/loongarch/translate.c83
1 files changed, 83 insertions, 0 deletions
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 332a6d2d58..65c7dfd3da 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -26,6 +26,11 @@ TCGv_i64 cpu_fpr[32];
#define DISAS_STOP DISAS_TARGET_0
+static inline int plus_1(DisasContext *ctx, int x)
+{
+ return x + 1;
+}
+
void generate_exception(DisasContext *ctx, int excp)
{
tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
@@ -57,6 +62,11 @@ static void loongarch_tr_init_disas_context(DisasContextBase *dcbase,
/* Bound the number of insns to execute to those left on the page. */
bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
+
+ ctx->ntemp = 0;
+ memset(ctx->temp, 0, sizeof(ctx->temp));
+
+ ctx->zero = tcg_constant_tl(0);
}
static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
@@ -70,6 +80,73 @@ static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
tcg_gen_insn_start(ctx->base.pc_next);
}
+/*
+ * Wrappers for getting reg values.
+ *
+ * The $zero register does not have cpu_gpr[0] allocated -- we supply the
+ * constant zero as a source, and an uninitialized sink as destination.
+ *
+ * Further, we may provide an extension for word operations.
+ */
+static TCGv temp_new(DisasContext *ctx)
+{
+ assert(ctx->ntemp < ARRAY_SIZE(ctx->temp));
+ return ctx->temp[ctx->ntemp++] = tcg_temp_new();
+}
+
+static TCGv gpr_src(DisasContext *ctx, int reg_num, DisasExtend src_ext)
+{
+ TCGv t;
+
+ if (reg_num == 0) {
+ return ctx->zero;
+ }
+
+ switch (src_ext) {
+ case EXT_NONE:
+ return cpu_gpr[reg_num];
+ case EXT_SIGN:
+ t = temp_new(ctx);
+ tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]);
+ return t;
+ case EXT_ZERO:
+ t = temp_new(ctx);
+ tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]);
+ return t;
+ }
+ g_assert_not_reached();
+}
+
+static TCGv gpr_dst(DisasContext *ctx, int reg_num, DisasExtend dst_ext)
+{
+ if (reg_num == 0 || dst_ext) {
+ return temp_new(ctx);
+ }
+ return cpu_gpr[reg_num];
+}
+
+static void gen_set_gpr(int reg_num, TCGv t, DisasExtend dst_ext)
+{
+ if (reg_num != 0) {
+ switch (dst_ext) {
+ case EXT_NONE:
+ tcg_gen_mov_tl(cpu_gpr[reg_num], t);
+ break;
+ case EXT_SIGN:
+ tcg_gen_ext32s_tl(cpu_gpr[reg_num], t);
+ break;
+ case EXT_ZERO:
+ tcg_gen_ext32u_tl(cpu_gpr[reg_num], t);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ }
+}
+
+#include "decode-insns.c.inc"
+#include "insn_trans/trans_arith.c.inc"
+
static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
{
CPULoongArchState *env = cs->env_ptr;
@@ -84,6 +161,12 @@ static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
generate_exception(ctx, EXCCODE_INE);
}
+ for (int i = ctx->ntemp - 1; i >= 0; --i) {
+ tcg_temp_free(ctx->temp[i]);
+ ctx->temp[i] = NULL;
+ }
+ ctx->ntemp = 0;
+
ctx->base.pc_next += 4;
}