1 |
6 |
jlechner |
; Opcode table support.
|
2 |
|
|
; Copyright (C) 2000, 2005, 2009 Red Hat, Inc.
|
3 |
|
|
; This file is part of CGEN.
|
4 |
|
|
|
5 |
|
|
; These are for internal use and aren't intended to appear in .cpu files.
|
6 |
|
|
; ??? Nothing currently uses them but that might change.
|
7 |
|
|
""""""""; Define CGEN_INIT_{PARSE,INSERT,EXTRACT,PRINT} macros.
|
8 |
|
|
|
9 |
|
|
"Generating init macros ...\n""#define CGEN_INIT_PARSE(od) \\
|
10 |
|
|
{\\\n""}\n""#define CGEN_INIT_INSERT(od) \\
|
11 |
|
|
{\\\n""}\n""#define CGEN_INIT_EXTRACT(od) \\
|
12 |
|
|
{\\\n""}\n""#define CGEN_INIT_PRINT(od) \\
|
13 |
|
|
|
14 |
|
|
; Return C code to declare various ifield types,decls.
|
15 |
|
|
"Generating instruction field decls ...\n""/* This struct records data prior to insertion or after extraction. */\n""struct cgen_fields\n{\n"; A special member `length' is used to record the length.
|
16 |
|
|
|
17 |
|
|
; Extract the operand fields in SYNTAX-STRING.
|
18 |
|
|
; The result is a list of operand names.
|
19 |
|
|
; ??? Not currently used, but keep awhile.
|
20 |
|
|
"missing char after '\\'"; Extract the symbol from the string, which will be the name of
|
21 |
|
|
; an operand. Append it to the result.
|
22 |
|
|
"missing operand name"; Note that 'n' includes the leading ${.
|
23 |
|
|
"empty operand name""missing '}'""empty or invalid operand name"; Strip the mnemonic part from SYNTAX.
|
24 |
|
|
; (ie: everything up to but not including the first space or '$')
|
25 |
|
|
; If STRIP-MNEM-OPERANDS?, strip them too.
|
26 |
|
|
""""; Compute the sequence of syntax bytes for SYNTAX.
|
27 |
|
|
; STRIP-MNEMONIC? is #t if the mnemonic part is to be stripped off.
|
28 |
|
|
; STRIP-MNEM-OPERANDS? is #t if any mnemonic operands are to be stripped off.
|
29 |
|
|
; SYNTAX is a string of text and operands.
|
30 |
|
|
; OP-MACRO is the macro to call that computes an operand's value.
|
31 |
|
|
; The resulting syntax is expressed as a sequence of bytes.
|
32 |
|
|
; Values < 128 are characters that must be matched.
|
33 |
|
|
; Values >= 128 are 128 + the index into the operand table.
|
34 |
|
|
"syntax computation""""0""missing char after '\\'""'\\\\', ""'""', "; Extract the symbol from the string, which will be the name of
|
35 |
|
|
; an operand. Append it to the result.
|
36 |
|
|
"missing operand name"; Is it $foo or ${foo}?
|
37 |
|
|
; Note that 'n' includes the leading ${.
|
38 |
|
|
|
39 |
|
|
"empty operand name""missing '}'"" (""), ""empty or invalid operand name""undefined operand "" (""), "; Append the character to the result.
|
40 |
|
|
|
41 |
|
|
; MNEM is the C value to use to represent the instruction's mnemonic.
|
42 |
|
|
|
43 |
|
|
"{ { "", "; `mnem' is used to represent the mnemonic, so we always want to strip it
|
44 |
|
|
; from the syntax string, regardless of the setting of `strip-mnemonic?'.
|
45 |
|
|
" } }"; Instruction format table support.
|
46 |
|
|
; Return the table for IFMT, an <iformat> object.
|
47 |
|
|
; sanitize based on the example insn
|
48 |
|
|
"static const CGEN_IFMT "" ATTRIBUTE_UNUSED = {\n"" "", "", ""0x"", ""{ ""{ F ("") }, ""{ 0 } }\n};\n\n"; Generate the insn format table.
|
49 |
|
|
"/* Instruction formats. */\n\n""F(f) & @arch@_cgen_ifld_table[@ARCH@_""f]""#undef F\n\n"; Parse/insert/extract/print handlers.
|
50 |
|
|
; Each handler type is recorded in the assembler/disassembler as an array of
|
51 |
|
|
; pointers to functions. The value recorded in the operand table is the index
|
52 |
|
|
; into this array. The first element in the array is reserved as index 0 is
|
53 |
|
|
; special (the "default").
|
54 |
|
|
|
55 |
|
|
; The handlers are recorded here as associative lists in case we ever want
|
56 |
|
|
|
57 |
|
|
;
|
58 |
|
|
; Adding a new handler involves
|
59 |
|
|
; - specifying its name in the .cpu file
|
60 |
|
|
|
61 |
|
|
; - writing the C code
|
62 |
|
|
;
|
63 |
|
|
|
64 |
|
|
; FIXME: There currently isn't a spot for specifying special handlers for
|
65 |
|
|
; each instruction. For now assume we always use the same ones.
|
66 |
|
|
|
67 |
|
|
; This is intended to be the ultimate escape hatch for the parse/insert/
|
68 |
|
|
; extract/print handlers. Each entry is an index into a table of handlers.
|
69 |
|
|
; The escape hatch isn't used yet.
|
70 |
|
|
"{ "" }"; Handler table support.
|
71 |
|
|
|
72 |
|
|
; Return C code to define the handler table for NAME with values VALUES.
|
73 |
|
|
"cgen_""_fn * const @arch@_cgen_""_handlers[] = \n{\n"" ""_"",\n""};\n\n"; Instruction table support.
|
74 |
|
|
; Return a declaration of an enum for all insns.
|
75 |
|
|
"Generating instruction enum ...\n""@arch@ instruction types""@ARCH@_INSN_""/* Index of `invalid' insn place holder. */\n""#define CGEN_INSN_INVALID @ARCH@_INSN_INVALID\n\n""/* Total number of insns in table. */\n""#define MAX_INSNS ((int) @ARCH@_INSN_"" + 1)\n\n"; Return a reference to the format table entry of INSN.
|
76 |
|
|
"& "; Return the definition of an instruction value entry.
|
77 |
|
|
"{ ""0x"; (ifmt-opcodes-beyond-base? (insn-ifmt insn))
|
78 |
|
|
", { "; ??? wip: opcode values beyond the base insn
|
79 |
|
|
"0 }"""" }"; Generate an insn opcode entry for INSN.
|
80 |
|
|
; ALL-ATTRS is a list of all instruction attributes.
|
81 |
|
|
; NUM-NON-BOOLS is the number of non-boolean insn attributes.
|
82 |
|
|
"/* "" */\n"" {\n"" "",\n"" ""MNEM""OP"",\n"; ??? 'twould save space to put a pointer here and record format separately
|
83 |
|
|
" "", ";"0x" (number->string (insn-value insn) 16) ",\n"
|
84 |
|
|
"\n"" },\n"; Generate insn table.
|
85 |
|
|
"Generating instruction opcode table ...\n""A(a) (1 << CGEN_INSN_""a)""OPERAND(op) @ARCH@_OPERAND_""op""\
|
86 |
|
|
#define MNEM CGEN_SYNTAX_MNEMONIC /* syntax value for mnemonic */
|
87 |
|
|
#define OP(field) CGEN_SYNTAX_MAKE_FIELD (OPERAND (field))
|
88 |
|
|
|
89 |
|
|
/* The instruction table. */
|
90 |
|
|
|
91 |
|
|
static const CGEN_OPCODE @arch@_cgen_insn_opcode_table[MAX_INSNS] =
|
92 |
|
|
|
93 |
|
|
/* Special null first entry.
|
94 |
|
|
A `num' value of zero is thus invalid.
|
95 |
|
|
|
96 |
|
|
{ { 0, 0, 0, 0 }, {{0}}, 0, {0}},\n""Generating insn opcode entry for "" ...\n""\
|
97 |
|
|
};
|
98 |
|
|
|
99 |
|
|
|
100 |
|
|
#undef OPERAND
|
101 |
|
|
#undef MNEM
|
102 |
|
|
#undef OP
|
103 |
|
|
|
104 |
|
|
"; Return assembly/disassembly hashing support.
|
105 |
|
|
"\
|
106 |
|
|
#ifndef CGEN_ASM_HASH_P
|
107 |
|
|
#define CGEN_ASM_HASH_P(insn) 1
|
108 |
|
|
#endif
|
109 |
|
|
|
110 |
|
|
#ifndef CGEN_DIS_HASH_P
|
111 |
|
|
#define CGEN_DIS_HASH_P(insn) 1
|
112 |
|
|
#endif
|
113 |
|
|
|
114 |
|
|
/* Return non-zero if INSN is to be added to the hash table.
|
115 |
|
|
|
116 |
|
|
|
117 |
|
|
static int
|
118 |
|
|
asm_hash_insn_p (insn)
|
119 |
|
|
const CGEN_INSN *insn ATTRIBUTE_UNUSED;
|
120 |
|
|
{
|
121 |
|
|
return CGEN_ASM_HASH_P (insn);
|
122 |
|
|
}
|
123 |
|
|
|
124 |
|
|
|
125 |
|
|
dis_hash_insn_p (insn)
|
126 |
|
|
const CGEN_INSN *insn;
|
127 |
|
|
{
|
128 |
|
|
/* If building the hash table and the NO-DIS attribute is present,
|
129 |
|
|
ignore. */
|
130 |
|
|
|
131 |
|
|
return 0;
|
132 |
|
|
|
133 |
|
|
}
|
134 |
|
|
|
135 |
|
|
|
136 |
|
|
#define CGEN_ASM_HASH_SIZE 127
|
137 |
|
|
#ifdef CGEN_MNEMONIC_OPERANDS
|
138 |
|
|
#define CGEN_ASM_HASH(mnem) (*(unsigned char *) (mnem) % CGEN_ASM_HASH_SIZE)
|
139 |
|
|
#else
|
140 |
|
|
#define CGEN_ASM_HASH(mnem) (*(unsigned char *) (mnem) % CGEN_ASM_HASH_SIZE) /*FIXME*/
|
141 |
|
|
#endif
|
142 |
|
|
#endif
|
143 |
|
|
|
144 |
|
|
|
145 |
|
|
but while this is under development we do.
|
146 |
|
|
BUFFER is a pointer to the bytes of the insn, target order.
|
147 |
|
|
VALUE is the first base_insn_bitsize bits as an int in host order. */
|
148 |
|
|
|
149 |
|
|
#ifndef CGEN_DIS_HASH
|
150 |
|
|
#define CGEN_DIS_HASH_SIZE 256
|
151 |
|
|
#define CGEN_DIS_HASH(buf, value) (*(unsigned char *) (buf))
|
152 |
|
|
#endif
|
153 |
|
|
|
154 |
|
|
/* The result is the hash value of the insn.
|
155 |
|
|
Targets are free to override CGEN_{ASM,DIS}_HASH in the .opc file. */
|
156 |
|
|
|
157 |
|
|
static unsigned int
|
158 |
|
|
asm_hash_insn (mnem)
|
159 |
|
|
const char * mnem;
|
160 |
|
|
{
|
161 |
|
|
return CGEN_ASM_HASH (mnem);
|
162 |
|
|
}
|
163 |
|
|
|
164 |
|
|
/* BUF is a pointer to the bytes of the insn, target order.
|
165 |
|
|
VALUE is the first base_insn_bitsize bits as an int in host order. */
|
166 |
|
|
|
167 |
|
|
static unsigned int
|
168 |
|
|
dis_hash_insn (buf, value)
|
169 |
|
|
const char * buf ATTRIBUTE_UNUSED;
|
170 |
|
|
CGEN_INSN_INT value ATTRIBUTE_UNUSED;
|
171 |
|
|
{
|
172 |
|
|
return CGEN_DIS_HASH (buf, value);
|
173 |
|
|
}
|
174 |
|
|
\n"; Hash support decls.
|
175 |
|
|
"\
|
176 |
|
|
|
177 |
|
|
the disassembler and vice versa. */
|
178 |
|
|
|
179 |
|
|
static int asm_hash_insn_p (const CGEN_INSN *);
|
180 |
|
|
static unsigned int asm_hash_insn (const char *);
|
181 |
|
|
static int dis_hash_insn_p (const CGEN_INSN *);
|
182 |
|
|
|
183 |
|
|
\n"; Macro insn support.
|
184 |
|
|
; Return a macro-insn expansion entry.
|
185 |
|
|
; FIXME: wip
|
186 |
|
|
|
187 |
|
|
; ??? wip, not currently used.
|
188 |
|
|
" /* "" */\n"" {\n"" ""-1, "; macro-insns are not currently enumerated, no current need to
|
189 |
|
|
"\"""\", ""\"""\",\n"" ""MNEM""OP"",\n"" (PTR) & macro_""_expansions[0],\n"" ""\n"" },\n"; Return a macro-insn opcode table entry.
|
190 |
|
|
; ??? wip, not currently used.
|
191 |
|
|
" /* "" */\n"" {\n"" ""-1, "; macro-insns are not currently enumerated, no current need to
|
192 |
|
|
"\"""\", ""\"""\",\n"" ""MNEM""OP"",\n"" (PTR) & macro_""_expansions[0],\n"" ""\n"" },\n"; Macro insn expansion has one basic form, but we optimize the common case
|
193 |
|
|
; of unconditionally expanding the input text to one instruction.
|
194 |
|
|
; The general form is a Scheme expression that is interpreted at runtime to
|
195 |
|
|
; decide how to perform the expansion. Yes, that means having a (perhaps
|
196 |
|
|
|
197 |
|
|
; Another thing to do is have a builder for each real insn so instead of
|
198 |
|
|
|
199 |
|
|
; expanded-to insn.
|
200 |
|
|
|
201 |
|
|
#define MNEM CGEN_SYNTAX_MNEMONIC /* syntax value for mnemonic */
|
202 |
|
|
#define OP(field) CGEN_SYNTAX_MAKE_FIELD (OPERAND (field))
|
203 |
|
|
|
204 |
|
|
/* The macro instruction table. */
|
205 |
|
|
|
206 |
|
|
static const CGEN_IBASE @arch@_cgen_macro_insn_table[] =
|
207 |
|
|
{
|
208 |
|
|
""Generating macro-insn table entry for "" ...\n"; Simple macro-insns are emitted as aliases of real insns.
|
209 |
|
|
"\
|
210 |
|
|
};
|
211 |
|
|
|
212 |
|
|
/* The macro instruction opcode table. */
|
213 |
|
|
|
214 |
|
|
static const CGEN_OPCODE @arch@_cgen_macro_insn_opcode_table[] =
|
215 |
|
|
{\n""Generating macro-insn table entry for "" ...\n"; Simple macro-insns are emitted as aliases of real insns.
|
216 |
|
|
|
217 |
|
|
};
|
218 |
|
|
|
219 |
|
|
#undef A
|
220 |
|
|
#undef OPERAND
|
221 |
|
|
#undef MNEM
|
222 |
|
|
#undef OP
|
223 |
|
|
\n"; Emit a function to call to initialize the opcode table.
|
224 |
|
|
"\
|
225 |
|
|
/* Set the recorded length of the insn in the CGEN_FIELDS struct. */
|
226 |
|
|
|
227 |
|
|
|
228 |
|
|
set_fields_bitsize (CGEN_FIELDS *fields, int size)
|
229 |
|
|
{
|
230 |
|
|
CGEN_FIELDS_BITSIZE (fields) = size;
|
231 |
|
|
}
|
232 |
|
|
|
233 |
|
|
/* Function to call before using the operand instance table.
|
234 |
|
|
This plugs the opcode entries and macro instructions into the cpu table. */
|
235 |
|
|
|
236 |
|
|
void
|
237 |
|
|
@arch@_cgen_init_opcode_table (CGEN_CPU_DESC cd)
|
238 |
|
|
{
|
239 |
|
|
int i;
|
240 |
|
|
int num_macros = (sizeof (@arch@_cgen_macro_insn_table) /
|
241 |
|
|
sizeof (@arch@_cgen_macro_insn_table[0]));
|
242 |
|
|
const CGEN_IBASE *ib = & @arch@_cgen_macro_insn_table[0];
|
243 |
|
|
|
244 |
|
|
CGEN_INSN *insns = xmalloc (num_macros * sizeof (CGEN_INSN));
|
245 |
|
|
|
246 |
|
|
/* This test has been added to avoid a warning generated
|
247 |
|
|
if memset is called with a third argument of value zero. */
|
248 |
|
|
|
249 |
|
|
memset (insns, 0, num_macros * sizeof (CGEN_INSN));
|
250 |
|
|
for (i = 0; i < num_macros; ++i)
|
251 |
|
|
|
252 |
|
|
insns[i].base = &ib[i];
|
253 |
|
|
insns[i].opcode = &oc[i];
|
254 |
|
|
@arch@_cgen_build_insn_regex (& insns[i]);
|
255 |
|
|
}
|
256 |
|
|
cd->macro_insn_table.init_entries = insns;
|
257 |
|
|
cd->macro_insn_table.entry_size = sizeof (CGEN_IBASE);
|
258 |
|
|
cd->macro_insn_table.num_init_entries = num_macros;
|
259 |
|
|
|
260 |
|
|
oc = & @arch@_cgen_insn_opcode_table[0];
|
261 |
|
|
insns = (CGEN_INSN *) cd->insn_table.init_entries;
|
262 |
|
|
for (i = 0; i < MAX_INSNS; ++i)
|
263 |
|
|
|
264 |
|
|
insns[i].opcode = &oc[i];
|
265 |
|
|
@arch@_cgen_build_insn_regex (& insns[i]);
|
266 |
|
|
}
|
267 |
|
|
|
268 |
|
|
|
269 |
|
|
cd->set_fields_bitsize = set_fields_bitsize;
|
270 |
|
|
|
271 |
|
|
cd->asm_hash_p = asm_hash_insn_p;
|
272 |
|
|
cd->asm_hash = asm_hash_insn;
|
273 |
|
|
cd->asm_hash_size = CGEN_ASM_HASH_SIZE;
|
274 |
|
|
|
275 |
|
|
cd->dis_hash_p = dis_hash_insn_p;
|
276 |
|
|
|
277 |
|
|
cd->dis_hash_size = CGEN_DIS_HASH_SIZE;
|
278 |
|
|
}
|
279 |
|
|
|
280 |
|
|
; FIXME: Create enum objects for all the enums we explicitly declare here.
|
281 |
|
|
|
282 |
|
|
"Generating ""-opc.h ...\n""Instruction opcode header for @arch@.""\
|
283 |
|
|
#ifndef @ARCH@_OPC_H
|
284 |
|
|
#define @ARCH@_OPC_H
|
285 |
|
|
|
286 |
|
|
""
|
287 |
|
|
|
288 |
|
|
#endif /* @ARCH@_OPC_H */
|
289 |
|
|
"; This file contains the instruction opcode table.
|
290 |
|
|
"Generating ""-opc.c ...\n""Instruction opcode table for @arch@.""\
|
291 |
|
|
#include \"sysdep.h\"
|
292 |
|
|
#include \"ansidecl.h\"
|
293 |
|
|
|
294 |
|
|
#include \"symcat.h\"
|
295 |
|
|
|
296 |
|
|
#include \"@prefix@-opc.h\"
|
297 |
|
|
|
298 |
|
|
\n"
|