* config/obj-ecoff.c (get_tag): Save tag name in permanent memory
[deliverable/binutils-gdb.git] / gas / config / tc-hppa.c
1 /* tc-hppa.c -- Assemble for the PA
2 Copyright (C) 1989 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21 /*
22 HP PA-RISC support was contributed by the Center for Software Science
23 at the University of Utah.
24 */
25
26 #include <stdio.h>
27 #include <ctype.h>
28
29 #include "as.h"
30 #include "subsegs.h"
31
32 /* #include "../bfd/libhppa.h" */
33 /*
34 * Unwind table and descriptor.
35 */
36
37 struct unwind_desc
38 {
39 unsigned int cannot_unwind:1;
40 unsigned int millicode:1;
41 unsigned int millicode_save_rest:1;
42 unsigned int region_desc:2;
43 unsigned int save_sr:2;
44 unsigned int entry_fr:4; /* number saved */
45 unsigned int entry_gr:5; /* number saved */
46 unsigned int args_stored:1;
47 unsigned int call_fr:5;
48 unsigned int call_gr:5;
49 unsigned int save_sp:1;
50 unsigned int save_rp:1;
51 unsigned int save_rp_in_frame:1;
52 unsigned int extn_ptr_defined:1;
53 unsigned int cleanup_defined:1;
54
55 unsigned int hpe_interrupt_marker:1;
56 unsigned int hpux_interrupt_marker:1;
57 unsigned int reserved:3;
58 unsigned int frame_size:27;
59 };
60
61 typedef struct unwind_desc unwind_descS;
62
63 struct unwind_table
64 {
65 unsigned int start_offset; /* starting offset (from SR4) of applicable region */
66 unsigned int end_offset; /* ending offset (from SR4) of applicable region */
67 unwind_descS descriptor;
68 };
69
70 typedef struct unwind_table unwind_tableS;
71
72 /*
73 * This structure is used by the .callinfo, .enter, .leave pseudo-ops to
74 * control the entry and exit code they generate. It is also used in
75 * creation of the correct stack unwind descriptors.
76 *
77 * The fields in structure roughly correspond to the arguments available on the
78 * .callinfo pseudo-op.
79 */
80
81 struct call_info
82 {
83 int frame;
84 int entry_sr;
85 int makes_calls;
86 int hpux_int;
87 unwind_tableS ci_unwind; /* the unwind descriptor we are building */
88 symbolS *start_symbol; /* name of function (used in relocation info) */
89 symbolS *end_symbol; /* temporary symbol used to mark the */
90 /* end of the function (used in */
91 /* relocation info) */
92 fragS *start_frag; /* frag associated w/ start of this function */
93 fragS *end_frag; /* frag associated w/ end of this function */
94 fragS *start_offset_frag; /* frag for start offset of this descriptor */
95 int start_frag_where; /* where in start_offset_frag is start_offset */
96 fixS *start_fix; /* fixup for the start_offset */
97 fragS *end_offset_frag; /* frag for start offset of this descriptor */
98 int end_frag_where; /* where in end_offset_frag is end_offset */
99 fixS *end_fix; /* fixup for the end_offset */
100 struct call_info *ci_next; /* the next call_info structure */
101 };
102
103 typedef struct call_info call_infoS;
104
105 call_infoS *last_call_info;
106 call_infoS *call_info_root;
107 call_descS last_call_desc;
108
109 /* A structure used during assembly of individual instructions */
110
111 struct pa_it
112 {
113 char *error;
114 unsigned long opcode;
115 /* symbol_dictS *nlistp; *//*** used to be: struct nlist *nlistp; */
116 asymbol *nlistp;
117 expressionS exp;
118 int pcrel;
119 FP_Operand_Format fpof1; /* Floating Point Operand Format, operand 1 */
120 FP_Operand_Format fpof2; /* Floating Point Operand Format, operand 2 */
121 /* (used only for class 1 instructions -- */
122 /* the conversion instructions) */
123 #ifdef OBJ_SOM
124 long field_selector;
125 unsigned int reloc;
126 int code;
127 long arg_reloc;
128 unwind_descS unwind;
129 #endif
130 #ifdef OBJ_ELF
131 elf32_hppa_reloc_type reloc;
132 long field_selector;
133 int format;
134 long arg_reloc;
135 unwind_descS unwind;
136 #endif
137 };
138
139 extern struct pa_it the_insn;
140
141 /* careful, this file includes data *declarations* */
142 #include "opcode/hppa.h"
143
144 void md_begin ();
145 void md_end ();
146 void md_number_to_chars ();
147 void md_assemble ();
148 char *md_atof ();
149 void md_convert_frag ();
150 void md_create_short_jump ();
151 void md_create_long_jump ();
152 int md_estimate_size_before_relax ();
153 void md_number_to_imm ();
154 void md_number_to_disp ();
155 void md_number_to_field ();
156 void md_ri_to_chars ();
157 void emit_relocations ();
158 static void pa_ip ();
159
160 const relax_typeS md_relax_table[] =
161 {0};
162 /* handle of the OPCODE hash table */
163 static struct hash_control *op_hash = NULL;
164
165 int md_short_jump_size = 4;
166 int md_long_jump_size = 4;
167
168 /* This array holds the chars that always start a comment. If the
169 pre-processor is disabled, these aren't very useful */
170 const char comment_chars[] = ";"; /* JF removed '|' from comment_chars */
171
172 const pseudo_typeS
173 md_pseudo_table[] =
174 {
175 {"align", s_align_bytes, 0}, /* .align 4 means .align to 4-byte boundary */
176 {"ALIGN", s_align_bytes, 0}, /* .align 4 means .align to 4-byte boundary */
177 {"block", pa_block, 1},
178 {"BLOCK", pa_block, 1},
179 {"blockz", pa_block, 0},
180 {"BLOCKZ", pa_block, 0},
181 {"byte", pa_cons, 1},
182 {"BYTE", pa_cons, 1},
183 {"call", pa_call, 0},
184 {"CALL", pa_call, 0},
185 {"callinfo", pa_callinfo, 0},
186 {"CALLINFO", pa_callinfo, 0},
187 {"code", pa_code, 0},
188 {"CODE", pa_code, 0},
189 {"comm", pa_comm, 0},
190 {"COMM", pa_comm, 0},
191 {"copyright", pa_copyright, 0},
192 {"COPYRIGHT", pa_copyright, 0},
193 {"data", pa_data, 0},
194 {"DATA", pa_data, 0},
195 {"desc", pa_desc, 0},
196 {"DESC", pa_desc, 0},
197 {"double", pa_float_cons, 'd'},
198 {"DOUBLE", pa_float_cons, 'd'},
199 {"end", pa_end, 0},
200 {"END", pa_end, 0},
201 {"enter", pa_enter, 0},
202 {"ENTER", pa_enter, 0},
203 {"entry", pa_entry, 0},
204 {"ENTRY", pa_entry, 0},
205 {"equ", pa_equ, 0},
206 {"EQU", pa_equ, 0},
207 {"exit", pa_exit, 0},
208 {"EXIT", pa_exit, 0},
209 {"export", pa_export, 0},
210 {"EXPORT", pa_export, 0},
211 {"fill", pa_fill, 0},
212 {"FILL", pa_fill, 0},
213 {"float", pa_float_cons, 'f'},
214 {"FLOAT", pa_float_cons, 'f'},
215 {"half", pa_cons, 2},
216 {"HALF", pa_cons, 2},
217 {"import", pa_import, 0},
218 {"IMPORT", pa_import, 0},
219 {"int", pa_cons, 4},
220 {"INT", pa_cons, 4},
221 {"label", pa_label, 0},
222 {"LABEL", pa_label, 0},
223 {"lcomm", pa_lcomm, 0},
224 {"LCOMM", pa_lcomm, 0},
225 {"leave", pa_leave, 0},
226 {"LEAVE", pa_leave, 0},
227 {"long", pa_cons, 4},
228 {"LONG", pa_cons, 4},
229 {"lsym", pa_lsym, 0},
230 {"LSYM", pa_lsym, 0},
231 {"octa", pa_big_cons, 16},
232 {"OCTA", pa_big_cons, 16},
233 {"org", pa_origin, 0},
234 {"ORG", pa_origin, 0},
235 {"origin", pa_origin, 0},
236 {"ORIGIN", pa_origin, 0},
237 {"proc", pa_proc, 0},
238 {"PROC", pa_proc, 0},
239 {"procend", pa_procend, 0},
240 {"PROCEND", pa_procend, 0},
241 {"quad", pa_big_cons, 8},
242 {"QUAD", pa_big_cons, 8},
243 {"reg", pa_equ, 1}, /* very similar to .equ */
244 {"REG", pa_equ, 1}, /* very similar to .equ */
245 {"short", pa_cons, 2},
246 {"SHORT", pa_cons, 2},
247 {"single", pa_float_cons, 'f'},
248 {"SINGLE", pa_float_cons, 'f'},
249 {"space", pa_space, 0},
250 {"SPACE", pa_space, 0},
251 {"spnum", pa_spnum, 0},
252 {"SPNUM", pa_spnum, 0},
253 {"string", pa_stringer, 0},
254 {"STRING", pa_stringer, 0},
255 {"stringz", pa_stringer, 1},
256 {"STRINGZ", pa_stringer, 1},
257 {"subspa", pa_subspace, 0},
258 {"SUBSPA", pa_subspace, 0},
259 {"text", pa_text, 0},
260 {"TEXT", pa_text, 0},
261 {"version", pa_version, 0},
262 {"VERSION", pa_version, 0},
263 {"word", pa_cons, 4},
264 {"WORD", pa_cons, 4},
265 {NULL, 0, 0}
266 };
267
268 /* This array holds the chars that only start a comment at the beginning of
269 a line. If the line seems to have the form '# 123 filename'
270 .line and .file directives will appear in the pre-processed output */
271 /* Note that input_file.c hand checks for '#' at the beginning of the
272 first line of the input file. This is because the compiler outputs
273 #NO_APP at the beginning of its output. */
274 /* Also note that '/*' will always start a comment */
275 const char line_comment_chars[] = "#";
276
277 const char line_separator_chars[] = "!";
278
279 /* Chars that can be used to separate mant from exp in floating point nums */
280 const char EXP_CHARS[] = "eE";
281
282 /* Chars that mean this number is a floating point constant */
283 /* As in 0f12.456 */
284 /* or 0d1.2345e12 */
285 const char FLT_CHARS[] = "rRsSfFdDxXpP";
286
287 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
288 changed in read.c . Ideally it shouldn't have to know about it at all,
289 but nothing is ideal around here.
290 */
291
292 static unsigned char octal[256];
293 #ifndef isoctal
294 #define isoctal(c) octal[c]
295 #endif
296 static unsigned char toHex[256];
297
298 struct pa_it set_insn; /* this structure is defined above */
299
300 /* SKV 12/22/92. Added prev_insn, prev_fix, and initialized the_insn
301 so that we can recognize instruction sequences such as (ldil, ble)
302 and generate the appropriate fixups. */
303
304 struct pa_it the_insn =
305 {
306 NULL, /* error */
307 0, /* opcode */
308 NULL, /* nlistp */
309 {
310 NULL, /* exp.X_add_symbol */
311 NULL, /* exp.X_subtract_symbol */
312 0, /* exp.X_add_number */
313 NULL /* exp.asection */
314 },
315 0, /* pcrel */
316 0, /* fpof1 */
317 0, /* fpof2 */
318 0, /* reloc */
319 0, /* field_selector */
320 0, /* code */
321 0, /* arg_reloc */
322 { /* unwind */
323 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
324 }
325 };
326
327 #ifdef OBJ_ELF
328
329 struct pa_it prev_insn;
330 char prev_str[10] = "";
331 fixS *prev_fix = NULL;
332 fixS *curr_fix = NULL;
333
334 #endif /* OBJ_ELF */
335
336 #ifdef __STDC__
337 void print_insn (struct pa_it *insn);
338 #else
339 void print_insn ();
340 #endif
341 char *expr_end;
342
343 symbolS *label_symbolP; /* the last label symbol encountered */
344 /* saved here in case a .equ is encountered */
345 int label_symbol_defined;
346
347 int callinfo_found; /* T if a .callinfo appeared within the current */
348 /* procedure definition and F otherwise */
349
350 int within_entry_exit; /* T if the assembler is currently within a */
351 /* .entry/.exit pair and F otherwise */
352
353 int exit_processing_complete; /* T is the assembler has completed exit */
354 /* processing for the current procedure */
355 /* and F otherwise */
356
357 int within_procedure; /* T if the assembler is currently within a */
358 /* a procedure definition and F otherwise */
359
360 void ignore_rest_of_line (); /* a useful function in read.c */
361
362 /* default space and subspace dictionaries */
363
364 #define GDB_SYMBOLS GDB_SYMBOLS_SUBSPACE_NAME
365 #define GDB_STRINGS GDB_STRINGS_SUBSPACE_NAME
366
367 #if defined(OBJ_ELF)
368 struct default_subspace_dict pa_def_subspaces[] =
369 {
370 {"$CODE$", 0, 1, 0, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, ".text", SUBSEG_CODE},
371 {"$DATA$", 0, 1, 0, 0, 0, 0, 24, 0x1f, 0, 8, 1, 1, ".data", SUBSEG_DATA},
372 {"$LIT$", 0, 1, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, ".text", SUBSEG_LIT},
373 {"$BSS$", 0, 1, 0, 0, 0, 1, 80, 0x1f, 0, 8, 1, 1, ".bss", SUBSEG_BSS},
374 {"$UNWIND$", 0, 1, 0, 0, 0, 0, 64, 0x2c, 0, 4, 0, 0, ".hppa_unwind", SUBSEG_UNWIND},
375 {GDB_STRINGS, 0, 0, 0, 0, 0, 0, 254, 0x1f, 0, 4, 0, 2, ".stabstr", SUBSEG_GDB_STRINGS},
376 {GDB_SYMBOLS, 0, 0, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, 2, ".stab", SUBSEG_GDB_SYMBOLS},
377 {NULL, 0, 1, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, 0, 0}
378 };
379
380 struct default_space_dict pa_def_spaces[] =
381 {
382 {"$TEXT$", 0, 1, 0, 0, 8, ASEC_NULL, ".text"},
383 {"$PRIVATE$", 0, 1, 0, 0, 16, ASEC_NULL, ".data"},
384 {GDB_DEBUG_SPACE_NAME, 0, 0, 0, 0, 255, ASEC_NULL, ".stab"},
385 {NULL, 0, 0, 0, 0, 0, ASEC_NULL, NULL}
386 };
387 #else
388 struct default_subspace_dict pa_def_subspaces[] =
389 {
390 {"$CODE$", 0, 1, 0, 0, 0, 0, 24, 0x2c, 0, 8, 0, SEG_TEXT, SUBSEG_CODE},
391 {"$DATA$", 0, 1, 0, 0, 0, 0, 24, 0x1f, 0, 8, 1, SEG_DATA, SUBSEG_DATA},
392 {"$LIT$", 0, 1, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, SEG_TEXT, SUBSEG_LIT},
393 {"$BSS$", 0, 1, 0, 0, 0, 1, 80, 0x1f, 0, 8, 1, SEG_DATA, SUBSEG_BSS},
394 {"$UNWIND$", 0, 1, 0, 0, 0, 0, 64, 0x2c, 0, 4, 0, SEG_TEXT, SUBSEG_UNWIND},
395 {GDB_STRINGS, 0, 0, 0, 0, 0, 0, 254, 0x1f, 0, 4, 0, SEG_GDB, SUBSEG_GDB_STRINGS
396 },
397 {GDB_SYMBOLS, 0, 0, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, SEG_GDB, SUBSEG_GDB_SYMBOLS
398 },
399 {NULL, 0, 1, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, SEG_GOOF, 0}
400 };
401
402 struct default_space_dict pa_def_spaces[] =
403 {
404 {"$TEXT$", 0, 1, 0, 0, 8, SEG_TEXT},
405 {"$PRIVATE$", 0, 1, 0, 0, 16, SEG_DATA},
406 {GDB_DEBUG_SPACE_NAME, 0, 0, 0, 0, 255, SEG_GDB},
407 {NULL, 0, 0, 0, 0, 0, SEG_GOOF}
408 };
409 #endif
410
411 #ifdef USG
412 #define bcmp(b1,b2,n) memcmp((b1),(b2),(n))
413 #define index strchr
414 #endif
415
416 #ifndef FALSE
417 #define FALSE (0)
418 #define TRUE (!FALSE)
419 #endif /* no FALSE yet */
420
421 /*
422 Support for keeping track of the most recent label in each
423 space.
424 */
425
426 /*
427 PA_PSEUDO_OP_MOVES_PC
428
429 A predicate that returns true if the pseudo-operation or
430 assembly directive results in a movement in the current
431 location. All instructions cause movement in the current
432 location.
433 */
434
435 static const char *movers[] =
436 {
437 /* these entries from 'static pseudo_typeS potable[]' in pa-read.c */
438 "ascii", "asciz",
439 "byte",
440 "comm",
441 "data", "desc", "double",
442 "fill", "float",
443 "globl",
444 "half",
445 "int",
446 "lcomm", "long", "lsym",
447 "octa", "org",
448 "quad",
449 "short", "single",
450 "text",
451 "word",
452 /* these entries from 'pseudo_typeS md_pseudo_table[]' in pa-aux.c */
453 "block", "blockz",
454 "code", "copyright",
455 "equ",
456 "origin",
457 "reg", /* very similar to .equ */
458 "string", "stringz",
459 "version",
460 NULL /* end sentinel */
461 };
462
463 int
464 pa_pseudo_op_moves_pc (name)
465 char *name;
466 {
467 int i = 0;
468 while (movers[i])
469 {
470 if (strcmp (name, movers[i++]) == 0)
471 return 1;
472 }
473
474 return 0;
475 }
476
477 /*
478 Support for keeping track of the most recent label in each
479 space.
480 */
481
482 /* XXX: NOTE: label_symbolS is defined in pa.h */
483
484 label_symbolS *label_symbols_rootP = NULL;
485
486 /*
487 PA_GET_LABEL
488
489 Returns a pointer to the label_symbolS for the current space.
490 */
491
492 label_symbolS *
493 pa_get_label ()
494 {
495 label_symbolS *lssP;
496 space_dict_chainS *now_sdcP = pa_segment_to_space (now_seg);
497
498 for (lssP = label_symbols_rootP; lssP; lssP = lssP->lss_next)
499 {
500 if (now_sdcP == lssP->lss_space && lssP->lss_label)
501 return lssP;
502 }
503
504 return (label_symbolS *) NULL;
505 }
506
507 /*
508 PA_LABEL_IS_DEFINED
509
510 A predicate to determine whether a useable label is defined in
511 the current space.
512 */
513
514 int
515 pa_label_is_defined ()
516 {
517 return (int) pa_get_label ();
518 }
519
520 /*
521 PA_DEFINE_LABEL
522
523 Defines a label for the current space. If one is already defined,
524 this function will replace it with the new label.
525 */
526
527 void
528 pa_define_label (symbolP)
529 symbolS *symbolP;
530 {
531 label_symbolS *lssP = pa_get_label ();
532 space_dict_chainS *now_sdcP = pa_segment_to_space (now_seg);
533
534 if (lssP)
535 {
536 lssP->lss_label = symbolP;
537 }
538 else
539 {
540 lssP = (label_symbolS *) xmalloc (sizeof (label_symbolS));
541 lssP->lss_label = symbolP;
542 lssP->lss_space = now_sdcP;
543 lssP->lss_next = (label_symbolS *) NULL;
544
545 if (label_symbols_rootP)
546 {
547 lssP->lss_next = label_symbols_rootP;
548 }
549 label_symbols_rootP = lssP;
550 }
551 }
552
553 /*
554 PA_UNDEFINE_LABEL
555
556 Removes a label definition for the current space.
557 If there is no label_symbolS entry, then no action is taken.
558 */
559
560 void
561 pa_undefine_label ()
562 {
563 label_symbolS *lssP;
564 label_symbolS *prevP = (label_symbolS *) NULL;
565 space_dict_chainS *now_sdcP = pa_segment_to_space (now_seg);
566
567 for (lssP = label_symbols_rootP; lssP; lssP = lssP->lss_next)
568 {
569 if (now_sdcP == lssP->lss_space && lssP->lss_label)
570 {
571 if (prevP)
572 prevP->lss_next = lssP->lss_next;
573 else
574 label_symbols_rootP = lssP->lss_next;
575
576 free (lssP);
577 break;
578 }
579 prevP = lssP;
580 }
581 }
582
583 /* end of label symbol support. */
584
585
586 /* An HPPA-specific version of fix_new. This is required because the HPPA */
587 /* code needs to keep track of some extra stuff. Each call to fix_new_hppa */
588 /* results in the creation of an instance of an hppa_fixS. An hppa_fixS */
589 /* stores the extra information along with a pointer to the original fixS. */
590
591 typedef struct hppa_fix_struct
592 {
593 fixS *fx_fixP;
594 int fx_r_field;
595 int fx_r_type;
596 int fx_r_format;
597 long fx_arg_reloc;
598 call_infoS *fx_call_infop;
599 char fx_unwind[8];
600 struct hppa_fix_struct *fx_next;
601 } hppa_fixS;
602
603 hppa_fixS *hppa_fix_root = NULL;
604
605 void
606 fix_new_hppa (frag, where, size, add_symbol, sub_symbol, offset, pcrel,
607 r_type, r_field, r_format, arg_reloc, unwind_desc)
608 fragS *frag; /* Which frag? */
609 int where; /* Where in that frag? */
610 short int size; /* 1, 2 or 4 usually. */
611 symbolS *add_symbol; /* X_add_symbol. */
612 symbolS *sub_symbol; /* X_subtract_symbol. */
613 long offset; /* X_add_number. */
614 int pcrel; /* TRUE if PC-relative relocation. */
615 #ifdef BFD_ASSEMBLER
616 bfd_reloc_code_real_type r_type; /* Relocation type */
617 #else
618 int r_type; /* Relocation type */
619 #endif
620 long r_field; /* F, R, L, etc */
621 int r_format; /* 11,12,14,17,21,32, etc */
622 long arg_reloc;
623 char *unwind_desc;
624 {
625 fixS *new_fix = fix_new (frag, where, size,
626 add_symbol, sub_symbol,
627 offset, pcrel, r_type);
628
629 hppa_fixS *hppa_fix = (hppa_fixS *) obstack_alloc (&notes, sizeof (hppa_fixS));
630
631 hppa_fix->fx_fixP = new_fix;
632 hppa_fix->fx_r_field = r_field;
633 hppa_fix->fx_r_format = r_format;
634 hppa_fix->fx_arg_reloc = arg_reloc;
635 hppa_fix->fx_next = (hppa_fixS *) 0;
636 hppa_fix->fx_call_infop = last_call_info;
637 if (unwind_desc)
638 bcopy (unwind_desc, hppa_fix->fx_unwind, 8);
639
640 if (hppa_fix_root)
641 hppa_fix->fx_next = hppa_fix_root;
642
643 hppa_fix_root = hppa_fix;
644
645 /* SKV 12/22/92. Added prev_insn, prev_fix, and initialized the_insn
646 so that we can recognize instruction sequences such as (ldil, ble)
647 and generate the appropriate fixups. */
648
649 #ifdef OBJ_ELF
650
651 curr_fix = new_fix;
652
653 #endif /* OBJ_ELF */
654 }
655
656 /* Parse a .byte, .word, .long expression for the HPPA. Called by
657 cons via the TC_PARSE_CONS_EXPRESSION macro. */
658
659 static int hppa_field_selector;
660
661 void
662 parse_cons_expression_hppa (exp)
663 expressionS *exp;
664 {
665 hppa_field_selector = pa_chk_field_selector (&input_line_pointer);
666 expression (&exp);
667 }
668
669 /* This fix_new is called by cons via TC_CONS_FIX_NEW.
670 hppa_field_selector is set by the parse_cons_expression_hppa. */
671
672 void
673 cons_fix_new_hppa (frag, where, size, exp)
674 fragS *frag; /* Which frag? */
675 int where; /* Where in that frag? */
676 int size; /* 1, 2 or 4 usually. */
677 expressionS *exp; /* Expression. */
678 {
679 unsigned int reloc_type;
680
681 if (is_DP_relative (*exp))
682 reloc_type = R_HPPA_GOTOFF;
683 else if (is_complex (*exp))
684 reloc_type = R_HPPA_COMPLEX;
685 else
686 reloc_type = R_HPPA;
687
688 if (hppa_field_selector != e_psel && hppa_field_selector != e_fsel)
689 as_warn("Invalid field selector. Assuming F%%.");
690
691 fix_new_hppa (frag, where, size
692 exp->X_add_symbol,
693 exp->X_subtract_symbol,
694 exp->X_add_number, 0, reloc_type,
695 hppa_field_selector, 32, 0, (char *) 0);
696 }
697
698 /* Given a FixS, find the hppa_fixS associated with it. */
699 hppa_fixS *
700 hppa_find_hppa_fix (fix)
701 fixS *fix;
702 {
703 hppa_fixS *hfP;
704
705 for (hfP = hppa_fix_root; hfP; hfP = hfP->fx_next)
706 {
707 if (hfP->fx_fixP == fix)
708 return hfP;
709 }
710
711 return (hppa_fixS *) 0;
712 }
713
714 /* This function is called once, at assembler startup time. It should
715 set up all the tables, etc. that the MD part of the assembler will need. */
716 void
717 md_begin ()
718 {
719 register char *retval = NULL;
720 int lose = 0;
721 register unsigned int i = 0;
722 void pa_spaces_begin (); /* forward declaration */
723
724 last_call_info = NULL;
725 call_info_root = NULL;
726
727 pa_spaces_begin ();
728
729 op_hash = hash_new ();
730 if (op_hash == NULL)
731 as_fatal ("Virtual memory exhausted");
732
733 while (i < NUMOPCODES)
734 {
735 const char *name = pa_opcodes[i].name;
736 retval = hash_insert (op_hash, name, &pa_opcodes[i]);
737 if (retval != NULL && *retval != '\0')
738 {
739 as_fatal ("Internal error: can't hash `%s': %s\n",
740 pa_opcodes[i].name, retval);
741 lose = 1;
742 }
743 do
744 {
745 if ((pa_opcodes[i].match & pa_opcodes[i].mask) != pa_opcodes[i].match)
746 {
747 fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n",
748 pa_opcodes[i].name, pa_opcodes[i].args);
749 lose = 1;
750 }
751 ++i;
752 }
753 while (i < NUMOPCODES
754 && !strcmp (pa_opcodes[i].name, name));
755 }
756
757 if (lose)
758 as_fatal ("Broken assembler. No assembly attempted.");
759
760 for (i = '0'; i < '8'; ++i)
761 octal[i] = 1;
762 for (i = '0'; i <= '9'; ++i)
763 toHex[i] = i - '0';
764 for (i = 'a'; i <= 'f'; ++i)
765 toHex[i] = i + 10 - 'a';
766 for (i = 'A'; i <= 'F'; ++i)
767 toHex[i] = i + 10 - 'A';
768
769 }
770
771 void
772 md_end ()
773 {
774 return;
775 }
776
777 void
778 md_assemble (str)
779 char *str;
780 {
781 char *toP;
782
783 assert (str);
784 pa_ip (str);
785 toP = frag_more (4);
786 /* put out the opcode */
787 md_number_to_chars (toP, the_insn.opcode, 4);
788
789 /* put out the symbol-dependent stuff */
790 #if defined ( OBJ_SOM )
791 if (the_insn.reloc != R_NO_RELOCATION)
792 {
793 #else
794 #if defined ( OBJ_ELF )
795 if (the_insn.reloc != R_HPPA_NONE)
796 {
797 #endif
798 #endif
799
800 #if defined(OBJ_ELF)
801 fix_new_hppa (frag_now, /* which frag */
802 (toP - frag_now->fr_literal), /* where */
803 4, /* size */
804 the_insn.exp.X_add_symbol,
805 the_insn.exp.X_subtract_symbol,
806 the_insn.exp.X_add_number,
807 the_insn.pcrel,
808 the_insn.reloc,
809 the_insn.field_selector,
810 the_insn.format,
811 the_insn.arg_reloc,
812 (char *) 0);
813 #endif
814 #ifdef OBJ_SOM
815 fix_new (frag_now, /* which frag */
816 (toP - frag_now->fr_literal), /* where */
817 4, /* size */
818 the_insn.exp.X_add_symbol,
819 the_insn.exp.X_subtract_symbol,
820 the_insn.exp.X_add_number,
821 the_insn.pcrel,
822 the_insn.reloc,
823 the_insn.field_selector,
824 the_insn.code,
825 the_insn.arg_reloc,
826 (char *) 0);
827 #endif
828 }
829
830 /* SKV 12/22/92. Added prev_insn, prev_fix, and initialized the_insn
831 so that we can recognize instruction sequences such as (ldil, ble)
832 and generate the appropriate fixups. */
833
834 #ifdef OBJ_ELF
835
836 prev_insn = the_insn;
837 strncpy (prev_str, str, 10);
838 if (prev_insn.reloc = R_HPPA_NONE)
839 {
840 prev_fix = NULL;
841 }
842 else
843 {
844 prev_fix = curr_fix;
845 }
846
847 #endif /* OBJ_ELF */
848 }
849
850 static void
851 pa_ip (str)
852 char *str;
853 {
854 char *error_message = "";
855 char *s;
856 const char *args;
857 char c;
858 unsigned long i;
859 struct pa_opcode *insn;
860 char *argsStart;
861 unsigned long opcode;
862 unsigned int mask;
863 int match = FALSE;
864 int comma = 0;
865
866 int reg, reg1, reg2, s2, s3;
867 unsigned int im21, im14, im11, im5;
868 int m, a, uu, f;
869 int cmpltr, nullif, flag;
870 int sfu, cond;
871 char *name;
872 char *p, *save_s;
873
874 #ifdef PA_DEBUG
875 fprintf (stderr, "STATEMENT: \"%s\"\n", str);
876 #endif
877 for (s = str; isupper (*s) || islower (*s) || (*s >= '0' && *s <= '3'); ++s)
878 ;
879 switch (*s)
880 {
881
882 case '\0':
883 break;
884
885 case ',':
886 comma = 1;
887
888 /*FALLTHROUGH*/
889
890 case ' ':
891 *s++ = '\0';
892 break;
893
894 default:
895 as_bad ("Unknown opcode: `%s'", str);
896 exit (1);
897 }
898
899 save_s = str;
900
901 while (*save_s)
902 {
903 if (isupper (*save_s))
904 *save_s = tolower (*save_s);
905 save_s++;
906 }
907
908 if ((insn = (struct pa_opcode *) hash_find (op_hash, str)) == NULL)
909 {
910 as_bad ("Unknown opcode: `%s'", str);
911 return;
912 }
913 if (comma)
914 {
915 *--s = ',';
916 }
917 argsStart = s;
918 for (;;)
919 {
920 opcode = insn->match;
921 bzero (&the_insn, sizeof (the_insn));
922 #if defined( OBJ_SOM )
923 the_insn.reloc = R_NO_RELOCATION;
924 #else
925 #if defined ( OBJ_ELF )
926 the_insn.reloc = R_HPPA_NONE;
927 #endif
928 #endif
929 /*
930 * Build the opcode, checking as we go to make
931 * sure that the operands match
932 */
933 for (args = insn->args;; ++args)
934 {
935
936 switch (*args)
937 {
938
939 case '\0': /* end of args */
940 if (*s == '\0')
941 {
942 match = TRUE;
943 }
944 break;
945
946 case '+':
947 if (*s == '+')
948 {
949 ++s;
950 continue;
951 }
952 if (*s == '-')
953 {
954 continue;
955 }
956 break;
957
958 case '(': /* these must match exactly */
959 case ')':
960 case ',':
961 case ' ':
962 if (*s++ == *args)
963 continue;
964 break;
965
966 case 'b': /* 5 bit register field at 10 */
967 case '^': /* 5 bit control register field at 10 */
968 reg = pa_parse_number (&s);
969 if (reg < 32 && reg >= 0)
970 {
971 opcode |= reg << 21;
972 continue;
973 }
974 break;
975 case 'x': /* 5 bit register field at 15 */
976 reg = pa_parse_number (&s);
977 if (reg < 32 && reg >= 0)
978 {
979 opcode |= reg << 16;
980 continue;
981 }
982 break;
983 case 't': /* 5 bit register field at 31 */
984 reg = pa_parse_number (&s);
985 if (reg < 32 && reg >= 0)
986 {
987 opcode |= reg;
988 continue;
989 }
990 break;
991 case 'T': /* 5 bit field length at 31 (encoded as 32-T) */
992 /*
993 reg = pa_parse_number(&s);
994 */
995 getAbsoluteExpression (s);
996 if (the_insn.exp.X_seg == &bfd_abs_section)
997 {
998 reg = the_insn.exp.X_add_number;
999 if (reg <= 32 && reg > 0)
1000 {
1001 opcode |= 32 - reg;
1002 s = expr_end;
1003 continue;
1004 }
1005 }
1006 break;
1007 case '5': /* 5 bit immediate at 15 */
1008 getAbsoluteExpression (s);
1009 /** PJH: The following 2 calls to as_bad() might eventually **/
1010 /** want to end up as as_warn(). **/
1011 if (the_insn.exp.X_add_number > 15)
1012 {
1013 as_bad ("5 bit immediate > 15. Set to 15",
1014 the_insn.exp.X_add_number);
1015 the_insn.exp.X_add_number = 15;
1016 }
1017 else if (the_insn.exp.X_add_number < -16)
1018 {
1019 as_bad ("5 bit immediate < -16. Set to -16",
1020 the_insn.exp.X_add_number);
1021 the_insn.exp.X_add_number = -16;
1022 }
1023
1024 low_sign_unext (evaluateAbsolute (the_insn.exp, the_insn.field_selector),
1025 5, &im5);
1026 opcode |= (im5 << 16);
1027 s = expr_end;
1028 continue;
1029
1030 case 's': /* 2 bit space identifier at 17 */
1031 s2 = pa_parse_number (&s);
1032 if (s2 < 4 && s2 >= 0)
1033 {
1034 opcode |= s2 << 14;
1035 continue;
1036 }
1037 break;
1038 case 'S': /* 3 bit space identifier at 18 */
1039 s3 = pa_parse_number (&s);
1040 if (s3 < 8 && s3 >= 0)
1041 {
1042 dis_assemble_3 (s3, &s3);
1043 opcode |= s3 << 13;
1044 continue;
1045 }
1046 break;
1047 case 'c': /* indexed load completer. */
1048 uu = 0;
1049 m = 0;
1050 i = 0;
1051 while (*s == ',' && i < 2)
1052 {
1053 s++;
1054 if (strncasecmp (s, "sm", 2) == 0)
1055 {
1056 uu = 1;
1057 m = 1;
1058 s++;
1059 i++;
1060 }
1061 else if (strncasecmp (s, "m", 1) == 0)
1062 m = 1;
1063 else if (strncasecmp (s, "s", 1) == 0)
1064 uu = 1;
1065 else
1066 as_bad ("Unrecognized Indexed Load Completer...assuming 0");
1067 s++;
1068 i++;
1069 }
1070 if (i > 2)
1071 as_bad ("Illegal Indexed Load Completer Syntax...extras ignored");
1072 /* pa_skip(&s); */
1073 while (*s == ' ' || *s == '\t')
1074 s++;
1075
1076 opcode |= m << 5;
1077 opcode |= uu << 13;
1078 continue;
1079 case 'C': /* short load and store completer */
1080 a = 0;
1081 m = 0;
1082 if (*s == ',')
1083 {
1084 s++;
1085 if (strncasecmp (s, "ma", 2) == 0)
1086 {
1087 a = 0;
1088 m = 1;
1089 }
1090 else if (strncasecmp (s, "mb", 2) == 0)
1091 {
1092 a = 1;
1093 m = 1;
1094 }
1095 else
1096 as_bad ("Unrecognized Indexed Load Completer...assuming 0");
1097 s += 2;
1098 }
1099 /* pa_skip(&s); */
1100 while (*s == ' ' || *s == '\t')
1101 s++;
1102 opcode |= m << 5;
1103 opcode |= a << 13;
1104 continue;
1105 case 'Y': /* Store Bytes Short completer */
1106 a = 0;
1107 m = 0;
1108 i = 0;
1109 while (*s == ',' && i < 2)
1110 {
1111 s++;
1112 if (strncasecmp (s, "m", 1) == 0)
1113 m = 1;
1114 else if (strncasecmp (s, "b", 1) == 0)
1115 a = 0;
1116 else if (strncasecmp (s, "e", 1) == 0)
1117 a = 1;
1118 else
1119 as_bad ("Unrecognized Store Bytes Short Completer...assuming 0");
1120 s++;
1121 i++;
1122 }
1123 /** if ( i >= 2 ) **/
1124 if (i > 2)
1125 as_bad ("Illegal Store Bytes Short Completer...extras ignored");
1126 while (*s == ' ' || *s == '\t') /* skip to next operand */
1127 s++;
1128 opcode |= m << 5;
1129 opcode |= a << 13;
1130 continue;
1131 case '<': /* non-negated compare/subtract conditions. */
1132 cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s);
1133 if (cmpltr < 0)
1134 {
1135 as_bad ("Unrecognized Compare/Subtract Condition: %c", *s);
1136 cmpltr = 0;
1137 }
1138 opcode |= cmpltr << 13;
1139 continue;
1140 case '?': /* negated or non-negated cmp/sub conditions. */
1141 /* used only by ``comb'' and ``comib'' pseudo-ops */
1142 save_s = s;
1143 cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s);
1144 if (cmpltr < 0)
1145 {
1146 s = save_s;
1147 cmpltr = pa_parse_neg_cmpsub_cmpltr (&s);
1148 if (cmpltr < 0)
1149 {
1150 as_bad ("Unrecognized Compare/Subtract Condition: %c", *s);
1151 cmpltr = 0;
1152 }
1153 else
1154 {
1155 opcode |= 1 << 27; /* required opcode change to make
1156 COMIBT into a COMIBF or a
1157 COMBT into a COMBF or a
1158 ADDBT into a ADDBF or a
1159 ADDIBT into a ADDIBF */
1160 }
1161 }
1162 opcode |= cmpltr << 13;
1163 continue;
1164 case '!': /* negated or non-negated add conditions. */
1165 /* used only by ``addb'' and ``addib'' pseudo-ops */
1166 save_s = s;
1167 cmpltr = pa_parse_nonneg_add_cmpltr (&s);
1168 if (cmpltr < 0)
1169 {
1170 s = save_s;
1171 cmpltr = pa_parse_neg_add_cmpltr (&s);
1172 if (cmpltr < 0)
1173 {
1174 as_bad ("Unrecognized Compare/Subtract Condition: %c", *s);
1175 cmpltr = 0;
1176 }
1177 else
1178 {
1179 opcode |= 1 << 27; /* required opcode change to make
1180 COMIBT into a COMIBF or a
1181 COMBT into a COMBF or a
1182 ADDBT into a ADDBF or a
1183 ADDIBT into a ADDIBF */
1184 }
1185 }
1186 opcode |= cmpltr << 13;
1187 continue;
1188 case 'a': /* compare/subtract conditions */
1189 cmpltr = 0;
1190 f = 0;
1191 save_s = s;
1192 if (*s == ',')
1193 {
1194 cmpltr = pa_parse_nonneg_cmpsub_cmpltr (&s);
1195 if (cmpltr < 0)
1196 {
1197 f = 1;
1198 s = save_s;
1199 cmpltr = pa_parse_neg_cmpsub_cmpltr (&s);
1200 if (cmpltr < 0)
1201 {
1202 as_bad ("Unrecognized Compare/Subtract Condition");
1203 }
1204 }
1205 }
1206 opcode |= cmpltr << 13;
1207 opcode |= f << 12;
1208 continue;
1209 case 'd': /* non-negated add conditions */
1210 cmpltr = 0;
1211 nullif = 0;
1212 flag = 0;
1213 if (*s == ',')
1214 {
1215 s++;
1216 name = s;
1217 while (*s != ',' && *s != ' ' && *s != '\t')
1218 s += 1;
1219 c = *s;
1220 *s = 0x00;
1221 if (strcmp (name, "=") == 0)
1222 {
1223 cmpltr = 1;
1224 }
1225 else if (strcmp (name, "<") == 0)
1226 {
1227 cmpltr = 2;
1228 }
1229 else if (strcmp (name, "<=") == 0)
1230 {
1231 cmpltr = 3;
1232 }
1233 else if (strcasecmp (name, "nuv") == 0)
1234 {
1235 cmpltr = 4;
1236 }
1237 else if (strcasecmp (name, "znv") == 0)
1238 {
1239 cmpltr = 5;
1240 }
1241 else if (strcasecmp (name, "sv") == 0)
1242 {
1243 cmpltr = 6;
1244 }
1245 else if (strcasecmp (name, "od") == 0)
1246 {
1247 cmpltr = 7;
1248 }
1249 else if (strcasecmp (name, "n") == 0)
1250 {
1251 nullif = 1;
1252 }
1253 else if (strcasecmp (name, "tr") == 0)
1254 {
1255 cmpltr = 0;
1256 flag = 1;
1257 }
1258 else if (strcasecmp (name, "<>") == 0)
1259 {
1260 cmpltr = 1;
1261 flag = 1;
1262 }
1263 else if (strcasecmp (name, ">=") == 0)
1264 {
1265 cmpltr = 2;
1266 flag = 1;
1267 }
1268 else if (strcasecmp (name, ">") == 0)
1269 {
1270 cmpltr = 3;
1271 flag = 1;
1272 }
1273 else if (strcasecmp (name, "uv") == 0)
1274 {
1275 cmpltr = 4;
1276 flag = 1;
1277 }
1278 else if (strcasecmp (name, "vnz") == 0)
1279 {
1280 cmpltr = 5;
1281 flag = 1;
1282 }
1283 else if (strcasecmp (name, "nsv") == 0)
1284 {
1285 cmpltr = 6;
1286 flag = 1;
1287 }
1288 else if (strcasecmp (name, "ev") == 0)
1289 {
1290 cmpltr = 7;
1291 flag = 1;
1292 }
1293 else
1294 as_bad ("Unrecognized Add Condition: %s", name);
1295 *s = c;
1296 }
1297 nullif = pa_parse_nullif (&s);
1298 opcode |= nullif << 1;
1299 opcode |= cmpltr << 13;
1300 opcode |= flag << 12;
1301 continue;
1302 case '&': /* logical instruction conditions */
1303 cmpltr = 0;
1304 f = 0;
1305 if (*s == ',')
1306 {
1307 s++;
1308 name = s;
1309 while (*s != ',' && *s != ' ' && *s != '\t')
1310 s += 1;
1311 c = *s;
1312 *s = 0x00;
1313 if (strcmp (name, "=") == 0)
1314 {
1315 cmpltr = 1;
1316 }
1317 else if (strcmp (name, "<") == 0)
1318 {
1319 cmpltr = 2;
1320 }
1321 else if (strcmp (name, "<=") == 0)
1322 {
1323 cmpltr = 3;
1324 }
1325 else if (strcasecmp (name, "od") == 0)
1326 {
1327 cmpltr = 7;
1328 }
1329 else if (strcasecmp (name, "tr") == 0)
1330 {
1331 cmpltr = 0;
1332 f = 1;
1333 }
1334 else if (strcmp (name, "<>") == 0)
1335 {
1336 cmpltr = 1;
1337 f = 1;
1338 }
1339 else if (strcmp (name, ">=") == 0)
1340 {
1341 cmpltr = 2;
1342 f = 1;
1343 }
1344 else if (strcmp (name, ">") == 0)
1345 {
1346 cmpltr = 3;
1347 f = 1;
1348 }
1349 else if (strcasecmp (name, "ev") == 0)
1350 {
1351 cmpltr = 7;
1352 f = 1;
1353 }
1354 else
1355 as_bad ("Unrecognized Logical Instruction Condition: %s", name);
1356 *s = c;
1357 }
1358 opcode |= cmpltr << 13;
1359 opcode |= f << 12;
1360 continue;
1361 case 'U': /* unit instruction conditions */
1362 cmpltr = 0;
1363 f = 0;
1364 if (*s == ',')
1365 {
1366 s++;
1367 if (strncasecmp (s, "sbz", 3) == 0)
1368 {
1369 cmpltr = 2;
1370 s += 3;
1371 }
1372 else if (strncasecmp (s, "shz", 3) == 0)
1373 {
1374 cmpltr = 3;
1375 s += 3;
1376 }
1377 else if (strncasecmp (s, "sdc", 3) == 0)
1378 {
1379 cmpltr = 4;
1380 s += 3;
1381 }
1382 else if (strncasecmp (s, "sbc", 3) == 0)
1383 {
1384 cmpltr = 6;
1385 s += 3;
1386 }
1387 else if (strncasecmp (s, "shc", 3) == 0)
1388 {
1389 cmpltr = 7;
1390 s += 3;
1391 }
1392 else if (strncasecmp (s, "tr", 2) == 0)
1393 {
1394 cmpltr = 0;
1395 f = 1;
1396 s += 2;
1397 }
1398 else if (strncasecmp (s, "nbz", 3) == 0)
1399 {
1400 cmpltr = 2;
1401 f = 1;
1402 s += 3;
1403 }
1404 else if (strncasecmp (s, "nhz", 3) == 0)
1405 {
1406 cmpltr = 3;
1407 f = 1;
1408 s += 3;
1409 }
1410 else if (strncasecmp (s, "ndc", 3) == 0)
1411 {
1412 cmpltr = 4;
1413 f = 1;
1414 s += 3;
1415 }
1416 else if (strncasecmp (s, "nbc", 3) == 0)
1417 {
1418 cmpltr = 6;
1419 f = 1;
1420 s += 3;
1421 }
1422 else if (strncasecmp (s, "nhc", 3) == 0)
1423 {
1424 cmpltr = 7;
1425 f = 1;
1426 s += 3;
1427 }
1428 else
1429 as_bad ("Unrecognized Logical Instruction Condition: %c", *s);
1430 }
1431 opcode |= cmpltr << 13;
1432 opcode |= f << 12;
1433 continue;
1434 case '>': /* shift/extract/deposit conditions. */
1435 cmpltr = 0;
1436 if (*s == ',')
1437 {
1438 s++;
1439 name = s;
1440 while (*s != ',' && *s != ' ' && *s != '\t')
1441 s += 1;
1442 c = *s;
1443 *s = 0x00;
1444 if (strcmp (name, "=") == 0)
1445 {
1446 cmpltr = 1;
1447 }
1448 else if (strcmp (name, "<") == 0)
1449 {
1450 cmpltr = 2;
1451 }
1452 else if (strcasecmp (name, "od") == 0)
1453 {
1454 cmpltr = 3;
1455 }
1456 else if (strcasecmp (name, "tr") == 0)
1457 {
1458 cmpltr = 4;
1459 }
1460 else if (strcmp (name, "<>") == 0)
1461 {
1462 cmpltr = 5;
1463 }
1464 else if (strcmp (name, ">=") == 0)
1465 {
1466 cmpltr = 6;
1467 }
1468 else if (strcasecmp (name, "ev") == 0)
1469 {
1470 cmpltr = 7;
1471 }
1472 else
1473 as_bad ("Unrecognized Shift/Extract/Deposit Condition: %s", name);
1474 *s = c;
1475 }
1476 opcode |= cmpltr << 13;
1477 continue;
1478 case '~': /* bvb,bb conditions */
1479 cmpltr = 0;
1480 if (*s == ',')
1481 {
1482 s++;
1483 if (strncmp (s, "<", 1) == 0)
1484 {
1485 cmpltr = 2;
1486 s++;
1487 }
1488 else if (strncmp (s, ">=", 2) == 0)
1489 {
1490 cmpltr = 6;
1491 s += 2;
1492 }
1493 else
1494 as_bad ("Unrecognized Bit Branch Condition: %c", *s);
1495 }
1496 opcode |= cmpltr << 13;
1497 continue;
1498 case 'V': /* 5 bit immediate at 31 */
1499 getExpression (s);
1500 low_sign_unext (evaluateAbsolute (the_insn.exp, the_insn.field_selector),
1501 5, &im5);
1502 opcode |= im5;
1503 s = expr_end;
1504 continue;
1505 case 'r': /* 5 bit immediate at 31 */
1506 /* (unsigned value for the break instruction) */
1507 getExpression (s);
1508 im5 = evaluateAbsolute (the_insn.exp, the_insn.field_selector);
1509 if (im5 > 31 || im5 < 0)
1510 {
1511 as_bad ("Operand out of range. Was: %d. Should be [0..31]. Assuming %d.\n", im5, im5 & 0x1f);
1512 im5 = im5 & 0x1f;
1513 }
1514 opcode |= im5;
1515 s = expr_end;
1516 continue;
1517 case 'R': /* 5 bit immediate at 15 */
1518 /* (unsigned value for the ssm and rsm instruction) */
1519 getExpression (s);
1520 im5 = evaluateAbsolute (the_insn.exp, the_insn.field_selector);
1521 if (im5 > 31 || im5 < 0)
1522 {
1523 as_bad ("Operand out of range. Was: %d. Should be [0..31]. Assuming %d.\n", im5, im5 & 0x1f);
1524 im5 = im5 & 0x1f;
1525 }
1526 opcode |= im5 << 16;
1527 s = expr_end;
1528 continue;
1529 case 'i': /* 11 bit immediate at 31 */
1530 #ifdef OBJ_SOM
1531 getExpression (s);
1532 if (the_insn.exp.X_seg == &bfd_abs_section)
1533 {
1534 low_sign_unext (evaluateAbsolute (the_insn.exp, the_insn.field_selector),
1535 11, &im11);
1536 opcode |= im11;
1537 }
1538 else
1539 {
1540 the_insn.reloc = R_CODE_ONE_SYMBOL;
1541 the_insn.code = 'i';
1542 the_insn.field_selector = the_insn.exp.field_selector;
1543 }
1544 s = expr_end;
1545 continue;
1546 #else
1547 the_insn.field_selector = pa_chk_field_selector (&s);
1548 getExpression (s);
1549 if (the_insn.exp.X_seg == &bfd_abs_section)
1550 {
1551 low_sign_unext (evaluateAbsolute (the_insn.exp, the_insn.field_selector),
1552 11, &im11);
1553 opcode |= im11;
1554 }
1555 else
1556 {
1557 if (is_DP_relative (the_insn.exp))
1558 the_insn.reloc = R_HPPA_GOTOFF;
1559 else if (is_PC_relative (the_insn.exp))
1560 the_insn.reloc = R_HPPA_PCREL_CALL;
1561 else if (is_complex (the_insn.exp))
1562 the_insn.reloc = R_HPPA_COMPLEX;
1563 else
1564 the_insn.reloc = R_HPPA;
1565 the_insn.format = 11;
1566 }
1567 s = expr_end;
1568 continue;
1569 #endif
1570 case 'j': /* 14 bit immediate at 31 */
1571 #ifdef OBJ_SOM
1572 getExpression (s);
1573 if (the_insn.exp.X_seg == &bfd_abs_section)
1574 {
1575 low_sign_unext (evaluateAbsolute (the_insn.exp, field_selector),
1576 14, &im14);
1577 if (the_insn.exp.field_selector == e_rsel)
1578 opcode |= (im14 & 0xfff);
1579 else
1580 opcode |= im14;
1581 }
1582 else
1583 {
1584 the_insn.reloc = R_CODE_ONE_SYMBOL;
1585 the_insn.code = 'j';
1586 the_insn.field_selector = the_insn.exp.field_selector;
1587 }
1588 s = expr_end;
1589 continue;
1590 #else
1591 the_insn.field_selector = pa_chk_field_selector (&s);
1592 getExpression (s);
1593 if (the_insn.exp.X_seg == &bfd_abs_section)
1594 {
1595 low_sign_unext (evaluateAbsolute (the_insn.exp, the_insn.field_selector),
1596 14, &im14);
1597 if (the_insn.field_selector == e_rsel)
1598 opcode |= (im14 & 0xfff);
1599 else
1600 opcode |= im14;
1601 }
1602 else
1603 {
1604 if (is_DP_relative (the_insn.exp))
1605 the_insn.reloc = R_HPPA_GOTOFF;
1606 else if (is_PC_relative (the_insn.exp))
1607 the_insn.reloc = R_HPPA_PCREL_CALL;
1608 else if (is_complex (the_insn.exp))
1609 the_insn.reloc = R_HPPA_COMPLEX;
1610 else
1611 the_insn.reloc = R_HPPA;
1612 the_insn.format = 14;
1613 }
1614 s = expr_end;
1615 continue;
1616 #endif
1617
1618 case 'k': /* 21 bit immediate at 31 */
1619 #ifdef OBJ_SOM
1620 getExpression (s);
1621 if (the_insn.exp.X_seg == &bfd_abs_section)
1622 {
1623 dis_assemble_21 (evaluateAbsolute (the_insn.exp, the_insn.field_selector),
1624 &im21);
1625 opcode |= im21;
1626 }
1627 else
1628 {
1629 the_insn.reloc = R_CODE_ONE_SYMBOL;
1630 the_insn.code = 'k';
1631 the_insn.field_selector = the_insn.exp.field_selector;
1632 }
1633 s = expr_end;
1634 continue;
1635 #else
1636 the_insn.field_selector = pa_chk_field_selector (&s);
1637 getExpression (s);
1638 if (the_insn.exp.X_seg == &bfd_abs_section)
1639 {
1640 dis_assemble_21 (evaluateAbsolute (the_insn.exp, the_insn.field_selector),
1641 &im21);
1642 opcode |= im21;
1643 }
1644 else
1645 {
1646 if (is_DP_relative (the_insn.exp))
1647 the_insn.reloc = R_HPPA_GOTOFF;
1648 else if (is_PC_relative (the_insn.exp))
1649 the_insn.reloc = R_HPPA_PCREL_CALL;
1650 else if (is_complex (the_insn.exp))
1651 the_insn.reloc = R_HPPA_COMPLEX;
1652 else
1653 the_insn.reloc = R_HPPA;
1654 the_insn.format = 21;
1655 }
1656 s = expr_end;
1657 continue;
1658 #endif
1659
1660 case 'n': /* nullification for branch instructions */
1661 nullif = pa_parse_nullif (&s);
1662 opcode |= nullif << 1;
1663 continue;
1664 case 'w': /* 12 bit branch displacement */
1665 #ifdef OBJ_SOM
1666 getExpression (s);
1667 the_insn.pcrel = 1;
1668 if (strcmp (the_insn.exp.X_add_symbol->sy_nlist.n_un.n_name, "L0\001") == 0)
1669 {
1670 unsigned int w1, w, result;
1671
1672 sign_unext ((the_insn.exp.X_add_number - 8) >> 2, 12, &result);
1673 dis_assemble_12 (result, &w1, &w);
1674 opcode |= ((w1 << 2) | w);
1675 the_insn.exp.X_add_symbol->sy_ref = FALSE;
1676 }
1677 else
1678 {
1679 /* this has to be wrong -- dont know what is right! */
1680 the_insn.reloc = R_PCREL_CALL;
1681 the_insn.code = 'w';
1682 the_insn.field_selector = the_insn.exp.field_selector;
1683 the_insn.arg_reloc = last_call_desc.arg_reloc;
1684 bzero (&last_call_desc, sizeof (call_descS));
1685 }
1686 s = expr_end;
1687 continue;
1688 #else
1689 the_insn.field_selector = pa_chk_field_selector (&s);
1690 getExpression (s);
1691 the_insn.pcrel = 1;
1692 if (strcmp (S_GET_NAME (the_insn.exp.X_add_symbol), "L0\001") == 0)
1693 {
1694 unsigned int w1, w, result;
1695
1696 sign_unext ((the_insn.exp.X_add_number - 8) >> 2, 12, &result);
1697 dis_assemble_12 (result, &w1, &w);
1698 opcode |= ((w1 << 2) | w);
1699 /* the_insn.exp.X_add_symbol->sy_ref = FALSE; *//* XXX: not sure how to do this in BFD */
1700 }
1701 else
1702 {
1703 if (is_complex (the_insn.exp))
1704 the_insn.reloc = R_HPPA_COMPLEX_PCREL_CALL;
1705 else
1706 the_insn.reloc = R_HPPA_PCREL_CALL;
1707 the_insn.format = 12;
1708 the_insn.arg_reloc = last_call_desc.arg_reloc;
1709 bzero (&last_call_desc, sizeof (call_descS));
1710 }
1711 s = expr_end;
1712 continue;
1713 #endif
1714 case 'W': /* 17 bit branch displacement */
1715 #if defined(OBJ_ELF)
1716 the_insn.field_selector = pa_chk_field_selector (&s);
1717 #endif
1718 getExpression (s);
1719 the_insn.pcrel = 1;
1720 #ifdef OBJ_SOM
1721 if (strcmp (the_insn.exp.X_add_symbol->sy_nlist.n_un.n_name, "L0\001") == 0)
1722 {
1723 unsigned int w2, w1, w, result;
1724
1725 sign_unext ((the_insn.exp.X_add_number - 8) >> 2, 17, &result);
1726 dis_assemble_17 (result, &w1, &w2, &w);
1727 opcode |= ((w2 << 2) | (w1 << 16) | w);
1728 the_insn.exp.X_add_symbol->sy_ref = FALSE;
1729 }
1730 else
1731 {
1732 /* this has to be wrong -- dont know what is right! */
1733 the_insn.reloc = R_PCREL_CALL;
1734 the_insn.code = 'W';
1735 the_insn.field_selector = the_insn.exp.field_selector;
1736 the_insn.arg_reloc = last_call_desc.arg_reloc;
1737 bzero (&last_call_desc, sizeof (call_descS));
1738 }
1739 #else
1740 if (the_insn.exp.X_add_symbol)
1741 {
1742 if (strcmp (S_GET_NAME (the_insn.exp.X_add_symbol), "L0\001") == 0)
1743 {
1744 unsigned int w2, w1, w, result;
1745
1746 sign_unext ((the_insn.exp.X_add_number - 8) >> 2, 17, &result);
1747 dis_assemble_17 (result, &w1, &w2, &w);
1748 opcode |= ((w2 << 2) | (w1 << 16) | w);
1749 }
1750 else
1751 {
1752 if (is_complex (the_insn.exp))
1753 the_insn.reloc = R_HPPA_COMPLEX_PCREL_CALL;
1754 else
1755 the_insn.reloc = R_HPPA_PCREL_CALL;
1756 the_insn.format = 17;
1757 the_insn.arg_reloc = last_call_desc.arg_reloc;
1758 bzero (&last_call_desc, sizeof (call_descS));
1759 }
1760 }
1761 else
1762 {
1763 unsigned int w2, w1, w, result;
1764
1765 sign_unext (the_insn.exp.X_add_number >> 2, 17, &result);
1766 dis_assemble_17 (result, &w1, &w2, &w);
1767 opcode |= ((w2 << 2) | (w1 << 16) | w);
1768 }
1769 #endif
1770 s = expr_end;
1771 continue;
1772 case 'z': /* 17 bit branch displacement (not pc-relative) */
1773 #if defined(OBJ_ELF)
1774 the_insn.field_selector = pa_chk_field_selector (&s);
1775 #endif
1776 getExpression (s);
1777 the_insn.pcrel = 0;
1778 #ifdef OBJ_SOM
1779 if (strcmp (the_insn.exp.X_add_symbol->sy_nlist.n_un.n_name, "L0\001") == 0)
1780 {
1781 unsigned int w2, w1, w, result;
1782
1783 sign_unext ((the_insn.exp.X_add_number - 8) >> 2, 17, &result);
1784 dis_assemble_17 (result, &w1, &w2, &w);
1785 opcode |= ((w2 << 2) | (w1 << 16) | w);
1786 the_insn.exp.X_add_symbol->sy_ref = FALSE;
1787 }
1788 else
1789 {
1790 /* this has to be wrong -- dont know what is right! */
1791 the_insn.reloc = R_PCREL_CALL;
1792 the_insn.code = 'W';
1793 the_insn.field_selector = the_insn.exp.field_selector;
1794 the_insn.arg_reloc = last_call_desc.arg_reloc;
1795 bzero (&last_call_desc, sizeof (call_descS));
1796 }
1797 #else
1798 if (the_insn.exp.X_add_symbol)
1799 {
1800 if (strcmp (S_GET_NAME (the_insn.exp.X_add_symbol), "L0\001") == 0)
1801 {
1802 unsigned int w2, w1, w, result;
1803
1804 sign_unext ((the_insn.exp.X_add_number - 8) >> 2, 17, &result);
1805 dis_assemble_17 (result, &w1, &w2, &w);
1806 opcode |= ((w2 << 2) | (w1 << 16) | w);
1807 }
1808 else
1809 {
1810 if (is_complex (the_insn.exp))
1811 {
1812 the_insn.reloc = R_HPPA_COMPLEX_ABS_CALL;
1813 }
1814 else
1815 {
1816 the_insn.reloc = R_HPPA_ABS_CALL;
1817 }
1818 /* This could also be part of an instruction sequence of
1819 interest. If so, check to make sure that the previous
1820 instruction's fixup is appropriate. (ble, be instructions
1821 affect the reloc of immediately preceding ldil
1822 instructions.) */
1823 if (strcasecmp (prev_str, "ldil") == 0 &&
1824 prev_insn.exp.X_add_symbol == the_insn.exp.X_add_symbol &&
1825 prev_insn.exp.X_subtract_symbol == the_insn.exp.X_subtract_symbol &&
1826 prev_insn.exp.X_seg == the_insn.exp.X_seg &&
1827 prev_insn.exp.X_add_number == the_insn.exp.X_add_number &&
1828 prev_fix != NULL)
1829 prev_fix->fx_r_type = the_insn.reloc;
1830
1831 the_insn.format = 17;
1832 the_insn.arg_reloc = last_call_desc.arg_reloc;
1833 bzero (&last_call_desc, sizeof (call_descS));
1834 }
1835 }
1836 else
1837 {
1838 unsigned int w2, w1, w, result;
1839
1840 sign_unext (the_insn.exp.X_add_number >> 2, 17, &result);
1841 dis_assemble_17 (result, &w1, &w2, &w);
1842 opcode |= ((w2 << 2) | (w1 << 16) | w);
1843 }
1844 #endif
1845 s = expr_end;
1846 continue;
1847 case 'p': /* 5 bit shift count at 26 (to support SHD instr.) */
1848 /* value is encoded in instr. as 31-p where p is */
1849 /* the value scanned here */
1850 getExpression (s);
1851 if (the_insn.exp.X_seg == &bfd_abs_section)
1852 {
1853 opcode |= (((31 - the_insn.exp.X_add_number) & 0x1f) << 5);
1854 }
1855 s = expr_end;
1856 continue;
1857 case 'P': /* 5-bit bit position at 26 */
1858 getExpression (s);
1859 if (the_insn.exp.X_seg == &bfd_abs_section)
1860 {
1861 opcode |= (the_insn.exp.X_add_number & 0x1f) << 5;
1862 }
1863 s = expr_end;
1864 continue;
1865 case 'Q': /* 5 bit immediate at 10 */
1866 /* (unsigned bit position value for the bb instruction) */
1867 getExpression (s);
1868 im5 = evaluateAbsolute (the_insn.exp, the_insn.field_selector);
1869 if (im5 > 31 || im5 < 0)
1870 {
1871 as_bad ("Operand out of range. Was: %d. Should be [0..31]. Assuming %d.\n", im5, im5 & 0x1f);
1872 im5 = im5 & 0x1f;
1873 }
1874 opcode |= im5 << 21;
1875 s = expr_end;
1876 continue;
1877 case 'A': /* 13 bit immediate at 18 (to support BREAK instr.) */
1878 getAbsoluteExpression (s);
1879 if (the_insn.exp.X_seg == &bfd_abs_section)
1880 opcode |= (the_insn.exp.X_add_number & 0x1fff) << 13;
1881 s = expr_end;
1882 continue;
1883 case 'Z': /* System Control Completer(for LDA, LHA, etc.) */
1884 if (*s == ',' && (*(s + 1) == 'm' || *(s + 1) == 'M'))
1885 {
1886 m = 1;
1887 s += 2;
1888 }
1889 else
1890 m = 0;
1891
1892 opcode |= m << 5;
1893 while (*s == ' ' || *s == '\t') /* skip to next operand */
1894 s++;
1895
1896 continue;
1897 case 'D': /* 26 bit immediate at 31 (to support DIAG instr.) */
1898 /* the action (and interpretation of this operand is
1899 implementation dependent) */
1900 #if defined(OBJ_ELF)
1901 the_insn.field_selector = pa_chk_field_selector (&s);
1902 #endif
1903 getExpression (s);
1904 if (the_insn.exp.X_seg == &bfd_abs_section)
1905 {
1906 opcode |= ((evaluateAbsolute (the_insn.exp, the_insn.field_selector) & 0x1ffffff) << 1);
1907 #ifdef NEW_SOM /* XXX what replaces this? */
1908 /* PJH: VERY unsure about the following */
1909 the_insn.field_selector = the_insn.exp.field_selector;
1910 #endif
1911 }
1912 else
1913 as_bad ("Illegal DIAG operand");
1914 s = expr_end;
1915 continue;
1916 case 'f': /* 3 bit Special Function Unit (SFU) identifier at 25 */
1917 sfu = pa_parse_number (&s);
1918 if ((sfu > 7) || (sfu < 0))
1919 as_bad ("Illegal SFU identifier: %02x", sfu);
1920 opcode |= (sfu & 7) << 6;
1921 continue;
1922 case 'O': /* 20 bit SFU op. split between 15 bits at 20
1923 and 5 bits at 31 */
1924 getExpression (s);
1925 s = expr_end;
1926 continue;
1927 case 'o': /* 15 bit Special Function Unit operation at 20 */
1928 getExpression (s);
1929 s = expr_end;
1930 continue;
1931 case '2': /* 22 bit SFU op. split between 17 bits at 20
1932 and 5 bits at 31 */
1933 getExpression (s);
1934 s = expr_end;
1935 continue;
1936 case '1': /* 15 bit SFU op. split between 10 bits at 20
1937 and 5 bits at 31 */
1938 getExpression (s);
1939 s = expr_end;
1940 continue;
1941 case '0': /* 10 bit SFU op. split between 5 bits at 20
1942 and 5 bits at 31 */
1943 getExpression (s);
1944 s = expr_end;
1945 continue;
1946 case 'u': /* 3 bit coprocessor unit identifier at 25 */
1947 getExpression (s);
1948 s = expr_end;
1949 continue;
1950 case 'F': /* Source FP Operand Format Completer (2 bits at 20) */
1951 f = pa_parse_fp_format (&s);
1952 opcode |= (int) f << 11;
1953 the_insn.fpof1 = f;
1954 continue;
1955 case 'G': /* Destination FP Operand Format Completer (2 bits at 18) */
1956 s--; /* need to pass the previous comma to pa_parse_fp_format */
1957 f = pa_parse_fp_format (&s);
1958 opcode |= (int) f << 13;
1959 the_insn.fpof2 = f;
1960 continue;
1961 case 'M': /* FP Compare Conditions (encoded as 5 bits at 31) */
1962 cond = pa_parse_fp_cmp_cond (&s);
1963 opcode |= cond;
1964 continue;
1965
1966 case 'v': /* a 't' type extended to handle L/R register halves. */
1967 {
1968 struct pa_89_fp_reg_struct result;
1969 int status;
1970
1971 pa_89_parse_number (&s, &result);
1972 if (result.number_part < 32 && result.number_part >= 0)
1973 {
1974 opcode |= (result.number_part & 0x1f);
1975
1976 /* 0x30 opcodes are FP arithmetic operation opcodes */
1977 /* load/store FP opcodes do not get converted to 0x38 */
1978 /* opcodes like the 0x30 opcodes do */
1979 if (need_89_opcode (&the_insn, &result))
1980 {
1981 if ((opcode & 0xfc000000) == 0x30000000)
1982 {
1983 opcode |= (result.L_R_select & 1) << 6;
1984 opcode |= 1 << 27;
1985 }
1986 else
1987 {
1988 opcode |= (result.L_R_select & 1) << 6;
1989 }
1990 }
1991 continue;
1992 }
1993 }
1994 break;
1995 case 'E': /* a 'b' type extended to handle L/R register halves. */
1996 {
1997 struct pa_89_fp_reg_struct result;
1998 int status;
1999
2000 pa_89_parse_number (&s, &result);
2001 if (result.number_part < 32 && result.number_part >= 0)
2002 {
2003 opcode |= (result.number_part & 0x1f) << 21;
2004 if (need_89_opcode (&the_insn, &result))
2005 {
2006 opcode |= (result.L_R_select & 1) << 7;
2007 opcode |= 1 << 27;
2008 }
2009 continue;
2010 }
2011 }
2012 break;
2013
2014 case 'X': /* an 'x' type extended to handle L/R register halves. */
2015 {
2016 struct pa_89_fp_reg_struct result;
2017 int status;
2018
2019
2020 pa_89_parse_number (&s, &result);
2021 if (result.number_part < 32 && result.number_part >= 0)
2022 {
2023 opcode |= (result.number_part & 0x1f) << 16;
2024 if (need_89_opcode (&the_insn, &result))
2025 {
2026 opcode |= (result.L_R_select & 1) << 12;
2027 opcode |= 1 << 27;
2028 }
2029 continue;
2030 }
2031 }
2032 break;
2033
2034 case '4': /* 5 bit register field at 10
2035 (used in 'fmpyadd' and 'fmpysub') */
2036 {
2037 struct pa_89_fp_reg_struct result;
2038 int status;
2039
2040 status = pa_89_parse_number (&s, &result);
2041 if (result.number_part < 32 && result.number_part >= 0)
2042 {
2043 if (the_insn.fpof1 == SGL)
2044 {
2045 result.number_part &= 0xF;
2046 result.number_part |= (result.L_R_select & 1) << 4;
2047 }
2048 opcode |= result.number_part << 21;
2049 continue;
2050 }
2051 }
2052 break;
2053
2054 case '6': /* 5 bit register field at 15
2055 (used in 'fmpyadd' and 'fmpysub') */
2056 {
2057 struct pa_89_fp_reg_struct result;
2058 int status;
2059
2060 status = pa_89_parse_number (&s, &result);
2061 if (result.number_part < 32 && result.number_part >= 0)
2062 {
2063 if (the_insn.fpof1 == SGL)
2064 {
2065 result.number_part &= 0xF;
2066 result.number_part |= (result.L_R_select & 1) << 4;
2067 }
2068 opcode |= result.number_part << 16;
2069 continue;
2070 }
2071 }
2072 break;
2073
2074 case '7': /* 5 bit register field at 31
2075 (used in 'fmpyadd' and 'fmpysub') */
2076 {
2077 struct pa_89_fp_reg_struct result;
2078 int status;
2079
2080 status = pa_89_parse_number (&s, &result);
2081 if (result.number_part < 32 && result.number_part >= 0)
2082 {
2083 if (the_insn.fpof1 == SGL)
2084 {
2085 result.number_part &= 0xF;
2086 result.number_part |= (result.L_R_select & 1) << 4;
2087 }
2088 opcode |= result.number_part;
2089 continue;
2090 }
2091 }
2092 break;
2093
2094 case '8': /* 5 bit register field at 20
2095 (used in 'fmpyadd' and 'fmpysub') */
2096 {
2097 struct pa_89_fp_reg_struct result;
2098 int status;
2099
2100 status = pa_89_parse_number (&s, &result);
2101 if (result.number_part < 32 && result.number_part >= 0)
2102 {
2103 if (the_insn.fpof1 == SGL)
2104 {
2105 result.number_part &= 0xF;
2106 result.number_part |= (result.L_R_select & 1) << 4;
2107 }
2108 opcode |= result.number_part << 11;
2109 continue;
2110 }
2111 }
2112 break;
2113
2114 case '9': /* 5 bit register field at 25
2115 (used in 'fmpyadd' and 'fmpysub') */
2116 {
2117 struct pa_89_fp_reg_struct result;
2118 int status;
2119
2120 status = pa_89_parse_number (&s, &result);
2121 if (result.number_part < 32 && result.number_part >= 0)
2122 {
2123 if (the_insn.fpof1 == SGL)
2124 {
2125 result.number_part &= 0xF;
2126 result.number_part |= (result.L_R_select & 1) << 4;
2127 }
2128 opcode |= result.number_part << 6;
2129 continue;
2130 }
2131 }
2132 break;
2133
2134 case 'H': /* Floating Point Operand Format at 26 for */
2135 /* 'fmpyadd' and 'fmpysub' (very similar to 'F') */
2136 /* bits are switched from other FP Operand */
2137 /* formats. 1=SGL, 1=<none>, 0=DBL */
2138 f = pa_parse_fp_format (&s);
2139 switch (f)
2140 {
2141 case SGL:
2142 opcode |= 0x20;
2143 case DBL:
2144 the_insn.fpof1 = f;
2145 continue;
2146
2147 case QUAD:
2148 case ILLEGAL_FMT:
2149 default:
2150 as_bad ("Illegal Floating Point Operand Format for this instruction: '%s'", *s);
2151 }
2152 break;
2153
2154 default:
2155 abort ();
2156 }
2157 break;
2158 }
2159 error:
2160 if (match == FALSE)
2161 {
2162 /* Args don't match. */
2163 if (&insn[1] - pa_opcodes < NUMOPCODES
2164 && !strcmp (insn->name, insn[1].name))
2165 {
2166 ++insn;
2167 s = argsStart;
2168 continue;
2169 }
2170 else
2171 {
2172 as_bad ("Illegal operands %s", error_message);
2173 return;
2174 }
2175 }
2176 break;
2177 }
2178
2179 the_insn.opcode = opcode;
2180
2181 #ifdef PA_DEBUG
2182 if (the_insn.exp.X_add_symbol && the_insn.exp.X_subtract_symbol)
2183 print_insn_short (&the_insn);
2184 fprintf (stderr, "*********** END OF STATEMENT\n");
2185 #endif
2186
2187 return;
2188 }
2189
2190 /*
2191 This is identical to the md_atof in m68k.c. I think this is right,
2192 but I'm not sure.
2193
2194 Turn a string in input_line_pointer into a floating point constant of type
2195 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
2196 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
2197 */
2198
2199 /* Equal to MAX_PRECISION in atof-ieee.c */
2200 #define MAX_LITTLENUMS 6
2201
2202 char *
2203 md_atof (type, litP, sizeP)
2204 char type;
2205 char *litP;
2206 int *sizeP;
2207 {
2208 int prec;
2209 LITTLENUM_TYPE words[MAX_LITTLENUMS];
2210 LITTLENUM_TYPE *wordP;
2211 char *t;
2212 char *atof_ieee ();
2213
2214 switch (type)
2215 {
2216
2217 case 'f':
2218 case 'F':
2219 case 's':
2220 case 'S':
2221 prec = 2;
2222 break;
2223
2224 case 'd':
2225 case 'D':
2226 case 'r':
2227 case 'R':
2228 prec = 4;
2229 break;
2230
2231 case 'x':
2232 case 'X':
2233 prec = 6;
2234 break;
2235
2236 case 'p':
2237 case 'P':
2238 prec = 6;
2239 break;
2240
2241 default:
2242 *sizeP = 0;
2243 return "Bad call to MD_ATOF()";
2244 }
2245 t = atof_ieee (input_line_pointer, type, words);
2246 if (t)
2247 input_line_pointer = t;
2248 *sizeP = prec * sizeof (LITTLENUM_TYPE);
2249 for (wordP = words; prec--;)
2250 {
2251 md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
2252 litP += sizeof (LITTLENUM_TYPE);
2253 }
2254 return ""; /* Someone should teach Dean about null pointers */
2255 }
2256
2257 /*
2258 * Write out big-endian.
2259 */
2260 void
2261 md_number_to_chars (buf, val, n)
2262 char *buf;
2263 valueT val;
2264 int n;
2265 {
2266
2267 switch (n)
2268 {
2269
2270 case 4:
2271 *buf++ = val >> 24;
2272 *buf++ = val >> 16;
2273 case 2:
2274 *buf++ = val >> 8;
2275 case 1:
2276 *buf = val;
2277 break;
2278
2279 default:
2280 abort ();
2281 }
2282 return;
2283 }
2284
2285 void
2286 md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
2287 char *ptr;
2288 addressT from_addr, to_addr;
2289 fragS *frag;
2290 symbolS *to_symbol;
2291 {
2292 fprintf (stderr, "pa_create_short_jmp\n");
2293 abort ();
2294 }
2295
2296 void
2297 md_number_to_disp (buf, val, n)
2298 char *buf;
2299 long val;
2300 int n;
2301 {
2302 fprintf (stderr, "md_number_to_disp\n");
2303 abort ();
2304 }
2305
2306 void
2307 md_number_to_field (buf, val, fix)
2308 char *buf;
2309 long val;
2310 void *fix;
2311 {
2312 fprintf (stderr, "pa_number_to_field\n");
2313 abort ();
2314 }
2315
2316 /* the bit-field entries in the relocation_info struct plays hell
2317 with the byte-order problems of cross-assembly. So as a hack,
2318 I added this mach. dependent ri twiddler. Ugly, but it gets
2319 you there. -KWK */
2320 /* on sparc: first 4 bytes are normal unsigned long address, next three
2321 bytes are index, most sig. byte first. Byte 7 is broken up with
2322 bit 7 as external, bits 6 & 5 unused, and the lower
2323 five bits as relocation type. Next 4 bytes are long int addend. */
2324 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
2325
2326 #ifdef OBJ_SOM
2327 void
2328 md_ri_to_chars (ri_p, ri)
2329 struct reloc_info_pa *ri_p, ri;
2330 {
2331 unsigned char the_bytes[sizeof (*ri_p)];
2332 #if defined(OBJ_SOM) | defined(OBJ_OSFROSE) | defined(OBJ_ELF)
2333 /* not sure what, if any, changes are required for new-style cross-assembly */
2334 #else
2335 the_bytes[0] = ((ri.need_data_ref << 7) & 0x80) | ((ri.arg_reloc & 0x03f8) >> 3);
2336 the_bytes[1] = ((ri.arg_reloc & 0x07) << 5) | ri.expression_type;
2337 the_bytes[2] = ((ri.exec_level << 6) & 0xc0) | ri.fixup_format;
2338 the_bytes[3] = ri.fixup_field & 0xff;
2339 md_number_to_chars (&the_bytes[4], ri.subspace_offset, sizeof (ri.subspace_offset));
2340 md_number_to_chars (&the_bytes[8], ri.symbol_index_one, sizeof (ri.symbol_index_one));
2341 md_number_to_chars (&the_bytes[12], ri.symbol_index_two, sizeof (ri.symbol_index_two));
2342 md_number_to_chars (&the_bytes[16], ri.fixup_constant, sizeof (ri.fixup_constant));
2343
2344 /* now put it back where you found it, Junior... */
2345 bcopy (the_bytes, (char *) ri_p, sizeof (*ri_p));
2346 #endif
2347
2348 }
2349
2350 #endif
2351
2352
2353 /* Translate internal representation of relocation info to BFD target
2354 format. */
2355 /* This may need additional work to make sure that SOM support is complete. */
2356 #ifdef OBJ_ELF
2357 arelent **
2358 tc_gen_reloc (section, fixp)
2359 asection *section;
2360 fixS *fixp;
2361 {
2362 arelent *reloc;
2363 hppa_fixS *hppa_fixp = hppa_find_hppa_fix (fixp);
2364 bfd_reloc_code_real_type code;
2365 static int unwind_reloc_fixp_cnt = 0;
2366 static arelent *unwind_reloc_entryP = NULL;
2367 static arelent *no_relocs = NULL;
2368 arelent **relocs;
2369 bfd_reloc_code_real_type **codes;
2370 int n_relocs;
2371 int i;
2372
2373 if (fixp->fx_addsy == 0)
2374 return &no_relocs;
2375 assert (hppa_fixp != 0);
2376 assert (section != 0);
2377
2378 /* unwind section relocations are handled in a special way. */
2379 /* The relocations for the .unwind section are originally */
2380 /* built in the usual way. That is, for each unwind table */
2381 /* entry there are two relocations: one for the beginning of */
2382 /* the function and one for the end. */
2383
2384 /* The first time we enter this function we create a */
2385 /* relocation of the type R_HPPA_UNWIND_ENTRIES. The addend */
2386 /* of the relocation is initialized to 0. Each additional */
2387 /* pair of times this function is called for the unwind */
2388 /* section represents an additional unwind table entry. Thus, */
2389 /* the addend of the relocation should end up to be the number */
2390 /* of unwind table entries. */
2391 if (strcmp (UNWIND_SECTION_NAME, section->name) == 0)
2392 {
2393 if (unwind_reloc_entryP == NULL)
2394 {
2395 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
2396 assert (reloc != 0);
2397 unwind_reloc_entryP = reloc;
2398 unwind_reloc_fixp_cnt++;
2399 unwind_reloc_entryP->address = fixp->fx_frag->fr_address + fixp->fx_where;
2400 /* a pointer any function will do. We only */
2401 /* need one to tell us what section the unwind */
2402 /* relocations are for. */
2403 unwind_reloc_entryP->sym_ptr_ptr = &fixp->fx_addsy->bsym;
2404 code = R_HPPA_UNWIND_ENTRIES;
2405 unwind_reloc_entryP->howto = bfd_reloc_type_lookup (stdoutput, code);
2406 unwind_reloc_entryP->addend = unwind_reloc_fixp_cnt / 2;
2407 relocs = (arelent **) bfd_alloc_by_size_t (stdoutput, sizeof (arelent *) * 2);
2408 assert (relocs != 0);
2409 relocs[0] = unwind_reloc_entryP;
2410 relocs[1] = NULL;
2411 return relocs;
2412 }
2413 unwind_reloc_fixp_cnt++;
2414 unwind_reloc_entryP->addend = unwind_reloc_fixp_cnt / 2;
2415
2416 return &no_relocs;
2417 }
2418
2419 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
2420 assert (reloc != 0);
2421
2422 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
2423 /* XXX: might need additional processing here */
2424 /* hppa_elf_gen_reloc_type() is defined in the */
2425 /* ELF/PA BFD back-end */
2426 codes = hppa_elf_gen_reloc_type (stdoutput,
2427 fixp->fx_r_type,
2428 hppa_fixp->fx_r_format,
2429 hppa_fixp->fx_r_field);
2430
2431 for (n_relocs = 0; codes[n_relocs]; n_relocs++)
2432 ;
2433
2434 relocs = (arelent **) bfd_alloc_by_size_t (stdoutput, sizeof (arelent *) * n_relocs + 1);
2435 assert (relocs != 0);
2436
2437 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent) * n_relocs);
2438 if (n_relocs > 0)
2439 assert (reloc != 0);
2440
2441 for (i = 0; i < n_relocs; i++)
2442 relocs[i] = &reloc[i];
2443
2444 relocs[n_relocs] = NULL;
2445
2446 switch (fixp->fx_r_type)
2447 {
2448 case R_HPPA_COMPLEX:
2449 case R_HPPA_COMPLEX_PCREL_CALL:
2450 case R_HPPA_COMPLEX_ABS_CALL:
2451 assert (n_relocs == 5);
2452
2453 for (i = 0; i < n_relocs; i++)
2454 {
2455 reloc[i].sym_ptr_ptr = NULL;
2456 reloc[i].address = 0;
2457 reloc[i].addend = 0;
2458 reloc[i].howto = bfd_reloc_type_lookup (stdoutput, *codes[i]);
2459 assert (reloc[i].howto && *codes[i] == reloc[i].howto->type);
2460 }
2461
2462 reloc[0].sym_ptr_ptr = &fixp->fx_addsy->bsym;
2463 reloc[1].sym_ptr_ptr = &fixp->fx_subsy->bsym;
2464 reloc[4].address = fixp->fx_frag->fr_address + fixp->fx_where;
2465
2466 if (fixp->fx_r_type == R_HPPA_COMPLEX)
2467 reloc[3].addend = fixp->fx_addnumber;
2468 else if (fixp->fx_r_type == R_HPPA_COMPLEX_PCREL_CALL ||
2469 fixp->fx_r_type == R_HPPA_COMPLEX_ABS_CALL)
2470 reloc[1].addend = fixp->fx_addnumber;
2471
2472 break;
2473
2474 default:
2475 assert (n_relocs == 1);
2476
2477 code = *codes[0];
2478
2479 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
2480 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
2481 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
2482 reloc->addend = 0; /* default */
2483
2484 assert (reloc->howto && code == reloc->howto->type);
2485
2486 /* Now, do any processing that is dependent on the relocation */
2487 /* type. */
2488 switch (code)
2489 {
2490 case R_HPPA_PLABEL_32:
2491 case R_HPPA_PLABEL_11:
2492 case R_HPPA_PLABEL_14:
2493 case R_HPPA_PLABEL_L21:
2494 case R_HPPA_PLABEL_R11:
2495 case R_HPPA_PLABEL_R14:
2496 /* For plabel relocations, the addend of the */
2497 /* relocation should be either 0 (no static link) or 2 */
2498 /* (static link required). */
2499 /* XXX: assume that fx_addnumber contains this */
2500 /* information */
2501 reloc->addend = fixp->fx_addnumber;
2502 break;
2503
2504 case R_HPPA_ABS_CALL_11:
2505 case R_HPPA_ABS_CALL_14:
2506 case R_HPPA_ABS_CALL_17:
2507 case R_HPPA_ABS_CALL_L21:
2508 case R_HPPA_ABS_CALL_R11:
2509 case R_HPPA_ABS_CALL_R14:
2510 case R_HPPA_ABS_CALL_R17:
2511 case R_HPPA_ABS_CALL_LS21:
2512 case R_HPPA_ABS_CALL_RS11:
2513 case R_HPPA_ABS_CALL_RS14:
2514 case R_HPPA_ABS_CALL_RS17:
2515 case R_HPPA_ABS_CALL_LD21:
2516 case R_HPPA_ABS_CALL_RD11:
2517 case R_HPPA_ABS_CALL_RD14:
2518 case R_HPPA_ABS_CALL_RD17:
2519 case R_HPPA_ABS_CALL_LR21:
2520 case R_HPPA_ABS_CALL_RR14:
2521 case R_HPPA_ABS_CALL_RR17:
2522
2523 case R_HPPA_PCREL_CALL_11:
2524 case R_HPPA_PCREL_CALL_14:
2525 case R_HPPA_PCREL_CALL_17:
2526 case R_HPPA_PCREL_CALL_L21:
2527 case R_HPPA_PCREL_CALL_R11:
2528 case R_HPPA_PCREL_CALL_R14:
2529 case R_HPPA_PCREL_CALL_R17:
2530 case R_HPPA_PCREL_CALL_LS21:
2531 case R_HPPA_PCREL_CALL_RS11:
2532 case R_HPPA_PCREL_CALL_RS14:
2533 case R_HPPA_PCREL_CALL_RS17:
2534 case R_HPPA_PCREL_CALL_LD21:
2535 case R_HPPA_PCREL_CALL_RD11:
2536 case R_HPPA_PCREL_CALL_RD14:
2537 case R_HPPA_PCREL_CALL_RD17:
2538 case R_HPPA_PCREL_CALL_LR21:
2539 case R_HPPA_PCREL_CALL_RR14:
2540 case R_HPPA_PCREL_CALL_RR17:
2541 /* constant is stored in the instruction */
2542 reloc->addend = ELF32_HPPA_R_ADDEND (hppa_fixp->fx_arg_reloc, 0);
2543 break;
2544 default:
2545 reloc->addend = fixp->fx_addnumber;
2546 break;
2547 }
2548 break;
2549 }
2550
2551 return relocs;
2552 }
2553
2554 #else
2555 arelent *
2556 tc_gen_reloc (section, fixp)
2557 asection *section;
2558 fixS *fixp;
2559 {
2560 arelent *reloc;
2561 hppa_fixS *hppa_fixp = hppa_find_hppa_fix (fixp);
2562 bfd_reloc_code_real_type code;
2563
2564 if (fixp->fx_addsy == 0)
2565 return 0;
2566 assert (hppa_fixp != 0);
2567 assert (section != 0);
2568
2569 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
2570 assert (reloc != 0);
2571
2572 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
2573 /* XXX: might need additional processing here */
2574 /* hppa_elf_gen_reloc_type() is defined in the */
2575 /* ELF/PA BFD back-end */
2576 code = hppa_elf_gen_reloc_type (stdoutput,
2577 fixp->fx_r_type,
2578 hppa_fixp->fx_r_format,
2579 hppa_fixp->fx_r_field);
2580 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
2581
2582 assert (code == reloc->howto->type);
2583
2584 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
2585 reloc->addend = 0; /* default */
2586
2587 /* Now, do any processing that is dependent on the relocation */
2588 /* type. (Is there any?) */
2589 switch (code)
2590 {
2591 default:
2592 reloc->addend = fixp->fx_addnumber;
2593 break;
2594 }
2595
2596 return reloc;
2597 }
2598
2599 #endif
2600
2601 void
2602 md_convert_frag (abfd, sec, fragP)
2603 register bfd *abfd;
2604 register asection *sec;
2605 register fragS *fragP;
2606 {
2607 unsigned int address;
2608
2609 if (fragP->fr_type == rs_machine_dependent)
2610 {
2611 switch ((int) fragP->fr_subtype)
2612 {
2613 case 0:
2614 fragP->fr_type = rs_fill;
2615 know (fragP->fr_var == 1);
2616 know (fragP->fr_next);
2617 address = fragP->fr_address + fragP->fr_fix;
2618 if (address % fragP->fr_offset)
2619 {
2620 fragP->fr_offset =
2621 fragP->fr_next->fr_address
2622 - fragP->fr_address
2623 - fragP->fr_fix;
2624 }
2625 else
2626 fragP->fr_offset = 0;
2627 break;
2628 }
2629 }
2630 }
2631
2632 /* Round up a section size to the appropriate boundary. */
2633 valueT
2634 md_section_align (segment, size)
2635 asection *segment;
2636 valueT size;
2637 {
2638 return (size + 7) & ~7; /* Round all sects to multiple of 8 */
2639 } /* md_section_align() */
2640
2641 void
2642 md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
2643 char *ptr;
2644 addressT from_addr, to_addr;
2645 fragS *frag;
2646 symbolS *to_symbol;
2647 {
2648 fprintf (stderr, "pa_create_long_jump\n");
2649 abort ();
2650 }
2651
2652 int
2653 /* md_estimate_size_before_relax(fragP, segtype) */
2654 md_estimate_size_before_relax (fragP, segment)
2655 register fragS *fragP;
2656 asection *segment;
2657 {
2658 int size;
2659
2660 size = 0;
2661
2662 while ((fragP->fr_fix + size) % fragP->fr_offset)
2663 size++;
2664
2665 return size;
2666 }
2667
2668 int
2669 md_parse_option (argP, cntP, vecP)
2670 char **argP;
2671 int *cntP;
2672 char ***vecP;
2673 {
2674 return 1;
2675 }
2676
2677 /* We have no need to default values of symbols. */
2678
2679 /* ARGSUSED */
2680 symbolS *
2681 md_undefined_symbol (name)
2682 char *name;
2683 {
2684 return 0;
2685 } /*md_undefined_symbol() */
2686
2687 /* Parse an operand that is machine-specific.
2688 We just return without modifying the expression if we have nothing
2689 to do. */
2690
2691 /* ARGSUSED */
2692 void
2693 md_operand (expressionP)
2694 expressionS *expressionP;
2695 {
2696 }
2697
2698 /* Apply a fixS to the frags, now that we know the value it ought to
2699 hold. */
2700
2701 int
2702 apply_field_selector (value, constant, field_selector)
2703 long value;
2704 long constant;
2705 int field_selector;
2706 {
2707 /* hppa_field_adjust() is defined in the HPPA target */
2708 return hppa_field_adjust (value, constant, field_selector);
2709 }
2710
2711 void
2712 md_apply_fix_1 (fixP, val)
2713 fixS *fixP;
2714 long val;
2715 {
2716 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
2717 hppa_fixS *hppa_fixP = hppa_find_hppa_fix (fixP);
2718 long new_val;
2719 long result;
2720 unsigned int w1, w2, w;
2721 /* The following routine is defined in the ELF/PA back-end */
2722 extern unsigned char hppa_elf_insn2fmt ();
2723
2724 if (hppa_fixP)
2725 {
2726 unsigned long buf_wd = bfd_get_32 (stdoutput, buf);
2727 unsigned char fmt = hppa_elf_insn2fmt (fixP->fx_r_type, buf_wd);
2728
2729 assert (fixP->fx_r_type < R_HPPA_UNIMPLEMENTED);
2730 assert (fixP->fx_r_type >= R_HPPA_NONE);
2731
2732 fixP->fx_addnumber = val; /* Remember value for emit_reloc */
2733
2734 /* Check if this is an undefined symbol. No relocation can */
2735 /* possibly be performed in this case. */
2736
2737 if ((fixP->fx_addsy && fixP->fx_addsy->bsym->section == &bfd_und_section)
2738 || (fixP->fx_subsy && fixP->fx_subsy->bsym->section == &bfd_und_section))
2739 return;
2740
2741 /* Perform some processing particular to unwind */
2742 /* relocations */
2743
2744 if (hppa_fixP->fx_call_infop
2745 && (((fixP == hppa_fixP->fx_call_infop->start_fix)
2746 && (fixP->fx_addsy ==
2747 hppa_fixP->fx_call_infop->start_symbol))
2748 || ((fixP == hppa_fixP->fx_call_infop->end_fix)
2749 && (fixP->fx_addsy ==
2750 hppa_fixP->fx_call_infop->end_symbol))
2751 ))
2752 val += fixP->fx_addsy->sy_frag->fr_address;
2753
2754 switch (fmt)
2755 {
2756
2757 case 14: /* all the opcodes with the 'j' operand type */
2758 new_val = apply_field_selector (val, 0, hppa_fixP->fx_r_field);
2759 /* need to check for overflow here */
2760
2761 /* mask off 14 bits to be changed */
2762 /* *(long *)buf = *(long *)buf & 0xffffc000; */
2763 bfd_put_32 (stdoutput,
2764 bfd_get_32 (stdoutput, buf) & 0xffffc000,
2765 buf);
2766 low_sign_unext (new_val, 14, &result);
2767 break;
2768
2769 case 21: /* all the opcodes with the 'k' operand type */
2770 new_val = apply_field_selector (val, 0, hppa_fixP->fx_r_field);
2771 /* need to check for overflow here */
2772
2773 /* mask off 21 bits to be changed */
2774 /* *(long *)buf = *(long *)buf & 0xffe00000; */
2775 bfd_put_32 (stdoutput,
2776 bfd_get_32 (stdoutput, buf) & 0xffe00000,
2777 buf);
2778 dis_assemble_21 (new_val, &result);
2779 break;
2780
2781 case 11: /* all the opcodes with the 'i' operand type */
2782 new_val = apply_field_selector (val, 0, hppa_fixP->fx_r_field);
2783 /* need to check for overflow here */
2784
2785 /* mask off 11 bits to be changed */
2786 /* *(long *)buf = *(long *)buf & 0xffff800; */
2787 bfd_put_32 (stdoutput,
2788 bfd_get_32 (stdoutput, buf) & 0xffff800,
2789 buf);
2790 low_sign_unext (new_val, 11, &result);
2791 break;
2792
2793 case 12: /* all the opcodes with the 'w' operand type */
2794 new_val = apply_field_selector (val, 0, hppa_fixP->fx_r_field);
2795
2796 /* mask off 11 bits to be changed */
2797 sign_unext ((new_val - 8) >> 2, 12, &result);
2798 /* *(long *)buf = *(long *)buf & 0xffffe002; */
2799 bfd_put_32 (stdoutput,
2800 bfd_get_32 (stdoutput, buf) & 0xffffe002,
2801 buf);
2802
2803 dis_assemble_12 (result, &w1, &w);
2804 result = ((w1 << 2) | w);
2805 break;
2806
2807 case 17: /* some of the opcodes with the 'W' operand type */
2808 new_val = apply_field_selector (val, 0, hppa_fixP->fx_r_field);
2809 /* need to check for overflow here */
2810
2811 /* mask off 17 bits to be changed */
2812 /* *(long *)buf = *(long *)buf & 0xffe0e002; */
2813 bfd_put_32 (stdoutput,
2814 bfd_get_32 (stdoutput, buf) & 0xffe0e002,
2815 buf);
2816 sign_unext ((new_val - 8) >> 2, 17, &result);
2817 dis_assemble_17 (result, &w1, &w2, &w);
2818 result = ((w2 << 2) | (w1 << 16) | w);
2819 break;
2820
2821 case 32:
2822 new_val = apply_field_selector (val, 0, hppa_fixP->fx_r_field);
2823 result = new_val; /* no transformation on result */
2824 /* *(long *)buf = 0; *//* clear out everything */
2825 bfd_put_32 (stdoutput, 0, buf); /* clear out everything */
2826 break;
2827
2828 case 0:
2829 return;
2830
2831 default:
2832 as_bad ("bad relocation type/fmt: 0x%02x/0x%02x",
2833 fixP->fx_r_type, fmt);
2834 return;
2835 }
2836 buf[0] |= (result & 0xff000000) >> 24;
2837 buf[1] |= (result & 0x00ff0000) >> 16;
2838 buf[2] |= (result & 0x0000ff00) >> 8;
2839 buf[3] |= result & 0x000000ff;
2840 /* We've now adjusted for fx_addnumber, we can */
2841 /* forget it now. */
2842 fixP->fx_addnumber = 0;
2843 }
2844 else
2845 {
2846 printf ("no hppa_fixup entry for this fixup (fixP = 0x%x, type = 0x%x)\n",
2847 fixP, fixP->fx_r_type);
2848 }
2849 } /* md_apply_fix_1() */
2850
2851 #ifdef BFD_ASSEMBLER
2852 int
2853 md_apply_fix (fixP, valp)
2854 fixS *fixP;
2855 long *valp;
2856 {
2857 md_apply_fix_1 (fixP, *valp);
2858 return 1;
2859 }
2860
2861 #else
2862 void
2863 md_apply_fix (fixP, val)
2864 fixS *fixP;
2865 long val;
2866 {
2867 md_apply_fix_1 (fixP, val);
2868 }
2869
2870 #endif
2871
2872 /* Exactly what point is a PC-relative offset relative TO?
2873 On the PA, they're relative to the address of the offset.
2874 (??? Is this right? FIXME-SOON) */
2875 long
2876 md_pcrel_from (fixP)
2877 fixS *fixP;
2878 {
2879 return fixP->fx_where + fixP->fx_frag->fr_address;
2880 } /* md_pcrel_from() */
2881
2882 int
2883 is_end_of_statement ()
2884 {
2885 return ((*input_line_pointer == '\n')
2886 || (*input_line_pointer == ';')
2887 || (*input_line_pointer == '!'));
2888 }
2889
2890 /* pa-aux.c -- Assembler for the PA - PA-RISC specific support routines */
2891
2892 struct aux_hdr_list *aux_hdr_root = NULL;
2893
2894 int print_errors = 1;
2895
2896 void
2897 pa_skip (s)
2898 char **s;
2899 {
2900 while (**s == ' ' || **s == '\t')
2901 *s = *s + 1;
2902 }
2903
2904 int
2905 pa_parse_number (s)
2906 char **s;
2907 {
2908 int num;
2909 char *name;
2910 char c;
2911 symbolS *sym;
2912 int status;
2913 char *p = *s;
2914
2915 while (*p == ' ' || *p == '\t')
2916 p = p + 1;
2917 num = -1; /* assume invalid number to begin with */
2918 if (isdigit (*p))
2919 {
2920 num = 0; /* now we know it is a number */
2921
2922 if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
2923 { /* hex input */
2924 p = p + 2;
2925 while (isdigit (*p) || ((*p >= 'a') && (*p <= 'f'))
2926 || ((*p >= 'A') && (*p <= 'F')))
2927 {
2928 if (isdigit (*p))
2929 num = num * 16 + *p - '0';
2930 else if (*p >= 'a' && *p <= 'f')
2931 num = num * 16 + *p - 'a' + 10;
2932 else
2933 num = num * 16 + *p - 'A' + 10;
2934 ++p;
2935 }
2936 }
2937 else
2938 {
2939 while (isdigit (*p))
2940 {
2941 num = num * 10 + *p - '0';
2942 ++p;
2943 }
2944 }
2945 }
2946 else if (*p == '%')
2947 { /* could be a pre-defined register */
2948 num = 0;
2949 name = p;
2950 p++;
2951 c = *p;
2952 /* tege hack: Special case for general registers
2953 as the general code makes a binary search with case translation,
2954 and is VERY slow. */
2955 if (c == 'r')
2956 {
2957 p++;
2958 if (*p == 'e' && *(p + 1) == 't' && (*(p + 2) == '0' || *(p + 2) == '1'))
2959 {
2960 p += 2;
2961 num = *p - '0' + 28; /* r28 is ret0 */
2962 p++;
2963 }
2964 else if (!isdigit (*p))
2965 as_bad ("Undefined register: '%s'. ASSUMING 0", name);
2966 else
2967 {
2968 do
2969 num = num * 10 + *p++ - '0';
2970 while (isdigit (*p));
2971 }
2972 }
2973 else
2974 {
2975 while (is_part_of_name (c))
2976 {
2977 p = p + 1;
2978 c = *p;
2979 }
2980 *p = 0;
2981 status = reg_name_search (name);
2982 if (status >= 0)
2983 num = status;
2984 else
2985 {
2986 if (print_errors)
2987 as_bad ("Undefined register: '%s'. ASSUMING 0", name);
2988 else
2989 num = -1;
2990 }
2991 *p = c;
2992 }
2993 }
2994 else
2995 {
2996 num = 0;
2997 name = p;
2998 c = *p;
2999 while (is_part_of_name (c))
3000 {
3001 p = p + 1;
3002 c = *p;
3003 }
3004 *p = 0;
3005 if ((sym = symbol_find (name)) != NULL)
3006 {
3007 #ifdef OBJ_SOM
3008 if (sym->pa_sy_type == ST_ABSOLUTE)
3009 {
3010 num = sym->pa_sy_value;
3011 #else
3012 if (S_GET_SEGMENT (sym) == &bfd_abs_section)
3013 {
3014 num = S_GET_VALUE (sym);
3015 #endif
3016 }
3017 else
3018 {
3019 if (print_errors)
3020 as_bad ("Non-absolute constant: '%s'. ASSUMING 0", name);
3021 else
3022 num = -1;
3023 }
3024 }
3025 else
3026 {
3027 if (print_errors)
3028 as_bad ("Undefined absolute constant: '%s'. ASSUMING 0", name);
3029 else
3030 num = -1;
3031 }
3032 *p = c;
3033 }
3034
3035 *s = p;
3036 return num;
3037 }
3038
3039 struct pd_reg
3040 {
3041 char *name;
3042 int value;
3043 };
3044
3045 /* List of registers that are pre-defined:
3046
3047 General Registers:
3048
3049 Name Value Name Value
3050 %r0 0 %r16 16
3051 %r1 1 %r17 17
3052 %r2 2 %r18 18
3053 %r3 3 %r19 19
3054 %r4 4 %r20 20
3055 %r5 5 %r21 21
3056 %r6 6 %r22 22
3057 %r7 7 %r23 23
3058 %r8 8 %r24 24
3059 %r9 9 %r25 25
3060 %r10 10 %r26 26
3061 %r11 11 %r27 27
3062 %r12 12 %r28 28
3063 %r13 13 %r29 29
3064 %r14 14 %r30 30
3065 %r15 15 %r31 31
3066
3067 Floating-point Registers:
3068 [NOTE: Also includes L and R versions of these (e.g. %fr19L, %fr19R)]
3069
3070 Name Value Name Value
3071 %fr0 0 %fr16 16
3072 %fr1 1 %fr17 17
3073 %fr2 2 %fr18 18
3074 %fr3 3 %fr19 19
3075 %fr4 4 %fr20 20
3076 %fr5 5 %fr21 21
3077 %fr6 6 %fr22 22
3078 %fr7 7 %fr23 23
3079 %fr8 8 %fr24 24
3080 %fr9 9 %fr25 25
3081 %fr10 10 %fr26 26
3082 %fr11 11 %fr27 27
3083 %fr12 12 %fr28 28
3084 %fr13 13 %fr29 29
3085 %fr14 14 %fr30 30
3086 %fr15 15 %fr31 31
3087
3088 Space Registers:
3089
3090 Name Value Name Value
3091 %sr0 0 %sr4 4
3092 %sr1 1 %sr5 5
3093 %sr2 2 %sr6 6
3094 %sr3 3 %sr7 7
3095
3096 Control registers and their synonyms:
3097
3098 Names Value
3099 %cr0 %rctr 0
3100 %cr8 %pidr1 8
3101 %cr9 %pidr2 9
3102 %cr10 %ccr 10
3103 %cr11 %sar 11
3104 %cr12 %pidr3 12
3105 %cr13 %pidr4 13
3106 %cr14 %iva 14
3107 %cr15 %eiem 15
3108 %cr16 %itmr 16
3109 %cr17 %pcsq 17
3110 %cr18 %pcoq 18
3111 %cr19 %iir 19
3112 %cr20 %isr 20
3113 %cr21 %ior 21
3114 %cr22 %ipsw 22
3115 %cr23 %eirr 23
3116 %cr24 %tr0 %ppda 24
3117 %cr25 %tr1 %hta 25
3118 %cr26 %tr2 26
3119 %cr27 %tr3 27
3120 %cr28 %tr4 28
3121 %cr29 %tr5 29
3122 %cr30 %tr6 30
3123 %cr31 %tr7 31
3124
3125 Miscellaneous registers and their synonyms:
3126
3127 Names Value
3128 %arg0 26
3129 %arg1 25
3130 %arg2 24
3131 %arg3 23
3132 %sp 30
3133 %ret0 28
3134 %ret1 29
3135 */
3136
3137 /* This table is sorted. Suitable for searching by a binary search. */
3138
3139 static struct pd_reg pre_defined_registers[] =
3140 {
3141 {"%arg0", 26},
3142 {"%arg1", 25},
3143 {"%arg2", 24},
3144 {"%arg3", 23},
3145 {"%cr0", 0},
3146 {"%cr10", 10},
3147 {"%cr11", 11},
3148 {"%cr12", 12},
3149 {"%cr13", 13},
3150 {"%cr14", 14},
3151 {"%cr15", 15},
3152 {"%cr16", 16},
3153 {"%cr17", 17},
3154 {"%cr18", 18},
3155 {"%cr19", 19},
3156 {"%cr20", 20},
3157 {"%cr21", 21},
3158 {"%cr22", 22},
3159 {"%cr23", 23},
3160 {"%cr24", 24},
3161 {"%cr25", 25},
3162 {"%cr26", 26},
3163 {"%cr27", 27},
3164 {"%cr28", 28},
3165 {"%cr29", 29},
3166 {"%cr30", 30},
3167 {"%cr31", 31},
3168 {"%cr8", 8},
3169 {"%cr9", 9},
3170 {"%eiem", 15},
3171 {"%eirr", 23},
3172 {"%fr0", 0},
3173 {"%fr0L", 0},
3174 {"%fr0R", 0},
3175 {"%fr1", 1},
3176 {"%fr10", 10},
3177 {"%fr10L", 10},
3178 {"%fr10R", 10},
3179 {"%fr11", 11},
3180 {"%fr11L", 11},
3181 {"%fr11R", 11},
3182 {"%fr12", 12},
3183 {"%fr12L", 12},
3184 {"%fr12R", 12},
3185 {"%fr13", 13},
3186 {"%fr13L", 13},
3187 {"%fr13R", 13},
3188 {"%fr14", 14},
3189 {"%fr14L", 14},
3190 {"%fr14R", 14},
3191 {"%fr15", 15},
3192 {"%fr15L", 15},
3193 {"%fr15R", 15},
3194 {"%fr16", 16},
3195 {"%fr16L", 16},
3196 {"%fr16R", 16},
3197 {"%fr17", 17},
3198 {"%fr17L", 17},
3199 {"%fr17R", 17},
3200 {"%fr18", 18},
3201 {"%fr18L", 18},
3202 {"%fr18R", 18},
3203 {"%fr19", 19},
3204 {"%fr19L", 19},
3205 {"%fr19R", 19},
3206 {"%fr1L", 1},
3207 {"%fr1R", 1},
3208 {"%fr2", 2},
3209 {"%fr20", 20},
3210 {"%fr20L", 20},
3211 {"%fr20R", 20},
3212 {"%fr21", 21},
3213 {"%fr21L", 21},
3214 {"%fr21R", 21},
3215 {"%fr22", 22},
3216 {"%fr22L", 22},
3217 {"%fr22R", 22},
3218 {"%fr23", 23},
3219 {"%fr23L", 23},
3220 {"%fr23R", 23},
3221 {"%fr24", 24},
3222 {"%fr24L", 24},
3223 {"%fr24R", 24},
3224 {"%fr25", 25},
3225 {"%fr25L", 25},
3226 {"%fr25R", 25},
3227 {"%fr26", 26},
3228 {"%fr26L", 26},
3229 {"%fr26R", 26},
3230 {"%fr27", 27},
3231 {"%fr27L", 27},
3232 {"%fr27R", 27},
3233 {"%fr28", 28},
3234 {"%fr28L", 28},
3235 {"%fr28R", 28},
3236 {"%fr29", 29},
3237 {"%fr29L", 29},
3238 {"%fr29R", 29},
3239 {"%fr2L", 2},
3240 {"%fr2R", 2},
3241 {"%fr3", 3},
3242 {"%fr30", 30},
3243 {"%fr30L", 30},
3244 {"%fr30R", 30},
3245 {"%fr31", 31},
3246 {"%fr31L", 31},
3247 {"%fr31R", 31},
3248 {"%fr3L", 3},
3249 {"%fr3R", 3},
3250 {"%fr4", 4},
3251 {"%fr4L", 4},
3252 {"%fr4R", 4},
3253 {"%fr5", 5},
3254 {"%fr5L", 5},
3255 {"%fr5R", 5},
3256 {"%fr6", 6},
3257 {"%fr6L", 6},
3258 {"%fr6R", 6},
3259 {"%fr7", 7},
3260 {"%fr7L", 7},
3261 {"%fr7R", 7},
3262 {"%fr8", 8},
3263 {"%fr8L", 8},
3264 {"%fr8R", 8},
3265 {"%fr9", 9},
3266 {"%fr9L", 9},
3267 {"%fr9R", 9},
3268 {"%hta", 25},
3269 {"%iir", 19},
3270 {"%ior", 21},
3271 {"%ipsw", 22},
3272 {"%isr", 20},
3273 {"%itmr", 16},
3274 {"%iva", 14},
3275 {"%pcoq", 18},
3276 {"%pcsq", 17},
3277 {"%pidr1", 8},
3278 {"%pidr2", 9},
3279 {"%pidr3", 12},
3280 {"%pidr4", 13},
3281 {"%ppda", 24},
3282 {"%r0", 0},
3283 {"%r1", 1},
3284 {"%r10", 10},
3285 {"%r11", 11},
3286 {"%r12", 12},
3287 {"%r13", 13},
3288 {"%r14", 14},
3289 {"%r15", 15},
3290 {"%r16", 16},
3291 {"%r17", 17},
3292 {"%r18", 18},
3293 {"%r19", 19},
3294 {"%r2", 2},
3295 {"%r20", 20},
3296 {"%r21", 21},
3297 {"%r22", 22},
3298 {"%r23", 23},
3299 {"%r24", 24},
3300 {"%r25", 25},
3301 {"%r26", 26},
3302 {"%r27", 27},
3303 {"%r28", 28},
3304 {"%r29", 29},
3305 {"%r3", 3},
3306 {"%r30", 30},
3307 {"%r31", 31},
3308 {"%r4", 4},
3309 {"%r4L", 4},
3310 {"%r4R", 4},
3311 {"%r5", 5},
3312 {"%r5L", 5},
3313 {"%r5R", 5},
3314 {"%r6", 6},
3315 {"%r6L", 6},
3316 {"%r6R", 6},
3317 {"%r7", 7},
3318 {"%r7L", 7},
3319 {"%r7R", 7},
3320 {"%r8", 8},
3321 {"%r8L", 8},
3322 {"%r8R", 8},
3323 {"%r9", 9},
3324 {"%r9L", 9},
3325 {"%r9R", 9},
3326 {"%rctr", 0},
3327 {"%ret0", 28},
3328 {"%ret1", 29},
3329 {"%sar", 11},
3330 {"%sp", 30},
3331 {"%sr0", 0},
3332 {"%sr1", 1},
3333 {"%sr2", 2},
3334 {"%sr3", 3},
3335 {"%sr4", 4},
3336 {"%sr5", 5},
3337 {"%sr6", 6},
3338 {"%sr7", 7},
3339 {"%tr0", 24},
3340 {"%tr1", 25},
3341 {"%tr2", 26},
3342 {"%tr3", 27},
3343 {"%tr4", 28},
3344 {"%tr5", 29},
3345 {"%tr6", 30},
3346 {"%tr7", 31}
3347 };
3348
3349 #define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct pd_reg))
3350
3351 int
3352 reg_name_search (name)
3353 char *name;
3354 {
3355 int x, l, r;
3356
3357 l = 0;
3358 r = REG_NAME_CNT - 1;
3359
3360 do
3361 {
3362 x = (l + r) / 2;
3363 if (strcasecmp (name, pre_defined_registers[x].name) < 0)
3364 r = x - 1;
3365 else
3366 l = x + 1;
3367 }
3368 while (!((strcasecmp (name, pre_defined_registers[x].name) == 0) ||
3369 (l > r)));
3370
3371 if (strcasecmp (name, pre_defined_registers[x].name) == 0)
3372 return (pre_defined_registers[x].value);
3373 else
3374 return (-1);
3375
3376 }
3377
3378 int
3379 is_pre_defined_register (s)
3380 char *s;
3381 {
3382 if (reg_name_search (s) >= 0)
3383 return (TRUE);
3384 else
3385 return (FALSE);
3386 }
3387
3388 int
3389 is_R_select (s)
3390 char *s;
3391 {
3392
3393 if (*s == 'R' || *s == 'r')
3394 return (TRUE);
3395 else
3396 return (FALSE);
3397 }
3398
3399 int
3400 is_L_select (s)
3401 char *s;
3402 {
3403
3404 if (*s == 'L' || *s == 'l')
3405 return (TRUE);
3406 else
3407 return (FALSE);
3408 }
3409
3410 int
3411 need_89_opcode (insn, result)
3412 struct pa_it *insn;
3413 struct pa_89_fp_reg_struct *result;
3414 {
3415 /* if ( result->L_R_select == 1 || insn->fpof1 == DBL || insn->fpof2 == DBL ) */
3416 /* if (result->L_R_select == 1 && !(insn->fpof1 == DBL || insn->fpof2 == DBL) ) */
3417 if (result->L_R_select == 1 && !(insn->fpof1 == DBL && insn->fpof2 == DBL))
3418 /* if ( insn->fpof1 == DBL || insn->fpof2 == DBL ) */
3419 return TRUE;
3420 else
3421 return FALSE;
3422 }
3423
3424 int
3425 pa_89_parse_number (s, result)
3426 char **s;
3427 struct pa_89_fp_reg_struct *result;
3428 {
3429 int num;
3430 char *name;
3431 char c;
3432 symbolS *sym;
3433 int status;
3434 char *p = *s;
3435
3436 while (*p == ' ' || *p == '\t')
3437 p = p + 1;
3438 num = -1; /* assume invalid number to begin with */
3439 result->number_part = -1;
3440 result->L_R_select = -1;
3441
3442 if (isdigit (*p))
3443 {
3444 num = 0; /* now we know it is a number */
3445
3446 if (*p == '0' && (*(p + 1) == 'x' || *(p + 1) == 'X'))
3447 { /* hex input */
3448 p = p + 2;
3449 while (isdigit (*p) || ((*p >= 'a') && (*p <= 'f'))
3450 || ((*p >= 'A') && (*p <= 'F')))
3451 {
3452 if (isdigit (*p))
3453 num = num * 16 + *p - '0';
3454 else if (*p >= 'a' && *p <= 'f')
3455 num = num * 16 + *p - 'a' + 10;
3456 else
3457 num = num * 16 + *p - 'A' + 10;
3458 ++p;
3459 }
3460 }
3461 else
3462 {
3463 while (isdigit (*p))
3464 {
3465 num = num * 10 + *p - '0';
3466 ++p;
3467 }
3468 }
3469
3470 result->number_part = num;
3471
3472 if (is_R_select (p))
3473 {
3474 result->L_R_select = 1;
3475 ++p;
3476 }
3477 else if (is_L_select (p))
3478 {
3479 result->L_R_select = 0;
3480 ++p;
3481 }
3482 else
3483 result->L_R_select = 0;
3484
3485 }
3486 else if (*p == '%')
3487 { /* could be a pre-defined register */
3488 num = 0;
3489 name = p;
3490 p++;
3491 c = *p;
3492 /* tege hack: Special case for general registers
3493 as the general code makes a binary search with case translation,
3494 and is VERY slow. */
3495 if (c == 'r')
3496 {
3497 p++;
3498 if (*p == 'e' && *(p + 1) == 't' && (*(p + 2) == '0' || *(p + 2) == '1'))
3499 {
3500 p += 2;
3501 num = *p - '0' + 28; /* r28 is ret0 */
3502 p++;
3503 }
3504 else if (!isdigit (*p))
3505 as_bad ("Undefined register: '%s'. ASSUMING 0", name);
3506 else
3507 {
3508 do
3509 num = num * 10 + *p++ - '0';
3510 while (isdigit (*p));
3511 }
3512 }
3513 else
3514 {
3515 while (is_part_of_name (c))
3516 {
3517 p = p + 1;
3518 c = *p;
3519 }
3520 *p = 0;
3521 status = reg_name_search (name);
3522 if (status >= 0)
3523 num = status;
3524 else
3525 {
3526 if (print_errors)
3527 as_bad ("Undefined register: '%s'. ASSUMING 0", name);
3528 else
3529 num = -1;
3530 }
3531 *p = c;
3532 }
3533
3534 result->number_part = num;
3535
3536 if (is_R_select (p - 1))
3537 result->L_R_select = 1;
3538 else if (is_L_select (p - 1))
3539 result->L_R_select = 0;
3540 else
3541 result->L_R_select = 0;
3542
3543 }
3544 else
3545 {
3546 num = 0;
3547 name = p;
3548 c = *p;
3549 while (is_part_of_name (c))
3550 {
3551 p = p + 1;
3552 c = *p;
3553 }
3554 *p = 0;
3555 if ((sym = symbol_find (name)) != NULL)
3556 {
3557 #ifdef OBJ_SOM
3558 if (sym->pa_sy_type == ST_ABSOLUTE)
3559 {
3560 num = sym->pa_sy_value;
3561 #else
3562 if (S_GET_SEGMENT (sym) == &bfd_abs_section)
3563 {
3564 num = S_GET_VALUE (sym);
3565 #endif
3566 }
3567 else
3568 {
3569 if (print_errors)
3570 as_bad ("Non-absolute constant: '%s'. ASSUMING 0", name);
3571 else
3572 num = -1;
3573 }
3574 }
3575 else
3576 {
3577 if (print_errors)
3578 as_bad ("Undefined absolute constant: '%s'. ASSUMING 0", name);
3579 else
3580 num = -1;
3581 }
3582 *p = c;
3583 result->number_part = num;
3584
3585 if (is_R_select (p - 1))
3586 result->L_R_select = 1;
3587 else if (is_L_select (p - 1))
3588 result->L_R_select = 0;
3589 else
3590 result->L_R_select = 0;
3591
3592 }
3593
3594 *s = p;
3595 return num;
3596
3597 }
3598
3599 int
3600 pa_parse_fp_cmp_cond (s)
3601 char **s;
3602 {
3603 int cond, i;
3604 struct possibleS
3605 {
3606 char *string;
3607 int cond;
3608 };
3609
3610 /*
3611 This table is sorted by order of the length of the string. This is so we
3612 check for <> before we check for <. If we had a <> and checked for < first,
3613 we would get a false match.
3614 */
3615 static struct possibleS poss[] =
3616 {
3617 {"false?", 0},
3618 {"false", 1},
3619 {"true?", 30},
3620 {"true", 31},
3621 {"!<=>", 3},
3622 {"!?>=", 8},
3623 {"!?<=", 16},
3624 {"!<>", 7},
3625 {"!>=", 11},
3626 {"!?>", 12},
3627 {"?<=", 14},
3628 {"!<=", 19},
3629 {"!?<", 20},
3630 {"?>=", 22},
3631 {"!?=", 24},
3632 {"!=t", 27},
3633 {"<=>", 29},
3634 {"=t", 5},
3635 {"?=", 6},
3636 {"?<", 10},
3637 {"<=", 13},
3638 {"!>", 15},
3639 {"?>", 18},
3640 {">=", 21},
3641 {"!<", 23},
3642 {"<>", 25},
3643 {"!=", 26},
3644 {"!?", 28},
3645 {"?", 2},
3646 {"=", 4},
3647 {"<", 9},
3648 {">", 17}
3649 };
3650
3651 cond = 0;
3652
3653 for (i = 0; i < 32; i++)
3654 {
3655 if (strncasecmp (*s, poss[i].string, strlen (poss[i].string)) == 0)
3656 {
3657 cond = poss[i].cond;
3658 *s += strlen (poss[i].string);
3659 while (**s == ' ' || **s == '\t')
3660 *s = *s + 1;
3661 return cond;
3662 }
3663 }
3664
3665 as_bad ("Illegal FP Compare Condition: %c", **s);
3666 return 0;
3667 }
3668
3669 FP_Operand_Format
3670 pa_parse_fp_format (s)
3671 char **s;
3672 {
3673 int f;
3674
3675 f = SGL;
3676 if (**s == ',')
3677 {
3678 *s += 1;
3679 if (strncasecmp (*s, "sgl", 3) == 0)
3680 {
3681 f = SGL;
3682 *s += 4;
3683 }
3684 else if (strncasecmp (*s, "dbl", 3) == 0)
3685 {
3686 f = DBL;
3687 *s += 4;
3688 }
3689 else if (strncasecmp (*s, "quad", 4) == 0)
3690 {
3691 f = QUAD;
3692 *s += 5;
3693 }
3694 else
3695 {
3696 f = ILLEGAL_FMT;
3697 as_bad ("Unrecognized FP Operand Format: %3s", *s);
3698 }
3699 }
3700 while (**s == ' ' || **s == '\t' || **s == 0)
3701 *s = *s + 1;
3702
3703 return f;
3704 }
3705
3706 #if defined(OBJ_ELF)
3707 int
3708 pa_chk_field_selector (str)
3709 char **str;
3710 {
3711 int selector;
3712 struct selector_entry
3713 {
3714 char *prefix;
3715 int field_selector;
3716 };
3717 static struct selector_entry selector_table[] =
3718 {
3719 {"F'", e_fsel},
3720 {"F%", e_fsel},
3721 {"LS'", e_lssel},
3722 {"LS%", e_lssel},
3723 {"RS'", e_rssel},
3724 {"RS%", e_rssel},
3725 {"L'", e_lsel},
3726 {"L%", e_lsel},
3727 {"R'", e_rsel},
3728 {"R%", e_rsel},
3729 {"LD'", e_ldsel},
3730 {"LD%", e_ldsel},
3731 {"RD'", e_rdsel},
3732 {"RD%", e_rdsel},
3733 {"LR'", e_lrsel},
3734 {"LR%", e_lrsel},
3735 {"RR'", e_rrsel},
3736 {"RR%", e_rrsel},
3737 {"P'", e_psel},
3738 {"P%", e_psel},
3739 {"RP'", e_rpsel},
3740 {"RP%", e_rpsel},
3741 {"LP'", e_lpsel},
3742 {"LP%", e_lpsel},
3743 {"T'", e_tsel},
3744 {"T%", e_tsel},
3745 {"RT'", e_rtsel},
3746 {"RT%", e_rtsel},
3747 {"LT'", e_ltsel},
3748 {"LT%", e_ltsel},
3749 {NULL, e_fsel}
3750 };
3751 struct selector_entry *tableP;
3752
3753 selector = e_fsel;
3754
3755 while (**str == ' ' || **str == '\t' || **str == '\n' || **str == '\f')
3756 {
3757 *str = *str + 1;
3758 }
3759 for (tableP = selector_table; tableP->prefix; tableP++)
3760 {
3761 if (strncasecmp (tableP->prefix, *str, strlen (tableP->prefix)) == 0)
3762 {
3763 *str += strlen (tableP->prefix);
3764 selector = tableP->field_selector;
3765 break;
3766 }
3767 }
3768 return selector;
3769 }
3770
3771 int
3772 getExpression (str)
3773 char *str;
3774 {
3775 char *save_in;
3776 asection *seg;
3777
3778 save_in = input_line_pointer;
3779 input_line_pointer = str;
3780 seg = expression (&the_insn.exp);
3781
3782 if (!(seg == &bfd_abs_section
3783 || seg == &bfd_und_section
3784 || seg == text_section
3785 || seg == data_section
3786 || seg == bss_section
3787 || seg == diff_section
3788 || seg == big_section
3789 || seg == absent_section))
3790 {
3791 the_insn.error = "bad segment";
3792 expr_end = input_line_pointer;
3793 input_line_pointer = save_in;
3794 return 1;
3795 }
3796 expr_end = input_line_pointer;
3797 input_line_pointer = save_in;
3798 return 0;
3799 }
3800
3801 int
3802 getAbsoluteExpression (str)
3803 char *str;
3804 {
3805 char *save_in;
3806 asection *seg;
3807
3808 save_in = input_line_pointer;
3809 input_line_pointer = str;
3810 seg = expression (&the_insn.exp);
3811
3812 if (seg != &bfd_abs_section)
3813 {
3814 the_insn.error = "segment should be ABSOLUTE";
3815 expr_end = input_line_pointer;
3816 input_line_pointer = save_in;
3817 return 1;
3818 }
3819 expr_end = input_line_pointer;
3820 input_line_pointer = save_in;
3821 return 0;
3822 }
3823
3824 #else
3825 int
3826 getExpression (str)
3827 char *str;
3828 {
3829 char *save_in;
3830 segT seg;
3831
3832 save_in = input_line_pointer;
3833 input_line_pointer = str;
3834 switch (seg = expression (&the_insn.exp))
3835 {
3836
3837 case SEG_ABSOLUTE:
3838 case SEG_TEXT:
3839 case SEG_DATA:
3840 case SEG_BSS:
3841 case SEG_UNKNOWN:
3842 case SEG_DIFFERENCE:
3843 case SEG_BIG:
3844 case SEG_GDB:
3845 case SEG_MILLICODE:
3846 case SEG_NONE:
3847 break;
3848
3849 default:
3850 the_insn.error = "illegal segment";
3851 expr_end = input_line_pointer;
3852 input_line_pointer = save_in;
3853 return 1;
3854 }
3855 expr_end = input_line_pointer;
3856 input_line_pointer = save_in;
3857 return 0;
3858 }
3859
3860 int
3861 getAbsoluteExpression (str)
3862 char *str;
3863 {
3864 char *save_in;
3865 segT seg;
3866
3867 save_in = input_line_pointer;
3868 input_line_pointer = str;
3869 switch (seg = expression (&the_insn.exp))
3870 {
3871
3872 case SEG_ABSOLUTE:
3873 break;
3874
3875 default:
3876 the_insn.error = "segment should be ABSOLUTE";
3877 expr_end = input_line_pointer;
3878 input_line_pointer = save_in;
3879 return 1;
3880 }
3881 expr_end = input_line_pointer;
3882 input_line_pointer = save_in;
3883 return 0;
3884 }
3885
3886 #endif
3887
3888 int
3889 evaluateAbsolute (exp, field_selector)
3890 expressionS exp;
3891 int field_selector;
3892 {
3893 int value;
3894
3895 value = exp.X_add_number;
3896
3897 if (exp.X_add_symbol)
3898 {
3899 value += S_GET_VALUE (exp.X_add_symbol);
3900 }
3901 if (exp.X_subtract_symbol)
3902 {
3903 value -= S_GET_VALUE (exp.X_subtract_symbol);
3904 }
3905
3906 switch (field_selector)
3907 {
3908 case e_fsel: /* F : no change */
3909 break;
3910
3911 case e_lssel: /* LS : if (bit 21) then add 0x800
3912 arithmetic shift right 11 bits */
3913 if (value & 0x00000400)
3914 value += 0x800;
3915 value = (value & 0xfffff800) >> 11;
3916 break;
3917
3918 case e_rssel: /* RS : Sign extend from bit 21 */
3919 if (value & 0x00000400)
3920 value |= 0xfffff800;
3921 else
3922 value &= 0x7ff;
3923 break;
3924
3925 case e_lsel: /* L : Arithmetic shift right 11 bits */
3926 value = (value & 0xfffff800) >> 11;
3927 break;
3928
3929 case e_rsel: /* R : Set bits 0-20 to zero */
3930 value = value & 0x7ff;
3931 break;
3932
3933 case e_ldsel: /* LD : Add 0x800, arithmetic shift
3934 right 11 bits */
3935 value += 0x800;
3936 value = (value & 0xfffff800) >> 11;
3937 break;
3938
3939 case e_rdsel: /* RD : Set bits 0-20 to one */
3940 value |= 0xfffff800;
3941 break;
3942
3943 case e_lrsel: /* LR : L with "rounded" constant */
3944 /* XXX: this isn't right. Need to add a "rounded" constant */
3945 /* XXX: (presumably from X_add_number) */
3946 value = (value & 0xfffff800) >> 11;
3947 break;
3948
3949 case e_rrsel: /* RR : R with "rounded" constant */
3950 /* XXX: this isn't right. Need to add a "rounded" constant */
3951 /* XXX: (presumably from X_add_number) */
3952 value = value & 0x7ff;
3953 break;
3954
3955 default:
3956 BAD_CASE (field_selector);
3957 break;
3958 }
3959 return value;
3960 }
3961
3962 int
3963 pa_build_arg_reloc (type_name)
3964 char *type_name;
3965 {
3966
3967 if (strncasecmp (type_name, "no", 2) == 0)
3968 {
3969 return 0;
3970 }
3971 if (strncasecmp (type_name, "gr", 2) == 0)
3972 {
3973 return 1;
3974 }
3975 else if (strncasecmp (type_name, "fr", 2) == 0)
3976 {
3977 return 2;
3978 }
3979 else if (strncasecmp (type_name, "fu", 2) == 0)
3980 {
3981 return 3;
3982 }
3983 else
3984 as_bad ("Unrecognized argument location: %s\n", type_name);
3985
3986 return 0;
3987 }
3988
3989 unsigned int
3990 pa_align_arg_reloc (reg, arg_reloc)
3991 unsigned int reg;
3992 unsigned int arg_reloc;
3993 {
3994 unsigned int new_reloc;
3995
3996 new_reloc = arg_reloc;
3997 switch (reg)
3998 {
3999 case 0:
4000 new_reloc <<= 8;
4001 break;
4002 case 1:
4003 new_reloc <<= 6;
4004 break;
4005 case 2:
4006 new_reloc <<= 4;
4007 break;
4008 case 3:
4009 new_reloc <<= 2;
4010 break;
4011 default:
4012 as_bad ("Illegal argument description: %d", reg);
4013 }
4014
4015 return new_reloc;
4016 }
4017
4018 int
4019 pa_parse_nullif (s)
4020 char **s;
4021 {
4022 int nullif;
4023
4024 nullif = 0;
4025 if (**s == ',')
4026 {
4027 *s = *s + 1;
4028 if (strncasecmp (*s, "n", 1) == 0)
4029 nullif = 1;
4030 else
4031 {
4032 as_bad ("Unrecognized Nullification: (%c)", **s);
4033 nullif = 0;
4034 }
4035 *s = *s + 1;
4036 }
4037 while (**s == ' ' || **s == '\t')
4038 *s = *s + 1;
4039
4040 return nullif;
4041 }
4042
4043 #if 0
4044 int
4045 pa_parse_nonneg_cmpsub_cmpltr (s)
4046 char **s;
4047 {
4048 int cmpltr;
4049 char *name;
4050 char c;
4051
4052 cmpltr = -1;
4053 /** cmpltr = 0; **/
4054 if (**s == ',')
4055 {
4056 *s += 1;
4057 name = *s;
4058 while (**s != ',' && **s != ' ' && **s != '\t')
4059 *s += 1;
4060 c = **s;
4061 **s = 0x00;
4062 if (strcmp (name, "=") == 0)
4063 {
4064 cmpltr = 1;
4065 }
4066 else if (strcmp (name, "<") == 0)
4067 {
4068 cmpltr = 2;
4069 }
4070 else if (strcmp (name, "<=") == 0)
4071 {
4072 cmpltr = 3;
4073 }
4074 else if (strcmp (name, "<<") == 0)
4075 {
4076 cmpltr = 4;
4077 }
4078 else if (strcmp (name, "<<=") == 0)
4079 {
4080 cmpltr = 5;
4081 }
4082 else if (strcasecmp (name, "sv") == 0)
4083 {
4084 cmpltr = 6;
4085 }
4086 else if (strcasecmp (name, "od") == 0)
4087 {
4088 cmpltr = 7;
4089 }
4090 /**
4091 else
4092 cmpltr = -1;
4093 **/
4094 **s = c;
4095 }
4096 if (cmpltr >= 0)
4097 {
4098 while (**s == ' ' || **s == '\t')
4099 *s = *s + 1;
4100 }
4101
4102 return cmpltr;
4103 }
4104
4105 #endif
4106 int
4107 pa_parse_nonneg_cmpsub_cmpltr (s)
4108 char **s;
4109 {
4110 int cmpltr;
4111 char *name;
4112 char c;
4113
4114 cmpltr = 0;
4115 if (**s == ',')
4116 {
4117 *s += 1;
4118 name = *s;
4119 while (**s != ',' && **s != ' ' && **s != '\t')
4120 *s += 1;
4121 c = **s;
4122 **s = 0x00;
4123 if (strcmp (name, "=") == 0)
4124 {
4125 cmpltr = 1;
4126 }
4127 else if (strcmp (name, "<") == 0)
4128 {
4129 cmpltr = 2;
4130 }
4131 else if (strcmp (name, "<=") == 0)
4132 {
4133 cmpltr = 3;
4134 }
4135 else if (strcmp (name, "<<") == 0)
4136 {
4137 cmpltr = 4;
4138 }
4139 else if (strcmp (name, "<<=") == 0)
4140 {
4141 cmpltr = 5;
4142 }
4143 else if (strcasecmp (name, "sv") == 0)
4144 {
4145 cmpltr = 6;
4146 }
4147 else if (strcasecmp (name, "od") == 0)
4148 {
4149 cmpltr = 7;
4150 }
4151 else
4152 cmpltr = -1;
4153 **s = c;
4154 }
4155 if (cmpltr >= 0)
4156 {
4157 while (**s == ' ' || **s == '\t')
4158 *s = *s + 1;
4159 }
4160
4161 return cmpltr;
4162 }
4163
4164 int
4165 pa_parse_neg_cmpsub_cmpltr (s)
4166 char **s;
4167 {
4168 int cmpltr;
4169 char *name;
4170 char c;
4171
4172 cmpltr = -1;
4173 if (**s == ',')
4174 {
4175 *s += 1;
4176 name = *s;
4177 while (**s != ',' && **s != ' ' && **s != '\t')
4178 *s += 1;
4179 c = **s;
4180 **s = 0x00;
4181 if (strcasecmp (name, "tr") == 0)
4182 {
4183 cmpltr = 0;
4184 }
4185 else if (strcmp (name, "<>") == 0)
4186 {
4187 cmpltr = 1;
4188 }
4189 else if (strcmp (name, ">=") == 0)
4190 {
4191 cmpltr = 2;
4192 }
4193 else if (strcmp (name, ">") == 0)
4194 {
4195 cmpltr = 3;
4196 }
4197 else if (strcmp (name, ">>=") == 0)
4198 {
4199 cmpltr = 4;
4200 }
4201 else if (strcmp (name, ">>") == 0)
4202 {
4203 cmpltr = 5;
4204 }
4205 else if (strcasecmp (name, "nsv") == 0)
4206 {
4207 cmpltr = 6;
4208 }
4209 else if (strcasecmp (name, "ev") == 0)
4210 {
4211 cmpltr = 7;
4212 }
4213 **s = c;
4214 }
4215 if (cmpltr >= 0)
4216 {
4217 while (**s == ' ' || **s == '\t')
4218 *s = *s + 1;
4219 }
4220
4221 return cmpltr;
4222 }
4223
4224 int
4225 pa_parse_nonneg_add_cmpltr (s)
4226 char **s;
4227 {
4228 int cmpltr;
4229 char *name;
4230 char c;
4231
4232 cmpltr = -1;
4233 if (**s == ',')
4234 {
4235 *s += 1;
4236 name = *s;
4237 while (**s != ',' && **s != ' ' && **s != '\t')
4238 *s += 1;
4239 c = **s;
4240 **s = 0x00;
4241 if (strcmp (name, "=") == 0)
4242 {
4243 cmpltr = 1;
4244 }
4245 else if (strcmp (name, "<") == 0)
4246 {
4247 cmpltr = 2;
4248 }
4249 else if (strcmp (name, "<=") == 0)
4250 {
4251 cmpltr = 3;
4252 }
4253 else if (strcasecmp (name, "nuv") == 0)
4254 {
4255 cmpltr = 4;
4256 }
4257 else if (strcasecmp (name, "znv") == 0)
4258 {
4259 cmpltr = 5;
4260 }
4261 else if (strcasecmp (name, "sv") == 0)
4262 {
4263 cmpltr = 6;
4264 }
4265 else if (strcasecmp (name, "od") == 0)
4266 {
4267 cmpltr = 7;
4268 }
4269 **s = c;
4270 }
4271 if (cmpltr >= 0)
4272 {
4273 while (**s == ' ' || **s == '\t')
4274 *s = *s + 1;
4275 }
4276
4277 return cmpltr;
4278 }
4279
4280 int
4281 pa_parse_neg_add_cmpltr (s)
4282 char **s;
4283 {
4284 int cmpltr;
4285 char *name;
4286 char c;
4287
4288 cmpltr = -1;
4289 if (**s == ',')
4290 {
4291 *s += 1;
4292 name = *s;
4293 while (**s != ',' && **s != ' ' && **s != '\t')
4294 *s += 1;
4295 c = **s;
4296 **s = 0x00;
4297 if (strcasecmp (name, "tr") == 0)
4298 {
4299 cmpltr = 0;
4300 }
4301 else if (strcmp (name, "<>") == 0)
4302 {
4303 cmpltr = 1;
4304 }
4305 else if (strcmp (name, ">=") == 0)
4306 {
4307 cmpltr = 2;
4308 }
4309 else if (strcmp (name, ">") == 0)
4310 {
4311 cmpltr = 3;
4312 }
4313 else if (strcmp (name, "uv") == 0)
4314 {
4315 cmpltr = 4;
4316 }
4317 else if (strcmp (name, "vnz") == 0)
4318 {
4319 cmpltr = 5;
4320 }
4321 else if (strcasecmp (name, "nsv") == 0)
4322 {
4323 cmpltr = 6;
4324 }
4325 else if (strcasecmp (name, "ev") == 0)
4326 {
4327 cmpltr = 7;
4328 }
4329 **s = c;
4330 }
4331 if (cmpltr >= 0)
4332 {
4333 while (**s == ' ' || **s == '\t')
4334 *s = *s + 1;
4335 }
4336
4337 return cmpltr;
4338 }
4339
4340 void
4341 s_seg ()
4342 {
4343
4344 if (strncmp (input_line_pointer, "\"text\"", 6) == 0)
4345 {
4346 input_line_pointer += 6;
4347 s_text ();
4348 return;
4349 }
4350 if (strncmp (input_line_pointer, "\"data\"", 6) == 0)
4351 {
4352 input_line_pointer += 6;
4353 s_data ();
4354 return;
4355 }
4356 if (strncmp (input_line_pointer, "\"data1\"", 7) == 0)
4357 {
4358 input_line_pointer += 7;
4359 s_data1 ();
4360 return;
4361 }
4362 as_bad ("Unknown segment type");
4363 demand_empty_rest_of_line ();
4364 return;
4365 }
4366
4367 void
4368 s_private ()
4369 {
4370 register int temp;
4371
4372 temp = get_absolute_expression ();
4373 #ifdef OBJ_SOM
4374 subseg_new (SEG_DATA, (subsegT) temp);
4375 #else
4376 subseg_new (".data", (subsegT) temp);
4377 #endif
4378 demand_empty_rest_of_line ();
4379 }
4380
4381 void
4382 s_data1 ()
4383 {
4384 #ifdef OBJ_SOM
4385 subseg_new (SEG_DATA, 1);
4386 #else
4387 subseg_new (".data", 1);
4388 #endif
4389 demand_empty_rest_of_line ();
4390 return;
4391 }
4392
4393 void
4394 s_proc ()
4395 {
4396 extern char is_end_of_line[];
4397
4398 while (!is_end_of_line[*input_line_pointer])
4399 {
4400 ++input_line_pointer;
4401 }
4402 ++input_line_pointer;
4403 return;
4404 }
4405
4406 void
4407 pa_block (z)
4408 int z;
4409 {
4410 register char *p;
4411 register long int temp_fill;
4412 register long int temp_size;
4413 register int i;
4414
4415 temp_size = get_absolute_expression ();
4416
4417 if (z)
4418 { /* fill with zeroes even if not requested to do so. */
4419 temp_fill = 0; /* HP assembler does this too. */
4420 }
4421 else
4422 {
4423 temp_fill = 0;
4424 }
4425
4426 if (temp_size <= 0)
4427 {
4428 as_bad ("size < 0, .block ignored");
4429 temp_size = 0;
4430 }
4431 p = frag_var (rs_fill,
4432 (int) temp_size,
4433 (int) temp_size, (relax_substateT) 0, (symbolS *) 0, 1, (char *) 0);
4434 bzero (p, (int) temp_size);
4435
4436 /* convert 2 bytes at a time */
4437
4438 for (i = 0; i < temp_size; i += 2)
4439 {
4440 md_number_to_chars (p + i,
4441 temp_fill,
4442 (int) ((temp_size - i) > 2 ? 2 : (temp_size - i)));
4443 }
4444
4445 pa_undefine_label ();
4446 demand_empty_rest_of_line ();
4447 return;
4448 }
4449
4450 void
4451 pa_call ()
4452 {
4453
4454 pa_call_args (&last_call_desc);
4455 demand_empty_rest_of_line ();
4456 return;
4457 }
4458
4459 void
4460 pa_call_args (call_desc)
4461 register call_descS *call_desc;
4462 {
4463 register char *name;
4464 register char c;
4465 register char *p;
4466 register int temp;
4467 register unsigned int arg_reloc;
4468
4469 while (!is_end_of_statement ())
4470 {
4471 name = input_line_pointer;
4472 c = get_symbol_end ();
4473 if ((strncasecmp (name, "argw", 4) == 0))
4474 {
4475 temp = atoi (name + 4);
4476 p = input_line_pointer;
4477 *p = c;
4478 input_line_pointer++;
4479 name = input_line_pointer;
4480 c = get_symbol_end ();
4481 arg_reloc = pa_build_arg_reloc (name);
4482 call_desc->arg_reloc |= pa_align_arg_reloc (temp, arg_reloc);
4483 }
4484 else if ((strncasecmp (name, "rtnval", 6) == 0))
4485 {
4486 p = input_line_pointer;
4487 *p = c;
4488 input_line_pointer++;
4489 name = input_line_pointer;
4490 c = get_symbol_end ();
4491 arg_reloc = pa_build_arg_reloc (name);
4492 call_desc->arg_reloc |= (arg_reloc & 0x3);
4493 }
4494 else
4495 {
4496 as_bad ("Unrecognized .CALL argument: %s", name);
4497 }
4498 p = input_line_pointer;
4499 *p = c;
4500 if (!is_end_of_statement ())
4501 input_line_pointer++;
4502 }
4503 }
4504
4505 static int
4506 is_same_frag (frag1P, frag2P)
4507 fragS *frag1P;
4508 fragS *frag2P;
4509 {
4510
4511 if (frag1P == NULL)
4512 return (FALSE);
4513 else if (frag2P == NULL)
4514 return (FALSE);
4515 else if (frag1P == frag2P)
4516 return (TRUE);
4517 else if (frag2P->fr_type == rs_fill && frag2P->fr_fix == 0)
4518 is_same_frag (frag1P, frag2P->fr_next);
4519 else
4520 return (FALSE);
4521 }
4522
4523 #ifdef OBJ_ELF
4524 static void
4525 pa_build_unwind_subspace (call_info)
4526 call_infoS *call_info;
4527 {
4528 char *unwindP;
4529 asection *seg;
4530 asection *save_seg;
4531 subsegT subseg, save_subseg;
4532 int i;
4533 char c;
4534 char *p;
4535
4536 subseg = SUBSEG_UNWIND;
4537 seg = bfd_get_section_by_name (stdoutput, UNWIND_SECTION_NAME);
4538 if (seg == ASEC_NULL)
4539 {
4540 seg = bfd_make_section_old_way (stdoutput, UNWIND_SECTION_NAME);
4541 }
4542 bfd_set_section_flags (stdoutput,
4543 seg,
4544 SEC_READONLY | SEC_ALLOC | SEC_LOAD | SEC_RELOC);
4545
4546 /* callinfo.frame is in bytes and unwind_desc is in 8 byte units */
4547 call_info->ci_unwind.descriptor.frame_size = call_info->frame / 8;
4548
4549 /* Now, dump the unwind descriptor to the $UNWIND$ subspace. This
4550 creates a couple of relocations */
4551
4552 save_seg = now_seg;
4553 save_subseg = now_subseg;
4554 subseg_new ((char *) seg->name, subseg);
4555 unwindP = (char *) &call_info->ci_unwind;
4556
4557 p = frag_more (4);
4558 call_info->start_offset_frag = frag_now;
4559 call_info->start_frag_where = p - frag_now->fr_literal;
4560
4561 /* relocation info. for start offset of the function */
4562
4563 fix_new_hppa (frag_now, p - frag_now->fr_literal, 4,
4564 call_info->start_symbol, (symbolS *) NULL,
4565 0, 0, R_HPPA, e_fsel, 32, 0, (char *) 0);
4566
4567 /** we need to search for the first relocation involving the start_symbol of **/
4568 /** this call_info descriptor **/
4569
4570 {
4571 fixS *fixP;
4572
4573 call_info->start_fix = seg_info (now_seg)->fix_root; /* the default */
4574 for (fixP = call_info->start_fix; fixP; fixP = fixP->fx_next)
4575 {
4576 if (fixP->fx_addsy == call_info->start_symbol
4577 || fixP->fx_subsy == call_info->start_symbol)
4578 {
4579 call_info->start_fix = fixP;
4580 break;
4581 }
4582 }
4583 }
4584
4585 p = frag_more (4);
4586 call_info->end_offset_frag = frag_now;
4587 call_info->end_frag_where = p - frag_now->fr_literal;
4588
4589 /* relocation info. for end offset of the function */
4590
4591 fix_new_hppa (frag_now, p - frag_now->fr_literal, 4,
4592 call_info->end_symbol, (symbolS *) NULL,
4593 0, 0, R_HPPA, e_fsel, 32, 0, (char *) 0);
4594
4595 /** we need to search for the first relocation involving the start_symbol of **/
4596 /** this call_info descriptor **/
4597
4598 {
4599 fixS *fixP;
4600
4601 call_info->end_fix = seg_info (now_seg)->fix_root; /* the default */
4602 for (fixP = call_info->end_fix; fixP; fixP = fixP->fx_next)
4603 {
4604 if (fixP->fx_addsy == call_info->end_symbol
4605 || fixP->fx_subsy == call_info->end_symbol)
4606 {
4607 call_info->end_fix = fixP;
4608 break;
4609 }
4610 }
4611 }
4612
4613 for (i = 8; i < sizeof (unwind_tableS); i++)
4614 {
4615 c = *(unwindP + i);
4616 {
4617 FRAG_APPEND_1_CHAR (c);
4618 }
4619 }
4620
4621 subseg_new ((char *) save_seg->name, save_subseg);
4622 }
4623
4624 #else
4625 #ifdef OBJ_SOM
4626 static void
4627 pa_build_unwind_subspace (call_info)
4628 call_infoS *call_info;
4629 {
4630 space_dict_chainS *spaceP;
4631 subspace_dict_chainS *subspaceP;
4632 char *unwindP;
4633 char defined, loadable, code_only, common, dup_common, is_zero, sort;
4634 int access, space_index, alignment, quadrant;
4635 segT seg, save_seg;
4636 subsegT subseg, save_subseg;
4637 int i;
4638 char c;
4639 char *p;
4640
4641 defined = 1;
4642 loadable = 1;
4643 code_only = 0;
4644 common = 0;
4645 dup_common = 0;
4646 is_zero = 0;
4647 sort = 0x40;
4648 access = 0x2c;
4649 space_index = 0;
4650 alignment = 8;
4651 quadrant = 0;
4652 subseg = SUBSEG_UNWIND;
4653 seg = SEG_TEXT;
4654
4655 spaceP = pa_segment_to_space (seg);
4656
4657 if ((subspaceP = is_defined_subspace ("$UNWIND$", SUBSEG_UNWIND)))
4658 {
4659 update_subspace ("$UNWIND$", defined, loadable, code_only, common, dup_common,
4660 sort, is_zero, access, space_index, alignment, quadrant,
4661 SUBSEG_UNWIND);
4662 }
4663 else
4664 {
4665 subspaceP = create_new_subspace (spaceP, "$UNWIND$", defined, loadable, code_only,
4666 common, dup_common, is_zero, sort, access,
4667 space_index, alignment, quadrant, seg);
4668 }
4669
4670
4671 /* callinfo.frame is in bytes and unwind_desc is in 8 byte units */
4672 call_info->ci_unwind.descriptor.frame_size = call_info->frame / 8;
4673
4674 /* Now, dump the unwind descriptor to the $UNWIND$ subspace. This
4675 creates a couple of relocations */
4676
4677 save_seg = now_seg;
4678 save_subseg = now_subseg;
4679 subseg_new (seg, subseg);
4680 unwindP = (char *) &call_info->ci_unwind;
4681
4682 p = frag_more (4);
4683 call_info->start_offset_frag = frag_now;
4684 call_info->start_frag_where = p - frag_now->fr_literal;
4685
4686 /* relocation info. for start offset of the function */
4687
4688 fix_new (frag_now, p - frag_now->fr_literal, 4,
4689 call_info->start_symbol, (symbolS *) NULL,
4690 0, 0, R_DATA_ONE_SYMBOL, e_fsel, 0, 0, (char *) 0);
4691
4692 /** we need to search for the first relocation involving the start_symbol of **/
4693 /** this call_info descriptor **/
4694
4695 {
4696 fixS *fixP;
4697
4698 call_info->start_fix = seg_info (now_seg)->fix_root; /* the default */
4699 for (fixP = call_info->start_fix; fixP; fixP = fixP->fx_next)
4700 {
4701 /*
4702 if ( ( fixP->fx_addsy == call_info->start_symbol ||
4703 fixP->fx_subsy == call_info->start_symbol )
4704 &&
4705 ( fixP->fx_frag == call_info->start_symbol->sy_frag ) ) {
4706 */
4707 if ((fixP->fx_addsy == call_info->start_symbol ||
4708 fixP->fx_subsy == call_info->start_symbol)
4709 &&
4710 (is_same_frag (fixP->fx_frag, call_info->start_symbol->sy_frag)))
4711 {
4712 call_info->start_fix = fixP;
4713 break;
4714 }
4715 }
4716 }
4717
4718 p = frag_more (4);
4719 call_info->end_offset_frag = frag_now;
4720 call_info->end_frag_where = p - frag_now->fr_literal;
4721
4722 /* relocation info. for end offset of the function */
4723
4724 fix_new (frag_now, p - frag_now->fr_literal, 4,
4725 call_info->start_symbol, (symbolS *) NULL,
4726 0, 0, R_DATA_ONE_SYMBOL, e_fsel, 0, 0, (char *) 0);
4727
4728 /** we need to search for the first relocation involving the start_symbol of **/
4729 /** this call_info descriptor **/
4730
4731 {
4732 fixS *fixP;
4733
4734 call_info->end_fix = seg_info (now_seg)->fix_root; /* the default */
4735 for (fixP = call_info->end_fix; fixP; fixP = fixP->fx_next)
4736 {
4737 /*
4738 if ( ( fixP->fx_addsy == call_info->start_symbol ||
4739 fixP->fx_subsy == call_info->start_symbol )
4740 &&
4741 ( fixP->fx_frag == call_info->start_symbol->sy_frag ) ) {
4742 */
4743 if ((fixP->fx_addsy == call_info->start_symbol ||
4744 fixP->fx_subsy == call_info->start_symbol)
4745 &&
4746 (is_same_frag (fixP->fx_frag, call_info->start_symbol->sy_frag)))
4747 {
4748 call_info->end_fix = fixP;
4749 break;
4750 }
4751 }
4752 }
4753
4754 for (i = 8; i < sizeof (unwind_tableS); i++)
4755 {
4756 c = *(unwindP + i);
4757 {
4758 FRAG_APPEND_1_CHAR (c);
4759 }
4760 }
4761
4762 subseg_new (save_seg, save_subseg);
4763
4764 }
4765
4766 #endif
4767 #endif
4768
4769 void
4770 pa_callinfo ()
4771 {
4772 register char *name;
4773 register char c;
4774 register char *p;
4775 register int temp;
4776 register symbolS *symbolP;
4777
4778 if (!within_procedure)
4779 as_bad (".callinfo is not within a procedure definition");
4780
4781 callinfo_found = TRUE;
4782
4783 while (!is_end_of_statement ())
4784 {
4785 name = input_line_pointer;
4786 c = get_symbol_end ();
4787 if ((strncasecmp (name, "frame", 5) == 0))
4788 {
4789 p = input_line_pointer;
4790 *p = c;
4791 input_line_pointer++;
4792 temp = get_absolute_expression ();
4793 if ((temp & 0x3) != 0)
4794 {
4795 as_bad ("FRAME parameter must be a multiple of 8: %d\n", temp);
4796 temp = 0;
4797 }
4798 last_call_info->frame = temp;
4799 }
4800 else if ((strncasecmp (name, "entry_gr", 8) == 0))
4801 {
4802 p = input_line_pointer;
4803 *p = c;
4804 input_line_pointer++;
4805 temp = get_absolute_expression ();
4806 last_call_info->ci_unwind.descriptor.entry_gr = temp;
4807 }
4808 else if ((strncasecmp (name, "entry_fr", 8) == 0))
4809 {
4810 p = input_line_pointer;
4811 *p = c;
4812 input_line_pointer++;
4813 temp = get_absolute_expression ();
4814 last_call_info->ci_unwind.descriptor.entry_fr = temp;
4815 }
4816 else if ((strncasecmp (name, "entry_sr", 8) == 0))
4817 {
4818 p = input_line_pointer;
4819 *p = c;
4820 input_line_pointer++;
4821 temp = get_absolute_expression ();
4822 last_call_info->entry_sr = temp;
4823 }
4824 else if ((strncasecmp (name, "calls", 5) == 0) ||
4825 (strncasecmp (name, "caller", 6) == 0))
4826 {
4827 p = input_line_pointer;
4828 *p = c;
4829 last_call_info->makes_calls = 1;
4830 }
4831 else if ((strncasecmp (name, "no_calls", 8) == 0))
4832 {
4833 p = input_line_pointer;
4834 *p = c;
4835 last_call_info->makes_calls = 0;
4836 }
4837 else if ((strncasecmp (name, "save_rp", 7) == 0))
4838 {
4839 p = input_line_pointer;
4840 *p = c;
4841 last_call_info->ci_unwind.descriptor.save_rp = 1;
4842 }
4843 else if ((strncasecmp (name, "save_sp", 7) == 0))
4844 {
4845 p = input_line_pointer;
4846 *p = c;
4847 last_call_info->ci_unwind.descriptor.save_sp = 1;
4848 }
4849 else if ((strncasecmp (name, "no_unwind", 9) == 0))
4850 {
4851 p = input_line_pointer;
4852 *p = c;
4853 last_call_info->ci_unwind.descriptor.cannot_unwind = 1;
4854 }
4855 else if ((strncasecmp (name, "hpux_int", 7) == 0))
4856 {
4857 p = input_line_pointer;
4858 *p = c;
4859 last_call_info->hpux_int = 1;
4860 }
4861 else
4862 {
4863 as_bad ("Unrecognized .CALLINFO argument: %s", name);
4864 }
4865 if (!is_end_of_statement ())
4866 input_line_pointer++;
4867 }
4868
4869 demand_empty_rest_of_line ();
4870 return;
4871 }
4872
4873 void
4874 pa_code ()
4875 {
4876 space_dict_chainS *sdchain;
4877
4878 if ((sdchain = is_defined_space ("$TEXT$")) == NULL)
4879 {
4880 sdchain = create_new_space (pa_def_spaces[0].name, pa_def_spaces[0].spnum,
4881 pa_def_spaces[0].loadable, pa_def_spaces[0].defined,
4882 pa_def_spaces[0].private, pa_def_spaces[0].sort,
4883 1, pa_def_spaces[0].segment);
4884 }
4885
4886 SPACE_DEFINED (sdchain) = 1;
4887 #ifdef OBJ_SOM
4888
4889 subseg_new (SEG_TEXT, SUBSEG_CODE);
4890 #else
4891
4892 subseg_new (".text", SUBSEG_CODE);
4893 #endif
4894
4895 demand_empty_rest_of_line ();
4896 return;
4897 }
4898
4899 /*
4900 * This is different than the standard GAS s_comm(). On HP9000/800 machines,
4901 * the .comm pseudo-op has the following symtax:
4902 *
4903 * <label> .comm <length>
4904 *
4905 * where <label> is optional and is a symbol whose address will be the start of
4906 * a block of memory <length> bytes long. <length> must be an absolute expressio
4907 n.
4908 * <length> bytes will be allocated in the current space and subspace.
4909 *
4910 */
4911
4912 void
4913 pa_comm ()
4914 {
4915 register char *p;
4916 register int size, i;
4917 register symbolS *symbolP;
4918 register label_symbolS *label_symbolP = pa_get_label ();
4919
4920 if (label_symbolP)
4921 symbolP = label_symbolP->lss_label;
4922 else
4923 symbolP = NULL;
4924
4925 SKIP_WHITESPACE ();
4926 if ((size = get_absolute_expression ()) < 0)
4927 {
4928 as_warn (".COMMon length (%d.) <0! Ignored.", size);
4929 ignore_rest_of_line ();
4930 return;
4931 }
4932
4933 if (symbolP)
4934 {
4935 #ifdef OBJ_SOM
4936 if (symbolP->pa_sy_type == ST_STORAGE &&
4937 symbolP->pa_sy_scope == SS_UNSAT)
4938 {
4939 if (symbolP->pa_sy_value != size)
4940 {
4941 as_warn ("Length of .comm \"%s\" is already %d. Not changed to %d.",
4942 symbolP->pa_sy_name, symbolP->pa_sy_value, size);
4943 return;
4944 }
4945 }
4946 else
4947 {
4948 symbolP->pa_sy_value = size;
4949 symbolP->pa_sy_scope = SS_UNSAT;
4950 symbolP->pa_sy_type = ST_STORAGE;
4951 symbolP->sy_ref = sym_def;
4952 }
4953 #endif
4954 #ifdef OBJ_ELF
4955 if (S_IS_DEFINED (symbolP) && S_GET_SEGMENT (symbolP) == bss_section)
4956 {
4957 as_bad ("Ignoring attempt to re-define symbol");
4958 ignore_rest_of_line ();
4959 return;
4960 }
4961 if (S_GET_VALUE (symbolP))
4962 {
4963 if (S_GET_VALUE (symbolP) != size)
4964 {
4965 as_warn ("Length of .comm \"%s\" is already %d. Not changed to %d.",
4966 S_GET_NAME (symbolP), S_GET_VALUE (symbolP), size);
4967 return;
4968 }
4969 }
4970 else
4971 {
4972 S_SET_VALUE (symbolP, size);
4973 S_SET_SEGMENT (symbolP, bss_section);
4974 S_SET_EXTERNAL (symbolP);
4975 }
4976 #endif
4977 }
4978
4979
4980 demand_empty_rest_of_line ();
4981 }
4982
4983 void
4984 pa_copyright ()
4985 {
4986 register char *name;
4987 register char c;
4988 register char *p;
4989 register int temp;
4990 register symbolS *symbolP;
4991
4992 SKIP_WHITESPACE ();
4993 if (*input_line_pointer == '\"')
4994 {
4995 ++input_line_pointer; /* -> 1st char of string. */
4996 name = input_line_pointer;
4997 while ((c = next_char_of_string ()) >= 0)
4998 ;
4999 c = *input_line_pointer;
5000 *input_line_pointer = '\0';
5001 *(input_line_pointer - 1) = '\0';
5002 {
5003 #ifdef OBJ_SOM
5004 #define PREFIX "Copyright "
5005 #define MIDFIX ". All rights reserved. No part of this program may be photocopied, reproduced, or transmitted without prior written consent of "
5006 #define SUFFIX "."
5007
5008 struct aux_hdr_list *aux_hdr_entry;
5009 int len;
5010 char *company_name = name;
5011 char *date_part;
5012
5013 date_part = (char *) index (name, ',');
5014 if (date_part)
5015 {
5016 *date_part = 0x00;
5017 date_part++;
5018 }
5019
5020 len =
5021 strlen (PREFIX) +
5022 strlen (MIDFIX) +
5023 strlen (SUFFIX) +
5024 2 * strlen (name);
5025
5026 if (date_part)
5027 {
5028 len += strlen (date_part) + strlen (",");
5029 }
5030
5031 aux_hdr_entry = (struct aux_hdr_list *) malloc (sizeof (struct aux_hdr_list));
5032 if (aux_hdr_root)
5033 {
5034 aux_hdr_entry->ahl_next = aux_hdr_root;
5035 aux_hdr_root = aux_hdr_entry;
5036 }
5037 else
5038 {
5039 aux_hdr_entry->ahl_next = NULL;
5040 aux_hdr_root = aux_hdr_entry;
5041 }
5042 aux_hdr_entry->type = COPYRIGHT_AUX_ID;
5043 aux_hdr_entry->contents.cpy.header_id.append = 1;
5044 aux_hdr_entry->contents.cpy.header_id.type = COPYRIGHT_AUX_ID;
5045 aux_hdr_entry->contents.cpy.header_id.length = len + sizeof (unsigned int);
5046 while (aux_hdr_entry->contents.usr_str.header_id.length % 4)
5047 aux_hdr_entry->contents.usr_str.header_id.length += 1;
5048
5049 aux_hdr_entry->contents.cpy.string_length = len;
5050 aux_hdr_entry->contents.cpy.copyright = (char *) (malloc (len + 1));
5051 strcpy (aux_hdr_entry->contents.cpy.copyright, PREFIX);
5052 strcat (aux_hdr_entry->contents.cpy.copyright, name);
5053 if (date_part)
5054 {
5055 strcat (aux_hdr_entry->contents.cpy.copyright, ",");
5056 strcat (aux_hdr_entry->contents.cpy.copyright, date_part);
5057 }
5058 strcat (aux_hdr_entry->contents.cpy.copyright, MIDFIX);
5059 strcat (aux_hdr_entry->contents.cpy.copyright, name);
5060 strcat (aux_hdr_entry->contents.cpy.copyright, SUFFIX);
5061 aux_hdr_entry->contents.cpy.copyright[len] = NULL;
5062 #undef PREFIX
5063 #undef MIDFIX
5064 #undef SUFFIX
5065 #endif /* OBJ_SOM */
5066 }
5067 *input_line_pointer = c;
5068 }
5069 else
5070 {
5071 as_bad ("Expected \"-ed string");
5072 }
5073 pa_undefine_label ();
5074 demand_empty_rest_of_line ();
5075 }
5076
5077 void
5078 pa_end ()
5079 {
5080
5081 demand_empty_rest_of_line ();
5082 return;
5083 }
5084
5085 void
5086 pa_enter ()
5087 {
5088
5089 as_bad (".ENTER encountered. gas doesn't generate entry code sequences.");
5090 pa_entry ();
5091 return;
5092 }
5093
5094 void
5095 pa_entry ()
5096 {
5097 char *where;
5098
5099 if (!within_procedure)
5100 as_bad ("Misplaced .entry. Ignored.");
5101 else
5102 {
5103 if (!callinfo_found)
5104 as_bad ("Missing .callinfo.");
5105
5106 last_call_info->start_frag = frag_now;
5107 }
5108 demand_empty_rest_of_line ();
5109 within_entry_exit = TRUE;
5110 where = frag_more (0);
5111 #ifdef OBJ_SOM
5112 fix_new (frag_now, where - frag_now->fr_literal, 0,
5113 last_call_info->start_symbol, (symbolS *) NULL, 0, 0,
5114 R_ENTRY, e_fsel, 0, 0, (char *) &last_call_info->ci_unwind.descriptor);
5115 #else
5116 #ifdef OBJ_ELF
5117 /* XXX: no ENTRY relocation for PA ELF. What do we do instead? */
5118 #else
5119 fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
5120 last_call_info->start_symbol, (symbolS *) NULL, 0, 0,
5121 R_HPPA_ENTRY, 0, 0, 0,
5122 (char *) &last_call_info->ci_unwind.descriptor);
5123 #endif
5124 #endif
5125 return;
5126 }
5127
5128 void
5129 pa_equ (reg)
5130 int reg;
5131 {
5132 register label_symbolS *label_symbolP = pa_get_label ();
5133 register symbolS *symbolP;
5134
5135 if (label_symbolP)
5136 {
5137 symbolP = label_symbolP->lss_label;
5138 #ifdef OBJ_SOM
5139 symbolP->pa_sy_value = get_absolute_expression ();
5140 symbolP->pa_sy_type = ST_ABSOLUTE;
5141 symbolP->sy_ref = sym_unref;
5142 symbolP->sy_equ = 1;
5143 #else
5144 S_SET_VALUE (symbolP, get_absolute_expression ());
5145 S_SET_SEGMENT (symbolP, &bfd_abs_section);
5146 #endif
5147 }
5148 else
5149 {
5150 if (reg)
5151 as_bad (".REG must use a label");
5152 else
5153 as_bad (".EQU must use a label");
5154 }
5155
5156 pa_undefine_label ();
5157 demand_empty_rest_of_line ();
5158 return;
5159 }
5160
5161 void
5162 process_exit ()
5163 {
5164 char *where;
5165
5166 where = frag_more (0);
5167 #ifdef OBJ_SOM
5168 fix_new (frag_now, where - frag_now->fr_literal, 0,
5169 last_call_info->start_symbol, (symbolS *) NULL, 0,
5170 0, R_EXIT, e_fsel, 0, 0, (char *) NULL);
5171 #endif
5172 #ifdef OBJ_ELF
5173 /* XXX: no EXIT relocation for PA ELF. All we do is create a */
5174 /* temporary symbol marking the end of the function. */
5175 {
5176 char *name = (char *) xmalloc (strlen ("L\001end_") +
5177 strlen (S_GET_NAME (last_call_info->start_symbol)) + 1);
5178
5179 if (name)
5180 {
5181 symbolS *symbolP;
5182
5183 strcpy (name, "L\001end_");
5184 strcat (name, S_GET_NAME (last_call_info->start_symbol));
5185
5186 symbolP = symbol_find (name);
5187 if (symbolP)
5188 as_warn ("Symbol '%s' already defined.", name);
5189 else
5190 {
5191 /* symbol value should be the offset of the */
5192 /* last instruction of the function */
5193 symbolP = symbol_new (name,
5194 now_seg,
5195 (valueT) (obstack_next_free (&frags) - frag_now->fr_literal - 4),
5196 frag_now);
5197
5198 assert (symbolP);
5199
5200 symbolP->bsym->flags = last_call_info->start_symbol->bsym->flags;
5201 symbol_table_insert (symbolP);
5202 }
5203 if (symbolP)
5204 last_call_info->end_symbol = symbolP;
5205 else
5206 as_bad ("Symbol '%s' could not be created.", name);
5207
5208 }
5209 else
5210 as_bad ("No memory for symbol name.");
5211 }
5212 #else
5213 fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
5214 last_call_info->start_symbol, (symbolS *) NULL, 0,
5215 0, R_HPPA_EXIT, 0, 0, 0, (char *) NULL);
5216 #endif
5217 last_call_info->end_frag = frag_now;
5218
5219 pa_build_unwind_subspace (last_call_info);
5220
5221 exit_processing_complete = TRUE;
5222 }
5223
5224 void
5225 pa_exit ()
5226 {
5227
5228 if (!within_procedure)
5229 as_bad (".EXIT must appear within a procedure");
5230 else
5231 {
5232 if (!callinfo_found)
5233 as_bad ("Missing .callinfo");
5234 else
5235 {
5236 if (!within_entry_exit)
5237 as_bad ("No .ENTRY for this .EXIT");
5238 else
5239 {
5240 within_entry_exit = FALSE;
5241 process_exit ();
5242 }
5243 }
5244 }
5245 demand_empty_rest_of_line ();
5246 return;
5247 }
5248
5249 void
5250 pa_export ()
5251 {
5252 register char *name;
5253 register char c;
5254 register char *p;
5255 register int temp;
5256 register int regno;
5257 register symbolS *symbolP;
5258
5259 name = input_line_pointer;
5260 c = get_symbol_end ();
5261 /* just after name is now '\0' */
5262
5263 if ((symbolP = symbol_find_or_make (name)) == NULL)
5264 {
5265 as_bad ("Cannot define export symbol: %s\n", name);
5266 p = input_line_pointer;
5267 *p = c;
5268 input_line_pointer++;
5269 }
5270 else
5271 {
5272 #ifdef OBJ_SOM
5273 symbolP->pa_sy_dict.symbol_scope = SS_UNIVERSAL;
5274 /* determination of the symbol_type field will have to wait until
5275 we know the subspace index (within the object file) of the subspace
5276 containing this symbol */
5277 #else
5278 /* S_SET_SEGMENT(symbolP,&bfd_und_section); */
5279 S_SET_EXTERNAL (symbolP);
5280 /* symbolP->sy_frag = frag_now; */
5281 #endif
5282
5283 p = input_line_pointer;
5284 *p = c;
5285 if (!is_end_of_statement ())
5286 {
5287 input_line_pointer++;
5288 pa_export_args (symbolP);
5289 }
5290 }
5291
5292 demand_empty_rest_of_line ();
5293 return;
5294 }
5295
5296 void
5297 pa_export_args (symbolP)
5298 register symbolS *symbolP;
5299 {
5300 register char *name;
5301 register char c;
5302 register char *p;
5303 register int temp;
5304 register unsigned int arg_reloc;
5305 #ifdef OBJ_ELF
5306 elf_symbol_type *esymbolP = (elf_symbol_type *) (symbolP->bsym);
5307 #endif
5308
5309 if (strncasecmp (input_line_pointer, "absolute", 8) == 0)
5310 {
5311 input_line_pointer += 8;
5312 #ifdef OBJ_SOM
5313 symbolP->pa_sy_dict.symbol_type = ST_ABSOLUTE;
5314 #else
5315 S_SET_SEGMENT (symbolP, &bfd_abs_section);
5316 #endif
5317 }
5318 else if (strncasecmp (input_line_pointer, "code", 4) == 0)
5319 {
5320 input_line_pointer += 4;
5321 #ifdef OBJ_SOM
5322 symbolP->pa_sy_dict.symbol_type = ST_CODE;
5323 #else
5324 /* S_SET_SEGMENT(symbolP,text_section); */
5325 #endif
5326 }
5327 else if (strncasecmp (input_line_pointer, "data", 4) == 0)
5328 {
5329 input_line_pointer += 4;
5330 #ifdef OBJ_SOM
5331 symbolP->pa_sy_dict.symbol_type = ST_DATA;
5332 #else
5333 /* S_SET_SEGMENT(symbolP,data_section); */
5334 #endif
5335 }
5336 else if ((strncasecmp (input_line_pointer, "entry", 5) == 0))
5337 {
5338 input_line_pointer += 5;
5339 #ifdef OBJ_SOM
5340 symbolP->pa_sy_dict.symbol_type = ST_ENTRY;
5341 #else
5342 symbolP->bsym->flags |= BSF_FUNCTION;
5343 #endif
5344 }
5345 else if (strncasecmp (input_line_pointer, "millicode", 9) == 0)
5346 {
5347 input_line_pointer += 9;
5348 #ifdef OBJ_SOM
5349 symbolP->pa_sy_dict.symbol_type = ST_MILLICODE;
5350 #endif
5351 }
5352 else if (strncasecmp (input_line_pointer, "plabel", 6) == 0)
5353 {
5354 input_line_pointer += 6;
5355 #ifdef OBJ_SOM
5356 symbolP->pa_sy_dict.symbol_type = ST_PLABEL;
5357 #endif
5358 }
5359 else if (strncasecmp (input_line_pointer, "pri_prog", 8) == 0)
5360 {
5361 input_line_pointer += 8;
5362 #ifdef OBJ_SOM
5363 symbolP->pa_sy_dict.symbol_type = ST_PRI_PROG;
5364 #endif
5365 }
5366 else if (strncasecmp (input_line_pointer, "sec_prog", 8) == 0)
5367 {
5368 input_line_pointer += 8;
5369 #ifdef OBJ_SOM
5370 symbolP->pa_sy_dict.symbol_type = ST_SEC_PROG;
5371 #endif
5372 }
5373
5374 while (!is_end_of_statement ())
5375 {
5376 if (*input_line_pointer == ',')
5377 input_line_pointer++;
5378 name = input_line_pointer;
5379 c = get_symbol_end ();
5380 if ((strncasecmp (name, "argw", 4) == 0))
5381 {
5382 p = input_line_pointer;
5383 *p = c;
5384 input_line_pointer++;
5385 temp = atoi (name + 4);
5386 name = input_line_pointer;
5387 c = get_symbol_end ();
5388 arg_reloc = pa_align_arg_reloc (temp, pa_build_arg_reloc (name));
5389 #ifdef OBJ_SOM
5390 symbolP->pa_sy_dict.arg_reloc |= arg_reloc;
5391 #else
5392 esymbolP->tc_data.hppa_arg_reloc |= arg_reloc;
5393 #endif
5394 *input_line_pointer = c;
5395 }
5396 else if ((strncasecmp (name, "rtnval", 6)) == 0)
5397 {
5398 p = input_line_pointer;
5399 *p = c;
5400 input_line_pointer++;
5401 name = input_line_pointer;
5402 c = get_symbol_end ();
5403 arg_reloc = pa_build_arg_reloc (name);
5404 #ifdef OBJ_SOM
5405 symbolP->pa_sy_dict.arg_reloc |= arg_reloc;
5406 #else
5407 esymbolP->tc_data.hppa_arg_reloc |= arg_reloc;
5408 #endif
5409 *input_line_pointer = c;
5410 }
5411 else if ((strncasecmp (name, "priv_lev", 8)) == 0)
5412 {
5413 p = input_line_pointer;
5414 *p = c;
5415 input_line_pointer++;
5416 /*** temp = get_absolute_expression (); ***/
5417 temp = atoi (input_line_pointer);
5418 c = get_symbol_end ();
5419 *input_line_pointer = c;
5420 #ifdef OBJ_SOM
5421 symbolP->sy_priv_lev = temp & 3; /* this is stored in symbol_value later */
5422 #endif
5423 }
5424 else
5425 {
5426 as_bad ("Undefined .EXPORT/.IMPORT argument (ignored): %s", name);
5427 p = input_line_pointer;
5428 *p = c;
5429 }
5430 if (!is_end_of_statement ())
5431 input_line_pointer++;
5432 }
5433 }
5434
5435 void
5436 pa_import ()
5437 {
5438 register char *name;
5439 register char c;
5440 register char *p;
5441 register symbolS *symbolP;
5442 register expressionS resultP; /* Deliver result here. */
5443
5444 name = input_line_pointer;
5445 c = get_symbol_end ();
5446 /* just after name is now '\0' */
5447
5448 symbolP = symbol_find_or_make (name);
5449 #if defined(OBJ_ELF)
5450 /* symbolP->bsym->flags |= BSF_IMPORT; *//* XXX BSF_IMPORT is obsolete */
5451 #else
5452 /* Check to see if this symbol has already been exported (this means its */
5453 /* defined locally and the import statement is redundant). */
5454 /* If it has not been exported, go ahead and mark this symbol as SS_UNSAT */
5455 /* (an unsatisfied external symbol) */
5456
5457 /* But, if the symbol has already been referenced (sy_ref == TRUE),
5458 leave it alone. */
5459
5460 if (!symbolP->sy_ref)
5461 {
5462 if (symbolP->pa_sy_dict.symbol_scope != SS_UNIVERSAL)
5463 {
5464 symbolP->pa_sy_dict.symbol_scope = SS_UNSAT;
5465 symbolP->sy_ref = FALSE;
5466 }
5467 }
5468 #endif
5469
5470 p = input_line_pointer;
5471 *p = c;
5472
5473 if (!is_end_of_statement ())
5474 {
5475 input_line_pointer++;
5476
5477 pa_export_args (symbolP);
5478 #ifdef OBJ_ELF
5479 /* In ELF, since this is an import, leave the section undefined. */
5480 /* S_SET_SEGMENT(symbolP,&bfd_und_section); */
5481 #endif
5482 }
5483 else
5484 {
5485 #ifdef OBJ_SOM
5486 /* no further arguments, assign a default type according
5487 to the current subspace (CODE or DATA) */
5488 switch (now_seg)
5489 {
5490 case SEG_TEXT:
5491 symbolP->pa_sy_dict.symbol_type = ST_CODE;
5492 break;
5493 case SEG_ABSOLUTE:
5494 symbolP->pa_sy_dict.symbol_type = ST_ABSOLUTE;
5495 break;
5496 default:
5497 symbolP->pa_sy_dict.symbol_type = ST_DATA;
5498 }
5499 #else
5500 /* In ELF, if the section is undefined, then the symbol is undefined */
5501 /* Since this is an import, leave the section undefined. */
5502 S_SET_SEGMENT (symbolP, &bfd_und_section);
5503 #endif
5504 }
5505
5506
5507 demand_empty_rest_of_line ();
5508 return;
5509 }
5510
5511 void
5512 pa_label ()
5513 {
5514 register char *name;
5515 register char c;
5516 register char *p;
5517
5518 name = input_line_pointer;
5519 c = get_symbol_end ();
5520 /* just after name is now '\0' */
5521
5522 if (strlen (name) > 0)
5523 {
5524 colon (name);
5525 p = input_line_pointer;
5526 *p = c;
5527 }
5528 else
5529 {
5530 as_warn ("Missing label name on .LABEL");
5531 }
5532
5533 if (!is_end_of_statement ())
5534 {
5535 as_warn ("extra .LABEL arguments ignored.");
5536 ignore_rest_of_line ();
5537 }
5538 demand_empty_rest_of_line ();
5539 return;
5540 }
5541
5542 void
5543 pa_leave ()
5544 {
5545
5546 as_bad (".LEAVE encountered. gas doesn't generate exit code sequences.");
5547 pa_exit ();
5548 return;
5549 }
5550
5551 void
5552 pa_origin ()
5553 {
5554 s_org (); /* ORG actually allows another argument (the fill value)
5555 but maybe this is OK? */
5556 pa_undefine_label ();
5557 return;
5558 }
5559
5560 void
5561 pa_proc ()
5562 {
5563 call_infoS *call_info;
5564
5565 if (within_procedure)
5566 as_fatal ("Nested procedures");
5567
5568 callinfo_found = FALSE;
5569 within_procedure = TRUE;
5570 exit_processing_complete = FALSE;
5571
5572 /* create another call_info structure */
5573
5574 call_info = (call_infoS *) xmalloc (sizeof (call_infoS));
5575
5576 if (!call_info)
5577 as_fatal ("Cannot allocate unwind descriptor\n");
5578
5579 bzero (call_info, sizeof (call_infoS));
5580
5581 call_info->ci_next = NULL;
5582
5583 if (call_info_root == NULL)
5584 {
5585 call_info_root = call_info;
5586 last_call_info = call_info;
5587 }
5588 else
5589 {
5590 last_call_info->ci_next = call_info;
5591 last_call_info = call_info;
5592 }
5593
5594 /* set up defaults on call_info structure */
5595
5596 call_info->ci_unwind.descriptor.cannot_unwind = 0;
5597 call_info->ci_unwind.descriptor.region_desc = 1;
5598 call_info->entry_sr = ~0;
5599 call_info->makes_calls = 1;
5600 call_info->hpux_int = 0;
5601
5602 /* If we got a .PROC pseudo-op, we know that the function is defined
5603 locally. Make sure it gets into the symbol table */
5604 {
5605 label_symbolS *label_symbolP = pa_get_label ();
5606
5607 if (label_symbolP)
5608 {
5609 if (label_symbolP->lss_label)
5610 {
5611 #ifdef OBJ_SOM
5612 label_symbolP->lss_label->sy_ref |= sym_def;
5613 #endif
5614 last_call_info->start_symbol = label_symbolP->lss_label;
5615 label_symbolP->lss_label->bsym->flags |= BSF_FUNCTION;
5616 }
5617 else
5618 as_bad ("Missing function name for .PROC (corrupted label)");
5619 }
5620 else
5621 as_bad ("Missing function name for .PROC");
5622 }
5623
5624 demand_empty_rest_of_line ();
5625 return;
5626 }
5627
5628 void
5629 pa_procend ()
5630 {
5631
5632 if (!within_procedure)
5633 as_bad ("misplaced .procend");
5634
5635 if (!callinfo_found)
5636 as_bad ("Missing .callinfo for this procedure");
5637
5638 if (within_entry_exit)
5639 as_bad ("Missing .EXIT for a .ENTRY");
5640
5641 if (!exit_processing_complete)
5642 process_exit ();
5643
5644 within_procedure = FALSE;
5645 demand_empty_rest_of_line ();
5646 return;
5647 }
5648
5649 space_dict_chainS *
5650 pa_parse_space_stmt (space_name, create_flag)
5651 char *space_name;
5652 int create_flag;
5653 {
5654 register char *name;
5655 register char c;
5656 register char *p;
5657 register int temp;
5658
5659 char *ptemp;
5660 int spnum;
5661 char loadable;
5662 char defined;
5663 char private;
5664 char sort;
5665 #ifdef OBJ_SOM
5666 segT seg;
5667 #else
5668 asection *seg;
5669 #endif
5670 space_dict_chainS *space;
5671
5672 /* load default values */
5673 spnum = 0;
5674 loadable = TRUE;
5675 defined = TRUE;
5676 private = FALSE;
5677 if (strcasecmp (space_name, "$TEXT$") == 0)
5678 {
5679 #ifdef OBJ_SOM
5680 seg = SEG_TEXT;
5681 #else
5682 seg = text_section;
5683 #endif
5684 sort = 8;
5685 }
5686 else
5687 {
5688 #ifdef OBJ_SOM
5689 seg = SEG_DATA;
5690 #else
5691 seg = data_section;
5692 #endif
5693 sort = 16;
5694 }
5695
5696 if (!is_end_of_statement ())
5697 {
5698 print_errors = FALSE;
5699 ptemp = input_line_pointer + 1;
5700 if ((temp = pa_parse_number (&ptemp)) >= 0)
5701 {
5702 spnum = temp;
5703 input_line_pointer = ptemp;
5704 }
5705 else
5706 {
5707 while (!is_end_of_statement ())
5708 {
5709 input_line_pointer++;
5710 name = input_line_pointer;
5711 c = get_symbol_end ();
5712 if ((strncasecmp (name, "SPNUM", 5) == 0))
5713 {
5714 p = input_line_pointer;
5715 *p = c;
5716 input_line_pointer++;
5717 temp = get_absolute_expression ();
5718 spnum = temp;
5719 }
5720 else if ((strncasecmp (name, "SORT", 4) == 0))
5721 {
5722 p = input_line_pointer;
5723 *p = c;
5724 input_line_pointer++;
5725 temp = get_absolute_expression ();
5726 sort = temp;
5727 }
5728 else if ((strncasecmp (name, "UNLOADABLE", 10) == 0))
5729 {
5730 p = input_line_pointer;
5731 *p = c;
5732 loadable = FALSE;
5733 }
5734 else if ((strncasecmp (name, "NOTDEFINED", 10) == 0))
5735 {
5736 p = input_line_pointer;
5737 *p = c;
5738 defined = FALSE;
5739 }
5740 else if ((strncasecmp (name, "PRIVATE", 7) == 0))
5741 {
5742 p = input_line_pointer;
5743 *p = c;
5744 private = TRUE;
5745 }
5746 else
5747 {
5748 as_bad ("Unrecognized .SPACE argument");
5749 p = input_line_pointer;
5750 *p = c;
5751 }
5752 }
5753 }
5754 print_errors = TRUE;
5755 }
5756 if (create_flag)
5757 space = create_new_space (space_name, spnum, loadable, defined, private, sort, 1, seg);
5758 else
5759 { /* if no creation of new space, this must be the first */
5760 /* occurrence of a built-in space */
5761 space = is_defined_space (space_name);
5762 SPACE_SPNUM (space) = spnum;
5763 SPACE_LOADABLE (space) = loadable & 1;
5764 SPACE_DEFINED (space) = defined & 1;
5765 SPACE_PRIVATE (space) = private & 1;
5766 SPACE_SORT (space) = sort & 0xff;
5767 space->sd_defined = 1;
5768 space->sd_seg = seg;
5769 }
5770 return space;
5771 }
5772
5773 void
5774 pa_align_subseg (seg, subseg)
5775 #ifdef OBJ_SOM
5776 segT seg;
5777 #else
5778 asection *seg;
5779 #endif
5780 subsegT subseg;
5781 {
5782 subspace_dict_chainS *now_subspace;
5783 int alignment;
5784 int shift;
5785
5786 now_subspace = pa_subsegment_to_subspace (seg, subseg);
5787 if (SUBSPACE_ALIGN (now_subspace) == 0)
5788 alignment = now_subspace->ssd_last_align;
5789 else if (now_subspace->ssd_last_align > SUBSPACE_ALIGN (now_subspace))
5790 alignment = now_subspace->ssd_last_align;
5791 else
5792 alignment = SUBSPACE_ALIGN (now_subspace);
5793
5794 shift = 0;
5795 while ((1 << shift) < alignment)
5796 shift++;
5797
5798 frag_align (shift, 0);
5799 }
5800
5801 void
5802 pa_space ()
5803 {
5804 register char *name;
5805 register char c;
5806 register char *p;
5807 register int temp;
5808 register symbolS *symbolP;
5809 register space_dict_chainS *sd_chain;
5810 char space_name[40];
5811
5812 if (within_procedure)
5813 {
5814 as_bad ("Can\'t change spaces within a procedure definition. Ignored");
5815 ignore_rest_of_line ();
5816 }
5817 else
5818 {
5819 if (strncasecmp (input_line_pointer, "$text$", 6) == 0)
5820 {
5821 input_line_pointer += 6;
5822 sd_chain = is_defined_space ("$TEXT$");
5823 if (sd_chain == NULL)
5824 sd_chain = pa_parse_space_stmt ("$TEXT$", 1);
5825 else if (sd_chain->sd_defined == 0)
5826 sd_chain = pa_parse_space_stmt ("$TEXT$", 0);
5827
5828 current_space = sd_chain;
5829 SPACE_DEFINED (current_space) = 1;
5830 current_space->sd_defined = 1;
5831 #ifdef OBJ_SOM
5832 if (now_seg != SEG_TEXT) /* no need to align if we are already there */
5833 #else
5834 if (now_seg != text_section) /* no need to align if we are already there */
5835 #endif
5836 pa_align_subseg (now_seg, now_subseg);
5837
5838 #ifdef OBJ_SOM
5839 subseg_new (SEG_TEXT, sd_chain->sd_last_subseg);
5840 current_subspace = pa_subsegment_to_subspace (SEG_TEXT,
5841 sd_chain->sd_last_subseg);
5842 #else
5843 subseg_new ((char *) text_section->name, sd_chain->sd_last_subseg);
5844 current_subspace = pa_subsegment_to_subspace (text_section,
5845 sd_chain->sd_last_subseg);
5846 #endif
5847 demand_empty_rest_of_line ();
5848 return;
5849 }
5850 if (strncasecmp (input_line_pointer, "$private$", 9) == 0)
5851 {
5852 input_line_pointer += 9;
5853 sd_chain = is_defined_space ("$PRIVATE$");
5854 if (sd_chain == NULL)
5855 sd_chain = pa_parse_space_stmt ("$PRIVATE$", 1);
5856 else if (sd_chain->sd_defined == 0)
5857 sd_chain = pa_parse_space_stmt ("$PRIVATE$", 0);
5858
5859 current_space = sd_chain;
5860 SPACE_DEFINED (current_space) = 1;
5861 current_space->sd_defined = 1;
5862 #ifdef OBJ_SOM
5863 if (now_seg != SEG_DATA) /* no need to align if we are already there */
5864 #else
5865 if (now_seg != data_section) /* no need to align if we are already there */
5866 #endif
5867 pa_align_subseg (now_seg, now_subseg);
5868 #ifdef OBJ_SOM
5869 subseg_new (SEG_DATA, sd_chain->sd_last_subseg);
5870 current_subspace = pa_subsegment_to_subspace (SEG_DATA,
5871 sd_chain->sd_last_subseg);
5872 #else
5873 subseg_new ((char *) data_section->name, sd_chain->sd_last_subseg);
5874 current_subspace = pa_subsegment_to_subspace (data_section,
5875 sd_chain->sd_last_subseg);
5876 #endif
5877 demand_empty_rest_of_line ();
5878 return;
5879 }
5880 if (strncasecmp (input_line_pointer,
5881 GDB_DEBUG_SPACE_NAME, strlen (GDB_DEBUG_SPACE_NAME)) == 0)
5882 {
5883 input_line_pointer += strlen (GDB_DEBUG_SPACE_NAME);
5884 sd_chain = is_defined_space (GDB_DEBUG_SPACE_NAME);
5885 if (sd_chain == NULL)
5886 sd_chain = pa_parse_space_stmt (GDB_DEBUG_SPACE_NAME, 1);
5887 else if (sd_chain->sd_defined == 0)
5888 sd_chain = pa_parse_space_stmt (GDB_DEBUG_SPACE_NAME, 0);
5889
5890 current_space = sd_chain;
5891 SPACE_DEFINED (current_space) = 1;
5892 current_space->sd_defined = 1;
5893 #ifdef OBJ_SOM
5894 if (now_seg != SEG_GDB) /* no need to align if we are already there */
5895 pa_align_subseg (now_seg, now_subseg);
5896 subseg_new (SEG_GDB, sd_chain->sd_last_subseg);
5897 current_subspace = pa_subsegment_to_subspace (SEG_GDB,
5898 sd_chain->sd_last_subseg);
5899 #else
5900 if (now_seg != gdb_section) /* no need to align if we are already there */
5901 pa_align_subseg (now_seg, now_subseg);
5902 subseg_new ((char *) gdb_section->name, sd_chain->sd_last_subseg);
5903 current_subspace = pa_subsegment_to_subspace (gdb_section,
5904 sd_chain->sd_last_subseg);
5905 #endif
5906 demand_empty_rest_of_line ();
5907 return;
5908 }
5909
5910 /* it could be a space specified by number */
5911
5912 if ((temp = pa_parse_number (&input_line_pointer)) >= 0)
5913 {
5914 if (sd_chain = pa_find_space_by_number (temp))
5915 {
5916 current_space = sd_chain;
5917 SPACE_DEFINED (current_space) = 1;
5918 current_space->sd_defined = 1;
5919 if (now_seg != sd_chain->sd_seg) /* don't align if we're already there */
5920 pa_align_subseg (now_seg, now_subseg);
5921 #ifdef OBJ_SOM
5922 subseg_new (sd_chain->sd_seg, sd_chain->sd_last_subseg);
5923 #else
5924 subseg_new ((char *) sd_chain->sd_seg->name, sd_chain->sd_last_subseg);
5925 #endif
5926 current_subspace = pa_subsegment_to_subspace (sd_chain->sd_seg,
5927 sd_chain->sd_last_subseg);
5928 demand_empty_rest_of_line ();
5929 return;
5930 }
5931 }
5932
5933 /* not a number, attempt to create a new space */
5934
5935 name = input_line_pointer;
5936 c = get_symbol_end ();
5937 space_name[0] = 0x00;
5938 strcpy (space_name, name);
5939 *input_line_pointer = c;
5940
5941 sd_chain = pa_parse_space_stmt (space_name, 1);
5942 current_space = sd_chain;
5943 SPACE_DEFINED (current_space) = 1;
5944 current_space->sd_defined = 1;
5945 if (now_seg != sd_chain->sd_seg) /* don't align if we're already there */
5946 pa_align_subseg (now_seg, now_subseg);
5947 #ifdef OBJ_SOM
5948 subseg_new (sd_chain->sd_seg, sd_chain->sd_last_subseg);
5949 #else
5950 subseg_new ((char *) sd_chain->sd_seg->name, sd_chain->sd_last_subseg);
5951 #endif
5952 current_subspace = pa_subsegment_to_subspace (sd_chain->sd_seg,
5953 sd_chain->sd_last_subseg);
5954 demand_empty_rest_of_line ();
5955 }
5956 return;
5957 }
5958
5959 void
5960 pa_spnum ()
5961 {
5962 register char *name;
5963 register char c;
5964 register char *p;
5965 space_dict_chainS *space;
5966
5967 name = input_line_pointer;
5968 c = get_symbol_end ();
5969 space = is_defined_space (name);
5970 if (space)
5971 {
5972 p = frag_more (4);
5973 /* put bytes in right order. */
5974 md_number_to_chars (p, SPACE_SPNUM (space), 4);
5975 }
5976 else
5977 as_warn ("Undefined space: '%s' Assuming space number = 0.", name);
5978
5979 *input_line_pointer = c;
5980 demand_empty_rest_of_line ();
5981 return;
5982 }
5983
5984 static
5985 int
5986 is_power_of_2 (value)
5987 int value;
5988 {
5989 int shift;
5990
5991 shift = 0;
5992 while ((1 << shift) != value && shift < 32)
5993 shift++;
5994
5995 if (shift >= 32)
5996 shift = 0;
5997 return shift;
5998 }
5999
6000 void
6001 pa_subspace ()
6002 {
6003 register char *name;
6004 register char c;
6005 register char *p;
6006 register int temp;
6007 register symbolS *symbolP;
6008
6009 char loadable, code_only, common, dup_common, zero;
6010 char sort;
6011 int number;
6012 int i;
6013 int access;
6014 int space_index;
6015 int alignment;
6016 int quadrant;
6017 int subseg;
6018 space_dict_chainS *space;
6019 subspace_dict_chainS *ssd;
6020 subspace_dict_chainS *ssdCh;
6021 char *ss_name;
6022 int is_power_of_2 ();
6023
6024 if (within_procedure)
6025 {
6026 as_bad ("Can\'t change subspaces within a procedure definition. Ignored");
6027 ignore_rest_of_line ();
6028 }
6029 else
6030 {
6031 name = input_line_pointer;
6032 c = get_symbol_end ();
6033 space = pa_segment_to_space (now_seg);
6034 ssd = is_defined_subspace (name, space->sd_last_subseg);
6035
6036 ss_name = xmalloc (strlen (name) + 1);
6037 strcpy (ss_name, name);
6038
6039 *input_line_pointer = c;
6040
6041 /* load default values */
6042 sort = 0;
6043 access = 0x7f;
6044 loadable = 1;
6045 common = 0;
6046 dup_common = 0;
6047 code_only = 0;
6048 zero = 0;
6049 space_index = ~0; /* filled in when the .o file is written */
6050 alignment = 0; /* alignment=0 means no ALIGN= appeared on the .SUBSPA */
6051 /* pseudo-op. The default will be the largest .ALIGN */
6052 /* encountered (or 1 if no .ALIGN is encountered) */
6053 quadrant = 0;
6054
6055 if (ssd)
6056 {
6057 if (ssd->ssd_defined)
6058 {
6059 #ifdef OBJ_SOM
6060 subseg_new (now_seg, ssd->ssd_subseg);
6061 #else
6062 /* subseg_new(now_seg->name,ssd->ssd_subseg); */
6063 subseg_new ((char *) ssd->ssd_seg->name, ssd->ssd_subseg);
6064 #endif
6065 if (!is_end_of_statement ())
6066 {
6067 as_warn ("Parameters of an existing subspace can\'t be modified");
6068 }
6069 demand_empty_rest_of_line ();
6070 return;
6071 }
6072 else
6073 {
6074 ssd->ssd_defined = 1;
6075 }
6076 }
6077 else
6078 {
6079 /* a new subspace */
6080 /* load default values */
6081 i = 0;
6082 while (pa_def_subspaces[i].name)
6083 {
6084 if (strcasecmp (pa_def_subspaces[i].name, ss_name) == 0)
6085 {
6086 loadable = pa_def_subspaces[i].loadable;
6087 common = pa_def_subspaces[i].common;
6088 dup_common = pa_def_subspaces[i].dup_common;
6089 code_only = pa_def_subspaces[i].code_only;
6090 zero = pa_def_subspaces[i].zero;
6091 space_index = pa_def_subspaces[i].space_index;
6092 /* alignment = pa_def_subspaces[i].alignment; */
6093 alignment = 0;
6094 quadrant = pa_def_subspaces[i].quadrant;
6095 access = pa_def_subspaces[i].access;
6096 sort = pa_def_subspaces[i].sort;
6097 break;
6098 }
6099 i++;
6100 }
6101 }
6102
6103 if (!is_end_of_statement ())
6104 {
6105 input_line_pointer++;
6106 while (!is_end_of_statement ())
6107 {
6108 name = input_line_pointer;
6109 c = get_symbol_end ();
6110 if ((strncasecmp (name, "QUAD", 4) == 0))
6111 {
6112 *input_line_pointer = c;
6113 input_line_pointer++;
6114 temp = get_absolute_expression ();
6115 quadrant = temp;
6116 }
6117 else if ((strncasecmp (name, "ALIGN", 5) == 0))
6118 {
6119 *input_line_pointer = c;
6120 input_line_pointer++;
6121 temp = get_absolute_expression ();
6122 alignment = temp;
6123 if (!is_power_of_2 (alignment))
6124 {
6125 as_bad ("Alignment must be a power of 2");
6126 alignment = 1;
6127 }
6128 }
6129 else if ((strncasecmp (name, "ACCESS", 6) == 0))
6130 {
6131 *input_line_pointer = c;
6132 input_line_pointer++;
6133 temp = get_absolute_expression ();
6134 access = temp;
6135 }
6136 else if ((strncasecmp (name, "SORT", 4) == 0))
6137 {
6138 *input_line_pointer = c;
6139 input_line_pointer++;
6140 temp = get_absolute_expression ();
6141 sort = temp;
6142 }
6143 else if ((strncasecmp (name, "CODE_ONLY", 9) == 0))
6144 {
6145 *input_line_pointer = c;
6146 code_only = 1;
6147 }
6148 else if ((strncasecmp (name, "UNLOADABLE", 10) == 0))
6149 {
6150 *input_line_pointer = c;
6151 loadable = 0;
6152 }
6153 else if ((strncasecmp (name, "COMMON", 6) == 0))
6154 {
6155 *input_line_pointer = c;
6156 common = 1;
6157 }
6158 else if ((strncasecmp (name, "DUP_COMM", 8) == 0))
6159 {
6160 *input_line_pointer = c;
6161 dup_common = 1;
6162 }
6163 else if ((strncasecmp (name, "ZERO", 4) == 0))
6164 {
6165 *input_line_pointer = c;
6166 zero = 1;
6167 }
6168 else
6169 {
6170 as_bad ("Unrecognized .SUBSPACE argument");
6171 }
6172 if (!is_end_of_statement ())
6173 input_line_pointer++;
6174 }
6175 }
6176 space = pa_segment_to_space (now_seg);
6177 if (ssd)
6178 {
6179 current_subspace = update_subspace (ss_name, 1, loadable, code_only,
6180 common, dup_common, sort, zero, access,
6181 space_index, alignment, quadrant,
6182 ssd->ssd_subseg);
6183 }
6184 else
6185 {
6186 current_subspace = create_new_subspace (space, ss_name, 1, loadable, code_only,
6187 common, dup_common, zero, sort,
6188 access, space_index, alignment,
6189 quadrant, now_seg);
6190 }
6191 SUBSPACE_SUBSPACE_START (current_subspace) = pa_subspace_start (space, quadrant);
6192
6193 demand_empty_rest_of_line ();
6194 #ifdef OBJ_SOM
6195 subseg_new (current_subspace->ssd_seg, current_subspace->ssd_subseg);
6196 #else
6197 subseg_new ((char *) current_subspace->ssd_seg->name, current_subspace->ssd_subseg);
6198 #endif
6199 }
6200 return;
6201 }
6202
6203 /* For ELF, this function serves one purpose: to setup the st_size */
6204 /* field of STT_FUNC symbols. To do this, we need to scan the */
6205 /* call_info structure list, determining st_size in one of two possible */
6206 /* ways: */
6207
6208 /* 1. call_info->start_frag->fr_fix has the size of the fragment. */
6209 /* This approach assumes that the function was built into a */
6210 /* single fragment. This works for most cases, but might fail. */
6211 /* For example, if there was a segment change in the middle of */
6212 /* the function. */
6213
6214 /* 2. The st_size field is the difference in the addresses of the */
6215 /* call_info->start_frag->fr_address field and the fr_address */
6216 /* field of the next fragment with fr_type == rs_fill and */
6217 /* fr_fix != 0. */
6218
6219 void
6220 elf_hppa_final_processing_hook ()
6221 {
6222 extern call_infoS *call_info_root;
6223
6224 call_infoS *ciP;
6225
6226 for (ciP = call_info_root; ciP; ciP = ciP->ci_next)
6227 {
6228 elf_symbol_type *esym = (elf_symbol_type *) ciP->start_symbol->bsym;
6229 esym->internal_elf_sym.st_size =
6230 ciP->end_symbol->bsym->value
6231 - ciP->start_symbol->bsym->value + 4;
6232 }
6233 }
6234
6235 /* pa-spaces.c -- Space/subspace support for the HP PA-RISC version of GAS */
6236
6237 /* for space, subspace, and symbol maintenance on HP 9000 Series 800 */
6238
6239 space_dict_chainS *space_dict_root;
6240 space_dict_chainS *space_dict_last;
6241
6242 space_dict_chainS *current_space;
6243 subspace_dict_chainS *current_subspace;
6244
6245 extern symbolS *start_symbol_root;
6246 extern symbolS *start_symbol_last;
6247
6248 void
6249 pa_spaces_begin ()
6250 {
6251 space_dict_chainS *space;
6252 int i;
6253 subsegT now_subseg = now_subseg;
6254
6255 space_dict_root = NULL;
6256 space_dict_last = NULL;
6257
6258 start_symbol_root = NULL;
6259 start_symbol_last = NULL;
6260
6261 /* create default space and subspace dictionaries */
6262
6263 i = 0;
6264 while (pa_def_spaces[i].name)
6265 {
6266 if (pa_def_spaces[i].alias)
6267 pa_def_spaces[i].segment = subseg_new (pa_def_spaces[i].alias, 0);
6268 else
6269 pa_def_spaces[i].segment = bfd_make_section_old_way (stdoutput, pa_def_spaces[i].name);
6270
6271 create_new_space (pa_def_spaces[i].name, pa_def_spaces[i].spnum,
6272 pa_def_spaces[i].loadable, pa_def_spaces[i].defined,
6273 pa_def_spaces[i].private, pa_def_spaces[i].sort, 0,
6274 pa_def_spaces[i].segment);
6275 i++;
6276 }
6277
6278 i = 0;
6279 while (pa_def_subspaces[i].name)
6280 {
6281 space = pa_segment_to_space (pa_def_spaces[pa_def_subspaces[i].def_space_index].segment);
6282 if (space)
6283 {
6284 char *name = pa_def_subspaces[i].alias;
6285 if (!name)
6286 name = pa_def_subspaces[i].name;
6287 create_new_subspace (space, name,
6288 pa_def_subspaces[i].defined,
6289 pa_def_subspaces[i].loadable,
6290 pa_def_subspaces[i].code_only, pa_def_subspaces[i].common,
6291 pa_def_subspaces[i].dup_common, pa_def_subspaces[i].zero,
6292 pa_def_subspaces[i].sort, pa_def_subspaces[i].access,
6293 pa_def_subspaces[i].space_index,
6294 pa_def_subspaces[i].alignment,
6295 pa_def_subspaces[i].quadrant,
6296 pa_def_spaces[pa_def_subspaces[i].def_space_index].segment);
6297 subseg_new (name, pa_def_subspaces[i].subsegment);
6298 }
6299 else
6300 as_fatal ("Internal error: space missing for subspace \"%s\"\n",
6301 pa_def_subspaces[i].name);
6302 i++;
6303 }
6304 }
6305
6306 space_dict_chainS *
6307 create_new_space (name, spnum, loadable, defined, private, sort, defined_in_file, seg)
6308 char *name;
6309 int spnum;
6310 char loadable;
6311 char defined;
6312 char private;
6313 char sort;
6314 char defined_in_file;
6315 asection *seg;
6316
6317 {
6318 Elf_Internal_Shdr *new_space;
6319 space_dict_chainS *chain_entry;
6320
6321 new_space = (Elf_Internal_Shdr *) xmalloc (sizeof (Elf_Internal_Shdr));
6322 if (!new_space)
6323 as_fatal ("Out of memory: could not allocate new Elf_Internal_Shdr: %s\n", name);
6324
6325 /*
6326 new_space->space_number = spnum;
6327 new_space->is_loadable = loadable & 1;
6328 new_space->is_defined = defined & 1;
6329 new_space->is_private = private & 1;
6330 new_space->sort_key = sort & 0xff;
6331
6332 new_space->loader_fix_index = ~0;
6333 new_space->loader_fix_quantity = 0;
6334 new_space->init_pointer_index = ~0;
6335 new_space->init_pointer_quantity = 0;
6336 new_space->subspace_quantity = 0;
6337 */
6338
6339 chain_entry = (space_dict_chainS *) xmalloc (sizeof (space_dict_chainS));
6340 if (!chain_entry)
6341 as_fatal ("Out of memory: could not allocate new space chain entry: %s\n", name);
6342
6343 SPACE_NAME (chain_entry) = (char *) xmalloc (strlen (name) + 1);
6344 strcpy (SPACE_NAME (chain_entry), name);
6345
6346 chain_entry->sd_entry = new_space;
6347 chain_entry->sd_defined = defined_in_file;
6348 chain_entry->sd_seg = seg;
6349 chain_entry->sd_last_subseg = -1;
6350 chain_entry->sd_next = NULL;
6351
6352 SPACE_SPNUM (chain_entry) = spnum;
6353 SPACE_LOADABLE (chain_entry) = loadable & 1;
6354 SPACE_DEFINED (chain_entry) = defined & 1;
6355 SPACE_PRIVATE (chain_entry) = private & 1;
6356 SPACE_SORT (chain_entry) = sort & 0xff;
6357
6358 /* find spot for the new space based on its sort key */
6359
6360 if (!space_dict_last)
6361 space_dict_last = chain_entry;
6362
6363 if (space_dict_root == NULL) /* if root is null, it is very easy */
6364 space_dict_root = chain_entry;
6365 else
6366 {
6367 space_dict_chainS *sdcP;
6368 space_dict_chainS *last_sdcP;
6369
6370 sdcP = space_dict_root;
6371 last_sdcP = NULL;
6372
6373 while (sdcP)
6374 {
6375 if (SPACE_SORT (sdcP) < SPACE_SORT (chain_entry))
6376 {
6377 last_sdcP = sdcP;
6378 sdcP = sdcP->sd_next;
6379 }
6380 else if (SPACE_SORT (sdcP) == SPACE_SORT (chain_entry))
6381 {
6382 last_sdcP = sdcP;
6383 sdcP = sdcP->sd_next;
6384 }
6385 else if (SPACE_SORT (sdcP) > SPACE_SORT (chain_entry))
6386 {
6387 break;
6388 }
6389 }
6390
6391 if (last_sdcP)
6392 {
6393 chain_entry->sd_next = sdcP;
6394 last_sdcP->sd_next = chain_entry;
6395 }
6396 else
6397 {
6398 space_dict_root = chain_entry;
6399 chain_entry->sd_next = sdcP;
6400 }
6401
6402 if (chain_entry->sd_next == NULL)
6403 space_dict_last = chain_entry;
6404 }
6405
6406 return chain_entry;
6407 }
6408
6409 subspace_dict_chainS
6410 * create_new_subspace (space, name, defined, loadable, code_only, common, dup_common,
6411 is_zero, sort, access, space_index, alignment, quadrant, seg)
6412 space_dict_chainS *space;
6413 char *name;
6414 char defined, loadable, code_only, common, dup_common, is_zero;
6415 char sort;
6416 int access;
6417 int space_index;
6418 int alignment;
6419 int quadrant;
6420 asection *seg;
6421 {
6422 Elf_Internal_Shdr *new_subspace;
6423 subspace_dict_chainS *chain_entry;
6424 symbolS *start_symbol;
6425
6426 new_subspace = (Elf_Internal_Shdr *) xmalloc (sizeof (Elf_Internal_Shdr));
6427 if (!new_subspace)
6428 as_fatal ("Out of memory: could not allocate new Elf_Internal_Shdr: %s\n",
6429 name);
6430
6431 /*
6432 new_subspace->space_index = space_index;
6433 new_subspace->fixup_request_index = ~0;
6434 */
6435
6436 chain_entry = (subspace_dict_chainS *) xmalloc (sizeof (subspace_dict_chainS));
6437 if (!chain_entry)
6438 as_fatal ("Out of memory: could not allocate new subspace chain entry: %s\n", name);
6439
6440 chain_entry->ssd_entry = new_subspace;
6441 SUBSPACE_NAME (chain_entry) = (char *) xmalloc (strlen (name) + 1);
6442 strcpy (SUBSPACE_NAME (chain_entry), name);
6443
6444 SUBSPACE_ACCESS (chain_entry) = access & 0x7f;
6445 SUBSPACE_LOADABLE (chain_entry) = loadable & 1;
6446 SUBSPACE_COMMON (chain_entry) = common & 1;
6447 SUBSPACE_DUP_COMM (chain_entry) = dup_common & 1;
6448 SUBSPACE_SORT (chain_entry) = sort & 0xff;
6449 SET_SUBSPACE_CODE_ONLY (chain_entry, code_only & 1);
6450 SUBSPACE_ALIGN (chain_entry) = alignment & 0xffff;
6451 SUBSPACE_QUADRANT (chain_entry) = quadrant & 0x3;
6452 SUBSPACE_SUBSPACE_START (chain_entry) = pa_subspace_start (space, quadrant);
6453
6454 chain_entry->ssd_defined = defined;
6455 chain_entry->ssd_space_number = space_index;
6456 chain_entry->ssd_subseg = pa_next_subseg (space);
6457 chain_entry->ssd_seg = seg;
6458 SUBSPACE_ZERO (chain_entry) = is_zero;
6459 chain_entry->ssd_last_align = 1;
6460 chain_entry->ssd_next = NULL;
6461
6462 /* find spot for the new subspace based on its sort key */
6463
6464 if (space->sd_subspaces == NULL) /* if root is null, it is very easy */
6465 space->sd_subspaces = chain_entry;
6466 else
6467 {
6468 subspace_dict_chainS *ssdcP;
6469 subspace_dict_chainS *last_ssdcP;
6470
6471 ssdcP = space->sd_subspaces;
6472 last_ssdcP = NULL;
6473
6474 while (ssdcP)
6475 {
6476 if (SUBSPACE_SORT (ssdcP) < SUBSPACE_SORT (chain_entry))
6477 {
6478 last_ssdcP = ssdcP;
6479 ssdcP = ssdcP->ssd_next;
6480 }
6481 else if (SUBSPACE_SORT (ssdcP) == SUBSPACE_SORT (chain_entry))
6482 {
6483 last_ssdcP = ssdcP;
6484 ssdcP = ssdcP->ssd_next;
6485 }
6486 else if (SUBSPACE_SORT (ssdcP) > SUBSPACE_SORT (chain_entry))
6487 {
6488 break;
6489 }
6490 }
6491
6492 if (last_ssdcP)
6493 {
6494 chain_entry->ssd_next = ssdcP;
6495 last_ssdcP->ssd_next = chain_entry;
6496 }
6497 else
6498 {
6499 space->sd_subspaces = chain_entry;
6500 chain_entry->ssd_next = ssdcP;
6501 }
6502 }
6503
6504 start_symbol = pa_set_start_symbol (seg, space->sd_last_subseg);
6505 chain_entry->ssd_start_sym = start_symbol;
6506 return chain_entry;
6507
6508 }
6509
6510 subspace_dict_chainS
6511 * update_subspace (name, defined, loadable, code_only, common, dup_common, sort, zero,
6512 access, space_index, alignment, quadrant, subseg)
6513 char *name;
6514 char defined, loadable, code_only, common, dup_common, zero;
6515 char sort;
6516 int access;
6517 int space_index;
6518 int alignment;
6519 int quadrant;
6520 subsegT subseg;
6521 {
6522 subspace_dict_chainS *chain_entry;
6523 subspace_dict_chainS *is_defined_subspace ();
6524
6525 if ((chain_entry = is_defined_subspace (name, subseg)))
6526 {
6527
6528 SUBSPACE_ACCESS (chain_entry) = access & 0x7f;
6529 SUBSPACE_LOADABLE (chain_entry) = loadable & 1;
6530 SUBSPACE_COMMON (chain_entry) = common & 1;
6531 SUBSPACE_DUP_COMM (chain_entry) = dup_common & 1;
6532 SET_SUBSPACE_CODE_ONLY (chain_entry, code_only & 1);
6533 SUBSPACE_SORT (chain_entry) = sort & 0xff;
6534 /* chain_entry->ssd_entry->space_index = space_index; */
6535 SUBSPACE_ALIGN (chain_entry) = alignment & 0xffff;
6536 SUBSPACE_QUADRANT (chain_entry) = quadrant & 0x3;
6537
6538 chain_entry->ssd_defined = defined;
6539 chain_entry->ssd_space_number = space_index;
6540 SUBSPACE_ZERO (chain_entry) = zero;
6541 }
6542 else
6543 chain_entry = NULL;
6544
6545 return chain_entry;
6546
6547 }
6548
6549 space_dict_chainS *
6550 is_defined_space (name)
6551 char *name;
6552 {
6553 space_dict_chainS *spaceCh;
6554
6555 for (spaceCh = space_dict_root; spaceCh; spaceCh = spaceCh->sd_next)
6556 {
6557 if (strcmp (SPACE_NAME (spaceCh), name) == 0)
6558 {
6559 return spaceCh;
6560 }
6561 }
6562
6563 return NULL;
6564 }
6565
6566 space_dict_chainS *
6567 pa_segment_to_space (seg)
6568 asection *seg;
6569 {
6570 space_dict_chainS *spaceCh;
6571
6572 for (spaceCh = space_dict_root; spaceCh; spaceCh = spaceCh->sd_next)
6573 {
6574 if (spaceCh->sd_seg == seg)
6575 {
6576 return spaceCh;
6577 }
6578 }
6579
6580 return NULL;
6581 }
6582
6583 subspace_dict_chainS *
6584 is_defined_subspace (name, subseg)
6585 char *name;
6586 subsegT subseg;
6587 {
6588 space_dict_chainS *spaceCh;
6589 subspace_dict_chainS *subspCh;
6590
6591 for (spaceCh = space_dict_root; spaceCh; spaceCh = spaceCh->sd_next)
6592 {
6593 for (subspCh = spaceCh->sd_subspaces; subspCh; subspCh = subspCh->ssd_next)
6594 {
6595 /*
6596 if ( strcmp(SUBSPACE_NAME(subspCh),name) == 0 &&
6597 subspCh->ssd_subseg == subseg ) {
6598 */
6599 if (strcmp (SUBSPACE_NAME (subspCh), name) == 0)
6600 {
6601 return subspCh;
6602 }
6603 }
6604 }
6605 return NULL;
6606 }
6607
6608 subspace_dict_chainS *
6609 pa_subsegment_to_subspace (seg, subseg)
6610 asection *seg;
6611 subsegT subseg;
6612 {
6613 space_dict_chainS *spaceCh;
6614 subspace_dict_chainS *subspCh;
6615
6616 for (spaceCh = space_dict_root; spaceCh; spaceCh = spaceCh->sd_next)
6617 {
6618 if (spaceCh->sd_seg == seg)
6619 {
6620 for (subspCh = spaceCh->sd_subspaces; subspCh; subspCh = subspCh->ssd_next)
6621 {
6622 if (subspCh->ssd_subseg == (int) subseg)
6623 {
6624 return subspCh;
6625 }
6626 }
6627 }
6628 }
6629
6630 return NULL;
6631 }
6632
6633 space_dict_chainS *
6634 pa_find_space_by_number (number)
6635 int number;
6636 {
6637 space_dict_chainS *spaceCh;
6638
6639 for (spaceCh = space_dict_root; spaceCh; spaceCh = spaceCh->sd_next)
6640 {
6641 if (SPACE_SPNUM (spaceCh) == number)
6642 {
6643 return spaceCh;
6644 }
6645 }
6646
6647 return NULL;
6648 }
6649
6650 unsigned int
6651 pa_subspace_start (space, quadrant)
6652 space_dict_chainS *space;
6653 int quadrant;
6654 {
6655 if ((strcasecmp (SPACE_NAME (space), "$PRIVATE$") == 0) &&
6656 quadrant == 1)
6657 {
6658 return 0x40000000;
6659 }
6660 else if (space->sd_seg == data_section && quadrant == 1)
6661 { /* in case name is */
6662 /* already converted */
6663 /* to a space dict- */
6664 /* ionary index */
6665 return 0x40000000;
6666 }
6667 else
6668 return 0;
6669 }
6670
6671 int
6672 pa_next_subseg (space)
6673 space_dict_chainS *space;
6674 {
6675
6676 space->sd_last_subseg++;
6677 return space->sd_last_subseg;
6678 }
6679
6680 int
6681 is_last_defined_subspace (ssd)
6682 subspace_dict_chainS *ssd;
6683 {
6684
6685 for (; ssd; ssd = ssd->ssd_next)
6686 {
6687 if (ssd->ssd_defined)
6688 return FALSE;
6689 }
6690
6691 return TRUE;
6692 }
6693
6694 symbolS *
6695 pa_get_start_symbol (seg, subseg)
6696 asection *seg;
6697 subsegT subseg;
6698 {
6699 symbolS *start_symbol;
6700 subspace_dict_chainS *ssd;
6701
6702 start_symbol = NULL;
6703
6704 /* each time a new space is created, build a symbol called LS$START_seg_subseg$ */
6705 /* where <space-name> is the name of the space */
6706 /* the start symbol will be SS_LOCAL and ST_CODE */
6707
6708 if (seg == bfd_make_section_old_way (stdoutput, ".text") ||
6709 seg == bfd_make_section_old_way (stdoutput, ".data") ||
6710 seg == bfd_make_section_old_way (stdoutput, GDB_DEBUG_SPACE_NAME))
6711 {
6712 ssd = pa_subsegment_to_subspace (seg, subseg);
6713 if (ssd)
6714 {
6715 start_symbol = ssd->ssd_start_sym;
6716 }
6717 else
6718 as_fatal ("Internal error: missing subspace for (seg,subseg)=('%s',%d)",
6719 seg->name, subseg);
6720 }
6721 else
6722 as_fatal ("Internal error: attempt to find start symbol for unloadable segment: '%s'",
6723 seg->name);
6724
6725 return start_symbol;
6726 }
6727
6728 /*
6729 Function to define a symbol whose address is the beginning of a subspace.
6730 This function assumes the symbol is to be defined for the current subspace.
6731 */
6732
6733 symbolS *
6734 pa_set_start_symbol (seg, subseg)
6735 asection *seg;
6736 subsegT subseg;
6737 {
6738 symbolS *start_symbol;
6739 subspace_dict_chainS *ssd;
6740 char *symbol_name;
6741
6742 symbol_name = (char *) xmalloc (strlen ("LS$START__000000$") + strlen (seg->name) + 1);
6743
6744 sprintf (symbol_name, "LS$START_%s_%03d$", seg->name, subseg);
6745
6746 start_symbol
6747 = symbol_new (symbol_name, seg, 0, frag_now); /* XXX: not sure if value s.b. 0 or frag s.b. NULL */
6748
6749 start_symbol->bsym->flags = BSF_LOCAL; /* XXX: isn't there a macro defined for this? */
6750
6751 /* each time a new space is created, build a symbol called LS$START_seg_subseg$ */
6752 /* where <space-name> is the name of the space */
6753 /* the start symbol will be SS_LOCAL and ST_CODE */
6754 /* This function assumes that (seg,subseg) is a new subsegment(subspace) */
6755
6756 if (seg == bfd_make_section_old_way (stdoutput, ".text") ||
6757 seg == bfd_make_section_old_way (stdoutput, ".data") ||
6758 seg == bfd_make_section_old_way (stdoutput, GDB_DEBUG_SPACE_NAME))
6759 {
6760 ssd = pa_subsegment_to_subspace (seg, subseg);
6761 if (ssd)
6762 {
6763 ssd->ssd_start_sym = start_symbol;
6764 }
6765 else
6766 as_fatal ("Internal error: missing subspace for (seg,subseg)=('%s',%d)",
6767 seg, subseg);
6768 }
6769 else
6770 as_fatal ("Internal error: attempt to define start symbol for unloadable segment: '%s'",
6771 seg->name);
6772
6773 return start_symbol;
6774 }
6775
6776 static unsigned int
6777 pa_stringer_aux (s)
6778 char *s;
6779 {
6780 unsigned int c = *s & CHAR_MASK;
6781 switch (c)
6782 {
6783 case '\"':
6784 c = NOT_A_CHAR;
6785 break;
6786 default:
6787 break;
6788 }
6789 return c;
6790 }
6791
6792 void
6793 pa_stringer (append_zero) /* Worker to do .ascii etc statements. */
6794 /* Checks end-of-line. */
6795 register int append_zero; /* 0: don't append '\0', else 1 */
6796 {
6797 char *s;
6798 unsigned int c;
6799 char num_buf[4];
6800 int i;
6801
6802 /* Preprocess the string to handle PA-specific escape sequences. */
6803 /* For example, \xDD where DD is a hexidecimal number should be */
6804 /* changed to \OOO where OOO is an octal number. */
6805
6806 s = input_line_pointer + 1; /* skip the opening quote */
6807
6808 while (is_a_char (c = pa_stringer_aux (s++)))
6809 {
6810 if (c == '\\')
6811 {
6812 c = *s;
6813 switch (c)
6814 {
6815 case 'x':
6816 {
6817 unsigned int number;
6818 int num_digit;
6819 char dg;
6820 char *s_start = s;
6821
6822 s++; /* get past the 'x' */
6823 for (num_digit = 0, number = 0, dg = *s;
6824 num_digit < 2
6825 && (isdigit (dg) || (dg >= 'a' && dg <= 'f')
6826 || (dg >= 'A' && dg <= 'F'));
6827 num_digit++)
6828 {
6829 if (isdigit (dg))
6830 number = number * 16 + dg - '0';
6831 else if (dg >= 'a' && dg <= 'f')
6832 number = number * 16 + dg - 'a' + 10;
6833 else
6834 number = number * 16 + dg - 'A' + 10;
6835
6836 s++;
6837 dg = *s;
6838 }
6839 if (num_digit > 0)
6840 {
6841 switch (num_digit)
6842 {
6843 case 1:
6844 sprintf (num_buf, "%02o", number);
6845 break;
6846 case 2:
6847 sprintf (num_buf, "%03o", number);
6848 break;
6849 }
6850 for (i = 0; i <= num_digit; i++)
6851 s_start[i] = num_buf[i];
6852 }
6853 }
6854 break;
6855 }
6856 }
6857 }
6858 stringer (append_zero);
6859 pa_undefine_label ();
6860 }
6861
6862 void
6863 pa_version ()
6864 {
6865 #ifdef OBJ_ELF
6866 obj_elf_version ();
6867 #endif
6868 pa_undefine_label ();
6869 }
6870
6871 void
6872 pa_cons (nbytes)
6873 register unsigned int nbytes; /* 1=.byte, 2=.word, 4=.long */
6874 {
6875 cons (nbytes);
6876 pa_undefine_label ();
6877 }
6878
6879 void
6880 pa_data ()
6881 {
6882 s_data ();
6883 pa_undefine_label ();
6884 }
6885
6886 void
6887 pa_desc ()
6888 {
6889
6890 #ifdef OBJ_ELF
6891 obj_elf_desc ();
6892 #endif
6893 pa_undefine_label ();
6894 }
6895
6896 void
6897 pa_float_cons (float_type)
6898 register int float_type; /* 'f':.ffloat ... 'F':.float ... */
6899 {
6900 float_cons (float_type);
6901 pa_undefine_label ();
6902 }
6903
6904 void
6905 pa_fill ()
6906 {
6907 s_fill ();
6908 pa_undefine_label ();
6909 }
6910
6911 void
6912 pa_lcomm (needs_align)
6913 /* 1 if this was a ".bss" directive, which may require a 3rd argument
6914 (alignment); 0 if it was an ".lcomm" (2 args only) */
6915 int needs_align;
6916 {
6917 s_lcomm (needs_align);
6918 pa_undefine_label ();
6919 }
6920
6921 void
6922 pa_lsym ()
6923 {
6924 s_lsym ();
6925 pa_undefine_label ();
6926 }
6927
6928 void
6929 pa_big_cons (nbytes)
6930 register int nbytes;
6931 {
6932 big_cons (nbytes);
6933 pa_undefine_label ();
6934 }
6935
6936 void
6937 pa_text ()
6938 {
6939 s_text ();
6940 pa_undefine_label ();
6941 }
This page took 0.238015 seconds and 4 git commands to generate.