xref: /qemu/target/mips/tcg/octeon_translate.c (revision 40efe733e10cc00e4fb4f9f5790a28e744e63c62)
172d680e4SPavel Dovgalyuk /*
272d680e4SPavel Dovgalyuk  * Octeon-specific instructions translation routines
372d680e4SPavel Dovgalyuk  *
472d680e4SPavel Dovgalyuk  *  Copyright (c) 2022 Pavel Dovgalyuk
572d680e4SPavel Dovgalyuk  *
672d680e4SPavel Dovgalyuk  * SPDX-License-Identifier: GPL-2.0-or-later
772d680e4SPavel Dovgalyuk  */
872d680e4SPavel Dovgalyuk 
972d680e4SPavel Dovgalyuk #include "qemu/osdep.h"
1072d680e4SPavel Dovgalyuk #include "translate.h"
118cab4157SRichard Henderson #include "tcg/tcg-op-gvec.h"
1272d680e4SPavel Dovgalyuk 
1372d680e4SPavel Dovgalyuk /* Include the auto-generated decoder.  */
1472d680e4SPavel Dovgalyuk #include "decode-octeon.c.inc"
155e806fb0SPavel Dovgalyuk 
trans_BBIT(DisasContext * ctx,arg_BBIT * a)165e806fb0SPavel Dovgalyuk static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a)
175e806fb0SPavel Dovgalyuk {
185e806fb0SPavel Dovgalyuk     TCGv p;
195e806fb0SPavel Dovgalyuk 
205e806fb0SPavel Dovgalyuk     if (ctx->hflags & MIPS_HFLAG_BMASK) {
21*a630055dSRichard Henderson         LOG_DISAS("Branch in delay / forbidden slot at PC 0x%" VADDR_PRIx "\n",
22*a630055dSRichard Henderson                   ctx->base.pc_next);
235e806fb0SPavel Dovgalyuk         generate_exception_end(ctx, EXCP_RI);
245e806fb0SPavel Dovgalyuk         return true;
255e806fb0SPavel Dovgalyuk     }
265e806fb0SPavel Dovgalyuk 
275e806fb0SPavel Dovgalyuk     /* Load needed operands */
285e806fb0SPavel Dovgalyuk     TCGv t0 = tcg_temp_new();
295e806fb0SPavel Dovgalyuk     gen_load_gpr(t0, a->rs);
305e806fb0SPavel Dovgalyuk 
315e806fb0SPavel Dovgalyuk     p = tcg_constant_tl(1ULL << a->p);
325e806fb0SPavel Dovgalyuk     if (a->set) {
335e806fb0SPavel Dovgalyuk         tcg_gen_and_tl(bcond, p, t0);
345e806fb0SPavel Dovgalyuk     } else {
355e806fb0SPavel Dovgalyuk         tcg_gen_andc_tl(bcond, p, t0);
365e806fb0SPavel Dovgalyuk     }
375e806fb0SPavel Dovgalyuk 
385e806fb0SPavel Dovgalyuk     ctx->hflags |= MIPS_HFLAG_BC;
395e806fb0SPavel Dovgalyuk     ctx->btarget = ctx->base.pc_next + 4 + a->offset * 4;
405e806fb0SPavel Dovgalyuk     ctx->hflags |= MIPS_HFLAG_BDS32;
415e806fb0SPavel Dovgalyuk     return true;
425e806fb0SPavel Dovgalyuk }
43dadd071aSPavel Dovgalyuk 
trans_BADDU(DisasContext * ctx,arg_BADDU * a)44dadd071aSPavel Dovgalyuk static bool trans_BADDU(DisasContext *ctx, arg_BADDU *a)
45dadd071aSPavel Dovgalyuk {
46dadd071aSPavel Dovgalyuk     TCGv t0, t1;
47dadd071aSPavel Dovgalyuk 
48dadd071aSPavel Dovgalyuk     if (a->rt == 0) {
49dadd071aSPavel Dovgalyuk         /* nop */
50dadd071aSPavel Dovgalyuk         return true;
51dadd071aSPavel Dovgalyuk     }
52dadd071aSPavel Dovgalyuk 
53dadd071aSPavel Dovgalyuk     t0 = tcg_temp_new();
54dadd071aSPavel Dovgalyuk     t1 = tcg_temp_new();
55dadd071aSPavel Dovgalyuk     gen_load_gpr(t0, a->rs);
56dadd071aSPavel Dovgalyuk     gen_load_gpr(t1, a->rt);
57dadd071aSPavel Dovgalyuk 
58dadd071aSPavel Dovgalyuk     tcg_gen_add_tl(t0, t0, t1);
59dadd071aSPavel Dovgalyuk     tcg_gen_andi_i64(cpu_gpr[a->rd], t0, 0xff);
60dadd071aSPavel Dovgalyuk     return true;
61dadd071aSPavel Dovgalyuk }
62dadd071aSPavel Dovgalyuk 
trans_DMUL(DisasContext * ctx,arg_DMUL * a)63dadd071aSPavel Dovgalyuk static bool trans_DMUL(DisasContext *ctx, arg_DMUL *a)
64dadd071aSPavel Dovgalyuk {
65dadd071aSPavel Dovgalyuk     TCGv t0, t1;
66dadd071aSPavel Dovgalyuk 
67dadd071aSPavel Dovgalyuk     if (a->rt == 0) {
68dadd071aSPavel Dovgalyuk         /* nop */
69dadd071aSPavel Dovgalyuk         return true;
70dadd071aSPavel Dovgalyuk     }
71dadd071aSPavel Dovgalyuk 
72dadd071aSPavel Dovgalyuk     t0 = tcg_temp_new();
73dadd071aSPavel Dovgalyuk     t1 = tcg_temp_new();
74dadd071aSPavel Dovgalyuk     gen_load_gpr(t0, a->rs);
75dadd071aSPavel Dovgalyuk     gen_load_gpr(t1, a->rt);
76dadd071aSPavel Dovgalyuk 
77dadd071aSPavel Dovgalyuk     tcg_gen_mul_i64(cpu_gpr[a->rd], t0, t1);
78dadd071aSPavel Dovgalyuk     return true;
79dadd071aSPavel Dovgalyuk }
80dadd071aSPavel Dovgalyuk 
trans_EXTS(DisasContext * ctx,arg_EXTS * a)81dadd071aSPavel Dovgalyuk static bool trans_EXTS(DisasContext *ctx, arg_EXTS *a)
82dadd071aSPavel Dovgalyuk {
83dadd071aSPavel Dovgalyuk     TCGv t0;
84dadd071aSPavel Dovgalyuk 
85dadd071aSPavel Dovgalyuk     if (a->rt == 0) {
86dadd071aSPavel Dovgalyuk         /* nop */
87dadd071aSPavel Dovgalyuk         return true;
88dadd071aSPavel Dovgalyuk     }
89dadd071aSPavel Dovgalyuk 
90dadd071aSPavel Dovgalyuk     t0 = tcg_temp_new();
91dadd071aSPavel Dovgalyuk     gen_load_gpr(t0, a->rs);
92dadd071aSPavel Dovgalyuk     tcg_gen_sextract_tl(t0, t0, a->p, a->lenm1 + 1);
93dadd071aSPavel Dovgalyuk     gen_store_gpr(t0, a->rt);
94dadd071aSPavel Dovgalyuk     return true;
95dadd071aSPavel Dovgalyuk }
96dadd071aSPavel Dovgalyuk 
trans_CINS(DisasContext * ctx,arg_CINS * a)97dadd071aSPavel Dovgalyuk static bool trans_CINS(DisasContext *ctx, arg_CINS *a)
98dadd071aSPavel Dovgalyuk {
99dadd071aSPavel Dovgalyuk     TCGv t0;
100dadd071aSPavel Dovgalyuk 
101dadd071aSPavel Dovgalyuk     if (a->rt == 0) {
102dadd071aSPavel Dovgalyuk         /* nop */
103dadd071aSPavel Dovgalyuk         return true;
104dadd071aSPavel Dovgalyuk     }
105dadd071aSPavel Dovgalyuk 
106dadd071aSPavel Dovgalyuk     t0 = tcg_temp_new();
107dadd071aSPavel Dovgalyuk     gen_load_gpr(t0, a->rs);
108dadd071aSPavel Dovgalyuk     tcg_gen_deposit_z_tl(t0, t0, a->p, a->lenm1 + 1);
109dadd071aSPavel Dovgalyuk     gen_store_gpr(t0, a->rt);
110dadd071aSPavel Dovgalyuk     return true;
111dadd071aSPavel Dovgalyuk }
112dadd071aSPavel Dovgalyuk 
trans_POP(DisasContext * ctx,arg_POP * a)113dadd071aSPavel Dovgalyuk static bool trans_POP(DisasContext *ctx, arg_POP *a)
114dadd071aSPavel Dovgalyuk {
115dadd071aSPavel Dovgalyuk     TCGv t0;
116dadd071aSPavel Dovgalyuk 
117dadd071aSPavel Dovgalyuk     if (a->rd == 0) {
118dadd071aSPavel Dovgalyuk         /* nop */
119dadd071aSPavel Dovgalyuk         return true;
120dadd071aSPavel Dovgalyuk     }
121dadd071aSPavel Dovgalyuk 
122dadd071aSPavel Dovgalyuk     t0 = tcg_temp_new();
123dadd071aSPavel Dovgalyuk     gen_load_gpr(t0, a->rs);
124dadd071aSPavel Dovgalyuk     if (!a->dw) {
125dadd071aSPavel Dovgalyuk         tcg_gen_andi_i64(t0, t0, 0xffffffff);
126dadd071aSPavel Dovgalyuk     }
127dadd071aSPavel Dovgalyuk     tcg_gen_ctpop_tl(t0, t0);
128dadd071aSPavel Dovgalyuk     gen_store_gpr(t0, a->rd);
129dadd071aSPavel Dovgalyuk     return true;
130dadd071aSPavel Dovgalyuk }
131dadd071aSPavel Dovgalyuk 
trans_SEQNE(DisasContext * ctx,arg_SEQNE * a)132dadd071aSPavel Dovgalyuk static bool trans_SEQNE(DisasContext *ctx, arg_SEQNE *a)
133dadd071aSPavel Dovgalyuk {
134dadd071aSPavel Dovgalyuk     TCGv t0, t1;
135dadd071aSPavel Dovgalyuk 
136dadd071aSPavel Dovgalyuk     if (a->rd == 0) {
137dadd071aSPavel Dovgalyuk         /* nop */
138dadd071aSPavel Dovgalyuk         return true;
139dadd071aSPavel Dovgalyuk     }
140dadd071aSPavel Dovgalyuk 
141dadd071aSPavel Dovgalyuk     t0 = tcg_temp_new();
142dadd071aSPavel Dovgalyuk     t1 = tcg_temp_new();
143dadd071aSPavel Dovgalyuk 
144dadd071aSPavel Dovgalyuk     gen_load_gpr(t0, a->rs);
145dadd071aSPavel Dovgalyuk     gen_load_gpr(t1, a->rt);
146dadd071aSPavel Dovgalyuk 
147dadd071aSPavel Dovgalyuk     if (a->ne) {
148dadd071aSPavel Dovgalyuk         tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr[a->rd], t1, t0);
149dadd071aSPavel Dovgalyuk     } else {
150dadd071aSPavel Dovgalyuk         tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr[a->rd], t1, t0);
151dadd071aSPavel Dovgalyuk     }
152dadd071aSPavel Dovgalyuk     return true;
153dadd071aSPavel Dovgalyuk }
154dadd071aSPavel Dovgalyuk 
trans_SEQNEI(DisasContext * ctx,arg_SEQNEI * a)155dadd071aSPavel Dovgalyuk static bool trans_SEQNEI(DisasContext *ctx, arg_SEQNEI *a)
156dadd071aSPavel Dovgalyuk {
157dadd071aSPavel Dovgalyuk     TCGv t0;
158dadd071aSPavel Dovgalyuk 
159dadd071aSPavel Dovgalyuk     if (a->rt == 0) {
160dadd071aSPavel Dovgalyuk         /* nop */
161dadd071aSPavel Dovgalyuk         return true;
162dadd071aSPavel Dovgalyuk     }
163dadd071aSPavel Dovgalyuk 
164dadd071aSPavel Dovgalyuk     t0 = tcg_temp_new();
165dadd071aSPavel Dovgalyuk 
166dadd071aSPavel Dovgalyuk     gen_load_gpr(t0, a->rs);
167dadd071aSPavel Dovgalyuk 
168dadd071aSPavel Dovgalyuk     /* Sign-extend to 64 bit value */
169dadd071aSPavel Dovgalyuk     target_ulong imm = a->imm;
170dadd071aSPavel Dovgalyuk     if (a->ne) {
171dadd071aSPavel Dovgalyuk         tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr[a->rt], t0, imm);
172dadd071aSPavel Dovgalyuk     } else {
173dadd071aSPavel Dovgalyuk         tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr[a->rt], t0, imm);
174dadd071aSPavel Dovgalyuk     }
175dadd071aSPavel Dovgalyuk     return true;
176dadd071aSPavel Dovgalyuk }
177