github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/cmd/5c/mul.c (about)

     1  // Inferno utils/5c/mul.c
     2  // http://code.google.com/p/inferno-os/source/browse/utils/5c/mul.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  
    32  #include "gc.h"
    33  
    34  /*
    35   * code sequences for multiply by constant.
    36   * [a-l][0-3]
    37   *	lsl	$(A-'a'),r0,r1
    38   * [+][0-7]
    39   *	add	r0,r1,r2
    40   * [-][0-7]
    41   *	sub	r0,r1,r2
    42   */
    43  
    44  static  int	maxmulops = 3;	/* max # of ops to replace mul with */
    45  static	int	multabp;
    46  static	int32	mulval;
    47  static	char*	mulcp;
    48  static	int32	valmax;
    49  static	int	shmax;
    50  
    51  static int	docode(char *hp, char *cp, int r0, int r1);
    52  static int	gen1(int len);
    53  static int	gen2(int len, int32 r1);
    54  static int	gen3(int len, int32 r0, int32 r1, int flag);
    55  enum
    56  {
    57  	SR1	= 1<<0,		/* r1 has been shifted */
    58  	SR0	= 1<<1,		/* r0 has been shifted */
    59  	UR1	= 1<<2,		/* r1 has not been used */
    60  	UR0	= 1<<3,		/* r0 has not been used */
    61  };
    62  
    63  Multab*
    64  mulcon0(int32 v)
    65  {
    66  	int a1, a2, g;
    67  	Multab *m, *m1;
    68  	char hint[10];
    69  
    70  	if(v < 0)
    71  		v = -v;
    72  
    73  	/*
    74  	 * look in cache
    75  	 */
    76  	m = multab;
    77  	for(g=0; g<nelem(multab); g++) {
    78  		if(m->val == v) {
    79  			if(m->code[0] == 0)
    80  				return 0;
    81  			return m;
    82  		}
    83  		m++;
    84  	}
    85  
    86  	/*
    87  	 * select a spot in cache to overwrite
    88  	 */
    89  	multabp++;
    90  	if(multabp < 0 || multabp >= nelem(multab))
    91  		multabp = 0;
    92  	m = multab+multabp;
    93  	m->val = v;
    94  	mulval = v;
    95  
    96  	/*
    97  	 * look in execption hint table
    98  	 */
    99  	a1 = 0;
   100  	a2 = hintabsize;
   101  	for(;;) {
   102  		if(a1 >= a2)
   103  			goto no;
   104  		g = (a2 + a1)/2;
   105  		if(v < hintab[g].val) {
   106  			a2 = g;
   107  			continue;
   108  		}
   109  		if(v > hintab[g].val) {
   110  			a1 = g+1;
   111  			continue;
   112  		}
   113  		break;
   114  	}
   115  
   116  	if(docode(hintab[g].hint, m->code, 1, 0))
   117  		return m;
   118  	print("multiply table failure %d\n", v);
   119  	m->code[0] = 0;
   120  	return 0;
   121  
   122  no:
   123  	/*
   124  	 * try to search
   125  	 */
   126  	hint[0] = 0;
   127  	for(g=1; g<=maxmulops; g++) {
   128  		if(g >= maxmulops && v >= 65535)
   129  			break;
   130  		mulcp = hint+g;
   131  		*mulcp = 0;
   132  		if(gen1(g)) {
   133  			if(docode(hint, m->code, 1, 0))
   134  				return m;
   135  			print("multiply table failure %d\n", v);
   136  			break;
   137  		}
   138  	}
   139  
   140  	/*
   141  	 * try a recur followed by a shift
   142  	 */
   143  	g = 0;
   144  	while(!(v & 1)) {
   145  		g++;
   146  		v >>= 1;
   147  	}
   148  	if(g) {
   149  		m1 = mulcon0(v);
   150  		if(m1) {
   151  			strcpy(m->code, m1->code);
   152  			sprint(strchr(m->code, 0), "%c0", g+'a');
   153  			return m;
   154  		}
   155  	}
   156  	m->code[0] = 0;
   157  	return 0;
   158  }
   159  
   160  static int
   161  docode(char *hp, char *cp, int r0, int r1)
   162  {
   163  	int c, i;
   164  
   165  	c = *hp++;
   166  	*cp = c;
   167  	cp += 2;
   168  	switch(c) {
   169  	default:
   170  		c -= 'a';
   171  		if(c < 1 || c >= 30)
   172  			break;
   173  		for(i=0; i<4; i++) {
   174  			switch(i) {
   175  			case 0:
   176  				if(docode(hp, cp, r0<<c, r1))
   177  					goto out;
   178  				break;
   179  			case 1:
   180  				if(docode(hp, cp, r1<<c, r1))
   181  					goto out;
   182  				break;
   183  			case 2:
   184  				if(docode(hp, cp, r0, r0<<c))
   185  					goto out;
   186  				break;
   187  			case 3:
   188  				if(docode(hp, cp, r0, r1<<c))
   189  					goto out;
   190  				break;
   191  			}
   192  		}
   193  		break;
   194  
   195  	case '+':
   196  		for(i=0; i<8; i++) {
   197  			cp[-1] = i+'0';
   198  			switch(i) {
   199  			case 1:
   200  				if(docode(hp, cp, r0+r1, r1))
   201  					goto out;
   202  				break;
   203  			case 5:
   204  				if(docode(hp, cp, r0, r0+r1))
   205  					goto out;
   206  				break;
   207  			}
   208  		}
   209  		break;
   210  
   211  	case '-':
   212  		for(i=0; i<8; i++) {
   213  			cp[-1] = i+'0';
   214  			switch(i) {
   215  			case 1:
   216  				if(docode(hp, cp, r0-r1, r1))
   217  					goto out;
   218  				break;
   219  			case 2:
   220  				if(docode(hp, cp, r1-r0, r1))
   221  					goto out;
   222  				break;
   223  			case 5:
   224  				if(docode(hp, cp, r0, r0-r1))
   225  					goto out;
   226  				break;
   227  			case 6:
   228  				if(docode(hp, cp, r0, r1-r0))
   229  					goto out;
   230  				break;
   231  			}
   232  		}
   233  		break;
   234  
   235  	case 0:
   236  		if(r0 == mulval)
   237  			return 1;
   238  	}
   239  	return 0;
   240  
   241  out:
   242  	cp[-1] = i+'0';
   243  	return 1;
   244  }
   245  
   246  static int
   247  gen1(int len)
   248  {
   249  	int i;
   250  
   251  	for(shmax=1; shmax<30; shmax++) {
   252  		valmax = 1<<shmax;
   253  		if(valmax >= mulval)
   254  			break;
   255  	}
   256  	if(mulval == 1)
   257  		return 1;
   258  
   259  	len--;
   260  	for(i=1; i<=shmax; i++)
   261  		if(gen2(len, 1<<i)) {
   262  			*--mulcp = 'a'+i;
   263  			return 1;
   264  		}
   265  	return 0;
   266  }
   267  
   268  static int
   269  gen2(int len, int32 r1)
   270  {
   271  	int i;
   272  
   273  	if(len <= 0) {
   274  		if(r1 == mulval)
   275  			return 1;
   276  		return 0;
   277  	}
   278  
   279  	len--;
   280  	if(len == 0)
   281  		goto calcr0;
   282  
   283  	if(gen3(len, r1, r1+1, UR1)) {
   284  		i = '+';
   285  		goto out;
   286  	}
   287  	if(gen3(len, r1-1, r1, UR0)) {
   288  		i = '-';
   289  		goto out;
   290  	}
   291  	if(gen3(len, 1, r1+1, UR1)) {
   292  		i = '+';
   293  		goto out;
   294  	}
   295  	if(gen3(len, 1, r1-1, UR1)) {
   296  		i = '-';
   297  		goto out;
   298  	}
   299  
   300  	return 0;
   301  
   302  calcr0:
   303  	if(mulval == r1+1) {
   304  		i = '+';
   305  		goto out;
   306  	}
   307  	if(mulval == r1-1) {
   308  		i = '-';
   309  		goto out;
   310  	}
   311  	return 0;
   312  
   313  out:
   314  	*--mulcp = i;
   315  	return 1;
   316  }
   317  
   318  static int
   319  gen3(int len, int32 r0, int32 r1, int flag)
   320  {
   321  	int i, f1, f2;
   322  	int32 x;
   323  
   324  	if(r0 <= 0 ||
   325  	   r0 >= r1 ||
   326  	   r1 > valmax)
   327  		return 0;
   328  
   329  	len--;
   330  	if(len == 0)
   331  		goto calcr0;
   332  
   333  	if(!(flag & UR1)) {
   334  		f1 = UR1|SR1;
   335  		for(i=1; i<=shmax; i++) {
   336  			x = r0<<i;
   337  			if(x > valmax)
   338  				break;
   339  			if(gen3(len, r0, x, f1)) {
   340  				i += 'a';
   341  				goto out;
   342  			}
   343  		}
   344  	}
   345  
   346  	if(!(flag & UR0)) {
   347  		f1 = UR1|SR1;
   348  		for(i=1; i<=shmax; i++) {
   349  			x = r1<<i;
   350  			if(x > valmax)
   351  				break;
   352  			if(gen3(len, r1, x, f1)) {
   353  				i += 'a';
   354  				goto out;
   355  			}
   356  		}
   357  	}
   358  
   359  	if(!(flag & SR1)) {
   360  		f1 = UR1|SR1|(flag&UR0);
   361  		for(i=1; i<=shmax; i++) {
   362  			x = r1<<i;
   363  			if(x > valmax)
   364  				break;
   365  			if(gen3(len, r0, x, f1)) {
   366  				i += 'a';
   367  				goto out;
   368  			}
   369  		}
   370  	}
   371  
   372  	if(!(flag & SR0)) {
   373  		f1 = UR0|SR0|(flag&(SR1|UR1));
   374  
   375  		f2 = UR1|SR1;
   376  		if(flag & UR1)
   377  			f2 |= UR0;
   378  		if(flag & SR1)
   379  			f2 |= SR0;
   380  
   381  		for(i=1; i<=shmax; i++) {
   382  			x = r0<<i;
   383  			if(x > valmax)
   384  				break;
   385  			if(x > r1) {
   386  				if(gen3(len, r1, x, f2)) {
   387  					i += 'a';
   388  					goto out;
   389  				}
   390  			} else
   391  				if(gen3(len, x, r1, f1)) {
   392  					i += 'a';
   393  					goto out;
   394  				}
   395  		}
   396  	}
   397  
   398  	x = r1+r0;
   399  	if(gen3(len, r0, x, UR1)) {
   400  		i = '+';
   401  		goto out;
   402  	}
   403  
   404  	if(gen3(len, r1, x, UR1)) {
   405  		i = '+';
   406  		goto out;
   407  	}
   408  
   409  	x = r1-r0;
   410  	if(gen3(len, x, r1, UR0)) {
   411  		i = '-';
   412  		goto out;
   413  	}
   414  
   415  	if(x > r0) {
   416  		if(gen3(len, r0, x, UR1)) {
   417  			i = '-';
   418  			goto out;
   419  		}
   420  	} else
   421  		if(gen3(len, x, r0, UR0)) {
   422  			i = '-';
   423  			goto out;
   424  		}
   425  
   426  	return 0;
   427  
   428  calcr0:
   429  	f1 = flag & (UR0|UR1);
   430  	if(f1 == UR1) {
   431  		for(i=1; i<=shmax; i++) {
   432  			x = r1<<i;
   433  			if(x >= mulval) {
   434  				if(x == mulval) {
   435  					i += 'a';
   436  					goto out;
   437  				}
   438  				break;
   439  			}
   440  		}
   441  	}
   442  
   443  	if(mulval == r1+r0) {
   444  		i = '+';
   445  		goto out;
   446  	}
   447  	if(mulval == r1-r0) {
   448  		i = '-';
   449  		goto out;
   450  	}
   451  
   452  	return 0;
   453  
   454  out:
   455  	*--mulcp = i;
   456  	return 1;
   457  }
   458  
   459  /*
   460   * hint table has numbers that
   461   * the search algorithm fails on.
   462   * <1000:
   463   *	all numbers
   464   * <5000:
   465   * 	÷ by 5
   466   * <10000:
   467   * 	÷ by 50
   468   * <65536:
   469   * 	÷ by 250
   470   */
   471  Hintab	hintab[] =
   472  {
   473  	683,	"b++d+e+",
   474  	687,	"b+e++e-",
   475  	691,	"b++d+e+",
   476  	731,	"b++d+e+",
   477  	811,	"b++d+i+",
   478  	821,	"b++e+e+",
   479  	843,	"b+d++e+",
   480  	851,	"b+f-+e-",
   481  	853,	"b++e+e+",
   482  	877,	"c++++g-",
   483  	933,	"b+c++g-",
   484  	981,	"c-+e-d+",
   485  	1375,	"b+c+b+h-",
   486  	1675,	"d+b++h+",
   487  	2425,	"c++f-e+",
   488  	2675,	"c+d++f-",
   489  	2750,	"b+d-b+h-",
   490  	2775,	"c-+g-e-",
   491  	3125,	"b++e+g+",
   492  	3275,	"b+c+g+e+",
   493  	3350,	"c++++i+",
   494  	3475,	"c-+e-f-",
   495  	3525,	"c-+d+g-",
   496  	3625,	"c-+e-j+",
   497  	3675,	"b+d+d+e+",
   498  	3725,	"b+d-+h+",
   499  	3925,	"b+d+f-d-",
   500  	4275,	"b+g++e+",
   501  	4325,	"b+h-+d+",
   502  	4425,	"b+b+g-j-",
   503  	4525,	"b+d-d+f+",
   504  	4675,	"c++d-g+",
   505  	4775,	"b+d+b+g-",
   506  	4825,	"c+c-+i-",
   507  	4850,	"c++++i-",
   508  	4925,	"b++e-g-",
   509  	4975,	"c+f++e-",
   510  	5500,	"b+g-c+d+",
   511  	6700,	"d+b++i+",
   512  	9700,	"d++++j-",
   513  	11000,	"b+f-c-h-",
   514  	11750,	"b+d+g+j-",
   515  	12500,	"b+c+e-k+",
   516  	13250,	"b+d+e-f+",
   517  	13750,	"b+h-c-d+",
   518  	14250,	"b+g-c+e-",
   519  	14500,	"c+f+j-d-",
   520  	14750,	"d-g--f+",
   521  	16750,	"b+e-d-n+",
   522  	17750,	"c+h-b+e+",
   523  	18250,	"d+b+h-d+",
   524  	18750,	"b+g-++f+",
   525  	19250,	"b+e+b+h+",
   526  	19750,	"b++h--f-",
   527  	20250,	"b+e-l-c+",
   528  	20750,	"c++bi+e-",
   529  	21250,	"b+i+l+c+",
   530  	22000,	"b+e+d-g-",
   531  	22250,	"b+d-h+k-",
   532  	22750,	"b+d-e-g+",
   533  	23250,	"b+c+h+e-",
   534  	23500,	"b+g-c-g-",
   535  	23750,	"b+g-b+h-",
   536  	24250,	"c++g+m-",
   537  	24750,	"b+e+e+j-",
   538  	25000,	"b++dh+g+",
   539  	25250,	"b+e+d-g-",
   540  	25750,	"b+e+b+j+",
   541  	26250,	"b+h+c+e+",
   542  	26500,	"b+h+c+g+",
   543  	26750,	"b+d+e+g-",
   544  	27250,	"b+e+e+f+",
   545  	27500,	"c-i-c-d+",
   546  	27750,	"b+bd++j+",
   547  	28250,	"d-d-++i-",
   548  	28500,	"c+c-h-e-",
   549  	29000,	"b+g-d-f+",
   550  	29500,	"c+h+++e-",
   551  	29750,	"b+g+f-c+",
   552  	30250,	"b+f-g-c+",
   553  	33500,	"c-f-d-n+",
   554  	33750,	"b+d-b+j-",
   555  	34250,	"c+e+++i+",
   556  	35250,	"e+b+d+k+",
   557  	35500,	"c+e+d-g-",
   558  	35750,	"c+i-++e+",
   559  	36250,	"b+bh-d+e+",
   560  	36500,	"c+c-h-e-",
   561  	36750,	"d+e--i+",
   562  	37250,	"b+g+g+b+",
   563  	37500,	"b+h-b+f+",
   564  	37750,	"c+be++j-",
   565  	38500,	"b+e+b+i+",
   566  	38750,	"d+i-b+d+",
   567  	39250,	"b+g-l-+d+",
   568  	39500,	"b+g-c+g-",
   569  	39750,	"b+bh-c+f-",
   570  	40250,	"b+bf+d+g-",
   571  	40500,	"b+g-c+g+",
   572  	40750,	"c+b+i-e+",
   573  	41250,	"d++bf+h+",
   574  	41500,	"b+j+c+d-",
   575  	41750,	"c+f+b+h-",
   576  	42500,	"c+h++g+",
   577  	42750,	"b+g+d-f-",
   578  	43250,	"b+l-e+d-",
   579  	43750,	"c+bd+h+f-",
   580  	44000,	"b+f+g-d-",
   581  	44250,	"b+d-g--f+",
   582  	44500,	"c+e+c+h+",
   583  	44750,	"b+e+d-h-",
   584  	45250,	"b++g+j-g+",
   585  	45500,	"c+d+e-g+",
   586  	45750,	"b+d-h-e-",
   587  	46250,	"c+bd++j+",
   588  	46500,	"b+d-c-j-",
   589  	46750,	"e-e-b+g-",
   590  	47000,	"b+c+d-j-",
   591  	47250,	"b+e+e-g-",
   592  	47500,	"b+g-c-h-",
   593  	47750,	"b+f-c+h-",
   594  	48250,	"d--h+n-",
   595  	48500,	"b+c-g+m-",
   596  	48750,	"b+e+e-g+",
   597  	49500,	"c-f+e+j-",
   598  	49750,	"c+c+g++f-",
   599  	50000,	"b+e+e+k+",
   600  	50250,	"b++i++g+",
   601  	50500,	"c+g+f-i+",
   602  	50750,	"b+e+d+k-",
   603  	51500,	"b+i+c-f+",
   604  	51750,	"b+bd+g-e-",
   605  	52250,	"b+d+g-j+",
   606  	52500,	"c+c+f+g+",
   607  	52750,	"b+c+e+i+",
   608  	53000,	"b+i+c+g+",
   609  	53500,	"c+g+g-n+",
   610  	53750,	"b+j+d-c+",
   611  	54250,	"b+d-g-j-",
   612  	54500,	"c-f+e+f+",
   613  	54750,	"b+f-+c+g+",
   614  	55000,	"b+g-d-g-",
   615  	55250,	"b+e+e+g+",
   616  	55500,	"b+cd++j+",
   617  	55750,	"b+bh-d-f-",
   618  	56250,	"c+d-b+j-",
   619  	56500,	"c+d+c+i+",
   620  	56750,	"b+e+d++h-",
   621  	57000,	"b+d+g-f+",
   622  	57250,	"b+f-m+d-",
   623  	57750,	"b+i+c+e-",
   624  	58000,	"b+e+d+h+",
   625  	58250,	"c+b+g+g+",
   626  	58750,	"d-e-j--e+",
   627  	59000,	"d-i-+e+",
   628  	59250,	"e--h-m+",
   629  	59500,	"c+c-h+f-",
   630  	59750,	"b+bh-e+i-",
   631  	60250,	"b+bh-e-e-",
   632  	60500,	"c+c-g-g-",
   633  	60750,	"b+e-l-e-",
   634  	61250,	"b+g-g-c+",
   635  	61750,	"b+g-c+g+",
   636  	62250,	"f--+c-i-",
   637  	62750,	"e+f--+g+",
   638  	64750,	"b+f+d+p-",
   639  };
   640  int	hintabsize	= nelem(hintab);