home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mitsch75.zip / scheme-7_5_17-src.zip / scheme-7.5.17 / src / compiler / machines / spectrum / lapgen.scm < prev    next >
Encoding:
Text File  |  1999-01-02  |  23.5 KB  |  734 lines

  1. #| -*-Scheme-*-
  2.  
  3. $Id: lapgen.scm,v 4.48 1999/01/02 06:06:43 cph Exp $
  4.  
  5. Copyright (c) 1988-1999 Massachusetts Institute of Technology
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. |#
  21.  
  22. ;;;; RTL Rules for HPPA.  Shared utilities.
  23. ;;; package: (compiler lap-syntaxer)
  24.  
  25. (declare (usual-integrations))
  26.  
  27. ;;;; Register-Allocator Interface
  28.  
  29. (define (register->register-transfer source target)
  30.   (if (not (register-types-compatible? source target))
  31.       (error "Moving between incompatible register types" source target))
  32.   (case (register-type source)
  33.     ((GENERAL) (copy source target))
  34.     ((FLOAT) (fp-copy source target))
  35.     (else (error "unknown register type" source))))
  36.  
  37. (define (home->register-transfer source target)
  38.   (memory->register-transfer (pseudo-register-displacement source)
  39.                  regnum:regs-pointer
  40.                  target))
  41.  
  42. (define (register->home-transfer source target)
  43.   (register->memory-transfer source
  44.                  (pseudo-register-displacement target)
  45.                  regnum:regs-pointer))
  46.  
  47. (define (reference->register-transfer source target)
  48.   (case (ea/mode source)
  49.     ((GR)
  50.      (copy (register-ea/register source) target))
  51.     ((FPR)
  52.      (fp-copy (fpr->float-register (register-ea/register source)) target))
  53.     ((OFFSET)
  54.      (memory->register-transfer (offset-ea/offset source)
  55.                 (offset-ea/register source)
  56.                 target))
  57.     (else
  58.      (error "unknown effective-address mode" source))))
  59.  
  60. (define (pseudo-register-home register)
  61.   ;; Register block consists of 16 4-byte registers followed by 256
  62.   ;; 8-byte temporaries.
  63.   (INST-EA (OFFSET ,(pseudo-register-displacement register)
  64.            0
  65.            ,regnum:regs-pointer)))
  66.  
  67. (define-integrable (sort-machine-registers registers)
  68.   registers)
  69.  
  70. ;; ***
  71. ;; Note: fp16-fp31 only exist on PA-RISC 1.1 or later.
  72. ;; If compiling for PA-RISC 1.0, truncate this
  73. ;; list after fp15.
  74. ;; ***
  75.  
  76. (define available-machine-registers
  77.   ;; g1 removed from this list since it is the target of ADDIL,
  78.   ;; needed to expand some rules.  g31 may want to be removed
  79.   ;; too.
  80.   (list
  81.    ;; g0 g1 g2 g3 g4 g5
  82.    g6 g7 g8 g9 g10 g11 g12 g13 g14 g15 g16 g17 g18
  83.    ;; g19 g20 g21 g22
  84.    g23 g24 g25 g26
  85.    ;; g27
  86.    g28 g29
  87.    ;; g30
  88.    g31
  89.    ;; fp0 fp1 fp2 fp3
  90.    fp12 fp13 fp14 fp15
  91.    fp4 fp5 fp6 fp7 fp8 fp9 fp10 fp11
  92.    ;; The following are only available on newer processors
  93.    fp16 fp17 fp18 fp19 fp20 fp21 fp22 fp23
  94.    fp24 fp25 fp26 fp27 fp28 fp29 fp30 fp31
  95.    ))
  96.  
  97. (define-integrable (float-register? register)
  98.   (eq? (register-type register) 'FLOAT))
  99.  
  100. (define-integrable (general-register? register)
  101.   (eq? (register-type register) 'GENERAL))
  102.  
  103. (define-integrable (word-register? register)
  104.   (eq? (register-type register) 'GENERAL))
  105.       
  106. (define (register-types-compatible? type1 type2)
  107.   (boolean=? (eq? type1 'FLOAT) (eq? type2 'FLOAT)))
  108.  
  109. (define (register-type register)
  110.   (cond ((machine-register? register)
  111.      (vector-ref
  112.       '#(GENERAL GENERAL GENERAL GENERAL GENERAL GENERAL GENERAL GENERAL
  113.          GENERAL GENERAL GENERAL GENERAL GENERAL GENERAL GENERAL GENERAL
  114.          GENERAL GENERAL GENERAL GENERAL GENERAL GENERAL GENERAL GENERAL
  115.          GENERAL GENERAL GENERAL GENERAL GENERAL GENERAL GENERAL GENERAL
  116.          FLOAT FLOAT FLOAT FLOAT FLOAT FLOAT FLOAT FLOAT
  117.          FLOAT FLOAT FLOAT FLOAT FLOAT FLOAT FLOAT FLOAT
  118.          FLOAT FLOAT FLOAT FLOAT FLOAT FLOAT FLOAT FLOAT
  119.          FLOAT FLOAT FLOAT FLOAT FLOAT FLOAT FLOAT FLOAT)
  120.       register))
  121.     ((register-value-class=word? register) 'GENERAL)
  122.     ((register-value-class=float? register) 'FLOAT)
  123.     (else (error "unable to determine register type" register))))
  124.  
  125. (define register-reference
  126.   (let ((references (make-vector number-of-machine-registers)))
  127.     (let loop ((register 0))
  128.       (if (< register 32)
  129.       (begin
  130.         (vector-set! references register (INST-EA (GR ,register)))
  131.         (loop (1+ register)))))
  132.     (let loop ((register 32) (fpr 0))
  133.       (if (< register 64)
  134.       (begin
  135.         (vector-set! references register (INST-EA (FPR ,fpr)))
  136.         (loop (1+ register) (1+ fpr)))))
  137.     (lambda (register)
  138.       (vector-ref references register))))
  139.  
  140. ;;;; Useful Cliches
  141.  
  142. (define (memory->register-transfer offset base target)
  143.   (case (register-type target)
  144.     ((GENERAL) (load-word offset base target))
  145.     ((FLOAT) (fp-load-doubleword offset base target))
  146.     (else (error "unknown register type" target))))
  147.  
  148. (define (register->memory-transfer source offset base)
  149.   (case (register-type source)
  150.     ((GENERAL) (store-word source offset base))
  151.     ((FLOAT) (fp-store-doubleword source offset base))
  152.     (else (error "unknown register type" source))))
  153.  
  154. (define (load-constant constant target)
  155.   ;; Load a Scheme constant into a machine register.
  156.   (if (non-pointer-object? constant)
  157.       (load-immediate (non-pointer->literal constant) target)
  158.       (load-pc-relative (constant->label constant) target 'CONSTANT)))
  159.  
  160. (define (load-non-pointer type datum target)
  161.   ;; Load a Scheme non-pointer constant, defined by type and datum,
  162.   ;; into a machine register.
  163.   (load-immediate (make-non-pointer-literal type datum) target))
  164.  
  165. (define (non-pointer->literal constant)
  166.   (make-non-pointer-literal (object-type constant)
  167.                 (careful-object-datum constant)))
  168.  
  169. (define-integrable (make-non-pointer-literal type datum)
  170.   (+ (* type type-scale-factor) datum))
  171.  
  172. (define-integrable type-scale-factor
  173.   ;; (expt 2 scheme-datum-width) ***
  174.   #x4000000)
  175.  
  176. (define-integrable (deposit-type type target)
  177.   (deposit-immediate type (-1+ scheme-type-width) scheme-type-width target))
  178.  
  179. ;;;; Regularized Machine Instructions
  180.  
  181. (define (copy r t)
  182.   (if (= r t)
  183.       (LAP)
  184.       (LAP (COPY () ,r ,t))))
  185.  
  186. (define-integrable ldil-scale
  187.   ;; (expt 2 11) ***
  188.   2048)
  189.  
  190. (define (load-immediate i t)
  191.   (if (fits-in-14-bits-signed? i)
  192.       (LAP (LDI () ,i ,t))
  193.       (let ((split (integer-divide i ldil-scale)))
  194.     (LAP (LDIL () ,(integer-divide-quotient split) ,t)
  195.          ,@(let ((r%i (integer-divide-remainder split)))
  196.          (if (zero? r%i)
  197.              (LAP)
  198.              (LAP (LDO () (OFFSET ,r%i 0 ,t) ,t))))))))
  199.  
  200. (define (deposit-immediate i p len t)
  201.   (if (fits-in-5-bits-signed? i)
  202.       (LAP (DEPI () ,i ,p ,len ,t))
  203.       (LAP ,@(load-immediate i regnum:addil-result)
  204.        (DEP () ,regnum:addil-result ,p ,len ,t))))
  205.  
  206. (define (load-offset d b t)
  207.   (cond ((and (zero? d) (= b t))
  208.      (LAP))
  209.     ((fits-in-14-bits-signed? d)
  210.      (LAP (LDO () (OFFSET ,d 0 ,b) ,t)))
  211.     (else
  212.      (let ((split (integer-divide d ldil-scale)))
  213.        (LAP (ADDIL () ,(integer-divide-quotient split) ,b)
  214.         (LDO () (OFFSET ,(integer-divide-remainder split) 0 1) ,t))))))
  215.  
  216. (define (load-word d b t)
  217.   (if (fits-in-14-bits-signed? d)
  218.       (LAP (LDW () (OFFSET ,d 0 ,b) ,t))
  219.       (let ((split (integer-divide d ldil-scale)))
  220.     (LAP (ADDIL () ,(integer-divide-quotient split) ,b)
  221.          (LDW () (OFFSET ,(integer-divide-remainder split) 0 1) ,t)))))
  222.  
  223. (define (load-byte d b t)
  224.   (if (fits-in-14-bits-signed? d)
  225.       (LAP (LDB () (OFFSET ,d 0 ,b) ,t))
  226.       (let ((split (integer-divide d ldil-scale)))
  227.     (LAP (ADDIL () ,(integer-divide-quotient split) ,b)
  228.          (LDB () (OFFSET ,(integer-divide-remainder split) 0 1) ,t)))))
  229.  
  230. (define (store-word b d t)
  231.   (if (fits-in-14-bits-signed? d)
  232.       (LAP (STW () ,b (OFFSET ,d 0 ,t)))
  233.       (let ((split (integer-divide d ldil-scale)))
  234.     (LAP (ADDIL () ,(integer-divide-quotient split) ,t)
  235.          (STW () ,b (OFFSET ,(integer-divide-remainder split) 0 1))))))
  236.  
  237. (define (store-byte b d t)
  238.   (if (fits-in-14-bits-signed? d)
  239.       (LAP (STB () ,b (OFFSET ,d 0 ,t)))
  240.       (let ((split (integer-divide d ldil-scale)))
  241.     (LAP (ADDIL () ,(integer-divide-quotient split) ,t)
  242.          (STB () ,b (OFFSET ,(integer-divide-remainder split) 0 1))))))
  243.  
  244. (define (fp-copy r t)
  245.   (if (= r t)
  246.       (LAP)
  247.       (LAP (FCPY (DBL) ,(float-register->fpr r) ,(float-register->fpr t)))))
  248.  
  249. (define (fp-load-doubleword d b t)
  250.   (let ((t (float-register->fpr t)))
  251.     (if (fits-in-5-bits-signed? d)
  252.     (LAP (FLDDS () (OFFSET ,d 0 ,b) ,t))
  253.     (LAP ,@(load-offset d b regnum:addil-result)
  254.          (FLDDS () (OFFSET 0 0 ,regnum:addil-result) ,t)))))
  255.  
  256. (define (fp-store-doubleword r d b)
  257.   (let ((r (float-register->fpr r)))
  258.     (if (fits-in-5-bits-signed? d)
  259.     (LAP (FSTDS () ,r (OFFSET ,d 0 ,b)))
  260.     (LAP ,@(load-offset d b regnum:addil-result)
  261.          (FSTDS () ,r (OFFSET 0 0 ,regnum:addil-result))))))
  262.  
  263. #|
  264. (define (load-pc-relative label target type)
  265.   type                    ; ignored
  266.   ;; Load a pc-relative location's contents into a machine register.
  267.   ;; This assumes that the offset fits in 14 bits!
  268.   ;; We should have a pseudo-op for LDW that does some "branch" tensioning.
  269.   (LAP (BL () ,regnum:addil-result (@PCO 0))
  270.        ;; Clear the privilege level, making this a memory address.
  271.        (DEP () 0 31 2 ,regnum:addil-result)
  272.        (LDW () (OFFSET (- ,label *PC*) 0 ,regnum:addil-result) ,target)))
  273.  
  274. (define (load-pc-relative-address label target type)
  275.   type                    ; ignored
  276.   ;; Load a pc-relative address into a machine register.
  277.   ;; This assumes that the offset fits in 14 bits!
  278.   ;; We should have a pseudo-op for LDO that does some "branch" tensioning.
  279.   (LAP (BL () ,regnum:addil-result (@PCO 0))
  280.        ;; Clear the privilege level, making this a memory address.
  281.        (DEP () 0 31 2 ,regnum:addil-result)
  282.        (LDO () (OFFSET (- ,label *PC*) 0 ,regnum:addil-result) ,target)))
  283. |#
  284.  
  285. ;; These versions of load-pc-... remember what they obtain, to avoid
  286. ;; doing the sequence multiple times.
  287. ;; In addition, they assume that the code is running in the least
  288. ;; privilege, and avoid the DEP in the sequences above.
  289.  
  290. (define-integrable *privilege-level* 3)
  291.  
  292. (define-integrable (close? label label*)
  293.   ;; Heuristic
  294.   label label*                ; ignored
  295.   compiler:compile-by-procedures?)
  296.  
  297. (define (load-pc-relative label target type)
  298.   (load-pc-relative-internal label target type
  299.                  (lambda (offset base target)
  300.                    (LAP (LDW () (OFFSET ,offset 0 ,base)
  301.                      ,target)))))
  302.  
  303. (define (load-pc-relative-address label target type)
  304.   (load-pc-relative-internal label target type
  305.                  (lambda (offset base target)
  306.                    (LAP (LDO () (OFFSET ,offset 0 ,base)
  307.                      ,target)))))
  308.  
  309. (define (load-pc-relative-internal label target type gen)
  310.   (with-values (lambda () (get-typed-label type))
  311.     (lambda (label* alias type*)
  312.       (define (closer label* alias)
  313.     (let ((temp (standard-temporary!)))
  314.       (set-typed-label! type label temp)
  315.       (LAP (LDO () (OFFSET (- ,label ,label*) 0 ,alias) ,temp)
  316.            ,@(gen 0 temp target))))
  317.  
  318.       (cond ((not label*)
  319.          (let ((temp (standard-temporary!))
  320.            (here (generate-label)))
  321.            (let ((value `(+ ,here ,(+ 8 *privilege-level*))))
  322.          (set-typed-label! 'CODE value temp)
  323.          (LAP (LABEL ,here)
  324.               (BL () ,temp (@PCO 0))
  325.               ,@(if (or (eq? type 'CODE) (close? label label*))
  326.                 (gen (INST-EA (- ,label ,value)) temp target)
  327.                 (closer value temp))))))
  328.         ((or (eq? type* type) (close? label label*))
  329.          (gen (INST-EA (- ,label ,label*)) alias target))
  330.         (else
  331.          (closer label* alias))))))
  332.  
  333. ;;; Typed labels provide further optimization.  There are two types,
  334. ;;; CODE and CONSTANT, that say whether the label is located in the
  335. ;;; code block or the constants block of the output.  Statistically,
  336. ;;; a label is likely to be closer to another label of the same type
  337. ;;; than to a label of the other type.
  338.  
  339. (define (get-typed-label type)
  340.   (let ((entries (register-map-labels *register-map* 'GENERAL)))
  341.     (let loop ((entries* entries))
  342.       (cond ((null? entries*)
  343.          ;; If no entries of the given type, use any entry that is
  344.          ;; available.
  345.          (let loop ((entries entries))
  346.            (cond ((null? entries)
  347.               (values false false false))
  348.              ((pair? (caar entries))
  349.               (values (cdaar entries) (cadar entries) (caaar entries)))
  350.              (else
  351.               (loop (cdr entries))))))
  352.         ((and (pair? (caar entries*))
  353.           (eq? type (caaar entries*)))
  354.          (values (cdaar entries*) (cadar entries*) type))
  355.         (else
  356.          (loop (cdr entries*)))))))
  357.  
  358. (define (set-typed-label! type label alias)
  359.   (set! *register-map*
  360.     (set-machine-register-label *register-map* alias (cons type label)))
  361.   unspecific)
  362.  
  363. ;; COMIBTN, COMIBFN, and COMBN are pseudo-instructions that nullify
  364. ;; the following instruction when the branch is taken.  Since COMIBT,
  365. ;; etc. nullify according to the sign of the displacement, the branch
  366. ;; tensioner inserts NOPs as necessary (backward branches).
  367.  
  368. (define (compare-immediate cc i r2)
  369.   (cond ((zero? i)
  370.      (compare cc 0 r2))
  371.     ((fits-in-5-bits-signed? i)
  372.      (let* ((inverted? (memq cc '(TR <> >= > >>= >> NSV EV
  373.                      LTGT GTEQ GT GTGTEQ GTGT)))
  374.         (cc (if inverted? (invert-condition cc) cc))
  375.         (set-branches!
  376.          (lambda (if-true if-false)
  377.            (if inverted?
  378.                (set-current-branches! if-false if-true)
  379.                (set-current-branches! if-true if-false)))))
  380.     
  381.        (set-branches!
  382.         (lambda (label)
  383.           (LAP (COMIBTN (,cc) ,i ,r2 (@PCR ,label))))
  384.         (lambda (label)
  385.           (LAP (COMIBFN (,cc) ,i ,r2 (@PCR ,label)))))
  386.        (LAP)))
  387.     ((fits-in-11-bits-signed? i)
  388.      (set-current-branches!
  389.       (lambda (label)
  390.         (LAP (COMICLR (,(invert-condition cc)) ,i ,r2 0)
  391.          (B (N) (@PCR ,label))))
  392.       (lambda (label)
  393.         (LAP (COMICLR (,cc) ,i ,r2 0)
  394.          (B (N) (@PCR ,label)))))
  395.      (LAP))
  396.     (else
  397.      (let ((temp (standard-temporary!)))
  398.        (LAP ,@(load-immediate i temp)
  399.         ,@(compare cc temp r2))))))
  400.  
  401. (define (compare condition r1 r2)
  402.   (set-current-branches!
  403.    (lambda (label)
  404.      (LAP (COMBN (,condition) ,r1 ,r2 (@PCR ,label))))
  405.    (lambda (label)
  406.      (LAP (COMBN (,(invert-condition condition)) ,r1 ,r2 (@PCR ,label)))))
  407.   (LAP))
  408.  
  409. ;;;; Conditions
  410.  
  411. (define (invert-condition condition)
  412.   (let ((place (assq condition condition-inversion-table)))
  413.     (if (not place)
  414.     (error "unknown condition" condition))
  415.     (cadr place)))
  416.  
  417. (define (invert-condition-noncommutative condition)
  418.   (let ((place (assq condition condition-inversion-table)))
  419.     (if (not place)
  420.     (error "unknown condition" condition))
  421.     (caddr place)))
  422.  
  423. (define condition-inversion-table
  424.   '((=        <>        =)
  425.     (<        >=        >)
  426.     (>        <=        <)
  427.     (NUV    UV        NUV)
  428.     (TR        NV        TR)
  429.     (<<        >>=        >>)
  430.     (>>        <<=        <<)
  431.     (<>        =        <>)
  432.     (<=        >        >=)
  433.     (>=        <        <=)
  434.     (<<=    >>        >>=)
  435.     (>>=    <<        <<=)
  436.     (NV        TR        NV)
  437.     (EQ        LTGT        EQ)
  438.     (LT        GTEQ        GT)
  439.     (SBZ    NBZ        SBZ)
  440.     (LTEQ    GT        GTEQ)
  441.     (SHZ    NHZ        SHZ)
  442.     (LTLT    GTGTEQ        GTGT)
  443.     (SDC    NDC        SDC)
  444.     (LTLTEQ    GTGT        GTGTEQ)
  445.     (ZNV    VNZ        ZNV)
  446.     (SV        NSV        SV)
  447.     (SBC    NBC        SBC)
  448.     (OD        EV        OD)
  449.     (SHC    NHC        SHC)
  450.     (LTGT    EQ        LTGT)
  451.     (GTEQ    LT        LTEQ)
  452.     (NBZ    SBZ        NBZ)
  453.     (GT        LTEQ        LT)
  454.     (NHZ    SHZ        NHZ)
  455.     (GTGTEQ    LTLT        LTLTEQ)
  456.     (UV        NUV        UV)
  457.     (NDC    SDC        NDC)
  458.     (GTGT    LTLTEQ        LTLT)
  459.     (VNZ    ZNV        NVZ)
  460.     (NSV    SV        NSV)
  461.     (NBC    SBC        NBC)
  462.     (EV        OD        EV)
  463.     (NHC    SHC        NHC)))
  464.  
  465. ;;;; Miscellaneous
  466.  
  467. (define-integrable (object->datum src tgt)
  468.   (LAP (ZDEP () ,src 31 ,scheme-datum-width ,tgt)))
  469.  
  470. (define-integrable (object->address reg)
  471.   (LAP (DEP ()
  472.         ,regnum:quad-bitmask
  473.         ,(-1+ scheme-type-width)
  474.         ,scheme-type-width
  475.         ,reg)))
  476.  
  477. (define-integrable (object->type src tgt)
  478.   (LAP (EXTRU () ,src ,(-1+ scheme-type-width) ,scheme-type-width ,tgt)))
  479.  
  480. (define (standard-unary-conversion source target conversion)
  481.   ;; `source' is any register, `target' a pseudo register.
  482.   (let ((source (standard-source! source)))
  483.     (conversion source (standard-target! target))))
  484.  
  485. (define (standard-binary-conversion source1 source2 target conversion)
  486.   ;; The sources are any register, `target' a pseudo register.
  487.   (let ((source1 (standard-source! source1))
  488.     (source2 (standard-source! source2)))
  489.     (conversion source1 source2 (standard-target! target))))
  490.  
  491. (define (standard-source! register)
  492.   (load-alias-register! register (register-type register)))
  493.  
  494. (define (standard-target! register)
  495.   (delete-dead-registers!)
  496.   (allocate-alias-register! register (register-type register)))
  497.  
  498. (define-integrable (standard-temporary!)
  499.   (allocate-temporary-register! 'GENERAL))
  500.  
  501. (define (standard-move-to-target! source target)
  502.   (move-to-alias-register! source (register-type source) target))
  503.  
  504. (define (standard-move-to-temporary! source)
  505.   (move-to-temporary-register! source (register-type source)))
  506.  
  507. (define (register-expression expression)
  508.   (case (rtl:expression-type expression)
  509.     ((REGISTER)
  510.      (rtl:register-number expression))
  511.     ((CONSTANT)
  512.      (let ((object (rtl:constant-value expression)))
  513.        (and (zero? (object-type object))
  514.         (zero? (object-datum object))
  515.         0)))
  516.     ((CONS-POINTER)
  517.      (and (let ((type (rtl:cons-pointer-type expression)))
  518.         (and (rtl:machine-constant? type)
  519.          (zero? (rtl:machine-constant-value type))))
  520.       (let ((datum (rtl:cons-pointer-datum expression)))
  521.         (and (rtl:machine-constant? datum)
  522.          (zero? (rtl:machine-constant-value datum))))
  523.       0))
  524.     (else false)))
  525.  
  526. (define (define-arithmetic-method operator methods method)
  527.   (let ((entry (assq operator (cdr methods))))
  528.     (if entry
  529.     (set-cdr! entry method)
  530.     (set-cdr! methods (cons (cons operator method) (cdr methods)))))
  531.   operator)
  532.  
  533. (define (lookup-arithmetic-method operator methods)
  534.   (cdr (or (assq operator (cdr methods))
  535.        (error "Unknown operator" operator))))
  536.  
  537. (define-integrable (arithmetic-method? operator methods)
  538.   (assq operator (cdr methods)))  
  539.  
  540. (define (fits-in-5-bits-signed? value)
  541.   (<= #x-10 value #xF))
  542.  
  543. (define (fits-in-11-bits-signed? value)
  544.   (<= #x-400 value #x3FF))
  545.  
  546. (define (fits-in-14-bits-signed? value)
  547.   (<= #x-2000 value #x1FFF))
  548.  
  549. (define-integrable (ea/mode ea) (car ea))
  550. (define-integrable (register-ea/register ea) (cadr ea))
  551. (define-integrable (offset-ea/offset ea) (cadr ea))
  552. (define-integrable (offset-ea/space ea) (caddr ea))
  553. (define-integrable (offset-ea/register ea) (cadddr ea))
  554.  
  555. (define (pseudo-register-displacement register)
  556.   ;; Register block consists of 16 4-byte registers followed by 256
  557.   ;; 8-byte temporaries.
  558.   (+ (* 4 16) (* 8 (register-renumber register))))
  559.  
  560. (define-integrable (float-register->fpr register)
  561.   ;; Float registers are represented by 32 through 47/63 in the RTL,
  562.   ;; corresponding to registers 0 through 15/31 in the machine.
  563.   (- register 32))
  564.  
  565. (define-integrable (fpr->float-register register)
  566.   (+ register 32))
  567.  
  568. (define-integrable reg:memtop
  569.   (INST-EA (OFFSET #x0000 0 ,regnum:regs-pointer)))
  570.  
  571. (define-integrable reg:environment
  572.   (INST-EA (OFFSET #x000C 0 ,regnum:regs-pointer)))
  573.  
  574. (define-integrable reg:lexpr-primitive-arity
  575.   (INST-EA (OFFSET #x001C 0 ,regnum:regs-pointer)))
  576.  
  577. (define-integrable reg:stack-guard
  578.   (INST-EA (OFFSET #x002C 0 ,regnum:regs-pointer)))
  579.  
  580. (define (lap:make-label-statement label)
  581.   (LAP (LABEL ,label)))
  582.  
  583. (define (lap:make-unconditional-branch label)
  584.   (LAP (B (N) (@PCR ,label))))
  585.  
  586. (define (lap:make-entry-point label block-start-label)
  587.   block-start-label
  588.   (LAP (ENTRY-POINT ,label)
  589.        ,@(make-external-label expression-code-word label)))
  590.  
  591. ;;;; Codes and Hooks
  592.  
  593. (let-syntax ((define-codes
  594.            (macro (start . names)
  595.          (define (loop names index)
  596.            (if (null? names)
  597.                '()
  598.                (cons `(DEFINE-INTEGRABLE
  599.                 ,(symbol-append 'CODE:COMPILER-
  600.                         (car names))
  601.                 ,index)
  602.                  (loop (cdr names) (1+ index)))))
  603.          `(BEGIN ,@(loop names start)))))
  604.   (define-codes #x012
  605.     primitive-apply primitive-lexpr-apply
  606.     apply error lexpr-apply link
  607.     interrupt-closure interrupt-dlink interrupt-procedure 
  608.     interrupt-continuation interrupt-ic-procedure
  609.     assignment-trap cache-reference-apply
  610.     reference-trap safe-reference-trap unassigned?-trap
  611.     -1+ &/ &= &> 1+ &< &- &* negative? &+ positive? zero?
  612.     access lookup safe-lookup unassigned? unbound?
  613.     set! define lookup-apply primitive-error
  614.     quotient remainder modulo
  615.     reflect-to-interface interrupt-continuation-2
  616.     compiled-code-bkpt compiled-closure-bkpt))
  617.  
  618. (define-integrable (invoke-interface-ble code)
  619.   ;; Jump to scheme-to-interface-ble
  620.   (LAP (BLE () (OFFSET 0 4 ,regnum:scheme-to-interface-ble))
  621.        (LDI () ,code 28)))
  622.  
  623. ;;; trampoline-to-interface uses (OFFSET 4 4 ,regnum:scheme-to-interface-ble)
  624.  
  625. (define-integrable (invoke-interface code)
  626.   ;; Jump to scheme-to-interface
  627.   (LAP (BLE () (OFFSET 12 4 ,regnum:scheme-to-interface-ble))
  628.        (LDI () ,code 28)))
  629.  
  630. (let-syntax ((define-hooks
  631.            (macro (start . names)
  632.          (define (loop names index)
  633.            (if (null? names)
  634.                '()
  635.                (cons `(DEFINE-INTEGRABLE
  636.                 ,(symbol-append 'HOOK:COMPILER-
  637.                         (car names))
  638.                 ,index)
  639.                  (loop (cdr names) (+ 8 index)))))
  640.          `(BEGIN ,@(loop names start)))))
  641.   (define-hooks 100
  642.     store-closure-code
  643.     store-closure-entry            ; newer version of store-closure-code.
  644.     multiply-fixnum
  645.     fixnum-quotient
  646.     fixnum-remainder
  647.     fixnum-lsh
  648.     &+
  649.     &-
  650.     &*
  651.     &/
  652.     &=
  653.     &<
  654.     &>
  655.     1+
  656.     -1+
  657.     zero?
  658.     positive?
  659.     negative?
  660.     shortcircuit-apply
  661.     shortcircuit-apply-1
  662.     shortcircuit-apply-2
  663.     shortcircuit-apply-3
  664.     shortcircuit-apply-4
  665.     shortcircuit-apply-5
  666.     shortcircuit-apply-6
  667.     shortcircuit-apply-7
  668.     shortcircuit-apply-8
  669.     stack-and-interrupt-check
  670.     invoke-primitive
  671.     vector-cons
  672.     string-allocate
  673.     floating-vector-cons
  674.     flonum-sin
  675.     flonum-cos
  676.     flonum-tan
  677.     flonum-asin
  678.     flonum-acos
  679.     flonum-atan
  680.     flonum-exp
  681.     flonum-log
  682.     flonum-truncate
  683.     flonum-ceiling
  684.     flonum-floor
  685.     flonum-atan2
  686.     compiled-code-bkpt
  687.     compiled-closure-bkpt
  688.     copy-closure-pattern
  689.     copy-multiclosure-pattern))
  690.  
  691. ;; There is a NOP here because otherwise the return address would have 
  692. ;; to be adjusted by the hook code.  This gives more flexibility to the
  693. ;; compiler since it may be able to eliminate the NOP by moving an
  694. ;; instruction preceding the BLE to the delay slot.
  695.  
  696. (define (invoke-hook hook)
  697.   (LAP (BLE () (OFFSET ,hook 4 ,regnum:scheme-to-interface-ble))
  698.        (NOP ())))
  699.  
  700. ;; This is used when not returning.  It uses BLE instead of BE as a debugging
  701. ;; aid.  The hook gets a return address pointing to the caller, even
  702. ;; though the code will not return.
  703.  
  704. (define (invoke-hook/no-return hook)
  705.   (LAP (BLE (N) (OFFSET ,hook 4 ,regnum:scheme-to-interface-ble))))
  706.  
  707. (define (require-registers! . regs)
  708.   (let ((code (apply clear-registers! regs)))
  709.     (need-registers! regs)
  710.     code))
  711.  
  712. (define (load-interface-args! first second third fourth)
  713.   (let ((clear-regs
  714.      (apply clear-registers!
  715.         (append (if first (list regnum:first-arg) '())
  716.             (if second (list regnum:second-arg) '())
  717.             (if third (list regnum:third-arg) '())
  718.             (if fourth (list regnum:fourth-arg) '()))))
  719.     (load-reg
  720.      (lambda (reg arg)
  721.        (if reg (load-machine-register! reg arg) (LAP)))))
  722.     (let ((load-regs
  723.        (LAP ,@(load-reg first regnum:first-arg)
  724.         ,@(load-reg second regnum:second-arg)
  725.         ,@(load-reg third regnum:third-arg)
  726.         ,@(load-reg fourth regnum:fourth-arg))))
  727.       (LAP ,@clear-regs
  728.        ,@load-regs
  729.        ,@(clear-map!)))))
  730.  
  731.  
  732. (define (pre-lapgen-analysis rgraphs)
  733.   rgraphs
  734.   unspecific)