tcg-target.c.inc (3704993f545efbe7b5a9ede83525f0d9c07cb31f) tcg-target.c.inc (748b7f3ef78654f0ed11c85ed0b34a02f97ea856)
1/*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2009 Ulrich Hecht <uli@suse.de>
5 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
6 * Copyright (c) 2010 Richard Henderson <rth@twiddle.net>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy

--- 52 unchanged lines hidden (view full) ---

61
62/* A scratch register that may be be used throughout the backend. */
63#define TCG_TMP0 TCG_REG_R1
64
65/* A scratch register that holds a pointer to the beginning of the TB.
66 We don't need this when we have pc-relative loads with the general
67 instructions extension facility. */
68#define TCG_REG_TB TCG_REG_R12
1/*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2009 Ulrich Hecht <uli@suse.de>
5 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
6 * Copyright (c) 2010 Richard Henderson <rth@twiddle.net>
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy

--- 52 unchanged lines hidden (view full) ---

61
62/* A scratch register that may be be used throughout the backend. */
63#define TCG_TMP0 TCG_REG_R1
64
65/* A scratch register that holds a pointer to the beginning of the TB.
66 We don't need this when we have pc-relative loads with the general
67 instructions extension facility. */
68#define TCG_REG_TB TCG_REG_R12
69#define USE_REG_TB (!(s390_facilities & FACILITY_GEN_INST_EXT))
69#define USE_REG_TB (!HAVE_FACILITY(GEN_INST_EXT))
70
71#ifndef CONFIG_SOFTMMU
72#define TCG_GUEST_BASE_REG TCG_REG_R13
73#endif
74
75/* All of the following instructions are prefixed with their instruction
76 format, and are defined as 8- or 16-bit quantities, even when the two
77 halves of the 16-bit quantity may appear 32 bits apart in the insn.

--- 294 unchanged lines hidden (view full) ---

372 [MO_LEQ] = helper_le_stq_mmu,
373 [MO_BEUW] = helper_be_stw_mmu,
374 [MO_BEUL] = helper_be_stl_mmu,
375 [MO_BEQ] = helper_be_stq_mmu,
376};
377#endif
378
379static const tcg_insn_unit *tb_ret_addr;
70
71#ifndef CONFIG_SOFTMMU
72#define TCG_GUEST_BASE_REG TCG_REG_R13
73#endif
74
75/* All of the following instructions are prefixed with their instruction
76 format, and are defined as 8- or 16-bit quantities, even when the two
77 halves of the 16-bit quantity may appear 32 bits apart in the insn.

--- 294 unchanged lines hidden (view full) ---

372 [MO_LEQ] = helper_le_stq_mmu,
373 [MO_BEUW] = helper_be_stw_mmu,
374 [MO_BEUL] = helper_be_stl_mmu,
375 [MO_BEQ] = helper_be_stq_mmu,
376};
377#endif
378
379static const tcg_insn_unit *tb_ret_addr;
380uint64_t s390_facilities;
380uint64_t s390_facilities[1];
381
382static bool patch_reloc(tcg_insn_unit *src_rw, int type,
383 intptr_t value, intptr_t addend)
384{
385 const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
386 intptr_t pcrel2;
387 uint32_t old;
388

--- 183 unchanged lines hidden (view full) ---

572
573 uval = sval;
574 if (type == TCG_TYPE_I32) {
575 uval = (uint32_t)sval;
576 sval = (int32_t)sval;
577 }
578
579 /* Try all 48-bit insns that can load it in one go. */
381
382static bool patch_reloc(tcg_insn_unit *src_rw, int type,
383 intptr_t value, intptr_t addend)
384{
385 const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
386 intptr_t pcrel2;
387 uint32_t old;
388

--- 183 unchanged lines hidden (view full) ---

572
573 uval = sval;
574 if (type == TCG_TYPE_I32) {
575 uval = (uint32_t)sval;
576 sval = (int32_t)sval;
577 }
578
579 /* Try all 48-bit insns that can load it in one go. */
580 if (s390_facilities & FACILITY_EXT_IMM) {
580 if (HAVE_FACILITY(EXT_IMM)) {
581 if (sval == (int32_t)sval) {
582 tcg_out_insn(s, RIL, LGFI, ret, sval);
583 return;
584 }
585 if (uval <= 0xffffffff) {
586 tcg_out_insn(s, RIL, LLILF, ret, uval);
587 return;
588 }

--- 26 unchanged lines hidden (view full) ---

615 both insns are required. */
616 if (uval <= 0xffffffff) {
617 tcg_out_insn(s, RI, LLILL, ret, uval);
618 tcg_out_insn(s, RI, IILH, ret, uval >> 16);
619 return;
620 }
621
622 /* Otherwise, stuff it in the constant pool. */
581 if (sval == (int32_t)sval) {
582 tcg_out_insn(s, RIL, LGFI, ret, sval);
583 return;
584 }
585 if (uval <= 0xffffffff) {
586 tcg_out_insn(s, RIL, LLILF, ret, uval);
587 return;
588 }

--- 26 unchanged lines hidden (view full) ---

615 both insns are required. */
616 if (uval <= 0xffffffff) {
617 tcg_out_insn(s, RI, LLILL, ret, uval);
618 tcg_out_insn(s, RI, IILH, ret, uval >> 16);
619 return;
620 }
621
622 /* Otherwise, stuff it in the constant pool. */
623 if (s390_facilities & FACILITY_GEN_INST_EXT) {
623 if (HAVE_FACILITY(GEN_INST_EXT)) {
624 tcg_out_insn(s, RIL, LGRL, ret, 0);
625 new_pool_label(s, sval, R_390_PC32DBL, s->code_ptr - 2, 2);
626 } else if (USE_REG_TB && !in_prologue) {
627 tcg_out_insn(s, RXY, LG, ret, TCG_REG_TB, TCG_REG_NONE, 0);
628 new_pool_label(s, sval, R_390_20, s->code_ptr - 2,
629 tcg_tbrel_diff(s, NULL));
630 } else {
631 TCGReg base = ret ? ret : TCG_TMP0;

--- 69 unchanged lines hidden (view full) ---

701}
702
703/* load data from an absolute host address */
704static void tcg_out_ld_abs(TCGContext *s, TCGType type,
705 TCGReg dest, const void *abs)
706{
707 intptr_t addr = (intptr_t)abs;
708
624 tcg_out_insn(s, RIL, LGRL, ret, 0);
625 new_pool_label(s, sval, R_390_PC32DBL, s->code_ptr - 2, 2);
626 } else if (USE_REG_TB && !in_prologue) {
627 tcg_out_insn(s, RXY, LG, ret, TCG_REG_TB, TCG_REG_NONE, 0);
628 new_pool_label(s, sval, R_390_20, s->code_ptr - 2,
629 tcg_tbrel_diff(s, NULL));
630 } else {
631 TCGReg base = ret ? ret : TCG_TMP0;

--- 69 unchanged lines hidden (view full) ---

701}
702
703/* load data from an absolute host address */
704static void tcg_out_ld_abs(TCGContext *s, TCGType type,
705 TCGReg dest, const void *abs)
706{
707 intptr_t addr = (intptr_t)abs;
708
709 if ((s390_facilities & FACILITY_GEN_INST_EXT) && !(addr & 1)) {
709 if (HAVE_FACILITY(GEN_INST_EXT) && !(addr & 1)) {
710 ptrdiff_t disp = tcg_pcrel_diff(s, abs) >> 1;
711 if (disp == (int32_t)disp) {
712 if (type == TCG_TYPE_I32) {
713 tcg_out_insn(s, RIL, LRL, dest, disp);
714 } else {
715 tcg_out_insn(s, RIL, LGRL, dest, disp);
716 }
717 return;

--- 17 unchanged lines hidden (view full) ---

735 /* Format RIE-f */
736 tcg_out16(s, (RIE_RISBG & 0xff00) | (dest << 4) | src);
737 tcg_out16(s, (msb << 8) | (z << 7) | lsb);
738 tcg_out16(s, (ofs << 8) | (RIE_RISBG & 0xff));
739}
740
741static void tgen_ext8s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
742{
710 ptrdiff_t disp = tcg_pcrel_diff(s, abs) >> 1;
711 if (disp == (int32_t)disp) {
712 if (type == TCG_TYPE_I32) {
713 tcg_out_insn(s, RIL, LRL, dest, disp);
714 } else {
715 tcg_out_insn(s, RIL, LGRL, dest, disp);
716 }
717 return;

--- 17 unchanged lines hidden (view full) ---

735 /* Format RIE-f */
736 tcg_out16(s, (RIE_RISBG & 0xff00) | (dest << 4) | src);
737 tcg_out16(s, (msb << 8) | (z << 7) | lsb);
738 tcg_out16(s, (ofs << 8) | (RIE_RISBG & 0xff));
739}
740
741static void tgen_ext8s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
742{
743 if (s390_facilities & FACILITY_EXT_IMM) {
743 if (HAVE_FACILITY(EXT_IMM)) {
744 tcg_out_insn(s, RRE, LGBR, dest, src);
745 return;
746 }
747
748 if (type == TCG_TYPE_I32) {
749 if (dest == src) {
750 tcg_out_sh32(s, RS_SLL, dest, TCG_REG_NONE, 24);
751 } else {
752 tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 24);
753 }
754 tcg_out_sh32(s, RS_SRA, dest, TCG_REG_NONE, 24);
755 } else {
756 tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 56);
757 tcg_out_sh64(s, RSY_SRAG, dest, dest, TCG_REG_NONE, 56);
758 }
759}
760
761static void tgen_ext8u(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
762{
744 tcg_out_insn(s, RRE, LGBR, dest, src);
745 return;
746 }
747
748 if (type == TCG_TYPE_I32) {
749 if (dest == src) {
750 tcg_out_sh32(s, RS_SLL, dest, TCG_REG_NONE, 24);
751 } else {
752 tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 24);
753 }
754 tcg_out_sh32(s, RS_SRA, dest, TCG_REG_NONE, 24);
755 } else {
756 tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 56);
757 tcg_out_sh64(s, RSY_SRAG, dest, dest, TCG_REG_NONE, 56);
758 }
759}
760
761static void tgen_ext8u(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
762{
763 if (s390_facilities & FACILITY_EXT_IMM) {
763 if (HAVE_FACILITY(EXT_IMM)) {
764 tcg_out_insn(s, RRE, LLGCR, dest, src);
765 return;
766 }
767
768 if (dest == src) {
769 tcg_out_movi(s, type, TCG_TMP0, 0xff);
770 src = TCG_TMP0;
771 } else {
772 tcg_out_movi(s, type, dest, 0xff);
773 }
774 if (type == TCG_TYPE_I32) {
775 tcg_out_insn(s, RR, NR, dest, src);
776 } else {
777 tcg_out_insn(s, RRE, NGR, dest, src);
778 }
779}
780
781static void tgen_ext16s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
782{
764 tcg_out_insn(s, RRE, LLGCR, dest, src);
765 return;
766 }
767
768 if (dest == src) {
769 tcg_out_movi(s, type, TCG_TMP0, 0xff);
770 src = TCG_TMP0;
771 } else {
772 tcg_out_movi(s, type, dest, 0xff);
773 }
774 if (type == TCG_TYPE_I32) {
775 tcg_out_insn(s, RR, NR, dest, src);
776 } else {
777 tcg_out_insn(s, RRE, NGR, dest, src);
778 }
779}
780
781static void tgen_ext16s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
782{
783 if (s390_facilities & FACILITY_EXT_IMM) {
783 if (HAVE_FACILITY(EXT_IMM)) {
784 tcg_out_insn(s, RRE, LGHR, dest, src);
785 return;
786 }
787
788 if (type == TCG_TYPE_I32) {
789 if (dest == src) {
790 tcg_out_sh32(s, RS_SLL, dest, TCG_REG_NONE, 16);
791 } else {
792 tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 16);
793 }
794 tcg_out_sh32(s, RS_SRA, dest, TCG_REG_NONE, 16);
795 } else {
796 tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 48);
797 tcg_out_sh64(s, RSY_SRAG, dest, dest, TCG_REG_NONE, 48);
798 }
799}
800
801static void tgen_ext16u(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
802{
784 tcg_out_insn(s, RRE, LGHR, dest, src);
785 return;
786 }
787
788 if (type == TCG_TYPE_I32) {
789 if (dest == src) {
790 tcg_out_sh32(s, RS_SLL, dest, TCG_REG_NONE, 16);
791 } else {
792 tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 16);
793 }
794 tcg_out_sh32(s, RS_SRA, dest, TCG_REG_NONE, 16);
795 } else {
796 tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 48);
797 tcg_out_sh64(s, RSY_SRAG, dest, dest, TCG_REG_NONE, 48);
798 }
799}
800
801static void tgen_ext16u(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
802{
803 if (s390_facilities & FACILITY_EXT_IMM) {
803 if (HAVE_FACILITY(EXT_IMM)) {
804 tcg_out_insn(s, RRE, LLGHR, dest, src);
805 return;
806 }
807
808 if (dest == src) {
809 tcg_out_movi(s, type, TCG_TMP0, 0xffff);
810 src = TCG_TMP0;
811 } else {

--- 71 unchanged lines hidden (view full) ---

883 uint64_t valid = (type == TCG_TYPE_I32 ? 0xffffffffull : -1ull);
884 int i;
885
886 /* Look for the zero-extensions. */
887 if ((val & valid) == 0xffffffff) {
888 tgen_ext32u(s, dest, dest);
889 return;
890 }
804 tcg_out_insn(s, RRE, LLGHR, dest, src);
805 return;
806 }
807
808 if (dest == src) {
809 tcg_out_movi(s, type, TCG_TMP0, 0xffff);
810 src = TCG_TMP0;
811 } else {

--- 71 unchanged lines hidden (view full) ---

883 uint64_t valid = (type == TCG_TYPE_I32 ? 0xffffffffull : -1ull);
884 int i;
885
886 /* Look for the zero-extensions. */
887 if ((val & valid) == 0xffffffff) {
888 tgen_ext32u(s, dest, dest);
889 return;
890 }
891 if (s390_facilities & FACILITY_EXT_IMM) {
891 if (HAVE_FACILITY(EXT_IMM)) {
892 if ((val & valid) == 0xff) {
893 tgen_ext8u(s, TCG_TYPE_I64, dest, dest);
894 return;
895 }
896 if ((val & valid) == 0xffff) {
897 tgen_ext16u(s, TCG_TYPE_I64, dest, dest);
898 return;
899 }

--- 4 unchanged lines hidden (view full) ---

904 tcg_target_ulong mask = ~(0xffffull << i*16);
905 if (((val | ~valid) & mask) == mask) {
906 tcg_out_insn_RI(s, ni_insns[i], dest, val >> i*16);
907 return;
908 }
909 }
910
911 /* Try all 48-bit insns that can perform it in one go. */
892 if ((val & valid) == 0xff) {
893 tgen_ext8u(s, TCG_TYPE_I64, dest, dest);
894 return;
895 }
896 if ((val & valid) == 0xffff) {
897 tgen_ext16u(s, TCG_TYPE_I64, dest, dest);
898 return;
899 }

--- 4 unchanged lines hidden (view full) ---

904 tcg_target_ulong mask = ~(0xffffull << i*16);
905 if (((val | ~valid) & mask) == mask) {
906 tcg_out_insn_RI(s, ni_insns[i], dest, val >> i*16);
907 return;
908 }
909 }
910
911 /* Try all 48-bit insns that can perform it in one go. */
912 if (s390_facilities & FACILITY_EXT_IMM) {
912 if (HAVE_FACILITY(EXT_IMM)) {
913 for (i = 0; i < 2; i++) {
914 tcg_target_ulong mask = ~(0xffffffffull << i*32);
915 if (((val | ~valid) & mask) == mask) {
916 tcg_out_insn_RIL(s, nif_insns[i], dest, val >> i*32);
917 return;
918 }
919 }
920 }
913 for (i = 0; i < 2; i++) {
914 tcg_target_ulong mask = ~(0xffffffffull << i*32);
915 if (((val | ~valid) & mask) == mask) {
916 tcg_out_insn_RIL(s, nif_insns[i], dest, val >> i*32);
917 return;
918 }
919 }
920 }
921 if ((s390_facilities & FACILITY_GEN_INST_EXT) && risbg_mask(val)) {
921 if (HAVE_FACILITY(GEN_INST_EXT) && risbg_mask(val)) {
922 tgen_andi_risbg(s, dest, dest, val);
923 return;
924 }
925
926 /* Use the constant pool if USE_REG_TB, but not for small constants. */
927 if (USE_REG_TB) {
928 if (!maybe_out_small_movi(s, type, TCG_TMP0, val)) {
929 tcg_out_insn(s, RXY, NG, dest, TCG_REG_TB, TCG_REG_NONE, 0);

--- 32 unchanged lines hidden (view full) ---

962 tcg_target_ulong mask = (0xffffull << i*16);
963 if ((val & mask) != 0 && (val & ~mask) == 0) {
964 tcg_out_insn_RI(s, oi_insns[i], dest, val >> i*16);
965 return;
966 }
967 }
968
969 /* Try all 48-bit insns that can perform it in one go. */
922 tgen_andi_risbg(s, dest, dest, val);
923 return;
924 }
925
926 /* Use the constant pool if USE_REG_TB, but not for small constants. */
927 if (USE_REG_TB) {
928 if (!maybe_out_small_movi(s, type, TCG_TMP0, val)) {
929 tcg_out_insn(s, RXY, NG, dest, TCG_REG_TB, TCG_REG_NONE, 0);

--- 32 unchanged lines hidden (view full) ---

962 tcg_target_ulong mask = (0xffffull << i*16);
963 if ((val & mask) != 0 && (val & ~mask) == 0) {
964 tcg_out_insn_RI(s, oi_insns[i], dest, val >> i*16);
965 return;
966 }
967 }
968
969 /* Try all 48-bit insns that can perform it in one go. */
970 if (s390_facilities & FACILITY_EXT_IMM) {
970 if (HAVE_FACILITY(EXT_IMM)) {
971 for (i = 0; i < 2; i++) {
972 tcg_target_ulong mask = (0xffffffffull << i*32);
973 if ((val & mask) != 0 && (val & ~mask) == 0) {
974 tcg_out_insn_RIL(s, oif_insns[i], dest, val >> i*32);
975 return;
976 }
977 }
978 }

--- 8 unchanged lines hidden (view full) ---

987 } else if (USE_REG_TB) {
988 tcg_out_insn(s, RXY, OG, dest, TCG_REG_TB, TCG_REG_NONE, 0);
989 new_pool_label(s, val, R_390_20, s->code_ptr - 2,
990 tcg_tbrel_diff(s, NULL));
991 } else {
992 /* Perform the OR via sequential modifications to the high and
993 low parts. Do this via recursion to handle 16-bit vs 32-bit
994 masks in each half. */
971 for (i = 0; i < 2; i++) {
972 tcg_target_ulong mask = (0xffffffffull << i*32);
973 if ((val & mask) != 0 && (val & ~mask) == 0) {
974 tcg_out_insn_RIL(s, oif_insns[i], dest, val >> i*32);
975 return;
976 }
977 }
978 }

--- 8 unchanged lines hidden (view full) ---

987 } else if (USE_REG_TB) {
988 tcg_out_insn(s, RXY, OG, dest, TCG_REG_TB, TCG_REG_NONE, 0);
989 new_pool_label(s, val, R_390_20, s->code_ptr - 2,
990 tcg_tbrel_diff(s, NULL));
991 } else {
992 /* Perform the OR via sequential modifications to the high and
993 low parts. Do this via recursion to handle 16-bit vs 32-bit
994 masks in each half. */
995 tcg_debug_assert(s390_facilities & FACILITY_EXT_IMM);
995 tcg_debug_assert(HAVE_FACILITY(EXT_IMM));
996 tgen_ori(s, type, dest, val & 0x00000000ffffffffull);
997 tgen_ori(s, type, dest, val & 0xffffffff00000000ull);
998 }
999}
1000
1001static void tgen_xori(TCGContext *s, TCGType type, TCGReg dest, uint64_t val)
1002{
1003 /* Try all 48-bit insns that can perform it in one go. */
996 tgen_ori(s, type, dest, val & 0x00000000ffffffffull);
997 tgen_ori(s, type, dest, val & 0xffffffff00000000ull);
998 }
999}
1000
1001static void tgen_xori(TCGContext *s, TCGType type, TCGReg dest, uint64_t val)
1002{
1003 /* Try all 48-bit insns that can perform it in one go. */
1004 if (s390_facilities & FACILITY_EXT_IMM) {
1004 if (HAVE_FACILITY(EXT_IMM)) {
1005 if ((val & 0xffffffff00000000ull) == 0) {
1006 tcg_out_insn(s, RIL, XILF, dest, val);
1007 return;
1008 }
1009 if ((val & 0x00000000ffffffffull) == 0) {
1010 tcg_out_insn(s, RIL, XIHF, dest, val >> 32);
1011 return;
1012 }

--- 7 unchanged lines hidden (view full) ---

1020 tcg_out_insn(s, RRE, XGR, dest, TCG_TMP0);
1021 }
1022 } else if (USE_REG_TB) {
1023 tcg_out_insn(s, RXY, XG, dest, TCG_REG_TB, TCG_REG_NONE, 0);
1024 new_pool_label(s, val, R_390_20, s->code_ptr - 2,
1025 tcg_tbrel_diff(s, NULL));
1026 } else {
1027 /* Perform the xor by parts. */
1005 if ((val & 0xffffffff00000000ull) == 0) {
1006 tcg_out_insn(s, RIL, XILF, dest, val);
1007 return;
1008 }
1009 if ((val & 0x00000000ffffffffull) == 0) {
1010 tcg_out_insn(s, RIL, XIHF, dest, val >> 32);
1011 return;
1012 }

--- 7 unchanged lines hidden (view full) ---

1020 tcg_out_insn(s, RRE, XGR, dest, TCG_TMP0);
1021 }
1022 } else if (USE_REG_TB) {
1023 tcg_out_insn(s, RXY, XG, dest, TCG_REG_TB, TCG_REG_NONE, 0);
1024 new_pool_label(s, val, R_390_20, s->code_ptr - 2,
1025 tcg_tbrel_diff(s, NULL));
1026 } else {
1027 /* Perform the xor by parts. */
1028 tcg_debug_assert(s390_facilities & FACILITY_EXT_IMM);
1028 tcg_debug_assert(HAVE_FACILITY(EXT_IMM));
1029 if (val & 0xffffffff) {
1030 tcg_out_insn(s, RIL, XILF, dest, val);
1031 }
1032 if (val > 0xffffffff) {
1033 tcg_out_insn(s, RIL, XIHF, dest, val >> 32);
1034 }
1035 }
1036}

--- 17 unchanged lines hidden (view full) ---

1054 }
1055
1056 if (!is_unsigned && c2 == (int16_t)c2) {
1057 op = (type == TCG_TYPE_I32 ? RI_CHI : RI_CGHI);
1058 tcg_out_insn_RI(s, op, r1, c2);
1059 goto exit;
1060 }
1061
1029 if (val & 0xffffffff) {
1030 tcg_out_insn(s, RIL, XILF, dest, val);
1031 }
1032 if (val > 0xffffffff) {
1033 tcg_out_insn(s, RIL, XIHF, dest, val >> 32);
1034 }
1035 }
1036}

--- 17 unchanged lines hidden (view full) ---

1054 }
1055
1056 if (!is_unsigned && c2 == (int16_t)c2) {
1057 op = (type == TCG_TYPE_I32 ? RI_CHI : RI_CGHI);
1058 tcg_out_insn_RI(s, op, r1, c2);
1059 goto exit;
1060 }
1061
1062 if (s390_facilities & FACILITY_EXT_IMM) {
1062 if (HAVE_FACILITY(EXT_IMM)) {
1063 if (type == TCG_TYPE_I32) {
1064 op = (is_unsigned ? RIL_CLFI : RIL_CFI);
1065 tcg_out_insn_RIL(s, op, r1, c2);
1066 goto exit;
1067 } else if (c2 == (is_unsigned ? (TCGArg)(uint32_t)c2 : (TCGArg)(int32_t)c2)) {
1068 op = (is_unsigned ? RIL_CLGFI : RIL_CGFI);
1069 tcg_out_insn_RIL(s, op, r1, c2);
1070 goto exit;

--- 46 unchanged lines hidden (view full) ---

1117
1118static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond,
1119 TCGReg dest, TCGReg c1, TCGArg c2, int c2const)
1120{
1121 int cc;
1122 bool have_loc;
1123
1124 /* With LOC2, we can always emit the minimum 3 insns. */
1063 if (type == TCG_TYPE_I32) {
1064 op = (is_unsigned ? RIL_CLFI : RIL_CFI);
1065 tcg_out_insn_RIL(s, op, r1, c2);
1066 goto exit;
1067 } else if (c2 == (is_unsigned ? (TCGArg)(uint32_t)c2 : (TCGArg)(int32_t)c2)) {
1068 op = (is_unsigned ? RIL_CLGFI : RIL_CGFI);
1069 tcg_out_insn_RIL(s, op, r1, c2);
1070 goto exit;

--- 46 unchanged lines hidden (view full) ---

1117
1118static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond,
1119 TCGReg dest, TCGReg c1, TCGArg c2, int c2const)
1120{
1121 int cc;
1122 bool have_loc;
1123
1124 /* With LOC2, we can always emit the minimum 3 insns. */
1125 if (s390_facilities & FACILITY_LOAD_ON_COND2) {
1125 if (HAVE_FACILITY(LOAD_ON_COND2)) {
1126 /* Emit: d = 0, d = (cc ? 1 : d). */
1127 cc = tgen_cmp(s, type, cond, c1, c2, c2const, false);
1128 tcg_out_movi(s, TCG_TYPE_I64, dest, 0);
1129 tcg_out_insn(s, RIE, LOCGHI, dest, 1, cc);
1130 return;
1131 }
1132
1126 /* Emit: d = 0, d = (cc ? 1 : d). */
1127 cc = tgen_cmp(s, type, cond, c1, c2, c2const, false);
1128 tcg_out_movi(s, TCG_TYPE_I64, dest, 0);
1129 tcg_out_insn(s, RIE, LOCGHI, dest, 1, cc);
1130 return;
1131 }
1132
1133 have_loc = (s390_facilities & FACILITY_LOAD_ON_COND) != 0;
1133 have_loc = HAVE_FACILITY(LOAD_ON_COND);
1134
1135 /* For HAVE_LOC, only the paths through GTU/GT/LEU/LE are smaller. */
1136 restart:
1137 switch (cond) {
1138 case TCG_COND_NE:
1139 /* X != 0 is X > 0. */
1140 if (c2const && c2 == 0) {
1141 cond = TCG_COND_GTU;

--- 69 unchanged lines hidden (view full) ---

1211 }
1212}
1213
1214static void tgen_movcond(TCGContext *s, TCGType type, TCGCond c, TCGReg dest,
1215 TCGReg c1, TCGArg c2, int c2const,
1216 TCGArg v3, int v3const)
1217{
1218 int cc;
1134
1135 /* For HAVE_LOC, only the paths through GTU/GT/LEU/LE are smaller. */
1136 restart:
1137 switch (cond) {
1138 case TCG_COND_NE:
1139 /* X != 0 is X > 0. */
1140 if (c2const && c2 == 0) {
1141 cond = TCG_COND_GTU;

--- 69 unchanged lines hidden (view full) ---

1211 }
1212}
1213
1214static void tgen_movcond(TCGContext *s, TCGType type, TCGCond c, TCGReg dest,
1215 TCGReg c1, TCGArg c2, int c2const,
1216 TCGArg v3, int v3const)
1217{
1218 int cc;
1219 if (s390_facilities & FACILITY_LOAD_ON_COND) {
1219 if (HAVE_FACILITY(LOAD_ON_COND)) {
1220 cc = tgen_cmp(s, type, c, c1, c2, c2const, false);
1221 if (v3const) {
1222 tcg_out_insn(s, RIE, LOCGHI, dest, v3, cc);
1223 } else {
1224 tcg_out_insn(s, RRF, LOCGR, dest, v3, cc);
1225 }
1226 } else {
1227 c = tcg_invert_cond(c);

--- 16 unchanged lines hidden (view full) ---

1244 if (a2const && a2 == 64) {
1245 tcg_out_mov(s, TCG_TYPE_I64, dest, TCG_REG_R0);
1246 } else {
1247 if (a2const) {
1248 tcg_out_movi(s, TCG_TYPE_I64, dest, a2);
1249 } else {
1250 tcg_out_mov(s, TCG_TYPE_I64, dest, a2);
1251 }
1220 cc = tgen_cmp(s, type, c, c1, c2, c2const, false);
1221 if (v3const) {
1222 tcg_out_insn(s, RIE, LOCGHI, dest, v3, cc);
1223 } else {
1224 tcg_out_insn(s, RRF, LOCGR, dest, v3, cc);
1225 }
1226 } else {
1227 c = tcg_invert_cond(c);

--- 16 unchanged lines hidden (view full) ---

1244 if (a2const && a2 == 64) {
1245 tcg_out_mov(s, TCG_TYPE_I64, dest, TCG_REG_R0);
1246 } else {
1247 if (a2const) {
1248 tcg_out_movi(s, TCG_TYPE_I64, dest, a2);
1249 } else {
1250 tcg_out_mov(s, TCG_TYPE_I64, dest, a2);
1251 }
1252 if (s390_facilities & FACILITY_LOAD_ON_COND) {
1252 if (HAVE_FACILITY(LOAD_ON_COND)) {
1253 /* Emit: if (one bit found) dest = r0. */
1254 tcg_out_insn(s, RRF, LOCGR, dest, TCG_REG_R0, 2);
1255 } else {
1256 /* Emit: if (no one bit found) goto over; dest = r0; over: */
1257 tcg_out_insn(s, RI, BRC, 8, (4 + 4) >> 1);
1258 tcg_out_insn(s, RRE, LGR, dest, TCG_REG_R0);
1259 }
1260 }

--- 59 unchanged lines hidden (view full) ---

1320 tcg_out16(s, (i2 << 8) | (opc & 0xff));
1321}
1322
1323static void tgen_brcond(TCGContext *s, TCGType type, TCGCond c,
1324 TCGReg r1, TCGArg c2, int c2const, TCGLabel *l)
1325{
1326 int cc;
1327
1253 /* Emit: if (one bit found) dest = r0. */
1254 tcg_out_insn(s, RRF, LOCGR, dest, TCG_REG_R0, 2);
1255 } else {
1256 /* Emit: if (no one bit found) goto over; dest = r0; over: */
1257 tcg_out_insn(s, RI, BRC, 8, (4 + 4) >> 1);
1258 tcg_out_insn(s, RRE, LGR, dest, TCG_REG_R0);
1259 }
1260 }

--- 59 unchanged lines hidden (view full) ---

1320 tcg_out16(s, (i2 << 8) | (opc & 0xff));
1321}
1322
1323static void tgen_brcond(TCGContext *s, TCGType type, TCGCond c,
1324 TCGReg r1, TCGArg c2, int c2const, TCGLabel *l)
1325{
1326 int cc;
1327
1328 if (s390_facilities & FACILITY_GEN_INST_EXT) {
1328 if (HAVE_FACILITY(GEN_INST_EXT)) {
1329 bool is_unsigned = is_unsigned_cond(c);
1330 bool in_range;
1331 S390Opcode opc;
1332
1333 cc = tcg_cond_to_s390_cond[c];
1334
1335 if (!c2const) {
1336 opc = (type == TCG_TYPE_I32

--- 177 unchanged lines hidden (view full) ---

1514 tcg_out_insn(s, RXY, NG, TCG_REG_R2, TCG_AREG0, TCG_REG_NONE, mask_off);
1515 tcg_out_insn(s, RXY, AG, TCG_REG_R2, TCG_AREG0, TCG_REG_NONE, table_off);
1516
1517 /* For aligned accesses, we check the first byte and include the alignment
1518 bits within the address. For unaligned access, we check that we don't
1519 cross pages using the address of the last byte of the access. */
1520 a_off = (a_bits >= s_bits ? 0 : s_mask - a_mask);
1521 tlb_mask = (uint64_t)TARGET_PAGE_MASK | a_mask;
1329 bool is_unsigned = is_unsigned_cond(c);
1330 bool in_range;
1331 S390Opcode opc;
1332
1333 cc = tcg_cond_to_s390_cond[c];
1334
1335 if (!c2const) {
1336 opc = (type == TCG_TYPE_I32

--- 177 unchanged lines hidden (view full) ---

1514 tcg_out_insn(s, RXY, NG, TCG_REG_R2, TCG_AREG0, TCG_REG_NONE, mask_off);
1515 tcg_out_insn(s, RXY, AG, TCG_REG_R2, TCG_AREG0, TCG_REG_NONE, table_off);
1516
1517 /* For aligned accesses, we check the first byte and include the alignment
1518 bits within the address. For unaligned access, we check that we don't
1519 cross pages using the address of the last byte of the access. */
1520 a_off = (a_bits >= s_bits ? 0 : s_mask - a_mask);
1521 tlb_mask = (uint64_t)TARGET_PAGE_MASK | a_mask;
1522 if ((s390_facilities & FACILITY_GEN_INST_EXT) && a_off == 0) {
1522 if (HAVE_FACILITY(GEN_INST_EXT) && a_off == 0) {
1523 tgen_andi_risbg(s, TCG_REG_R3, addr_reg, tlb_mask);
1524 } else {
1525 tcg_out_insn(s, RX, LA, TCG_REG_R3, addr_reg, TCG_REG_NONE, a_off);
1526 tgen_andi(s, TCG_TYPE_TL, TCG_REG_R3, tlb_mask);
1527 }
1528
1529 if (is_ld) {
1530 ofs = offsetof(CPUTLBEntry, addr_read);

--- 274 unchanged lines hidden (view full) ---

1805 a0 = args[0], a1 = args[1], a2 = (int32_t)args[2];
1806 if (const_args[2]) {
1807 do_addi_32:
1808 if (a0 == a1) {
1809 if (a2 == (int16_t)a2) {
1810 tcg_out_insn(s, RI, AHI, a0, a2);
1811 break;
1812 }
1523 tgen_andi_risbg(s, TCG_REG_R3, addr_reg, tlb_mask);
1524 } else {
1525 tcg_out_insn(s, RX, LA, TCG_REG_R3, addr_reg, TCG_REG_NONE, a_off);
1526 tgen_andi(s, TCG_TYPE_TL, TCG_REG_R3, tlb_mask);
1527 }
1528
1529 if (is_ld) {
1530 ofs = offsetof(CPUTLBEntry, addr_read);

--- 274 unchanged lines hidden (view full) ---

1805 a0 = args[0], a1 = args[1], a2 = (int32_t)args[2];
1806 if (const_args[2]) {
1807 do_addi_32:
1808 if (a0 == a1) {
1809 if (a2 == (int16_t)a2) {
1810 tcg_out_insn(s, RI, AHI, a0, a2);
1811 break;
1812 }
1813 if (s390_facilities & FACILITY_EXT_IMM) {
1813 if (HAVE_FACILITY(EXT_IMM)) {
1814 tcg_out_insn(s, RIL, AFI, a0, a2);
1815 break;
1816 }
1817 }
1818 tcg_out_mem(s, RX_LA, RXY_LAY, a0, a1, TCG_REG_NONE, a2);
1819 } else if (a0 == a1) {
1820 tcg_out_insn(s, RR, AR, a0, a2);
1821 } else {

--- 229 unchanged lines hidden (view full) ---

2051 a0 = args[0], a1 = args[1], a2 = args[2];
2052 if (const_args[2]) {
2053 do_addi_64:
2054 if (a0 == a1) {
2055 if (a2 == (int16_t)a2) {
2056 tcg_out_insn(s, RI, AGHI, a0, a2);
2057 break;
2058 }
1814 tcg_out_insn(s, RIL, AFI, a0, a2);
1815 break;
1816 }
1817 }
1818 tcg_out_mem(s, RX_LA, RXY_LAY, a0, a1, TCG_REG_NONE, a2);
1819 } else if (a0 == a1) {
1820 tcg_out_insn(s, RR, AR, a0, a2);
1821 } else {

--- 229 unchanged lines hidden (view full) ---

2051 a0 = args[0], a1 = args[1], a2 = args[2];
2052 if (const_args[2]) {
2053 do_addi_64:
2054 if (a0 == a1) {
2055 if (a2 == (int16_t)a2) {
2056 tcg_out_insn(s, RI, AGHI, a0, a2);
2057 break;
2058 }
2059 if (s390_facilities & FACILITY_EXT_IMM) {
2059 if (HAVE_FACILITY(EXT_IMM)) {
2060 if (a2 == (int32_t)a2) {
2061 tcg_out_insn(s, RIL, AGFI, a0, a2);
2062 break;
2063 } else if (a2 == (uint32_t)a2) {
2064 tcg_out_insn(s, RIL, ALGFI, a0, a2);
2065 break;
2066 } else if (-a2 == (uint32_t)-a2) {
2067 tcg_out_insn(s, RIL, SLGFI, a0, -a2);

--- 208 unchanged lines hidden (view full) ---

2276 case INDEX_op_clz_i64:
2277 tgen_clz(s, args[0], args[1], args[2], const_args[2]);
2278 break;
2279
2280 case INDEX_op_mb:
2281 /* The host memory model is quite strong, we simply need to
2282 serialize the instruction stream. */
2283 if (args[0] & TCG_MO_ST_LD) {
2060 if (a2 == (int32_t)a2) {
2061 tcg_out_insn(s, RIL, AGFI, a0, a2);
2062 break;
2063 } else if (a2 == (uint32_t)a2) {
2064 tcg_out_insn(s, RIL, ALGFI, a0, a2);
2065 break;
2066 } else if (-a2 == (uint32_t)-a2) {
2067 tcg_out_insn(s, RIL, SLGFI, a0, -a2);

--- 208 unchanged lines hidden (view full) ---

2276 case INDEX_op_clz_i64:
2277 tgen_clz(s, args[0], args[1], args[2], const_args[2]);
2278 break;
2279
2280 case INDEX_op_mb:
2281 /* The host memory model is quite strong, we simply need to
2282 serialize the instruction stream. */
2283 if (args[0] & TCG_MO_ST_LD) {
2284 tcg_out_insn(s, RR, BCR,
2285 s390_facilities & FACILITY_FAST_BCR_SER ? 14 : 15, 0);
2284 tcg_out_insn(s, RR, BCR, HAVE_FACILITY(FAST_BCR_SER) ? 14 : 15, 0);
2286 }
2287 break;
2288
2289 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
2290 case INDEX_op_mov_i64:
2291 case INDEX_op_call: /* Always emitted via tcg_out_call. */
2292 default:
2293 tcg_abort();

--- 46 unchanged lines hidden (view full) ---

2340 case INDEX_op_sub_i32:
2341 case INDEX_op_sub_i64:
2342 case INDEX_op_and_i32:
2343 case INDEX_op_and_i64:
2344 case INDEX_op_or_i32:
2345 case INDEX_op_or_i64:
2346 case INDEX_op_xor_i32:
2347 case INDEX_op_xor_i64:
2285 }
2286 break;
2287
2288 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
2289 case INDEX_op_mov_i64:
2290 case INDEX_op_call: /* Always emitted via tcg_out_call. */
2291 default:
2292 tcg_abort();

--- 46 unchanged lines hidden (view full) ---

2339 case INDEX_op_sub_i32:
2340 case INDEX_op_sub_i64:
2341 case INDEX_op_and_i32:
2342 case INDEX_op_and_i64:
2343 case INDEX_op_or_i32:
2344 case INDEX_op_or_i64:
2345 case INDEX_op_xor_i32:
2346 case INDEX_op_xor_i64:
2348 return (s390_facilities & FACILITY_DISTINCT_OPS
2347 return (HAVE_FACILITY(DISTINCT_OPS)
2349 ? C_O1_I2(r, r, ri)
2350 : C_O1_I2(r, 0, ri));
2351
2352 case INDEX_op_mul_i32:
2353 /* If we have the general-instruction-extensions, then we have
2354 MULTIPLY SINGLE IMMEDIATE with a signed 32-bit, otherwise we
2355 have only MULTIPLY HALFWORD IMMEDIATE, with a signed 16-bit. */
2348 ? C_O1_I2(r, r, ri)
2349 : C_O1_I2(r, 0, ri));
2350
2351 case INDEX_op_mul_i32:
2352 /* If we have the general-instruction-extensions, then we have
2353 MULTIPLY SINGLE IMMEDIATE with a signed 32-bit, otherwise we
2354 have only MULTIPLY HALFWORD IMMEDIATE, with a signed 16-bit. */
2356 return (s390_facilities & FACILITY_GEN_INST_EXT
2355 return (HAVE_FACILITY(GEN_INST_EXT)
2357 ? C_O1_I2(r, 0, ri)
2358 : C_O1_I2(r, 0, rI));
2359
2360 case INDEX_op_mul_i64:
2356 ? C_O1_I2(r, 0, ri)
2357 : C_O1_I2(r, 0, rI));
2358
2359 case INDEX_op_mul_i64:
2361 return (s390_facilities & FACILITY_GEN_INST_EXT
2360 return (HAVE_FACILITY(GEN_INST_EXT)
2362 ? C_O1_I2(r, 0, rJ)
2363 : C_O1_I2(r, 0, rI));
2364
2365 case INDEX_op_shl_i32:
2366 case INDEX_op_shr_i32:
2367 case INDEX_op_sar_i32:
2361 ? C_O1_I2(r, 0, rJ)
2362 : C_O1_I2(r, 0, rI));
2363
2364 case INDEX_op_shl_i32:
2365 case INDEX_op_shr_i32:
2366 case INDEX_op_sar_i32:
2368 return (s390_facilities & FACILITY_DISTINCT_OPS
2367 return (HAVE_FACILITY(DISTINCT_OPS)
2369 ? C_O1_I2(r, r, ri)
2370 : C_O1_I2(r, 0, ri));
2371
2372 case INDEX_op_brcond_i32:
2373 case INDEX_op_brcond_i64:
2374 return C_O0_I2(r, ri);
2375
2376 case INDEX_op_bswap16_i32:

--- 27 unchanged lines hidden (view full) ---

2404 return C_O0_I2(L, L);
2405
2406 case INDEX_op_deposit_i32:
2407 case INDEX_op_deposit_i64:
2408 return C_O1_I2(r, rZ, r);
2409
2410 case INDEX_op_movcond_i32:
2411 case INDEX_op_movcond_i64:
2368 ? C_O1_I2(r, r, ri)
2369 : C_O1_I2(r, 0, ri));
2370
2371 case INDEX_op_brcond_i32:
2372 case INDEX_op_brcond_i64:
2373 return C_O0_I2(r, ri);
2374
2375 case INDEX_op_bswap16_i32:

--- 27 unchanged lines hidden (view full) ---

2403 return C_O0_I2(L, L);
2404
2405 case INDEX_op_deposit_i32:
2406 case INDEX_op_deposit_i64:
2407 return C_O1_I2(r, rZ, r);
2408
2409 case INDEX_op_movcond_i32:
2410 case INDEX_op_movcond_i64:
2412 return (s390_facilities & FACILITY_LOAD_ON_COND2
2411 return (HAVE_FACILITY(LOAD_ON_COND2)
2413 ? C_O1_I4(r, r, ri, rI, 0)
2414 : C_O1_I4(r, r, ri, r, 0));
2415
2416 case INDEX_op_div2_i32:
2417 case INDEX_op_div2_i64:
2418 case INDEX_op_divu2_i32:
2419 case INDEX_op_divu2_i64:
2420 return C_O2_I3(b, a, 0, 1, r);
2421
2422 case INDEX_op_mulu2_i64:
2423 return C_O2_I2(b, a, 0, r);
2424
2425 case INDEX_op_add2_i32:
2426 case INDEX_op_sub2_i32:
2412 ? C_O1_I4(r, r, ri, rI, 0)
2413 : C_O1_I4(r, r, ri, r, 0));
2414
2415 case INDEX_op_div2_i32:
2416 case INDEX_op_div2_i64:
2417 case INDEX_op_divu2_i32:
2418 case INDEX_op_divu2_i64:
2419 return C_O2_I3(b, a, 0, 1, r);
2420
2421 case INDEX_op_mulu2_i64:
2422 return C_O2_I2(b, a, 0, r);
2423
2424 case INDEX_op_add2_i32:
2425 case INDEX_op_sub2_i32:
2427 return (s390_facilities & FACILITY_EXT_IMM
2426 return (HAVE_FACILITY(EXT_IMM)
2428 ? C_O2_I4(r, r, 0, 1, ri, r)
2429 : C_O2_I4(r, r, 0, 1, r, r));
2430
2431 case INDEX_op_add2_i64:
2432 case INDEX_op_sub2_i64:
2427 ? C_O2_I4(r, r, 0, 1, ri, r)
2428 : C_O2_I4(r, r, 0, 1, r, r));
2429
2430 case INDEX_op_add2_i64:
2431 case INDEX_op_sub2_i64:
2433 return (s390_facilities & FACILITY_EXT_IMM
2432 return (HAVE_FACILITY(EXT_IMM)
2434 ? C_O2_I4(r, r, 0, 1, rA, r)
2435 : C_O2_I4(r, r, 0, 1, r, r));
2436
2437 default:
2438 g_assert_not_reached();
2439 }
2440}
2441
2442static void query_s390_facilities(void)
2443{
2444 unsigned long hwcap = qemu_getauxval(AT_HWCAP);
2445
2446 /* Is STORE FACILITY LIST EXTENDED available? Honestly, I believe this
2447 is present on all 64-bit systems, but let's check for it anyway. */
2448 if (hwcap & HWCAP_S390_STFLE) {
2433 ? C_O2_I4(r, r, 0, 1, rA, r)
2434 : C_O2_I4(r, r, 0, 1, r, r));
2435
2436 default:
2437 g_assert_not_reached();
2438 }
2439}
2440
2441static void query_s390_facilities(void)
2442{
2443 unsigned long hwcap = qemu_getauxval(AT_HWCAP);
2444
2445 /* Is STORE FACILITY LIST EXTENDED available? Honestly, I believe this
2446 is present on all 64-bit systems, but let's check for it anyway. */
2447 if (hwcap & HWCAP_S390_STFLE) {
2449 register int r0 __asm__("0");
2450 register void *r1 __asm__("1");
2448 register int r0 __asm__("0") = ARRAY_SIZE(s390_facilities) - 1;
2449 register void *r1 __asm__("1") = s390_facilities;
2451
2452 /* stfle 0(%r1) */
2450
2451 /* stfle 0(%r1) */
2453 r1 = &s390_facilities;
2454 asm volatile(".word 0xb2b0,0x1000"
2452 asm volatile(".word 0xb2b0,0x1000"
2455 : "=r"(r0) : "0"(0), "r"(r1) : "memory", "cc");
2453 : "=r"(r0) : "r"(r0), "r"(r1) : "memory", "cc");
2456 }
2457}
2458
2459static void tcg_target_init(TCGContext *s)
2460{
2461 query_s390_facilities();
2462
2463 tcg_target_available_regs[TCG_TYPE_I32] = 0xffff;

--- 124 unchanged lines hidden ---
2454 }
2455}
2456
2457static void tcg_target_init(TCGContext *s)
2458{
2459 query_s390_facilities();
2460
2461 tcg_target_available_regs[TCG_TYPE_I32] = 0xffff;

--- 124 unchanged lines hidden ---