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