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