Commit | Line | Data |
---|---|---|
df8b2c02 DE |
1 | /* Header file for targets using CGEN: Cpu tools GENerator. |
2 | ||
19d45995 | 3 | Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. |
df8b2c02 DE |
4 | |
5 | This file is part of GDB, the GNU debugger, and the GNU Binutils. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
19d45995 DE |
17 | You should have received a copy of the GNU General Public License along |
18 | with this program; if not, write to the Free Software Foundation, Inc., | |
19 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
df8b2c02 DE |
20 | |
21 | #ifndef CGEN_H | |
22 | #define CGEN_H | |
23 | ||
24 | #ifndef CGEN_CAT3 | |
25 | #if defined(__STDC__) || defined(ALMOST_STDC) | |
26 | #define CGEN_XCAT3(a,b,c) a ## b ## c | |
27 | #define CGEN_CAT3(a,b,c) CGEN_XCAT3 (a, b, c) | |
28 | #else | |
29 | #define CGEN_CAT3(a,b,c) a/**/b/**/c | |
30 | #endif | |
31 | #endif | |
32 | ||
33 | /* Prepend the cpu name, defined in cpu-opc.h, and _cgen_ to symbol S. | |
34 | The lack of spaces in the arg list is important for non-stdc systems. | |
35 | This file is included by <cpu>-opc.h. | |
36 | It can be included independently of cpu-opc.h, in which case the cpu | |
37 | dependent portions will be declared as "unknown_cgen_foo". */ | |
38 | ||
39 | #ifndef CGEN_SYM | |
40 | #define CGEN_SYM(s) CGEN_CAT3 (unknown,_cgen_,s) | |
41 | #endif | |
42 | ||
43 | /* This file contains the static (unchanging) pieces and as much other stuff | |
44 | as we can reasonably put here. It's generally cleaner to put stuff here | |
45 | rather than having it machine generated if possible. */ | |
46 | ||
47 | /* The assembler syntax is made up of expressions (duh...). | |
48 | At the lowest level the values are mnemonics, register names, numbers, etc. | |
49 | Above that are subexpressions, if any (an example might be the | |
50 | "effective address" in m68k cpus). At the second highest level are the | |
51 | insns themselves. Above that are pseudo-insns, synthetic insns, and macros, | |
52 | if any. | |
53 | */ | |
54 | \f | |
55 | /* Lots of cpu's have a fixed insn size, or one which rarely changes, | |
56 | and it's generally easier to handle these by treating the insn as an | |
57 | integer type, rather than an array of characters. So we allow targets | |
58 | to control this. */ | |
59 | ||
60 | #ifdef CGEN_INT_INSN | |
61 | typedef unsigned int cgen_insn_t; | |
62 | #else | |
b61df026 | 63 | typedef char * cgen_insn_t; |
df8b2c02 DE |
64 | #endif |
65 | ||
66 | #ifdef __GNUC__ | |
67 | #define CGEN_INLINE inline | |
68 | #else | |
69 | #define CGEN_INLINE | |
70 | #endif | |
71 | ||
72 | /* Perhaps we should just use bfd.h, but it's not clear | |
73 | one would want to require that yet. */ | |
b61df026 NC |
74 | enum cgen_endian |
75 | { | |
df8b2c02 DE |
76 | CGEN_ENDIAN_UNKNOWN, |
77 | CGEN_ENDIAN_LITTLE, | |
78 | CGEN_ENDIAN_BIG | |
79 | }; | |
80 | \f | |
81 | /* Attributes. | |
82 | Attributes are used to describe various random things. */ | |
83 | ||
84 | /* Struct to record attribute information. */ | |
b61df026 NC |
85 | typedef struct |
86 | { | |
19d45995 | 87 | unsigned char num_nonbools; |
df8b2c02 DE |
88 | unsigned int bool; |
89 | unsigned int nonbool[1]; | |
90 | } CGEN_ATTR; | |
91 | ||
92 | /* Define a structure member for attributes with N non-boolean entries. | |
93 | The attributes are sorted so that the non-boolean ones come first. | |
94 | num_nonbools: count of nonboolean attributes | |
95 | bool: values of boolean attributes | |
96 | nonbool: values of non-boolean attributes | |
97 | There is a maximum of 32 attributes total. */ | |
98 | #define CGEN_ATTR_TYPE(n) \ | |
19d45995 | 99 | const struct { unsigned char num_nonbools; \ |
df8b2c02 DE |
100 | unsigned int bool; \ |
101 | unsigned int nonbool[(n) ? (n) : 1]; } | |
102 | ||
103 | /* Given an attribute number, return its mask. */ | |
104 | #define CGEN_ATTR_MASK(attr) (1 << (attr)) | |
105 | ||
106 | /* Return value of attribute ATTR in ATTR_TABLE for OBJ. | |
107 | OBJ is a pointer to the entity that has the attributes. | |
108 | It's not used at present but is reserved for future purposes. */ | |
109 | #define CGEN_ATTR_VALUE(obj, attr_table, attr) \ | |
110 | ((unsigned int) (attr) < (attr_table)->num_nonbools \ | |
111 | ? ((attr_table)->nonbool[attr]) \ | |
112 | : (((attr_table)->bool & (1 << (attr))) != 0)) | |
19d45995 DE |
113 | |
114 | /* Attribute name/value tables. | |
115 | These are used to assist parsing of descriptions at runtime. */ | |
116 | ||
b61df026 NC |
117 | typedef struct |
118 | { | |
119 | const char * name; | |
120 | int value; | |
19d45995 DE |
121 | } CGEN_ATTR_ENTRY; |
122 | ||
123 | /* For each domain (fld,operand,insn), list of attributes. */ | |
124 | ||
b61df026 NC |
125 | typedef struct |
126 | { | |
127 | const char * name; | |
19d45995 | 128 | /* NULL for boolean attributes. */ |
b61df026 | 129 | const CGEN_ATTR_ENTRY * vals; |
19d45995 | 130 | } CGEN_ATTR_TABLE; |
df8b2c02 DE |
131 | \f |
132 | /* Parse result (also extraction result). | |
133 | ||
134 | The result of parsing an insn is stored here. | |
135 | To generate the actual insn, this is passed to the insert handler. | |
136 | When printing an insn, the result of extraction is stored here. | |
137 | To print the insn, this is passed to the print handler. | |
138 | ||
139 | It is machine generated so we don't define it here, | |
140 | but we do need a forward decl for the handler fns. | |
141 | ||
142 | There is one member for each possible field in the insn. | |
143 | The type depends on the field. | |
144 | Also recorded here is the computed length of the insn for architectures | |
145 | where it varies. | |
146 | */ | |
147 | ||
42d56c40 | 148 | typedef struct cgen_fields CGEN_FIELDS; |
df8b2c02 DE |
149 | |
150 | /* Total length of the insn, as recorded in the `fields' struct. */ | |
151 | /* ??? The field insert handler has lots of opportunities for optimization | |
152 | if it ever gets inlined. On architectures where insns all have the same | |
153 | size, may wish to detect that and make this macro a constant - to allow | |
154 | further optimizations. */ | |
155 | #define CGEN_FIELDS_BITSIZE(fields) ((fields)->length) | |
156 | \f | |
157 | /* Associated with each insn or expression is a set of "handlers" for | |
158 | performing operations like parsing, printing, etc. */ | |
159 | ||
160 | /* Forward decl. */ | |
161 | typedef struct cgen_insn CGEN_INSN; | |
162 | ||
163 | /* Parse handler. | |
164 | The first argument is a pointer to a struct describing the insn being | |
165 | parsed. | |
166 | The second argument is a pointer to a pointer to the text being parsed. | |
167 | The third argument is a pointer to a cgen_fields struct | |
168 | in which the results are placed. | |
169 | If the expression is successfully parsed, the pointer to the text is | |
170 | updated. If not it is left alone. | |
171 | The result is NULL if success or an error message. */ | |
172 | typedef const char * (cgen_parse_fn) PARAMS ((const struct cgen_insn *, | |
173 | const char **, | |
42d56c40 | 174 | CGEN_FIELDS *)); |
df8b2c02 DE |
175 | |
176 | /* Print handler. | |
177 | The first argument is a pointer to the disassembly info. | |
178 | Eg: disassemble_info. It's defined as `PTR' so this file can be included | |
179 | without dis-asm.h. | |
180 | The second argument is a pointer to a struct describing the insn being | |
181 | printed. | |
182 | The third argument is a pointer to a cgen_fields struct. | |
183 | The fourth argument is the pc value of the insn. | |
184 | The fifth argument is the length of the insn, in bytes. */ | |
185 | /* Don't require bfd.h unnecessarily. */ | |
186 | #ifdef BFD_VERSION | |
187 | typedef void (cgen_print_fn) PARAMS ((PTR, const struct cgen_insn *, | |
42d56c40 | 188 | CGEN_FIELDS *, bfd_vma, int)); |
df8b2c02 DE |
189 | #else |
190 | typedef void (cgen_print_fn) (); | |
191 | #endif | |
192 | ||
193 | /* Insert handler. | |
194 | The first argument is a pointer to a struct describing the insn being | |
195 | parsed. | |
196 | The second argument is a pointer to a cgen_fields struct | |
197 | from which the values are fetched. | |
198 | The third argument is a pointer to a buffer in which to place the insn. */ | |
199 | typedef void (cgen_insert_fn) PARAMS ((const struct cgen_insn *, | |
42d56c40 | 200 | CGEN_FIELDS *, cgen_insn_t *)); |
df8b2c02 DE |
201 | |
202 | /* Extract handler. | |
203 | The first argument is a pointer to a struct describing the insn being | |
204 | parsed. | |
205 | The second argument is a pointer to a struct controlling extraction | |
206 | (only used for variable length insns). | |
207 | The third argument is the first CGEN_BASE_INSN_SIZE bytes. | |
208 | The fourth argument is a pointer to a cgen_fields struct | |
209 | in which the results are placed. | |
210 | The result is the length of the insn or zero if not recognized. */ | |
211 | typedef int (cgen_extract_fn) PARAMS ((const struct cgen_insn *, | |
212 | void *, cgen_insn_t, | |
42d56c40 | 213 | CGEN_FIELDS *)); |
df8b2c02 DE |
214 | |
215 | /* The `parse' and `insert' fields are indices into these tables. | |
216 | The elements are pointer to specialized handler functions. | |
217 | Element 0 is special, it means use the default handler. */ | |
218 | extern cgen_parse_fn * CGEN_SYM (parse_handlers) []; | |
219 | #define CGEN_PARSE_FN(x) (CGEN_SYM (parse_handlers)[(x)->base.parse]) | |
220 | extern cgen_insert_fn * CGEN_SYM (insert_handlers) []; | |
221 | #define CGEN_INSERT_FN(x) (CGEN_SYM (insert_handlers)[(x)->base.insert]) | |
222 | ||
223 | /* Likewise for the `extract' and `print' fields. */ | |
224 | extern cgen_extract_fn * CGEN_SYM (extract_handlers) []; | |
225 | #define CGEN_EXTRACT_FN(x) (CGEN_SYM (extract_handlers)[(x)->base.extract]) | |
226 | extern cgen_print_fn * CGEN_SYM (print_handlers) []; | |
227 | #define CGEN_PRINT_FN(x) (CGEN_SYM (print_handlers)[(x)->base.print]) | |
228 | \f | |
229 | /* Base class of parser/printer. | |
19d45995 DE |
230 | (Don't read too much into the use of the phrase "base class". |
231 | It's a name I'm using to organize my thoughts.) | |
df8b2c02 DE |
232 | |
233 | Instructions and expressions all share this data in common. | |
19d45995 DE |
234 | It's a collection of the common elements needed to parse, insert, extract, |
235 | and print each of them. */ | |
df8b2c02 | 236 | |
42d56c40 DE |
237 | #ifndef CGEN_INSN_MAX_ATTRS |
238 | #define CGEN_INSN_MAX_ATTRS 1 | |
df8b2c02 DE |
239 | #endif |
240 | ||
b61df026 NC |
241 | struct cgen_base |
242 | { | |
df8b2c02 DE |
243 | /* Indices into the handler tables. |
244 | We could use pointers here instead, but in the case of the insn table, | |
245 | 90% of them would be identical and that's a lot of redundant data. | |
246 | 0 means use the default (what the default is is up to the code). */ | |
247 | unsigned char parse, insert, extract, print; | |
df8b2c02 DE |
248 | }; |
249 | \f | |
19d45995 | 250 | /* Assembler interface. |
df8b2c02 | 251 | |
19d45995 DE |
252 | The interface to the assembler is intended to be clean in the sense that |
253 | libopcodes.a is a standalone entity and could be used with any assembler. | |
254 | Not that one would necessarily want to do that but rather that it helps | |
255 | keep a clean interface. The interface will obviously be slanted towards | |
256 | GAS, but at least it's a start. | |
df8b2c02 | 257 | |
19d45995 DE |
258 | Parsing is controlled by the assembler which calls |
259 | CGEN_SYM (assemble_insn). If it can parse and build the entire insn | |
260 | it doesn't call back to the assembler. If it needs/wants to call back | |
261 | to the assembler, (*cgen_parse_operand_fn) is called which can either | |
df8b2c02 | 262 | |
19d45995 DE |
263 | - return a number to be inserted in the insn |
264 | - return a "register" value to be inserted | |
265 | (the register might not be a register per pe) | |
266 | - queue the argument and return a marker saying the expression has been | |
267 | queued (eg: a fix-up) | |
268 | - return an error message indicating the expression wasn't recognizable | |
269 | ||
270 | The result is an error message or NULL for success. | |
271 | The parsed value is stored in the bfd_vma *. */ | |
df8b2c02 | 272 | |
19d45995 | 273 | /* Values for indicating what the caller wants. */ |
b61df026 NC |
274 | enum cgen_parse_operand_type |
275 | { | |
276 | CGEN_PARSE_OPERAND_INIT, | |
277 | CGEN_PARSE_OPERAND_INTEGER, | |
19d45995 DE |
278 | CGEN_PARSE_OPERAND_ADDRESS |
279 | }; | |
df8b2c02 | 280 | |
19d45995 DE |
281 | /* Values for indicating what was parsed. |
282 | ??? Not too useful at present but in time. */ | |
b61df026 NC |
283 | enum cgen_parse_operand_result |
284 | { | |
285 | CGEN_PARSE_OPERAND_RESULT_NUMBER, | |
286 | CGEN_PARSE_OPERAND_RESULT_REGISTER, | |
287 | CGEN_PARSE_OPERAND_RESULT_QUEUED, | |
288 | CGEN_PARSE_OPERAND_RESULT_ERROR | |
19d45995 | 289 | }; |
df8b2c02 | 290 | |
19d45995 DE |
291 | /* Don't require bfd.h unnecessarily. */ |
292 | #ifdef BFD_VERSION | |
293 | extern const char * (*cgen_parse_operand_fn) | |
294 | PARAMS ((enum cgen_parse_operand_type, const char **, int, int, | |
295 | enum cgen_parse_operand_result *, bfd_vma *)); | |
df8b2c02 DE |
296 | #endif |
297 | ||
19d45995 DE |
298 | /* Called before trying to match a table entry with the insn. */ |
299 | void cgen_init_parse_operand PARAMS ((void)); | |
df8b2c02 | 300 | |
19d45995 | 301 | /* Called from <cpu>-asm.c to initialize operand parsing. */ |
df8b2c02 | 302 | |
19d45995 DE |
303 | /* These are GAS specific. They're not here as part of the interface, |
304 | but rather that we need to put them somewhere. */ | |
df8b2c02 | 305 | |
19d45995 DE |
306 | /* Call this from md_assemble to initialize the assembler callback. */ |
307 | void cgen_asm_init_parse PARAMS ((void)); | |
df8b2c02 | 308 | |
19d45995 DE |
309 | /* Don't require bfd.h unnecessarily. */ |
310 | #ifdef BFD_VERSION | |
311 | /* The result is an error message or NULL for success. | |
312 | The parsed value is stored in the bfd_vma *. */ | |
810d9833 | 313 | const char * cgen_parse_operand PARAMS ((enum cgen_parse_operand_type, |
42d56c40 DE |
314 | const char **, int, int, |
315 | enum cgen_parse_operand_result *, | |
316 | bfd_vma *)); | |
19d45995 DE |
317 | #endif |
318 | ||
a0f40e47 NC |
319 | void cgen_save_fixups PARAMS ((void)); |
320 | void cgen_restore_fixups PARAMS ((void)); | |
321 | void cgen_swap_fixups PARAMS ((void)); | |
810d9833 | 322 | |
19d45995 DE |
323 | /* Add a register to the assembler's hash table. |
324 | This makes lets GAS parse registers for us. | |
325 | ??? This isn't currently used, but it could be in the future. */ | |
326 | void cgen_asm_record_register PARAMS ((char *, int)); | |
327 | ||
328 | /* After CGEN_SYM (assemble_insn) is done, this is called to | |
810d9833 NC |
329 | output the insn and record any fixups. The address of the |
330 | assembled instruction is returned in case it is needed by | |
331 | the caller. */ | |
332 | char * cgen_asm_finish_insn PARAMS ((const struct cgen_insn *, cgen_insn_t *, | |
19d45995 | 333 | unsigned int)); |
df8b2c02 DE |
334 | \f |
335 | /* Operand values (keywords, integers, symbols, etc.) */ | |
336 | ||
337 | /* Types of assembler elements. */ | |
338 | ||
b61df026 NC |
339 | enum cgen_asm_type |
340 | { | |
df8b2c02 DE |
341 | CGEN_ASM_KEYWORD, CGEN_ASM_MAX |
342 | }; | |
343 | ||
344 | /* List of hardware elements. */ | |
345 | ||
b61df026 NC |
346 | typedef struct cgen_hw_entry |
347 | { | |
42d56c40 DE |
348 | /* The type of this entry, one of `enum hw_type'. |
349 | This is an int and not the enum as the latter may not be declared yet. */ | |
350 | int type; | |
351 | const struct cgen_hw_entry * next; | |
352 | char * name; | |
353 | enum cgen_asm_type asm_type; | |
354 | PTR asm_data; | |
df8b2c02 DE |
355 | } CGEN_HW_ENTRY; |
356 | ||
42d56c40 | 357 | const CGEN_HW_ENTRY * cgen_hw_lookup PARAMS ((const char *)); |
df8b2c02 | 358 | |
42d56c40 DE |
359 | #ifndef CGEN_KEYWORD_MAX_ATTRS |
360 | #define CGEN_KEYWORD_MAX_ATTRS 1 | |
df8b2c02 DE |
361 | #endif |
362 | ||
363 | /* This struct is used to describe things like register names, etc. */ | |
364 | ||
b61df026 NC |
365 | typedef struct cgen_keyword_entry |
366 | { | |
df8b2c02 | 367 | /* Name (as in register name). */ |
b61df026 | 368 | char * name; |
df8b2c02 DE |
369 | |
370 | /* Value (as in register number). | |
371 | The value cannot be -1 as that is used to indicate "not found". | |
372 | IDEA: Have "FUNCTION" attribute? [function is called to fetch value]. */ | |
373 | int value; | |
374 | ||
19d45995 DE |
375 | /* Attributes. |
376 | This should, but technically needn't, appear last. It is a variable sized | |
377 | array in that one architecture may have 1 nonbool attribute and another | |
378 | may have more. Having this last means the non-architecture specific code | |
379 | needn't care. */ | |
380 | /* ??? Moving this last should be done by treating keywords like insn lists | |
381 | and moving the `next' fields into a CGEN_KEYWORD_LIST struct. */ | |
df8b2c02 | 382 | /* FIXME: Not used yet. */ |
42d56c40 | 383 | CGEN_ATTR_TYPE (CGEN_KEYWORD_MAX_ATTRS) attrs; |
df8b2c02 DE |
384 | |
385 | /* Next name hash table entry. */ | |
386 | struct cgen_keyword_entry *next_name; | |
387 | /* Next value hash table entry. */ | |
388 | struct cgen_keyword_entry *next_value; | |
389 | } CGEN_KEYWORD_ENTRY; | |
390 | ||
391 | /* Top level struct for describing a set of related keywords | |
392 | (e.g. register names). | |
393 | ||
394 | This struct supports runtime entry of new values, and hashed lookups. */ | |
395 | ||
b61df026 NC |
396 | typedef struct cgen_keyword |
397 | { | |
df8b2c02 | 398 | /* Pointer to initial [compiled in] values. */ |
b61df026 NC |
399 | CGEN_KEYWORD_ENTRY * init_entries; |
400 | ||
df8b2c02 DE |
401 | /* Number of entries in `init_entries'. */ |
402 | unsigned int num_init_entries; | |
b61df026 | 403 | |
df8b2c02 | 404 | /* Hash table used for name lookup. */ |
b61df026 NC |
405 | CGEN_KEYWORD_ENTRY ** name_hash_table; |
406 | ||
df8b2c02 | 407 | /* Hash table used for value lookup. */ |
b61df026 NC |
408 | CGEN_KEYWORD_ENTRY ** value_hash_table; |
409 | ||
df8b2c02 DE |
410 | /* Number of entries in the hash_tables. */ |
411 | unsigned int hash_table_size; | |
b61df026 | 412 | |
19d45995 | 413 | /* Pointer to null keyword "" entry if present. */ |
b61df026 | 414 | const CGEN_KEYWORD_ENTRY * null_entry; |
df8b2c02 DE |
415 | } CGEN_KEYWORD; |
416 | ||
417 | /* Structure used for searching. */ | |
418 | ||
b61df026 NC |
419 | typedef struct |
420 | { | |
df8b2c02 | 421 | /* Table being searched. */ |
b61df026 NC |
422 | const CGEN_KEYWORD * table; |
423 | ||
df8b2c02 | 424 | /* Specification of what is being searched for. */ |
b61df026 NC |
425 | const char * spec; |
426 | ||
df8b2c02 DE |
427 | /* Current index in hash table. */ |
428 | unsigned int current_hash; | |
b61df026 | 429 | |
df8b2c02 | 430 | /* Current element in current hash chain. */ |
b61df026 | 431 | CGEN_KEYWORD_ENTRY * current_entry; |
df8b2c02 DE |
432 | } CGEN_KEYWORD_SEARCH; |
433 | ||
434 | /* Lookup a keyword from its name. */ | |
19d45995 DE |
435 | const CGEN_KEYWORD_ENTRY * cgen_keyword_lookup_name |
436 | PARAMS ((CGEN_KEYWORD *, const char *)); | |
df8b2c02 | 437 | /* Lookup a keyword from its value. */ |
19d45995 DE |
438 | const CGEN_KEYWORD_ENTRY * cgen_keyword_lookup_value |
439 | PARAMS ((CGEN_KEYWORD *, int)); | |
df8b2c02 | 440 | /* Add a keyword. */ |
19d45995 | 441 | void cgen_keyword_add PARAMS ((CGEN_KEYWORD *, CGEN_KEYWORD_ENTRY *)); |
df8b2c02 DE |
442 | /* Keyword searching. |
443 | This can be used to retrieve every keyword, or a subset. */ | |
19d45995 DE |
444 | CGEN_KEYWORD_SEARCH cgen_keyword_search_init |
445 | PARAMS ((CGEN_KEYWORD *, const char *)); | |
446 | const CGEN_KEYWORD_ENTRY *cgen_keyword_search_next | |
447 | PARAMS ((CGEN_KEYWORD_SEARCH *)); | |
df8b2c02 DE |
448 | |
449 | /* Operand value support routines. */ | |
450 | /* FIXME: some of the long's here will need to be bfd_vma or some such. */ | |
451 | ||
452 | const char * cgen_parse_keyword PARAMS ((const char **, | |
19d45995 | 453 | CGEN_KEYWORD *, |
df8b2c02 DE |
454 | long *)); |
455 | const char * cgen_parse_signed_integer PARAMS ((const char **, int, | |
456 | long, long, long *)); | |
457 | const char * cgen_parse_unsigned_integer PARAMS ((const char **, int, | |
458 | unsigned long, unsigned long, | |
459 | unsigned long *)); | |
19d45995 DE |
460 | const char * cgen_parse_address PARAMS ((const char **, int, int, |
461 | enum cgen_parse_operand_result *, | |
462 | long *)); | |
df8b2c02 DE |
463 | const char * cgen_validate_signed_integer PARAMS ((long, long, long)); |
464 | const char * cgen_validate_unsigned_integer PARAMS ((unsigned long, | |
465 | unsigned long, | |
466 | unsigned long)); | |
467 | \f | |
42d56c40 DE |
468 | /* Operand modes. */ |
469 | ||
470 | /* ??? This duplicates the values in arch.h. Revisit. | |
471 | These however need the CGEN_ prefix [as does everything in this file]. */ | |
472 | /* ??? Targets may need to add their own modes so we may wish to move this | |
473 | to <arch>-opc.h, or add a hook. */ | |
474 | ||
475 | enum cgen_mode { | |
476 | CGEN_MODE_VOID, /* FIXME: rename simulator's VM to VOID */ | |
477 | CGEN_MODE_BI, CGEN_MODE_QI, CGEN_MODE_HI, CGEN_MODE_SI, CGEN_MODE_DI, | |
478 | CGEN_MODE_UBI, CGEN_MODE_UQI, CGEN_MODE_UHI, CGEN_MODE_USI, CGEN_MODE_UDI, | |
479 | CGEN_MODE_SF, CGEN_MODE_DF, CGEN_MODE_XF, CGEN_MODE_TF, | |
480 | CGEN_MODE_MAX | |
481 | }; | |
482 | ||
483 | /* FIXME: Until simulator is updated. */ | |
484 | #define CGEN_MODE_VM CGEN_MODE_VOID | |
485 | \f | |
df8b2c02 DE |
486 | /* This struct defines each entry in the operand table. */ |
487 | ||
42d56c40 DE |
488 | #ifndef CGEN_OPERAND_MAX_ATTRS |
489 | #define CGEN_OPERAND_MAX_ATTRS 1 | |
df8b2c02 DE |
490 | #endif |
491 | ||
b61df026 NC |
492 | typedef struct cgen_operand |
493 | { | |
19d45995 | 494 | /* Name as it appears in the syntax string. */ |
b61df026 | 495 | char * name; |
df8b2c02 | 496 | |
42d56c40 DE |
497 | /* The hardware element associated with this operand. */ |
498 | const CGEN_HW_ENTRY *hw; | |
499 | ||
500 | /* FIXME: We don't yet record ifield definitions, which we should. | |
501 | When we do it might make sense to delete start/length (since they will | |
502 | be duplicated in the ifield's definition) and replace them with a | |
503 | pointer to the ifield entry. Note that as more complicated situations | |
504 | need to be handled, going more and more with an OOP paradigm will help | |
505 | keep the complication under control. Of course, this was the goal from | |
506 | the start, but getting there in one step was too much too soon. */ | |
507 | ||
df8b2c02 | 508 | /* Bit position (msb of first byte = bit 0). |
19d45995 | 509 | This is just a hint, and may be unused in more complex operands. |
df8b2c02 DE |
510 | May be unused for a modifier. */ |
511 | unsigned char start; | |
512 | ||
513 | /* The number of bits in the operand. | |
19d45995 | 514 | This is just a hint, and may be unused in more complex operands. |
df8b2c02 DE |
515 | May be unused for a modifier. */ |
516 | unsigned char length; | |
517 | ||
19d45995 DE |
518 | #if 0 /* ??? Interesting idea but relocs tend to get too complicated, |
519 | and ABI dependent, for simple table lookups to work. */ | |
df8b2c02 DE |
520 | /* Ideally this would be the internal (external?) reloc type. */ |
521 | int reloc_type; | |
522 | #endif | |
19d45995 DE |
523 | |
524 | /* Attributes. | |
525 | This should, but technically needn't, appear last. It is a variable sized | |
526 | array in that one architecture may have 1 nonbool attribute and another | |
527 | may have more. Having this last means the non-architecture specific code | |
528 | needn't care, now or tomorrow. */ | |
42d56c40 | 529 | CGEN_ATTR_TYPE (CGEN_OPERAND_MAX_ATTRS) attrs; |
19d45995 | 530 | #define CGEN_OPERAND_ATTRS(operand) (&(operand)->attrs) |
df8b2c02 DE |
531 | } CGEN_OPERAND; |
532 | ||
533 | /* Return value of attribute ATTR in OPERAND. */ | |
534 | #define CGEN_OPERAND_ATTR(operand, attr) \ | |
535 | CGEN_ATTR_VALUE (operand, CGEN_OPERAND_ATTRS (operand), attr) | |
536 | ||
537 | /* The operand table is currently a very static entity. */ | |
538 | extern const CGEN_OPERAND CGEN_SYM (operand_table)[]; | |
539 | ||
540 | enum cgen_operand_type; | |
541 | ||
542 | #define CGEN_OPERAND_INDEX(operand) ((int) ((operand) - CGEN_SYM (operand_table))) | |
543 | /* FIXME: Rename, cpu-opc.h defines this as the typedef of the enum. */ | |
544 | #define CGEN_OPERAND_TYPE(operand) ((enum cgen_operand_type) CGEN_OPERAND_INDEX (operand)) | |
545 | #define CGEN_OPERAND_ENTRY(n) (& CGEN_SYM (operand_table) [n]) | |
546 | \f | |
42d56c40 DE |
547 | /* Instruction operand instances. |
548 | ||
549 | For each instruction, a list of the hardware elements that are read and | |
550 | written are recorded. */ | |
551 | ||
552 | /* The type of the instance. */ | |
553 | enum cgen_operand_instance_type { | |
554 | /* End of table marker. */ | |
555 | CGEN_OPERAND_INSTANCE_END = 0, | |
556 | CGEN_OPERAND_INSTANCE_INPUT, CGEN_OPERAND_INSTANCE_OUTPUT | |
557 | }; | |
558 | ||
559 | typedef struct | |
560 | { | |
561 | /* The type of this operand. */ | |
562 | enum cgen_operand_instance_type type; | |
563 | #define CGEN_OPERAND_INSTANCE_TYPE(opinst) ((opinst)->type) | |
564 | ||
565 | /* The hardware element referenced. */ | |
566 | const CGEN_HW_ENTRY *hw; | |
567 | #define CGEN_OPERAND_INSTANCE_HW(opinst) ((opinst)->hw) | |
568 | ||
569 | /* The mode in which the operand is being used. */ | |
570 | enum cgen_mode mode; | |
571 | #define CGEN_OPERAND_INSTANCE_MODE(opinst) ((opinst)->mode) | |
572 | ||
573 | /* The operand table entry or NULL if there is none (i.e. an explicit | |
574 | hardware reference). */ | |
575 | const CGEN_OPERAND *operand; | |
576 | #define CGEN_OPERAND_INSTANCE_OPERAND(opinst) ((opinst)->operand) | |
577 | ||
578 | /* If `operand' is NULL, the index (e.g. into array of registers). */ | |
579 | int index; | |
580 | #define CGEN_OPERAND_INSTANCE_INDEX(opinst) ((opinst)->index) | |
581 | } CGEN_OPERAND_INSTANCE; | |
582 | \f | |
19d45995 DE |
583 | /* Syntax string. |
584 | ||
585 | Each insn format and subexpression has one of these. | |
586 | ||
587 | The syntax "string" consists of characters (n > 0 && n < 128), and operand | |
588 | values (n >= 128), and is terminated by 0. Operand values are 128 + index | |
589 | into the operand table. The operand table doesn't exist in C, per se, as | |
590 | the data is recorded in the parse/insert/extract/print switch statements. */ | |
591 | ||
592 | #ifndef CGEN_MAX_SYNTAX_BYTES | |
593 | #define CGEN_MAX_SYNTAX_BYTES 16 | |
594 | #endif | |
595 | ||
b61df026 NC |
596 | typedef struct |
597 | { | |
19d45995 DE |
598 | unsigned char syntax[CGEN_MAX_SYNTAX_BYTES]; |
599 | } CGEN_SYNTAX; | |
600 | ||
601 | #define CGEN_SYNTAX_STRING(syn) (syn->syntax) | |
602 | #define CGEN_SYNTAX_CHAR_P(c) ((c) < 128) | |
603 | #define CGEN_SYNTAX_CHAR(c) (c) | |
604 | #define CGEN_SYNTAX_FIELD(c) ((c) - 128) | |
605 | ||
606 | /* ??? I can't currently think of any case where the mnemonic doesn't come | |
607 | first [and if one ever doesn't building the hash tables will be tricky]. | |
608 | However, we treat mnemonics as just another operand of the instruction. | |
609 | A value of 1 means "this is where the mnemonic appears". 1 isn't | |
610 | special other than it's a non-printable ASCII char. */ | |
611 | #define CGEN_SYNTAX_MNEMONIC_P(ch) ((ch) == 1) | |
612 | \f | |
613 | /* Instruction formats. | |
614 | ||
615 | Instructions are grouped by format. Associated with an instruction is its | |
616 | format. Each opcode table entry contains a pointer into the format table. | |
617 | This cuts down on the size of the opcode table as there are relatively few | |
618 | formats compared with the number of instructions. */ | |
619 | ||
b61df026 NC |
620 | typedef struct |
621 | { | |
19d45995 DE |
622 | /* Length that MASK and VALUE have been calculated to |
623 | [VALUE is recorded elsewhere]. | |
624 | Normally it is CGEN_BASE_INSN_BITSIZE. On [V]LIW architectures where | |
625 | the base insn size may be larger than the size of an insn, this field is | |
626 | less than CGEN_BASE_INSN_BITSIZE. */ | |
627 | unsigned char mask_length; | |
628 | ||
629 | /* Total length of instruction. */ | |
630 | unsigned char length; | |
631 | ||
632 | /* Mask to apply to the first BASE_LENGTH bits. | |
633 | Each insn's value is stored with the insn. | |
634 | The first step in recognizing an insn for disassembly is | |
635 | (opcode & mask) == value. */ | |
636 | unsigned int mask; | |
637 | } CGEN_FORMAT; | |
638 | \f | |
df8b2c02 DE |
639 | /* This struct defines each entry in the instruction table. */ |
640 | ||
b61df026 NC |
641 | struct cgen_insn |
642 | { | |
19d45995 DE |
643 | /* ??? Further table size reductions can be had by moving this element |
644 | either to the format table or to a separate table of its own. Not | |
645 | sure this is desirable yet. */ | |
df8b2c02 | 646 | struct cgen_base base; |
b61df026 | 647 | |
df8b2c02 DE |
648 | /* Given a pointer to a cgen_insn struct, return a pointer to `base'. */ |
649 | #define CGEN_INSN_BASE(insn) (&(insn)->base) | |
df8b2c02 | 650 | |
19d45995 DE |
651 | /* Name of entry (that distinguishes it from all other entries). |
652 | This is used, for example, in simulator profiling results. */ | |
653 | /* ??? If mnemonics have operands, try to print full mnemonic. */ | |
b61df026 | 654 | const char * name; |
19d45995 DE |
655 | #define CGEN_INSN_NAME(insn) ((insn)->name) |
656 | ||
657 | /* Mnemonic. This is used when parsing and printing the insn. | |
658 | In the case of insns that have operands on the mnemonics, this is | |
659 | only the constant part. E.g. for conditional execution of an `add' insn, | |
660 | where the full mnemonic is addeq, addne, etc., this is only "add". */ | |
b61df026 | 661 | const char * mnemonic; |
19d45995 DE |
662 | #define CGEN_INSN_MNEMONIC(insn) ((insn)->mnemonic) |
663 | ||
664 | /* Syntax string. | |
665 | For now this only points to CGEN_SYNTAX elements, but it can point | |
666 | to other things (e.g. something different for macros?). */ | |
b61df026 | 667 | const CGEN_SYNTAX * syntax; |
19d45995 DE |
668 | #define CGEN_INSN_SYNTAX(insn) ((CGEN_SYNTAX *) (insn)->syntax) |
669 | ||
670 | /* Format entry. | |
671 | For now this only points to CGEN_FORMAT elements, but it can point | |
672 | to other things (e.g. something different for macros?). */ | |
b61df026 | 673 | const CGEN_FORMAT * format; |
19d45995 DE |
674 | #define CGEN_INSN_MASK_BITSIZE(insn) (((CGEN_FORMAT *) (insn)->format)->mask_length) |
675 | #define CGEN_INSN_BITSIZE(insn) (((CGEN_FORMAT *) (insn)->format)->length) | |
676 | ||
677 | /* Instruction opcode value. */ | |
678 | unsigned int value; | |
679 | #define CGEN_INSN_VALUE(insn) ((insn)->value) | |
680 | #define CGEN_INSN_MASK(insn) (((CGEN_FORMAT *) (insn)->format)->mask) | |
681 | ||
42d56c40 DE |
682 | /* Pointer to NULL entry terminated table of operands used, |
683 | or NULL if none. */ | |
684 | const CGEN_OPERAND_INSTANCE *operands; | |
685 | #define CGEN_INSN_OPERANDS(insn) ((insn)->operands) | |
686 | ||
19d45995 DE |
687 | /* Attributes. |
688 | This must appear last. It is a variable sized array in that one | |
689 | architecture may have 1 nonbool attribute and another may have more. | |
690 | Having this last means the non-architecture specific code needn't | |
691 | care. */ | |
42d56c40 | 692 | CGEN_ATTR_TYPE (CGEN_INSN_MAX_ATTRS) attrs; |
19d45995 | 693 | #define CGEN_INSN_ATTRS(insn) (&(insn)->attrs) |
df8b2c02 DE |
694 | /* Return value of attribute ATTR in INSN. */ |
695 | #define CGEN_INSN_ATTR(insn, attr) \ | |
696 | CGEN_ATTR_VALUE (insn, CGEN_INSN_ATTRS (insn), attr) | |
19d45995 | 697 | }; |
df8b2c02 DE |
698 | |
699 | /* Instruction lists. | |
700 | This is used for adding new entries and for creating the hash lists. */ | |
701 | ||
b61df026 NC |
702 | typedef struct cgen_insn_list |
703 | { | |
704 | struct cgen_insn_list * next; | |
705 | const CGEN_INSN * insn; | |
df8b2c02 DE |
706 | } CGEN_INSN_LIST; |
707 | ||
708 | /* The table of instructions. */ | |
709 | ||
b61df026 NC |
710 | typedef struct |
711 | { | |
df8b2c02 | 712 | /* Pointer to initial [compiled in] entries. */ |
b61df026 NC |
713 | const CGEN_INSN * init_entries; |
714 | ||
19d45995 DE |
715 | /* Size of an entry (since the attribute member is variable sized). */ |
716 | unsigned int entry_size; | |
b61df026 | 717 | |
df8b2c02 DE |
718 | /* Number of entries in `init_entries', including trailing NULL entry. */ |
719 | unsigned int num_init_entries; | |
b61df026 | 720 | |
df8b2c02 | 721 | /* Values added at runtime. */ |
b61df026 NC |
722 | CGEN_INSN_LIST * new_entries; |
723 | ||
df8b2c02 | 724 | /* Assembler hash function. */ |
b61df026 NC |
725 | unsigned int (* asm_hash) PARAMS ((const char *)); |
726 | ||
df8b2c02 DE |
727 | /* Number of entries in assembler hash table. */ |
728 | unsigned int asm_hash_table_size; | |
b61df026 | 729 | |
df8b2c02 | 730 | /* Disassembler hash function. */ |
b61df026 NC |
731 | unsigned int (* dis_hash) PARAMS ((const char *, unsigned long)); |
732 | ||
df8b2c02 DE |
733 | /* Number of entries in disassembler hash table. */ |
734 | unsigned int dis_hash_table_size; | |
735 | } CGEN_INSN_TABLE; | |
736 | ||
737 | /* ??? This is currently used by the simulator. | |
738 | We want this to be fast and the simulator currently doesn't handle | |
739 | runtime added instructions so this is ok. An alternative would be to | |
740 | store the index in the table. */ | |
741 | extern const CGEN_INSN CGEN_SYM (insn_table_entries)[]; | |
742 | #define CGEN_INSN_INDEX(insn) ((int) ((insn) - CGEN_SYM (insn_table_entries))) | |
743 | #define CGEN_INSN_ENTRY(n) (& CGEN_SYM (insn_table_entries) [n]) | |
744 | ||
745 | /* Return number of instructions. This includes any added at runtime. */ | |
746 | ||
19d45995 | 747 | int cgen_insn_count PARAMS ((void)); |
df8b2c02 DE |
748 | |
749 | /* The assembler insn table is hashed based on some function of the mnemonic | |
750 | (the actually hashing done is up to the target, but we provide a few | |
751 | examples like the first letter or a function of the entire mnemonic). | |
752 | The index of each entry is the index of the corresponding table entry. | |
753 | The value of each entry is the index of the next entry, with a 0 | |
754 | terminating (thus the first entry is reserved). */ | |
755 | ||
756 | #ifndef CGEN_ASM_HASH | |
757 | #ifdef CGEN_MNEMONIC_OPERANDS | |
758 | #define CGEN_ASM_HASH_SIZE 127 | |
759 | #define CGEN_ASM_HASH(string) (*(unsigned char *) (string) % CGEN_ASM_HASH_SIZE) | |
760 | #else | |
761 | #define CGEN_ASM_HASH_SIZE 128 | |
762 | #define CGEN_ASM_HASH(string) (*(unsigned char *) (string) % CGEN_ASM_HASH_SIZE) /*FIXME*/ | |
763 | #endif | |
764 | #endif | |
765 | ||
766 | unsigned int CGEN_SYM (asm_hash_insn) PARAMS ((const char *)); | |
767 | CGEN_INSN_LIST * cgen_asm_lookup_insn PARAMS ((const char *)); | |
768 | #define CGEN_ASM_LOOKUP_INSN(insn) cgen_asm_lookup_insn (insn) | |
769 | #define CGEN_ASM_NEXT_INSN(insn) ((insn)->next) | |
770 | ||
771 | /* The disassembler insn table is hashed based on some function of machine | |
772 | instruction (the actually hashing done is up to the target). */ | |
773 | ||
774 | /* It doesn't make much sense to provide a default here, | |
775 | but while this is under development we do. | |
776 | BUFFER is a pointer to the bytes of the insn. | |
777 | INSN is the first CGEN_BASE_INSN_SIZE bytes as an int in host order. */ | |
778 | #ifndef CGEN_DIS_HASH | |
779 | #define CGEN_DIS_HASH_SIZE 256 | |
780 | #define CGEN_DIS_HASH(buffer, insn) (*(unsigned char *) (buffer)) | |
781 | #endif | |
782 | ||
783 | unsigned int CGEN_SYM (dis_hash_insn) PARAMS ((const char *, unsigned long)); | |
784 | CGEN_INSN_LIST * cgen_dis_lookup_insn PARAMS ((const char *, unsigned long)); | |
785 | #define CGEN_DIS_LOOKUP_INSN(buf, insn) cgen_dis_lookup_insn (buf, insn) | |
786 | #define CGEN_DIS_NEXT_INSN(insn) ((insn)->next) | |
787 | \f | |
788 | /* Top level structures and functions. */ | |
789 | ||
b61df026 NC |
790 | typedef struct |
791 | { | |
42d56c40 | 792 | const CGEN_HW_ENTRY * hw_list; |
b61df026 NC |
793 | /*CGEN_OPERAND_TABLE * operand_table; - FIXME:wip */ |
794 | CGEN_INSN_TABLE * insn_table; | |
df8b2c02 DE |
795 | } CGEN_OPCODE_DATA; |
796 | ||
797 | /* Each CPU has one of these. */ | |
798 | extern CGEN_OPCODE_DATA CGEN_SYM (opcode_data); | |
799 | ||
800 | /* Global state access macros. | |
801 | Some of these are tucked away and accessed with cover fns. | |
802 | Simpler things like the current machine and endian are not. */ | |
803 | ||
804 | extern int cgen_current_machine; | |
805 | #define CGEN_CURRENT_MACHINE cgen_current_machine | |
806 | ||
807 | extern enum cgen_endian cgen_current_endian; | |
808 | #define CGEN_CURRENT_ENDIAN cgen_current_endian | |
809 | ||
810 | /* Prototypes of major functions. */ | |
811 | ||
42d56c40 | 812 | /* Set the current cpu (+ mach number, endian, etc.). */ |
df8b2c02 DE |
813 | void cgen_set_cpu PARAMS ((CGEN_OPCODE_DATA *, int, enum cgen_endian)); |
814 | ||
815 | /* Initialize the assembler, disassembler. */ | |
816 | void cgen_asm_init PARAMS ((void)); | |
817 | void cgen_dis_init PARAMS ((void)); | |
818 | ||
819 | /* `init_tables' must be called before `xxx_supported'. */ | |
820 | void CGEN_SYM (init_tables) PARAMS ((int)); | |
821 | void CGEN_SYM (init_asm) PARAMS ((int, enum cgen_endian)); | |
822 | void CGEN_SYM (init_dis) PARAMS ((int, enum cgen_endian)); | |
823 | void CGEN_SYM (init_parse) PARAMS ((void)); | |
824 | void CGEN_SYM (init_print) PARAMS ((void)); | |
825 | void CGEN_SYM (init_insert) PARAMS ((void)); | |
826 | void CGEN_SYM (init_extract) PARAMS ((void)); | |
42d56c40 DE |
827 | |
828 | /* FIXME: This prototype is wrong ifndef CGEN_INT_INSN. | |
829 | Furthermore, ifdef CGEN_INT_INSN, the insn is created in | |
830 | target byte order (in which case why use int's at all). | |
831 | Perhaps replace cgen_insn_t * with char *? */ | |
df8b2c02 | 832 | const struct cgen_insn * |
42d56c40 | 833 | CGEN_SYM (assemble_insn) PARAMS ((const char *, CGEN_FIELDS *, |
fe2dd642 | 834 | cgen_insn_t *, char **)); |
df8b2c02 | 835 | #if 0 /* old */ |
19d45995 | 836 | int CGEN_SYM (insn_supported) PARAMS ((const struct cgen_insn *)); |
df8b2c02 DE |
837 | int CGEN_SYM (opval_supported) PARAMS ((const struct cgen_opval *)); |
838 | #endif | |
839 | ||
19d45995 | 840 | extern const CGEN_KEYWORD CGEN_SYM (operand_mach); |
df8b2c02 DE |
841 | int CGEN_SYM (get_mach) PARAMS ((const char *)); |
842 | ||
42d56c40 DE |
843 | const CGEN_INSN * |
844 | CGEN_SYM (get_insn_operands) PARAMS ((const CGEN_INSN *, cgen_insn_t, | |
845 | int, int *)); | |
846 | const CGEN_INSN * | |
847 | CGEN_SYM (lookup_insn) PARAMS ((const CGEN_INSN *, cgen_insn_t, | |
848 | int, CGEN_FIELDS *)); | |
849 | ||
df8b2c02 DE |
850 | CGEN_INLINE void |
851 | CGEN_SYM (put_operand) PARAMS ((int, const long *, | |
42d56c40 | 852 | CGEN_FIELDS *)); |
df8b2c02 | 853 | CGEN_INLINE long |
42d56c40 | 854 | CGEN_SYM (get_operand) PARAMS ((int, const CGEN_FIELDS *)); |
df8b2c02 DE |
855 | |
856 | CGEN_INLINE const char * | |
42d56c40 | 857 | CGEN_SYM (parse_operand) PARAMS ((int, const char **, CGEN_FIELDS *)); |
df8b2c02 DE |
858 | |
859 | CGEN_INLINE const char * | |
42d56c40 | 860 | CGEN_SYM (validate_operand) PARAMS ((int, const CGEN_FIELDS *)); |
df8b2c02 DE |
861 | |
862 | /* Default insn parser, printer. */ | |
863 | extern cgen_parse_fn CGEN_SYM (parse_insn); | |
864 | extern cgen_insert_fn CGEN_SYM (insert_insn); | |
865 | extern cgen_extract_fn CGEN_SYM (extract_insn); | |
866 | extern cgen_print_fn CGEN_SYM (print_insn); | |
867 | ||
868 | /* Read in a cpu description file. */ | |
869 | const char * cgen_read_cpu_file PARAMS ((const char *)); | |
df8b2c02 DE |
870 | |
871 | #endif /* CGEN_H */ |