* src/ops/bit.ops:
[parrot.git] / src / ops / bit.ops
blob96962eec18c98461dd82976e6bd0a63ee13fbc6a
1 /*
2 ** bit.ops
3 */
5  /* Signed shift operator that is compatible with PMC shifts.  This is
6   * guaranteed to produce the same result as bitwise_left_shift_internal modulo
7   * word size, ignoring the fact that Parrot integers are always signed.  This
8   * usually gives the same answer regardless whether you shift PMC operands and
9   * then assign to an I-reg, or move the operands to I-regs and do the shift
10   * there -- except when the true result is between 2^{w-1} and 2^w (where w is
11   * the word size), in which case the high order bit is taken as the sign,
12   * giving a truncated result that is 2^w lower.
13   */
14 #define bit_shift_left(number, bits) \
15     ((bits) >= 8*INTVAL_SIZE     ? 0                    \
16      : (bits) >= 0               ? (number) << (bits)   \
17      : (bits) > -8*INTVAL_SIZE   ? (number) >> -(bits)   \
18      : 0)
20 VERSION = PARROT_VERSION;
22 =head1 NAME
24 bit.ops - Bitwise Operations
26 =head1 DESCRIPTION
28 Operations that deal with bits directly, either individually
29 or in groups.
31 The variant with an appended B<s> like B<bands> work on strings.
33 The variants with a prepended B<n_> like <n_bnot> generate a new target PMC.
34 If possible, they use the appropriate language type, specified with C<.HLL>.
36 =over 4
38 =cut
40 ###############################################################################
42 =item B<band>(inout INT, in INT)
44 Set the bits of $1 according to the B<and> of the corresponding bits
45 from $1 and $2.
47 =item B<band>(out INT, in INT, in INT)
49 Set the bits of $1 according to the B<and> of the corresponding bits
50 from $2 and $3.
52 =cut
54 inline op band(inout INT, in INT) :base_core {
55   $1 &= $2;
56   goto NEXT();
59 inline op band(out INT, in INT, in INT) :base_core {
60   $1 = $2 & $3;
61   goto NEXT();
64 =item B<bands>(inout STR, in STR)
66 Set the bits of $1 according to the B<and> of the corresponding bits
67 from $1 and $2.
69 =item B<bands>(out STR, in STR, in STR)
71 Set the bits of $1 according to the B<and> of the corresponding bits
72 from $2 and $3.
74 =cut
76 inline op bands(inout STR, in STR) :base_core {
77   string_bitwise_and(interp, $1, $2, &$1);
78   goto NEXT();
81 inline op bands(out STR, in STR, in STR) :base_core {
82   $1 = string_bitwise_and(interp, $2, $3, NULL);
83   goto NEXT();
86 ########################################
88 =item B<bnot>(inout INT)
90 =item B<bnot>(invar PMC)
92 Sets $1 to C<bitwise not> $1 inplace.
94 =item B<bnot>(out INT, in INT)
96 =item B<bnot>(out PMC, invar PMC)
98 =item B<n_bnot>(out PMC, invar PMC)
100 Set the bits of $1 to the B<not> of the corresponding bits from $2.
102 =cut
104 inline op bnot(inout INT) :base_core {
105   $1 = ~ $1;
106   goto NEXT();
109 inline op bnot(out INT, in INT) :base_core {
110   $1 = ~ $2;
111   goto NEXT();
114 inline op bnot(invar PMC) :base_core {
115   $1->vtable->i_bitwise_not(interp, $1);
116   goto NEXT();
119 inline op bnot(out PMC, invar PMC) :base_core {
120   $1 = $2->vtable->bitwise_not(interp, $2, $1);
121   goto NEXT();
124 inline op n_bnot(out PMC, invar PMC) :base_core {
125   $1 = $2->vtable->bitwise_not(interp, $2, NULL);
126   goto NEXT();
129 =item B<bnots>(inout STR)
131 =item B<bnots>(invar PMC)
133 =item B<bnots>(out STR, in STR)
135 =item B<bnots>(out PMC, invar PMC)
137 =item B<n_bnots>(out PMC, invar PMC)
139 Set the bits of $1 to the B<not> of the corresponding bits from $2.
141 =cut
143 inline op bnots(inout STR) :base_core {
144   string_bitwise_not(interp, $1, &$1);
145   goto NEXT();
148 inline op bnots(out STR, in STR) :base_core {
149   string_bitwise_not(interp, $2, &$1);
150   goto NEXT();
153 inline op bnots(invar PMC) :base_core {
154   $1->vtable->i_bitwise_nots(interp, $1);
155   goto NEXT();
158 inline op bnots(out PMC, invar PMC) :base_core {
159   $1 = $2->vtable->bitwise_nots(interp, $2, $1);
160   goto NEXT();
163 inline op n_bnots(out PMC, invar PMC) :base_core {
164   $1 = $2->vtable->bitwise_nots(interp, $2, NULL);
165   goto NEXT();
168 ########################################
170 =item B<bor>(inout INT, in INT)
172 Set the bits of $1 according to the B<or> of the corresponding bits
173 from $1 and $2.
175 =item B<bor>(out INT, in INT, in INT)
177 Set the bits of $1 according to the B<or> of the corresponding bits
178 from $2 and $3.
180 =cut
182 inline op bor(inout INT, in INT) :base_core {
183   $1 |= $2;
184   goto NEXT();
187 inline op bor(out INT, in INT, in INT) :base_core {
188   $1 = $2 | $3;
189   goto NEXT();
192 =item B<bors>(inout STR, in STR)
194 Set the bits of $1 according to the B<or> of the corresponding bits
195 from $1 and $2.
197 =item B<bors>(out STR, in STR, in STR)
199 Set the bits of $1 according to the B<or> of the corresponding bits
200 from $2 and $3.
202 =cut
204 inline op bors(inout STR, in STR) :base_core {
205   string_bitwise_or(interp, $1, $2, &$1);
206   goto NEXT();
209 inline op bors(out STR, in STR, in STR) :base_core {
210   $1 = string_bitwise_or(interp, $2, $3, NULL);
211   goto NEXT();
214 ########################################
216 =item B<shl>(inout INT, in INT)
218 Shift left $1 by $2 bits.
220 =item B<shl>(out INT, in INT, in INT)
222 Set $1 to the value of $2 shifted left by $3 bits.
224 =cut
226 inline op shl(inout INT, in INT) :base_core {
227   $1 = bit_shift_left($1, $2);
228   goto NEXT();
231 inline op shl(out INT, in INT, in INT) :base_core {
232   $1 = bit_shift_left($2, $3);
233   goto NEXT();
236 ########################################
238 =item B<shr>(inout INT, in INT)
240 Shift right $1 by $2 bits.
242 =item B<shr>(out INT, in INT, in INT)
244 Set $1 to the value of $2 shifted right by $3 bits.
246 =cut
248 inline op shr(inout INT, in INT) :base_core {
249   INTVAL signed_shift = -$2;
250   $1 = bit_shift_left($1, signed_shift);
251   goto NEXT();
254 inline op shr(out INT, in INT, in INT) :base_core {
255   INTVAL signed_shift = -$3;
256   $1 = bit_shift_left($2, signed_shift);
257   goto NEXT();
260 ########################################
262 =item B<lsr>(out INT, in INT)
264 Shift $1 logically shifted right by $2 bits.
266 =item B<lsr>(out INT, in INT, in INT)
268 Set $1 to the value of $2 logically shifted right by $3 bits.
270 =cut
272 inline op lsr(out INT, in INT) :base_core {
273   /*
274    * lvalue casts are evil, but this one isn't evil enough to kill.
275    * it's just casting a signed integral to the equivalent unsigned.
276    */
277   LVALUE_CAST(UINTVAL, $1) >>= $2;
278   goto NEXT();
281 inline op lsr(out INT, in INT, in INT) :base_core {
282   $1 = (INTVAL)((UINTVAL)$2 >> $3);
283   goto NEXT();
286 =item B<rot>(out INT, in INT, in INT, inconst INT)
288 Rotate $2 left or right by $3 and place result in $1.
289 $4 is the amount of bits to rotate, 32 bit on a 32-bit CPU and 32 or 64
290 on a 64-bit CPU. If the rotate count is negative a rotate right by ($3+$4)
291 is performed.
293 =cut
295 inline op rot(out INT, in INT, in INT, inconst INT) {
296   const INTVAL r = $2;
297   INTVAL s = $3;
298   const INTVAL w = $4;
299   INTVAL d, t;
300   if (s < 0)
301     s += w;
302   d = r << s;
303   t = w - s;
304   t = (INTVAL)((UINTVAL)r >> t);
305   d |= t;
306   $1 = d;
307   goto NEXT();
313 ########################################
315 =item B<bxor>(inout INT, in INT)
317 Set the bits of $1 according to the B<xor> of the corresponding bits
318 from $1 and $2.
320 =item B<bxor>(out INT, in INT, in INT)
322 Set the bits of $1 according to the B<xor> of the corresponding bits
323 from $2 and $3.
325 =cut
327 inline op bxor(inout INT, in INT) :base_core {
328   $1 ^= $2;
329   goto NEXT();
332 inline op bxor(out INT, in INT, in INT) :base_core {
333   $1 = $2 ^ $3;
334   goto NEXT();
337 =item B<bxors>(inout STR, in STR)
339 Set the bits of $1 according to the B<xor> of the corresponding bits
340 from $1 and $2.
342 =item B<bxors>(out STR, in STR, in STR)
344 Set the bits of $1 according to the B<xor> of the corresponding bits
345 from $2 and $3.
347 =cut
349 inline op bxors(inout STR, in STR) :base_core {
350   string_bitwise_xor(interp, $1, $2, &$1);
351   goto NEXT();
354 inline op bxors(out STR, in STR, in STR) :base_core {
355   $1 = string_bitwise_xor(interp, $2, $3, NULL);
356   goto NEXT();
359 =back
361 =cut
363 ###############################################################################
365 =head1 COPYRIGHT
367 Copyright (C) 2001-2006, The Perl Foundation.
369 =head1 LICENSE
371 This program is free software. It is subject to the same license
372 as the Parrot interpreter itself.
374 =cut
377  * Local variables:
378  *   c-file-style: "parrot"
379  * End:
380  * vim: expandtab shiftwidth=4:
381  */