]>
git.proxmox.com Git - mirror_qemu.git/blob - target/riscv/insn_trans/trans_rvi.inc.c
2 * RISC-V translation routines for the RVXI Base Integer Instruction Set.
4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
5 * Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de
6 * Bastian Koppelmann, kbastian@mail.uni-paderborn.de
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2 or later, as published by the Free Software Foundation.
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
21 static bool trans_lui(DisasContext
*ctx
, arg_lui
*a
)
24 tcg_gen_movi_tl(cpu_gpr
[a
->rd
], a
->imm
);
29 static bool trans_auipc(DisasContext
*ctx
, arg_auipc
*a
)
32 tcg_gen_movi_tl(cpu_gpr
[a
->rd
], a
->imm
+ ctx
->base
.pc_next
);
37 static bool trans_jal(DisasContext
*ctx
, arg_jal
*a
)
39 gen_jal(ctx
, a
->rd
, a
->imm
);
43 static bool trans_jalr(DisasContext
*ctx
, arg_jalr
*a
)
45 /* no chaining with JALR */
46 TCGLabel
*misaligned
= NULL
;
47 TCGv t0
= tcg_temp_new();
50 gen_get_gpr(cpu_pc
, a
->rs1
);
51 tcg_gen_addi_tl(cpu_pc
, cpu_pc
, a
->imm
);
52 tcg_gen_andi_tl(cpu_pc
, cpu_pc
, (target_ulong
)-2);
54 if (!has_ext(ctx
, RVC
)) {
55 misaligned
= gen_new_label();
56 tcg_gen_andi_tl(t0
, cpu_pc
, 0x2);
57 tcg_gen_brcondi_tl(TCG_COND_NE
, t0
, 0x0, misaligned
);
61 tcg_gen_movi_tl(cpu_gpr
[a
->rd
], ctx
->pc_succ_insn
);
63 tcg_gen_lookup_and_goto_ptr();
66 gen_set_label(misaligned
);
67 gen_exception_inst_addr_mis(ctx
);
69 ctx
->base
.is_jmp
= DISAS_NORETURN
;
75 static bool gen_branch(DisasContext
*ctx
, arg_b
*a
, TCGCond cond
)
77 TCGLabel
*l
= gen_new_label();
78 TCGv source1
, source2
;
79 source1
= tcg_temp_new();
80 source2
= tcg_temp_new();
81 gen_get_gpr(source1
, a
->rs1
);
82 gen_get_gpr(source2
, a
->rs2
);
84 tcg_gen_brcond_tl(cond
, source1
, source2
, l
);
85 gen_goto_tb(ctx
, 1, ctx
->pc_succ_insn
);
86 gen_set_label(l
); /* branch taken */
88 if (!has_ext(ctx
, RVC
) && ((ctx
->base
.pc_next
+ a
->imm
) & 0x3)) {
90 gen_exception_inst_addr_mis(ctx
);
92 gen_goto_tb(ctx
, 0, ctx
->base
.pc_next
+ a
->imm
);
94 ctx
->base
.is_jmp
= DISAS_NORETURN
;
96 tcg_temp_free(source1
);
97 tcg_temp_free(source2
);
102 static bool trans_beq(DisasContext
*ctx
, arg_beq
*a
)
104 return gen_branch(ctx
, a
, TCG_COND_EQ
);
107 static bool trans_bne(DisasContext
*ctx
, arg_bne
*a
)
109 return gen_branch(ctx
, a
, TCG_COND_NE
);
112 static bool trans_blt(DisasContext
*ctx
, arg_blt
*a
)
114 return gen_branch(ctx
, a
, TCG_COND_LT
);
117 static bool trans_bge(DisasContext
*ctx
, arg_bge
*a
)
119 return gen_branch(ctx
, a
, TCG_COND_GE
);
122 static bool trans_bltu(DisasContext
*ctx
, arg_bltu
*a
)
124 return gen_branch(ctx
, a
, TCG_COND_LTU
);
127 static bool trans_bgeu(DisasContext
*ctx
, arg_bgeu
*a
)
129 return gen_branch(ctx
, a
, TCG_COND_GEU
);
132 static bool gen_load(DisasContext
*ctx
, arg_lb
*a
, TCGMemOp memop
)
134 TCGv t0
= tcg_temp_new();
135 TCGv t1
= tcg_temp_new();
136 gen_get_gpr(t0
, a
->rs1
);
137 tcg_gen_addi_tl(t0
, t0
, a
->imm
);
139 tcg_gen_qemu_ld_tl(t1
, t0
, ctx
->mem_idx
, memop
);
140 gen_set_gpr(a
->rd
, t1
);
146 static bool trans_lb(DisasContext
*ctx
, arg_lb
*a
)
148 return gen_load(ctx
, a
, MO_SB
);
151 static bool trans_lh(DisasContext
*ctx
, arg_lh
*a
)
153 return gen_load(ctx
, a
, MO_TESW
);
156 static bool trans_lw(DisasContext
*ctx
, arg_lw
*a
)
158 return gen_load(ctx
, a
, MO_TESL
);
161 static bool trans_lbu(DisasContext
*ctx
, arg_lbu
*a
)
163 return gen_load(ctx
, a
, MO_UB
);
166 static bool trans_lhu(DisasContext
*ctx
, arg_lhu
*a
)
168 return gen_load(ctx
, a
, MO_TEUW
);
171 static bool gen_store(DisasContext
*ctx
, arg_sb
*a
, TCGMemOp memop
)
173 TCGv t0
= tcg_temp_new();
174 TCGv dat
= tcg_temp_new();
175 gen_get_gpr(t0
, a
->rs1
);
176 tcg_gen_addi_tl(t0
, t0
, a
->imm
);
177 gen_get_gpr(dat
, a
->rs2
);
179 tcg_gen_qemu_st_tl(dat
, t0
, ctx
->mem_idx
, memop
);
186 static bool trans_sb(DisasContext
*ctx
, arg_sb
*a
)
188 return gen_store(ctx
, a
, MO_SB
);
191 static bool trans_sh(DisasContext
*ctx
, arg_sh
*a
)
193 return gen_store(ctx
, a
, MO_TESW
);
196 static bool trans_sw(DisasContext
*ctx
, arg_sw
*a
)
198 return gen_store(ctx
, a
, MO_TESL
);
201 #ifdef TARGET_RISCV64
202 static bool trans_lwu(DisasContext
*ctx
, arg_lwu
*a
)
204 return gen_load(ctx
, a
, MO_TEUL
);
207 static bool trans_ld(DisasContext
*ctx
, arg_ld
*a
)
209 return gen_load(ctx
, a
, MO_TEQ
);
212 static bool trans_sd(DisasContext
*ctx
, arg_sd
*a
)
214 return gen_store(ctx
, a
, MO_TEQ
);
218 static bool trans_addi(DisasContext
*ctx
, arg_addi
*a
)
220 return gen_arith_imm(ctx
, a
, &tcg_gen_add_tl
);
223 static bool trans_slti(DisasContext
*ctx
, arg_slti
*a
)
226 source1
= tcg_temp_new();
227 gen_get_gpr(source1
, a
->rs1
);
229 tcg_gen_setcondi_tl(TCG_COND_LT
, source1
, source1
, a
->imm
);
231 gen_set_gpr(a
->rd
, source1
);
232 tcg_temp_free(source1
);
236 static bool trans_sltiu(DisasContext
*ctx
, arg_sltiu
*a
)
239 source1
= tcg_temp_new();
240 gen_get_gpr(source1
, a
->rs1
);
242 tcg_gen_setcondi_tl(TCG_COND_LTU
, source1
, source1
, a
->imm
);
244 gen_set_gpr(a
->rd
, source1
);
245 tcg_temp_free(source1
);
249 static bool trans_xori(DisasContext
*ctx
, arg_xori
*a
)
251 return gen_arith_imm(ctx
, a
, &tcg_gen_xor_tl
);
253 static bool trans_ori(DisasContext
*ctx
, arg_ori
*a
)
255 return gen_arith_imm(ctx
, a
, &tcg_gen_or_tl
);
257 static bool trans_andi(DisasContext
*ctx
, arg_andi
*a
)
259 return gen_arith_imm(ctx
, a
, &tcg_gen_and_tl
);
261 static bool trans_slli(DisasContext
*ctx
, arg_slli
*a
)
263 if (a
->shamt
>= TARGET_LONG_BITS
) {
268 TCGv t
= tcg_temp_new();
269 gen_get_gpr(t
, a
->rs1
);
271 tcg_gen_shli_tl(t
, t
, a
->shamt
);
273 gen_set_gpr(a
->rd
, t
);
275 } /* NOP otherwise */
279 static bool trans_srli(DisasContext
*ctx
, arg_srli
*a
)
281 if (a
->shamt
>= TARGET_LONG_BITS
) {
286 TCGv t
= tcg_temp_new();
287 gen_get_gpr(t
, a
->rs1
);
289 tcg_gen_shri_tl(t
, t
, a
->shamt
);
290 gen_set_gpr(a
->rd
, t
);
292 } /* NOP otherwise */
296 static bool trans_srai(DisasContext
*ctx
, arg_srai
*a
)
298 if (a
->shamt
>= TARGET_LONG_BITS
) {
303 TCGv t
= tcg_temp_new();
304 gen_get_gpr(t
, a
->rs1
);
306 tcg_gen_sari_tl(t
, t
, a
->shamt
);
307 gen_set_gpr(a
->rd
, t
);
309 } /* NOP otherwise */
313 static bool trans_add(DisasContext
*ctx
, arg_add
*a
)
315 gen_arith(ctx
, OPC_RISC_ADD
, a
->rd
, a
->rs1
, a
->rs2
);
319 static bool trans_sub(DisasContext
*ctx
, arg_sub
*a
)
321 gen_arith(ctx
, OPC_RISC_SUB
, a
->rd
, a
->rs1
, a
->rs2
);
325 static bool trans_sll(DisasContext
*ctx
, arg_sll
*a
)
327 gen_arith(ctx
, OPC_RISC_SLL
, a
->rd
, a
->rs1
, a
->rs2
);
331 static bool trans_slt(DisasContext
*ctx
, arg_slt
*a
)
333 gen_arith(ctx
, OPC_RISC_SLT
, a
->rd
, a
->rs1
, a
->rs2
);
337 static bool trans_sltu(DisasContext
*ctx
, arg_sltu
*a
)
339 gen_arith(ctx
, OPC_RISC_SLTU
, a
->rd
, a
->rs1
, a
->rs2
);
343 static bool trans_xor(DisasContext
*ctx
, arg_xor
*a
)
345 gen_arith(ctx
, OPC_RISC_XOR
, a
->rd
, a
->rs1
, a
->rs2
);
349 static bool trans_srl(DisasContext
*ctx
, arg_srl
*a
)
351 gen_arith(ctx
, OPC_RISC_SRL
, a
->rd
, a
->rs1
, a
->rs2
);
355 static bool trans_sra(DisasContext
*ctx
, arg_sra
*a
)
357 gen_arith(ctx
, OPC_RISC_SRA
, a
->rd
, a
->rs1
, a
->rs2
);
361 static bool trans_or(DisasContext
*ctx
, arg_or
*a
)
363 gen_arith(ctx
, OPC_RISC_OR
, a
->rd
, a
->rs1
, a
->rs2
);
367 static bool trans_and(DisasContext
*ctx
, arg_and
*a
)
369 gen_arith(ctx
, OPC_RISC_AND
, a
->rd
, a
->rs1
, a
->rs2
);
373 #ifdef TARGET_RISCV64
374 static bool trans_addiw(DisasContext
*ctx
, arg_addiw
*a
)
376 return gen_arith_imm(ctx
, a
, &gen_addw
);
379 static bool trans_slliw(DisasContext
*ctx
, arg_slliw
*a
)
382 source1
= tcg_temp_new();
383 gen_get_gpr(source1
, a
->rs1
);
385 tcg_gen_shli_tl(source1
, source1
, a
->shamt
);
386 tcg_gen_ext32s_tl(source1
, source1
);
387 gen_set_gpr(a
->rd
, source1
);
389 tcg_temp_free(source1
);
393 static bool trans_srliw(DisasContext
*ctx
, arg_srliw
*a
)
395 TCGv t
= tcg_temp_new();
396 gen_get_gpr(t
, a
->rs1
);
397 tcg_gen_extract_tl(t
, t
, a
->shamt
, 32 - a
->shamt
);
398 /* sign-extend for W instructions */
399 tcg_gen_ext32s_tl(t
, t
);
400 gen_set_gpr(a
->rd
, t
);
405 static bool trans_sraiw(DisasContext
*ctx
, arg_sraiw
*a
)
407 TCGv t
= tcg_temp_new();
408 gen_get_gpr(t
, a
->rs1
);
409 tcg_gen_sextract_tl(t
, t
, a
->shamt
, 32 - a
->shamt
);
410 gen_set_gpr(a
->rd
, t
);
415 static bool trans_addw(DisasContext
*ctx
, arg_addw
*a
)
417 gen_arith(ctx
, OPC_RISC_ADDW
, a
->rd
, a
->rs1
, a
->rs2
);
421 static bool trans_subw(DisasContext
*ctx
, arg_subw
*a
)
423 gen_arith(ctx
, OPC_RISC_SUBW
, a
->rd
, a
->rs1
, a
->rs2
);
427 static bool trans_sllw(DisasContext
*ctx
, arg_sllw
*a
)
429 gen_arith(ctx
, OPC_RISC_SLLW
, a
->rd
, a
->rs1
, a
->rs2
);
433 static bool trans_srlw(DisasContext
*ctx
, arg_srlw
*a
)
435 gen_arith(ctx
, OPC_RISC_SRLW
, a
->rd
, a
->rs1
, a
->rs2
);
439 static bool trans_sraw(DisasContext
*ctx
, arg_sraw
*a
)
441 gen_arith(ctx
, OPC_RISC_SRAW
, a
->rd
, a
->rs1
, a
->rs2
);
446 static bool trans_fence(DisasContext
*ctx
, arg_fence
*a
)
448 /* FENCE is a full memory barrier. */
449 tcg_gen_mb(TCG_MO_ALL
| TCG_BAR_SC
);
453 static bool trans_fence_i(DisasContext
*ctx
, arg_fence_i
*a
)
456 * FENCE_I is a no-op in QEMU,
457 * however we need to end the translation block
459 tcg_gen_movi_tl(cpu_pc
, ctx
->pc_succ_insn
);
460 tcg_gen_exit_tb(NULL
, 0);
461 ctx
->base
.is_jmp
= DISAS_NORETURN
;
465 #define RISCV_OP_CSR_PRE do {\
466 source1 = tcg_temp_new(); \
467 csr_store = tcg_temp_new(); \
468 dest = tcg_temp_new(); \
469 rs1_pass = tcg_temp_new(); \
470 gen_get_gpr(source1, a->rs1); \
471 tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); \
472 tcg_gen_movi_tl(rs1_pass, a->rs1); \
473 tcg_gen_movi_tl(csr_store, a->csr); \
477 #define RISCV_OP_CSR_POST do {\
479 gen_set_gpr(a->rd, dest); \
480 tcg_gen_movi_tl(cpu_pc, ctx->pc_succ_insn); \
481 tcg_gen_exit_tb(NULL, 0); \
482 ctx->base.is_jmp = DISAS_NORETURN; \
483 tcg_temp_free(source1); \
484 tcg_temp_free(csr_store); \
485 tcg_temp_free(dest); \
486 tcg_temp_free(rs1_pass); \
490 static bool trans_csrrw(DisasContext
*ctx
, arg_csrrw
*a
)
492 TCGv source1
, csr_store
, dest
, rs1_pass
;
494 gen_helper_csrrw(dest
, cpu_env
, source1
, csr_store
);
499 static bool trans_csrrs(DisasContext
*ctx
, arg_csrrs
*a
)
501 TCGv source1
, csr_store
, dest
, rs1_pass
;
503 gen_helper_csrrs(dest
, cpu_env
, source1
, csr_store
, rs1_pass
);
508 static bool trans_csrrc(DisasContext
*ctx
, arg_csrrc
*a
)
510 TCGv source1
, csr_store
, dest
, rs1_pass
;
512 gen_helper_csrrc(dest
, cpu_env
, source1
, csr_store
, rs1_pass
);
517 static bool trans_csrrwi(DisasContext
*ctx
, arg_csrrwi
*a
)
519 TCGv source1
, csr_store
, dest
, rs1_pass
;
521 gen_helper_csrrw(dest
, cpu_env
, rs1_pass
, csr_store
);
526 static bool trans_csrrsi(DisasContext
*ctx
, arg_csrrsi
*a
)
528 TCGv source1
, csr_store
, dest
, rs1_pass
;
530 gen_helper_csrrs(dest
, cpu_env
, rs1_pass
, csr_store
, rs1_pass
);
535 static bool trans_csrrci(DisasContext
*ctx
, arg_csrrci
*a
)
537 TCGv source1
, csr_store
, dest
, rs1_pass
;
539 gen_helper_csrrc(dest
, cpu_env
, rs1_pass
, csr_store
, rs1_pass
);