OSDN Git Service

* cos.scm (/method-lookup): Delete arg virtual?, all callers updated.
[pf3gnuchains/sourceware.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-macro (gen-sym self)
529                           (if (hw-scalar? self) "" "index")
530                           (rtl-c mode expr
531                                  (if (hw-scalar? self)
532                                      nil
533                                      (list (list (car args) 'UINT "index")))
534                                  #:rtl-cover-fns? #t)))
535          (send self 'gen-sym-get-macro
536                (obj:name self) (obj:comment self)))))
537 )
538
539 (method-make!
540  <hw-register> 'gen-set-macro
541  (lambda (self)
542    (let ((setter (elm-get self 'set))
543          (mode (send self 'get-mode)))
544      (if setter
545          (let ((args (car setter))
546                (expr (cadr setter)))
547            (gen-set-macro2 (gen-sym self)
548                            (if (hw-scalar? self)
549                                ""
550                                "index")
551                            "x"
552                            (rtl-c VOID ; not `mode', sets have mode VOID
553                                   expr
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                                   #:rtl-cover-fns? #t #:macro? #t)))
559          (send self 'gen-sym-set-macro
560                (obj:name self) (obj:comment self)))))
561 )
562
563 ; Utility to build a <c-expr> object to fetch the value of a register.
564
565 (define (/hw-cxmake-get hw estate mode index selector)
566   (let ((mode (if (mode:eq? 'DFLT mode)
567                   (send hw 'get-mode)
568                   mode))
569         (getter (hw-getter hw)))
570     ; If the register is accessed via a cover function/macro, do it.
571     ; Otherwise fetch the value from the cached address or from the CPU struct.
572     (cx:make mode
573              (cond (getter
574                     (let ((scalar? (hw-scalar? hw))
575                           (c-index (/gen-hw-index index estate)))
576                       (string-append "GET_"
577                                      (string-upcase (gen-sym hw))
578                                      " ("
579                                      (if scalar? "" c-index)
580                                      ")")))
581                    ((and (hw-cache-addr? hw) ; FIXME: redo test
582                          (eq? 'ifield (hw-index:type index)))
583                     (string-append
584                      "* "
585                      (if (with-scache?)
586                          (gen-hw-index-argbuf-ref index)
587                          (gen-hw-index-argbuf-name index))))
588                    (else (gen-cpu-ref (send hw 'gen-ref
589                                             (gen-sym hw) index estate))))))
590 )
591
592 (method-make! <hw-register> 'cxmake-get /hw-cxmake-get)
593
594 ; raw-reg: support
595 ; ??? raw-reg: support is wip
596
597 (method-make!
598  <hw-register> 'cxmake-get-raw
599  (lambda (self estate mode index selector)
600   (let ((mode (if (mode:eq? 'DFLT mode)
601                   (send self 'get-mode)
602                   mode)))
603     (cx:make mode (gen-cpu-ref (send self 'gen-ref
604                                      (gen-sym self) index estate)))))
605 )
606
607 ; Utilities to generate C code to assign a variable to a register.
608
609 (define (/hw-gen-set-quiet hw estate mode index selector newval)
610   (let ((setter (hw-setter hw)))
611     (cond (setter
612            (let ((scalar? (hw-scalar? hw))
613                  (c-index (/gen-hw-index index estate)))
614              (string-append "SET_"
615                             (string-upcase (gen-sym hw))
616                             " ("
617                             (if scalar? "" (string-append c-index ", "))
618                             (cx:c newval)
619                             ");\n")))
620           ((and (hw-cache-addr? hw) ; FIXME: redo test
621                 (eq? 'ifield (hw-index:type index)))
622            (string-append "* "
623                           (if (with-scache?)
624                               (gen-hw-index-argbuf-ref index)
625                               (gen-hw-index-argbuf-name index))
626                           " = " (cx:c newval) ";\n"))
627           (else (string-append (gen-cpu-ref (send hw 'gen-ref
628                                                   (gen-sym hw) index estate))
629                                " = " (cx:c newval) ";\n"))))
630 )
631
632 (method-make! <hw-register> 'gen-set-quiet /hw-gen-set-quiet)
633
634 ; raw-reg: support
635 ; ??? wip
636
637 (method-make!
638  <hw-register> 'gen-set-quiet-raw
639  (lambda (self estate mode index selector newval)
640    (string-append (gen-cpu-ref (send self 'gen-ref
641                                      (gen-sym self) index estate))
642                   " = " (cx:c newval) ";\n"))
643 )
644
645 ; Return name of C access function for getting/setting a register.
646
647 (define (gen-reg-getter-fn hw prefix)
648   (string-append prefix "_" (gen-sym hw) "_get")
649 )
650
651 (define (gen-reg-setter-fn hw prefix)
652   (string-append prefix "_" (gen-sym hw) "_set")
653 )
654
655 ; Generate decls for access fns of register HW, beginning with
656 ; PREFIX, using C type TYPE.
657 ; SCALAR? is #t if the register is a scalar.  Otherwise it is #f and the
658 ; register is a bank of registers.
659
660 (define (gen-reg-access-decl hw prefix type scalar?)
661   (string-append
662    type " "
663    (gen-reg-getter-fn hw prefix)
664    " (SIM_CPU *"
665    (if scalar? "" ", UINT")
666    ");\n"
667    "void "
668    (gen-reg-setter-fn hw prefix)
669    " (SIM_CPU *, "
670    (if scalar? "" "UINT, ")
671    type ");\n"
672    )
673 )
674
675 ; Generate defns of access fns of register HW, beginning with
676 ; PREFIX, using C type TYPE.
677 ; SCALAR? is #t if the register is a scalar.  Otherwise it is #f and the
678 ; register is a bank of registers.
679 ; GET/SET-CODE are C fragments to get/set the value.
680 ; ??? Inlining left for later.
681
682 (define (gen-reg-access-defn hw prefix type scalar? get-code set-code)
683   (string-append
684    "/* Get the value of " (obj:str-name hw) ".  */\n\n"
685    type "\n"
686    (gen-reg-getter-fn hw prefix)
687    " (SIM_CPU *current_cpu"
688    (if scalar? "" ", UINT regno")
689    ")\n{\n"
690    get-code
691    "}\n\n"
692    "/* Set a value for " (obj:str-name hw) ".  */\n\n"
693    "void\n"
694    (gen-reg-setter-fn hw prefix)
695    " (SIM_CPU *current_cpu, "
696    (if scalar? "" "UINT regno, ")
697    type " newval)\n"
698    "{\n"
699    set-code
700    "}\n\n")
701 )
702 \f
703 ; Memory support.
704
705 (method-make!
706  <hw-memory> 'cxmake-get
707  (lambda (self estate mode index selector)
708    (let ((mode (if (mode:eq? 'DFLT mode)
709                    (hw-mode self)
710                    mode))
711          (default-selector? (hw-selector-default? selector)))
712      (cx:make mode
713               (string-append "GETMEM" (obj:str-name mode)
714                              (if default-selector? "" "ASI")
715                              " ("
716                              "current_cpu, pc, "
717                              (/gen-hw-index index estate)
718                              (if default-selector?
719                                  ""
720                                  (string-append ", "
721                                                 (/gen-hw-selector selector)))
722                              ")"))))
723 )
724
725 (method-make!
726  <hw-memory> 'gen-set-quiet
727  (lambda (self estate mode index selector newval)
728    (let ((mode (if (mode:eq? 'DFLT mode)
729                    (hw-mode self)
730                    mode))
731          (default-selector? (hw-selector-default? selector)))
732      (string-append "SETMEM" (obj:str-name mode)
733                     (if default-selector? "" "ASI")
734                     " ("
735                     "current_cpu, pc, "
736                     (/gen-hw-index index estate)
737                     (if default-selector?
738                         ""
739                         (string-append ", "
740                                        (/gen-hw-selector selector)))
741                     ", " (cx:c newval) ");\n")))
742 )
743
744 (method-make-forward! <hw-memory> 'type '(gen-type))
745 (method-make! <hw-memory> 'gen-defn (lambda (self sym comment) ""))
746 (method-make! <hw-memory> 'gen-sym-get-macro (lambda (self sym comment) ""))
747 (method-make! <hw-memory> 'gen-sym-set-macro (lambda (self sym comment) ""))
748
749 ; For parallel instructions supported by queueing outputs for later update,
750 ; return the type of the index or #f if not needed.
751
752 (method-make!
753  <hw-memory> 'save-index?
754  (lambda (self op)
755    ; In the case of the complete memory address being an immediate
756    ; argument, we can return #f (later).
757    AI)
758 )
759
760 (method-make!
761  <hw-memory> 'gen-write
762  (lambda (self estate index mode sfmt op access-macro)
763    (let ((index (send index 'get-write-index self sfmt op access-macro)))
764      (string-append "  "
765                     (send self 'gen-set-quiet estate mode index
766                           hw-selector-default
767                           (cx:make DFLT (string-append access-macro " ("
768                                                      (gen-sym op)
769                                                      ")"))))))
770 )
771 \f
772 ; Immediates, addresses.
773
774 (method-make-forward! <hw-immediate> 'type '(gen-type))
775
776 (method-make!
777  <hw-immediate> 'gen-defn
778  (lambda (self)
779    (send (elm-get self 'type) 'gen-sym-defn (obj:name self) (obj:comment self)))
780 )
781
782 (method-make-forward! <hw-immediate> 'type '(gen-sym-get-macro
783                                              gen-sym-set-macro))
784
785 (method-make!
786  <hw-immediate> 'gen-write
787  (lambda (self estate index mode sfmt op access-macro)
788    (error "gen-write of <hw-immediate> shouldn't happen"))
789 )
790
791 ;; FIXME
792 (method-make! <hw-address> 'gen-type (lambda (self) "ADDR"))
793 (method-make! <hw-address> 'gen-defn (lambda (self sym comment) ""))
794 (method-make! <hw-address> 'gen-sym-get-macro (lambda (self sym comment) ""))
795 (method-make! <hw-address> 'gen-sym-set-macro (lambda (self sym comment) ""))
796
797 ; Return a <c-expr> object of the value of SELF.
798 ; ESTATE is the current rtl evaluator state.
799 ; INDEX is a hw-index object.  It must be an ifield.
800 ; Needed because we record our own copy of the ifield in ARGBUF.
801 ; SELECTOR is a hardware selector RTX.
802
803 (method-make!
804  <hw-address> 'cxmake-get
805  (lambda (self estate mode index selector)
806    (if (not (eq? 'ifield (hw-index:type index)))
807        (error "not an ifield hw-index" index))
808    (if (with-scache?)
809        (cx:make mode (gen-hw-index-argbuf-ref index))
810        (cx:make mode (gen-hw-index-argbuf-name index))))
811 )
812
813 (method-make!
814  <hw-address> 'gen-write
815  (lambda (self estate index mode sfmt op access-macro)
816    (error "gen-write of <hw-address> shouldn't happen"))
817 )
818
819 ;; FIXME: consistency says there should be gen-defn, gen-sym-[gs]et-macro
820 (method-make! <hw-iaddress> 'gen-type (lambda (self) "IADDR"))
821
822 ; Return a <c-expr> object of the value of SELF.
823 ; ESTATE is the current rtl evaluator state.
824 ; INDEX is a <hw-index> object.  It must be an ifield.
825 ; Needed because we record our own copy of the ifield in ARGBUF,
826 ; *and* because we want to record in the result the 'CACHED attribute
827 ; since instruction addresses based on ifields are fixed [and thus cacheable].
828 ; SELECTOR is a hardware selector RTX.
829
830 (method-make!
831  <hw-iaddress> 'cxmake-get
832  (lambda (self estate mode index selector)
833    (if (not (eq? 'ifield (hw-index:type index)))
834        (error "not an ifield hw-index" index))
835    (if (with-scache?)
836        ; ??? Perhaps a better way would be to defer evaluating the src of a
837        ; set until the method processing the dest.
838        (cx:make-with-atlist mode (gen-hw-index-argbuf-ref index)
839                             (atlist-make "" (bool-attr-make 'CACHED #t)))
840        (cx:make mode (gen-hw-index-argbuf-name index))))
841 )
842 \f
843 ; Hardware index support code.
844
845 ; Return the index to use by the gen-write method.
846 ; In the cases where this is needed (the index isn't known until insn
847 ; execution time), the index is computed along with the value to be stored,
848 ; so this is easy.
849
850 (method-make!
851  <hw-index> 'get-write-index
852  (lambda (self hw sfmt op access-macro)
853    (if (memq (hw-index:type self) '(scalar constant str-expr ifield))
854        self
855        (let ((index-mode (send hw 'get-index-mode)))
856          (if index-mode
857              (make <hw-index> 'anonymous 'str-expr index-mode
858                    (string-append access-macro " (" (/op-index-name op) ")"))
859              (hw-index-scalar)))))
860 )
861
862 ; Return the name of the PAREXEC structure member holding a hardware index
863 ; for operand OP.
864
865 (define (/op-index-name op)
866   (string-append (gen-sym op) "_idx")
867 )
868
869 ; Cover fn to hardware indices to generate the actual C code.
870 ; INDEX is the hw-index object (i.e. op:index).
871 ; The result is a string of C code.
872 ; FIXME:wip
873
874 (define (/gen-hw-index-raw index estate)
875   (let ((type (hw-index:type index))
876         (mode (hw-index:mode index))
877         (value (hw-index:value index)))
878     (case type
879       ((scalar) "")
880       ; special case UINT to cut down on unnecessary verbosity.
881       ; ??? May wish to handle more similarily.
882       ((constant) (if (mode:eq? 'UINT mode)
883                       (number->string value)
884                       (string-append "((" (mode:c-type mode) ") "
885                                      (number->string value)
886                                      ")")))
887       ((str-expr) value)
888       ((rtx) (rtl-c-with-estate estate mode value))
889       ((ifield) (if (= (ifld-length value) 0)
890                     ""
891                     (gen-extracted-ifld-value value)))
892       ((operand) (cx:c (send value 'cxmake-get estate mode (op:index value)
893                              (op:selector value) #f)))
894       (else (error "/gen-hw-index-raw: invalid index:" index))))
895 )
896
897 ; Same as /gen-hw-index-raw except used where speedups are possible.
898 ; e.g. doing array index calcs at extraction time.
899
900 (define (/gen-hw-index index estate)
901   (let ((type (hw-index:type index))
902         (mode (hw-index:mode index))
903         (value (hw-index:value index)))
904     (case type
905       ((scalar) "")
906       ((constant) (string-append "((" (mode:c-type mode) ") "
907                                  (number->string value)
908                                  ")"))
909       ((str-expr) value)
910       ((rtx) (rtl-c-with-estate estate mode value))
911       ((ifield) (if (= (ifld-length value) 0)
912                     ""
913                     (cx:c (/cxmake-ifld-val mode value))))
914       ((operand) (cx:c (send value 'cxmake-get estate mode (op:index value)
915                              (op:selector value))))
916       (else (error "/gen-hw-index: invalid index:" index))))
917 )
918
919 ; Return address where HW is stored.
920
921 (define (/gen-hw-addr hw estate index)
922   (let ((setter (hw-setter hw)))
923     (cond ((and (hw-cache-addr? hw) ; FIXME: redo test
924                 (eq? 'ifield (hw-index:type index)))
925            (if (with-scache?)
926                (gen-hw-index-argbuf-ref index)
927                (gen-hw-index-argbuf-name index)))
928           (else
929            (string-append "& "
930                           (gen-cpu-ref (send hw 'gen-ref
931                                              (gen-sym hw) index estate))))))
932 )
933
934 ; Return a <c-expr> object of the value of a hardware index.
935
936 (method-make!
937  <hw-index> 'cxmake-get
938  (lambda (self estate mode)
939    (let ((mode (if (mode:eq? 'DFLT mode) (elm-get self 'mode) mode)))
940      ; If MODE is VOID, abort.
941      (if (mode:eq? 'VOID mode)
942          (error "hw-index:cxmake-get: result needs a mode" self))
943      (cx:make (if (mode:host? mode)
944                   ; FIXME: Temporary hack to generate same code as before.
945                   (let ((xmode (object-copy-top mode)))
946                     (obj-cons-attr! xmode (bool-attr-make 'FORCE-C #t))
947                     xmode)
948                   mode)
949               (/gen-hw-index self estate))))
950 )
951 \f
952 ; Hardware selector support code.
953
954 ; Generate C code for SEL.
955
956 (define (/gen-hw-selector sel)
957   (rtl-c 'INT sel nil)
958 )
959 \f
960 ; Instruction operand support code.
961
962 ; Methods:
963 ; gen-type      - Return C type to use to hold operand's value.
964 ; gen-read      - Record an operand's value prior to parallely executing
965 ;                 several instructions.  Not used if gen-write used.
966 ; gen-write     - Write back an operand's value after parallely executing
967 ;                 several instructions.  Not used if gen-read used.
968 ; cxmake-get    - Return C code to fetch the value of an operand.
969 ; gen-set-quiet - Return C code to set the value of an operand.
970 ; gen-set-trace - Return C code to set the value of an operand, and print
971 ;                 a result trace message.  ??? Ideally this will go away when
972 ;                 trace record support is complete.
973
974 ; Return the C type of an operand.
975 ; Generally we forward things on to TYPE, but for the actual type we need to
976 ; use the get-mode method.
977
978 ;(method-make-forward! <operand> 'type '(gen-type))
979 (method-make!
980  <operand> 'gen-type
981  (lambda (self)
982    ; First get the mode.
983    (let ((mode (send self 'get-mode)))
984      ; If it's VOID use the type's type.
985      (if (mode:eq? 'DFLT mode)
986          (send (op:type self) 'gen-type)
987          (mode:c-type mode))))
988 )
989
990 ; Extra pc operand methods.
991
992 (method-make!
993  <pc> 'cxmake-get
994  (lambda (self estate mode index selector)
995    (let ((mode (if (mode:eq? 'DFLT mode)
996                    (send self 'get-mode)
997                    mode)))
998      ; The enclosing function must set `pc' to the correct value.
999      (cx:make mode "pc")))
1000 )
1001
1002 (method-make!
1003  <pc> 'cxmake-skip
1004  (lambda (self estate yes?)
1005    (send (op:type self) 'cxmake-skip estate
1006          (rtl-c INT yes? nil #:rtl-cover-fns? #t)))
1007 )
1008
1009 ; For parallel write post-processing, we don't want to defer setting the pc.
1010 ; ??? Not sure anymore.
1011 ;(method-make!
1012 ; <pc> 'gen-set-quiet
1013 ; (lambda (self estate mode index selector newval)
1014 ;   (/op-gen-set-quiet self estate mode index selector newval)))
1015 ;(method-make!
1016 ; <pc> 'gen-set-trace
1017 ; (lambda (self estate mode index selector newval)
1018 ;   (/op-gen-set-trace self estate mode index selector newval)))
1019
1020 ; Name of C macro to access parallel execution operand support.
1021
1022 (define /par-operand-macro "OPRND")
1023
1024 ; Return C code to fetch an operand's value and save it away for the
1025 ; semantic handler.  This is used to handle parallel execution of several
1026 ; instructions where all inputs of all insns are read before any outputs are
1027 ; written.
1028 ; For operands, the word `read' is only used in this context.
1029
1030 (define (op:read op sfmt)
1031   (let ((estate (estate-make-for-rtl-c nil nil)))
1032     (send op 'gen-read estate sfmt /par-operand-macro))
1033 )
1034
1035 ; Return C code to write an operand's value.
1036 ; This is used to handle parallel execution of several instructions where all
1037 ; outputs are written to temporary spots first, and then a final
1038 ; post-processing pass is run to update cpu state.
1039 ; For operands, the word `write' is only used in this context.
1040
1041 (define (op:write op sfmt)
1042   (let ((estate (estate-make-for-rtl-c nil nil)))
1043     (send op 'gen-write estate sfmt /par-operand-macro))
1044 )
1045
1046 ; Default gen-read method.
1047 ; This is used to help support targets with parallel insns.
1048 ; Either this or gen-write (but not both) is used.
1049
1050 (method-make!
1051  <operand> 'gen-read
1052  (lambda (self estate sfmt access-macro)
1053    (string-append "  "
1054                   access-macro " ("
1055                   (gen-sym self)
1056                   ") = "
1057                   ; Pass #f for the index -> use the operand's builtin index.
1058                   ; Ditto for the selector.
1059                   (cx:c (send self 'cxmake-get estate DFLT #f #f))
1060                   ";\n"))
1061 )
1062
1063 ; Forward gen-write onto the <hardware> object.
1064
1065 (method-make!
1066  <operand> 'gen-write
1067  (lambda (self estate sfmt access-macro)
1068    (let ((write-back-code (send (op:type self) 'gen-write estate
1069                                 (op:index self) (op:mode self)
1070                                 sfmt self access-macro)))
1071      ; If operand is conditionally written, we have to check that first.
1072      ; ??? If two (or more) operands are written based on the same condition,
1073      ; all the tests can be collapsed together.  Not sure that's a big
1074      ; enough win yet.
1075      (if (op:cond? self)
1076          (string-append "  if (written & (1 << "
1077                         (number->string (op:num self))
1078                         "))\n"
1079                         "    {\n"
1080                         "    " write-back-code
1081                         "    }\n")
1082          write-back-code)))
1083 )
1084
1085 ; Return <c-expr> object to get the value of an operand.
1086 ; ESTATE is the current rtl evaluator state.
1087 ; If INDEX is non-#f use it, otherwise use (op:index self).
1088 ; This special handling of #f for INDEX is *only* supported for operands
1089 ; in cxmake-get, gen-set-quiet, and gen-set-trace.
1090 ; Ditto for SELECTOR.
1091
1092 (method-make!
1093  <operand> 'cxmake-get
1094  (lambda (self estate mode index selector)
1095    (let ((mode (if (mode:eq? 'DFLT mode)
1096                    (send self 'get-mode)
1097                    mode))
1098          (index (if index index (op:index self)))
1099          (selector (if selector selector (op:selector self))))
1100      ; If the instruction could be parallely executed with others and we're
1101      ; doing read pre-processing, the operand has already been fetched, we
1102      ; just have to grab the cached value.
1103      ; ??? reg-raw: support wip
1104      (cond ((obj-has-attr? self 'RAW)
1105             (send (op:type self) 'cxmake-get-raw estate mode index selector))
1106            ((with-parallel-read?)
1107             (cx:make-with-atlist mode
1108                                  (string-append /par-operand-macro
1109                                                 " (" (gen-sym self) ")")
1110                                  nil)) ; FIXME: want CACHED attr if present
1111            ((op:getter self)
1112             (let ((args (car (op:getter self)))
1113                   (expr (cadr (op:getter self))))
1114               (rtl-c-expr mode expr
1115                           (if (= (length args) 0)
1116                               nil
1117                               (list (list (car args) 'UINT index)))
1118                           #:rtl-cover-fns? #t)))
1119            (else
1120             (send (op:type self) 'cxmake-get estate mode index selector)))))
1121 )
1122
1123 ; Utilities to implement gen-set-quiet/gen-set-trace.
1124
1125 (define (/op-gen-set-quiet op estate mode index selector newval)
1126   (send (op:type op) 'gen-set-quiet estate mode index selector newval)
1127 )
1128
1129 ; Return C code to call the appropriate queued-write handler.
1130 ; ??? wip
1131
1132 (define (/op-gen-queued-write op estate mode index selector newval)
1133   (let* ((hw (op:type op))
1134          (setter (hw-setter hw))
1135          (sem-mode (mode:sem-mode mode)))
1136     (string-append
1137      "    "
1138      "sim_queue_"
1139      ; FIXME: clean up (pc? op) vs (memory? hw)
1140      ; FIXME: (send 'pc?) is a temporary hack, (pc? op) didn't work
1141      (cond ((send hw 'pc?)
1142             (string-append
1143              (if setter
1144                  "fn_"
1145                  "")
1146              "pc"))
1147            (else
1148             (string-append
1149              (cond ((memory? hw)
1150                     "mem_")
1151                    ((hw-scalar? hw)
1152                     "scalar_")
1153                    (else ""))
1154              (if setter
1155                  "fn_"
1156                  "")
1157              (string-downcase (symbol->string (if sem-mode
1158                                                   (mode-real-name sem-mode)
1159                                                   (mode-real-name mode)))))))
1160      "_write (current_cpu"
1161      ; ??? May need to include h/w id some day.
1162      (if setter
1163          (string-append ", " (gen-reg-setter-fn hw "@cpu@"))
1164          "")
1165      (cond ((hw-scalar? hw)
1166             "")
1167            (setter
1168             (string-append ", " (/gen-hw-index index estate)))
1169            ((memory? hw)
1170             (string-append ", " (/gen-hw-index index estate)))
1171            (else
1172             (string-append ", " (/gen-hw-addr (op:type op) estate index))))
1173      ", "
1174      newval
1175      ");\n"))
1176 )
1177
1178 (define (/op-gen-set-quiet-parallel op estate mode index selector newval)
1179   (if (with-generic-write?)
1180       (/op-gen-queued-write op estate mode index selector (cx:c newval))
1181       (string-append
1182        (if (op-save-index? op)
1183            (string-append "    "
1184                           /par-operand-macro " (" (/op-index-name op) ")"
1185                           " = " (/gen-hw-index index estate) ";\n")
1186            "")
1187        "    "
1188        /par-operand-macro " (" (gen-sym op) ")"
1189        " = " (cx:c newval) ";\n"))
1190 )
1191
1192 (define (/op-gen-set-trace op estate mode index selector newval)
1193   (string-append
1194    "  {\n"
1195    "    " (mode:c-type mode) " opval = " (cx:c newval) ";\n"
1196    ; Dispatch to setter code if appropriate
1197    "    "
1198    (if (op:setter op)
1199        (let ((args (car (op:setter op)))
1200              (expr (cadr (op:setter op))))
1201          (rtl-c 'VOID expr
1202                 (if (= (length args) 0)
1203                     (list (list 'newval mode "opval"))
1204                     (list (list (car args) 'UINT index)
1205                           (list 'newval mode "opval")))
1206                 #:rtl-cover-fns? #t))
1207        ;else
1208        (send (op:type op) 'gen-set-quiet estate mode index selector
1209              (cx:make-with-atlist mode "opval" (cx:atlist newval))))
1210    (if (op:cond? op)
1211        (string-append "    written |= (1 << "
1212                       (number->string (op:num op))
1213                       ");\n")
1214        "")
1215 ; TRACE_RESULT_<MODE> (cpu, abuf, hwnum, opnum, value);
1216 ; For each insn record array of operand numbers [or indices into
1217 ; operand instance table].
1218 ; Could just scan the operand table for the operand or hardware number,
1219 ; assuming the operand number is stored in `op'.
1220    "    TRACE_RESULT (current_cpu, abuf"
1221    ", " (send op 'gen-pretty-name mode)
1222    ", " (mode:printf-type mode)
1223    ", opval);\n"
1224    "  }\n")
1225 )
1226
1227 (define (/op-gen-set-trace-parallel op estate mode index selector newval)
1228   (string-append
1229    "  {\n"
1230    "    " (mode:c-type mode) " opval = " (cx:c newval) ";\n"
1231    (if (with-generic-write?)
1232        (/op-gen-queued-write op estate mode index selector "opval")
1233        (string-append
1234         (if (op-save-index? op)
1235             (string-append "    "
1236                            /par-operand-macro " (" (/op-index-name op) ")"
1237                            " = " (/gen-hw-index index estate) ";\n")
1238             "")
1239         "    " /par-operand-macro " (" (gen-sym op) ")"
1240         " = opval;\n"))
1241    (if (op:cond? op)
1242        (string-append "    written |= (1 << "
1243                       (number->string (op:num op))
1244                       ");\n")
1245        "")
1246 ; TRACE_RESULT_<MODE> (cpu, abuf, hwnum, opnum, value);
1247 ; For each insn record array of operand numbers [or indices into
1248 ; operand instance table].
1249 ; Could just scan the operand table for the operand or hardware number,
1250 ; assuming the operand number is stored in `op'.
1251    "    TRACE_RESULT (current_cpu, abuf"
1252    ", " (send op 'gen-pretty-name mode)
1253    ", " (mode:printf-type mode)
1254    ", opval);\n"
1255    "  }\n")
1256 )
1257
1258 ; Return C code to set the value of an operand.
1259 ; NEWVAL is a <c-expr> object of the value to store.
1260 ; If INDEX is non-#f use it, otherwise use (op:index self).
1261 ; This special handling of #f for INDEX is *only* supported for operands
1262 ; in cxmake-get, gen-set-quiet, and gen-set-trace.
1263 ; Ditto for SELECTOR.
1264
1265 (method-make!
1266  <operand> 'gen-set-quiet
1267  (lambda (self estate mode index selector newval)
1268    (let ((mode (if (mode:eq? 'DFLT mode)
1269                    (send self 'get-mode)
1270                    mode))
1271          (index (if index index (op:index self)))
1272          (selector (if selector selector (op:selector self))))
1273      ; ??? raw-reg: support wip
1274      (cond ((obj-has-attr? self 'RAW)
1275             (send (op:type self) 'gen-set-quiet-raw estate mode index selector newval))
1276            ((with-parallel-write?)
1277             (/op-gen-set-quiet-parallel self estate mode index selector newval))
1278            (else
1279             (/op-gen-set-quiet self estate mode index selector newval)))))
1280 )
1281
1282 ; Return C code to set the value of an operand and print TRACE_RESULT message.
1283 ; NEWVAL is a <c-expr> object of the value to store.
1284 ; If INDEX is non-#f use it, otherwise use (op:index self).
1285 ; This special handling of #f for INDEX is *only* supported for operands
1286 ; in cxmake-get, gen-set-quiet, and gen-set-trace.
1287 ; Ditto for SELECTOR.
1288
1289 (method-make!
1290  <operand> 'gen-set-trace
1291  (lambda (self estate mode index selector newval)
1292    (let ((mode (if (mode:eq? 'DFLT mode)
1293                    (send self 'get-mode)
1294                    mode))
1295          (index (if index index (op:index self)))
1296          (selector (if selector selector (op:selector self))))
1297      ; ??? raw-reg: support wip
1298      (cond ((obj-has-attr? self 'RAW)
1299             (send (op:type self) 'gen-set-quiet-raw estate mode index selector newval))
1300            ((with-parallel-write?)
1301             (/op-gen-set-trace-parallel self estate mode index selector newval))
1302            (else
1303             (/op-gen-set-trace self estate mode index selector newval)))))
1304 )
1305
1306 ; Define and undefine C macros to tuck away details of instruction format used
1307 ; in the parallel execution functions.  See gen-define-field-macro for a
1308 ; similar thing done for extraction/semantic functions.
1309
1310 (define (gen-define-parallel-operand-macro sfmt)
1311   (string-append "#define " /par-operand-macro "(f) "
1312                  "par_exec->operands."
1313                  (gen-sym sfmt)
1314                  ".f\n")
1315 )
1316
1317 (define (gen-undef-parallel-operand-macro sfmt)
1318   (string-append "#undef " /par-operand-macro "\n")
1319 )
1320 \f
1321 ; Operand profiling and parallel execution support.
1322
1323 (method-make!
1324  <operand> 'save-index?
1325  (lambda (self) (send (op:type self) 'save-index? self))
1326 )
1327
1328 ; Return boolean indicating if operand OP needs its index saved
1329 ; (for parallel write post-processing support).
1330
1331 (define (op-save-index? op)
1332   (send op 'save-index?)
1333 )
1334
1335 ; Return C code to record profile data for modeling use.
1336 ; In the case of a register, this is usually the register's number.
1337 ; This shouldn't be called in the case of a scalar, the code should be
1338 ; smart enough to know there is no need.
1339
1340 (define (op:record-profile op sfmt out?)
1341   (let ((estate (estate-make-for-rtl-c nil nil)))
1342     (send op 'gen-record-profile sfmt out? estate))
1343 )
1344
1345 ; Return C code to record the data needed for profiling operand SELF.
1346 ; This is done during extraction.
1347
1348 (method-make!
1349  <operand> 'gen-record-profile
1350  (lambda (self sfmt out? estate)
1351    (if (hw-scalar? (op:type self))
1352        ""
1353        (string-append "      "
1354                       (gen-argbuf-ref (send self 'sbuf-profile-sym out?))
1355                       " = "
1356                       (send (op:type self) 'gen-record-profile
1357                             (op:index self) sfmt estate)
1358                       ";\n")))
1359 )
1360
1361 ; Return C code to track profiling of operand SELF.
1362 ; This is usually called by the x-after handler.
1363
1364 (method-make!
1365  <operand> 'gen-profile-code
1366  (lambda (self insn out?)
1367    (string-append "  "
1368                   "@cpu@_model_mark_"
1369                   (if out? "set_" "get_")
1370                   (gen-sym (op:type self))
1371                   " (current_cpu"
1372                   (if (hw-scalar? (op:type self))
1373                       ""
1374                       (string-append ", "
1375                                      (gen-argbuf-ref
1376                                       (send self 'sbuf-profile-sym out?))))
1377                   ");\n"))
1378 )
1379 \f
1380 ; CPU, mach, model support.
1381
1382 ; Return the declaration of the cpu/insn enum.
1383
1384 (define (gen-cpu-insn-enum-decl cpu insn-list)
1385   (gen-enum-decl "@prefix@_insn_type"
1386                  "instructions in cpu family @cpu@"
1387                  "@PREFIX@_INSN_"
1388                  (append! (map (lambda (i)
1389                                  (cons (obj:name i)
1390                                        (cons '-
1391                                              (atlist-attrs (obj-atlist i)))))
1392                                insn-list)
1393                           (if (with-parallel?)
1394                               (apply append!
1395                                      (map (lambda (i)
1396                                             (list
1397                                              (cons (symbol-append 'par- (obj:name i))
1398                                                    (cons '-
1399                                                          (atlist-attrs (obj-atlist i))))
1400                                              (cons (symbol-append 'write- (obj:name i))
1401                                                    (cons '-
1402                                                          (atlist-attrs (obj-atlist i))))))
1403                                           (parallel-insns insn-list)))
1404                               nil)
1405                           (list '(-max))))
1406 )
1407
1408 ; Return the enum of INSN in cpu family CPU.
1409 ; In addition to CGEN_INSN_TYPE, an enum is created for each insn in each
1410 ; cpu family.  This collapses the insn enum space for each cpu to increase
1411 ; cache efficiently (since the IDESC table is similarily collapsed).
1412
1413 (define (gen-cpu-insn-enum cpu insn)
1414   (string-upcase (string-append "@PREFIX@_INSN_" (gen-sym insn)))
1415 )
1416
1417 ; Return C code to declare the machine data.
1418
1419 (define (/gen-mach-decls)
1420   (string-append
1421    (string-map (lambda (mach)
1422                  (gen-obj-sanitize mach
1423                                    (string-append "extern const MACH "
1424                                                   (gen-sym mach)
1425                                                   "_mach;\n")))
1426                (current-mach-list))
1427    "\n")
1428 )
1429
1430 ; Return C code to define the machine data.
1431
1432 (define (/gen-mach-data)
1433   (string-append
1434    "const MACH *sim_machs[] =\n{\n"
1435    (string-map (lambda (mach)
1436                  (gen-obj-sanitize
1437                   mach
1438                   (string-append "#ifdef " (gen-have-cpu (mach-cpu mach)) "\n"
1439                                  "  & " (gen-sym mach) "_mach,\n"
1440                                  "#endif\n")))
1441                (current-mach-list))
1442    "  0\n"
1443    "};\n\n"
1444    )
1445 )
1446
1447 ; Return C declarations of cpu model support stuff.
1448 ; ??? This goes in arch.h but a better place is each cpu.h.
1449
1450 (define (/gen-arch-model-decls)
1451   (string-append
1452    (gen-enum-decl 'model_type "model types"
1453                   "MODEL_"
1454                   (append (map (lambda (model)
1455                                  (cons (obj:name model)
1456                                        (cons '-
1457                                              (atlist-attrs (obj-atlist model)))))
1458                                (current-model-list))
1459                           '((max))))
1460    "#define MAX_MODELS ((int) MODEL_MAX)\n\n"
1461    (gen-enum-decl 'unit_type "unit types"
1462                   "UNIT_"
1463                   (cons '(none)
1464                         (append
1465                          ; "apply append" squeezes out nils.
1466                          (apply append
1467                                 ; create <model_name>-<unit-name> for each unit
1468                                 (map (lambda (model)
1469                                        (let ((units (model:units model)))
1470                                          (if (null? units)
1471                                              nil
1472                                              (map (lambda (unit)
1473                                                     (cons (symbol-append (obj:name model) '-
1474                                                                          (obj:name unit))
1475                                                           (cons '- (atlist-attrs (obj-atlist model)))))
1476                                                   units))))
1477                                      (current-model-list)))
1478                          '((max)))))
1479    ; FIXME: revisit MAX_UNITS
1480    "#define MAX_UNITS ("
1481    (number->string
1482     (apply max
1483            (map (lambda (lengths) (apply max lengths))
1484                 (map (lambda (insn)
1485                        (let ((timing (insn-timing insn)))
1486                          (if (null? timing)
1487                              '(1)
1488                              (map (lambda (insn-timing)
1489                                     (if (null? (cdr insn-timing))
1490                                         '1
1491                                         (length (timing:units (cdr insn-timing)))))
1492                                   timing))))
1493                      (current-insn-list)))))
1494    ")\n\n"
1495    )
1496 )
1497 \f
1498 ; Function units.
1499
1500 (method-make! <unit> 'gen-decl (lambda (self) ""))
1501
1502 ; Lookup operand named OP-NAME in INSN.
1503 ; Returns #f if OP-NAME is not an operand of INSN.
1504 ; IN-OUT is 'in to request an input operand, 'out to request an output operand,
1505 ; and 'in-out to request either (though if an operand is used for input and
1506 ; output then the input version is returned).
1507 ; FIXME: Move elsewhere.
1508
1509 (define (insn-op-lookup op-name insn in-out)
1510   (letrec ((lookup (lambda (op-list)
1511                      (cond ((null? op-list) #f)
1512                            ((eq? op-name (op:sem-name (car op-list))) (car op-list))
1513                            (else (lookup (cdr op-list)))))))
1514     (case in-out
1515       ((in) (lookup (sfmt-in-ops (insn-sfmt insn))))
1516       ((out) (lookup (sfmt-out-ops (insn-sfmt insn))))
1517       ((in-out) (or (lookup (sfmt-in-ops (insn-sfmt insn)))
1518                     (lookup (sfmt-out-ops (insn-sfmt insn)))))
1519       (else (error "insn-op-lookup: bad arg:" in-out))))
1520 )
1521
1522 ; Return C code to profile a unit's usage.
1523 ; UNIT-NUM is number of the unit in INSN.
1524 ; OVERRIDES is a list of (name value) pairs, where
1525 ; - NAME is a spec name, one of cycles, pred, in, out.
1526 ;   The only ones we're concerned with are in,out.  They map operand names
1527 ;   as they appear in the semantic code to operand names as they appear in
1528 ;   the function unit spec.
1529 ; - VALUE is the operand to NAME.  For in,out it is (NAME VALUE) where
1530 ;   - NAME is the name of an input/output arg of the unit.
1531 ;   - VALUE is the name of the operand as it appears in semantic code.
1532 ;
1533 ; ??? This is a big sucker, though half of it is just the definitions
1534 ; of utility fns.
1535
1536 (method-make!
1537  <unit> 'gen-profile-code
1538  (lambda (self unit-num insn overrides cycles-var-name)
1539    (let (
1540          (inputs (unit:inputs self))
1541          (outputs (unit:outputs self))
1542
1543           ; Return C code to initialize UNIT-REFERENCED-VAR to be a bit mask
1544           ; of operands of UNIT that were read/written by INSN.
1545           ; INSN-REFERENCED-VAR is a bitmask of operands read/written by INSN.
1546           ; All we have to do is map INSN-REFERENCED-VAR to
1547           ; UNIT-REFERENCED-VAR.
1548           ; ??? For now we assume all input operands are read.
1549           (gen-ref-arg (lambda (arg num in-out)
1550                          (let* ((op-name (assq-ref overrides (car arg)))
1551                                 (op (insn-op-lookup (if op-name
1552                                                         (car op-name)
1553                                                         (car arg))
1554                                                     insn in-out))
1555                                 (insn-referenced-var "insn_referenced")
1556                                 (unit-referenced-var "referenced"))
1557                            (if op
1558                                (if (op:cond? op)
1559                                    (string-append "    "
1560                                                   "if ("
1561                                                   insn-referenced-var
1562                                                   " & (1 << "
1563                                                   (number->string (op:num op))
1564                                                   ")) "
1565                                                   unit-referenced-var
1566                                                   " |= 1 << "
1567                                                   (number->string num)
1568                                                   ";\n")
1569                                    (string-append "    "
1570                                                   unit-referenced-var
1571                                                   " |= 1 << "
1572                                                   (number->string num)
1573                                                   ";\n"))
1574                                ""))))
1575
1576           ; Initialize unit argument ARG.
1577           ; OUT? is #f for input args, #t for output args.
1578           (gen-arg-init (lambda (arg out?)
1579                           (if (or
1580                                ; Ignore scalars.
1581                                (null? (cdr arg))
1582                                ; Ignore remapped arg, handled elsewhere.
1583                                (assq (car arg) overrides)
1584                                ; Ignore operands not in INSN.
1585                                (not (insn-op-lookup (car arg) insn
1586                                                     (if out? 'out 'in))))
1587                               ""
1588                               (let ((sym (gen-profile-sym (gen-c-symbol (car arg))
1589                                                            out?)))
1590                                 (string-append "    "
1591                                                sym
1592                                                " = "
1593                                                (gen-argbuf-ref sym)
1594                                                ";\n")))))
1595
1596           ; Return C code to declare variable to hold unit argument ARG.
1597           ; OUT? is #f for input args, #t for output args.
1598           (gen-arg-decl (lambda (arg out?)
1599                           (if (null? (cdr arg)) ; ignore scalars
1600                               ""
1601                               (string-append "    "
1602                                              (mode:c-type (mode:lookup (cadr arg)))
1603                                              " "
1604                                              (gen-profile-sym (gen-c-symbol (car arg))
1605                                                               out?)
1606                                              " = "
1607                                              (if (null? (cddr arg))
1608                                                  "0"
1609                                                  (number->string (caddr arg)))
1610                                              ";\n"))))
1611
1612           ; Return C code to pass unit argument ARG to the handler.
1613           ; OUT? is #f for input args, #t for output args.
1614           (gen-arg-arg (lambda (arg out?)
1615                          (if (null? (cdr arg)) ; ignore scalars
1616                              ""
1617                              (string-append ", "
1618                                             (gen-profile-sym (gen-c-symbol (car arg))
1619                                                              out?)))))
1620           )
1621
1622      (string-list
1623       "  {\n"
1624       "    int referenced = 0;\n"
1625       "    int UNUSED insn_referenced = abuf->written;\n"
1626       ; Declare variables to hold unit arguments.
1627       (string-map (lambda (arg) (gen-arg-decl arg #f))
1628                   inputs)
1629       (string-map (lambda (arg) (gen-arg-decl arg #t))
1630                   outputs)
1631       ; Initialize 'em, being careful not to initialize an operand that
1632       ; has an override.
1633       (let (; Make a list of names of in/out overrides.
1634             (in-overrides (find-apply cadr
1635                                       (lambda (elm) (eq? (car elm) 'in))
1636                                       overrides))
1637             (out-overrides (find-apply cadr
1638                                       (lambda (elm) (eq? (car elm) 'out))
1639                                       overrides)))
1640         (string-list
1641          (string-map (lambda (arg)
1642                        (if (memq (car arg) in-overrides)
1643                            ""
1644                            (gen-arg-init arg #f)))
1645                      inputs)
1646          (string-map (lambda (arg)
1647                        (if (memq (car arg) out-overrides)
1648                            ""
1649                            (gen-arg-init arg #t)))
1650                      outputs)))
1651       (string-map (lambda (arg)
1652                     (case (car arg)
1653                       ((pred) "")
1654                       ((cycles) "")
1655                       ((in)
1656                        (if (caddr arg)
1657                            (string-append "    "
1658                                           (gen-profile-sym (gen-c-symbol (cadr arg)) #f)
1659                                           " = "
1660                                           (gen-argbuf-ref
1661                                            (gen-profile-sym (gen-c-symbol (caddr arg)) #f))
1662                                           ";\n")
1663                            ""))
1664                       ((out)
1665                        (if (caddr arg)
1666                            (string-append "    "
1667                                           (gen-profile-sym (gen-c-symbol (cadr arg)) #t)
1668                                           " = "
1669                                           (gen-argbuf-ref
1670                                            (gen-profile-sym (gen-c-symbol (caddr arg)) #t))
1671                                           ";\n")
1672                            ""))
1673                       (else
1674                        (parse-error (make-prefix-context "insn function unit spec")
1675                                     "invalid spec" arg))))
1676                   overrides)
1677       ; Create bitmask indicating which args were referenced.
1678       (string-map (lambda (arg num) (gen-ref-arg arg num 'in))
1679                   inputs
1680                   (iota (length inputs)))
1681       (string-map (lambda (arg num) (gen-ref-arg arg num 'out))
1682                   outputs
1683                   (iota (length outputs)
1684                         (length inputs)))
1685       ; Emit the call to the handler.
1686       "    " cycles-var-name " += "
1687       (gen-model-unit-fn-name (unit:model self) self)
1688       " (current_cpu, idesc"
1689       ", " (number->string unit-num)
1690       ", referenced"
1691       (string-map (lambda (arg) (gen-arg-arg arg #f))
1692                   inputs)
1693       (string-map (lambda (arg) (gen-arg-arg arg #t))
1694                   outputs)
1695       ");\n"
1696       "  }\n"
1697       )))
1698 )
1699
1700 ; Return C code to profile an insn-specific unit's usage.
1701 ; UNIT-NUM is number of the unit in INSN.
1702
1703 (method-make!
1704  <iunit> 'gen-profile-code
1705  (lambda (self unit-num insn cycles-var-name)
1706    (let ((args (iunit:args self))
1707          (unit (iunit:unit self)))
1708      (send unit 'gen-profile-code unit-num insn args cycles-var-name)))
1709 )
1710 \f
1711 ; ARGBUF generation.
1712 ; ARGBUF support is put in cpuall.h, which doesn't depend on sim-cpu.scm,
1713 ; so this support is here.
1714
1715 ; Utility of /gen-argbuf-fields-union to generate the definition for
1716 ; <sformat-abuf> SBUF.
1717
1718 (define (/gen-argbuf-elm sbuf)
1719   (logit 2 "Processing sbuf format " (obj:name sbuf) " ...\n")
1720   (string-list
1721    "  struct { /* " (obj:comment sbuf) " */\n"
1722    (let ((elms (sbuf-elms sbuf)))
1723      (if (null? elms)
1724          "    int empty;\n"
1725          (string-list-map (lambda (elm)
1726                             (string-append "    "
1727                                            (cadr elm)
1728                                            " "
1729                                            (car elm)
1730                                            ";\n"))
1731                           (sbuf-elms sbuf))))
1732    "  } " (gen-sym sbuf) ";\n")
1733 )
1734
1735 ; Utility of gen-argbuf-type to generate the union of extracted ifields.
1736
1737 (define (/gen-argbuf-fields-union)
1738   (string-list
1739    "\
1740 /* Instruction argument buffer.  */
1741
1742 union sem_fields {\n"
1743    (string-list-map /gen-argbuf-elm (current-sbuf-list))
1744    "\
1745 #if WITH_SCACHE_PBB
1746   /* Writeback handler.  */
1747   struct {
1748     /* Pointer to argbuf entry for insn whose results need writing back.  */
1749     const struct argbuf *abuf;
1750   } write;
1751   /* x-before handler */
1752   struct {
1753     /*const SCACHE *insns[MAX_PARALLEL_INSNS];*/
1754     int first_p;
1755   } before;
1756   /* x-after handler */
1757   struct {
1758     int empty;
1759   } after;
1760   /* This entry is used to terminate each pbb.  */
1761   struct {
1762     /* Number of insns in pbb.  */
1763     int insn_count;
1764     /* Next pbb to execute.  */
1765     SCACHE *next;
1766     SCACHE *branch_target;
1767   } chain;
1768 #endif
1769 };\n\n"
1770    )
1771 )
1772
1773 ; Generate the definition of the structure that records arguments.
1774 ; This is a union of structures with one structure for each insn format.
1775 ; It also includes hardware profiling information and miscellaneous
1776 ; administrivia.
1777 ; CPU-DATA? is #t if data for the currently selected cpu is to be included.
1778
1779 (define (gen-argbuf-type cpu-data?)
1780   (logit 2 "Generating ARGBUF type ...\n")
1781   (string-list
1782    (if (and cpu-data? (with-scache?))
1783        (/gen-argbuf-fields-union)
1784        "")
1785    (if cpu-data? "" "#ifndef WANT_CPU\n")
1786    "\
1787 /* The ARGBUF struct.  */
1788 struct argbuf {
1789   /* These are the baseclass definitions.  */
1790   IADDR addr;
1791   const IDESC *idesc;
1792   char trace_p;
1793   char profile_p;
1794   /* ??? Temporary hack for skip insns.  */
1795   char skip_count;
1796   char unused;
1797   /* cpu specific data follows */\n"
1798    (if cpu-data?
1799        (if (with-scache?)
1800             "\
1801   union sem semantic;
1802   int written;
1803   union sem_fields fields;\n"
1804             "\
1805   CGEN_INSN_INT insn;
1806   int written;\n")
1807        "")
1808    "};\n"
1809    (if cpu-data? "" "#endif\n")
1810    "\n"
1811    )
1812 )
1813
1814 ; Generate the definition of the structure that records a cached insn.
1815 ; This is cpu family specific (member `argbuf' is) so it is machine generated.
1816 ; CPU-DATA? is #t if data for the currently selected cpu is to be included.
1817
1818 (define (gen-scache-type cpu-data?)
1819   (logit 2 "Generating SCACHE type ...\n")
1820   (string-append
1821    (if cpu-data? "" "#ifndef WANT_CPU\n")
1822    "\
1823 /* A cached insn.
1824
1825    ??? SCACHE used to contain more than just argbuf.  We could delete the
1826    type entirely and always just use ARGBUF, but for future concerns and as
1827    a level of abstraction it is left in.  */
1828
1829 struct scache {
1830   struct argbuf argbuf;\n"
1831    (if (with-generic-write?) "\
1832   int first_insn_p;
1833   int last_insn_p;\n" "")
1834    "};\n"
1835    (if cpu-data? "" "#endif\n")
1836    "\n"
1837   )
1838 )
1839 \f
1840 ; Mode support.
1841
1842 ; Generate a table of mode data.
1843 ; For now all we need is the names.
1844
1845 (define (gen-mode-defs)
1846   (string-append
1847    "const char *mode_names[] = {\n"
1848    (string-map (lambda (m)
1849                  (string-append "  \"" (string-upcase (obj:str-name m)) "\",\n"))
1850                ; We don't treat aliases as being different from the real
1851                ; mode here, so ignore them.
1852                (mode-list-non-alias-values))
1853    "};\n\n"
1854    )
1855 )
1856 \f
1857 ; Insn profiling support.
1858
1859 ; Generate declarations for local variables needed for modelling code.
1860
1861 (method-make!
1862  <insn> 'gen-profile-locals
1863  (lambda (self model)
1864 ;   (let ((cti? (or (has-attr? self 'UNCOND-CTI)
1865 ;                  (has-attr? self 'COND-CTI))))
1866 ;     (string-append
1867 ;      (if cti? "  int UNUSED taken_p = 0;\n" "")
1868 ;      ))
1869    "")
1870 )
1871
1872 ; Generate C code to profile INSN.
1873
1874 (method-make!
1875  <insn> 'gen-profile-code
1876  (lambda (self model cycles-var-name)
1877    (string-list
1878     (let ((timing (assq-ref (insn-timing self) (obj:name model))))
1879       (if timing
1880           (string-list-map (lambda (iunit unit-num)
1881                              (send iunit 'gen-profile-code unit-num self cycles-var-name))
1882                            (timing:units timing)
1883                            (iota (length (timing:units timing))))
1884           (send (model-default-unit model) 'gen-profile-code 0 self nil cycles-var-name)))
1885     ))
1886 )
1887 \f
1888 ; .cpu file loading support
1889
1890 ; Only run sim-analyze-insns! once.
1891 (define /sim-insns-analyzed? #f)
1892
1893 ; List of computed sformat argument buffers.
1894 (define /sim-sformat-abuf-list #f)
1895 (define (current-sbuf-list) /sim-sformat-abuf-list)
1896
1897 ; Called before/after the .cpu file has been read in.
1898
1899 (define (sim-init!)
1900   (set! /sim-insns-analyzed? #f)
1901   (set! /sim-sformat-abuf-list #f)
1902   *UNSPECIFIED*
1903 )
1904
1905 ;; Subroutine of /create-virtual-insns!.
1906 ;; Add virtual insn INSN to the database.
1907 ;; We put virtual insns ahead of normal insns because they're kind of special,
1908 ;; and it helps to see them first in lists.
1909 ;; ORDINAL is a used to place the insn ahead of normal insns;
1910 ;; it is a pair so we can do the update for the next virtual insn here.
1911
1912 (define (/virtual-insn-add! ordinal insn)
1913   (obj-set-ordinal! insn (cdr ordinal))
1914   (current-insn-add! insn)
1915   (set-cdr! ordinal (- (cdr ordinal) 1))
1916 )
1917
1918 ; Create the virtual insns.
1919
1920 (define (/create-virtual-insns!)
1921   (let ((all (all-isas-attr-value))
1922         (context (make-prefix-context "virtual insns"))
1923         ;; Record as a pair so /virtual-insn-add! can update it.
1924         (ordinal (cons #f -1)))
1925
1926     (/virtual-insn-add!
1927      ordinal
1928      (insn-read context
1929                 '(name x-begin)
1930                 '(comment "pbb begin handler")
1931                 `(attrs VIRTUAL PBB (ISA ,all))
1932                 '(syntax "--begin--")
1933                 '(semantics (c-code VOID "\
1934   {
1935 #if WITH_SCACHE_PBB_@PREFIX@
1936 #if defined DEFINE_SWITCH || defined FAST_P
1937     /* In the switch case FAST_P is a constant, allowing several optimizations
1938        in any called inline functions.  */
1939     vpc = @prefix@_pbb_begin (current_cpu, FAST_P);
1940 #else
1941 #if 0 /* cgen engine can't handle dynamic fast/full switching yet.  */
1942     vpc = @prefix@_pbb_begin (current_cpu, STATE_RUN_FAST_P (CPU_STATE (current_cpu)));
1943 #else
1944     vpc = @prefix@_pbb_begin (current_cpu, 0);
1945 #endif
1946 #endif
1947 #endif
1948   }
1949 "))
1950                 ))
1951
1952     (/virtual-insn-add!
1953      ordinal
1954      (insn-read context
1955                 '(name x-chain)
1956                 '(comment "pbb chain handler")
1957                 `(attrs VIRTUAL PBB (ISA ,all))
1958                 '(syntax "--chain--")
1959                 '(semantics (c-code VOID "\
1960   {
1961 #if WITH_SCACHE_PBB_@PREFIX@
1962     vpc = @prefix@_pbb_chain (current_cpu, sem_arg);
1963 #ifdef DEFINE_SWITCH
1964     BREAK (sem);
1965 #endif
1966 #endif
1967   }
1968 "))
1969                 ))
1970
1971     (/virtual-insn-add!
1972      ordinal
1973      (insn-read context
1974                 '(name x-cti-chain)
1975                 '(comment "pbb cti-chain handler")
1976                 `(attrs VIRTUAL PBB (ISA ,all))
1977                 '(syntax "--cti-chain--")
1978                 '(semantics (c-code VOID "\
1979   {
1980 #if WITH_SCACHE_PBB_@PREFIX@
1981 #ifdef DEFINE_SWITCH
1982     vpc = @prefix@_pbb_cti_chain (current_cpu, sem_arg,
1983                                pbb_br_type, pbb_br_npc);
1984     BREAK (sem);
1985 #else
1986     /* FIXME: Allow provision of explicit ifmt spec in insn spec.  */
1987     vpc = @prefix@_pbb_cti_chain (current_cpu, sem_arg,
1988                                CPU_PBB_BR_TYPE (current_cpu),
1989                                CPU_PBB_BR_NPC (current_cpu));
1990 #endif
1991 #endif
1992   }
1993 "))
1994                 ))
1995
1996     (/virtual-insn-add!
1997      ordinal
1998      (insn-read context
1999                 '(name x-before)
2000                 '(comment "pbb begin handler")
2001                 `(attrs VIRTUAL PBB (ISA ,all))
2002                 '(syntax "--before--")
2003                 '(semantics (c-code VOID "\
2004   {
2005 #if WITH_SCACHE_PBB_@PREFIX@
2006     @prefix@_pbb_before (current_cpu, sem_arg);
2007 #endif
2008   }
2009 "))
2010                 ))
2011
2012     (/virtual-insn-add!
2013      ordinal
2014      (insn-read context
2015                 '(name x-after)
2016                 '(comment "pbb after handler")
2017                 `(attrs VIRTUAL PBB (ISA ,all))
2018                 '(syntax "--after--")
2019                 '(semantics (c-code VOID "\
2020   {
2021 #if WITH_SCACHE_PBB_@PREFIX@
2022     @prefix@_pbb_after (current_cpu, sem_arg);
2023 #endif
2024   }
2025 "))
2026                 ))
2027
2028     (/virtual-insn-add!
2029      ordinal
2030      (insn-read context
2031                 '(name x-invalid)
2032                 '(comment "invalid insn handler")
2033                 `(attrs VIRTUAL (ISA ,all))
2034                 '(syntax "--invalid--")
2035                 (list 'semantics (list 'c-code 'VOID (string-append "\
2036   {
2037     /* Update the recorded pc in the cpu state struct.
2038        Only necessary for WITH_SCACHE case, but to avoid the
2039        conditional compilation ....  */
2040     SET_H_PC (pc);
2041     /* Virtual insns have zero size.  Overwrite vpc with address of next insn
2042        using the default-insn-bitsize spec.  When executing insns in parallel
2043        we may want to queue the fault and continue execution.  */
2044     vpc = SEM_NEXT_VPC (sem_arg, pc, " (number->string (bits->bytes (state-default-insn-bitsize))) ");
2045     vpc = sim_engine_invalid_insn (current_cpu, pc, vpc);
2046   }
2047 ")))
2048                 ))
2049     )
2050 )
2051
2052 (define (sim-finish!)
2053   ; Add begin,chain,before,after,invalid handlers if not provided.
2054   ; The code generators should first look for x-foo-@prefix@, then for x-foo.
2055   ; ??? This is good enough for the first pass.  Will eventually need to use
2056   ; less C and more RTL.
2057   (/create-virtual-insns!)
2058
2059   *UNSPECIFIED*
2060 )
2061
2062 ; Called after file is read in and global error checks are done
2063 ; to initialize tables.
2064
2065 (define (sim-analyze!)
2066   *UNSPECIFIED*
2067 )
2068
2069 ; Scan insns, analyzing semantics and computing instruction formats.
2070 ; 'twould be nice to do this in sim-analyze! but it doesn't know whether this
2071 ; needs to be done or not (which is determined by what files are being
2072 ; generated).  Since this is an expensive operation, we defer doing this
2073 ; to the files that need it.
2074
2075 (define (sim-analyze-insns!)
2076   ; This can only be done if one isa and one cpu family is being kept.
2077   (assert-keep-one)
2078
2079   (if (not /sim-insns-analyzed?)
2080
2081       (begin
2082         (arch-analyze-insns! CURRENT-ARCH
2083                              #f ; don't include aliases
2084                              #t) ; do analyze the semantics
2085
2086         ; Compute the set of sformat argument buffers.
2087         (set! /sim-sformat-abuf-list (compute-sformat-argbufs! (current-sfmt-list)))
2088
2089         (set! /sim-insns-analyzed? #t)))
2090
2091   ; Do our own error checking.
2092   (assert (current-insn-lookup 'x-invalid))
2093
2094   *UNSPECIFIED*
2095 )
2096 \f
2097 ; For debugging.
2098
2099 (define (cgen-all-arch)
2100   (string-write
2101    cgen-arch.h
2102    cgen-arch.c
2103    cgen-cpuall.h
2104    ;cgen-mem-ops.h
2105    ;cgen-sem-ops.h
2106    ;cgen-ops.c
2107    )
2108 )
2109
2110 (define (cgen-all-cpu)
2111   (string-write
2112    cgen-cpu.h
2113    cgen-cpu.c
2114    cgen-decode.h
2115    cgen-decode.c
2116    ;cgen-extract.c
2117    cgen-read.c
2118    cgen-write.c
2119    cgen-semantics.c
2120    cgen-sem-switch.c
2121    cgen-model.c
2122    ;cgen-mainloop.in
2123    )
2124 )