master
inc 144 lines 3.8 KB
Raw
1 /*
2 * RISC-V translation routines for the MIPS extensions (xmips*).
3 *
4 * Copyright (c) 2025 MIPS
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 *
8 * Reference: MIPS P8700 instructions
9 * (https://mips.com/products/hardware/p8700/)
10 */
11
12 #define REQUIRE_XMIPSCBOP(ctx) do { \
13 if (!ctx->cfg_ptr->ext_xmipscbop) { \
14 return false; \
15 } \
16 } while (0)
17
18 #define REQUIRE_XMIPSCMOV(ctx) do { \
19 if (!ctx->cfg_ptr->ext_xmipscmov) { \
20 return false; \
21 } \
22 } while (0)
23
24 #define REQUIRE_XMIPSLSP(ctx) do { \
25 if (!ctx->cfg_ptr->ext_xmipslsp) { \
26 return false; \
27 } \
28 } while (0)
29
30 /* Conditional move by MIPS. */
31 static bool trans_ccmov(DisasContext *ctx, arg_ccmov *a)
32 {
33 REQUIRE_XMIPSCMOV(ctx);
34
35 TCGv zero, source1, source2, source3;
36 zero = tcg_constant_tl(0);
37 source1 = get_gpr(ctx, a->rs1, EXT_NONE);
38 source2 = get_gpr(ctx, a->rs2, EXT_NONE);
39 source3 = get_gpr(ctx, a->rs3, EXT_NONE);
40
41 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[a->rd],
42 source2, zero, source1, source3);
43
44 return true;
45 }
46
47 /* Load Doubleword Pair. */
48 static bool trans_ldp(DisasContext *ctx, arg_ldp *a)
49 {
50 MemOp memop = MO_SQ | ctx->mo_endianness;
51
52 REQUIRE_XMIPSLSP(ctx);
53 REQUIRE_64_OR_128BIT(ctx);
54
55 TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
56 TCGv dest0 = dest_gpr(ctx, a->rd);
57 TCGv dest1 = dest_gpr(ctx, a->rs3);
58 TCGv addr = tcg_temp_new();
59
60 tcg_gen_addi_tl(addr, src, a->imm_y);
61 tcg_gen_qemu_ld_tl(dest0, addr, ctx->mem_idx, memop);
62 gen_set_gpr(ctx, a->rd, dest0);
63
64 tcg_gen_addi_tl(addr, addr, 8);
65 tcg_gen_qemu_ld_tl(dest1, addr, ctx->mem_idx, memop);
66 gen_set_gpr(ctx, a->rs3, dest1);
67
68 return true;
69 }
70
71 /* Load Word Pair. */
72 static bool trans_lwp(DisasContext *ctx, arg_lwp *a)
73 {
74 MemOp memop = MO_SL | ctx->mo_endianness;
75
76 REQUIRE_XMIPSLSP(ctx);
77
78 TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
79 TCGv dest0 = dest_gpr(ctx, a->rd);
80 TCGv dest1 = dest_gpr(ctx, a->rs3);
81 TCGv addr = tcg_temp_new();
82
83 tcg_gen_addi_tl(addr, src, a->imm_x);
84 tcg_gen_qemu_ld_tl(dest0, addr, ctx->mem_idx, memop);
85 gen_set_gpr(ctx, a->rd, dest0);
86
87 tcg_gen_addi_tl(addr, addr, 4);
88 tcg_gen_qemu_ld_tl(dest1, addr, ctx->mem_idx, memop);
89 gen_set_gpr(ctx, a->rs3, dest1);
90
91 return true;
92 }
93
94 /* Store Doubleword Pair. */
95 static bool trans_sdp(DisasContext *ctx, arg_sdp *a)
96 {
97 MemOp memop = MO_UQ | ctx->mo_endianness;
98
99 REQUIRE_XMIPSLSP(ctx);
100 REQUIRE_64_OR_128BIT(ctx);
101
102 TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
103 TCGv data0 = get_gpr(ctx, a->rs2, EXT_NONE);
104 TCGv data1 = get_gpr(ctx, a->rs3, EXT_NONE);
105 TCGv addr = tcg_temp_new();
106
107 tcg_gen_addi_tl(addr, src, a->imm_w);
108 tcg_gen_qemu_st_tl(data0, addr, ctx->mem_idx, memop);
109
110 tcg_gen_addi_tl(addr, addr, 8);
111 tcg_gen_qemu_st_tl(data1, addr, ctx->mem_idx, memop);
112
113 return true;
114 }
115
116 /* Store Word Pair. */
117 static bool trans_swp(DisasContext *ctx, arg_swp *a)
118 {
119 MemOp memop = MO_SL | ctx->mo_endianness;
120
121 REQUIRE_XMIPSLSP(ctx);
122
123 TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
124 TCGv data0 = get_gpr(ctx, a->rs2, EXT_NONE);
125 TCGv data1 = get_gpr(ctx, a->rs3, EXT_NONE);
126 TCGv addr = tcg_temp_new();
127
128 tcg_gen_addi_tl(addr, src, a->imm_v);
129 tcg_gen_qemu_st_tl(data0, addr, ctx->mem_idx, memop);
130
131 tcg_gen_addi_tl(addr, addr, 4);
132 tcg_gen_qemu_st_tl(data1, addr, ctx->mem_idx, memop);
133
134 return true;
135 }
136
137 /* Move data from memory into cache. */
138 static bool trans_pref(DisasContext *ctx, arg_pref *a)
139 {
140 REQUIRE_XMIPSCBOP(ctx);
141
142 /* Nop */
143 return true;
144 }