OSDN Git Service

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