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 / back / bitutl.scm < prev    next >
Encoding:
Text File  |  1999-01-02  |  10.3 KB  |  335 lines

  1. #| -*-Scheme-*-
  2.  
  3. $Id: bitutl.scm,v 1.10 1999/01/02 06:06:43 cph Exp $
  4.  
  5. Copyright (c) 1987-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. ;;;; Assembler utilities
  23. ;;; package: (compiler assembler)
  24.  
  25. (declare (usual-integrations))
  26.  
  27. (define-integrable (make-queue)
  28.   (cons '() '()))
  29.  
  30. (define-integrable (queue->list queue)
  31.   (car queue))
  32.  
  33. (define (add-to-queue! queue entry)
  34.   (let ((new (cons entry '())))
  35.     (if (null? (cdr queue))
  36.     (set-car! queue new)
  37.     (set-cdr! (cdr queue) new))
  38.     (set-cdr! queue new)))
  39.  
  40. (define-integrable (set-label-value! name low high)
  41.   (symbol-table-define! *the-symbol-table*
  42.             name
  43.             (label->machine-interval low high)))
  44.  
  45. (define (clear-symbol-table!)
  46.   (set! *the-symbol-table* (make-symbol-table))
  47.   unspecific)
  48.  
  49. (define (initialize-symbol-table!)
  50.   (symbol-table-define! *the-symbol-table* *start-label* 0))
  51.  
  52. (define (finish-symbol-table!)
  53.   (call-with-values
  54.       (lambda ()
  55.     (interval-values (symbol-table-value *the-symbol-table* *end-label*)))
  56.     (lambda (low high)
  57.       (do ((objects (queue->list *objects*) (cdr objects))
  58.        (pcmin (->bitstring-pc low) (+ pcmin scheme-object-width))
  59.        (pcmax (->bitstring-pc high) (+ pcmax scheme-object-width)))
  60.       ((null? objects))
  61.     (set-label-value! (cadar objects) pcmin pcmax))))
  62.   (for-each (lambda (equate)
  63.           (symbol-table-define! *the-symbol-table*
  64.                     (car equate)
  65.                     (evaluate (cadr equate) #f)))
  66.         (queue->list *equates*)))
  67.  
  68. (define (variable-width-lengths v)
  69.   (let ((sel (vector-ref v 3)))
  70.     (if (null? sel)
  71.     (error "Bad variable width directive:" v))
  72.     (let ((l (selector/length (car sel))))
  73.       (let loop ((selectors (cdr sel)) (min l) (max l))
  74.     (if (null? selectors)
  75.         (values min max)
  76.         (let ((this (selector/length (car selectors))))
  77.           (cond ((< this min) (loop (cdr selectors) this max))
  78.             ((> this max) (loop (cdr selectors) min this))
  79.             (else         (loop (cdr selectors) min max)))))))))
  80.  
  81. (define-integrable (selector/handler sel)
  82.   (vector-ref sel 0))
  83.  
  84. (define-integrable (selector/length sel)
  85.   (vector-ref sel 1))
  86.  
  87. (define-integrable (selector/low sel)
  88.   (vector-ref sel 2))
  89.  
  90. (define-integrable (selector/high sel)
  91.   (vector-ref sel 3))
  92.  
  93. ;;;; Expression Evaluation
  94.  
  95. (define (evaluate expression pc-value)
  96.   (define (inner exp)
  97.     (cond ((pair? exp)
  98.        ((find-operator (car exp))
  99.         (inner (cadr exp))
  100.         (inner (caddr exp))))
  101.       ((number? exp) exp)
  102.       ((not (symbol? exp))
  103.        (error "evaluate: bad expression" exp))
  104.       ((eq? exp '*PC*)
  105.        (if (not pc-value)
  106.            (error "evaluate: *PC* found with no PC defined"))
  107.        pc-value)
  108.       (else
  109.        (symbol-table-value *the-symbol-table* exp))))
  110.   (inner expression))
  111.  
  112. (define (find-operator keyword)
  113.   (let ((place (assq keyword operators)))
  114.     (if (not place)
  115.     (error "evaluate: unknown operator:" keyword))
  116.     ((cdr place))))
  117.  
  118. (define operators
  119.   `((+ . ,(lambda () interval:+))
  120.     (- . ,(lambda () interval:-))
  121.     (* . ,(lambda () interval:*))
  122.     (/ . ,(lambda () interval:/))
  123.     (QUOTIENT . ,(lambda () interval:quotient))
  124.     (REMAINDER . ,(lambda () interval:remainder))))
  125.  
  126. (define-integrable (->machine-pc pc)
  127.   (paranoid-quotient pc addressing-granularity))
  128.  
  129. (define-integrable (->bitstring-pc pc)
  130.   (* pc addressing-granularity))
  131.  
  132. (define (paranoid-quotient dividend divisor)
  133.   (let ((result (integer-divide dividend divisor)))
  134.     (if (not (zero? (integer-divide-remainder result)))
  135.     (error "paranoid-quotient: not a multiple" dividend divisor))
  136.     (integer-divide-quotient result)))
  137.  
  138. (define (final-pad pcvalue)
  139.   (paddify pcvalue 0 scheme-object-width))
  140.  
  141. (define (paddify pc-val remdr divsr)
  142.   (let ((aremdr (remainder pc-val divsr)))
  143.     (+ pc-val
  144.        (if (<= aremdr remdr)
  145.        (- remdr aremdr)
  146.        (+ remdr (- divsr aremdr))))))
  147.  
  148. ;;;; Interval Arithmetic
  149.  
  150. (define-structure (interval (constructor %make-interval))
  151.   (offset #f read-only #t)
  152.   (segset #f read-only #t))
  153.  
  154. (define-integrable (label->machine-interval low high)
  155.   (make-interval 0
  156.          (list (make-segment (make-point (->machine-pc low)
  157.                          (->machine-pc high))
  158.                      1))))
  159.  
  160. (define (make-interval offset segset)
  161.   (if (null? segset)
  162.       offset
  163.       (%make-interval offset segset)))
  164.  
  165. (define (interval-values interval)
  166.   (if (interval? interval)
  167.       (let loop
  168.       ((result-1 (interval-offset interval))
  169.        (result-2 (interval-offset interval))
  170.        (base-1 0)
  171.        (base-2 0)
  172.        (segset (interval-segset interval)))
  173.     (if (null? segset)
  174.         (if (<= result-1 result-2)
  175.         (values result-1 result-2)
  176.         (values result-2 result-1))
  177.         (let ((position-1 (segment-min (car segset)))
  178.           (position-2 (segment-max (car segset)))
  179.           (k (segment-coeff (car segset))))
  180.           (loop (+ result-1 (* (- position-1 base-1) k))
  181.             (+ result-2 (* (- position-2 base-2) k))
  182.             position-1
  183.             position-2
  184.             (cdr segset)))))
  185.       (values interval interval)))
  186.  
  187. (define (interval-final-value interval)
  188.   (if (interval? interval)
  189.       (let loop
  190.       ((result (interval-offset interval))
  191.        (base 0)
  192.        (segset (interval-segset interval)))
  193.     (if (null? segset)
  194.         result
  195.         (let ((position (segment-min (car segset)))
  196.           (k (segment-coeff (car segset))))
  197.           (loop (+ result (* (- position base) k))
  198.             position
  199.             (cdr segset)))))
  200.       interval))
  201.  
  202. (define (interval:+ a b)
  203.   (if (interval? a)
  204.       (if (interval? b)
  205.       (make-interval (+ (interval-offset a) (interval-offset b))
  206.              (segset:+ (interval-segset a) (interval-segset b)))
  207.       (make-interval (+ (interval-offset a) b) (interval-segset a)))
  208.       (if (interval? b)
  209.       (make-interval (+ a (interval-offset b)) (interval-segset b))
  210.       (+ a b))))
  211.  
  212. (define (interval:- a b)
  213.   (if (interval? a)
  214.       (if (interval? b)
  215.       (make-interval (- (interval-offset a) (interval-offset b))
  216.              (segset:- (interval-segset a) (interval-segset b)))
  217.       (make-interval (- (interval-offset a) b) (interval-segset a)))
  218.       (if (interval? b)
  219.       (make-interval (- a (interval-offset b))
  220.              (segset:negate (interval-segset b)))
  221.       (- a b))))
  222.  
  223. (define (interval:* a b)
  224.   (if (interval? a)
  225.       (if (interval? b)
  226.       (error "Can't multiply two intervals:" a b)
  227.       (make-interval (* (interval-offset a) b)
  228.              (segset:scale (interval-segset a) b)))
  229.       (if (interval? b)
  230.       (make-interval (* (interval-offset b) a)
  231.              (segset:scale (interval-segset b) a))
  232.       (* a b))))
  233.  
  234. ;;; Integer division on intervals is hard because the numerator of the
  235. ;;; division is a summation.  For exact division we can just check the
  236. ;;; sum of the result to make sure it's an integer.  QUOTIENT and
  237. ;;; REMAINDER can't be done at all unless we constrain the remainder
  238. ;;; of the high and low values to be the same.
  239.  
  240. (define (interval:/ a b)
  241.   (if (interval? b)
  242.       (error "Can't divide by an interval:" b))
  243.   (if (interval? a)
  244.       (let ((result
  245.          (make-interval (/ (interval-offset a) b)
  246.                 (segset:scale (interval-segset a) (/ 1 b)))))
  247.     (if (not
  248.          (call-with-values (lambda () (interval-values result))
  249.            (lambda (low high)
  250.          (and (integer? low)
  251.               (integer? high)))))
  252.         (error "Interval division not exact:" a b))
  253.     result)
  254.       (paranoid-quotient a b)))
  255.  
  256. (define (interval:quotient a b)
  257.   (if (or (interval? a) (interval? b))
  258.       (error "QUOTIENT doesn't do intervals:" a b))
  259.   (quotient a b))
  260.  
  261. (define (interval:remainder a b)
  262.   (if (or (interval? a) (interval? b))
  263.       (error "REMAINDER doesn't do intervals:" a b))
  264.   (remainder a b))
  265.  
  266. ;;; A segment consists of an ending point and a coefficient.
  267. ;;; The ending point has a minimum and maximum non-negative integer value.
  268. ;;; The coefficient is an integer.
  269. ;;; min(s1)=min(s2) iff max(s1)=max(s2)
  270. ;;; min(s1)<min(s2) iff max(s1)<max(s2)
  271.  
  272. (define-integrable make-segment cons)
  273. (define-integrable segment-point car)
  274. (define-integrable segment-coeff cdr)
  275.  
  276. (define-integrable make-point cons)
  277. (define-integrable point-min car)
  278. (define-integrable point-max cdr)
  279.  
  280. (define-integrable (segment-min segment)
  281.   (point-min (segment-point segment)))
  282.  
  283. (define-integrable (segment-max segment)
  284.   (point-max (segment-point segment)))
  285.  
  286. (define-integrable (segment:< s1 s2)
  287.   (< (segment-min s1) (segment-min s2)))
  288.  
  289. (define-integrable (segment:= s1 s2)
  290.   (= (segment-min s1) (segment-min s2)))
  291.  
  292. ;;; A segset is a list of segments.
  293. ;;; The segments are sorted in order from least to greatest.
  294. ;;; There is an implicit starting point of zero.
  295.  
  296. (define (segset:+ a b)
  297.   (cond ((null? a) b)
  298.     ((null? b) a)
  299.     ((segment:< (car a) (car b))
  300.      (cons-segset (segment-point (car a))
  301.               (+ (segment-coeff (car a)) (segment-coeff (car b)))
  302.               (segset:+ (cdr a) b)))
  303.     (else
  304.      (cons-segset (segment-point (car b))
  305.               (+ (segment-coeff (car a)) (segment-coeff (car b)))
  306.               (segset:+ (if (segment:= (car a) (car b)) (cdr a) a)
  307.                 (cdr b))))))
  308.  
  309. (define (segset:- a b)
  310.   (cond ((null? a) (segset:negate b))
  311.     ((null? b) a)
  312.     ((segment:< (car a) (car b))
  313.      (cons-segset (segment-point (car a))
  314.               (- (segment-coeff (car a)) (segment-coeff (car b)))
  315.               (segset:- (cdr a) b)))
  316.     (else
  317.      (cons-segset (segment-point (car b))
  318.               (- (segment-coeff (car a)) (segment-coeff (car b)))
  319.               (segset:- (if (segment:= (car a) (car b)) (cdr a) a)
  320.                 (cdr b))))))
  321.  
  322. (define (segset:negate b)
  323.   (segset:scale b -1))
  324.  
  325. (define (segset:scale b c)
  326.   (if (null? b)
  327.       b
  328.       (cons (make-segment (segment-point (car b))
  329.               (* (segment-coeff (car b)) c))
  330.         (segset:scale (cdr b) c))))
  331.  
  332. (define (cons-segset point coeff segset)
  333.   (if (= coeff (if (null? segset) 0 (segment-coeff (car segset))))
  334.       segset
  335.       (cons (make-segment point coeff) segset)))