OSDN Git Service

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