+ (inst sll q-pass n-fixnum-tag-bits q)
+ ;(move q-pass q)
+ (move r-pass r)))
+
+(define-vop (fast-truncate/unsigned fast-unsigned-binop)
+ (:translate truncate)
+ (:args (x :scs (unsigned-reg) :target x-pass)
+ (y :scs (unsigned-reg) :target y-pass))
+ (:temporary (:sc unsigned-reg :offset nl0-offset
+ :from (:argument 0) :to (:result 0)) x-pass)
+ (:temporary (:sc unsigned-reg :offset nl1-offset
+ :from (:argument 1) :to (:result 0)) y-pass)
+ (:temporary (:sc unsigned-reg :offset nl2-offset :target q
+ :from (:argument 1) :to (:result 0)) q-pass)
+ (:temporary (:sc unsigned-reg :offset nl3-offset :target r
+ :from (:argument 1) :to (:result 1)) r-pass)
+ (:results (q :scs (unsigned-reg))
+ (r :scs (unsigned-reg)))
+ (:result-types unsigned-num unsigned-num)
+ (:vop-var vop)
+ (:save-p :compute-only)
+ (:generator 35
+ (let ((zero (generate-error-code vop division-by-zero-error x y)))
+ (inst bc := nil y zero-tn zero))
+ (move x x-pass)
+ (move y y-pass)
+ ;; really dirty trick to avoid the bug truncate/unsigned vop
+ ;; followed by move-from/word->fixnum where the result from
+ ;; the truncate is 0xe39516a7 and move-from-word will treat
+ ;; the unsigned high number as an negative number.
+ ;; instead we clear the high bit in the input to truncate.
+ (inst li #x1fffffff q)
+ (inst comb :<> q y skip :nullify t)
+ (inst addi -1 zero-tn q)
+ (inst srl q 1 q) ; this should result in #7fffffff
+ (inst and x-pass q x-pass)
+ (inst and y-pass q y-pass)
+ SKIP
+ ;; fix bug#2 (truncate #xe39516a7 #x3) => #0xf687078d,#x0
+ (inst li #x7fffffff q)
+ (inst and x-pass q x-pass)
+ (let ((fixup (make-fixup 'truncate :assembly-routine)))
+ (inst ldil fixup q-pass)
+ (inst ble fixup lisp-heap-space q-pass :nullify t))
+ (inst nop)