github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/5g/list.c (about) 1 // Derived from 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 "gg.h" 34 35 // TODO(kaib): make 5g/list.c congruent with 5l/list.c 36 37 static int sconsize; 38 void 39 listinit(void) 40 { 41 42 fmtinstall('A', Aconv); // as 43 fmtinstall('C', Cconv); // conditional execution bit 44 fmtinstall('P', Pconv); // Prog* 45 fmtinstall('D', Dconv); // Addr* 46 fmtinstall('Y', Yconv); // sconst 47 fmtinstall('R', Rconv); // register 48 fmtinstall('M', Mconv); // names 49 } 50 51 int 52 Pconv(Fmt *fp) 53 { 54 char str[STRINGSZ], str1[STRINGSZ]; 55 Prog *p; 56 57 p = va_arg(fp->args, Prog*); 58 sconsize = 8; 59 switch(p->as) { 60 default: 61 snprint(str1, sizeof(str1), "%A%C", p->as, p->scond); 62 if(p->reg == NREG && p->as != AGLOBL) 63 snprint(str, sizeof(str), "%.4d (%L) %-7s %D,%D", 64 p->loc, p->lineno, str1, &p->from, &p->to); 65 else 66 if (p->from.type != D_FREG) { 67 snprint(str, sizeof(str), "%.4d (%L) %-7s %D,R%d,%D", 68 p->loc, p->lineno, str1, &p->from, p->reg, &p->to); 69 } else 70 snprint(str, sizeof(str), "%.4d (%L) %-7A%C %D,F%d,%D", 71 p->loc, p->lineno, p->as, p->scond, &p->from, p->reg, &p->to); 72 break; 73 74 case ADATA: 75 snprint(str, sizeof(str), "%.4d (%L) %-7A %D/%d,%D", 76 p->loc, p->lineno, p->as, &p->from, p->reg, &p->to); 77 break; 78 } 79 return fmtstrcpy(fp, str); 80 } 81 82 int 83 Dconv(Fmt *fp) 84 { 85 char str[STRINGSZ]; 86 const char *op; 87 Addr *a; 88 int i; 89 int32 v; 90 91 a = va_arg(fp->args, Addr*); 92 if(a == A) { 93 sprint(str, "<nil>"); 94 goto conv; 95 } 96 i = a->type; 97 switch(i) { 98 99 default: 100 sprint(str, "GOK-type(%d)", a->type); 101 break; 102 103 case D_NONE: 104 str[0] = 0; 105 if(a->name != D_NONE || a->reg != NREG || a->sym != S) 106 sprint(str, "%M(R%d)(NONE)", a, a->reg); 107 break; 108 109 case D_CONST: 110 if(a->reg != NREG) 111 sprint(str, "$%M(R%d)", a, a->reg); 112 else 113 sprint(str, "$%M", a); 114 break; 115 116 case D_CONST2: 117 sprint(str, "$%d-%d", a->offset, a->offset2); 118 break; 119 120 case D_SHIFT: 121 v = a->offset; 122 op = &"<<>>->@>"[(((v>>5) & 3) << 1)]; 123 if(v & (1<<4)) 124 sprint(str, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15); 125 else 126 sprint(str, "R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31); 127 if(a->reg != NREG) 128 sprint(str+strlen(str), "(R%d)", a->reg); 129 break; 130 131 case D_OCONST: 132 sprint(str, "$*$%M", a); 133 if(a->reg != NREG) 134 sprint(str, "%M(R%d)(CONST)", a, a->reg); 135 break; 136 137 case D_OREG: 138 if(a->reg != NREG) 139 sprint(str, "%M(R%d)", a, a->reg); 140 else 141 sprint(str, "%M", a); 142 break; 143 144 case D_REG: 145 sprint(str, "R%d", a->reg); 146 if(a->name != D_NONE || a->sym != S) 147 sprint(str, "%M(R%d)(REG)", a, a->reg); 148 break; 149 150 case D_REGREG: 151 sprint(str, "(R%d,R%d)", a->reg, (int)a->offset); 152 if(a->name != D_NONE || a->sym != S) 153 sprint(str, "%M(R%d)(REG)", a, a->reg); 154 break; 155 156 case D_REGREG2: 157 sprint(str, "R%d,R%d", a->reg, (int)a->offset); 158 if(a->name != D_NONE || a->sym != S) 159 sprint(str, "%M(R%d)(REG)", a, a->reg); 160 break; 161 162 case D_FREG: 163 sprint(str, "F%d", a->reg); 164 if(a->name != D_NONE || a->sym != S) 165 sprint(str, "%M(R%d)(REG)", a, a->reg); 166 break; 167 168 case D_BRANCH: 169 if(a->u.branch == P || a->u.branch->loc == 0) { 170 if(a->sym != S) 171 sprint(str, "%s+%d(APC)", a->sym->name, a->offset); 172 else 173 sprint(str, "%d(APC)", a->offset); 174 } else 175 if(a->sym != S) 176 sprint(str, "%s+%d(APC)", a->sym->name, a->u.branch->loc); 177 else 178 sprint(str, "%d(APC)", a->u.branch->loc); 179 break; 180 181 case D_FCONST: 182 snprint(str, sizeof(str), "$(%.17e)", a->u.dval); 183 break; 184 185 case D_SCONST: 186 snprint(str, sizeof(str), "$\"%Y\"", a->u.sval); 187 break; 188 189 // TODO(kaib): Add back 190 // case D_ADDR: 191 // a->type = a->index; 192 // a->index = D_NONE; 193 // snprint(str, sizeof(str), "$%D", a); 194 // a->index = a->type; 195 // a->type = D_ADDR; 196 // goto conv; 197 } 198 conv: 199 fmtstrcpy(fp, str); 200 if(a->gotype) 201 fmtprint(fp, "{%s}", a->gotype->name); 202 return 0; 203 } 204 205 int 206 Aconv(Fmt *fp) 207 { 208 int i; 209 210 i = va_arg(fp->args, int); 211 return fmtstrcpy(fp, anames[i]); 212 } 213 214 char* strcond[16] = 215 { 216 ".EQ", 217 ".NE", 218 ".HS", 219 ".LO", 220 ".MI", 221 ".PL", 222 ".VS", 223 ".VC", 224 ".HI", 225 ".LS", 226 ".GE", 227 ".LT", 228 ".GT", 229 ".LE", 230 "", 231 ".NV" 232 }; 233 234 int 235 Cconv(Fmt *fp) 236 { 237 char s[STRINGSZ]; 238 int c; 239 240 c = va_arg(fp->args, int); 241 strcpy(s, strcond[c & C_SCOND]); 242 if(c & C_SBIT) 243 strcat(s, ".S"); 244 if(c & C_PBIT) 245 strcat(s, ".P"); 246 if(c & C_WBIT) 247 strcat(s, ".W"); 248 if(c & C_UBIT) /* ambiguous with FBIT */ 249 strcat(s, ".U"); 250 return fmtstrcpy(fp, s); 251 } 252 253 int 254 Yconv(Fmt *fp) 255 { 256 int i, c; 257 char str[STRINGSZ], *p, *a; 258 259 a = va_arg(fp->args, char*); 260 p = str; 261 for(i=0; i<sconsize; i++) { 262 c = a[i] & 0xff; 263 if((c >= 'a' && c <= 'z') || 264 (c >= 'A' && c <= 'Z') || 265 (c >= '0' && c <= '9')) { 266 *p++ = c; 267 continue; 268 } 269 *p++ = '\\'; 270 switch(c) { 271 default: 272 if(c < 040 || c >= 0177) 273 break; /* not portable */ 274 p[-1] = c; 275 continue; 276 case 0: 277 *p++ = 'z'; 278 continue; 279 case '\\': 280 case '"': 281 *p++ = c; 282 continue; 283 case '\n': 284 *p++ = 'n'; 285 continue; 286 case '\t': 287 *p++ = 't'; 288 continue; 289 } 290 *p++ = (c>>6) + '0'; 291 *p++ = ((c>>3) & 7) + '0'; 292 *p++ = (c & 7) + '0'; 293 } 294 *p = 0; 295 return fmtstrcpy(fp, str); 296 } 297 298 int 299 Rconv(Fmt *fp) 300 { 301 int r; 302 char str[STRINGSZ]; 303 304 r = va_arg(fp->args, int); 305 snprint(str, sizeof(str), "R%d", r); 306 return fmtstrcpy(fp, str); 307 } 308 309 int 310 Mconv(Fmt *fp) 311 { 312 char str[STRINGSZ]; 313 Addr *a; 314 315 a = va_arg(fp->args, Addr*); 316 switch(a->name) { 317 default: 318 snprint(str, sizeof(str), "GOK-name(%d)", a->name); 319 break; 320 321 case D_NONE: 322 snprint(str, sizeof(str), "%d", a->offset); 323 break; 324 325 case D_EXTERN: 326 snprint(str, sizeof(str), "%S+%d(SB)", a->sym, a->offset); 327 break; 328 329 case D_STATIC: 330 snprint(str, sizeof(str), "%S<>+%d(SB)", a->sym, a->offset); 331 break; 332 333 case D_AUTO: 334 snprint(str, sizeof(str), "%S+%d(SP)", a->sym, a->offset); 335 break; 336 337 case D_PARAM: 338 snprint(str, sizeof(str), "%S+%d(FP)", a->sym, a->offset); 339 break; 340 } 341 return fmtstrcpy(fp, str); 342 }