@@ -265,13 +265,20 @@ typedef enum S390Opcode {
265
265
RX_STC = 0x42 ,
266
266
RX_STH = 0x40 ,
267
267
268
+ VRIa_VGBM = 0xe744 ,
269
+ VRIa_VREPI = 0xe745 ,
270
+ VRIb_VGM = 0xe746 ,
271
+ VRIc_VREP = 0xe74d ,
272
+
268
273
VRRa_VLR = 0xe756 ,
274
+ VRRf_VLVGP = 0xe762 ,
269
275
270
276
VRSb_VLVG = 0xe722 ,
271
277
VRSc_VLGV = 0xe721 ,
272
278
273
279
VRX_VL = 0xe706 ,
274
280
VRX_VLLEZ = 0xe704 ,
281
+ VRX_VLREP = 0xe705 ,
275
282
VRX_VST = 0xe70e ,
276
283
VRX_VSTEF = 0xe70b ,
277
284
VRX_VSTEG = 0xe70a ,
@@ -563,6 +570,34 @@ static int RXB(TCGReg v1, TCGReg v2, TCGReg v3, TCGReg v4)
563
570
| ((v4 & 0x10 ) << (4 + 0 ));
564
571
}
565
572
573
+ static void tcg_out_insn_VRIa (TCGContext *s, S390Opcode op,
574
+ TCGReg v1, uint16_t i2, int m3)
575
+ {
576
+ tcg_debug_assert (is_vector_reg (v1));
577
+ tcg_out16 (s, (op & 0xff00 ) | ((v1 & 0xf ) << 4 ));
578
+ tcg_out16 (s, i2);
579
+ tcg_out16 (s, (op & 0x00ff ) | RXB (v1, 0 , 0 , 0 ) | (m3 << 12 ));
580
+ }
581
+
582
+ static void tcg_out_insn_VRIb (TCGContext *s, S390Opcode op,
583
+ TCGReg v1, uint8_t i2, uint8_t i3, int m4)
584
+ {
585
+ tcg_debug_assert (is_vector_reg (v1));
586
+ tcg_out16 (s, (op & 0xff00 ) | ((v1 & 0xf ) << 4 ));
587
+ tcg_out16 (s, (i2 << 8 ) | (i3 & 0xff ));
588
+ tcg_out16 (s, (op & 0x00ff ) | RXB (v1, 0 , 0 , 0 ) | (m4 << 12 ));
589
+ }
590
+
591
+ static void tcg_out_insn_VRIc (TCGContext *s, S390Opcode op,
592
+ TCGReg v1, uint16_t i2, TCGReg v3, int m4)
593
+ {
594
+ tcg_debug_assert (is_vector_reg (v1));
595
+ tcg_debug_assert (is_vector_reg (v3));
596
+ tcg_out16 (s, (op & 0xff00 ) | ((v1 & 0xf ) << 4 ) | (v3 & 0xf ));
597
+ tcg_out16 (s, i2);
598
+ tcg_out16 (s, (op & 0x00ff ) | RXB (v1, 0 , v3, 0 ) | (m4 << 12 ));
599
+ }
600
+
566
601
static void tcg_out_insn_VRRa (TCGContext *s, S390Opcode op,
567
602
TCGReg v1, TCGReg v2, int m3)
568
603
{
@@ -572,6 +607,17 @@ static void tcg_out_insn_VRRa(TCGContext *s, S390Opcode op,
572
607
tcg_out32 (s, (op & 0x00ff ) | RXB (v1, v2, 0 , 0 ) | (m3 << 12 ));
573
608
}
574
609
610
+ static void tcg_out_insn_VRRf (TCGContext *s, S390Opcode op,
611
+ TCGReg v1, TCGReg r2, TCGReg r3)
612
+ {
613
+ tcg_debug_assert (is_vector_reg (v1));
614
+ tcg_debug_assert (is_general_reg (r2));
615
+ tcg_debug_assert (is_general_reg (r3));
616
+ tcg_out16 (s, (op & 0xff00 ) | ((v1 & 0xf ) << 4 ) | r2);
617
+ tcg_out16 (s, r3 << 12 );
618
+ tcg_out16 (s, (op & 0x00ff ) | RXB (v1, 0 , 0 , 0 ));
619
+ }
620
+
575
621
static void tcg_out_insn_VRSb (TCGContext *s, S390Opcode op, TCGReg v1,
576
622
intptr_t d2, TCGReg b2, TCGReg r3, int m4)
577
623
{
@@ -2501,19 +2547,89 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
2501
2547
static bool tcg_out_dup_vec (TCGContext *s, TCGType type, unsigned vece,
2502
2548
TCGReg dst, TCGReg src)
2503
2549
{
2504
- g_assert_not_reached ();
2550
+ if (is_general_reg (src)) {
2551
+ /* Replicate general register into two MO_64. */
2552
+ tcg_out_insn (s, VRRf, VLVGP, dst, src, src);
2553
+ if (vece == MO_64) {
2554
+ return true ;
2555
+ }
2556
+ }
2557
+
2558
+ /*
2559
+ * Recall that the "standard" integer, within a vector, is the
2560
+ * rightmost element of the leftmost doubleword, a-la VLLEZ.
2561
+ */
2562
+ tcg_out_insn (s, VRIc, VREP, dst, (8 >> vece) - 1 , src, vece);
2563
+ return true ;
2505
2564
}
2506
2565
2507
2566
static bool tcg_out_dupm_vec (TCGContext *s, TCGType type, unsigned vece,
2508
2567
TCGReg dst, TCGReg base, intptr_t offset)
2509
2568
{
2510
- g_assert_not_reached ();
2569
+ tcg_out_vrx_mem (s, VRX_VLREP, dst, base, TCG_REG_NONE, offset, vece);
2570
+ return true ;
2511
2571
}
2512
2572
2513
2573
static void tcg_out_dupi_vec (TCGContext *s, TCGType type, unsigned vece,
2514
2574
TCGReg dst, int64_t val)
2515
2575
{
2516
- g_assert_not_reached ();
2576
+ int i, mask, msb, lsb;
2577
+
2578
+ /* Look for int16_t elements. */
2579
+ if (vece <= MO_16 ||
2580
+ (vece == MO_32 ? (int32_t )val : val) == (int16_t )val) {
2581
+ tcg_out_insn (s, VRIa, VREPI, dst, val, vece);
2582
+ return ;
2583
+ }
2584
+
2585
+ /* Look for bit masks. */
2586
+ if (vece == MO_32) {
2587
+ if (risbg_mask ((int32_t )val)) {
2588
+ /* Handle wraparound by swapping msb and lsb. */
2589
+ if ((val & 0x80000001u ) == 0x80000001u ) {
2590
+ msb = 32 - ctz32 (~val);
2591
+ lsb = clz32 (~val) - 1 ;
2592
+ } else {
2593
+ msb = clz32 (val);
2594
+ lsb = 31 - ctz32 (val);
2595
+ }
2596
+ tcg_out_insn (s, VRIb, VGM, dst, lsb, msb, MO_32);
2597
+ return ;
2598
+ }
2599
+ } else {
2600
+ if (risbg_mask (val)) {
2601
+ /* Handle wraparound by swapping msb and lsb. */
2602
+ if ((val & 0x8000000000000001ull ) == 0x8000000000000001ull ) {
2603
+ /* Handle wraparound by swapping msb and lsb. */
2604
+ msb = 64 - ctz64 (~val);
2605
+ lsb = clz64 (~val) - 1 ;
2606
+ } else {
2607
+ msb = clz64 (val);
2608
+ lsb = 63 - ctz64 (val);
2609
+ }
2610
+ tcg_out_insn (s, VRIb, VGM, dst, lsb, msb, MO_64);
2611
+ return ;
2612
+ }
2613
+ }
2614
+
2615
+ /* Look for all bytes 0x00 or 0xff. */
2616
+ for (i = mask = 0 ; i < 8 ; i++) {
2617
+ uint8_t byte = val >> (i * 8 );
2618
+ if (byte == 0xff ) {
2619
+ mask |= 1 << i;
2620
+ } else if (byte != 0 ) {
2621
+ break ;
2622
+ }
2623
+ }
2624
+ if (i == 8 ) {
2625
+ tcg_out_insn (s, VRIa, VGBM, dst, mask * 0x0101 , 0 );
2626
+ return ;
2627
+ }
2628
+
2629
+ /* Otherwise, stuff it in the constant pool. */
2630
+ tcg_out_insn (s, RIL, LARL, TCG_TMP0, 0 );
2631
+ new_pool_label (s, val, R_390_PC32DBL, s->code_ptr - 2 , 2 );
2632
+ tcg_out_insn (s, VRX, VLREP, dst, TCG_TMP0, TCG_REG_NONE, 0 , MO_64);
2517
2633
}
2518
2634
2519
2635
static void tcg_out_vec_op (TCGContext *s, TCGOpcode opc,
0 commit comments