-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathopc-opinst.scm
174 lines (155 loc) · 4.99 KB
/
opc-opinst.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
; Operand instance support.
; Copyright (C) 2000, 2009 Red Hat, Inc.
; This file is part of CGEN.
; Return C code to define one instance of operand object OP.
; TYPE is one of "INPUT" or "OUTPUT".
(define (/gen-operand-instance op type)
(let ((index (op:index op)))
(string-append " { "
type ", "
"\"" (gen-sym op) "\", "
(hw-enum (op:type op)) ", "
; FIXME: Revisit CGEN_ prefix, use MODE (FOO) instead.
"CGEN_" (mode:enum (op:mode op)) ", "
; FIXME: We don't handle memory properly yet. Later.
(cond ((memory? (op:type op))
"0, 0")
((has-attr? op 'SEM-ONLY)
"0, 0")
((eq? (hw-index:type index) 'ifield)
(if (= (ifld-length (hw-index:value index)) 0)
"0, 0"
(string-append "OP_ENT ("
(string-upcase (gen-sym op))
"), 0")))
((eq? (hw-index:type index) 'constant)
(string-append "0, "
(number->string (hw-index:value index))))
((eq? (hw-index:type index) 'enum)
(let ((sym (hw-index-enum-name index))
(obj (hw-index-enum-obj index)))
(string-append "0, "
(gen-enum-sym obj sym))))
(else "0, 0"))
", " (if (op:cond? op) "COND_REF" "0")
" },\n"))
)
; Return C code to define arrays of operand instances read from and written
; to by <sformat> SFMT.
; This is based on the semantics of the instruction.
; ??? All runtime chosen values (e.g. a particular register in a register bank)
; is assumed to be selected statically by the instruction. When some cpu
; violates this assumption (say because a previous instruction determines
; which register(s) the next instruction operates on), this will need
; additional support.
(define (/gen-operand-instance-table sfmt)
(let ((ins (sfmt-in-ops sfmt))
(outs (sfmt-out-ops sfmt)))
; This used to exclude outputing anything if there were no ins or outs.
(gen-obj-sanitize
(sfmt-eg-insn sfmt) ; sanitize based on the example insn
(string-append
"static const CGEN_OPINST "
(gen-sym sfmt) "_ops[] ATTRIBUTE_UNUSED = {\n"
(string-map (lambda (op) (/gen-operand-instance op "INPUT"))
ins)
(string-map (lambda (op) (/gen-operand-instance op "OUTPUT"))
outs)
" { END, (const char *)0, (enum cgen_hw_type)0, (enum cgen_mode)0, (enum cgen_operand_type)0, 0, 0 }\n};\n\n")))
)
(define (/gen-operand-instance-tables)
(string-write
"\
/* Operand references. */
"
(gen-define-with-symcat "OP_ENT(op) @ARCH@_OPERAND_" "op")
"\
#define INPUT CGEN_OPINST_INPUT
#define OUTPUT CGEN_OPINST_OUTPUT
#define END CGEN_OPINST_END
#define COND_REF CGEN_OPINST_COND_REF
"
(lambda () (string-write-map /gen-operand-instance-table (current-sfmt-list)))
"\
#undef OP_ENT
#undef INPUT
#undef OUTPUT
#undef END
#undef COND_REF
"
)
)
; Return C code for INSN's operand instance table.
(define (gen-operand-instance-ref insn)
(let* ((sfmt (insn-sfmt insn))
(ins (sfmt-in-ops sfmt))
(outs (sfmt-out-ops sfmt)))
(if (and (null? ins) (null? outs))
"0"
(string-append "& " (gen-sym sfmt) "_ops[0]")))
)
; Return C code to define a table to lookup an insn's operand instance table.
(define (/gen-insn-opinst-lookup-table)
(string-list
"/* Operand instance lookup table. */\n\n"
"static const CGEN_OPINST *@arch@_cgen_opinst_table[MAX_INSNS] = {\n"
" 0,\n" ; null first entry
(string-list-map
(lambda (insn)
(gen-obj-sanitize
insn
(string-append " & " (gen-sym (insn-sfmt insn)) "_ops[0],\n")))
(current-insn-list))
"};\n\n"
"\
/* Function to call before using the operand instance table. */
void
@arch@_cgen_init_opinst_table (CGEN_CPU_DESC cd)
{
int i;
const CGEN_OPINST **oi = & @arch@_cgen_opinst_table[0];
CGEN_INSN *insns = (CGEN_INSN *) cd->insn_table.init_entries;
for (i = 0; i < MAX_INSNS; ++i)
insns[i].opinst = oi[i];
}
"
)
)
; Return the maximum number of operand instances used by any insn.
; If not generating the operand instance table, use a heuristic.
(define (max-operand-instances)
(if /opcodes-build-operand-instance-table?
(apply max
(map (lambda (insn)
(+ (length (sfmt-in-ops (insn-sfmt insn)))
(length (sfmt-out-ops (insn-sfmt insn)))))
(current-insn-list)))
8) ; FIXME: for now
)
; Generate $arch-opinst.c.
(define (cgen-opinst.c)
(logit 1 "Generating " (current-arch-name) "-opinst.c ...\n")
; If instruction semantics haven't been analyzed, do that now.
(if (not (arch-semantics-analyzed? CURRENT-ARCH))
(begin
(logit 1 "Instruction semantics weren't analyzed when .cpu file was loaded.\n")
(logit 1 "Doing so now ...\n")
(arch-analyze-insns! CURRENT-ARCH
#t ; include aliases
#t) ; /opcodes-build-operand-instance-table?
))
(string-write
(gen-c-copyright "Semantic operand instances for @arch@."
CURRENT-COPYRIGHT CURRENT-PACKAGE)
"\
#include \"sysdep.h\"
#include \"ansidecl.h\"
#include \"bfd.h\"
#include \"symcat.h\"
#include \"@[email protected]\"
#include \"@[email protected]\"
\n"
/gen-operand-instance-tables
/gen-insn-opinst-lookup-table
)
)