Add test for EM _rck_. Fix traps in PowerPC ncg.
The new test rck_e.e segfaults on PowerPC unless I make some changes. The inline code for _rck_ was wrong because it didn't allow the trap handler to return. _sig_ forgot to push the old trap handler. Move plat/linuxppc/libsys/trap.s to mach/powerpc/libem/trp.s and rewrite it with simplified/extended mnemonics. Remove .trap alias for .trp procedure. Add a missing `mtspr lr, r0` so we can return from the trap handler. Call write() and _exit() so trp.s works with both linuxppc and osxppc. Before, Mac OS X was wrongly using the trap.s for Linux. In powerpc/libem, simplify .aar4; teach .csa and .csb to raise the trap if the default target is zero. C programs don't need these changes. You may relink your C programs with the changed .csa and .csb, but C code doesn't raise the trap. Modula-2 code can raise traps, so you may want to relink your Modula-2 programs with the changed libem, but you might keep your old .o files from Modula-2. You may need to recompile your Pascal programs (delete old .o files from Pascal) because the Pascal compiler might use _rck_.
This commit is contained in:
parent
5f2a7b260f
commit
26de4c1ab1
|
@ -8,21 +8,17 @@
|
|||
|
||||
.define .aar4
|
||||
.aar4:
|
||||
lis r0, hi16[.trap_earray]
|
||||
ori r0, r0, lo16[.trap_earray]
|
||||
mtspr ctr, r0 ! load CTR with trap address
|
||||
|
||||
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
|
||||
blt .trap_earray ! check lower bound
|
||||
|
||||
lwz r0, 4(r4)
|
||||
cmplw r5, r0
|
||||
bgtctr ! check upper bound
|
||||
bgt .trap_earray ! check upper bound
|
||||
|
||||
lwz r3, 8(r4) ! r3 = size of element
|
||||
mullw r5, r5, r3 ! scale index by size
|
||||
|
@ -30,3 +26,7 @@
|
|||
stw r6, 8(sp) ! push address of element
|
||||
addi sp, sp, 8
|
||||
blr
|
||||
|
||||
.trap_earray:
|
||||
li r3, 0 ! EARRAY = 0 in h/em_abs.h
|
||||
b .trp
|
||||
|
|
|
@ -6,7 +6,7 @@ for _, plat in ipairs(vars.plats) do
|
|||
acklibrary {
|
||||
name = "lib_"..plat,
|
||||
srcs = {
|
||||
"./*.s", -- exg.s
|
||||
"./*.s", -- trp.s
|
||||
},
|
||||
vars = { plat = plat },
|
||||
deps = {
|
||||
|
@ -15,4 +15,3 @@ for _, plat in ipairs(vars.plats) do
|
|||
}
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -13,22 +13,21 @@
|
|||
lwz r4, 4(sp)
|
||||
addi sp, sp, 8
|
||||
|
||||
lwz r5, 0(r3) ! load default
|
||||
mtspr ctr, r5
|
||||
lwz r5, 0(r3) ! r5 = default target
|
||||
|
||||
lwz r5, 4(r3) ! fetch lower bound
|
||||
subf. r4, r5, r4 ! adjust value
|
||||
bltctr ! jump to default if out of range
|
||||
lwz r6, 4(r3) ! fetch lower bound
|
||||
subf. r4, r6, r4 ! adjust value
|
||||
blt 1f ! jump to default if out of range
|
||||
|
||||
lwz r5, 8(r3) ! fetch range
|
||||
cmplw r4, r5
|
||||
bgtctr ! jump to default if out of range
|
||||
lwz r6, 8(r3) ! fetch range
|
||||
cmplw r4, r6
|
||||
bgt 1f ! jump to default if out of range
|
||||
|
||||
addi r3, r3, 12 ! skip header
|
||||
slwi r4, r4, 2 ! scale value (<<2)
|
||||
lwzx r5, r3, r4 ! load target
|
||||
mtspr ctr, r5
|
||||
lwzx r5, r3, r4 ! r5 = new target
|
||||
|
||||
or. r5, r5, r5 ! test it
|
||||
1: mtspr ctr, r5
|
||||
mr. r5, r5 ! test it
|
||||
bnectr ! jump to target if non-zero
|
||||
b .trap_ecase ! otherwise trap
|
||||
|
|
|
@ -13,23 +13,20 @@
|
|||
lwz r4, 4(sp)
|
||||
addi sp, sp, 8
|
||||
|
||||
lwz r5, 0(r3) ! load default
|
||||
mtspr ctr, r5
|
||||
lwz r5, 0(r3) ! r5 = default target
|
||||
|
||||
lwz r6, 4(r3) ! fetch count
|
||||
|
||||
1:
|
||||
or. r6, r6, r6 ! test count
|
||||
beqctr ! exit if zero
|
||||
addi r6, r6, -1 ! otherwise decrement
|
||||
|
||||
lwzu r7, 8(r3) ! fetch target index, increment pointer
|
||||
mr. r6, r6 ! skip loop if count is zero
|
||||
beq 3f ! (needed by Modula-2 "CASE i OF END")
|
||||
mtspr ctr, r6
|
||||
1: lwzu r7, 8(r3) ! fetch target index, increment pointer
|
||||
cmpw r4, r7 ! compare with value
|
||||
bne 1b ! if not equal, go again
|
||||
beq 2f
|
||||
bdnz 1b ! if not equal, go again
|
||||
b 3f
|
||||
|
||||
lwz r7, 4(r3) ! fetch target address
|
||||
mtspr ctr, r7
|
||||
|
||||
or. r7, r7, r7 ! test it
|
||||
2: lwz r5, 4(r3) ! r5 = new target
|
||||
3: mtspr ctr, r5
|
||||
mr. r5, r5 ! test target
|
||||
bnectr ! jump to target if non-zero
|
||||
b .trap_ecase ! otherwise trap
|
||||
|
|
|
@ -18,3 +18,7 @@
|
|||
bgt .trap_erange
|
||||
|
||||
blr
|
||||
|
||||
.trap_erange:
|
||||
li r3, 1 ! ERANGE = 1 in h/em_abs.h
|
||||
b .trp
|
||||
|
|
56
mach/powerpc/libem/trp.s
Normal file
56
mach/powerpc/libem/trp.s
Normal file
|
@ -0,0 +1,56 @@
|
|||
.sect .text
|
||||
|
||||
.define .trap_ecase
|
||||
.trap_ecase:
|
||||
li r3, 20 ! ECASE = 20 in h/em_abs.h
|
||||
! FALLTHROUGH to .trp
|
||||
|
||||
! Raises an EM trap.
|
||||
! Expects r3 = trap number.
|
||||
|
||||
.define .trp
|
||||
.trp:
|
||||
cmplwi r3, 15 ! traps > 15 can't be ignored
|
||||
bgt 1f
|
||||
|
||||
lis r4, ha16[.ignmask]
|
||||
lwz r4, lo16[.ignmask](r4) ! load ignore mask
|
||||
srw r4, r4, r3
|
||||
andi. r4, r4, 1
|
||||
bnelr ! return if ignoring trap
|
||||
|
||||
1: lis r4, ha16[.trppc]
|
||||
lwz r5, lo16[.trppc](r4) ! r5 = user trap routine
|
||||
mr. r5, r5
|
||||
beq 2f ! if no user trap routine, bail out
|
||||
|
||||
mtspr ctr, r5
|
||||
mfspr r6, lr
|
||||
li r0, 0
|
||||
stwu r3, -8(sp) ! push trap number
|
||||
stw r0, lo16[.trppc](r4) ! reset trap routine
|
||||
stw r6, 4(sp) ! save old lr
|
||||
bctrl ! call trap routine
|
||||
|
||||
lwz r0, 4(sp)
|
||||
mtspr lr, r0
|
||||
addi sp, sp, 8 ! retract over stack usage
|
||||
blr
|
||||
|
||||
2: ! No trap handler. Write error message, exit.
|
||||
li r3, 2
|
||||
stwu r3, -12(sp)
|
||||
lis r4, ha16[message]
|
||||
addi r4, r4, lo16[message]
|
||||
li r5, 6
|
||||
stw r4, 4(sp)
|
||||
stw r5, 8(sp)
|
||||
bl _write ! write(2, message, 6)
|
||||
|
||||
li r3, 1
|
||||
stw r3, 0(sp)
|
||||
bl __exit ! _exit(1)
|
||||
|
||||
.sect .rom
|
||||
message:
|
||||
.ascii "TRAP!\n"
|
|
@ -2168,10 +2168,13 @@ PATTERNS
|
|||
pat trp /* Raise EM trap */
|
||||
with REG3
|
||||
kills ALL
|
||||
gen bl {LABEL, ".trap"}
|
||||
gen bl {LABEL, ".trp"}
|
||||
|
||||
pat sig /* Set trap handler */
|
||||
leaving ste ".trppc"
|
||||
pat sig /* Set trap handler, yield old */
|
||||
leaving
|
||||
loe ".trppc"
|
||||
exg 4
|
||||
ste ".trppc"
|
||||
|
||||
pat rtt /* Return from trap */
|
||||
leaving ret 0
|
||||
|
@ -2216,22 +2219,14 @@ PATTERNS
|
|||
with REG
|
||||
gen move %1, sp
|
||||
|
||||
pat lae rck $2==4 /* Range check */
|
||||
with REG
|
||||
kills ALL
|
||||
gen
|
||||
cmpwi %1, {C, rom($1, 1)}
|
||||
blt {LABEL, ".trap_erange"}
|
||||
cmpwi %1, {C, rom($1, 2)}
|
||||
bgt {LABEL, ".trap_erange"}
|
||||
yields %1
|
||||
pat rck $1==4 /* Range check */
|
||||
leaving cal ".rck"
|
||||
|
||||
|
||||
/* Single-precision floating-point */
|
||||
|
||||
pat zrf $1==4 /* Push zero */
|
||||
leaving
|
||||
loe ".fs_00000000"
|
||||
leaving loe ".fs_00000000"
|
||||
|
||||
pat adf $1==4 /* Add single */
|
||||
with FSREG FSREG
|
||||
|
|
|
@ -4,7 +4,6 @@ acklibrary {
|
|||
"./_syscall.s",
|
||||
"./sigaction.s",
|
||||
"./signal.c",
|
||||
"./trap.s",
|
||||
"plat/linux/libsys/_exit.c",
|
||||
"plat/linux/libsys/_hol0.s",
|
||||
"plat/linux/libsys/close.c",
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
#
|
||||
! $Source: /cvsroot/tack/Ack/plat/linux386/libsys/_syscall.s,v $
|
||||
! $State: Exp $
|
||||
! $Revision: 1.1 $
|
||||
|
||||
! Declare segments (the order is important).
|
||||
|
||||
.sect .text
|
||||
.sect .rom
|
||||
.sect .data
|
||||
.sect .bss
|
||||
|
||||
.sect .text
|
||||
|
||||
#define IFFALSE 4
|
||||
#define IFTRUE 12
|
||||
#define ALWAYS 20
|
||||
|
||||
#define LT 0
|
||||
#define GT 1
|
||||
#define EQ 2
|
||||
#define OV 3
|
||||
|
||||
EARRAY = 0
|
||||
ERANGE = 1
|
||||
ESET = 2
|
||||
EIOVFL = 3
|
||||
EFOVFL = 4
|
||||
EFUNFL = 5
|
||||
EIDIVZ = 6
|
||||
EFDIVZ = 7
|
||||
EIUND = 8
|
||||
EFUND = 9
|
||||
ECONV = 10
|
||||
ESTACK = 16
|
||||
EHEAP = 17
|
||||
EILLINS = 18
|
||||
EODDZ = 19
|
||||
ECASE = 20
|
||||
EMEMFLT = 21
|
||||
EBADPTR = 22
|
||||
EBADPC = 23
|
||||
EBADLAE = 24
|
||||
EBADMON = 25
|
||||
EBADLIN = 26
|
||||
EBADGTO = 27
|
||||
EUNIMPL = 63 ! unimplemented em-instruction called
|
||||
|
||||
! EM trap handling.
|
||||
|
||||
.define .trap_ecase
|
||||
.trap_ecase:
|
||||
addi r3, r0, ECASE
|
||||
b .trap
|
||||
|
||||
.define .trap_earray
|
||||
.trap_earray:
|
||||
addi r3, r0, EARRAY
|
||||
b .trap
|
||||
|
||||
.define .trap_erange
|
||||
.trap_erange:
|
||||
addi r3, r0, ERANGE
|
||||
b .trap
|
||||
|
||||
.define .trp
|
||||
.define .trap
|
||||
.trp:
|
||||
.trap:
|
||||
cmpi cr0, 0, r3, 15 ! traps >15 can't be ignored
|
||||
bc IFTRUE, LT, 1f
|
||||
|
||||
addi r4, r0, 1
|
||||
rlwnm r4, r4, r3, 0, 31 ! calculate trap bit
|
||||
li32 r5, .ignmask
|
||||
lwz r5, 0(r5) ! load ignore mask
|
||||
and. r4, r4, r5 ! compare
|
||||
bclr IFFALSE, EQ, 0 ! return if non-zero
|
||||
|
||||
1:
|
||||
li32 r4, .trppc
|
||||
lwz r5, 0(r4) ! load user trap routine
|
||||
or. r5, r5, r5 ! test
|
||||
bc IFTRUE, EQ, fatal ! if no user trap routine, bail out
|
||||
|
||||
addi r0, r0, 0
|
||||
stw r0, 0(r4) ! reset trap routine
|
||||
|
||||
mfspr r0, lr
|
||||
stwu r0, -4(sp) ! save old lr
|
||||
|
||||
stwu r3, -4(sp)
|
||||
mtspr ctr, r5
|
||||
bcctrl ALWAYS, 0, 0 ! call trap routine
|
||||
|
||||
lwz r0, 4(sp) ! load old lr again
|
||||
addi sp, sp, 8 ! retract over stack usage
|
||||
bclr ALWAYS, 0, 0 ! return
|
||||
|
||||
fatal:
|
||||
addi r3, r0, 1
|
||||
li32 r4, message
|
||||
addi r5, r0, 6
|
||||
addi r0, r0, 4 ! write()
|
||||
sc 0
|
||||
|
||||
addi r0, r0, 1 ! exit()
|
||||
sc 0
|
||||
|
||||
.sect .rom
|
||||
message:
|
||||
.ascii "TRAP!\n"
|
|
@ -19,7 +19,6 @@ acklibrary {
|
|||
"./sigaction.s",
|
||||
"./stat.s",
|
||||
"./write.s",
|
||||
"plat/linuxppc/libsys/trap.s",
|
||||
"plat/osx/libsys/brk.c",
|
||||
"plat/osx/libsys/creat.c",
|
||||
"plat/osx/libsys/isatty.c",
|
||||
|
|
|
@ -13,6 +13,7 @@ definerule("plat_testsuite",
|
|||
"tests/plat/dup_e.e",
|
||||
"tests/plat/exg_e.e",
|
||||
"tests/plat/inn_e.e",
|
||||
"tests/plat/rck_e.e",
|
||||
"tests/plat/rotate_e.e",
|
||||
"tests/plat/*.p",
|
||||
"tests/plat/b/*.b",
|
||||
|
|
186
tests/plat/rck_e.e
Normal file
186
tests/plat/rck_e.e
Normal file
|
@ -0,0 +1,186 @@
|
|||
#
|
||||
mes 2, EM_WSIZE, EM_PSIZE
|
||||
|
||||
/*
|
||||
* Uses _rck_ for range checks. Catches the EM trap if a value is out
|
||||
* of range, and continues with the next instruction after _rck_.
|
||||
*
|
||||
* Some back ends, like i80, ignore _rck_, so this test fails.
|
||||
*/
|
||||
|
||||
testnr
|
||||
con 1 ; test number
|
||||
caught
|
||||
con 0 ; number of caught traps
|
||||
|
||||
inp $next
|
||||
inp $catch
|
||||
inp $never
|
||||
exp $_m_a_i_n
|
||||
pro $_m_a_i_n,0
|
||||
|
||||
lim ; load ignore mask
|
||||
loc 2
|
||||
and EM_WSIZE ; check bit 1 << ERANGE
|
||||
zeq *1 ; fail if ignoring ERANGE
|
||||
.1
|
||||
rom 1I4
|
||||
lae .1
|
||||
loi 4
|
||||
cal $fail
|
||||
asp 4
|
||||
1
|
||||
|
||||
cal $next ; increment testnr, catch next trap
|
||||
loc 10125
|
||||
.2
|
||||
rom 4283, 13644
|
||||
lae .2
|
||||
rck EM_WSIZE ; testnr 2 in range
|
||||
asp EM_WSIZE
|
||||
|
||||
cal $next
|
||||
loc 4282
|
||||
lae .2
|
||||
rck EM_WSIZE ; testnr 3 out of range
|
||||
asp EM_WSIZE
|
||||
|
||||
cal $next
|
||||
loc 4283
|
||||
lae .2
|
||||
rck EM_WSIZE ; testnr 4 in range
|
||||
asp EM_WSIZE
|
||||
|
||||
cal $next
|
||||
loc 13644
|
||||
lae .2
|
||||
rck EM_WSIZE ; testnr 5 in range
|
||||
asp EM_WSIZE
|
||||
|
||||
cal $next
|
||||
loc 13655
|
||||
lae .2
|
||||
rck EM_WSIZE ; testnr 6 out of range
|
||||
asp EM_WSIZE
|
||||
|
||||
cal $next
|
||||
loc -13015
|
||||
.7
|
||||
rom -31344, -1898
|
||||
lae .7
|
||||
rck EM_WSIZE ; testnr 7 in range
|
||||
asp EM_WSIZE
|
||||
|
||||
cal $next
|
||||
loc 8580
|
||||
.8
|
||||
rom -26315, 4588
|
||||
lae .8
|
||||
rck EM_WSIZE ; testnr 8 out of range
|
||||
asp EM_WSIZE
|
||||
|
||||
; The last test raised a trap, so now there is no trap handler.
|
||||
lpi $never
|
||||
sig ; push old trap handler
|
||||
loc 0
|
||||
loc EM_WSIZE
|
||||
loc EM_PSIZE
|
||||
cuu ; push NULL pointer
|
||||
cmp
|
||||
zeq *17 ; fail unless old handler is NULL
|
||||
.17
|
||||
rom 17I4
|
||||
lae .17
|
||||
loi 4
|
||||
cal $fail
|
||||
asp 4
|
||||
17
|
||||
; Change the trap handler from $never to $catch.
|
||||
lpi $catch
|
||||
sig
|
||||
lpi $never
|
||||
cmp
|
||||
zeq *18
|
||||
.18
|
||||
rom 18I4
|
||||
lae .18
|
||||
loi 4
|
||||
cal $fail
|
||||
asp 4
|
||||
18
|
||||
; Begin ignoring range traps.
|
||||
loc 2 ; 1 << ERANGE
|
||||
sim
|
||||
loc 18
|
||||
ste testnr
|
||||
loc 8580
|
||||
lae .8
|
||||
rck EM_WSIZE ; testnr 18 out of range but ignored
|
||||
|
||||
; Fail if we caught the wrong number of traps.
|
||||
loe caught
|
||||
loc 3
|
||||
beq *20
|
||||
.20
|
||||
rom 20I4
|
||||
lae .20
|
||||
loi 4
|
||||
cal $fail
|
||||
asp 4
|
||||
20
|
||||
cal $finished
|
||||
end
|
||||
|
||||
pro $next,0
|
||||
ine testnr ; next test
|
||||
lpi $catch
|
||||
sig ; catch next EM trap (only one trap)
|
||||
asp EM_PSIZE
|
||||
ret 0
|
||||
end
|
||||
|
||||
pro $catch,0
|
||||
ine caught ; count this trap
|
||||
|
||||
lol 0 ; load trap number
|
||||
loc 1
|
||||
beq *1 ; fail if trap != ERANGE
|
||||
.101
|
||||
rom 257I4
|
||||
lae .101
|
||||
loi 4
|
||||
cal $fail
|
||||
; Wrong type of trap. _rtt_ might not work, so exit now.
|
||||
cal $finished
|
||||
1
|
||||
; Fail if the wrong test raised this trap.
|
||||
loe testnr
|
||||
loc 3
|
||||
beq *2
|
||||
loe testnr
|
||||
loc 6
|
||||
beq *2
|
||||
loe testnr
|
||||
loc 8
|
||||
beq *2
|
||||
loc 256
|
||||
loe testnr
|
||||
adi EM_WSIZE ; 0x100 + testnr
|
||||
loc EM_WSIZE
|
||||
loc 4
|
||||
cuu
|
||||
cal $fail
|
||||
asp 4
|
||||
2
|
||||
rtt ; return from trap handler
|
||||
end
|
||||
|
||||
pro $never,0
|
||||
.200
|
||||
rom 200I4
|
||||
lae .200
|
||||
loi 4
|
||||
cal $fail
|
||||
asp 4
|
||||
rtt
|
||||
end
|
Loading…
Reference in a new issue