1 ; CPU family related simulator generator, excluding decoding and model support.
2 ; Copyright (C) 2000, 2001, 2009 Red Hat, Inc.
3 ; This file is part of CGEN.
6 ; - Add support to generate copies of semantic code and perform constant
7 ; folding based on selected mach. This would collapse out untaken branches
8 ; of tests on (current-mach).
10 ; Utilities of cgen-cpu.h.
12 ; Print various parameters of the cpu family.
13 ; A "cpu family" here is a collection of variants of a particular architecture
14 ; that share sufficient commonality that they can be handled together.
16 (define (/gen-cpu-defines)
19 /* Maximum number of instructions that are fetched at a time.
20 This is for LIW type instructions sets (e.g. m32r). */
21 #define MAX_LIW_INSNS " (number->string (state-liw-insns))
24 /* Maximum number of instructions that can be executed in parallel. */
25 #define MAX_PARALLEL_INSNS " (number->string (state-parallel-insns))
27 ; (gen-enum-decl '@cpu@_virtual
28 ; "@cpu@ virtual insns"
29 ; "@ARCH@_INSN_" ; not @CPU@ to match CGEN_INSN_TYPE in opc.h
31 ; (x-before -1) (x-after -2)
32 ; (x-begin -3) (x-chain -4) (x-cti-chain -5)))
36 ; Return a boolean indicating if hardware element HW needs storage allocated
37 ; for it in the SIM_CPU struct.
39 (define (hw-need-storage? hw)
40 (and (register? hw) (not (obj-has-attr? hw 'VIRTUAL)))
43 ; Subroutine of /gen-hardware-types to generate the struct containing
44 ; hardware elements of one isa.
46 (define (/gen-hardware-struct hw-list)
48 ; If struct is empty, leave it out to simplify generated code.
50 (string-list-map (lambda (hw)
55 (send hw 'gen-get-macro)
56 (send hw 'gen-set-macro)))))
57 (find hw-need-storage? hw-list)))
60 ; Return C type declarations of all of the hardware elements.
61 ; The name of the type is prepended with the cpu family name.
63 (define (/gen-hardware-types)
65 "/* CPU state information. */\n"
67 " /* Hardware elements. */\n"
71 (or (not (with-multiple-isa?))
73 (current-keep-isa-name-list)
74 (obj-attr-value hw 'ISA))
79 "#define CPU_CGEN_HW(cpu) (& (cpu)->cpu_data.hardware)\n"
80 ;" /* CPU profiling state information. */\n"
82 ;(string-list-map (lambda (hw) (send hw 'gen-profile-decl))
83 ; (find hw-profilable? (current-hw-list)))
85 ;"#define CPU_CGEN_PROFILE(cpu) (& (cpu)->cpu_data.profile)\n"
86 "} @CPU@_CPU_DATA;\n\n"
87 ; If there are any virtual regs, output get/set macros for them.
88 (let ((virtual-regs (find (lambda (hw)
90 (obj-has-attr? hw 'VIRTUAL)))
92 (orig-with-parallel? (with-parallel?))
94 (set-with-parallel?! #f)
95 (if (not (null? virtual-regs))
98 "/* Virtual regs. */\n\n"
99 (string-list-map (lambda (hw)
100 (logit 3 "Generating get/set for " (obj:name hw)
104 (send hw 'gen-get-macro)
105 (send hw 'gen-set-macro))))
109 (set-with-parallel?! orig-with-parallel?)
114 ; Return the declaration of register access functions.
116 (define (/gen-cpu-reg-access-decls)
118 "/* Cover fns for register access. */\n"
119 (string-list-map (lambda (hw)
120 (gen-reg-access-decl hw
124 (find register? (current-hw-list)))
126 "/* These must be hand-written. */\n"
127 "extern CPUREG_FETCH_FN @cpu@_fetch_register;\n"
128 "extern CPUREG_STORE_FN @cpu@_store_register;\n"
132 ; Generate type of struct holding model state while executing.
134 (define (/gen-model-decls)
135 (logit 2 "Generating model decls ...\n")
141 (if (null? (model:state model))
142 " int empty;\n" ; ensure struct isn't empty so it compiles
143 (string-map (lambda (var)
145 (mode:c-type (mode:lookup (cadr var)))
147 (gen-c-symbol (car var))
149 (model:state model)))
150 "} MODEL_" (string-upcase (gen-sym model)) "_DATA;\n\n"
152 (current-model-list))
156 ; Utility of /gen-extract-macros to generate a macro to define the local
157 ; vars to contain extracted field values and the code to assign them
158 ; for <iformat> IFMT.
160 (define (/gen-extract-ifmt-macro ifmt)
161 (logit 2 "Processing format " (obj:name ifmt) " ...\n")
163 (gen-define-ifmt-ifields ifmt "" #t #f)
164 (gen-extract-ifmt-ifields ifmt "" #t #f)
165 ; We don't need an extra blank line here as gen-extract-ifields adds one.
169 ; Generate macros to extract instruction fields.
171 (define (/gen-extract-macros)
172 (logit 2 "Generating extraction macros ...\n")
175 /* Macros to simplify extraction, reading and semantic code.
176 These define and assign the local vars that contain the insn's fields. */
178 (string-list-map /gen-extract-ifmt-macro (current-ifmt-list))
182 ; Utility of /gen-parallel-exec-type to generate the definition of one
183 ; structure in PAREXEC.
184 ; SFMT is an <sformat> object.
186 (define (/gen-parallel-exec-elm sfmt)
188 " struct { /* " (obj:comment sfmt) " */\n"
190 ((if (with-parallel-write?) sfmt-out-ops sfmt-in-ops) sfmt)))
192 " int empty;\n" ; ensure struct isn't empty so it compiles
195 (logit 2 "Processing operand " (obj:name op) " of format "
196 (obj:name sfmt) " ...\n")
197 (if (with-parallel-write?)
198 (let ((index-type (and (op-save-index? op)
199 (gen-index-type op sfmt))))
200 (string-append " " (gen-type op)
201 " " (gen-sym op) ";\n"
203 (string-append " " index-type
204 " " (gen-sym op) "_idx;\n")
212 " } " (gen-sym sfmt) ";\n"
216 ; Generate the definition of the structure that holds register values, etc.
217 ; for use during parallel execution. When instructions are executed parallelly
219 ; - their inputs are read before their outputs are written. Thus we have to
220 ; fetch the input values of several instructions before executing any of them.
221 ; - or their outputs are queued here first and then written out after all insns
223 ; The fetched/queued values are stored in an array of PAREXEC structs, one
224 ; element per instruction.
226 (define (/gen-parallel-exec-type)
227 (logit 2 "Generating PAREXEC type ...\n")
229 (if (with-parallel-write?)
230 "/* Queued output values of an instruction. */\n"
231 "/* Fetched input values of an instruction. */\n")
236 (string-map /gen-parallel-exec-elm (current-sfmt-list))
239 /* For conditionally written operands, bitmask of which ones were. */
245 ; Generate the TRACE_RECORD struct definition.
246 ; This struct will hold all necessary data for doing tracing and profiling
247 ; (e.g. register numbers). The goal is to remove all tracing code from the
248 ; semantic code. Then the fast/full distinction needn't use conditionals to
249 ; discard/include the tracing/profiling code.
251 (define (/gen-trace-record-type)
254 /* Collection of various things for the trace handler to use. */
256 typedef struct trace_record {
264 ; Utilities of cgen-cpu.c
266 ; Get/set fns for every register.
268 (define (/gen-cpu-reg-access-defns)
271 (let ((scalar? (hw-scalar? hw))
273 (getter (hw-getter hw))
274 (setter (hw-setter hw)))
275 (gen-reg-access-defn hw
282 (string-upcase (gen-c-symbol name))
284 (if scalar? "" "regno")
289 (if scalar? "" "[regno]")
294 (string-upcase (gen-c-symbol name))
296 (if scalar? "" "regno, ")
301 (if scalar? "" "[regno]")
303 (find (lambda (hw) (register? hw))
307 ; Generate a function to record trace results in a trace record.
309 (define (/gen-cpu-record-results)
312 /* Record trace results for INSN. */
315 @cpu@_record_trace_results (SIM_CPU *current_cpu, CGEN_INSN *insn,
316 int *indices, TRACE_RECORD *tr)
322 ; Utilities of cgen-read.c.
323 ; Parallel-read support is not currently used by any port and this code
324 ; has been left to bitrot. Don't delete it just yet.
326 ; Return C code to fetch and save all input operands to instructions with
329 (define (/gen-read-args sfmt)
330 (string-map (lambda (op) (op:read op sfmt))
334 ; Utility of /gen-read-switch to generate a switch case for <sformat> SFMT.
336 (define (/gen-read-case sfmt)
337 (logit 2 "Processing read switch case for \"" (obj:name sfmt) "\" ...\n")
339 " CASE (read, READ_" (string-upcase (gen-sym sfmt)) ") : "
340 "/* " (obj:comment sfmt) " */\n"
342 (gen-define-field-macro (if (with-scache?) sfmt #f))
343 (gen-define-parallel-operand-macro sfmt)
344 (gen-define-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) " " #f)
345 (gen-extract-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) " " #f)
346 (/gen-read-args sfmt)
347 (gen-undef-parallel-operand-macro sfmt)
348 (gen-undef-field-macro sfmt)
354 ; Generate the guts of a C switch statement to read insn operands.
355 ; The switch is based on instruction formats.
357 (define (/gen-read-switch)
358 (logit 2 "Processing readers ...\n")
359 (string-write-map /gen-read-case (current-sfmt-list))
362 ; Utilities of cgen-write.c.
364 ; This is the other way of implementing parallel execution support.
365 ; Instead of fetching all the input operands first, write all the output
366 ; operands and their addresses to holding variables, and then run a
367 ; post-processing pass to update the cpu state.
369 ; There are separate implementations for semantics as functions and semantics
370 ; as one big switch. For the function case we create a function that is a
371 ; switch on each semantic format and loops writing each insn's results back.
372 ; For the switch case we add cases to the switch to handle the write back,
373 ; and it is up to the pbb compiler to include them in the generated "code".
375 ; Return C code to fetch and save all output operands to instructions with
378 (define (/gen-write-args sfmt)
379 (string-map (lambda (op) (op:write op sfmt))
383 ; Utility of gen-write-switch to generate a switch case for <sformat> SFMT.
384 ; If INSN is non-#f, it is the <insn> object of the insn in which case
385 ; the case is named after the insn not the format. This is done because
386 ; current sem-switch support emits one handler per insn instead of per sfmt.
388 (define (/gen-write-case sfmt insn)
389 (logit 2 "Processing write switch case for \"" (obj:name sfmt) "\" ...\n")
393 "CASE (sem, INSN_WRITE_"
394 (string-upcase (gen-sym insn)) ") : ")
397 (string-upcase (gen-sym sfmt)) " : "))
400 (string-list (insn-syntax insn))
407 " SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);\n"
409 " const ARGBUF *abuf = SEM_ARGBUF (sem_arg)->fields.write.abuf;\n")
411 (gen-define-field-macro (if (with-scache?) sfmt #f))
412 (gen-define-parallel-operand-macro sfmt)
414 " int UNUSED written = abuf->written;\n"
415 ;(gen-define-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) " " #f) - used by cgen-read.c
416 ;(gen-extract-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) " " #f) - used by cgen-read.c
418 (string-list /indent " IADDR UNUSED pc = abuf->addr;\n")
420 (if (and insn (insn-cti? insn))
422 " SEM_BRANCH_INIT\n") ; no trailing `;' on purpose
425 (string-list /indent " vpc = SEM_NEXT_VPC (sem_arg, pc, 0);\n")
429 (/gen-write-args sfmt)
432 (if (and insn (insn-cti? insn))
433 (string-list /indent " SEM_BRANCH_FINI (vpc);\n")
435 (gen-undef-parallel-operand-macro sfmt)
436 (gen-undef-field-macro sfmt)
439 (string-list /indent " NEXT (vpc);\n")
440 (string-list /indent " break;\n"))
445 ; Generate the guts of a C switch statement to write insn operands.
446 ; The switch is based on instruction formats.
447 ; ??? This will generate cases for formats that don't need it.
448 ; E.g. on the m32r all 32 bit insns can't be executed in parallel.
449 ; It's easier to generate the code anyway so we do.
451 (define (/gen-write-switch)
452 (logit 2 "Processing writers ...\n")
453 (string-write-map (lambda (sfmt)
454 (/gen-write-case sfmt #f))
458 ; Utilities of cgen-semantics.c.
460 ; Return name of semantic fn for INSN.
462 (define (/gen-sem-fn-name insn)
463 ;(string-append "sem_" (gen-sym insn))
467 ; Return semantic fn table entry for INSN.
469 (define (/gen-sem-fn-table-entry insn)
473 (string-upcase (gen-sym insn))
475 "SEM_FN_NAME (@prefix@," (/gen-sem-fn-name insn) ")"
480 ; Return C code to define a table of all semantic fns and a function to
481 ; add the info to the insn descriptor table.
483 (define (/gen-semantic-fn-table)
486 /* Table of all semantic fns. */
488 static const struct sem_fn_desc sem_fns[] = {\n"
491 (string-write-map /gen-sem-fn-table-entry
492 (non-alias-insns (current-insn-list))))
498 /* Add the semantic fns to IDESC_TABLE. */
501 SEM_FN_NAME (@prefix@,init_idesc_table) (SIM_CPU *current_cpu)
503 IDESC *idesc_table = CPU_IDESC (current_cpu);
504 const struct sem_fn_desc *sf;
505 int mach_num = MACH_NUM (CPU_MACH (current_cpu));
507 for (sf = &sem_fns[0]; sf->fn != 0; ++sf)
509 const CGEN_INSN *insn = idesc_table[sf->index].idata;
510 int valid_p = (CGEN_INSN_VIRTUAL_P (insn)
511 || CGEN_INSN_MACH_HAS_P (insn, mach_num));
514 idesc_table[sf->index].sem_fast = sf->fn;
516 idesc_table[sf->index].sem_fast = SEM_FN_NAME (@prefix@,x_invalid);
519 idesc_table[sf->index].sem_full = sf->fn;
521 idesc_table[sf->index].sem_full = SEM_FN_NAME (@prefix@,x_invalid);
529 ; Return C code to perform the semantics of INSN.
531 (define (gen-semantic-code insn)
533 (if (and (insn-real? insn)
534 (isa-setup-semantics (current-isa)))
537 (rtl-c VOID (obj-isa-list insn) nil
538 (isa-setup-semantics (current-isa))
545 ; Indicate generating code for INSN.
546 ; Use the compiled form if available.
547 ; The case when they're not available is for virtual insns. xxx Still true?
548 (cond ((insn-compiled-semantics insn)
550 (rtl-c-parsed VOID sem
554 ((insn-canonical-semantics insn)
556 (rtl-c-parsed VOID sem
561 (context-error (make-obj-context insn #f)
562 "While generating semantic code"
563 "semantics of insn are not canonicalized"))))
566 ; Return definition of C function to perform INSN.
567 ; This version handles the with-scache case.
569 (define (/gen-scache-semantic-fn insn)
570 (logit 2 "Processing semantics for " (obj:name insn) ": \"" (insn-syntax insn) "\" ...\n")
571 (set! /with-profile? /with-profile-fn?)
572 (let ((profile? (and (with-profile?)
573 (not (obj-has-attr? insn 'VIRTUAL))))
574 (parallel? (with-parallel?))
575 (cti? (insn-cti? insn))
576 (insn-len (insn-length-bytes insn)))
578 "/* " (obj:str-name insn) ": " (insn-syntax insn) " */\n\n"
580 "SEM_FN_NAME (@prefix@," (gen-sym insn) ")"
581 (if (and parallel? (not (with-generic-write?)))
582 " (SIM_CPU *current_cpu, SEM_ARG sem_arg, PAREXEC *par_exec)\n"
583 " (SIM_CPU *current_cpu, SEM_ARG sem_arg)\n")
585 (gen-define-field-macro (insn-sfmt insn))
586 (if (and parallel? (not (with-generic-write?)))
587 (gen-define-parallel-operand-macro (insn-sfmt insn))
589 " ARGBUF *abuf = SEM_ARGBUF (sem_arg);\n"
590 ; Unconditionally written operands are not recorded here.
591 " int UNUSED written = 0;\n"
592 ; The address of this insn, needed by extraction and semantic code.
593 ; Note that the address recorded in the cpu state struct is not used.
594 ; For faster engines that copy will be out of date.
595 " IADDR UNUSED pc = abuf->addr;\n"
596 (if (and cti? (not parallel?))
597 " SEM_BRANCH_INIT\n" ; no trailing `;' on purpose
599 (string-list " SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, "
600 (number->string insn-len)
603 (gen-semantic-code insn) "\n"
604 ; Only update what's been written if some are conditionally written.
605 ; Otherwise we know they're all written so there's no point in
607 (if (/any-cond-written? (insn-sfmt insn))
608 " abuf->written = written;\n"
610 (if (and cti? (not parallel?))
611 " SEM_BRANCH_FINI (vpc);\n"
614 (if (and parallel? (not (with-generic-write?)))
615 (gen-undef-parallel-operand-macro (insn-sfmt insn))
617 (gen-undef-field-macro (insn-sfmt insn))
622 ; Return definition of C function to perform INSN.
623 ; This version handles the without-scache case.
624 ; ??? TODO: multiword insns.
626 (define (/gen-no-scache-semantic-fn insn)
627 (logit 2 "Processing semantics for " (obj:name insn) ": \"" (insn-syntax insn) "\" ...\n")
628 (set! /with-profile? /with-profile-fn?)
629 (let ((profile? (and (with-profile?)
630 (not (obj-has-attr? insn 'VIRTUAL))))
631 (parallel? (with-parallel?))
632 (cti? (insn-cti? insn))
633 (insn-len (insn-length-bytes insn)))
635 "/* " (obj:str-name insn) ": " (insn-syntax insn) " */\n\n"
636 "static SEM_STATUS\n"
637 "SEM_FN_NAME (@prefix@," (gen-sym insn) ")"
638 (if (and parallel? (not (with-generic-write?)))
639 " (SIM_CPU *current_cpu, SEM_ARG sem_arg, PAREXEC *par_exec, CGEN_INSN_INT insn)\n"
640 " (SIM_CPU *current_cpu, SEM_ARG sem_arg, CGEN_INSN_INT insn)\n")
642 (if (and parallel? (not (with-generic-write?)))
643 (gen-define-parallel-operand-macro (insn-sfmt insn))
645 " SEM_STATUS status = 0;\n" ; ??? wip
646 " ARGBUF *abuf = SEM_ARGBUF (sem_arg);\n"
647 (gen-define-field-macro (if (with-scache?) (insn-sfmt insn) #f))
648 ; Unconditionally written operands are not recorded here.
649 " int UNUSED written = 0;\n"
650 " IADDR UNUSED pc = GET_H_PC ();\n"
651 (if (and cti? (not parallel?))
652 " SEM_BRANCH_INIT\n" ; no trailing `;' on purpose
654 (string-list " SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, "
655 (number->string insn-len)
657 (string-list (gen-define-ifmt-ifields (insn-ifmt insn) " " #f #t)
658 (gen-sfmt-op-argbuf-defns (insn-sfmt insn))
659 (gen-extract-ifmt-ifields (insn-ifmt insn) " " #f #t)
660 (gen-sfmt-op-argbuf-assigns (insn-sfmt insn)))
662 (gen-semantic-code insn) "\n"
663 ; Only update what's been written if some are conditionally written.
664 ; Otherwise we know they're all written so there's no point in
666 (if (/any-cond-written? (insn-sfmt insn))
667 " abuf->written = written;\n"
669 ; SEM_{,N}BRANCH_FINI are user-supplied macros.
673 " SEM_BRANCH_FINI (vpc, "
674 " SEM_NBRANCH_FINI (vpc, ")
675 (gen-bool-attrs (obj-atlist insn) gen-attr-mask)
678 (gen-undef-field-macro (insn-sfmt insn))
680 (if (and parallel? (not (with-generic-write?)))
681 (gen-undef-parallel-operand-macro (insn-sfmt insn))
687 (define (/gen-all-semantic-fns)
688 (logit 2 "Processing semantics ...\n")
689 (let ((insns (non-alias-insns (current-insn-list))))
691 (string-write-map /gen-scache-semantic-fn insns)
692 (string-write-map /gen-no-scache-semantic-fn insns)))
695 ; Utility of /gen-sem-case to return the mask of operands always written
696 ; to in <sformat> SFMT.
697 ; ??? Not currently used.
699 (define (/uncond-written-mask sfmt)
700 (apply + (map (lambda (op)
703 (logsll 1 (op:num op))))
704 (sfmt-out-ops sfmt)))
707 ; Utility of /gen-sem-case to return #t if any operand in <sformat> SFMT is
708 ; conditionally written to.
710 (define (/any-cond-written? sfmt)
711 (any-true? (map op:cond? (sfmt-out-ops sfmt)))
714 ; Generate a switch case to perform INSN.
716 (define (/gen-sem-case insn parallel?)
717 (logit 2 "Processing "
718 (if parallel? "parallel " "")
719 "semantic switch case for " (obj:name insn) ": \""
720 (insn-syntax insn) "\" ...\n")
721 (set! /with-profile? /with-profile-sw?)
722 (let ((cti? (insn-cti? insn))
723 (insn-len (insn-length-bytes insn)))
725 ; INSN_ is prepended here and not elsewhere to avoid name collisions
726 ; with symbols like AND, etc.
729 (if parallel? "PAR_" "")
730 (string-upcase (gen-sym insn)) ") : "
731 "/* " (insn-syntax insn) " */\n"
733 " SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);\n"
734 " ARGBUF *abuf = SEM_ARGBUF (sem_arg);\n"
735 (gen-define-field-macro (if (with-scache?) (insn-sfmt insn) #f))
736 (if (and parallel? (not (with-generic-write?)))
737 (gen-define-parallel-operand-macro (insn-sfmt insn))
739 ; Unconditionally written operands are not recorded here.
740 " int UNUSED written = 0;\n"
741 ; The address of this insn, needed by extraction and semantic code.
742 ; Note that the address recorded in the cpu state struct is not used.
743 " IADDR UNUSED pc = abuf->addr;\n"
744 (if (and cti? (not parallel?))
745 " SEM_BRANCH_INIT\n" ; no trailing `;' on purpose
749 (string-list (gen-define-ifmt-ifields (insn-ifmt insn) " " #f #t)
750 (gen-extract-ifmt-ifields (insn-ifmt insn) " " #f #t)
752 (string-list " vpc = SEM_NEXT_VPC (sem_arg, pc, "
753 (number->string insn-len)
756 (gen-semantic-code insn) "\n"
757 ; Only update what's been written if some are conditionally written.
758 ; Otherwise we know they're all written so there's no point in
760 (if (/any-cond-written? (insn-sfmt insn))
761 " abuf->written = written;\n"
763 (if (and cti? (not parallel?))
764 " SEM_BRANCH_FINI (vpc);\n"
766 (if (and parallel? (not (with-generic-write?)))
767 (gen-undef-parallel-operand-macro (insn-sfmt insn))
769 (gen-undef-field-macro (insn-sfmt insn))
775 (define (/gen-sem-switch)
776 (logit 2 "Processing semantic switch ...\n")
777 ; Turn parallel execution support off.
778 (let ((orig-with-parallel? (with-parallel?)))
779 (set-with-parallel?! #f)
781 (string-write-map (lambda (insn) (/gen-sem-case insn #f))
782 (non-alias-insns (current-insn-list)))))
783 (set-with-parallel?! orig-with-parallel?)
787 ; Generate the guts of a C switch statement to execute parallel instructions.
788 ; This switch is included after the non-parallel instructions in the semantic
791 ; ??? We duplicate the writeback case for each insn, even though we only need
792 ; one case per insn format. The former keeps the code for each insn
793 ; together and might improve cache usage. On the other hand the latter
794 ; reduces the amount of code, though it is believed that in this particular
795 ; instance the win isn't big enough.
797 (define (/gen-parallel-sem-switch)
798 (logit 2 "Processing parallel insn semantic switch ...\n")
799 ; Turn parallel execution support on.
800 (let ((orig-with-parallel? (with-parallel?)))
801 (set-with-parallel?! #t)
803 (string-write-map (lambda (insn)
804 (string-list (/gen-sem-case insn #t)
805 (/gen-write-case (insn-sfmt insn) insn)))
806 (parallel-insns (current-insn-list)))))
807 (set-with-parallel?! orig-with-parallel?)
811 ; Top level file generators.
813 ; Generate cpu-<cpu>.h
816 (logit 1 "Generating " (gen-cpu-name) "'s cpu.h ...\n")
820 ; Turn parallel execution support on if cpu needs it.
821 (set-with-parallel?! (state-parallel-exec?))
823 ; Tell the rtl->c translator we're not the simulator.
824 ; ??? Minimizes changes in generated code until this is changed.
825 ; RTL->C happens for field decoding.
826 (rtl-c-config! #:rtl-cover-fns? #f)
829 (gen-c-copyright "CPU family header for @cpu@."
830 CURRENT-COPYRIGHT CURRENT-PACKAGE)
838 /gen-cpu-reg-access-decls
841 (if (not (with-multiple-isa?))
843 (lambda () (gen-argbuf-type #t))
844 (lambda () (gen-scache-type #t))
848 (if (and (with-parallel?) (not (with-generic-write?)))
849 /gen-parallel-exec-type
851 /gen-trace-record-type
852 "#endif /* CPU_@CPU@_H */\n"
856 ; Generate defs-<isa>.h.
858 (define (cgen-defs.h)
859 (logit 1 "Generating " (obj:name (current-isa)) "'s defs.h ...\n")
863 ; Tell the rtl->c translator we're not the simulator.
864 ; ??? Minimizes changes in generated code until this is changed.
865 ; RTL->C happens for field decoding.
866 (rtl-c-config! #:rtl-cover-fns? #f)
869 (gen-c-copyright (string-append
870 "ISA definitions header for "
871 (obj:str-name (current-isa))
873 CURRENT-COPYRIGHT CURRENT-PACKAGE)
875 #ifndef DEFS_@PREFIX@_H
876 #define DEFS_@PREFIX@_H
879 (lambda () (gen-argbuf-type #t))
880 (lambda () (gen-scache-type #t))
883 "#endif /* DEFS_@PREFIX@_H */\n"
887 ; Generate cpu-<cpu>.c
890 (logit 1 "Generating " (gen-cpu-name) "'s cpu.c ...\n")
894 ; Turn parallel execution support on if cpu needs it.
895 (set-with-parallel?! (state-parallel-exec?))
897 ; Initialize rtl generation.
898 (rtl-c-config! #:rtl-cover-fns? #t)
901 (gen-c-copyright "Misc. support for CPU family @cpu@."
902 CURRENT-COPYRIGHT CURRENT-PACKAGE)
904 #define WANT_CPU @cpu@
905 #define WANT_CPU_@CPU@
907 #include \"sim-main.h\"
908 #include \"cgen-ops.h\"
911 /gen-cpu-reg-access-defns
912 /gen-cpu-record-results
918 (define (cgen-read.c)
919 (logit 1 "Generating " (gen-cpu-name) "'s read.c ...\n")
923 ; Turn parallel execution support off.
924 (set-with-parallel?! #f)
926 ; Tell the rtx->c translator we are the simulator.
927 (rtl-c-config! #:rtl-cover-fns? #t)
930 (gen-c-copyright (string-append "Simulator instruction operand reader for "
931 (symbol->string (current-arch-name)) ".")
932 CURRENT-COPYRIGHT CURRENT-PACKAGE)
936 /* The labels have the case they have because the enum of insn types
937 is all uppercase and in the non-stdc case the fmt symbol is built
938 into the enum name. */
946 (string-write-map (lambda (insn)
949 (string-upcase (gen-sym insn))
950 ", && case_read_READ_"
951 (string-upcase (gen-sym (insn-sfmt insn)))
953 (non-alias-insns (current-insn-list))))
959 for (i = 0; labels[i].label != 0; ++i)
960 CPU_IDESC (current_cpu) [labels[i].index].read = labels[i].label;
963 #endif /* DEFINE_LABELS */
970 SEM_ARG sem_arg = sc;
971 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
973 SWITCH (read, sem_arg->read)\n"
975 SWITCH (read, decode->read)\n")
985 ENDSWITCH (read) /* End of read switch. */
989 #endif /* DEFINE_SWITCH */
996 (define (cgen-write.c)
997 (logit 1 "Generating " (gen-cpu-name) "'s write.c ...\n")
1001 ; Turn parallel execution support off.
1002 (set-with-parallel?! #f)
1004 ; Tell the rtx->c translator we are the simulator.
1005 (rtl-c-config! #:rtl-cover-fns? #t)
1008 (gen-c-copyright (string-append "Simulator instruction operand writer for "
1009 (symbol->string (current-arch-name)) ".")
1010 CURRENT-COPYRIGHT CURRENT-PACKAGE)
1012 /* Write cached results of 1 or more insns executed in parallel. */
1015 @cpu@_parallel_write (SIM_CPU *cpu, SCACHE *sbufs, PAREXEC *pbufs, int ninsns)
1019 SEM_ARG sem_arg = sc;
1020 ARGBUF *abuf = SEM_ARGBUF (sem_arg);\n"
1026 ARGBUF *abuf = SEM_ARGBUF (sbufs);
1028 switch (abuf->idesc->write)
1039 while (--ninsns > 0);
1045 ; Generate semantics.c
1046 ; Each instruction is implemented in its own function.
1048 (define (cgen-semantics.c)
1049 (logit 1 "Generating " (gen-cpu-name) "'s semantics.c ...\n")
1051 (sim-analyze-insns!)
1053 ; Turn parallel execution support on if cpu needs it.
1054 (set-with-parallel?! (state-parallel-exec?))
1056 ; Tell the rtx->c translator we are the simulator.
1057 (rtl-c-config! #:rtl-cover-fns? #t)
1060 (gen-c-copyright "Simulator instruction semantics for @cpu@."
1061 CURRENT-COPYRIGHT CURRENT-PACKAGE)
1063 #define WANT_CPU @cpu@
1064 #define WANT_CPU_@CPU@
1066 #include \"sim-main.h\"
1067 #include \"cgen-mem.h\"
1068 #include \"cgen-ops.h\"
1072 (gen-define-with-symcat "GET_ATTR(cpu, num, attr) \
1073 CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_" "attr)")
1075 /* This is used so that we can compile two copies of the semantic code,
1076 one with full feature support and one without that runs fast(er).
1077 FAST_P, when desired, is defined on the command line, -DFAST_P=1. */
1079 #define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_semf_,fn)
1081 #define TRACE_RESULT(cpu, abuf, name, type, val)
1083 #define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_sem_,fn)
1087 /gen-all-semantic-fns
1088 ; Put the table at the end so we don't have to declare all the sem fns.
1089 /gen-semantic-fn-table
1093 ; Generate sem-switch.c.
1094 ; Each instruction is a case in a switch().
1095 ; This file consists of just the switch(). It is included by mainloop.c.
1097 (define (cgen-sem-switch.c)
1098 (logit 1 "Generating " (gen-cpu-name) "'s sem-switch.c ...\n")
1100 (sim-analyze-insns!)
1102 ; Turn parallel execution support off.
1103 ; It is later turned on/off when generating the actual semantic code.
1104 (set-with-parallel?! #f)
1106 ; Tell the rtx->c translator we are the simulator.
1107 (rtl-c-config! #:rtl-cover-fns? #t)
1110 (gen-c-copyright "Simulator instruction semantics for @cpu@."
1111 CURRENT-COPYRIGHT CURRENT-PACKAGE)
1114 #ifdef DEFINE_LABELS
1116 /* The labels have the case they have because the enum of insn types
1117 is all uppercase and in the non-stdc case the insn symbol is built
1118 into the enum name. */
1126 (string-write-map (lambda (insn)
1127 (string-append " { "
1129 (string-upcase (gen-sym insn))
1130 ", && case_sem_INSN_"
1131 (string-upcase (gen-sym insn))
1133 (non-alias-insns (current-insn-list))))
1135 (if (state-parallel-exec?)
1137 (string-write-map (lambda (insn)
1138 (string-append " { "
1140 (string-upcase (gen-sym insn))
1141 ", && case_sem_INSN_PAR_"
1142 (string-upcase (gen-sym insn))
1146 (string-upcase (gen-sym insn))
1147 ", && case_sem_INSN_WRITE_"
1148 (string-upcase (gen-sym insn))
1150 (parallel-insns (current-insn-list))))
1157 for (i = 0; labels[i].label != 0; ++i)
1160 CPU_IDESC (current_cpu) [labels[i].index].sem_fast_lab = labels[i].label;
1162 CPU_IDESC (current_cpu) [labels[i].index].sem_full_lab = labels[i].label;
1166 #undef DEFINE_LABELS
1167 #endif /* DEFINE_LABELS */
1169 #ifdef DEFINE_SWITCH
1171 /* If hyper-fast [well not unnecessarily slow] execution is selected, turn
1172 off frills like tracing and profiling. */
1173 /* FIXME: A better way would be to have TRACE_RESULT check for something
1174 that can cause it to be optimized out. Another way would be to emit
1175 special handlers into the instruction \"stream\". */
1179 #define TRACE_RESULT(cpu, abuf, name, type, val)
1184 (gen-define-with-symcat "GET_ATTR(cpu, num, attr) \
1185 CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_" "attr)")
1191 /* Branch to next handler without going around main loop. */
1192 #define NEXT(vpc) goto * SEM_ARGBUF (vpc) -> semantic.sem_case
1193 SWITCH (sem, SEM_ARGBUF (vpc) -> semantic.sem_case)
1195 #else /* ! WITH_SCACHE_PBB */
1197 #define NEXT(vpc) BREAK (sem)
1200 SWITCH (sem, SEM_ARGBUF (sc) -> idesc->sem_fast_lab)
1202 SWITCH (sem, SEM_ARGBUF (sc) -> idesc->sem_full_lab)
1205 SWITCH (sem, SEM_ARGBUF (sc) -> idesc->num)
1208 #endif /* ! WITH_SCACHE_PBB */
1216 (if (state-parallel-exec?)
1217 /gen-parallel-sem-switch
1222 ENDSWITCH (sem) /* End of semantic switch. */
1224 /* At this point `vpc' contains the next insn to execute. */
1227 #undef DEFINE_SWITCH
1228 #endif /* DEFINE_SWITCH */
1233 ; Generate mainloop.in.
1234 ; ??? Not currently used.
1236 (define (cgen-mainloop.in)
1237 (logit 1 "Generating mainloop.in ...\n")
1240 "cat <<EOF >/dev/null\n"
1241 (gen-c-copyright "Simulator main loop for @arch@."
1242 CURRENT-COPYRIGHT CURRENT-PACKAGE)
1247 # /bin/sh mainloop.in init|support|{full,fast}-{extract,exec}-{scache,nocache}
1249 # ??? There's lots of conditional compilation here.
1250 # After a few more ports are done, revisit.
1270 xfull-extract-* | xfast-extract-*)
1275 (rtl-c VOID #f nil insn-extract #:rtl-cover-fns? #t)
1281 xfull-exec-* | xfast-exec-*)
1286 (rtl-c VOID #f nil insn-execute #:rtl-cover-fns? #t)
1293 echo \"Invalid argument to mainloop.in: $1\" >&2