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
trans_BBIT(DisasContext * ctx,arg_BBIT * a)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
trans_BADDU(DisasContext * ctx,arg_BADDU * a)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
trans_DMUL(DisasContext * ctx,arg_DMUL * a)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
trans_EXTS(DisasContext * ctx,arg_EXTS * a)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
trans_CINS(DisasContext * ctx,arg_CINS * a)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
trans_POP(DisasContext * ctx,arg_POP * a)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
trans_SEQNE(DisasContext * ctx,arg_SEQNE * a)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
trans_SEQNEI(DisasContext * ctx,arg_SEQNEI * a)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