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