OSDN Git Service

remove unnecessary comment in generated code
[pf3gnuchains/pf3gnuchains4x.git] / cgen / sim.scm
1 ; Simulator generator support routines.
2 ; Copyright (C) 2000, 2001, 2002, 2006, 2009 Red Hat, Inc.
3 ; This file is part of CGEN.
4
5 ; One goal of this file is to provide cover functions for all methods.
6 ; i.e. this file fills in the missing pieces of the interface between
7 ; the application independent part of CGEN (i.e. the code loaded by read.scm)
8 ; and the application dependent part (i.e. sim-*.scm).
9 ; `send' is not intended to appear in sim-*.scm.
10 ; [It still does but that's to be fixed.]
11
12 ; Specify which application.
13 (set! APPLICATION 'SIMULATOR)
14 \f
15 ; Cover functions for various methods.
16
17 ; Return the C type of something.  This isn't always a mode.
18
19 (define (gen-type self) (send self 'gen-type))
20
21 ; Return the C type of an index's value or #f if not needed (scalar).
22
23 (define (gen-index-type op sfmt)
24   (let ((index-mode (send op 'get-index-mode)))
25     (if index-mode
26         (mode:c-type index-mode)
27         #f))
28 )
29 \f
30 ; Misc. state info.
31
32 ; Currently supported options:
33 ; with-scache
34 ;       generate code to use the scache
35 ;       This is an all or nothing option, either scache is used or it's not.
36 ; with-profile fn|sw
37 ;       generate code to do profiling in the semantic function
38 ;       code (fn) or in the semantic switch (sw)
39 ; with-generic-write
40 ;       For architectures that have parallel execution.
41 ;       Execute the semantics by recording the results in a generic buffer,
42 ;       and doing a post-semantics writeback pass.
43 ; with-parallel-only
44 ;       Only generate parallel versions of each insn.
45 ; with-multiple-isa
46 ;       Enable multiple-isa support (eg. arm+thumb).
47 ; copyright fsf|redhat
48 ;       emit an FSF or Cygnus copyright (temporary, pending decision)
49 ; package gnusim|cygsim
50 ;       indicate the software package
51
52 ; #t if the scache is being used
53 (define /with-scache? #f)
54 (define (with-scache?) /with-scache?)
55
56 ; #t if we're generating profiling code
57 ; Each of the function and switch semantic code can have profiling.
58 ; The options as passed are stored in /with-profile-{fn,sw}?, and
59 ; /with-profile? is set at code generation time.
60 (define /with-profile-fn? #f)
61 (define /with-profile-sw? #f)
62 (define /with-profile? #f)
63 (define (with-profile?) /with-profile?)
64 (define (with-any-profile?) (or /with-profile-fn? /with-profile-sw?))
65
66 ; #t if multiple isa support is enabled
67 (define /with-multiple-isa? #f)
68 (define (with-multiple-isa?) /with-multiple-isa?)
69
70 ; Handle parallel execution with generic writeback pass.
71 (define /with-generic-write? #f)
72 (define (with-generic-write?) /with-generic-write?)
73
74 ; Only generate parallel versions of each insn.
75 (define /with-parallel-only? #f)
76 (define (with-parallel-only?) /with-parallel-only?)
77
78 ; String containing copyright text.
79 (define CURRENT-COPYRIGHT #f)
80
81 ; String containing text defining the package we're generating code for.
82 (define CURRENT-PACKAGE #f)
83
84 ; Initialize the options.
85
86 (define (option-init!)
87   (set! /with-scache? #f)
88   (set! /with-profile-fn? #f)
89   (set! /with-profile-sw? #f)
90   (set! /with-multiple-isa? #f)
91   (set! /with-generic-write? #f)
92   (set! /with-parallel-only? #f)
93   (set! CURRENT-COPYRIGHT copyright-fsf)
94   (set! CURRENT-PACKAGE package-gnu-simulators)
95   *UNSPECIFIED*
96 )
97
98 ; Handle an option passed in from the command line.
99
100 (define (option-set! name value)
101   (case name
102     ((with-scache) (set! /with-scache? #t))
103     ((with-profile) (cond ((equal? value '("fn"))
104                            (set! /with-profile-fn? #t))
105                           ((equal? value '("sw"))
106                            (set! /with-profile-sw? #t))
107                           (else (error "invalid with-profile value" value))))
108     ((with-multiple-isa) (set! /with-multiple-isa? #t))
109     ((with-generic-write) (set! /with-generic-write? #t))
110     ((with-parallel-only) (set! /with-parallel-only? #t))
111     ((copyright) (cond ((equal?  value '("fsf"))
112                         (set! CURRENT-COPYRIGHT copyright-fsf))
113                        ((equal? value '("redhat"))
114                         (set! CURRENT-COPYRIGHT copyright-red-hat))
115                        (else (error "invalid copyright value" value))))
116     ((package) (cond ((equal?  value '("gnusim"))
117                       (set! CURRENT-PACKAGE package-gnu-simulators))
118                      ((equal? value '("cygsim"))
119                       (set! CURRENT-PACKAGE package-red-hat-simulators))
120                      (else (error "invalid package value" value))))
121     (else (error "unknown option" name))
122     )
123   *UNSPECIFIED*
124 )
125
126 ; #t if the cpu can execute insns parallely.
127 ; This one isn't passed on the command line, but we follow the convention
128 ; of prefixing these things with `with-'.
129 ; While processing operand reading (or writing), parallel execution support
130 ; needs to be turned off, so it is up to the appropriate cgen-foo.c proc to
131 ; set-with-parallel?! appropriately.
132 (define /with-parallel? #f)
133 (define (with-parallel?) /with-parallel?)
134 (define (set-with-parallel?! flag) (set! /with-parallel? flag))
135
136 ; Kind of parallel support.
137 ; If 'read, read pre-processing is done.
138 ; If 'write, write post-processing is done.
139 ; ??? At present we always use write post-processing, though the previous
140 ; version used read pre-processing.  Not sure supporting both is useful
141 ; in the long run.
142 (define /with-parallel-kind 'write)
143 ; #t if parallel support is provided by read pre-processing.
144 (define (with-parallel-read?)
145   (and /with-parallel? (eq? /with-parallel-kind 'read))
146 )
147 ; #t if parallel support is provided by write post-processing.
148 (define (with-parallel-write?)
149   (and /with-parallel? (eq? /with-parallel-kind 'write))
150 )
151 \f
152 ; Misc. utilities.
153
154 ; All machine generated cpu elements are accessed through a cover macro
155 ; to hide the details of the underlying implementation.
156
157 (define c-cpu-macro "CPU")
158
159 (define (gen-cpu-ref sym)
160   (string-append c-cpu-macro " (" sym ")")
161 )
162 \f
163
164 ; Return C code to fetch a value from instruction memory.
165 ; PC-VAR is the C expression containing the address of the start of the
166 ; instruction.
167 ; ??? Aligned/unaligned support?
168
169 (define (gen-ifetch pc-var bitoffset bitsize)
170   (string-append "GETIMEM"
171                  (case bitsize
172                    ((8) "UQI")
173                    ((16) "UHI")
174                    ((32) "USI")
175                    (else (error "bad bitsize argument to gen-ifetch" bitsize)))
176                  " (current_cpu, "
177                  pc-var " + " (number->string (quotient bitoffset 8))
178                  ")")
179 )
180
181 ; Instruction field support code.
182
183 ; Return a <c-expr> object of the value of an ifield.
184
185 (define (/cxmake-ifld-val mode f)
186   (if (with-scache?)
187       ; ??? Perhaps a better way would be to defer evaluating the src of a
188       ; set until the method processing the dest.
189       (cx:make-with-atlist mode (gen-ifld-argbuf-ref f)
190                            (atlist-make "" (bool-attr-make 'CACHED #t)))
191       (cx:make mode (gen-extracted-ifld-value f)))
192 )
193 \f
194 ; Type system.
195
196 ; Methods:
197 ; gen-type - return C code representing the type
198 ; gen-sym-defn - generate decl using the provided symbol
199 ; gen-sym-get-macro - generate GET macro for accessing CPU elements
200 ; gen-sym-set-macro - generate SET macro for accessing CPU elements
201
202 ; Scalar type
203
204 (method-make!
205  <scalar> 'gen-type
206  (lambda (self) (mode:c-type (elm-get self 'mode)))
207 )
208
209 (method-make!
210  <scalar> 'gen-sym-defn
211  (lambda (self sym comment)
212    (string-append
213     "  /* " comment " */\n"
214     "  " (send self 'gen-type) " "
215     (gen-c-symbol sym) ";\n"))
216 )
217
218 (method-make!
219  <scalar> 'gen-sym-get-macro
220  (lambda (self sym comment)
221    (let ((sym (gen-c-symbol sym)))
222      (gen-get-macro sym "" (gen-cpu-ref sym))))
223 )
224
225 (method-make!
226  <scalar> 'gen-sym-set-macro
227  (lambda (self sym comment)
228    (let ((sym (gen-c-symbol sym)))
229      (gen-set-macro sym "" (gen-cpu-ref sym))))
230 )
231
232 (method-make! <scalar> 'gen-ref (lambda (self sym index estate) sym))
233
234 ; Array type
235
236 (method-make!
237  <array> 'gen-type
238  (lambda (self) (mode:c-type (elm-get self 'mode)))
239 )
240
241 (method-make!
242  <array> 'gen-sym-defn
243  (lambda (self sym comment)
244    (string-append
245     "  /* " comment " */\n"
246     "  " (send self 'gen-type) " "
247     (gen-c-symbol sym)
248     (gen-array-ref (elm-get self 'dimensions))
249     ";\n")
250    )
251 )
252
253 (method-make!
254  <array> 'gen-sym-get-macro
255  (lambda (self sym comment)
256    (let ((sym (gen-c-symbol sym))
257          (rank (length (elm-get self 'dimensions))))
258      (string-append
259       "#define GET_" (string-upcase sym)
260       "(" (string-drop 2 (gen-macro-args rank)) ") "
261       (gen-cpu-ref sym) (gen-array-ref (macro-args rank)) "\n"
262       )))
263 )
264
265 (method-make!
266  <array> 'gen-sym-set-macro
267  (lambda (self sym comment)
268    (let ((sym (gen-c-symbol sym))
269          (rank (length (elm-get self 'dimensions))))
270      (string-append
271       "#define SET_" (string-upcase sym)
272       "(" (string-drop 2 (gen-macro-args rank)) ", x) "
273       "(" (gen-cpu-ref sym) (gen-array-ref (macro-args rank))
274       " = (x))\n"
275       )))
276 )
277
278 ; Return a reference to the array.
279 ; SYM is the name of the array.
280 ; INDEX is either a single index object or a (possibly empty) list of objects,
281 ; one object per dimension.
282
283 (method-make!
284  <array> 'gen-ref
285  (lambda (self sym index estate)
286    (let ((gen-index1 (lambda (idx)
287                        (string-append "["
288                                       (/gen-hw-index idx estate)
289                                       "]"))))
290      (string-append sym
291                     (cond ((list? index) (string-map gen-index1 index))
292                           (else (gen-index1 index))))))
293 )
294
295 ; Integers
296 ;
297 ;(method-make!
298 ; <integer> 'gen-type
299 ; (lambda (self)
300 ;   (mode:c-type (mode-find (elm-get self 'bits)
301 ;                          (if (has-attr? self 'UNSIGNED)
302 ;                              'UINT 'INT)))
303 ;   )
304 ;)
305 ;
306 ;(method-make! <integer> 'gen-sym-defn (lambda (self sym comment) ""))
307 ;(method-make! <integer> 'gen-sym-get-macro (lambda (self sym comment) ""))
308 ;(method-make! <integer> 'gen-sym-set-macro (lambda (self sym comment) ""))
309 \f
310 ; Hardware descriptions support code.
311 ;
312 ; Various operations are required for each h/w object to support the various
313 ; things the simulator will want to do with it.
314 ;
315 ; Methods:
316 ; gen-type      - C type to use to record value, as a string.
317 ;                 ??? Delete and just use get-mode?
318 ; gen-defn      - generate a definition of the h/w element
319 ; gen-get-macro - Generate definition of the GET access macro.
320 ; gen-set-macro - Generate definition of the SET access macro.
321 ; gen-write     - Same as gen-read except done on output operands
322 ; cxmake-get    - Return a <c-expr> object to fetch the value.
323 ; gen-set-quiet - Set the value.
324 ;                 ??? Could just call this gen-set as there is no gen-set-trace
325 ;                 but for consistency with the messages passed to operands
326 ;                 we use this same.
327 ; save-index?   - return #t if an index needs to be saved for parallel
328 ;                 execution post-write processing
329 ; gen-profile-decl
330 ; gen-record-profile
331 ; get-mode
332 ; gen-profile-locals
333 ; gen-sym-get-macro - Generate default GET access macro.
334 ; gen-sym-set-macro - Generate default SET access macro.
335 ; gen-ref       - Return a C reference to the object.
336
337 ; gen-type handler, must be overridden.
338
339 (method-make!
340  <hardware-base> 'gen-type
341  (lambda (self) (error "gen-type not overridden:" self))
342 )
343
344 ; Generate CPU state struct entries, must be overridden.
345
346 (method-make!
347  <hardware-base> 'gen-defn
348  (lambda (self) (error "gen-defn not overridden:" self))
349 )
350
351 (method-make! <hardware-base> 'gen-sym-decl (lambda (self sym comment) ""))
352
353 ; Return a C reference to a hardware object.
354
355 (method-make! <hardware-base> 'gen-ref (lambda (self sym index estate) sym))
356
357 ; Each hardware type must provide its own gen-write method.
358
359 (method-make!
360  <hardware-base> 'gen-write
361  (lambda (self estate index mode sfmt op access-macro)
362    (error "gen-write method not overridden:" self))
363 )
364
365 (method-make! <hardware-base> 'gen-profile-decl (lambda (self) ""))
366
367 ; Default gen-record-profile method.
368
369 (method-make!
370  <hardware-base> 'gen-record-profile
371  (lambda (self index sfmt estate)
372    "") ; nothing to do
373 )
374
375 ; Default cxmake-get method.
376 ; Return a <c-expr> object of the value of SELF.
377 ; ESTATE is the current rtl evaluator state.
378 ; INDEX is a <hw-index> object.  It must be an ifield.
379 ; SELECTOR is a hardware selector RTX.
380
381 (method-make!
382  <hardware-base> 'cxmake-get
383  (lambda (self estate mode index selector)
384    (if (not (eq? 'ifield (hw-index:type index)))
385        (error "not an ifield hw-index" index))
386    (/cxmake-ifld-val mode (hw-index:value index)))
387 )
388
389 ; Handle gen-get-macro/gen-set-macro.
390
391 (method-make!
392  <hardware-base> 'gen-get-macro
393  (lambda (self)
394    "")
395 )
396
397 (method-make!
398  <hardware-base> 'gen-set-macro
399  (lambda (self)
400    "")
401 )
402 \f
403 ; PC support
404
405 ; 'gen-set-quiet helper for PC values.
406 ; NEWVAL is a <c-expr> object of the value to be assigned.
407 ; If OPTIONS contains #:direct, set the PC directly, bypassing semantic
408 ; code considerations.
409 ; ??? OPTIONS support wip.  Probably want a new form (or extend existing form)
410 ; of rtx: that takes a variable number of named arguments.
411 ; ??? Another way to get #:direct might be (raw-reg h-pc).
412
413 (define (/hw-gen-set-quiet-pc self estate mode index selector newval . options)
414   (if (not (send self 'pc?)) (error "Not a PC:" self))
415   (cond ((memq #:direct options)
416          (/hw-gen-set-quiet self estate mode index selector newval))
417         ((has-attr? newval 'CACHED)
418          (string-append "SEM_BRANCH_VIA_CACHE (current_cpu, sem_arg, "
419                         (cx:c newval)
420                         ", vpc);\n"))
421         (else
422          (string-append "SEM_BRANCH_VIA_ADDR (current_cpu, sem_arg, "
423                         (cx:c newval)
424                         ", vpc);\n")))
425 )
426
427 (method-make! <hw-pc> 'gen-set-quiet /hw-gen-set-quiet-pc)
428
429 ; Handle updates of the pc during parallel execution.
430 ; This is done in a post-processing pass after semantic evaluation.
431 ; SFMT is the <sformat>.
432 ; OP is the operand.
433 ; ACCESS-MACRO is the runtime C macro to use to fetch indices computed
434 ; during semantic evaluation.
435 ;
436 ; ??? This wouldn't be necessary if gen-set-quiet were a virtual method.
437 ; At this point I'm reluctant to willy nilly make methods virtual.
438
439 (method-make!
440  <hw-pc> 'gen-write
441  (lambda (self estate index mode sfmt op access-macro)
442    (string-append "  "
443                   (send self 'gen-set-quiet estate VOID index hw-selector-default
444                         (cx:make DFLT (string-append access-macro
445                                                    " (" (gen-sym op) ")")))))
446 )
447
448 (method-make!
449  <hw-pc> 'cxmake-skip
450  (lambda (self estate yes?)
451    (cx:make VOID
452             (string-append "if ("
453                            yes?
454                            ")\n"
455                            "  SEM_SKIP_INSN (current_cpu, sem_arg, vpc);\n")))
456 )
457 \f
458 ; Registers.
459
460 (method-make-forward! <hw-register> 'type '(gen-type))
461
462 (method-make!
463  <hw-register> 'gen-defn
464  (lambda (self)
465    (send (elm-get self 'type) 'gen-sym-defn (obj:name self) (obj:comment self)))
466 )
467
468 (method-make-forward! <hw-register> 'type '(gen-ref
469                                             gen-sym-get-macro
470                                             gen-sym-set-macro))
471
472 ; For parallel instructions supported by queueing outputs for later update,
473 ; return a boolean indicating if an index needs to be recorded.
474 ; An example of when the index isn't needed is if the index can be determined
475 ; during extraction.
476
477 (method-make!
478  <hw-register> 'save-index?
479  (lambda (self op)
480    ; FIXME: Later handle case where register number is determined at runtime.
481    #f)
482 )
483
484 ; Handle updates of registers during parallel execution.
485 ; This is done in a post-processing pass after semantic evaluation.
486 ; SFMT is the <sformat>.
487 ; OP is the <operand>.
488 ; ACCESS-MACRO is the runtime C macro to use to fetch indices computed
489 ; during semantic evaluation.
490 ; FIXME: May need mode of OP.
491
492 (method-make!
493  <hw-register> 'gen-write
494  (lambda (self estate index mode sfmt op access-macro)
495    ; First get a hw-index object to use during indexing.
496    ; Some indices, e.g. memory addresses, are computed during semantic
497    ; evaluation.  Others are computed during the extraction phase.
498    (let ((index (send index 'get-write-index self sfmt op access-macro)))
499      (string-append "  "
500                     (send self 'gen-set-quiet estate mode index hw-selector-default
501                           (cx:make DFLT (string-append access-macro
502                                                      " (" (gen-sym op) ")"))))))
503 )
504
505 (method-make!
506  <hw-register> 'gen-profile-decl
507  (lambda (self)
508    (string-append
509     "  /* " (obj:comment self) " */\n"
510     "  unsigned long " (gen-c-symbol (obj:name self)) ";\n"))
511 )
512
513 (method-make!
514  <hw-register> 'gen-record-profile
515  (lambda (self index sfmt estate)
516    ; FIXME: Need to handle scalars.
517    (/gen-hw-index-raw index estate))
518 )
519
520 (method-make!
521  <hw-register> 'gen-get-macro
522  (lambda (self)
523    (let ((getter (elm-get self 'get))
524          (mode (send self 'get-mode)))
525      (if getter
526          (let ((args (car getter))
527                (expr (cadr getter)))
528            (gen-get-macro2 (gen-sym self)
529                            (if (hw-scalar? self) "" "index")
530                            (rtl-c mode
531                                   #f ;; h/w is not ISA-specific
532                                   (if (hw-scalar? self)
533                                       nil
534                                       (list (list (car args) 'UINT "index")))
535                                   expr
536                                   #:rtl-cover-fns? #t #:macro? #t)))
537          (send self 'gen-sym-get-macro
538                (obj:name self) (obj:comment self)))))
539 )
540
541 (method-make!
542  <hw-register> 'gen-set-macro
543  (lambda (self)
544    (let ((setter (elm-get self 'set))
545          (mode (send self 'get-mode)))
546      (if setter
547          (let ((args (car setter))
548                (expr (cadr setter)))
549            (gen-set-macro2 (gen-sym self)
550                            (if (hw-scalar? self) "" "index")
551                            "x"
552                            (rtl-c VOID ;; not `mode', sets have mode VOID
553                                   #f ;; h/w is not ISA-specific
554                                   (if (hw-scalar? self)
555                                       (list (list (car args) (hw-mode self) "(x)"))
556                                       (list (list (car args) 'UINT "(index)")
557                                             (list (cadr args) (hw-mode self) "(x)")))
558                                   expr
559                                   #:rtl-cover-fns? #t #:macro? #t)))
560          (send self 'gen-sym-set-macro
561                (obj:name self) (obj:comment self)))))
562 )
563
564 ; Utility to build a <c-expr> object to fetch the value of a register.
565
566 (define (/hw-cxmake-get hw estate mode index selector)
567   (let ((mode (if (mode:eq? 'DFLT mode)
568                   (send hw 'get-mode)
569                   mode))
570         (getter (hw-getter hw)))
571     ; If the register is accessed via a cover function/macro, do it.
572     ; Otherwise fetch the value from the cached address or from the CPU struct.
573     (cx:make mode
574              (cond (getter
575                     (let ((scalar? (hw-scalar? hw))
576                           (c-index (/gen-hw-index index estate)))
577                       (string-append "GET_"
578                                      (string-upcase (gen-sym hw))
579                                      " ("
580                                      (if scalar? "" c-index)
581                                      ")")))
582                    ((and (hw-cache-addr? hw) ; FIXME: redo test
583                          (eq? 'ifield (hw-index:type index)))
584                     (string-append
585                      "* "
586                      (if (with-scache?)
587                          (gen-hw-index-argbuf-ref index)
588                          (gen-hw-index-argbuf-name index))))
589                    (else (gen-cpu-ref (send hw 'gen-ref
590                                             (gen-sym hw) index estate))))))
591 )
592
593 (method-make! <hw-register> 'cxmake-get /hw-cxmake-get)
594
595 ; raw-reg: support
596 ; ??? raw-reg: support is wip
597
598 (method-make!
599  <hw-register> 'cxmake-get-raw
600  (lambda (self estate mode index selector)
601   (let ((mode (if (mode:eq? 'DFLT mode)
602                   (send self 'get-mode)
603                   mode)))
604     (cx:make mode (gen-cpu-ref (send self 'gen-ref
605                                      (gen-sym self) index estate)))))
606 )
607
608 ; Utilities to generate C code to assign a variable to a register.
609
610 (define (/hw-gen-set-quiet hw estate mode index selector newval)
611   (let ((setter (hw-setter hw)))
612     (cond (setter
613            (let ((scalar? (hw-scalar? hw))
614                  (c-index (/gen-hw-index index estate)))
615              (string-append "SET_"
616                             (string-upcase (gen-sym hw))
617                             " ("
618                             (if scalar? "" (string-append c-index ", "))
619                             (cx:c newval)
620                             ");\n")))
621           ((and (hw-cache-addr? hw) ; FIXME: redo test
622                 (eq? 'ifield (hw-index:type index)))
623            (string-append "* "
624                           (if (with-scache?)
625                               (gen-hw-index-argbuf-ref index)
626                               (gen-hw-index-argbuf-name index))
627                           " = " (cx:c newval) ";\n"))
628           (else (string-append (gen-cpu-ref (send hw 'gen-ref
629                                                   (gen-sym hw) index estate))
630                                " = " (cx:c newval) ";\n"))))
631 )
632
633 (method-make! <hw-register> 'gen-set-quiet /hw-gen-set-quiet)
634
635 ; raw-reg: support
636 ; ??? wip
637
638 (method-make!
639  <hw-register> 'gen-set-quiet-raw
640  (lambda (self estate mode index selector newval)
641    (string-append (gen-cpu-ref (send self 'gen-ref
642                                      (gen-sym self) index estate))
643                   " = " (cx:c newval) ";\n"))
644 )
645
646 ; Return name of C access function for getting/setting a register.
647
648 (define (gen-reg-getter-fn hw prefix)
649   (string-append prefix "_" (gen-sym hw) "_get")
650 )
651
652 (define (gen-reg-setter-fn hw prefix)
653   (string-append prefix "_" (gen-sym hw) "_set")
654 )
655
656 ; Generate decls for access fns of register HW, beginning with
657 ; PREFIX, using C type TYPE.
658 ; SCALAR? is #t if the register is a scalar.  Otherwise it is #f and the
659 ; register is a bank of registers.
660
661 (define (gen-reg-access-decl hw prefix type scalar?)
662   (string-append
663    type " "
664    (gen-reg-getter-fn hw prefix)
665    " (SIM_CPU *"
666    (if scalar? "" ", UINT")
667    ");\n"
668    "void "
669    (gen-reg-setter-fn hw prefix)
670    " (SIM_CPU *, "
671    (if scalar? "" "UINT, ")
672    type ");\n"
673    )
674 )
675
676 ; Generate defns of access fns of register HW, beginning with
677 ; PREFIX, using C type TYPE.
678 ; SCALAR? is #t if the register is a scalar.  Otherwise it is #f and the
679 ; register is a bank of registers.
680 ; GET/SET-CODE are C fragments to get/set the value.
681 ; ??? Inlining left for later.
682
683 (define (gen-reg-access-defn hw prefix type scalar? get-code set-code)
684   (string-append
685    "/* Get the value of " (obj:str-name hw) ".  */\n\n"
686    type "\n"
687    (gen-reg-getter-fn hw prefix)
688    " (SIM_CPU *current_cpu"
689    (if scalar? "" ", UINT regno")
690    ")\n{\n"
691    get-code
692    "}\n\n"
693    "/* Set a value for " (obj:str-name hw) ".  */\n\n"
694    "void\n"
695    (gen-reg-setter-fn hw prefix)
696    " (SIM_CPU *current_cpu, "
697    (if scalar? "" "UINT regno, ")
698    type " newval)\n"
699    "{\n"
700    set-code
701    "}\n\n")
702 )
703 \f
704 ; Memory support.
705
706 (method-make!
707  <hw-memory> 'cxmake-get
708  (lambda (self estate mode index selector)
709    (let ((mode (if (mode:eq? 'DFLT mode)
710                    (hw-mode self)
711                    mode))
712          (default-selector? (hw-selector-default? selector)))
713      (cx:make mode
714               (string-append "GETMEM" (obj:str-name mode)
715                              (if default-selector? "" "ASI")
716                              " ("
717                              "current_cpu, pc, "
718                              (/gen-hw-index index estate)
719                              (if default-selector?
720                                  ""
721                                  (string-append ", "
722                                                 (/gen-hw-selector selector)))
723                              ")"))))
724 )
725
726 (method-make!
727  <hw-memory> 'gen-set-quiet
728  (lambda (self estate mode index selector newval)
729    (let ((mode (if (mode:eq? 'DFLT mode)
730                    (hw-mode self)
731                    mode))
732          (default-selector? (hw-selector-default? selector)))
733      (string-append "SETMEM" (obj:str-name mode)
734                     (if default-selector? "" "ASI")
735                     " ("
736                     "current_cpu, pc, "
737                     (/gen-hw-index index estate)
738                     (if default-selector?
739                         ""
740                         (string-append ", "
741                                        (/gen-hw-selector selector)))
742                     ", " (cx:c newval) ");\n")))
743 )
744
745 (method-make-forward! <hw-memory> 'type '(gen-type))
746 (method-make! <hw-memory> 'gen-defn (lambda (self sym comment) ""))
747 (method-make! <hw-memory> 'gen-sym-get-macro (lambda (self sym comment) ""))
748 (method-make! <hw-memory> 'gen-sym-set-macro (lambda (self sym comment) ""))
749
750 ; For parallel instructions supported by queueing outputs for later update,
751 ; return the type of the index or #f if not needed.
752
753 (method-make!
754  <hw-memory> 'save-index?
755  (lambda (self op)
756    ; In the case of the complete memory address being an immediate
757    ; argument, we can return #f (later).
758    AI)
759 )
760
761 (method-make!
762  <hw-memory> 'gen-write
763  (lambda (self estate index mode sfmt op access-macro)
764    (let ((index (send index 'get-write-index self sfmt op access-macro)))
765      (string-append "  "
766                     (send self 'gen-set-quiet estate mode index
767                           hw-selector-default
768                           (cx:make DFLT (string-append access-macro " ("
769                                                      (gen-sym op)
770                                                      ")"))))))
771 )
772 \f
773 ; Immediates, addresses.
774
775 (method-make-forward! <hw-immediate> 'type '(gen-type))
776
777 (method-make!
778  <hw-immediate> 'gen-defn
779  (lambda (self)
780    (send (elm-get self 'type) 'gen-sym-defn (obj:name self) (obj:comment self)))
781 )
782
783 (method-make-forward! <hw-immediate> 'type '(gen-sym-get-macro
784                                              gen-sym-set-macro))
785
786 (method-make!
787  <hw-immediate> 'gen-write
788  (lambda (self estate index mode sfmt op access-macro)
789    (error "gen-write of <hw-immediate> shouldn't happen"))
790 )
791
792 ;; FIXME
793 (method-make! <hw-address> 'gen-type (lambda (self) "ADDR"))
794 (method-make! <hw-address> 'gen-defn (lambda (self sym comment) ""))
795 (method-make! <hw-address> 'gen-sym-get-macro (lambda (self sym comment) ""))
796 (method-make! <hw-address> 'gen-sym-set-macro (lambda (self sym comment) ""))
797
798 ; Return a <c-expr> object of the value of SELF.
799 ; ESTATE is the current rtl evaluator state.
800 ; INDEX is a hw-index object.  It must be an ifield.
801 ; Needed because we record our own copy of the ifield in ARGBUF.
802 ; SELECTOR is a hardware selector RTX.
803
804 (method-make!
805  <hw-address> 'cxmake-get
806  (lambda (self estate mode index selector)
807    (if (not (eq? 'ifield (hw-index:type index)))
808        (error "not an ifield hw-index" index))
809    (if (with-scache?)
810        (cx:make mode (gen-hw-index-argbuf-ref index))
811        (cx:make mode (gen-hw-index-argbuf-name index))))
812 )
813
814 (method-make!
815  <hw-address> 'gen-write
816  (lambda (self estate index mode sfmt op access-macro)
817    (error "gen-write of <hw-address> shouldn't happen"))
818 )
819
820 ;; FIXME: consistency says there should be gen-defn, gen-sym-[gs]et-macro
821 (method-make! <hw-iaddress> 'gen-type (lambda (self) "IADDR"))
822
823 ; Return a <c-expr> object of the value of SELF.
824 ; ESTATE is the current rtl evaluator state.
825 ; INDEX is a <hw-index> object.  It must be an ifield.
826 ; Needed because we record our own copy of the ifield in ARGBUF,
827 ; *and* because we want to record in the result the 'CACHED attribute
828 ; since instruction addresses based on ifields are fixed [and thus cacheable].
829 ; SELECTOR is a hardware selector RTX.
830
831 (method-make!
832  <hw-iaddress> 'cxmake-get
833  (lambda (self estate mode index selector)
834    (if (not (eq? 'ifield (hw-index:type index)))
835        (error "not an ifield hw-index" index))
836    (if (with-scache?)
837        ; ??? Perhaps a better way would be to defer evaluating the src of a
838        ; set until the method processing the dest.
839        (cx:make-with-atlist mode (gen-hw-index-argbuf-ref index)
840                             (atlist-make "" (bool-attr-make 'CACHED #t)))
841        (cx:make mode (gen-hw-index-argbuf-name index))))
842 )
843 \f
844 ; Hardware index support code.
845
846 ; Return the index to use by the gen-write method.
847 ; In the cases where this is needed (the index isn't known until insn
848 ; execution time), the index is computed along with the value to be stored,
849 ; so this is easy.
850
851 (method-make!
852  <hw-index> 'get-write-index
853  (lambda (self hw sfmt op access-macro)
854    (if (memq (hw-index:type self) '(scalar constant enum str-expr ifield))
855        self
856        (let ((index-mode (send hw 'get-index-mode)))
857          (if index-mode
858              (make <hw-index> 'anonymous 'str-expr index-mode
859                    (string-append access-macro " (" (/op-index-name op) ")"))
860              (hw-index-scalar)))))
861 )
862
863 ; Return the name of the PAREXEC structure member holding a hardware index
864 ; for operand OP.
865
866 (define (/op-index-name op)
867   (string-append (gen-sym op) "_idx")
868 )
869
870 ; Cover fn to hardware indices to generate the actual C code.
871 ; INDEX is the hw-index object (i.e. op:index).
872 ; The result is a string of C code.
873 ; FIXME:wip
874
875 (define (/gen-hw-index-raw index estate)
876   (let ((type (hw-index:type index))
877         (mode (hw-index:mode index))
878         (value (hw-index:value index)))
879     (case type
880       ((scalar) "")
881       ; special case UINT to cut down on unnecessary verbosity.
882       ; ??? May wish to handle more similarily.
883       ((constant) (if (mode:eq? 'UINT mode)
884                       (number->string value)
885                       (string-append "((" (mode:c-type mode) ") "
886                                      (number->string value)
887                                      ")")))
888       ((enum) (let ((sym (hw-index-enum-name index))
889                     (obj (hw-index-enum-obj index)))
890                 (gen-enum-sym obj sym)))
891       ((str-expr) value)
892       ((rtx) (rtl-c-with-estate estate mode value))
893       ((ifield) (if (= (ifld-length value) 0)
894                     ""
895                     (gen-extracted-ifld-value value)))
896       ((operand) (cx:c (send value 'cxmake-get estate mode (op:index value)
897                              (op:selector value) #f)))
898       (else (error "/gen-hw-index-raw: invalid index:" index))))
899 )
900
901 ; Same as /gen-hw-index-raw except used where speedups are possible.
902 ; e.g. doing array index calcs at extraction time.
903
904 (define (/gen-hw-index index estate)
905   (let ((type (hw-index:type index))
906         (mode (hw-index:mode index))
907         (value (hw-index:value index)))
908     (case type
909       ((scalar) "")
910       ((constant) (string-append "((" (mode:c-type mode) ") "
911                                  (number->string value)
912                                  ")"))
913       ((enum) (let ((sym (hw-index-enum-name index))
914                     (obj (hw-index-enum-obj index)))
915                 (gen-enum-sym obj sym)))
916       ((str-expr) value)
917       ((rtx) (rtl-c-with-estate estate mode value))
918       ((ifield) (if (= (ifld-length value) 0)
919                     ""
920                     (cx:c (/cxmake-ifld-val mode value))))
921       ((operand) (cx:c (send value 'cxmake-get estate mode (op:index value)
922                              (op:selector value))))
923       (else (error "/gen-hw-index: invalid index:" index))))
924 )
925
926 ; Return address where HW is stored.
927
928 (define (/gen-hw-addr hw estate index)
929   (let ((setter (hw-setter hw)))
930     (cond ((and (hw-cache-addr? hw) ; FIXME: redo test
931                 (eq? 'ifield (hw-index:type index)))
932            (if (with-scache?)
933                (gen-hw-index-argbuf-ref index)
934                (gen-hw-index-argbuf-name index)))
935           (else
936            (string-append "& "
937                           (gen-cpu-ref (send hw 'gen-ref
938                                              (gen-sym hw) index estate))))))
939 )
940
941 ; Return a <c-expr> object of the value of a hardware index.
942
943 (method-make!
944  <hw-index> 'cxmake-get
945  (lambda (self estate mode)
946    (let ((mode (if (mode:eq? 'DFLT mode) (elm-get self 'mode) mode)))
947      ; If MODE is VOID, abort.
948      (if (mode:eq? 'VOID mode)
949          (error "hw-index:cxmake-get: result needs a mode" self))
950      (cx:make (if (mode:host? mode)
951                   ; FIXME: Temporary hack to generate same code as before.
952                   (let ((xmode (object-copy-top mode)))
953                     (obj-cons-attr! xmode (bool-attr-make 'FORCE-C #t))
954                     xmode)
955                   mode)
956               (/gen-hw-index self estate))))
957 )
958 \f
959 ; Hardware selector support code.
960
961 ; Generate C code for SEL.
962
963 (define (/gen-hw-selector sel)
964   (rtl-c INT #f nil sel)
965 )
966 \f
967 ; Instruction operand support code.
968
969 ; Methods:
970 ; gen-type      - Return C type to use to hold operand's value.
971 ; gen-read      - Record an operand's value prior to parallely executing
972 ;                 several instructions.  Not used if gen-write used.
973 ; gen-write     - Write back an operand's value after parallely executing
974 ;                 several instructions.  Not used if gen-read used.
975 ; cxmake-get    - Return C code to fetch the value of an operand.
976 ; gen-set-quiet - Return C code to set the value of an operand.
977 ; gen-set-trace - Return C code to set the value of an operand, and print
978 ;                 a result trace message.  ??? Ideally this will go away when
979 ;                 trace record support is complete.
980
981 ; Return the C type of an operand.
982 ; Generally we forward things on to TYPE, but for the actual type we need to
983 ; use the get-mode method.
984
985 ;(method-make-forward! <operand> 'type '(gen-type))
986 (method-make!
987  <operand> 'gen-type
988  (lambda (self)
989    ; First get the mode.
990    (let ((mode (send self 'get-mode)))
991      ; If it's VOID use the type's type.
992      (if (mode:eq? 'DFLT mode)
993          (send (op:type self) 'gen-type)
994          (mode:c-type mode))))
995 )
996
997 ; Extra pc operand methods.
998
999 (method-make!
1000  <pc> 'cxmake-get
1001  (lambda (self estate mode index selector)
1002    (let ((mode (if (mode:eq? 'DFLT mode)
1003                    (send self 'get-mode)
1004                    mode)))
1005      ; The enclosing function must set `pc' to the correct value.
1006      (cx:make mode "pc")))
1007 )
1008
1009 (method-make!
1010  <pc> 'cxmake-skip
1011  (lambda (self estate yes?)
1012    (send (op:type self) 'cxmake-skip estate
1013          (rtl-c INT (obj-isa-list self) nil yes? #:rtl-cover-fns? #t)))
1014 )
1015
1016 ; For parallel write post-processing, we don't want to defer setting the pc.
1017 ; ??? Not sure anymore.
1018 ;(method-make!
1019 ; <pc> 'gen-set-quiet
1020 ; (lambda (self estate mode index selector newval)
1021 ;   (/op-gen-set-quiet self estate mode index selector newval)))
1022 ;(method-make!
1023 ; <pc> 'gen-set-trace
1024 ; (lambda (self estate mode index selector newval)
1025 ;   (/op-gen-set-trace self estate mode index selector newval)))
1026
1027 ; Name of C macro to access parallel execution operand support.
1028
1029 (define /par-operand-macro "OPRND")
1030
1031 ; Return C code to fetch an operand's value and save it away for the
1032 ; semantic handler.  This is used to handle parallel execution of several
1033 ; instructions where all inputs of all insns are read before any outputs are
1034 ; written.
1035 ; For operands, the word `read' is only used in this context.
1036
1037 (define (op:read op sfmt)
1038   (let ((estate (estate-make-for-rtl-c nil)))
1039     (send op 'gen-read estate sfmt /par-operand-macro))
1040 )
1041
1042 ; Return C code to write an operand's value.
1043 ; This is used to handle parallel execution of several instructions where all
1044 ; outputs are written to temporary spots first, and then a final
1045 ; post-processing pass is run to update cpu state.
1046 ; For operands, the word `write' is only used in this context.
1047
1048 (define (op:write op sfmt)
1049   (let ((estate (estate-make-for-rtl-c nil)))
1050     (send op 'gen-write estate sfmt /par-operand-macro))
1051 )
1052
1053 ; Default gen-read method.
1054 ; This is used to help support targets with parallel insns.
1055 ; Either this or gen-write (but not both) is used.
1056
1057 (method-make!
1058  <operand> 'gen-read
1059  (lambda (self estate sfmt access-macro)
1060    (string-append "  "
1061                   access-macro " ("
1062                   (gen-sym self)
1063                   ") = "
1064                   ; Pass #f for the index -> use the operand's builtin index.
1065                   ; Ditto for the selector.
1066                   (cx:c (send self 'cxmake-get estate DFLT #f #f))
1067                   ";\n"))
1068 )
1069
1070 ; Forward gen-write onto the <hardware> object.
1071
1072 (method-make!
1073  <operand> 'gen-write
1074  (lambda (self estate sfmt access-macro)
1075    (let ((write-back-code (send (op:type self) 'gen-write estate
1076                                 (op:index self) (op:mode self)
1077                                 sfmt self access-macro)))
1078      ; If operand is conditionally written, we have to check that first.
1079      ; ??? If two (or more) operands are written based on the same condition,
1080      ; all the tests can be collapsed together.  Not sure that's a big
1081      ; enough win yet.
1082      (if (op:cond? self)
1083          (string-append "  if (written & (1 << "
1084                         (number->string (op:num self))
1085                         "))\n"
1086                         "    {\n"
1087                         "    " write-back-code
1088                         "    }\n")
1089          write-back-code)))
1090 )
1091
1092 ; Return <c-expr> object to get the value of an operand.
1093 ; ESTATE is the current rtl evaluator state.
1094 ; If INDEX is non-#f use it, otherwise use (op:index self).
1095 ; This special handling of #f for INDEX is *only* supported for operands
1096 ; in cxmake-get, gen-set-quiet, and gen-set-trace.
1097 ; Ditto for SELECTOR.
1098
1099 (method-make!
1100  <operand> 'cxmake-get
1101  (lambda (self estate mode index selector)
1102    (let ((mode (if (mode:eq? 'DFLT mode)
1103                    (send self 'get-mode)
1104                    mode))
1105          (index (if index index (op:index self)))
1106          (selector (if selector selector (op:selector self))))
1107      ; If the instruction could be parallely executed with others and we're
1108      ; doing read pre-processing, the operand has already been fetched, we
1109      ; just have to grab the cached value.
1110      ; ??? reg-raw: support wip
1111      (cond ((obj-has-attr? self 'RAW)
1112             (send (op:type self) 'cxmake-get-raw estate mode index selector))
1113            ((with-parallel-read?)
1114             (cx:make-with-atlist mode
1115                                  (string-append /par-operand-macro
1116                                                 " (" (gen-sym self) ")")
1117                                  nil)) ; FIXME: want CACHED attr if present
1118            ((op:getter self)
1119             (let ((args (car (op:getter self)))
1120                   (expr (cadr (op:getter self))))
1121               (rtl-c-expr mode
1122                           (obj-isa-list self)
1123                           (if (= (length args) 0)
1124                               nil
1125                               (list (list (car args) 'UINT index)))
1126                           expr
1127                           #:rtl-cover-fns? #t)))
1128            (else
1129             (send (op:type self) 'cxmake-get estate mode index selector)))))
1130 )
1131
1132 ; Utilities to implement gen-set-quiet/gen-set-trace.
1133
1134 (define (/op-gen-set-quiet op estate mode index selector newval)
1135   (send (op:type op) 'gen-set-quiet estate mode index selector newval)
1136 )
1137
1138 ; Return C code to call the appropriate queued-write handler.
1139 ; ??? wip
1140
1141 (define (/op-gen-queued-write op estate mode index selector newval)
1142   (let* ((hw (op:type op))
1143          (setter (hw-setter hw))
1144          (sem-mode (mode:sem-mode mode)))
1145     (string-append
1146      "    "
1147      "sim_queue_"
1148      ; FIXME: clean up (pc? op) vs (memory? hw)
1149      ; FIXME: (send 'pc?) is a temporary hack, (pc? op) didn't work
1150      (cond ((send hw 'pc?)
1151             (string-append
1152              (if setter
1153                  "fn_"
1154                  "")
1155              "pc"))
1156            (else
1157             (string-append
1158              (cond ((memory? hw)
1159                     "mem_")
1160                    ((hw-scalar? hw)
1161                     "scalar_")
1162                    (else ""))
1163              (if setter
1164                  "fn_"
1165                  "")
1166              (string-downcase (symbol->string (if sem-mode
1167                                                   (mode-real-name sem-mode)
1168                                                   (mode-real-name mode)))))))
1169      "_write (current_cpu"
1170      ; ??? May need to include h/w id some day.
1171      (if setter
1172          (string-append ", " (gen-reg-setter-fn hw "@cpu@"))
1173          "")
1174      (cond ((hw-scalar? hw)
1175             "")
1176            (setter
1177             (string-append ", " (/gen-hw-index index estate)))
1178            ((memory? hw)
1179             (string-append ", " (/gen-hw-index index estate)))
1180            (else
1181             (string-append ", " (/gen-hw-addr (op:type op) estate index))))
1182      ", "
1183      newval
1184      ");\n"))
1185 )
1186
1187 (define (/op-gen-set-quiet-parallel op estate mode index selector newval)
1188   (if (with-generic-write?)
1189       (/op-gen-queued-write op estate mode index selector (cx:c newval))
1190       (string-append
1191        (if (op-save-index? op)
1192            (string-append "    "
1193                           /par-operand-macro " (" (/op-index-name op) ")"
1194                           " = " (/gen-hw-index index estate) ";\n")
1195            "")
1196        "    "
1197        /par-operand-macro " (" (gen-sym op) ")"
1198        " = " (cx:c newval) ";\n"))
1199 )
1200
1201 (define /operand-number-elaboration-written? #f)
1202
1203 ;; Return code to update `written'.
1204
1205 (define (/op-gen-written-update op)
1206   (if (op:cond? op)
1207       ;; FIXME: we don't yet handle a large number of operands
1208       (if (< (op:num op) 32)
1209           (string-append "    written |= (1 << "
1210                          (number->string (op:num op))
1211                          ");\n")
1212           (begin
1213             ;; FIXME: This creates broken simulators if with-parallel-write?.
1214             (message (if (with-parallel-write?) "Error: " "Warning: ")
1215                      (obj:name op)
1216                      " operand number " (op:num op)
1217                      " is too large (>= 32)\n")
1218             (if (not /operand-number-elaboration-written?)
1219                 (begin
1220                   (message "This is a current internal cgen limitation.\n")
1221                   (if (not (with-parallel-write?))
1222                       (message "The only effect is a loss in profiling capability.\n"))
1223                   (set! /operand-number-elaboration-written? #t)))
1224             ""))
1225       "")
1226 )
1227
1228 (define (/op-gen-set-trace op estate mode index selector newval)
1229   (string-append
1230    "  {\n"
1231    "    " (mode:c-type mode) " opval = " (cx:c newval) ";\n"
1232    ; Dispatch to setter code if appropriate
1233    "    "
1234    (if (op:setter op)
1235        (let ((args (car (op:setter op)))
1236              (expr (cadr (op:setter op))))
1237          (rtl-c VOID
1238                 (obj-isa-list op)
1239                 (if (= (length args) 0)
1240                     (list (list 'newval mode "opval"))
1241                     (list (list (car args) 'UINT index)
1242                           (list 'newval mode "opval")))
1243                 expr
1244                 #:rtl-cover-fns? #t))
1245        ;else
1246        (send (op:type op) 'gen-set-quiet estate mode index selector
1247              (cx:make-with-atlist mode "opval" (cx:atlist newval))))
1248    (/op-gen-written-update op)
1249 ; TRACE_RESULT_<MODE> (cpu, abuf, hwnum, opnum, value);
1250 ; For each insn record array of operand numbers [or indices into
1251 ; operand instance table].
1252 ; Could just scan the operand table for the operand or hardware number,
1253 ; assuming the operand number is stored in `op'.
1254    "    TRACE_RESULT (current_cpu, abuf"
1255    ", " (send op 'gen-pretty-name mode)
1256    ", " (mode:printf-type mode)
1257    ", opval);\n"
1258    "  }\n")
1259 )
1260
1261 (define (/op-gen-set-trace-parallel op estate mode index selector newval)
1262   (string-append
1263    "  {\n"
1264    "    " (mode:c-type mode) " opval = " (cx:c newval) ";\n"
1265    (if (with-generic-write?)
1266        (/op-gen-queued-write op estate mode index selector "opval")
1267        (string-append
1268         (if (op-save-index? op)
1269             (string-append "    "
1270                            /par-operand-macro " (" (/op-index-name op) ")"
1271                            " = " (/gen-hw-index index estate) ";\n")
1272             "")
1273         "    " /par-operand-macro " (" (gen-sym op) ")"
1274         " = opval;\n"))
1275    (/op-gen-written-update op)
1276 ; TRACE_RESULT_<MODE> (cpu, abuf, hwnum, opnum, value);
1277 ; For each insn record array of operand numbers [or indices into
1278 ; operand instance table].
1279 ; Could just scan the operand table for the operand or hardware number,
1280 ; assuming the operand number is stored in `op'.
1281    "    TRACE_RESULT (current_cpu, abuf"
1282    ", " (send op 'gen-pretty-name mode)
1283    ", " (mode:printf-type mode)
1284    ", opval);\n"
1285    "  }\n")
1286 )
1287
1288 ; Return C code to set the value of an operand.
1289 ; NEWVAL is a <c-expr> object of the value to store.
1290 ; If INDEX is non-#f use it, otherwise use (op:index self).
1291 ; This special handling of #f for INDEX is *only* supported for operands
1292 ; in cxmake-get, gen-set-quiet, and gen-set-trace.
1293 ; Ditto for SELECTOR.
1294
1295 (method-make!
1296  <operand> 'gen-set-quiet
1297  (lambda (self estate mode index selector newval)
1298    (let ((mode (if (mode:eq? 'DFLT mode)
1299                    (send self 'get-mode)
1300                    mode))
1301          (index (if index index (op:index self)))
1302          (selector (if selector selector (op:selector self))))
1303      ; ??? raw-reg: support wip
1304      (cond ((obj-has-attr? self 'RAW)
1305             (send (op:type self) 'gen-set-quiet-raw estate mode index selector newval))
1306            ((with-parallel-write?)
1307             (/op-gen-set-quiet-parallel self estate mode index selector newval))
1308            (else
1309             (/op-gen-set-quiet self estate mode index selector newval)))))
1310 )
1311
1312 ; Return C code to set the value of an operand and print TRACE_RESULT message.
1313 ; NEWVAL is a <c-expr> object of the value to store.
1314 ; If INDEX is non-#f use it, otherwise use (op:index self).
1315 ; This special handling of #f for INDEX is *only* supported for operands
1316 ; in cxmake-get, gen-set-quiet, and gen-set-trace.
1317 ; Ditto for SELECTOR.
1318
1319 (method-make!
1320  <operand> 'gen-set-trace
1321  (lambda (self estate mode index selector newval)
1322    (let ((mode (if (mode:eq? 'DFLT mode)
1323                    (send self 'get-mode)
1324                    mode))
1325          (index (if index index (op:index self)))
1326          (selector (if selector selector (op:selector self))))
1327      ; ??? raw-reg: support wip
1328      (cond ((obj-has-attr? self 'RAW)
1329             (send (op:type self) 'gen-set-quiet-raw estate mode index selector newval))
1330            ((with-parallel-write?)
1331             (/op-gen-set-trace-parallel self estate mode index selector newval))
1332            (else
1333             (/op-gen-set-trace self estate mode index selector newval)))))
1334 )
1335
1336 ; Define and undefine C macros to tuck away details of instruction format used
1337 ; in the parallel execution functions.  See gen-define-field-macro for a
1338 ; similar thing done for extraction/semantic functions.
1339
1340 (define (gen-define-parallel-operand-macro sfmt)
1341   (string-append "#define " /par-operand-macro "(f) "
1342                  "par_exec->operands."
1343                  (gen-sym sfmt)
1344                  ".f\n")
1345 )
1346
1347 (define (gen-undef-parallel-operand-macro sfmt)
1348   (string-append "#undef " /par-operand-macro "\n")
1349 )
1350 \f
1351 ; Operand profiling and parallel execution support.
1352
1353 (method-make!
1354  <operand> 'save-index?
1355  (lambda (self) (send (op:type self) 'save-index? self))
1356 )
1357
1358 ; Return boolean indicating if operand OP needs its index saved
1359 ; (for parallel write post-processing support).
1360
1361 (define (op-save-index? op)
1362   (send op 'save-index?)
1363 )
1364
1365 ; Return C code to record profile data for modeling use.
1366 ; In the case of a register, this is usually the register's number.
1367 ; This shouldn't be called in the case of a scalar, the code should be
1368 ; smart enough to know there is no need.
1369
1370 (define (op:record-profile op sfmt out?)
1371   (let ((estate (estate-make-for-rtl-c nil)))
1372     (send op 'gen-record-profile sfmt out? estate))
1373 )
1374
1375 ; Return C code to record the data needed for profiling operand SELF.
1376 ; This is done during extraction.
1377
1378 (method-make!
1379  <operand> 'gen-record-profile
1380  (lambda (self sfmt out? estate)
1381    (if (hw-scalar? (op:type self))
1382        ""
1383        (string-append "      "
1384                       (gen-argbuf-ref (send self 'sbuf-profile-sym out?))
1385                       " = "
1386                       (send (op:type self) 'gen-record-profile
1387                             (op:index self) sfmt estate)
1388                       ";\n")))
1389 )
1390
1391 ; Return C code to track profiling of operand SELF.
1392 ; This is usually called by the x-after handler.
1393
1394 (method-make!
1395  <operand> 'gen-profile-code
1396  (lambda (self insn out?)
1397    (string-append "  "
1398                   "@cpu@_model_mark_"
1399                   (if out? "set_" "get_")
1400                   (gen-sym (op:type self))
1401                   " (current_cpu"
1402                   (if (hw-scalar? (op:type self))
1403                       ""
1404                       (string-append ", "
1405                                      (gen-argbuf-ref
1406                                       (send self 'sbuf-profile-sym out?))))
1407                   ");\n"))
1408 )
1409 \f
1410 ; CPU, mach, model support.
1411
1412 ; Return the declaration of the cpu/insn enum.
1413
1414 (define (gen-cpu-insn-enum-decl cpu insn-list)
1415   (gen-enum-decl "@prefix@_insn_type"
1416                  "instructions in cpu family @cpu@"
1417                  "@PREFIX@_INSN_"
1418                  (append! (map (lambda (i)
1419                                  (cons (obj:name i)
1420                                        (cons '-
1421                                              (atlist-attrs (obj-atlist i)))))
1422                                insn-list)
1423                           (if (with-parallel?)
1424                               (apply append!
1425                                      (map (lambda (i)
1426                                             (list
1427                                              (cons (symbol-append 'par- (obj:name i))
1428                                                    (cons '-
1429                                                          (atlist-attrs (obj-atlist i))))
1430                                              (cons (symbol-append 'write- (obj:name i))
1431                                                    (cons '-
1432                                                          (atlist-attrs (obj-atlist i))))))
1433                                           (parallel-insns insn-list)))
1434                               nil)
1435                           (list '(-max))))
1436 )
1437
1438 ; Return the enum of INSN in cpu family CPU.
1439 ; In addition to CGEN_INSN_TYPE, an enum is created for each insn in each
1440 ; cpu family.  This collapses the insn enum space for each cpu to increase
1441 ; cache efficiently (since the IDESC table is similarily collapsed).
1442
1443 (define (gen-cpu-insn-enum cpu insn)
1444   (string-upcase (string-append "@PREFIX@_INSN_" (gen-sym insn)))
1445 )
1446
1447 ; Return C code to declare the machine data.
1448
1449 (define (/gen-mach-decls)
1450   (string-append
1451    (string-map (lambda (mach)
1452                  (gen-obj-sanitize mach
1453                                    (string-append "extern const MACH "
1454                                                   (gen-sym mach)
1455                                                   "_mach;\n")))
1456                (current-mach-list))
1457    "\n")
1458 )
1459
1460 ; Return C code to define the machine data.
1461
1462 (define (/gen-mach-data)
1463   (string-append
1464    "const MACH *sim_machs[] =\n{\n"
1465    (string-map (lambda (mach)
1466                  (gen-obj-sanitize
1467                   mach
1468                   (string-append "#ifdef " (gen-have-cpu (mach-cpu mach)) "\n"
1469                                  "  & " (gen-sym mach) "_mach,\n"
1470                                  "#endif\n")))
1471                (current-mach-list))
1472    "  0\n"
1473    "};\n\n"
1474    )
1475 )
1476
1477 ; Return C declarations of cpu model support stuff.
1478 ; ??? This goes in arch.h but a better place is each cpu.h.
1479
1480 (define (/gen-arch-model-decls)
1481   (string-append
1482    (gen-enum-decl 'model_type "model types"
1483                   "MODEL_"
1484                   (append (map (lambda (model)
1485                                  (cons (obj:name model)
1486                                        (cons '-
1487                                              (atlist-attrs (obj-atlist model)))))
1488                                (current-model-list))
1489                           '((max))))
1490    "#define MAX_MODELS ((int) MODEL_MAX)\n\n"
1491    (gen-enum-decl 'unit_type "unit types"
1492                   "UNIT_"
1493                   (cons '(none)
1494                         (append
1495                          ; "apply append" squeezes out nils.
1496                          (apply append
1497                                 ; create <model_name>-<unit-name> for each unit
1498                                 (map (lambda (model)
1499                                        (let ((units (model:units model)))
1500                                          (if (null? units)
1501                                              nil
1502                                              (map (lambda (unit)
1503                                                     (cons (symbol-append (obj:name model) '-
1504                                                                          (obj:name unit))
1505                                                           (cons '- (atlist-attrs (obj-atlist model)))))
1506                                                   units))))
1507                                      (current-model-list)))
1508                          '((max)))))
1509    ; FIXME: revisit MAX_UNITS
1510    "#define MAX_UNITS ("
1511    (number->string
1512     (apply max
1513            (map (lambda (lengths) (apply max lengths))
1514                 (map (lambda (insn)
1515                        (let ((timing (insn-timing insn)))
1516                          (if (null? timing)
1517                              '(1)
1518                              (map (lambda (insn-timing)
1519                                     (if (null? (cdr insn-timing))
1520                                         '1
1521                                         (length (timing:units (cdr insn-timing)))))
1522                                   timing))))
1523                      (current-insn-list)))))
1524    ")\n\n"
1525    )
1526 )
1527 \f
1528 ; Function units.
1529
1530 (method-make! <unit> 'gen-decl (lambda (self) ""))
1531
1532 ; Lookup operand named OP-NAME in INSN.
1533 ; Returns #f if OP-NAME is not an operand of INSN.
1534 ; IN-OUT is 'in to request an input operand, 'out to request an output operand,
1535 ; and 'in-out to request either (though if an operand is used for input and
1536 ; output then the input version is returned).
1537 ; FIXME: Move elsewhere.
1538
1539 (define (insn-op-lookup op-name insn in-out)
1540   (letrec ((lookup (lambda (op-list)
1541                      (cond ((null? op-list) #f)
1542                            ((eq? op-name (op:sem-name (car op-list))) (car op-list))
1543                            (else (lookup (cdr op-list)))))))
1544     (case in-out
1545       ((in) (lookup (sfmt-in-ops (insn-sfmt insn))))
1546       ((out) (lookup (sfmt-out-ops (insn-sfmt insn))))
1547       ((in-out) (or (lookup (sfmt-in-ops (insn-sfmt insn)))
1548                     (lookup (sfmt-out-ops (insn-sfmt insn)))))
1549       (else (error "insn-op-lookup: bad arg:" in-out))))
1550 )
1551
1552 ; Return C code to profile a unit's usage.
1553 ; UNIT-NUM is number of the unit in INSN.
1554 ; OVERRIDES is a list of (name value) pairs, where
1555 ; - NAME is a spec name, one of cycles, pred, in, out.
1556 ;   The only ones we're concerned with are in,out.  They map operand names
1557 ;   as they appear in the semantic code to operand names as they appear in
1558 ;   the function unit spec.
1559 ; - VALUE is the operand to NAME.  For in,out it is (NAME VALUE) where
1560 ;   - NAME is the name of an input/output arg of the unit.
1561 ;   - VALUE is the name of the operand as it appears in semantic code.
1562 ;
1563 ; ??? This is a big sucker, though half of it is just the definitions
1564 ; of utility fns.
1565
1566 (method-make!
1567  <unit> 'gen-profile-code
1568  (lambda (self unit-num insn overrides cycles-var-name)
1569    (let (
1570          (inputs (unit:inputs self))
1571          (outputs (unit:outputs self))
1572
1573           ; Return C code to initialize UNIT-REFERENCED-VAR to be a bit mask
1574           ; of operands of UNIT that were read/written by INSN.
1575           ; INSN-REFERENCED-VAR is a bitmask of operands read/written by INSN.
1576           ; All we have to do is map INSN-REFERENCED-VAR to
1577           ; UNIT-REFERENCED-VAR.
1578           ; ??? For now we assume all input operands are read.
1579           (gen-ref-arg (lambda (arg num in-out)
1580                          (let* ((op-name (assq-ref overrides (car arg)))
1581                                 (op (insn-op-lookup (if op-name
1582                                                         (car op-name)
1583                                                         (car arg))
1584                                                     insn in-out))
1585                                 (insn-referenced-var "insn_referenced")
1586                                 (unit-referenced-var "referenced"))
1587                            (if op
1588                                (if (op:cond? op)
1589                                    (string-append "    "
1590                                                   "if ("
1591                                                   insn-referenced-var
1592                                                   " & (1 << "
1593                                                   (number->string (op:num op))
1594                                                   ")) "
1595                                                   unit-referenced-var
1596                                                   " |= 1 << "
1597                                                   (number->string num)
1598                                                   ";\n")
1599                                    (string-append "    "
1600                                                   unit-referenced-var
1601                                                   " |= 1 << "
1602                                                   (number->string num)
1603                                                   ";\n"))
1604                                ""))))
1605
1606           ; Initialize unit argument ARG.
1607           ; OUT? is #f for input args, #t for output args.
1608           (gen-arg-init (lambda (arg out?)
1609                           (if (or
1610                                ; Ignore scalars.
1611                                (null? (cdr arg))
1612                                ; Ignore remapped arg, handled elsewhere.
1613                                (assq (car arg) overrides)
1614                                ; Ignore operands not in INSN.
1615                                (not (insn-op-lookup (car arg) insn
1616                                                     (if out? 'out 'in))))
1617                               ""
1618                               (let ((sym (gen-profile-sym (gen-c-symbol (car arg))
1619                                                            out?)))
1620                                 (string-append "    "
1621                                                sym
1622                                                " = "
1623                                                (gen-argbuf-ref sym)
1624                                                ";\n")))))
1625
1626           ; Return C code to declare variable to hold unit argument ARG.
1627           ; OUT? is #f for input args, #t for output args.
1628           (gen-arg-decl (lambda (arg out?)
1629                           (if (null? (cdr arg)) ; ignore scalars
1630                               ""
1631                               (string-append "    "
1632                                              (mode:c-type (mode:lookup (cadr arg)))
1633                                              " "
1634                                              (gen-profile-sym (gen-c-symbol (car arg))
1635                                                               out?)
1636                                              " = "
1637                                              (if (null? (cddr arg))
1638                                                  "0"
1639                                                  (number->string (caddr arg)))
1640                                              ";\n"))))
1641
1642           ; Return C code to pass unit argument ARG to the handler.
1643           ; OUT? is #f for input args, #t for output args.
1644           (gen-arg-arg (lambda (arg out?)
1645                          (if (null? (cdr arg)) ; ignore scalars
1646                              ""
1647                              (string-append ", "
1648                                             (gen-profile-sym (gen-c-symbol (car arg))
1649                                                              out?)))))
1650           )
1651
1652      (string-list
1653       "  {\n"
1654       "    int referenced = 0;\n"
1655       "    int UNUSED insn_referenced = abuf->written;\n"
1656       ; Declare variables to hold unit arguments.
1657       (string-map (lambda (arg) (gen-arg-decl arg #f))
1658                   inputs)
1659       (string-map (lambda (arg) (gen-arg-decl arg #t))
1660                   outputs)
1661       ; Initialize 'em, being careful not to initialize an operand that
1662       ; has an override.
1663       (let (; Make a list of names of in/out overrides.
1664             (in-overrides (find-apply cadr
1665                                       (lambda (elm) (eq? (car elm) 'in))
1666                                       overrides))
1667             (out-overrides (find-apply cadr
1668                                       (lambda (elm) (eq? (car elm) 'out))
1669                                       overrides)))
1670         (string-list
1671          (string-map (lambda (arg)
1672                        (if (memq (car arg) in-overrides)
1673                            ""
1674                            (gen-arg-init arg #f)))
1675                      inputs)
1676          (string-map (lambda (arg)
1677                        (if (memq (car arg) out-overrides)
1678                            ""
1679                            (gen-arg-init arg #t)))
1680                      outputs)))
1681       (string-map (lambda (arg)
1682                     (case (car arg)
1683                       ((pred) "")
1684                       ((cycles) "")
1685                       ((in)
1686                        (if (caddr arg)
1687                            (string-append "    "
1688                                           (gen-profile-sym (gen-c-symbol (cadr arg)) #f)
1689                                           " = "
1690                                           (gen-argbuf-ref
1691                                            (gen-profile-sym (gen-c-symbol (caddr arg)) #f))
1692                                           ";\n")
1693                            ""))
1694                       ((out)
1695                        (if (caddr arg)
1696                            (string-append "    "
1697                                           (gen-profile-sym (gen-c-symbol (cadr arg)) #t)
1698                                           " = "
1699                                           (gen-argbuf-ref
1700                                            (gen-profile-sym (gen-c-symbol (caddr arg)) #t))
1701                                           ";\n")
1702                            ""))
1703                       (else
1704                        (parse-error (make-prefix-context "insn function unit spec")
1705                                     "invalid spec" arg))))
1706                   overrides)
1707       ; Create bitmask indicating which args were referenced.
1708       (string-map (lambda (arg num) (gen-ref-arg arg num 'in))
1709                   inputs
1710                   (iota (length inputs)))
1711       (string-map (lambda (arg num) (gen-ref-arg arg num 'out))
1712                   outputs
1713                   (iota (length outputs)
1714                         (length inputs)))
1715       ; Emit the call to the handler.
1716       "    " cycles-var-name " += "
1717       (gen-model-unit-fn-name (unit:model self) self)
1718       " (current_cpu, idesc"
1719       ", " (number->string unit-num)
1720       ", referenced"
1721       (string-map (lambda (arg) (gen-arg-arg arg #f))
1722                   inputs)
1723       (string-map (lambda (arg) (gen-arg-arg arg #t))
1724                   outputs)
1725       ");\n"
1726       "  }\n"
1727       )))
1728 )
1729
1730 ; Return C code to profile an insn-specific unit's usage.
1731 ; UNIT-NUM is number of the unit in INSN.
1732
1733 (method-make!
1734  <iunit> 'gen-profile-code
1735  (lambda (self unit-num insn cycles-var-name)
1736    (let ((args (iunit:args self))
1737          (unit (iunit:unit self)))
1738      (send unit 'gen-profile-code unit-num insn args cycles-var-name)))
1739 )
1740 \f
1741 ; ARGBUF generation.
1742 ; ARGBUF support is put in cpuall.h, which doesn't depend on sim-cpu.scm,
1743 ; so this support is here.
1744
1745 ; Utility of /gen-argbuf-fields-union to generate the definition for
1746 ; <sformat-abuf> SBUF.
1747
1748 (define (/gen-argbuf-elm sbuf)
1749   (logit 2 "Processing sbuf format " (obj:name sbuf) " ...\n")
1750   (string-list
1751    "  struct { /* " (obj:comment sbuf) " */\n"
1752    (let ((elms (sbuf-elms sbuf)))
1753      (if (null? elms)
1754          "    int empty;\n"
1755          (string-list-map (lambda (elm)
1756                             (string-append "    "
1757                                            (cadr elm)
1758                                            " "
1759                                            (car elm)
1760                                            ";\n"))
1761                           (sbuf-elms sbuf))))
1762    "  } " (gen-sym sbuf) ";\n")
1763 )
1764
1765 ; Utility of gen-argbuf-type to generate the union of extracted ifields.
1766
1767 (define (/gen-argbuf-fields-union)
1768   (string-list
1769    "\
1770 /* Instruction argument buffer.  */
1771
1772 union sem_fields {\n"
1773    (string-list-map /gen-argbuf-elm (current-sbuf-list))
1774    "\
1775 #if WITH_SCACHE_PBB
1776   /* Writeback handler.  */
1777   struct {
1778     /* Pointer to argbuf entry for insn whose results need writing back.  */
1779     const struct argbuf *abuf;
1780   } write;
1781   /* x-before handler */
1782   struct {
1783     /*const SCACHE *insns[MAX_PARALLEL_INSNS];*/
1784     int first_p;
1785   } before;
1786   /* x-after handler */
1787   struct {
1788     int empty;
1789   } after;
1790   /* This entry is used to terminate each pbb.  */
1791   struct {
1792     /* Number of insns in pbb.  */
1793     int insn_count;
1794     /* Next pbb to execute.  */
1795     SCACHE *next;
1796     SCACHE *branch_target;
1797   } chain;
1798 #endif
1799 };\n\n"
1800    )
1801 )
1802
1803 ; Generate the definition of the structure that records arguments.
1804 ; This is a union of structures with one structure for each insn format.
1805 ; It also includes hardware profiling information and miscellaneous
1806 ; administrivia.
1807 ; CPU-DATA? is #t if data for the currently selected cpu is to be included.
1808
1809 (define (gen-argbuf-type cpu-data?)
1810   (logit 2 "Generating ARGBUF type ...\n")
1811   (string-list
1812    (if (and cpu-data? (with-scache?))
1813        (/gen-argbuf-fields-union)
1814        "")
1815    (if cpu-data? "" "#ifndef WANT_CPU\n")
1816    "\
1817 /* The ARGBUF struct.  */
1818 struct argbuf {
1819   /* These are the baseclass definitions.  */
1820   IADDR addr;
1821   const IDESC *idesc;
1822   char trace_p;
1823   char profile_p;
1824   /* ??? Temporary hack for skip insns.  */
1825   char skip_count;
1826   char unused;
1827   /* cpu specific data follows */\n"
1828    (if cpu-data?
1829        (if (with-scache?)
1830             "\
1831   union sem semantic;
1832   int written;
1833   union sem_fields fields;\n"
1834             "\
1835   CGEN_INSN_WORD insn;
1836   int written;\n")
1837        "")
1838    "};\n"
1839    (if cpu-data? "" "#endif\n")
1840    "\n"
1841    )
1842 )
1843
1844 ; Generate the definition of the structure that records a cached insn.
1845 ; This is cpu family specific (member `argbuf' is) so it is machine generated.
1846 ; CPU-DATA? is #t if data for the currently selected cpu is to be included.
1847
1848 (define (gen-scache-type cpu-data?)
1849   (logit 2 "Generating SCACHE type ...\n")
1850   (string-append
1851    (if cpu-data? "" "#ifndef WANT_CPU\n")
1852    "\
1853 /* A cached insn.
1854
1855    ??? SCACHE used to contain more than just argbuf.  We could delete the
1856    type entirely and always just use ARGBUF, but for future concerns and as
1857    a level of abstraction it is left in.  */
1858
1859 struct scache {
1860   struct argbuf argbuf;\n"
1861    (if (with-generic-write?) "\
1862   int first_insn_p;
1863   int last_insn_p;\n" "")
1864    "};\n"
1865    (if cpu-data? "" "#endif\n")
1866    "\n"
1867   )
1868 )
1869 \f
1870 ; Mode support.
1871
1872 ; Generate a table of mode data.
1873 ; For now all we need is the names.
1874
1875 (define (gen-mode-defs)
1876   (string-append
1877    "const char *mode_names[] = {\n"
1878    (string-map (lambda (m)
1879                  (string-append "  \"" (string-upcase (obj:str-name m)) "\",\n"))
1880                ; We don't treat aliases as being different from the real
1881                ; mode here, so ignore them.
1882                (mode-list-non-alias-values))
1883    "};\n\n"
1884    )
1885 )
1886 \f
1887 ; Insn profiling support.
1888
1889 ; Generate declarations for local variables needed for modelling code.
1890
1891 (method-make!
1892  <insn> 'gen-profile-locals
1893  (lambda (self model)
1894 ;   (let ((cti? (or (has-attr? self 'UNCOND-CTI)
1895 ;                  (has-attr? self 'COND-CTI))))
1896 ;     (string-append
1897 ;      (if cti? "  int UNUSED taken_p = 0;\n" "")
1898 ;      ))
1899    "")
1900 )
1901
1902 ; Generate C code to profile INSN.
1903
1904 (method-make!
1905  <insn> 'gen-profile-code
1906  (lambda (self model cycles-var-name)
1907    (string-list
1908     (let ((timing (assq-ref (insn-timing self) (obj:name model))))
1909       (if timing
1910           (string-list-map (lambda (iunit unit-num)
1911                              (send iunit 'gen-profile-code unit-num self cycles-var-name))
1912                            (timing:units timing)
1913                            (iota (length (timing:units timing))))
1914           (send (model-default-unit model) 'gen-profile-code 0 self nil cycles-var-name)))
1915     ))
1916 )
1917 \f
1918 ; .cpu file loading support
1919
1920 ; Only run sim-analyze-insns! once.
1921 (define /sim-insns-analyzed? #f)
1922
1923 ; List of computed sformat argument buffers.
1924 (define /sim-sformat-abuf-list #f)
1925 (define (current-sbuf-list) /sim-sformat-abuf-list)
1926
1927 ; Called before/after the .cpu file has been read in.
1928
1929 (define (sim-init!)
1930   (set! /sim-insns-analyzed? #f)
1931   (set! /sim-sformat-abuf-list #f)
1932   *UNSPECIFIED*
1933 )
1934
1935 ;; Subroutine of /create-virtual-insns!.
1936 ;; Add virtual insn INSN to the database.
1937 ;; We put virtual insns ahead of normal insns because they're kind of special,
1938 ;; and it helps to see them first in lists.
1939 ;; ORDINAL is a used to place the insn ahead of normal insns;
1940 ;; it is a pair so we can do the update for the next virtual insn here.
1941
1942 (define (/virtual-insn-add! ordinal insn)
1943   (obj-set-ordinal! insn (cdr ordinal))
1944   (current-insn-add! insn)
1945   (set-cdr! ordinal (- (cdr ordinal) 1))
1946 )
1947
1948 ; Create the virtual insns.
1949
1950 (define (/create-virtual-insns!)
1951   (let ((all (all-isas-attr-value))
1952         (context (make-prefix-context "virtual insns"))
1953         ;; Record as a pair so /virtual-insn-add! can update it.
1954         (ordinal (cons #f -1)))
1955
1956     (/virtual-insn-add!
1957      ordinal
1958      (insn-read context
1959                 '(name x-begin)
1960                 '(comment "pbb begin handler")
1961                 `(attrs VIRTUAL PBB (ISA ,@all))
1962                 '(syntax "--begin--")
1963                 '(semantics (c-code VOID "\
1964   {
1965 #if WITH_SCACHE_PBB_@PREFIX@
1966 #if defined DEFINE_SWITCH || defined FAST_P
1967     /* In the switch case FAST_P is a constant, allowing several optimizations
1968        in any called inline functions.  */
1969     vpc = @prefix@_pbb_begin (current_cpu, FAST_P);
1970 #else
1971 #if 0 /* cgen engine can't handle dynamic fast/full switching yet.  */
1972     vpc = @prefix@_pbb_begin (current_cpu, STATE_RUN_FAST_P (CPU_STATE (current_cpu)));
1973 #else
1974     vpc = @prefix@_pbb_begin (current_cpu, 0);
1975 #endif
1976 #endif
1977 #endif
1978   }
1979 "))
1980                 ))
1981
1982     (/virtual-insn-add!
1983      ordinal
1984      (insn-read context
1985                 '(name x-chain)
1986                 '(comment "pbb chain handler")
1987                 `(attrs VIRTUAL PBB (ISA ,@all))
1988                 '(syntax "--chain--")
1989                 '(semantics (c-code VOID "\
1990   {
1991 #if WITH_SCACHE_PBB_@PREFIX@
1992     vpc = @prefix@_pbb_chain (current_cpu, sem_arg);
1993 #ifdef DEFINE_SWITCH
1994     BREAK (sem);
1995 #endif
1996 #endif
1997   }
1998 "))
1999                 ))
2000
2001     (/virtual-insn-add!
2002      ordinal
2003      (insn-read context
2004                 '(name x-cti-chain)
2005                 '(comment "pbb cti-chain handler")
2006                 `(attrs VIRTUAL PBB (ISA ,@all))
2007                 '(syntax "--cti-chain--")
2008                 '(semantics (c-code VOID "\
2009   {
2010 #if WITH_SCACHE_PBB_@PREFIX@
2011 #ifdef DEFINE_SWITCH
2012     vpc = @prefix@_pbb_cti_chain (current_cpu, sem_arg,
2013                                pbb_br_type, pbb_br_npc);
2014     BREAK (sem);
2015 #else
2016     /* FIXME: Allow provision of explicit ifmt spec in insn spec.  */
2017     vpc = @prefix@_pbb_cti_chain (current_cpu, sem_arg,
2018                                CPU_PBB_BR_TYPE (current_cpu),
2019                                CPU_PBB_BR_NPC (current_cpu));
2020 #endif
2021 #endif
2022   }
2023 "))
2024                 ))
2025
2026     (/virtual-insn-add!
2027      ordinal
2028      (insn-read context
2029                 '(name x-before)
2030                 '(comment "pbb begin handler")
2031                 `(attrs VIRTUAL PBB (ISA ,@all))
2032                 '(syntax "--before--")
2033                 '(semantics (c-code VOID "\
2034   {
2035 #if WITH_SCACHE_PBB_@PREFIX@
2036     @prefix@_pbb_before (current_cpu, sem_arg);
2037 #endif
2038   }
2039 "))
2040                 ))
2041
2042     (/virtual-insn-add!
2043      ordinal
2044      (insn-read context
2045                 '(name x-after)
2046                 '(comment "pbb after handler")
2047                 `(attrs VIRTUAL PBB (ISA ,@all))
2048                 '(syntax "--after--")
2049                 '(semantics (c-code VOID "\
2050   {
2051 #if WITH_SCACHE_PBB_@PREFIX@
2052     @prefix@_pbb_after (current_cpu, sem_arg);
2053 #endif
2054   }
2055 "))
2056                 ))
2057
2058     (/virtual-insn-add!
2059      ordinal
2060      (insn-read context
2061                 '(name x-invalid)
2062                 '(comment "invalid insn handler")
2063                 `(attrs VIRTUAL (ISA ,@all))
2064                 '(syntax "--invalid--")
2065                 (list 'semantics (list 'c-code 'VOID (string-append "\
2066   {
2067     /* Update the recorded pc in the cpu state struct.
2068        Only necessary for WITH_SCACHE case, but to avoid the
2069        conditional compilation ....  */
2070     SET_H_PC (pc);
2071     /* Virtual insns have zero size.  Overwrite vpc with address of next insn
2072        using the default-insn-bitsize spec.  When executing insns in parallel
2073        we may want to queue the fault and continue execution.  */
2074     vpc = SEM_NEXT_VPC (sem_arg, pc, " (number->string (bits->bytes (state-default-insn-bitsize))) ");
2075     vpc = sim_engine_invalid_insn (current_cpu, pc, vpc);
2076   }
2077 ")))
2078                 ))
2079     )
2080 )
2081
2082 (define (sim-finish!)
2083   ; Add begin,chain,before,after,invalid handlers if not provided.
2084   ; The code generators should first look for x-foo-@prefix@, then for x-foo.
2085   ; ??? This is good enough for the first pass.  Will eventually need to use
2086   ; less C and more RTL.
2087   (/create-virtual-insns!)
2088
2089   *UNSPECIFIED*
2090 )
2091
2092 ; Called after file is read in and global error checks are done
2093 ; to initialize tables.
2094
2095 (define (sim-analyze!)
2096   *UNSPECIFIED*
2097 )
2098
2099 ; Scan insns, analyzing semantics and computing instruction formats.
2100 ; 'twould be nice to do this in sim-analyze! but it doesn't know whether this
2101 ; needs to be done or not (which is determined by what files are being
2102 ; generated).  Since this is an expensive operation, we defer doing this
2103 ; to the files that need it.
2104
2105 (define (sim-analyze-insns!)
2106   ; This can only be done if one isa and one cpu family is being kept.
2107   (assert-keep-one)
2108
2109   (if (not /sim-insns-analyzed?)
2110
2111       (begin
2112         (arch-analyze-insns! CURRENT-ARCH
2113                              #f ; don't include aliases
2114                              #t) ; do analyze the semantics
2115
2116         ; Compute the set of sformat argument buffers.
2117         (set! /sim-sformat-abuf-list (compute-sformat-argbufs! (current-sfmt-list)))
2118
2119         (set! /sim-insns-analyzed? #t)))
2120
2121   ; Do our own error checking.
2122   (assert (current-insn-lookup 'x-invalid #f))
2123
2124   *UNSPECIFIED*
2125 )
2126 \f
2127 ; For debugging.
2128
2129 (define (cgen-all-arch)
2130   (string-write
2131    cgen-arch.h
2132    cgen-arch.c
2133    cgen-cpuall.h
2134    ;cgen-mem-ops.h
2135    ;cgen-sem-ops.h
2136    ;cgen-ops.c
2137    )
2138 )
2139
2140 (define (cgen-all-cpu)
2141   (string-write
2142    cgen-cpu.h
2143    cgen-cpu.c
2144    cgen-decode.h
2145    cgen-decode.c
2146    ;cgen-extract.c
2147    cgen-read.c
2148    cgen-write.c
2149    cgen-semantics.c
2150    cgen-sem-switch.c
2151    cgen-model.c
2152    ;cgen-mainloop.in
2153    )
2154 )