master
inc 613 lines 17 KB
Raw
1 /*
2 * IBM PPE Instructions
3 *
4 * Copyright (c) 2025, IBM Corporation.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9
10 static bool vdr_is_valid(uint32_t vdr)
11 {
12 const uint32_t valid_bitmap = 0xf00003ff;
13 return !!((1ul << (vdr & 0x1f)) & valid_bitmap);
14 }
15
16 static bool ppe_gpr_is_valid(uint32_t reg)
17 {
18 const uint32_t valid_bitmap = 0xf00027ff;
19 return !!((1ul << (reg & 0x1f)) & valid_bitmap);
20 }
21
22 #define CHECK_VDR(CTX, VDR) \
23 do { \
24 if (unlikely(!vdr_is_valid(VDR))) { \
25 gen_invalid(CTX); \
26 return true; \
27 } \
28 } while (0)
29
30 #define CHECK_PPE_GPR(CTX, REG) \
31 do { \
32 if (unlikely(!ppe_gpr_is_valid(REG))) { \
33 gen_invalid(CTX); \
34 return true; \
35 } \
36 } while (0)
37
38 #define VDR_PAIR_REG(VDR) (((VDR) + 1) & 0x1f)
39
40 #define CHECK_PPE_LEVEL(CTX, LVL) \
41 do { \
42 if (unlikely(!((CTX)->insns_flags2 & (LVL)))) { \
43 gen_invalid(CTX); \
44 return true; \
45 } \
46 } while (0)
47
48 static bool trans_LCXU(DisasContext *ctx, arg_LCXU *a)
49 {
50 int i;
51 TCGv base, EA;
52 TCGv lo, hi;
53 TCGv_i64 t8;
54 const uint8_t vd_list[] = {9, 7, 5, 3, 0};
55
56 if (unlikely(!is_ppe(ctx))) {
57 return false;
58 }
59 CHECK_PPE_LEVEL(ctx, PPC2_PPE42X);
60 CHECK_PPE_GPR(ctx, a->rt);
61
62 if (unlikely((a->rt != a->ra) || (a->ra == 0) || (a->si < 0xB))) {
63 gen_invalid(ctx);
64 return true;
65 }
66
67 EA = tcg_temp_new();
68 base = tcg_temp_new();
69
70 tcg_gen_addi_tl(base, cpu_gpr[a->ra], a->si * 8);
71 gen_store_spr(SPR_PPE42_EDR, base);
72
73 t8 = tcg_temp_new_i64();
74
75 tcg_gen_addi_tl(EA, base, -8);
76 tcg_gen_qemu_ld_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
77 tcg_gen_extr_i64_tl(cpu_gpr[31], cpu_gpr[30], t8);
78
79 tcg_gen_addi_tl(EA, EA, -8);
80 tcg_gen_qemu_ld_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
81 tcg_gen_extr_i64_tl(cpu_gpr[29], cpu_gpr[28], t8);
82
83 lo = tcg_temp_new();
84 hi = tcg_temp_new();
85
86 tcg_gen_addi_tl(EA, EA, -8);
87 tcg_gen_qemu_ld_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
88 tcg_gen_extr_i64_tl(lo, hi, t8);
89 gen_store_spr(SPR_SRR0, hi);
90 gen_store_spr(SPR_SRR1, lo);
91
92 tcg_gen_addi_tl(EA, EA, -8);
93 tcg_gen_qemu_ld_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
94 tcg_gen_extr_i64_tl(lo, hi, t8);
95 gen_set_xer(ctx, hi);
96 tcg_gen_mov_tl(cpu_ctr, lo);
97
98 for (i = 0; i < sizeof(vd_list); i++) {
99 int vd = vd_list[i];
100 tcg_gen_addi_tl(EA, EA, -8);
101 tcg_gen_qemu_ld_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
102 tcg_gen_extr_i64_tl(cpu_gpr[VDR_PAIR_REG(vd)], cpu_gpr[vd], t8);
103 }
104
105 tcg_gen_addi_tl(EA, EA, -8);
106 tcg_gen_qemu_ld_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
107 tcg_gen_extr_i64_tl(lo, hi, t8);
108 tcg_gen_shri_tl(hi, hi, 28);
109 tcg_gen_trunc_tl_i32(cpu_crf[0], hi);
110 gen_store_spr(SPR_SPRG0, lo);
111
112 tcg_gen_addi_tl(EA, base, 4);
113 tcg_gen_qemu_ld_tl(cpu_lr, EA, ctx->mem_idx, DEF_MEMOP(MO_32) | MO_ALIGN);
114 tcg_gen_mov_tl(cpu_gpr[a->ra], base);
115 return true;
116 }
117
118 static bool trans_LSKU(DisasContext *ctx, arg_LSKU *a)
119 {
120 int64_t n;
121 TCGv base, EA;
122 TCGv lo, hi;
123 TCGv_i64 t8;
124
125 if (unlikely(!is_ppe(ctx))) {
126 return false;
127 }
128
129 CHECK_PPE_LEVEL(ctx, PPC2_PPE42X);
130 CHECK_PPE_GPR(ctx, a->rt);
131
132 if (unlikely((a->rt != a->ra) || (a->ra == 0) ||
133 (a->si & PPC_BIT(0)) || (a->si == 0))) {
134 gen_invalid(ctx);
135 return true;
136 }
137
138 EA = tcg_temp_new();
139 base = tcg_temp_new();
140 gen_addr_register(ctx, base);
141
142
143 tcg_gen_addi_tl(base, base, a->si * 8);
144 gen_store_spr(SPR_PPE42_EDR, base);
145
146 n = a->si - 1;
147 t8 = tcg_temp_new_i64();
148 if (n > 0) {
149 tcg_gen_addi_tl(EA, base, -8);
150 tcg_gen_qemu_ld_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
151 hi = cpu_gpr[30];
152 lo = cpu_gpr[31];
153 tcg_gen_extr_i64_tl(lo, hi, t8);
154 }
155 if (n > 1) {
156 tcg_gen_addi_tl(EA, base, -16);
157 tcg_gen_qemu_ld_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
158 hi = cpu_gpr[28];
159 lo = cpu_gpr[29];
160 tcg_gen_extr_i64_tl(lo, hi, t8);
161 }
162 tcg_gen_addi_tl(EA, base, 4);
163 tcg_gen_qemu_ld_tl(cpu_lr, EA, ctx->mem_idx, DEF_MEMOP(MO_32) | MO_ALIGN);
164 tcg_gen_mov_tl(cpu_gpr[a->ra], base);
165 return true;
166 }
167
168 static bool trans_STCXU(DisasContext *ctx, arg_STCXU *a)
169 {
170 TCGv EA;
171 TCGv lo, hi;
172 TCGv_i64 t8;
173 int i;
174 const uint8_t vd_list[] = {9, 7, 5, 3, 0};
175
176 if (unlikely(!is_ppe(ctx))) {
177 return false;
178 }
179
180 CHECK_PPE_LEVEL(ctx, PPC2_PPE42X);
181 CHECK_PPE_GPR(ctx, a->rt);
182
183 if (unlikely((a->rt != a->ra) || (a->ra == 0) || !(a->si & PPC_BIT(0)))) {
184 gen_invalid(ctx);
185 return true;
186 }
187
188 EA = tcg_temp_new();
189 tcg_gen_addi_tl(EA, cpu_gpr[a->ra], 4);
190 tcg_gen_qemu_st_tl(cpu_lr, EA, ctx->mem_idx, DEF_MEMOP(MO_32) | MO_ALIGN);
191
192 gen_store_spr(SPR_PPE42_EDR, cpu_gpr[a->ra]);
193
194 t8 = tcg_temp_new_i64();
195
196 tcg_gen_concat_tl_i64(t8, cpu_gpr[31], cpu_gpr[30]);
197 tcg_gen_addi_tl(EA, cpu_gpr[a->ra], -8);
198 tcg_gen_qemu_st_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
199
200 tcg_gen_concat_tl_i64(t8, cpu_gpr[29], cpu_gpr[28]);
201 tcg_gen_addi_tl(EA, EA, -8);
202 tcg_gen_qemu_st_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
203
204 lo = tcg_temp_new();
205 hi = tcg_temp_new();
206
207 gen_load_spr(hi, SPR_SRR0);
208 gen_load_spr(lo, SPR_SRR1);
209 tcg_gen_concat_tl_i64(t8, lo, hi);
210 tcg_gen_addi_tl(EA, EA, -8);
211 tcg_gen_qemu_st_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
212
213 gen_get_xer(ctx, hi);
214 tcg_gen_mov_tl(lo, cpu_ctr);
215 tcg_gen_concat_tl_i64(t8, lo, hi);
216 tcg_gen_addi_tl(EA, EA, -8);
217 tcg_gen_qemu_st_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
218
219 for (i = 0; i < sizeof(vd_list); i++) {
220 int vd = vd_list[i];
221 tcg_gen_concat_tl_i64(t8, cpu_gpr[VDR_PAIR_REG(vd)], cpu_gpr[vd]);
222 tcg_gen_addi_tl(EA, EA, -8);
223 tcg_gen_qemu_st_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
224 }
225
226 gen_load_spr(lo, SPR_SPRG0);
227 tcg_gen_extu_i32_tl(hi, cpu_crf[0]);
228 tcg_gen_shli_tl(hi, hi, 28);
229 tcg_gen_concat_tl_i64(t8, lo, hi);
230 tcg_gen_addi_tl(EA, EA, -8);
231 tcg_gen_qemu_st_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
232
233 tcg_gen_addi_tl(EA, cpu_gpr[a->ra], a->si * 8);
234 tcg_gen_qemu_st_tl(cpu_gpr[a->rt], EA, ctx->mem_idx, DEF_MEMOP(MO_32) |
235 MO_ALIGN);
236 tcg_gen_mov_tl(cpu_gpr[a->ra], EA);
237 return true;
238 }
239
240 static bool trans_STSKU(DisasContext *ctx, arg_STSKU *a)
241 {
242 int64_t n;
243 TCGv base, EA;
244 TCGv lo, hi;
245 TCGv_i64 t8;
246
247 if (unlikely(!is_ppe(ctx))) {
248 return false;
249 }
250
251 CHECK_PPE_LEVEL(ctx, PPC2_PPE42X);
252 CHECK_PPE_GPR(ctx, a->rt);
253
254 if (unlikely((a->rt != a->ra) || (a->ra == 0) || !(a->si & PPC_BIT(0)))) {
255 gen_invalid(ctx);
256 return true;
257 }
258
259 EA = tcg_temp_new();
260 base = tcg_temp_new();
261 gen_addr_register(ctx, base);
262 tcg_gen_addi_tl(EA, base, 4);
263 tcg_gen_qemu_st_tl(cpu_lr, EA, ctx->mem_idx, DEF_MEMOP(MO_32) | MO_ALIGN);
264
265 gen_store_spr(SPR_PPE42_EDR, base);
266
267 n = ~(a->si);
268
269 t8 = tcg_temp_new_i64();
270 if (n > 0) {
271 hi = cpu_gpr[30];
272 lo = cpu_gpr[31];
273 tcg_gen_concat_tl_i64(t8, lo, hi);
274 tcg_gen_addi_tl(EA, base, -8);
275 tcg_gen_qemu_st_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
276 }
277 if (n > 1) {
278 hi = cpu_gpr[28];
279 lo = cpu_gpr[29];
280 tcg_gen_concat_tl_i64(t8, lo, hi);
281 tcg_gen_addi_tl(EA, base, -16);
282 tcg_gen_qemu_st_i64(t8, EA, ctx->mem_idx, DEF_MEMOP(MO_64) | MO_ALIGN);
283 }
284
285 tcg_gen_addi_tl(EA, base, a->si * 8);
286 tcg_gen_qemu_st_tl(cpu_gpr[a->rt], EA, ctx->mem_idx, DEF_MEMOP(MO_32) |
287 MO_ALIGN);
288 tcg_gen_mov_tl(cpu_gpr[a->ra], EA);
289 return true;
290 }
291
292 static bool do_ppe_ldst(DisasContext *ctx, int rt, int ra, TCGv disp,
293 bool update, bool store)
294 {
295 TCGv ea;
296 int rt_lo;
297 TCGv_i64 t8;
298
299 CHECK_VDR(ctx, rt);
300 CHECK_PPE_GPR(ctx, ra);
301 rt_lo = VDR_PAIR_REG(rt);
302 if (update && (ra == 0 || (!store && ((ra == rt) || (ra == rt_lo))))) {
303 gen_invalid(ctx);
304 return true;
305 }
306 gen_set_access_type(ctx, ACCESS_INT);
307
308 ea = do_ea_calc(ctx, ra, disp);
309 t8 = tcg_temp_new_i64();
310 if (store) {
311 tcg_gen_concat_tl_i64(t8, cpu_gpr[rt_lo], cpu_gpr[rt]);
312 tcg_gen_qemu_st_i64(t8, ea, ctx->mem_idx, DEF_MEMOP(MO_64));
313 } else {
314 tcg_gen_qemu_ld_i64(t8, ea, ctx->mem_idx, DEF_MEMOP(MO_64));
315 tcg_gen_extr_i64_tl(cpu_gpr[rt_lo], cpu_gpr[rt], t8);
316 }
317 if (update) {
318 tcg_gen_mov_tl(cpu_gpr[ra], ea);
319 }
320 return true;
321 }
322
323 static bool do_ppe_ldst_D(DisasContext *ctx, arg_D *a, bool update, bool store)
324 {
325 if (unlikely(!is_ppe(ctx))) {
326 return false;
327 }
328 return do_ppe_ldst(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update,
329 store);
330 }
331
332 static bool do_ppe_ldst_X(DisasContext *ctx, arg_X *a, bool store)
333 {
334 if (unlikely(!is_ppe(ctx))) {
335 return false;
336 }
337 CHECK_PPE_GPR(ctx, a->rb);
338 return do_ppe_ldst(ctx, a->rt, a->ra, cpu_gpr[a->rb], false, store);
339 }
340
341 TRANS(LVD, do_ppe_ldst_D, false, false)
342 TRANS(LVDU, do_ppe_ldst_D, true, false)
343 TRANS(STVD, do_ppe_ldst_D, false, true)
344 TRANS(STVDU, do_ppe_ldst_D, true, true)
345 TRANS(LVDX, do_ppe_ldst_X, false)
346 TRANS(STVDX, do_ppe_ldst_X, true)
347
348
349 static bool do_fcb(DisasContext *ctx, TCGv ra_val, TCGv rb_val, int bix,
350 int32_t bdx, bool s, bool px, bool lk)
351 {
352 TCGCond cond;
353 uint32_t mask;
354 TCGLabel *no_branch;
355 target_ulong dest;
356
357 /* Update CR0 */
358 gen_op_cmp32(ra_val, rb_val, s, 0);
359
360 if (lk) {
361 gen_setlr(ctx, ctx->base.pc_next);
362 }
363
364
365 mask = PPC_BIT32(28 + bix);
366 cond = (px) ? TCG_COND_TSTEQ : TCG_COND_TSTNE;
367 no_branch = gen_new_label();
368 dest = ctx->cia + bdx;
369
370 /* Do the branch if CR0[bix] == PX */
371 tcg_gen_brcondi_i32(cond, cpu_crf[0], mask, no_branch);
372 gen_goto_tb(ctx, 0, dest);
373 gen_set_label(no_branch);
374 gen_goto_tb(ctx, 1, ctx->base.pc_next);
375 ctx->base.is_jmp = DISAS_NORETURN;
376 return true;
377 }
378
379 static bool do_cmp_branch(DisasContext *ctx, arg_FCB_bix *a, bool s,
380 bool rb_is_gpr)
381 {
382 TCGv old_ra;
383 TCGv rb_val;
384
385 if (unlikely(!is_ppe(ctx))) {
386 return false;
387 }
388 CHECK_PPE_GPR(ctx, a->ra);
389 if (rb_is_gpr) {
390 CHECK_PPE_GPR(ctx, a->rb);
391 rb_val = cpu_gpr[a->rb];
392 } else {
393 rb_val = tcg_constant_tl(a->rb);
394 }
395 if (a->bix == 3) {
396 old_ra = tcg_temp_new();
397 tcg_gen_mov_tl(old_ra, cpu_gpr[a->ra]);
398 tcg_gen_sub_tl(cpu_gpr[a->ra], cpu_gpr[a->ra], rb_val);
399 return do_fcb(ctx, old_ra, rb_val, 2,
400 a->bdx, s, a->px, a->lk);
401 } else {
402 return do_fcb(ctx, cpu_gpr[a->ra], rb_val, a->bix,
403 a->bdx, s, a->px, a->lk);
404 }
405 }
406
407 TRANS(CMPWBC, do_cmp_branch, true, true)
408 TRANS(CMPLWBC, do_cmp_branch, false, true)
409 TRANS(CMPWIBC, do_cmp_branch, true, false)
410
411 static bool do_mask_branch(DisasContext *ctx, arg_FCB * a, bool invert,
412 bool update, bool rb_is_gpr)
413 {
414 TCGv r;
415 TCGv mask, shift;
416
417 if (unlikely(!is_ppe(ctx))) {
418 return false;
419 }
420 CHECK_PPE_GPR(ctx, a->ra);
421 if (rb_is_gpr) {
422 CHECK_PPE_GPR(ctx, a->rb);
423 mask = tcg_temp_new();
424 shift = tcg_temp_new();
425 tcg_gen_andi_tl(shift, cpu_gpr[a->rb], 0x1f);
426 tcg_gen_shr_tl(mask, tcg_constant_tl(0x80000000), shift);
427 if (invert) {
428 tcg_gen_not_tl(mask, mask);
429 }
430 } else {
431 target_ulong mask_const = PPC_BIT32(a->rb);
432 if (invert) {
433 mask_const = ~mask_const;
434 }
435 mask = tcg_constant_tl(mask_const);
436 }
437
438 /* apply mask to ra */
439 r = tcg_temp_new();
440 tcg_gen_and_tl(r, cpu_gpr[a->ra], mask);
441 if (update) {
442 tcg_gen_mov_tl(cpu_gpr[a->ra], r);
443 }
444 return do_fcb(ctx, r, tcg_constant_tl(0), 2,
445 a->bdx, false, a->px, a->lk);
446 }
447
448 TRANS(BNBWI, do_mask_branch, false, false, false)
449 TRANS(BNBW, do_mask_branch, false, false, true)
450 TRANS(CLRBWIBC, do_mask_branch, true, true, false)
451 TRANS(CLRBWBC, do_mask_branch, true, true, true)
452
453 static void gen_set_Rc0_i64(DisasContext *ctx, TCGv_i64 reg)
454 {
455 TCGv_i64 t0 = tcg_temp_new_i64();
456 TCGv_i64 t1 = tcg_temp_new_i64();
457 TCGv_i32 t = tcg_temp_new_i32();
458
459 tcg_gen_movi_i64(t0, CRF_EQ);
460 tcg_gen_movi_i64(t1, CRF_LT);
461 tcg_gen_movcond_i64(TCG_COND_LT, t0, reg, tcg_constant_i64(0), t1, t0);
462 tcg_gen_movi_i64(t1, CRF_GT);
463 tcg_gen_movcond_i64(TCG_COND_GT, t0, reg, tcg_constant_i64(0), t1, t0);
464 tcg_gen_extrl_i64_i32(t, t0);
465 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
466 tcg_gen_or_i32(cpu_crf[0], cpu_crf[0], t);
467 }
468
469 static bool do_shift64(DisasContext *ctx, arg_X_rc *a, bool left)
470 {
471 int rt_lo, ra_lo;
472 TCGv_i64 t0, t8;
473
474 if (unlikely(!is_ppe(ctx))) {
475 return false;
476 }
477 CHECK_PPE_LEVEL(ctx, PPC2_PPE42X);
478 CHECK_VDR(ctx, a->rt);
479 CHECK_VDR(ctx, a->ra);
480 CHECK_PPE_GPR(ctx, a->rb);
481 rt_lo = VDR_PAIR_REG(a->rt);
482 ra_lo = VDR_PAIR_REG(a->ra);
483 t8 = tcg_temp_new_i64();
484
485 /* AND rt with a mask that is 0 when rb >= 0x40 */
486 t0 = tcg_temp_new_i64();
487 tcg_gen_extu_tl_i64(t0, cpu_gpr[a->rb]);
488 tcg_gen_shli_i64(t0, t0, 0x39);
489 tcg_gen_sari_i64(t0, t0, 0x3f);
490
491 /* form 64bit value from two 32bit regs */
492 tcg_gen_concat_tl_i64(t8, cpu_gpr[rt_lo], cpu_gpr[a->rt]);
493
494 /* apply mask */
495 tcg_gen_andc_i64(t8, t8, t0);
496
497 /* do the shift */
498 tcg_gen_extu_tl_i64(t0, cpu_gpr[a->rb]);
499 tcg_gen_andi_i64(t0, t0, 0x3f);
500 if (left) {
501 tcg_gen_shl_i64(t8, t8, t0);
502 } else {
503 tcg_gen_shr_i64(t8, t8, t0);
504 }
505
506 /* split the 64bit word back into two 32bit regs */
507 tcg_gen_extr_i64_tl(cpu_gpr[ra_lo], cpu_gpr[a->ra], t8);
508
509 /* update CR0 if requested */
510 if (unlikely(a->rc != 0)) {
511 gen_set_Rc0_i64(ctx, t8);
512 }
513 return true;
514 }
515
516 TRANS(SRVD, do_shift64, false)
517 TRANS(SLVD, do_shift64, true)
518
519 static bool trans_DCBQ(DisasContext *ctx, arg_DCBQ * a)
520 {
521 if (unlikely(!is_ppe(ctx))) {
522 return false;
523 }
524
525 CHECK_PPE_GPR(ctx, a->rt);
526 CHECK_PPE_GPR(ctx, a->ra);
527 CHECK_PPE_GPR(ctx, a->rb);
528
529 /* No cache exists, so just set RT to 0 */
530 tcg_gen_movi_tl(cpu_gpr[a->rt], 0);
531 return true;
532 }
533
534 static bool trans_RLDIMI(DisasContext *ctx, arg_RLDIMI *a)
535 {
536 TCGv_i64 t_rs, t_ra;
537 int ra_lo, rs_lo;
538 uint32_t sh = a->sh;
539 uint32_t mb = a->mb;
540 uint32_t me = 63 - sh;
541
542 if (unlikely(!is_ppe(ctx))) {
543 return false;
544 }
545 CHECK_PPE_LEVEL(ctx, PPC2_PPE42X);
546 CHECK_VDR(ctx, a->rs);
547 CHECK_VDR(ctx, a->ra);
548
549 rs_lo = VDR_PAIR_REG(a->rs);
550 ra_lo = VDR_PAIR_REG(a->ra);
551
552 t_rs = tcg_temp_new_i64();
553 t_ra = tcg_temp_new_i64();
554
555 tcg_gen_concat_tl_i64(t_rs, cpu_gpr[rs_lo], cpu_gpr[a->rs]);
556 tcg_gen_concat_tl_i64(t_ra, cpu_gpr[ra_lo], cpu_gpr[a->ra]);
557
558 if (mb <= me) {
559 tcg_gen_deposit_i64(t_ra, t_ra, t_rs, sh, me - mb + 1);
560 } else {
561 uint64_t mask = mask_u64(mb, me);
562 TCGv_i64 t1 = tcg_temp_new_i64();
563
564 tcg_gen_rotli_i64(t1, t_rs, sh);
565 tcg_gen_andi_i64(t1, t1, mask);
566 tcg_gen_andi_i64(t_ra, t_ra, ~mask);
567 tcg_gen_or_i64(t_ra, t_ra, t1);
568 }
569
570 tcg_gen_extr_i64_tl(cpu_gpr[ra_lo], cpu_gpr[a->ra], t_ra);
571
572 if (unlikely(a->rc != 0)) {
573 gen_set_Rc0_i64(ctx, t_ra);
574 }
575 return true;
576 }
577
578
579 static bool gen_rldinm_i64(DisasContext *ctx, arg_MD *a, int mb, int me, int sh)
580 {
581 int len = me - mb + 1;
582 int rsh = (64 - sh) & 63;
583 int ra_lo, rs_lo;
584 TCGv_i64 t8;
585
586 if (unlikely(!is_ppe(ctx))) {
587 return false;
588 }
589 CHECK_PPE_LEVEL(ctx, PPC2_PPE42X);
590 CHECK_VDR(ctx, a->rs);
591 CHECK_VDR(ctx, a->ra);
592
593 rs_lo = VDR_PAIR_REG(a->rs);
594 ra_lo = VDR_PAIR_REG(a->ra);
595 t8 = tcg_temp_new_i64();
596 tcg_gen_concat_tl_i64(t8, cpu_gpr[rs_lo], cpu_gpr[a->rs]);
597 if (sh != 0 && len > 0 && me == (63 - sh)) {
598 tcg_gen_deposit_z_i64(t8, t8, sh, len);
599 } else if (me == 63 && rsh + len <= 64) {
600 tcg_gen_extract_i64(t8, t8, rsh, len);
601 } else {
602 tcg_gen_rotli_i64(t8, t8, sh);
603 tcg_gen_andi_i64(t8, t8, mask_u64(mb, me));
604 }
605 tcg_gen_extr_i64_tl(cpu_gpr[ra_lo], cpu_gpr[a->ra], t8);
606 if (unlikely(a->rc != 0)) {
607 gen_set_Rc0_i64(ctx, t8);
608 }
609 return true;
610 }
611
612 TRANS(RLDICL, gen_rldinm_i64, a->mb, 63, a->sh)
613 TRANS(RLDICR, gen_rldinm_i64, 0, a->mb, a->sh)