1 /*
2  * Octeon-specific instructions translation routines
3  *
4  *  Copyright (c) 2022 Pavel Dovgalyuk
5  *
6  * SPDX-License-Identifier: GPL-2.0-or-later
7  */
8 
9 #include "qemu/osdep.h"
10 #include "tcg/tcg-op.h"
11 #include "tcg/tcg-op-gvec.h"
12 #include "exec/helper-gen.h"
13 #include "translate.h"
14 
15 /* Include the auto-generated decoder.  */
16 #include "decode-octeon.c.inc"
17 
18 static bool trans_BBIT(DisasContext *ctx, arg_BBIT *a)
19 {
20     TCGv p;
21 
22     if (ctx->hflags & MIPS_HFLAG_BMASK) {
23         LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
24                   TARGET_FMT_lx "\n", ctx->base.pc_next);
25         generate_exception_end(ctx, EXCP_RI);
26         return true;
27     }
28 
29     /* Load needed operands */
30     TCGv t0 = tcg_temp_new();
31     gen_load_gpr(t0, a->rs);
32 
33     p = tcg_constant_tl(1ULL << a->p);
34     if (a->set) {
35         tcg_gen_and_tl(bcond, p, t0);
36     } else {
37         tcg_gen_andc_tl(bcond, p, t0);
38     }
39 
40     ctx->hflags |= MIPS_HFLAG_BC;
41     ctx->btarget = ctx->base.pc_next + 4 + a->offset * 4;
42     ctx->hflags |= MIPS_HFLAG_BDS32;
43     return true;
44 }
45 
46 static bool trans_BADDU(DisasContext *ctx, arg_BADDU *a)
47 {
48     TCGv t0, t1;
49 
50     if (a->rt == 0) {
51         /* nop */
52         return true;
53     }
54 
55     t0 = tcg_temp_new();
56     t1 = tcg_temp_new();
57     gen_load_gpr(t0, a->rs);
58     gen_load_gpr(t1, a->rt);
59 
60     tcg_gen_add_tl(t0, t0, t1);
61     tcg_gen_andi_i64(cpu_gpr[a->rd], t0, 0xff);
62     return true;
63 }
64 
65 static bool trans_DMUL(DisasContext *ctx, arg_DMUL *a)
66 {
67     TCGv t0, t1;
68 
69     if (a->rt == 0) {
70         /* nop */
71         return true;
72     }
73 
74     t0 = tcg_temp_new();
75     t1 = tcg_temp_new();
76     gen_load_gpr(t0, a->rs);
77     gen_load_gpr(t1, a->rt);
78 
79     tcg_gen_mul_i64(cpu_gpr[a->rd], t0, t1);
80     return true;
81 }
82 
83 static bool trans_EXTS(DisasContext *ctx, arg_EXTS *a)
84 {
85     TCGv t0;
86 
87     if (a->rt == 0) {
88         /* nop */
89         return true;
90     }
91 
92     t0 = tcg_temp_new();
93     gen_load_gpr(t0, a->rs);
94     tcg_gen_sextract_tl(t0, t0, a->p, a->lenm1 + 1);
95     gen_store_gpr(t0, a->rt);
96     return true;
97 }
98 
99 static bool trans_CINS(DisasContext *ctx, arg_CINS *a)
100 {
101     TCGv t0;
102 
103     if (a->rt == 0) {
104         /* nop */
105         return true;
106     }
107 
108     t0 = tcg_temp_new();
109     gen_load_gpr(t0, a->rs);
110     tcg_gen_deposit_z_tl(t0, t0, a->p, a->lenm1 + 1);
111     gen_store_gpr(t0, a->rt);
112     return true;
113 }
114 
115 static bool trans_POP(DisasContext *ctx, arg_POP *a)
116 {
117     TCGv t0;
118 
119     if (a->rd == 0) {
120         /* nop */
121         return true;
122     }
123 
124     t0 = tcg_temp_new();
125     gen_load_gpr(t0, a->rs);
126     if (!a->dw) {
127         tcg_gen_andi_i64(t0, t0, 0xffffffff);
128     }
129     tcg_gen_ctpop_tl(t0, t0);
130     gen_store_gpr(t0, a->rd);
131     return true;
132 }
133 
134 static bool trans_SEQNE(DisasContext *ctx, arg_SEQNE *a)
135 {
136     TCGv t0, t1;
137 
138     if (a->rd == 0) {
139         /* nop */
140         return true;
141     }
142 
143     t0 = tcg_temp_new();
144     t1 = tcg_temp_new();
145 
146     gen_load_gpr(t0, a->rs);
147     gen_load_gpr(t1, a->rt);
148 
149     if (a->ne) {
150         tcg_gen_setcond_tl(TCG_COND_NE, cpu_gpr[a->rd], t1, t0);
151     } else {
152         tcg_gen_setcond_tl(TCG_COND_EQ, cpu_gpr[a->rd], t1, t0);
153     }
154     return true;
155 }
156 
157 static bool trans_SEQNEI(DisasContext *ctx, arg_SEQNEI *a)
158 {
159     TCGv t0;
160 
161     if (a->rt == 0) {
162         /* nop */
163         return true;
164     }
165 
166     t0 = tcg_temp_new();
167 
168     gen_load_gpr(t0, a->rs);
169 
170     /* Sign-extend to 64 bit value */
171     target_ulong imm = a->imm;
172     if (a->ne) {
173         tcg_gen_setcondi_tl(TCG_COND_NE, cpu_gpr[a->rt], t0, imm);
174     } else {
175         tcg_gen_setcondi_tl(TCG_COND_EQ, cpu_gpr[a->rt], t0, imm);
176     }
177     return true;
178 }
179