0.8.17.17:
[sbcl.git] / src / compiler / mips / sap.lisp
1 ;;;; the MIPS VM definition of SAP operations
2
3 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; more information.
5 ;;;;
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.
11
12 (in-package "SB!VM")
13 \f
14 ;;;; Moves and coercions:
15
16 ;;; Move a tagged SAP to an untagged representation.
17 (define-vop (move-to-sap)
18   (:args (x :scs (descriptor-reg)))
19   (:results (y :scs (sap-reg)))
20   (:note "system area pointer indirection")
21   (:generator 1
22     (loadw y x sap-pointer-slot other-pointer-lowtag)))
23
24 (define-move-vop move-to-sap :move
25   (descriptor-reg) (sap-reg))
26
27 ;;; Move an untagged SAP to a tagged representation.
28 (define-vop (move-from-sap)
29   (:args (x :scs (sap-reg) :target sap))
30   (:temporary (:scs (sap-reg) :from (:argument 0)) sap)
31   (:temporary (:scs (non-descriptor-reg)) ndescr)
32   (:temporary (:sc non-descriptor-reg :offset nl4-offset) pa-flag)
33   (:results (y :scs (descriptor-reg)))
34   (:note "system area pointer allocation")
35   (:generator 20
36     (move sap x)
37     (with-fixed-allocation (y pa-flag ndescr sap-widetag sap-size)
38       (storew sap y sap-pointer-slot other-pointer-lowtag))))
39
40 (define-move-vop move-from-sap :move
41   (sap-reg) (descriptor-reg))
42
43 ;;; Move untagged sap values.
44 (define-vop (sap-move)
45   (:args (x :target y
46             :scs (sap-reg)
47             :load-if (not (location= x y))))
48   (:results (y :scs (sap-reg)
49                :load-if (not (location= x y))))
50   (:effects)
51   (:affected)
52   (:generator 0
53     (move y x)))
54
55 (define-move-vop sap-move :move
56   (sap-reg) (sap-reg))
57
58 ;;; Move untagged sap arguments/return-values.
59 (define-vop (move-sap-arg)
60   (:args (x :target y
61             :scs (sap-reg))
62          (fp :scs (any-reg)
63              :load-if (not (sc-is y sap-reg))))
64   (:results (y))
65   (:generator 0
66     (sc-case y
67       (sap-reg
68        (move y x))
69       (sap-stack
70        (storew x fp (tn-offset y))))))
71
72 (define-move-vop move-sap-arg :move-arg
73   (descriptor-reg sap-reg) (sap-reg))
74
75 ;;; Use standard MOVE-ARG + coercion to move an untagged sap to a
76 ;;; descriptor passing location.
77 (define-move-vop move-arg :move-arg
78   (sap-reg) (descriptor-reg))
79 \f
80 ;;;; SAP-INT and INT-SAP
81 (define-vop (sap-int)
82   (:args (sap :scs (sap-reg) :target int))
83   (:arg-types system-area-pointer)
84   (:results (int :scs (unsigned-reg)))
85   (:result-types unsigned-num)
86   (:translate sap-int)
87   (:policy :fast-safe)
88   (:generator 1
89     (move int sap)))
90
91 (define-vop (int-sap)
92   (:args (int :scs (unsigned-reg) :target sap))
93   (:arg-types unsigned-num)
94   (:results (sap :scs (sap-reg)))
95   (:result-types system-area-pointer)
96   (:translate int-sap)
97   (:policy :fast-safe)
98   (:generator 1
99     (move sap int)))
100 \f
101 ;;;; POINTER+ and POINTER-
102 (define-vop (pointer+)
103   (:translate sap+)
104   (:args (ptr :scs (sap-reg))
105          (offset :scs (signed-reg immediate)))
106   (:arg-types system-area-pointer signed-num)
107   (:results (res :scs (sap-reg)))
108   (:result-types system-area-pointer)
109   (:policy :fast-safe)
110   (:generator 1
111     (sc-case offset
112       (signed-reg
113        (inst addu res ptr offset))
114       (immediate
115        (inst addu res ptr (tn-value offset))))))
116
117 (define-vop (pointer-)
118   (:translate sap-)
119   (:args (ptr1 :scs (sap-reg))
120          (ptr2 :scs (sap-reg)))
121   (:arg-types system-area-pointer system-area-pointer)
122   (:policy :fast-safe)
123   (:results (res :scs (signed-reg)))
124   (:result-types signed-num)
125   (:generator 1
126     (inst subu res ptr1 ptr2)))
127 \f
128 ;;;; mumble-SYSTEM-REF and mumble-SYSTEM-SET
129 (macrolet ((def-system-ref-and-set
130           (ref-name set-name sc type size &optional signed)
131   (let ((ref-name-c (symbolicate ref-name "-C"))
132         (set-name-c (symbolicate set-name "-C")))
133     `(progn
134        (define-vop (,ref-name)
135          (:translate ,ref-name)
136          (:policy :fast-safe)
137          (:args (object :scs (sap-reg) :target sap)
138                 (offset :scs (signed-reg)))
139          (:arg-types system-area-pointer signed-num)
140          (:results (result :scs (,sc)))
141          (:result-types ,type)
142          (:temporary (:scs (sap-reg) :from (:argument 0)) sap)
143          (:generator 5
144            (inst addu sap object offset)
145            ,@(ecase size
146                (:byte
147                 (if signed
148                     '((inst lb result sap 0))
149                     '((inst lbu result sap 0))))
150                  (:short
151                   (if signed
152                       '((inst lh result sap 0))
153                       '((inst lhu result sap 0))))
154                  (:long
155                   '((inst lw result sap 0)))
156                  (:single
157                   '((inst lwc1 result sap 0)))
158                  (:double
159                   (ecase *backend-byte-order*
160                     (:big-endian
161                      '((inst lwc1 result sap n-word-bytes)
162                        (inst lwc1-odd result sap 0)))
163                     (:little-endian
164                      '((inst lwc1 result sap 0)
165                        (inst lwc1-odd result sap n-word-bytes))))))
166            (inst nop)))
167        (define-vop (,ref-name-c)
168          (:translate ,ref-name)
169          (:policy :fast-safe)
170          (:args (object :scs (sap-reg)))
171          (:arg-types system-area-pointer
172                      (:constant ,(if (eq size :double)
173                                      ;; We need to be able to add 4.
174                                      `(integer ,(- (ash 1 16))
175                                                ,(- (ash 1 16) 5))
176                                      '(signed-byte 16))))
177          (:info offset)
178          (:results (result :scs (,sc)))
179          (:result-types ,type)
180          (:generator 4
181            ,@(ecase size
182                (:byte
183                 (if signed
184                     '((inst lb result object offset))
185                     '((inst lbu result object offset))))
186                (:short
187                 (if signed
188                     '((inst lh result object offset))
189                     '((inst lhu result object offset))))
190                (:long
191                 '((inst lw result object offset)))
192                (:single
193                 '((inst lwc1 result object offset)))
194                (:double
195                 (ecase *backend-byte-order*
196                   (:big-endian
197                    '((inst lwc1 result object (+ offset n-word-bytes))
198                      (inst lwc1-odd result object offset)))
199                   (:little-endian
200                    '((inst lwc1 result object offset)
201                      (inst lwc1-odd result object (+ offset n-word-bytes)))))))
202            (inst nop)))
203        (define-vop (,set-name)
204          (:translate ,set-name)
205          (:policy :fast-safe)
206          (:args (object :scs (sap-reg) :target sap)
207                 (offset :scs (signed-reg))
208                 (value :scs (,sc) :target result))
209          (:arg-types system-area-pointer signed-num ,type)
210          (:results (result :scs (,sc)))
211          (:result-types ,type)
212          (:temporary (:scs (sap-reg) :from (:argument 0)) sap)
213          (:generator 5
214            (inst addu sap object offset)
215            ,@(ecase size
216                (:byte
217                 '((inst sb value sap 0)
218                   (move result value)))
219                (:short
220                 '((inst sh value sap 0)
221                   (move result value)))
222                (:long
223                 '((inst sw value sap 0)
224                   (move result value)))
225                (:single
226                 '((inst swc1 value sap 0)
227                   (unless (location= result value)
228                     (inst fmove :single result value))))
229                (:double
230                 (ecase *backend-byte-order*
231                   (:big-endian
232                    '((inst swc1 value sap n-word-bytes)
233                      (inst swc1-odd value sap 0)
234                      (unless (location= result value)
235                        (inst fmove :double result value))))
236                   (:little-endian
237                    '((inst swc1 value sap 0)
238                      (inst swc1-odd value sap n-word-bytes)
239                      (unless (location= result value)
240                        (inst fmove :double result value)))))))))
241        (define-vop (,set-name-c)
242          (:translate ,set-name)
243          (:policy :fast-safe)
244          (:args (object :scs (sap-reg))
245                 (value :scs (,sc) :target result))
246          (:arg-types system-area-pointer
247                      (:constant ,(if (eq size :double)
248                                      ;; We need to be able to add 4.
249                                      `(integer ,(- (ash 1 16))
250                                                ,(- (ash 1 16) 5))
251                                      '(signed-byte 16)))
252                      ,type)
253          (:info offset)
254          (:results (result :scs (,sc)))
255          (:result-types ,type)
256          (:generator 5
257            ,@(ecase size
258                (:byte
259                 '((inst sb value object offset)
260                   (move result value)))
261                (:short
262                 '((inst sh value object offset)
263                   (move result value)))
264                (:long
265                 '((inst sw value object offset)
266                   (move result value)))
267                (:single
268                 '((inst swc1 value object offset)
269                   (unless (location= result value)
270                     (inst fmove :single result value))))
271                (:double
272                 (ecase *backend-byte-order*
273                   (:big-endian
274                    '((inst swc1 value object (+ offset n-word-bytes))
275                      (inst swc1-odd value object (+ offset n-word-bytes))
276                      (unless (location= result value)
277                        (inst fmove :double result value))))
278                   (:little-endian
279                    '((inst swc1 value object offset)
280                      (inst swc1-odd value object (+ offset n-word-bytes))
281                      (unless (location= result value)
282                        (inst fmove :double result value)))))))))))))
283   (def-system-ref-and-set sap-ref-8 %set-sap-ref-8
284     unsigned-reg positive-fixnum :byte nil)
285   (def-system-ref-and-set signed-sap-ref-8 %set-signed-sap-ref-8
286     signed-reg tagged-num :byte t)
287   (def-system-ref-and-set sap-ref-16 %set-sap-ref-16
288     unsigned-reg positive-fixnum :short nil)
289   (def-system-ref-and-set signed-sap-ref-16 %set-signed-sap-ref-16
290     signed-reg tagged-num :short t)
291   (def-system-ref-and-set sap-ref-32 %set-sap-ref-32
292     unsigned-reg unsigned-num :long nil)
293   (def-system-ref-and-set signed-sap-ref-32 %set-signed-sap-ref-32
294     signed-reg signed-num :long t)
295   (def-system-ref-and-set sap-ref-sap %set-sap-ref-sap
296     sap-reg system-area-pointer :long)
297   (def-system-ref-and-set sap-ref-single %set-sap-ref-single
298     single-reg single-float :single)
299   (def-system-ref-and-set sap-ref-double %set-sap-ref-double
300     double-reg double-float :double))
301 \f
302 ;;; Noise to convert normal lisp data objects into SAPs.
303 (define-vop (vector-sap)
304   (:translate vector-sap)
305   (:policy :fast-safe)
306   (:args (vector :scs (descriptor-reg)))
307   (:results (sap :scs (sap-reg)))
308   (:result-types system-area-pointer)
309   (:generator 2
310     (inst addu sap vector
311           (- (* vector-data-offset n-word-bytes) other-pointer-lowtag))))
312 \f
313 ;;; Transforms for 64-bit SAP accessors.
314 #!+little-endian
315 (progn
316   (deftransform sap-ref-64 ((sap offset) (* *))
317     '(logior (sap-ref-32 sap offset)
318              (ash (sap-ref-32 sap (+ offset 4)) 32)))
319   (deftransform signed-sap-ref-64 ((sap offset) (* *))
320     '(logior (sap-ref-32 sap offset)
321              (ash (signed-sap-ref-32 sap (+ offset 4)) 32)))
322   (deftransform %set-sap-ref-64 ((sap offset value) (* * *))
323     '(progn
324        (%set-sap-ref-32 sap offset (logand value #xffffffff))
325        (%set-sap-ref-32 sap (+ offset 4) (ash value -32))))
326   (deftransform %set-signed-sap-ref-64 ((sap offset value) (* * *))
327     '(progn
328        (%set-sap-ref-32 sap offset (logand value #xffffffff))
329        (%set-signed-sap-ref-32 sap (+ offset 4) (ash value -32)))))
330 #!-little-endian
331 (progn
332   (deftransform sap-ref-64 ((sap offset) (* *))
333     '(logior (ash (sap-ref-32 sap offset) 32)
334              (sap-ref-32 sap (+ offset 4))))
335   (deftransform signed-sap-ref-64 ((sap offset) (* *))
336     '(logior (ash (signed-sap-ref-32 sap offset) 32)
337              (sap-ref-32 sap (+ 4 offset))))
338   (deftransform %set-sap-ref-64 ((sap offset value) (* * *))
339     '(progn
340        (%set-sap-ref-32 sap offset (ash value -32))
341        (%set-sap-ref-32 sap (+ offset 4) (logand value #xffffffff))))
342   (deftransform %set-signed-sap-ref-64 ((sap offset value) (* * *))
343     '(progn
344        (%set-signed-sap-ref-32 sap offset (ash value -32))
345        (%set-sap-ref-32 sap (+ 4 offset) (logand value #xffffffff)))))
346