source: mainline/uspace/app/pcc/arch/amd64/order.c@ 423e5e87

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 423e5e87 was a7de7182, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Added pcc source tree (contents of pcc-1.0.0.tgz)

  • Property mode set to 100644
File size: 7.7 KB
Line 
1/* $Id: order.c,v 1.14 2011/02/18 17:08:31 ragge Exp $ */
2/*
3 * Copyright (c) 2008 Michael Shalayeff
4 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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
17 *
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.
28 */
29
30
31# include "pass2.h"
32
33#include <string.h>
34
35int canaddr(NODE *);
36
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 */
40int
41notoff(TWORD t, int r, CONSZ off, char *cp)
42{
43 return(0); /* YES */
44}
45
46/*
47 * Check if LS and try to make it indexable.
48 * Ignore SCONV to long.
49 * Return 0 if failed.
50 */
51static int
52findls(NODE *p, int check)
53{
54 CONSZ c;
55
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)
59 return 0;
60 if ((c = p->n_right->n_lval) != 1 && c != 2 && c != 3)
61 return 0;
62 if (check == 1 && p->n_left->n_op != REG)
63 return 0;
64 if (!isreg(p->n_left))
65 (void)geninsn(p->n_left, INAREG);
66 return 1;
67}
68
69/*
70 * Turn a UMUL-referenced node into OREG.
71 * Be careful about register classes, this is a place where classes change.
72 *
73 * AMD64 (and i386) have a quite powerful addressing scheme:
74 * : 4(%rax) 4 + %rax
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.
78 */
79void
80offstar(NODE *p, int shape)
81{
82 NODE *l;
83
84 if (x2debug) {
85 printf("offstar(%p)\n", p);
86 fwalk(p, e2print, 0);
87 }
88
89 if (isreg(p))
90 return; /* Matched (%rax) */
91
92 if (findls(p, 0))
93 return; /* Matched (,%rax,8) */
94
95 if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_left->n_op == ICON) {
96 l = p->n_right;
97 if (isreg(l))
98 return; /* Matched 4(%rax) */
99 if (findls(l, 0))
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) */
106 }
107 (void)geninsn(l, INAREG);
108 return; /* Generate 4(%rbx) */
109 }
110
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) */
120 }
121
122 (void)geninsn(p, INAREG);
123}
124
125/*
126 * Do the actual conversion of offstar-found OREGs into real OREGs.
127 * For simple OREGs conversion should already be done.
128 */
129void
130myormake(NODE *q)
131{
132 static int shtbl[] = { 1,2,4,8 };
133 NODE *p, *r;
134 CONSZ c = 0;
135 int r1, r2, sh;
136 int mkconv = 0;
137 char *n = "";
138
139#define risreg(p) (p->n_op == REG)
140 if (x2debug) {
141 printf("myormake(%p)\n", q);
142 fwalk(q, e2print, 0);
143 }
144 r1 = r2 = MAXREGS;
145 sh = 1;
146
147 r = p = q->n_left;
148
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;
152 p = p->n_right;
153 }
154
155 if (p->n_op == PLUS && risreg(p->n_left)) {
156 r1 = regno(p->n_left);
157 p = p->n_right;
158 }
159
160 if (findls(p, 1)) {
161 if (p->n_op == SCONV)
162 p = p->n_left;
163 sh = shtbl[(int)p->n_right->n_lval];
164 r2 = regno(p->n_left);
165 mkconv = 1;
166 } else if (risreg(p)) {
167 r2 = regno(p);
168 mkconv = 1;
169 } //else
170 // comperr("bad myormake tree");
171
172 if (mkconv == 0)
173 return;
174
175 q->n_op = OREG;
176 q->n_lval = c;
177 q->n_rval = R2PACK(r1, r2, sh);
178 q->n_name = n;
179 tfree(r);
180 if (x2debug) {
181 printf("myormake converted %p\n", q);
182 fwalk(q, e2print, 0);
183 }
184}
185
186/*
187 * Shape matches for UMUL. Cooperates with offstar().
188 */
189int
190shumul(NODE *p, int shape)
191{
192
193 if (x2debug)
194 printf("shumul(%p)\n", p);
195
196 /* Turns currently anything into OREG on x86 */
197 if (shape & SOREG)
198 return SROREG;
199 return SRNOPE;
200}
201
202/*
203 * Rewrite operations on binary operators (like +, -, etc...).
204 * Called as a result of table lookup.
205 */
206int
207setbin(NODE *p)
208{
209
210 if (x2debug)
211 printf("setbin(%p)\n", p);
212 return 0;
213
214}
215
216/* setup for assignment operator */
217int
218setasg(NODE *p, int cookie)
219{
220 if (x2debug)
221 printf("setasg(%p)\n", p);
222 return(0);
223}
224
225/* setup for unary operator */
226int
227setuni(NODE *p, int cookie)
228{
229 return 0;
230}
231
232/*
233 * Special handling of some instruction register allocation.
234 */
235struct rspecial *
236nspecial(struct optab *q)
237{
238 switch (q->op) {
239 case SCONV:
240 if ((q->ltype & TINT) &&
241 q->rtype == (TLONGLONG|TULONGLONG|TLONG|TULONG)) {
242 static struct rspecial s[] = {
243 { NLEFT, RAX }, { NRES, RAX }, { 0 } };
244 return s;
245 }
246 break;
247
248 case DIV:
249 {
250 static struct rspecial s[] = {
251 { NEVER, RAX }, { NEVER, RDX },
252 { NLEFT, RAX }, { NRES, RAX },
253 { NORIGHT, RDX }, { NORIGHT, RAX }, { 0 } };
254 return s;
255 }
256 break;
257
258 case MOD:
259 if (q->ltype & TUCHAR) {
260 static struct rspecial s[] = {
261 { NEVER, RAX },
262 { NLEFT, RAX }, { NRES, RAX },
263 { NORIGHT, RAX }, { 0 } };
264 return s;
265 } else {
266 static struct rspecial s[] = {
267 { NEVER, RAX }, { NEVER, RDX },
268 { NLEFT, RAX }, { NRES, RDX },
269 { NORIGHT, RDX }, { NORIGHT, RAX }, { 0 } };
270 return s;
271 }
272 break;
273
274 case STARG:
275 {
276 static struct rspecial s[] = {
277 { NEVER, RDI },
278 { NLEFT, RSI },
279 { NEVER, RCX }, { 0 } };
280 return s;
281 }
282
283 case STASG:
284 {
285 static struct rspecial s[] = {
286 { NEVER, RDI },
287 { NRIGHT, RSI }, { NOLEFT, RSI },
288 { NOLEFT, RCX }, { NORIGHT, RCX },
289 { NEVER, RCX }, { 0 } };
290 return s;
291 }
292
293 case MUL:
294 if (q->lshape == SAREG) {
295 static struct rspecial s[] = {
296 { NEVER, RAX },
297 { NLEFT, RAX }, { NRES, RAX }, { 0 } };
298 return s;
299 }
300 break;
301
302 case LS:
303 case RS:
304 {
305 static struct rspecial s[] = {
306 { NRIGHT, RCX }, { NOLEFT, RCX }, { 0 } };
307 return s;
308 }
309 break;
310
311 default:
312 break;
313 }
314 comperr("nspecial entry %d", q - table);
315 return 0; /* XXX gcc */
316}
317
318/*
319 * Set evaluation order of a binary node if it differs from default.
320 */
321int
322setorder(NODE *p)
323{
324 return 0; /* nothing differs on x86 */
325}
326
327/*
328 * set registers in calling conventions live.
329 */
330int *
331livecall(NODE *p)
332{
333 static int r[NTEMPREG+1];
334 NODE *q;
335 int cr = 0;
336
337 if (optype(p->n_op) != BITYPE)
338 return r[0] = -1, r;
339
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);
344 }
345 if (q->n_op == ASSIGN && q->n_left->n_op == REG)
346 r[cr++] = regno(q->n_left);
347 r[cr++] = -1;
348 return r;
349}
350
351/*
352 * Signal whether the instruction is acceptable for this target.
353 */
354int
355acceptable(struct optab *op)
356{
357 return 1;
358}
Note: See TracBrowser for help on using the repository browser.