1 ;;;; functions to implement bitblt-ish operations
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
16 (deftype bit-offset
() '(integer 0 (#.sb
!vm
:n-word-bits
)))
20 ;;; A particular implementation must offer either VOPs to translate
21 ;;; these, or DEFTRANSFORMs to convert them into something supported
22 ;;; by the architecture.
23 (macrolet ((def (name &rest args
)
26 (def word-logical-not x
)
27 (def word-logical-and x y
)
28 (def word-logical-or x y
)
29 (def word-logical-xor x y
)
30 (def word-logical-nor x y
)
31 (def word-logical-eqv x y
)
32 (def word-logical-nand x y
)
33 (def word-logical-andc1 x y
)
34 (def word-logical-andc2 x y
)
35 (def word-logical-orc1 x y
)
36 (def word-logical-orc2 x y
))
38 ;;; Shift NUMBER by the low-order bits of COUNTOID, adding zero bits
39 ;;; at the "end" and removing bits from the "start". On big-endian
40 ;;; machines this is a left-shift and on little-endian machines this
42 (defun shift-towards-start (number countoid
)
43 (declare (type sb
!vm
:word number
) (fixnum countoid
))
44 (let ((count (ldb (byte (1- (integer-length sb
!vm
:n-word-bits
)) 0) countoid
)))
45 (declare (type bit-offset count
))
48 (ecase sb
!c
:*backend-byte-order
*
50 (ash (ldb (byte (- sb
!vm
:n-word-bits count
) 0) number
) count
))
52 (ash number
(- count
)))))))
54 ;;; Shift NUMBER by COUNT bits, adding zero bits at the "start" and
55 ;;; removing bits from the "end". On big-endian machines this is a
56 ;;; right-shift and on little-endian machines this is a left-shift.
57 (defun shift-towards-end (number count
)
58 (declare (type sb
!vm
:word number
) (fixnum count
))
59 (let ((count (ldb (byte (1- (integer-length sb
!vm
:n-word-bits
)) 0) count
)))
60 (declare (type bit-offset count
))
63 (ecase sb
!c
:*backend-byte-order
*
65 (ash number
(- count
)))
67 (ash (ldb (byte (- sb
!vm
:n-word-bits count
) 0) number
) count
))))))
69 #!-sb-fluid
(declaim (inline start-mask end-mask
))
71 ;;; Produce a mask that contains 1's for the COUNT "start" bits and
72 ;;; 0's for the remaining "end" bits. Only the lower 5 bits of COUNT
73 ;;; are significant (KLUDGE: because of hardwired implicit dependence
74 ;;; on 32-bit word size -- WHN 2001-03-19).
75 (defun start-mask (count)
76 (declare (fixnum count
))
77 (shift-towards-start (1- (ash 1 sb
!vm
:n-word-bits
)) (- count
)))
79 ;;; Produce a mask that contains 1's for the COUNT "end" bits and 0's
80 ;;; for the remaining "start" bits. Only the lower 5 bits of COUNT are
81 ;;; significant (KLUDGE: because of hardwired implicit dependence on
82 ;;; 32-bit word size -- WHN 2001-03-19).
83 (defun end-mask (count)
84 (declare (fixnum count
))
85 (shift-towards-end (1- (ash 1 sb
!vm
:n-word-bits
)) (- count
)))
87 #!-sb-fluid
(declaim (inline word-sap-ref %set-word-sap-ref
))
88 (defun word-sap-ref (sap offset
)
89 (declare (type system-area-pointer sap
)
92 (optimize (speed 3) (safety 0) #-sb-xc-host
(inhibit-warnings 3)))
93 (sap-ref-word sap
(the index
(ash offset sb
!vm
:n-fixnum-tag-bits
))))
94 (defun %set-word-sap-ref
(sap offset value
)
95 (declare (type system-area-pointer sap
)
97 (type sb
!vm
:word value
)
99 (optimize (speed 3) (safety 0) (inhibit-warnings 3)))
100 (setf (sap-ref-word sap
(the index
(ash offset sb
!vm
:n-fixnum-tag-bits
)))
104 ;;; the actual bashers and common uses of same
106 ;;; This is a little ugly. Fixing bug 188 would bring the ability to
107 ;;; wrap a MACROLET or something similar around this whole thing would
108 ;;; make things significantly less ugly. --njf, 2005-02-23
109 (eval-when (:compile-toplevel
:load-toplevel
:execute
)
111 ;;; Align the SAP to a word boundary, and update the offset accordingly.
112 (defmacro !define-sap-fixer
(bitsize)
113 (let ((name (intern (format nil
"FIX-SAP-AND-OFFSET-UB~D" bitsize
))))
115 (declaim (inline ,name
))
116 (defun ,name
(sap offset
)
117 (declare (type system-area-pointer sap
)
119 (values system-area-pointer index
))
120 (let ((address (sap-int sap
)))
121 (values (int-sap #!-alpha
(word-logical-andc2 address
122 sb
!vm
:fixnum-tag-mask
)
123 #!+alpha
(ash (ash address -
2) 2))
125 (1 '(* (logand address sb
!vm
:fixnum-tag-mask
) n-byte-bits
))
126 (2 '(* (logand address sb
!vm
:fixnum-tag-mask
) (/ n-byte-bits
2)))
127 (4 '(* (logand address sb
!vm
:fixnum-tag-mask
) (/ n-byte-bits
4)))
128 ((8 16 32 64) '(logand address sb
!vm
:fixnum-tag-mask
)))
131 ;;; We cheat a little bit by using TRULY-THE in the copying function to
132 ;;; force the compiler to generate good code in the (= BITSIZE
133 ;;; SB!VM:N-WORD-BITS) case. We don't use TRULY-THE in the other cases
134 ;;; to give the compiler freedom to generate better code.
135 (defmacro !define-byte-bashers
(bitsize)
136 (let* ((bytes-per-word (/ n-word-bits bitsize
))
137 (byte-offset `(integer 0 (,bytes-per-word
)))
138 (byte-count `(integer 1 (,bytes-per-word
)))
139 (max-bytes (ash sb
!xc
:most-positive-fixnum
140 ;; FIXME: this reflects code contained in the
141 ;; original bit-bash.lisp, but seems very
142 ;; nonsensical. Why shouldn't we be able to
143 ;; handle M-P-FIXNUM bits? And if we can't,
144 ;; are these other shift amounts bogus, too?
153 (offset `(integer 0 ,max-bytes
))
154 (max-word-offset (ceiling max-bytes bytes-per-word
))
155 (word-offset `(integer 0 ,max-word-offset
))
156 (fix-sap-and-offset-name (intern (format nil
"FIX-SAP-AND-OFFSET-UB~D" bitsize
)))
157 (constant-bash-name (intern (format nil
"CONSTANT-UB~D-BASH" bitsize
) (find-package "SB!KERNEL")))
158 (array-fill-name (intern (format nil
"UB~D-BASH-FILL" bitsize
) (find-package "SB!KERNEL")))
159 (system-area-fill-name (intern (format nil
"SYSTEM-AREA-UB~D-FILL" bitsize
) (find-package "SB!KERNEL")))
160 (unary-bash-name (intern (format nil
"UNARY-UB~D-BASH" bitsize
) (find-package "SB!KERNEL")))
161 (array-copy-name (intern (format nil
"UB~D-BASH-COPY" bitsize
) (find-package "SB!KERNEL")))
162 (system-area-copy-name (intern (format nil
"SYSTEM-AREA-UB~D-COPY" bitsize
) (find-package "SB!KERNEL")))
163 (array-copy-to-system-area-name
164 (intern (format nil
"COPY-UB~D-TO-SYSTEM-AREA" bitsize
) (find-package "SB!KERNEL")))
165 (system-area-copy-to-array-name
166 (intern (format nil
"COPY-UB~D-FROM-SYSTEM-AREA" bitsize
)
167 (find-package "SB!KERNEL"))))
169 (declaim (inline ,constant-bash-name
,unary-bash-name
))
170 ;; Fill DST with VALUE starting at DST-OFFSET and continuing
171 ;; for LENGTH bytes (however bytes are defined).
172 (defun ,constant-bash-name
(dst dst-offset length value
173 dst-ref-fn dst-set-fn
)
174 (declare (type word value
) (type index dst-offset length
))
175 (declare (ignorable dst-ref-fn
))
176 (multiple-value-bind (dst-word-offset dst-byte-offset
)
177 (floor dst-offset
,bytes-per-word
)
178 (declare (type ,word-offset dst-word-offset
)
179 (type ,byte-offset dst-byte-offset
))
180 (multiple-value-bind (n-words final-bytes
)
181 (floor (+ dst-byte-offset length
) ,bytes-per-word
)
182 (declare (type ,word-offset n-words
)
183 (type ,byte-offset final-bytes
))
185 ,(unless (= bytes-per-word
1)
186 `(unless (zerop length
)
187 (locally (declare (type ,byte-count length
))
188 (funcall dst-set-fn dst dst-word-offset
189 (if (= length
,bytes-per-word
)
191 (let ((mask (shift-towards-end
192 (start-mask (* length
,bitsize
))
193 (* dst-byte-offset
,bitsize
))))
194 (word-logical-or (word-logical-and value mask
)
195 (word-logical-andc2 (funcall dst-ref-fn dst dst-word-offset
)
197 (let ((interior (floor (- length final-bytes
) ,bytes-per-word
)))
198 ,@(unless (= bytes-per-word
1)
199 `((unless (zerop dst-byte-offset
)
200 (let ((mask (end-mask (* (- dst-byte-offset
) ,bitsize
))))
201 (funcall dst-set-fn dst dst-word-offset
202 (word-logical-or (word-logical-and value mask
)
203 (word-logical-andc2 (funcall dst-ref-fn dst dst-word-offset
)
205 (incf dst-word-offset
))))
206 (let ((end (+ dst-word-offset interior
)))
207 (declare (type ,word-offset end
))
209 ((>= dst-word-offset end
))
210 (funcall dst-set-fn dst dst-word-offset value
)
211 (incf dst-word-offset
)))
213 (dotimes (i interior
)
214 (funcall dst-set-fn dst dst-word-offset value
)
215 (incf dst-word-offset
))
216 ,@(unless (= bytes-per-word
1)
217 `((unless (zerop final-bytes
)
218 (let ((mask (start-mask (* final-bytes
,bitsize
))))
219 (funcall dst-set-fn dst dst-word-offset
220 (word-logical-or (word-logical-and value mask
)
221 (word-logical-andc2 (funcall dst-ref-fn dst dst-word-offset
)
225 ;; common uses for constant-byte-bashing
226 (defun ,array-fill-name
(value dst dst-offset length
)
227 (declare (type word value
) (type ,offset dst-offset length
))
228 (declare (optimize (speed 3) (safety 1)))
229 (,constant-bash-name dst dst-offset length value
230 #'%vector-raw-bits
#'%set-vector-raw-bits
))
231 (defun ,system-area-fill-name
(value dst dst-offset length
)
232 (declare (type word value
) (type ,offset dst-offset length
))
233 (declare (optimize (speed 3) (safety 1)))
234 (multiple-value-bind (dst dst-offset
) (,fix-sap-and-offset-name dst dst-offset
)
235 (,constant-bash-name dst dst-offset length value
236 #'word-sap-ref
#'%set-word-sap-ref
)))
238 ;; unary byte bashing (copying)
239 (defun ,unary-bash-name
(src src-offset dst dst-offset length
240 dst-ref-fn dst-set-fn src-ref-fn
)
241 (declare (type index src-offset dst-offset length
)
242 (type function dst-ref-fn dst-set-fn src-ref-fn
)
243 (ignorable dst-ref-fn
))
244 (multiple-value-bind (dst-word-offset dst-byte-offset
)
245 (floor dst-offset
,bytes-per-word
)
246 (declare (type ,word-offset dst-word-offset
)
247 (type ,byte-offset dst-byte-offset
))
248 (multiple-value-bind (src-word-offset src-byte-offset
)
249 (floor src-offset
,bytes-per-word
)
250 (declare (type ,word-offset src-word-offset
)
251 (type ,byte-offset src-byte-offset
))
253 ((<= (+ dst-byte-offset length
) ,bytes-per-word
)
254 ;; We are only writing one word, so it doesn't matter what
255 ;; order we do it in. But we might be reading from
256 ;; multiple words, so take care.
259 ;; We're not writing anything. This is really easy.
261 ((= length
,bytes-per-word
)
262 ;; DST-BYTE-OFFSET must be equal to zero, or we would be
263 ;; writing multiple words. If SRC-BYTE-OFFSET is also zero,
264 ;; the we just transfer the single word. Otherwise we have
265 ;; to extract bytes from two source words.
266 (funcall dst-set-fn dst dst-word-offset
268 ((zerop src-byte-offset
)
269 (funcall src-ref-fn src src-word-offset
))
270 ,@(unless (= bytes-per-word
1)
271 `((t (word-logical-or (shift-towards-start
272 (funcall src-ref-fn src src-word-offset
)
273 (* src-byte-offset
,bitsize
))
275 (funcall src-ref-fn src
(1+ src-word-offset
))
276 (* (- src-byte-offset
) ,bitsize
)))))))))
277 ,@(unless (= bytes-per-word
1)
279 ;; We are only writing some portion of the destination word.
280 ;; We still don't know whether we need one or two source words.
281 (locally (declare (type ,byte-count length
))
282 (let ((mask (shift-towards-end (start-mask (* length
,bitsize
))
283 (* dst-byte-offset
,bitsize
)))
284 (orig (funcall dst-ref-fn dst dst-word-offset
))
285 (value (if (> src-byte-offset dst-byte-offset
)
286 ;; The source starts further
287 ;; into the word than does the
288 ;; destination, so the source
289 ;; could extend into the next
290 ;; word. If it does, we have
291 ;; to merge the two words, and
292 ;; it not, we can just shift
294 (let ((src-byte-shift (- src-byte-offset
296 (if (> (+ src-byte-offset length
) ,bytes-per-word
)
299 (funcall src-ref-fn src src-word-offset
)
300 (* src-byte-shift
,bitsize
))
302 (funcall src-ref-fn src
(1+ src-word-offset
))
303 (* (- src-byte-shift
) ,bitsize
)))
304 (shift-towards-start (funcall src-ref-fn src src-word-offset
)
305 (* src-byte-shift
,bitsize
))))
306 ;; The destination starts further
307 ;; into the word than does the
308 ;; source, so we know the source
309 ;; cannot extend into a second
310 ;; word (or else the destination
311 ;; would too, and we wouldn't be
314 (funcall src-ref-fn src src-word-offset
)
315 (* (- dst-byte-offset src-byte-offset
) ,bitsize
)))))
316 (declare (type word mask orig value
))
317 (funcall dst-set-fn dst dst-word-offset
318 (word-logical-or (word-logical-and value mask
)
319 (word-logical-andc2 orig mask
))))))))))
320 ((= src-byte-offset dst-byte-offset
)
321 ;; The source and destination are aligned, so shifting
322 ;; is unnecessary. But we have to pick the direction
323 ;; of the copy in case the source and destination are
324 ;; really the same object.
325 (multiple-value-bind (words final-bytes
)
326 (floor (+ dst-byte-offset length
) ,bytes-per-word
)
327 (declare (type ,word-offset words
)
328 (type ,byte-offset final-bytes
))
329 (let ((interior (floor (- length final-bytes
) ,bytes-per-word
)))
330 (declare (type ,word-offset interior
))
332 ((<= dst-offset src-offset
)
333 ;; We need to loop from left to right.
334 ,@(unless (= bytes-per-word
1)
335 `((unless (zerop dst-byte-offset
)
336 ;; We are only writing part of the first word, so mask
337 ;; off the bytes we want to preserve.
338 (let ((mask (end-mask (* (- dst-byte-offset
) ,bitsize
)))
339 (orig (funcall dst-ref-fn dst dst-word-offset
))
340 (value (funcall src-ref-fn src src-word-offset
)))
341 (declare (type word mask orig value
))
342 (funcall dst-set-fn dst dst-word-offset
343 (word-logical-or (word-logical-and value mask
)
344 (word-logical-andc2 orig mask
))))
345 (incf src-word-offset
)
346 (incf dst-word-offset
))))
347 ;; Copy the interior words.
348 (let ((end ,(if (= bytes-per-word
1)
349 `(truly-the ,word-offset
350 (+ dst-word-offset interior
))
351 `(+ dst-word-offset interior
))))
352 (declare (type ,word-offset end
))
354 ((>= dst-word-offset end
))
355 (funcall dst-set-fn dst dst-word-offset
356 (funcall src-ref-fn src src-word-offset
))
357 ,(if (= bytes-per-word
1)
358 `(setf src-word-offset
(truly-the ,word-offset
(+ src-word-offset
1)))
359 `(incf src-word-offset
))
360 (incf dst-word-offset
)))
361 ,@(unless (= bytes-per-word
1)
362 `((unless (zerop final-bytes
)
363 ;; We are only writing part of the last word.
364 (let ((mask (start-mask (* final-bytes
,bitsize
)))
365 (orig (funcall dst-ref-fn dst dst-word-offset
))
366 (value (funcall src-ref-fn src src-word-offset
)))
367 (declare (type word mask orig value
))
368 (funcall dst-set-fn dst dst-word-offset
369 (word-logical-or (word-logical-and value mask
)
370 (word-logical-andc2 orig mask
))))))))
372 ;; We need to loop from right to left.
373 ,(if (= bytes-per-word
1)
374 `(setf dst-word-offset
(truly-the ,word-offset
375 (+ dst-word-offset words
)))
376 `(incf dst-word-offset words
))
377 ,(if (= bytes-per-word
1)
378 `(setf src-word-offset
(truly-the ,word-offset
379 (+ src-word-offset words
)))
380 `(incf src-word-offset words
))
381 ,@(unless (= bytes-per-word
1)
382 `((unless (zerop final-bytes
)
383 (let ((mask (start-mask (* final-bytes
,bitsize
)))
384 (orig (funcall dst-ref-fn dst dst-word-offset
))
385 (value (funcall src-ref-fn src src-word-offset
)))
386 (declare (type word mask orig value
))
387 (funcall dst-set-fn dst dst-word-offset
388 (word-logical-or (word-logical-and value mask
)
389 (word-logical-andc2 orig mask
)))))))
390 (let ((end (- dst-word-offset interior
)))
392 ((<= dst-word-offset end
))
393 (decf src-word-offset
)
394 (decf dst-word-offset
)
395 (funcall dst-set-fn dst dst-word-offset
396 (funcall src-ref-fn src src-word-offset
))))
397 ,@(unless (= bytes-per-word
1)
398 `((unless (zerop dst-byte-offset
)
399 ;; We are only writing part of the last word.
400 (decf src-word-offset
)
401 (decf dst-word-offset
)
402 (let ((mask (end-mask (* (- dst-byte-offset
) ,bitsize
)))
403 (orig (funcall dst-ref-fn dst dst-word-offset
))
404 (value (funcall src-ref-fn src src-word-offset
)))
405 (declare (type word mask orig value
))
406 (funcall dst-set-fn dst dst-word-offset
407 (word-logical-or (word-logical-and value mask
)
408 (word-logical-andc2 orig mask
))))))))))))
410 ;; Source and destination are not aligned.
411 (multiple-value-bind (words final-bytes
)
412 (floor (+ dst-byte-offset length
) ,bytes-per-word
)
413 (declare (type ,word-offset words
)
414 (type ,byte-offset final-bytes
))
415 (let ((src-shift (mod (- src-byte-offset dst-byte-offset
)
417 (interior (floor (- length final-bytes
) ,bytes-per-word
)))
418 (declare (type ,word-offset interior
)
419 (type ,byte-offset src-shift
))
421 ((<= dst-offset src-offset
)
422 ;; We need to loop from left to right.
424 (next (funcall src-ref-fn src src-word-offset
)))
425 (declare (type word prev next
))
426 (flet ((get-next-src ()
428 (setf next
(funcall src-ref-fn src
429 (setf src-word-offset
(incf src-word-offset
))))))
430 (declare (inline get-next-src
))
431 ,@(unless (= bytes-per-word
1)
432 `((unless (zerop dst-byte-offset
)
433 (when (> src-byte-offset dst-byte-offset
)
435 (let ((mask (end-mask (* (- dst-byte-offset
) ,bitsize
)))
436 (orig (funcall dst-ref-fn dst dst-word-offset
))
437 (value (word-logical-or (shift-towards-start prev
(* src-shift
,bitsize
))
438 (shift-towards-end next
(* (- src-shift
) ,bitsize
)))))
439 (declare (type word mask orig value
))
440 (funcall dst-set-fn dst dst-word-offset
441 (word-logical-or (word-logical-and value mask
)
442 (word-logical-andc2 orig mask
))))
443 (incf dst-word-offset
))))
444 (let ((end (+ dst-word-offset interior
)))
445 (declare (type ,word-offset end
))
447 ((>= dst-word-offset end
))
449 (let ((value (word-logical-or
450 (shift-towards-end next
(* (- src-shift
) ,bitsize
))
451 (shift-towards-start prev
(* src-shift
,bitsize
)))))
452 (declare (type word value
))
453 (funcall dst-set-fn dst dst-word-offset value
)
454 (incf dst-word-offset
))))
455 ,@(unless (= bytes-per-word
1)
456 `((unless (zerop final-bytes
)
458 (if (> (+ final-bytes src-shift
) ,bytes-per-word
)
462 (shift-towards-end next
(* (- src-shift
) ,bitsize
))
463 (shift-towards-start prev
(* src-shift
,bitsize
))))
464 (shift-towards-start next
(* src-shift
,bitsize
))))
465 (mask (start-mask (* final-bytes
,bitsize
)))
466 (orig (funcall dst-ref-fn dst dst-word-offset
)))
467 (declare (type word mask orig value
))
468 (funcall dst-set-fn dst dst-word-offset
469 (word-logical-or (word-logical-and value mask
)
470 (word-logical-andc2 orig mask
))))))))))
472 ;; We need to loop from right to left.
473 (incf dst-word-offset words
)
474 (incf src-word-offset
(1- (ceiling (+ src-byte-offset length
) ,bytes-per-word
)))
476 (prev (funcall src-ref-fn src src-word-offset
)))
477 (declare (type word prev next
))
478 (flet ((get-next-src ()
480 (setf prev
(funcall src-ref-fn src
(decf src-word-offset
)))))
481 (declare (inline get-next-src
))
482 ,@(unless (= bytes-per-word
1)
483 `((unless (zerop final-bytes
)
484 (when (> final-bytes
(- ,bytes-per-word src-shift
))
486 (let ((value (word-logical-or
487 (shift-towards-end next
(* (- src-shift
) ,bitsize
))
488 (shift-towards-start prev
(* src-shift
,bitsize
))))
489 (mask (start-mask (* final-bytes
,bitsize
)))
490 (orig (funcall dst-ref-fn dst dst-word-offset
)))
491 (declare (type word mask orig value
))
492 (funcall dst-set-fn dst dst-word-offset
493 (word-logical-or (word-logical-and value mask
)
494 (word-logical-andc2 orig mask
)))))))
495 (decf dst-word-offset
)
496 (let ((end (- dst-word-offset interior
)))
498 ((<= dst-word-offset end
))
500 (let ((value (word-logical-or
501 (shift-towards-end next
(* (- src-shift
) ,bitsize
))
502 (shift-towards-start prev
(* src-shift
,bitsize
)))))
503 (declare (type word value
))
504 (funcall dst-set-fn dst dst-word-offset value
)
505 (decf dst-word-offset
))))
506 ,@(unless (= bytes-per-word
1)
507 `((unless (zerop dst-byte-offset
)
508 (if (> src-byte-offset dst-byte-offset
)
510 (setf next prev prev
0))
511 (let ((mask (end-mask (* (- dst-byte-offset
) ,bitsize
)))
512 (orig (funcall dst-ref-fn dst dst-word-offset
))
513 (value (word-logical-or
514 (shift-towards-start prev
(* src-shift
,bitsize
))
515 (shift-towards-end next
(* (- src-shift
) ,bitsize
)))))
516 (declare (type word mask orig value
))
517 (funcall dst-set-fn dst dst-word-offset
518 (word-logical-or (word-logical-and value mask
)
519 (word-logical-andc2 orig mask
)))))))))))))))))
522 ;; common uses for unary-byte-bashing
523 (defun ,array-copy-name
(src src-offset dst dst-offset length
)
524 (declare (type ,offset src-offset dst-offset length
))
525 (locally (declare (optimize (speed 3) (safety 1)))
526 (,unary-bash-name src src-offset dst dst-offset length
528 #'%set-vector-raw-bits
529 #'%vector-raw-bits
)))
531 (defun ,system-area-copy-name
(src src-offset dst dst-offset length
)
532 (declare (type ,offset src-offset dst-offset length
))
533 (locally (declare (optimize (speed 3) (safety 1)))
534 (multiple-value-bind (src src-offset
) (,fix-sap-and-offset-name src src-offset
)
535 (declare (type sb
!sys
:system-area-pointer src
))
536 (multiple-value-bind (dst dst-offset
) (,fix-sap-and-offset-name dst dst-offset
)
537 (declare (type sb
!sys
:system-area-pointer dst
))
538 (,unary-bash-name src src-offset dst dst-offset length
539 #'word-sap-ref
#'%set-word-sap-ref
542 (defun ,array-copy-to-system-area-name
(src src-offset dst dst-offset length
)
543 (declare (type ,offset src-offset dst-offset length
))
544 (locally (declare (optimize (speed 3) (safety 1)))
545 (multiple-value-bind (dst dst-offset
) (,fix-sap-and-offset-name dst dst-offset
)
546 (,unary-bash-name src src-offset dst dst-offset length
547 #'word-sap-ref
#'%set-word-sap-ref
548 #'%vector-raw-bits
))))
550 (defun ,system-area-copy-to-array-name
(src src-offset dst dst-offset length
)
551 (declare (type ,offset src-offset dst-offset length
))
552 (locally (declare (optimize (speed 3) (safety 1)))
553 (multiple-value-bind (src src-offset
) (,fix-sap-and-offset-name src src-offset
)
554 (,unary-bash-name src src-offset dst dst-offset length
556 #'%set-vector-raw-bits
557 #'word-sap-ref
)))))))
560 ;;; We would normally do this with a MACROLET, but then we run into
561 ;;; problems with the lexical environment being too hairy for the
562 ;;; cross-compiler and it cannot inline the basic basher functions.
563 #.
(loop for i
= 1 then
(* i
2)
564 collect
`(!define-sap-fixer
,i
) into fixers
565 collect
`(!define-byte-bashers
,i
) into bashers
566 until
(= i sb
!vm
:n-word-bits
)
567 ;; FIXERS must come first so their inline expansions are available
569 finally
(return `(progn ,@fixers
,@bashers
)))
571 ;;; a common idiom for calling COPY-TO-SYSTEM-AREA
573 ;;; Copy the entire contents of the vector V to memory starting at SAP+OFFSET.
574 (defun copy-byte-vector-to-system-area (bv sap
&optional
(offset 0))
575 ;; FIXME: There should be a type like SB!VM:BYTE so that we can write this
576 ;; type as (SIMPLE-ARRAY SB!VM:BYTE 1). Except BYTE is an external symbol of
577 ;; package CL, and shadowing it would be too ugly; so maybe SB!VM:VMBYTE?
578 ;; (And then N-BYTE-BITS would be N-VMBYTE-BITS and so forth?)
579 (declare (type (simple-array (unsigned-byte 8) 1) bv
))
580 (declare (type system-area-pointer sap
))
581 (declare (type fixnum offset
))
582 (copy-ub8-to-system-area bv
0 sap offset
(length bv
)))