|
|
1.1 root 1: /* hppa.c -- Assemble for the HP-PA
2: Copyright (C) 1989 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:
21: /*
22: HP PA-RISC support was contributed by the Center for Software Science
23: at the University of Utah.
24: */
25:
26: /* HP-PA support for Mach-O ... USV */
27:
28: #include <stdio.h>
29: #include <ctype.h>
30: #include <string.h>
31: #include <mach-o/hppa/reloc.h>
32: #define HPPA_RELOC_12BRANCH (127) /* only used internal in here */
33:
34: #include "obstack.h"
35: #include "hppa-opcode.h"
36: #include "as.h"
37: #include "frags.h"
38: #include "flonum.h"
39: #include "hash.h"
40: #include "md.h"
41: #include "symbols.h"
42: #include "hppa-aux.h"
43: #include "messages.h"
44: #include "stuff/hppa.h"
45:
46: /*
47: * These are the default cputype and cpusubtype for the hppa architecture.
48: */
49: const cpu_type_t md_cputype = CPU_TYPE_HPPA;
50: cpu_subtype_t md_cpusubtype = CPU_SUBTYPE_HPPA_ALL;
51:
52: /* This is the byte sex for the hppa architecture */
53: const enum byte_sex md_target_byte_sex = BIG_ENDIAN_BYTE_SEX;
54:
55: /* These characters start a comment anywhere on the line */
56: const char md_comment_chars[] = ";";
57:
58: /* These characters only start a comment at the beginning of a line */
59: const char md_line_comment_chars[] = "#";
60:
61: /*
62: * These characters can be used to separate mantissa decimal digits from
63: * exponent decimal digits in floating point numbers.
64: */
65: const char md_EXP_CHARS[] = "eE";
66:
67: /*
68: * The characters after a leading 0 that means this number is a floating point
69: * constant as in 0f123.456 or 0d1.234E-12 (see md_EXP_CHARS above).
70: */
71: const char md_FLT_CHARS[] = "dDfF";
72:
73: /*
74: * This is the machine dependent pseudo opcode table for this target machine.
75: */
76: const pseudo_typeS md_pseudo_table[] =
77: {
78: {0} /* end of table marker */
79: };
80:
81:
82: static int found_jbsr = 0;
83: static char *toP;
84:
85: const relax_typeS md_relax_table[] = { 0 };
86:
87: /* handle of the OPCODE hash table */
88: static struct hash_control *op_hash = NULL;
89:
90: struct pa_it the_insn; /* this structure is defined in pa-aux.h */
91:
92: char *expr_end;
93:
94: static void pa_ip(
95: char *str);
96: static int parse_L_or_R(
97: char *str);
98: static unsigned long parse_completer_with_cache_control_hint(
99: char **s, /* Note : the function changes '*s' */
100: int option, /* option = 0 for store instruction */
101: /* option = 1 for load and clear instruction */
102: char completer);/* 'c' or 'C' */
103: static unsigned long parse_cache_control_hint(
104: char **s, /* Note : the function changes '*s' */
105: int option); /* option = 0 for store instruction */
106: /* option = 1 for load and clear instruction */
107:
108: /* This function is called once, at assembler startup time. It should
109: set up all the tables, etc. that the MD part of the assembler will need. */
110: void
111: md_begin(
112: void)
113: {
114: register char *retval = NULL;
115: int lose = 0;
116: register unsigned int i = 0;
117:
118: op_hash = hash_new();
119: if (op_hash == NULL)
120: as_fatal("Virtual memory exhausted");
121:
122: while (i < NUMOPCODES) {
123: const char *name = pa_opcodes[i].name;
124: retval = hash_insert(op_hash, (char *)name,
125: (char *)&pa_opcodes[i]);
126: if(retval != NULL && *retval != '\0') {
127: as_fatal("Internal error: can't hash `%s': %s\n",
128: pa_opcodes[i].name, retval);
129: lose = 1;
130: }
131: ++i;
132: }
133:
134: if (lose)
135: as_fatal ("Broken assembler. No assembly attempted.");
136: }
137:
138: void
139: md_end(
140: void)
141: {
142: return;
143: }
144:
145: void
146: md_assemble(
147: char *str)
148: {
149:
150: assert(str);
151: pa_ip(str);
152: if (!found_jbsr)
153: toP = frag_more(4);
154: else
155: found_jbsr = 0;
156:
157: /* put out the opcode */
158: md_number_to_chars(toP, the_insn.opcode, 4);
159:
160: /* put out the symbol-dependent stuff */
161: if (the_insn.reloc != NO_RELOC) {
162: fix_new(frag_now, /* which frag */
163: (toP - frag_now->fr_literal), /* where */
164: 4, /* size */
165: the_insn.exp.X_add_symbol,
166: the_insn.exp.X_subtract_symbol,
167: the_insn.exp.X_add_number, /* offset */
168: the_insn.pcrel,
169: the_insn.pcrel_reloc,
170: the_insn.reloc);
171: }
172: }
173:
174: static
175: void
176: pa_ip(
177: char *str)
178: {
179: char *s;
180: const char *args;
181: char c;
182: unsigned long i;
183: struct pa_opcode *insn;
184: char *argsStart;
185: unsigned long opcode;
186: int match = FALSE;
187: int comma = 0;
188:
189: int reg,reg1,reg2,s2,s3;
190: unsigned int im21,im14,im11,im5;
191: int m,a,u,f;
192: int cmpltr,nullif, flag;
193: int sfu, cond;
194: char *name;
195: char *save_s;
196:
197: #ifdef PA_DEBUG
198: fprintf(stderr,"STATEMENT: \"%s\"\n",str);
199: #endif
200: for (s = str; isupper(*s) || islower(*s) || (*s >= '0' && *s <= '3'); ++s)
201: ;
202: switch (*s) {
203:
204: case '\0':
205: break;
206:
207: case ',':
208: comma = 1;
209:
210: /*FALLTHROUGH*/
211:
212: case ' ':
213: *s++ = '\0';
214: break;
215:
216: default:
217: as_bad("Unknown opcode: `%s'", str);
218: exit(1);
219: }
220:
221: save_s = str;
222:
223: while ( *save_s ) {
224: if ( isupper(*save_s) )
225: *save_s = tolower(*save_s);
226: save_s++;
227: }
228:
229: if ((insn = (struct pa_opcode *) hash_find(op_hash, str)) == NULL) {
230: as_bad("Unknown opcode: `%s'", str);
231: return;
232: }
233: if (comma) {
234: *--s = ',';
235: }
236: argsStart = s;
237: for (;;) {
238: opcode = insn->match;
239: memset(&the_insn, '\0', sizeof(the_insn));
240: the_insn.reloc = NO_RELOC; /* USV */
241:
242: /*
243: * Build the opcode, checking as we go to make
244: * sure that the operands match
245: */
246: for (args = insn->args; ; ++args) {
247:
248: switch (*args) {
249:
250: case '\0': /* end of args */
251: if (*s == '\0') {
252: match = TRUE;
253: }
254: break;
255:
256: case '(': /* these must match exactly */
257: case ')':
258: case ',':
259: case ' ':
260: if (*s++ == *args)
261: continue;
262: break;
263:
264: case 'b': /* 5 bit register field at 10 */
265: reg = pa_parse_number(&s);
266: if ( reg < 32 && reg >= 0 ) {
267: opcode |= reg << 21;
268: continue;
269: }
270: break;
271: case 'x': /* 5 bit register field at 15 */
272: reg = pa_parse_number(&s);
273: if ( reg < 32 && reg >= 0 ) {
274: opcode |= reg << 16;
275: continue;
276: }
277: break;
278: case 't': /* 5 bit register field at 31 */
279: reg = pa_parse_number(&s);
280: if ( reg < 32 && reg >= 0 ) {
281: opcode |= reg;
282: continue;
283: }
284: break;
285: case 'T': /* 5 bit field length at 31 (encoded as 32-T) */
286: /*
287: reg = pa_parse_number(&s);
288: */
289: getAbsoluteExpression(s);
290: if ( the_insn.exp.X_seg == SEG_ABSOLUTE ) {
291: reg = the_insn.exp.X_add_number;
292: if ( reg <= 32 && reg > 0 ) {
293: opcode |= 32 - reg;
294: s = expr_end;
295: continue;
296: }
297: }
298: break;
299: case '5': /* 5 bit immediate at 15 */
300: getAbsoluteExpression(s);
301: /** PJH: The following 2 calls to as_bad() might eventually **/
302: /** want to end up as as_warn(). **/
303: if ( the_insn.exp.X_add_number > 15 ) {
304: as_bad("5 bit immediate: %ld > 15. Set to 15",
305: the_insn.exp.X_add_number);
306: the_insn.exp.X_add_number = 15;
307: }
308: else if ( the_insn.exp.X_add_number < -16 ) {
309: as_bad("5 bit immediate: %ld < -16. Set to -16",
310: the_insn.exp.X_add_number);
311: the_insn.exp.X_add_number = -16;
312: }
313:
314: im5 = low_sign_unext(evaluateAbsolute(
315: the_insn.exp,0),5);
316: opcode |= ( im5 << 16 );
317: s = expr_end;
318: continue;
319:
320: case 's': /* 2 bit space identifier at 17 */
321: s2 = pa_parse_number(&s);
322: if ( s2 < 4 && s2 >= 0 ) {
323: opcode |= s2 << 14;
324: continue;
325: }
326: break;
327: case 'S': /* 3 bit space identifier at 18 */
328: s3 = pa_parse_number(&s);
329: if ( s3 < 8 && s3 >= 0 ) {
330: s3 = dis_assemble_3(s3);
331: opcode |= s3 << 13;
332: continue;
333: }
334: break;
335: case 'c': /* indexed load completer. */
336: i = m = u = 0;
337: while ( *s == ',' && i < 2 ) {
338: s++;
339: if ( strncasecmp(s,"sm",2) == 0 ) {
340: m = u = 1;
341: s++;
342: i++;
343: }
344: else if ( strncasecmp(s,"m",1) == 0 )
345: m = 1;
346: else if ( strncasecmp(s,"s",1) == 0 )
347: u = 1;
348: else
349: as_bad("Unrecognized Indexed Load"
350: "Completer...assuming 0");
351: s++;
352: i++;
353: }
354: if ( i > 2 )
355: as_bad("Illegal Indexed Load Completer Syntax..."
356: "extras ignored");
357: while ( *s == ' ' || *s == '\t' )
358: s++;
359:
360: opcode |= m << 5;
361: opcode |= u << 13;
362: continue;
363: case 'C': /* short load and store completer */
364: m = a = 0;
365: if ( *s == ',' ) {
366: s++;
367: if ( strncasecmp(s,"ma",2) == 0 ) {
368: a = 0;
369: m = 1;
370: }
371: else if ( strncasecmp(s,"mb",2) == 0 ) {
372: m = a = 1;
373: }
374: else
375: as_bad("Unrecognized Indexed Load Completer"
376: "...assuming 0");
377: s += 2;
378: }
379: while ( *s == ' ' || *s == '\t' )
380: s++;
381: opcode |= m << 5;
382: opcode |= a << 13;
383: continue;
384:
385: /* bug #41317 .... [email protected]
386: * Fri Jul 22 09:43:46 PDT 1994
387: *
388: * Modified to parse 'cache control hints'
389: *
390: * These parse ",cc" and encode "cc" in 2 bits at 20,
391: * where "cc" encoding is as given in Tables 5-8, 5-9.
392: * Refer to 'PA-RISC 1.1 Architecture and Instruction Set
393: * Reference Manual, Second Edition' for the tables.
394: */
395: case 'Y': /* Store Bytes Short completer */
396: /* with cache control hints */
397: {
398: unsigned long result = (unsigned long)0UL;
399:
400: i = m = a = 0;
401: while ( *s == ',' && i < 3 ) {
402: s++;
403: if ( strncasecmp(s,"m",1) == 0 )
404: m = 1;
405: else if ( strncasecmp(s,"b",1) == 0 &&
406: (strncasecmp((s+1),"c",1) != 0) )
407: a = 0;
408: else if ( strncasecmp(s,"e",1) == 0 )
409: a = 1;
410: else if ( strncmp(s,",",1) == 0 ) /* no completer */
411: result |= parse_cache_control_hint(&s, 0);
412: else if ( (strncasecmp(s,"c",1) == 0) ||
413: (strncasecmp(s,"b",1) == 0) ) {/* just 1 completer */
414: s--;
415: result |= parse_cache_control_hint(&s, 0);
416: }
417: else
418: as_bad("Unrecognized Store Bytes Short"
419: "Completer with cache control hints"
420: " ...assuming 0");
421: if (result == (unsigned long)0UL)
422: s++;
423: i++;
424: }
425: /** if ( i >= 2 ) **/
426: if ( i > 3 )
427: as_bad("Illegal Store Bytes Short Completer "
428: "with cache control hints ... extras ignored");
429: while ( *s == ' ' || *s == '\t' ) /* skip to next operand */
430: s++;
431: opcode |= result;
432: opcode |= m << 5;
433: opcode |= a << 13;
434: continue;
435: }
436: case '<': /* non-negated compare/subtract conditions. */
437: cmpltr = pa_parse_nonneg_cmpsub_cmpltr(&s);
438: if ( cmpltr < 0 ) {
439: as_bad("Unrecognized Compare/Subtract Condition: %c",*s);
440: cmpltr = 0;
441: }
442: opcode |= cmpltr << 13;
443: continue;
444: case '?': /* negated or non-negated cmp/sub conditions. */
445: /* used only by ``comb'' and ``comib'' pseudo-ops */
446: save_s = s;
447: cmpltr = pa_parse_nonneg_cmpsub_cmpltr(&s);
448: if ( cmpltr < 0 ) {
449: s = save_s;
450: cmpltr = pa_parse_neg_cmpsub_cmpltr(&s);
451: if ( cmpltr < 0 ) {
452: as_bad("Unrecognized Compare/Subtract Condition: %c"
453: ,*s);
454: cmpltr = 0;
455: }
456: else {
457: opcode |= 1 << 27; /* required opcode change to make
458: COMIBT into a COMIBF or a
459: COMBT into a COMBF or a
460: ADDBT into a ADDBF or a
461: ADDIBT into a ADDIBF */
462: }
463: }
464: opcode |= cmpltr << 13;
465: continue;
466: case '!': /* negated or non-negated add conditions. */
467: /* used only by ``addb'' and ``addib'' pseudo-ops */
468: save_s = s;
469: cmpltr = pa_parse_nonneg_add_cmpltr(&s);
470: if ( cmpltr < 0 ) {
471: s = save_s;
472: cmpltr = pa_parse_neg_add_cmpltr(&s);
473: if ( cmpltr < 0 ) {
474: as_bad("Unrecognized Compare/Subtract Condition: %c",
475: *s);
476: cmpltr = 0;
477: }
478: else {
479: opcode |= 1 << 27; /* required opcode change to make
480: COMIBT into a COMIBF or a
481: COMBT into a COMBF or a
482: ADDBT into a ADDBF or a
483: ADDIBT into a ADDIBF */
484: }
485: }
486: opcode |= cmpltr << 13;
487: continue;
488: case '-': /* compare/subtract conditions */
489: f = cmpltr = 0;
490: save_s = s;
491: if ( *s == ',' ) {
492: cmpltr = pa_parse_nonneg_cmpsub_cmpltr(&s);
493: if ( cmpltr < 0 ) {
494: f = 1;
495: s = save_s;
496: cmpltr = pa_parse_neg_cmpsub_cmpltr(&s);
497: if ( cmpltr < 0 ) {
498: as_bad("Unrecognized Compare/Subtract Condition");
499: }
500: }
501: }
502: opcode |= cmpltr << 13;
503: opcode |= f << 12;
504: continue;
505: case '+': /* non-negated add conditions */
506: flag = nullif = cmpltr = 0;
507: if ( *s == ',' ) {
508: s++;
509: name = s;
510: while ( *s != ',' && *s != ' ' && *s != '\t' )
511: s += 1;
512: c = *s;
513: *s = 0x00;
514: if ( strcmp(name,"=") == 0 ) {
515: cmpltr = 1;
516: }
517: else if ( strcmp(name,"<") == 0 ) {
518: cmpltr = 2;
519: }
520: else if ( strcmp(name,"<=") == 0 ) {
521: cmpltr = 3;
522: }
523: else if ( strcasecmp(name,"nuv") == 0 ) {
524: cmpltr = 4;
525: }
526: else if ( strcasecmp(name,"znv") == 0 ) {
527: cmpltr = 5;
528: }
529: else if ( strcasecmp(name,"sv") == 0 ) {
530: cmpltr = 6;
531: }
532: else if ( strcasecmp(name,"od") == 0 ) {
533: cmpltr = 7;
534: }
535: else if ( strcasecmp(name,"n") == 0 ) {
536: nullif = 1;
537: }
538: else if ( strcasecmp(name,"tr") == 0 ) {
539: cmpltr = 0;
540: flag = 1;
541: }
542: else if ( strcasecmp(name,"<>") == 0 ) {
543: flag = cmpltr = 1;
544: }
545: else if ( strcasecmp(name,">=") == 0 ) {
546: cmpltr = 2;
547: flag = 1;
548: }
549: else if ( strcasecmp(name,">") == 0 ) {
550: cmpltr = 3;
551: flag = 1;
552: }
553: else if ( strcasecmp(name,"uv") == 0 ) {
554: cmpltr = 4;
555: flag = 1;
556: }
557: else if ( strcasecmp(name,"vnz") == 0 ) {
558: cmpltr = 5;
559: flag = 1;
560: }
561: else if ( strcasecmp(name,"nsv") == 0 ) {
562: cmpltr = 6;
563: flag = 1;
564: }
565: else if ( strcasecmp(name,"ev") == 0 ) {
566: cmpltr = 7;
567: flag = 1;
568: }
569: else
570: as_bad("Unrecognized Add Condition: %s",name);
571: *s = c;
572: }
573: nullif = pa_parse_nullif(&s);
574: opcode |= nullif << 1;
575: opcode |= cmpltr << 13;
576: opcode |= flag << 12;
577: continue;
578: case '&': /* logical instruction conditions */
579: f = cmpltr = 0;
580: if ( *s == ',' ) {
581: s++;
582: name = s;
583: while ( *s != ',' && *s != ' ' && *s != '\t' )
584: s += 1;
585: c = *s;
586: *s = 0x00;
587: if ( strcmp(name,"=") == 0 ) {
588: cmpltr = 1;
589: }
590: else if ( strcmp(name,"<") == 0 ) {
591: cmpltr = 2;
592: }
593: else if ( strcmp(name,"<=") == 0 ) {
594: cmpltr = 3;
595: }
596: else if ( strcasecmp(name,"od") == 0 ) {
597: cmpltr = 7;
598: }
599: else if ( strcasecmp(name,"tr") == 0 ) {
600: cmpltr = 0;
601: f = 1;
602: }
603: else if ( strcmp(name,"<>") == 0 ) {
604: f = cmpltr = 1;
605: }
606: else if ( strcmp(name,">=") == 0 ) {
607: cmpltr = 2;
608: f = 1;
609: }
610: else if ( strcmp(name,">") == 0 ) {
611: cmpltr = 3;
612: f = 1;
613: }
614: else if ( strcasecmp(name,"ev") == 0 ) {
615: cmpltr = 7;
616: f = 1;
617: }
618: else
619: as_bad("Unrecognized Logical Instruction Condition:"
620: " %s",name);
621: *s = c;
622: }
623: opcode |= cmpltr << 13;
624: opcode |= f << 12;
625: continue;
626: case 'U': /* unit instruction conditions */
627: cmpltr = 0;
628: f = 0;
629: if ( *s == ',' ) {
630: s++;
631: if ( strncasecmp(s,"sbz",3) == 0 ) {
632: cmpltr = 2;
633: s += 3;
634: }
635: else if ( strncasecmp(s,"shz",3) == 0 ) {
636: cmpltr = 3;
637: s += 3;
638: }
639: else if ( strncasecmp(s,"sdc",3) == 0 ) {
640: cmpltr = 4;
641: s += 3;
642: }
643: else if ( strncasecmp(s,"sbc",3) == 0 ) {
644: cmpltr = 6;
645: s += 3;
646: }
647: else if ( strncasecmp(s,"shc",3) == 0 ) {
648: cmpltr = 7;
649: s += 3;
650: }
651: else if ( strncasecmp(s,"tr",2) == 0 ) {
652: cmpltr = 0;
653: f = 1;
654: s += 2;
655: }
656: else if ( strncasecmp(s,"nbz",3) == 0 ) {
657: cmpltr = 2;
658: f = 1;
659: s += 3;
660: }
661: else if ( strncasecmp(s,"nhz",3) == 0 ) {
662: cmpltr = 3;
663: f = 1;
664: s += 3;
665: }
666: else if ( strncasecmp(s,"ndc",3) == 0 ) {
667: cmpltr = 4;
668: f = 1;
669: s += 3;
670: }
671: else if ( strncasecmp(s,"nbc",3) == 0 ) {
672: cmpltr = 6;
673: f = 1;
674: s += 3;
675: }
676: else if ( strncasecmp(s,"nhc",3) == 0 ) {
677: cmpltr = 7;
678: f = 1;
679: s += 3;
680: }
681: else
682: as_bad("Unrecognized Logical Instruction Condition:"
683: " %c",*s);
684: }
685: opcode |= cmpltr << 13;
686: opcode |= f << 12;
687: continue;
688: case '>': /* shift/extract/deposit conditions. */
689: cmpltr = 0;
690: if ( *s == ',' ) {
691: s++;
692: name = s;
693: while ( *s != ',' && *s != ' ' && *s != '\t' )
694: s += 1;
695: c = *s;
696: *s = 0x00;
697: if ( strcmp(name,"=") == 0 ) {
698: cmpltr = 1;
699: }
700: else if ( strcmp(name,"<") == 0 ) {
701: cmpltr = 2;
702: }
703: else if ( strcasecmp(name,"od") == 0 ) {
704: cmpltr = 3;
705: }
706: else if ( strcasecmp(name,"tr") == 0 ) {
707: cmpltr = 4;
708: }
709: else if ( strcmp(name,"<>") == 0 ) {
710: cmpltr = 5;
711: }
712: else if ( strcmp(name,">=") == 0 ) {
713: cmpltr = 6;
714: }
715: else if ( strcasecmp(name,"ev") == 0 ) {
716: cmpltr = 7;
717: }
718: else
719: as_bad("Unrecognized Shift/Extract/Deposit"
720: "Condition: %s",name);
721: *s = c;
722: }
723: opcode |= cmpltr << 13;
724: continue;
725: case '~': /* bvb,bb conditions */
726: cmpltr = 0;
727: if ( *s == ',' ) {
728: s++;
729: if ( strncmp(s,"<",1) == 0 ) {
730: cmpltr = 2;
731: s++;
732: }
733: else if ( strncmp(s,">=",2) == 0 ) {
734: cmpltr = 6;
735: s += 2;
736: }
737: else
738: as_bad("Unrecognized Bit Branch Condition: %c",*s);
739: }
740: opcode |= cmpltr << 13;
741: continue;
742: case 'V': /* 5 bit immediate at 31 */
743: getExpression(s);
744: im5 = low_sign_unext(evaluateAbsolute(
745: the_insn.exp,0),5);
746: opcode |= im5;
747: s = expr_end;
748: continue;
749: case 'r': /* 5 bit immediate at 31 */
750: /* (unsigned value for the break instruction) */
751: getExpression(s);
752: im5 = evaluateAbsolute(the_insn.exp,0);
753: if ( im5 > 31 ) {
754: as_bad("Operand out of range. Was: %d. Should be"
755: "[0..31]. Assuming %d.\n",im5,im5&0x1f);
756: im5 = im5 & 0x1f;
757: }
758: opcode |= im5;
759: s = expr_end;
760: continue;
761: case 'R': /* 5 bit immediate at 15 */
762: /* (unsigned value for the ssm and rsm instruction) */
763: getExpression(s);
764: im5 = evaluateAbsolute(the_insn.exp,0);
765: if ( im5 > 31 ) {
766: as_bad("Operand out of range. Was: %d. Should be"
767: "[0..31]. Assuming %d.\n",im5,im5&0x1f);
768: im5 = im5 & 0x1f;
769: }
770: opcode |= im5 << 16;
771: s = expr_end;
772: continue;
773: case 'i': /* 11 bit immediate at 31 */
774: getExpression(s);
775: if ( the_insn.exp.X_seg == SEG_ABSOLUTE ) {
776: im11 = low_sign_unext(evaluateAbsolute(
777: the_insn.exp,0),11);
778: opcode |= im11;
779: }
780: else {
781: the_insn.code = 'i';
782: }
783: s = expr_end;
784: continue;
785: case 'j': /* 14 bit immediate at 31 --- LO14 */
786: {
787: int field_selector = parse_L_or_R(s);
788: switch (field_selector) {
789: case 2: /* found the field selector R`*/
790: case 1: /* found the field selector L`*/
791: s += 2; /* eat up L` or R` */
792: case 0: /* not found */
793: getExpression(s);
794: break;
795: default:
796: as_bad("Bad field selector. Was: %.2s. Should be either L` or R`\n",s);
797: break;
798: }
799: if ( the_insn.exp.X_seg == SEG_ABSOLUTE ) {
800: im14 = low_sign_unext(
801: evaluateAbsolute(the_insn.exp,field_selector), 14);
802:
803: /* I donot think the mask is necessary here low_sign_unext() takes */
804: /* care of putting only 14 bits in im14 ! ... 090993 ... USV */
805: /* if (field_selector)
806: opcode |= (im14 & 0x7ff);
807: else
808: */
809: opcode |= im14;
810: }
811: else {
812: the_insn.reloc = HPPA_RELOC_LO14;
813: the_insn.code = 'j';
814: }
815: s = expr_end;
816: continue;
817: }
818: case 'z': /* 17 bit branch displacement (non-pc-relative) */
819: /* for be, ble --- BR17*/
820: /* bl, ble in absence of L` or R` can have */
821: /* a 17 bit immmidiate number */
822: {
823: unsigned long w, w1, w2;
824: int field_selector = parse_L_or_R(s);
825: switch (field_selector) {
826: case 2: /* found the field selector R`*/
827: case 1: /* found the field selector L`*/
828: s += 2; /* eat up L` or R` */
829: case 0: /* not found */
830: getExpression(s);
831: break;
832: default:
833: as_bad("Bad field selector. Was: %.2s." "Should be either L` or R`\n",s);
834: break;
835: }
836: if ( the_insn.exp.X_seg == SEG_ABSOLUTE ) {
837: im14 = sign_unext(
838: evaluateAbsolute(the_insn.exp,field_selector),
839: 17);
840: dis_assemble_17(im14>>2,&w1,&w2,&w);
841: opcode |= ( ( w2 << 2 ) | ( w1 << 16 ) | w );
842: }
843: else {
844: the_insn.reloc = HPPA_RELOC_BR17;
845: the_insn.code = 'z';
846: }
847: s = expr_end;
848: continue;
849: }
850: case 'k': /* 21 bit immediate at 31 --- HI21 */
851: {
852: int field_selector = parse_L_or_R(s);
853: switch (field_selector) {
854: case 2: /* found the field selector R`*/
855: case 1: /* found the field selector L`*/
856: s += 2; /* eat up L` or R` */
857: case 0: /* not found */
858: getExpression(s);
859: break;
860: default:
861: as_bad("Bad field selector. Was: %.2s." "Should be either L` or R`\n",s);
862: break;
863: }
864: if ( the_insn.exp.X_seg == SEG_ABSOLUTE ) {
865: im21 = dis_assemble_21(
866: (evaluateAbsolute(the_insn.exp,field_selector) >> 11));
867: opcode |= im21 ;
868: }
869: else {
870: the_insn.reloc = HPPA_RELOC_HI21;
871: the_insn.code = 'k';
872: }
873: s = expr_end;
874: continue;
875: }
876: case 'n': /* nullification for branch instructions */
877: nullif = pa_parse_nullif(&s);
878: opcode |= nullif << 1;
879: continue;
880: case 'w': /* 12 bit branch displacement */
881: getExpression(s);
882: the_insn.pcrel_reloc = 0;
883: the_insn.pcrel = 1;
884: if ( the_insn.exp.X_add_symbol ) {
885: if ( strcmp(
886: the_insn.exp.X_add_symbol->sy_nlist.n_un.n_name,"L0\001") == 0 ) {
887: unsigned long w1,w,result;
888: result = sign_unext( (the_insn.exp.X_add_number
889: - 8) >> 2,
890: 12);
891: dis_assemble_12(result,&w1,&w);
892: opcode |= ( ( w1 << 2 ) | w );
893: }
894: else {
895: /* this has to be wrong -- dont know what is right! */
896: /* the_insn.reloc = R_PCREL_CALL; */
897: the_insn.reloc = HPPA_RELOC_12BRANCH;
898: the_insn.code = 'w';
899: }
900: }
901: else {
902: unsigned long w1,w,result;
903: result = sign_unext( the_insn.exp.X_add_number >>
904: 2,12);
905: dis_assemble_12(result,&w1,&w);
906: opcode |= ( ( w1 << 2 ) | w );
907: }
908: s = expr_end;
909: continue;
910: case 'W': /* 17 bit branch displacement --- BL17 */
911: getExpression(s);
912: /*
913: * The NeXT linker has the ability to scatter
914: * blocks of sections between labels. This
915: * requires that brances to labels that survive
916: * to the link phase must be able to be
917: * relocated.
918: */
919: if(the_insn.exp.X_add_symbol != NULL &&
920: (the_insn.exp.X_add_symbol->sy_name[0] != 'L'
921: || flagseen['L']))
922: the_insn.pcrel_reloc = 1;
923: else
924: the_insn.pcrel_reloc = 0;
925: the_insn.pcrel = 1;
926: if ( the_insn.exp.X_add_symbol ) {
927: if ( strcmp(the_insn.exp.X_add_symbol->sy_nlist.n_un.n_name,"L0\001") == 0 ) {
928: unsigned long w2,w1,w,result;
929:
930: result = sign_unext(
931: (the_insn.exp.X_add_number - 8) >> 2,17);
932: dis_assemble_17(result,&w1,&w2,&w);
933: opcode |= ( ( w2 << 2 ) | ( w1 << 16 ) | w );
934: }
935: else {
936: if ( (the_insn.reloc == HPPA_RELOC_JBSR) &&
937: (the_insn.exp.X_add_symbol->sy_name[0] != 'L') )
938: as_fatal("Stub label used in a JBSR must be "
939: "non-relocatable");
940: the_insn.reloc = HPPA_RELOC_BL17;
941: the_insn.code = 'W';
942: }
943: }
944: else {
945: unsigned long w2,w1,w,result;
946:
947: result = sign_unext( the_insn.exp.X_add_number >> 2,17);
948: dis_assemble_17(result,&w1,&w2,&w);
949: opcode |= ( ( w2 << 2 ) | ( w1 << 16 ) | w );
950: }
951: s = expr_end;
952: continue;
953: case '@': /* 17 bit branch displacement --- JBSR */
954: getExpression(s);
955:
956: /*
957: * assumption here is this will only be used in case of jbsr
958: * in which case the format is
959: * jbsr,n symbol,register,label
960: * and a relocation entry for symbol needs to be created
961: */
962:
963: the_insn.pcrel = 0;
964: the_insn.pcrel_reloc = 1;
965: the_insn.reloc = HPPA_RELOC_JBSR;
966: the_insn.code = '@';
967: s = expr_end;
968: /*
969: * The code to hook a frag in the chain should be here.
970: * Then set a flag saying that the next 'W' should not create a relocation
971: * entry. The way 'jbsr' is expected to work is the label will always be
972: * local!
973: * This flag should be reset in 'W'.
974: */
975: found_jbsr = 1;
976: toP = frag_more(4);
977: fix_new(frag_now,
978: (toP - frag_now->fr_literal),
979: 4,
980: the_insn.exp.X_add_symbol,
981: the_insn.exp.X_subtract_symbol,
982: the_insn.exp.X_add_number,
983: the_insn.pcrel,
984: the_insn.pcrel_reloc,
985: the_insn.reloc);
986:
987: continue;
988: case 'B': /* either "s,b" or "b" where b & s are defined above */
989: reg1 = pa_parse_number(&s);
990: if ( *s == ',' ) {
991: s++;
992: reg2 = pa_parse_number(&s);
993: }
994: else {
995: reg2 = reg1;
996: reg1 = 0;
997: }
998: if ( reg1 < 4 && reg1 >= 0 ) {
999: opcode |= reg1 << 14;
1000: opcode |= reg2 << 21;
1001: continue;
1002: }
1003: break;
1004: case 'p': /* 5 bit shift count at 26 (to support SHD instr.) */
1005: /* value is encoded in instr. as 31-p where p is */
1006: /* the value scanned here */
1007: getExpression(s);
1008: if ( the_insn.exp.X_seg == SEG_ABSOLUTE ) {
1009: opcode |= ( ( (31 - the_insn.exp.X_add_number) & 0x1f ) << 5 );
1010: }
1011: s = expr_end;
1012: continue;
1013: case 'P': /* 5-bit bit position at 26 */
1014: getExpression(s);
1015: if ( the_insn.exp.X_seg == SEG_ABSOLUTE ) {
1016: opcode |= ( the_insn.exp.X_add_number & 0x1f ) << 5;
1017: }
1018: s = expr_end;
1019: continue;
1020: case 'Q': /* 5 bit immediate at 10 */
1021: /* (unsigned bit position value for the bb instruction) */
1022: getExpression(s);
1023: im5 = evaluateAbsolute(the_insn.exp,0);
1024: if ( im5 > 31 ) {
1025: as_bad("Operand out of range. Was: %d. Should be"
1026: "[0..31]. Assuming %d.\n",im5,im5&0x1f);
1027: im5 = im5 & 0x1f;
1028: }
1029: opcode |= im5 << 21;
1030: s = expr_end;
1031: continue;
1032: case 'A': /* 13 bit immediate at 18 (to support BREAK instr.) */
1033: getAbsoluteExpression(s);
1034: if ( the_insn.exp.X_seg == SEG_ABSOLUTE )
1035: opcode |= (the_insn.exp.X_add_number & 0x1fff) << 13;
1036: s = expr_end;
1037: continue;
1038: case 'Z': /* System Control Completer(for LDA, LHA, etc.) */
1039: if ( *s == ',' && ( *(s+1) == 'm' || *(s+1) == 'M' ) ) {
1040: m = 1;
1041: s += 2;
1042: }
1043: else
1044: m = 0;
1045:
1046: opcode |= m << 5;
1047: while ( *s == ' ' || *s == '\t' ) /* skip to next operand */
1048: s++;
1049:
1050: continue;
1051: case 'D': /* 26 bit immediate at 31 (to support DIAG instr.) */
1052: /* the action (and interpretation of this operand is
1053: implementation dependent) */
1054: getExpression(s);
1055: if ( the_insn.exp.X_seg == SEG_ABSOLUTE ) {
1056: opcode |= ( (evaluateAbsolute(the_insn.exp,0) & 0x1ffffff) << 1 );
1057: }
1058: else
1059: as_bad("Illegal DIAG operand");
1060: s = expr_end;
1061: continue;
1062: case 'f': /* 3 bit Special Function Unit (SFU) identifier at 25 */
1063: sfu = pa_parse_number(&s);
1064: if ( (sfu > 7) || (sfu < 0) )
1065: as_bad("Illegal SFU identifier: %02x", sfu);
1066: opcode |= (sfu & 7) << 6;
1067: continue;
1068: case 'O': /* 20 bit SFU op. split between 15 bits at 20 and 5 bits at 31 */
1069: getExpression(s);
1070: s = expr_end;
1071: continue;
1072: case 'o': /* 15 bit Special Function Unit operation at 20 */
1073: getExpression(s);
1074: s = expr_end;
1075: continue;
1076: case '2': /* 22 bit SFU op. split between 17 bits at 20
1077: and 5 bits at 31 */
1078: getExpression(s);
1079: s = expr_end;
1080: continue;
1081: case '1': /* 15 bit SFU op. split between 10 bits at 20
1082: and 5 bits at 31 */
1083: getExpression(s);
1084: s = expr_end;
1085: continue;
1086: case '0': /* 10 bit SFU op. split between 5 bits at 20
1087: and 5 bits at 31 */
1088: getExpression(s);
1089: s = expr_end;
1090: continue;
1091: case 'u': /* 3 bit coprocessor unit identifier at 25 */
1092: getExpression(s);
1093: s = expr_end;
1094: continue;
1095: case 'F': /* Source FP Operand Format Completer (2 bits at 20) */
1096: f = pa_parse_fp_format(&s);
1097: opcode |= (int)f << 11;
1098: the_insn.fpof1 = f;
1099: continue;
1100: case 'G': /* Destination FP Operand Format Completer (2 bits at 18) */
1101: s--; /* need to pass the previous comma to pa_parse_fp_format */
1102: f = pa_parse_fp_format(&s);
1103: opcode |= (int)f << 13;
1104: the_insn.fpof2 = f;
1105: continue;
1106: case 'M': /* FP Compare Conditions (encoded as 5 bits at 31) */
1107: cond = pa_parse_fp_cmp_cond(&s);
1108: opcode |= cond;
1109: continue;
1110:
1111: case 'v': /* a 't' type extended to handle L/R register halves. */
1112: {
1113: struct pa_89_fp_reg_struct result;
1114:
1115: pa_89_parse_number(&s,&result);
1116: if ( result.number_part < 32 && result.number_part >= 0 ) {
1117: opcode |= (result.number_part & 0x1f);
1118:
1119: /* 0x30 opcodes are FP arithmetic operation opcodes */
1120: /* load/store FP opcodes do not get converted to 0x38 */
1121: /* opcodes like the 0x30 opcodes do */
1122: if ( need_89_opcode(&the_insn,&result) ) {
1123: if ( (opcode & 0xfc000000) == 0x30000000 ) {
1124: opcode |= (result.L_R_select & 1) << 6;
1125: opcode |= 1 << 27;
1126: }
1127: else {
1128: opcode |= (result.L_R_select & 1) << 6;
1129: }
1130: }
1131: continue;
1132: }
1133: }
1134: break;
1135: case 'E': /* a 'b' type extended to handle L/R register halves. */
1136: {
1137: struct pa_89_fp_reg_struct result;
1138:
1139: pa_89_parse_number(&s,&result);
1140: if ( result.number_part < 32 && result.number_part >= 0 ) {
1141: opcode |= (result.number_part & 0x1f) << 21;
1142: if ( need_89_opcode(&the_insn,&result) ) {
1143: opcode |= (result.L_R_select & 1) << 7;
1144: opcode |= 1 << 27;
1145: }
1146: continue;
1147: }
1148: }
1149: break;
1150:
1151: case 'X': /* an 'x' type extended to handle L/R register halves. */
1152: {
1153: struct pa_89_fp_reg_struct result;
1154:
1155:
1156: pa_89_parse_number(&s,&result);
1157: if ( result.number_part < 32 && result.number_part >= 0 ) {
1158: opcode |= (result.number_part & 0x1f) << 16;
1159: if ( need_89_opcode(&the_insn,&result) ) {
1160: opcode |= (result.L_R_select & 1) << 12;
1161: opcode |= 1 << 27;
1162: }
1163: continue;
1164: }
1165: }
1166: break;
1167:
1168: case '4': /* 5 bit register field at 10
1169: (used in 'fmpyadd' and 'fmpysub') */
1170: {
1171: struct pa_89_fp_reg_struct result;
1172: int status;
1173:
1174: status = pa_89_parse_number(&s,&result);
1175: if ( result.number_part < 32 && result.number_part >= 0 ) {
1176: if ( the_insn.fpof1 == SGL ) {
1177: result.number_part &= 0xF;
1178: result.number_part |= (result.L_R_select & 1) << 4;
1179: }
1180: opcode |= result.number_part << 21;
1181: continue;
1182: }
1183: }
1184: break;
1185:
1186: case '6': /* 5 bit register field at 15
1187: (used in 'fmpyadd' and 'fmpysub') */
1188: {
1189: struct pa_89_fp_reg_struct result;
1190: int status;
1191:
1192: status = pa_89_parse_number(&s,&result);
1193: if ( result.number_part < 32 && result.number_part >= 0 ) {
1194: if ( the_insn.fpof1 == SGL ) {
1195: result.number_part &= 0xF;
1196: result.number_part |= (result.L_R_select & 1) << 4;
1197: }
1198: opcode |= result.number_part << 16;
1199: continue;
1200: }
1201: }
1202: break;
1203:
1204: case '7': /* 5 bit register field at 31
1205: (used in 'fmpyadd' and 'fmpysub') */
1206: {
1207: struct pa_89_fp_reg_struct result;
1208: int status;
1209:
1210: status = pa_89_parse_number(&s,&result);
1211: if ( result.number_part < 32 && result.number_part >= 0 ) {
1212: if ( the_insn.fpof1 == SGL ) {
1213: result.number_part &= 0xF;
1214: result.number_part |= (result.L_R_select & 1) << 4;
1215: }
1216: opcode |= result.number_part;
1217: continue;
1218: }
1219: }
1220: break;
1221:
1222: case '8': /* 5 bit register field at 20
1223: (used in 'fmpyadd' and 'fmpysub') */
1224: {
1225: struct pa_89_fp_reg_struct result;
1226: int status;
1227:
1228: status = pa_89_parse_number(&s,&result);
1229: if ( result.number_part < 32 && result.number_part >= 0 ) {
1230: if ( the_insn.fpof1 == SGL ) {
1231: result.number_part &= 0xF;
1232: result.number_part |= (result.L_R_select & 1) << 4;
1233: }
1234: opcode |= result.number_part << 11;
1235: continue;
1236: }
1237: }
1238: break;
1239:
1240: case '9': /* 5 bit register field at 25
1241: (used in 'fmpyadd' and 'fmpysub') */
1242: {
1243: struct pa_89_fp_reg_struct result;
1244: int status;
1245:
1246: status = pa_89_parse_number(&s,&result);
1247: if ( result.number_part < 32 && result.number_part >= 0 ) {
1248: if ( the_insn.fpof1 == SGL ) {
1249: result.number_part &= 0xF;
1250: result.number_part |= (result.L_R_select & 1) << 4;
1251: }
1252: opcode |= result.number_part << 6;
1253: continue;
1254: }
1255: }
1256: break;
1257:
1258: case 'H': /* Floating Point Operand Format at 26 for */
1259: /* 'fmpyadd' and 'fmpysub' (very similar to 'F') */
1260: /* bits are switched from other FP Operand */
1261: /* formats. 1=SGL, 1=<none>, 0=DBL */
1262: f = pa_parse_fp_format(&s);
1263: switch (f) {
1264: case SGL:
1265: opcode |= 0x20;
1266: case DBL:
1267: the_insn.fpof1 = f;
1268: continue;
1269:
1270: case QUAD:
1271: case ILLEGAL_FMT:
1272: default:
1273: as_bad("Illegal Floating Point Operand Format for"
1274: "this instruction: '%s'",s);
1275: }
1276: break;
1277:
1278: case 'y' : /* nullify at 26 */
1279: nullif = pa_parse_nullif(&s);
1280: opcode |= nullif << 5;
1281: continue;
1282:
1283: /* bug #41317 .... [email protected] Mon May 2 17:53:29 PDT 1994
1284:
1285: These are for 'cache control hints'
1286:
1287: l Store Instruction Cache Control Hint (Table 5-8) with
1288: Short displacement load and store completers (Table 5-11)
1289:
1290: L Load and Clear Word Cache Control Hint (Table 5-9) with
1291: Indexed load completers (Table 5-10)
1292:
1293: 3 Store Instruction Cache Control Hint (Table 5-8) with
1294: Indexed load completers (Table 5-10)
1295:
1296: a Load and Clear Word Cache Control Hint (Table 5-9) with
1297: Short displacement load and store completers (Table 5-11)
1298:
1299: These parse ",cc" and encode "cc" in 2 bits at 20,
1300: where "cc" encoding is as given in Tables 5-8, 5-9.
1301: Refer to 'PA-RISC 1.1 Architecture and Instruction Set Reference
1302: Manual, Second Edition' for the tables.
1303: */
1304:
1305: case 'l' : /* Store Instruction Cache Control Hint */
1306: /* Short displacement load and store completers */
1307: opcode |= parse_completer_with_cache_control_hint(&s, 0, 'C');
1308: continue;
1309:
1310: case 'L' : /* Load and Clear Word Cache Control Hint */
1311: /* Indexed load completers */
1312: opcode |= parse_completer_with_cache_control_hint(&s, 1, 'c');
1313: continue;
1314:
1315: case '3' : /* Store Instruction Cache Control Hint */
1316: /* Indexed load completers */
1317: opcode |= parse_completer_with_cache_control_hint(&s, 0, 'c');
1318: continue;
1319:
1320: case 'a' : /* Load and Clear Word Cache Control Hint */
1321: /* Short displacement load and store completers */
1322: opcode |= parse_completer_with_cache_control_hint(&s, 1, 'C');
1323: continue;
1324:
1325: default:
1326: abort();
1327: }
1328: break;
1329: }
1330:
1331: if (match == FALSE)
1332: {
1333: /* Args don't match. */
1334: if (&insn[1] - pa_opcodes < NUMOPCODES
1335: && !strcmp(insn->name, insn[1].name))
1336: {
1337: ++insn;
1338: s = argsStart;
1339: continue;
1340: }
1341: else
1342: {
1343: as_bad("Illegal operands");
1344: return;
1345: }
1346: }
1347: break;
1348: }
1349:
1350: the_insn.opcode = opcode;
1351: return;
1352: } /* end pa_ip() */
1353:
1354: /*
1355: This is identical to the md_atof in m68k.c. I think this is right,
1356: but I'm not sure.
1357:
1358: Turn a string in input_line_pointer into a floating point constant of type
1359: type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1360: emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1361: */
1362:
1363: /* Equal to MAX_PRECISION in atof-ieee.c */
1364: #define MAX_LITTLENUMS 6
1365:
1366: char *
1367: md_atof(
1368: int type,
1369: char *litP,
1370: int *sizeP)
1371: {
1372: int prec;
1373: LITTLENUM_TYPE words[MAX_LITTLENUMS];
1374: LITTLENUM_TYPE *wordP;
1375: char *t;
1376: char *atof_ieee();
1377:
1378: switch(type) {
1379:
1380: case 'f':
1381: case 'F':
1382: case 's':
1383: case 'S':
1384: prec = 2;
1385: break;
1386:
1387: case 'd':
1388: case 'D':
1389: case 'r':
1390: case 'R':
1391: prec = 4;
1392: break;
1393:
1394: case 'x':
1395: case 'X':
1396: prec = 6;
1397: break;
1398:
1399: case 'p':
1400: case 'P':
1401: prec = 6;
1402: break;
1403:
1404: default:
1405: *sizeP=0;
1406: return "Bad call to MD_ATOF()";
1407: }
1408: t=atof_ieee(input_line_pointer,type,words);
1409: if(t)
1410: input_line_pointer=t;
1411: *sizeP=prec * sizeof(LITTLENUM_TYPE);
1412: for(wordP=words;prec--;) {
1413: md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
1414: litP+=sizeof(LITTLENUM_TYPE);
1415: }
1416: return ""; /* Someone should teach Dean about null pointers */
1417: }
1418:
1419: /*
1420: * Write out big-endian.
1421: */
1422: void
1423: md_number_to_chars(
1424: char *buf,
1425: long val,
1426: int n)
1427: {
1428:
1429: switch(n) {
1430:
1431: case 4:
1432: *buf++ = val >> 24;
1433: *buf++ = val >> 16;
1434: case 2:
1435: *buf++ = val >> 8;
1436: case 1:
1437: *buf = val;
1438: break;
1439:
1440: default:
1441: abort();
1442: }
1443: return;
1444: }
1445:
1446: void
1447: md_number_to_imm(
1448: unsigned char *buf,
1449: long val,
1450: int n,
1451: fixS *fixP,
1452: int nsect)
1453: {
1454: unsigned long w1,w2,w;
1455: unsigned new_val = 0;
1456: unsigned long left21, right14;
1457:
1458: if(fixP->fx_r_type == NO_RELOC ||
1459: fixP->fx_r_type == HPPA_RELOC_VANILLA){
1460: switch(n){
1461: case 4:
1462: *buf++ = val >> 24;
1463: *buf++ = val >> 16;
1464: case 2:
1465: *buf++ = val >> 8;
1466: case 1:
1467: *buf = val;
1468: break;
1469:
1470: default:
1471: abort();
1472: }
1473: return;
1474: }
1475:
1476:
1477: calc_hppa_HILO(val - fixP->fx_offset, fixP->fx_offset,
1478: &left21, &right14);
1479:
1480: switch (fixP->fx_r_type) {
1481: default:
1482: break;
1483: /* case 'j': */
1484: case HPPA_RELOC_LO14 :
1485: w = low_sign_unext(right14, 14);
1486: goto fixit;
1487:
1488: /* case 'k': */
1489: case HPPA_RELOC_HI21 :
1490: w = dis_assemble_21((left21>>11));
1491: fixit:
1492: /* There is no guarantee that buf is word-aligned, */
1493: /* so the adjustment must be done the hard way. */
1494:
1495: new_val = (*buf & 0xff) << 24;
1496: new_val |= (*(buf+1) & 0xff) << 16;
1497: new_val |= (*(buf+2) & 0xff) << 8;
1498: new_val |= (*(buf+3) & 0xff);
1499: new_val |= w; /* Now, make the adjustment */
1500: md_number_to_chars(buf,new_val,4);
1501: break;
1502:
1503: /* case 'W': */
1504: case HPPA_RELOC_BL17 :
1505: if ( !fixP->fx_addsy ) {
1506: val -= 4; /* PA adjustment: a 0 disp is actually 4 bytes */
1507: /* further because of the delay slot */
1508: val >>= 2;
1509: dis_assemble_17(val,&w1,&w2,&w);
1510: /* There is no guarantee that buf is word-aligned, */
1511: /* so the adjustment must be done the hard way. */
1512:
1513: new_val = (*buf & 0xff) << 24;
1514: new_val |= (*(buf+1) & 0xff) << 16;
1515: new_val |= (*(buf+2) & 0xff) << 8;
1516: new_val |= (*(buf+3) & 0xff);
1517: new_val |= ( ( w2 << 2 ) | ( w1 << 16 ) | w );
1518: /* Now, do the adjustment */
1519: md_number_to_chars(buf,new_val,4);
1520: }
1521: else {
1522: unsigned long result;
1523: val -= 4; /* PA adjustment: a 0 disp is actually 4 bytes */
1524: /* further because of the delay slot */
1525: val >>= 2;
1526:
1527: result = sign_unext( val,17);
1528: dis_assemble_17(result,&w1,&w2,&w);
1529: /* There is no guarantee that buf is word-aligned, */
1530: /* so the adjustment must be done the hard way. */
1531:
1532: new_val = (*buf & 0xff) << 24;
1533: new_val |= (*(buf+1) & 0xff) << 16;
1534: new_val |= (*(buf+2) & 0xff) << 8;
1535: new_val |= (*(buf+3) & 0xff);
1536: new_val |= ( ( w2 << 2 ) | ( w1 << 16 ) | w );
1537: /* Now, do the adjustment */
1538: md_number_to_chars(buf,new_val,4);
1539:
1540: }
1541: break;
1542: /* case 'z': */
1543: case HPPA_RELOC_BR17 :
1544: {
1545: unsigned long result;
1546: right14 >>= 2;
1547: result = sign_unext(right14,17);
1548: dis_assemble_17(result,&w1,&w2,&w);
1549: /* There is no guarantee that buf is word-aligned, */
1550: /* so the adjustment must be done the hard way. */
1551:
1552: new_val = (*buf & 0xff) << 24;
1553: new_val |= (*(buf+1) & 0xff) << 16;
1554: new_val |= (*(buf+2) & 0xff) << 8;
1555: new_val |= (*(buf+3) & 0xff);
1556: new_val |= ( ( w2 << 2 ) | ( w1 << 16 ) | w );
1557: /* Now, do the adjustment */
1558: md_number_to_chars(buf,new_val,4);
1559: }
1560: break;
1561: /* case '@': */
1562: case HPPA_RELOC_JBSR :
1563: /*
1564: * In case of the jbsr relocation no bytes are to be written to the
1565: * output.
1566: *
1567: * SO DO NOTHING!
1568: */
1569: break;
1570:
1571: /* case 'w': */
1572: /* To take care of 12 bit label */
1573: case HPPA_RELOC_12BRANCH :
1574: if ( !fixP->fx_addsy ) {
1575: val -= 4; /* PA adjustment: a 0 disp is actually 4 bytes */
1576: /* further because of the delay slot */
1577: val >>= 2;
1578: dis_assemble_12(val,&w1,&w);
1579: /* There is no guarantee that buf is word-aligned, */
1580: /* so the adjustment must be done the hard way. */
1581:
1582: new_val = (*buf & 0xff) << 24;
1583: new_val |= (*(buf+1) & 0xff) << 16;
1584: new_val |= (*(buf+2) & 0xff) << 8;
1585: new_val |= (*(buf+3) & 0xff);
1586: new_val |= ( ( w1 << 2 ) | w ); /* Now, do the adjustment */
1587: md_number_to_chars(buf,new_val,4);
1588: }
1589: else {
1590: as_bad("Undefined symbol %s", fixP->fx_addsy->sy_name);
1591: }
1592:
1593: break;
1594: }
1595: }
1596:
1597: void
1598: md_convert_frag(
1599: fragS *fragP)
1600: {
1601: unsigned int address;
1602:
1603: if ( fragP -> fr_type == rs_machine_dependent ) {
1604: switch ( (int) fragP -> fr_subtype ) {
1605: case 0:
1606: fragP -> fr_type = rs_fill;
1607: know( fragP -> fr_var == 1 );
1608: know( fragP -> fr_next );
1609: address = fragP -> fr_address + fragP -> fr_fix;
1610: if ( address % fragP -> fr_offset ) {
1611: fragP -> fr_offset =
1612: fragP -> fr_next -> fr_address
1613: - fragP -> fr_address
1614: - fragP -> fr_fix;
1615: }
1616: else
1617: fragP -> fr_offset = 0;
1618: break;
1619: }
1620: }
1621: }
1622:
1623: int
1624: md_estimate_size_before_relax(
1625: fragS *fragP,
1626: int nsect)
1627: {
1628: int size;
1629:
1630: size = 0;
1631:
1632: while ( (fragP->fr_fix + size) % fragP->fr_offset )
1633: size++;
1634:
1635: return size;
1636: }
1637:
1638: int
1639: md_parse_option(
1640: char **argP,
1641: int *cntP,
1642: char ***vecP)
1643: {
1644: return 1;
1645: }
1646:
1647: /*
1648: int is_end_of_statement()
1649: {
1650: return ( (*input_line_pointer == '\n')
1651: || (*input_line_pointer == ';')
1652: || (*input_line_pointer == '!') );
1653: }
1654: */
1655:
1656: static
1657: int
1658: parse_L_or_R(
1659: char *str)
1660: {
1661: /* not much work done as yet! */
1662: switch (*str) {
1663: case '%':
1664: case '(':
1665: return 0; /* ie. not found */
1666: break;
1667: case 'L':
1668: case 'l':
1669: if (*(str+1) == '\'' || *(str+1) == '`') /* check next character */
1670: return 1; /* found */
1671: else
1672: return 0; /* not found */
1673: break;
1674: case 'R':
1675: case 'r':
1676: if (*(str+1) == '\'' || *(str+1) == '`') /* check next character */
1677: return 2; /* found */
1678: else
1679: return 0; /* not found */
1680: break;
1681: default: /* default is not found ... at least for the time being */
1682: return 0;
1683: break;
1684: }
1685: } /* end parse_L_or_R() */
1686:
1687: static
1688: unsigned long
1689: parse_cache_control_hint(
1690: char **s, /* Note : the function changes '*s' */
1691: int option) /* option = 0 for store instruction */
1692: /* option = 1 for load and clear instruction */
1693: {
1694: unsigned long cc = NO_CACHE_CONTROL_HINT;
1695:
1696: if (**s == ',') {
1697: (*s)++;
1698: switch (option) {
1699: case 0 : /* Store Instruction Cache Control Hint */
1700: if ( strncasecmp(*s,"bc",2) == 0 ) {
1701: /* BLOCK_COPY */
1702: (*s) += 2;
1703: cc = BC_OR_CO_CACHE_CONTROL_HINT;
1704: /* eat up extra blanks and tabs */
1705: while ( **s == ' ' || **s == '\t' )
1706: (*s)++;
1707: } else
1708: as_fatal("Illegal Cache Control Hint: '%s'"
1709: " - expected 'bc'",*s);
1710: break;
1711:
1712: case 1 : /* Load and Clear Word Cache Control Hint */
1713: if ( strncasecmp(*s,"co",2) == 0 ) {
1714: /* COHERENT_OPERATION */
1715: (*s) +=2;
1716: cc = BC_OR_CO_CACHE_CONTROL_HINT;
1717: /* eat up extra blanks and tabs */
1718: while ( **s == ' ' || **s == '\t' )
1719: (*s)++;
1720: } else
1721: as_fatal("Illegal Cache Control Hint: '%s'"
1722: " - expected 'co'",*s);
1723: break;
1724:
1725: default :
1726: as_fatal("Invalid option (%d) for parsing cache control hints",
1727: option);
1728: break;
1729: }
1730: }
1731: /* else NO_HINT */
1732:
1733: /*
1734: * the completers have already eaten up extra blanks
1735: * and tabs. So there is no need to do that again here.
1736: */
1737:
1738: return cc;
1739:
1740: } /* end parse_cache_control_hint() */
1741:
1742: static
1743: unsigned long
1744: parse_completer_with_cache_control_hint(
1745: char **s, /* Note : the function changes '*s' */
1746: int option, /* option = 0 for store instruction */
1747: /* option = 1 for load and clear instruction */
1748: char completer) /* 'c' or 'C' */
1749: {
1750: unsigned long i, result = (unsigned long) 0UL;
1751: int m, a, u;
1752:
1753: switch (completer) {
1754: case 'c': /* indexed load completer. */
1755: i = m = u = 0;
1756: while ( **s == ',' && i < 3 ) {
1757: (*s)++;
1758: if ( strncasecmp((*s),"sm",2) == 0 ) {
1759: m = u = 1;
1760: (*s)++;
1761: i++;
1762: }
1763: else if ( strncasecmp((*s),"m",1) == 0 )
1764: m = 1;
1765: else if ( strncasecmp((*s),"s",1) == 0 )
1766: u = 1;
1767: else if ( strncmp((*s),",",1) == 0 ) /* no completer */
1768: result |= parse_cache_control_hint(s, option);
1769: else if ( (strncasecmp((*s),"c",1) == 0) ||
1770: (strncasecmp((*s),"b",1) == 0) ) {/* just 1 completer */
1771: (*s)--;
1772: result |= parse_cache_control_hint(s, option);
1773: }
1774: else
1775: as_bad("Unrecognized Indexed Load"
1776: "Completer with cache control hints...assuming 0");
1777: if (result == (unsigned long)0UL)
1778: (*s)++;
1779: i++;
1780: }
1781: if ( i > 3 )
1782: as_bad("Illegal Indexed Load Completer with cache control hints"
1783: " Syntax... extras ignored");
1784: while ( **s == ' ' || **s == '\t' )
1785: (*s)++;
1786:
1787: result |= m << 5;
1788: result |= u << 13;
1789: break;
1790: case 'C': /* short load and store completer */
1791: i = m = a = 0;
1792: while ( **s == ',' && i < 2 ) {
1793: (*s)++;
1794: if ( strncasecmp((*s),"ma",2) == 0 ) {
1795: a = 0;
1796: m = 1;
1797: }
1798: else if ( strncasecmp((*s),"mb",2) == 0 ) {
1799: m = a = 1;
1800: }
1801: else if ( strncmp((*s),",",1) == 0 ) /* no completer */
1802: result |= parse_cache_control_hint(s, option);
1803: else if ( (strncasecmp((*s),"c",1) == 0) ||
1804: (strncasecmp((*s),"b",1) == 0) ) {/* just 1 completer */
1805: (*s)--;
1806: result |= parse_cache_control_hint(s, option);
1807: }
1808: else
1809: as_bad("Unrecognized Indexed Load Completer"
1810: "...assuming 0");
1811: i++;
1812: (*s) += 2;
1813: }
1814: while ( **s == ' ' || **s == '\t' )
1815: (*s)++;
1816: result |= m << 5;
1817: result |= a << 13;
1818: break;
1819:
1820:
1821: default :
1822: as_fatal("Invalid completer (%c) for parsing cache control hints",
1823: completer);
1824: break;
1825: }
1826: return result;
1827: } /* end parse_completer_with_cache_control_hint() */
1828:
1829: /* end hppa.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.