github.com/bgentry/go@v0.0.0-20150121062915-6cf5a733d54d/src/liblink/list5.c (about) 1 // Inferno utils/5c/list.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5c/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 #include <u.h> 32 #include <libc.h> 33 #include <bio.h> 34 #include <link.h> 35 #include "../cmd/5l/5.out.h" 36 37 enum 38 { 39 STRINGSZ = 1000 40 }; 41 42 static int Aconv(Fmt *fp); 43 static int Dconv(Fmt *fp); 44 static int Mconv(Fmt *fp); 45 static int Pconv(Fmt *fp); 46 static int Rconv(Fmt *fp); 47 static int RAconv(Fmt *fp); 48 static int DSconv(Fmt *fp); 49 static int DRconv(Fmt*); 50 51 #pragma varargck type "$" char* 52 #pragma varargck type "M" Addr* 53 #pragma varargck type "@" Addr* 54 55 void 56 listinit5(void) 57 { 58 fmtinstall('A', Aconv); 59 fmtinstall('D', Dconv); 60 fmtinstall('P', Pconv); 61 fmtinstall('R', Rconv); 62 63 // for liblink internal use 64 fmtinstall('^', DRconv); 65 66 // for internal use 67 fmtinstall('$', DSconv); 68 fmtinstall('M', Mconv); 69 fmtinstall('@', RAconv); 70 } 71 72 static char *extra [] = { 73 ".EQ", ".NE", ".CS", ".CC", 74 ".MI", ".PL", ".VS", ".VC", 75 ".HI", ".LS", ".GE", ".LT", 76 ".GT", ".LE", "", ".NV", 77 }; 78 79 static Prog* bigP; 80 81 static int 82 Pconv(Fmt *fp) 83 { 84 char str[STRINGSZ], sc[20]; 85 Prog *p; 86 int a, s; 87 88 p = va_arg(fp->args, Prog*); 89 bigP = p; 90 a = p->as; 91 s = p->scond; 92 strcpy(sc, extra[s & C_SCOND]); 93 if(s & C_SBIT) 94 strcat(sc, ".S"); 95 if(s & C_PBIT) 96 strcat(sc, ".P"); 97 if(s & C_WBIT) 98 strcat(sc, ".W"); 99 if(s & C_UBIT) /* ambiguous with FBIT */ 100 strcat(sc, ".U"); 101 if(a == AMOVM) { 102 if(p->from.type == D_CONST) 103 sprint(str, "%.5lld (%L) %A%s %@,%D", p->pc, p->lineno, a, sc, &p->from, &p->to); 104 else 105 if(p->to.type == D_CONST) 106 sprint(str, "%.5lld (%L) %A%s %D,%@", p->pc, p->lineno, a, sc, &p->from, &p->to); 107 else 108 sprint(str, "%.5lld (%L) %A%s %D,%D", p->pc, p->lineno, a, sc, &p->from, &p->to); 109 } else 110 if(a == ADATA) 111 sprint(str, "%.5lld (%L) %A %D/%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to); 112 else 113 if(p->as == ATEXT) 114 sprint(str, "%.5lld (%L) %A %D,%d,%D", p->pc, p->lineno, a, &p->from, p->reg, &p->to); 115 else 116 if(p->reg == NREG) 117 sprint(str, "%.5lld (%L) %A%s %D,%D", p->pc, p->lineno, a, sc, &p->from, &p->to); 118 else 119 if(p->from.type != D_FREG) 120 sprint(str, "%.5lld (%L) %A%s %D,R%d,%D", p->pc, p->lineno, a, sc, &p->from, p->reg, &p->to); 121 else 122 sprint(str, "%.5lld (%L) %A%s %D,F%d,%D", p->pc, p->lineno, a, sc, &p->from, p->reg, &p->to); 123 bigP = nil; 124 return fmtstrcpy(fp, str); 125 } 126 127 static int 128 Aconv(Fmt *fp) 129 { 130 char *s; 131 int a; 132 133 a = va_arg(fp->args, int); 134 s = "???"; 135 if(a >= AXXX && a < ALAST) 136 s = anames5[a]; 137 return fmtstrcpy(fp, s); 138 } 139 140 static int 141 Dconv(Fmt *fp) 142 { 143 char str[STRINGSZ]; 144 Addr *a; 145 const char *op; 146 int v; 147 148 a = va_arg(fp->args, Addr*); 149 switch(a->type) { 150 151 default: 152 sprint(str, "GOK-type(%d)", a->type); 153 break; 154 155 case D_NONE: 156 str[0] = 0; 157 if(a->name != D_NONE || a->reg != NREG || a->sym != nil) 158 sprint(str, "%M(R%d)(NONE)", a, a->reg); 159 break; 160 161 case D_CONST: 162 if(a->reg != NREG) 163 sprint(str, "$%M(R%d)", a, a->reg); 164 else 165 sprint(str, "$%M", a); 166 break; 167 168 case D_CONST2: 169 sprint(str, "$%lld-%d", a->offset, a->offset2); 170 break; 171 172 case D_SHIFT: 173 v = a->offset; 174 op = &"<<>>->@>"[(((v>>5) & 3) << 1)]; 175 if(v & (1<<4)) 176 sprint(str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15); 177 else 178 sprint(str, "R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31); 179 if(a->reg != NREG) 180 sprint(str+strlen(str), "(R%d)", a->reg); 181 break; 182 183 case D_OREG: 184 if(a->reg != NREG) 185 sprint(str, "%M(R%d)", a, a->reg); 186 else 187 sprint(str, "%M", a); 188 break; 189 190 case D_REG: 191 sprint(str, "R%d", a->reg); 192 if(a->name != D_NONE || a->sym != nil) 193 sprint(str, "%M(R%d)(REG)", a, a->reg); 194 break; 195 196 case D_FREG: 197 sprint(str, "F%d", a->reg); 198 if(a->name != D_NONE || a->sym != nil) 199 sprint(str, "%M(R%d)(REG)", a, a->reg); 200 break; 201 202 case D_PSR: 203 sprint(str, "PSR"); 204 if(a->name != D_NONE || a->sym != nil) 205 sprint(str, "%M(PSR)(REG)", a); 206 break; 207 208 case D_BRANCH: 209 if(a->sym != nil) 210 sprint(str, "%s(SB)", a->sym->name); 211 else if(bigP != nil && bigP->pcond != nil) 212 sprint(str, "%lld", bigP->pcond->pc); 213 else if(a->u.branch != nil) 214 sprint(str, "%lld", a->u.branch->pc); 215 else 216 sprint(str, "%lld(PC)", a->offset/*-pc*/); 217 break; 218 219 case D_FCONST: 220 sprint(str, "$%.17g", a->u.dval); 221 break; 222 223 case D_SCONST: 224 sprint(str, "$\"%$\"", a->u.sval); 225 break; 226 } 227 return fmtstrcpy(fp, str); 228 } 229 230 static int 231 RAconv(Fmt *fp) 232 { 233 char str[STRINGSZ]; 234 Addr *a; 235 int i, v; 236 237 a = va_arg(fp->args, Addr*); 238 sprint(str, "GOK-reglist"); 239 switch(a->type) { 240 case D_CONST: 241 case D_CONST2: 242 if(a->reg != NREG) 243 break; 244 if(a->sym != nil) 245 break; 246 v = a->offset; 247 strcpy(str, ""); 248 for(i=0; i<NREG; i++) { 249 if(v & (1<<i)) { 250 if(str[0] == 0) 251 strcat(str, "[R"); 252 else 253 strcat(str, ",R"); 254 sprint(strchr(str, 0), "%d", i); 255 } 256 } 257 strcat(str, "]"); 258 } 259 return fmtstrcpy(fp, str); 260 } 261 262 static int 263 DSconv(Fmt *fp) 264 { 265 int i, c; 266 char str[STRINGSZ], *p, *a; 267 268 a = va_arg(fp->args, char*); 269 p = str; 270 for(i=0; i<NSNAME; i++) { 271 c = a[i] & 0xff; 272 if(c >= 'a' && c <= 'z' || 273 c >= 'A' && c <= 'Z' || 274 c >= '0' && c <= '9' || 275 c == ' ' || c == '%') { 276 *p++ = c; 277 continue; 278 } 279 *p++ = '\\'; 280 switch(c) { 281 case 0: 282 *p++ = 'z'; 283 continue; 284 case '\\': 285 case '"': 286 *p++ = c; 287 continue; 288 case '\n': 289 *p++ = 'n'; 290 continue; 291 case '\t': 292 *p++ = 't'; 293 continue; 294 case '\r': 295 *p++ = 'r'; 296 continue; 297 case '\f': 298 *p++ = 'f'; 299 continue; 300 } 301 *p++ = (c>>6) + '0'; 302 *p++ = ((c>>3) & 7) + '0'; 303 *p++ = (c & 7) + '0'; 304 } 305 *p = 0; 306 return fmtstrcpy(fp, str); 307 } 308 309 static int 310 Rconv(Fmt *fp) 311 { 312 int r; 313 char str[STRINGSZ]; 314 315 r = va_arg(fp->args, int); 316 sprint(str, "R%d", r); 317 return fmtstrcpy(fp, str); 318 } 319 320 static int 321 DRconv(Fmt *fp) 322 { 323 char *s; 324 int a; 325 326 a = va_arg(fp->args, int); 327 s = "C_??"; 328 if(a >= C_NONE && a <= C_NCLASS) 329 s = cnames5[a]; 330 return fmtstrcpy(fp, s); 331 } 332 333 static int 334 Mconv(Fmt *fp) 335 { 336 char str[STRINGSZ]; 337 Addr *a; 338 LSym *s; 339 340 a = va_arg(fp->args, Addr*); 341 s = a->sym; 342 if(s == nil) { 343 sprint(str, "%d", (int)a->offset); 344 goto out; 345 } 346 switch(a->name) { 347 default: 348 sprint(str, "GOK-name(%d)", a->name); 349 break; 350 351 case D_NONE: 352 sprint(str, "%lld", a->offset); 353 break; 354 355 case D_EXTERN: 356 sprint(str, "%s+%d(SB)", s->name, (int)a->offset); 357 break; 358 359 case D_STATIC: 360 sprint(str, "%s<>+%d(SB)", s->name, (int)a->offset); 361 break; 362 363 case D_AUTO: 364 sprint(str, "%s-%d(SP)", s->name, (int)-a->offset); 365 break; 366 367 case D_PARAM: 368 sprint(str, "%s+%d(FP)", s->name, (int)a->offset); 369 break; 370 } 371 out: 372 return fmtstrcpy(fp, str); 373 }