Add test for EM _rck_. Fix traps in PowerPC ncg.
authorGeorge Koehler <xkernigh@netscape.net>
Mon, 25 Dec 2017 03:37:52 +0000 (22:37 -0500)
committerGeorge Koehler <xkernigh@netscape.net>
Mon, 25 Dec 2017 03:37:52 +0000 (22:37 -0500)
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_.

12 files changed:
mach/powerpc/libem/aar4.s
mach/powerpc/libem/build.lua
mach/powerpc/libem/csa.s
mach/powerpc/libem/csb.s
mach/powerpc/libem/rck.s
mach/powerpc/libem/trp.s [new file with mode: 0644]
mach/powerpc/ncg/table
plat/linuxppc/libsys/build.lua
plat/linuxppc/libsys/trap.s [deleted file]
plat/osxppc/libsys/build.lua
tests/plat/build.lua
tests/plat/rck_e.e [new file with mode: 0644]

index fc8620d..08390b0 100644 (file)
@@ -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
index cb5efd2..ac84e3b 100644 (file)
@@ -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
-
index 3898241..86d7925 100644 (file)
        lwz r4, 4(sp)
        addi sp, sp, 8
 
-       lwz r5, 0(r3)            ! load default
-       mtspr ctr, r5
-       
-       lwz r5, 4(r3)            ! fetch lower bound
-       subf. r4, r5, r4         ! adjust value
-       bltctr                   ! jump to default if out of range
+       lwz r5, 0(r3)            ! r5 = default target
 
-       lwz r5, 8(r3)            ! fetch range
-       cmplw r4, r5
-       bgtctr                   ! 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 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
index 571bfc2..92c6d09 100644 (file)
        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
-
-       lwz r7, 4(r3)            ! fetch target address
-       mtspr ctr, r7
+       beq 2f
+       bdnz 1b                  ! if not equal, go again
+       b 3f
 
-       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
index 9008be6..f1cf7f8 100644 (file)
@@ -18,3 +18,7 @@
     bgt .trap_erange
 
     blr
+
+.trap_erange:
+    li r3, 1       ! ERANGE = 1 in h/em_abs.h
+    b .trp
diff --git a/mach/powerpc/libem/trp.s b/mach/powerpc/libem/trp.s
new file mode 100644 (file)
index 0000000..b07afb9
--- /dev/null
@@ -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"
index e66ae85..10ffadb 100644 (file)
@@ -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
index f7b16b3..696c62d 100644 (file)
@@ -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",
diff --git a/plat/linuxppc/libsys/trap.s b/plat/linuxppc/libsys/trap.s
deleted file mode 100644 (file)
index 93c5189..0000000
+++ /dev/null
@@ -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"
index 072730b..49fc0c9 100644 (file)
@@ -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",
index 666af7d..fdac9ba 100644 (file)
@@ -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",
diff --git a/tests/plat/rck_e.e b/tests/plat/rck_e.e
new file mode 100644 (file)
index 0000000..cd5c581
--- /dev/null
@@ -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