github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/cmd/5l/obj.c (about) 1 // Inferno utils/5l/obj.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5l/obj.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 // Reading object files. 32 33 #define EXTERN 34 #include "l.h" 35 #include "../ld/lib.h" 36 #include "../ld/elf.h" 37 #include "../ld/dwarf.h" 38 #include <ar.h> 39 40 #ifndef DEFAULT 41 #define DEFAULT '9' 42 #endif 43 44 char *noname = "<none>"; 45 char *thestring = "arm"; 46 47 Header headers[] = { 48 "noheader", Hnoheader, 49 "risc", Hrisc, 50 "plan9", Hplan9x32, 51 "ixp1200", Hixp1200, 52 "ipaq", Hipaq, 53 "linux", Hlinux, 54 "freebsd", Hfreebsd, 55 "netbsd", Hnetbsd, 56 0, 0 57 }; 58 59 /* 60 * -Hrisc -T0x10005000 -R4 is aif for risc os 61 * -Hplan9 -T4128 -R4096 is plan9 format 62 * -Hixp1200 is IXP1200 (raw) 63 * -Hipaq -T0xC0008010 -R1024 is ipaq 64 * -Hlinux -Tx -Rx is linux elf 65 * -Hfreebsd is freebsd elf 66 * -Hnetbsd is netbsd elf 67 */ 68 69 void 70 main(int argc, char *argv[]) 71 { 72 char *p; 73 Sym *s; 74 75 Binit(&bso, 1, OWRITE); 76 listinit(); 77 nerrors = 0; 78 outfile = "5.out"; 79 HEADTYPE = -1; 80 INITTEXT = -1; 81 INITDAT = -1; 82 INITRND = -1; 83 INITENTRY = 0; 84 linkmode = LinkAuto; 85 nuxiinit(); 86 87 p = getgoarm(); 88 if(p != nil) 89 goarm = atoi(p); 90 else 91 goarm = 6; 92 if(goarm == 5) 93 debug['F'] = 1; 94 95 flagcount("1", "use alternate profiling code", &debug['1']); 96 flagfn1("B", "info: define ELF NT_GNU_BUILD_ID note", addbuildinfo); 97 flagstr("E", "sym: entry symbol", &INITENTRY); 98 flagint32("D", "addr: data address", &INITDAT); 99 flagcount("G", "debug pseudo-ops", &debug['G']); 100 flagfn1("I", "interp: set ELF interp", setinterp); 101 flagfn1("L", "dir: add dir to library path", Lflag); 102 flagfn1("H", "head: header type", setheadtype); 103 flagcount("K", "add stack underflow checks", &debug['K']); 104 flagcount("M", "disable software div/mod", &debug['M']); 105 flagcount("O", "print pc-line tables", &debug['O']); 106 flagcount("P", "debug code generation", &debug['P']); 107 flagint32("R", "rnd: address rounding", &INITRND); 108 flagint32("T", "addr: text address", &INITTEXT); 109 flagfn0("V", "print version and exit", doversion); 110 flagcount("W", "disassemble input", &debug['W']); 111 flagfn2("X", "name value: define string data", addstrdata); 112 flagcount("Z", "clear stack frame on entry", &debug['Z']); 113 flagcount("a", "disassemble output", &debug['a']); 114 flagcount("c", "dump call graph", &debug['c']); 115 flagcount("d", "disable dynamic executable", &debug['d']); 116 flagstr("extld", "linker to run in external mode", &extld); 117 flagstr("extldflags", "flags for external linker", &extldflags); 118 flagcount("f", "ignore version mismatch", &debug['f']); 119 flagcount("g", "disable go package data checks", &debug['g']); 120 flagstr("k", "sym: set field tracking symbol", &tracksym); 121 flagfn1("linkmode", "mode: set link mode (internal, external, auto)", setlinkmode); 122 flagcount("n", "dump symbol table", &debug['n']); 123 flagstr("o", "outfile: set output file", &outfile); 124 flagcount("p", "insert profiling code", &debug['p']); 125 flagstr("r", "dir1:dir2:...: set ELF dynamic linker search path", &rpath); 126 flagcount("race", "enable race detector", &flag_race); 127 flagcount("s", "disable symbol table", &debug['s']); 128 flagcount("shared", "generate shared object (implies -linkmode external)", &flag_shared); 129 flagstr("tmpdir", "leave temporary files in this directory", &tmpdir); 130 flagcount("u", "reject unsafe packages", &debug['u']); 131 flagcount("v", "print link trace", &debug['v']); 132 flagcount("w", "disable DWARF generation", &debug['w']); 133 134 flagparse(&argc, &argv, usage); 135 136 if(argc != 1) 137 usage(); 138 139 if(flag_shared) 140 linkmode = LinkExternal; 141 142 mywhatsys(); 143 144 if(HEADTYPE == -1) 145 HEADTYPE = headtype(goos); 146 147 // getgoextlinkenabled is based on GO_EXTLINK_ENABLED when 148 // Go was built; see ../../make.bash. 149 if(linkmode == LinkAuto && strcmp(getgoextlinkenabled(), "0") == 0) 150 linkmode = LinkInternal; 151 152 switch(HEADTYPE) { 153 default: 154 if(linkmode == LinkAuto) 155 linkmode = LinkInternal; 156 if(linkmode == LinkExternal && strcmp(getgoextlinkenabled(), "1") != 0) 157 sysfatal("cannot use -linkmode=external with -H %s", headstr(HEADTYPE)); 158 break; 159 case Hlinux: 160 break; 161 } 162 163 libinit(); 164 165 switch(HEADTYPE) { 166 default: 167 diag("unknown -H option"); 168 errorexit(); 169 case Hnoheader: /* no header */ 170 HEADR = 0L; 171 if(INITTEXT == -1) 172 INITTEXT = 0; 173 if(INITDAT == -1) 174 INITDAT = 0; 175 if(INITRND == -1) 176 INITRND = 4; 177 break; 178 case Hrisc: /* aif for risc os */ 179 HEADR = 128L; 180 if(INITTEXT == -1) 181 INITTEXT = 0x10005000 + HEADR; 182 if(INITDAT == -1) 183 INITDAT = 0; 184 if(INITRND == -1) 185 INITRND = 4; 186 break; 187 case Hplan9x32: /* plan 9 */ 188 HEADR = 32L; 189 if(INITTEXT == -1) 190 INITTEXT = 4128; 191 if(INITDAT == -1) 192 INITDAT = 0; 193 if(INITRND == -1) 194 INITRND = 4096; 195 break; 196 case Hixp1200: /* boot for IXP1200 */ 197 HEADR = 0L; 198 if(INITTEXT == -1) 199 INITTEXT = 0x0; 200 if(INITDAT == -1) 201 INITDAT = 0; 202 if(INITRND == -1) 203 INITRND = 4; 204 break; 205 case Hipaq: /* boot for ipaq */ 206 HEADR = 16L; 207 if(INITTEXT == -1) 208 INITTEXT = 0xC0008010; 209 if(INITDAT == -1) 210 INITDAT = 0; 211 if(INITRND == -1) 212 INITRND = 1024; 213 break; 214 case Hlinux: /* arm elf */ 215 case Hfreebsd: 216 case Hnetbsd: 217 debug['d'] = 0; // with dynamic linking 218 tlsoffset = -8; // hardcoded number, first 4-byte word for g, and then 4-byte word for m 219 // this number is known to ../../pkg/runtime/rt0_*_arm.s 220 elfinit(); 221 HEADR = ELFRESERVE; 222 if(INITTEXT == -1) 223 INITTEXT = 0x10000 + HEADR; 224 if(INITDAT == -1) 225 INITDAT = 0; 226 if(INITRND == -1) 227 INITRND = 4096; 228 break; 229 } 230 if(INITDAT != 0 && INITRND != 0) 231 print("warning: -D0x%ux is ignored because of -R0x%ux\n", 232 INITDAT, INITRND); 233 if(debug['v']) 234 Bprint(&bso, "HEADER = -H0x%d -T0x%ux -D0x%ux -R0x%ux\n", 235 HEADTYPE, INITTEXT, INITDAT, INITRND); 236 Bflush(&bso); 237 zprg.as = AGOK; 238 zprg.scond = 14; 239 zprg.reg = NREG; 240 zprg.from.name = D_NONE; 241 zprg.from.type = D_NONE; 242 zprg.from.reg = NREG; 243 zprg.to = zprg.from; 244 buildop(); 245 histgen = 0; 246 pc = 0; 247 dtype = 4; 248 249 version = 0; 250 cbp = buf.cbuf; 251 cbc = sizeof(buf.cbuf); 252 253 // embed goarm to runtime.goarm 254 s = lookup("runtime.goarm", 0); 255 s->dupok = 1; 256 adduint8(s, goarm); 257 258 addlibpath("command line", "command line", argv[0], "main"); 259 loadlib(); 260 261 // mark some functions that are only referenced after linker code editing 262 if(debug['F']) 263 mark(rlookup("_sfloat", 0)); 264 mark(lookup("runtime.read_tls_fallback", 0)); 265 deadcode(); 266 if(textp == nil) { 267 diag("no code"); 268 errorexit(); 269 } 270 271 patch(); 272 if(debug['p']) 273 if(debug['1']) 274 doprof1(); 275 else 276 doprof2(); 277 doelf(); 278 follow(); 279 softfloat(); 280 // 5l -Z means zero the stack frame on entry. 281 // This slows down function calls but can help avoid 282 // false positives in garbage collection. 283 if(debug['Z']) 284 dozerostk(); 285 noops(); // generate stack split prolog, handle div/mod, etc. 286 dostkcheck(); 287 span(); 288 addexport(); 289 // textaddress() functionality is handled in span() 290 pclntab(); 291 symtab(); 292 dodata(); 293 address(); 294 doweak(); 295 reloc(); 296 asmb(); 297 undef(); 298 hostlink(); 299 300 if(debug['c']) 301 print("ARM size = %d\n", armsize); 302 if(debug['v']) { 303 Bprint(&bso, "%5.2f cpu time\n", cputime()); 304 Bprint(&bso, "%d sizeof adr\n", sizeof(Adr)); 305 Bprint(&bso, "%d sizeof prog\n", sizeof(Prog)); 306 } 307 Bflush(&bso); 308 errorexit(); 309 } 310 311 static Sym* 312 zsym(char *pn, Biobuf *f, Sym *h[]) 313 { 314 int o; 315 316 o = BGETC(f); 317 if(o == 0) 318 return S; 319 if(o < 0 || o >= NSYM || h[o] == nil) 320 mangle(pn); 321 return h[o]; 322 } 323 324 static void 325 zaddr(char *pn, Biobuf *f, Adr *a, Sym *h[]) 326 { 327 int i, c; 328 int32 l; 329 Sym *s; 330 Auto *u; 331 332 a->type = BGETC(f); 333 a->reg = BGETC(f); 334 c = BGETC(f); 335 if(c < 0 || c > NSYM){ 336 print("sym out of range: %d\n", c); 337 BPUTC(f, ALAST+1); 338 return; 339 } 340 a->sym = h[c]; 341 a->name = BGETC(f); 342 adrgotype = zsym(pn, f, h); 343 344 if((schar)a->reg < 0 || a->reg > NREG) { 345 print("register out of range %d\n", a->reg); 346 BPUTC(f, ALAST+1); 347 return; /* force real diagnostic */ 348 } 349 350 if(a->type == D_CONST || a->type == D_OCONST) { 351 if(a->name == D_EXTERN || a->name == D_STATIC) { 352 s = a->sym; 353 if(s != S && (s->type == STEXT || s->type == SCONST || s->type == SXREF)) { 354 if(0 && !s->fnptr && s->name[0] != '.') 355 print("%s used as function pointer\n", s->name); 356 s->fnptr = 1; // over the top cos of SXREF 357 } 358 } 359 } 360 361 switch(a->type) { 362 default: 363 print("unknown type %d\n", a->type); 364 BPUTC(f, ALAST+1); 365 return; /* force real diagnostic */ 366 367 case D_NONE: 368 case D_REG: 369 case D_FREG: 370 case D_PSR: 371 case D_FPCR: 372 break; 373 374 case D_REGREG: 375 case D_REGREG2: 376 a->offset = BGETC(f); 377 break; 378 379 case D_CONST2: 380 a->offset2 = BGETLE4(f); // fall through 381 case D_BRANCH: 382 case D_OREG: 383 case D_CONST: 384 case D_OCONST: 385 case D_SHIFT: 386 a->offset = BGETLE4(f); 387 break; 388 389 case D_SCONST: 390 a->sval = mal(NSNAME); 391 Bread(f, a->sval, NSNAME); 392 break; 393 394 case D_FCONST: 395 a->ieee.l = BGETLE4(f); 396 a->ieee.h = BGETLE4(f); 397 break; 398 } 399 s = a->sym; 400 if(s == S) 401 return; 402 i = a->name; 403 if(i != D_AUTO && i != D_PARAM) { 404 if(s && adrgotype) 405 s->gotype = adrgotype; 406 return; 407 } 408 409 l = a->offset; 410 for(u=curauto; u; u=u->link) 411 if(u->asym == s) 412 if(u->type == i) { 413 if(u->aoffset > l) 414 u->aoffset = l; 415 if(adrgotype) 416 u->gotype = adrgotype; 417 return; 418 } 419 420 u = mal(sizeof(Auto)); 421 u->link = curauto; 422 curauto = u; 423 u->asym = s; 424 u->aoffset = l; 425 u->type = i; 426 u->gotype = adrgotype; 427 } 428 429 void 430 nopout(Prog *p) 431 { 432 p->as = ANOP; 433 p->from.type = D_NONE; 434 p->to.type = D_NONE; 435 } 436 437 void 438 ldobj1(Biobuf *f, char *pkg, int64 len, char *pn) 439 { 440 int32 ipc; 441 Prog *p; 442 Sym *h[NSYM], *s; 443 int v, o, r, skip; 444 uint32 sig; 445 char *name; 446 int ntext; 447 int32 eof; 448 char src[1024], *x; 449 Prog *lastp; 450 451 lastp = nil; 452 ntext = 0; 453 eof = Boffset(f) + len; 454 src[0] = 0; 455 pn = estrdup(pn); // we keep it in Sym* references 456 457 newloop: 458 memset(h, 0, sizeof(h)); 459 version++; 460 histfrogp = 0; 461 ipc = pc; 462 skip = 0; 463 464 loop: 465 if(f->state == Bracteof || Boffset(f) >= eof) 466 goto eof; 467 o = BGETC(f); 468 if(o == Beof) 469 goto eof; 470 471 if(o <= AXXX || o >= ALAST) { 472 diag("%s:#%lld: opcode out of range: %#ux", pn, Boffset(f), o); 473 print(" probably not a .5 file\n"); 474 errorexit(); 475 } 476 if(o == ANAME || o == ASIGNAME) { 477 sig = 0; 478 if(o == ASIGNAME) 479 sig = BGETLE4(f); 480 v = BGETC(f); /* type */ 481 o = BGETC(f); /* sym */ 482 r = 0; 483 if(v == D_STATIC) 484 r = version; 485 name = Brdline(f, '\0'); 486 if(name == nil) { 487 if(Blinelen(f) > 0) { 488 fprint(2, "%s: name too long\n", pn); 489 errorexit(); 490 } 491 goto eof; 492 } 493 x = expandpkg(name, pkg); 494 s = lookup(x, r); 495 if(x != name) 496 free(x); 497 498 if(sig != 0){ 499 if(s->sig != 0 && s->sig != sig) 500 diag("incompatible type signatures %ux(%s) and %ux(%s) for %s", s->sig, s->file, sig, pn, s->name); 501 s->sig = sig; 502 s->file = pn; 503 } 504 505 if(debug['W']) 506 print(" ANAME %s\n", s->name); 507 if(o < 0 || o >= nelem(h)) { 508 fprint(2, "%s: mangled input file\n", pn); 509 errorexit(); 510 } 511 h[o] = s; 512 if((v == D_EXTERN || v == D_STATIC) && s->type == 0) 513 s->type = SXREF; 514 if(v == D_FILE) { 515 if(s->type != SFILE) { 516 histgen++; 517 s->type = SFILE; 518 s->value = histgen; 519 } 520 if(histfrogp < MAXHIST) { 521 histfrog[histfrogp] = s; 522 histfrogp++; 523 } else 524 collapsefrog(s); 525 dwarfaddfrag(s->value, s->name); 526 } 527 goto loop; 528 } 529 530 p = mal(sizeof(Prog)); 531 p->as = o; 532 p->scond = BGETC(f); 533 p->reg = BGETC(f); 534 p->line = BGETLE4(f); 535 536 zaddr(pn, f, &p->from, h); 537 fromgotype = adrgotype; 538 zaddr(pn, f, &p->to, h); 539 540 if(p->as != ATEXT && p->as != AGLOBL && p->reg > NREG) 541 diag("register out of range %A %d", p->as, p->reg); 542 543 p->link = P; 544 p->cond = P; 545 546 if(debug['W']) 547 print("%P\n", p); 548 549 switch(o) { 550 case AHISTORY: 551 if(p->to.offset == -1) { 552 addlib(src, pn); 553 histfrogp = 0; 554 goto loop; 555 } 556 if(src[0] == '\0') 557 copyhistfrog(src, sizeof src); 558 addhist(p->line, D_FILE); /* 'z' */ 559 if(p->to.offset) 560 addhist(p->to.offset, D_FILE1); /* 'Z' */ 561 savehist(p->line, p->to.offset); 562 histfrogp = 0; 563 goto loop; 564 565 case AEND: 566 histtoauto(); 567 if(cursym != nil && cursym->text) 568 cursym->autom = curauto; 569 curauto = 0; 570 cursym = nil; 571 if(Boffset(f) == eof) 572 return; 573 goto newloop; 574 575 case AGLOBL: 576 s = p->from.sym; 577 if(s == S) { 578 diag("GLOBL must have a name\n%P", p); 579 errorexit(); 580 } 581 if(s->type == 0 || s->type == SXREF) { 582 s->type = SBSS; 583 s->value = 0; 584 } 585 if(s->type != SBSS && s->type != SNOPTRBSS && !s->dupok) { 586 diag("redefinition: %s\n%P", s->name, p); 587 s->type = SBSS; 588 s->value = 0; 589 } 590 if(p->to.offset > s->size) 591 s->size = p->to.offset; 592 if(p->reg & DUPOK) 593 s->dupok = 1; 594 if(p->reg & RODATA) 595 s->type = SRODATA; 596 else if(p->reg & NOPTR) 597 s->type = SNOPTRBSS; 598 break; 599 600 case ADATA: 601 // Assume that AGLOBL comes after ADATA. 602 // If we've seen an AGLOBL that said this sym was DUPOK, 603 // ignore any more ADATA we see, which must be 604 // redefinitions. 605 s = p->from.sym; 606 if(s->dupok) { 607 // if(debug['v']) 608 // Bprint(&bso, "skipping %s in %s: dupok\n", s->name, pn); 609 goto loop; 610 } 611 if(s->file == nil) 612 s->file = pn; 613 else if(s->file != pn) { 614 diag("multiple initialization for %s: in both %s and %s", s->name, s->file, pn); 615 errorexit(); 616 } 617 savedata(s, p, pn); 618 unmal(p, sizeof *p); 619 break; 620 621 case AGOK: 622 diag("unknown opcode\n%P", p); 623 p->pc = pc; 624 pc++; 625 break; 626 627 case ATYPE: 628 if(skip) 629 goto casedef; 630 pc++; 631 goto loop; 632 633 case ATEXT: 634 if(cursym != nil && cursym->text) { 635 histtoauto(); 636 cursym->autom = curauto; 637 curauto = 0; 638 } 639 s = p->from.sym; 640 if(s == S) { 641 diag("TEXT must have a name\n%P", p); 642 errorexit(); 643 } 644 cursym = s; 645 if(s->type != 0 && s->type != SXREF && (p->reg & DUPOK)) { 646 skip = 1; 647 goto casedef; 648 } 649 if(ntext++ == 0 && s->type != 0 && s->type != SXREF) { 650 /* redefinition, so file has probably been seen before */ 651 if(debug['v']) 652 Bprint(&bso, "skipping: %s: redefinition: %s", pn, s->name); 653 return; 654 } 655 skip = 0; 656 if(s->type != 0 && s->type != SXREF) 657 diag("redefinition: %s\n%P", s->name, p); 658 if(etextp) 659 etextp->next = s; 660 else 661 textp = s; 662 if(fromgotype) { 663 if(s->gotype && s->gotype != fromgotype) 664 diag("%s: type mismatch for %s", pn, s->name); 665 s->gotype = fromgotype; 666 } 667 etextp = s; 668 p->align = 4; 669 autosize = (p->to.offset+3L) & ~3L; 670 p->to.offset = autosize; 671 autosize += 4; 672 s->type = STEXT; 673 s->hist = gethist(); 674 s->text = p; 675 s->value = pc; 676 s->args = p->to.offset2; 677 lastp = p; 678 p->pc = pc; 679 pc++; 680 break; 681 682 case ASUB: 683 if(p->from.type == D_CONST) 684 if(p->from.name == D_NONE) 685 if(p->from.offset < 0) { 686 p->from.offset = -p->from.offset; 687 p->as = AADD; 688 } 689 goto casedef; 690 691 case AADD: 692 if(p->from.type == D_CONST) 693 if(p->from.name == D_NONE) 694 if(p->from.offset < 0) { 695 p->from.offset = -p->from.offset; 696 p->as = ASUB; 697 } 698 goto casedef; 699 700 case AMOVWD: 701 case AMOVWF: 702 case AMOVDW: 703 case AMOVFW: 704 case AMOVFD: 705 case AMOVDF: 706 // case AMOVF: 707 // case AMOVD: 708 case ACMPF: 709 case ACMPD: 710 case AADDF: 711 case AADDD: 712 case ASUBF: 713 case ASUBD: 714 case AMULF: 715 case AMULD: 716 case ADIVF: 717 case ADIVD: 718 goto casedef; 719 720 case AMOVF: 721 if(skip) 722 goto casedef; 723 724 if(p->from.type == D_FCONST && chipfloat(&p->from.ieee) < 0 && 725 (chipzero(&p->from.ieee) < 0 || (p->scond & C_SCOND) != C_SCOND_NONE)) { 726 /* size sb 9 max */ 727 sprint(literal, "$%ux", ieeedtof(&p->from.ieee)); 728 s = lookup(literal, 0); 729 if(s->type == 0) { 730 s->type = SRODATA; 731 adduint32(s, ieeedtof(&p->from.ieee)); 732 s->reachable = 0; 733 } 734 p->from.type = D_OREG; 735 p->from.sym = s; 736 p->from.name = D_EXTERN; 737 p->from.offset = 0; 738 } 739 goto casedef; 740 741 case AMOVD: 742 if(skip) 743 goto casedef; 744 745 if(p->from.type == D_FCONST && chipfloat(&p->from.ieee) < 0 && 746 (chipzero(&p->from.ieee) < 0 || (p->scond & C_SCOND) != C_SCOND_NONE)) { 747 /* size sb 18 max */ 748 sprint(literal, "$%ux.%ux", 749 p->from.ieee.l, p->from.ieee.h); 750 s = lookup(literal, 0); 751 if(s->type == 0) { 752 s->type = SRODATA; 753 adduint32(s, p->from.ieee.l); 754 adduint32(s, p->from.ieee.h); 755 s->reachable = 0; 756 } 757 p->from.type = D_OREG; 758 p->from.sym = s; 759 p->from.name = D_EXTERN; 760 p->from.offset = 0; 761 } 762 goto casedef; 763 764 default: 765 casedef: 766 if(skip) 767 nopout(p); 768 p->pc = pc; 769 pc++; 770 if(p->to.type == D_BRANCH) 771 p->to.offset += ipc; 772 if(lastp == nil) { 773 if(p->as != ANOP) 774 diag("unexpected instruction: %P", p); 775 break; 776 } 777 lastp->link = p; 778 lastp = p; 779 break; 780 } 781 goto loop; 782 783 eof: 784 diag("truncated object file: %s", pn); 785 } 786 787 Prog* 788 prg(void) 789 { 790 Prog *p; 791 792 p = mal(sizeof(Prog)); 793 *p = zprg; 794 return p; 795 } 796 797 Prog* 798 appendp(Prog *q) 799 { 800 Prog *p; 801 802 p = prg(); 803 p->link = q->link; 804 q->link = p; 805 p->line = q->line; 806 return p; 807 }