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