@@ -265,6 +265,12 @@ typedef enum S390Opcode {
265
265
RX_STC = 0x42 ,
266
266
RX_STH = 0x40 ,
267
267
268
+ VRX_VL = 0xe706 ,
269
+ VRX_VLLEZ = 0xe704 ,
270
+ VRX_VST = 0xe70e ,
271
+ VRX_VSTEF = 0xe70b ,
272
+ VRX_VSTEG = 0xe70a ,
273
+
268
274
NOP = 0x0707 ,
269
275
} S390Opcode;
270
276
@@ -412,6 +418,16 @@ static void * const qemu_st_helpers[(MO_SIZE | MO_BSWAP) + 1] = {
412
418
static const tcg_insn_unit *tb_ret_addr;
413
419
uint64_t s390_facilities[3 ];
414
420
421
+ static inline bool is_general_reg (TCGReg r)
422
+ {
423
+ return r <= TCG_REG_R15;
424
+ }
425
+
426
+ static inline bool is_vector_reg (TCGReg r)
427
+ {
428
+ return r >= TCG_REG_V0 && r <= TCG_REG_V31;
429
+ }
430
+
415
431
static bool patch_reloc (tcg_insn_unit *src_rw, int type,
416
432
intptr_t value, intptr_t addend)
417
433
{
@@ -529,6 +545,31 @@ static void tcg_out_insn_RSY(TCGContext *s, S390Opcode op, TCGReg r1,
529
545
#define tcg_out_insn_RX tcg_out_insn_RS
530
546
#define tcg_out_insn_RXY tcg_out_insn_RSY
531
547
548
+ static int RXB (TCGReg v1, TCGReg v2, TCGReg v3, TCGReg v4)
549
+ {
550
+ /*
551
+ * Shift bit 4 of each regno to its corresponding bit of RXB.
552
+ * RXB itself begins at bit 8 of the instruction so 8 - 4 = 4
553
+ * is the left-shift of the 4th operand.
554
+ */
555
+ return ((v1 & 0x10 ) << (4 + 3 ))
556
+ | ((v2 & 0x10 ) << (4 + 2 ))
557
+ | ((v3 & 0x10 ) << (4 + 1 ))
558
+ | ((v4 & 0x10 ) << (4 + 0 ));
559
+ }
560
+
561
+ static void tcg_out_insn_VRX (TCGContext *s, S390Opcode op, TCGReg v1,
562
+ TCGReg b2, TCGReg x2, intptr_t d2, int m3)
563
+ {
564
+ tcg_debug_assert (is_vector_reg (v1));
565
+ tcg_debug_assert (d2 >= 0 && d2 <= 0xfff );
566
+ tcg_debug_assert (is_general_reg (x2));
567
+ tcg_debug_assert (is_general_reg (b2));
568
+ tcg_out16 (s, (op & 0xff00 ) | ((v1 & 0xf ) << 4 ) | x2);
569
+ tcg_out16 (s, (b2 << 12 ) | d2);
570
+ tcg_out16 (s, (op & 0x00ff ) | RXB (v1, 0 , 0 , 0 ) | (m3 << 12 ));
571
+ }
572
+
532
573
/* Emit an opcode with "type-checking" of the format. */
533
574
#define tcg_out_insn (S, FMT, OP, ...) \
534
575
glue (tcg_out_insn_,FMT)(S, glue(glue(FMT,_),OP), ## __VA_ARGS__)
@@ -705,25 +746,92 @@ static void tcg_out_mem(TCGContext *s, S390Opcode opc_rx, S390Opcode opc_rxy,
705
746
}
706
747
}
707
748
749
+ static void tcg_out_vrx_mem (TCGContext *s, S390Opcode opc_vrx,
750
+ TCGReg data, TCGReg base, TCGReg index,
751
+ tcg_target_long ofs, int m3)
752
+ {
753
+ if (ofs < 0 || ofs >= 0x1000 ) {
754
+ if (ofs >= -0x80000 && ofs < 0x80000 ) {
755
+ tcg_out_insn (s, RXY, LAY, TCG_TMP0, base, index, ofs);
756
+ base = TCG_TMP0;
757
+ index = TCG_REG_NONE;
758
+ ofs = 0 ;
759
+ } else {
760
+ tcg_out_movi (s, TCG_TYPE_PTR, TCG_TMP0, ofs);
761
+ if (index != TCG_REG_NONE) {
762
+ tcg_out_insn (s, RRE, AGR, TCG_TMP0, index);
763
+ }
764
+ index = TCG_TMP0;
765
+ ofs = 0 ;
766
+ }
767
+ }
768
+ tcg_out_insn_VRX (s, opc_vrx, data, base, index, ofs, m3);
769
+ }
708
770
709
771
/* load data without address translation or endianness conversion */
710
- static inline void tcg_out_ld (TCGContext *s, TCGType type, TCGReg data,
711
- TCGReg base, intptr_t ofs)
772
+ static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg data,
773
+ TCGReg base, intptr_t ofs)
712
774
{
713
- if (type == TCG_TYPE_I32) {
714
- tcg_out_mem (s, RX_L, RXY_LY, data, base, TCG_REG_NONE, ofs);
715
- } else {
716
- tcg_out_mem (s, 0 , RXY_LG, data, base, TCG_REG_NONE, ofs);
775
+ switch (type) {
776
+ case TCG_TYPE_I32:
777
+ if (likely (is_general_reg (data))) {
778
+ tcg_out_mem (s, RX_L, RXY_LY, data, base, TCG_REG_NONE, ofs);
779
+ break ;
780
+ }
781
+ tcg_out_vrx_mem (s, VRX_VLLEZ, data, base, TCG_REG_NONE, ofs, MO_32);
782
+ break ;
783
+
784
+ case TCG_TYPE_I64:
785
+ if (likely (is_general_reg (data))) {
786
+ tcg_out_mem (s, 0 , RXY_LG, data, base, TCG_REG_NONE, ofs);
787
+ break ;
788
+ }
789
+ /* fallthru */
790
+
791
+ case TCG_TYPE_V64:
792
+ tcg_out_vrx_mem (s, VRX_VLLEZ, data, base, TCG_REG_NONE, ofs, MO_64);
793
+ break ;
794
+
795
+ case TCG_TYPE_V128:
796
+ /* Hint quadword aligned. */
797
+ tcg_out_vrx_mem (s, VRX_VL, data, base, TCG_REG_NONE, ofs, 4 );
798
+ break ;
799
+
800
+ default :
801
+ g_assert_not_reached ();
717
802
}
718
803
}
719
804
720
- static inline void tcg_out_st (TCGContext *s, TCGType type, TCGReg data,
721
- TCGReg base, intptr_t ofs)
805
+ static void tcg_out_st (TCGContext *s, TCGType type, TCGReg data,
806
+ TCGReg base, intptr_t ofs)
722
807
{
723
- if (type == TCG_TYPE_I32) {
724
- tcg_out_mem (s, RX_ST, RXY_STY, data, base, TCG_REG_NONE, ofs);
725
- } else {
726
- tcg_out_mem (s, 0 , RXY_STG, data, base, TCG_REG_NONE, ofs);
808
+ switch (type) {
809
+ case TCG_TYPE_I32:
810
+ if (likely (is_general_reg (data))) {
811
+ tcg_out_mem (s, RX_ST, RXY_STY, data, base, TCG_REG_NONE, ofs);
812
+ } else {
813
+ tcg_out_vrx_mem (s, VRX_VSTEF, data, base, TCG_REG_NONE, ofs, 1 );
814
+ }
815
+ break ;
816
+
817
+ case TCG_TYPE_I64:
818
+ if (likely (is_general_reg (data))) {
819
+ tcg_out_mem (s, 0 , RXY_STG, data, base, TCG_REG_NONE, ofs);
820
+ break ;
821
+ }
822
+ /* fallthru */
823
+
824
+ case TCG_TYPE_V64:
825
+ tcg_out_vrx_mem (s, VRX_VSTEG, data, base, TCG_REG_NONE, ofs, 0 );
826
+ break ;
827
+
828
+ case TCG_TYPE_V128:
829
+ /* Hint quadword aligned. */
830
+ tcg_out_vrx_mem (s, VRX_VST, data, base, TCG_REG_NONE, ofs, 4 );
831
+ break ;
832
+
833
+ default :
834
+ g_assert_not_reached ();
727
835
}
728
836
}
729
837
0 commit comments