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 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 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 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 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 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 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 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 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 * 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 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 * 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 361 acceptable(struct optab *op) 362 { 363 return 1; 364 } 365