Merge pull request #59 from kernigh/kernigh-ppc-regs

PowerPC ncg: register allocation, floats, lxl
This commit is contained in:
David Given 2017-10-26 15:15:55 +01:00 committed by GitHub
commit 66147529d9
43 changed files with 1171 additions and 969 deletions

14
h/out.h
View file

@ -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. */

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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 = {

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
View 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

View file

@ -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

View file

@ -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

View file

@ -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
View 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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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, ...);

View file

@ -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");

View file

@ -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;

View file

@ -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

View file

@ -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();

View file

@ -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.

View file

@ -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:

View file

@ -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:

View file

@ -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];

View file

@ -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.

View file

@ -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:

View file

@ -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

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -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++) {

View file

@ -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];

View file

@ -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;

View file

@ -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];