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
				
			
		
							
								
								
									
										2
									
								
								h/out.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								h/out.h
									
										
									
									
									
								
							|  | @ -66,7 +66,7 @@ struct outname { | ||||||
| #define RELO2        2          /* 2 bytes */ | #define RELO2        2          /* 2 bytes */ | ||||||
| #define RELO4        3          /* 4 bytes */ | #define RELO4        3          /* 4 bytes */ | ||||||
| #define RELOPPC      4          /* PowerPC 26-bit address */ | #define RELOPPC      4          /* PowerPC 26-bit address */ | ||||||
| #define RELOLIS    5			/* PowerPC lis */ | #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 RELPC	0x2000			/* pc relative */ | #define RELPC	0x2000			/* pc relative */ | ||||||
|  |  | ||||||
|  | @ -42,8 +42,8 @@ void emit_hl(word_t in) | ||||||
| 	case OP_HA:  /* ha16[expr] */ | 	case OP_HA:  /* ha16[expr] */ | ||||||
| 		if (PASS_RELO && (hl_expr.typ & S_TYP) != S_ABS) { | 		if (PASS_RELO && (hl_expr.typ & S_TYP) != S_ABS) { | ||||||
| 			/*
 | 			/*
 | ||||||
| 			 * RELOLIS only works with lis _, _ (same as | 			 * RELOPPC_LIS only works with lis _, _ (same | ||||||
| 			 * addis _, r0, _).  Check if instruction | 			 * as addis _, r0, _).  Check if instruction | ||||||
| 			 * isn't addis or register RA isn't r0. | 			 * isn't addis or register RA isn't r0. | ||||||
| 			 */ | 			 */ | ||||||
| 			if ((in & 0xfc1f0000) != (0x3c000000)) | 			if ((in & 0xfc1f0000) != (0x3c000000)) | ||||||
|  | @ -55,7 +55,7 @@ void emit_hl(word_t in) | ||||||
| 			 * Low 26 bits: signed offset | 			 * Low 26 bits: signed offset | ||||||
| 			 */ | 			 */ | ||||||
| 			fit(fitx(hl_expr.val, 26)); | 			fit(fitx(hl_expr.val, 26)); | ||||||
| 			newrelo(hl_expr.typ, RELOLIS | FIXUPFLAGS); | 			newrelo(hl_expr.typ, RELOPPC_LIS | FIXUPFLAGS); | ||||||
| 			reg = (in >> 21) & 0x1f; | 			reg = (in >> 21) & 0x1f; | ||||||
| 			in = (hl_token == OP_HA) << 31; | 			in = (hl_token == OP_HA) << 31; | ||||||
| 			in |= reg << 26; | 			in |= reg << 26; | ||||||
|  |  | ||||||
|  | @ -1,14 +1,9 @@ | ||||||
| .sect .text | .sect .text | ||||||
| 
 | 
 | ||||||
| ! Index into a bounds-checked array. | ! Get address of element of bounds-checked array. | ||||||
| ! | ! | ||||||
| ! On entry: | ! Stack: ( array-adr index descriptor-adr -- element-adr ) | ||||||
| !    r3 = ptr to descriptor | ! Sets r3 = size of element for .los4, .sts4 | ||||||
| !    r4 = index |  | ||||||
| !    r5 = address of array |  | ||||||
| ! Yields: |  | ||||||
| !    r3 = address of element |  | ||||||
| !    r0 = size of element (used by .lar4, .sar4) |  | ||||||
| ! Preserves r10 for .lar4, .sar4 | ! Preserves r10 for .lar4, .sar4 | ||||||
| 
 | 
 | ||||||
| .define .aar4 | .define .aar4 | ||||||
|  | @ -17,16 +12,21 @@ | ||||||
| 	ori r0, r0, lo16[.trap_earray] | 	ori r0, r0, lo16[.trap_earray] | ||||||
| 	mtspr ctr, r0            ! load CTR with trap address | 	mtspr ctr, r0            ! load CTR with trap address | ||||||
| 
 | 
 | ||||||
| 	lwz r0, 0(r3) | 	lwz r4, 0(sp)            ! r4 = address of descriptor | ||||||
| 	subf. r4, r0, r4         ! adjust range | 	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 | 	bltctr                   ! check lower bound | ||||||
| 
 | 
 | ||||||
| 	lwz r0, 4(r3) | 	lwz r0, 4(r4) | ||||||
| 	cmplw r4, r3 | 	cmplw r5, r0 | ||||||
| 	bgectr                   ! check upper bound | 	bgtctr                   ! check upper bound | ||||||
| 
 |  | ||||||
| 	lwz r0, 8(r3) |  | ||||||
| 	mullw r4, r4, r0         ! scale index |  | ||||||
| 	add r3, r4, r5           ! calculate element address |  | ||||||
| 
 | 
 | ||||||
|  | 	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 | 	blr | ||||||
|  |  | ||||||
|  | @ -1,24 +1,20 @@ | ||||||
| .sect .text | .sect .text | ||||||
| 
 | 
 | ||||||
| ! Set intersection. | ! Set intersection. | ||||||
| !  Stack: ( b a size -- a*b ) | !  Stack: ( a b size -- a*b ) | ||||||
| 
 | 
 | ||||||
| .define .and | .define .and | ||||||
| .and: | .and: | ||||||
| 	lwz r3, 0 (sp)      ! r3 = size | 	lwz	r3, 0(sp)		! r3 = size | ||||||
| 	addi sp, sp, 4 | 	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 | 	! Loop with r4 in set a and sp in set b. | ||||||
| 	add	r5, sp, r3		! r5 = ptr to set b | 1:	lwzu	r5, 4(r4) | ||||||
| 	srwi	r6, r3, 2 | 	lwzu	r6, 4(sp) | ||||||
| 	mtspr	ctr, r6			! ctr = r3 / 4 | 	and	r7, r5, r6		! intersection of words | ||||||
| 1: | 	stw	r7, 0(r4) | ||||||
| 	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 |  | ||||||
| 	bdnz	1b			! loop ctr times | 	bdnz	1b			! loop ctr times | ||||||
| 	add	sp, sp, r3 | 	addi	sp, sp, 4		! drop last word of set b | ||||||
| 	blr | 	blr | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ for _, plat in ipairs(vars.plats) do | ||||||
| 	acklibrary { | 	acklibrary { | ||||||
| 		name = "lib_"..plat, | 		name = "lib_"..plat, | ||||||
| 		srcs = { | 		srcs = { | ||||||
| 			"./*.s", | 			"./*.s", -- rm ret.s | ||||||
| 		}, | 		}, | ||||||
| 		vars = { plat = plat }, | 		vars = { plat = plat }, | ||||||
| 		deps = { | 		deps = { | ||||||
|  |  | ||||||
|  | @ -8,25 +8,24 @@ | ||||||
| 
 | 
 | ||||||
| .define .cif8 | .define .cif8 | ||||||
| .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) | 	lwz r3, 4(sp) | ||||||
| 	xoris r3, r3, 0x8000 | 	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 | 	lfd f0, 0(sp)            ! f0 = (1 << 52) + (1 << 31) + i | ||||||
| 	stw r3, 0(sp)            ! set high word to construct a double | 	lis r3, 0x8000 | ||||||
| 
 | 	stw r3, 4(sp) | ||||||
| 	lfd f0, 0(sp)            ! load value | 	lfd f1, 0(sp)            ! f1 = (1 << 52) + (1 << 31) | ||||||
| 
 | 	fsub f0, f0, f1          ! finish conversion | ||||||
| 	lis r3, ha16[pivot] |  | ||||||
| 	lfd f1, lo16[pivot](r3)  ! load pivot value |  | ||||||
| 	fsub f0, f0, f1          ! adjust |  | ||||||
| 
 | 
 | ||||||
| 	stfd f0, 0(sp)           ! save value again... | 	stfd f0, 0(sp)           ! save value again... | ||||||
| 	blr                      ! ...and return  | 	blr                      ! ...and return  | ||||||
| 
 |  | ||||||
| .sect .rom |  | ||||||
| pivot: |  | ||||||
| 	.data4 0x43300000
 |  | ||||||
| 	.data4 0x80000000
 |  | ||||||
|  |  | ||||||
|  | @ -1,30 +1,27 @@ | ||||||
| .sect .text | .sect .text | ||||||
| 
 | 
 | ||||||
| ! Compare sets a, b. | ! Compare sets a, b. | ||||||
| !  Stack: ( b a -- ) | !  Stack: ( a b size -- result ) | ||||||
| !  With r3 = size of each set | !  Result is 0 if equal, nonzero if not equal. | ||||||
| !  Yields r3 = 0 if equal, nonzero if not equal |  | ||||||
| 
 | 
 | ||||||
| .define .cms | .define .cms | ||||||
| .cms: | .cms: | ||||||
| 	mr	r4, sp			! r4 = ptr to set a | 	lwz	r3, 0(sp)		! r3 = size of each set | ||||||
| 	add	r5, sp, r3		! r5 = ptr to set b | 	srwi	r7, r3, 2 | ||||||
| 	mr	r6, r3			! r6 = size | 	mtspr	ctr, r7			! ctr = size / 4 | ||||||
| 	srwi	r3, r3, 2 | 	add	r4, sp, r3		! r4 = pointer before set a | ||||||
| 	mtspr	ctr, r3			! ctr = size / 4 | 	add	r7, r4, r3		! r7 = pointer to store result | ||||||
| 1: | 
 | ||||||
| 	lwz	r7, 0(r4) | 	! Loop with r4 in a set a and sp in set b. | ||||||
| 	lwz	r8, 0(r5) | 1:	lwzu	r5, 4(r4) | ||||||
| 	cmpw	cr0, r7, r8		! compare words in sets | 	lwzu	r6, 4(sp) | ||||||
| 	addi	r4, r4, 4 | 	cmpw	r5, r6			! compare words | ||||||
| 	addi	r5, r5, 4 | 	bne	2f			! branch if not equal | ||||||
| 	bne	cr0, 2f			! branch if not equal |  | ||||||
| 	bdnz	1b			! loop ctr times | 	bdnz	1b			! loop ctr times | ||||||
| 	addi	r3, r0, 0		! equal: return 0 | 
 | ||||||
|  | 	li	r3, 0			! equal: return 0 | ||||||
| 	b	3f | 	b	3f | ||||||
| 2: | 2:	li	r3, 1			! not equal: return 1 | ||||||
| 	addi	r3, r0, 1		! not equal: return 1 | 3:	mr	sp, r7 | ||||||
| 3: | 	stw	r3, 0(sp)		! push result | ||||||
| 	slwi	r6, r6, 1		! r6 = size * 2 |  | ||||||
| 	add	sp, sp, r6		! remove sets from stack |  | ||||||
| 	blr | 	blr | ||||||
|  |  | ||||||
|  | @ -5,16 +5,15 @@ | ||||||
| 
 | 
 | ||||||
| .define .com | .define .com | ||||||
| .com: | .com: | ||||||
| 	lwz r3, 0 (sp)       ! size | 	lwz	r3, 0(sp)		! r3 = size | ||||||
| 	addi sp, sp, 4 | 	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 | 	! Loop with r4 in set a. | ||||||
| 	srwi	r5, r3, 2 | 1:	lwzu	r5, 4(r4) | ||||||
| 	mtspr	ctr, r5			! ctr = r3 / 4 | 	nor	r7, r5, r5		! complement of word | ||||||
| 1: | 	stw	r7, 0(r4) | ||||||
| 	lwz	r6, 0(r4) |  | ||||||
| 	nor	r6, r6, r6		! complement of word |  | ||||||
| 	stw	r6, 0(r4) |  | ||||||
| 	addi	r4, r4, 4 |  | ||||||
| 	bdnz	1b			! loop ctr times | 	bdnz	1b			! loop ctr times | ||||||
|  | 	addi	sp, sp, 4		! drop size from stack | ||||||
| 	blr | 	blr | ||||||
|  |  | ||||||
|  | @ -6,21 +6,20 @@ | ||||||
| 
 | 
 | ||||||
| .define .cuf8 | .define .cuf8 | ||||||
| .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 | 	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 | 	lfd f0, 0(sp)            ! f0 = (1 << 52) + u | ||||||
| 
 | 	li r3, 0x0000 | ||||||
| 	lis r3, ha16[pivot] | 	stw r3, 4(sp) | ||||||
| 	lfd f1, lo16[pivot](r3)  ! load pivot value | 	lfd f1, 0(sp)            ! f1 = (1 << 52) | ||||||
| 	fsub f0, f0, f1          ! adjust | 	fsub f0, f0, f1          ! finish conversion | ||||||
| 
 | 
 | ||||||
| 	stfd f0, 0(sp)           ! save value again... | 	stfd f0, 0(sp)           ! save value again... | ||||||
| 	blr                      ! ...and return | 	blr                      ! ...and return | ||||||
| 
 |  | ||||||
| .sect .rom |  | ||||||
| pivot: |  | ||||||
| 	.data4 0x43300000
 |  | ||||||
| 	.data4 0x00000000
 |  | ||||||
|  |  | ||||||
|  | @ -3,35 +3,48 @@ | ||||||
| .sect .text | .sect .text | ||||||
| 
 | 
 | ||||||
| ! Split a double-precision float into fraction and exponent, like | ! Split a double-precision float into fraction and exponent, like | ||||||
| ! frexp(3) in C.  On entry: | ! frexp(3) in C. | ||||||
| !  r3 = float, high word (bits 0..31) | ! | ||||||
| !  r4 = float, low word (bits 32..63) | ! Stack: ( double -- fraction exponent ) | ||||||
| ! Yields: |  | ||||||
| !  r3 = fraction, high word (bits 0..31) |  | ||||||
| !  r4 = fraction, low word (bits 32..63) |  | ||||||
| !  r5 = exponent |  | ||||||
| 
 | 
 | ||||||
| .define .fef8 | .define .fef8 | ||||||
| .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: | 	! IEEE double-precision format: | ||||||
| 	!   sign  exponent  fraction | 	!   sign  exponent  fraction | ||||||
| 	!   0     1..11     12..63 | 	!   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 | 	cmpwi r6, 2047 | ||||||
| 	beqlr				! return if infinity or NaN | 	beq 1f				! jump if infinity or NaN | ||||||
| 	cmpwi r6, 0 | 	! fall through if normalized | ||||||
| 	bne 1f				! jump if normalized number |  | ||||||
| 
 | 
 | ||||||
| 	! 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 | 	extrwi r6, r3, 22, 12 | ||||||
| 	addi r5, r0, 0			! r5 = true exponent = 0 |  | ||||||
| 	or. r6, r6, r4			! r6 = high|low fraction | 	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. | 3:	! Got denormalized number, not zero. | ||||||
| 	stwu r4, -4(sp) |  | ||||||
| 	stwu r3, -4(sp) |  | ||||||
| 	lfd f0, 0(sp) | 	lfd f0, 0(sp) | ||||||
| 	lis r6, ha16[_2_64] | 	lis r6, ha16[_2_64] | ||||||
| 	lfd f1, lo16[_2_64](r6) | 	lfd f1, lo16[_2_64](r6) | ||||||
|  | @ -40,14 +53,8 @@ | ||||||
| 	lwz r3, 0(sp) | 	lwz r3, 0(sp) | ||||||
| 	lwz r4, 4(sp) | 	lwz r4, 4(sp) | ||||||
| 	extrwi r6, r3, 11, 1		! r6 = IEEE exponent | 	extrwi r6, r3, 11, 1		! r6 = IEEE exponent | ||||||
| 	addi sp, sp, 8 | 	addi r5, r6, -1022 - 64		! r5 = our exponent | ||||||
| 	addi r5, r6, -1022 - 64		! r5 = true exponent | 	b 1b | ||||||
| 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 |  | ||||||
| 
 | 
 | ||||||
| .sect .rom | .sect .rom | ||||||
| _2_64: | _2_64: | ||||||
|  |  | ||||||
|  | @ -1,45 +1,37 @@ | ||||||
| .sect .text | .sect .text | ||||||
| 
 | 
 | ||||||
| ! Multiplies two double-precision floats, then splits the product into | ! Multiplies two double-precision floats, then splits the product into | ||||||
| ! integer and fraction, like modf(3) in C.  On entry: | ! fraction and integer, like modf(3) in C.  On entry: | ||||||
| !  f1 = float | ! | ||||||
| !  f2 = other float | ! Stack: ( a b -- fraction integer ) | ||||||
| ! Yields: |  | ||||||
| !  f1 = fraction |  | ||||||
| !  f2 = integer |  | ||||||
| 
 | 
 | ||||||
| .define .fif8 | .define .fif8 | ||||||
| .fif8: | .fif8: | ||||||
| 	fmul f1, f1, f2 | 	lfd f1, 8(sp) | ||||||
| 	stfdu f1, -8(sp)		! push f1 = product | 	lfd f2, 0(sp) | ||||||
|  | 	fmul f1, f1, f2			! f1 = a * b | ||||||
|  | 	stfd f1, 0(sp) | ||||||
| 	lwz r3, 0(sp)			! r3 = high word | 	lwz r3, 0(sp)			! r3 = high word | ||||||
| 	lwz r4, 4(sp)			! r4 = low word | 	lwz r4, 4(sp)			! r4 = low word | ||||||
| 
 | 
 | ||||||
| 	! IEEE double-precision format: | 	! IEEE double-precision format: | ||||||
| 	!   sign  exponent  fraction | 	!   sign  exponent  fraction | ||||||
| 	!   0     1..11     12..63 | 	!   0     1..11     12..63 | ||||||
|  | 	! | ||||||
| 	! Subtract 1023 from the IEEE exponent.  If the result is from | 	! Subtract 1023 from the IEEE exponent.  If the result is from | ||||||
| 	! 0 to 51, then the IEEE fraction has that many integer bits. | 	! 0 to 51, then the IEEE fraction has that many integer bits. | ||||||
| 	! (IEEE has an implicit 1 before its fraction.  If the IEEE | 	! (IEEE has an implicit 1 before its fraction.  If the IEEE | ||||||
| 	! fraction has 0 integer bits, we still have an integer.) | 	! fraction has 0 integer bits, we still have an integer.) | ||||||
|  | 
 | ||||||
| 	extrwi r5, r3, 11, 1		! r5 = IEEE exponent | 	extrwi r5, r3, 11, 1		! r5 = IEEE exponent | ||||||
| 	addic. r5, r5, -1023		! r5 = nr of integer bits | 	addic. r5, r5, -1023		! r5 = nr of integer bits | ||||||
| 	blt no_int | 	blt 4f				! branch if no integer | ||||||
| 	cmpwi r5, 21 |  | ||||||
| 	blt small_int |  | ||||||
| 	cmpwi r5, 52 | 	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. | 	! f1 has r5 = 0 to 20 integer bits in the IEEE fraction. | ||||||
| 	! High word has 20 - r5 fraction bits. | 	! High word has 20 - r5 fraction bits. | ||||||
| 	li r6, 20 | 	li r6, 20 | ||||||
|  | @ -47,21 +39,28 @@ small_int: | ||||||
| 	srw r3, r3, r6 | 	srw r3, r3, r6 | ||||||
| 	li r4, 0			! clear low word | 	li r4, 0			! clear low word | ||||||
| 	slw r3, r3, r6			! clear fraction in high word | 	slw r3, r3, r6			! clear fraction in high word | ||||||
| 	b move_int | 	! fall through | ||||||
| 
 | 
 | ||||||
| big_int: | 1:	stw r3, 0(sp) | ||||||
| 	! f1 has r5 = 21 to 51 to integer bits. | 	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. | 	! Low word has 52 - r5 fraction bits. | ||||||
| 	li r6, 52 | 	li r6, 52 | ||||||
| 	subf r6, r5, r6 | 	subf r6, r5, r6 | ||||||
| 	srw r4, r4, r6 | 	srw r4, r4, r6 | ||||||
| 	slw r4, r4, r6			! clear fraction in low word | 	slw r4, r4, r6			! clear fraction in low word | ||||||
| move_int: | 	b 1b | ||||||
| 	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 |  | ||||||
|  |  | ||||||
|  | @ -1,24 +1,20 @@ | ||||||
| .sect .text | .sect .text | ||||||
| 
 | 
 | ||||||
| ! Set union. | ! Set union. | ||||||
| !  Stack: ( b a size -- a+b ) | !  Stack: ( a b size -- a+b ) | ||||||
| 
 | 
 | ||||||
| .define .ior | .define .ior | ||||||
| .ior: | .ior: | ||||||
| 	lwz r3, 0 (sp) | 	lwz	r3, 0(sp)		! r3 = size | ||||||
| 	addi sp, sp, 4 | 	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 | 	! Loop with r4 in set a and sp in set b. | ||||||
| 	add	r5, sp, r3		! r5 = ptr to set b | 1:	lwzu	r5, 4(r4) | ||||||
| 	srwi	r6, r3, 2 | 	lwzu	r6, 4(sp) | ||||||
| 	mtspr	ctr, r6			! ctr = r3 / 4 | 	or	r7, r5, r6		! union of words | ||||||
| 1: | 	stw	r7, 0(r4) | ||||||
| 	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 |  | ||||||
| 	bdnz	1b			! loop ctr times | 	bdnz	1b			! loop ctr times | ||||||
| 	add	sp, sp, r3 | 	addi	sp, sp, 4		! drop last word of set b | ||||||
| 	blr | 	blr | ||||||
|  |  | ||||||
|  | @ -2,39 +2,13 @@ | ||||||
| 
 | 
 | ||||||
| ! Load from bounds-checked array. | ! Load from bounds-checked array. | ||||||
| ! | ! | ||||||
| ! On entry: | ! Stack: ( array-adr index descriptor-adr -- element ) | ||||||
| !    r3 = ptr to descriptor |  | ||||||
| !    r4 = index |  | ||||||
| !    r5 = address of array |  | ||||||
| 
 | 
 | ||||||
| .define .lar4 | .define .lar4 | ||||||
| .lar4: | .lar4: | ||||||
| 	mfspr r10, lr | 	mfspr r10, lr | ||||||
| 	bl .aar4 | 	bl .aar4 | ||||||
|  | 	! pass r3 = size from .aar4 to .los4 | ||||||
|  | 	bl .los4 | ||||||
| 	mtspr lr, r10 | 	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 | 	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. | ! Store to bounds-checked array. | ||||||
| ! | ! | ||||||
| ! On entry: | ! Stack: ( element array-adr index descriptor-adr -- ) | ||||||
| !    r3 = ptr to descriptor |  | ||||||
| !    r4 = index |  | ||||||
| !    r5 = address of array |  | ||||||
| 
 | 
 | ||||||
| .define .sar4 | .define .sar4 | ||||||
| .sar4: | .sar4: | ||||||
| 	mfspr r10, lr | 	mfspr r10, lr | ||||||
| 	bl .aar4 | 	bl .aar4 | ||||||
|  | 	! pass r3 = size from .aar4 to .sts4 | ||||||
|  | 	bl .sts4 | ||||||
| 	mtspr lr, r10 | 	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 | 	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 | .sect .text | ||||||
| 
 | 
 | ||||||
| ! Set symmetric difference. | ! Set symmetric difference. | ||||||
| !  Stack: ( b a -- a/b ) | !  Stack: ( a b size -- a/b ) | ||||||
| !  With r3 = size of set |  | ||||||
| 
 | 
 | ||||||
| .define .xor | .define .xor | ||||||
| .xor: | .xor: | ||||||
| 	mr	r4, sp			! r4 = ptr to set a | 	lwz	r3, 0(sp)		! r3 = size | ||||||
| 	add	r5, sp, r3		! r5 = ptr to set b | 	srwi	r7, r3, 2 | ||||||
| 	srwi	r6, r3, 2 | 	mtspr	ctr, r7			! ctr = size / 4 | ||||||
| 	mtspr	ctr, r6			! ctr = r3 / 4 | 	add	r4, sp, r3		! r4 = pointer before set a | ||||||
| 1: | 
 | ||||||
| 	lwz	r7, 0(r4) | 	! Loop with r4 in set a and sp in set b. | ||||||
| 	lwz	r8, 0(r5) | 1:	lwzu	r5, 4(r4) | ||||||
| 	xor	r8, r7, r8		! symmetric difference of words | 	lwzu	r6, 4(sp) | ||||||
| 	stw	r8, 0(r5) | 	xor	r7, r5, r6		! symmetric difference of words | ||||||
| 	addi	r4, r4, 4 | 	stw	r7, 0(r4) | ||||||
| 	addi	r5, r5, 4 |  | ||||||
| 	bdnz	1b			! loop ctr times | 	bdnz	1b			! loop ctr times | ||||||
| 	add	sp, sp, r3 | 	addi	sp, sp, 4		! drop last word of set b | ||||||
| 	blr | 	blr | ||||||
|  |  | ||||||
|  | @ -5,17 +5,12 @@ | ||||||
| 
 | 
 | ||||||
| .define .zer | .define .zer | ||||||
| .zer: | .zer: | ||||||
| 	lwz     r3, 0(sp) | 	lwz	r3, 0(sp)		! r3 = size | ||||||
| 	addi    sp, sp, 4 |  | ||||||
| 
 |  | ||||||
| 	srwi	r7, r3, 2 | 	srwi	r7, r3, 2 | ||||||
| 	li	r4, 0			! r4 = zero | 	mtspr	ctr, r7			! ctr = size / 4 | ||||||
| 	neg	r5, r3 | 	addi	sp, sp, 4		! drop size from stack | ||||||
| 	add	sp, sp, r5		! allocate set | 	li	r4, 0 | ||||||
| 	mr	r6, sp			! r6 = ptr to set | 
 | ||||||
| 	mtspr	ctr, r7			! ctr = r3 / 4 | 1:	stwu	r4, -4(sp)		! push zero | ||||||
| 1: |  | ||||||
| 	stw	r4, 0(r6)		! store zero in set |  | ||||||
| 	addi	r6, r6, 4 |  | ||||||
| 	bdnz	1b			! loop ctr times | 	bdnz	1b			! loop ctr times | ||||||
| 	blr | 	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) | con_part(int sz, word w) | ||||||
| { | { | ||||||
| 	while (part_size % sz) | 	while (part_size % sz) | ||||||
|  | @ -25,17 +21,14 @@ con_part(int sz, word w) | ||||||
| 		part_flush(); | 		part_flush(); | ||||||
| 	if (sz == 1) { | 	if (sz == 1) { | ||||||
| 		w &= 0xFF; | 		w &= 0xFF; | ||||||
| 		w <<= 8*(3-part_size); | 		w <<= 8 * (3 - part_size); | ||||||
| 		part_word |= w; | 		part_word |= w; | ||||||
| 	} else if (sz == 2) { | 	} else if (sz == 2) { | ||||||
| 		w &= 0xFFFF; | 		w &= 0xFFFF; | ||||||
| 		if (part_size == 0) { | 		w <<= 8 * (2 - part_size); | ||||||
| 			/* Shift 8 for m68k2, 16 otherwise */ |  | ||||||
| 			w <<= 4 * TEM_WSIZE; |  | ||||||
| 		} |  | ||||||
| 		part_word |= w; | 		part_word |= w; | ||||||
| 	} else { | 	} else { | ||||||
| 		assert(sz == TEM_WSIZE); | 		assert(sz == 4); | ||||||
| 		part_word = w; | 		part_word = w; | ||||||
| 	} | 	} | ||||||
| 	part_size += sz; | 	part_size += sz; | ||||||
|  | @ -56,17 +49,26 @@ con_mult(word sz) | ||||||
| #define FL_MSB_AT_LOW_ADDRESS	1 | #define FL_MSB_AT_LOW_ADDRESS	1 | ||||||
| #include <con_float> | #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 | void | ||||||
| prolog(full nlocals) | 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; | 	framesize = nlocals; | ||||||
|  | 
 | ||||||
|  | #ifdef REGVARS | ||||||
|  | 	/* f_regsave() will call emit_prolog() */ | ||||||
|  | #else | ||||||
|  | 	emit_prolog(); | ||||||
|  | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
|  | @ -102,110 +104,153 @@ char *segname[] = { | ||||||
| 
 | 
 | ||||||
| #ifdef REGVARS | #ifdef REGVARS | ||||||
| 
 | 
 | ||||||
| static int savedregsi[32]; | static long savedf[32]; | ||||||
| static int numsaved; | 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. */ | /* Initialise regvar system for one function. */ | ||||||
| 
 | 
 | ||||||
| i_regsave() | i_regsave(void) | ||||||
| { | { | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	fprintf(codefile, "! i_regsave()\n"); | 	for (i=0; i<32; i++) { | ||||||
| 	for (i=0; i<32; i++) | 		savedf[i] = LONG_MIN; | ||||||
| 		savedregsi[i] = INT_MAX; | 		savedi[i] = LONG_MIN; | ||||||
| 	numsaved = 0; | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Set top of register save area, relative to fp. */ | ||||||
|  | 	savedtop = -framesize; | ||||||
|  | 
 | ||||||
|  | 	lfs_set = 0;  /* empty set */ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Mark a register as being saved. */ | /* 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); | 	int regnum = atoi(regname + 1); | ||||||
| 	savedregsi[regnum] = offset; |  | ||||||
| 	numsaved++; |  | ||||||
| 
 | 
 | ||||||
| 	fprintf(codefile, "! %d is saved in %s\n", offset, regname); | 	assert(regnum >= 0 && regnum <= 31); | ||||||
| #if 0 | 	switch (regname[0]) { | ||||||
| 	fprintf(codefile, "stwu %s, -4(sp)\n", regname); | 		case 'f': | ||||||
| 	if (offset >= 0) | 			savedf[regnum] = offset; | ||||||
| 		fprintf(codefile, "lwz %s, %d(fp)\n", regname, offset); | 			framesize += 8; | ||||||
| #endif | 			if (size == 4) | ||||||
| } | 				lfs_set |= ((uint32_t)1<<regnum); | ||||||
| 
 | 			break; | ||||||
| /* Finish saving ragisters. */ | 		case 'r': | ||||||
| 
 | 			savedi[regnum] = offset; | ||||||
| void saveloadregs(const char* ops, const char* opm) | 			framesize += 4; | ||||||
| { | 			break; | ||||||
| 	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; |  | ||||||
| 		} |  | ||||||
| 		reg--; |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| f_regsave() | static void | ||||||
|  | saveloadregs(const char* ops, const char* opm, const char *opf) | ||||||
| { | { | ||||||
| 	int i; | 	long offset = savedtop; | ||||||
| 	fprintf(codefile, "! f_regsave()\n"); | 	int reg; | ||||||
| 	fprintf(codefile, "addi sp, sp, %d\n", -numsaved*4); |  | ||||||
| 
 | 
 | ||||||
| 	saveloadregs("stw", "stmw"); | 	/* 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); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i=0; i<32; i++) | 	if (savedi[31] != LONG_MIN && savedi[30] != LONG_MIN) { | ||||||
| 		if ((savedregsi[i] != INT_MAX) && (savedregsi[i] > 0)) | 		/*
 | ||||||
| 			fprintf(codefile, "lwz r%d, %d(fp)\n", i, savedregsi[i]); | 		 * 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); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | f_regsave(void) | ||||||
|  | { | ||||||
|  | 	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. */ | /* Restore all saved registers. */ | ||||||
| 
 | 
 | ||||||
| regreturn() | regreturn(void) | ||||||
| { | { | ||||||
| 	fprintf(codefile, "! regreturn()\n"); | 	saveloadregs("lwz", "lmw", "lfd"); | ||||||
| 	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; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -14,6 +14,9 @@ static char rcsid[] = "$Id$"; | ||||||
| #include "result.h" | #include "result.h" | ||||||
| #include "glosym.h" | #include "glosym.h" | ||||||
| #include "extern.h" | #include "extern.h" | ||||||
|  | #ifdef REGVARS | ||||||
|  | #include "regvar.h" | ||||||
|  | #endif | ||||||
| #ifdef USE_TES | #ifdef USE_TES | ||||||
| #include "label.h" | #include "label.h" | ||||||
| #endif | #endif | ||||||
|  | @ -382,7 +385,7 @@ compute(node, presult) register node_p node; register result_t *presult; { | ||||||
| 		return; | 		return; | ||||||
| 	case EX_REGVAR: | 	case EX_REGVAR: | ||||||
| 	assert(leaf1.e_typ == EV_INT); | 	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)  { | 		if (i<=0)  { | ||||||
| 			presult->e_typ = EV_UNDEF; | 			presult->e_typ = EV_UNDEF; | ||||||
| 			return; | 			return; | ||||||
|  | @ -390,7 +393,7 @@ compute(node, presult) register node_p node; register result_t *presult; { | ||||||
| 		presult->e_typ = EV_REG; | 		presult->e_typ = EV_REG; | ||||||
| 		presult->e_v.e_reg=i; | 		presult->e_v.e_reg=i; | ||||||
| 		return; | 		return; | ||||||
| #endif | #endif /* REGVARS */ | ||||||
| 	case EX_UMINUS: | 	case EX_UMINUS: | ||||||
| 	assert(leaf1.e_typ == EV_INT); | 	assert(leaf1.e_typ == EV_INT); | ||||||
| 		presult->e_v.e_con = -leaf1.e_v.e_con; | 		presult->e_v.e_con = -leaf1.e_v.e_con; | ||||||
|  |  | ||||||
|  | @ -54,4 +54,6 @@ extern int *rvnumbers[];		/* lists of numbers */ | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| extern FILE *codefile; | 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) { | 		} else if (argval == ms_reg) { | ||||||
| 			long r_off; | 			long r_off; | ||||||
| 			int r_size,r_type,r_score; | 			int r_size,r_type,r_score; | ||||||
| 			struct regvar *linkreg(); |  | ||||||
| 
 | 
 | ||||||
| 			if (!regallowed) | 			if (!regallowed) | ||||||
| 				error("mes 3 not allowed here"); | 				error("mes 3 not allowed here"); | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ extern string myalloc(); | ||||||
| struct regvar *rvlist; | struct regvar *rvlist; | ||||||
| 
 | 
 | ||||||
| struct regvar * | struct regvar * | ||||||
| linkreg(of,sz,tp,sc) long of; { | linkreg(long of, int sz, int tp, int sc) { | ||||||
| 	register struct regvar *rvlp; | 	register struct regvar *rvlp; | ||||||
| 
 | 
 | ||||||
| 	rvlp= (struct regvar *) myalloc(sizeof *rvlp); | 	rvlp= (struct regvar *) myalloc(sizeof *rvlp); | ||||||
|  | @ -43,14 +43,26 @@ linkreg(of,sz,tp,sc) long of; { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| tryreg(rvlp,typ) register struct regvar *rvlp; { | tryreg(struct regvar *rvlp, int typ) { | ||||||
| 	int score; | 	int score; | ||||||
| 	register i; | 	register i; | ||||||
| 	register struct regassigned *ra; | 	register struct regassigned *ra; | ||||||
| 	struct regvar *save; | 	struct regvar *save; | ||||||
| 
 | 
 | ||||||
| 	if (typ != reg_any && nregvar[typ]!=0) { | 	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; | 			score = -1; | ||||||
| 		else | 		else | ||||||
| 			score = regscore(rvlp->rv_off, | 			score = regscore(rvlp->rv_off, | ||||||
|  | @ -88,30 +100,54 @@ tryreg(rvlp,typ) register struct regvar *rvlp; { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fixregvars(saveall) { | void | ||||||
| 	register struct regvar *rv; | fixregvars(int saveall) { | ||||||
| 	register rvtyp,i; | 	struct reginfo *rp, *rp2; | ||||||
|  | 	struct regvar *rv; | ||||||
|  | 	int i, regno, rvtyp; | ||||||
| 	 | 	 | ||||||
| 	swtxt(); | 	swtxt(); | ||||||
| 	i_regsave();	/* machine dependent initialization */ | 	i_regsave();	/* machine dependent initialization */ | ||||||
| 	for (rvtyp=reg_any;rvtyp<=reg_float;rvtyp++) { | 	for (rvtyp=reg_any;rvtyp<=reg_float;rvtyp++) { | ||||||
| 	    for(i=0;i<nregvar[rvtyp];i++) | 	    for(i=0;i<nregvar[rvtyp];i++) | ||||||
| 		if (saveall) { | 		if (saveall) { | ||||||
| 			struct reginfo *rp; |  | ||||||
| 			rp= &machregs[rvnumbers[rvtyp][i]]; | 			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) { | 		} else if(regassigned[rvtyp][i].ra_score>0) { | ||||||
| 			rv=regassigned[rvtyp][i].ra_rv; | 			rv=regassigned[rvtyp][i].ra_rv; | ||||||
| 			rv->rv_reg=rvnumbers[rvtyp][i]; | 			rv->rv_reg = regno = rvnumbers[rvtyp][i]; | ||||||
| 			rv->rv_type = rvtyp; | 			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); | 				    rv->rv_off,rv->rv_size); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	f_regsave(); | 	f_regsave(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| isregvar(off) long off; { | int | ||||||
|  | isregvar(long off) { | ||||||
| 	register struct regvar *rvlp; | 	register struct regvar *rvlp; | ||||||
| 
 | 
 | ||||||
| 	for(rvlp=rvlist;rvlp!=0;rvlp=rvlp->rv_next) | 	for(rvlp=rvlist;rvlp!=0;rvlp=rvlp->rv_next) | ||||||
|  | @ -120,7 +156,28 @@ isregvar(off) long off; { | ||||||
| 	return(-1); | 	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; | 	register struct regvar *rvlp; | ||||||
| 
 | 
 | ||||||
| 	for(rvlp=rvlist;rvlp!=0;rvlp=rvlp->rv_next) | 	for(rvlp=rvlist;rvlp!=0;rvlp=rvlp->rv_next) | ||||||
|  | @ -129,7 +186,8 @@ isregtyp(off) long off; { | ||||||
| 	return(-1); | 	return(-1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| unlinkregs() { | void | ||||||
|  | unlinkregs(void) { | ||||||
| 	register struct regvar *rvlp,*t; | 	register struct regvar *rvlp,*t; | ||||||
| 	register struct regassigned *ra; | 	register struct regassigned *ra; | ||||||
| 	int rvtyp,i; | 	int rvtyp,i; | ||||||
|  |  | ||||||
|  | @ -21,3 +21,19 @@ struct regassigned { | ||||||
| extern struct regvar *rvlist; | extern struct regvar *rvlist; | ||||||
| extern int nregvar[]; | extern int nregvar[]; | ||||||
| extern struct regassigned *regassigned[]; | 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$"; | static char rcsid[] = "$Id$"; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #include <stdlib.h> | #include <stdarg.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  | #include <stdlib.h> | ||||||
| #include "assert.h" | #include "assert.h" | ||||||
| #include "param.h" | #include "param.h" | ||||||
| #include "tables.h" | #include "tables.h" | ||||||
|  | @ -12,6 +13,9 @@ static char rcsid[] = "$Id$"; | ||||||
| #include "data.h" | #include "data.h" | ||||||
| #include "result.h" | #include "result.h" | ||||||
| #include "extern.h" | #include "extern.h" | ||||||
|  | #ifdef REGVARS | ||||||
|  | #include "regvar.h" | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. |  * (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: | 	case IN_D_DESCR: | ||||||
| 		compute(&enodes[inp->in_info[1]], &result); | 		compute(&enodes[inp->in_info[1]], &result); | ||||||
| 		assert(result.e_typ==EV_INT); | 		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_token = -1; | ||||||
| 			token->t_att[0].ar = regno; | 			token->t_att[0].ar = regno; | ||||||
| 			for (i=TOKENSIZE-1;i>0;i--) | 			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); | 			compute(&enodes[inp->in_info[1]], &result); | ||||||
| 			curtoken = ct; | 			curtoken = ct; | ||||||
| 			assert(result.e_typ==EV_INT); | 			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_token = -1; | ||||||
| 				token->t_att[0].ar = regno; | 				token->t_att[0].ar = regno; | ||||||
| 				for (i=TOKENSIZE-1;i>0;i--) | 				for (i=TOKENSIZE-1;i>0;i--) | ||||||
|  | @ -657,11 +665,12 @@ itokcost() { | ||||||
| 		tdp->t_cost.ct_space = costcalc(tdp->t_cost); | 		tdp->t_cost.ct_space = costcalc(tdp->t_cost); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*VARARGS1*/ | void error(const char *s, ...) { | ||||||
| error(s,a1,a2,a3,a4,a5,a6,a7,a8) char *s; { | 	va_list ap; | ||||||
| 
 | 
 | ||||||
|  | 	va_start(ap,s); | ||||||
| 	fprintf(stderr,"Error: "); | 	fprintf(stderr,"Error: "); | ||||||
| 	fprintf(stderr,s,a1,a2,a3,a4,a5,a6,a7,a8); | 	vfprintf(stderr,s,ap); | ||||||
| 	fprintf(stderr,"\n"); | 	fprintf(stderr,"\n"); | ||||||
| #ifdef TABLEDEBUG | #ifdef TABLEDEBUG | ||||||
| 	ruletrace(); | 	ruletrace(); | ||||||
|  | @ -670,11 +679,12 @@ error(s,a1,a2,a3,a4,a5,a6,a7,a8) char *s; { | ||||||
| 	exit(-1); | 	exit(-1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*VARARGS1*/ | void fatal(const char *s, ...) { | ||||||
| fatal(s,a1,a2,a3,a4,a5,a6,a7,a8) char *s; { | 	va_list ap; | ||||||
| 
 | 
 | ||||||
|  | 	va_start(ap,s); | ||||||
| 	fprintf(stderr,"Fatal: "); | 	fprintf(stderr,"Fatal: "); | ||||||
| 	fprintf(stderr,s,a1,a2,a3,a4,a5,a6,a7,a8); | 	vfprintf(stderr,s,ap); | ||||||
| 	fprintf(stderr,"\n"); | 	fprintf(stderr,"\n"); | ||||||
| #ifdef TABLEDEBUG | #ifdef TABLEDEBUG | ||||||
| 	ruletrace(); | 	ruletrace(); | ||||||
|  |  | ||||||
|  | @ -19,11 +19,8 @@ var PLATFORM=linuxppc | ||||||
| var PLATFORMDIR={EM}/share/ack/{PLATFORM} | var PLATFORMDIR={EM}/share/ack/{PLATFORM} | ||||||
| var CPP_F=-D__unix | var CPP_F=-D__unix | ||||||
| var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x10000054 | var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x10000054 | ||||||
| var C_LIB={PLATFORMDIR}/libc-ansi.a | var MACHOPT_F=-m3 | ||||||
| # bitfields reversed for compatibility with (g)cc. | var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr | ||||||
| var CC_ALIGN=-Vr |  | ||||||
| var OLD_C_LIB={C_LIB} |  | ||||||
| var MACHOPT_F= |  | ||||||
| 
 | 
 | ||||||
| # Override the setting in fe so that files compiled for linuxppc can see | # Override the setting in fe so that files compiled for linuxppc can see | ||||||
| # the platform-specific headers. | # the platform-specific headers. | ||||||
|  |  | ||||||
|  | @ -140,7 +140,7 @@ showrelo() | ||||||
| 	case RELOPPC: | 	case RELOPPC: | ||||||
| 		printf("\tPowerPC 26-bit address\n"); | 		printf("\tPowerPC 26-bit address\n"); | ||||||
| 		break; | 		break; | ||||||
| 	case RELOLIS: | 	case RELOPPC_LIS: | ||||||
| 		printf("\tPowerPC lis instruction\n"); | 		printf("\tPowerPC lis instruction\n"); | ||||||
| 		break; | 		break; | ||||||
| 	case RELOVC4: | 	case RELOVC4: | ||||||
|  |  | ||||||
|  | @ -3,26 +3,32 @@ pointersize: 4 | ||||||
| %%RA | %%RA | ||||||
| general registers: 19 | general registers: 19 | ||||||
| address registers: 0 | address registers: 0 | ||||||
| floating point registers: 0 | floating point registers: 18 | ||||||
| use general as pointer: yes | use general as pointer: yes | ||||||
| 
 | 
 | ||||||
| register score parameters: | register score parameters: | ||||||
| 	local variable: | 	local variable: | ||||||
| 		(2 cases) | 		(3 cases) | ||||||
| 		pointer,general | 		pointer,general | ||||||
| 			(1 size) | 			(1 size) | ||||||
| 			default ->	(3,4) | 			default ->	(3,4) | ||||||
| 		general,general | 		general,general | ||||||
| 			(1 size) | 			(1 size) | ||||||
| 			default ->	(3,4) | 			default ->	(3,4) | ||||||
|  | 		float,float | ||||||
|  | 			(1 size) | ||||||
|  | 			default ->	(5,4) | ||||||
| 	address of local variable: | 	address of local variable: | ||||||
| 		(2 cases) | 		(3 cases) | ||||||
| 		pointer,general | 		pointer,general | ||||||
| 			(1 size) | 			(1 size) | ||||||
| 			default ->	(0,0) | 			default ->	(0,0) | ||||||
| 		general,general | 		general,general | ||||||
| 			(1 size) | 			(1 size) | ||||||
| 			default ->	(0,0) | 			default ->	(0,0) | ||||||
|  | 		float,float | ||||||
|  | 			(1 size) | ||||||
|  | 			default ->	(0,0) | ||||||
| 	constant: | 	constant: | ||||||
| 		(2 sizes) | 		(2 sizes) | ||||||
| 		fitbyte ->	(-1,-1) | 		fitbyte ->	(-1,-1) | ||||||
|  | @ -39,21 +45,27 @@ register score parameters: | ||||||
| 
 | 
 | ||||||
| opening cost parameters: | opening cost parameters: | ||||||
| 	local variable: | 	local variable: | ||||||
| 		(2 cases) | 		(3 cases) | ||||||
| 		pointer | 		pointer | ||||||
| 			(1 size) | 			(1 size) | ||||||
| 			default ->	(3,4) | 			default ->	(3,4) | ||||||
| 		general | 		general | ||||||
| 			(1 size) | 			(1 size) | ||||||
| 			default ->	(3,4) | 			default ->	(3,4) | ||||||
|  | 		float | ||||||
|  | 			(1 size) | ||||||
|  | 			default ->	(5,4) | ||||||
| 	address of local variable: | 	address of local variable: | ||||||
| 		(2 cases) | 		(3 cases) | ||||||
| 		pointer | 		pointer | ||||||
| 			(1 size) | 			(1 size) | ||||||
| 			default ->	(1,4) | 			default ->	(1,4) | ||||||
| 		general | 		general | ||||||
| 			(1 size) | 			(1 size) | ||||||
| 			general ->	(1,4) | 			default ->	(1,4) | ||||||
|  | 		float | ||||||
|  | 			(1 size) | ||||||
|  | 			default ->	(1,4) | ||||||
| 	constant: | 	constant: | ||||||
| 		(2 sizes) | 		(2 sizes) | ||||||
| 		fitbyte ->	(1000,1000) | 		fitbyte ->	(1000,1000) | ||||||
|  | @ -69,7 +81,7 @@ opening cost parameters: | ||||||
| 		default ->	(1000,1000) | 		default ->	(1000,1000) | ||||||
| 
 | 
 | ||||||
| register save costs: | register save costs: | ||||||
| 	(21 cases) | 	(39 cases) | ||||||
| 	0 -> (0,0) | 	0 -> (0,0) | ||||||
| 	1 -> (6,8) | 	1 -> (6,8) | ||||||
| 	2 -> (12,16) | 	2 -> (12,16) | ||||||
|  | @ -90,6 +102,24 @@ register save costs: | ||||||
| 	17 -> (102,136) | 	17 -> (102,136) | ||||||
| 	18 -> (108,144) | 	18 -> (108,144) | ||||||
| 	19 -> (114,152) | 	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) | 	0 -> (0,0) | ||||||
| %%UD | %%UD | ||||||
| access costs of global variables: | 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; | 	cond_p m = (cond_p) 0; | ||||||
| 
 | 
 | ||||||
| 	if (localtyp == reg_loop) localtyp = reg_any; | 	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) { | 		switch(itemtyp) { | ||||||
| 		   case LOCALVAR: | 		   case LOCALVAR: | ||||||
| 			m = alocaltab[localtyp][totyp]; | 			m = alocaltab[localtyp][totyp]; | ||||||
|  |  | ||||||
|  | @ -162,12 +162,13 @@ struct outrelo { | ||||||
|  * relocation type bits |  * relocation type bits | ||||||
|  */ |  */ | ||||||
| #define RELSZ   0x0fff          /* relocation length */ | #define RELSZ   0x0fff          /* relocation length */ | ||||||
| #define RELO1	0x01		/* 1 byte */ | #define RELO1        1          /* 1 byte */ | ||||||
| #define RELO2	0x02		/* 2 bytes */ | #define RELO2        2          /* 2 bytes */ | ||||||
| #define RELO4	0x03		/* 4 bytes */ | #define RELO4        3          /* 4 bytes */ | ||||||
| #define RELOPPC	0x04		/* 26-bit PowerPC address */ | #define RELOPPC      4          /* PowerPC 26-bit address */ | ||||||
| #define RELOLIS	0x05		/* PowerPC lis */ | #define RELOPPC_LIS  5          /* PowerPC lis */ | ||||||
| #define RELOVC4	0x06 /* VideoCore IV address in 32-bit insruction */ | #define RELOVC4      6  /* VideoCore IV address in 32-bit instruction */ | ||||||
|  | 
 | ||||||
| #define RELPC	0x2000		/* pc relative */ | #define RELPC	0x2000		/* pc relative */ | ||||||
| #define RELBR	0x4000		/* High order byte lowest address. */ | #define RELBR	0x4000		/* High order byte lowest address. */ | ||||||
| #define RELWR	0x8000		/* High order word 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 | The relocation depends on the instruction, and uses an offset encoded | ||||||
| in the instruction. | in the instruction. | ||||||
| .PP | .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 relocatable datum is a 4-byte integer. | ||||||
| The high bit is set for ha16 or clear for hi16. | The high bit is set for ha16 or clear for hi16. | ||||||
| The next 5 bits are the register \fIRT\fR. | 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); | 		(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) | static uint32_t get_lis_valu(char *addr, uint16_t type) | ||||||
| { | { | ||||||
| 	uint32_t valu = read4(addr, type) & 0x03ffffff; | 	uint32_t valu = read4(addr, type) & 0x03ffffff; | ||||||
|  | @ -193,7 +193,7 @@ static uint32_t getvalu(char* addr, uint16_t type) | ||||||
| 		return read4(addr, type); | 		return read4(addr, type); | ||||||
| 	case RELOPPC: | 	case RELOPPC: | ||||||
| 		return get_powerpc_valu(addr, type); | 		return get_powerpc_valu(addr, type); | ||||||
| 	case RELOLIS: | 	case RELOPPC_LIS: | ||||||
| 		return get_lis_valu(addr, type); | 		return get_lis_valu(addr, type); | ||||||
| 	case RELOVC4: | 	case RELOVC4: | ||||||
| 		return get_vc4_valu(addr); | 		return get_vc4_valu(addr); | ||||||
|  | @ -389,7 +389,7 @@ static putvalu(uint32_t valu, char* addr, uint16_t type) | ||||||
| 	case RELOPPC: | 	case RELOPPC: | ||||||
| 		put_powerpc_valu(addr, valu, type); | 		put_powerpc_valu(addr, valu, type); | ||||||
| 		break; | 		break; | ||||||
| 	case RELOLIS: | 	case RELOPPC_LIS: | ||||||
| 		put_lis_valu(addr, valu, type); | 		put_lis_valu(addr, valu, type); | ||||||
| 		break; | 		break; | ||||||
| 	case RELOVC4: | 	case RELOVC4: | ||||||
|  |  | ||||||
|  | @ -78,7 +78,8 @@ iocc_t iops[20]; | ||||||
| %token PATTERNS PAT WITH EXACT KILLS USES REUSING GEN YIELDS LEAVING | %token PATTERNS PAT WITH EXACT KILLS USES REUSING GEN YIELDS LEAVING | ||||||
| %token DEFINED SAMESIGN SFIT UFIT ROM LOWW HIGHW ISROM | %token DEFINED SAMESIGN SFIT UFIT ROM LOWW HIGHW ISROM | ||||||
| %token CMPEQ CMPNE CMPLT CMPGT CMPLE CMPGE OR2 AND2 LSHIFT RSHIFT NOT COMP | %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> ADORNACCESS | ||||||
| %token <yy_int> ADORNCC | %token <yy_int> ADORNCC | ||||||
| %token INT | %token INT | ||||||
|  | @ -129,6 +130,7 @@ machtable | ||||||
| 	: constants | 	: constants | ||||||
| 	  properties | 	  properties | ||||||
| 	  registers | 	  registers | ||||||
|  | 		{ check_reglap(); } | ||||||
| 	  tokens | 	  tokens | ||||||
| 		{ make_std_sets(); } | 		{ make_std_sets(); } | ||||||
| 	  sets | 	  sets | ||||||
|  | @ -1086,7 +1088,11 @@ expr | ||||||
| 
 | 
 | ||||||
| regvarexpr | regvarexpr | ||||||
| 	: REGVAR '(' expr optregvartype ')' | 	: 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 | optregvartype | ||||||
|  |  | ||||||
|  | @ -18,6 +18,7 @@ static char rcsid[]= "$Id$"; | ||||||
| #include "expr.h" | #include "expr.h" | ||||||
| #include "regvar.h" | #include "regvar.h" | ||||||
| #include <cgg_cg.h> | #include <cgg_cg.h> | ||||||
|  | #include <em_reg.h> | ||||||
| #include "extern.h" | #include "extern.h" | ||||||
| 
 | 
 | ||||||
| extern set_t l_sets[]; | extern set_t l_sets[]; | ||||||
|  | @ -273,15 +274,38 @@ expr_t iextoaddr(e) expr_t e; { | ||||||
| 	return(result); | 	return(result); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| expr_t regvar_expr(e,regtyp) expr_t e; { | expr_t regvar_expr(e,regtyp,regsiz) expr_t e; { | ||||||
| 	expr_t result; | 	expr_t result; | ||||||
| 	register i; | 	int i, regno, s, two_sizes; | ||||||
| 
 | 
 | ||||||
| 	result = make_expr(TYPREG,EX_REGVAR,i_expr(e),0); | 	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++) | 	for(i=0;i<SZOFSET(MAXREGS);i++) | ||||||
| 		result.ex_regset[i]=0; | 		result.ex_regset[i]=0; | ||||||
|  | 
 | ||||||
|  | 	/* 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++) | 		for(i=0;i<nregvar[regtyp];i++) | ||||||
| 			BIS(result.ex_regset,rvnumbers[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); | 	return(result); | ||||||
| } | } | ||||||
| 		 | 		 | ||||||
|  |  | ||||||
|  | @ -175,7 +175,11 @@ found: | ||||||
| 		case IN_D_DESCR: | 		case IN_D_DESCR: | ||||||
| 			{ int temp; | 			{ 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_next = generase(temp); | ||||||
| 			vi = vi->vi_next; | 			vi = vi->vi_next; | ||||||
| 			vi->vi_next = genremove(temp); | 			vi->vi_next = genremove(temp); | ||||||
|  |  | ||||||
|  | @ -38,6 +38,8 @@ reg_float	REG_FLOAT | ||||||
| reg_loop	REG_LOOP | reg_loop	REG_LOOP | ||||||
| reg_pointer	REG_POINTER | reg_pointer	REG_POINTER | ||||||
| regvar	REGVAR | regvar	REGVAR | ||||||
|  | regvar_d	REGVAR_D | ||||||
|  | regvar_w	REGVAR_W | ||||||
| return	RETURN | return	RETURN | ||||||
| reusing	REUSING | reusing	REUSING | ||||||
| rom	ROM | rom	ROM | ||||||
|  |  | ||||||
|  | @ -317,7 +317,15 @@ outregs() { | ||||||
| 			} | 			} | ||||||
| 			clashlist[iclashlist++] = 0; | 			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"); | ||||||
| 	} | 	} | ||||||
| 	fprintf(ctable,"};\n\n short clashlist[] = {\n\t"); | 	fprintf(ctable,"};\n\n short clashlist[] = {\n\t"); | ||||||
|  | @ -332,6 +340,8 @@ outregvars() { | ||||||
| 	register i,j; | 	register i,j; | ||||||
| 
 | 
 | ||||||
| 	fprintf(htable,"#define REGVARS\n"); | 	fprintf(htable,"#define REGVARS\n"); | ||||||
|  | 	if (reglap!=0) | ||||||
|  | 		fprintf(htable,"#define REGLAP\n"); | ||||||
| 	fprintf(ctable,"#include \"regvar.h\"\n"); | 	fprintf(ctable,"#include \"regvar.h\"\n"); | ||||||
| 	fprintf(ctable,"int nregvar[4] = { "); | 	fprintf(ctable,"int nregvar[4] = { "); | ||||||
| 	for (i=0;i<4;i++) { | 	for (i=0;i<4;i++) { | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
| #define DL_REGVAR	0x4 | #define DL_REGVAR	0x4 | ||||||
| 
 | 
 | ||||||
| extern int rvused; | extern int rvused; | ||||||
|  | extern int reglap; | ||||||
| extern int nregvar[4]; | extern int nregvar[4]; | ||||||
| extern int rvsize[4]; | extern int rvsize[4]; | ||||||
| extern int rvnumbers[4][MAXREGVAR]; | 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 "token.h" | ||||||
| #include "regvar.h" | #include "regvar.h" | ||||||
| #include <cgg_cg.h> | #include <cgg_cg.h> | ||||||
|  | #include <em_reg.h> | ||||||
| #include "extern.h" | #include "extern.h" | ||||||
| 
 | 
 | ||||||
| n_proc(name) char *name; { | n_proc(name) char *name; { | ||||||
|  | @ -228,6 +229,72 @@ n_sconst(ident,val) char *ident,*val; { | ||||||
| 	sy_p->sy_value.syv_stringno = strlookup(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; { | regline(rl,pl,rv) varinfo *rl,*pl; { | ||||||
| 	register varinfo *rrl,*rpl; | 	register varinfo *rrl,*rpl; | ||||||
| 	register short *sp; | 	register short *sp; | ||||||
|  | @ -251,25 +318,29 @@ regline(rl,pl,rv) varinfo *rl,*pl; { | ||||||
| 		regp->ri_size = thissize; | 		regp->ri_size = thissize; | ||||||
| 		regp->ri_class = regclass; | 		regp->ri_class = regclass; | ||||||
| 		regp->ri_rregvar = rv; | 		regp->ri_rregvar = rv; | ||||||
| 		if (rv>=0) { | 		if (rv>=0) | ||||||
| 			if (regp->ri_memb[0]!=0) | 			add_regvar(rrl->vi_int[0], regp, rv); | ||||||
| 				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]; |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 	regclass++; | 	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; { | setallreg(vi) struct varinfo *vi; { | ||||||
| 
 | 
 | ||||||
| 	nallreg=0; | 	nallreg=0; | ||||||
|  |  | ||||||
|  | @ -39,6 +39,7 @@ int maxmembers=0; | ||||||
| int regclass=1; | int regclass=1; | ||||||
| int maxtokensize=0; | int maxtokensize=0; | ||||||
| int rvused=0; | int rvused=0; | ||||||
|  | int reglap=0; | ||||||
| int nregvar[4]; | int nregvar[4]; | ||||||
| int rvsize[4]; | int rvsize[4]; | ||||||
| int rvnumbers[4][MAXREGVAR]; | int rvnumbers[4][MAXREGVAR]; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue