1 /* ns32k.c -- Assemble on the National Semiconductor 32k series
2 Copyright (C) 1987, 1992 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 2, 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 "opcode/ns32k.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
; /* length in bytes from the
115 instruction start to the
117 int im_disp
; /* True if the object is a displacement */
118 relax_substateT relax_substate
; /* Initial relaxsubstate */
119 bit_fixS
*bit_fixP
; /* Pointer at bit_fix struct */
120 int addr_mode
; /* What addrmode do we associate with this iif-entry */
121 char bsr
; /* Sequent hack */
122 }iif_entryT
; /* Internal Instruction Format */
124 struct int_ins_form
{
125 int instr_size
; /* Max size of instruction in bytes. */
126 iif_entryT iifP
[IIF_ENTRIES
+ 1];
128 struct int_ins_form iif
;
130 char *input_line_pointer
;
131 /* description of the PARTs in IIF
133 * 0 total length in bytes of entries in iif
146 * For every entry there is a datalength in bytes. This is stored in size[n].
147 * 0, the objectlength is not explicitly given by the instruction
148 * and the operand is undefined. This is a case for relaxation.
149 * Reserve 4 bytes for the final object.
151 * 1, the entry contains one byte
152 * 2, the entry contains two bytes
153 * 3, the entry contains three bytes
154 * 4, the entry contains four bytes
157 * Furthermore, every entry has a data type identifier in type[n].
159 * 0, the entry is void, ignore it.
160 * 1, the entry is a binary number.
161 * 2, the entry is a pointer at an expression.
162 * Where expression may be as simple as a single '1',
163 * and as complicated as foo-bar+12,
164 * foo and bar may be undefined but suffixed by :{b|w|d} to
165 * control the length of the object.
167 * 3, the entry is a pointer at a bignum struct
170 * The low-order-byte coresponds to low physical memory.
171 * Obviously a FRAGment must be created for each valid disp in PART whose
172 * datalength is undefined (to bad) .
173 * The case where just the expression is undefined is less severe and is
174 * handled by fix. Here the number of bytes in the objectfile is known.
175 * With this representation we simplify the assembly and separates the
176 * machine dependent/independent parts in a more clean way (said OE)
179 struct option opt1
[]= /* restore, exit */
181 { "r0", 0x80, 0xff },
182 { "r1", 0x40, 0xff },
183 { "r2", 0x20, 0xff },
184 { "r3", 0x10, 0xff },
185 { "r4", 0x08, 0xff },
186 { "r5", 0x04, 0xff },
187 { "r6", 0x02, 0xff },
188 { "r7", 0x01, 0xff },
191 struct option opt2
[]= /* save, enter */
193 { "r0", 0x01, 0xff },
194 { "r1", 0x02, 0xff },
195 { "r2", 0x04, 0xff },
196 { "r3", 0x08, 0xff },
197 { "r4", 0x10, 0xff },
198 { "r5", 0x20, 0xff },
199 { "r6", 0x40, 0xff },
200 { "r7", 0x80, 0xff },
203 struct option opt3
[]= /* setcfg */
211 struct option opt4
[]= /* cinv */
218 struct option opt5
[]= /* string inst */
225 struct option opt6
[]= /* plain reg ext,cvtp etc */
227 { "r0", 0x00, 0xff },
228 { "r1", 0x01, 0xff },
229 { "r2", 0x02, 0xff },
230 { "r3", 0x03, 0xff },
231 { "r4", 0x04, 0xff },
232 { "r5", 0x05, 0xff },
233 { "r6", 0x06, 0xff },
234 { "r7", 0x07, 0xff },
238 #if !defined(NS32032) && !defined(NS32532)
242 struct option cpureg_532
[]= /* lpr spr */
245 { "dcr", 0x1, 0xff },
246 { "bpc", 0x2, 0xff },
247 { "dsr", 0x3, 0xff },
248 { "car", 0x4, 0xff },
252 { "usp", 0xb, 0xff },
253 { "cfg", 0xc, 0xff },
254 { "psr", 0xd, 0xff },
255 { "intbase", 0xe, 0xff },
256 { "mod", 0xf, 0xff },
259 struct option mmureg_532
[]= /* lmr smr */
261 { "mcr", 0x9, 0xff },
262 { "msr", 0xa, 0xff },
263 { "tear", 0xb, 0xff },
264 { "ptb0", 0xc, 0xff },
265 { "ptb1", 0xd, 0xff },
266 { "ivar0", 0xe, 0xff },
267 { "ivar1", 0xf, 0xff },
271 struct option cpureg_032
[]= /* lpr spr */
273 { "upsr", 0x0, 0xff },
277 { "psr", 0xd, 0xff },
278 { "intbase", 0xe, 0xff },
279 { "mod", 0xf, 0xff },
282 struct option mmureg_032
[]= /* lmr smr */
284 { "bpr0", 0x0, 0xff },
285 { "bpr1", 0x1, 0xff },
286 { "pf0", 0x4, 0xff },
287 { "pf1", 0x5, 0xff },
289 { "msr", 0xa, 0xff },
290 { "bcnt", 0xb, 0xff },
291 { "ptb0", 0xc, 0xff },
292 { "ptb1", 0xd, 0xff },
293 { "eia", 0xf, 0xff },
298 struct option
*cpureg
= cpureg_532
;
299 struct option
*mmureg
= mmureg_532
;
301 struct option
*cpureg
= cpureg_032
;
302 struct option
*mmureg
= mmureg_032
;
306 const pseudo_typeS md_pseudo_table
[]={ /* so far empty */
310 #define IND(x,y) (((x)<<2)+(y))
312 /* those are index's to relax groups in md_relax_table
313 ie it must be multiplied by 4 to point at a group start. Viz IND(x,y)
314 Se function relax_segment in write.c for more info */
319 /* those are index's to entries in a relax group */
325 /* Those limits are calculated from the displacement start in memory.
326 The ns32k uses the begining of the instruction as displacement base.
327 This type of displacements could be handled here by moving the limit window
328 up or down. I choose to use an internal displacement base-adjust as there
329 are other routines that must consider this. Also, as we have two various
330 offset-adjusts in the ns32k (acb versus br/brs/jsr/bcond), two set of limits
331 would have had to be used.
332 Now we dont have to think about that. */
335 const relax_typeS md_relax_table
[] = {
341 { (63), (-64), 1, IND(BRANCH
,WORD
) },
342 { (8192), (-8192), 2, IND(BRANCH
,DOUBLE
) },
347 /* Array used to test if mode contains displacements.
348 Value is true if mode contains displacement. */
350 char disp_test
[] = { 0,0,0,0,0,0,0,0,
355 /* Array used to calculate max size of displacements */
357 char disp_size
[] = { 4,1,2,0,4 };
362 static segT
evaluate_expr(expressionS
*resultP
, char *ptr
);
363 static void md_number_to_disp(char *buf
, long val
, int n
);
364 static void md_number_to_imm(char *buf
, long val
, int n
);
366 #else /* not __STDC__ */
368 static segT
evaluate_expr();
369 static void md_number_to_disp();
370 static void md_number_to_imm();
372 #endif /* not __STDC__ */
374 /* Parses a general operand into an addressingmode struct
376 in: pointer at operand in ascii form
377 pointer at addr_mode struct for result
378 the level of recursion. (always 0 or 1)
380 out: data in addr_mode struct
382 int addr_mode(operand
,addr_modeP
,recursive_level
)
384 register addr_modeS
*addr_modeP
;
392 mode
= DEFAULT
; /* default */
393 addr_modeP
->scaled_mode
=0; /* why not */
394 addr_modeP
->scaled_reg
=0; /* if 0, not scaled index */
395 addr_modeP
->float_flag
=0;
396 addr_modeP
->am_size
=0;
397 addr_modeP
->im_disp
=0;
398 addr_modeP
->pcrel
=0; /* not set in this function */
399 addr_modeP
->disp_suffix
[0]=0;
400 addr_modeP
->disp_suffix
[1]=0;
401 addr_modeP
->disp
[0]=NULL
;
402 addr_modeP
->disp
[1]=NULL
;
404 if (str
[0]==0) {return (0);} /* we don't want this */
407 /* the following three case statements controls the mode-chars
408 this is the place to ed if you want to change them */
409 #ifdef ABSOLUTE_PREFIX
410 case ABSOLUTE_PREFIX
:
411 if (str
[strl
-1]==']') break;
412 addr_modeP
->mode
=21; /* absolute */
413 addr_modeP
->disp
[0]=str
+1;
416 #ifdef IMMEDIATE_PREFIX
417 case IMMEDIATE_PREFIX
:
418 if (str
[strl
-1]==']') break;
419 addr_modeP
->mode
=20; /* immediate */
420 addr_modeP
->disp
[0]=str
+1;
424 if (str
[strl
-1]!=']') {
427 if (str
[2]!='\000') {
428 addr_modeP
->mode
=27; /* pc-relativ */
429 addr_modeP
->disp
[0]=str
+2;
433 as_warn("Invalid syntax in PC-relative addressing mode");
439 if (str
[strl
-1]!=']') {
440 if((!strncmp(str
,"ext(",4)) && strl
>7) { /* external */
441 addr_modeP
->disp
[0]=str
+4;
444 do { /* disp[0]'s termination point */
446 if (str
[j
]=='(') i
++;
447 if (str
[j
]==')') i
--;
448 } while (j
<strl
&& i
!=0);
449 if (i
!=0 || !(str
[j
+1]=='-' || str
[j
+1]=='+') ) {
450 as_warn("Invalid syntax in External addressing mode");
453 str
[j
]='\000'; /* null terminate disp[0] */
454 addr_modeP
->disp
[1]=str
+j
+2;
466 case'f':addr_modeP
->float_flag
=1;
468 if (str
[1]>='0' && str
[1]<'8') {
469 addr_modeP
->mode
=str
[1]-'0';
474 if (!strncmp(str
,"tos",3)) {
475 addr_modeP
->mode
=23; /* TopOfStack */
481 if (str
[strl
-1]==')') {
482 if (str
[strl
-2]==')') {
483 if (!strncmp(&str
[strl
-5],"(fp",3)) {
484 mode
=16; /* Memory Relative */
486 if (!strncmp(&str
[strl
-5],"(sp",3)) {
489 if (!strncmp(&str
[strl
-5],"(sb",3)) {
492 if (mode
!=DEFAULT
) { /* memory relative */
493 addr_modeP
->mode
=mode
;
494 j
=strl
-5; /* temp for end of disp[0] */
498 if (str
[strl
]==')') i
++;
499 if (str
[strl
]=='(') i
--;
500 } while (strl
>-1 && i
!=0);
502 as_warn("Invalid syntax in Memory Relative addressing mode");
505 addr_modeP
->disp
[1]=str
;
506 addr_modeP
->disp
[0]=str
+strl
+1;
507 str
[j
]='\000'; /* null terminate disp[0] */
508 str
[strl
]='\000'; /* null terminate disp[1] */
512 switch (str
[strl
-3]) {
514 if (str
[strl
-2]>='0' && str
[strl
-2]<'8' && str
[strl
-4]=='(') {
515 addr_modeP
->mode
=str
[strl
-2]-'0'+8;
516 addr_modeP
->disp
[0]=str
;
518 return (-1); /* reg rel */
521 if (!strncmp(&str
[strl
-4],"(fp",3)) {
524 if (!strncmp(&str
[strl
-4],"(sp",3)) {
527 if (!strncmp(&str
[strl
-4],"(sb",3)) {
530 if (!strncmp(&str
[strl
-4],"(pc",3)) {
534 addr_modeP
->mode
=mode
;
535 addr_modeP
->disp
[0]=str
;
537 return (-1); /* memory space */
541 /* no trailing ')' do we have a ']' ? */
542 if (str
[strl
-1]==']') {
543 switch (str
[strl
-2]) {
544 case'b':mode
=28;break;
545 case'w':mode
=29;break;
546 case'd':mode
=30;break;
547 case'q':mode
=31;break;
549 as_warn("Invalid scaled-indexed mode, use (b,w,d,q)");
550 if (str
[strl
-3]!=':' || str
[strl
-6]!='[' ||
551 str
[strl
-5]=='r' || str
[strl
-4]<'0' || str
[strl
-4]>'7') {
552 as_warn("Syntax in scaled-indexed mode, use [Rn:m] where n=[0..7] m={b,w,d,q}");
556 if (recursive_level
>0) {
557 as_warn("Scaled-indexed addressing mode combined with scaled-index");
560 addr_modeP
->am_size
+=1; /* scaled index byte */
561 j
=str
[strl
-4]-'0'; /* store temporary */
562 str
[strl
-6]='\000'; /* nullterminate for recursive call */
563 i
=addr_mode(str
,addr_modeP
,1);
564 if (!i
|| addr_modeP
->mode
==20) {
565 as_warn("Invalid or illegal addressing mode combined with scaled-index");
568 addr_modeP
->scaled_mode
=addr_modeP
->mode
; /* store the inferior mode */
569 addr_modeP
->mode
=mode
;
570 addr_modeP
->scaled_reg
=j
+1;
575 addr_modeP
->mode
= DEFAULT
; /* default to whatever */
576 addr_modeP
->disp
[0]=str
;
580 /* ptr points at string
581 addr_modeP points at struct with result
582 This routine calls addr_mode to determine the general addr.mode of
583 the operand. When this is ready it parses the displacements for size
584 specifying suffixes and determines size of immediate mode via ns32k-opcode.
585 Also builds index bytes if needed.
587 int get_addr_mode(ptr
,addr_modeP
)
589 addr_modeS
*addr_modeP
;
592 addr_mode(ptr
,addr_modeP
,0);
593 if (addr_modeP
->mode
== DEFAULT
|| addr_modeP
->scaled_mode
== -1) {
594 /* resolve ambigious operands, this shouldn't
595 be necessary if one uses standard NSC operand
596 syntax. But the sequent compiler doesn't!!!
597 This finds a proper addressinging mode if it
598 is implicitly stated. See ns32k-opcode.h */
599 (void)evaluate_expr(&exprP
,ptr
); /* this call takes time Sigh! */
600 if (addr_modeP
->mode
== DEFAULT
) {
601 if (exprP
.X_add_symbol
|| exprP
.X_subtract_symbol
) {
602 addr_modeP
->mode
=desc
->default_model
; /* we have a label */
604 addr_modeP
->mode
=desc
->default_modec
; /* we have a constant */
607 if (exprP
.X_add_symbol
|| exprP
.X_subtract_symbol
) {
608 addr_modeP
->scaled_mode
=desc
->default_model
;
610 addr_modeP
->scaled_mode
=desc
->default_modec
;
613 /* must put this mess down in addr_mode to handle the scaled case better */
615 /* It appears as the sequent compiler wants an absolute when we have a
616 label without @. Constants becomes immediates besides the addr case.
617 Think it does so with local labels too, not optimum, pcrel is better.
618 When I have time I will make gas check this and select pcrel when possible
619 Actually that is trivial.
621 if (tmp
=addr_modeP
->scaled_reg
) { /* build indexbyte */
622 tmp
--; /* remember regnumber comes incremented for flagpurpose */
623 tmp
|=addr_modeP
->scaled_mode
<<3;
624 addr_modeP
->index_byte
=(char)tmp
;
625 addr_modeP
->am_size
+=1;
627 if (disp_test
[addr_modeP
->mode
]) { /* there was a displacement, probe for length specifying suffix*/
630 register char suffix
;
631 register char suffix_sub
;
634 register char *fromP
;
637 if (disp_test
[addr_modeP
->mode
]) { /* there is a displacement */
638 if (addr_modeP
->mode
==27 || addr_modeP
->scaled_mode
==27) { /* do we have pcrel. mode */
641 addr_modeP
->im_disp
=1;
644 if (toP
=addr_modeP
->disp
[i
]) { /* suffix of expression, the largest size rules */
646 while (c
= *fromP
++) {
651 as_warn("Premature end of suffix--Defaulting to d");
654 case 'b':suffix_sub
=1;break;
655 case 'w':suffix_sub
=2;break;
656 case 'd':suffix_sub
=4;break;
658 as_warn("Bad suffix after ':' use {b|w|d} Defaulting to d");
662 toP
--; /* So we write over the ':' */
663 if (suffix
<suffix_sub
) suffix
=suffix_sub
;
666 *toP
='\0'; /* terminate properly */
667 addr_modeP
->disp_suffix
[i
]=suffix
;
668 addr_modeP
->am_size
+=suffix
? suffix
: 4;
674 if (addr_modeP
->mode
==20) { /* look in ns32k_opcode for size */
675 addr_modeP
->disp_suffix
[0]=addr_modeP
->am_size
=desc
->im_size
;
676 addr_modeP
->im_disp
=0;
679 return addr_modeP
->mode
;
683 /* read an optionlist */
684 void optlist(str
,optionP
,default_map
)
685 char *str
; /* the string to extract options from */
686 struct option
*optionP
; /* how to search the string */
687 unsigned long *default_map
; /* default pattern and output */
689 register int i
,j
,k
,strlen1
,strlen2
;
690 register char *patternP
,*strP
;
693 as_fatal("Very short instr to option, ie you can't do it on a NULLstr");
695 for (i
=0;optionP
[i
].pattern
!=0;i
++) {
696 strlen2
=strlen(optionP
[i
].pattern
);
697 for (j
=0;j
<strlen1
;j
++) {
698 patternP
=optionP
[i
].pattern
;
700 for (k
=0;k
<strlen2
;k
++) {
701 if (*(strP
++)!=*(patternP
++)) break;
703 if (k
==strlen2
) { /* match */
704 *default_map
|=optionP
[i
].or;
705 *default_map
&=optionP
[i
].and;
710 /* search struct for symbols
711 This function is used to get the short integer form of reg names
712 in the instructions lmr, smr, lpr, spr
713 return true if str is found in list */
715 int list_search(str
,optionP
,default_map
)
716 char *str
; /* the string to match */
717 struct option
*optionP
; /* list to search */
718 unsigned long *default_map
; /* default pattern and output */
721 for (i
=0;optionP
[i
].pattern
!=0;i
++) {
722 if (!strncmp(optionP
[i
].pattern
,str
,20)) { /* use strncmp to be safe */
723 *default_map
|=optionP
[i
].or;
724 *default_map
&=optionP
[i
].and;
728 as_warn("No such entry in list. (cpu/mmu register)");
731 static segT
evaluate_expr(resultP
,ptr
)
732 expressionS
*resultP
;
735 register char *tmp_line
;
736 register segT segment
;
737 tmp_line
=input_line_pointer
;
738 input_line_pointer
=ptr
;
739 segment
=expression(&exprP
);
740 input_line_pointer
=tmp_line
;
744 /* Convert operands to iif-format and adds bitfields to the opcode.
745 Operands are parsed in such an order that the opcode is updated from
746 its most significant bit, that is when the operand need to alter the
748 Be carefull not to put to objects in the same iif-slot.
751 void encode_operand(argc
,argv
,operandsP
,suffixP
,im_size
,opcode_bit_ptr
)
760 int pcrel
,tmp
,b
,loop
,pcrel_adjust
;
761 for(loop
=0;loop
<argc
;loop
++) {
762 i
=operandsP
[loop
<<1]-'1'; /* what operand are we supposed to work on */
763 if (i
>3) as_fatal("Internal consistency error. check ns32k-opcode.h");
767 switch (operandsP
[(loop
<<1)+1]) {
768 case 'f': /* operand of sfsr turns out to be a nasty specialcase */
770 case 'F': /* 32 bit float general form */
771 case 'L': /* 64 bit float */
772 case 'Q': /* quad-word */
775 case 'D': /* double-word */
776 case 'A': /* double-word gen-address-form ie no regs allowed */
777 get_addr_mode(argv
[i
],&addr_modeP
);
778 iif
.instr_size
+=addr_modeP
.am_size
;
779 if (opcode_bit_ptr
==desc
->opcode_size
) b
=4; else b
=6;
780 for (j
=b
;j
<(b
+2);j
++) {
781 if (addr_modeP
.disp
[j
-b
]) {
784 addr_modeP
.disp_suffix
[j
-b
],
785 (unsigned long)addr_modeP
.disp
[j
-b
],
788 iif
.instr_size
-addr_modeP
.am_size
, /* this aint used (now) */
792 addr_modeP
.scaled_reg
? addr_modeP
.scaled_mode
:addr_modeP
.mode
,
797 iif
.iifP
[1].object
|=((long)addr_modeP
.mode
)<<opcode_bit_ptr
;
798 if (addr_modeP
.scaled_reg
) {
800 IIF(j
,1,1, (unsigned long)addr_modeP
.index_byte
,0,0,0,0,0, NULL
,-1,0);
803 case 'b': /* multiple instruction disp */
804 freeptr
++; /* OVE:this is an useful hack */
805 tmp
= (int) sprintf(freeptr
,
807 argv
[i
], desc
->im_size
);
810 pcrel
-=1; /* make pcrel 0 inspite of what case 'p': wants */
812 case 'p': /* displacement - pc relative addressing */
815 case 'd': /* displacement */
816 iif
.instr_size
+=suffixP
[i
] ? suffixP
[i
] : 4;
817 IIF(12, 2, suffixP
[i
], (unsigned long)argv
[i
], 0,
818 pcrel
, pcrel_adjust
, 1, IND(BRANCH
,BYTE
), NULL
,-1,0);
820 case 'H': /* sequent-hack: the linker wants a bit set when bsr */
822 iif
.instr_size
+=suffixP
[i
] ? suffixP
[i
] : 4;
823 IIF(12, 2, suffixP
[i
], (unsigned long)argv
[i
], 0,
824 pcrel
, pcrel_adjust
, 1, IND(BRANCH
,BYTE
), NULL
,-1,1);break;
825 case 'q': /* quick */
827 IIF(11,2,42,(unsigned long)argv
[i
],0,0,0,0,0,
828 bit_fix_new(4,opcode_bit_ptr
,-8,7,0,1,0),-1,0);
830 case 'r': /* register number (3 bits) */
831 list_search(argv
[i
],opt6
,&tmp
);
833 iif
.iifP
[1].object
|=tmp
<<opcode_bit_ptr
;
835 case 'O': /* setcfg instruction optionslist */
836 optlist(argv
[i
],opt3
,&tmp
);
838 iif
.iifP
[1].object
|=tmp
<<15;
840 case 'C': /* cinv instruction optionslist */
841 optlist(argv
[i
],opt4
,&tmp
);
843 iif
.iifP
[1].object
|=tmp
<<15;/*insert the regtype in opcode */
845 case 'S': /* stringinstruction optionslist */
846 optlist(argv
[i
],opt5
,&tmp
);
848 iif
.iifP
[1].object
|=tmp
<<15;
850 case 'u':case 'U': /* registerlist */
851 IIF(10,1,1,0,0,0,0,0,0,NULL
,-1,0);
852 switch (operandsP
[(i
<<1)+1]) {
853 case 'u': /* restore, exit */
854 optlist(argv
[i
],opt1
,&iif
.iifP
[10].object
);
856 case 'U': /* save,enter */
857 optlist(argv
[i
],opt2
,&iif
.iifP
[10].object
);
862 case 'M': /* mmu register */
863 list_search(argv
[i
],mmureg
,&tmp
);
865 iif
.iifP
[1].object
|=tmp
<<opcode_bit_ptr
;
867 case 'P': /* cpu register */
868 list_search(argv
[i
],cpureg
,&tmp
);
870 iif
.iifP
[1].object
|=tmp
<<opcode_bit_ptr
;
872 case 'g': /* inss exts */
873 iif
.instr_size
+=1; /* 1 byte is allocated after the opcode */
875 (unsigned long)argv
[i
], /* i always 2 here */
877 bit_fix_new(3,5,0,7,0,0,0), /* a bit_fix is targeted to the byte */
881 (unsigned long)argv
[i
], /* i always 3 here */
883 bit_fix_new(5,0,1,32,-1,0,-1),-1,0);
887 b
=2+i
; /* put the extension byte after opcode */
888 IIF(b
,2,1,0,0,0,0,0,0,0,-1,0);
890 as_fatal("Bad opcode-table-option, check in file ns32k-opcode.h");
895 /* in: instruction line
896 out: internal structure of instruction
897 that has been prepared for direct conversion to fragment(s) and
898 fixes in a systematical fashion
899 Return-value = recursive_level
901 /* build iif of one assembly text line */
902 int parse(line
,recursive_level
)
906 register char *lineptr
,c
,suffix_separator
;
910 char suffix
[MAX_ARGS
],*argv
[MAX_ARGS
];/* no more than 4 operands */
911 if (recursive_level
<=0) { /* called from md_assemble */
912 for (lineptr
=line
;(*lineptr
)!='\0' && (*lineptr
)!=' ';lineptr
++);
915 if (!(desc
=(struct ns32k_opcode
*)hash_find(inst_hash_handle
,line
))) {
916 as_fatal("No such opcode");
923 if (*desc
->operands
) {
924 if (*lineptr
++!='\0') {
927 while (*lineptr
!='\0') {
928 if (desc
->operands
[argc
<<1]) {
930 arg_type
=desc
->operands
[(argc
<<1)+1];
932 case 'd': case 'b': case 'p': case 'H': /* the operand is supposed to be a displacement */
933 /* Hackwarning: do not forget to update the 4 cases above when editing ns32k-opcode.h */
934 suffix_separator
=':';
937 suffix_separator
='\255'; /* if this char occurs we loose */
939 suffix
[argc
]=0; /* 0 when no ':' is encountered */
942 while ((c
= *lineptr
)!='\0' && c
!=sep
) {
950 if (c
==suffix_separator
) { /* ':' - label/suffix separator */
951 switch (lineptr
[1]) {
952 case 'b':suffix
[argc
]=1;break;
953 case 'w':suffix
[argc
]=2;break;
954 case 'd':suffix
[argc
]=4;break;
955 default: as_warn("Bad suffix, defaulting to d");
957 if (lineptr
[1]=='\0' || lineptr
[1]==sep
) {
970 if (*lineptr
=='\0') continue;
973 as_fatal("Too many operands passed to instruction");
978 if (argc
!=strlen(desc
->operands
)/2) {
979 if (strlen(desc
->default_args
)) { /* we can apply default, dont goof */
980 if (parse(desc
->default_args
,1)!=1) { /* check error in default */
981 as_fatal("Wrong numbers of operands in default, check ns32k-opcodes.h");
984 as_fatal("Wrong number of operands");
988 for (i
=0;i
<IIF_ENTRIES
;i
++) {
989 iif
.iifP
[i
].type
=0; /* mark all entries as void*/
992 /* build opcode iif-entry */
993 iif
.instr_size
=desc
->opcode_size
/8;
994 IIF(1,1,iif
.instr_size
,desc
->opcode_seed
,0,0,0,0,0,0,-1,0);
996 /* this call encodes operands to iif format */
1005 return recursive_level
;
1009 /* Convert iif to fragments.
1010 From this point we start to dribble with functions in other files than
1011 this one.(Except hash.c) So, if it's possible to make an iif for an other
1012 CPU, you don't need to know what frags, relax, obstacks, etc is in order
1013 to port this assembler. You only need to know if it's possible to reduce
1014 your cpu-instruction to iif-format (takes some work) and adopt the other
1015 md_? parts according to given instructions
1016 Note that iif was invented for the clean ns32k`s architecure.
1018 void convert_iif() {
1028 int rem_size
; /* count the remaining bytes of instruction */
1031 int size_so_far
= 0; /* used to calculate pcrel_adjust */
1033 rem_size
=iif
.instr_size
;
1034 memP
=frag_more(iif
.instr_size
); /* make sure we have enough bytes for instruction */
1036 inst_offset
=(char*)(memP
-frag_now
->fr_literal
);
1038 for (i
=0;i
<IIF_ENTRIES
;i
++) {
1039 if (type
=iif
.iifP
[i
].type
) { /* the object exist, so handle it */
1040 switch (size
=iif
.iifP
[i
].size
) {
1041 case 42: size
=0; /* it's a bitfix that operates on an existing object*/
1042 if (iif
.iifP
[i
].bit_fixP
->fx_bit_base
) { /* expand fx_bit_base to point at opcode */
1043 iif
.iifP
[i
].bit_fixP
->fx_bit_base
=(long)inst_opcode
;
1045 case 8: /* bignum or doublefloat */
1046 memset(memP
, '\0', 8);
1047 case 1:case 2:case 3:case 4:/* the final size in objectmemory is known */
1048 j
=(unsigned long)iif
.iifP
[i
].bit_fixP
;
1050 case 1: /* the object is pure binary */
1051 if (j
|| iif
.iifP
[i
].pcrel
) {
1052 fix_new_ns32k(frag_now
,
1053 (long)(memP
-frag_now
->fr_literal
),
1059 (char)size_so_far
, /*iif.iifP[i].pcrel_adjust,*/
1060 iif
.iifP
[i
].im_disp
,
1062 iif
.iifP
[i
].bsr
); /* sequent hack */
1063 } else { /* good, just put them bytes out */
1064 switch (iif
.iifP
[i
].im_disp
) {
1066 md_number_to_chars(memP
,iif
.iifP
[i
].object
,size
);break;
1068 md_number_to_disp(memP
,iif
.iifP
[i
].object
,size
);break;
1069 default: as_fatal("iif convert internal pcrel/binary");
1075 case 2: /* the object is a pointer at an expression, so unpack
1076 it, note that bignums may result from the expression
1078 if ((segment
=evaluate_expr(&exprP
,(char*)iif
.iifP
[i
].object
))==SEG_BIG
|| size
==8) {
1079 if ((k
=exprP
.X_add_number
)>0) { /* we have a bignum ie a quad */
1080 /* this can only happens in a long suffixed instruction */
1081 memset(memP
, '\0', size
); /* size normally is 8 */
1082 if (k
*2>size
) as_warn("Bignum too big for long");
1084 for (l
=0;k
>0;k
--,l
+=2) {
1085 md_number_to_chars(memP
+l
,generic_bignum
[l
>>1],sizeof(LITTLENUM_TYPE
));
1087 } else { /* flonum */
1088 LITTLENUM_TYPE words
[4];
1092 gen_to_words(words
,2,8);
1093 md_number_to_imm(memP
,(long)words
[0],sizeof(LITTLENUM_TYPE
));
1094 md_number_to_imm(memP
+sizeof(LITTLENUM_TYPE
),(long)words
[1],sizeof(LITTLENUM_TYPE
));
1097 gen_to_words(words
,4,11);
1098 md_number_to_imm(memP
,(long)words
[0],sizeof(LITTLENUM_TYPE
));
1099 md_number_to_imm(memP
+sizeof(LITTLENUM_TYPE
) ,(long)words
[1],sizeof(LITTLENUM_TYPE
));
1100 md_number_to_imm(memP
+2*sizeof(LITTLENUM_TYPE
),(long)words
[2],sizeof(LITTLENUM_TYPE
));
1101 md_number_to_imm(memP
+3*sizeof(LITTLENUM_TYPE
),(long)words
[3],sizeof(LITTLENUM_TYPE
));
1110 exprP
.X_add_symbol
||
1111 exprP
.X_subtract_symbol
||
1112 iif
.iifP
[i
].pcrel
) { /* fixit */
1113 /* the expression was undefined due to an undefined label */
1114 /* create a fix so we can fix the object later */
1115 exprP
.X_add_number
+=iif
.iifP
[i
].object_adjust
;
1116 fix_new_ns32k(frag_now
,
1117 (long)(memP
-frag_now
->fr_literal
),
1120 exprP
.X_subtract_symbol
,
1123 (char)size_so_far
, /*iif.iifP[i].pcrel_adjust,*/
1124 iif
.iifP
[i
].im_disp
,
1126 iif
.iifP
[i
].bsr
); /* sequent hack */
1128 } else { /* good, just put them bytes out */
1129 switch (iif
.iifP
[i
].im_disp
) {
1131 md_number_to_imm(memP
,exprP
.X_add_number
,size
);break;
1133 md_number_to_disp(memP
,exprP
.X_add_number
,size
);break;
1134 default: as_fatal("iif convert internal pcrel/pointer");
1140 default: as_fatal("Internal logic error in iif.iifP[n].type");
1143 case 0: /* To bad, the object may be undefined as far as its final
1144 nsize in object memory is concerned. The size of the object
1145 in objectmemory is not explicitly given.
1146 If the object is defined its length can be determined and
1147 a fix can replace the frag.
1151 segment
=evaluate_expr(&exprP
,(char*)iif
.iifP
[i
].object
);
1152 if ((exprP
.X_add_symbol
|| exprP
.X_subtract_symbol
) &&
1153 !iif
.iifP
[i
].pcrel
) { /* OVE: hack, clamp to 4 bytes */
1154 size
=4; /* we dont wan't to frag this, use 4 so it reaches */
1155 fix_new_ns32k(frag_now
,
1156 (long)(memP
-frag_now
->fr_literal
),
1159 exprP
.X_subtract_symbol
,
1161 0, /* never iif.iifP[i].pcrel, */
1162 (char)size_so_far
, /*iif.iifP[i].pcrel_adjust,*/
1163 1, /* always iif.iifP[i].im_disp, */
1167 break; /* exit this absolute hack */
1170 if (exprP
.X_add_symbol
|| exprP
.X_subtract_symbol
) { /* frag it */
1171 if (exprP
.X_subtract_symbol
) { /* We cant relax this case */
1172 as_fatal("Can't relax difference");
1175 /* at this stage we must undo some of the effect caused
1176 by frag_more, ie we must make sure that frag_var causes
1177 frag_new to creat a valid fix-size in the frag it`s closing
1179 temp
= -(rem_size
-4);
1180 obstack_blank_fast(&frags
,temp
);
1181 /* we rewind none, some or all of the requested size we
1182 requested by the first frag_more for this iif chunk.
1183 Note: that we allocate 4 bytes to an object we NOT YET
1184 know the size of, thus rem_size-4.
1186 (void)frag_variant(rs_machine_dependent
,
1189 IND(BRANCH
,UNDEF
), /* expecting the worst */
1193 (char)size_so_far
, /*iif.iifP[i].pcrel_adjust);*/
1194 iif
.iifP
[i
].bsr
); /* sequent linker hack */
1197 memP
=frag_more(rem_size
);
1201 else {/* Double work, this is done in md_number_to_disp */
1202 /* exprP.X_add_number; what was this supposed to be?
1204 if (-64<=exprP
.X_add_number
&& exprP
.X_add_number
<=63) {
1207 if (-8192<=exprP
.X_add_number
&& exprP
.X_add_number
<=8191) {
1210 if (-0x1f000000<=exprP
.X_add_number
&&
1211 exprP
.X_add_number
<=0x1fffffff)
1212 /* if (-0x40000000<=exprP.X_add_number &&
1213 exprP.X_add_number<=0x3fffffff) */
1217 as_warn("Displacement to large for :d");
1222 /* rewind the bytes not used */
1224 md_number_to_disp(memP
,exprP
.X_add_number
,size
);
1225 obstack_blank_fast(&frags
,temp
);
1227 rem_size
-=4; /* we allocated this amount */
1232 as_fatal("Internal logic error in iif.iifP[].type");
1240 void md_assemble(line
)
1243 freeptr
=freeptr_static
;
1244 parse(line
,0); /* explode line to more fix form in iif */
1245 convert_iif(); /* convert iif to frags, fix's etc */
1247 printf(" \t\t\t%s\n",line
);
1253 /* build a hashtable of the instructions */
1254 register const struct ns32k_opcode
*ptr
;
1255 register char *stat
;
1256 inst_hash_handle
=hash_new();
1257 for (ptr
=ns32k_opcodes
;ptr
<endop
;ptr
++) {
1258 if (*(stat
=hash_insert(inst_hash_handle
,ptr
->name
,(char*)ptr
))) {
1259 as_fatal("Can't hash %s: %s", ptr
->name
,stat
); /*fatal*/
1263 freeptr_static
=(char*)malloc(PRIVATE_SIZE
); /* some private space please! */
1269 free(freeptr_static
);
1272 /* Must be equal to MAX_PRECISON in atof-ieee.c */
1273 #define MAX_LITTLENUMS 6
1275 /* Turn the string pointed to by litP into a floating point constant of type
1276 type, and emit the appropriate bytes. The number of LITTLENUMS emitted
1277 is stored in *sizeP . An error message is returned, or NULL on OK.
1280 md_atof(type
,litP
,sizeP
)
1286 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
1287 LITTLENUM_TYPE
*wordP
;
1300 return "Bad call to MD_ATOF()";
1302 t
=atof_ieee(input_line_pointer
,type
,words
);
1304 input_line_pointer
=t
;
1306 *sizeP
=prec
* sizeof(LITTLENUM_TYPE
);
1307 for(wordP
=words
+prec
;prec
--;) {
1308 md_number_to_chars(litP
,(long)(*--wordP
),sizeof(LITTLENUM_TYPE
));
1309 litP
+=sizeof(LITTLENUM_TYPE
);
1311 return ""; /* Someone should teach Dean about null pointers */
1314 /* Convert number to chars in correct order */
1317 md_number_to_chars (buf
, value
, nbytes
)
1324 printf("%x ",value
& 0xff);
1326 *buf
++ = value
; /* Lint wants & MASK_CHAR. */
1327 value
>>= BITS_PER_CHAR
;
1329 } /* md_number_to_chars() */
1332 /* This is a variant of md_numbers_to_chars. The reason for its' existence
1333 is the fact that ns32k uses Huffman coded displacements. This implies
1334 that the bit order is reversed in displacements and that they are prefixed
1339 10xxxxxx xxxxxxxx word
1340 11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx double word
1342 This must be taken care of and we do it here!
1344 static void md_number_to_disp(buf
, val
, n
)
1351 if (val
< -64 || val
> 63)
1352 as_warn("Byte displacement out of range. line number not valid");
1355 printf("%x ",val
& 0xff);
1360 if (val
< -8192 || val
> 8191)
1361 as_warn("Word displacement out of range. line number not valid");
1365 printf("%x ",val
>>8 & 0xff);
1369 printf("%x ",val
& 0xff);
1374 if (val
< -0x1f000000 || val
>= 0x20000000)
1375 /* if (val < -0x20000000 || val >= 0x20000000) */
1376 as_warn("Double word displacement out of range");
1379 printf("%x ",val
>>24 & 0xff);
1383 printf("%x ",val
>>16 & 0xff);
1387 printf("%x ",val
>>8 & 0xff);
1391 printf("%x ",val
& 0xff);
1396 as_fatal("Internal logic error. line %s, file \"%s\"", __LINE__
, __FILE__
);
1400 static void md_number_to_imm(buf
,val
,n
)
1408 printf("%x ",val
& 0xff);
1414 printf("%x ",val
>>8 & 0xff);
1418 printf("%x ",val
& 0xff);
1424 printf("%x ",val
>>24 & 0xff);
1428 printf("%x ",val
>>16 & 0xff);
1432 printf("%x ",val
>>8 & 0xff);
1436 printf("%x ",val
& 0xff);
1441 as_fatal("Internal logic error. line %s, file \"%s\"", __LINE__
, __FILE__
);
1445 /* Translate internal representation of relocation info into target format.
1447 OVE: on a ns32k the twiddling continues at an even deeper level
1448 here we have to distinguish between displacements and immediates.
1450 The sequent has a bit for this. It also has a bit for relocobjects that
1451 points at the target for a bsr (BranchSubRoutine) !?!?!?!
1453 This md_ri.... is tailored for sequent.
1458 md_ri_to_chars(the_bytes
, ri
)
1460 struct reloc_info_generic
*ri
;
1462 if (ri
->r_bsr
) { ri
->r_pcrel
= 0; } /* sequent seems to want this */
1463 md_number_to_chars(the_bytes
, ri
->r_address
, sizeof(ri
->r_address
));
1464 md_number_to_chars(the_bytes
+4, ((long)(ri
->r_symbolnum
)
1465 | (long)(ri
->r_pcrel
<< 24 )
1466 | (long)(ri
->r_length
<< 25 )
1467 | (long)(ri
->r_extern
<< 27 )
1468 | (long)(ri
->r_bsr
<< 28 )
1469 | (long)(ri
->r_disp
<< 29 )),
1471 /* the first and second md_number_to_chars never overlaps (32bit cpu case) */
1473 #endif /* comment */
1475 /* fast bitfiddling support */
1476 /* mask used to zero bitfield before oring in the true field */
1478 static unsigned long l_mask
[]={ 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
1479 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
1480 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
1481 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
1482 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
1483 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
1484 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
1485 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000,
1487 static unsigned long r_mask
[]={ 0x00000000, 0x00000001, 0x00000003, 0x00000007,
1488 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
1489 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
1490 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
1491 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
1492 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
1493 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
1494 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
1496 #define MASK_BITS 31
1497 /* Insert bitfield described by field_ptr and val at buf
1498 This routine is written for modification of the first 4 bytes pointed
1499 to by buf, to yield speed.
1500 The ifdef stuff is for selection between a ns32k-dependent routine
1501 and a general version. (My advice: use the general version!)
1505 md_number_to_field(buf
,val
,field_ptr
)
1508 register bit_fixS
*field_ptr
;
1510 register unsigned long object
;
1511 register unsigned long mask
;
1512 /* define ENDIAN on a ns32k machine */
1514 register unsigned long *mem_ptr
;
1516 register char *mem_ptr
;
1518 if (field_ptr
->fx_bit_min
<=val
&& val
<=field_ptr
->fx_bit_max
) {
1520 if (field_ptr
->fx_bit_base
) { /* override buf */
1521 mem_ptr
=(unsigned long*)field_ptr
->fx_bit_base
;
1523 mem_ptr
=(unsigned long*)buf
;
1526 if (field_ptr
->fx_bit_base
) { /* override buf */
1527 mem_ptr
=(char*)field_ptr
->fx_bit_base
;
1532 mem_ptr
+=field_ptr
->fx_bit_base_adj
;
1533 #ifdef ENDIAN /* we have a nice ns32k machine with lowbyte at low-physical mem */
1534 object
= *mem_ptr
; /* get some bytes */
1535 #else /* OVE Goof! the machine is a m68k or dito */
1536 /* That takes more byte fiddling */
1538 object
|=mem_ptr
[3] & 0xff;
1540 object
|=mem_ptr
[2] & 0xff;
1542 object
|=mem_ptr
[1] & 0xff;
1544 object
|=mem_ptr
[0] & 0xff;
1547 mask
|=(r_mask
[field_ptr
->fx_bit_offset
]);
1548 mask
|=(l_mask
[field_ptr
->fx_bit_offset
+field_ptr
->fx_bit_size
]);
1550 val
+=field_ptr
->fx_bit_add
;
1551 object
|=((val
<<field_ptr
->fx_bit_offset
) & (mask
^ 0xffffffff));
1555 mem_ptr
[0]=(char)object
;
1557 mem_ptr
[1]=(char)object
;
1559 mem_ptr
[2]=(char)object
;
1561 mem_ptr
[3]=(char)object
;
1564 as_warn("Bit field out of range");
1568 /* Apply a fixS (fixup of an instruction or data that we didn't have
1569 enough info to complete immediately) to the data in a frag.
1571 On the ns32k, everything is in a different format, so we have broken
1572 out separate functions for each kind of thing we could be fixing.
1573 They all get called from here. */
1576 md_apply_fix(fixP
, val
)
1580 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
1582 if (fixP
->fx_bit_fixP
) { /* Bitfields to fix, sigh */
1583 md_number_to_field (buf
, val
, fixP
->fx_bit_fixP
);
1584 } else switch (fixP
->fx_im_disp
) {
1586 case 0: /* Immediate field */
1587 md_number_to_imm (buf
, val
, fixP
->fx_size
);
1590 case 1: /* Displacement field */
1591 md_number_to_disp (buf
,
1592 fixP
->fx_pcrel
? val
+ fixP
->fx_pcrel_adjust
: val
,
1596 case 2: /* Pointer in a data object */
1597 md_number_to_chars (buf
, val
, fixP
->fx_size
);
1602 /* Convert a relaxed displacement to ditto in final output */
1605 md_convert_frag(headers
, fragP
)
1606 object_headers
*headers
;
1607 register fragS
*fragP
;
1612 /* Address in gas core of the place to store the displacement. */
1613 register char *buffer_address
= fragP
->fr_fix
+ fragP
->fr_literal
;
1614 /* Address in object code of the displacement. */
1615 register int object_address
= fragP
->fr_fix
+ fragP
->fr_address
;
1617 know(fragP
->fr_symbol
);
1619 /* The displacement of the address, from current location. */
1620 disp
= (S_GET_VALUE(fragP
->fr_symbol
) + fragP
->fr_offset
) - object_address
;
1621 disp
+= fragP
->fr_pcrel_adjust
;
1623 switch(fragP
->fr_subtype
) {
1624 case IND(BRANCH
,BYTE
):
1627 case IND(BRANCH
,WORD
):
1630 case IND(BRANCH
,DOUBLE
):
1635 md_number_to_disp(buffer_address
,(long)disp
,(int)ext
);
1642 /* This function returns the estimated size a variable object will occupy,
1643 one can say that we tries to guess the size of the objects before we
1646 int md_estimate_size_before_relax(fragP
, segment
)
1647 register fragS
*fragP
;
1651 old_fix
=fragP
->fr_fix
;
1652 switch(fragP
->fr_subtype
) {
1653 case IND(BRANCH
,UNDEF
):
1654 if(S_GET_SEGMENT(fragP
->fr_symbol
) == segment
) {
1655 /* the symbol has been assigned a value */
1656 fragP
->fr_subtype
=IND(BRANCH
,BYTE
);
1658 /* we don't relax symbols defined in an other segment
1659 the thing to do is to assume the object will occupy 4 bytes */
1660 fix_new_ns32k(fragP
,
1661 (int)(fragP
->fr_fix
),
1667 fragP
->fr_pcrel_adjust
,
1670 fragP
->fr_bsr
); /*sequent hack */
1672 /* fragP->fr_opcode[1]=0xff; */
1676 case IND(BRANCH
,BYTE
):
1682 return fragP
->fr_var
+ fragP
->fr_fix
- old_fix
;
1685 int md_short_jump_size
= 3;
1686 int md_long_jump_size
= 5;
1687 int md_reloc_size
= 8; /* Size of relocation record */
1690 md_create_short_jump(ptr
,from_addr
,to_addr
,frag
,to_symbol
)
1699 offset
= to_addr
- from_addr
;
1700 md_number_to_chars(ptr
, (long)0xEA ,1);
1701 md_number_to_disp(ptr
+1,(long)offset
,2);
1705 md_create_long_jump(ptr
,from_addr
,to_addr
,frag
,to_symbol
)
1714 offset
= to_addr
- from_addr
;
1715 md_number_to_chars(ptr
, (long)0xEA, 2);
1716 md_number_to_disp(ptr
+2,(long)offset
,4);
1719 /* JF this is a new function to parse machine-dep options */
1721 md_parse_option(argP
,cntP
,vecP
)
1730 if(!strcmp(*argP
,"32032")) {
1731 cpureg
= cpureg_032
;
1732 mmureg
= mmureg_032
;
1733 } else if(!strcmp(*argP
, "32532")) {
1734 cpureg
= cpureg_532
;
1735 mmureg
= mmureg_532
;
1737 as_warn("Unknown -m option ignored");
1752 * Create a bit_fixS in obstack 'notes'.
1753 * This struct is used to profile the normal fix. If the bit_fixP is a
1754 * valid pointer (not NULL) the bit_fix data will be used to format the fix.
1756 bit_fixS
*bit_fix_new(size
, offset
, min
, max
, add
, base_type
, base_adj
)
1757 char size
; /* Length of bitfield */
1758 char offset
; /* Bit offset to bitfield */
1759 long base_type
; /* 0 or 1, if 1 it's exploded to opcode ptr */
1761 long min
; /* Signextended min for bitfield */
1762 long max
; /* Signextended max for bitfield */
1763 long add
; /* Add mask, used for huffman prefix */
1765 register bit_fixS
* bit_fixP
;
1767 bit_fixP
= (bit_fixS
*)obstack_alloc(¬es
,sizeof(bit_fixS
));
1769 bit_fixP
->fx_bit_size
= size
;
1770 bit_fixP
->fx_bit_offset
= offset
;
1771 bit_fixP
->fx_bit_base
= base_type
;
1772 bit_fixP
->fx_bit_base_adj
= base_adj
;
1773 bit_fixP
->fx_bit_max
= max
;
1774 bit_fixP
->fx_bit_min
= min
;
1775 bit_fixP
->fx_bit_add
= add
;
1781 fix_new_ns32k(frag
, where
, size
, add_symbol
, sub_symbol
, offset
, pcrel
,
1782 pcrel_adjust
, im_disp
, bit_fixP
, bsr
)
1783 fragS
*frag
; /* Which frag? */
1784 int where
; /* Where in that frag? */
1785 int size
; /* 1, 2 or 4 usually. */
1786 symbolS
*add_symbol
; /* X_add_symbol. */
1787 symbolS
*sub_symbol
; /* X_subtract_symbol. */
1788 long offset
; /* X_add_number. */
1789 int pcrel
; /* TRUE if PC-relative relocation. */
1790 char pcrel_adjust
; /* not zero if adjustment of pcrel offset is needed */
1791 char im_disp
; /* true if the value to write is a displacement */
1792 bit_fixS
*bit_fixP
; /* pointer at struct of bit_fix's, ignored if NULL */
1793 char bsr
; /* sequent-linker-hack: 1 when relocobject is a bsr */
1796 fixS
*fixP
= fix_new(frag
, where
, size
, add_symbol
, sub_symbol
,
1797 offset
, pcrel
, NO_RELOC
);
1799 fixP
->fx_pcrel_adjust
= pcrel_adjust
;
1800 fixP
->fx_im_disp
= im_disp
;
1801 fixP
->fx_bit_fixP
= bit_fixP
;
1803 } /* fix_new_ns32k() */
1805 /* We have no need to default values of symbols. */
1808 md_undefined_symbol (name
)
1814 /* Parse an operand that is machine-specific.
1815 We just return without modifying the expression if we have nothing
1820 md_operand (expressionP
)
1821 expressionS
*expressionP
;
1825 /* Round up a section size to the appropriate boundary. */
1827 md_section_align (segment
, size
)
1831 return size
; /* Byte alignment is fine */
1834 /* Exactly what point is a PC-relative offset relative TO?
1835 On the National warts, they're relative to the address of the offset,
1836 with some funny adjustments in some circumstances during blue moons.
1837 (??? Is this right? FIXME-SOON) */
1839 md_pcrel_from (fixP
)
1843 res
= fixP
->fx_where
+ fixP
->fx_frag
->fr_address
;
1844 #ifdef SEQUENT_COMPATABILITY
1845 if (fixP
->fx_frag
->fr_bsr
)
1846 res
+= 0x12 /* FOO Kludge alert! */
1851 void tc_aout_fix_to_chars(char *where
, struct fix
*fixP
,
1852 relax_addressT segment_address
) {
1853 know(0); /* know nothing */
1862 /* end of tc-ns32k.c */