code.c (15296B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 5 #include <scc/cstd.h> 6 #include <scc/scc.h> 7 8 #include "arch.h" 9 #include "../cc2.h" 10 11 #define ADDR_LEN (INTIDENTSIZ+64) 12 13 static void binary(void), unary(void), store(void), jmp(void), ret(void), 14 branch(void), call(void), ecall(void), param(void), 15 asalloc(void), form2local(void), blit(void), vastart(void), 16 vaarg(void); 17 18 static struct opdata { 19 void (*fun)(void); 20 char *txt; 21 char letter; 22 } optbl [] = { 23 [ASLDSB] = {.fun = unary, .txt = "loadsb", .letter = 'w'}, 24 [ASLDUB] = {.fun = unary, .txt = "loadub", .letter = 'w'}, 25 [ASLDSH] = {.fun = unary, .txt = "loadsh", .letter = 'w'}, 26 [ASLDUH] = {.fun = unary, .txt = "loaduh", .letter = 'w'}, 27 [ASLDSW] = {.fun = unary, .txt = "loadsw", .letter = 'w'}, 28 [ASLDUW] = {.fun = unary, .txt = "loaduw", .letter = 'w'}, 29 [ASLDL] = {.fun = unary, .txt = "loadl", .letter = 'l'}, 30 [ASLDS] = {.fun = unary, .txt = "loads", .letter = 's'}, 31 [ASLDD] = {.fun = unary, .txt = "loadd", .letter = 'd'}, 32 33 [ASCOPYB] = {.fun = unary, .txt = "copy", .letter = 'b'}, 34 [ASCOPYH] = {.fun = unary, .txt = "copy", .letter = 'h'}, 35 [ASCOPYW] = {.fun = unary, .txt = "copy", .letter = 'w'}, 36 [ASCOPYL] = {.fun = unary, .txt = "copy", .letter = 'l'}, 37 [ASCOPYS] = {.fun = unary, .txt = "copy", .letter = 's'}, 38 [ASCOPYD] = {.fun = unary, .txt = "copy", .letter = 'd'}, 39 40 [ASSTB] = {.fun = store, .txt = "store", .letter = 'b'}, 41 [ASSTH] = {.fun = store, .txt = "store", .letter = 'h'}, 42 [ASSTW] = {.fun = store, .txt = "store", .letter = 'w'}, 43 [ASSTL] = {.fun = store, .txt = "store", .letter = 'l'}, 44 [ASSTM] = {.fun = blit}, 45 [ASSTS] = {.fun = store, .txt = "store", .letter = 's'}, 46 [ASSTD] = {.fun = store, .txt = "store", .letter = 'd'}, 47 48 [ASADDW] = {.fun = binary, .txt = "add", .letter = 'w'}, 49 [ASSUBW] = {.fun = binary, .txt = "sub", .letter = 'w'}, 50 [ASMULW] = {.fun = binary, .txt = "mul", .letter = 'w'}, 51 [ASMODW] = {.fun = binary, .txt = "rem", .letter = 'w'}, 52 [ASUMODW] = {.fun = binary, .txt = "urem", .letter = 'w'}, 53 [ASDIVW] = {.fun = binary, .txt = "div", .letter = 'w'}, 54 [ASUDIVW] = {.fun = binary, .txt = "udiv", .letter = 'w'}, 55 [ASSHLW] = {.fun = binary, .txt = "shl", .letter = 'w'}, 56 [ASSHRW] = {.fun = binary, .txt = "sar", .letter = 'w'}, 57 [ASUSHRW] = {.fun = binary, .txt = "shr", .letter = 'w'}, 58 [ASLTW] = {.fun = binary, .txt = "csltw", .letter = 'w'}, 59 [ASULTW] = {.fun = binary, .txt = "cultw", .letter = 'w'}, 60 [ASGTW] = {.fun = binary, .txt = "csgtw", .letter = 'w'}, 61 [ASUGTW] = {.fun = binary, .txt = "cugtw", .letter = 'w'}, 62 [ASLEW] = {.fun = binary, .txt = "cslew", .letter = 'w'}, 63 [ASULEW] = {.fun = binary, .txt = "culew", .letter = 'w'}, 64 [ASGEW] = {.fun = binary, .txt = "csgew", .letter = 'w'}, 65 [ASUGEW] = {.fun = binary, .txt = "cugew", .letter = 'w'}, 66 [ASEQW] = {.fun = binary, .txt = "ceqw", .letter = 'w'}, 67 [ASNEW] = {.fun = binary, .txt = "cnew", .letter = 'w'}, 68 [ASBANDW] = {.fun = binary, .txt = "and", .letter = 'w'}, 69 [ASBORW] = {.fun = binary, .txt = "or", .letter = 'w'}, 70 [ASBXORW] = {.fun = binary, .txt = "xor", .letter = 'w'}, 71 72 [ASADDL] = {.fun = binary, .txt = "add", .letter = 'l'}, 73 [ASSUBL] = {.fun = binary, .txt = "sub", .letter = 'l'}, 74 [ASMULL] = {.fun = binary, .txt = "mul", .letter = 'l'}, 75 [ASMODL] = {.fun = binary, .txt = "rem", .letter = 'l'}, 76 [ASUMODL] = {.fun = binary, .txt = "urem", .letter = 'l'}, 77 [ASDIVL] = {.fun = binary, .txt = "div", .letter = 'l'}, 78 [ASUDIVL] = {.fun = binary, .txt = "udiv", .letter = 'l'}, 79 [ASSHLL] = {.fun = binary, .txt = "shl", .letter = 'l'}, 80 [ASSHRL] = {.fun = binary, .txt = "sar", .letter = 'l'}, 81 [ASUSHRL] = {.fun = binary, .txt = "shr", .letter = 'l'}, 82 [ASLTL] = {.fun = binary, .txt = "csltl", .letter = 'w'}, 83 [ASULTL] = {.fun = binary, .txt = "cultl", .letter = 'w'}, 84 [ASGTL] = {.fun = binary, .txt = "csgtl", .letter = 'w'}, 85 [ASUGTL] = {.fun = binary, .txt = "cugtl", .letter = 'w'}, 86 [ASLEL] = {.fun = binary, .txt = "cslel", .letter = 'w'}, 87 [ASULEL] = {.fun = binary, .txt = "culel", .letter = 'w'}, 88 [ASGEL] = {.fun = binary, .txt = "csgel", .letter = 'w'}, 89 [ASUGEL] = {.fun = binary, .txt = "cugel", .letter = 'w'}, 90 [ASEQL] = {.fun = binary, .txt = "ceql", .letter = 'w'}, 91 [ASNEL] = {.fun = binary, .txt = "cnel", .letter = 'w'}, 92 [ASBANDL] = {.fun = binary, .txt = "and", .letter = 'l'}, 93 [ASBORL] = {.fun = binary, .txt = "or", .letter = 'l'}, 94 [ASBXORL] = {.fun = binary, .txt = "xor", .letter = 'l'}, 95 96 [ASADDS] = {.fun = binary, .txt = "add", .letter = 's'}, 97 [ASSUBS] = {.fun = binary, .txt = "sub", .letter = 's'}, 98 [ASMULS] = {.fun = binary, .txt = "mul", .letter = 's'}, 99 [ASDIVS] = {.fun = binary, .txt = "div", .letter = 's'}, 100 [ASLTS] = {.fun = binary, .txt = "clts", .letter = 'w'}, 101 [ASGTS] = {.fun = binary, .txt = "cgts", .letter = 'w'}, 102 [ASLES] = {.fun = binary, .txt = "cles", .letter = 'w'}, 103 [ASGES] = {.fun = binary, .txt = "cges", .letter = 'w'}, 104 [ASEQS] = {.fun = binary, .txt = "ceqs", .letter = 'w'}, 105 [ASNES] = {.fun = binary, .txt = "cnes", .letter = 'w'}, 106 107 [ASADDD] = {.fun = binary, .txt = "add", .letter = 'd'}, 108 [ASSUBD] = {.fun = binary, .txt = "sub", .letter = 'd'}, 109 [ASMULD] = {.fun = binary, .txt = "mul", .letter = 'd'}, 110 [ASDIVD] = {.fun = binary, .txt = "div", .letter = 'd'}, 111 [ASLTD] = {.fun = binary, .txt = "cltd", .letter = 'w'}, 112 [ASGTD] = {.fun = binary, .txt = "cgtd", .letter = 'w'}, 113 [ASLED] = {.fun = binary, .txt = "cled", .letter = 'w'}, 114 [ASGED] = {.fun = binary, .txt = "cged", .letter = 'w'}, 115 [ASEQD] = {.fun = binary, .txt = "ceqd", .letter = 'w'}, 116 [ASNED] = {.fun = binary, .txt = "cned", .letter = 'w'}, 117 118 [ASEXTBW] = {.fun = unary, .txt = "extsb", .letter = 'w'}, 119 [ASUEXTBW]= {.fun = unary, .txt = "extub", .letter = 'w'}, 120 [ASEXTBL] = {.fun = unary, .txt = "extsb", .letter = 'l'}, 121 [ASUEXTBL]= {.fun = unary, .txt = "extub", .letter = 'l'}, 122 [ASEXTHW] = {.fun = unary, .txt = "extsh", .letter = 'w'}, 123 [ASUEXTHW]= {.fun = unary, .txt = "extuh", .letter = 'w'}, 124 [ASEXTHL] = {.fun = unary, .txt = "extsh", .letter = 'l'}, 125 [ASUEXTHL]= {.fun = unary, .txt = "extuh", .letter = 'l'}, 126 [ASEXTWL] = {.fun = unary, .txt = "extsw", .letter = 'l'}, 127 [ASUEXTWL]= {.fun = unary, .txt = "extuw", .letter = 'l'}, 128 129 [ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'}, 130 [ASSTOUL] = {.fun = unary, .txt = "stoui", .letter = 'l'}, 131 [ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'}, 132 [ASSTOUW] = {.fun = unary, .txt = "stoui", .letter = 'w'}, 133 [ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'}, 134 [ASDTOUL] = {.fun = unary, .txt = "dtoui", .letter = 'l'}, 135 [ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'}, 136 [ASDTOUW] = {.fun = unary, .txt = "dtoui", .letter = 'w'}, 137 138 [ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'}, 139 [ASUWTOD] = {.fun = unary, .txt = "uwtof", .letter = 'd'}, 140 [ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'}, 141 [ASUWTOS] = {.fun = unary, .txt = "uwtof", .letter = 's'}, 142 [ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'}, 143 [ASULTOD] = {.fun = unary, .txt = "ultof", .letter = 'd'}, 144 [ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'}, 145 [ASULTOS] = {.fun = unary, .txt = "ultof", .letter = 's'}, 146 147 [ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'}, 148 [ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'}, 149 150 [ASBRANCH] = {.fun = branch}, 151 [ASJMP] = {.fun = jmp}, 152 [ASRET] = {.fun = ret}, 153 [ASCALL] = {.fun = call}, 154 [ASCALLE] = {.fun = ecall, .txt = ")"}, 155 [ASCALLEX] = {.fun = ecall, .txt = ", ...)"}, 156 [ASPAR] = {.fun = param, .txt = "%s %s, "}, 157 [ASPARE] = {.fun = param, .txt = "%s %s"}, 158 [ASALLOC] = {.fun = asalloc}, 159 [ASFORM] = {.fun = form2local}, 160 161 [ASVSTAR] = {.fun = vastart}, 162 [ASVARG] = {.fun = vaarg}, 163 }; 164 165 static char buff[ADDR_LEN]; 166 /* 167 * : is for user-defined Aggregate Types 168 * $ is for globals (represented by a pointer) 169 * % is for function-scope temporaries 170 * @ is for block labels 171 */ 172 static char 173 sigil(Symbol *sym) 174 { 175 switch (sym->kind) { 176 case SEXTRN: 177 case SGLOB: 178 case SPRIV: 179 case SLOCAL: 180 return '$'; 181 case SAUTO: 182 case STMP: 183 return '%'; 184 case SLABEL: 185 return '@'; 186 default: 187 abort(); 188 } 189 } 190 191 static char * 192 symname(Symbol *sym) 193 { 194 char c = sigil(sym); 195 196 if (sym->name) { 197 switch (sym->kind) { 198 case SEXTRN: 199 case SGLOB: 200 sprintf(buff, "%c%s", c, sym->name); 201 return buff; 202 case SLOCAL: 203 case SPRIV: 204 case SAUTO: 205 sprintf(buff, "%c%s.L%u", c, sym->name, sym->id); 206 return buff; 207 default: 208 abort(); 209 } 210 } 211 sprintf(buff, "%c.L%u", c, sym->numid); 212 213 return buff; 214 } 215 216 static void 217 emitconst(Node *np) 218 { 219 switch (np->type.size) { 220 case 1: 221 printf("%d", (int) np->u.i & 0xFF); 222 break; 223 case 2: 224 printf("%d", (int) np->u.i & 0xFFFF); 225 break; 226 case 4: 227 printf("%ld", (long) np->u.i & 0xFFFFFFFF); 228 break; 229 case 8: 230 printf("%lld", (long long) np->u.i); 231 break; 232 default: 233 abort(); 234 } 235 } 236 237 static void 238 emittree(Node *np) 239 { 240 if (!np) 241 return; 242 243 switch (np->op) { 244 case OSTRING: 245 pprint(np->u.s); 246 free(np->u.s); 247 np->u.s = NULL; 248 break; 249 case OCONST: 250 emitconst(np); 251 break; 252 case OADDR: 253 emittree(np->left); 254 break; 255 case OMEM: 256 fputs(symname(np->u.sym), stdout); 257 break; 258 default: 259 emittree(np->left); 260 printf(" %c ", np->op); 261 emittree(np->right); 262 break; 263 } 264 } 265 266 static char * 267 size2asm(Type *tp) 268 { 269 static char spec[ADDR_LEN]; 270 271 if (tp->flags & STRF) { 272 return "b"; 273 } else if (tp->flags & INTF) { 274 switch (tp->size) { 275 case 1: 276 return "b"; 277 case 2: 278 return "h"; 279 case 4: 280 return "w"; 281 case 8: 282 return "l"; 283 } 284 } else if (tp->flags & FLOATF) { 285 if (tp->size == 4) 286 return "s"; 287 else if (tp->size == 8) 288 return "d"; 289 } 290 291 abort(); 292 } 293 294 void 295 defglobal(Symbol *sym) 296 { 297 Type *tp = &sym->type; 298 299 if (sym->kind == SEXTRN) 300 return; 301 if (sym->kind == SGLOB) 302 fputs("export ", stdout); 303 if ((tp->flags & INITF) == 0) 304 fputs("common ", stdout); 305 306 printf("data %s = align %d {\n", 307 symname(sym), 308 tp->align); 309 if ((tp->flags & INITF) == 0) 310 printf("\tz\t%lu\n}\n", tp->size); 311 } 312 313 void 314 defpar(Symbol *sym) 315 { 316 if (sym->kind == SREG) 317 sym->kind = SAUTO; 318 sym->type.flags |= PARF; 319 } 320 321 void 322 defvar(Symbol *sym) 323 { 324 if (sym->kind == SREG) 325 sym->kind = SAUTO; 326 } 327 328 void 329 data(Node *np) 330 { 331 printf("\t%s\t", size2asm(&np->type)); 332 emittree(np); 333 putchar(','); 334 putchar('\n'); 335 } 336 337 static char * 338 size2stack(Type *tp) 339 { 340 static char spec[ADDR_LEN]; 341 342 if (tp->flags & INTF) { 343 switch (tp->size) { 344 case 1: 345 case 2: 346 case 4: 347 return "w"; 348 case 8: 349 return "l"; 350 } 351 } else if (tp->flags & FLOATF) { 352 if (tp->size == 4) 353 return "s"; 354 else if (tp->size == 8) 355 return "d"; 356 } else if (tp->flags & (ARRF|AGGRF)) { 357 sprintf(spec, ":.%u", tp->id); 358 return spec; 359 } else if (tp->size == 0) { 360 return "w"; 361 } 362 abort(); 363 } 364 365 void 366 deftype(Type *tp) 367 { 368 printf("type :.%u = align %d { %lu }\n", 369 tp->id, tp->align, tp->size); 370 } 371 372 void 373 writeout(void) 374 { 375 Symbol *p; 376 Type *tp; 377 char *sep; 378 int haslabel = 0; 379 380 if (!curfun) 381 return; 382 if (curfun->kind == SGLOB) 383 fputs("export ", stdout); 384 printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun)); 385 386 /* declare formal parameters */ 387 sep = ""; 388 for (p = locals; p; p = p->next) { 389 if ((p->type.flags & PARF) == 0) 390 continue; 391 printf("%s%s %s%s", 392 sep, size2stack(&p->type), 393 symname(p), 394 (p->type.flags & AGGRF) ? "" : ".val"); 395 sep = ","; 396 } 397 printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : ""); 398 399 /* emit assembler instructions */ 400 for (pc = prog; pc; pc = pc->next) { 401 if (pc->label) { 402 haslabel = 1; 403 printf("%s\n", symname(pc->label)); 404 } 405 if (pc->op == ASLABEL) 406 continue; 407 if (pc->flags&BBENTRY && !haslabel) 408 printf("%s\n", symname(newlabel())); 409 (*optbl[pc->op].fun)(); 410 if (!pc->label) 411 haslabel = 0; 412 } 413 414 puts("}"); 415 } 416 417 static char * 418 addr2txt(Addr *a) 419 { 420 switch (a->kind) { 421 case SCONST: 422 sprintf(buff, "%llu", (unsigned long long) a->u.i); 423 return buff; 424 case SAUTO: 425 case SLABEL: 426 case STMP: 427 case SGLOB: 428 case SEXTRN: 429 case SPRIV: 430 case SLOCAL: 431 return symname(a->u.sym); 432 default: 433 abort(); 434 } 435 } 436 437 static void 438 binary(void) 439 { 440 struct opdata *p = &optbl[pc->op]; 441 char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN]; 442 443 strcpy(to, addr2txt(&pc->to)); 444 strcpy(from1, addr2txt(&pc->from1)); 445 strcpy(from2, addr2txt(&pc->from2)); 446 printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2); 447 } 448 449 static void 450 blit(void) 451 { 452 Type *tp = &pc->to.u.sym->type; 453 char to[ADDR_LEN], from[ADDR_LEN]; 454 455 strcpy(to, addr2txt(&pc->to)); 456 strcpy(from, addr2txt(&pc->from1)); 457 printf("\t\tblit\t%s,%s,%lu\n", from, to, tp->size); 458 } 459 460 static void 461 store(void) 462 { 463 struct opdata *p = &optbl[pc->op]; 464 char to[ADDR_LEN], from[ADDR_LEN]; 465 466 strcpy(to, addr2txt(&pc->to)); 467 strcpy(from, addr2txt(&pc->from1)); 468 printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to); 469 } 470 471 static void 472 unary(void) 473 { 474 struct opdata *p = &optbl[pc->op]; 475 char to[ADDR_LEN], from[ADDR_LEN]; 476 477 strcpy(to, addr2txt(&pc->to)); 478 strcpy(from, addr2txt(&pc->from1)); 479 printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from); 480 } 481 482 static void 483 call(void) 484 { 485 char to[ADDR_LEN], from[ADDR_LEN]; 486 Symbol *sym = pc->to.u.sym; 487 488 strcpy(to, addr2txt(&pc->to)); 489 strcpy(from, addr2txt(&pc->from1)); 490 printf("\t%s =%s\tcall\t%s(", 491 to, size2stack(&sym->type), from); 492 } 493 494 static void 495 param(void) 496 { 497 Symbol *sym = pc->from2.u.sym; 498 499 printf(optbl[pc->op].txt, 500 size2stack(&sym->type), addr2txt(&pc->from1)); 501 } 502 503 static void 504 ecall(void) 505 { 506 struct opdata *p = &optbl[pc->op]; 507 508 puts(p->txt); 509 } 510 511 static void 512 ret(void) 513 { 514 if (pc->from1.kind == SNONE) 515 puts("\t\tret"); 516 else 517 printf("\t\tret\t%s\n", addr2txt(&pc->from1)); 518 } 519 520 static void 521 jmp(void) 522 { 523 printf("\t\tjmp\t%s\n", addr2txt(&pc->from1)); 524 } 525 526 static void 527 branch(void) 528 { 529 char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN]; 530 531 strcpy(to, addr2txt(&pc->to)); 532 strcpy(from1, addr2txt(&pc->from1)); 533 strcpy(from2, addr2txt(&pc->from2)); 534 printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2); 535 } 536 537 static void 538 vastart(void) 539 { 540 printf("\t\tvastart %s\n", addr2txt(&pc->from1)); 541 } 542 543 static void 544 vaarg(void) 545 { 546 Symbol *sym = pc->to.u.sym; 547 Type *tp = &sym->type; 548 char to[ADDR_LEN], from[ADDR_LEN]; 549 550 strcpy(to, addr2txt(&pc->to)); 551 strcpy(from, addr2txt(&pc->from1)); 552 printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from); 553 } 554 555 static void 556 asalloc(void) 557 { 558 Symbol *sym = pc->to.u.sym; 559 Type *tp = &sym->type; 560 extern Type ptrtype; 561 562 printf("\t%s =%s\talloc%lu\t%lu\n", 563 symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size); 564 } 565 566 static void 567 form2local(void) 568 { 569 Symbol *sym = pc->to.u.sym; 570 Type *tp = &sym->type; 571 char *name = symname(sym); 572 573 printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name); 574 } 575 576 void 577 endinit(void) 578 { 579 puts("}"); 580 } 581 582 void 583 getbblocks(void) 584 { 585 Inst *i; 586 587 if (!prog) 588 return; 589 590 prog->flags |= BBENTRY; 591 for (pc = prog; pc; pc = pc->next) { 592 switch (pc->op) { 593 case ASBRANCH: 594 i = pc->from2.u.sym->u.inst; 595 i->flags |= BBENTRY; 596 case ASJMP: 597 i = pc->from1.u.sym->u.inst; 598 i->flags |= BBENTRY; 599 case ASRET: 600 if (pc->next) 601 pc->next->flags |= BBENTRY; 602 break; 603 } 604 } 605 }