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