xref: /openbmc/qemu/tcg/tci.c (revision b701f195)
1244f1441SYang Zhong /*
2244f1441SYang Zhong  * Tiny Code Interpreter for QEMU
3244f1441SYang Zhong  *
4244f1441SYang Zhong  * Copyright (c) 2009, 2011, 2016 Stefan Weil
5244f1441SYang Zhong  *
6244f1441SYang Zhong  * This program is free software: you can redistribute it and/or modify
7244f1441SYang Zhong  * it under the terms of the GNU General Public License as published by
8244f1441SYang Zhong  * the Free Software Foundation, either version 2 of the License, or
9244f1441SYang Zhong  * (at your option) any later version.
10244f1441SYang Zhong  *
11244f1441SYang Zhong  * This program is distributed in the hope that it will be useful,
12244f1441SYang Zhong  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13244f1441SYang Zhong  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14244f1441SYang Zhong  * GNU General Public License for more details.
15244f1441SYang Zhong  *
16244f1441SYang Zhong  * You should have received a copy of the GNU General Public License
17244f1441SYang Zhong  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18244f1441SYang Zhong  */
19244f1441SYang Zhong 
20244f1441SYang Zhong #include "qemu/osdep.h"
21ad3d0e4dSRichard Henderson #include "tcg/tcg.h"
22d2ba8026SRichard Henderson #include "tcg/tcg-ldst.h"
237b7d8b2dSRichard Henderson #include <ffi.h>
24244f1441SYang Zhong 
257b7d8b2dSRichard Henderson 
267b7d8b2dSRichard Henderson /*
277b7d8b2dSRichard Henderson  * Enable TCI assertions only when debugging TCG (and without NDEBUG defined).
287b7d8b2dSRichard Henderson  * Without assertions, the interpreter runs much faster.
297b7d8b2dSRichard Henderson  */
30244f1441SYang Zhong #if defined(CONFIG_DEBUG_TCG)
31244f1441SYang Zhong # define tci_assert(cond) assert(cond)
32244f1441SYang Zhong #else
3392bc4fadSRichard Henderson # define tci_assert(cond) ((void)(cond))
34244f1441SYang Zhong #endif
35244f1441SYang Zhong 
3613e71f08SRichard Henderson __thread uintptr_t tci_tb_ptr;
3713e71f08SRichard Henderson 
tci_write_reg64(tcg_target_ulong * regs,uint32_t high_index,uint32_t low_index,uint64_t value)385e75150cSEmilio G. Cota static void tci_write_reg64(tcg_target_ulong *regs, uint32_t high_index,
395e75150cSEmilio G. Cota                             uint32_t low_index, uint64_t value)
40244f1441SYang Zhong {
41f6db0d8dSRichard Henderson     regs[low_index] = (uint32_t)value;
427e00a080SRichard Henderson     regs[high_index] = value >> 32;
43244f1441SYang Zhong }
44244f1441SYang Zhong 
45244f1441SYang Zhong /* Create a 64 bit value from two 32 bit values. */
tci_uint64(uint32_t high,uint32_t low)46244f1441SYang Zhong static uint64_t tci_uint64(uint32_t high, uint32_t low)
47244f1441SYang Zhong {
48244f1441SYang Zhong     return ((uint64_t)high << 32) + low;
49244f1441SYang Zhong }
50244f1441SYang Zhong 
51cdd9799bSRichard Henderson /*
52cdd9799bSRichard Henderson  * Load sets of arguments all at once.  The naming convention is:
53cdd9799bSRichard Henderson  *   tci_args_<arguments>
54cdd9799bSRichard Henderson  * where arguments is a sequence of
55cdd9799bSRichard Henderson  *
5679dd3a4fSRichard Henderson  *   b = immediate (bit position)
57963e9fa2SRichard Henderson  *   c = condition (TCGCond)
58b95aa12eSRichard Henderson  *   i = immediate (uint32_t)
59b95aa12eSRichard Henderson  *   I = immediate (tcg_target_ulong)
60f28ca03eSRichard Henderson  *   l = label or pointer
619002ffcbSRichard Henderson  *   m = immediate (MemOpIdx)
627b7d8b2dSRichard Henderson  *   n = immediate (call return length)
63cdd9799bSRichard Henderson  *   r = register
64cdd9799bSRichard Henderson  *   s = signed ldst offset
65cdd9799bSRichard Henderson  */
66cdd9799bSRichard Henderson 
tci_args_l(uint32_t insn,const void * tb_ptr,void ** l0)6765089889SRichard Henderson static void tci_args_l(uint32_t insn, const void *tb_ptr, void **l0)
6892bc4fadSRichard Henderson {
6965089889SRichard Henderson     int diff = sextract32(insn, 12, 20);
7065089889SRichard Henderson     *l0 = diff ? (void *)tb_ptr + diff : NULL;
7192bc4fadSRichard Henderson }
7292bc4fadSRichard Henderson 
tci_args_r(uint32_t insn,TCGReg * r0)736eea0434SRichard Henderson static void tci_args_r(uint32_t insn, TCGReg *r0)
746eea0434SRichard Henderson {
756eea0434SRichard Henderson     *r0 = extract32(insn, 8, 4);
766eea0434SRichard Henderson }
776eea0434SRichard Henderson 
tci_args_nl(uint32_t insn,const void * tb_ptr,uint8_t * n0,void ** l1)7865089889SRichard Henderson static void tci_args_nl(uint32_t insn, const void *tb_ptr,
7965089889SRichard Henderson                         uint8_t *n0, void **l1)
80f28ca03eSRichard Henderson {
8165089889SRichard Henderson     *n0 = extract32(insn, 8, 4);
8265089889SRichard Henderson     *l1 = sextract32(insn, 12, 20) + (void *)tb_ptr;
83f28ca03eSRichard Henderson }
84f28ca03eSRichard Henderson 
tci_args_rl(uint32_t insn,const void * tb_ptr,TCGReg * r0,void ** l1)8565089889SRichard Henderson static void tci_args_rl(uint32_t insn, const void *tb_ptr,
8665089889SRichard Henderson                         TCGReg *r0, void **l1)
877b7d8b2dSRichard Henderson {
8865089889SRichard Henderson     *r0 = extract32(insn, 8, 4);
8965089889SRichard Henderson     *l1 = sextract32(insn, 12, 20) + (void *)tb_ptr;
907b7d8b2dSRichard Henderson }
917b7d8b2dSRichard Henderson 
tci_args_rr(uint32_t insn,TCGReg * r0,TCGReg * r1)9265089889SRichard Henderson static void tci_args_rr(uint32_t insn, TCGReg *r0, TCGReg *r1)
93fc8ec9e1SRichard Henderson {
9465089889SRichard Henderson     *r0 = extract32(insn, 8, 4);
9565089889SRichard Henderson     *r1 = extract32(insn, 12, 4);
96fc8ec9e1SRichard Henderson }
97fc8ec9e1SRichard Henderson 
tci_args_ri(uint32_t insn,TCGReg * r0,tcg_target_ulong * i1)9865089889SRichard Henderson static void tci_args_ri(uint32_t insn, TCGReg *r0, tcg_target_ulong *i1)
99fc4a62f6SRichard Henderson {
10065089889SRichard Henderson     *r0 = extract32(insn, 8, 4);
10165089889SRichard Henderson     *i1 = sextract32(insn, 12, 20);
102fc4a62f6SRichard Henderson }
103fc4a62f6SRichard Henderson 
tci_args_rrm(uint32_t insn,TCGReg * r0,TCGReg * r1,MemOpIdx * m2)10465089889SRichard Henderson static void tci_args_rrm(uint32_t insn, TCGReg *r0,
1059002ffcbSRichard Henderson                          TCGReg *r1, MemOpIdx *m2)
106b95aa12eSRichard Henderson {
10765089889SRichard Henderson     *r0 = extract32(insn, 8, 4);
10865089889SRichard Henderson     *r1 = extract32(insn, 12, 4);
109*ab64da79SRichard Henderson     *m2 = extract32(insn, 16, 16);
110b95aa12eSRichard Henderson }
111b95aa12eSRichard Henderson 
tci_args_rrr(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2)11265089889SRichard Henderson static void tci_args_rrr(uint32_t insn, TCGReg *r0, TCGReg *r1, TCGReg *r2)
113b95aa12eSRichard Henderson {
11465089889SRichard Henderson     *r0 = extract32(insn, 8, 4);
11565089889SRichard Henderson     *r1 = extract32(insn, 12, 4);
11665089889SRichard Henderson     *r2 = extract32(insn, 16, 4);
11763041ed2SRichard Henderson }
11863041ed2SRichard Henderson 
tci_args_rrs(uint32_t insn,TCGReg * r0,TCGReg * r1,int32_t * i2)11965089889SRichard Henderson static void tci_args_rrs(uint32_t insn, TCGReg *r0, TCGReg *r1, int32_t *i2)
120e85e4b8fSRichard Henderson {
12165089889SRichard Henderson     *r0 = extract32(insn, 8, 4);
12265089889SRichard Henderson     *r1 = extract32(insn, 12, 4);
12365089889SRichard Henderson     *i2 = sextract32(insn, 16, 16);
124e85e4b8fSRichard Henderson }
125e85e4b8fSRichard Henderson 
tci_args_rrbb(uint32_t insn,TCGReg * r0,TCGReg * r1,uint8_t * i2,uint8_t * i3)1260f10d7c5SRichard Henderson static void tci_args_rrbb(uint32_t insn, TCGReg *r0, TCGReg *r1,
1270f10d7c5SRichard Henderson                           uint8_t *i2, uint8_t *i3)
1280f10d7c5SRichard Henderson {
1290f10d7c5SRichard Henderson     *r0 = extract32(insn, 8, 4);
1300f10d7c5SRichard Henderson     *r1 = extract32(insn, 12, 4);
1310f10d7c5SRichard Henderson     *i2 = extract32(insn, 16, 6);
1320f10d7c5SRichard Henderson     *i3 = extract32(insn, 22, 6);
1330f10d7c5SRichard Henderson }
1340f10d7c5SRichard Henderson 
tci_args_rrrc(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2,TCGCond * c3)13565089889SRichard Henderson static void tci_args_rrrc(uint32_t insn,
136963e9fa2SRichard Henderson                           TCGReg *r0, TCGReg *r1, TCGReg *r2, TCGCond *c3)
137963e9fa2SRichard Henderson {
13865089889SRichard Henderson     *r0 = extract32(insn, 8, 4);
13965089889SRichard Henderson     *r1 = extract32(insn, 12, 4);
14065089889SRichard Henderson     *r2 = extract32(insn, 16, 4);
14165089889SRichard Henderson     *c3 = extract32(insn, 20, 4);
142963e9fa2SRichard Henderson }
143963e9fa2SRichard Henderson 
tci_args_rrrbb(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2,uint8_t * i3,uint8_t * i4)14465089889SRichard Henderson static void tci_args_rrrbb(uint32_t insn, TCGReg *r0, TCGReg *r1,
14579dd3a4fSRichard Henderson                            TCGReg *r2, uint8_t *i3, uint8_t *i4)
14679dd3a4fSRichard Henderson {
14765089889SRichard Henderson     *r0 = extract32(insn, 8, 4);
14865089889SRichard Henderson     *r1 = extract32(insn, 12, 4);
14965089889SRichard Henderson     *r2 = extract32(insn, 16, 4);
15065089889SRichard Henderson     *i3 = extract32(insn, 20, 6);
15165089889SRichard Henderson     *i4 = extract32(insn, 26, 6);
15279dd3a4fSRichard Henderson }
15379dd3a4fSRichard Henderson 
tci_args_rrrrr(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2,TCGReg * r3,TCGReg * r4)15465089889SRichard Henderson static void tci_args_rrrrr(uint32_t insn, TCGReg *r0, TCGReg *r1,
15565089889SRichard Henderson                            TCGReg *r2, TCGReg *r3, TCGReg *r4)
15663041ed2SRichard Henderson {
15765089889SRichard Henderson     *r0 = extract32(insn, 8, 4);
15865089889SRichard Henderson     *r1 = extract32(insn, 12, 4);
15965089889SRichard Henderson     *r2 = extract32(insn, 16, 4);
16065089889SRichard Henderson     *r3 = extract32(insn, 20, 4);
16165089889SRichard Henderson     *r4 = extract32(insn, 24, 4);
16263041ed2SRichard Henderson }
16363041ed2SRichard Henderson 
tci_args_rrrr(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2,TCGReg * r3)16465089889SRichard Henderson static void tci_args_rrrr(uint32_t insn,
165cbe87131SRichard Henderson                           TCGReg *r0, TCGReg *r1, TCGReg *r2, TCGReg *r3)
166cbe87131SRichard Henderson {
16765089889SRichard Henderson     *r0 = extract32(insn, 8, 4);
16865089889SRichard Henderson     *r1 = extract32(insn, 12, 4);
16965089889SRichard Henderson     *r2 = extract32(insn, 16, 4);
17065089889SRichard Henderson     *r3 = extract32(insn, 20, 4);
171cbe87131SRichard Henderson }
172cbe87131SRichard Henderson 
tci_args_rrrrrc(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2,TCGReg * r3,TCGReg * r4,TCGCond * c5)17365089889SRichard Henderson static void tci_args_rrrrrc(uint32_t insn, TCGReg *r0, TCGReg *r1,
174817cadd6SRichard Henderson                             TCGReg *r2, TCGReg *r3, TCGReg *r4, TCGCond *c5)
175817cadd6SRichard Henderson {
17665089889SRichard Henderson     *r0 = extract32(insn, 8, 4);
17765089889SRichard Henderson     *r1 = extract32(insn, 12, 4);
17865089889SRichard Henderson     *r2 = extract32(insn, 16, 4);
17965089889SRichard Henderson     *r3 = extract32(insn, 20, 4);
18065089889SRichard Henderson     *r4 = extract32(insn, 24, 4);
18165089889SRichard Henderson     *c5 = extract32(insn, 28, 4);
182817cadd6SRichard Henderson }
183120402b5SRichard Henderson 
tci_args_rrrrrr(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2,TCGReg * r3,TCGReg * r4,TCGReg * r5)18465089889SRichard Henderson static void tci_args_rrrrrr(uint32_t insn, TCGReg *r0, TCGReg *r1,
185120402b5SRichard Henderson                             TCGReg *r2, TCGReg *r3, TCGReg *r4, TCGReg *r5)
186120402b5SRichard Henderson {
18765089889SRichard Henderson     *r0 = extract32(insn, 8, 4);
18865089889SRichard Henderson     *r1 = extract32(insn, 12, 4);
18965089889SRichard Henderson     *r2 = extract32(insn, 16, 4);
19065089889SRichard Henderson     *r3 = extract32(insn, 20, 4);
19165089889SRichard Henderson     *r4 = extract32(insn, 24, 4);
19265089889SRichard Henderson     *r5 = extract32(insn, 28, 4);
193120402b5SRichard Henderson }
194817cadd6SRichard Henderson 
tci_compare32(uint32_t u0,uint32_t u1,TCGCond condition)195244f1441SYang Zhong static bool tci_compare32(uint32_t u0, uint32_t u1, TCGCond condition)
196244f1441SYang Zhong {
197244f1441SYang Zhong     bool result = false;
198244f1441SYang Zhong     int32_t i0 = u0;
199244f1441SYang Zhong     int32_t i1 = u1;
200244f1441SYang Zhong     switch (condition) {
201244f1441SYang Zhong     case TCG_COND_EQ:
202244f1441SYang Zhong         result = (u0 == u1);
203244f1441SYang Zhong         break;
204244f1441SYang Zhong     case TCG_COND_NE:
205244f1441SYang Zhong         result = (u0 != u1);
206244f1441SYang Zhong         break;
207244f1441SYang Zhong     case TCG_COND_LT:
208244f1441SYang Zhong         result = (i0 < i1);
209244f1441SYang Zhong         break;
210244f1441SYang Zhong     case TCG_COND_GE:
211244f1441SYang Zhong         result = (i0 >= i1);
212244f1441SYang Zhong         break;
213244f1441SYang Zhong     case TCG_COND_LE:
214244f1441SYang Zhong         result = (i0 <= i1);
215244f1441SYang Zhong         break;
216244f1441SYang Zhong     case TCG_COND_GT:
217244f1441SYang Zhong         result = (i0 > i1);
218244f1441SYang Zhong         break;
219244f1441SYang Zhong     case TCG_COND_LTU:
220244f1441SYang Zhong         result = (u0 < u1);
221244f1441SYang Zhong         break;
222244f1441SYang Zhong     case TCG_COND_GEU:
223244f1441SYang Zhong         result = (u0 >= u1);
224244f1441SYang Zhong         break;
225244f1441SYang Zhong     case TCG_COND_LEU:
226244f1441SYang Zhong         result = (u0 <= u1);
227244f1441SYang Zhong         break;
228244f1441SYang Zhong     case TCG_COND_GTU:
229244f1441SYang Zhong         result = (u0 > u1);
230244f1441SYang Zhong         break;
231244f1441SYang Zhong     default:
232f6996f99SRichard Henderson         g_assert_not_reached();
233244f1441SYang Zhong     }
234244f1441SYang Zhong     return result;
235244f1441SYang Zhong }
236244f1441SYang Zhong 
tci_compare64(uint64_t u0,uint64_t u1,TCGCond condition)237244f1441SYang Zhong static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition)
238244f1441SYang Zhong {
239244f1441SYang Zhong     bool result = false;
240244f1441SYang Zhong     int64_t i0 = u0;
241244f1441SYang Zhong     int64_t i1 = u1;
242244f1441SYang Zhong     switch (condition) {
243244f1441SYang Zhong     case TCG_COND_EQ:
244244f1441SYang Zhong         result = (u0 == u1);
245244f1441SYang Zhong         break;
246244f1441SYang Zhong     case TCG_COND_NE:
247244f1441SYang Zhong         result = (u0 != u1);
248244f1441SYang Zhong         break;
249244f1441SYang Zhong     case TCG_COND_LT:
250244f1441SYang Zhong         result = (i0 < i1);
251244f1441SYang Zhong         break;
252244f1441SYang Zhong     case TCG_COND_GE:
253244f1441SYang Zhong         result = (i0 >= i1);
254244f1441SYang Zhong         break;
255244f1441SYang Zhong     case TCG_COND_LE:
256244f1441SYang Zhong         result = (i0 <= i1);
257244f1441SYang Zhong         break;
258244f1441SYang Zhong     case TCG_COND_GT:
259244f1441SYang Zhong         result = (i0 > i1);
260244f1441SYang Zhong         break;
261244f1441SYang Zhong     case TCG_COND_LTU:
262244f1441SYang Zhong         result = (u0 < u1);
263244f1441SYang Zhong         break;
264244f1441SYang Zhong     case TCG_COND_GEU:
265244f1441SYang Zhong         result = (u0 >= u1);
266244f1441SYang Zhong         break;
267244f1441SYang Zhong     case TCG_COND_LEU:
268244f1441SYang Zhong         result = (u0 <= u1);
269244f1441SYang Zhong         break;
270244f1441SYang Zhong     case TCG_COND_GTU:
271244f1441SYang Zhong         result = (u0 > u1);
272244f1441SYang Zhong         break;
273244f1441SYang Zhong     default:
274f6996f99SRichard Henderson         g_assert_not_reached();
275244f1441SYang Zhong     }
276244f1441SYang Zhong     return result;
277244f1441SYang Zhong }
278244f1441SYang Zhong 
tci_qemu_ld(CPUArchState * env,uint64_t taddr,MemOpIdx oi,const void * tb_ptr)279dd7dc93eSRichard Henderson static uint64_t tci_qemu_ld(CPUArchState *env, uint64_t taddr,
2809002ffcbSRichard Henderson                             MemOpIdx oi, const void *tb_ptr)
28169acc02aSRichard Henderson {
282fe1bee3aSRichard Henderson     MemOp mop = get_memop(oi);
283d1b1348cSRichard Henderson     uintptr_t ra = (uintptr_t)tb_ptr;
284d1b1348cSRichard Henderson 
2850cadc1edSRichard Henderson     switch (mop & MO_SSIZE) {
28669acc02aSRichard Henderson     case MO_UB:
2870cadc1edSRichard Henderson         return helper_ldub_mmu(env, taddr, oi, ra);
28869acc02aSRichard Henderson     case MO_SB:
2890cadc1edSRichard Henderson         return helper_ldsb_mmu(env, taddr, oi, ra);
2900cadc1edSRichard Henderson     case MO_UW:
2910cadc1edSRichard Henderson         return helper_lduw_mmu(env, taddr, oi, ra);
2920cadc1edSRichard Henderson     case MO_SW:
2930cadc1edSRichard Henderson         return helper_ldsw_mmu(env, taddr, oi, ra);
2940cadc1edSRichard Henderson     case MO_UL:
2950cadc1edSRichard Henderson         return helper_ldul_mmu(env, taddr, oi, ra);
2960cadc1edSRichard Henderson     case MO_SL:
2970cadc1edSRichard Henderson         return helper_ldsl_mmu(env, taddr, oi, ra);
2980cadc1edSRichard Henderson     case MO_UQ:
2990cadc1edSRichard Henderson         return helper_ldq_mmu(env, taddr, oi, ra);
30069acc02aSRichard Henderson     default:
30169acc02aSRichard Henderson         g_assert_not_reached();
30269acc02aSRichard Henderson     }
30369acc02aSRichard Henderson }
30469acc02aSRichard Henderson 
tci_qemu_st(CPUArchState * env,uint64_t taddr,uint64_t val,MemOpIdx oi,const void * tb_ptr)305dd7dc93eSRichard Henderson static void tci_qemu_st(CPUArchState *env, uint64_t taddr, uint64_t val,
3069002ffcbSRichard Henderson                         MemOpIdx oi, const void *tb_ptr)
30769acc02aSRichard Henderson {
308fe1bee3aSRichard Henderson     MemOp mop = get_memop(oi);
309d1b1348cSRichard Henderson     uintptr_t ra = (uintptr_t)tb_ptr;
310d1b1348cSRichard Henderson 
3110cadc1edSRichard Henderson     switch (mop & MO_SIZE) {
31269acc02aSRichard Henderson     case MO_UB:
3130cadc1edSRichard Henderson         helper_stb_mmu(env, taddr, val, oi, ra);
31469acc02aSRichard Henderson         break;
3150cadc1edSRichard Henderson     case MO_UW:
3160cadc1edSRichard Henderson         helper_stw_mmu(env, taddr, val, oi, ra);
31769acc02aSRichard Henderson         break;
3180cadc1edSRichard Henderson     case MO_UL:
3190cadc1edSRichard Henderson         helper_stl_mmu(env, taddr, val, oi, ra);
32069acc02aSRichard Henderson         break;
3210cadc1edSRichard Henderson     case MO_UQ:
3220cadc1edSRichard Henderson         helper_stq_mmu(env, taddr, val, oi, ra);
32369acc02aSRichard Henderson         break;
32469acc02aSRichard Henderson     default:
32569acc02aSRichard Henderson         g_assert_not_reached();
32669acc02aSRichard Henderson     }
32769acc02aSRichard Henderson }
32869acc02aSRichard Henderson 
3297f33f5cdSRichard Henderson #if TCG_TARGET_REG_BITS == 64
3307f33f5cdSRichard Henderson # define CASE_32_64(x) \
3317f33f5cdSRichard Henderson         case glue(glue(INDEX_op_, x), _i64): \
3327f33f5cdSRichard Henderson         case glue(glue(INDEX_op_, x), _i32):
3337f33f5cdSRichard Henderson # define CASE_64(x) \
3347f33f5cdSRichard Henderson         case glue(glue(INDEX_op_, x), _i64):
3357f33f5cdSRichard Henderson #else
3367f33f5cdSRichard Henderson # define CASE_32_64(x) \
3377f33f5cdSRichard Henderson         case glue(glue(INDEX_op_, x), _i32):
3387f33f5cdSRichard Henderson # define CASE_64(x)
3397f33f5cdSRichard Henderson #endif
3407f33f5cdSRichard Henderson 
341244f1441SYang Zhong /* Interpret pseudo code in tb. */
342c905a368SDaniele Buono /*
343c905a368SDaniele Buono  * Disable CFI checks.
344c905a368SDaniele Buono  * One possible operation in the pseudo code is a call to binary code.
345c905a368SDaniele Buono  * Therefore, disable CFI checks in the interpreter function
346c905a368SDaniele Buono  */
tcg_qemu_tb_exec(CPUArchState * env,const void * v_tb_ptr)347db0c51a3SRichard Henderson uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
348db0c51a3SRichard Henderson                                             const void *v_tb_ptr)
349244f1441SYang Zhong {
35065089889SRichard Henderson     const uint32_t *tb_ptr = v_tb_ptr;
3515e75150cSEmilio G. Cota     tcg_target_ulong regs[TCG_TARGET_NB_REGS];
3527b7d8b2dSRichard Henderson     uint64_t stack[(TCG_STATIC_CALL_ARGS_SIZE + TCG_STATIC_FRAME_SIZE)
3537b7d8b2dSRichard Henderson                    / sizeof(uint64_t)];
354244f1441SYang Zhong 
3555e75150cSEmilio G. Cota     regs[TCG_AREG0] = (tcg_target_ulong)env;
3567b7d8b2dSRichard Henderson     regs[TCG_REG_CALL_STACK] = (uintptr_t)stack;
357244f1441SYang Zhong     tci_assert(tb_ptr);
358244f1441SYang Zhong 
359244f1441SYang Zhong     for (;;) {
36065089889SRichard Henderson         uint32_t insn;
36165089889SRichard Henderson         TCGOpcode opc;
36208096b1aSRichard Henderson         TCGReg r0, r1, r2, r3, r4, r5;
363244f1441SYang Zhong         tcg_target_ulong t1;
364244f1441SYang Zhong         TCGCond condition;
36579dd3a4fSRichard Henderson         uint8_t pos, len;
366244f1441SYang Zhong         uint32_t tmp32;
367dd7dc93eSRichard Henderson         uint64_t tmp64, taddr;
3685a0adf34SRichard Henderson         uint64_t T1, T2;
3699002ffcbSRichard Henderson         MemOpIdx oi;
370cdd9799bSRichard Henderson         int32_t ofs;
37165089889SRichard Henderson         void *ptr;
372244f1441SYang Zhong 
37365089889SRichard Henderson         insn = *tb_ptr++;
37465089889SRichard Henderson         opc = extract32(insn, 0, 8);
375244f1441SYang Zhong 
376244f1441SYang Zhong         switch (opc) {
377244f1441SYang Zhong         case INDEX_op_call:
378e9709e17SRichard Henderson             {
379e9709e17SRichard Henderson                 void *call_slots[MAX_CALL_IARGS];
380e9709e17SRichard Henderson                 ffi_cif *cif;
381e9709e17SRichard Henderson                 void *func;
382e9709e17SRichard Henderson                 unsigned i, s, n;
3837b7d8b2dSRichard Henderson 
38465089889SRichard Henderson                 tci_args_nl(insn, tb_ptr, &len, &ptr);
385e9709e17SRichard Henderson                 func = ((void **)ptr)[0];
386e9709e17SRichard Henderson                 cif = ((void **)ptr)[1];
387e9709e17SRichard Henderson 
388e9709e17SRichard Henderson                 n = cif->nargs;
389e9709e17SRichard Henderson                 for (i = s = 0; i < n; ++i) {
390e9709e17SRichard Henderson                     ffi_type *t = cif->arg_types[i];
391e9709e17SRichard Henderson                     call_slots[i] = &stack[s];
392e9709e17SRichard Henderson                     s += DIV_ROUND_UP(t->size, 8);
393e9709e17SRichard Henderson                 }
3947b7d8b2dSRichard Henderson 
3957b7d8b2dSRichard Henderson                 /* Helper functions may need to access the "return address" */
39613e71f08SRichard Henderson                 tci_tb_ptr = (uintptr_t)tb_ptr;
397e9709e17SRichard Henderson                 ffi_call(cif, func, stack, call_slots);
39865089889SRichard Henderson             }
3997b7d8b2dSRichard Henderson 
4007b7d8b2dSRichard Henderson             switch (len) {
4017b7d8b2dSRichard Henderson             case 0: /* void */
402244f1441SYang Zhong                 break;
4037b7d8b2dSRichard Henderson             case 1: /* uint32_t */
4047b7d8b2dSRichard Henderson                 /*
405896c76e6SRichard Henderson                  * The result winds up "left-aligned" in the stack[0] slot.
4067b7d8b2dSRichard Henderson                  * Note that libffi has an odd special case in that it will
4077b7d8b2dSRichard Henderson                  * always widen an integral result to ffi_arg.
4087b7d8b2dSRichard Henderson                  */
409896c76e6SRichard Henderson                 if (sizeof(ffi_arg) == 8) {
410896c76e6SRichard Henderson                     regs[TCG_REG_R0] = (uint32_t)stack[0];
4117b7d8b2dSRichard Henderson                 } else {
412896c76e6SRichard Henderson                     regs[TCG_REG_R0] = *(uint32_t *)stack;
4137b7d8b2dSRichard Henderson                 }
4147b7d8b2dSRichard Henderson                 break;
415896c76e6SRichard Henderson             case 2: /* uint64_t */
416896c76e6SRichard Henderson                 /*
417896c76e6SRichard Henderson                  * For TCG_TARGET_REG_BITS == 32, the register pair
418896c76e6SRichard Henderson                  * must stay in host memory order.
419896c76e6SRichard Henderson                  */
420896c76e6SRichard Henderson                 memcpy(&regs[TCG_REG_R0], stack, 8);
421896c76e6SRichard Henderson                 break;
422e9709e17SRichard Henderson             case 3: /* Int128 */
423e9709e17SRichard Henderson                 memcpy(&regs[TCG_REG_R0], stack, 16);
424e9709e17SRichard Henderson                 break;
4257b7d8b2dSRichard Henderson             default:
4267b7d8b2dSRichard Henderson                 g_assert_not_reached();
4277b7d8b2dSRichard Henderson             }
4287b7d8b2dSRichard Henderson             break;
4297b7d8b2dSRichard Henderson 
430244f1441SYang Zhong         case INDEX_op_br:
43165089889SRichard Henderson             tci_args_l(insn, tb_ptr, &ptr);
432f28ca03eSRichard Henderson             tb_ptr = ptr;
433244f1441SYang Zhong             continue;
434244f1441SYang Zhong         case INDEX_op_setcond_i32:
43565089889SRichard Henderson             tci_args_rrrc(insn, &r0, &r1, &r2, &condition);
436963e9fa2SRichard Henderson             regs[r0] = tci_compare32(regs[r1], regs[r2], condition);
437244f1441SYang Zhong             break;
438df093c19SRichard Henderson         case INDEX_op_movcond_i32:
439df093c19SRichard Henderson             tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &condition);
440df093c19SRichard Henderson             tmp32 = tci_compare32(regs[r1], regs[r2], condition);
441df093c19SRichard Henderson             regs[r0] = regs[tmp32 ? r3 : r4];
442df093c19SRichard Henderson             break;
443244f1441SYang Zhong #if TCG_TARGET_REG_BITS == 32
444244f1441SYang Zhong         case INDEX_op_setcond2_i32:
44565089889SRichard Henderson             tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &condition);
446817cadd6SRichard Henderson             T1 = tci_uint64(regs[r2], regs[r1]);
447817cadd6SRichard Henderson             T2 = tci_uint64(regs[r4], regs[r3]);
448817cadd6SRichard Henderson             regs[r0] = tci_compare64(T1, T2, condition);
449244f1441SYang Zhong             break;
450244f1441SYang Zhong #elif TCG_TARGET_REG_BITS == 64
451244f1441SYang Zhong         case INDEX_op_setcond_i64:
45265089889SRichard Henderson             tci_args_rrrc(insn, &r0, &r1, &r2, &condition);
453963e9fa2SRichard Henderson             regs[r0] = tci_compare64(regs[r1], regs[r2], condition);
454244f1441SYang Zhong             break;
455df093c19SRichard Henderson         case INDEX_op_movcond_i64:
456df093c19SRichard Henderson             tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &condition);
457df093c19SRichard Henderson             tmp32 = tci_compare64(regs[r1], regs[r2], condition);
458df093c19SRichard Henderson             regs[r0] = regs[tmp32 ? r3 : r4];
459df093c19SRichard Henderson             break;
460244f1441SYang Zhong #endif
4619e9acb7bSRichard Henderson         CASE_32_64(mov)
46265089889SRichard Henderson             tci_args_rr(insn, &r0, &r1);
463fc4a62f6SRichard Henderson             regs[r0] = regs[r1];
464244f1441SYang Zhong             break;
46565089889SRichard Henderson         case INDEX_op_tci_movi:
46665089889SRichard Henderson             tci_args_ri(insn, &r0, &t1);
467b95aa12eSRichard Henderson             regs[r0] = t1;
468244f1441SYang Zhong             break;
46965089889SRichard Henderson         case INDEX_op_tci_movl:
47065089889SRichard Henderson             tci_args_rl(insn, tb_ptr, &r0, &ptr);
47165089889SRichard Henderson             regs[r0] = *(tcg_target_ulong *)ptr;
47265089889SRichard Henderson             break;
473244f1441SYang Zhong 
474244f1441SYang Zhong             /* Load/store operations (32 bit). */
475244f1441SYang Zhong 
4767f33f5cdSRichard Henderson         CASE_32_64(ld8u)
47765089889SRichard Henderson             tci_args_rrs(insn, &r0, &r1, &ofs);
478cdd9799bSRichard Henderson             ptr = (void *)(regs[r1] + ofs);
479cdd9799bSRichard Henderson             regs[r0] = *(uint8_t *)ptr;
480244f1441SYang Zhong             break;
481850163ebSRichard Henderson         CASE_32_64(ld8s)
48265089889SRichard Henderson             tci_args_rrs(insn, &r0, &r1, &ofs);
483cdd9799bSRichard Henderson             ptr = (void *)(regs[r1] + ofs);
484cdd9799bSRichard Henderson             regs[r0] = *(int8_t *)ptr;
4852f160e0fSStefan Weil             break;
48677c38c7cSRichard Henderson         CASE_32_64(ld16u)
48765089889SRichard Henderson             tci_args_rrs(insn, &r0, &r1, &ofs);
488cdd9799bSRichard Henderson             ptr = (void *)(regs[r1] + ofs);
489cdd9799bSRichard Henderson             regs[r0] = *(uint16_t *)ptr;
490244f1441SYang Zhong             break;
491b09d78bfSRichard Henderson         CASE_32_64(ld16s)
49265089889SRichard Henderson             tci_args_rrs(insn, &r0, &r1, &ofs);
493cdd9799bSRichard Henderson             ptr = (void *)(regs[r1] + ofs);
494cdd9799bSRichard Henderson             regs[r0] = *(int16_t *)ptr;
495244f1441SYang Zhong             break;
496244f1441SYang Zhong         case INDEX_op_ld_i32:
497c1d77e94SRichard Henderson         CASE_64(ld32u)
49865089889SRichard Henderson             tci_args_rrs(insn, &r0, &r1, &ofs);
499cdd9799bSRichard Henderson             ptr = (void *)(regs[r1] + ofs);
500cdd9799bSRichard Henderson             regs[r0] = *(uint32_t *)ptr;
501244f1441SYang Zhong             break;
502ba9a80c1SRichard Henderson         CASE_32_64(st8)
50365089889SRichard Henderson             tci_args_rrs(insn, &r0, &r1, &ofs);
504cdd9799bSRichard Henderson             ptr = (void *)(regs[r1] + ofs);
505cdd9799bSRichard Henderson             *(uint8_t *)ptr = regs[r0];
506244f1441SYang Zhong             break;
50790be4ddeSRichard Henderson         CASE_32_64(st16)
50865089889SRichard Henderson             tci_args_rrs(insn, &r0, &r1, &ofs);
509cdd9799bSRichard Henderson             ptr = (void *)(regs[r1] + ofs);
510cdd9799bSRichard Henderson             *(uint16_t *)ptr = regs[r0];
511244f1441SYang Zhong             break;
512244f1441SYang Zhong         case INDEX_op_st_i32:
513b4d5bf0fSRichard Henderson         CASE_64(st32)
51465089889SRichard Henderson             tci_args_rrs(insn, &r0, &r1, &ofs);
515cdd9799bSRichard Henderson             ptr = (void *)(regs[r1] + ofs);
516cdd9799bSRichard Henderson             *(uint32_t *)ptr = regs[r0];
517244f1441SYang Zhong             break;
518244f1441SYang Zhong 
519dd2bb20eSRichard Henderson             /* Arithmetic operations (mixed 32/64 bit). */
520244f1441SYang Zhong 
521dd2bb20eSRichard Henderson         CASE_32_64(add)
52265089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
523e85e4b8fSRichard Henderson             regs[r0] = regs[r1] + regs[r2];
524244f1441SYang Zhong             break;
525dd2bb20eSRichard Henderson         CASE_32_64(sub)
52665089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
527e85e4b8fSRichard Henderson             regs[r0] = regs[r1] - regs[r2];
528244f1441SYang Zhong             break;
529dd2bb20eSRichard Henderson         CASE_32_64(mul)
53065089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
531e85e4b8fSRichard Henderson             regs[r0] = regs[r1] * regs[r2];
532244f1441SYang Zhong             break;
533dd2bb20eSRichard Henderson         CASE_32_64(and)
53465089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
535e85e4b8fSRichard Henderson             regs[r0] = regs[r1] & regs[r2];
536dd2bb20eSRichard Henderson             break;
537dd2bb20eSRichard Henderson         CASE_32_64(or)
53865089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
539e85e4b8fSRichard Henderson             regs[r0] = regs[r1] | regs[r2];
540dd2bb20eSRichard Henderson             break;
541dd2bb20eSRichard Henderson         CASE_32_64(xor)
54265089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
543e85e4b8fSRichard Henderson             regs[r0] = regs[r1] ^ regs[r2];
544dd2bb20eSRichard Henderson             break;
545a81520b9SRichard Henderson #if TCG_TARGET_HAS_andc_i32 || TCG_TARGET_HAS_andc_i64
546a81520b9SRichard Henderson         CASE_32_64(andc)
547a81520b9SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
548a81520b9SRichard Henderson             regs[r0] = regs[r1] & ~regs[r2];
549a81520b9SRichard Henderson             break;
550a81520b9SRichard Henderson #endif
551a81520b9SRichard Henderson #if TCG_TARGET_HAS_orc_i32 || TCG_TARGET_HAS_orc_i64
552a81520b9SRichard Henderson         CASE_32_64(orc)
553a81520b9SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
554a81520b9SRichard Henderson             regs[r0] = regs[r1] | ~regs[r2];
555a81520b9SRichard Henderson             break;
556a81520b9SRichard Henderson #endif
557a81520b9SRichard Henderson #if TCG_TARGET_HAS_eqv_i32 || TCG_TARGET_HAS_eqv_i64
558a81520b9SRichard Henderson         CASE_32_64(eqv)
559a81520b9SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
560a81520b9SRichard Henderson             regs[r0] = ~(regs[r1] ^ regs[r2]);
561a81520b9SRichard Henderson             break;
562a81520b9SRichard Henderson #endif
563a81520b9SRichard Henderson #if TCG_TARGET_HAS_nand_i32 || TCG_TARGET_HAS_nand_i64
564a81520b9SRichard Henderson         CASE_32_64(nand)
565a81520b9SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
566a81520b9SRichard Henderson             regs[r0] = ~(regs[r1] & regs[r2]);
567a81520b9SRichard Henderson             break;
568a81520b9SRichard Henderson #endif
569a81520b9SRichard Henderson #if TCG_TARGET_HAS_nor_i32 || TCG_TARGET_HAS_nor_i64
570a81520b9SRichard Henderson         CASE_32_64(nor)
571a81520b9SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
572a81520b9SRichard Henderson             regs[r0] = ~(regs[r1] | regs[r2]);
573a81520b9SRichard Henderson             break;
574a81520b9SRichard Henderson #endif
575dd2bb20eSRichard Henderson 
576dd2bb20eSRichard Henderson             /* Arithmetic operations (32 bit). */
577dd2bb20eSRichard Henderson 
578244f1441SYang Zhong         case INDEX_op_div_i32:
57965089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
580e85e4b8fSRichard Henderson             regs[r0] = (int32_t)regs[r1] / (int32_t)regs[r2];
581244f1441SYang Zhong             break;
582244f1441SYang Zhong         case INDEX_op_divu_i32:
58365089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
584e85e4b8fSRichard Henderson             regs[r0] = (uint32_t)regs[r1] / (uint32_t)regs[r2];
585244f1441SYang Zhong             break;
586244f1441SYang Zhong         case INDEX_op_rem_i32:
58765089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
588e85e4b8fSRichard Henderson             regs[r0] = (int32_t)regs[r1] % (int32_t)regs[r2];
589244f1441SYang Zhong             break;
590244f1441SYang Zhong         case INDEX_op_remu_i32:
59165089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
592e85e4b8fSRichard Henderson             regs[r0] = (uint32_t)regs[r1] % (uint32_t)regs[r2];
593244f1441SYang Zhong             break;
5945255f48cSRichard Henderson #if TCG_TARGET_HAS_clz_i32
5955255f48cSRichard Henderson         case INDEX_op_clz_i32:
5965255f48cSRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
5975255f48cSRichard Henderson             tmp32 = regs[r1];
5985255f48cSRichard Henderson             regs[r0] = tmp32 ? clz32(tmp32) : regs[r2];
5995255f48cSRichard Henderson             break;
6005255f48cSRichard Henderson #endif
6015255f48cSRichard Henderson #if TCG_TARGET_HAS_ctz_i32
6025255f48cSRichard Henderson         case INDEX_op_ctz_i32:
6035255f48cSRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
6045255f48cSRichard Henderson             tmp32 = regs[r1];
6055255f48cSRichard Henderson             regs[r0] = tmp32 ? ctz32(tmp32) : regs[r2];
6065255f48cSRichard Henderson             break;
6075255f48cSRichard Henderson #endif
6085255f48cSRichard Henderson #if TCG_TARGET_HAS_ctpop_i32
6095255f48cSRichard Henderson         case INDEX_op_ctpop_i32:
6105255f48cSRichard Henderson             tci_args_rr(insn, &r0, &r1);
6115255f48cSRichard Henderson             regs[r0] = ctpop32(regs[r1]);
6125255f48cSRichard Henderson             break;
6135255f48cSRichard Henderson #endif
614244f1441SYang Zhong 
615244f1441SYang Zhong             /* Shift/rotate operations (32 bit). */
616244f1441SYang Zhong 
617244f1441SYang Zhong         case INDEX_op_shl_i32:
61865089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
619e85e4b8fSRichard Henderson             regs[r0] = (uint32_t)regs[r1] << (regs[r2] & 31);
620244f1441SYang Zhong             break;
621244f1441SYang Zhong         case INDEX_op_shr_i32:
62265089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
623e85e4b8fSRichard Henderson             regs[r0] = (uint32_t)regs[r1] >> (regs[r2] & 31);
624244f1441SYang Zhong             break;
625244f1441SYang Zhong         case INDEX_op_sar_i32:
62665089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
627e85e4b8fSRichard Henderson             regs[r0] = (int32_t)regs[r1] >> (regs[r2] & 31);
628244f1441SYang Zhong             break;
629244f1441SYang Zhong #if TCG_TARGET_HAS_rot_i32
630244f1441SYang Zhong         case INDEX_op_rotl_i32:
63165089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
632e85e4b8fSRichard Henderson             regs[r0] = rol32(regs[r1], regs[r2] & 31);
633244f1441SYang Zhong             break;
634244f1441SYang Zhong         case INDEX_op_rotr_i32:
63565089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
636e85e4b8fSRichard Henderson             regs[r0] = ror32(regs[r1], regs[r2] & 31);
637244f1441SYang Zhong             break;
638244f1441SYang Zhong #endif
639244f1441SYang Zhong #if TCG_TARGET_HAS_deposit_i32
640244f1441SYang Zhong         case INDEX_op_deposit_i32:
64165089889SRichard Henderson             tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
64279dd3a4fSRichard Henderson             regs[r0] = deposit32(regs[r1], pos, len, regs[r2]);
643244f1441SYang Zhong             break;
644244f1441SYang Zhong #endif
6450f10d7c5SRichard Henderson #if TCG_TARGET_HAS_extract_i32
6460f10d7c5SRichard Henderson         case INDEX_op_extract_i32:
6470f10d7c5SRichard Henderson             tci_args_rrbb(insn, &r0, &r1, &pos, &len);
6480f10d7c5SRichard Henderson             regs[r0] = extract32(regs[r1], pos, len);
6490f10d7c5SRichard Henderson             break;
6500f10d7c5SRichard Henderson #endif
6510f10d7c5SRichard Henderson #if TCG_TARGET_HAS_sextract_i32
6520f10d7c5SRichard Henderson         case INDEX_op_sextract_i32:
6530f10d7c5SRichard Henderson             tci_args_rrbb(insn, &r0, &r1, &pos, &len);
6540f10d7c5SRichard Henderson             regs[r0] = sextract32(regs[r1], pos, len);
6550f10d7c5SRichard Henderson             break;
6560f10d7c5SRichard Henderson #endif
657244f1441SYang Zhong         case INDEX_op_brcond_i32:
65865089889SRichard Henderson             tci_args_rl(insn, tb_ptr, &r0, &ptr);
659fc8ec9e1SRichard Henderson             if ((uint32_t)regs[r0]) {
6605a0adf34SRichard Henderson                 tb_ptr = ptr;
661244f1441SYang Zhong             }
662244f1441SYang Zhong             break;
66308096b1aSRichard Henderson #if TCG_TARGET_REG_BITS == 32 || TCG_TARGET_HAS_add2_i32
664244f1441SYang Zhong         case INDEX_op_add2_i32:
66565089889SRichard Henderson             tci_args_rrrrrr(insn, &r0, &r1, &r2, &r3, &r4, &r5);
666120402b5SRichard Henderson             T1 = tci_uint64(regs[r3], regs[r2]);
667120402b5SRichard Henderson             T2 = tci_uint64(regs[r5], regs[r4]);
668120402b5SRichard Henderson             tci_write_reg64(regs, r1, r0, T1 + T2);
669244f1441SYang Zhong             break;
67008096b1aSRichard Henderson #endif
67108096b1aSRichard Henderson #if TCG_TARGET_REG_BITS == 32 || TCG_TARGET_HAS_sub2_i32
672244f1441SYang Zhong         case INDEX_op_sub2_i32:
67365089889SRichard Henderson             tci_args_rrrrrr(insn, &r0, &r1, &r2, &r3, &r4, &r5);
674120402b5SRichard Henderson             T1 = tci_uint64(regs[r3], regs[r2]);
675120402b5SRichard Henderson             T2 = tci_uint64(regs[r5], regs[r4]);
676120402b5SRichard Henderson             tci_write_reg64(regs, r1, r0, T1 - T2);
677244f1441SYang Zhong             break;
67808096b1aSRichard Henderson #endif
679f6db0d8dSRichard Henderson #if TCG_TARGET_HAS_mulu2_i32
680244f1441SYang Zhong         case INDEX_op_mulu2_i32:
68165089889SRichard Henderson             tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
682f6db0d8dSRichard Henderson             tmp64 = (uint64_t)(uint32_t)regs[r2] * (uint32_t)regs[r3];
683f6db0d8dSRichard Henderson             tci_write_reg64(regs, r1, r0, tmp64);
684244f1441SYang Zhong             break;
685f6db0d8dSRichard Henderson #endif
686f6db0d8dSRichard Henderson #if TCG_TARGET_HAS_muls2_i32
687f6db0d8dSRichard Henderson         case INDEX_op_muls2_i32:
688f6db0d8dSRichard Henderson             tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
689f6db0d8dSRichard Henderson             tmp64 = (int64_t)(int32_t)regs[r2] * (int32_t)regs[r3];
690f6db0d8dSRichard Henderson             tci_write_reg64(regs, r1, r0, tmp64);
691f6db0d8dSRichard Henderson             break;
692f6db0d8dSRichard Henderson #endif
69313a1d640SRichard Henderson #if TCG_TARGET_HAS_ext8s_i32 || TCG_TARGET_HAS_ext8s_i64
69413a1d640SRichard Henderson         CASE_32_64(ext8s)
69565089889SRichard Henderson             tci_args_rr(insn, &r0, &r1);
696fc4a62f6SRichard Henderson             regs[r0] = (int8_t)regs[r1];
697244f1441SYang Zhong             break;
698244f1441SYang Zhong #endif
6990d57d36aSRichard Henderson #if TCG_TARGET_HAS_ext16s_i32 || TCG_TARGET_HAS_ext16s_i64 || \
7000d57d36aSRichard Henderson     TCG_TARGET_HAS_bswap16_i32 || TCG_TARGET_HAS_bswap16_i64
70113a1d640SRichard Henderson         CASE_32_64(ext16s)
70265089889SRichard Henderson             tci_args_rr(insn, &r0, &r1);
703fc4a62f6SRichard Henderson             regs[r0] = (int16_t)regs[r1];
704244f1441SYang Zhong             break;
705244f1441SYang Zhong #endif
70613a1d640SRichard Henderson #if TCG_TARGET_HAS_ext8u_i32 || TCG_TARGET_HAS_ext8u_i64
70713a1d640SRichard Henderson         CASE_32_64(ext8u)
70865089889SRichard Henderson             tci_args_rr(insn, &r0, &r1);
709fc4a62f6SRichard Henderson             regs[r0] = (uint8_t)regs[r1];
710244f1441SYang Zhong             break;
711244f1441SYang Zhong #endif
71213a1d640SRichard Henderson #if TCG_TARGET_HAS_ext16u_i32 || TCG_TARGET_HAS_ext16u_i64
71313a1d640SRichard Henderson         CASE_32_64(ext16u)
71465089889SRichard Henderson             tci_args_rr(insn, &r0, &r1);
715fc4a62f6SRichard Henderson             regs[r0] = (uint16_t)regs[r1];
716244f1441SYang Zhong             break;
717244f1441SYang Zhong #endif
718fe2b13bbSRichard Henderson #if TCG_TARGET_HAS_bswap16_i32 || TCG_TARGET_HAS_bswap16_i64
719fe2b13bbSRichard Henderson         CASE_32_64(bswap16)
72065089889SRichard Henderson             tci_args_rr(insn, &r0, &r1);
721fc4a62f6SRichard Henderson             regs[r0] = bswap16(regs[r1]);
722244f1441SYang Zhong             break;
723244f1441SYang Zhong #endif
724fe2b13bbSRichard Henderson #if TCG_TARGET_HAS_bswap32_i32 || TCG_TARGET_HAS_bswap32_i64
725fe2b13bbSRichard Henderson         CASE_32_64(bswap32)
72665089889SRichard Henderson             tci_args_rr(insn, &r0, &r1);
727fc4a62f6SRichard Henderson             regs[r0] = bswap32(regs[r1]);
728244f1441SYang Zhong             break;
729244f1441SYang Zhong #endif
7309e9acb7bSRichard Henderson #if TCG_TARGET_HAS_not_i32 || TCG_TARGET_HAS_not_i64
7319e9acb7bSRichard Henderson         CASE_32_64(not)
73265089889SRichard Henderson             tci_args_rr(insn, &r0, &r1);
733fc4a62f6SRichard Henderson             regs[r0] = ~regs[r1];
734244f1441SYang Zhong             break;
735244f1441SYang Zhong #endif
7369e9acb7bSRichard Henderson         CASE_32_64(neg)
73765089889SRichard Henderson             tci_args_rr(insn, &r0, &r1);
738fc4a62f6SRichard Henderson             regs[r0] = -regs[r1];
739244f1441SYang Zhong             break;
740244f1441SYang Zhong #if TCG_TARGET_REG_BITS == 64
741244f1441SYang Zhong             /* Load/store operations (64 bit). */
742244f1441SYang Zhong 
743244f1441SYang Zhong         case INDEX_op_ld32s_i64:
74465089889SRichard Henderson             tci_args_rrs(insn, &r0, &r1, &ofs);
745cdd9799bSRichard Henderson             ptr = (void *)(regs[r1] + ofs);
746cdd9799bSRichard Henderson             regs[r0] = *(int32_t *)ptr;
747244f1441SYang Zhong             break;
748244f1441SYang Zhong         case INDEX_op_ld_i64:
74965089889SRichard Henderson             tci_args_rrs(insn, &r0, &r1, &ofs);
750cdd9799bSRichard Henderson             ptr = (void *)(regs[r1] + ofs);
751cdd9799bSRichard Henderson             regs[r0] = *(uint64_t *)ptr;
752244f1441SYang Zhong             break;
753244f1441SYang Zhong         case INDEX_op_st_i64:
75465089889SRichard Henderson             tci_args_rrs(insn, &r0, &r1, &ofs);
755cdd9799bSRichard Henderson             ptr = (void *)(regs[r1] + ofs);
756cdd9799bSRichard Henderson             *(uint64_t *)ptr = regs[r0];
757244f1441SYang Zhong             break;
758244f1441SYang Zhong 
759244f1441SYang Zhong             /* Arithmetic operations (64 bit). */
760244f1441SYang Zhong 
761244f1441SYang Zhong         case INDEX_op_div_i64:
76265089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
763e85e4b8fSRichard Henderson             regs[r0] = (int64_t)regs[r1] / (int64_t)regs[r2];
764244f1441SYang Zhong             break;
765ae40c098SRichard Henderson         case INDEX_op_divu_i64:
76665089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
767e85e4b8fSRichard Henderson             regs[r0] = (uint64_t)regs[r1] / (uint64_t)regs[r2];
768ae40c098SRichard Henderson             break;
769ae40c098SRichard Henderson         case INDEX_op_rem_i64:
77065089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
771e85e4b8fSRichard Henderson             regs[r0] = (int64_t)regs[r1] % (int64_t)regs[r2];
772ae40c098SRichard Henderson             break;
773ae40c098SRichard Henderson         case INDEX_op_remu_i64:
77465089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
775e85e4b8fSRichard Henderson             regs[r0] = (uint64_t)regs[r1] % (uint64_t)regs[r2];
776ae40c098SRichard Henderson             break;
7775255f48cSRichard Henderson #if TCG_TARGET_HAS_clz_i64
7785255f48cSRichard Henderson         case INDEX_op_clz_i64:
7795255f48cSRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
7805255f48cSRichard Henderson             regs[r0] = regs[r1] ? clz64(regs[r1]) : regs[r2];
7815255f48cSRichard Henderson             break;
7825255f48cSRichard Henderson #endif
7835255f48cSRichard Henderson #if TCG_TARGET_HAS_ctz_i64
7845255f48cSRichard Henderson         case INDEX_op_ctz_i64:
7855255f48cSRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
7865255f48cSRichard Henderson             regs[r0] = regs[r1] ? ctz64(regs[r1]) : regs[r2];
7875255f48cSRichard Henderson             break;
7885255f48cSRichard Henderson #endif
7895255f48cSRichard Henderson #if TCG_TARGET_HAS_ctpop_i64
7905255f48cSRichard Henderson         case INDEX_op_ctpop_i64:
7915255f48cSRichard Henderson             tci_args_rr(insn, &r0, &r1);
7925255f48cSRichard Henderson             regs[r0] = ctpop64(regs[r1]);
7935255f48cSRichard Henderson             break;
7945255f48cSRichard Henderson #endif
795f6db0d8dSRichard Henderson #if TCG_TARGET_HAS_mulu2_i64
796f6db0d8dSRichard Henderson         case INDEX_op_mulu2_i64:
797f6db0d8dSRichard Henderson             tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
798f6db0d8dSRichard Henderson             mulu64(&regs[r0], &regs[r1], regs[r2], regs[r3]);
799f6db0d8dSRichard Henderson             break;
800f6db0d8dSRichard Henderson #endif
801f6db0d8dSRichard Henderson #if TCG_TARGET_HAS_muls2_i64
802f6db0d8dSRichard Henderson         case INDEX_op_muls2_i64:
803f6db0d8dSRichard Henderson             tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
804f6db0d8dSRichard Henderson             muls64(&regs[r0], &regs[r1], regs[r2], regs[r3]);
805f6db0d8dSRichard Henderson             break;
806f6db0d8dSRichard Henderson #endif
80708096b1aSRichard Henderson #if TCG_TARGET_HAS_add2_i64
80808096b1aSRichard Henderson         case INDEX_op_add2_i64:
80908096b1aSRichard Henderson             tci_args_rrrrrr(insn, &r0, &r1, &r2, &r3, &r4, &r5);
81008096b1aSRichard Henderson             T1 = regs[r2] + regs[r4];
81108096b1aSRichard Henderson             T2 = regs[r3] + regs[r5] + (T1 < regs[r2]);
81208096b1aSRichard Henderson             regs[r0] = T1;
81308096b1aSRichard Henderson             regs[r1] = T2;
81408096b1aSRichard Henderson             break;
81508096b1aSRichard Henderson #endif
81608096b1aSRichard Henderson #if TCG_TARGET_HAS_add2_i64
81708096b1aSRichard Henderson         case INDEX_op_sub2_i64:
81808096b1aSRichard Henderson             tci_args_rrrrrr(insn, &r0, &r1, &r2, &r3, &r4, &r5);
81908096b1aSRichard Henderson             T1 = regs[r2] - regs[r4];
82008096b1aSRichard Henderson             T2 = regs[r3] - regs[r5] - (regs[r2] < regs[r4]);
82108096b1aSRichard Henderson             regs[r0] = T1;
82208096b1aSRichard Henderson             regs[r1] = T2;
82308096b1aSRichard Henderson             break;
82408096b1aSRichard Henderson #endif
825244f1441SYang Zhong 
826244f1441SYang Zhong             /* Shift/rotate operations (64 bit). */
827244f1441SYang Zhong 
828244f1441SYang Zhong         case INDEX_op_shl_i64:
82965089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
830e85e4b8fSRichard Henderson             regs[r0] = regs[r1] << (regs[r2] & 63);
831244f1441SYang Zhong             break;
832244f1441SYang Zhong         case INDEX_op_shr_i64:
83365089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
834e85e4b8fSRichard Henderson             regs[r0] = regs[r1] >> (regs[r2] & 63);
835244f1441SYang Zhong             break;
836244f1441SYang Zhong         case INDEX_op_sar_i64:
83765089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
838e85e4b8fSRichard Henderson             regs[r0] = (int64_t)regs[r1] >> (regs[r2] & 63);
839244f1441SYang Zhong             break;
840244f1441SYang Zhong #if TCG_TARGET_HAS_rot_i64
841244f1441SYang Zhong         case INDEX_op_rotl_i64:
84265089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
843e85e4b8fSRichard Henderson             regs[r0] = rol64(regs[r1], regs[r2] & 63);
844244f1441SYang Zhong             break;
845244f1441SYang Zhong         case INDEX_op_rotr_i64:
84665089889SRichard Henderson             tci_args_rrr(insn, &r0, &r1, &r2);
847e85e4b8fSRichard Henderson             regs[r0] = ror64(regs[r1], regs[r2] & 63);
848244f1441SYang Zhong             break;
849244f1441SYang Zhong #endif
850244f1441SYang Zhong #if TCG_TARGET_HAS_deposit_i64
851244f1441SYang Zhong         case INDEX_op_deposit_i64:
85265089889SRichard Henderson             tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
85379dd3a4fSRichard Henderson             regs[r0] = deposit64(regs[r1], pos, len, regs[r2]);
854244f1441SYang Zhong             break;
855244f1441SYang Zhong #endif
8560f10d7c5SRichard Henderson #if TCG_TARGET_HAS_extract_i64
8570f10d7c5SRichard Henderson         case INDEX_op_extract_i64:
8580f10d7c5SRichard Henderson             tci_args_rrbb(insn, &r0, &r1, &pos, &len);
8590f10d7c5SRichard Henderson             regs[r0] = extract64(regs[r1], pos, len);
8600f10d7c5SRichard Henderson             break;
8610f10d7c5SRichard Henderson #endif
8620f10d7c5SRichard Henderson #if TCG_TARGET_HAS_sextract_i64
8630f10d7c5SRichard Henderson         case INDEX_op_sextract_i64:
8640f10d7c5SRichard Henderson             tci_args_rrbb(insn, &r0, &r1, &pos, &len);
8650f10d7c5SRichard Henderson             regs[r0] = sextract64(regs[r1], pos, len);
8660f10d7c5SRichard Henderson             break;
8670f10d7c5SRichard Henderson #endif
868244f1441SYang Zhong         case INDEX_op_brcond_i64:
86965089889SRichard Henderson             tci_args_rl(insn, tb_ptr, &r0, &ptr);
870fc8ec9e1SRichard Henderson             if (regs[r0]) {
8715a0adf34SRichard Henderson                 tb_ptr = ptr;
872244f1441SYang Zhong             }
873244f1441SYang Zhong             break;
874244f1441SYang Zhong         case INDEX_op_ext32s_i64:
875244f1441SYang Zhong         case INDEX_op_ext_i32_i64:
87665089889SRichard Henderson             tci_args_rr(insn, &r0, &r1);
877fc4a62f6SRichard Henderson             regs[r0] = (int32_t)regs[r1];
878244f1441SYang Zhong             break;
879244f1441SYang Zhong         case INDEX_op_ext32u_i64:
880244f1441SYang Zhong         case INDEX_op_extu_i32_i64:
88165089889SRichard Henderson             tci_args_rr(insn, &r0, &r1);
882fc4a62f6SRichard Henderson             regs[r0] = (uint32_t)regs[r1];
883244f1441SYang Zhong             break;
884244f1441SYang Zhong #if TCG_TARGET_HAS_bswap64_i64
885244f1441SYang Zhong         case INDEX_op_bswap64_i64:
88665089889SRichard Henderson             tci_args_rr(insn, &r0, &r1);
887fc4a62f6SRichard Henderson             regs[r0] = bswap64(regs[r1]);
888244f1441SYang Zhong             break;
889244f1441SYang Zhong #endif
890244f1441SYang Zhong #endif /* TCG_TARGET_REG_BITS == 64 */
891244f1441SYang Zhong 
892244f1441SYang Zhong             /* QEMU specific operations. */
893244f1441SYang Zhong 
894244f1441SYang Zhong         case INDEX_op_exit_tb:
89565089889SRichard Henderson             tci_args_l(insn, tb_ptr, &ptr);
896158d3873SRichard Henderson             return (uintptr_t)ptr;
897158d3873SRichard Henderson 
898244f1441SYang Zhong         case INDEX_op_goto_tb:
89965089889SRichard Henderson             tci_args_l(insn, tb_ptr, &ptr);
9001670a2b9SRichard Henderson             tb_ptr = *(void **)ptr;
90192bc4fadSRichard Henderson             break;
9021670a2b9SRichard Henderson 
9036eea0434SRichard Henderson         case INDEX_op_goto_ptr:
9046eea0434SRichard Henderson             tci_args_r(insn, &r0);
9056eea0434SRichard Henderson             ptr = (void *)regs[r0];
9066eea0434SRichard Henderson             if (!ptr) {
9076eea0434SRichard Henderson                 return 0;
9086eea0434SRichard Henderson             }
9096eea0434SRichard Henderson             tb_ptr = ptr;
9106eea0434SRichard Henderson             break;
9116eea0434SRichard Henderson 
912fecccfccSRichard Henderson         case INDEX_op_qemu_ld_a32_i32:
913dd7dc93eSRichard Henderson             tci_args_rrm(insn, &r0, &r1, &oi);
914dd7dc93eSRichard Henderson             taddr = (uint32_t)regs[r1];
915dd7dc93eSRichard Henderson             goto do_ld_i32;
916fecccfccSRichard Henderson         case INDEX_op_qemu_ld_a64_i32:
917dd7dc93eSRichard Henderson             if (TCG_TARGET_REG_BITS == 64) {
91865089889SRichard Henderson                 tci_args_rrm(insn, &r0, &r1, &oi);
91963041ed2SRichard Henderson                 taddr = regs[r1];
92063041ed2SRichard Henderson             } else {
921*ab64da79SRichard Henderson                 tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
92263041ed2SRichard Henderson                 taddr = tci_uint64(regs[r2], regs[r1]);
923*ab64da79SRichard Henderson                 oi = regs[r3];
92463041ed2SRichard Henderson             }
925dd7dc93eSRichard Henderson         do_ld_i32:
926dd7dc93eSRichard Henderson             regs[r0] = tci_qemu_ld(env, taddr, oi, tb_ptr);
927244f1441SYang Zhong             break;
92863041ed2SRichard Henderson 
929fecccfccSRichard Henderson         case INDEX_op_qemu_ld_a32_i64:
930dd7dc93eSRichard Henderson             if (TCG_TARGET_REG_BITS == 64) {
931dd7dc93eSRichard Henderson                 tci_args_rrm(insn, &r0, &r1, &oi);
932dd7dc93eSRichard Henderson                 taddr = (uint32_t)regs[r1];
933dd7dc93eSRichard Henderson             } else {
934*ab64da79SRichard Henderson                 tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
935dd7dc93eSRichard Henderson                 taddr = (uint32_t)regs[r2];
936*ab64da79SRichard Henderson                 oi = regs[r3];
937dd7dc93eSRichard Henderson             }
938dd7dc93eSRichard Henderson             goto do_ld_i64;
939fecccfccSRichard Henderson         case INDEX_op_qemu_ld_a64_i64:
94063041ed2SRichard Henderson             if (TCG_TARGET_REG_BITS == 64) {
94165089889SRichard Henderson                 tci_args_rrm(insn, &r0, &r1, &oi);
94263041ed2SRichard Henderson                 taddr = regs[r1];
94363041ed2SRichard Henderson             } else {
94465089889SRichard Henderson                 tci_args_rrrrr(insn, &r0, &r1, &r2, &r3, &r4);
94563041ed2SRichard Henderson                 taddr = tci_uint64(regs[r3], regs[r2]);
94665089889SRichard Henderson                 oi = regs[r4];
947244f1441SYang Zhong             }
948dd7dc93eSRichard Henderson         do_ld_i64:
94969acc02aSRichard Henderson             tmp64 = tci_qemu_ld(env, taddr, oi, tb_ptr);
950244f1441SYang Zhong             if (TCG_TARGET_REG_BITS == 32) {
95163041ed2SRichard Henderson                 tci_write_reg64(regs, r1, r0, tmp64);
95263041ed2SRichard Henderson             } else {
95363041ed2SRichard Henderson                 regs[r0] = tmp64;
954244f1441SYang Zhong             }
955244f1441SYang Zhong             break;
95663041ed2SRichard Henderson 
957fecccfccSRichard Henderson         case INDEX_op_qemu_st_a32_i32:
958dd7dc93eSRichard Henderson             tci_args_rrm(insn, &r0, &r1, &oi);
959dd7dc93eSRichard Henderson             taddr = (uint32_t)regs[r1];
960dd7dc93eSRichard Henderson             goto do_st_i32;
961fecccfccSRichard Henderson         case INDEX_op_qemu_st_a64_i32:
962dd7dc93eSRichard Henderson             if (TCG_TARGET_REG_BITS == 64) {
96365089889SRichard Henderson                 tci_args_rrm(insn, &r0, &r1, &oi);
96463041ed2SRichard Henderson                 taddr = regs[r1];
96563041ed2SRichard Henderson             } else {
966*ab64da79SRichard Henderson                 tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
96763041ed2SRichard Henderson                 taddr = tci_uint64(regs[r2], regs[r1]);
968*ab64da79SRichard Henderson                 oi = regs[r3];
96963041ed2SRichard Henderson             }
970dd7dc93eSRichard Henderson         do_st_i32:
971dd7dc93eSRichard Henderson             tci_qemu_st(env, taddr, regs[r0], oi, tb_ptr);
972244f1441SYang Zhong             break;
97363041ed2SRichard Henderson 
974fecccfccSRichard Henderson         case INDEX_op_qemu_st_a32_i64:
975dd7dc93eSRichard Henderson             if (TCG_TARGET_REG_BITS == 64) {
976dd7dc93eSRichard Henderson                 tci_args_rrm(insn, &r0, &r1, &oi);
977dd7dc93eSRichard Henderson                 tmp64 = regs[r0];
978dd7dc93eSRichard Henderson                 taddr = (uint32_t)regs[r1];
979dd7dc93eSRichard Henderson             } else {
980*ab64da79SRichard Henderson                 tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
981dd7dc93eSRichard Henderson                 tmp64 = tci_uint64(regs[r1], regs[r0]);
982dd7dc93eSRichard Henderson                 taddr = (uint32_t)regs[r2];
983*ab64da79SRichard Henderson                 oi = regs[r3];
984dd7dc93eSRichard Henderson             }
985dd7dc93eSRichard Henderson             goto do_st_i64;
986fecccfccSRichard Henderson         case INDEX_op_qemu_st_a64_i64:
98763041ed2SRichard Henderson             if (TCG_TARGET_REG_BITS == 64) {
98865089889SRichard Henderson                 tci_args_rrm(insn, &r0, &r1, &oi);
98963041ed2SRichard Henderson                 tmp64 = regs[r0];
990dd7dc93eSRichard Henderson                 taddr = regs[r1];
99163041ed2SRichard Henderson             } else {
99265089889SRichard Henderson                 tci_args_rrrrr(insn, &r0, &r1, &r2, &r3, &r4);
993dd7dc93eSRichard Henderson                 tmp64 = tci_uint64(regs[r1], regs[r0]);
99463041ed2SRichard Henderson                 taddr = tci_uint64(regs[r3], regs[r2]);
99565089889SRichard Henderson                 oi = regs[r4];
99663041ed2SRichard Henderson             }
997dd7dc93eSRichard Henderson         do_st_i64:
99869acc02aSRichard Henderson             tci_qemu_st(env, taddr, tmp64, oi, tb_ptr);
999244f1441SYang Zhong             break;
100063041ed2SRichard Henderson 
1001244f1441SYang Zhong         case INDEX_op_mb:
1002244f1441SYang Zhong             /* Ensure ordering for all kinds */
1003244f1441SYang Zhong             smp_mb();
1004244f1441SYang Zhong             break;
1005244f1441SYang Zhong         default:
1006f6996f99SRichard Henderson             g_assert_not_reached();
1007244f1441SYang Zhong         }
1008244f1441SYang Zhong     }
1009244f1441SYang Zhong }
101059964b4fSRichard Henderson 
101159964b4fSRichard Henderson /*
101259964b4fSRichard Henderson  * Disassembler that matches the interpreter
101359964b4fSRichard Henderson  */
101459964b4fSRichard Henderson 
str_r(TCGReg r)101559964b4fSRichard Henderson static const char *str_r(TCGReg r)
101659964b4fSRichard Henderson {
101759964b4fSRichard Henderson     static const char regs[TCG_TARGET_NB_REGS][4] = {
101859964b4fSRichard Henderson         "r0", "r1", "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
101959964b4fSRichard Henderson         "r8", "r9", "r10", "r11", "r12", "r13", "env", "sp"
102059964b4fSRichard Henderson     };
102159964b4fSRichard Henderson 
102259964b4fSRichard Henderson     QEMU_BUILD_BUG_ON(TCG_AREG0 != TCG_REG_R14);
102359964b4fSRichard Henderson     QEMU_BUILD_BUG_ON(TCG_REG_CALL_STACK != TCG_REG_R15);
102459964b4fSRichard Henderson 
102559964b4fSRichard Henderson     assert((unsigned)r < TCG_TARGET_NB_REGS);
102659964b4fSRichard Henderson     return regs[r];
102759964b4fSRichard Henderson }
102859964b4fSRichard Henderson 
str_c(TCGCond c)102959964b4fSRichard Henderson static const char *str_c(TCGCond c)
103059964b4fSRichard Henderson {
103159964b4fSRichard Henderson     static const char cond[16][8] = {
103259964b4fSRichard Henderson         [TCG_COND_NEVER] = "never",
103359964b4fSRichard Henderson         [TCG_COND_ALWAYS] = "always",
103459964b4fSRichard Henderson         [TCG_COND_EQ] = "eq",
103559964b4fSRichard Henderson         [TCG_COND_NE] = "ne",
103659964b4fSRichard Henderson         [TCG_COND_LT] = "lt",
103759964b4fSRichard Henderson         [TCG_COND_GE] = "ge",
103859964b4fSRichard Henderson         [TCG_COND_LE] = "le",
103959964b4fSRichard Henderson         [TCG_COND_GT] = "gt",
104059964b4fSRichard Henderson         [TCG_COND_LTU] = "ltu",
104159964b4fSRichard Henderson         [TCG_COND_GEU] = "geu",
104259964b4fSRichard Henderson         [TCG_COND_LEU] = "leu",
104359964b4fSRichard Henderson         [TCG_COND_GTU] = "gtu",
104459964b4fSRichard Henderson     };
104559964b4fSRichard Henderson 
104659964b4fSRichard Henderson     assert((unsigned)c < ARRAY_SIZE(cond));
104759964b4fSRichard Henderson     assert(cond[c][0] != 0);
104859964b4fSRichard Henderson     return cond[c];
104959964b4fSRichard Henderson }
105059964b4fSRichard Henderson 
105159964b4fSRichard Henderson /* Disassemble TCI bytecode. */
print_insn_tci(bfd_vma addr,disassemble_info * info)105259964b4fSRichard Henderson int print_insn_tci(bfd_vma addr, disassemble_info *info)
105359964b4fSRichard Henderson {
105465089889SRichard Henderson     const uint32_t *tb_ptr = (const void *)(uintptr_t)addr;
105559964b4fSRichard Henderson     const TCGOpDef *def;
105659964b4fSRichard Henderson     const char *op_name;
105765089889SRichard Henderson     uint32_t insn;
105859964b4fSRichard Henderson     TCGOpcode op;
105908096b1aSRichard Henderson     TCGReg r0, r1, r2, r3, r4, r5;
106059964b4fSRichard Henderson     tcg_target_ulong i1;
106159964b4fSRichard Henderson     int32_t s2;
106259964b4fSRichard Henderson     TCGCond c;
10639002ffcbSRichard Henderson     MemOpIdx oi;
106459964b4fSRichard Henderson     uint8_t pos, len;
106565089889SRichard Henderson     void *ptr;
106659964b4fSRichard Henderson 
106765089889SRichard Henderson     /* TCI is always the host, so we don't need to load indirect. */
106865089889SRichard Henderson     insn = *tb_ptr++;
106959964b4fSRichard Henderson 
107065089889SRichard Henderson     info->fprintf_func(info->stream, "%08x  ", insn);
107159964b4fSRichard Henderson 
107265089889SRichard Henderson     op = extract32(insn, 0, 8);
107359964b4fSRichard Henderson     def = &tcg_op_defs[op];
107459964b4fSRichard Henderson     op_name = def->name;
107559964b4fSRichard Henderson 
107659964b4fSRichard Henderson     switch (op) {
107759964b4fSRichard Henderson     case INDEX_op_br:
107859964b4fSRichard Henderson     case INDEX_op_exit_tb:
107959964b4fSRichard Henderson     case INDEX_op_goto_tb:
108065089889SRichard Henderson         tci_args_l(insn, tb_ptr, &ptr);
108159964b4fSRichard Henderson         info->fprintf_func(info->stream, "%-12s  %p", op_name, ptr);
108259964b4fSRichard Henderson         break;
108359964b4fSRichard Henderson 
10846eea0434SRichard Henderson     case INDEX_op_goto_ptr:
10856eea0434SRichard Henderson         tci_args_r(insn, &r0);
10866eea0434SRichard Henderson         info->fprintf_func(info->stream, "%-12s  %s", op_name, str_r(r0));
10876eea0434SRichard Henderson         break;
10886eea0434SRichard Henderson 
10897b7d8b2dSRichard Henderson     case INDEX_op_call:
109065089889SRichard Henderson         tci_args_nl(insn, tb_ptr, &len, &ptr);
109165089889SRichard Henderson         info->fprintf_func(info->stream, "%-12s  %d, %p", op_name, len, ptr);
10927b7d8b2dSRichard Henderson         break;
10937b7d8b2dSRichard Henderson 
109459964b4fSRichard Henderson     case INDEX_op_brcond_i32:
109559964b4fSRichard Henderson     case INDEX_op_brcond_i64:
109665089889SRichard Henderson         tci_args_rl(insn, tb_ptr, &r0, &ptr);
1097fc8ec9e1SRichard Henderson         info->fprintf_func(info->stream, "%-12s  %s, 0, ne, %p",
1098fc8ec9e1SRichard Henderson                            op_name, str_r(r0), ptr);
109959964b4fSRichard Henderson         break;
110059964b4fSRichard Henderson 
110159964b4fSRichard Henderson     case INDEX_op_setcond_i32:
110259964b4fSRichard Henderson     case INDEX_op_setcond_i64:
110365089889SRichard Henderson         tci_args_rrrc(insn, &r0, &r1, &r2, &c);
110459964b4fSRichard Henderson         info->fprintf_func(info->stream, "%-12s  %s, %s, %s, %s",
110559964b4fSRichard Henderson                            op_name, str_r(r0), str_r(r1), str_r(r2), str_c(c));
110659964b4fSRichard Henderson         break;
110759964b4fSRichard Henderson 
110865089889SRichard Henderson     case INDEX_op_tci_movi:
110965089889SRichard Henderson         tci_args_ri(insn, &r0, &i1);
111059964b4fSRichard Henderson         info->fprintf_func(info->stream, "%-12s  %s, 0x%" TCG_PRIlx,
111159964b4fSRichard Henderson                            op_name, str_r(r0), i1);
111259964b4fSRichard Henderson         break;
111359964b4fSRichard Henderson 
111465089889SRichard Henderson     case INDEX_op_tci_movl:
111565089889SRichard Henderson         tci_args_rl(insn, tb_ptr, &r0, &ptr);
111665089889SRichard Henderson         info->fprintf_func(info->stream, "%-12s  %s, %p",
111765089889SRichard Henderson                            op_name, str_r(r0), ptr);
111859964b4fSRichard Henderson         break;
111959964b4fSRichard Henderson 
112059964b4fSRichard Henderson     case INDEX_op_ld8u_i32:
112159964b4fSRichard Henderson     case INDEX_op_ld8u_i64:
112259964b4fSRichard Henderson     case INDEX_op_ld8s_i32:
112359964b4fSRichard Henderson     case INDEX_op_ld8s_i64:
112459964b4fSRichard Henderson     case INDEX_op_ld16u_i32:
112559964b4fSRichard Henderson     case INDEX_op_ld16u_i64:
112659964b4fSRichard Henderson     case INDEX_op_ld16s_i32:
112759964b4fSRichard Henderson     case INDEX_op_ld16s_i64:
112859964b4fSRichard Henderson     case INDEX_op_ld32u_i64:
112959964b4fSRichard Henderson     case INDEX_op_ld32s_i64:
113059964b4fSRichard Henderson     case INDEX_op_ld_i32:
113159964b4fSRichard Henderson     case INDEX_op_ld_i64:
113259964b4fSRichard Henderson     case INDEX_op_st8_i32:
113359964b4fSRichard Henderson     case INDEX_op_st8_i64:
113459964b4fSRichard Henderson     case INDEX_op_st16_i32:
113559964b4fSRichard Henderson     case INDEX_op_st16_i64:
113659964b4fSRichard Henderson     case INDEX_op_st32_i64:
113759964b4fSRichard Henderson     case INDEX_op_st_i32:
113859964b4fSRichard Henderson     case INDEX_op_st_i64:
113965089889SRichard Henderson         tci_args_rrs(insn, &r0, &r1, &s2);
114059964b4fSRichard Henderson         info->fprintf_func(info->stream, "%-12s  %s, %s, %d",
114159964b4fSRichard Henderson                            op_name, str_r(r0), str_r(r1), s2);
114259964b4fSRichard Henderson         break;
114359964b4fSRichard Henderson 
114459964b4fSRichard Henderson     case INDEX_op_mov_i32:
114559964b4fSRichard Henderson     case INDEX_op_mov_i64:
114659964b4fSRichard Henderson     case INDEX_op_ext8s_i32:
114759964b4fSRichard Henderson     case INDEX_op_ext8s_i64:
114859964b4fSRichard Henderson     case INDEX_op_ext8u_i32:
114959964b4fSRichard Henderson     case INDEX_op_ext8u_i64:
115059964b4fSRichard Henderson     case INDEX_op_ext16s_i32:
115159964b4fSRichard Henderson     case INDEX_op_ext16s_i64:
115259964b4fSRichard Henderson     case INDEX_op_ext16u_i32:
115359964b4fSRichard Henderson     case INDEX_op_ext32s_i64:
115459964b4fSRichard Henderson     case INDEX_op_ext32u_i64:
115559964b4fSRichard Henderson     case INDEX_op_ext_i32_i64:
115659964b4fSRichard Henderson     case INDEX_op_extu_i32_i64:
115759964b4fSRichard Henderson     case INDEX_op_bswap16_i32:
115859964b4fSRichard Henderson     case INDEX_op_bswap16_i64:
115959964b4fSRichard Henderson     case INDEX_op_bswap32_i32:
116059964b4fSRichard Henderson     case INDEX_op_bswap32_i64:
116159964b4fSRichard Henderson     case INDEX_op_bswap64_i64:
116259964b4fSRichard Henderson     case INDEX_op_not_i32:
116359964b4fSRichard Henderson     case INDEX_op_not_i64:
116459964b4fSRichard Henderson     case INDEX_op_neg_i32:
116559964b4fSRichard Henderson     case INDEX_op_neg_i64:
11665255f48cSRichard Henderson     case INDEX_op_ctpop_i32:
11675255f48cSRichard Henderson     case INDEX_op_ctpop_i64:
116865089889SRichard Henderson         tci_args_rr(insn, &r0, &r1);
116959964b4fSRichard Henderson         info->fprintf_func(info->stream, "%-12s  %s, %s",
117059964b4fSRichard Henderson                            op_name, str_r(r0), str_r(r1));
117159964b4fSRichard Henderson         break;
117259964b4fSRichard Henderson 
117359964b4fSRichard Henderson     case INDEX_op_add_i32:
117459964b4fSRichard Henderson     case INDEX_op_add_i64:
117559964b4fSRichard Henderson     case INDEX_op_sub_i32:
117659964b4fSRichard Henderson     case INDEX_op_sub_i64:
117759964b4fSRichard Henderson     case INDEX_op_mul_i32:
117859964b4fSRichard Henderson     case INDEX_op_mul_i64:
117959964b4fSRichard Henderson     case INDEX_op_and_i32:
118059964b4fSRichard Henderson     case INDEX_op_and_i64:
118159964b4fSRichard Henderson     case INDEX_op_or_i32:
118259964b4fSRichard Henderson     case INDEX_op_or_i64:
118359964b4fSRichard Henderson     case INDEX_op_xor_i32:
118459964b4fSRichard Henderson     case INDEX_op_xor_i64:
1185a81520b9SRichard Henderson     case INDEX_op_andc_i32:
1186a81520b9SRichard Henderson     case INDEX_op_andc_i64:
1187a81520b9SRichard Henderson     case INDEX_op_orc_i32:
1188a81520b9SRichard Henderson     case INDEX_op_orc_i64:
1189a81520b9SRichard Henderson     case INDEX_op_eqv_i32:
1190a81520b9SRichard Henderson     case INDEX_op_eqv_i64:
1191a81520b9SRichard Henderson     case INDEX_op_nand_i32:
1192a81520b9SRichard Henderson     case INDEX_op_nand_i64:
1193a81520b9SRichard Henderson     case INDEX_op_nor_i32:
1194a81520b9SRichard Henderson     case INDEX_op_nor_i64:
119559964b4fSRichard Henderson     case INDEX_op_div_i32:
119659964b4fSRichard Henderson     case INDEX_op_div_i64:
119759964b4fSRichard Henderson     case INDEX_op_rem_i32:
119859964b4fSRichard Henderson     case INDEX_op_rem_i64:
119959964b4fSRichard Henderson     case INDEX_op_divu_i32:
120059964b4fSRichard Henderson     case INDEX_op_divu_i64:
120159964b4fSRichard Henderson     case INDEX_op_remu_i32:
120259964b4fSRichard Henderson     case INDEX_op_remu_i64:
120359964b4fSRichard Henderson     case INDEX_op_shl_i32:
120459964b4fSRichard Henderson     case INDEX_op_shl_i64:
120559964b4fSRichard Henderson     case INDEX_op_shr_i32:
120659964b4fSRichard Henderson     case INDEX_op_shr_i64:
120759964b4fSRichard Henderson     case INDEX_op_sar_i32:
120859964b4fSRichard Henderson     case INDEX_op_sar_i64:
120959964b4fSRichard Henderson     case INDEX_op_rotl_i32:
121059964b4fSRichard Henderson     case INDEX_op_rotl_i64:
121159964b4fSRichard Henderson     case INDEX_op_rotr_i32:
121259964b4fSRichard Henderson     case INDEX_op_rotr_i64:
12135255f48cSRichard Henderson     case INDEX_op_clz_i32:
12145255f48cSRichard Henderson     case INDEX_op_clz_i64:
12155255f48cSRichard Henderson     case INDEX_op_ctz_i32:
12165255f48cSRichard Henderson     case INDEX_op_ctz_i64:
121765089889SRichard Henderson         tci_args_rrr(insn, &r0, &r1, &r2);
121859964b4fSRichard Henderson         info->fprintf_func(info->stream, "%-12s  %s, %s, %s",
121959964b4fSRichard Henderson                            op_name, str_r(r0), str_r(r1), str_r(r2));
122059964b4fSRichard Henderson         break;
122159964b4fSRichard Henderson 
122259964b4fSRichard Henderson     case INDEX_op_deposit_i32:
122359964b4fSRichard Henderson     case INDEX_op_deposit_i64:
122465089889SRichard Henderson         tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
122559964b4fSRichard Henderson         info->fprintf_func(info->stream, "%-12s  %s, %s, %s, %d, %d",
122659964b4fSRichard Henderson                            op_name, str_r(r0), str_r(r1), str_r(r2), pos, len);
122759964b4fSRichard Henderson         break;
122859964b4fSRichard Henderson 
12290f10d7c5SRichard Henderson     case INDEX_op_extract_i32:
12300f10d7c5SRichard Henderson     case INDEX_op_extract_i64:
12310f10d7c5SRichard Henderson     case INDEX_op_sextract_i32:
12320f10d7c5SRichard Henderson     case INDEX_op_sextract_i64:
12330f10d7c5SRichard Henderson         tci_args_rrbb(insn, &r0, &r1, &pos, &len);
12340f10d7c5SRichard Henderson         info->fprintf_func(info->stream, "%-12s  %s,%s,%d,%d",
12350f10d7c5SRichard Henderson                            op_name, str_r(r0), str_r(r1), pos, len);
12360f10d7c5SRichard Henderson         break;
12370f10d7c5SRichard Henderson 
1238df093c19SRichard Henderson     case INDEX_op_movcond_i32:
1239df093c19SRichard Henderson     case INDEX_op_movcond_i64:
124059964b4fSRichard Henderson     case INDEX_op_setcond2_i32:
124165089889SRichard Henderson         tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &c);
124259964b4fSRichard Henderson         info->fprintf_func(info->stream, "%-12s  %s, %s, %s, %s, %s, %s",
124359964b4fSRichard Henderson                            op_name, str_r(r0), str_r(r1), str_r(r2),
124459964b4fSRichard Henderson                            str_r(r3), str_r(r4), str_c(c));
124559964b4fSRichard Henderson         break;
124659964b4fSRichard Henderson 
124759964b4fSRichard Henderson     case INDEX_op_mulu2_i32:
1248f6db0d8dSRichard Henderson     case INDEX_op_mulu2_i64:
1249f6db0d8dSRichard Henderson     case INDEX_op_muls2_i32:
1250f6db0d8dSRichard Henderson     case INDEX_op_muls2_i64:
125165089889SRichard Henderson         tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
125259964b4fSRichard Henderson         info->fprintf_func(info->stream, "%-12s  %s, %s, %s, %s",
125359964b4fSRichard Henderson                            op_name, str_r(r0), str_r(r1),
125459964b4fSRichard Henderson                            str_r(r2), str_r(r3));
125559964b4fSRichard Henderson         break;
125659964b4fSRichard Henderson 
125759964b4fSRichard Henderson     case INDEX_op_add2_i32:
125808096b1aSRichard Henderson     case INDEX_op_add2_i64:
125959964b4fSRichard Henderson     case INDEX_op_sub2_i32:
126008096b1aSRichard Henderson     case INDEX_op_sub2_i64:
126165089889SRichard Henderson         tci_args_rrrrrr(insn, &r0, &r1, &r2, &r3, &r4, &r5);
126259964b4fSRichard Henderson         info->fprintf_func(info->stream, "%-12s  %s, %s, %s, %s, %s, %s",
126359964b4fSRichard Henderson                            op_name, str_r(r0), str_r(r1), str_r(r2),
126459964b4fSRichard Henderson                            str_r(r3), str_r(r4), str_r(r5));
126559964b4fSRichard Henderson         break;
126659964b4fSRichard Henderson 
1267fecccfccSRichard Henderson     case INDEX_op_qemu_ld_a32_i32:
1268fecccfccSRichard Henderson     case INDEX_op_qemu_st_a32_i32:
1269fecccfccSRichard Henderson         len = 1 + 1;
127059964b4fSRichard Henderson         goto do_qemu_ldst;
1271fecccfccSRichard Henderson     case INDEX_op_qemu_ld_a32_i64:
1272fecccfccSRichard Henderson     case INDEX_op_qemu_st_a32_i64:
1273fecccfccSRichard Henderson     case INDEX_op_qemu_ld_a64_i32:
1274fecccfccSRichard Henderson     case INDEX_op_qemu_st_a64_i32:
1275fecccfccSRichard Henderson         len = 1 + DIV_ROUND_UP(64, TCG_TARGET_REG_BITS);
1276fecccfccSRichard Henderson         goto do_qemu_ldst;
1277fecccfccSRichard Henderson     case INDEX_op_qemu_ld_a64_i64:
1278fecccfccSRichard Henderson     case INDEX_op_qemu_st_a64_i64:
1279fecccfccSRichard Henderson         len = 2 * DIV_ROUND_UP(64, TCG_TARGET_REG_BITS);
1280fecccfccSRichard Henderson         goto do_qemu_ldst;
128159964b4fSRichard Henderson     do_qemu_ldst:
128259964b4fSRichard Henderson         switch (len) {
128359964b4fSRichard Henderson         case 2:
128465089889SRichard Henderson             tci_args_rrm(insn, &r0, &r1, &oi);
128559964b4fSRichard Henderson             info->fprintf_func(info->stream, "%-12s  %s, %s, %x",
128659964b4fSRichard Henderson                                op_name, str_r(r0), str_r(r1), oi);
128759964b4fSRichard Henderson             break;
128859964b4fSRichard Henderson         case 3:
1289*ab64da79SRichard Henderson             tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
1290*ab64da79SRichard Henderson             info->fprintf_func(info->stream, "%-12s  %s, %s, %s, %s",
1291*ab64da79SRichard Henderson                                op_name, str_r(r0), str_r(r1),
1292*ab64da79SRichard Henderson                                str_r(r2), str_r(r3));
129359964b4fSRichard Henderson             break;
129459964b4fSRichard Henderson         case 4:
129565089889SRichard Henderson             tci_args_rrrrr(insn, &r0, &r1, &r2, &r3, &r4);
129665089889SRichard Henderson             info->fprintf_func(info->stream, "%-12s  %s, %s, %s, %s, %s",
129759964b4fSRichard Henderson                                op_name, str_r(r0), str_r(r1),
129865089889SRichard Henderson                                str_r(r2), str_r(r3), str_r(r4));
129959964b4fSRichard Henderson             break;
130059964b4fSRichard Henderson         default:
130159964b4fSRichard Henderson             g_assert_not_reached();
130259964b4fSRichard Henderson         }
130359964b4fSRichard Henderson         break;
130459964b4fSRichard Henderson 
130565089889SRichard Henderson     case 0:
130665089889SRichard Henderson         /* tcg_out_nop_fill uses zeros */
130765089889SRichard Henderson         if (insn == 0) {
130865089889SRichard Henderson             info->fprintf_func(info->stream, "align");
130965089889SRichard Henderson             break;
131065089889SRichard Henderson         }
131165089889SRichard Henderson         /* fall through */
131265089889SRichard Henderson 
131359964b4fSRichard Henderson     default:
131459964b4fSRichard Henderson         info->fprintf_func(info->stream, "illegal opcode %d", op);
131559964b4fSRichard Henderson         break;
131659964b4fSRichard Henderson     }
131759964b4fSRichard Henderson 
131865089889SRichard Henderson     return sizeof(insn);
131959964b4fSRichard Henderson }
1320