OSDN Git Service

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