1 #include "l.h" 2 3 #define Dbufslop 100 4 5 long 6 entryvalue(void) 7 { 8 char *a; 9 Sym *s; 10 11 a = INITENTRY; 12 if(*a >= '0' && *a <= '9') 13 return atolwhex(a); 14 s = lookup(a, 0); 15 if(s->type == 0) 16 return INITTEXT; 17 switch(s->type) { 18 case STEXT: 19 break; 20 case SDATA: 21 if(dlm) 22 return s->value+INITDAT; 23 default: 24 diag("entry not text: %s", s->name); 25 } 26 return s->value; 27 } 28 29 void 30 wput(ushort w) 31 { 32 cput(w); 33 cput(w>>8); 34 } 35 36 void 37 wputb(ushort w) 38 { 39 cput(w>>8); 40 cput(w); 41 } 42 43 void 44 asmb(void) 45 { 46 Prog *p; 47 long v, magic; 48 int a; 49 uchar *op1; 50 51 if(debug['v']) 52 Bprint(&bso, "%5.2f asmb\n", cputime()); 53 Bflush(&bso); 54 55 seek(cout, HEADR, 0); 56 pc = INITTEXT; 57 curp = firstp; 58 for(p = firstp; p != P; p = p->link) { 59 if(p->as == ATEXT) 60 curtext = p; 61 if(p->pc != pc) { 62 if(!debug['a']) 63 print("%P\n", curp); 64 diag("phase error %lux sb %lux in %s", p->pc, pc, TNAME); 65 pc = p->pc; 66 } 67 curp = p; 68 asmins(p); 69 if(cbc < sizeof(and)) 70 cflush(); 71 a = (andptr - and); 72 if(debug['a']) { 73 Bprint(&bso, pcstr, pc); 74 for(op1 = and; op1 < andptr; op1++) 75 Bprint(&bso, "%.2ux", *op1 & 0xff); 76 Bprint(&bso, "\t%P\n", curp); 77 } 78 if(dlm) { 79 if(p->as == ATEXT) 80 reloca = nil; 81 else if(reloca != nil) 82 diag("reloc failure: %P", curp); 83 } 84 memmove(cbp, and, a); 85 cbp += a; 86 pc += a; 87 cbc -= a; 88 } 89 cflush(); 90 switch(HEADTYPE) { 91 default: 92 diag("unknown header type %d", HEADTYPE); 93 case 0: 94 seek(cout, rnd(HEADR+textsize, 8192), 0); 95 break; 96 case 1: 97 textsize = rnd(HEADR+textsize, 4096)-HEADR; 98 seek(cout, textsize+HEADR, 0); 99 break; 100 case 2: 101 seek(cout, HEADR+textsize, 0); 102 break; 103 case 3: 104 case 4: 105 seek(cout, HEADR+rnd(textsize, INITRND), 0); 106 break; 107 } 108 109 if(debug['v']) 110 Bprint(&bso, "%5.2f datblk\n", cputime()); 111 Bflush(&bso); 112 113 if(dlm){ 114 char buf[8]; 115 116 write(cout, buf, INITDAT-textsize); 117 textsize = INITDAT; 118 } 119 120 for(v = 0; v < datsize; v += sizeof(buf)-Dbufslop) { 121 if(datsize-v > sizeof(buf)-Dbufslop) 122 datblk(v, sizeof(buf)-Dbufslop); 123 else 124 datblk(v, datsize-v); 125 } 126 127 symsize = 0; 128 spsize = 0; 129 lcsize = 0; 130 if(!debug['s']) { 131 if(debug['v']) 132 Bprint(&bso, "%5.2f sym\n", cputime()); 133 Bflush(&bso); 134 switch(HEADTYPE) { 135 default: 136 case 0: 137 seek(cout, rnd(HEADR+textsize, 8192)+datsize, 0); 138 break; 139 case 1: 140 seek(cout, rnd(HEADR+textsize, INITRND)+datsize, 0); 141 break; 142 case 2: 143 seek(cout, HEADR+textsize+datsize, 0); 144 break; 145 case 3: 146 case 4: 147 debug['s'] = 1; 148 break; 149 } 150 if(!debug['s']) 151 asmsym(); 152 if(debug['v']) 153 Bprint(&bso, "%5.2f sp\n", cputime()); 154 Bflush(&bso); 155 if(debug['v']) 156 Bprint(&bso, "%5.2f pc\n", cputime()); 157 Bflush(&bso); 158 if(!debug['s']) 159 asmlc(); 160 if(dlm) 161 asmdyn(); 162 cflush(); 163 } 164 else if(dlm){ 165 seek(cout, HEADR+textsize+datsize, 0); 166 asmdyn(); 167 cflush(); 168 } 169 if(debug['v']) 170 Bprint(&bso, "%5.2f headr\n", cputime()); 171 Bflush(&bso); 172 seek(cout, 0L, 0); 173 switch(HEADTYPE) { 174 default: 175 case 0: /* garbage */ 176 lput(0x160L<<16); /* magic and sections */ 177 lput(0L); /* time and date */ 178 lput(rnd(HEADR+textsize, 4096)+datsize); 179 lput(symsize); /* nsyms */ 180 lput((0x38L<<16)|7L); /* size of optional hdr and flags */ 181 lput((0413<<16)|0437L); /* magic and version */ 182 lput(rnd(HEADR+textsize, 4096)); /* sizes */ 183 lput(datsize); 184 lput(bsssize); 185 lput(entryvalue()); /* va of entry */ 186 lput(INITTEXT-HEADR); /* va of base of text */ 187 lput(INITDAT); /* va of base of data */ 188 lput(INITDAT+datsize); /* va of base of bss */ 189 lput(~0L); /* gp reg mask */ 190 lput(0L); 191 lput(0L); 192 lput(0L); 193 lput(0L); 194 lput(~0L); /* gp value ?? */ 195 break; 196 lputl(0); /* x */ 197 case 1: /* unix coff */ 198 /* 199 * file header 200 */ 201 lputl(0x0004014c); /* 4 sections, magic */ 202 lputl(0); /* unix time stamp */ 203 lputl(0); /* symbol table */ 204 lputl(0); /* nsyms */ 205 lputl(0x0003001c); /* flags, sizeof a.out header */ 206 /* 207 * a.out header 208 */ 209 lputl(0x10b); /* magic, version stamp */ 210 lputl(rnd(textsize, INITRND)); /* text sizes */ 211 lputl(datsize); /* data sizes */ 212 lputl(bsssize); /* bss sizes */ 213 lput(entryvalue()); /* va of entry */ 214 lputl(INITTEXT); /* text start */ 215 lputl(INITDAT); /* data start */ 216 /* 217 * text section header 218 */ 219 s8put(".text"); 220 lputl(HEADR); /* pa */ 221 lputl(HEADR); /* va */ 222 lputl(textsize); /* text size */ 223 lputl(HEADR); /* file offset */ 224 lputl(0); /* relocation */ 225 lputl(0); /* line numbers */ 226 lputl(0); /* relocation, line numbers */ 227 lputl(0x20); /* flags text only */ 228 /* 229 * data section header 230 */ 231 s8put(".data"); 232 lputl(INITDAT); /* pa */ 233 lputl(INITDAT); /* va */ 234 lputl(datsize); /* data size */ 235 lputl(HEADR+textsize); /* file offset */ 236 lputl(0); /* relocation */ 237 lputl(0); /* line numbers */ 238 lputl(0); /* relocation, line numbers */ 239 lputl(0x40); /* flags data only */ 240 /* 241 * bss section header 242 */ 243 s8put(".bss"); 244 lputl(INITDAT+datsize); /* pa */ 245 lputl(INITDAT+datsize); /* va */ 246 lputl(bsssize); /* bss size */ 247 lputl(0); /* file offset */ 248 lputl(0); /* relocation */ 249 lputl(0); /* line numbers */ 250 lputl(0); /* relocation, line numbers */ 251 lputl(0x80); /* flags bss only */ 252 /* 253 * comment section header 254 */ 255 s8put(".comment"); 256 lputl(0); /* pa */ 257 lputl(0); /* va */ 258 lputl(symsize+lcsize); /* comment size */ 259 lputl(HEADR+textsize+datsize); /* file offset */ 260 lputl(HEADR+textsize+datsize); /* offset of syms */ 261 lputl(HEADR+textsize+datsize+symsize);/* offset of line numbers */ 262 lputl(0); /* relocation, line numbers */ 263 lputl(0x200); /* flags comment only */ 264 break; 265 case 2: /* plan9 */ 266 magic = 4*11*11+7; 267 if(dlm) 268 magic |= 0x80000000; 269 lput(magic); /* magic */ 270 lput(textsize); /* sizes */ 271 lput(datsize); 272 lput(bsssize); 273 lput(symsize); /* nsyms */ 274 lput(entryvalue()); /* va of entry */ 275 lput(spsize); /* sp offsets */ 276 lput(lcsize); /* line offsets */ 277 break; 278 case 3: 279 /* MS-DOS .COM */ 280 break; 281 case 4: 282 /* fake MS-DOS .EXE */ 283 v = rnd(HEADR+textsize, INITRND)+datsize; 284 wput(0x5A4D); /* 'MZ' */ 285 wput(v % 512); /* bytes in last page */ 286 wput(rnd(v, 512)/512); /* total number of pages */ 287 wput(0x0000); /* number of reloc items */ 288 v = rnd(HEADR-(INITTEXT & 0xFFFF), 16); 289 wput(v/16); /* size of header */ 290 wput(0x0000); /* minimum allocation */ 291 wput(0xFFFF); /* maximum allocation */ 292 wput(0x0000); /* initial ss value */ 293 wput(0x0100); /* initial sp value */ 294 wput(0x0000); /* complemented checksum */ 295 v = entryvalue(); 296 wput(v); /* initial ip value (!) */ 297 wput(0x0000); /* initial cs value */ 298 wput(0x0000); 299 wput(0x0000); 300 wput(0x003E); /* reloc table offset */ 301 wput(0x0000); /* overlay number */ 302 break; 303 } 304 cflush(); 305 } 306 307 void 308 lput(long l) 309 { 310 cput(l>>24); 311 cput(l>>16); 312 cput(l>>8); 313 cput(l); 314 } 315 316 void 317 lputl(long l) 318 { 319 cput(l); 320 cput(l>>8); 321 cput(l>>16); 322 cput(l>>24); 323 } 324 325 void 326 s8put(char *n) 327 { 328 char name[8]; 329 int i; 330 331 strncpy(name, n, sizeof(name)); 332 for(i=0; i<sizeof(name); i++) 333 cput(name[i]); 334 } 335 336 void 337 cflush(void) 338 { 339 int n; 340 341 n = sizeof(buf.cbuf) - cbc; 342 if(n) 343 write(cout, buf.cbuf, n); 344 cbp = buf.cbuf; 345 cbc = sizeof(buf.cbuf); 346 } 347 348 void 349 datblk(long s, long n) 350 { 351 Prog *p; 352 char *cast; 353 long l, fl, j; 354 int i, c; 355 356 memset(buf.dbuf, 0, n+Dbufslop); 357 for(p = datap; p != P; p = p->link) { 358 curp = p; 359 l = p->from.sym->value + p->from.offset - s; 360 c = p->from.scale; 361 i = 0; 362 if(l < 0) { 363 if(l+c <= 0) 364 continue; 365 while(l < 0) { 366 l++; 367 i++; 368 } 369 } 370 if(l >= n) 371 continue; 372 if(p->as != AINIT && p->as != ADYNT) { 373 for(j=l+(c-i)-1; j>=l; j--) 374 if(buf.dbuf[j]) { 375 print("%P\n", p); 376 diag("multiple initialization"); 377 break; 378 } 379 } 380 switch(p->to.type) { 381 case D_FCONST: 382 switch(c) { 383 default: 384 case 4: 385 fl = ieeedtof(&p->to.ieee); 386 cast = (char*)&fl; 387 if(debug['a'] && i == 0) { 388 Bprint(&bso, pcstr, l+s+INITDAT); 389 for(j=0; j<c; j++) 390 Bprint(&bso, "%.2ux", cast[fnuxi4[j]] & 0xff); 391 Bprint(&bso, "\t%P\n", curp); 392 } 393 for(; i<c; i++) { 394 buf.dbuf[l] = cast[fnuxi4[i]]; 395 l++; 396 } 397 break; 398 case 8: 399 cast = (char*)&p->to.ieee; 400 if(debug['a'] && i == 0) { 401 Bprint(&bso, pcstr, l+s+INITDAT); 402 for(j=0; j<c; j++) 403 Bprint(&bso, "%.2ux", cast[fnuxi8[j]] & 0xff); 404 Bprint(&bso, "\t%P\n", curp); 405 } 406 for(; i<c; i++) { 407 buf.dbuf[l] = cast[fnuxi8[i]]; 408 l++; 409 } 410 break; 411 } 412 break; 413 414 case D_SCONST: 415 if(debug['a'] && i == 0) { 416 Bprint(&bso, pcstr, l+s+INITDAT); 417 for(j=0; j<c; j++) 418 Bprint(&bso, "%.2ux", p->to.scon[j] & 0xff); 419 Bprint(&bso, "\t%P\n", curp); 420 } 421 for(; i<c; i++) { 422 buf.dbuf[l] = p->to.scon[i]; 423 l++; 424 } 425 break; 426 default: 427 fl = p->to.offset; 428 if(p->to.type == D_ADDR) { 429 if(p->to.index != D_STATIC && p->to.index != D_EXTERN) 430 diag("DADDR type%P", p); 431 if(p->to.sym) { 432 if(p->to.sym->type == SUNDEF) 433 ckoff(p->to.sym, fl); 434 fl += p->to.sym->value; 435 if(p->to.sym->type != STEXT && p->to.sym->type != SUNDEF) 436 fl += INITDAT; 437 if(dlm) 438 dynreloc(p->to.sym, l+s+INITDAT, 1); 439 } 440 } 441 cast = (char*)&fl; 442 switch(c) { 443 default: 444 diag("bad nuxi %d %d\n%P", c, i, curp); 445 break; 446 case 1: 447 if(debug['a'] && i == 0) { 448 Bprint(&bso, pcstr, l+s+INITDAT); 449 for(j=0; j<c; j++) 450 Bprint(&bso, "%.2ux", cast[inuxi1[j]] & 0xff); 451 Bprint(&bso, "\t%P\n", curp); 452 } 453 for(; i<c; i++) { 454 buf.dbuf[l] = cast[inuxi1[i]]; 455 l++; 456 } 457 break; 458 case 2: 459 if(debug['a'] && i == 0) { 460 Bprint(&bso, pcstr, l+s+INITDAT); 461 for(j=0; j<c; j++) 462 Bprint(&bso, "%.2ux", cast[inuxi2[j]] & 0xff); 463 Bprint(&bso, "\t%P\n", curp); 464 } 465 for(; i<c; i++) { 466 buf.dbuf[l] = cast[inuxi2[i]]; 467 l++; 468 } 469 break; 470 case 4: 471 if(debug['a'] && i == 0) { 472 Bprint(&bso, pcstr, l+s+INITDAT); 473 for(j=0; j<c; j++) 474 Bprint(&bso, "%.2ux", cast[inuxi4[j]] & 0xff); 475 Bprint(&bso, "\t%P\n", curp); 476 } 477 for(; i<c; i++) { 478 buf.dbuf[l] = cast[inuxi4[i]]; 479 l++; 480 } 481 break; 482 } 483 break; 484 } 485 } 486 write(cout, buf.dbuf, n); 487 } 488 489 long 490 rnd(long v, long r) 491 { 492 long c; 493 494 if(r <= 0) 495 return v; 496 v += r - 1; 497 c = v % r; 498 if(c < 0) 499 c += r; 500 v -= c; 501 return v; 502 } 503