* add p cc
[mascara-docs.git] / compilers / pcc / pcc-1.0.0 / arch / amd64 / order.c
blobf52fc8d532214c04a6e8aef0d3c30a2eebf3c95d
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.
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
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.
31 # include "pass2.h"
33 #include <string.h>
35 int canaddr(NODE *);
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 */
40 int
41 notoff(TWORD t, int r, CONSZ off, char *cp)
43 return(0); /* YES */
47 * Check if LS and try to make it indexable.
48 * Ignore SCONV to long.
49 * Return 0 if failed.
51 static int
52 findls(NODE *p, int check)
54 CONSZ c;
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;
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:
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.
79 void
80 offstar(NODE *p, int shape)
82 NODE *l;
84 if (x2debug) {
85 printf("offstar(%p)\n", p);
86 fwalk(p, e2print, 0);
89 if (isreg(p))
90 return; /* Matched (%rax) */
92 if (findls(p, 0))
93 return; /* Matched (,%rax,8) */
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) */
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.
129 void
130 myormake(NODE *q)
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 = "";
139 #define risreg(p) (p->n_op == REG)
140 if (x2debug) {
141 printf("myormake(%p)\n", q);
142 fwalk(q, e2print, 0);
144 r1 = r2 = MAXREGS;
145 sh = 1;
147 r = p = q->n_left;
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;
155 if (p->n_op == PLUS && risreg(p->n_left)) {
156 r1 = regno(p->n_left);
157 p = p->n_right;
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");
172 if (mkconv == 0)
173 return;
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);
187 * Shape matches for UMUL. Cooperates with offstar().
190 shumul(NODE *p, int shape)
193 if (x2debug)
194 printf("shumul(%p)\n", p);
196 /* Turns currently anything into OREG on x86 */
197 if (shape & SOREG)
198 return SROREG;
199 return SRNOPE;
203 * Rewrite operations on binary operators (like +, -, etc...).
204 * Called as a result of table lookup.
207 setbin(NODE *p)
210 if (x2debug)
211 printf("setbin(%p)\n", p);
212 return 0;
216 /* setup for assignment operator */
218 setasg(NODE *p, int cookie)
220 if (x2debug)
221 printf("setasg(%p)\n", p);
222 return(0);
225 /* setup for unary operator */
227 setuni(NODE *p, int cookie)
229 return 0;
233 * Special handling of some instruction register allocation.
235 struct rspecial *
236 nspecial(struct optab *q)
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;
246 break;
248 case DIV:
250 static struct rspecial s[] = {
251 { NEVER, RAX }, { NEVER, RDX },
252 { NLEFT, RAX }, { NRES, RAX },
253 { NORIGHT, RDX }, { NORIGHT, RAX }, { 0 } };
254 return s;
256 break;
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;
272 break;
274 case STARG:
276 static struct rspecial s[] = {
277 { NEVER, RDI },
278 { NLEFT, RSI },
279 { NEVER, RCX }, { 0 } };
280 return s;
283 case STASG:
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;
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;
300 break;
302 case LS:
303 case RS:
305 static struct rspecial s[] = {
306 { NRIGHT, RCX }, { NOLEFT, RCX }, { 0 } };
307 return s;
309 break;
311 default:
312 break;
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.
322 setorder(NODE *p)
324 return 0; /* nothing differs on x86 */
328 * set registers in calling conventions live.
330 int *
331 livecall(NODE *p)
333 static int r[NTEMPREG+1];
334 NODE *q;
335 int cr = 0;
337 if (optype(p->n_op) != BITYPE)
338 return r[0] = -1, r;
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);
347 r[cr++] = -1;
348 return r;
352 * Signal whether the instruction is acceptable for this target.
355 acceptable(struct optab *op)
357 return 1;