OSDN Git Service

* read.scm (rtl-version-equal?): New function.
[pf3gnuchains/pf3gnuchains3x.git] / cgen / mode.scm
1 ; Mode objects.
2 ; Copyright (C) 2000, 2009 Red Hat, Inc.
3 ; This file is part of CGEN.
4 ; See file COPYING.CGEN for details.
5
6 ; FIXME: Later allow target to add new modes.
7
8 (define <mode>
9   (class-make '<mode>
10               '(<ident>)
11               '(
12                 ; One of RANDOM, INT, UINT, FLOAT.
13                 class
14
15                 ; size in bits
16                 bits
17
18                 ; size in bytes
19                 bytes
20
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.
27                 non-mode-c-type
28
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
32                 ; with printf.
33                 ;
34                 ; Possible values:
35                 ; %x - as always
36                 ; %D - DI mode (8 bytes)
37                 ; %T - TI mode (16 bytes)
38                 ; %O - OI mode (32 bytes)
39                 ; %f - SF,DF modes
40                 ; %F - XF,TF modes
41                 printf-type
42
43                 ; SEM-MODE is the mode to use for semantic operations.
44                 ; Unsigned modes are not part of the semantic language proper,
45                 ; but they can be used in hardware descriptions.  This maps
46                 ; unusable -> usable modes.  It is #f if the mode is usable by
47                 ; itself.  This prevents circular data structures and makes it
48                 ; easy to define since the object doesn't exist before it's
49                 ; defined.
50                 ; ??? May wish to later remove SEM-MODE (e.g. mips signed add
51                 ; is different than mips unsigned add).  However for now it keeps
52                 ; things simpler, and prevents being wildly dissimilar from
53                 ; GCC-RTL.  And the mips case needn't be handled with different
54                 ; adds anyway.
55                 sem-mode
56
57                 ; PTR-TO, if non-#f, is the mode being pointed to.
58                 ptr-to
59
60                 ; HOST? is non-#f if the mode is a portable int for hosts,
61                 ; or other host-related value.
62                 ; This is used for things like register numbers and small
63                 ; odd-sized immediates and registers.
64                 ; ??? Not my favorite word choice here, but it's close.
65                 host?
66                 )
67               nil)
68 )
69
70 ; Accessor fns
71
72 (define mode:class (elm-make-getter <mode> 'class))
73 (define mode:bits (elm-make-getter <mode> 'bits))
74 (define mode:bytes (elm-make-getter <mode> 'bytes))
75 (define mode:non-mode-c-type (elm-make-getter <mode> 'non-mode-c-type))
76 (define mode:printf-type (elm-make-getter <mode> 'printf-type))
77 (define mode:sem-mode (elm-make-getter <mode> 'sem-mode))
78 ; ptr-to is currently private so there is no accessor.
79 (define mode:host? (elm-make-getter <mode> 'host?))
80
81 ; Return string C type to use for values of mode M.
82
83 (define (mode:c-type m)
84   (let ((ptr-to (elm-xget m 'ptr-to)))
85     (if ptr-to
86         (string-append (mode:c-type ptr-to) " *")
87         (obj:str-name m)))
88 )
89
90 ; CM is short for "concat mode".  It is a list of modes of the elements
91 ; of a `concat'.
92 ; ??? Experiment.  Not currently used.
93
94 (define <concat-mode>
95   (class-make '<concat-mode> '(<mode>)
96               '(
97                 ; List of element modes
98                 elm-modes
99                 )
100               nil)
101 )
102
103 ; Accessors.
104
105 (define cmode-elm-modes (elm-make-getter <concat-mode> 'elm-modes))
106 \f
107 ; List of all modes.
108
109 (define mode-list nil)
110
111 ; Return list of mode objects.
112 ; Hides the fact that its stored as an alist from caller.
113
114 (define (mode-list-values) (map cdr mode-list))
115
116 ; Return list of real mode objects (no aliases).
117
118 (define (mode-list-non-alias-values)
119   (map cdr
120        (find (lambda (m) (eq? (car m) (obj:name (cdr m))))
121              mode-list))
122 )
123
124 ; Return a boolean indicating if X is a <mode> object.
125
126 (define (mode? x) (class-instance? <mode> x))
127
128 ; Return enum cgen_mode_types value for M.
129
130 (define (mode:enum m)
131   (gen-c-symbol (string-append "MODE_" (string-upcase (obj:str-name m))))
132 )
133
134 ; Return a boolean indicating if MODE1 is equal to MODE2
135 ; Either may be the name of a mode or a <mode> object.
136 ; Aliases are handled by refering to their real name.
137
138 (define (mode:eq? mode1 mode2)
139   (let ((mode1-name (mode-real-name mode1))
140         (mode2-name (mode-real-name mode2)))
141     (eq? mode1-name mode2-name))
142 )
143
144 ; Return a boolean indicating if CLASS is one of INT/UINT.
145
146 (define (mode-class-integral? class) (memq class '(INT UINT)))
147 (define (mode-class-signed? class) (eq? class 'INT))
148 (define (mode-class-unsigned? class) (eq? class 'UINT))
149
150 ; Return a boolean indicating if CLASS is floating point.
151
152 (define (mode-class-float? class) (memq class '(FLOAT)))
153
154 ; Return a boolean indicating if CLASS is numeric.
155
156 (define (mode-class-numeric? class) (memq class '(INT UINT FLOAT)))
157
158 ; Return a boolean indicating if MODE has an integral mode class.
159 ; Similarily for signed/unsigned.
160
161 (define (mode-integral? mode) (mode-class-integral? (mode:class mode)))
162 (define (mode-signed? mode) (mode-class-signed? (mode:class mode)))
163 (define (mode-unsigned? mode) (mode-class-unsigned? (mode:class mode)))
164
165 ; Return a boolean indicating if MODE has a floating point mode class.
166
167 (define (mode-float? mode) (mode-class-float? (mode:class mode)))
168
169 ; Return a boolean indicating if MODE has a numeric mode class.
170
171 (define (mode-numeric? mode) (mode-class-numeric? (mode:class mode))) 
172
173 ; Return a boolean indicating if MODE1 is compatible with MODE2.
174 ; MODE[12] are either names or <mode> objects.
175 ; HOW is a symbol indicating how the test is performed:
176 ; strict: modes must have same name
177 ; samesize: modes must be both float or both integer (int or uint) and have
178 ;           same size
179 ; sameclass: modes must be both float or both integer (int or uint)
180 ; numeric: modes must be both numeric
181
182 (define (mode-compatible? how mode1 mode2)
183   (let ((m1 (mode:lookup mode1))
184         (m2 (mode:lookup mode2)))
185     (case how
186       ((strict)
187        (eq? (obj:name m1) (obj:name m2)))
188       ((samesize)
189        (cond ((mode-integral? m1)
190               (and (mode-integral? m2)
191                    (= (mode:bits m1) (mode:bits m2))))
192              ((mode-float? m1)
193               (and (mode-float? m2)
194                    (= (mode:bits m1) (mode:bits m2))))
195              (else #f)))
196       ((sameclass)
197        (cond ((mode-integral? m1) (mode-integral? m2))
198              ((mode-float? m1) (mode-float? m2))
199              (else #f)))
200       ((numeric)
201        (and (mode-numeric? m1) (mode-numeric? m2)))
202       (else (error "bad `how' arg to mode-compatible?" how))))
203 )
204
205 ; Add MODE named NAME to the list of recognized modes.
206 ; If NAME is already present, replace it with MODE.
207 ; MODE is a mode object.
208 ; NAME exists to allow aliases of modes [e.g. WI, UWI, AI, IAI].
209 ;
210 ; No attempt to preserve any particular order of entries is done here.
211 ; That is up to the caller.
212
213 (define (mode:add! name mode)
214   (let ((entry (assq name mode-list)))
215     (if entry
216         (set-cdr! entry mode)
217         (set! mode-list (acons name mode mode-list)))
218     mode)
219 )
220 \f
221 ; Parse a mode.
222 ; This is the main routine for building a mode object.
223 ; All arguments are in raw (non-evaluated) form.
224
225 (define (/mode-parse context name comment attrs class bits bytes
226                      non-mode-c-type printf-type sem-mode ptr-to host?)
227   (logit 2 "Processing mode " name " ...\n")
228
229   ;; Pick out name first to augment the error context.
230   (let* ((name (parse-name context name))
231          (context (context-append-name context name)))
232
233     (make <mode>
234       name
235       (parse-comment context comment)
236       (atlist-parse context attrs "mode")
237       class bits bytes non-mode-c-type printf-type
238       sem-mode ptr-to host?))
239 )
240
241 ; ??? At present there is no define-mode that takes an associative list
242 ; of arguments.
243
244 ; Define a mode object, all arguments specified.
245
246 (define (define-full-mode name comment attrs class bits bytes
247           non-mode-c-type printf-type sem-mode ptr-to host?)
248   (let ((m (/mode-parse (make-current-context "define-full-mode")
249                         name comment attrs
250                         class bits bytes
251                         non-mode-c-type printf-type sem-mode ptr-to host?)))
252     ; Add it to the list of insn modes.
253     (mode:add! name m)
254     m)
255 )
256 \f
257 ; Lookup the mode named X.
258 ; Return the found object or #f.
259 ; If X is already a mode object, return that.
260
261 (define (mode:lookup x)
262   (if (mode? x)
263       x
264       (let ((result (assq x mode-list)))
265         (if result
266             (cdr result)
267             #f)))
268 )
269
270 ; Return a boolean indicating if X is a valid mode name.
271
272 (define (mode-name? x)
273   (and (symbol? x)
274        ; FIXME: Time to make `mode-list' a hash table.
275        (->bool (assq x mode-list)))
276 )
277
278 ; Return the name of the real mode of M.
279 ; This is a no-op unless M is an alias in which case we return the
280 ; real mode of the alias.
281
282 (define (mode-real-name m)
283   (obj:name (mode:lookup m))
284 )
285
286 ; Return the real mode of M.
287 ; This is a no-op unless M is an alias in which case we return the
288 ; real mode of the alias.
289
290 (define (mode-real-mode m)
291   (mode:lookup (mode-real-name m))
292 )
293
294 ; Return the version of MODE to use in semantic expressions.
295 ; This (essentially) converts aliases to their real value and then uses
296 ; mode:sem-mode.  The implementation is the opposite but the effect is the
297 ; same.
298 ; ??? Less efficient than it should be.  One improvement would be to
299 ; disallow unsigned modes from being aliased and set sem-mode for aliased
300 ; modes.
301
302 (define (mode-sem-mode m)
303   (let* ((m1 (mode:lookup m))
304          (sm (mode:sem-mode m1)))
305     (if sm
306         sm
307         (mode-real-mode m1)))
308 )
309
310 ; Return #t if mode M1-NAME is bigger than mode M2-NAME.
311
312 (define (mode-bigger? m1-name m2-name)
313   (> (mode:bits (mode:lookup m1-name))
314      (mode:bits (mode:lookup m2-name)))
315 )
316
317 ; Return a mode in mode class CLASS wide enough to hold BITS.
318 ; This ignores "host" modes (e.g. INT,UINT).
319
320 (define (mode-find bits class)
321   (let ((modes (find (lambda (mode)
322                        (and (eq? (mode:class (cdr mode)) class)
323                             (not (mode:host? (cdr mode)))))
324                      mode-list)))
325     (if (null? modes)
326         (error "invalid mode class" class))
327     (let loop ((modes modes))
328       (cond ((null? modes) (error "no modes for bits" bits))
329             ((<= bits (mode:bits (cdar modes))) (cdar modes))
330             (else (loop (cdr modes))))))
331 )
332
333 ; Parse MODE-NAME and return the mode object.
334 ; CONTEXT is a <context> object for error messages.
335 ; An error is signalled if MODE isn't valid.
336
337 (define (parse-mode-name context mode-name)
338   (let ((m (mode:lookup mode-name)))
339     (if (not m)
340         (parse-error context "not a valid mode" mode-name))
341     m)
342 )
343
344 ; Make a new INT/UINT mode.
345 ; These have a variable number of bits (1-64).
346
347 (define (mode-make-int bits)
348   (if (or (<= bits 0) (> bits 64))
349       (error "unsupported number of bits" bits))
350   (let ((result (object-copy-top INT)))
351     (elm-xset! result 'bits bits)
352     (elm-xset! result 'bytes (bits->bytes bits))
353     result)
354 )
355
356 (define (mode-make-uint bits)
357   (if (or (<= bits 0) (> bits 64))
358       (error "unsupported number of bits" bits))
359   (let ((result (object-copy-top UINT)))
360     (elm-xset! result 'bits bits)
361     (elm-xset! result 'bytes (bits->bytes bits))
362     result)
363 )
364 \f
365 ; WI/UWI/AI/IAI modes
366 ; These are aliases for other modes, e.g. SI,DI.
367 ; Final values are defered until all cpu family definitions have been
368 ; read in so that we know the word size, etc.
369 ;
370 ; NOTE: We currently assume WI/AI/IAI all have the same size: cpu:word-bitsize.
371 ; If we ever add an architecture that needs different modes for WI/AI/IAI,
372 ; we can add the support then.
373
374 ; This is defined by the target in define-cpu:word-bitsize.
375 (define WI #f)
376 (define UWI #f)
377
378 ; An "address int".  This is recorded in addition to a "word int" because it
379 ; is believed that some target will need it.  It also stays consistent with
380 ; what BFD does.  It also allows one to write rtl without having to care
381 ; what the real mode actually is.
382 ; ??? These are currently set from define-cpu:word-bitsize but that's just
383 ; laziness.  If an architecture comes along that has different values,
384 ; add the support then.
385 (define AI #f)
386 (define IAI #f)
387
388 ; Kind of word size handling wanted.
389 ; BIGGEST: pick the largest word size
390 ; IDENTICAL: all word sizes must be identical
391 (define /mode-word-sizes-kind #f)
392
393 ; Called when a cpu-family is read in to set the word sizes.
394
395 (define (mode-set-word-modes! bitsize)
396   (let ((current-word-bitsize (mode:bits WI))
397         (word-mode (mode-find bitsize 'INT))
398         (uword-mode (mode-find bitsize 'UINT))
399         (ignore? #f))
400
401     ; Ensure we found a precise match.
402     (if (!= bitsize (mode:bits word-mode))
403         (error "unable to find precise mode to match cpu word-bitsize" bitsize))
404
405     ; Enforce word size kind.
406     (if (!= current-word-bitsize 0)
407         ; word size already set
408         (case /mode-word-sizes-kind
409           ((IDENTICAL)
410            (if (!= current-word-bitsize (mode:bits word-mode))
411                (error "app requires all selected cpu families to have same word size"))
412            (set! ignore? #t))
413           ((BIGGEST)
414            (if (>= current-word-bitsize (mode:bits word-mode))
415                (set! ignore? #t)))
416           ))
417
418     (if (not ignore?)
419         (begin
420           (set! WI word-mode)
421           (set! UWI uword-mode)
422           (set! AI uword-mode)
423           (set! IAI uword-mode)
424           (assq-set! mode-list 'WI word-mode)
425           (assq-set! mode-list 'UWI uword-mode)
426           (assq-set! mode-list 'AI uword-mode)
427           (assq-set! mode-list 'IAI uword-mode)
428           ))
429     )
430 )
431
432 ; Called by apps to indicate cpu:word-bitsize always has one value.
433 ; It is an error to call this if the selected cpu families have
434 ; different word sizes.
435 ; Must be called before loading .cpu files.
436
437 (define (mode-set-identical-word-bitsizes!)
438   (set! /mode-word-sizes-kind 'IDENTICAL)
439 )
440
441 ; Called by apps to indicate using the biggest cpu:word-bitsize of all
442 ; selected cpu families.
443 ; Must be called before loading .cpu files.
444
445 (define (mode-set-biggest-word-bitsizes!)
446   (set! /mode-word-sizes-kind 'BIGGEST)
447 )
448
449 ; Ensure word sizes have been defined.
450 ; This must be called after all cpu families have been defined
451 ; and before any ifields, hardware, operand or insns have been read.
452
453 (define (mode-ensure-word-sizes-defined)
454   (if (eq? (mode-real-name WI) 'VOID)
455       (error "word sizes must be defined"))
456 )
457 \f
458 ; Initialization.
459
460 ; Some modes are refered to by the Scheme code.
461 ; These have global bindings, but we try not to make this the general rule.
462 ; [Actually I don't think this is all that bad, but it seems reasonable to
463 ; not create global bindings that we don't have to.]
464
465 (define VOID #f)
466 (define DFLT #f)
467
468 ; Variable sized portable ints.
469 (define INT #f)
470 (define UINT #f)
471
472 (define (mode-init!)
473   (set! /mode-word-sizes-kind 'IDENTICAL)
474
475   (reader-add-command! 'define-full-mode
476                        "\
477 Define a mode, all arguments specified.
478 "
479                        nil '(name commment attrs class bits bytes
480                              non-c-mode-type printf-type sem-mode ptr-to host?)
481                        define-full-mode)
482
483   *UNSPECIFIED*
484 )
485
486 ; Called before a . cpu file is read in to install any builtins.
487
488 (define (mode-builtin!)
489   ; FN-SUPPORT: In sem-ops.h file, include prototypes as well as macros.
490   ;             Elsewhere, functions are defined to perform the operation.
491   (define-attr '(for mode) '(type boolean) '(name FN-SUPPORT))
492
493   (set! mode-list nil)
494
495   (let ((dfm define-full-mode))
496     ; This list must be defined in order of increasing size among each type.
497
498     (dfm 'VOID "void" '() 'RANDOM 0 0 "void" "" #f #f #f) ; VOIDmode
499
500     ; Special marker to indicate "use the default mode".
501     ; ??? Not yet used everywhere it should be.
502     (dfm 'DFLT "default mode" '() 'RANDOM 0 0 "" "" #f #f #f)
503
504     ; Not UINT on purpose.
505     (dfm 'BI "one bit (0,1 not 0,-1)" '() 'INT 1 1 "int" "'x'" #f #f #f)
506
507     (dfm 'QI "8 bit byte" '() 'INT 8 1 "int" "'x'" #f #f #f)
508     (dfm 'HI "16 bit int" '() 'INT 16 2 "int" "'x'" #f #f #f)
509     (dfm 'SI "32 bit int" '() 'INT 32 4 "int" "'x'" #f #f #f)
510     (dfm 'DI "64 bit int" '(FN-SUPPORT) 'INT 64 8 "" "'D'" #f #f #f)
511
512     ; No unsigned versions on purpose for now.
513     (dfm 'TI "128 bit int" '(FN-SUPPORT) 'INT 128 16 "" "'T'" #f #f #f)
514     (dfm 'OI "256 bit int" '(FN-SUPPORT) 'INT 256 32 "" "'O'" #f #f #f)
515
516     (dfm 'UQI "8 bit unsigned byte" '() 'UINT
517          8 1 "unsigned int" "'x'" (mode:lookup 'QI) #f #f)
518     (dfm 'UHI "16 bit unsigned int" '() 'UINT
519          16 2 "unsigned int" "'x'" (mode:lookup 'HI) #f #f)
520     (dfm 'USI "32 bit unsigned int" '() 'UINT
521          32 4 "unsigned int" "'x'" (mode:lookup 'SI) #f #f)
522     (dfm 'UDI "64 bit unsigned int" '(FN-SUPPORT) 'UINT
523          64 8 "" "'D'" (mode:lookup 'DI) #f #f)
524
525     ; Floating point values.
526     (dfm 'SF "32 bit float" '(FN-SUPPORT) 'FLOAT
527          32 4 "" "'f'" #f #f #f)
528     (dfm 'DF "64 bit float" '(FN-SUPPORT) 'FLOAT
529          64 8 "" "'f'" #f #f #f)
530     (dfm 'XF "80/96 bit float" '(FN-SUPPORT) 'FLOAT
531          96 12 "" "'F'" #f #f #f)
532     (dfm 'TF "128 bit float" '(FN-SUPPORT) 'FLOAT
533          128 16 "" "'F'" #f #f #f)
534
535     ; These are useful modes that represent host values.
536     ; For INT/UINT the sizes indicate maximum portable values.
537     ; These are also used for random width hardware elements (e.g. immediates
538     ; and registers).
539     ; FIXME: Can't be used to represent both host and target values.
540     ; Either remove the distinction or add new modes with the distinction.
541     (dfm 'INT "portable int" '() 'INT 32 4 "int" "'x'"
542          (mode:lookup 'SI) #f #t)
543     (dfm 'UINT "portable unsigned int" '() 'UINT 32 4 "unsigned int" "'x'"
544          (mode:lookup 'SI) #f #t)
545
546     ; ??? Experimental.
547     (dfm 'PTR "host pointer" '() 'RANDOM 0 0 "PTR" "'x'"
548          #f (mode:lookup 'VOID) #t)
549     )
550
551   (set! VOID (mode:lookup 'VOID))
552   (set! DFLT (mode:lookup 'DFLT))
553
554   (set! INT (mode:lookup 'INT))
555   (set! UINT (mode:lookup 'UINT))
556
557   ; While setting the real values of WI/UWI/AI/IAI is defered to
558   ; mode-set-word-modes!, create entries in the list.
559   (set! WI (mode:add! 'WI (mode:lookup 'VOID)))
560   (set! UWI (mode:add! 'UWI (mode:lookup 'VOID)))
561   (set! AI (mode:add! 'AI (mode:lookup 'VOID)))
562   (set! IAI (mode:add! 'IAI (mode:lookup 'VOID)))
563
564   ; Keep the fields sorted for mode-find.
565   (set! mode-list (reverse mode-list))
566
567   *UNSPECIFIED*
568 )
569
570 (define (mode-finish!)
571   *UNSPECIFIED*
572 )