master
inc 2,269 lines 61.2 KB
Raw
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 */
19
20 /*
21 * Byte-Reverse Instructions
22 */
23 static bool trans_BRD(DisasContext *ctx, arg_BRD *a)
24 {
25 REQUIRE_64BIT(ctx);
26 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
27 #if defined(TARGET_PPC64)
28 tcg_gen_bswap64_i64(cpu_gpr[a->ra], cpu_gpr[a->rs]);
29 #else
30 qemu_build_not_reached();
31 #endif
32 return true;
33 }
34
35 static bool trans_BRW(DisasContext *ctx, arg_BRW *a)
36 {
37 REQUIRE_64BIT(ctx);
38 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
39 #if defined(TARGET_PPC64)
40 tcg_gen_bswap64_i64(cpu_gpr[a->ra], cpu_gpr[a->rs]);
41 tcg_gen_rotli_i64(cpu_gpr[a->ra], cpu_gpr[a->ra], 32);
42 #else
43 qemu_build_not_reached();
44 #endif
45 return true;
46 }
47
48 static bool trans_BRH(DisasContext *ctx, arg_BRH *a)
49 {
50 REQUIRE_64BIT(ctx);
51 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
52 #if defined(TARGET_PPC64)
53 TCGv_i64 mask = tcg_constant_i64(0x00ff00ff00ff00ffull);
54 TCGv_i64 t1 = tcg_temp_new_i64();
55 TCGv_i64 t2 = tcg_temp_new_i64();
56
57 tcg_gen_shri_i64(t1, cpu_gpr[a->rs], 8);
58 tcg_gen_and_i64(t2, t1, mask);
59 tcg_gen_and_i64(t1, cpu_gpr[a->rs], mask);
60 tcg_gen_shli_i64(t1, t1, 8);
61 tcg_gen_or_i64(cpu_gpr[a->ra], t1, t2);
62 #else
63 qemu_build_not_reached();
64 #endif
65 return true;
66 }
67
68 /*
69 * Fixed-Point Load/Store Instructions
70 */
71
72 static bool do_ldst(DisasContext *ctx, int rt, int ra, TCGv displ, bool update,
73 bool store, MemOp mop)
74 {
75 TCGv ea;
76
77 if (update && (ra == 0 || (!store && ra == rt))) {
78 gen_invalid(ctx);
79 return true;
80 }
81 gen_set_access_type(ctx, ACCESS_INT);
82
83 ea = do_ea_calc(ctx, ra, displ);
84 mop ^= ctx->default_tcg_memop_mask;
85 if (store) {
86 tcg_gen_qemu_st_tl(cpu_gpr[rt], ea, ctx->mem_idx, mop);
87 } else {
88 tcg_gen_qemu_ld_tl(cpu_gpr[rt], ea, ctx->mem_idx, mop);
89 }
90 if (update) {
91 tcg_gen_mov_tl(cpu_gpr[ra], ea);
92 }
93 return true;
94 }
95
96 static bool do_ldst_D(DisasContext *ctx, arg_D *a, bool update, bool store,
97 MemOp mop)
98 {
99 return do_ldst(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update, store, mop);
100 }
101
102 static bool do_ldst_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool update,
103 bool store, MemOp mop)
104 {
105 arg_D d;
106 if (!resolve_PLS_D(ctx, &d, a)) {
107 return true;
108 }
109 return do_ldst_D(ctx, &d, update, store, mop);
110 }
111
112 static bool do_ldst_X(DisasContext *ctx, arg_X *a, bool update,
113 bool store, MemOp mop)
114 {
115 return do_ldst(ctx, a->rt, a->ra, cpu_gpr[a->rb], update, store, mop);
116 }
117
118 static bool do_ldst_quad(DisasContext *ctx, arg_D *a, bool store, bool prefixed)
119 {
120 #if defined(TARGET_PPC64)
121 TCGv ea;
122 TCGv_i64 lo, hi;
123 TCGv_i128 t16;
124
125 REQUIRE_INSNS_FLAGS(ctx, 64BX);
126
127 if (!prefixed && !(ctx->insns_flags2 & PPC2_ISA207)) {
128 /* lq and stq were privileged prior to V. 2.07 */
129 REQUIRE_SV(ctx);
130
131 if (ctx->le_mode) {
132 gen_align_no_le(ctx);
133 return true;
134 }
135 }
136
137 if (!store && unlikely(a->ra == a->rt)) {
138 gen_invalid(ctx);
139 return true;
140 }
141
142 gen_set_access_type(ctx, ACCESS_INT);
143 ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->si));
144
145 if (ctx->le_mode && prefixed) {
146 lo = cpu_gpr[a->rt];
147 hi = cpu_gpr[a->rt + 1];
148 } else {
149 lo = cpu_gpr[a->rt + 1];
150 hi = cpu_gpr[a->rt];
151 }
152 t16 = tcg_temp_new_i128();
153
154 if (store) {
155 tcg_gen_concat_i64_i128(t16, lo, hi);
156 tcg_gen_qemu_st_i128(t16, ea, ctx->mem_idx, DEF_MEMOP(MO_128));
157 } else {
158 tcg_gen_qemu_ld_i128(t16, ea, ctx->mem_idx, DEF_MEMOP(MO_128));
159 tcg_gen_extr_i128_i64(lo, hi, t16);
160 }
161 #else
162 qemu_build_not_reached();
163 #endif
164
165 return true;
166 }
167
168 static bool do_ldst_quad_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store)
169 {
170 arg_D d;
171 if (!resolve_PLS_D(ctx, &d, a)) {
172 return true;
173 }
174
175 return do_ldst_quad(ctx, &d, store, true);
176 }
177
178 /* Load Byte and Zero */
179 TRANS(LBZ, do_ldst_D, false, false, MO_UB)
180 TRANS(LBZX, do_ldst_X, false, false, MO_UB)
181 TRANS(LBZU, do_ldst_D, true, false, MO_UB)
182 TRANS(LBZUX, do_ldst_X, true, false, MO_UB)
183 TRANS(PLBZ, do_ldst_PLS_D, false, false, MO_UB)
184
185 /* Load Halfword and Zero */
186 TRANS(LHZ, do_ldst_D, false, false, MO_UW)
187 TRANS(LHZX, do_ldst_X, false, false, MO_UW)
188 TRANS(LHZU, do_ldst_D, true, false, MO_UW)
189 TRANS(LHZUX, do_ldst_X, true, false, MO_UW)
190 TRANS(PLHZ, do_ldst_PLS_D, false, false, MO_UW)
191
192 /* Load Halfword Algebraic */
193 TRANS(LHA, do_ldst_D, false, false, MO_SW)
194 TRANS(LHAX, do_ldst_X, false, false, MO_SW)
195 TRANS(LHAU, do_ldst_D, true, false, MO_SW)
196 TRANS(LHAXU, do_ldst_X, true, false, MO_SW)
197 TRANS(PLHA, do_ldst_PLS_D, false, false, MO_SW)
198
199 /* Load Word and Zero */
200 TRANS(LWZ, do_ldst_D, false, false, MO_UL)
201 TRANS(LWZX, do_ldst_X, false, false, MO_UL)
202 TRANS(LWZU, do_ldst_D, true, false, MO_UL)
203 TRANS(LWZUX, do_ldst_X, true, false, MO_UL)
204 TRANS(PLWZ, do_ldst_PLS_D, false, false, MO_UL)
205
206 /* Load Word Algebraic */
207 TRANS64(LWA, do_ldst_D, false, false, MO_SL)
208 TRANS64(LWAX, do_ldst_X, false, false, MO_SL)
209 TRANS64(LWAUX, do_ldst_X, true, false, MO_SL)
210 TRANS64(PLWA, do_ldst_PLS_D, false, false, MO_SL)
211
212 /* Load Doubleword */
213 TRANS64(LD, do_ldst_D, false, false, MO_UQ)
214 TRANS64(LDX, do_ldst_X, false, false, MO_UQ)
215 TRANS64(LDU, do_ldst_D, true, false, MO_UQ)
216 TRANS64(LDUX, do_ldst_X, true, false, MO_UQ)
217 TRANS64(PLD, do_ldst_PLS_D, false, false, MO_UQ)
218
219 /* Load Quadword */
220 TRANS64(LQ, do_ldst_quad, false, false);
221 TRANS64(PLQ, do_ldst_quad_PLS_D, false);
222
223 /* Store Byte */
224 TRANS(STB, do_ldst_D, false, true, MO_UB)
225 TRANS(STBX, do_ldst_X, false, true, MO_UB)
226 TRANS(STBU, do_ldst_D, true, true, MO_UB)
227 TRANS(STBUX, do_ldst_X, true, true, MO_UB)
228 TRANS(PSTB, do_ldst_PLS_D, false, true, MO_UB)
229
230 /* Store Halfword */
231 TRANS(STH, do_ldst_D, false, true, MO_UW)
232 TRANS(STHX, do_ldst_X, false, true, MO_UW)
233 TRANS(STHU, do_ldst_D, true, true, MO_UW)
234 TRANS(STHUX, do_ldst_X, true, true, MO_UW)
235 TRANS(PSTH, do_ldst_PLS_D, false, true, MO_UW)
236
237 /* Store Word */
238 TRANS(STW, do_ldst_D, false, true, MO_UL)
239 TRANS(STWX, do_ldst_X, false, true, MO_UL)
240 TRANS(STWU, do_ldst_D, true, true, MO_UL)
241 TRANS(STWUX, do_ldst_X, true, true, MO_UL)
242 TRANS(PSTW, do_ldst_PLS_D, false, true, MO_UL)
243
244 /* Store Doubleword */
245 TRANS64(STD, do_ldst_D, false, true, MO_UQ)
246 TRANS64(STDX, do_ldst_X, false, true, MO_UQ)
247 TRANS64(STDU, do_ldst_D, true, true, MO_UQ)
248 TRANS64(STDUX, do_ldst_X, true, true, MO_UQ)
249 TRANS64(PSTD, do_ldst_PLS_D, false, true, MO_UQ)
250
251 /* Store Quadword */
252 TRANS64(STQ, do_ldst_quad, true, false);
253 TRANS64(PSTQ, do_ldst_quad_PLS_D, true);
254
255 /* Store Conditional Instructions */
256
257 static bool do_store_cond(DisasContext *ctx, arg_X *a, MemOp mop)
258 {
259 TCGLabel *lfail = gen_new_label();
260 TCGv ea = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
261 TCGv cr0 = tcg_temp_new();
262 TCGv t0 = tcg_temp_new();
263
264 tcg_gen_mov_tl(cr0, cpu_so);
265 gen_set_access_type(ctx, ACCESS_RES);
266
267 tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_reserve, lfail);
268 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_reserve_length, memop_size(mop), lfail);
269
270 tcg_gen_atomic_cmpxchg_tl(t0, cpu_reserve, cpu_reserve_val,
271 cpu_gpr[a->rt], ctx->mem_idx,
272 DEF_MEMOP(mop) | MO_ALIGN);
273 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_reserve_val);
274 tcg_gen_shli_tl(t0, t0, CRF_EQ_BIT);
275 tcg_gen_or_tl(cr0, cr0, t0);
276
277 gen_set_label(lfail);
278 tcg_gen_trunc_tl_i32(cpu_crf[0], cr0);
279 tcg_gen_movi_tl(cpu_reserve, -1);
280 return true;
281 }
282
283 TRANS_FLAGS2(ATOMIC_ISA206, STBCX, do_store_cond, MO_UB);
284 TRANS_FLAGS2(ATOMIC_ISA206, STHCX, do_store_cond, MO_UW);
285 TRANS(STWCX, do_store_cond, MO_UL);
286 TRANS64(STDCX, do_store_cond, MO_UQ);
287
288 static bool trans_STQCX(DisasContext *ctx, arg_STQCX *a)
289 {
290 REQUIRE_64BIT(ctx);
291 REQUIRE_INSNS_FLAGS2(ctx, ISA207);
292 #if defined(TARGET_PPC64)
293 TCGLabel *lfail = gen_new_label();
294 TCGv ea = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
295 TCGv t0 = tcg_temp_new();
296 TCGv t1 = tcg_temp_new();
297 TCGv cr0 = tcg_temp_new();
298 TCGv_i128 cmp = tcg_temp_new_i128();
299 TCGv_i128 val = tcg_temp_new_i128();
300
301 if (unlikely(a->rt & 1)) {
302 gen_invalid(ctx);
303 return true;
304 }
305
306 tcg_gen_mov_tl(cr0, cpu_so);
307 gen_set_access_type(ctx, ACCESS_RES);
308
309 tcg_gen_brcond_tl(TCG_COND_NE, ea, cpu_reserve, lfail);
310 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_reserve_length, 16, lfail);
311
312 tcg_gen_concat_i64_i128(cmp, cpu_reserve_val2, cpu_reserve_val);
313
314 /* Note that the low part is always in RS+1, even in LE mode. */
315 tcg_gen_concat_i64_i128(val, cpu_gpr[a->rt + 1], cpu_gpr[a->rt]);
316
317 tcg_gen_atomic_cmpxchg_i128(val, cpu_reserve, cmp, val, ctx->mem_idx,
318 DEF_MEMOP(MO_128 | MO_ALIGN));
319
320 tcg_gen_extr_i128_i64(t1, t0, val);
321
322 tcg_gen_xor_tl(t1, t1, cpu_reserve_val2);
323 tcg_gen_xor_tl(t0, t0, cpu_reserve_val);
324 tcg_gen_or_tl(t0, t0, t1);
325
326 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, 0);
327 tcg_gen_shli_tl(t0, t0, CRF_EQ_BIT);
328 tcg_gen_or_tl(cr0, cr0, t0);
329
330 gen_set_label(lfail);
331 tcg_gen_trunc_tl_i32(cpu_crf[0], cr0);
332 tcg_gen_movi_tl(cpu_reserve, -1);
333 #else
334 qemu_build_not_reached();
335 #endif
336 return true;
337 }
338
339 /* Load/Store Multiple Word */
340 static bool do_ldst_multiple(DisasContext *ctx, arg_D *a, bool store)
341 {
342 TCGv ea;
343 TCGv_i32 reg;
344
345 REQUIRE_INSNS_FLAGS(ctx, INTEGER);
346
347 /* Little-endian mode is not supported for multiple word operations */
348 if (ctx->le_mode) {
349 gen_align_no_le(ctx);
350 return true;
351 }
352
353 gen_set_access_type(ctx, ACCESS_INT);
354
355 reg = tcg_constant_i32(a->rt);
356 ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->si));
357
358 /* Call the appropriate helper function */
359 if (store) {
360 gen_helper_STMW(tcg_env, ea, reg);
361 } else {
362 gen_helper_LMW(tcg_env, ea, reg);
363 }
364
365 return true;
366 }
367
368 TRANS(LMW, do_ldst_multiple, false)
369 TRANS(STMW, do_ldst_multiple, true)
370
371 /*
372 * Fixed-Point Compare Instructions
373 */
374
375 static bool do_cmp_X(DisasContext *ctx, arg_X_bfl *a, bool s)
376 {
377 if ((ctx->insns_flags & PPC_64B) == 0) {
378 /*
379 * For 32-bit implementations, The Programming Environments Manual says
380 * that "the L field must be cleared, otherwise the instruction form is
381 * invalid." It seems, however, that most 32-bit CPUs ignore invalid
382 * forms (e.g., section "Instruction Formats" of the 405 and 440
383 * manuals, "Integer Compare Instructions" of the 601 manual), with the
384 * notable exception of the e500 and e500mc, where L=1 was reported to
385 * cause an exception.
386 */
387 if (a->l) {
388 if ((ctx->insns_flags2 & PPC2_BOOKE206)) {
389 /*
390 * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc),
391 * generate an illegal instruction exception.
392 */
393 return false;
394 } else {
395 qemu_log_mask(LOG_GUEST_ERROR,
396 "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n",
397 s ? "" : "L", ctx->cia);
398 }
399 }
400 gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
401 return true;
402 }
403
404 /* For 64-bit implementations, deal with bit L accordingly. */
405 if (a->l) {
406 gen_op_cmp(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
407 } else {
408 gen_op_cmp32(cpu_gpr[a->ra], cpu_gpr[a->rb], s, a->bf);
409 }
410 return true;
411 }
412
413 static bool do_cmp_D(DisasContext *ctx, arg_D_bf *a, bool s)
414 {
415 if ((ctx->insns_flags & PPC_64B) == 0) {
416 /*
417 * For 32-bit implementations, The Programming Environments Manual says
418 * that "the L field must be cleared, otherwise the instruction form is
419 * invalid." It seems, however, that most 32-bit CPUs ignore invalid
420 * forms (e.g., section "Instruction Formats" of the 405 and 440
421 * manuals, "Integer Compare Instructions" of the 601 manual), with the
422 * notable exception of the e500 and e500mc, where L=1 was reported to
423 * cause an exception.
424 */
425 if (a->l) {
426 if ((ctx->insns_flags2 & PPC2_BOOKE206)) {
427 /*
428 * For 32-bit Book E v2.06 implementations (i.e. e500/e500mc),
429 * generate an illegal instruction exception.
430 */
431 return false;
432 } else {
433 qemu_log_mask(LOG_GUEST_ERROR,
434 "Invalid form of CMP%s at 0x" TARGET_FMT_lx ", L = 1\n",
435 s ? "I" : "LI", ctx->cia);
436 }
437 }
438 gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
439 return true;
440 }
441
442 /* For 64-bit implementations, deal with bit L accordingly. */
443 if (a->l) {
444 gen_op_cmp(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
445 } else {
446 gen_op_cmp32(cpu_gpr[a->ra], tcg_constant_tl(a->imm), s, a->bf);
447 }
448 return true;
449 }
450
451 TRANS(CMP, do_cmp_X, true);
452 TRANS(CMPL, do_cmp_X, false);
453 TRANS(CMPI, do_cmp_D, true);
454 TRANS(CMPLI, do_cmp_D, false);
455
456 static bool trans_CMPRB(DisasContext *ctx, arg_CMPRB *a)
457 {
458 TCGv_i32 src1 = tcg_temp_new_i32();
459 TCGv_i32 src2 = tcg_temp_new_i32();
460 TCGv_i32 src2lo = tcg_temp_new_i32();
461 TCGv_i32 src2hi = tcg_temp_new_i32();
462 TCGv_i32 crf = cpu_crf[a->bf];
463
464 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
465 tcg_gen_trunc_tl_i32(src1, cpu_gpr[a->ra]);
466 tcg_gen_trunc_tl_i32(src2, cpu_gpr[a->rb]);
467
468 tcg_gen_andi_i32(src1, src1, 0xFF);
469 tcg_gen_ext8u_i32(src2lo, src2);
470 tcg_gen_extract_i32(src2hi, src2, 8, 8);
471
472 tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1);
473 tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi);
474 tcg_gen_and_i32(crf, src2lo, src2hi);
475
476 if (a->l) {
477 tcg_gen_extract_i32(src2lo, src2, 16, 8);
478 tcg_gen_extract_i32(src2hi, src2, 24, 8);
479 tcg_gen_setcond_i32(TCG_COND_LEU, src2lo, src2lo, src1);
480 tcg_gen_setcond_i32(TCG_COND_LEU, src2hi, src1, src2hi);
481 tcg_gen_and_i32(src2lo, src2lo, src2hi);
482 tcg_gen_or_i32(crf, crf, src2lo);
483 }
484 tcg_gen_shli_i32(crf, crf, CRF_GT_BIT);
485 return true;
486 }
487
488 static bool trans_CMPEQB(DisasContext *ctx, arg_CMPEQB *a)
489 {
490 REQUIRE_64BIT(ctx);
491 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
492 #if defined(TARGET_PPC64)
493 gen_helper_CMPEQB(cpu_crf[a->bf], cpu_gpr[a->ra], cpu_gpr[a->rb]);
494 #else
495 qemu_build_not_reached();
496 #endif
497 return true;
498 }
499
500 /*
501 * Fixed-Point Arithmetic Instructions
502 */
503
504 static bool trans_ADDI(DisasContext *ctx, arg_D *a)
505 {
506 if (a->ra) {
507 tcg_gen_addi_tl(cpu_gpr[a->rt], cpu_gpr[a->ra], a->si);
508 } else {
509 tcg_gen_movi_tl(cpu_gpr[a->rt], a->si);
510 }
511 return true;
512 }
513
514 static bool trans_PADDI(DisasContext *ctx, arg_PLS_D *a)
515 {
516 arg_D d;
517 if (!resolve_PLS_D(ctx, &d, a)) {
518 return true;
519 }
520 return trans_ADDI(ctx, &d);
521 }
522
523 static bool trans_ADDIS(DisasContext *ctx, arg_D *a)
524 {
525 a->si <<= 16;
526 return trans_ADDI(ctx, a);
527 }
528
529 static bool trans_ADDPCIS(DisasContext *ctx, arg_DX *a)
530 {
531 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
532 tcg_gen_movi_tl(cpu_gpr[a->rt], ctx->base.pc_next + (a->d << 16));
533 return true;
534 }
535
536 static bool trans_ADDEX(DisasContext *ctx, arg_X *a)
537 {
538 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
539 gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
540 cpu_ov, cpu_ov32, true, true, false, false);
541 return true;
542 }
543
544 static bool trans_MTCRF(DisasContext *ctx, arg_MTCRF *a)
545 {
546 TCGv_i32 temp;
547 uint32_t crm, crn;
548
549 crm = a->fxm;
550
551 temp = tcg_temp_new_i32();
552 tcg_gen_trunc_tl_i32(temp, cpu_gpr[a->rt]);
553
554 for (crn = 0 ; crn < 8 ; crn++) {
555 if (crm & (1 << crn)) {
556 tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
557 tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
558 }
559 }
560
561 return true;
562 }
563
564 static bool trans_MTOCRF(DisasContext *ctx, arg_MTOCRF *a)
565 {
566 uint32_t crm, crn;
567
568 crm = a->fxm;
569
570 /* Checking crm > 0 and set_bits(crm) == 1 */
571 if (crm && ((crm & (crm - 1)) == 0)) {
572 TCGv_i32 temp = tcg_temp_new_i32();
573 crn = ctz32(crm);
574 tcg_gen_trunc_tl_i32(temp, cpu_gpr[a->rt]);
575 tcg_gen_shri_i32(temp, temp, crn * 4);
576 tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
577 }
578
579 return true;
580 }
581
582 static bool trans_MFOCR(DisasContext *ctx, arg_MFOCR *a)
583 {
584 uint32_t crm, crn;
585
586 crm = a->fxm;
587
588 /* Checking crm > 0 and set_bits(crm) == 1 */
589 if (likely(crm && ((crm & (crm - 1)) == 0))) {
590 crn = ctz32(crm);
591 tcg_gen_extu_i32_tl(cpu_gpr[a->rt], cpu_crf[7 - crn]);
592 tcg_gen_shli_tl(cpu_gpr[a->rt],
593 cpu_gpr[a->rt], crn * 4);
594 }
595
596 return true;
597 }
598
599 static bool trans_MFCR(DisasContext *ctx, arg_MFCR *a)
600 {
601 TCGv_i32 t0 = tcg_temp_new_i32();
602 tcg_gen_mov_i32(t0, cpu_crf[0]);
603 tcg_gen_shli_i32(t0, t0, 4);
604 tcg_gen_or_i32(t0, t0, cpu_crf[1]);
605 tcg_gen_shli_i32(t0, t0, 4);
606 tcg_gen_or_i32(t0, t0, cpu_crf[2]);
607 tcg_gen_shli_i32(t0, t0, 4);
608 tcg_gen_or_i32(t0, t0, cpu_crf[3]);
609 tcg_gen_shli_i32(t0, t0, 4);
610 tcg_gen_or_i32(t0, t0, cpu_crf[4]);
611 tcg_gen_shli_i32(t0, t0, 4);
612 tcg_gen_or_i32(t0, t0, cpu_crf[5]);
613 tcg_gen_shli_i32(t0, t0, 4);
614 tcg_gen_or_i32(t0, t0, cpu_crf[6]);
615 tcg_gen_shli_i32(t0, t0, 4);
616 tcg_gen_or_i32(t0, t0, cpu_crf[7]);
617 tcg_gen_extu_i32_tl(cpu_gpr[a->rt], t0);
618
619 return true;
620 }
621
622 static bool cr_logic_common(DisasContext *ctx, arg_X *a,
623 void (*tcg_op)(TCGv_i32, TCGv_i32, TCGv_i32))
624 {
625 uint8_t bitmask;
626 int sh;
627 TCGv_i32 t0, t1;
628 sh = (a->rt & 0x03) - (a->ra & 0x03);
629 t0 = tcg_temp_new_i32();
630 t1 = tcg_temp_new_i32();
631
632 if (sh > 0) {
633 tcg_gen_shri_i32(t0, cpu_crf[a->ra >> 2], sh);
634 } else if (sh < 0) {
635 tcg_gen_shli_i32(t0, cpu_crf[a->ra >> 2], -sh);
636 } else {
637 tcg_gen_mov_i32(t0, cpu_crf[a->ra >> 2]);
638 }
639
640 sh = (a->rt & 0x03) - (a->rb & 0x03);
641 if (sh > 0) {
642 tcg_gen_shri_i32(t1, cpu_crf[a->rb >> 2], sh);
643 } else if (sh < 0) {
644 tcg_gen_shli_i32(t1, cpu_crf[a->rb >> 2], -sh);
645 } else {
646 tcg_gen_mov_i32(t1, cpu_crf[a->rb >> 2]);
647 }
648 tcg_op(t0, t0, t1);
649
650 bitmask = 0x08 >> (a->rt & 0x03);
651 tcg_gen_andi_i32(t0, t0, bitmask);
652 tcg_gen_andi_i32(t1, cpu_crf[a->rt >> 2], ~bitmask);
653 tcg_gen_or_i32(cpu_crf[a->rt >> 2], t0, t1);
654
655 return true;
656 }
657
658 TRANS(CRAND, cr_logic_common, tcg_gen_and_i32);
659 TRANS(CROR, cr_logic_common, tcg_gen_or_i32);
660 TRANS(CRXOR, cr_logic_common, tcg_gen_xor_i32);
661 TRANS(CRNAND, cr_logic_common, tcg_gen_nand_i32);
662 TRANS(CRNOR, cr_logic_common, tcg_gen_nor_i32);
663 TRANS(CRANDC, cr_logic_common, tcg_gen_andc_i32);
664 TRANS(CREQV, cr_logic_common, tcg_gen_eqv_i32);
665 TRANS(CRORC, cr_logic_common, tcg_gen_orc_i32);
666
667 /*** Integer load and store strings ***/
668
669 /* lswi */
670 static bool trans_LSWI(DisasContext *ctx, arg_LSWI *a)
671 {
672 TCGv t0;
673 TCGv_i32 t1, t2;
674 int nb = a->rb;
675 int start = a->rt;
676 int ra = a->ra;
677 int nr;
678
679 REQUIRE_INSNS_FLAGS(ctx, STRING);
680 if (ctx->le_mode) {
681 gen_align_no_le(ctx);
682 return true;
683 }
684 if (nb == 0) {
685 nb = 32;
686 }
687 nr = DIV_ROUND_UP(nb, 4);
688 if (unlikely(lsw_reg_in_range(start, nr, ra))) {
689 gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
690 return true;
691 }
692 gen_set_access_type(ctx, ACCESS_INT);
693 t0 = do_ea_calc_ra(ctx, ra);
694 t1 = tcg_constant_i32(nb);
695 t2 = tcg_constant_i32(start);
696 gen_helper_LSW(tcg_env, t0, t1, t2);
697
698 return true;
699 }
700
701 /* lswx */
702 static bool trans_LSWX(DisasContext *ctx, arg_LSWX *a)
703 {
704 TCGv t0;
705 TCGv_i32 t1, t2, t3;
706
707 REQUIRE_INSNS_FLAGS(ctx, STRING);
708 if (ctx->le_mode) {
709 gen_align_no_le(ctx);
710 return true;
711 }
712
713 gen_set_access_type(ctx, ACCESS_INT);
714 t0 = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
715 t1 = tcg_constant_i32(a->rt);
716 t2 = tcg_constant_i32(a->ra);
717 t3 = tcg_constant_i32(a->rb);
718 gen_helper_LSWX(tcg_env, t0, t1, t2, t3);
719
720 return true;
721 }
722
723 /* stswi */
724 static bool trans_STSWI(DisasContext *ctx, arg_STSWI *a)
725 {
726 TCGv t0;
727 TCGv_i32 t1, t2;
728 int nb = a->rb;
729
730 REQUIRE_INSNS_FLAGS(ctx, STRING);
731 if (ctx->le_mode) {
732 gen_align_no_le(ctx);
733 return true;
734 }
735 gen_set_access_type(ctx, ACCESS_INT);
736 t0 = do_ea_calc_ra(ctx, a->ra);
737 if (nb == 0) {
738 nb = 32;
739 }
740 t1 = tcg_constant_i32(nb);
741 t2 = tcg_constant_i32(a->rt);
742 gen_helper_STSW(tcg_env, t0, t1, t2);
743
744 return true;
745 }
746
747 /* stswx */
748 static bool trans_STSWX(DisasContext *ctx, arg_STSWX *a)
749 {
750 TCGv t0;
751 TCGv_i32 t1, t2;
752
753 REQUIRE_INSNS_FLAGS(ctx, STRING);
754 if (ctx->le_mode) {
755 gen_align_no_le(ctx);
756 return true;
757 }
758 gen_set_access_type(ctx, ACCESS_INT);
759 t0 = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
760 t1 = tcg_temp_new_i32();
761 tcg_gen_trunc_tl_i32(t1, cpu_xer);
762 tcg_gen_andi_i32(t1, t1, 0x7F);
763 t2 = tcg_constant_i32(a->rt);
764 gen_helper_STSW(tcg_env, t0, t1, t2);
765
766 return true;
767 }
768
769 static bool do_add_D(DisasContext *ctx, arg_D *a, bool add_ca, bool compute_ca,
770 bool compute_ov, bool compute_rc0)
771 {
772 gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra],
773 tcg_constant_tl(a->si), cpu_ca, cpu_ca32,
774 add_ca, compute_ca, compute_ov, compute_rc0);
775 return true;
776 }
777
778 static bool do_add_XO(DisasContext *ctx, arg_XO *a, bool add_ca,
779 bool compute_ca)
780 {
781 gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
782 cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc);
783 return true;
784 }
785
786 static bool do_add_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val,
787 bool add_ca, bool compute_ca)
788 {
789 gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val,
790 cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc);
791 return true;
792 }
793
794 static bool do_shift_X_rc(DisasContext *ctx, arg_X_rc *a,
795 void(*op)(TCGv, TCGv, TCGv))
796 {
797 REQUIRE_64BIT(ctx);
798 #if defined(TARGET_PPC64)
799 TCGv t0 = tcg_temp_new();
800 TCGv t1 = tcg_temp_new();
801
802 /* AND rt with a mask that is 0 when rb >= 0x40 */
803 tcg_gen_shli_tl(t0, cpu_gpr[a->rb], 0x39);
804 tcg_gen_sari_tl(t0, t0, 0x3f);
805 tcg_gen_andc_tl(t0, cpu_gpr[a->rt], t0);
806 tcg_gen_andi_tl(t1, cpu_gpr[a->rb], 0x3f);
807 op(cpu_gpr[a->ra], t0, t1);
808 if (unlikely(a->rc)) {
809 gen_set_Rc0(ctx, cpu_gpr[a->ra]);
810 }
811 #else
812 qemu_build_not_reached();
813 #endif
814 return true;
815 }
816
817 static bool trans_SRAD(DisasContext *ctx, arg_SRAD *a)
818 {
819 REQUIRE_64BIT(ctx);
820 #if defined(TARGET_PPC64)
821 gen_helper_SRAD(cpu_gpr[a->ra], tcg_env, cpu_gpr[a->rt], cpu_gpr[a->rb]);
822 if (unlikely(a->rc)) {
823 gen_set_Rc0(ctx, cpu_gpr[a->ra]);
824 }
825 #else
826 qemu_build_not_reached();
827 #endif
828 return true;
829 }
830
831 static bool trans_SRADI(DisasContext *ctx, arg_SRADI *a)
832 {
833 REQUIRE_64BIT(ctx);
834 #if defined(TARGET_PPC64)
835 int sh = a->sh;
836 TCGv dst = cpu_gpr[a->ra];
837 TCGv src = cpu_gpr[a->rs];
838 if (sh == 0) {
839 tcg_gen_mov_tl(dst, src);
840 tcg_gen_movi_tl(cpu_ca, 0);
841 if (is_isa300(ctx)) {
842 tcg_gen_movi_tl(cpu_ca32, 0);
843 }
844 } else {
845 TCGv t0 = tcg_temp_new();
846 tcg_gen_andi_tl(cpu_ca, src, (1ULL << sh) - 1);
847 tcg_gen_sari_tl(t0, src, TARGET_LONG_BITS - 1);
848 tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
849 tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
850 if (is_isa300(ctx)) {
851 tcg_gen_mov_tl(cpu_ca32, cpu_ca);
852 }
853 tcg_gen_sari_tl(dst, src, sh);
854 }
855 if (unlikely(a->rc)) {
856 gen_set_Rc0(ctx, dst);
857 }
858 #else
859 qemu_build_not_reached();
860 #endif
861 return true;
862 }
863
864 TRANS(ADD, do_add_XO, false, false);
865 TRANS(ADDC, do_add_XO, false, true);
866 TRANS(ADDE, do_add_XO, true, true);
867 TRANS(ADDME, do_add_const_XO, tcg_constant_tl(-1LL), true, true);
868 TRANS(ADDZE, do_add_const_XO, tcg_constant_tl(0), true, true);
869 TRANS(ADDIC, do_add_D, false, true, false, false);
870 TRANS(ADDIC_, do_add_D, false, true, false, true);
871 TRANS(SLD, do_shift_X_rc, tcg_gen_shl_tl);
872 TRANS(SRD, do_shift_X_rc, tcg_gen_shr_tl);
873
874 static bool do_stxx(DisasContext *ctx, arg_X *a,
875 void(*op)(DisasContext *, TCGv, TCGv), bool is_hvrm)
876 {
877 TCGv ea;
878
879 if (is_hvrm) {
880 REQUIRE_HVRM(ctx);
881 }
882
883 gen_set_access_type(ctx, ACCESS_INT);
884 ea = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
885 op(ctx, cpu_gpr[a->rt], ea);
886
887 return true;
888 }
889
890 TRANS(STHBRX, do_stxx, gen_qemu_st16r, 0);
891 TRANS(STWBRX, do_stxx, gen_qemu_st32r, 0);
892
893 static bool trans_STDBRX(DisasContext *ctx, arg_STDBRX *a)
894 {
895 REQUIRE_64BIT(ctx);
896 REQUIRE_INSNS_FLAGS2(ctx, DBRX);
897 #if defined(TARGET_PPC64)
898 return do_stxx(ctx, a, gen_qemu_st64r_i64, false);
899 #else
900 qemu_build_not_reached();
901 #endif
902 return true;
903 }
904
905 static bool trans_STDCIX(DisasContext *ctx, arg_STDCIX *a)
906 {
907 REQUIRE_64BIT(ctx);
908 REQUIRE_INSNS_FLAGS(ctx, CILDST);
909 #if defined(TARGET_PPC64)
910 return do_stxx(ctx, a, gen_qemu_st64_i64, true);
911 #else
912 qemu_build_not_reached();
913 #endif
914 return true;
915 }
916
917 static bool trans_STWCIX(DisasContext *ctx, arg_STWCIX *a)
918 {
919 REQUIRE_64BIT(ctx);
920 REQUIRE_INSNS_FLAGS(ctx, CILDST);
921 #if defined(TARGET_PPC64)
922 return do_stxx(ctx, a, gen_qemu_st32, true);
923 #else
924 qemu_build_not_reached();
925 #endif
926 return true;
927 }
928
929 static bool trans_STHCIX(DisasContext *ctx, arg_STHCIX *a)
930 {
931 REQUIRE_64BIT(ctx);
932 REQUIRE_INSNS_FLAGS(ctx, CILDST);
933 #if defined(TARGET_PPC64)
934 return do_stxx(ctx, a, gen_qemu_st16, true);
935 #else
936 qemu_build_not_reached();
937 #endif
938 return true;
939 }
940
941 static bool trans_STBCIX(DisasContext *ctx, arg_STBCIX *a)
942 {
943 REQUIRE_64BIT(ctx);
944 REQUIRE_INSNS_FLAGS(ctx, CILDST);
945 #if defined(TARGET_PPC64)
946 return do_stxx(ctx, a, gen_qemu_st8, true);
947 #else
948 qemu_build_not_reached();
949 #endif
950 return true;
951 }
952
953 static bool trans_SUBFIC(DisasContext *ctx, arg_D *a)
954 {
955 gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra],
956 tcg_constant_tl(a->si), false, true, false, false);
957 return true;
958 }
959
960 static bool do_subf_XO(DisasContext *ctx, arg_XO *a, bool add_ca,
961 bool compute_ca)
962 {
963 gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
964 add_ca, compute_ca, a->oe, a->rc);
965 return true;
966 }
967
968 static bool do_subf_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val,
969 bool add_ca, bool compute_ca)
970 {
971 gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val,
972 add_ca, compute_ca, a->oe, a->rc);
973 return true;
974 }
975
976 TRANS(SUBF, do_subf_XO, false, false)
977 TRANS(SUBFC, do_subf_XO, false, true)
978 TRANS(SUBFE, do_subf_XO, true, true)
979 TRANS(SUBFME, do_subf_const_XO, tcg_constant_tl(-1LL), true, true)
980 TRANS(SUBFZE, do_subf_const_XO, tcg_constant_tl(0), true, true)
981
982 static bool trans_MULLI(DisasContext *ctx, arg_MULLI *a)
983 {
984 tcg_gen_muli_tl(cpu_gpr[a->rt], cpu_gpr[a->ra], a->si);
985 return true;
986 }
987
988 static bool trans_MULLW(DisasContext *ctx, arg_MULLW *a)
989 {
990 TCGv t0 = tcg_temp_new();
991 TCGv t1 = tcg_temp_new();
992
993 tcg_gen_ext32s_tl(t0, cpu_gpr[a->ra]);
994 tcg_gen_ext32s_tl(t1, cpu_gpr[a->rb]);
995 tcg_gen_mul_tl(cpu_gpr[a->rt], t0, t1);
996 if (unlikely(a->rc)) {
997 gen_set_Rc0(ctx, cpu_gpr[a->rt]);
998 }
999 return true;
1000 }
1001
1002 static bool trans_MULLWO(DisasContext *ctx, arg_MULLWO *a)
1003 {
1004 TCGv t0 = tcg_temp_new();
1005 TCGv t1 = tcg_temp_new();
1006
1007 #if defined(TARGET_PPC64)
1008 tcg_gen_ext32s_i64(t0, cpu_gpr[a->ra]);
1009 tcg_gen_ext32s_i64(t1, cpu_gpr[a->rb]);
1010 tcg_gen_mul_i64(cpu_gpr[a->rt], t0, t1);
1011 tcg_gen_sextract_i64(t0, cpu_gpr[a->rt], 31, 1);
1012 tcg_gen_sari_i64(t1, cpu_gpr[a->rt], 32);
1013 #else
1014 tcg_gen_muls2_i32(cpu_gpr[a->rt], t1, cpu_gpr[a->ra], cpu_gpr[a->rb]);
1015 tcg_gen_sari_i32(t0, cpu_gpr[a->rt], 31);
1016 #endif
1017 tcg_gen_setcond_tl(TCG_COND_NE, cpu_ov, t0, t1);
1018 if (is_isa300(ctx)) {
1019 tcg_gen_mov_tl(cpu_ov32, cpu_ov);
1020 }
1021 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1022
1023 if (unlikely(a->rc)) {
1024 gen_set_Rc0(ctx, cpu_gpr[a->rt]);
1025 }
1026 return true;
1027 }
1028
1029 static bool do_mulhw(DisasContext *ctx, arg_XO_tab_rc *a,
1030 void (*helper)(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1,
1031 TCGv_i32 arg2))
1032 {
1033 TCGv_i32 t0 = tcg_temp_new_i32();
1034 TCGv_i32 t1 = tcg_temp_new_i32();
1035 tcg_gen_trunc_tl_i32(t0, cpu_gpr[a->ra]);
1036 tcg_gen_trunc_tl_i32(t1, cpu_gpr[a->rb]);
1037 helper(t0, t1, t0, t1);
1038 tcg_gen_extu_i32_tl(cpu_gpr[a->rt], t1);
1039 if (unlikely(a->rc)) {
1040 gen_set_Rc0(ctx, cpu_gpr[a->rt]);
1041 }
1042 return true;
1043 }
1044
1045 TRANS(MULHW, do_mulhw, tcg_gen_muls2_i32)
1046 TRANS(MULHWU, do_mulhw, tcg_gen_mulu2_i32)
1047
1048 static bool do_divw(DisasContext *ctx, arg_XO *a, int sign)
1049 {
1050 gen_op_arith_divw(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
1051 sign, a->oe, a->rc);
1052 return true;
1053 }
1054
1055 static bool do_dive(DisasContext *ctx, arg_XO *a,
1056 void (*helper)(TCGv, TCGv_ptr, TCGv, TCGv, TCGv_i32))
1057 {
1058 REQUIRE_INSNS_FLAGS2(ctx, DIVE_ISA206);
1059 helper(cpu_gpr[a->rt], tcg_env, cpu_gpr[a->ra], cpu_gpr[a->rb],
1060 tcg_constant_i32(a->oe));
1061 if (unlikely(a->rc)) {
1062 gen_set_Rc0(ctx, cpu_gpr[a->rt]);
1063 }
1064 return true;
1065 }
1066
1067 TRANS(DIVW, do_divw, 1);
1068 TRANS(DIVWU, do_divw, 0);
1069 TRANS(DIVWE, do_dive, gen_helper_DIVWE);
1070 TRANS(DIVWEU, do_dive, gen_helper_DIVWEU);
1071
1072 static bool do_modw(DisasContext *ctx, arg_X *a, bool sign)
1073 {
1074 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
1075 gen_op_arith_modw(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
1076 sign);
1077 return true;
1078 }
1079
1080 TRANS(MODUW, do_modw, false);
1081 TRANS(MODSW, do_modw, true);
1082
1083 static bool trans_NEG(DisasContext *ctx, arg_NEG *a)
1084 {
1085 if (a->oe) {
1086 TCGv zero = tcg_constant_tl(0);
1087 gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], zero,
1088 false, false, true, a->rc);
1089 } else {
1090 tcg_gen_neg_tl(cpu_gpr[a->rt], cpu_gpr[a->ra]);
1091 if (unlikely(a->rc)) {
1092 gen_set_Rc0(ctx, cpu_gpr[a->rt]);
1093 }
1094 }
1095 return true;
1096 }
1097
1098 static bool trans_DARN(DisasContext *ctx, arg_DARN *a)
1099 {
1100 REQUIRE_64BIT(ctx);
1101 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
1102 #if defined(TARGET_PPC64)
1103 if (a->l > 2) {
1104 tcg_gen_movi_i64(cpu_gpr[a->rt], -1);
1105 } else {
1106 translator_io_start(&ctx->base);
1107 if (a->l == 0) {
1108 gen_helper_DARN32(cpu_gpr[a->rt]);
1109 } else {
1110 /* Return 64-bit random for both CRN and RRN */
1111 gen_helper_DARN64(cpu_gpr[a->rt]);
1112 }
1113 }
1114 #else
1115 qemu_build_not_reached();
1116 #endif
1117 return true;
1118 }
1119
1120 static bool trans_MULLD(DisasContext *ctx, arg_MULLD *a)
1121 {
1122 REQUIRE_64BIT(ctx);
1123 #if defined(TARGET_PPC64)
1124 tcg_gen_mul_tl(cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb]);
1125 if (unlikely(a->rc)) {
1126 gen_set_Rc0(ctx, cpu_gpr[a->rt]);
1127 }
1128 #else
1129 qemu_build_not_reached();
1130 #endif
1131 return true;
1132 }
1133
1134 static bool trans_MULLDO(DisasContext *ctx, arg_MULLD *a)
1135 {
1136 REQUIRE_64BIT(ctx);
1137 #if defined(TARGET_PPC64)
1138 TCGv_i64 t0 = tcg_temp_new_i64();
1139 TCGv_i64 t1 = tcg_temp_new_i64();
1140
1141 tcg_gen_muls2_i64(t0, t1, cpu_gpr[a->ra], cpu_gpr[a->rb]);
1142 tcg_gen_mov_i64(cpu_gpr[a->rt], t0);
1143
1144 tcg_gen_sari_i64(t0, t0, 63);
1145 tcg_gen_setcond_i64(TCG_COND_NE, cpu_ov, t0, t1);
1146 if (is_isa300(ctx)) {
1147 tcg_gen_mov_tl(cpu_ov32, cpu_ov);
1148 }
1149 tcg_gen_or_tl(cpu_so, cpu_so, cpu_ov);
1150
1151 if (unlikely(a->rc)) {
1152 gen_set_Rc0(ctx, cpu_gpr[a->rt]);
1153 }
1154 #else
1155 qemu_build_not_reached();
1156 #endif
1157 return true;
1158 }
1159
1160 static bool do_mulhd(DisasContext *ctx, arg_XO_tab_rc *a,
1161 void (*helper)(TCGv, TCGv, TCGv, TCGv))
1162 {
1163 TCGv lo = tcg_temp_new();
1164 helper(lo, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb]);
1165 if (unlikely(a->rc)) {
1166 gen_set_Rc0(ctx, cpu_gpr[a->rt]);
1167 }
1168 return true;
1169 }
1170
1171 TRANS64(MULHD, do_mulhd, tcg_gen_muls2_tl);
1172 TRANS64(MULHDU, do_mulhd, tcg_gen_mulu2_tl);
1173
1174 static bool trans_MADDLD(DisasContext *ctx, arg_MADDLD *a)
1175 {
1176 REQUIRE_64BIT(ctx);
1177 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
1178 #if defined(TARGET_PPC64)
1179 TCGv_i64 t1 = tcg_temp_new_i64();
1180
1181 tcg_gen_mul_i64(t1, cpu_gpr[a->vra], cpu_gpr[a->vrb]);
1182 tcg_gen_add_i64(cpu_gpr[a->vrt], t1, cpu_gpr[a->rc]);
1183 #else
1184 qemu_build_not_reached();
1185 #endif
1186 return true;
1187 }
1188
1189 static bool trans_MADDHD(DisasContext *ctx, arg_MADDHD *a)
1190 {
1191 REQUIRE_64BIT(ctx);
1192 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
1193 #if defined(TARGET_PPC64)
1194 TCGv_i64 lo = tcg_temp_new_i64();
1195 TCGv_i64 hi = tcg_temp_new_i64();
1196 TCGv_i64 t1 = tcg_temp_new_i64();
1197
1198 tcg_gen_muls2_i64(lo, hi, cpu_gpr[a->vra], cpu_gpr[a->vrb]);
1199 tcg_gen_sari_i64(t1, cpu_gpr[a->rc], 63);
1200 tcg_gen_add2_i64(t1, cpu_gpr[a->vrt], lo, hi, cpu_gpr[a->rc], t1);
1201 #else
1202 qemu_build_not_reached();
1203 #endif
1204 return true;
1205 }
1206
1207 static bool trans_MADDHDU(DisasContext *ctx, arg_MADDHDU *a)
1208 {
1209 REQUIRE_64BIT(ctx);
1210 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
1211 #if defined(TARGET_PPC64)
1212 TCGv_i64 lo = tcg_temp_new_i64();
1213 TCGv_i64 hi = tcg_temp_new_i64();
1214 TCGv_i64 t1 = tcg_temp_new_i64();
1215
1216 tcg_gen_mulu2_i64(lo, hi, cpu_gpr[a->vra], cpu_gpr[a->vrb]);
1217 tcg_gen_add2_i64(t1, cpu_gpr[a->vrt], lo, hi, cpu_gpr[a->rc],
1218 tcg_constant_i64(0));
1219 #else
1220 qemu_build_not_reached();
1221 #endif
1222 return true;
1223 }
1224
1225 static bool do_divd(DisasContext *ctx, arg_XO *a, bool sign)
1226 {
1227 REQUIRE_64BIT(ctx);
1228 #if defined(TARGET_PPC64)
1229 gen_op_arith_divd(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
1230 sign, a->oe, a->rc);
1231 #else
1232 qemu_build_not_reached();
1233 #endif
1234 return true;
1235 }
1236
1237 static bool do_modd(DisasContext *ctx, arg_X *a, bool sign)
1238 {
1239 REQUIRE_64BIT(ctx);
1240 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
1241 #if defined(TARGET_PPC64)
1242 gen_op_arith_modd(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
1243 sign);
1244 #else
1245 qemu_build_not_reached();
1246 #endif
1247 return true;
1248 }
1249
1250 TRANS64(DIVD, do_divd, true);
1251 TRANS64(DIVDU, do_divd, false);
1252
1253 static bool trans_DIVDE(DisasContext *ctx, arg_DIVDE *a)
1254 {
1255 REQUIRE_64BIT(ctx);
1256 #if defined(TARGET_PPC64)
1257 return do_dive(ctx, a, gen_helper_DIVDE);
1258 #else
1259 qemu_build_not_reached();
1260 #endif
1261 }
1262
1263 static bool trans_DIVDEU(DisasContext *ctx, arg_DIVDEU *a)
1264 {
1265 REQUIRE_64BIT(ctx);
1266 #if defined(TARGET_PPC64)
1267 return do_dive(ctx, a, gen_helper_DIVDEU);
1268 #else
1269 qemu_build_not_reached();
1270 #endif
1271 return true;
1272 }
1273
1274 TRANS64(MODSD, do_modd, true);
1275 TRANS64(MODUD, do_modd, false);
1276
1277 /*
1278 * Fixed-Point Select Instructions
1279 */
1280
1281 static bool trans_ISEL(DisasContext *ctx, arg_ISEL *a)
1282 {
1283 REQUIRE_INSNS_FLAGS(ctx, ISEL);
1284 uint32_t bi = a->bc;
1285 uint32_t mask = 0x08 >> (bi & 0x03);
1286 TCGv t0 = tcg_temp_new();
1287 TCGv zr;
1288
1289 tcg_gen_extu_i32_tl(t0, cpu_crf[bi >> 2]);
1290 tcg_gen_andi_tl(t0, t0, mask);
1291
1292 zr = tcg_constant_tl(0);
1293 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[a->rt], t0, zr,
1294 a->ra ? cpu_gpr[a->ra] : zr,
1295 cpu_gpr[a->rb]);
1296 return true;
1297 }
1298
1299 /*
1300 * Fixed-Point Trap Instructions
1301 */
1302
1303 static bool trans_TW(DisasContext *ctx, arg_TW *a)
1304 {
1305 TCGv_i32 t0;
1306
1307 if (check_unconditional_trap(ctx, a->rt)) {
1308 return true;
1309 }
1310 t0 = tcg_constant_i32(a->rt);
1311 gen_helper_TW(tcg_env, cpu_gpr[a->ra], cpu_gpr[a->rb], t0);
1312 return true;
1313 }
1314
1315 static bool trans_TWI(DisasContext *ctx, arg_TWI *a)
1316 {
1317 TCGv t0;
1318 TCGv_i32 t1;
1319
1320 if (check_unconditional_trap(ctx, a->rt)) {
1321 return true;
1322 }
1323 t0 = tcg_constant_tl(a->si);
1324 t1 = tcg_constant_i32(a->rt);
1325 gen_helper_TW(tcg_env, cpu_gpr[a->ra], t0, t1);
1326 return true;
1327 }
1328
1329 static bool trans_TD(DisasContext *ctx, arg_TD *a)
1330 {
1331 REQUIRE_64BIT(ctx);
1332 #if defined(TARGET_PPC64)
1333 TCGv_i32 t0;
1334
1335 if (check_unconditional_trap(ctx, a->rt)) {
1336 return true;
1337 }
1338 t0 = tcg_constant_i32(a->rt);
1339 gen_helper_TD(tcg_env, cpu_gpr[a->ra], cpu_gpr[a->rb], t0);
1340 #else
1341 qemu_build_not_reached();
1342 #endif
1343 return true;
1344 }
1345
1346 static bool trans_TDI(DisasContext *ctx, arg_TDI *a)
1347 {
1348 REQUIRE_64BIT(ctx);
1349 #if defined(TARGET_PPC64)
1350 TCGv t0;
1351 TCGv_i32 t1;
1352
1353 if (check_unconditional_trap(ctx, a->rt)) {
1354 return true;
1355 }
1356 t0 = tcg_constant_tl(a->si);
1357 t1 = tcg_constant_i32(a->rt);
1358 gen_helper_TD(tcg_env, cpu_gpr[a->ra], t0, t1);
1359 #else
1360 qemu_build_not_reached();
1361 #endif
1362 return true;
1363 }
1364
1365 static bool trans_INVALID(DisasContext *ctx, arg_INVALID *a)
1366 {
1367 gen_invalid(ctx);
1368 return true;
1369 }
1370
1371 static bool trans_PNOP(DisasContext *ctx, arg_PNOP *a)
1372 {
1373 return true;
1374 }
1375
1376 static bool do_set_bool_cond(DisasContext *ctx, arg_X_bi *a, bool neg, bool rev)
1377 {
1378 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1379 uint32_t mask = 0x08 >> (a->bi & 0x03);
1380 TCGCond cond = rev ? TCG_COND_EQ : TCG_COND_NE;
1381 TCGv temp = tcg_temp_new();
1382 TCGv zero = tcg_constant_tl(0);
1383
1384 tcg_gen_extu_i32_tl(temp, cpu_crf[a->bi >> 2]);
1385 tcg_gen_andi_tl(temp, temp, mask);
1386 if (neg) {
1387 tcg_gen_negsetcond_tl(cond, cpu_gpr[a->rt], temp, zero);
1388 } else {
1389 tcg_gen_setcond_tl(cond, cpu_gpr[a->rt], temp, zero);
1390 }
1391 return true;
1392 }
1393
1394 TRANS(SETBC, do_set_bool_cond, false, false)
1395 TRANS(SETBCR, do_set_bool_cond, false, true)
1396 TRANS(SETNBC, do_set_bool_cond, true, false)
1397 TRANS(SETNBCR, do_set_bool_cond, true, true)
1398
1399 /*
1400 * Fixed-Point Logical Instructions
1401 */
1402
1403 static bool do_addi_(DisasContext *ctx, arg_D_ui *a, bool shift)
1404 {
1405 tcg_gen_andi_tl(cpu_gpr[a->ra], cpu_gpr[a->rt], shift ? a->ui << 16 : a->ui);
1406 gen_set_Rc0(ctx, cpu_gpr[a->ra]);
1407 return true;
1408 }
1409
1410 static bool do_ori(DisasContext *ctx, arg_D_ui *a, bool shift)
1411 {
1412 if (a->rt == a->ra && a->ui == 0) {
1413 /* NOP */
1414 return true;
1415 }
1416 tcg_gen_ori_tl(cpu_gpr[a->ra], cpu_gpr[a->rt], shift ? a->ui << 16 : a->ui);
1417 return true;
1418 }
1419
1420 static bool do_xori(DisasContext *ctx, arg_D_ui *a, bool shift)
1421 {
1422 if (a->rt == a->ra && a->ui == 0) {
1423 /* NOP */
1424 return true;
1425 }
1426 tcg_gen_xori_tl(cpu_gpr[a->ra], cpu_gpr[a->rt], shift ? a->ui << 16 : a->ui);
1427 return true;
1428 }
1429
1430 static bool do_logical1(DisasContext *ctx, arg_X_sa_rc *a,
1431 void (*helper)(TCGv, TCGv))
1432 {
1433 helper(cpu_gpr[a->ra], cpu_gpr[a->rs]);
1434 if (unlikely(a->rc)) {
1435 gen_set_Rc0(ctx, cpu_gpr[a->ra]);
1436 }
1437 return true;
1438 }
1439
1440 static bool do_logical2(DisasContext *ctx, arg_X_rc *a,
1441 void (*helper)(TCGv, TCGv, TCGv))
1442 {
1443 helper(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
1444 if (unlikely(a->rc)) {
1445 gen_set_Rc0(ctx, cpu_gpr[a->ra]);
1446 }
1447 return true;
1448 }
1449
1450 static bool trans_OR(DisasContext *ctx, arg_OR *a)
1451 {
1452 /* Optimisation for mr. ri case */
1453 if (a->rt != a->ra || a->rt != a->rb) {
1454 if (a->rt != a->rb) {
1455 tcg_gen_or_tl(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
1456 } else {
1457 tcg_gen_mov_tl(cpu_gpr[a->ra], cpu_gpr[a->rt]);
1458 }
1459 if (unlikely(a->rc)) {
1460 gen_set_Rc0(ctx, cpu_gpr[a->ra]);
1461 }
1462 } else if (unlikely(a->rc)) {
1463 gen_set_Rc0(ctx, cpu_gpr[a->rt]);
1464 #if defined(TARGET_PPC64)
1465 } else if (a->rt != 0) { /* 0 is nop */
1466 int prio = 0;
1467
1468 switch (a->rt) {
1469 case 1:
1470 /* Set process priority to low */
1471 prio = 2;
1472 break;
1473 case 6:
1474 /* Set process priority to medium-low */
1475 prio = 3;
1476 break;
1477 case 2:
1478 /* Set process priority to normal */
1479 prio = 4;
1480 break;
1481 #if !defined(CONFIG_USER_ONLY)
1482 case 31:
1483 if (!ctx->pr) {
1484 /* Set process priority to very low */
1485 prio = 1;
1486 }
1487 break;
1488 case 5:
1489 if (!ctx->pr) {
1490 /* Set process priority to medium-hight */
1491 prio = 5;
1492 }
1493 break;
1494 case 3:
1495 if (!ctx->pr) {
1496 /* Set process priority to high */
1497 prio = 6;
1498 }
1499 break;
1500 case 7:
1501 if (ctx->hv && !ctx->pr) {
1502 /* Set process priority to very high */
1503 prio = 7;
1504 }
1505 break;
1506 #endif
1507 default:
1508 break;
1509 }
1510 if (prio) {
1511 TCGv t0 = tcg_temp_new();
1512 gen_load_spr(t0, SPR_PPR);
1513 tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
1514 tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
1515 gen_store_spr(SPR_PPR, t0);
1516 }
1517 #if !defined(CONFIG_USER_ONLY)
1518 /*
1519 * Pause out of TCG otherwise spin loops with smt_low eat too
1520 * much CPU and the kernel hangs. This applies to all
1521 * encodings other than no-op, e.g., miso(rs=26), yield(27),
1522 * mdoio(29), mdoom(30), and all currently undefined.
1523 */
1524 gen_pause(ctx);
1525 #endif
1526 #endif
1527 }
1528
1529 return true;
1530 }
1531
1532 static bool trans_XOR(DisasContext *ctx, arg_XOR *a)
1533 {
1534 /* Optimisation for "set to zero" case */
1535 if (a->rt != a->rb) {
1536 tcg_gen_xor_tl(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
1537 } else {
1538 tcg_gen_movi_tl(cpu_gpr[a->ra], 0);
1539 }
1540 if (unlikely(a->rc)) {
1541 gen_set_Rc0(ctx, cpu_gpr[a->ra]);
1542 }
1543 return true;
1544 }
1545
1546 static bool trans_CMPB(DisasContext *ctx, arg_CMPB *a)
1547 {
1548 REQUIRE_INSNS_FLAGS2(ctx, ISA205);
1549 gen_helper_CMPB(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
1550 return true;
1551 }
1552
1553 static bool do_cntzw(DisasContext *ctx, arg_X_sa_rc *a,
1554 void (*helper)(TCGv_i32, TCGv_i32, uint32_t))
1555 {
1556 TCGv_i32 t = tcg_temp_new_i32();
1557
1558 tcg_gen_trunc_tl_i32(t, cpu_gpr[a->rs]);
1559 helper(t, t, 32);
1560 tcg_gen_extu_i32_tl(cpu_gpr[a->ra], t);
1561
1562 if (unlikely(a->rc)) {
1563 gen_set_Rc0(ctx, cpu_gpr[a->ra]);
1564 }
1565 return true;
1566 }
1567
1568 #if defined(TARGET_PPC64)
1569 static bool do_cntzd(DisasContext *ctx, arg_X_sa_rc *a,
1570 void (*helper)(TCGv_i64, TCGv_i64, uint64_t))
1571 {
1572 helper(cpu_gpr[a->ra], cpu_gpr[a->rs], 64);
1573 if (unlikely(a->rc)) {
1574 gen_set_Rc0(ctx, cpu_gpr[a->ra]);
1575 }
1576 return true;
1577 }
1578 #endif
1579
1580 static bool trans_CNTLZD(DisasContext *ctx, arg_CNTLZD *a)
1581 {
1582 REQUIRE_64BIT(ctx);
1583 #if defined(TARGET_PPC64)
1584 do_cntzd(ctx, a, tcg_gen_clzi_i64);
1585 #else
1586 qemu_build_not_reached();
1587 #endif
1588 return true;
1589 }
1590
1591 static bool trans_CNTTZD(DisasContext *ctx, arg_CNTTZD *a)
1592 {
1593 REQUIRE_64BIT(ctx);
1594 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
1595 #if defined(TARGET_PPC64)
1596 do_cntzd(ctx, a, tcg_gen_ctzi_i64);
1597 #else
1598 qemu_build_not_reached();
1599 #endif
1600 return true;
1601 }
1602
1603 static bool trans_POPCNTB(DisasContext *ctx, arg_POPCNTB *a)
1604 {
1605 REQUIRE_INSNS_FLAGS(ctx, POPCNTB);
1606 gen_helper_POPCNTB(cpu_gpr[a->ra], cpu_gpr[a->rs]);
1607 return true;
1608 }
1609
1610 static bool trans_POPCNTW(DisasContext *ctx, arg_POPCNTW *a)
1611 {
1612 REQUIRE_INSNS_FLAGS(ctx, POPCNTWD);
1613 #if defined(TARGET_PPC64)
1614 gen_helper_POPCNTW(cpu_gpr[a->ra], cpu_gpr[a->rs]);
1615 #else
1616 tcg_gen_ctpop_i32(cpu_gpr[a->ra], cpu_gpr[a->rs]);
1617 #endif
1618 return true;
1619 }
1620
1621 static bool trans_POPCNTD(DisasContext *ctx, arg_POPCNTD *a)
1622 {
1623 REQUIRE_64BIT(ctx);
1624 REQUIRE_INSNS_FLAGS(ctx, POPCNTWD);
1625 #if defined(TARGET_PPC64)
1626 tcg_gen_ctpop_i64(cpu_gpr[a->ra], cpu_gpr[a->rs]);
1627 #else
1628 qemu_build_not_reached();
1629 #endif
1630 return true;
1631 }
1632
1633 static bool trans_PRTYW(DisasContext *ctx, arg_PRTYW *a)
1634 {
1635 TCGv ra = cpu_gpr[a->ra];
1636 TCGv rs = cpu_gpr[a->rs];
1637 TCGv t0 = tcg_temp_new();
1638
1639 REQUIRE_INSNS_FLAGS2(ctx, ISA205);
1640 tcg_gen_shri_tl(t0, rs, 16);
1641 tcg_gen_xor_tl(ra, rs, t0);
1642 tcg_gen_shri_tl(t0, ra, 8);
1643 tcg_gen_xor_tl(ra, ra, t0);
1644 tcg_gen_andi_tl(ra, ra, (target_ulong)0x100000001ULL);
1645 return true;
1646 }
1647
1648 static bool trans_PRTYD(DisasContext *ctx, arg_PRTYD *a)
1649 {
1650 TCGv ra = cpu_gpr[a->ra];
1651 TCGv rs = cpu_gpr[a->rs];
1652 TCGv t0 = tcg_temp_new();
1653
1654 REQUIRE_64BIT(ctx);
1655 REQUIRE_INSNS_FLAGS2(ctx, ISA205);
1656 tcg_gen_shri_tl(t0, rs, 32);
1657 tcg_gen_xor_tl(ra, rs, t0);
1658 tcg_gen_shri_tl(t0, ra, 16);
1659 tcg_gen_xor_tl(ra, ra, t0);
1660 tcg_gen_shri_tl(t0, ra, 8);
1661 tcg_gen_xor_tl(ra, ra, t0);
1662 tcg_gen_andi_tl(ra, ra, 1);
1663 return true;
1664 }
1665
1666 static bool trans_BPERMD(DisasContext *ctx, arg_BPERMD *a)
1667 {
1668 REQUIRE_64BIT(ctx);
1669 REQUIRE_INSNS_FLAGS2(ctx, PERM_ISA206);
1670 #if defined(TARGET_PPC64)
1671 gen_helper_BPERMD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
1672 #else
1673 qemu_build_not_reached();
1674 #endif
1675 return true;
1676 }
1677
1678 static bool trans_CFUGED(DisasContext *ctx, arg_X *a)
1679 {
1680 REQUIRE_64BIT(ctx);
1681 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1682 #if defined(TARGET_PPC64)
1683 gen_helper_CFUGED(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
1684 #else
1685 qemu_build_not_reached();
1686 #endif
1687 return true;
1688 }
1689
1690 static void do_cntzdm(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 mask, int64_t trail)
1691 {
1692 TCGv_i64 t0, t1;
1693
1694 t0 = tcg_temp_new_i64();
1695 t1 = tcg_temp_new_i64();
1696
1697 tcg_gen_and_i64(t0, src, mask);
1698 if (trail) {
1699 tcg_gen_ctzi_i64(t0, t0, -1);
1700 } else {
1701 tcg_gen_clzi_i64(t0, t0, -1);
1702 }
1703
1704 tcg_gen_setcondi_i64(TCG_COND_NE, t1, t0, -1);
1705 tcg_gen_andi_i64(t0, t0, 63);
1706 tcg_gen_xori_i64(t0, t0, 63);
1707 if (trail) {
1708 tcg_gen_shl_i64(t0, mask, t0);
1709 tcg_gen_shl_i64(t0, t0, t1);
1710 } else {
1711 tcg_gen_shr_i64(t0, mask, t0);
1712 tcg_gen_shr_i64(t0, t0, t1);
1713 }
1714
1715 tcg_gen_ctpop_i64(dst, t0);
1716 }
1717
1718 static bool trans_CNTLZDM(DisasContext *ctx, arg_X *a)
1719 {
1720 REQUIRE_64BIT(ctx);
1721 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1722 #if defined(TARGET_PPC64)
1723 do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], false);
1724 #else
1725 qemu_build_not_reached();
1726 #endif
1727 return true;
1728 }
1729
1730 static bool trans_CNTTZDM(DisasContext *ctx, arg_X *a)
1731 {
1732 REQUIRE_64BIT(ctx);
1733 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1734 #if defined(TARGET_PPC64)
1735 do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], true);
1736 #else
1737 qemu_build_not_reached();
1738 #endif
1739 return true;
1740 }
1741
1742 static bool trans_PDEPD(DisasContext *ctx, arg_X *a)
1743 {
1744 REQUIRE_64BIT(ctx);
1745 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1746 #if defined(TARGET_PPC64)
1747 gen_helper_PDEPD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
1748 #else
1749 qemu_build_not_reached();
1750 #endif
1751 return true;
1752 }
1753
1754 static bool trans_PEXTD(DisasContext *ctx, arg_X *a)
1755 {
1756 REQUIRE_64BIT(ctx);
1757 REQUIRE_INSNS_FLAGS2(ctx, ISA310);
1758 #if defined(TARGET_PPC64)
1759 gen_helper_PEXTD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
1760 #else
1761 qemu_build_not_reached();
1762 #endif
1763 return true;
1764 }
1765
1766 TRANS(ANDI_, do_addi_, false);
1767 TRANS(ANDIS_, do_addi_, true);
1768 TRANS(ORI, do_ori, false);
1769 TRANS(ORIS, do_ori, true);
1770 TRANS(XORI, do_xori, false);
1771 TRANS(XORIS, do_xori, true);
1772
1773 TRANS(AND, do_logical2, tcg_gen_and_tl);
1774 TRANS(ANDC, do_logical2, tcg_gen_andc_tl);
1775 TRANS(NAND, do_logical2, tcg_gen_nand_tl);
1776 TRANS(ORC, do_logical2, tcg_gen_orc_tl);
1777 TRANS(NOR, do_logical2, tcg_gen_nor_tl);
1778 TRANS(EQV, do_logical2, tcg_gen_eqv_tl);
1779 TRANS(EXTSB, do_logical1, tcg_gen_ext8s_tl);
1780 TRANS(EXTSH, do_logical1, tcg_gen_ext16s_tl);
1781
1782 TRANS(CNTLZW, do_cntzw, tcg_gen_clzi_i32);
1783 TRANS_FLAGS2(ISA300, CNTTZW, do_cntzw, tcg_gen_ctzi_i32);
1784
1785 TRANS64(EXTSW, do_logical1, tcg_gen_ext32s_tl);
1786
1787 static bool trans_ADDG6S(DisasContext *ctx, arg_X *a)
1788 {
1789 const target_ulong carry_bits = (target_ulong)-1 / 0xf;
1790 TCGv in1, in2, carryl, carryh, tmp;
1791 TCGv zero = tcg_constant_tl(0);
1792
1793 REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
1794
1795 in1 = cpu_gpr[a->ra];
1796 in2 = cpu_gpr[a->rb];
1797 tmp = tcg_temp_new();
1798 carryl = tcg_temp_new();
1799 carryh = tcg_temp_new();
1800
1801 /* Addition with carry. */
1802 tcg_gen_add2_tl(carryl, carryh, in1, zero, in2, zero);
1803 /* Addition without carry. */
1804 tcg_gen_xor_tl(tmp, in1, in2);
1805 /* Difference between the two is carry in to each bit. */
1806 tcg_gen_xor_tl(carryl, carryl, tmp);
1807
1808 /*
1809 * The carry-out that we're looking for is the carry-in to
1810 * the next nibble. Shift the double-word down one nibble,
1811 * which puts all of the bits back into one word.
1812 */
1813 tcg_gen_extract2_tl(carryl, carryl, carryh, 4);
1814
1815 /* Invert, isolate the carry bits, and produce 6's. */
1816 tcg_gen_andc_tl(carryl, tcg_constant_tl(carry_bits), carryl);
1817 tcg_gen_muli_tl(cpu_gpr[a->rt], carryl, 6);
1818 return true;
1819 }
1820
1821 static bool trans_CDTBCD(DisasContext *ctx, arg_X_sa *a)
1822 {
1823 REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
1824 gen_helper_CDTBCD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
1825 return true;
1826 }
1827
1828 static bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a)
1829 {
1830 REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
1831 gen_helper_CBCDTD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
1832 return true;
1833 }
1834
1835 static bool do_hash(DisasContext *ctx, arg_X *a, bool priv,
1836 void (*helper)(TCGv_ptr, TCGv, TCGv, TCGv))
1837 {
1838 TCGv ea;
1839
1840 if (!(ctx->insns_flags2 & PPC2_ISA310)) {
1841 /* if version is before v3.1, this operation is a nop */
1842 return true;
1843 }
1844
1845 if (priv) {
1846 /* if instruction is privileged but the context is in user space */
1847 REQUIRE_SV(ctx);
1848 }
1849
1850 if (unlikely(a->ra == 0)) {
1851 /* if RA=0, the instruction form is invalid */
1852 gen_invalid(ctx);
1853 return true;
1854 }
1855
1856 ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->rt));
1857 helper(tcg_env, ea, cpu_gpr[a->ra], cpu_gpr[a->rb]);
1858 return true;
1859 }
1860
1861 TRANS(HASHST, do_hash, false, gen_helper_HASHST)
1862 TRANS(HASHCHK, do_hash, false, gen_helper_HASHCHK)
1863 TRANS(HASHSTP, do_hash, true, gen_helper_HASHSTP)
1864 TRANS(HASHCHKP, do_hash, true, gen_helper_HASHCHKP)
1865
1866 static bool trans_SLW(DisasContext *ctx, arg_SLW *a)
1867 {
1868 TCGv t0, t1;
1869
1870 t0 = tcg_temp_new();
1871 /* AND rt with a mask that is 0 when rB >= 0x20 */
1872 #if defined(TARGET_PPC64)
1873 tcg_gen_shli_tl(t0, cpu_gpr[a->rb], 0x3a);
1874 tcg_gen_sari_tl(t0, t0, 0x3f);
1875 #else
1876 tcg_gen_shli_tl(t0, cpu_gpr[a->rb], 0x1a);
1877 tcg_gen_sari_tl(t0, t0, 0x1f);
1878 #endif
1879 tcg_gen_andc_tl(t0, cpu_gpr[a->rt], t0);
1880 t1 = tcg_temp_new();
1881 tcg_gen_andi_tl(t1, cpu_gpr[a->rb], 0x1f);
1882 tcg_gen_shl_tl(cpu_gpr[a->ra], t0, t1);
1883 tcg_gen_ext32u_tl(cpu_gpr[a->ra], cpu_gpr[a->ra]);
1884 if (unlikely(a->rc)) {
1885 gen_set_Rc0(ctx, cpu_gpr[a->ra]);
1886 }
1887 return true;
1888 }
1889
1890 static bool trans_SRW(DisasContext *ctx, arg_SRW *a)
1891 {
1892 TCGv t0, t1;
1893
1894 t0 = tcg_temp_new();
1895 /* AND rt with a mask that is 0 when rB >= 0x20 */
1896 #if defined(TARGET_PPC64)
1897 tcg_gen_shli_tl(t0, cpu_gpr[a->rb], 0x3a);
1898 tcg_gen_sari_tl(t0, t0, 0x3f);
1899 #else
1900 tcg_gen_shli_tl(t0, cpu_gpr[a->rb], 0x1a);
1901 tcg_gen_sari_tl(t0, t0, 0x1f);
1902 #endif
1903 tcg_gen_andc_tl(t0, cpu_gpr[a->rt], t0);
1904 tcg_gen_ext32u_tl(t0, t0);
1905 t1 = tcg_temp_new();
1906 tcg_gen_andi_tl(t1, cpu_gpr[a->rb], 0x1f);
1907 tcg_gen_shr_tl(cpu_gpr[a->ra], t0, t1);
1908 if (unlikely(a->rc)) {
1909 gen_set_Rc0(ctx, cpu_gpr[a->ra]);
1910 }
1911 return true;
1912 }
1913
1914 /* sraw & sraw. */
1915 static bool trans_SRAW(DisasContext *ctx, arg_SRAW *a)
1916 {
1917 gen_helper_SRAW(cpu_gpr[a->ra], tcg_env,
1918 cpu_gpr[a->rt], cpu_gpr[a->rb]);
1919 if (unlikely(a->rc)) {
1920 gen_set_Rc0(ctx, cpu_gpr[a->ra]);
1921 }
1922 return true;
1923 }
1924
1925 /* srawi & srawi. */
1926 static bool trans_SRAWI(DisasContext *ctx, arg_SRAWI *a)
1927 {
1928 TCGv dst = cpu_gpr[a->ra];
1929 TCGv src = cpu_gpr[a->rt];
1930 if (a->rb == 0) {
1931 tcg_gen_ext32s_tl(dst, src);
1932 tcg_gen_movi_tl(cpu_ca, 0);
1933 if (is_isa300(ctx)) {
1934 tcg_gen_movi_tl(cpu_ca32, 0);
1935 }
1936 } else {
1937 TCGv t0;
1938 tcg_gen_ext32s_tl(dst, src);
1939 tcg_gen_andi_tl(cpu_ca, dst, (1ULL << a->rb) - 1);
1940 t0 = tcg_temp_new();
1941 tcg_gen_sari_tl(t0, dst, TARGET_LONG_BITS - 1);
1942 tcg_gen_and_tl(cpu_ca, cpu_ca, t0);
1943 tcg_gen_setcondi_tl(TCG_COND_NE, cpu_ca, cpu_ca, 0);
1944 if (is_isa300(ctx)) {
1945 tcg_gen_mov_tl(cpu_ca32, cpu_ca);
1946 }
1947 tcg_gen_sari_tl(dst, dst, a->rb);
1948 }
1949 if (unlikely(a->rc)) {
1950 gen_set_Rc0(ctx, dst);
1951 }
1952 return true;
1953 }
1954
1955 static bool trans_RLWIMI(DisasContext *ctx, arg_RLWIMI *a)
1956 {
1957 TCGv t_ra = cpu_gpr[a->ra];
1958 TCGv t_rs = cpu_gpr[a->rs];
1959 int mb = a->mb;
1960 int me = a->me;
1961
1962 if (a->sh == (31 - me) && mb <= me) {
1963 tcg_gen_deposit_tl(t_ra, t_ra, t_rs, a->sh, me - mb + 1);
1964 } else {
1965 target_ulong mask;
1966 bool mask_in_32b = true;
1967 TCGv t1;
1968
1969 #if defined(TARGET_PPC64)
1970 mb += 32;
1971 me += 32;
1972 #endif
1973 mask = MASK(mb, me);
1974
1975 #if defined(TARGET_PPC64)
1976 if (mask > 0xffffffffu) {
1977 mask_in_32b = false;
1978 }
1979 #endif
1980 t1 = tcg_temp_new();
1981 if (mask_in_32b) {
1982 TCGv_i32 t0 = tcg_temp_new_i32();
1983 tcg_gen_trunc_tl_i32(t0, t_rs);
1984 tcg_gen_rotli_i32(t0, t0, a->sh);
1985 tcg_gen_extu_i32_tl(t1, t0);
1986 } else {
1987 #if defined(TARGET_PPC64)
1988 tcg_gen_deposit_i64(t1, t_rs, t_rs, 32, 32);
1989 tcg_gen_rotli_i64(t1, t1, a->sh);
1990 #else
1991 g_assert_not_reached();
1992 #endif
1993 }
1994
1995 tcg_gen_andi_tl(t1, t1, mask);
1996 tcg_gen_andi_tl(t_ra, t_ra, ~mask);
1997 tcg_gen_or_tl(t_ra, t_ra, t1);
1998 }
1999 if (unlikely(a->rc)) {
2000 gen_set_Rc0(ctx, t_ra);
2001 }
2002 return true;
2003 }
2004
2005 static bool trans_RLWINM(DisasContext *ctx, arg_RLWINM *a)
2006 {
2007 TCGv t_ra = cpu_gpr[a->ra];
2008 TCGv t_rs = cpu_gpr[a->rs];
2009 int me = a->me;
2010 int mb = a->mb;
2011 int len = me - mb + 1;
2012 int rsh = (32 - a->sh) & 31;
2013
2014 if (a->sh != 0 && len > 0 && me == (31 - a->sh)) {
2015 tcg_gen_deposit_z_tl(t_ra, t_rs, a->sh, len);
2016 } else if (me == 31 && rsh + len <= 32) {
2017 tcg_gen_extract_tl(t_ra, t_rs, rsh, len);
2018 } else {
2019 target_ulong mask;
2020 bool mask_in_32b = true;
2021 #if defined(TARGET_PPC64)
2022 mb += 32;
2023 me += 32;
2024 #endif
2025 mask = MASK(mb, me);
2026 #if defined(TARGET_PPC64)
2027 if (mask > 0xffffffffu) {
2028 mask_in_32b = false;
2029 }
2030 #endif
2031 if (mask_in_32b) {
2032 if (a->sh == 0) {
2033 tcg_gen_andi_tl(t_ra, t_rs, mask);
2034 } else {
2035 TCGv_i32 t0 = tcg_temp_new_i32();
2036 tcg_gen_trunc_tl_i32(t0, t_rs);
2037 tcg_gen_rotli_i32(t0, t0, a->sh);
2038 tcg_gen_andi_i32(t0, t0, mask);
2039 tcg_gen_extu_i32_tl(t_ra, t0);
2040 }
2041 } else {
2042 #if defined(TARGET_PPC64)
2043 tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);
2044 tcg_gen_rotli_i64(t_ra, t_ra, a->sh);
2045 tcg_gen_andi_i64(t_ra, t_ra, mask);
2046 #else
2047 g_assert_not_reached();
2048 #endif
2049 }
2050 }
2051 if (unlikely(a->rc)) {
2052 gen_set_Rc0(ctx, t_ra);
2053 }
2054 return true;
2055 }
2056
2057 static void do_fetch_inc_conditional(DisasContext *ctx, MemOp memop,
2058 TCGv EA, int rt,
2059 TCGCond cond, int addend)
2060 {
2061 TCGv t = tcg_temp_new();
2062 TCGv t2 = tcg_temp_new();
2063 TCGv u = tcg_temp_new();
2064
2065 tcg_gen_qemu_ld_tl(t, EA, ctx->mem_idx, memop);
2066 tcg_gen_addi_tl(t2, EA, memop_size(memop));
2067 tcg_gen_qemu_ld_tl(t2, t2, ctx->mem_idx, memop);
2068 tcg_gen_addi_tl(u, t, addend);
2069
2070 /* mem(EA,s) = (t cond t2 ? u = t + addend : t) */
2071 tcg_gen_movcond_tl(cond, u, t, t2, u, t);
2072 tcg_gen_qemu_st_tl(u, EA, ctx->mem_idx, memop);
2073
2074 /* RT = (t cond t2 ? t : 1<<(s*8-1)) */
2075 tcg_gen_movcond_tl(cond, cpu_gpr[rt], t, t2, t,
2076 tcg_constant_tl(1 << (memop_size(memop) * 8 - 1)));
2077 }
2078
2079 /*
2080 * Fixed-Point Atomic Load/Store Instructions
2081 *
2082 * In the X-form encoding the RB field carries the Function Code (FC)
2083 * that selects the atomic operation. EA is computed from RA alone.
2084 */
2085 static bool do_ld_atomic(DisasContext *ctx, arg_X *a, MemOp memop)
2086 {
2087 TCGv EA, dst, src;
2088 bool need_serial;
2089
2090 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
2091
2092 EA = do_ea_calc(ctx, a->ra, tcg_constant_tl(0));
2093 dst = cpu_gpr[a->rt];
2094 src = cpu_gpr[(a->rt + 1) & 31];
2095
2096 need_serial = false;
2097 memop |= MO_ALIGN;
2098 switch (a->rb) {
2099 case 0: /* Fetch and add */
2100 tcg_gen_atomic_fetch_add_tl(dst, EA, src, ctx->mem_idx, memop);
2101 break;
2102 case 1: /* Fetch and xor */
2103 tcg_gen_atomic_fetch_xor_tl(dst, EA, src, ctx->mem_idx, memop);
2104 break;
2105 case 2: /* Fetch and or */
2106 tcg_gen_atomic_fetch_or_tl(dst, EA, src, ctx->mem_idx, memop);
2107 break;
2108 case 3: /* Fetch and 'and' */
2109 tcg_gen_atomic_fetch_and_tl(dst, EA, src, ctx->mem_idx, memop);
2110 break;
2111 case 4: /* Fetch and max unsigned */
2112 tcg_gen_atomic_fetch_umax_tl(dst, EA, src, ctx->mem_idx, memop);
2113 break;
2114 case 5: /* Fetch and max signed */
2115 tcg_gen_atomic_fetch_smax_tl(dst, EA, src, ctx->mem_idx, memop);
2116 break;
2117 case 6: /* Fetch and min unsigned */
2118 tcg_gen_atomic_fetch_umin_tl(dst, EA, src, ctx->mem_idx, memop);
2119 break;
2120 case 7: /* Fetch and min signed */
2121 tcg_gen_atomic_fetch_smin_tl(dst, EA, src, ctx->mem_idx, memop);
2122 break;
2123 case 8: /* Swap */
2124 tcg_gen_atomic_xchg_tl(dst, EA, src, ctx->mem_idx, memop);
2125 break;
2126
2127 case 16: /* Compare and swap not equal */
2128 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
2129 need_serial = true;
2130 } else {
2131 TCGv t0 = tcg_temp_new();
2132 TCGv t1 = tcg_temp_new();
2133
2134 tcg_gen_qemu_ld_tl(t0, EA, ctx->mem_idx, memop);
2135 if ((memop & MO_SIZE) == MO_64 || TARGET_LONG_BITS == 32) {
2136 tcg_gen_mov_tl(t1, src);
2137 } else {
2138 tcg_gen_ext32u_tl(t1, src);
2139 }
2140 tcg_gen_movcond_tl(TCG_COND_NE, t1, t0, t1,
2141 cpu_gpr[(a->rt + 2) & 31], t0);
2142 tcg_gen_qemu_st_tl(t1, EA, ctx->mem_idx, memop);
2143 tcg_gen_mov_tl(dst, t0);
2144 }
2145 break;
2146
2147 case 24: /* Fetch and increment bounded */
2148 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
2149 need_serial = true;
2150 } else {
2151 do_fetch_inc_conditional(ctx, memop, EA, a->rt, TCG_COND_NE, 1);
2152 }
2153 break;
2154 case 25: /* Fetch and increment equal */
2155 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
2156 need_serial = true;
2157 } else {
2158 do_fetch_inc_conditional(ctx, memop, EA, a->rt, TCG_COND_EQ, 1);
2159 }
2160 break;
2161 case 28: /* Fetch and decrement bounded */
2162 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
2163 need_serial = true;
2164 } else {
2165 do_fetch_inc_conditional(ctx, memop, EA, a->rt, TCG_COND_NE, -1);
2166 }
2167 break;
2168
2169 default:
2170 /* invoke data storage error handler */
2171 gen_exception_err(ctx, POWERPC_EXCP_DSI, POWERPC_EXCP_INVAL);
2172 }
2173
2174 if (need_serial) {
2175 /* Restart with exclusive lock. */
2176 gen_helper_exit_atomic(tcg_env);
2177 ctx->base.is_jmp = DISAS_NORETURN;
2178 }
2179 return true;
2180 }
2181
2182 static bool do_st_atomic(DisasContext *ctx, arg_X *a, MemOp memop)
2183 {
2184 TCGv EA, src, discard;
2185
2186 REQUIRE_INSNS_FLAGS2(ctx, ISA300);
2187
2188 EA = do_ea_calc(ctx, a->ra, tcg_constant_tl(0));
2189 src = cpu_gpr[a->rt];
2190 discard = tcg_temp_new();
2191
2192 memop |= MO_ALIGN;
2193 switch (a->rb) {
2194 case 0: /* add and Store */
2195 tcg_gen_atomic_add_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
2196 break;
2197 case 1: /* xor and Store */
2198 tcg_gen_atomic_xor_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
2199 break;
2200 case 2: /* Or and Store */
2201 tcg_gen_atomic_or_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
2202 break;
2203 case 3: /* 'and' and Store */
2204 tcg_gen_atomic_and_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
2205 break;
2206 case 4: /* Store max unsigned */
2207 tcg_gen_atomic_umax_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
2208 break;
2209 case 5: /* Store max signed */
2210 tcg_gen_atomic_smax_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
2211 break;
2212 case 6: /* Store min unsigned */
2213 tcg_gen_atomic_umin_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
2214 break;
2215 case 7: /* Store min signed */
2216 tcg_gen_atomic_smin_fetch_tl(discard, EA, src, ctx->mem_idx, memop);
2217 break;
2218 case 24: /* Store twin */
2219 if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
2220 /* Restart with exclusive lock. */
2221 gen_helper_exit_atomic(tcg_env);
2222 ctx->base.is_jmp = DISAS_NORETURN;
2223 } else {
2224 TCGv t = tcg_temp_new();
2225 TCGv t2 = tcg_temp_new();
2226 TCGv s = tcg_temp_new();
2227 TCGv s2 = tcg_temp_new();
2228 TCGv ea_plus_s = tcg_temp_new();
2229
2230 tcg_gen_qemu_ld_tl(t, EA, ctx->mem_idx, memop);
2231 tcg_gen_addi_tl(ea_plus_s, EA, memop_size(memop));
2232 tcg_gen_qemu_ld_tl(t2, ea_plus_s, ctx->mem_idx, memop);
2233 tcg_gen_movcond_tl(TCG_COND_EQ, s, t, t2, src, t);
2234 tcg_gen_movcond_tl(TCG_COND_EQ, s2, t, t2, src, t2);
2235 tcg_gen_qemu_st_tl(s, EA, ctx->mem_idx, memop);
2236 tcg_gen_qemu_st_tl(s2, ea_plus_s, ctx->mem_idx, memop);
2237 }
2238 break;
2239 default:
2240 /* invoke data storage error handler */
2241 gen_exception_err(ctx, POWERPC_EXCP_DSI, POWERPC_EXCP_INVAL);
2242 }
2243 return true;
2244 }
2245
2246 TRANS(LWAT, do_ld_atomic, DEF_MEMOP(MO_UL))
2247 TRANS(STWAT, do_st_atomic, DEF_MEMOP(MO_UL))
2248
2249 static bool trans_LDAT(DisasContext *ctx, arg_LDAT *a)
2250 {
2251 REQUIRE_64BIT(ctx);
2252 #if defined(TARGET_PPC64)
2253 return do_ld_atomic(ctx, a, DEF_MEMOP(MO_UQ));
2254 #else
2255 qemu_build_not_reached();
2256 #endif
2257 return true;
2258 }
2259
2260 static bool trans_STDAT(DisasContext *ctx, arg_STDAT *a)
2261 {
2262 REQUIRE_64BIT(ctx);
2263 #if defined(TARGET_PPC64)
2264 return do_st_atomic(ctx, a, DEF_MEMOP(MO_UQ));
2265 #else
2266 qemu_build_not_reached();
2267 #endif
2268 return true;
2269 }