1 /* $Id: order.c,v 1.3 2008/10/04 08:43:17 ragge Exp $ */
2 /*
3 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29
30 # include "pass2.h"
31
32 #include <string.h>
33
34 int canaddr(NODE *);
35
36 /* is it legal to make an OREG or NAME entry which has an
37 * offset of off, (from a register of r), if the
38 * resulting thing had type t */
39 int
notoff(TWORD t,int r,CONSZ off,char * cp)40 notoff(TWORD t, int r, CONSZ off, char *cp)
41 {
42 return(0); /* YES */
43 }
44
45 static int
inctree(NODE * p)46 inctree(NODE *p)
47 {
48 if (p->n_op == MINUS && p->n_left->n_op == ASSIGN &&
49 p->n_left->n_right->n_op == PLUS &&
50 treecmp(p->n_left->n_left, p->n_left->n_right->n_left) &&
51 p->n_right->n_op == ICON && p->n_right->n_lval == 1 &&
52 p->n_left->n_right->n_right->n_op == ICON &&
53 p->n_left->n_right->n_right->n_lval == 1) {
54 /* post-increment by 1; (r0)+ */
55 if (isreg(p->n_left->n_left)) /* Ignore if index not in reg */
56 return 1;
57 }
58 return 0;
59 }
60
61 /*
62 * Turn a UMUL-referenced node into OREG.
63 * Be careful about register classes, this is a place where classes change.
64 */
65 void
offstar(NODE * p,int shape)66 offstar(NODE *p, int shape)
67 {
68 if (x2debug)
69 printf("offstar(%p)\n", p);
70
71 if (isreg(p))
72 return; /* Is already OREG */
73
74 if (p->n_op == UMUL)
75 p = p->n_left; /* double indexed umul */
76
77 if (inctree(p)) /* Do post-inc conversion */
78 return;
79
80 if( p->n_op == PLUS || p->n_op == MINUS ){
81 if (p->n_right->n_op == ICON) {
82 if (isreg(p->n_left) == 0)
83 (void)geninsn(p->n_left, INAREG);
84 /* Converted in ormake() */
85 return;
86 }
87 }
88 (void)geninsn(p, INAREG);
89 }
90
91 /*
92 * Do the actual conversion of offstar-found OREGs into real OREGs.
93 */
94 void
myormake(NODE * p)95 myormake(NODE *p)
96 {
97 NODE *q = p->n_left;
98
99 if (x2debug) {
100 printf("myormake(%p)\n", p);
101 fwalk(p, e2print, 0);
102 }
103 if (inctree(q)) {
104 if (q->n_left->n_left->n_op == TEMP)
105 return;
106 p->n_op = OREG;
107 p->n_lval = 0; /* Add support for index offset */
108 p->n_rval = R2PACK(regno(q->n_left->n_left), 0, 1);
109 tfree(q);
110 return;
111 }
112 if (q->n_op != OREG)
113 return;
114 p->n_op = OREG;
115 p->n_lval = q->n_lval;
116 p->n_rval = R2PACK(q->n_rval, 0, 0);
117 nfree(q);
118 }
119
120 /*
121 * Shape matches for UMUL. Cooperates with offstar().
122 */
123 int
shumul(NODE * p,int shape)124 shumul(NODE *p, int shape)
125 {
126
127 if (x2debug)
128 printf("shumul(%p)\n", p);
129
130 if (p->n_op == NAME && (shape & STARNM))
131 return SRDIR;
132 if (shape & SOREG)
133 return SROREG; /* Calls offstar */
134 return SRNOPE;
135 }
136
137 /*
138 * Rewrite operations on binary operators (like +, -, etc...).
139 * Called as a result of table lookup.
140 */
141 int
setbin(NODE * p)142 setbin(NODE *p)
143 {
144
145 if (x2debug)
146 printf("setbin(%p)\n", p);
147 return 0;
148
149 }
150
151 /* setup for assignment operator */
152 int
setasg(NODE * p,int cookie)153 setasg(NODE *p, int cookie)
154 {
155 if (x2debug)
156 printf("setasg(%p)\n", p);
157 return(0);
158 }
159
160 /* setup for unary operator */
161 int
setuni(NODE * p,int cookie)162 setuni(NODE *p, int cookie)
163 {
164 return(0);
165 }
166
167 /*
168 * Special handling of some instruction register allocation.
169 */
170 struct rspecial *
nspecial(struct optab * q)171 nspecial(struct optab *q)
172 {
173 switch (q->op) {
174 case MUL:
175 if (q->visit == INAREG) {
176 static struct rspecial s[] = { { NLEFT, R1 }, { 0 } };
177 return s;
178 } else if (q->visit == INBREG) {
179 static struct rspecial s[] = { { NRES, R01 }, { 0 } };
180 return s;
181 }
182 break;
183
184 case DIV:
185 if (q->visit == INAREG && q->ltype == TUNSIGNED) {
186 static struct rspecial s[] = {
187 { NLEFT, R0 }, { NRIGHT, R1 }, { NRES, R0 }, { 0 } };
188 return s;
189 } else if (q->visit == INAREG) {
190 static struct rspecial s[] = {
191 { NRES, R0 }, { 0 } };
192 return s;
193 } else if (q->visit == INBREG) {
194 static struct rspecial s[] = { { NRES, R01 }, { 0 } };
195 return s;
196 }
197 break;
198
199 case MOD:
200 if (q->visit == INAREG && q->ltype == TUNSIGNED) {
201 static struct rspecial s[] = {
202 { NLEFT, R0 }, { NRIGHT, R1 }, { NRES, R0 }, { 0 } };
203 return s;
204 } else if (q->visit == INBREG) {
205 static struct rspecial s[] = { { NRES, R01 }, { 0 } };
206 return s;
207 }
208 break;
209
210 case SCONV:
211 if (q->lshape == SAREG) {
212 static struct rspecial s[] = {
213 { NLEFT, R1 }, { NRES, R01 }, { 0 } };
214 return s;
215 }
216 break;
217 }
218 comperr("nspecial entry %d", q - table);
219 return 0; /* XXX gcc */
220 }
221
222 /*
223 * Set evaluation order of a binary node if it differs from default.
224 */
225 int
setorder(NODE * p)226 setorder(NODE *p)
227 {
228 return 0; /* nothing differs on x86 */
229 }
230
231 /*
232 * set registers in calling conventions live.
233 */
234 int *
livecall(NODE * p)235 livecall(NODE *p)
236 {
237 static int r[] = { -1 };
238
239 return r;
240 }
241
242 /*
243 * Signal whether the instruction is acceptable for this target.
244 */
245 int
acceptable(struct optab * op)246 acceptable(struct optab *op)
247 {
248 return 1;
249 }
250