Changeset 14939


Ignore:
Timestamp:
Aug 14, 2011, 12:24:19 AM (13 years ago)
Author:
Gary Byers
Message:

Change the rules a bit to allow the LR to point to arbitrary
word-aligned locations inside a vector of single- or double-floats.
The old (well, few months old) trick of allowing the LR to point
to the (0-valued) pad word at the beginning of a DOUBLE-FLOAT or
DOUBLE-FLOAT vector isn't supported anymore (if we can point the lr
at any word in the vector, we can't tell whether that's the pad
word or not.)
This is GC safe as long as the containing vector is marked before
the LR is (and that's true of the ARM version of mark_xp()).
Having the LR point into an ivector (other than a CODE-VECTOR) isn't
sufficient to mark the ivector, so we generally have to be careful
to ensure that the LR doesn't point into an ivector that becomes
garbage. Vinsns that use the LR as a locative zero it out after
use; that's correct but overly conservative. (We -could- have the
compiler watch the vinsn stream and only zero the LR if the register
containing the LR changes/might change and cause the vector to get
GCed before the LR itself changes. We might want that sort of
vinsn-watching mechanism for other reasons, but zeroing the LR isn't
incredibly expensive and it's much better to be safe than sorry.)

The point(s) of all this is/are to avoid the mandatory use of
imm0/imm1 in fp vector references and to make it practical to (at
least in LAP) use NEON vector instructions in some cases. (Because of
addressing limitations in the ARM's coprocessor load/store
instructions, we pretty much have to have a way to point "into"
floating-point vectors; we won't have the option of loading/storing
GPR pairs when using quadword NEON instructions.)

This is an ABI change, though I don't plan to change image/fasl
versions in the trunk. To be safe, recompile any FP-intensive
ARM code after doing a full rebuild.

Location:
trunk/source
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/compiler/ARM/arm-vinsns.lisp

    r14909 r14939  
    144144
    145145                             
    146 (define-arm-vinsn (misc-ref-single-float :predicatable)
     146(define-arm-vinsn (misc-ref-single-float :predicatable :sets-lr)
    147147    (((dest :single-float))
    148148     ((v :lisp)
    149       (scaled-idx :u32))
    150      ((temp :u32)))
    151   (ldr temp (:@ v scaled-idx))
    152   (fmsr dest temp))
    153 
    154 (define-arm-vinsn (misc-ref-c-single-float :predicatable)
     149      (scaled-idx :u32)))
     150  (add lr v scaled-idx)
     151  (flds dest (:@ lr (:$ 0)))
     152  (mov lr (:$ 0)))
     153
     154(define-arm-vinsn (misc-ref-c-single-float :predicatable :sets-lr)
    155155    (((dest :single-float))
    156156     ((v :lisp)
    157157      (idx :u32const))
    158      ((temp :u32)))
    159   (ldr temp (:@ v (:$ (:apply + arm::misc-data-offset (:apply ash idx 2)))))
    160   (fmsr dest temp))
    161 
    162 (define-arm-vinsn (misc-ref-double-float :predicatable)
     158     ())
     159  (add lr v (:$ arm::misc-data-offset))
     160  (flds dest (:@ lr (:$ (:apply ash idx 2))))
     161  (mov lr (:$ 0)))
     162
     163(define-arm-vinsn (misc-ref-double-float :predicatable :sets-lr)
    163164    (((dest :double-float))
    164165     ((v :lisp)
    165       (scaled-idx :u32))
    166      ((low (:u32 #.arm::imm0))
    167       (high (:u32 #.arm::imm1))))
    168   (ldrd low (:@ v scaled-idx))
    169   (fmdrr dest low high))
     166      (unscaled-idx :imm)))
     167  (add arm::lr v (:$ arm::misc-dfloat-offset))
     168  (add arm::lr arm::lr (:lsl unscaled-idx (:$ 1)))
     169  (fldd dest (:@ arm::lr (:$ 0)))
     170  (mov lr (:$ 0)))
    170171
    171172
     
    176177     ((v :lisp)
    177178      (idx :u32const)))
    178   (add lr v (:$ arm::double-float.pad))
    179   (fldd dest (:@ lr (:$ (:apply + (:apply ash idx 3) (- arm::double-float.value arm::double-float.pad))))))
    180 
    181 (define-arm-vinsn (misc-set-c-double-float :predicatable)
     179  (add lr v (:$ arm::double-float.value))
     180  (fldd dest (:@ lr (:$ (:apply ash idx 3))))
     181  (mov lr (:$ 0)))
     182
     183(define-arm-vinsn (misc-set-c-double-float :predicatable :sets-lr)
    182184    (((val :double-float))
    183185     ((v :lisp)
    184186      (idx :u32const)))
    185   (add lr v (:$ arm::double-float.pad))
    186   (fstd val (:@ lr (:$ (:apply + (:apply ash idx 3) (- arm::double-float.value arm::double-float.pad))))))
    187 
    188 (define-arm-vinsn (misc-set-double-float :predicatable)
     187  (add lr v (:$ arm::double-float.value))
     188  (fstd val (:@ lr (:$ (:apply ash idx 3))))
     189  (mov lr (:$ 0)))
     190
     191(define-arm-vinsn (misc-set-double-float :predicatable :sets-lr)
    189192    (()
    190193     ((val :double-float)
    191194      (v :lisp)
    192       (scaled-idx :u32))
    193      ((low (:u32 #.arm::imm0))
    194       (high (:u32 #.arm::imm1))))
    195   (fmrrd low high val)
    196   (strd low (:@ v scaled-idx)))
     195      (unscaled-idx :imm)))             ; a fixnum
     196  (add lr v (:$ arm::misc-dfloat-offset))
     197  (add lr lr (:lsl unscaled-idx (:$ 1)))
     198  (fstd val (:@ lr (:$ 0)))
     199  (mov lr (:$ 0)))
    197200
    198201(define-arm-vinsn (misc-set-c-single-float :predicatable)
     
    200203     ((val :single-float)
    201204      (v :lisp)
    202       (idx :u32const))
    203      ((temp :u32)))
    204   (fmrs temp val)
    205   (str temp (:@ v (:$ (:apply + arm::misc-data-offset (:apply ash idx 2))))))
     205      (idx :u32const)))
     206  (add lr v (:$ arm::misc-data-offset))
     207  (fsts val (:@ lr (:$ (:apply ash idx 2))))
     208  (mov lr (:$ 0)))
     209
    206210
    207211
     
    24282432;;; Heap-cons a double-float to store contents of FPREG.  Hope that we don't do
    24292433;;; this blindly.
    2430 (define-arm-vinsn double->heap (((result :lisp)) ; tagged as a double-float
     2434(define-arm-vinsn (double->heap :sets-lr) (((result :lisp)) ; tagged as a double-float
    24312435                                ((fpreg :double-float))
    24322436                                ((header-temp (:u32 #.arm::imm0))
     
    24422446  (mov result allocptr)
    24432447  (bic allocptr allocptr (:$ arm::fulltagmask))
    2444   (add lr result (:$ arm::double-float.pad))
    2445   (fstd fpreg (:@ lr (:$ (- arm::double-float.value arm::double-float.pad)))))
     2448  (add lr result (:$ arm::double-float.value))
     2449  (fstd fpreg (:@ lr (:$ 0)))
     2450  (mov lr (:$ 0)))
    24462451
    24472452
     
    24632468  (mov result allocptr)
    24642469  (bic allocptr allocptr (:$ arm::fulltagmask))
     2470  (add lr result (:$ arm::single-float.value))
    24652471  (fmrs header-temp fpreg)
    24662472  (str header-temp (:@ result (:$ arm::single-float.value))))
     
    24692475
    24702476;;; "dest" is preallocated, presumably on a stack somewhere.
    2471 (define-arm-vinsn (store-double :predicatable)
     2477(define-arm-vinsn (store-double :predicatable :sets-lr)
    24722478    (()
    24732479     ((dest :lisp)
    2474       (source :double-float))
    2475      ((low (:u32 #.arm::imm0))
    2476       (high (:u32 #.arm::imm1))))
    2477   (fmrrd low high source)
    2478   (strd low (:@ dest (:$ arm::double-float.value))))
     2480      (source :double-float)))
     2481  (add lr dest (:$ arm::double-float.value))
     2482  (fstd source (:@ lr (:$ 0)))
     2483  (mov lr (:$ 0)))
    24792484
    24802485(define-arm-vinsn (get-double :predicatable :sets-lr)
    24812486    (((target :double-float))
    24822487     ((source :lisp)))
    2483   (add lr source (:$ arm::double-float.pad))
    2484   (fldd target (:@ lr (:$ (- arm::double-float.value arm::double-float.pad)))))
     2488  (add lr source (:$ arm::double-float.value))
     2489  (fldd target (:@ lr (:$ 0)))
     2490  (mov lr (:$ 0)))
    24852491
    24862492;;; Extract a double-float value, typechecking in the process.
  • trunk/source/compiler/ARM/arm2.lisp

    r14922 r14939  
    15821582                    (with-imm-target () idx-reg
    15831583                      (if index-known-fixnum
    1584                         (arm2-absolute-natural seg idx-reg nil (+ (arch::target-misc-data-offset arch) (ash index-known-fixnum 3)))
    1585                         (! scale-64bit-misc-index idx-reg unscaled-idx))
    1586                       (! misc-ref-double-float fp-val src idx-reg)))
     1584                        (unless unscaled-idx
     1585                          (setq unscaled-idx idx-reg)
     1586                          (arm2-absolute-natural seg unscaled-idx nil (ash index-known-fixnum arm::fixnumshift))))
     1587                      (! misc-ref-double-float fp-val src unscaled-idx)))
    15871588                  (if (eq vreg-class hard-reg-class-fpr)
    15881589                    (<- fp-val)
     
    21542155                    (progn
    21552156                      (if index-known-fixnum
    2156                         (arm2-absolute-natural seg scaled-idx nil (+ (arch::target-misc-dfloat-offset arch) (ash index-known-fixnum 3)))
    2157                         (! scale-64bit-misc-index scaled-idx unscaled-idx))
    2158                       (! misc-set-double-float unboxed-val-reg src scaled-idx)))))
     2157                        (unless unscaled-idx
     2158                          (setq unscaled-idx scaled-idx)
     2159                          (arm2-absolute-natural seg unscaled-idx nil (ash index-known-fixnum arm::fixnumshift))))
     2160                      (! misc-set-double-float unboxed-val-reg src unscaled-idx)))))
    21592161                 (t
    21602162                  (with-imm-target (unboxed-val-reg) scaled-idx
  • trunk/source/lisp-kernel/arm-gc.c

    r14770 r14939  
    10561056{
    10571057  natural *regs = (natural *) xpGPRvector(xp);
    1058   LispObj lr_value;
    1059 
    10601058  int r;
    10611059  /* registers between arg_z and Rfn should be tagged and marked as
     
    10761074
    10771075  mark_pc_root(ptr_to_lispobj(xpPC(xp)));
    1078   lr_value = ptr_to_lispobj(xpLR(xp));
    1079   if (*((LispObj *)lr_value) == 0) { /* pointing into a double-float/double-float vector */
    1080     mark_root(untag(lr_value)+fulltag_misc);
    1081   } else {
    1082     mark_pc_root(lr_value);
    1083   }
     1076  mark_pc_root(ptr_to_lispobj(xpLR(xp)));
    10841077}
    10851078
Note: See TracChangeset for help on using the changeset viewer.