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"
22*ed30e7b1SRichard Henderson #include "tcg/helper-info.h"
23d2ba8026SRichard Henderson #include "tcg/tcg-ldst.h"
247b7d8b2dSRichard Henderson #include <ffi.h>
25244f1441SYang Zhong
267b7d8b2dSRichard Henderson
277b7d8b2dSRichard Henderson /*
287b7d8b2dSRichard Henderson * Enable TCI assertions only when debugging TCG (and without NDEBUG defined).
297b7d8b2dSRichard Henderson * Without assertions, the interpreter runs much faster.
307b7d8b2dSRichard Henderson */
31244f1441SYang Zhong #if defined(CONFIG_DEBUG_TCG)
32244f1441SYang Zhong # define tci_assert(cond) assert(cond)
33244f1441SYang Zhong #else
3492bc4fadSRichard Henderson # define tci_assert(cond) ((void)(cond))
35244f1441SYang Zhong #endif
36244f1441SYang Zhong
3713e71f08SRichard Henderson __thread uintptr_t tci_tb_ptr;
3813e71f08SRichard Henderson
tci_write_reg64(tcg_target_ulong * regs,uint32_t high_index,uint32_t low_index,uint64_t value)395e75150cSEmilio G. Cota static void tci_write_reg64(tcg_target_ulong *regs, uint32_t high_index,
405e75150cSEmilio G. Cota uint32_t low_index, uint64_t value)
41244f1441SYang Zhong {
42f6db0d8dSRichard Henderson regs[low_index] = (uint32_t)value;
437e00a080SRichard Henderson regs[high_index] = value >> 32;
44244f1441SYang Zhong }
45244f1441SYang Zhong
46244f1441SYang Zhong /* Create a 64 bit value from two 32 bit values. */
tci_uint64(uint32_t high,uint32_t low)47244f1441SYang Zhong static uint64_t tci_uint64(uint32_t high, uint32_t low)
48244f1441SYang Zhong {
49244f1441SYang Zhong return ((uint64_t)high << 32) + low;
50244f1441SYang Zhong }
51244f1441SYang Zhong
52cdd9799bSRichard Henderson /*
53cdd9799bSRichard Henderson * Load sets of arguments all at once. The naming convention is:
54cdd9799bSRichard Henderson * tci_args_<arguments>
55cdd9799bSRichard Henderson * where arguments is a sequence of
56cdd9799bSRichard Henderson *
5779dd3a4fSRichard Henderson * b = immediate (bit position)
58963e9fa2SRichard Henderson * c = condition (TCGCond)
59b95aa12eSRichard Henderson * i = immediate (uint32_t)
60b95aa12eSRichard Henderson * I = immediate (tcg_target_ulong)
61f28ca03eSRichard Henderson * l = label or pointer
629002ffcbSRichard Henderson * m = immediate (MemOpIdx)
637b7d8b2dSRichard Henderson * n = immediate (call return length)
64cdd9799bSRichard Henderson * r = register
65cdd9799bSRichard Henderson * s = signed ldst offset
66cdd9799bSRichard Henderson */
67cdd9799bSRichard Henderson
tci_args_l(uint32_t insn,const void * tb_ptr,void ** l0)6865089889SRichard Henderson static void tci_args_l(uint32_t insn, const void *tb_ptr, void **l0)
6992bc4fadSRichard Henderson {
7065089889SRichard Henderson int diff = sextract32(insn, 12, 20);
7165089889SRichard Henderson *l0 = diff ? (void *)tb_ptr + diff : NULL;
7292bc4fadSRichard Henderson }
7392bc4fadSRichard Henderson
tci_args_r(uint32_t insn,TCGReg * r0)746eea0434SRichard Henderson static void tci_args_r(uint32_t insn, TCGReg *r0)
756eea0434SRichard Henderson {
766eea0434SRichard Henderson *r0 = extract32(insn, 8, 4);
776eea0434SRichard Henderson }
786eea0434SRichard Henderson
tci_args_nl(uint32_t insn,const void * tb_ptr,uint8_t * n0,void ** l1)7965089889SRichard Henderson static void tci_args_nl(uint32_t insn, const void *tb_ptr,
8065089889SRichard Henderson uint8_t *n0, void **l1)
81f28ca03eSRichard Henderson {
8265089889SRichard Henderson *n0 = extract32(insn, 8, 4);
8365089889SRichard Henderson *l1 = sextract32(insn, 12, 20) + (void *)tb_ptr;
84f28ca03eSRichard Henderson }
85f28ca03eSRichard Henderson
tci_args_rl(uint32_t insn,const void * tb_ptr,TCGReg * r0,void ** l1)8665089889SRichard Henderson static void tci_args_rl(uint32_t insn, const void *tb_ptr,
8765089889SRichard Henderson TCGReg *r0, void **l1)
887b7d8b2dSRichard Henderson {
8965089889SRichard Henderson *r0 = extract32(insn, 8, 4);
9065089889SRichard Henderson *l1 = sextract32(insn, 12, 20) + (void *)tb_ptr;
917b7d8b2dSRichard Henderson }
927b7d8b2dSRichard Henderson
tci_args_rr(uint32_t insn,TCGReg * r0,TCGReg * r1)9365089889SRichard Henderson static void tci_args_rr(uint32_t insn, TCGReg *r0, TCGReg *r1)
94fc8ec9e1SRichard Henderson {
9565089889SRichard Henderson *r0 = extract32(insn, 8, 4);
9665089889SRichard Henderson *r1 = extract32(insn, 12, 4);
97fc8ec9e1SRichard Henderson }
98fc8ec9e1SRichard Henderson
tci_args_ri(uint32_t insn,TCGReg * r0,tcg_target_ulong * i1)9965089889SRichard Henderson static void tci_args_ri(uint32_t insn, TCGReg *r0, tcg_target_ulong *i1)
100fc4a62f6SRichard Henderson {
10165089889SRichard Henderson *r0 = extract32(insn, 8, 4);
10265089889SRichard Henderson *i1 = sextract32(insn, 12, 20);
103fc4a62f6SRichard Henderson }
104fc4a62f6SRichard Henderson
tci_args_rrm(uint32_t insn,TCGReg * r0,TCGReg * r1,MemOpIdx * m2)10565089889SRichard Henderson static void tci_args_rrm(uint32_t insn, TCGReg *r0,
1069002ffcbSRichard Henderson TCGReg *r1, MemOpIdx *m2)
107b95aa12eSRichard Henderson {
10865089889SRichard Henderson *r0 = extract32(insn, 8, 4);
10965089889SRichard Henderson *r1 = extract32(insn, 12, 4);
110ab64da79SRichard Henderson *m2 = extract32(insn, 16, 16);
111b95aa12eSRichard Henderson }
112b95aa12eSRichard Henderson
tci_args_rrr(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2)11365089889SRichard Henderson static void tci_args_rrr(uint32_t insn, TCGReg *r0, TCGReg *r1, TCGReg *r2)
114b95aa12eSRichard Henderson {
11565089889SRichard Henderson *r0 = extract32(insn, 8, 4);
11665089889SRichard Henderson *r1 = extract32(insn, 12, 4);
11765089889SRichard Henderson *r2 = extract32(insn, 16, 4);
11863041ed2SRichard Henderson }
11963041ed2SRichard Henderson
tci_args_rrs(uint32_t insn,TCGReg * r0,TCGReg * r1,int32_t * i2)12065089889SRichard Henderson static void tci_args_rrs(uint32_t insn, TCGReg *r0, TCGReg *r1, int32_t *i2)
121e85e4b8fSRichard Henderson {
12265089889SRichard Henderson *r0 = extract32(insn, 8, 4);
12365089889SRichard Henderson *r1 = extract32(insn, 12, 4);
12465089889SRichard Henderson *i2 = sextract32(insn, 16, 16);
125e85e4b8fSRichard Henderson }
126e85e4b8fSRichard Henderson
tci_args_rrbb(uint32_t insn,TCGReg * r0,TCGReg * r1,uint8_t * i2,uint8_t * i3)1270f10d7c5SRichard Henderson static void tci_args_rrbb(uint32_t insn, TCGReg *r0, TCGReg *r1,
1280f10d7c5SRichard Henderson uint8_t *i2, uint8_t *i3)
1290f10d7c5SRichard Henderson {
1300f10d7c5SRichard Henderson *r0 = extract32(insn, 8, 4);
1310f10d7c5SRichard Henderson *r1 = extract32(insn, 12, 4);
1320f10d7c5SRichard Henderson *i2 = extract32(insn, 16, 6);
1330f10d7c5SRichard Henderson *i3 = extract32(insn, 22, 6);
1340f10d7c5SRichard Henderson }
1350f10d7c5SRichard Henderson
tci_args_rrrc(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2,TCGCond * c3)13665089889SRichard Henderson static void tci_args_rrrc(uint32_t insn,
137963e9fa2SRichard Henderson TCGReg *r0, TCGReg *r1, TCGReg *r2, TCGCond *c3)
138963e9fa2SRichard Henderson {
13965089889SRichard Henderson *r0 = extract32(insn, 8, 4);
14065089889SRichard Henderson *r1 = extract32(insn, 12, 4);
14165089889SRichard Henderson *r2 = extract32(insn, 16, 4);
14265089889SRichard Henderson *c3 = extract32(insn, 20, 4);
143963e9fa2SRichard Henderson }
144963e9fa2SRichard Henderson
tci_args_rrrbb(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2,uint8_t * i3,uint8_t * i4)14565089889SRichard Henderson static void tci_args_rrrbb(uint32_t insn, TCGReg *r0, TCGReg *r1,
14679dd3a4fSRichard Henderson TCGReg *r2, uint8_t *i3, uint8_t *i4)
14779dd3a4fSRichard Henderson {
14865089889SRichard Henderson *r0 = extract32(insn, 8, 4);
14965089889SRichard Henderson *r1 = extract32(insn, 12, 4);
15065089889SRichard Henderson *r2 = extract32(insn, 16, 4);
15165089889SRichard Henderson *i3 = extract32(insn, 20, 6);
15265089889SRichard Henderson *i4 = extract32(insn, 26, 6);
15379dd3a4fSRichard Henderson }
15479dd3a4fSRichard Henderson
tci_args_rrrrr(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2,TCGReg * r3,TCGReg * r4)15565089889SRichard Henderson static void tci_args_rrrrr(uint32_t insn, TCGReg *r0, TCGReg *r1,
15665089889SRichard Henderson TCGReg *r2, TCGReg *r3, TCGReg *r4)
15763041ed2SRichard Henderson {
15865089889SRichard Henderson *r0 = extract32(insn, 8, 4);
15965089889SRichard Henderson *r1 = extract32(insn, 12, 4);
16065089889SRichard Henderson *r2 = extract32(insn, 16, 4);
16165089889SRichard Henderson *r3 = extract32(insn, 20, 4);
16265089889SRichard Henderson *r4 = extract32(insn, 24, 4);
16363041ed2SRichard Henderson }
16463041ed2SRichard Henderson
tci_args_rrrr(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2,TCGReg * r3)16565089889SRichard Henderson static void tci_args_rrrr(uint32_t insn,
166cbe87131SRichard Henderson TCGReg *r0, TCGReg *r1, TCGReg *r2, TCGReg *r3)
167cbe87131SRichard Henderson {
16865089889SRichard Henderson *r0 = extract32(insn, 8, 4);
16965089889SRichard Henderson *r1 = extract32(insn, 12, 4);
17065089889SRichard Henderson *r2 = extract32(insn, 16, 4);
17165089889SRichard Henderson *r3 = extract32(insn, 20, 4);
172cbe87131SRichard Henderson }
173cbe87131SRichard Henderson
tci_args_rrrrrc(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2,TCGReg * r3,TCGReg * r4,TCGCond * c5)17465089889SRichard Henderson static void tci_args_rrrrrc(uint32_t insn, TCGReg *r0, TCGReg *r1,
175817cadd6SRichard Henderson TCGReg *r2, TCGReg *r3, TCGReg *r4, TCGCond *c5)
176817cadd6SRichard Henderson {
17765089889SRichard Henderson *r0 = extract32(insn, 8, 4);
17865089889SRichard Henderson *r1 = extract32(insn, 12, 4);
17965089889SRichard Henderson *r2 = extract32(insn, 16, 4);
18065089889SRichard Henderson *r3 = extract32(insn, 20, 4);
18165089889SRichard Henderson *r4 = extract32(insn, 24, 4);
18265089889SRichard Henderson *c5 = extract32(insn, 28, 4);
183817cadd6SRichard Henderson }
184120402b5SRichard Henderson
tci_args_rrrrrr(uint32_t insn,TCGReg * r0,TCGReg * r1,TCGReg * r2,TCGReg * r3,TCGReg * r4,TCGReg * r5)18565089889SRichard Henderson static void tci_args_rrrrrr(uint32_t insn, TCGReg *r0, TCGReg *r1,
186120402b5SRichard Henderson TCGReg *r2, TCGReg *r3, TCGReg *r4, TCGReg *r5)
187120402b5SRichard Henderson {
18865089889SRichard Henderson *r0 = extract32(insn, 8, 4);
18965089889SRichard Henderson *r1 = extract32(insn, 12, 4);
19065089889SRichard Henderson *r2 = extract32(insn, 16, 4);
19165089889SRichard Henderson *r3 = extract32(insn, 20, 4);
19265089889SRichard Henderson *r4 = extract32(insn, 24, 4);
19365089889SRichard Henderson *r5 = extract32(insn, 28, 4);
194120402b5SRichard Henderson }
195817cadd6SRichard Henderson
tci_compare32(uint32_t u0,uint32_t u1,TCGCond condition)196244f1441SYang Zhong static bool tci_compare32(uint32_t u0, uint32_t u1, TCGCond condition)
197244f1441SYang Zhong {
198244f1441SYang Zhong bool result = false;
199244f1441SYang Zhong int32_t i0 = u0;
200244f1441SYang Zhong int32_t i1 = u1;
201244f1441SYang Zhong switch (condition) {
202244f1441SYang Zhong case TCG_COND_EQ:
203244f1441SYang Zhong result = (u0 == u1);
204244f1441SYang Zhong break;
205244f1441SYang Zhong case TCG_COND_NE:
206244f1441SYang Zhong result = (u0 != u1);
207244f1441SYang Zhong break;
208244f1441SYang Zhong case TCG_COND_LT:
209244f1441SYang Zhong result = (i0 < i1);
210244f1441SYang Zhong break;
211244f1441SYang Zhong case TCG_COND_GE:
212244f1441SYang Zhong result = (i0 >= i1);
213244f1441SYang Zhong break;
214244f1441SYang Zhong case TCG_COND_LE:
215244f1441SYang Zhong result = (i0 <= i1);
216244f1441SYang Zhong break;
217244f1441SYang Zhong case TCG_COND_GT:
218244f1441SYang Zhong result = (i0 > i1);
219244f1441SYang Zhong break;
220244f1441SYang Zhong case TCG_COND_LTU:
221244f1441SYang Zhong result = (u0 < u1);
222244f1441SYang Zhong break;
223244f1441SYang Zhong case TCG_COND_GEU:
224244f1441SYang Zhong result = (u0 >= u1);
225244f1441SYang Zhong break;
226244f1441SYang Zhong case TCG_COND_LEU:
227244f1441SYang Zhong result = (u0 <= u1);
228244f1441SYang Zhong break;
229244f1441SYang Zhong case TCG_COND_GTU:
230244f1441SYang Zhong result = (u0 > u1);
231244f1441SYang Zhong break;
23223c5692aSRichard Henderson case TCG_COND_TSTEQ:
23323c5692aSRichard Henderson result = (u0 & u1) == 0;
23423c5692aSRichard Henderson break;
23523c5692aSRichard Henderson case TCG_COND_TSTNE:
23623c5692aSRichard Henderson result = (u0 & u1) != 0;
23723c5692aSRichard Henderson break;
238244f1441SYang Zhong default:
239f6996f99SRichard Henderson g_assert_not_reached();
240244f1441SYang Zhong }
241244f1441SYang Zhong return result;
242244f1441SYang Zhong }
243244f1441SYang Zhong
tci_compare64(uint64_t u0,uint64_t u1,TCGCond condition)244244f1441SYang Zhong static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition)
245244f1441SYang Zhong {
246244f1441SYang Zhong bool result = false;
247244f1441SYang Zhong int64_t i0 = u0;
248244f1441SYang Zhong int64_t i1 = u1;
249244f1441SYang Zhong switch (condition) {
250244f1441SYang Zhong case TCG_COND_EQ:
251244f1441SYang Zhong result = (u0 == u1);
252244f1441SYang Zhong break;
253244f1441SYang Zhong case TCG_COND_NE:
254244f1441SYang Zhong result = (u0 != u1);
255244f1441SYang Zhong break;
256244f1441SYang Zhong case TCG_COND_LT:
257244f1441SYang Zhong result = (i0 < i1);
258244f1441SYang Zhong break;
259244f1441SYang Zhong case TCG_COND_GE:
260244f1441SYang Zhong result = (i0 >= i1);
261244f1441SYang Zhong break;
262244f1441SYang Zhong case TCG_COND_LE:
263244f1441SYang Zhong result = (i0 <= i1);
264244f1441SYang Zhong break;
265244f1441SYang Zhong case TCG_COND_GT:
266244f1441SYang Zhong result = (i0 > i1);
267244f1441SYang Zhong break;
268244f1441SYang Zhong case TCG_COND_LTU:
269244f1441SYang Zhong result = (u0 < u1);
270244f1441SYang Zhong break;
271244f1441SYang Zhong case TCG_COND_GEU:
272244f1441SYang Zhong result = (u0 >= u1);
273244f1441SYang Zhong break;
274244f1441SYang Zhong case TCG_COND_LEU:
275244f1441SYang Zhong result = (u0 <= u1);
276244f1441SYang Zhong break;
277244f1441SYang Zhong case TCG_COND_GTU:
278244f1441SYang Zhong result = (u0 > u1);
279244f1441SYang Zhong break;
28023c5692aSRichard Henderson case TCG_COND_TSTEQ:
28123c5692aSRichard Henderson result = (u0 & u1) == 0;
28223c5692aSRichard Henderson break;
28323c5692aSRichard Henderson case TCG_COND_TSTNE:
28423c5692aSRichard Henderson result = (u0 & u1) != 0;
28523c5692aSRichard Henderson break;
286244f1441SYang Zhong default:
287f6996f99SRichard Henderson g_assert_not_reached();
288244f1441SYang Zhong }
289244f1441SYang Zhong return result;
290244f1441SYang Zhong }
291244f1441SYang Zhong
tci_qemu_ld(CPUArchState * env,uint64_t taddr,MemOpIdx oi,const void * tb_ptr)292dd7dc93eSRichard Henderson static uint64_t tci_qemu_ld(CPUArchState *env, uint64_t taddr,
2939002ffcbSRichard Henderson MemOpIdx oi, const void *tb_ptr)
29469acc02aSRichard Henderson {
295fe1bee3aSRichard Henderson MemOp mop = get_memop(oi);
296d1b1348cSRichard Henderson uintptr_t ra = (uintptr_t)tb_ptr;
297d1b1348cSRichard Henderson
2980cadc1edSRichard Henderson switch (mop & MO_SSIZE) {
29969acc02aSRichard Henderson case MO_UB:
3000cadc1edSRichard Henderson return helper_ldub_mmu(env, taddr, oi, ra);
30169acc02aSRichard Henderson case MO_SB:
3020cadc1edSRichard Henderson return helper_ldsb_mmu(env, taddr, oi, ra);
3030cadc1edSRichard Henderson case MO_UW:
3040cadc1edSRichard Henderson return helper_lduw_mmu(env, taddr, oi, ra);
3050cadc1edSRichard Henderson case MO_SW:
3060cadc1edSRichard Henderson return helper_ldsw_mmu(env, taddr, oi, ra);
3070cadc1edSRichard Henderson case MO_UL:
3080cadc1edSRichard Henderson return helper_ldul_mmu(env, taddr, oi, ra);
3090cadc1edSRichard Henderson case MO_SL:
3100cadc1edSRichard Henderson return helper_ldsl_mmu(env, taddr, oi, ra);
3110cadc1edSRichard Henderson case MO_UQ:
3120cadc1edSRichard Henderson return helper_ldq_mmu(env, taddr, oi, ra);
31369acc02aSRichard Henderson default:
31469acc02aSRichard Henderson g_assert_not_reached();
31569acc02aSRichard Henderson }
31669acc02aSRichard Henderson }
31769acc02aSRichard Henderson
tci_qemu_st(CPUArchState * env,uint64_t taddr,uint64_t val,MemOpIdx oi,const void * tb_ptr)318dd7dc93eSRichard Henderson static void tci_qemu_st(CPUArchState *env, uint64_t taddr, uint64_t val,
3199002ffcbSRichard Henderson MemOpIdx oi, const void *tb_ptr)
32069acc02aSRichard Henderson {
321fe1bee3aSRichard Henderson MemOp mop = get_memop(oi);
322d1b1348cSRichard Henderson uintptr_t ra = (uintptr_t)tb_ptr;
323d1b1348cSRichard Henderson
3240cadc1edSRichard Henderson switch (mop & MO_SIZE) {
32569acc02aSRichard Henderson case MO_UB:
3260cadc1edSRichard Henderson helper_stb_mmu(env, taddr, val, oi, ra);
32769acc02aSRichard Henderson break;
3280cadc1edSRichard Henderson case MO_UW:
3290cadc1edSRichard Henderson helper_stw_mmu(env, taddr, val, oi, ra);
33069acc02aSRichard Henderson break;
3310cadc1edSRichard Henderson case MO_UL:
3320cadc1edSRichard Henderson helper_stl_mmu(env, taddr, val, oi, ra);
33369acc02aSRichard Henderson break;
3340cadc1edSRichard Henderson case MO_UQ:
3350cadc1edSRichard Henderson helper_stq_mmu(env, taddr, val, oi, ra);
33669acc02aSRichard Henderson break;
33769acc02aSRichard Henderson default:
33869acc02aSRichard Henderson g_assert_not_reached();
33969acc02aSRichard Henderson }
34069acc02aSRichard Henderson }
34169acc02aSRichard Henderson
3427f33f5cdSRichard Henderson #if TCG_TARGET_REG_BITS == 64
3437f33f5cdSRichard Henderson # define CASE_32_64(x) \
3447f33f5cdSRichard Henderson case glue(glue(INDEX_op_, x), _i64): \
3457f33f5cdSRichard Henderson case glue(glue(INDEX_op_, x), _i32):
3467f33f5cdSRichard Henderson # define CASE_64(x) \
3477f33f5cdSRichard Henderson case glue(glue(INDEX_op_, x), _i64):
3487f33f5cdSRichard Henderson #else
3497f33f5cdSRichard Henderson # define CASE_32_64(x) \
3507f33f5cdSRichard Henderson case glue(glue(INDEX_op_, x), _i32):
3517f33f5cdSRichard Henderson # define CASE_64(x)
3527f33f5cdSRichard Henderson #endif
3537f33f5cdSRichard Henderson
354244f1441SYang Zhong /* Interpret pseudo code in tb. */
355c905a368SDaniele Buono /*
356c905a368SDaniele Buono * Disable CFI checks.
357c905a368SDaniele Buono * One possible operation in the pseudo code is a call to binary code.
358c905a368SDaniele Buono * Therefore, disable CFI checks in the interpreter function
359c905a368SDaniele Buono */
tcg_qemu_tb_exec(CPUArchState * env,const void * v_tb_ptr)360db0c51a3SRichard Henderson uintptr_t QEMU_DISABLE_CFI tcg_qemu_tb_exec(CPUArchState *env,
361db0c51a3SRichard Henderson const void *v_tb_ptr)
362244f1441SYang Zhong {
36365089889SRichard Henderson const uint32_t *tb_ptr = v_tb_ptr;
3645e75150cSEmilio G. Cota tcg_target_ulong regs[TCG_TARGET_NB_REGS];
3657b7d8b2dSRichard Henderson uint64_t stack[(TCG_STATIC_CALL_ARGS_SIZE + TCG_STATIC_FRAME_SIZE)
3667b7d8b2dSRichard Henderson / sizeof(uint64_t)];
367244f1441SYang Zhong
3685e75150cSEmilio G. Cota regs[TCG_AREG0] = (tcg_target_ulong)env;
3697b7d8b2dSRichard Henderson regs[TCG_REG_CALL_STACK] = (uintptr_t)stack;
370244f1441SYang Zhong tci_assert(tb_ptr);
371244f1441SYang Zhong
372244f1441SYang Zhong for (;;) {
37365089889SRichard Henderson uint32_t insn;
37465089889SRichard Henderson TCGOpcode opc;
37508096b1aSRichard Henderson TCGReg r0, r1, r2, r3, r4, r5;
376244f1441SYang Zhong tcg_target_ulong t1;
377244f1441SYang Zhong TCGCond condition;
37879dd3a4fSRichard Henderson uint8_t pos, len;
379244f1441SYang Zhong uint32_t tmp32;
380dd7dc93eSRichard Henderson uint64_t tmp64, taddr;
3815a0adf34SRichard Henderson uint64_t T1, T2;
3829002ffcbSRichard Henderson MemOpIdx oi;
383cdd9799bSRichard Henderson int32_t ofs;
38465089889SRichard Henderson void *ptr;
385244f1441SYang Zhong
38665089889SRichard Henderson insn = *tb_ptr++;
38765089889SRichard Henderson opc = extract32(insn, 0, 8);
388244f1441SYang Zhong
389244f1441SYang Zhong switch (opc) {
390244f1441SYang Zhong case INDEX_op_call:
391e9709e17SRichard Henderson {
392e9709e17SRichard Henderson void *call_slots[MAX_CALL_IARGS];
393e9709e17SRichard Henderson ffi_cif *cif;
394e9709e17SRichard Henderson void *func;
395e9709e17SRichard Henderson unsigned i, s, n;
3967b7d8b2dSRichard Henderson
39765089889SRichard Henderson tci_args_nl(insn, tb_ptr, &len, &ptr);
398e9709e17SRichard Henderson func = ((void **)ptr)[0];
399e9709e17SRichard Henderson cif = ((void **)ptr)[1];
400e9709e17SRichard Henderson
401e9709e17SRichard Henderson n = cif->nargs;
402e9709e17SRichard Henderson for (i = s = 0; i < n; ++i) {
403e9709e17SRichard Henderson ffi_type *t = cif->arg_types[i];
404e9709e17SRichard Henderson call_slots[i] = &stack[s];
405e9709e17SRichard Henderson s += DIV_ROUND_UP(t->size, 8);
406e9709e17SRichard Henderson }
4077b7d8b2dSRichard Henderson
4087b7d8b2dSRichard Henderson /* Helper functions may need to access the "return address" */
40913e71f08SRichard Henderson tci_tb_ptr = (uintptr_t)tb_ptr;
410e9709e17SRichard Henderson ffi_call(cif, func, stack, call_slots);
41165089889SRichard Henderson }
4127b7d8b2dSRichard Henderson
4137b7d8b2dSRichard Henderson switch (len) {
4147b7d8b2dSRichard Henderson case 0: /* void */
415244f1441SYang Zhong break;
4167b7d8b2dSRichard Henderson case 1: /* uint32_t */
4177b7d8b2dSRichard Henderson /*
418896c76e6SRichard Henderson * The result winds up "left-aligned" in the stack[0] slot.
4197b7d8b2dSRichard Henderson * Note that libffi has an odd special case in that it will
4207b7d8b2dSRichard Henderson * always widen an integral result to ffi_arg.
4217b7d8b2dSRichard Henderson */
422896c76e6SRichard Henderson if (sizeof(ffi_arg) == 8) {
423896c76e6SRichard Henderson regs[TCG_REG_R0] = (uint32_t)stack[0];
4247b7d8b2dSRichard Henderson } else {
425896c76e6SRichard Henderson regs[TCG_REG_R0] = *(uint32_t *)stack;
4267b7d8b2dSRichard Henderson }
4277b7d8b2dSRichard Henderson break;
428896c76e6SRichard Henderson case 2: /* uint64_t */
429896c76e6SRichard Henderson /*
430896c76e6SRichard Henderson * For TCG_TARGET_REG_BITS == 32, the register pair
431896c76e6SRichard Henderson * must stay in host memory order.
432896c76e6SRichard Henderson */
433896c76e6SRichard Henderson memcpy(®s[TCG_REG_R0], stack, 8);
434896c76e6SRichard Henderson break;
435e9709e17SRichard Henderson case 3: /* Int128 */
436e9709e17SRichard Henderson memcpy(®s[TCG_REG_R0], stack, 16);
437e9709e17SRichard Henderson break;
4387b7d8b2dSRichard Henderson default:
4397b7d8b2dSRichard Henderson g_assert_not_reached();
4407b7d8b2dSRichard Henderson }
4417b7d8b2dSRichard Henderson break;
4427b7d8b2dSRichard Henderson
443244f1441SYang Zhong case INDEX_op_br:
44465089889SRichard Henderson tci_args_l(insn, tb_ptr, &ptr);
445f28ca03eSRichard Henderson tb_ptr = ptr;
446244f1441SYang Zhong continue;
447244f1441SYang Zhong case INDEX_op_setcond_i32:
44865089889SRichard Henderson tci_args_rrrc(insn, &r0, &r1, &r2, &condition);
449963e9fa2SRichard Henderson regs[r0] = tci_compare32(regs[r1], regs[r2], condition);
450244f1441SYang Zhong break;
451df093c19SRichard Henderson case INDEX_op_movcond_i32:
452df093c19SRichard Henderson tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &condition);
453df093c19SRichard Henderson tmp32 = tci_compare32(regs[r1], regs[r2], condition);
454df093c19SRichard Henderson regs[r0] = regs[tmp32 ? r3 : r4];
455df093c19SRichard Henderson break;
456244f1441SYang Zhong #if TCG_TARGET_REG_BITS == 32
457244f1441SYang Zhong case INDEX_op_setcond2_i32:
45865089889SRichard Henderson tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &condition);
459817cadd6SRichard Henderson T1 = tci_uint64(regs[r2], regs[r1]);
460817cadd6SRichard Henderson T2 = tci_uint64(regs[r4], regs[r3]);
461817cadd6SRichard Henderson regs[r0] = tci_compare64(T1, T2, condition);
462244f1441SYang Zhong break;
463244f1441SYang Zhong #elif TCG_TARGET_REG_BITS == 64
464244f1441SYang Zhong case INDEX_op_setcond_i64:
46565089889SRichard Henderson tci_args_rrrc(insn, &r0, &r1, &r2, &condition);
466963e9fa2SRichard Henderson regs[r0] = tci_compare64(regs[r1], regs[r2], condition);
467244f1441SYang Zhong break;
468df093c19SRichard Henderson case INDEX_op_movcond_i64:
469df093c19SRichard Henderson tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &condition);
470df093c19SRichard Henderson tmp32 = tci_compare64(regs[r1], regs[r2], condition);
471df093c19SRichard Henderson regs[r0] = regs[tmp32 ? r3 : r4];
472df093c19SRichard Henderson break;
473244f1441SYang Zhong #endif
4749e9acb7bSRichard Henderson CASE_32_64(mov)
47565089889SRichard Henderson tci_args_rr(insn, &r0, &r1);
476fc4a62f6SRichard Henderson regs[r0] = regs[r1];
477244f1441SYang Zhong break;
47865089889SRichard Henderson case INDEX_op_tci_movi:
47965089889SRichard Henderson tci_args_ri(insn, &r0, &t1);
480b95aa12eSRichard Henderson regs[r0] = t1;
481244f1441SYang Zhong break;
48265089889SRichard Henderson case INDEX_op_tci_movl:
48365089889SRichard Henderson tci_args_rl(insn, tb_ptr, &r0, &ptr);
48465089889SRichard Henderson regs[r0] = *(tcg_target_ulong *)ptr;
48565089889SRichard Henderson break;
486244f1441SYang Zhong
487244f1441SYang Zhong /* Load/store operations (32 bit). */
488244f1441SYang Zhong
4897f33f5cdSRichard Henderson CASE_32_64(ld8u)
49065089889SRichard Henderson tci_args_rrs(insn, &r0, &r1, &ofs);
491cdd9799bSRichard Henderson ptr = (void *)(regs[r1] + ofs);
492cdd9799bSRichard Henderson regs[r0] = *(uint8_t *)ptr;
493244f1441SYang Zhong break;
494850163ebSRichard Henderson CASE_32_64(ld8s)
49565089889SRichard Henderson tci_args_rrs(insn, &r0, &r1, &ofs);
496cdd9799bSRichard Henderson ptr = (void *)(regs[r1] + ofs);
497cdd9799bSRichard Henderson regs[r0] = *(int8_t *)ptr;
4982f160e0fSStefan Weil break;
49977c38c7cSRichard Henderson CASE_32_64(ld16u)
50065089889SRichard Henderson tci_args_rrs(insn, &r0, &r1, &ofs);
501cdd9799bSRichard Henderson ptr = (void *)(regs[r1] + ofs);
502cdd9799bSRichard Henderson regs[r0] = *(uint16_t *)ptr;
503244f1441SYang Zhong break;
504b09d78bfSRichard Henderson CASE_32_64(ld16s)
50565089889SRichard Henderson tci_args_rrs(insn, &r0, &r1, &ofs);
506cdd9799bSRichard Henderson ptr = (void *)(regs[r1] + ofs);
507cdd9799bSRichard Henderson regs[r0] = *(int16_t *)ptr;
508244f1441SYang Zhong break;
509244f1441SYang Zhong case INDEX_op_ld_i32:
510c1d77e94SRichard Henderson CASE_64(ld32u)
51165089889SRichard Henderson tci_args_rrs(insn, &r0, &r1, &ofs);
512cdd9799bSRichard Henderson ptr = (void *)(regs[r1] + ofs);
513cdd9799bSRichard Henderson regs[r0] = *(uint32_t *)ptr;
514244f1441SYang Zhong break;
515ba9a80c1SRichard Henderson CASE_32_64(st8)
51665089889SRichard Henderson tci_args_rrs(insn, &r0, &r1, &ofs);
517cdd9799bSRichard Henderson ptr = (void *)(regs[r1] + ofs);
518cdd9799bSRichard Henderson *(uint8_t *)ptr = regs[r0];
519244f1441SYang Zhong break;
52090be4ddeSRichard Henderson CASE_32_64(st16)
52165089889SRichard Henderson tci_args_rrs(insn, &r0, &r1, &ofs);
522cdd9799bSRichard Henderson ptr = (void *)(regs[r1] + ofs);
523cdd9799bSRichard Henderson *(uint16_t *)ptr = regs[r0];
524244f1441SYang Zhong break;
525244f1441SYang Zhong case INDEX_op_st_i32:
526b4d5bf0fSRichard Henderson CASE_64(st32)
52765089889SRichard Henderson tci_args_rrs(insn, &r0, &r1, &ofs);
528cdd9799bSRichard Henderson ptr = (void *)(regs[r1] + ofs);
529cdd9799bSRichard Henderson *(uint32_t *)ptr = regs[r0];
530244f1441SYang Zhong break;
531244f1441SYang Zhong
532dd2bb20eSRichard Henderson /* Arithmetic operations (mixed 32/64 bit). */
533244f1441SYang Zhong
534dd2bb20eSRichard Henderson CASE_32_64(add)
53565089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
536e85e4b8fSRichard Henderson regs[r0] = regs[r1] + regs[r2];
537244f1441SYang Zhong break;
538dd2bb20eSRichard Henderson CASE_32_64(sub)
53965089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
540e85e4b8fSRichard Henderson regs[r0] = regs[r1] - regs[r2];
541244f1441SYang Zhong break;
542dd2bb20eSRichard Henderson CASE_32_64(mul)
54365089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
544e85e4b8fSRichard Henderson regs[r0] = regs[r1] * regs[r2];
545244f1441SYang Zhong break;
546dd2bb20eSRichard Henderson CASE_32_64(and)
54765089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
548e85e4b8fSRichard Henderson regs[r0] = regs[r1] & regs[r2];
549dd2bb20eSRichard Henderson break;
550dd2bb20eSRichard Henderson CASE_32_64(or)
55165089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
552e85e4b8fSRichard Henderson regs[r0] = regs[r1] | regs[r2];
553dd2bb20eSRichard Henderson break;
554dd2bb20eSRichard Henderson CASE_32_64(xor)
55565089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
556e85e4b8fSRichard Henderson regs[r0] = regs[r1] ^ regs[r2];
557dd2bb20eSRichard Henderson break;
558a81520b9SRichard Henderson #if TCG_TARGET_HAS_andc_i32 || TCG_TARGET_HAS_andc_i64
559a81520b9SRichard Henderson CASE_32_64(andc)
560a81520b9SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
561a81520b9SRichard Henderson regs[r0] = regs[r1] & ~regs[r2];
562a81520b9SRichard Henderson break;
563a81520b9SRichard Henderson #endif
564a81520b9SRichard Henderson #if TCG_TARGET_HAS_orc_i32 || TCG_TARGET_HAS_orc_i64
565a81520b9SRichard Henderson CASE_32_64(orc)
566a81520b9SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
567a81520b9SRichard Henderson regs[r0] = regs[r1] | ~regs[r2];
568a81520b9SRichard Henderson break;
569a81520b9SRichard Henderson #endif
570a81520b9SRichard Henderson #if TCG_TARGET_HAS_eqv_i32 || TCG_TARGET_HAS_eqv_i64
571a81520b9SRichard Henderson CASE_32_64(eqv)
572a81520b9SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
573a81520b9SRichard Henderson regs[r0] = ~(regs[r1] ^ regs[r2]);
574a81520b9SRichard Henderson break;
575a81520b9SRichard Henderson #endif
576a81520b9SRichard Henderson #if TCG_TARGET_HAS_nand_i32 || TCG_TARGET_HAS_nand_i64
577a81520b9SRichard Henderson CASE_32_64(nand)
578a81520b9SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
579a81520b9SRichard Henderson regs[r0] = ~(regs[r1] & regs[r2]);
580a81520b9SRichard Henderson break;
581a81520b9SRichard Henderson #endif
582a81520b9SRichard Henderson #if TCG_TARGET_HAS_nor_i32 || TCG_TARGET_HAS_nor_i64
583a81520b9SRichard Henderson CASE_32_64(nor)
584a81520b9SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
585a81520b9SRichard Henderson regs[r0] = ~(regs[r1] | regs[r2]);
586a81520b9SRichard Henderson break;
587a81520b9SRichard Henderson #endif
588dd2bb20eSRichard Henderson
589dd2bb20eSRichard Henderson /* Arithmetic operations (32 bit). */
590dd2bb20eSRichard Henderson
591244f1441SYang Zhong case INDEX_op_div_i32:
59265089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
593e85e4b8fSRichard Henderson regs[r0] = (int32_t)regs[r1] / (int32_t)regs[r2];
594244f1441SYang Zhong break;
595244f1441SYang Zhong case INDEX_op_divu_i32:
59665089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
597e85e4b8fSRichard Henderson regs[r0] = (uint32_t)regs[r1] / (uint32_t)regs[r2];
598244f1441SYang Zhong break;
599244f1441SYang Zhong case INDEX_op_rem_i32:
60065089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
601e85e4b8fSRichard Henderson regs[r0] = (int32_t)regs[r1] % (int32_t)regs[r2];
602244f1441SYang Zhong break;
603244f1441SYang Zhong case INDEX_op_remu_i32:
60465089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
605e85e4b8fSRichard Henderson regs[r0] = (uint32_t)regs[r1] % (uint32_t)regs[r2];
606244f1441SYang Zhong break;
6075255f48cSRichard Henderson #if TCG_TARGET_HAS_clz_i32
6085255f48cSRichard Henderson case INDEX_op_clz_i32:
6095255f48cSRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
6105255f48cSRichard Henderson tmp32 = regs[r1];
6115255f48cSRichard Henderson regs[r0] = tmp32 ? clz32(tmp32) : regs[r2];
6125255f48cSRichard Henderson break;
6135255f48cSRichard Henderson #endif
6145255f48cSRichard Henderson #if TCG_TARGET_HAS_ctz_i32
6155255f48cSRichard Henderson case INDEX_op_ctz_i32:
6165255f48cSRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
6175255f48cSRichard Henderson tmp32 = regs[r1];
6185255f48cSRichard Henderson regs[r0] = tmp32 ? ctz32(tmp32) : regs[r2];
6195255f48cSRichard Henderson break;
6205255f48cSRichard Henderson #endif
6215255f48cSRichard Henderson #if TCG_TARGET_HAS_ctpop_i32
6225255f48cSRichard Henderson case INDEX_op_ctpop_i32:
6235255f48cSRichard Henderson tci_args_rr(insn, &r0, &r1);
6245255f48cSRichard Henderson regs[r0] = ctpop32(regs[r1]);
6255255f48cSRichard Henderson break;
6265255f48cSRichard Henderson #endif
627244f1441SYang Zhong
628244f1441SYang Zhong /* Shift/rotate operations (32 bit). */
629244f1441SYang Zhong
630244f1441SYang Zhong case INDEX_op_shl_i32:
63165089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
632e85e4b8fSRichard Henderson regs[r0] = (uint32_t)regs[r1] << (regs[r2] & 31);
633244f1441SYang Zhong break;
634244f1441SYang Zhong case INDEX_op_shr_i32:
63565089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
636e85e4b8fSRichard Henderson regs[r0] = (uint32_t)regs[r1] >> (regs[r2] & 31);
637244f1441SYang Zhong break;
638244f1441SYang Zhong case INDEX_op_sar_i32:
63965089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
640e85e4b8fSRichard Henderson regs[r0] = (int32_t)regs[r1] >> (regs[r2] & 31);
641244f1441SYang Zhong break;
642244f1441SYang Zhong #if TCG_TARGET_HAS_rot_i32
643244f1441SYang Zhong case INDEX_op_rotl_i32:
64465089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
645e85e4b8fSRichard Henderson regs[r0] = rol32(regs[r1], regs[r2] & 31);
646244f1441SYang Zhong break;
647244f1441SYang Zhong case INDEX_op_rotr_i32:
64865089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
649e85e4b8fSRichard Henderson regs[r0] = ror32(regs[r1], regs[r2] & 31);
650244f1441SYang Zhong break;
651244f1441SYang Zhong #endif
652244f1441SYang Zhong #if TCG_TARGET_HAS_deposit_i32
653244f1441SYang Zhong case INDEX_op_deposit_i32:
65465089889SRichard Henderson tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
65579dd3a4fSRichard Henderson regs[r0] = deposit32(regs[r1], pos, len, regs[r2]);
656244f1441SYang Zhong break;
657244f1441SYang Zhong #endif
6580f10d7c5SRichard Henderson #if TCG_TARGET_HAS_extract_i32
6590f10d7c5SRichard Henderson case INDEX_op_extract_i32:
6600f10d7c5SRichard Henderson tci_args_rrbb(insn, &r0, &r1, &pos, &len);
6610f10d7c5SRichard Henderson regs[r0] = extract32(regs[r1], pos, len);
6620f10d7c5SRichard Henderson break;
6630f10d7c5SRichard Henderson #endif
6640f10d7c5SRichard Henderson #if TCG_TARGET_HAS_sextract_i32
6650f10d7c5SRichard Henderson case INDEX_op_sextract_i32:
6660f10d7c5SRichard Henderson tci_args_rrbb(insn, &r0, &r1, &pos, &len);
6670f10d7c5SRichard Henderson regs[r0] = sextract32(regs[r1], pos, len);
6680f10d7c5SRichard Henderson break;
6690f10d7c5SRichard Henderson #endif
670244f1441SYang Zhong case INDEX_op_brcond_i32:
67165089889SRichard Henderson tci_args_rl(insn, tb_ptr, &r0, &ptr);
672fc8ec9e1SRichard Henderson if ((uint32_t)regs[r0]) {
6735a0adf34SRichard Henderson tb_ptr = ptr;
674244f1441SYang Zhong }
675244f1441SYang Zhong break;
67608096b1aSRichard Henderson #if TCG_TARGET_REG_BITS == 32 || TCG_TARGET_HAS_add2_i32
677244f1441SYang Zhong case INDEX_op_add2_i32:
67865089889SRichard Henderson tci_args_rrrrrr(insn, &r0, &r1, &r2, &r3, &r4, &r5);
679120402b5SRichard Henderson T1 = tci_uint64(regs[r3], regs[r2]);
680120402b5SRichard Henderson T2 = tci_uint64(regs[r5], regs[r4]);
681120402b5SRichard Henderson tci_write_reg64(regs, r1, r0, T1 + T2);
682244f1441SYang Zhong break;
68308096b1aSRichard Henderson #endif
68408096b1aSRichard Henderson #if TCG_TARGET_REG_BITS == 32 || TCG_TARGET_HAS_sub2_i32
685244f1441SYang Zhong case INDEX_op_sub2_i32:
68665089889SRichard Henderson tci_args_rrrrrr(insn, &r0, &r1, &r2, &r3, &r4, &r5);
687120402b5SRichard Henderson T1 = tci_uint64(regs[r3], regs[r2]);
688120402b5SRichard Henderson T2 = tci_uint64(regs[r5], regs[r4]);
689120402b5SRichard Henderson tci_write_reg64(regs, r1, r0, T1 - T2);
690244f1441SYang Zhong break;
69108096b1aSRichard Henderson #endif
692f6db0d8dSRichard Henderson #if TCG_TARGET_HAS_mulu2_i32
693244f1441SYang Zhong case INDEX_op_mulu2_i32:
69465089889SRichard Henderson tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
695f6db0d8dSRichard Henderson tmp64 = (uint64_t)(uint32_t)regs[r2] * (uint32_t)regs[r3];
696f6db0d8dSRichard Henderson tci_write_reg64(regs, r1, r0, tmp64);
697244f1441SYang Zhong break;
698f6db0d8dSRichard Henderson #endif
699f6db0d8dSRichard Henderson #if TCG_TARGET_HAS_muls2_i32
700f6db0d8dSRichard Henderson case INDEX_op_muls2_i32:
701f6db0d8dSRichard Henderson tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
702f6db0d8dSRichard Henderson tmp64 = (int64_t)(int32_t)regs[r2] * (int32_t)regs[r3];
703f6db0d8dSRichard Henderson tci_write_reg64(regs, r1, r0, tmp64);
704f6db0d8dSRichard Henderson break;
705f6db0d8dSRichard Henderson #endif
70613a1d640SRichard Henderson #if TCG_TARGET_HAS_ext8s_i32 || TCG_TARGET_HAS_ext8s_i64
70713a1d640SRichard Henderson CASE_32_64(ext8s)
70865089889SRichard Henderson tci_args_rr(insn, &r0, &r1);
709fc4a62f6SRichard Henderson regs[r0] = (int8_t)regs[r1];
710244f1441SYang Zhong break;
711244f1441SYang Zhong #endif
7120d57d36aSRichard Henderson #if TCG_TARGET_HAS_ext16s_i32 || TCG_TARGET_HAS_ext16s_i64 || \
7130d57d36aSRichard Henderson TCG_TARGET_HAS_bswap16_i32 || TCG_TARGET_HAS_bswap16_i64
71413a1d640SRichard Henderson CASE_32_64(ext16s)
71565089889SRichard Henderson tci_args_rr(insn, &r0, &r1);
716fc4a62f6SRichard Henderson regs[r0] = (int16_t)regs[r1];
717244f1441SYang Zhong break;
718244f1441SYang Zhong #endif
71913a1d640SRichard Henderson #if TCG_TARGET_HAS_ext8u_i32 || TCG_TARGET_HAS_ext8u_i64
72013a1d640SRichard Henderson CASE_32_64(ext8u)
72165089889SRichard Henderson tci_args_rr(insn, &r0, &r1);
722fc4a62f6SRichard Henderson regs[r0] = (uint8_t)regs[r1];
723244f1441SYang Zhong break;
724244f1441SYang Zhong #endif
72513a1d640SRichard Henderson #if TCG_TARGET_HAS_ext16u_i32 || TCG_TARGET_HAS_ext16u_i64
72613a1d640SRichard Henderson CASE_32_64(ext16u)
72765089889SRichard Henderson tci_args_rr(insn, &r0, &r1);
728fc4a62f6SRichard Henderson regs[r0] = (uint16_t)regs[r1];
729244f1441SYang Zhong break;
730244f1441SYang Zhong #endif
731fe2b13bbSRichard Henderson #if TCG_TARGET_HAS_bswap16_i32 || TCG_TARGET_HAS_bswap16_i64
732fe2b13bbSRichard Henderson CASE_32_64(bswap16)
73365089889SRichard Henderson tci_args_rr(insn, &r0, &r1);
734fc4a62f6SRichard Henderson regs[r0] = bswap16(regs[r1]);
735244f1441SYang Zhong break;
736244f1441SYang Zhong #endif
737fe2b13bbSRichard Henderson #if TCG_TARGET_HAS_bswap32_i32 || TCG_TARGET_HAS_bswap32_i64
738fe2b13bbSRichard Henderson CASE_32_64(bswap32)
73965089889SRichard Henderson tci_args_rr(insn, &r0, &r1);
740fc4a62f6SRichard Henderson regs[r0] = bswap32(regs[r1]);
741244f1441SYang Zhong break;
742244f1441SYang Zhong #endif
7439e9acb7bSRichard Henderson #if TCG_TARGET_HAS_not_i32 || TCG_TARGET_HAS_not_i64
7449e9acb7bSRichard Henderson CASE_32_64(not)
74565089889SRichard Henderson tci_args_rr(insn, &r0, &r1);
746fc4a62f6SRichard Henderson regs[r0] = ~regs[r1];
747244f1441SYang Zhong break;
748244f1441SYang Zhong #endif
7499e9acb7bSRichard Henderson CASE_32_64(neg)
75065089889SRichard Henderson tci_args_rr(insn, &r0, &r1);
751fc4a62f6SRichard Henderson regs[r0] = -regs[r1];
752244f1441SYang Zhong break;
753244f1441SYang Zhong #if TCG_TARGET_REG_BITS == 64
754244f1441SYang Zhong /* Load/store operations (64 bit). */
755244f1441SYang Zhong
756244f1441SYang Zhong case INDEX_op_ld32s_i64:
75765089889SRichard Henderson tci_args_rrs(insn, &r0, &r1, &ofs);
758cdd9799bSRichard Henderson ptr = (void *)(regs[r1] + ofs);
759cdd9799bSRichard Henderson regs[r0] = *(int32_t *)ptr;
760244f1441SYang Zhong break;
761244f1441SYang Zhong case INDEX_op_ld_i64:
76265089889SRichard Henderson tci_args_rrs(insn, &r0, &r1, &ofs);
763cdd9799bSRichard Henderson ptr = (void *)(regs[r1] + ofs);
764cdd9799bSRichard Henderson regs[r0] = *(uint64_t *)ptr;
765244f1441SYang Zhong break;
766244f1441SYang Zhong case INDEX_op_st_i64:
76765089889SRichard Henderson tci_args_rrs(insn, &r0, &r1, &ofs);
768cdd9799bSRichard Henderson ptr = (void *)(regs[r1] + ofs);
769cdd9799bSRichard Henderson *(uint64_t *)ptr = regs[r0];
770244f1441SYang Zhong break;
771244f1441SYang Zhong
772244f1441SYang Zhong /* Arithmetic operations (64 bit). */
773244f1441SYang Zhong
774244f1441SYang Zhong case INDEX_op_div_i64:
77565089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
776e85e4b8fSRichard Henderson regs[r0] = (int64_t)regs[r1] / (int64_t)regs[r2];
777244f1441SYang Zhong break;
778ae40c098SRichard Henderson case INDEX_op_divu_i64:
77965089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
780e85e4b8fSRichard Henderson regs[r0] = (uint64_t)regs[r1] / (uint64_t)regs[r2];
781ae40c098SRichard Henderson break;
782ae40c098SRichard Henderson case INDEX_op_rem_i64:
78365089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
784e85e4b8fSRichard Henderson regs[r0] = (int64_t)regs[r1] % (int64_t)regs[r2];
785ae40c098SRichard Henderson break;
786ae40c098SRichard Henderson case INDEX_op_remu_i64:
78765089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
788e85e4b8fSRichard Henderson regs[r0] = (uint64_t)regs[r1] % (uint64_t)regs[r2];
789ae40c098SRichard Henderson break;
7905255f48cSRichard Henderson #if TCG_TARGET_HAS_clz_i64
7915255f48cSRichard Henderson case INDEX_op_clz_i64:
7925255f48cSRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
7935255f48cSRichard Henderson regs[r0] = regs[r1] ? clz64(regs[r1]) : regs[r2];
7945255f48cSRichard Henderson break;
7955255f48cSRichard Henderson #endif
7965255f48cSRichard Henderson #if TCG_TARGET_HAS_ctz_i64
7975255f48cSRichard Henderson case INDEX_op_ctz_i64:
7985255f48cSRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
7995255f48cSRichard Henderson regs[r0] = regs[r1] ? ctz64(regs[r1]) : regs[r2];
8005255f48cSRichard Henderson break;
8015255f48cSRichard Henderson #endif
8025255f48cSRichard Henderson #if TCG_TARGET_HAS_ctpop_i64
8035255f48cSRichard Henderson case INDEX_op_ctpop_i64:
8045255f48cSRichard Henderson tci_args_rr(insn, &r0, &r1);
8055255f48cSRichard Henderson regs[r0] = ctpop64(regs[r1]);
8065255f48cSRichard Henderson break;
8075255f48cSRichard Henderson #endif
808f6db0d8dSRichard Henderson #if TCG_TARGET_HAS_mulu2_i64
809f6db0d8dSRichard Henderson case INDEX_op_mulu2_i64:
810f6db0d8dSRichard Henderson tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
811f6db0d8dSRichard Henderson mulu64(®s[r0], ®s[r1], regs[r2], regs[r3]);
812f6db0d8dSRichard Henderson break;
813f6db0d8dSRichard Henderson #endif
814f6db0d8dSRichard Henderson #if TCG_TARGET_HAS_muls2_i64
815f6db0d8dSRichard Henderson case INDEX_op_muls2_i64:
816f6db0d8dSRichard Henderson tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
817f6db0d8dSRichard Henderson muls64(®s[r0], ®s[r1], regs[r2], regs[r3]);
818f6db0d8dSRichard Henderson break;
819f6db0d8dSRichard Henderson #endif
82008096b1aSRichard Henderson #if TCG_TARGET_HAS_add2_i64
82108096b1aSRichard Henderson case INDEX_op_add2_i64:
82208096b1aSRichard Henderson tci_args_rrrrrr(insn, &r0, &r1, &r2, &r3, &r4, &r5);
82308096b1aSRichard Henderson T1 = regs[r2] + regs[r4];
82408096b1aSRichard Henderson T2 = regs[r3] + regs[r5] + (T1 < regs[r2]);
82508096b1aSRichard Henderson regs[r0] = T1;
82608096b1aSRichard Henderson regs[r1] = T2;
82708096b1aSRichard Henderson break;
82808096b1aSRichard Henderson #endif
82908096b1aSRichard Henderson #if TCG_TARGET_HAS_add2_i64
83008096b1aSRichard Henderson case INDEX_op_sub2_i64:
83108096b1aSRichard Henderson tci_args_rrrrrr(insn, &r0, &r1, &r2, &r3, &r4, &r5);
83208096b1aSRichard Henderson T1 = regs[r2] - regs[r4];
83308096b1aSRichard Henderson T2 = regs[r3] - regs[r5] - (regs[r2] < regs[r4]);
83408096b1aSRichard Henderson regs[r0] = T1;
83508096b1aSRichard Henderson regs[r1] = T2;
83608096b1aSRichard Henderson break;
83708096b1aSRichard Henderson #endif
838244f1441SYang Zhong
839244f1441SYang Zhong /* Shift/rotate operations (64 bit). */
840244f1441SYang Zhong
841244f1441SYang Zhong case INDEX_op_shl_i64:
84265089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
843e85e4b8fSRichard Henderson regs[r0] = regs[r1] << (regs[r2] & 63);
844244f1441SYang Zhong break;
845244f1441SYang Zhong case INDEX_op_shr_i64:
84665089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
847e85e4b8fSRichard Henderson regs[r0] = regs[r1] >> (regs[r2] & 63);
848244f1441SYang Zhong break;
849244f1441SYang Zhong case INDEX_op_sar_i64:
85065089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
851e85e4b8fSRichard Henderson regs[r0] = (int64_t)regs[r1] >> (regs[r2] & 63);
852244f1441SYang Zhong break;
853244f1441SYang Zhong #if TCG_TARGET_HAS_rot_i64
854244f1441SYang Zhong case INDEX_op_rotl_i64:
85565089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
856e85e4b8fSRichard Henderson regs[r0] = rol64(regs[r1], regs[r2] & 63);
857244f1441SYang Zhong break;
858244f1441SYang Zhong case INDEX_op_rotr_i64:
85965089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
860e85e4b8fSRichard Henderson regs[r0] = ror64(regs[r1], regs[r2] & 63);
861244f1441SYang Zhong break;
862244f1441SYang Zhong #endif
863244f1441SYang Zhong #if TCG_TARGET_HAS_deposit_i64
864244f1441SYang Zhong case INDEX_op_deposit_i64:
86565089889SRichard Henderson tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
86679dd3a4fSRichard Henderson regs[r0] = deposit64(regs[r1], pos, len, regs[r2]);
867244f1441SYang Zhong break;
868244f1441SYang Zhong #endif
8690f10d7c5SRichard Henderson #if TCG_TARGET_HAS_extract_i64
8700f10d7c5SRichard Henderson case INDEX_op_extract_i64:
8710f10d7c5SRichard Henderson tci_args_rrbb(insn, &r0, &r1, &pos, &len);
8720f10d7c5SRichard Henderson regs[r0] = extract64(regs[r1], pos, len);
8730f10d7c5SRichard Henderson break;
8740f10d7c5SRichard Henderson #endif
8750f10d7c5SRichard Henderson #if TCG_TARGET_HAS_sextract_i64
8760f10d7c5SRichard Henderson case INDEX_op_sextract_i64:
8770f10d7c5SRichard Henderson tci_args_rrbb(insn, &r0, &r1, &pos, &len);
8780f10d7c5SRichard Henderson regs[r0] = sextract64(regs[r1], pos, len);
8790f10d7c5SRichard Henderson break;
8800f10d7c5SRichard Henderson #endif
881244f1441SYang Zhong case INDEX_op_brcond_i64:
88265089889SRichard Henderson tci_args_rl(insn, tb_ptr, &r0, &ptr);
883fc8ec9e1SRichard Henderson if (regs[r0]) {
8845a0adf34SRichard Henderson tb_ptr = ptr;
885244f1441SYang Zhong }
886244f1441SYang Zhong break;
887244f1441SYang Zhong case INDEX_op_ext32s_i64:
888244f1441SYang Zhong case INDEX_op_ext_i32_i64:
88965089889SRichard Henderson tci_args_rr(insn, &r0, &r1);
890fc4a62f6SRichard Henderson regs[r0] = (int32_t)regs[r1];
891244f1441SYang Zhong break;
892244f1441SYang Zhong case INDEX_op_ext32u_i64:
893244f1441SYang Zhong case INDEX_op_extu_i32_i64:
89465089889SRichard Henderson tci_args_rr(insn, &r0, &r1);
895fc4a62f6SRichard Henderson regs[r0] = (uint32_t)regs[r1];
896244f1441SYang Zhong break;
897244f1441SYang Zhong #if TCG_TARGET_HAS_bswap64_i64
898244f1441SYang Zhong case INDEX_op_bswap64_i64:
89965089889SRichard Henderson tci_args_rr(insn, &r0, &r1);
900fc4a62f6SRichard Henderson regs[r0] = bswap64(regs[r1]);
901244f1441SYang Zhong break;
902244f1441SYang Zhong #endif
903244f1441SYang Zhong #endif /* TCG_TARGET_REG_BITS == 64 */
904244f1441SYang Zhong
905244f1441SYang Zhong /* QEMU specific operations. */
906244f1441SYang Zhong
907244f1441SYang Zhong case INDEX_op_exit_tb:
90865089889SRichard Henderson tci_args_l(insn, tb_ptr, &ptr);
909158d3873SRichard Henderson return (uintptr_t)ptr;
910158d3873SRichard Henderson
911244f1441SYang Zhong case INDEX_op_goto_tb:
91265089889SRichard Henderson tci_args_l(insn, tb_ptr, &ptr);
9131670a2b9SRichard Henderson tb_ptr = *(void **)ptr;
91492bc4fadSRichard Henderson break;
9151670a2b9SRichard Henderson
9166eea0434SRichard Henderson case INDEX_op_goto_ptr:
9176eea0434SRichard Henderson tci_args_r(insn, &r0);
9186eea0434SRichard Henderson ptr = (void *)regs[r0];
9196eea0434SRichard Henderson if (!ptr) {
9206eea0434SRichard Henderson return 0;
9216eea0434SRichard Henderson }
9226eea0434SRichard Henderson tb_ptr = ptr;
9236eea0434SRichard Henderson break;
9246eea0434SRichard Henderson
925fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i32:
926dd7dc93eSRichard Henderson tci_args_rrm(insn, &r0, &r1, &oi);
927dd7dc93eSRichard Henderson taddr = (uint32_t)regs[r1];
928dd7dc93eSRichard Henderson goto do_ld_i32;
929fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i32:
930dd7dc93eSRichard Henderson if (TCG_TARGET_REG_BITS == 64) {
93165089889SRichard Henderson tci_args_rrm(insn, &r0, &r1, &oi);
93263041ed2SRichard Henderson taddr = regs[r1];
93363041ed2SRichard Henderson } else {
934ab64da79SRichard Henderson tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
93563041ed2SRichard Henderson taddr = tci_uint64(regs[r2], regs[r1]);
936ab64da79SRichard Henderson oi = regs[r3];
93763041ed2SRichard Henderson }
938dd7dc93eSRichard Henderson do_ld_i32:
939dd7dc93eSRichard Henderson regs[r0] = tci_qemu_ld(env, taddr, oi, tb_ptr);
940244f1441SYang Zhong break;
94163041ed2SRichard Henderson
942fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i64:
943dd7dc93eSRichard Henderson if (TCG_TARGET_REG_BITS == 64) {
944dd7dc93eSRichard Henderson tci_args_rrm(insn, &r0, &r1, &oi);
945dd7dc93eSRichard Henderson taddr = (uint32_t)regs[r1];
946dd7dc93eSRichard Henderson } else {
947ab64da79SRichard Henderson tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
948dd7dc93eSRichard Henderson taddr = (uint32_t)regs[r2];
949ab64da79SRichard Henderson oi = regs[r3];
950dd7dc93eSRichard Henderson }
951dd7dc93eSRichard Henderson goto do_ld_i64;
952fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i64:
95363041ed2SRichard Henderson if (TCG_TARGET_REG_BITS == 64) {
95465089889SRichard Henderson tci_args_rrm(insn, &r0, &r1, &oi);
95563041ed2SRichard Henderson taddr = regs[r1];
95663041ed2SRichard Henderson } else {
95765089889SRichard Henderson tci_args_rrrrr(insn, &r0, &r1, &r2, &r3, &r4);
95863041ed2SRichard Henderson taddr = tci_uint64(regs[r3], regs[r2]);
95965089889SRichard Henderson oi = regs[r4];
960244f1441SYang Zhong }
961dd7dc93eSRichard Henderson do_ld_i64:
96269acc02aSRichard Henderson tmp64 = tci_qemu_ld(env, taddr, oi, tb_ptr);
963244f1441SYang Zhong if (TCG_TARGET_REG_BITS == 32) {
96463041ed2SRichard Henderson tci_write_reg64(regs, r1, r0, tmp64);
96563041ed2SRichard Henderson } else {
96663041ed2SRichard Henderson regs[r0] = tmp64;
967244f1441SYang Zhong }
968244f1441SYang Zhong break;
96963041ed2SRichard Henderson
970fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i32:
971dd7dc93eSRichard Henderson tci_args_rrm(insn, &r0, &r1, &oi);
972dd7dc93eSRichard Henderson taddr = (uint32_t)regs[r1];
973dd7dc93eSRichard Henderson goto do_st_i32;
974fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i32:
975dd7dc93eSRichard Henderson if (TCG_TARGET_REG_BITS == 64) {
97665089889SRichard Henderson tci_args_rrm(insn, &r0, &r1, &oi);
97763041ed2SRichard Henderson taddr = regs[r1];
97863041ed2SRichard Henderson } else {
979ab64da79SRichard Henderson tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
98063041ed2SRichard Henderson taddr = tci_uint64(regs[r2], regs[r1]);
981ab64da79SRichard Henderson oi = regs[r3];
98263041ed2SRichard Henderson }
983dd7dc93eSRichard Henderson do_st_i32:
984dd7dc93eSRichard Henderson tci_qemu_st(env, taddr, regs[r0], oi, tb_ptr);
985244f1441SYang Zhong break;
98663041ed2SRichard Henderson
987fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i64:
988dd7dc93eSRichard Henderson if (TCG_TARGET_REG_BITS == 64) {
989dd7dc93eSRichard Henderson tci_args_rrm(insn, &r0, &r1, &oi);
990dd7dc93eSRichard Henderson tmp64 = regs[r0];
991dd7dc93eSRichard Henderson taddr = (uint32_t)regs[r1];
992dd7dc93eSRichard Henderson } else {
993ab64da79SRichard Henderson tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
994dd7dc93eSRichard Henderson tmp64 = tci_uint64(regs[r1], regs[r0]);
995dd7dc93eSRichard Henderson taddr = (uint32_t)regs[r2];
996ab64da79SRichard Henderson oi = regs[r3];
997dd7dc93eSRichard Henderson }
998dd7dc93eSRichard Henderson goto do_st_i64;
999fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i64:
100063041ed2SRichard Henderson if (TCG_TARGET_REG_BITS == 64) {
100165089889SRichard Henderson tci_args_rrm(insn, &r0, &r1, &oi);
100263041ed2SRichard Henderson tmp64 = regs[r0];
1003dd7dc93eSRichard Henderson taddr = regs[r1];
100463041ed2SRichard Henderson } else {
100565089889SRichard Henderson tci_args_rrrrr(insn, &r0, &r1, &r2, &r3, &r4);
1006dd7dc93eSRichard Henderson tmp64 = tci_uint64(regs[r1], regs[r0]);
100763041ed2SRichard Henderson taddr = tci_uint64(regs[r3], regs[r2]);
100865089889SRichard Henderson oi = regs[r4];
100963041ed2SRichard Henderson }
1010dd7dc93eSRichard Henderson do_st_i64:
101169acc02aSRichard Henderson tci_qemu_st(env, taddr, tmp64, oi, tb_ptr);
1012244f1441SYang Zhong break;
101363041ed2SRichard Henderson
1014244f1441SYang Zhong case INDEX_op_mb:
1015244f1441SYang Zhong /* Ensure ordering for all kinds */
1016244f1441SYang Zhong smp_mb();
1017244f1441SYang Zhong break;
1018244f1441SYang Zhong default:
1019f6996f99SRichard Henderson g_assert_not_reached();
1020244f1441SYang Zhong }
1021244f1441SYang Zhong }
1022244f1441SYang Zhong }
102359964b4fSRichard Henderson
102459964b4fSRichard Henderson /*
102559964b4fSRichard Henderson * Disassembler that matches the interpreter
102659964b4fSRichard Henderson */
102759964b4fSRichard Henderson
str_r(TCGReg r)102859964b4fSRichard Henderson static const char *str_r(TCGReg r)
102959964b4fSRichard Henderson {
103059964b4fSRichard Henderson static const char regs[TCG_TARGET_NB_REGS][4] = {
103159964b4fSRichard Henderson "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
103259964b4fSRichard Henderson "r8", "r9", "r10", "r11", "r12", "r13", "env", "sp"
103359964b4fSRichard Henderson };
103459964b4fSRichard Henderson
103559964b4fSRichard Henderson QEMU_BUILD_BUG_ON(TCG_AREG0 != TCG_REG_R14);
103659964b4fSRichard Henderson QEMU_BUILD_BUG_ON(TCG_REG_CALL_STACK != TCG_REG_R15);
103759964b4fSRichard Henderson
103859964b4fSRichard Henderson assert((unsigned)r < TCG_TARGET_NB_REGS);
103959964b4fSRichard Henderson return regs[r];
104059964b4fSRichard Henderson }
104159964b4fSRichard Henderson
str_c(TCGCond c)104259964b4fSRichard Henderson static const char *str_c(TCGCond c)
104359964b4fSRichard Henderson {
104459964b4fSRichard Henderson static const char cond[16][8] = {
104559964b4fSRichard Henderson [TCG_COND_NEVER] = "never",
104659964b4fSRichard Henderson [TCG_COND_ALWAYS] = "always",
104759964b4fSRichard Henderson [TCG_COND_EQ] = "eq",
104859964b4fSRichard Henderson [TCG_COND_NE] = "ne",
104959964b4fSRichard Henderson [TCG_COND_LT] = "lt",
105059964b4fSRichard Henderson [TCG_COND_GE] = "ge",
105159964b4fSRichard Henderson [TCG_COND_LE] = "le",
105259964b4fSRichard Henderson [TCG_COND_GT] = "gt",
105359964b4fSRichard Henderson [TCG_COND_LTU] = "ltu",
105459964b4fSRichard Henderson [TCG_COND_GEU] = "geu",
105559964b4fSRichard Henderson [TCG_COND_LEU] = "leu",
105659964b4fSRichard Henderson [TCG_COND_GTU] = "gtu",
105723c5692aSRichard Henderson [TCG_COND_TSTEQ] = "tsteq",
105823c5692aSRichard Henderson [TCG_COND_TSTNE] = "tstne",
105959964b4fSRichard Henderson };
106059964b4fSRichard Henderson
106159964b4fSRichard Henderson assert((unsigned)c < ARRAY_SIZE(cond));
106259964b4fSRichard Henderson assert(cond[c][0] != 0);
106359964b4fSRichard Henderson return cond[c];
106459964b4fSRichard Henderson }
106559964b4fSRichard Henderson
106659964b4fSRichard Henderson /* Disassemble TCI bytecode. */
print_insn_tci(bfd_vma addr,disassemble_info * info)106759964b4fSRichard Henderson int print_insn_tci(bfd_vma addr, disassemble_info *info)
106859964b4fSRichard Henderson {
106965089889SRichard Henderson const uint32_t *tb_ptr = (const void *)(uintptr_t)addr;
107059964b4fSRichard Henderson const TCGOpDef *def;
107159964b4fSRichard Henderson const char *op_name;
107265089889SRichard Henderson uint32_t insn;
107359964b4fSRichard Henderson TCGOpcode op;
107408096b1aSRichard Henderson TCGReg r0, r1, r2, r3, r4, r5;
107559964b4fSRichard Henderson tcg_target_ulong i1;
107659964b4fSRichard Henderson int32_t s2;
107759964b4fSRichard Henderson TCGCond c;
10789002ffcbSRichard Henderson MemOpIdx oi;
107959964b4fSRichard Henderson uint8_t pos, len;
108065089889SRichard Henderson void *ptr;
108159964b4fSRichard Henderson
108265089889SRichard Henderson /* TCI is always the host, so we don't need to load indirect. */
108365089889SRichard Henderson insn = *tb_ptr++;
108459964b4fSRichard Henderson
108565089889SRichard Henderson info->fprintf_func(info->stream, "%08x ", insn);
108659964b4fSRichard Henderson
108765089889SRichard Henderson op = extract32(insn, 0, 8);
108859964b4fSRichard Henderson def = &tcg_op_defs[op];
108959964b4fSRichard Henderson op_name = def->name;
109059964b4fSRichard Henderson
109159964b4fSRichard Henderson switch (op) {
109259964b4fSRichard Henderson case INDEX_op_br:
109359964b4fSRichard Henderson case INDEX_op_exit_tb:
109459964b4fSRichard Henderson case INDEX_op_goto_tb:
109565089889SRichard Henderson tci_args_l(insn, tb_ptr, &ptr);
109659964b4fSRichard Henderson info->fprintf_func(info->stream, "%-12s %p", op_name, ptr);
109759964b4fSRichard Henderson break;
109859964b4fSRichard Henderson
10996eea0434SRichard Henderson case INDEX_op_goto_ptr:
11006eea0434SRichard Henderson tci_args_r(insn, &r0);
11016eea0434SRichard Henderson info->fprintf_func(info->stream, "%-12s %s", op_name, str_r(r0));
11026eea0434SRichard Henderson break;
11036eea0434SRichard Henderson
11047b7d8b2dSRichard Henderson case INDEX_op_call:
110565089889SRichard Henderson tci_args_nl(insn, tb_ptr, &len, &ptr);
110665089889SRichard Henderson info->fprintf_func(info->stream, "%-12s %d, %p", op_name, len, ptr);
11077b7d8b2dSRichard Henderson break;
11087b7d8b2dSRichard Henderson
110959964b4fSRichard Henderson case INDEX_op_brcond_i32:
111059964b4fSRichard Henderson case INDEX_op_brcond_i64:
111165089889SRichard Henderson tci_args_rl(insn, tb_ptr, &r0, &ptr);
1112fc8ec9e1SRichard Henderson info->fprintf_func(info->stream, "%-12s %s, 0, ne, %p",
1113fc8ec9e1SRichard Henderson op_name, str_r(r0), ptr);
111459964b4fSRichard Henderson break;
111559964b4fSRichard Henderson
111659964b4fSRichard Henderson case INDEX_op_setcond_i32:
111759964b4fSRichard Henderson case INDEX_op_setcond_i64:
111865089889SRichard Henderson tci_args_rrrc(insn, &r0, &r1, &r2, &c);
111959964b4fSRichard Henderson info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s",
112059964b4fSRichard Henderson op_name, str_r(r0), str_r(r1), str_r(r2), str_c(c));
112159964b4fSRichard Henderson break;
112259964b4fSRichard Henderson
112365089889SRichard Henderson case INDEX_op_tci_movi:
112465089889SRichard Henderson tci_args_ri(insn, &r0, &i1);
112559964b4fSRichard Henderson info->fprintf_func(info->stream, "%-12s %s, 0x%" TCG_PRIlx,
112659964b4fSRichard Henderson op_name, str_r(r0), i1);
112759964b4fSRichard Henderson break;
112859964b4fSRichard Henderson
112965089889SRichard Henderson case INDEX_op_tci_movl:
113065089889SRichard Henderson tci_args_rl(insn, tb_ptr, &r0, &ptr);
113165089889SRichard Henderson info->fprintf_func(info->stream, "%-12s %s, %p",
113265089889SRichard Henderson op_name, str_r(r0), ptr);
113359964b4fSRichard Henderson break;
113459964b4fSRichard Henderson
113559964b4fSRichard Henderson case INDEX_op_ld8u_i32:
113659964b4fSRichard Henderson case INDEX_op_ld8u_i64:
113759964b4fSRichard Henderson case INDEX_op_ld8s_i32:
113859964b4fSRichard Henderson case INDEX_op_ld8s_i64:
113959964b4fSRichard Henderson case INDEX_op_ld16u_i32:
114059964b4fSRichard Henderson case INDEX_op_ld16u_i64:
114159964b4fSRichard Henderson case INDEX_op_ld16s_i32:
114259964b4fSRichard Henderson case INDEX_op_ld16s_i64:
114359964b4fSRichard Henderson case INDEX_op_ld32u_i64:
114459964b4fSRichard Henderson case INDEX_op_ld32s_i64:
114559964b4fSRichard Henderson case INDEX_op_ld_i32:
114659964b4fSRichard Henderson case INDEX_op_ld_i64:
114759964b4fSRichard Henderson case INDEX_op_st8_i32:
114859964b4fSRichard Henderson case INDEX_op_st8_i64:
114959964b4fSRichard Henderson case INDEX_op_st16_i32:
115059964b4fSRichard Henderson case INDEX_op_st16_i64:
115159964b4fSRichard Henderson case INDEX_op_st32_i64:
115259964b4fSRichard Henderson case INDEX_op_st_i32:
115359964b4fSRichard Henderson case INDEX_op_st_i64:
115465089889SRichard Henderson tci_args_rrs(insn, &r0, &r1, &s2);
115559964b4fSRichard Henderson info->fprintf_func(info->stream, "%-12s %s, %s, %d",
115659964b4fSRichard Henderson op_name, str_r(r0), str_r(r1), s2);
115759964b4fSRichard Henderson break;
115859964b4fSRichard Henderson
115959964b4fSRichard Henderson case INDEX_op_mov_i32:
116059964b4fSRichard Henderson case INDEX_op_mov_i64:
116159964b4fSRichard Henderson case INDEX_op_ext8s_i32:
116259964b4fSRichard Henderson case INDEX_op_ext8s_i64:
116359964b4fSRichard Henderson case INDEX_op_ext8u_i32:
116459964b4fSRichard Henderson case INDEX_op_ext8u_i64:
116559964b4fSRichard Henderson case INDEX_op_ext16s_i32:
116659964b4fSRichard Henderson case INDEX_op_ext16s_i64:
116759964b4fSRichard Henderson case INDEX_op_ext16u_i32:
116859964b4fSRichard Henderson case INDEX_op_ext32s_i64:
116959964b4fSRichard Henderson case INDEX_op_ext32u_i64:
117059964b4fSRichard Henderson case INDEX_op_ext_i32_i64:
117159964b4fSRichard Henderson case INDEX_op_extu_i32_i64:
117259964b4fSRichard Henderson case INDEX_op_bswap16_i32:
117359964b4fSRichard Henderson case INDEX_op_bswap16_i64:
117459964b4fSRichard Henderson case INDEX_op_bswap32_i32:
117559964b4fSRichard Henderson case INDEX_op_bswap32_i64:
117659964b4fSRichard Henderson case INDEX_op_bswap64_i64:
117759964b4fSRichard Henderson case INDEX_op_not_i32:
117859964b4fSRichard Henderson case INDEX_op_not_i64:
117959964b4fSRichard Henderson case INDEX_op_neg_i32:
118059964b4fSRichard Henderson case INDEX_op_neg_i64:
11815255f48cSRichard Henderson case INDEX_op_ctpop_i32:
11825255f48cSRichard Henderson case INDEX_op_ctpop_i64:
118365089889SRichard Henderson tci_args_rr(insn, &r0, &r1);
118459964b4fSRichard Henderson info->fprintf_func(info->stream, "%-12s %s, %s",
118559964b4fSRichard Henderson op_name, str_r(r0), str_r(r1));
118659964b4fSRichard Henderson break;
118759964b4fSRichard Henderson
118859964b4fSRichard Henderson case INDEX_op_add_i32:
118959964b4fSRichard Henderson case INDEX_op_add_i64:
119059964b4fSRichard Henderson case INDEX_op_sub_i32:
119159964b4fSRichard Henderson case INDEX_op_sub_i64:
119259964b4fSRichard Henderson case INDEX_op_mul_i32:
119359964b4fSRichard Henderson case INDEX_op_mul_i64:
119459964b4fSRichard Henderson case INDEX_op_and_i32:
119559964b4fSRichard Henderson case INDEX_op_and_i64:
119659964b4fSRichard Henderson case INDEX_op_or_i32:
119759964b4fSRichard Henderson case INDEX_op_or_i64:
119859964b4fSRichard Henderson case INDEX_op_xor_i32:
119959964b4fSRichard Henderson case INDEX_op_xor_i64:
1200a81520b9SRichard Henderson case INDEX_op_andc_i32:
1201a81520b9SRichard Henderson case INDEX_op_andc_i64:
1202a81520b9SRichard Henderson case INDEX_op_orc_i32:
1203a81520b9SRichard Henderson case INDEX_op_orc_i64:
1204a81520b9SRichard Henderson case INDEX_op_eqv_i32:
1205a81520b9SRichard Henderson case INDEX_op_eqv_i64:
1206a81520b9SRichard Henderson case INDEX_op_nand_i32:
1207a81520b9SRichard Henderson case INDEX_op_nand_i64:
1208a81520b9SRichard Henderson case INDEX_op_nor_i32:
1209a81520b9SRichard Henderson case INDEX_op_nor_i64:
121059964b4fSRichard Henderson case INDEX_op_div_i32:
121159964b4fSRichard Henderson case INDEX_op_div_i64:
121259964b4fSRichard Henderson case INDEX_op_rem_i32:
121359964b4fSRichard Henderson case INDEX_op_rem_i64:
121459964b4fSRichard Henderson case INDEX_op_divu_i32:
121559964b4fSRichard Henderson case INDEX_op_divu_i64:
121659964b4fSRichard Henderson case INDEX_op_remu_i32:
121759964b4fSRichard Henderson case INDEX_op_remu_i64:
121859964b4fSRichard Henderson case INDEX_op_shl_i32:
121959964b4fSRichard Henderson case INDEX_op_shl_i64:
122059964b4fSRichard Henderson case INDEX_op_shr_i32:
122159964b4fSRichard Henderson case INDEX_op_shr_i64:
122259964b4fSRichard Henderson case INDEX_op_sar_i32:
122359964b4fSRichard Henderson case INDEX_op_sar_i64:
122459964b4fSRichard Henderson case INDEX_op_rotl_i32:
122559964b4fSRichard Henderson case INDEX_op_rotl_i64:
122659964b4fSRichard Henderson case INDEX_op_rotr_i32:
122759964b4fSRichard Henderson case INDEX_op_rotr_i64:
12285255f48cSRichard Henderson case INDEX_op_clz_i32:
12295255f48cSRichard Henderson case INDEX_op_clz_i64:
12305255f48cSRichard Henderson case INDEX_op_ctz_i32:
12315255f48cSRichard Henderson case INDEX_op_ctz_i64:
123265089889SRichard Henderson tci_args_rrr(insn, &r0, &r1, &r2);
123359964b4fSRichard Henderson info->fprintf_func(info->stream, "%-12s %s, %s, %s",
123459964b4fSRichard Henderson op_name, str_r(r0), str_r(r1), str_r(r2));
123559964b4fSRichard Henderson break;
123659964b4fSRichard Henderson
123759964b4fSRichard Henderson case INDEX_op_deposit_i32:
123859964b4fSRichard Henderson case INDEX_op_deposit_i64:
123965089889SRichard Henderson tci_args_rrrbb(insn, &r0, &r1, &r2, &pos, &len);
124059964b4fSRichard Henderson info->fprintf_func(info->stream, "%-12s %s, %s, %s, %d, %d",
124159964b4fSRichard Henderson op_name, str_r(r0), str_r(r1), str_r(r2), pos, len);
124259964b4fSRichard Henderson break;
124359964b4fSRichard Henderson
12440f10d7c5SRichard Henderson case INDEX_op_extract_i32:
12450f10d7c5SRichard Henderson case INDEX_op_extract_i64:
12460f10d7c5SRichard Henderson case INDEX_op_sextract_i32:
12470f10d7c5SRichard Henderson case INDEX_op_sextract_i64:
12480f10d7c5SRichard Henderson tci_args_rrbb(insn, &r0, &r1, &pos, &len);
12490f10d7c5SRichard Henderson info->fprintf_func(info->stream, "%-12s %s,%s,%d,%d",
12500f10d7c5SRichard Henderson op_name, str_r(r0), str_r(r1), pos, len);
12510f10d7c5SRichard Henderson break;
12520f10d7c5SRichard Henderson
1253df093c19SRichard Henderson case INDEX_op_movcond_i32:
1254df093c19SRichard Henderson case INDEX_op_movcond_i64:
125559964b4fSRichard Henderson case INDEX_op_setcond2_i32:
125665089889SRichard Henderson tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &c);
125759964b4fSRichard Henderson info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s, %s, %s",
125859964b4fSRichard Henderson op_name, str_r(r0), str_r(r1), str_r(r2),
125959964b4fSRichard Henderson str_r(r3), str_r(r4), str_c(c));
126059964b4fSRichard Henderson break;
126159964b4fSRichard Henderson
126259964b4fSRichard Henderson case INDEX_op_mulu2_i32:
1263f6db0d8dSRichard Henderson case INDEX_op_mulu2_i64:
1264f6db0d8dSRichard Henderson case INDEX_op_muls2_i32:
1265f6db0d8dSRichard Henderson case INDEX_op_muls2_i64:
126665089889SRichard Henderson tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
126759964b4fSRichard Henderson info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s",
126859964b4fSRichard Henderson op_name, str_r(r0), str_r(r1),
126959964b4fSRichard Henderson str_r(r2), str_r(r3));
127059964b4fSRichard Henderson break;
127159964b4fSRichard Henderson
127259964b4fSRichard Henderson case INDEX_op_add2_i32:
127308096b1aSRichard Henderson case INDEX_op_add2_i64:
127459964b4fSRichard Henderson case INDEX_op_sub2_i32:
127508096b1aSRichard Henderson case INDEX_op_sub2_i64:
127665089889SRichard Henderson tci_args_rrrrrr(insn, &r0, &r1, &r2, &r3, &r4, &r5);
127759964b4fSRichard Henderson info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s, %s, %s",
127859964b4fSRichard Henderson op_name, str_r(r0), str_r(r1), str_r(r2),
127959964b4fSRichard Henderson str_r(r3), str_r(r4), str_r(r5));
128059964b4fSRichard Henderson break;
128159964b4fSRichard Henderson
1282fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i32:
1283fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i32:
1284fecccfccSRichard Henderson len = 1 + 1;
128559964b4fSRichard Henderson goto do_qemu_ldst;
1286fecccfccSRichard Henderson case INDEX_op_qemu_ld_a32_i64:
1287fecccfccSRichard Henderson case INDEX_op_qemu_st_a32_i64:
1288fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i32:
1289fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i32:
1290fecccfccSRichard Henderson len = 1 + DIV_ROUND_UP(64, TCG_TARGET_REG_BITS);
1291fecccfccSRichard Henderson goto do_qemu_ldst;
1292fecccfccSRichard Henderson case INDEX_op_qemu_ld_a64_i64:
1293fecccfccSRichard Henderson case INDEX_op_qemu_st_a64_i64:
1294fecccfccSRichard Henderson len = 2 * DIV_ROUND_UP(64, TCG_TARGET_REG_BITS);
1295fecccfccSRichard Henderson goto do_qemu_ldst;
129659964b4fSRichard Henderson do_qemu_ldst:
129759964b4fSRichard Henderson switch (len) {
129859964b4fSRichard Henderson case 2:
129965089889SRichard Henderson tci_args_rrm(insn, &r0, &r1, &oi);
130059964b4fSRichard Henderson info->fprintf_func(info->stream, "%-12s %s, %s, %x",
130159964b4fSRichard Henderson op_name, str_r(r0), str_r(r1), oi);
130259964b4fSRichard Henderson break;
130359964b4fSRichard Henderson case 3:
1304ab64da79SRichard Henderson tci_args_rrrr(insn, &r0, &r1, &r2, &r3);
1305ab64da79SRichard Henderson info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s",
1306ab64da79SRichard Henderson op_name, str_r(r0), str_r(r1),
1307ab64da79SRichard Henderson str_r(r2), str_r(r3));
130859964b4fSRichard Henderson break;
130959964b4fSRichard Henderson case 4:
131065089889SRichard Henderson tci_args_rrrrr(insn, &r0, &r1, &r2, &r3, &r4);
131165089889SRichard Henderson info->fprintf_func(info->stream, "%-12s %s, %s, %s, %s, %s",
131259964b4fSRichard Henderson op_name, str_r(r0), str_r(r1),
131365089889SRichard Henderson str_r(r2), str_r(r3), str_r(r4));
131459964b4fSRichard Henderson break;
131559964b4fSRichard Henderson default:
131659964b4fSRichard Henderson g_assert_not_reached();
131759964b4fSRichard Henderson }
131859964b4fSRichard Henderson break;
131959964b4fSRichard Henderson
132065089889SRichard Henderson case 0:
132165089889SRichard Henderson /* tcg_out_nop_fill uses zeros */
132265089889SRichard Henderson if (insn == 0) {
132365089889SRichard Henderson info->fprintf_func(info->stream, "align");
132465089889SRichard Henderson break;
132565089889SRichard Henderson }
132665089889SRichard Henderson /* fall through */
132765089889SRichard Henderson
132859964b4fSRichard Henderson default:
132959964b4fSRichard Henderson info->fprintf_func(info->stream, "illegal opcode %d", op);
133059964b4fSRichard Henderson break;
133159964b4fSRichard Henderson }
133259964b4fSRichard Henderson
133365089889SRichard Henderson return sizeof(insn);
133459964b4fSRichard Henderson }
1335