3b2307ec0dbcdcfa0e074242f83b3e4dee672e71
[sbcl.git] / src / compiler / x86-64 / char.lisp
1 ;;;; x86-64 definition of character 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 ;;; Space optimization: As the upper 32 bits of (tagged or untagged)
15 ;;; characters are always zero many operations can be done on 32-bit
16 ;;; registers. This often leads to smaller encodings as the REX prefix
17 ;;; is then only needed if registers R8 - R15 are used.
18
19 ;;;; moves and coercions
20
21 ;;; Move a tagged char to an untagged representation.
22 #!+sb-unicode
23 (define-vop (move-to-character)
24   (:args (x :scs (any-reg descriptor-reg) :target y
25             :load-if (not (location= x y))))
26   (:results (y :scs (character-reg)
27                :load-if (not (location= x y))))
28   (:note "character untagging")
29   (:generator 1
30     (let ((y-dword (make-dword-tn y)))
31       (move y-dword (make-dword-tn x))
32       (inst shr y-dword n-widetag-bits))))
33 #!-sb-unicode
34 (define-vop (move-to-character)
35   (:args (x :scs (any-reg control-stack)))
36   (:results (y :scs (character-reg #+nil character-stack)))
37   (:note "character untagging")
38   (:generator 1
39     (let ((y-wide-tn (make-random-tn
40                       :kind :normal
41                       :sc (sc-or-lose 'any-reg)
42                       :offset (tn-offset y))))
43       (move y-wide-tn x)
44       (inst shr y-wide-tn 8)
45       (inst and y-wide-tn #xff))))
46 (define-move-vop move-to-character :move
47   (any-reg #!-sb-unicode control-stack)
48   (character-reg))
49
50 ;;; Move an untagged char to a tagged representation.
51 #!+sb-unicode
52 (define-vop (move-from-character)
53   (:args (x :scs (character-reg) :target y))
54   (:results (y :scs (any-reg descriptor-reg)))
55   (:note "character tagging")
56   (:generator 1
57     (let ((y-dword (make-dword-tn y)))
58       (unless (location= x y)
59         (inst mov y-dword (make-dword-tn x)))
60       (inst shl y-dword n-widetag-bits)
61       (inst or y-dword character-widetag))))
62 #!-sb-unicode
63 (define-vop (move-from-character)
64   (:args (x :scs (character-reg character-stack)))
65   (:results (y :scs (any-reg descriptor-reg #+nil control-stack)))
66   (:note "character tagging")
67   (:generator 1
68     (move (make-random-tn :kind :normal :sc (sc-or-lose 'character-reg)
69                           :offset (tn-offset y))
70           x)
71     (inst shl y n-widetag-bits)
72     (inst or y character-widetag)
73     (inst and y #xffff)))
74 (define-move-vop move-from-character :move
75   (character-reg)
76   (any-reg descriptor-reg #!-sb-unicode control-stack))
77
78 ;;; Move untagged character values.
79 (define-vop (character-move)
80   (:args (x :target y
81             :scs (character-reg)
82             :load-if (not (location= x y))))
83   (:results (y :scs (character-reg character-stack)
84                :load-if (not (location= x y))))
85   (:note "character move")
86   (:effects)
87   (:affected)
88   (:generator 0
89     (move y x)))
90 (define-move-vop character-move :move
91   (character-reg) (character-reg character-stack))
92
93 ;;; Move untagged character arguments/return-values.
94 (define-vop (move-character-arg)
95   (:args (x :target y
96             :scs (character-reg))
97          (fp :scs (any-reg)
98              :load-if (not (sc-is y character-reg))))
99   (:results (y))
100   (:note "character arg move")
101   (:generator 0
102     (sc-case y
103       (character-reg
104        (move y x))
105       (character-stack
106        #!-sb-unicode
107        (inst mov
108              ;; FIXME: naked 8 (should be... what?  n-register-bytes?
109              ;; n-word-bytes?  Dunno.
110              (make-ea :byte :base fp :disp (- (* (1+ (tn-offset y)) 8)))
111              x)
112        #!+sb-unicode
113        (if (= (tn-offset fp) esp-offset)
114            (storew x fp (tn-offset y)) ; c-call
115            (storew x fp (- (1+ (tn-offset y)))))))))
116 (define-move-vop move-character-arg :move-arg
117   (any-reg character-reg) (character-reg))
118
119 ;;; Use standard MOVE-ARG + coercion to move an untagged character
120 ;;; to a descriptor passing location.
121 (define-move-vop move-arg :move-arg
122   (character-reg) (any-reg descriptor-reg))
123 \f
124 ;;;; other operations
125
126 (define-vop (char-code)
127   (:translate char-code)
128   (:policy :fast-safe)
129   (:args #!-sb-unicode (ch :scs (character-reg character-stack))
130          #!+sb-unicode (ch :scs (character-reg character-stack) :target res))
131   (:arg-types character)
132   (:results (res :scs (unsigned-reg)))
133   (:result-types positive-fixnum)
134   (:generator 1
135     #!-sb-unicode
136     (inst movzx res ch)
137     #!+sb-unicode
138     (move res ch)))
139
140 #!+sb-unicode
141 (define-vop (code-char)
142   (:translate code-char)
143   (:policy :fast-safe)
144   (:args (code :scs (unsigned-reg unsigned-stack) :target res))
145   (:arg-types positive-fixnum)
146   (:results (res :scs (character-reg)))
147   (:result-types character)
148   (:generator 1
149     (move res code)))
150 #!-sb-unicode
151 (define-vop (code-char)
152   (:translate code-char)
153   (:policy :fast-safe)
154   (:args (code :scs (unsigned-reg unsigned-stack) :target eax))
155   (:arg-types positive-fixnum)
156   (:temporary (:sc unsigned-reg :offset rax-offset :target res
157                    :from (:argument 0) :to (:result 0))
158               eax)
159   (:results (res :scs (character-reg)))
160   (:result-types character)
161   (:generator 1
162     (move eax code)
163     (move res al-tn)))
164 \f
165 ;;; comparison of CHARACTERs
166 (define-vop (character-compare)
167   (:args (x :scs (character-reg character-stack))
168          (y :scs (character-reg)
169             :load-if (not (and (sc-is x character-reg)
170                                (sc-is y character-stack)))))
171   (:arg-types character character)
172   (:conditional)
173   (:info target not-p)
174   (:policy :fast-safe)
175   (:note "inline comparison")
176   (:variant-vars condition not-condition)
177   (:generator 3
178     (inst cmp x y)
179     (inst jmp (if not-p not-condition condition) target)))
180
181 (define-vop (fast-char=/character character-compare)
182   (:translate char=)
183   (:variant :e :ne))
184
185 (define-vop (fast-char</character character-compare)
186   (:translate char<)
187   (:variant :b :nb))
188
189 (define-vop (fast-char>/character character-compare)
190   (:translate char>)
191   (:variant :a :na))
192
193 (define-vop (character-compare/c)
194   (:args (x :scs (character-reg character-stack)))
195   (:arg-types character (:constant character))
196   (:conditional)
197   (:info target not-p y)
198   (:policy :fast-safe)
199   (:note "inline constant comparison")
200   (:variant-vars condition not-condition)
201   (:generator 2
202     (inst cmp x (sb!xc:char-code y))
203     (inst jmp (if not-p not-condition condition) target)))
204
205 (define-vop (fast-char=/character/c character-compare/c)
206   (:translate char=)
207   (:variant :e :ne))
208
209 (define-vop (fast-char</character/c character-compare/c)
210   (:translate char<)
211   (:variant :b :nb))
212
213 (define-vop (fast-char>/character/c character-compare/c)
214   (:translate char>)
215   (:variant :a :na))