1 /* ns32k.c -- Assemble on the National Semiconductor 32k series
2 Copyright (C) 1987 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
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.
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. */
20 /*#define SHOW_NUM 1*/ /* uncomment for debugging */
29 #include "ns32k-opcode.h"
36 #define IIF_ENTRIES 13 /* number of entries in iif */
37 #define PRIVATE_SIZE 256 /* size of my garbage memory */
39 #define DEFAULT -1 /* addr_mode returns this value when plain constant or label is encountered */
41 #define IIF(ptr,a1,c1,e1,g1,i1,k1,m1,o1,q1,s1,u1) \
42 iif.iifP[ptr].type= a1; \
43 iif.iifP[ptr].size= c1; \
44 iif.iifP[ptr].object= e1; \
45 iif.iifP[ptr].object_adjust= g1; \
46 iif.iifP[ptr].pcrel= i1; \
47 iif.iifP[ptr].pcrel_adjust= k1; \
48 iif.iifP[ptr].im_disp= m1; \
49 iif.iifP[ptr].relax_substate= o1; \
50 iif.iifP[ptr].bit_fixP= q1; \
51 iif.iifP[ptr].addr_mode= s1; \
52 iif.iifP[ptr].bsr= u1;
54 #ifdef SEQUENT_COMPATABILITY
55 #define LINE_COMMENT_CHARS "|"
56 #define ABSOLUTE_PREFIX '@'
57 #define IMMEDIATE_PREFIX '#'
60 #ifndef LINE_COMMENT_CHARS
61 #define LINE_COMMENT_CHARS "#"
64 char comment_chars
[] = "#";
65 char line_comment_chars
[] = LINE_COMMENT_CHARS
;
66 #if !defined(ABSOLUTE_PREFIX) && !defined(IMMEDIATE_PREFIX)
67 #define ABSOLUTE_PREFIX '@' /* One or the other MUST be defined */
71 char mode
; /* addressing mode of operand (0-31) */
72 char scaled_mode
; /* mode combined with scaled mode */
73 char scaled_reg
; /* register used in scaled+1 (1-8) */
74 char float_flag
; /* set if R0..R7 was F0..F7 ie a floating-point-register */
75 char am_size
; /* estimated max size of general addr-mode parts*/
76 char im_disp
; /* if im_disp==1 we have a displacement */
77 char pcrel
; /* 1 if pcrel, this is really redundant info */
78 char disp_suffix
[2]; /* length of displacement(s), 0=undefined */
79 char *disp
[2]; /* pointer(s) at displacement(s)
80 or immediates(s) (ascii) */
81 char index_byte
; /* index byte */
83 typedef struct addr_mode addr_modeS
;
86 char *freeptr
,*freeptr_static
; /* points at some number of free bytes */
87 struct hash_control
*inst_hash_handle
;
89 struct ns32k_opcode
*desc
; /* pointer at description of instruction */
90 addr_modeS addr_modeP
;
91 char EXP_CHARS
[] = "eE";
92 char FLT_CHARS
[] = "fd"; /* we don't want to support lowercase, do we */
94 /* UPPERCASE denotes live names
95 * when an instruction is built, IIF is used as an intermidiate form to store
96 * the actual parts of the instruction. A ns32k machine instruction can
97 * be divided into a couple of sub PARTs. When an instruction is assembled
98 * the appropriate PART get an assignment. When an IIF has been completed it's
99 * converted to a FRAGment as specified in AS.H */
101 /* internal structs */
109 int type
; /* how to interpret object */
110 int size
; /* Estimated max size of object */
111 unsigned long object
; /* binary data */
112 int object_adjust
; /* number added to object */
113 int pcrel
; /* True if object is pcrel */
114 int pcrel_adjust
; /* It's value reflects the length in bytes from the instruction start to the displacement */
115 int im_disp
; /* True if the object is a displacement */
116 relax_substateT relax_substate
; /* Initial relaxsubstate */
117 bit_fixS
*bit_fixP
; /* Pointer at bit_fix struct */
118 int addr_mode
; /* What addrmode do we associate with this iif-entry */
119 char bsr
; /* Sequent hack */
120 }iif_entryT
; /* Internal Instruction Format */
121 struct int_ins_form
{
122 int instr_size
; /* Max size of instruction in bytes. */
123 iif_entryT iifP
[IIF_ENTRIES
+1];
125 struct int_ins_form iif
;
127 char *input_line_pointer
;
128 /* description of the PARTs in IIF
130 * 0 total length in bytes of entries in iif
143 * For every entry there is a datalength in bytes. This is stored in size[n].
144 * 0, the objectlength is not explicitly given by the instruction
145 * and the operand is undefined. This is a case for relaxation.
146 * Reserve 4 bytes for the final object.
148 * 1, the entry contains one byte
149 * 2, the entry contains two bytes
150 * 3, the entry contains three bytes
151 * 4, the entry contains four bytes
154 * Furthermore, every entry has a data type identifier in type[n].
156 * 0, the entry is void, ignore it.
157 * 1, the entry is a binary number.
158 * 2, the entry is a pointer at an expression.
159 * Where expression may be as simple as a single '1',
160 * and as complicated as foo-bar+12,
161 * foo and bar may be undefined but suffixed by :{b|w|d} to
162 * control the length of the object.
164 * 3, the entry is a pointer at a bignum struct
167 * The low-order-byte coresponds to low physical memory.
168 * Obviously a FRAGment must be created for each valid disp in PART whose
169 * datalength is undefined (to bad) .
170 * The case where just the expression is undefined is less severe and is
171 * handled by fix. Here the number of bytes in the objectfile is known.
172 * With this representation we simplify the assembly and separates the
173 * machine dependent/independent parts in a more clean way (said OE)
176 struct option opt1
[]= /* restore, exit */
178 { "r0", 0x80, 0xff },
179 { "r1", 0x40, 0xff },
180 { "r2", 0x20, 0xff },
181 { "r3", 0x10, 0xff },
182 { "r4", 0x08, 0xff },
183 { "r5", 0x04, 0xff },
184 { "r6", 0x02, 0xff },
185 { "r7", 0x01, 0xff },
188 struct option opt2
[]= /* save, enter */
190 { "r0", 0x01, 0xff },
191 { "r1", 0x02, 0xff },
192 { "r2", 0x04, 0xff },
193 { "r3", 0x08, 0xff },
194 { "r4", 0x10, 0xff },
195 { "r5", 0x20, 0xff },
196 { "r6", 0x40, 0xff },
197 { "r7", 0x80, 0xff },
200 struct option opt3
[]= /* setcfg */
208 struct option opt4
[]= /* cinv */
215 struct option opt5
[]= /* string inst */
222 struct option opt6
[]= /* plain reg ext,cvtp etc */
224 { "r0", 0x00, 0xff },
225 { "r1", 0x01, 0xff },
226 { "r2", 0x02, 0xff },
227 { "r3", 0x03, 0xff },
228 { "r4", 0x04, 0xff },
229 { "r5", 0x05, 0xff },
230 { "r6", 0x06, 0xff },
231 { "r7", 0x07, 0xff },
235 #if !defined(NS32032) && !defined(NS32532)
239 struct option cpureg_532
[]= /* lpr spr */
242 { "dcr", 0x1, 0xff },
243 { "bpc", 0x2, 0xff },
244 { "dsr", 0x3, 0xff },
245 { "car", 0x4, 0xff },
249 { "usp", 0xb, 0xff },
250 { "cfg", 0xc, 0xff },
251 { "psr", 0xd, 0xff },
252 { "intbase", 0xe, 0xff },
253 { "mod", 0xf, 0xff },
256 struct option mmureg_532
[]= /* lmr smr */
258 { "mcr", 0x9, 0xff },
259 { "msr", 0xa, 0xff },
260 { "tear", 0xb, 0xff },
261 { "ptb0", 0xc, 0xff },
262 { "ptb1", 0xd, 0xff },
263 { "ivar0", 0xe, 0xff },
264 { "ivar1", 0xf, 0xff },
268 struct option cpureg_032
[]= /* lpr spr */
270 { "upsr", 0x0, 0xff },
274 { "psr", 0xd, 0xff },
275 { "intbase", 0xe, 0xff },
276 { "mod", 0xf, 0xff },
279 struct option mmureg_032
[]= /* lmr smr */
281 { "bpr0", 0x0, 0xff },
282 { "bpr1", 0x1, 0xff },
283 { "pf0", 0x4, 0xff },
284 { "pf1", 0x5, 0xff },
286 { "msr", 0xa, 0xff },
287 { "bcnt", 0xb, 0xff },
288 { "ptb0", 0xc, 0xff },
289 { "ptb1", 0xd, 0xff },
290 { "eia", 0xf, 0xff },
295 struct option
*cpureg
= cpureg_532
;
296 struct option
*mmureg
= mmureg_532
;
298 struct option
*cpureg
= cpureg_032
;
299 struct option
*mmureg
= mmureg_032
;
303 const pseudo_typeS md_pseudo_table
[]={ /* so far empty */
307 #define IND(x,y) (((x)<<2)+(y))
309 /* those are index's to relax groups in md_relax_table
310 ie it must be multiplied by 4 to point at a group start. Viz IND(x,y)
311 Se function relax_segment in write.c for more info */
316 /* those are index's to entries in a relax group */
322 /* Those limits are calculated from the displacement start in memory.
323 The ns32k uses the begining of the instruction as displacement base.
324 This type of displacements could be handled here by moving the limit window
325 up or down. I choose to use an internal displacement base-adjust as there
326 are other routines that must consider this. Also, as we have two various
327 offset-adjusts in the ns32k (acb versus br/brs/jsr/bcond), two set of limits
328 would have had to be used.
329 Now we dont have to think about that. */
332 const relax_typeS md_relax_table
[]={
338 { (63), (-64), 1, IND(BRANCH
,WORD
) },
339 { (8192), (-8192), 2, IND(BRANCH
,DOUBLE
) },
344 /* Array used to test if mode contains displacements.
345 Value is true if mode contains displacement. */
347 char disp_test
[]={ 0,0,0,0,0,0,0,0,
352 /* Array used to calculate max size of displacements */
354 char disp_size
[]={ 4,1,2,0,4 };
359 static segT
evaluate_expr(expressionS
*resultP
, char *ptr
);
360 static void md_number_to_disp(char *buf
, long val
, int n
);
361 static void md_number_to_imm(char *buf
, long val
, int n
);
365 static segT
evaluate_expr();
366 static void md_number_to_disp();
367 static void md_number_to_imm();
369 #endif /* __STDC__ */
371 /* Parses a general operand into an addressingmode struct
373 in: pointer at operand in ascii form
374 pointer at addr_mode struct for result
375 the level of recursion. (always 0 or 1)
377 out: data in addr_mode struct
379 int addr_mode(operand
,addr_modeP
,recursive_level
)
381 register addr_modeS
*addr_modeP
;
389 mode
= DEFAULT
; /* default */
390 addr_modeP
->scaled_mode
=0; /* why not */
391 addr_modeP
->scaled_reg
=0; /* if 0, not scaled index */
392 addr_modeP
->float_flag
=0;
393 addr_modeP
->am_size
=0;
394 addr_modeP
->im_disp
=0;
395 addr_modeP
->pcrel
=0; /* not set in this function */
396 addr_modeP
->disp_suffix
[0]=0;
397 addr_modeP
->disp_suffix
[1]=0;
398 addr_modeP
->disp
[0]=NULL
;
399 addr_modeP
->disp
[1]=NULL
;
401 if (str
[0]==0) {return (0);} /* we don't want this */
404 /* the following three case statements controls the mode-chars
405 this is the place to ed if you want to change them */
406 #ifdef ABSOLUTE_PREFIX
407 case ABSOLUTE_PREFIX
:
408 if (str
[strl
-1]==']') break;
409 addr_modeP
->mode
=21; /* absolute */
410 addr_modeP
->disp
[0]=str
+1;
413 #ifdef IMMEDIATE_PREFIX
414 case IMMEDIATE_PREFIX
:
415 if (str
[strl
-1]==']') break;
416 addr_modeP
->mode
=20; /* immediate */
417 addr_modeP
->disp
[0]=str
+1;
421 if (str
[strl
-1]!=']') {
424 if (str
[2]!='\000') {
425 addr_modeP
->mode
=27; /* pc-relativ */
426 addr_modeP
->disp
[0]=str
+2;
430 as_warn("Invalid syntax in PC-relative addressing mode");
436 if (str
[strl
-1]!=']') {
437 if((!strncmp(str
,"ext(",4)) && strl
>7) { /* external */
438 addr_modeP
->disp
[0]=str
+4;
441 do { /* disp[0]'s termination point */
443 if (str
[j
]=='(') i
++;
444 if (str
[j
]==')') i
--;
445 } while (j
<strl
&& i
!=0);
446 if (i
!=0 || !(str
[j
+1]=='-' || str
[j
+1]=='+') ) {
447 as_warn("Invalid syntax in External addressing mode");
450 str
[j
]='\000'; /* null terminate disp[0] */
451 addr_modeP
->disp
[1]=str
+j
+2;
463 case'f':addr_modeP
->float_flag
=1;
465 if (str
[1]>='0' && str
[1]<'8') {
466 addr_modeP
->mode
=str
[1]-'0';
471 if (!strncmp(str
,"tos",3)) {
472 addr_modeP
->mode
=23; /* TopOfStack */
478 if (str
[strl
-1]==')') {
479 if (str
[strl
-2]==')') {
480 if (!strncmp(&str
[strl
-5],"(fp",3)) {
481 mode
=16; /* Memory Relative */
483 if (!strncmp(&str
[strl
-5],"(sp",3)) {
486 if (!strncmp(&str
[strl
-5],"(sb",3)) {
489 if (mode
!=DEFAULT
) { /* memory relative */
490 addr_modeP
->mode
=mode
;
491 j
=strl
-5; /* temp for end of disp[0] */
495 if (str
[strl
]==')') i
++;
496 if (str
[strl
]=='(') i
--;
497 } while (strl
>-1 && i
!=0);
499 as_warn("Invalid syntax in Memory Relative addressing mode");
502 addr_modeP
->disp
[1]=str
;
503 addr_modeP
->disp
[0]=str
+strl
+1;
504 str
[j
]='\000'; /* null terminate disp[0] */
505 str
[strl
]='\000'; /* null terminate disp[1] */
509 switch (str
[strl
-3]) {
511 if (str
[strl
-2]>='0' && str
[strl
-2]<'8' && str
[strl
-4]=='(') {
512 addr_modeP
->mode
=str
[strl
-2]-'0'+8;
513 addr_modeP
->disp
[0]=str
;
515 return (-1); /* reg rel */
518 if (!strncmp(&str
[strl
-4],"(fp",3)) {
521 if (!strncmp(&str
[strl
-4],"(sp",3)) {
524 if (!strncmp(&str
[strl
-4],"(sb",3)) {
527 if (!strncmp(&str
[strl
-4],"(pc",3)) {
531 addr_modeP
->mode
=mode
;
532 addr_modeP
->disp
[0]=str
;
534 return (-1); /* memory space */
538 /* no trailing ')' do we have a ']' ? */
539 if (str
[strl
-1]==']') {
540 switch (str
[strl
-2]) {
541 case'b':mode
=28;break;
542 case'w':mode
=29;break;
543 case'd':mode
=30;break;
544 case'q':mode
=31;break;
546 as_warn("Invalid scaled-indexed mode, use (b,w,d,q)");
547 if (str
[strl
-3]!=':' || str
[strl
-6]!='[' ||
548 str
[strl
-5]=='r' || str
[strl
-4]<'0' || str
[strl
-4]>'7') {
549 as_warn("Syntax in scaled-indexed mode, use [Rn:m] where n=[0..7] m={b,w,d,q}");
553 if (recursive_level
>0) {
554 as_warn("Scaled-indexed addressing mode combined with scaled-index");
557 addr_modeP
->am_size
+=1; /* scaled index byte */
558 j
=str
[strl
-4]-'0'; /* store temporary */
559 str
[strl
-6]='\000'; /* nullterminate for recursive call */
560 i
=addr_mode(str
,addr_modeP
,1);
561 if (!i
|| addr_modeP
->mode
==20) {
562 as_warn("Invalid or illegal addressing mode combined with scaled-index");
565 addr_modeP
->scaled_mode
=addr_modeP
->mode
; /* store the inferior mode */
566 addr_modeP
->mode
=mode
;
567 addr_modeP
->scaled_reg
=j
+1;
572 addr_modeP
->mode
= DEFAULT
; /* default to whatever */
573 addr_modeP
->disp
[0]=str
;
577 /* ptr points at string
578 addr_modeP points at struct with result
579 This routine calls addr_mode to determine the general addr.mode of
580 the operand. When this is ready it parses the displacements for size
581 specifying suffixes and determines size of immediate mode via ns32k-opcode.
582 Also builds index bytes if needed.
584 int get_addr_mode(ptr
,addr_modeP
)
586 addr_modeS
*addr_modeP
;
589 addr_mode(ptr
,addr_modeP
,0);
590 if (addr_modeP
->mode
== DEFAULT
|| addr_modeP
->scaled_mode
== -1) {
591 /* resolve ambigious operands, this shouldn't
592 be necessary if one uses standard NSC operand
593 syntax. But the sequent compiler doesn't!!!
594 This finds a proper addressinging mode if it
595 is implicitly stated. See ns32k-opcode.h */
596 (void)evaluate_expr(&exprP
,ptr
); /* this call takes time Sigh! */
597 if (addr_modeP
->mode
== DEFAULT
) {
598 if (exprP
.X_add_symbol
|| exprP
.X_subtract_symbol
) {
599 addr_modeP
->mode
=desc
->default_model
; /* we have a label */
601 addr_modeP
->mode
=desc
->default_modec
; /* we have a constant */
604 if (exprP
.X_add_symbol
|| exprP
.X_subtract_symbol
) {
605 addr_modeP
->scaled_mode
=desc
->default_model
;
607 addr_modeP
->scaled_mode
=desc
->default_modec
;
610 /* must put this mess down in addr_mode to handle the scaled case better */
612 /* It appears as the sequent compiler wants an absolute when we have a
613 label without @. Constants becomes immediates besides the addr case.
614 Think it does so with local labels too, not optimum, pcrel is better.
615 When I have time I will make gas check this and select pcrel when possible
616 Actually that is trivial.
618 if (tmp
=addr_modeP
->scaled_reg
) { /* build indexbyte */
619 tmp
--; /* remember regnumber comes incremented for flagpurpose */
620 tmp
|=addr_modeP
->scaled_mode
<<3;
621 addr_modeP
->index_byte
=(char)tmp
;
622 addr_modeP
->am_size
+=1;
624 if (disp_test
[addr_modeP
->mode
]) { /* there was a displacement, probe for length specifying suffix*/
627 register char suffix
;
628 register char suffix_sub
;
631 register char *fromP
;
634 if (disp_test
[addr_modeP
->mode
]) { /* there is a displacement */
635 if (addr_modeP
->mode
==27 || addr_modeP
->scaled_mode
==27) { /* do we have pcrel. mode */
638 addr_modeP
->im_disp
=1;
641 if (toP
=addr_modeP
->disp
[i
]) { /* suffix of expression, the largest size rules */
643 while (c
= *fromP
++) {
648 as_warn("Premature end of suffix--Defaulting to d");
651 case 'b':suffix_sub
=1;break;
652 case 'w':suffix_sub
=2;break;
653 case 'd':suffix_sub
=4;break;
655 as_warn("Bad suffix after ':' use {b|w|d} Defaulting to d");
659 toP
--; /* So we write over the ':' */
660 if (suffix
<suffix_sub
) suffix
=suffix_sub
;
663 *toP
='\0'; /* terminate properly */
664 addr_modeP
->disp_suffix
[i
]=suffix
;
665 addr_modeP
->am_size
+=suffix
? suffix
: 4;
671 if (addr_modeP
->mode
==20) { /* look in ns32k_opcode for size */
672 addr_modeP
->disp_suffix
[0]=addr_modeP
->am_size
=desc
->im_size
;
673 addr_modeP
->im_disp
=0;
676 return addr_modeP
->mode
;
680 /* read an optionlist */
681 void optlist(str
,optionP
,default_map
)
682 char *str
; /* the string to extract options from */
683 struct option
*optionP
; /* how to search the string */
684 unsigned long *default_map
; /* default pattern and output */
686 register int i
,j
,k
,strlen1
,strlen2
;
687 register char *patternP
,*strP
;
690 as_fatal("Very short instr to option, ie you can't do it on a NULLstr");
692 for (i
=0;optionP
[i
].pattern
!=0;i
++) {
693 strlen2
=strlen(optionP
[i
].pattern
);
694 for (j
=0;j
<strlen1
;j
++) {
695 patternP
=optionP
[i
].pattern
;
697 for (k
=0;k
<strlen2
;k
++) {
698 if (*(strP
++)!=*(patternP
++)) break;
700 if (k
==strlen2
) { /* match */
701 *default_map
|=optionP
[i
].or;
702 *default_map
&=optionP
[i
].and;
707 /* search struct for symbols
708 This function is used to get the short integer form of reg names
709 in the instructions lmr, smr, lpr, spr
710 return true if str is found in list */
712 int list_search(str
,optionP
,default_map
)
713 char *str
; /* the string to match */
714 struct option
*optionP
; /* list to search */
715 unsigned long *default_map
; /* default pattern and output */
718 for (i
=0;optionP
[i
].pattern
!=0;i
++) {
719 if (!strncmp(optionP
[i
].pattern
,str
,20)) { /* use strncmp to be safe */
720 *default_map
|=optionP
[i
].or;
721 *default_map
&=optionP
[i
].and;
725 as_warn("No such entry in list. (cpu/mmu register)");
728 static segT
evaluate_expr(resultP
,ptr
)
729 expressionS
*resultP
;
732 register char *tmp_line
;
733 register segT segment
;
734 tmp_line
=input_line_pointer
;
735 input_line_pointer
=ptr
;
736 segment
=expression(&exprP
);
737 input_line_pointer
=tmp_line
;
741 /* Convert operands to iif-format and adds bitfields to the opcode.
742 Operands are parsed in such an order that the opcode is updated from
743 its most significant bit, that is when the operand need to alter the
745 Be carefull not to put to objects in the same iif-slot.
748 void encode_operand(argc
,argv
,operandsP
,suffixP
,im_size
,opcode_bit_ptr
)
757 int pcrel
,tmp
,b
,loop
,pcrel_adjust
;
758 for(loop
=0;loop
<argc
;loop
++) {
759 i
=operandsP
[loop
<<1]-'1'; /* what operand are we supposed to work on */
760 if (i
>3) as_fatal("Internal consistency error. check ns32k-opcode.h");
764 switch (operandsP
[(loop
<<1)+1]) {
765 case 'f': /* operand of sfsr turns out to be a nasty specialcase */
767 case 'F': /* 32 bit float general form */
768 case 'L': /* 64 bit float */
769 case 'Q': /* quad-word */
772 case 'D': /* double-word */
773 case 'A': /* double-word gen-address-form ie no regs allowed */
774 get_addr_mode(argv
[i
],&addr_modeP
);
775 iif
.instr_size
+=addr_modeP
.am_size
;
776 if (opcode_bit_ptr
==desc
->opcode_size
) b
=4; else b
=6;
777 for (j
=b
;j
<(b
+2);j
++) {
778 if (addr_modeP
.disp
[j
-b
]) {
781 addr_modeP
.disp_suffix
[j
-b
],
782 (unsigned long)addr_modeP
.disp
[j
-b
],
785 iif
.instr_size
-addr_modeP
.am_size
, /* this aint used (now) */
789 addr_modeP
.scaled_reg
? addr_modeP
.scaled_mode
:addr_modeP
.mode
,
794 iif
.iifP
[1].object
|=((long)addr_modeP
.mode
)<<opcode_bit_ptr
;
795 if (addr_modeP
.scaled_reg
) {
797 IIF(j
,1,1, (unsigned long)addr_modeP
.index_byte
,0,0,0,0,0, NULL
,-1,0);
800 case 'b': /* multiple instruction disp */
801 freeptr
++; /* OVE:this is an useful hack */
802 tmp
=(int)sprintf(freeptr
,"((%s-1)*%d)\000",argv
[i
],desc
->im_size
);
805 pcrel
-=1; /* make pcrel 0 inspite of what case 'p': wants */
807 case 'p': /* displacement - pc relative addressing */
810 case 'd': /* displacement */
811 iif
.instr_size
+=suffixP
[i
] ? suffixP
[i
] : 4;
812 IIF(12, 2, suffixP
[i
], (unsigned long)argv
[i
], 0,
813 pcrel
, pcrel_adjust
, 1, IND(BRANCH
,BYTE
), NULL
,-1,0);
815 case 'H': /* sequent-hack: the linker wants a bit set when bsr */
817 iif
.instr_size
+=suffixP
[i
] ? suffixP
[i
] : 4;
818 IIF(12, 2, suffixP
[i
], (unsigned long)argv
[i
], 0,
819 pcrel
, pcrel_adjust
, 1, IND(BRANCH
,BYTE
), NULL
,-1,1);break;
820 case 'q': /* quick */
822 IIF(11,2,42,(unsigned long)argv
[i
],0,0,0,0,0,
823 bit_fix_new(4,opcode_bit_ptr
,-8,7,0,1,0),-1,0);
825 case 'r': /* register number (3 bits) */
826 list_search(argv
[i
],opt6
,&tmp
);
828 iif
.iifP
[1].object
|=tmp
<<opcode_bit_ptr
;
830 case 'O': /* setcfg instruction optionslist */
831 optlist(argv
[i
],opt3
,&tmp
);
833 iif
.iifP
[1].object
|=tmp
<<15;
835 case 'C': /* cinv instruction optionslist */
836 optlist(argv
[i
],opt4
,&tmp
);
838 iif
.iifP
[1].object
|=tmp
<<15;/*insert the regtype in opcode */
840 case 'S': /* stringinstruction optionslist */
841 optlist(argv
[i
],opt5
,&tmp
);
843 iif
.iifP
[1].object
|=tmp
<<15;
845 case 'u':case 'U': /* registerlist */
846 IIF(10,1,1,0,0,0,0,0,0,NULL
,-1,0);
847 switch (operandsP
[(i
<<1)+1]) {
848 case 'u': /* restore, exit */
849 optlist(argv
[i
],opt1
,&iif
.iifP
[10].object
);
851 case 'U': /* save,enter */
852 optlist(argv
[i
],opt2
,&iif
.iifP
[10].object
);
857 case 'M': /* mmu register */
858 list_search(argv
[i
],mmureg
,&tmp
);
860 iif
.iifP
[1].object
|=tmp
<<opcode_bit_ptr
;
862 case 'P': /* cpu register */
863 list_search(argv
[i
],cpureg
,&tmp
);
865 iif
.iifP
[1].object
|=tmp
<<opcode_bit_ptr
;
867 case 'g': /* inss exts */
868 iif
.instr_size
+=1; /* 1 byte is allocated after the opcode */
870 (unsigned long)argv
[i
], /* i always 2 here */
872 bit_fix_new(3,5,0,7,0,0,0), /* a bit_fix is targeted to the byte */
876 (unsigned long)argv
[i
], /* i always 3 here */
878 bit_fix_new(5,0,1,32,-1,0,-1),-1,0);
882 b
=2+i
; /* put the extension byte after opcode */
883 IIF(b
,2,1,0,0,0,0,0,0,0,-1,0);
885 as_fatal("Bad opcode-table-option, check in file ns32k-opcode.h");
890 /* in: instruction line
891 out: internal structure of instruction
892 that has been prepared for direct conversion to fragment(s) and
893 fixes in a systematical fashion
894 Return-value = recursive_level
896 /* build iif of one assembly text line */
897 int parse(line
,recursive_level
)
901 register char *lineptr
,c
,suffix_separator
;
905 char suffix
[MAX_ARGS
],*argv
[MAX_ARGS
];/* no more than 4 operands */
906 if (recursive_level
<=0) { /* called from md_assemble */
907 for (lineptr
=line
;(*lineptr
)!='\0' && (*lineptr
)!=' ';lineptr
++);
910 if (!(desc
=(struct ns32k_opcode
*)hash_find(inst_hash_handle
,line
))) {
911 as_fatal("No such opcode");
918 if (*desc
->operands
) {
919 if (*lineptr
++!='\0') {
922 while (*lineptr
!='\0') {
923 if (desc
->operands
[argc
<<1]) {
925 arg_type
=desc
->operands
[(argc
<<1)+1];
927 case 'd': case 'b': case 'p': case 'H': /* the operand is supposed to be a displacement */
928 /* Hackwarning: do not forget to update the 4 cases above when editing ns32k-opcode.h */
929 suffix_separator
=':';
932 suffix_separator
='\255'; /* if this char occurs we loose */
934 suffix
[argc
]=0; /* 0 when no ':' is encountered */
937 while ((c
= *lineptr
)!='\0' && c
!=sep
) {
945 if (c
==suffix_separator
) { /* ':' - label/suffix separator */
946 switch (lineptr
[1]) {
947 case 'b':suffix
[argc
]=1;break;
948 case 'w':suffix
[argc
]=2;break;
949 case 'd':suffix
[argc
]=4;break;
950 default: as_warn("Bad suffix, defaulting to d");
952 if (lineptr
[1]=='\0' || lineptr
[1]==sep
) {
965 if (*lineptr
=='\0') continue;
968 as_fatal("Too many operands passed to instruction");
973 if (argc
!=strlen(desc
->operands
)/2) {
974 if (strlen(desc
->default_args
)) { /* we can apply default, dont goof */
975 if (parse(desc
->default_args
,1)!=1) { /* check error in default */
976 as_fatal("Wrong numbers of operands in default, check ns32k-opcodes.h");
979 as_fatal("Wrong number of operands");
983 for (i
=0;i
<IIF_ENTRIES
;i
++) {
984 iif
.iifP
[i
].type
=0; /* mark all entries as void*/
987 /* build opcode iif-entry */
988 iif
.instr_size
=desc
->opcode_size
/8;
989 IIF(1,1,iif
.instr_size
,desc
->opcode_seed
,0,0,0,0,0,0,-1,0);
991 /* this call encodes operands to iif format */
1000 return recursive_level
;
1004 /* Convert iif to fragments.
1005 From this point we start to dribble with functions in other files than
1006 this one.(Except hash.c) So, if it's possible to make an iif for an other
1007 CPU, you don't need to know what frags, relax, obstacks, etc is in order
1008 to port this assembler. You only need to know if it's possible to reduce
1009 your cpu-instruction to iif-format (takes some work) and adopt the other
1010 md_? parts according to given instructions
1011 Note that iif was invented for the clean ns32k`s architecure.
1013 void convert_iif() {
1016 char *inst_offset
,*inst_opcode
;
1020 register int rem_size
; /* count the remaining bytes of instruction */
1022 register char size
= 0;
1023 int size_so_far
=0; /* used to calculate pcrel_adjust */
1025 rem_size
=iif
.instr_size
;
1026 memP
=frag_more(iif
.instr_size
); /* make sure we have enough bytes for instruction */
1028 inst_offset
=(char*)(memP
-frag_now
->fr_literal
);
1030 for (i
=0;i
<IIF_ENTRIES
;i
++) {
1031 if (type
=iif
.iifP
[i
].type
) { /* the object exist, so handle it */
1032 switch (size
=iif
.iifP
[i
].size
) {
1033 case 42: size
=0; /* it's a bitfix that operates on an existing object*/
1034 if (iif
.iifP
[i
].bit_fixP
->fx_bit_base
) { /* expand fx_bit_base to point at opcode */
1035 iif
.iifP
[i
].bit_fixP
->fx_bit_base
=(long)inst_opcode
;
1037 case 8: /* bignum or doublefloat */
1039 case 1:case 2:case 3:case 4:/* the final size in objectmemory is known */
1040 j
=(unsigned long)iif
.iifP
[i
].bit_fixP
;
1042 case 1: /* the object is pure binary */
1043 if (j
|| iif
.iifP
[i
].pcrel
) {
1044 fix_new_ns32k(frag_now
,
1045 (long)(memP
-frag_now
->fr_literal
),
1051 (char)size_so_far
, /*iif.iifP[i].pcrel_adjust,*/
1052 iif
.iifP
[i
].im_disp
,
1054 iif
.iifP
[i
].bsr
); /* sequent hack */
1055 } else { /* good, just put them bytes out */
1056 switch (iif
.iifP
[i
].im_disp
) {
1058 md_number_to_chars(memP
,iif
.iifP
[i
].object
,size
);break;
1060 md_number_to_disp(memP
,iif
.iifP
[i
].object
,size
);break;
1061 default: as_fatal("iif convert internal pcrel/binary");
1067 case 2: /* the object is a pointer at an expression, so unpack
1068 it, note that bignums may result from the expression
1070 if ((segment
=evaluate_expr(&exprP
,(char*)iif
.iifP
[i
].object
))==SEG_BIG
|| size
==8) {
1071 if ((k
=exprP
.X_add_number
)>0) { /* we have a bignum ie a quad */
1072 /* this can only happens in a long suffixed instruction */
1073 bzero(memP
,size
); /* size normally is 8 */
1074 if (k
*2>size
) as_warn("Bignum too big for long");
1076 for (l
=0;k
>0;k
--,l
+=2) {
1077 md_number_to_chars(memP
+l
,generic_bignum
[l
>>1],sizeof(LITTLENUM_TYPE
));
1079 } else { /* flonum */
1080 LITTLENUM_TYPE words
[4];
1084 gen_to_words(words
,2,8);
1085 md_number_to_imm(memP
,(long)words
[0],sizeof(LITTLENUM_TYPE
));
1086 md_number_to_imm(memP
+sizeof(LITTLENUM_TYPE
),(long)words
[1],sizeof(LITTLENUM_TYPE
));
1089 gen_to_words(words
,4,11);
1090 md_number_to_imm(memP
,(long)words
[0],sizeof(LITTLENUM_TYPE
));
1091 md_number_to_imm(memP
+sizeof(LITTLENUM_TYPE
) ,(long)words
[1],sizeof(LITTLENUM_TYPE
));
1092 md_number_to_imm(memP
+2*sizeof(LITTLENUM_TYPE
),(long)words
[2],sizeof(LITTLENUM_TYPE
));
1093 md_number_to_imm(memP
+3*sizeof(LITTLENUM_TYPE
),(long)words
[3],sizeof(LITTLENUM_TYPE
));
1102 exprP
.X_add_symbol
||
1103 exprP
.X_subtract_symbol
||
1104 iif
.iifP
[i
].pcrel
) { /* fixit */
1105 /* the expression was undefined due to an undefined label */
1106 /* create a fix so we can fix the object later */
1107 exprP
.X_add_number
+=iif
.iifP
[i
].object_adjust
;
1108 fix_new_ns32k(frag_now
,
1109 (long)(memP
-frag_now
->fr_literal
),
1112 exprP
.X_subtract_symbol
,
1115 (char)size_so_far
, /*iif.iifP[i].pcrel_adjust,*/
1116 iif
.iifP
[i
].im_disp
,
1118 iif
.iifP
[i
].bsr
); /* sequent hack */
1120 } else { /* good, just put them bytes out */
1121 switch (iif
.iifP
[i
].im_disp
) {
1123 md_number_to_imm(memP
,exprP
.X_add_number
,size
);break;
1125 md_number_to_disp(memP
,exprP
.X_add_number
,size
);break;
1126 default: as_fatal("iif convert internal pcrel/pointer");
1132 default: as_fatal("Internal logic error in iif.iifP[n].type");
1135 case 0: /* To bad, the object may be undefined as far as its final
1136 nsize in object memory is concerned. The size of the object
1137 in objectmemory is not explicitly given.
1138 If the object is defined its length can be determined and
1139 a fix can replace the frag.
1143 segment
=evaluate_expr(&exprP
,(char*)iif
.iifP
[i
].object
);
1144 if ((exprP
.X_add_symbol
|| exprP
.X_subtract_symbol
) &&
1145 !iif
.iifP
[i
].pcrel
) { /* OVE: hack, clamp to 4 bytes */
1146 size
=4; /* we dont wan't to frag this, use 4 so it reaches */
1147 fix_new_ns32k(frag_now
,
1148 (long)(memP
-frag_now
->fr_literal
),
1151 exprP
.X_subtract_symbol
,
1153 0, /* never iif.iifP[i].pcrel, */
1154 (char)size_so_far
, /*iif.iifP[i].pcrel_adjust,*/
1155 1, /* always iif.iifP[i].im_disp, */
1159 break; /* exit this absolute hack */
1162 if (exprP
.X_add_symbol
|| exprP
.X_subtract_symbol
) { /* frag it */
1163 if (exprP
.X_subtract_symbol
) { /* We cant relax this case */
1164 as_fatal("Can't relax difference");
1167 /* at this stage we must undo some of the effect caused
1168 by frag_more, ie we must make sure that frag_var causes
1169 frag_new to creat a valid fix-size in the frag it`s closing
1171 temp
= -(rem_size
-4);
1172 obstack_blank_fast(&frags
,temp
);
1173 /* we rewind none, some or all of the requested size we
1174 requested by the first frag_more for this iif chunk.
1175 Note: that we allocate 4 bytes to an object we NOT YET
1176 know the size of, thus rem_size-4.
1178 (void)frag_variant(rs_machine_dependent
,
1181 IND(BRANCH
,UNDEF
), /* expecting the worst */
1185 (char)size_so_far
, /*iif.iifP[i].pcrel_adjust);*/
1186 iif
.iifP
[i
].bsr
); /* sequent linker hack */
1189 memP
=frag_more(rem_size
);
1193 else {/* Double work, this is done in md_number_to_disp */
1194 /* exprP.X_add_number; what was this supposed to be?
1196 if (-64<=exprP
.X_add_number
&& exprP
.X_add_number
<=63) {
1199 if (-8192<=exprP
.X_add_number
&& exprP
.X_add_number
<=8191) {
1202 if (-0x1f000000<=exprP
.X_add_number
&&
1203 exprP
.X_add_number
<=0x1fffffff)
1204 /* if (-0x40000000<=exprP.X_add_number &&
1205 exprP.X_add_number<=0x3fffffff) */
1209 as_warn("Displacement to large for :d");
1214 /* rewind the bytes not used */
1216 md_number_to_disp(memP
,exprP
.X_add_number
,size
);
1217 obstack_blank_fast(&frags
,temp
);
1219 rem_size
-=4; /* we allocated this amount */
1224 as_fatal("Internal logic error in iif.iifP[].type");
1232 void md_assemble(line
)
1235 freeptr
=freeptr_static
;
1236 parse(line
,0); /* explode line to more fix form in iif */
1237 convert_iif(); /* convert iif to frags, fix's etc */
1239 printf(" \t\t\t%s\n",line
);
1245 /* build a hashtable of the instructions */
1246 register const struct ns32k_opcode
*ptr
;
1247 register char *stat
;
1248 inst_hash_handle
=hash_new();
1249 for (ptr
=ns32k_opcodes
;ptr
<endop
;ptr
++) {
1250 if (*(stat
=hash_insert(inst_hash_handle
,ptr
->name
,(char*)ptr
))) {
1251 as_fatal("Can't hash %s: %s", ptr
->name
,stat
); /*fatal*/
1255 freeptr_static
=(char*)malloc(PRIVATE_SIZE
); /* some private space please! */
1261 free(freeptr_static
);
1264 /* Must be equal to MAX_PRECISON in atof-ieee.c */
1265 #define MAX_LITTLENUMS 6
1267 /* Turn the string pointed to by litP into a floating point constant of type
1268 type, and emit the appropriate bytes. The number of LITTLENUMS emitted
1269 is stored in *sizeP . An error message is returned, or NULL on OK.
1272 md_atof(type
,litP
,sizeP
)
1278 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
1279 LITTLENUM_TYPE
*wordP
;
1292 return "Bad call to MD_ATOF()";
1294 t
=atof_ieee(input_line_pointer
,type
,words
);
1296 input_line_pointer
=t
;
1298 *sizeP
=prec
* sizeof(LITTLENUM_TYPE
);
1299 for(wordP
=words
+prec
;prec
--;) {
1300 md_number_to_chars(litP
,(long)(*--wordP
),sizeof(LITTLENUM_TYPE
));
1301 litP
+=sizeof(LITTLENUM_TYPE
);
1303 return ""; /* Someone should teach Dean about null pointers */
1306 /* Convert number to chars in correct order */
1309 md_number_to_chars (buf
, value
, nbytes
)
1317 printf("%x ",value
& 0xff);
1319 *buf
++ = value
; /* Lint wants & MASK_CHAR. */
1320 value
>>= BITS_PER_CHAR
;
1323 /* Convert number to chars in correct order */
1327 /* This is a variant of md_numbers_to_chars. The reason for its' existence
1328 is the fact that ns32k uses Huffman coded displacements. This implies
1329 that the bit order is reversed in displacements and that they are prefixed
1332 binary: msb -> lsb 0xxxxxxx byte
1333 10xxxxxx xxxxxxxx word
1334 11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx double word
1336 This must be taken care of and we do it here!
1338 static void md_number_to_disp(buf
,val
,n
)
1345 if (val
< -64 || val
> 63)
1346 as_warn("Byte displacement out of range. line number not valid");
1349 printf("%x ",val
& 0xff);
1354 if (val
< -8192 || val
> 8191)
1355 as_warn("Word displacement out of range. line number not valid");
1359 printf("%x ",val
>>8 & 0xff);
1363 printf("%x ",val
& 0xff);
1368 if (val
< -0x1f000000 || val
>= 0x20000000)
1369 /* if (val < -0x20000000 || val >= 0x20000000) */
1370 as_warn("Double word displacement out of range");
1373 printf("%x ",val
>>24 & 0xff);
1377 printf("%x ",val
>>16 & 0xff);
1381 printf("%x ",val
>>8 & 0xff);
1385 printf("%x ",val
& 0xff);
1390 as_fatal("Internal logic error. line %s, file \"%s\"", __LINE__
, __FILE__
);
1394 static void md_number_to_imm(buf
,val
,n
)
1402 printf("%x ",val
& 0xff);
1408 printf("%x ",val
>>8 & 0xff);
1412 printf("%x ",val
& 0xff);
1418 printf("%x ",val
>>24 & 0xff);
1422 printf("%x ",val
>>16 & 0xff);
1426 printf("%x ",val
>>8 & 0xff);
1430 printf("%x ",val
& 0xff);
1435 as_fatal("Internal logic error. line %s, file \"%s\"", __LINE__
, __FILE__
);
1439 /* Translate internal representation of relocation info into target format.
1441 OVE: on a ns32k the twiddling continues at an even deeper level
1442 here we have to distinguish between displacements and immediates.
1444 The sequent has a bit for this. It also has a bit for relocobjects that
1445 points at the target for a bsr (BranchSubRoutine) !?!?!?!
1447 This md_ri.... is tailored for sequent.
1451 md_ri_to_chars(the_bytes
, ri
)
1453 struct reloc_info_generic
*ri
;
1455 if (ri
->r_bsr
) {ri
->r_pcrel
=0;} /* sequent seems to want this */
1456 md_number_to_chars(the_bytes
, ri
->r_address
, sizeof(ri
->r_address
));
1457 md_number_to_chars(the_bytes
+4,
1458 (long)(ri
->r_symbolnum
) |
1459 (long)(ri
->r_pcrel
<< 24 ) |
1460 (long)(ri
->r_length
<< 25 ) |
1461 (long)(ri
->r_extern
<< 27 ) |
1462 (long)(ri
->r_bsr
<< 28 ) |
1463 (long)(ri
->r_disp
<< 29 ),
1465 /* the first and second md_number_to_chars never overlaps (32bit cpu case) */
1468 /* fast bitfiddling support */
1469 /* mask used to zero bitfield before oring in the true field */
1471 static unsigned long l_mask
[]={ 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
1472 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
1473 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
1474 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
1475 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
1476 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
1477 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
1478 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
1480 static unsigned long r_mask
[]={ 0x00000000, 0x00000001, 0x00000003, 0x00000007,
1481 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
1482 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
1483 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
1484 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
1485 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
1486 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
1487 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
1489 #define MASK_BITS 31
1490 /* Insert bitfield described by field_ptr and val at buf
1491 This routine is written for modification of the first 4 bytes pointed
1492 to by buf, to yield speed.
1493 The ifdef stuff is for selection between a ns32k-dependent routine
1494 and a general version. (My advice: use the general version!)
1498 md_number_to_field(buf
,val
,field_ptr
)
1501 register bit_fixS
*field_ptr
;
1503 register unsigned long object
;
1504 register unsigned long mask
;
1505 /* define ENDIAN on a ns32k machine */
1507 register unsigned long *mem_ptr
;
1509 register char *mem_ptr
;
1511 if (field_ptr
->fx_bit_min
<=val
&& val
<=field_ptr
->fx_bit_max
) {
1513 if (field_ptr
->fx_bit_base
) { /* override buf */
1514 mem_ptr
=(unsigned long*)field_ptr
->fx_bit_base
;
1516 mem_ptr
=(unsigned long*)buf
;
1519 if (field_ptr
->fx_bit_base
) { /* override buf */
1520 mem_ptr
=(char*)field_ptr
->fx_bit_base
;
1525 mem_ptr
+=field_ptr
->fx_bit_base_adj
;
1526 #ifdef ENDIAN /* we have a nice ns32k machine with lowbyte at low-physical mem */
1527 object
= *mem_ptr
; /* get some bytes */
1528 #else /* OVE Goof! the machine is a m68k or dito */
1529 /* That takes more byte fiddling */
1531 object
|=mem_ptr
[3] & 0xff;
1533 object
|=mem_ptr
[2] & 0xff;
1535 object
|=mem_ptr
[1] & 0xff;
1537 object
|=mem_ptr
[0] & 0xff;
1540 mask
|=(r_mask
[field_ptr
->fx_bit_offset
]);
1541 mask
|=(l_mask
[field_ptr
->fx_bit_offset
+field_ptr
->fx_bit_size
]);
1543 val
+=field_ptr
->fx_bit_add
;
1544 object
|=((val
<<field_ptr
->fx_bit_offset
) & (mask
^ 0xffffffff));
1548 mem_ptr
[0]=(char)object
;
1550 mem_ptr
[1]=(char)object
;
1552 mem_ptr
[2]=(char)object
;
1554 mem_ptr
[3]=(char)object
;
1557 as_warn("Bit field out of range");
1561 /* Apply a fixS (fixup of an instruction or data that we didn't have
1562 enough info to complete immediately) to the data in a frag.
1564 On the ns32k, everything is in a different format, so we have broken
1565 out separate functions for each kind of thing we could be fixing.
1566 They all get called from here. */
1569 md_apply_fix(fixP
, val
)
1573 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
1575 if (fixP
->fx_bit_fixP
) { /* Bitfields to fix, sigh */
1576 md_number_to_field (buf
, val
, fixP
->fx_bit_fixP
);
1577 } else switch (fixP
->fx_im_disp
) {
1579 case 0: /* Immediate field */
1580 md_number_to_imm (buf
, val
, fixP
->fx_size
);
1583 case 1: /* Displacement field */
1584 md_number_to_disp (buf
,
1585 fixP
->fx_pcrel
? val
+ fixP
->fx_pcrel_adjust
: val
,
1589 case 2: /* Pointer in a data object */
1590 md_number_to_chars (buf
, val
, fixP
->fx_size
);
1595 /* Convert a relaxed displacement to ditto in final output */
1598 md_convert_frag(fragP
)
1599 register fragS
*fragP
;
1604 /* Address in gas core of the place to store the displacement. */
1605 register char *buffer_address
= fragP
-> fr_fix
+ fragP
-> fr_literal
;
1606 /* Address in object code of the displacement. */
1607 register int object_address
= fragP
-> fr_fix
+ fragP
-> fr_address
;
1609 know(fragP
->fr_symbol
);
1611 /* The displacement of the address, from current location. */
1612 disp
= (S_GET_VALUE(fragP
->fr_symbol
) + fragP
->fr_offset
) - object_address
;
1613 disp
+= fragP
->fr_pcrel_adjust
;
1615 switch(fragP
->fr_subtype
) {
1616 case IND(BRANCH
,BYTE
):
1619 case IND(BRANCH
,WORD
):
1622 case IND(BRANCH
,DOUBLE
):
1627 md_number_to_disp(buffer_address
,(long)disp
,(int)ext
);
1634 /* This function returns the estimated size a variable object will occupy,
1635 one can say that we tries to guess the size of the objects before we
1638 int md_estimate_size_before_relax(fragP
, segment
)
1639 register fragS
*fragP
;
1643 old_fix
=fragP
->fr_fix
;
1644 switch(fragP
->fr_subtype
) {
1645 case IND(BRANCH
,UNDEF
):
1646 if(S_GET_SEGMENT(fragP
->fr_symbol
) == segment
) {
1647 /* the symbol has been assigned a value */
1648 fragP
->fr_subtype
=IND(BRANCH
,BYTE
);
1650 /* we don't relax symbols defined in an other segment
1651 the thing to do is to assume the object will occupy 4 bytes */
1652 fix_new_ns32k(fragP
,
1653 (int)(fragP
->fr_fix
),
1659 fragP
->fr_pcrel_adjust
,
1662 fragP
->fr_bsr
); /*sequent hack */
1664 /* fragP->fr_opcode[1]=0xff; */
1668 case IND(BRANCH
,BYTE
):
1674 return fragP
->fr_var
+ fragP
->fr_fix
- old_fix
;
1677 int md_short_jump_size
= 3;
1678 int md_long_jump_size
= 5;
1679 int md_reloc_size
= 8; /* Size of relocation record */
1682 md_create_short_jump(ptr
,from_addr
,to_addr
,frag
,to_symbol
)
1691 offset
= to_addr
- from_addr
;
1692 md_number_to_chars(ptr
, (long)0xEA ,1);
1693 md_number_to_disp(ptr
+1,(long)offset
,2);
1697 md_create_long_jump(ptr
,from_addr
,to_addr
,frag
,to_symbol
)
1706 offset
= to_addr
- from_addr
;
1707 md_number_to_chars(ptr
, (long)0xEA, 2);
1708 md_number_to_disp(ptr
+2,(long)offset
,4);
1711 /* JF this is a new function to parse machine-dep options */
1713 md_parse_option(argP
,cntP
,vecP
)
1722 if(!strcmp(*argP
,"32032")) {
1723 cpureg
= cpureg_032
;
1724 mmureg
= mmureg_032
;
1725 } else if(!strcmp(*argP
, "32532")) {
1726 cpureg
= cpureg_532
;
1727 mmureg
= mmureg_532
;
1729 as_warn("Unknown -m option ignored");
1744 * Create a bit_fixS in obstack 'notes'.
1745 * This struct is used to profile the normal fix. If the bit_fixP is a
1746 * valid pointer (not NULL) the bit_fix data will be used to format the fix.
1748 bit_fixS
*bit_fix_new (size
,offset
,min
,max
,add
,base_type
,base_adj
)
1749 char size
; /* Length of bitfield */
1750 char offset
; /* Bit offset to bitfield */
1751 long base_type
; /* 0 or 1, if 1 it's exploded to opcode ptr */
1753 long min
; /* Signextended min for bitfield */
1754 long max
; /* Signextended max for bitfield */
1755 long add
; /* Add mask, used for huffman prefix */
1757 register bit_fixS
* bit_fixP
;
1759 bit_fixP
= (bit_fixS
*)obstack_alloc(¬es
,sizeof(bit_fixS
));
1761 bit_fixP
-> fx_bit_size
= size
;
1762 bit_fixP
-> fx_bit_offset
= offset
;
1763 bit_fixP
-> fx_bit_base
= base_type
;
1764 bit_fixP
-> fx_bit_base_adj
= base_adj
;
1765 bit_fixP
-> fx_bit_max
= max
;
1766 bit_fixP
-> fx_bit_min
= min
;
1767 bit_fixP
-> fx_bit_add
= add
;
1773 fix_new_ns32k (frag
, where
, size
, add_symbol
, sub_symbol
, offset
, pcrel
,
1774 pcrel_adjust
, im_disp
, bit_fixP
, bsr
)
1775 fragS
* frag
; /* Which frag? */
1776 int where
; /* Where in that frag? */
1777 short int size
; /* 1, 2 or 4 usually. */
1778 symbolS
* add_symbol
; /* X_add_symbol. */
1779 symbolS
* sub_symbol
; /* X_subtract_symbol. */
1780 long offset
; /* X_add_number. */
1781 int pcrel
; /* TRUE if PC-relative relocation. */
1782 char pcrel_adjust
; /* not zero if adjustment of pcrel offset is needed */
1783 char im_disp
; /* true if the value to write is a displacement */
1784 bit_fixS
*bit_fixP
; /* pointer at struct of bit_fix's, ignored if NULL */
1785 char bsr
; /* sequent-linker-hack: 1 when relocobject is a bsr */
1788 register fixS
* fixP
;
1790 fixP
= (fixS
*)obstack_alloc(¬es
,sizeof(fixS
));
1791 fixP
-> fx_frag
= frag
;
1792 fixP
-> fx_where
= where
;
1793 fixP
-> fx_size
= size
;
1794 fixP
-> fx_addsy
= add_symbol
;
1795 fixP
-> fx_subsy
= sub_symbol
;
1796 fixP
-> fx_offset
= offset
;
1797 fixP
-> fx_pcrel
= pcrel
;
1798 fixP
-> fx_pcrel_adjust
= pcrel_adjust
;
1799 fixP
-> fx_im_disp
= im_disp
;
1800 fixP
-> fx_bit_fixP
= bit_fixP
;
1801 fixP
-> fx_bsr
= bsr
;
1802 fixP
-> fx_next
= * seg_fix_rootP
;
1804 * seg_fix_rootP
= fixP
;
1807 /* We have no need to default values of symbols. */
1810 md_undefined_symbol (name
)
1816 /* Parse an operand that is machine-specific.
1817 We just return without modifying the expression if we have nothing
1822 md_operand (expressionP
)
1823 expressionS
*expressionP
;
1827 /* Round up a section size to the appropriate boundary. */
1829 md_section_align (segment
, size
)
1833 return size
; /* Byte alignment is fine */
1836 /* Exactly what point is a PC-relative offset relative TO?
1837 On the National warts, they're relative to the address of the offset,
1838 with some funny adjustments in some circumstances during blue moons.
1839 (??? Is this right? FIXME-SOON) */
1841 md_pcrel_from (fixP
)
1845 res
= fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
1846 #ifdef SEQUENT_COMPATABILITY
1847 if (fixP
->fx_frag
->fr_bsr
)
1848 res
+= 0x12 /* FOO Kludge alert! */
1855 * Revision 1.1 1991/04/04 18:17:05 rich
1867 /* end of tc-ns32k.c */