hw/ppc/ppc.c: Tidy over-long lines
[qemu/kevin.git] / target / ppc / translate / fixedpoint-impl.c.inc
blob4ce02fd3a4793f5c32f11eec774cfecbb516d6b4
1 /*
2  * Power ISA decode for Fixed-Point Facility instructions
3  *
4  * Copyright (c) 2021 Instituto de Pesquisas Eldorado (eldorado.org.br)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
21  * Fixed-Point Load/Store Instructions
22  */
24 static bool do_ldst(DisasContext *ctx, int rt, int ra, TCGv displ, bool update,
25                     bool store, MemOp mop)
27     TCGv ea;
29     if (update && (ra == 0 || (!store && ra == rt))) {
30         gen_invalid(ctx);
31         return true;
32     }
33     gen_set_access_type(ctx, ACCESS_INT);
35     ea = do_ea_calc(ctx, ra, displ);
36     mop ^= ctx->default_tcg_memop_mask;
37     if (store) {
38         tcg_gen_qemu_st_tl(cpu_gpr[rt], ea, ctx->mem_idx, mop);
39     } else {
40         tcg_gen_qemu_ld_tl(cpu_gpr[rt], ea, ctx->mem_idx, mop);
41     }
42     if (update) {
43         tcg_gen_mov_tl(cpu_gpr[ra], ea);
44     }
45     return true;
48 static bool do_ldst_D(DisasContext *ctx, arg_D *a, bool update, bool store,
49                       MemOp mop)
51     return do_ldst(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update, store, mop);
54 static bool do_ldst_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool update,
55                           bool store, MemOp mop)
57     arg_D d;
58     if (!resolve_PLS_D(ctx, &d, a)) {
59         return true;
60     }
61     return do_ldst_D(ctx, &d, update, store, mop);
64 static bool do_ldst_X(DisasContext *ctx, arg_X *a, bool update,
65                       bool store, MemOp mop)
67     return do_ldst(ctx, a->rt, a->ra, cpu_gpr[a->rb], update, store, mop);
70 static bool do_ldst_quad(DisasContext *ctx, arg_D *a, bool store, bool prefixed)
72 #if defined(TARGET_PPC64)
73     TCGv ea;
74     TCGv_i64 low_addr_gpr, high_addr_gpr;
75     TCGv_i128 t16;
77     REQUIRE_INSNS_FLAGS(ctx, 64BX);
79     if (!prefixed && !(ctx->insns_flags2 & PPC2_LSQ_ISA207)) {
80         /* lq and stq were privileged prior to V. 2.07 */
81         REQUIRE_SV(ctx);
83         if (ctx->le_mode) {
84             gen_align_no_le(ctx);
85             return true;
86         }
87     }
89     if (!store && unlikely(a->ra == a->rt)) {
90         gen_invalid(ctx);
91         return true;
92     }
94     gen_set_access_type(ctx, ACCESS_INT);
95     ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->si));
97     if (prefixed || !ctx->le_mode) {
98         low_addr_gpr = cpu_gpr[a->rt];
99         high_addr_gpr = cpu_gpr[a->rt + 1];
100     } else {
101         low_addr_gpr = cpu_gpr[a->rt + 1];
102         high_addr_gpr = cpu_gpr[a->rt];
103     }
104     t16 = tcg_temp_new_i128();
106     if (store) {
107         tcg_gen_concat_i64_i128(t16, low_addr_gpr, high_addr_gpr);
108         tcg_gen_qemu_st_i128(t16, ea, ctx->mem_idx, DEF_MEMOP(MO_128));
109     } else {
110         tcg_gen_qemu_ld_i128(t16, ea, ctx->mem_idx, DEF_MEMOP(MO_128));
111         tcg_gen_extr_i128_i64(low_addr_gpr, high_addr_gpr, t16);
112     }
113 #else
114     qemu_build_not_reached();
115 #endif
117     return true;
120 static bool do_ldst_quad_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store)
122     arg_D d;
123     if (!resolve_PLS_D(ctx, &d, a)) {
124         return true;
125     }
127     return do_ldst_quad(ctx, &d, store, true);
130 /* Load Byte and Zero */
131 TRANS(LBZ, do_ldst_D, false, false, MO_UB)
132 TRANS(LBZX, do_ldst_X, false, false, MO_UB)
133 TRANS(LBZU, do_ldst_D, true, false, MO_UB)
134 TRANS(LBZUX, do_ldst_X, true, false, MO_UB)
135 TRANS(PLBZ, do_ldst_PLS_D, false, false, MO_UB)
137 /* Load Halfword and Zero */
138 TRANS(LHZ, do_ldst_D, false, false, MO_UW)
139 TRANS(LHZX, do_ldst_X, false, false, MO_UW)
140 TRANS(LHZU, do_ldst_D, true, false, MO_UW)
141 TRANS(LHZUX, do_ldst_X, true, false, MO_UW)
142 TRANS(PLHZ, do_ldst_PLS_D, false, false, MO_UW)
144 /* Load Halfword Algebraic */
145 TRANS(LHA, do_ldst_D, false, false, MO_SW)
146 TRANS(LHAX, do_ldst_X, false, false, MO_SW)
147 TRANS(LHAU, do_ldst_D, true, false, MO_SW)
148 TRANS(LHAXU, do_ldst_X, true, false, MO_SW)
149 TRANS(PLHA, do_ldst_PLS_D, false, false, MO_SW)
151 /* Load Word and Zero */
152 TRANS(LWZ, do_ldst_D, false, false, MO_UL)
153 TRANS(LWZX, do_ldst_X, false, false, MO_UL)
154 TRANS(LWZU, do_ldst_D, true, false, MO_UL)
155 TRANS(LWZUX, do_ldst_X, true, false, MO_UL)
156 TRANS(PLWZ, do_ldst_PLS_D, false, false, MO_UL)
158 /* Load Word Algebraic */
159 TRANS64(LWA, do_ldst_D, false, false, MO_SL)
160 TRANS64(LWAX, do_ldst_X, false, false, MO_SL)
161 TRANS64(LWAUX, do_ldst_X, true, false, MO_SL)
162 TRANS64(PLWA, do_ldst_PLS_D, false, false, MO_SL)
164 /* Load Doubleword */
165 TRANS64(LD, do_ldst_D, false, false, MO_UQ)
166 TRANS64(LDX, do_ldst_X, false, false, MO_UQ)
167 TRANS64(LDU, do_ldst_D, true, false, MO_UQ)
168 TRANS64(LDUX, do_ldst_X, true, false, MO_UQ)
169 TRANS64(PLD, do_ldst_PLS_D, false, false, MO_UQ)
171 /* Load Quadword */
172 TRANS64(LQ, do_ldst_quad, false, false);
173 TRANS64(PLQ, do_ldst_quad_PLS_D, false);
175 /* Store Byte */
176 TRANS(STB, do_ldst_D, false, true, MO_UB)
177 TRANS(STBX, do_ldst_X, false, true, MO_UB)
178 TRANS(STBU, do_ldst_D, true, true, MO_UB)
179 TRANS(STBUX, do_ldst_X, true, true, MO_UB)
180 TRANS(PSTB, do_ldst_PLS_D, false, true, MO_UB)
182 /* Store Halfword */
183 TRANS(STH, do_ldst_D, false, true, MO_UW)
184 TRANS(STHX, do_ldst_X, false, true, MO_UW)
185 TRANS(STHU, do_ldst_D, true, true, MO_UW)
186 TRANS(STHUX, do_ldst_X, true, true, MO_UW)
187 TRANS(PSTH, do_ldst_PLS_D, false, true, MO_UW)
189 /* Store Word */
190 TRANS(STW, do_ldst_D, false, true, MO_UL)
191 TRANS(STWX, do_ldst_X, false, true, MO_UL)
192 TRANS(STWU, do_ldst_D, true, true, MO_UL)
193 TRANS(STWUX, do_ldst_X, true, true, MO_UL)
194 TRANS(PSTW, do_ldst_PLS_D, false, true, MO_UL)
196 /* Store Doubleword */
197 TRANS64(STD, do_ldst_D, false, true, MO_UQ)
198 TRANS64(STDX, do_ldst_X, false, true, MO_UQ)
199 TRANS64(STDU, do_ldst_D, true, true, MO_UQ)
200 TRANS64(STDUX, do_ldst_X, true, true, MO_UQ)
201 TRANS64(PSTD, do_ldst_PLS_D, false, true, MO_UQ)
203 /* Store Quadword */
204 TRANS64(STQ, do_ldst_quad, true, false);
205 TRANS64(PSTQ, do_ldst_quad_PLS_D, true);
208  * Fixed-Point Compare Instructions
209  */
211 static bool do_cmp_X(DisasContext *ctx, arg_X_bfl *a, bool s)
213     if ((ctx->insns_flags & PPC_64B) == 0) {
214         /*
215          * For 32-bit implementations, The Programming Environments Manual says
216          * that "the L field must be cleared, otherwise the instruction form is
217          * invalid." It seems, however, that most 32-bit CPUs ignore invalid
218          * forms (e.g., section "Instruction Formats" of the 405 and 440
219          * manuals, "Integer Compare Instructions" of the 601 manual), with the
220          * notable exception of the e500 and e500mc, where L=1 was reported to
221          * cause an exception.
222          */
223         if (a->l) {
224             if ((ctx->insns_flags2 & PPC2_BOOKE206)) {
225                 /*
226                  * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc),
227                  * generate an illegal instruction exception.
228                  */
229                 return false;
230             } else {
231                 qemu_log_mask(LOG_GUEST_ERROR,
232                         "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n",
233                         s ? "" : "L", ctx->cia);
234             }
235         }
236         gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
237         return true;
238     }
240     /* For 64-bit implementations, deal with bit L accordingly. */
241     if (a->l) {
242         gen_op_cmp(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
243     } else {
244         gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
245     }
246     return true;
249 static bool do_cmp_D(DisasContext *ctx, arg_D_bf *a, bool s)
251     if ((ctx->insns_flags & PPC_64B) == 0) {
252         /*
253          * For 32-bit implementations, The Programming Environments Manual says
254          * that "the L field must be cleared, otherwise the instruction form is
255          * invalid." It seems, however, that most 32-bit CPUs ignore invalid
256          * forms (e.g., section "Instruction Formats" of the 405 and 440
257          * manuals, "Integer Compare Instructions" of the 601 manual), with the
258          * notable exception of the e500 and e500mc, where L=1 was reported to
259          * cause an exception.
260          */
261         if (a->l) {
262             if ((ctx->insns_flags2 & PPC2_BOOKE206)) {
263                 /*
264                  * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc),
265                  * generate an illegal instruction exception.
266                  */
267                 return false;
268             } else {
269                 qemu_log_mask(LOG_GUEST_ERROR,
270                         "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n",
271                         s ? "I" : "LI", ctx->cia);
272             }
273         }
274         gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
275         return true;
276     }
278     /* For 64-bit implementations, deal with bit L accordingly. */
279     if (a->l) {
280         gen_op_cmp(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
281     } else {
282         gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
283     }
284     return true;
287 TRANS(CMP, do_cmp_X, true);
288 TRANS(CMPL, do_cmp_X, false);
289 TRANS(CMPI, do_cmp_D, true);
290 TRANS(CMPLI, do_cmp_D, false);
293  * Fixed-Point Arithmetic Instructions
294  */
296 static bool trans_ADDI(DisasContext *ctx, arg_D *a)
298     if (a->ra) {
299         tcg_gen_addi_tl(cpu_gpr[a->rt], cpu_gpr[a->ra], a->si);
300     } else {
301         tcg_gen_movi_tl(cpu_gpr[a->rt], a->si);
302     }
303     return true;
306 static bool trans_PADDI(DisasContext *ctx, arg_PLS_D *a)
308     arg_D d;
309     if (!resolve_PLS_D(ctx, &d, a)) {
310         return true;
311     }
312     return trans_ADDI(ctx, &d);
315 static bool trans_ADDIS(DisasContext *ctx, arg_D *a)
317     a->si <<= 16;
318     return trans_ADDI(ctx, a);
321 static bool trans_ADDPCIS(DisasContext *ctx, arg_DX *a)
323     REQUIRE_INSNS_FLAGS2(ctx, ISA300);
324     tcg_gen_movi_tl(cpu_gpr[a->rt], ctx->base.pc_next + (a->d << 16));
325     return true;
328 static bool trans_INVALID(DisasContext *ctx, arg_INVALID *a)
330     gen_invalid(ctx);
331     return true;
334 static bool trans_PNOP(DisasContext *ctx, arg_PNOP *a)
336     return true;
339 static bool do_set_bool_cond(DisasContext *ctx, arg_X_bi *a, bool neg, bool rev)
341     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
342     uint32_t mask = 0x08 >> (a->bi & 0x03);
343     TCGCond cond = rev ? TCG_COND_EQ : TCG_COND_NE;
344     TCGv temp = tcg_temp_new();
345     TCGv zero = tcg_constant_tl(0);
347     tcg_gen_extu_i32_tl(temp, cpu_crf[a->bi >> 2]);
348     tcg_gen_andi_tl(temp, temp, mask);
349     if (neg) {
350         tcg_gen_negsetcond_tl(cond, cpu_gpr[a->rt], temp, zero);
351     } else {
352         tcg_gen_setcond_tl(cond, cpu_gpr[a->rt], temp, zero);
353     }
354     return true;
357 TRANS(SETBC, do_set_bool_cond, false, false)
358 TRANS(SETBCR, do_set_bool_cond, false, true)
359 TRANS(SETNBC, do_set_bool_cond, true, false)
360 TRANS(SETNBCR, do_set_bool_cond, true, true)
362 static bool trans_CFUGED(DisasContext *ctx, arg_X *a)
364     REQUIRE_64BIT(ctx);
365     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
366 #if defined(TARGET_PPC64)
367     gen_helper_CFUGED(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
368 #else
369     qemu_build_not_reached();
370 #endif
371     return true;
374 static void do_cntzdm(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 mask, int64_t trail)
376     TCGv_i64 t0, t1;
378     t0 = tcg_temp_new_i64();
379     t1 = tcg_temp_new_i64();
381     tcg_gen_and_i64(t0, src, mask);
382     if (trail) {
383         tcg_gen_ctzi_i64(t0, t0, -1);
384     } else {
385         tcg_gen_clzi_i64(t0, t0, -1);
386     }
388     tcg_gen_setcondi_i64(TCG_COND_NE, t1, t0, -1);
389     tcg_gen_andi_i64(t0, t0, 63);
390     tcg_gen_xori_i64(t0, t0, 63);
391     if (trail) {
392         tcg_gen_shl_i64(t0, mask, t0);
393         tcg_gen_shl_i64(t0, t0, t1);
394     } else {
395         tcg_gen_shr_i64(t0, mask, t0);
396         tcg_gen_shr_i64(t0, t0, t1);
397     }
399     tcg_gen_ctpop_i64(dst, t0);
402 static bool trans_CNTLZDM(DisasContext *ctx, arg_X *a)
404     REQUIRE_64BIT(ctx);
405     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
406 #if defined(TARGET_PPC64)
407     do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], false);
408 #else
409     qemu_build_not_reached();
410 #endif
411     return true;
414 static bool trans_CNTTZDM(DisasContext *ctx, arg_X *a)
416     REQUIRE_64BIT(ctx);
417     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
418 #if defined(TARGET_PPC64)
419     do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], true);
420 #else
421     qemu_build_not_reached();
422 #endif
423     return true;
426 static bool trans_PDEPD(DisasContext *ctx, arg_X *a)
428     REQUIRE_64BIT(ctx);
429     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
430 #if defined(TARGET_PPC64)
431     gen_helper_PDEPD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
432 #else
433     qemu_build_not_reached();
434 #endif
435     return true;
438 static bool trans_PEXTD(DisasContext *ctx, arg_X *a)
440     REQUIRE_64BIT(ctx);
441     REQUIRE_INSNS_FLAGS2(ctx, ISA310);
442 #if defined(TARGET_PPC64)
443     gen_helper_PEXTD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
444 #else
445     qemu_build_not_reached();
446 #endif
447     return true;
450 static bool trans_ADDG6S(DisasContext *ctx, arg_X *a)
452     const target_ulong carry_bits = (target_ulong)-1 / 0xf;
453     TCGv in1, in2, carryl, carryh, tmp;
454     TCGv zero = tcg_constant_tl(0);
456     REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
458     in1 = cpu_gpr[a->ra];
459     in2 = cpu_gpr[a->rb];
460     tmp = tcg_temp_new();
461     carryl = tcg_temp_new();
462     carryh = tcg_temp_new();
464     /* Addition with carry. */
465     tcg_gen_add2_tl(carryl, carryh, in1, zero, in2, zero);
466     /* Addition without carry. */
467     tcg_gen_xor_tl(tmp, in1, in2);
468     /* Difference between the two is carry in to each bit. */
469     tcg_gen_xor_tl(carryl, carryl, tmp);
471     /*
472      * The carry-out that we're looking for is the carry-in to
473      * the next nibble.  Shift the double-word down one nibble,
474      * which puts all of the bits back into one word.
475      */
476     tcg_gen_extract2_tl(carryl, carryl, carryh, 4);
478     /* Invert, isolate the carry bits, and produce 6's. */
479     tcg_gen_andc_tl(carryl, tcg_constant_tl(carry_bits), carryl);
480     tcg_gen_muli_tl(cpu_gpr[a->rt], carryl, 6);
481     return true;
484 static bool trans_CDTBCD(DisasContext *ctx, arg_X_sa *a)
486     REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
487     gen_helper_CDTBCD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
488     return true;
491 static bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a)
493     REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
494     gen_helper_CBCDTD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
495     return true;
498 static bool do_hash(DisasContext *ctx, arg_X *a, bool priv,
499     void (*helper)(TCGv_ptr, TCGv, TCGv, TCGv))
501     TCGv ea;
503     if (!(ctx->insns_flags2 & PPC2_ISA310)) {
504         /* if version is before v3.1, this operation is a nop */
505         return true;
506     }
508     if (priv) {
509         /* if instruction is privileged but the context is in user space */
510         REQUIRE_SV(ctx);
511     }
513     if (unlikely(a->ra == 0)) {
514         /* if RA=0, the instruction form is invalid */
515         gen_invalid(ctx);
516         return true;
517     }
519     ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->rt));
520     helper(cpu_env, ea, cpu_gpr[a->ra], cpu_gpr[a->rb]);
521     return true;
524 TRANS(HASHST, do_hash, false, gen_helper_HASHST)
525 TRANS(HASHCHK, do_hash, false, gen_helper_HASHCHK)
526 TRANS(HASHSTP, do_hash, true, gen_helper_HASHSTP)
527 TRANS(HASHCHKP, do_hash, true, gen_helper_HASHCHKP)