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