... |
... |
@@ -406,298 +406,4 @@ |
406
|
406
|
;;;
|
407
|
407
|
(define-move-vop move-argument :move-argument
|
408
|
408
|
(signed-reg unsigned-reg) (any-reg descriptor-reg))
|
409
|
|
-
|
410
|
|
-;; 64-bit stuff
|
411
|
|
-#+(and sparc-v9 sparc-v8plus)
|
412
|
|
-(progn
|
413
|
|
-
|
414
|
|
-;; Move a signed-reg to a signed64-reg by sign-extending. (Is this
|
415
|
|
-;; needed?)
|
416
|
|
-(define-move-function (load-signed64-signed 1) (vop x y)
|
417
|
|
- ((signed-reg) (signed64-reg unsigned64-reg))
|
418
|
|
- (inst signx y x))
|
419
|
|
-
|
420
|
|
-;; Move a signed64-reg to signed-reg by setting the high 32 bits to be
|
421
|
|
-;; the sign. (Is this needed and will this do the right thing when
|
422
|
|
-;; that signed64-reg actually has more than 32 significant bits?)
|
423
|
|
-#+nil
|
424
|
|
-(define-move-function (load-signed-signed64 1) (vop x y)
|
425
|
|
- ((signed64-reg) (signed-reg))
|
426
|
|
- (inst signx y x))
|
427
|
|
-
|
428
|
|
-;; Load a 64-bit number from the stack
|
429
|
|
-(define-move-function (load-number-stack-64 5) (vop x y)
|
430
|
|
- ((signed64-stack) (signed64-reg)
|
431
|
|
- (unsigned64-stack) (unsigned64-reg))
|
432
|
|
- (let ((nfp (current-nfp-tn vop)))
|
433
|
|
- (load64 y nfp (tn-offset x))))
|
434
|
|
-
|
435
|
|
-;; Save a 64-bit number to the stack
|
436
|
|
-(define-move-function (store-number-stack-64 5) (vop x y)
|
437
|
|
- ((signed64-reg) (signed64-stack)
|
438
|
|
- (unsigned64-reg) (unsigned64-stack))
|
439
|
|
- (let ((nfp (current-nfp-tn vop)))
|
440
|
|
- (store64 x nfp (tn-offset y))))
|
441
|
|
-
|
442
|
|
-;; Move a tagged integer to a raw double-word representation.
|
443
|
|
-(define-vop (move-to-64bit-word/fixnum)
|
444
|
|
- (:args (x :scs (any-reg descriptor-reg)))
|
445
|
|
- (:results (y :scs (signed64-reg unsigned64-reg)))
|
446
|
|
- (:arg-types tagged-num)
|
447
|
|
- (:note _N"fixnum untagging")
|
448
|
|
- (:generator 0
|
449
|
|
- ;; Sign-extend the fixnum and then remove the tag. (Can't just
|
450
|
|
- ;; remove the tag because we don't know for sure if X has been
|
451
|
|
- ;; sign-extended to 64-bits. Let's be safe.)
|
452
|
|
- (inst signx y x)
|
453
|
|
- (inst srax y y fixnum-tag-bits)))
|
454
|
|
-
|
455
|
|
-(define-move-vop move-to-64bit-word/fixnum :move
|
456
|
|
- (any-reg descriptor-reg) (signed64-reg unsigned64-reg))
|
457
|
|
-
|
458
|
|
-;; Arg is a non-immediate constant, load it.
|
459
|
|
-(define-vop (move-to-64bit-word-c)
|
460
|
|
- (:args (x :scs (constant)))
|
461
|
|
- (:results (y :scs (signed64-reg unsigned64-reg)))
|
462
|
|
- (:note _N"constant load")
|
463
|
|
- (:generator 1
|
464
|
|
- (inst li64 y (tn-value x))))
|
465
|
|
-
|
466
|
|
-(define-move-vop move-to-64bit-word-c :move
|
467
|
|
- (constant) (signed64-reg unsigned64-reg))
|
468
|
|
-
|
469
|
|
-;; Arg is a fixnum or bignum. Figure out which and load if necessary
|
470
|
|
-(define-vop (move-to-64bit-word/integer)
|
471
|
|
- (:args (x :scs (descriptor-reg)))
|
472
|
|
- (:results (y :scs (signed64-reg)))
|
473
|
|
- (:note _N"integer to untagged word coercion")
|
474
|
|
- (:temporary (:scs (signed64-reg)) temp)
|
475
|
|
- (:generator 4
|
476
|
|
- (let ((done (gen-label)))
|
477
|
|
- (inst andcc temp x fixnum-tag-mask)
|
478
|
|
- (inst signx temp x) ; sign-extend X to TEMP
|
479
|
|
- (inst b :eq done :pt :xcc)
|
480
|
|
- (inst sran y temp fixnum-tag-bits) ; Zap the tag bits
|
481
|
|
-
|
482
|
|
- ;; We have a bignum. We need to check the length. If the
|
483
|
|
- ;; length is 1, just get the one word. If it's 2, we need to
|
484
|
|
- ;; get both words.
|
485
|
|
-
|
486
|
|
- (loadw temp x 0 other-pointer-type)
|
487
|
|
- (inst srln temp 8)
|
488
|
|
- (inst cmp temp 1)
|
489
|
|
- (inst b :eq done)
|
490
|
|
- ;; Get the low word and sign-extend it
|
491
|
|
- (loadsw y x bignum-digits-offset other-pointer-type)
|
492
|
|
-
|
493
|
|
-
|
494
|
|
- ;; Get the high word and then the low word. Merge them
|
495
|
|
- ;; together. (If we knew that bignum digits started on an 8-byte
|
496
|
|
- ;; boundary, we could do an 8-byte load and them manipulate the
|
497
|
|
- ;; pieces to get the order we want. I think this would require
|
498
|
|
- ;; adding a filler word to the bignum type in objdef.lisp. But
|
499
|
|
- ;; then every bignum has a wasted word. Is that ok?)
|
500
|
|
- (loadw temp x (1+ bignum-digits-offset) other-pointer-type)
|
501
|
|
- (inst sllx temp temp 32)
|
502
|
|
- (loadw y x bignum-digits-offset other-pointer-type)
|
503
|
|
- (inst or y temp)
|
504
|
|
-
|
505
|
|
- (emit-label done)
|
506
|
|
-
|
507
|
|
- )))
|
508
|
|
-
|
509
|
|
-(define-move-vop move-to-64bit-word/integer :move
|
510
|
|
- (descriptor-reg) (signed64-reg))
|
511
|
|
-
|
512
|
|
-;; Move a signed-byte 32 to a signed-byte 64. (Is this ever called?
|
513
|
|
-;; I don't think so.)
|
514
|
|
-(define-vop (move-to-64bit-word/signed)
|
515
|
|
- (:args (x :scs (signed-reg)))
|
516
|
|
- (:results (y :scs (signed64-reg)))
|
517
|
|
- (:arg-types signed-num)
|
518
|
|
- (:generator 0
|
519
|
|
- ;; Sign-extend the 32-bit number
|
520
|
|
- (inst signx y x)))
|
521
|
|
-
|
522
|
|
-(define-move-vop move-to-64bit-word/signed :move
|
523
|
|
- (signed-reg) (signed64-reg unsigned64-reg))
|
524
|
|
-
|
525
|
|
-;; Move an unsigned-byte 32 to signed-byte 64. (I don't think this
|
526
|
|
-;; ever gets called.)
|
527
|
|
-(define-vop (move-to-64bit-word/unsigned)
|
528
|
|
- (:args (x :scs (unsigned-reg)))
|
529
|
|
- (:results (y :scs (signed64-reg)))
|
530
|
|
- (:arg-types unsigned-num)
|
531
|
|
- (:generator 1
|
532
|
|
- ;; Zero-extend the 32-bit number
|
533
|
|
- (inst clruw y x)))
|
534
|
|
-
|
535
|
|
-(define-move-vop move-to-64bit-word/unsigned :move
|
536
|
|
- (unsigned-reg) (signed64-reg unsigned64-reg))
|
537
|
|
-
|
538
|
|
-;; Save a 64-bit int to a bignum.
|
539
|
|
-(define-vop (move-from-signed64)
|
540
|
|
- (:args (arg :scs (signed64-reg) :target x))
|
541
|
|
- (:results (y :scs (descriptor-reg)))
|
542
|
|
- (:temporary (:scs (signed64-reg) :from (:argument 0)) x temp)
|
543
|
|
- (:note _N"signed 64-bit word to integer coercion")
|
544
|
|
- (:generator 20
|
545
|
|
- (move x arg)
|
546
|
|
- (let ((fixnum (gen-label))
|
547
|
|
- (done (gen-label)))
|
548
|
|
- ;; See if the result will fit in a fixnum.
|
549
|
|
- (inst srax temp x positive-fixnum-bits)
|
550
|
|
- (inst cmp temp)
|
551
|
|
- ;; If result is all zeroes, we have a positive fixnum.
|
552
|
|
- (inst b :eq fixnum :pt :xcc)
|
553
|
|
- (inst orncc temp zero-tn temp)
|
554
|
|
- ;; If result is all zeroes, we have a negative fixnum.
|
555
|
|
- (inst b :eq done :pt :xcc)
|
556
|
|
- (inst slln y x fixnum-tag-bits)
|
557
|
|
-
|
558
|
|
- ;; A 64-bit signed integer takes exactly 2 bignum digits
|
559
|
|
- (with-fixed-allocation
|
560
|
|
- (y temp bignum-type (+ 2 bignum-digits-offset))
|
561
|
|
- ;; Store the low word at the low address, the high word at the
|
562
|
|
- ;; higher address. (Like move-to-64bit-word/integer, if we knew
|
563
|
|
- ;; the first bignum digit was on a 8-byte boundary, we could
|
564
|
|
- ;; just do a single 8-byte store instead of 2 stores here.)
|
565
|
|
- (storew x y bignum-digits-offset other-pointer-type)
|
566
|
|
- (inst srax x x 32)
|
567
|
|
- (storew x y (1+ bignum-digits-offset) other-pointer-type))
|
568
|
|
- (inst b done)
|
569
|
|
- (inst nop)
|
570
|
|
-
|
571
|
|
- (emit-label fixnum)
|
572
|
|
- (inst slln y x fixnum-tag-bits)
|
573
|
|
- (emit-label done))))
|
574
|
|
-
|
575
|
|
-(define-move-vop move-from-signed64 :move
|
576
|
|
- (signed64-reg) (descriptor-reg))
|
577
|
|
-
|
578
|
|
-;; Save an unsigned 64-bit int to a bignum.
|
579
|
|
-(define-vop (move-from-unsigned64)
|
580
|
|
- (:args (arg :scs (unsigned64-reg) :target x))
|
581
|
|
- (:results (y :scs (descriptor-reg)))
|
582
|
|
- (:temporary (:scs (unsigned64-reg) :from (:argument 0)) x temp)
|
583
|
|
- (:note _N"unsigned 64-bit word to integer coercion")
|
584
|
|
- (:generator 20
|
585
|
|
- (move x arg)
|
586
|
|
- (let ((two-words (gen-label))
|
587
|
|
- (done (gen-label)))
|
588
|
|
- ;; See if the result will fit in a fixnum.
|
589
|
|
- (inst srax temp x positive-fixnum-bits)
|
590
|
|
- (inst cmp temp)
|
591
|
|
- ;; If result is all zeroes, we have a positive fixnum.
|
592
|
|
- (inst b :eq done :pt :xcc)
|
593
|
|
- (inst slln y x fixnum-tag-bits)
|
594
|
|
-
|
595
|
|
- ;; A unsigned 64-bit signed integer takes exactly 2 or 3 bignum
|
596
|
|
- ;; digits. We always allocate 3. (The copying GC will take
|
597
|
|
- ;; care of freeing the unused extra word, if any.)
|
598
|
|
- (with-fixed-allocation
|
599
|
|
- (y temp bignum-type (+ 3 bignum-digits-offset))
|
600
|
|
- (inst cmp x)
|
601
|
|
- (inst b :ge two-words :pn :xcc)
|
602
|
|
- (inst li temp (logior (ash 2 type-bits) bignum-type))
|
603
|
|
- (inst li temp (logior (ash 3 type-bits) bignum-type))
|
604
|
|
- (emit-label two-words)
|
605
|
|
- ;; Set the header word with the correct bignum length.
|
606
|
|
- (storew temp y 0 other-pointer-type)
|
607
|
|
- ;; Store the low word at the low address, the high word at the
|
608
|
|
- ;; higher address. (Like move-to-64bit-word/integer, if we knew
|
609
|
|
- ;; the first bignum digit was on a 8-byte boundary, we could
|
610
|
|
- ;; just do a single 8-byte store instead of 2 stores here.)
|
611
|
|
- (storew x y bignum-digits-offset other-pointer-type)
|
612
|
|
- (inst srax x x 32)
|
613
|
|
- (storew x y (1+ bignum-digits-offset) other-pointer-type))
|
614
|
|
- (emit-label done))))
|
615
|
|
-
|
616
|
|
-(define-move-vop move-from-unsigned64 :move
|
617
|
|
- (unsigned64-reg) (descriptor-reg))
|
618
|
|
-
|
619
|
|
-(define-vop (move-to-unsigned-64bit-word/integer)
|
620
|
|
- (:args (x :scs (descriptor-reg)))
|
621
|
|
- (:results (y :scs (unsigned64-reg)))
|
622
|
|
- (:note _N"integer to untagged word coercion")
|
623
|
|
- (:temporary (:scs (unsigned64-reg)) temp)
|
624
|
|
- (:generator 4
|
625
|
|
- (let ((done (gen-label)))
|
626
|
|
- (inst andcc temp x fixnum-tag-mask)
|
627
|
|
- (inst signx temp x) ; sign-extend X to TEMP
|
628
|
|
- (inst b :eq done :pt :xcc)
|
629
|
|
- (inst sran y temp fixnum-tag-bits) ; Zap the tag bits
|
630
|
|
-
|
631
|
|
- ;; We have a bignum. We need to check the length. If the
|
632
|
|
- ;; length is 1, just get the one word. If it's 2, we need to
|
633
|
|
- ;; get both words.
|
634
|
|
-
|
635
|
|
- (loadw temp x 0 other-pointer-type)
|
636
|
|
- (inst srln temp 8)
|
637
|
|
- (inst cmp temp 1)
|
638
|
|
- (inst b :eq done)
|
639
|
|
- ;; Get the low word and zero-extend it and we're done.
|
640
|
|
- (loadw y x bignum-digits-offset other-pointer-type)
|
641
|
|
-
|
642
|
|
-
|
643
|
|
- ;; Get the high word and then the low word. Merge them
|
644
|
|
- ;; together. (If we knew that bignum digits started on an 8-byte
|
645
|
|
- ;; boundary, we could do an 8-byte load and them manipulate the
|
646
|
|
- ;; pieces to get the order we want. I think this would require
|
647
|
|
- ;; adding a filler word to the bignum type in objdef.lisp. But
|
648
|
|
- ;; then every bignum has a wasted word. Is that ok?)
|
649
|
|
- (loadw temp x (1+ bignum-digits-offset) other-pointer-type)
|
650
|
|
- (inst sllx temp temp 32)
|
651
|
|
- (loadw y x bignum-digits-offset other-pointer-type)
|
652
|
|
- (inst or y temp)
|
653
|
|
-
|
654
|
|
- (emit-label done)
|
655
|
|
-
|
656
|
|
- )))
|
657
|
|
-
|
658
|
|
-(define-move-vop move-to-unsigned-64bit-word/integer :move
|
659
|
|
- (descriptor-reg) (unsigned64-reg))
|
660
|
|
-
|
661
|
|
-(define-vop (64bit-word-move)
|
662
|
|
- (:args (x :target y
|
663
|
|
- :scs (signed64-reg unsigned64-reg)
|
664
|
|
- :load-if (not (location= x y))))
|
665
|
|
- (:results (y :scs (signed64-reg unsigned64-reg)
|
666
|
|
- :load-if (not (location= x y))))
|
667
|
|
- (:effects)
|
668
|
|
- (:affected)
|
669
|
|
- (:note _N"word integer move")
|
670
|
|
- (:generator 0
|
671
|
|
- (move y x)))
|
672
|
|
-
|
673
|
|
-(define-move-vop 64bit-word-move :move
|
674
|
|
- (signed64-reg unsigned64-reg) (signed64-reg unsigned64-reg))
|
675
|
|
-
|
676
|
|
-;; Move untagged number arguments/return-values.
|
677
|
|
-(define-vop (move-64bit-word-argument)
|
678
|
|
- (:args (x :target y
|
679
|
|
- :scs (signed-reg signed64-reg unsigned64-reg immediate))
|
680
|
|
- (fp :scs (any-reg)
|
681
|
|
- :load-if (not (sc-is y sap-reg))))
|
682
|
|
- (:results (y))
|
683
|
|
- (:note _N"word integer argument move")
|
684
|
|
- (:generator 0
|
685
|
|
- (sc-case y
|
686
|
|
- ((signed64-reg unsigned64-reg)
|
687
|
|
- (sc-case x
|
688
|
|
- ((signed64-reg unsigned64-reg)
|
689
|
|
- (move y x))
|
690
|
|
- (signed-reg
|
691
|
|
- (inst signx y x))
|
692
|
|
- (immediate
|
693
|
|
- (inst li64 y (tn-value x)))))
|
694
|
|
- ((signed64-stack unsigned64-stack)
|
695
|
|
- (store64 x fp (tn-offset y))))))
|
696
|
|
-
|
697
|
|
-(define-move-vop move-64bit-word-argument :move-argument
|
698
|
|
- (descriptor-reg signed64-reg unsigned64-reg) (signed64-reg unsigned64-reg))
|
699
|
|
-
|
700
|
|
-(define-move-vop move-argument :move-argument
|
701
|
|
- (signed64-reg unsigned64-reg) (descriptor-reg))
|
702
|
409
|
|
703
|
|
-)
|