OSDN Git Service

* read.scm (/cmd-include): Fix absolute path handling.
[pf3gnuchains/pf3gnuchains4x.git] / cgen / types.scm
1 ; Type system.
2 ; This provides the low level classes for describing data, except for
3 ; the actual type (confusingly enough) which is described in mode.scm.
4 ; Copyright (C) 2000, 2009 Red Hat, Inc.
5 ; This file is part of CGEN.
6 ; See file COPYING.CGEN for details.
7
8 ; Array type.
9 ; DIMENSIONS has a suitable initial value so (new <scalar>) to works.
10
11 (define <array> (class-make '<array> nil '(mode (dimensions . ())) nil))
12
13 ; Return number of elements in array.
14
15 (method-make!
16  <array> 'get-num-elms
17  (lambda (self)
18    (apply * (elm-get self 'dimensions)))
19 )
20
21 ; Return mode of the array.
22
23 (method-make! <array> 'get-mode (lambda (self) (elm-get self 'mode)))
24
25 ; Return the rank of the array (number of dimensions).
26
27 (method-make! <array> 'get-rank (lambda (self) (length (elm-get self 'dimensions)))
28 )
29
30 ; Return shape of array
31
32 (method-make! <array> 'get-shape (lambda (self) (elm-get self 'dimensions))
33 )
34
35 ; Return #t if X is an array.
36
37 (define (array? x) (class-instance? <array> x))
38
39 ; Scalar type.
40
41 (define <scalar> (class-make '<scalar> '(<array>) nil nil))
42
43 (method-make-make! <scalar> '(mode))
44
45 ; Return #t if X is a scalar.
46
47 (define (scalar? x) (and (array? x) (= (send x 'get-rank) 0)))
48
49 ; Return number of bits in an element of TYPE.
50
51 (define (type-bits type)
52   (mode:bits (send type 'get-mode))
53 )
54 \f
55 ; Integers.
56 ; These are like scalars but are specified in bits.
57 ; BITS is the size in bits.
58 ; ATTRS contains !UNSIGNED [or nothing] or UNSIGNED.
59 ;
60 ; A mode is needed so we know how big a field is needed to record the value.
61 ; It might be more appropriate to use a host mode though.
62 ;
63 ; FIXME: Need to separate rank from type.  scalar/array are not types.
64 ;
65 ;(define <integer> (class-make '<integer> nil '(attrs bits) nil))
66 ;
67 ;(method-make! <integer> 'get-atlist (lambda (self) (elm-get self 'attrs)))
68 ;
69 ;(method-make!
70 ; <integer> 'get-mode 
71 ; (lambda (self)
72 ;   (mode-find (elm-get self 'bits)
73 ;             (if (has-attr? self 'UNSIGNED) 'UINT 'INT))
74 ;   )
75 ;)
76 ;
77 ; FIXME: Quick hack.  Revisit.
78 ;
79 ;(method-make! <integer> 'get-rank (lambda (self) 0))
80
81 ; Parse a type spec.
82 ; TYPE-SPEC is: (mode [(dimensions ...)])
83 ;           or: ((mode bits) [(dimensions ...)])
84
85 (define (parse-type context type-spec)
86   ; Preliminary error checking.
87   (let ((expected
88          ", expected (mode [(dimensions)]) or ((mode bits) [(dimensions)])"))
89     (if (not (list? type-spec))
90         (parse-error context (string-append "invalid type spec" expected)
91                      type-spec))
92     (let ((len (length type-spec)))
93       (if (or (< len 1)
94               (> len 2))
95           (parse-error context (string-append "invalid type spec" expected)
96                        type-spec))
97       ; Validate the mode spec.
98       (cond ((symbol? (car type-spec))
99              #t) ; ok
100             ((list? (car type-spec))
101              (begin
102                (if (not (= (length (car type-spec)) 2))
103                    (parse-error context
104                                 (string-append "invalid mode in type spec"
105                                                expected)
106                                 type-spec))
107                (if (not (symbol? (caar type-spec)))
108                    (parse-error context
109                                 (string-append "invalid mode in type spec"
110                                                expected)
111                                 type-spec))
112                (if (not (integer? (cadar type-spec)))
113                    (parse-error context
114                                 (string-append "invalid #bits in type spec"
115                                                expected)
116                                 type-spec))
117                ))
118              (else
119               (parse-error context
120                            (string-append "invalid mode in type spec" expected)
121                            type-spec)))
122       ; Validate the dimension list if present.
123       (if (= len 2)
124           (if (or (not (list? (cadr type-spec)))
125                   (not (all-true? (map non-negative-integer?
126                                        (cadr type-spec)))))
127               (parse-error context
128                            (string-append "invalid dimension spec in type spec"
129                                           expected)
130                            type-spec)))
131       ))
132
133   ; Pick out the arguments.
134   (let ((mode (if (list? (car type-spec)) (caar type-spec) (car type-spec)))
135         (bits (if (list? (car type-spec)) (cadar type-spec) #f))
136         (dims (if (> (length type-spec) 1) (cadr type-spec) nil)))
137
138     ; Look up the mode and create the mode object.
139     (let* ((base-mode (parse-mode-name context mode))
140            (mode-obj
141             (cond ((eq? mode 'INT)
142                    (mode-make-int bits))
143                   ((eq? mode 'UINT)
144                    (mode-make-uint bits))
145                   (else
146                    (if (and bits (!= bits (mode:bits base-mode)))
147                        (parse-error context "wrong number of bits for mode"
148                                     bits))
149                    base-mode))))
150
151       ; All done, create the <array> object.
152       ; ??? Special casing scalars is a concession for apps that think
153       ; scalars aren't arrays.  Not sure it should stay.
154       (if (null? dims)
155           (make <scalar> mode-obj)
156           (make <array> mode-obj dims))))
157 )
158 \f
159 ; Bit ranges.
160 ; ??? Perhaps this should live in a different source file, but for now
161 ; it's here.
162 ;
163 ; Endianness is not recorded with the bitrange.
164 ; Values are operated on a "word" at a time.
165 ; This is to handle bi-endian systems: we don't want two copies of
166 ; every bitrange.
167 ;
168 ; Instruction word sizes are based on the "base insn length" which is the
169 ; number of bytes the cpu first looks at to decode an insn.  In cases where
170 ; the total length is longer than the base insn length, the word length
171 ; for the rest of the insn is the base insn length replicated as many times
172 ; as necessary.  The trailing part [last few bytes] of the insn may not fill
173 ; the entire word, in which case the numbering is adjusted for it.
174 ; ??? Might need to have an insn-base-length and an insn-word-length.
175 ;
176 ; Instructions that have words of one endianness and sub-words of a different
177 ; endianness are handled at a higher level.
178 ;
179 ; Bit numbering examples:
180 ; [each byte is represented MSB to LSB, low address to high address]
181 ;
182 ; lsb0? = #f
183 ; insn-word-length = 2
184 ; endian = little
185 ; | 8 ... 15 | 0 ... 7 | 24 ... 31 | 16 ... 23 | 40 ... 47 | 32 ... 39 |
186 ;
187 ; lsb0? = #t
188 ; insn-word-length = 2
189 ; endian = little
190 ; [note that this is the little endian canonical form (*)
191 ;  - word length is irrelevant]
192 ; | 7 ... 0 | 15 ... 8 | 23 ... 16 | 31 ... 24 | 39 ... 32 | 47 ... 40 |
193 ;
194 ; lsb0? = #f
195 ; insn-word-length = 2
196 ; endian = big
197 ; [note that this is the big endian canonical form (*)
198 ;  - word length is irrelevant]
199 ; | 0 ... 7 | 8 ... 15 | 16 ... 23 | 24 ... 31 | 32 ... 39 | 40 ... 47 |
200 ;
201 ; lsb0? = #t
202 ; insn-word-length = 2
203 ; endian = big
204 ; | 15 ... 8 | 7 ... 0 | 31 ... 24 | 23 ... 16 | 47 ... 40 | 39 ... 32 |
205 ;
206 ; (*) NOTE: This canonical form should not be confused with what might be
207 ; called the canonical form when writing .cpu ifield descriptions: lsb0? = #f.
208 ; The ifield canonical form is lsb0? = #f because the starting bit number of
209 ; ifields is defined to be the MSB.
210 ; ---
211 ; At the bitrange level, insns with different sized words is supported.
212 ; This is because each <bitrange> contains the specs of the word it resides in.
213 ; For example a 48 bit insn with a 16 bit opcode and a 32 bit immediate value
214 ; might [but not necessarily] consist of one 16 bit "word" and one 32 bit
215 ; "word".
216 ;
217 ; Examples:
218 ;
219 ; lsb0? = #f
220 ; insn-word-length = 2, 4
221 ; endian = little
222 ; | 8 ... 15 | 0 ... 7 | 40 ... 47 | 32 ... 39 | 24 ... 31 | 16 ... 23 |
223 ;
224 ; lsb0? = #t
225 ; insn-word-length = 2, 4
226 ; endian = little
227 ; | 7 ... 0 | 15 ... 8 | 23 ... 16 | 31 ... 24 | 39 ... 32 | 47 ... 40 |
228 ;
229 ; lsb0? = #f
230 ; insn-word-length = 2, 4
231 ; endian = big
232 ; | 0 ... 7 | 8 ... 15 | 16 ... 23 | 24 ... 31 | 32 ... 39 | 40 ... 47 |
233 ;
234 ; lsb0? = #t
235 ; insn-word-length = 2, 4
236 ; endian = big
237 ; | 15 ... 8 | 7 ... 0 | 47 ... 40 | 39 ... 32 | 31 ... 24 | 23 ... 16 |
238
239 (define <bitrange>
240   (class-make '<bitrange>
241               nil
242               '(
243                 ; offset in bits from the start of the insn of the word
244                 ; in which the value resides [must be divisible by 8]
245                 ; [this allows the bitrange to be independent of the lengths
246                 ; of words preceding this one]
247                 word-offset
248                 ; starting bit number within the word,
249                 ; this is the MSB of the bitrange within the word
250                 ; [externally, = word-offset + start]
251                 start
252                 ; number of bits in the value
253                 length
254                 ; length of word in which the value resides
255                 word-length
256                 ; lsb = bit number 0?
257                 lsb0?
258                 )
259               nil)
260 )
261
262 ; Accessor fns.
263
264 (define-getters <bitrange> bitrange
265   (word-offset start length word-length lsb0?)
266 )
267
268 (define-setters <bitrange> bitrange
269   ; lsb0? left out on purpose: not sure changing it should be allowed
270   (word-offset start length word-length)
271 )
272
273 ; Return a boolean indicating if two bitranges overlap.
274 ;
275 ; lsb0? = #t: 31 ...  0
276 ; lsb0? = #f: 0  ... 31
277
278 (define (bitrange-overlap? start1 length1 start2 length2 lsb0?)
279   (if lsb0?
280       (let ((end1 (- start1 length1))
281             (end2 (- start2 length2)))
282         (and (< end1 start2)
283              (> start1 end2)))
284       (let ((end1 (+ start1 length1))
285             (end2 (+ start2 length2)))
286         (and (> end1 start2)
287              (< start1 end2))))
288 )
289
290 ; Return a boolean indicating if BITPOS is beyond bitrange START,LEN.
291 ; ??? This needs more thought.
292
293 (define (bitpos-beyond? bitpos start length word-length lsb0?)
294   (>= bitpos (+ start length))
295 )
296
297 ; Return the offset of the word after <bitrange> br.
298
299 (define (bitrange-next-word br)
300   (let ((word-offset (bitrange-word-offset br))
301         (start (bitrange-start br))
302         (length (bitrange-length br))
303         (word-length (bitrange-word-length br))
304         (lsb0? (bitrange-lsb0? br)))
305     ; ??? revisit
306     (+ word-offset word-length))
307 )
308 \f
309 ; Initialize/finalize support.
310
311 (define (types-init!)
312   *UNSPECIFIED*
313 )
314
315 (define (types-finish!)
316   *UNSPECIFIED*
317 )