xref: /qemu/target/hexagon/gen_tcg.h (revision 97ef5f88)
1 /*
2  *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef HEXAGON_GEN_TCG_H
19 #define HEXAGON_GEN_TCG_H
20 
21 /*
22  * Here is a primer to understand the tag names for load/store instructions
23  *
24  * Data types
25  *      b        signed byte                       r0 = memb(r2+#0)
26  *     ub        unsigned byte                     r0 = memub(r2+#0)
27  *      h        signed half word (16 bits)        r0 = memh(r2+#0)
28  *     uh        unsigned half word                r0 = memuh(r2+#0)
29  *      i        integer (32 bits)                 r0 = memw(r2+#0)
30  *      d        double word (64 bits)             r1:0 = memd(r2+#0)
31  *
32  * Addressing modes
33  *     _io       indirect with offset              r0 = memw(r1+#4)
34  *     _ur       absolute with register offset     r0 = memw(r1<<#4+##variable)
35  *     _rr       indirect with register offset     r0 = memw(r1+r4<<#2)
36  *     gp        global pointer relative           r0 = memw(gp+#200)
37  *     _sp       stack pointer relative            r0 = memw(r29+#12)
38  *     _ap       absolute set                      r0 = memw(r1=##variable)
39  *     _pr       post increment register           r0 = memw(r1++m1)
40  *     _pi       post increment immediate          r0 = memb(r1++#1)
41  */
42 
43 /* Macros for complex addressing modes */
44 #define GET_EA_ap \
45     do { \
46         fEA_IMM(UiV); \
47         tcg_gen_movi_tl(ReV, UiV); \
48     } while (0)
49 #define GET_EA_pr \
50     do { \
51         fEA_REG(RxV); \
52         fPM_M(RxV, MuV); \
53     } while (0)
54 #define GET_EA_pi \
55     do { \
56         fEA_REG(RxV); \
57         fPM_I(RxV, siV); \
58     } while (0)
59 
60 
61 /* Instructions with multiple definitions */
62 #define fGEN_TCG_LOAD_AP(RES, SIZE, SIGN) \
63     do { \
64         fMUST_IMMEXT(UiV); \
65         fEA_IMM(UiV); \
66         fLOAD(1, SIZE, SIGN, EA, RES); \
67         tcg_gen_movi_tl(ReV, UiV); \
68     } while (0)
69 
70 #define fGEN_TCG_L4_loadrub_ap(SHORTCODE) \
71     fGEN_TCG_LOAD_AP(RdV, 1, u)
72 #define fGEN_TCG_L4_loadrb_ap(SHORTCODE) \
73     fGEN_TCG_LOAD_AP(RdV, 1, s)
74 #define fGEN_TCG_L4_loadruh_ap(SHORTCODE) \
75     fGEN_TCG_LOAD_AP(RdV, 2, u)
76 #define fGEN_TCG_L4_loadrh_ap(SHORTCODE) \
77     fGEN_TCG_LOAD_AP(RdV, 2, s)
78 #define fGEN_TCG_L4_loadri_ap(SHORTCODE) \
79     fGEN_TCG_LOAD_AP(RdV, 4, u)
80 #define fGEN_TCG_L4_loadrd_ap(SHORTCODE) \
81     fGEN_TCG_LOAD_AP(RddV, 8, u)
82 
83 #define fGEN_TCG_L2_loadrub_pr(SHORTCODE)      SHORTCODE
84 #define fGEN_TCG_L2_loadrub_pi(SHORTCODE)      SHORTCODE
85 #define fGEN_TCG_L2_loadrb_pr(SHORTCODE)       SHORTCODE
86 #define fGEN_TCG_L2_loadrb_pi(SHORTCODE)       SHORTCODE;
87 #define fGEN_TCG_L2_loadruh_pr(SHORTCODE)      SHORTCODE
88 #define fGEN_TCG_L2_loadruh_pi(SHORTCODE)      SHORTCODE;
89 #define fGEN_TCG_L2_loadrh_pr(SHORTCODE)       SHORTCODE
90 #define fGEN_TCG_L2_loadrh_pi(SHORTCODE)       SHORTCODE
91 #define fGEN_TCG_L2_loadri_pr(SHORTCODE)       SHORTCODE
92 #define fGEN_TCG_L2_loadri_pi(SHORTCODE)       SHORTCODE
93 #define fGEN_TCG_L2_loadrd_pr(SHORTCODE)       SHORTCODE
94 #define fGEN_TCG_L2_loadrd_pi(SHORTCODE)       SHORTCODE
95 
96 /*
97  * Predicated loads
98  * Here is a primer to understand the tag names
99  *
100  * Predicate used
101  *      t        true "old" value                  if (p0) r0 = memb(r2+#0)
102  *      f        false "old" value                 if (!p0) r0 = memb(r2+#0)
103  *      tnew     true "new" value                  if (p0.new) r0 = memb(r2+#0)
104  *      fnew     false "new" value                 if (!p0.new) r0 = memb(r2+#0)
105  */
106 #define fGEN_TCG_PRED_LOAD(GET_EA, PRED, SIZE, SIGN) \
107     do { \
108         TCGv LSB = tcg_temp_local_new(); \
109         TCGLabel *label = gen_new_label(); \
110         GET_EA; \
111         PRED;  \
112         PRED_LOAD_CANCEL(LSB, EA); \
113         tcg_gen_movi_tl(RdV, 0); \
114         tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
115             fLOAD(1, SIZE, SIGN, EA, RdV); \
116         gen_set_label(label); \
117         tcg_temp_free(LSB); \
118     } while (0)
119 
120 #define fGEN_TCG_L2_ploadrubt_pi(SHORTCODE) \
121     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 1, u)
122 #define fGEN_TCG_L2_ploadrubf_pi(SHORTCODE) \
123     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 1, u)
124 #define fGEN_TCG_L2_ploadrubtnew_pi(SHORTCODE) \
125     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 1, u)
126 #define fGEN_TCG_L2_ploadrubfnew_pi(SHORTCODE) \
127     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEWNOT(PtN), 1, u)
128 #define fGEN_TCG_L2_ploadrbt_pi(SHORTCODE) \
129     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 1, s)
130 #define fGEN_TCG_L2_ploadrbf_pi(SHORTCODE) \
131     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 1, s)
132 #define fGEN_TCG_L2_ploadrbtnew_pi(SHORTCODE) \
133     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 1, s)
134 #define fGEN_TCG_L2_ploadrbfnew_pi(SHORTCODE) \
135     fGEN_TCG_PRED_LOAD({ fEA_REG(RxV); fPM_I(RxV, siV); }, \
136                        fLSBNEWNOT(PtN), 1, s)
137 
138 #define fGEN_TCG_L2_ploadruht_pi(SHORTCODE) \
139     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 2, u)
140 #define fGEN_TCG_L2_ploadruhf_pi(SHORTCODE) \
141     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 2, u)
142 #define fGEN_TCG_L2_ploadruhtnew_pi(SHORTCODE) \
143     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 2, u)
144 #define fGEN_TCG_L2_ploadruhfnew_pi(SHORTCODE) \
145     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEWNOT(PtN), 2, u)
146 #define fGEN_TCG_L2_ploadrht_pi(SHORTCODE) \
147     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 2, s)
148 #define fGEN_TCG_L2_ploadrhf_pi(SHORTCODE) \
149     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 2, s)
150 #define fGEN_TCG_L2_ploadrhtnew_pi(SHORTCODE) \
151     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 2, s)
152 #define fGEN_TCG_L2_ploadrhfnew_pi(SHORTCODE) \
153     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEWNOT(PtN), 2, s)
154 
155 #define fGEN_TCG_L2_ploadrit_pi(SHORTCODE) \
156     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 4, u)
157 #define fGEN_TCG_L2_ploadrif_pi(SHORTCODE) \
158     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 4, u)
159 #define fGEN_TCG_L2_ploadritnew_pi(SHORTCODE) \
160     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 4, u)
161 #define fGEN_TCG_L2_ploadrifnew_pi(SHORTCODE) \
162     fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEWNOT(PtN), 4, u)
163 
164 /* Predicated loads into a register pair */
165 #define fGEN_TCG_PRED_LOAD_PAIR(GET_EA, PRED) \
166     do { \
167         TCGv LSB = tcg_temp_local_new(); \
168         TCGLabel *label = gen_new_label(); \
169         GET_EA; \
170         PRED;  \
171         PRED_LOAD_CANCEL(LSB, EA); \
172         tcg_gen_movi_i64(RddV, 0); \
173         tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
174             fLOAD(1, 8, u, EA, RddV); \
175         gen_set_label(label); \
176         tcg_temp_free(LSB); \
177     } while (0)
178 
179 #define fGEN_TCG_L2_ploadrdt_pi(SHORTCODE) \
180     fGEN_TCG_PRED_LOAD_PAIR(GET_EA_pi, fLSBOLD(PtV))
181 #define fGEN_TCG_L2_ploadrdf_pi(SHORTCODE) \
182     fGEN_TCG_PRED_LOAD_PAIR(GET_EA_pi, fLSBOLDNOT(PtV))
183 #define fGEN_TCG_L2_ploadrdtnew_pi(SHORTCODE) \
184     fGEN_TCG_PRED_LOAD_PAIR(GET_EA_pi, fLSBNEW(PtN))
185 #define fGEN_TCG_L2_ploadrdfnew_pi(SHORTCODE) \
186     fGEN_TCG_PRED_LOAD_PAIR(GET_EA_pi, fLSBNEWNOT(PtN))
187 
188 /* load-locked and store-locked */
189 #define fGEN_TCG_L2_loadw_locked(SHORTCODE) \
190     SHORTCODE
191 #define fGEN_TCG_L4_loadd_locked(SHORTCODE) \
192     SHORTCODE
193 #define fGEN_TCG_S2_storew_locked(SHORTCODE) \
194     do { SHORTCODE; READ_PREG(PdV, PdN); } while (0)
195 #define fGEN_TCG_S4_stored_locked(SHORTCODE) \
196     do { SHORTCODE; READ_PREG(PdV, PdN); } while (0)
197 
198 /* Floating point */
199 #define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \
200     gen_helper_conv_sf2df(RddV, cpu_env, RsV)
201 #define fGEN_TCG_F2_conv_df2sf(SHORTCODE) \
202     gen_helper_conv_df2sf(RdV, cpu_env, RssV)
203 #define fGEN_TCG_F2_conv_uw2sf(SHORTCODE) \
204     gen_helper_conv_uw2sf(RdV, cpu_env, RsV)
205 #define fGEN_TCG_F2_conv_uw2df(SHORTCODE) \
206     gen_helper_conv_uw2df(RddV, cpu_env, RsV)
207 #define fGEN_TCG_F2_conv_w2sf(SHORTCODE) \
208     gen_helper_conv_w2sf(RdV, cpu_env, RsV)
209 #define fGEN_TCG_F2_conv_w2df(SHORTCODE) \
210     gen_helper_conv_w2df(RddV, cpu_env, RsV)
211 #define fGEN_TCG_F2_conv_ud2sf(SHORTCODE) \
212     gen_helper_conv_ud2sf(RdV, cpu_env, RssV)
213 #define fGEN_TCG_F2_conv_ud2df(SHORTCODE) \
214     gen_helper_conv_ud2df(RddV, cpu_env, RssV)
215 #define fGEN_TCG_F2_conv_d2sf(SHORTCODE) \
216     gen_helper_conv_d2sf(RdV, cpu_env, RssV)
217 #define fGEN_TCG_F2_conv_d2df(SHORTCODE) \
218     gen_helper_conv_d2df(RddV, cpu_env, RssV)
219 #define fGEN_TCG_F2_conv_sf2uw(SHORTCODE) \
220     gen_helper_conv_sf2uw(RdV, cpu_env, RsV)
221 #define fGEN_TCG_F2_conv_sf2w(SHORTCODE) \
222     gen_helper_conv_sf2w(RdV, cpu_env, RsV)
223 #define fGEN_TCG_F2_conv_sf2ud(SHORTCODE) \
224     gen_helper_conv_sf2ud(RddV, cpu_env, RsV)
225 #define fGEN_TCG_F2_conv_sf2d(SHORTCODE) \
226     gen_helper_conv_sf2d(RddV, cpu_env, RsV)
227 #define fGEN_TCG_F2_conv_df2uw(SHORTCODE) \
228     gen_helper_conv_df2uw(RdV, cpu_env, RssV)
229 #define fGEN_TCG_F2_conv_df2w(SHORTCODE) \
230     gen_helper_conv_df2w(RdV, cpu_env, RssV)
231 #define fGEN_TCG_F2_conv_df2ud(SHORTCODE) \
232     gen_helper_conv_df2ud(RddV, cpu_env, RssV)
233 #define fGEN_TCG_F2_conv_df2d(SHORTCODE) \
234     gen_helper_conv_df2d(RddV, cpu_env, RssV)
235 #define fGEN_TCG_F2_conv_sf2uw_chop(SHORTCODE) \
236     gen_helper_conv_sf2uw_chop(RdV, cpu_env, RsV)
237 #define fGEN_TCG_F2_conv_sf2w_chop(SHORTCODE) \
238     gen_helper_conv_sf2w_chop(RdV, cpu_env, RsV)
239 #define fGEN_TCG_F2_conv_sf2ud_chop(SHORTCODE) \
240     gen_helper_conv_sf2ud_chop(RddV, cpu_env, RsV)
241 #define fGEN_TCG_F2_conv_sf2d_chop(SHORTCODE) \
242     gen_helper_conv_sf2d_chop(RddV, cpu_env, RsV)
243 #define fGEN_TCG_F2_conv_df2uw_chop(SHORTCODE) \
244     gen_helper_conv_df2uw_chop(RdV, cpu_env, RssV)
245 #define fGEN_TCG_F2_conv_df2w_chop(SHORTCODE) \
246     gen_helper_conv_df2w_chop(RdV, cpu_env, RssV)
247 #define fGEN_TCG_F2_conv_df2ud_chop(SHORTCODE) \
248     gen_helper_conv_df2ud_chop(RddV, cpu_env, RssV)
249 #define fGEN_TCG_F2_conv_df2d_chop(SHORTCODE) \
250     gen_helper_conv_df2d_chop(RddV, cpu_env, RssV)
251 #define fGEN_TCG_F2_sfadd(SHORTCODE) \
252     gen_helper_sfadd(RdV, cpu_env, RsV, RtV)
253 #define fGEN_TCG_F2_sfsub(SHORTCODE) \
254     gen_helper_sfsub(RdV, cpu_env, RsV, RtV)
255 #define fGEN_TCG_F2_sfcmpeq(SHORTCODE) \
256     gen_helper_sfcmpeq(PdV, cpu_env, RsV, RtV)
257 #define fGEN_TCG_F2_sfcmpgt(SHORTCODE) \
258     gen_helper_sfcmpgt(PdV, cpu_env, RsV, RtV)
259 #define fGEN_TCG_F2_sfcmpge(SHORTCODE) \
260     gen_helper_sfcmpge(PdV, cpu_env, RsV, RtV)
261 #define fGEN_TCG_F2_sfcmpuo(SHORTCODE) \
262     gen_helper_sfcmpuo(PdV, cpu_env, RsV, RtV)
263 #define fGEN_TCG_F2_sfmax(SHORTCODE) \
264     gen_helper_sfmax(RdV, cpu_env, RsV, RtV)
265 #define fGEN_TCG_F2_sfmin(SHORTCODE) \
266     gen_helper_sfmin(RdV, cpu_env, RsV, RtV)
267 #define fGEN_TCG_F2_sfclass(SHORTCODE) \
268     do { \
269         TCGv imm = tcg_const_tl(uiV); \
270         gen_helper_sfclass(PdV, cpu_env, RsV, imm); \
271         tcg_temp_free(imm); \
272     } while (0)
273 #define fGEN_TCG_F2_sffixupn(SHORTCODE) \
274     gen_helper_sffixupn(RdV, cpu_env, RsV, RtV)
275 #define fGEN_TCG_F2_sffixupd(SHORTCODE) \
276     gen_helper_sffixupd(RdV, cpu_env, RsV, RtV)
277 #define fGEN_TCG_F2_sffixupr(SHORTCODE) \
278     gen_helper_sffixupr(RdV, cpu_env, RsV)
279 #define fGEN_TCG_F2_dfadd(SHORTCODE) \
280     gen_helper_dfadd(RddV, cpu_env, RssV, RttV)
281 #define fGEN_TCG_F2_dfsub(SHORTCODE) \
282     gen_helper_dfsub(RddV, cpu_env, RssV, RttV)
283 #define fGEN_TCG_F2_dfmax(SHORTCODE) \
284     gen_helper_dfmax(RddV, cpu_env, RssV, RttV)
285 #define fGEN_TCG_F2_dfmin(SHORTCODE) \
286     gen_helper_dfmin(RddV, cpu_env, RssV, RttV)
287 #define fGEN_TCG_F2_dfcmpeq(SHORTCODE) \
288     gen_helper_dfcmpeq(PdV, cpu_env, RssV, RttV)
289 #define fGEN_TCG_F2_dfcmpgt(SHORTCODE) \
290     gen_helper_dfcmpgt(PdV, cpu_env, RssV, RttV)
291 #define fGEN_TCG_F2_dfcmpge(SHORTCODE) \
292     gen_helper_dfcmpge(PdV, cpu_env, RssV, RttV)
293 #define fGEN_TCG_F2_dfcmpuo(SHORTCODE) \
294     gen_helper_dfcmpuo(PdV, cpu_env, RssV, RttV)
295 #define fGEN_TCG_F2_dfclass(SHORTCODE) \
296     do { \
297         TCGv imm = tcg_const_tl(uiV); \
298         gen_helper_dfclass(PdV, cpu_env, RssV, imm); \
299         tcg_temp_free(imm); \
300     } while (0)
301 #define fGEN_TCG_F2_sfmpy(SHORTCODE) \
302     gen_helper_sfmpy(RdV, cpu_env, RsV, RtV)
303 #define fGEN_TCG_F2_sffma(SHORTCODE) \
304     gen_helper_sffma(RxV, cpu_env, RxV, RsV, RtV)
305 #define fGEN_TCG_F2_sffma_sc(SHORTCODE) \
306     gen_helper_sffma_sc(RxV, cpu_env, RxV, RsV, RtV, PuV)
307 #define fGEN_TCG_F2_sffms(SHORTCODE) \
308     gen_helper_sffms(RxV, cpu_env, RxV, RsV, RtV)
309 #define fGEN_TCG_F2_sffma_lib(SHORTCODE) \
310     gen_helper_sffma_lib(RxV, cpu_env, RxV, RsV, RtV)
311 #define fGEN_TCG_F2_sffms_lib(SHORTCODE) \
312     gen_helper_sffms_lib(RxV, cpu_env, RxV, RsV, RtV)
313 
314 #define fGEN_TCG_F2_dfmpyfix(SHORTCODE) \
315     gen_helper_dfmpyfix(RddV, cpu_env, RssV, RttV)
316 #define fGEN_TCG_F2_dfmpyhh(SHORTCODE) \
317     gen_helper_dfmpyhh(RxxV, cpu_env, RxxV, RssV, RttV)
318 
319 #endif
320