1/* Id: local2.c,v 1.26 2011/06/23 13:41:25 ragge Exp */ 2/* $NetBSD$ */ 3 4/* 5 * Copyright (c) 2008 David Crawshaw <david@zentus.com> 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#include "pass1.h" 21#include "pass2.h" 22 23 24char * 25rnames[] = { 26 /* "\%g0", always zero, removed due to 31-element class limit */ 27 "\%g1", "\%g2", "\%g3", "\%g4", "\%g5", "\%g6", "\%g7", 28 "\%o0", "\%o1", "\%o2", "\%o3", "\%o4", "\%o5", "\%o6", "\%o7", 29 "\%l0", "\%l1", "\%l2", "\%l3", "\%l4", "\%l5", "\%l6", "\%l7", 30 "\%i0", "\%i1", "\%i2", "\%i3", "\%i4", "\%i5", "\%i6", "\%i7", 31 32 "\%f0", "\%f1", "\%f2", "\%f3", "\%f4", "\%f5", "\%f6", "\%f7", 33 "\%f8", "\%f9", "\%f10", "\%f11", "\%f12", "\%f13", "\%f14", "\%f15", 34 "\%f16", "\%f17", "\%f18", "\%f19", "\%f20", "\%f21", "\%f22", "\%f23", 35 "\%f24", "\%f25", "\%f26", "\%f27", "\%f28", "\%f29", "\%f30", 36 /*, "\%f31" XXX removed due to 31-element class limit */ 37 38 "\%f0", "\%f2", "\%f4", "\%f6", "\%f8", "\%f10", "\%f12", "\%f14", 39 "\%f16", "\%f18", "\%f20", "\%f22", "\%f24", "\%f26", "\%f28", "\%f30", 40 41 "\%sp", "\%fp", 42}; 43 44void 45deflab(int label) 46{ 47 printf(LABFMT ":\n", label); 48} 49 50void 51prologue(struct interpass_prolog *ipp) 52{ 53 int i, stack; 54 55 stack = V9RESERVE + V9STEP(p2maxautooff); 56 57 for (i = ipp->ipp_regs[0]; i; i >>= 1) 58 if (i & 1) 59 stack += 16; 60 61 /* TODO printf("\t.proc %d\n"); */ 62 if (SIMM13(stack)) 63 printf("\tsave %%sp,-%d,%%sp\n", stack); 64 else { 65 printf("\tsetx -%d,%%g4,%%g1\n", stack); 66 printf("\tsave %%sp,%%g1,%%sp\n"); 67 } 68} 69 70void 71eoftn(struct interpass_prolog *ipp) 72{ 73 printf("\tret\n"); 74 printf("\trestore\n"); 75 printf("\t.type %s,#function\n", ipp->ipp_name); 76 printf("\t.size %s,(.-%s)\n", ipp->ipp_name, ipp->ipp_name); 77} 78 79void 80hopcode(int f, int o) 81{ 82 char *str; 83 84 switch (o) { 85 case EQ: str = "brz"; break; 86 case NE: str = "brnz"; break; 87 case ULE: 88 case LE: str = "brlez"; break; 89 case ULT: 90 case LT: str = "brlz"; break; 91 case UGE: 92 case GE: str = "brgez"; break; 93 case UGT: 94 case GT: str = "brgz"; break; 95 case PLUS: str = "add"; break; 96 case MINUS: str = "sub"; break; 97 case AND: str = "and"; break; 98 case OR: str = "or"; break; 99 case ER: str = "xor"; break; 100 default: 101 comperr("unknown hopcode: %d (with %c)", o, f); 102 return; 103 } 104 105 printf("%s%c", str, f); 106} 107 108int 109tlen(NODE *p) 110{ 111 switch (p->n_type) { 112 case CHAR: 113 case UCHAR: 114 return 1; 115 case SHORT: 116 case USHORT: 117 return (SZSHORT / SZCHAR); 118 case FLOAT: 119 return (SZFLOAT / SZCHAR); 120 case DOUBLE: 121 return (SZDOUBLE / SZCHAR); 122 case INT: 123 case UNSIGNED: 124 return (SZINT / SZCHAR); 125 case LONG: 126 case ULONG: 127 case LONGLONG: 128 case ULONGLONG: 129 return SZLONGLONG / SZCHAR; 130 default: 131 if (!ISPTR(p->n_type)) 132 comperr("tlen type unknown: %d"); 133 return SZPOINT(p->n_type) / SZCHAR; 134 } 135} 136 137void 138zzzcode(NODE * p, int c) 139{ 140 char *str; 141 NODE *l, *r; 142 l = p->n_left; 143 r = p->n_right; 144 145 switch (c) { 146 147 case 'A': /* Add const. */ 148 if (ISPTR(l->n_type) && l->n_rval == FP) 149 r->n_lval += V9BIAS; 150 151 if (SIMM13(r->n_lval)) 152 expand(p, 0, "\tadd AL,AR,A1\t\t! add const\n"); 153 else 154 expand(p, 0, "\tsetx AR,A3,A2\t\t! add const\n" 155 "\tadd AL,A2,A1\n"); 156 break; 157 case 'B': /* Subtract const. */ 158 if (ISPTR(l->n_type) && l->n_rval == FP) 159 r->n_lval -= V9BIAS; 160 161 if (SIMM13(r->n_lval)) 162 expand(p, 0, "\tsub AL,AR,A1\t\t! subtract const\n"); 163 else 164 expand(p, 0, "\tsetx AR,A3,A2\t\t! subtract const\n" 165 "\tsub AL,A2,A1\n"); 166 break; 167 case 'C': /* Load constant to register. */ 168 if (ISPTR(p->n_type)) 169 expand(p, 0, 170 "\tsethi %h44(AL),A1\t\t! load label\n" 171 "\tor A1,%m44(AL),A1\n" 172 "\tsllx A1,12,A1\n" 173 "\tor A1,%l44(AL),A1\n"); 174 else if (SIMM13(p->n_lval)) 175 expand(p, 0, "\tor %g0,AL,A1\t\t\t! load const\n"); 176 else 177 expand(p, 0, "\tsetx AL,A2,A1\t\t! load const\n"); 178 break; 179 case 'F': /* Floating-point comparison, cf. hopcode(). */ 180 switch (p->n_op) { 181 case EQ: str = "fbe"; break; 182 case NE: str = "fbne"; break; 183 case ULE: 184 case LE: str = "fbule"; break; 185 case ULT: 186 case LT: str = "fbul"; break; 187 case UGE: 188 case GE: str = "fbuge"; break; 189 case UGT: 190 case GT: str = "fbug"; break; 191 /* XXX 192 case PLUS: str = "add"; break; 193 case MINUS: str = "sub"; break; 194 case AND: str = "and"; break; 195 case OR: str = "or"; break; 196 case ER: str = "xor"; break;*/ 197 default: 198 comperr("unknown float code: %d", p->n_op); 199 return; 200 } 201 printf(str); 202 break; 203 204 case 'Q': /* Structure assignment. */ 205 /* TODO Check if p->n_stsize is small and use a few ldx's 206 to move the struct instead of memcpy. The equiv. 207 could be done on all the architectures. */ 208 if (l->n_rval != O0) 209 printf("\tmov %s,%s\n", rnames[l->n_rval], rnames[O0]); 210 if (SIMM13(p->n_stsize)) 211 printf("\tor %%g0,%d,%%o2\n", p->n_stsize); 212 else 213 printf("\tsetx %d,%%g1,%%o2\n", p->n_stsize); 214 printf("\tcall memcpy\t\t\t! struct assign (dest, src, len)\n"); 215 printf("\tnop\n"); 216 break; 217 default: 218 cerror("unknown zzzcode call: %c", c); 219 } 220} 221 222int 223rewfld(NODE * p) 224{ 225 return (1); 226} 227 228int 229fldexpand(NODE *p, int cookie, char **cp) 230{ 231 printf("XXX fldexpand called\n"); /* XXX */ 232 return 1; 233} 234 235int 236flshape(NODE * p) 237{ 238 return SRREG; 239} 240 241int 242shtemp(NODE * p) 243{ 244 return 0; 245} 246 247 248void 249adrcon(CONSZ val) 250{ 251} 252 253void 254conput(FILE * fp, NODE * p) 255{ 256 if (p->n_op != ICON) { 257 comperr("conput got bad op: %s", copst(p->n_op)); 258 return; 259 } 260 261 if (p->n_name[0] != '\0') { 262 fprintf(fp, "%s", p->n_name); 263 if (p->n_lval > 0) 264 fprintf(fp, "+"); 265 if (p->n_lval) 266 fprintf(fp, CONFMT, p->n_lval); 267 } else 268 fprintf(fp, CONFMT, p->n_lval); 269} 270 271void 272insput(NODE * p) 273{ 274 comperr("insput"); 275} 276 277void 278upput(NODE *p, int size) 279{ 280 comperr("upput"); 281} 282 283void 284adrput(FILE * io, NODE * p) 285{ 286 int64_t off; 287 288 if (p->n_op == FLD) { 289 printf("adrput a FLD\n"); 290 p = p->n_left; 291 } 292 293 if (p->n_op == UMUL && p->n_right == 0) 294 p = p->n_left; 295 296 off = p->n_lval; 297 298 switch (p->n_op) { 299 case NAME: 300 if (p->n_name[0] != '\0') 301 fputs(p->n_name, io); 302 if (off > 0) 303 fprintf(io, "+"); 304 if (off != 0) 305 fprintf(io, CONFMT, (long long int)off); 306 return; 307 case OREG: 308 fprintf(io, "%s", rnames[p->n_rval]); 309 if (p->n_rval == FP) 310 off += V9BIAS; 311 if (p->n_rval == SP) 312 off += V9BIAS + V9RESERVE; 313 if (off > 0) 314 fprintf(io, "+"); 315 if (off) 316 fprintf(io, CONFMT, (CONSZ)off); 317 return; 318 case ICON: 319 /* addressable value of the constant */ 320 conput(io, p); 321 return; 322 case REG: 323 fputs(rnames[p->n_rval], io); 324 return; 325 case FUNARG: 326 /* We do something odd and store the stack offset in n_rval. */ 327 fprintf(io, "%d", V9BIAS + V9RESERVE + p->n_rval); 328 return; 329 default: 330 comperr("bad address, %s, node %p", copst(p->n_op), p); 331 return; 332 } 333} 334 335void 336cbgen(int o, int lab) 337{ 338} 339 340void 341myreader(struct interpass * ipole) 342{ 343} 344 345void 346mycanon(NODE * p) 347{ 348} 349 350void 351myoptim(struct interpass * ipole) 352{ 353} 354 355void 356rmove(int s, int d, TWORD t) 357{ 358 printf("\t"); 359 360 if (t == FLOAT) printf("fmovs"); 361 else if (t == DOUBLE) printf("fmovd"); 362 else printf("mov"); 363 364 printf(" %s,%s\t\t\t! rmove()\n", rnames[s], rnames[d]); 365} 366 367int 368gclass(TWORD t) 369{ 370 if (t == FLOAT) 371 return CLASSB; 372 if (t == DOUBLE) 373 return CLASSC; 374 return CLASSA; 375} 376 377void 378lastcall(NODE *p) 379{ 380} 381 382int 383special(NODE *p, int shape) 384{ 385 return SRNOPE; 386} 387 388void mflags(char *str) 389{ 390} 391 392int 393COLORMAP(int c, int *r) 394{ 395 int num=0; 396 397 switch (c) { 398 case CLASSA: 399 num += r[CLASSA]; 400 return num < 32; 401 case CLASSB: 402 num += r[CLASSB]; 403 num += 2*r[CLASSC]; 404 return num < 32;; 405 case CLASSC: 406 num += r[CLASSC]; 407 num += 2*r[CLASSB]; 408 return num < 17; 409 case CLASSD: 410 return 0; 411 default: 412 comperr("COLORMAP: unknown class: %d", c); 413 return 0; 414 } 415} 416/* 417 * Do something target-dependent for xasm arguments. 418 * Supposed to find target-specific constraints and rewrite them. 419 */ 420int 421myxasm(struct interpass *ip, NODE *p) 422{ 423 return 0; 424} 425