]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/loongarch64/tcg-target.c.inc
tcg/loongarch64: Implement the memory barrier op
[mirror_qemu.git] / tcg / loongarch64 / tcg-target.c.inc
CommitLineData
1bcfbf03
WX
1/*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2021 WANG Xuerui <git@xen0n.name>
5 *
6 * Based on tcg/riscv/tcg-target.c.inc
7 *
8 * Copyright (c) 2018 SiFive, Inc
9 * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
10 * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
11 * Copyright (c) 2008 Fabrice Bellard
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a copy
14 * of this software and associated documentation files (the "Software"), to deal
15 * in the Software without restriction, including without limitation the rights
16 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 * copies of the Software, and to permit persons to whom the Software is
18 * furnished to do so, subject to the following conditions:
19 *
20 * The above copyright notice and this permission notice shall be included in
21 * all copies or substantial portions of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29 * THE SOFTWARE.
30 */
31
32#ifdef CONFIG_DEBUG_TCG
33static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
34 "zero",
35 "ra",
36 "tp",
37 "sp",
38 "a0",
39 "a1",
40 "a2",
41 "a3",
42 "a4",
43 "a5",
44 "a6",
45 "a7",
46 "t0",
47 "t1",
48 "t2",
49 "t3",
50 "t4",
51 "t5",
52 "t6",
53 "t7",
54 "t8",
55 "r21", /* reserved in the LP64* ABI, hence no ABI name */
56 "s9",
57 "s0",
58 "s1",
59 "s2",
60 "s3",
61 "s4",
62 "s5",
63 "s6",
64 "s7",
65 "s8"
66};
67#endif
68
69static const int tcg_target_reg_alloc_order[] = {
70 /* Registers preserved across calls */
71 /* TCG_REG_S0 reserved for TCG_AREG0 */
72 TCG_REG_S1,
73 TCG_REG_S2,
74 TCG_REG_S3,
75 TCG_REG_S4,
76 TCG_REG_S5,
77 TCG_REG_S6,
78 TCG_REG_S7,
79 TCG_REG_S8,
80 TCG_REG_S9,
81
82 /* Registers (potentially) clobbered across calls */
83 TCG_REG_T0,
84 TCG_REG_T1,
85 TCG_REG_T2,
86 TCG_REG_T3,
87 TCG_REG_T4,
88 TCG_REG_T5,
89 TCG_REG_T6,
90 TCG_REG_T7,
91 TCG_REG_T8,
92
93 /* Argument registers, opposite order of allocation. */
94 TCG_REG_A7,
95 TCG_REG_A6,
96 TCG_REG_A5,
97 TCG_REG_A4,
98 TCG_REG_A3,
99 TCG_REG_A2,
100 TCG_REG_A1,
101 TCG_REG_A0,
102};
103
104static const int tcg_target_call_iarg_regs[] = {
105 TCG_REG_A0,
106 TCG_REG_A1,
107 TCG_REG_A2,
108 TCG_REG_A3,
109 TCG_REG_A4,
110 TCG_REG_A5,
111 TCG_REG_A6,
112 TCG_REG_A7,
113};
114
115static const int tcg_target_call_oarg_regs[] = {
116 TCG_REG_A0,
117 TCG_REG_A1,
118};
ba0cdd80
WX
119
120#define TCG_CT_CONST_ZERO 0x100
121#define TCG_CT_CONST_S12 0x200
122#define TCG_CT_CONST_N12 0x400
123#define TCG_CT_CONST_U12 0x800
124#define TCG_CT_CONST_C12 0x1000
125#define TCG_CT_CONST_WSZ 0x2000
126
127#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32)
128/*
129 * For softmmu, we need to avoid conflicts with the first 5
130 * argument registers to call the helper. Some of these are
131 * also used for the tlb lookup.
132 */
133#ifdef CONFIG_SOFTMMU
134#define SOFTMMU_RESERVE_REGS MAKE_64BIT_MASK(TCG_REG_A0, 5)
135#else
136#define SOFTMMU_RESERVE_REGS 0
137#endif
138
139
140static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len)
141{
142 return sextract64(val, pos, len);
143}
144
145/* test if a constant matches the constraint */
146static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
147{
148 if (ct & TCG_CT_CONST) {
149 return true;
150 }
151 if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
152 return true;
153 }
154 if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) {
155 return true;
156 }
157 if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) {
158 return true;
159 }
160 if ((ct & TCG_CT_CONST_U12) && val >= 0 && val <= 0xfff) {
161 return true;
162 }
163 if ((ct & TCG_CT_CONST_C12) && ~val >= 0 && ~val <= 0xfff) {
164 return true;
165 }
166 if ((ct & TCG_CT_CONST_WSZ) && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
167 return true;
168 }
169 return false;
170}
bf8c1c81
WX
171
172/*
173 * Relocations
174 */
175
176/*
177 * Relocation records defined in LoongArch ELF psABI v1.00 is way too
178 * complicated; a whopping stack machine is needed to stuff the fields, at
179 * the very least one SOP_PUSH and one SOP_POP (of the correct format) are
180 * needed.
181 *
182 * Hence, define our own simpler relocation types. Numbers are chosen as to
183 * not collide with potential future additions to the true ELF relocation
184 * type enum.
185 */
186
187/* Field Sk16, shifted right by 2; suitable for conditional jumps */
188#define R_LOONGARCH_BR_SK16 256
189/* Field Sd10k16, shifted right by 2; suitable for B and BL */
190#define R_LOONGARCH_BR_SD10K16 257
191
192static bool reloc_br_sk16(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
193{
194 const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
195 intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
196
197 tcg_debug_assert((offset & 3) == 0);
198 offset >>= 2;
199 if (offset == sextreg(offset, 0, 16)) {
200 *src_rw = deposit64(*src_rw, 10, 16, offset);
201 return true;
202 }
203
204 return false;
205}
206
207static bool reloc_br_sd10k16(tcg_insn_unit *src_rw,
208 const tcg_insn_unit *target)
209{
210 const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
211 intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
212
213 tcg_debug_assert((offset & 3) == 0);
214 offset >>= 2;
215 if (offset == sextreg(offset, 0, 26)) {
216 *src_rw = deposit64(*src_rw, 0, 10, offset >> 16); /* slot d10 */
217 *src_rw = deposit64(*src_rw, 10, 16, offset); /* slot k16 */
218 return true;
219 }
220
221 return false;
222}
223
224static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
225 intptr_t value, intptr_t addend)
226{
227 tcg_debug_assert(addend == 0);
228 switch (type) {
229 case R_LOONGARCH_BR_SK16:
230 return reloc_br_sk16(code_ptr, (tcg_insn_unit *)value);
231 case R_LOONGARCH_BR_SD10K16:
232 return reloc_br_sd10k16(code_ptr, (tcg_insn_unit *)value);
233 default:
234 g_assert_not_reached();
235 }
236}
fae2361d
WX
237
238#include "tcg-insn-defs.c.inc"
239
240/*
241 * TCG intrinsics
242 */
243
244static void tcg_out_mb(TCGContext *s, TCGArg a0)
245{
246 /* Baseline LoongArch only has the full barrier, unfortunately. */
247 tcg_out_opc_dbar(s, 0);
248}
249
250/*
251 * Entry-points
252 */
253
254static void tcg_out_op(TCGContext *s, TCGOpcode opc,
255 const TCGArg args[TCG_MAX_OP_ARGS],
256 const int const_args[TCG_MAX_OP_ARGS])
257{
258 TCGArg a0 = args[0];
259
260 switch (opc) {
261 case INDEX_op_mb:
262 tcg_out_mb(s, a0);
263 break;
264
265 default:
266 g_assert_not_reached();
267 }
268}