2 ; Copyright (C) 2000, 2009 Red Hat, Inc.
3 ; This file is part of CGEN.
4 ; See file COPYING.CGEN for details.
6 ; FIXME: Later allow target to add new modes.
12 ; One of RANDOM, INT, UINT, FLOAT.
21 ; NON-MODE-C-TYPE is the C type to use in situations where
22 ; modes aren't available. A somewhat dubious feature, but at
23 ; the moment the opcodes tables use it. It is either the C
24 ; type as a string (e.g. "int") or #f for non-portable modes
25 ; (??? could use other typedefs for #f, e.g. int64 for DI).
26 ; Use of GCC can't be assumed though.
29 ; PRINTF-TYPE is the %<letter> arg to printf-like functions,
30 ; however we define our own extensions for non-portable modes.
31 ; Values not understood by printf aren't intended to be used
41 ; SEM-MODE is the mode to use for semantic operations.
42 ; Unsigned modes are not part of the semantic language proper,
43 ; but they can be used in hardware descriptions. This maps
44 ; unusable -> usable modes. It is #f if the mode is usable by
45 ; itself. This prevents circular data structures and makes it
46 ; easy to define since the object doesn't exist before it's
48 ; ??? May wish to later remove SEM-MODE (e.g. mips signed add
49 ; is different than mips unsigned add). However for now it keeps
50 ; things simpler, and prevents being wildly dissimilar from
51 ; GCC-RTL. And the mips case needn't be handled with different
55 ; PTR-TO, if non-#f, is the mode being pointed to.
58 ; HOST? is non-#f if the mode is a portable int for hosts,
59 ; or other host-related value.
60 ; This is used for things like register numbers and small
61 ; odd-sized immediates and registers.
62 ; ??? Not my favorite word choice here, but it's close.
70 (define mode:class (elm-make-getter <mode> 'class))
71 (define mode:bits (elm-make-getter <mode> 'bits))
72 (define mode:bytes (elm-make-getter <mode> 'bytes))
73 (define mode:non-mode-c-type (elm-make-getter <mode> 'non-mode-c-type))
74 (define mode:printf-type (elm-make-getter <mode> 'printf-type))
75 (define mode:sem-mode (elm-make-getter <mode> 'sem-mode))
76 ; ptr-to is currently private so there is no accessor.
77 (define mode:host? (elm-make-getter <mode> 'host?))
79 ; Return string C type to use for values of mode M.
81 (define (mode:c-type m)
82 (let ((ptr-to (elm-xget m 'ptr-to)))
84 (string-append (mode:c-type ptr-to) " *")
88 ; CM is short for "concat mode". It is a list of modes of the elements
90 ; ??? Experiment. Not currently used.
93 (class-make '<concat-mode> '(<mode>)
95 ; List of element modes
103 (define cmode-elm-modes (elm-make-getter <concat-mode> 'elm-modes))
107 (define mode-list nil)
109 ; Return list of mode objects.
110 ; Hides the fact that its stored as an alist from caller.
112 (define (mode-list-values) (map cdr mode-list))
114 ; Return list of real mode objects (no aliases).
116 (define (mode-list-non-alias-values)
118 (find (lambda (m) (eq? (car m) (obj:name (cdr m))))
122 ; Return a boolean indicating if X is a <mode> object.
124 (define (mode? x) (class-instance? <mode> x))
126 ; Return enum cgen_mode_types value for M.
128 (define (mode:enum m)
129 (gen-c-symbol (string-append "MODE_" (string-upcase (obj:str-name m))))
132 ; Return a boolean indicating if MODE1 is equal to MODE2
133 ; Either may be the name of a mode or a <mode> object.
134 ; Aliases are handled by refering to their real name.
136 (define (mode:eq? mode1 mode2)
137 (let ((mode1-name (mode-real-name mode1))
138 (mode2-name (mode-real-name mode2)))
139 (eq? mode1-name mode2-name))
142 ; Return a boolean indicating if CLASS is one of INT/UINT.
144 (define (mode-class-integral? class) (memq class '(INT UINT)))
145 (define (mode-class-signed? class) (eq? class 'INT))
146 (define (mode-class-unsigned? class) (eq? class 'UINT))
148 ; Return a boolean indicating if CLASS is floating point.
150 (define (mode-class-float? class) (memq class '(FLOAT)))
152 ; Return a boolean indicating if CLASS is numeric.
154 (define (mode-class-numeric? class) (memq class '(INT UINT FLOAT)))
156 ; Return a boolean indicating if MODE has an integral mode class.
157 ; Similarily for signed/unsigned.
159 (define (mode-integral? mode) (mode-class-integral? (mode:class mode)))
160 (define (mode-signed? mode) (mode-class-signed? (mode:class mode)))
161 (define (mode-unsigned? mode) (mode-class-unsigned? (mode:class mode)))
163 ; Return a boolean indicating if MODE has a floating point mode class.
165 (define (mode-float? mode) (mode-class-float? (mode:class mode)))
167 ; Return a boolean indicating if MODE has a numeric mode class.
169 (define (mode-numeric? mode) (mode-class-numeric? (mode:class mode)))
171 ; Return a boolean indicating if MODE1 is compatible with MODE2.
172 ; MODE[12] are either names or <mode> objects.
173 ; HOW is a symbol indicating how the test is performed:
174 ; strict: modes must have same name
175 ; samesize: modes must be both float or both integer (int or uint) and have
177 ; sameclass: modes must be both float or both integer (int or uint)
178 ; numeric: modes must be both numeric
180 (define (mode-compatible? how mode1 mode2)
181 (let ((m1 (mode:lookup mode1))
182 (m2 (mode:lookup mode2)))
185 (eq? (obj:name m1) (obj:name m2)))
187 (cond ((mode-integral? m1)
188 (and (mode-integral? m2)
189 (= (mode:bits m1) (mode:bits m2))))
191 (and (mode-float? m2)
192 (= (mode:bits m1) (mode:bits m2))))
195 (cond ((mode-integral? m1) (mode-integral? m2))
196 ((mode-float? m1) (mode-float? m2))
199 (and (mode-numeric? m1) (mode-numeric? m2)))
200 (else (error "bad `how' arg to mode-compatible?" how))))
203 ; Add MODE named NAME to the list of recognized modes.
204 ; If NAME is already present, replace it with MODE.
205 ; MODE is a mode object.
206 ; NAME exists to allow aliases of modes [e.g. WI, UWI, AI, IAI].
208 ; No attempt to preserve any particular order of entries is done here.
209 ; That is up to the caller.
211 (define (mode:add! name mode)
212 (let ((entry (assq name mode-list)))
214 (set-cdr! entry mode)
215 (set! mode-list (acons name mode mode-list)))
220 ; This is the main routine for building a mode object.
221 ; All arguments are in raw (non-evaluated) form.
223 (define (-mode-parse errtxt name comment attrs class bits bytes
224 non-mode-c-type printf-type sem-mode ptr-to host?)
225 (logit 2 "Processing mode " name " ...\n")
226 (let* ((name (parse-name name errtxt))
227 (errtxt (stringsym-append errtxt " " name))
230 (parse-comment comment errtxt)
231 (atlist-parse attrs "mode" errtxt)
232 class bits bytes non-mode-c-type printf-type
233 sem-mode ptr-to host?)))
237 ; ??? At present there is no define-mode that takes an associative list
240 ; Define a mode object, all arguments specified.
242 (define (define-full-mode name comment attrs class bits bytes
243 non-mode-c-type printf-type sem-mode ptr-to host?)
244 (let ((m (-mode-parse "define-full-mode" name comment attrs
246 non-mode-c-type printf-type sem-mode ptr-to host?)))
247 ; Add it to the list of insn modes.
252 ; Lookup the mode named X.
253 ; Return the found object or #f.
254 ; If X is already a mode object, return that.
256 (define (mode:lookup x)
259 (let ((result (assq x mode-list)))
265 ; Return a boolean indicating if X is a valid mode name.
267 (define (mode-name? x)
269 ; FIXME: Time to make `mode-list' a hash table.
270 (->bool (assq x mode-list)))
273 ; Return the name of the real mode of M.
274 ; This is a no-op unless M is an alias in which case we return the
275 ; real mode of the alias.
277 (define (mode-real-name m)
278 (obj:name (mode:lookup m))
281 ; Return the real mode of M.
282 ; This is a no-op unless M is an alias in which case we return the
283 ; real mode of the alias.
285 (define (mode-real-mode m)
286 (mode:lookup (mode-real-name m))
289 ; Return the version of MODE to use in semantic expressions.
290 ; This (essentially) converts aliases to their real value and then uses
291 ; mode:sem-mode. The implementation is the opposite but the effect is the
293 ; ??? Less efficient than it should be. One improvement would be to
294 ; disallow unsigned modes from being aliased and set sem-mode for aliased
297 (define (mode-sem-mode m)
298 (let* ((m1 (mode:lookup m))
299 (sm (mode:sem-mode m1)))
302 (mode-real-mode m1)))
305 ; Return #t if mode M1-NAME is bigger than mode M2-NAME.
307 (define (mode-bigger? m1-name m2-name)
308 (> (mode:bits (mode:lookup m1-name))
309 (mode:bits (mode:lookup m2-name)))
312 ; Return a mode in mode class CLASS wide enough to hold BITS.
313 ; This ignores "host" modes (e.g. INT,UINT).
315 (define (mode-find bits class)
316 (let ((modes (find (lambda (mode)
317 (and (eq? (mode:class (cdr mode)) class)
318 (not (mode:host? (cdr mode)))))
321 (error "invalid mode class" class))
322 (let loop ((modes modes))
323 (cond ((null? modes) (error "no modes for bits" bits))
324 ((<= bits (mode:bits (cdar modes))) (cdar modes))
325 (else (loop (cdr modes))))))
328 ; Parse MODE-NAME and return the mode object.
329 ; An error is signalled if MODE isn't valid.
331 (define (parse-mode-name mode-name errtxt)
332 (let ((m (mode:lookup mode-name)))
333 (if (not m) (parse-error errtxt "not a valid mode" mode-name))
337 ; Make a new INT/UINT mode.
338 ; These have a variable number of bits (1-64).
340 (define (mode-make-int bits)
341 (if (or (<= bits 0) (> bits 64))
342 (error "unsupported number of bits" bits))
343 (let ((result (object-copy-top INT)))
344 (elm-xset! result 'bits bits)
345 (elm-xset! result 'bytes (bits->bytes bits))
349 (define (mode-make-uint bits)
350 (if (or (<= bits 0) (> bits 64))
351 (error "unsupported number of bits" bits))
352 (let ((result (object-copy-top UINT)))
353 (elm-xset! result 'bits bits)
354 (elm-xset! result 'bytes (bits->bytes bits))
358 ; WI/UWI/AI/IAI modes
359 ; These are aliases for other modes, e.g. SI,DI.
360 ; Final values are defered until all cpu family definitions have been
361 ; read in so that we know the word size, etc.
363 ; NOTE: We currently assume WI/AI/IAI all have the same size: cpu:word-bitsize.
364 ; If we ever add an architecture that needs different modes for WI/AI/IAI,
365 ; we can add the support then.
367 ; This is defined by the target in define-cpu:word-bitsize.
371 ; An "address int". This is recorded in addition to a "word int" because it
372 ; is believed that some target will need it. It also stays consistent with
373 ; what BFD does. It also allows one to write rtl without having to care
374 ; what the real mode actually is.
375 ; ??? These are currently set from define-cpu:word-bitsize but that's just
376 ; laziness. If an architecture comes along that has different values,
377 ; add the support then.
381 ; Kind of word size handling wanted.
382 ; BIGGEST: pick the largest word size
383 ; IDENTICAL: all word sizes must be identical
384 (define -mode-word-sizes-kind #f)
386 ; Called when a cpu-family is read in to set the word sizes.
388 (define (mode-set-word-modes! bitsize)
389 (let ((current-word-bitsize (mode:bits WI))
390 (word-mode (mode-find bitsize 'INT))
391 (uword-mode (mode-find bitsize 'UINT))
394 ; Ensure we found a precise match.
395 (if (!= bitsize (mode:bits word-mode))
396 (error "unable to find precise mode to match cpu word-bitsize" bitsize))
398 ; Enforce word size kind.
399 (if (!= current-word-bitsize 0)
400 ; word size already set
401 (case -mode-word-sizes-kind
403 (if (!= current-word-bitsize (mode:bits word-mode))
404 (error "app requires all selected cpu families to have same word size"))
407 (if (>= current-word-bitsize (mode:bits word-mode))
414 (set! UWI uword-mode)
416 (set! IAI uword-mode)
417 (assq-set! mode-list 'WI word-mode)
418 (assq-set! mode-list 'UWI uword-mode)
419 (assq-set! mode-list 'AI uword-mode)
420 (assq-set! mode-list 'IAI uword-mode)
425 ; Called by apps to indicate cpu:word-bitsize always has one value.
426 ; It is an error to call this if the selected cpu families have
427 ; different word sizes.
428 ; Must be called before loading .cpu files.
430 (define (mode-set-identical-word-bitsizes!)
431 (set! -mode-word-sizes-kind 'IDENTICAL)
434 ; Called by apps to indicate using the biggest cpu:word-bitsize of all
435 ; selected cpu families.
436 ; Must be called before loading .cpu files.
438 (define (mode-set-biggest-word-bitsizes!)
439 (set! -mode-word-sizes-kind 'BIGGEST)
442 ; Ensure word sizes have been defined.
443 ; This must be called after all cpu families have been defined
444 ; and before any ifields, hardware, operand or insns have been read.
446 (define (mode-ensure-word-sizes-defined)
447 (if (eq? (mode-real-name WI) 'VOID)
448 (error "word sizes must be defined"))
453 ; Some modes are refered to by the Scheme code.
454 ; These have global bindings, but we try not to make this the general rule.
455 ; [Actually I don't think this is all that bad, but it seems reasonable to
456 ; not create global bindings that we don't have to.]
461 ; Variable sized portable ints.
466 (set! -mode-word-sizes-kind 'IDENTICAL)
468 (reader-add-command! 'define-full-mode
470 Define a mode, all arguments specified.
472 nil '(name commment attrs class bits bytes
473 non-c-mode-type printf-type sem-mode ptr-to host?)
479 ; Called before a . cpu file is read in to install any builtins.
481 (define (mode-builtin!)
482 ; FN-SUPPORT: In sem-ops.h file, include prototypes as well as macros.
483 ; Elsewhere, functions are defined to perform the operation.
484 (define-attr '(for mode) '(type boolean) '(name FN-SUPPORT))
488 (let ((dfm define-full-mode))
489 ; This list must be defined in order of increasing size among each type.
491 (dfm 'VOID "void" '() 'RANDOM 0 0 "void" "" #f #f #f) ; VOIDmode
493 ; Special marker to indicate "use the default mode".
494 ; ??? Not yet used everywhere it should be.
495 (dfm 'DFLT "default mode" '() 'RANDOM 0 0 "" "" #f #f #f)
497 ; Not UINT on purpose.
498 (dfm 'BI "one bit (0,1 not 0,-1)" '() 'INT 1 1 "int" "'x'" #f #f #f)
500 (dfm 'QI "8 bit byte" '() 'INT 8 1 "int" "'x'" #f #f #f)
501 (dfm 'HI "16 bit int" '() 'INT 16 2 "int" "'x'" #f #f #f)
502 (dfm 'SI "32 bit int" '() 'INT 32 4 "int" "'x'" #f #f #f)
503 (dfm 'DI "64 bit int" '(FN-SUPPORT) 'INT 64 8 "" "'D'" #f #f #f)
505 (dfm 'UQI "8 bit unsigned byte" '() 'UINT
506 8 1 "unsigned int" "'x'" (mode:lookup 'QI) #f #f)
507 (dfm 'UHI "16 bit unsigned int" '() 'UINT
508 16 2 "unsigned int" "'x'" (mode:lookup 'HI) #f #f)
509 (dfm 'USI "32 bit unsigned int" '() 'UINT
510 32 4 "unsigned int" "'x'" (mode:lookup 'SI) #f #f)
511 (dfm 'UDI "64 bit unsigned int" '(FN-SUPPORT) 'UINT
512 64 8 "" "'D'" (mode:lookup 'DI) #f #f)
514 ; Floating point values.
515 (dfm 'SF "32 bit float" '(FN-SUPPORT) 'FLOAT
516 32 4 "" "'f'" #f #f #f)
517 (dfm 'DF "64 bit float" '(FN-SUPPORT) 'FLOAT
518 64 8 "" "'f'" #f #f #f)
519 (dfm 'XF "80/96 bit float" '(FN-SUPPORT) 'FLOAT
520 96 12 "" "'F'" #f #f #f)
521 (dfm 'TF "128 bit float" '(FN-SUPPORT) 'FLOAT
522 128 16 "" "'F'" #f #f #f)
524 ; These are useful modes that represent host values.
525 ; For INT/UINT the sizes indicate maximum portable values.
526 ; These are also used for random width hardware elements (e.g. immediates
528 ; FIXME: Can't be used to represent both host and target values.
529 ; Either remove the distinction or add new modes with the distinction.
530 (dfm 'INT "portable int" '() 'INT 32 4 "int" "'x'"
531 (mode:lookup 'SI) #f #t)
532 (dfm 'UINT "portable unsigned int" '() 'UINT 32 4 "unsigned int" "'x'"
533 (mode:lookup 'SI) #f #t)
536 (dfm 'PTR "host pointer" '() 'RANDOM 0 0 "PTR" "'x'"
537 #f (mode:lookup 'VOID) #t)
540 (set! VOID (mode:lookup 'VOID))
541 (set! DFLT (mode:lookup 'DFLT))
543 (set! INT (mode:lookup 'INT))
544 (set! UINT (mode:lookup 'UINT))
546 ; While setting the real values of WI/UWI/AI/IAI is defered to
547 ; mode-set-word-modes!, create entries in the list.
548 (set! WI (mode:add! 'WI (mode:lookup 'VOID)))
549 (set! UWI (mode:add! 'UWI (mode:lookup 'VOID)))
550 (set! AI (mode:add! 'AI (mode:lookup 'VOID)))
551 (set! IAI (mode:add! 'IAI (mode:lookup 'VOID)))
553 ; Keep the fields sorted for mode-find.
554 (set! mode-list (reverse mode-list))
559 (define (mode-finish!)