|
|
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.