1 /* $Id: order.c,v 1.14 2011/02/18 17:08:31 ragge Exp $ */
3 * Copyright (c) 2008 Michael Shalayeff
4 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 /* is it legal to make an OREG or NAME entry which has an
38 * offset of off, (from a register of r), if the
39 * resulting thing had type t */
41 notoff(TWORD t
, int r
, CONSZ off
, char *cp
)
47 * Check if LS and try to make it indexable.
48 * Ignore SCONV to long.
52 findls(NODE
*p
, int check
)
56 if (p
->n_op
== SCONV
&& p
->n_type
== LONG
&& p
->n_left
->n_type
== INT
)
57 p
= p
->n_left
; /* Ignore pointless SCONVs here */
58 if (p
->n_op
!= LS
|| p
->n_right
->n_op
!= ICON
)
60 if ((c
= p
->n_right
->n_lval
) != 1 && c
!= 2 && c
!= 3)
62 if (check
== 1 && p
->n_left
->n_op
!= REG
)
64 if (!isreg(p
->n_left
))
65 (void)geninsn(p
->n_left
, INAREG
);
70 * Turn a UMUL-referenced node into OREG.
71 * Be careful about register classes, this is a place where classes change.
73 * AMD64 (and i386) have a quite powerful addressing scheme:
75 * : 4(%rbx,%rax,8) 4 + %rbx + %rax * 8
76 * : 4(,%rax) 4 + %rax * 8
77 * The 8 above can be 1,2,4 or 8.
80 offstar(NODE
*p
, int shape
)
85 printf("offstar(%p)\n", p
);
90 return; /* Matched (%rax) */
93 return; /* Matched (,%rax,8) */
95 if ((p
->n_op
== PLUS
|| p
->n_op
== MINUS
) && p
->n_left
->n_op
== ICON
) {
98 return; /* Matched 4(%rax) */
100 return; /* Matched 4(,%rax,8) */
101 if (l
->n_op
== PLUS
&& isreg(l
->n_right
)) {
102 if (findls(l
->n_left
, 0))
103 return; /* Matched 4(%rbx,%rax,8) */
104 (void)geninsn(l
->n_left
, INAREG
);
105 return; /* Generate 4(%rbx,%rax) */
107 (void)geninsn(l
, INAREG
);
108 return; /* Generate 4(%rbx) */
111 if (p
->n_op
== PLUS
) {
112 if (!isreg(p
->n_left
)) /* ensure right is REG */
113 (void)geninsn(p
->n_left
, INAREG
);
114 if (isreg(p
->n_right
))
115 return; /* Matched (%rax,%rbx) */
116 if (findls(p
->n_right
, 0))
117 return; /* Matched (%rax,%rbx,4) */
118 (void)geninsn(p
->n_right
, INAREG
);
119 return; /* Generate (%rbx,%rax) */
122 (void)geninsn(p
, INAREG
);
126 * Do the actual conversion of offstar-found OREGs into real OREGs.
127 * For simple OREGs conversion should already be done.
132 static int shtbl
[] = { 1,2,4,8 };
139 #define risreg(p) (p->n_op == REG)
141 printf("myormake(%p)\n", q
);
142 fwalk(q
, e2print
, 0);
149 if ((p
->n_op
== PLUS
|| p
->n_op
== MINUS
) && p
->n_left
->n_op
== ICON
) {
150 c
= p
->n_left
->n_lval
;
151 n
= p
->n_left
->n_name
;
155 if (p
->n_op
== PLUS
&& risreg(p
->n_left
)) {
156 r1
= regno(p
->n_left
);
161 if (p
->n_op
== SCONV
)
163 sh
= shtbl
[(int)p
->n_right
->n_lval
];
164 r2
= regno(p
->n_left
);
166 } else if (risreg(p
)) {
170 // comperr("bad myormake tree");
177 q
->n_rval
= R2PACK(r1
, r2
, sh
);
181 printf("myormake converted %p\n", q
);
182 fwalk(q
, e2print
, 0);
187 * Shape matches for UMUL. Cooperates with offstar().
190 shumul(NODE
*p
, int shape
)
194 printf("shumul(%p)\n", p
);
196 /* Turns currently anything into OREG on x86 */
203 * Rewrite operations on binary operators (like +, -, etc...).
204 * Called as a result of table lookup.
211 printf("setbin(%p)\n", p
);
216 /* setup for assignment operator */
218 setasg(NODE
*p
, int cookie
)
221 printf("setasg(%p)\n", p
);
225 /* setup for unary operator */
227 setuni(NODE
*p
, int cookie
)
233 * Special handling of some instruction register allocation.
236 nspecial(struct optab
*q
)
240 if ((q
->ltype
& TINT
) &&
241 q
->rtype
== (TLONGLONG
|TULONGLONG
|TLONG
|TULONG
)) {
242 static struct rspecial s
[] = {
243 { NLEFT
, RAX
}, { NRES
, RAX
}, { 0 } };
250 static struct rspecial s
[] = {
251 { NEVER
, RAX
}, { NEVER
, RDX
},
252 { NLEFT
, RAX
}, { NRES
, RAX
},
253 { NORIGHT
, RDX
}, { NORIGHT
, RAX
}, { 0 } };
259 if (q
->ltype
& TUCHAR
) {
260 static struct rspecial s
[] = {
262 { NLEFT
, RAX
}, { NRES
, RAX
},
263 { NORIGHT
, RAX
}, { 0 } };
266 static struct rspecial s
[] = {
267 { NEVER
, RAX
}, { NEVER
, RDX
},
268 { NLEFT
, RAX
}, { NRES
, RDX
},
269 { NORIGHT
, RDX
}, { NORIGHT
, RAX
}, { 0 } };
276 static struct rspecial s
[] = {
279 { NEVER
, RCX
}, { 0 } };
285 static struct rspecial s
[] = {
287 { NRIGHT
, RSI
}, { NOLEFT
, RSI
},
288 { NOLEFT
, RCX
}, { NORIGHT
, RCX
},
289 { NEVER
, RCX
}, { 0 } };
294 if (q
->lshape
== SAREG
) {
295 static struct rspecial s
[] = {
297 { NLEFT
, RAX
}, { NRES
, RAX
}, { 0 } };
305 static struct rspecial s
[] = {
306 { NRIGHT
, RCX
}, { NOLEFT
, RCX
}, { 0 } };
314 comperr("nspecial entry %d", q
- table
);
315 return 0; /* XXX gcc */
319 * Set evaluation order of a binary node if it differs from default.
324 return 0; /* nothing differs on x86 */
328 * set registers in calling conventions live.
333 static int r
[NTEMPREG
+1];
337 if (optype(p
->n_op
) != BITYPE
)
340 for (q
= p
->n_right
; q
->n_op
== CM
; q
= q
->n_left
) {
341 if (q
->n_right
->n_op
== ASSIGN
&&
342 q
->n_right
->n_left
->n_op
== REG
)
343 r
[cr
++] = regno(q
->n_right
->n_left
);
345 if (q
->n_op
== ASSIGN
&& q
->n_left
->n_op
== REG
)
346 r
[cr
++] = regno(q
->n_left
);
352 * Signal whether the instruction is acceptable for this target.
355 acceptable(struct optab
*op
)