]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gas/config/tc-ns32k.c
Initial revision
[thirdparty/binutils-gdb.git] / gas / config / tc-ns32k.c
1 /* ns32k.c -- Assemble on the National Semiconductor 32k series
2 Copyright (C) 1987 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 1, 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 "ns32k-opcode.h"
30
31 #include "as.h"
32
33 #include "obstack.h"
34
35 /* Macros */
36 #define IIF_ENTRIES 13 /* number of entries in iif */
37 #define PRIVATE_SIZE 256 /* size of my garbage memory */
38 #define MAX_ARGS 4
39 #define DEFAULT -1 /* addr_mode returns this value when plain constant or label is encountered */
40
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;
53
54 #ifdef SEQUENT_COMPATABILITY
55 #define LINE_COMMENT_CHARS "|"
56 #define ABSOLUTE_PREFIX '@'
57 #define IMMEDIATE_PREFIX '#'
58 #endif
59
60 #ifndef LINE_COMMENT_CHARS
61 #define LINE_COMMENT_CHARS "#"
62 #endif
63
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 */
68 #endif
69
70 struct addr_mode {
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 */
82 };
83 typedef struct addr_mode addr_modeS;
84
85
86 char *freeptr,*freeptr_static; /* points at some number of free bytes */
87 struct hash_control *inst_hash_handle;
88
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 */
93
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 */
100
101 /* internal structs */
102 struct option {
103 char *pattern;
104 unsigned long or;
105 unsigned long and;
106 };
107
108 typedef struct {
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];
124 };
125 struct int_ins_form iif;
126 expressionS exprP;
127 char *input_line_pointer;
128 /* description of the PARTs in IIF
129 *object[n]:
130 * 0 total length in bytes of entries in iif
131 * 1 opcode
132 * 2 index_byte_a
133 * 3 index_byte_b
134 * 4 disp_a_1
135 * 5 disp_a_2
136 * 6 disp_b_1
137 * 7 disp_b_2
138 * 8 imm_a
139 * 9 imm_b
140 * 10 implied1
141 * 11 implied2
142 *
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.
147 *
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
152 * etc
153 *
154 * Furthermore, every entry has a data type identifier in type[n].
155 *
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.
163 *
164 * 3, the entry is a pointer at a bignum struct
165 *
166 *
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)
174 */
175 \f
176 struct option opt1[]= /* restore, exit */
177 {
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 },
186 { 0 , 0x00, 0xff }
187 };
188 struct option opt2[]= /* save, enter */
189 {
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 },
198 { 0 , 0x00, 0xff }
199 };
200 struct option opt3[]= /* setcfg */
201 {
202 { "c", 0x8, 0xff },
203 { "m", 0x4, 0xff },
204 { "f", 0x2, 0xff },
205 { "i", 0x1, 0xff },
206 { 0 , 0x0, 0xff }
207 };
208 struct option opt4[]= /* cinv */
209 {
210 { "a", 0x4, 0xff },
211 { "i", 0x2, 0xff },
212 { "d", 0x1, 0xff },
213 { 0 , 0x0, 0xff }
214 };
215 struct option opt5[]= /* string inst */
216 {
217 { "b", 0x2, 0xff },
218 { "u", 0xc, 0xff },
219 { "w", 0x4, 0xff },
220 { 0 , 0x0, 0xff }
221 };
222 struct option opt6[]= /* plain reg ext,cvtp etc */
223 {
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 },
232 { 0 , 0x00, 0xff }
233 };
234
235 #if !defined(NS32032) && !defined(NS32532)
236 #define NS32032
237 #endif
238
239 struct option cpureg_532[]= /* lpr spr */
240 {
241 { "us", 0x0, 0xff },
242 { "dcr", 0x1, 0xff },
243 { "bpc", 0x2, 0xff },
244 { "dsr", 0x3, 0xff },
245 { "car", 0x4, 0xff },
246 { "fp", 0x8, 0xff },
247 { "sp", 0x9, 0xff },
248 { "sb", 0xa, 0xff },
249 { "usp", 0xb, 0xff },
250 { "cfg", 0xc, 0xff },
251 { "psr", 0xd, 0xff },
252 { "intbase", 0xe, 0xff },
253 { "mod", 0xf, 0xff },
254 { 0 , 0x00, 0xff }
255 };
256 struct option mmureg_532[]= /* lmr smr */
257 {
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 },
265 { 0 , 0x0, 0xff }
266 };
267
268 struct option cpureg_032[]= /* lpr spr */
269 {
270 { "upsr", 0x0, 0xff },
271 { "fp", 0x8, 0xff },
272 { "sp", 0x9, 0xff },
273 { "sb", 0xa, 0xff },
274 { "psr", 0xd, 0xff },
275 { "intbase", 0xe, 0xff },
276 { "mod", 0xf, 0xff },
277 { 0 , 0x0, 0xff }
278 };
279 struct option mmureg_032[]= /* lmr smr */
280 {
281 { "bpr0", 0x0, 0xff },
282 { "bpr1", 0x1, 0xff },
283 { "pf0", 0x4, 0xff },
284 { "pf1", 0x5, 0xff },
285 { "sc", 0x8, 0xff },
286 { "msr", 0xa, 0xff },
287 { "bcnt", 0xb, 0xff },
288 { "ptb0", 0xc, 0xff },
289 { "ptb1", 0xd, 0xff },
290 { "eia", 0xf, 0xff },
291 { 0 , 0x0, 0xff }
292 };
293
294 #if defined(NS32532)
295 struct option *cpureg = cpureg_532;
296 struct option *mmureg = mmureg_532;
297 #else
298 struct option *cpureg = cpureg_032;
299 struct option *mmureg = mmureg_032;
300 #endif
301 \f
302
303 const pseudo_typeS md_pseudo_table[]={ /* so far empty */
304 { 0, 0, 0 }
305 };
306
307 #define IND(x,y) (((x)<<2)+(y))
308
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 */
312
313 #define BRANCH 1
314 #define PCREL 2
315
316 /* those are index's to entries in a relax group */
317
318 #define BYTE 0
319 #define WORD 1
320 #define DOUBLE 2
321 #define UNDEF 3
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. */
330
331
332 const relax_typeS md_relax_table[]={
333 { 1, 1, 0, 0 },
334 { 1, 1, 0, 0 },
335 { 1, 1, 0, 0 },
336 { 1, 1, 0, 0 },
337
338 { (63), (-64), 1, IND(BRANCH,WORD) },
339 { (8192), (-8192), 2, IND(BRANCH,DOUBLE) },
340 { 0, 0, 4, 0 },
341 { 1, 1, 0, 0 }
342 };
343
344 /* Array used to test if mode contains displacements.
345 Value is true if mode contains displacement. */
346
347 char disp_test[]={ 0,0,0,0,0,0,0,0,
348 1,1,1,1,1,1,1,1,
349 1,1,1,0,0,1,1,0,
350 1,1,1,1,1,1,1,1 };
351
352 /* Array used to calculate max size of displacements */
353
354 char disp_size[]={ 4,1,2,0,4 };
355 \f
356
357 #ifdef __STDC__
358
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);
362
363 #else /* __STDC__ */
364
365 static segT evaluate_expr();
366 static void md_number_to_disp();
367 static void md_number_to_imm();
368
369 #endif /* __STDC__ */
370
371 /* Parses a general operand into an addressingmode struct
372
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)
376
377 out: data in addr_mode struct
378 */
379 int addr_mode(operand,addr_modeP,recursive_level)
380 char *operand;
381 register addr_modeS *addr_modeP;
382 int recursive_level;
383 {
384 register char *str;
385 register int i;
386 register int strl;
387 register int mode;
388 int j;
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;
400 str=operand;
401 if (str[0]==0) {return (0);} /* we don't want this */
402 strl=strlen(str);
403 switch (str[0]) {
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;
411 return (-1);
412 #endif
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;
418 return (-1);
419 #endif
420 case '.':
421 if (str[strl-1]!=']') {
422 switch (str[1]) {
423 case'-':case'+':
424 if (str[2]!='\000') {
425 addr_modeP->mode=27; /* pc-relativ */
426 addr_modeP->disp[0]=str+2;
427 return (-1);
428 }
429 default:
430 as_warn("Invalid syntax in PC-relative addressing mode");
431 return(0);
432 }
433 }
434 break;
435 case'e':
436 if (str[strl-1]!=']') {
437 if((!strncmp(str,"ext(",4)) && strl>7) { /* external */
438 addr_modeP->disp[0]=str+4;
439 i=0;
440 j=2;
441 do { /* disp[0]'s termination point */
442 j+=1;
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");
448 return(0);
449 }
450 str[j]='\000'; /* null terminate disp[0] */
451 addr_modeP->disp[1]=str+j+2;
452 addr_modeP->mode=22;
453 return (-1);
454 }
455 }
456 break;
457 default:;
458 }
459 strl=strlen(str);
460 switch(strl) {
461 case 2:
462 switch (str[0]) {
463 case'f':addr_modeP->float_flag=1;
464 case'r':
465 if (str[1]>='0' && str[1]<'8') {
466 addr_modeP->mode=str[1]-'0';
467 return (-1);
468 }
469 }
470 case 3:
471 if (!strncmp(str,"tos",3)) {
472 addr_modeP->mode=23; /* TopOfStack */
473 return (-1);
474 }
475 default:;
476 }
477 if (strl>4) {
478 if (str[strl-1]==')') {
479 if (str[strl-2]==')') {
480 if (!strncmp(&str[strl-5],"(fp",3)) {
481 mode=16; /* Memory Relative */
482 }
483 if (!strncmp(&str[strl-5],"(sp",3)) {
484 mode=17;
485 }
486 if (!strncmp(&str[strl-5],"(sb",3)) {
487 mode=18;
488 }
489 if (mode!=DEFAULT) { /* memory relative */
490 addr_modeP->mode=mode;
491 j=strl-5; /* temp for end of disp[0] */
492 i=0;
493 do {
494 strl-=1;
495 if (str[strl]==')') i++;
496 if (str[strl]=='(') i--;
497 } while (strl>-1 && i!=0);
498 if (i!=0) {
499 as_warn("Invalid syntax in Memory Relative addressing mode");
500 return(0);
501 }
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] */
506 return (-1);
507 }
508 }
509 switch (str[strl-3]) {
510 case'r':case'R':
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;
514 str[strl-4]=0;
515 return (-1); /* reg rel */
516 }
517 default:
518 if (!strncmp(&str[strl-4],"(fp",3)) {
519 mode=24;
520 }
521 if (!strncmp(&str[strl-4],"(sp",3)) {
522 mode=25;
523 }
524 if (!strncmp(&str[strl-4],"(sb",3)) {
525 mode=26;
526 }
527 if (!strncmp(&str[strl-4],"(pc",3)) {
528 mode=27;
529 }
530 if (mode!=DEFAULT) {
531 addr_modeP->mode=mode;
532 addr_modeP->disp[0]=str;
533 str[strl-4]='\0';
534 return (-1); /* memory space */
535 }
536 }
537 }
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;
545 default:;
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}");
550 }
551 } /* scaled index */
552 {
553 if (recursive_level>0) {
554 as_warn("Scaled-indexed addressing mode combined with scaled-index");
555 return(0);
556 }
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");
563 return(0);
564 }
565 addr_modeP->scaled_mode=addr_modeP->mode; /* store the inferior mode */
566 addr_modeP->mode=mode;
567 addr_modeP->scaled_reg=j+1;
568 return (-1);
569 }
570 }
571 }
572 addr_modeP->mode = DEFAULT; /* default to whatever */
573 addr_modeP->disp[0]=str;
574 return (-1);
575 }
576 \f
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.
583 */
584 int get_addr_mode(ptr,addr_modeP)
585 char *ptr;
586 addr_modeS *addr_modeP;
587 {
588 int tmp;
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 */
600 } else {
601 addr_modeP->mode=desc->default_modec; /* we have a constant */
602 }
603 } else {
604 if (exprP.X_add_symbol || exprP.X_subtract_symbol) {
605 addr_modeP->scaled_mode=desc->default_model;
606 } else {
607 addr_modeP->scaled_mode=desc->default_modec;
608 }
609 }
610 /* must put this mess down in addr_mode to handle the scaled case better */
611 }
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.
617 */
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;
623 }
624 if (disp_test[addr_modeP->mode]) { /* there was a displacement, probe for length specifying suffix*/
625 {
626 register char c;
627 register char suffix;
628 register char suffix_sub;
629 register int i;
630 register char *toP;
631 register char *fromP;
632
633 addr_modeP->pcrel=0;
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 */
636 addr_modeP->pcrel=1;
637 }
638 addr_modeP->im_disp=1;
639 for(i=0;i<2;i++) {
640 suffix_sub=suffix=0;
641 if (toP=addr_modeP->disp[i]) { /* suffix of expression, the largest size rules */
642 fromP=toP;
643 while (c = *fromP++) {
644 *toP++=c;
645 if (c==':') {
646 switch (*fromP) {
647 case '\0':
648 as_warn("Premature end of suffix--Defaulting to d");
649 suffix=4;
650 continue;
651 case 'b':suffix_sub=1;break;
652 case 'w':suffix_sub=2;break;
653 case 'd':suffix_sub=4;break;
654 default:
655 as_warn("Bad suffix after ':' use {b|w|d} Defaulting to d");
656 suffix=4;
657 }
658 fromP++;
659 toP--; /* So we write over the ':' */
660 if (suffix<suffix_sub) suffix=suffix_sub;
661 }
662 }
663 *toP='\0'; /* terminate properly */
664 addr_modeP->disp_suffix[i]=suffix;
665 addr_modeP->am_size+=suffix ? suffix : 4;
666 }
667 }
668 }
669 }
670 } else {
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;
674 }
675 }
676 return addr_modeP->mode;
677 }
678
679
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 */
685 {
686 register int i,j,k,strlen1,strlen2;
687 register char *patternP,*strP;
688 strlen1=strlen(str);
689 if (strlen1<1) {
690 as_fatal("Very short instr to option, ie you can't do it on a NULLstr");
691 }
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;
696 strP = &str[j];
697 for (k=0;k<strlen2;k++) {
698 if (*(strP++)!=*(patternP++)) break;
699 }
700 if (k==strlen2) { /* match */
701 *default_map|=optionP[i].or;
702 *default_map&=optionP[i].and;
703 }
704 }
705 }
706 }
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 */
711
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 */
716 {
717 register int i;
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;
722 return -1;
723 }
724 }
725 as_warn("No such entry in list. (cpu/mmu register)");
726 return 0;
727 }
728 static segT evaluate_expr(resultP,ptr)
729 expressionS *resultP;
730 char *ptr;
731 {
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;
738 return (segment);
739 }
740 \f
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
744 opcode.
745 Be carefull not to put to objects in the same iif-slot.
746 */
747
748 void encode_operand(argc,argv,operandsP,suffixP,im_size,opcode_bit_ptr)
749 int argc;
750 char **argv;
751 char *operandsP;
752 char *suffixP;
753 char im_size;
754 char opcode_bit_ptr;
755 {
756 register int i,j;
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");
761 pcrel=0;
762 pcrel_adjust=0;
763 tmp=0;
764 switch (operandsP[(loop<<1)+1]) {
765 case 'f': /* operand of sfsr turns out to be a nasty specialcase */
766 opcode_bit_ptr-=5;
767 case 'F': /* 32 bit float general form */
768 case 'L': /* 64 bit float */
769 case 'Q': /* quad-word */
770 case 'B': /* byte */
771 case 'W': /* 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]) {
779 IIF(j,
780 2,
781 addr_modeP.disp_suffix[j-b],
782 (unsigned long)addr_modeP.disp[j-b],
783 0,
784 addr_modeP.pcrel,
785 iif.instr_size-addr_modeP.am_size, /* this aint used (now) */
786 addr_modeP.im_disp,
787 IND(BRANCH,BYTE),
788 NULL,
789 addr_modeP.scaled_reg ? addr_modeP.scaled_mode:addr_modeP.mode,
790 0);
791 }
792 }
793 opcode_bit_ptr-=5;
794 iif.iifP[1].object|=((long)addr_modeP.mode)<<opcode_bit_ptr;
795 if (addr_modeP.scaled_reg) {
796 j=b/2;
797 IIF(j,1,1, (unsigned long)addr_modeP.index_byte,0,0,0,0,0, NULL,-1,0);
798 }
799 break;
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);
803 argv[i]=freeptr;
804 freeptr=(char*)tmp;
805 pcrel-=1; /* make pcrel 0 inspite of what case 'p': wants */
806 /* fall thru */
807 case 'p': /* displacement - pc relative addressing */
808 pcrel+=1;
809 /* fall thru */
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);
814 break;
815 case 'H': /* sequent-hack: the linker wants a bit set when bsr */
816 pcrel=1;
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 */
821 opcode_bit_ptr-=4;
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);
824 break;
825 case 'r': /* register number (3 bits) */
826 list_search(argv[i],opt6,&tmp);
827 opcode_bit_ptr-=3;
828 iif.iifP[1].object|=tmp<<opcode_bit_ptr;
829 break;
830 case 'O': /* setcfg instruction optionslist */
831 optlist(argv[i],opt3,&tmp);
832 opcode_bit_ptr-=4;
833 iif.iifP[1].object|=tmp<<15;
834 break;
835 case 'C': /* cinv instruction optionslist */
836 optlist(argv[i],opt4,&tmp);
837 opcode_bit_ptr-=4;
838 iif.iifP[1].object|=tmp<<15;/*insert the regtype in opcode */
839 break;
840 case 'S': /* stringinstruction optionslist */
841 optlist(argv[i],opt5,&tmp);
842 opcode_bit_ptr-=4;
843 iif.iifP[1].object|=tmp<<15;
844 break;
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);
850 break;
851 case 'U': /* save,enter */
852 optlist(argv[i],opt2,&iif.iifP[10].object);
853 break;
854 }
855 iif.instr_size+=1;
856 break;
857 case 'M': /* mmu register */
858 list_search(argv[i],mmureg,&tmp);
859 opcode_bit_ptr-=4;
860 iif.iifP[1].object|=tmp<<opcode_bit_ptr;
861 break;
862 case 'P': /* cpu register */
863 list_search(argv[i],cpureg,&tmp);
864 opcode_bit_ptr-=4;
865 iif.iifP[1].object|=tmp<<opcode_bit_ptr;
866 break;
867 case 'g': /* inss exts */
868 iif.instr_size+=1; /* 1 byte is allocated after the opcode */
869 IIF(10,2,1,
870 (unsigned long)argv[i], /* i always 2 here */
871 0,0,0,0,0,
872 bit_fix_new(3,5,0,7,0,0,0), /* a bit_fix is targeted to the byte */
873 -1,0);
874 case 'G':
875 IIF(11,2,42,
876 (unsigned long)argv[i], /* i always 3 here */
877 0,0,0,0,0,
878 bit_fix_new(5,0,1,32,-1,0,-1),-1,0);
879 break;
880 case 'i':
881 iif.instr_size+=1;
882 b=2+i; /* put the extension byte after opcode */
883 IIF(b,2,1,0,0,0,0,0,0,0,-1,0);
884 default:
885 as_fatal("Bad opcode-table-option, check in file ns32k-opcode.h");
886 }
887 }
888 }
889 \f
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
895 */
896 /* build iif of one assembly text line */
897 int parse(line,recursive_level)
898 char *line;
899 int recursive_level;
900 {
901 register char *lineptr,c,suffix_separator;
902 register int i;
903 int argc,arg_type;
904 char sqr,sep;
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++);
908 c = *lineptr;
909 *lineptr='\0';
910 if (!(desc=(struct ns32k_opcode*)hash_find(inst_hash_handle,line))) {
911 as_fatal("No such opcode");
912 }
913 *lineptr=c;
914 } else {
915 lineptr=line;
916 }
917 argc=0;
918 if (*desc->operands) {
919 if (*lineptr++!='\0') {
920 sqr='[';
921 sep=',';
922 while (*lineptr!='\0') {
923 if (desc->operands[argc<<1]) {
924 suffix[argc]=0;
925 arg_type=desc->operands[(argc<<1)+1];
926 switch (arg_type) {
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=':';
930 break;
931 default:
932 suffix_separator='\255'; /* if this char occurs we loose */
933 }
934 suffix[argc]=0; /* 0 when no ':' is encountered */
935 argv[argc]=freeptr;
936 *freeptr='\0';
937 while ((c = *lineptr)!='\0' && c!=sep) {
938 if (c==sqr) {
939 if (sqr=='[') {
940 sqr=']';sep='\0';
941 } else {
942 sqr='[';sep=',';
943 }
944 }
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");
951 suffix[argc]=4;
952 if (lineptr[1]=='\0' || lineptr[1]==sep) {
953 lineptr+=1;
954 continue;
955 }
956 }
957 lineptr+=2;
958 continue;
959 }
960 *freeptr++=c;
961 lineptr++;
962 }
963 *freeptr++='\0';
964 argc+=1;
965 if (*lineptr=='\0') continue;
966 lineptr+=1;
967 } else {
968 as_fatal("Too many operands passed to instruction");
969 }
970 }
971 }
972 }
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");
977 }
978 } else {
979 as_fatal("Wrong number of operands");
980 }
981
982 }
983 for (i=0;i<IIF_ENTRIES;i++) {
984 iif.iifP[i].type=0; /* mark all entries as void*/
985 }
986
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);
990
991 /* this call encodes operands to iif format */
992 if (argc) {
993 encode_operand(argc,
994 argv,
995 &desc->operands[0],
996 &suffix[0],
997 desc->im_size,
998 desc->opcode_size);
999 }
1000 return recursive_level;
1001 }
1002
1003 \f
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.
1012 */
1013 void convert_iif() {
1014 register int i,j;
1015 fragS *inst_frag;
1016 char *inst_offset,*inst_opcode;
1017 char *memP;
1018 segT segment;
1019 int l,k;
1020 register int rem_size; /* count the remaining bytes of instruction */
1021 register char type;
1022 register char size = 0;
1023 int size_so_far=0; /* used to calculate pcrel_adjust */
1024
1025 rem_size=iif.instr_size;
1026 memP=frag_more(iif.instr_size); /* make sure we have enough bytes for instruction */
1027 inst_opcode=memP;
1028 inst_offset=(char*)(memP-frag_now->fr_literal);
1029 inst_frag=frag_now;
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;
1036 }
1037 case 8: /* bignum or doublefloat */
1038 bzero (memP,8);
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;
1041 switch (type) {
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),
1046 size,
1047 0,
1048 0,
1049 iif.iifP[i].object,
1050 iif.iifP[i].pcrel,
1051 (char)size_so_far, /*iif.iifP[i].pcrel_adjust,*/
1052 iif.iifP[i].im_disp,
1053 j,
1054 iif.iifP[i].bsr); /* sequent hack */
1055 } else { /* good, just put them bytes out */
1056 switch (iif.iifP[i].im_disp) {
1057 case 0:
1058 md_number_to_chars(memP,iif.iifP[i].object,size);break;
1059 case 1:
1060 md_number_to_disp(memP,iif.iifP[i].object,size);break;
1061 default: as_fatal("iif convert internal pcrel/binary");
1062 }
1063 }
1064 memP+=size;
1065 rem_size-=size;
1066 break;
1067 case 2: /* the object is a pointer at an expression, so unpack
1068 it, note that bignums may result from the expression
1069 */
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");
1075 if (k==3) memP+=2;
1076 for (l=0;k>0;k--,l+=2) {
1077 md_number_to_chars(memP+l,generic_bignum[l>>1],sizeof(LITTLENUM_TYPE));
1078 }
1079 } else { /* flonum */
1080 LITTLENUM_TYPE words[4];
1081
1082 switch(size) {
1083 case 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));
1087 break;
1088 case 8:
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));
1094 break;
1095 }
1096 }
1097 memP+=size;
1098 rem_size-=size;
1099 break;
1100 }
1101 if (j ||
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),
1110 size,
1111 exprP.X_add_symbol,
1112 exprP.X_subtract_symbol,
1113 exprP.X_add_number,
1114 iif.iifP[i].pcrel,
1115 (char)size_so_far, /*iif.iifP[i].pcrel_adjust,*/
1116 iif.iifP[i].im_disp,
1117 j,
1118 iif.iifP[i].bsr); /* sequent hack */
1119
1120 } else { /* good, just put them bytes out */
1121 switch (iif.iifP[i].im_disp) {
1122 case 0:
1123 md_number_to_imm(memP,exprP.X_add_number,size);break;
1124 case 1:
1125 md_number_to_disp(memP,exprP.X_add_number,size);break;
1126 default: as_fatal("iif convert internal pcrel/pointer");
1127 }
1128 }
1129 memP+=size;
1130 rem_size-=size;
1131 break;
1132 default: as_fatal("Internal logic error in iif.iifP[n].type");
1133 }
1134 break;
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.
1140 */
1141 {
1142 int temp;
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),
1149 size,
1150 exprP.X_add_symbol,
1151 exprP.X_subtract_symbol,
1152 exprP.X_add_number,
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, */
1156 0,0);
1157 memP+=size;
1158 rem_size-=4;
1159 break; /* exit this absolute hack */
1160 }
1161
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");
1165 }
1166 else {
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
1170 */
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.
1177 */
1178 (void)frag_variant(rs_machine_dependent,
1179 4,
1180 0,
1181 IND(BRANCH,UNDEF), /* expecting the worst */
1182 exprP.X_add_symbol,
1183 exprP.X_add_number,
1184 (char*)inst_opcode,
1185 (char)size_so_far, /*iif.iifP[i].pcrel_adjust);*/
1186 iif.iifP[i].bsr); /* sequent linker hack */
1187 rem_size-=4;
1188 if (rem_size>0) {
1189 memP=frag_more(rem_size);
1190 }
1191 }
1192 }
1193 else {/* Double work, this is done in md_number_to_disp */
1194 /* exprP.X_add_number; what was this supposed to be?
1195 xoxorich. */
1196 if (-64<=exprP.X_add_number && exprP.X_add_number<=63) {
1197 size=1;
1198 } else {
1199 if (-8192<=exprP.X_add_number && exprP.X_add_number<=8191) {
1200 size=2;
1201 } else {
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) */
1206 {
1207 size=4;
1208 } else {
1209 as_warn("Displacement to large for :d");
1210 size=4;
1211 }
1212 }
1213 }
1214 /* rewind the bytes not used */
1215 temp = -(4-size);
1216 md_number_to_disp(memP,exprP.X_add_number,size);
1217 obstack_blank_fast(&frags,temp);
1218 memP+=size;
1219 rem_size-=4; /* we allocated this amount */
1220 }
1221 }
1222 break;
1223 default:
1224 as_fatal("Internal logic error in iif.iifP[].type");
1225 }
1226 size_so_far+=size;
1227 size=0;
1228 }
1229 }
1230 }
1231 \f
1232 void md_assemble(line)
1233 char *line;
1234 {
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 */
1238 #ifdef SHOW_NUM
1239 printf(" \t\t\t%s\n",line);
1240 #endif
1241 }
1242
1243
1244 void md_begin() {
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*/
1252 exit(0);
1253 }
1254 }
1255 freeptr_static=(char*)malloc(PRIVATE_SIZE); /* some private space please! */
1256 }
1257
1258
1259 void
1260 md_end() {
1261 free(freeptr_static);
1262 }
1263
1264 /* Must be equal to MAX_PRECISON in atof-ieee.c */
1265 #define MAX_LITTLENUMS 6
1266
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.
1270 */
1271 char *
1272 md_atof(type,litP,sizeP)
1273 char type;
1274 char *litP;
1275 int *sizeP;
1276 {
1277 int prec;
1278 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1279 LITTLENUM_TYPE *wordP;
1280 char *t;
1281
1282 switch(type) {
1283 case 'f':
1284 prec = 2;
1285 break;
1286
1287 case 'd':
1288 prec = 4;
1289 break;
1290 default:
1291 *sizeP=0;
1292 return "Bad call to MD_ATOF()";
1293 }
1294 t=atof_ieee(input_line_pointer,type,words);
1295 if(t)
1296 input_line_pointer=t;
1297
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);
1302 }
1303 return ""; /* Someone should teach Dean about null pointers */
1304 }
1305 \f
1306 /* Convert number to chars in correct order */
1307
1308 void
1309 md_number_to_chars (buf, value, nbytes)
1310 char *buf;
1311 long value;
1312 int nbytes;
1313 {
1314 while (nbytes--)
1315 {
1316 #ifdef SHOW_NUM
1317 printf("%x ",value & 0xff);
1318 #endif
1319 *buf++ = value; /* Lint wants & MASK_CHAR. */
1320 value >>= BITS_PER_CHAR;
1321 }
1322 }
1323 /* Convert number to chars in correct order */
1324
1325
1326
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
1330 with a size-tag.
1331
1332 binary: msb -> lsb 0xxxxxxx byte
1333 10xxxxxx xxxxxxxx word
1334 11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx double word
1335
1336 This must be taken care of and we do it here!
1337 */
1338 static void md_number_to_disp(buf,val,n)
1339 char *buf;
1340 long val;
1341 char n;
1342 {
1343 switch(n) {
1344 case 1:
1345 if (val < -64 || val > 63)
1346 as_warn("Byte displacement out of range. line number not valid");
1347 val&=0x7f;
1348 #ifdef SHOW_NUM
1349 printf("%x ",val & 0xff);
1350 #endif
1351 *buf++=val;
1352 break;
1353 case 2:
1354 if (val < -8192 || val > 8191)
1355 as_warn("Word displacement out of range. line number not valid");
1356 val&=0x3fff;
1357 val|=0x8000;
1358 #ifdef SHOW_NUM
1359 printf("%x ",val>>8 & 0xff);
1360 #endif
1361 *buf++=(val>>8);
1362 #ifdef SHOW_NUM
1363 printf("%x ",val & 0xff);
1364 #endif
1365 *buf++=val;
1366 break;
1367 case 4:
1368 if (val < -0x1f000000 || val >= 0x20000000)
1369 /* if (val < -0x20000000 || val >= 0x20000000) */
1370 as_warn("Double word displacement out of range");
1371 val|=0xc0000000;
1372 #ifdef SHOW_NUM
1373 printf("%x ",val>>24 & 0xff);
1374 #endif
1375 *buf++=(val>>24);
1376 #ifdef SHOW_NUM
1377 printf("%x ",val>>16 & 0xff);
1378 #endif
1379 *buf++=(val>>16);
1380 #ifdef SHOW_NUM
1381 printf("%x ",val>>8 & 0xff);
1382 #endif
1383 *buf++=(val>>8);
1384 #ifdef SHOW_NUM
1385 printf("%x ",val & 0xff);
1386 #endif
1387 *buf++=val;
1388 break;
1389 default:
1390 as_fatal("Internal logic error. line %s, file \"%s\"", __LINE__, __FILE__);
1391 }
1392 }
1393
1394 static void md_number_to_imm(buf,val,n)
1395 char *buf;
1396 long val;
1397 char n;
1398 {
1399 switch(n) {
1400 case 1:
1401 #ifdef SHOW_NUM
1402 printf("%x ",val & 0xff);
1403 #endif
1404 *buf++=val;
1405 break;
1406 case 2:
1407 #ifdef SHOW_NUM
1408 printf("%x ",val>>8 & 0xff);
1409 #endif
1410 *buf++=(val>>8);
1411 #ifdef SHOW_NUM
1412 printf("%x ",val & 0xff);
1413 #endif
1414 *buf++=val;
1415 break;
1416 case 4:
1417 #ifdef SHOW_NUM
1418 printf("%x ",val>>24 & 0xff);
1419 #endif
1420 *buf++=(val>>24);
1421 #ifdef SHOW_NUM
1422 printf("%x ",val>>16 & 0xff);
1423 #endif
1424 *buf++=(val>>16);
1425 #ifdef SHOW_NUM
1426 printf("%x ",val>>8 & 0xff);
1427 #endif
1428 *buf++=(val>>8);
1429 #ifdef SHOW_NUM
1430 printf("%x ",val & 0xff);
1431 #endif
1432 *buf++=val;
1433 break;
1434 default:
1435 as_fatal("Internal logic error. line %s, file \"%s\"", __LINE__, __FILE__);
1436 }
1437 }
1438
1439 /* Translate internal representation of relocation info into target format.
1440
1441 OVE: on a ns32k the twiddling continues at an even deeper level
1442 here we have to distinguish between displacements and immediates.
1443
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) !?!?!?!
1446
1447 This md_ri.... is tailored for sequent.
1448 */
1449
1450 void
1451 md_ri_to_chars(the_bytes, ri)
1452 char *the_bytes;
1453 struct reloc_info_generic *ri;
1454 {
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 ),
1464 4);
1465 /* the first and second md_number_to_chars never overlaps (32bit cpu case) */
1466 }
1467 \f
1468 /* fast bitfiddling support */
1469 /* mask used to zero bitfield before oring in the true field */
1470
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,
1479 };
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,
1488 };
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!)
1495 */
1496
1497 static void
1498 md_number_to_field(buf,val,field_ptr)
1499 register char *buf;
1500 register long val;
1501 register bit_fixS *field_ptr;
1502 {
1503 register unsigned long object;
1504 register unsigned long mask;
1505 /* define ENDIAN on a ns32k machine */
1506 #ifdef ENDIAN
1507 register unsigned long *mem_ptr;
1508 #else
1509 register char *mem_ptr;
1510 #endif
1511 if (field_ptr->fx_bit_min<=val && val<=field_ptr->fx_bit_max) {
1512 #ifdef ENDIAN
1513 if (field_ptr->fx_bit_base) { /* override buf */
1514 mem_ptr=(unsigned long*)field_ptr->fx_bit_base;
1515 } else {
1516 mem_ptr=(unsigned long*)buf;
1517 }
1518 #else
1519 if (field_ptr->fx_bit_base) { /* override buf */
1520 mem_ptr=(char*)field_ptr->fx_bit_base;
1521 } else {
1522 mem_ptr=buf;
1523 }
1524 #endif
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 */
1530 object=0;
1531 object|=mem_ptr[3] & 0xff;
1532 object<<=8;
1533 object|=mem_ptr[2] & 0xff;
1534 object<<=8;
1535 object|=mem_ptr[1] & 0xff;
1536 object<<=8;
1537 object|=mem_ptr[0] & 0xff;
1538 #endif
1539 mask=0;
1540 mask|=(r_mask[field_ptr->fx_bit_offset]);
1541 mask|=(l_mask[field_ptr->fx_bit_offset+field_ptr->fx_bit_size]);
1542 object&=mask;
1543 val+=field_ptr->fx_bit_add;
1544 object|=((val<<field_ptr->fx_bit_offset) & (mask ^ 0xffffffff));
1545 #ifdef ENDIAN
1546 *mem_ptr=object;
1547 #else
1548 mem_ptr[0]=(char)object;
1549 object>>=8;
1550 mem_ptr[1]=(char)object;
1551 object>>=8;
1552 mem_ptr[2]=(char)object;
1553 object>>=8;
1554 mem_ptr[3]=(char)object;
1555 #endif
1556 } else {
1557 as_warn("Bit field out of range");
1558 }
1559 }
1560
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.
1563
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. */
1567
1568 void
1569 md_apply_fix(fixP, val)
1570 fixS *fixP;
1571 long val;
1572 {
1573 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
1574
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) {
1578
1579 case 0: /* Immediate field */
1580 md_number_to_imm (buf, val, fixP->fx_size);
1581 break;
1582
1583 case 1: /* Displacement field */
1584 md_number_to_disp (buf,
1585 fixP->fx_pcrel? val + fixP->fx_pcrel_adjust: val,
1586 fixP->fx_size);
1587 break;
1588
1589 case 2: /* Pointer in a data object */
1590 md_number_to_chars (buf, val, fixP->fx_size);
1591 break;
1592 }
1593 }
1594 \f
1595 /* Convert a relaxed displacement to ditto in final output */
1596
1597 void
1598 md_convert_frag(fragP)
1599 register fragS *fragP;
1600 {
1601 long disp;
1602 long ext;
1603
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;
1608
1609 know(fragP->fr_symbol);
1610
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;
1614
1615 switch(fragP->fr_subtype) {
1616 case IND(BRANCH,BYTE):
1617 ext=1;
1618 break;
1619 case IND(BRANCH,WORD):
1620 ext=2;
1621 break;
1622 case IND(BRANCH,DOUBLE):
1623 ext=4;
1624 break;
1625 }
1626 if(ext) {
1627 md_number_to_disp(buffer_address,(long)disp,(int)ext);
1628 fragP->fr_fix+=ext;
1629 }
1630 }
1631
1632
1633
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
1636 actually know it */
1637
1638 int md_estimate_size_before_relax(fragP, segment)
1639 register fragS *fragP;
1640 segT segment;
1641 {
1642 int old_fix;
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);
1649 } else {
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),
1654 4,
1655 fragP->fr_symbol,
1656 (symbolS *)0,
1657 fragP->fr_offset,
1658 1,
1659 fragP->fr_pcrel_adjust,
1660 1,
1661 0,
1662 fragP->fr_bsr); /*sequent hack */
1663 fragP->fr_fix+=4;
1664 /* fragP->fr_opcode[1]=0xff; */
1665 frag_wane(fragP);
1666 break;
1667 }
1668 case IND(BRANCH,BYTE):
1669 fragP->fr_var+=1;
1670 break;
1671 default:
1672 break;
1673 }
1674 return fragP->fr_var + fragP->fr_fix - old_fix;
1675 }
1676
1677 int md_short_jump_size = 3;
1678 int md_long_jump_size = 5;
1679 int md_reloc_size = 8; /* Size of relocation record */
1680
1681 void
1682 md_create_short_jump(ptr,from_addr,to_addr,frag,to_symbol)
1683 char *ptr;
1684 long from_addr,
1685 to_addr;
1686 fragS *frag;
1687 symbolS *to_symbol;
1688 {
1689 long offset;
1690
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);
1694 }
1695
1696 void
1697 md_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol)
1698 char *ptr;
1699 long from_addr,
1700 to_addr;
1701 fragS *frag;
1702 symbolS *to_symbol;
1703 {
1704 long offset;
1705
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);
1709 }
1710 \f
1711 /* JF this is a new function to parse machine-dep options */
1712 int
1713 md_parse_option(argP,cntP,vecP)
1714 char **argP;
1715 int *cntP;
1716 char ***vecP;
1717 {
1718 switch(**argP) {
1719 case 'm':
1720 (*argP)++;
1721
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;
1728 } else
1729 as_warn("Unknown -m option ignored");
1730
1731 while(**argP)
1732 (*argP)++;
1733 break;
1734
1735 default:
1736 return 0;
1737 }
1738 return 1;
1739 }
1740 \f
1741 /*
1742 * bit_fix_new()
1743 *
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.
1747 */
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 */
1752 long base_adj;
1753 long min; /* Signextended min for bitfield */
1754 long max; /* Signextended max for bitfield */
1755 long add; /* Add mask, used for huffman prefix */
1756 {
1757 register bit_fixS * bit_fixP;
1758
1759 bit_fixP = (bit_fixS *)obstack_alloc(&notes,sizeof(bit_fixS));
1760
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;
1768
1769 return bit_fixP;
1770 }
1771
1772 void
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 */
1786
1787 {
1788 register fixS * fixP;
1789
1790 fixP = (fixS *)obstack_alloc(&notes,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;
1803
1804 * seg_fix_rootP = fixP;
1805 }
1806
1807 /* We have no need to default values of symbols. */
1808
1809 symbolS *
1810 md_undefined_symbol (name)
1811 char *name;
1812 {
1813 return 0;
1814 }
1815
1816 /* Parse an operand that is machine-specific.
1817 We just return without modifying the expression if we have nothing
1818 to do. */
1819
1820 /* ARGSUSED */
1821 void
1822 md_operand (expressionP)
1823 expressionS *expressionP;
1824 {
1825 }
1826
1827 /* Round up a section size to the appropriate boundary. */
1828 long
1829 md_section_align (segment, size)
1830 segT segment;
1831 long size;
1832 {
1833 return size; /* Byte alignment is fine */
1834 }
1835
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) */
1840 long
1841 md_pcrel_from (fixP)
1842 fixS *fixP;
1843 {
1844 long res;
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! */
1849 #endif
1850 return res;
1851 }
1852
1853 /*
1854 * $Log$
1855 * Revision 1.1 1991/04/04 18:17:05 rich
1856 * Initial revision
1857 *
1858 *
1859 */
1860
1861 /*
1862 * Local Variables:
1863 * comment-column: 0
1864 * End:
1865 */
1866
1867 /* end of tc-ns32k.c */