Merge pull request #59 from kernigh/kernigh-ppc-regs
PowerPC ncg: register allocation, floats, lxl
This commit is contained in:
		
						commit
						66147529d9
					
				
					 43 changed files with 1171 additions and 969 deletions
				
			
		
							
								
								
									
										14
									
								
								h/out.h
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								h/out.h
									
										
									
									
									
								
							|  | @ -61,13 +61,13 @@ struct outname { | |||
| /*
 | ||||
|  * relocation type bits | ||||
|  */ | ||||
| #define RELSZ	0x0fff			/* relocation length */ | ||||
| #define RELO1	   1			/* 1 byte */ | ||||
| #define RELO2	   2			/* 2 bytes */ | ||||
| #define RELO4	   3			/* 4 bytes */ | ||||
| #define RELOPPC    4			/* PowerPC 26-bit address */ | ||||
| #define RELOLIS    5			/* PowerPC lis */ | ||||
| #define RELOVC4    6	/* VideoCore IV address in 32-bit instruction */ | ||||
| #define RELSZ   0x0fff          /* relocation length */ | ||||
| #define RELO1        1          /* 1 byte */ | ||||
| #define RELO2        2          /* 2 bytes */ | ||||
| #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 RELPC	0x2000			/* pc relative */ | ||||
| #define RELBR	0x4000			/* High order byte lowest address. */ | ||||
|  |  | |||
|  | @ -42,8 +42,8 @@ void emit_hl(word_t in) | |||
| 	case OP_HA:  /* ha16[expr] */ | ||||
| 		if (PASS_RELO && (hl_expr.typ & S_TYP) != S_ABS) { | ||||
| 			/*
 | ||||
| 			 * RELOLIS only works with lis _, _ (same as | ||||
| 			 * addis _, r0, _).  Check if instruction | ||||
| 			 * RELOPPC_LIS only works with lis _, _ (same | ||||
| 			 * as addis _, r0, _).  Check if instruction | ||||
| 			 * isn't addis or register RA isn't r0. | ||||
| 			 */ | ||||
| 			if ((in & 0xfc1f0000) != (0x3c000000)) | ||||
|  | @ -55,7 +55,7 @@ void emit_hl(word_t in) | |||
| 			 * Low 26 bits: signed offset | ||||
| 			 */ | ||||
| 			fit(fitx(hl_expr.val, 26)); | ||||
| 			newrelo(hl_expr.typ, RELOLIS | FIXUPFLAGS); | ||||
| 			newrelo(hl_expr.typ, RELOPPC_LIS | FIXUPFLAGS); | ||||
| 			reg = (in >> 21) & 0x1f; | ||||
| 			in = (hl_token == OP_HA) << 31; | ||||
| 			in |= reg << 26; | ||||
|  |  | |||
|  | @ -1,14 +1,9 @@ | |||
| .sect .text | ||||
| 
 | ||||
| ! Index into a bounds-checked array. | ||||
| ! Get address of element of bounds-checked array. | ||||
| ! | ||||
| ! On entry: | ||||
| !    r3 = ptr to descriptor | ||||
| !    r4 = index | ||||
| !    r5 = address of array | ||||
| ! Yields: | ||||
| !    r3 = address of element | ||||
| !    r0 = size of element (used by .lar4, .sar4) | ||||
| ! Stack: ( array-adr index descriptor-adr -- element-adr ) | ||||
| ! Sets r3 = size of element for .los4, .sts4 | ||||
| ! Preserves r10 for .lar4, .sar4 | ||||
| 
 | ||||
| .define .aar4 | ||||
|  | @ -17,16 +12,21 @@ | |||
| 	ori r0, r0, lo16[.trap_earray] | ||||
| 	mtspr ctr, r0            ! load CTR with trap address | ||||
| 
 | ||||
| 	lwz r0, 0(r3) | ||||
| 	subf. r4, r0, r4         ! adjust range | ||||
| 	lwz r4, 0(sp)            ! r4 = address of descriptor | ||||
| 	lwz r5, 4(sp)            ! r5 = index | ||||
| 	lwz r6, 8(sp)            ! r6 = address of array | ||||
| 
 | ||||
| 	lwz r0, 0(r4) | ||||
| 	subf. r5, r0, r5         ! subtract lower bound from index | ||||
| 	bltctr                   ! check lower bound | ||||
| 
 | ||||
| 	lwz r0, 4(r3) | ||||
| 	cmplw r4, r3 | ||||
| 	bgectr                   ! check upper bound | ||||
| 
 | ||||
| 	lwz r0, 8(r3) | ||||
| 	mullw r4, r4, r0         ! scale index | ||||
| 	add r3, r4, r5           ! calculate element address | ||||
| 	lwz r0, 4(r4) | ||||
| 	cmplw r5, r0 | ||||
| 	bgtctr                   ! check upper bound | ||||
| 
 | ||||
| 	lwz r3, 8(r4)            ! r3 = size of element | ||||
| 	mullw r5, r5, r3         ! scale index by size | ||||
| 	add r6, r6, r5 | ||||
| 	stw r6, 8(sp)            ! push address of element | ||||
| 	addi sp, sp, 8 | ||||
| 	blr | ||||
|  |  | |||
|  | @ -1,24 +1,20 @@ | |||
| .sect .text | ||||
| 
 | ||||
| ! Set intersection. | ||||
| !  Stack: ( b a size -- a*b ) | ||||
| !  Stack: ( a b size -- a*b ) | ||||
| 
 | ||||
| .define .and | ||||
| .and: | ||||
| 	lwz r3, 0 (sp)      ! r3 = size | ||||
| 	addi sp, sp, 4 | ||||
| 	lwz	r3, 0(sp)		! r3 = size | ||||
| 	srwi	r7, r3, 2 | ||||
| 	mtspr	ctr, r7			! ctr = size / 4 | ||||
| 	add	r4, sp, r3		! r4 = pointer before set a | ||||
| 
 | ||||
| 	mr	r4, sp			! r4 = ptr to set a | ||||
| 	add	r5, sp, r3		! r5 = ptr to set b | ||||
| 	srwi	r6, r3, 2 | ||||
| 	mtspr	ctr, r6			! ctr = r3 / 4 | ||||
| 1: | ||||
| 	lwz	r7, 0(r4) | ||||
| 	lwz	r8, 0(r5) | ||||
| 	and	r8, r7, r8		! intersection of words | ||||
| 	stw	r8, 0(r5) | ||||
| 	addi	r4, r4, 4 | ||||
| 	addi	r5, r5, 4 | ||||
| 	! Loop with r4 in set a and sp in set b. | ||||
| 1:	lwzu	r5, 4(r4) | ||||
| 	lwzu	r6, 4(sp) | ||||
| 	and	r7, r5, r6		! intersection of words | ||||
| 	stw	r7, 0(r4) | ||||
| 	bdnz	1b			! loop ctr times | ||||
| 	add	sp, sp, r3 | ||||
| 	addi	sp, sp, 4		! drop last word of set b | ||||
| 	blr | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ for _, plat in ipairs(vars.plats) do | |||
| 	acklibrary { | ||||
| 		name = "lib_"..plat, | ||||
| 		srcs = { | ||||
| 			"./*.s", | ||||
| 			"./*.s", -- rm ret.s | ||||
| 		}, | ||||
| 		vars = { plat = plat }, | ||||
| 		deps = { | ||||
|  |  | |||
|  | @ -8,25 +8,24 @@ | |||
| 
 | ||||
| .define .cif8 | ||||
| .cif8: | ||||
| 	addi sp, sp, -4          ! make space for the double | ||||
| 	! Conversion uses the pivot value | ||||
| 	!   1 << 52 = 0x4330 0000 0000 0000 | ||||
| 	! | ||||
| 	! From signed integer i, we compute | ||||
| 	!   ((1 << 52) + (1 << 31) + i) - ((1 << 52) + (1 << 31)) | ||||
| 
 | ||||
| 	lis r3, 0x4330 | ||||
| 	stwu r3, -4(sp)          ! make space for the double | ||||
| 
 | ||||
| 	lwz r3, 4(sp) | ||||
| 	xoris r3, r3, 0x8000 | ||||
| 	stw r3, 4(sp)            ! flip sign of integer value | ||||
| 	stw r3, 4(sp)            ! flip sign bit to get (1 << 31) + i | ||||
| 
 | ||||
| 	addis r3, r0, 0x4330 | ||||
| 	stw r3, 0(sp)            ! set high word to construct a double | ||||
| 
 | ||||
| 	lfd f0, 0(sp)            ! load value | ||||
| 
 | ||||
| 	lis r3, ha16[pivot] | ||||
| 	lfd f1, lo16[pivot](r3)  ! load pivot value | ||||
| 	fsub f0, f0, f1          ! adjust | ||||
| 	lfd f0, 0(sp)            ! f0 = (1 << 52) + (1 << 31) + i | ||||
| 	lis r3, 0x8000 | ||||
| 	stw r3, 4(sp) | ||||
| 	lfd f1, 0(sp)            ! f1 = (1 << 52) + (1 << 31) | ||||
| 	fsub f0, f0, f1          ! finish conversion | ||||
| 
 | ||||
| 	stfd f0, 0(sp)           ! save value again... | ||||
| 	blr                      ! ...and return  | ||||
| 
 | ||||
| .sect .rom | ||||
| pivot: | ||||
| 	.data4 0x43300000
 | ||||
| 	.data4 0x80000000
 | ||||
|  |  | |||
|  | @ -1,30 +1,27 @@ | |||
| .sect .text | ||||
| 
 | ||||
| ! Compare sets a, b. | ||||
| !  Stack: ( b a -- ) | ||||
| !  With r3 = size of each set | ||||
| !  Yields r3 = 0 if equal, nonzero if not equal | ||||
| !  Stack: ( a b size -- result ) | ||||
| !  Result is 0 if equal, nonzero if not equal. | ||||
| 
 | ||||
| .define .cms | ||||
| .cms: | ||||
| 	mr	r4, sp			! r4 = ptr to set a | ||||
| 	add	r5, sp, r3		! r5 = ptr to set b | ||||
| 	mr	r6, r3			! r6 = size | ||||
| 	srwi	r3, r3, 2 | ||||
| 	mtspr	ctr, r3			! ctr = size / 4 | ||||
| 1: | ||||
| 	lwz	r7, 0(r4) | ||||
| 	lwz	r8, 0(r5) | ||||
| 	cmpw	cr0, r7, r8		! compare words in sets | ||||
| 	addi	r4, r4, 4 | ||||
| 	addi	r5, r5, 4 | ||||
| 	bne	cr0, 2f			! branch if not equal | ||||
| 	lwz	r3, 0(sp)		! r3 = size of each set | ||||
| 	srwi	r7, r3, 2 | ||||
| 	mtspr	ctr, r7			! ctr = size / 4 | ||||
| 	add	r4, sp, r3		! r4 = pointer before set a | ||||
| 	add	r7, r4, r3		! r7 = pointer to store result | ||||
| 
 | ||||
| 	! Loop with r4 in a set a and sp in set b. | ||||
| 1:	lwzu	r5, 4(r4) | ||||
| 	lwzu	r6, 4(sp) | ||||
| 	cmpw	r5, r6			! compare words | ||||
| 	bne	2f			! branch if not equal | ||||
| 	bdnz	1b			! loop ctr times | ||||
| 	addi	r3, r0, 0		! equal: return 0 | ||||
| 
 | ||||
| 	li	r3, 0			! equal: return 0 | ||||
| 	b	3f | ||||
| 2: | ||||
| 	addi	r3, r0, 1		! not equal: return 1 | ||||
| 3: | ||||
| 	slwi	r6, r6, 1		! r6 = size * 2 | ||||
| 	add	sp, sp, r6		! remove sets from stack | ||||
| 2:	li	r3, 1			! not equal: return 1 | ||||
| 3:	mr	sp, r7 | ||||
| 	stw	r3, 0(sp)		! push result | ||||
| 	blr | ||||
|  |  | |||
|  | @ -5,16 +5,15 @@ | |||
| 
 | ||||
| .define .com | ||||
| .com: | ||||
| 	lwz r3, 0 (sp)       ! size | ||||
| 	addi sp, sp, 4 | ||||
| 	lwz	r3, 0(sp)		! r3 = size | ||||
| 	srwi	r7, r3, 2 | ||||
| 	mtspr	ctr, r7			! ctr = size / 4 | ||||
| 	mr	r4, sp			! r4 = pointer before set a | ||||
| 
 | ||||
| 	mr	r4, sp			! r4 = pointer to set a | ||||
| 	srwi	r5, r3, 2 | ||||
| 	mtspr	ctr, r5			! ctr = r3 / 4 | ||||
| 1: | ||||
| 	lwz	r6, 0(r4) | ||||
| 	nor	r6, r6, r6		! complement of word | ||||
| 	stw	r6, 0(r4) | ||||
| 	addi	r4, r4, 4 | ||||
| 	! Loop with r4 in set a. | ||||
| 1:	lwzu	r5, 4(r4) | ||||
| 	nor	r7, r5, r5		! complement of word | ||||
| 	stw	r7, 0(r4) | ||||
| 	bdnz	1b			! loop ctr times | ||||
| 	addi	sp, sp, 4		! drop size from stack | ||||
| 	blr | ||||
|  |  | |||
|  | @ -6,21 +6,20 @@ | |||
| 
 | ||||
| .define .cuf8 | ||||
| .cuf8: | ||||
| 	addi sp, sp, -4          ! make space for the double | ||||
| 	! Conversion uses the pivot value | ||||
| 	!   1 << 52 = 0x4330 0000 0000 0000 | ||||
| 	! | ||||
| 	! From unsigned integer u, we compute | ||||
| 	!   ((1 << 52) + u) - (1 << 52) | ||||
| 
 | ||||
| 	lis r3, 0x4330 | ||||
| 	stw r3, 0(sp)            ! set high word to construct a double | ||||
| 	stwu r3, -4(sp)          ! make space for the double | ||||
| 
 | ||||
| 	lfd f0, 0(sp)            ! load value | ||||
| 
 | ||||
| 	lis r3, ha16[pivot] | ||||
| 	lfd f1, lo16[pivot](r3)  ! load pivot value | ||||
| 	fsub f0, f0, f1          ! adjust | ||||
| 	lfd f0, 0(sp)            ! f0 = (1 << 52) + u | ||||
| 	li r3, 0x0000 | ||||
| 	stw r3, 4(sp) | ||||
| 	lfd f1, 0(sp)            ! f1 = (1 << 52) | ||||
| 	fsub f0, f0, f1          ! finish conversion | ||||
| 
 | ||||
| 	stfd f0, 0(sp)           ! save value again... | ||||
| 	blr                      ! ...and return | ||||
| 
 | ||||
| .sect .rom | ||||
| pivot: | ||||
| 	.data4 0x43300000
 | ||||
| 	.data4 0x00000000
 | ||||
|  |  | |||
|  | @ -3,35 +3,48 @@ | |||
| .sect .text | ||||
| 
 | ||||
| ! Split a double-precision float into fraction and exponent, like | ||||
| ! frexp(3) in C.  On entry: | ||||
| !  r3 = float, high word (bits 0..31) | ||||
| !  r4 = float, low word (bits 32..63) | ||||
| ! Yields: | ||||
| !  r3 = fraction, high word (bits 0..31) | ||||
| !  r4 = fraction, low word (bits 32..63) | ||||
| !  r5 = exponent | ||||
| ! frexp(3) in C. | ||||
| ! | ||||
| ! Stack: ( double -- fraction exponent ) | ||||
| 
 | ||||
| .define .fef8 | ||||
| .fef8: | ||||
| 	lwz r3, 0(sp)			! r3 = high word (bits 0..31) | ||||
| 	lwz r4, 4(sp)			! r4 = low word (bits 32..63) | ||||
| 
 | ||||
| 	! IEEE double-precision format: | ||||
| 	!   sign  exponent  fraction | ||||
| 	!   0     1..11     12..63 | ||||
| 	extrwi r6, r3, 11, 1		! r6 = IEEE exponent | ||||
| 	addi r5, r6, -1022		! r5 = true exponent | ||||
| 	! | ||||
| 	! To get fraction in [0.5, 1) or (-1, -0.5], we subtract 1022 | ||||
| 	! from the IEEE exponent. | ||||
| 
 | ||||
| 	extrwi. r6, r3, 11, 1		! r6 = IEEE exponent | ||||
| 	addi r5, r6, -1022		! r5 = our exponent | ||||
| 	beq 2f				! jump if zero or denormalized | ||||
| 	cmpwi r6, 2047 | ||||
| 	beqlr				! return if infinity or NaN | ||||
| 	cmpwi r6, 0 | ||||
| 	bne 1f				! jump if normalized number | ||||
| 	beq 1f				! jump if infinity or NaN | ||||
| 	! fall through if normalized | ||||
| 
 | ||||
| 	! Got denormalized number or zero, probably zero. | ||||
| 	! Put fraction in [0.5, 1) or (-1, -0.5] by setting its | ||||
| 	! IEEE exponent to 1022. | ||||
| 	rlwinm r3, r3, 0, 12, 0		! clear old exponent | ||||
| 	oris r3, r3, 1022 << 4		! set new exponent | ||||
| 	! fall through | ||||
| 
 | ||||
| 1:	stw r3, 0(sp) | ||||
| 	stw r4, 4(sp)			! push fraction | ||||
| 	stwu r5, -4(sp)			! push exponent | ||||
| 	blr | ||||
| 
 | ||||
| 2:	! Got denormalized number or zero, probably zero. | ||||
| 	extrwi r6, r3, 22, 12 | ||||
| 	addi r5, r0, 0			! r5 = true exponent = 0 | ||||
| 	or. r6, r6, r4			! r6 = high|low fraction | ||||
| 	beqlr				! return if zero | ||||
| 	bne 3f				! jump if not zero | ||||
| 	li r5, 0			! exponent = 0 | ||||
| 	b 1b | ||||
| 
 | ||||
| 	! Got denormalized number, not zero. | ||||
| 	stwu r4, -4(sp) | ||||
| 	stwu r3, -4(sp) | ||||
| 3:	! Got denormalized number, not zero. | ||||
| 	lfd f0, 0(sp) | ||||
| 	lis r6, ha16[_2_64] | ||||
| 	lfd f1, lo16[_2_64](r6) | ||||
|  | @ -40,14 +53,8 @@ | |||
| 	lwz r3, 0(sp) | ||||
| 	lwz r4, 4(sp) | ||||
| 	extrwi r6, r3, 11, 1		! r6 = IEEE exponent | ||||
| 	addi sp, sp, 8 | ||||
| 	addi r5, r6, -1022 - 64		! r5 = true exponent | ||||
| 1: | ||||
| 	! Put fraction in [0.5, 1) or (-1, -0.5] by setting its | ||||
| 	! exponent to true 0, IEEE 1022. | ||||
| 	rlwinm r3, r3, 0, 12, 0		! clear old exponent | ||||
| 	oris r3, r3, 1022 << 4		! set new exponent | ||||
| 	blr | ||||
| 	addi r5, r6, -1022 - 64		! r5 = our exponent | ||||
| 	b 1b | ||||
| 
 | ||||
| .sect .rom | ||||
| _2_64: | ||||
|  |  | |||
|  | @ -1,45 +1,37 @@ | |||
| .sect .text | ||||
| 
 | ||||
| ! Multiplies two double-precision floats, then splits the product into | ||||
| ! integer and fraction, like modf(3) in C.  On entry: | ||||
| !  f1 = float | ||||
| !  f2 = other float | ||||
| ! Yields: | ||||
| !  f1 = fraction | ||||
| !  f2 = integer | ||||
| ! fraction and integer, like modf(3) in C.  On entry: | ||||
| ! | ||||
| ! Stack: ( a b -- fraction integer ) | ||||
| 
 | ||||
| .define .fif8 | ||||
| .fif8: | ||||
| 	fmul f1, f1, f2 | ||||
| 	stfdu f1, -8(sp)		! push f1 = product | ||||
| 	lfd f1, 8(sp) | ||||
| 	lfd f2, 0(sp) | ||||
| 	fmul f1, f1, f2			! f1 = a * b | ||||
| 	stfd f1, 0(sp) | ||||
| 	lwz r3, 0(sp)			! r3 = high word | ||||
| 	lwz r4, 4(sp)			! r4 = low word | ||||
| 
 | ||||
| 	! IEEE double-precision format: | ||||
| 	!   sign  exponent  fraction | ||||
| 	!   0     1..11     12..63 | ||||
| 	! | ||||
| 	! Subtract 1023 from the IEEE exponent.  If the result is from | ||||
| 	! 0 to 51, then the IEEE fraction has that many integer bits. | ||||
| 	! (IEEE has an implicit 1 before its fraction.  If the IEEE | ||||
| 	! fraction has 0 integer bits, we still have an integer.) | ||||
| 
 | ||||
| 	extrwi r5, r3, 11, 1		! r5 = IEEE exponent | ||||
| 	addic. r5, r5, -1023		! r5 = nr of integer bits | ||||
| 	blt no_int | ||||
| 	cmpwi r5, 21 | ||||
| 	blt small_int | ||||
| 	blt 4f				! branch if no integer | ||||
| 	cmpwi r5, 52 | ||||
| 	blt big_int | ||||
| 	bge 5f				! branch if no fraction | ||||
| 	cmpwi r5, 21 | ||||
| 	bge 6f				! branch if large integer | ||||
| 	! fall through if small integer | ||||
| 
 | ||||
| 	! f1 is an integer without fraction (or infinity or NaN). | ||||
| 	fmr f2, f1			! integer = f1 | ||||
| 	b subtract | ||||
| 
 | ||||
| no_int: | ||||
| 	! f1 is a fraction without integer. | ||||
| 	fsub f2, f1, f1			! integer = zero | ||||
| 	b done | ||||
| 
 | ||||
| small_int: | ||||
| 	! f1 has r5 = 0 to 20 integer bits in the IEEE fraction. | ||||
| 	! High word has 20 - r5 fraction bits. | ||||
| 	li r6, 20 | ||||
|  | @ -47,21 +39,28 @@ small_int: | |||
| 	srw r3, r3, r6 | ||||
| 	li r4, 0			! clear low word | ||||
| 	slw r3, r3, r6			! clear fraction in high word | ||||
| 	b move_int | ||||
| 	! fall through | ||||
| 
 | ||||
| big_int: | ||||
| 	! f1 has r5 = 21 to 51 to integer bits. | ||||
| 1:	stw r3, 0(sp) | ||||
| 	stw r4, 4(sp) | ||||
| 	lfd f2, 0(sp)			! integer = high word, low word | ||||
| 2:	fsub f1, f1, f2			! fraction = value - integer | ||||
| 3:	stfd f1, 8(sp)			! push fraction | ||||
| 	stfd f2, 0(sp)			! push integer | ||||
| 	blr | ||||
| 
 | ||||
| 4:	! f1 is a fraction without integer. | ||||
| 	fsub f2, f1, f1			! integer = zero | ||||
| 	b 3b | ||||
| 
 | ||||
| 5:	! f1 is an integer without fraction (or infinity or NaN). | ||||
| 	fmr f2, f1			! integer = f1 | ||||
| 	b 2b | ||||
| 
 | ||||
| 6:	! f1 has r5 = 21 to 51 to integer bits. | ||||
| 	! Low word has 52 - r5 fraction bits. | ||||
| 	li r6, 52 | ||||
| 	subf r6, r5, r6 | ||||
| 	srw r4, r4, r6 | ||||
| 	slw r4, r4, r6			! clear fraction in low word | ||||
| move_int: | ||||
| 	stw r3, 0(sp) | ||||
| 	stw r4, 4(sp) | ||||
| 	lfd f2, 0(sp)			! f2 = integer | ||||
| subtract: | ||||
| 	fsub f1, f1, f2			! fraction = value - integer | ||||
| done: | ||||
| 	addi sp, sp, 8			! restore stack pointer | ||||
| 	blr | ||||
| 	b 1b | ||||
|  |  | |||
|  | @ -1,24 +1,20 @@ | |||
| .sect .text | ||||
| 
 | ||||
| ! Set union. | ||||
| !  Stack: ( b a size -- a+b ) | ||||
| !  Stack: ( a b size -- a+b ) | ||||
| 
 | ||||
| .define .ior | ||||
| .ior: | ||||
| 	lwz r3, 0 (sp) | ||||
| 	addi sp, sp, 4 | ||||
| 	lwz	r3, 0(sp)		! r3 = size | ||||
| 	srwi	r7, r3, 2 | ||||
| 	mtspr	ctr, r7			! ctr = size / 4 | ||||
| 	add	r4, sp, r3		! r4 = pointer before set a | ||||
| 
 | ||||
| 	mr	r4, sp			! r4 = ptr to set a | ||||
| 	add	r5, sp, r3		! r5 = ptr to set b | ||||
| 	srwi	r6, r3, 2 | ||||
| 	mtspr	ctr, r6			! ctr = r3 / 4 | ||||
| 1: | ||||
| 	lwz	r7, 0(r4) | ||||
| 	lwz	r8, 0(r5) | ||||
| 	or	r8, r7, r8		! union of words | ||||
| 	stw	r8, 0(r5) | ||||
| 	addi	r4, r4, 4 | ||||
| 	addi	r5, r5, 4 | ||||
| 	! Loop with r4 in set a and sp in set b. | ||||
| 1:	lwzu	r5, 4(r4) | ||||
| 	lwzu	r6, 4(sp) | ||||
| 	or	r7, r5, r6		! union of words | ||||
| 	stw	r7, 0(r4) | ||||
| 	bdnz	1b			! loop ctr times | ||||
| 	add	sp, sp, r3 | ||||
| 	addi	sp, sp, 4		! drop last word of set b | ||||
| 	blr | ||||
|  |  | |||
|  | @ -2,39 +2,13 @@ | |||
| 
 | ||||
| ! Load from bounds-checked array. | ||||
| ! | ||||
| ! On entry: | ||||
| !    r3 = ptr to descriptor | ||||
| !    r4 = index | ||||
| !    r5 = address of array | ||||
| ! Stack: ( array-adr index descriptor-adr -- element ) | ||||
| 
 | ||||
| .define .lar4 | ||||
| .lar4: | ||||
| 	mfspr r10, lr | ||||
| 	bl .aar4 | ||||
| 	! pass r3 = size from .aar4 to .los4 | ||||
| 	bl .los4 | ||||
| 	mtspr lr, r10 | ||||
| 	! r3 = ptr to element | ||||
| 	! r0 = size of element | ||||
| 
 | ||||
| 	cmpwi r0, 1 | ||||
| 	bne 1f | ||||
| 	! Load 1 byte. | ||||
| 	lbz r4, 0(r3) | ||||
| 	stwu r4, -4(sp) | ||||
| 	blr | ||||
| 1: | ||||
| 	cmpwi r0, 2 | ||||
| 	bne 2f | ||||
| 	! Load 2 bytes. | ||||
| 	lhz r4, 0(r3) | ||||
| 	stwu r4, -4(sp) | ||||
| 	blr | ||||
| 2: | ||||
| 	! Load r0 bytes, where r0 must be a positive multiple of 4. | ||||
| 	subf sp, r0, sp		! move stack pointer down | ||||
| 	or r5, r0, r0		! index r5 = length r0 | ||||
| 3: | ||||
| 	addic. r5, r5, -4	! r5 -= 4 | ||||
| 	lwzx r4, r5, r3 | ||||
| 	stwx r4, r5, sp | ||||
| 	bgt 3b			! loop if r5 > 0 | ||||
| 	blr | ||||
|  |  | |||
|  | @ -1,47 +0,0 @@ | |||
| .sect .text | ||||
| 
 | ||||
| ! Loads a variable-sized structure onto the stack. | ||||
| ! | ||||
| !     r3 = size | ||||
| !     r4 = address | ||||
| 
 | ||||
| .define .los | ||||
| .los: | ||||
| 	! These sizes are handled specially. | ||||
| 
 | ||||
| 	cmplwi r3, 1 | ||||
| 	ble size1 | ||||
| 
 | ||||
| 	cmplwi r3, 2 | ||||
| 	ble size2 | ||||
| 
 | ||||
| 	cmplwi r3, 4 | ||||
| 	ble size4 | ||||
| 
 | ||||
| 	! Variable-sized structure. | ||||
| 
 | ||||
| 	addi r3, r3, 3 | ||||
| 	clrrwi r3, r3, 2         ! align size | ||||
| 
 | ||||
| 	add r4, r4, r3           ! adjust address to top of block | ||||
| 
 | ||||
| 	srwi r3, r3, 2           ! convert size to the number of words | ||||
| 	mtspr ctr, r3 | ||||
| 
 | ||||
| 1: | ||||
| 	lwzu r5, -4(r4) | ||||
| 	stwu r5, -4(sp) | ||||
| 	bdnz 1b                  ! decrement CTR, jump if non-zero | ||||
| 	blr | ||||
| 
 | ||||
| size1: | ||||
| 	lbz r3, 0(r4) | ||||
| 	b 1f | ||||
| size2: | ||||
| 	lhz r3, 0(r4) | ||||
| 	b 1f | ||||
| size4: | ||||
| 	lwz r3, 0(r4) | ||||
| 1: | ||||
| 	stwu r3, -4(sp) | ||||
| 	blr | ||||
							
								
								
									
										34
									
								
								mach/powerpc/libem/los4.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								mach/powerpc/libem/los4.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,34 @@ | |||
| .sect .text | ||||
| 
 | ||||
| ! Loads a variable-sized block onto the stack. | ||||
| ! | ||||
| ! On entry: r3 = size | ||||
| ! Stack: ( address -- block ) | ||||
| ! Preserves r10 for .lar4 | ||||
| 
 | ||||
| .define .los4 | ||||
| .los4: | ||||
| 	lwz r4, 0(sp)            ! r4 = address | ||||
| 
 | ||||
| 	! Sizes 1 and 2 are handled specially. | ||||
| 	cmplwi r3, 1 | ||||
| 	ble 1f | ||||
| 	cmplwi r3, 2 | ||||
| 	ble 2f | ||||
| 
 | ||||
| 	! Else the size must be a multiple of 4. | ||||
| 	srwi r5, r3, 2 | ||||
| 	mtspr ctr, r5            ! ctr = number of words | ||||
| 	addi sp, sp, 4 | ||||
| 	add r4, r4, r3           ! adjust address to end of block | ||||
| 4:	lwzu r5, -4(r4) | ||||
| 	stwu r5, -4(sp) | ||||
| 	bdnz 4b                  ! decrement ctr, jump if non-zero | ||||
| 	blr | ||||
| 
 | ||||
| 1:	lbz r5, 0(r4) | ||||
| 	stw r5, 0(sp) | ||||
| 	blr | ||||
| 2:	lhz r5, 0(r4) | ||||
| 	stw r5, 0(sp) | ||||
| 	blr | ||||
|  | @ -1,12 +0,0 @@ | |||
| .sect .text | ||||
| 
 | ||||
| ! Standard boilerplate for returning from functions. | ||||
| 
 | ||||
| .define .ret | ||||
| .ret: | ||||
| 	lwz r0, 4(fp) | ||||
| 	mtspr lr, r0 | ||||
| 	lwz r0, 0(fp)   ! our stack frame becomes invalid as soon as... | ||||
| 	addi sp, fp, 8  ! ...we change sp | ||||
| 	mr fp, r0 | ||||
| 	blr | ||||
|  | @ -2,41 +2,13 @@ | |||
| 
 | ||||
| ! Store to bounds-checked array. | ||||
| ! | ||||
| ! On entry: | ||||
| !    r3 = ptr to descriptor | ||||
| !    r4 = index | ||||
| !    r5 = address of array | ||||
| ! Stack: ( element array-adr index descriptor-adr -- ) | ||||
| 
 | ||||
| .define .sar4 | ||||
| .sar4: | ||||
| 	mfspr r10, lr | ||||
| 	bl .aar4 | ||||
| 	! pass r3 = size from .aar4 to .sts4 | ||||
| 	bl .sts4 | ||||
| 	mtspr lr, r10 | ||||
| 	! r3 = ptr to element | ||||
| 	! r0 = size of element | ||||
| 
 | ||||
| 	cmpwi r0, 1 | ||||
| 	bne 1f | ||||
| 	! Store 1 byte. | ||||
| 	lwz r4, 0(sp) | ||||
| 	addi sp, sp, 4 | ||||
| 	stb r4, 0(r3) | ||||
| 	blr | ||||
| 1: | ||||
| 	cmpwi r0, 2 | ||||
| 	bne 2f | ||||
| 	! Store 2 bytes. | ||||
| 	lwz r4, 0(sp) | ||||
| 	addi sp, sp, 4 | ||||
| 	sth r4, 0(r3) | ||||
| 	blr | ||||
| 2: | ||||
| 	! Store r0 bytes, where r0 must be a positive multiple of 4. | ||||
| 	or r5, r0, r0		! index r5 = length r0 | ||||
| 3: | ||||
| 	addic. r5, r5, -4	! r5 -= 4 | ||||
| 	lwzx r4, r5, sp | ||||
| 	stwx r4, r5, r3 | ||||
| 	bgt 3b			! loop if r5 > 0 | ||||
| 	add sp, r0, sp		! move stack pointer up | ||||
| 	blr | ||||
|  |  | |||
|  | @ -1,50 +0,0 @@ | |||
| .sect .text | ||||
| 
 | ||||
| ! Stores a variable-sized structure from the stack. | ||||
| ! | ||||
| !     r3 = size | ||||
| !     r4 = address | ||||
| 
 | ||||
| .define .sts | ||||
| .sts: | ||||
| 	! These sizes are handled specially. | ||||
| 
 | ||||
| 	lwz r5, 0(sp) | ||||
| 
 | ||||
| 	cmplwi r3, 1 | ||||
| 	ble size1 | ||||
| 
 | ||||
| 	cmplwi r3, 2 | ||||
| 	ble size2 | ||||
| 
 | ||||
| 	cmplwi r3, 4 | ||||
| 	ble size4 | ||||
| 
 | ||||
| 	! Variable-sized structure. | ||||
| 
 | ||||
| 	addi r3, r3, 3 | ||||
| 	clrrwi r3, r3, 2         ! align size | ||||
| 
 | ||||
| 	srwi r3, r3, 2           ! convert size to the number of words | ||||
| 	mtspr ctr, r3 | ||||
| 
 | ||||
| 1: | ||||
| 	lwz r5, 0(sp) | ||||
| 	addi sp, sp, 4 | ||||
| 	stw r5, 0(r4) | ||||
| 	addi r4, r4, 4 | ||||
| 
 | ||||
| 	bdnz 1b                  ! decrement CTR, jump if non-zero | ||||
| 	blr | ||||
| 
 | ||||
| size1: | ||||
| 	stb r5, 0(r4) | ||||
| 	b 1f | ||||
| size2: | ||||
| 	sth r5, 0(r4) | ||||
| 	b 1f | ||||
| size4: | ||||
| 	stw r5, 0(r4) | ||||
| 1: | ||||
| 	addi sp, sp, 4 | ||||
| 	blr | ||||
							
								
								
									
										35
									
								
								mach/powerpc/libem/sts4.s
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								mach/powerpc/libem/sts4.s
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | |||
| .sect .text | ||||
| 
 | ||||
| ! Stores a variable-sized block from the stack. | ||||
| ! | ||||
| ! On entry: r3 = size | ||||
| ! Stack: ( block address -- ) | ||||
| ! Preserves r10 for .sar4 | ||||
| 
 | ||||
| .define .sts4 | ||||
| .sts4: | ||||
| 	lwz r4, 0(sp)            ! r4 = address | ||||
| 
 | ||||
| 	! Sizes 1 and 2 are handled specially. | ||||
| 	cmplwi r3, 1 | ||||
| 	ble 1f | ||||
| 	cmplwi r3, 2 | ||||
| 	ble 2f | ||||
| 
 | ||||
| 	! Else the size must be a multiple of 4. | ||||
| 	srwi r5, r3, 2 | ||||
| 	mtspr ctr, r5            ! ctr = number of words | ||||
| 	addi r4, r4, -4          ! adjust address to before block | ||||
| 4:	lwzu r5, 4(sp) | ||||
| 	stwu r5, 4(r4) | ||||
| 	bdnz 4b                  ! decrement ctr, jump if non-zero | ||||
| 	addi sp, sp, 4 | ||||
| 	blr | ||||
| 
 | ||||
| 1:	lwz r5, 4(sp) | ||||
| 	stb r5, 0(r4) | ||||
| 	b 3f | ||||
| 2:	lwz r5, 4(sp) | ||||
| 	sth r5, 0(r4) | ||||
| 3:	addi sp, sp, 8 | ||||
| 	blr | ||||
|  | @ -1,22 +1,20 @@ | |||
| .sect .text | ||||
| 
 | ||||
| ! Set symmetric difference. | ||||
| !  Stack: ( b a -- a/b ) | ||||
| !  With r3 = size of set | ||||
| !  Stack: ( a b size -- a/b ) | ||||
| 
 | ||||
| .define .xor | ||||
| .xor: | ||||
| 	mr	r4, sp			! r4 = ptr to set a | ||||
| 	add	r5, sp, r3		! r5 = ptr to set b | ||||
| 	srwi	r6, r3, 2 | ||||
| 	mtspr	ctr, r6			! ctr = r3 / 4 | ||||
| 1: | ||||
| 	lwz	r7, 0(r4) | ||||
| 	lwz	r8, 0(r5) | ||||
| 	xor	r8, r7, r8		! symmetric difference of words | ||||
| 	stw	r8, 0(r5) | ||||
| 	addi	r4, r4, 4 | ||||
| 	addi	r5, r5, 4 | ||||
| 	lwz	r3, 0(sp)		! r3 = size | ||||
| 	srwi	r7, r3, 2 | ||||
| 	mtspr	ctr, r7			! ctr = size / 4 | ||||
| 	add	r4, sp, r3		! r4 = pointer before set a | ||||
| 
 | ||||
| 	! Loop with r4 in set a and sp in set b. | ||||
| 1:	lwzu	r5, 4(r4) | ||||
| 	lwzu	r6, 4(sp) | ||||
| 	xor	r7, r5, r6		! symmetric difference of words | ||||
| 	stw	r7, 0(r4) | ||||
| 	bdnz	1b			! loop ctr times | ||||
| 	add	sp, sp, r3 | ||||
| 	addi	sp, sp, 4		! drop last word of set b | ||||
| 	blr | ||||
|  |  | |||
|  | @ -5,17 +5,12 @@ | |||
| 
 | ||||
| .define .zer | ||||
| .zer: | ||||
| 	lwz     r3, 0(sp) | ||||
| 	addi    sp, sp, 4 | ||||
| 
 | ||||
| 	lwz	r3, 0(sp)		! r3 = size | ||||
| 	srwi	r7, r3, 2 | ||||
| 	li	r4, 0			! r4 = zero | ||||
| 	neg	r5, r3 | ||||
| 	add	sp, sp, r5		! allocate set | ||||
| 	mr	r6, sp			! r6 = ptr to set | ||||
| 	mtspr	ctr, r7			! ctr = r3 / 4 | ||||
| 1: | ||||
| 	stw	r4, 0(r6)		! store zero in set | ||||
| 	addi	r6, r6, 4 | ||||
| 	mtspr	ctr, r7			! ctr = size / 4 | ||||
| 	addi	sp, sp, 4		! drop size from stack | ||||
| 	li	r4, 0 | ||||
| 
 | ||||
| 1:	stwu	r4, -4(sp)		! push zero | ||||
| 	bdnz	1b			! loop ctr times | ||||
| 	blr | ||||
|  |  | |||
|  | @ -4,19 +4,15 @@ | |||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <limits.h> | ||||
| 
 | ||||
| #ifndef NORCSID | ||||
| static char rcsid[]=	"$Id$" ; | ||||
| #endif | ||||
| 
 | ||||
| int framesize; | ||||
| 
 | ||||
| /*
 | ||||
|  * machine dependent back end routines for the Zilog Z80. | ||||
|  * machine dependent back end routines for the PowerPC | ||||
|  */ | ||||
| 
 | ||||
| #include <limits.h> | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| static long framesize; | ||||
| 
 | ||||
| con_part(int sz, word w) | ||||
| { | ||||
| 	while (part_size % sz) | ||||
|  | @ -25,17 +21,14 @@ con_part(int sz, word w) | |||
| 		part_flush(); | ||||
| 	if (sz == 1) { | ||||
| 		w &= 0xFF; | ||||
| 		w <<= 8*(3-part_size); | ||||
| 		w <<= 8 * (3 - part_size); | ||||
| 		part_word |= w; | ||||
| 	} else if (sz == 2) { | ||||
| 		w &= 0xFFFF; | ||||
| 		if (part_size == 0) { | ||||
| 			/* Shift 8 for m68k2, 16 otherwise */ | ||||
| 			w <<= 4 * TEM_WSIZE; | ||||
| 		} | ||||
| 		w <<= 8 * (2 - part_size); | ||||
| 		part_word |= w; | ||||
| 	} else { | ||||
| 		assert(sz == TEM_WSIZE); | ||||
| 		assert(sz == 4); | ||||
| 		part_word = w; | ||||
| 	} | ||||
| 	part_size += sz; | ||||
|  | @ -56,17 +49,26 @@ con_mult(word sz) | |||
| #define FL_MSB_AT_LOW_ADDRESS	1 | ||||
| #include <con_float> | ||||
| 
 | ||||
| static void | ||||
| emit_prolog(void) | ||||
| { | ||||
| 	fprintf(codefile, "mfspr r0, lr\n"); | ||||
| 	fprintf(codefile, "addi sp, sp, %ld\n", -framesize - 8); | ||||
| 	fprintf(codefile, "stw fp, %ld(sp)\n", framesize); | ||||
| 	fprintf(codefile, "stw r0, %ld(sp)\n", framesize + 4); | ||||
| 	fprintf(codefile, "addi fp, sp, %ld\n", framesize); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| prolog(full nlocals) | ||||
| { | ||||
| 	int ss = nlocals + 8; | ||||
| 	fprintf(codefile, "addi sp, sp, %d\n", -ss); | ||||
| 	fprintf(codefile, "stw fp, %d(sp)\n", nlocals); | ||||
| 	fprintf(codefile, "mfspr r0, lr\n" | ||||
| 	                  "stw r0, %d(sp)\n", nlocals+4); | ||||
| 	fprintf(codefile, "addi fp, sp, %d\n", nlocals); | ||||
| 	 | ||||
| 	framesize = nlocals; | ||||
| 
 | ||||
| #ifdef REGVARS | ||||
| 	/* f_regsave() will call emit_prolog() */ | ||||
| #else | ||||
| 	emit_prolog(); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void | ||||
|  | @ -102,110 +104,153 @@ char *segname[] = { | |||
| 
 | ||||
| #ifdef REGVARS | ||||
| 
 | ||||
| static int savedregsi[32]; | ||||
| static int numsaved; | ||||
| static long savedf[32]; | ||||
| static long savedi[32]; | ||||
| static int savedtop; | ||||
| static uint32_t lfs_set; | ||||
| 
 | ||||
| /* Calculate the register score of a local variable. */ | ||||
| int | ||||
| regscore(long offset, int size, int type, int frequency, int totype) | ||||
| { | ||||
| 	int score; | ||||
| 
 | ||||
| 	switch (type) { | ||||
| 		case reg_float: | ||||
| 			/* Don't put reg_float in reg_any. */ | ||||
| 			if (totype != reg_float) | ||||
| 				return -1; | ||||
| 			assert(size == 4 || size == 8); | ||||
| 			break; | ||||
| 		default: | ||||
| 			assert(size == 4); | ||||
| 			break; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Clamp to avoid overflowing 16-bit int score. */ | ||||
| 	if (frequency > 8000) | ||||
| 		frequency = 8000; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Each occurence of a regvar saves about 4 bytes by not | ||||
| 	 * emitting a load or store instruction.  The overhead is | ||||
| 	 * about 8 bytes to save and restore the register, plus | ||||
| 	 * 4 bytes if the local is a parameter. | ||||
| 	 */ | ||||
| 	score = 4 * frequency - 8 - ((offset >= 0) ? 4 : 0); | ||||
| #if 0 | ||||
| 	fprintf(codefile, "! local %ld score %d\n", offset, score); | ||||
| #endif | ||||
| 	return score; | ||||
| } | ||||
| 
 | ||||
| /* Initialise regvar system for one function. */ | ||||
| 
 | ||||
| i_regsave() | ||||
| i_regsave(void) | ||||
| { | ||||
| 	int i; | ||||
| 	 | ||||
| 	fprintf(codefile, "! i_regsave()\n"); | ||||
| 	for (i=0; i<32; i++) | ||||
| 		savedregsi[i] = INT_MAX; | ||||
| 	numsaved = 0; | ||||
| 
 | ||||
| 	for (i=0; i<32; i++) { | ||||
| 		savedf[i] = LONG_MIN; | ||||
| 		savedi[i] = LONG_MIN; | ||||
| 	} | ||||
| 
 | ||||
| 	/* Set top of register save area, relative to fp. */ | ||||
| 	savedtop = -framesize; | ||||
| 
 | ||||
| 	lfs_set = 0;  /* empty set */ | ||||
| } | ||||
| 
 | ||||
| /* Mark a register as being saved. */ | ||||
| 
 | ||||
| regsave(const char* regname, full offset, int size) | ||||
| regsave(const char* regname, long offset, int size) | ||||
| { | ||||
| 	int regnum = atoi(regname+1); | ||||
| 	savedregsi[regnum] = offset; | ||||
| 	numsaved++; | ||||
| 	 | ||||
| 	fprintf(codefile, "! %d is saved in %s\n", offset, regname); | ||||
| #if 0 | ||||
| 	fprintf(codefile, "stwu %s, -4(sp)\n", regname); | ||||
| 	if (offset >= 0) | ||||
| 		fprintf(codefile, "lwz %s, %d(fp)\n", regname, offset); | ||||
| #endif | ||||
| 	int regnum = atoi(regname + 1); | ||||
| 
 | ||||
| 	assert(regnum >= 0 && regnum <= 31); | ||||
| 	switch (regname[0]) { | ||||
| 		case 'f': | ||||
| 			savedf[regnum] = offset; | ||||
| 			framesize += 8; | ||||
| 			if (size == 4) | ||||
| 				lfs_set |= ((uint32_t)1<<regnum); | ||||
| 			break; | ||||
| 		case 'r': | ||||
| 			savedi[regnum] = offset; | ||||
| 			framesize += 4; | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* Finish saving ragisters. */ | ||||
| 
 | ||||
| void saveloadregs(const char* ops, const char* opm) | ||||
| static void | ||||
| saveloadregs(const char* ops, const char* opm, const char *opf) | ||||
| { | ||||
| 	int offset = -(framesize + numsaved*4); | ||||
| 	int reg = 32; | ||||
| 	 | ||||
| 	/* Check for the possibility of a multiple. */ | ||||
| 	 | ||||
| 	do | ||||
| 	{ | ||||
| 		reg--; | ||||
| 	} | ||||
| 	while ((reg > 0) && (savedregsi[reg] != INT_MAX)); | ||||
| 	if (reg < 31) | ||||
| 	{ | ||||
| 		fprintf(codefile, "%s r%d, %d(fp)\n", opm, reg+1, offset); | ||||
| 		offset += (31-reg)*4; | ||||
| 	} | ||||
| 	 | ||||
| 	/* Saved everything else singly. */ | ||||
| 	 | ||||
| 	while (reg > 0) | ||||
| 	{ | ||||
| 		if (savedregsi[reg] != INT_MAX) | ||||
| 		{ | ||||
| 			fprintf(codefile, "%s r%d, %d(fp)\n", ops, reg, offset); | ||||
| 			offset += 4; | ||||
| 	long offset = savedtop; | ||||
| 	int reg; | ||||
| 
 | ||||
| 	/* Do floating-point registers. */ | ||||
| 	for (reg = 31; reg >= 0; reg--) { | ||||
| 		if (savedf[reg] != LONG_MIN) { | ||||
| 			offset -= 8; | ||||
| 			fprintf(codefile, "%s f%d, %ld(fp)\n", | ||||
| 				opf, reg, offset); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (savedi[31] != LONG_MIN && savedi[30] != LONG_MIN) { | ||||
| 		/*
 | ||||
| 		 * Do multiple registers from reg to r31. | ||||
| 		 * | ||||
| 		 * Using stmw or lmw reduces code size, but in some | ||||
| 		 * processors, runs slower than the equivalent pile of | ||||
| 		 * stw or lwz instructions. | ||||
| 		 */ | ||||
| 		reg = 30; | ||||
| 		while (reg > 0 && savedi[reg - 1] != LONG_MIN) | ||||
| 			reg--; | ||||
| 		offset -= (32 - reg) * 4; | ||||
| 		fprintf(codefile, "%s r%d, %ld(fp)\n", opm, reg, offset); | ||||
| 	} else | ||||
| 		reg = 32; | ||||
| 
 | ||||
| 	/* Do single general-purpose registers. */ | ||||
| 	for (reg--; reg >= 0; reg--) { | ||||
| 		if (savedi[reg] != LONG_MIN) { | ||||
| 			offset -= 4; | ||||
| 			fprintf(codefile, "%s r%d, %ld(fp)\n", | ||||
| 				ops, reg, offset); | ||||
| 		} | ||||
| 		reg--; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| f_regsave() | ||||
| f_regsave(void) | ||||
| { | ||||
| 	int i; | ||||
| 	fprintf(codefile, "! f_regsave()\n"); | ||||
| 	fprintf(codefile, "addi sp, sp, %d\n", -numsaved*4); | ||||
| 	 | ||||
| 	saveloadregs("stw", "stmw"); | ||||
| 	 | ||||
| 	for (i=0; i<32; i++) | ||||
| 		if ((savedregsi[i] != INT_MAX) && (savedregsi[i] > 0)) | ||||
| 			fprintf(codefile, "lwz r%d, %d(fp)\n", i, savedregsi[i]); | ||||
| 	int reg; | ||||
| 
 | ||||
| 	emit_prolog(); | ||||
| 	saveloadregs("stw", "stmw", "stfd"); | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Register variables with offset >= 0 must load an argument | ||||
| 	 * from that offset. | ||||
| 	 */ | ||||
| 	for (reg = 31; reg >= 0; reg--) | ||||
| 		if (savedf[reg] >= 0) | ||||
| 			fprintf(codefile, "%s f%d, %ld(fp)\n", | ||||
| 				(lfs_set & ((uint32_t)1<<reg)) ? "lfs" : "lfd", | ||||
| 				reg, savedf[reg]); | ||||
| 
 | ||||
| 	for (reg = 31; reg >= 0; reg--) | ||||
| 		if (savedi[reg] >= 0) | ||||
| 			fprintf(codefile, "lwz r%d, %ld(fp)\n", | ||||
| 				reg, savedi[reg]); | ||||
| } | ||||
| 
 | ||||
| /* Restore all saved registers. */ | ||||
| 
 | ||||
| regreturn() | ||||
| regreturn(void) | ||||
| { | ||||
| 	fprintf(codefile, "! regreturn()\n"); | ||||
| 	saveloadregs("lwz", "lmw"); | ||||
| } | ||||
| 
 | ||||
| /* Calculate the score of a given register. */ | ||||
| 
 | ||||
| int regscore(full offset, int size, int type, int frequency, int totype) | ||||
| { | ||||
| 	int score; | ||||
| 	 | ||||
| 	fprintf(codefile, "! regscore(%ld, %d, %d, %d, %d)\n", offset, size, type, frequency, totype); | ||||
| 	 | ||||
| 	if (size != 4) | ||||
| 		return -1; | ||||
| 	 | ||||
| 	/* Per use: 6 bytes (on average)
 | ||||
| 	 * Overhead in prologue: 4 bytes, plus 4 if a parameter | ||||
| 	 * Overhead in epilogue: 0 bytes | ||||
| 	 */ | ||||
| 	  | ||||
| 	score = frequency*6 - 4 - ((offset>=0) ? 4 : 0); | ||||
| 	fprintf(codefile, "! local at offset %d has regvar score %d\n", offset, score); | ||||
| 	return score; | ||||
| 	saveloadregs("lwz", "lmw", "lfd"); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -14,6 +14,9 @@ static char rcsid[] = "$Id$"; | |||
| #include "result.h" | ||||
| #include "glosym.h" | ||||
| #include "extern.h" | ||||
| #ifdef REGVARS | ||||
| #include "regvar.h" | ||||
| #endif | ||||
| #ifdef USE_TES | ||||
| #include "label.h" | ||||
| #endif | ||||
|  | @ -382,7 +385,7 @@ compute(node, presult) register node_p node; register result_t *presult; { | |||
| 		return; | ||||
| 	case EX_REGVAR: | ||||
| 	assert(leaf1.e_typ == EV_INT); | ||||
| 		i = isregvar((long) leaf1.e_v.e_con); | ||||
| 		i = PICK_REGVAR((long) leaf1.e_v.e_con, node->ex_rnode); | ||||
| 		if (i<=0)  { | ||||
| 			presult->e_typ = EV_UNDEF; | ||||
| 			return; | ||||
|  | @ -390,7 +393,7 @@ compute(node, presult) register node_p node; register result_t *presult; { | |||
| 		presult->e_typ = EV_REG; | ||||
| 		presult->e_v.e_reg=i; | ||||
| 		return; | ||||
| #endif | ||||
| #endif /* REGVARS */ | ||||
| 	case EX_UMINUS: | ||||
| 	assert(leaf1.e_typ == EV_INT); | ||||
| 		presult->e_v.e_con = -leaf1.e_v.e_con; | ||||
|  |  | |||
|  | @ -54,4 +54,6 @@ extern int *rvnumbers[];		/* lists of numbers */ | |||
| #endif | ||||
| 
 | ||||
| extern FILE *codefile; | ||||
| extern FILE *freopen(); | ||||
| 
 | ||||
| extern void error(const char *s, ...); | ||||
| extern void fatal(const char *s, ...); | ||||
|  |  | |||
|  | @ -365,7 +365,6 @@ dopseudo() { | |||
| 		} else if (argval == ms_reg) { | ||||
| 			long r_off; | ||||
| 			int r_size,r_type,r_score; | ||||
| 			struct regvar *linkreg(); | ||||
| 
 | ||||
| 			if (!regallowed) | ||||
| 				error("mes 3 not allowed here"); | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ extern string myalloc(); | |||
| struct regvar *rvlist; | ||||
| 
 | ||||
| struct regvar * | ||||
| linkreg(of,sz,tp,sc) long of; { | ||||
| linkreg(long of, int sz, int tp, int sc) { | ||||
| 	register struct regvar *rvlp; | ||||
| 
 | ||||
| 	rvlp= (struct regvar *) myalloc(sizeof *rvlp); | ||||
|  | @ -43,14 +43,26 @@ linkreg(of,sz,tp,sc) long of; { | |||
| } | ||||
| 
 | ||||
| void | ||||
| tryreg(rvlp,typ) register struct regvar *rvlp; { | ||||
| tryreg(struct regvar *rvlp, int typ) { | ||||
| 	int score; | ||||
| 	register i; | ||||
| 	register struct regassigned *ra; | ||||
| 	struct regvar *save; | ||||
| 
 | ||||
| 	if (typ != reg_any && nregvar[typ]!=0) { | ||||
| 		if (machregs[rvnumbers[typ][0]].r_size!=rvlp->rv_size) | ||||
| 		struct reginfo *ri = &machregs[rvnumbers[typ][0]]; | ||||
| 		int size, wrong; | ||||
| 
 | ||||
| 		size = ri->r_size; | ||||
| 		wrong = (size!=rvlp->rv_size); | ||||
| #ifdef REGLAP | ||||
| 		/* reg_float may have one subregister */ | ||||
| 		if (wrong && ri->r_members[0]!=0) { | ||||
| 			size = machregs[ri->r_members[0]].r_size; | ||||
| 			wrong = (size!=rvlp->rv_size); | ||||
| 		} | ||||
| #endif /* REGLAP */ | ||||
| 		if (wrong) | ||||
| 			score = -1; | ||||
| 		else | ||||
| 			score = regscore(rvlp->rv_off, | ||||
|  | @ -88,30 +100,54 @@ tryreg(rvlp,typ) register struct regvar *rvlp; { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| fixregvars(saveall) { | ||||
| 	register struct regvar *rv; | ||||
| 	register rvtyp,i; | ||||
| void | ||||
| fixregvars(int saveall) { | ||||
| 	struct reginfo *rp, *rp2; | ||||
| 	struct regvar *rv; | ||||
| 	int i, regno, rvtyp; | ||||
| 	 | ||||
| 	swtxt(); | ||||
| 	i_regsave();	/* machine dependent initialization */ | ||||
| 	for (rvtyp=reg_any;rvtyp<=reg_float;rvtyp++) { | ||||
| 	    for(i=0;i<nregvar[rvtyp];i++) | ||||
| 		if (saveall) { | ||||
| 			struct reginfo *rp; | ||||
| 			rp= &machregs[rvnumbers[rvtyp][i]]; | ||||
| 			regsave(codestrings[rp->r_repr],(long)-TEM_WSIZE,rp->r_size); | ||||
| #ifdef REGLAP | ||||
| 			/*
 | ||||
| 			 * A reg_float may have two sizes.  If so, | ||||
| 			 * only save the larger size. | ||||
| 			 */ | ||||
| 			if ((regno = rp->r_members[0]) != 0 && | ||||
| 			    machregs[regno].r_size > rp->r_size) | ||||
| 				rp= &machregs[regno]; | ||||
| #endif | ||||
| 			regsave(codestrings[rp->r_repr], | ||||
| 				    (long)-TEM_WSIZE,rp->r_size); | ||||
| 		} else if(regassigned[rvtyp][i].ra_score>0) { | ||||
| 			rv=regassigned[rvtyp][i].ra_rv; | ||||
| 			rv->rv_reg=rvnumbers[rvtyp][i]; | ||||
| 			rv->rv_reg = regno = rvnumbers[rvtyp][i]; | ||||
| 			rv->rv_type = rvtyp; | ||||
| 			regsave(codestrings[machregs[rv->rv_reg].r_repr], | ||||
| #ifdef REGLAP | ||||
| 			/*
 | ||||
| 			 * Change regno to match rv->rv_size, but | ||||
| 			 * leave old regno in rv->rv_reg so that | ||||
| 			 * isregvar_size() can handle both sizes. | ||||
| 			 */ | ||||
| 			if (machregs[regno].r_size != rv->rv_size) { | ||||
| 				regno = machregs[regno].r_members[0]; | ||||
| 				assert(regno != 0); | ||||
| 				assert(machregs[regno].r_size == rv->rv_size); | ||||
| 			} | ||||
| #endif | ||||
| 			regsave(codestrings[machregs[regno].r_repr], | ||||
| 				    rv->rv_off,rv->rv_size); | ||||
| 		} | ||||
| 	} | ||||
| 	f_regsave(); | ||||
| } | ||||
| 
 | ||||
| isregvar(off) long off; { | ||||
| int | ||||
| isregvar(long off) { | ||||
| 	register struct regvar *rvlp; | ||||
| 
 | ||||
| 	for(rvlp=rvlist;rvlp!=0;rvlp=rvlp->rv_next) | ||||
|  | @ -120,7 +156,28 @@ isregvar(off) long off; { | |||
| 	return(-1); | ||||
| } | ||||
| 
 | ||||
| isregtyp(off) long off; { | ||||
| #ifdef REGLAP | ||||
| int | ||||
| isregvar_size(long off, int size) { | ||||
| 	int regno = isregvar(off); | ||||
| 	/*
 | ||||
| 	 * A reg_float may have two sizes.  If this register has the | ||||
| 	 * wrong size, then use the overlapping register.  A register | ||||
| 	 * may switch sizes in the middle of a procedure. | ||||
| 	 */ | ||||
| 	if (regno > 0 && machregs[regno].r_size != size) { | ||||
| 		if (machregs[regno].r_size != size) { | ||||
| 			regno = machregs[regno].r_members[0]; | ||||
| 			assert(regno != 0); | ||||
| 			assert(machregs[regno].r_size == size); | ||||
| 		} | ||||
| 	} | ||||
| 	return regno; | ||||
| } | ||||
| #endif /* REGLAP */ | ||||
| 
 | ||||
| int | ||||
| isregtyp(long off) { | ||||
| 	register struct regvar *rvlp; | ||||
| 
 | ||||
| 	for(rvlp=rvlist;rvlp!=0;rvlp=rvlp->rv_next) | ||||
|  | @ -129,7 +186,8 @@ isregtyp(off) long off; { | |||
| 	return(-1); | ||||
| } | ||||
| 
 | ||||
| unlinkregs() { | ||||
| void | ||||
| unlinkregs(void) { | ||||
| 	register struct regvar *rvlp,*t; | ||||
| 	register struct regassigned *ra; | ||||
| 	int rvtyp,i; | ||||
|  |  | |||
|  | @ -21,3 +21,19 @@ struct regassigned { | |||
| extern struct regvar *rvlist; | ||||
| extern int nregvar[]; | ||||
| extern struct regassigned *regassigned[]; | ||||
| 
 | ||||
| struct regvar *linkreg(long, int, int, int); | ||||
| void tryreg(struct regvar *, int); | ||||
| void fixregvars(int); | ||||
| int isregvar(long); | ||||
| #ifdef REGLAP | ||||
| int isregvar_size(long, int); | ||||
| #endif | ||||
| int isregtyp(long); | ||||
| void unlinkregs(void); | ||||
| 
 | ||||
| #ifdef REGLAP | ||||
| #define PICK_REGVAR(off, size) isregvar_size(off, size) | ||||
| #else | ||||
| #define PICK_REGVAR(off, size) isregvar(off) | ||||
| #endif | ||||
|  |  | |||
|  | @ -2,8 +2,9 @@ | |||
| static char rcsid[] = "$Id$"; | ||||
| #endif | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <stdarg.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include "assert.h" | ||||
| #include "param.h" | ||||
| #include "tables.h" | ||||
|  | @ -12,6 +13,9 @@ static char rcsid[] = "$Id$"; | |||
| #include "data.h" | ||||
| #include "result.h" | ||||
| #include "extern.h" | ||||
| #ifdef REGVARS | ||||
| #include "regvar.h" | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||
|  | @ -117,7 +121,9 @@ instance(instno,token) register token_p token; { | |||
| 	case IN_D_DESCR: | ||||
| 		compute(&enodes[inp->in_info[1]], &result); | ||||
| 		assert(result.e_typ==EV_INT); | ||||
| 		if ((regno=isregvar(result.e_v.e_con)) > 0) { | ||||
| 		regno = PICK_REGVAR(result.e_v.e_con, | ||||
| 				    tokens[inp->in_info[0]].t_size); | ||||
| 		if (regno > 0) { | ||||
| 			token->t_token = -1; | ||||
| 			token->t_att[0].ar = regno; | ||||
| 			for (i=TOKENSIZE-1;i>0;i--) | ||||
|  | @ -205,7 +211,9 @@ cinstance(instno,token,tp,regno) register token_p token,tp; { | |||
| 			compute(&enodes[inp->in_info[1]], &result); | ||||
| 			curtoken = ct; | ||||
| 			assert(result.e_typ==EV_INT); | ||||
| 			if ((regno=isregvar(result.e_v.e_con)) > 0) { | ||||
| 			regno = PICK_REGVAR(result.e_v.e_con, | ||||
| 					    tokens[inp->in_info[0]].t_size); | ||||
| 			if (regno > 0) { | ||||
| 				token->t_token = -1; | ||||
| 				token->t_att[0].ar = regno; | ||||
| 				for (i=TOKENSIZE-1;i>0;i--) | ||||
|  | @ -657,11 +665,12 @@ itokcost() { | |||
| 		tdp->t_cost.ct_space = costcalc(tdp->t_cost); | ||||
| } | ||||
| 
 | ||||
| /*VARARGS1*/ | ||||
| error(s,a1,a2,a3,a4,a5,a6,a7,a8) char *s; { | ||||
| void error(const char *s, ...) { | ||||
| 	va_list ap; | ||||
| 
 | ||||
| 	va_start(ap,s); | ||||
| 	fprintf(stderr,"Error: "); | ||||
| 	fprintf(stderr,s,a1,a2,a3,a4,a5,a6,a7,a8); | ||||
| 	vfprintf(stderr,s,ap); | ||||
| 	fprintf(stderr,"\n"); | ||||
| #ifdef TABLEDEBUG | ||||
| 	ruletrace(); | ||||
|  | @ -670,11 +679,12 @@ error(s,a1,a2,a3,a4,a5,a6,a7,a8) char *s; { | |||
| 	exit(-1); | ||||
| } | ||||
| 
 | ||||
| /*VARARGS1*/ | ||||
| fatal(s,a1,a2,a3,a4,a5,a6,a7,a8) char *s; { | ||||
| void fatal(const char *s, ...) { | ||||
| 	va_list ap; | ||||
| 
 | ||||
| 	va_start(ap,s); | ||||
| 	fprintf(stderr,"Fatal: "); | ||||
| 	fprintf(stderr,s,a1,a2,a3,a4,a5,a6,a7,a8); | ||||
| 	vfprintf(stderr,s,ap); | ||||
| 	fprintf(stderr,"\n"); | ||||
| #ifdef TABLEDEBUG | ||||
| 	ruletrace(); | ||||
|  |  | |||
|  | @ -19,11 +19,8 @@ var PLATFORM=linuxppc | |||
| var PLATFORMDIR={EM}/share/ack/{PLATFORM} | ||||
| var CPP_F=-D__unix | ||||
| var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x10000054 | ||||
| var C_LIB={PLATFORMDIR}/libc-ansi.a | ||||
| # bitfields reversed for compatibility with (g)cc. | ||||
| var CC_ALIGN=-Vr | ||||
| var OLD_C_LIB={C_LIB} | ||||
| var MACHOPT_F= | ||||
| var MACHOPT_F=-m3 | ||||
| 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. | ||||
|  |  | |||
|  | @ -140,7 +140,7 @@ showrelo() | |||
| 	case RELOPPC: | ||||
| 		printf("\tPowerPC 26-bit address\n"); | ||||
| 		break; | ||||
| 	case RELOLIS: | ||||
| 	case RELOPPC_LIS: | ||||
| 		printf("\tPowerPC lis instruction\n"); | ||||
| 		break; | ||||
| 	case RELOVC4: | ||||
|  |  | |||
|  | @ -3,26 +3,32 @@ pointersize: 4 | |||
| %%RA | ||||
| general registers: 19 | ||||
| address registers: 0 | ||||
| floating point registers: 0 | ||||
| floating point registers: 18 | ||||
| use general as pointer: yes | ||||
| 
 | ||||
| register score parameters: | ||||
| 	local variable: | ||||
| 		(2 cases) | ||||
| 		(3 cases) | ||||
| 		pointer,general | ||||
| 			(1 size) | ||||
| 			default ->	(3,4) | ||||
| 		general,general | ||||
| 			(1 size) | ||||
| 			default ->	(3,4) | ||||
| 		float,float | ||||
| 			(1 size) | ||||
| 			default ->	(5,4) | ||||
| 	address of local variable: | ||||
| 		(2 cases) | ||||
| 		(3 cases) | ||||
| 		pointer,general | ||||
| 			(1 size) | ||||
| 			default ->	(0,0) | ||||
| 		general,general | ||||
| 			(1 size) | ||||
| 			default ->	(0,0) | ||||
| 		float,float | ||||
| 			(1 size) | ||||
| 			default ->	(0,0) | ||||
| 	constant: | ||||
| 		(2 sizes) | ||||
| 		fitbyte ->	(-1,-1) | ||||
|  | @ -39,21 +45,27 @@ register score parameters: | |||
| 
 | ||||
| opening cost parameters: | ||||
| 	local variable: | ||||
| 		(2 cases) | ||||
| 		(3 cases) | ||||
| 		pointer | ||||
| 			(1 size) | ||||
| 			default ->	(3,4) | ||||
| 		general | ||||
| 			(1 size) | ||||
| 			default ->	(3,4) | ||||
| 		float | ||||
| 			(1 size) | ||||
| 			default ->	(5,4) | ||||
| 	address of local variable: | ||||
| 		(2 cases) | ||||
| 		(3 cases) | ||||
| 		pointer | ||||
| 			(1 size) | ||||
| 			default ->	(1,4) | ||||
| 		general | ||||
| 			(1 size) | ||||
| 			general ->	(1,4) | ||||
| 			default ->	(1,4) | ||||
| 		float | ||||
| 			(1 size) | ||||
| 			default ->	(1,4) | ||||
| 	constant: | ||||
| 		(2 sizes) | ||||
| 		fitbyte ->	(1000,1000) | ||||
|  | @ -69,7 +81,7 @@ opening cost parameters: | |||
| 		default ->	(1000,1000) | ||||
| 
 | ||||
| register save costs: | ||||
| 	(21 cases) | ||||
| 	(39 cases) | ||||
| 	0 -> (0,0) | ||||
| 	1 -> (6,8) | ||||
| 	2 -> (12,16) | ||||
|  | @ -90,6 +102,24 @@ register save costs: | |||
| 	17 -> (102,136) | ||||
| 	18 -> (108,144) | ||||
| 	19 -> (114,152) | ||||
|         20 -> (120,160) | ||||
| 	21 -> (126,168) | ||||
| 	22 -> (132,176) | ||||
| 	23 -> (138,184) | ||||
| 	24 -> (144,192) | ||||
| 	25 -> (150,200) | ||||
| 	26 -> (156,208) | ||||
| 	27 -> (162,216) | ||||
| 	28 -> (168,224) | ||||
| 	29 -> (174,232) | ||||
| 	30 -> (180,240) | ||||
| 	31 -> (186,248) | ||||
| 	32 -> (192,256) | ||||
| 	33 -> (198,264) | ||||
| 	34 -> (204,272) | ||||
| 	35 -> (210,280) | ||||
| 	36 -> (216,288) | ||||
| 	37 -> (222,296) | ||||
| 	0 -> (0,0) | ||||
| %%UD | ||||
| access costs of global variables: | ||||
|  |  | |||
|  | @ -69,7 +69,8 @@ allocscore(itemtyp,localtyp,size,off,totyp,time_out,space_out) | |||
| 	cond_p m = (cond_p) 0; | ||||
| 
 | ||||
| 	if (localtyp == reg_loop) localtyp = reg_any; | ||||
| 	if (size == ws || size ==ps && totyp == reg_pointer) { | ||||
| 	if (size == ws || size == ps && totyp == reg_pointer || | ||||
| 	    size == 2 * ws && totyp == reg_float) { | ||||
| 		switch(itemtyp) { | ||||
| 		   case LOCALVAR: | ||||
| 			m = alocaltab[localtyp][totyp]; | ||||
|  |  | |||
|  | @ -161,13 +161,14 @@ struct outrelo { | |||
| /* | ||||
|  * relocation type bits | ||||
|  */ | ||||
| #define RELSZ	0x0fff		/* relocation length */ | ||||
| #define RELO1	0x01		/* 1 byte */ | ||||
| #define RELO2	0x02		/* 2 bytes */ | ||||
| #define RELO4	0x03		/* 4 bytes */ | ||||
| #define RELOPPC	0x04		/* 26-bit PowerPC address */ | ||||
| #define RELOLIS	0x05		/* PowerPC lis */ | ||||
| #define RELOVC4	0x06 /* VideoCore IV address in 32-bit insruction */ | ||||
| #define RELSZ   0x0fff          /* relocation length */ | ||||
| #define RELO1        1          /* 1 byte */ | ||||
| #define RELO2        2          /* 2 bytes */ | ||||
| #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 RELPC	0x2000		/* pc relative */ | ||||
| #define RELBR	0x4000		/* High order byte lowest address. */ | ||||
| #define RELWR	0x8000		/* High order word lowest address. */ | ||||
|  | @ -231,7 +232,7 @@ VideoCore IV instruction. | |||
| The relocation depends on the instruction, and uses an offset encoded | ||||
| in the instruction. | ||||
| .PP | ||||
| RELOLIS assembles a PowerPC \fBlis\fR instruction. | ||||
| RELOPPC_LIS assembles a PowerPC \fBlis\fR instruction. | ||||
| The relocatable datum is a 4-byte integer. | ||||
| The high bit is set for ha16 or clear for hi16. | ||||
| The next 5 bits are the register \fIRT\fR. | ||||
|  |  | |||
|  | @ -169,7 +169,7 @@ static uint32_t get_powerpc_valu(char* addr, uint16_t type) | |||
| 		(unsigned long)opcode1, (unsigned long)opcode2); | ||||
| } | ||||
| 
 | ||||
| /* RELOLIS stores a signed 26-bit offset in the low bits. */ | ||||
| /* RELOPPC_LIS stores a signed 26-bit offset in the low bits. */ | ||||
| static uint32_t get_lis_valu(char *addr, uint16_t type) | ||||
| { | ||||
| 	uint32_t valu = read4(addr, type) & 0x03ffffff; | ||||
|  | @ -193,7 +193,7 @@ static uint32_t getvalu(char* addr, uint16_t type) | |||
| 		return read4(addr, type); | ||||
| 	case RELOPPC: | ||||
| 		return get_powerpc_valu(addr, type); | ||||
| 	case RELOLIS: | ||||
| 	case RELOPPC_LIS: | ||||
| 		return get_lis_valu(addr, type); | ||||
| 	case RELOVC4: | ||||
| 		return get_vc4_valu(addr); | ||||
|  | @ -389,7 +389,7 @@ static putvalu(uint32_t valu, char* addr, uint16_t type) | |||
| 	case RELOPPC: | ||||
| 		put_powerpc_valu(addr, valu, type); | ||||
| 		break; | ||||
| 	case RELOLIS: | ||||
| 	case RELOPPC_LIS: | ||||
| 		put_lis_valu(addr, valu, type); | ||||
| 		break; | ||||
| 	case RELOVC4: | ||||
|  |  | |||
|  | @ -78,7 +78,8 @@ iocc_t iops[20]; | |||
| %token PATTERNS PAT WITH EXACT KILLS USES REUSING GEN YIELDS LEAVING | ||||
| %token DEFINED SAMESIGN SFIT UFIT ROM LOWW HIGHW ISROM | ||||
| %token CMPEQ CMPNE CMPLT CMPGT CMPLE CMPGE OR2 AND2 LSHIFT RSHIFT NOT COMP | ||||
| %token INREG REGVAR REG_ANY REG_FLOAT REG_LOOP REG_POINTER | ||||
| %token INREG REGVAR REGVAR_W REGVAR_D | ||||
| %token REG_ANY REG_FLOAT REG_LOOP REG_POINTER | ||||
| %token <yy_int> ADORNACCESS | ||||
| %token <yy_int> ADORNCC | ||||
| %token INT | ||||
|  | @ -129,8 +130,9 @@ machtable | |||
| 	: constants | ||||
| 	  properties | ||||
| 	  registers | ||||
| 		{ check_reglap(); } | ||||
| 	  tokens | ||||
| 	  	{ make_std_sets(); } | ||||
| 		{ make_std_sets(); } | ||||
| 	  sets | ||||
| 	  instructions | ||||
| 	  moves | ||||
|  | @ -1086,7 +1088,11 @@ expr | |||
| 
 | ||||
| regvarexpr | ||||
| 	: REGVAR '(' expr optregvartype ')' | ||||
| 		{ $$ = regvar_expr($3,$4); } | ||||
| 		{ $$ = regvar_expr($3,$4,-1); } | ||||
| 	| REGVAR_W '(' expr optregvartype ')' | ||||
| 		{ $$ = regvar_expr($3,$4,wordsize); } | ||||
| 	| REGVAR_D '(' expr optregvartype ')' | ||||
| 		{ $$ = regvar_expr($3,$4,2*wordsize); } | ||||
| 	; | ||||
| 
 | ||||
| optregvartype | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ static char rcsid[]= "$Id$"; | |||
| #include "expr.h" | ||||
| #include "regvar.h" | ||||
| #include <cgg_cg.h> | ||||
| #include <em_reg.h> | ||||
| #include "extern.h" | ||||
| 
 | ||||
| extern set_t l_sets[]; | ||||
|  | @ -273,15 +274,38 @@ expr_t iextoaddr(e) expr_t e; { | |||
| 	return(result); | ||||
| } | ||||
| 
 | ||||
| expr_t regvar_expr(e,regtyp) expr_t e; { | ||||
| expr_t regvar_expr(e,regtyp,regsiz) expr_t e; { | ||||
| 	expr_t result; | ||||
| 	register i; | ||||
| 	 | ||||
| 	result = make_expr(TYPREG,EX_REGVAR,i_expr(e),0); | ||||
| 	int i, regno, s, two_sizes; | ||||
| 
 | ||||
| 	two_sizes = (regtyp == reg_float && reglap != 0); | ||||
| 	if (regsiz == -1) { | ||||
| 		/* reglap: Can't guess between 2 sizes of reg_float. */ | ||||
| 		if (two_sizes && regsiz == -1) | ||||
| 			error("Must use regvar_w() or regvar_d()"); | ||||
| 		else | ||||
| 			regsiz = rvsize[regtyp]; | ||||
| 	} | ||||
| 
 | ||||
| 	result = make_expr(TYPREG,EX_REGVAR,i_expr(e),regsiz); | ||||
| 	for(i=0;i<SZOFSET(MAXREGS);i++) | ||||
| 		result.ex_regset[i]=0; | ||||
| 	for(i=0;i<nregvar[regtyp];i++) | ||||
| 		BIS(result.ex_regset,rvnumbers[regtyp][i]); | ||||
| 
 | ||||
| 	/* s = the size of the registers in rvnumbers[regtyp] */ | ||||
| 	s = two_sizes ? reglap : rvsize[regtyp]; | ||||
| 	if (s == regsiz) { | ||||
| 		for(i=0;i<nregvar[regtyp];i++) | ||||
| 			BIS(result.ex_regset,rvnumbers[regtyp][i]); | ||||
| 	} | ||||
| 	/* reglap: Also check the 2nd size of reg_float. */ | ||||
| 	if (two_sizes && rvsize[regtyp] == regsiz) { | ||||
| 		for(i=0;i<nregvar[regtyp];i++) { | ||||
| 			/* regno = first subregister */ | ||||
| 			regno = l_regs[rvnumbers[regtyp][i]].ri_memb[0]; | ||||
| 			if (regno != 0) | ||||
| 				BIS(result.ex_regset, regno); | ||||
| 		} | ||||
| 	} | ||||
| 	return(result); | ||||
| } | ||||
| 		 | ||||
|  |  | |||
|  | @ -175,7 +175,11 @@ found: | |||
| 		case IN_D_DESCR: | ||||
| 			{ int temp; | ||||
| 
 | ||||
| 			temp=ex_lookup(EX_REGVAR,insta->in_info[1],0); | ||||
| 			if (insta->in_which == IN_S_DESCR) | ||||
| 				temp = wordsize; | ||||
| 			else | ||||
| 				temp = 2 * wordsize; | ||||
| 			temp=ex_lookup(EX_REGVAR,insta->in_info[1],temp); | ||||
| 			vi->vi_next = generase(temp); | ||||
| 			vi = vi->vi_next; | ||||
| 			vi->vi_next = genremove(temp); | ||||
|  |  | |||
|  | @ -38,6 +38,8 @@ reg_float	REG_FLOAT | |||
| reg_loop	REG_LOOP | ||||
| reg_pointer	REG_POINTER | ||||
| regvar	REGVAR | ||||
| regvar_d	REGVAR_D | ||||
| regvar_w	REGVAR_W | ||||
| return	RETURN | ||||
| reusing	REUSING | ||||
| rom	ROM | ||||
|  |  | |||
|  | @ -317,7 +317,15 @@ outregs() { | |||
| 			} | ||||
| 			clashlist[iclashlist++] = 0; | ||||
| 		} | ||||
| 		fprintf(ctable,",%d",l_regs[i].ri_rregvar>=0); | ||||
| 		/*
 | ||||
| 		 * Write .r_refcount = 1 for register variables or 0 | ||||
| 		 * for other registers. | ||||
| 		 * | ||||
| 		 * reglap: Write .r_refcount = 0 if the register | ||||
| 		 *   variable has a subregister. | ||||
| 		 */ | ||||
| 		fprintf(ctable,",%d", | ||||
| 		    l_regs[i].ri_rregvar>=0 && l_regs[i].ri_memb[0]==0); | ||||
| 		fprintf(ctable,"},\n"); | ||||
| 	} | ||||
| 	fprintf(ctable,"};\n\n short clashlist[] = {\n\t"); | ||||
|  | @ -332,6 +340,8 @@ outregvars() { | |||
| 	register i,j; | ||||
| 
 | ||||
| 	fprintf(htable,"#define REGVARS\n"); | ||||
| 	if (reglap!=0) | ||||
| 		fprintf(htable,"#define REGLAP\n"); | ||||
| 	fprintf(ctable,"#include \"regvar.h\"\n"); | ||||
| 	fprintf(ctable,"int nregvar[4] = { "); | ||||
| 	for (i=0;i<4;i++) { | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ | |||
| #define DL_REGVAR	0x4 | ||||
| 
 | ||||
| extern int rvused; | ||||
| extern int reglap; | ||||
| extern int nregvar[4]; | ||||
| extern int rvsize[4]; | ||||
| extern int rvnumbers[4][MAXREGVAR]; | ||||
|  |  | |||
							
								
								
									
										101
									
								
								util/ncgg/subr.c
									
										
									
									
									
								
							
							
						
						
									
										101
									
								
								util/ncgg/subr.c
									
										
									
									
									
								
							|  | @ -19,6 +19,7 @@ static char rcsid[]= "$Id$"; | |||
| #include "token.h" | ||||
| #include "regvar.h" | ||||
| #include <cgg_cg.h> | ||||
| #include <em_reg.h> | ||||
| #include "extern.h" | ||||
| 
 | ||||
| n_proc(name) char *name; { | ||||
|  | @ -228,6 +229,72 @@ n_sconst(ident,val) char *ident,*val; { | |||
| 	sy_p->sy_value.syv_stringno = strlookup(val); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| add_regvar(int rvnum, reginfo *regp, int rv) | ||||
| { | ||||
| 	int overlap, wrong; | ||||
| 
 | ||||
| 	overlap = wrong = 0; | ||||
| 	if (regp->ri_memb[0]!=0) { | ||||
| 		/* reglap: float may overlap with one subregister */ | ||||
| 		if (rv==reg_float && regp->ri_memb[1]==0) | ||||
| 			overlap = 1; | ||||
| 		else | ||||
| 			wrong = 1; | ||||
| 	} | ||||
| 	if (wrong) | ||||
| 		error("Register variables may not have subregisters"); | ||||
| 
 | ||||
| 	rvused |= ANY_REGVAR; | ||||
| 	if (regp->ri_size == wordsize) | ||||
| 		rvused |= SL_REGVAR; | ||||
| 	else if (regp->ri_size == 2*wordsize) | ||||
| 		rvused |= DL_REGVAR; | ||||
| 
 | ||||
| 	wrong = 0; | ||||
| 	if (overlap) { | ||||
| 		/* reglap = size of overlap float */ | ||||
| 		if (reglap==0) { | ||||
| 			reglap = regp->ri_size; | ||||
| 			if (reglap == rvsize[reg_float]) | ||||
| 				error("Two sizes of reg_float can't be same size"); | ||||
| 		} else if (reglap!=regp->ri_size) | ||||
| 			wrong = 1; | ||||
| 	} else { | ||||
| 		if (nregvar[rv]==0) | ||||
| 			rvsize[rv] = regp->ri_size; | ||||
| 		else if (rvsize[rv]!=regp->ri_size) | ||||
| 			wrong = 1; | ||||
| 	} | ||||
| 	if (wrong) | ||||
| 		error("All register variables of one type must have the same size"); | ||||
| 
 | ||||
| 	if (overlap) { | ||||
| 		reginfo *member_p = &l_regs[regp->ri_memb[0]]; | ||||
| 		int i; | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * reglap: Remove member_p from rvnumbers. | ||||
| 		 *   Add reg_p in its place. | ||||
| 		 */ | ||||
| 		wrong = 1; | ||||
| 		for (i = 0; i < nregvar[rv]; i++) { | ||||
| 			if (rvnumbers[rv][i] == regp->ri_memb[0]) { | ||||
| 				rvnumbers[rv][i] = rvnum; | ||||
| 				wrong = 0; | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		if (wrong) | ||||
| 			error("Register variable %s can't overlap %s", | ||||
| 			    regp->ri_name, member_p->ri_name); | ||||
| 	} else { | ||||
| 		NEXT(nregvar[rv],MAXREGVAR,"Register variable"); | ||||
| 		rvnumbers[rv][nregvar[rv]-1] = rvnum; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| regline(rl,pl,rv) varinfo *rl,*pl; { | ||||
| 	register varinfo *rrl,*rpl; | ||||
| 	register short *sp; | ||||
|  | @ -251,25 +318,29 @@ regline(rl,pl,rv) varinfo *rl,*pl; { | |||
| 		regp->ri_size = thissize; | ||||
| 		regp->ri_class = regclass; | ||||
| 		regp->ri_rregvar = rv; | ||||
| 		if (rv>=0) { | ||||
| 			if (regp->ri_memb[0]!=0) | ||||
| 				error("Register variables may not have subregisters"); | ||||
| 			rvused |= ANY_REGVAR; | ||||
| 			if (regp->ri_size == wordsize) | ||||
| 				rvused |= SL_REGVAR; | ||||
| 			else if (regp->ri_size == 2*wordsize) | ||||
| 				rvused |= DL_REGVAR; | ||||
| 			if (nregvar[rv]==0) | ||||
| 				rvsize[rv] = regp->ri_size; | ||||
| 			else if (rvsize[rv]!=regp->ri_size) | ||||
| 				error("All register variables of one type must have the same size"); | ||||
| 			NEXT(nregvar[rv],MAXREGVAR,"Register variable"); | ||||
| 			rvnumbers[rv][nregvar[rv]-1] = rrl->vi_int[0]; | ||||
| 		} | ||||
| 		if (rv>=0) | ||||
| 			add_regvar(rrl->vi_int[0], regp, rv); | ||||
| 	} | ||||
| 	regclass++; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| check_reglap() { | ||||
| 	reginfo *regp; | ||||
| 	int i; | ||||
| 
 | ||||
| 	if (reglap == 0) | ||||
| 		return; | ||||
| 
 | ||||
| 	/* reglap: Check that every reg_float has size == reglap. */ | ||||
| 	for (i = 0; i < nregvar[reg_float]; i++) { | ||||
| 		regp = &l_regs[rvnumbers[reg_float][i]]; | ||||
| 		if (regp->ri_size != reglap) | ||||
| 			error("Missing reg_float of size %d to contain %s", | ||||
| 			      reglap, regp->ri_name); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| setallreg(vi) struct varinfo *vi; { | ||||
| 
 | ||||
| 	nallreg=0; | ||||
|  |  | |||
|  | @ -39,6 +39,7 @@ int maxmembers=0; | |||
| int regclass=1; | ||||
| int maxtokensize=0; | ||||
| int rvused=0; | ||||
| int reglap=0; | ||||
| int nregvar[4]; | ||||
| int rvsize[4]; | ||||
| int rvnumbers[4][MAXREGVAR]; | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue