OSDN Git Service

daily update
[pf3gnuchains/pf3gnuchains3x.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 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 ; Structures.
82 ; FIXME: Unfinished.
83
84 (define <struct> (class-make '<struct> nil '(members) nil))
85
86 ; Parse a type spec.
87 ; TYPE-SPEC is: (mode [(dimensions ...)])
88 ;           or: ((mode bits) [(dimensions ...)])
89
90 (define (parse-type errtxt type-spec)
91   ; Preliminary error checking.
92   (if (and (list? (car type-spec))
93            (not (= (length (car type-spec)) 2)))
94       (parse-error errtxt "invalid type spec" type-spec))
95
96   ; Pick out the arguments.
97   (let ((mode (if (list? (car type-spec)) (caar type-spec) (car type-spec)))
98         (bits (if (list? (car type-spec)) (cadar type-spec) #f))
99         (dims (if (> (length type-spec) 1) (cadr type-spec) nil)))
100
101     ; FIXME: Need more error checking here.
102     ; Validate the mode and bits.
103     (let ((mode-obj
104            (case mode
105              ((INT)
106               (if (integer? bits)
107                   (mode-make-int bits)
108                   (parse-error errtxt "invalid number of bits" bits)))
109              ((UINT)
110               (if (integer? bits)
111                   (mode-make-uint bits)
112                   (parse-error errtxt "invalid number of bits" bits)))
113              ((BI QI HI SI DI WI UQI UHI USI UDI UWI SF DF XF TF)
114               (let ((x (parse-mode-name mode errtxt)))
115                 (if (and bits (not (= bits (mode:bits x))))
116                     (parse-error errtxt "wrong number of bits for mode" bits))
117                 x))
118              (else (parse-error errtxt "unknown/unsupported mode" mode)))))
119
120       ; Validate the dimension spec.
121       (if (or (not (list? dims))
122               (not (all-true? (map integer? dims))))
123           (parse-error errtxt "invalid dimension spec" dims))
124
125       ; All done, create the <array> object.
126       ; ??? Special casing scalars is a concession for apps that think
127       ; scalars aren't arrays.  Not sure it should stay.
128       (if (null? dims)
129           (make <scalar> mode-obj)
130           (make <array> mode-obj dims))))
131 )
132 \f
133 ; Bit ranges.
134 ; ??? Perhaps this should live in a different source file, but for now
135 ; it's here.
136 ;
137 ; Endianness is not recorded with the bitrange.
138 ; Values are operated on a "word" at a time.
139 ; This is to handle bi-endian systems: we don't want two copies of
140 ; every bitrange.
141 ;
142 ; Instruction word sizes are based on the "base insn length" which is the
143 ; number of bytes the cpu first looks at to decode an insn.  In cases where
144 ; the total length is longer than the base insn length, the word length
145 ; for the rest of the insn is the base insn length replicated as many times
146 ; as necessary.  The trailing part [last few bytes] of the insn may not fill
147 ; the entire word, in which case the numbering is adjusted for it.
148 ; ??? Might need to have an insn-base-length and an insn-word-length.
149 ;
150 ; Instructions that have words of one endianness and sub-words of a different
151 ; endianness are handled at a higher level.
152 ;
153 ; Bit numbering examples:
154 ; [each byte is represented MSB to LSB, low address to high address]
155 ;
156 ; lsb0? = #f
157 ; insn-word-length = 2
158 ; endian = little
159 ; | 8 ... 15 | 0 ... 7 | 24 ... 31 | 16 ... 23 | 40 ... 47 | 32 ... 39 |
160 ;
161 ; lsb0? = #t
162 ; insn-word-length = 2
163 ; endian = little
164 ; [note that this is the little endian canonical form (*)
165 ;  - word length is irrelevant]
166 ; | 7 ... 0 | 15 ... 8 | 23 ... 16 | 31 ... 24 | 39 ... 32 | 47 ... 40 |
167 ;
168 ; lsb0? = #f
169 ; insn-word-length = 2
170 ; endian = big
171 ; [note that this is the big endian canonical form (*)
172 ;  - word length is irrelevant]
173 ; | 0 ... 7 | 8 ... 15 | 16 ... 23 | 24 ... 31 | 32 ... 39 | 40 ... 47 |
174 ;
175 ; lsb0? = #t
176 ; insn-word-length = 2
177 ; endian = big
178 ; | 15 ... 8 | 7 ... 0 | 31 ... 24 | 23 ... 16 | 47 ... 40 | 39 ... 32 |
179 ;
180 ; (*) NOTE: This canonical form should not be confused with what might be
181 ; called the canonical form when writing .cpu ifield descriptions: lsb0? = #f.
182 ; The ifield canonical form is lsb0? = #f because the starting bit number of
183 ; ifields is defined to be the MSB.
184 ; ---
185 ; At the bitrange level, insns with different sized words is supported.
186 ; This is because each <bitrange> contains the specs of the word it resides in.
187 ; For example a 48 bit insn with a 16 bit opcode and a 32 bit immediate value
188 ; might [but not necessarily] consist of one 16 bit "word" and one 32 bit
189 ; "word".
190 ;
191 ; Examples:
192 ;
193 ; lsb0? = #f
194 ; insn-word-length = 2, 4
195 ; endian = little
196 ; | 8 ... 15 | 0 ... 7 | 40 ... 47 | 32 ... 39 | 24 ... 31 | 16 ... 23 |
197 ;
198 ; lsb0? = #t
199 ; insn-word-length = 2, 4
200 ; endian = little
201 ; | 7 ... 0 | 15 ... 8 | 23 ... 16 | 31 ... 24 | 39 ... 32 | 47 ... 40 |
202 ;
203 ; lsb0? = #f
204 ; insn-word-length = 2, 4
205 ; endian = big
206 ; | 0 ... 7 | 8 ... 15 | 16 ... 23 | 24 ... 31 | 32 ... 39 | 40 ... 47 |
207 ;
208 ; lsb0? = #t
209 ; insn-word-length = 2, 4
210 ; endian = big
211 ; | 15 ... 8 | 7 ... 0 | 47 ... 40 | 39 ... 32 | 31 ... 24 | 23 ... 16 |
212
213 (define <bitrange>
214   (class-make '<bitrange>
215               nil
216               '(
217                 ; offset in bits from the start of the insn of the word
218                 ; in which the value resides [must be divisible by 8]
219                 ; [this allows the bitrange to be independent of the lengths
220                 ; of words preceding this one]
221                 word-offset
222                 ; starting bit number within the word,
223                 ; this is the MSB of the bitrange within the word
224                 ; [externally, = word-offset + start]
225                 start
226                 ; number of bits in the value
227                 length
228                 ; length of word in which the value resides
229                 word-length
230                 ; lsb = bit number 0?
231                 lsb0?
232                 )
233               nil)
234 )
235
236 ; Accessor fns.
237
238 (define-getters <bitrange> bitrange
239   (word-offset start length word-length lsb0?)
240 )
241
242 (define-setters <bitrange> bitrange
243   ; lsb0? left out on purpose: not sure changing it should be allowed
244   (word-offset start length word-length)
245 )
246
247 ; Return a boolean indicating if two bitranges overlap.
248 ;
249 ; lsb0? = #t: 31 ...  0
250 ; lsb0? = #f: 0  ... 31
251
252 (define (bitrange-overlap? start1 length1 start2 length2 lsb0?)
253   (if lsb0?
254       (let ((end1 (- start1 length1))
255             (end2 (- start2 length2)))
256         (and (< end1 start2)
257              (> start1 end2)))
258       (let ((end1 (+ start1 length1))
259             (end2 (+ start2 length2)))
260         (and (> end1 start2)
261              (< start1 end2))))
262 )
263
264 ; Return a boolean indicating if BITPOS is beyond bitrange START,LEN.
265 ; ??? This needs more thought.
266
267 (define (bitpos-beyond? bitpos start length word-length lsb0?)
268   (>= bitpos (+ start length))
269 )
270
271 ; Return the offset of the word after <bitrange> br.
272
273 (define (bitrange-next-word br)
274   (let ((word-offset (bitrange-word-offset br))
275         (start (bitrange-start br))
276         (length (bitrange-length br))
277         (word-length (bitrange-word-length br))
278         (lsb0? (bitrange-lsb0? br)))
279     ; ??? revisit
280     (+ word-offset word-length))
281 )
282 \f
283 ; Initialize/finalize support.
284
285 (define (types-init!)
286   *UNSPECIFIED*
287 )
288
289 (define (types-finish!)
290   *UNSPECIFIED*
291 )