1 /* Id: order.c,v 1.18 2015/12/13 09:00:04 ragge Exp */
2 /* $NetBSD: order.c,v 1.1.1.5 2016/02/09 20:28:10 plunky Exp $ */
3 /*
4 * Copyright (c) 2008 Michael Shalayeff
5 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31
32 # include "pass2.h"
33
34 #include <string.h>
35
36 int canaddr(NODE *);
37
38 /* is it legal to make an OREG or NAME entry which has an
39 * offset of off, (from a register of r), if the
40 * resulting thing had type t */
41 int
notoff(TWORD t,int r,CONSZ off,char * cp)42 notoff(TWORD t, int r, CONSZ off, char *cp)
43 {
44 if (off > MAX_INT || off < MIN_INT)
45 return 1; /* max signed 32-bit offset */
46 return(0); /* YES */
47 }
48
49 /*
50 * Check if LS and try to make it indexable.
51 * Ignore SCONV to long.
52 * Return 0 if failed.
53 */
54 static int
findls(NODE * p,int check)55 findls(NODE *p, int check)
56 {
57 CONSZ c;
58
59 if (p->n_op == SCONV && p->n_type == LONG && p->n_left->n_type == INT)
60 p = p->n_left; /* Ignore pointless SCONVs here */
61 if (p->n_op != LS || p->n_right->n_op != ICON)
62 return 0;
63 if ((c = getlval(p->n_right)) != 1 && c != 2 && c != 3)
64 return 0;
65 if (check == 1 && p->n_left->n_op != REG)
66 return 0;
67 if (!isreg(p->n_left))
68 (void)geninsn(p->n_left, INAREG);
69 return 1;
70 }
71
72 /*
73 * Turn a UMUL-referenced node into OREG.
74 * Be careful about register classes, this is a place where classes change.
75 *
76 * AMD64 (and i386) have a quite powerful addressing scheme:
77 * : 4(%rax) 4 + %rax
78 * : 4(%rbx,%rax,8) 4 + %rbx + %rax * 8
79 * : 4(,%rax) 4 + %rax * 8
80 * The 8 above can be 1,2,4 or 8.
81 */
82 void
offstar(NODE * p,int shape)83 offstar(NODE *p, int shape)
84 {
85 NODE *l;
86
87 if (x2debug) {
88 printf("offstar(%p)\n", p);
89 fwalk(p, e2print, 0);
90 }
91
92 if (isreg(p))
93 return; /* Matched (%rax) */
94
95 if (findls(p, 0))
96 return; /* Matched (,%rax,8) */
97
98 if ((p->n_op == PLUS || p->n_op == MINUS) &&
99 p->n_left->n_op == ICON &&
100 p->n_left->n_name[0] == '\0' &&
101 notoff(0, 0, getlval(p->n_left), 0) == 0) {
102 l = p->n_right;
103 if (isreg(l))
104 return; /* Matched 4(%rax) */
105 if (findls(l, 0))
106 return; /* Matched 4(,%rax,8) */
107 if (l->n_op == PLUS && isreg(l->n_right)) {
108 if (findls(l->n_left, 0))
109 return; /* Matched 4(%rbx,%rax,8) */
110 (void)geninsn(l->n_left, INAREG);
111 return; /* Generate 4(%rbx,%rax) */
112 }
113 (void)geninsn(l, INAREG);
114 return; /* Generate 4(%rbx) */
115 }
116
117 if (p->n_op == PLUS) {
118 if (!isreg(p->n_left)) /* ensure right is REG */
119 (void)geninsn(p->n_left, INAREG);
120 if (isreg(p->n_right))
121 return; /* Matched (%rax,%rbx) */
122 if (findls(p->n_right, 0))
123 return; /* Matched (%rax,%rbx,4) */
124 (void)geninsn(p->n_right, INAREG);
125 return; /* Generate (%rbx,%rax) */
126 }
127
128 (void)geninsn(p, INAREG);
129 }
130
131 /*
132 * Do the actual conversion of offstar-found OREGs into real OREGs.
133 * For simple OREGs conversion should already be done.
134 */
135 void
myormake(NODE * q)136 myormake(NODE *q)
137 {
138 static int shtbl[] = { 1,2,4,8 };
139 NODE *p, *r;
140 CONSZ c = 0;
141 int r1, r2, sh;
142 int mkconv = 0;
143 char *n = "";
144
145 #define risreg(p) (p->n_op == REG)
146 if (x2debug) {
147 printf("myormake(%p)\n", q);
148 fwalk(q, e2print, 0);
149 }
150 r1 = r2 = MAXREGS;
151 sh = 1;
152
153 r = p = q->n_left;
154
155 if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_left->n_op == ICON) {
156 c = getlval(p->n_left);
157 n = p->n_left->n_name;
158 p = p->n_right;
159 }
160
161 if (p->n_op == PLUS && risreg(p->n_left)) {
162 r1 = regno(p->n_left);
163 p = p->n_right;
164 }
165
166 if (findls(p, 1)) {
167 if (p->n_op == SCONV)
168 p = p->n_left;
169 sh = shtbl[(int)getlval(p->n_right)];
170 r2 = regno(p->n_left);
171 mkconv = 1;
172 } else if (risreg(p)) {
173 r2 = regno(p);
174 mkconv = 1;
175 } //else
176 // comperr("bad myormake tree");
177
178 if (mkconv == 0)
179 return;
180
181 q->n_op = OREG;
182 setlval(q, c);
183 q->n_rval = R2PACK(r1, r2, sh);
184 q->n_name = n;
185 tfree(r);
186 if (x2debug) {
187 printf("myormake converted %p\n", q);
188 fwalk(q, e2print, 0);
189 }
190 }
191
192 /*
193 * Shape matches for UMUL. Cooperates with offstar().
194 */
195 int
shumul(NODE * p,int shape)196 shumul(NODE *p, int shape)
197 {
198
199 if (x2debug)
200 printf("shumul(%p)\n", p);
201
202 /* Turns currently anything into OREG on x86 */
203 if (shape & SOREG)
204 return SROREG;
205 return SRNOPE;
206 }
207
208 /*
209 * Rewrite operations on binary operators (like +, -, etc...).
210 * Called as a result of table lookup.
211 */
212 int
setbin(NODE * p)213 setbin(NODE *p)
214 {
215
216 if (x2debug)
217 printf("setbin(%p)\n", p);
218 return 0;
219
220 }
221
222 /* setup for assignment operator */
223 int
setasg(NODE * p,int cookie)224 setasg(NODE *p, int cookie)
225 {
226 if (x2debug)
227 printf("setasg(%p)\n", p);
228 return(0);
229 }
230
231 /* setup for unary operator */
232 int
setuni(NODE * p,int cookie)233 setuni(NODE *p, int cookie)
234 {
235 return 0;
236 }
237
238 /*
239 * Special handling of some instruction register allocation.
240 */
241 struct rspecial *
nspecial(struct optab * q)242 nspecial(struct optab *q)
243 {
244 switch (q->op) {
245 case SCONV:
246 if ((q->ltype & TINT) &&
247 q->rtype == (TLONGLONG|TULONGLONG|TLONG|TULONG)) {
248 static struct rspecial s[] = {
249 { NLEFT, RAX }, { NRES, RAX }, { 0 } };
250 return s;
251 }
252 break;
253
254 case DIV:
255 {
256 static struct rspecial s[] = {
257 { NEVER, RAX }, { NEVER, RDX },
258 { NLEFT, RAX }, { NRES, RAX },
259 { NORIGHT, RDX }, { NORIGHT, RAX }, { 0 } };
260 return s;
261 }
262 break;
263
264 case MOD:
265 if (q->ltype & TUCHAR) {
266 static struct rspecial s[] = {
267 { NEVER, RAX },
268 { NLEFT, RAX }, { NRES, RAX },
269 { NORIGHT, RAX }, { 0 } };
270 return s;
271 } else {
272 static struct rspecial s[] = {
273 { NEVER, RAX }, { NEVER, RDX },
274 { NLEFT, RAX }, { NRES, RDX },
275 { NORIGHT, RDX }, { NORIGHT, RAX }, { 0 } };
276 return s;
277 }
278 break;
279
280 case STARG:
281 {
282 static struct rspecial s[] = {
283 { NEVER, RDI },
284 { NLEFT, RSI },
285 { NEVER, RCX }, { 0 } };
286 return s;
287 }
288
289 case STASG:
290 {
291 static struct rspecial s[] = {
292 { NEVER, RDI },
293 { NRIGHT, RSI }, { NOLEFT, RSI },
294 { NOLEFT, RCX }, { NORIGHT, RCX },
295 { NEVER, RCX }, { 0 } };
296 return s;
297 }
298
299 case MUL:
300 if (q->lshape == SAREG) {
301 static struct rspecial s[] = {
302 { NEVER, RAX },
303 { NLEFT, RAX }, { NRES, RAX }, { 0 } };
304 return s;
305 }
306 break;
307
308 case LS:
309 case RS:
310 {
311 static struct rspecial s[] = {
312 { NRIGHT, RCX }, { NOLEFT, RCX }, { 0 } };
313 return s;
314 }
315 break;
316
317 default:
318 break;
319 }
320 comperr("nspecial entry %d", q - table);
321 return 0; /* XXX gcc */
322 }
323
324 /*
325 * Set evaluation order of a binary node if it differs from default.
326 */
327 int
setorder(NODE * p)328 setorder(NODE *p)
329 {
330 return 0; /* nothing differs on x86 */
331 }
332
333 /*
334 * set registers in calling conventions live.
335 */
336 int *
livecall(NODE * p)337 livecall(NODE *p)
338 {
339 static int r[NTEMPREG+1];
340 NODE *q;
341 int cr = 0;
342
343 if (optype(p->n_op) != BITYPE)
344 return r[0] = -1, r;
345
346 for (q = p->n_right; q->n_op == CM; q = q->n_left) {
347 if (q->n_right->n_op == ASSIGN &&
348 q->n_right->n_left->n_op == REG)
349 r[cr++] = regno(q->n_right->n_left);
350 }
351 if (q->n_op == ASSIGN && q->n_left->n_op == REG)
352 r[cr++] = regno(q->n_left);
353 r[cr++] = -1;
354 return r;
355 }
356
357 /*
358 * Signal whether the instruction is acceptable for this target.
359 */
360 int
acceptable(struct optab * op)361 acceptable(struct optab *op)
362 {
363 return 1;
364 }
365