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