diff --git a/mach/mips/libem/aar4.s b/mach/mips/libem/aar4.s new file mode 100644 index 000000000..fc1068f48 --- /dev/null +++ b/mach/mips/libem/aar4.s @@ -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 index 000000000..ca5a295a9 --- /dev/null +++ b/mach/mips/libem/dus4.s @@ -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 index 000000000..24753f328 --- /dev/null +++ b/mach/mips/libem/exg.s @@ -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 index 000000000..07a4991b6 --- /dev/null +++ b/mach/mips/libem/inn.s @@ -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 index 000000000..870140255 --- /dev/null +++ b/mach/mips/libem/lar4.s @@ -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 index 000000000..be9434a34 --- /dev/null +++ b/mach/mips/libem/los4.s @@ -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 index 000000000..01eca7156 --- /dev/null +++ b/mach/mips/libem/rck.s @@ -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 diff --git a/mach/mips/libem/trp.s b/mach/mips/libem/trp.s index 1794459f6..a283b07a2 100644 --- a/mach/mips/libem/trp.s +++ b/mach/mips/libem/trp.s @@ -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