summaryrefslogtreecommitdiff
path: root/development/gcc-d/gcc.66782.diff
blob: 0743f8853b42767313a41070d7d87d5f0b7e9a91 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md	(revision 225539)
+++ config/i386/i386.md	(working copy)
@@ -108,6 +108,7 @@
   UNSPEC_LD_MPIC	; load_macho_picbase
   UNSPEC_TRUNC_NOOP
   UNSPEC_DIV_ALREADY_SPLIT
+  UNSPEC_MS_TO_SYSV_CALL
   UNSPEC_PAUSE
   UNSPEC_LEA_ADDR
   UNSPEC_XBEGIN_ABORT
@@ -11584,6 +11585,15 @@
   "* return ix86_output_call_insn (insn, operands[0]);"
   [(set_attr "type" "call")])
 
+(define_insn "*call_rex64_ms_sysv"
+  [(match_parallel 2 "call_rex64_ms_sysv_operation"
+    [(call (mem:QI (match_operand:DI 0 "call_insn_operand" "rBwBz"))
+	   (match_operand 1))
+     (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)])]
+  "TARGET_64BIT && !SIBLING_CALL_P (insn)"
+  "* return ix86_output_call_insn (insn, operands[0]);"
+  [(set_attr "type" "call")])
+
 (define_insn "*sibcall"
   [(call (mem:QI (match_operand:W 0 "sibcall_insn_operand" "UBsBz"))
 	 (match_operand 1))]
@@ -11808,6 +11818,16 @@
 			 (match_dup 3)))
 	      (unspec [(const_int 0)] UNSPEC_PEEPSIB)])])
 
+(define_insn "*call_value_rex64_ms_sysv"
+  [(match_parallel 3 "call_rex64_ms_sysv_operation"
+    [(set (match_operand 0)
+	  (call (mem:QI (match_operand:DI 1 "call_insn_operand" "rBwBz"))
+		(match_operand 2)))
+     (unspec [(const_int 0)] UNSPEC_MS_TO_SYSV_CALL)])]
+ "TARGET_64BIT && !SIBLING_CALL_P (insn)"
+  "* return ix86_output_call_insn (insn, operands[1]);"
+  [(set_attr "type" "callv")])
+
 (define_expand "call_value_pop"
   [(parallel [(set (match_operand 0)
 		   (call (match_operand:QI 1)
Index: config/i386/predicates.md
===================================================================
--- config/i386/predicates.md	(revision 225533)
+++ config/i386/predicates.md	(working copy)
@@ -616,6 +616,36 @@
 	  && XINT (XEXP (op, 0), 1) == UNSPEC_GOTPCREL);
 })
 
+;; Return true if OP is a call from MS ABI to SYSV ABI function.
+(define_predicate "call_rex64_ms_sysv_operation"
+  (match_code "parallel")
+{
+  unsigned creg_size = ARRAY_SIZE (x86_64_ms_sysv_extra_clobbered_registers);
+  unsigned i;
+
+  if ((unsigned) XVECLEN (op, 0) != creg_size + 2)
+    return false;
+
+  for (i = 0; i < creg_size; i++)
+    {
+      rtx elt = XVECEXP (op, 0, i+2);
+      enum machine_mode mode;
+      unsigned regno;
+
+      if (GET_CODE (elt) != CLOBBER
+          || GET_CODE (SET_DEST (elt)) != REG)
+        return false;
+
+      regno = x86_64_ms_sysv_extra_clobbered_registers[i];
+      mode = SSE_REGNO_P (regno) ? TImode : DImode;
+
+      if (GET_MODE (SET_DEST (elt)) != mode
+	  || REGNO (SET_DEST (elt)) != regno)
+	return false;
+    }
+  return true;
+})
+
 ;; Match exactly zero.
 (define_predicate "const0_operand"
   (match_code "const_int,const_wide_int,const_double,const_vector")
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 225533)
+++ config/i386/i386.c	(working copy)
@@ -25639,7 +25639,9 @@
 		  rtx callarg2,
 		  rtx pop, bool sibcall)
 {
-  rtx vec[3];
+  unsigned int const cregs_size
+    = ARRAY_SIZE (x86_64_ms_sysv_extra_clobbered_registers);
+  rtx vec[3 + cregs_size];
   rtx use = NULL, call;
   unsigned int vec_len = 0;
 
@@ -25742,16 +25744,18 @@
   if (TARGET_64BIT_MS_ABI
       && (!callarg2 || INTVAL (callarg2) != -2))
     {
-      int const cregs_size
-	= ARRAY_SIZE (x86_64_ms_sysv_extra_clobbered_registers);
-      int i;
+      unsigned i;
 
+      vec[vec_len++] = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx),
+ 				       UNSPEC_MS_TO_SYSV_CALL);
+
       for (i = 0; i < cregs_size; i++)
 	{
 	  int regno = x86_64_ms_sysv_extra_clobbered_registers[i];
 	  machine_mode mode = SSE_REGNO_P (regno) ? TImode : DImode;
 
-	  clobber_reg (&use, gen_rtx_REG (mode, regno));
+ 	  vec[vec_len++]
+ 	    = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno));
 	}
     }