Lots more untested helper functions.
authorDavid Given <dg@cowlark.com>
Sun, 9 Sep 2018 23:08:25 +0000 (01:08 +0200)
committerDavid Given <dg@cowlark.com>
Sun, 9 Sep 2018 23:08:25 +0000 (01:08 +0200)
mach/mips/libem/aar4.s [new file with mode: 0644]
mach/mips/libem/dus4.s [new file with mode: 0644]
mach/mips/libem/exg.s [new file with mode: 0644]
mach/mips/libem/inn.s [new file with mode: 0644]
mach/mips/libem/lar4.s [new file with mode: 0644]
mach/mips/libem/los4.s [new file with mode: 0644]
mach/mips/libem/rck.s [new file with mode: 0644]
mach/mips/libem/trp.s

diff --git a/mach/mips/libem/aar4.s b/mach/mips/libem/aar4.s
new file mode 100644 (file)
index 0000000..fc1068f
--- /dev/null
@@ -0,0 +1,39 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+/* Get address of element of bounds-checked array.
+ *
+ * Stack: ( array-adr index descriptor-adr -- element-adr )
+ * Sets r2 = size of element for .los4, .sts4
+ * Preserves r25 (the last volatile register)
+ */
+
+.sect .text
+.define .aar4
+.aar4:
+       lw r4, 0(sp)            ! r4 = address of descriptor
+       lw r5, 0(sp)            ! r5 = index
+       lw r6, 0(sp)            ! r6 = address of array
+
+       lw r7, 0(r4)            ! at = lower bound
+       slt at, r7, at          ! at = r5 < at
+       bne at, zero, .trap_earray
+
+       lw at, 4(r4)            ! at = upper bound
+       slt at, at, r5          ! at = at < r5
+       bne at, zero, .trap_earray
+
+       lw r2, 8(r4)            ! r2 = size of element
+       subu r5, r5, r7         ! adjust index for non-zero lower bound
+       mul r5, r5, r2          ! scale index by size
+       addu r5, r5, r6         ! calculate address of element
+
+       sw r5, 8(sp)            ! push address of element
+       addiu sp, sp, 8
+       jr ra
+       nop
+
+.define .trap_earray
+.trap_earray:
+       li r4, 0                 ! EARRAY = 0 in h/em_abs.h
+       b .trp
diff --git a/mach/mips/libem/dus4.s b/mach/mips/libem/dus4.s
new file mode 100644 (file)
index 0000000..ca5a295
--- /dev/null
@@ -0,0 +1,28 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+/* Duplicates some words on top of stack.
+ *  Stack: ( a size -- a a )
+ */
+
+.sect .text
+.define .dus4
+.dus4:
+       lw r4, 0(sp)        ! r4 = size
+       addiu sp, sp, 4     ! sp = pointer to a
+       mov r5, sp          ! r5 = pointer to a
+       subu sp, sp, r4     ! sp = pointer to newa
+       mov r6, sp          ! r6 = pointer to b
+
+       srl r4, r4, 2       ! r4 = number of words
+1:
+       lw at, 0(r5)
+       sw at, 0(r6)
+       addiu r5, r5, 4
+       addiu r6, r6, 4
+       addiu r4, r4, -1
+       bne r4, zero, 1b
+       nop
+
+       jr ra
+       nop
diff --git a/mach/mips/libem/exg.s b/mach/mips/libem/exg.s
new file mode 100644 (file)
index 0000000..24753f3
--- /dev/null
@@ -0,0 +1,31 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+/* Exchange top two values on stack.
+ *   Stack: ( a b size -- b a )
+ */
+
+.sect .text
+.define .exg
+.exg:
+       lw r4, 0(sp)            ! r4 = size
+       srl r5, r4, 2           ! r5 = number of words
+       addiu sp, sp, 4         ! adjust stack for input/output parameter size
+
+       mov r6, sp              ! r6 = pointer to b
+       addu r7, r6, r4         ! r7 = pointer to a
+
+       ! Loop to swap each pair of words.
+1:
+       lw r8, 0(r6)
+       lw r9, 0(r7)
+       sw r9, 0(r6)
+       sw r8, 0(r7)
+       addiu r6, r6, 4
+       addiu r7, r7, 4
+       addiu r5, r5, -1
+       bne r5, zero, 1b
+       nop
+
+       jr ra
+       nop
diff --git a/mach/mips/libem/inn.s b/mach/mips/libem/inn.s
new file mode 100644 (file)
index 0000000..07a4991
--- /dev/null
@@ -0,0 +1,33 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+/* Tests a bit in a bitset on the stack.
+ *
+ * Stack: ( bitset bitnum setsize -- bool )
+ *
+ * Some back ends push false if bitnum is too large.  We don't because
+ * the compilers tend to pass a small enough bitnum.
+ */
+
+.sect .text
+.define .inn
+.inn:
+       lw r4, 0(sp)        ! r4 = size of set (bytes)
+       lw r5, 0(sp)        ! r5 = bit number
+       addiu sp, sp, 8     ! sp now points at bitset
+
+       srl r6, r5, 3       ! r6 = offset of word in set
+       addu r6, sp, r6     ! r6 = address of word in set
+       lw r6, 0(r6)        ! r6 = word
+
+       ext r7, r5, 0, 3    ! r7 = bit number within word
+       srlv r6, r6, r7     ! r7 = candidate bit now at bit 0
+       andi r6, r6, 1      ! r7 = bool
+
+       addu sp, sp, r4     ! retract over bitfield
+
+       addiu sp, sp, -4
+       sw r6, 0(sp)        ! push result
+
+       jr ra
+       nop
diff --git a/mach/mips/libem/lar4.s b/mach/mips/libem/lar4.s
new file mode 100644 (file)
index 0000000..8701402
--- /dev/null
@@ -0,0 +1,23 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+/* Load from bounds-checked array.
+ *
+ * Stack: ( array-adr index descriptor-adr -- element )
+ */
+
+.sect .text
+.define .lar4
+.lar4:
+       mov r25, ra
+
+       jal .aar4
+       nop
+
+       /* pass r2 = size from .aar4 to .los4
+
+       jal .los4
+       nop
+
+       jr r25
+       nop
diff --git a/mach/mips/libem/los4.s b/mach/mips/libem/los4.s
new file mode 100644 (file)
index 0000000..be9434a
--- /dev/null
@@ -0,0 +1,55 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+/* Loads a variable-sized block onto the stack.
+ *
+ * On entry: r2 = size
+ * Stack: ( address -- block )
+ * Preserves r25 for .lar4 and .sar4
+ */
+
+.sect .text
+.define .los4
+.los4:
+       lw r4, 0(sp)            ! r4 = address
+
+       ! Sizes 1 and 2 are handled specially.
+
+       li at, 1
+       beq r2, at, byte_sized
+       nop
+
+       li at, 2
+       beq r2, at, word_sized
+       nop
+
+       ! Else the size must be a multiple of 4.
+
+       srl r5, r2, 2           ! r5 = number of words
+       addiu sp, sp, 4         ! adjust to end of block
+       subu sp, sp, r4         ! sp = start of block
+       mov r6, sp              ! r6 = start of block
+
+1:
+       lw at, 0(r2)
+       sw at, 0(r6)
+       addiu r2, r2, 4
+       addiu r6, r6, 4
+       addiu r5, r5, -1
+       bne r5, zero, 1b
+       nop
+
+       jr ra
+       nop
+
+byte_sized:
+       lb at, 0(r4)
+       sw at, 0(sp)
+       jr ra
+       nop
+
+word_sized:
+       lh at, 0(r4)
+       sw at, 0(sp)
+       jr ra
+       nop
diff --git a/mach/mips/libem/rck.s b/mach/mips/libem/rck.s
new file mode 100644 (file)
index 0000000..01eca71
--- /dev/null
@@ -0,0 +1,33 @@
+#
+.sect .text; .sect .rom; .sect .data; .sect .bss
+
+/* Bounds check. Traps if the value is out of range.
+ *  Stack: ( value descriptor -- value )
+ *
+ * This ".rck" only works with 4-byte integers.  The name is ".rck" and
+ * not ".rck4" because many back ends only do rck with the word size.
+ */
+
+.sect .text
+.define .rck
+.rck:
+       lw r4, 0(sp)            ! r4 = pointer to descriptor
+       addiu sp, sp, 4         ! leave value on stack
+       lw r5, 0(sp)            ! r5 = value
+
+       lw at, 0(sp)            ! at = lower bound
+       slt at, r5, at          ! at = r5 < at
+       bne at, zero, .trap_erange
+
+       lw at, 4(sp)            ! at = upper bound
+       slt at, at, r5          ! at = at < r5
+       bne at, zero, .trap_erange
+
+       jr ra
+       nop
+
+.define .trap_erange
+.trap_erange:
+       li r4, 1
+       j .trp
+       nop
index 1794459..a283b07 100644 (file)
@@ -7,7 +7,7 @@
 .sect .text
 .define .trap_ecase
 .trap_ecase:
-       li      r3, 20                  ! ECASE = 20 in h/em_abs.h
+       li      r4, 20                  ! ECASE = 20 in h/em_abs.h
        ! FALLTHROUGH to .trp
 
 .define .trp