tc-kvx.c revision 1.1.1.1.2.2 1 1.1.1.1.2.2 perseant /* tc-kvx.c -- Assemble for the KVX ISA
2 1.1.1.1.2.2 perseant
3 1.1.1.1.2.2 perseant Copyright (C) 2009-2024 Free Software Foundation, Inc.
4 1.1.1.1.2.2 perseant Contributed by Kalray SA.
5 1.1.1.1.2.2 perseant
6 1.1.1.1.2.2 perseant This file is part of GAS.
7 1.1.1.1.2.2 perseant
8 1.1.1.1.2.2 perseant GAS is free software; you can redistribute it and/or modify
9 1.1.1.1.2.2 perseant it under the terms of the GNU General Public License as published by
10 1.1.1.1.2.2 perseant the Free Software Foundation; either version 3 of the license, or
11 1.1.1.1.2.2 perseant (at your option) any later version.
12 1.1.1.1.2.2 perseant
13 1.1.1.1.2.2 perseant GAS is distributed in the hope that it will be useful,
14 1.1.1.1.2.2 perseant but WITHOUT ANY WARRANTY; without even the implied warranty of
15 1.1.1.1.2.2 perseant MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 1.1.1.1.2.2 perseant GNU General Public License for more details.
17 1.1.1.1.2.2 perseant
18 1.1.1.1.2.2 perseant You should have received a copy of the GNU General Public License
19 1.1.1.1.2.2 perseant along with this program; see the file COPYING3. If not,
20 1.1.1.1.2.2 perseant see <http://www.gnu.org/licenses/>. */
21 1.1.1.1.2.2 perseant
22 1.1.1.1.2.2 perseant #include "as.h"
23 1.1.1.1.2.2 perseant #include "obstack.h"
24 1.1.1.1.2.2 perseant #include "subsegs.h"
25 1.1.1.1.2.2 perseant #include "tc-kvx.h"
26 1.1.1.1.2.2 perseant #include "libiberty.h"
27 1.1.1.1.2.2 perseant
28 1.1.1.1.2.2 perseant #include <assert.h>
29 1.1.1.1.2.2 perseant #include <stdio.h>
30 1.1.1.1.2.2 perseant #include <stdint.h>
31 1.1.1.1.2.2 perseant #include <string.h>
32 1.1.1.1.2.2 perseant #include <ctype.h>
33 1.1.1.1.2.2 perseant
34 1.1.1.1.2.2 perseant #ifdef OBJ_ELF
35 1.1.1.1.2.2 perseant #include "elf/kvx.h"
36 1.1.1.1.2.2 perseant #include "dwarf2dbg.h"
37 1.1.1.1.2.2 perseant #include "dw2gencfi.h"
38 1.1.1.1.2.2 perseant #endif
39 1.1.1.1.2.2 perseant
40 1.1.1.1.2.2 perseant #define D(args...) do { if(debug) fprintf(args); } while(0)
41 1.1.1.1.2.2 perseant
42 1.1.1.1.2.2 perseant static void supported_cores (char buf[], size_t buflen);
43 1.1.1.1.2.2 perseant
44 1.1.1.1.2.2 perseant #define NELEMS(a) ((int) (sizeof (a)/sizeof ((a)[0])))
45 1.1.1.1.2.2 perseant
46 1.1.1.1.2.2 perseant #define STREQ(x,y) !strcmp(((x) ? (x) : ""), ((y) ? (y) : ""))
47 1.1.1.1.2.2 perseant #define STRNEQ(x,y,n) !strncmp(((x) ? (x) : ""), ((y) ? (y) : ""),(n))
48 1.1.1.1.2.2 perseant
49 1.1.1.1.2.2 perseant /* The PARALLEL_BIT is set to 0 when an instruction is the last of a bundle. */
50 1.1.1.1.2.2 perseant #define PARALLEL_BIT (1u << 31)
51 1.1.1.1.2.2 perseant
52 1.1.1.1.2.2 perseant /*TB begin*/
53 1.1.1.1.2.2 perseant int size_type_function = 1;
54 1.1.1.1.2.2 perseant /*TB end */
55 1.1.1.1.2.2 perseant
56 1.1.1.1.2.2 perseant struct kvx_as_env env = {
57 1.1.1.1.2.2 perseant .params = {
58 1.1.1.1.2.2 perseant .abi = ELF_KVX_ABI_UNDEF,
59 1.1.1.1.2.2 perseant .osabi = ELFOSABI_NONE,
60 1.1.1.1.2.2 perseant .core = -1,
61 1.1.1.1.2.2 perseant .core_set = 0,
62 1.1.1.1.2.2 perseant .abi_set = 0,
63 1.1.1.1.2.2 perseant .osabi_set = 0,
64 1.1.1.1.2.2 perseant .pic_flags = 0,
65 1.1.1.1.2.2 perseant .arch_size = 64
66 1.1.1.1.2.2 perseant },
67 1.1.1.1.2.2 perseant .opts = {
68 1.1.1.1.2.2 perseant .march = NULL,
69 1.1.1.1.2.2 perseant .check_resource_usage = 1,
70 1.1.1.1.2.2 perseant .generate_illegal_code = 0,
71 1.1.1.1.2.2 perseant .dump_table = 0,
72 1.1.1.1.2.2 perseant .dump_insn = 0,
73 1.1.1.1.2.2 perseant .diagnostics = 1,
74 1.1.1.1.2.2 perseant .more = 1,
75 1.1.1.1.2.2 perseant .allow_all_sfr = 0
76 1.1.1.1.2.2 perseant }
77 1.1.1.1.2.2 perseant };
78 1.1.1.1.2.2 perseant
79 1.1.1.1.2.2 perseant /* This string should contain position in string where error occured. */
80 1.1.1.1.2.2 perseant
81 1.1.1.1.2.2 perseant /* Default kvx_registers array. */
82 1.1.1.1.2.2 perseant const struct kvx_Register *kvx_registers = NULL;
83 1.1.1.1.2.2 perseant /* Default kvx_modifiers array. */
84 1.1.1.1.2.2 perseant const char ***kvx_modifiers = NULL;
85 1.1.1.1.2.2 perseant /* Default kvx_regfiles array. */
86 1.1.1.1.2.2 perseant const int *kvx_regfiles = NULL;
87 1.1.1.1.2.2 perseant /* Default values used if no assume directive is given */
88 1.1.1.1.2.2 perseant const struct kvx_core_info *kvx_core_info = NULL;
89 1.1.1.1.2.2 perseant
90 1.1.1.1.2.2 perseant /***********************************************/
91 1.1.1.1.2.2 perseant /* Generic Globals for GAS */
92 1.1.1.1.2.2 perseant /***********************************************/
93 1.1.1.1.2.2 perseant
94 1.1.1.1.2.2 perseant const char comment_chars[] = "#";
95 1.1.1.1.2.2 perseant const char line_comment_chars[] = "#";
96 1.1.1.1.2.2 perseant const char line_separator_chars[] = ";";
97 1.1.1.1.2.2 perseant const char EXP_CHARS[] = "eE";
98 1.1.1.1.2.2 perseant const char FLT_CHARS[] = "dD";
99 1.1.1.1.2.2 perseant const int md_short_jump_size = 0;
100 1.1.1.1.2.2 perseant const int md_long_jump_size = 0;
101 1.1.1.1.2.2 perseant
102 1.1.1.1.2.2 perseant /***********************************************/
103 1.1.1.1.2.2 perseant /* Local Types */
104 1.1.1.1.2.2 perseant /***********************************************/
105 1.1.1.1.2.2 perseant
106 1.1.1.1.2.2 perseant /* a fix up record */
107 1.1.1.1.2.2 perseant
108 1.1.1.1.2.2 perseant struct kvx_fixup
109 1.1.1.1.2.2 perseant {
110 1.1.1.1.2.2 perseant /* The expression used. */
111 1.1.1.1.2.2 perseant expressionS exp;
112 1.1.1.1.2.2 perseant /* The place in the frag where this goes. */
113 1.1.1.1.2.2 perseant int where;
114 1.1.1.1.2.2 perseant /* The relocation. */
115 1.1.1.1.2.2 perseant bfd_reloc_code_real_type reloc;
116 1.1.1.1.2.2 perseant };
117 1.1.1.1.2.2 perseant
118 1.1.1.1.2.2 perseant /* a single assembled instruction record */
119 1.1.1.1.2.2 perseant /* may include immediate extension words */
120 1.1.1.1.2.2 perseant struct kvxinsn
121 1.1.1.1.2.2 perseant {
122 1.1.1.1.2.2 perseant /* written out? */
123 1.1.1.1.2.2 perseant int written;
124 1.1.1.1.2.2 perseant /* Opcode table entry for this insn */
125 1.1.1.1.2.2 perseant const struct kvxopc *opdef;
126 1.1.1.1.2.2 perseant /* length of instruction in words (1 or 2) */
127 1.1.1.1.2.2 perseant int len;
128 1.1.1.1.2.2 perseant /* insn is extended */
129 1.1.1.1.2.2 perseant int immx0;
130 1.1.1.1.2.2 perseant /* insn has two immx */
131 1.1.1.1.2.2 perseant int immx1;
132 1.1.1.1.2.2 perseant /* order to stabilize sort */
133 1.1.1.1.2.2 perseant int order;
134 1.1.1.1.2.2 perseant /* instruction words */
135 1.1.1.1.2.2 perseant uint32_t words[KVXMAXBUNDLEWORDS];
136 1.1.1.1.2.2 perseant /* the number of fixups [0,2] */
137 1.1.1.1.2.2 perseant int nfixups;
138 1.1.1.1.2.2 perseant /* the actual fixups */
139 1.1.1.1.2.2 perseant struct kvx_fixup fixup[2];
140 1.1.1.1.2.2 perseant };
141 1.1.1.1.2.2 perseant
142 1.1.1.1.2.2 perseant typedef void (*print_insn_t) (struct kvxopc * op);
143 1.1.1.1.2.2 perseant static print_insn_t print_insn = NULL;
144 1.1.1.1.2.2 perseant
145 1.1.1.1.2.2 perseant /* Set to TRUE when we assemble instructions. */
146 1.1.1.1.2.2 perseant static bool assembling_insn = false;
147 1.1.1.1.2.2 perseant
148 1.1.1.1.2.2 perseant #define NOIMMX -1
149 1.1.1.1.2.2 perseant
150 1.1.1.1.2.2 perseant /* Was KVXMAXBUNDLEISSUE, changed because of NOPs */
151 1.1.1.1.2.2 perseant static struct kvxinsn insbuf[KVXMAXBUNDLEWORDS];
152 1.1.1.1.2.2 perseant static int insncnt = 0;
153 1.1.1.1.2.2 perseant static struct kvxinsn immxbuf[KVXMAXBUNDLEWORDS];
154 1.1.1.1.2.2 perseant static int immxcnt = 0;
155 1.1.1.1.2.2 perseant
156 1.1.1.1.2.2 perseant static void
157 1.1.1.1.2.2 perseant incr_immxcnt (void)
158 1.1.1.1.2.2 perseant {
159 1.1.1.1.2.2 perseant immxcnt++;
160 1.1.1.1.2.2 perseant if (immxcnt >= KVXMAXBUNDLEWORDS)
161 1.1.1.1.2.2 perseant as_bad ("Max immx number exceeded: %d", immxcnt);
162 1.1.1.1.2.2 perseant }
163 1.1.1.1.2.2 perseant
164 1.1.1.1.2.2 perseant static void set_byte_counter (asection * sec, int value);
165 1.1.1.1.2.2 perseant static void
166 1.1.1.1.2.2 perseant set_byte_counter (asection * sec, int value)
167 1.1.1.1.2.2 perseant {
168 1.1.1.1.2.2 perseant sec->target_index = value;
169 1.1.1.1.2.2 perseant }
170 1.1.1.1.2.2 perseant
171 1.1.1.1.2.2 perseant static int get_byte_counter (asection * sec);
172 1.1.1.1.2.2 perseant int
173 1.1.1.1.2.2 perseant get_byte_counter (asection * sec)
174 1.1.1.1.2.2 perseant {
175 1.1.1.1.2.2 perseant return sec->target_index;
176 1.1.1.1.2.2 perseant }
177 1.1.1.1.2.2 perseant
178 1.1.1.1.2.2 perseant const char *
179 1.1.1.1.2.2 perseant kvx_target_format (void)
180 1.1.1.1.2.2 perseant {
181 1.1.1.1.2.2 perseant return env.params.arch_size == 64 ? "elf64-kvx" : "elf32-kvx";
182 1.1.1.1.2.2 perseant }
183 1.1.1.1.2.2 perseant
184 1.1.1.1.2.2 perseant /****************************************************/
185 1.1.1.1.2.2 perseant /* ASSEMBLER Pseudo-ops. Some of this just */
186 1.1.1.1.2.2 perseant /* extends the default definitions */
187 1.1.1.1.2.2 perseant /* others are KVX specific */
188 1.1.1.1.2.2 perseant /****************************************************/
189 1.1.1.1.2.2 perseant
190 1.1.1.1.2.2 perseant static void kvx_check_resources (int);
191 1.1.1.1.2.2 perseant static void kvx_proc (int start);
192 1.1.1.1.2.2 perseant static void kvx_endp (int start);
193 1.1.1.1.2.2 perseant static void kvx_type (int start);
194 1.1.1.1.2.2 perseant
195 1.1.1.1.2.2 perseant const pseudo_typeS md_pseudo_table[] = {
196 1.1.1.1.2.2 perseant /* override default 2-bytes */
197 1.1.1.1.2.2 perseant { "word", cons, 4 },
198 1.1.1.1.2.2 perseant
199 1.1.1.1.2.2 perseant /* KVX specific */
200 1.1.1.1.2.2 perseant { "dword", cons, 8 },
201 1.1.1.1.2.2 perseant
202 1.1.1.1.2.2 perseant /* Override align directives to have a boundary as argument (and not the
203 1.1.1.1.2.2 perseant power of two as in p2align) */
204 1.1.1.1.2.2 perseant { "align", s_align_bytes, 0 },
205 1.1.1.1.2.2 perseant
206 1.1.1.1.2.2 perseant { "checkresources", kvx_check_resources, 1 },
207 1.1.1.1.2.2 perseant { "nocheckresources", kvx_check_resources, 0 },
208 1.1.1.1.2.2 perseant
209 1.1.1.1.2.2 perseant { "proc", kvx_proc, 1 },
210 1.1.1.1.2.2 perseant { "endp", kvx_endp, 0 },
211 1.1.1.1.2.2 perseant
212 1.1.1.1.2.2 perseant { "type", kvx_type, 0 },
213 1.1.1.1.2.2 perseant
214 1.1.1.1.2.2 perseant #ifdef OBJ_ELF
215 1.1.1.1.2.2 perseant { "file", dwarf2_directive_file, 0 },
216 1.1.1.1.2.2 perseant { "loc", dwarf2_directive_loc, 0 },
217 1.1.1.1.2.2 perseant #endif
218 1.1.1.1.2.2 perseant { NULL, 0, 0 }
219 1.1.1.1.2.2 perseant };
220 1.1.1.1.2.2 perseant
221 1.1.1.1.2.2 perseant
222 1.1.1.1.2.2 perseant static int inside_bundle = 0;
223 1.1.1.1.2.2 perseant
224 1.1.1.1.2.2 perseant /* Stores the labels inside bundles (typically debug labels) that need
225 1.1.1.1.2.2 perseant to be postponed to the next bundle. */
226 1.1.1.1.2.2 perseant struct label_fix
227 1.1.1.1.2.2 perseant {
228 1.1.1.1.2.2 perseant struct label_fix *next;
229 1.1.1.1.2.2 perseant symbolS *sym;
230 1.1.1.1.2.2 perseant } *label_fixes = 0;
231 1.1.1.1.2.2 perseant
232 1.1.1.1.2.2 perseant /*****************************************************/
233 1.1.1.1.2.2 perseant /* OPTIONS PROCESSING */
234 1.1.1.1.2.2 perseant /*****************************************************/
235 1.1.1.1.2.2 perseant
236 1.1.1.1.2.2 perseant const char *md_shortopts = "hV"; /* catted to std short options */
237 1.1.1.1.2.2 perseant
238 1.1.1.1.2.2 perseant /* added to std long options */
239 1.1.1.1.2.2 perseant
240 1.1.1.1.2.2 perseant #define OPTION_HEXFILE (OPTION_MD_BASE + 0)
241 1.1.1.1.2.2 perseant #define OPTION_MARCH (OPTION_MD_BASE + 4)
242 1.1.1.1.2.2 perseant #define OPTION_CHECK_RESOURCES (OPTION_MD_BASE + 5)
243 1.1.1.1.2.2 perseant #define OPTION_NO_CHECK_RESOURCES (OPTION_MD_BASE + 6)
244 1.1.1.1.2.2 perseant #define OPTION_GENERATE_ILLEGAL_CODE (OPTION_MD_BASE + 7)
245 1.1.1.1.2.2 perseant #define OPTION_DUMP_TABLE (OPTION_MD_BASE + 8)
246 1.1.1.1.2.2 perseant #define OPTION_PIC (OPTION_MD_BASE + 9)
247 1.1.1.1.2.2 perseant #define OPTION_BIGPIC (OPTION_MD_BASE + 10)
248 1.1.1.1.2.2 perseant #define OPTION_NOPIC (OPTION_MD_BASE + 12)
249 1.1.1.1.2.2 perseant #define OPTION_32 (OPTION_MD_BASE + 13)
250 1.1.1.1.2.2 perseant #define OPTION_DUMPINSN (OPTION_MD_BASE + 15)
251 1.1.1.1.2.2 perseant #define OPTION_ALL_SFR (OPTION_MD_BASE + 16)
252 1.1.1.1.2.2 perseant #define OPTION_DIAGNOSTICS (OPTION_MD_BASE + 17)
253 1.1.1.1.2.2 perseant #define OPTION_NO_DIAGNOSTICS (OPTION_MD_BASE + 18)
254 1.1.1.1.2.2 perseant #define OPTION_MORE (OPTION_MD_BASE + 19)
255 1.1.1.1.2.2 perseant #define OPTION_NO_MORE (OPTION_MD_BASE + 20)
256 1.1.1.1.2.2 perseant
257 1.1.1.1.2.2 perseant struct option md_longopts[] = {
258 1.1.1.1.2.2 perseant { "march", required_argument, NULL, OPTION_MARCH },
259 1.1.1.1.2.2 perseant { "check-resources", no_argument, NULL, OPTION_CHECK_RESOURCES },
260 1.1.1.1.2.2 perseant { "no-check-resources", no_argument, NULL, OPTION_NO_CHECK_RESOURCES },
261 1.1.1.1.2.2 perseant { "generate-illegal-code", no_argument, NULL, OPTION_GENERATE_ILLEGAL_CODE },
262 1.1.1.1.2.2 perseant { "dump-table", no_argument, NULL, OPTION_DUMP_TABLE },
263 1.1.1.1.2.2 perseant { "mpic", no_argument, NULL, OPTION_PIC },
264 1.1.1.1.2.2 perseant { "mPIC", no_argument, NULL, OPTION_BIGPIC },
265 1.1.1.1.2.2 perseant { "mnopic", no_argument, NULL, OPTION_NOPIC },
266 1.1.1.1.2.2 perseant { "m32", no_argument, NULL, OPTION_32 },
267 1.1.1.1.2.2 perseant { "dump-insn", no_argument, NULL, OPTION_DUMPINSN },
268 1.1.1.1.2.2 perseant { "all-sfr", no_argument, NULL, OPTION_ALL_SFR },
269 1.1.1.1.2.2 perseant { "diagnostics", no_argument, NULL, OPTION_DIAGNOSTICS },
270 1.1.1.1.2.2 perseant { "no-diagnostics", no_argument, NULL, OPTION_NO_DIAGNOSTICS },
271 1.1.1.1.2.2 perseant { "more", no_argument, NULL, OPTION_MORE },
272 1.1.1.1.2.2 perseant { "no-more", no_argument, NULL, OPTION_NO_MORE },
273 1.1.1.1.2.2 perseant { NULL, no_argument, NULL, 0 }
274 1.1.1.1.2.2 perseant };
275 1.1.1.1.2.2 perseant
276 1.1.1.1.2.2 perseant size_t md_longopts_size = sizeof (md_longopts);
277 1.1.1.1.2.2 perseant
278 1.1.1.1.2.2 perseant int
279 1.1.1.1.2.2 perseant md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
280 1.1.1.1.2.2 perseant {
281 1.1.1.1.2.2 perseant int find_core = 0;
282 1.1.1.1.2.2 perseant
283 1.1.1.1.2.2 perseant switch (c)
284 1.1.1.1.2.2 perseant {
285 1.1.1.1.2.2 perseant case 'h':
286 1.1.1.1.2.2 perseant md_show_usage (stdout);
287 1.1.1.1.2.2 perseant exit (EXIT_SUCCESS);
288 1.1.1.1.2.2 perseant break;
289 1.1.1.1.2.2 perseant
290 1.1.1.1.2.2 perseant /* -V: SVR4 argument to print version ID. */
291 1.1.1.1.2.2 perseant case 'V':
292 1.1.1.1.2.2 perseant print_version_id ();
293 1.1.1.1.2.2 perseant exit (EXIT_SUCCESS);
294 1.1.1.1.2.2 perseant break;
295 1.1.1.1.2.2 perseant case OPTION_MARCH:
296 1.1.1.1.2.2 perseant env.opts.march = strdup (arg);
297 1.1.1.1.2.2 perseant for (int i = 0; i < KVXNUMCORES && !find_core; ++i)
298 1.1.1.1.2.2 perseant if (!strcasecmp (env.opts.march, kvx_core_info_table[i]->name))
299 1.1.1.1.2.2 perseant {
300 1.1.1.1.2.2 perseant kvx_core_info = kvx_core_info_table[i];
301 1.1.1.1.2.2 perseant kvx_registers = kvx_registers_table[i];
302 1.1.1.1.2.2 perseant kvx_modifiers = kvx_modifiers_table[i];
303 1.1.1.1.2.2 perseant kvx_regfiles = kvx_regfiles_table[i];
304 1.1.1.1.2.2 perseant
305 1.1.1.1.2.2 perseant find_core = 1;
306 1.1.1.1.2.2 perseant break;
307 1.1.1.1.2.2 perseant }
308 1.1.1.1.2.2 perseant if (!find_core)
309 1.1.1.1.2.2 perseant {
310 1.1.1.1.2.2 perseant char buf[100];
311 1.1.1.1.2.2 perseant supported_cores (buf, sizeof (buf));
312 1.1.1.1.2.2 perseant as_fatal ("Specified arch not supported [%s]", buf);
313 1.1.1.1.2.2 perseant }
314 1.1.1.1.2.2 perseant break;
315 1.1.1.1.2.2 perseant case OPTION_CHECK_RESOURCES:
316 1.1.1.1.2.2 perseant env.opts.check_resource_usage = 1;
317 1.1.1.1.2.2 perseant break;
318 1.1.1.1.2.2 perseant case OPTION_NO_CHECK_RESOURCES:
319 1.1.1.1.2.2 perseant env.opts.check_resource_usage = 0;
320 1.1.1.1.2.2 perseant break;
321 1.1.1.1.2.2 perseant case OPTION_GENERATE_ILLEGAL_CODE:
322 1.1.1.1.2.2 perseant env.opts.generate_illegal_code = 1;
323 1.1.1.1.2.2 perseant break;
324 1.1.1.1.2.2 perseant case OPTION_DUMP_TABLE:
325 1.1.1.1.2.2 perseant env.opts.dump_table = 1;
326 1.1.1.1.2.2 perseant break;
327 1.1.1.1.2.2 perseant case OPTION_DUMPINSN:
328 1.1.1.1.2.2 perseant env.opts.dump_insn = 1;
329 1.1.1.1.2.2 perseant break;
330 1.1.1.1.2.2 perseant case OPTION_ALL_SFR:
331 1.1.1.1.2.2 perseant env.opts.allow_all_sfr = 1;
332 1.1.1.1.2.2 perseant break;
333 1.1.1.1.2.2 perseant case OPTION_DIAGNOSTICS:
334 1.1.1.1.2.2 perseant env.opts.diagnostics = 1;
335 1.1.1.1.2.2 perseant break;
336 1.1.1.1.2.2 perseant case OPTION_NO_DIAGNOSTICS:
337 1.1.1.1.2.2 perseant env.opts.diagnostics = 0;
338 1.1.1.1.2.2 perseant break;
339 1.1.1.1.2.2 perseant case OPTION_MORE:
340 1.1.1.1.2.2 perseant env.opts.more = 1;
341 1.1.1.1.2.2 perseant break;
342 1.1.1.1.2.2 perseant case OPTION_NO_MORE:
343 1.1.1.1.2.2 perseant env.opts.more = 0;
344 1.1.1.1.2.2 perseant break;
345 1.1.1.1.2.2 perseant case OPTION_PIC:
346 1.1.1.1.2.2 perseant /* fallthrough, for now the same on KVX */
347 1.1.1.1.2.2 perseant case OPTION_BIGPIC:
348 1.1.1.1.2.2 perseant env.params.pic_flags |= ELF_KVX_ABI_PIC_BIT;
349 1.1.1.1.2.2 perseant break;
350 1.1.1.1.2.2 perseant case OPTION_NOPIC:
351 1.1.1.1.2.2 perseant env.params.pic_flags &= ~(ELF_KVX_ABI_PIC_BIT);
352 1.1.1.1.2.2 perseant break;
353 1.1.1.1.2.2 perseant case OPTION_32:
354 1.1.1.1.2.2 perseant env.params.arch_size = 32;
355 1.1.1.1.2.2 perseant break;
356 1.1.1.1.2.2 perseant
357 1.1.1.1.2.2 perseant default:
358 1.1.1.1.2.2 perseant return 0;
359 1.1.1.1.2.2 perseant }
360 1.1.1.1.2.2 perseant return 1;
361 1.1.1.1.2.2 perseant }
362 1.1.1.1.2.2 perseant
363 1.1.1.1.2.2 perseant void
364 1.1.1.1.2.2 perseant md_show_usage (FILE * stream)
365 1.1.1.1.2.2 perseant {
366 1.1.1.1.2.2 perseant char buf[100];
367 1.1.1.1.2.2 perseant supported_cores (buf, sizeof (buf));
368 1.1.1.1.2.2 perseant
369 1.1.1.1.2.2 perseant fprintf (stream, "\n"
370 1.1.1.1.2.2 perseant "KVX specific options:\n\n"
371 1.1.1.1.2.2 perseant " --check-resources\t Perform minimal resource checking\n"
372 1.1.1.1.2.2 perseant " --march [%s]\t Select architecture\n"
373 1.1.1.1.2.2 perseant " -V \t\t\t Print assembler version number\n\n"
374 1.1.1.1.2.2 perseant " The options -M, --mri and -f are not supported in this assembler.\n", buf);
375 1.1.1.1.2.2 perseant }
376 1.1.1.1.2.2 perseant
377 1.1.1.1.2.2 perseant /**************************************************/
378 1.1.1.1.2.2 perseant /* UTILITIES */
379 1.1.1.1.2.2 perseant /**************************************************/
380 1.1.1.1.2.2 perseant
381 1.1.1.1.2.2 perseant /*
382 1.1.1.1.2.2 perseant * Read a value from to the object file
383 1.1.1.1.2.2 perseant */
384 1.1.1.1.2.2 perseant
385 1.1.1.1.2.2 perseant static valueT md_chars_to_number (char *buf, int n);
386 1.1.1.1.2.2 perseant valueT
387 1.1.1.1.2.2 perseant md_chars_to_number (char *buf, int n)
388 1.1.1.1.2.2 perseant {
389 1.1.1.1.2.2 perseant valueT val = 0;
390 1.1.1.1.2.2 perseant
391 1.1.1.1.2.2 perseant if (n > (int) sizeof (val) || n <= 0)
392 1.1.1.1.2.2 perseant abort ();
393 1.1.1.1.2.2 perseant
394 1.1.1.1.2.2 perseant while (n--)
395 1.1.1.1.2.2 perseant {
396 1.1.1.1.2.2 perseant val <<= 8;
397 1.1.1.1.2.2 perseant val |= (buf[n] & 0xff);
398 1.1.1.1.2.2 perseant }
399 1.1.1.1.2.2 perseant
400 1.1.1.1.2.2 perseant return val;
401 1.1.1.1.2.2 perseant }
402 1.1.1.1.2.2 perseant
403 1.1.1.1.2.2 perseant /* Returns the corresponding pseudo function matching SYM and to be
404 1.1.1.1.2.2 perseant used for data section */
405 1.1.1.1.2.2 perseant static struct pseudo_func *
406 1.1.1.1.2.2 perseant kvx_get_pseudo_func_data_scn (symbolS * sym)
407 1.1.1.1.2.2 perseant {
408 1.1.1.1.2.2 perseant for (int i = 0; i < kvx_core_info->nb_pseudo_funcs; i++)
409 1.1.1.1.2.2 perseant if (sym == kvx_core_info->pseudo_funcs[i].sym
410 1.1.1.1.2.2 perseant && kvx_core_info->pseudo_funcs[i].pseudo_relocs.single != BFD_RELOC_UNUSED)
411 1.1.1.1.2.2 perseant return &kvx_core_info->pseudo_funcs[i];
412 1.1.1.1.2.2 perseant return NULL;
413 1.1.1.1.2.2 perseant }
414 1.1.1.1.2.2 perseant
415 1.1.1.1.2.2 perseant /* Returns the corresponding pseudo function matching SYM and operand
416 1.1.1.1.2.2 perseant format OPND */
417 1.1.1.1.2.2 perseant static struct pseudo_func *
418 1.1.1.1.2.2 perseant kvx_get_pseudo_func2 (symbolS *sym, struct kvx_operand * opnd)
419 1.1.1.1.2.2 perseant {
420 1.1.1.1.2.2 perseant for (int i = 0; i < kvx_core_info->nb_pseudo_funcs; i++)
421 1.1.1.1.2.2 perseant if (sym == kvx_core_info->pseudo_funcs[i].sym)
422 1.1.1.1.2.2 perseant for (int relidx = 0; relidx < opnd->reloc_nb; relidx++)
423 1.1.1.1.2.2 perseant if (opnd->relocs[relidx] == kvx_core_info->pseudo_funcs[i].pseudo_relocs.kreloc
424 1.1.1.1.2.2 perseant && (env.params.arch_size == (int) kvx_core_info->pseudo_funcs[i].pseudo_relocs.avail_modes
425 1.1.1.1.2.2 perseant || kvx_core_info->pseudo_funcs[i].pseudo_relocs.avail_modes == PSEUDO_ALL))
426 1.1.1.1.2.2 perseant return &kvx_core_info->pseudo_funcs[i];
427 1.1.1.1.2.2 perseant
428 1.1.1.1.2.2 perseant return NULL;
429 1.1.1.1.2.2 perseant }
430 1.1.1.1.2.2 perseant
431 1.1.1.1.2.2 perseant static void
432 1.1.1.1.2.2 perseant supported_cores (char buf[], size_t buflen)
433 1.1.1.1.2.2 perseant {
434 1.1.1.1.2.2 perseant buf[0] = '\0';
435 1.1.1.1.2.2 perseant for (int i = 0; i < KVXNUMCORES; i++)
436 1.1.1.1.2.2 perseant {
437 1.1.1.1.2.2 perseant if (buf[0] == '\0')
438 1.1.1.1.2.2 perseant strcpy (buf, kvx_core_info_table[i]->name);
439 1.1.1.1.2.2 perseant else
440 1.1.1.1.2.2 perseant if ((strlen (buf) + 1 + strlen (kvx_core_info_table[i]->name) + 1) < buflen)
441 1.1.1.1.2.2 perseant {
442 1.1.1.1.2.2 perseant strcat (buf, "|");
443 1.1.1.1.2.2 perseant strcat (buf, kvx_core_info_table[i]->name);
444 1.1.1.1.2.2 perseant }
445 1.1.1.1.2.2 perseant }
446 1.1.1.1.2.2 perseant }
447 1.1.1.1.2.2 perseant
448 1.1.1.1.2.2 perseant /***************************************************/
449 1.1.1.1.2.2 perseant /* ASSEMBLE AN INSTRUCTION */
450 1.1.1.1.2.2 perseant /***************************************************/
451 1.1.1.1.2.2 perseant
452 1.1.1.1.2.2 perseant /*
453 1.1.1.1.2.2 perseant * Insert ARG into the operand described by OPDEF in instruction INSN
454 1.1.1.1.2.2 perseant * Returns 1 if the immediate extension (IMMX) has been
455 1.1.1.1.2.2 perseant * handled along with relocation, 0 if not.
456 1.1.1.1.2.2 perseant */
457 1.1.1.1.2.2 perseant static int
458 1.1.1.1.2.2 perseant insert_operand (struct kvxinsn *insn, struct kvx_operand *opdef,
459 1.1.1.1.2.2 perseant struct token_list *tok)
460 1.1.1.1.2.2 perseant {
461 1.1.1.1.2.2 perseant uint64_t op = 0;
462 1.1.1.1.2.2 perseant struct kvx_bitfield *bfields = opdef->bfield;
463 1.1.1.1.2.2 perseant int bf_nb = opdef->bitfields;
464 1.1.1.1.2.2 perseant int immx_ready = 0;
465 1.1.1.1.2.2 perseant
466 1.1.1.1.2.2 perseant if (opdef->width == 0)
467 1.1.1.1.2.2 perseant return 0;
468 1.1.1.1.2.2 perseant
469 1.1.1.1.2.2 perseant #define add_fixup(insn_, reloc_, exp_) \
470 1.1.1.1.2.2 perseant do { \
471 1.1.1.1.2.2 perseant (insn_)->fixup[(insn_)->nfixups].reloc = (reloc_); \
472 1.1.1.1.2.2 perseant (insn_)->fixup[(insn_)->nfixups].exp = (exp_); \
473 1.1.1.1.2.2 perseant (insn_)->fixup[(insn_)->nfixups].where = 0; \
474 1.1.1.1.2.2 perseant (insn_)->nfixups++; \
475 1.1.1.1.2.2 perseant } while (0)
476 1.1.1.1.2.2 perseant
477 1.1.1.1.2.2 perseant #define add_immx(insn_, words_, reloc_, exp_, nfixups_, len_) \
478 1.1.1.1.2.2 perseant do { \
479 1.1.1.1.2.2 perseant immxbuf[immxcnt].words[0] = (words_); \
480 1.1.1.1.2.2 perseant immxbuf[immxcnt].fixup[0].reloc = (reloc_); \
481 1.1.1.1.2.2 perseant immxbuf[immxcnt].fixup[0].exp = (exp_); \
482 1.1.1.1.2.2 perseant immxbuf[immxcnt].fixup[0].where = 0; \
483 1.1.1.1.2.2 perseant immxbuf[immxcnt].nfixups = (nfixups_); \
484 1.1.1.1.2.2 perseant immxbuf[immxcnt].len = (len_); \
485 1.1.1.1.2.2 perseant /* decrement insn->len: immx part handled separately \
486 1.1.1.1.2.2 perseant from insn and must not be emited twice. */ \
487 1.1.1.1.2.2 perseant (insn_)->len -= 1; \
488 1.1.1.1.2.2 perseant incr_immxcnt (); \
489 1.1.1.1.2.2 perseant } while (0)
490 1.1.1.1.2.2 perseant
491 1.1.1.1.2.2 perseant #define chk_imm(core_, imm_) \
492 1.1.1.1.2.2 perseant (env.params.core == ELF_KVX_CORE_## core_ && opdef->type == (imm_))
493 1.1.1.1.2.2 perseant
494 1.1.1.1.2.2 perseant /* try to resolve the value */
495 1.1.1.1.2.2 perseant
496 1.1.1.1.2.2 perseant switch (tok->category)
497 1.1.1.1.2.2 perseant {
498 1.1.1.1.2.2 perseant case CAT_REGISTER:
499 1.1.1.1.2.2 perseant op = S_GET_VALUE (str_hash_find (env.reg_hash, tok->tok));
500 1.1.1.1.2.2 perseant op -= opdef->bias;
501 1.1.1.1.2.2 perseant op >>= opdef->shift;
502 1.1.1.1.2.2 perseant break;
503 1.1.1.1.2.2 perseant case CAT_MODIFIER:
504 1.1.1.1.2.2 perseant op = tok->val;
505 1.1.1.1.2.2 perseant op -= opdef->bias;
506 1.1.1.1.2.2 perseant op >>= opdef->shift;
507 1.1.1.1.2.2 perseant break;
508 1.1.1.1.2.2 perseant case CAT_IMMEDIATE:
509 1.1.1.1.2.2 perseant {
510 1.1.1.1.2.2 perseant char *ilp_save = input_line_pointer;
511 1.1.1.1.2.2 perseant input_line_pointer = tok->tok;
512 1.1.1.1.2.2 perseant expressionS exp = { 0 };
513 1.1.1.1.2.2 perseant expression (&exp);
514 1.1.1.1.2.2 perseant input_line_pointer = ilp_save;
515 1.1.1.1.2.2 perseant
516 1.1.1.1.2.2 perseant /* We are dealing with a pseudo-function. */
517 1.1.1.1.2.2 perseant if (tok->tok[0] == '@')
518 1.1.1.1.2.2 perseant {
519 1.1.1.1.2.2 perseant if (insn->nfixups == 0)
520 1.1.1.1.2.2 perseant {
521 1.1.1.1.2.2 perseant expressionS reloc_arg;
522 1.1.1.1.2.2 perseant reloc_arg = exp;
523 1.1.1.1.2.2 perseant reloc_arg.X_op = O_symbol;
524 1.1.1.1.2.2 perseant struct pseudo_func *pf =
525 1.1.1.1.2.2 perseant kvx_get_pseudo_func2 (exp.X_op_symbol, opdef);
526 1.1.1.1.2.2 perseant /* S64 uses LO10/UP27/EX27 format (3 words), with one reloc in each words (3) */
527 1.1.1.1.2.2 perseant /* S43 uses LO10/EX6/UP27 format (2 words), with 2 relocs in main syllabes and 1 in extra word */
528 1.1.1.1.2.2 perseant /* S37 uses LO10/UP27 format (2 words), with one reloc in each word (2) */
529 1.1.1.1.2.2 perseant
530 1.1.1.1.2.2 perseant /* Beware that immxbuf must be filled in the same order as relocs should be emitted. */
531 1.1.1.1.2.2 perseant
532 1.1.1.1.2.2 perseant if (pf->pseudo_relocs.reloc_type == S64_LO10_UP27_EX27
533 1.1.1.1.2.2 perseant || pf->pseudo_relocs.reloc_type == S43_LO10_UP27_EX6
534 1.1.1.1.2.2 perseant || pf->pseudo_relocs.reloc_type == S37_LO10_UP27)
535 1.1.1.1.2.2 perseant {
536 1.1.1.1.2.2 perseant add_fixup (insn, pf->pseudo_relocs.reloc_lo10, reloc_arg);
537 1.1.1.1.2.2 perseant
538 1.1.1.1.2.2 perseant insn->immx0 = immxcnt;
539 1.1.1.1.2.2 perseant add_immx (insn, 0, pf->pseudo_relocs.reloc_up27,
540 1.1.1.1.2.2 perseant reloc_arg, 1, 1);
541 1.1.1.1.2.2 perseant immx_ready = 1;
542 1.1.1.1.2.2 perseant }
543 1.1.1.1.2.2 perseant else if (pf->pseudo_relocs.reloc_type == S32_LO5_UP27)
544 1.1.1.1.2.2 perseant {
545 1.1.1.1.2.2 perseant add_fixup (insn, pf->pseudo_relocs.reloc_lo5, reloc_arg);
546 1.1.1.1.2.2 perseant
547 1.1.1.1.2.2 perseant insn->immx0 = immxcnt;
548 1.1.1.1.2.2 perseant add_immx (insn, 0, pf->pseudo_relocs.reloc_up27,
549 1.1.1.1.2.2 perseant reloc_arg, 1, 1);
550 1.1.1.1.2.2 perseant immx_ready = 1;
551 1.1.1.1.2.2 perseant }
552 1.1.1.1.2.2 perseant else if (pf->pseudo_relocs.reloc_type == S16)
553 1.1.1.1.2.2 perseant add_fixup (insn, pf->pseudo_relocs.single, reloc_arg);
554 1.1.1.1.2.2 perseant else
555 1.1.1.1.2.2 perseant as_fatal ("Unexpected fixup");
556 1.1.1.1.2.2 perseant
557 1.1.1.1.2.2 perseant if (pf->pseudo_relocs.reloc_type == S64_LO10_UP27_EX27)
558 1.1.1.1.2.2 perseant {
559 1.1.1.1.2.2 perseant insn->immx1 = immxcnt;
560 1.1.1.1.2.2 perseant add_immx (insn, 0, pf->pseudo_relocs.reloc_ex, reloc_arg,
561 1.1.1.1.2.2 perseant 1, 1);
562 1.1.1.1.2.2 perseant }
563 1.1.1.1.2.2 perseant else if (pf->pseudo_relocs.reloc_type == S43_LO10_UP27_EX6)
564 1.1.1.1.2.2 perseant add_fixup (insn, pf->pseudo_relocs.reloc_ex, reloc_arg);
565 1.1.1.1.2.2 perseant }
566 1.1.1.1.2.2 perseant }
567 1.1.1.1.2.2 perseant else
568 1.1.1.1.2.2 perseant {
569 1.1.1.1.2.2 perseant if (exp.X_op == O_constant)
570 1.1.1.1.2.2 perseant {
571 1.1.1.1.2.2 perseant /* This is a immediate: either a regular immediate, or an
572 1.1.1.1.2.2 perseant immediate that was saved in a variable through `.equ'. */
573 1.1.1.1.2.2 perseant uint64_t sval = (int64_t) tok->val;
574 1.1.1.1.2.2 perseant op = opdef->flags & kvxSIGNED ? sval : tok->val;
575 1.1.1.1.2.2 perseant op >>= opdef->shift;
576 1.1.1.1.2.2 perseant }
577 1.1.1.1.2.2 perseant else if (exp.X_op == O_subtract)
578 1.1.1.1.2.2 perseant as_fatal ("O_subtract not supported.");
579 1.1.1.1.2.2 perseant else
580 1.1.1.1.2.2 perseant {
581 1.1.1.1.2.2 perseant
582 1.1.1.1.2.2 perseant /* This is a symbol which needs a relocation. */
583 1.1.1.1.2.2 perseant if (insn->nfixups == 0)
584 1.1.1.1.2.2 perseant {
585 1.1.1.1.2.2 perseant if (chk_imm (KV3_1, Immediate_kv3_v1_pcrel17)
586 1.1.1.1.2.2 perseant || chk_imm (KV3_2, Immediate_kv3_v2_pcrel17)
587 1.1.1.1.2.2 perseant || chk_imm (KV4_1, Immediate_kv4_v1_pcrel17))
588 1.1.1.1.2.2 perseant add_fixup (insn, BFD_RELOC_KVX_PCREL17, exp);
589 1.1.1.1.2.2 perseant else if (chk_imm (KV3_1, Immediate_kv3_v1_pcrel27)
590 1.1.1.1.2.2 perseant || chk_imm (KV3_2, Immediate_kv3_v2_pcrel27)
591 1.1.1.1.2.2 perseant || chk_imm (KV4_1, Immediate_kv4_v1_pcrel27))
592 1.1.1.1.2.2 perseant add_fixup (insn, BFD_RELOC_KVX_PCREL27, exp);
593 1.1.1.1.2.2 perseant else if (chk_imm (KV3_1, Immediate_kv3_v1_wrapped32)
594 1.1.1.1.2.2 perseant || chk_imm (KV3_2, Immediate_kv3_v2_wrapped32)
595 1.1.1.1.2.2 perseant || chk_imm (KV4_1, Immediate_kv4_v1_wrapped32))
596 1.1.1.1.2.2 perseant {
597 1.1.1.1.2.2 perseant add_fixup (insn, BFD_RELOC_KVX_S32_LO5, exp);
598 1.1.1.1.2.2 perseant
599 1.1.1.1.2.2 perseant insn->immx0 = immxcnt;
600 1.1.1.1.2.2 perseant add_immx (insn, 0, BFD_RELOC_KVX_S32_UP27, exp, 1, 1);
601 1.1.1.1.2.2 perseant
602 1.1.1.1.2.2 perseant immx_ready = 1;
603 1.1.1.1.2.2 perseant }
604 1.1.1.1.2.2 perseant else if (chk_imm (KV3_1, Immediate_kv3_v1_signed10)
605 1.1.1.1.2.2 perseant || chk_imm (KV3_2, Immediate_kv3_v2_signed10)
606 1.1.1.1.2.2 perseant || chk_imm (KV4_1, Immediate_kv4_v1_signed10))
607 1.1.1.1.2.2 perseant add_fixup (insn, BFD_RELOC_KVX_S37_LO10, exp);
608 1.1.1.1.2.2 perseant else if (chk_imm (KV3_1, Immediate_kv3_v1_signed37)
609 1.1.1.1.2.2 perseant || chk_imm (KV3_2, Immediate_kv3_v2_signed37)
610 1.1.1.1.2.2 perseant || chk_imm (KV4_1, Immediate_kv4_v1_signed37))
611 1.1.1.1.2.2 perseant {
612 1.1.1.1.2.2 perseant add_fixup (insn, BFD_RELOC_KVX_S37_LO10, exp);
613 1.1.1.1.2.2 perseant
614 1.1.1.1.2.2 perseant insn->immx0 = immxcnt;
615 1.1.1.1.2.2 perseant add_immx (insn, 0, BFD_RELOC_KVX_S37_UP27, exp, 1, 1);
616 1.1.1.1.2.2 perseant
617 1.1.1.1.2.2 perseant immx_ready = 1;
618 1.1.1.1.2.2 perseant }
619 1.1.1.1.2.2 perseant else if (chk_imm (KV3_1, Immediate_kv3_v1_signed43)
620 1.1.1.1.2.2 perseant || chk_imm (KV3_2, Immediate_kv3_v2_signed43)
621 1.1.1.1.2.2 perseant || chk_imm (KV4_1, Immediate_kv4_v1_signed43))
622 1.1.1.1.2.2 perseant {
623 1.1.1.1.2.2 perseant add_fixup (insn, BFD_RELOC_KVX_S43_LO10, exp);
624 1.1.1.1.2.2 perseant add_fixup (insn, BFD_RELOC_KVX_S43_EX6, exp);
625 1.1.1.1.2.2 perseant
626 1.1.1.1.2.2 perseant insn->immx0 = immxcnt;
627 1.1.1.1.2.2 perseant add_immx (insn, insn->words[1],
628 1.1.1.1.2.2 perseant BFD_RELOC_KVX_S43_UP27, exp, 1, 1);
629 1.1.1.1.2.2 perseant
630 1.1.1.1.2.2 perseant immx_ready = 1;
631 1.1.1.1.2.2 perseant }
632 1.1.1.1.2.2 perseant else if (chk_imm (KV3_1, Immediate_kv3_v1_wrapped64)
633 1.1.1.1.2.2 perseant || chk_imm (KV3_2, Immediate_kv3_v2_wrapped64)
634 1.1.1.1.2.2 perseant || chk_imm (KV4_1, Immediate_kv4_v1_wrapped64))
635 1.1.1.1.2.2 perseant {
636 1.1.1.1.2.2 perseant add_fixup (insn, BFD_RELOC_KVX_S64_LO10, exp);
637 1.1.1.1.2.2 perseant
638 1.1.1.1.2.2 perseant insn->immx0 = immxcnt;
639 1.1.1.1.2.2 perseant add_immx (insn, insn->words[1],
640 1.1.1.1.2.2 perseant BFD_RELOC_KVX_S64_UP27, exp, 1, 1);
641 1.1.1.1.2.2 perseant
642 1.1.1.1.2.2 perseant insn->immx1 = immxcnt;
643 1.1.1.1.2.2 perseant add_immx (insn, insn->words[2],
644 1.1.1.1.2.2 perseant BFD_RELOC_KVX_S64_EX27, exp, 1, 1);
645 1.1.1.1.2.2 perseant
646 1.1.1.1.2.2 perseant immx_ready = 1;
647 1.1.1.1.2.2 perseant }
648 1.1.1.1.2.2 perseant else
649 1.1.1.1.2.2 perseant as_fatal ("don't know how to generate a fixup record");
650 1.1.1.1.2.2 perseant return immx_ready;
651 1.1.1.1.2.2 perseant }
652 1.1.1.1.2.2 perseant else
653 1.1.1.1.2.2 perseant as_fatal ("No room for fixup ");
654 1.1.1.1.2.2 perseant }
655 1.1.1.1.2.2 perseant }
656 1.1.1.1.2.2 perseant }
657 1.1.1.1.2.2 perseant break;
658 1.1.1.1.2.2 perseant default:
659 1.1.1.1.2.2 perseant break;
660 1.1.1.1.2.2 perseant }
661 1.1.1.1.2.2 perseant
662 1.1.1.1.2.2 perseant for (int bf_idx = 0; bf_idx < bf_nb; bf_idx++)
663 1.1.1.1.2.2 perseant {
664 1.1.1.1.2.2 perseant uint64_t value =
665 1.1.1.1.2.2 perseant ((uint64_t) op >> bfields[bf_idx].from_offset);
666 1.1.1.1.2.2 perseant int j = 0;
667 1.1.1.1.2.2 perseant int to_offset = bfields[bf_idx].to_offset;
668 1.1.1.1.2.2 perseant value &= (1LL << bfields[bf_idx].size) - 1;
669 1.1.1.1.2.2 perseant j = to_offset / 32;
670 1.1.1.1.2.2 perseant to_offset = to_offset % 32;
671 1.1.1.1.2.2 perseant insn->words[j] |= (value << to_offset) & 0xffffffff;
672 1.1.1.1.2.2 perseant }
673 1.1.1.1.2.2 perseant
674 1.1.1.1.2.2 perseant return immx_ready;
675 1.1.1.1.2.2 perseant
676 1.1.1.1.2.2 perseant #undef chk_imm
677 1.1.1.1.2.2 perseant #undef add_immx
678 1.1.1.1.2.2 perseant #undef add_fixup
679 1.1.1.1.2.2 perseant }
680 1.1.1.1.2.2 perseant
681 1.1.1.1.2.2 perseant /*
682 1.1.1.1.2.2 perseant * Given a set of operands and a matching instruction,
683 1.1.1.1.2.2 perseant * assemble it
684 1.1.1.1.2.2 perseant *
685 1.1.1.1.2.2 perseant */
686 1.1.1.1.2.2 perseant static void
687 1.1.1.1.2.2 perseant assemble_insn (const struct kvxopc * opcode, struct token_list *tok, struct kvxinsn *insn)
688 1.1.1.1.2.2 perseant {
689 1.1.1.1.2.2 perseant unsigned immx_ready = 0;
690 1.1.1.1.2.2 perseant
691 1.1.1.1.2.2 perseant memset (insn, 0, sizeof (*insn));
692 1.1.1.1.2.2 perseant insn->opdef = opcode;
693 1.1.1.1.2.2 perseant for (int i = 0; i < opcode->wordcount; i++)
694 1.1.1.1.2.2 perseant {
695 1.1.1.1.2.2 perseant insn->words[i] = opcode->codewords[i].opcode;
696 1.1.1.1.2.2 perseant insn->len += 1;
697 1.1.1.1.2.2 perseant }
698 1.1.1.1.2.2 perseant
699 1.1.1.1.2.2 perseant insn->immx0 = NOIMMX;
700 1.1.1.1.2.2 perseant insn->immx1 = NOIMMX;
701 1.1.1.1.2.2 perseant
702 1.1.1.1.2.2 perseant struct token_list *tok_ = tok;
703 1.1.1.1.2.2 perseant struct kvx_operand **format = (struct kvx_operand **) opcode->format;
704 1.1.1.1.2.2 perseant
705 1.1.1.1.2.2 perseant while (tok_)
706 1.1.1.1.2.2 perseant {
707 1.1.1.1.2.2 perseant int ret = insert_operand (insn, *format, tok_);
708 1.1.1.1.2.2 perseant immx_ready |= ret;
709 1.1.1.1.2.2 perseant while ((tok_ = tok_->next) && tok_->category == CAT_SEPARATOR);
710 1.1.1.1.2.2 perseant format++;
711 1.1.1.1.2.2 perseant }
712 1.1.1.1.2.2 perseant
713 1.1.1.1.2.2 perseant // Handle immx if insert_operand did not already take care of that
714 1.1.1.1.2.2 perseant if (!immx_ready)
715 1.1.1.1.2.2 perseant {
716 1.1.1.1.2.2 perseant for (int i = 0; i < opcode->wordcount; i++)
717 1.1.1.1.2.2 perseant {
718 1.1.1.1.2.2 perseant if (opcode->codewords[i].flags & kvxOPCODE_FLAG_IMMX0)
719 1.1.1.1.2.2 perseant {
720 1.1.1.1.2.2 perseant insn->immx0 = immxcnt;
721 1.1.1.1.2.2 perseant immxbuf[immxcnt].words[0] = insn->words[i];
722 1.1.1.1.2.2 perseant immxbuf[immxcnt].nfixups = 0;
723 1.1.1.1.2.2 perseant immxbuf[immxcnt].len = 1;
724 1.1.1.1.2.2 perseant insn->len -= 1;
725 1.1.1.1.2.2 perseant incr_immxcnt ();
726 1.1.1.1.2.2 perseant }
727 1.1.1.1.2.2 perseant if (opcode->codewords[i].flags & kvxOPCODE_FLAG_IMMX1)
728 1.1.1.1.2.2 perseant {
729 1.1.1.1.2.2 perseant insn->immx1 = immxcnt;
730 1.1.1.1.2.2 perseant immxbuf[immxcnt].words[0] = insn->words[i];
731 1.1.1.1.2.2 perseant immxbuf[immxcnt].nfixups = 0;
732 1.1.1.1.2.2 perseant immxbuf[immxcnt].len = 1;
733 1.1.1.1.2.2 perseant insn->len -= 1;
734 1.1.1.1.2.2 perseant incr_immxcnt ();
735 1.1.1.1.2.2 perseant }
736 1.1.1.1.2.2 perseant }
737 1.1.1.1.2.2 perseant }
738 1.1.1.1.2.2 perseant }
739 1.1.1.1.2.2 perseant
740 1.1.1.1.2.2 perseant /* Emit an instruction from the instruction array into the object
741 1.1.1.1.2.2 perseant * file. INSN points to an element of the instruction array. STOPFLAG
742 1.1.1.1.2.2 perseant * is true if this is the last instruction in the bundle.
743 1.1.1.1.2.2 perseant *
744 1.1.1.1.2.2 perseant * Only handles main syllables of bundle. Immediate extensions are
745 1.1.1.1.2.2 perseant * handled by insert_operand.
746 1.1.1.1.2.2 perseant */
747 1.1.1.1.2.2 perseant static void
748 1.1.1.1.2.2 perseant emit_insn (struct kvxinsn * insn, int insn_pos, int stopflag)
749 1.1.1.1.2.2 perseant {
750 1.1.1.1.2.2 perseant char *f;
751 1.1.1.1.2.2 perseant unsigned int image;
752 1.1.1.1.2.2 perseant
753 1.1.1.1.2.2 perseant /* if we are listing, attach frag to previous line. */
754 1.1.1.1.2.2 perseant if (listing)
755 1.1.1.1.2.2 perseant listing_prev_line ();
756 1.1.1.1.2.2 perseant
757 1.1.1.1.2.2 perseant /* Update text size for lane parity checking. */
758 1.1.1.1.2.2 perseant set_byte_counter (now_seg, (get_byte_counter (now_seg) + (insn->len * 4)));
759 1.1.1.1.2.2 perseant
760 1.1.1.1.2.2 perseant /* allocate space in the fragment. */
761 1.1.1.1.2.2 perseant f = frag_more (insn->len * 4);
762 1.1.1.1.2.2 perseant
763 1.1.1.1.2.2 perseant /* spit out bits. */
764 1.1.1.1.2.2 perseant for (int i = 0; i < insn->len; i++)
765 1.1.1.1.2.2 perseant {
766 1.1.1.1.2.2 perseant image = insn->words[i];
767 1.1.1.1.2.2 perseant
768 1.1.1.1.2.2 perseant /* Handle bundle parallel bit. */ ;
769 1.1.1.1.2.2 perseant if ((i == insn->len - 1) && stopflag)
770 1.1.1.1.2.2 perseant image &= ~PARALLEL_BIT;
771 1.1.1.1.2.2 perseant else
772 1.1.1.1.2.2 perseant image |= PARALLEL_BIT;
773 1.1.1.1.2.2 perseant
774 1.1.1.1.2.2 perseant /* Emit the instruction image. */
775 1.1.1.1.2.2 perseant md_number_to_chars (f + (i * 4), image, 4);
776 1.1.1.1.2.2 perseant }
777 1.1.1.1.2.2 perseant
778 1.1.1.1.2.2 perseant /* generate fixup records */
779 1.1.1.1.2.2 perseant
780 1.1.1.1.2.2 perseant for (int i = 0; i < insn->nfixups; i++)
781 1.1.1.1.2.2 perseant {
782 1.1.1.1.2.2 perseant int size, pcrel;
783 1.1.1.1.2.2 perseant reloc_howto_type *reloc_howto =
784 1.1.1.1.2.2 perseant bfd_reloc_type_lookup (stdoutput, insn->fixup[i].reloc);
785 1.1.1.1.2.2 perseant assert (reloc_howto);
786 1.1.1.1.2.2 perseant size = bfd_get_reloc_size (reloc_howto);
787 1.1.1.1.2.2 perseant pcrel = reloc_howto->pc_relative;
788 1.1.1.1.2.2 perseant
789 1.1.1.1.2.2 perseant /* In case the PCREL relocation is not for the first insn in the
790 1.1.1.1.2.2 perseant bundle, we have to offset it. The pc used by the hardware
791 1.1.1.1.2.2 perseant references a bundle and not separate insn.
792 1.1.1.1.2.2 perseant */
793 1.1.1.1.2.2 perseant assert (!(insn_pos == -1 && pcrel));
794 1.1.1.1.2.2 perseant if (pcrel && insn_pos > 0)
795 1.1.1.1.2.2 perseant insn->fixup[i].exp.X_add_number += insn_pos * 4;
796 1.1.1.1.2.2 perseant
797 1.1.1.1.2.2 perseant fixS *fixup = fix_new_exp (frag_now,
798 1.1.1.1.2.2 perseant f - frag_now->fr_literal +
799 1.1.1.1.2.2 perseant insn->fixup[i].where,
800 1.1.1.1.2.2 perseant size,
801 1.1.1.1.2.2 perseant &(insn->fixup[i].exp),
802 1.1.1.1.2.2 perseant pcrel,
803 1.1.1.1.2.2 perseant insn->fixup[i].reloc);
804 1.1.1.1.2.2 perseant /*
805 1.1.1.1.2.2 perseant * Set this bit so that large value can still be
806 1.1.1.1.2.2 perseant * handled. Without it, assembler will fail in fixup_segment
807 1.1.1.1.2.2 perseant * when it checks there is enough bits to store the value. As we
808 1.1.1.1.2.2 perseant * usually split our reloc across different words, it may think
809 1.1.1.1.2.2 perseant * that 4 bytes are not enough for large value. This simply
810 1.1.1.1.2.2 perseant * skips the tests
811 1.1.1.1.2.2 perseant */
812 1.1.1.1.2.2 perseant fixup->fx_no_overflow = 1;
813 1.1.1.1.2.2 perseant }
814 1.1.1.1.2.2 perseant }
815 1.1.1.1.2.2 perseant
816 1.1.1.1.2.2 perseant
817 1.1.1.1.2.2 perseant /* Called for any expression that can not be recognized. When the
818 1.1.1.1.2.2 perseant * function is called, `input_line_pointer' will point to the start of
819 1.1.1.1.2.2 perseant * the expression. */
820 1.1.1.1.2.2 perseant /* FIXME: Should be done by the parser */
821 1.1.1.1.2.2 perseant void
822 1.1.1.1.2.2 perseant md_operand (expressionS * e)
823 1.1.1.1.2.2 perseant {
824 1.1.1.1.2.2 perseant /* enum pseudo_type pseudo_type; */
825 1.1.1.1.2.2 perseant /* char *name = NULL; */
826 1.1.1.1.2.2 perseant size_t len;
827 1.1.1.1.2.2 perseant int ch, i;
828 1.1.1.1.2.2 perseant
829 1.1.1.1.2.2 perseant switch (*input_line_pointer)
830 1.1.1.1.2.2 perseant {
831 1.1.1.1.2.2 perseant case '@':
832 1.1.1.1.2.2 perseant /* Find what relocation pseudo-function we're dealing with. */
833 1.1.1.1.2.2 perseant /* pseudo_type = 0; */
834 1.1.1.1.2.2 perseant ch = *++input_line_pointer;
835 1.1.1.1.2.2 perseant for (i = 0; i < kvx_core_info->nb_pseudo_funcs; ++i)
836 1.1.1.1.2.2 perseant if (kvx_core_info->pseudo_funcs[i].name && kvx_core_info->pseudo_funcs[i].name[0] == ch)
837 1.1.1.1.2.2 perseant {
838 1.1.1.1.2.2 perseant len = strlen (kvx_core_info->pseudo_funcs[i].name);
839 1.1.1.1.2.2 perseant if (strncmp (kvx_core_info->pseudo_funcs[i].name + 1,
840 1.1.1.1.2.2 perseant input_line_pointer + 1, len - 1) == 0
841 1.1.1.1.2.2 perseant && !is_part_of_name (input_line_pointer[len]))
842 1.1.1.1.2.2 perseant {
843 1.1.1.1.2.2 perseant input_line_pointer += len;
844 1.1.1.1.2.2 perseant break;
845 1.1.1.1.2.2 perseant }
846 1.1.1.1.2.2 perseant }
847 1.1.1.1.2.2 perseant SKIP_WHITESPACE ();
848 1.1.1.1.2.2 perseant if (*input_line_pointer != '(')
849 1.1.1.1.2.2 perseant {
850 1.1.1.1.2.2 perseant as_bad ("Expected '('");
851 1.1.1.1.2.2 perseant goto err;
852 1.1.1.1.2.2 perseant }
853 1.1.1.1.2.2 perseant /* Skip '('. */
854 1.1.1.1.2.2 perseant ++input_line_pointer;
855 1.1.1.1.2.2 perseant if (!kvx_core_info->pseudo_funcs[i].pseudo_relocs.has_no_arg)
856 1.1.1.1.2.2 perseant expression (e);
857 1.1.1.1.2.2 perseant if (*input_line_pointer++ != ')')
858 1.1.1.1.2.2 perseant {
859 1.1.1.1.2.2 perseant as_bad ("Missing ')'");
860 1.1.1.1.2.2 perseant goto err;
861 1.1.1.1.2.2 perseant }
862 1.1.1.1.2.2 perseant if (!kvx_core_info->pseudo_funcs[i].pseudo_relocs.has_no_arg)
863 1.1.1.1.2.2 perseant {
864 1.1.1.1.2.2 perseant if (e->X_op != O_symbol)
865 1.1.1.1.2.2 perseant as_fatal ("Illegal combination of relocation functions");
866 1.1.1.1.2.2 perseant }
867 1.1.1.1.2.2 perseant /* Make sure gas doesn't get rid of local symbols that are used
868 1.1.1.1.2.2 perseant in relocs. */
869 1.1.1.1.2.2 perseant e->X_op = O_pseudo_fixup;
870 1.1.1.1.2.2 perseant e->X_op_symbol = kvx_core_info->pseudo_funcs[i].sym;
871 1.1.1.1.2.2 perseant break;
872 1.1.1.1.2.2 perseant
873 1.1.1.1.2.2 perseant default:
874 1.1.1.1.2.2 perseant break;
875 1.1.1.1.2.2 perseant }
876 1.1.1.1.2.2 perseant return;
877 1.1.1.1.2.2 perseant
878 1.1.1.1.2.2 perseant err:
879 1.1.1.1.2.2 perseant ignore_rest_of_line ();
880 1.1.1.1.2.2 perseant }
881 1.1.1.1.2.2 perseant
882 1.1.1.1.2.2 perseant /*
883 1.1.1.1.2.2 perseant * Return the Bundling type for an insn.
884 1.1.1.1.2.2 perseant */
885 1.1.1.1.2.2 perseant static int
886 1.1.1.1.2.2 perseant find_bundling (const struct kvxinsn * insn)
887 1.1.1.1.2.2 perseant {
888 1.1.1.1.2.2 perseant return insn->opdef->bundling;
889 1.1.1.1.2.2 perseant }
890 1.1.1.1.2.2 perseant
891 1.1.1.1.2.2 perseant static int
892 1.1.1.1.2.2 perseant find_reservation (const struct kvxinsn * insn)
893 1.1.1.1.2.2 perseant {
894 1.1.1.1.2.2 perseant return insn->opdef->reservation;
895 1.1.1.1.2.2 perseant }
896 1.1.1.1.2.2 perseant
897 1.1.1.1.2.2 perseant static struct kvxopc *
898 1.1.1.1.2.2 perseant assemble_tokens (struct token_list *tok_list)
899 1.1.1.1.2.2 perseant {
900 1.1.1.1.2.2 perseant assert (tok_list != NULL);
901 1.1.1.1.2.2 perseant struct token_list *toks = tok_list;
902 1.1.1.1.2.2 perseant
903 1.1.1.1.2.2 perseant /* make sure there is room in instruction buffer */
904 1.1.1.1.2.2 perseant /* Was KVXMAXBUNDLEISSUE, changed because of NOPs */
905 1.1.1.1.2.2 perseant if (insncnt >= KVXMAXBUNDLEWORDS)
906 1.1.1.1.2.2 perseant as_fatal ("[assemble_tokens]: too many instructions in bundle.");
907 1.1.1.1.2.2 perseant
908 1.1.1.1.2.2 perseant /* TODO: Merge */
909 1.1.1.1.2.2 perseant struct kvxinsn *insn;
910 1.1.1.1.2.2 perseant insn = insbuf + insncnt;
911 1.1.1.1.2.2 perseant
912 1.1.1.1.2.2 perseant /* The formats table registers the modifier into the opcode, therefore we need
913 1.1.1.1.2.2 perseant to fuse both before looking up the opcodes hashtable. */
914 1.1.1.1.2.2 perseant char *opcode = NULL;
915 1.1.1.1.2.2 perseant
916 1.1.1.1.2.2 perseant opcode = toks->tok;
917 1.1.1.1.2.2 perseant toks = toks->next;
918 1.1.1.1.2.2 perseant
919 1.1.1.1.2.2 perseant while (toks && toks->category == CAT_SEPARATOR)
920 1.1.1.1.2.2 perseant toks = toks->next;
921 1.1.1.1.2.2 perseant
922 1.1.1.1.2.2 perseant /* Find the format requested by the instruction. */
923 1.1.1.1.2.2 perseant struct kvxopc *format_tbl = str_hash_find (env.opcode_hash, opcode);
924 1.1.1.1.2.2 perseant struct kvxopc *format = NULL;
925 1.1.1.1.2.2 perseant
926 1.1.1.1.2.2 perseant struct token_list *toks_ = toks;
927 1.1.1.1.2.2 perseant
928 1.1.1.1.2.2 perseant while (!format && format_tbl && STREQ (opcode, format_tbl->as_op))
929 1.1.1.1.2.2 perseant {
930 1.1.1.1.2.2 perseant for (int i = 0 ; toks_ && format_tbl->format[i]
931 1.1.1.1.2.2 perseant && toks_->class_id == format_tbl->format[i]->type ;)
932 1.1.1.1.2.2 perseant {
933 1.1.1.1.2.2 perseant toks_ = toks_->next;
934 1.1.1.1.2.2 perseant while (toks_ && toks_->category == CAT_SEPARATOR)
935 1.1.1.1.2.2 perseant toks_ = toks_->next;
936 1.1.1.1.2.2 perseant i += 1;
937 1.1.1.1.2.2 perseant }
938 1.1.1.1.2.2 perseant
939 1.1.1.1.2.2 perseant if (!toks_)
940 1.1.1.1.2.2 perseant format = format_tbl;
941 1.1.1.1.2.2 perseant else
942 1.1.1.1.2.2 perseant {
943 1.1.1.1.2.2 perseant toks_ = toks;
944 1.1.1.1.2.2 perseant format_tbl++;
945 1.1.1.1.2.2 perseant }
946 1.1.1.1.2.2 perseant }
947 1.1.1.1.2.2 perseant
948 1.1.1.1.2.2 perseant assert (format != NULL);
949 1.1.1.1.2.2 perseant
950 1.1.1.1.2.2 perseant assemble_insn (format, toks, insn);
951 1.1.1.1.2.2 perseant insncnt++;
952 1.1.1.1.2.2 perseant
953 1.1.1.1.2.2 perseant return NULL;
954 1.1.1.1.2.2 perseant }
955 1.1.1.1.2.2 perseant
956 1.1.1.1.2.2 perseant /*
957 1.1.1.1.2.2 perseant * Write in buf at most buf_size.
958 1.1.1.1.2.2 perseant * Returns the number of writen characters.
959 1.1.1.1.2.2 perseant */
960 1.1.1.1.2.2 perseant static int ATTRIBUTE_UNUSED
961 1.1.1.1.2.2 perseant insn_syntax (struct kvxopc * op, char *buf, int buf_size)
962 1.1.1.1.2.2 perseant {
963 1.1.1.1.2.2 perseant int chars = snprintf (buf, buf_size, "%s ", op->as_op);
964 1.1.1.1.2.2 perseant const char *fmtp = op->fmtstring;
965 1.1.1.1.2.2 perseant char ch = 0;
966 1.1.1.1.2.2 perseant
967 1.1.1.1.2.2 perseant for (int i = 0; op->format[i]; i++)
968 1.1.1.1.2.2 perseant {
969 1.1.1.1.2.2 perseant int type = op->format[i]->type;
970 1.1.1.1.2.2 perseant const char *type_name = TOKEN_NAME (type);
971 1.1.1.1.2.2 perseant int offset = 0;
972 1.1.1.1.2.2 perseant
973 1.1.1.1.2.2 perseant for (int j = 0 ; type_name[j] ; ++j)
974 1.1.1.1.2.2 perseant if (type_name[j] == '_')
975 1.1.1.1.2.2 perseant offset = j + 1;
976 1.1.1.1.2.2 perseant
977 1.1.1.1.2.2 perseant /* Print characters in the format string up to the following * % or nul. */
978 1.1.1.1.2.2 perseant while ((chars < buf_size) && (ch = *fmtp) && ch != '%')
979 1.1.1.1.2.2 perseant {
980 1.1.1.1.2.2 perseant buf[chars++] = ch;
981 1.1.1.1.2.2 perseant fmtp++;
982 1.1.1.1.2.2 perseant }
983 1.1.1.1.2.2 perseant
984 1.1.1.1.2.2 perseant /* Skip past %s */
985 1.1.1.1.2.2 perseant if (ch == '%')
986 1.1.1.1.2.2 perseant {
987 1.1.1.1.2.2 perseant ch = *fmtp++;
988 1.1.1.1.2.2 perseant fmtp++;
989 1.1.1.1.2.2 perseant }
990 1.1.1.1.2.2 perseant
991 1.1.1.1.2.2 perseant chars += snprintf (&buf[chars], buf_size - chars, "%s", type_name + offset);
992 1.1.1.1.2.2 perseant }
993 1.1.1.1.2.2 perseant
994 1.1.1.1.2.2 perseant /* Print trailing characters in the format string, if any */
995 1.1.1.1.2.2 perseant while ((chars < buf_size) && (ch = *fmtp))
996 1.1.1.1.2.2 perseant {
997 1.1.1.1.2.2 perseant buf[chars++] = ch;
998 1.1.1.1.2.2 perseant fmtp++;
999 1.1.1.1.2.2 perseant }
1000 1.1.1.1.2.2 perseant
1001 1.1.1.1.2.2 perseant if (chars < buf_size)
1002 1.1.1.1.2.2 perseant buf[chars++] = '\0';
1003 1.1.1.1.2.2 perseant else
1004 1.1.1.1.2.2 perseant buf[buf_size - 1] = '\0';
1005 1.1.1.1.2.2 perseant
1006 1.1.1.1.2.2 perseant return chars;
1007 1.1.1.1.2.2 perseant }
1008 1.1.1.1.2.2 perseant
1009 1.1.1.1.2.2 perseant #define ASM_CHARS_MAX (71)
1010 1.1.1.1.2.2 perseant
1011 1.1.1.1.2.2 perseant static void
1012 1.1.1.1.2.2 perseant kvx_print_insn (struct kvxopc * op ATTRIBUTE_UNUSED)
1013 1.1.1.1.2.2 perseant {
1014 1.1.1.1.2.2 perseant char asm_str[ASM_CHARS_MAX];
1015 1.1.1.1.2.2 perseant int chars = insn_syntax (op, asm_str, ASM_CHARS_MAX);
1016 1.1.1.1.2.2 perseant const char *insn_type = "UNKNOWN";
1017 1.1.1.1.2.2 perseant const char *insn_mode = "";
1018 1.1.1.1.2.2 perseant
1019 1.1.1.1.2.2 perseant for (int i = chars - 1; i < ASM_CHARS_MAX - 1; i++)
1020 1.1.1.1.2.2 perseant asm_str[i] = '-';
1021 1.1.1.1.2.2 perseant
1022 1.1.1.1.2.2 perseant /* This is a hack which works because the Bundling is the same for all cores
1023 1.1.1.1.2.2 perseant for now. */
1024 1.1.1.1.2.2 perseant switch ((int) op->bundling)
1025 1.1.1.1.2.2 perseant {
1026 1.1.1.1.2.2 perseant case Bundling_kv3_v1_ALL:
1027 1.1.1.1.2.2 perseant insn_type = "ALL ";
1028 1.1.1.1.2.2 perseant break;
1029 1.1.1.1.2.2 perseant case Bundling_kv3_v1_BCU:
1030 1.1.1.1.2.2 perseant insn_type = "BCU ";
1031 1.1.1.1.2.2 perseant break;
1032 1.1.1.1.2.2 perseant case Bundling_kv3_v1_TCA:
1033 1.1.1.1.2.2 perseant insn_type = "TCA ";
1034 1.1.1.1.2.2 perseant break;
1035 1.1.1.1.2.2 perseant case Bundling_kv3_v1_FULL:
1036 1.1.1.1.2.2 perseant case Bundling_kv3_v1_FULL_X:
1037 1.1.1.1.2.2 perseant case Bundling_kv3_v1_FULL_Y:
1038 1.1.1.1.2.2 perseant insn_type = "FULL ";
1039 1.1.1.1.2.2 perseant break;
1040 1.1.1.1.2.2 perseant case Bundling_kv3_v1_LITE:
1041 1.1.1.1.2.2 perseant case Bundling_kv3_v1_LITE_X:
1042 1.1.1.1.2.2 perseant case Bundling_kv3_v1_LITE_Y:
1043 1.1.1.1.2.2 perseant insn_type = "LITE ";
1044 1.1.1.1.2.2 perseant break;
1045 1.1.1.1.2.2 perseant case Bundling_kv3_v1_TINY:
1046 1.1.1.1.2.2 perseant case Bundling_kv3_v1_TINY_X:
1047 1.1.1.1.2.2 perseant case Bundling_kv3_v1_TINY_Y:
1048 1.1.1.1.2.2 perseant insn_type = "TINY ";
1049 1.1.1.1.2.2 perseant break;
1050 1.1.1.1.2.2 perseant case Bundling_kv3_v1_MAU:
1051 1.1.1.1.2.2 perseant case Bundling_kv3_v1_MAU_X:
1052 1.1.1.1.2.2 perseant case Bundling_kv3_v1_MAU_Y:
1053 1.1.1.1.2.2 perseant insn_type = "MAU ";
1054 1.1.1.1.2.2 perseant break;
1055 1.1.1.1.2.2 perseant case Bundling_kv3_v1_LSU:
1056 1.1.1.1.2.2 perseant case Bundling_kv3_v1_LSU_X:
1057 1.1.1.1.2.2 perseant case Bundling_kv3_v1_LSU_Y:
1058 1.1.1.1.2.2 perseant insn_type = "LSU ";
1059 1.1.1.1.2.2 perseant break;
1060 1.1.1.1.2.2 perseant case Bundling_kv3_v1_NOP:
1061 1.1.1.1.2.2 perseant insn_type = "NOP ";
1062 1.1.1.1.2.2 perseant break;
1063 1.1.1.1.2.2 perseant default:
1064 1.1.1.1.2.2 perseant as_fatal ("Unhandled Bundling class %d", op->bundling);
1065 1.1.1.1.2.2 perseant }
1066 1.1.1.1.2.2 perseant
1067 1.1.1.1.2.2 perseant if (op->codewords[0].flags & kvxOPCODE_FLAG_MODE64
1068 1.1.1.1.2.2 perseant && op->codewords[0].flags & kvxOPCODE_FLAG_MODE32)
1069 1.1.1.1.2.2 perseant insn_mode = "32 and 64";
1070 1.1.1.1.2.2 perseant else if (op->codewords[0].flags & kvxOPCODE_FLAG_MODE64)
1071 1.1.1.1.2.2 perseant insn_mode = "64";
1072 1.1.1.1.2.2 perseant else if (op->codewords[0].flags & kvxOPCODE_FLAG_MODE32)
1073 1.1.1.1.2.2 perseant insn_mode = "32";
1074 1.1.1.1.2.2 perseant else
1075 1.1.1.1.2.2 perseant as_fatal ("Unknown instruction mode.");
1076 1.1.1.1.2.2 perseant
1077 1.1.1.1.2.2 perseant printf ("%s | syllables: %d | type: %s | mode: %s bits\n", asm_str,
1078 1.1.1.1.2.2 perseant op->wordcount, insn_type, insn_mode);
1079 1.1.1.1.2.2 perseant }
1080 1.1.1.1.2.2 perseant
1081 1.1.1.1.2.2 perseant /* Comparison function compatible with qsort. This is used to sort the issues
1082 1.1.1.1.2.2 perseant into the right order. */
1083 1.1.1.1.2.2 perseant static int
1084 1.1.1.1.2.2 perseant kvxinsn_compare (const void *a, const void *b)
1085 1.1.1.1.2.2 perseant {
1086 1.1.1.1.2.2 perseant struct kvxinsn *kvxinsn_a = *(struct kvxinsn **) a;
1087 1.1.1.1.2.2 perseant struct kvxinsn *kvxinsn_b = *(struct kvxinsn **) b;
1088 1.1.1.1.2.2 perseant int bundling_a = find_bundling (kvxinsn_a);
1089 1.1.1.1.2.2 perseant int bundling_b = find_bundling (kvxinsn_b);
1090 1.1.1.1.2.2 perseant int order_a = kvxinsn_a->order;
1091 1.1.1.1.2.2 perseant int order_b = kvxinsn_b->order;
1092 1.1.1.1.2.2 perseant if (bundling_a != bundling_b)
1093 1.1.1.1.2.2 perseant return (bundling_b < bundling_a) - (bundling_a < bundling_b);
1094 1.1.1.1.2.2 perseant return (order_b < order_a) - (order_a < order_b);
1095 1.1.1.1.2.2 perseant }
1096 1.1.1.1.2.2 perseant
1097 1.1.1.1.2.2 perseant static void
1098 1.1.1.1.2.2 perseant kvx_reorder_bundle (struct kvxinsn *bundle_insn[], int bundle_insncnt)
1099 1.1.1.1.2.2 perseant {
1100 1.1.1.1.2.2 perseant enum
1101 1.1.1.1.2.2 perseant { EXU_BCU, EXU_TCA, EXU_ALU0, EXU_ALU1, EXU_MAU, EXU_LSU, EXU__ };
1102 1.1.1.1.2.2 perseant struct kvxinsn *issued[EXU__];
1103 1.1.1.1.2.2 perseant int tag, exu;
1104 1.1.1.1.2.2 perseant
1105 1.1.1.1.2.2 perseant memset (issued, 0, sizeof (issued));
1106 1.1.1.1.2.2 perseant for (int i = 0; i < bundle_insncnt; i++)
1107 1.1.1.1.2.2 perseant {
1108 1.1.1.1.2.2 perseant struct kvxinsn *kvxinsn = bundle_insn[i];
1109 1.1.1.1.2.2 perseant tag = -1, exu = -1;
1110 1.1.1.1.2.2 perseant /* This is a hack. It works because all the Bundling are the same for all
1111 1.1.1.1.2.2 perseant cores for now. */
1112 1.1.1.1.2.2 perseant switch ((int) find_bundling (kvxinsn))
1113 1.1.1.1.2.2 perseant {
1114 1.1.1.1.2.2 perseant case Bundling_kv3_v1_ALL:
1115 1.1.1.1.2.2 perseant if (bundle_insncnt > 1)
1116 1.1.1.1.2.2 perseant as_fatal ("Too many ops in a single op bundle");
1117 1.1.1.1.2.2 perseant issued[0] = kvxinsn;
1118 1.1.1.1.2.2 perseant break;
1119 1.1.1.1.2.2 perseant case Bundling_kv3_v1_BCU:
1120 1.1.1.1.2.2 perseant if (!issued[EXU_BCU])
1121 1.1.1.1.2.2 perseant issued[EXU_BCU] = kvxinsn;
1122 1.1.1.1.2.2 perseant else
1123 1.1.1.1.2.2 perseant as_fatal ("More than one BCU instruction in bundle");
1124 1.1.1.1.2.2 perseant break;
1125 1.1.1.1.2.2 perseant case Bundling_kv3_v1_TCA:
1126 1.1.1.1.2.2 perseant if (!issued[EXU_TCA])
1127 1.1.1.1.2.2 perseant issued[EXU_TCA] = kvxinsn;
1128 1.1.1.1.2.2 perseant else
1129 1.1.1.1.2.2 perseant as_fatal ("More than one TCA instruction in bundle");
1130 1.1.1.1.2.2 perseant break;
1131 1.1.1.1.2.2 perseant case Bundling_kv3_v1_FULL:
1132 1.1.1.1.2.2 perseant case Bundling_kv3_v1_FULL_X:
1133 1.1.1.1.2.2 perseant case Bundling_kv3_v1_FULL_Y:
1134 1.1.1.1.2.2 perseant if (!issued[EXU_ALU0])
1135 1.1.1.1.2.2 perseant {
1136 1.1.1.1.2.2 perseant issued[EXU_ALU0] = kvxinsn;
1137 1.1.1.1.2.2 perseant tag = Modifier_kv3_v1_exunum_ALU0;
1138 1.1.1.1.2.2 perseant exu = EXU_ALU0;
1139 1.1.1.1.2.2 perseant }
1140 1.1.1.1.2.2 perseant else
1141 1.1.1.1.2.2 perseant as_fatal ("More than one ALU FULL instruction in bundle");
1142 1.1.1.1.2.2 perseant break;
1143 1.1.1.1.2.2 perseant case Bundling_kv3_v1_LITE:
1144 1.1.1.1.2.2 perseant case Bundling_kv3_v1_LITE_X:
1145 1.1.1.1.2.2 perseant case Bundling_kv3_v1_LITE_Y:
1146 1.1.1.1.2.2 perseant if (!issued[EXU_ALU0])
1147 1.1.1.1.2.2 perseant {
1148 1.1.1.1.2.2 perseant issued[EXU_ALU0] = kvxinsn;
1149 1.1.1.1.2.2 perseant tag = Modifier_kv3_v1_exunum_ALU0;
1150 1.1.1.1.2.2 perseant exu = EXU_ALU0;
1151 1.1.1.1.2.2 perseant }
1152 1.1.1.1.2.2 perseant else if (!issued[EXU_ALU1])
1153 1.1.1.1.2.2 perseant {
1154 1.1.1.1.2.2 perseant issued[EXU_ALU1] = kvxinsn;
1155 1.1.1.1.2.2 perseant tag = Modifier_kv3_v1_exunum_ALU1;
1156 1.1.1.1.2.2 perseant exu = EXU_ALU1;
1157 1.1.1.1.2.2 perseant }
1158 1.1.1.1.2.2 perseant else
1159 1.1.1.1.2.2 perseant as_fatal ("Too many ALU FULL or LITE instructions in bundle");
1160 1.1.1.1.2.2 perseant break;
1161 1.1.1.1.2.2 perseant case Bundling_kv3_v1_MAU:
1162 1.1.1.1.2.2 perseant case Bundling_kv3_v1_MAU_X:
1163 1.1.1.1.2.2 perseant case Bundling_kv3_v1_MAU_Y:
1164 1.1.1.1.2.2 perseant if (!issued[EXU_MAU])
1165 1.1.1.1.2.2 perseant {
1166 1.1.1.1.2.2 perseant issued[EXU_MAU] = kvxinsn;
1167 1.1.1.1.2.2 perseant tag = Modifier_kv3_v1_exunum_MAU;
1168 1.1.1.1.2.2 perseant exu = EXU_MAU;
1169 1.1.1.1.2.2 perseant }
1170 1.1.1.1.2.2 perseant else
1171 1.1.1.1.2.2 perseant as_fatal ("More than one MAU instruction in bundle");
1172 1.1.1.1.2.2 perseant break;
1173 1.1.1.1.2.2 perseant case Bundling_kv3_v1_LSU:
1174 1.1.1.1.2.2 perseant case Bundling_kv3_v1_LSU_X:
1175 1.1.1.1.2.2 perseant case Bundling_kv3_v1_LSU_Y:
1176 1.1.1.1.2.2 perseant if (!issued[EXU_LSU])
1177 1.1.1.1.2.2 perseant {
1178 1.1.1.1.2.2 perseant issued[EXU_LSU] = kvxinsn;
1179 1.1.1.1.2.2 perseant tag = Modifier_kv3_v1_exunum_LSU;
1180 1.1.1.1.2.2 perseant exu = EXU_LSU;
1181 1.1.1.1.2.2 perseant }
1182 1.1.1.1.2.2 perseant else
1183 1.1.1.1.2.2 perseant as_fatal ("More than one LSU instruction in bundle");
1184 1.1.1.1.2.2 perseant break;
1185 1.1.1.1.2.2 perseant case Bundling_kv3_v1_TINY:
1186 1.1.1.1.2.2 perseant case Bundling_kv3_v1_TINY_X:
1187 1.1.1.1.2.2 perseant case Bundling_kv3_v1_TINY_Y:
1188 1.1.1.1.2.2 perseant case Bundling_kv3_v1_NOP:
1189 1.1.1.1.2.2 perseant if (!issued[EXU_ALU0])
1190 1.1.1.1.2.2 perseant {
1191 1.1.1.1.2.2 perseant issued[EXU_ALU0] = kvxinsn;
1192 1.1.1.1.2.2 perseant tag = Modifier_kv3_v1_exunum_ALU0;
1193 1.1.1.1.2.2 perseant exu = EXU_ALU0;
1194 1.1.1.1.2.2 perseant }
1195 1.1.1.1.2.2 perseant else if (!issued[EXU_ALU1])
1196 1.1.1.1.2.2 perseant {
1197 1.1.1.1.2.2 perseant issued[EXU_ALU1] = kvxinsn;
1198 1.1.1.1.2.2 perseant tag = Modifier_kv3_v1_exunum_ALU1;
1199 1.1.1.1.2.2 perseant exu = EXU_ALU1;
1200 1.1.1.1.2.2 perseant }
1201 1.1.1.1.2.2 perseant else if (!issued[EXU_MAU])
1202 1.1.1.1.2.2 perseant {
1203 1.1.1.1.2.2 perseant issued[EXU_MAU] = kvxinsn;
1204 1.1.1.1.2.2 perseant tag = Modifier_kv3_v1_exunum_MAU;
1205 1.1.1.1.2.2 perseant exu = EXU_MAU;
1206 1.1.1.1.2.2 perseant }
1207 1.1.1.1.2.2 perseant else if (!issued[EXU_LSU])
1208 1.1.1.1.2.2 perseant {
1209 1.1.1.1.2.2 perseant issued[EXU_LSU] = kvxinsn;
1210 1.1.1.1.2.2 perseant tag = Modifier_kv3_v1_exunum_LSU;
1211 1.1.1.1.2.2 perseant exu = EXU_LSU;
1212 1.1.1.1.2.2 perseant }
1213 1.1.1.1.2.2 perseant else
1214 1.1.1.1.2.2 perseant as_fatal ("Too many ALU instructions in bundle");
1215 1.1.1.1.2.2 perseant break;
1216 1.1.1.1.2.2 perseant default:
1217 1.1.1.1.2.2 perseant as_fatal ("Unhandled Bundling class %d", find_bundling (kvxinsn));
1218 1.1.1.1.2.2 perseant }
1219 1.1.1.1.2.2 perseant if (tag >= 0)
1220 1.1.1.1.2.2 perseant {
1221 1.1.1.1.2.2 perseant if (issued[exu]->immx0 != NOIMMX)
1222 1.1.1.1.2.2 perseant immxbuf[issued[exu]->immx0].words[0] |= (tag << 27);
1223 1.1.1.1.2.2 perseant if (issued[exu]->immx1 != NOIMMX)
1224 1.1.1.1.2.2 perseant immxbuf[issued[exu]->immx1].words[0] |= (tag << 27);
1225 1.1.1.1.2.2 perseant }
1226 1.1.1.1.2.2 perseant }
1227 1.1.1.1.2.2 perseant
1228 1.1.1.1.2.2 perseant int i;
1229 1.1.1.1.2.2 perseant for (i = 0, exu = 0; exu < EXU__; exu++)
1230 1.1.1.1.2.2 perseant {
1231 1.1.1.1.2.2 perseant if (issued[exu])
1232 1.1.1.1.2.2 perseant bundle_insn[i++] = issued[exu];
1233 1.1.1.1.2.2 perseant }
1234 1.1.1.1.2.2 perseant if (i != bundle_insncnt)
1235 1.1.1.1.2.2 perseant as_fatal ("Mismatch between bundle and issued instructions");
1236 1.1.1.1.2.2 perseant }
1237 1.1.1.1.2.2 perseant
1238 1.1.1.1.2.2 perseant static void
1239 1.1.1.1.2.2 perseant kvx_check_resource_usage (struct kvxinsn **bundle_insn, int bundle_insncnt)
1240 1.1.1.1.2.2 perseant {
1241 1.1.1.1.2.2 perseant const int reservation_table_len =
1242 1.1.1.1.2.2 perseant (kvx_core_info->reservation_table_lines * kvx_core_info->resource_max);
1243 1.1.1.1.2.2 perseant const int *resources = kvx_core_info->resources;
1244 1.1.1.1.2.2 perseant int *resources_used =
1245 1.1.1.1.2.2 perseant malloc (reservation_table_len * sizeof (int));
1246 1.1.1.1.2.2 perseant memset (resources_used, 0, reservation_table_len * sizeof (int));
1247 1.1.1.1.2.2 perseant
1248 1.1.1.1.2.2 perseant for (int i = 0; i < bundle_insncnt; i++)
1249 1.1.1.1.2.2 perseant {
1250 1.1.1.1.2.2 perseant int insn_reservation = find_reservation (bundle_insn[i]);
1251 1.1.1.1.2.2 perseant int reservation = insn_reservation & 0xff;
1252 1.1.1.1.2.2 perseant const int *reservation_table = kvx_core_info->reservation_table_table[reservation];
1253 1.1.1.1.2.2 perseant for (int j = 0; j < reservation_table_len; j++)
1254 1.1.1.1.2.2 perseant resources_used[j] += reservation_table[j];
1255 1.1.1.1.2.2 perseant }
1256 1.1.1.1.2.2 perseant
1257 1.1.1.1.2.2 perseant for (int i = 0; i < kvx_core_info->reservation_table_lines; i++)
1258 1.1.1.1.2.2 perseant {
1259 1.1.1.1.2.2 perseant for (int j = 0; j < kvx_core_info->resource_max; j++)
1260 1.1.1.1.2.2 perseant if (resources_used[(i * kvx_core_info->resource_max) + j] > resources[j])
1261 1.1.1.1.2.2 perseant {
1262 1.1.1.1.2.2 perseant int v = resources_used[(i * kvx_core_info->resource_max) + j];
1263 1.1.1.1.2.2 perseant free (resources_used);
1264 1.1.1.1.2.2 perseant as_fatal ("Resource %s over-used in bundle: %d used, %d available",
1265 1.1.1.1.2.2 perseant kvx_core_info->resource_names[j], v, resources[j]);
1266 1.1.1.1.2.2 perseant }
1267 1.1.1.1.2.2 perseant }
1268 1.1.1.1.2.2 perseant free (resources_used);
1269 1.1.1.1.2.2 perseant }
1270 1.1.1.1.2.2 perseant
1271 1.1.1.1.2.2 perseant /*
1272 1.1.1.1.2.2 perseant * Called by core to assemble a single line
1273 1.1.1.1.2.2 perseant */
1274 1.1.1.1.2.2 perseant void
1275 1.1.1.1.2.2 perseant md_assemble (char *line)
1276 1.1.1.1.2.2 perseant {
1277 1.1.1.1.2.2 perseant char *line_cursor = line;
1278 1.1.1.1.2.2 perseant
1279 1.1.1.1.2.2 perseant if (get_byte_counter (now_seg) & 3)
1280 1.1.1.1.2.2 perseant as_fatal ("code segment not word aligned in md_assemble");
1281 1.1.1.1.2.2 perseant
1282 1.1.1.1.2.2 perseant while (line_cursor && line_cursor[0] && (line_cursor[0] == ' '))
1283 1.1.1.1.2.2 perseant line_cursor++;
1284 1.1.1.1.2.2 perseant
1285 1.1.1.1.2.2 perseant /* ;; was converted to "be" by line hook */
1286 1.1.1.1.2.2 perseant /* here we look for the bundle end */
1287 1.1.1.1.2.2 perseant /* and actually output any instructions in bundle */
1288 1.1.1.1.2.2 perseant /* also we need to implement the stop bit */
1289 1.1.1.1.2.2 perseant /* check for bundle end */
1290 1.1.1.1.2.2 perseant if (strncmp (line_cursor, "be", 2) == 0)
1291 1.1.1.1.2.2 perseant {
1292 1.1.1.1.2.2 perseant inside_bundle = 0;
1293 1.1.1.1.2.2 perseant //int sec_align = bfd_get_section_alignment(stdoutput, now_seg);
1294 1.1.1.1.2.2 perseant /* Was KVXMAXBUNDLEISSUE, changed because of NOPs */
1295 1.1.1.1.2.2 perseant struct kvxinsn *bundle_insn[KVXMAXBUNDLEWORDS];
1296 1.1.1.1.2.2 perseant int bundle_insncnt = 0;
1297 1.1.1.1.2.2 perseant int syllables = 0;
1298 1.1.1.1.2.2 perseant int entry;
1299 1.1.1.1.2.2 perseant
1300 1.1.1.1.2.2 perseant #ifdef OBJ_ELF
1301 1.1.1.1.2.2 perseant /* Emit Dwarf debug line information */
1302 1.1.1.1.2.2 perseant dwarf2_emit_insn (0);
1303 1.1.1.1.2.2 perseant #endif
1304 1.1.1.1.2.2 perseant for (int j = 0; j < insncnt; j++)
1305 1.1.1.1.2.2 perseant {
1306 1.1.1.1.2.2 perseant insbuf[j].order = j;
1307 1.1.1.1.2.2 perseant bundle_insn[bundle_insncnt++] = &insbuf[j];
1308 1.1.1.1.2.2 perseant syllables += insbuf[j].len;
1309 1.1.1.1.2.2 perseant }
1310 1.1.1.1.2.2 perseant
1311 1.1.1.1.2.2 perseant if (syllables + immxcnt > KVXMAXBUNDLEWORDS)
1312 1.1.1.1.2.2 perseant as_fatal ("Bundle has too many syllables : %d instead of %d",
1313 1.1.1.1.2.2 perseant syllables + immxcnt, KVXMAXBUNDLEWORDS);
1314 1.1.1.1.2.2 perseant
1315 1.1.1.1.2.2 perseant if (env.opts.check_resource_usage)
1316 1.1.1.1.2.2 perseant kvx_check_resource_usage (bundle_insn, bundle_insncnt);
1317 1.1.1.1.2.2 perseant
1318 1.1.1.1.2.2 perseant /* Reorder and check the bundle. */
1319 1.1.1.1.2.2 perseant if (!env.opts.generate_illegal_code)
1320 1.1.1.1.2.2 perseant {
1321 1.1.1.1.2.2 perseant /* Sort the bundle_insn in order of bundling. */
1322 1.1.1.1.2.2 perseant qsort (bundle_insn, bundle_insncnt, sizeof (struct kvxinsn *), kvxinsn_compare);
1323 1.1.1.1.2.2 perseant
1324 1.1.1.1.2.2 perseant kvx_reorder_bundle (bundle_insn, bundle_insncnt);
1325 1.1.1.1.2.2 perseant }
1326 1.1.1.1.2.2 perseant
1327 1.1.1.1.2.2 perseant /* The ordering of the insns has been set correctly in bundle_insn. */
1328 1.1.1.1.2.2 perseant for (int i = 0; i < bundle_insncnt; i++)
1329 1.1.1.1.2.2 perseant {
1330 1.1.1.1.2.2 perseant emit_insn (bundle_insn[i], i, (i == bundle_insncnt + immxcnt - 1));
1331 1.1.1.1.2.2 perseant bundle_insn[i]->written = 1;
1332 1.1.1.1.2.2 perseant }
1333 1.1.1.1.2.2 perseant
1334 1.1.1.1.2.2 perseant // Emit immx, ordering them by EXU tags, 0 to 3
1335 1.1.1.1.2.2 perseant entry = 0;
1336 1.1.1.1.2.2 perseant for (int tag = 0; tag < 4; tag++)
1337 1.1.1.1.2.2 perseant {
1338 1.1.1.1.2.2 perseant for (int j = 0; j < immxcnt; j++)
1339 1.1.1.1.2.2 perseant {
1340 1.1.1.1.2.2 perseant #define kv3_exunum2_fld(x) (int)(((unsigned int)(x) >> 27) & 0x3)
1341 1.1.1.1.2.2 perseant if (kv3_exunum2_fld (immxbuf[j].words[0]) == tag)
1342 1.1.1.1.2.2 perseant {
1343 1.1.1.1.2.2 perseant assert (immxbuf[j].written == 0);
1344 1.1.1.1.2.2 perseant int insn_pos = bundle_insncnt + entry;
1345 1.1.1.1.2.2 perseant emit_insn (&(immxbuf[j]), insn_pos, entry == immxcnt - 1);
1346 1.1.1.1.2.2 perseant immxbuf[j].written = 1;
1347 1.1.1.1.2.2 perseant entry++;
1348 1.1.1.1.2.2 perseant }
1349 1.1.1.1.2.2 perseant #undef kv3_exunum2_fld
1350 1.1.1.1.2.2 perseant }
1351 1.1.1.1.2.2 perseant }
1352 1.1.1.1.2.2 perseant if (entry != immxcnt)
1353 1.1.1.1.2.2 perseant as_fatal ("%d IMMX produced, only %d emitted.", immxcnt, entry);
1354 1.1.1.1.2.2 perseant
1355 1.1.1.1.2.2 perseant /* The debug label that appear in the middle of bundles
1356 1.1.1.1.2.2 perseant had better appear to be attached to the next
1357 1.1.1.1.2.2 perseant bundle. This is because usually these labels point to
1358 1.1.1.1.2.2 perseant the first instruction where some condition is met. If
1359 1.1.1.1.2.2 perseant the label isn't handled this way it will be attached to
1360 1.1.1.1.2.2 perseant the current bundle which is wrong as the corresponding
1361 1.1.1.1.2.2 perseant instruction wasn't executed yet. */
1362 1.1.1.1.2.2 perseant while (label_fixes)
1363 1.1.1.1.2.2 perseant {
1364 1.1.1.1.2.2 perseant struct label_fix *fix = label_fixes;
1365 1.1.1.1.2.2 perseant
1366 1.1.1.1.2.2 perseant label_fixes = fix->next;
1367 1.1.1.1.2.2 perseant symbol_set_value_now (fix->sym);
1368 1.1.1.1.2.2 perseant free (fix);
1369 1.1.1.1.2.2 perseant }
1370 1.1.1.1.2.2 perseant
1371 1.1.1.1.2.2 perseant insncnt = 0;
1372 1.1.1.1.2.2 perseant immxcnt = 0;
1373 1.1.1.1.2.2 perseant memset (immxbuf, 0, sizeof (immxbuf));
1374 1.1.1.1.2.2 perseant
1375 1.1.1.1.2.2 perseant return;
1376 1.1.1.1.2.2 perseant }
1377 1.1.1.1.2.2 perseant
1378 1.1.1.1.2.2 perseant char *buf = NULL;
1379 1.1.1.1.2.2 perseant sscanf (line_cursor, "%m[^\n]", &buf);
1380 1.1.1.1.2.2 perseant struct token_s my_tok = { .insn = buf, .begin = 0, .end = 0, .class_id = -1 , .val = 0 };
1381 1.1.1.1.2.2 perseant struct token_list *tok_lst = parse (my_tok);
1382 1.1.1.1.2.2 perseant free (buf);
1383 1.1.1.1.2.2 perseant
1384 1.1.1.1.2.2 perseant if (!tok_lst)
1385 1.1.1.1.2.2 perseant return;
1386 1.1.1.1.2.2 perseant
1387 1.1.1.1.2.2 perseant /* Skip opcode */
1388 1.1.1.1.2.2 perseant line_cursor += strlen (tok_lst->tok);
1389 1.1.1.1.2.2 perseant
1390 1.1.1.1.2.2 perseant assembling_insn = true;
1391 1.1.1.1.2.2 perseant
1392 1.1.1.1.2.2 perseant inside_bundle = 1;
1393 1.1.1.1.2.2 perseant assemble_tokens (tok_lst);
1394 1.1.1.1.2.2 perseant free_token_list (tok_lst);
1395 1.1.1.1.2.2 perseant assembling_insn = false;
1396 1.1.1.1.2.2 perseant }
1397 1.1.1.1.2.2 perseant
1398 1.1.1.1.2.2 perseant static void
1399 1.1.1.1.2.2 perseant kvx_set_cpu (void)
1400 1.1.1.1.2.2 perseant {
1401 1.1.1.1.2.2 perseant if (!kvx_core_info)
1402 1.1.1.1.2.2 perseant kvx_core_info = &kvx_kv3_v1_core_info;
1403 1.1.1.1.2.2 perseant
1404 1.1.1.1.2.2 perseant if (!kvx_registers)
1405 1.1.1.1.2.2 perseant kvx_registers = kvx_kv3_v1_registers;
1406 1.1.1.1.2.2 perseant
1407 1.1.1.1.2.2 perseant if (!kvx_regfiles)
1408 1.1.1.1.2.2 perseant kvx_regfiles = kvx_kv3_v1_regfiles;
1409 1.1.1.1.2.2 perseant
1410 1.1.1.1.2.2 perseant if (!kvx_modifiers)
1411 1.1.1.1.2.2 perseant kvx_modifiers = kvx_kv3_v1_modifiers;
1412 1.1.1.1.2.2 perseant
1413 1.1.1.1.2.2 perseant if (env.params.core == -1)
1414 1.1.1.1.2.2 perseant env.params.core = kvx_core_info->elf_core;
1415 1.1.1.1.2.2 perseant
1416 1.1.1.1.2.2 perseant int kvx_bfd_mach;
1417 1.1.1.1.2.2 perseant print_insn = kvx_print_insn;
1418 1.1.1.1.2.2 perseant
1419 1.1.1.1.2.2 perseant switch (kvx_core_info->elf_core)
1420 1.1.1.1.2.2 perseant {
1421 1.1.1.1.2.2 perseant case ELF_KVX_CORE_KV3_1:
1422 1.1.1.1.2.2 perseant kvx_bfd_mach = env.params.arch_size == 32 ? bfd_mach_kv3_1 : bfd_mach_kv3_1_64;
1423 1.1.1.1.2.2 perseant setup (ELF_KVX_CORE_KV3_1);
1424 1.1.1.1.2.2 perseant break;
1425 1.1.1.1.2.2 perseant case ELF_KVX_CORE_KV3_2:
1426 1.1.1.1.2.2 perseant kvx_bfd_mach = env.params.arch_size == 32 ? bfd_mach_kv3_2 : bfd_mach_kv3_2_64;
1427 1.1.1.1.2.2 perseant setup (ELF_KVX_CORE_KV3_2);
1428 1.1.1.1.2.2 perseant break;
1429 1.1.1.1.2.2 perseant case ELF_KVX_CORE_KV4_1:
1430 1.1.1.1.2.2 perseant kvx_bfd_mach = env.params.arch_size == 32 ? bfd_mach_kv4_1 : bfd_mach_kv4_1_64;
1431 1.1.1.1.2.2 perseant setup (ELF_KVX_CORE_KV4_1);
1432 1.1.1.1.2.2 perseant break;
1433 1.1.1.1.2.2 perseant default:
1434 1.1.1.1.2.2 perseant as_fatal ("Unknown elf core: 0x%x", kvx_core_info->elf_core);
1435 1.1.1.1.2.2 perseant }
1436 1.1.1.1.2.2 perseant
1437 1.1.1.1.2.2 perseant if (!bfd_set_arch_mach (stdoutput, TARGET_ARCH, kvx_bfd_mach))
1438 1.1.1.1.2.2 perseant as_warn (_("could not set architecture and machine"));
1439 1.1.1.1.2.2 perseant }
1440 1.1.1.1.2.2 perseant
1441 1.1.1.1.2.2 perseant static int
1442 1.1.1.1.2.2 perseant kvxop_compar (const void *a, const void *b)
1443 1.1.1.1.2.2 perseant {
1444 1.1.1.1.2.2 perseant const struct kvxopc *opa = (const struct kvxopc *) a;
1445 1.1.1.1.2.2 perseant const struct kvxopc *opb = (const struct kvxopc *) b;
1446 1.1.1.1.2.2 perseant int res = strcmp (opa->as_op, opb->as_op);
1447 1.1.1.1.2.2 perseant
1448 1.1.1.1.2.2 perseant if (res)
1449 1.1.1.1.2.2 perseant return res;
1450 1.1.1.1.2.2 perseant else
1451 1.1.1.1.2.2 perseant {
1452 1.1.1.1.2.2 perseant for (int i = 0; opa->format[i] && opb->format[i]; ++i)
1453 1.1.1.1.2.2 perseant if (opa->format[i]->width != opb->format[i]->width)
1454 1.1.1.1.2.2 perseant return opa->format[i]->width - opb->format[i]->width;
1455 1.1.1.1.2.2 perseant return 0;
1456 1.1.1.1.2.2 perseant }
1457 1.1.1.1.2.2 perseant }
1458 1.1.1.1.2.2 perseant
1459 1.1.1.1.2.2 perseant /***************************************************/
1460 1.1.1.1.2.2 perseant /* INITIALIZE ASSEMBLER */
1461 1.1.1.1.2.2 perseant /***************************************************/
1462 1.1.1.1.2.2 perseant
1463 1.1.1.1.2.2 perseant static int
1464 1.1.1.1.2.2 perseant print_hash (void **slot, void *arg ATTRIBUTE_UNUSED)
1465 1.1.1.1.2.2 perseant {
1466 1.1.1.1.2.2 perseant string_tuple_t *tuple = *((string_tuple_t **) slot);
1467 1.1.1.1.2.2 perseant printf ("%s\n", tuple->key);
1468 1.1.1.1.2.2 perseant return 1;
1469 1.1.1.1.2.2 perseant }
1470 1.1.1.1.2.2 perseant
1471 1.1.1.1.2.2 perseant static void
1472 1.1.1.1.2.2 perseant declare_register (const char *name, int number)
1473 1.1.1.1.2.2 perseant {
1474 1.1.1.1.2.2 perseant symbolS *regS = symbol_create (name, reg_section,
1475 1.1.1.1.2.2 perseant &zero_address_frag, number);
1476 1.1.1.1.2.2 perseant
1477 1.1.1.1.2.2 perseant if (str_hash_insert (env.reg_hash, S_GET_NAME (regS), regS, 0) != NULL)
1478 1.1.1.1.2.2 perseant as_fatal (_("duplicate %s"), name);
1479 1.1.1.1.2.2 perseant }
1480 1.1.1.1.2.2 perseant
1481 1.1.1.1.2.2 perseant void
1482 1.1.1.1.2.2 perseant md_begin ()
1483 1.1.1.1.2.2 perseant {
1484 1.1.1.1.2.2 perseant kvx_set_cpu ();
1485 1.1.1.1.2.2 perseant
1486 1.1.1.1.2.2 perseant /*
1487 1.1.1.1.2.2 perseant * Declare register names with symbols
1488 1.1.1.1.2.2 perseant */
1489 1.1.1.1.2.2 perseant
1490 1.1.1.1.2.2 perseant env.reg_hash = str_htab_create ();
1491 1.1.1.1.2.2 perseant
1492 1.1.1.1.2.2 perseant for (int i = 0; i < kvx_regfiles[KVX_REGFILE_REGISTERS]; i++)
1493 1.1.1.1.2.2 perseant declare_register (kvx_registers[i].name, kvx_registers[i].id);
1494 1.1.1.1.2.2 perseant
1495 1.1.1.1.2.2 perseant /* Sort optab, so that identical mnemonics appear consecutively */
1496 1.1.1.1.2.2 perseant {
1497 1.1.1.1.2.2 perseant int nel;
1498 1.1.1.1.2.2 perseant for (nel = 0; !STREQ ("", kvx_core_info->optab[nel].as_op); nel++)
1499 1.1.1.1.2.2 perseant ;
1500 1.1.1.1.2.2 perseant qsort (kvx_core_info->optab, nel, sizeof (kvx_core_info->optab[0]),
1501 1.1.1.1.2.2 perseant kvxop_compar);
1502 1.1.1.1.2.2 perseant }
1503 1.1.1.1.2.2 perseant
1504 1.1.1.1.2.2 perseant /* The '?' is an operand separator */
1505 1.1.1.1.2.2 perseant lex_type['?'] = 0;
1506 1.1.1.1.2.2 perseant
1507 1.1.1.1.2.2 perseant /* Create the opcode hash table */
1508 1.1.1.1.2.2 perseant /* Each name should appear only once */
1509 1.1.1.1.2.2 perseant
1510 1.1.1.1.2.2 perseant env.opcode_hash = str_htab_create ();
1511 1.1.1.1.2.2 perseant env.reloc_hash = str_htab_create ();
1512 1.1.1.1.2.2 perseant
1513 1.1.1.1.2.2 perseant {
1514 1.1.1.1.2.2 perseant struct kvxopc *op;
1515 1.1.1.1.2.2 perseant const char *name = 0;
1516 1.1.1.1.2.2 perseant for (op = kvx_core_info->optab; !(STREQ ("", op->as_op)); op++)
1517 1.1.1.1.2.2 perseant {
1518 1.1.1.1.2.2 perseant /* enter in hash table if this is a new name */
1519 1.1.1.1.2.2 perseant if (!(STREQ (name, op->as_op)))
1520 1.1.1.1.2.2 perseant {
1521 1.1.1.1.2.2 perseant name = op->as_op;
1522 1.1.1.1.2.2 perseant if (str_hash_insert (env.opcode_hash, name, op, 0))
1523 1.1.1.1.2.2 perseant as_fatal ("internal error: can't hash opcode `%s'", name);
1524 1.1.1.1.2.2 perseant }
1525 1.1.1.1.2.2 perseant
1526 1.1.1.1.2.2 perseant
1527 1.1.1.1.2.2 perseant for (int i = 0 ; op->format[i] ; ++i)
1528 1.1.1.1.2.2 perseant {
1529 1.1.1.1.2.2 perseant const char *reloc_name = TOKEN_NAME (op->format[i]->type);
1530 1.1.1.1.2.2 perseant void *relocs = op->format[i]->relocs;
1531 1.1.1.1.2.2 perseant if (op->format[i]->relocs[0] != 0
1532 1.1.1.1.2.2 perseant && !str_hash_find (env.reloc_hash, reloc_name))
1533 1.1.1.1.2.2 perseant if (str_hash_insert (env.reloc_hash, reloc_name, relocs, 0))
1534 1.1.1.1.2.2 perseant as_fatal ("internal error: can't hash type `%s'", reloc_name);
1535 1.1.1.1.2.2 perseant }
1536 1.1.1.1.2.2 perseant }
1537 1.1.1.1.2.2 perseant }
1538 1.1.1.1.2.2 perseant
1539 1.1.1.1.2.2 perseant if (env.opts.dump_table)
1540 1.1.1.1.2.2 perseant {
1541 1.1.1.1.2.2 perseant htab_traverse (env.opcode_hash, print_hash, NULL);
1542 1.1.1.1.2.2 perseant exit (0);
1543 1.1.1.1.2.2 perseant }
1544 1.1.1.1.2.2 perseant
1545 1.1.1.1.2.2 perseant if (env.opts.dump_insn)
1546 1.1.1.1.2.2 perseant {
1547 1.1.1.1.2.2 perseant for (struct kvxopc *op = kvx_core_info->optab; !(STREQ ("", op->as_op)); op++)
1548 1.1.1.1.2.2 perseant print_insn (op);
1549 1.1.1.1.2.2 perseant exit (0);
1550 1.1.1.1.2.2 perseant }
1551 1.1.1.1.2.2 perseant
1552 1.1.1.1.2.2 perseant /* Here we enforce the minimum section alignment. Remember, in
1553 1.1.1.1.2.2 perseant * the linker we can make the boudaries between the linked sections
1554 1.1.1.1.2.2 perseant * on larger boundaries. The text segment is aligned to long words
1555 1.1.1.1.2.2 perseant * because of the odd/even constraint on immediate extensions
1556 1.1.1.1.2.2 perseant */
1557 1.1.1.1.2.2 perseant
1558 1.1.1.1.2.2 perseant bfd_set_section_alignment (text_section, 3); /* -- 8 bytes */
1559 1.1.1.1.2.2 perseant bfd_set_section_alignment (data_section, 2); /* -- 4 bytes */
1560 1.1.1.1.2.2 perseant bfd_set_section_alignment (bss_section, 2); /* -- 4 bytes */
1561 1.1.1.1.2.2 perseant subseg_set (text_section, 0);
1562 1.1.1.1.2.2 perseant
1563 1.1.1.1.2.2 perseant symbolS *gotoff_sym = symbol_create (".<gotoff>", undefined_section, &zero_address_frag, 0);
1564 1.1.1.1.2.2 perseant symbolS *got_sym = symbol_create (".<got>", undefined_section, &zero_address_frag, 0);
1565 1.1.1.1.2.2 perseant symbolS *plt_sym = symbol_create (".<plt>", undefined_section, &zero_address_frag, 0);
1566 1.1.1.1.2.2 perseant symbolS *tlsgd_sym = symbol_create (".<tlsgd>", undefined_section, &zero_address_frag, 0);
1567 1.1.1.1.2.2 perseant symbolS *tlsie_sym = symbol_create (".<tlsie>", undefined_section, &zero_address_frag, 0);
1568 1.1.1.1.2.2 perseant symbolS *tlsle_sym = symbol_create (".<tlsle>", undefined_section, &zero_address_frag, 0);
1569 1.1.1.1.2.2 perseant symbolS *tlsld_sym = symbol_create (".<tlsld>", undefined_section, &zero_address_frag, 0);
1570 1.1.1.1.2.2 perseant symbolS *dtpoff_sym = symbol_create (".<dtpoff>", undefined_section, &zero_address_frag, 0);
1571 1.1.1.1.2.2 perseant symbolS *plt64_sym = symbol_create (".<plt64>", undefined_section, &zero_address_frag, 0);
1572 1.1.1.1.2.2 perseant symbolS *gotaddr_sym = symbol_create (".<gotaddr>", undefined_section, &zero_address_frag, 0);
1573 1.1.1.1.2.2 perseant symbolS *pcrel16_sym = symbol_create (".<pcrel16>", undefined_section, &zero_address_frag, 0);
1574 1.1.1.1.2.2 perseant symbolS *pcrel_sym = symbol_create (".<pcrel>", undefined_section, &zero_address_frag, 0);
1575 1.1.1.1.2.2 perseant symbolS *signed32_sym = symbol_create (".<signed32>", undefined_section, &zero_address_frag, 0);
1576 1.1.1.1.2.2 perseant
1577 1.1.1.1.2.2 perseant for (int i = 0; i < kvx_core_info->nb_pseudo_funcs; ++i)
1578 1.1.1.1.2.2 perseant {
1579 1.1.1.1.2.2 perseant symbolS *sym;
1580 1.1.1.1.2.2 perseant if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "gotoff"))
1581 1.1.1.1.2.2 perseant sym = gotoff_sym;
1582 1.1.1.1.2.2 perseant else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "got"))
1583 1.1.1.1.2.2 perseant sym = got_sym;
1584 1.1.1.1.2.2 perseant else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "plt"))
1585 1.1.1.1.2.2 perseant sym = plt_sym;
1586 1.1.1.1.2.2 perseant else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "tlsgd"))
1587 1.1.1.1.2.2 perseant sym = tlsgd_sym;
1588 1.1.1.1.2.2 perseant else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "tlsle"))
1589 1.1.1.1.2.2 perseant sym = tlsle_sym;
1590 1.1.1.1.2.2 perseant else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "tlsld"))
1591 1.1.1.1.2.2 perseant sym = tlsld_sym;
1592 1.1.1.1.2.2 perseant else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "dtpoff"))
1593 1.1.1.1.2.2 perseant sym = dtpoff_sym;
1594 1.1.1.1.2.2 perseant else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "tlsie"))
1595 1.1.1.1.2.2 perseant sym = tlsie_sym;
1596 1.1.1.1.2.2 perseant else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "plt64"))
1597 1.1.1.1.2.2 perseant sym = plt64_sym;
1598 1.1.1.1.2.2 perseant else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "pcrel16"))
1599 1.1.1.1.2.2 perseant sym = pcrel16_sym;
1600 1.1.1.1.2.2 perseant else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "pcrel"))
1601 1.1.1.1.2.2 perseant sym = pcrel_sym;
1602 1.1.1.1.2.2 perseant else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "gotaddr"))
1603 1.1.1.1.2.2 perseant sym = gotaddr_sym;
1604 1.1.1.1.2.2 perseant else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "signed32"))
1605 1.1.1.1.2.2 perseant sym = signed32_sym;
1606 1.1.1.1.2.2 perseant else
1607 1.1.1.1.2.2 perseant as_fatal ("internal error: Unknown pseudo func `%s'",
1608 1.1.1.1.2.2 perseant kvx_core_info->pseudo_funcs[i].name);
1609 1.1.1.1.2.2 perseant
1610 1.1.1.1.2.2 perseant kvx_core_info->pseudo_funcs[i].sym = sym;
1611 1.1.1.1.2.2 perseant }
1612 1.1.1.1.2.2 perseant }
1613 1.1.1.1.2.2 perseant
1614 1.1.1.1.2.2 perseant /***************************************************/
1615 1.1.1.1.2.2 perseant /* ASSEMBLER CLEANUP STUFF */
1616 1.1.1.1.2.2 perseant /***************************************************/
1617 1.1.1.1.2.2 perseant
1618 1.1.1.1.2.2 perseant /* Return non-zero if the indicated VALUE has overflowed the maximum
1619 1.1.1.1.2.2 perseant range expressible by a signed number with the indicated number of
1620 1.1.1.1.2.2 perseant BITS.
1621 1.1.1.1.2.2 perseant
1622 1.1.1.1.2.2 perseant This is from tc-aarch64.c
1623 1.1.1.1.2.2 perseant */
1624 1.1.1.1.2.2 perseant
1625 1.1.1.1.2.2 perseant static bfd_boolean
1626 1.1.1.1.2.2 perseant signed_overflow (offsetT value, unsigned bits)
1627 1.1.1.1.2.2 perseant {
1628 1.1.1.1.2.2 perseant offsetT lim;
1629 1.1.1.1.2.2 perseant if (bits >= sizeof (offsetT) * 8)
1630 1.1.1.1.2.2 perseant return FALSE;
1631 1.1.1.1.2.2 perseant lim = (offsetT) 1 << (bits - 1);
1632 1.1.1.1.2.2 perseant return (value < -lim || value >= lim);
1633 1.1.1.1.2.2 perseant }
1634 1.1.1.1.2.2 perseant
1635 1.1.1.1.2.2 perseant /***************************************************/
1636 1.1.1.1.2.2 perseant /* ASSEMBLER FIXUP STUFF */
1637 1.1.1.1.2.2 perseant /***************************************************/
1638 1.1.1.1.2.2 perseant
1639 1.1.1.1.2.2 perseant void
1640 1.1.1.1.2.2 perseant md_apply_fix (fixS * fixP, valueT * valueP, segT segmentP ATTRIBUTE_UNUSED)
1641 1.1.1.1.2.2 perseant {
1642 1.1.1.1.2.2 perseant char *const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
1643 1.1.1.1.2.2 perseant valueT value = *valueP;
1644 1.1.1.1.2.2 perseant valueT image;
1645 1.1.1.1.2.2 perseant arelent *rel;
1646 1.1.1.1.2.2 perseant
1647 1.1.1.1.2.2 perseant rel = (arelent *) xmalloc (sizeof (arelent));
1648 1.1.1.1.2.2 perseant
1649 1.1.1.1.2.2 perseant rel->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1650 1.1.1.1.2.2 perseant if (rel->howto == NULL)
1651 1.1.1.1.2.2 perseant {
1652 1.1.1.1.2.2 perseant as_fatal
1653 1.1.1.1.2.2 perseant ("[md_apply_fix] unsupported relocation type (can't find howto)");
1654 1.1.1.1.2.2 perseant }
1655 1.1.1.1.2.2 perseant
1656 1.1.1.1.2.2 perseant /* Note whether this will delete the relocation. */
1657 1.1.1.1.2.2 perseant if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
1658 1.1.1.1.2.2 perseant fixP->fx_done = 1;
1659 1.1.1.1.2.2 perseant
1660 1.1.1.1.2.2 perseant if (fixP->fx_size > 0)
1661 1.1.1.1.2.2 perseant image = md_chars_to_number (fixpos, fixP->fx_size);
1662 1.1.1.1.2.2 perseant else
1663 1.1.1.1.2.2 perseant image = 0;
1664 1.1.1.1.2.2 perseant if (fixP->fx_addsy != NULL)
1665 1.1.1.1.2.2 perseant {
1666 1.1.1.1.2.2 perseant switch (fixP->fx_r_type)
1667 1.1.1.1.2.2 perseant {
1668 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_TLS_LE_UP27:
1669 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_TLS_LE_LO10:
1670 1.1.1.1.2.2 perseant
1671 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_LE_EX6:
1672 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_LE_UP27:
1673 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_LE_LO10:
1674 1.1.1.1.2.2 perseant
1675 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_TLS_GD_LO10:
1676 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_TLS_GD_UP27:
1677 1.1.1.1.2.2 perseant
1678 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_GD_LO10:
1679 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_GD_UP27:
1680 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_GD_EX6:
1681 1.1.1.1.2.2 perseant
1682 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_TLS_IE_LO10:
1683 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_TLS_IE_UP27:
1684 1.1.1.1.2.2 perseant
1685 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_IE_LO10:
1686 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_IE_UP27:
1687 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_IE_EX6:
1688 1.1.1.1.2.2 perseant
1689 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_TLS_LD_LO10:
1690 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_TLS_LD_UP27:
1691 1.1.1.1.2.2 perseant
1692 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_LD_LO10:
1693 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_LD_UP27:
1694 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_LD_EX6:
1695 1.1.1.1.2.2 perseant
1696 1.1.1.1.2.2 perseant S_SET_THREAD_LOCAL (fixP->fx_addsy);
1697 1.1.1.1.2.2 perseant break;
1698 1.1.1.1.2.2 perseant default:
1699 1.1.1.1.2.2 perseant break;
1700 1.1.1.1.2.2 perseant }
1701 1.1.1.1.2.2 perseant }
1702 1.1.1.1.2.2 perseant
1703 1.1.1.1.2.2 perseant /* If relocation has been marked for deletion, apply remaining changes */
1704 1.1.1.1.2.2 perseant if (fixP->fx_done)
1705 1.1.1.1.2.2 perseant {
1706 1.1.1.1.2.2 perseant switch (fixP->fx_r_type)
1707 1.1.1.1.2.2 perseant {
1708 1.1.1.1.2.2 perseant case BFD_RELOC_8:
1709 1.1.1.1.2.2 perseant case BFD_RELOC_16:
1710 1.1.1.1.2.2 perseant case BFD_RELOC_32:
1711 1.1.1.1.2.2 perseant case BFD_RELOC_64:
1712 1.1.1.1.2.2 perseant
1713 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_GLOB_DAT:
1714 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_32_GOT:
1715 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_64_GOT:
1716 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_64_GOTOFF:
1717 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_32_GOTOFF:
1718 1.1.1.1.2.2 perseant image = value;
1719 1.1.1.1.2.2 perseant md_number_to_chars (fixpos, image, fixP->fx_size);
1720 1.1.1.1.2.2 perseant break;
1721 1.1.1.1.2.2 perseant
1722 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_PCREL17:
1723 1.1.1.1.2.2 perseant if (signed_overflow (value, 17 + 2))
1724 1.1.1.1.2.2 perseant as_bad_where (fixP->fx_file, fixP->fx_line,
1725 1.1.1.1.2.2 perseant _("branch out of range"));
1726 1.1.1.1.2.2 perseant goto pcrel_common;
1727 1.1.1.1.2.2 perseant
1728 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_PCREL27:
1729 1.1.1.1.2.2 perseant if (signed_overflow (value, 27 + 2))
1730 1.1.1.1.2.2 perseant as_bad_where (fixP->fx_file, fixP->fx_line,
1731 1.1.1.1.2.2 perseant _("branch out of range"));
1732 1.1.1.1.2.2 perseant goto pcrel_common;
1733 1.1.1.1.2.2 perseant
1734 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S16_PCREL:
1735 1.1.1.1.2.2 perseant if (signed_overflow (value, 16))
1736 1.1.1.1.2.2 perseant as_bad_where (fixP->fx_file, fixP->fx_line,
1737 1.1.1.1.2.2 perseant _("signed16 PCREL value out of range"));
1738 1.1.1.1.2.2 perseant goto pcrel_common;
1739 1.1.1.1.2.2 perseant
1740 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_PCREL_LO10:
1741 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_PCREL_UP27:
1742 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_PCREL_EX6:
1743 1.1.1.1.2.2 perseant if (signed_overflow (value, 10 + 27 + 6))
1744 1.1.1.1.2.2 perseant as_bad_where (fixP->fx_file, fixP->fx_line,
1745 1.1.1.1.2.2 perseant _("signed43 PCREL value out of range"));
1746 1.1.1.1.2.2 perseant goto pcrel_common;
1747 1.1.1.1.2.2 perseant
1748 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_PCREL_LO10:
1749 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_PCREL_UP27:
1750 1.1.1.1.2.2 perseant if (signed_overflow (value, 10 + 27))
1751 1.1.1.1.2.2 perseant as_bad_where (fixP->fx_file, fixP->fx_line,
1752 1.1.1.1.2.2 perseant _("signed37 PCREL value out of range"));
1753 1.1.1.1.2.2 perseant goto pcrel_common;
1754 1.1.1.1.2.2 perseant
1755 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S64_PCREL_LO10:
1756 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S64_PCREL_UP27:
1757 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S64_PCREL_EX27:
1758 1.1.1.1.2.2 perseant
1759 1.1.1.1.2.2 perseant pcrel_common:
1760 1.1.1.1.2.2 perseant if (fixP->fx_pcrel || fixP->fx_addsy)
1761 1.1.1.1.2.2 perseant return;
1762 1.1.1.1.2.2 perseant value =
1763 1.1.1.1.2.2 perseant (((value >> rel->howto->rightshift) << rel->howto->bitpos) & rel->
1764 1.1.1.1.2.2 perseant howto->dst_mask);
1765 1.1.1.1.2.2 perseant image = (image & ~(rel->howto->dst_mask)) | value;
1766 1.1.1.1.2.2 perseant md_number_to_chars (fixpos, image, fixP->fx_size);
1767 1.1.1.1.2.2 perseant break;
1768 1.1.1.1.2.2 perseant
1769 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S64_GOTADDR_LO10:
1770 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S64_GOTADDR_UP27:
1771 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S64_GOTADDR_EX27:
1772 1.1.1.1.2.2 perseant
1773 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOTADDR_LO10:
1774 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOTADDR_UP27:
1775 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOTADDR_EX6:
1776 1.1.1.1.2.2 perseant
1777 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOTADDR_LO10:
1778 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOTADDR_UP27:
1779 1.1.1.1.2.2 perseant value = 0;
1780 1.1.1.1.2.2 perseant /* Fallthrough */
1781 1.1.1.1.2.2 perseant
1782 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S32_UP27:
1783 1.1.1.1.2.2 perseant
1784 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_UP27:
1785 1.1.1.1.2.2 perseant
1786 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_UP27:
1787 1.1.1.1.2.2 perseant
1788 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S64_UP27:
1789 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S64_EX27:
1790 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S64_LO10:
1791 1.1.1.1.2.2 perseant
1792 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_LE_UP27:
1793 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_LE_EX6:
1794 1.1.1.1.2.2 perseant
1795 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_TLS_LE_UP27:
1796 1.1.1.1.2.2 perseant
1797 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOTOFF_UP27:
1798 1.1.1.1.2.2 perseant
1799 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOTOFF_UP27:
1800 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOTOFF_EX6:
1801 1.1.1.1.2.2 perseant
1802 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOT_UP27:
1803 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOT_EX6:
1804 1.1.1.1.2.2 perseant
1805 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOT_UP27:
1806 1.1.1.1.2.2 perseant
1807 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S32_LO5:
1808 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_LO10:
1809 1.1.1.1.2.2 perseant
1810 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_LO10:
1811 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_EX6:
1812 1.1.1.1.2.2 perseant
1813 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_TLS_LE_LO10:
1814 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_TLS_LE_LO10:
1815 1.1.1.1.2.2 perseant
1816 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOTOFF_LO10:
1817 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOTOFF_LO10:
1818 1.1.1.1.2.2 perseant
1819 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOT_LO10:
1820 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOT_LO10:
1821 1.1.1.1.2.2 perseant
1822 1.1.1.1.2.2 perseant default:
1823 1.1.1.1.2.2 perseant as_fatal ("[md_apply_fix]:"
1824 1.1.1.1.2.2 perseant "unsupported relocation type (type not handled : %d)",
1825 1.1.1.1.2.2 perseant fixP->fx_r_type);
1826 1.1.1.1.2.2 perseant }
1827 1.1.1.1.2.2 perseant }
1828 1.1.1.1.2.2 perseant }
1829 1.1.1.1.2.2 perseant
1830 1.1.1.1.2.2 perseant /*
1831 1.1.1.1.2.2 perseant * Warning: Can be called only in fixup_segment() after fx_addsy field
1832 1.1.1.1.2.2 perseant * has been updated by calling symbol_get_value_expression(...->X_add_symbol)
1833 1.1.1.1.2.2 perseant */
1834 1.1.1.1.2.2 perseant int
1835 1.1.1.1.2.2 perseant kvx_validate_sub_fix (fixS * fixP)
1836 1.1.1.1.2.2 perseant {
1837 1.1.1.1.2.2 perseant segT add_symbol_segment, sub_symbol_segment;
1838 1.1.1.1.2.2 perseant
1839 1.1.1.1.2.2 perseant switch (fixP->fx_r_type)
1840 1.1.1.1.2.2 perseant {
1841 1.1.1.1.2.2 perseant case BFD_RELOC_8:
1842 1.1.1.1.2.2 perseant case BFD_RELOC_16:
1843 1.1.1.1.2.2 perseant case BFD_RELOC_32:
1844 1.1.1.1.2.2 perseant if (fixP->fx_addsy != NULL)
1845 1.1.1.1.2.2 perseant add_symbol_segment = S_GET_SEGMENT (fixP->fx_addsy);
1846 1.1.1.1.2.2 perseant else
1847 1.1.1.1.2.2 perseant return 0;
1848 1.1.1.1.2.2 perseant if (fixP->fx_subsy != NULL)
1849 1.1.1.1.2.2 perseant sub_symbol_segment = S_GET_SEGMENT (fixP->fx_subsy);
1850 1.1.1.1.2.2 perseant else
1851 1.1.1.1.2.2 perseant return 0;
1852 1.1.1.1.2.2 perseant
1853 1.1.1.1.2.2 perseant if ((strcmp (S_GET_NAME (fixP->fx_addsy),
1854 1.1.1.1.2.2 perseant S_GET_NAME (fixP->fx_subsy)) == 0) &&
1855 1.1.1.1.2.2 perseant (add_symbol_segment == sub_symbol_segment))
1856 1.1.1.1.2.2 perseant return 1;
1857 1.1.1.1.2.2 perseant break;
1858 1.1.1.1.2.2 perseant default:
1859 1.1.1.1.2.2 perseant break;
1860 1.1.1.1.2.2 perseant }
1861 1.1.1.1.2.2 perseant
1862 1.1.1.1.2.2 perseant return 0;
1863 1.1.1.1.2.2 perseant }
1864 1.1.1.1.2.2 perseant
1865 1.1.1.1.2.2 perseant /* This is called whenever some data item (not an instruction) needs a
1866 1.1.1.1.2.2 perseant * fixup. */
1867 1.1.1.1.2.2 perseant void
1868 1.1.1.1.2.2 perseant kvx_cons_fix_new (fragS * f, int where, int nbytes, expressionS * exp,
1869 1.1.1.1.2.2 perseant bfd_reloc_code_real_type code)
1870 1.1.1.1.2.2 perseant {
1871 1.1.1.1.2.2 perseant if (exp->X_op == O_pseudo_fixup)
1872 1.1.1.1.2.2 perseant {
1873 1.1.1.1.2.2 perseant exp->X_op = O_symbol;
1874 1.1.1.1.2.2 perseant struct pseudo_func *pf =
1875 1.1.1.1.2.2 perseant kvx_get_pseudo_func_data_scn (exp->X_op_symbol);
1876 1.1.1.1.2.2 perseant assert (pf != NULL);
1877 1.1.1.1.2.2 perseant code = pf->pseudo_relocs.single;
1878 1.1.1.1.2.2 perseant
1879 1.1.1.1.2.2 perseant if (code == BFD_RELOC_UNUSED)
1880 1.1.1.1.2.2 perseant as_fatal ("Unsupported relocation");
1881 1.1.1.1.2.2 perseant }
1882 1.1.1.1.2.2 perseant else
1883 1.1.1.1.2.2 perseant {
1884 1.1.1.1.2.2 perseant switch (nbytes)
1885 1.1.1.1.2.2 perseant {
1886 1.1.1.1.2.2 perseant case 1:
1887 1.1.1.1.2.2 perseant code = BFD_RELOC_8;
1888 1.1.1.1.2.2 perseant break;
1889 1.1.1.1.2.2 perseant case 2:
1890 1.1.1.1.2.2 perseant code = BFD_RELOC_16;
1891 1.1.1.1.2.2 perseant break;
1892 1.1.1.1.2.2 perseant case 4:
1893 1.1.1.1.2.2 perseant code = BFD_RELOC_32;
1894 1.1.1.1.2.2 perseant break;
1895 1.1.1.1.2.2 perseant case 8:
1896 1.1.1.1.2.2 perseant code = BFD_RELOC_64;
1897 1.1.1.1.2.2 perseant break;
1898 1.1.1.1.2.2 perseant default:
1899 1.1.1.1.2.2 perseant as_fatal ("unsupported BFD relocation size %u", nbytes);
1900 1.1.1.1.2.2 perseant break;
1901 1.1.1.1.2.2 perseant }
1902 1.1.1.1.2.2 perseant }
1903 1.1.1.1.2.2 perseant fix_new_exp (f, where, nbytes, exp, 0, code);
1904 1.1.1.1.2.2 perseant }
1905 1.1.1.1.2.2 perseant
1906 1.1.1.1.2.2 perseant /*
1907 1.1.1.1.2.2 perseant * generate a relocation record
1908 1.1.1.1.2.2 perseant */
1909 1.1.1.1.2.2 perseant
1910 1.1.1.1.2.2 perseant arelent *
1911 1.1.1.1.2.2 perseant tc_gen_reloc (asection * sec ATTRIBUTE_UNUSED, fixS * fixp)
1912 1.1.1.1.2.2 perseant {
1913 1.1.1.1.2.2 perseant arelent *reloc;
1914 1.1.1.1.2.2 perseant bfd_reloc_code_real_type code;
1915 1.1.1.1.2.2 perseant
1916 1.1.1.1.2.2 perseant reloc = (arelent *) xmalloc (sizeof (arelent));
1917 1.1.1.1.2.2 perseant
1918 1.1.1.1.2.2 perseant reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1919 1.1.1.1.2.2 perseant *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1920 1.1.1.1.2.2 perseant reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1921 1.1.1.1.2.2 perseant
1922 1.1.1.1.2.2 perseant code = fixp->fx_r_type;
1923 1.1.1.1.2.2 perseant if (code == BFD_RELOC_32 && fixp->fx_pcrel)
1924 1.1.1.1.2.2 perseant code = BFD_RELOC_32_PCREL;
1925 1.1.1.1.2.2 perseant reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
1926 1.1.1.1.2.2 perseant
1927 1.1.1.1.2.2 perseant if (reloc->howto == NULL)
1928 1.1.1.1.2.2 perseant {
1929 1.1.1.1.2.2 perseant as_bad_where (fixp->fx_file, fixp->fx_line,
1930 1.1.1.1.2.2 perseant "cannot represent `%s' relocation in object file",
1931 1.1.1.1.2.2 perseant bfd_get_reloc_code_name (code));
1932 1.1.1.1.2.2 perseant return NULL;
1933 1.1.1.1.2.2 perseant }
1934 1.1.1.1.2.2 perseant
1935 1.1.1.1.2.2 perseant // if (!fixp->fx_pcrel != !reloc->howto->pc_relative)
1936 1.1.1.1.2.2 perseant // {
1937 1.1.1.1.2.2 perseant // as_fatal ("internal error? cannot generate `%s' relocation",
1938 1.1.1.1.2.2 perseant // bfd_get_reloc_code_name (code));
1939 1.1.1.1.2.2 perseant // }
1940 1.1.1.1.2.2 perseant // assert (!fixp->fx_pcrel == !reloc->howto->pc_relative);
1941 1.1.1.1.2.2 perseant
1942 1.1.1.1.2.2 perseant reloc->addend = fixp->fx_offset;
1943 1.1.1.1.2.2 perseant
1944 1.1.1.1.2.2 perseant /*
1945 1.1.1.1.2.2 perseant * Ohhh, this is ugly. The problem is that if this is a local global
1946 1.1.1.1.2.2 perseant * symbol, the relocation will entirely be performed at link time, not
1947 1.1.1.1.2.2 perseant * at assembly time. bfd_perform_reloc doesn't know about this sort
1948 1.1.1.1.2.2 perseant * of thing, and as a result we need to fake it out here.
1949 1.1.1.1.2.2 perseant */
1950 1.1.1.1.2.2 perseant
1951 1.1.1.1.2.2 perseant /* GD I'm not sure what this is used for in the kvx case but it sure */
1952 1.1.1.1.2.2 perseant /* messes up the relocs when emit_all_relocs is used as they are not */
1953 1.1.1.1.2.2 perseant /* resolved with respect to a global sysmbol (e.g. .text), and hence */
1954 1.1.1.1.2.2 perseant /* they are ALWAYS resolved at link time */
1955 1.1.1.1.2.2 perseant /* FIXME FIXME */
1956 1.1.1.1.2.2 perseant
1957 1.1.1.1.2.2 perseant /* clarkes: 030827: This code (and the other half of the fix in write.c)
1958 1.1.1.1.2.2 perseant * have caused problems with the PIC relocations.
1959 1.1.1.1.2.2 perseant * The root problem is that bfd_install_relocation adds in to the reloc
1960 1.1.1.1.2.2 perseant * addend the section offset of a symbol defined in the current object.
1961 1.1.1.1.2.2 perseant * This causes problems on numerous other targets too, and there are
1962 1.1.1.1.2.2 perseant * several different methods used to get around it:
1963 1.1.1.1.2.2 perseant * 1. In tc_gen_reloc, subtract off the value that bfd_install_relocation
1964 1.1.1.1.2.2 perseant * added. That is what we do here, and it is also done the
1965 1.1.1.1.2.2 perseant * same way for alpha.
1966 1.1.1.1.2.2 perseant * 2. In md_apply_fix, subtract off the value that bfd_install_relocation
1967 1.1.1.1.2.2 perseant * will add. This is done on SH (non-ELF) and sparc targets.
1968 1.1.1.1.2.2 perseant * 3. In the howto structure for the relocations, specify a
1969 1.1.1.1.2.2 perseant * special function that does not return bfd_reloc_continue.
1970 1.1.1.1.2.2 perseant * This causes bfd_install_relocaion to terminate before it
1971 1.1.1.1.2.2 perseant * adds in the symbol offset. This is done on SH ELF targets.
1972 1.1.1.1.2.2 perseant * Note that on ST200 we specify bfd_elf_generic_reloc as
1973 1.1.1.1.2.2 perseant * the special function. This will return bfd_reloc_continue
1974 1.1.1.1.2.2 perseant * only in some circumstances, but in particular if the reloc
1975 1.1.1.1.2.2 perseant * is marked as partial_inplace in the bfd howto structure, then
1976 1.1.1.1.2.2 perseant * bfd_elf_generic_reloc will return bfd_reloc_continue.
1977 1.1.1.1.2.2 perseant * Some ST200 relocations are marked as partial_inplace
1978 1.1.1.1.2.2 perseant * (this is an error in my opinion because ST200 always uses
1979 1.1.1.1.2.2 perseant * a separate addend), but some are not. The PIC relocations
1980 1.1.1.1.2.2 perseant * are not marked as partial_inplace, so for them,
1981 1.1.1.1.2.2 perseant * bfd_elf_generic_reloc returns bfd_reloc_ok, and the addend
1982 1.1.1.1.2.2 perseant * is not modified by bfd_install_relocation. The relocations
1983 1.1.1.1.2.2 perseant * R_KVX_16 and R_KVX_32 are marked partial_inplace, and so for
1984 1.1.1.1.2.2 perseant * these we need to correct the addend.
1985 1.1.1.1.2.2 perseant * In the code below, the condition in the emit_all_relocs branch
1986 1.1.1.1.2.2 perseant * (now moved to write.c) is the inverse of the condition that
1987 1.1.1.1.2.2 perseant * bfd_elf_generic_reloc uses to short-circuit the code in
1988 1.1.1.1.2.2 perseant * bfd_install_relocation that modifies the addend. The condition
1989 1.1.1.1.2.2 perseant * in the else branch match the condition used in the alpha version
1990 1.1.1.1.2.2 perseant * of tc_gen_reloc (see tc-alpha.c).
1991 1.1.1.1.2.2 perseant * I do not know why we need to use different conditions in these
1992 1.1.1.1.2.2 perseant * two branches, it seems to me that the condition should be the same
1993 1.1.1.1.2.2 perseant * whether or not emit_all_relocs is true.
1994 1.1.1.1.2.2 perseant * I also do not understand why it was necessary to move the emit_all_relocs
1995 1.1.1.1.2.2 perseant * condition to write.c.
1996 1.1.1.1.2.2 perseant */
1997 1.1.1.1.2.2 perseant
1998 1.1.1.1.2.2 perseant if (S_IS_EXTERNAL (fixp->fx_addsy) &&
1999 1.1.1.1.2.2 perseant !S_IS_COMMON (fixp->fx_addsy) && reloc->howto->partial_inplace)
2000 1.1.1.1.2.2 perseant reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value;
2001 1.1.1.1.2.2 perseant
2002 1.1.1.1.2.2 perseant return reloc;
2003 1.1.1.1.2.2 perseant }
2004 1.1.1.1.2.2 perseant
2005 1.1.1.1.2.2 perseant /* Round up segment to appropriate boundary */
2006 1.1.1.1.2.2 perseant
2007 1.1.1.1.2.2 perseant valueT
2008 1.1.1.1.2.2 perseant md_section_align (asection * seg ATTRIBUTE_UNUSED, valueT size)
2009 1.1.1.1.2.2 perseant {
2010 1.1.1.1.2.2 perseant #ifndef OBJ_ELF
2011 1.1.1.1.2.2 perseant /* This is not right for ELF; a.out wants it, and COFF will force
2012 1.1.1.1.2.2 perseant * the alignment anyways. */
2013 1.1.1.1.2.2 perseant int align = bfd_get_section_alignment (stdoutput, seg);
2014 1.1.1.1.2.2 perseant valueT mask = ((valueT) 1 << align) - 1;
2015 1.1.1.1.2.2 perseant return (size + mask) & ~mask;
2016 1.1.1.1.2.2 perseant #else
2017 1.1.1.1.2.2 perseant return size;
2018 1.1.1.1.2.2 perseant #endif
2019 1.1.1.1.2.2 perseant }
2020 1.1.1.1.2.2 perseant
2021 1.1.1.1.2.2 perseant int
2022 1.1.1.1.2.2 perseant md_estimate_size_before_relax (register fragS * fragP ATTRIBUTE_UNUSED,
2023 1.1.1.1.2.2 perseant segT segtype ATTRIBUTE_UNUSED)
2024 1.1.1.1.2.2 perseant {
2025 1.1.1.1.2.2 perseant as_fatal ("estimate_size_before_relax called");
2026 1.1.1.1.2.2 perseant }
2027 1.1.1.1.2.2 perseant
2028 1.1.1.1.2.2 perseant void
2029 1.1.1.1.2.2 perseant md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
2030 1.1.1.1.2.2 perseant asection * sec ATTRIBUTE_UNUSED,
2031 1.1.1.1.2.2 perseant fragS * fragp ATTRIBUTE_UNUSED)
2032 1.1.1.1.2.2 perseant {
2033 1.1.1.1.2.2 perseant as_fatal ("kvx convert_frag");
2034 1.1.1.1.2.2 perseant }
2035 1.1.1.1.2.2 perseant
2036 1.1.1.1.2.2 perseant symbolS *
2037 1.1.1.1.2.2 perseant md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
2038 1.1.1.1.2.2 perseant {
2039 1.1.1.1.2.2 perseant return 0;
2040 1.1.1.1.2.2 perseant }
2041 1.1.1.1.2.2 perseant
2042 1.1.1.1.2.2 perseant const char *
2043 1.1.1.1.2.2 perseant md_atof (int type ATTRIBUTE_UNUSED,
2044 1.1.1.1.2.2 perseant char *litp ATTRIBUTE_UNUSED, int *sizep ATTRIBUTE_UNUSED)
2045 1.1.1.1.2.2 perseant {
2046 1.1.1.1.2.2 perseant return ieee_md_atof (type, litp, sizep, TARGET_BYTES_BIG_ENDIAN);
2047 1.1.1.1.2.2 perseant }
2048 1.1.1.1.2.2 perseant
2049 1.1.1.1.2.2 perseant /*
2050 1.1.1.1.2.2 perseant * calculate the base for a pcrel fixup
2051 1.1.1.1.2.2 perseant * -- for relocation, we might need to add addend ?
2052 1.1.1.1.2.2 perseant */
2053 1.1.1.1.2.2 perseant
2054 1.1.1.1.2.2 perseant long
2055 1.1.1.1.2.2 perseant md_pcrel_from (fixS * fixP)
2056 1.1.1.1.2.2 perseant {
2057 1.1.1.1.2.2 perseant return (fixP->fx_where + fixP->fx_frag->fr_address);
2058 1.1.1.1.2.2 perseant }
2059 1.1.1.1.2.2 perseant
2060 1.1.1.1.2.2 perseant /************************************************************/
2061 1.1.1.1.2.2 perseant /* Hooks into standard processing -- we hook into label */
2062 1.1.1.1.2.2 perseant /* handling code to detect double ':' and we hook before */
2063 1.1.1.1.2.2 perseant /* a line of code is processed to do some simple sed style */
2064 1.1.1.1.2.2 perseant /* edits. */
2065 1.1.1.1.2.2 perseant /************************************************************/
2066 1.1.1.1.2.2 perseant
2067 1.1.1.1.2.2 perseant static symbolS *last_proc_sym = NULL;
2068 1.1.1.1.2.2 perseant static int update_last_proc_sym = 0;
2069 1.1.1.1.2.2 perseant
2070 1.1.1.1.2.2 perseant void
2071 1.1.1.1.2.2 perseant kvx_frob_label (symbolS *sym)
2072 1.1.1.1.2.2 perseant {
2073 1.1.1.1.2.2 perseant if (update_last_proc_sym)
2074 1.1.1.1.2.2 perseant {
2075 1.1.1.1.2.2 perseant last_proc_sym = sym;
2076 1.1.1.1.2.2 perseant update_last_proc_sym = 0;
2077 1.1.1.1.2.2 perseant }
2078 1.1.1.1.2.2 perseant
2079 1.1.1.1.2.2 perseant if (inside_bundle)
2080 1.1.1.1.2.2 perseant {
2081 1.1.1.1.2.2 perseant struct label_fix *fix;
2082 1.1.1.1.2.2 perseant fix = malloc (sizeof (*fix));
2083 1.1.1.1.2.2 perseant fix->next = label_fixes;
2084 1.1.1.1.2.2 perseant fix->sym = sym;
2085 1.1.1.1.2.2 perseant label_fixes = fix;
2086 1.1.1.1.2.2 perseant }
2087 1.1.1.1.2.2 perseant
2088 1.1.1.1.2.2 perseant dwarf2_emit_label (sym);
2089 1.1.1.1.2.2 perseant }
2090 1.1.1.1.2.2 perseant
2091 1.1.1.1.2.2 perseant void
2092 1.1.1.1.2.2 perseant kvx_check_label (symbolS *sym)
2093 1.1.1.1.2.2 perseant {
2094 1.1.1.1.2.2 perseant /* Labels followed by a second semi-colon are considered external symbols. */
2095 1.1.1.1.2.2 perseant if (*input_line_pointer == ':')
2096 1.1.1.1.2.2 perseant {
2097 1.1.1.1.2.2 perseant S_SET_EXTERNAL (sym);
2098 1.1.1.1.2.2 perseant input_line_pointer++;
2099 1.1.1.1.2.2 perseant }
2100 1.1.1.1.2.2 perseant }
2101 1.1.1.1.2.2 perseant
2102 1.1.1.1.2.2 perseant /* Emit single bundle nop. This is needed by .nop asm directive
2103 1.1.1.1.2.2 perseant * Have to manage end of bundle done usually by start_line_hook
2104 1.1.1.1.2.2 perseant * using BE pseudo op
2105 1.1.1.1.2.2 perseant */
2106 1.1.1.1.2.2 perseant void
2107 1.1.1.1.2.2 perseant kvx_emit_single_noop (void)
2108 1.1.1.1.2.2 perseant {
2109 1.1.1.1.2.2 perseant char *nop;
2110 1.1.1.1.2.2 perseant char *end_of_bundle;
2111 1.1.1.1.2.2 perseant
2112 1.1.1.1.2.2 perseant if (asprintf (&nop, "nop") < 0)
2113 1.1.1.1.2.2 perseant as_fatal ("%s", xstrerror (errno));
2114 1.1.1.1.2.2 perseant
2115 1.1.1.1.2.2 perseant if (asprintf (&end_of_bundle, "be") < 0)
2116 1.1.1.1.2.2 perseant as_fatal ("%s", xstrerror (errno));
2117 1.1.1.1.2.2 perseant
2118 1.1.1.1.2.2 perseant char *saved_ilp = input_line_pointer;
2119 1.1.1.1.2.2 perseant md_assemble (nop);
2120 1.1.1.1.2.2 perseant md_assemble (end_of_bundle);
2121 1.1.1.1.2.2 perseant input_line_pointer = saved_ilp;
2122 1.1.1.1.2.2 perseant free (nop);
2123 1.1.1.1.2.2 perseant free (end_of_bundle);
2124 1.1.1.1.2.2 perseant }
2125 1.1.1.1.2.2 perseant
2126 1.1.1.1.2.2 perseant /* edit out some syntactic sugar that confuses GAS */
2127 1.1.1.1.2.2 perseant /* input_line_pointer is guaranteed to point to the */
2128 1.1.1.1.2.2 perseant /* the current line but may include text from following */
2129 1.1.1.1.2.2 perseant /* lines. Thus, '\n' must be scanned for as well as '\0' */
2130 1.1.1.1.2.2 perseant
2131 1.1.1.1.2.2 perseant void
2132 1.1.1.1.2.2 perseant kvx_md_start_line_hook (void)
2133 1.1.1.1.2.2 perseant {
2134 1.1.1.1.2.2 perseant char *t;
2135 1.1.1.1.2.2 perseant
2136 1.1.1.1.2.2 perseant for (t = input_line_pointer; t && t[0] == ' '; t++);
2137 1.1.1.1.2.2 perseant
2138 1.1.1.1.2.2 perseant /* Detect illegal syntax patterns:
2139 1.1.1.1.2.2 perseant * - two bundle ends on the same line: ;; ;;
2140 1.1.1.1.2.2 perseant * - illegal token: ;;;
2141 1.1.1.1.2.2 perseant */
2142 1.1.1.1.2.2 perseant if (t && (t[0] == ';') && (t[1] == ';'))
2143 1.1.1.1.2.2 perseant {
2144 1.1.1.1.2.2 perseant char *tmp_t;
2145 1.1.1.1.2.2 perseant bool newline_seen = false;
2146 1.1.1.1.2.2 perseant
2147 1.1.1.1.2.2 perseant if (t[2] == ';')
2148 1.1.1.1.2.2 perseant as_fatal ("Syntax error: Illegal ;;; token");
2149 1.1.1.1.2.2 perseant
2150 1.1.1.1.2.2 perseant tmp_t = t + 2;
2151 1.1.1.1.2.2 perseant
2152 1.1.1.1.2.2 perseant while (tmp_t && tmp_t[0])
2153 1.1.1.1.2.2 perseant {
2154 1.1.1.1.2.2 perseant while (tmp_t && tmp_t[0] &&
2155 1.1.1.1.2.2 perseant ((tmp_t[0] == ' ') || (tmp_t[0] == '\n')))
2156 1.1.1.1.2.2 perseant {
2157 1.1.1.1.2.2 perseant if (tmp_t[0] == '\n')
2158 1.1.1.1.2.2 perseant newline_seen = true;
2159 1.1.1.1.2.2 perseant tmp_t++;
2160 1.1.1.1.2.2 perseant }
2161 1.1.1.1.2.2 perseant if (tmp_t[0] == ';' && tmp_t[1] == ';')
2162 1.1.1.1.2.2 perseant {
2163 1.1.1.1.2.2 perseant /* if there's no newline between the two bundle stops
2164 1.1.1.1.2.2 perseant * then raise a syntax error now, otherwise a strange error
2165 1.1.1.1.2.2 perseant * message from read.c will be raised: "junk at end of line..."
2166 1.1.1.1.2.2 perseant */
2167 1.1.1.1.2.2 perseant if (tmp_t[2] == ';')
2168 1.1.1.1.2.2 perseant as_fatal ("Syntax error: Illegal ;;; token");
2169 1.1.1.1.2.2 perseant
2170 1.1.1.1.2.2 perseant if (!newline_seen)
2171 1.1.1.1.2.2 perseant as_fatal ("Syntax error: More than one bundle stop on a line");
2172 1.1.1.1.2.2 perseant newline_seen = false; /* reset */
2173 1.1.1.1.2.2 perseant
2174 1.1.1.1.2.2 perseant /* this is an empty bundle, transform it into an
2175 1.1.1.1.2.2 perseant * empty statement */
2176 1.1.1.1.2.2 perseant tmp_t[0] = ';';
2177 1.1.1.1.2.2 perseant tmp_t[1] = ' ';
2178 1.1.1.1.2.2 perseant
2179 1.1.1.1.2.2 perseant tmp_t += 2;
2180 1.1.1.1.2.2 perseant }
2181 1.1.1.1.2.2 perseant else
2182 1.1.1.1.2.2 perseant break;
2183 1.1.1.1.2.2 perseant }
2184 1.1.1.1.2.2 perseant }
2185 1.1.1.1.2.2 perseant
2186 1.1.1.1.2.2 perseant /* check for bundle end */
2187 1.1.1.1.2.2 perseant /* we transform these into a special opcode BE */
2188 1.1.1.1.2.2 perseant /* because gas has ';' hardwired as a statement end */
2189 1.1.1.1.2.2 perseant if (t && (t[0] == ';') && (t[1] == ';'))
2190 1.1.1.1.2.2 perseant {
2191 1.1.1.1.2.2 perseant t[0] = 'B';
2192 1.1.1.1.2.2 perseant t[1] = 'E';
2193 1.1.1.1.2.2 perseant return;
2194 1.1.1.1.2.2 perseant }
2195 1.1.1.1.2.2 perseant }
2196 1.1.1.1.2.2 perseant
2197 1.1.1.1.2.2 perseant static void
2198 1.1.1.1.2.2 perseant kvx_check_resources (int f)
2199 1.1.1.1.2.2 perseant {
2200 1.1.1.1.2.2 perseant env.opts.check_resource_usage = f;
2201 1.1.1.1.2.2 perseant }
2202 1.1.1.1.2.2 perseant
2203 1.1.1.1.2.2 perseant /** called before write_object_file */
2204 1.1.1.1.2.2 perseant void
2205 1.1.1.1.2.2 perseant kvx_end (void)
2206 1.1.1.1.2.2 perseant {
2207 1.1.1.1.2.2 perseant int newflags;
2208 1.1.1.1.2.2 perseant
2209 1.1.1.1.2.2 perseant if (!env.params.core_set)
2210 1.1.1.1.2.2 perseant env.params.core = kvx_core_info->elf_core;
2211 1.1.1.1.2.2 perseant
2212 1.1.1.1.2.2 perseant /* (pp) the flags must be set at once */
2213 1.1.1.1.2.2 perseant newflags = env.params.core | env.params.abi | env.params.pic_flags;
2214 1.1.1.1.2.2 perseant
2215 1.1.1.1.2.2 perseant if (env.params.arch_size == 64)
2216 1.1.1.1.2.2 perseant newflags |= ELF_KVX_ABI_64B_ADDR_BIT;
2217 1.1.1.1.2.2 perseant
2218 1.1.1.1.2.2 perseant bfd_set_private_flags (stdoutput, newflags);
2219 1.1.1.1.2.2 perseant
2220 1.1.1.1.2.2 perseant cleanup ();
2221 1.1.1.1.2.2 perseant
2222 1.1.1.1.2.2 perseant if (inside_bundle && insncnt != 0)
2223 1.1.1.1.2.2 perseant as_bad ("unexpected end-of-file while processing a bundle."
2224 1.1.1.1.2.2 perseant " Please check that ;; is on its own line.");
2225 1.1.1.1.2.2 perseant }
2226 1.1.1.1.2.2 perseant
2227 1.1.1.1.2.2 perseant static void
2228 1.1.1.1.2.2 perseant kvx_type (int start ATTRIBUTE_UNUSED)
2229 1.1.1.1.2.2 perseant {
2230 1.1.1.1.2.2 perseant char *name;
2231 1.1.1.1.2.2 perseant char c;
2232 1.1.1.1.2.2 perseant int type;
2233 1.1.1.1.2.2 perseant char *typename = NULL;
2234 1.1.1.1.2.2 perseant symbolS *sym;
2235 1.1.1.1.2.2 perseant elf_symbol_type *elfsym;
2236 1.1.1.1.2.2 perseant
2237 1.1.1.1.2.2 perseant c = get_symbol_name (&name);
2238 1.1.1.1.2.2 perseant sym = symbol_find_or_make (name);
2239 1.1.1.1.2.2 perseant elfsym = (elf_symbol_type *) symbol_get_bfdsym (sym);
2240 1.1.1.1.2.2 perseant *input_line_pointer = c;
2241 1.1.1.1.2.2 perseant
2242 1.1.1.1.2.2 perseant if (!*S_GET_NAME (sym))
2243 1.1.1.1.2.2 perseant as_bad (_("Missing symbol name in directive"));
2244 1.1.1.1.2.2 perseant
2245 1.1.1.1.2.2 perseant SKIP_WHITESPACE ();
2246 1.1.1.1.2.2 perseant if (*input_line_pointer == ',')
2247 1.1.1.1.2.2 perseant ++input_line_pointer;
2248 1.1.1.1.2.2 perseant
2249 1.1.1.1.2.2 perseant
2250 1.1.1.1.2.2 perseant SKIP_WHITESPACE ();
2251 1.1.1.1.2.2 perseant if (*input_line_pointer == '#'
2252 1.1.1.1.2.2 perseant || *input_line_pointer == '@'
2253 1.1.1.1.2.2 perseant || *input_line_pointer == '"' || *input_line_pointer == '%')
2254 1.1.1.1.2.2 perseant ++input_line_pointer;
2255 1.1.1.1.2.2 perseant
2256 1.1.1.1.2.2 perseant /* typename = input_line_pointer; */
2257 1.1.1.1.2.2 perseant /* c = get_symbol_end(); */
2258 1.1.1.1.2.2 perseant c = get_symbol_name (&typename);
2259 1.1.1.1.2.2 perseant
2260 1.1.1.1.2.2 perseant type = 0;
2261 1.1.1.1.2.2 perseant if (strcmp (typename, "function") == 0
2262 1.1.1.1.2.2 perseant || strcmp (typename, "STT_FUNC") == 0)
2263 1.1.1.1.2.2 perseant type = BSF_FUNCTION;
2264 1.1.1.1.2.2 perseant else if (strcmp (typename, "object") == 0
2265 1.1.1.1.2.2 perseant || strcmp (typename, "STT_OBJECT") == 0)
2266 1.1.1.1.2.2 perseant type = BSF_OBJECT;
2267 1.1.1.1.2.2 perseant else if (strcmp (typename, "tls_object") == 0
2268 1.1.1.1.2.2 perseant || strcmp (typename, "STT_TLS") == 0)
2269 1.1.1.1.2.2 perseant type = BSF_OBJECT | BSF_THREAD_LOCAL;
2270 1.1.1.1.2.2 perseant else if (strcmp (typename, "common") == 0
2271 1.1.1.1.2.2 perseant || strcmp (typename, "STT_COMMON") == 0)
2272 1.1.1.1.2.2 perseant type = BSF_ELF_COMMON;
2273 1.1.1.1.2.2 perseant else if (strcmp (typename, "gnu_unique_object") == 0
2274 1.1.1.1.2.2 perseant || strcmp (typename, "STB_GNU_UNIQUE") == 0)
2275 1.1.1.1.2.2 perseant {
2276 1.1.1.1.2.2 perseant elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_unique;
2277 1.1.1.1.2.2 perseant type = BSF_OBJECT | BSF_GNU_UNIQUE;
2278 1.1.1.1.2.2 perseant }
2279 1.1.1.1.2.2 perseant else if (strcmp (typename, "notype") == 0
2280 1.1.1.1.2.2 perseant || strcmp (typename, "STT_NOTYPE") == 0)
2281 1.1.1.1.2.2 perseant ;
2282 1.1.1.1.2.2 perseant #ifdef md_elf_symbol_type
2283 1.1.1.1.2.2 perseant else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1)
2284 1.1.1.1.2.2 perseant ;
2285 1.1.1.1.2.2 perseant #endif
2286 1.1.1.1.2.2 perseant else
2287 1.1.1.1.2.2 perseant as_bad (_("unrecognized symbol type \"%s\""), typename);
2288 1.1.1.1.2.2 perseant
2289 1.1.1.1.2.2 perseant *input_line_pointer = c;
2290 1.1.1.1.2.2 perseant
2291 1.1.1.1.2.2 perseant if (*input_line_pointer == '"')
2292 1.1.1.1.2.2 perseant ++input_line_pointer;
2293 1.1.1.1.2.2 perseant
2294 1.1.1.1.2.2 perseant elfsym->symbol.flags |= type;
2295 1.1.1.1.2.2 perseant symbol_get_bfdsym (sym)->flags |= type;
2296 1.1.1.1.2.2 perseant
2297 1.1.1.1.2.2 perseant demand_empty_rest_of_line ();
2298 1.1.1.1.2.2 perseant }
2299 1.1.1.1.2.2 perseant
2300 1.1.1.1.2.2 perseant #define ENDPROCEXTENSION "$endproc"
2301 1.1.1.1.2.2 perseant #define MINUSEXPR ".-"
2302 1.1.1.1.2.2 perseant
2303 1.1.1.1.2.2 perseant static int proc_endp_status = 0;
2304 1.1.1.1.2.2 perseant
2305 1.1.1.1.2.2 perseant static void
2306 1.1.1.1.2.2 perseant kvx_endp (int start ATTRIBUTE_UNUSED)
2307 1.1.1.1.2.2 perseant {
2308 1.1.1.1.2.2 perseant char c;
2309 1.1.1.1.2.2 perseant char *name;
2310 1.1.1.1.2.2 perseant
2311 1.1.1.1.2.2 perseant if (inside_bundle)
2312 1.1.1.1.2.2 perseant as_warn (".endp directive inside a bundle.");
2313 1.1.1.1.2.2 perseant /* function name is optionnal and is ignored */
2314 1.1.1.1.2.2 perseant /* there may be several names separated by commas... */
2315 1.1.1.1.2.2 perseant while (1)
2316 1.1.1.1.2.2 perseant {
2317 1.1.1.1.2.2 perseant SKIP_WHITESPACE ();
2318 1.1.1.1.2.2 perseant c = get_symbol_name (&name);
2319 1.1.1.1.2.2 perseant (void) restore_line_pointer (c);
2320 1.1.1.1.2.2 perseant SKIP_WHITESPACE ();
2321 1.1.1.1.2.2 perseant if (*input_line_pointer != ',')
2322 1.1.1.1.2.2 perseant break;
2323 1.1.1.1.2.2 perseant ++input_line_pointer;
2324 1.1.1.1.2.2 perseant }
2325 1.1.1.1.2.2 perseant demand_empty_rest_of_line ();
2326 1.1.1.1.2.2 perseant
2327 1.1.1.1.2.2 perseant if (!proc_endp_status)
2328 1.1.1.1.2.2 perseant {
2329 1.1.1.1.2.2 perseant as_warn (".endp directive doesn't follow .proc -- ignoring ");
2330 1.1.1.1.2.2 perseant return;
2331 1.1.1.1.2.2 perseant }
2332 1.1.1.1.2.2 perseant
2333 1.1.1.1.2.2 perseant proc_endp_status = 0;
2334 1.1.1.1.2.2 perseant
2335 1.1.1.1.2.2 perseant /* TB begin : add BSF_FUNCTION attribute to last_proc_sym symbol */
2336 1.1.1.1.2.2 perseant if (size_type_function)
2337 1.1.1.1.2.2 perseant {
2338 1.1.1.1.2.2 perseant if (!last_proc_sym)
2339 1.1.1.1.2.2 perseant {
2340 1.1.1.1.2.2 perseant as_bad ("Cannot set function attributes (bad symbol)");
2341 1.1.1.1.2.2 perseant return;
2342 1.1.1.1.2.2 perseant }
2343 1.1.1.1.2.2 perseant
2344 1.1.1.1.2.2 perseant /* last_proc_sym->symbol.flags |= BSF_FUNCTION; */
2345 1.1.1.1.2.2 perseant symbol_get_bfdsym (last_proc_sym)->flags |= BSF_FUNCTION;
2346 1.1.1.1.2.2 perseant /* Add .size funcname,.-funcname in order to add size
2347 1.1.1.1.2.2 perseant * attribute to the current function */
2348 1.1.1.1.2.2 perseant {
2349 1.1.1.1.2.2 perseant const int newdirective_sz =
2350 1.1.1.1.2.2 perseant strlen (S_GET_NAME (last_proc_sym)) + strlen (MINUSEXPR) + 1;
2351 1.1.1.1.2.2 perseant char *newdirective = malloc (newdirective_sz);
2352 1.1.1.1.2.2 perseant char *savep = input_line_pointer;
2353 1.1.1.1.2.2 perseant expressionS exp;
2354 1.1.1.1.2.2 perseant
2355 1.1.1.1.2.2 perseant memset (newdirective, 0, newdirective_sz);
2356 1.1.1.1.2.2 perseant
2357 1.1.1.1.2.2 perseant /* BUILD :".-funcname" expression */
2358 1.1.1.1.2.2 perseant strcat (newdirective, MINUSEXPR);
2359 1.1.1.1.2.2 perseant strcat (newdirective, S_GET_NAME (last_proc_sym));
2360 1.1.1.1.2.2 perseant input_line_pointer = newdirective;
2361 1.1.1.1.2.2 perseant expression (&exp);
2362 1.1.1.1.2.2 perseant
2363 1.1.1.1.2.2 perseant if (exp.X_op == O_constant)
2364 1.1.1.1.2.2 perseant {
2365 1.1.1.1.2.2 perseant S_SET_SIZE (last_proc_sym, exp.X_add_number);
2366 1.1.1.1.2.2 perseant if (symbol_get_obj (last_proc_sym)->size)
2367 1.1.1.1.2.2 perseant {
2368 1.1.1.1.2.2 perseant xfree (symbol_get_obj (last_proc_sym)->size);
2369 1.1.1.1.2.2 perseant symbol_get_obj (last_proc_sym)->size = NULL;
2370 1.1.1.1.2.2 perseant }
2371 1.1.1.1.2.2 perseant }
2372 1.1.1.1.2.2 perseant else
2373 1.1.1.1.2.2 perseant {
2374 1.1.1.1.2.2 perseant symbol_get_obj (last_proc_sym)->size =
2375 1.1.1.1.2.2 perseant (expressionS *) xmalloc (sizeof (expressionS));
2376 1.1.1.1.2.2 perseant *symbol_get_obj (last_proc_sym)->size = exp;
2377 1.1.1.1.2.2 perseant }
2378 1.1.1.1.2.2 perseant
2379 1.1.1.1.2.2 perseant /* just restore the real input pointer */
2380 1.1.1.1.2.2 perseant input_line_pointer = savep;
2381 1.1.1.1.2.2 perseant free (newdirective);
2382 1.1.1.1.2.2 perseant }
2383 1.1.1.1.2.2 perseant }
2384 1.1.1.1.2.2 perseant /* TB end */
2385 1.1.1.1.2.2 perseant
2386 1.1.1.1.2.2 perseant last_proc_sym = NULL;
2387 1.1.1.1.2.2 perseant }
2388 1.1.1.1.2.2 perseant
2389 1.1.1.1.2.2 perseant static void
2390 1.1.1.1.2.2 perseant kvx_proc (int start ATTRIBUTE_UNUSED)
2391 1.1.1.1.2.2 perseant {
2392 1.1.1.1.2.2 perseant char c;
2393 1.1.1.1.2.2 perseant char *name;
2394 1.1.1.1.2.2 perseant /* there may be several names separated by commas... */
2395 1.1.1.1.2.2 perseant while (1)
2396 1.1.1.1.2.2 perseant {
2397 1.1.1.1.2.2 perseant SKIP_WHITESPACE ();
2398 1.1.1.1.2.2 perseant c = get_symbol_name (&name);
2399 1.1.1.1.2.2 perseant (void) restore_line_pointer (c);
2400 1.1.1.1.2.2 perseant
2401 1.1.1.1.2.2 perseant SKIP_WHITESPACE ();
2402 1.1.1.1.2.2 perseant if (*input_line_pointer != ',')
2403 1.1.1.1.2.2 perseant break;
2404 1.1.1.1.2.2 perseant ++input_line_pointer;
2405 1.1.1.1.2.2 perseant }
2406 1.1.1.1.2.2 perseant demand_empty_rest_of_line ();
2407 1.1.1.1.2.2 perseant
2408 1.1.1.1.2.2 perseant if (proc_endp_status)
2409 1.1.1.1.2.2 perseant {
2410 1.1.1.1.2.2 perseant as_warn (".proc follows .proc -- ignoring");
2411 1.1.1.1.2.2 perseant return;
2412 1.1.1.1.2.2 perseant }
2413 1.1.1.1.2.2 perseant
2414 1.1.1.1.2.2 perseant proc_endp_status = 1;
2415 1.1.1.1.2.2 perseant
2416 1.1.1.1.2.2 perseant /* this code emit a global symbol to mark the end of each function */
2417 1.1.1.1.2.2 perseant /* the symbol emitted has a name formed by the original function name */
2418 1.1.1.1.2.2 perseant /* concatenated with $endproc so if _foo is a function name the symbol */
2419 1.1.1.1.2.2 perseant /* marking the end of it is _foo$endproc */
2420 1.1.1.1.2.2 perseant /* It is also required for generation of .size directive in kvx_endp() */
2421 1.1.1.1.2.2 perseant
2422 1.1.1.1.2.2 perseant if (size_type_function)
2423 1.1.1.1.2.2 perseant update_last_proc_sym = 1;
2424 1.1.1.1.2.2 perseant }
2425 1.1.1.1.2.2 perseant
2426 1.1.1.1.2.2 perseant int
2427 1.1.1.1.2.2 perseant kvx_force_reloc (fixS * fixP)
2428 1.1.1.1.2.2 perseant {
2429 1.1.1.1.2.2 perseant symbolS *sym;
2430 1.1.1.1.2.2 perseant asection *symsec;
2431 1.1.1.1.2.2 perseant
2432 1.1.1.1.2.2 perseant if (generic_force_reloc (fixP))
2433 1.1.1.1.2.2 perseant return 1;
2434 1.1.1.1.2.2 perseant
2435 1.1.1.1.2.2 perseant switch (fixP->fx_r_type)
2436 1.1.1.1.2.2 perseant {
2437 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_32_GOTOFF:
2438 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOTOFF_UP27:
2439 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOTOFF_LO10:
2440 1.1.1.1.2.2 perseant
2441 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_64_GOTOFF:
2442 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOTOFF_UP27:
2443 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOTOFF_LO10:
2444 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOTOFF_EX6:
2445 1.1.1.1.2.2 perseant
2446 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_32_GOT:
2447 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_64_GOT:
2448 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOT_UP27:
2449 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOT_LO10:
2450 1.1.1.1.2.2 perseant
2451 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_GLOB_DAT:
2452 1.1.1.1.2.2 perseant return 1;
2453 1.1.1.1.2.2 perseant default:
2454 1.1.1.1.2.2 perseant return 0;
2455 1.1.1.1.2.2 perseant }
2456 1.1.1.1.2.2 perseant
2457 1.1.1.1.2.2 perseant sym = fixP->fx_addsy;
2458 1.1.1.1.2.2 perseant if (sym)
2459 1.1.1.1.2.2 perseant {
2460 1.1.1.1.2.2 perseant symsec = S_GET_SEGMENT (sym);
2461 1.1.1.1.2.2 perseant /* if (bfd_is_abs_section (symsec)) return 0; */
2462 1.1.1.1.2.2 perseant if (!SEG_NORMAL (symsec))
2463 1.1.1.1.2.2 perseant return 0;
2464 1.1.1.1.2.2 perseant }
2465 1.1.1.1.2.2 perseant return 1;
2466 1.1.1.1.2.2 perseant }
2467 1.1.1.1.2.2 perseant
2468 1.1.1.1.2.2 perseant int
2469 1.1.1.1.2.2 perseant kvx_force_reloc_sub_same (fixS * fixP, segT sec)
2470 1.1.1.1.2.2 perseant {
2471 1.1.1.1.2.2 perseant symbolS *sym;
2472 1.1.1.1.2.2 perseant asection *symsec;
2473 1.1.1.1.2.2 perseant const char *sec_name = NULL;
2474 1.1.1.1.2.2 perseant
2475 1.1.1.1.2.2 perseant if (generic_force_reloc (fixP))
2476 1.1.1.1.2.2 perseant return 1;
2477 1.1.1.1.2.2 perseant
2478 1.1.1.1.2.2 perseant switch (fixP->fx_r_type)
2479 1.1.1.1.2.2 perseant {
2480 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_32_GOTOFF:
2481 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOTOFF_UP27:
2482 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOTOFF_LO10:
2483 1.1.1.1.2.2 perseant
2484 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_64_GOTOFF:
2485 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOTOFF_UP27:
2486 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOTOFF_LO10:
2487 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S43_GOTOFF_EX6:
2488 1.1.1.1.2.2 perseant
2489 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_32_GOT:
2490 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_64_GOT:
2491 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOT_UP27:
2492 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_GOT_LO10:
2493 1.1.1.1.2.2 perseant
2494 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_LO10:
2495 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_S37_UP27:
2496 1.1.1.1.2.2 perseant
2497 1.1.1.1.2.2 perseant case BFD_RELOC_KVX_GLOB_DAT:
2498 1.1.1.1.2.2 perseant return 1;
2499 1.1.1.1.2.2 perseant
2500 1.1.1.1.2.2 perseant default:
2501 1.1.1.1.2.2 perseant return 0;
2502 1.1.1.1.2.2 perseant }
2503 1.1.1.1.2.2 perseant
2504 1.1.1.1.2.2 perseant sym = fixP->fx_addsy;
2505 1.1.1.1.2.2 perseant if (sym)
2506 1.1.1.1.2.2 perseant {
2507 1.1.1.1.2.2 perseant symsec = S_GET_SEGMENT (sym);
2508 1.1.1.1.2.2 perseant /* if (bfd_is_abs_section (symsec)) return 0; */
2509 1.1.1.1.2.2 perseant if (!SEG_NORMAL (symsec))
2510 1.1.1.1.2.2 perseant return 0;
2511 1.1.1.1.2.2 perseant
2512 1.1.1.1.2.2 perseant /*
2513 1.1.1.1.2.2 perseant * for .debug_arrange, .debug_frame, .eh_frame sections, containing
2514 1.1.1.1.2.2 perseant * expressions of the form "sym2 - sym1 + addend", solve them even when
2515 1.1.1.1.2.2 perseant * --emit-all-relocs is set. Otherwise, a relocation on two symbols
2516 1.1.1.1.2.2 perseant * is necessary and fails at elf level. Binopt should not be impacted by
2517 1.1.1.1.2.2 perseant * the resolution of this relocatable expression on symbols inside a
2518 1.1.1.1.2.2 perseant * function.
2519 1.1.1.1.2.2 perseant */
2520 1.1.1.1.2.2 perseant sec_name = segment_name (sec);
2521 1.1.1.1.2.2 perseant if ((strcmp (sec_name, ".eh_frame") == 0) ||
2522 1.1.1.1.2.2 perseant (strcmp (sec_name, ".except_table") == 0) ||
2523 1.1.1.1.2.2 perseant (strncmp (sec_name, ".debug_", sizeof (".debug_")) == 0))
2524 1.1.1.1.2.2 perseant return 0;
2525 1.1.1.1.2.2 perseant }
2526 1.1.1.1.2.2 perseant return 1;
2527 1.1.1.1.2.2 perseant }
2528 1.1.1.1.2.2 perseant
2529 1.1.1.1.2.2 perseant /* Implement HANDLE_ALIGN. */
2530 1.1.1.1.2.2 perseant
2531 1.1.1.1.2.2 perseant static void
2532 1.1.1.1.2.2 perseant kvx_make_nops (char *buf, bfd_vma bytes)
2533 1.1.1.1.2.2 perseant {
2534 1.1.1.1.2.2 perseant bfd_vma i = 0;
2535 1.1.1.1.2.2 perseant unsigned int j;
2536 1.1.1.1.2.2 perseant
2537 1.1.1.1.2.2 perseant static unsigned int nop_single = 0;
2538 1.1.1.1.2.2 perseant
2539 1.1.1.1.2.2 perseant if (!nop_single)
2540 1.1.1.1.2.2 perseant {
2541 1.1.1.1.2.2 perseant const struct kvxopc *opcode =
2542 1.1.1.1.2.2 perseant (struct kvxopc *) str_hash_find (env.opcode_hash, "nop");
2543 1.1.1.1.2.2 perseant
2544 1.1.1.1.2.2 perseant if (opcode == NULL)
2545 1.1.1.1.2.2 perseant as_fatal
2546 1.1.1.1.2.2 perseant ("internal error: could not find opcode for 'nop' during padding");
2547 1.1.1.1.2.2 perseant
2548 1.1.1.1.2.2 perseant nop_single = opcode->codewords[0].opcode;
2549 1.1.1.1.2.2 perseant }
2550 1.1.1.1.2.2 perseant
2551 1.1.1.1.2.2 perseant /* KVX instructions are always 4-bytes aligned. If we are at a position */
2552 1.1.1.1.2.2 perseant /* that is not 4 bytes aligned, it means this is not part of an instruction, */
2553 1.1.1.1.2.2 perseant /* so it is safe to use a zero byte for padding. */
2554 1.1.1.1.2.2 perseant
2555 1.1.1.1.2.2 perseant for (j = bytes % 4; j > 0; j--)
2556 1.1.1.1.2.2 perseant buf[i++] = 0;
2557 1.1.1.1.2.2 perseant
2558 1.1.1.1.2.2 perseant for (j = 0; j < (bytes - i); j += 4)
2559 1.1.1.1.2.2 perseant {
2560 1.1.1.1.2.2 perseant unsigned nop = nop_single;
2561 1.1.1.1.2.2 perseant
2562 1.1.1.1.2.2 perseant // nop has bundle end only if #4 nop or last padding nop.
2563 1.1.1.1.2.2 perseant // Sets the parallel bit when neither conditions are matched.
2564 1.1.1.1.2.2 perseant // 4*4 = biggest nop bundle we can get
2565 1.1.1.1.2.2 perseant // 12 = offset when writting the last nop possible in a 4 nops bundle
2566 1.1.1.1.2.2 perseant // bytes-i-4 = offset for the last 4-words in the padding
2567 1.1.1.1.2.2 perseant if (j % (4 * 4) != 12 && j != (bytes - i - 4))
2568 1.1.1.1.2.2 perseant nop |= PARALLEL_BIT;
2569 1.1.1.1.2.2 perseant
2570 1.1.1.1.2.2 perseant memcpy (buf + i + j, &nop, sizeof (nop));
2571 1.1.1.1.2.2 perseant }
2572 1.1.1.1.2.2 perseant }
2573 1.1.1.1.2.2 perseant
2574 1.1.1.1.2.2 perseant /* Pads code section with bundle of nops when possible, 0 if not. */
2575 1.1.1.1.2.2 perseant void
2576 1.1.1.1.2.2 perseant kvx_handle_align (fragS *fragP)
2577 1.1.1.1.2.2 perseant {
2578 1.1.1.1.2.2 perseant switch (fragP->fr_type)
2579 1.1.1.1.2.2 perseant {
2580 1.1.1.1.2.2 perseant case rs_align_code:
2581 1.1.1.1.2.2 perseant {
2582 1.1.1.1.2.2 perseant bfd_signed_vma bytes = (fragP->fr_next->fr_address
2583 1.1.1.1.2.2 perseant - fragP->fr_address - fragP->fr_fix);
2584 1.1.1.1.2.2 perseant char *p = fragP->fr_literal + fragP->fr_fix;
2585 1.1.1.1.2.2 perseant
2586 1.1.1.1.2.2 perseant if (bytes <= 0)
2587 1.1.1.1.2.2 perseant break;
2588 1.1.1.1.2.2 perseant
2589 1.1.1.1.2.2 perseant /* Insert zeros or nops to get 4 byte alignment. */
2590 1.1.1.1.2.2 perseant kvx_make_nops (p, bytes);
2591 1.1.1.1.2.2 perseant fragP->fr_fix += bytes;
2592 1.1.1.1.2.2 perseant }
2593 1.1.1.1.2.2 perseant break;
2594 1.1.1.1.2.2 perseant
2595 1.1.1.1.2.2 perseant default:
2596 1.1.1.1.2.2 perseant break;
2597 1.1.1.1.2.2 perseant }
2598 1.1.1.1.2.2 perseant }
2599 1.1.1.1.2.2 perseant /*
2600 1.1.1.1.2.2 perseant * This is just used for debugging
2601 1.1.1.1.2.2 perseant */
2602 1.1.1.1.2.2 perseant
2603 1.1.1.1.2.2 perseant ATTRIBUTE_UNUSED
2604 1.1.1.1.2.2 perseant static void
2605 1.1.1.1.2.2 perseant print_operand (expressionS * e, FILE * out)
2606 1.1.1.1.2.2 perseant {
2607 1.1.1.1.2.2 perseant if (e)
2608 1.1.1.1.2.2 perseant {
2609 1.1.1.1.2.2 perseant switch (e->X_op)
2610 1.1.1.1.2.2 perseant {
2611 1.1.1.1.2.2 perseant case O_register:
2612 1.1.1.1.2.2 perseant fprintf (out, "%s", kvx_registers[e->X_add_number].name);
2613 1.1.1.1.2.2 perseant break;
2614 1.1.1.1.2.2 perseant
2615 1.1.1.1.2.2 perseant case O_constant:
2616 1.1.1.1.2.2 perseant if (e->X_add_symbol)
2617 1.1.1.1.2.2 perseant {
2618 1.1.1.1.2.2 perseant if (e->X_add_number)
2619 1.1.1.1.2.2 perseant fprintf (out, "(%s + %d)", S_GET_NAME (e->X_add_symbol),
2620 1.1.1.1.2.2 perseant (int) e->X_add_number);
2621 1.1.1.1.2.2 perseant else
2622 1.1.1.1.2.2 perseant fprintf (out, "%s", S_GET_NAME (e->X_add_symbol));
2623 1.1.1.1.2.2 perseant }
2624 1.1.1.1.2.2 perseant else
2625 1.1.1.1.2.2 perseant fprintf (out, "%d", (int) e->X_add_number);
2626 1.1.1.1.2.2 perseant break;
2627 1.1.1.1.2.2 perseant
2628 1.1.1.1.2.2 perseant case O_symbol:
2629 1.1.1.1.2.2 perseant if (e->X_add_symbol)
2630 1.1.1.1.2.2 perseant {
2631 1.1.1.1.2.2 perseant if (e->X_add_number)
2632 1.1.1.1.2.2 perseant fprintf (out, "(%s + %d)", S_GET_NAME (e->X_add_symbol),
2633 1.1.1.1.2.2 perseant (int) e->X_add_number);
2634 1.1.1.1.2.2 perseant else
2635 1.1.1.1.2.2 perseant fprintf (out, "%s", S_GET_NAME (e->X_add_symbol));
2636 1.1.1.1.2.2 perseant }
2637 1.1.1.1.2.2 perseant else
2638 1.1.1.1.2.2 perseant fprintf (out, "%d", (int) e->X_add_number);
2639 1.1.1.1.2.2 perseant break;
2640 1.1.1.1.2.2 perseant
2641 1.1.1.1.2.2 perseant default:
2642 1.1.1.1.2.2 perseant fprintf (out, "o,ptype-%d", e->X_op);
2643 1.1.1.1.2.2 perseant }
2644 1.1.1.1.2.2 perseant }
2645 1.1.1.1.2.2 perseant }
2646 1.1.1.1.2.2 perseant
2647 1.1.1.1.2.2 perseant void
2648 1.1.1.1.2.2 perseant kvx_cfi_frame_initial_instructions (void)
2649 1.1.1.1.2.2 perseant {
2650 1.1.1.1.2.2 perseant cfi_add_CFA_def_cfa (KVX_SP_REGNO, 0);
2651 1.1.1.1.2.2 perseant }
2652 1.1.1.1.2.2 perseant
2653 1.1.1.1.2.2 perseant int
2654 1.1.1.1.2.2 perseant kvx_regname_to_dw2regnum (const char *regname)
2655 1.1.1.1.2.2 perseant {
2656 1.1.1.1.2.2 perseant unsigned int regnum = -1;
2657 1.1.1.1.2.2 perseant const char *p;
2658 1.1.1.1.2.2 perseant char *q;
2659 1.1.1.1.2.2 perseant
2660 1.1.1.1.2.2 perseant if (regname[0] == 'r')
2661 1.1.1.1.2.2 perseant {
2662 1.1.1.1.2.2 perseant p = regname + 1;
2663 1.1.1.1.2.2 perseant regnum = strtoul (p, &q, 10);
2664 1.1.1.1.2.2 perseant if (p == q || *q || regnum >= 64)
2665 1.1.1.1.2.2 perseant return -1;
2666 1.1.1.1.2.2 perseant }
2667 1.1.1.1.2.2 perseant return regnum;
2668 1.1.1.1.2.2 perseant }
2669