* add p cc
[mascara-docs.git] / compilers / pcc / pcc-1.0.0 / arch / arm / order.c
blob021bc465376b26ddb3b9960bcf99bbcb7911d9cc
1 /* $Id: order.c,v 1.9 2008/09/27 07:35:22 ragge Exp $ */
2 /*
3 * Copyright (c) 2007 Gregory McGarry (g.mcgarry@ieee.org).
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 * Machine-dependent code-generation strategy (pass 2).
34 #include <assert.h>
35 #include <string.h>
37 #include "pass2.h"
40 * Check size of offset in OREG. Called by oregok() to see if an
41 * OREG can be generated.
43 int
44 notoff(TWORD ty, int r, CONSZ off, char *cp)
46 if (cp && cp[0]) return 1;
47 if (DEUNSIGN(ty) == INT || ty == UCHAR)
48 return !(off < 4096 && off > -4096);
49 else
50 return !(off < 256 && off > -256);
54 * Generate instructions for an OREG. Why is this routine MD?
55 * Called by swmatch().
57 void
58 offstar(NODE *p, int shape)
60 NODE *r;
62 if (isreg(p))
63 return; /* Is already OREG */
65 r = p->n_right;
66 if( p->n_op == PLUS || p->n_op == MINUS ){
67 if( r->n_op == ICON ){
68 if (isreg(p->n_left) == 0)
69 (void)geninsn(p->n_left, INAREG);
70 /* Converted in ormake() */
71 return;
73 /* usually for arraying indexing: */
74 if (r->n_op == LS && r->n_right->n_op == ICON &&
75 r->n_right->n_lval == 2 && p->n_op == PLUS) {
76 if (isreg(p->n_left) == 0)
77 (void)geninsn(p->n_left, INAREG);
78 if (isreg(r->n_left) == 0)
79 (void)geninsn(r->n_left, INAREG);
80 return;
83 (void)geninsn(p, INAREG);
87 * Unable to convert to OREG (notoff() returned failure). Output
88 * suitable instructions to replace OREG.
90 void
91 myormake(NODE *q)
93 NODE *p, *r;
95 if (x2debug)
96 printf("myormake(%p)\n", q);
98 p = q->n_left;
101 * This handles failed OREGs conversions, due to the offset
102 * being too large for an OREG.
104 if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_right->n_op == ICON) {
105 if (isreg(p->n_left) == 0)
106 (void)geninsn(p->n_left, INAREG);
107 if (isreg(p->n_right) == 0)
108 (void)geninsn(p->n_right, INAREG);
109 (void)geninsn(p, INAREG);
110 } else if (p->n_op == REG) {
111 q->n_op = OREG;
112 q->n_lval = p->n_lval;
113 q->n_rval = p->n_rval;
114 tfree(p);
115 } else if (p->n_op == PLUS && (r = p->n_right)->n_op == LS &&
116 r->n_right->n_op == ICON && r->n_right->n_lval == 2 &&
117 p->n_left->n_op == REG && r->n_left->n_op == REG) {
118 q->n_op = OREG;
119 q->n_lval = 0;
120 q->n_rval = R2PACK(p->n_left->n_rval, r->n_left->n_rval,
121 r->n_right->n_lval);
122 tfree(p);
127 * Check to if the UMUL node can be converted into an OREG.
130 shumul(NODE *p, int shape)
132 /* Turns currently anything into OREG */
133 if (shape & SOREG)
134 return SROREG;
135 return SRNOPE;
139 * Rewrite operations on binary operators (like +, -, etc...).
140 * Called as a result of a failed table lookup.
142 * Return nonzero to retry table search on new tree, or zero to fail.
145 setbin(NODE *p)
147 return 0;
152 * Rewrite assignment operations.
153 * Called as a result of a failed table lookup.
155 * Return nonzero to retry table search on new tree, or zero to fail.
158 setasg(NODE *p, int cookie)
160 return 0;
164 * Rewrite UMUL operation.
165 * Called as a result of a failed table lookup.
167 * Return nonzero to retry table search on new tree, or zero to fail.
170 setuni(NODE *p, int cookie)
172 return 0;
176 * Special handling of some instruction register allocation.
178 * Called as a result of specifying NSPECIAL in the table.
180 struct rspecial *
181 nspecial(struct optab *q)
184 switch (q->op) {
186 #if !defined(ARM_HAS_FPA) && !defined(ARM_HAS_VFP)
187 case UMINUS:
188 case SCONV:
189 if (q->lshape == SBREG && q->rshape == SAREG) {
190 static struct rspecial s[] = {
191 { NLEFT, R0R1 },
192 { NRES, R0 },
193 { 0 }
195 return s;
196 } else if (q->lshape == SAREG && q->rshape == SBREG) {
197 static struct rspecial s[] = {
198 { NLEFT, R0 },
199 { NRES, R0R1 },
200 { 0 }
202 return s;
203 } else if (q->lshape == SAREG && q->rshape == SAREG) {
204 static struct rspecial s[] = {
205 { NLEFT, R0 },
206 { NRES, R0 },
207 { 0 }
209 return s;
210 } else if (q->lshape == SBREG && q->rshape == SBREG) {
211 static struct rspecial s[] = {
212 { NLEFT, R0R1 },
213 { NRES, R0R1 },
214 { 0 }
216 return s;
219 case OPLOG:
220 if (q->lshape == SBREG) {
221 static struct rspecial s[] = {
222 { NLEFT, R0R1 },
223 { NRIGHT, R2R3 },
224 { NRES, R0 },
225 { 0 }
227 return s;
228 } else if (q->lshape == SAREG) {
229 static struct rspecial s[] = {
230 { NLEFT, R0 },
231 { NRIGHT, R1 },
232 { NRES, R0 },
233 { 0 }
235 return s;
237 case PLUS:
238 case MINUS:
239 case MUL:
240 #endif
241 case MOD:
242 case DIV:
243 if (q->lshape == SBREG) {
244 static struct rspecial s[] = {
245 { NLEFT, R0R1 },
246 { NRIGHT, R2R3 },
247 { NRES, R0R1 },
248 { 0 }
250 return s;
251 } else if (q->lshape == SAREG) {
252 static struct rspecial s[] = {
253 { NLEFT, R0 },
254 { NRIGHT, R1 },
255 { NRES, R0 },
256 { 0 }
258 return s;
260 case LS:
261 case RS:
262 if (q->lshape == SBREG) {
263 static struct rspecial s[] = {
264 { NLEFT, R0R1 },
265 { NRIGHT, R2 },
266 { NRES, R0R1 },
267 { 0 }
269 return s;
270 } else if (q->lshape == SAREG) {
271 static struct rspecial s[] = {
272 { NLEFT, R0 },
273 { NRIGHT, R1 },
274 { NRES, R0 },
275 { 0 }
277 return s;
279 case STASG:
281 static struct rspecial s[] = {
282 { NEVER, R0 },
283 { NRIGHT, R1 },
284 { NEVER, R2 },
285 { 0 } };
286 return s;
288 break;
290 default:
291 break;
294 #ifdef PCC_DEBUG
295 comperr("nspecial entry %d [0x%x]: %s", q - table, q->op, q->cstring);
296 #endif
297 return 0; /* XXX gcc */
301 * Set evaluation order of a binary node ('+','-', '*', '/', etc) if it
302 * differs from default.
305 setorder(NODE *p)
307 return 0;
311 * Set registers "live" at function calls (like arguments in registers).
312 * This is for liveness analysis of registers.
314 int *
315 livecall(NODE *p)
317 static int r[] = { R3, R2, R1, R0, -1 };
318 int num = 1;
320 if (p->n_op != CALL && p->n_op != FORTCALL && p->n_op != STCALL)
321 return &r[4-0];
323 for (p = p->n_right; p->n_op == CM; p = p->n_left)
324 num += szty(p->n_right->n_type);
325 num += szty(p->n_right->n_type);
327 num = (num > 4 ? 4 : num);
329 return &r[4 - num];
333 * Signal whether the instruction is acceptable for this target.
336 acceptable(struct optab *op)
338 return features(op->visit & 0xffff0000);