17f709ce7SMax Filippov /* Configurable Xtensa ISA support.
27f709ce7SMax Filippov *
37f709ce7SMax Filippov * Copyright (c) 2001-2011 Tensilica Inc.
47f709ce7SMax Filippov *
57f709ce7SMax Filippov * Permission is hereby granted, free of charge, to any person obtaining
67f709ce7SMax Filippov * a copy of this software and associated documentation files (the
77f709ce7SMax Filippov * "Software"), to deal in the Software without restriction, including
87f709ce7SMax Filippov * without limitation the rights to use, copy, modify, merge, publish,
97f709ce7SMax Filippov * distribute, sublicense, and/or sell copies of the Software, and to
107f709ce7SMax Filippov * permit persons to whom the Software is furnished to do so, subject to
117f709ce7SMax Filippov * the following conditions:
127f709ce7SMax Filippov *
137f709ce7SMax Filippov * The above copyright notice and this permission notice shall be included
147f709ce7SMax Filippov * in all copies or substantial portions of the Software.
157f709ce7SMax Filippov *
167f709ce7SMax Filippov * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
177f709ce7SMax Filippov * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
187f709ce7SMax Filippov * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
197f709ce7SMax Filippov * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
207f709ce7SMax Filippov * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
217f709ce7SMax Filippov * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
227f709ce7SMax Filippov * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
237f709ce7SMax Filippov */
247f709ce7SMax Filippov
25*8f0a3716SMarkus Armbruster #include "qemu/osdep.h"
267f709ce7SMax Filippov #include "xtensa-isa.h"
277f709ce7SMax Filippov #include "xtensa-isa-internal.h"
287f709ce7SMax Filippov
297f709ce7SMax Filippov xtensa_isa_status xtisa_errno;
307f709ce7SMax Filippov char xtisa_error_msg[1024];
317f709ce7SMax Filippov
327f709ce7SMax Filippov
xtensa_isa_errno(xtensa_isa isa)337f709ce7SMax Filippov xtensa_isa_status xtensa_isa_errno(xtensa_isa isa __attribute__ ((unused)))
347f709ce7SMax Filippov {
357f709ce7SMax Filippov return xtisa_errno;
367f709ce7SMax Filippov }
377f709ce7SMax Filippov
387f709ce7SMax Filippov
xtensa_isa_error_msg(xtensa_isa isa)397f709ce7SMax Filippov char *xtensa_isa_error_msg(xtensa_isa isa __attribute__ ((unused)))
407f709ce7SMax Filippov {
417f709ce7SMax Filippov return xtisa_error_msg;
427f709ce7SMax Filippov }
437f709ce7SMax Filippov
447f709ce7SMax Filippov
457f709ce7SMax Filippov #define CHECK_ALLOC(MEM, ERRVAL) \
467f709ce7SMax Filippov do { \
477f709ce7SMax Filippov if ((MEM) == 0) { \
487f709ce7SMax Filippov xtisa_errno = xtensa_isa_out_of_memory; \
497f709ce7SMax Filippov strcpy(xtisa_error_msg, "out of memory"); \
507f709ce7SMax Filippov return ERRVAL; \
517f709ce7SMax Filippov } \
527f709ce7SMax Filippov } while (0)
537f709ce7SMax Filippov
547f709ce7SMax Filippov #define CHECK_ALLOC_FOR_INIT(MEM, ERRVAL, ERRNO_P, ERROR_MSG_P) \
557f709ce7SMax Filippov do { \
567f709ce7SMax Filippov if ((MEM) == 0) { \
577f709ce7SMax Filippov xtisa_errno = xtensa_isa_out_of_memory; \
587f709ce7SMax Filippov strcpy(xtisa_error_msg, "out of memory"); \
597f709ce7SMax Filippov if (ERRNO_P) { \
607f709ce7SMax Filippov *(ERRNO_P) = xtisa_errno; \
617f709ce7SMax Filippov } \
627f709ce7SMax Filippov if (ERROR_MSG_P) { \
637f709ce7SMax Filippov *(ERROR_MSG_P) = xtisa_error_msg; \
647f709ce7SMax Filippov } \
657f709ce7SMax Filippov return ERRVAL; \
667f709ce7SMax Filippov } \
677f709ce7SMax Filippov } while (0)
687f709ce7SMax Filippov
697f709ce7SMax Filippov
707f709ce7SMax Filippov /* Instruction buffers. */
717f709ce7SMax Filippov
xtensa_insnbuf_size(xtensa_isa isa)727f709ce7SMax Filippov int xtensa_insnbuf_size(xtensa_isa isa)
737f709ce7SMax Filippov {
747f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
757f709ce7SMax Filippov return intisa->insnbuf_size;
767f709ce7SMax Filippov }
777f709ce7SMax Filippov
787f709ce7SMax Filippov
xtensa_insnbuf_alloc(xtensa_isa isa)797f709ce7SMax Filippov xtensa_insnbuf xtensa_insnbuf_alloc(xtensa_isa isa)
807f709ce7SMax Filippov {
817f709ce7SMax Filippov xtensa_insnbuf result = (xtensa_insnbuf)
827f709ce7SMax Filippov malloc(xtensa_insnbuf_size(isa) * sizeof(xtensa_insnbuf_word));
837f709ce7SMax Filippov
847f709ce7SMax Filippov CHECK_ALLOC(result, 0);
857f709ce7SMax Filippov return result;
867f709ce7SMax Filippov }
877f709ce7SMax Filippov
887f709ce7SMax Filippov
xtensa_insnbuf_free(xtensa_isa isa,xtensa_insnbuf buf)897f709ce7SMax Filippov void xtensa_insnbuf_free(xtensa_isa isa __attribute__ ((unused)),
907f709ce7SMax Filippov xtensa_insnbuf buf)
917f709ce7SMax Filippov {
927f709ce7SMax Filippov free(buf);
937f709ce7SMax Filippov }
947f709ce7SMax Filippov
957f709ce7SMax Filippov
967f709ce7SMax Filippov /*
977f709ce7SMax Filippov * Given <byte_index>, the index of a byte in a xtensa_insnbuf, our
987f709ce7SMax Filippov * internal representation of a xtensa instruction word, return the index of
997f709ce7SMax Filippov * its word and the bit index of its low order byte in the xtensa_insnbuf.
1007f709ce7SMax Filippov */
1017f709ce7SMax Filippov
byte_to_word_index(int byte_index)1027f709ce7SMax Filippov static inline int byte_to_word_index(int byte_index)
1037f709ce7SMax Filippov {
1047f709ce7SMax Filippov return byte_index / sizeof(xtensa_insnbuf_word);
1057f709ce7SMax Filippov }
1067f709ce7SMax Filippov
1077f709ce7SMax Filippov
byte_to_bit_index(int byte_index)1087f709ce7SMax Filippov static inline int byte_to_bit_index(int byte_index)
1097f709ce7SMax Filippov {
1107f709ce7SMax Filippov return (byte_index & 0x3) * 8;
1117f709ce7SMax Filippov }
1127f709ce7SMax Filippov
1137f709ce7SMax Filippov
1147f709ce7SMax Filippov /*
1157f709ce7SMax Filippov * Copy an instruction in the 32-bit words pointed at by "insn" to
1167f709ce7SMax Filippov * characters pointed at by "cp". This is more complicated than you
1177f709ce7SMax Filippov * might think because we want 16-bit instructions in bytes 2 & 3 for
1187f709ce7SMax Filippov * big-endian configurations. This function allows us to specify
1197f709ce7SMax Filippov * which byte in "insn" to start with and which way to increment,
1207f709ce7SMax Filippov * allowing trivial implementation for both big- and little-endian
1217f709ce7SMax Filippov * configurations....and it seems to make pretty good code for
1227f709ce7SMax Filippov * both.
1237f709ce7SMax Filippov */
1247f709ce7SMax Filippov
xtensa_insnbuf_to_chars(xtensa_isa isa,const xtensa_insnbuf insn,unsigned char * cp,int num_chars)1257f709ce7SMax Filippov int xtensa_insnbuf_to_chars(xtensa_isa isa,
1267f709ce7SMax Filippov const xtensa_insnbuf insn,
1277f709ce7SMax Filippov unsigned char *cp,
1287f709ce7SMax Filippov int num_chars)
1297f709ce7SMax Filippov {
1307f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1317f709ce7SMax Filippov int insn_size = xtensa_isa_maxlength(isa);
1327f709ce7SMax Filippov int fence_post, start, increment, i, byte_count;
1337f709ce7SMax Filippov xtensa_format fmt;
1347f709ce7SMax Filippov
1357f709ce7SMax Filippov if (num_chars == 0) {
1367f709ce7SMax Filippov num_chars = insn_size;
1377f709ce7SMax Filippov }
1387f709ce7SMax Filippov
1397f709ce7SMax Filippov if (intisa->is_big_endian) {
1407f709ce7SMax Filippov start = insn_size - 1;
1417f709ce7SMax Filippov increment = -1;
1427f709ce7SMax Filippov } else {
1437f709ce7SMax Filippov start = 0;
1447f709ce7SMax Filippov increment = 1;
1457f709ce7SMax Filippov }
1467f709ce7SMax Filippov
1477f709ce7SMax Filippov /*
1487f709ce7SMax Filippov * Find the instruction format. Do nothing if the buffer does not contain
1497f709ce7SMax Filippov * a valid instruction since we need to know how many bytes to copy.
1507f709ce7SMax Filippov */
1517f709ce7SMax Filippov fmt = xtensa_format_decode(isa, insn);
1527f709ce7SMax Filippov if (fmt == XTENSA_UNDEFINED) {
1537f709ce7SMax Filippov return XTENSA_UNDEFINED;
1547f709ce7SMax Filippov }
1557f709ce7SMax Filippov
1567f709ce7SMax Filippov byte_count = xtensa_format_length(isa, fmt);
1577f709ce7SMax Filippov if (byte_count == XTENSA_UNDEFINED) {
1587f709ce7SMax Filippov return XTENSA_UNDEFINED;
1597f709ce7SMax Filippov }
1607f709ce7SMax Filippov
1617f709ce7SMax Filippov if (byte_count > num_chars) {
1627f709ce7SMax Filippov xtisa_errno = xtensa_isa_buffer_overflow;
1637f709ce7SMax Filippov strcpy(xtisa_error_msg, "output buffer too small for instruction");
1647f709ce7SMax Filippov return XTENSA_UNDEFINED;
1657f709ce7SMax Filippov }
1667f709ce7SMax Filippov
1677f709ce7SMax Filippov fence_post = start + (byte_count * increment);
1687f709ce7SMax Filippov
1697f709ce7SMax Filippov for (i = start; i != fence_post; i += increment, ++cp) {
1707f709ce7SMax Filippov int word_inx = byte_to_word_index(i);
1717f709ce7SMax Filippov int bit_inx = byte_to_bit_index(i);
1727f709ce7SMax Filippov
1737f709ce7SMax Filippov *cp = (insn[word_inx] >> bit_inx) & 0xff;
1747f709ce7SMax Filippov }
1757f709ce7SMax Filippov
1767f709ce7SMax Filippov return byte_count;
1777f709ce7SMax Filippov }
1787f709ce7SMax Filippov
1797f709ce7SMax Filippov
1807f709ce7SMax Filippov /*
1817f709ce7SMax Filippov * Inward conversion from byte stream to xtensa_insnbuf. See
1827f709ce7SMax Filippov * xtensa_insnbuf_to_chars for a discussion of why this is complicated
1837f709ce7SMax Filippov * by endianness.
1847f709ce7SMax Filippov */
1857f709ce7SMax Filippov
xtensa_insnbuf_from_chars(xtensa_isa isa,xtensa_insnbuf insn,const unsigned char * cp,int num_chars)1867f709ce7SMax Filippov void xtensa_insnbuf_from_chars(xtensa_isa isa,
1877f709ce7SMax Filippov xtensa_insnbuf insn,
1887f709ce7SMax Filippov const unsigned char *cp,
1897f709ce7SMax Filippov int num_chars)
1907f709ce7SMax Filippov {
1917f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
1927f709ce7SMax Filippov int max_size, insn_size, fence_post, start, increment, i;
1937f709ce7SMax Filippov
1947f709ce7SMax Filippov max_size = xtensa_isa_maxlength(isa);
1957f709ce7SMax Filippov
1967f709ce7SMax Filippov /* Decode the instruction length so we know how many bytes to read. */
1977f709ce7SMax Filippov insn_size = (intisa->length_decode_fn)(cp);
1987f709ce7SMax Filippov if (insn_size == XTENSA_UNDEFINED) {
1997f709ce7SMax Filippov /*
2007f709ce7SMax Filippov * This should never happen when the byte stream contains a
2017f709ce7SMax Filippov * valid instruction. Just read the maximum number of bytes....
2027f709ce7SMax Filippov */
2037f709ce7SMax Filippov insn_size = max_size;
2047f709ce7SMax Filippov }
2057f709ce7SMax Filippov
2067f709ce7SMax Filippov if (num_chars == 0 || num_chars > insn_size) {
2077f709ce7SMax Filippov num_chars = insn_size;
2087f709ce7SMax Filippov }
2097f709ce7SMax Filippov
2107f709ce7SMax Filippov if (intisa->is_big_endian) {
2117f709ce7SMax Filippov start = max_size - 1;
2127f709ce7SMax Filippov increment = -1;
2137f709ce7SMax Filippov } else {
2147f709ce7SMax Filippov start = 0;
2157f709ce7SMax Filippov increment = 1;
2167f709ce7SMax Filippov }
2177f709ce7SMax Filippov
2187f709ce7SMax Filippov fence_post = start + (num_chars * increment);
2197f709ce7SMax Filippov memset(insn, 0, xtensa_insnbuf_size(isa) * sizeof(xtensa_insnbuf_word));
2207f709ce7SMax Filippov
2217f709ce7SMax Filippov for (i = start; i != fence_post; i += increment, ++cp) {
2227f709ce7SMax Filippov int word_inx = byte_to_word_index(i);
2237f709ce7SMax Filippov int bit_inx = byte_to_bit_index(i);
2247f709ce7SMax Filippov
2257f709ce7SMax Filippov insn[word_inx] |= (*cp & 0xff) << bit_inx;
2267f709ce7SMax Filippov }
2277f709ce7SMax Filippov }
2287f709ce7SMax Filippov
2297f709ce7SMax Filippov
2307f709ce7SMax Filippov /* ISA information. */
2317f709ce7SMax Filippov
xtensa_isa_init(void * xtensa_modules,xtensa_isa_status * errno_p,char ** error_msg_p)2327f709ce7SMax Filippov xtensa_isa xtensa_isa_init(void *xtensa_modules, xtensa_isa_status *errno_p,
2337f709ce7SMax Filippov char **error_msg_p)
2347f709ce7SMax Filippov {
2357f709ce7SMax Filippov xtensa_isa_internal *isa = xtensa_modules;
2367f709ce7SMax Filippov int n, is_user;
2377f709ce7SMax Filippov
2387f709ce7SMax Filippov /* Set up the opcode name lookup table. */
2397f709ce7SMax Filippov isa->opname_lookup_table =
2407f709ce7SMax Filippov malloc(isa->num_opcodes * sizeof(xtensa_lookup_entry));
2417f709ce7SMax Filippov CHECK_ALLOC_FOR_INIT(isa->opname_lookup_table, NULL, errno_p, error_msg_p);
2427f709ce7SMax Filippov for (n = 0; n < isa->num_opcodes; n++) {
2437f709ce7SMax Filippov isa->opname_lookup_table[n].key = isa->opcodes[n].name;
2447f709ce7SMax Filippov isa->opname_lookup_table[n].u.opcode = n;
2457f709ce7SMax Filippov }
2467f709ce7SMax Filippov qsort(isa->opname_lookup_table, isa->num_opcodes,
2477f709ce7SMax Filippov sizeof(xtensa_lookup_entry), xtensa_isa_name_compare);
2487f709ce7SMax Filippov
2497f709ce7SMax Filippov /* Set up the state name lookup table. */
2507f709ce7SMax Filippov isa->state_lookup_table =
2517f709ce7SMax Filippov malloc(isa->num_states * sizeof(xtensa_lookup_entry));
2527f709ce7SMax Filippov CHECK_ALLOC_FOR_INIT(isa->state_lookup_table, NULL, errno_p, error_msg_p);
2537f709ce7SMax Filippov for (n = 0; n < isa->num_states; n++) {
2547f709ce7SMax Filippov isa->state_lookup_table[n].key = isa->states[n].name;
2557f709ce7SMax Filippov isa->state_lookup_table[n].u.state = n;
2567f709ce7SMax Filippov }
2577f709ce7SMax Filippov qsort(isa->state_lookup_table, isa->num_states,
2587f709ce7SMax Filippov sizeof(xtensa_lookup_entry), xtensa_isa_name_compare);
2597f709ce7SMax Filippov
2607f709ce7SMax Filippov /* Set up the sysreg name lookup table. */
2617f709ce7SMax Filippov isa->sysreg_lookup_table =
2627f709ce7SMax Filippov malloc(isa->num_sysregs * sizeof(xtensa_lookup_entry));
2637f709ce7SMax Filippov CHECK_ALLOC_FOR_INIT(isa->sysreg_lookup_table, NULL, errno_p, error_msg_p);
2647f709ce7SMax Filippov for (n = 0; n < isa->num_sysregs; n++) {
2657f709ce7SMax Filippov isa->sysreg_lookup_table[n].key = isa->sysregs[n].name;
2667f709ce7SMax Filippov isa->sysreg_lookup_table[n].u.sysreg = n;
2677f709ce7SMax Filippov }
2687f709ce7SMax Filippov qsort(isa->sysreg_lookup_table, isa->num_sysregs,
2697f709ce7SMax Filippov sizeof(xtensa_lookup_entry), xtensa_isa_name_compare);
2707f709ce7SMax Filippov
2717f709ce7SMax Filippov /* Set up the user & system sysreg number tables. */
2727f709ce7SMax Filippov for (is_user = 0; is_user < 2; is_user++) {
2737f709ce7SMax Filippov isa->sysreg_table[is_user] =
2747f709ce7SMax Filippov malloc((isa->max_sysreg_num[is_user] + 1) * sizeof(xtensa_sysreg));
2757f709ce7SMax Filippov CHECK_ALLOC_FOR_INIT(isa->sysreg_table[is_user], NULL,
2767f709ce7SMax Filippov errno_p, error_msg_p);
2777f709ce7SMax Filippov
2787f709ce7SMax Filippov for (n = 0; n <= isa->max_sysreg_num[is_user]; n++) {
2797f709ce7SMax Filippov isa->sysreg_table[is_user][n] = XTENSA_UNDEFINED;
2807f709ce7SMax Filippov }
2817f709ce7SMax Filippov }
2827f709ce7SMax Filippov for (n = 0; n < isa->num_sysregs; n++) {
2837f709ce7SMax Filippov xtensa_sysreg_internal *sreg = &isa->sysregs[n];
2847f709ce7SMax Filippov is_user = sreg->is_user;
2857f709ce7SMax Filippov
2867f709ce7SMax Filippov if (sreg->number >= 0) {
2877f709ce7SMax Filippov isa->sysreg_table[is_user][sreg->number] = n;
2887f709ce7SMax Filippov }
2897f709ce7SMax Filippov }
2907f709ce7SMax Filippov
2917f709ce7SMax Filippov /* Set up the interface lookup table. */
2927f709ce7SMax Filippov isa->interface_lookup_table =
2937f709ce7SMax Filippov malloc(isa->num_interfaces * sizeof(xtensa_lookup_entry));
2947f709ce7SMax Filippov CHECK_ALLOC_FOR_INIT(isa->interface_lookup_table, NULL, errno_p,
2957f709ce7SMax Filippov error_msg_p);
2967f709ce7SMax Filippov for (n = 0; n < isa->num_interfaces; n++) {
2977f709ce7SMax Filippov isa->interface_lookup_table[n].key = isa->interfaces[n].name;
2987f709ce7SMax Filippov isa->interface_lookup_table[n].u.intf = n;
2997f709ce7SMax Filippov }
3007f709ce7SMax Filippov qsort(isa->interface_lookup_table, isa->num_interfaces,
3017f709ce7SMax Filippov sizeof(xtensa_lookup_entry), xtensa_isa_name_compare);
3027f709ce7SMax Filippov
3037f709ce7SMax Filippov /* Set up the funcUnit lookup table. */
3047f709ce7SMax Filippov isa->funcUnit_lookup_table =
3057f709ce7SMax Filippov malloc(isa->num_funcUnits * sizeof(xtensa_lookup_entry));
3067f709ce7SMax Filippov CHECK_ALLOC_FOR_INIT(isa->funcUnit_lookup_table, NULL, errno_p,
3077f709ce7SMax Filippov error_msg_p);
3087f709ce7SMax Filippov for (n = 0; n < isa->num_funcUnits; n++) {
3097f709ce7SMax Filippov isa->funcUnit_lookup_table[n].key = isa->funcUnits[n].name;
3107f709ce7SMax Filippov isa->funcUnit_lookup_table[n].u.fun = n;
3117f709ce7SMax Filippov }
3127f709ce7SMax Filippov qsort(isa->funcUnit_lookup_table, isa->num_funcUnits,
3137f709ce7SMax Filippov sizeof(xtensa_lookup_entry), xtensa_isa_name_compare);
3147f709ce7SMax Filippov
3157f709ce7SMax Filippov isa->insnbuf_size = ((isa->insn_size + sizeof(xtensa_insnbuf_word) - 1) /
3167f709ce7SMax Filippov sizeof(xtensa_insnbuf_word));
3177f709ce7SMax Filippov isa->num_stages = XTENSA_UNDEFINED;
3187f709ce7SMax Filippov
3197f709ce7SMax Filippov return (xtensa_isa)isa;
3207f709ce7SMax Filippov }
3217f709ce7SMax Filippov
3227f709ce7SMax Filippov
xtensa_isa_free(xtensa_isa isa)3237f709ce7SMax Filippov void xtensa_isa_free(xtensa_isa isa)
3247f709ce7SMax Filippov {
3257f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
3267f709ce7SMax Filippov int n;
3277f709ce7SMax Filippov
3287f709ce7SMax Filippov /*
3297f709ce7SMax Filippov * With this version of the code, the xtensa_isa structure is not
3307f709ce7SMax Filippov * dynamically allocated, so this function is not essential. Free
3317f709ce7SMax Filippov * the memory allocated by xtensa_isa_init and restore the xtensa_isa
3327f709ce7SMax Filippov * structure to its initial state.
3337f709ce7SMax Filippov */
3347f709ce7SMax Filippov
3357f709ce7SMax Filippov if (intisa->opname_lookup_table) {
3367f709ce7SMax Filippov free(intisa->opname_lookup_table);
3377f709ce7SMax Filippov intisa->opname_lookup_table = 0;
3387f709ce7SMax Filippov }
3397f709ce7SMax Filippov
3407f709ce7SMax Filippov if (intisa->state_lookup_table) {
3417f709ce7SMax Filippov free(intisa->state_lookup_table);
3427f709ce7SMax Filippov intisa->state_lookup_table = 0;
3437f709ce7SMax Filippov }
3447f709ce7SMax Filippov
3457f709ce7SMax Filippov if (intisa->sysreg_lookup_table) {
3467f709ce7SMax Filippov free(intisa->sysreg_lookup_table);
3477f709ce7SMax Filippov intisa->sysreg_lookup_table = 0;
3487f709ce7SMax Filippov }
3497f709ce7SMax Filippov for (n = 0; n < 2; n++) {
3507f709ce7SMax Filippov if (intisa->sysreg_table[n]) {
3517f709ce7SMax Filippov free(intisa->sysreg_table[n]);
3527f709ce7SMax Filippov intisa->sysreg_table[n] = 0;
3537f709ce7SMax Filippov }
3547f709ce7SMax Filippov }
3557f709ce7SMax Filippov
3567f709ce7SMax Filippov if (intisa->interface_lookup_table) {
3577f709ce7SMax Filippov free(intisa->interface_lookup_table);
3587f709ce7SMax Filippov intisa->interface_lookup_table = 0;
3597f709ce7SMax Filippov }
3607f709ce7SMax Filippov
3617f709ce7SMax Filippov if (intisa->funcUnit_lookup_table) {
3627f709ce7SMax Filippov free(intisa->funcUnit_lookup_table);
3637f709ce7SMax Filippov intisa->funcUnit_lookup_table = 0;
3647f709ce7SMax Filippov }
3657f709ce7SMax Filippov }
3667f709ce7SMax Filippov
3677f709ce7SMax Filippov
xtensa_isa_name_compare(const void * v1,const void * v2)3687f709ce7SMax Filippov int xtensa_isa_name_compare(const void *v1, const void *v2)
3697f709ce7SMax Filippov {
3707f709ce7SMax Filippov xtensa_lookup_entry *e1 = (xtensa_lookup_entry *)v1;
3717f709ce7SMax Filippov xtensa_lookup_entry *e2 = (xtensa_lookup_entry *)v2;
3727f709ce7SMax Filippov
3737f709ce7SMax Filippov return strcasecmp(e1->key, e2->key);
3747f709ce7SMax Filippov }
3757f709ce7SMax Filippov
3767f709ce7SMax Filippov
xtensa_isa_maxlength(xtensa_isa isa)3777f709ce7SMax Filippov int xtensa_isa_maxlength(xtensa_isa isa)
3787f709ce7SMax Filippov {
3797f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
3807f709ce7SMax Filippov return intisa->insn_size;
3817f709ce7SMax Filippov }
3827f709ce7SMax Filippov
3837f709ce7SMax Filippov
xtensa_isa_length_from_chars(xtensa_isa isa,const unsigned char * cp)3847f709ce7SMax Filippov int xtensa_isa_length_from_chars(xtensa_isa isa, const unsigned char *cp)
3857f709ce7SMax Filippov {
3867f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
3877f709ce7SMax Filippov return (intisa->length_decode_fn)(cp);
3887f709ce7SMax Filippov }
3897f709ce7SMax Filippov
3907f709ce7SMax Filippov
xtensa_isa_num_pipe_stages(xtensa_isa isa)3917f709ce7SMax Filippov int xtensa_isa_num_pipe_stages(xtensa_isa isa)
3927f709ce7SMax Filippov {
3937f709ce7SMax Filippov xtensa_opcode opcode;
3947f709ce7SMax Filippov xtensa_funcUnit_use *use;
3957f709ce7SMax Filippov int num_opcodes, num_uses;
3967f709ce7SMax Filippov int i, stage, max_stage;
3977f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
3987f709ce7SMax Filippov
3997f709ce7SMax Filippov /* Only compute the value once. */
4007f709ce7SMax Filippov if (intisa->num_stages != XTENSA_UNDEFINED) {
4017f709ce7SMax Filippov return intisa->num_stages;
4027f709ce7SMax Filippov }
4037f709ce7SMax Filippov
4047f709ce7SMax Filippov max_stage = -1;
4057f709ce7SMax Filippov
4067f709ce7SMax Filippov num_opcodes = xtensa_isa_num_opcodes(isa);
4077f709ce7SMax Filippov for (opcode = 0; opcode < num_opcodes; opcode++) {
4087f709ce7SMax Filippov num_uses = xtensa_opcode_num_funcUnit_uses(isa, opcode);
4097f709ce7SMax Filippov for (i = 0; i < num_uses; i++) {
4107f709ce7SMax Filippov use = xtensa_opcode_funcUnit_use(isa, opcode, i);
4117f709ce7SMax Filippov stage = use->stage;
4127f709ce7SMax Filippov if (stage > max_stage) {
4137f709ce7SMax Filippov max_stage = stage;
4147f709ce7SMax Filippov }
4157f709ce7SMax Filippov }
4167f709ce7SMax Filippov }
4177f709ce7SMax Filippov
4187f709ce7SMax Filippov intisa->num_stages = max_stage + 1;
4197f709ce7SMax Filippov return intisa->num_states;
4207f709ce7SMax Filippov }
4217f709ce7SMax Filippov
4227f709ce7SMax Filippov
xtensa_isa_num_formats(xtensa_isa isa)4237f709ce7SMax Filippov int xtensa_isa_num_formats(xtensa_isa isa)
4247f709ce7SMax Filippov {
4257f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
4267f709ce7SMax Filippov return intisa->num_formats;
4277f709ce7SMax Filippov }
4287f709ce7SMax Filippov
4297f709ce7SMax Filippov
xtensa_isa_num_opcodes(xtensa_isa isa)4307f709ce7SMax Filippov int xtensa_isa_num_opcodes(xtensa_isa isa)
4317f709ce7SMax Filippov {
4327f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
4337f709ce7SMax Filippov return intisa->num_opcodes;
4347f709ce7SMax Filippov }
4357f709ce7SMax Filippov
4367f709ce7SMax Filippov
xtensa_isa_num_regfiles(xtensa_isa isa)4377f709ce7SMax Filippov int xtensa_isa_num_regfiles(xtensa_isa isa)
4387f709ce7SMax Filippov {
4397f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
4407f709ce7SMax Filippov return intisa->num_regfiles;
4417f709ce7SMax Filippov }
4427f709ce7SMax Filippov
4437f709ce7SMax Filippov
xtensa_isa_num_states(xtensa_isa isa)4447f709ce7SMax Filippov int xtensa_isa_num_states(xtensa_isa isa)
4457f709ce7SMax Filippov {
4467f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
4477f709ce7SMax Filippov return intisa->num_states;
4487f709ce7SMax Filippov }
4497f709ce7SMax Filippov
4507f709ce7SMax Filippov
xtensa_isa_num_sysregs(xtensa_isa isa)4517f709ce7SMax Filippov int xtensa_isa_num_sysregs(xtensa_isa isa)
4527f709ce7SMax Filippov {
4537f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
4547f709ce7SMax Filippov return intisa->num_sysregs;
4557f709ce7SMax Filippov }
4567f709ce7SMax Filippov
4577f709ce7SMax Filippov
xtensa_isa_num_interfaces(xtensa_isa isa)4587f709ce7SMax Filippov int xtensa_isa_num_interfaces(xtensa_isa isa)
4597f709ce7SMax Filippov {
4607f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
4617f709ce7SMax Filippov return intisa->num_interfaces;
4627f709ce7SMax Filippov }
4637f709ce7SMax Filippov
4647f709ce7SMax Filippov
xtensa_isa_num_funcUnits(xtensa_isa isa)4657f709ce7SMax Filippov int xtensa_isa_num_funcUnits(xtensa_isa isa)
4667f709ce7SMax Filippov {
4677f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
4687f709ce7SMax Filippov return intisa->num_funcUnits;
4697f709ce7SMax Filippov }
4707f709ce7SMax Filippov
4717f709ce7SMax Filippov
4727f709ce7SMax Filippov /* Instruction formats. */
4737f709ce7SMax Filippov
4747f709ce7SMax Filippov
4757f709ce7SMax Filippov #define CHECK_FORMAT(INTISA, FMT, ERRVAL) \
4767f709ce7SMax Filippov do { \
4777f709ce7SMax Filippov if ((FMT) < 0 || (FMT) >= (INTISA)->num_formats) { \
4787f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_format; \
4797f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid format specifier"); \
4807f709ce7SMax Filippov return ERRVAL; \
4817f709ce7SMax Filippov } \
4827f709ce7SMax Filippov } while (0)
4837f709ce7SMax Filippov
4847f709ce7SMax Filippov
4857f709ce7SMax Filippov #define CHECK_SLOT(INTISA, FMT, SLOT, ERRVAL) \
4867f709ce7SMax Filippov do { \
4877f709ce7SMax Filippov if ((SLOT) < 0 || (SLOT) >= (INTISA)->formats[FMT].num_slots) { \
4887f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_slot; \
4897f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid slot specifier"); \
4907f709ce7SMax Filippov return ERRVAL; \
4917f709ce7SMax Filippov } \
4927f709ce7SMax Filippov } while (0)
4937f709ce7SMax Filippov
4947f709ce7SMax Filippov
xtensa_format_name(xtensa_isa isa,xtensa_format fmt)4957f709ce7SMax Filippov const char *xtensa_format_name(xtensa_isa isa, xtensa_format fmt)
4967f709ce7SMax Filippov {
4977f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
4987f709ce7SMax Filippov
4997f709ce7SMax Filippov CHECK_FORMAT(intisa, fmt, NULL);
5007f709ce7SMax Filippov return intisa->formats[fmt].name;
5017f709ce7SMax Filippov }
5027f709ce7SMax Filippov
5037f709ce7SMax Filippov
xtensa_format_lookup(xtensa_isa isa,const char * fmtname)5047f709ce7SMax Filippov xtensa_format xtensa_format_lookup(xtensa_isa isa, const char *fmtname)
5057f709ce7SMax Filippov {
5067f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
5077f709ce7SMax Filippov int fmt;
5087f709ce7SMax Filippov
5097f709ce7SMax Filippov if (!fmtname || !*fmtname) {
5107f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_format;
5117f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid format name");
5127f709ce7SMax Filippov return XTENSA_UNDEFINED;
5137f709ce7SMax Filippov }
5147f709ce7SMax Filippov
5157f709ce7SMax Filippov for (fmt = 0; fmt < intisa->num_formats; fmt++) {
5167f709ce7SMax Filippov if (strcasecmp(fmtname, intisa->formats[fmt].name) == 0) {
5177f709ce7SMax Filippov return fmt;
5187f709ce7SMax Filippov }
5197f709ce7SMax Filippov }
5207f709ce7SMax Filippov
5217f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_format;
5227f709ce7SMax Filippov sprintf(xtisa_error_msg, "format \"%s\" not recognized", fmtname);
5237f709ce7SMax Filippov return XTENSA_UNDEFINED;
5247f709ce7SMax Filippov }
5257f709ce7SMax Filippov
5267f709ce7SMax Filippov
xtensa_format_decode(xtensa_isa isa,const xtensa_insnbuf insn)5277f709ce7SMax Filippov xtensa_format xtensa_format_decode(xtensa_isa isa, const xtensa_insnbuf insn)
5287f709ce7SMax Filippov {
5297f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
5307f709ce7SMax Filippov xtensa_format fmt;
5317f709ce7SMax Filippov
5327f709ce7SMax Filippov fmt = (intisa->format_decode_fn)(insn);
5337f709ce7SMax Filippov if (fmt != XTENSA_UNDEFINED) {
5347f709ce7SMax Filippov return fmt;
5357f709ce7SMax Filippov }
5367f709ce7SMax Filippov
5377f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_format;
5387f709ce7SMax Filippov strcpy(xtisa_error_msg, "cannot decode instruction format");
5397f709ce7SMax Filippov return XTENSA_UNDEFINED;
5407f709ce7SMax Filippov }
5417f709ce7SMax Filippov
5427f709ce7SMax Filippov
xtensa_format_encode(xtensa_isa isa,xtensa_format fmt,xtensa_insnbuf insn)5437f709ce7SMax Filippov int xtensa_format_encode(xtensa_isa isa, xtensa_format fmt,
5447f709ce7SMax Filippov xtensa_insnbuf insn)
5457f709ce7SMax Filippov {
5467f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
5477f709ce7SMax Filippov
5487f709ce7SMax Filippov CHECK_FORMAT(intisa, fmt, -1);
5497f709ce7SMax Filippov (*intisa->formats[fmt].encode_fn)(insn);
5507f709ce7SMax Filippov return 0;
5517f709ce7SMax Filippov }
5527f709ce7SMax Filippov
5537f709ce7SMax Filippov
xtensa_format_length(xtensa_isa isa,xtensa_format fmt)5547f709ce7SMax Filippov int xtensa_format_length(xtensa_isa isa, xtensa_format fmt)
5557f709ce7SMax Filippov {
5567f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
5577f709ce7SMax Filippov
5587f709ce7SMax Filippov CHECK_FORMAT(intisa, fmt, XTENSA_UNDEFINED);
5597f709ce7SMax Filippov return intisa->formats[fmt].length;
5607f709ce7SMax Filippov }
5617f709ce7SMax Filippov
5627f709ce7SMax Filippov
xtensa_format_num_slots(xtensa_isa isa,xtensa_format fmt)5637f709ce7SMax Filippov int xtensa_format_num_slots(xtensa_isa isa, xtensa_format fmt)
5647f709ce7SMax Filippov {
5657f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
5667f709ce7SMax Filippov
5677f709ce7SMax Filippov CHECK_FORMAT(intisa, fmt, XTENSA_UNDEFINED);
5687f709ce7SMax Filippov return intisa->formats[fmt].num_slots;
5697f709ce7SMax Filippov }
5707f709ce7SMax Filippov
5717f709ce7SMax Filippov
xtensa_format_slot_nop_opcode(xtensa_isa isa,xtensa_format fmt,int slot)5727f709ce7SMax Filippov xtensa_opcode xtensa_format_slot_nop_opcode(xtensa_isa isa, xtensa_format fmt,
5737f709ce7SMax Filippov int slot)
5747f709ce7SMax Filippov {
5757f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
5767f709ce7SMax Filippov int slot_id;
5777f709ce7SMax Filippov
5787f709ce7SMax Filippov CHECK_FORMAT(intisa, fmt, XTENSA_UNDEFINED);
5797f709ce7SMax Filippov CHECK_SLOT(intisa, fmt, slot, XTENSA_UNDEFINED);
5807f709ce7SMax Filippov
5817f709ce7SMax Filippov slot_id = intisa->formats[fmt].slot_id[slot];
5827f709ce7SMax Filippov return xtensa_opcode_lookup(isa, intisa->slots[slot_id].nop_name);
5837f709ce7SMax Filippov }
5847f709ce7SMax Filippov
5857f709ce7SMax Filippov
xtensa_format_get_slot(xtensa_isa isa,xtensa_format fmt,int slot,const xtensa_insnbuf insn,xtensa_insnbuf slotbuf)5867f709ce7SMax Filippov int xtensa_format_get_slot(xtensa_isa isa, xtensa_format fmt, int slot,
5877f709ce7SMax Filippov const xtensa_insnbuf insn, xtensa_insnbuf slotbuf)
5887f709ce7SMax Filippov {
5897f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
5907f709ce7SMax Filippov int slot_id;
5917f709ce7SMax Filippov
5927f709ce7SMax Filippov CHECK_FORMAT(intisa, fmt, -1);
5937f709ce7SMax Filippov CHECK_SLOT(intisa, fmt, slot, -1);
5947f709ce7SMax Filippov
5957f709ce7SMax Filippov slot_id = intisa->formats[fmt].slot_id[slot];
5967f709ce7SMax Filippov (*intisa->slots[slot_id].get_fn)(insn, slotbuf);
5977f709ce7SMax Filippov return 0;
5987f709ce7SMax Filippov }
5997f709ce7SMax Filippov
6007f709ce7SMax Filippov
xtensa_format_set_slot(xtensa_isa isa,xtensa_format fmt,int slot,xtensa_insnbuf insn,const xtensa_insnbuf slotbuf)6017f709ce7SMax Filippov int xtensa_format_set_slot(xtensa_isa isa, xtensa_format fmt, int slot,
6027f709ce7SMax Filippov xtensa_insnbuf insn, const xtensa_insnbuf slotbuf)
6037f709ce7SMax Filippov {
6047f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
6057f709ce7SMax Filippov int slot_id;
6067f709ce7SMax Filippov
6077f709ce7SMax Filippov CHECK_FORMAT(intisa, fmt, -1);
6087f709ce7SMax Filippov CHECK_SLOT(intisa, fmt, slot, -1);
6097f709ce7SMax Filippov
6107f709ce7SMax Filippov slot_id = intisa->formats[fmt].slot_id[slot];
6117f709ce7SMax Filippov (*intisa->slots[slot_id].set_fn)(insn, slotbuf);
6127f709ce7SMax Filippov return 0;
6137f709ce7SMax Filippov }
6147f709ce7SMax Filippov
6157f709ce7SMax Filippov
6167f709ce7SMax Filippov /* Opcode information. */
6177f709ce7SMax Filippov
6187f709ce7SMax Filippov
6197f709ce7SMax Filippov #define CHECK_OPCODE(INTISA, OPC, ERRVAL) \
6207f709ce7SMax Filippov do { \
6217f709ce7SMax Filippov if ((OPC) < 0 || (OPC) >= (INTISA)->num_opcodes) { \
6227f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_opcode; \
6237f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid opcode specifier"); \
6247f709ce7SMax Filippov return ERRVAL; \
6257f709ce7SMax Filippov } \
6267f709ce7SMax Filippov } while (0)
6277f709ce7SMax Filippov
6287f709ce7SMax Filippov
xtensa_opcode_lookup(xtensa_isa isa,const char * opname)6297f709ce7SMax Filippov xtensa_opcode xtensa_opcode_lookup(xtensa_isa isa, const char *opname)
6307f709ce7SMax Filippov {
6317f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
6327f709ce7SMax Filippov xtensa_lookup_entry entry, *result = 0;
6337f709ce7SMax Filippov
6347f709ce7SMax Filippov if (!opname || !*opname) {
6357f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_opcode;
6367f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid opcode name");
6377f709ce7SMax Filippov return XTENSA_UNDEFINED;
6387f709ce7SMax Filippov }
6397f709ce7SMax Filippov
6407f709ce7SMax Filippov if (intisa->num_opcodes != 0) {
6417f709ce7SMax Filippov entry.key = opname;
6427f709ce7SMax Filippov result = bsearch(&entry, intisa->opname_lookup_table,
6437f709ce7SMax Filippov intisa->num_opcodes, sizeof(xtensa_lookup_entry),
6447f709ce7SMax Filippov xtensa_isa_name_compare);
6457f709ce7SMax Filippov }
6467f709ce7SMax Filippov
6477f709ce7SMax Filippov if (!result) {
6487f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_opcode;
6497f709ce7SMax Filippov sprintf(xtisa_error_msg, "opcode \"%s\" not recognized", opname);
6507f709ce7SMax Filippov return XTENSA_UNDEFINED;
6517f709ce7SMax Filippov }
6527f709ce7SMax Filippov
6537f709ce7SMax Filippov return result->u.opcode;
6547f709ce7SMax Filippov }
6557f709ce7SMax Filippov
6567f709ce7SMax Filippov
xtensa_opcode_decode(xtensa_isa isa,xtensa_format fmt,int slot,const xtensa_insnbuf slotbuf)6577f709ce7SMax Filippov xtensa_opcode xtensa_opcode_decode(xtensa_isa isa, xtensa_format fmt, int slot,
6587f709ce7SMax Filippov const xtensa_insnbuf slotbuf)
6597f709ce7SMax Filippov {
6607f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
6617f709ce7SMax Filippov int slot_id;
6627f709ce7SMax Filippov xtensa_opcode opc;
6637f709ce7SMax Filippov
6647f709ce7SMax Filippov CHECK_FORMAT(intisa, fmt, XTENSA_UNDEFINED);
6657f709ce7SMax Filippov CHECK_SLOT(intisa, fmt, slot, XTENSA_UNDEFINED);
6667f709ce7SMax Filippov
6677f709ce7SMax Filippov slot_id = intisa->formats[fmt].slot_id[slot];
6687f709ce7SMax Filippov
6697f709ce7SMax Filippov opc = (intisa->slots[slot_id].opcode_decode_fn) (slotbuf);
6707f709ce7SMax Filippov if (opc != XTENSA_UNDEFINED) {
6717f709ce7SMax Filippov return opc;
6727f709ce7SMax Filippov }
6737f709ce7SMax Filippov
6747f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_opcode;
6757f709ce7SMax Filippov strcpy(xtisa_error_msg, "cannot decode opcode");
6767f709ce7SMax Filippov return XTENSA_UNDEFINED;
6777f709ce7SMax Filippov }
6787f709ce7SMax Filippov
6797f709ce7SMax Filippov
xtensa_opcode_encode(xtensa_isa isa,xtensa_format fmt,int slot,xtensa_insnbuf slotbuf,xtensa_opcode opc)6807f709ce7SMax Filippov int xtensa_opcode_encode(xtensa_isa isa, xtensa_format fmt, int slot,
6817f709ce7SMax Filippov xtensa_insnbuf slotbuf, xtensa_opcode opc)
6827f709ce7SMax Filippov {
6837f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
6847f709ce7SMax Filippov int slot_id;
6857f709ce7SMax Filippov xtensa_opcode_encode_fn encode_fn;
6867f709ce7SMax Filippov
6877f709ce7SMax Filippov CHECK_FORMAT(intisa, fmt, -1);
6887f709ce7SMax Filippov CHECK_SLOT(intisa, fmt, slot, -1);
6897f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, -1);
6907f709ce7SMax Filippov
6917f709ce7SMax Filippov slot_id = intisa->formats[fmt].slot_id[slot];
6927f709ce7SMax Filippov encode_fn = intisa->opcodes[opc].encode_fns[slot_id];
6937f709ce7SMax Filippov if (!encode_fn) {
6947f709ce7SMax Filippov xtisa_errno = xtensa_isa_wrong_slot;
6957f709ce7SMax Filippov sprintf(xtisa_error_msg,
6967f709ce7SMax Filippov "opcode \"%s\" is not allowed in slot %d of format \"%s\"",
6977f709ce7SMax Filippov intisa->opcodes[opc].name, slot, intisa->formats[fmt].name);
6987f709ce7SMax Filippov return -1;
6997f709ce7SMax Filippov }
7007f709ce7SMax Filippov (*encode_fn)(slotbuf);
7017f709ce7SMax Filippov return 0;
7027f709ce7SMax Filippov }
7037f709ce7SMax Filippov
7047f709ce7SMax Filippov
xtensa_opcode_name(xtensa_isa isa,xtensa_opcode opc)7057f709ce7SMax Filippov const char *xtensa_opcode_name(xtensa_isa isa, xtensa_opcode opc)
7067f709ce7SMax Filippov {
7077f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
7087f709ce7SMax Filippov
7097f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, NULL);
7107f709ce7SMax Filippov return intisa->opcodes[opc].name;
7117f709ce7SMax Filippov }
7127f709ce7SMax Filippov
7137f709ce7SMax Filippov
xtensa_opcode_is_branch(xtensa_isa isa,xtensa_opcode opc)7147f709ce7SMax Filippov int xtensa_opcode_is_branch(xtensa_isa isa, xtensa_opcode opc)
7157f709ce7SMax Filippov {
7167f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
7177f709ce7SMax Filippov
7187f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
7197f709ce7SMax Filippov if ((intisa->opcodes[opc].flags & XTENSA_OPCODE_IS_BRANCH) != 0) {
7207f709ce7SMax Filippov return 1;
7217f709ce7SMax Filippov }
7227f709ce7SMax Filippov return 0;
7237f709ce7SMax Filippov }
7247f709ce7SMax Filippov
7257f709ce7SMax Filippov
xtensa_opcode_is_jump(xtensa_isa isa,xtensa_opcode opc)7267f709ce7SMax Filippov int xtensa_opcode_is_jump(xtensa_isa isa, xtensa_opcode opc)
7277f709ce7SMax Filippov {
7287f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
7297f709ce7SMax Filippov
7307f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
7317f709ce7SMax Filippov if ((intisa->opcodes[opc].flags & XTENSA_OPCODE_IS_JUMP) != 0) {
7327f709ce7SMax Filippov return 1;
7337f709ce7SMax Filippov }
7347f709ce7SMax Filippov return 0;
7357f709ce7SMax Filippov }
7367f709ce7SMax Filippov
7377f709ce7SMax Filippov
xtensa_opcode_is_loop(xtensa_isa isa,xtensa_opcode opc)7387f709ce7SMax Filippov int xtensa_opcode_is_loop(xtensa_isa isa, xtensa_opcode opc)
7397f709ce7SMax Filippov {
7407f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
7417f709ce7SMax Filippov
7427f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
7437f709ce7SMax Filippov if ((intisa->opcodes[opc].flags & XTENSA_OPCODE_IS_LOOP) != 0) {
7447f709ce7SMax Filippov return 1;
7457f709ce7SMax Filippov }
7467f709ce7SMax Filippov return 0;
7477f709ce7SMax Filippov }
7487f709ce7SMax Filippov
7497f709ce7SMax Filippov
xtensa_opcode_is_call(xtensa_isa isa,xtensa_opcode opc)7507f709ce7SMax Filippov int xtensa_opcode_is_call(xtensa_isa isa, xtensa_opcode opc)
7517f709ce7SMax Filippov {
7527f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
7537f709ce7SMax Filippov
7547f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
7557f709ce7SMax Filippov if ((intisa->opcodes[opc].flags & XTENSA_OPCODE_IS_CALL) != 0) {
7567f709ce7SMax Filippov return 1;
7577f709ce7SMax Filippov }
7587f709ce7SMax Filippov return 0;
7597f709ce7SMax Filippov }
7607f709ce7SMax Filippov
7617f709ce7SMax Filippov
xtensa_opcode_num_operands(xtensa_isa isa,xtensa_opcode opc)7627f709ce7SMax Filippov int xtensa_opcode_num_operands(xtensa_isa isa, xtensa_opcode opc)
7637f709ce7SMax Filippov {
7647f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
7657f709ce7SMax Filippov int iclass_id;
7667f709ce7SMax Filippov
7677f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
7687f709ce7SMax Filippov iclass_id = intisa->opcodes[opc].iclass_id;
7697f709ce7SMax Filippov return intisa->iclasses[iclass_id].num_operands;
7707f709ce7SMax Filippov }
7717f709ce7SMax Filippov
7727f709ce7SMax Filippov
xtensa_opcode_num_stateOperands(xtensa_isa isa,xtensa_opcode opc)7737f709ce7SMax Filippov int xtensa_opcode_num_stateOperands(xtensa_isa isa, xtensa_opcode opc)
7747f709ce7SMax Filippov {
7757f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
7767f709ce7SMax Filippov int iclass_id;
7777f709ce7SMax Filippov
7787f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
7797f709ce7SMax Filippov iclass_id = intisa->opcodes[opc].iclass_id;
7807f709ce7SMax Filippov return intisa->iclasses[iclass_id].num_stateOperands;
7817f709ce7SMax Filippov }
7827f709ce7SMax Filippov
7837f709ce7SMax Filippov
xtensa_opcode_num_interfaceOperands(xtensa_isa isa,xtensa_opcode opc)7847f709ce7SMax Filippov int xtensa_opcode_num_interfaceOperands(xtensa_isa isa, xtensa_opcode opc)
7857f709ce7SMax Filippov {
7867f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
7877f709ce7SMax Filippov int iclass_id;
7887f709ce7SMax Filippov
7897f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
7907f709ce7SMax Filippov iclass_id = intisa->opcodes[opc].iclass_id;
7917f709ce7SMax Filippov return intisa->iclasses[iclass_id].num_interfaceOperands;
7927f709ce7SMax Filippov }
7937f709ce7SMax Filippov
7947f709ce7SMax Filippov
xtensa_opcode_num_funcUnit_uses(xtensa_isa isa,xtensa_opcode opc)7957f709ce7SMax Filippov int xtensa_opcode_num_funcUnit_uses(xtensa_isa isa, xtensa_opcode opc)
7967f709ce7SMax Filippov {
7977f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
7987f709ce7SMax Filippov
7997f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
8007f709ce7SMax Filippov return intisa->opcodes[opc].num_funcUnit_uses;
8017f709ce7SMax Filippov }
8027f709ce7SMax Filippov
8037f709ce7SMax Filippov
xtensa_opcode_funcUnit_use(xtensa_isa isa,xtensa_opcode opc,int u)8047f709ce7SMax Filippov xtensa_funcUnit_use *xtensa_opcode_funcUnit_use(xtensa_isa isa,
8057f709ce7SMax Filippov xtensa_opcode opc, int u)
8067f709ce7SMax Filippov {
8077f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
8087f709ce7SMax Filippov
8097f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, NULL);
8107f709ce7SMax Filippov if (u < 0 || u >= intisa->opcodes[opc].num_funcUnit_uses) {
8117f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_funcUnit;
8127f709ce7SMax Filippov sprintf(xtisa_error_msg, "invalid functional unit use number (%d); "
8137f709ce7SMax Filippov "opcode \"%s\" has %d", u, intisa->opcodes[opc].name,
8147f709ce7SMax Filippov intisa->opcodes[opc].num_funcUnit_uses);
8157f709ce7SMax Filippov return NULL;
8167f709ce7SMax Filippov }
8177f709ce7SMax Filippov return &intisa->opcodes[opc].funcUnit_uses[u];
8187f709ce7SMax Filippov }
8197f709ce7SMax Filippov
8207f709ce7SMax Filippov
8217f709ce7SMax Filippov /* Operand information. */
8227f709ce7SMax Filippov
8237f709ce7SMax Filippov
8247f709ce7SMax Filippov #define CHECK_OPERAND(INTISA, OPC, ICLASS, OPND, ERRVAL) \
8257f709ce7SMax Filippov do { \
8267f709ce7SMax Filippov if ((OPND) < 0 || (OPND) >= (ICLASS)->num_operands) { \
8277f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_operand; \
8287f709ce7SMax Filippov sprintf(xtisa_error_msg, "invalid operand number (%d); " \
8297f709ce7SMax Filippov "opcode \"%s\" has %d operands", (OPND), \
8307f709ce7SMax Filippov (INTISA)->opcodes[(OPC)].name, (ICLASS)->num_operands); \
8317f709ce7SMax Filippov return ERRVAL; \
8327f709ce7SMax Filippov } \
8337f709ce7SMax Filippov } while (0)
8347f709ce7SMax Filippov
8357f709ce7SMax Filippov
get_operand(xtensa_isa_internal * intisa,xtensa_opcode opc,int opnd)8367f709ce7SMax Filippov static xtensa_operand_internal *get_operand(xtensa_isa_internal *intisa,
8377f709ce7SMax Filippov xtensa_opcode opc, int opnd)
8387f709ce7SMax Filippov {
8397f709ce7SMax Filippov xtensa_iclass_internal *iclass;
8407f709ce7SMax Filippov int iclass_id, operand_id;
8417f709ce7SMax Filippov
8427f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, NULL);
8437f709ce7SMax Filippov iclass_id = intisa->opcodes[opc].iclass_id;
8447f709ce7SMax Filippov iclass = &intisa->iclasses[iclass_id];
8457f709ce7SMax Filippov CHECK_OPERAND(intisa, opc, iclass, opnd, NULL);
8467f709ce7SMax Filippov operand_id = iclass->operands[opnd].u.operand_id;
8477f709ce7SMax Filippov return &intisa->operands[operand_id];
8487f709ce7SMax Filippov }
8497f709ce7SMax Filippov
8507f709ce7SMax Filippov
xtensa_operand_name(xtensa_isa isa,xtensa_opcode opc,int opnd)8517f709ce7SMax Filippov const char *xtensa_operand_name(xtensa_isa isa, xtensa_opcode opc, int opnd)
8527f709ce7SMax Filippov {
8537f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
8547f709ce7SMax Filippov xtensa_operand_internal *intop;
8557f709ce7SMax Filippov
8567f709ce7SMax Filippov intop = get_operand(intisa, opc, opnd);
8577f709ce7SMax Filippov if (!intop) {
8587f709ce7SMax Filippov return NULL;
8597f709ce7SMax Filippov }
8607f709ce7SMax Filippov return intop->name;
8617f709ce7SMax Filippov }
8627f709ce7SMax Filippov
8637f709ce7SMax Filippov
xtensa_operand_is_visible(xtensa_isa isa,xtensa_opcode opc,int opnd)8647f709ce7SMax Filippov int xtensa_operand_is_visible(xtensa_isa isa, xtensa_opcode opc, int opnd)
8657f709ce7SMax Filippov {
8667f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
8677f709ce7SMax Filippov xtensa_iclass_internal *iclass;
8687f709ce7SMax Filippov int iclass_id, operand_id;
8697f709ce7SMax Filippov xtensa_operand_internal *intop;
8707f709ce7SMax Filippov
8717f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
8727f709ce7SMax Filippov iclass_id = intisa->opcodes[opc].iclass_id;
8737f709ce7SMax Filippov iclass = &intisa->iclasses[iclass_id];
8747f709ce7SMax Filippov CHECK_OPERAND(intisa, opc, iclass, opnd, XTENSA_UNDEFINED);
8757f709ce7SMax Filippov
8767f709ce7SMax Filippov /* Special case for "sout" operands. */
8777f709ce7SMax Filippov if (iclass->operands[opnd].inout == 's') {
8787f709ce7SMax Filippov return 0;
8797f709ce7SMax Filippov }
8807f709ce7SMax Filippov
8817f709ce7SMax Filippov operand_id = iclass->operands[opnd].u.operand_id;
8827f709ce7SMax Filippov intop = &intisa->operands[operand_id];
8837f709ce7SMax Filippov
8847f709ce7SMax Filippov if ((intop->flags & XTENSA_OPERAND_IS_INVISIBLE) == 0) {
8857f709ce7SMax Filippov return 1;
8867f709ce7SMax Filippov }
8877f709ce7SMax Filippov return 0;
8887f709ce7SMax Filippov }
8897f709ce7SMax Filippov
8907f709ce7SMax Filippov
xtensa_operand_inout(xtensa_isa isa,xtensa_opcode opc,int opnd)8917f709ce7SMax Filippov char xtensa_operand_inout(xtensa_isa isa, xtensa_opcode opc, int opnd)
8927f709ce7SMax Filippov {
8937f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
8947f709ce7SMax Filippov xtensa_iclass_internal *iclass;
8957f709ce7SMax Filippov int iclass_id;
8967f709ce7SMax Filippov char inout;
8977f709ce7SMax Filippov
8987f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, 0);
8997f709ce7SMax Filippov iclass_id = intisa->opcodes[opc].iclass_id;
9007f709ce7SMax Filippov iclass = &intisa->iclasses[iclass_id];
9017f709ce7SMax Filippov CHECK_OPERAND(intisa, opc, iclass, opnd, 0);
9027f709ce7SMax Filippov inout = iclass->operands[opnd].inout;
9037f709ce7SMax Filippov
9047f709ce7SMax Filippov /* Special case for "sout" and "_sin" operands. */
9057f709ce7SMax Filippov if (inout == 's') {
9067f709ce7SMax Filippov return 'o';
9077f709ce7SMax Filippov }
9087f709ce7SMax Filippov if (inout == 't') {
9097f709ce7SMax Filippov return 'i';
9107f709ce7SMax Filippov }
9117f709ce7SMax Filippov return inout;
9127f709ce7SMax Filippov }
9137f709ce7SMax Filippov
9147f709ce7SMax Filippov
xtensa_operand_get_field(xtensa_isa isa,xtensa_opcode opc,int opnd,xtensa_format fmt,int slot,const xtensa_insnbuf slotbuf,uint32_t * valp)9157f709ce7SMax Filippov int xtensa_operand_get_field(xtensa_isa isa, xtensa_opcode opc, int opnd,
9167f709ce7SMax Filippov xtensa_format fmt, int slot,
9177f709ce7SMax Filippov const xtensa_insnbuf slotbuf, uint32_t *valp)
9187f709ce7SMax Filippov {
9197f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
9207f709ce7SMax Filippov xtensa_operand_internal *intop;
9217f709ce7SMax Filippov int slot_id;
9227f709ce7SMax Filippov xtensa_get_field_fn get_fn;
9237f709ce7SMax Filippov
9247f709ce7SMax Filippov intop = get_operand(intisa, opc, opnd);
9257f709ce7SMax Filippov if (!intop) {
9267f709ce7SMax Filippov return -1;
9277f709ce7SMax Filippov }
9287f709ce7SMax Filippov
9297f709ce7SMax Filippov CHECK_FORMAT(intisa, fmt, -1);
9307f709ce7SMax Filippov CHECK_SLOT(intisa, fmt, slot, -1);
9317f709ce7SMax Filippov
9327f709ce7SMax Filippov slot_id = intisa->formats[fmt].slot_id[slot];
9337f709ce7SMax Filippov if (intop->field_id == XTENSA_UNDEFINED) {
9347f709ce7SMax Filippov xtisa_errno = xtensa_isa_no_field;
9357f709ce7SMax Filippov strcpy(xtisa_error_msg, "implicit operand has no field");
9367f709ce7SMax Filippov return -1;
9377f709ce7SMax Filippov }
9387f709ce7SMax Filippov get_fn = intisa->slots[slot_id].get_field_fns[intop->field_id];
9397f709ce7SMax Filippov if (!get_fn) {
9407f709ce7SMax Filippov xtisa_errno = xtensa_isa_wrong_slot;
9417f709ce7SMax Filippov sprintf(xtisa_error_msg,
9427f709ce7SMax Filippov "operand \"%s\" does not exist in slot %d of format \"%s\"",
9437f709ce7SMax Filippov intop->name, slot, intisa->formats[fmt].name);
9447f709ce7SMax Filippov return -1;
9457f709ce7SMax Filippov }
9467f709ce7SMax Filippov *valp = (*get_fn)(slotbuf);
9477f709ce7SMax Filippov return 0;
9487f709ce7SMax Filippov }
9497f709ce7SMax Filippov
9507f709ce7SMax Filippov
xtensa_operand_set_field(xtensa_isa isa,xtensa_opcode opc,int opnd,xtensa_format fmt,int slot,xtensa_insnbuf slotbuf,uint32_t val)9517f709ce7SMax Filippov int xtensa_operand_set_field(xtensa_isa isa, xtensa_opcode opc, int opnd,
9527f709ce7SMax Filippov xtensa_format fmt, int slot,
9537f709ce7SMax Filippov xtensa_insnbuf slotbuf, uint32_t val)
9547f709ce7SMax Filippov {
9557f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
9567f709ce7SMax Filippov xtensa_operand_internal *intop;
9577f709ce7SMax Filippov int slot_id;
9587f709ce7SMax Filippov xtensa_set_field_fn set_fn;
9597f709ce7SMax Filippov
9607f709ce7SMax Filippov intop = get_operand(intisa, opc, opnd);
9617f709ce7SMax Filippov if (!intop) {
9627f709ce7SMax Filippov return -1;
9637f709ce7SMax Filippov }
9647f709ce7SMax Filippov
9657f709ce7SMax Filippov CHECK_FORMAT(intisa, fmt, -1);
9667f709ce7SMax Filippov CHECK_SLOT(intisa, fmt, slot, -1);
9677f709ce7SMax Filippov
9687f709ce7SMax Filippov slot_id = intisa->formats[fmt].slot_id[slot];
9697f709ce7SMax Filippov if (intop->field_id == XTENSA_UNDEFINED) {
9707f709ce7SMax Filippov xtisa_errno = xtensa_isa_no_field;
9717f709ce7SMax Filippov strcpy(xtisa_error_msg, "implicit operand has no field");
9727f709ce7SMax Filippov return -1;
9737f709ce7SMax Filippov }
9747f709ce7SMax Filippov set_fn = intisa->slots[slot_id].set_field_fns[intop->field_id];
9757f709ce7SMax Filippov if (!set_fn) {
9767f709ce7SMax Filippov xtisa_errno = xtensa_isa_wrong_slot;
9777f709ce7SMax Filippov sprintf(xtisa_error_msg,
9787f709ce7SMax Filippov "operand \"%s\" does not exist in slot %d of format \"%s\"",
9797f709ce7SMax Filippov intop->name, slot, intisa->formats[fmt].name);
9807f709ce7SMax Filippov return -1;
9817f709ce7SMax Filippov }
9827f709ce7SMax Filippov (*set_fn)(slotbuf, val);
9837f709ce7SMax Filippov return 0;
9847f709ce7SMax Filippov }
9857f709ce7SMax Filippov
9867f709ce7SMax Filippov
xtensa_operand_encode(xtensa_isa isa,xtensa_opcode opc,int opnd,uint32_t * valp)9877f709ce7SMax Filippov int xtensa_operand_encode(xtensa_isa isa, xtensa_opcode opc, int opnd,
9887f709ce7SMax Filippov uint32_t *valp)
9897f709ce7SMax Filippov {
9907f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
9917f709ce7SMax Filippov xtensa_operand_internal *intop;
9927f709ce7SMax Filippov uint32_t test_val, orig_val;
9937f709ce7SMax Filippov
9947f709ce7SMax Filippov intop = get_operand(intisa, opc, opnd);
9957f709ce7SMax Filippov if (!intop) {
9967f709ce7SMax Filippov return -1;
9977f709ce7SMax Filippov }
9987f709ce7SMax Filippov
9997f709ce7SMax Filippov if (!intop->encode) {
10007f709ce7SMax Filippov /*
10017f709ce7SMax Filippov * This is a default operand for a field. How can we tell if the
10027f709ce7SMax Filippov * value fits in the field? Write the value into the field,
10037f709ce7SMax Filippov * read it back, and then make sure we get the same value.
10047f709ce7SMax Filippov */
10057f709ce7SMax Filippov static xtensa_insnbuf tmpbuf;
10067f709ce7SMax Filippov int slot_id;
10077f709ce7SMax Filippov
10087f709ce7SMax Filippov if (!tmpbuf) {
10097f709ce7SMax Filippov tmpbuf = xtensa_insnbuf_alloc(isa);
10107f709ce7SMax Filippov CHECK_ALLOC(tmpbuf, -1);
10117f709ce7SMax Filippov }
10127f709ce7SMax Filippov
10137f709ce7SMax Filippov /*
10147f709ce7SMax Filippov * A default operand is always associated with a field,
10157f709ce7SMax Filippov * but check just to be sure....
10167f709ce7SMax Filippov */
10177f709ce7SMax Filippov if (intop->field_id == XTENSA_UNDEFINED) {
10187f709ce7SMax Filippov xtisa_errno = xtensa_isa_internal_error;
10197f709ce7SMax Filippov strcpy(xtisa_error_msg, "operand has no field");
10207f709ce7SMax Filippov return -1;
10217f709ce7SMax Filippov }
10227f709ce7SMax Filippov
10237f709ce7SMax Filippov /* Find some slot that includes the field. */
10247f709ce7SMax Filippov for (slot_id = 0; slot_id < intisa->num_slots; slot_id++) {
10257f709ce7SMax Filippov xtensa_get_field_fn get_fn =
10267f709ce7SMax Filippov intisa->slots[slot_id].get_field_fns[intop->field_id];
10277f709ce7SMax Filippov xtensa_set_field_fn set_fn =
10287f709ce7SMax Filippov intisa->slots[slot_id].set_field_fns[intop->field_id];
10297f709ce7SMax Filippov
10307f709ce7SMax Filippov if (get_fn && set_fn) {
10317f709ce7SMax Filippov (*set_fn)(tmpbuf, *valp);
10327f709ce7SMax Filippov return (*get_fn)(tmpbuf) != *valp;
10337f709ce7SMax Filippov }
10347f709ce7SMax Filippov }
10357f709ce7SMax Filippov
10367f709ce7SMax Filippov /* Couldn't find any slot containing the field.... */
10377f709ce7SMax Filippov xtisa_errno = xtensa_isa_no_field;
10387f709ce7SMax Filippov strcpy(xtisa_error_msg, "field does not exist in any slot");
10397f709ce7SMax Filippov return -1;
10407f709ce7SMax Filippov }
10417f709ce7SMax Filippov
10427f709ce7SMax Filippov /*
10437f709ce7SMax Filippov * Encode the value. In some cases, the encoding function may detect
10447f709ce7SMax Filippov * errors, but most of the time the only way to determine if the value
10457f709ce7SMax Filippov * was successfully encoded is to decode it and check if it matches
10467f709ce7SMax Filippov * the original value.
10477f709ce7SMax Filippov */
10487f709ce7SMax Filippov orig_val = *valp;
10497f709ce7SMax Filippov if ((*intop->encode)(valp) ||
10507f709ce7SMax Filippov (test_val = *valp, (*intop->decode)(&test_val)) ||
10517f709ce7SMax Filippov test_val != orig_val) {
10527f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_value;
10537f709ce7SMax Filippov sprintf(xtisa_error_msg, "cannot encode operand value 0x%08x", *valp);
10547f709ce7SMax Filippov return -1;
10557f709ce7SMax Filippov }
10567f709ce7SMax Filippov
10577f709ce7SMax Filippov return 0;
10587f709ce7SMax Filippov }
10597f709ce7SMax Filippov
10607f709ce7SMax Filippov
xtensa_operand_decode(xtensa_isa isa,xtensa_opcode opc,int opnd,uint32_t * valp)10617f709ce7SMax Filippov int xtensa_operand_decode(xtensa_isa isa, xtensa_opcode opc, int opnd,
10627f709ce7SMax Filippov uint32_t *valp)
10637f709ce7SMax Filippov {
10647f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
10657f709ce7SMax Filippov xtensa_operand_internal *intop;
10667f709ce7SMax Filippov
10677f709ce7SMax Filippov intop = get_operand(intisa, opc, opnd);
10687f709ce7SMax Filippov if (!intop) {
10697f709ce7SMax Filippov return -1;
10707f709ce7SMax Filippov }
10717f709ce7SMax Filippov
10727f709ce7SMax Filippov /* Use identity function for "default" operands. */
10737f709ce7SMax Filippov if (!intop->decode) {
10747f709ce7SMax Filippov return 0;
10757f709ce7SMax Filippov }
10767f709ce7SMax Filippov
10777f709ce7SMax Filippov if ((*intop->decode)(valp)) {
10787f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_value;
10797f709ce7SMax Filippov sprintf(xtisa_error_msg, "cannot decode operand value 0x%08x", *valp);
10807f709ce7SMax Filippov return -1;
10817f709ce7SMax Filippov }
10827f709ce7SMax Filippov return 0;
10837f709ce7SMax Filippov }
10847f709ce7SMax Filippov
10857f709ce7SMax Filippov
xtensa_operand_is_register(xtensa_isa isa,xtensa_opcode opc,int opnd)10867f709ce7SMax Filippov int xtensa_operand_is_register(xtensa_isa isa, xtensa_opcode opc, int opnd)
10877f709ce7SMax Filippov {
10887f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
10897f709ce7SMax Filippov xtensa_operand_internal *intop;
10907f709ce7SMax Filippov
10917f709ce7SMax Filippov intop = get_operand(intisa, opc, opnd);
10927f709ce7SMax Filippov if (!intop) {
10937f709ce7SMax Filippov return XTENSA_UNDEFINED;
10947f709ce7SMax Filippov }
10957f709ce7SMax Filippov
10967f709ce7SMax Filippov if ((intop->flags & XTENSA_OPERAND_IS_REGISTER) != 0) {
10977f709ce7SMax Filippov return 1;
10987f709ce7SMax Filippov }
10997f709ce7SMax Filippov return 0;
11007f709ce7SMax Filippov }
11017f709ce7SMax Filippov
11027f709ce7SMax Filippov
xtensa_operand_regfile(xtensa_isa isa,xtensa_opcode opc,int opnd)11037f709ce7SMax Filippov xtensa_regfile xtensa_operand_regfile(xtensa_isa isa, xtensa_opcode opc,
11047f709ce7SMax Filippov int opnd)
11057f709ce7SMax Filippov {
11067f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
11077f709ce7SMax Filippov xtensa_operand_internal *intop;
11087f709ce7SMax Filippov
11097f709ce7SMax Filippov intop = get_operand(intisa, opc, opnd);
11107f709ce7SMax Filippov if (!intop) {
11117f709ce7SMax Filippov return XTENSA_UNDEFINED;
11127f709ce7SMax Filippov }
11137f709ce7SMax Filippov
11147f709ce7SMax Filippov return intop->regfile;
11157f709ce7SMax Filippov }
11167f709ce7SMax Filippov
11177f709ce7SMax Filippov
xtensa_operand_num_regs(xtensa_isa isa,xtensa_opcode opc,int opnd)11187f709ce7SMax Filippov int xtensa_operand_num_regs(xtensa_isa isa, xtensa_opcode opc, int opnd)
11197f709ce7SMax Filippov {
11207f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
11217f709ce7SMax Filippov xtensa_operand_internal *intop;
11227f709ce7SMax Filippov
11237f709ce7SMax Filippov intop = get_operand(intisa, opc, opnd);
11247f709ce7SMax Filippov if (!intop) {
11257f709ce7SMax Filippov return XTENSA_UNDEFINED;
11267f709ce7SMax Filippov }
11277f709ce7SMax Filippov
11287f709ce7SMax Filippov return intop->num_regs;
11297f709ce7SMax Filippov }
11307f709ce7SMax Filippov
11317f709ce7SMax Filippov
xtensa_operand_is_known_reg(xtensa_isa isa,xtensa_opcode opc,int opnd)11327f709ce7SMax Filippov int xtensa_operand_is_known_reg(xtensa_isa isa, xtensa_opcode opc, int opnd)
11337f709ce7SMax Filippov {
11347f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
11357f709ce7SMax Filippov xtensa_operand_internal *intop;
11367f709ce7SMax Filippov
11377f709ce7SMax Filippov intop = get_operand(intisa, opc, opnd);
11387f709ce7SMax Filippov if (!intop) {
11397f709ce7SMax Filippov return XTENSA_UNDEFINED;
11407f709ce7SMax Filippov }
11417f709ce7SMax Filippov
11427f709ce7SMax Filippov if ((intop->flags & XTENSA_OPERAND_IS_UNKNOWN) == 0) {
11437f709ce7SMax Filippov return 1;
11447f709ce7SMax Filippov }
11457f709ce7SMax Filippov return 0;
11467f709ce7SMax Filippov }
11477f709ce7SMax Filippov
11487f709ce7SMax Filippov
xtensa_operand_is_PCrelative(xtensa_isa isa,xtensa_opcode opc,int opnd)11497f709ce7SMax Filippov int xtensa_operand_is_PCrelative(xtensa_isa isa, xtensa_opcode opc, int opnd)
11507f709ce7SMax Filippov {
11517f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
11527f709ce7SMax Filippov xtensa_operand_internal *intop;
11537f709ce7SMax Filippov
11547f709ce7SMax Filippov intop = get_operand(intisa, opc, opnd);
11557f709ce7SMax Filippov if (!intop) {
11567f709ce7SMax Filippov return XTENSA_UNDEFINED;
11577f709ce7SMax Filippov }
11587f709ce7SMax Filippov
11597f709ce7SMax Filippov if ((intop->flags & XTENSA_OPERAND_IS_PCRELATIVE) != 0) {
11607f709ce7SMax Filippov return 1;
11617f709ce7SMax Filippov }
11627f709ce7SMax Filippov return 0;
11637f709ce7SMax Filippov }
11647f709ce7SMax Filippov
11657f709ce7SMax Filippov
xtensa_operand_do_reloc(xtensa_isa isa,xtensa_opcode opc,int opnd,uint32_t * valp,uint32_t pc)11667f709ce7SMax Filippov int xtensa_operand_do_reloc(xtensa_isa isa, xtensa_opcode opc, int opnd,
11677f709ce7SMax Filippov uint32_t *valp, uint32_t pc)
11687f709ce7SMax Filippov {
11697f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
11707f709ce7SMax Filippov xtensa_operand_internal *intop;
11717f709ce7SMax Filippov
11727f709ce7SMax Filippov intop = get_operand(intisa, opc, opnd);
11737f709ce7SMax Filippov if (!intop) {
11747f709ce7SMax Filippov return -1;
11757f709ce7SMax Filippov }
11767f709ce7SMax Filippov
11777f709ce7SMax Filippov if ((intop->flags & XTENSA_OPERAND_IS_PCRELATIVE) == 0) {
11787f709ce7SMax Filippov return 0;
11797f709ce7SMax Filippov }
11807f709ce7SMax Filippov
11817f709ce7SMax Filippov if (!intop->do_reloc) {
11827f709ce7SMax Filippov xtisa_errno = xtensa_isa_internal_error;
11837f709ce7SMax Filippov strcpy(xtisa_error_msg, "operand missing do_reloc function");
11847f709ce7SMax Filippov return -1;
11857f709ce7SMax Filippov }
11867f709ce7SMax Filippov
11877f709ce7SMax Filippov if ((*intop->do_reloc)(valp, pc)) {
11887f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_value;
11897f709ce7SMax Filippov sprintf(xtisa_error_msg,
11907f709ce7SMax Filippov "do_reloc failed for value 0x%08x at PC 0x%08x", *valp, pc);
11917f709ce7SMax Filippov return -1;
11927f709ce7SMax Filippov }
11937f709ce7SMax Filippov
11947f709ce7SMax Filippov return 0;
11957f709ce7SMax Filippov }
11967f709ce7SMax Filippov
11977f709ce7SMax Filippov
xtensa_operand_undo_reloc(xtensa_isa isa,xtensa_opcode opc,int opnd,uint32_t * valp,uint32_t pc)11987f709ce7SMax Filippov int xtensa_operand_undo_reloc(xtensa_isa isa, xtensa_opcode opc, int opnd,
11997f709ce7SMax Filippov uint32_t *valp, uint32_t pc)
12007f709ce7SMax Filippov {
12017f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
12027f709ce7SMax Filippov xtensa_operand_internal *intop;
12037f709ce7SMax Filippov
12047f709ce7SMax Filippov intop = get_operand(intisa, opc, opnd);
12057f709ce7SMax Filippov if (!intop) {
12067f709ce7SMax Filippov return -1;
12077f709ce7SMax Filippov }
12087f709ce7SMax Filippov
12097f709ce7SMax Filippov if ((intop->flags & XTENSA_OPERAND_IS_PCRELATIVE) == 0) {
12107f709ce7SMax Filippov return 0;
12117f709ce7SMax Filippov }
12127f709ce7SMax Filippov
12137f709ce7SMax Filippov if (!intop->undo_reloc) {
12147f709ce7SMax Filippov xtisa_errno = xtensa_isa_internal_error;
12157f709ce7SMax Filippov strcpy(xtisa_error_msg, "operand missing undo_reloc function");
12167f709ce7SMax Filippov return -1;
12177f709ce7SMax Filippov }
12187f709ce7SMax Filippov
12197f709ce7SMax Filippov if ((*intop->undo_reloc)(valp, pc)) {
12207f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_value;
12217f709ce7SMax Filippov sprintf(xtisa_error_msg,
12227f709ce7SMax Filippov "undo_reloc failed for value 0x%08x at PC 0x%08x", *valp, pc);
12237f709ce7SMax Filippov return -1;
12247f709ce7SMax Filippov }
12257f709ce7SMax Filippov
12267f709ce7SMax Filippov return 0;
12277f709ce7SMax Filippov }
12287f709ce7SMax Filippov
12297f709ce7SMax Filippov
12307f709ce7SMax Filippov /* State Operands. */
12317f709ce7SMax Filippov
12327f709ce7SMax Filippov
12337f709ce7SMax Filippov #define CHECK_STATE_OPERAND(INTISA, OPC, ICLASS, STOP, ERRVAL) \
12347f709ce7SMax Filippov do { \
12357f709ce7SMax Filippov if ((STOP) < 0 || (STOP) >= (ICLASS)->num_stateOperands) { \
12367f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_operand; \
12377f709ce7SMax Filippov sprintf(xtisa_error_msg, "invalid state operand number (%d); " \
12387f709ce7SMax Filippov "opcode \"%s\" has %d state operands", (STOP), \
12397f709ce7SMax Filippov (INTISA)->opcodes[(OPC)].name, \
12407f709ce7SMax Filippov (ICLASS)->num_stateOperands); \
12417f709ce7SMax Filippov return ERRVAL; \
12427f709ce7SMax Filippov } \
12437f709ce7SMax Filippov } while (0)
12447f709ce7SMax Filippov
12457f709ce7SMax Filippov
xtensa_stateOperand_state(xtensa_isa isa,xtensa_opcode opc,int stOp)12467f709ce7SMax Filippov xtensa_state xtensa_stateOperand_state(xtensa_isa isa, xtensa_opcode opc,
12477f709ce7SMax Filippov int stOp)
12487f709ce7SMax Filippov {
12497f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
12507f709ce7SMax Filippov xtensa_iclass_internal *iclass;
12517f709ce7SMax Filippov int iclass_id;
12527f709ce7SMax Filippov
12537f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
12547f709ce7SMax Filippov iclass_id = intisa->opcodes[opc].iclass_id;
12557f709ce7SMax Filippov iclass = &intisa->iclasses[iclass_id];
12567f709ce7SMax Filippov CHECK_STATE_OPERAND(intisa, opc, iclass, stOp, XTENSA_UNDEFINED);
12577f709ce7SMax Filippov return iclass->stateOperands[stOp].u.state;
12587f709ce7SMax Filippov }
12597f709ce7SMax Filippov
12607f709ce7SMax Filippov
xtensa_stateOperand_inout(xtensa_isa isa,xtensa_opcode opc,int stOp)12617f709ce7SMax Filippov char xtensa_stateOperand_inout(xtensa_isa isa, xtensa_opcode opc, int stOp)
12627f709ce7SMax Filippov {
12637f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
12647f709ce7SMax Filippov xtensa_iclass_internal *iclass;
12657f709ce7SMax Filippov int iclass_id;
12667f709ce7SMax Filippov
12677f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, 0);
12687f709ce7SMax Filippov iclass_id = intisa->opcodes[opc].iclass_id;
12697f709ce7SMax Filippov iclass = &intisa->iclasses[iclass_id];
12707f709ce7SMax Filippov CHECK_STATE_OPERAND(intisa, opc, iclass, stOp, 0);
12717f709ce7SMax Filippov return iclass->stateOperands[stOp].inout;
12727f709ce7SMax Filippov }
12737f709ce7SMax Filippov
12747f709ce7SMax Filippov
12757f709ce7SMax Filippov /* Interface Operands. */
12767f709ce7SMax Filippov
12777f709ce7SMax Filippov
12787f709ce7SMax Filippov #define CHECK_INTERFACE_OPERAND(INTISA, OPC, ICLASS, IFOP, ERRVAL) \
12797f709ce7SMax Filippov do { \
12807f709ce7SMax Filippov if ((IFOP) < 0 || (IFOP) >= (ICLASS)->num_interfaceOperands) { \
12817f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_operand; \
12827f709ce7SMax Filippov sprintf(xtisa_error_msg, \
12837f709ce7SMax Filippov "invalid interface operand number (%d); " \
12847f709ce7SMax Filippov "opcode \"%s\" has %d interface operands", (IFOP), \
12857f709ce7SMax Filippov (INTISA)->opcodes[(OPC)].name, \
12867f709ce7SMax Filippov (ICLASS)->num_interfaceOperands); \
12877f709ce7SMax Filippov return ERRVAL; \
12887f709ce7SMax Filippov } \
12897f709ce7SMax Filippov } while (0)
12907f709ce7SMax Filippov
12917f709ce7SMax Filippov
xtensa_interfaceOperand_interface(xtensa_isa isa,xtensa_opcode opc,int ifOp)12927f709ce7SMax Filippov xtensa_interface xtensa_interfaceOperand_interface(xtensa_isa isa,
12937f709ce7SMax Filippov xtensa_opcode opc,
12947f709ce7SMax Filippov int ifOp)
12957f709ce7SMax Filippov {
12967f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
12977f709ce7SMax Filippov xtensa_iclass_internal *iclass;
12987f709ce7SMax Filippov int iclass_id;
12997f709ce7SMax Filippov
13007f709ce7SMax Filippov CHECK_OPCODE(intisa, opc, XTENSA_UNDEFINED);
13017f709ce7SMax Filippov iclass_id = intisa->opcodes[opc].iclass_id;
13027f709ce7SMax Filippov iclass = &intisa->iclasses[iclass_id];
13037f709ce7SMax Filippov CHECK_INTERFACE_OPERAND(intisa, opc, iclass, ifOp, XTENSA_UNDEFINED);
13047f709ce7SMax Filippov return iclass->interfaceOperands[ifOp];
13057f709ce7SMax Filippov }
13067f709ce7SMax Filippov
13077f709ce7SMax Filippov
13087f709ce7SMax Filippov /* Register Files. */
13097f709ce7SMax Filippov
13107f709ce7SMax Filippov
13117f709ce7SMax Filippov #define CHECK_REGFILE(INTISA, RF, ERRVAL) \
13127f709ce7SMax Filippov do { \
13137f709ce7SMax Filippov if ((RF) < 0 || (RF) >= (INTISA)->num_regfiles) { \
13147f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_regfile; \
13157f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid regfile specifier"); \
13167f709ce7SMax Filippov return ERRVAL; \
13177f709ce7SMax Filippov } \
13187f709ce7SMax Filippov } while (0)
13197f709ce7SMax Filippov
13207f709ce7SMax Filippov
xtensa_regfile_lookup(xtensa_isa isa,const char * name)13217f709ce7SMax Filippov xtensa_regfile xtensa_regfile_lookup(xtensa_isa isa, const char *name)
13227f709ce7SMax Filippov {
13237f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
13247f709ce7SMax Filippov int n;
13257f709ce7SMax Filippov
13267f709ce7SMax Filippov if (!name || !*name) {
13277f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_regfile;
13287f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid regfile name");
13297f709ce7SMax Filippov return XTENSA_UNDEFINED;
13307f709ce7SMax Filippov }
13317f709ce7SMax Filippov
13327f709ce7SMax Filippov /* The expected number of regfiles is small; use a linear search. */
13337f709ce7SMax Filippov for (n = 0; n < intisa->num_regfiles; n++) {
13347f709ce7SMax Filippov if (!strcmp(intisa->regfiles[n].name, name)) {
13357f709ce7SMax Filippov return n;
13367f709ce7SMax Filippov }
13377f709ce7SMax Filippov }
13387f709ce7SMax Filippov
13397f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_regfile;
13407f709ce7SMax Filippov sprintf(xtisa_error_msg, "regfile \"%s\" not recognized", name);
13417f709ce7SMax Filippov return XTENSA_UNDEFINED;
13427f709ce7SMax Filippov }
13437f709ce7SMax Filippov
13447f709ce7SMax Filippov
xtensa_regfile_lookup_shortname(xtensa_isa isa,const char * shortname)13457f709ce7SMax Filippov xtensa_regfile xtensa_regfile_lookup_shortname(xtensa_isa isa,
13467f709ce7SMax Filippov const char *shortname)
13477f709ce7SMax Filippov {
13487f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
13497f709ce7SMax Filippov int n;
13507f709ce7SMax Filippov
13517f709ce7SMax Filippov if (!shortname || !*shortname) {
13527f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_regfile;
13537f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid regfile shortname");
13547f709ce7SMax Filippov return XTENSA_UNDEFINED;
13557f709ce7SMax Filippov }
13567f709ce7SMax Filippov
13577f709ce7SMax Filippov /* The expected number of regfiles is small; use a linear search. */
13587f709ce7SMax Filippov for (n = 0; n < intisa->num_regfiles; n++) {
13597f709ce7SMax Filippov /*
13607f709ce7SMax Filippov * Ignore regfile views since they always have the same shortnames
13617f709ce7SMax Filippov * as their parents.
13627f709ce7SMax Filippov */
13637f709ce7SMax Filippov if (intisa->regfiles[n].parent != n) {
13647f709ce7SMax Filippov continue;
13657f709ce7SMax Filippov }
13667f709ce7SMax Filippov if (!strcmp(intisa->regfiles[n].shortname, shortname)) {
13677f709ce7SMax Filippov return n;
13687f709ce7SMax Filippov }
13697f709ce7SMax Filippov }
13707f709ce7SMax Filippov
13717f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_regfile;
13727f709ce7SMax Filippov sprintf(xtisa_error_msg, "regfile shortname \"%s\" not recognized",
13737f709ce7SMax Filippov shortname);
13747f709ce7SMax Filippov return XTENSA_UNDEFINED;
13757f709ce7SMax Filippov }
13767f709ce7SMax Filippov
13777f709ce7SMax Filippov
xtensa_regfile_name(xtensa_isa isa,xtensa_regfile rf)13787f709ce7SMax Filippov const char *xtensa_regfile_name(xtensa_isa isa, xtensa_regfile rf)
13797f709ce7SMax Filippov {
13807f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
13817f709ce7SMax Filippov
13827f709ce7SMax Filippov CHECK_REGFILE(intisa, rf, NULL);
13837f709ce7SMax Filippov return intisa->regfiles[rf].name;
13847f709ce7SMax Filippov }
13857f709ce7SMax Filippov
13867f709ce7SMax Filippov
xtensa_regfile_shortname(xtensa_isa isa,xtensa_regfile rf)13877f709ce7SMax Filippov const char *xtensa_regfile_shortname(xtensa_isa isa, xtensa_regfile rf)
13887f709ce7SMax Filippov {
13897f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
13907f709ce7SMax Filippov
13917f709ce7SMax Filippov CHECK_REGFILE(intisa, rf, NULL);
13927f709ce7SMax Filippov return intisa->regfiles[rf].shortname;
13937f709ce7SMax Filippov }
13947f709ce7SMax Filippov
13957f709ce7SMax Filippov
xtensa_regfile_view_parent(xtensa_isa isa,xtensa_regfile rf)13967f709ce7SMax Filippov xtensa_regfile xtensa_regfile_view_parent(xtensa_isa isa, xtensa_regfile rf)
13977f709ce7SMax Filippov {
13987f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
13997f709ce7SMax Filippov
14007f709ce7SMax Filippov CHECK_REGFILE(intisa, rf, XTENSA_UNDEFINED);
14017f709ce7SMax Filippov return intisa->regfiles[rf].parent;
14027f709ce7SMax Filippov }
14037f709ce7SMax Filippov
14047f709ce7SMax Filippov
xtensa_regfile_num_bits(xtensa_isa isa,xtensa_regfile rf)14057f709ce7SMax Filippov int xtensa_regfile_num_bits(xtensa_isa isa, xtensa_regfile rf)
14067f709ce7SMax Filippov {
14077f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
14087f709ce7SMax Filippov
14097f709ce7SMax Filippov CHECK_REGFILE(intisa, rf, XTENSA_UNDEFINED);
14107f709ce7SMax Filippov return intisa->regfiles[rf].num_bits;
14117f709ce7SMax Filippov }
14127f709ce7SMax Filippov
14137f709ce7SMax Filippov
xtensa_regfile_num_entries(xtensa_isa isa,xtensa_regfile rf)14147f709ce7SMax Filippov int xtensa_regfile_num_entries(xtensa_isa isa, xtensa_regfile rf)
14157f709ce7SMax Filippov {
14167f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
14177f709ce7SMax Filippov
14187f709ce7SMax Filippov CHECK_REGFILE(intisa, rf, XTENSA_UNDEFINED);
14197f709ce7SMax Filippov return intisa->regfiles[rf].num_entries;
14207f709ce7SMax Filippov }
14217f709ce7SMax Filippov
14227f709ce7SMax Filippov
14237f709ce7SMax Filippov /* Processor States. */
14247f709ce7SMax Filippov
14257f709ce7SMax Filippov
14267f709ce7SMax Filippov #define CHECK_STATE(INTISA, ST, ERRVAL) \
14277f709ce7SMax Filippov do { \
14287f709ce7SMax Filippov if ((ST) < 0 || (ST) >= (INTISA)->num_states) { \
14297f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_state; \
14307f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid state specifier"); \
14317f709ce7SMax Filippov return ERRVAL; \
14327f709ce7SMax Filippov } \
14337f709ce7SMax Filippov } while (0)
14347f709ce7SMax Filippov
14357f709ce7SMax Filippov
xtensa_state_lookup(xtensa_isa isa,const char * name)14367f709ce7SMax Filippov xtensa_state xtensa_state_lookup(xtensa_isa isa, const char *name)
14377f709ce7SMax Filippov {
14387f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
14397f709ce7SMax Filippov xtensa_lookup_entry entry, *result = 0;
14407f709ce7SMax Filippov
14417f709ce7SMax Filippov if (!name || !*name) {
14427f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_state;
14437f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid state name");
14447f709ce7SMax Filippov return XTENSA_UNDEFINED;
14457f709ce7SMax Filippov }
14467f709ce7SMax Filippov
14477f709ce7SMax Filippov if (intisa->num_states != 0) {
14487f709ce7SMax Filippov entry.key = name;
14497f709ce7SMax Filippov result = bsearch(&entry, intisa->state_lookup_table,
14507f709ce7SMax Filippov intisa->num_states, sizeof(xtensa_lookup_entry),
14517f709ce7SMax Filippov xtensa_isa_name_compare);
14527f709ce7SMax Filippov }
14537f709ce7SMax Filippov
14547f709ce7SMax Filippov if (!result) {
14557f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_state;
14567f709ce7SMax Filippov sprintf(xtisa_error_msg, "state \"%s\" not recognized", name);
14577f709ce7SMax Filippov return XTENSA_UNDEFINED;
14587f709ce7SMax Filippov }
14597f709ce7SMax Filippov
14607f709ce7SMax Filippov return result->u.state;
14617f709ce7SMax Filippov }
14627f709ce7SMax Filippov
14637f709ce7SMax Filippov
xtensa_state_name(xtensa_isa isa,xtensa_state st)14647f709ce7SMax Filippov const char *xtensa_state_name(xtensa_isa isa, xtensa_state st)
14657f709ce7SMax Filippov {
14667f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
14677f709ce7SMax Filippov
14687f709ce7SMax Filippov CHECK_STATE(intisa, st, NULL);
14697f709ce7SMax Filippov return intisa->states[st].name;
14707f709ce7SMax Filippov }
14717f709ce7SMax Filippov
14727f709ce7SMax Filippov
xtensa_state_num_bits(xtensa_isa isa,xtensa_state st)14737f709ce7SMax Filippov int xtensa_state_num_bits(xtensa_isa isa, xtensa_state st)
14747f709ce7SMax Filippov {
14757f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
14767f709ce7SMax Filippov
14777f709ce7SMax Filippov CHECK_STATE(intisa, st, XTENSA_UNDEFINED);
14787f709ce7SMax Filippov return intisa->states[st].num_bits;
14797f709ce7SMax Filippov }
14807f709ce7SMax Filippov
14817f709ce7SMax Filippov
xtensa_state_is_exported(xtensa_isa isa,xtensa_state st)14827f709ce7SMax Filippov int xtensa_state_is_exported(xtensa_isa isa, xtensa_state st)
14837f709ce7SMax Filippov {
14847f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
14857f709ce7SMax Filippov
14867f709ce7SMax Filippov CHECK_STATE(intisa, st, XTENSA_UNDEFINED);
14877f709ce7SMax Filippov if ((intisa->states[st].flags & XTENSA_STATE_IS_EXPORTED) != 0) {
14887f709ce7SMax Filippov return 1;
14897f709ce7SMax Filippov }
14907f709ce7SMax Filippov return 0;
14917f709ce7SMax Filippov }
14927f709ce7SMax Filippov
14937f709ce7SMax Filippov
xtensa_state_is_shared_or(xtensa_isa isa,xtensa_state st)14947f709ce7SMax Filippov int xtensa_state_is_shared_or(xtensa_isa isa, xtensa_state st)
14957f709ce7SMax Filippov {
14967f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
14977f709ce7SMax Filippov
14987f709ce7SMax Filippov CHECK_STATE(intisa, st, XTENSA_UNDEFINED);
14997f709ce7SMax Filippov if ((intisa->states[st].flags & XTENSA_STATE_IS_SHARED_OR) != 0) {
15007f709ce7SMax Filippov return 1;
15017f709ce7SMax Filippov }
15027f709ce7SMax Filippov return 0;
15037f709ce7SMax Filippov }
15047f709ce7SMax Filippov
15057f709ce7SMax Filippov
15067f709ce7SMax Filippov /* Sysregs. */
15077f709ce7SMax Filippov
15087f709ce7SMax Filippov
15097f709ce7SMax Filippov #define CHECK_SYSREG(INTISA, SYSREG, ERRVAL) \
15107f709ce7SMax Filippov do { \
15117f709ce7SMax Filippov if ((SYSREG) < 0 || (SYSREG) >= (INTISA)->num_sysregs) { \
15127f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_sysreg; \
15137f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid sysreg specifier"); \
15147f709ce7SMax Filippov return ERRVAL; \
15157f709ce7SMax Filippov } \
15167f709ce7SMax Filippov } while (0)
15177f709ce7SMax Filippov
15187f709ce7SMax Filippov
xtensa_sysreg_lookup(xtensa_isa isa,int num,int is_user)15197f709ce7SMax Filippov xtensa_sysreg xtensa_sysreg_lookup(xtensa_isa isa, int num, int is_user)
15207f709ce7SMax Filippov {
15217f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
15227f709ce7SMax Filippov
15237f709ce7SMax Filippov if (is_user != 0) {
15247f709ce7SMax Filippov is_user = 1;
15257f709ce7SMax Filippov }
15267f709ce7SMax Filippov
15277f709ce7SMax Filippov if (num < 0 || num > intisa->max_sysreg_num[is_user] ||
15287f709ce7SMax Filippov intisa->sysreg_table[is_user][num] == XTENSA_UNDEFINED) {
15297f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_sysreg;
15307f709ce7SMax Filippov strcpy(xtisa_error_msg, "sysreg not recognized");
15317f709ce7SMax Filippov return XTENSA_UNDEFINED;
15327f709ce7SMax Filippov }
15337f709ce7SMax Filippov
15347f709ce7SMax Filippov return intisa->sysreg_table[is_user][num];
15357f709ce7SMax Filippov }
15367f709ce7SMax Filippov
15377f709ce7SMax Filippov
xtensa_sysreg_lookup_name(xtensa_isa isa,const char * name)15387f709ce7SMax Filippov xtensa_sysreg xtensa_sysreg_lookup_name(xtensa_isa isa, const char *name)
15397f709ce7SMax Filippov {
15407f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
15417f709ce7SMax Filippov xtensa_lookup_entry entry, *result = 0;
15427f709ce7SMax Filippov
15437f709ce7SMax Filippov if (!name || !*name) {
15447f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_sysreg;
15457f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid sysreg name");
15467f709ce7SMax Filippov return XTENSA_UNDEFINED;
15477f709ce7SMax Filippov }
15487f709ce7SMax Filippov
15497f709ce7SMax Filippov if (intisa->num_sysregs != 0) {
15507f709ce7SMax Filippov entry.key = name;
15517f709ce7SMax Filippov result = bsearch(&entry, intisa->sysreg_lookup_table,
15527f709ce7SMax Filippov intisa->num_sysregs, sizeof(xtensa_lookup_entry),
15537f709ce7SMax Filippov xtensa_isa_name_compare);
15547f709ce7SMax Filippov }
15557f709ce7SMax Filippov
15567f709ce7SMax Filippov if (!result) {
15577f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_sysreg;
15587f709ce7SMax Filippov sprintf(xtisa_error_msg, "sysreg \"%s\" not recognized", name);
15597f709ce7SMax Filippov return XTENSA_UNDEFINED;
15607f709ce7SMax Filippov }
15617f709ce7SMax Filippov
15627f709ce7SMax Filippov return result->u.sysreg;
15637f709ce7SMax Filippov }
15647f709ce7SMax Filippov
15657f709ce7SMax Filippov
xtensa_sysreg_name(xtensa_isa isa,xtensa_sysreg sysreg)15667f709ce7SMax Filippov const char *xtensa_sysreg_name(xtensa_isa isa, xtensa_sysreg sysreg)
15677f709ce7SMax Filippov {
15687f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
15697f709ce7SMax Filippov
15707f709ce7SMax Filippov CHECK_SYSREG(intisa, sysreg, NULL);
15717f709ce7SMax Filippov return intisa->sysregs[sysreg].name;
15727f709ce7SMax Filippov }
15737f709ce7SMax Filippov
15747f709ce7SMax Filippov
xtensa_sysreg_number(xtensa_isa isa,xtensa_sysreg sysreg)15757f709ce7SMax Filippov int xtensa_sysreg_number(xtensa_isa isa, xtensa_sysreg sysreg)
15767f709ce7SMax Filippov {
15777f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
15787f709ce7SMax Filippov
15797f709ce7SMax Filippov CHECK_SYSREG(intisa, sysreg, XTENSA_UNDEFINED);
15807f709ce7SMax Filippov return intisa->sysregs[sysreg].number;
15817f709ce7SMax Filippov }
15827f709ce7SMax Filippov
15837f709ce7SMax Filippov
xtensa_sysreg_is_user(xtensa_isa isa,xtensa_sysreg sysreg)15847f709ce7SMax Filippov int xtensa_sysreg_is_user(xtensa_isa isa, xtensa_sysreg sysreg)
15857f709ce7SMax Filippov {
15867f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
15877f709ce7SMax Filippov
15887f709ce7SMax Filippov CHECK_SYSREG(intisa, sysreg, XTENSA_UNDEFINED);
15897f709ce7SMax Filippov if (intisa->sysregs[sysreg].is_user) {
15907f709ce7SMax Filippov return 1;
15917f709ce7SMax Filippov }
15927f709ce7SMax Filippov return 0;
15937f709ce7SMax Filippov }
15947f709ce7SMax Filippov
15957f709ce7SMax Filippov
15967f709ce7SMax Filippov /* Interfaces. */
15977f709ce7SMax Filippov
15987f709ce7SMax Filippov
15997f709ce7SMax Filippov #define CHECK_INTERFACE(INTISA, INTF, ERRVAL) \
16007f709ce7SMax Filippov do { \
16017f709ce7SMax Filippov if ((INTF) < 0 || (INTF) >= (INTISA)->num_interfaces) { \
16027f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_interface; \
16037f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid interface specifier"); \
16047f709ce7SMax Filippov return ERRVAL; \
16057f709ce7SMax Filippov } \
16067f709ce7SMax Filippov } while (0)
16077f709ce7SMax Filippov
16087f709ce7SMax Filippov
xtensa_interface_lookup(xtensa_isa isa,const char * ifname)16097f709ce7SMax Filippov xtensa_interface xtensa_interface_lookup(xtensa_isa isa, const char *ifname)
16107f709ce7SMax Filippov {
16117f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
16127f709ce7SMax Filippov xtensa_lookup_entry entry, *result = 0;
16137f709ce7SMax Filippov
16147f709ce7SMax Filippov if (!ifname || !*ifname) {
16157f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_interface;
16167f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid interface name");
16177f709ce7SMax Filippov return XTENSA_UNDEFINED;
16187f709ce7SMax Filippov }
16197f709ce7SMax Filippov
16207f709ce7SMax Filippov if (intisa->num_interfaces != 0) {
16217f709ce7SMax Filippov entry.key = ifname;
16227f709ce7SMax Filippov result = bsearch(&entry, intisa->interface_lookup_table,
16237f709ce7SMax Filippov intisa->num_interfaces, sizeof(xtensa_lookup_entry),
16247f709ce7SMax Filippov xtensa_isa_name_compare);
16257f709ce7SMax Filippov }
16267f709ce7SMax Filippov
16277f709ce7SMax Filippov if (!result) {
16287f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_interface;
16297f709ce7SMax Filippov sprintf(xtisa_error_msg, "interface \"%s\" not recognized", ifname);
16307f709ce7SMax Filippov return XTENSA_UNDEFINED;
16317f709ce7SMax Filippov }
16327f709ce7SMax Filippov
16337f709ce7SMax Filippov return result->u.intf;
16347f709ce7SMax Filippov }
16357f709ce7SMax Filippov
16367f709ce7SMax Filippov
xtensa_interface_name(xtensa_isa isa,xtensa_interface intf)16377f709ce7SMax Filippov const char *xtensa_interface_name(xtensa_isa isa, xtensa_interface intf)
16387f709ce7SMax Filippov {
16397f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
16407f709ce7SMax Filippov
16417f709ce7SMax Filippov CHECK_INTERFACE(intisa, intf, NULL);
16427f709ce7SMax Filippov return intisa->interfaces[intf].name;
16437f709ce7SMax Filippov }
16447f709ce7SMax Filippov
16457f709ce7SMax Filippov
xtensa_interface_num_bits(xtensa_isa isa,xtensa_interface intf)16467f709ce7SMax Filippov int xtensa_interface_num_bits(xtensa_isa isa, xtensa_interface intf)
16477f709ce7SMax Filippov {
16487f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
16497f709ce7SMax Filippov
16507f709ce7SMax Filippov CHECK_INTERFACE(intisa, intf, XTENSA_UNDEFINED);
16517f709ce7SMax Filippov return intisa->interfaces[intf].num_bits;
16527f709ce7SMax Filippov }
16537f709ce7SMax Filippov
16547f709ce7SMax Filippov
xtensa_interface_inout(xtensa_isa isa,xtensa_interface intf)16557f709ce7SMax Filippov char xtensa_interface_inout(xtensa_isa isa, xtensa_interface intf)
16567f709ce7SMax Filippov {
16577f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
16587f709ce7SMax Filippov
16597f709ce7SMax Filippov CHECK_INTERFACE(intisa, intf, 0);
16607f709ce7SMax Filippov return intisa->interfaces[intf].inout;
16617f709ce7SMax Filippov }
16627f709ce7SMax Filippov
16637f709ce7SMax Filippov
xtensa_interface_has_side_effect(xtensa_isa isa,xtensa_interface intf)16647f709ce7SMax Filippov int xtensa_interface_has_side_effect(xtensa_isa isa, xtensa_interface intf)
16657f709ce7SMax Filippov {
16667f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
16677f709ce7SMax Filippov
16687f709ce7SMax Filippov CHECK_INTERFACE(intisa, intf, XTENSA_UNDEFINED);
16697f709ce7SMax Filippov if ((intisa->interfaces[intf].flags &
16707f709ce7SMax Filippov XTENSA_INTERFACE_HAS_SIDE_EFFECT) != 0) {
16717f709ce7SMax Filippov return 1;
16727f709ce7SMax Filippov }
16737f709ce7SMax Filippov return 0;
16747f709ce7SMax Filippov }
16757f709ce7SMax Filippov
16767f709ce7SMax Filippov
xtensa_interface_class_id(xtensa_isa isa,xtensa_interface intf)16777f709ce7SMax Filippov int xtensa_interface_class_id(xtensa_isa isa, xtensa_interface intf)
16787f709ce7SMax Filippov {
16797f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
16807f709ce7SMax Filippov
16817f709ce7SMax Filippov CHECK_INTERFACE(intisa, intf, XTENSA_UNDEFINED);
16827f709ce7SMax Filippov return intisa->interfaces[intf].class_id;
16837f709ce7SMax Filippov }
16847f709ce7SMax Filippov
16857f709ce7SMax Filippov
16867f709ce7SMax Filippov /* Functional Units. */
16877f709ce7SMax Filippov
16887f709ce7SMax Filippov
16897f709ce7SMax Filippov #define CHECK_FUNCUNIT(INTISA, FUN, ERRVAL) \
16907f709ce7SMax Filippov do { \
16917f709ce7SMax Filippov if ((FUN) < 0 || (FUN) >= (INTISA)->num_funcUnits) { \
16927f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_funcUnit; \
16937f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid functional unit specifier"); \
16947f709ce7SMax Filippov return ERRVAL; \
16957f709ce7SMax Filippov } \
16967f709ce7SMax Filippov } while (0)
16977f709ce7SMax Filippov
16987f709ce7SMax Filippov
xtensa_funcUnit_lookup(xtensa_isa isa,const char * fname)16997f709ce7SMax Filippov xtensa_funcUnit xtensa_funcUnit_lookup(xtensa_isa isa, const char *fname)
17007f709ce7SMax Filippov {
17017f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
17027f709ce7SMax Filippov xtensa_lookup_entry entry, *result = 0;
17037f709ce7SMax Filippov
17047f709ce7SMax Filippov if (!fname || !*fname) {
17057f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_funcUnit;
17067f709ce7SMax Filippov strcpy(xtisa_error_msg, "invalid functional unit name");
17077f709ce7SMax Filippov return XTENSA_UNDEFINED;
17087f709ce7SMax Filippov }
17097f709ce7SMax Filippov
17107f709ce7SMax Filippov if (intisa->num_funcUnits != 0) {
17117f709ce7SMax Filippov entry.key = fname;
17127f709ce7SMax Filippov result = bsearch(&entry, intisa->funcUnit_lookup_table,
17137f709ce7SMax Filippov intisa->num_funcUnits, sizeof(xtensa_lookup_entry),
17147f709ce7SMax Filippov xtensa_isa_name_compare);
17157f709ce7SMax Filippov }
17167f709ce7SMax Filippov
17177f709ce7SMax Filippov if (!result) {
17187f709ce7SMax Filippov xtisa_errno = xtensa_isa_bad_funcUnit;
17197f709ce7SMax Filippov sprintf(xtisa_error_msg,
17207f709ce7SMax Filippov "functional unit \"%s\" not recognized", fname);
17217f709ce7SMax Filippov return XTENSA_UNDEFINED;
17227f709ce7SMax Filippov }
17237f709ce7SMax Filippov
17247f709ce7SMax Filippov return result->u.fun;
17257f709ce7SMax Filippov }
17267f709ce7SMax Filippov
17277f709ce7SMax Filippov
xtensa_funcUnit_name(xtensa_isa isa,xtensa_funcUnit fun)17287f709ce7SMax Filippov const char *xtensa_funcUnit_name(xtensa_isa isa, xtensa_funcUnit fun)
17297f709ce7SMax Filippov {
17307f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
17317f709ce7SMax Filippov
17327f709ce7SMax Filippov CHECK_FUNCUNIT(intisa, fun, NULL);
17337f709ce7SMax Filippov return intisa->funcUnits[fun].name;
17347f709ce7SMax Filippov }
17357f709ce7SMax Filippov
17367f709ce7SMax Filippov
xtensa_funcUnit_num_copies(xtensa_isa isa,xtensa_funcUnit fun)17377f709ce7SMax Filippov int xtensa_funcUnit_num_copies(xtensa_isa isa, xtensa_funcUnit fun)
17387f709ce7SMax Filippov {
17397f709ce7SMax Filippov xtensa_isa_internal *intisa = (xtensa_isa_internal *)isa;
17407f709ce7SMax Filippov
17417f709ce7SMax Filippov CHECK_FUNCUNIT(intisa, fun, XTENSA_UNDEFINED);
17427f709ce7SMax Filippov return intisa->funcUnits[fun].num_copies;
17437f709ce7SMax Filippov }
1744