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.
9 ; DIMENSIONS has a suitable initial value so (new <scalar>) to works.
11 (define <array> (class-make '<array> nil '(mode (dimensions . ())) nil))
13 ; Return number of elements in array.
18 (apply * (elm-get self 'dimensions)))
21 ; Return mode of the array.
23 (method-make! <array> 'get-mode (lambda (self) (elm-get self 'mode)))
25 ; Return the rank of the array (number of dimensions).
27 (method-make! <array> 'get-rank (lambda (self) (length (elm-get self 'dimensions)))
30 ; Return shape of array
32 (method-make! <array> 'get-shape (lambda (self) (elm-get self 'dimensions))
35 ; Return #t if X is an array.
37 (define (array? x) (class-instance? <array> x))
41 (define <scalar> (class-make '<scalar> '(<array>) nil nil))
43 (method-make-make! <scalar> '(mode))
45 ; Return #t if X is a scalar.
47 (define (scalar? x) (and (array? x) (= (send x 'get-rank) 0)))
49 ; Return number of bits in an element of TYPE.
51 (define (type-bits type)
52 (mode:bits (send type 'get-mode))
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.
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.
63 ; FIXME: Need to separate rank from type. scalar/array are not types.
65 ;(define <integer> (class-make '<integer> nil '(attrs bits) nil))
67 ;(method-make! <integer> 'get-atlist (lambda (self) (elm-get self 'attrs)))
72 ; (mode-find (elm-get self 'bits)
73 ; (if (has-attr? self 'UNSIGNED) 'UINT 'INT))
77 ; FIXME: Quick hack. Revisit.
79 ;(method-make! <integer> 'get-rank (lambda (self) 0))
84 (define <struct> (class-make '<struct> nil '(members) nil))
87 ; TYPE-SPEC is: (mode [(dimensions ...)])
88 ; or: ((mode bits) [(dimensions ...)])
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))
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)))
101 ; FIXME: Need more error checking here.
102 ; Validate the mode and bits.
108 (parse-error errtxt "invalid number of bits" 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))
118 (else (parse-error errtxt "unknown/unsupported mode" mode)))))
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))
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.
129 (make <scalar> mode-obj)
130 (make <array> mode-obj dims))))
134 ; ??? Perhaps this should live in a different source file, but for now
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
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.
150 ; Instructions that have words of one endianness and sub-words of a different
151 ; endianness are handled at a higher level.
153 ; Bit numbering examples:
154 ; [each byte is represented MSB to LSB, low address to high address]
157 ; insn-word-length = 2
159 ; | 8 ... 15 | 0 ... 7 | 24 ... 31 | 16 ... 23 | 40 ... 47 | 32 ... 39 |
162 ; insn-word-length = 2
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 |
169 ; insn-word-length = 2
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 |
176 ; insn-word-length = 2
178 ; | 15 ... 8 | 7 ... 0 | 31 ... 24 | 23 ... 16 | 47 ... 40 | 39 ... 32 |
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.
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
194 ; insn-word-length = 2, 4
196 ; | 8 ... 15 | 0 ... 7 | 40 ... 47 | 32 ... 39 | 24 ... 31 | 16 ... 23 |
199 ; insn-word-length = 2, 4
201 ; | 7 ... 0 | 15 ... 8 | 23 ... 16 | 31 ... 24 | 39 ... 32 | 47 ... 40 |
204 ; insn-word-length = 2, 4
206 ; | 0 ... 7 | 8 ... 15 | 16 ... 23 | 24 ... 31 | 32 ... 39 | 40 ... 47 |
209 ; insn-word-length = 2, 4
211 ; | 15 ... 8 | 7 ... 0 | 47 ... 40 | 39 ... 32 | 31 ... 24 | 23 ... 16 |
214 (class-make '<bitrange>
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]
222 ; starting bit number within the word,
223 ; this is the MSB of the bitrange within the word
224 ; [externally, = word-offset + start]
226 ; number of bits in the value
228 ; length of word in which the value resides
230 ; lsb = bit number 0?
238 (define-getters <bitrange> bitrange
239 (word-offset start length word-length lsb0?)
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)
247 ; Return a boolean indicating if two bitranges overlap.
249 ; lsb0? = #t: 31 ... 0
250 ; lsb0? = #f: 0 ... 31
252 (define (bitrange-overlap? start1 length1 start2 length2 lsb0?)
254 (let ((end1 (- start1 length1))
255 (end2 (- start2 length2)))
258 (let ((end1 (+ start1 length1))
259 (end2 (+ start2 length2)))
264 ; Return a boolean indicating if BITPOS is beyond bitrange START,LEN.
265 ; ??? This needs more thought.
267 (define (bitpos-beyond? bitpos start length word-length lsb0?)
268 (>= bitpos (+ start length))
271 ; Return the offset of the word after <bitrange> br.
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)))
280 (+ word-offset word-length))
283 ; Initialize/finalize support.
285 (define (types-init!)
289 (define (types-finish!)