Ran "indent", for GNU coding style; some code & comments still need fixup.
[deliverable/binutils-gdb.git] / gas / config / tc-ns32k.c
1 /* ns32k.c -- Assemble on the National Semiconductor 32k series
2 Copyright (C) 1987, 1992 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /*#define SHOW_NUM 1*//* uncomment for debugging */
21
22 #include <stdio.h>
23 #include <ctype.h>
24 #ifdef USG
25 #include <string.h>
26 #else
27 #include <strings.h>
28 #endif
29 #include "opcode/ns32k.h"
30
31 #include "as.h"
32 #include "read.h"
33
34 #include "obstack.h"
35
36 /* Macros */
37 #define IIF_ENTRIES 13 /* number of entries in iif */
38 #define PRIVATE_SIZE 256 /* size of my garbage memory */
39 #define MAX_ARGS 4
40 #define DEFAULT -1 /* addr_mode returns this value when plain constant or label is encountered */
41
42 #define IIF(ptr,a1,c1,e1,g1,i1,k1,m1,o1,q1,s1,u1) \
43 iif.iifP[ptr].type= a1; \
44 iif.iifP[ptr].size= c1; \
45 iif.iifP[ptr].object= e1; \
46 iif.iifP[ptr].object_adjust= g1; \
47 iif.iifP[ptr].pcrel= i1; \
48 iif.iifP[ptr].pcrel_adjust= k1; \
49 iif.iifP[ptr].im_disp= m1; \
50 iif.iifP[ptr].relax_substate= o1; \
51 iif.iifP[ptr].bit_fixP= q1; \
52 iif.iifP[ptr].addr_mode= s1; \
53 iif.iifP[ptr].bsr= u1;
54
55 #ifdef SEQUENT_COMPATABILITY
56 #define LINE_COMMENT_CHARS "|"
57 #define ABSOLUTE_PREFIX '@'
58 #define IMMEDIATE_PREFIX '#'
59 #endif
60
61 #ifndef LINE_COMMENT_CHARS
62 #define LINE_COMMENT_CHARS "#"
63 #endif
64
65 const char comment_chars[] = "#";
66 const char line_comment_chars[] = LINE_COMMENT_CHARS;
67 const char line_separator_chars[] = "";
68 #if !defined(ABSOLUTE_PREFIX) && !defined(IMMEDIATE_PREFIX)
69 #define ABSOLUTE_PREFIX '@' /* One or the other MUST be defined */
70 #endif
71
72 struct addr_mode
73 {
74 char mode; /* addressing mode of operand (0-31) */
75 char scaled_mode; /* mode combined with scaled mode */
76 char scaled_reg; /* register used in scaled+1 (1-8) */
77 char float_flag; /* set if R0..R7 was F0..F7 ie a floating-point-register */
78 char am_size; /* estimated max size of general addr-mode parts*/
79 char im_disp; /* if im_disp==1 we have a displacement */
80 char pcrel; /* 1 if pcrel, this is really redundant info */
81 char disp_suffix[2]; /* length of displacement(s), 0=undefined */
82 char *disp[2]; /* pointer(s) at displacement(s)
83 or immediates(s) (ascii) */
84 char index_byte; /* index byte */
85 };
86 typedef struct addr_mode addr_modeS;
87
88
89 char *freeptr, *freeptr_static; /* points at some number of free bytes */
90 struct hash_control *inst_hash_handle;
91
92 struct ns32k_opcode *desc; /* pointer at description of instruction */
93 addr_modeS addr_modeP;
94 const char EXP_CHARS[] = "eE";
95 const char FLT_CHARS[] = "fd"; /* we don't want to support lowercase, do we */
96
97 /* UPPERCASE denotes live names
98 * when an instruction is built, IIF is used as an intermidiate form to store
99 * the actual parts of the instruction. A ns32k machine instruction can
100 * be divided into a couple of sub PARTs. When an instruction is assembled
101 * the appropriate PART get an assignment. When an IIF has been completed it's
102 * converted to a FRAGment as specified in AS.H */
103
104 /* internal structs */
105 struct option
106 {
107 char *pattern;
108 unsigned long or;
109 unsigned long and;
110 };
111
112 typedef struct
113 {
114 int type; /* how to interpret object */
115 int size; /* Estimated max size of object */
116 unsigned long object; /* binary data */
117 int object_adjust; /* number added to object */
118 int pcrel; /* True if object is pcrel */
119 int pcrel_adjust; /* length in bytes from the
120 instruction start to the
121 displacement */
122 int im_disp; /* True if the object is a displacement */
123 relax_substateT relax_substate; /* Initial relaxsubstate */
124 bit_fixS *bit_fixP; /* Pointer at bit_fix struct */
125 int addr_mode; /* What addrmode do we associate with this iif-entry */
126 char bsr; /* Sequent hack */
127 }
128
129 iif_entryT; /* Internal Instruction Format */
130
131 struct int_ins_form
132 {
133 int instr_size; /* Max size of instruction in bytes. */
134 iif_entryT iifP[IIF_ENTRIES + 1];
135 };
136 struct int_ins_form iif;
137 expressionS exprP;
138 char *input_line_pointer;
139 /* description of the PARTs in IIF
140 *object[n]:
141 * 0 total length in bytes of entries in iif
142 * 1 opcode
143 * 2 index_byte_a
144 * 3 index_byte_b
145 * 4 disp_a_1
146 * 5 disp_a_2
147 * 6 disp_b_1
148 * 7 disp_b_2
149 * 8 imm_a
150 * 9 imm_b
151 * 10 implied1
152 * 11 implied2
153 *
154 * For every entry there is a datalength in bytes. This is stored in size[n].
155 * 0, the objectlength is not explicitly given by the instruction
156 * and the operand is undefined. This is a case for relaxation.
157 * Reserve 4 bytes for the final object.
158 *
159 * 1, the entry contains one byte
160 * 2, the entry contains two bytes
161 * 3, the entry contains three bytes
162 * 4, the entry contains four bytes
163 * etc
164 *
165 * Furthermore, every entry has a data type identifier in type[n].
166 *
167 * 0, the entry is void, ignore it.
168 * 1, the entry is a binary number.
169 * 2, the entry is a pointer at an expression.
170 * Where expression may be as simple as a single '1',
171 * and as complicated as foo-bar+12,
172 * foo and bar may be undefined but suffixed by :{b|w|d} to
173 * control the length of the object.
174 *
175 * 3, the entry is a pointer at a bignum struct
176 *
177 *
178 * The low-order-byte coresponds to low physical memory.
179 * Obviously a FRAGment must be created for each valid disp in PART whose
180 * datalength is undefined (to bad) .
181 * The case where just the expression is undefined is less severe and is
182 * handled by fix. Here the number of bytes in the objectfile is known.
183 * With this representation we simplify the assembly and separates the
184 * machine dependent/independent parts in a more clean way (said OE)
185 */
186 \f
187 struct option opt1[] = /* restore, exit */
188 {
189 {"r0", 0x80, 0xff},
190 {"r1", 0x40, 0xff},
191 {"r2", 0x20, 0xff},
192 {"r3", 0x10, 0xff},
193 {"r4", 0x08, 0xff},
194 {"r5", 0x04, 0xff},
195 {"r6", 0x02, 0xff},
196 {"r7", 0x01, 0xff},
197 {0, 0x00, 0xff}
198 };
199 struct option opt2[] = /* save, enter */
200 {
201 {"r0", 0x01, 0xff},
202 {"r1", 0x02, 0xff},
203 {"r2", 0x04, 0xff},
204 {"r3", 0x08, 0xff},
205 {"r4", 0x10, 0xff},
206 {"r5", 0x20, 0xff},
207 {"r6", 0x40, 0xff},
208 {"r7", 0x80, 0xff},
209 {0, 0x00, 0xff}
210 };
211 struct option opt3[] = /* setcfg */
212 {
213 {"c", 0x8, 0xff},
214 {"m", 0x4, 0xff},
215 {"f", 0x2, 0xff},
216 {"i", 0x1, 0xff},
217 {0, 0x0, 0xff}
218 };
219 struct option opt4[] = /* cinv */
220 {
221 {"a", 0x4, 0xff},
222 {"i", 0x2, 0xff},
223 {"d", 0x1, 0xff},
224 {0, 0x0, 0xff}
225 };
226 struct option opt5[] = /* string inst */
227 {
228 {"b", 0x2, 0xff},
229 {"u", 0xc, 0xff},
230 {"w", 0x4, 0xff},
231 {0, 0x0, 0xff}
232 };
233 struct option opt6[] = /* plain reg ext,cvtp etc */
234 {
235 {"r0", 0x00, 0xff},
236 {"r1", 0x01, 0xff},
237 {"r2", 0x02, 0xff},
238 {"r3", 0x03, 0xff},
239 {"r4", 0x04, 0xff},
240 {"r5", 0x05, 0xff},
241 {"r6", 0x06, 0xff},
242 {"r7", 0x07, 0xff},
243 {0, 0x00, 0xff}
244 };
245
246 #if !defined(NS32032) && !defined(NS32532)
247 #define NS32032
248 #endif
249
250 struct option cpureg_532[] = /* lpr spr */
251 {
252 {"us", 0x0, 0xff},
253 {"dcr", 0x1, 0xff},
254 {"bpc", 0x2, 0xff},
255 {"dsr", 0x3, 0xff},
256 {"car", 0x4, 0xff},
257 {"fp", 0x8, 0xff},
258 {"sp", 0x9, 0xff},
259 {"sb", 0xa, 0xff},
260 {"usp", 0xb, 0xff},
261 {"cfg", 0xc, 0xff},
262 {"psr", 0xd, 0xff},
263 {"intbase", 0xe, 0xff},
264 {"mod", 0xf, 0xff},
265 {0, 0x00, 0xff}
266 };
267 struct option mmureg_532[] = /* lmr smr */
268 {
269 {"mcr", 0x9, 0xff},
270 {"msr", 0xa, 0xff},
271 {"tear", 0xb, 0xff},
272 {"ptb0", 0xc, 0xff},
273 {"ptb1", 0xd, 0xff},
274 {"ivar0", 0xe, 0xff},
275 {"ivar1", 0xf, 0xff},
276 {0, 0x0, 0xff}
277 };
278
279 struct option cpureg_032[] = /* lpr spr */
280 {
281 {"upsr", 0x0, 0xff},
282 {"fp", 0x8, 0xff},
283 {"sp", 0x9, 0xff},
284 {"sb", 0xa, 0xff},
285 {"psr", 0xd, 0xff},
286 {"intbase", 0xe, 0xff},
287 {"mod", 0xf, 0xff},
288 {0, 0x0, 0xff}
289 };
290 struct option mmureg_032[] = /* lmr smr */
291 {
292 {"bpr0", 0x0, 0xff},
293 {"bpr1", 0x1, 0xff},
294 {"pf0", 0x4, 0xff},
295 {"pf1", 0x5, 0xff},
296 {"sc", 0x8, 0xff},
297 {"msr", 0xa, 0xff},
298 {"bcnt", 0xb, 0xff},
299 {"ptb0", 0xc, 0xff},
300 {"ptb1", 0xd, 0xff},
301 {"eia", 0xf, 0xff},
302 {0, 0x0, 0xff}
303 };
304
305 #if defined(NS32532)
306 struct option *cpureg = cpureg_532;
307 struct option *mmureg = mmureg_532;
308 #else
309 struct option *cpureg = cpureg_032;
310 struct option *mmureg = mmureg_032;
311 #endif
312 \f
313
314 const pseudo_typeS md_pseudo_table[] =
315 { /* so far empty */
316 {0, 0, 0}
317 };
318
319 #define IND(x,y) (((x)<<2)+(y))
320
321 /* those are index's to relax groups in md_relax_table
322 ie it must be multiplied by 4 to point at a group start. Viz IND(x,y)
323 Se function relax_segment in write.c for more info */
324
325 #define BRANCH 1
326 #define PCREL 2
327
328 /* those are index's to entries in a relax group */
329
330 #define BYTE 0
331 #define WORD 1
332 #define DOUBLE 2
333 #define UNDEF 3
334 /* Those limits are calculated from the displacement start in memory.
335 The ns32k uses the begining of the instruction as displacement base.
336 This type of displacements could be handled here by moving the limit window
337 up or down. I choose to use an internal displacement base-adjust as there
338 are other routines that must consider this. Also, as we have two various
339 offset-adjusts in the ns32k (acb versus br/brs/jsr/bcond), two set of limits
340 would have had to be used.
341 Now we dont have to think about that. */
342
343
344 const relax_typeS md_relax_table[] =
345 {
346 {1, 1, 0, 0},
347 {1, 1, 0, 0},
348 {1, 1, 0, 0},
349 {1, 1, 0, 0},
350
351 {(63), (-64), 1, IND (BRANCH, WORD)},
352 {(8192), (-8192), 2, IND (BRANCH, DOUBLE)},
353 {0, 0, 4, 0},
354 {1, 1, 0, 0}
355 };
356
357 /* Array used to test if mode contains displacements.
358 Value is true if mode contains displacement. */
359
360 char disp_test[] =
361 {0, 0, 0, 0, 0, 0, 0, 0,
362 1, 1, 1, 1, 1, 1, 1, 1,
363 1, 1, 1, 0, 0, 1, 1, 0,
364 1, 1, 1, 1, 1, 1, 1, 1};
365
366 /* Array used to calculate max size of displacements */
367
368 char disp_size[] =
369 {4, 1, 2, 0, 4};
370 \f
371
372 #if __STDC__ == 1
373
374 static segT evaluate_expr (expressionS * resultP, char *ptr);
375 static void md_number_to_disp (char *buf, long val, int n);
376 static void md_number_to_imm (char *buf, long val, int n);
377
378 #else /* not __STDC__ */
379
380 static segT evaluate_expr ();
381 static void md_number_to_disp ();
382 static void md_number_to_imm ();
383
384 #endif /* not __STDC__ */
385
386 /* Parses a general operand into an addressingmode struct
387
388 in: pointer at operand in ascii form
389 pointer at addr_mode struct for result
390 the level of recursion. (always 0 or 1)
391
392 out: data in addr_mode struct
393 */
394 int
395 addr_mode (operand, addr_modeP, recursive_level)
396 char *operand;
397 register addr_modeS *addr_modeP;
398 int recursive_level;
399 {
400 register char *str;
401 register int i;
402 register int strl;
403 register int mode;
404 int j;
405 mode = DEFAULT; /* default */
406 addr_modeP->scaled_mode = 0; /* why not */
407 addr_modeP->scaled_reg = 0; /* if 0, not scaled index */
408 addr_modeP->float_flag = 0;
409 addr_modeP->am_size = 0;
410 addr_modeP->im_disp = 0;
411 addr_modeP->pcrel = 0; /* not set in this function */
412 addr_modeP->disp_suffix[0] = 0;
413 addr_modeP->disp_suffix[1] = 0;
414 addr_modeP->disp[0] = NULL;
415 addr_modeP->disp[1] = NULL;
416 str = operand;
417 if (str[0] == 0)
418 {
419 return (0);
420 } /* we don't want this */
421 strl = strlen (str);
422 switch (str[0])
423 {
424 /* the following three case statements controls the mode-chars
425 this is the place to ed if you want to change them */
426 #ifdef ABSOLUTE_PREFIX
427 case ABSOLUTE_PREFIX:
428 if (str[strl - 1] == ']')
429 break;
430 addr_modeP->mode = 21; /* absolute */
431 addr_modeP->disp[0] = str + 1;
432 return (-1);
433 #endif
434 #ifdef IMMEDIATE_PREFIX
435 case IMMEDIATE_PREFIX:
436 if (str[strl - 1] == ']')
437 break;
438 addr_modeP->mode = 20; /* immediate */
439 addr_modeP->disp[0] = str + 1;
440 return (-1);
441 #endif
442 case '.':
443 if (str[strl - 1] != ']')
444 {
445 switch (str[1])
446 {
447 case '-':
448 case '+':
449 if (str[2] != '\000')
450 {
451 addr_modeP->mode = 27; /* pc-relativ */
452 addr_modeP->disp[0] = str + 2;
453 return (-1);
454 }
455 default:
456 as_warn ("Invalid syntax in PC-relative addressing mode");
457 return (0);
458 }
459 }
460 break;
461 case 'e':
462 if (str[strl - 1] != ']')
463 {
464 if ((!strncmp (str, "ext(", 4)) && strl > 7)
465 { /* external */
466 addr_modeP->disp[0] = str + 4;
467 i = 0;
468 j = 2;
469 do
470 { /* disp[0]'s termination point */
471 j += 1;
472 if (str[j] == '(')
473 i++;
474 if (str[j] == ')')
475 i--;
476 }
477 while (j < strl && i != 0);
478 if (i != 0 || !(str[j + 1] == '-' || str[j + 1] == '+'))
479 {
480 as_warn ("Invalid syntax in External addressing mode");
481 return (0);
482 }
483 str[j] = '\000'; /* null terminate disp[0] */
484 addr_modeP->disp[1] = str + j + 2;
485 addr_modeP->mode = 22;
486 return (-1);
487 }
488 }
489 break;
490 default:;
491 }
492 strl = strlen (str);
493 switch (strl)
494 {
495 case 2:
496 switch (str[0])
497 {
498 case 'f':
499 addr_modeP->float_flag = 1;
500 case 'r':
501 if (str[1] >= '0' && str[1] < '8')
502 {
503 addr_modeP->mode = str[1] - '0';
504 return (-1);
505 }
506 }
507 case 3:
508 if (!strncmp (str, "tos", 3))
509 {
510 addr_modeP->mode = 23;/* TopOfStack */
511 return (-1);
512 }
513 default:;
514 }
515 if (strl > 4)
516 {
517 if (str[strl - 1] == ')')
518 {
519 if (str[strl - 2] == ')')
520 {
521 if (!strncmp (&str[strl - 5], "(fp", 3))
522 {
523 mode = 16; /* Memory Relative */
524 }
525 if (!strncmp (&str[strl - 5], "(sp", 3))
526 {
527 mode = 17;
528 }
529 if (!strncmp (&str[strl - 5], "(sb", 3))
530 {
531 mode = 18;
532 }
533 if (mode != DEFAULT)
534 { /* memory relative */
535 addr_modeP->mode = mode;
536 j = strl - 5; /* temp for end of disp[0] */
537 i = 0;
538 do
539 {
540 strl -= 1;
541 if (str[strl] == ')')
542 i++;
543 if (str[strl] == '(')
544 i--;
545 }
546 while (strl > -1 && i != 0);
547 if (i != 0)
548 {
549 as_warn ("Invalid syntax in Memory Relative addressing mode");
550 return (0);
551 }
552 addr_modeP->disp[1] = str;
553 addr_modeP->disp[0] = str + strl + 1;
554 str[j] = '\000'; /* null terminate disp[0] */
555 str[strl] = '\000'; /* null terminate disp[1] */
556 return (-1);
557 }
558 }
559 switch (str[strl - 3])
560 {
561 case 'r':
562 case 'R':
563 if (str[strl - 2] >= '0' && str[strl - 2] < '8' && str[strl - 4] == '(')
564 {
565 addr_modeP->mode = str[strl - 2] - '0' + 8;
566 addr_modeP->disp[0] = str;
567 str[strl - 4] = 0;
568 return (-1); /* reg rel */
569 }
570 default:
571 if (!strncmp (&str[strl - 4], "(fp", 3))
572 {
573 mode = 24;
574 }
575 if (!strncmp (&str[strl - 4], "(sp", 3))
576 {
577 mode = 25;
578 }
579 if (!strncmp (&str[strl - 4], "(sb", 3))
580 {
581 mode = 26;
582 }
583 if (!strncmp (&str[strl - 4], "(pc", 3))
584 {
585 mode = 27;
586 }
587 if (mode != DEFAULT)
588 {
589 addr_modeP->mode = mode;
590 addr_modeP->disp[0] = str;
591 str[strl - 4] = '\0';
592 return (-1); /* memory space */
593 }
594 }
595 }
596 /* no trailing ')' do we have a ']' ? */
597 if (str[strl - 1] == ']')
598 {
599 switch (str[strl - 2])
600 {
601 case 'b':
602 mode = 28;
603 break;
604 case 'w':
605 mode = 29;
606 break;
607 case 'd':
608 mode = 30;
609 break;
610 case 'q':
611 mode = 31;
612 break;
613 default:;
614 as_warn ("Invalid scaled-indexed mode, use (b,w,d,q)");
615 if (str[strl - 3] != ':' || str[strl - 6] != '[' ||
616 str[strl - 5] == 'r' || str[strl - 4] < '0' || str[strl - 4] > '7')
617 {
618 as_warn ("Syntax in scaled-indexed mode, use [Rn:m] where n=[0..7] m={b,w,d,q}");
619 }
620 } /* scaled index */
621 {
622 if (recursive_level > 0)
623 {
624 as_warn ("Scaled-indexed addressing mode combined with scaled-index");
625 return (0);
626 }
627 addr_modeP->am_size += 1; /* scaled index byte */
628 j = str[strl - 4] - '0'; /* store temporary */
629 str[strl - 6] = '\000'; /* nullterminate for recursive call */
630 i = addr_mode (str, addr_modeP, 1);
631 if (!i || addr_modeP->mode == 20)
632 {
633 as_warn ("Invalid or illegal addressing mode combined with scaled-index");
634 return (0);
635 }
636 addr_modeP->scaled_mode = addr_modeP->mode; /* store the inferior mode */
637 addr_modeP->mode = mode;
638 addr_modeP->scaled_reg = j + 1;
639 return (-1);
640 }
641 }
642 }
643 addr_modeP->mode = DEFAULT; /* default to whatever */
644 addr_modeP->disp[0] = str;
645 return (-1);
646 }
647 \f
648 /* ptr points at string
649 addr_modeP points at struct with result
650 This routine calls addr_mode to determine the general addr.mode of
651 the operand. When this is ready it parses the displacements for size
652 specifying suffixes and determines size of immediate mode via ns32k-opcode.
653 Also builds index bytes if needed.
654 */
655 int
656 get_addr_mode (ptr, addr_modeP)
657 char *ptr;
658 addr_modeS *addr_modeP;
659 {
660 int tmp;
661 addr_mode (ptr, addr_modeP, 0);
662 if (addr_modeP->mode == DEFAULT || addr_modeP->scaled_mode == -1)
663 {
664 /* resolve ambigious operands, this shouldn't
665 be necessary if one uses standard NSC operand
666 syntax. But the sequent compiler doesn't!!!
667 This finds a proper addressinging mode if it
668 is implicitly stated. See ns32k-opcode.h */
669 (void) evaluate_expr (&exprP, ptr); /* this call takes time Sigh! */
670 if (addr_modeP->mode == DEFAULT)
671 {
672 if (exprP.X_add_symbol || exprP.X_subtract_symbol)
673 {
674 addr_modeP->mode = desc->default_model; /* we have a label */
675 }
676 else
677 {
678 addr_modeP->mode = desc->default_modec; /* we have a constant */
679 }
680 }
681 else
682 {
683 if (exprP.X_add_symbol || exprP.X_subtract_symbol)
684 {
685 addr_modeP->scaled_mode = desc->default_model;
686 }
687 else
688 {
689 addr_modeP->scaled_mode = desc->default_modec;
690 }
691 }
692 /* must put this mess down in addr_mode to handle the scaled case better */
693 }
694 /* It appears as the sequent compiler wants an absolute when we have a
695 label without @. Constants becomes immediates besides the addr case.
696 Think it does so with local labels too, not optimum, pcrel is better.
697 When I have time I will make gas check this and select pcrel when possible
698 Actually that is trivial.
699 */
700 if (tmp = addr_modeP->scaled_reg)
701 { /* build indexbyte */
702 tmp--; /* remember regnumber comes incremented for flagpurpose */
703 tmp |= addr_modeP->scaled_mode << 3;
704 addr_modeP->index_byte = (char) tmp;
705 addr_modeP->am_size += 1;
706 }
707 if (disp_test[addr_modeP->mode])
708 { /* there was a displacement, probe for length specifying suffix*/
709 {
710 register char c;
711 register char suffix;
712 register char suffix_sub;
713 register int i;
714 register char *toP;
715 register char *fromP;
716
717 addr_modeP->pcrel = 0;
718 if (disp_test[addr_modeP->mode])
719 { /* there is a displacement */
720 if (addr_modeP->mode == 27 || addr_modeP->scaled_mode == 27)
721 { /* do we have pcrel. mode */
722 addr_modeP->pcrel = 1;
723 }
724 addr_modeP->im_disp = 1;
725 for (i = 0; i < 2; i++)
726 {
727 suffix_sub = suffix = 0;
728 if (toP = addr_modeP->disp[i])
729 { /* suffix of expression, the largest size rules */
730 fromP = toP;
731 while (c = *fromP++)
732 {
733 *toP++ = c;
734 if (c == ':')
735 {
736 switch (*fromP)
737 {
738 case '\0':
739 as_warn ("Premature end of suffix--Defaulting to d");
740 suffix = 4;
741 continue;
742 case 'b':
743 suffix_sub = 1;
744 break;
745 case 'w':
746 suffix_sub = 2;
747 break;
748 case 'd':
749 suffix_sub = 4;
750 break;
751 default:
752 as_warn ("Bad suffix after ':' use {b|w|d} Defaulting to d");
753 suffix = 4;
754 }
755 fromP++;
756 toP--; /* So we write over the ':' */
757 if (suffix < suffix_sub)
758 suffix = suffix_sub;
759 }
760 }
761 *toP = '\0';/* terminate properly */
762 addr_modeP->disp_suffix[i] = suffix;
763 addr_modeP->am_size += suffix ? suffix : 4;
764 }
765 }
766 }
767 }
768 }
769 else
770 {
771 if (addr_modeP->mode == 20)
772 { /* look in ns32k_opcode for size */
773 addr_modeP->disp_suffix[0] = addr_modeP->am_size = desc->im_size;
774 addr_modeP->im_disp = 0;
775 }
776 }
777 return addr_modeP->mode;
778 }
779
780
781 /* read an optionlist */
782 void
783 optlist (str, optionP, default_map)
784 char *str; /* the string to extract options from */
785 struct option *optionP; /* how to search the string */
786 unsigned long *default_map;/* default pattern and output */
787 {
788 register int i, j, k, strlen1, strlen2;
789 register char *patternP, *strP;
790 strlen1 = strlen (str);
791 if (strlen1 < 1)
792 {
793 as_fatal ("Very short instr to option, ie you can't do it on a NULLstr");
794 }
795 for (i = 0; optionP[i].pattern != 0; i++)
796 {
797 strlen2 = strlen (optionP[i].pattern);
798 for (j = 0; j < strlen1; j++)
799 {
800 patternP = optionP[i].pattern;
801 strP = &str[j];
802 for (k = 0; k < strlen2; k++)
803 {
804 if (*(strP++) != *(patternP++))
805 break;
806 }
807 if (k == strlen2)
808 { /* match */
809 *default_map |= optionP[i].or;
810 *default_map &= optionP[i].and;
811 }
812 }
813 }
814 }
815
816 /* search struct for symbols
817 This function is used to get the short integer form of reg names
818 in the instructions lmr, smr, lpr, spr
819 return true if str is found in list */
820
821 int
822 list_search (str, optionP, default_map)
823 char *str; /* the string to match */
824 struct option *optionP; /* list to search */
825 unsigned long *default_map;/* default pattern and output */
826 {
827 register int i;
828 for (i = 0; optionP[i].pattern != 0; i++)
829 {
830 if (!strncmp (optionP[i].pattern, str, 20))
831 { /* use strncmp to be safe */
832 *default_map |= optionP[i].or;
833 *default_map &= optionP[i].and;
834 return -1;
835 }
836 }
837 as_warn ("No such entry in list. (cpu/mmu register)");
838 return 0;
839 }
840
841 static segT
842 evaluate_expr (resultP, ptr)
843 expressionS *resultP;
844 char *ptr;
845 {
846 register char *tmp_line;
847 register segT segment;
848 tmp_line = input_line_pointer;
849 input_line_pointer = ptr;
850 segment = expression (&exprP);
851 input_line_pointer = tmp_line;
852 return (segment);
853 }
854 \f
855 /* Convert operands to iif-format and adds bitfields to the opcode.
856 Operands are parsed in such an order that the opcode is updated from
857 its most significant bit, that is when the operand need to alter the
858 opcode.
859 Be carefull not to put to objects in the same iif-slot.
860 */
861
862 void
863 encode_operand (argc, argv, operandsP, suffixP, im_size, opcode_bit_ptr)
864 int argc;
865 char **argv;
866 char *operandsP;
867 char *suffixP;
868 char im_size;
869 char opcode_bit_ptr;
870 {
871 register int i, j;
872 int pcrel, tmp, b, loop, pcrel_adjust;
873 for (loop = 0; loop < argc; loop++)
874 {
875 i = operandsP[loop << 1] - '1'; /* what operand are we supposed to work on */
876 if (i > 3)
877 as_fatal ("Internal consistency error. check ns32k-opcode.h");
878 pcrel = 0;
879 pcrel_adjust = 0;
880 tmp = 0;
881 switch (operandsP[(loop << 1) + 1])
882 {
883 case 'f': /* operand of sfsr turns out to be a nasty specialcase */
884 opcode_bit_ptr -= 5;
885 case 'F': /* 32 bit float general form */
886 case 'L': /* 64 bit float */
887 case 'Q': /* quad-word */
888 case 'B': /* byte */
889 case 'W': /* word */
890 case 'D': /* double-word */
891 case 'A': /* double-word gen-address-form ie no regs allowed */
892 get_addr_mode (argv[i], &addr_modeP);
893 iif.instr_size += addr_modeP.am_size;
894 if (opcode_bit_ptr == desc->opcode_size)
895 b = 4;
896 else
897 b = 6;
898 for (j = b; j < (b + 2); j++)
899 {
900 if (addr_modeP.disp[j - b])
901 {
902 IIF (j,
903 2,
904 addr_modeP.disp_suffix[j - b],
905 (unsigned long) addr_modeP.disp[j - b],
906 0,
907 addr_modeP.pcrel,
908 iif.instr_size - addr_modeP.am_size, /* this aint used (now) */
909 addr_modeP.im_disp,
910 IND (BRANCH, BYTE),
911 NULL,
912 addr_modeP.scaled_reg ? addr_modeP.scaled_mode : addr_modeP.mode,
913 0);
914 }
915 }
916 opcode_bit_ptr -= 5;
917 iif.iifP[1].object |= ((long) addr_modeP.mode) << opcode_bit_ptr;
918 if (addr_modeP.scaled_reg)
919 {
920 j = b / 2;
921 IIF (j, 1, 1, (unsigned long) addr_modeP.index_byte, 0, 0, 0, 0, 0, NULL, -1, 0);
922 }
923 break;
924 case 'b': /* multiple instruction disp */
925 freeptr++; /* OVE:this is an useful hack */
926 tmp = (int) sprintf (freeptr,
927 "((%s-1)*%d)\000",
928 argv[i], desc->im_size);
929 argv[i] = freeptr;
930 freeptr = (char *) tmp;
931 pcrel -= 1; /* make pcrel 0 inspite of what case 'p': wants */
932 /* fall thru */
933 case 'p': /* displacement - pc relative addressing */
934 pcrel += 1;
935 /* fall thru */
936 case 'd': /* displacement */
937 iif.instr_size += suffixP[i] ? suffixP[i] : 4;
938 IIF (12, 2, suffixP[i], (unsigned long) argv[i], 0,
939 pcrel, pcrel_adjust, 1, IND (BRANCH, BYTE), NULL, -1, 0);
940 break;
941 case 'H': /* sequent-hack: the linker wants a bit set when bsr */
942 pcrel = 1;
943 iif.instr_size += suffixP[i] ? suffixP[i] : 4;
944 IIF (12, 2, suffixP[i], (unsigned long) argv[i], 0,
945 pcrel, pcrel_adjust, 1, IND (BRANCH, BYTE), NULL, -1, 1);
946 break;
947 case 'q': /* quick */
948 opcode_bit_ptr -= 4;
949 IIF (11, 2, 42, (unsigned long) argv[i], 0, 0, 0, 0, 0,
950 bit_fix_new (4, opcode_bit_ptr, -8, 7, 0, 1, 0), -1, 0);
951 break;
952 case 'r': /* register number (3 bits) */
953 list_search (argv[i], opt6, &tmp);
954 opcode_bit_ptr -= 3;
955 iif.iifP[1].object |= tmp << opcode_bit_ptr;
956 break;
957 case 'O': /* setcfg instruction optionslist */
958 optlist (argv[i], opt3, &tmp);
959 opcode_bit_ptr -= 4;
960 iif.iifP[1].object |= tmp << 15;
961 break;
962 case 'C': /* cinv instruction optionslist */
963 optlist (argv[i], opt4, &tmp);
964 opcode_bit_ptr -= 4;
965 iif.iifP[1].object |= tmp << 15; /*insert the regtype in opcode */
966 break;
967 case 'S': /* stringinstruction optionslist */
968 optlist (argv[i], opt5, &tmp);
969 opcode_bit_ptr -= 4;
970 iif.iifP[1].object |= tmp << 15;
971 break;
972 case 'u':
973 case 'U': /* registerlist */
974 IIF (10, 1, 1, 0, 0, 0, 0, 0, 0, NULL, -1, 0);
975 switch (operandsP[(i << 1) + 1])
976 {
977 case 'u': /* restore, exit */
978 optlist (argv[i], opt1, &iif.iifP[10].object);
979 break;
980 case 'U': /* save,enter */
981 optlist (argv[i], opt2, &iif.iifP[10].object);
982 break;
983 }
984 iif.instr_size += 1;
985 break;
986 case 'M': /* mmu register */
987 list_search (argv[i], mmureg, &tmp);
988 opcode_bit_ptr -= 4;
989 iif.iifP[1].object |= tmp << opcode_bit_ptr;
990 break;
991 case 'P': /* cpu register */
992 list_search (argv[i], cpureg, &tmp);
993 opcode_bit_ptr -= 4;
994 iif.iifP[1].object |= tmp << opcode_bit_ptr;
995 break;
996 case 'g': /* inss exts */
997 iif.instr_size += 1; /* 1 byte is allocated after the opcode */
998 IIF (10, 2, 1,
999 (unsigned long) argv[i], /* i always 2 here */
1000 0, 0, 0, 0, 0,
1001 bit_fix_new (3, 5, 0, 7, 0, 0, 0), /* a bit_fix is targeted to the byte */
1002 -1, 0);
1003 case 'G':
1004 IIF (11, 2, 42,
1005 (unsigned long) argv[i], /* i always 3 here */
1006 0, 0, 0, 0, 0,
1007 bit_fix_new (5, 0, 1, 32, -1, 0, -1), -1, 0);
1008 break;
1009 case 'i':
1010 iif.instr_size += 1;
1011 b = 2 + i; /* put the extension byte after opcode */
1012 IIF (b, 2, 1, 0, 0, 0, 0, 0, 0, 0, -1, 0);
1013 default:
1014 as_fatal ("Bad opcode-table-option, check in file ns32k-opcode.h");
1015 }
1016 }
1017 }
1018 \f
1019 /* in: instruction line
1020 out: internal structure of instruction
1021 that has been prepared for direct conversion to fragment(s) and
1022 fixes in a systematical fashion
1023 Return-value = recursive_level
1024 */
1025 /* build iif of one assembly text line */
1026 int
1027 parse (line, recursive_level)
1028 char *line;
1029 int recursive_level;
1030 {
1031 register char *lineptr, c, suffix_separator;
1032 register int i;
1033 int argc, arg_type;
1034 char sqr, sep;
1035 char suffix[MAX_ARGS], *argv[MAX_ARGS]; /* no more than 4 operands */
1036 if (recursive_level <= 0)
1037 { /* called from md_assemble */
1038 for (lineptr = line; (*lineptr) != '\0' && (*lineptr) != ' '; lineptr++);
1039 c = *lineptr;
1040 *lineptr = '\0';
1041 if (!(desc = (struct ns32k_opcode *) hash_find (inst_hash_handle, line)))
1042 {
1043 as_fatal ("No such opcode");
1044 }
1045 *lineptr = c;
1046 }
1047 else
1048 {
1049 lineptr = line;
1050 }
1051 argc = 0;
1052 if (*desc->operands)
1053 {
1054 if (*lineptr++ != '\0')
1055 {
1056 sqr = '[';
1057 sep = ',';
1058 while (*lineptr != '\0')
1059 {
1060 if (desc->operands[argc << 1])
1061 {
1062 suffix[argc] = 0;
1063 arg_type = desc->operands[(argc << 1) + 1];
1064 switch (arg_type)
1065 {
1066 case 'd':
1067 case 'b':
1068 case 'p':
1069 case 'H': /* the operand is supposed to be a displacement */
1070 /* Hackwarning: do not forget to update the 4 cases above when editing ns32k-opcode.h */
1071 suffix_separator = ':';
1072 break;
1073 default:
1074 suffix_separator = '\255'; /* if this char occurs we loose */
1075 }
1076 suffix[argc] = 0; /* 0 when no ':' is encountered */
1077 argv[argc] = freeptr;
1078 *freeptr = '\0';
1079 while ((c = *lineptr) != '\0' && c != sep)
1080 {
1081 if (c == sqr)
1082 {
1083 if (sqr == '[')
1084 {
1085 sqr = ']';
1086 sep = '\0';
1087 }
1088 else
1089 {
1090 sqr = '[';
1091 sep = ',';
1092 }
1093 }
1094 if (c == suffix_separator)
1095 { /* ':' - label/suffix separator */
1096 switch (lineptr[1])
1097 {
1098 case 'b':
1099 suffix[argc] = 1;
1100 break;
1101 case 'w':
1102 suffix[argc] = 2;
1103 break;
1104 case 'd':
1105 suffix[argc] = 4;
1106 break;
1107 default:
1108 as_warn ("Bad suffix, defaulting to d");
1109 suffix[argc] = 4;
1110 if (lineptr[1] == '\0' || lineptr[1] == sep)
1111 {
1112 lineptr += 1;
1113 continue;
1114 }
1115 }
1116 lineptr += 2;
1117 continue;
1118 }
1119 *freeptr++ = c;
1120 lineptr++;
1121 }
1122 *freeptr++ = '\0';
1123 argc += 1;
1124 if (*lineptr == '\0')
1125 continue;
1126 lineptr += 1;
1127 }
1128 else
1129 {
1130 as_fatal ("Too many operands passed to instruction");
1131 }
1132 }
1133 }
1134 }
1135 if (argc != strlen (desc->operands) / 2)
1136 {
1137 if (strlen (desc->default_args))
1138 { /* we can apply default, dont goof */
1139 if (parse (desc->default_args, 1) != 1)
1140 { /* check error in default */
1141 as_fatal ("Wrong numbers of operands in default, check ns32k-opcodes.h");
1142 }
1143 }
1144 else
1145 {
1146 as_fatal ("Wrong number of operands");
1147 }
1148
1149 }
1150 for (i = 0; i < IIF_ENTRIES; i++)
1151 {
1152 iif.iifP[i].type = 0; /* mark all entries as void*/
1153 }
1154
1155 /* build opcode iif-entry */
1156 iif.instr_size = desc->opcode_size / 8;
1157 IIF (1, 1, iif.instr_size, desc->opcode_seed, 0, 0, 0, 0, 0, 0, -1, 0);
1158
1159 /* this call encodes operands to iif format */
1160 if (argc)
1161 {
1162 encode_operand (argc,
1163 argv,
1164 &desc->operands[0],
1165 &suffix[0],
1166 desc->im_size,
1167 desc->opcode_size);
1168 }
1169 return recursive_level;
1170 }
1171 \f
1172
1173 /* Convert iif to fragments.
1174 From this point we start to dribble with functions in other files than
1175 this one.(Except hash.c) So, if it's possible to make an iif for an other
1176 CPU, you don't need to know what frags, relax, obstacks, etc is in order
1177 to port this assembler. You only need to know if it's possible to reduce
1178 your cpu-instruction to iif-format (takes some work) and adopt the other
1179 md_? parts according to given instructions
1180 Note that iif was invented for the clean ns32k`s architecure.
1181 */
1182 void
1183 convert_iif ()
1184 {
1185 int i;
1186 int j;
1187 fragS *inst_frag;
1188 char *inst_offset;
1189 char **inst_opcode;
1190 char *memP;
1191 segT segment;
1192 int l;
1193 int k;
1194 int rem_size; /* count the remaining bytes of instruction */
1195 char type;
1196 char size = 0;
1197 int size_so_far = 0; /* used to calculate pcrel_adjust */
1198
1199 rem_size = iif.instr_size;
1200 memP = frag_more (iif.instr_size); /* make sure we have enough bytes for instruction */
1201 inst_opcode = memP;
1202 inst_offset = (char *) (memP - frag_now->fr_literal);
1203 inst_frag = frag_now;
1204 for (i = 0; i < IIF_ENTRIES; i++)
1205 {
1206 if (type = iif.iifP[i].type)
1207 { /* the object exist, so handle it */
1208 switch (size = iif.iifP[i].size)
1209 {
1210 case 42:
1211 size = 0; /* it's a bitfix that operates on an existing object*/
1212 if (iif.iifP[i].bit_fixP->fx_bit_base)
1213 { /* expand fx_bit_base to point at opcode */
1214 iif.iifP[i].bit_fixP->fx_bit_base = (long) inst_opcode;
1215 }
1216 case 8: /* bignum or doublefloat */
1217 memset (memP, '\0', 8);
1218 case 1:
1219 case 2:
1220 case 3:
1221 case 4: /* the final size in objectmemory is known */
1222 j = (unsigned long) iif.iifP[i].bit_fixP;
1223 switch (type)
1224 {
1225 case 1: /* the object is pure binary */
1226 if (j || iif.iifP[i].pcrel)
1227 {
1228 fix_new_ns32k (frag_now,
1229 (long) (memP - frag_now->fr_literal),
1230 size,
1231 0,
1232 0,
1233 iif.iifP[i].object,
1234 iif.iifP[i].pcrel,
1235 (char) size_so_far, /*iif.iifP[i].pcrel_adjust,*/
1236 iif.iifP[i].im_disp,
1237 j,
1238 iif.iifP[i].bsr); /* sequent hack */
1239 }
1240 else
1241 { /* good, just put them bytes out */
1242 switch (iif.iifP[i].im_disp)
1243 {
1244 case 0:
1245 md_number_to_chars (memP, iif.iifP[i].object, size);
1246 break;
1247 case 1:
1248 md_number_to_disp (memP, iif.iifP[i].object, size);
1249 break;
1250 default:
1251 as_fatal ("iif convert internal pcrel/binary");
1252 }
1253 }
1254 memP += size;
1255 rem_size -= size;
1256 break;
1257 case 2: /* the object is a pointer at an expression, so unpack
1258 it, note that bignums may result from the expression
1259 */
1260 if ((segment = evaluate_expr (&exprP, (char *) iif.iifP[i].object)) == SEG_BIG || size == 8)
1261 {
1262 if ((k = exprP.X_add_number) > 0)
1263 { /* we have a bignum ie a quad */
1264 /* this can only happens in a long suffixed instruction */
1265 memset (memP, '\0', size); /* size normally is 8 */
1266 if (k * 2 > size)
1267 as_warn ("Bignum too big for long");
1268 if (k == 3)
1269 memP += 2;
1270 for (l = 0; k > 0; k--, l += 2)
1271 {
1272 md_number_to_chars (memP + l, generic_bignum[l >> 1], sizeof (LITTLENUM_TYPE));
1273 }
1274 }
1275 else
1276 { /* flonum */
1277 LITTLENUM_TYPE words[4];
1278
1279 switch (size)
1280 {
1281 case 4:
1282 gen_to_words (words, 2, 8);
1283 md_number_to_imm (memP, (long) words[0], sizeof (LITTLENUM_TYPE));
1284 md_number_to_imm (memP + sizeof (LITTLENUM_TYPE), (long) words[1], sizeof (LITTLENUM_TYPE));
1285 break;
1286 case 8:
1287 gen_to_words (words, 4, 11);
1288 md_number_to_imm (memP, (long) words[0], sizeof (LITTLENUM_TYPE));
1289 md_number_to_imm (memP + sizeof (LITTLENUM_TYPE), (long) words[1], sizeof (LITTLENUM_TYPE));
1290 md_number_to_imm (memP + 2 * sizeof (LITTLENUM_TYPE), (long) words[2], sizeof (LITTLENUM_TYPE));
1291 md_number_to_imm (memP + 3 * sizeof (LITTLENUM_TYPE), (long) words[3], sizeof (LITTLENUM_TYPE));
1292 break;
1293 }
1294 }
1295 memP += size;
1296 rem_size -= size;
1297 break;
1298 }
1299 if (j ||
1300 exprP.X_add_symbol ||
1301 exprP.X_subtract_symbol ||
1302 iif.iifP[i].pcrel)
1303 { /* fixit */
1304 /* the expression was undefined due to an undefined label */
1305 /* create a fix so we can fix the object later */
1306 exprP.X_add_number += iif.iifP[i].object_adjust;
1307 fix_new_ns32k (frag_now,
1308 (long) (memP - frag_now->fr_literal),
1309 size,
1310 exprP.X_add_symbol,
1311 exprP.X_subtract_symbol,
1312 exprP.X_add_number,
1313 iif.iifP[i].pcrel,
1314 (char) size_so_far, /*iif.iifP[i].pcrel_adjust,*/
1315 iif.iifP[i].im_disp,
1316 j,
1317 iif.iifP[i].bsr); /* sequent hack */
1318
1319 }
1320 else
1321 { /* good, just put them bytes out */
1322 switch (iif.iifP[i].im_disp)
1323 {
1324 case 0:
1325 md_number_to_imm (memP, exprP.X_add_number, size);
1326 break;
1327 case 1:
1328 md_number_to_disp (memP, exprP.X_add_number, size);
1329 break;
1330 default:
1331 as_fatal ("iif convert internal pcrel/pointer");
1332 }
1333 }
1334 memP += size;
1335 rem_size -= size;
1336 break;
1337 default:
1338 as_fatal ("Internal logic error in iif.iifP[n].type");
1339 }
1340 break;
1341 case 0: /* To bad, the object may be undefined as far as its final
1342 nsize in object memory is concerned. The size of the object
1343 in objectmemory is not explicitly given.
1344 If the object is defined its length can be determined and
1345 a fix can replace the frag.
1346 */
1347 {
1348 int temp;
1349 segment = evaluate_expr (&exprP, (char *) iif.iifP[i].object);
1350 if ((exprP.X_add_symbol || exprP.X_subtract_symbol) &&
1351 !iif.iifP[i].pcrel)
1352 { /* OVE: hack, clamp to 4 bytes */
1353 size = 4; /* we dont wan't to frag this, use 4 so it reaches */
1354 fix_new_ns32k (frag_now,
1355 (long) (memP - frag_now->fr_literal),
1356 size,
1357 exprP.X_add_symbol,
1358 exprP.X_subtract_symbol,
1359 exprP.X_add_number,
1360 0, /* never iif.iifP[i].pcrel, */
1361 (char) size_so_far, /*iif.iifP[i].pcrel_adjust,*/
1362 1, /* always iif.iifP[i].im_disp, */
1363 0, 0);
1364 memP += size;
1365 rem_size -= 4;
1366 break; /* exit this absolute hack */
1367 }
1368
1369 if (exprP.X_add_symbol || exprP.X_subtract_symbol)
1370 { /* frag it */
1371 if (exprP.X_subtract_symbol)
1372 { /* We cant relax this case */
1373 as_fatal ("Can't relax difference");
1374 }
1375 else
1376 {
1377 /* at this stage we must undo some of the effect caused
1378 by frag_more, ie we must make sure that frag_var causes
1379 frag_new to creat a valid fix-size in the frag it`s closing
1380 */
1381 temp = -(rem_size - 4);
1382 obstack_blank_fast (&frags, temp);
1383 /* we rewind none, some or all of the requested size we
1384 requested by the first frag_more for this iif chunk.
1385 Note: that we allocate 4 bytes to an object we NOT YET
1386 know the size of, thus rem_size-4.
1387 */
1388 (void) frag_variant (rs_machine_dependent,
1389 4,
1390 0,
1391 IND (BRANCH, UNDEF), /* expecting the worst */
1392 exprP.X_add_symbol,
1393 exprP.X_add_number,
1394 (char *) inst_opcode,
1395 (char) size_so_far, /*iif.iifP[i].pcrel_adjust);*/
1396 iif.iifP[i].bsr); /* sequent linker hack */
1397 rem_size -= 4;
1398 if (rem_size > 0)
1399 {
1400 memP = frag_more (rem_size);
1401 }
1402 }
1403 }
1404 else
1405 { /* Double work, this is done in md_number_to_disp */
1406 /* exprP.X_add_number; what was this supposed to be?
1407 xoxorich. */
1408 if (-64 <= exprP.X_add_number && exprP.X_add_number <= 63)
1409 {
1410 size = 1;
1411 }
1412 else
1413 {
1414 if (-8192 <= exprP.X_add_number && exprP.X_add_number <= 8191)
1415 {
1416 size = 2;
1417 }
1418 else
1419 {
1420 if (-0x1f000000 <= exprP.X_add_number &&
1421 exprP.X_add_number <= 0x1fffffff)
1422 /* if (-0x40000000<=exprP.X_add_number &&
1423 exprP.X_add_number<=0x3fffffff) */
1424 {
1425 size = 4;
1426 }
1427 else
1428 {
1429 as_warn ("Displacement to large for :d");
1430 size = 4;
1431 }
1432 }
1433 }
1434 /* rewind the bytes not used */
1435 temp = -(4 - size);
1436 md_number_to_disp (memP, exprP.X_add_number, size);
1437 obstack_blank_fast (&frags, temp);
1438 memP += size;
1439 rem_size -= 4; /* we allocated this amount */
1440 }
1441 }
1442 break;
1443 default:
1444 as_fatal ("Internal logic error in iif.iifP[].type");
1445 }
1446 size_so_far += size;
1447 size = 0;
1448 }
1449 }
1450 }
1451 \f
1452 void
1453 md_assemble (line)
1454 char *line;
1455 {
1456 freeptr = freeptr_static;
1457 parse (line, 0); /* explode line to more fix form in iif */
1458 convert_iif (); /* convert iif to frags, fix's etc */
1459 #ifdef SHOW_NUM
1460 printf (" \t\t\t%s\n", line);
1461 #endif
1462 }
1463
1464
1465 void
1466 md_begin ()
1467 {
1468 /* build a hashtable of the instructions */
1469 register const struct ns32k_opcode *ptr;
1470 register char *stat;
1471 inst_hash_handle = hash_new ();
1472 for (ptr = ns32k_opcodes; ptr < endop; ptr++)
1473 {
1474 if (*(stat = hash_insert (inst_hash_handle, ptr->name, (char *) ptr)))
1475 {
1476 as_fatal ("Can't hash %s: %s", ptr->name, stat); /*fatal*/
1477 exit (0);
1478 }
1479 }
1480 freeptr_static = (char *) malloc (PRIVATE_SIZE); /* some private space please! */
1481 }
1482
1483
1484 void
1485 md_end ()
1486 {
1487 free (freeptr_static);
1488 }
1489
1490 /* Must be equal to MAX_PRECISON in atof-ieee.c */
1491 #define MAX_LITTLENUMS 6
1492
1493 /* Turn the string pointed to by litP into a floating point constant of type
1494 type, and emit the appropriate bytes. The number of LITTLENUMS emitted
1495 is stored in *sizeP . An error message is returned, or NULL on OK.
1496 */
1497 char *
1498 md_atof (type, litP, sizeP)
1499 char type;
1500 char *litP;
1501 int *sizeP;
1502 {
1503 int prec;
1504 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1505 LITTLENUM_TYPE *wordP;
1506 char *t;
1507
1508 switch (type)
1509 {
1510 case 'f':
1511 prec = 2;
1512 break;
1513
1514 case 'd':
1515 prec = 4;
1516 break;
1517 default:
1518 *sizeP = 0;
1519 return "Bad call to MD_ATOF()";
1520 }
1521 t = atof_ns32k (input_line_pointer, type, words);
1522 if (t)
1523 input_line_pointer = t;
1524
1525 *sizeP = prec * sizeof (LITTLENUM_TYPE);
1526 for (wordP = words + prec; prec--;)
1527 {
1528 md_number_to_chars (litP, (long) (*--wordP), sizeof (LITTLENUM_TYPE));
1529 litP += sizeof (LITTLENUM_TYPE);
1530 }
1531 return ""; /* Someone should teach Dean about null pointers */
1532 }
1533 \f
1534 /* Convert number to chars in correct order */
1535
1536 void
1537 md_number_to_chars (buf, value, nbytes)
1538 char *buf;
1539 long value;
1540 int nbytes;
1541 {
1542 while (nbytes--)
1543 {
1544 #ifdef SHOW_NUM
1545 printf ("%x ", value & 0xff);
1546 #endif
1547 *buf++ = value; /* Lint wants & MASK_CHAR. */
1548 value >>= BITS_PER_CHAR;
1549 }
1550 } /* md_number_to_chars() */
1551
1552
1553 /* This is a variant of md_numbers_to_chars. The reason for its' existence
1554 is the fact that ns32k uses Huffman coded displacements. This implies
1555 that the bit order is reversed in displacements and that they are prefixed
1556 with a size-tag.
1557
1558 binary: msb -> lsb
1559 0xxxxxxx byte
1560 10xxxxxx xxxxxxxx word
1561 11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx double word
1562
1563 This must be taken care of and we do it here!
1564 */
1565 static void
1566 md_number_to_disp (buf, val, n)
1567 char *buf;
1568 long val;
1569 char n;
1570 {
1571 switch (n)
1572 {
1573 case 1:
1574 if (val < -64 || val > 63)
1575 as_warn ("Byte displacement out of range. line number not valid");
1576 val &= 0x7f;
1577 #ifdef SHOW_NUM
1578 printf ("%x ", val & 0xff);
1579 #endif
1580 *buf++ = val;
1581 break;
1582 case 2:
1583 if (val < -8192 || val > 8191)
1584 as_warn ("Word displacement out of range. line number not valid");
1585 val &= 0x3fff;
1586 val |= 0x8000;
1587 #ifdef SHOW_NUM
1588 printf ("%x ", val >> 8 & 0xff);
1589 #endif
1590 *buf++ = (val >> 8);
1591 #ifdef SHOW_NUM
1592 printf ("%x ", val & 0xff);
1593 #endif
1594 *buf++ = val;
1595 break;
1596 case 4:
1597 if (val < -0x1f000000 || val >= 0x20000000)
1598 /* if (val < -0x20000000 || val >= 0x20000000) */
1599 as_warn ("Double word displacement out of range");
1600 val |= 0xc0000000;
1601 #ifdef SHOW_NUM
1602 printf ("%x ", val >> 24 & 0xff);
1603 #endif
1604 *buf++ = (val >> 24);
1605 #ifdef SHOW_NUM
1606 printf ("%x ", val >> 16 & 0xff);
1607 #endif
1608 *buf++ = (val >> 16);
1609 #ifdef SHOW_NUM
1610 printf ("%x ", val >> 8 & 0xff);
1611 #endif
1612 *buf++ = (val >> 8);
1613 #ifdef SHOW_NUM
1614 printf ("%x ", val & 0xff);
1615 #endif
1616 *buf++ = val;
1617 break;
1618 default:
1619 as_fatal ("Internal logic error. line %s, file \"%s\"", __LINE__, __FILE__);
1620 }
1621 }
1622
1623 static void
1624 md_number_to_imm (buf, val, n)
1625 char *buf;
1626 long val;
1627 char n;
1628 {
1629 switch (n)
1630 {
1631 case 1:
1632 #ifdef SHOW_NUM
1633 printf ("%x ", val & 0xff);
1634 #endif
1635 *buf++ = val;
1636 break;
1637 case 2:
1638 #ifdef SHOW_NUM
1639 printf ("%x ", val >> 8 & 0xff);
1640 #endif
1641 *buf++ = (val >> 8);
1642 #ifdef SHOW_NUM
1643 printf ("%x ", val & 0xff);
1644 #endif
1645 *buf++ = val;
1646 break;
1647 case 4:
1648 #ifdef SHOW_NUM
1649 printf ("%x ", val >> 24 & 0xff);
1650 #endif
1651 *buf++ = (val >> 24);
1652 #ifdef SHOW_NUM
1653 printf ("%x ", val >> 16 & 0xff);
1654 #endif
1655 *buf++ = (val >> 16);
1656 #ifdef SHOW_NUM
1657 printf ("%x ", val >> 8 & 0xff);
1658 #endif
1659 *buf++ = (val >> 8);
1660 #ifdef SHOW_NUM
1661 printf ("%x ", val & 0xff);
1662 #endif
1663 *buf++ = val;
1664 break;
1665 default:
1666 as_fatal ("Internal logic error. line %s, file \"%s\"", __LINE__, __FILE__);
1667 }
1668 }
1669
1670 /* Translate internal representation of relocation info into target format.
1671
1672 OVE: on a ns32k the twiddling continues at an even deeper level
1673 here we have to distinguish between displacements and immediates.
1674
1675 The sequent has a bit for this. It also has a bit for relocobjects that
1676 points at the target for a bsr (BranchSubRoutine) !?!?!?!
1677
1678 This md_ri.... is tailored for sequent.
1679 */
1680
1681 #ifdef comment
1682 void
1683 md_ri_to_chars (the_bytes, ri)
1684 char *the_bytes;
1685 struct reloc_info_generic *ri;
1686 {
1687 if (ri->r_bsr)
1688 {
1689 ri->r_pcrel = 0;
1690 } /* sequent seems to want this */
1691 md_number_to_chars (the_bytes, ri->r_address, sizeof (ri->r_address));
1692 md_number_to_chars (the_bytes + 4, ((long) (ri->r_symbolnum)
1693 | (long) (ri->r_pcrel << 24)
1694 | (long) (ri->r_length << 25)
1695 | (long) (ri->r_extern << 27)
1696 | (long) (ri->r_bsr << 28)
1697 | (long) (ri->r_disp << 29)),
1698 4);
1699 /* the first and second md_number_to_chars never overlaps (32bit cpu case) */
1700 }
1701
1702 #endif /* comment */
1703
1704 #ifdef OBJ_AOUT
1705 void
1706 tc_aout_fix_to_chars (where, fixP, segment_address_in_file)
1707 char *where;
1708 struct fix *fixP;
1709 relax_addressT segment_address_in_file;
1710 {
1711 /*
1712 * In: length of relocation (or of address) in chars: 1, 2 or 4.
1713 * Out: GNU LD relocation length code: 0, 1, or 2.
1714 */
1715
1716 static unsigned char nbytes_r_length[] =
1717 {42, 0, 1, 42, 2};
1718 long r_symbolnum;
1719
1720 know (fixP->fx_addsy != NULL);
1721
1722 md_number_to_chars (where,
1723 fixP->fx_frag->fr_address + fixP->fx_where - segment_address_in_file,
1724 4);
1725
1726 r_symbolnum = (S_IS_DEFINED (fixP->fx_addsy)
1727 ? S_GET_TYPE (fixP->fx_addsy)
1728 : fixP->fx_addsy->sy_number);
1729
1730 md_number_to_chars (where,
1731 ((long) (r_symbolnum)
1732 | (long) (fixP->fx_pcrel << 24)
1733 | (long) (nbytes_r_length[fixP->fx_size] << 25)
1734 | (long) ((!S_IS_DEFINED (fixP->fx_addsy)) << 27)
1735 | (long) (fixP->fx_bsr << 28)
1736 | (long) (fixP->fx_im_disp << 29)),
1737 4);
1738
1739 return;
1740 } /* tc_aout_fix_to_chars() */
1741
1742 #endif /* OBJ_AOUT */
1743
1744 /* fast bitfiddling support */
1745 /* mask used to zero bitfield before oring in the true field */
1746
1747 static unsigned long l_mask[] =
1748 {
1749 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
1750 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
1751 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
1752 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
1753 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
1754 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
1755 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
1756 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
1757 };
1758 static unsigned long r_mask[] =
1759 {
1760 0x00000000, 0x00000001, 0x00000003, 0x00000007,
1761 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
1762 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
1763 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
1764 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
1765 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
1766 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
1767 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
1768 };
1769 #define MASK_BITS 31
1770 /* Insert bitfield described by field_ptr and val at buf
1771 This routine is written for modification of the first 4 bytes pointed
1772 to by buf, to yield speed.
1773 The ifdef stuff is for selection between a ns32k-dependent routine
1774 and a general version. (My advice: use the general version!)
1775 */
1776
1777 static void
1778 md_number_to_field (buf, val, field_ptr)
1779 register char *buf;
1780 register long val;
1781 register bit_fixS *field_ptr;
1782 {
1783 register unsigned long object;
1784 register unsigned long mask;
1785 /* define ENDIAN on a ns32k machine */
1786 #ifdef ENDIAN
1787 register unsigned long *mem_ptr;
1788 #else
1789 register char *mem_ptr;
1790 #endif
1791 if (field_ptr->fx_bit_min <= val && val <= field_ptr->fx_bit_max)
1792 {
1793 #ifdef ENDIAN
1794 if (field_ptr->fx_bit_base)
1795 { /* override buf */
1796 mem_ptr = (unsigned long *) field_ptr->fx_bit_base;
1797 }
1798 else
1799 {
1800 mem_ptr = (unsigned long *) buf;
1801 }
1802 #else
1803 if (field_ptr->fx_bit_base)
1804 { /* override buf */
1805 mem_ptr = (char *) field_ptr->fx_bit_base;
1806 }
1807 else
1808 {
1809 mem_ptr = buf;
1810 }
1811 #endif
1812 mem_ptr += field_ptr->fx_bit_base_adj;
1813 #ifdef ENDIAN /* we have a nice ns32k machine with lowbyte at low-physical mem */
1814 object = *mem_ptr; /* get some bytes */
1815 #else /* OVE Goof! the machine is a m68k or dito */
1816 /* That takes more byte fiddling */
1817 object = 0;
1818 object |= mem_ptr[3] & 0xff;
1819 object <<= 8;
1820 object |= mem_ptr[2] & 0xff;
1821 object <<= 8;
1822 object |= mem_ptr[1] & 0xff;
1823 object <<= 8;
1824 object |= mem_ptr[0] & 0xff;
1825 #endif
1826 mask = 0;
1827 mask |= (r_mask[field_ptr->fx_bit_offset]);
1828 mask |= (l_mask[field_ptr->fx_bit_offset + field_ptr->fx_bit_size]);
1829 object &= mask;
1830 val += field_ptr->fx_bit_add;
1831 object |= ((val << field_ptr->fx_bit_offset) & (mask ^ 0xffffffff));
1832 #ifdef ENDIAN
1833 *mem_ptr = object;
1834 #else
1835 mem_ptr[0] = (char) object;
1836 object >>= 8;
1837 mem_ptr[1] = (char) object;
1838 object >>= 8;
1839 mem_ptr[2] = (char) object;
1840 object >>= 8;
1841 mem_ptr[3] = (char) object;
1842 #endif
1843 }
1844 else
1845 {
1846 as_warn ("Bit field out of range");
1847 }
1848 }
1849
1850 /* Apply a fixS (fixup of an instruction or data that we didn't have
1851 enough info to complete immediately) to the data in a frag.
1852
1853 On the ns32k, everything is in a different format, so we have broken
1854 out separate functions for each kind of thing we could be fixing.
1855 They all get called from here. */
1856
1857 void
1858 md_apply_fix (fixP, val)
1859 fixS *fixP;
1860 long val;
1861 {
1862 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
1863
1864 if (fixP->fx_bit_fixP)
1865 { /* Bitfields to fix, sigh */
1866 md_number_to_field (buf, val, fixP->fx_bit_fixP);
1867 }
1868 else
1869 switch (fixP->fx_im_disp)
1870 {
1871
1872 case 0: /* Immediate field */
1873 md_number_to_imm (buf, val, fixP->fx_size);
1874 break;
1875
1876 case 1: /* Displacement field */
1877 md_number_to_disp (buf,
1878 fixP->fx_pcrel ? val + fixP->fx_pcrel_adjust : val,
1879 fixP->fx_size);
1880 break;
1881
1882 case 2: /* Pointer in a data object */
1883 md_number_to_chars (buf, val, fixP->fx_size);
1884 break;
1885 }
1886 }
1887 \f
1888 /* Convert a relaxed displacement to ditto in final output */
1889
1890 void
1891 md_convert_frag (headers, fragP)
1892 object_headers *headers;
1893 register fragS *fragP;
1894 {
1895 long disp;
1896 long ext = 0;
1897
1898 /* Address in gas core of the place to store the displacement. */
1899 register char *buffer_address = fragP->fr_fix + fragP->fr_literal;
1900 /* Address in object code of the displacement. */
1901 register int object_address = fragP->fr_fix + fragP->fr_address;
1902
1903 know (fragP->fr_symbol);
1904
1905 /* The displacement of the address, from current location. */
1906 disp = (S_GET_VALUE (fragP->fr_symbol) + fragP->fr_offset) - object_address;
1907 disp += fragP->fr_pcrel_adjust;
1908
1909 switch (fragP->fr_subtype)
1910 {
1911 case IND (BRANCH, BYTE):
1912 ext = 1;
1913 break;
1914 case IND (BRANCH, WORD):
1915 ext = 2;
1916 break;
1917 case IND (BRANCH, DOUBLE):
1918 ext = 4;
1919 break;
1920 }
1921 if (ext)
1922 {
1923 md_number_to_disp (buffer_address, (long) disp, (int) ext);
1924 fragP->fr_fix += ext;
1925 }
1926 }
1927
1928
1929
1930 /* This function returns the estimated size a variable object will occupy,
1931 one can say that we tries to guess the size of the objects before we
1932 actually know it */
1933
1934 int
1935 md_estimate_size_before_relax (fragP, segment)
1936 register fragS *fragP;
1937 segT segment;
1938 {
1939 int old_fix;
1940 old_fix = fragP->fr_fix;
1941 switch (fragP->fr_subtype)
1942 {
1943 case IND (BRANCH, UNDEF):
1944 if (S_GET_SEGMENT (fragP->fr_symbol) == segment)
1945 {
1946 /* the symbol has been assigned a value */
1947 fragP->fr_subtype = IND (BRANCH, BYTE);
1948 }
1949 else
1950 {
1951 /* we don't relax symbols defined in an other segment
1952 the thing to do is to assume the object will occupy 4 bytes */
1953 fix_new_ns32k (fragP,
1954 (int) (fragP->fr_fix),
1955 4,
1956 fragP->fr_symbol,
1957 (symbolS *) 0,
1958 fragP->fr_offset,
1959 1,
1960 fragP->fr_pcrel_adjust,
1961 1,
1962 0,
1963 fragP->fr_bsr); /*sequent hack */
1964 fragP->fr_fix += 4;
1965 /* fragP->fr_opcode[1]=0xff; */
1966 frag_wane (fragP);
1967 break;
1968 }
1969 case IND (BRANCH, BYTE):
1970 fragP->fr_var += 1;
1971 break;
1972 default:
1973 break;
1974 }
1975 return fragP->fr_var + fragP->fr_fix - old_fix;
1976 }
1977
1978 int md_short_jump_size = 3;
1979 int md_long_jump_size = 5;
1980 int md_reloc_size = 8; /* Size of relocation record */
1981
1982 void
1983 md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
1984 char *ptr;
1985 long from_addr, to_addr;
1986 fragS *frag;
1987 symbolS *to_symbol;
1988 {
1989 long offset;
1990
1991 offset = to_addr - from_addr;
1992 md_number_to_chars (ptr, (long) 0xEA, 1);
1993 md_number_to_disp (ptr + 1, (long) offset, 2);
1994 }
1995
1996 void
1997 md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
1998 char *ptr;
1999 long from_addr, to_addr;
2000 fragS *frag;
2001 symbolS *to_symbol;
2002 {
2003 long offset;
2004
2005 offset = to_addr - from_addr;
2006 md_number_to_chars (ptr, (long) 0xEA, 2);
2007 md_number_to_disp (ptr + 2, (long) offset, 4);
2008 }
2009 \f
2010 /* JF this is a new function to parse machine-dep options */
2011 int
2012 md_parse_option (argP, cntP, vecP)
2013 char **argP;
2014 int *cntP;
2015 char ***vecP;
2016 {
2017 switch (**argP)
2018 {
2019 case 'm':
2020 (*argP)++;
2021
2022 if (!strcmp (*argP, "32032"))
2023 {
2024 cpureg = cpureg_032;
2025 mmureg = mmureg_032;
2026 }
2027 else if (!strcmp (*argP, "32532"))
2028 {
2029 cpureg = cpureg_532;
2030 mmureg = mmureg_532;
2031 }
2032 else
2033 as_warn ("Unknown -m option ignored");
2034
2035 while (**argP)
2036 (*argP)++;
2037 break;
2038
2039 default:
2040 return 0;
2041 }
2042 return 1;
2043 }
2044 \f
2045 /*
2046 * bit_fix_new()
2047 *
2048 * Create a bit_fixS in obstack 'notes'.
2049 * This struct is used to profile the normal fix. If the bit_fixP is a
2050 * valid pointer (not NULL) the bit_fix data will be used to format the fix.
2051 */
2052 bit_fixS *
2053 bit_fix_new (size, offset, min, max, add, base_type, base_adj)
2054 char size; /* Length of bitfield */
2055 char offset; /* Bit offset to bitfield */
2056 long base_type; /* 0 or 1, if 1 it's exploded to opcode ptr */
2057 long base_adj;
2058 long min; /* Signextended min for bitfield */
2059 long max; /* Signextended max for bitfield */
2060 long add; /* Add mask, used for huffman prefix */
2061 {
2062 register bit_fixS *bit_fixP;
2063
2064 bit_fixP = (bit_fixS *) obstack_alloc (&notes, sizeof (bit_fixS));
2065
2066 bit_fixP->fx_bit_size = size;
2067 bit_fixP->fx_bit_offset = offset;
2068 bit_fixP->fx_bit_base = base_type;
2069 bit_fixP->fx_bit_base_adj = base_adj;
2070 bit_fixP->fx_bit_max = max;
2071 bit_fixP->fx_bit_min = min;
2072 bit_fixP->fx_bit_add = add;
2073
2074 return (bit_fixP);
2075 }
2076
2077 void
2078 fix_new_ns32k (frag, where, size, add_symbol, sub_symbol, offset, pcrel,
2079 pcrel_adjust, im_disp, bit_fixP, bsr)
2080 fragS *frag; /* Which frag? */
2081 int where; /* Where in that frag? */
2082 int size; /* 1, 2 or 4 usually. */
2083 symbolS *add_symbol; /* X_add_symbol. */
2084 symbolS *sub_symbol; /* X_subtract_symbol. */
2085 long offset; /* X_add_number. */
2086 int pcrel; /* TRUE if PC-relative relocation. */
2087 char pcrel_adjust; /* not zero if adjustment of pcrel offset is needed */
2088 char im_disp; /* true if the value to write is a displacement */
2089 bit_fixS *bit_fixP; /* pointer at struct of bit_fix's, ignored if NULL */
2090 char bsr; /* sequent-linker-hack: 1 when relocobject is a bsr */
2091
2092 {
2093 fixS *fixP = fix_new (frag, where, size, add_symbol, sub_symbol,
2094 offset, pcrel, NO_RELOC);
2095
2096 fixP->fx_pcrel_adjust = pcrel_adjust;
2097 fixP->fx_im_disp = im_disp;
2098 fixP->fx_bit_fixP = bit_fixP;
2099 fixP->fx_bsr = bsr;
2100 } /* fix_new_ns32k() */
2101
2102 /* We have no need to default values of symbols. */
2103
2104 symbolS *
2105 md_undefined_symbol (name)
2106 char *name;
2107 {
2108 return 0;
2109 }
2110
2111 /* Parse an operand that is machine-specific.
2112 We just return without modifying the expression if we have nothing
2113 to do. */
2114
2115 /* ARGSUSED */
2116 void
2117 md_operand (expressionP)
2118 expressionS *expressionP;
2119 {
2120 }
2121
2122 /* Round up a section size to the appropriate boundary. */
2123 long
2124 md_section_align (segment, size)
2125 segT segment;
2126 long size;
2127 {
2128 return size; /* Byte alignment is fine */
2129 }
2130
2131 /* Exactly what point is a PC-relative offset relative TO?
2132 On the National warts, they're relative to the address of the offset,
2133 with some funny adjustments in some circumstances during blue moons.
2134 (??? Is this right? FIXME-SOON) */
2135 long
2136 md_pcrel_from (fixP)
2137 fixS *fixP;
2138 {
2139 long res;
2140 res = fixP->fx_where + fixP->fx_frag->fr_address;
2141 #ifdef SEQUENT_COMPATABILITY
2142 if (fixP->fx_frag->fr_bsr)
2143 res += 0x12 /* FOO Kludge alert! */
2144 #endif
2145 return res;
2146 }
2147
2148 /*
2149 * Local Variables:
2150 * comment-column: 0
2151 * End:
2152 */
2153
2154 /* end of tc-ns32k.c */
This page took 0.078181 seconds and 4 git commands to generate.