1 (in-package "SB-ROTATE-BYTE")
3 (defknown rotate-byte
(integer byte-specifier integer
) integer
5 (defknown %rotate-byte
(integer bit-index bit-index integer
) integer
7 (defknown %unsigned-32-rotate-byte
((integer -
31 31) (unsigned-byte 32))
11 (macrolet (;; see src/compiler/srctran.lisp
12 (with-byte-specifier ((size-var pos-var spec
) &body body
)
13 (once-only ((spec `(macroexpand ,spec
))
15 `(if (and (consp ,spec
)
16 (eq (car ,spec
) 'byte
)
18 (let ((,size-var
(second ,spec
))
19 (,pos-var
(third ,spec
)))
21 (let ((,size-var
`(byte-size ,,temp
))
22 (,pos-var
`(byte-position ,,temp
)))
23 `(let ((,,temp
,,spec
))
25 (define-source-transform rotate-byte
(count spec num
)
26 (with-byte-specifier (size pos spec
)
27 `(%rotate-byte
,count
,size
,pos
,num
))))
29 (defoptimizer (%rotate-byte derive-type
) ((count size posn num
))
30 ;; FIXME: this looks fairly unwieldy. I'm sure it can be made
31 ;; simpler, and also be made to deal with negative integers too.
32 (let ((size (sb-c::lvar-type size
)))
33 (if (numeric-type-p size
)
34 (let ((size-high (numeric-type-high size
))
35 (num-type (sb-c::lvar-type num
)))
38 (<= size-high sb-vm
:n-word-bits
)
40 (specifier-type `(unsigned-byte ,size-high
))))
41 (specifier-type `(unsigned-byte ,size-high
))
45 (deftransform %rotate-byte
((count size pos integer
)
46 ((constant-arg (member 0)) * * *) *)
47 "fold identity operation"
50 (deftransform %rotate-byte
((count size pos integer
)
52 (constant-arg (member 32))
53 (constant-arg (member 0))
54 (unsigned-byte 32)) *)
55 "inline 32-bit rotation"
56 ;; FIXME: What happens when, as here, the two type specifiers for
57 ;; COUNT overlap? Which gets to run first?
58 '(%unsigned-32-rotate-byte count integer
))
60 ;; Generic implementation for platforms that don't supply VOPs for 32-bit
63 (deftransform %unsigned-32-rotate-byte
((.count. .integer.
)
65 (unsigned-byte 32)) *)
67 (logior (ldb (byte 32 0) (ash .integer.
(+ .count.
32)))
68 (ash .integer. .count.
))
69 (logior (ldb (byte 32 0) (ash .integer. .count.
))
70 (ash .integer.
(- .count.
32)))))