master
inc 139 lines 3.93 KB
Raw
1 /*
2 * RISC-V translation routines for the RV64 Zacas Standard Extension.
3 *
4 * Copyright (c) 2020-2023 PLCT Lab
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2 or later, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #define REQUIRE_ZACAS(ctx) do { \
20 if (!ctx->cfg_ptr->ext_zacas) { \
21 return false; \
22 } \
23 } while (0)
24
25 static bool trans_amocas_w(DisasContext *ctx, arg_amocas_w *a)
26 {
27 REQUIRE_ZACAS(ctx);
28 return gen_cmpxchg(ctx, a, MO_ALIGN | MO_SL);
29 }
30
31 static TCGv_i64 get_gpr_pair(DisasContext *ctx, int reg_num)
32 {
33 TCGv_i64 t;
34
35 assert(get_ol(ctx) == MXL_RV32);
36
37 if (reg_num == 0) {
38 return tcg_constant_i64(0);
39 }
40
41 t = tcg_temp_new_i64();
42 tcg_gen_concat_tl_i64(t, cpu_gpr[reg_num], cpu_gpr[reg_num + 1]);
43 return t;
44 }
45
46 static void gen_set_gpr_pair(DisasContext *ctx, int reg_num, TCGv_i64 t)
47 {
48 assert(get_ol(ctx) == MXL_RV32);
49
50 if (reg_num != 0) {
51 #ifdef TARGET_RISCV32
52 tcg_gen_extr_i64_i32(cpu_gpr[reg_num], cpu_gpr[reg_num + 1], t);
53 #else
54 tcg_gen_ext32s_i64(cpu_gpr[reg_num], t);
55 tcg_gen_sari_i64(cpu_gpr[reg_num + 1], t, 32);
56 #endif
57
58 if (get_xl_max(ctx) == MXL_RV128) {
59 tcg_gen_sari_tl(cpu_gprh[reg_num], cpu_gpr[reg_num], 63);
60 tcg_gen_sari_tl(cpu_gprh[reg_num + 1], cpu_gpr[reg_num + 1], 63);
61 }
62 }
63 }
64
65 static bool gen_cmpxchg64(DisasContext *ctx, arg_atomic *a, MemOp mop)
66 {
67 /*
68 * Encodings with odd numbered registers specified in rs2 and rd are
69 * reserved.
70 */
71 if ((a->rs2 | a->rd) & 1) {
72 return false;
73 }
74
75 TCGv_i64 dest = get_gpr_pair(ctx, a->rd);
76 TCGv src1 = get_address(ctx, a->rs1, 0);
77 TCGv_i64 src2 = get_gpr_pair(ctx, a->rs2);
78
79 mop |= ctx->mo_endianness;
80 decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO);
81 tcg_gen_atomic_cmpxchg_i64(dest, src1, dest, src2, ctx->mem_idx, mop);
82
83 gen_set_gpr_pair(ctx, a->rd, dest);
84 return true;
85 }
86
87 static bool trans_amocas_d(DisasContext *ctx, arg_amocas_d *a)
88 {
89 REQUIRE_ZACAS(ctx);
90 switch (get_ol(ctx)) {
91 case MXL_RV32:
92 return gen_cmpxchg64(ctx, a, MO_ALIGN | MO_UQ);
93 case MXL_RV64:
94 case MXL_RV128:
95 return gen_cmpxchg(ctx, a, MO_ALIGN | MO_UQ);
96 default:
97 g_assert_not_reached();
98 }
99 }
100
101 static bool trans_amocas_q(DisasContext *ctx, arg_amocas_q *a)
102 {
103 REQUIRE_ZACAS(ctx);
104 REQUIRE_64BIT(ctx);
105
106 /*
107 * Encodings with odd numbered registers specified in rs2 and rd are
108 * reserved.
109 */
110 if ((a->rs2 | a->rd) & 1) {
111 return false;
112 }
113
114 #ifdef TARGET_RISCV64
115 TCGv_i128 dest = tcg_temp_new_i128();
116 TCGv src1 = get_address(ctx, a->rs1, 0);
117 TCGv_i128 src2 = tcg_temp_new_i128();
118 TCGv_i64 src2l = get_gpr(ctx, a->rs2, EXT_NONE);
119 TCGv_i64 src2h = get_gpr(ctx, a->rs2 == 0 ? 0 : a->rs2 + 1, EXT_NONE);
120 TCGv_i64 destl = get_gpr(ctx, a->rd, EXT_NONE);
121 TCGv_i64 desth = get_gpr(ctx, a->rd == 0 ? 0 : a->rd + 1, EXT_NONE);
122 MemOp memop = MO_ALIGN | MO_UO;
123
124 memop |= ctx->mo_endianness;
125 tcg_gen_concat_i64_i128(src2, src2l, src2h);
126 tcg_gen_concat_i64_i128(dest, destl, desth);
127 decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO);
128 tcg_gen_atomic_cmpxchg_i128(dest, src1, dest, src2, ctx->mem_idx, memop);
129
130 tcg_gen_extr_i128_i64(destl, desth, dest);
131
132 if (a->rd != 0) {
133 gen_set_gpr(ctx, a->rd, destl);
134 gen_set_gpr(ctx, a->rd + 1, desth);
135 }
136 #endif
137
138 return true;
139 }