From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:42082) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1boU7w-000395-Dq for qemu-devel@nongnu.org; Mon, 26 Sep 2016 07:31:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1boU7s-0006EB-7y for qemu-devel@nongnu.org; Mon, 26 Sep 2016 07:31:15 -0400 Received: from gateway0.eecs.berkeley.edu ([169.229.60.87]:41702) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1boU7r-0006Cc-V5 for qemu-devel@nongnu.org; Mon, 26 Sep 2016 07:31:12 -0400 From: Sagar Karandikar Date: Mon, 26 Sep 2016 03:56:37 -0700 Message-Id: In-Reply-To: References: In-Reply-To: References: Subject: [Qemu-devel] [PATCH 07/18] target-riscv: Add Loads/Stores, FP Loads/Stores List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: peter.maydell@linaro.org, rth@twiddle.net, kbastian@mail.uni-paderborn.de, Sagar Karandikar Signed-off-by: Sagar Karandikar --- target-riscv/translate.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/target-riscv/translate.c b/target-riscv/translate.c index d8044cf..767cdbe 100644 --- a/target-riscv/translate.c +++ b/target-riscv/translate.c @@ -72,6 +72,10 @@ static const char * const fpr_regnames[] = { "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11" }; +/* convert riscv funct3 to qemu memop for load/store */ +static int tcg_memop_lookup[] = { MO_SB, MO_TESW, MO_TESL, MO_TEQ, MO_UB, + MO_TEUW, MO_TEUL }; + static inline void generate_exception(DisasContext *ctx, int excp) { tcg_gen_movi_tl(cpu_PC, ctx->pc); @@ -538,6 +542,105 @@ static inline void gen_branch(DisasContext *ctx, uint32_t opc, int rs1, int rs2, ctx->bstate = BS_BRANCH; } +static inline void gen_load(DisasContext *ctx, uint32_t opc, int rd, int rs1, + int16_t imm) +{ + target_long uimm = (target_long)imm; /* sign ext 16->64 bits */ + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + gen_get_gpr(t0, rs1); + tcg_gen_addi_tl(t0, t0, uimm); /* */ + int memop = (opc >> 12) & 0x7; + +#if defined(TARGET_RISCV64) + if (memop == 0x7) { +#else + if (memop == 0x7 || memop == 0x3 || memop == 0x6) { +#endif + kill_unknown(ctx, RISCV_EXCP_ILLEGAL_INST); + } else { + tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, tcg_memop_lookup[memop]); + } + + gen_set_gpr(rd, t1); + tcg_temp_free(t0); + tcg_temp_free(t1); +} + +static inline void gen_store(DisasContext *ctx, uint32_t opc, int rs1, int rs2, + int16_t imm) +{ + target_long uimm = (target_long)imm; /* sign ext 16->64 bits */ + + TCGv t0 = tcg_temp_new(); + TCGv dat = tcg_temp_new(); + gen_get_gpr(t0, rs1); + tcg_gen_addi_tl(t0, t0, uimm); + gen_get_gpr(dat, rs2); + int memop = (opc >> 12) & 0x7; + +#if defined(TARGET_RISCV64) + if (memop > 0x3) { +#else + if (memop > 0x2) { +#endif + kill_unknown(ctx, RISCV_EXCP_ILLEGAL_INST); + } else { + tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx, tcg_memop_lookup[memop]); + } + + tcg_temp_free(t0); + tcg_temp_free(dat); +} + +static inline void gen_fp_load(DisasContext *ctx, uint32_t opc, int rd, + int rs1, int16_t imm) +{ + target_long uimm = (target_long)imm; /* sign ext 16->64 bits */ + TCGv t0 = tcg_temp_new(); + gen_get_gpr(t0, rs1); + tcg_gen_addi_tl(t0, t0, uimm); + + switch (opc) { + case OPC_RISC_FLW: + tcg_gen_qemu_ld_i64(cpu_fpr[rd], t0, ctx->mem_idx, MO_TEUL); + break; + case OPC_RISC_FLD: + tcg_gen_qemu_ld_i64(cpu_fpr[rd], t0, ctx->mem_idx, MO_TEQ); + break; + default: + kill_unknown(ctx, RISCV_EXCP_ILLEGAL_INST); + break; + } + tcg_temp_free(t0); +} + +static inline void gen_fp_store(DisasContext *ctx, uint32_t opc, int rs1, + int rs2, int16_t imm) +{ + target_long uimm = (target_long)imm; /* sign ext 16->64 bits */ + + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + gen_get_gpr(t0, rs1); + tcg_gen_addi_tl(t0, t0, uimm); + + switch (opc) { + case OPC_RISC_FSW: + tcg_gen_qemu_st_i64(cpu_fpr[rs2], t0, ctx->mem_idx, MO_TEUL); + break; + case OPC_RISC_FSD: + tcg_gen_qemu_st_i64(cpu_fpr[rs2], t0, ctx->mem_idx, MO_TEQ); + break; + default: + kill_unknown(ctx, RISCV_EXCP_ILLEGAL_INST); + break; + } + + tcg_temp_free(t0); + tcg_temp_free(t1); +} + static void decode_opc(CPURISCVState *env, DisasContext *ctx) { int rs1; @@ -611,6 +714,13 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx) gen_branch(ctx, MASK_OP_BRANCH(ctx->opcode), rs1, rs2, GET_B_IMM(ctx->opcode)); break; + case OPC_RISC_LOAD: + gen_load(ctx, MASK_OP_LOAD(ctx->opcode), rd, rs1, imm); + break; + case OPC_RISC_STORE: + gen_store(ctx, MASK_OP_STORE(ctx->opcode), rs1, rs2, + GET_STORE_IMM(ctx->opcode)); + break; case OPC_RISC_ARITH_IMM: #if defined(TARGET_RISCV64) case OPC_RISC_ARITH_IMM_W: @@ -629,6 +739,13 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx) } gen_arith(ctx, MASK_OP_ARITH(ctx->opcode), rd, rs1, rs2); break; + case OPC_RISC_FP_LOAD: + gen_fp_load(ctx, MASK_OP_FP_LOAD(ctx->opcode), rd, rs1, imm); + break; + case OPC_RISC_FP_STORE: + gen_fp_store(ctx, MASK_OP_FP_STORE(ctx->opcode), rs1, rs2, + GET_STORE_IMM(ctx->opcode)); + break; default: kill_unknown(ctx, RISCV_EXCP_ILLEGAL_INST); break; -- 2.9.3