github.com/ader1990/go@v0.0.0-20140630135419-8c24447fa791/src/cmd/5a/lex.c (about)

     1  // Inferno utils/5a/lex.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/5a/lex.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  #define	EXTERN
    32  #include <u.h>
    33  #include <libc.h>
    34  #include "a.h"
    35  #include "y.tab.h"
    36  
    37  enum
    38  {
    39  	Plan9	= 1<<0,
    40  	Unix	= 1<<1,
    41  	Windows	= 1<<2,
    42  };
    43  
    44  int
    45  systemtype(int sys)
    46  {
    47  #ifdef _WIN32
    48  	return sys&Windows;
    49  #else
    50  	return sys&Plan9;
    51  #endif
    52  }
    53  
    54  int
    55  Lconv(Fmt *fp)
    56  {
    57  	return linklinefmt(ctxt, fp);
    58  }
    59  
    60  void
    61  dodef(char *p)
    62  {
    63  	if(nDlist%8 == 0)
    64  		Dlist = allocn(Dlist, nDlist*sizeof(char *),
    65  			8*sizeof(char *));
    66  	Dlist[nDlist++] = p;
    67  }
    68  
    69  void
    70  usage(void)
    71  {
    72  	print("usage: %ca [options] file.c...\n", thechar);
    73  	flagprint(1);
    74  	errorexit();
    75  }
    76  
    77  void
    78  main(int argc, char *argv[])
    79  {
    80  	char *p;
    81  
    82  	thechar = '5';
    83  	thestring = "arm";
    84  
    85  	ctxt = linknew(&linkarm);
    86  	ctxt->diag = yyerror;
    87  	ctxt->bso = &bstdout;
    88  	Binit(&bstdout, 1, OWRITE);
    89  	listinit5();
    90  	fmtinstall('L', Lconv);
    91  
    92  	// Allow GOARCH=thestring or GOARCH=thestringsuffix,
    93  	// but not other values.	
    94  	p = getgoarch();
    95  	if(strncmp(p, thestring, strlen(thestring)) != 0)
    96  		sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
    97  
    98  	ensuresymb(NSYMB);
    99  	memset(debug, 0, sizeof(debug));
   100  	cinit();
   101  	outfile = 0;
   102  	setinclude(".");
   103  	
   104  	flagfn1("D", "name[=value]: add #define", dodef);
   105  	flagfn1("I", "dir: add dir to include path", setinclude);
   106  	flagcount("S", "print assembly and machine code", &debug['S']);
   107  	flagcount("m", "debug preprocessor macros", &debug['m']);
   108  	flagstr("o", "file: set output file", &outfile);
   109  	flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
   110  
   111  	flagparse(&argc, &argv, usage);
   112  	ctxt->debugasm = debug['S'];
   113  
   114  	if(argc < 1)
   115  		usage();
   116  	if(argc > 1){
   117  		print("can't assemble multiple files\n");
   118  		errorexit();
   119  	}
   120  
   121  	if(assemble(argv[0]))
   122  		errorexit();
   123  	Bflush(&bstdout);
   124  	exits(0);
   125  }
   126  
   127  int
   128  assemble(char *file)
   129  {
   130  	char *ofile, *p;
   131  	int i, of;
   132  
   133  	ofile = alloc(strlen(file)+3); // +3 for .x\0 (x=thechar)
   134  	strcpy(ofile, file);
   135  	p = utfrrune(ofile, '/');
   136  	if(p) {
   137  		include[0] = ofile;
   138  		*p++ = 0;
   139  	} else
   140  		p = ofile;
   141  	if(outfile == 0) {
   142  		outfile = p;
   143  		if(outfile){
   144  			p = utfrrune(outfile, '.');
   145  			if(p)
   146  				if(p[1] == 's' && p[2] == 0)
   147  					p[0] = 0;
   148  			p = utfrune(outfile, 0);
   149  			p[0] = '.';
   150  			p[1] = thechar;
   151  			p[2] = 0;
   152  		} else
   153  			outfile = "/dev/null";
   154  	}
   155  
   156  	of = create(outfile, OWRITE, 0664);
   157  	if(of < 0) {
   158  		yyerror("%ca: cannot create %s", thechar, outfile);
   159  		errorexit();
   160  	}
   161  	Binit(&obuf, of, OWRITE);
   162  	Bprint(&obuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
   163  	Bprint(&obuf, "!\n");
   164  
   165  	for(pass = 1; pass <= 2; pass++) {
   166  		pinit(file);
   167  		for(i=0; i<nDlist; i++)
   168  			dodefine(Dlist[i]);
   169  		yyparse();
   170  		cclean();
   171  		if(nerrors)
   172  			return nerrors;
   173  	}
   174  
   175  	writeobj(ctxt, &obuf);
   176  	Bflush(&obuf);
   177  	return 0;
   178  }
   179  
   180  struct
   181  {
   182  	char	*name;
   183  	ushort	type;
   184  	ushort	value;
   185  } itab[] =
   186  {
   187  	"SP",		LSP,	D_AUTO,
   188  	"SB",		LSB,	D_EXTERN,
   189  	"FP",		LFP,	D_PARAM,
   190  	"PC",		LPC,	D_BRANCH,
   191  
   192  	"R",		LR,	0,
   193  	"R0",		LREG,	0,
   194  	"R1",		LREG,	1,
   195  	"R2",		LREG,	2,
   196  	"R3",		LREG,	3,
   197  	"R4",		LREG,	4,
   198  	"R5",		LREG,	5,
   199  	"R6",		LREG,	6,
   200  	"R7",		LREG,	7,
   201  	"R8",		LREG,	8,
   202  	"m",		LREG,	9, // avoid unintentionally clobber m/g using R9/R10
   203  	"g",		LREG,	10,
   204  	"R11",		LREG,	11,
   205  	"R12",		LREG,	12,
   206  	"R13",		LREG,	13,
   207  	"R14",		LREG,	14,
   208  	"R15",		LREG,	15,
   209  
   210  	"F",		LF,	0,
   211  
   212  	"F0",		LFREG,	0,
   213  	"F1",		LFREG,	1,
   214  	"F2",		LFREG,	2,
   215  	"F3",		LFREG,	3,
   216  	"F4",		LFREG,	4,
   217  	"F5",		LFREG,	5,
   218  	"F6",		LFREG,	6,
   219  	"F7",		LFREG,	7,
   220  	"F8",		LFREG,	8,
   221  	"F9",		LFREG,	9,
   222  	"F10",		LFREG,	10,
   223  	"F11",		LFREG,	11,
   224  	"F12",		LFREG,	12,
   225  	"F13",		LFREG,	13,
   226  	"F14",		LFREG,	14,
   227  	"F15",		LFREG,	15,
   228  
   229  	"C",		LC,	0,
   230  
   231  	"C0",		LCREG,	0,
   232  	"C1",		LCREG,	1,
   233  	"C2",		LCREG,	2,
   234  	"C3",		LCREG,	3,
   235  	"C4",		LCREG,	4,
   236  	"C5",		LCREG,	5,
   237  	"C6",		LCREG,	6,
   238  	"C7",		LCREG,	7,
   239  	"C8",		LCREG,	8,
   240  	"C9",		LCREG,	9,
   241  	"C10",		LCREG,	10,
   242  	"C11",		LCREG,	11,
   243  	"C12",		LCREG,	12,
   244  	"C13",		LCREG,	13,
   245  	"C14",		LCREG,	14,
   246  	"C15",		LCREG,	15,
   247  
   248  	"CPSR",		LPSR,	0,
   249  	"SPSR",		LPSR,	1,
   250  
   251  	"FPSR",		LFCR,	0,
   252  	"FPCR",		LFCR,	1,
   253  
   254  	".EQ",		LCOND,	0,
   255  	".NE",		LCOND,	1,
   256  	".CS",		LCOND,	2,
   257  	".HS",		LCOND,	2,
   258  	".CC",		LCOND,	3,
   259  	".LO",		LCOND,	3,
   260  	".MI",		LCOND,	4,
   261  	".PL",		LCOND,	5,
   262  	".VS",		LCOND,	6,
   263  	".VC",		LCOND,	7,
   264  	".HI",		LCOND,	8,
   265  	".LS",		LCOND,	9,
   266  	".GE",		LCOND,	10,
   267  	".LT",		LCOND,	11,
   268  	".GT",		LCOND,	12,
   269  	".LE",		LCOND,	13,
   270  	".AL",		LCOND,	Always,
   271  
   272  	".U",		LS,	C_UBIT,
   273  	".S",		LS,	C_SBIT,
   274  	".W",		LS,	C_WBIT,
   275  	".P",		LS,	C_PBIT,
   276  	".PW",		LS,	C_WBIT|C_PBIT,
   277  	".WP",		LS,	C_WBIT|C_PBIT,
   278  
   279  	".F",		LS,	C_FBIT,
   280  
   281  	".IBW",		LS,	C_WBIT|C_PBIT|C_UBIT,
   282  	".IAW",		LS,	C_WBIT|C_UBIT,
   283  	".DBW",		LS,	C_WBIT|C_PBIT,
   284  	".DAW",		LS,	C_WBIT,
   285  	".IB",		LS,	C_PBIT|C_UBIT,
   286  	".IA",		LS,	C_UBIT,
   287  	".DB",		LS,	C_PBIT,
   288  	".DA",		LS,	0,
   289  
   290  	"@",		LAT,	0,
   291  
   292  	"AND",		LTYPE1,	AAND,
   293  	"EOR",		LTYPE1,	AEOR,
   294  	"SUB",		LTYPE1,	ASUB,
   295  	"RSB",		LTYPE1,	ARSB,
   296  	"ADD",		LTYPE1,	AADD,
   297  	"ADC",		LTYPE1,	AADC,
   298  	"SBC",		LTYPE1,	ASBC,
   299  	"RSC",		LTYPE1,	ARSC,
   300  	"ORR",		LTYPE1,	AORR,
   301  	"BIC",		LTYPE1,	ABIC,
   302  
   303  	"SLL",		LTYPE1,	ASLL,
   304  	"SRL",		LTYPE1,	ASRL,
   305  	"SRA",		LTYPE1,	ASRA,
   306  
   307  	"MUL",		LTYPE1, AMUL,
   308  	"MULA",		LTYPEN, AMULA,
   309  	"DIV",		LTYPE1,	ADIV,
   310  	"MOD",		LTYPE1,	AMOD,
   311  
   312  	"MULL",		LTYPEM, AMULL,
   313  	"MULAL",	LTYPEM, AMULAL,
   314  	"MULLU",	LTYPEM, AMULLU,
   315  	"MULALU",	LTYPEM, AMULALU,
   316  
   317  	"MVN",		LTYPE2, AMVN,	/* op2 ignored */
   318  
   319  	"MOVB",		LTYPE3, AMOVB,
   320  	"MOVBU",	LTYPE3, AMOVBU,
   321  	"MOVH",		LTYPE3, AMOVH,
   322  	"MOVHU",	LTYPE3, AMOVHU,
   323  	"MOVW",		LTYPE3, AMOVW,
   324  
   325  	"MOVD",		LTYPE3, AMOVD,
   326  	"MOVDF",		LTYPE3, AMOVDF,
   327  	"MOVDW",	LTYPE3, AMOVDW,
   328  	"MOVF",		LTYPE3, AMOVF,
   329  	"MOVFD",		LTYPE3, AMOVFD,
   330  	"MOVFW",		LTYPE3, AMOVFW,
   331  	"MOVWD",	LTYPE3, AMOVWD,
   332  	"MOVWF",		LTYPE3, AMOVWF,
   333  
   334  	"LDREX",		LTYPE3, ALDREX,
   335  	"LDREXD",		LTYPE3, ALDREXD,
   336  	"STREX",		LTYPE9, ASTREX,
   337  	"STREXD",		LTYPE9, ASTREXD,
   338  
   339  /*
   340  	"NEGF",		LTYPEI, ANEGF,
   341  	"NEGD",		LTYPEI, ANEGD,
   342  	"SQTF",		LTYPEI,	ASQTF,
   343  	"SQTD",		LTYPEI,	ASQTD,
   344  	"RNDF",		LTYPEI,	ARNDF,
   345  	"RNDD",		LTYPEI,	ARNDD,
   346  	"URDF",		LTYPEI,	AURDF,
   347  	"URDD",		LTYPEI,	AURDD,
   348  	"NRMF",		LTYPEI,	ANRMF,
   349  	"NRMD",		LTYPEI,	ANRMD,
   350  */
   351  
   352  	"ABSF",		LTYPEI, AABSF,
   353  	"ABSD",		LTYPEI, AABSD,
   354  	"SQRTF",	LTYPEI, ASQRTF,
   355  	"SQRTD",	LTYPEI, ASQRTD,
   356  	"CMPF",		LTYPEL, ACMPF,
   357  	"CMPD",		LTYPEL, ACMPD,
   358  	"ADDF",		LTYPEK,	AADDF,
   359  	"ADDD",		LTYPEK,	AADDD,
   360  	"SUBF",		LTYPEK,	ASUBF,
   361  	"SUBD",		LTYPEK,	ASUBD,
   362  	"MULF",		LTYPEK,	AMULF,
   363  	"MULD",		LTYPEK,	AMULD,
   364  	"DIVF",		LTYPEK,	ADIVF,
   365  	"DIVD",		LTYPEK,	ADIVD,
   366  
   367  	"B",		LTYPE4, AB,
   368  	"BL",		LTYPE4, ABL,
   369  	"BX",		LTYPEBX,	ABX,
   370  
   371  	"BEQ",		LTYPE5,	ABEQ,
   372  	"BNE",		LTYPE5,	ABNE,
   373  	"BCS",		LTYPE5,	ABCS,
   374  	"BHS",		LTYPE5,	ABHS,
   375  	"BCC",		LTYPE5,	ABCC,
   376  	"BLO",		LTYPE5,	ABLO,
   377  	"BMI",		LTYPE5,	ABMI,
   378  	"BPL",		LTYPE5,	ABPL,
   379  	"BVS",		LTYPE5,	ABVS,
   380  	"BVC",		LTYPE5,	ABVC,
   381  	"BHI",		LTYPE5,	ABHI,
   382  	"BLS",		LTYPE5,	ABLS,
   383  	"BGE",		LTYPE5,	ABGE,
   384  	"BLT",		LTYPE5,	ABLT,
   385  	"BGT",		LTYPE5,	ABGT,
   386  	"BLE",		LTYPE5,	ABLE,
   387  	"BCASE",	LTYPE5,	ABCASE,
   388  
   389  	"SWI",		LTYPE6, ASWI,
   390  
   391  	"CMP",		LTYPE7,	ACMP,
   392  	"TST",		LTYPE7,	ATST,
   393  	"TEQ",		LTYPE7,	ATEQ,
   394  	"CMN",		LTYPE7,	ACMN,
   395  
   396  	"MOVM",		LTYPE8, AMOVM,
   397  
   398  	"SWPBU",	LTYPE9, ASWPBU,
   399  	"SWPW",		LTYPE9, ASWPW,
   400  
   401  	"RET",		LTYPEA, ARET,
   402  	"RFE",		LTYPEA, ARFE,
   403  
   404  	"TEXT",		LTYPEB, ATEXT,
   405  	"GLOBL",	LTYPEB, AGLOBL,
   406  	"DATA",		LTYPEC, ADATA,
   407  	"CASE",		LTYPED, ACASE,
   408  	"END",		LTYPEE, AEND,
   409  	"WORD",		LTYPEH, AWORD,
   410  	"NOP",		LTYPEI, ANOP,
   411  
   412  	"MCR",		LTYPEJ, 0,
   413  	"MRC",		LTYPEJ, 1,
   414  
   415  	"PLD",		LTYPEPLD, APLD,
   416  	"UNDEF",	LTYPEE,	AUNDEF,
   417  	"CLZ",		LTYPE2, ACLZ,
   418  
   419  	"MULWT",	LTYPE1, AMULWT,
   420  	"MULWB",	LTYPE1, AMULWB,
   421  	"MULAWT",	LTYPEN, AMULAWT,
   422  	"MULAWB",	LTYPEN, AMULAWB,
   423  
   424  	"USEFIELD",	LTYPEN, AUSEFIELD,
   425  	"PCDATA",	LTYPEPC,	APCDATA,
   426  	"FUNCDATA",	LTYPEF,	AFUNCDATA,
   427  
   428  	0
   429  };
   430  
   431  void
   432  cinit(void)
   433  {
   434  	Sym *s;
   435  	int i;
   436  
   437  	nullgen.type = D_NONE;
   438  	nullgen.name = D_NONE;
   439  	nullgen.reg = NREG;
   440  
   441  	nerrors = 0;
   442  	iostack = I;
   443  	iofree = I;
   444  	peekc = IGN;
   445  	nhunk = 0;
   446  	for(i=0; i<NHASH; i++)
   447  		hash[i] = S;
   448  	for(i=0; itab[i].name; i++) {
   449  		s = slookup(itab[i].name);
   450  		s->type = itab[i].type;
   451  		s->value = itab[i].value;
   452  	}
   453  }
   454  
   455  void
   456  syminit(Sym *s)
   457  {
   458  
   459  	s->type = LNAME;
   460  	s->value = 0;
   461  }
   462  
   463  int
   464  isreg(Addr *g)
   465  {
   466  
   467  	USED(g);
   468  	return 1;
   469  }
   470  
   471  void
   472  cclean(void)
   473  {
   474  	outcode(AEND, Always, &nullgen, NREG, &nullgen);
   475  }
   476  
   477  static int bcode[] =
   478  {
   479  	ABEQ,
   480  	ABNE,
   481  	ABCS,
   482  	ABCC,
   483  	ABMI,
   484  	ABPL,
   485  	ABVS,
   486  	ABVC,
   487  	ABHI,
   488  	ABLS,
   489  	ABGE,
   490  	ABLT,
   491  	ABGT,
   492  	ABLE,
   493  	AB,
   494  	ANOP,
   495  };
   496  
   497  static Prog *lastpc;
   498  
   499  void
   500  outcode(int a, int scond, Addr *g1, int reg, Addr *g2)
   501  {
   502  	Prog *p;
   503  	Plist *pl;
   504  
   505  	/* hack to make B.NE etc. work: turn it into the corresponding conditional */
   506  	if(a == AB){
   507  		a = bcode[scond&0xf];
   508  		scond = (scond & ~0xf) | Always;
   509  	}
   510  
   511  	if(pass == 1)
   512  		goto out;
   513  	
   514  	p = malloc(sizeof *p);
   515  	memset(p, 0, sizeof *p);
   516  	p->as = a;
   517  	p->lineno = stmtline;
   518  	p->scond = scond;
   519  	p->from = *g1;
   520  	p->reg = reg;
   521  	p->to = *g2;
   522  	p->pc = pc;
   523  
   524  	if(lastpc == nil) {
   525  		pl = linknewplist(ctxt);
   526  		pl->firstpc = p;
   527  	} else
   528  		lastpc->link = p;
   529  	lastpc = p;	
   530  
   531  out:
   532  	if(a != AGLOBL && a != ADATA)
   533  		pc++;
   534  }
   535  
   536  #include "../cc/lexbody"
   537  #include "../cc/macbody"