aboutsummaryrefslogtreecommitdiff
path: root/target/xtensa/xtensa-isa-internal.h
blob: 40dd8bac96ee7dc5cbea5c34e943597226495b34 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/* Internal definitions for the Xtensa ISA library.
 *
 * Copyright (c) 2004-2011 Tensilica Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef XTENSA_ISA_INTERNAL_H
#define XTENSA_ISA_INTERNAL_H

#ifndef uint32
#define uint32 uint32_t
#endif

/* Flags. */

#define XTENSA_OPERAND_IS_REGISTER      0x00000001
#define XTENSA_OPERAND_IS_PCRELATIVE    0x00000002
#define XTENSA_OPERAND_IS_INVISIBLE     0x00000004
#define XTENSA_OPERAND_IS_UNKNOWN       0x00000008

#define XTENSA_OPCODE_IS_BRANCH         0x00000001
#define XTENSA_OPCODE_IS_JUMP           0x00000002
#define XTENSA_OPCODE_IS_LOOP           0x00000004
#define XTENSA_OPCODE_IS_CALL           0x00000008

#define XTENSA_STATE_IS_EXPORTED        0x00000001
#define XTENSA_STATE_IS_SHARED_OR       0x00000002

#define XTENSA_INTERFACE_HAS_SIDE_EFFECT 0x00000001

/* Function pointer typedefs */
typedef void (*xtensa_format_encode_fn)(xtensa_insnbuf);
typedef void (*xtensa_get_slot_fn)(const xtensa_insnbuf, xtensa_insnbuf);
typedef void (*xtensa_set_slot_fn)(xtensa_insnbuf, const xtensa_insnbuf);
typedef int (*xtensa_opcode_decode_fn)(const xtensa_insnbuf);
typedef uint32_t (*xtensa_get_field_fn)(const xtensa_insnbuf);
typedef void (*xtensa_set_field_fn)(xtensa_insnbuf, uint32_t);
typedef int (*xtensa_immed_decode_fn)(uint32_t *);
typedef int (*xtensa_immed_encode_fn)(uint32_t *);
typedef int (*xtensa_do_reloc_fn)(uint32_t *, uint32_t);
typedef int (*xtensa_undo_reloc_fn)(uint32_t *, uint32_t);
typedef void (*xtensa_opcode_encode_fn)(xtensa_insnbuf);
typedef int (*xtensa_format_decode_fn)(const xtensa_insnbuf);
typedef int (*xtensa_length_decode_fn)(const unsigned char *);

typedef struct xtensa_format_internal_struct {
    const char *name;           /* Instruction format name. */
    int length;                 /* Instruction length in bytes. */
    xtensa_format_encode_fn encode_fn;
    int num_slots;
    int *slot_id;               /* Array[num_slots] of slot IDs. */
} xtensa_format_internal;

typedef struct xtensa_slot_internal_struct {
    const char *name;                   /* Not necessarily unique. */
    const char *format;
    int position;
    xtensa_get_slot_fn get_fn;
    xtensa_set_slot_fn set_fn;
    xtensa_get_field_fn *get_field_fns; /* Array[field_id]. */
    xtensa_set_field_fn *set_field_fns; /* Array[field_id]. */
    xtensa_opcode_decode_fn opcode_decode_fn;
    const char *nop_name;
} xtensa_slot_internal;

typedef struct xtensa_operand_internal_struct {
    const char *name;
    int field_id;
    xtensa_regfile regfile;             /* Register file. */
    int num_regs;                       /* Usually 1; 2 for reg pairs, etc. */
    uint32_t flags;                     /* See XTENSA_OPERAND_* flags. */
    xtensa_immed_encode_fn encode;      /* Encode the operand value. */
    xtensa_immed_decode_fn decode;      /* Decode the value from the field. */
    xtensa_do_reloc_fn do_reloc;        /* Perform a PC-relative reloc. */
    xtensa_undo_reloc_fn undo_reloc;    /* Undo a PC-relative relocation. */
} xtensa_operand_internal;

typedef struct xtensa_arg_internal_struct {
    union {
        int operand_id;         /* For normal operands. */
        xtensa_state state;     /* For stateOperands. */
    } u;
    char inout;                 /* Direction: 'i', 'o', or 'm'. */
} xtensa_arg_internal;

typedef struct xtensa_iclass_internal_struct {
    int num_operands;           /* Size of "operands" array. */
    xtensa_arg_internal *operands;          /* Array[num_operands]. */

    int num_stateOperands;      /* Size of "stateOperands" array. */
    xtensa_arg_internal *stateOperands;     /* Array[num_stateOperands]. */

    int num_interfaceOperands;  /* Size of "interfaceOperands". */
    xtensa_interface *interfaceOperands;    /* Array[num_interfaceOperands]. */
} xtensa_iclass_internal;

