xref: /netbsd-src/external/gpl3/binutils/dist/include/opcode/loongarch.h (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1 /* LoongArch assembler/disassembler support.
2 
3    Copyright (C) 2021-2024 Free Software Foundation, Inc.
4    Contributed by Loongson Ltd.
5 
6    This file is part of GNU Binutils.
7 
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the license, or
11    (at your option) any later version.
12 
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with this program; see the file COPYING3.  If not,
20    see <http://www.gnu.org/licenses/>.  */
21 
22 #ifndef _LOONGARCH_H_
23 #define _LOONGARCH_H_
24 #include <stdint.h>
25 
26 #ifdef __cplusplus
27 extern "C"
28 {
29 #endif
30 
31   #define LARCH_NOP 0x03400000
32   #define LARCH_B 0x50000000
33   /* BCEQZ/BCNEZ.  */
34   #define LARCH_FLOAT_BRANCH 0x48000000
35   #define LARCH_BRANCH_OPCODE_MASK 0xfc000000
36   #define LARCH_BRANCH_INVERT_BIT 0x04000000
37   #define LARCH_FLOAT_BRANCH_INVERT_BIT 0x00000100
38 
39   #define ENCODE_BRANCH16_IMM(x) (((x) >> 2) << 10)
40 
41   #define OUT_OF_RANGE(value, bits, align)	\
42     ((value) < (-(1 << ((bits) - 1) << align)) 	\
43       || (value) > ((((1 << ((bits) - 1)) - 1) << align)))
44 
45   #define LARCH_LU12I_W 0x14000000
46   #define LARCH_ORI 0x03800000
47   #define LARCH_LD_D 0x28c00000
48   #define LARCH_RD_A0 0x04
49   #define LARCH_RD_RJ_A0 0x084
50 
51   typedef uint32_t insn_t;
52 
53   struct loongarch_opcode
54   {
55     const insn_t match;
56     const insn_t mask; /* High 1 byte is main opcode and it must be 0xf.  */
57 #define LARCH_INSN_OPC(insn) ((insn & 0xf0000000) >> 28)
58     const char *const name;
59 
60     /* ACTUAL PARAMETER:
61 
62   // BNF with regular expression.
63 args : token* end
64 
65   // just few char separate 'iden'
66 token : ','
67 | '('
68 | ')'
69 | iden	     // maybe a label (include at least one alphabet),
70 		      maybe a number, maybe a expr
71 | regname
72 
73 regname : '$' iden
74 
75 iden : [a-zA-Z0-9\.\+\-]+
76 
77 end : '\0'
78 
79 
80 FORMAT: A string to describe the format of actual parameter including
81 bit field infomation.  For example, "r5:5,r0:5,sr10:16<<2" matches
82 "$12,$13,12345" and "$4,$7,a_label".  That 'sr' means the instruction
83 may need relocate. '10:16' means bit field of instruction.
84 In a 'format', every 'escape's can be replaced to 'iden' or 'regname'
85 acrroding to its meaning.  We fill all information needed by
86 disassembing and assembing to 'format'.
87 
88   // BNF with regular expression.
89 format : escape (literal+ escape)* literal* end
90 | (literal+ escape)* literal* end
91 
92 end : '\0'       // Get here means parse end.
93 
94   // The intersection between any two among FIRST (end), FIRST
95   // (literal) and FIRST (escape) must be empty.
96   // So we can build a simple parser.
97 literal : ','
98 | '('
99 | ')'
100 
101   // Double '<'s means the real number is the immediate after shifting left.
102 escape : esc_ch bit_field '<' '<' dec2
103 | esc_ch bit_field
104 | esc_ch    // for MACRO. non-macro format must indicate 'bit_field'
105 
106   // '|' means to concatenate nonadjacent bit fields
107   // For example, "10:16|0:4" means
108   // "16 bits starting from the 10th bit concatenating with 4 bits
109   // starting from the 0th bit".
110   // This is to say "[25..10]||[3..0]" (little endian).
111 b_field : dec2 ':' dec2
112 | dec2 ':' dec2 '|' bit_field
113 
114 esc_ch : 's' 'r'   // signed immediate or label need relocate
115 | 's'       // signed immediate no need relocate
116 | 'u'       // unsigned immediate
117 | 'l'       // label needed relocate
118 | 'r'       // general purpose registers
119 | 'f'       // FPU registers
120 | 'v'       // 128 bit SIMD register
121 | 'x'       // 256 bit SIMD register
122 
123 dec2 : [1-9][0-9]?
124 | 0
125 
126 */
127     const char *const format;
128 
129     /* MACRO: Indicate how a macro instruction expand for assembling.
130        The main is to replace the '%num'(means the 'num'th 'escape' in
131        'format') in 'macro' string to get the real instruction.
132 
133        Maybe need
134        */
135     const char *const macro;
136     const int *include;
137     const int *exclude;
138 
139     const unsigned long pinfo;
140 #define USELESS 0x0l
141 /* Instruction is a simple alias only for disassembler use.  */
142 #define INSN_DIS_ALIAS		0x00000001l
143   };
144 
145   struct hash_control;
146 
147   struct loongarch_ase
148   {
149     const int *enabled;
150     struct loongarch_opcode *const opcodes;
151     const int *include;
152     const int *exclude;
153 
154     /* For disassemble to create main opcode hash table.  */
155     const struct loongarch_opcode *opc_htab[16];
156     unsigned char opc_htab_inited;
157 
158     /* For GAS to create hash table.  */
159     struct htab *name_hash_entry;
160   };
161 
162   extern int is_unsigned (const char *);
163   extern int is_signed (const char *);
164   extern int is_branch_label (const char *);
165 
166   extern int loongarch_get_bit_field_width (const char *bit_field, char **end);
167   extern int32_t loongarch_decode_imm (const char *bit_field, insn_t insn,
168 				       int si);
169 
170 #define MAX_ARG_NUM_PLUS_2 9
171 
172   extern size_t loongarch_split_args_by_comma (char *args,
173 					       const char *arg_strs[]);
174   extern char *loongarch_cat_splited_strs (const char *arg_strs[]);
175   extern insn_t loongarch_foreach_args (
176     const char *format, const char *arg_strs[],
177     int32_t (*helper) (char esc1, char esc2, const char *bit_field,
178 		       const char *arg, void *context),
179     void *context);
180 
181   extern int loongarch_check_format (const char *format);
182   extern int loongarch_check_macro (const char *format, const char *macro);
183 
184   extern char *loongarch_expand_macro_with_format_map (
185     const char *format, const char *macro, const char *const arg_strs[],
186     const char *(*map) (char esc1, char esc2, const char *arg),
187     char *(*helper) (const char *const arg_strs[], void *context),
188     void *context, size_t len_str);
189   extern char *loongarch_expand_macro (
190     const char *macro, const char *const arg_strs[],
191     char *(*helper) (const char *const arg_strs[], void *context),
192     void *context, size_t len_str);
193   extern size_t loongarch_bits_imm_needed (int64_t imm, int si);
194 
195   extern void loongarch_eliminate_adjacent_repeat_char (char *dest, char c);
196 
197   extern const char *const loongarch_r_normal_name[32];
198   extern const char *const loongarch_r_alias[32];
199   extern const char *const loongarch_r_alias_1[32];
200   extern const char *const loongarch_r_alias_deprecated[32];
201   extern const char *const loongarch_f_normal_name[32];
202   extern const char *const loongarch_f_alias[32];
203   extern const char *const loongarch_f_alias_deprecated[32];
204   extern const char *const loongarch_fc_normal_name[4];
205   extern const char *const loongarch_fc_numeric_name[4];
206   extern const char *const loongarch_c_normal_name[8];
207   extern const char *const loongarch_cr_normal_name[4];
208   extern const char *const loongarch_v_normal_name[32];
209   extern const char *const loongarch_x_normal_name[32];
210 
211   extern struct loongarch_ase loongarch_ASEs[];
212 
213   extern struct loongarch_ASEs_option
214   {
215     struct opt_abi
216     {
217 	    int elf_abi;
218     } abi;
219 #define ase_abi abi.elf_abi
220 
221     struct opt_isa
222     {
223 	    int use_ilp32;
224 	    int use_lp64;
225 
226 	    int use_soft_float;
227 	    int use_single_float;
228 	    int use_double_float;
229 
230 	    int use_lsx;
231 	    int use_lasx;
232 
233 	    int use_lvz;
234 	    int use_lbt;
235 
236 	    int use_la_local_with_abs;
237 	    int use_la_global_with_pcrel;
238 	    int use_la_global_with_abs;
239     } isa;
240 #define ase_ilp32	isa.use_ilp32
241 #define ase_lp64	isa.use_lp64
242 
243 #define ase_nf		isa.use_soft_float
244 #define ase_sf		isa.use_single_float
245 #define ase_df		isa.use_double_float
246 
247 #define ase_lsx		isa.use_lsx
248 #define ase_lasx	isa.use_lasx
249 
250 #define ase_lvz		isa.use_lvz
251 #define ase_lbt		isa.use_lbt
252 
253 #define ase_labs	isa.use_la_local_with_abs
254 #define ase_gpcr	isa.use_la_global_with_pcrel
255 #define ase_gabs	isa.use_la_global_with_abs
256 
257     int relax;
258     int thin_add_sub;
259   } LARCH_opts;
260 
261   extern size_t loongarch_insn_length (insn_t insn);
262 
263 #ifdef __cplusplus
264 }
265 #endif
266 
267 #endif /* _LOONGARCH_H_ */
268