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 * relocation type bits
*/ */
#define RELSZ 0x0fff /* relocation length */ #define RELSZ 0x0fff /* relocation length */
#define RELO1 1 /* 1 byte */ #define RELO1 1 /* 1 byte */
#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 */
#define RELBR 0x4000 /* High order byte lowest address. */ #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] */ 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;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

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

View file

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

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) 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;
case 'r':
savedi[regnum] = offset;
framesize += 4;
break;
}
} }
/* Finish saving ragisters. */ static void
saveloadregs(const char* ops, const char* opm, const char *opf)
void saveloadregs(const char* ops, const char* opm)
{ {
int offset = -(framesize + numsaved*4); long offset = savedtop;
int reg = 32; int reg;
/* Check for the possibility of a multiple. */ /* Do floating-point registers. */
for (reg = 31; reg >= 0; reg--) {
do if (savedf[reg] != LONG_MIN) {
{ offset -= 8;
reg--; fprintf(codefile, "%s f%d, %ld(fp)\n",
} opf, reg, offset);
while ((reg > 0) && (savedregsi[reg] != INT_MAX)); }
if (reg < 31) }
{
fprintf(codefile, "%s r%d, %d(fp)\n", opm, reg+1, offset); if (savedi[31] != LONG_MIN && savedi[30] != LONG_MIN) {
offset += (31-reg)*4; /*
} * Do multiple registers from reg to r31.
*
/* Saved everything else singly. */ * Using stmw or lmw reduces code size, but in some
* processors, runs slower than the equivalent pile of
while (reg > 0) * stw or lwz instructions.
{ */
if (savedregsi[reg] != INT_MAX) reg = 30;
{ while (reg > 0 && savedi[reg - 1] != LONG_MIN)
fprintf(codefile, "%s r%d, %d(fp)\n", ops, reg, offset); reg--;
offset += 4; 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; int reg;
fprintf(codefile, "! f_regsave()\n");
fprintf(codefile, "addi sp, sp, %d\n", -numsaved*4);
saveloadregs("stw", "stmw"); emit_prolog();
saveloadregs("stw", "stmw", "stfd");
for (i=0; i<32; i++) /*
if ((savedregsi[i] != INT_MAX) && (savedregsi[i] > 0)) * Register variables with offset >= 0 must load an argument
fprintf(codefile, "lwz r%d, %d(fp)\n", i, savedregsi[i]); * 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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -161,13 +161,14 @@ 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.

View file

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

View file

@ -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,8 +130,9 @@ machtable
: constants : constants
properties properties
registers registers
{ check_reglap(); }
tokens tokens
{ make_std_sets(); } { make_std_sets(); }
sets sets
instructions instructions
moves moves
@ -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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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