github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/5l/list.c (about) 1 // Inferno utils/5l/list.h 2 // http://code.google.com/p/inferno-os/source/browse/utils/5l/list.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 // Printing. 32 33 #include "l.h" 34 #include "../ld/lib.h" 35 36 void 37 listinit(void) 38 { 39 40 fmtinstall('A', Aconv); 41 fmtinstall('C', Cconv); 42 fmtinstall('D', Dconv); 43 fmtinstall('P', Pconv); 44 fmtinstall('S', Sconv); 45 fmtinstall('N', Nconv); 46 fmtinstall('O', Oconv); // C_type constants 47 fmtinstall('I', Iconv); 48 } 49 50 void 51 prasm(Prog *p) 52 { 53 print("%P\n", p); 54 } 55 56 int 57 Pconv(Fmt *fp) 58 { 59 Prog *p; 60 int a; 61 62 p = va_arg(fp->args, Prog*); 63 curp = p; 64 a = p->as; 65 switch(a) { 66 default: 67 fmtprint(fp, "(%d)", p->line); 68 if(p->reg == NREG && p->as != AGLOBL) 69 fmtprint(fp, " %A%C %D,%D", 70 a, p->scond, &p->from, &p->to); 71 else 72 if(p->from.type != D_FREG) 73 fmtprint(fp, " %A%C %D,R%d,%D", 74 a, p->scond, &p->from, p->reg, &p->to); 75 else 76 fmtprint(fp, " %A%C %D,F%d,%D", 77 a, p->scond, &p->from, p->reg, &p->to); 78 break; 79 80 case ASWPW: 81 case ASWPBU: 82 fmtprint(fp, "(%d) %A%C R%d,%D,%D", 83 p->line, a, p->scond, p->reg, &p->from, &p->to); 84 break; 85 86 case ADATA: 87 case AINIT_: 88 case ADYNT_: 89 fmtprint(fp, "(%d) %A%C %D/%d,%D", 90 p->line, a, p->scond, &p->from, p->reg, &p->to); 91 break; 92 93 case AWORD: 94 fmtprint(fp, "(%d) WORD %D", p->line, &p->to); 95 break; 96 97 case ADWORD: 98 fmtprint(fp, "(%d) DWORD %D %D", p->line, &p->from, &p->to); 99 break; 100 } 101 102 if(p->spadj) 103 fmtprint(fp, " (spadj%+d)", p->spadj); 104 105 return 0; 106 } 107 108 int 109 Aconv(Fmt *fp) 110 { 111 char *s; 112 int a; 113 114 a = va_arg(fp->args, int); 115 s = "???"; 116 if(a >= AXXX && a < ALAST) 117 s = anames[a]; 118 return fmtstrcpy(fp, s); 119 } 120 121 char* strcond[16] = 122 { 123 ".EQ", 124 ".NE", 125 ".HS", 126 ".LO", 127 ".MI", 128 ".PL", 129 ".VS", 130 ".VC", 131 ".HI", 132 ".LS", 133 ".GE", 134 ".LT", 135 ".GT", 136 ".LE", 137 "", 138 ".NV" 139 }; 140 141 int 142 Cconv(Fmt *fp) 143 { 144 char s[20]; 145 int c; 146 147 c = va_arg(fp->args, int); 148 strcpy(s, strcond[c & C_SCOND]); 149 if(c & C_SBIT) 150 strcat(s, ".S"); 151 if(c & C_PBIT) 152 strcat(s, ".P"); 153 if(c & C_WBIT) 154 strcat(s, ".W"); 155 if(c & C_UBIT) /* ambiguous with FBIT */ 156 strcat(s, ".U"); 157 return fmtstrcpy(fp, s); 158 } 159 160 int 161 Dconv(Fmt *fp) 162 { 163 char str[STRINGSZ]; 164 const char *op; 165 Adr *a; 166 int32 v; 167 168 a = va_arg(fp->args, Adr*); 169 switch(a->type) { 170 171 default: 172 snprint(str, sizeof str, "GOK-type(%d)", a->type); 173 break; 174 175 case D_NONE: 176 str[0] = 0; 177 if(a->name != D_NONE || a->reg != NREG || a->sym != S) 178 snprint(str, sizeof str, "%N(R%d)(NONE)", a, a->reg); 179 break; 180 181 case D_CONST: 182 if(a->reg == NREG) 183 snprint(str, sizeof str, "$%N", a); 184 else 185 snprint(str, sizeof str, "$%N(R%d)", a, a->reg); 186 break; 187 188 case D_CONST2: 189 snprint(str, sizeof str, "$%d-%d", a->offset, a->offset2); 190 break; 191 192 case D_SHIFT: 193 v = a->offset; 194 op = &"<<>>->@>"[(((v>>5) & 3) << 1)]; 195 if(v & (1<<4)) 196 snprint(str, sizeof str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15); 197 else 198 snprint(str, sizeof str, "R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31); 199 if(a->reg != NREG) 200 seprint(str+strlen(str), str+sizeof str, "(R%d)", a->reg); 201 break; 202 203 case D_OCONST: 204 snprint(str, sizeof str, "$*$%N", a); 205 if(a->reg != NREG) 206 snprint(str, sizeof str, "%N(R%d)(CONST)", a, a->reg); 207 break; 208 209 case D_OREG: 210 if(a->reg != NREG) 211 snprint(str, sizeof str, "%N(R%d)", a, a->reg); 212 else 213 snprint(str, sizeof str, "%N", a); 214 break; 215 216 case D_REG: 217 snprint(str, sizeof str, "R%d", a->reg); 218 if(a->name != D_NONE || a->sym != S) 219 snprint(str, sizeof str, "%N(R%d)(REG)", a, a->reg); 220 break; 221 222 case D_REGREG: 223 snprint(str, sizeof str, "(R%d,R%d)", a->reg, (int)a->offset); 224 if(a->name != D_NONE || a->sym != S) 225 snprint(str, sizeof str, "%N(R%d)(REG)", a, a->reg); 226 break; 227 228 case D_REGREG2: 229 snprint(str, sizeof str, "R%d,R%d", a->reg, (int)a->offset); 230 if(a->name != D_NONE || a->sym != S) 231 snprint(str, sizeof str, "%N(R%d)(REG)", a, a->reg); 232 break; 233 234 case D_FREG: 235 snprint(str, sizeof str, "F%d", a->reg); 236 if(a->name != D_NONE || a->sym != S) 237 snprint(str, sizeof str, "%N(R%d)(REG)", a, a->reg); 238 break; 239 240 case D_PSR: 241 switch(a->reg) { 242 case 0: 243 snprint(str, sizeof str, "CPSR"); 244 break; 245 case 1: 246 snprint(str, sizeof str, "SPSR"); 247 break; 248 default: 249 snprint(str, sizeof str, "PSR%d", a->reg); 250 break; 251 } 252 if(a->name != D_NONE || a->sym != S) 253 snprint(str, sizeof str, "%N(PSR%d)(REG)", a, a->reg); 254 break; 255 256 case D_FPCR: 257 switch(a->reg){ 258 case 0: 259 snprint(str, sizeof str, "FPSR"); 260 break; 261 case 1: 262 snprint(str, sizeof str, "FPCR"); 263 break; 264 default: 265 snprint(str, sizeof str, "FCR%d", a->reg); 266 break; 267 } 268 if(a->name != D_NONE || a->sym != S) 269 snprint(str, sizeof str, "%N(FCR%d)(REG)", a, a->reg); 270 271 break; 272 273 case D_BRANCH: /* botch */ 274 if(curp->cond != P) { 275 v = curp->cond->pc; 276 if(a->sym != S) 277 snprint(str, sizeof str, "%s+%.5ux(BRANCH)", a->sym->name, v); 278 else 279 snprint(str, sizeof str, "%.5ux(BRANCH)", v); 280 } else 281 if(a->sym != S) 282 snprint(str, sizeof str, "%s+%d(APC)", a->sym->name, a->offset); 283 else 284 snprint(str, sizeof str, "%d(APC)", a->offset); 285 break; 286 287 case D_FCONST: 288 snprint(str, sizeof str, "$%e", ieeedtod(&a->ieee)); 289 break; 290 291 case D_SCONST: 292 snprint(str, sizeof str, "$\"%S\"", a->sval); 293 break; 294 } 295 return fmtstrcpy(fp, str); 296 } 297 298 int 299 Nconv(Fmt *fp) 300 { 301 char str[STRINGSZ]; 302 Adr *a; 303 Sym *s; 304 305 a = va_arg(fp->args, Adr*); 306 s = a->sym; 307 switch(a->name) { 308 default: 309 sprint(str, "GOK-name(%d)", a->name); 310 break; 311 312 case D_NONE: 313 sprint(str, "%d", a->offset); 314 break; 315 316 case D_EXTERN: 317 if(s == S) 318 sprint(str, "%d(SB)", a->offset); 319 else 320 sprint(str, "%s+%d(SB)", s->name, a->offset); 321 break; 322 323 case D_STATIC: 324 if(s == S) 325 sprint(str, "<>+%d(SB)", a->offset); 326 else 327 sprint(str, "%s<>+%d(SB)", s->name, a->offset); 328 break; 329 330 case D_AUTO: 331 if(s == S) 332 sprint(str, "%d(SP)", a->offset); 333 else 334 sprint(str, "%s-%d(SP)", s->name, -a->offset); 335 break; 336 337 case D_PARAM: 338 if(s == S) 339 sprint(str, "%d(FP)", a->offset); 340 else 341 sprint(str, "%s+%d(FP)", s->name, a->offset); 342 break; 343 } 344 return fmtstrcpy(fp, str); 345 } 346 347 int 348 Sconv(Fmt *fp) 349 { 350 int i, c; 351 char str[STRINGSZ], *p, *a; 352 353 a = va_arg(fp->args, char*); 354 p = str; 355 for(i=0; i<sizeof(int32); i++) { 356 c = a[i] & 0xff; 357 if(c >= 'a' && c <= 'z' || 358 c >= 'A' && c <= 'Z' || 359 c >= '0' && c <= '9' || 360 c == ' ' || c == '%') { 361 *p++ = c; 362 continue; 363 } 364 *p++ = '\\'; 365 switch(c) { 366 case 0: 367 *p++ = 'z'; 368 continue; 369 case '\\': 370 case '"': 371 *p++ = c; 372 continue; 373 case '\n': 374 *p++ = 'n'; 375 continue; 376 case '\t': 377 *p++ = 't'; 378 continue; 379 } 380 *p++ = (c>>6) + '0'; 381 *p++ = ((c>>3) & 7) + '0'; 382 *p++ = (c & 7) + '0'; 383 } 384 *p = 0; 385 return fmtstrcpy(fp, str); 386 } 387 388 int 389 Iconv(Fmt *fp) 390 { 391 int i, n; 392 uint32 *p; 393 char *s; 394 Fmt fmt; 395 396 n = fp->prec; 397 fp->prec = 0; 398 if(!(fp->flags&FmtPrec) || n < 0) 399 return fmtstrcpy(fp, "%I"); 400 fp->flags &= ~FmtPrec; 401 p = va_arg(fp->args, uint32*); 402 403 // format into temporary buffer and 404 // call fmtstrcpy to handle padding. 405 fmtstrinit(&fmt); 406 for(i=0; i<n/4; i++) { 407 if(i > 0) 408 fmtprint(&fmt, " "); 409 fmtprint(&fmt, "%.8ux", *p++); 410 } 411 s = fmtstrflush(&fmt); 412 fmtstrcpy(fp, s); 413 free(s); 414 return 0; 415 } 416 417 static char* 418 cnames[] = 419 { 420 [C_ADDR] = "C_ADDR", 421 [C_FAUTO] = "C_FAUTO", 422 [C_ZFCON] = "C_SFCON", 423 [C_SFCON] = "C_SFCON", 424 [C_LFCON] = "C_LFCON", 425 [C_FCR] = "C_FCR", 426 [C_FOREG] = "C_FOREG", 427 [C_FREG] = "C_FREG", 428 [C_GOK] = "C_GOK", 429 [C_HAUTO] = "C_HAUTO", 430 [C_HFAUTO] = "C_HFAUTO", 431 [C_HFOREG] = "C_HFOREG", 432 [C_HOREG] = "C_HOREG", 433 [C_HREG] = "C_HREG", 434 [C_LACON] = "C_LACON", 435 [C_LAUTO] = "C_LAUTO", 436 [C_LBRA] = "C_LBRA", 437 [C_LCON] = "C_LCON", 438 [C_LCONADDR] = "C_LCONADDR", 439 [C_LOREG] = "C_LOREG", 440 [C_NCON] = "C_NCON", 441 [C_NONE] = "C_NONE", 442 [C_PC] = "C_PC", 443 [C_PSR] = "C_PSR", 444 [C_RACON] = "C_RACON", 445 [C_RCON] = "C_RCON", 446 [C_REG] = "C_REG", 447 [C_REGREG] = "C_REGREG", 448 [C_REGREG2] = "C_REGREG2", 449 [C_ROREG] = "C_ROREG", 450 [C_SAUTO] = "C_SAUTO", 451 [C_SBRA] = "C_SBRA", 452 [C_SCON] = "C_SCON", 453 [C_SHIFT] = "C_SHIFT", 454 [C_SOREG] = "C_SOREG", 455 [C_SP] = "C_SP", 456 [C_SROREG] = "C_SROREG" 457 }; 458 459 int 460 Oconv(Fmt *fp) 461 { 462 char buf[500]; 463 int o; 464 465 o = va_arg(fp->args, int); 466 if(o < 0 || o >= nelem(cnames) || cnames[o] == nil) { 467 snprint(buf, sizeof(buf), "C_%d", o); 468 return fmtstrcpy(fp, buf); 469 } 470 return fmtstrcpy(fp, cnames[o]); 471 } 472 473 void 474 diag(char *fmt, ...) 475 { 476 char buf[STRINGSZ], *tn, *sep; 477 va_list arg; 478 479 tn = ""; 480 sep = ""; 481 if(cursym != S) { 482 tn = cursym->name; 483 sep = ": "; 484 } 485 va_start(arg, fmt); 486 vseprint(buf, buf+sizeof(buf), fmt, arg); 487 va_end(arg); 488 print("%s%s%s\n", tn, sep, buf); 489 490 nerrors++; 491 if(nerrors > 20) { 492 print("too many errors\n"); 493 errorexit(); 494 } 495 }