master
inc 275 lines 7.95 KB
Raw
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3 * Copyright (c) 2021 Loongson Technology Corporation Limited
4 */
5
6 static bool gen_load(DisasContext *ctx, arg_rr_i *a, MemOp mop)
7 {
8 TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
9 TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
10 TCGv t1 = tcg_temp_new();
11 TCGv mask = tcg_constant_tl(0x8);
12 TCGv zero = tcg_constant_tl(0);
13 TCGLabel *done = gen_new_label();
14 TCGLabel *l1 = gen_new_label();
15
16 addr = make_address_i(ctx, addr, a->imm);
17
18 if (avail_SCQ(ctx) && mop == MO_LEUQ) {
19 /*
20 * The LL.D+LD.D may be paired with SC.Q,
21 * use llval_high if llbit_scq && (addr == lladdr ^ 0x8)
22 */
23 tcg_gen_brcond_tl(TCG_COND_EQ, cpu_llbit_scq, zero, l1);
24 tcg_gen_xor_tl(t1, addr, mask);
25 tcg_gen_brcond_tl(TCG_COND_NE, cpu_lladdr, t1, l1);
26 gen_set_gpr(a->rd, cpu_llval_high, EXT_NONE);
27 tcg_gen_br(done);
28 gen_set_label(l1);
29 }
30
31 tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
32 gen_set_gpr(a->rd, dest, EXT_NONE);
33
34 if (avail_SCQ(ctx) && mop == MO_LEUQ) {
35 gen_set_label(done);
36 }
37 return true;
38 }
39
40 static bool gen_store(DisasContext *ctx, arg_rr_i *a, MemOp mop)
41 {
42 TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
43 TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
44
45 addr = make_address_i(ctx, addr, a->imm);
46
47 tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
48 return true;
49 }
50
51 static bool gen_loadx(DisasContext *ctx, arg_rrr *a, MemOp mop)
52 {
53 TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
54 TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
55 TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
56 TCGv addr = make_address_x(ctx, src1, src2);
57
58 tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
59 gen_set_gpr(a->rd, dest, EXT_NONE);
60
61 return true;
62 }
63
64 static bool gen_storex(DisasContext *ctx, arg_rrr *a, MemOp mop)
65 {
66 TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
67 TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
68 TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
69 TCGv addr = make_address_x(ctx, src1, src2);
70
71 tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
72
73 return true;
74 }
75
76 static bool gen_load_gt(DisasContext *ctx, arg_rrr *a, MemOp mop)
77 {
78 TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
79 TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
80 TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
81
82 gen_helper_asrtgt_d(tcg_env, src1, src2);
83 src1 = make_address_i(ctx, src1, 0);
84 tcg_gen_qemu_ld_tl(dest, src1, ctx->mem_idx, mop);
85 gen_set_gpr(a->rd, dest, EXT_NONE);
86
87 return true;
88 }
89
90 static bool gen_load_le(DisasContext *ctx, arg_rrr *a, MemOp mop)
91 {
92 TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
93 TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
94 TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
95
96 gen_helper_asrtle_d(tcg_env, src1, src2);
97 src1 = make_address_i(ctx, src1, 0);
98 tcg_gen_qemu_ld_tl(dest, src1, ctx->mem_idx, mop);
99 gen_set_gpr(a->rd, dest, EXT_NONE);
100
101 return true;
102 }
103
104 static bool gen_store_gt(DisasContext *ctx, arg_rrr *a, MemOp mop)
105 {
106 TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
107 TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
108 TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
109
110 gen_helper_asrtgt_d(tcg_env, src1, src2);
111 src1 = make_address_i(ctx, src1, 0);
112 tcg_gen_qemu_st_tl(data, src1, ctx->mem_idx, mop);
113
114 return true;
115 }
116
117 static bool gen_store_le(DisasContext *ctx, arg_rrr *a, MemOp mop)
118 {
119 TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
120 TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
121 TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
122
123 gen_helper_asrtle_d(tcg_env, src1, src2);
124 src1 = make_address_i(ctx, src1, 0);
125 tcg_gen_qemu_st_tl(data, src1, ctx->mem_idx, mop);
126
127 return true;
128 }
129
130 static bool trans_preld(DisasContext *ctx, arg_preld *a)
131 {
132 return true;
133 }
134
135 static bool trans_preldx(DisasContext *ctx, arg_preldx * a)
136 {
137 return true;
138 }
139
140 /*
141 * Decode dbar hint and emit appropriate TCG memory barrier.
142 *
143 * The hint is a 5-bit field (0-31) encoded in the instruction.
144 * For hint 0x700 (special LL/SC loop barrier), treat as full barrier.
145 *
146 * See LoongArch Reference Manual v1.10, Section 4.2.2 for details.
147 */
148 static bool trans_dbar(DisasContext *ctx, arg_dbar * a)
149 {
150 int hint = a->imm;
151 TCGBar bar_flags = 0;
152
153 /* Reserved/no-op hints: 0xf and 0x1f */
154 if (hint == 0xf || hint == 0x1f) {
155 return true;
156 }
157
158 /* If the CPU does not support fine-grained hints,or for the special LL/SC
159 * loop barrier (0x700), emit a full barrier.
160 */
161 if (!avail_DBAR_HINT(ctx) || hint == 0x700) {
162 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
163 return true;
164 }
165
166 /*
167 * Fine-grained hint decoding:
168 * The hint is a 5-bit field (bits 4-0). Bit4 is reserved and currently
169 * ignored/discarded. Only bits 3-0 are used for ordering control.
170 * Bit3: barrier for previous read (0: true, 1: false)
171 * Bit2: barrier for previous write (0: true, 1: false)
172 * Bit1: barrier for succeeding read (0: true, 1: false)
173 * Bit0: barrier for succeeding write (0: true, 1: false)
174 *
175 * For each combination, we set the corresponding TCG_MO_* flag if both
176 * sides of the barrier require ordering.
177 */
178
179 bool prev_rd = !(hint & 0x08); /* bit3 */
180 bool prev_wr = !(hint & 0x04); /* bit2 */
181 bool succ_rd = !(hint & 0x02); /* bit1 */
182 bool succ_wr = !(hint & 0x01); /* bit0 */
183
184 if (prev_rd) {
185 bar_flags |= TCG_MO_LD_LD | TCG_MO_LD_ST;
186 }
187 if (prev_wr) {
188 bar_flags |= TCG_MO_ST_LD | TCG_MO_ST_ST;
189 }
190 if (succ_rd) {
191 bar_flags |= TCG_MO_LD_LD | TCG_MO_ST_LD;
192 }
193 if (succ_wr) {
194 bar_flags |= TCG_MO_ST_ST | TCG_MO_LD_ST;
195 }
196
197 if (bar_flags == 0) {
198 bar_flags = TCG_MO_ALL;
199 }
200
201 tcg_gen_mb(bar_flags | TCG_BAR_SC);
202 return true;
203 }
204
205 static bool trans_ibar(DisasContext *ctx, arg_ibar *a)
206 {
207 ctx->base.is_jmp = DISAS_STOP;
208 return true;
209 }
210
211 static bool gen_ldptr(DisasContext *ctx, arg_rr_i *a, MemOp mop)
212 {
213 TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
214 TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
215
216 addr = make_address_i(ctx, addr, a->imm);
217
218 tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
219 gen_set_gpr(a->rd, dest, EXT_NONE);
220 return true;
221 }
222
223 static bool gen_stptr(DisasContext *ctx, arg_rr_i *a, MemOp mop)
224 {
225 TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
226 TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
227
228 addr = make_address_i(ctx, addr, a->imm);
229
230 tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
231 return true;
232 }
233
234 TRANS(ld_b, ALL, gen_load, MO_SB)
235 TRANS(ld_h, ALL, gen_load, MO_LESW)
236 TRANS(ld_w, ALL, gen_load, MO_LESL)
237 TRANS(ld_d, 64, gen_load, MO_LEUQ)
238 TRANS(st_b, ALL, gen_store, MO_UB)
239 TRANS(st_h, ALL, gen_store, MO_LEUW)
240 TRANS(st_w, ALL, gen_store, MO_LEUL)
241 TRANS(st_d, 64, gen_store, MO_LEUQ)
242 TRANS(ld_bu, ALL, gen_load, MO_UB)
243 TRANS(ld_hu, ALL, gen_load, MO_LEUW)
244 TRANS(ld_wu, 64, gen_load, MO_LEUL)
245 TRANS(ldx_b, 64, gen_loadx, MO_SB)
246 TRANS(ldx_h, 64, gen_loadx, MO_LESW)
247 TRANS(ldx_w, 64, gen_loadx, MO_LESL)
248 TRANS(ldx_d, 64, gen_loadx, MO_LEUQ)
249 TRANS(stx_b, 64, gen_storex, MO_UB)
250 TRANS(stx_h, 64, gen_storex, MO_LEUW)
251 TRANS(stx_w, 64, gen_storex, MO_LEUL)
252 TRANS(stx_d, 64, gen_storex, MO_LEUQ)
253 TRANS(ldx_bu, 64, gen_loadx, MO_UB)
254 TRANS(ldx_hu, 64, gen_loadx, MO_LEUW)
255 TRANS(ldx_wu, 64, gen_loadx, MO_LEUL)
256 TRANS(ldptr_w, 64, gen_ldptr, MO_LESL)
257 TRANS(stptr_w, 64, gen_stptr, MO_LEUL)
258 TRANS(ldptr_d, 64, gen_ldptr, MO_LEUQ)
259 TRANS(stptr_d, 64, gen_stptr, MO_LEUQ)
260 TRANS(ldgt_b, 64, gen_load_gt, MO_SB)
261 TRANS(ldgt_h, 64, gen_load_gt, MO_LESW)
262 TRANS(ldgt_w, 64, gen_load_gt, MO_LESL)
263 TRANS(ldgt_d, 64, gen_load_gt, MO_LEUQ)
264 TRANS(ldle_b, 64, gen_load_le, MO_SB)
265 TRANS(ldle_h, 64, gen_load_le, MO_LESW)
266 TRANS(ldle_w, 64, gen_load_le, MO_LESL)
267 TRANS(ldle_d, 64, gen_load_le, MO_LEUQ)
268 TRANS(stgt_b, 64, gen_store_gt, MO_UB)
269 TRANS(stgt_h, 64, gen_store_gt, MO_LEUW)
270 TRANS(stgt_w, 64, gen_store_gt, MO_LEUL)
271 TRANS(stgt_d, 64, gen_store_gt, MO_LEUQ)
272 TRANS(stle_b, 64, gen_store_le, MO_UB)
273 TRANS(stle_h, 64, gen_store_le, MO_LEUW)
274 TRANS(stle_w, 64, gen_store_le, MO_LEUL)
275 TRANS(stle_d, 64, gen_store_le, MO_LEUQ)