typedef struct xtensa_opcode_internal_struct {
    const char *name;           /* Opcode mnemonic. */
    int iclass_id;              /* Iclass for this opcode. */
    uint32_t flags;             /* See XTENSA_OPCODE_* flags. */
    xtensa_opcode_encode_fn *encode_fns;    /* Array[slot_id]. */
    int num_funcUnit_uses;      /* Number of funcUnit_use entries. */
    xtensa_funcUnit_use *funcUnit_uses;     /* Array[num_funcUnit_uses]. */
} xtensa_opcode_internal;

typedef struct xtensa_regfile_internal_struct {
    const char *name;           /* Full name of the regfile. */
    const char *shortname;      /* Abbreviated name. */
    xtensa_regfile parent;      /* View parent (or identity). */
    int num_bits;               /* Width of the registers. */
    int num_entries;            /* Number of registers. */
} xtensa_regfile_internal;

typedef struct xtensa_interface_internal_struct {
    const char *name;           /* Interface name. */
    int num_bits;               /* Width of the interface. */
    uint32_t flags;             /* See XTENSA_INTERFACE_* flags. */
    int class_id;               /* Class of related interfaces. */
    char inout;                 /* "i" or "o". */
} xtensa_interface_internal;

typedef struct xtensa_funcUnit_internal_struct {
    const char *name;           /* Functional unit name. */
    int num_copies;             /* Number of instances. */
} xtensa_funcUnit_internal;

typedef struct xtensa_state_internal_struct {
    const char *name;           /* State name. */
    int num_bits;               /* Number of state bits. */
    uint32_t flags;             /* See XTENSA_STATE_* flags. */
} xtensa_state_internal;

typedef struct xtensa_sysreg_internal_struct {
    const char *name;           /* Register name. */
    int number;                 /* Register number. */
    int is_user;                /* Non-zero if a "user register". */
} xtensa_sysreg_internal;

typedef struct xtensa_lookup_entry_struct {
    const char *key;
    union {
        xtensa_opcode opcode;   /* Internal opcode number. */
        xtensa_sysreg sysreg;   /* Internal sysreg number. */
        xtensa_state state;     /* Internal state number. */
        xtensa_interface intf;  /* Internal interface number. */
        xtensa_funcUnit fun;    /* Internal funcUnit number. */
    } u;
} xtensa_lookup_entry;

typedef struct xtensa_isa_internal_struct {
    int is_big_endian;          /* Endianness. */
    int insn_size;              /* Maximum length in bytes. */
    int insnbuf_size;           /* Number of insnbuf_words. */

    int num_formats;
    xtensa_format_internal *formats;
    xtensa_format_decode_fn format_decode_fn;
    xtensa_length_decode_fn length_decode_fn;

    int num_slots;
    xtensa_slot_internal *slots;

    int num_fields;

    int num_operands;
    xtensa_operand_internal *operands;

    int num_iclasses;
    xtensa_iclass_internal *iclasses;

    int num_opcodes;
    xtensa_opcode_internal *opcodes;
    xtensa_lookup_entry *opname_lookup_table;

    int num_regfiles;
    xtensa_regfile_internal *regfiles;

    int num_states;
    xtensa_state_internal *states;
    xtensa_lookup_entry *state_lookup_table;

    int num_sysregs;
    xtensa_sysreg_internal *sysregs;
    xtensa_lookup_entry *sysreg_lookup_table;

    /*
     * The current Xtensa ISA only supports 256 of each kind of sysreg so
     * we can get away with implementing lookups with tables indexed by
     * the register numbers. If we ever allow larger sysreg numbers, this
     * may have to be reimplemented. The first entry in the following
     * arrays corresponds to "special" registers and the second to "user"
     * registers.
     */
    int max_sysreg_num[2];
    xtensa_sysreg *sysreg_table[2];

    int num_interfaces;
    xtensa_interface_internal *interfaces;
    xtensa_lookup_entry *interface_lookup_table;

    int num_funcUnits;
    xtensa_funcUnit_internal *funcUnits;
    xtensa_lookup_entry *funcUnit_lookup_table;

    int num_stages;             /* Number of pipe stages. */
} xtensa_isa_internal;

int xtensa_isa_name_compare(const void *, const void *);

extern xtensa_isa_status xtisa_errno;
extern char xtisa_error_msg[];

#endif /* XTENSA_ISA_INTERNAL_H */