fighting bitrot in a major way
[deliverable/binutils-gdb.git] / gas / config / tc-ns32k.c
1 /* ns32k.c -- Assemble on the National Semiconductor 32k series
2 Copyright (C) 1987, 1992 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /*#define SHOW_NUM 1*/ /* uncomment for debugging */
21
22 #include <stdio.h>
23 #include <ctype.h>
24 #ifdef USG
25 #include <string.h>
26 #else
27 #include <strings.h>
28 #endif
29 #include "opcode/ns32k.h"
30
31 #include "as.h"
32
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; /* length in bytes from the
115 instruction start to the
116 displacement */
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 */
123
124 struct int_ins_form {
125 int instr_size; /* Max size of instruction in bytes. */
126 iif_entryT iifP[IIF_ENTRIES + 1];
127 };
128 struct int_ins_form iif;
129 expressionS exprP;
130 char *input_line_pointer;
131 /* description of the PARTs in IIF
132 *object[n]:
133 * 0 total length in bytes of entries in iif
134 * 1 opcode
135 * 2 index_byte_a
136 * 3 index_byte_b
137 * 4 disp_a_1
138 * 5 disp_a_2
139 * 6 disp_b_1
140 * 7 disp_b_2
141 * 8 imm_a
142 * 9 imm_b
143 * 10 implied1
144 * 11 implied2
145 *
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.
150 *
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
155 * etc
156 *
157 * Furthermore, every entry has a data type identifier in type[n].
158 *
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.
166 *
167 * 3, the entry is a pointer at a bignum struct
168 *
169 *
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)
177 */
178 \f
179 struct option opt1[]= /* restore, exit */
180 {
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 },
189 { 0 , 0x00, 0xff }
190 };
191 struct option opt2[]= /* save, enter */
192 {
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 },
201 { 0 , 0x00, 0xff }
202 };
203 struct option opt3[]= /* setcfg */
204 {
205 { "c", 0x8, 0xff },
206 { "m", 0x4, 0xff },
207 { "f", 0x2, 0xff },
208 { "i", 0x1, 0xff },
209 { 0 , 0x0, 0xff }
210 };
211 struct option opt4[]= /* cinv */
212 {
213 { "a", 0x4, 0xff },
214 { "i", 0x2, 0xff },
215 { "d", 0x1, 0xff },
216 { 0 , 0x0, 0xff }
217 };
218 struct option opt5[]= /* string inst */
219 {
220 { "b", 0x2, 0xff },
221 { "u", 0xc, 0xff },
222 { "w", 0x4, 0xff },
223 { 0 , 0x0, 0xff }
224 };
225 struct option opt6[]= /* plain reg ext,cvtp etc */
226 {
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 },
235 { 0 , 0x00, 0xff }
236 };
237
238 #if !defined(NS32032) && !defined(NS32532)
239 #define NS32032
240 #endif
241
242 struct option cpureg_532[]= /* lpr spr */
243 {
244 { "us", 0x0, 0xff },
245 { "dcr", 0x1, 0xff },
246 { "bpc", 0x2, 0xff },
247 { "dsr", 0x3, 0xff },
248 { "car", 0x4, 0xff },
249 { "fp", 0x8, 0xff },
250 { "sp", 0x9, 0xff },
251 { "sb", 0xa, 0xff },
252 { "usp", 0xb, 0xff },
253 { "cfg", 0xc, 0xff },
254 { "psr", 0xd, 0xff },
255 { "intbase", 0xe, 0xff },
256 { "mod", 0xf, 0xff },
257 { 0 , 0x00, 0xff }
258 };
259 struct option mmureg_532[]= /* lmr smr */
260 {
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 },
268 { 0 , 0x0, 0xff }
269 };
270
271 struct option cpureg_032[]= /* lpr spr */
272 {
273 { "upsr", 0x0, 0xff },
274 { "fp", 0x8, 0xff },
275 { "sp", 0x9, 0xff },
276 { "sb", 0xa, 0xff },
277 { "psr", 0xd, 0xff },
278 { "intbase", 0xe, 0xff },
279 { "mod", 0xf, 0xff },
280 { 0 , 0x0, 0xff }
281 };
282 struct option mmureg_032[]= /* lmr smr */
283 {
284 { "bpr0", 0x0, 0xff },
285 { "bpr1", 0x1, 0xff },
286 { "pf0", 0x4, 0xff },
287 { "pf1", 0x5, 0xff },
288 { "sc", 0x8, 0xff },
289 { "msr", 0xa, 0xff },
290 { "bcnt", 0xb, 0xff },
291 { "ptb0", 0xc, 0xff },
292 { "ptb1", 0xd, 0xff },
293 { "eia", 0xf, 0xff },
294 { 0 , 0x0, 0xff }
295 };
296
297 #if defined(NS32532)
298 struct option *cpureg = cpureg_532;
299 struct option *mmureg = mmureg_532;
300 #else
301 struct option *cpureg = cpureg_032;
302 struct option *mmureg = mmureg_032;
303 #endif
304 \f
305
306 const pseudo_typeS md_pseudo_table[]={ /* so far empty */
307 { 0, 0, 0 }
308 };
309
310 #define IND(x,y) (((x)<<2)+(y))
311
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 */
315
316 #define BRANCH 1
317 #define PCREL 2
318
319 /* those are index's to entries in a relax group */
320
321 #define BYTE 0
322 #define WORD 1
323 #define DOUBLE 2
324 #define UNDEF 3
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. */
333
334
335 const relax_typeS md_relax_table[] = {
336 { 1, 1, 0, 0 },
337 { 1, 1, 0, 0 },
338 { 1, 1, 0, 0 },
339 { 1, 1, 0, 0 },
340
341 { (63), (-64), 1, IND(BRANCH,WORD) },
342 { (8192), (-8192), 2, IND(BRANCH,DOUBLE) },
343 { 0, 0, 4, 0 },
344 { 1, 1, 0, 0 }
345 };
346
347 /* Array used to test if mode contains displacements.
348 Value is true if mode contains displacement. */
349
350 char disp_test[] = { 0,0,0,0,0,0,0,0,
351 1,1,1,1,1,1,1,1,
352 1,1,1,0,0,1,1,0,
353 1,1,1,1,1,1,1,1 };
354
355 /* Array used to calculate max size of displacements */
356
357 char disp_size[] = { 4,1,2,0,4 };
358 \f
359
360 #if __STDC__ == 1
361
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);
365
366 #else /* not __STDC__ */
367
368 static segT evaluate_expr();
369 static void md_number_to_disp();
370 static void md_number_to_imm();
371
372 #endif /* not __STDC__ */
373
374 /* Parses a general operand into an addressingmode struct
375
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)
379
380 out: data in addr_mode struct
381 */
382 int addr_mode(operand,addr_modeP,recursive_level)
383 char *operand;
384 register addr_modeS *addr_modeP;
385 int recursive_level;
386 {
387 register char *str;
388 register int i;
389 register int strl;
390 register int mode;
391 int j;
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;
403 str=operand;
404 if (str[0]==0) {return (0);} /* we don't want this */
405 strl=strlen(str);
406 switch (str[0]) {
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;
414 return (-1);
415 #endif
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;
421 return (-1);
422 #endif
423 case '.':
424 if (str[strl-1]!=']') {
425 switch (str[1]) {
426 case'-':case'+':
427 if (str[2]!='\000') {
428 addr_modeP->mode=27; /* pc-relativ */
429 addr_modeP->disp[0]=str+2;
430 return (-1);
431 }
432 default:
433 as_warn("Invalid syntax in PC-relative addressing mode");
434 return(0);
435 }
436 }
437 break;
438 case'e':
439 if (str[strl-1]!=']') {
440 if((!strncmp(str,"ext(",4)) && strl>7) { /* external */
441 addr_modeP->disp[0]=str+4;
442 i=0;
443 j=2;
444 do { /* disp[0]'s termination point */
445 j+=1;
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");
451 return(0);
452 }
453 str[j]='\000'; /* null terminate disp[0] */
454 addr_modeP->disp[1]=str+j+2;
455 addr_modeP->mode=22;
456 return (-1);
457 }
458 }
459 break;
460 default:;
461 }
462 strl=strlen(str);
463 switch(strl) {
464 case 2:
465 switch (str[0]) {
466 case'f':addr_modeP->float_flag=1;
467 case'r':
468 if (str[1]>='0' && str[1]<'8') {
469 addr_modeP->mode=str[1]-'0';
470 return (-1);
471 }
472 }
473 case 3:
474 if (!strncmp(str,"tos",3)) {
475 addr_modeP->mode=23; /* TopOfStack */
476 return (-1);
477 }
478 default:;
479 }
480 if (strl>4) {
481 if (str[strl-1]==')') {
482 if (str[strl-2]==')') {
483 if (!strncmp(&str[strl-5],"(fp",3)) {
484 mode=16; /* Memory Relative */
485 }
486 if (!strncmp(&str[strl-5],"(sp",3)) {
487 mode=17;
488 }
489 if (!strncmp(&str[strl-5],"(sb",3)) {
490 mode=18;
491 }
492 if (mode!=DEFAULT) { /* memory relative */
493 addr_modeP->mode=mode;
494 j=strl-5; /* temp for end of disp[0] */
495 i=0;
496 do {
497 strl-=1;
498 if (str[strl]==')') i++;
499 if (str[strl]=='(') i--;
500 } while (strl>-1 && i!=0);
501 if (i!=0) {
502 as_warn("Invalid syntax in Memory Relative addressing mode");
503 return(0);
504 }
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] */
509 return (-1);
510 }
511 }
512 switch (str[strl-3]) {
513 case'r':case'R':
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;
517 str[strl-4]=0;
518 return (-1); /* reg rel */
519 }
520 default:
521 if (!strncmp(&str[strl-4],"(fp",3)) {
522 mode=24;
523 }
524 if (!strncmp(&str[strl-4],"(sp",3)) {
525 mode=25;
526 }
527 if (!strncmp(&str[strl-4],"(sb",3)) {
528 mode=26;
529 }
530 if (!strncmp(&str[strl-4],"(pc",3)) {
531 mode=27;
532 }
533 if (mode!=DEFAULT) {
534 addr_modeP->mode=mode;
535 addr_modeP->disp[0]=str;
536 str[strl-4]='\0';
537 return (-1); /* memory space */
538 }
539 }
540 }
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;
548 default:;
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}");
553 }
554 } /* scaled index */
555 {
556 if (recursive_level>0) {
557 as_warn("Scaled-indexed addressing mode combined with scaled-index");
558 return(0);
559 }
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");
566 return(0);
567 }
568 addr_modeP->scaled_mode=addr_modeP->mode; /* store the inferior mode */
569 addr_modeP->mode=mode;
570 addr_modeP->scaled_reg=j+1;
571 return (-1);
572 }
573 }
574 }
575 addr_modeP->mode = DEFAULT; /* default to whatever */
576 addr_modeP->disp[0]=str;
577 return (-1);
578 }
579 \f
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.
586 */
587 int get_addr_mode(ptr,addr_modeP)
588 char *ptr;
589 addr_modeS *addr_modeP;
590 {
591 int tmp;
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 */
603 } else {
604 addr_modeP->mode=desc->default_modec; /* we have a constant */
605 }
606 } else {
607 if (exprP.X_add_symbol || exprP.X_subtract_symbol) {
608 addr_modeP->scaled_mode=desc->default_model;
609 } else {
610 addr_modeP->scaled_mode=desc->default_modec;
611 }
612 }
613 /* must put this mess down in addr_mode to handle the scaled case better */
614 }
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.
620 */
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;
626 }
627 if (disp_test[addr_modeP->mode]) { /* there was a displacement, probe for length specifying suffix*/
628 {
629 register char c;
630 register char suffix;
631 register char suffix_sub;
632 register int i;
633 register char *toP;
634 register char *fromP;
635
636 addr_modeP->pcrel=0;
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 */
639 addr_modeP->pcrel=1;
640 }
641 addr_modeP->im_disp=1;
642 for(i=0;i<2;i++) {
643 suffix_sub=suffix=0;
644 if (toP=addr_modeP->disp[i]) { /* suffix of expression, the largest size rules */
645 fromP=toP;
646 while (c = *fromP++) {
647 *toP++=c;
648 if (c==':') {
649 switch (*fromP) {
650 case '\0':
651 as_warn("Premature end of suffix--Defaulting to d");
652 suffix=4;
653 continue;
654 case 'b':suffix_sub=1;break;
655 case 'w':suffix_sub=2;break;
656 case 'd':suffix_sub=4;break;
657 default:
658 as_warn("Bad suffix after ':' use {b|w|d} Defaulting to d");
659 suffix=4;
660 }
661 fromP++;
662 toP--; /* So we write over the ':' */
663 if (suffix<suffix_sub) suffix=suffix_sub;
664 }
665 }
666 *toP='\0'; /* terminate properly */
667 addr_modeP->disp_suffix[i]=suffix;
668 addr_modeP->am_size+=suffix ? suffix : 4;
669 }
670 }
671 }
672 }
673 } else {
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;
677 }
678 }
679 return addr_modeP->mode;
680 }
681
682
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 */
688 {
689 register int i,j,k,strlen1,strlen2;
690 register char *patternP,*strP;
691 strlen1=strlen(str);
692 if (strlen1<1) {
693 as_fatal("Very short instr to option, ie you can't do it on a NULLstr");
694 }
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;
699 strP = &str[j];
700 for (k=0;k<strlen2;k++) {
701 if (*(strP++)!=*(patternP++)) break;
702 }
703 if (k==strlen2) { /* match */
704 *default_map|=optionP[i].or;
705 *default_map&=optionP[i].and;
706 }
707 }
708 }
709 }
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 */
714
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 */
719 {
720 register int i;
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;
725 return -1;
726 }
727 }
728 as_warn("No such entry in list. (cpu/mmu register)");
729 return 0;
730 }
731 static segT evaluate_expr(resultP,ptr)
732 expressionS *resultP;
733 char *ptr;
734 {
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;
741 return (segment);
742 }
743 \f
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
747 opcode.
748 Be carefull not to put to objects in the same iif-slot.
749 */
750
751 void encode_operand(argc,argv,operandsP,suffixP,im_size,opcode_bit_ptr)
752 int argc;
753 char **argv;
754 char *operandsP;
755 char *suffixP;
756 char im_size;
757 char opcode_bit_ptr;
758 {
759 register int i,j;
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");
764 pcrel=0;
765 pcrel_adjust=0;
766 tmp=0;
767 switch (operandsP[(loop<<1)+1]) {
768 case 'f': /* operand of sfsr turns out to be a nasty specialcase */
769 opcode_bit_ptr-=5;
770 case 'F': /* 32 bit float general form */
771 case 'L': /* 64 bit float */
772 case 'Q': /* quad-word */
773 case 'B': /* byte */
774 case 'W': /* 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]) {
782 IIF(j,
783 2,
784 addr_modeP.disp_suffix[j-b],
785 (unsigned long)addr_modeP.disp[j-b],
786 0,
787 addr_modeP.pcrel,
788 iif.instr_size-addr_modeP.am_size, /* this aint used (now) */
789 addr_modeP.im_disp,
790 IND(BRANCH,BYTE),
791 NULL,
792 addr_modeP.scaled_reg ? addr_modeP.scaled_mode:addr_modeP.mode,
793 0);
794 }
795 }
796 opcode_bit_ptr-=5;
797 iif.iifP[1].object|=((long)addr_modeP.mode)<<opcode_bit_ptr;
798 if (addr_modeP.scaled_reg) {
799 j=b/2;
800 IIF(j,1,1, (unsigned long)addr_modeP.index_byte,0,0,0,0,0, NULL,-1,0);
801 }
802 break;
803 case 'b': /* multiple instruction disp */
804 freeptr++; /* OVE:this is an useful hack */
805 tmp = (int) sprintf(freeptr,
806 "((%s-1)*%d)\000",
807 argv[i], desc->im_size);
808 argv[i]=freeptr;
809 freeptr=(char*)tmp;
810 pcrel-=1; /* make pcrel 0 inspite of what case 'p': wants */
811 /* fall thru */
812 case 'p': /* displacement - pc relative addressing */
813 pcrel+=1;
814 /* fall thru */
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);
819 break;
820 case 'H': /* sequent-hack: the linker wants a bit set when bsr */
821 pcrel=1;
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 */
826 opcode_bit_ptr-=4;
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);
829 break;
830 case 'r': /* register number (3 bits) */
831 list_search(argv[i],opt6,&tmp);
832 opcode_bit_ptr-=3;
833 iif.iifP[1].object|=tmp<<opcode_bit_ptr;
834 break;
835 case 'O': /* setcfg instruction optionslist */
836 optlist(argv[i],opt3,&tmp);
837 opcode_bit_ptr-=4;
838 iif.iifP[1].object|=tmp<<15;
839 break;
840 case 'C': /* cinv instruction optionslist */
841 optlist(argv[i],opt4,&tmp);
842 opcode_bit_ptr-=4;
843 iif.iifP[1].object|=tmp<<15;/*insert the regtype in opcode */
844 break;
845 case 'S': /* stringinstruction optionslist */
846 optlist(argv[i],opt5,&tmp);
847 opcode_bit_ptr-=4;
848 iif.iifP[1].object|=tmp<<15;
849 break;
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);
855 break;
856 case 'U': /* save,enter */
857 optlist(argv[i],opt2,&iif.iifP[10].object);
858 break;
859 }
860 iif.instr_size+=1;
861 break;
862 case 'M': /* mmu register */
863 list_search(argv[i],mmureg,&tmp);
864 opcode_bit_ptr-=4;
865 iif.iifP[1].object|=tmp<<opcode_bit_ptr;
866 break;
867 case 'P': /* cpu register */
868 list_search(argv[i],cpureg,&tmp);
869 opcode_bit_ptr-=4;
870 iif.iifP[1].object|=tmp<<opcode_bit_ptr;
871 break;
872 case 'g': /* inss exts */
873 iif.instr_size+=1; /* 1 byte is allocated after the opcode */
874 IIF(10,2,1,
875 (unsigned long)argv[i], /* i always 2 here */
876 0,0,0,0,0,
877 bit_fix_new(3,5,0,7,0,0,0), /* a bit_fix is targeted to the byte */
878 -1,0);
879 case 'G':
880 IIF(11,2,42,
881 (unsigned long)argv[i], /* i always 3 here */
882 0,0,0,0,0,
883 bit_fix_new(5,0,1,32,-1,0,-1),-1,0);
884 break;
885 case 'i':
886 iif.instr_size+=1;
887 b=2+i; /* put the extension byte after opcode */
888 IIF(b,2,1,0,0,0,0,0,0,0,-1,0);
889 default:
890 as_fatal("Bad opcode-table-option, check in file ns32k-opcode.h");
891 }
892 }
893 }
894 \f
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
900 */
901 /* build iif of one assembly text line */
902 int parse(line,recursive_level)
903 char *line;
904 int recursive_level;
905 {
906 register char *lineptr,c,suffix_separator;
907 register int i;
908 int argc,arg_type;
909 char sqr,sep;
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++);
913 c = *lineptr;
914 *lineptr='\0';
915 if (!(desc=(struct ns32k_opcode*)hash_find(inst_hash_handle,line))) {
916 as_fatal("No such opcode");
917 }
918 *lineptr=c;
919 } else {
920 lineptr=line;
921 }
922 argc=0;
923 if (*desc->operands) {
924 if (*lineptr++!='\0') {
925 sqr='[';
926 sep=',';
927 while (*lineptr!='\0') {
928 if (desc->operands[argc<<1]) {
929 suffix[argc]=0;
930 arg_type=desc->operands[(argc<<1)+1];
931 switch (arg_type) {
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=':';
935 break;
936 default:
937 suffix_separator='\255'; /* if this char occurs we loose */
938 }
939 suffix[argc]=0; /* 0 when no ':' is encountered */
940 argv[argc]=freeptr;
941 *freeptr='\0';
942 while ((c = *lineptr)!='\0' && c!=sep) {
943 if (c==sqr) {
944 if (sqr=='[') {
945 sqr=']';sep='\0';
946 } else {
947 sqr='[';sep=',';
948 }
949 }
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");
956 suffix[argc]=4;
957 if (lineptr[1]=='\0' || lineptr[1]==sep) {
958 lineptr+=1;
959 continue;
960 }
961 }
962 lineptr+=2;
963 continue;
964 }
965 *freeptr++=c;
966 lineptr++;
967 }
968 *freeptr++='\0';
969 argc+=1;
970 if (*lineptr=='\0') continue;
971 lineptr+=1;
972 } else {
973 as_fatal("Too many operands passed to instruction");
974 }
975 }
976 }
977 }
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");
982 }
983 } else {
984 as_fatal("Wrong number of operands");
985 }
986
987 }
988 for (i=0;i<IIF_ENTRIES;i++) {
989 iif.iifP[i].type=0; /* mark all entries as void*/
990 }
991
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);
995
996 /* this call encodes operands to iif format */
997 if (argc) {
998 encode_operand(argc,
999 argv,
1000 &desc->operands[0],
1001 &suffix[0],
1002 desc->im_size,
1003 desc->opcode_size);
1004 }
1005 return recursive_level;
1006 }
1007
1008 \f
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.
1017 */
1018 void convert_iif() {
1019 int i;
1020 int j;
1021 fragS *inst_frag;
1022 char *inst_offset;
1023 char **inst_opcode;
1024 char *memP;
1025 segT segment;
1026 int l;
1027 int k;
1028 int rem_size; /* count the remaining bytes of instruction */
1029 char type;
1030 char size = 0;
1031 int size_so_far = 0; /* used to calculate pcrel_adjust */
1032
1033 rem_size=iif.instr_size;
1034 memP=frag_more(iif.instr_size); /* make sure we have enough bytes for instruction */
1035 inst_opcode=memP;
1036 inst_offset=(char*)(memP-frag_now->fr_literal);
1037 inst_frag=frag_now;
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;
1044 }
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;
1049 switch (type) {
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),
1054 size,
1055 0,
1056 0,
1057 iif.iifP[i].object,
1058 iif.iifP[i].pcrel,
1059 (char)size_so_far, /*iif.iifP[i].pcrel_adjust,*/
1060 iif.iifP[i].im_disp,
1061 j,
1062 iif.iifP[i].bsr); /* sequent hack */
1063 } else { /* good, just put them bytes out */
1064 switch (iif.iifP[i].im_disp) {
1065 case 0:
1066 md_number_to_chars(memP,iif.iifP[i].object,size);break;
1067 case 1:
1068 md_number_to_disp(memP,iif.iifP[i].object,size);break;
1069 default: as_fatal("iif convert internal pcrel/binary");
1070 }
1071 }
1072 memP+=size;
1073 rem_size-=size;
1074 break;
1075 case 2: /* the object is a pointer at an expression, so unpack
1076 it, note that bignums may result from the expression
1077 */
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");
1083 if (k==3) memP+=2;
1084 for (l=0;k>0;k--,l+=2) {
1085 md_number_to_chars(memP+l,generic_bignum[l>>1],sizeof(LITTLENUM_TYPE));
1086 }
1087 } else { /* flonum */
1088 LITTLENUM_TYPE words[4];
1089
1090 switch(size) {
1091 case 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));
1095 break;
1096 case 8:
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));
1102 break;
1103 }
1104 }
1105 memP+=size;
1106 rem_size-=size;
1107 break;
1108 }
1109 if (j ||
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),
1118 size,
1119 exprP.X_add_symbol,
1120 exprP.X_subtract_symbol,
1121 exprP.X_add_number,
1122 iif.iifP[i].pcrel,
1123 (char)size_so_far, /*iif.iifP[i].pcrel_adjust,*/
1124 iif.iifP[i].im_disp,
1125 j,
1126 iif.iifP[i].bsr); /* sequent hack */
1127
1128 } else { /* good, just put them bytes out */
1129 switch (iif.iifP[i].im_disp) {
1130 case 0:
1131 md_number_to_imm(memP,exprP.X_add_number,size);break;
1132 case 1:
1133 md_number_to_disp(memP,exprP.X_add_number,size);break;
1134 default: as_fatal("iif convert internal pcrel/pointer");
1135 }
1136 }
1137 memP+=size;
1138 rem_size-=size;
1139 break;
1140 default: as_fatal("Internal logic error in iif.iifP[n].type");
1141 }
1142 break;
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.
1148 */
1149 {
1150 int temp;
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),
1157 size,
1158 exprP.X_add_symbol,
1159 exprP.X_subtract_symbol,
1160 exprP.X_add_number,
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, */
1164 0,0);
1165 memP+=size;
1166 rem_size-=4;
1167 break; /* exit this absolute hack */
1168 }
1169
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");
1173 }
1174 else {
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
1178 */
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.
1185 */
1186 (void)frag_variant(rs_machine_dependent,
1187 4,
1188 0,
1189 IND(BRANCH,UNDEF), /* expecting the worst */
1190 exprP.X_add_symbol,
1191 exprP.X_add_number,
1192 (char*)inst_opcode,
1193 (char)size_so_far, /*iif.iifP[i].pcrel_adjust);*/
1194 iif.iifP[i].bsr); /* sequent linker hack */
1195 rem_size-=4;
1196 if (rem_size>0) {
1197 memP=frag_more(rem_size);
1198 }
1199 }
1200 }
1201 else {/* Double work, this is done in md_number_to_disp */
1202 /* exprP.X_add_number; what was this supposed to be?
1203 xoxorich. */
1204 if (-64<=exprP.X_add_number && exprP.X_add_number<=63) {
1205 size=1;
1206 } else {
1207 if (-8192<=exprP.X_add_number && exprP.X_add_number<=8191) {
1208 size=2;
1209 } else {
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) */
1214 {
1215 size=4;
1216 } else {
1217 as_warn("Displacement to large for :d");
1218 size=4;
1219 }
1220 }
1221 }
1222 /* rewind the bytes not used */
1223 temp = -(4-size);
1224 md_number_to_disp(memP,exprP.X_add_number,size);
1225 obstack_blank_fast(&frags,temp);
1226 memP+=size;
1227 rem_size-=4; /* we allocated this amount */
1228 }
1229 }
1230 break;
1231 default:
1232 as_fatal("Internal logic error in iif.iifP[].type");
1233 }
1234 size_so_far+=size;
1235 size=0;
1236 }
1237 }
1238 }
1239 \f
1240 void md_assemble(line)
1241 char *line;
1242 {
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 */
1246 #ifdef SHOW_NUM
1247 printf(" \t\t\t%s\n",line);
1248 #endif
1249 }
1250
1251
1252 void md_begin() {
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*/
1260 exit(0);
1261 }
1262 }
1263 freeptr_static=(char*)malloc(PRIVATE_SIZE); /* some private space please! */
1264 }
1265
1266
1267 void
1268 md_end() {
1269 free(freeptr_static);
1270 }
1271
1272 /* Must be equal to MAX_PRECISON in atof-ieee.c */
1273 #define MAX_LITTLENUMS 6
1274
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.
1278 */
1279 char *
1280 md_atof(type,litP,sizeP)
1281 char type;
1282 char *litP;
1283 int *sizeP;
1284 {
1285 int prec;
1286 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1287 LITTLENUM_TYPE *wordP;
1288 char *t;
1289
1290 switch(type) {
1291 case 'f':
1292 prec = 2;
1293 break;
1294
1295 case 'd':
1296 prec = 4;
1297 break;
1298 default:
1299 *sizeP=0;
1300 return "Bad call to MD_ATOF()";
1301 }
1302 t=atof_ieee(input_line_pointer,type,words);
1303 if(t)
1304 input_line_pointer=t;
1305
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);
1310 }
1311 return ""; /* Someone should teach Dean about null pointers */
1312 }
1313 \f
1314 /* Convert number to chars in correct order */
1315
1316 void
1317 md_number_to_chars (buf, value, nbytes)
1318 char *buf;
1319 long value;
1320 int nbytes;
1321 {
1322 while (nbytes--) {
1323 #ifdef SHOW_NUM
1324 printf("%x ",value & 0xff);
1325 #endif
1326 *buf++ = value; /* Lint wants & MASK_CHAR. */
1327 value >>= BITS_PER_CHAR;
1328 }
1329 } /* md_number_to_chars() */
1330
1331
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
1335 with a size-tag.
1336
1337 binary: msb -> lsb
1338 0xxxxxxx byte
1339 10xxxxxx xxxxxxxx word
1340 11xxxxxx xxxxxxxx xxxxxxxx xxxxxxxx double word
1341
1342 This must be taken care of and we do it here!
1343 */
1344 static void md_number_to_disp(buf, val, n)
1345 char *buf;
1346 long val;
1347 char n;
1348 {
1349 switch(n) {
1350 case 1:
1351 if (val < -64 || val > 63)
1352 as_warn("Byte displacement out of range. line number not valid");
1353 val&=0x7f;
1354 #ifdef SHOW_NUM
1355 printf("%x ",val & 0xff);
1356 #endif
1357 *buf++=val;
1358 break;
1359 case 2:
1360 if (val < -8192 || val > 8191)
1361 as_warn("Word displacement out of range. line number not valid");
1362 val&=0x3fff;
1363 val|=0x8000;
1364 #ifdef SHOW_NUM
1365 printf("%x ",val>>8 & 0xff);
1366 #endif
1367 *buf++=(val>>8);
1368 #ifdef SHOW_NUM
1369 printf("%x ",val & 0xff);
1370 #endif
1371 *buf++=val;
1372 break;
1373 case 4:
1374 if (val < -0x1f000000 || val >= 0x20000000)
1375 /* if (val < -0x20000000 || val >= 0x20000000) */
1376 as_warn("Double word displacement out of range");
1377 val|=0xc0000000;
1378 #ifdef SHOW_NUM
1379 printf("%x ",val>>24 & 0xff);
1380 #endif
1381 *buf++=(val>>24);
1382 #ifdef SHOW_NUM
1383 printf("%x ",val>>16 & 0xff);
1384 #endif
1385 *buf++=(val>>16);
1386 #ifdef SHOW_NUM
1387 printf("%x ",val>>8 & 0xff);
1388 #endif
1389 *buf++=(val>>8);
1390 #ifdef SHOW_NUM
1391 printf("%x ",val & 0xff);
1392 #endif
1393 *buf++=val;
1394 break;
1395 default:
1396 as_fatal("Internal logic error. line %s, file \"%s\"", __LINE__, __FILE__);
1397 }
1398 }
1399
1400 static void md_number_to_imm(buf,val,n)
1401 char *buf;
1402 long val;
1403 char n;
1404 {
1405 switch(n) {
1406 case 1:
1407 #ifdef SHOW_NUM
1408 printf("%x ",val & 0xff);
1409 #endif
1410 *buf++=val;
1411 break;
1412 case 2:
1413 #ifdef SHOW_NUM
1414 printf("%x ",val>>8 & 0xff);
1415 #endif
1416 *buf++=(val>>8);
1417 #ifdef SHOW_NUM
1418 printf("%x ",val & 0xff);
1419 #endif
1420 *buf++=val;
1421 break;
1422 case 4:
1423 #ifdef SHOW_NUM
1424 printf("%x ",val>>24 & 0xff);
1425 #endif
1426 *buf++=(val>>24);
1427 #ifdef SHOW_NUM
1428 printf("%x ",val>>16 & 0xff);
1429 #endif
1430 *buf++=(val>>16);
1431 #ifdef SHOW_NUM
1432 printf("%x ",val>>8 & 0xff);
1433 #endif
1434 *buf++=(val>>8);
1435 #ifdef SHOW_NUM
1436 printf("%x ",val & 0xff);
1437 #endif
1438 *buf++=val;
1439 break;
1440 default:
1441 as_fatal("Internal logic error. line %s, file \"%s\"", __LINE__, __FILE__);
1442 }
1443 }
1444
1445 /* Translate internal representation of relocation info into target format.
1446
1447 OVE: on a ns32k the twiddling continues at an even deeper level
1448 here we have to distinguish between displacements and immediates.
1449
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) !?!?!?!
1452
1453 This md_ri.... is tailored for sequent.
1454 */
1455
1456 #ifdef comment
1457 void
1458 md_ri_to_chars(the_bytes, ri)
1459 char *the_bytes;
1460 struct reloc_info_generic *ri;
1461 {
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 )),
1470 4);
1471 /* the first and second md_number_to_chars never overlaps (32bit cpu case) */
1472 }
1473 #endif /* comment */
1474
1475 /* fast bitfiddling support */
1476 /* mask used to zero bitfield before oring in the true field */
1477
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,
1486 };
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,
1495 };
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!)
1502 */
1503
1504 static void
1505 md_number_to_field(buf,val,field_ptr)
1506 register char *buf;
1507 register long val;
1508 register bit_fixS *field_ptr;
1509 {
1510 register unsigned long object;
1511 register unsigned long mask;
1512 /* define ENDIAN on a ns32k machine */
1513 #ifdef ENDIAN
1514 register unsigned long *mem_ptr;
1515 #else
1516 register char *mem_ptr;
1517 #endif
1518 if (field_ptr->fx_bit_min<=val && val<=field_ptr->fx_bit_max) {
1519 #ifdef ENDIAN
1520 if (field_ptr->fx_bit_base) { /* override buf */
1521 mem_ptr=(unsigned long*)field_ptr->fx_bit_base;
1522 } else {
1523 mem_ptr=(unsigned long*)buf;
1524 }
1525 #else
1526 if (field_ptr->fx_bit_base) { /* override buf */
1527 mem_ptr=(char*)field_ptr->fx_bit_base;
1528 } else {
1529 mem_ptr=buf;
1530 }
1531 #endif
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 */
1537 object=0;
1538 object|=mem_ptr[3] & 0xff;
1539 object<<=8;
1540 object|=mem_ptr[2] & 0xff;
1541 object<<=8;
1542 object|=mem_ptr[1] & 0xff;
1543 object<<=8;
1544 object|=mem_ptr[0] & 0xff;
1545 #endif
1546 mask=0;
1547 mask|=(r_mask[field_ptr->fx_bit_offset]);
1548 mask|=(l_mask[field_ptr->fx_bit_offset+field_ptr->fx_bit_size]);
1549 object&=mask;
1550 val+=field_ptr->fx_bit_add;
1551 object|=((val<<field_ptr->fx_bit_offset) & (mask ^ 0xffffffff));
1552 #ifdef ENDIAN
1553 *mem_ptr=object;
1554 #else
1555 mem_ptr[0]=(char)object;
1556 object>>=8;
1557 mem_ptr[1]=(char)object;
1558 object>>=8;
1559 mem_ptr[2]=(char)object;
1560 object>>=8;
1561 mem_ptr[3]=(char)object;
1562 #endif
1563 } else {
1564 as_warn("Bit field out of range");
1565 }
1566 }
1567
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.
1570
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. */
1574
1575 void
1576 md_apply_fix(fixP, val)
1577 fixS *fixP;
1578 long val;
1579 {
1580 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
1581
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) {
1585
1586 case 0: /* Immediate field */
1587 md_number_to_imm (buf, val, fixP->fx_size);
1588 break;
1589
1590 case 1: /* Displacement field */
1591 md_number_to_disp (buf,
1592 fixP->fx_pcrel? val + fixP->fx_pcrel_adjust: val,
1593 fixP->fx_size);
1594 break;
1595
1596 case 2: /* Pointer in a data object */
1597 md_number_to_chars (buf, val, fixP->fx_size);
1598 break;
1599 }
1600 }
1601 \f
1602 /* Convert a relaxed displacement to ditto in final output */
1603
1604 void
1605 md_convert_frag(headers, fragP)
1606 object_headers *headers;
1607 register fragS *fragP;
1608 {
1609 long disp;
1610 long ext = 0;
1611
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;
1616
1617 know(fragP->fr_symbol);
1618
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;
1622
1623 switch(fragP->fr_subtype) {
1624 case IND(BRANCH,BYTE):
1625 ext=1;
1626 break;
1627 case IND(BRANCH,WORD):
1628 ext=2;
1629 break;
1630 case IND(BRANCH,DOUBLE):
1631 ext=4;
1632 break;
1633 }
1634 if(ext) {
1635 md_number_to_disp(buffer_address,(long)disp,(int)ext);
1636 fragP->fr_fix+=ext;
1637 }
1638 }
1639
1640
1641
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
1644 actually know it */
1645
1646 int md_estimate_size_before_relax(fragP, segment)
1647 register fragS *fragP;
1648 segT segment;
1649 {
1650 int old_fix;
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);
1657 } else {
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),
1662 4,
1663 fragP->fr_symbol,
1664 (symbolS *)0,
1665 fragP->fr_offset,
1666 1,
1667 fragP->fr_pcrel_adjust,
1668 1,
1669 0,
1670 fragP->fr_bsr); /*sequent hack */
1671 fragP->fr_fix+=4;
1672 /* fragP->fr_opcode[1]=0xff; */
1673 frag_wane(fragP);
1674 break;
1675 }
1676 case IND(BRANCH,BYTE):
1677 fragP->fr_var+=1;
1678 break;
1679 default:
1680 break;
1681 }
1682 return fragP->fr_var + fragP->fr_fix - old_fix;
1683 }
1684
1685 int md_short_jump_size = 3;
1686 int md_long_jump_size = 5;
1687 int md_reloc_size = 8; /* Size of relocation record */
1688
1689 void
1690 md_create_short_jump(ptr,from_addr,to_addr,frag,to_symbol)
1691 char *ptr;
1692 long from_addr,
1693 to_addr;
1694 fragS *frag;
1695 symbolS *to_symbol;
1696 {
1697 long offset;
1698
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);
1702 }
1703
1704 void
1705 md_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol)
1706 char *ptr;
1707 long from_addr,
1708 to_addr;
1709 fragS *frag;
1710 symbolS *to_symbol;
1711 {
1712 long offset;
1713
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);
1717 }
1718 \f
1719 /* JF this is a new function to parse machine-dep options */
1720 int
1721 md_parse_option(argP,cntP,vecP)
1722 char **argP;
1723 int *cntP;
1724 char ***vecP;
1725 {
1726 switch(**argP) {
1727 case 'm':
1728 (*argP)++;
1729
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;
1736 } else
1737 as_warn("Unknown -m option ignored");
1738
1739 while(**argP)
1740 (*argP)++;
1741 break;
1742
1743 default:
1744 return 0;
1745 }
1746 return 1;
1747 }
1748 \f
1749 /*
1750 * bit_fix_new()
1751 *
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.
1755 */
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 */
1760 long base_adj;
1761 long min; /* Signextended min for bitfield */
1762 long max; /* Signextended max for bitfield */
1763 long add; /* Add mask, used for huffman prefix */
1764 {
1765 register bit_fixS * bit_fixP;
1766
1767 bit_fixP = (bit_fixS *)obstack_alloc(&notes,sizeof(bit_fixS));
1768
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;
1776
1777 return(bit_fixP);
1778 }
1779
1780 void
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 */
1794
1795 {
1796 fixS *fixP = fix_new(frag, where, size, add_symbol, sub_symbol,
1797 offset, pcrel, NO_RELOC);
1798
1799 fixP->fx_pcrel_adjust = pcrel_adjust;
1800 fixP->fx_im_disp = im_disp;
1801 fixP->fx_bit_fixP = bit_fixP;
1802 fixP->fx_bsr = bsr;
1803 } /* fix_new_ns32k() */
1804
1805 /* We have no need to default values of symbols. */
1806
1807 symbolS *
1808 md_undefined_symbol (name)
1809 char *name;
1810 {
1811 return 0;
1812 }
1813
1814 /* Parse an operand that is machine-specific.
1815 We just return without modifying the expression if we have nothing
1816 to do. */
1817
1818 /* ARGSUSED */
1819 void
1820 md_operand (expressionP)
1821 expressionS *expressionP;
1822 {
1823 }
1824
1825 /* Round up a section size to the appropriate boundary. */
1826 long
1827 md_section_align (segment, size)
1828 segT segment;
1829 long size;
1830 {
1831 return size; /* Byte alignment is fine */
1832 }
1833
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) */
1838 long
1839 md_pcrel_from (fixP)
1840 fixS *fixP;
1841 {
1842 long res;
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! */
1847 #endif
1848 return res;
1849 }
1850
1851 void tc_aout_fix_to_chars(char *where, struct fix *fixP,
1852 relax_addressT segment_address) {
1853 know(0); /* know nothing */
1854 }
1855
1856 /*
1857 * Local Variables:
1858 * comment-column: 0
1859 * End:
1860 */
1861
1862 /* end of tc-ns32k.c */
This page took 0.072954 seconds and 5 git commands to generate.