* mips-opc.c: Correct lwu opcode value (book had it wrong).
[deliverable/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},
236 {"octa", pa_big_cons, 16},
237 {"OCTA", pa_big_cons, 16},
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},
248 {"quad", pa_big_cons, 8},
249 {"QUAD", pa_big_cons, 8},
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]);
735 if (retval != NULL && *retval != '\0')
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;
4294 s_text ();
4295 return;
4296 }
4297 if (strncmp (input_line_pointer, "\"data\"", 6) == 0)
4298 {
4299 input_line_pointer += 6;
4300 s_data ();
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 ();
4320#ifdef OBJ_SOM
4321 subseg_new (SEG_DATA, (subsegT) temp);
4322#else
4323 subseg_new (".data", (subsegT) temp);
4324#endif
4325 demand_empty_rest_of_line ();
4326}
4327
4328void
4329s_data1 ()
4330{
4331#ifdef OBJ_SOM
4332 subseg_new (SEG_DATA, 1);
4333#else
4334 subseg_new (".data", 1);
4335#endif
4336 demand_empty_rest_of_line ();
4337 return;
4338}
4339
4340void
4341s_proc ()
4342{
4343 extern char is_end_of_line[];
4344
4345 while (!is_end_of_line[*input_line_pointer])
4346 {
4347 ++input_line_pointer;
4348 }
4349 ++input_line_pointer;
4350 return;
4351}
4352
4353void
4354pa_block (z)
4355 int z;
4356{
4357 register char *p;
4358 register long int temp_fill;
4359 register long int temp_size;
4360 register int i;
4361
4362 temp_size = get_absolute_expression ();
4363
4364 if (z)
4365 { /* fill with zeroes even if not requested to do so. */
4366 temp_fill = 0; /* HP assembler does this too. */
4367 }
4368 else
4369 {
4370 temp_fill = 0;
4371 }
4372
4373 if (temp_size <= 0)
4374 {
4375 as_bad ("size < 0, .block ignored");
4376 temp_size = 0;
4377 }
4378 p = frag_var (rs_fill,
4379 (int) temp_size,
4380 (int) temp_size, (relax_substateT) 0, (symbolS *) 0, 1, (char *) 0);
4381 bzero (p, (int) temp_size);
4382
4383 /* convert 2 bytes at a time */
4384
4385 for (i = 0; i < temp_size; i += 2)
4386 {
4387 md_number_to_chars (p + i,
4388 temp_fill,
4389 (int) ((temp_size - i) > 2 ? 2 : (temp_size - i)));
4390 }
4391
4392 pa_undefine_label ();
4393 demand_empty_rest_of_line ();
4394 return;
4395}
4396
4397void
4398pa_call ()
4399{
4400
4401 pa_call_args (&last_call_desc);
4402 demand_empty_rest_of_line ();
4403 return;
4404}
4405
4406void
4407pa_call_args (call_desc)
4408 register call_descS *call_desc;
4409{
4410 register char *name;
4411 register char c;
4412 register char *p;
4413 register int temp;
4414 register unsigned int arg_reloc;
4415
4416 while (!is_end_of_statement ())
4417 {
4418 name = input_line_pointer;
4419 c = get_symbol_end ();
4420 if ((strncasecmp (name, "argw", 4) == 0))
4421 {
4422 temp = atoi (name + 4);
4423 p = input_line_pointer;
4424 *p = c;
4425 input_line_pointer++;
4426 name = input_line_pointer;
4427 c = get_symbol_end ();
4428 arg_reloc = pa_build_arg_reloc (name);
4429 call_desc->arg_reloc |= pa_align_arg_reloc (temp, arg_reloc);
4430 }
4431 else if ((strncasecmp (name, "rtnval", 6) == 0))
4432 {
4433 p = input_line_pointer;
4434 *p = c;
4435 input_line_pointer++;
4436 name = input_line_pointer;
4437 c = get_symbol_end ();
4438 arg_reloc = pa_build_arg_reloc (name);
4439 call_desc->arg_reloc |= (arg_reloc & 0x3);
4440 }
4441 else
4442 {
4443 as_bad ("Unrecognized .CALL argument: %s", name);
4444 }
4445 p = input_line_pointer;
4446 *p = c;
4447 if (!is_end_of_statement ())
4448 input_line_pointer++;
4449 }
4450}
4451
4452static int
4453is_same_frag (frag1P, frag2P)
4454 fragS *frag1P;
4455 fragS *frag2P;
4456{
4457
4458 if (frag1P == NULL)
4459 return (FALSE);
4460 else if (frag2P == NULL)
4461 return (FALSE);
4462 else if (frag1P == frag2P)
4463 return (TRUE);
4464 else if (frag2P->fr_type == rs_fill && frag2P->fr_fix == 0)
892a3ff1 4465 return (is_same_frag (frag1P, frag2P->fr_next));
025b0302
ME
4466 else
4467 return (FALSE);
4468}
4469
4470#ifdef OBJ_ELF
4471static void
4472pa_build_unwind_subspace (call_info)
4473 call_infoS *call_info;
4474{
4475 char *unwindP;
4476 asection *seg;
4477 asection *save_seg;
4478 subsegT subseg, save_subseg;
4479 int i;
4480 char c;
4481 char *p;
4482
4483 subseg = SUBSEG_UNWIND;
4484 seg = bfd_get_section_by_name (stdoutput, UNWIND_SECTION_NAME);
4485 if (seg == ASEC_NULL)
4486 {
4487 seg = bfd_make_section_old_way (stdoutput, UNWIND_SECTION_NAME);
4488 }
5cf4cd1b
KR
4489 bfd_set_section_flags (stdoutput, seg,
4490 (SEC_READONLY | SEC_HAS_CONTENTS
4491 | SEC_LOAD | SEC_RELOC));
025b0302
ME
4492
4493 /* callinfo.frame is in bytes and unwind_desc is in 8 byte units */
4494 call_info->ci_unwind.descriptor.frame_size = call_info->frame / 8;
4495
4496 /* Now, dump the unwind descriptor to the $UNWIND$ subspace. This
4497 creates a couple of relocations */
4498
4499 save_seg = now_seg;
4500 save_subseg = now_subseg;
4501 subseg_new ((char *) seg->name, subseg);
4502 unwindP = (char *) &call_info->ci_unwind;
4503
4504 p = frag_more (4);
4505 call_info->start_offset_frag = frag_now;
4506 call_info->start_frag_where = p - frag_now->fr_literal;
4507
4508 /* relocation info. for start offset of the function */
4509
4510 fix_new_hppa (frag_now, p - frag_now->fr_literal, 4,
5cf4cd1b
KR
4511 call_info->start_symbol, (offsetT) 0,
4512 (expressionS *) NULL, 0, R_HPPA_UNWIND, e_fsel, 32, 0,
4513 (char *) 0);
025b0302
ME
4514
4515 /** we need to search for the first relocation involving the start_symbol of **/
4516 /** this call_info descriptor **/
4517
4518 {
4519 fixS *fixP;
4520
4521 call_info->start_fix = seg_info (now_seg)->fix_root; /* the default */
4522 for (fixP = call_info->start_fix; fixP; fixP = fixP->fx_next)
4523 {
4524 if (fixP->fx_addsy == call_info->start_symbol
4525 || fixP->fx_subsy == call_info->start_symbol)
4526 {
4527 call_info->start_fix = fixP;
4528 break;
4529 }
4530 }
4531 }
4532
4533 p = frag_more (4);
4534 call_info->end_offset_frag = frag_now;
4535 call_info->end_frag_where = p - frag_now->fr_literal;
4536
4537 /* relocation info. for end offset of the function */
4538
4539 fix_new_hppa (frag_now, p - frag_now->fr_literal, 4,
5cf4cd1b
KR
4540 call_info->end_symbol, (offsetT) 0,
4541 (expressionS *) NULL, 0, R_HPPA_UNWIND, e_fsel, 32, 0,
4542 (char *) 0);
025b0302
ME
4543
4544 /** we need to search for the first relocation involving the start_symbol of **/
4545 /** this call_info descriptor **/
4546
4547 {
4548 fixS *fixP;
4549
4550 call_info->end_fix = seg_info (now_seg)->fix_root; /* the default */
4551 for (fixP = call_info->end_fix; fixP; fixP = fixP->fx_next)
4552 {
4553 if (fixP->fx_addsy == call_info->end_symbol
4554 || fixP->fx_subsy == call_info->end_symbol)
4555 {
4556 call_info->end_fix = fixP;
4557 break;
4558 }
4559 }
4560 }
4561
4562 for (i = 8; i < sizeof (unwind_tableS); i++)
4563 {
4564 c = *(unwindP + i);
4565 {
4566 FRAG_APPEND_1_CHAR (c);
4567 }
4568 }
4569
4570 subseg_new ((char *) save_seg->name, save_subseg);
4571}
4572
4573#else
4574#ifdef OBJ_SOM
4575static void
4576pa_build_unwind_subspace (call_info)
4577 call_infoS *call_info;
4578{
4579 space_dict_chainS *spaceP;
4580 subspace_dict_chainS *subspaceP;
4581 char *unwindP;
4582 char defined, loadable, code_only, common, dup_common, is_zero, sort;
4583 int access, space_index, alignment, quadrant;
4584 segT seg, save_seg;
4585 subsegT subseg, save_subseg;
4586 int i;
4587 char c;
4588 char *p;
4589
4590 defined = 1;
4591 loadable = 1;
4592 code_only = 0;
4593 common = 0;
4594 dup_common = 0;
4595 is_zero = 0;
4596 sort = 0x40;
4597 access = 0x2c;
4598 space_index = 0;
4599 alignment = 8;
4600 quadrant = 0;
4601 subseg = SUBSEG_UNWIND;
4602 seg = SEG_TEXT;
4603
4604 spaceP = pa_segment_to_space (seg);
4605
4606 if ((subspaceP = is_defined_subspace ("$UNWIND$", SUBSEG_UNWIND)))
4607 {
4608 update_subspace ("$UNWIND$", defined, loadable, code_only, common, dup_common,
4609 sort, is_zero, access, space_index, alignment, quadrant,
4610 SUBSEG_UNWIND);
4611 }
4612 else
4613 {
4614 subspaceP = create_new_subspace (spaceP, "$UNWIND$", defined, loadable, code_only,
4615 common, dup_common, is_zero, sort, access,
4616 space_index, alignment, quadrant, seg);
4617 }
4618
4619
4620 /* callinfo.frame is in bytes and unwind_desc is in 8 byte units */
4621 call_info->ci_unwind.descriptor.frame_size = call_info->frame / 8;
4622
4623 /* Now, dump the unwind descriptor to the $UNWIND$ subspace. This
4624 creates a couple of relocations */
4625
4626 save_seg = now_seg;
4627 save_subseg = now_subseg;
4628 subseg_new (seg, subseg);
4629 unwindP = (char *) &call_info->ci_unwind;
4630
4631 p = frag_more (4);
4632 call_info->start_offset_frag = frag_now;
4633 call_info->start_frag_where = p - frag_now->fr_literal;
4634
4635 /* relocation info. for start offset of the function */
4636
4637 fix_new (frag_now, p - frag_now->fr_literal, 4,
5cf4cd1b
KR
4638 call_info->start_symbol, (offsetT) 0,
4639 (expressionS *) NULL, 0, R_DATA_ONE_SYMBOL, e_fsel, 0, 0,
4640 (char *) 0);
025b0302
ME
4641
4642 /** we need to search for the first relocation involving the start_symbol of **/
4643 /** this call_info descriptor **/
4644
4645 {
4646 fixS *fixP;
4647
4648 call_info->start_fix = seg_info (now_seg)->fix_root; /* the default */
4649 for (fixP = call_info->start_fix; fixP; fixP = fixP->fx_next)
4650 {
4651 /*
4652 if ( ( fixP->fx_addsy == call_info->start_symbol ||
4653 fixP->fx_subsy == call_info->start_symbol )
4654 &&
4655 ( fixP->fx_frag == call_info->start_symbol->sy_frag ) ) {
4656 */
4657 if ((fixP->fx_addsy == call_info->start_symbol ||
4658 fixP->fx_subsy == call_info->start_symbol)
4659 &&
4660 (is_same_frag (fixP->fx_frag, call_info->start_symbol->sy_frag)))
4661 {
4662 call_info->start_fix = fixP;
4663 break;
4664 }
4665 }
4666 }
4667
4668 p = frag_more (4);
4669 call_info->end_offset_frag = frag_now;
4670 call_info->end_frag_where = p - frag_now->fr_literal;
4671
4672 /* relocation info. for end offset of the function */
4673
4674 fix_new (frag_now, p - frag_now->fr_literal, 4,
5cf4cd1b
KR
4675 call_info->start_symbol, (offsetT) 0,
4676 (expressionS *) NULL, 0, R_DATA_ONE_SYMBOL, e_fsel, 0, 0,
4677 (char *) 0);
025b0302
ME
4678
4679 /** we need to search for the first relocation involving the start_symbol of **/
4680 /** this call_info descriptor **/
4681
4682 {
4683 fixS *fixP;
4684
4685 call_info->end_fix = seg_info (now_seg)->fix_root; /* the default */
4686 for (fixP = call_info->end_fix; fixP; fixP = fixP->fx_next)
4687 {
4688 /*
4689 if ( ( fixP->fx_addsy == call_info->start_symbol ||
4690 fixP->fx_subsy == call_info->start_symbol )
4691 &&
4692 ( fixP->fx_frag == call_info->start_symbol->sy_frag ) ) {
4693 */
4694 if ((fixP->fx_addsy == call_info->start_symbol ||
4695 fixP->fx_subsy == call_info->start_symbol)
4696 &&
4697 (is_same_frag (fixP->fx_frag, call_info->start_symbol->sy_frag)))
4698 {
4699 call_info->end_fix = fixP;
4700 break;
4701 }
4702 }
4703 }
4704
4705 for (i = 8; i < sizeof (unwind_tableS); i++)
4706 {
4707 c = *(unwindP + i);
4708 {
4709 FRAG_APPEND_1_CHAR (c);
4710 }
4711 }
4712
4713 subseg_new (save_seg, save_subseg);
4714
4715}
4716
4717#endif
4718#endif
4719
4720void
4721pa_callinfo ()
4722{
4723 register char *name;
4724 register char c;
4725 register char *p;
4726 register int temp;
025b0302
ME
4727
4728 if (!within_procedure)
4729 as_bad (".callinfo is not within a procedure definition");
4730
4731 callinfo_found = TRUE;
4732
4733 while (!is_end_of_statement ())
4734 {
4735 name = input_line_pointer;
4736 c = get_symbol_end ();
4737 if ((strncasecmp (name, "frame", 5) == 0))
4738 {
4739 p = input_line_pointer;
4740 *p = c;
4741 input_line_pointer++;
4742 temp = get_absolute_expression ();
4743 if ((temp & 0x3) != 0)
4744 {
4745 as_bad ("FRAME parameter must be a multiple of 8: %d\n", temp);
4746 temp = 0;
4747 }
4748 last_call_info->frame = temp;
4749 }
4750 else if ((strncasecmp (name, "entry_gr", 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_gr = temp;
4757 }
4758 else if ((strncasecmp (name, "entry_fr", 8) == 0))
4759 {
4760 p = input_line_pointer;
4761 *p = c;
4762 input_line_pointer++;
4763 temp = get_absolute_expression ();
4764 last_call_info->ci_unwind.descriptor.entry_fr = temp;
4765 }
4766 else if ((strncasecmp (name, "entry_sr", 8) == 0))
4767 {
4768 p = input_line_pointer;
4769 *p = c;
4770 input_line_pointer++;
4771 temp = get_absolute_expression ();
4772 last_call_info->entry_sr = temp;
4773 }
4774 else if ((strncasecmp (name, "calls", 5) == 0) ||
4775 (strncasecmp (name, "caller", 6) == 0))
4776 {
4777 p = input_line_pointer;
4778 *p = c;
4779 last_call_info->makes_calls = 1;
4780 }
4781 else if ((strncasecmp (name, "no_calls", 8) == 0))
4782 {
4783 p = input_line_pointer;
4784 *p = c;
4785 last_call_info->makes_calls = 0;
4786 }
4787 else if ((strncasecmp (name, "save_rp", 7) == 0))
4788 {
4789 p = input_line_pointer;
4790 *p = c;
4791 last_call_info->ci_unwind.descriptor.save_rp = 1;
4792 }
4793 else if ((strncasecmp (name, "save_sp", 7) == 0))
4794 {
4795 p = input_line_pointer;
4796 *p = c;
4797 last_call_info->ci_unwind.descriptor.save_sp = 1;
4798 }
4799 else if ((strncasecmp (name, "no_unwind", 9) == 0))
4800 {
4801 p = input_line_pointer;
4802 *p = c;
4803 last_call_info->ci_unwind.descriptor.cannot_unwind = 1;
4804 }
4805 else if ((strncasecmp (name, "hpux_int", 7) == 0))
4806 {
4807 p = input_line_pointer;
4808 *p = c;
4809 last_call_info->hpux_int = 1;
4810 }
4811 else
4812 {
4813 as_bad ("Unrecognized .CALLINFO argument: %s", name);
4814 }
4815 if (!is_end_of_statement ())
4816 input_line_pointer++;
4817 }
4818
4819 demand_empty_rest_of_line ();
4820 return;
4821}
4822
4823void
4824pa_code ()
4825{
4826 space_dict_chainS *sdchain;
4827
4828 if ((sdchain = is_defined_space ("$TEXT$")) == NULL)
4829 {
4830 sdchain = create_new_space (pa_def_spaces[0].name, pa_def_spaces[0].spnum,
4831 pa_def_spaces[0].loadable, pa_def_spaces[0].defined,
4832 pa_def_spaces[0].private, pa_def_spaces[0].sort,
4833 1, pa_def_spaces[0].segment);
4834 }
4835
4836 SPACE_DEFINED (sdchain) = 1;
4837#ifdef OBJ_SOM
4838
4839 subseg_new (SEG_TEXT, SUBSEG_CODE);
4840#else
4841
4842 subseg_new (".text", SUBSEG_CODE);
4843#endif
4844
4845 demand_empty_rest_of_line ();
4846 return;
4847}
4848
4849/*
4850 * This is different than the standard GAS s_comm(). On HP9000/800 machines,
4851 * the .comm pseudo-op has the following symtax:
4852 *
4853 * <label> .comm <length>
4854 *
4855 * where <label> is optional and is a symbol whose address will be the start of
4856 * a block of memory <length> bytes long. <length> must be an absolute expressio
4857n.
4858 * <length> bytes will be allocated in the current space and subspace.
4859 *
4860 */
4861
4862void
4863pa_comm ()
4864{
892a3ff1 4865 register int size;
025b0302
ME
4866 register symbolS *symbolP;
4867 register label_symbolS *label_symbolP = pa_get_label ();
4868
4869 if (label_symbolP)
4870 symbolP = label_symbolP->lss_label;
4871 else
4872 symbolP = NULL;
4873
4874 SKIP_WHITESPACE ();
4875 if ((size = get_absolute_expression ()) < 0)
4876 {
4877 as_warn (".COMMon length (%d.) <0! Ignored.", size);
4878 ignore_rest_of_line ();
4879 return;
4880 }
4881
4882 if (symbolP)
4883 {
4884#ifdef OBJ_SOM
4885 if (symbolP->pa_sy_type == ST_STORAGE &&
4886 symbolP->pa_sy_scope == SS_UNSAT)
4887 {
4888 if (symbolP->pa_sy_value != size)
4889 {
4890 as_warn ("Length of .comm \"%s\" is already %d. Not changed to %d.",
4891 symbolP->pa_sy_name, symbolP->pa_sy_value, size);
4892 return;
4893 }
4894 }
4895 else
4896 {
4897 symbolP->pa_sy_value = size;
4898 symbolP->pa_sy_scope = SS_UNSAT;
4899 symbolP->pa_sy_type = ST_STORAGE;
4900 symbolP->sy_ref = sym_def;
4901 }
4902#endif
4903#ifdef OBJ_ELF
4904 if (S_IS_DEFINED (symbolP) && S_GET_SEGMENT (symbolP) == bss_section)
4905 {
4906 as_bad ("Ignoring attempt to re-define symbol");
4907 ignore_rest_of_line ();
4908 return;
4909 }
4910 if (S_GET_VALUE (symbolP))
4911 {
4912 if (S_GET_VALUE (symbolP) != size)
4913 {
4914 as_warn ("Length of .comm \"%s\" is already %d. Not changed to %d.",
4915 S_GET_NAME (symbolP), S_GET_VALUE (symbolP), size);
4916 return;
4917 }
4918 }
4919 else
4920 {
4921 S_SET_VALUE (symbolP, size);
4922 S_SET_SEGMENT (symbolP, bss_section);
4923 S_SET_EXTERNAL (symbolP);
4924 }
4925#endif
4926 }
4927
4928
4929 demand_empty_rest_of_line ();
4930}
4931
4932void
4933pa_copyright ()
4934{
4935 register char *name;
4936 register char c;
025b0302
ME
4937
4938 SKIP_WHITESPACE ();
4939 if (*input_line_pointer == '\"')
4940 {
4941 ++input_line_pointer; /* -> 1st char of string. */
4942 name = input_line_pointer;
4943 while ((c = next_char_of_string ()) >= 0)
4944 ;
4945 c = *input_line_pointer;
4946 *input_line_pointer = '\0';
4947 *(input_line_pointer - 1) = '\0';
4948 {
4949#ifdef OBJ_SOM
4950#define PREFIX "Copyright "
4951#define MIDFIX ". All rights reserved. No part of this program may be photocopied, reproduced, or transmitted without prior written consent of "
4952#define SUFFIX "."
4953
4954 struct aux_hdr_list *aux_hdr_entry;
4955 int len;
4956 char *company_name = name;
4957 char *date_part;
4958
5cf4cd1b 4959 date_part = (char *) strchr (name, ',');
025b0302
ME
4960 if (date_part)
4961 {
4962 *date_part = 0x00;
4963 date_part++;
4964 }
4965
4966 len =
4967 strlen (PREFIX) +
4968 strlen (MIDFIX) +
4969 strlen (SUFFIX) +
4970 2 * strlen (name);
4971
4972 if (date_part)
4973 {
4974 len += strlen (date_part) + strlen (",");
4975 }
4976
4977 aux_hdr_entry = (struct aux_hdr_list *) malloc (sizeof (struct aux_hdr_list));
4978 if (aux_hdr_root)
4979 {
4980 aux_hdr_entry->ahl_next = aux_hdr_root;
4981 aux_hdr_root = aux_hdr_entry;
4982 }
4983 else
4984 {
4985 aux_hdr_entry->ahl_next = NULL;
4986 aux_hdr_root = aux_hdr_entry;
4987 }
4988 aux_hdr_entry->type = COPYRIGHT_AUX_ID;
4989 aux_hdr_entry->contents.cpy.header_id.append = 1;
4990 aux_hdr_entry->contents.cpy.header_id.type = COPYRIGHT_AUX_ID;
4991 aux_hdr_entry->contents.cpy.header_id.length = len + sizeof (unsigned int);
4992 while (aux_hdr_entry->contents.usr_str.header_id.length % 4)
4993 aux_hdr_entry->contents.usr_str.header_id.length += 1;
4994
4995 aux_hdr_entry->contents.cpy.string_length = len;
4996 aux_hdr_entry->contents.cpy.copyright = (char *) (malloc (len + 1));
4997 strcpy (aux_hdr_entry->contents.cpy.copyright, PREFIX);
4998 strcat (aux_hdr_entry->contents.cpy.copyright, name);
4999 if (date_part)
5000 {
5001 strcat (aux_hdr_entry->contents.cpy.copyright, ",");
5002 strcat (aux_hdr_entry->contents.cpy.copyright, date_part);
5003 }
5004 strcat (aux_hdr_entry->contents.cpy.copyright, MIDFIX);
5005 strcat (aux_hdr_entry->contents.cpy.copyright, name);
5006 strcat (aux_hdr_entry->contents.cpy.copyright, SUFFIX);
5007 aux_hdr_entry->contents.cpy.copyright[len] = NULL;
5008#undef PREFIX
5009#undef MIDFIX
5010#undef SUFFIX
5011#endif /* OBJ_SOM */
5012 }
5013 *input_line_pointer = c;
5014 }
5015 else
5016 {
5017 as_bad ("Expected \"-ed string");
5018 }
5019 pa_undefine_label ();
5020 demand_empty_rest_of_line ();
5021}
5022
5023void
5024pa_end ()
5025{
5026
5027 demand_empty_rest_of_line ();
5028 return;
5029}
5030
5031void
5032pa_enter ()
5033{
5034
5035 as_bad (".ENTER encountered. gas doesn't generate entry code sequences.");
5036 pa_entry ();
5037 return;
5038}
5039
5040void
5041pa_entry ()
5042{
5043 char *where;
5044
5045 if (!within_procedure)
5046 as_bad ("Misplaced .entry. Ignored.");
5047 else
5048 {
5049 if (!callinfo_found)
5050 as_bad ("Missing .callinfo.");
5051
5052 last_call_info->start_frag = frag_now;
5053 }
5054 demand_empty_rest_of_line ();
5055 within_entry_exit = TRUE;
5056 where = frag_more (0);
5057#ifdef OBJ_SOM
5cf4cd1b
KR
5058 fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
5059 last_call_info->start_symbol, (offsetT) 0,
5060 (expressionS *) NULL, 0, R_ENTRY, e_fsel, 0, 0,
5061 (char *) &last_call_info->ci_unwind.descriptor);
025b0302
ME
5062#else
5063#ifdef OBJ_ELF
5064 /* XXX: no ENTRY relocation for PA ELF. What do we do instead? */
5065#else
5066 fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
5cf4cd1b
KR
5067 last_call_info->start_symbol, (offsetT) 0,
5068 (expressionS *) NULL, 0,
025b0302
ME
5069 R_HPPA_ENTRY, 0, 0, 0,
5070 (char *) &last_call_info->ci_unwind.descriptor);
5071#endif
5072#endif
5073 return;
5074}
5075
5076void
5077pa_equ (reg)
5078 int reg;
5079{
5080 register label_symbolS *label_symbolP = pa_get_label ();
5081 register symbolS *symbolP;
5082
5083 if (label_symbolP)
5084 {
5085 symbolP = label_symbolP->lss_label;
5086#ifdef OBJ_SOM
5087 symbolP->pa_sy_value = get_absolute_expression ();
5088 symbolP->pa_sy_type = ST_ABSOLUTE;
5089 symbolP->sy_ref = sym_unref;
5090 symbolP->sy_equ = 1;
5091#else
5092 S_SET_VALUE (symbolP, get_absolute_expression ());
5093 S_SET_SEGMENT (symbolP, &bfd_abs_section);
5094#endif
5095 }
5096 else
5097 {
5098 if (reg)
5099 as_bad (".REG must use a label");
5100 else
5101 as_bad (".EQU must use a label");
5102 }
5103
5104 pa_undefine_label ();
5105 demand_empty_rest_of_line ();
5106 return;
5107}
5108
5109void
5110process_exit ()
5111{
5112 char *where;
5113
5114 where = frag_more (0);
5115#ifdef OBJ_SOM
5cf4cd1b
KR
5116 fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
5117 last_call_info->start_symbol, (offsetT) 0,
5118 (expressionS *) NULL, 0, R_EXIT, e_fsel, 0, 0,
5119 (char *) NULL);
025b0302
ME
5120#endif
5121#ifdef OBJ_ELF
5122 /* XXX: no EXIT relocation for PA ELF. All we do is create a */
5123 /* temporary symbol marking the end of the function. */
5124 {
5125 char *name = (char *) xmalloc (strlen ("L\001end_") +
5126 strlen (S_GET_NAME (last_call_info->start_symbol)) + 1);
5127
5128 if (name)
5129 {
5130 symbolS *symbolP;
5131
5132 strcpy (name, "L\001end_");
5133 strcat (name, S_GET_NAME (last_call_info->start_symbol));
5134
5135 symbolP = symbol_find (name);
5136 if (symbolP)
5137 as_warn ("Symbol '%s' already defined.", name);
5138 else
5139 {
5140 /* symbol value should be the offset of the */
5141 /* last instruction of the function */
5142 symbolP = symbol_new (name,
5143 now_seg,
5144 (valueT) (obstack_next_free (&frags) - frag_now->fr_literal - 4),
5145 frag_now);
5146
5147 assert (symbolP);
5148
5cf4cd1b 5149 symbolP->bsym->flags = BSF_LOCAL;
025b0302
ME
5150 symbol_table_insert (symbolP);
5151 }
5152 if (symbolP)
5153 last_call_info->end_symbol = symbolP;
5154 else
5155 as_bad ("Symbol '%s' could not be created.", name);
5156
5157 }
5158 else
5159 as_bad ("No memory for symbol name.");
5160 }
5161#else
5162 fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
5cf4cd1b
KR
5163 last_call_info->start_symbol, (offsetT) 0,
5164 (expressionS *) NULL, 0, R_HPPA_EXIT, 0, 0, 0,
5165 (char *) NULL);
025b0302
ME
5166#endif
5167 last_call_info->end_frag = frag_now;
5168
5169 pa_build_unwind_subspace (last_call_info);
5170
5171 exit_processing_complete = TRUE;
5172}
5173
5174void
5175pa_exit ()
5176{
5177
5178 if (!within_procedure)
5179 as_bad (".EXIT must appear within a procedure");
5180 else
5181 {
5182 if (!callinfo_found)
5183 as_bad ("Missing .callinfo");
5184 else
5185 {
5186 if (!within_entry_exit)
5187 as_bad ("No .ENTRY for this .EXIT");
5188 else
5189 {
5190 within_entry_exit = FALSE;
5191 process_exit ();
5192 }
5193 }
5194 }
5195 demand_empty_rest_of_line ();
5196 return;
5197}
5198
5cf4cd1b
KR
5199#ifdef OBJ_ELF
5200void
5201 pa_build_symextn_section()
5202{
5203 segT seg;
5204 asection *save_seg = now_seg;
5205 subsegT subseg = (subsegT)0;
5206 subsegT save_subseg = now_subseg;
5207
5208 seg = subseg_new(".hppa_symextn", subseg);
5209 bfd_set_section_flags (stdoutput,
5210 seg,
5211 SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC | SEC_LOAD);
5212
5213 subseg_new(save_seg->name, save_subseg);
5214
5215}
5216#endif
5217
025b0302
ME
5218void
5219pa_export ()
5220{
5221 register char *name;
5222 register char c;
5223 register char *p;
025b0302
ME
5224 register symbolS *symbolP;
5225
5226 name = input_line_pointer;
5227 c = get_symbol_end ();
5228 /* just after name is now '\0' */
5229
5230 if ((symbolP = symbol_find_or_make (name)) == NULL)
5231 {
5232 as_bad ("Cannot define export symbol: %s\n", name);
5233 p = input_line_pointer;
5234 *p = c;
5235 input_line_pointer++;
5236 }
5237 else
5238 {
5239#ifdef OBJ_SOM
5240 symbolP->pa_sy_dict.symbol_scope = SS_UNIVERSAL;
5241 /* determination of the symbol_type field will have to wait until
5242 we know the subspace index (within the object file) of the subspace
5243 containing this symbol */
5244#else
5245 /* S_SET_SEGMENT(symbolP,&bfd_und_section); */
5246 S_SET_EXTERNAL (symbolP);
5247 /* symbolP->sy_frag = frag_now; */
5248#endif
5249
5250 p = input_line_pointer;
5251 *p = c;
5252 if (!is_end_of_statement ())
5253 {
5254 input_line_pointer++;
5255 pa_export_args (symbolP);
5cf4cd1b
KR
5256#ifdef OBJ_ELF
5257 pa_build_symextn_section();
5258#endif
025b0302
ME
5259 }
5260 }
5261
5262 demand_empty_rest_of_line ();
5263 return;
5264}
5265
5266void
5267pa_export_args (symbolP)
5268 register symbolS *symbolP;
5269{
5270 register char *name;
5271 register char c;
5272 register char *p;
5273 register int temp;
5274 register unsigned int arg_reloc;
5275#ifdef OBJ_ELF
5cf4cd1b 5276 elf32_symbol_type *esymbolP = (elf32_symbol_type *) (symbolP->bsym);
025b0302
ME
5277#endif
5278
5279 if (strncasecmp (input_line_pointer, "absolute", 8) == 0)
5280 {
5281 input_line_pointer += 8;
5282#ifdef OBJ_SOM
5283 symbolP->pa_sy_dict.symbol_type = ST_ABSOLUTE;
5284#else
5285 S_SET_SEGMENT (symbolP, &bfd_abs_section);
5286#endif
5287 }
5288 else if (strncasecmp (input_line_pointer, "code", 4) == 0)
5289 {
5290 input_line_pointer += 4;
5291#ifdef OBJ_SOM
5292 symbolP->pa_sy_dict.symbol_type = ST_CODE;
5293#else
5294 /* S_SET_SEGMENT(symbolP,text_section); */
5295#endif
5296 }
5297 else if (strncasecmp (input_line_pointer, "data", 4) == 0)
5298 {
5299 input_line_pointer += 4;
5300#ifdef OBJ_SOM
5301 symbolP->pa_sy_dict.symbol_type = ST_DATA;
5302#else
5303 /* S_SET_SEGMENT(symbolP,data_section); */
5304#endif
5305 }
5306 else if ((strncasecmp (input_line_pointer, "entry", 5) == 0))
5307 {
5308 input_line_pointer += 5;
5309#ifdef OBJ_SOM
5310 symbolP->pa_sy_dict.symbol_type = ST_ENTRY;
5311#else
5312 symbolP->bsym->flags |= BSF_FUNCTION;
5313#endif
5314 }
5315 else if (strncasecmp (input_line_pointer, "millicode", 9) == 0)
5316 {
5317 input_line_pointer += 9;
5318#ifdef OBJ_SOM
5319 symbolP->pa_sy_dict.symbol_type = ST_MILLICODE;
5320#endif
5321 }
5322 else if (strncasecmp (input_line_pointer, "plabel", 6) == 0)
5323 {
5324 input_line_pointer += 6;
5325#ifdef OBJ_SOM
5326 symbolP->pa_sy_dict.symbol_type = ST_PLABEL;
5327#endif
5328 }
5329 else if (strncasecmp (input_line_pointer, "pri_prog", 8) == 0)
5330 {
5331 input_line_pointer += 8;
5332#ifdef OBJ_SOM
5333 symbolP->pa_sy_dict.symbol_type = ST_PRI_PROG;
5334#endif
5335 }
5336 else if (strncasecmp (input_line_pointer, "sec_prog", 8) == 0)
5337 {
5338 input_line_pointer += 8;
5339#ifdef OBJ_SOM
5340 symbolP->pa_sy_dict.symbol_type = ST_SEC_PROG;
5341#endif
5342 }
5343
5344 while (!is_end_of_statement ())
5345 {
5346 if (*input_line_pointer == ',')
5347 input_line_pointer++;
5348 name = input_line_pointer;
5349 c = get_symbol_end ();
5350 if ((strncasecmp (name, "argw", 4) == 0))
5351 {
5352 p = input_line_pointer;
5353 *p = c;
5354 input_line_pointer++;
5355 temp = atoi (name + 4);
5356 name = input_line_pointer;
5357 c = get_symbol_end ();
5358 arg_reloc = pa_align_arg_reloc (temp, pa_build_arg_reloc (name));
5359#ifdef OBJ_SOM
5360 symbolP->pa_sy_dict.arg_reloc |= arg_reloc;
5361#else
5362 esymbolP->tc_data.hppa_arg_reloc |= arg_reloc;
5363#endif
5364 *input_line_pointer = c;
5365 }
5366 else if ((strncasecmp (name, "rtnval", 6)) == 0)
5367 {
5368 p = input_line_pointer;
5369 *p = c;
5370 input_line_pointer++;
5371 name = input_line_pointer;
5372 c = get_symbol_end ();
5373 arg_reloc = pa_build_arg_reloc (name);
5374#ifdef OBJ_SOM
5375 symbolP->pa_sy_dict.arg_reloc |= arg_reloc;
5376#else
5377 esymbolP->tc_data.hppa_arg_reloc |= arg_reloc;
5378#endif
5379 *input_line_pointer = c;
5380 }
5381 else if ((strncasecmp (name, "priv_lev", 8)) == 0)
5382 {
5383 p = input_line_pointer;
5384 *p = c;
5385 input_line_pointer++;
5386 /*** temp = get_absolute_expression (); ***/
5387 temp = atoi (input_line_pointer);
5388 c = get_symbol_end ();
5389 *input_line_pointer = c;
5390#ifdef OBJ_SOM
5391 symbolP->sy_priv_lev = temp & 3; /* this is stored in symbol_value later */
5392#endif
5393 }
5394 else
5395 {
5396 as_bad ("Undefined .EXPORT/.IMPORT argument (ignored): %s", name);
5397 p = input_line_pointer;
5398 *p = c;
5399 }
5400 if (!is_end_of_statement ())
5401 input_line_pointer++;
5402 }
5403}
5404
5405void
5406pa_import ()
5407{
5408 register char *name;
5409 register char c;
5410 register char *p;
5411 register symbolS *symbolP;
025b0302
ME
5412
5413 name = input_line_pointer;
5414 c = get_symbol_end ();
5415 /* just after name is now '\0' */
5416
5417 symbolP = symbol_find_or_make (name);
5418#if defined(OBJ_ELF)
5419 /* symbolP->bsym->flags |= BSF_IMPORT; *//* XXX BSF_IMPORT is obsolete */
5420#else
5421 /* Check to see if this symbol has already been exported (this means its */
5422 /* defined locally and the import statement is redundant). */
5423 /* If it has not been exported, go ahead and mark this symbol as SS_UNSAT */
5424 /* (an unsatisfied external symbol) */
5425
5426 /* But, if the symbol has already been referenced (sy_ref == TRUE),
5427 leave it alone. */
5428
5429 if (!symbolP->sy_ref)
5430 {
5431 if (symbolP->pa_sy_dict.symbol_scope != SS_UNIVERSAL)
5432 {
5433 symbolP->pa_sy_dict.symbol_scope = SS_UNSAT;
5434 symbolP->sy_ref = FALSE;
5435 }
5436 }
5437#endif
5438
5439 p = input_line_pointer;
5440 *p = c;
5441
5442 if (!is_end_of_statement ())
5443 {
5444 input_line_pointer++;
5445
5446 pa_export_args (symbolP);
5447#ifdef OBJ_ELF
5448 /* In ELF, since this is an import, leave the section undefined. */
5449 /* S_SET_SEGMENT(symbolP,&bfd_und_section); */
5450#endif
5451 }
5452 else
5453 {
5454#ifdef OBJ_SOM
5455 /* no further arguments, assign a default type according
5456 to the current subspace (CODE or DATA) */
5457 switch (now_seg)
5458 {
5459 case SEG_TEXT:
5460 symbolP->pa_sy_dict.symbol_type = ST_CODE;
5461 break;
5462 case SEG_ABSOLUTE:
5463 symbolP->pa_sy_dict.symbol_type = ST_ABSOLUTE;
5464 break;
5465 default:
5466 symbolP->pa_sy_dict.symbol_type = ST_DATA;
5467 }
5468#else
5469 /* In ELF, if the section is undefined, then the symbol is undefined */
5470 /* Since this is an import, leave the section undefined. */
5471 S_SET_SEGMENT (symbolP, &bfd_und_section);
5472#endif
5473 }
5474
5475
5476 demand_empty_rest_of_line ();
5477 return;
5478}
5479
5480void
5481pa_label ()
5482{
5483 register char *name;
5484 register char c;
5485 register char *p;
5486
5487 name = input_line_pointer;
5488 c = get_symbol_end ();
5489 /* just after name is now '\0' */
5490
5491 if (strlen (name) > 0)
5492 {
5493 colon (name);
5494 p = input_line_pointer;
5495 *p = c;
5496 }
5497 else
5498 {
5499 as_warn ("Missing label name on .LABEL");
5500 }
5501
5502 if (!is_end_of_statement ())
5503 {
5504 as_warn ("extra .LABEL arguments ignored.");
5505 ignore_rest_of_line ();
5506 }
5507 demand_empty_rest_of_line ();
5508 return;
5509}
5510
5511void
5512pa_leave ()
5513{
5514
5515 as_bad (".LEAVE encountered. gas doesn't generate exit code sequences.");
5516 pa_exit ();
5517 return;
5518}
5519
5520void
5521pa_origin ()
5522{
5cf4cd1b
KR
5523 s_org (); /* ORG actually allows another argument
5524 (the fill value) but maybe this is OK? */
025b0302
ME
5525 pa_undefine_label ();
5526 return;
5527}
5528
5cf4cd1b
KR
5529
5530void
5531pa_param ()
5532{
5533 char *name;
5534 char c;
5535 char *p;
5cf4cd1b
KR
5536 symbolS *symbolP;
5537
5538 name = input_line_pointer;
5539 c = get_symbol_end ();
5540 /* just after name is now '\0' */
5541
5542 if ((symbolP = symbol_find_or_make (name)) == NULL)
5543 {
5544 as_bad ("Cannot define static symbol: %s\n", name);
5545 p = input_line_pointer;
5546 *p = c;
5547 input_line_pointer++;
5548 }
5549 else
5550 {
5551#ifdef OBJ_SOM
5552 symbolP->pa_sy_dict.symbol_scope = SS_LOCAL;
5553 /* determination of the symbol_type field will have to wait until
5554 we know the subspace index (within the object file) of the subspace
5555 containing this symbol */
5556#else
5557 /* S_SET_SEGMENT(symbolP,&bfd_und_section); */
5558 S_CLEAR_EXTERNAL (symbolP);
5559 /* symbolP->sy_frag = frag_now; */
5560#endif
5561
5562 p = input_line_pointer;
5563 *p = c;
5564 if (!is_end_of_statement ())
5565 {
5566 input_line_pointer++;
5567 pa_export_args (symbolP);
5568 }
5569 }
5570
5571 demand_empty_rest_of_line ();
5572 return;
5573}
5574
025b0302
ME
5575void
5576pa_proc ()
5577{
5578 call_infoS *call_info;
5579
5580 if (within_procedure)
5581 as_fatal ("Nested procedures");
5582
5583 callinfo_found = FALSE;
5584 within_procedure = TRUE;
5585 exit_processing_complete = FALSE;
5586
5587 /* create another call_info structure */
5588
5589 call_info = (call_infoS *) xmalloc (sizeof (call_infoS));
5590
5591 if (!call_info)
5592 as_fatal ("Cannot allocate unwind descriptor\n");
5593
5594 bzero (call_info, sizeof (call_infoS));
5595
5596 call_info->ci_next = NULL;
5597
5598 if (call_info_root == NULL)
5599 {
5600 call_info_root = call_info;
5601 last_call_info = call_info;
5602 }
5603 else
5604 {
5605 last_call_info->ci_next = call_info;
5606 last_call_info = call_info;
5607 }
5608
5609 /* set up defaults on call_info structure */
5610
5611 call_info->ci_unwind.descriptor.cannot_unwind = 0;
5612 call_info->ci_unwind.descriptor.region_desc = 1;
5613 call_info->entry_sr = ~0;
5614 call_info->makes_calls = 1;
5615 call_info->hpux_int = 0;
5616
5617 /* If we got a .PROC pseudo-op, we know that the function is defined
5618 locally. Make sure it gets into the symbol table */
5619 {
5620 label_symbolS *label_symbolP = pa_get_label ();
5621
5622 if (label_symbolP)
5623 {
5624 if (label_symbolP->lss_label)
5625 {
5626#ifdef OBJ_SOM
5627 label_symbolP->lss_label->sy_ref |= sym_def;
5628#endif
5629 last_call_info->start_symbol = label_symbolP->lss_label;
5630 label_symbolP->lss_label->bsym->flags |= BSF_FUNCTION;
5631 }
5632 else
5633 as_bad ("Missing function name for .PROC (corrupted label)");
5634 }
5635 else
5636 as_bad ("Missing function name for .PROC");
5637 }
5638
5639 demand_empty_rest_of_line ();
5640 return;
5641}
5642
5643void
5644pa_procend ()
5645{
5646
5647 if (!within_procedure)
5648 as_bad ("misplaced .procend");
5649
5650 if (!callinfo_found)
5651 as_bad ("Missing .callinfo for this procedure");
5652
5653 if (within_entry_exit)
5654 as_bad ("Missing .EXIT for a .ENTRY");
5655
5656 if (!exit_processing_complete)
5657 process_exit ();
5658
5659 within_procedure = FALSE;
5660 demand_empty_rest_of_line ();
5661 return;
5662}
5663
5664space_dict_chainS *
5665pa_parse_space_stmt (space_name, create_flag)
5666 char *space_name;
5667 int create_flag;
5668{
5669 register char *name;
5670 register char c;
5671 register char *p;
5672 register int temp;
5673
5674 char *ptemp;
5675 int spnum;
5676 char loadable;
5677 char defined;
5678 char private;
5679 char sort;
5680#ifdef OBJ_SOM
5681 segT seg;
5682#else
5683 asection *seg;
5684#endif
5685 space_dict_chainS *space;
5686
5687 /* load default values */
5688 spnum = 0;
5689 loadable = TRUE;
5690 defined = TRUE;
5691 private = FALSE;
5692 if (strcasecmp (space_name, "$TEXT$") == 0)
5693 {
5694#ifdef OBJ_SOM
5695 seg = SEG_TEXT;
5696#else
5697 seg = text_section;
5698#endif
5699 sort = 8;
5700 }
5701 else
5702 {
5703#ifdef OBJ_SOM
5704 seg = SEG_DATA;
5705#else
5706 seg = data_section;
5707#endif
5708 sort = 16;
5709 }
5710
5711 if (!is_end_of_statement ())
5712 {
5713 print_errors = FALSE;
5714 ptemp = input_line_pointer + 1;
5715 if ((temp = pa_parse_number (&ptemp)) >= 0)
5716 {
5717 spnum = temp;
5718 input_line_pointer = ptemp;
5719 }
5720 else
5721 {
5722 while (!is_end_of_statement ())
5723 {
5724 input_line_pointer++;
5725 name = input_line_pointer;
5726 c = get_symbol_end ();
5727 if ((strncasecmp (name, "SPNUM", 5) == 0))
5728 {
5729 p = input_line_pointer;
5730 *p = c;
5731 input_line_pointer++;
5732 temp = get_absolute_expression ();
5733 spnum = temp;
5734 }
5735 else if ((strncasecmp (name, "SORT", 4) == 0))
5736 {
5737 p = input_line_pointer;
5738 *p = c;
5739 input_line_pointer++;
5740 temp = get_absolute_expression ();
5741 sort = temp;
5742 }
5743 else if ((strncasecmp (name, "UNLOADABLE", 10) == 0))
5744 {
5745 p = input_line_pointer;
5746 *p = c;
5747 loadable = FALSE;
5748 }
5749 else if ((strncasecmp (name, "NOTDEFINED", 10) == 0))
5750 {
5751 p = input_line_pointer;
5752 *p = c;
5753 defined = FALSE;
5754 }
5755 else if ((strncasecmp (name, "PRIVATE", 7) == 0))
5756 {
5757 p = input_line_pointer;
5758 *p = c;
5759 private = TRUE;
5760 }
5761 else
5762 {
5763 as_bad ("Unrecognized .SPACE argument");
5764 p = input_line_pointer;
5765 *p = c;
5766 }
5767 }
5768 }
5769 print_errors = TRUE;
5770 }
5771 if (create_flag)
5772 space = create_new_space (space_name, spnum, loadable, defined, private, sort, 1, seg);
5773 else
5774 { /* if no creation of new space, this must be the first */
5775 /* occurrence of a built-in space */
5776 space = is_defined_space (space_name);
5777 SPACE_SPNUM (space) = spnum;
5778 SPACE_LOADABLE (space) = loadable & 1;
5779 SPACE_DEFINED (space) = defined & 1;
5780 SPACE_PRIVATE (space) = private & 1;
5781 SPACE_SORT (space) = sort & 0xff;
5782 space->sd_defined = 1;
5783 space->sd_seg = seg;
5784 }
5785 return space;
5786}
5787
5788void
5789pa_align_subseg (seg, subseg)
5790#ifdef OBJ_SOM
5791 segT seg;
5792#else
5793 asection *seg;
5794#endif
5795 subsegT subseg;
5796{
5797 subspace_dict_chainS *now_subspace;
5798 int alignment;
5799 int shift;
5800
5801 now_subspace = pa_subsegment_to_subspace (seg, subseg);
5802 if (SUBSPACE_ALIGN (now_subspace) == 0)
5803 alignment = now_subspace->ssd_last_align;
5804 else if (now_subspace->ssd_last_align > SUBSPACE_ALIGN (now_subspace))
5805 alignment = now_subspace->ssd_last_align;
5806 else
5807 alignment = SUBSPACE_ALIGN (now_subspace);
5808
5809 shift = 0;
5810 while ((1 << shift) < alignment)
5811 shift++;
5812
5813 frag_align (shift, 0);
5814}
5815
5816void
5817pa_space ()
5818{
5819 register char *name;
5820 register char c;
025b0302 5821 register int temp;
025b0302
ME
5822 register space_dict_chainS *sd_chain;
5823 char space_name[40];
5824
5825 if (within_procedure)
5826 {
5827 as_bad ("Can\'t change spaces within a procedure definition. Ignored");
5828 ignore_rest_of_line ();
5829 }
5830 else
5831 {
5832 if (strncasecmp (input_line_pointer, "$text$", 6) == 0)
5833 {
5834 input_line_pointer += 6;
5835 sd_chain = is_defined_space ("$TEXT$");
5836 if (sd_chain == NULL)
5837 sd_chain = pa_parse_space_stmt ("$TEXT$", 1);
5838 else if (sd_chain->sd_defined == 0)
5839 sd_chain = pa_parse_space_stmt ("$TEXT$", 0);
5840
5841 current_space = sd_chain;
5842 SPACE_DEFINED (current_space) = 1;
5843 current_space->sd_defined = 1;
5844#ifdef OBJ_SOM
5845 if (now_seg != SEG_TEXT) /* no need to align if we are already there */
5846#else
5847 if (now_seg != text_section) /* no need to align if we are already there */
5848#endif
5849 pa_align_subseg (now_seg, now_subseg);
5850
5851#ifdef OBJ_SOM
5852 subseg_new (SEG_TEXT, sd_chain->sd_last_subseg);
5853 current_subspace = pa_subsegment_to_subspace (SEG_TEXT,
5854 sd_chain->sd_last_subseg);
5855#else
5856 subseg_new ((char *) text_section->name, sd_chain->sd_last_subseg);
5857 current_subspace = pa_subsegment_to_subspace (text_section,
5858 sd_chain->sd_last_subseg);
5859#endif
5860 demand_empty_rest_of_line ();
5861 return;
5862 }
5863 if (strncasecmp (input_line_pointer, "$private$", 9) == 0)
5864 {
5865 input_line_pointer += 9;
5866 sd_chain = is_defined_space ("$PRIVATE$");
5867 if (sd_chain == NULL)
5868 sd_chain = pa_parse_space_stmt ("$PRIVATE$", 1);
5869 else if (sd_chain->sd_defined == 0)
5870 sd_chain = pa_parse_space_stmt ("$PRIVATE$", 0);
5871
5872 current_space = sd_chain;
5873 SPACE_DEFINED (current_space) = 1;
5874 current_space->sd_defined = 1;
5875#ifdef OBJ_SOM
5876 if (now_seg != SEG_DATA) /* no need to align if we are already there */
5877#else
5878 if (now_seg != data_section) /* no need to align if we are already there */
5879#endif
5880 pa_align_subseg (now_seg, now_subseg);
5881#ifdef OBJ_SOM
5882 subseg_new (SEG_DATA, sd_chain->sd_last_subseg);
5883 current_subspace = pa_subsegment_to_subspace (SEG_DATA,
5884 sd_chain->sd_last_subseg);
5885#else
5886 subseg_new ((char *) data_section->name, sd_chain->sd_last_subseg);
5887 current_subspace = pa_subsegment_to_subspace (data_section,
5888 sd_chain->sd_last_subseg);
5889#endif
5890 demand_empty_rest_of_line ();
5891 return;
5892 }
5893 if (strncasecmp (input_line_pointer,
5894 GDB_DEBUG_SPACE_NAME, strlen (GDB_DEBUG_SPACE_NAME)) == 0)
5895 {
5896 input_line_pointer += strlen (GDB_DEBUG_SPACE_NAME);
5897 sd_chain = is_defined_space (GDB_DEBUG_SPACE_NAME);
5898 if (sd_chain == NULL)
5899 sd_chain = pa_parse_space_stmt (GDB_DEBUG_SPACE_NAME, 1);
5900 else if (sd_chain->sd_defined == 0)
5901 sd_chain = pa_parse_space_stmt (GDB_DEBUG_SPACE_NAME, 0);
5902
5903 current_space = sd_chain;
5904 SPACE_DEFINED (current_space) = 1;
5905 current_space->sd_defined = 1;
5906#ifdef OBJ_SOM
5907 if (now_seg != SEG_GDB) /* no need to align if we are already there */
5908 pa_align_subseg (now_seg, now_subseg);
5909 subseg_new (SEG_GDB, sd_chain->sd_last_subseg);
5910 current_subspace = pa_subsegment_to_subspace (SEG_GDB,
5911 sd_chain->sd_last_subseg);
5912#else
5cf4cd1b
KR
5913 {
5914 asection *gdb_section
5915 = bfd_make_section_old_way (stdoutput, GDB_DEBUG_SPACE_NAME);
5916 if (now_seg != gdb_section) /* no need to align if we are already there */
5917 pa_align_subseg (now_seg, now_subseg);
5918 subseg_new ((char *) gdb_section->name, sd_chain->sd_last_subseg);
5919 current_subspace = pa_subsegment_to_subspace (gdb_section,
5920 sd_chain->sd_last_subseg);
5921 }
025b0302
ME
5922#endif
5923 demand_empty_rest_of_line ();
5924 return;
5925 }
5926
5927 /* it could be a space specified by number */
5928
5929 if ((temp = pa_parse_number (&input_line_pointer)) >= 0)
5930 {
5931 if (sd_chain = pa_find_space_by_number (temp))
5932 {
5933 current_space = sd_chain;
5934 SPACE_DEFINED (current_space) = 1;
5935 current_space->sd_defined = 1;
5936 if (now_seg != sd_chain->sd_seg) /* don't align if we're already there */
5937 pa_align_subseg (now_seg, now_subseg);
5938#ifdef OBJ_SOM
5939 subseg_new (sd_chain->sd_seg, sd_chain->sd_last_subseg);
5940#else
5941 subseg_new ((char *) sd_chain->sd_seg->name, sd_chain->sd_last_subseg);
5942#endif
5943 current_subspace = pa_subsegment_to_subspace (sd_chain->sd_seg,
5944 sd_chain->sd_last_subseg);
5945 demand_empty_rest_of_line ();
5946 return;
5947 }
5948 }
5949
5950 /* not a number, attempt to create a new space */
5951
5952 name = input_line_pointer;
5953 c = get_symbol_end ();
5954 space_name[0] = 0x00;
5955 strcpy (space_name, name);
5956 *input_line_pointer = c;
5957
5958 sd_chain = pa_parse_space_stmt (space_name, 1);
5959 current_space = sd_chain;
5960 SPACE_DEFINED (current_space) = 1;
5961 current_space->sd_defined = 1;
5962 if (now_seg != sd_chain->sd_seg) /* don't align if we're already there */
5963 pa_align_subseg (now_seg, now_subseg);
5964#ifdef OBJ_SOM
5965 subseg_new (sd_chain->sd_seg, sd_chain->sd_last_subseg);
5966#else
5967 subseg_new ((char *) sd_chain->sd_seg->name, sd_chain->sd_last_subseg);
5968#endif
5969 current_subspace = pa_subsegment_to_subspace (sd_chain->sd_seg,
5970 sd_chain->sd_last_subseg);
5971 demand_empty_rest_of_line ();
5972 }
5973 return;
5974}
5975
5976void
5977pa_spnum ()
5978{
5979 register char *name;
5980 register char c;
5981 register char *p;
5982 space_dict_chainS *space;
5983
5984 name = input_line_pointer;
5985 c = get_symbol_end ();
5986 space = is_defined_space (name);
5987 if (space)
5988 {
5989 p = frag_more (4);
5990 /* put bytes in right order. */
5991 md_number_to_chars (p, SPACE_SPNUM (space), 4);
5992 }
5993 else
5994 as_warn ("Undefined space: '%s' Assuming space number = 0.", name);
5995
5996 *input_line_pointer = c;
5997 demand_empty_rest_of_line ();
5998 return;
5999}
6000
6001static
6002int
6003is_power_of_2 (value)
6004 int value;
6005{
6006 int shift;
6007
6008 shift = 0;
6009 while ((1 << shift) != value && shift < 32)
6010 shift++;
6011
6012 if (shift >= 32)
6013 shift = 0;
6014 return shift;
6015}
6016
6017void
6018pa_subspace ()
6019{
6020 register char *name;
6021 register char c;
025b0302 6022 register int temp;
025b0302
ME
6023 char loadable, code_only, common, dup_common, zero;
6024 char sort;
025b0302
ME
6025 int i;
6026 int access;
6027 int space_index;
6028 int alignment;
6029 int quadrant;
025b0302
ME
6030 space_dict_chainS *space;
6031 subspace_dict_chainS *ssd;
025b0302
ME
6032 char *ss_name;
6033 int is_power_of_2 ();
6034
6035 if (within_procedure)
6036 {
6037 as_bad ("Can\'t change subspaces within a procedure definition. Ignored");
6038 ignore_rest_of_line ();
6039 }
6040 else
6041 {
6042 name = input_line_pointer;
6043 c = get_symbol_end ();
6044 space = pa_segment_to_space (now_seg);
6045 ssd = is_defined_subspace (name, space->sd_last_subseg);
6046
6047 ss_name = xmalloc (strlen (name) + 1);
6048 strcpy (ss_name, name);
6049
6050 *input_line_pointer = c;
6051
6052 /* load default values */
6053 sort = 0;
6054 access = 0x7f;
6055 loadable = 1;
6056 common = 0;
6057 dup_common = 0;
6058 code_only = 0;
6059 zero = 0;
6060 space_index = ~0; /* filled in when the .o file is written */
6061 alignment = 0; /* alignment=0 means no ALIGN= appeared on the .SUBSPA */
6062 /* pseudo-op. The default will be the largest .ALIGN */
6063 /* encountered (or 1 if no .ALIGN is encountered) */
6064 quadrant = 0;
6065
6066 if (ssd)
6067 {
6068 if (ssd->ssd_defined)
6069 {
6070#ifdef OBJ_SOM
6071 subseg_new (now_seg, ssd->ssd_subseg);
6072#else
6073 /* subseg_new(now_seg->name,ssd->ssd_subseg); */
6074 subseg_new ((char *) ssd->ssd_seg->name, ssd->ssd_subseg);
6075#endif
6076 if (!is_end_of_statement ())
6077 {
6078 as_warn ("Parameters of an existing subspace can\'t be modified");
6079 }
6080 demand_empty_rest_of_line ();
6081 return;
6082 }
6083 else
6084 {
6085 ssd->ssd_defined = 1;
6086 }
6087 }
6088 else
6089 {
6090 /* a new subspace */
6091 /* load default values */
6092 i = 0;
6093 while (pa_def_subspaces[i].name)
6094 {
6095 if (strcasecmp (pa_def_subspaces[i].name, ss_name) == 0)
6096 {
6097 loadable = pa_def_subspaces[i].loadable;
6098 common = pa_def_subspaces[i].common;
6099 dup_common = pa_def_subspaces[i].dup_common;
6100 code_only = pa_def_subspaces[i].code_only;
6101 zero = pa_def_subspaces[i].zero;
6102 space_index = pa_def_subspaces[i].space_index;
6103 /* alignment = pa_def_subspaces[i].alignment; */
6104 alignment = 0;
6105 quadrant = pa_def_subspaces[i].quadrant;
6106 access = pa_def_subspaces[i].access;
6107 sort = pa_def_subspaces[i].sort;
6108 break;
6109 }
6110 i++;
6111 }
6112 }
6113
6114 if (!is_end_of_statement ())
6115 {
6116 input_line_pointer++;
6117 while (!is_end_of_statement ())
6118 {
6119 name = input_line_pointer;
6120 c = get_symbol_end ();
6121 if ((strncasecmp (name, "QUAD", 4) == 0))
6122 {
6123 *input_line_pointer = c;
6124 input_line_pointer++;
6125 temp = get_absolute_expression ();
6126 quadrant = temp;
6127 }
6128 else if ((strncasecmp (name, "ALIGN", 5) == 0))
6129 {
6130 *input_line_pointer = c;
6131 input_line_pointer++;
6132 temp = get_absolute_expression ();
6133 alignment = temp;
6134 if (!is_power_of_2 (alignment))
6135 {
6136 as_bad ("Alignment must be a power of 2");
6137 alignment = 1;
6138 }
6139 }
6140 else if ((strncasecmp (name, "ACCESS", 6) == 0))
6141 {
6142 *input_line_pointer = c;
6143 input_line_pointer++;
6144 temp = get_absolute_expression ();
6145 access = temp;
6146 }
6147 else if ((strncasecmp (name, "SORT", 4) == 0))
6148 {
6149 *input_line_pointer = c;
6150 input_line_pointer++;
6151 temp = get_absolute_expression ();
6152 sort = temp;
6153 }
6154 else if ((strncasecmp (name, "CODE_ONLY", 9) == 0))
6155 {
6156 *input_line_pointer = c;
6157 code_only = 1;
6158 }
6159 else if ((strncasecmp (name, "UNLOADABLE", 10) == 0))
6160 {
6161 *input_line_pointer = c;
6162 loadable = 0;
6163 }
6164 else if ((strncasecmp (name, "COMMON", 6) == 0))
6165 {
6166 *input_line_pointer = c;
6167 common = 1;
6168 }
6169 else if ((strncasecmp (name, "DUP_COMM", 8) == 0))
6170 {
6171 *input_line_pointer = c;
6172 dup_common = 1;
6173 }
6174 else if ((strncasecmp (name, "ZERO", 4) == 0))
6175 {
6176 *input_line_pointer = c;
6177 zero = 1;
6178 }
6179 else
6180 {
6181 as_bad ("Unrecognized .SUBSPACE argument");
6182 }
6183 if (!is_end_of_statement ())
6184 input_line_pointer++;
6185 }
6186 }
6187 space = pa_segment_to_space (now_seg);
6188 if (ssd)
6189 {
6190 current_subspace = update_subspace (ss_name, 1, loadable, code_only,
6191 common, dup_common, sort, zero, access,
6192 space_index, alignment, quadrant,
6193 ssd->ssd_subseg);
6194 }
6195 else
6196 {
6197 current_subspace = create_new_subspace (space, ss_name, 1, loadable, code_only,
6198 common, dup_common, zero, sort,
6199 access, space_index, alignment,
6200 quadrant, now_seg);
6201 }
6202 SUBSPACE_SUBSPACE_START (current_subspace) = pa_subspace_start (space, quadrant);
6203
6204 demand_empty_rest_of_line ();
6205#ifdef OBJ_SOM
6206 subseg_new (current_subspace->ssd_seg, current_subspace->ssd_subseg);
6207#else
6208 subseg_new ((char *) current_subspace->ssd_seg->name, current_subspace->ssd_subseg);
6209#endif
6210 }
6211 return;
6212}
6213
6214/* For ELF, this function serves one purpose: to setup the st_size */
6215/* field of STT_FUNC symbols. To do this, we need to scan the */
6216/* call_info structure list, determining st_size in one of two possible */
6217/* ways: */
6218
6219/* 1. call_info->start_frag->fr_fix has the size of the fragment. */
6220/* This approach assumes that the function was built into a */
6221/* single fragment. This works for most cases, but might fail. */
6222/* For example, if there was a segment change in the middle of */
6223/* the function. */
6224
6225/* 2. The st_size field is the difference in the addresses of the */
6226/* call_info->start_frag->fr_address field and the fr_address */
6227/* field of the next fragment with fr_type == rs_fill and */
6228/* fr_fix != 0. */
6229
6230void
5cf4cd1b 6231elf_hppa_final_processing ()
025b0302
ME
6232{
6233 extern call_infoS *call_info_root;
6234
6235 call_infoS *ciP;
6236
6237 for (ciP = call_info_root; ciP; ciP = ciP->ci_next)
6238 {
5cf4cd1b 6239 elf32_symbol_type *esym = (elf32_symbol_type *) ciP->start_symbol->bsym;
025b0302 6240 esym->internal_elf_sym.st_size =
5cf4cd1b 6241 S_GET_VALUE (ciP->end_symbol) - S_GET_VALUE (ciP->start_symbol) + 4;
025b0302
ME
6242 }
6243}
6244
6245/* pa-spaces.c -- Space/subspace support for the HP PA-RISC version of GAS */
6246
6247/* for space, subspace, and symbol maintenance on HP 9000 Series 800 */
6248
6249space_dict_chainS *space_dict_root;
6250space_dict_chainS *space_dict_last;
6251
6252space_dict_chainS *current_space;
6253subspace_dict_chainS *current_subspace;
6254
025b0302
ME
6255void
6256pa_spaces_begin ()
6257{
6258 space_dict_chainS *space;
6259 int i;
6260 subsegT now_subseg = now_subseg;
6261
6262 space_dict_root = NULL;
6263 space_dict_last = NULL;
6264
025b0302
ME
6265 /* create default space and subspace dictionaries */
6266
6267 i = 0;
6268 while (pa_def_spaces[i].name)
6269 {
6270 if (pa_def_spaces[i].alias)
6271 pa_def_spaces[i].segment = subseg_new (pa_def_spaces[i].alias, 0);
6272 else
6273 pa_def_spaces[i].segment = bfd_make_section_old_way (stdoutput, pa_def_spaces[i].name);
6274
6275 create_new_space (pa_def_spaces[i].name, pa_def_spaces[i].spnum,
6276 pa_def_spaces[i].loadable, pa_def_spaces[i].defined,
6277 pa_def_spaces[i].private, pa_def_spaces[i].sort, 0,
6278 pa_def_spaces[i].segment);
6279 i++;
6280 }
6281
6282 i = 0;
6283 while (pa_def_subspaces[i].name)
6284 {
6285 space = pa_segment_to_space (pa_def_spaces[pa_def_subspaces[i].def_space_index].segment);
6286 if (space)
6287 {
6288 char *name = pa_def_subspaces[i].alias;
6289 if (!name)
6290 name = pa_def_subspaces[i].name;
6291 create_new_subspace (space, name,
6292 pa_def_subspaces[i].defined,
6293 pa_def_subspaces[i].loadable,
6294 pa_def_subspaces[i].code_only, pa_def_subspaces[i].common,
6295 pa_def_subspaces[i].dup_common, pa_def_subspaces[i].zero,
6296 pa_def_subspaces[i].sort, pa_def_subspaces[i].access,
6297 pa_def_subspaces[i].space_index,
6298 pa_def_subspaces[i].alignment,
6299 pa_def_subspaces[i].quadrant,
6300 pa_def_spaces[pa_def_subspaces[i].def_space_index].segment);
6301 subseg_new (name, pa_def_subspaces[i].subsegment);
6302 }
6303 else
6304 as_fatal ("Internal error: space missing for subspace \"%s\"\n",
6305 pa_def_subspaces[i].name);
6306 i++;
6307 }
6308}
6309
6310space_dict_chainS *
6311create_new_space (name, spnum, loadable, defined, private, sort, defined_in_file, seg)
6312 char *name;
6313 int spnum;
6314 char loadable;
6315 char defined;
6316 char private;
6317 char sort;
6318 char defined_in_file;
6319 asection *seg;
6320
6321{
6322 Elf_Internal_Shdr *new_space;
6323 space_dict_chainS *chain_entry;
6324
6325 new_space = (Elf_Internal_Shdr *) xmalloc (sizeof (Elf_Internal_Shdr));
6326 if (!new_space)
6327 as_fatal ("Out of memory: could not allocate new Elf_Internal_Shdr: %s\n", name);
6328
6329 /*
6330 new_space->space_number = spnum;
6331 new_space->is_loadable = loadable & 1;
6332 new_space->is_defined = defined & 1;
6333 new_space->is_private = private & 1;
6334 new_space->sort_key = sort & 0xff;
6335
6336 new_space->loader_fix_index = ~0;
6337 new_space->loader_fix_quantity = 0;
6338 new_space->init_pointer_index = ~0;
6339 new_space->init_pointer_quantity = 0;
6340 new_space->subspace_quantity = 0;
6341 */
6342
6343 chain_entry = (space_dict_chainS *) xmalloc (sizeof (space_dict_chainS));
6344 if (!chain_entry)
6345 as_fatal ("Out of memory: could not allocate new space chain entry: %s\n", name);
6346
6347 SPACE_NAME (chain_entry) = (char *) xmalloc (strlen (name) + 1);
6348 strcpy (SPACE_NAME (chain_entry), name);
6349
6350 chain_entry->sd_entry = new_space;
6351 chain_entry->sd_defined = defined_in_file;
6352 chain_entry->sd_seg = seg;
6353 chain_entry->sd_last_subseg = -1;
6354 chain_entry->sd_next = NULL;
6355
6356 SPACE_SPNUM (chain_entry) = spnum;
6357 SPACE_LOADABLE (chain_entry) = loadable & 1;
6358 SPACE_DEFINED (chain_entry) = defined & 1;
6359 SPACE_PRIVATE (chain_entry) = private & 1;
6360 SPACE_SORT (chain_entry) = sort & 0xff;
6361
6362 /* find spot for the new space based on its sort key */
6363
6364 if (!space_dict_last)
6365 space_dict_last = chain_entry;
6366
6367 if (space_dict_root == NULL) /* if root is null, it is very easy */
6368 space_dict_root = chain_entry;
6369 else
6370 {
6371 space_dict_chainS *sdcP;
6372 space_dict_chainS *last_sdcP;
6373
6374 sdcP = space_dict_root;
6375 last_sdcP = NULL;
6376
6377 while (sdcP)
6378 {
6379 if (SPACE_SORT (sdcP) < SPACE_SORT (chain_entry))
6380 {
6381 last_sdcP = sdcP;
6382 sdcP = sdcP->sd_next;
6383 }
6384 else if (SPACE_SORT (sdcP) == SPACE_SORT (chain_entry))
6385 {
6386 last_sdcP = sdcP;
6387 sdcP = sdcP->sd_next;
6388 }
6389 else if (SPACE_SORT (sdcP) > SPACE_SORT (chain_entry))
6390 {
6391 break;
6392 }
6393 }
6394
6395 if (last_sdcP)
6396 {
6397 chain_entry->sd_next = sdcP;
6398 last_sdcP->sd_next = chain_entry;
6399 }
6400 else
6401 {
6402 space_dict_root = chain_entry;
6403 chain_entry->sd_next = sdcP;
6404 }
6405
6406 if (chain_entry->sd_next == NULL)
6407 space_dict_last = chain_entry;
6408 }
6409
6410 return chain_entry;
6411}
6412
6413subspace_dict_chainS
6414* create_new_subspace (space, name, defined, loadable, code_only, common, dup_common,
6415 is_zero, sort, access, space_index, alignment, quadrant, seg)
6416 space_dict_chainS *space;
6417 char *name;
6418 char defined, loadable, code_only, common, dup_common, is_zero;
6419 char sort;
6420 int access;
6421 int space_index;
6422 int alignment;
6423 int quadrant;
6424 asection *seg;
6425{
6426 Elf_Internal_Shdr *new_subspace;
6427 subspace_dict_chainS *chain_entry;
6428 symbolS *start_symbol;
6429
6430 new_subspace = (Elf_Internal_Shdr *) xmalloc (sizeof (Elf_Internal_Shdr));
6431 if (!new_subspace)
6432 as_fatal ("Out of memory: could not allocate new Elf_Internal_Shdr: %s\n",
6433 name);
6434
6435 /*
6436 new_subspace->space_index = space_index;
6437 new_subspace->fixup_request_index = ~0;
6438 */
6439
6440 chain_entry = (subspace_dict_chainS *) xmalloc (sizeof (subspace_dict_chainS));
6441 if (!chain_entry)
6442 as_fatal ("Out of memory: could not allocate new subspace chain entry: %s\n", name);
6443
6444 chain_entry->ssd_entry = new_subspace;
6445 SUBSPACE_NAME (chain_entry) = (char *) xmalloc (strlen (name) + 1);
6446 strcpy (SUBSPACE_NAME (chain_entry), name);
6447
6448 SUBSPACE_ACCESS (chain_entry) = access & 0x7f;
6449 SUBSPACE_LOADABLE (chain_entry) = loadable & 1;
6450 SUBSPACE_COMMON (chain_entry) = common & 1;
6451 SUBSPACE_DUP_COMM (chain_entry) = dup_common & 1;
6452 SUBSPACE_SORT (chain_entry) = sort & 0xff;
6453 SET_SUBSPACE_CODE_ONLY (chain_entry, code_only & 1);
6454 SUBSPACE_ALIGN (chain_entry) = alignment & 0xffff;
6455 SUBSPACE_QUADRANT (chain_entry) = quadrant & 0x3;
6456 SUBSPACE_SUBSPACE_START (chain_entry) = pa_subspace_start (space, quadrant);
6457
6458 chain_entry->ssd_defined = defined;
6459 chain_entry->ssd_space_number = space_index;
6460 chain_entry->ssd_subseg = pa_next_subseg (space);
6461 chain_entry->ssd_seg = seg;
6462 SUBSPACE_ZERO (chain_entry) = is_zero;
6463 chain_entry->ssd_last_align = 1;
6464 chain_entry->ssd_next = NULL;
6465
6466 /* find spot for the new subspace based on its sort key */
6467
6468 if (space->sd_subspaces == NULL) /* if root is null, it is very easy */
6469 space->sd_subspaces = chain_entry;
6470 else
6471 {
6472 subspace_dict_chainS *ssdcP;
6473 subspace_dict_chainS *last_ssdcP;
6474
6475 ssdcP = space->sd_subspaces;
6476 last_ssdcP = NULL;
6477
6478 while (ssdcP)
6479 {
6480 if (SUBSPACE_SORT (ssdcP) < SUBSPACE_SORT (chain_entry))
6481 {
6482 last_ssdcP = ssdcP;
6483 ssdcP = ssdcP->ssd_next;
6484 }
6485 else if (SUBSPACE_SORT (ssdcP) == SUBSPACE_SORT (chain_entry))
6486 {
6487 last_ssdcP = ssdcP;
6488 ssdcP = ssdcP->ssd_next;
6489 }
6490 else if (SUBSPACE_SORT (ssdcP) > SUBSPACE_SORT (chain_entry))
6491 {
6492 break;
6493 }
6494 }
6495
6496 if (last_ssdcP)
6497 {
6498 chain_entry->ssd_next = ssdcP;
6499 last_ssdcP->ssd_next = chain_entry;
6500 }
6501 else
6502 {
6503 space->sd_subspaces = chain_entry;
6504 chain_entry->ssd_next = ssdcP;
6505 }
6506 }
6507
6508 start_symbol = pa_set_start_symbol (seg, space->sd_last_subseg);
6509 chain_entry->ssd_start_sym = start_symbol;
6510 return chain_entry;
6511
6512}
6513
6514subspace_dict_chainS
6515* update_subspace (name, defined, loadable, code_only, common, dup_common, sort, zero,
6516 access, space_index, alignment, quadrant, subseg)
6517 char *name;
6518 char defined, loadable, code_only, common, dup_common, zero;
6519 char sort;
6520 int access;
6521 int space_index;
6522 int alignment;
6523 int quadrant;
6524 subsegT subseg;
6525{
6526 subspace_dict_chainS *chain_entry;
6527 subspace_dict_chainS *is_defined_subspace ();
6528
6529 if ((chain_entry = is_defined_subspace (name, subseg)))
6530 {
6531
6532 SUBSPACE_ACCESS (chain_entry) = access & 0x7f;
6533 SUBSPACE_LOADABLE (chain_entry) = loadable & 1;
6534 SUBSPACE_COMMON (chain_entry) = common & 1;
6535 SUBSPACE_DUP_COMM (chain_entry) = dup_common & 1;
6536 SET_SUBSPACE_CODE_ONLY (chain_entry, code_only & 1);
6537 SUBSPACE_SORT (chain_entry) = sort & 0xff;
6538 /* chain_entry->ssd_entry->space_index = space_index; */
6539 SUBSPACE_ALIGN (chain_entry) = alignment & 0xffff;
6540 SUBSPACE_QUADRANT (chain_entry) = quadrant & 0x3;
6541
6542 chain_entry->ssd_defined = defined;
6543 chain_entry->ssd_space_number = space_index;
6544 SUBSPACE_ZERO (chain_entry) = zero;
6545 }
6546 else
6547 chain_entry = NULL;
6548
6549 return chain_entry;
6550
6551}
6552
6553space_dict_chainS *
6554is_defined_space (name)
6555 char *name;
6556{
6557 space_dict_chainS *spaceCh;
6558
6559 for (spaceCh = space_dict_root; spaceCh; spaceCh = spaceCh->sd_next)
6560 {
6561 if (strcmp (SPACE_NAME (spaceCh), name) == 0)
6562 {
6563 return spaceCh;
6564 }
6565 }
6566
6567 return NULL;
6568}
6569
6570space_dict_chainS *
6571pa_segment_to_space (seg)
6572 asection *seg;
6573{
6574 space_dict_chainS *spaceCh;
6575
6576 for (spaceCh = space_dict_root; spaceCh; spaceCh = spaceCh->sd_next)
6577 {
6578 if (spaceCh->sd_seg == seg)
6579 {
6580 return spaceCh;
6581 }
6582 }
6583
6584 return NULL;
6585}
6586
6587subspace_dict_chainS *
6588is_defined_subspace (name, subseg)
6589 char *name;
6590 subsegT subseg;
6591{
6592 space_dict_chainS *spaceCh;
6593 subspace_dict_chainS *subspCh;
6594
6595 for (spaceCh = space_dict_root; spaceCh; spaceCh = spaceCh->sd_next)
6596 {
6597 for (subspCh = spaceCh->sd_subspaces; subspCh; subspCh = subspCh->ssd_next)
6598 {
6599 /*
6600 if ( strcmp(SUBSPACE_NAME(subspCh),name) == 0 &&
6601 subspCh->ssd_subseg == subseg ) {
6602 */
6603 if (strcmp (SUBSPACE_NAME (subspCh), name) == 0)
6604 {
6605 return subspCh;
6606 }
6607 }
6608 }
6609 return NULL;
6610}
6611
6612subspace_dict_chainS *
6613pa_subsegment_to_subspace (seg, subseg)
6614 asection *seg;
6615 subsegT subseg;
6616{
6617 space_dict_chainS *spaceCh;
6618 subspace_dict_chainS *subspCh;
6619
6620 for (spaceCh = space_dict_root; spaceCh; spaceCh = spaceCh->sd_next)
6621 {
6622 if (spaceCh->sd_seg == seg)
6623 {
6624 for (subspCh = spaceCh->sd_subspaces; subspCh; subspCh = subspCh->ssd_next)
6625 {
6626 if (subspCh->ssd_subseg == (int) subseg)
6627 {
6628 return subspCh;
6629 }
6630 }
6631 }
6632 }
6633
6634 return NULL;
6635}
6636
6637space_dict_chainS *
6638pa_find_space_by_number (number)
6639 int number;
6640{
6641 space_dict_chainS *spaceCh;
6642
6643 for (spaceCh = space_dict_root; spaceCh; spaceCh = spaceCh->sd_next)
6644 {
6645 if (SPACE_SPNUM (spaceCh) == number)
6646 {
6647 return spaceCh;
6648 }
6649 }
6650
6651 return NULL;
6652}
6653
6654unsigned int
6655pa_subspace_start (space, quadrant)
6656 space_dict_chainS *space;
6657 int quadrant;
6658{
6659 if ((strcasecmp (SPACE_NAME (space), "$PRIVATE$") == 0) &&
6660 quadrant == 1)
6661 {
6662 return 0x40000000;
6663 }
6664 else if (space->sd_seg == data_section && quadrant == 1)
6665 { /* in case name is */
6666 /* already converted */
6667 /* to a space dict- */
6668 /* ionary index */
6669 return 0x40000000;
6670 }
6671 else
6672 return 0;
6673}
6674
6675int
6676pa_next_subseg (space)
6677 space_dict_chainS *space;
6678{
6679
6680 space->sd_last_subseg++;
6681 return space->sd_last_subseg;
6682}
6683
6684int
6685is_last_defined_subspace (ssd)
6686 subspace_dict_chainS *ssd;
6687{
6688
6689 for (; ssd; ssd = ssd->ssd_next)
6690 {
6691 if (ssd->ssd_defined)
6692 return FALSE;
6693 }
6694
6695 return TRUE;
6696}
6697
6698symbolS *
6699pa_get_start_symbol (seg, subseg)
6700 asection *seg;
6701 subsegT subseg;
6702{
6703 symbolS *start_symbol;
6704 subspace_dict_chainS *ssd;
6705
6706 start_symbol = NULL;
6707
6708 /* each time a new space is created, build a symbol called LS$START_seg_subseg$ */
6709 /* where <space-name> is the name of the space */
6710 /* the start symbol will be SS_LOCAL and ST_CODE */
6711
6712 if (seg == bfd_make_section_old_way (stdoutput, ".text") ||
6713 seg == bfd_make_section_old_way (stdoutput, ".data") ||
6714 seg == bfd_make_section_old_way (stdoutput, GDB_DEBUG_SPACE_NAME))
6715 {
6716 ssd = pa_subsegment_to_subspace (seg, subseg);
6717 if (ssd)
6718 {
6719 start_symbol = ssd->ssd_start_sym;
6720 }
6721 else
6722 as_fatal ("Internal error: missing subspace for (seg,subseg)=('%s',%d)",
6723 seg->name, subseg);
6724 }
6725 else
6726 as_fatal ("Internal error: attempt to find start symbol for unloadable segment: '%s'",
6727 seg->name);
6728
6729 return start_symbol;
6730}
6731
6732/*
6733 Function to define a symbol whose address is the beginning of a subspace.
6734 This function assumes the symbol is to be defined for the current subspace.
6735 */
6736
6737symbolS *
6738pa_set_start_symbol (seg, subseg)
6739 asection *seg;
6740 subsegT subseg;
6741{
6742 symbolS *start_symbol;
6743 subspace_dict_chainS *ssd;
6744 char *symbol_name;
6745
6746 symbol_name = (char *) xmalloc (strlen ("LS$START__000000$") + strlen (seg->name) + 1);
6747
6748 sprintf (symbol_name, "LS$START_%s_%03d$", seg->name, subseg);
6749
6750 start_symbol
6751 = symbol_new (symbol_name, seg, 0, frag_now); /* XXX: not sure if value s.b. 0 or frag s.b. NULL */
6752
6753 start_symbol->bsym->flags = BSF_LOCAL; /* XXX: isn't there a macro defined for this? */
6754
6755 /* each time a new space is created, build a symbol called LS$START_seg_subseg$ */
6756 /* where <space-name> is the name of the space */
6757 /* the start symbol will be SS_LOCAL and ST_CODE */
6758 /* This function assumes that (seg,subseg) is a new subsegment(subspace) */
6759
6760 if (seg == bfd_make_section_old_way (stdoutput, ".text") ||
6761 seg == bfd_make_section_old_way (stdoutput, ".data") ||
6762 seg == bfd_make_section_old_way (stdoutput, GDB_DEBUG_SPACE_NAME))
6763 {
6764 ssd = pa_subsegment_to_subspace (seg, subseg);
6765 if (ssd)
6766 {
6767 ssd->ssd_start_sym = start_symbol;
6768 }
6769 else
6770 as_fatal ("Internal error: missing subspace for (seg,subseg)=('%s',%d)",
6771 seg, subseg);
6772 }
6773 else
6774 as_fatal ("Internal error: attempt to define start symbol for unloadable segment: '%s'",
6775 seg->name);
6776
6777 return start_symbol;
6778}
6779
6780static unsigned int
6781pa_stringer_aux (s)
6782 char *s;
6783{
6784 unsigned int c = *s & CHAR_MASK;
6785 switch (c)
6786 {
6787 case '\"':
6788 c = NOT_A_CHAR;
6789 break;
6790 default:
6791 break;
6792 }
6793 return c;
6794}
6795
6796void
6797pa_stringer (append_zero) /* Worker to do .ascii etc statements. */
6798 /* Checks end-of-line. */
6799 register int append_zero; /* 0: don't append '\0', else 1 */
6800{
6801 char *s;
6802 unsigned int c;
6803 char num_buf[4];
6804 int i;
6805
6806 /* Preprocess the string to handle PA-specific escape sequences. */
6807 /* For example, \xDD where DD is a hexidecimal number should be */
6808 /* changed to \OOO where OOO is an octal number. */
6809
6810 s = input_line_pointer + 1; /* skip the opening quote */
6811
6812 while (is_a_char (c = pa_stringer_aux (s++)))
6813 {
6814 if (c == '\\')
6815 {
6816 c = *s;
6817 switch (c)
6818 {
6819 case 'x':
6820 {
6821 unsigned int number;
6822 int num_digit;
6823 char dg;
6824 char *s_start = s;
6825
6826 s++; /* get past the 'x' */
6827 for (num_digit = 0, number = 0, dg = *s;
6828 num_digit < 2
6829 && (isdigit (dg) || (dg >= 'a' && dg <= 'f')
6830 || (dg >= 'A' && dg <= 'F'));
6831 num_digit++)
6832 {
6833 if (isdigit (dg))
6834 number = number * 16 + dg - '0';
6835 else if (dg >= 'a' && dg <= 'f')
6836 number = number * 16 + dg - 'a' + 10;
6837 else
6838 number = number * 16 + dg - 'A' + 10;
6839
6840 s++;
6841 dg = *s;
6842 }
6843 if (num_digit > 0)
6844 {
6845 switch (num_digit)
6846 {
6847 case 1:
6848 sprintf (num_buf, "%02o", number);
6849 break;
6850 case 2:
6851 sprintf (num_buf, "%03o", number);
6852 break;
6853 }
6854 for (i = 0; i <= num_digit; i++)
6855 s_start[i] = num_buf[i];
6856 }
5cf4cd1b 6857 break;
025b0302 6858 }
5cf4cd1b
KR
6859 /* This might be a "\"", skip over the escaped char. */
6860 default:
6861 s++;
025b0302
ME
6862 break;
6863 }
6864 }
6865 }
6866 stringer (append_zero);
6867 pa_undefine_label ();
6868}
6869
6870void
6871pa_version ()
6872{
6873#ifdef OBJ_ELF
6874 obj_elf_version ();
6875#endif
6876 pa_undefine_label ();
6877}
6878
6879void
6880pa_cons (nbytes)
6881 register unsigned int nbytes; /* 1=.byte, 2=.word, 4=.long */
6882{
6883 cons (nbytes);
6884 pa_undefine_label ();
6885}
6886
6887void
6888pa_data ()
6889{
6890 s_data ();
6891 pa_undefine_label ();
6892}
6893
6894void
6895pa_desc ()
6896{
6897
6898#ifdef OBJ_ELF
6899 obj_elf_desc ();
6900#endif
6901 pa_undefine_label ();
6902}
6903
6904void
6905pa_float_cons (float_type)
6906 register int float_type; /* 'f':.ffloat ... 'F':.float ... */
6907{
6908 float_cons (float_type);
6909 pa_undefine_label ();
6910}
6911
6912void
6913pa_fill ()
6914{
6915 s_fill ();
6916 pa_undefine_label ();
6917}
6918
6919void
6920pa_lcomm (needs_align)
6921 /* 1 if this was a ".bss" directive, which may require a 3rd argument
6922 (alignment); 0 if it was an ".lcomm" (2 args only) */
6923 int needs_align;
6924{
6925 s_lcomm (needs_align);
6926 pa_undefine_label ();
6927}
6928
6929void
6930pa_lsym ()
6931{
6932 s_lsym ();
6933 pa_undefine_label ();
6934}
6935
6936void
6937pa_big_cons (nbytes)
6938 register int nbytes;
6939{
6940 big_cons (nbytes);
6941 pa_undefine_label ();
6942}
6943
6944void
6945pa_text ()
6946{
6947 s_text ();
6948 pa_undefine_label ();
6949}
5cf4cd1b
KR
6950
6951static symext_chainS *symext_rootP = NULL;
6952static symext_chainS *symext_lastP = NULL;
6953
6954void
6955hppa_tc_symbol (abfd, symbolP, sym_idx)
6956 bfd * abfd;
6957 elf_symbol_type * symbolP;
6958 int sym_idx;
6959{
6960 symext_chainS *symextP;
6961 unsigned int arg_reloc;
6962
6963 if (!(symbolP->symbol.flags & BSF_FUNCTION))
6964 return;
6965
6966 arg_reloc = symbolP->tc_data.hppa_arg_reloc;
6967
6968 symextP = (symext_chainS *) bfd_alloc (abfd, sizeof (symext_chainS) * 2);
6969
6970 symextP[0].entry = ELF32_HPPA_SX_WORD (HPPA_SXT_SYMNDX, sym_idx);
6971 symextP[0].next = &symextP[1];
6972
6973 symextP[1].entry = ELF32_HPPA_SX_WORD (HPPA_SXT_ARG_RELOC, arg_reloc);
6974 symextP[1].next = NULL;
6975
6976 if (symext_rootP == NULL)
6977 {
6978 symext_rootP = &symextP[0];
6979 symext_lastP = &symextP[1];
6980 }
6981 else
6982 {
6983 symext_lastP->next = &symextP[0];
6984 symext_lastP = &symextP[1];
6985 }
6986}
6987
6988void
6989hppa_tc_make_sections (abfd)
6990bfd * abfd;
6991{
6992 symext_chainS *symextP;
6993 symext_entryS *outbound_symexts;
6994 int size;
6995 int n;
6996 extern void hppa_elf_stub_finish (); /* forward declaration */
6997 asection *symextn_sec;
6998 segT save_seg = now_seg;
6999 subsegT save_subseg = now_subseg;
7000
7001 hppa_tc_make_symextn_section();
7002
7003 bfd_set_section_contents(stdoutput, stdoutput->sections, "", 0, 0); /* force some calculations */
7004
7005 hppa_elf_stub_finish (abfd);
7006
7007 if (symext_rootP == NULL)
7008 return;
7009
7010 for (n = 0, symextP = symext_rootP; symextP; symextP = symextP->next, ++n)
7011 ;
7012
7013 size = sizeof (symext_entryS) * n;
7014
7015 symextn_sec = subseg_new(SYMEXTN_SECTION_NAME, 0);
7016
7017 frag_wane (frag_now);
7018 frag_new (0);
7019
7020 for (symextP = symext_rootP; symextP; symextP = symextP->next)
7021 {
7022 char *ptr;
7023 extern int *elf_get_symtab_map();
7024 Elf_Sym_Extra *symextra = elf_sym_extra (abfd);
7025 int idx;
7026
7027 /* First, patch the symbol extension record to reflect the true */
7028 /* symbol table index */
7029
7030 if (ELF32_HPPA_SX_TYPE(symextP->entry) == HPPA_SXT_SYMNDX)
7031 {
7032 idx = ELF32_HPPA_SX_VAL(symextP->entry) - 1;
7033 symextP->entry = ELF32_HPPA_SX_WORD (HPPA_SXT_SYMNDX,
7034 symextra[idx].elf_sym_num);
7035 }
7036
7037 ptr = frag_more(sizeof(symextP->entry));
7038 md_number_to_chars(ptr,symextP->entry,sizeof(symextP->entry));
7039 }
7040
7041 frag_now->fr_fix = obstack_next_free (&frags) - frag_now->fr_literal;
7042 frag_wane (frag_now);
7043
7044 /* now, switch back to the original segment */
7045
7046 subseg_new(save_seg->name, save_subseg);
7047
7048 return;
7049}
7050
7051static void
7052hppa_tc_make_symextn_section()
7053{
7054 extern symext_chainS *elf32_hppa_get_symextn_chain();
7055
7056 if (symext_rootP)
7057 {
7058 symext_chainS *symextP;
7059 int n;
7060 int size;
7061 segT symextn_sec;
7062 segT save_seg = now_seg;
7063 subsegT save_subseg = now_subseg;
7064
7065 for (n = 0, symextP = symext_rootP; symextP; symextP = symextP->next, ++n)
7066 ;
7067
7068 size = sizeof (symext_entryS) * n;
7069
7070 symextn_sec = subseg_new(SYMEXTN_SECTION_NAME, 0);
7071
7072 bfd_set_section_flags(stdoutput, symextn_sec, SEC_LOAD | SEC_HAS_CONTENTS | SEC_DATA);
7073 bfd_set_section_size (stdoutput, symextn_sec, size);
7074
7075 /* now, switch back to the original segment */
7076 subseg_new(save_seg->name, save_subseg);
7077 }
7078}
This page took 0.330389 seconds and 4 git commands to generate.