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