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))
28 /* The size of an \"int\" needed to hold an instruction word.
29 This is usually 32 bits, but some architectures needs 64 bits. */
31 (if (adata-large-insn-word? CURRENT-ARCH)
34 " CGEN_INSN_WORD;\n\n"
35 ; (gen-enum-decl '@cpu@_virtual
36 ; "@cpu@ virtual insns"
37 ; "@ARCH@_INSN_" ; not @CPU@ to match CGEN_INSN_TYPE in opc.h
39 ; (x-before -1) (x-after -2)
40 ; (x-begin -3) (x-chain -4) (x-cti-chain -5)))
44 ; Return a boolean indicating if hardware element HW needs storage allocated
45 ; for it in the SIM_CPU struct.
47 (define (hw-need-storage? hw)
48 (and (register? hw) (not (obj-has-attr? hw 'VIRTUAL)))
51 ; Subroutine of /gen-hardware-types to generate the struct containing
52 ; hardware elements of one isa.
54 (define (/gen-hardware-struct hw-list)
56 ; If struct is empty, leave it out to simplify generated code.
58 (string-list-map (lambda (hw)
63 (send hw 'gen-get-macro)
64 (send hw 'gen-set-macro)))))
65 (find hw-need-storage? hw-list)))
68 ; Return C type declarations of all of the hardware elements.
69 ; The name of the type is prepended with the cpu family name.
71 (define (/gen-hardware-types)
73 "/* CPU state information. */\n"
75 " /* Hardware elements. */\n"
79 (or (not (with-multiple-isa?))
81 (current-keep-isa-name-list)
82 (obj-attr-value hw 'ISA))
87 "#define CPU_CGEN_HW(cpu) (& (cpu)->cpu_data.hardware)\n"
88 ;" /* CPU profiling state information. */\n"
90 ;(string-list-map (lambda (hw) (send hw 'gen-profile-decl))
91 ; (find hw-profilable? (current-hw-list)))
93 ;"#define CPU_CGEN_PROFILE(cpu) (& (cpu)->cpu_data.profile)\n"
94 "} @CPU@_CPU_DATA;\n\n"
95 ; If there are any virtual regs, output get/set macros for them.
96 (let ((virtual-regs (find (lambda (hw)
98 (obj-has-attr? hw 'VIRTUAL)))
100 (orig-with-parallel? (with-parallel?))
102 (set-with-parallel?! #f)
103 (if (not (null? virtual-regs))
106 "/* Virtual regs. */\n\n"
107 (string-list-map (lambda (hw)
108 (logit 3 "Generating get/set for " (obj:name hw)
112 (send hw 'gen-get-macro)
113 (send hw 'gen-set-macro))))
117 (set-with-parallel?! orig-with-parallel?)
122 ; Return the declaration of register access functions.
124 (define (/gen-cpu-reg-access-decls)
126 "/* Cover fns for register access. */\n"
127 (string-list-map (lambda (hw)
128 (gen-reg-access-decl hw
132 (find register? (current-hw-list)))
134 "/* These must be hand-written. */\n"
135 "extern CPUREG_FETCH_FN @cpu@_fetch_register;\n"
136 "extern CPUREG_STORE_FN @cpu@_store_register;\n"
140 ; Generate type of struct holding model state while executing.
142 (define (/gen-model-decls)
143 (logit 2 "Generating model decls ...\n")
149 (if (null? (model:state model))
150 " int empty;\n" ; ensure struct isn't empty so it compiles
151 (string-map (lambda (var)
153 (mode:c-type (mode:lookup (cadr var)))
155 (gen-c-symbol (car var))
157 (model:state model)))
158 "} MODEL_" (string-upcase (gen-sym model)) "_DATA;\n\n"
160 (current-model-list))
164 ; Utility of /gen-extract-macros to generate a macro to define the local
165 ; vars to contain extracted field values and the code to assign them
166 ; for <iformat> IFMT.
168 (define (/gen-extract-ifmt-macro ifmt)
169 (logit 2 "Processing format " (obj:name ifmt) " ...\n")
171 (gen-define-ifmt-ifields ifmt "" #t #f)
172 (gen-extract-ifmt-ifields ifmt "" #t #f)
173 ; We don't need an extra blank line here as gen-extract-ifields adds one.
177 ; Generate macros to extract instruction fields.
179 (define (/gen-extract-macros)
180 (logit 2 "Generating extraction macros ...\n")
183 /* Macros to simplify extraction, reading and semantic code.
184 These define and assign the local vars that contain the insn's fields. */
186 (string-list-map /gen-extract-ifmt-macro (current-ifmt-list))
190 ; Utility of /gen-parallel-exec-type to generate the definition of one
191 ; structure in PAREXEC.
192 ; SFMT is an <sformat> object.
194 (define (/gen-parallel-exec-elm sfmt)
196 " struct { /* " (obj:comment sfmt) " */\n"
198 ((if (with-parallel-write?) sfmt-out-ops sfmt-in-ops) sfmt)))
200 " int empty;\n" ; ensure struct isn't empty so it compiles
203 (logit 2 "Processing operand " (obj:name op) " of format "
204 (obj:name sfmt) " ...\n")
205 (if (with-parallel-write?)
206 (let ((index-type (and (op-save-index? op)
207 (gen-index-type op sfmt))))
208 (string-append " " (gen-type op)
209 " " (gen-sym op) ";\n"
211 (string-append " " index-type
212 " " (gen-sym op) "_idx;\n")
220 " } " (gen-sym sfmt) ";\n"
224 ; Generate the definition of the structure that holds register values, etc.
225 ; for use during parallel execution. When instructions are executed parallelly
227 ; - their inputs are read before their outputs are written. Thus we have to
228 ; fetch the input values of several instructions before executing any of them.
229 ; - or their outputs are queued here first and then written out after all insns
231 ; The fetched/queued values are stored in an array of PAREXEC structs, one
232 ; element per instruction.
234 (define (/gen-parallel-exec-type)
235 (logit 2 "Generating PAREXEC type ...\n")
237 (if (with-parallel-write?)
238 "/* Queued output values of an instruction. */\n"
239 "/* Fetched input values of an instruction. */\n")
244 (string-map /gen-parallel-exec-elm (current-sfmt-list))
247 /* For conditionally written operands, bitmask of which ones were. */
253 ; Generate the TRACE_RECORD struct definition.
254 ; This struct will hold all necessary data for doing tracing and profiling
255 ; (e.g. register numbers). The goal is to remove all tracing code from the
256 ; semantic code. Then the fast/full distinction needn't use conditionals to
257 ; discard/include the tracing/profiling code.
259 (define (/gen-trace-record-type)
262 /* Collection of various things for the trace handler to use. */
264 typedef struct trace_record {
272 ; Utilities of cgen-cpu.c
274 ; Get/set fns for every register.
276 (define (/gen-cpu-reg-access-defns)
279 (let ((scalar? (hw-scalar? hw))
281 (getter (hw-getter hw))
282 (setter (hw-setter hw)))
283 (gen-reg-access-defn hw
290 (string-upcase (gen-c-symbol name))
292 (if scalar? "" "regno")
297 (if scalar? "" "[regno]")
302 (string-upcase (gen-c-symbol name))
304 (if scalar? "" "regno, ")
309 (if scalar? "" "[regno]")
311 (find (lambda (hw) (register? hw))
315 ; Generate a function to record trace results in a trace record.
317 (define (/gen-cpu-record-results)
320 /* Record trace results for INSN. */
323 @cpu@_record_trace_results (SIM_CPU *current_cpu, CGEN_INSN *insn,
324 int *indices, TRACE_RECORD *tr)
330 ; Utilities of cgen-read.c.
331 ; Parallel-read support is not currently used by any port and this code
332 ; has been left to bitrot. Don't delete it just yet.
334 ; Return C code to fetch and save all input operands to instructions with
337 (define (/gen-read-args sfmt)
338 (string-map (lambda (op) (op:read op sfmt))
342 ; Utility of /gen-read-switch to generate a switch case for <sformat> SFMT.
344 (define (/gen-read-case sfmt)
345 (logit 2 "Processing read switch case for \"" (obj:name sfmt) "\" ...\n")
347 " CASE (read, READ_" (string-upcase (gen-sym sfmt)) ") : "
348 "/* " (obj:comment sfmt) " */\n"
350 (gen-define-field-macro (if (with-scache?) sfmt #f))
351 (gen-define-parallel-operand-macro sfmt)
352 (gen-define-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) " " #f)
353 (gen-extract-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) " " #f)
354 (/gen-read-args sfmt)
355 (gen-undef-parallel-operand-macro sfmt)
356 (gen-undef-field-macro sfmt)
362 ; Generate the guts of a C switch statement to read insn operands.
363 ; The switch is based on instruction formats.
365 (define (/gen-read-switch)
366 (logit 2 "Processing readers ...\n")
367 (string-write-map /gen-read-case (current-sfmt-list))
370 ; Utilities of cgen-write.c.
372 ; This is the other way of implementing parallel execution support.
373 ; Instead of fetching all the input operands first, write all the output
374 ; operands and their addresses to holding variables, and then run a
375 ; post-processing pass to update the cpu state.
377 ; There are separate implementations for semantics as functions and semantics
378 ; as one big switch. For the function case we create a function that is a
379 ; switch on each semantic format and loops writing each insn's results back.
380 ; For the switch case we add cases to the switch to handle the write back,
381 ; and it is up to the pbb compiler to include them in the generated "code".
383 ; Return C code to fetch and save all output operands to instructions with
386 (define (/gen-write-args sfmt)
387 (string-map (lambda (op) (op:write op sfmt))
391 ; Utility of gen-write-switch to generate a switch case for <sformat> SFMT.
392 ; If INSN is non-#f, it is the <insn> object of the insn in which case
393 ; the case is named after the insn not the format. This is done because
394 ; current sem-switch support emits one handler per insn instead of per sfmt.
396 (define (/gen-write-case sfmt insn)
397 (logit 2 "Processing write switch case for \"" (obj:name sfmt) "\" ...\n")
401 "CASE (sem, INSN_WRITE_"
402 (string-upcase (gen-sym insn)) ") : ")
405 (string-upcase (gen-sym sfmt)) " : "))
408 (string-list (insn-syntax insn))
415 " SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);\n"
417 " const ARGBUF *abuf = SEM_ARGBUF (sem_arg)->fields.write.abuf;\n")
419 (gen-define-field-macro (if (with-scache?) sfmt #f))
420 (gen-define-parallel-operand-macro sfmt)
422 " int UNUSED written = abuf->written;\n"
423 ;(gen-define-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) " " #f) - used by cgen-read.c
424 ;(gen-extract-ifields (sfmt-iflds sfmt) (sfmt-length sfmt) " " #f) - used by cgen-read.c
426 (string-list /indent " IADDR UNUSED pc = abuf->addr;\n")
428 (if (and insn (insn-cti? insn))
430 " SEM_BRANCH_INIT\n") ; no trailing `;' on purpose
433 (string-list /indent " vpc = SEM_NEXT_VPC (sem_arg, pc, 0);\n")
437 (/gen-write-args sfmt)
440 (if (and insn (insn-cti? insn))
441 (string-list /indent " SEM_BRANCH_FINI (vpc);\n")
443 (gen-undef-parallel-operand-macro sfmt)
444 (gen-undef-field-macro sfmt)
447 (string-list /indent " NEXT (vpc);\n")
448 (string-list /indent " break;\n"))
453 ; Generate the guts of a C switch statement to write insn operands.
454 ; The switch is based on instruction formats.
455 ; ??? This will generate cases for formats that don't need it.
456 ; E.g. on the m32r all 32 bit insns can't be executed in parallel.
457 ; It's easier to generate the code anyway so we do.
459 (define (/gen-write-switch)
460 (logit 2 "Processing writers ...\n")
461 (string-write-map (lambda (sfmt)
462 (/gen-write-case sfmt #f))
466 ; Utilities of cgen-semantics.c.
468 ; Return name of semantic fn for INSN.
470 (define (/gen-sem-fn-name insn)
471 ;(string-append "sem_" (gen-sym insn))
475 ; Return semantic fn table entry for INSN.
477 (define (/gen-sem-fn-table-entry insn)
481 (string-upcase (gen-sym insn))
483 "SEM_FN_NAME (@prefix@," (/gen-sem-fn-name insn) ")"
488 ; Return C code to define a table of all semantic fns and a function to
489 ; add the info to the insn descriptor table.
491 (define (/gen-semantic-fn-table)
494 /* Table of all semantic fns. */
496 static const struct sem_fn_desc sem_fns[] = {\n"
499 (string-write-map /gen-sem-fn-table-entry
500 (non-alias-insns (current-insn-list))))
506 /* Add the semantic fns to IDESC_TABLE. */
509 SEM_FN_NAME (@prefix@,init_idesc_table) (SIM_CPU *current_cpu)
511 IDESC *idesc_table = CPU_IDESC (current_cpu);
512 const struct sem_fn_desc *sf;
513 int mach_num = MACH_NUM (CPU_MACH (current_cpu));
515 for (sf = &sem_fns[0]; sf->fn != 0; ++sf)
517 const CGEN_INSN *insn = idesc_table[sf->index].idata;
518 int valid_p = (CGEN_INSN_VIRTUAL_P (insn)
519 || CGEN_INSN_MACH_HAS_P (insn, mach_num));
522 idesc_table[sf->index].sem_fast = sf->fn;
524 idesc_table[sf->index].sem_fast = SEM_FN_NAME (@prefix@,x_invalid);
527 idesc_table[sf->index].sem_full = sf->fn;
529 idesc_table[sf->index].sem_full = SEM_FN_NAME (@prefix@,x_invalid);
537 ; Return C code to perform the semantics of INSN.
539 (define (gen-semantic-code insn)
541 (if (and (insn-real? insn)
542 (isa-setup-semantics (current-isa)))
545 (rtl-c VOID (obj-isa-list insn) nil
546 (isa-setup-semantics (current-isa))
553 ; Indicate generating code for INSN.
554 ; Use the compiled form if available.
555 ; The case when they're not available is for virtual insns. xxx Still true?
556 (cond ((insn-compiled-semantics insn)
558 (rtl-c-parsed VOID sem
562 ((insn-canonical-semantics insn)
564 (rtl-c-parsed VOID sem
569 (context-error (make-obj-context insn #f)
570 "While generating semantic code"
571 "semantics of insn are not canonicalized"))))
574 ; Return definition of C function to perform INSN.
575 ; This version handles the with-scache case.
577 (define (/gen-scache-semantic-fn insn)
578 (logit 2 "Processing semantics for " (obj:name insn) ": \"" (insn-syntax insn) "\" ...\n")
579 (set! /with-profile? /with-profile-fn?)
580 (let ((profile? (and (with-profile?)
581 (not (obj-has-attr? insn 'VIRTUAL))))
582 (parallel? (with-parallel?))
583 (cti? (insn-cti? insn))
584 (insn-len (insn-length-bytes insn)))
586 "/* " (obj:str-name insn) ": " (insn-syntax insn) " */\n\n"
588 "SEM_FN_NAME (@prefix@," (gen-sym insn) ")"
589 (if (and parallel? (not (with-generic-write?)))
590 " (SIM_CPU *current_cpu, SEM_ARG sem_arg, PAREXEC *par_exec)\n"
591 " (SIM_CPU *current_cpu, SEM_ARG sem_arg)\n")
593 (gen-define-field-macro (insn-sfmt insn))
594 (if (and parallel? (not (with-generic-write?)))
595 (gen-define-parallel-operand-macro (insn-sfmt insn))
597 " ARGBUF *abuf = SEM_ARGBUF (sem_arg);\n"
598 ; Unconditionally written operands are not recorded here.
599 " int UNUSED written = 0;\n"
600 ; The address of this insn, needed by extraction and semantic code.
601 ; Note that the address recorded in the cpu state struct is not used.
602 ; For faster engines that copy will be out of date.
603 " IADDR UNUSED pc = abuf->addr;\n"
604 (if (and cti? (not parallel?))
605 " SEM_BRANCH_INIT\n" ; no trailing `;' on purpose
607 (string-list " SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, "
608 (number->string insn-len)
611 (gen-semantic-code insn) "\n"
612 ; Only update what's been written if some are conditionally written.
613 ; Otherwise we know they're all written so there's no point in
615 (if (/any-cond-written? (insn-sfmt insn))
616 " abuf->written = written;\n"
618 (if (and cti? (not parallel?))
619 " SEM_BRANCH_FINI (vpc);\n"
622 (if (and parallel? (not (with-generic-write?)))
623 (gen-undef-parallel-operand-macro (insn-sfmt insn))
625 (gen-undef-field-macro (insn-sfmt insn))
630 ; Return definition of C function to perform INSN.
631 ; This version handles the without-scache case.
632 ; ??? TODO: multiword insns.
634 (define (/gen-no-scache-semantic-fn insn)
635 (logit 2 "Processing semantics for " (obj:name insn) ": \"" (insn-syntax insn) "\" ...\n")
636 (set! /with-profile? /with-profile-fn?)
637 (let ((profile? (and (with-profile?)
638 (not (obj-has-attr? insn 'VIRTUAL))))
639 (parallel? (with-parallel?))
640 (cti? (insn-cti? insn))
641 (insn-len (insn-length-bytes insn)))
643 "/* " (obj:str-name insn) ": " (insn-syntax insn) " */\n\n"
644 "static SEM_STATUS\n"
645 "SEM_FN_NAME (@prefix@," (gen-sym insn) ")"
646 (if (and parallel? (not (with-generic-write?)))
647 " (SIM_CPU *current_cpu, SEM_ARG sem_arg, PAREXEC *par_exec, CGEN_INSN_WORD insn)\n"
648 " (SIM_CPU *current_cpu, SEM_ARG sem_arg, CGEN_INSN_WORD insn)\n")
650 (if (and parallel? (not (with-generic-write?)))
651 (gen-define-parallel-operand-macro (insn-sfmt insn))
653 " SEM_STATUS status = 0;\n" ; ??? wip
654 " ARGBUF *abuf = SEM_ARGBUF (sem_arg);\n"
655 (gen-define-field-macro (if (with-scache?) (insn-sfmt insn) #f))
656 ; Unconditionally written operands are not recorded here.
657 " int UNUSED written = 0;\n"
658 " IADDR UNUSED pc = GET_H_PC ();\n"
659 (if (and cti? (not parallel?))
660 " SEM_BRANCH_INIT\n" ; no trailing `;' on purpose
662 (string-list " SEM_PC vpc = SEM_NEXT_VPC (sem_arg, pc, "
663 (number->string insn-len)
665 (string-list (gen-define-ifmt-ifields (insn-ifmt insn) " " #f #t)
666 (gen-sfmt-op-argbuf-defns (insn-sfmt insn))
667 (gen-extract-ifmt-ifields (insn-ifmt insn) " " #f #t)
668 (gen-sfmt-op-argbuf-assigns (insn-sfmt insn)))
670 (gen-semantic-code insn) "\n"
671 ; Only update what's been written if some are conditionally written.
672 ; Otherwise we know they're all written so there's no point in
674 (if (/any-cond-written? (insn-sfmt insn))
675 " abuf->written = written;\n"
677 ; SEM_{,N}BRANCH_FINI are user-supplied macros.
681 " SEM_BRANCH_FINI (vpc, "
682 " SEM_NBRANCH_FINI (vpc, ")
683 (gen-bool-attrs (obj-atlist insn) gen-attr-mask)
686 (gen-undef-field-macro (insn-sfmt insn))
688 (if (and parallel? (not (with-generic-write?)))
689 (gen-undef-parallel-operand-macro (insn-sfmt insn))
695 (define (/gen-all-semantic-fns)
696 (logit 2 "Processing semantics ...\n")
697 (let ((insns (non-alias-insns (current-insn-list))))
699 (string-write-map /gen-scache-semantic-fn insns)
700 (string-write-map /gen-no-scache-semantic-fn insns)))
703 ; Utility of /gen-sem-case to return the mask of operands always written
704 ; to in <sformat> SFMT.
705 ; ??? Not currently used.
707 (define (/uncond-written-mask sfmt)
708 (apply + (map (lambda (op)
711 (logsll 1 (op:num op))))
712 (sfmt-out-ops sfmt)))
715 ; Utility of /gen-sem-case to return #t if any operand in <sformat> SFMT is
716 ; conditionally written to.
718 (define (/any-cond-written? sfmt)
719 (any-true? (map op:cond? (sfmt-out-ops sfmt)))
722 ; Generate a switch case to perform INSN.
724 (define (/gen-sem-case insn parallel?)
725 (logit 2 "Processing "
726 (if parallel? "parallel " "")
727 "semantic switch case for " (obj:name insn) ": \""
728 (insn-syntax insn) "\" ...\n")
729 (set! /with-profile? /with-profile-sw?)
730 (let ((cti? (insn-cti? insn))
731 (insn-len (insn-length-bytes insn)))
733 ; INSN_ is prepended here and not elsewhere to avoid name collisions
734 ; with symbols like AND, etc.
737 (if parallel? "PAR_" "")
738 (string-upcase (gen-sym insn)) ") : "
739 "/* " (insn-syntax insn) " */\n"
741 " SEM_ARG sem_arg = SEM_SEM_ARG (vpc, sc);\n"
742 " ARGBUF *abuf = SEM_ARGBUF (sem_arg);\n"
743 (gen-define-field-macro (if (with-scache?) (insn-sfmt insn) #f))
744 (if (and parallel? (not (with-generic-write?)))
745 (gen-define-parallel-operand-macro (insn-sfmt insn))
747 ; Unconditionally written operands are not recorded here.
748 " int UNUSED written = 0;\n"
749 ; The address of this insn, needed by extraction and semantic code.
750 ; Note that the address recorded in the cpu state struct is not used.
751 " IADDR UNUSED pc = abuf->addr;\n"
752 (if (and cti? (not parallel?))
753 " SEM_BRANCH_INIT\n" ; no trailing `;' on purpose
757 (string-list (gen-define-ifmt-ifields (insn-ifmt insn) " " #f #t)
758 (gen-extract-ifmt-ifields (insn-ifmt insn) " " #f #t)
760 (string-list " vpc = SEM_NEXT_VPC (sem_arg, pc, "
761 (number->string insn-len)
764 (gen-semantic-code insn) "\n"
765 ; Only update what's been written if some are conditionally written.
766 ; Otherwise we know they're all written so there's no point in
768 (if (/any-cond-written? (insn-sfmt insn))
769 " abuf->written = written;\n"
771 (if (and cti? (not parallel?))
772 " SEM_BRANCH_FINI (vpc);\n"
774 (if (and parallel? (not (with-generic-write?)))
775 (gen-undef-parallel-operand-macro (insn-sfmt insn))
777 (gen-undef-field-macro (insn-sfmt insn))
783 (define (/gen-sem-switch)
784 (logit 2 "Processing semantic switch ...\n")
785 ; Turn parallel execution support off.
786 (let ((orig-with-parallel? (with-parallel?)))
787 (set-with-parallel?! #f)
789 (string-write-map (lambda (insn) (/gen-sem-case insn #f))
790 (non-alias-insns (current-insn-list)))))
791 (set-with-parallel?! orig-with-parallel?)
795 ; Generate the guts of a C switch statement to execute parallel instructions.
796 ; This switch is included after the non-parallel instructions in the semantic
799 ; ??? We duplicate the writeback case for each insn, even though we only need
800 ; one case per insn format. The former keeps the code for each insn
801 ; together and might improve cache usage. On the other hand the latter
802 ; reduces the amount of code, though it is believed that in this particular
803 ; instance the win isn't big enough.
805 (define (/gen-parallel-sem-switch)
806 (logit 2 "Processing parallel insn semantic switch ...\n")
807 ; Turn parallel execution support on.
808 (let ((orig-with-parallel? (with-parallel?)))
809 (set-with-parallel?! #t)
811 (string-write-map (lambda (insn)
812 (string-list (/gen-sem-case insn #t)
813 (/gen-write-case (insn-sfmt insn) insn)))
814 (parallel-insns (current-insn-list)))))
815 (set-with-parallel?! orig-with-parallel?)
819 ; Top level file generators.
821 ; Generate cpu-<cpu>.h
824 (logit 1 "Generating " (gen-cpu-name) "'s cpu.h ...\n")
828 ; Turn parallel execution support on if cpu needs it.
829 (set-with-parallel?! (state-parallel-exec?))
831 ; Tell the rtl->c translator we're not the simulator.
832 ; ??? Minimizes changes in generated code until this is changed.
833 ; RTL->C happens for field decoding.
834 (rtl-c-config! #:rtl-cover-fns? #f)
837 (gen-c-copyright "CPU family header for @cpu@."
838 CURRENT-COPYRIGHT CURRENT-PACKAGE)
845 ;; After CGEN_INSN_WORD is defined we can include cgen-engine.h.
846 ;; We need to include it here (or thereabouts) because cgen-engine.h
847 ;; needs CGEN_INSN_WORD and parts of the remainder of this file need
849 "#include \"cgen-engine.h\"\n\n"
851 /gen-cpu-reg-access-decls
854 (if (not (with-multiple-isa?))
856 (lambda () (gen-argbuf-type #t))
857 (lambda () (gen-scache-type #t))
861 (if (and (with-parallel?) (not (with-generic-write?)))
862 /gen-parallel-exec-type
864 /gen-trace-record-type
865 "#endif /* CPU_@CPU@_H */\n"
869 ; Generate defs-<isa>.h.
871 (define (cgen-defs.h)
872 (logit 1 "Generating " (obj:name (current-isa)) "'s defs.h ...\n")
876 ; Tell the rtl->c translator we're not the simulator.
877 ; ??? Minimizes changes in generated code until this is changed.
878 ; RTL->C happens for field decoding.
879 (rtl-c-config! #:rtl-cover-fns? #f)
882 (gen-c-copyright (string-append
883 "ISA definitions header for "
884 (obj:str-name (current-isa))
886 CURRENT-COPYRIGHT CURRENT-PACKAGE)
888 #ifndef DEFS_@PREFIX@_H
889 #define DEFS_@PREFIX@_H
892 (lambda () (gen-argbuf-type #t))
893 (lambda () (gen-scache-type #t))
896 "#endif /* DEFS_@PREFIX@_H */\n"
900 ; Generate cpu-<cpu>.c
903 (logit 1 "Generating " (gen-cpu-name) "'s cpu.c ...\n")
907 ; Turn parallel execution support on if cpu needs it.
908 (set-with-parallel?! (state-parallel-exec?))
910 ; Initialize rtl generation.
911 (rtl-c-config! #:rtl-cover-fns? #t)
914 (gen-c-copyright "Misc. support for CPU family @cpu@."
915 CURRENT-COPYRIGHT CURRENT-PACKAGE)
917 #define WANT_CPU @cpu@
918 #define WANT_CPU_@CPU@
920 #include \"sim-main.h\"
921 #include \"cgen-ops.h\"
924 /gen-cpu-reg-access-defns
925 /gen-cpu-record-results
931 (define (cgen-read.c)
932 (logit 1 "Generating " (gen-cpu-name) "'s read.c ...\n")
936 ; Turn parallel execution support off.
937 (set-with-parallel?! #f)
939 ; Tell the rtx->c translator we are the simulator.
940 (rtl-c-config! #:rtl-cover-fns? #t)
943 (gen-c-copyright (string-append "Simulator instruction operand reader for "
944 (symbol->string (current-arch-name)) ".")
945 CURRENT-COPYRIGHT CURRENT-PACKAGE)
949 /* The labels have the case they have because the enum of insn types
950 is all uppercase and in the non-stdc case the fmt symbol is built
951 into the enum name. */
959 (string-write-map (lambda (insn)
962 (string-upcase (gen-sym insn))
963 ", && case_read_READ_"
964 (string-upcase (gen-sym (insn-sfmt insn)))
966 (non-alias-insns (current-insn-list))))
972 for (i = 0; labels[i].label != 0; ++i)
973 CPU_IDESC (current_cpu) [labels[i].index].read = labels[i].label;
976 #endif /* DEFINE_LABELS */
983 SEM_ARG sem_arg = sc;
984 ARGBUF *abuf = SEM_ARGBUF (sem_arg);
986 SWITCH (read, sem_arg->read)\n"
988 SWITCH (read, decode->read)\n")
998 ENDSWITCH (read) /* End of read switch. */
1001 #undef DEFINE_SWITCH
1002 #endif /* DEFINE_SWITCH */
1009 (define (cgen-write.c)
1010 (logit 1 "Generating " (gen-cpu-name) "'s write.c ...\n")
1012 (sim-analyze-insns!)
1014 ; Turn parallel execution support off.
1015 (set-with-parallel?! #f)
1017 ; Tell the rtx->c translator we are the simulator.
1018 (rtl-c-config! #:rtl-cover-fns? #t)
1021 (gen-c-copyright (string-append "Simulator instruction operand writer for "
1022 (symbol->string (current-arch-name)) ".")
1023 CURRENT-COPYRIGHT CURRENT-PACKAGE)
1025 /* Write cached results of 1 or more insns executed in parallel. */
1028 @cpu@_parallel_write (SIM_CPU *cpu, SCACHE *sbufs, PAREXEC *pbufs, int ninsns)
1032 SEM_ARG sem_arg = sc;
1033 ARGBUF *abuf = SEM_ARGBUF (sem_arg);\n"
1039 ARGBUF *abuf = SEM_ARGBUF (sbufs);
1041 switch (abuf->idesc->write)
1052 while (--ninsns > 0);
1058 ; Generate semantics.c
1059 ; Each instruction is implemented in its own function.
1061 (define (cgen-semantics.c)
1062 (logit 1 "Generating " (gen-cpu-name) "'s semantics.c ...\n")
1064 (sim-analyze-insns!)
1066 ; Turn parallel execution support on if cpu needs it.
1067 (set-with-parallel?! (state-parallel-exec?))
1069 ; Tell the rtx->c translator we are the simulator.
1070 (rtl-c-config! #:rtl-cover-fns? #t)
1073 (gen-c-copyright "Simulator instruction semantics for @cpu@."
1074 CURRENT-COPYRIGHT CURRENT-PACKAGE)
1076 #define WANT_CPU @cpu@
1077 #define WANT_CPU_@CPU@
1079 #include \"sim-main.h\"
1080 #include \"cgen-mem.h\"
1081 #include \"cgen-ops.h\"
1085 (gen-define-with-symcat "GET_ATTR(cpu, num, attr) \
1086 CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_" "attr)")
1088 /* This is used so that we can compile two copies of the semantic code,
1089 one with full feature support and one without that runs fast(er).
1090 FAST_P, when desired, is defined on the command line, -DFAST_P=1. */
1092 #define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_semf_,fn)
1094 #define TRACE_RESULT(cpu, abuf, name, type, val)
1096 #define SEM_FN_NAME(cpu,fn) XCONCAT3 (cpu,_sem_,fn)
1100 /gen-all-semantic-fns
1101 ; Put the table at the end so we don't have to declare all the sem fns.
1102 /gen-semantic-fn-table
1106 ; Generate sem-switch.c.
1107 ; Each instruction is a case in a switch().
1108 ; This file consists of just the switch(). It is included by mainloop.c.
1110 (define (cgen-sem-switch.c)
1111 (logit 1 "Generating " (gen-cpu-name) "'s sem-switch.c ...\n")
1113 (sim-analyze-insns!)
1115 ; Turn parallel execution support off.
1116 ; It is later turned on/off when generating the actual semantic code.
1117 (set-with-parallel?! #f)
1119 ; Tell the rtx->c translator we are the simulator.
1120 (rtl-c-config! #:rtl-cover-fns? #t)
1123 (gen-c-copyright "Simulator instruction semantics for @cpu@."
1124 CURRENT-COPYRIGHT CURRENT-PACKAGE)
1127 #ifdef DEFINE_LABELS
1129 /* The labels have the case they have because the enum of insn types
1130 is all uppercase and in the non-stdc case the insn symbol is built
1131 into the enum name. */
1139 (string-write-map (lambda (insn)
1140 (string-append " { "
1142 (string-upcase (gen-sym insn))
1143 ", && case_sem_INSN_"
1144 (string-upcase (gen-sym insn))
1146 (non-alias-insns (current-insn-list))))
1148 (if (state-parallel-exec?)
1150 (string-write-map (lambda (insn)
1151 (string-append " { "
1153 (string-upcase (gen-sym insn))
1154 ", && case_sem_INSN_PAR_"
1155 (string-upcase (gen-sym insn))
1159 (string-upcase (gen-sym insn))
1160 ", && case_sem_INSN_WRITE_"
1161 (string-upcase (gen-sym insn))
1163 (parallel-insns (current-insn-list))))
1170 for (i = 0; labels[i].label != 0; ++i)
1173 CPU_IDESC (current_cpu) [labels[i].index].sem_fast_lab = labels[i].label;
1175 CPU_IDESC (current_cpu) [labels[i].index].sem_full_lab = labels[i].label;
1179 #undef DEFINE_LABELS
1180 #endif /* DEFINE_LABELS */
1182 #ifdef DEFINE_SWITCH
1184 /* If hyper-fast [well not unnecessarily slow] execution is selected, turn
1185 off frills like tracing and profiling. */
1186 /* FIXME: A better way would be to have TRACE_RESULT check for something
1187 that can cause it to be optimized out. Another way would be to emit
1188 special handlers into the instruction \"stream\". */
1192 #define TRACE_RESULT(cpu, abuf, name, type, val)
1197 (gen-define-with-symcat "GET_ATTR(cpu, num, attr) \
1198 CGEN_ATTR_VALUE (NULL, abuf->idesc->attrs, CGEN_INSN_" "attr)")
1204 /* Branch to next handler without going around main loop. */
1205 #define NEXT(vpc) goto * SEM_ARGBUF (vpc) -> semantic.sem_case
1206 SWITCH (sem, SEM_ARGBUF (vpc) -> semantic.sem_case)
1208 #else /* ! WITH_SCACHE_PBB */
1210 #define NEXT(vpc) BREAK (sem)
1213 SWITCH (sem, SEM_ARGBUF (sc) -> idesc->sem_fast_lab)
1215 SWITCH (sem, SEM_ARGBUF (sc) -> idesc->sem_full_lab)
1218 SWITCH (sem, SEM_ARGBUF (sc) -> idesc->num)
1221 #endif /* ! WITH_SCACHE_PBB */
1229 (if (state-parallel-exec?)
1230 /gen-parallel-sem-switch
1235 ENDSWITCH (sem) /* End of semantic switch. */
1237 /* At this point `vpc' contains the next insn to execute. */
1240 #undef DEFINE_SWITCH
1241 #endif /* DEFINE_SWITCH */
1246 ; Generate mainloop.in.
1247 ; ??? Not currently used.
1249 (define (cgen-mainloop.in)
1250 (logit 1 "Generating mainloop.in ...\n")
1253 "cat <<EOF >/dev/null\n"
1254 (gen-c-copyright "Simulator main loop for @arch@."
1255 CURRENT-COPYRIGHT CURRENT-PACKAGE)
1260 # /bin/sh mainloop.in init|support|{full,fast}-{extract,exec}-{scache,nocache}
1262 # ??? There's lots of conditional compilation here.
1263 # After a few more ports are done, revisit.
1283 xfull-extract-* | xfast-extract-*)
1288 (rtl-c VOID #f nil insn-extract #:rtl-cover-fns? #t)
1294 xfull-exec-* | xfast-exec-*)
1299 (rtl-c VOID #f nil insn-execute #:rtl-cover-fns? #t)
1306 echo \"Invalid argument to mainloop.in: $1\" >&2