Merge pull request #131 from davidgiven/dtrg-mips
Add an mcg-based MIPS code generator.
This commit is contained in:
		
						commit
						8fd3e1f5ce
					
				
					 101 changed files with 5450 additions and 781 deletions
				
			
		
							
								
								
									
										3
									
								
								README
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								README
									
										
									
									
									
								
							|  | @ -33,6 +33,7 @@ pc86          produces bootable floppy disk images for 8086 PCs | |||
| linux386      produces ELF executables for PC Linux systems | ||||
| linux68k      produces ELF executables for m68020 Linux systems | ||||
| linuxppc      produces ELF executables for PowerPC Linux systems | ||||
| linuxmips     produces ELF executables for little-endian MIPS32r2 Linux systems | ||||
| cpm           produces i80 CP/M .COM files | ||||
| rpi           produces Raspberry Pi GPU binaries | ||||
| pdpv7         produces PDP/11 V7 Unix binaries | ||||
|  | @ -194,4 +195,4 @@ Please enjoy. | |||
| 
 | ||||
| David Given (davidgiven on Github) | ||||
| dg@cowlark.com | ||||
| 2016-11-26 | ||||
| 2018-09-18 | ||||
|  |  | |||
|  | @ -10,9 +10,9 @@ vars.plats = { | |||
| 	"linux386", | ||||
| 	"linux68k", | ||||
| 	"linuxppc", | ||||
| 	"linuxmips", | ||||
| 	"osx386", | ||||
| 	"osxppc", | ||||
| --	--"qemuppc", | ||||
| 	"pc86", | ||||
| 	"rpi", | ||||
| 	"pdpv7", | ||||
|  | @ -22,7 +22,7 @@ vars.plats_with_tests = { | |||
| 	"linux68k", | ||||
| 	"linux386", | ||||
| 	"linuxppc", | ||||
| --	--"qemuppc", | ||||
| 	"linuxmips", | ||||
| 	"pc86", | ||||
| } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										203
									
								
								h/con_float
									
										
									
									
									
								
							
							
						
						
									
										203
									
								
								h/con_float
									
										
									
									
									
								
							|  | @ -20,9 +20,9 @@ | |||
| 
 | ||||
|    Unfortunately, the IEEE standard does not define the byte-order. | ||||
|    depends on the #defines | ||||
| 	FL_MSL_AT_LOW_ADDRESS	1 if most significant long is at low address | ||||
| 	FL_MSW_AT_LOW_ADDRESS	1 if most significant word is at low address | ||||
| 	FL_MSB_AT_LOW_ADDRESS	1 if most significant byte is at low address | ||||
|     FL_MSL_AT_LOW_ADDRESS	1 if most significant long is at low address | ||||
|     FL_MSW_AT_LOW_ADDRESS	1 if most significant word is at low address | ||||
|     FL_MSB_AT_LOW_ADDRESS	1 if most significant byte is at low address | ||||
| */ | ||||
| #ifdef IEEEFLOAT | ||||
| #define USE_FLT | ||||
|  | @ -37,47 +37,57 @@ | |||
| #define FL_MSB_AT_LOW_ADDRESS 0 | ||||
| #endif | ||||
| 
 | ||||
| #define I0 ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \ | ||||
| 		+ (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) | ||||
| #define I1 ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \ | ||||
| 		+ (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) | ||||
| #define I2 ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \ | ||||
| 		+ (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) | ||||
| #define I3 ((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \ | ||||
| 		+ (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) | ||||
| #define I4 ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \ | ||||
| 		+ (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) | ||||
| #define I5 ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2) \ | ||||
| 		+ (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) | ||||
| #define I6 ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \ | ||||
| 		+ (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) | ||||
| #define I7 ((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0) \ | ||||
| 		+ (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) | ||||
| #define I0                                                                                         \ | ||||
| 	((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2)                             \ | ||||
| 	 + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) | ||||
| #define I1                                                                                         \ | ||||
| 	((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2)                             \ | ||||
| 	 + (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) | ||||
| #define I2                                                                                         \ | ||||
| 	((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0)                             \ | ||||
| 	 + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) | ||||
| #define I3                                                                                         \ | ||||
| 	((FL_MSL_AT_LOW_ADDRESS ? 0 : 4) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0)                             \ | ||||
| 	 + (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) | ||||
| #define I4                                                                                         \ | ||||
| 	((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2)                             \ | ||||
| 	 + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) | ||||
| #define I5                                                                                         \ | ||||
| 	((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 0 : 2)                             \ | ||||
| 	 + (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) | ||||
| #define I6                                                                                         \ | ||||
| 	((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0)                             \ | ||||
| 	 + (FL_MSB_AT_LOW_ADDRESS ? 0 : 1)) | ||||
| #define I7                                                                                         \ | ||||
| 	((FL_MSL_AT_LOW_ADDRESS ? 4 : 0) + (FL_MSW_AT_LOW_ADDRESS ? 2 : 0)                             \ | ||||
| 	 + (FL_MSB_AT_LOW_ADDRESS ? 1 : 0)) | ||||
| 
 | ||||
| #ifndef USE_FLT | ||||
| static int | ||||
| float_cst(str, sz, buf) | ||||
| 	char *str, *buf; | ||||
| 	int sz; | ||||
| static int float_cst(str, sz, buf) char *str, *buf; | ||||
| int sz; | ||||
| { | ||||
| 	int i; | ||||
| 	char *p; | ||||
| 	char* p; | ||||
| 	float fl; | ||||
| 	double f; | ||||
| 	double atof(); | ||||
| 
 | ||||
| 	if (sz!= 4 && sz!= 8)	{ | ||||
| 	if (sz != 4 && sz != 8) | ||||
| 	{ | ||||
| 		return 1; | ||||
| 	} | ||||
| 	f = atof(str); | ||||
| 	if (sz == 4) { | ||||
| 	if (sz == 4) | ||||
| 	{ | ||||
| 		fl = f; | ||||
| 		p = (char *) &fl; | ||||
| 		p = (char*)&fl; | ||||
| 	} | ||||
| 	else { | ||||
| 		p = (char *) &f; | ||||
| 	else | ||||
| 	{ | ||||
| 		p = (char*)&f; | ||||
| 	} | ||||
| 	for (i = sz; i; i--) { | ||||
| 	for (i = sz; i; i--) | ||||
| 	{ | ||||
| 		*buf++ = *p++; | ||||
| 	} | ||||
| 	return 0; | ||||
|  | @ -87,89 +97,105 @@ float_cst(str, sz, buf) | |||
| #include <ctype.h> | ||||
| #include <flt_arith.h> | ||||
| 
 | ||||
| int | ||||
| float_cst(str, sz, buf) | ||||
| 	char *str, *buf; | ||||
| 	int sz; | ||||
| int float_cst(str, sz, buf) char *str, *buf; | ||||
| int sz; | ||||
| { | ||||
| 	int overflow = 0; | ||||
| 	flt_arith e; | ||||
| 
 | ||||
| 	if (sz!= 4 && sz!= 8)	{ | ||||
| 	if (sz != 4 && sz != 8) | ||||
| 	{ | ||||
| 		return 1; | ||||
| 	} | ||||
| 	flt_str2flt(str, &e); | ||||
| #ifdef IEEEFLOAT | ||||
| 	if (sz == 4) { | ||||
| 	if (sz == 4) | ||||
| 	{ | ||||
| #endif | ||||
| #ifdef PDPFLOAT | ||||
| 		e.flt_exp += 129; | ||||
| #else | ||||
| 		e.flt_exp += 127; | ||||
| 	e.flt_exp += 127; | ||||
| #endif | ||||
| 		if (e.flt_mantissa.flt_h_32 == 0) e.flt_exp = 0; | ||||
| 		if (e.flt_mantissa.flt_h_32 == 0) | ||||
| 			e.flt_exp = 0; | ||||
| #ifdef IEEEFLOAT | ||||
| 		if (e.flt_mantissa.flt_h_32 & 0x80) { | ||||
| 		if (e.flt_mantissa.flt_h_32 & 0x80) | ||||
| 		{ | ||||
| 			/* rounding */ | ||||
| 			if ((e.flt_mantissa.flt_h_32 & 0xffffff00) == 0xffffff00) { | ||||
| 			if ((e.flt_mantissa.flt_h_32 & 0xffffff00) == 0xffffff00) | ||||
| 			{ | ||||
| 				e.flt_exp++; | ||||
| 				e.flt_mantissa.flt_h_32 = 0x80000000; | ||||
| 			} | ||||
| 			else { | ||||
| 			else | ||||
| 			{ | ||||
| 				e.flt_mantissa.flt_h_32 += 0x80; | ||||
| 			} | ||||
| 		} | ||||
| 		if (e.flt_exp >= 255) { | ||||
| 		if (e.flt_exp >= 255) | ||||
| 		{ | ||||
| 			overflow = 1; | ||||
| 			e.flt_exp = 255; | ||||
| 			e.flt_mantissa.flt_h_32 = e.flt_mantissa.flt_l_32 = 0; | ||||
| 		} | ||||
| 		if (e.flt_exp <= 0) { | ||||
| 		if (e.flt_exp <= 0) | ||||
| 		{ | ||||
| 			flt_b64_sft(&(e.flt_mantissa), 1); | ||||
| 			if (e.flt_exp < 0) { | ||||
| 			if (e.flt_exp < 0) | ||||
| 			{ | ||||
| 				flt_b64_sft(&(e.flt_mantissa), -e.flt_exp); | ||||
| 				e.flt_exp = 0; | ||||
| 			} | ||||
| 		} | ||||
| #endif | ||||
| #ifndef IEEEFLOAT | ||||
| 		if (sz == 4 && (e.flt_mantissa.flt_h_32 & 0x80)) { | ||||
| 		if (sz == 4 && (e.flt_mantissa.flt_h_32 & 0x80)) | ||||
| 		{ | ||||
| 			/* rounding */ | ||||
| 			if ((e.flt_mantissa.flt_h_32 & 0xffffff00) == 0xffffff00) { | ||||
| 			if ((e.flt_mantissa.flt_h_32 & 0xffffff00) == 0xffffff00) | ||||
| 			{ | ||||
| 				e.flt_exp++; | ||||
| 				e.flt_mantissa.flt_h_32 = 0x80000000; | ||||
| 			} | ||||
| 			else { | ||||
| 			else | ||||
| 			{ | ||||
| 				e.flt_mantissa.flt_h_32 += 0x80; | ||||
| 			} | ||||
| 		} | ||||
| 		if (sz == 8 && (e.flt_mantissa.flt_l_32 & 0x80)) { | ||||
| 		if (sz == 8 && (e.flt_mantissa.flt_l_32 & 0x80)) | ||||
| 		{ | ||||
| 			/* rounding */ | ||||
| 			if ((e.flt_mantissa.flt_l_32 & 0xffffff00) == 0xffffff00) { | ||||
| 			if ((e.flt_mantissa.flt_l_32 & 0xffffff00) == 0xffffff00) | ||||
| 			{ | ||||
| 				e.flt_mantissa.flt_l_32 = 0; | ||||
| 				if (e.flt_mantissa.flt_h_32 == 0xffffffff) { | ||||
| 				if (e.flt_mantissa.flt_h_32 == 0xffffffff) | ||||
| 				{ | ||||
| 					e.flt_exp++; | ||||
| 					e.flt_mantissa.flt_h_32 = 0x80000000; | ||||
| 				} | ||||
| 				else e.flt_mantissa.flt_h_32++; | ||||
| 				else | ||||
| 					e.flt_mantissa.flt_h_32++; | ||||
| 			} | ||||
| 			else { | ||||
| 			else | ||||
| 			{ | ||||
| 				e.flt_mantissa.flt_l_32 += 0x80; | ||||
| 			} | ||||
| 		} | ||||
| 		if (e.flt_exp > 255) { | ||||
| 		if (e.flt_exp > 255) | ||||
| 		{ | ||||
| 			overflow = 1; | ||||
| 			e.flt_exp = 255; | ||||
| 			e.flt_mantissa.flt_h_32 = e.flt_mantissa.flt_l_32 = 0xffffffff; | ||||
| 		} | ||||
| #endif | ||||
| 		buf[I0] = (e.flt_sign << 7) | (e.flt_exp >> 1); | ||||
| 		buf[I1] = ((e.flt_exp&1) << 7) | | ||||
| 				((e.flt_mantissa.flt_h_32 & 0x7fffffff) >> 24); | ||||
| 		buf[I1] = ((e.flt_exp & 1) << 7) | ((e.flt_mantissa.flt_h_32 & 0x7fffffff) >> 24); | ||||
| 		buf[I2] = e.flt_mantissa.flt_h_32 >> 16; | ||||
| 		buf[I3] = e.flt_mantissa.flt_h_32 >> 8; | ||||
| #ifndef IEEEFLOAT | ||||
| 		if (sz == 8) { | ||||
| 		if (sz == 8) | ||||
| 		{ | ||||
| 			buf[I4] = e.flt_mantissa.flt_h_32; | ||||
| 			buf[I5] = e.flt_mantissa.flt_l_32 >> 24; | ||||
| 			buf[I6] = e.flt_mantissa.flt_l_32 >> 16; | ||||
|  | @ -181,37 +207,47 @@ float_cst(str, sz, buf) | |||
| 			flt_b64_sft(&(e.flt_mantissa), -24); | ||||
| #ifdef IEEEFLOAT | ||||
| 	} | ||||
| 	else { | ||||
| 	else | ||||
| 	{ | ||||
| 		e.flt_exp += 1023; | ||||
| 		if (e.flt_mantissa.flt_h_32 == 0) e.flt_exp = 0; | ||||
| 		if (e.flt_mantissa.flt_l_32 & 0x400) { | ||||
| 		if (e.flt_mantissa.flt_h_32 == 0) | ||||
| 			e.flt_exp = 0; | ||||
| 		if (e.flt_mantissa.flt_l_32 & 0x400) | ||||
| 		{ | ||||
| 			/* rounding */ | ||||
| 			if ((e.flt_mantissa.flt_l_32 & 0xfffff800) == 0xfffff800) { | ||||
| 			if ((e.flt_mantissa.flt_l_32 & 0xfffff800) == 0xfffff800) | ||||
| 			{ | ||||
| 				e.flt_mantissa.flt_l_32 = 0; | ||||
| 				if (e.flt_mantissa.flt_h_32 == 0xffffffff) { | ||||
| 				if (e.flt_mantissa.flt_h_32 == 0xffffffff) | ||||
| 				{ | ||||
| 					e.flt_exp++; | ||||
| 					e.flt_mantissa.flt_h_32 = 0x80000000; | ||||
| 				} | ||||
| 				else e.flt_mantissa.flt_h_32++; | ||||
| 				else | ||||
| 					e.flt_mantissa.flt_h_32++; | ||||
| 			} | ||||
| 			else { | ||||
| 			else | ||||
| 			{ | ||||
| 				e.flt_mantissa.flt_l_32 += 0x400; | ||||
| 			} | ||||
| 		} | ||||
| 		if (e.flt_exp >= 2047) { | ||||
| 		if (e.flt_exp >= 2047) | ||||
| 		{ | ||||
| 			overflow = 1; | ||||
| 			e.flt_exp = 2047; | ||||
| 			e.flt_mantissa.flt_h_32 = e.flt_mantissa.flt_l_32 = 0; | ||||
| 		} | ||||
| 		if (e.flt_exp <= 0) { | ||||
| 		if (e.flt_exp <= 0) | ||||
| 		{ | ||||
| 			flt_b64_sft(&(e.flt_mantissa), 1); | ||||
| 			if (e.flt_exp < 0) { | ||||
| 			if (e.flt_exp < 0) | ||||
| 			{ | ||||
| 				flt_b64_sft(&(e.flt_mantissa), -e.flt_exp); | ||||
| 				e.flt_exp = 0; | ||||
| 			} | ||||
| 		} | ||||
| 		buf[I0] = (e.flt_sign << 7) | (e.flt_exp >> 4); | ||||
| 		buf[I1] = ((e.flt_exp & 017)<< 4) | ((e.flt_mantissa.flt_h_32 >> 27) & 017); | ||||
| 		buf[I1] = ((e.flt_exp & 017) << 4) | ((e.flt_mantissa.flt_h_32 >> 27) & 017); | ||||
| 		buf[I2] = e.flt_mantissa.flt_h_32 >> 19; | ||||
| 		buf[I3] = e.flt_mantissa.flt_h_32 >> 11; | ||||
| 		buf[I4] = e.flt_mantissa.flt_h_32 >> 3; | ||||
|  | @ -221,15 +257,17 @@ float_cst(str, sz, buf) | |||
| 		flt_b64_sft(&(e.flt_mantissa), -53); | ||||
| 	} | ||||
| #endif | ||||
| #if ! FL_MSL_AT_LOW_ADDRESS | ||||
| 	if (sz == 4) { | ||||
| #if !FL_MSL_AT_LOW_ADDRESS | ||||
| 	if (sz == 4) | ||||
| 	{ | ||||
| 		buf[I4] = buf[I0]; | ||||
| 		buf[I5] = buf[I1]; | ||||
| 		buf[I6] = buf[I2]; | ||||
| 		buf[I7] = buf[I3]; | ||||
| 	} | ||||
| #endif | ||||
| 	if (overflow) { | ||||
| 	if (overflow) | ||||
| 	{ | ||||
| 		return 2; | ||||
| 	} | ||||
| 	return 0; | ||||
|  | @ -237,22 +275,25 @@ float_cst(str, sz, buf) | |||
| #endif /* USE_FLT */ | ||||
| 
 | ||||
| #ifdef CODE_GENERATOR | ||||
| con_float() | ||||
| void con_float(void) | ||||
| { | ||||
| 	char buf[8]; | ||||
| 	int rval = float_cst(str, (int)argval, buf); | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (rval == 1) { | ||||
| 		fprintf(stderr,"float constant size = %d\n",(int)argval); | ||||
| 	if (rval == 1) | ||||
| 	{ | ||||
| 		fprintf(stderr, "float constant size = %d\n", (int)argval); | ||||
| 		fatal("bad fcon size"); | ||||
| 	} | ||||
| 	fprintf(codefile,"!float %s sz %d\n", str, (int)argval); | ||||
| 	if (rval == 2) { | ||||
| 	fprintf(codefile, "!float %s sz %d\n", str, (int)argval); | ||||
| 	if (rval == 2) | ||||
| 	{ | ||||
| 		fprintf(stderr, "Warning: overflow in floating point constant %s\n", str); | ||||
| 	} | ||||
| 	fprintf(codefile, ".data1 0%o", buf[0] & 0377); | ||||
| 	for (i = 1; i < (int)argval; i++) { | ||||
| 	for (i = 1; i < (int)argval; i++) | ||||
| 	{ | ||||
| 		fprintf(codefile, ",0%o", buf[i] & 0377); | ||||
| 	} | ||||
| 	putc('\n', codefile); | ||||
|  | @ -260,19 +301,19 @@ con_float() | |||
| #endif /* CODE_GENERATOR */ | ||||
| 
 | ||||
| #ifdef CODE_EXPANDER | ||||
| con_float(str, argval) | ||||
| 	char *str; | ||||
| 	arith argval; | ||||
| void con_float(const char* str, arith argval) | ||||
| { | ||||
| 	char buf[8]; | ||||
| 	int rval = float_cst(str, (int)argval, buf); | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (rval == 1) { | ||||
| 	if (rval == 1) | ||||
| 	{ | ||||
| 		argval = 8; | ||||
| 		rval = float_cst(str, 8, buf); | ||||
| 	} | ||||
| 	for (i = 0; i < (int)argval; i++) { | ||||
| 	for (i = 0; i < (int)argval; i++) | ||||
| 	{ | ||||
| 		gen1(buf[i]); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										5
									
								
								h/out.h
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								h/out.h
									
										
									
									
									
								
							|  | @ -67,7 +67,10 @@ struct outname { | |||
| #define RELO4        3          /* 4 bytes */ | ||||
| #define RELOPPC      4          /* PowerPC 26-bit address */ | ||||
| #define RELOPPC_LIS  5          /* PowerPC lis */ | ||||
| #define RELOVC4      6  /* VideoCore IV address in 32-bit instruction */ | ||||
| #define RELOVC4      6          /* VideoCore IV address in 32-bit instruction */ | ||||
| #define RELOMIPS     7          /* MIPS */ | ||||
| #define RELO2HI      8          /* high 2 bytes of word */ | ||||
| #define RELO2HISAD   9          /* high 2 bytes of word, sign adjusted */ | ||||
| 
 | ||||
| #define RELPC	0x2000			/* pc relative */ | ||||
| #define RELBR	0x4000			/* High order byte lowest address. */ | ||||
|  |  | |||
|  | @ -199,19 +199,26 @@ int lab; | |||
| 
 | ||||
| genreturns() | ||||
| { | ||||
| 	int count; | ||||
| 	int nr; | ||||
| 
 | ||||
| 	nr= genlabel(); | ||||
|         C_df_dnam("returns"); | ||||
|         C_rom_ilb((label) nr); | ||||
|         C_rom_cst((arith)1); | ||||
|         C_rom_cst((arith) (gosubcnt-1)); | ||||
|         C_rom_cst((arith) (gosubcnt-2)); | ||||
| 
 | ||||
| 	count = 0; | ||||
| 	while ( gosubhead) | ||||
| 	{ | ||||
|                 C_rom_ilb((label) gosubhead->emlabel); | ||||
| 		gosubhead= gosubhead->nextlist; | ||||
| 		count++; | ||||
| 	} | ||||
| 
 | ||||
| 	if (count != (gosubcnt-1)) | ||||
| 		error("gosub count table mismatch"); | ||||
| 
 | ||||
|         C_df_ilb((label) nr); | ||||
|         C_loc((arith) 1); | ||||
|         C_cal("error"); | ||||
|  |  | |||
							
								
								
									
										6
									
								
								mach/mips/as/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								mach/mips/as/build.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| normalrule { | ||||
|     name = "astables", | ||||
|     outleaves = {"definitions.y", "tokens.y", "rules.y"}, | ||||
|     ins = {"./mktables.lua", "./instructions.dat"}, | ||||
|     commands = {"$(LUA) %{ins[1]} %{outs} < %{ins[2]}"} | ||||
| } | ||||
							
								
								
									
										275
									
								
								mach/mips/as/instructions.dat
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										275
									
								
								mach/mips/as/instructions.dat
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,275 @@ | |||
| # Syntax: | ||||
| # <thing---->: a field occupying so many bits. | ||||
| # T: a field occupying one bit. | ||||
| # Undefined bits end up as 0. | ||||
| # | ||||
| # This is intended to be compatible with MIPS release 5, integer instructions | ||||
| # only. It's based on the MIPS32 Instruction Set v5.04 manual (available from | ||||
| # https://www.mips.com/products/architectures/mips32-2/). | ||||
| 
 | ||||
| # Useful pseudoops. | ||||
| 
 | ||||
| # or RD, RS, zero | ||||
| 000000<RS->00000<RD->00000100101 "mov" RD=gpr ',' RS=gpr | ||||
| 
 | ||||
| # Condition code tokens; these have to be defined here because .f overlaps with | ||||
| # a format code. | ||||
| 
 | ||||
| %token .f | ||||
| %token .un | ||||
| %token .eq | ||||
| %token .ueq | ||||
| %token .olt | ||||
| %token .ult | ||||
| %token .ole | ||||
| %token .ule | ||||
| %token .sf | ||||
| %token .ngle | ||||
| %token .seq | ||||
| %token .ngl | ||||
| %token .lt | ||||
| %token .nge | ||||
| %token .le | ||||
| %token .ngt | ||||
| 
 | ||||
| # Core ALU instructions. | ||||
| 
 | ||||
| 000000<RS-><RT-><RD->00000100000 "add" RD=gpr ',' RS=gpr ',' RT=gpr | ||||
| 001000<RS-><RT-><IMM-----------> "addi" RT=gpr ',' RS=gpr ',' IMM=e16 | ||||
| 001001<RS-><RT-><IMM-----------> "addiu" RT=gpr ',' RS=gpr ',' IMM=e16 | ||||
| 000000<RS-><RT-><RD->00000100001 "addu" RD=gpr ',' RS=gpr ',' RT=gpr | ||||
| 000000<RS-><RT-><RD->00000100100 "and" RD=gpr ',' RS=gpr ',' RT=gpr | ||||
| 001100<RS-><RT-><IMM-----------> "andi" RT=gpr ',' RS=gpr ',' IMM=e16 | ||||
| 0001000000000000<OFF-----------> "b" OFF=offset16 | ||||
| 0000010000010001<OFF-----------> "bal" OFF=offset16 | ||||
| 000100<RS-><RT-><OFF-----------> "beq" RS=gpr ',' RT=gpr ',' OFF=offset16 | ||||
| 010100<RS-><RT-><OFF-----------> "beql" RS=gpr ',' RT=gpr ',' OFF=offset16 | ||||
| 000001<RS->00001<OFF-----------> "bgez" RS=gpr ',' OFF=offset16 | ||||
| 000001<RS->10001<OFF-----------> "bgezal" RS=gpr ',' OFF=offset16 | ||||
| 000001<RS->10011<OFF-----------> "bgezall" RS=gpr ',' OFF=offset16 | ||||
| 000001<RS->00011<OFF-----------> "bgezl" RS=gpr ',' OFF=offset16 | ||||
| 000111<RS->00000<OFF-----------> "bgtz" RS=gpr ',' OFF=offset16 | ||||
| 010111<RS->00000<OFF-----------> "bgtzl" RS=gpr ',' OFF=offset16 | ||||
| 000110<RS->00000<OFF-----------> "blez" RS=gpr ',' OFF=offset16 | ||||
| 010110<RS->00000<OFF-----------> "blezl" RS=gpr ',' OFF=offset16 | ||||
| 000001<RS->00000<OFF-----------> "bltz" RS=gpr ',' OFF=offset16 | ||||
| 000001<RS->10000<OFF-----------> "bltzal" RS=gpr ',' OFF=offset16 | ||||
| 000001<RS->10010<OFF-----------> "bltzall" RS=gpr ',' OFF=offset16 | ||||
| 000001<RS->00010<OFF-----------> "bltzl" RS=gpr ',' OFF=offset16 | ||||
| 000101<RS-><RT-><OFF-----------> "bne" RS=gpr ',' RT=gpr ',' OFF=offset16 | ||||
| 010101<RS-><RT-><OFF-----------> "bnel" RS=gpr ',' RT=gpr ',' OFF=offset16 | ||||
| 101111<RS-><OP-><OFF-----------> "cache" OP=u5 ',' OFF=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><OP-><OFF---->0011011 "cachee" OP=u5 ',' OFF=e9 '(' RS=gpr ')' | ||||
| 011100<RS-><RT-><RD->00000100001 "clo" RD=RT=gpr ',' RS=gpr | ||||
| 011100<RS-><RT-><RD->00000100000 "clz" RD=RT=gpr ',' RS=gpr | ||||
| 01000010000000000000000000011111 "deret" | ||||
| 01000001011<RT->0110000000000000 "di" RT=gpr | ||||
| 01000001011000000110000000000000 "di" | ||||
| 000000<RS-><RT->0000000000011010 "div" RS=gpr ',' RT=gpr | ||||
| 000000<RS-><RT->0000000000011011 "divu" RS=gpr ',' RT=gpr | ||||
| 00000000000000000000000011000000 "ehb" | ||||
| 01000001011<RT->0110000000100000 "ei" RT=gpr | ||||
| 01000001011000000110000000100000 "ei" | ||||
| 011111<RS-><RT-><MSBLSB-->000000 "ext" RT=gpr ',' RS=gpr ',' extmsblsb | ||||
| 011111<RS-><RT-><MSBLSB-->000100 "ins" RT=gpr ',' RS=gpr ',' insmsblsb | ||||
| 000010<ABS---------------------> "j" ABS=abs26 | ||||
| 000011<ABS---------------------> "jal" ABS=abs26 | ||||
| 000000<RS->00000<RD->00000001001 "jalr" RD=gpr ',' RS=gpr | ||||
| 000000<RS->000001111100000001001 "jalr" RS=gpr | ||||
| 000000<RS->00000<RD->10000001001 "jalr.hb" RD=gpr ',' RS=gpr | ||||
| 000000<RS->000001111110000001001 "jalr.hb" RS=gpr | ||||
| 011101<ABS---------------------> "jalx" ABS=abs26 | ||||
| 000000<RS->000000000000000001000 "jr" RS=gpr | ||||
| 000000<RS->000000000010000001000 "jr.hb" RS=gpr | ||||
| 100000<RS-><RT-><IMM-----------> "lb" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0101100 "lbe" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 100100<RS-><RT-><IMM-----------> "lbu" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0101000 "lbue" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 100001<RS-><RT-><IMM-----------> "lh" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0101101 "lhe" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 100101<RS-><RT-><IMM-----------> "lhu" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0101001 "lhue" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 110000<RS-><RT-><IMM-----------> "ll" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0101110 "lle" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 00111100000<RT-><IMM-----------> "lui" RT=gpr ',' IMM=e16 | ||||
| 100011<RS-><RT-><IMM-----------> "lw" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0101111 "lwe" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 100010<RS-><RT-><IMM-----------> "lwl" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0011001 "lwle" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 100110<RS-><RT-><IMM-----------> "lwr" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0011010 "lwre" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 011100<RS-><RT->0000000000000000 "madd" RS=gpr ',' RT=gpr | ||||
| 011100<RS-><RT->0000000000000001 "maddu" RS=gpr ',' RT=gpr | ||||
| 0000000000000000<RD->00000010000 "mfhi" RD=gpr | ||||
| 0000000000000000<RD->00000010010 "mflo" RD=gpr | ||||
| 000000<RS-><RT-><RD->00000001011 "movn" RD=gpr ',' RS=gpr ',' RT=gpr | ||||
| 000000<RS-><RT-><RD->00000001010 "movz" RD=gpr ',' RS=gpr ',' RT=gpr | ||||
| 011100<RS-><RT->0000000000000100 "msub" RS=gpr ',' RT=gpr | ||||
| 011100<RS-><RT->0000000000000101 "msubu" RS=gpr ',' RT=gpr | ||||
| 000000<RS->000000000000000010001 "mthi" RS=gpr | ||||
| 000000<RS->000000000000000010011 "mtlo" RS=gpr | ||||
| 011100<RS-><RT-><RD->00000000010 "mul" RD=gpr ',' RS=gpr ',' RT=gpr | ||||
| 000000<RS-><RT->0000000000011000 "mult" RS=gpr ',' RT=gpr | ||||
| 000000<RS-><RT->0000000000000001 "multu" RS=gpr ',' RT=gpr | ||||
| 00000000000000000000000000000000 "nop" | ||||
| 000000<RS-><RT-><RD->00000100111 "nor" RD=gpr ',' RS=gpr ',' RT=gpr | ||||
| 000000<RS-><RT-><RD->00000100101 "or" RD=gpr ',' RS=gpr ',' RT=gpr | ||||
| 001101<RS-><RT-><IMM-----------> "ori" RT=gpr ',' RS=gpr ',' IMM=e16 | ||||
| 00000000000000000000000101000000 "pause" | ||||
| 110011<RS-><H--><IMM-----------> "pref" H=u5 ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><H--><IMM---->0100011 "prefe" H=u5 ',' IMM=e9 '(' RS=gpr ')' | ||||
| 010011<RS-><RT-><H-->00000001111 "prefx" H=u5 ',' RT=gpr '(' RS=gpr ')' | ||||
| 01111100000<RT-><RD->00000111011 "rdhwr" RT=gpr ',' RD=gpr | ||||
| 01000001010<RT-><RD->00000000000 "rdpgpr" RD=gpr ',' RT=gpr | ||||
| 00000000001<RT-><RD-><SA->000010 "rotr" RD=gpr ',' RT=gpr ',' SA=u5 | ||||
| 000000<RS-><RT-><RD->00001000110 "rotrv" RD=gpr ',' RT=gpr ',' RS=gpr | ||||
| 101000<RS-><RT-><IMM-----------> "sb" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0011100 "sbe" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 111000<RS-><RT-><IMM-----------> "sc" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0011110 "sce" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 011100<CODE-------------->111111 "sdbbp" CODE=u20 | ||||
| 01111100000<RT-><RD->10000100000 "seb" RD=gpr ',' RT=gpr | ||||
| 01111100000<RT-><RD->11000100000 "seh" RD=gpr ',' RT=gpr | ||||
| 101001<RS-><RT-><IMM-----------> "sh" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0011101 "she" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 00000000000<RT-><RD-><SA->000000 "sll" RD=gpr ',' RT=gpr ',' SA=u5 | ||||
| 000000<RS-><RT-><RD->00000000100 "sllv" RD=gpr ',' RT=gpr ',' RS=gpr | ||||
| 000000<RS-><RT-><RD->00000101010 "slt" RD=gpr ',' RS=gpr ',' RT=gpr | ||||
| 001010<RS-><RT-><IMM-----------> "slti" RT=gpr ',' RS=gpr ',' IMM=e16 | ||||
| 001011<RS-><RT-><IMM-----------> "sltiu" RT=gpr ',' RS=gpr ',' IMM=e16 | ||||
| 000000<RS-><RT-><RD->00000101011 "sltu" RD=gpr ',' RS=gpr ',' RT=gpr | ||||
| 00000000000<RT-><RD-><SA->000011 "sra" RD=gpr ',' RT=gpr ',' SA=u5 | ||||
| 000000<RS-><RT-><RD->00000000111 "srav" RD=gpr ',' RT=gpr ',' RS=gpr | ||||
| 00000000000<RT-><RD-><SA->000010 "srl" RD=gpr ',' RT=gpr ',' SA=u5 | ||||
| 000000<RS-><RT-><RD->00000000110 "srlv" RD=gpr ',' RT=gpr ',' RS=gpr | ||||
| 00000000000000000000000001000000 "ssnop" | ||||
| 000000<RS-><RT-><RD->00000100010 "sub" RD=gpr ',' RS=gpr ',' RT=gpr | ||||
| 000000<RS-><RT-><RD->00000100011 "subu" RD=gpr ',' RS=gpr ',' RT=gpr | ||||
| 101011<RS-><RT-><IMM-----------> "sw" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0011111 "swe" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 101010<RS-><RT-><IMM-----------> "swl" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0010001 "swle" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 101110<RS-><RT-><IMM-----------> "swr" RT=gpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 011111<RS-><RT-><IMM---->0100010 "swre" RT=gpr ',' IMM=e9 '(' RS=gpr ')' | ||||
| 000001<RS->11111<IMM-----------> "synci" IMM=e16 '(' RS=gpr ')' | ||||
| 000000<CODE-------------->001100 "syscall" CODE=u20 | ||||
| 000000<RS-><RT->0000000000110100 "teq" RS=gpr ',' RT=gpr | ||||
| 000001<RS->01100<IMM-----------> "teqi" RS=gpr ',' IMM=e16 | ||||
| 000000<RS-><RT->0000000000110000 "tge" RS=gpr ',' RT=gpr | ||||
| 000001<RS->01000<IMM-----------> "tgei" RS=gpr ',' IMM=e16 | ||||
| 000001<RS->01001<IMM-----------> "tgeiu" RS=gpr ',' IMM=e16 | ||||
| 000000<RS-><RT->0000000000110001 "tgeu" RS=gpr ',' RT=gpr | ||||
| 01000010000000000000000000000011 "tlbinv" | ||||
| 01000010000000000000000000000100 "tlbinvf" | ||||
| 01000010000000000000000000001000 "tlbp" | ||||
| 01000010000000000000000000000001 "tlbr" | ||||
| 01000010000000000000000000000010 "tlbwi" | ||||
| 01000010000000000000000000000110 "tlbwr" | ||||
| 000000<RS-><RT->0000000000110010 "tlt" RS=gpr ',' RT=gpr | ||||
| 000001<RS->01010<IMM-----------> "tlti" RS=gpr ',' IMM=e16 | ||||
| 000001<RS->01011<IMM-----------> "tltiu" RS=gpr ',' IMM=e16 | ||||
| 000000<RS-><RT->0000000000110011 "tltu" RS=gpr ',' RT=gpr | ||||
| 000000<RS-><RT->0000000000110110 "tne" RS=gpr ',' RT=gpr | ||||
| 000001<RS->01110<IMM-----------> "tnei" RS=gpr ',' IMM=e16 | ||||
| 01000010000000000000000000100000 "wait" | ||||
| 01000001110<RT-><RD->00000000000 "wrpgpr" RD=gpr ',' RT=gpr | ||||
| 01111100000<RT-><RD->00010100000 "wsbh" RD=gpr ',' RT=gpr | ||||
| 000000<RS-><RT-><RD->00000100110 "xor" RD=gpr ',' RS=gpr ',' RT=gpr | ||||
| 001110<RS-><RT-><IMM-----------> "xori" RT=gpr ',' RS=gpr ',' IMM=e16 | ||||
| 
 | ||||
| # FPU instructions. | ||||
| 
 | ||||
| 010001<F-->00000<FS-><FD->000101 "abs" F=fmt FD=fpr ',' FS=fpr | ||||
| 010001<F--><FT-><FS-><FD->000000 "add" F=fmt FD=fpr ',' FS=fpr ',' FT=fpr | ||||
| 010011<RS-><FT-><FS-><FD->011110 "alnv" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr ',' RS=gpr | ||||
| 010001<F--><FT-><FS-><C>0011<CO> "c" CO=fcond F=fmt C=u3 ',' FS=fpr ',' FT=fpr | ||||
| 010001<F-->00000<FS-><FD->001010 "ceil" ".l" F=fmt FD=fpr ',' FS=fpr | ||||
| 010001<F-->00000<FS-><FD->001110 "ceil" ".w" F=fmt FD=fpr ',' FS=fpr | ||||
| 01000100010<RT-><FS->00000000000 "cfc1" RT=gpr ',' FS=fpr | ||||
| 01000100110<RT-><FS->00000000000 "ctc1" RT=gpr ',' FS=fpr | ||||
| 010001<F-->00000<FS-><FD->100001 "cvt" ".d" F=fmt FD=fpr ',' FS=fpr | ||||
| 010001<F-->00000<FS-><FD->100101 "cvt" ".l" F=fmt FD=fpr ',' FS=fpr | ||||
| 01000110000<FT-><FS-><FD->100110 "cvt" ".ps" ".s" FD=fpr ',' FS=fpr ',' FT=fpr | ||||
| 010001<F-->00000<FS-><FD->100000 "cvt" ".s" F=fmt FD=fpr ',' FS=fpr | ||||
| 0100011011000000<FS-><FD->101000 "cvt" ".s" ".pl" FS=fpr ',' FD=fpr | ||||
| 0100011011000000<FS-><FD->100000 "cvt" ".s" ".pu" FS=fpr ',' FD=fpr | ||||
| 010001<F-->00000<FS-><FD->100100 "cvt" ".w" F=fmt FD=fpr ',' FS=fpr | ||||
| 010001<F--><FT-><FS-><FD->000011 "div" F=fmt FD=fpr ',' FS=fpr ',' FT=fpr | ||||
| 010001<F-->00000<FS-><FD->001011 "floor" ".l" F=fmt FD=fpr ',' FS=fpr | ||||
| 010001<F-->00000<FS-><FD->001111 "floor" ".w" F=fmt FD=fpr ',' FS=fpr | ||||
| 110101<RS-><FT-><IMM-----------> "ldc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 010011<RS-><RT->00000<FD->000001 "ldxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' | ||||
| 010011<RS-><RT->00000<FD->000101 "luxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' | ||||
| 110001<RS-><FT-><IMM-----------> "lwc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 010011<RS-><RT->00000<FD->000000 "lwxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' | ||||
| 010011<FR-><FT-><FS-><FD->100<F> "madd" F=fmt3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr | ||||
| 01000100000<RT-><FS->00000000000 "mfc1" RT=gpr ',' FS=fpr | ||||
| 01000100011<RT-><FS->00000000000 "mfhc1" RT=gpr ',' FS=fpr | ||||
| 010001<F-->00000<FS-><FD->000110 "mov" F=fmt FD=fpr ',' FS=fpr | ||||
| 000000<RS-><C>00<RD->00000000001 "movf" RD=gpr ',' RS=gpr ',' C=u3 | ||||
| 010001<F--><C>00<FS-><FD->010001 "movf" F=fmt FD=fpr ',' FS=fpr ',' C=u3 | ||||
| 010001<F--><RT-><FS-><FD->010011 "movn" F=fmt FD=fpr ',' FS=fpr ',' RT=gpr | ||||
| 000000<RS-><C>01<RD->00000000001 "movt" RD=gpr ',' RS=gpr ',' C=u3 | ||||
| 010001<F--><C>01<FS-><FD->010001 "movt" F=fmt FD=fpr ',' FS=fpr ',' C=u3 | ||||
| 010001<F--><RT-><FS-><FD->010010 "movz" F=fmt FD=fpr ',' FS=fpr ',' RT=gpr | ||||
| 010011<FR-><FT-><FS-><FD->101<F> "msub" F=fmt3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr | ||||
| 01000100100<RT-><FS->00000000000 "mtc1" RT=gpr ',' FS=fpr | ||||
| 01000100111<RT-><FS->00000000000 "mthc1" RT=gpr ',' FS=fpr | ||||
| 010001<F--><FT-><FS-><FD->000010 "mul" F=fmt FD=fpr ',' FS=fpr ',' FT=fpr | ||||
| 010001<F-->00000<FS-><FD->000111 "neg" F=fmt FD=fpr ',' FS=fpr | ||||
| 010011<FR-><FT-><FS-><FD->110<F> "nmadd" F=fmt3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr | ||||
| 010011<FR-><FT-><FS-><FD->111<F> "nmsub" F=fmt3 FD=fpr ',' FR=fpr ',' FS=fpr ',' FT=fpr | ||||
| 01000110110<FT-><FS-><FD->101100 "pll" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr | ||||
| 01000110110<FT-><FS-><FD->101101 "plu" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr | ||||
| 01000110110<FT-><FS-><FD->101110 "pul" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr | ||||
| 01000110110<FT-><FS-><FD->101111 "puu" ".ps" FD=fpr ',' FS=fpr ',' FT=fpr | ||||
| 010001<F-->00000<FS-><FD->010101 "recip." F=fmt FD=fpr ',' FS=fpr | ||||
| 010001<F-->00000<FS-><FD->001000 "round" ".l" F=fmt FD=fpr ',' FS=fpr | ||||
| 010001<F-->00000<FS-><FD->001100 "round" ".w" F=fmt FD=fpr ',' FS=fpr | ||||
| 010001<F-->00000<FS-><FD->010110 "rsqrt" F=fmt FD=fpr ',' FS=fpr | ||||
| 111101<RS-><FT-><IMM-----------> "sdc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 010011<RS-><RT->00000<FD->001001 "sdxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' | ||||
| 010001<F-->00000<FS-><FD->000100 "sqrt" F=fmt FD=fpr ',' FS=fpr | ||||
| 010001<F--><FT-><FS-><FD->000001 "sub" F=fmt FD=fpr ',' FS=fpr ',' FT=fpr | ||||
| 010011<RS-><RT->00000<FD->001101 "suxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' | ||||
| 111001<RS-><FT-><IMM-----------> "swc1" FT=fpr ',' IMM=e16 '(' RS=gpr ')' | ||||
| 010011<RS-><RT->00000<FD->001000 "swxc1" FD=fpr ',' RT=gpr '(' RS=gpr ')' | ||||
| 010001<F-->00000<FS-><FD->001001 "trunc" ".l" F=fmt FD=fpr ',' FS=fpr | ||||
| 010001<F-->00000<FS-><FD->001101 "trunc" ".w" F=fmt FD=fpr ',' FS=fpr | ||||
| 
 | ||||
| # Generic coprocessor instructions. | ||||
| 
 | ||||
| 01000101000<C>00<OFF-----------> "bc1f" C=u3 ',' OFF=offset16 | ||||
| 0100010100000000<OFF-----------> "bc1f" OFF=offset16 | ||||
| 01000101000<C>10<OFF-----------> "bc1fl" C=u3 ',' OFF=offset16 | ||||
| 0100010100000010<OFF-----------> "bc1fl" OFF=offset16 | ||||
| 01000101000<C>01<OFF-----------> "bc1t" C=u3 ',' OFF=offset16 | ||||
| 0100010100000001<OFF-----------> "bc1t" OFF=offset16 | ||||
| 01000101000<C>11<OFF-----------> "bc1tl" C=u3 ',' OFF=offset16 | ||||
| 0100010100000011<OFF-----------> "bc1tl" OFF=offset16 | ||||
| 01001001000<C>00<OFF-----------> "bc2f" C=u3 ',' OFF=offset16 | ||||
| 0100100100000000<OFF-----------> "bc2f" OFF=offset16 | ||||
| 01001001000<C>10<OFF-----------> "bc2fl" C=u3 ',' OFF=offset16 | ||||
| 0100100100000010<OFF-----------> "bc2fl" OFF=offset16 | ||||
| 01001001000<C>01<OFF-----------> "bc2t" C=u3 ',' OFF=offset16 | ||||
| 0100100100000001<OFF-----------> "bc2t" OFF=offset16 | ||||
| 01001001000<C>11<OFF-----------> "bc2tl" C=u3 ',' OFF=offset16 | ||||
| 0100100100000011<OFF-----------> "bc2tl" OFF=offset16 | ||||
| 01001000010<RT-><IMM-----------> "cfc2" RT=gpr ',' IMM=u16 | ||||
| 01001000110<RT-><IMM-----------> "ctc2" RT=gpr ',' IMM=u16 | ||||
| 0100101<FUN--------------------> "cop2" FUN=u25 | ||||
| 110110<RS-><RT-><IMM-----------> "ldc2" RT=u5 ',' IMM=e16 '(' RS=gpr ')' | ||||
| 110010<RS-><RT-><IMM-----------> "lwc2" RT=u5 ',' IMM=e16 '(' RS=gpr ')' | ||||
| 01000000000<RT-><RD->00000000<S> "mfc0" RT=gpr ',' RD=u5 ',' S=u3 | ||||
| 01001000000<RT-><IMM-----------> "mfc2" RT=gpr ',' IMM=u16 | ||||
| 01000000010<RT-><RD->00000000<S> "mfhc0" RT=gpr ',' RD=u5 ',' S=u3 | ||||
| 01001000011<RT-><IMM-----------> "mfhc2" RT=gpr ',' IMM=u16 | ||||
| 01000000100<RT-><RD->00000000<S> "mtc0" RT=gpr ',' RD=u5 ',' S=u3 | ||||
| 01001000100<RT-><IMM-----------> "mtc2" RT=gpr ',' IMM=u16 | ||||
| 01000000110<RT-><RD->00000000<S> "mthc0" RT=gpr ',' RD=u5 ',' S=u3 | ||||
| 01001000111<RT-><IMM-----------> "mthc2" RT=gpr ',' IMM=u16 | ||||
| 111110<RS-><RT-><IMM-----------> "sdc2" RT=u5 ',' IMM=e16 '(' RS=gpr ')' | ||||
| 111010<RS-><RT-><IMM-----------> "swc2" RT=u5 ',' IMM=e16 '(' RS=gpr ')' | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										29
									
								
								mach/mips/as/mach0.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								mach/mips/as/mach0.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | |||
| /*
 | ||||
|  * $Source$ | ||||
|  * $State$ | ||||
|  */ | ||||
| 
 | ||||
| #define	THREE_PASS          /* branch and offset optimization */ | ||||
| #define LISTING             /* enable listing facilities */ | ||||
| #define RELOCATION          /* generate relocatable code */ | ||||
| #define DEBUG 0 | ||||
| 
 | ||||
| #undef valu_t | ||||
| #define valu_t int32_t | ||||
| 
 | ||||
| #undef ADDR_T | ||||
| #define ADDR_T uint32_t | ||||
| 
 | ||||
| #undef word_t | ||||
| #define word_t uint32_t | ||||
| 
 | ||||
| #undef ALIGNWORD | ||||
| #define ALIGNWORD	4 | ||||
| 
 | ||||
| #undef ALIGNSECT | ||||
| #define ALIGNSECT	4 | ||||
| 
 | ||||
| #undef VALWIDTH | ||||
| #define VALWIDTH	8 | ||||
| 
 | ||||
| #define FIXUPFLAGS 0 | ||||
							
								
								
									
										3
									
								
								mach/mips/as/mach1.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								mach/mips/as/mach1.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | |||
| /*
 | ||||
|  * Do not #include anything here.  Do it in mach/proto/as/comm0.h | ||||
|  */ | ||||
							
								
								
									
										23
									
								
								mach/mips/as/mach2.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								mach/mips/as/mach2.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| %token <y_word> GPR | ||||
| %token <y_word> FPR | ||||
| %token <y_word> FCOND | ||||
| 
 | ||||
| %token <y_word> OP_LI | ||||
| 
 | ||||
| %token <y_word> HI16 | ||||
| %token <y_word> HA16 | ||||
| %token <y_word> LO16 | ||||
| 
 | ||||
| %type <y_word> gpr fpr | ||||
| %type <y_word> e16 e9 | ||||
| %type <y_word> u25 u20 u16 u5 u3 | ||||
| %type <y_word> abs26 offset16 | ||||
| 
 | ||||
| %type <y_word> fmt fmt3 | ||||
| %type <y_word> fcond | ||||
| 
 | ||||
| %type <y_word> extmsblsb insmsblsb | ||||
| %type <y_valu> extabsexp | ||||
| 
 | ||||
| #include "definitions.y" | ||||
| 
 | ||||
							
								
								
									
										83
									
								
								mach/mips/as/mach3.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								mach/mips/as/mach3.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,83 @@ | |||
| /* Integer registers */ | ||||
| 
 | ||||
| 0,     GPR,        0,          "r0", | ||||
| 0,     GPR,        0,          "zero", | ||||
| 0,     GPR,        1,          "r1", | ||||
| 0,     GPR,        1,          "at", | ||||
| 0,     GPR,        2,          "r2", | ||||
| 0,     GPR,        3,          "r3", | ||||
| 0,     GPR,        4,          "r4", | ||||
| 0,     GPR,        5,          "r5", | ||||
| 0,     GPR,        6,          "r6", | ||||
| 0,     GPR,        7,          "r7", | ||||
| 0,     GPR,        8,          "r8", | ||||
| 0,     GPR,        9,          "r9", | ||||
| 0,     GPR,        10,         "r10", | ||||
| 0,     GPR,        11,         "r11", | ||||
| 0,     GPR,        12,         "r12", | ||||
| 0,     GPR,        13,         "r13", | ||||
| 0,     GPR,        14,         "r14", | ||||
| 0,     GPR,        15,         "r15", | ||||
| 0,     GPR,        16,         "r16", | ||||
| 0,     GPR,        17,         "r17", | ||||
| 0,     GPR,        18,         "r18", | ||||
| 0,     GPR,        19,         "r19", | ||||
| 0,     GPR,        20,         "r20", | ||||
| 0,     GPR,        21,         "r21", | ||||
| 0,     GPR,        22,         "r22", | ||||
| 0,     GPR,        23,         "r23", | ||||
| 0,     GPR,        24,         "r24", | ||||
| 0,     GPR,        25,         "r25", | ||||
| 0,     GPR,        26,         "r26", | ||||
| 0,     GPR,        27,         "r27", | ||||
| 0,     GPR,        28,         "r28", | ||||
| 0,     GPR,        28,         "gp", | ||||
| 0,     GPR,        29,         "r29", | ||||
| 0,     GPR,        29,         "sp", | ||||
| 0,     GPR,        30,         "r30", | ||||
| 0,     GPR,        30,         "fp", | ||||
| 0,     GPR,        31,         "r31", | ||||
| 0,     GPR,        31,         "ra", | ||||
| 
 | ||||
| /* Floating-point registers */ | ||||
| 
 | ||||
| 0,     FPR,        0,          "f0", | ||||
| 0,     FPR,        1,          "f1", | ||||
| 0,     FPR,        2,          "f2", | ||||
| 0,     FPR,        3,          "f3", | ||||
| 0,     FPR,        4,          "f4", | ||||
| 0,     FPR,        5,          "f5", | ||||
| 0,     FPR,        6,          "f6", | ||||
| 0,     FPR,        7,          "f7", | ||||
| 0,     FPR,        8,          "f8", | ||||
| 0,     FPR,        9,          "f9", | ||||
| 0,     FPR,        10,         "f10", | ||||
| 0,     FPR,        11,         "f11", | ||||
| 0,     FPR,        12,         "f12", | ||||
| 0,     FPR,        13,         "f13", | ||||
| 0,     FPR,        14,         "f14", | ||||
| 0,     FPR,        15,         "f15", | ||||
| 0,     FPR,        16,         "f16", | ||||
| 0,     FPR,        17,         "f17", | ||||
| 0,     FPR,        18,         "f18", | ||||
| 0,     FPR,        19,         "f19", | ||||
| 0,     FPR,        20,         "f20", | ||||
| 0,     FPR,        21,         "f21", | ||||
| 0,     FPR,        22,         "f22", | ||||
| 0,     FPR,        23,         "f23", | ||||
| 0,     FPR,        24,         "f24", | ||||
| 0,     FPR,        25,         "f25", | ||||
| 0,     FPR,        26,         "f26", | ||||
| 0,     FPR,        27,         "f27", | ||||
| 0,     FPR,        28,         "f28", | ||||
| 0,     FPR,        29,         "f29", | ||||
| 0,     FPR,        30,         "f30", | ||||
| 0,     FPR,        31,         "f31", | ||||
| 
 | ||||
| 0,     OP_LI,      0,          "li", | ||||
| 0,     HI16,       0,         "hi16", | ||||
| 0,     HA16,       0,         "ha16", | ||||
| 0,     LO16,       0,         "lo16", | ||||
| 
 | ||||
| #include "tokens.y" | ||||
| 
 | ||||
							
								
								
									
										184
									
								
								mach/mips/as/mach4.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								mach/mips/as/mach4.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,184 @@ | |||
| #include "rules.y" | ||||
| 	| OP_LI GPR ',' extabsexp | ||||
| 	{ | ||||
| 		word_t reg = $2; | ||||
| 		uint32_t val = $4; | ||||
| 
 | ||||
| 		if (((int32_t)val >= -0x8000) && ((int32_t)val <= 0x7fff)) | ||||
| 			emit4(0x24000000 | (reg<<16) | (val & 0xffff)); /* addiu reg, zero, value */ | ||||
| 		else if (val <= 0xffff) | ||||
| 			emit4(0x34000000 | (reg<<16) | val); /* ori reg, zero, value */ | ||||
| 		else | ||||
| 		{ | ||||
| 			emit4(0x3c000000 | (reg<<16) | (val>>16)); /* lui reg, value */ | ||||
| 			emit4(0x34000000 | (reg<<16) | (reg<<21) | (val & 0xffff)); /* ori reg, reg, value */ | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| extabsexp | ||||
| 	: absexp | ||||
| 	| LO16 ASC_LPAR expr ASC_RPAR | ||||
| 	{ | ||||
| 		newrelo($3.typ, RELO2 | FIXUPFLAGS); | ||||
| 		$$ = $3.val; | ||||
| 	} | ||||
| 	| HI16 ASC_LPAR expr ASC_RPAR | ||||
| 	{ | ||||
| 		newrelo($3.typ, RELO2HI | FIXUPFLAGS); | ||||
| 		if ($3.val & 0xffff0000) | ||||
| 			fatal("relocation offset in hi16[] too big"); | ||||
| 		$$ = $3.val; | ||||
| 	} | ||||
| 	| HA16 ASC_LPAR expr ASC_RPAR | ||||
| 	{ | ||||
| 		newrelo($3.typ, RELO2HISAD | FIXUPFLAGS); | ||||
| 		if ($3.val & 0xffff0000) | ||||
| 			fatal("relocation offset in ha16[] too big"); | ||||
| 		$$ = $3.val; | ||||
| 	} | ||||
| 	; | ||||
| 
 | ||||
| gpr: GPR | ||||
| fpr: FPR | ||||
| 
 | ||||
| fmt3 | ||||
| 	: OP__DOT_S  { $$ = 0; } | ||||
| 	| OP__DOT_D  { $$ = 1; } | ||||
| 	| OP__DOT_W  { $$ = 4; } | ||||
| 	| OP__DOT_L  { $$ = 5; } | ||||
| 	| OP__DOT_PS { $$ = 6; } | ||||
| 	; | ||||
| 
 | ||||
| fmt | ||||
| 	: fmt3       { $$ = $1 + 16; } | ||||
|     ; | ||||
| 
 | ||||
| fcond | ||||
| 	: OP__DOT_F    { $$ = 0; } | ||||
| 	| OP__DOT_UN   { $$ = 1; } | ||||
| 	| OP__DOT_EQ   { $$ = 2; } | ||||
| 	| OP__DOT_UEQ  { $$ = 3; } | ||||
| 	| OP__DOT_OLT  { $$ = 4; } | ||||
| 	| OP__DOT_ULT  { $$ = 5; } | ||||
| 	| OP__DOT_OLE  { $$ = 6; } | ||||
| 	| OP__DOT_ULE  { $$ = 7; } | ||||
| 	| OP__DOT_SF   { $$ = 8; } | ||||
| 	| OP__DOT_NGLE { $$ = 9; } | ||||
| 	| OP__DOT_SEQ  { $$ = 10; } | ||||
| 	| OP__DOT_NGL  { $$ = 11; } | ||||
| 	| OP__DOT_LT   { $$ = 12; } | ||||
| 	| OP__DOT_NGE  { $$ = 13; } | ||||
| 	| OP__DOT_LE   { $$ = 14; } | ||||
| 	| OP__DOT_NGT  { $$ = 15; } | ||||
| 	; | ||||
| 
 | ||||
| e16 | ||||
| 	: extabsexp | ||||
| 	{ | ||||
| 		/* Allow signed or unsigned 16-bit values. */ | ||||
| 		if (($1 < -0x8000) || ($1 > 0xffff)) | ||||
| 			serror("16-bit signed value out of range"); | ||||
| 		$$ = (uint16_t) $1; | ||||
| 	} | ||||
| 	; | ||||
| 
 | ||||
| e9 | ||||
| 	: absexp | ||||
| 	{ | ||||
| 		/* Allow signed or unsigned 9-bit values. */ | ||||
| 		if (($1 < -0x100) || ($1 > 0x1ff)) | ||||
| 			serror("9-bit signed value out of range"); | ||||
| 		$$ = (uint16_t) $1; | ||||
| 	} | ||||
| 	; | ||||
| 
 | ||||
| u25 | ||||
| 	: absexp | ||||
| 	{ | ||||
| 		if (($1 < 0) || ($1 > 0x1ffffff)) | ||||
| 			serror("25-bit unsigned value out of range"); | ||||
| 		$$ = $1; | ||||
| 	} | ||||
| 	; | ||||
| 
 | ||||
| u20 | ||||
| 	: absexp | ||||
| 	{ | ||||
| 		if (($1 < 0) || ($1 > 0xfffff)) | ||||
| 			serror("20-bit unsigned value out of range"); | ||||
| 		$$ = $1; | ||||
| 	} | ||||
| 	; | ||||
| 
 | ||||
| u16 | ||||
| 	: extabsexp | ||||
| 	{ | ||||
| 		if (($1 < 0) || ($1 > 0xffff)) | ||||
| 			serror("16-bit unsigned value out of range"); | ||||
| 		$$ = $1; | ||||
| 	} | ||||
| 	; | ||||
| 
 | ||||
| u5 | ||||
| 	: absexp | ||||
| 	{ | ||||
| 		if (($1 < 0) || ($1 > 0x1f)) | ||||
| 			serror("5-bit unsigned value out of range"); | ||||
| 		$$ = $1; | ||||
| 	} | ||||
| 	; | ||||
| 
 | ||||
| u3 | ||||
| 	: absexp | ||||
| 	{ | ||||
| 		if (($1 < 0) || ($1 > 0x7)) | ||||
| 			serror("3-bit unsigned value out of range"); | ||||
| 		$$ = $1; | ||||
| 	} | ||||
| 	; | ||||
| 
 | ||||
| offset16 | ||||
| 	: expr | ||||
| 	{ | ||||
| 		int dist = $1.val - DOTVAL - 4; | ||||
| 		fit(fitx(dist, 18)); | ||||
| 
 | ||||
| 		if (dist & 0x3) | ||||
| 			serror("jump targets must be 4-aligned"); | ||||
| 
 | ||||
| 		newrelo($1.typ, RELOMIPS | RELPC | FIXUPFLAGS); | ||||
| 		$$ = (dist >> 2) & 0x0000ffff; | ||||
| 	} | ||||
| 	; | ||||
| 
 | ||||
| abs26 | ||||
| 	: expr | ||||
| 	{ | ||||
| 		int target = $1.val; | ||||
| 		fit(fitx(target, 28)); | ||||
| 
 | ||||
| 		if (target & 0x3) | ||||
| 			serror("jump targets must be 4-aligned"); | ||||
| 
 | ||||
| 		newrelo($1.typ, RELOMIPS | FIXUPFLAGS); | ||||
| 		$$ = (target >> 2) & 0x03ffffff; | ||||
| 	} | ||||
| 	; | ||||
| 
 | ||||
| extmsblsb | ||||
| 	: u5 ',' u5 | ||||
| 	{ | ||||
| 		int pos = $1; | ||||
| 		int size = $3; | ||||
| 		$$ = ((size-1) << 5) | pos; | ||||
| 	} | ||||
| 	; | ||||
| 
 | ||||
| insmsblsb | ||||
| 	: u5 ',' u5 | ||||
| 	{ | ||||
| 		int pos = $1; | ||||
| 		int size = $3; | ||||
| 		$$ = ((pos+size-1) << 5) | pos; | ||||
| 	} | ||||
| 	; | ||||
							
								
								
									
										0
									
								
								mach/mips/as/mach5.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								mach/mips/as/mach5.c
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										192
									
								
								mach/mips/as/mktables.lua
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										192
									
								
								mach/mips/as/mktables.lua
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,192 @@ | |||
| local args = {...} | ||||
| 
 | ||||
| local words = {} | ||||
| local insns = {} | ||||
| 
 | ||||
| local function addword(word) | ||||
| 	local w = words[word] | ||||
| 	if not w then | ||||
| 		w = word:upper() | ||||
| 		w = w:gsub("%.", "_DOT_") | ||||
|     	if not w:match("^[A-Z0-9_]*$") then | ||||
| 			error(word.." is not a valid token") | ||||
|         end | ||||
| 		words[word] = w | ||||
| 	end | ||||
| 	return w | ||||
| end | ||||
| 
 | ||||
| local function parsesyntax(line) | ||||
|     local syntax = {} | ||||
|     for word in line:gmatch("%S+") do | ||||
| 		local _, _, s = word:find('^"(.*)"$') | ||||
|         if s then | ||||
| 			syntax[#syntax+1] = {word=addword(s) } | ||||
| 		else | ||||
|             _, _, s = word:find("^('.*')$") | ||||
|             if s then | ||||
|                 syntax[#syntax+1] = {punct=s } | ||||
| 			else | ||||
| 				local token = {} | ||||
| 				for equate in word:gmatch("([^=]+)=") do | ||||
| 					token[#token+1] = equate | ||||
|                 end | ||||
| 				_, _, token.token = word:find("([^=]*)$") | ||||
|                 syntax[#syntax+1] = token | ||||
|                 if not token.token then | ||||
| 					error("can't parse "..word) | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| 	return syntax | ||||
| end | ||||
| 
 | ||||
| local function parsefields(line) | ||||
| 	local _, _, bits = line:find("^([^ ]+) ") | ||||
| 	if #bits ~= 32 then | ||||
| 		error("'"..bits.."' isn't 32 bits long") | ||||
| 	end | ||||
| 
 | ||||
| 	local fields = {} | ||||
| 	local i = 1 | ||||
| 	while i ~= 33 do | ||||
| 		local c = line:sub(i, i) | ||||
| 		if c ~= "." then | ||||
| 			local f = { pos=i } | ||||
| 			if c:find("%w") then | ||||
| 				f.size = 1 | ||||
| 				f.value = c | ||||
| 			elseif c == "<" then | ||||
| 				local _, newi, name = line:find("^<%-*(%w+)%-*>", i) | ||||
| 				f.size = 1 + newi - i | ||||
| 				f.value = name | ||||
| 				i = newi | ||||
| 			else | ||||
| 				error("bad field char '"..c.."' in '"..line.."'") | ||||
| 			end | ||||
| 			if f.value:find("[0-9]+") then | ||||
| 				f.literal = true | ||||
| 				f.variable = false | ||||
| 			else | ||||
| 				f.literal = false | ||||
| 				f.variable = true | ||||
| 			end | ||||
| 			-- Convert from PowerPC numbering to sane numbering | ||||
| 			f.pos = 33-(f.pos + f.size) | ||||
| 			fields[#fields+1] = f | ||||
|             if f.value then | ||||
| 				fields[f.value] = f | ||||
| 			end | ||||
| 		end | ||||
| 		i = i + 1 | ||||
|     end | ||||
| 
 | ||||
| 	local value = 0 | ||||
| 	for _, f in ipairs(fields) do | ||||
| 		if f.literal then | ||||
| 			local s = math.pow(2, f.pos) | ||||
| 			value = value + f.value*s | ||||
| 		end | ||||
|     end | ||||
|     fields.value = value | ||||
| 
 | ||||
| 	return fields | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
| local function emit(fields, code) | ||||
| 	local mask = 0 | ||||
| 	local value = 0 | ||||
| 	for _, f in ipairs(fields) do | ||||
| 		if f.literal then | ||||
| 			local s = math.pow(2, f.pos) | ||||
| 			local m = math.pow(2, f.size) - 1 | ||||
| 			mask = mask + m*s | ||||
| 			value = value + f.value*s | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	print(string.format("if ((value & 0x%x) == 0x%x) {", mask, value)) | ||||
| 	for _, f in ipairs(fields) do | ||||
| 		if f.variable then | ||||
| 			local m = math.pow(2, f.size) - 1 | ||||
| 			print(string.format("uint32_t %s = (value >> %d) & 0x%x;", f.value, f.pos, m)) | ||||
| 		end | ||||
| 	end | ||||
| 
 | ||||
| 	print(code) | ||||
| 	print("return;") | ||||
| 	print("}") | ||||
| end | ||||
| 
 | ||||
| while true do | ||||
| 	local line = io.stdin:read("*l") | ||||
| 	if not line then | ||||
| 		break | ||||
| 	end | ||||
| 	line = line:gsub("#.*$", "") | ||||
| 	line = line:gsub(" *$", "") | ||||
| 	if line:find("^%%token ") then | ||||
| 		addword(line:sub(8)) | ||||
| 	elseif line ~= "" then | ||||
| 		local fields = parsefields(line) | ||||
| 		local syntax = parsesyntax(line:sub(34, #line)) | ||||
|     	insns[#insns+1] = { | ||||
| 			fields=parsefields(line), | ||||
| 			syntax=parsesyntax(line:sub(34, #line)) | ||||
| 		} | ||||
| 	end | ||||
| end | ||||
| 
 | ||||
| local definitionsfp = io.open(args[1], "w") | ||||
| for word, value in pairs(words) do | ||||
| 	definitionsfp:write("%token <y_word> OP_", tostring(value), " /* ", word, " */\n") | ||||
| end | ||||
| definitionsfp:close() | ||||
| 
 | ||||
| local tokensfp = io.open(args[2], "w") | ||||
| for word, value in pairs(words) do | ||||
| 	tokensfp:write("0, OP_", value, ", 0, \"", word, "\",\n") | ||||
| end | ||||
| tokensfp:close() | ||||
| 
 | ||||
| local rulesfp = io.open(args[3], "w") | ||||
| rulesfp:write("operation\n") | ||||
| for index, insn in ipairs(insns) do | ||||
| 	if index == 1 then | ||||
| 		rulesfp:write("\t:") | ||||
| 	else | ||||
| 		rulesfp:write("\t|") | ||||
| 	end | ||||
| 	for _, word in ipairs(insn.syntax) do | ||||
| 		if word.word then | ||||
| 			rulesfp:write(" OP_", word.word) | ||||
| 		end | ||||
| 		if word.punct then | ||||
| 			rulesfp:write(" ", word.punct) | ||||
| 		end | ||||
| 		if word.token then | ||||
| 			rulesfp:write(" ", word.token) | ||||
| 		end | ||||
| 	end | ||||
| 	rulesfp:write("\n") | ||||
| 
 | ||||
| 	rulesfp:write("\t{ emit4(", string.format("0x%08x", insn.fields.value)) | ||||
| 	for wordindex, word in ipairs(insn.syntax) do | ||||
| 		if word.token then | ||||
| 			for _, alias in ipairs(word) do | ||||
| 				local f = insn.fields[alias] | ||||
| 				if not f then | ||||
| 					error("reference to field "..alias.." which doesn't exist") | ||||
|                 end | ||||
| 				local mask = math.pow(2, f.size) - 1 | ||||
| 				rulesfp:write(" | (($", wordindex, | ||||
|                     " & ", string.format("0x%x", mask), ") << ", f.pos, ")") | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| 	rulesfp:write("); }\n") | ||||
| end | ||||
| rulesfp:close() | ||||
| 
 | ||||
							
								
								
									
										47
									
								
								mach/mips/libem/aar4.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								mach/mips/libem/aar4.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* Get address of element of bounds-checked array. | ||||
|  * | ||||
|  * Stack: ( array-adr index descriptor-adr -- element-adr ) | ||||
|  * Sets r2 = size of element for .los4, .sts4 | ||||
|  * Preserves r25 (the last volatile register) | ||||
|  * | ||||
|  * An array descriptor is: | ||||
|  * | ||||
|  *   +0 lower bound | ||||
|  *   +4 range (upper bound - lower bound); *inclusive*
 | ||||
|  *   +8 element size | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .aar4 | ||||
| .aar4: | ||||
| 	lw r4, 0(sp)            ! r4 = address of descriptor | ||||
| 	lw r5, 4(sp)            ! r5 = index | ||||
| 	lw r6, 8(sp)            ! r6 = address of array | ||||
| 
 | ||||
| 	lw r7, 0(r4)            ! r7 = lower bound | ||||
| 	slt at, r5, r7          ! at = index < lower bound | ||||
| 	bne at, zero, .trap_earray | ||||
| 	nop | ||||
| 	subu r5, r5, r7         ! adjust index for non-zero lower bound | ||||
| 
 | ||||
| 	lw at, 4(r4)            ! at = range | ||||
| 	slt at, at, r5          ! at = range < adjusted index | ||||
| 	bne at, zero, .trap_earray | ||||
| 	nop | ||||
| 
 | ||||
| 	lw r2, 8(r4)            ! r2 = size of element | ||||
| 	mul r5, r5, r2          ! scale index by size | ||||
| 	addu r5, r5, r6         ! calculate address of element | ||||
| 
 | ||||
| 	sw r5, 8(sp)            ! push address of element | ||||
| 	addiu sp, sp, 8 | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| .define .trap_earray | ||||
| .trap_earray: | ||||
| 	li r4, 0                 ! EARRAY = 0 in h/em_abs.h | ||||
| 	b .trp | ||||
							
								
								
									
										30
									
								
								mach/mips/libem/and.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								mach/mips/libem/and.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* | ||||
|  * Set intersection. | ||||
|  * Stack: ( a b size -- a&b ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .and | ||||
| .and: | ||||
| 	lw r4, 0(sp)        ! r4 = size | ||||
| 	addiu sp, sp, 4     ! sp points at b | ||||
| 	addu r5, sp, r4     ! r5 points at a | ||||
| 	srl r4, r4, 2       ! r4 = count of words | ||||
| 
 | ||||
| 1: | ||||
| 	lw at, 0(r5)        ! load a | ||||
| 	lw r6, 0(sp)        ! load b | ||||
| 	and at, at, r6      ! combine | ||||
| 	sw at, 0(r5)        ! write back to a | ||||
| 	addiu r5, r5, 4 | ||||
| 	addiu sp, sp, 4 | ||||
| 	addiu r4, r4, -1 | ||||
| 	bne r4, zero, 1b | ||||
| 	nop | ||||
| 
 | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
							
								
								
									
										31
									
								
								mach/mips/libem/bls4.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								mach/mips/libem/bls4.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* Does a block move of words between non-overlapping buffers. | ||||
|  * Stack: ( src dst len -- ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .bls4 | ||||
| .bls4: | ||||
| 	lw r4, 0(sp)	! r4=len | ||||
| 	lw r5, 4(sp)	! r5=dst | ||||
| 	lw r6, 8(sp)	! r6=src | ||||
| 	addiu sp, sp, 12 | ||||
| 
 | ||||
| 	srl r4, r4, 2   ! convert len to words | ||||
| 1: | ||||
| 	beq r4, zero, 2f | ||||
| 	nop | ||||
| 
 | ||||
| 	lw at, 0(r6) | ||||
| 	sw at, 0(r5) | ||||
| 	addiu r6, r6, 4 | ||||
| 	addiu r5, r5, 4 | ||||
| 	addiu r4, r4, -1 | ||||
| 	b 1b | ||||
| 	nop | ||||
| 
 | ||||
| 2: | ||||
| 	jr ra | ||||
| 	nop | ||||
							
								
								
									
										17
									
								
								mach/mips/libem/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								mach/mips/libem/build.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | |||
| for _, plat in ipairs(vars.plats) do | ||||
| 	acklibrary { | ||||
| 		name = "headers_"..plat, | ||||
| 	} | ||||
| 
 | ||||
| 	acklibrary { | ||||
| 		name = "lib_"..plat, | ||||
| 		srcs = { | ||||
| 			"./*.s", -- dus4.s | ||||
| 		}, | ||||
| 		vars = { plat = plat }, | ||||
| 		deps = { | ||||
| 			"h+emheaders", | ||||
| 			"+headers_"..plat, | ||||
| 		} | ||||
| 	} | ||||
| end | ||||
							
								
								
									
										36
									
								
								mach/mips/libem/c_ud_i.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								mach/mips/libem/c_ud_i.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| .sect .text | ||||
| .define .c_ud_i | ||||
| .c_ud_i: | ||||
| 	/* Input: f0 | ||||
| 	 * Output: r2 | ||||
| 	 * Only at and f30/f31 may be used. | ||||
| 	 */ | ||||
| 
 | ||||
| 	lui at, ha16[.fd_80000000] | ||||
| 	ldc1 f30, lo16[.fd_80000000] (at) | ||||
| 	c.le.d 0, f30, f0 | ||||
| 	bc1t toobig | ||||
| 	nop | ||||
| 
 | ||||
| 	trunc.w.d f0, f0 | ||||
| 	mfc1 r2, f0 | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| toobig: | ||||
| 	sub.d f0, f0, f30 | ||||
| 	trunc.w.d f0, f0 | ||||
| 	mfc1 r2, f0 | ||||
| 	lui at, 0x8000			! load 0x80000000 | ||||
| 	addu r2, r2, at | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| .sect .rom | ||||
| .define .fd_80000000 | ||||
| .fd_80000000: | ||||
| 	.dataf8 2147483648.0 | ||||
| 
 | ||||
							
								
								
									
										38
									
								
								mach/mips/libem/c_uf_i.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								mach/mips/libem/c_uf_i.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | |||
| # | ||||
| .sect .text | ||||
| .sect .rom | ||||
| .sect .data | ||||
| .sect .bss | ||||
| 
 | ||||
| .sect .text | ||||
| .define .c_uf_i | ||||
| .c_uf_i: | ||||
| 	/* Input: f0 | ||||
| 	 * Output: r2 | ||||
| 	 * Only at and f30/f31 may be used. | ||||
| 	 */ | ||||
| 
 | ||||
| 	lui at, ha16[.ff_80000000] | ||||
| 	lwc1 f30, lo16[.ff_80000000] (at) | ||||
| 	c.le.s 0, f30, f0 | ||||
| 	bc1t toobig | ||||
| 	nop | ||||
| 
 | ||||
| 	trunc.w.s f0, f0 | ||||
| 	mfc1 r2, f0 | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| toobig: | ||||
| 	sub.s f0, f0, f30 | ||||
| 	trunc.w.s f0, f0 | ||||
| 	mfc1 r2, f0 | ||||
| 	lui at, 0x8000			! load 0x80000000 | ||||
| 	addu r2, r2, at | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| .sect .rom | ||||
| .ff_80000000: | ||||
| 	.dataf4 2147483648.0 | ||||
| 
 | ||||
							
								
								
									
										25
									
								
								mach/mips/libem/c_ui_d.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								mach/mips/libem/c_ui_d.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| .sect .text | ||||
| .define .c_ui_d | ||||
| .c_ui_d: | ||||
| 	/* Input: r2 | ||||
| 	 * Output: f0 | ||||
| 	 * Only at and f30/f31 may be used. | ||||
| 	 */ | ||||
| 	mtc1 r2, f0 | ||||
| 	cvt.d.w f0, f0 | ||||
| 	bgez r2, nonnegative | ||||
| 	nop | ||||
| 
 | ||||
| 	lui at, ha16[.fd_100000000] | ||||
| 	ldc1 f30, lo16[.fd_100000000] (at) | ||||
| 	add.d f0, f0, f30 | ||||
| nonnegative: | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| .sect .rom | ||||
| .fd_100000000: | ||||
| 	.dataf8 4294967296.0 | ||||
							
								
								
									
										26
									
								
								mach/mips/libem/c_ui_f.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								mach/mips/libem/c_ui_f.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| .sect .text | ||||
| .define .c_ui_f | ||||
| .c_ui_f: | ||||
| 	/* Input: r2 | ||||
| 	 * Output: f0 | ||||
| 	 * Only at and f30/f31 may be used. | ||||
| 	 */ | ||||
| 	mtc1 r2, f0 | ||||
| 	cvt.s.w f0, f0 | ||||
| 	bgez r2, nonnegative | ||||
| 	nop | ||||
| 
 | ||||
| 	lui at, ha16[.fs_100000000] | ||||
| 	ldc1 f30, lo16[.fs_100000000] (at) | ||||
| 	add.d f0, f0, f30 | ||||
| nonnegative: | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| /* 4294967296 as a float. */ | ||||
| .sect .rom | ||||
| .fs_100000000: | ||||
| 	.dataf4 4294967296.0 | ||||
							
								
								
									
										35
									
								
								mach/mips/libem/cms.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								mach/mips/libem/cms.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* | ||||
|  * Set comparison Returns 0 if the sets were equal. | ||||
|  * Stack: ( a b size -- a!=b ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .cms | ||||
| .cms: | ||||
| 	lw r4, 0(sp)        ! r4 = size; sp points at b-word
 | ||||
| 	addu r5, sp, r4     ! r5 points at a-word | ||||
| 	addu r6, r5, r4		! r6 is final sp-word | ||||
| 	srl r4, r4, 2       ! r4 = count of words | ||||
| 	li r8, 1			! result | ||||
| 
 | ||||
| 1: | ||||
| 	lw at, 4(r5)        ! load a | ||||
| 	lw r7, 4(sp)        ! load b | ||||
| 	bne at, r7, exit	! branch if not equal | ||||
| 	nop | ||||
| 	addiu r5, r5, 4 | ||||
| 	addiu sp, sp, 4 | ||||
| 	addiu r4, r4, -1 | ||||
| 	bne r4, zero, 1b | ||||
| 	nop | ||||
| 
 | ||||
| 	li r8, 0			! Update result. | ||||
| exit: | ||||
| 	mov sp, r6 | ||||
| 	sw r8, 0(sp) | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
							
								
								
									
										28
									
								
								mach/mips/libem/com.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								mach/mips/libem/com.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* | ||||
|  * Set complement. | ||||
|  * Stack: ( a size -- ~a ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .com | ||||
| .com: | ||||
| 	lw r4, 0(sp)        ! r4 = size | ||||
| 	addiu sp, sp, 4 | ||||
| 	mov r5, sp          ! r5 points to set | ||||
| 	srl r4, r4, 2       ! r4 = word count | ||||
| 
 | ||||
| 1: | ||||
| 	lw at, 0(r5) | ||||
| 	nor at, zero, at | ||||
| 	sw at, 0(r5) | ||||
| 	addiu r5, r5, 4 | ||||
| 	addiu r4, r4, -1 | ||||
| 	bne r4, zero, 1b | ||||
| 	nop | ||||
| 
 | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
							
								
								
									
										39
									
								
								mach/mips/libem/compareul.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								mach/mips/libem/compareul.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* | ||||
|  * 64-big unsigned tristate comparison. | ||||
|  * Inputs: | ||||
|  *    r2r3: left | ||||
|  *    r4r5: right | ||||
|  * Outputs;
 | ||||
|  *    r2: result | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .compareul | ||||
| .compareul: | ||||
| 	/* Compare high words. */ | ||||
| 
 | ||||
| 	sltu at, r3, r5			! if r3<r5, then 1 | ||||
| 	subu at, zero, at		! if r3<r5, then -1 | ||||
| 	bne at, zero, exit | ||||
| 	nop | ||||
| 
 | ||||
| 	sltu at, r5, r3			! if r3>r5, then 1 | ||||
| 	bne at, zero, exit | ||||
| 	nop | ||||
| 
 | ||||
| 	/* High words are equal --- compare low words. */ | ||||
| 
 | ||||
| 	sltu at, r2, r4			! if r2<r4, then 1 | ||||
| 	subu at, zero, at		! if r2<r4, then -1 | ||||
| 	bne at, zero, exit | ||||
| 	nop | ||||
| 
 | ||||
| 	sltu at, r4, r2			! if r2>r4, then 1 | ||||
| exit: | ||||
| 	mov r2, at | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
							
								
								
									
										42
									
								
								mach/mips/libem/csa.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								mach/mips/libem/csa.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* This is not a subroutine, but just a | ||||
|  * piece of code that computes the jump- | ||||
|  * address and jumps to it. | ||||
|  * traps if resulting address is zero | ||||
|  * | ||||
|  * Stack: ( value tableaddr -- ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .csa | ||||
| .csa: | ||||
| 	lw r4, 0(sp)            /* r4 = table */ | ||||
| 	lw r5, 4(sp)            /* r5 = value */ | ||||
| 	addiu sp, sp, 8 | ||||
| 
 | ||||
| 	lw r6, 0(r4)            /* r6 = default target */ | ||||
| 	lw r7, 4(r4)            /* r7 = lower bound */ | ||||
| 	subu r5, r5, r7         /* adjust value */ | ||||
| 	bltz r5, 1f             /* jump to default if out of range */ | ||||
| 	nop | ||||
| 
 | ||||
| 	lw r7, 8(r4)            /* fetch range */ | ||||
| 	subu r7, r7, r5         /* compute difference within range */ | ||||
| 	bltz r7, 1f             /* jump to default if out of range */ | ||||
| 	nop | ||||
| 
 | ||||
| 	addiu r4, r4, 12        /* skip header */ | ||||
| 	sll r5, r5, 2           /* value = value<<2 */ | ||||
| 	addu r4, r4, r5         /* find address of target */ | ||||
| 	lw r6, 0(r4)            /* r6 = new target */ | ||||
| 
 | ||||
| 1: | ||||
| 	beq r6, zero, 2f        /* trap if null */ | ||||
| 	nop | ||||
| 	jr r6                   /* otherwise jump */ | ||||
| 	nop | ||||
| 2: | ||||
| 	j .trap_ecase | ||||
| 	nop | ||||
							
								
								
									
										47
									
								
								mach/mips/libem/csb.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								mach/mips/libem/csb.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* this is not a subroutine, but just a | ||||
|  * piece of code that computes the jump- | ||||
|  * address and jumps to it. | ||||
|  * traps if resulting address is zero | ||||
|  * | ||||
|  * Stack: ( value tableaddr -- ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .csb | ||||
| .csb: | ||||
| 	lw r4, 0(sp)             ! r4 = address of table | ||||
| 	lw r5, 4(sp)             ! r5 = value | ||||
| 	addiu sp, sp, 8 | ||||
| 
 | ||||
| 	lw r6, 0(r4)             ! r6 = default target | ||||
| 	lw r7, 4(r4)             ! r7 = table count | ||||
| 
 | ||||
| 2: | ||||
| 	addiu r7, r7, -1         ! decrement count | ||||
| 	bltz r7, 1f              ! exit loop if out | ||||
| 	nop | ||||
| 
 | ||||
| 	lw r8, 8(r4)             ! candidate value | ||||
| 	beq r8, r5, 3f           ! branch if equal | ||||
| 	nop | ||||
| 
 | ||||
| 	addiu r4, r4, 8          ! next entry | ||||
| 	b 2b | ||||
| 	nop | ||||
| 
 | ||||
| 3: | ||||
| 	/* We found an item in the table. */ | ||||
| 	lw r6, 12(r4)            ! load jump target | ||||
| 	/* fall through */ | ||||
| 1: | ||||
| 	beq r6, zero, 4f        /* trap if null */ | ||||
| 	nop | ||||
| 	jr r6                   /* otherwise jump */ | ||||
| 	nop | ||||
| 4: | ||||
| 	j .trap_ecase | ||||
| 	nop | ||||
| 
 | ||||
							
								
								
									
										28
									
								
								mach/mips/libem/dus4.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								mach/mips/libem/dus4.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* Duplicates some words on top of stack. | ||||
|  *  Stack: ( a size -- a a ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .dus4 | ||||
| .dus4: | ||||
| 	lw r4, 0(sp)        ! r4 = size | ||||
| 	addiu sp, sp, 4     ! sp = pointer to a | ||||
| 	mov r5, sp          ! r5 = pointer to a | ||||
| 	subu sp, sp, r4     ! sp = pointer to newa | ||||
| 	mov r6, sp          ! r6 = pointer to b | ||||
| 
 | ||||
| 	srl r4, r4, 2       ! r4 = number of words | ||||
| 1: | ||||
| 	lw at, 0(r5) | ||||
| 	sw at, 0(r6) | ||||
| 	addiu r5, r5, 4 | ||||
| 	addiu r6, r6, 4 | ||||
| 	addiu r4, r4, -1 | ||||
| 	bne r4, zero, 1b | ||||
| 	nop | ||||
| 
 | ||||
| 	jr ra | ||||
| 	nop | ||||
							
								
								
									
										31
									
								
								mach/mips/libem/exg.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								mach/mips/libem/exg.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* Exchange top two values on stack. | ||||
|  *   Stack: ( a b size -- b a ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .exg | ||||
| .exg: | ||||
| 	lw r4, 0(sp)            ! r4 = size | ||||
| 	srl r5, r4, 2           ! r5 = number of words | ||||
| 	addiu sp, sp, 4         ! adjust stack for input/output parameter size | ||||
| 
 | ||||
| 	mov r6, sp              ! r6 = pointer to b | ||||
| 	addu r7, r6, r4         ! r7 = pointer to a | ||||
| 
 | ||||
| 	! Loop to swap each pair of words. | ||||
| 1: | ||||
| 	lw r8, 0(r6) | ||||
| 	lw r9, 0(r7) | ||||
| 	sw r9, 0(r6) | ||||
| 	sw r8, 0(r7) | ||||
| 	addiu r6, r6, 4 | ||||
| 	addiu r7, r7, 4 | ||||
| 	addiu r5, r5, -1 | ||||
| 	bne r5, zero, 1b | ||||
| 	nop | ||||
| 
 | ||||
| 	jr ra | ||||
| 	nop | ||||
							
								
								
									
										56
									
								
								mach/mips/libem/fef8.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								mach/mips/libem/fef8.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,56 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* Split a double-precision float into fraction and exponent, like | ||||
|  * frexp(3) in C, http://en.cppreference.com/w/c/numeric/math/frexp | ||||
|  * | ||||
|  * Stack: ( double -- fraction exponent ) | ||||
|  */ | ||||
| 
 | ||||
| #define DBL_EXPBITS	11 | ||||
| #define DBL_FRACHBITS	20 | ||||
| #define DBL_FRACLBITS	32 | ||||
| #define DBL_FRACBITS	52 | ||||
| #define DBL_EXP_INFNAN	2047 | ||||
| 
 | ||||
| #define DBL_EXP_BIAS 1023 | ||||
| 
 | ||||
| .sect .text | ||||
| .define .fef8 | ||||
| .fef8: | ||||
| 	lw r4, 0(sp)			! r4 = low word (bits 0..31) | ||||
| 	lw r5, 4(sp)			! r5 = high word (bits 32..63) | ||||
| 
 | ||||
| 	! IEEE double = sign * 1.fraction * 2**(exponent - 1023) | ||||
| 	!   sign  exponent  fraction | ||||
| 	!   31     30..19     18..0, 31..0 | ||||
| 	! | ||||
| 	! IEEE exponent = 1022 in [0.5, 1) or (-1, -0.5]. | ||||
| 
 | ||||
| 	ext r7, r5, DBL_FRACHBITS, DBL_EXPBITS ! r7 = IEEE exponent | ||||
| 	beq r7, zero, zeroexp   ! this number is zero or denormalised, treat specially | ||||
| 	nop | ||||
| 
 | ||||
| 	li at, DBL_EXP_INFNAN | ||||
| 	beq r7, at, return      ! just return if infinity or NaN | ||||
| 	nop | ||||
| 
 | ||||
| 	addiu r7, r7, -[DBL_EXP_BIAS-1] ! undo exponent bias | ||||
| 	li at, DBL_EXP_BIAS-1 | ||||
| 	ins r5, at, DBL_FRACHBITS, DBL_EXPBITS ! replace exponent | ||||
| return: | ||||
| 	addiu sp, sp, -4        ! returning one more quad than we got | ||||
| 	sw r5, 8(sp) | ||||
| 	sw r6, 4(sp) | ||||
| 	sw r7, 0(sp) | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| 	/* We received a denormalised number or zero. */ | ||||
| zeroexp: | ||||
| 	/* TODO: we just assume that the number is zero here. */ | ||||
| 	mov r5, zero | ||||
| 	mov r6, zero | ||||
| 	mov r7, zero | ||||
| 	b return | ||||
| 	nop | ||||
							
								
								
									
										69
									
								
								mach/mips/libem/fif8.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								mach/mips/libem/fif8.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,69 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* Multiplies two double-precision floats, then splits the product into | ||||
|  *  fraction and integer, both as floats, like modf(3) in C, | ||||
|  *  http://en.cppreference.com/w/c/numeric/math/modf | ||||
|  * | ||||
|  * Stack: ( a b -- fraction integer ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .fif8 | ||||
| .fif8: | ||||
| 	ldc1 f0, 8(sp)          ! f0 = a | ||||
| 	ldc1 f2, 0(sp)          ! f2 = b | ||||
| 	mul.d f0, f0, f2        ! f0 = a * b | ||||
| 	abs.d f2, f0            ! f2 = abs(f0) | ||||
| 
 | ||||
| 	lui at, ha16[max_power_of_two] | ||||
| 	ldc1 f4, lo16[max_power_of_two] (at) ! f4 = max power of two | ||||
| 
 | ||||
| 	mov.d f6, f2            ! we're going to assemble the integer part in f6 | ||||
| 	c.lt.d 0, f4, f2        ! if absolute value too big, it must be integral | ||||
| 	bc1t 0, return | ||||
| 	nop | ||||
| 
 | ||||
| 	! Crudely strip off the fractional part. | ||||
| 
 | ||||
| 	add.d f6, f2, f4        ! f6 = absolute value + max power of two | ||||
| 	sub.d f6, f6, f4        ! f6 -= max_power_of_two | ||||
| 
 | ||||
| 	! The above might round, so correct that. | ||||
| 
 | ||||
| 	lui at, ha16[one] | ||||
| 	ldc1 f8, lo16[one] (at)   ! f8 = 1.0 | ||||
| 1: | ||||
| 	c.le.d 0, f6, f2        ! if result <= absolute value, stop | ||||
| 	bc1t 0, 2f | ||||
| 	nop | ||||
| 
 | ||||
| 	sub.d f6, f6, f8        ! result -= 1.0 | ||||
| 	b 1b | ||||
| 	nop | ||||
| 2: | ||||
| 
 | ||||
| 	! Correct the sign of the result. | ||||
| 
 | ||||
| 	mtc1 zero, f8 | ||||
| 	mthc1 zero, f8          ! f8 = 0.0 | ||||
| 	c.lt.d 0, f0, f8        ! if original value was negative | ||||
| 	bc1f 0, 1f | ||||
| 	nop | ||||
| 	neg.d f6, f6            ! negate the result | ||||
| 1: | ||||
| 
 | ||||
| return: | ||||
| 	sdc1 f6, 0(sp)          ! store integer part | ||||
| 	sub.d f6, f0, f6        ! calculate fractional part | ||||
| 	sdc1 f6, 8(sp)          ! store fractional part | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| ! doubles >= MAXPOWTWO are already integers | ||||
| .sect .rom | ||||
| max_power_of_two: | ||||
| 	.dataf8 4.503599627370496000E+15 | ||||
| 
 | ||||
| one: | ||||
| 	.dataf8 1.0 | ||||
							
								
								
									
										32
									
								
								mach/mips/libem/inn.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								mach/mips/libem/inn.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* Tests a bit in a bitset on the stack. | ||||
|  * | ||||
|  * Stack: ( bitset bitnum setsize -- bool ) | ||||
|  * | ||||
|  * Some back ends push false if bitnum is too large.  We don't because | ||||
|  * the compilers tend to pass a small enough bitnum. | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .inn | ||||
| .inn: | ||||
| 	lw r4, 0(sp)        ! r4 = size of set (bytes) | ||||
| 	lw r5, 4(sp)        ! r5 = bit number | ||||
| 	addiu sp, sp, 4     ! sp now points to word below bitset | ||||
| 
 | ||||
| 	andi r6, r5, ~31    ! r6 = bit offset of base of word in set | ||||
| 	srl r6, r6, 3		! r6 = byte offset of base of word in set | ||||
| 	addu r6, sp, r6     ! r6 = address of word in set | ||||
| 	lw r6, 4(r6)        ! r6 = word (remember stack offset) | ||||
| 
 | ||||
| 	andi r7, r5, 31     ! r7 = bit number within word | ||||
| 	srlv r6, r6, r7     ! r7 = candidate bit now at bit 0 | ||||
| 	andi r6, r6, 1      ! r7 = bool | ||||
| 
 | ||||
| 	addu sp, sp, r4     ! retract over bitfield (remember stack offset) | ||||
| 	sw r6, 0(sp)        ! store result | ||||
| 
 | ||||
| 	jr ra | ||||
| 	nop | ||||
							
								
								
									
										30
									
								
								mach/mips/libem/ior.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								mach/mips/libem/ior.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* | ||||
|  * Set union. | ||||
|  * Stack: ( a b size -- a|b ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .ior | ||||
| .ior: | ||||
| 	lw r4, 0(sp)        ! r4 = size | ||||
| 	addiu sp, sp, 4     ! sp points at b | ||||
| 	addu r5, sp, r4     ! r5 points at a | ||||
| 	srl r4, r4, 2       ! r4 = count of words | ||||
| 
 | ||||
| 1: | ||||
| 	lw at, 0(r5)        ! load a | ||||
| 	lw r6, 0(sp)        ! load b | ||||
| 	or at, at, r6       ! combine | ||||
| 	sw at, 0(r5)        ! write back to a | ||||
| 	addiu r5, r5, 4 | ||||
| 	addiu sp, sp, 4 | ||||
| 	addiu r4, r4, -1 | ||||
| 	bne r4, zero, 1b | ||||
| 	nop | ||||
| 
 | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
							
								
								
									
										23
									
								
								mach/mips/libem/lar4.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								mach/mips/libem/lar4.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* Load from bounds-checked array. | ||||
|  * | ||||
|  * Stack: ( array-adr index descriptor-adr -- element ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .lar4 | ||||
| .lar4: | ||||
| 	mov r25, ra | ||||
| 
 | ||||
| 	jal .aar4 | ||||
| 	nop | ||||
| 
 | ||||
| 	/* pass r2 = size from .aar4 to .los4 */ | ||||
| 
 | ||||
| 	jal .los4 | ||||
| 	nop | ||||
| 
 | ||||
| 	jr r25 | ||||
| 	nop | ||||
							
								
								
									
										55
									
								
								mach/mips/libem/los4.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								mach/mips/libem/los4.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* Loads a variable-sized block onto the stack. | ||||
|  * | ||||
|  * On entry: r2 = size | ||||
|  * Stack: ( address -- block ) | ||||
|  * Preserves r25 for .lar4 and .sar4 | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .los4 | ||||
| .los4: | ||||
| 	lw r4, 0(sp)            ! r4 = address of source block | ||||
| 
 | ||||
| 	! Sizes 1 and 2 are handled specially. | ||||
| 
 | ||||
| 	li at, 1 | ||||
| 	beq r2, at, byte_sized | ||||
| 	nop | ||||
| 
 | ||||
| 	li at, 2 | ||||
| 	beq r2, at, word_sized | ||||
| 	nop | ||||
| 
 | ||||
| 	! Else the size must be a multiple of 4. | ||||
| 
 | ||||
| 	srl r5, r2, 2           ! r5 = number of words | ||||
| 	addiu sp, sp, 4         ! retract over address | ||||
| 	subu sp, sp, r2         ! allocate space for destination block | ||||
| 	mov r6, sp              ! r6 = start of destination block | ||||
| 
 | ||||
| 1: | ||||
| 	lw at, 0(r4) | ||||
| 	sw at, 0(r6) | ||||
| 	addiu r4, r4, 4 | ||||
| 	addiu r6, r6, 4 | ||||
| 	addiu r5, r5, -1 | ||||
| 	bne r5, zero, 1b | ||||
| 	nop | ||||
| 
 | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| byte_sized: | ||||
| 	lbu at, 0(r4) | ||||
| 	sw at, 0(sp) | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| word_sized: | ||||
| 	lhu at, 0(r4) | ||||
| 	sw at, 0(sp) | ||||
| 	jr ra | ||||
| 	nop | ||||
							
								
								
									
										35
									
								
								mach/mips/libem/rck.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								mach/mips/libem/rck.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* Bounds check. Traps if the value is out of range. | ||||
|  *  Stack: ( value descriptor -- value ) | ||||
|  * | ||||
|  * This ".rck" only works with 4-byte integers.  The name is ".rck" and | ||||
|  * not ".rck4" because many back ends only do rck with the word size. | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .rck | ||||
| .rck: | ||||
| 	lw r4, 0(sp)            ! r4 = pointer to descriptor | ||||
| 	addiu sp, sp, 4         ! leave value on stack | ||||
| 	lw r5, 0(sp)            ! r5 = value | ||||
| 
 | ||||
| 	lw at, 0(r4)            ! at = lower bound | ||||
| 	slt at, r5, at          ! at = r5 < at | ||||
| 	bne at, zero, .trap_erange | ||||
| 	nop | ||||
| 
 | ||||
| 	lw at, 4(r4)            ! at = upper bound | ||||
| 	slt at, at, r5          ! at = at < r5 | ||||
| 	bne at, zero, .trap_erange | ||||
| 	nop | ||||
| 
 | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| .define .trap_erange | ||||
| .trap_erange: | ||||
| 	li r4, 1 | ||||
| 	j .trp | ||||
| 	nop | ||||
							
								
								
									
										24
									
								
								mach/mips/libem/sar4.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								mach/mips/libem/sar4.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* Store to bounds-checked array. | ||||
|  * | ||||
|  * Stack: ( element array-adr index descriptor-adr -- ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .sar4 | ||||
| .sar4: | ||||
| 	mov r25, ra | ||||
| 
 | ||||
| 	jal .aar4 | ||||
| 	nop | ||||
| 
 | ||||
| 	/* pass r2 = size from .aar4 to .sts4 */ | ||||
| 
 | ||||
| 	jal .sts4 | ||||
| 	nop | ||||
| 
 | ||||
| 	jr r25 | ||||
| 	nop | ||||
| 
 | ||||
							
								
								
									
										39
									
								
								mach/mips/libem/set.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								mach/mips/libem/set.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* | ||||
|  * Create singleton set. | ||||
|  * Stack: ( bitnumber size -- set ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .set | ||||
| .set: | ||||
| 	lw r4, 0(sp)        ! r4 = size | ||||
| 	lw r5, 4(sp)        ! r5 = bit number | ||||
| 	addiu sp, sp, 8 | ||||
| 	srl r4, r4, 2       ! r4 = word count | ||||
| 
 | ||||
| 	! Create an empty set by pushing zeros. | ||||
| 
 | ||||
| 1: | ||||
| 	addiu sp, sp, -4 | ||||
| 	sw zero, 0(sp) | ||||
| 	addiu r4, r4, -1 | ||||
| 	bne r4, zero, 1b | ||||
| 	nop | ||||
| 
 | ||||
| 	! sp now points at the set. | ||||
| 
 | ||||
| 	andi r6, r5, ~31	! r6 = bit offset of base of word in set | ||||
| 	srl r6,r6, 3        ! r6 = byte offset of word in set | ||||
| 	addu r6, sp, r6		! r6 = address of word in set | ||||
| 
 | ||||
| 	andi r7, r5, 31		! r7 = bit number within word | ||||
| 	li r8, 1 | ||||
| 	sllv r8, r8, r7     ! r8 = word with 1 set | ||||
| 	sw r8, 0(r6)        ! write to set | ||||
| 
 | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
							
								
								
									
										57
									
								
								mach/mips/libem/sts4.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								mach/mips/libem/sts4.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,57 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* Stores a variable-sized block from the stack. | ||||
|  * | ||||
|  * On entry: r2 = size | ||||
|  * Stack: ( block address -- ) | ||||
|  * Preserves r25 for .lar4 and .sar4 | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .sts4 | ||||
| .sts4: | ||||
| 	lw r4, 0(sp)            ! r4 = address | ||||
| 	addiu sp, sp, 4         ! sp = pointer to block | ||||
| 
 | ||||
| 	! Sizes 1 and 2 are handled specially. | ||||
| 
 | ||||
| 	li at, 1 | ||||
| 	beq r2, at, byte_sized | ||||
| 	nop | ||||
| 
 | ||||
| 	li at, 2 | ||||
| 	beq r2, at, word_sized | ||||
| 	nop | ||||
| 
 | ||||
| 	! Else the size must be a multiple of 4. | ||||
| 
 | ||||
| 	srl r5, r2, 2           ! r5 = number of words | ||||
| 
 | ||||
| 	! Copy. | ||||
| 
 | ||||
| 1: | ||||
| 	lw at, 0(sp) | ||||
| 	sw at, 0(r4) | ||||
| 	addiu sp, sp, 4 | ||||
| 	addiu r4, r4, 4 | ||||
| 	addiu r5, r5, -1 | ||||
| 	bne r5, zero, 1b | ||||
| 	nop | ||||
| 
 | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| byte_sized: | ||||
| 	lw at, 0(sp) | ||||
| 	sb at, 0(r4) | ||||
| 	addiu sp, sp, 4 | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| word_sized: | ||||
| 	lw at, 0(sp) | ||||
| 	sh at, 0(r4) | ||||
| 	addiu sp, sp, 4 | ||||
| 	jr ra | ||||
| 	nop | ||||
							
								
								
									
										65
									
								
								mach/mips/libem/trp.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								mach/mips/libem/trp.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,65 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| 
 | ||||
| .sect .text | ||||
| .define .trap_ecase | ||||
| .trap_ecase: | ||||
| 	li	r4, 20			! ECASE = 20 in h/em_abs.h | ||||
| 	! FALLTHROUGH to .trp | ||||
| 
 | ||||
| ! Raises an EM trap. | ||||
| ! Expects r4 = trap number. | ||||
| 
 | ||||
| .define .trp | ||||
| .trp: | ||||
| 	andi at, r4, 0xfff0 | ||||
| 	bne at, zero, 1f				! traps > 15 can't be ignored | ||||
| 	nop | ||||
| 
 | ||||
| 	lui at, ha16[.ignmask] | ||||
| 	lw r5, lo16[.ignmask] (at)		! load ignore mask | ||||
| 	srlv r5, r5, r4 | ||||
| 	andi r5, r5, 1 | ||||
| 	bne r5, zero, return			! return if ignoring trap | ||||
| 	nop | ||||
| 1: | ||||
| 
 | ||||
| 	lui at, ha16[.trppc] | ||||
| 	lw r5, lo16[.trppc] (at)		! r5 = user trap routine | ||||
| 	sw zero, lo16[.trppc] (at)		! reset the trap routine for next time | ||||
| 	beq r5, zero, abend				! abort if no user trap routine | ||||
| 	nop | ||||
| 
 | ||||
| 	addiu sp, sp, -8 | ||||
| 	sw r4, 0(sp)					! push trap number | ||||
| 	sw ra, 4(sp)					! and link register | ||||
| 	jalr r5							! call trap routine | ||||
| 	nop | ||||
| 
 | ||||
| 	lw ra, 4(sp)					! ...and return | ||||
| 	addiu sp, sp, 8 | ||||
| return: | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
| 	! No trap handler; write error message and exit.
 | ||||
| abend: | ||||
| 	addiu sp, sp, -12 | ||||
| 	li at, 2 | ||||
| 	sw at, 0(sp) | ||||
| 	lui at, hi16[message] | ||||
| 	ori at, at, lo16[message] | ||||
| 	sw at, 4(sp) | ||||
| 	li at, 6 | ||||
| 	sw at, 8(sp) | ||||
| 	jal _write						! write(2, message, 6) | ||||
| 	nop | ||||
| 
 | ||||
| 	li at, 1 | ||||
| 	sw at, 0(sp) | ||||
| 	j __exit						! _exit(1) | ||||
| 
 | ||||
| .sect .rom | ||||
| message: | ||||
| 	.ascii "TRAP!\n" | ||||
							
								
								
									
										30
									
								
								mach/mips/libem/xor.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								mach/mips/libem/xor.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* | ||||
|  * Set xor.. | ||||
|  * Stack: ( a b size -- a^b ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .xor | ||||
| .xor: | ||||
| 	lw r4, 0(sp)        ! r4 = size | ||||
| 	addiu sp, sp, 4     ! sp points at b | ||||
| 	addu r5, sp, r4     ! r5 points at a | ||||
| 	srl r4, r4, 2       ! r4 = count of words | ||||
| 
 | ||||
| 1: | ||||
| 	lw at, 0(r5)        ! load a | ||||
| 	lw r6, 0(sp)        ! load b | ||||
| 	xor at, at, r6      ! combine | ||||
| 	sw at, 0(r5)        ! write back to a | ||||
| 	addiu r5, r5, 4 | ||||
| 	addiu sp, sp, 4 | ||||
| 	addiu r4, r4, -1 | ||||
| 	bne r4, zero, 1b | ||||
| 	nop | ||||
| 
 | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
							
								
								
									
										25
									
								
								mach/mips/libem/zer.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								mach/mips/libem/zer.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| # | ||||
| .sect .text; .sect .rom; .sect .data; .sect .bss
 | ||||
| 
 | ||||
| /* | ||||
|  * Create empty set. | ||||
|  * Stack: ( size -- set ) | ||||
|  */ | ||||
| 
 | ||||
| .sect .text | ||||
| .define .zer | ||||
| .zer: | ||||
| 	lw r4, 0(sp)        ! r4 = size | ||||
| 	addiu sp, sp, 4 | ||||
| 	srl r4, r4, 2       ! r4 = word count | ||||
| 
 | ||||
| 1: | ||||
| 	addiu sp, sp, -4 | ||||
| 	sw zero, 0(sp) | ||||
| 	addiu r4, r4, -1 | ||||
| 	bne r4, zero, 1b | ||||
| 	nop | ||||
| 
 | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
							
								
								
									
										8
									
								
								mach/mips/libend/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								mach/mips/libend/build.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| for _, plat in ipairs(vars.plats) do | ||||
| 	acklibrary { | ||||
| 		name = "lib_"..plat, | ||||
| 		srcs = { "./*.s" }, | ||||
| 		vars = { plat = plat }, | ||||
| 	} | ||||
| end | ||||
| 
 | ||||
							
								
								
									
										9
									
								
								mach/mips/libend/edata.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								mach/mips/libend/edata.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| .sect .text | ||||
| .sect .rom | ||||
| .sect .data | ||||
| .sect .bss | ||||
| .define	_edata
 | ||||
| .sect .data | ||||
| 	.align 4
 | ||||
| 	.sect .data | ||||
| _edata: | ||||
							
								
								
									
										24
									
								
								mach/mips/libend/em_end.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								mach/mips/libend/em_end.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| ! $Source$ | ||||
| ! $State$ | ||||
| ! $Revision$ | ||||
| 
 | ||||
| .sect .text | ||||
| .sect .rom | ||||
| .sect .data | ||||
| .sect .bss | ||||
| .sect .end ! only for declaration of _end, __end and endbss. | ||||
| .define	endtext, endrom, enddata, endbss, __end | ||||
| 
 | ||||
| 	.sect .text | ||||
| 	.align 4
 | ||||
| endtext: | ||||
| 	.sect .rom | ||||
| 	.align 4
 | ||||
| endrom: | ||||
| 	.sect .data | ||||
| 	.align 4
 | ||||
| enddata: | ||||
| 	.sect .end | ||||
| 	.align 4
 | ||||
| __end: | ||||
| endbss: | ||||
							
								
								
									
										7
									
								
								mach/mips/libend/end.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								mach/mips/libend/end.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| .sect .text | ||||
| .sect .rom | ||||
| .sect .data | ||||
| .sect .bss | ||||
| .define	_end
 | ||||
| .sect .end ! only for declaration of _end, __end and endbss. | ||||
| _end: | ||||
							
								
								
									
										9
									
								
								mach/mips/libend/etext.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								mach/mips/libend/etext.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| .sect .text | ||||
| .sect .rom | ||||
| .sect .data | ||||
| .sect .bss | ||||
| .define	_etext
 | ||||
| .sect .text | ||||
| 	.align 4
 | ||||
| 	.sect .text | ||||
| _etext: | ||||
							
								
								
									
										310
									
								
								mach/mips/mcg/platform.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										310
									
								
								mach/mips/mcg/platform.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,310 @@ | |||
| #include "mcg.h" | ||||
| 
 | ||||
| /* mcg stack frames are laid out as:
 | ||||
|  * | ||||
|  * |    ...params... | ||||
|  * |  --------------- <- ab | ||||
|  * |       old FR | ||||
|  * |       old FP | ||||
|  * |  --------------- <- fp (a.k.a. lb)  | ||||
|  * |      locals | ||||
|  * |  --------------- | ||||
|  * |      spills | ||||
|  * |  --------------- <- sb | ||||
|  * |     saved regs | ||||
|  * |  --------------- <- sp, rb | ||||
|  * V  ...user area... | ||||
|  * | ||||
|  * st indexes up; lb indexes down. | ||||
|  * | ||||
|  * Note that [fp] == old_fp and ab == fp + 8. | ||||
|  */ | ||||
| 
 | ||||
| static ARRAYOF(struct hreg) saved_regs; | ||||
| 
 | ||||
| void platform_calculate_offsets(void) | ||||
| { | ||||
|     int i; | ||||
| 
 | ||||
|     saved_regs.count = 0; | ||||
|     for (i=0; i<current_proc->usedregs.count; i++) | ||||
|     { | ||||
|         struct hreg* hreg = current_proc->usedregs.item[i]; | ||||
| 
 | ||||
|         if (!(hreg->attrs & burm_volatile_ATTR) && | ||||
|             ((hreg->attrs & burm_long_ATTR) || (hreg->attrs & burm_double_ATTR))) | ||||
|         { | ||||
|             hreg->offset = current_proc->saved_size; | ||||
|             current_proc->saved_size += 8; | ||||
|             array_append(&saved_regs, hreg); | ||||
|         } | ||||
|     } | ||||
|     for (i=0; i<current_proc->usedregs.count; i++) | ||||
|     { | ||||
|         struct hreg* hreg = current_proc->usedregs.item[i]; | ||||
| 
 | ||||
|         if (!(hreg->attrs & burm_volatile_ATTR) && | ||||
|             ((hreg->attrs & burm_int_ATTR) || (hreg->attrs & burm_float_ATTR))) | ||||
|         { | ||||
|             hreg->offset = current_proc->saved_size; | ||||
|             current_proc->saved_size += 4; | ||||
|             array_append(&saved_regs, hreg); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 	current_proc->fp_to_ab = 8; | ||||
| 	current_proc->fp_to_lb = 0; | ||||
| 	current_proc->fp_to_sb = -(current_proc->locals_size + current_proc->spills_size); | ||||
|     current_proc->fp_to_rb = current_proc->fp_to_sb - current_proc->saved_size; | ||||
| } | ||||
| 
 | ||||
| struct hop* platform_prologue(void) | ||||
| { | ||||
|     int i; | ||||
|     int spoffset = current_proc->saved_size + current_proc->spills_size + | ||||
|         current_proc->locals_size; | ||||
| 	struct hop* hop = new_hop(current_proc->entry, NULL); | ||||
| 
 | ||||
|     hop_add_insel(hop, "! locals_size = %d", current_proc->locals_size); | ||||
|     hop_add_insel(hop, "! spills_size = %d", current_proc->spills_size); | ||||
|     hop_add_insel(hop, "! saved_size = %d", current_proc->saved_size); | ||||
|     hop_add_insel(hop, "! params @ fp+%d", current_proc->fp_to_ab); | ||||
|     hop_add_insel(hop, "! lr @ fp+4");   | ||||
|     hop_add_insel(hop, "! fp @ fp+0");   | ||||
|     hop_add_insel(hop, "! locals @ fp-%d to fp+0", | ||||
|         current_proc->locals_size); | ||||
|     hop_add_insel(hop, "! spills @ fp-%d to fp-%d", | ||||
|         -current_proc->fp_to_sb, current_proc->locals_size); | ||||
|     for (i=saved_regs.count-1; i>=0; i--) | ||||
|     { | ||||
|         struct hreg* hreg = saved_regs.item[i]; | ||||
|         hop_add_insel(hop, "! %s @ fp-%d", | ||||
|             hreg->id, -(current_proc->fp_to_rb + hreg->offset)); | ||||
|     } | ||||
| 
 | ||||
| 	hop_add_insel(hop, "addiu sp, sp, %d", -(spoffset + 8)); | ||||
| 	hop_add_insel(hop, "sw fp, %d(sp)", spoffset + 0); | ||||
| 	hop_add_insel(hop, "sw ra, %d(sp)", spoffset + 4); | ||||
| 	hop_add_insel(hop, "addiu fp, sp, %d", spoffset); | ||||
| 
 | ||||
|     /* Saved reg offsets are negative. */ | ||||
|     for (i=0; i<saved_regs.count; i++) | ||||
|     { | ||||
|         struct hreg* hreg = saved_regs.item[i]; | ||||
|         if (hreg->attrs & burm_int_ATTR) | ||||
|             hop_add_insel(hop, "sw %H, %d(fp)", | ||||
|                 hreg, current_proc->fp_to_rb + hreg->offset); | ||||
|         else if (hreg->attrs & burm_long_ATTR) | ||||
|         { | ||||
|             hop_add_insel(hop, "sw %0H, %d(fp)", | ||||
|                 hreg, current_proc->fp_to_rb + hreg->offset + 0); | ||||
|             hop_add_insel(hop, "sw %1H, %d(fp)", | ||||
|                 hreg, current_proc->fp_to_rb + hreg->offset + 4); | ||||
|         } | ||||
|         else if (hreg->attrs & burm_float_ATTR) | ||||
|             hop_add_insel(hop, "swc1 %H, %d(fp)", | ||||
|                 hreg, current_proc->fp_to_rb + hreg->offset); | ||||
|         else if (hreg->attrs & burm_double_ATTR) | ||||
|             hop_add_insel(hop, "sdc1 %H, %d(fp)", | ||||
|                 hreg, current_proc->fp_to_rb + hreg->offset); | ||||
|         else | ||||
|             fatal("unsavable non-volatile register %s", hreg->id); | ||||
|     } | ||||
| 	return hop; | ||||
| } | ||||
| 
 | ||||
| struct hop* platform_epilogue(void) | ||||
| { | ||||
| 	struct hop* hop = new_hop(current_proc->exit, NULL); | ||||
|     int i; | ||||
| 
 | ||||
|     for (i=0; i<saved_regs.count; i++) | ||||
|     { | ||||
|         struct hreg* hreg = saved_regs.item[i]; | ||||
|         if (hreg->attrs & burm_int_ATTR) | ||||
|             hop_add_insel(hop, "lw %H, %d(fp)", | ||||
|                 hreg, current_proc->fp_to_rb + hreg->offset); | ||||
|         else if (hreg->attrs & burm_long_ATTR) | ||||
|         { | ||||
|             hop_add_insel(hop, "lw %0H, %d(fp)", | ||||
|                 hreg, current_proc->fp_to_rb + hreg->offset + 0); | ||||
|             hop_add_insel(hop, "lw %1H, %d(fp)", | ||||
|                 hreg, current_proc->fp_to_rb + hreg->offset + 4); | ||||
|         } | ||||
|         else if (hreg->attrs & burm_float_ATTR) | ||||
|             hop_add_insel(hop, "lwc1 %H, %d(fp)", | ||||
|                 hreg, current_proc->fp_to_rb + hreg->offset); | ||||
|         else if (hreg->attrs & burm_double_ATTR) | ||||
|             hop_add_insel(hop, "ldc1 %H, %d(fp)", | ||||
|                 hreg, current_proc->fp_to_rb + hreg->offset); | ||||
|         else | ||||
|             fatal("unloadable non-volatile register %s", hreg->id); | ||||
|     } | ||||
| 
 | ||||
|     hop_add_insel(hop, "lw ra, 4(fp)"); | ||||
|     hop_add_insel(hop, "lw at, 0(fp)"); /* load old fp */ | ||||
|     hop_add_insel(hop, "addiu sp, fp, %d", current_proc->fp_to_ab); | ||||
|     hop_add_insel(hop, "mov fp, at"); | ||||
|     hop_add_insel(hop, "jr ra"); | ||||
|     hop_add_insel(hop, "nop"); | ||||
| 
 | ||||
| 	return hop; | ||||
| } | ||||
| 
 | ||||
| struct hop* platform_move(struct basicblock* bb, struct vreg* vreg, struct hreg* src, struct hreg* dest) | ||||
| { | ||||
|     struct hop* hop = new_hop(bb, NULL); | ||||
| 
 | ||||
|     if ((src->attrs & TYPE_ATTRS) != (dest->attrs & TYPE_ATTRS)) | ||||
|             fatal("hreg move of %%%d from %s to %s with mismatched types", vreg->id, src->id, dest->id); | ||||
|     else | ||||
|     { | ||||
|         uint32_t type = src->attrs & TYPE_ATTRS; | ||||
| 		tracef('R', "R: non-converting move from %s to %s of type 0x%x\n", src->id, dest->id, type); | ||||
| 
 | ||||
|         if (!src->is_stacked && dest->is_stacked) | ||||
|         { | ||||
|             switch (type) | ||||
|             { | ||||
|                 case burm_int_ATTR: | ||||
|                     hop_add_insel(hop, "sw %H, %S(fp) ! %H", src, dest, dest); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_long_ATTR: | ||||
|                     hop_add_insel(hop, "sw %0H, 0+%S(fp) ! %H", src, dest, dest); | ||||
|                     hop_add_insel(hop, "sw %1H, 4+%S(fp) ! %H", src, dest, dest); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_float_ATTR: | ||||
|                     hop_add_insel(hop, "swc1 %H, %S(fp) ! %H", src, dest, dest); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_double_ATTR: | ||||
|                     hop_add_insel(hop, "sdc1 %H, %S(fp) ! %H", src, dest, dest); | ||||
|                     break; | ||||
| 
 | ||||
|                 default: | ||||
|                     goto nomove; | ||||
|             } | ||||
|         } | ||||
|         else if (src->is_stacked && !dest->is_stacked) | ||||
|         { | ||||
|             switch (type) | ||||
|             { | ||||
|                 case burm_int_ATTR: | ||||
|                     hop_add_insel(hop, "lw %H, %S(fp) ! %H", dest, src, src); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_long_ATTR: | ||||
|                     /* Can't load straight into dest because it might overlap with src. */ | ||||
|                     hop_add_insel(hop, "lw at, 0+%S(fp) ! %H", dest, src, src); | ||||
|                     hop_add_insel(hop, "lw %1H, 4+%S(fp) ! %H", dest, src, src); | ||||
|                     hop_add_insel(hop, "mov %0H, at", dest); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_float_ATTR: | ||||
|                     hop_add_insel(hop, "lwc1 %H, %S(fp) ! %H", dest, src, src); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_double_ATTR: | ||||
|                     hop_add_insel(hop, "ldc1 %H, %S(fp) ! %H", dest, src, src); | ||||
|                     break; | ||||
| 
 | ||||
|                 default: | ||||
|                     goto nomove; | ||||
|             } | ||||
|         } | ||||
|         else if (!src->is_stacked && !dest->is_stacked) | ||||
|         { | ||||
|             switch (type) | ||||
|             { | ||||
|                 case burm_int_ATTR: | ||||
|                     hop_add_insel(hop, "mov %H, %H", dest, src); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_long_ATTR: | ||||
|                     hop_add_insel(hop, "mov %0H, %0H", dest, src); | ||||
|                     hop_add_insel(hop, "mov %1H, %1H", dest, src); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_float_ATTR: | ||||
|                     hop_add_insel(hop, "mov.s %H, %H", dest, src); | ||||
|                     break; | ||||
| 
 | ||||
|                 case burm_double_ATTR: | ||||
|                     hop_add_insel(hop, "mov.d %H, %H", dest, src); | ||||
|                     break; | ||||
| 
 | ||||
|                 default: | ||||
|                     goto nomove; | ||||
|             } | ||||
|         } | ||||
|         else if (src->is_stacked && dest->is_stacked) | ||||
|             fatal("tried to move stacked object %%%d of type 0x%x from %s to %s", vreg->id, type, src->id, dest->id); | ||||
|         else | ||||
|             goto nomove; | ||||
|     } | ||||
| 
 | ||||
|     return hop; | ||||
| 
 | ||||
| nomove: | ||||
|     fatal("cannot move %s to %s", src->id, dest->id); | ||||
| } | ||||
| 
 | ||||
| struct hop* platform_swap(struct basicblock* bb, struct hreg* src, struct hreg* dest) | ||||
| { | ||||
|     struct hop* hop = new_hop(bb, NULL); | ||||
| 
 | ||||
| 	tracef('R', "R: swap of %s to %s\n", src->id, dest->id); | ||||
|     assert(!src->is_stacked); | ||||
|     assert(!dest->is_stacked); | ||||
|     assert((src->attrs & TYPE_ATTRS) == (dest->attrs & TYPE_ATTRS)); | ||||
|      | ||||
|     switch (src->attrs & TYPE_ATTRS) | ||||
|     { | ||||
|         case burm_int_ATTR: | ||||
|             hop_add_insel(hop, "mov at, %H", src); | ||||
|             hop_add_insel(hop, "mov %H, %H", src, dest); | ||||
|             hop_add_insel(hop, "mov %H, at", dest); | ||||
|             break; | ||||
| 
 | ||||
|         case burm_long_ATTR: | ||||
|             hop_add_insel(hop, "mov at, %0H", src); | ||||
|             hop_add_insel(hop, "mov %0H, %0H", src, dest); | ||||
|             hop_add_insel(hop, "mov %0H, at", dest); | ||||
| 
 | ||||
|             hop_add_insel(hop, "mov at, %1H", src); | ||||
|             hop_add_insel(hop, "mov %1H, %1H", src, dest); | ||||
|             hop_add_insel(hop, "mov %1H, at", dest); | ||||
|             break; | ||||
| 
 | ||||
|         case burm_float_ATTR: | ||||
|             hop_add_insel(hop, "mov.s f30, %H", src); | ||||
|             hop_add_insel(hop, "mov.s %H, %H", src, dest); | ||||
|             hop_add_insel(hop, "mov.s %H, f30", dest); | ||||
|             break; | ||||
| 
 | ||||
|         case burm_double_ATTR: | ||||
|             hop_add_insel(hop, "mov.d f30, %H", src); | ||||
|             hop_add_insel(hop, "mov.d %H, %H", src, dest); | ||||
|             hop_add_insel(hop, "mov.d %H, f30", dest); | ||||
|             break; | ||||
|     } | ||||
| 
 | ||||
|     return hop; | ||||
| } | ||||
| 
 | ||||
| const char* platform_label(const char* label) | ||||
| { | ||||
|     /* Labels starting with . are internal, not exported, and don't need mangling. */ | ||||
| 
 | ||||
|     if (label[0] == '.') | ||||
|         return label; | ||||
| 
 | ||||
|     /* Otherwise, mangle. */ | ||||
| 
 | ||||
|     return aprintf("_%s", label); | ||||
| } | ||||
| 
 | ||||
| /* vim: set sw=4 ts=4 expandtab : */ | ||||
| 
 | ||||
							
								
								
									
										992
									
								
								mach/mips/mcg/table
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										992
									
								
								mach/mips/mcg/table
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,992 @@ | |||
| REGISTERS | ||||
| 
 | ||||
|     /* Registers are allocated top down. The odd order below is to make sure | ||||
|      * that cheap registers get allocated first. | ||||
|      * | ||||
|      * Attributes may have at most one of: int, float, long, double. These | ||||
|      * indicate that the register is used to store a value of that type. If | ||||
|      * your register can store more than one type, create an alias. Registers | ||||
|      * with none of these cannot be copied by the code generator (and so cannot | ||||
|      * be moved from register to register or spilt). | ||||
|      */ | ||||
| 
 | ||||
| 	r4                                            int volatile; | ||||
| 	r5                                            int volatile; | ||||
| 	r6                                            int volatile; | ||||
| 	r7                                            int volatile; | ||||
| 	r8                                            int volatile; | ||||
| 	r9                                            int volatile; | ||||
| 	r10                                           int volatile; | ||||
| 	r11                                           int volatile; | ||||
| 	r12                                           int volatile; | ||||
| 	r13                                           int volatile; | ||||
| 	r14                                           int volatile; | ||||
| 	r15                                           int volatile; | ||||
| 	r24                                           int volatile; | ||||
| 	r25                                           int volatile; | ||||
| 	r2                                            int volatile iret; | ||||
| 	r3                                            int volatile; | ||||
| 
 | ||||
| 	r17 named("r16")                              int; | ||||
| 	r18 named("r18")                              int; | ||||
| 	r19 named("r19")                              int; | ||||
| 	r20 named("r20")                              int; | ||||
| 	r21 named("r21")                              int; | ||||
| 	r22 named("r22")                              int; | ||||
| 	r23 named("r23")                              int; | ||||
| 
 | ||||
| 	r4r5    named("r4", "r5")   aliases(r4,  r5)  long volatilei lret1; | ||||
| 	r6r7    named("r6", "r7")   aliases(r6,  r7)  long volatile; | ||||
| 	r8r9    named("r8", "r9")   aliases(r8,  r9)  long volatile; | ||||
| 	r10r11  named("r10", "r11") aliases(r10, r11) long volatile; | ||||
| 	r12r13  named("r12", "r13") aliases(r12, r13) long volatile; | ||||
| 	r14r15  named("r14", "r15") aliases(r14, r15) long volatile; | ||||
| 	r24r25  named("r24", "r25") aliases(r24, r25) long volatile; | ||||
| 	r2r3    named("r2", "r3")   aliases(r2,  r3)  long volatile lret; | ||||
| 
 | ||||
| 	r17r18  named("r17", "r18") aliases(r17, r18) long; | ||||
| 	r19r20  named("r19", "r20") aliases(r19, r20) long; | ||||
| 	r21r22  named("r21", "r22") aliases(r21, r22) long; | ||||
| 
 | ||||
| 	f0                                            float volatile fret; | ||||
| 	f1                                            float volatile; | ||||
| 	f2                                            float volatile; | ||||
| 	f3                                            float volatile; | ||||
| 	f4                                            float volatile; | ||||
| 	f5                                            float volatile; | ||||
| 	f6                                            float volatile; | ||||
| 	f7                                            float volatile; | ||||
| 	f8                                            float volatile; | ||||
| 	f9                                            float volatile; | ||||
| 	f10                                           float volatile; | ||||
| 	f11                                           float volatile; | ||||
| 	f12                                           float volatile; | ||||
| 	f13                                           float volatile; | ||||
| 	f14                                           float volatile; | ||||
| 	f15                                           float volatile; | ||||
| 	f16                                           float volatile; | ||||
| 	f17                                           float volatile; | ||||
| 	f18                                           float volatile; | ||||
| 	f19                                           float volatile; | ||||
| 
 | ||||
| 	f20                                           float; | ||||
| 	f21                                           float; | ||||
| 	f22                                           float; | ||||
| 	f23                                           float; | ||||
| 	f24                                           float; | ||||
| 	f25                                           float; | ||||
| 	f26                                           float; | ||||
| 	f27                                           float; | ||||
| 	f28                                           float; | ||||
| 	f29                                           float; | ||||
|     /* f30 and f31 is used by the compiler as a temporary. */ | ||||
| 
 | ||||
| 	d0  named("f0")  aliases(f0, f1)              double volatile dret; | ||||
| 	d2  named("f2")  aliases(f2, f3)              double volatile; | ||||
| 	d4  named("f4")  aliases(f4, f5)              double volatile; | ||||
| 	d6  named("f6")  aliases(f6, f7)              double volatile; | ||||
| 	d8  named("f8")  aliases(f8, f9)              double volatile; | ||||
| 	d10 named("f10") aliases(f10, f11)            double volatile; | ||||
| 	d12 named("f12") aliases(f12, f13)            double volatile; | ||||
| 	d14 named("f14") aliases(f14, f15)            double volatile; | ||||
| 	d16 named("f16") aliases(f16, f17)            double volatile; | ||||
| 	d18 named("f18") aliases(f18, f19)            double volatile; | ||||
| 
 | ||||
| 	d20 named("f20") aliases(f20, f21)            double; | ||||
| 	d22 named("f22") aliases(f22, f23)            double; | ||||
| 	d24 named("f24") aliases(f24, f25)            double; | ||||
| 	d26 named("f26") aliases(f26, f27)            double; | ||||
| 	d28 named("f28") aliases(f28, f29)            double; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| DECLARATIONS | ||||
| 
 | ||||
|     ubyteX;   /* bottom 8 bits valid, the rest undefined */ | ||||
|     ubyte0;   /* bottom 8 bits valid, the rest 0 */ | ||||
|     ushortX;  /* bottom 16 bits valid, the rest undefined */ | ||||
|     ushort0;  /* bottom 16 bits valid, the rest 0 */ | ||||
| 
 | ||||
| 	address fragment; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| PATTERNS | ||||
| 
 | ||||
| /* Special */ | ||||
| 
 | ||||
| 	PAIR(BLOCK.I, BLOCK.I); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Miscellaneous special things */ | ||||
| 
 | ||||
| 	PUSH.I(in:(int)reg) | ||||
| 		emit "addiu sp, sp, -4" | ||||
| 		emit "sw %in, 0(sp)" | ||||
| 		cost 8; | ||||
| 
 | ||||
|     PUSH.L(in:(long)reg) | ||||
|         emit "addiu sp, sp, -8" | ||||
|         emit "sw %in.0, 0(sp)" | ||||
|         emit "sw %in.1, 4(sp)" | ||||
|         cost 12; | ||||
| 
 | ||||
| 	PUSH.F(in:(float)reg) | ||||
| 		emit "addiu sp, sp, -4" | ||||
| 		emit "swc1 %in, 0(sp)" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	PUSH.D(in:(double)reg) | ||||
| 		emit "addiu sp, sp, -8" | ||||
| 		emit "sdc1 %in, 0(sp)" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	out:(int)reg = POP.I | ||||
| 		emit "lw %out, 0(sp)" | ||||
|         emit "addiu sp, sp, 4" | ||||
| 		cost 8; | ||||
| 
 | ||||
|     out:(long)reg = POP.L | ||||
|         emit "lw %out.0, 4(sp)" | ||||
|         emit "lw %out.1, 0(sp)" | ||||
|         emit "addiu sp, sp, 8" | ||||
|         cost 12; | ||||
| 
 | ||||
| 	out:(float)reg = POP.F | ||||
| 		emit "lwc1 %out, 0(sp)" | ||||
| 		emit "addiu sp, sp, 4" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	out:(double)reg = POP.D | ||||
| 		emit "ldc1 %out, 0(sp)" | ||||
| 		emit "addiu sp, sp, 8" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	SETRET.I(in:(iret)reg) | ||||
| 		emit "! setret.i" | ||||
| 		cost 1; | ||||
| 
 | ||||
|     SETRET.L(in:(lret)reg) | ||||
|         emit "! setret.l" | ||||
|         cost 1; | ||||
| 
 | ||||
| 	SETRET.F(in:(fret)reg) | ||||
| 		emit "! setret.f" | ||||
| 		cost 1; | ||||
| 
 | ||||
| 	SETRET.D(in:(dret)reg) | ||||
| 		emit "! setret.d" | ||||
| 		cost 1; | ||||
| 
 | ||||
| 	STACKADJUST.I(delta:CONST.I) | ||||
|         when signed_constant(%delta, 16) | ||||
| 		emit "addiu sp, sp, $delta" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	STACKADJUST.I(in:(int)reg) | ||||
| 		emit "addu sp, sp, %in" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	STACKADJUST.I(NEG.I(in:(int)reg)) | ||||
| 		emit "subu sp, sp, %in" | ||||
| 		cost 4; | ||||
| 
 | ||||
|     out:(int)reg = GETFP.I | ||||
|         emit "mov %out, fp" | ||||
|         cost 4; | ||||
| 
 | ||||
|     SETFP.I(in:(int)reg) | ||||
|         emit "mov fp, %in" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)reg = CHAINFP.I(in:(int)reg) | ||||
|         emit "lw %out, 0(%in)" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)reg = FPTOAB.I(GETFP.I) | ||||
|         emit "addiu %out, fp, 8" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)reg = FPTOAB.I(in:(int)reg) | ||||
|         emit "addiu %out, %in, 8" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)reg = FPTOLB.I(in:(int)reg) | ||||
|         with %out == %in | ||||
|         cost 1; | ||||
| 
 | ||||
|     out:(int)reg = GETSP.I | ||||
|         emit "mov %out, sp" | ||||
|         cost 4; | ||||
| 
 | ||||
|     SETSP.I(in:(int)reg) | ||||
|         emit "mov sp, %in" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)reg = ANY.I | ||||
|         cost 1; | ||||
| 
 | ||||
|     out:(long)reg = ANY.L | ||||
|         cost 1; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Memory operations */ | ||||
| 
 | ||||
|     /* Stores */ | ||||
| 
 | ||||
| 	STORE.L(addr:address, value:(long)reg) | ||||
| 		emit "sw %value.0, 0+%addr" | ||||
| 		emit "sw %value.1, 4+%addr" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	STORE.I(addr:address, value:(int)reg) | ||||
| 		emit "sw %value, %addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
|     STORE.I(label:LABEL.I, value:(int)reg) | ||||
|         emit "lui at, ha16[$label]" | ||||
|         emit "sw %value, lo16[$label] (at)" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	STOREH.I(addr:address, value:(int)ushortX) | ||||
| 		emit "sh %value, %addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
|     STOREH.I(label:LABEL.I, value:(int)reg) | ||||
|         emit "lui at, ha16[$label]" | ||||
|         emit "sh %value, lo16[$label] (at)" | ||||
| 		cost 8; | ||||
| 
 | ||||
|     STOREB.I(addr:address, value:(int)ubyteX) | ||||
| 		emit "sb %value, %addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
|     STOREB.I(label:LABEL.I, value:(int)reg) | ||||
|         emit "lui at, ha16[$label]" | ||||
|         emit "sb %value, lo16[$label] (at)" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	STORE.F(addr:address, value:(float)reg) | ||||
| 		emit "swc1 %value, %addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
|     STORE.F(label:LABEL.I, value:(int)reg) | ||||
|         emit "lui at, ha16[$label]" | ||||
|         emit "swc1 %value, lo16[$label] (at)" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	STORE.D(addr:address, value:(double)reg) | ||||
| 		emit "sdc1 %value, %addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
|     STORE.D(label:LABEL.I, value:(int)reg) | ||||
|         emit "lui at, ha16[$label]" | ||||
|         emit "sdc1 %value, lo16[$label] (at)" | ||||
| 		cost 8; | ||||
| 
 | ||||
|     /* Loads */ | ||||
| 
 | ||||
| 	out:(int)reg = LOAD.I(addr:address) | ||||
| 		emit "lw %out, %addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(int)reg = LOAD.I(label:LABEL.I) | ||||
| 		emit "lui at, ha16[$label]" | ||||
|         emit "lw %out, lo16[$label] (at)" | ||||
| 		cost 8; | ||||
| 
 | ||||
|     /* We can't just load directly because %out.0 and %addr might share | ||||
|      * a register, resulting in %addr being corrupted before %out.1 is | ||||
|      * loaded. */ | ||||
|     out:(long)reg = LOAD.L(addr:address) | ||||
|         emit "lw at, 0+%addr" | ||||
|         emit "lw %out.1, 4+%addr" | ||||
|         emit "mov %out.0, at" | ||||
|         cost 12; | ||||
| 
 | ||||
| 	out:(int)ushort0 = LOADH.I(addr:address) | ||||
| 		emit "lhu %out, %addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(int)reg = EXTENDH.I(LOADH.I(addr:address)) | ||||
| 		emit "lh %out, %addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(int)ushort0 = LOADH.I(label:LABEL.I) | ||||
| 		emit "lui at, ha16[$label]" | ||||
|         emit "lhu %out, lo16[$label] (at)" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	out:(int)reg = EXTENDH.I(LOADH.I(label:LABEL.I)) | ||||
| 		emit "lui at, ha16[$label]" | ||||
|         emit "lh %out, lo16[$label] (at)" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	out:(int)ubyte0 = LOADB.I(addr:address) | ||||
| 		emit "lbu %out, %addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(int)reg = EXTENDB.I(LOADB.I(addr:address)) | ||||
| 		emit "lb %out, %addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(int)ubyte0 = LOADB.I(label:LABEL.I) | ||||
| 		emit "lui at, ha16[$label]" | ||||
|         emit "lbu %out, lo16[$label] (at)" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	out:(int)reg = EXTENDB.I(LOADB.I(label:LABEL.I)) | ||||
| 		emit "lui at, ha16[$label]" | ||||
|         emit "lb %out, lo16[$label] (at)" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	out:(float)reg = LOAD.F(addr:address) | ||||
| 		emit "lwc1 %out, %addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(float)reg = LOAD.F(label:LABEL.I) | ||||
| 		emit "lui at, ha16[$label]" | ||||
|         emit "lwc1 %out, lo16[$label] (at)" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	out:(double)reg = LOAD.D(addr:address) | ||||
| 		emit "ldc1 %out, %addr" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(double)reg = LOAD.D(label:LABEL.I) | ||||
| 		emit "lui at, ha16[$label]" | ||||
|         emit "ldc1 %out, lo16[$label] (at)" | ||||
| 		cost 8; | ||||
| 
 | ||||
|     /* ubyte intrinsics */ | ||||
| 
 | ||||
|     out:(int)ubyteX = in:(int)ubyte0 | ||||
|         with %out == %in | ||||
|         emit "! ubyte0 -> ubyteX" | ||||
|         cost 1; | ||||
| 
 | ||||
|     out:(int)ubyte0 = in:(int)ubyteX | ||||
|         emit "andiu %out, %in, 0xff ! ubyteX -> ubyte0" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)reg = in:(int)ubyte0 | ||||
|         with %out == %in | ||||
|         emit "! ubyte0 -> reg" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)ubyteX = in:(int)reg | ||||
|         with %out == %in | ||||
|         emit "! reg -> ubyteX" | ||||
|         cost 1; | ||||
| 
 | ||||
|     /* ushort intrinsics */ | ||||
| 
 | ||||
|     out:(int)ushortX = in:(int)ushort0 | ||||
|         with %out == %in | ||||
|         emit "! ushort0 -> ushortX" | ||||
|         cost 1; | ||||
| 
 | ||||
|     out:(int)ushort0 = in:(int)ushortX | ||||
|         emit "andiu %out, %in, 0xffff ! ushortX -> ushort0" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)reg = in:(int)ushort0 | ||||
|         with %out == %in | ||||
|         emit "! ushort0 -> reg" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)ushortX = in:(int)reg | ||||
|         with %out == %in | ||||
|         emit "! reg -> ushortX" | ||||
|         cost 1; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Extensions and conversions */ | ||||
| 
 | ||||
|     out:(int)reg = EXTENDB.I(in:(int)reg) | ||||
|         emit "seb %out, %in" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)reg = EXTENDH.I(in:(int)reg) | ||||
|         emit "seh %out, %in" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)reg = FROMSI.I(in:(int)reg) | ||||
|         with %out == %in | ||||
|         emit "! FROMSI.I(int) -> int" | ||||
|         cost 1; | ||||
| 
 | ||||
|     out:(int)reg = FROMUI.I(in:(int)reg) | ||||
|         with %out == %in | ||||
|         emit "! FROMUI.I(int) -> int" | ||||
|         cost 1; | ||||
| 
 | ||||
|     out:(long)reg = FROMSI.L(in:(int)reg) | ||||
|         emit "mov %out.0, %in" | ||||
|         emit "sra %out.1, %in, 31" | ||||
|         cost 8; | ||||
| 
 | ||||
|     out:(long)reg = FROMUI.L(in:(int)reg) | ||||
|         emit "mr %out.0, %in" | ||||
|         emit "li %out.1, 0" | ||||
|         cost 8; | ||||
| 
 | ||||
|     out:(lret)reg = FROMIPAIR.L(in1:(int)reg, in2:(int)reg) | ||||
|         with preserved(%in1), preserved(%in2) | ||||
|         emit "mov %out.0, %in1" | ||||
|         emit "mov %out.1, %in2" | ||||
|         cost 8; | ||||
|      | ||||
|     out:(int)reg = FROML0.I(in:(long)reg) | ||||
|         emit "mov %out, %in.0" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)reg = FROML1.I(in:(long)reg) | ||||
|         emit "mov %out, %in.1" | ||||
|         cost 4; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Locals */ | ||||
| 
 | ||||
| 	out:(int)reg = in:LOCAL.I | ||||
| 		emit "addiu %out, fp, $in" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	address = in:LOCAL.I | ||||
| 		emit "$in(fp)"; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Memory addressing modes */ | ||||
| 
 | ||||
| 	address = ADD.I(addr:(int)reg, offset:CONST.I) | ||||
|         when signed_constant(%offset, 16) | ||||
| 		emit "$offset(%addr)"; | ||||
| 
 | ||||
| 	address = addr:(int)reg | ||||
| 		emit "0(%addr)"; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Branches */ | ||||
| 
 | ||||
| 	JUMP(addr:BLOCK.I) | ||||
| 		emit "b $addr" | ||||
|         emit "nop" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	FARJUMP(addr:LABEL.I) | ||||
|         with corrupted(volatile) | ||||
| 		emit "j $addr" | ||||
|         emit "nop" | ||||
| 		cost 8; | ||||
| 
 | ||||
|     JUMP(dest:(int)reg) | ||||
|         emit "jr %dest" | ||||
|         emit "nop" | ||||
|         cost 8; | ||||
| 
 | ||||
| 	CJUMPEQ(left:(int)reg, PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         emit "beq %left, zero, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 16; | ||||
| 
 | ||||
| 	CJUMPLT(left:(int)reg, PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         emit "bltz %left, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 20; | ||||
| 
 | ||||
| 	CJUMPLE(left:(int)reg, PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         emit "blez %left, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 20; | ||||
| 
 | ||||
|     #define CALLLABEL(insn) \ | ||||
|         insn (dest:LABEL.I) \ | ||||
|             with corrupted(volatile) \ | ||||
|             emit "jal $dest" \ | ||||
|             emit "nop" \ | ||||
|             cost 8; | ||||
| 
 | ||||
|     CALLLABEL(CALL) | ||||
|     out:(iret)reg = CALLLABEL(CALL.I) | ||||
|     out:(lret)reg = CALLLABEL(CALL.L) | ||||
| 
 | ||||
|     #define CALLINDIRECT(insn) \ | ||||
|         insn (dest:(int)reg) \ | ||||
|             with corrupted(volatile) \ | ||||
|             emit "jalr %dest" \ | ||||
|             emit "nop" \ | ||||
|             cost 8; | ||||
| 
 | ||||
|     CALLINDIRECT(CALL) | ||||
|     out:(iret)reg = CALLINDIRECT(CALL.I) | ||||
|     out:(lret)reg = CALLINDIRECT(CALL.L) | ||||
| 
 | ||||
|     JUMP(dest:LABEL.I) | ||||
|         emit "b $dest" | ||||
|         emit "nop" | ||||
|         cost 8; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Conditional branches */ | ||||
| 
 | ||||
|     /* Normally COMPARE returns a condition code (in a flags register) which the CJUMP | ||||
|      * instructions can then operate on. But MIPS doesn't have a flags register, and | ||||
|      * requires you to know what condition you're testing for when you do the comparison. | ||||
|      * mcg doesn't like this much and we have to list every combination individually. | ||||
|      */ | ||||
| 
 | ||||
|     /* Signed integer comparisons against zero */ | ||||
| 
 | ||||
| 	CJUMPEQ(COMPARESI.I(left:(int)reg, zero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         when specific_constant(%zero, 0) | ||||
|         emit "beq %left, zero, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 16; | ||||
| 
 | ||||
| 	CJUMPLT(COMPARESI.I(left:(int)reg, zero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         when specific_constant(%zero, 0) | ||||
|         emit "bltz %left, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 16; | ||||
| 
 | ||||
| 	CJUMPLE(COMPARESI.I(left:(int)reg, zero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         when specific_constant(%zero, 0) | ||||
|         emit "blez %left, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 16; | ||||
| 
 | ||||
|     /* Signed integer comparisons against a constant */ | ||||
| 
 | ||||
| 	CJUMPEQ(COMPARESI.I(left:(int)reg, value:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         emit "li at, $value" | ||||
|         emit "beq %left, at, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 20; | ||||
| 
 | ||||
| 	CJUMPLT(COMPARESI.I(left:(int)reg, value:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         when signed_constant(%value, 16) | ||||
|         emit "slti at, %left, $value" | ||||
|         emit "bne at, zero, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 20; | ||||
| 
 | ||||
| 	CJUMPLE(COMPARESI.I(left:(int)reg, value:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         when constant_within_inclusive_range(%value, -0x8000, 0x7ffe) | ||||
|         emit "slti at, %left, 1+$value" | ||||
|         emit "bne at, zero, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 20; | ||||
| 
 | ||||
|     /* Signed integer comparisons against a register */ | ||||
| 
 | ||||
| 	CJUMPEQ(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         emit "beq %left, %right, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 20; | ||||
| 
 | ||||
| 	CJUMPLT(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         emit "slt at, %left, %right" | ||||
|         emit "bne at, zero, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 20; | ||||
| 
 | ||||
| 	CJUMPLE(COMPARESI.I(left:(int)reg, right:(int)reg), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         emit "slt at, %right, %left" | ||||
|         emit "beq at, zero, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 20; | ||||
| 
 | ||||
|     /* Unsigned integer comparisons against a constant */ | ||||
| 
 | ||||
|     CJUMPLT(COMPARESI.I(COMPAREUI.I(left:(int)reg, right:CONST.I), alwayszero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         when signed_constant(%right, 16) | ||||
|         when specific_constant(%alwayszero, 0) | ||||
|         emit "sltiu at, %left, $right" | ||||
|         emit "bne at, zero, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 16; | ||||
| 
 | ||||
|     CJUMPLE(COMPARESI.I(COMPAREUI.I(left:(int)reg, right:CONST.I), alwayszero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         when constant_within_inclusive_range(%right, -0x8000, 0x7ffe) | ||||
|         when specific_constant(%alwayszero, 0) | ||||
|         emit "sltiu at, %left, 1+$right" | ||||
|         emit "bne at, zero, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 20; | ||||
| 
 | ||||
|     /* Unsigned integer comparisons against registers */ | ||||
| 
 | ||||
|     CJUMPEQ(COMPARESI.I(COMPAREUI.I(left:(int)reg, right:(int)reg), alwayszero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         when specific_constant(%alwayszero, 0) | ||||
|         emit "beq %left, %right, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 16; | ||||
| 
 | ||||
|     CJUMPLT(COMPARESI.I(COMPAREUI.I(left:(int)reg, right:(int)reg), alwayszero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         when specific_constant(%alwayszero, 0) | ||||
|         emit "sltu at, %left, %right" | ||||
|         emit "bne at, zero, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 16; | ||||
| 
 | ||||
|     CJUMPLE(COMPARESI.I(COMPAREUI.I(left:(int)reg, right:(int)reg), alwayszero:CONST.I), PAIR(true:BLOCK.I, false:BLOCK.I)) | ||||
|         when specific_constant(%alwayszero, 0) | ||||
|         emit "sltu at, %right, %left" | ||||
|         emit "beq at, zero, $true" | ||||
|         emit "nop" | ||||
|         emit "b $false" | ||||
|         emit "nop" | ||||
|         cost 16; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Comparisons */ | ||||
| 
 | ||||
| 	/* The COMPARE nodes return tristate integer values; -1, 0 or 1. */ | ||||
| 
 | ||||
|     out:(int)reg = COMPARESI.I(left:(int)reg, right:(int)reg) | ||||
|         with preserved(%left), preserved(%right) | ||||
|         emit "slt at, %left, %right" | ||||
|         emit "bne at, zero, 1f" | ||||
|         emit "li %out, -1" /* delay slot */ | ||||
|         emit "slt %out, %right, %left" | ||||
|         emit "1:" | ||||
|         cost 20; | ||||
| 
 | ||||
|     out:(int)reg = COMPAREUI.I(left:(int)reg, right:(int)reg) | ||||
|         with preserved(%left), preserved(%right) | ||||
|         emit "sltu at, %left, %right" | ||||
|         emit "bne at, zero, 1f" | ||||
|         emit "li %out, -1" /* delay slot */ | ||||
|         emit "sltu %out, %right, %left" | ||||
|         emit "1:" | ||||
|         cost 20; | ||||
| 
 | ||||
|     out:(iret)reg = COMPAREUL.I(left:(lret)reg, right:(lret1)reg) | ||||
|         emit "jal .compareul" | ||||
|         emit "nop" | ||||
|         cost 30; | ||||
| 
 | ||||
|     out:(int)reg = COMPAREF.I(left:(float)reg, right:(float)reg) | ||||
|         with preserved(%left), preserved(%right) | ||||
|         emit "c.lt.s 0, %left, %right" | ||||
|         emit "li %out, -1" | ||||
|         emit "bc1t 0, 1f" | ||||
|         emit "nop" | ||||
|         emit "c.lt.s 0, %right, %left" | ||||
|         emit "li %out, 1" | ||||
|         emit "movf %out, zero, 0" | ||||
|         emit "1:" | ||||
|         cost 28; | ||||
| 
 | ||||
|     out:(int)reg = COMPARED.I(left:(double)reg, right:(double)reg) | ||||
|         with preserved(%left), preserved(%right) | ||||
|         emit "c.lt.d 0, %left, %right" | ||||
|         emit "li %out, -1" | ||||
|         emit "bc1t 0, 1f" | ||||
|         emit "nop" | ||||
|         emit "c.lt.d 0, %right, %left" | ||||
|         emit "li %out, 1" | ||||
|         emit "movf %out, zero, 0" | ||||
|         emit "1:" | ||||
|         cost 28; | ||||
| 
 | ||||
| /* Booleans */ | ||||
| 
 | ||||
| 	/* If 0 then 1, else 0 */ | ||||
| 	out:(int)reg = IFEQ.I(in:(int)reg) | ||||
| 		emit "sltiu %out, %in, 1" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	/* If -1 then 1, else 0 */ | ||||
| 	out:(int)reg = IFLT.I(in:(int)reg) | ||||
| 		emit "srl %out, %in, 31" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	/* If 1 or 0 then 1, else 0 */ | ||||
| 	out:(int)reg = IFLE.I(in:(int)reg) | ||||
| 		emit "slti %out, %in, 1" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* Conversions */ | ||||
| 
 | ||||
| #if 0 | ||||
|     out:(int)reg = CIU44(in:(int)reg) | ||||
|         with %out == %in | ||||
|         emit "! ciu44" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)reg = CUI44(in:(int)reg) | ||||
|         with %out == %in | ||||
|         emit "! cui44" | ||||
|         cost 4; | ||||
| #endif | ||||
| 
 | ||||
| /* ALU operations */ | ||||
| 
 | ||||
| 	/* reg + reg */ | ||||
|     #define ALUR(name, instr) \ | ||||
|         out:(int)reg = name(left:(int)reg, right:(int)reg) \ | ||||
|             emit instr " %out, %left, %right"              \ | ||||
|             cost 4;                                        \ | ||||
| 
 | ||||
| 	/* reg + const */ | ||||
|     #define ALUC(name, instr) \ | ||||
|         out:(int)reg = name(left:(int)reg, right:CONST.I)  \ | ||||
|             when signed_constant(%right, 16)               \ | ||||
|             emit instr " %out, %left, $right"              \ | ||||
|             cost 4;                                        \ | ||||
| 
 | ||||
| 	/* const + reg */ | ||||
|     #define ALUC_reversed(name, instr) \ | ||||
|         out:(int)reg = name(left:CONST.I, right:(int)reg)  \ | ||||
|             when signed_constant(%left, 16)                \ | ||||
|             emit instr " %out, %right, $left"              \ | ||||
|             cost 4;                                        \ | ||||
| 
 | ||||
| 	/* reg + const AND const + reg */ | ||||
|     #define ALUCC(name, instr) \ | ||||
|         ALUC(name, instr) \ | ||||
|         ALUC_reversed(name, instr) | ||||
| 
 | ||||
|     ALUR(ADD.I, "addu") | ||||
|     ALUCC(ADD.I, "addiu") | ||||
| 
 | ||||
| 	out:(int)reg = SUB.I(left:(int)reg, right:(int)reg) | ||||
| 		emit "subu %out, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(int)reg = SUB.I(left:(int)reg, right:CONST.I) | ||||
| 		emit "addiu %out, %left, -[$right]" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(int)reg = DIV.I(left:(int)reg, right:(int)reg) | ||||
| 		emit "div %left, %right" | ||||
| 		emit "mflo %out" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	out:(int)reg = DIVU.I(left:(int)reg, right:(int)reg) | ||||
| 		emit "divu %left, %right" | ||||
| 		emit "mflo %out" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	out:(int)reg = MOD.I(left:(int)reg, right:(int)reg) | ||||
| 		emit "div %left, %right" | ||||
| 		emit "mfhi %out" | ||||
| 		cost 8; | ||||
| 
 | ||||
| 	out:(int)reg = MODU.I(left:(int)reg, right:(int)reg) | ||||
| 		emit "divu %left, %right" | ||||
| 		emit "mfhi %out" | ||||
| 		cost 8; | ||||
| 
 | ||||
|     ALUR(MUL.I, "mul") | ||||
| 
 | ||||
|     ALUR(ASL.I, "sllv") | ||||
|     ALUC(ASL.I, "sll") | ||||
|     ALUR(ASR.I, "srav") | ||||
|     ALUC(ASR.I, "sra") | ||||
| 
 | ||||
|     ALUR(LSL.I, "sllv") | ||||
|     ALUC(LSL.I, "sll") | ||||
|     ALUR(LSR.I, "srlv") | ||||
|     ALUC(LSR.I, "srl") | ||||
| 
 | ||||
|     out:(int)reg = NEG.I(left:(int)reg) | ||||
|         emit "subu %out, zero, %left" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)reg = NOT.I(in:(int)reg) | ||||
|         emit "nor %out, %in, %in" | ||||
|         cost 4; | ||||
| 
 | ||||
|     ALUR(AND.I, "and") | ||||
|     ALUCC(AND.I, "andi") | ||||
| 
 | ||||
|     ALUR(OR.I, "or") | ||||
|     ALUCC(OR.I, "ori") | ||||
| 
 | ||||
|     ALUR(EOR.I, "xor") | ||||
|     ALUCC(EOR.I, "xori") | ||||
| 
 | ||||
| 	out:(int)reg = value:LABEL.I | ||||
| 		emit "lui %out, hi16[$value]" | ||||
|         emit "ori %out, %out, lo16[$value]" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(int)reg = value:BLOCK.I | ||||
| 		emit "lui %out, hi16[$value]" | ||||
|         emit "ori %out, %out, lo16[$value]" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(int)reg = value:CONST.I | ||||
| 		emit "li %out, $value" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /* FPU operations */ | ||||
| 
 | ||||
| 	/* Doubles */ | ||||
| 
 | ||||
| 	out:(double)reg = ADDF.D(left:(double)reg, right:(double)reg) | ||||
| 		emit "add.d %out, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(double)reg = SUBF.D(left:(double)reg, right:(double)reg) | ||||
| 		emit "sub.d %out, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(double)reg = MULF.D(left:(double)reg, right:(double)reg) | ||||
| 		emit "mul.d %out, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(double)reg = DIVF.D(left:(double)reg, right:(double)reg) | ||||
| 		emit "div.d %out, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(double)reg = NEGF.D(left:(double)reg) | ||||
| 		emit "neg.d %out, %left" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(double)reg = FROMSI.D(in:(int)reg) | ||||
| 		emit "mtc1 %in, %out" /* mtc1 has reversed parameters */ | ||||
| 		emit "cvt.d.w %out, %out" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(dret)reg = FROMUI.D(in:(iret)reg) | ||||
| 		emit "jal .c_ui_d" | ||||
| 		emit "nop" | ||||
| 		cost 30; | ||||
| 
 | ||||
| 	out:(int)reg = FROMSD.I(in:(double)reg) | ||||
|         emit "trunc.w.d f30, %in" | ||||
|         emit "mfc1 %out, f30" | ||||
|         cost 8; | ||||
| 
 | ||||
| 	out:(lret)reg = FROMSD.L(in:(dret)reg) | ||||
| 		emit "jal .c_sd_l" | ||||
| 		emit "nop" | ||||
| 		cost 30; | ||||
| 
 | ||||
| 	out:(iret)reg = FROMUD.I(in:(dret)reg) | ||||
| 		with corrupted(dret) | ||||
| 		emit "jal .c_ud_i" | ||||
| 		emit "nop" | ||||
|         cost 30; | ||||
| 
 | ||||
|     out:(double)reg = COPYL.D(in:(long)reg) | ||||
|         emit "mtc1 %in.0, %out" /* mtc1 has reversed parameters */ | ||||
|         emit "mthc1 %in.1, %out" /* mtc1 has reversed parameters */ | ||||
|         cost 8; | ||||
| 
 | ||||
|     out:(long)reg = COPYD.L(in:(double)reg) | ||||
|         emit "mfc1 %out.0, %in" | ||||
|         emit "mfhc1 %out.1, %in" | ||||
|         cost 8; | ||||
| 
 | ||||
| 	/* Floats */ | ||||
| 
 | ||||
| 	out:(float)reg = ADDF.F(left:(float)reg, right:(float)reg) | ||||
| 		emit "add.d %out, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(float)reg = SUBF.F(left:(float)reg, right:(float)reg) | ||||
| 		emit "sub.d %out, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(float)reg = MULF.F(left:(float)reg, right:(float)reg) | ||||
| 		emit "mul.d %out, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(float)reg = DIVF.F(left:(float)reg, right:(float)reg) | ||||
| 		emit "div.d %out, %left, %right" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(float)reg = NEGF.F(left:(float)reg) | ||||
| 		emit "neg.s %out, %left" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(float)reg = FROMSI.F(in:(int)reg) | ||||
| 		emit "mtc1 %in, %out" /* mtc1 has reversed parameters */ | ||||
| 		emit "cvt.s.w %out, %out" | ||||
| 		cost 4; | ||||
| 
 | ||||
| 	out:(int)reg = FROMSF.I(in:(float)reg) | ||||
|         emit "trunc.w.s f30, %in" | ||||
|         emit "mfc1 %out, f30" | ||||
|         cost 8; | ||||
| 
 | ||||
| 	out:(lret)reg = FROMSF.L(in:(fret)reg) | ||||
| 		emit "jal .c_sf_l" | ||||
| 		emit "nop" | ||||
| 		cost 30; | ||||
| 
 | ||||
| 	out:(fret)reg = FROMUI.F(in:(iret)reg) | ||||
| 		emit "jal .c_ui_f" | ||||
| 		emit "nop" | ||||
| 		cost 30; | ||||
| 
 | ||||
| 	out:(iret)reg = FROMUF.I(in:(fret)reg) | ||||
| 		with corrupted(fret) | ||||
| 		emit "jal .c_uf_i" | ||||
| 		emit "nop" | ||||
|         cost 30; | ||||
| 
 | ||||
|     out:(float)reg = COPYI.F(in:(int)reg) | ||||
|         emit "mtc1 %in, %out" /* mtc1 has reversed parameters */ | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(int)reg = COPYF.I(in:(float)reg) | ||||
|         emit "mfc1 %out, %in" | ||||
|         cost 4; | ||||
| 
 | ||||
|     out:(float)reg = value:CONST.F | ||||
|         when specific_constant(%value, 0) | ||||
|         emit "mtc1 zero, %out" /* mtc1 has reversed parameters */ | ||||
|         cost 4; | ||||
| 
 | ||||
| /* vim: set sw=4 ts=4 expandtab : */ | ||||
| 
 | ||||
							
								
								
									
										47
									
								
								mach/mips/top/table
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								mach/mips/top/table
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | |||
| 
 | ||||
| /* MIPS table for ACK target optimizer */ | ||||
| 
 | ||||
| MAXOP 5; | ||||
| LABEL_STARTER '.'; | ||||
| 
 | ||||
| %%; | ||||
| 
 | ||||
| X, Y, Z                      { TRUE }; | ||||
| R                            { TRUE }; | ||||
| 
 | ||||
| %%; | ||||
| 
 | ||||
| /* Whitespace is significant here! */ | ||||
| 
 | ||||
| addiu R, R, X : addiu R, R, Y { plus(X, Y, Z) } -> addiu R, R, Z ; | ||||
| 
 | ||||
| addiu X, X, 0                -> ; | ||||
| 
 | ||||
| b X : nop : labdef X         -> labdef X ; | ||||
| 
 | ||||
| %%; | ||||
| 
 | ||||
| /* Does it fit a signed 16-bit integer? */ | ||||
| static int fits16(long l) { | ||||
|         return l >= -32768 && l <= 32767; | ||||
| } | ||||
| 
 | ||||
| /* Tries sum = a + b with signed 16-bit integers. */ | ||||
| int plus(const char *a, const char *b, const char *sum) | ||||
| { | ||||
|         long la, lb, lsum; | ||||
|         char *end; | ||||
| 
 | ||||
|         la = strtol(a, &end, 10); | ||||
|         if (*a == '\0' || *end != '\0' || !fits16(la)) | ||||
|                 return 0; | ||||
|         lb = strtol(b, &end, 10); | ||||
|         if (*b == '\0' || *end != '\0' || !fits16(lb)) | ||||
|                 return 0; | ||||
| 
 | ||||
|         lsum = la + lb; | ||||
|         if (!fits16(lsum)) | ||||
|                 return 0; | ||||
|         snprintf(sum, 7, "%ld", lsum); | ||||
|         return 1; | ||||
| } | ||||
|  | @ -12,6 +12,7 @@ | |||
| #define WORDS_REVERSED | ||||
| #define LISTING | ||||
| #define RELOCATION | ||||
| #define PDPFLOAT | ||||
| #undef ISALPHA | ||||
| #define ISALPHA(c)	(isalpha(c) || c == '_' || c == '.' || c == '~') | ||||
| #undef ISALNUM | ||||
|  |  | |||
|  | @ -128,7 +128,7 @@ struct hop* platform_epilogue(void) | |||
| 	return hop; | ||||
| } | ||||
| 
 | ||||
| struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest) | ||||
| struct hop* platform_move(struct basicblock* bb, struct vreg* vreg, struct hreg* src, struct hreg* dest) | ||||
| { | ||||
|     struct hop* hop = new_hop(bb, NULL); | ||||
| 
 | ||||
|  |  | |||
|  | @ -2,7 +2,8 @@ include("first/yacc.lua") | |||
| 
 | ||||
| definerule("build_as", | ||||
| 	{ | ||||
| 		arch = { type="string" } | ||||
| 		arch = { type="string" }, | ||||
| 		deps = { type="targets", default={} }, | ||||
| 	}, | ||||
| 	function(e) | ||||
| 		-- Remember this is executed from the caller's directory; local | ||||
|  | @ -25,6 +26,7 @@ definerule("build_as", | |||
| 				"mach/proto/as/comm1.h", | ||||
| 				"h+emheaders", | ||||
| 				archlib, | ||||
| 				e.deps, | ||||
| 			}, | ||||
| 		} | ||||
| 
 | ||||
|  | @ -42,8 +44,10 @@ definerule("build_as", | |||
| 			deps = { | ||||
| 				"h+emheaders", | ||||
| 				"modules/src/object+lib", | ||||
| 				"modules/src/flt_arith+lib", | ||||
| 				archlib, | ||||
| 				yaccfiles | ||||
| 				yaccfiles, | ||||
| 				e.deps | ||||
| 			} | ||||
| 		} | ||||
| 	end | ||||
|  |  | |||
|  | @ -22,6 +22,7 @@ _include	<string.h> | |||
| #include	<stdio.h> | ||||
| #include	<stdlib.h> | ||||
| #include	<string.h> | ||||
| #include    <unistd.h> | ||||
| #endif | ||||
| 
 | ||||
| /* ========== ON/OFF options (use #define in mach0.c) ========== */ | ||||
|  |  | |||
|  | @ -153,6 +153,7 @@ void	 emit1(int); | |||
| void	 emit2(int); | ||||
| void	 emit4(long); | ||||
| void	 emitx(valu_t, int); | ||||
| void     emitf(int size, int negative); | ||||
| void	 emitstr(int); | ||||
| void	 ffreopen(char *, FILE *); | ||||
| FILE	*ffcreat(char *); | ||||
|  |  | |||
|  | @ -43,9 +43,11 @@ static item_t	*last_it, *o_it; | |||
| %token NUMBER2 | ||||
| %token NUMBER3 | ||||
| %token <y_valu> NUMBER | ||||
| %token NUMBERF | ||||
| %token DOT | ||||
| %token EXTERN | ||||
| %token <y_word> DATA | ||||
| %token <y_word> DATAF | ||||
| %token <y_word> ASCII | ||||
| %token SECTION | ||||
| %token COMMON | ||||
|  | @ -58,14 +60,6 @@ static item_t	*last_it, *o_it; | |||
| %token <y_word> LINE | ||||
| %token FILe | ||||
| %token <y_word> LIST | ||||
| %token OP_EQ | ||||
| %token OP_NE | ||||
| %token OP_LE | ||||
| %token OP_GE | ||||
| %token OP_LL | ||||
| %token OP_RR | ||||
| %token OP_OO | ||||
| %token OP_AA | ||||
| 
 | ||||
| %left OP_OO | ||||
| %left OP_AA | ||||
|  | @ -257,6 +251,7 @@ operation | |||
| 				DOTSCT->s_zero += $2; | ||||
| 			} | ||||
| 	|	DATA datalist | ||||
| 	|   DATAF dataflist | ||||
| 	|	ASCII STRING | ||||
| 			{	emitstr($1);} | ||||
| 	; | ||||
|  | @ -284,6 +279,23 @@ datalist | |||
| 				emitx($3.val, (int)$<y_word>0); | ||||
| 			} | ||||
| 	; | ||||
| 
 | ||||
| numberf | ||||
| 	:	NUMBERF | ||||
| 			{ | ||||
| 				emitf((int)$<y_word>-1, 0); | ||||
| 			} | ||||
| 	|	'-' NUMBERF | ||||
| 			{ | ||||
| 				emitf((int)$<y_word>-1, 1); | ||||
| 			} | ||||
| 	; | ||||
| 
 | ||||
| dataflist | ||||
| 	:   numberf | ||||
| 	|   dataflist ',' numberf | ||||
| 	; | ||||
| 
 | ||||
| expr	:	error | ||||
| 			{	serror("expr syntax err"); | ||||
| 				$$.val = 0; $$.typ = S_UND; | ||||
|  |  | |||
|  | @ -29,6 +29,8 @@ item_t	keytab[] = { | |||
| 	0,	DATA,		RELO1,	".data1", | ||||
| 	0,	DATA,		RELO2,	".data2", | ||||
| 	0,	DATA,		RELO4,	".data4", | ||||
| 	0,  DATAF,      4,      ".dataf4", | ||||
| 	0,  DATAF,      8,      ".dataf8", | ||||
| 	0,	ASCII,		0,		".ascii", | ||||
| 	0,	ASCII,		1,		".asciz", | ||||
| 	0,	ALIGN,		0,		".align", | ||||
|  |  | |||
|  | @ -5,26 +5,28 @@ | |||
|  */ | ||||
| /* @(#)comm5.c	1.1 */ | ||||
| 
 | ||||
| #include	"comm0.h" | ||||
| #include	"comm1.h" | ||||
| #include	"y.tab.h" | ||||
| #include "comm0.h" | ||||
| #include "comm1.h" | ||||
| #include "y.tab.h" | ||||
| 
 | ||||
| extern YYSTYPE	yylval; | ||||
| extern YYSTYPE yylval; | ||||
| 
 | ||||
| static void	readcode(int); | ||||
| static int	induo(int); | ||||
| static int	inident(int); | ||||
| static int	innumber(int); | ||||
| static int	instring(int); | ||||
| static int	inescape(void); | ||||
| static int	infbsym(const char *); | ||||
| static void readcode(int); | ||||
| static int induo(int); | ||||
| static int inident(int); | ||||
| static int innumber(int); | ||||
| static int instring(int); | ||||
| static int inescape(void); | ||||
| static int infbsym(const char*); | ||||
| 
 | ||||
| int | ||||
| yylex(void) | ||||
| static int maxstring = 0; | ||||
| 
 | ||||
| int yylex(void) | ||||
| { | ||||
| 	int c, c0, c1; | ||||
| 
 | ||||
| 	if (pass == PASS_1) { | ||||
| 	if (pass == PASS_1) | ||||
| 	{ | ||||
| 		/* scan the input file */ | ||||
| 		do | ||||
| 			c = nextchar(); | ||||
|  | @ -33,126 +35,150 @@ yylex(void) | |||
| 			c = inident(c); | ||||
| 		else if (isdigit(c)) | ||||
| 			c = innumber(c); | ||||
| 		else switch (c) { | ||||
| 		case '=': | ||||
| 		case '<': | ||||
| 		case '>': | ||||
| 		case '|': | ||||
| 		case '&': | ||||
| 			c = induo(c); break; | ||||
| 		case ASC_SQUO: | ||||
| 		case ASC_DQUO: | ||||
| 			c = instring(c); break; | ||||
| 		case ASC_COMM: | ||||
| 			do | ||||
| 				c = nextchar(); | ||||
| 			while (c != '\n' && c != '\0'); | ||||
| 			break; | ||||
| 		case CTRL('A'): | ||||
| 			c = CODE1; readcode(1); break; | ||||
| 		case CTRL('B'): | ||||
| 			c = CODE2; readcode(2); break; | ||||
| 		case CTRL('C'): | ||||
| 			c = CODE4; readcode(4); break; | ||||
| 		} | ||||
| 		else | ||||
| 			switch (c) | ||||
| 			{ | ||||
| 				case '=': | ||||
| 				case '<': | ||||
| 				case '>': | ||||
| 				case '|': | ||||
| 				case '&': | ||||
| 					c = induo(c); | ||||
| 					break; | ||||
| 				case ASC_SQUO: | ||||
| 				case ASC_DQUO: | ||||
| 					c = instring(c); | ||||
| 					break; | ||||
| 				case ASC_COMM: | ||||
| 					do | ||||
| 						c = nextchar(); | ||||
| 					while (c != '\n' && c != '\0'); | ||||
| 					break; | ||||
| 				case CTRL('A'): | ||||
| 					c = CODE1; | ||||
| 					readcode(1); | ||||
| 					break; | ||||
| 				case CTRL('B'): | ||||
| 					c = CODE2; | ||||
| 					readcode(2); | ||||
| 					break; | ||||
| 				case CTRL('C'): | ||||
| 					c = CODE4; | ||||
| 					readcode(4); | ||||
| 					break; | ||||
| 			} | ||||
| 
 | ||||
| 		/* produce the intermediate token file */ | ||||
| 		if (c <= 0) | ||||
| 			return(0); | ||||
| 		if (c < 256) { | ||||
| 			return (0); | ||||
| 		if (c < 256) | ||||
| 		{ | ||||
| 			putc(c, tempfile); | ||||
| 			putc(0, tempfile); | ||||
| 		} else { | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			putval(c); | ||||
| 		} | ||||
| 	} else { | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		/* read from intermediate token file */ | ||||
| 		c0 = getc(tempfile); | ||||
| 		if (c0 == EOF) | ||||
| 			return(0); | ||||
| 			return (0); | ||||
| 		c1 = getc(tempfile); | ||||
| 		if (c1 == EOF) | ||||
| 			return(0); | ||||
| 			return (0); | ||||
| 
 | ||||
| 		c = c0 + (c1 << 8); | ||||
| 		if (c >= 256) | ||||
| 			c = getval(c); | ||||
| 	} | ||||
| 	curr_token = c; | ||||
| 	return(c); | ||||
| 	return (c); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| putval(int c) | ||||
| void putval(int c) | ||||
| { | ||||
| 	valu_t v; | ||||
| 	int n = 0; | ||||
| 	char *p = 0; | ||||
| 	char* p = 0; | ||||
| 
 | ||||
| 	assert(c == (c & 0xffff)); | ||||
| 	switch (c) { | ||||
| 	case CODE1: | ||||
| 		n = 1; goto putnum; | ||||
| 	case CODE2: | ||||
| 		n = 2; goto putnum; | ||||
| 	case CODE4: | ||||
| 		n = 4; goto putnum; | ||||
| 	case NUMBER: | ||||
| 		v = yylval.y_valu; | ||||
| 		for (n = 0; n < sizeof(v); n++) { | ||||
| 			if (v == 0) | ||||
| 				break; | ||||
| 			v >>= 8; | ||||
| 		} | ||||
| 		assert(n <= 4); | ||||
| 		c = NUMBER0 + n; | ||||
| 	putnum: | ||||
| 		putc(c, tempfile); | ||||
| 		putc(c >> 8, tempfile); | ||||
| 		v = yylval.y_valu; | ||||
| 		while (--n >= 0) | ||||
| 			putc((int) (v >> (n*8)), tempfile); | ||||
| 		return; | ||||
| 	case IDENT: | ||||
| 	case FBSYM: | ||||
| 		n = sizeof(item_t *); | ||||
| 		p = (char *) &yylval.y_item; break; | ||||
| 	switch (c) | ||||
| 	{ | ||||
| 		case CODE1: | ||||
| 			n = 1; | ||||
| 			goto putnum; | ||||
| 		case CODE2: | ||||
| 			n = 2; | ||||
| 			goto putnum; | ||||
| 		case CODE4: | ||||
| 			n = 4; | ||||
| 			goto putnum; | ||||
| 		case NUMBER: | ||||
| 			v = yylval.y_valu; | ||||
| 			for (n = 0; n < sizeof(v); n++) | ||||
| 			{ | ||||
| 				if (v == 0) | ||||
| 					break; | ||||
| 				v >>= 8; | ||||
| 			} | ||||
| 			assert(n <= 4); | ||||
| 			c = NUMBER0 + n; | ||||
| 		putnum: | ||||
| 			putc(c, tempfile); | ||||
| 			putc(c >> 8, tempfile); | ||||
| 			v = yylval.y_valu; | ||||
| 			while (--n >= 0) | ||||
| 				putc((int)(v >> (n * 8)), tempfile); | ||||
| 			return; | ||||
| 		case IDENT: | ||||
| 		case FBSYM: | ||||
| 			n = sizeof(item_t*); | ||||
| 			p = (char*)&yylval.y_item; | ||||
| 			break; | ||||
| #ifdef ASLD | ||||
| 	case MODULE: | ||||
| 		n = sizeof(char *); | ||||
| 		p = (char *) &yylval.y_strp; break; | ||||
| 		case MODULE: | ||||
| 			n = sizeof(char*); | ||||
| 			p = (char*)&yylval.y_strp; | ||||
| 			break; | ||||
| #endif | ||||
| 	case STRING: | ||||
| 		v = stringlen; | ||||
| 		putc(c, tempfile); | ||||
| 		putc(c >> 8, tempfile); | ||||
| 		for (n = 0; n < sizeof(v); n++) { | ||||
| 			if (v == 0) | ||||
| 				break; | ||||
| 			v >>= 8; | ||||
| 		} | ||||
| 		assert(n <= 4); | ||||
| 		putc(n, tempfile); | ||||
| 		v = stringlen; | ||||
| 		while (--n >= 0) | ||||
| 			putc((int) (v >> (n*8)), tempfile); | ||||
| 		p = stringbuf; | ||||
| 		n = stringlen; | ||||
| 		while (--n >= 0) | ||||
| 			putc(*p++, tempfile); | ||||
| 		return; | ||||
| 	case OP_EQ: | ||||
| 	case OP_NE: | ||||
| 	case OP_LE: | ||||
| 	case OP_GE: | ||||
| 	case OP_LL: | ||||
| 	case OP_RR: | ||||
| 	case OP_OO: | ||||
| 	case OP_AA: | ||||
| 		break; | ||||
| 	default: | ||||
| 		n = sizeof(word_t); | ||||
| 		p = (char *) &yylval.y_word; break; | ||||
| 		case STRING: | ||||
| 		case NUMBERF: | ||||
| 			v = stringlen; | ||||
| 			putc(c, tempfile); | ||||
| 			putc(c >> 8, tempfile); | ||||
| 			for (n = 0; n < sizeof(v); n++) | ||||
| 			{ | ||||
| 				if (v == 0) | ||||
| 					break; | ||||
| 				v >>= 8; | ||||
| 			} | ||||
| 			assert(n <= 4); | ||||
| 			putc(n, tempfile); | ||||
| 			v = stringlen; | ||||
| 			while (--n >= 0) | ||||
| 				putc((int)(v >> (n * 8)), tempfile); | ||||
| 			p = stringbuf; | ||||
| 			n = stringlen; | ||||
| 			while (--n >= 0) | ||||
| 				putc(*p++, tempfile); | ||||
| 			return; | ||||
| 		case OP_EQ: | ||||
| 		case OP_NE: | ||||
| 		case OP_LE: | ||||
| 		case OP_GE: | ||||
| 		case OP_LL: | ||||
| 		case OP_RR: | ||||
| 		case OP_OO: | ||||
| 		case OP_AA: | ||||
| 			break; | ||||
| 		default: | ||||
| 			n = sizeof(word_t); | ||||
| 			p = (char*)&yylval.y_word; | ||||
| 			break; | ||||
| 	} | ||||
| 	putc(c, tempfile); | ||||
| 	putc(c >> 8, tempfile); | ||||
|  | @ -160,151 +186,172 @@ putval(int c) | |||
| 		putc(*p++, tempfile); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| getval(int c) | ||||
| int getval(int c) | ||||
| { | ||||
| 	int n = 0; | ||||
| 	valu_t v; | ||||
| 	char *p = 0; | ||||
| 	char* p = 0; | ||||
| 
 | ||||
| 	switch (c) { | ||||
| 	case CODE1: | ||||
| 		n = 1; goto getnum; | ||||
| 	case CODE2: | ||||
| 		n = 2; goto getnum; | ||||
| 	case CODE4: | ||||
| 		n = 4; goto getnum; | ||||
| 	case NUMBER0: | ||||
| 		c = NUMBER; goto getnum; | ||||
| 	case NUMBER1: | ||||
| 		n = 1; c = NUMBER; goto getnum; | ||||
| 	case NUMBER2: | ||||
| 		n = 2; c = NUMBER; goto getnum; | ||||
| 	case NUMBER3: | ||||
| 		n = 3; c = NUMBER; goto getnum; | ||||
| 	case NUMBER: | ||||
| 		n = 4; | ||||
| 	getnum: | ||||
| 		v = 0; | ||||
| 		while (--n >= 0) { | ||||
| 			v <<= 8; | ||||
| 			v |= getc(tempfile); | ||||
| 		} | ||||
| 		yylval.y_valu = v; | ||||
| 		return(c); | ||||
| 	case IDENT: | ||||
| 	case FBSYM: | ||||
| 		n = sizeof(item_t *); | ||||
| 		p = (char *) &yylval.y_item; break; | ||||
| 	switch (c) | ||||
| 	{ | ||||
| 		case CODE1: | ||||
| 			n = 1; | ||||
| 			goto getnum; | ||||
| 		case CODE2: | ||||
| 			n = 2; | ||||
| 			goto getnum; | ||||
| 		case CODE4: | ||||
| 			n = 4; | ||||
| 			goto getnum; | ||||
| 		case NUMBER0: | ||||
| 			c = NUMBER; | ||||
| 			goto getnum; | ||||
| 		case NUMBER1: | ||||
| 			n = 1; | ||||
| 			c = NUMBER; | ||||
| 			goto getnum; | ||||
| 		case NUMBER2: | ||||
| 			n = 2; | ||||
| 			c = NUMBER; | ||||
| 			goto getnum; | ||||
| 		case NUMBER3: | ||||
| 			n = 3; | ||||
| 			c = NUMBER; | ||||
| 			goto getnum; | ||||
| 		case NUMBER: | ||||
| 			n = 4; | ||||
| 		getnum: | ||||
| 			v = 0; | ||||
| 			while (--n >= 0) | ||||
| 			{ | ||||
| 				v <<= 8; | ||||
| 				v |= getc(tempfile); | ||||
| 			} | ||||
| 			yylval.y_valu = v; | ||||
| 			return (c); | ||||
| 		case IDENT: | ||||
| 		case FBSYM: | ||||
| 			n = sizeof(item_t*); | ||||
| 			p = (char*)&yylval.y_item; | ||||
| 			break; | ||||
| #ifdef ASLD | ||||
| 	case MODULE: | ||||
| 		n = sizeof(char *); | ||||
| 		p = (char *) &yylval.y_strp; break; | ||||
| 		case MODULE: | ||||
| 			n = sizeof(char*); | ||||
| 			p = (char*)&yylval.y_strp; | ||||
| 			break; | ||||
| #endif | ||||
| 	case STRING: | ||||
| 		getval(getc(tempfile)+NUMBER0); | ||||
| 		stringlen = n = yylval.y_valu; | ||||
| 		p = stringbuf; | ||||
| 		p[n] = '\0'; break; | ||||
| 	case OP_EQ: | ||||
| 	case OP_NE: | ||||
| 	case OP_LE: | ||||
| 	case OP_GE: | ||||
| 	case OP_LL: | ||||
| 	case OP_RR: | ||||
| 	case OP_OO: | ||||
| 	case OP_AA: | ||||
| 		break; | ||||
| 	default: | ||||
| 		n = sizeof(word_t); | ||||
| 		p = (char *) &yylval.y_word; break; | ||||
| 		case STRING: | ||||
| 		case NUMBERF: | ||||
| 			getval(getc(tempfile) + NUMBER0); | ||||
| 			stringlen = n = yylval.y_valu; | ||||
| 			p = stringbuf; | ||||
| 			p[n] = '\0'; | ||||
| 			break; | ||||
| 		case OP_EQ: | ||||
| 		case OP_NE: | ||||
| 		case OP_LE: | ||||
| 		case OP_GE: | ||||
| 		case OP_LL: | ||||
| 		case OP_RR: | ||||
| 		case OP_OO: | ||||
| 		case OP_AA: | ||||
| 			break; | ||||
| 		default: | ||||
| 			n = sizeof(word_t); | ||||
| 			p = (char*)&yylval.y_word; | ||||
| 			break; | ||||
| 	} | ||||
| 	while (--n >= 0) | ||||
| 		*p++ = getc(tempfile); | ||||
| 	return(c); | ||||
| 	return (c); | ||||
| } | ||||
| 
 | ||||
| /* ---------- lexical scan in pass 1 ---------- */ | ||||
| 
 | ||||
| int | ||||
| nextchar(void) | ||||
| int nextchar(void) | ||||
| { | ||||
| 	int c; | ||||
| 
 | ||||
| 	if (peekc != -1) { | ||||
| 	if (peekc != -1) | ||||
| 	{ | ||||
| 		c = peekc; | ||||
| 		peekc = -1; | ||||
| 		return(c); | ||||
| 		return (c); | ||||
| 	} | ||||
| #ifdef ASLD | ||||
| 	if (archmode && --archsize < 0) | ||||
| 		return(0); | ||||
| 		return (0); | ||||
| #endif | ||||
| 	if ((c = getc(input)) == EOF) | ||||
| 		return(0); | ||||
| 		return (0); | ||||
| 	if (isascii(c) == 0) | ||||
| 		fatal("non-ascii character"); | ||||
| #ifdef LISTING | ||||
| 	if (listflag & 0440) | ||||
| 		putc(c, listfile); | ||||
| #endif | ||||
| 	return(c); | ||||
| 	return (c); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| readcode(int n) | ||||
| static void readcode(int n) | ||||
| { | ||||
| 	int c; | ||||
| 
 | ||||
| 	yylval.y_valu = 0; | ||||
| 	do { | ||||
| 	do | ||||
| 	{ | ||||
| 		if ( | ||||
| #ifdef ASLD | ||||
| 			(archmode && --archsize < 0) | ||||
| 			|| | ||||
| 		    (archmode && --archsize < 0) || | ||||
| #endif | ||||
| 			(c = getc(input)) == EOF | ||||
| 		) | ||||
| 		    (c = getc(input)) == EOF) | ||||
| 			fatal("unexpected EOF in compact input"); | ||||
| 		yylval.y_valu <<= 8; | ||||
| 		yylval.y_valu |= c; | ||||
| 	} while (--n); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| induo(int c) | ||||
| static int induo(int c) | ||||
| { | ||||
| 	static short duo[] = { | ||||
| 		('='<<8) | '=', OP_EQ, | ||||
| 		('<'<<8) | '>', OP_NE, | ||||
| 		('<'<<8) | '=', OP_LE, | ||||
| 		('>'<<8) | '=', OP_GE, | ||||
| 		('<'<<8) | '<', OP_LL, | ||||
| 		('>'<<8) | '>', OP_RR, | ||||
| 		('|'<<8) | '|', OP_OO, | ||||
| 		('&'<<8) | '&', OP_AA, | ||||
| 		0  /* terminates array */ | ||||
| 		('=' << 8) | '=', | ||||
| 		OP_EQ, | ||||
| 		('<' << 8) | '>', | ||||
| 		OP_NE, | ||||
| 		('<' << 8) | '=', | ||||
| 		OP_LE, | ||||
| 		('>' << 8) | '=', | ||||
| 		OP_GE, | ||||
| 		('<' << 8) | '<', | ||||
| 		OP_LL, | ||||
| 		('>' << 8) | '>', | ||||
| 		OP_RR, | ||||
| 		('|' << 8) | '|', | ||||
| 		OP_OO, | ||||
| 		('&' << 8) | '&', | ||||
| 		OP_AA, | ||||
| 		0 /* terminates array */ | ||||
| 	}; | ||||
| 	short *p; | ||||
| 	short* p; | ||||
| 
 | ||||
| 	c = (c<<8) | nextchar(); | ||||
| 	c = (c << 8) | nextchar(); | ||||
| 	for (p = duo; *p; p++) | ||||
| 		if (*p++ == c) | ||||
| 			return(*p++); | ||||
| 			return (*p++); | ||||
| 	peekc = c & 0377; | ||||
| 	return(c>>8); | ||||
| 	return (c >> 8); | ||||
| } | ||||
| 
 | ||||
| static char name[NAMEMAX+1]; | ||||
| static char name[NAMEMAX + 1]; | ||||
| 
 | ||||
| static int | ||||
| inident(int c) | ||||
| static int inident(int c) | ||||
| { | ||||
| 	char *p = name; | ||||
| 	item_t *ip; | ||||
| 	char* p = name; | ||||
| 	item_t* ip; | ||||
| 	int n = NAMEMAX; | ||||
| 
 | ||||
| 	do { | ||||
| 	do | ||||
| 	{ | ||||
| 		if (--n >= 0) | ||||
| 			*p++ = c; | ||||
| 		c = nextchar(); | ||||
|  | @ -312,76 +359,88 @@ inident(int c) | |||
| 	*p = '\0'; | ||||
| 	peekc = c; | ||||
| 	ip = item_search(name); | ||||
| 	if (ip == 0) { | ||||
| 	if (ip == 0) | ||||
| 	{ | ||||
| 		ip = item_alloc(S_UND); | ||||
| 		ip->i_name = remember(name); | ||||
| 		/* printf("ident %s %o\n", ip->i_name, ip); */ | ||||
| 		unresolved++; | ||||
| 		item_insert(ip, H_LOCAL + (hashindex%H_SIZE)); | ||||
| 	} else if (hashindex < H_SIZE) { | ||||
| 		item_insert(ip, H_LOCAL + (hashindex % H_SIZE)); | ||||
| 	} | ||||
| 	else if (hashindex < H_SIZE) | ||||
| 	{ | ||||
| 		assert(H_KEY == 0); | ||||
| 		yylval.y_word = (word_t) ip->i_valu; | ||||
| 		return(ip->i_type); | ||||
| 		yylval.y_word = (word_t)ip->i_valu; | ||||
| 		return (ip->i_type); | ||||
| 	} | ||||
| 	yylval.y_item = ip; | ||||
| 	return(IDENT); | ||||
| 	return (IDENT); | ||||
| } | ||||
| 
 | ||||
| #ifdef ASLD | ||||
| char * | ||||
| readident(int c) | ||||
| char* readident(int c) | ||||
| { | ||||
| 	int n = NAMEMAX; | ||||
| 	char *p = name; | ||||
| 	char* p = name; | ||||
| 
 | ||||
| 	do { | ||||
| 	do | ||||
| 	{ | ||||
| 		if (--n >= 0) | ||||
| 			*p++ = c; | ||||
| 		c = nextchar(); | ||||
| 	} while (ISALNUM(c)); | ||||
| 	*p++ = '\0'; | ||||
| 	peekc = c; | ||||
| 	return(name); | ||||
| 	return (name); | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| static int | ||||
| innumber(int c) | ||||
| static int innumber(int c) | ||||
| { | ||||
| 	char *p; | ||||
| 	char* p; | ||||
| 	int radix; | ||||
| 	static char num[20+1]; | ||||
| 	static char num[40 + 1]; | ||||
| 
 | ||||
| 	p = num; | ||||
| 	radix = 20; | ||||
| 	do { | ||||
| 	radix = 40; | ||||
| 	if (c == '.') | ||||
| 		goto floatconstant; | ||||
| 	do | ||||
| 	{ | ||||
| 		if (--radix < 0) | ||||
| 			fatal("number too long"); | ||||
| 		if (isupper(c)) | ||||
| 			c += ('a' - 'A'); | ||||
| 		*p++ = c; | ||||
| 		c = nextchar(); | ||||
| 		if (c == '.') | ||||
| 			goto floatconstant; | ||||
| 	} while (isalnum(c)); | ||||
| 	peekc = c; | ||||
| 	*p = '\0'; | ||||
| 	c = *--p; | ||||
| 	p = num; | ||||
| 	radix = 10; | ||||
| 	if (*p == '0') { | ||||
| 	if (*p == '0') | ||||
| 	{ | ||||
| 		radix = 8; | ||||
| 		p++; | ||||
| 		if (*p == 'x') { | ||||
| 		if (*p == 'x') | ||||
| 		{ | ||||
| 			radix = 16; | ||||
| 			p++; | ||||
| 		} else if (*p == 'b') { | ||||
| 		} | ||||
| 		else if (*p == 'b') | ||||
| 		{ | ||||
| 			radix = 2; | ||||
| 			p++; | ||||
| 		} | ||||
| 	} | ||||
| 	if (radix != 16 && (c == 'f' || c == 'b')) | ||||
| 		return(infbsym(num)); | ||||
| 		return (infbsym(num)); | ||||
| 	yylval.y_valu = 0; | ||||
| 	while (c = *p++) { | ||||
| 	while (c = *p++) | ||||
| 	{ | ||||
| 		if (c > '9') | ||||
| 			c -= ('a' - '9' - 1); | ||||
| 		c -= '0'; | ||||
|  | @ -389,26 +448,50 @@ innumber(int c) | |||
| 			serror("digit exceeds radix"); | ||||
| 		yylval.y_valu = yylval.y_valu * radix + c; | ||||
| 	} | ||||
| 	return(NUMBER); | ||||
| 	return (NUMBER); | ||||
| 
 | ||||
| floatconstant: | ||||
| 	do | ||||
| 	{ | ||||
| 		if (--radix < 0) | ||||
| 			fatal("number too long"); | ||||
| 		*p++ = c; | ||||
| 		c = nextchar(); | ||||
| 		if (isupper(c)) | ||||
| 			c = tolower(c); | ||||
| 	} while (isdigit(c) || (c == '.') || (c == 'e') || (c == '+') || (c == '-')); | ||||
| 	peekc = c; | ||||
| 
 | ||||
| 	*p = '\0'; | ||||
| 	stringlen = p - num; | ||||
| 	if (stringlen > maxstring) | ||||
| 	{ | ||||
| 		maxstring = stringlen; | ||||
| 		stringbuf = realloc(stringbuf, maxstring); | ||||
| 	} | ||||
| 	strcpy(stringbuf, num); | ||||
| 	return NUMBERF; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| instring(int termc) | ||||
| static int instring(int termc) | ||||
| { | ||||
| 	char *p; | ||||
| 	char* p; | ||||
| 	int c; | ||||
| 	static int maxstring = 0; | ||||
| 
 | ||||
| 	if (! maxstring) { | ||||
| 	if (!maxstring) | ||||
| 	{ | ||||
| 		maxstring = STRINGMAX; | ||||
| 		if ((stringbuf = malloc(maxstring)) == 0) { | ||||
| 		if ((stringbuf = malloc(maxstring)) == 0) | ||||
| 		{ | ||||
| 			fatal("out of memory"); | ||||
| 		} | ||||
| 	} | ||||
| 	p = stringbuf; | ||||
| 	for (;;) { | ||||
| 	for (;;) | ||||
| 	{ | ||||
| 		c = nextchar(); | ||||
| 		if (c == '\n' || c == '\0') { | ||||
| 		if (c == '\n' || c == '\0') | ||||
| 		{ | ||||
| 			peekc = c; | ||||
| 			serror("non-terminated string"); | ||||
| 			break; | ||||
|  | @ -417,10 +500,12 @@ instring(int termc) | |||
| 			break; | ||||
| 		if (c == '\\') | ||||
| 			c = inescape(); | ||||
| 		if (p >= &stringbuf[maxstring - 1]) { | ||||
| 		if (p >= &stringbuf[maxstring - 1]) | ||||
| 		{ | ||||
| 			int cnt = p - stringbuf; | ||||
| 
 | ||||
| 			if ((stringbuf = realloc(stringbuf, maxstring += 256)) == 0) { | ||||
| 			if ((stringbuf = realloc(stringbuf, maxstring += 256)) == 0) | ||||
| 			{ | ||||
| 				fatal("out of memory"); | ||||
| 			} | ||||
| 			p = stringbuf + cnt; | ||||
|  | @ -429,57 +514,69 @@ instring(int termc) | |||
| 	} | ||||
| 	stringlen = p - stringbuf; | ||||
| 	*p = '\0'; | ||||
| 	return(STRING); | ||||
| 	return (STRING); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| inescape(void) | ||||
| static int inescape(void) | ||||
| { | ||||
| 	int c, j, r; | ||||
| 
 | ||||
| 	c = nextchar(); | ||||
| 	if (c >= '0' && c <= '7') { | ||||
| 	if (c >= '0' && c <= '7') | ||||
| 	{ | ||||
| 		r = c - '0'; | ||||
| 		for (j = 0; j < 2; j++) { | ||||
| 		for (j = 0; j < 2; j++) | ||||
| 		{ | ||||
| 			c = nextchar(); | ||||
| 			if (c < '0' || c > '7') { | ||||
| 			if (c < '0' || c > '7') | ||||
| 			{ | ||||
| 				peekc = c; | ||||
| 				return(r); | ||||
| 				return (r); | ||||
| 			} | ||||
| 			r <<= 3; | ||||
| 			r += (c - '0'); | ||||
| 		} | ||||
| 		return(r); | ||||
| 		return (r); | ||||
| 	} | ||||
| 	switch (c) { | ||||
| 	case 'b':	return('\b'); | ||||
| 	case 'f':	return('\f'); | ||||
| 	case 'n':	return('\n'); | ||||
| 	case 'r':	return('\r'); | ||||
| 	case 't':	return('\t'); | ||||
| 	case '\'':	return('\''); | ||||
| 	case '"':	return('"'); | ||||
| 	switch (c) | ||||
| 	{ | ||||
| 		case 'b': | ||||
| 			return ('\b'); | ||||
| 		case 'f': | ||||
| 			return ('\f'); | ||||
| 		case 'n': | ||||
| 			return ('\n'); | ||||
| 		case 'r': | ||||
| 			return ('\r'); | ||||
| 		case 't': | ||||
| 			return ('\t'); | ||||
| 		case '\'': | ||||
| 			return ('\''); | ||||
| 		case '"': | ||||
| 			return ('"'); | ||||
| 	} | ||||
| 	return(c); | ||||
| 	return (c); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| infbsym(const char *p) | ||||
| static int infbsym(const char* p) | ||||
| { | ||||
| 	int lab; | ||||
| 	item_t *ip; | ||||
| 	item_t* ip; | ||||
| 
 | ||||
| 	lab = *p++ - '0'; | ||||
| 	if ((unsigned)lab < 10) { | ||||
| 		if (*p++ == 'f') { | ||||
| 			ip = fb_ptr[FB_FORW+lab]; | ||||
| 			if (ip == 0) { | ||||
| 	if ((unsigned)lab < 10) | ||||
| 	{ | ||||
| 		if (*p++ == 'f') | ||||
| 		{ | ||||
| 			ip = fb_ptr[FB_FORW + lab]; | ||||
| 			if (ip == 0) | ||||
| 			{ | ||||
| 				ip = fb_alloc(lab); | ||||
| 				fb_ptr[FB_FORW+lab] = ip; | ||||
| 				fb_ptr[FB_FORW + lab] = ip; | ||||
| 			} | ||||
| 			goto ok; | ||||
| 		} | ||||
| 		ip = fb_ptr[FB_BACK+lab]; | ||||
| 		ip = fb_ptr[FB_BACK + lab]; | ||||
| 		if (ip != 0 && *p == 0) | ||||
| 			goto ok; | ||||
| 	} | ||||
|  | @ -487,32 +584,33 @@ infbsym(const char *p) | |||
| 	ip = fb_alloc(0); | ||||
| ok: | ||||
| 	yylval.y_item = ip; | ||||
| 	return(FBSYM); | ||||
| 	return (FBSYM); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| hash(const char *p) | ||||
| int hash(const char* p) | ||||
| { | ||||
| 	unsigned short h; | ||||
| 	int c; | ||||
| 
 | ||||
| 	h = 0; | ||||
| 	while (c = *p++) { | ||||
| 	while (c = *p++) | ||||
| 	{ | ||||
| 		h <<= 2; | ||||
| 		h += c; | ||||
| 	} | ||||
| 	return(h % H_SIZE); | ||||
| 	return (h % H_SIZE); | ||||
| } | ||||
| 
 | ||||
| item_t * | ||||
| item_search(const char *p) | ||||
| item_t* item_search(const char* p) | ||||
| { | ||||
| 	int h; | ||||
| 	item_t *ip; | ||||
| 	item_t* ip; | ||||
| 
 | ||||
| 	for (h = hash(p); h < H_TOTAL; h += H_SIZE) { | ||||
| 	for (h = hash(p); h < H_TOTAL; h += H_SIZE) | ||||
| 	{ | ||||
| 		ip = hashtab[h]; | ||||
| 		while (ip != 0) { | ||||
| 		while (ip != 0) | ||||
| 		{ | ||||
| 			if (strcmp(p, ip->i_name) == 0) | ||||
| 				goto done; | ||||
| 			ip = ip->i_next; | ||||
|  | @ -520,25 +618,24 @@ item_search(const char *p) | |||
| 	} | ||||
| done: | ||||
| 	hashindex = h; | ||||
| 	return(ip); | ||||
| 	return (ip); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| item_insert(item_t *ip, int h) | ||||
| void item_insert(item_t* ip, int h) | ||||
| { | ||||
| 	ip->i_next = hashtab[h]; | ||||
| 	hashtab[h] = ip; | ||||
| } | ||||
| 
 | ||||
| item_t * | ||||
| item_alloc(int typ) | ||||
| item_t* item_alloc(int typ) | ||||
| { | ||||
| 	item_t *ip; | ||||
| 	item_t* ip; | ||||
| 	static int nleft = 0; | ||||
| 	static item_t *next; | ||||
| 	static item_t* next; | ||||
| 
 | ||||
| 	if (--nleft < 0) { | ||||
| 		next = (item_t *) malloc(MEMINCR); | ||||
| 	if (--nleft < 0) | ||||
| 	{ | ||||
| 		next = (item_t*)malloc(MEMINCR); | ||||
| 		if (next == 0) | ||||
| 			fatal("out of memory"); | ||||
| 		nleft += (MEMINCR / sizeof(item_t)); | ||||
|  | @ -548,36 +645,34 @@ item_alloc(int typ) | |||
| 	ip->i_type = typ; | ||||
| 	ip->i_name = 0; | ||||
| 	ip->i_valu = 0; | ||||
| 	return(ip); | ||||
| 	return (ip); | ||||
| } | ||||
| 
 | ||||
| item_t * | ||||
| fb_alloc(int lab) | ||||
| item_t* fb_alloc(int lab) | ||||
| { | ||||
| 	item_t *ip, *p; | ||||
| 
 | ||||
| 	ip = item_alloc(S_UND); | ||||
| 	p = fb_ptr[FB_TAIL+lab]; | ||||
| 	p = fb_ptr[FB_TAIL + lab]; | ||||
| 	if (p == 0) | ||||
| 		fb_ptr[FB_HEAD+lab] = ip; | ||||
| 		fb_ptr[FB_HEAD + lab] = ip; | ||||
| 	else | ||||
| 		p->i_next = ip; | ||||
| 	fb_ptr[FB_TAIL+lab] = ip; | ||||
| 	return(ip); | ||||
| 	fb_ptr[FB_TAIL + lab] = ip; | ||||
| 	return (ip); | ||||
| } | ||||
| 
 | ||||
| item_t * | ||||
| fb_shift(int lab) | ||||
| item_t* fb_shift(int lab) | ||||
| { | ||||
| 	item_t *ip; | ||||
| 	item_t* ip; | ||||
| 
 | ||||
| 	ip = fb_ptr[FB_FORW+lab]; | ||||
| 	ip = fb_ptr[FB_FORW + lab]; | ||||
| 	if (ip == 0) | ||||
| 		if (pass == PASS_1) | ||||
| 			ip = fb_alloc(lab); | ||||
| 		else | ||||
| 			ip = fb_ptr[FB_HEAD+lab]; | ||||
| 	fb_ptr[FB_BACK+lab] = ip; | ||||
| 	fb_ptr[FB_FORW+lab] = ip->i_next; | ||||
| 	return(ip); | ||||
| 			ip = fb_ptr[FB_HEAD + lab]; | ||||
| 	fb_ptr[FB_BACK + lab] = ip; | ||||
| 	fb_ptr[FB_FORW + lab] = ip->i_next; | ||||
| 	return (ip); | ||||
| } | ||||
|  |  | |||
|  | @ -8,37 +8,37 @@ | |||
|  * miscellaneous | ||||
|  */ | ||||
| 
 | ||||
| #include	"comm0.h" | ||||
| #include	"comm1.h" | ||||
| #include	"y.tab.h" | ||||
| #include	<stdarg.h> | ||||
| #include	<object.h> | ||||
| #include "comm0.h" | ||||
| #include "comm1.h" | ||||
| #include "y.tab.h" | ||||
| #include <stdarg.h> | ||||
| #include <object.h> | ||||
| 
 | ||||
| valu_t | ||||
| load(const item_t *ip) | ||||
| valu_t load(const item_t* ip) | ||||
| { | ||||
| #ifdef ASLD | ||||
| 	int typ; | ||||
| 
 | ||||
| 	typ = ip->i_type & S_TYP; | ||||
| 	if ((typ -= S_MIN) < 0)		/* S_UND or S_ABS */ | ||||
| 		return(ip->i_valu); | ||||
| 	return(ip->i_valu + sect[typ].s_base); | ||||
| 	if ((typ -= S_MIN) < 0) /* S_UND or S_ABS */ | ||||
| 		return (ip->i_valu); | ||||
| 	return (ip->i_valu + sect[typ].s_base); | ||||
| #else | ||||
| 	if ((ip->i_type & S_TYP) == S_UND || (ip->i_type & S_COM)) { | ||||
| 		if (pass == PASS_3) { | ||||
| 	if ((ip->i_type & S_TYP) == S_UND || (ip->i_type & S_COM)) | ||||
| 	{ | ||||
| 		if (pass == PASS_3) | ||||
| 		{ | ||||
| 			if (relonami != 0) | ||||
| 				serror("relocation error (relonami=%d, type=%08x)", relonami, ip->i_type); | ||||
| 			relonami = ip->i_valu+1; | ||||
| 			relonami = ip->i_valu + 1; | ||||
| 		} | ||||
| 		return(0); | ||||
| 		return (0); | ||||
| 	} | ||||
| 	return(ip->i_valu); | ||||
| 	return (ip->i_valu); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| int | ||||
| store(item_t *ip, valu_t val) | ||||
| int store(item_t* ip, valu_t val) | ||||
| { | ||||
| #ifdef ASLD | ||||
| 	int typ; | ||||
|  | @ -48,27 +48,27 @@ store(item_t *ip, valu_t val) | |||
| 		val -= sect[typ].s_base; | ||||
| #else | ||||
| 	if ((ip->i_type & S_TYP) == S_UND) | ||||
| 		return(0); | ||||
| 		return (0); | ||||
| #endif | ||||
| 	assert(pass != PASS_3 || (ip->i_type & S_VAR) || ip->i_valu == val); | ||||
| 	ip->i_valu = val; | ||||
| 	return(1); | ||||
| 	return (1); | ||||
| } | ||||
| 
 | ||||
| char * | ||||
| remember(char *s) | ||||
| char* remember(char* s) | ||||
| { | ||||
| 	char *p; | ||||
| 	char* p; | ||||
| 	int n; | ||||
| 	static int nleft = 0; | ||||
| 	static char *next; | ||||
| 	static char* next; | ||||
| 
 | ||||
| 	p = s; | ||||
| 	n = 0; | ||||
| 	do | ||||
| 		n++; | ||||
| 	while (*p++); | ||||
| 	if ((nleft -= n) < 0) { | ||||
| 	if ((nleft -= n) < 0) | ||||
| 	{ | ||||
| 		next = malloc(MEMINCR); | ||||
| 		if (next == 0) | ||||
| 			fatal("out of memory"); | ||||
|  | @ -80,84 +80,86 @@ remember(char *s) | |||
| 		; | ||||
| 	s = next; | ||||
| 	next = p; | ||||
| 	return(s); | ||||
| 	return (s); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| combine(int typ1, int typ2, int op) | ||||
| int combine(int typ1, int typ2, int op) | ||||
| { | ||||
| 	switch (op) { | ||||
| 	case '+': | ||||
| 		if (typ1 == S_ABS) | ||||
| 			return(typ2); | ||||
| 		if (typ2 == S_ABS) | ||||
| 			return(typ1); | ||||
| 		break; | ||||
| 	case '-': | ||||
| 		if (typ2 == S_ABS) | ||||
| 			return(typ1); | ||||
| 		if ((typ1 & ~S_DOT) == (typ2 & ~S_DOT) && typ1 != S_UND) | ||||
| 			return(S_ABS|S_VAR); | ||||
| 		break; | ||||
| 	case '>': | ||||
| 		if (typ1 == S_ABS && typ2 == S_ABS) | ||||
| 			return(S_ABS); | ||||
| 		if ( | ||||
| 		    ((typ1 & ~S_DOT) == (typ2 & ~S_DOT) && typ1 != S_UND) | ||||
| 		    || (typ1 == S_ABS) | ||||
| 		    || (typ2 == S_ABS) | ||||
| 		   ) | ||||
| 			return(S_ABS|S_VAR); | ||||
| 		break; | ||||
| 	default: | ||||
| 		if (typ1 == S_ABS && typ2 == S_ABS) | ||||
| 			return(S_ABS); | ||||
| 		break; | ||||
| 	switch (op) | ||||
| 	{ | ||||
| 		case '+': | ||||
| 			if (typ1 == S_ABS) | ||||
| 				return (typ2); | ||||
| 			if (typ2 == S_ABS) | ||||
| 				return (typ1); | ||||
| 			break; | ||||
| 		case '-': | ||||
| 			if (typ2 == S_ABS) | ||||
| 				return (typ1); | ||||
| 			if ((typ1 & ~S_DOT) == (typ2 & ~S_DOT) && typ1 != S_UND) | ||||
| 				return (S_ABS | S_VAR); | ||||
| 			break; | ||||
| 		case '>': | ||||
| 			if (typ1 == S_ABS && typ2 == S_ABS) | ||||
| 				return (S_ABS); | ||||
| 			if (((typ1 & ~S_DOT) == (typ2 & ~S_DOT) && typ1 != S_UND) || (typ1 == S_ABS) | ||||
| 			    || (typ2 == S_ABS)) | ||||
| 				return (S_ABS | S_VAR); | ||||
| 			break; | ||||
| 		default: | ||||
| 			if (typ1 == S_ABS && typ2 == S_ABS) | ||||
| 				return (S_ABS); | ||||
| 			break; | ||||
| 	} | ||||
| 	if (pass != PASS_1) | ||||
| 		serror("illegal operator"); | ||||
| 	return(S_UND); | ||||
| 	return (S_UND); | ||||
| } | ||||
| 
 | ||||
| #ifdef LISTING | ||||
| int | ||||
| printx(int ndig, valu_t val) | ||||
| int printx(int ndig, valu_t val) | ||||
| { | ||||
| 	static char buf[8]; | ||||
| 	char *p; | ||||
| 	char* p; | ||||
| 	int c, n; | ||||
| 
 | ||||
| 	p = buf; n = ndig; | ||||
| 	do { | ||||
| 		*p++ = (int) val & 017; | ||||
| 	p = buf; | ||||
| 	n = ndig; | ||||
| 	do | ||||
| 	{ | ||||
| 		*p++ = (int)val & 017; | ||||
| 		val >>= 4; | ||||
| 	} while (--n); | ||||
| 	do { | ||||
| 	do | ||||
| 	{ | ||||
| 		c = "0123456789ABCDEF"[*--p]; | ||||
| 		putchar(c); | ||||
| 	} while (p > buf); | ||||
| 	return(ndig); | ||||
| 	return (ndig); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| listline(int textline) | ||||
| void listline(int textline) | ||||
| { | ||||
| 	int c; | ||||
| 
 | ||||
| 	if ((listflag & 4) && (c = getc(listfile)) != '\n' && textline) { | ||||
| 	if ((listflag & 4) && (c = getc(listfile)) != '\n' && textline) | ||||
| 	{ | ||||
| 		if (listcolm >= 24) | ||||
| 			printf(" \\\n\t\t\t"); | ||||
| 		else | ||||
| 			do { | ||||
| 			do | ||||
| 			{ | ||||
| 				putchar('\t'); | ||||
| 				listcolm += 8; | ||||
| 			} while (listcolm < 24); | ||||
| 		do { | ||||
| 		do | ||||
| 		{ | ||||
| 			assert(c != EOF); | ||||
| 			putchar(c); | ||||
| 		} while ((c = getc(listfile)) != '\n'); | ||||
| 	} | ||||
| 	if (listflag & 7) { | ||||
| 	if (listflag & 7) | ||||
| 	{ | ||||
| 		putchar('\n'); | ||||
| 		fflush(stdout); | ||||
| 	} | ||||
|  | @ -170,35 +172,40 @@ listline(int textline) | |||
| /* ---------- code optimization ---------- */ | ||||
| 
 | ||||
| #ifdef THREE_PASS | ||||
| #define PBITTABSZ	128 | ||||
| static char *pbittab[PBITTABSZ]; | ||||
| #define PBITTABSZ 128 | ||||
| static char* pbittab[PBITTABSZ]; | ||||
| 
 | ||||
| int | ||||
| small(int fitsmall, int gain) | ||||
| int small(int fitsmall, int gain) | ||||
| { | ||||
| 	int bit; | ||||
| 	char *p; | ||||
| 	char* p; | ||||
| 
 | ||||
| 	if (DOTSCT == NULL) | ||||
| 		nosect(); | ||||
| 	if (bflag) | ||||
| 		return(0); | ||||
| 	if (nbits == BITCHUNK) { | ||||
| 		return (0); | ||||
| 	if (nbits == BITCHUNK) | ||||
| 	{ | ||||
| 		bitindex++; | ||||
| 		nbits = 0; | ||||
| 		if (bitindex == PBITTABSZ) { | ||||
| 		if (bitindex == PBITTABSZ) | ||||
| 		{ | ||||
| 			static int w_given; | ||||
| 			if (pass == PASS_1 && ! w_given) { | ||||
| 			if (pass == PASS_1 && !w_given) | ||||
| 			{ | ||||
| 				w_given = 1; | ||||
| 				warning("bit table overflow"); | ||||
| 			} | ||||
| 			return(0); | ||||
| 			return (0); | ||||
| 		} | ||||
| 		if (pbittab[bitindex] == 0 && pass == PASS_1) { | ||||
| 			if ((pbittab[bitindex] = calloc(MEMINCR, 1)) == 0) { | ||||
| 		if (pbittab[bitindex] == 0 && pass == PASS_1) | ||||
| 		{ | ||||
| 			if ((pbittab[bitindex] = calloc(MEMINCR, 1)) == 0) | ||||
| 			{ | ||||
| 				static int w2_given; | ||||
| 
 | ||||
| 				if (!w2_given) { | ||||
| 				if (!w2_given) | ||||
| 				{ | ||||
| 					w2_given = 1; | ||||
| 					warning("out of space for bit table"); | ||||
| 				} | ||||
|  | @ -207,21 +214,23 @@ small(int fitsmall, int gain) | |||
| 		if (pbittab[bitindex] == 0) | ||||
| 			return (0); | ||||
| 	} | ||||
| 	bit = 1 << (nbits&7); | ||||
| 	p = pbittab[bitindex]+(nbits>>3); | ||||
| 	bit = 1 << (nbits & 7); | ||||
| 	p = pbittab[bitindex] + (nbits >> 3); | ||||
| 	nbits++; | ||||
| 	switch (pass) { | ||||
| 	case PASS_1: | ||||
| 		return(0); | ||||
| 	case PASS_2: | ||||
| 		if (fitsmall) { | ||||
| 			DOTGAIN += gain; | ||||
| 			*p |= bit; | ||||
| 		} | ||||
| 		return(fitsmall); | ||||
| 	case PASS_3: | ||||
| 		assert(fitsmall || (*p & bit) == 0); | ||||
| 		return(*p & bit); | ||||
| 	switch (pass) | ||||
| 	{ | ||||
| 		case PASS_1: | ||||
| 			return (0); | ||||
| 		case PASS_2: | ||||
| 			if (fitsmall) | ||||
| 			{ | ||||
| 				DOTGAIN += gain; | ||||
| 				*p |= bit; | ||||
| 			} | ||||
| 			return (fitsmall); | ||||
| 		case PASS_3: | ||||
| 			assert(fitsmall || (*p & bit) == 0); | ||||
| 			return (*p & bit); | ||||
| 	} | ||||
| 	/*NOTREACHED*/ | ||||
| } | ||||
|  | @ -229,13 +238,14 @@ small(int fitsmall, int gain) | |||
| 
 | ||||
| /* ---------- output ---------- */ | ||||
| 
 | ||||
| void | ||||
| emit1(int arg) | ||||
| void emit1(int arg) | ||||
| { | ||||
| 	static int olddottyp = -1; | ||||
| #ifdef LISTING | ||||
| 	if (listeoln) { | ||||
| 		if (listflag & 1) { | ||||
| 	if (listeoln) | ||||
| 	{ | ||||
| 		if (listflag & 1) | ||||
| 		{ | ||||
| 			listcolm += printx(VALWIDTH, (valu_t)DOTVAL); | ||||
| 			listcolm++; | ||||
| 			putchar(' '); | ||||
|  | @ -243,81 +253,90 @@ emit1(int arg) | |||
| 		listeoln = 0; | ||||
| 	} | ||||
| 	if (listflag & 2) | ||||
| 		listcolm += printx(2, (valu_t) arg); | ||||
| 		listcolm += printx(2, (valu_t)arg); | ||||
| #endif | ||||
| 	switch (pass) { | ||||
| 	case PASS_1: | ||||
| 		if (DOTSCT == NULL) | ||||
| 			nosect(); | ||||
| 		/* no break */ | ||||
| 	case PASS_2: | ||||
| 		DOTSCT->s_zero = 0; | ||||
| 		break; | ||||
| 	case PASS_3: | ||||
| 		if (DOTTYP != olddottyp) { | ||||
| 			wr_outsect(DOTTYP-S_MIN); | ||||
| 			olddottyp = DOTTYP; | ||||
| 		} | ||||
| 		while (DOTSCT->s_zero) { | ||||
| 			wr_putc(0); | ||||
| 			DOTSCT->s_zero--; | ||||
| 		} | ||||
| 		wr_putc(arg); | ||||
| 		break; | ||||
| 	switch (pass) | ||||
| 	{ | ||||
| 		case PASS_1: | ||||
| 			if (DOTSCT == NULL) | ||||
| 				nosect(); | ||||
| 			/* no break */ | ||||
| 		case PASS_2: | ||||
| 			DOTSCT->s_zero = 0; | ||||
| 			break; | ||||
| 		case PASS_3: | ||||
| 			if (DOTTYP != olddottyp) | ||||
| 			{ | ||||
| 				wr_outsect(DOTTYP - S_MIN); | ||||
| 				olddottyp = DOTTYP; | ||||
| 			} | ||||
| 			while (DOTSCT->s_zero) | ||||
| 			{ | ||||
| 				wr_putc(0); | ||||
| 				DOTSCT->s_zero--; | ||||
| 			} | ||||
| 			wr_putc(arg); | ||||
| 			break; | ||||
| 	} | ||||
| 	DOTVAL++; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| emit2(int arg) | ||||
| void emit2(int arg) | ||||
| { | ||||
| #ifdef BYTES_REVERSED | ||||
| 	emit1((arg>>8)); emit1(arg); | ||||
| 	emit1((arg >> 8)); | ||||
| 	emit1(arg); | ||||
| #else | ||||
| 	emit1(arg); emit1((arg>>8)); | ||||
| 	emit1(arg); | ||||
| 	emit1((arg >> 8)); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void | ||||
| emit4(long arg) | ||||
| void emit4(long arg) | ||||
| { | ||||
| #ifdef WORDS_REVERSED | ||||
| 	emit2((int)(arg>>16)); emit2((int)(arg)); | ||||
| 	emit2((int)(arg >> 16)); | ||||
| 	emit2((int)(arg)); | ||||
| #else | ||||
| 	emit2((int)(arg)); emit2((int)(arg>>16)); | ||||
| 	emit2((int)(arg)); | ||||
| 	emit2((int)(arg >> 16)); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void | ||||
| emitx(valu_t val, int n) | ||||
| void emitx(valu_t val, int n) | ||||
| { | ||||
| 	switch (n) { | ||||
| 	case RELO1: | ||||
| 		emit1((int)val); break; | ||||
| 	case RELO2: | ||||
| 	switch (n) | ||||
| 	{ | ||||
| 		case RELO1: | ||||
| 			emit1((int)val); | ||||
| 			break; | ||||
| 		case RELO2: | ||||
| #ifdef BYTES_REVERSED | ||||
| 		emit1(((int)val>>8)); emit1((int)val); | ||||
| 			emit1(((int)val >> 8)); | ||||
| 			emit1((int)val); | ||||
| #else | ||||
| 		emit1((int)val); emit1(((int)val>>8)); | ||||
| 			emit1((int)val); | ||||
| 			emit1(((int)val >> 8)); | ||||
| #endif | ||||
| 		break; | ||||
| 	case RELO4: | ||||
| 			break; | ||||
| 		case RELO4: | ||||
| #ifdef WORDS_REVERSED | ||||
| 		emit2((int)(val>>16)); emit2((int)(val)); | ||||
| 			emit2((int)(val >> 16)); | ||||
| 			emit2((int)(val)); | ||||
| #else | ||||
| 		emit2((int)(val)); emit2((int)(val>>16)); | ||||
| 			emit2((int)(val)); | ||||
| 			emit2((int)(val >> 16)); | ||||
| #endif | ||||
| 		break; | ||||
| 	default: | ||||
| 		assert(0); | ||||
| 			break; | ||||
| 		default: | ||||
| 			assert(0); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| emitstr(int zero) | ||||
| void emitstr(int zero) | ||||
| { | ||||
| 	int i; | ||||
| 	char *p; | ||||
| 	char* p; | ||||
| 
 | ||||
| 	p = stringbuf; | ||||
| 	i = stringlen; | ||||
|  | @ -327,57 +346,92 @@ emitstr(int zero) | |||
| 		emit1(0); | ||||
| } | ||||
| 
 | ||||
| #define CODE_EXPANDER | ||||
| 
 | ||||
| #if !defined IEEEFLOAT && !defined PDPFLOAT | ||||
| 	#define IEEEFLOAT | ||||
| #endif | ||||
| 
 | ||||
| #if defined WORDS_REVERSED | ||||
| 	#define FL_MSL_AT_LOW_ADDRESS 1 | ||||
| 	#define FL_MSW_AT_LOW_ADDRESS 1 | ||||
| #else | ||||
| 	#define FL_MSL_AT_LOW_ADDRESS 0 | ||||
| 	#define FL_MSW_AT_LOW_ADDRESS 0 | ||||
| #endif | ||||
| 
 | ||||
| #if defined BYTES_REVERSED | ||||
| 	#define FL_MSB_AT_LOW_ADDRESS 1 | ||||
| #else | ||||
| 	#define FL_MSB_AT_LOW_ADDRESS 0 | ||||
| #endif | ||||
| 
 | ||||
| #define gen1 emit1 | ||||
| #include <con_float> | ||||
| 
 | ||||
| void emitf(int size, int negative) | ||||
| { | ||||
| 	char buffer[40]; | ||||
| 
 | ||||
| 	if (stringlen > sizeof(buffer)-1) | ||||
| 		fatal("floating point constant too long"); | ||||
| 
 | ||||
| 	if (negative) | ||||
| 	{ | ||||
| 		buffer[0] = '-'; | ||||
| 		strcpy(buffer+1, stringbuf); | ||||
| 		con_float(buffer, size); | ||||
| 	} | ||||
| 	else | ||||
| 		con_float(stringbuf, size); | ||||
| } | ||||
| 
 | ||||
| /* ---------- Error checked file I/O  ---------- */ | ||||
| 
 | ||||
| void | ||||
| ffreopen(char *s, FILE *f) | ||||
| void ffreopen(char* s, FILE* f) | ||||
| { | ||||
| 	if (freopen(s, "r", f) == NULL) | ||||
| 		fatal("can't reopen %s", s); | ||||
| } | ||||
| 
 | ||||
| FILE * | ||||
| ffcreat(char *s) | ||||
| FILE* ffcreat(char* s) | ||||
| { | ||||
| 	FILE *f; | ||||
| 	FILE* f; | ||||
| 
 | ||||
| 	if ((f = fopen(s, "w")) == NULL) | ||||
| 		fatal("can't create %s", s); | ||||
| 	return(f); | ||||
| 	return (f); | ||||
| } | ||||
| 
 | ||||
| #ifndef TMPDIR | ||||
| #define TMPDIR "/tmp" | ||||
| #endif | ||||
| char *tmp_dir = TMPDIR; | ||||
| char* tmp_dir = TMPDIR; | ||||
| 
 | ||||
| FILE * | ||||
| fftemp(char *path, char *tail) | ||||
| FILE* fftemp(char* path, char* tail) | ||||
| { | ||||
| 	char *dir; | ||||
| 	char* dir; | ||||
| 
 | ||||
| 	if ((dir = getenv("TMPDIR")) == NULL) | ||||
| 		dir = tmp_dir; | ||||
| 	sprintf(path, "%s/%s", dir, tail); | ||||
| 	close(mkstemp(path)); | ||||
| 	return(ffcreat(path)); | ||||
| 	return (ffcreat(path)); | ||||
| } | ||||
| 
 | ||||
| /* ---------- Error handling ---------- */ | ||||
| 
 | ||||
| /* ARGSUSED */ | ||||
| void | ||||
| yyerror(const char *message) | ||||
| {}		/* we will do our own error printing */ | ||||
| void yyerror(const char* message) | ||||
| { | ||||
| } /* we will do our own error printing */ | ||||
| 
 | ||||
| void | ||||
| nosect(void) | ||||
| void nosect(void) | ||||
| { | ||||
| 	fatal("no sections"); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| wr_fatal(void) | ||||
| void wr_fatal(void) | ||||
| { | ||||
| 	fatal("write error"); | ||||
| } | ||||
|  | @ -432,8 +486,7 @@ void warning(const char* s, ...) | |||
| 	va_end(ap); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| nofit(void) | ||||
| void nofit(void) | ||||
| { | ||||
| 	if (pass == PASS_3) | ||||
| 		warning("too big"); | ||||
|  |  | |||
|  | @ -85,6 +85,7 @@ int regallowed=0; | |||
| extern char em_flag[]; | ||||
| extern short em_ptyp[]; | ||||
| extern double atof(); | ||||
| extern void con_float(void); | ||||
| 
 | ||||
| /* Own version of atol that continues computing on overflow.
 | ||||
|    We don't know that about the ANSI C one. | ||||
|  |  | |||
|  | @ -35,7 +35,6 @@ definerule("build_mcg", | |||
| 				"modules/src/data+lib", | ||||
| 				"modules/src/em_code+lib_k", | ||||
| 				"modules/src/em_data+lib", | ||||
| 				"modules/src/flt_arith+lib", | ||||
| 				"modules/src/idf+lib", | ||||
| 				"modules/src/object+lib", | ||||
| 				"modules/src/read_em+lib_kv", | ||||
|  |  | |||
|  | @ -1,13 +1,6 @@ | |||
| #include "mcg.h" | ||||
| #include <ctype.h> | ||||
| 
 | ||||
| #define IEEEFLOAT | ||||
| #define FL_MSL_AT_LOW_ADDRESS 1 | ||||
| #define FL_MSW_AT_LOW_ADDRESS 1 | ||||
| #define FL_MSB_AT_LOW_ADDRESS 1 | ||||
| 
 | ||||
| #include "con_float" | ||||
| 
 | ||||
| static struct symbol* pending; | ||||
| 
 | ||||
| void data_label(const char* label) | ||||
|  | @ -66,7 +59,7 @@ void data_int(arith data, size_t size, bool is_ro) | |||
| { | ||||
| 	emit_header(is_ro ? SECTION_ROM : SECTION_DATA); | ||||
|     assert((size == 1) || (size == 2) || (size == 4) || (size == 8)); | ||||
|     fprintf(outputfile, "\t.data%d ", size); | ||||
|     fprintf(outputfile, "\t.data%ld ", size); | ||||
|     writehex(data, size); | ||||
|     fprintf(outputfile, "\n"); | ||||
| } | ||||
|  | @ -80,19 +73,7 @@ void data_float(const char* data, size_t size, bool is_ro) | |||
| 	emit_header(is_ro ? SECTION_ROM : SECTION_DATA); | ||||
|     assert((size == 4) || (size == 8)); | ||||
| 
 | ||||
|     i = float_cst(data, size, (char*) buffer); | ||||
|     if ((i != 0) && (i != 2)) /* 2 == overflow */ | ||||
|         fatal("cannot parse floating point constant %s sz %d", data, size); | ||||
| 
 | ||||
|     fprintf(outputfile, "\t!float %s sz %d\n", data, size); | ||||
|     fprintf(outputfile, "\t.data1 "); | ||||
|     writehex(buffer[0], 1); | ||||
|     for (i=1; i<size; i++) | ||||
|     { | ||||
|         fprintf(outputfile, ", "); | ||||
|         writehex(buffer[i], 1); | ||||
|     } | ||||
|     fprintf(outputfile, "\n"); | ||||
|     fprintf(outputfile, "\t.dataf%ld %s\n", size, data); | ||||
| } | ||||
| 
 | ||||
| static bool istext(c) | ||||
|  | @ -149,7 +130,7 @@ void data_block(const uint8_t* data, size_t size, bool is_ro) | |||
| void data_offset(const char* label, arith offset, bool is_ro) | ||||
| { | ||||
| 	emit_header(is_ro ? SECTION_ROM : SECTION_DATA); | ||||
|     fprintf(outputfile, "\t.data%d %s+%lld\n", | ||||
|     fprintf(outputfile, "\t.data%d %s+%ld\n", | ||||
|         EM_pointersize, platform_label(label), offset); | ||||
| } | ||||
| 
 | ||||
|  | @ -159,7 +140,7 @@ void data_bss(arith size, int init) | |||
|         fatal("non-zero-initialised bss not supported"); | ||||
| 
 | ||||
|     emit_header(SECTION_BSS); | ||||
|     fprintf(outputfile, "\t.space %lld\n", size); | ||||
|     fprintf(outputfile, "\t.space %ld\n", size); | ||||
| } | ||||
| 
 | ||||
| /* vim: set sw=4 ts=4 expandtab : */ | ||||
|  |  | |||
|  | @ -8,7 +8,6 @@ | |||
| #include <stdint.h> | ||||
| #include <string.h> | ||||
| #include <assert.h> | ||||
| #include "flt_arith.h" | ||||
| #include "em_arith.h" | ||||
| #include "em_label.h" | ||||
| #include "em.h" | ||||
|  | @ -123,7 +122,7 @@ extern void pass_wire_up_return_values(void); | |||
| extern void platform_calculate_offsets(void); | ||||
| extern struct hop* platform_prologue(void); | ||||
| extern struct hop* platform_epilogue(void); | ||||
| extern struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* dest); | ||||
| extern struct hop* platform_move(struct basicblock* bb, struct vreg* vreg, struct hreg* src, struct hreg* dest); | ||||
| extern struct hop* platform_swap(struct basicblock* bb, struct hreg* src, struct hreg* dest); | ||||
| extern const char* platform_label(const char* label); | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ extern void burm_panic_cannot_match(NODEPTR_TYPE node); | |||
| extern bool burm_predicate_signed_constant(struct burm_node* node, arith size); | ||||
| extern bool burm_predicate_unsigned_constant(struct burm_node* node, arith size); | ||||
| extern bool burm_predicate_specific_constant(struct burm_node* node, arith value); | ||||
| extern bool burm_predicate_constant_within_inclusive_range(struct burm_node* node, arith min, arith max); | ||||
| 
 | ||||
| /* vim: set sw=4 ts=4 expandtab : */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -181,6 +181,36 @@ static void queue_ilabel(arith label) | |||
|     change_basicblock(bb_get(ilabel_to_str(label))); | ||||
| } | ||||
| 
 | ||||
| /* This is really hacky; to handle basic block flow
 | ||||
|  * descriptor blocks, we need to be able to identify | ||||
|  * them, read them and parse them. So we create | ||||
|  * can exit to. So we create fake bb objects for each | ||||
|  * block, purely to track this, and copy ints and labels | ||||
|  * into them. | ||||
|  */ | ||||
| 
 | ||||
| static void data_block_int(arith value) | ||||
| { | ||||
| 	if (data_bb) | ||||
| 	{ | ||||
| 		struct em* em = new_insn(op_loc); | ||||
| 		em->paramtype = PARAM_IVALUE; | ||||
| 		em->u.ivalue = value; | ||||
| 		array_append(&data_bb->ems, em); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void data_block_label(const char* label) | ||||
| { | ||||
| 	if (data_bb) | ||||
| 	{ | ||||
| 		struct em* em = new_insn(op_bra); | ||||
| 		em->paramtype = PARAM_BVALUE; | ||||
| 		em->u.bvalue.left = bb_get(label); | ||||
| 		array_append(&data_bb->ems, em); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void parse_pseu(void) | ||||
| { | ||||
| 	switch (em.em_opcode) | ||||
|  | @ -227,6 +257,7 @@ static void parse_pseu(void) | |||
|                 { | ||||
|                     arith val = atol(em.em_string); | ||||
|                     data_int(val, em.em_size, ro); | ||||
|                     data_block_int(val); | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|  | @ -237,12 +268,16 @@ static void parse_pseu(void) | |||
|                 } | ||||
| 
 | ||||
| 				case str_ptyp: | ||||
|                     data_block(strdup(em.em_string), em.em_size, ro); | ||||
|                     data_block((const uint8_t*) strdup(em.em_string), em.em_size, ro); | ||||
| 					break; | ||||
| 
 | ||||
|                 case cst_ptyp: | ||||
|                     data_int(em.em_cst, EM_wordsize, ro); | ||||
|                 { | ||||
|                     arith value = em.em_cst; | ||||
|                     data_int(value, EM_wordsize, ro); | ||||
|                     data_block_int(value); | ||||
|                     break; | ||||
| 				} | ||||
|                      | ||||
|                 case nof_ptyp: | ||||
|                     data_offset(dlabel_to_str(em.em_dlb), em.em_off, ro); | ||||
|  | @ -256,22 +291,8 @@ static void parse_pseu(void) | |||
|                 case ilb_ptyp: | ||||
|                 { | ||||
|                     const char* label = ilabel_to_str(em.em_ilb); | ||||
| 
 | ||||
|                     /* This is really hacky; to handle basic block flow
 | ||||
|                      * descriptor blocks, we need to track which bbs a descriptor | ||||
|                      * can exit to. So we create fake bb objects for each | ||||
|                      * block, purely to track this. | ||||
|                      */ | ||||
| 
 | ||||
|                     if (data_bb) | ||||
|                     { | ||||
|                         struct em* em = new_insn(op_bra); | ||||
|                         em->paramtype = PARAM_BVALUE; | ||||
|                         em->u.bvalue.left = bb_get(label); | ||||
|                         array_append(&data_bb->ems, em); | ||||
|                     } | ||||
| 
 | ||||
|                     data_offset(label, 0, ro); | ||||
|                     data_block_label(label); | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|  | @ -384,9 +405,12 @@ static void create_data_label(const char* label) | |||
|     data_label(label); | ||||
|     if (current_proc) | ||||
|     { | ||||
|         /* Create the fake bb used to track values inside this data block
 | ||||
|          * (as it's a chance it's a jump table which we'll need to process | ||||
|          * later). | ||||
|          */ | ||||
|         data_bb = bb_get(label); | ||||
|         data_bb->is_fake = true; | ||||
|         array_append(¤t_proc->blocks, data_bb); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ static void make_phimap(void) | |||
| 	{ | ||||
| 		struct basicblock* bb = cfg.preorder.item[i]; | ||||
| 
 | ||||
| 		/* Registers imported through a phi can come from multiple locations. */ | ||||
| 		for (j=0; j<bb->phis.count; j++) | ||||
| 		{ | ||||
| 			struct vreg* vreg = bb->phis.item[j].left; | ||||
|  | @ -37,7 +38,9 @@ static void recursively_associate_group(struct phicongruence* c, struct vreg* vr | |||
|         if (c->type == 0) | ||||
|             c->type = vreg->type; | ||||
| 
 | ||||
|         assert(c->type == vreg->type); | ||||
|         if (c->type != vreg->type) | ||||
|             fatal("tried to add register %%%d of type 0x%x to a phi congruence group of type 0x%x", | ||||
|                 vreg->id, vreg->type, c->type); | ||||
| 
 | ||||
|         array_appendu(&c->definitions, vreg->defined); | ||||
|     } | ||||
|  |  | |||
|  | @ -386,16 +386,28 @@ static void find_new_home_for_evicted_register(struct vreg* vreg, struct hreg* s | |||
|     for (i=0; i<hregs.count; i++) | ||||
|     { | ||||
|         hreg = hregs.item[i]; | ||||
|         if ((hreg->attrs & srctype) && | ||||
|         if (!hreg->is_stacked && (hreg->attrs & srctype) && | ||||
|             allocatable_through(hreg, vreg)) | ||||
|         { | ||||
|             goto found; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /* No more registers --- allocate a stack slot. */ | ||||
|     /* No more registers --- allocate a stack slot. Ensure that we use the same stack
 | ||||
|      * slot for this vreg throughout the function. */ | ||||
| 
 | ||||
|     hreg = new_stacked_hreg(srctype); | ||||
| 	hreg = vreg->evicted; | ||||
| 	if (!hreg) | ||||
| 	{ | ||||
| 		if (vreg->congruence) | ||||
| 			hreg = vreg->evicted = vreg->congruence->evicted; | ||||
| 		if (!hreg) | ||||
| 		{ | ||||
| 			hreg = vreg->evicted = new_stacked_hreg(srctype); | ||||
| 			if (vreg->congruence) | ||||
| 				vreg->congruence->evicted = hreg; | ||||
| 		} | ||||
| 	} | ||||
|     array_append(&hregs, hreg); | ||||
| 
 | ||||
| found: | ||||
|  | @ -480,7 +492,7 @@ static void assign_hregs_to_vregs(void) | |||
|                 { | ||||
|                     tracef('R', "R: import hreg %s for input %%%d from %s\n", | ||||
|                         hreg->id, vreg->id, prevbb->name); | ||||
|                     assert(!pmap_findleft(old, hreg)); | ||||
|                     assert(!register_used(old, hreg)); | ||||
|                     pmap_put(old, hreg, vreg); | ||||
|                     goto nextvreg; | ||||
|                 } | ||||
|  | @ -506,7 +518,7 @@ static void assign_hregs_to_vregs(void) | |||
| 
 | ||||
|                 struct hreg* hreg = pmap_findright( | ||||
|                     phi->prev->regsout, phi->ir->result); | ||||
|                 if (hreg && !pmap_findleft(old, hreg)) | ||||
|                 if (hreg && !register_used(old, hreg)) | ||||
|                 { | ||||
|                     tracef('R', "R: import hreg %s for %%%d, imported from %s %%%d\n", | ||||
|                         hreg->id, vreg->id, | ||||
|  | @ -617,7 +629,8 @@ static int insert_moves(struct basicblock* bb, int index, | |||
|         { | ||||
|             /* Copy. */ | ||||
| 
 | ||||
|             hop = platform_move(bb, src, dest); | ||||
| 			struct vreg* vreg = pmap_findleft(srcregs, src); | ||||
|             hop = platform_move(bb, vreg, src, dest); | ||||
|             pmap_remove(&copies, src, dest); | ||||
|         } | ||||
|         else | ||||
|  | @ -710,13 +723,17 @@ static void insert_phi_copies(void) | |||
| 
 | ||||
|             for (k=0; k<bb->regsin.count; k++) | ||||
|             { | ||||
|                 struct hreg*hreg = bb->regsin.item[k].left; | ||||
|                 struct hreg* hreg = bb->regsin.item[k].left; | ||||
|                 struct vreg* vreg = bb->regsin.item[k].right; | ||||
|                 struct hreg* src = pmap_findright(prevbb->regsout, vreg); | ||||
|                 if (!pmap_findleft(&bb->phis, vreg)) | ||||
|                 { | ||||
|                     tracef('R', "R: input map %%%d (%s) -> (%s)\n", | ||||
|                         vreg->id, src->id, hreg->id); | ||||
|                     if ((src->id != hreg->id) && src->is_stacked && hreg->is_stacked) | ||||
|                         fatal("vreg %%%d is stacked in %s on entry to %s, but is passed in in %s from %s", | ||||
|                             vreg->id, hreg->id, bb->name, | ||||
|                             src->id, prevbb->name); | ||||
| 
 | ||||
|                     pmap_add(&destregs, hreg, vreg); | ||||
|                 } | ||||
|  |  | |||
|  | @ -27,6 +27,14 @@ bool burm_predicate_specific_constant(struct burm_node* node, arith val) | |||
|     return ir->u.ivalue == val; | ||||
| } | ||||
| 
 | ||||
| bool burm_predicate_constant_within_inclusive_range(struct burm_node* node, arith min, arith max) | ||||
| { | ||||
| 	struct ir* ir = node->ir; | ||||
| 	assert(ir->opcode == IR_CONST); | ||||
| 
 | ||||
|     return (ir->u.ivalue >= min) && (ir->u.ivalue <= max); | ||||
| } | ||||
| 
 | ||||
| /* vim: set sw=4 ts=4 expandtab : */ | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -38,6 +38,18 @@ static void print_blocks(char k) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void print_vreg(char k, register_assignment_t* assignments, struct vreg* vreg) | ||||
| { | ||||
| 	struct hreg* hreg; | ||||
| 	tracef(k, "%%%d", vreg->id); | ||||
| 	if (assignments) | ||||
| 	{ | ||||
| 		hreg = pmap_findright(assignments, vreg); | ||||
| 		if (hreg) | ||||
| 			tracef(k, "(%s)", hreg->id); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void print_hops(char k) | ||||
| { | ||||
|     int i; | ||||
|  | @ -73,7 +85,10 @@ static void print_hops(char k) | |||
|         { | ||||
|             tracef(k, "%c:  INS:", k); | ||||
|             for (j=0; j<bb->liveins.count; j++) | ||||
|                 tracef(k, " %%%d", bb->liveins.item[j]->id); | ||||
|             { | ||||
|                 tracef(k, " "); | ||||
|                 print_vreg(k, &bb->regsin, bb->liveins.item[j]); | ||||
| 			} | ||||
|             tracef(k, "\n"); | ||||
|         } | ||||
| 
 | ||||
|  | @ -81,7 +96,10 @@ static void print_hops(char k) | |||
|         { | ||||
|             tracef(k, "%c: OUTS:", k); | ||||
|             for (j=0; j<bb->liveouts.count; j++) | ||||
|                 tracef(k, " %%%d", bb->liveouts.item[j]->id); | ||||
|             { | ||||
|                 tracef(k, " "); | ||||
|                 print_vreg(k, bb->regsout, bb->liveouts.item[j]); | ||||
| 			} | ||||
|             tracef(k, "\n"); | ||||
|         } | ||||
| 
 | ||||
|  | @ -93,10 +111,10 @@ static void print_hops(char k) | |||
|                 struct vreg* vreg = bb->phis.item[j].left; | ||||
|                 struct phi* phi = bb->phis.item[j].right; | ||||
| 
 | ||||
|                 tracef(k, " %%%d(via %s)=>%%%d", | ||||
|                 tracef(k, " %%%d(via %s)=>", | ||||
|                     phi->ir->result->id, | ||||
|                     phi->prev->name, | ||||
|                     vreg->id); | ||||
|                     phi->prev->name); | ||||
|                 print_vreg(k, &bb->regsin, vreg); | ||||
|             } | ||||
|             tracef(k, "\n"); | ||||
|         } | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ struct phicongruence | |||
|     ARRAYOF(struct vreg) vregs; | ||||
|     ARRAYOF(struct hop) definitions; | ||||
|     uint32_t type; | ||||
|     struct hreg* evicted; /* stack slot to evict to */ | ||||
| }; | ||||
| 
 | ||||
| struct hreg | ||||
|  | @ -28,6 +29,7 @@ struct vreg | |||
|     struct phicongruence* congruence; | ||||
|     struct hop* defined; | ||||
|     ARRAYOF(struct hop) used; | ||||
|     struct hreg* evicted; /* stack slot to evict to */ | ||||
| }; | ||||
| 
 | ||||
| typedef PMAPOF(struct hreg, struct vreg) register_assignment_t; | ||||
|  |  | |||
|  | @ -5,10 +5,20 @@ static struct basicblock* current_bb; | |||
| static int stackptr; | ||||
| static struct ir* stack[64]; | ||||
| 
 | ||||
| struct jumptable | ||||
| { | ||||
| 	struct basicblock* defaulttarget; | ||||
| 	IMAPOF(struct basicblock) targets; | ||||
| }; | ||||
| 
 | ||||
| static struct ir* convert(struct ir* src, int srcsize, int destsize, int opcode); | ||||
| static struct ir* appendir(struct ir* ir); | ||||
| static void insn_ivalue(int opcode, arith value); | ||||
| 
 | ||||
| static void parse_csa(struct basicblock* data_bb, struct jumptable* table); | ||||
| static void parse_csb(struct basicblock* data_bb, struct jumptable* table); | ||||
| static void emit_jumptable(struct ir* targetvalue, struct jumptable* table); | ||||
| 
 | ||||
| static void reset_stack(void) | ||||
| { | ||||
|     stackptr = 0; | ||||
|  | @ -85,6 +95,8 @@ static struct ir* pop(int size) | |||
|             } | ||||
|             else if ((size == EM_wordsize) && (ir->size == (EM_wordsize*2))) | ||||
|             { | ||||
|                 appendir(ir); | ||||
| 
 | ||||
|                 /* Tried to read an int, but we got a long. */ | ||||
|                 push( | ||||
|                     new_ir1( | ||||
|  | @ -553,6 +565,7 @@ static void insn_simple(int opcode) | |||
|         { | ||||
|             struct ir* label = new_labelir(".trppc"); | ||||
|             struct ir* value = pop(EM_pointersize); | ||||
|             appendir(label); /* because we need to use label twice */ | ||||
|             push( | ||||
|                 load( | ||||
|                     EM_pointersize, | ||||
|  | @ -717,6 +730,10 @@ static void rotate(int opcode, int size, int irop, int irop_reverse) | |||
|         struct ir* left = pop(size); | ||||
|         struct ir* bits = new_wordir(8 * size); | ||||
| 
 | ||||
|         /* Fix left and right so we can refer to them multiple times. */ | ||||
|         appendir(right); | ||||
|         appendir(left); | ||||
| 
 | ||||
|         /* a rol b -> (a << b) | (a >> (32 - b)) */ | ||||
|         push( | ||||
|             new_ir2( | ||||
|  | @ -732,27 +749,6 @@ static void rotate(int opcode, int size, int irop, int irop_reverse) | |||
|     } | ||||
| } | ||||
| 
 | ||||
| static struct ir* extract_block_refs(struct basicblock* bb) | ||||
| { | ||||
|     struct ir* outir = NULL; | ||||
|     int i; | ||||
| 
 | ||||
|     for (i=0; i<bb->ems.count; i++) | ||||
|     { | ||||
|         struct em* em = bb->ems.item[i]; | ||||
|         assert(em->opcode == op_bra); | ||||
|         assert(em->paramtype == PARAM_BVALUE); | ||||
| 
 | ||||
|         outir = new_ir2( | ||||
|             IR_PAIR, 0, | ||||
|             new_bbir(em->u.bvalue.left), | ||||
|             outir | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     return outir; | ||||
| } | ||||
| 
 | ||||
| static void change_by(struct ir* address, int amount) | ||||
| { | ||||
|     appendir( | ||||
|  | @ -1332,25 +1328,34 @@ static void insn_ivalue(int opcode, arith value) | |||
|         } | ||||
| 
 | ||||
|         case op_csa: | ||||
|         case op_csb: | ||||
|         { | ||||
|             const char* helper = aprintf(".%s", | ||||
|                 (opcode == op_csa) ? "csa" : "csb"); | ||||
|             struct ir* descriptor = pop(EM_pointersize); | ||||
|             struct ir* targetvalue = appendir(pop(EM_pointersize)); | ||||
|             struct jumptable jumptable = {}; | ||||
|             int i; | ||||
| 
 | ||||
|             if (descriptor->opcode != IR_LABEL) | ||||
|                 fatal("csa/csb are only supported if they refer " | ||||
|                 fatal("csa is only supported if it refers " | ||||
|                     "directly to a descriptor block"); | ||||
| 
 | ||||
|             push(descriptor); | ||||
|             materialise_stack(); | ||||
|             appendir( | ||||
|                 new_ir2( | ||||
|                     IR_FARJUMP, 0, | ||||
|                     new_labelir(helper), | ||||
|                     extract_block_refs(bb_get(descriptor->u.lvalue)) | ||||
|                 ) | ||||
|             ); | ||||
| 			parse_csa(bb_get(descriptor->u.lvalue), &jumptable); | ||||
| 			emit_jumptable(targetvalue, &jumptable); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         case op_csb: | ||||
|         { | ||||
|             struct ir* descriptor = pop(EM_pointersize); | ||||
|             struct ir* targetvalue = appendir(pop(EM_pointersize)); | ||||
|             struct jumptable jumptable = {}; | ||||
|             int i; | ||||
| 
 | ||||
|             if (descriptor->opcode != IR_LABEL) | ||||
|                 fatal("csb is only supported if it refers " | ||||
|                     "directly to a descriptor block"); | ||||
| 
 | ||||
| 			parse_csb(bb_get(descriptor->u.lvalue), &jumptable); | ||||
| 			emit_jumptable(targetvalue, &jumptable); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|  | @ -1755,4 +1760,133 @@ void tb_procedure(void) | |||
|         generate_tree(current_proc->blocks.item[i]); | ||||
| } | ||||
| 
 | ||||
| static void parse_csa(struct basicblock* data_bb, struct jumptable* table) | ||||
| { | ||||
| 	struct em* em; | ||||
| 	int lowerbound; | ||||
| 	int count; | ||||
| 	int i; | ||||
| 
 | ||||
| 	assert(data_bb->ems.count >= 3); | ||||
| 
 | ||||
| 	/* Default target */ | ||||
| 
 | ||||
| 	em = data_bb->ems.item[0]; | ||||
| 	assert(em->opcode == op_bra); | ||||
| 	assert(em->paramtype == PARAM_BVALUE); | ||||
| 	table->defaulttarget = em->u.bvalue.left; | ||||
| 
 | ||||
| 	/* Lower bound */ | ||||
| 
 | ||||
| 	em = data_bb->ems.item[1]; | ||||
| 	assert(em->opcode == op_loc); | ||||
| 	assert(em->paramtype == PARAM_IVALUE); | ||||
| 	lowerbound = em->u.ivalue; | ||||
| 
 | ||||
| 	/* Count */ | ||||
| 
 | ||||
| 	em = data_bb->ems.item[2]; | ||||
| 	assert(em->opcode == op_loc); | ||||
| 	assert(em->paramtype == PARAM_IVALUE); | ||||
| 	count = em->u.ivalue + 1; /* value in descriptor is inclusive */ | ||||
| 	assert(data_bb->ems.count >= (count + 3)); | ||||
| 
 | ||||
| 	/* Now, each target in turn. */ | ||||
| 
 | ||||
| 	for (i=0; i<count; i++) | ||||
| 	{ | ||||
| 		struct basicblock* target; | ||||
| 
 | ||||
| 		em = data_bb->ems.item[3 + i]; | ||||
| 		assert(em->opcode == op_bra); | ||||
| 		assert(em->paramtype == PARAM_BVALUE); | ||||
| 		target = em->u.bvalue.left; | ||||
| 
 | ||||
| 		imap_put(&table->targets, lowerbound+i, target); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void parse_csb(struct basicblock* data_bb, struct jumptable* table) | ||||
| { | ||||
| 	struct em* em; | ||||
| 	int count; | ||||
| 	int i; | ||||
| 
 | ||||
| 	assert(data_bb->ems.count >= 2); | ||||
| 
 | ||||
| 	/* Default target */ | ||||
| 
 | ||||
| 	em = data_bb->ems.item[0]; | ||||
| 	assert(em->opcode == op_bra); | ||||
| 	assert(em->paramtype == PARAM_BVALUE); | ||||
| 	table->defaulttarget = em->u.bvalue.left; | ||||
| 
 | ||||
| 	/* Number of targets */ | ||||
| 
 | ||||
| 	em = data_bb->ems.item[1]; | ||||
| 	assert(em->opcode == op_loc); | ||||
| 	assert(em->paramtype == PARAM_IVALUE); | ||||
| 	count = em->u.ivalue; | ||||
| 	assert(data_bb->ems.count >= (count*2 + 2)); | ||||
| 
 | ||||
| 	/* Now, each target in turn. */ | ||||
| 
 | ||||
| 	for (i=0; i<count; i++) | ||||
| 	{ | ||||
| 		int value; | ||||
| 		struct basicblock* target; | ||||
| 
 | ||||
| 		em = data_bb->ems.item[2 + i*2]; | ||||
| 		assert(em->opcode == op_loc); | ||||
| 		assert(em->paramtype == PARAM_IVALUE); | ||||
| 		value = em->u.ivalue; | ||||
| 
 | ||||
| 		em = data_bb->ems.item[3 + i*2]; | ||||
| 		assert(em->opcode == op_bra); | ||||
| 		assert(em->paramtype == PARAM_BVALUE); | ||||
| 		target = em->u.bvalue.left; | ||||
| 
 | ||||
| 		imap_put(&table->targets, value, target); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void emit_jumptable(struct ir* targetvalue, struct jumptable* jumptable) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| 	materialise_stack(); | ||||
| 	for (i=0; i<jumptable->targets.count; i++) | ||||
| 	{ | ||||
| 		int value = jumptable->targets.item[i].left; | ||||
| 		struct basicblock* target = jumptable->targets.item[i].right; | ||||
| 		struct basicblock* nextblock = bb_get(NULL); | ||||
| 
 | ||||
| 		array_append(¤t_proc->blocks, nextblock); | ||||
| 		appendir( | ||||
| 			new_ir2( | ||||
| 				IR_CJUMPEQ, 0, | ||||
| 				new_ir2( | ||||
| 					IR_COMPARESI, EM_wordsize, | ||||
| 					targetvalue, | ||||
| 					new_wordir(value) | ||||
| 				), | ||||
| 				new_ir2( | ||||
| 					IR_PAIR, 0, | ||||
| 					new_bbir(target), | ||||
| 					new_bbir(nextblock) | ||||
| 				) | ||||
| 			) | ||||
| 		); | ||||
| 
 | ||||
| 		current_bb = nextblock; | ||||
| 	} | ||||
| 
 | ||||
| 	appendir( | ||||
| 		new_ir1( | ||||
| 			IR_JUMP, 0, | ||||
| 			new_bbir(jumptable->defaulttarget) | ||||
| 		) | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| /* vim: set sw=4 ts=4 expandtab : */ | ||||
|  |  | |||
|  | @ -83,7 +83,7 @@ extern short em_ptyp[]; | |||
| /* machine dependent */ | ||||
| void con_part(int, word); | ||||
| void con_mult(word); | ||||
| int con_float(void); /* actually returns void, but need K&R C compatibility */ | ||||
| void con_float(void); /* actually returns void, but need K&R C compatibility */ | ||||
| void prolog(full nlocals); | ||||
| void mes(word); | ||||
| 
 | ||||
|  |  | |||
|  | @ -206,6 +206,16 @@ This is not followed by automatic alignment. | |||
| .Pu ".data4 \fIexpression [, expression]*\fP" | ||||
| Initialize a sequence of longs (4-byte values). | ||||
| This is not followed by automatic alignment. | ||||
| .Pu ".dataf4 \fIliteralfloat [, literalfloat]*\fP" | ||||
| Initialize a sequence of floats (4-byte values). | ||||
| The values must be literal floating point constants containing | ||||
| a dot character. | ||||
| This is not followed by automatic alignment. | ||||
| .Pu ".dataf8 \fIliteralfloat [, literalfloat]*\fP" | ||||
| Initialize a sequence of doubles (8-byte values). | ||||
| The values must be literal floating point constants containing | ||||
| a dot character. | ||||
| This is not followed by automatic alignment. | ||||
| .Pu ".ascii \fIstring\fP" | ||||
| Initialize a sequence of bytes with the value of the bytes in | ||||
| the string. | ||||
|  |  | |||
							
								
								
									
										37
									
								
								plat/linuxmips/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								plat/linuxmips/README
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| The linuxmips platform | ||||
| ====================== | ||||
| 
 | ||||
| linuxmips is a little-endian MIPS32r2 BSP that produces Linux MIPS executables. | ||||
| 
 | ||||
| This port only implements a very limited number of system calls; basically, | ||||
| just enough to make the demo apps run. Adding more is easy, but there are some | ||||
| subtleties that require more thought. The port should be considered only in | ||||
| proof-of-concept stage right now. | ||||
| 
 | ||||
| Important note: you *can't* link access ELF shared libraries from these | ||||
| executables. In other words, you have to all your work from inside ACK. | ||||
| 
 | ||||
| IEEE floating point is available, but requires an FPU. | ||||
| 
 | ||||
| The executables are generated with aelfslod and are extremely simple; there's | ||||
| one rwx ELF section which contains all the application's code and data. This | ||||
| is not optimal, but it does work. Symbols are provided. | ||||
| 
 | ||||
| 
 | ||||
| Bugs | ||||
| ==== | ||||
| 
 | ||||
| isatty() is a stub and always returns 0. | ||||
| 
 | ||||
| 
 | ||||
| Example command line | ||||
| ==================== | ||||
| 
 | ||||
| ack -mlinuxmips -O -o linuxmips.exe examples/paranoia.c | ||||
| 
 | ||||
| The file linuxmips.exe can then be run on a MIPS32r2 Linux machine (or on an | ||||
| emulation thereof). | ||||
| 
 | ||||
| 
 | ||||
| David Given | ||||
| dg@cowlark.com | ||||
							
								
								
									
										58
									
								
								plat/linuxmips/boot.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								plat/linuxmips/boot.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | |||
| # | ||||
| ! Declare segments (the order is important). | ||||
| 
 | ||||
| .sect .text | ||||
| .sect .rom | ||||
| .sect .data | ||||
| .sect .bss | ||||
| 
 | ||||
| .sect .text | ||||
| 
 | ||||
| .define .entry | ||||
| .entry: | ||||
| 	! This code is placed at the beginning of the ELF executable and is the | ||||
| 	! first thing that runs. | ||||
| 	! | ||||
| 	! On entry, the stack looks like this: | ||||
| 	! | ||||
| 	! sp+...          NULL | ||||
| 	! sp+8+(4*argc)   env (X quads) | ||||
| 	! sp+4+(4*argc)   NULL | ||||
| 	! sp+4            argv (argc quads) | ||||
| 	! sp              argc | ||||
| 	! | ||||
| 	! The ACK actually expects: | ||||
| 	! | ||||
| 	! sp+8            argc | ||||
| 	! sp+4            ptr to argv | ||||
| 	! sp              ptr to env | ||||
| 
 | ||||
| 	lw r4, 0(sp)             ! r4 = argc | ||||
| 	addiu r5, sp, 4          ! r5 = argv | ||||
| 	sll r6, r4, 2            ! r6 = argc*4 | ||||
| 	addu r6, r6, r5          ! r6 = null after last arg | ||||
| 	addiu r6, r6, 4          ! r6 = env | ||||
| 
 | ||||
| 	addiu sp, sp, -3 * 4 | ||||
| 	sw r4, 0(sp)			 ! argc | ||||
| 	sw r5, 4(sp)			 ! argv | ||||
| 	sw r6, 8(sp)			 ! envp | ||||
| 
 | ||||
| 	j __m_a_i_n | ||||
| 	nop | ||||
| 
 | ||||
| ! Define symbols at the beginning of our various segments, so that we can find | ||||
| ! them. (Except .text, which has already been done.) | ||||
| 
 | ||||
| .sect .data;       begdata:
 | ||||
| .sect .rom;        begrom:
 | ||||
| .sect .bss;        begbss:
 | ||||
| 
 | ||||
| ! Some magic data. All EM systems need these. | ||||
| 
 | ||||
| .define _errno
 | ||||
| .comm _errno, 4              ! Posix errno storage | ||||
| 
 | ||||
| .define .trppc, .ignmask | ||||
| .comm .trppc, 4              ! ptr to user trap handler | ||||
| .comm .ignmask, 4            ! user trap ignore mask  | ||||
							
								
								
									
										25
									
								
								plat/linuxmips/build-pkg.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								plat/linuxmips/build-pkg.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| include("plat/build.lua") | ||||
| 
 | ||||
| ackfile { | ||||
| 	name = "boot", | ||||
| 	srcs = { "./boot.s" }, | ||||
| 	vars = { plat = "linuxmips" } | ||||
| } | ||||
| 
 | ||||
| build_plat_libs { | ||||
| 	name = "libs", | ||||
| 	arch = "mips", | ||||
| 	plat = "linuxmips", | ||||
| } | ||||
| 
 | ||||
| installable { | ||||
| 	name = "pkg", | ||||
| 	map = { | ||||
| 		"+tools", | ||||
| 		"+libs", | ||||
| 		"./include+pkg", | ||||
| 		["$(PLATIND)/linuxmips/boot.o"] = "+boot", | ||||
|         ["$(PLATIND)/linuxmips/libsys.a"] = "./libsys+lib", | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										29
									
								
								plat/linuxmips/build-tools.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								plat/linuxmips/build-tools.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | |||
| include("plat/build.lua") | ||||
| 
 | ||||
| build_as { | ||||
| 	name = "as", | ||||
| 	arch = "mips", | ||||
| 	deps = { "mach/mips/as+astables" } | ||||
| } | ||||
| 
 | ||||
| build_mcg { | ||||
| 	name = "mcg", | ||||
| 	arch = "mips", | ||||
| } | ||||
| 
 | ||||
| build_top { | ||||
| 	name = "top", | ||||
| 	arch = "mips", | ||||
| } | ||||
| 
 | ||||
| return installable { | ||||
| 	name = "tools", | ||||
| 	map = { | ||||
| 		["$(PLATDEP)/linuxmips/as"] = "+as", | ||||
| 		["$(PLATDEP)/linuxmips/mcg"] = "+mcg", | ||||
| 		["$(PLATDEP)/linuxmips/top"] = "+top", | ||||
| 		["$(PLATIND)/descr/linuxmips"] = "./descr", | ||||
| 		"util/amisc+aelflod-pkg", | ||||
| 		"util/opt+pkg", | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										87
									
								
								plat/linuxmips/descr
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								plat/linuxmips/descr
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,87 @@ | |||
| # plat/linuxppc/descr | ||||
| 
 | ||||
| var w=4 | ||||
| var wa=4 | ||||
| var p={w} | ||||
| var pa={w} | ||||
| var s=2 | ||||
| var sa={s} | ||||
| var l={w} | ||||
| var la={w} | ||||
| var f={w} | ||||
| var fa={w} | ||||
| var d=8 | ||||
| var da={d} | ||||
| var x=8 | ||||
| var xa={x} | ||||
| var ARCH=mips | ||||
| var PLATFORM=linuxmips | ||||
| var PLATFORMDIR={EM}/share/ack/{PLATFORM} | ||||
| var CPP_F=-D__unix | ||||
| var ALIGN=-a0:8 -a1:8 -a2:8 -a3:8 -b0:0x00400058 | ||||
| var MACHOPT_F=-m2 | ||||
| #var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr | ||||
| 
 | ||||
| # Override the setting in fe so that files compiled for linuxppc can see | ||||
| # the platform-specific headers. | ||||
| 
 | ||||
| var C_INCLUDES=-I{EM}/share/ack/linux/include -I{EM}/share/ack/include/ansi | ||||
| 
 | ||||
| name be | ||||
| 	from .m.g | ||||
| 	to .s | ||||
| 	program {EM}/lib/ack/{PLATFORM}/mcg | ||||
| 	mapflag -gdb GF=-gdb | ||||
| 	args {GF?} < | ||||
| 	stdout | ||||
| 	need .e | ||||
| end | ||||
| name asopt | ||||
| 	from .s | ||||
| 	to .so | ||||
| 	program {EM}/lib/ack/{PLATFORM}/top | ||||
| 	args | ||||
| 	optimizer | ||||
| 	stdin | ||||
| 	stdout | ||||
| end | ||||
| name as | ||||
| 	from .s.so | ||||
| 	to .o | ||||
| 	program {EM}/lib/ack/{PLATFORM}/as | ||||
| 	args - -o > < | ||||
| 	prep cond | ||||
| end | ||||
| name led | ||||
| 	from .o.a | ||||
| 	to .out | ||||
| 	program {EM}/lib/ack/em_led | ||||
| 	mapflag -l* LNAME={PLATFORMDIR}/lib* | ||||
| 	mapflag -fp FLOATS={EM}/{LIB}fp | ||||
| 	args {ALIGN} {SEPID?} \ | ||||
| 		({RTS}:.b=-u _i_main) \ | ||||
| 	    (.e:{HEAD}={PLATFORMDIR}/boot.o) \ | ||||
| 		({RTS}:.ocm.bas.b={PLATFORMDIR}/c-ansi.o) \ | ||||
| 		({RTS}:.c={PLATFORMDIR}/c-ansi.o) \ | ||||
| 		({RTS}:.mod={PLATFORMDIR}/modula2.o) \ | ||||
| 		({RTS}:.p={PLATFORMDIR}/pascal.o) \ | ||||
| 		-o > < \ | ||||
| 		(.p:{TAIL}={PLATFORMDIR}/libpascal.a) \ | ||||
| 		(.b:{TAIL}={PLATFORMDIR}/libb.a) \ | ||||
| 		(.bas:{TAIL}={PLATFORMDIR}/libbasic.a) \ | ||||
| 		(.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \ | ||||
| 		(.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \ | ||||
| 		(.ocm.bas.mod.b.c.p:{TAIL}={PLATFORMDIR}/libc.a) \ | ||||
| 		{FLOATS?} \ | ||||
| 		(.e:{TAIL}={PLATFORMDIR}/libem.a \ | ||||
| 		           {PLATFORMDIR}/libsys.a \ | ||||
| 		           {PLATFORMDIR}/libend.a) | ||||
| 	linker | ||||
| end | ||||
| name cv | ||||
| 	from .out | ||||
| 	to .exe | ||||
| 	program {EM}/bin/aelflod | ||||
| 	args -m8 -l -f0x70001000 < > | ||||
| 	outfile linuxmips.exe | ||||
| end | ||||
							
								
								
									
										4
									
								
								plat/linuxmips/include/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								plat/linuxmips/include/build.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,4 @@ | |||
| installable { | ||||
| 	name = "pkg", | ||||
| 	map = { "plat/linux/include+pkg" } | ||||
| } | ||||
							
								
								
									
										34
									
								
								plat/linuxmips/libsys/_syscall.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								plat/linuxmips/libsys/_syscall.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| # | ||||
| ! Declare segments (the order is important). | ||||
| 
 | ||||
| .sect .text | ||||
| .sect .rom | ||||
| .sect .data | ||||
| .sect .bss | ||||
| 
 | ||||
| .sect .text | ||||
| 
 | ||||
| #define EINVAL 22 | ||||
| 
 | ||||
| ! Perform a Linux system call. | ||||
| 
 | ||||
| .define __syscall
 | ||||
| __syscall: | ||||
| 	lw r2, 0(sp)        ! syscall number | ||||
| 	addiu r2, r2, 4000  ! MIPS uses non-standard numbers | ||||
| 	lw r4, 4(sp) | ||||
| 	lw r5, 8(sp) | ||||
| 	lw r6, 12(sp) | ||||
| 	syscall 0 | ||||
| 
 | ||||
| 	beq r7, zero, exit  ! branch on success | ||||
| 	nop | ||||
| 
 | ||||
| 	/* The result (in r2) is the errno. */ | ||||
| 	lui at, ha16[_errno] | ||||
| 	sw r2, lo16[_errno] (at) | ||||
| 	li r2, -1 | ||||
| exit: | ||||
| 	jr ra | ||||
| 	nop | ||||
| 
 | ||||
							
								
								
									
										33
									
								
								plat/linuxmips/libsys/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								plat/linuxmips/libsys/build.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| acklibrary { | ||||
| 	name = "lib", | ||||
| 	srcs = { | ||||
| 		"./_syscall.s", | ||||
| 		"plat/linux/libsys/_exit.c", | ||||
| 		"plat/linux/libsys/_hol0.s", | ||||
| 		"plat/linux/libsys/close.c", | ||||
| 		"plat/linux/libsys/creat.c", | ||||
| 		"plat/linux/libsys/execve.c", | ||||
| 		"plat/linux/libsys/getpid.c", | ||||
| 		"plat/linux/libsys/gettimeofday.c", | ||||
| 		"plat/linux/libsys/ioctl.c", | ||||
| 		"plat/linux/libsys/isatty.c", | ||||
| 		"plat/linux/libsys/kill.c", | ||||
| 		"plat/linux/libsys/lseek.c", | ||||
| 		"plat/linux/libsys/open.c", | ||||
| 		"plat/linux/libsys/read.c", | ||||
| 		"plat/linux/libsys/sbrk.c", | ||||
| 		"plat/linux/libsys/signal.c", | ||||
| 		"plat/linux/libsys/sigprocmask.c", | ||||
| 		"plat/linux/libsys/unlink.c", | ||||
| 		"plat/linux/libsys/write.c", | ||||
| 	}, | ||||
| 	deps = { | ||||
| 		"plat/linux/libsys/*.h", | ||||
| 		"lang/cem/libcc.ansi/headers+headers", | ||||
| 		"plat/linuxmips/include+pkg", | ||||
| 	}, | ||||
| 	vars = { | ||||
| 		plat = "linuxmips" | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										8
									
								
								plat/linuxmips/tests/build.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								plat/linuxmips/tests/build.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | |||
| include("tests/plat/build.lua") | ||||
| 
 | ||||
| plat_testsuite { | ||||
|     name = "tests", | ||||
|     plat = "linuxmips", | ||||
|     method = "qemu-mipsel", | ||||
| --	skipsets = {"m2"}, | ||||
| } | ||||
							
								
								
									
										75
									
								
								tests/plat/core/aar_e.e
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								tests/plat/core/aar_e.e
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,75 @@ | |||
| # | ||||
|     mes 2, EM_WSIZE, EM_PSIZE | ||||
| 
 | ||||
| /* | ||||
|  * Does basic testing of aar. Unfortunately, aar throws ERANGE on | ||||
|  * error, which we can't catch (or at least, the platforms I've looked at | ||||
|  * don't allow it to be caught, those platforms which actually throw it on | ||||
|  * error). So we just test the non-throwing cases, not the negative ones. | ||||
|  */ | ||||
| 
 | ||||
| array | ||||
| 	bss 3*EM_WSIZE, 0, 0 | ||||
| 
 | ||||
| descriptor | ||||
| 	con -1			; lower bound | ||||
| 	con 2			; range, *inclusive* | ||||
| 	con EM_WSIZE	; size of element | ||||
| 
 | ||||
| 
 | ||||
| 	exp $_m_a_i_n | ||||
| 	pro $_m_a_i_n, 0 | ||||
| 
 | ||||
| 	/* Access element -1 */ | ||||
| 
 | ||||
| 	lae array | ||||
| 	loc -1 | ||||
| 	lae descriptor | ||||
| 	aar EM_WSIZE | ||||
| 
 | ||||
| 	lae array | ||||
| 	cmu EM_WSIZE | ||||
| 	zeq *1 | ||||
| 
 | ||||
| 	loc __LINE__ | ||||
| 	cal $fail | ||||
| 	ass EM_WSIZE | ||||
| 1 | ||||
| 
 | ||||
| 	/* Access element 0 */ | ||||
| 
 | ||||
| 	lae array | ||||
| 	loc 0 | ||||
| 	lae descriptor | ||||
| 	aar EM_WSIZE | ||||
| 
 | ||||
| 	lae array | ||||
| 	adp EM_WSIZE | ||||
| 	cmu EM_WSIZE | ||||
| 	zeq *2 | ||||
| 
 | ||||
| 	loc __LINE__ | ||||
| 	cal $fail | ||||
| 	ass EM_WSIZE | ||||
| 2 | ||||
| 
 | ||||
| 	/* Access element 1 */ | ||||
| 
 | ||||
| 	lae array | ||||
| 	loc 1 | ||||
| 	lae descriptor | ||||
| 	aar EM_WSIZE | ||||
| 
 | ||||
| 	lae array | ||||
| 	adp EM_WSIZE*2 | ||||
| 	cmu EM_WSIZE | ||||
| 	zeq *3 | ||||
| 
 | ||||
| 	loc __LINE__ | ||||
| 	cal $fail | ||||
| 	ass EM_WSIZE | ||||
| 3 | ||||
| 
 | ||||
|     cal $finished | ||||
|     end | ||||
| 
 | ||||
							
								
								
									
										54
									
								
								tests/plat/core/and_e.e
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								tests/plat/core/and_e.e
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | |||
| # | ||||
|     mes 2, EM_WSIZE, EM_PSIZE | ||||
| 
 | ||||
|     exp $_m_a_i_n | ||||
|     pro $_m_a_i_n, 0 | ||||
| 
 | ||||
| 	/* And word-sized set */ | ||||
| 
 | ||||
| four | ||||
| 	rom EM_WSIZE | ||||
| 
 | ||||
| 	loc 32769 | ||||
| 	loc 1 | ||||
| 	loe four		/* to defeat constant folding */ | ||||
| 	and | ||||
| 	loc 1 | ||||
| 	cmu EM_WSIZE | ||||
| 	zeq *1 | ||||
| 
 | ||||
|     loc __LINE__ | ||||
|     cal $fail | ||||
|     asp 4 | ||||
| 1 | ||||
| 
 | ||||
| 	/* And triple-word-sized set */ | ||||
| 
 | ||||
| four_by_three | ||||
| 	rom EM_WSIZE*3 | ||||
| 
 | ||||
| 	loc 32769 | ||||
| 	loc 32770 | ||||
| 	loc 32772 | ||||
| 	loc 1 | ||||
| 	loc 2 | ||||
| 	loc 4 | ||||
| 	loe four_by_three | ||||
| 	and | ||||
| 	loc 4 | ||||
| 	cmu EM_WSIZE | ||||
| 	zne *2 | ||||
| 	loc 2 | ||||
| 	cmu EM_WSIZE | ||||
| 	zne *2 | ||||
| 	loc 1 | ||||
| 	cmu EM_WSIZE | ||||
| 	zeq *3 | ||||
| 2 | ||||
| 	loc __LINE__ | ||||
| 	cal $fail | ||||
| 	asp 4 | ||||
| 3 | ||||
| 
 | ||||
|     cal $finished | ||||
|     end | ||||
							
								
								
									
										75
									
								
								tests/plat/core/cms_e.e
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								tests/plat/core/cms_e.e
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,75 @@ | |||
| # | ||||
|     mes 2, EM_WSIZE, EM_PSIZE | ||||
| 
 | ||||
|     exp $_m_a_i_n | ||||
|     pro $_m_a_i_n, 0 | ||||
| 
 | ||||
| 	/* Compare equal word sets. */ | ||||
| 
 | ||||
| word | ||||
| 	rom EM_WSIZE | ||||
| 
 | ||||
| 	loc 1 | ||||
| 	loc 1 | ||||
| 	loe word		/* to defeat constant folding */ | ||||
| 	cms | ||||
| 	zeq *1 | ||||
| 
 | ||||
|     loc __LINE__ | ||||
|     cal $fail | ||||
|     asp 4 | ||||
| 1 | ||||
| 
 | ||||
| 	/* Compare non-equal word sets. */ | ||||
| 
 | ||||
| 	loc 1 | ||||
| 	loc 2 | ||||
| 	loe word		/* to defeat constant folding */ | ||||
| 	cms | ||||
| 	zne *2 | ||||
| 
 | ||||
|     loc __LINE__ | ||||
|     cal $fail | ||||
|     asp 4 | ||||
| 2 | ||||
| 
 | ||||
| 	/* Compare equal triple-word sets. */ | ||||
| 
 | ||||
| 	loc 1 | ||||
| 	loc 2 | ||||
| 	loc 3 | ||||
| 	loc 1 | ||||
| 	loc 2 | ||||
| 	loc 3 | ||||
| 	loe word		/* to defeat constant folding */ | ||||
| 	loc 3 | ||||
| 	mli EM_WSIZE | ||||
| 	cms | ||||
| 	zeq *3 | ||||
| 
 | ||||
|     loc __LINE__ | ||||
|     cal $fail | ||||
|     asp 4 | ||||
| 3 | ||||
| 
 | ||||
| 	/* Compare non-equal triple-word sets. */ | ||||
| 
 | ||||
| 	loc 1 | ||||
| 	loc 2 | ||||
| 	loc 3 | ||||
| 	loc 1 | ||||
| 	loc 2 | ||||
| 	loc 4 | ||||
| 	loe word		/* to defeat constant folding */ | ||||
| 	loc 3 | ||||
| 	mli EM_WSIZE | ||||
| 	cms | ||||
| 	zne *4 | ||||
| 
 | ||||
|     loc __LINE__ | ||||
|     cal $fail | ||||
|     asp 4 | ||||
| 4 | ||||
| 
 | ||||
|     cal $finished | ||||
|     end | ||||
							
								
								
									
										54
									
								
								tests/plat/core/ior_e.e
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								tests/plat/core/ior_e.e
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | |||
| # | ||||
|     mes 2, EM_WSIZE, EM_PSIZE | ||||
| 
 | ||||
|     exp $_m_a_i_n | ||||
|     pro $_m_a_i_n, 0 | ||||
| 
 | ||||
| 	/* Or word-sized set */ | ||||
| 
 | ||||
| four | ||||
| 	rom EM_WSIZE | ||||
| 
 | ||||
| 	loc 0 | ||||
| 	loc 1 | ||||
| 	loe four		/* to defeat constant folding */ | ||||
| 	ior | ||||
| 	loc 1 | ||||
| 	cmu EM_WSIZE | ||||
| 	zeq *1 | ||||
| 
 | ||||
|     loc __LINE__ | ||||
|     cal $fail | ||||
|     asp 4 | ||||
| 1 | ||||
| 
 | ||||
| 	/* Or triple-word-sized set */ | ||||
| 
 | ||||
| four_by_three | ||||
| 	rom EM_WSIZE*3 | ||||
| 
 | ||||
| 	loc 16 | ||||
| 	loc 32 | ||||
| 	loc 64 | ||||
| 	loc 1 | ||||
| 	loc 2 | ||||
| 	loc 3 | ||||
| 	loe four_by_three | ||||
| 	ior | ||||
| 	loc 67 | ||||
| 	cmu EM_WSIZE | ||||
| 	zne *2 | ||||
| 	loc 34 | ||||
| 	cmu EM_WSIZE | ||||
| 	zne *2 | ||||
| 	loc 17 | ||||
| 	cmu EM_WSIZE | ||||
| 	zeq *3 | ||||
| 2 | ||||
| 	loc __LINE__ | ||||
| 	cal $fail | ||||
| 	asp 4 | ||||
| 3 | ||||
| 
 | ||||
|     cal $finished | ||||
|     end | ||||
							
								
								
									
										73
									
								
								tests/plat/core/lar_e.e
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								tests/plat/core/lar_e.e
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,73 @@ | |||
| # | ||||
|     mes 2, EM_WSIZE, EM_PSIZE | ||||
| 
 | ||||
| /* | ||||
|  * Does basic testing of lar. Unfortunately, lar throws ERANGE on | ||||
|  * error, which we can't catch (or at least, the platforms I've looked at | ||||
|  * don't allow it to be caught, those platforms which actually throw it on | ||||
|  * error). So we just test the non-throwing cases, not the negative ones. | ||||
|  */ | ||||
| 
 | ||||
| #define ARRAY_SIZE 3*EM_WSIZE | ||||
| 
 | ||||
| array | ||||
| 	con 1 | ||||
| 	con 2 | ||||
| 	con 3 | ||||
| 
 | ||||
| descriptor | ||||
| 	con -1			; lower bound | ||||
| 	con 2			; range, *inclusive* | ||||
| 	con EM_WSIZE	; size of element | ||||
| 
 | ||||
| 	exp $_m_a_i_n | ||||
| 	pro $_m_a_i_n, 0 | ||||
| 
 | ||||
| 	/* Read element -1 */ | ||||
| 
 | ||||
| 	lae array | ||||
| 	loc -1 | ||||
| 	lae descriptor | ||||
| 	lar EM_WSIZE | ||||
| 
 | ||||
| 	loc 1 | ||||
| 	beq *1 | ||||
| 
 | ||||
| 	loc __LINE__ | ||||
| 	cal $fail | ||||
| 	ass EM_WSIZE | ||||
| 1 | ||||
| 
 | ||||
| 	/* Read element 0 */ | ||||
| 
 | ||||
| 	lae array | ||||
| 	loc 0 | ||||
| 	lae descriptor | ||||
| 	lar EM_WSIZE | ||||
| 
 | ||||
| 	loc 2 | ||||
| 	beq *2 | ||||
| 
 | ||||
| 	loc __LINE__ | ||||
| 	cal $fail | ||||
| 	ass EM_WSIZE | ||||
| 2 | ||||
| 
 | ||||
| 	/* Read element 1 */ | ||||
| 
 | ||||
| 	lae array | ||||
| 	loc 1 | ||||
| 	lae descriptor | ||||
| 	lar EM_WSIZE | ||||
| 
 | ||||
| 	loc 3 | ||||
| 	beq *3 | ||||
| 
 | ||||
| 	loc __LINE__ | ||||
| 	cal $fail | ||||
| 	ass EM_WSIZE | ||||
| 3 | ||||
| 
 | ||||
|     cal $finished | ||||
|     end | ||||
| 
 | ||||
							
								
								
									
										125
									
								
								tests/plat/core/sar_e.e
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								tests/plat/core/sar_e.e
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,125 @@ | |||
| # | ||||
|     mes 2, EM_WSIZE, EM_PSIZE | ||||
| 
 | ||||
| /* | ||||
|  * Does basic testing of sar. Unfortunately, sar throws ERANGE on | ||||
|  * error, which we can't catch (or at least, the platforms I've looked at | ||||
|  * don't allow it to be caught, those platforms which actually throw it on | ||||
|  * error). So we just test the non-throwing cases, not the negative ones. | ||||
|  */ | ||||
| 
 | ||||
| #define ARRAY_SIZE 3*EM_WSIZE | ||||
| 
 | ||||
| array | ||||
| 	bss ARRAY_SIZE, 0, 0 | ||||
| 
 | ||||
| descriptor | ||||
| 	con -1			; lower bound | ||||
| 	con 2			; range, *inclusive* | ||||
| 	con EM_WSIZE	; size of element | ||||
| 
 | ||||
| element0 | ||||
| 	con 1 | ||||
| 	con 0 | ||||
| 	con 0 | ||||
| 
 | ||||
| element1 | ||||
| 	con 0 | ||||
| 	con 1 | ||||
| 	con 0 | ||||
| 
 | ||||
| element2 | ||||
| 	con 0 | ||||
| 	con 0 | ||||
| 	con 1 | ||||
| 
 | ||||
| 	exp $_m_a_i_n | ||||
| 	pro $_m_a_i_n, 0 | ||||
| 
 | ||||
| 	/* Write element -1 */ | ||||
| 
 | ||||
| 	cal $clear_array | ||||
| 	loc 1 | ||||
| 	lae array | ||||
| 	loc -1 | ||||
| 	lae descriptor | ||||
| 	sar EM_WSIZE | ||||
| 
 | ||||
| 	lae array | ||||
| 	loi ARRAY_SIZE | ||||
| 	lae element0 | ||||
| 	loi ARRAY_SIZE | ||||
| 	loc ARRAY_SIZE | ||||
| 	cms | ||||
| 	zeq *1 | ||||
| 
 | ||||
| 	loc __LINE__ | ||||
| 	cal $fail | ||||
| 	ass EM_WSIZE | ||||
| 1 | ||||
| 
 | ||||
| 	/* Write element 0 */ | ||||
| 
 | ||||
| 	cal $clear_array | ||||
| 	loc 1 | ||||
| 	lae array | ||||
| 	loc 0 | ||||
| 	lae descriptor | ||||
| 	sar EM_WSIZE | ||||
| 
 | ||||
| 	lae array | ||||
| 	loi ARRAY_SIZE | ||||
| 	lae element1 | ||||
| 	loi ARRAY_SIZE | ||||
| 	loc ARRAY_SIZE | ||||
| 	cms | ||||
| 	zeq *2 | ||||
| 
 | ||||
| 	loc __LINE__ | ||||
| 	cal $fail | ||||
| 	ass EM_WSIZE | ||||
| 2 | ||||
| 
 | ||||
| 	/* Write element 1 */ | ||||
| 
 | ||||
| 	cal $clear_array | ||||
| 	loc 1 | ||||
| 	lae array | ||||
| 	loc 1 | ||||
| 	lae descriptor | ||||
| 	sar EM_WSIZE | ||||
| 
 | ||||
| 	lae array | ||||
| 	loi ARRAY_SIZE | ||||
| 	lae element2 | ||||
| 	loi ARRAY_SIZE | ||||
| 	loc ARRAY_SIZE | ||||
| 	cms | ||||
| 	zeq *3 | ||||
| 
 | ||||
| 	loc __LINE__ | ||||
| 	cal $fail | ||||
| 	ass EM_WSIZE | ||||
| 3 | ||||
| 
 | ||||
|     cal $finished | ||||
|     end | ||||
| 
 | ||||
| 	exp $clear_array | ||||
| 	pro $clear_array, 0 | ||||
| 
 | ||||
| 	loc 0 | ||||
| 	lae array + EM_WSIZE*0 | ||||
| 	sti EM_WSIZE | ||||
| 
 | ||||
| 	loc 0 | ||||
| 	lae array + EM_WSIZE*1 | ||||
| 	sti EM_WSIZE | ||||
| 
 | ||||
| 	loc 0 | ||||
| 	lae array + EM_WSIZE*2 | ||||
| 	sti EM_WSIZE | ||||
| 
 | ||||
| 	ret 0 | ||||
| 	end | ||||
| 
 | ||||
							
								
								
									
										50
									
								
								tests/plat/core/set_e.e
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								tests/plat/core/set_e.e
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | |||
| # | ||||
|     mes 2, EM_WSIZE, EM_PSIZE | ||||
| 
 | ||||
|     exp $_m_a_i_n | ||||
|     pro $_m_a_i_n, 0 | ||||
| 
 | ||||
| 	/* Create word-sized singleton set. */ | ||||
| 
 | ||||
| word | ||||
| 	rom EM_WSIZE | ||||
| 
 | ||||
| 	loc 1 | ||||
| 	loe word		/* to defeat constant folding */ | ||||
| 	set | ||||
| 
 | ||||
| 	loc 2 | ||||
| 	cmu EM_WSIZE | ||||
| 	zeq *1 | ||||
| 
 | ||||
|     loc __LINE__ | ||||
|     cal $fail | ||||
|     asp 4 | ||||
| 1 | ||||
| 
 | ||||
| 	/* Create triple-word-sized set with low bit */ | ||||
| 
 | ||||
| 	loc EM_WSIZE*8 + 1 | ||||
| 	loe word		/* to defeat constant folding */ | ||||
| 	loc 3 | ||||
| 	mli EM_WSIZE | ||||
| 	set | ||||
| 
 | ||||
| 
 | ||||
| 	loc 0 | ||||
| 	cmu EM_WSIZE | ||||
| 	zne *2 | ||||
| 	loc 2 | ||||
| 	cmu EM_WSIZE | ||||
| 	zne *2 | ||||
| 	loc 0 | ||||
| 	cmu EM_WSIZE | ||||
| 	zeq *3 | ||||
| 2 | ||||
| 	loc __LINE__ | ||||
| 	cal $fail | ||||
| 	asp 4 | ||||
| 3 | ||||
| 
 | ||||
|     cal $finished | ||||
|     end | ||||
							
								
								
									
										54
									
								
								tests/plat/core/xor_e.e
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								tests/plat/core/xor_e.e
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | |||
| # | ||||
|     mes 2, EM_WSIZE, EM_PSIZE | ||||
| 
 | ||||
|     exp $_m_a_i_n | ||||
|     pro $_m_a_i_n, 0 | ||||
| 
 | ||||
| 	/* Xor word-sized set */ | ||||
| 
 | ||||
| four | ||||
| 	rom EM_WSIZE | ||||
| 
 | ||||
| 	loc 32769 | ||||
| 	loc 1 | ||||
| 	loe four		/* to defeat constant folding */ | ||||
| 	xor | ||||
| 	loc 32768 | ||||
| 	cmu EM_WSIZE | ||||
| 	zeq *1 | ||||
| 
 | ||||
|     loc __LINE__ | ||||
|     cal $fail | ||||
|     asp 4 | ||||
| 1 | ||||
| 
 | ||||
| 	/* Xor triple-word-sized set */ | ||||
| 
 | ||||
| four_by_three | ||||
| 	rom EM_WSIZE*3 | ||||
| 
 | ||||
| 	loc 32769 | ||||
| 	loc 32770 | ||||
| 	loc 32772 | ||||
| 	loc 1 | ||||
| 	loc 2 | ||||
| 	loc 4 | ||||
| 	loe four_by_three | ||||
| 	xor | ||||
| 	loc 32768 | ||||
| 	cmu EM_WSIZE | ||||
| 	zne *2 | ||||
| 	loc 32768 | ||||
| 	cmu EM_WSIZE | ||||
| 	zne *2 | ||||
| 	loc 32768 | ||||
| 	cmu EM_WSIZE | ||||
| 	zeq *3 | ||||
| 2 | ||||
| 	loc __LINE__ | ||||
| 	cal $fail | ||||
| 	asp 4 | ||||
| 3 | ||||
| 
 | ||||
|     cal $finished | ||||
|     end | ||||
|  | @ -6,7 +6,9 @@ double one = 1.0; | |||
| double zero = 0.0; | ||||
| double minusone = -1.0; | ||||
| double big = (double)INT_MAX; | ||||
| double minusbig = (double)INT_MIN; | ||||
| /* We don't test INT_MIN because some platforms *cough*mips*cough* don't handle
 | ||||
|  * it correctly, and we don't want to fail them. */ | ||||
| double minusbig = (double)(INT_MIN+1); | ||||
| 
 | ||||
| /* Bypasses the CRT, so there's no stdio. */ | ||||
| void _m_a_i_n(void) | ||||
|  | @ -15,7 +17,7 @@ void _m_a_i_n(void) | |||
|     ASSERT((int)one == 1); | ||||
|     ASSERT((int)minusone == -1); | ||||
|     ASSERT((int)big == INT_MAX); | ||||
|     ASSERT((int)minusbig == INT_MIN); | ||||
|     ASSERT((int)minusbig == (INT_MIN+1)); | ||||
| 
 | ||||
|     finished(); | ||||
| } | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ void finished(void) | |||
|     _exit(0); | ||||
| } | ||||
| 
 | ||||
| void writehex(uint32_t code) | ||||
| void writehex(unsigned int code) | ||||
| { | ||||
|     char buf[8]; | ||||
|     char* p = &buf[sizeof(buf)]; | ||||
|  | @ -24,7 +24,7 @@ void writehex(uint32_t code) | |||
|     write(1, p, buf + sizeof(buf) - p); | ||||
| } | ||||
| 
 | ||||
| void fail(uint32_t code) | ||||
| void fail(unsigned int code) | ||||
| { | ||||
|     static const char fail_msg[] = "@@FAIL 0x"; | ||||
|     static const char nl_msg[] = "\n"; | ||||
|  |  | |||
|  | @ -5,8 +5,8 @@ | |||
| #include <stdint.h> | ||||
| 
 | ||||
| extern void finished(void); | ||||
| extern void writehex(uint32_t code); | ||||
| extern void fail(uint32_t code); | ||||
| extern void writehex(unsigned int code); | ||||
| extern void fail(unsigned int code); | ||||
| 
 | ||||
| #define ASSERT(condition) \ | ||||
|     do { if (!(condition)) fail(__LINE__); } while(0) | ||||
|  |  | |||
|  | @ -35,6 +35,10 @@ The default value is \fI3\fP for Intel 386 (i386). | |||
| Other values are \fI4\fP for Motorola 68000 (m68k) | ||||
| and \fI20\fP for PowerPC. | ||||
| .TP | ||||
| .BI \-f number | ||||
| Set the processor flags in the ELF header to \fInumber\fP. | ||||
| The default value is 0. | ||||
| .TP | ||||
| .B \-v | ||||
| Be verbose. | ||||
| .PP | ||||
|  |  | |||
|  | @ -33,6 +33,7 @@ | |||
| int bigendian = 0; | ||||
| int elfabi = 3;                         /* abi = Linux */ | ||||
| int elfmachine = 3;                     /* machine = EM_386 */ | ||||
| uint32_t elfflags = 0;                  /* elf processor flags */ | ||||
| 
 | ||||
| /* Header and section table of an ack object file. */ | ||||
| 
 | ||||
|  | @ -643,7 +644,7 @@ int main(int argc, char* argv[]) | |||
| 		switch (argv[1][1]) | ||||
| 		{ | ||||
| 			case 'a': | ||||
| 				elfabi = atoi(&argv[1][2]); | ||||
| 				elfabi = strtoul(&argv[1][2], NULL, 0); | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'b': | ||||
|  | @ -660,7 +661,11 @@ int main(int argc, char* argv[]) | |||
| 				break; | ||||
| 
 | ||||
| 			case 'm': | ||||
| 				elfmachine = atoi(&argv[1][2]); | ||||
| 				elfmachine = strtoul(&argv[1][2], NULL, 0); | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'f': | ||||
| 				elfflags = strtoul(&argv[1][2], NULL, 0); | ||||
| 				break; | ||||
| 
 | ||||
| 			case 'v': | ||||
|  | @ -808,7 +813,7 @@ int main(int argc, char* argv[]) | |||
| 	emit32(outsect[TEXT].os_base);     /* entry point */ | ||||
| 	emit32(ELF_HEADER_SIZE);           /* program header offset */ | ||||
| 	emit32(sh_offset);                 /* section header offset */ | ||||
| 	emit32(0);                         /* flags */ | ||||
| 	emit32(elfflags);                  /* flags */ | ||||
| 	emit16(ELF_HEADER_SIZE);           /* elf header size */ | ||||
| 	emit16(PROGRAM_HEADER_SIZE);       /* program header entry size */ | ||||
| 	emit16(1);                         /* number of program header entries */ | ||||
|  |  | |||
|  | @ -134,6 +134,12 @@ showrelo() | |||
| 	case RELO2: | ||||
| 		printf("\t2 bytes\n"); | ||||
| 		break; | ||||
| 	case RELO2HI: | ||||
| 		printf("\ttop 2 bytes of result\n"); | ||||
| 		break; | ||||
| 	case RELO2HISAD: | ||||
| 		printf("\ttop 2 bytes of result, sign adjusted\n"); | ||||
| 		break; | ||||
| 	case RELO4: | ||||
| 		printf("\t4 bytes\n"); | ||||
| 		break; | ||||
|  | @ -146,6 +152,9 @@ showrelo() | |||
| 	case RELOVC4: | ||||
| 		printf("\tVideoCore IV address in 32-bit instruction\n"); | ||||
| 		break; | ||||
| 	case RELOMIPS: | ||||
| 		printf("\tMIPS b or j instruction\n"); | ||||
| 		break; | ||||
| 	default: | ||||
| 		printf("\tunknown relocation type %d\n", relrec.or_type & RELSZ); | ||||
| 		break; | ||||
|  |  | |||
|  | @ -579,7 +579,7 @@ addbase(name) | |||
| 		return; | ||||
| 
 | ||||
| 	name->on_valu += outsect[sectindex].os_base; | ||||
| 	debug(	"%s: type 0x%x, value %ld\n", | ||||
| 	debug(	"%s: type 0x%x, value 0x%lx\n", | ||||
| 		address((name->on_type & S_EXT) ? ALLOGCHR : ALLOLCHR, | ||||
| 			(ind_t)name->on_foff | ||||
| 		), | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ static char rcsid[] = "$Id$"; | |||
| #include "orig.h" | ||||
| #include "sym.h" | ||||
| 
 | ||||
| #define UBYTE(x)	((x) & BYTEMASK) | ||||
| #define UBYTE(x) ((x)&BYTEMASK) | ||||
| 
 | ||||
| static uint16_t read2(char* addr, int type) | ||||
| { | ||||
|  | @ -34,10 +34,13 @@ static uint32_t read4(char* addr, int type) | |||
| { | ||||
| 	unsigned short word0, word1; | ||||
| 
 | ||||
| 	if (type & RELBR) { | ||||
| 	if (type & RELBR) | ||||
| 	{ | ||||
| 		word0 = (UBYTE(addr[0]) << WIDTH) + UBYTE(addr[1]); | ||||
| 		word1 = (UBYTE(addr[2]) << WIDTH) + UBYTE(addr[3]); | ||||
| 	} else { | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		word0 = (UBYTE(addr[1]) << WIDTH) + UBYTE(addr[0]); | ||||
| 		word1 = (UBYTE(addr[3]) << WIDTH) + UBYTE(addr[2]); | ||||
| 	} | ||||
|  | @ -61,9 +64,9 @@ static uint32_t get_vc4_valu(char* addr) | |||
| 		 * st<w> rd, $+o:  [1110 0111 ww 1 d:5] [11111 o:27] | ||||
| 		 */ | ||||
| 
 | ||||
| 		int32_t value = read4(addr+2, 0); | ||||
| 		int32_t value = read4(addr + 2, 0); | ||||
| 		value &= 0x07ffffff; | ||||
| 		value = value<<5>>5; | ||||
| 		value = value << 5 >> 5; | ||||
| 		return value; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -75,7 +78,7 @@ static uint32_t get_vc4_valu(char* addr) | |||
| 
 | ||||
| 		uint32_t value = read4(addr, RELWR); | ||||
| 		value &= 0x007fffff; | ||||
| 		value = value<<9>>9; | ||||
| 		value = value << 9 >> 9; | ||||
| 		value *= 2; | ||||
| 		return value; | ||||
| 	} | ||||
|  | @ -90,18 +93,18 @@ static uint32_t get_vc4_valu(char* addr) | |||
| 		int32_t value = read4(addr, RELWR); | ||||
| 		int32_t lov = value & 0x007fffff; | ||||
| 		int32_t hiv = value & 0x0f000000; | ||||
| 		value = lov | (hiv>>1); | ||||
| 		value = value<<5>>5; | ||||
| 		value = lov | (hiv >> 1); | ||||
| 		value = value << 5 >> 5; | ||||
| 		value *= 2; | ||||
| 		return value; | ||||
| 	} | ||||
| 
 | ||||
| 	if ((opcode & 0xffe0) == 0xe500) | ||||
| 	{ | ||||
|         /* lea: [1110 0101 000 d:5] [o:32] */ | ||||
| 		/* lea: [1110 0101 000 d:5] [o:32] */ | ||||
| 
 | ||||
|         return read4(addr+2, 0); | ||||
|     } | ||||
| 		return read4(addr + 2, 0); | ||||
| 	} | ||||
| 
 | ||||
| 	assert(0 && "unrecognised VC4 instruction"); | ||||
| } | ||||
|  | @ -137,22 +140,20 @@ static bool is_powerpc_memory_op(uint32_t opcode) | |||
| 
 | ||||
| static uint32_t get_powerpc_valu(char* addr, uint16_t type) | ||||
| { | ||||
| 	uint32_t opcode1 = read4(addr+0, type); | ||||
| 	uint32_t opcode2 = read4(addr+4, type); | ||||
| 	uint32_t opcode1 = read4(addr + 0, type); | ||||
| 	uint32_t opcode2 = read4(addr + 4, type); | ||||
| 
 | ||||
| 	if ((opcode1 & 0xfc000000) == 0x48000000) | ||||
| 	{ | ||||
| 		/* branch instruction */ | ||||
| 		return opcode1 & 0x03fffffd; | ||||
| 	} | ||||
| 	else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && | ||||
| 	         ((opcode2 & 0xfc000000) == 0x60000000)) | ||||
| 	else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && ((opcode2 & 0xfc000000) == 0x60000000)) | ||||
| 	{ | ||||
| 		/* addis / ori instruction pair */ | ||||
| 		return ((opcode1 & 0xffff) << 16) | (opcode2 & 0xffff); | ||||
| 	} | ||||
| 	else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && | ||||
| 	         is_powerpc_memory_op(opcode2)) | ||||
| 	else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && is_powerpc_memory_op(opcode2)) | ||||
| 	{ | ||||
| 		/* addis / memoryop instruction pair */ | ||||
| 		uint16_t hi = opcode1 & 0xffff; | ||||
|  | @ -166,12 +167,13 @@ static uint32_t get_powerpc_valu(char* addr, uint16_t type) | |||
| 		return ((hi << 16) | lo); | ||||
| 	} | ||||
| 
 | ||||
| 	fatal("Don't know how to read from PowerPC fixup on instructions 0x%08lx+0x%08lx", | ||||
| 		(unsigned long)opcode1, (unsigned long)opcode2); | ||||
| 	fatal( | ||||
| 	    "Don't know how to read from PowerPC fixup on instructions 0x%08lx+0x%08lx", | ||||
| 	    (unsigned long)opcode1, (unsigned long)opcode2); | ||||
| } | ||||
| 
 | ||||
| /* RELOPPC_LIS stores a signed 26-bit offset in the low bits. */ | ||||
| static uint32_t get_lis_valu(char *addr, uint16_t type) | ||||
| static uint32_t get_lis_valu(char* addr, uint16_t type) | ||||
| { | ||||
| 	uint32_t valu = read4(addr, type) & 0x03ffffff; | ||||
| 	if (valu & 0x02000000) | ||||
|  | @ -179,39 +181,71 @@ static uint32_t get_lis_valu(char *addr, uint16_t type) | |||
| 	return valu; | ||||
| } | ||||
| 
 | ||||
| /* RELOMIPS is used for j and b instructions only. */ | ||||
| static uint32_t get_mips_valu(char* addr) | ||||
| { | ||||
| 	uint32_t value = read4(addr, 0); | ||||
| 	switch (value >> 26) | ||||
| 	{ | ||||
| 		case 2: /* j */ | ||||
| 		case 3: /* jal */ | ||||
| 		case 29: /* jalx */ | ||||
| 			/* Unsigned 26-bit payload. */ | ||||
| 			value = value & ((1 << 26) - 1); | ||||
| 			break; | ||||
| 
 | ||||
| 		default: /* assume everything else is a b, there are lots */ | ||||
| 			/* Signed 16-bit payload. */ | ||||
| 			value = ((int32_t)value << 16) >> 16; | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	/* The value has two implicit zero bits on the bottom. */ | ||||
| 	value <<= 2; | ||||
| 	return value; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * The bits in type indicate how many bytes the value occupies and what | ||||
|  * significance should be attributed to each byte. | ||||
|  */ | ||||
| static uint32_t getvalu(char* addr, uint16_t type) | ||||
| { | ||||
| 	switch (type & RELSZ) { | ||||
| 	case RELO1: | ||||
| 		return UBYTE(addr[0]); | ||||
| 	case RELO2: | ||||
| 		return read2(addr, type); | ||||
| 	case RELO4: | ||||
| 		return read4(addr, type); | ||||
| 	case RELOPPC: | ||||
| 		return get_powerpc_valu(addr, type); | ||||
| 	case RELOPPC_LIS: | ||||
| 		return get_lis_valu(addr, type); | ||||
| 	case RELOVC4: | ||||
| 		return get_vc4_valu(addr); | ||||
| 	default: | ||||
| 		fatal("bad relocation type %x", type & RELSZ); | ||||
| 	switch (type & RELSZ) | ||||
| 	{ | ||||
| 		case RELO1: | ||||
| 			return UBYTE(addr[0]); | ||||
| 		case RELO2: | ||||
| 		case RELO2HI: | ||||
| 		case RELO2HISAD: | ||||
| 			return read2(addr, type); | ||||
| 		case RELO4: | ||||
| 			return read4(addr, type); | ||||
| 		case RELOPPC: | ||||
| 			return get_powerpc_valu(addr, type); | ||||
| 		case RELOPPC_LIS: | ||||
| 			return get_lis_valu(addr, type); | ||||
| 		case RELOVC4: | ||||
| 			return get_vc4_valu(addr); | ||||
| 		case RELOMIPS: | ||||
| 			return get_mips_valu(addr); | ||||
| 		default: | ||||
| 			fatal("can't read relocation type %x", type & RELSZ); | ||||
| 	} | ||||
| 	/* NOTREACHED */ | ||||
| } | ||||
| 
 | ||||
| static void write2(uint16_t valu, char* addr, int type) | ||||
| { | ||||
| 	unsigned short	word0, word1; | ||||
| 	unsigned short word0, word1; | ||||
| 
 | ||||
| 	if (type & RELBR) { | ||||
| 	if (type & RELBR) | ||||
| 	{ | ||||
| 		addr[0] = valu >> WIDTH; | ||||
| 		addr[1] = valu; | ||||
| 	} else { | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		addr[0] = valu; | ||||
| 		addr[1] = valu >> WIDTH; | ||||
| 	} | ||||
|  | @ -219,21 +253,27 @@ static void write2(uint16_t valu, char* addr, int type) | |||
| 
 | ||||
| static void write4(uint32_t valu, char* addr, int type) | ||||
| { | ||||
| 	unsigned short	word0, word1; | ||||
| 	unsigned short word0, word1; | ||||
| 
 | ||||
| 	if (type & RELWR) { | ||||
| 	if (type & RELWR) | ||||
| 	{ | ||||
| 		word0 = valu >> (2 * WIDTH); | ||||
| 		word1 = valu; | ||||
| 	} else { | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		word0 = valu; | ||||
| 		word1 = valu >> (2 * WIDTH); | ||||
| 	} | ||||
| 	if (type & RELBR) { | ||||
| 	if (type & RELBR) | ||||
| 	{ | ||||
| 		addr[0] = word0 >> WIDTH; | ||||
| 		addr[1] = word0; | ||||
| 		addr[2] = word1 >> WIDTH; | ||||
| 		addr[3] = word1; | ||||
| 	} else { | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		addr[0] = word0; | ||||
| 		addr[1] = word0 >> WIDTH; | ||||
| 		addr[2] = word1; | ||||
|  | @ -255,10 +295,10 @@ static void put_vc4_valu(char* addr, uint32_t value) | |||
| 		 * st<w> rd, o, (pc):  [1110 0111 ww 1 d:5] [11111 o:27] | ||||
| 		 */ | ||||
| 
 | ||||
| 		uint32_t v = read4(addr+2, 0); | ||||
| 		uint32_t v = read4(addr + 2, 0); | ||||
| 		v &= 0xf8000000; | ||||
| 		v |= value & 0x07ffffff; | ||||
| 		write4(v, addr+2, 0); | ||||
| 		write4(v, addr + 2, 0); | ||||
| 	} | ||||
| 	else if ((opcode & 0xf080) == 0x9000) | ||||
| 	{ | ||||
|  | @ -268,7 +308,7 @@ static void put_vc4_valu(char* addr, uint32_t value) | |||
| 
 | ||||
| 		uint32_t v = read4(addr, RELWR); | ||||
| 		v &= 0xff800000; | ||||
| 		v |= (value/2) & 0x007fffff; | ||||
| 		v |= (value / 2) & 0x007fffff; | ||||
| 		write4(v, addr, RELWR); | ||||
| 	} | ||||
| 	else if ((opcode & 0xf080) == 0x9080) | ||||
|  | @ -279,19 +319,19 @@ static void put_vc4_valu(char* addr, uint32_t value) | |||
| 		 */ | ||||
| 
 | ||||
| 		uint32_t v = read4(addr, RELWR); | ||||
| 		uint32_t lovalue = (value/2) & 0x007fffff; | ||||
| 		uint32_t hivalue = (value/2) & 0x07800000; | ||||
| 		uint32_t lovalue = (value / 2) & 0x007fffff; | ||||
| 		uint32_t hivalue = (value / 2) & 0x07800000; | ||||
| 		v &= 0xf0800000; | ||||
| 		v |= lovalue | (hivalue<<1); | ||||
| 		v |= lovalue | (hivalue << 1); | ||||
| 		write4(v, addr, RELWR); | ||||
| 	} | ||||
| 	else if ((opcode & 0xffe0) == 0xe500) | ||||
| 	{ | ||||
|         /* lea: [1110 0101 000 d:5] [o:32] */ | ||||
| 		/* lea: [1110 0101 000 d:5] [o:32] */ | ||||
| 
 | ||||
| 		write4(value, addr+2, 0); | ||||
|     } | ||||
|     else | ||||
| 		write4(value, addr + 2, 0); | ||||
| 	} | ||||
| 	else | ||||
| 		assert(0 && "unrecognised VC4 instruction"); | ||||
| } | ||||
| 
 | ||||
|  | @ -302,8 +342,8 @@ static void put_vc4_valu(char* addr, uint32_t value) | |||
| 
 | ||||
| static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type) | ||||
| { | ||||
| 	uint32_t opcode1 = read4(addr+0, type); | ||||
| 	uint32_t opcode2 = read4(addr+4, type); | ||||
| 	uint32_t opcode1 = read4(addr + 0, type); | ||||
| 	uint32_t opcode2 = read4(addr + 4, type); | ||||
| 
 | ||||
| 	if ((opcode1 & 0xfc000000) == 0x48000000) | ||||
| 	{ | ||||
|  | @ -312,18 +352,16 @@ static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type) | |||
| 		i |= value & 0x03fffffd; | ||||
| 		write4(i, addr, type); | ||||
| 	} | ||||
| 	else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && | ||||
| 	         ((opcode2 & 0xfc000000) == 0x60000000)) | ||||
| 	else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && ((opcode2 & 0xfc000000) == 0x60000000)) | ||||
| 	{ | ||||
| 		/* addis / ori instruction pair */ | ||||
| 		uint16_t hi = value >> 16; | ||||
| 		uint16_t lo = value & 0xffff; | ||||
| 
 | ||||
| 		write4((opcode1 & 0xffff0000) | hi, addr+0, type); | ||||
| 		write4((opcode2 & 0xffff0000) | lo, addr+4, type); | ||||
| 		write4((opcode1 & 0xffff0000) | hi, addr + 0, type); | ||||
| 		write4((opcode2 & 0xffff0000) | lo, addr + 4, type); | ||||
| 	} | ||||
| 	else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && | ||||
| 	         is_powerpc_memory_op(opcode2)) | ||||
| 	else if (((opcode1 & 0xfc1f0000) == 0x3c000000) && is_powerpc_memory_op(opcode2)) | ||||
| 	{ | ||||
| 		/* addis / memoryop instruction pair */ | ||||
| 		uint16_t hi = value >> 16; | ||||
|  | @ -334,13 +372,14 @@ static void put_powerpc_valu(char* addr, uint32_t value, uint16_t type) | |||
| 		if (lo > 0x7fff) | ||||
| 			hi++; | ||||
| 
 | ||||
| 		write4((opcode1 & 0xffff0000) | hi, addr+0, type); | ||||
| 		write4((opcode2 & 0xffff0000) | lo, addr+4, type); | ||||
| 		write4((opcode1 & 0xffff0000) | hi, addr + 0, type); | ||||
| 		write4((opcode2 & 0xffff0000) | lo, addr + 4, type); | ||||
| 	} | ||||
| 
 | ||||
| 	else | ||||
| 		fatal("Don't know how to write a PowerPC fixup to instructions 0x%08lx+0x%08lx", | ||||
| 			(unsigned long)opcode1, (unsigned long)opcode2); | ||||
| 		fatal( | ||||
| 		    "Don't know how to write a PowerPC fixup to instructions 0x%08lx+0x%08lx", | ||||
| 		    (unsigned long)opcode1, (unsigned long)opcode2); | ||||
| } | ||||
| 
 | ||||
| /* Writes a PowerPC lis instruction. */ | ||||
|  | @ -369,6 +408,36 @@ static void put_lis_valu(char* addr, uint32_t value, uint16_t type) | |||
| 	write4(opcode, addr, type); | ||||
| } | ||||
| 
 | ||||
| /* RELOMIPS is used for j and b instructions only. */ | ||||
| static void put_mips_valu(char* addr, uint32_t value) | ||||
| { | ||||
| 	uint32_t opcode = read4(addr, 0); | ||||
| 
 | ||||
| 	/* The two bottom zero bits are implicit. */ | ||||
| 	if (value & 3) | ||||
| 		fatal("invalid MIPS relocation value 0x%x", value); | ||||
| 	value >>= 2; | ||||
| 
 | ||||
| 	switch (opcode >> 26) | ||||
| 	{ | ||||
| 		case 2: /* j */ | ||||
| 		case 3: /* jal */ | ||||
| 		case 29: /* jalx */ | ||||
| 			/* Unsigned 26-bit payload. */ | ||||
| 			value = value & ((1 << 26) - 1); | ||||
| 			opcode = opcode & ~((1 << 26) - 1); | ||||
| 			break; | ||||
| 
 | ||||
| 		default: /* assume everything else is a b, there are lots */ | ||||
| 			/* Signed 16-bit payload. */ | ||||
| 			value = value & ((1 << 16) - 1); | ||||
| 			opcode = opcode & ~((1 << 16) - 1); | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	write4(opcode | value, addr, 0); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * The bits in type indicate how many bytes the value occupies and what | ||||
|  * significance should be attributed to each byte. | ||||
|  | @ -377,32 +446,42 @@ static void put_lis_valu(char* addr, uint32_t value, uint16_t type) | |||
| static putvalu(uint32_t valu, char* addr, uint16_t type) | ||||
| { | ||||
| 
 | ||||
| 	switch (type & RELSZ) { | ||||
| 	case RELO1: | ||||
| 		addr[0] = valu; | ||||
| 		break; | ||||
| 	case RELO2: | ||||
| 		write2(valu, addr, type); | ||||
| 		break; | ||||
| 	case RELO4: | ||||
| 		write4(valu, addr, type); | ||||
| 		break; | ||||
| 	case RELOPPC: | ||||
| 		put_powerpc_valu(addr, valu, type); | ||||
| 		break; | ||||
| 	case RELOPPC_LIS: | ||||
| 		put_lis_valu(addr, valu, type); | ||||
| 		break; | ||||
| 	case RELOVC4: | ||||
| 		put_vc4_valu(addr, valu); | ||||
| 		break; | ||||
| 	default: | ||||
| 		fatal("bad relocation type %x", type & RELSZ); | ||||
| 	switch (type & RELSZ) | ||||
| 	{ | ||||
| 		case RELO1: | ||||
| 			addr[0] = valu; | ||||
| 			break; | ||||
| 		case RELO2: | ||||
| 			write2(valu, addr, type); | ||||
| 			break; | ||||
| 		case RELO2HI: | ||||
| 			write2(valu >> 16, addr, type); | ||||
| 			break; | ||||
| 		case RELO2HISAD: | ||||
| 			write2((valu >> 16) + !!(valu & 0x8000), addr, type); | ||||
| 			break; | ||||
| 		case RELO4: | ||||
| 			write4(valu, addr, type); | ||||
| 			break; | ||||
| 		case RELOPPC: | ||||
| 			put_powerpc_valu(addr, valu, type); | ||||
| 			break; | ||||
| 		case RELOPPC_LIS: | ||||
| 			put_lis_valu(addr, valu, type); | ||||
| 			break; | ||||
| 		case RELOVC4: | ||||
| 			put_vc4_valu(addr, valu); | ||||
| 			break; | ||||
| 		case RELOMIPS: | ||||
| 			put_mips_valu(addr, valu); | ||||
| 			break; | ||||
| 		default: | ||||
| 			fatal("can't write relocation type %x", type & RELSZ); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| extern struct outsect	outsect[]; | ||||
| extern struct orig	relorig[]; | ||||
| extern struct outsect outsect[]; | ||||
| extern struct orig relorig[]; | ||||
| 
 | ||||
| /*
 | ||||
|  * There are two cases: `local' is an undefined external or common name, | ||||
|  | @ -416,42 +495,47 @@ extern struct orig	relorig[]; | |||
|  * Second case: we must update the value by the change | ||||
|  * in position of the section of local. | ||||
|  */ | ||||
| static unsigned | ||||
| addrelo(relo, names, valu_out) | ||||
| 	struct outrelo		*relo; | ||||
| 	struct outname		*names; | ||||
| 	long			*valu_out;	/* Out variable. */ | ||||
| static unsigned addrelo(relo, names, valu_out) struct outrelo* relo; | ||||
| struct outname* names; | ||||
| long* valu_out; /* Out variable. */ | ||||
| { | ||||
| 	register struct outname	*local = &names[relo->or_nami]; | ||||
| 	register unsigned short		index = NLocals; | ||||
| 	register long		valu = *valu_out; | ||||
| 	register struct outname* local = &names[relo->or_nami]; | ||||
| 	register unsigned short index = NLocals; | ||||
| 	register long valu = *valu_out; | ||||
| 
 | ||||
| 	if ((local->on_type & S_SCT)) { | ||||
| 		register int	sectindex = (local->on_type & S_TYP) - S_MIN; | ||||
| 	if ((local->on_type & S_SCT)) | ||||
| 	{ | ||||
| 		register int sectindex = (local->on_type & S_TYP) - S_MIN; | ||||
| 
 | ||||
| 		valu += relorig[sectindex].org_size; | ||||
| 		valu += outsect[sectindex].os_base; | ||||
| 		index += NGlobals + sectindex; | ||||
| 	} else { | ||||
| 		register struct outname	*name; | ||||
| 		extern int		hash(); | ||||
| 		extern struct outname	*searchname(); | ||||
| 		extern unsigned 	indexof(); | ||||
| 		extern struct outhead	outhead; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		register struct outname* name; | ||||
| 		extern int hash(); | ||||
| 		extern struct outname* searchname(); | ||||
| 		extern unsigned indexof(); | ||||
| 		extern struct outhead outhead; | ||||
| 
 | ||||
| 		name = searchname(local->on_mptr, hash(local->on_mptr)); | ||||
| 		if (name == (struct outname *)0) | ||||
| 		if (name == (struct outname*)0) | ||||
| 			fatal("name %s not found in pass 2", local->on_mptr); | ||||
| 		if (ISCOMMON(name) || ISUNDEFINED(name)) { | ||||
| 			debug("can't relocate from %s\n",local->on_mptr,0,0,0); | ||||
| 		if (ISCOMMON(name) || ISUNDEFINED(name)) | ||||
| 		{ | ||||
| 			debug("can't relocate from %s\n", local->on_mptr, 0, 0, 0); | ||||
| 			index += indexof(name); | ||||
| 		} else { | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			valu += name->on_valu; | ||||
| 			if ((name->on_type & S_TYP) == S_ABS) { | ||||
| 			if ((name->on_type & S_TYP) == S_ABS) | ||||
| 			{ | ||||
| 				index += NGlobals + outhead.oh_nsect; | ||||
| 			} | ||||
| 			else	index += NGlobals + | ||||
| 					(name->on_type & S_TYP) - S_MIN; | ||||
| 			else | ||||
| 				index += NGlobals + (name->on_type & S_TYP) - S_MIN; | ||||
| 		} | ||||
| 	} | ||||
| 	*valu_out = valu; | ||||
|  | @ -463,21 +547,23 @@ addrelo(relo, names, valu_out) | |||
|  * which the header is pointed to by `head'. Relocation is relative to the | ||||
|  * names in `names'; `relo' tells how to relocate. | ||||
|  */ | ||||
| relocate(head, emit, names, relo, off) | ||||
| 	struct outhead	*head; | ||||
| 	char		*emit; | ||||
| 	struct outname	names[]; | ||||
| 	struct outrelo	*relo; | ||||
| 	long		off; | ||||
| relocate(head, emit, names, relo, off) struct outhead* head; | ||||
| char* emit; | ||||
| struct outname names[]; | ||||
| struct outrelo* relo; | ||||
| long off; | ||||
| { | ||||
| 	long		valu; | ||||
| 	int		sectindex = relo->or_sect - S_MIN; | ||||
| 	extern struct outhead	outhead; | ||||
| 	long valu; | ||||
| 	int sectindex = relo->or_sect - S_MIN; | ||||
| 	extern struct outhead outhead; | ||||
| 	uint32_t realaddress = outsect[sectindex].os_base + relo->or_addr | ||||
| 		+ relorig[sectindex].org_size; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Pick up previous value at location to be relocated. | ||||
| 	 */ | ||||
| 	valu = getvalu(emit + (relo->or_addr - off), relo->or_type); | ||||
| 	debug("read relocation from 0x%08x type 0x%x value 0x%08x symbol %d\n", realaddress, relo->or_type, valu, relo->or_nami); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Or_nami is an index in the name table of the considered module. | ||||
|  | @ -486,10 +572,13 @@ relocate(head, emit, names, relo, off) | |||
| 	 *	- a section name | ||||
| 	 *	- the first name outside! the name table (argh) | ||||
| 	 */ | ||||
| 	if (relo->or_nami < head->oh_nname) { | ||||
| 	if (relo->or_nami < head->oh_nname) | ||||
| 	{ | ||||
| 		/* First two cases. */ | ||||
| 		relo->or_nami = addrelo(relo, names, &valu); | ||||
| 	} else { | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		/*
 | ||||
| 		 * Third case: it is absolute. The relocation of absolute | ||||
| 		 * names is always 0. We only need to change the index. | ||||
|  | @ -504,11 +593,12 @@ relocate(head, emit, names, relo, off) | |||
| 	 * now we subtract the origin of the referencING section. | ||||
| 	 */ | ||||
| 	if (relo->or_type & RELPC) | ||||
| 		valu -=	relorig[sectindex].org_size+outsect[sectindex].os_base; | ||||
| 		valu -= relorig[sectindex].org_size + outsect[sectindex].os_base; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Now put the value back. | ||||
| 	 */ | ||||
| 	debug("written fixed up relocation to 0x%08x type 0x%x value 0x%08x\n", realaddress, relo->or_type, valu, 0); | ||||
| 	putvalu(valu, emit + (relo->or_addr - off), relo->or_type); | ||||
| 
 | ||||
| 	/*
 | ||||
|  |  | |||
|  | @ -16,7 +16,10 @@ | |||
| #include "smap.h" | ||||
| #include "mcgg.h" | ||||
| 
 | ||||
| static char rcsid[] = "$Id$"; | ||||
| #define REGATTR_INT 0 | ||||
| #define REGATTR_LONG 1 | ||||
| #define REGATTR_FLOAT 2 | ||||
| #define REGATTR_DOUBLE 3 | ||||
| 
 | ||||
| int maxcost = SHRT_MAX / 2; | ||||
| 
 | ||||
|  | @ -162,6 +165,18 @@ int main(int argc, char* argv[]) | |||
| 		rule(®, tree(&NOPL, tree(®, NULL, NULL), NULL))->cost = 1; | ||||
| 		rule(®, tree(&NOPD, tree(®, NULL, NULL), NULL))->cost = 1; | ||||
| 		rule(NULL, tree(&RET, NULL, NULL))->cost = 1; | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	{ | ||||
| 		struct regattr* attr = makeregattr("int"); | ||||
| 		assert(attr->number == REGATTR_INT); | ||||
| 		attr = makeregattr("long"); | ||||
| 		assert(attr->number == REGATTR_LONG); | ||||
| 		attr = makeregattr("float"); | ||||
| 		assert(attr->number == REGATTR_FLOAT); | ||||
| 		attr = makeregattr("double"); | ||||
| 		assert(attr->number == REGATTR_DOUBLE); | ||||
| 	} | ||||
| 
 | ||||
| 	yyin = infp; | ||||
|  | @ -612,7 +627,8 @@ static void emitregisterattrs(void) | |||
| 		assert(rc->number == i); | ||||
| 
 | ||||
| 		print("%1\"%s\",\n", rc->name); | ||||
| 		printh("#define %P%s_ATTR (1U<<%d)\n", rc->name, rc->number); | ||||
| 		if (rc->number > REGATTR_DOUBLE) | ||||
| 			printh("#define %P%s_ATTR (1U<<%d)\n", rc->name, rc->number); | ||||
| 	} | ||||
| 	print("};\n\n"); | ||||
| 	printh("\n"); | ||||
|  | @ -655,7 +671,10 @@ static void emitregisters(void) | |||
| 	for (i=0; i<registers.count; i++) | ||||
| 	{ | ||||
| 		struct reg* r = registers.item[i].right; | ||||
| 		uint32_t type = r->attrs & TYPE_ATTRS; | ||||
| 		assert(r->number == i); | ||||
| 		if (type & (type-1)) | ||||
| 			yyerror("register %s has more than one type attribute set", r->name); | ||||
| 
 | ||||
| 		print("%1{ \"%s\", 0x%x, %Pregister_names_%d_%s, %Pregister_aliases_%d_%s },\n", | ||||
| 			r->name, r->attrs, i, r->name, i, r->name); | ||||
|  |  | |||
|  | @ -17,6 +17,11 @@ struct ir_data | |||
| 
 | ||||
| extern const struct ir_data ir_data[]; | ||||
| 
 | ||||
| #define burm_int_ATTR (1U<<0) | ||||
| #define burm_long_ATTR (1U<<1) | ||||
| #define burm_float_ATTR (1U<<2) | ||||
| #define burm_double_ATTR (1U<<3) | ||||
| 
 | ||||
| #define TYPE_ATTRS \ | ||||
|     (burm_int_ATTR | burm_long_ATTR | burm_float_ATTR | burm_double_ATTR) | ||||
| 
 | ||||
|  |  | |||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		
		Reference in a new issue