diff --git a/assembly/mips/bit-bash.lisp b/assembly/mips/bit-bash.lisp index 5bf9ca90bd23ff947baed3f3e2e210764e28fc3b..9db43f6825907d71ab6c71ad6323a7a6d80a0105 100644 --- a/assembly/mips/bit-bash.lisp +++ b/assembly/mips/bit-bash.lisp @@ -100,12 +100,16 @@ (defmacro wide-copy () '(let ((aligned (gen-label))) + ;; Check to see if they are aligned. (inst beq src-bit-offset dst-bit-offset aligned) - (inst nop) + + ;; Calc src-shift + (inst subu src-shift dst-offset src-offset) + (inst and src-shift (fixnum 31)) (macrolet - ((get-src () - '(progn + ((middle (&rest before-last-inst) + `(progn (inst lw ntemp1 src) (inst lw ntemp2 src 4) (inst addu src 4) @@ -113,22 +117,39 @@ (inst sll ntemp2 ntemp2 ntemp3) (inst subu ntemp3 zero-tn ntemp3) (inst srl ntemp1 ntemp1 ntemp3) - (inst or ntemp1 ntemp2)))) - ;; Possibly fix src if we need to get bits from the previous word. - (inst sltu ntemp1 src-bit-offset dst-bit-offset) - (inst sll ntemp1 2) - (inst subu src ntemp1) - - ;; Calc src-shift - (inst subu src-shift dst-offset src-offset) - (inst and src-shift (fixnum 31)) - + ,@before-last-inst + (inst or ntemp1 ntemp2))) + (get-src (where) + (ecase where + (:left + '(let ((dont-load (gen-label)) + (done-load (gen-label))) + (inst sltu ntemp1 src-bit-offset dst-bit-offset) + (inst bne ntemp1 dont-load) + (middle (inst b done-load)) + (emit-label dont-load) + (inst sra ntemp3 src-shift 2) + (inst sll ntemp1 ntemp3) + (emit-label done-load))) + (:middle '(middle)) + (:right + '(let ((dont-load (gen-label)) + (done-load (gen-label))) + (inst sltu ntemp1 src-shift final-bits) + (inst beq ntemp1 dont-load) + (middle (inst b done-load)) + (emit-label dont-load) + (inst sra ntemp3 src-shift 2) + (inst subu ntemp3 zero-tn ntemp3) + (inst srl ntemp1 ntemp3) + (emit-label done-load)))))) (wide-copy-aux) (inst b done) (inst nop)) (macrolet - ((get-src () + ((get-src (where) + (declare (ignore where)) '(progn (inst lw ntemp1 src) (inst addu src 4)))) @@ -144,7 +165,7 @@ (inst beq dst-bit-offset left-aligned) (inst nop) - (get-src) + (get-src :left) (inst li ntemp3 (make-fixup "bit_bash_low_masks" :foreign)) (inst addu ntemp3 dst-bit-offset) (inst lw ntemp3 ntemp3) @@ -162,13 +183,11 @@ (inst and final-bits (fixnum 31)) (inst subu ntemp1 length final-bits) (inst srl ntemp1 7) + (inst beq ntemp1 check-right) (inst sll interior ntemp1 2) - (inst beq interior check-right) - (inst nop) - (emit-label loop) - (get-src) + (get-src :middle) (inst sw ntemp1 dst) (check-for-interrupts) (inst subu interior 4) @@ -179,7 +198,7 @@ (inst beq final-bits done) (inst nop) - (get-src) + (get-src :right) (inst li ntemp3 (make-fixup "bit_bash_low_masks" :foreign)) (inst addu ntemp3 final-bits) (inst lw ntemp3 ntemp3) @@ -308,10 +327,10 @@ (inst subu src src-arg vm:other-pointer-type) (inst subu dst dst-arg vm:other-pointer-type) (macrolet - ((check-for-interrupt () - '(let ((label ((gen-label)))) + ((check-for-interrupts () + '(let ((label (gen-label))) (inst and ntemp1 flags-tn (ash 1 interrupted-flag)) - (inst bne ntemp1 label) + (inst beq ntemp1 label) (inst nop) (inst subu src src-arg) (inst subu dst dst-arg)