github.com/golang-haiku/go-1.4.3@v0.0.0-20190609233734-1f5ae41cc308/src/liblink/list6.c (about)

     1  // Inferno utils/6c/list.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/6c/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/6l/6.out.h"
    36  
    37  //
    38  // Format conversions
    39  //	%A int		Opcodes (instruction mnemonics)
    40  //
    41  //	%D Addr*	Addresses (instruction operands)
    42  //		Flags: "%lD": seperate the high and low words of a constant by "-"
    43  //
    44  //	%P Prog*	Instructions
    45  //
    46  //	%R int		Registers
    47  //
    48  //	%$ char*	String constant addresses (for internal use only)
    49  
    50  static int	Aconv(Fmt *fp);
    51  static int	Dconv(Fmt *fp);
    52  static int	Pconv(Fmt *fp);
    53  static int	Rconv(Fmt *fp);
    54  static int	DSconv(Fmt *fp);
    55  
    56  enum
    57  {
    58  	STRINGSZ = 1000
    59  };
    60  
    61  #pragma	varargck	type	"$"	char*
    62  
    63  void
    64  listinit6(void)
    65  {
    66  	fmtinstall('A', Aconv);
    67  	fmtinstall('D', Dconv);
    68  	fmtinstall('P', Pconv);
    69  	fmtinstall('R', Rconv);
    70  
    71  	// for internal use
    72  	fmtinstall('$', DSconv);
    73  }
    74  
    75  static	Prog*	bigP;
    76  
    77  static int
    78  Pconv(Fmt *fp)
    79  {
    80  	char str[STRINGSZ];
    81  	Prog *p;
    82  
    83  	p = va_arg(fp->args, Prog*);
    84  	bigP = p;
    85  	switch(p->as) {
    86  	case ADATA:
    87  		sprint(str, "%.5lld (%L)	%A	%D/%d,%D",
    88  			p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to);
    89  		break;
    90  
    91  	case ATEXT:
    92  		if(p->from.scale) {
    93  			sprint(str, "%.5lld (%L)	%A	%D,%d,%lD",
    94  				p->pc, p->lineno, p->as, &p->from, p->from.scale, &p->to);
    95  			break;
    96  		}
    97  		sprint(str, "%.5lld (%L)	%A	%D,%lD",
    98  			p->pc, p->lineno, p->as, &p->from, &p->to);
    99  		break;
   100  
   101  	default:
   102  		sprint(str, "%.5lld (%L)	%A	%D,%D",
   103  			p->pc, p->lineno, p->as, &p->from, &p->to);
   104  		break;
   105  	}
   106  	bigP = nil;
   107  	return fmtstrcpy(fp, str);
   108  }
   109  
   110  static int
   111  Aconv(Fmt *fp)
   112  {
   113  	int i;
   114  
   115  	i = va_arg(fp->args, int);
   116  	return fmtstrcpy(fp, anames6[i]);
   117  }
   118  
   119  static int
   120  Dconv(Fmt *fp)
   121  {
   122  	char str[STRINGSZ], s[STRINGSZ];
   123  	Addr *a;
   124  	int i;
   125  
   126  	a = va_arg(fp->args, Addr*);
   127  	i = a->type;
   128  
   129  	if(fp->flags & FmtLong) {
   130  		if(i == D_CONST)
   131  			sprint(str, "$%lld-%lld", a->offset&0xffffffffLL, a->offset>>32);
   132  		else {
   133  			// ATEXT dst is not constant
   134  			sprint(str, "!!%D", a);
   135  		}
   136  		goto brk;
   137  	}
   138  
   139  	if(i >= D_INDIR) {
   140  		if(a->offset)
   141  			sprint(str, "%lld(%R)", a->offset, i-D_INDIR);
   142  		else
   143  			sprint(str, "(%R)", i-D_INDIR);
   144  		goto brk;
   145  	}
   146  	switch(i) {
   147  	default:
   148  		if(a->offset)
   149  			sprint(str, "$%lld,%R", a->offset, i);
   150  		else
   151  			sprint(str, "%R", i);
   152  		break;
   153  
   154  	case D_NONE:
   155  		str[0] = 0;
   156  		break;
   157  
   158  	case D_BRANCH:
   159  		if(a->sym != nil)
   160  			sprint(str, "%s(SB)", a->sym->name);
   161  		else if(bigP != nil && bigP->pcond != nil)
   162  			sprint(str, "%lld", bigP->pcond->pc);
   163  		else if(a->u.branch != nil)
   164  			sprint(str, "%lld", a->u.branch->pc);
   165  		else
   166  			sprint(str, "%lld(PC)", a->offset);
   167  		break;
   168  
   169  	case D_EXTERN:
   170  		sprint(str, "%s+%lld(SB)", a->sym->name, a->offset);
   171  		break;
   172  
   173  	case D_STATIC:
   174  		sprint(str, "%s<>+%lld(SB)", a->sym->name, a->offset);
   175  		break;
   176  
   177  	case D_AUTO:
   178  		if(a->sym)
   179  			sprint(str, "%s+%lld(SP)", a->sym->name, a->offset);
   180  		else
   181  			sprint(str, "%lld(SP)", a->offset);
   182  		break;
   183  
   184  	case D_PARAM:
   185  		if(a->sym)
   186  			sprint(str, "%s+%lld(FP)", a->sym->name, a->offset);
   187  		else
   188  			sprint(str, "%lld(FP)", a->offset);
   189  		break;
   190  
   191  	case D_CONST:
   192  		sprint(str, "$%lld", a->offset);
   193  		break;
   194  
   195  	case D_FCONST:
   196  		sprint(str, "$(%.17g)", a->u.dval);
   197  		break;
   198  
   199  	case D_SCONST:
   200  		sprint(str, "$\"%$\"", a->u.sval);
   201  		break;
   202  
   203  	case D_ADDR:
   204  		a->type = a->index;
   205  		a->index = D_NONE;
   206  		sprint(str, "$%D", a);
   207  		a->index = a->type;
   208  		a->type = D_ADDR;
   209  		goto conv;
   210  	}
   211  brk:
   212  	if(a->index != D_NONE) {
   213  		sprint(s, "(%R*%d)", (int)a->index, (int)a->scale);
   214  		strcat(str, s);
   215  	}
   216  conv:
   217  	return fmtstrcpy(fp, str);
   218  }
   219  
   220  static char*	regstr[] =
   221  {
   222  	"AL",	/* [D_AL] */
   223  	"CL",
   224  	"DL",
   225  	"BL",
   226  	"SPB",
   227  	"BPB",
   228  	"SIB",
   229  	"DIB",
   230  	"R8B",
   231  	"R9B",
   232  	"R10B",
   233  	"R11B",
   234  	"R12B",
   235  	"R13B",
   236  	"R14B",
   237  	"R15B",
   238  
   239  	"AX",	/* [D_AX] */
   240  	"CX",
   241  	"DX",
   242  	"BX",
   243  	"SP",
   244  	"BP",
   245  	"SI",
   246  	"DI",
   247  	"R8",
   248  	"R9",
   249  	"R10",
   250  	"R11",
   251  	"R12",
   252  	"R13",
   253  	"R14",
   254  	"R15",
   255  
   256  	"AH",
   257  	"CH",
   258  	"DH",
   259  	"BH",
   260  
   261  	"F0",	/* [D_F0] */
   262  	"F1",
   263  	"F2",
   264  	"F3",
   265  	"F4",
   266  	"F5",
   267  	"F6",
   268  	"F7",
   269  
   270  	"M0",
   271  	"M1",
   272  	"M2",
   273  	"M3",
   274  	"M4",
   275  	"M5",
   276  	"M6",
   277  	"M7",
   278  
   279  	"X0",
   280  	"X1",
   281  	"X2",
   282  	"X3",
   283  	"X4",
   284  	"X5",
   285  	"X6",
   286  	"X7",
   287  	"X8",
   288  	"X9",
   289  	"X10",
   290  	"X11",
   291  	"X12",
   292  	"X13",
   293  	"X14",
   294  	"X15",
   295  
   296  	"CS",	/* [D_CS] */
   297  	"SS",
   298  	"DS",
   299  	"ES",
   300  	"FS",
   301  	"GS",
   302  
   303  	"GDTR",	/* [D_GDTR] */
   304  	"IDTR",	/* [D_IDTR] */
   305  	"LDTR",	/* [D_LDTR] */
   306  	"MSW",	/* [D_MSW] */
   307  	"TASK",	/* [D_TASK] */
   308  
   309  	"CR0",	/* [D_CR] */
   310  	"CR1",
   311  	"CR2",
   312  	"CR3",
   313  	"CR4",
   314  	"CR5",
   315  	"CR6",
   316  	"CR7",
   317  	"CR8",
   318  	"CR9",
   319  	"CR10",
   320  	"CR11",
   321  	"CR12",
   322  	"CR13",
   323  	"CR14",
   324  	"CR15",
   325  
   326  	"DR0",	/* [D_DR] */
   327  	"DR1",
   328  	"DR2",
   329  	"DR3",
   330  	"DR4",
   331  	"DR5",
   332  	"DR6",
   333  	"DR7",
   334  
   335  	"TR0",	/* [D_TR] */
   336  	"TR1",
   337  	"TR2",
   338  	"TR3",
   339  	"TR4",
   340  	"TR5",
   341  	"TR6",
   342  	"TR7",
   343  
   344  	"TLS",	/* [D_TLS] */
   345  	"NONE",	/* [D_NONE] */
   346  };
   347  
   348  static int
   349  Rconv(Fmt *fp)
   350  {
   351  	char str[STRINGSZ];
   352  	int r;
   353  
   354  	r = va_arg(fp->args, int);
   355  	if(r >= D_AL && r <= D_NONE)
   356  		sprint(str, "%s", regstr[r-D_AL]);
   357  	else
   358  		sprint(str, "gok(%d)", r);
   359  
   360  	return fmtstrcpy(fp, str);
   361  }
   362  
   363  static int
   364  DSconv(Fmt *fp)
   365  {
   366  	int i, c;
   367  	char str[STRINGSZ], *p, *a;
   368  
   369  	a = va_arg(fp->args, char*);
   370  	p = str;
   371  	for(i=0; i<sizeof(double); i++) {
   372  		c = a[i] & 0xff;
   373  		if(c >= 'a' && c <= 'z' ||
   374  		   c >= 'A' && c <= 'Z' ||
   375  		   c >= '0' && c <= '9') {
   376  			*p++ = c;
   377  			continue;
   378  		}
   379  		*p++ = '\\';
   380  		switch(c) {
   381  		default:
   382  			if(c < 040 || c >= 0177)
   383  				break;	/* not portable */
   384  			p[-1] = c;
   385  			continue;
   386  		case 0:
   387  			*p++ = 'z';
   388  			continue;
   389  		case '\\':
   390  		case '"':
   391  			*p++ = c;
   392  			continue;
   393  		case '\n':
   394  			*p++ = 'n';
   395  			continue;
   396  		case '\t':
   397  			*p++ = 't';
   398  			continue;
   399  		}
   400  		*p++ = (c>>6) + '0';
   401  		*p++ = ((c>>3) & 7) + '0';
   402  		*p++ = (c & 7) + '0';
   403  	}
   404  	*p = 0;
   405  	return fmtstrcpy(fp, str);
   406  }