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