* t/op/lexicals-2.t (added), MANIFEST:
[parrot.git] / t / op / bitwise.t
blobcecccde2bc1ea91f594a30e0e9d7fafe5fe7c8d0
1 #!perl
2 # Copyright (C) 2001-2005, The Perl Foundation.
3 # $Id$
5 use strict;
6 use warnings;
7 use lib qw( . lib ../lib ../../lib );
8 use Test::More;
9 use Parrot::Test tests => 27;
10 use Parrot::Config;
12 =head1 NAME
14 t/op/bitwise.t - Bitwise Ops
16 =head1 SYNOPSIS
18         % prove t/op/bitwise.t
20 =head1 DESCRIPTION
22 Tests various bitwise logical operations.
24 =cut
26 pasm_output_is( <<'CODE', <<'OUTPUT', "shr_i_i_i (>>)" );
27         set I0, 0b001100
28         set I1, 0b010100
29         set I2, 1
30         set I3, 2
31         shr I4, I0, I2
32         shr I2, I0, I2
33         shr I1, I1, I3
34         print I4
35         print "\n"
36         print I2
37         print "\n"
38         print I1
39         print "\n"
40         print I0
41         print "\n"
42         end
43 CODE
48 OUTPUT
50 pasm_output_is( <<'CODE', <<'OUTPUT', "shr_i_i (>>)" );
51         set I0, 0b001100
52         set I1, 0b010100
53         set I2, 1
54         set I3, 2
55         shr I0, I2
56         shr I1, I3
57         print I0
58         print "\n"
59         print I1
60         print "\n"
61         end
62 CODE
65 OUTPUT
67 pasm_output_is( <<'CODE', <<'OUTPUT', "shr_i_i_ic (>>)" );
68         set     I0, 0b001100
69         set     I1, 0b010100
70         shr     I2, I0, 1
71         shr     I1, I1, 2
72         print   I2
73         print   "\n"
74         print   I1
75         print   "\n"
76         print   I0
77         print   "\n"
78         end
79 CODE
83 OUTPUT
85 pasm_output_is( <<'CODE', <<'OUTPUT', "shr_i_ic_i (>>)" );
86         set I0, 1
87         set I1, 2
88         shr I2, 0b001100, I0
89         shr I1, 0b010100, I1
90         print I2
91         print "\n"
92         print I1
93         print "\n"
94         end
95 CODE
98 OUTPUT
100 pasm_output_is( <<'CODE', <<'OUTPUT', "shr_i_ic_ic (>>)" );
101         shr I2, 0b001100, 1
102         shr I1, 0b010100, 2
103         print I2
104         print "\n"
105         print I1
106         print "\n"
107         end
108 CODE
111 OUTPUT
113 # The crux of this test is that a proper logical right shift
114 # will clear the most significant bit, so the shifted value
115 # will be a positive value on any 2's or 1's complement CPU
116 pasm_output_is( <<'CODE', <<'OUTPUT', "lsr_i_ic_ic (>>)" );
117         lsr I2, -40, 1
118         lt I2, 0, BAD
119         print "OK\n"
120         end
121 BAD:
122         print "Not OK"
123         print "\n"
124         end
125 CODE
127 OUTPUT
129 pasm_output_is( <<'CODE', <<'OUTPUT', "lsr_i_ic (>>)" );
130         set I2, -100
131         lsr I2, 1
132         lt I2, 0, BAD
133         print "OK\n"
134         end
135 BAD:
136         print "Not OK"
137         print "\n"
138         end
139 CODE
141 OUTPUT
143 pasm_output_is( <<'CODE', <<'OUTPUT', "lsr_i_i_i (>>)" );
144         set I0, -40
145         set I1, 1
146         lsr I2, I0, I1
147         lt I2, 0, BAD
148         print "OK\n"
149         end
150 BAD:
151         print "Not OK"
152         print "\n"
153         end
154 CODE
156 OUTPUT
158 # ... and the missing op signature was untested and wrong in JIT/i386
159 pasm_output_is( <<'CODE', <<'OUTPUT', "lsr_i_i_ic (>>)" );
160         set I0, -40
161         lsr I2, I0, 1
162         lt I2, 0, BAD
163         print "OK\n"
164         end
165 BAD:
166         print "Not OK"
167         print "\n"
168         end
169 CODE
171 OUTPUT
173 pasm_output_is( <<'CODE', <<'OUTPUT', "shr_i_i_ic (>>) negative" );
174         set I0, -40
175         shr I2, I0, 1
176         ge I2, 0, BAD
177         print "OK\n"
178         end
179 BAD:
180         print "Not OK"
181         print "\n"
182         end
183 CODE
185 OUTPUT
186 pasm_output_is( <<'CODE', <<'OUTPUT', "shl_i_i_i (<<)" );
187         set I0, 0b001100
188         set I1, 0b010100
189         set I2, 2
190         set I3, 1
191         shl I4, I0, I2
192         shl I2, I0, I2
193         shl I1, I1, I3
194         print I4
195         print "\n"
196         print I2
197         print "\n"
198         print I1
199         print "\n"
200         print I0
201         print "\n"
202         end
203 CODE
208 OUTPUT
210 pasm_output_is( <<'CODE', <<'OUTPUT', "shl_i_i_ic (<<)" );
211         set I0, 0b001100
212         set I1, 0b010100
213         shl I2, I0, 2
214         shl I1, I1, 1
215         print I2
216         print "\n"
217         print I1
218         print "\n"
219         print I0
220         print "\n"
221         end
222 CODE
226 OUTPUT
228 pasm_output_is( <<'CODE', <<'OUTPUT', "shl_i_ic_i (<<)" );
229         set I0, 2
230         set I1, 1
231         shl I2, 0b001100, I0
232         shl I1, 0b010100, I1
233         print I2
234         print "\n"
235         print I1
236         print "\n"
237         end
238 CODE
241 OUTPUT
243 pasm_output_is( <<'CODE', <<'OUTPUT', "shl_i_ic_ic (<<)" );
244         shl I2, 0b001100, 2
245         shl I1, 0b010100, 1
246         print I2
247         print "\n"
248         print I1
249         print "\n"
250         end
251 CODE
254 OUTPUT
256 pasm_output_is( <<'CODE', <<'OUTPUT', "shl_i_i (<<)" );
257         set I0, 0b001100
258         set I1, 0b010100
259         set I2, 1
260         set I3, 2
261         shl I0, I2
262         shl I1, I3
263         print I0
264         print "\n"
265         print I1
266         print "\n"
267         end
268 CODE
271 OUTPUT
273 pasm_output_is( <<'CODE', <<'OUTPUT', "bxor_i_i_i (^)" );
274         set     I0, 0b001100
275         set     I1, 0b100110
276         bxor    I2, I0, I1
277         print   I2
278         print   "\n"
279         bxor    I1, I0, I1
280         print   I1
281         print   "\n"
282         print   I0
283         print   "\n"
284         end
285 CODE
289 OUTPUT
291 pasm_output_is( <<'CODE', <<'OUTPUT', "bxor_i_i_ic (^)" );
292         set I0, 0b001100
293         bxor I2, I0, 0b100110
294         print I2
295         print "\n"
296         print I0
297         print "\n"
298         bxor I0, I0, 0b100110
299         print I0
300         print "\n"
301         end
302 CODE
306 OUTPUT
308 pasm_output_is( <<'CODE', <<'OUTPUT', "bxor_i|ic (^)" );
309         set I0, 0b001100
310         set I2, 0b000011
311         bxor I2, I0
312         print I2
313         print "\n"
315         set I2, 0b001100
316         bxor  I2, I0
317         print I2
318         print "\n"
320         set I2, 0b101010
321         bxor I2, I2
322         print I2
323         print "\n"
325         set I2, 0b010101
326         bxor I2, 0b000011
327         print I2
328         print "\n"
330         end
331 CODE
336 OUTPUT
338 pasm_output_is( <<'CODE', <<'OUTPUT', "band_i_i_i (&)" );
339         set     I0, 0b001100
340         set     I1, 0b010110
341         band    I2, I0,I1
342         print   I2
343         print   "\n"
344         band    I1,I0,I1
345         print   I1
346         print   "\n"
347         print   I0
348         print   "\n"
349         end
350 CODE
354 OUTPUT
356 pasm_output_is( <<'CODE', <<'OUTPUT', "band_i_i_ic (&)" );
357         set I0, 0b001100
358         band I2, I0,0b010110
359         print I2
360         print "\n"
361         print I0
362         print "\n"
363         band I0,I0,0b010110
364         print I0
365         print "\n"
366         end
367 CODE
371 OUTPUT
373 pasm_output_is( <<'CODE', <<'OUTPUT', "band_i_i|ic (&)" );
374         set I0, 0b001100
375         set I2, 0b000011
376         band I2, I0
377         print I2
378         print "\n"
380         set I2, 0b001100
381         band  I2, I0
382         print I2
383         print "\n"
385         set I2, 0b101010
386         band I2, I2
387         print I2
388         print "\n"
390         set I2, 0b010101
391         band I2, 0b000011
392         print I2
393         print "\n"
395         end
396 CODE
401 OUTPUT
403 pasm_output_is( <<'CODE', <<'OUTPUT', "bor_i_i_i (|)" );
404         set I0, 0b001100
405         set I1, 0b010110
406         bor I2, I0,I1
407         print I2
408         print "\n"
409         bor I1,I0,I1
410         print I1
411         print "\n"
412         print I0
413         print "\n"
414         end
415 CODE
419 OUTPUT
421 pasm_output_is( <<'CODE', <<'OUTPUT', "bor_i_i_ic (|)" );
422         set I0, 0b001100
423         bor I2, I0,0b010110
424         print I2
425         print "\n"
426         print I0
427         print "\n"
428         bor I0,I0,0b010110
429         print I0
430         print "\n"
431         end
432 CODE
436 OUTPUT
438 pasm_output_is( <<'CODE', <<'OUTPUT', "bor_i_i|ic (|)" );
439         set I0, 0b001100
440         set I2, 0b000011
441         bor I2, I0
442         print I2
443         print "\n"
445         set I2, 0b001100
446         bor  I2, I0
447         print I2
448         print "\n"
450         set I2, 0b101010
451         bor I2, I2
452         print I2
453         print "\n"
455         set I2, 0b010101
456         bor I2, 0b000011
457         print I2
458         print "\n"
460         end
461 CODE
466 OUTPUT
468 # use C<and> to only check low order bits, this should be platform nice
469 pasm_output_is( <<'CODE', <<'OUTPUT', "bnot_i_i (~)" );
470         set     I0, 0b001100
471         set     I1, 0b001100
472         set     I31, 0b111111
473         bnot    I2, I0
474         band    I2, I2, I31
475         print   I2
476         print   "\n"
477         bnot    I1, I1
478         band    I1, I1, I31
479         print   I1
480         print   "\n"
481         print   I0
482         print   "\n"
483         end
484 CODE
488 OUTPUT
490 my $int_bits = $PConfig{intvalsize} * 8;
491 pasm_output_is( <<"CODE", <<'OUTPUT', 'rot_i_i_ic_ic' );
492     set I0, 0b001100
493     rot I1, I0, 1, $int_bits   # 1 left
494     print I1
495     print "\\n"
496     rot I1, I0, -1, $int_bits   # 1 right
497     print I1
498     print "\\n"
499     end
500 CODE
503 OUTPUT
505 SKIP: {
506     skip 'no BigInt lib found' => 1
507         unless $PConfig{gmp};
509     my @todo;
510     @todo = ( todo => 'broken with JIT (RT #43245)' )
511         if $ENV{TEST_PROG_ARGS} =~ /-j/;
513     pir_output_is( <<'CODE', <<'OUT', "I-reg shl and PMC shl are consistent", @todo );
514 ## The PMC shl op will promote Integer to Bigint when needed.  We can't stuff a
515 ## BigInt in an I register, but we can produce the same result modulo wordsize.
516 ## [Only we cheat by using the word size minus one, so that we don't have to
517 ## deal with negative numbers.  -- rgr, 2-Jun-07.]
518 .sub main :main
519     ## Figure out the wordsize.  We need integer_modulus because assigning a
520     ## too-big BigInt throws an error otherwise.
521     .include 'sysinfo.pasm'
522     .local int i_bytes_per_word, i_bits_per_word_minus_one
523     .local pmc bits_per_word_minus_one, integer_modulus
524     i_bytes_per_word = sysinfo .SYSINFO_PARROT_INTSIZE
525     i_bits_per_word_minus_one = 8 * i_bytes_per_word
526     dec i_bits_per_word_minus_one
527     bits_per_word_minus_one = new 'Integer'
528     bits_per_word_minus_one = i_bits_per_word_minus_one
529     integer_modulus = new 'BigInt'
530     integer_modulus = 1
531     integer_modulus <<= bits_per_word_minus_one
533     ## Test shifting a positive number.
534     new $P0, 'Integer'
535     set $P0, 1000001
536     test_shift($P0, integer_modulus)
538     ## Test shifting a negative number.
539     set $P0, -1000001
540     test_shift($P0, integer_modulus)
541 .end
543 .sub test_shift
544     .param pmc number
545     .param pmc integer_modulus
546     new $P1, 'Integer'
547     set $P1, 1
548     .local int i_number
549     i_number = number
551     ## Start the loop.
552 loop:
553     if $P1 > 100 goto done
554     ## shift number and i_number into $P2 and $I2.
555     n_shl $P2, number, $P1
556     $I1 = $P1
557     shl $I2, i_number, $I1
558     ## compare in I registers.
559     $P3 = n_mod $P2, integer_modulus
560     $I3 = $P3
561     if $I2 >= 0 goto pos_check
562     ## The register op gave a negative result, but the modulus will always be
563     ## positive.  If the truncated result is correct, then the difference will
564     ## be the most negative INTVAL, which is the only number for which -x==x.
565     $I4 = $I3 - $I2
566     $I5 = - $I4
567     if $I4 == $I5 goto ok
568     goto bad
569 pos_check:
570     if $I2 == $I3 goto ok
571 bad:
572     print "oops; not ok: "
573     print i_number
574     print ' << '
575     print $I1
576     print ' gives I '
577     print $I2
578     print ' vs. P '
579     print $P3
580     print ".\n"
581     print $I5
582     print "\n"
584     ## set up for the next one
585     inc $P1
586     goto loop
587 done:
588     print "done.\n"
589 .end
590 CODE
591 done.
592 done.
596 # Local Variables:
597 #   mode: cperl
598 #   cperl-indent-level: 4
599 #   fill-column: 100
600 # End:
601 # vim: expandtab shiftwidth=4: