Adds the new Fields and Operand types for the new instructions in Armv8.4-a.
[deliverable/binutils-gdb.git] / gas / config / obj-evax.c
1 /* obj-evax.c - EVAX (openVMS/Alpha) object file format.
2 Copyright (C) 1996-2017 Free Software Foundation, Inc.
3 Contributed by Klaus Kämpf (kkaempf@progis.de) of
4 proGIS Software, Aachen, Germany.
5 Extensively enhanced by Douglas Rupp of AdaCore.
6
7 This file is part of GAS, the GNU Assembler
8
9 GAS is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
13
14 GAS is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GAS; see the file COPYING. If not, write to
21 the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
22 MA 02110-1301, USA. */
23
24 #define OBJ_HEADER "obj-evax.h"
25
26 #include "as.h"
27 #include "bfd.h"
28 #include "vms.h"
29 #include "subsegs.h"
30 #include "struc-symbol.h"
31 #include "safe-ctype.h"
32
33 static void s_evax_weak (int);
34 static unsigned int crc32 (unsigned char *, int);
35 static char *encode_32 (unsigned int);
36 static char *encode_16 (unsigned int);
37 static int decode_16 (const char *);
38
39 const pseudo_typeS obj_pseudo_table[] =
40 {
41 { "weak", s_evax_weak, 0},
42 {0, 0, 0},
43 }; /* obj_pseudo_table */
44
45 void obj_read_begin_hook () {}
46
47 /* Handle the weak specific pseudo-op. */
48
49 static void
50 s_evax_weak (int ignore ATTRIBUTE_UNUSED)
51 {
52 char *name;
53 int c;
54 symbolS *symbolP;
55 char *stop = NULL;
56 char stopc;
57
58 if (flag_mri)
59 stop = mri_comment_field (&stopc);
60
61 do
62 {
63 c = get_symbol_name (&name);
64 symbolP = symbol_find_or_make (name);
65 (void) restore_line_pointer (c);
66 SKIP_WHITESPACE ();
67 S_SET_WEAK (symbolP);
68 if (c == ',')
69 {
70 input_line_pointer++;
71 SKIP_WHITESPACE ();
72 if (*input_line_pointer == '\n')
73 c = '\n';
74 }
75 }
76 while (c == ',');
77
78 if (flag_mri)
79 mri_comment_end (stop, stopc);
80
81 demand_empty_rest_of_line ();
82 }
83
84 void
85 evax_symbol_new_hook (symbolS *sym)
86 {
87 struct evax_private_udata_struct *udata;
88
89 udata = XNEW (struct evax_private_udata_struct);
90
91 udata->bsym = symbol_get_bfdsym (sym);
92 udata->enbsym = NULL;
93 udata->origname = xstrdup (S_GET_NAME (sym));
94 udata->lkindex = 0;
95 symbol_get_bfdsym(sym)->udata.p = (PTR) udata;
96 }
97
98 void
99 evax_frob_symbol (symbolS *sym, int *punt)
100 {
101 const char *symname = S_GET_NAME (sym);
102 int symlen = strlen (symname);
103 asymbol *symbol = symbol_get_bfdsym (sym);
104
105 if (symlen > 4
106 && strcmp (symname + symlen - 4, "..en") == 0
107 && S_GET_SEGMENT (sym) == undefined_section)
108 {
109 symbol_clear_used_in_reloc (sym);
110 *punt = 1;
111 }
112
113 else if ((symbol->flags & BSF_GLOBAL) && (symbol->flags & BSF_FUNCTION))
114 {
115 struct evax_private_udata_struct *udata
116 = (struct evax_private_udata_struct *)symbol->udata.p;
117
118 /* Fix up equates of function definitions. */
119 while (udata->enbsym == NULL)
120 {
121 /* ??? Equates have been resolved at this point so their
122 expression is O_constant; but they previously were
123 O_symbol and we hope the equated symbol is still there. */
124 sym = symbol_get_value_expression (sym)->X_add_symbol;
125 if (sym == NULL)
126 {
127 as_bad (_("no entry symbol for global function '%s'"), symname);
128 return;
129 }
130 symbol = symbol_get_bfdsym (sym);
131 udata->enbsym
132 = ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym;
133 }
134 }
135 }
136
137 void
138 evax_frob_file_before_adjust (void)
139 {
140 struct alpha_linkage_fixups *l;
141 segT current_section = now_seg;
142 int current_subsec = now_subseg;
143 segment_info_type *seginfo;
144 int linkage_index = 1;
145
146 subseg_set (alpha_link_section, 0);
147 seginfo = seg_info (alpha_link_section);
148
149 /* Handle .linkage fixups. */
150 for (l = alpha_linkage_fixup_root; l != NULL; l = l->next)
151 {
152 if (S_GET_SEGMENT (l->fixp->fx_addsy) == alpha_link_section)
153 {
154 /* The symbol is defined in the file. The linkage entry decays to
155 two relocs. */
156 symbolS *entry_sym;
157 fixS *fixpentry, *fixppdesc, *fixtail;
158
159 fixtail = seginfo->fix_tail;
160
161 /* Replace the linkage with the local symbols */
162 entry_sym = symbol_find
163 (((struct evax_private_udata_struct *)symbol_get_bfdsym (l->fixp->fx_addsy)->udata.p)->enbsym->name);
164 if (!entry_sym)
165 abort ();
166 fixpentry = fix_new (l->fixp->fx_frag, l->fixp->fx_where, 8,
167 entry_sym, l->fixp->fx_offset, 0,
168 BFD_RELOC_64);
169 fixppdesc = fix_new (l->fixp->fx_frag, l->fixp->fx_where + 8, 8,
170 l->fixp->fx_addsy, l->fixp->fx_offset, 0,
171 BFD_RELOC_64);
172 l->fixp->fx_size = 0;
173 l->fixp->fx_done = 1;
174
175 /* If not already at the tail, splice the new fixups into
176 the chain right after the one we are nulling out */
177 if (fixtail != l->fixp)
178 {
179 fixppdesc->fx_next = l->fixp->fx_next;
180 l->fixp->fx_next = fixpentry;
181 fixtail->fx_next = 0;
182 seginfo->fix_tail = fixtail;
183 }
184 }
185 else
186 {
187 /* Assign a linkage index. */
188 ((struct evax_private_udata_struct *)
189 symbol_get_bfdsym (l->label)->udata.p)->lkindex = linkage_index;
190
191 l->fixp->fx_addnumber = linkage_index;
192
193 linkage_index += 2;
194 }
195 }
196
197 subseg_set (current_section, current_subsec);
198 }
199
200 void
201 evax_frob_file_before_fix (void)
202 {
203 /* Now that the fixups are done earlier, we need to transfer the values
204 into the BFD symbols before calling fix_segment (ideally should not
205 be done also later). */
206 if (symbol_rootP)
207 {
208 symbolS *symp;
209
210 /* Set the value into the BFD symbol. Up til now the value
211 has only been kept in the gas symbolS struct. */
212 for (symp = symbol_rootP; symp; symp = symbol_next (symp))
213 symbol_get_bfdsym (symp)->value = S_GET_VALUE (symp);
214 }
215 }
216
217 /* The length is computed from the maximum allowable length of 64 less the
218 4 character ..xx extension that must be preserved (removed before
219 crunching and appended back on afterwards). The $<nnn>.. prefix is
220 also removed and prepened back on, but doesn't enter into the length
221 computation because symbols with that prefix are always resolved
222 by the assembler and will never appear in the symbol table. At least
223 I hope that's true, TBD. */
224 #define MAX_LABEL_LENGTH 60
225
226 static char *shorten_identifier (char *);
227 static int is_truncated_identifier (char *);
228
229 char *
230 evax_shorten_name (char *id)
231 {
232 int prefix_dotdot = 0;
233 char prefix [64];
234 int len = strlen (id);
235 int suffix_dotdot = len;
236 char suffix [64];
237 char *base_id;
238
239 /* This test may be too conservative. */
240 if (len <= MAX_LABEL_LENGTH)
241 return id;
242
243 suffix [0] = 0;
244 prefix [0] = 0;
245
246 /* Check for ..xx suffix and save it. */
247 if (strncmp (&id[len-4], "..", 2) == 0)
248 {
249 suffix_dotdot = len - 4;
250 strncpy (suffix, &id[len-4], 4);
251 suffix [4] = 0;
252 }
253
254 /* Check for $<nnn>.. prefix and save it. */
255 if ((id[0] == '$') && ISDIGIT (id[1]))
256 {
257 int i;
258
259 for (i=2; i < len; i++)
260 {
261 if (!ISDIGIT (id[i]))
262 {
263 if (id[i] == '.' && id [i+1] == '.')
264 {
265 prefix_dotdot = i+2;
266 strncpy (prefix, id, prefix_dotdot);
267 prefix [prefix_dotdot] = 0;
268 }
269 break;
270 }
271 }
272 }
273
274 /* We only need worry about crunching the base symbol. */
275 base_id = xmemdup0 (&id[prefix_dotdot], suffix_dotdot - prefix_dotdot);
276
277 if (strlen (base_id) > MAX_LABEL_LENGTH)
278 {
279 char new_id [4096];
280 char *return_id;
281
282 strcpy (new_id, base_id);
283
284 /* Shorten it. */
285 strcpy (new_id, shorten_identifier (new_id));
286
287 /* Prepend back the prefix if there was one. */
288 if (prefix_dotdot)
289 {
290 memmove (&new_id [prefix_dotdot], new_id, strlen (new_id) + 1);
291 strncpy (new_id, prefix, prefix_dotdot);
292 }
293
294 /* Append back the suffix if there was one. */
295 if (strlen (suffix))
296 strcat (new_id, suffix);
297
298 /* Save it on the heap and return. */
299 return_id = xstrdup (new_id);
300
301 return return_id;
302 }
303 else
304 return id;
305 }
306
307 /* The code below implements a mechanism for truncating long
308 identifiers to an arbitrary length (set by MAX_LABEL_LENGTH).
309
310 It attempts to make each truncated identifier unique by replacing
311 part of the identifier with an encoded 32-bit CRC and an associated
312 checksum (the checksum is used as a way to determine that the name
313 was truncated).
314
315 Note that both a portion of the start and of the end of the
316 identifier may be kept. The macro ID_SUFFIX_LENGTH will return the
317 number of characters in the suffix of the identifier that should be
318 kept.
319
320 The portion of the identifier that is going to be removed is
321 checksummed. The checksum is then encoded as a 5-character string,
322 the characters of which are then summed. This sum is then encoded
323 as a 3-character string. Finally, the original length of the
324 identifier is encoded as a 3-character string.
325
326 These three strings are then concatenated together (along with an _h
327 which further designates that the name was truncated):
328
329 "original_identifier"_haaaaabbbccc
330
331 aaaaa = 32-bit CRC
332 bbb = length of original identifier
333 ccc = sum of 32-bit CRC characters
334
335 The resulting identifier will be MAX_LABEL_LENGTH characters long.
336
337 */
338
339
340 /* Table used to convert an integer into a string. */
341
342 static const char codings[] = {
343 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
344 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
345 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
346 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
347 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '_'};
348
349 /* The number of codings in the above table. */
350 static const int number_of_codings = sizeof (codings) / sizeof (char);
351
352 /* Table used by decode_16 () to convert an encoded string back into
353 an integer. */
354 static char decodings[256];
355
356 /* Table used by the crc32 function to calculate the checksum. */
357 static unsigned int crc32_table[256] = {0, 0};
358
359 /* Given a string in BUF, calculate a 32-bit CRC for it.
360
361 This is used as a reasonably unique hash for the given string. */
362
363 static unsigned int
364 crc32 (unsigned char *buf, int len)
365 {
366 unsigned int crc = 0xffffffff;
367
368 if (! crc32_table[1])
369 {
370 /* Initialize the CRC table and the decoding table. */
371 int i, j;
372 unsigned int c;
373
374 for (i = 0; i < 256; i++)
375 {
376 for (c = i << 24, j = 8; j > 0; --j)
377 c = c & 0x80000000 ? (c << 1) ^ 0x04c11db7 : (c << 1);
378 crc32_table[i] = c;
379 decodings[i] = 0;
380 }
381 for (i = 0; i < number_of_codings; i++)
382 decodings[codings[i] & 255] = i;
383 }
384
385 while (len--)
386 {
387 crc = (crc << 8) ^ crc32_table[(crc >> 24) ^ *buf];
388 buf++;
389 }
390 return crc;
391 }
392
393 /* Encode the lower 32 bits of VALUE as a 5-character string. */
394
395 static char *
396 encode_32 (unsigned int value)
397 {
398 static char res[6];
399 int x;
400
401 res[5] = 0;
402 for(x = 0; x < 5; x++)
403 {
404 res[x] = codings[value % number_of_codings];
405 value = value / number_of_codings;
406 }
407 return res;
408 }
409
410 /* Encode the lower 16 bits of VALUE as a 3-character string. */
411
412 static char *
413 encode_16 (unsigned int value)
414 {
415 static char res[4];
416 int x;
417
418 res[3] = 0;
419 for(x = 0; x < 3; x++)
420 {
421 res[x] = codings[value % number_of_codings];
422 value = value / number_of_codings;
423 }
424 return res;
425 }
426
427 /* Convert the encoded string obtained from encode_16 () back into a
428 16-bit integer. */
429
430 static int
431 decode_16 (const char *string)
432 {
433 return decodings[(int) string[2]] * number_of_codings * number_of_codings
434 + decodings[(int) string[1]] * number_of_codings
435 + decodings[(int) string[0]];
436 }
437
438 /* ID_SUFFIX_LENGTH is used to determine how many characters in the
439 suffix of the identifier are to be preserved, if any. */
440
441 #ifndef ID_SUFFIX_LENGTH
442 #define ID_SUFFIX_LENGTH(ID) (0)
443 #endif
444
445 /* Return a reasonably-unique version of NAME that is less than or
446 equal to MAX_LABEL_LENGTH characters long. The string returned from
447 this function may be a copy of NAME; the function will never
448 actually modify the contents of NAME. */
449
450 static char newname[MAX_LABEL_LENGTH + 1];
451
452 static char *
453 shorten_identifier (char *name)
454 {
455 int crc, len, sum, x, final_len;
456 char *crc_chars;
457 int suffix_length = ID_SUFFIX_LENGTH (name);
458
459 if ((len = strlen (name)) <= MAX_LABEL_LENGTH)
460 return name;
461
462 final_len = MAX_LABEL_LENGTH - 2 - 5 - 3 - 3 - suffix_length;
463 crc = crc32 ((unsigned char *)name + final_len,
464 len - final_len - suffix_length);
465 crc_chars = encode_32 (crc);
466 sum = 0;
467 for (x = 0; x < 5; x++)
468 sum += crc_chars [x];
469 strncpy (newname, name, final_len);
470 newname [MAX_LABEL_LENGTH] = 0;
471 /* Now append the suffix of the original identifier, if any. */
472 if (suffix_length)
473 strncpy (newname + MAX_LABEL_LENGTH - suffix_length,
474 name + len - suffix_length,
475 suffix_length);
476 strncpy (newname + final_len, "_h", 2);
477 strncpy (newname + final_len + 2 , crc_chars, 5);
478 strncpy (newname + final_len + 2 + 5, encode_16 (len), 3);
479 strncpy (newname + final_len + 2 + 5 + 3, encode_16 (sum), 3);
480 if (!is_truncated_identifier (newname))
481 abort ();
482 return newname;
483 }
484
485 /* Determine whether or not ID is a truncated identifier, and return a
486 non-zero value if it is. */
487
488 static int
489 is_truncated_identifier (char *id)
490 {
491 char *ptr;
492 int len = strlen (id);
493 /* If it's not exactly MAX_LABEL_LENGTH characters long, it can't be
494 a truncated identifier. */
495 if (len != MAX_LABEL_LENGTH)
496 return 0;
497
498 /* Start scanning backwards for a _h. */
499 len = len - 3 - 3 - 5 - 2;
500 ptr = id + len;
501 while (ptr >= id)
502 {
503 if (ptr[0] == '_' && ptr[1] == 'h')
504 {
505 /* Now see if the sum encoded in the identifier matches. */
506 int x, sum;
507 sum = 0;
508 for (x = 0; x < 5; x++)
509 sum += ptr[x + 2];
510 /* If it matches, this is probably a truncated identifier. */
511 if (sum == decode_16 (ptr + 5 + 2 + 3))
512 return 1;
513 }
514 ptr--;
515 }
516 return 0;
517 }
518
519 /* end of obj-evax.c */
This page took 0.040784 seconds and 4 git commands to generate.