home *** CD-ROM | disk | FTP | other *** search
- #include <ctype.h>
- #include <string.h>
- #include <mach-o/m98k/reloc.h>
- #include "m98k-opcode.h"
- #include "as.h"
- #include "flonum.h"
- #include "expr.h"
- #include "hash.h"
- #include "read.h"
- #include "md.h"
- #include "obstack.h"
- #include "symbols.h"
- #include "messages.h"
- #include "atof-ieee.h"
- #include "input-scrub.h"
- #include "sections.h"
-
-
- /*
- * These are the default cputype and cpusubtype for the m98k architecture.
- */
- const cpu_type_t md_cputype = CPU_TYPE_MC98000;
- cpu_subtype_t md_cpusubtype = CPU_SUBTYPE_MC98000_ALL;
-
- /* This is the byte sex for the m98k architecture */
- const enum byte_sex md_target_byte_sex = BIG_ENDIAN_BYTE_SEX;
-
- /* These characters start a comment anywhere on the line */
- const char md_comment_chars[] = ";";
-
- /* These characters only start a comment at the beginning of a line */
- const char md_line_comment_chars[] = "#";
-
- /*
- * These characters can be used to separate mantissa decimal digits from
- * exponent decimal digits in floating point numbers.
- */
- const char md_EXP_CHARS[] = "eE";
-
- /*
- * The characters after a leading 0 that means this number is a floating point
- * constant as in 0f123.456 or 0d1.234E-12 (see md_EXP_CHARS above).
- */
- const char md_FLT_CHARS[] = "dDfF";
-
- /*
- * This is the machine dependent pseudo opcode table for this target machine.
- */
- static void s_reg(
- int reg);
- const pseudo_typeS md_pseudo_table[] =
- {
- {"greg", s_reg, 'r' },
- {0} /* end of table marker */
- };
-
- #define RT(x) (((x) >> 21) & 0x1f)
- #define RA(x) (((x) >> 16) & 0x1f)
-
- struct m98k_insn {
- unsigned long opcode;
- expressionS exp;
- enum reloc_type_m98k reloc;
- long pcrel;
- long pcrel_reloc;
- };
-
- /*
- * The pointer to the opcode hash table built by md_begin() and used by
- * md_assemble() to look up opcodes.
- */
- static struct hash_control *op_hash = NULL;
-
- /*
- * These aid in the printing of better error messages for parameter syntax
- * errors when there is only one mnemonic in the tables.
- */
- static unsigned long error_param_count = 0;
- static char *error_param_message = NULL;
-
- /*
- * These are name names of the known special registers and the numbers assigned
- * to them.
- */
- struct special_register {
- unsigned long number;
- char *name;
- };
- static const struct special_register special_registers[] = {
- { 0, "mq" }, /* 601 only */
- { 1, "xer" },
- { 4, "rtcu" },
- { 5, "rtcl" },
- { 8, "lr" },
- { 9, "ctr" },
- { 18, "dsisr" },
- { 19, "dar" },
- { 22, "dec" },
- { 25, "sdr1" },
- { 26, "srr0" },
- { 27, "srr1" },
- { 272, "sprg0" },
- { 273, "sprg1" },
- { 274, "sprg2" },
- { 275, "sprg3" },
- { 280, "asr" },
- { 281, "rtcd" },
- { 282, "rtci" },
- { 287, "pvr" },
- { 528, "ibat0u" },
- { 529, "ibat0l" },
- { 530, "ibat1u" },
- { 531, "ibat1l" },
- { 532, "ibat2u" },
- { 533, "ibat2l" },
- { 534, "ibat3u" },
- { 535, "ibat3l" },
- { 528, "bat0u" }, /* 601 only */
- { 529, "bat0l" }, /* 601 only */
- { 530, "bat1u" }, /* 601 only */
- { 531, "bat1l" }, /* 601 only */
- { 532, "bat2u" }, /* 601 only */
- { 533, "bat2l" }, /* 601 only */
- { 534, "bat3u" }, /* 601 only */
- { 535, "bat3l" }, /* 601 only */
- { 536, "dbat0u" },
- { 537, "dbat0l" },
- { 538, "dbat1u" },
- { 539, "dbat1l" },
- { 540, "dbat2u" },
- { 541, "dbat2l" },
- { 542, "dbat3u" },
- { 543, "dbat3l" },
- { 1008,"hid0" }, /* 601 only */
- { 1009,"hid1" }, /* 601 only */
- { 1010,"hid2" }, /* 601 only */
- { 1013,"hid5" }, /* 601 only */
- { 1013,"dabr" }, /* 601 only */
- { 1022,"fpecr" },
- { 1023,"pid" }, /* 601 only */
- { 0, "" } /* end of table marker */
- };
-
- /*
- * These are name names of the condition field special registers and the
- * numbers assigned to them.
- */
- struct condition_symbol {
- unsigned long value;
- char *name;
- };
- static const struct condition_symbol condition_symbols[] = {
- { 0, "lt" }, /* less than */
- { 1, "gt" }, /* greater than */
- { 2, "eq" }, /* equal */
- { 3, "so" }, /* summary overflow */
- { 3, "un" }, /* unordered */
- { 0, "" } /* end of table marker */
- };
-
- struct CR_field {
- unsigned long value;
- char *name;
- };
- static const struct CR_field CR_fields[] = {
- { 0, "cr0" }, /* CR field 0 */
- { 4, "cr1" }, /* CR field 1 */
- { 8, "cr2" }, /* CR field 2 */
- { 12, "cr3" }, /* CR field 3 */
- { 16, "cr4" }, /* CR field 4 */
- { 20, "cr5" }, /* CR field 5 */
- { 24, "cr6" }, /* CR field 6 */
- { 28, "cr7" }, /* CR field 7 */
- { 0, "" } /* end of table marker */
- };
-
- /*
- * These are built in macros because they are trivial to implement as macros
- * which otherwise be less obvious to do special entries for them.
- */
- struct macros {
- char *name;
- char *body;
- };
- static const struct macros m98k_macros[] = {
- { "extldi\n", "rldicr $0,$1,$3,$2-1\n" },
- { "extldi.\n", "rldicr. $0,$1,$3,$2-1\n" },
- { "extrdi\n", "rldicl $0,$1,$2+$3,64-$2\n" },
- { "extrdi.\n", "rldicl. $0,$1,$2+$3,64-$2\n" },
- { "insrdi\n", "rldimi $0,$1,64-($3+$2),$3\n" },
- { "insrdi.\n", "rldimi. $0,$1,64-($3+$2),$3\n" },
- { "rotldi\n", "rldicl $0,$1,$2,0\n" },
- { "rotldi.\n", "rldicl. $0,$1,$2,0\n" },
- { "rotrdi\n", "rldicl $0,$1,64-$2,0\n" },
- { "rotrdi.\n", "rldicl. $0,$1,64-$2,0\n" },
- { "rotld\n", "rldcl $0,$1,$2,0\n" },
- { "rotld.\n", "rldcl. $0,$1,$2,0\n" },
- { "sldi\n", "rldicr $0,$1,$2,63-$2\n" },
- { "sldi.\n", "rldicr. $0,$1,$2,63-$2\n" },
- { "srdi\n", "rldicl $0,$1,64-$2,$2\n" },
- { "srdi.\n", "rldicl. $0,$1,64-$2,$2\n" },
- { "clrldi\n", "rldicl $0,$1,0,$2\n" },
- { "clrldi.\n", "rldicl. $0,$1,0,$2\n" },
- { "clrrdi\n", "rldicl $0,$1,0,63-$2\n" },
- { "clrrdi.\n", "rldicl. $0,$1,0,63-$2\n" },
- { "clrlsldi\n","rldic $0,$1,$3,$2-$3\n" },
- { "clrlsldi.\n","rldic. $0,$1,$3,$2-$3\n" },
-
- { "extlwi\n", "rlwinm $0,$1,$3,0,$2-1\n" },
- { "extlwi.\n", "rlwinm. $0,$1,$3,0,$2-1\n" },
- { "extrwi\n", "rlwinm $0,$1,$2+$3,32-$2,31\n" },
- { "extrwi.\n", "rlwinm. $0,$1,$2+$3,32-$2,31\n" },
- { "inslwi\n", "rlwimi $0,$1,32-$3,$3,($3+$2)-1\n" },
- { "inslwi.\n", "rlwimi. $0,$1,32-$3,$3,($3+$2)-1\n" },
- { "insrwi\n", "rlwimi $0,$1,32-($3+$2),$3,($3+$2)-1\n" },
- { "insrwi.\n", "rlwimi. $0,$1,32-($3+$2),$3,($3+$2)-1\n" },
- { "rotlwi\n", "rlwinm $0,$1,$2,0,31\n" },
- { "rotlwi.\n", "rlwinm. $0,$1,$2,0,31\n" },
- { "rotrwi\n", "rlwinm $0,$1,32-$2,0,31\n" },
- { "rotrwi.\n", "rlwinm. $0,$1,32-$2,0,31\n" },
- { "rotlw\n", "rlwnm $0,$1,$2,0,31\n" },
- { "rotlw.\n", "rlwnm. $0,$1,$2,0,31\n" },
- { "slwi\n", "rlwinm $0,$1,$2,0,31-$2\n" },
- { "slwi.\n", "rlwinm. $0,$1,$2,0,31-$2\n" },
- { "srwi\n", "rlwinm $0,$1,32-$2,$2,31\n" },
- { "srwi.\n", "rlwinm. $0,$1,32-$2,$2,31\n" },
- { "clrlwi\n", "rlwinm $0,$1,0,$2,31\n" },
- { "clrlwi.\n", "rlwinm. $0,$1,0,$2,31\n" },
- { "clrrwi\n", "rlwinm $0,$1,0,0,31-$2\n" },
- { "clrrwi.\n", "rlwinm. $0,$1,0,0,31-$2\n" },
- { "clrlslwi\n","rlwinm $0,$1,$3,$2-$3,31-$2\n" },
- { "clrlslwi.\n","rlwinm. $0,$1,$3,$2-$3,31-$2\n" },
-
- { "mtxer\n", "mtspr 1,$0\n"},
- { "mfxer\n", "mfspr $0,1\n"},
- { "mtlr\n", "mtspr 8,$0\n"},
- { "mflr\n", "mfspr $0,8\n"},
- { "mtctr\n", "mtspr 9,$0\n"},
- { "mfctr\n", "mfspr $0,9\n"},
- { "mtdsisr\n", "mtspr 18,$0\n"},
- { "mfdsisr\n", "mfspr $0,18\n"},
- { "mtdar\n", "mtspr 19,$0\n"},
- { "mfdar\n", "mfspr $0,19\n"},
- { "mtdec\n", "mtspr 22,$0\n"},
- { "mfdec\n", "mfspr $0,22\n"},
- { "mtsdr1\n", "mtspr 25,$0\n"},
- { "mfsdr1\n", "mfspr $0,25\n"},
- { "mtsrr0\n", "mtspr 26,$0\n"},
- { "mfsrr0\n", "mfspr $0,26\n"},
- { "mtsrr1\n", "mtspr 27,$0\n"},
- { "mfsrr1\n", "mfspr $0,27\n"},
- { "mtsprg\n", "mtspr 272+$0,$1\n"},
- { "mfsprg\n", "mfspr $0,272+$1\n"},
- { "mtasr\n", "mtspr 280,$0\n"},
- { "mfasr\n", "mfspr $0,280\n"},
- { "mtrtcd\n", "mtspr 281,$0\n"},
- { "mfrtcd\n", "mfspr $0,281\n"},
- { "mtrtci\n", "mtspr 282,$0\n"},
- { "mfrtci\n", "mfspr $0,282\n"},
- { "mfpvr\n", "mfspr $0,287\n"},
- { "mtibatu\n", "mtspr 528+2*$0,$1\n"},
- { "mfibatu\n", "mfspr $0,528+2*$1\n"},
- { "mtibatl\n", "mtspr 529+2*$0,$1\n"},
- { "mfibatl\n", "mfspr $0,529+2*$1\n"},
- { "mtdbatu\n", "mtspr 536+2*$0,$1\n"},
- { "mfdbatu\n", "mfspr $0,536+2*$1\n"},
- { "mtdbatl\n", "mtspr 537+2*$0,$1\n"},
- { "mfdbatl\n", "mfspr $0,537+2*$1\n"},
-
- { "mtbatu\n", "mtspr 528+2*$0,$1\n"},
- { "mfbatu\n", "mfspr $0,528+2*$1\n"},
- { "mtbatl\n", "mtspr 529+2*$0,$1\n"},
- { "mfbatl\n", "mfspr $0,529+2*$1\n"},
-
- { "subi\n", "addi $0,$1,-($2)\n"},
- { "subis\n", "addis $0,$1,-($2)\n"},
- { "subic\n", "addic $0,$1,-($2)\n"},
- { "subic.\n", "addic. $0,$1,-($2)\n"},
-
- { "", "" } /* end of table marker */
- };
-
- static int calcop(
- struct m98k_opcode *format,
- char *param,
- struct m98k_insn *insn,
- char *op,
- char prediction);
- static char *parse_branch(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- int parcnt);
- static char *parse_displacement(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- int parcnt);
- static char *parse_immediate(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- int parcnt);
- static char *parse_reg(
- char *reg_name,
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt);
- static char *parse_spreg(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt);
- static char *parse_bcnd(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt);
- static char *parse_crf(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt);
- static char *parse_num(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt,
- long max_width_zero);
- static char *parse_sh(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt);
- static char *parse_mb(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt);
-
- /*
- * md_begin() is called from main() in as.c before assembly begins. It is used
- * to allow target machine dependent initialization.
- */
- void
- md_begin(void)
- {
- unsigned long i;
- char *name, *retval;
-
- /* initialize the opcode hash table */
- op_hash = hash_new();
- if(op_hash == NULL)
- as_fatal("Could not initialize the opcode hash table");
-
- /* loop until you see the end of the list */
- i = 0;
- while(*m98k_opcodes[i].name){
- name = m98k_opcodes[i].name;
-
- /* hash each mnemonic and record its position */
- retval = hash_insert(op_hash, name, (char *)&m98k_opcodes[i]);
- if(retval != NULL && *retval != '\0')
- as_fatal("Can't hash instruction '%s':%s",
- m98k_opcodes[i].name, retval);
-
- /* skip to next unique mnemonic or end of list */
- for(i++; strcmp(m98k_opcodes[i].name, name) == 0; i++)
- ;
- }
-
- /*
- * Load the builtin macros for extended mnemonics for rotate and
- * shift mnemonics.
- */
- for(i = 0; *m98k_macros[i].name != '\0'; i++){
- input_line_pointer = m98k_macros[i].name;
- s_macro(0);
- add_to_macro_definition(m98k_macros[i].body);
- s_endmacro(0);
- }
- }
-
- /*
- * md_end() is called from main() in as.c after assembly ends. It is used
- * to allow target machine dependent clean up.
- */
- void
- md_end(void)
- {
- }
-
- /*
- * md_parse_option() is called from main() in as.c to parse target machine
- * dependent command line options. This routine returns 0 if it is passed an
- * option that is not recognized non-zero otherwise.
- */
- int
- md_parse_option(
- char **argP,
- int *cntP,
- char ***vecP)
- {
- return(0);
- }
-
- /*
- * s_reg() is used to implement ".greg symbol,exp" and ".xreg symbol,exp"
- * which set symbol to 1 or 0 depending on if the expression is a general
- * register or extended register respectfully. These are intended for use in
- * macros.
- */
- static
- void
- s_reg(
- int reg)
- {
- char *name, *end_name, delim;
- symbolS *symbolP;
- unsigned long n_value, val;
-
- if( * input_line_pointer == '"')
- name = input_line_pointer + 1;
- else
- name = input_line_pointer;
- delim = get_symbol_end();
- end_name = input_line_pointer;
- *end_name = delim;
- SKIP_WHITESPACE();
- if ( * input_line_pointer != ',' ) {
- *end_name = 0;
- as_warn("Expected comma after name \"%s\"", name);
- *end_name = delim;
- ignore_rest_of_line();
- return;
- }
- input_line_pointer ++;
- *end_name = 0;
-
- SKIP_WHITESPACE();
- n_value = 0;
- if (*input_line_pointer == reg || *input_line_pointer == toupper(reg)){
- input_line_pointer++;
- if(isdigit(*input_line_pointer)){
- val = 0;
- while (isdigit(*input_line_pointer)){
- if ((val = val * 10 + *input_line_pointer++ - '0') > 31)
- break;
- }
- SKIP_WHITESPACE();
- if(val <= 31 &&
- (*input_line_pointer == '\n' || *input_line_pointer == '@'))
- n_value = 1;
- }
- }
-
- symbolP = symbol_find_or_make (name);
- symbolP -> sy_type = N_ABS;
- symbolP -> sy_other = 0; /* NO_SECT */
- symbolP -> sy_value = n_value;
- symbolP -> sy_frag = & zero_address_frag;
-
- *end_name = delim;
- totally_ignore_line();
- }
-
- /*
- * md_assemble() is passed a pointer to a string that should be a assembly
- * statement for the target machine.
- */
- void
- md_assemble(
- char *op)
- {
- char *param, *thisfrag, prediction;
- struct m98k_opcode *format;
- struct m98k_insn insn;
- unsigned long retry;
-
- /*
- * Pick up the instruction and any trailing branch prediction character
- * (a trailing '+' or '-' on the instruction).
- */
- prediction = '\0';
- for(param = op; !isspace(*param) && *param != '\0' ; param++)
- prediction = *param;
- if(prediction == '+' || prediction == '-')
- param[-1] = '\0';
- else
- prediction = '\0';
- if(*param != '\0')
- *param++ = '\0';
-
- /* try to find the instruction in the hash table */
- if((format = (struct m98k_opcode *)hash_find(op_hash, op)) == NULL){
- as_warn("Invalid mnemonic '%s'", op);
- return;
- }
-
- /* try parsing this instruction into insn */
- retry = 0;
- error_param_count = 0;
- error_param_message = NULL;
- while(calcop(format, param, &insn, op, prediction) == 0){
- /* if it doesn't parse try the next instruction */
- if(strcmp(format->name, format[1].name) == 0){
- format++;
- retry = 1;
- }
- else{
- if(retry == 0){
- if(error_param_message != NULL)
- as_warn(error_param_message, error_param_count + 1);
- else
- as_warn("Parameter syntax error (parameter %lu)",
- error_param_count + 1);
- }
- else
- as_warn("Parameter syntax error");
- return;
- }
- }
-
- /*
- * Check for invalid forms of instructions. For the following
- * instructions: lbzu, lbzux, lhzu, lhzux, lhau, lhaux, lwzu, lwzux,
- * lwaux, ldu, ldux
- * if RA == 0 or RA == RT the instruction form is invalid.
- */
- if((insn.opcode & 0xfc000000) == 0x8c000000 || /* lbzu */
- (insn.opcode & 0xfc0007fe) == 0x7c0000ee || /* lbzux */
- (insn.opcode & 0xfc000000) == 0xa4000000 || /* lhzu */
- (insn.opcode & 0xfc0007fe) == 0x7c00026e || /* lbzux */
- (insn.opcode & 0xfc000000) == 0xac000000 || /* lhau */
- (insn.opcode & 0xfc0007fe) == 0x7c0002ee || /* lhaux */
- (insn.opcode & 0xfc000000) == 0x84000000 || /* lwzu */
- (insn.opcode & 0xfc0007fe) == 0x7c00006e || /* lwzux */
- (insn.opcode & 0xfc0007fe) == 0x7c0002ea || /* lwaux */
- (insn.opcode & 0xfc000000) == 0xe8000000 || /* ldu */
- (insn.opcode & 0xfc0007fe) == 0x7c00006a){ /* ldux */
- if(RA(insn.opcode) == 0)
- as_warn("Invalid form of the instruction (RA must not be 0)");
- if(RA(insn.opcode) == RT(insn.opcode))
- as_warn("Invalid form of the instruction (RA must not the same "
- "as RT)");
- }
- /*
- * For the following instructions: stbu, stbux, sthu, sthux, stwu,
- * stwux, stdu, stdux, lfsu, lfsux, lfdu, lfdux, stfsu, stfsux, stfdu,
- * stfdux
- * if RA == 0 the instruction form is invalid.
- */
- if((insn.opcode & 0xfc000000) == 0x9c000000 || /* stbu */
- (insn.opcode & 0xfc0007fe) == 0x7c0001ee || /* stbux */
- (insn.opcode & 0xfc000000) == 0xb4000000 || /* sthu */
- (insn.opcode & 0xfc0007fe) == 0x7c00036e || /* sthux */
- (insn.opcode & 0xfc000000) == 0x94000000 || /* stwu */
- (insn.opcode & 0xfc0007fe) == 0x7c00016e || /* stwux */
- (insn.opcode & 0xfc000003) == 0xf8000001 || /* stdu */
- (insn.opcode & 0xfc0007fe) == 0x7c00016a || /* stdux */
- (insn.opcode & 0xfc000000) == 0xc4000000 || /* lfsu */
- (insn.opcode & 0xfc0007fe) == 0x7c00046e || /* lfsux */
- (insn.opcode & 0xfc000000) == 0xcc000000 || /* lfdu */
- (insn.opcode & 0xfc0007fe) == 0x7c0004ee || /* lfdux */
- (insn.opcode & 0xfc000000) == 0xd4000000 || /* stfsu */
- (insn.opcode & 0xfc0007fe) == 0x7c00056e || /* stfsux */
- (insn.opcode & 0xfc000000) == 0xdc000000 || /* stfdu */
- (insn.opcode & 0xfc0007fe) == 0x7c0005ee){ /* stfdux */
- if(RA(insn.opcode) == 0)
- as_warn("Invalid form of the instruction (RA must not be 0)");
- }
- /*
- * For the following instructions: lmw, lmd, lswi, lswx
- * if RA is in the range of registers to be loaded or RT == RA == 0
- * the instruction form is invalid. WHAT does this mean?
- */
- if((insn.opcode & 0xfc000000) == 0xb8000000 || /* lmw */
- (insn.opcode & 0xfc000003) == 0xe8000003 || /* lmw */
- (insn.opcode & 0xfc0007fe) == 0x7c0004aa || /* lswi */
- (insn.opcode & 0xfc0007fe) == 0x7c00042a){ /* lswx */
- }
-
- /* grow the current frag and plop in the opcode */
- thisfrag = frag_more(4);
- md_number_to_chars(thisfrag, insn.opcode, 4);
-
- /*
- * If the -g flag is present generate a line number stab for the
- * instruction.
- *
- * See the detailed comments about stabs in read_a_source_file() for a
- * description of what is going on here.
- */
- if(flagseen['g'] && frchain_now->frch_nsect == text_nsect){
- (void)symbol_new(
- "",
- 68 /* N_SLINE */,
- text_nsect,
- logical_input_line /* n_desc, line number */,
- obstack_next_free(&frags) - frag_now->fr_literal,
- frag_now);
- }
-
- /*
- * We are putting a machine instruction in this section so mark it as
- * containg some machine instructions.
- */
- frchain_now->frch_section.flags |= S_ATTR_SOME_INSTRUCTIONS;
-
- /* if this instruction requires labels mark it for later */
- switch(insn.reloc){
- case NO_RELOC:
- break;
- case M98K_RELOC_HI16:
- case M98K_RELOC_LO16:
- case M98K_RELOC_HA16:
- case M98K_RELOC_LO14:
- fix_new(frag_now,
- thisfrag - frag_now->fr_literal,
- 4,
- insn.exp.X_add_symbol,
- insn.exp.X_subtract_symbol,
- insn.exp.X_add_number,
- 0, 0,
- insn.reloc);
- break;
- case M98K_RELOC_BR14:
- fix_new(frag_now,
- thisfrag - frag_now->fr_literal,
- 4,
- insn.exp.X_add_symbol,
- insn.exp.X_subtract_symbol,
- insn.exp.X_add_number,
- insn.pcrel,
- insn.pcrel_reloc,
- insn.reloc);
- break;
-
- case M98K_RELOC_BR24:
- fix_new(frag_now,
- thisfrag - frag_now->fr_literal,
- 4,
- insn.exp.X_add_symbol,
- insn.exp.X_subtract_symbol,
- insn.exp.X_add_number,
- insn.pcrel,
- insn.pcrel_reloc,
- insn.reloc);
- break;
- default:
- as_warn("Unknown relocation type");
- break;
- }
- }
-
- static
- int
- calcop(
- struct m98k_opcode *format,
- char *param,
- struct m98k_insn *insn,
- char *op,
- char prediction)
- {
- unsigned long parcnt;
-
- /* initial the passed structure */
- memset(insn, '\0', sizeof(struct m98k_insn));
- insn->opcode = format->opcode;
- insn->reloc = NO_RELOC;
-
- /* parse all parameters */
- for(parcnt = 0; parcnt < 5 &&
- format->ops[parcnt].type != NONE; parcnt++){
- error_param_count = parcnt;
-
- switch(format->ops[parcnt].type){
- case PCREL:
- case BADDR:
- param = parse_branch(param, insn, format, parcnt);
- break;
- case D:
- case DS:
- param = parse_displacement(param, insn, format, parcnt);
- break;
- case SI:
- case UI:
- param = parse_immediate(param, insn, format, parcnt);
- break;
- case GREG:
- case G0REG:
- param = parse_reg("r", param, insn, format, parcnt);
- break;
- case FREG:
- param = parse_reg("f", param, insn, format, parcnt);
- break;
- case SGREG:
- param = parse_reg("sr", param, insn, format, parcnt);
- break;
- case SPREG:
- param = parse_spreg(param, insn, format, parcnt);
- break;
- case BCND:
- param = parse_bcnd(param, insn, format, parcnt);
- break;
- case CRF:
- case CRFONLY:
- param = parse_crf(param, insn, format, parcnt);
- break;
- case NUM:
- param = parse_num(param, insn, format, parcnt, 0);
- break;
- case NUM0:
- param = parse_num(param, insn, format, parcnt, 1);
- break;
- case sh:
- param = parse_sh(param, insn, format, parcnt);
- break;
- case mb:
- param = parse_mb(param, insn, format, parcnt);
- break;
- default:
- as_fatal("Unknown parameter type");
- }
-
- /* see if parser failed or not */
- if (param == NULL)
- return(0);
- }
- if(format->ops[0].type == NONE && *param != '\0'){
- error_param_message = "too many parameters";
- return(0);
- }
-
- if(IS_BRANCH_CONDITIONAL(insn->opcode)){
- if(prediction != '\0'){
- /*
- * Set the Y_BIT assuming the displacement is non-negitive.
- * If the displacement is negitive then the Y_BIT is flipped
- * in md_number_to_imm().
- */
- if(prediction == '+')
- insn->opcode |= Y_BIT;
- else{ /* prediction == '-' */
- if((insn->opcode & Y_BIT) != 0)
- as_warn("branch prediction ('-') ignored (specified "
- "operand has prediction bit set)");
- else
- insn->opcode &= ~(Y_BIT);
- }
- }
- }
- else{
- if(prediction != '\0')
- as_warn("branch prediction ignored (instruction is not a "
- "conditional branch)");
- }
- return(1);
- }
-
- static
- char *
- parse_displacement(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- int parcnt)
- {
- unsigned long val;
- char *end, *saveptr, *saveparam;
- segT seg;
-
-
- if(parcnt != 1 || format->ops[2].type != G0REG)
- as_fatal("internal error, bad table entry for instruction %s "
- "(displacement operand not second operand or general "
- "register not third operand)", format->name);
-
- /*
- * There must be "(rX)" (where X is a number between 0-31) or "(0)"
- * at the end of the parameter string. To know out where the
- * displacement expression ends determine the begining the "(rX)"
- * by looking for the last '(' in the string. The parsing of this
- * trailing string will be done in another routine.
- */
- end = strrchr(param, '(');
- if(end == NULL)
- return(NULL);
- *end = '\0';
-
- /*
- * The expression may have one of the following: hi16(exp), ha16(exp),
- * or lo16(exp) around the expression which determines the relocation
- * type.
- */
- if(strncmp(param,"hi16(",5) == 0){
- insn->reloc = M98K_RELOC_HI16;
- param += 5;
- }
- else if(strncmp(param,"ha16(",5) == 0){
- insn->reloc = M98K_RELOC_HA16;
- param += 5;
- }
- else if(strncmp(param,"lo16(",5) == 0){
- if(format->ops[parcnt].type == DS)
- insn->reloc = M98K_RELOC_LO14;
- else
- insn->reloc = M98K_RELOC_LO16;
- param += 5;
- }
-
- saveptr = input_line_pointer;
- input_line_pointer = param;
-
- seg = expression(&insn->exp);
- try_to_make_absolute(&insn->exp);
- seg = insn->exp.X_seg;
-
- saveparam = input_line_pointer;
- input_line_pointer = saveptr;
- *end = '(';
-
- if(insn->reloc != NO_RELOC){
- if(*saveparam != ')' || ++saveparam != end)
- return(NULL);
- }
- else{
- if(saveparam != end)
- return(NULL);
- val = insn->exp.X_add_number;
- if(seg != SEG_ABSOLUTE){
- error_param_message = "Parameter error: expression must be "
- "absolute (parameter %lu)";
- return(NULL);
- }
- if(val & 0x8000){
- if((val & 0xffff0000) != 0xffff0000){
- error_param_message = "Parameter error: expression out of "
- "range (parameter %lu)";
- return(NULL);
- }
- val = val & 0xffff;
- }
- else{
- if((val & 0xffff0000) != 0){
- error_param_message = "Parameter error: expression out of "
- "range (parameter %lu)";
- return(NULL);
- }
- }
- if(format->ops[parcnt].type == DS){
- if((val & 0x3) != 0){
- error_param_message = "Parameter error: expression must be "
- "a multiple of 4 (parameter %lu)";
- return(NULL);
- }
- val >>= 2;
- }
- insn->opcode |= val << format->ops[parcnt].offset;
- }
- return(saveparam);
- }
-
- static
- char *
- parse_immediate(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- int parcnt)
- {
- unsigned long val;
- char *saveptr, *saveparam;
- segT seg;
-
- /*
- * The expression may have one of the following: hi16(exp), ha16(exp),
- * or lo16(exp) around the expression which determines the relocation
- * type.
- */
- if(strncmp(param,"hi16(",5) == 0){
- insn->reloc = M98K_RELOC_HI16;
- param += 5;
- }
- else if(strncmp(param,"ha16(",5) == 0){
- insn->reloc = M98K_RELOC_HA16;
- param += 5;
- }
- else if(strncmp(param,"lo16(",5) == 0){
- if(format->ops[parcnt].type == DS)
- insn->reloc = M98K_RELOC_LO14;
- else
- insn->reloc = M98K_RELOC_LO16;
- param += 5;
- }
-
- saveptr = input_line_pointer;
- input_line_pointer = param;
-
- seg = expression(&insn->exp);
- try_to_make_absolute(&insn->exp);
- seg = insn->exp.X_seg;
-
- saveparam = input_line_pointer;
- input_line_pointer = saveptr;
-
- if(insn->reloc != NO_RELOC){
- if(*saveparam != ')')
- return(NULL);
- saveparam++;
- if(*saveparam == '\0'){
- if(parcnt == 4 || format->ops[parcnt+1].type == NONE)
- return(saveparam);
- else
- return(NULL);
- }
- else if(*saveparam == ','){
- if(parcnt != 4 && format->ops[parcnt+1].type != NONE)
- return(saveparam+1);
- else
- return(NULL);
- }
- else
- return(NULL);
- }
- else{
- val = insn->exp.X_add_number;
- if(seg != SEG_ABSOLUTE){
- error_param_message = "Parameter error: expression must be "
- "absolute (parameter %lu)";
- return(NULL);
- }
- if(format->ops[parcnt].type == SI){
- if(val & 0x8000){
- if((val & 0xffff0000) != 0xffff0000){
- error_param_message = "Parameter error: expression out "
- "of range (parameter %lu)";
- return(NULL);
- }
- val = val & 0xffff;
- }
- else{
- if((val & 0xffff0000) != 0){
- error_param_message = "Parameter error: expression out "
- "of range (parameter %lu)";
- return(NULL);
- }
- }
- }
- else{
- if((val & 0xffff0000) != 0){
- error_param_message = "Parameter error: expression out "
- "of range (parameter %lu)";
- return(NULL);
- }
- }
- if(*saveparam == '\0'){
- if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
- insn->opcode |= val << format->ops[parcnt].offset;
- return(saveparam);
- }
- else
- return(NULL);
- }
- else if(*saveparam == ','){
- if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
- insn->opcode |= val << format->ops[parcnt].offset;
- return(saveparam+1);
- }
- else
- return(NULL);
- }
- else
- return(NULL);
- }
- return(saveparam);
- }
-
- static
- char *
- parse_branch(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- int parcnt)
- {
- char *saveptr, *saveparam;
- segT seg;
-
- saveptr = input_line_pointer;
- input_line_pointer = param;
-
- seg = expression(&insn->exp);
- try_to_make_absolute(&insn->exp);
- seg = insn->exp.X_seg;
-
- saveparam = input_line_pointer;
- input_line_pointer = saveptr;
-
- insn->pcrel = 0;
- insn->pcrel_reloc = 0;
- if(format->ops[parcnt].type == PCREL){
- /*
- * The NeXT linker has the ability to scatter blocks of
- * sections between labels. This requires that brances to
- * labels that survive to the link phase must be able to
- * be relocated.
- */
- if(insn->exp.X_add_symbol != NULL &&
- (insn->exp.X_add_symbol->sy_name[0] != 'L' || flagseen ['L']))
- insn->pcrel_reloc = 1;
- else
- insn->pcrel_reloc = 0;
- insn->pcrel = 1;
- }
- switch(format->ops[parcnt].width){
- case 14:
- insn->reloc = M98K_RELOC_BR14;
- break;
- case 24:
- insn->reloc = M98K_RELOC_BR24;
- break;
- default:
- as_fatal("Unknown branch instruction width %d",
- format->ops[parcnt].width);
- break;
- }
- return(saveparam);
- }
-
- static
- char *
- parse_reg(
- char *reg_name,
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt)
- {
- unsigned long val, d;
-
- d = 0;
- if(*param == '(' && parcnt == 2 &&
- (format->ops[1].type == D || format->ops[1].type == DS)){
- d = 1;
- param++;
- }
-
- if(format->ops[parcnt].type == G0REG && *param == '0'){
- val = 0;
- param++;
- }
- else{
- val = 0;
- while(*reg_name){
- if(*param++ != *reg_name++)
- return(NULL);
- }
- if(!isdigit(*param))
- return(NULL);
-
- while(isdigit(*param))
- if((val = val * 10 + *param++ - '0') >=
- 1 << format->ops[parcnt].width)
- return(NULL);
-
- if(format->ops[parcnt].type == G0REG && val == 0){
- error_param_message = "Parameter error: r0 not allowed "
- "for parameter %lu (code as 0 not r0)";
- return(NULL);
- }
- }
-
- if(*param == '\0'){
- if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
- insn->opcode |= val << format->ops[parcnt].offset;
- return(param);
- }
- else
- return(NULL);
- }
- else if(*param == ','){
- if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
- insn->opcode |= val << format->ops[parcnt].offset;
- return(param+1);
- }
- else
- return(NULL);
- }
- else if(d == 1 && *param == ')' && param[1] == '\0'){
- if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
- insn->opcode |= val << format->ops[parcnt].offset;
- return(++param);
- }
- else
- return(NULL);
- }
- return(NULL);
- }
-
- static
- char *
- parse_spreg(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt)
- {
- int val;
- unsigned long i;
- char *saveptr, save_c;
- expressionS exp;
- segT seg;
-
- saveptr = input_line_pointer;
- input_line_pointer = param;
- while(*param != ',' && *param != '\0')
- param++;
- save_c = *param;
- *param = '\0';
-
- seg = SEG_ABSOLUTE;
- val = 0;
- for(i = 0; *special_registers[i].name != '\0'; i++){
- if(strcmp(input_line_pointer, special_registers[i].name) == 0){
- val = special_registers[i].number;
- break;
- }
- }
- if(*special_registers[i].name == '\0'){
- seg = expression(&exp);
- try_to_make_absolute(&exp);
- seg = exp.X_seg;
- val = exp.X_add_number;
- }
- *param = save_c;
- input_line_pointer = saveptr;
-
- if(seg != SEG_ABSOLUTE){
- error_param_message = "Parameter error: expression must be "
- "absolute (parameter %lu)";
- return(NULL);
- }
- if(val > 1024 || val < 0){
- error_param_message = "Parameter error: expression out "
- "of range (parameter %lu)";
- return(NULL);
- }
-
- val = ((val & 0x1f) << 5) | ((val >> 5) & 0x1f);
-
- if(*param == '\0'){
- if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
- insn->opcode |= val << format->ops[parcnt].offset;
- return(param);
- }
- else
- return(NULL);
- }
- else if(*param == ','){
- if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
- insn->opcode |= val << format->ops[parcnt].offset;
- return(param+1);
- }
- else
- return(NULL);
- }
- return(NULL);
- }
-
- static
- char *
- parse_bcnd(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt)
- {
- int val;
- unsigned long i, j;
- char *saveptr, save_c, *plus, save_plus;
- expressionS exp;
- segT seg;
-
- saveptr = input_line_pointer;
- input_line_pointer = param;
- while(*param != ',' && *param != '\0')
- param++;
- save_c = *param;
- *param = '\0';
-
- /*
- * look for "[CR_field+]condition_symbol".
- */
- val = -1;
- for(plus = input_line_pointer; *plus != '+' && *plus != '\0'; plus++)
- ;
- if(*plus == '+'){
- save_plus = *plus;
- *plus = '\0';
- for(i = 0; *CR_fields[i].name != '\0'; i++)
- if(strcmp(input_line_pointer, CR_fields[i].name) == 0)
- break;
- *plus = save_plus;
- if(*CR_fields[i].name != '\0'){
- for(j = 0; *condition_symbols[j].name != '\0'; j++)
- if(strcmp(plus+1, condition_symbols[j].name) == 0)
- break;
- if(*condition_symbols[j].name != '\0'){
- val = CR_fields[i].value + condition_symbols[j].value;
- }
- }
- }
- else{
- for(i = 0; *condition_symbols[i].name != '\0'; i++)
- if(strcmp(input_line_pointer, condition_symbols[i].name) == 0)
- break;
- if(*condition_symbols[i].name != '\0')
- val = condition_symbols[i].value;
- }
- if(val == -1){
- seg = expression(&exp);
- try_to_make_absolute(&exp);
- seg = exp.X_seg;
- val = exp.X_add_number;
- if(seg != SEG_ABSOLUTE){
- error_param_message = "Parameter error: expression must be "
- "absolute (parameter %lu)";
- *param = save_c;
- input_line_pointer = saveptr;
- return(NULL);
- }
- if(val >= (1 << format->ops[parcnt].width) || val < 0){
- error_param_message = "Parameter error: expression out "
- "of range (parameter %lu)";
- *param = save_c;
- input_line_pointer = saveptr;
- return(NULL);
- }
- }
-
- *param = save_c;
- input_line_pointer = saveptr;
-
-
- if(*param == '\0'){
- if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
- insn->opcode |= val << format->ops[parcnt].offset;
- return(param);
- }
- else
- return(NULL);
- }
- else if(*param == ','){
- if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
- insn->opcode |= val << format->ops[parcnt].offset;
- return(param+1);
- }
- else
- return(NULL);
- }
- return(NULL);
-
- }
-
- static
- char *
- parse_crf(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt)
- {
- int val;
- unsigned long i;
- char *saveptr, save_c;
- expressionS exp;
- segT seg;
-
- saveptr = input_line_pointer;
- input_line_pointer = param;
- while(*param != ',' && *param != '\0')
- param++;
- save_c = *param;
- *param = '\0';
- val = -1;
- for(i = 0; *CR_fields[i].name != '\0'; i++){
- if(strcmp(input_line_pointer, CR_fields[i].name) == 0){
- val = CR_fields[i].value;
- break;
- }
- }
- if(val == -1){
- if(format->ops[parcnt].type == CRFONLY){
- *param = save_c;
- input_line_pointer = saveptr;
- return(NULL);
- }
- seg = expression(&exp);
- try_to_make_absolute(&exp);
- seg = exp.X_seg;
- val = exp.X_add_number;
- if(seg != SEG_ABSOLUTE){
- error_param_message = "Parameter error: expression must be "
- "absolute (parameter %lu)";
- *param = save_c;
- input_line_pointer = saveptr;
- return(NULL);
- }
- if(val >= (1 << format->ops[parcnt].width) || val < 0){
- error_param_message = "Parameter error: expression out "
- "of range (parameter %lu)";
- *param = save_c;
- input_line_pointer = saveptr;
- return(NULL);
- }
- }
- *param = save_c;
- input_line_pointer = saveptr;
-
- if(*param == '\0'){
- if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
- insn->opcode |= val << format->ops[parcnt].offset;
- return(param);
- }
- else
- return(NULL);
- }
- else if(*param == ','){
- if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
- insn->opcode |= val << format->ops[parcnt].offset;
- return(param+1);
- }
- else
- return(NULL);
- }
- return(NULL);
- }
-
- static
- char *
- parse_num(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt,
- long max_width_zero)
- {
- int val;
- char *saveptr, save_c;
- expressionS exp;
- segT seg;
-
- saveptr = input_line_pointer;
- input_line_pointer = param;
- while(*param != ',' && *param != '\0')
- param++;
- save_c = *param;
- *param = '\0';
- seg = expression(&exp);
- try_to_make_absolute(&exp);
- seg = exp.X_seg;
- *param = save_c;
- input_line_pointer = saveptr;
-
- val = exp.X_add_number;
- if(seg != SEG_ABSOLUTE){
- error_param_message = "Parameter error: expression must be "
- "absolute (parameter %lu)";
- return(NULL);
- }
- if(max_width_zero){
- if(val == (1 << format->ops[parcnt].width))
- val = 0;
- }
- if(val >= (1 << format->ops[parcnt].width) || val < 0){
- error_param_message = "Parameter error: expression out "
- "of range (parameter %lu)";
- return(NULL);
- }
-
- if(*param == '\0'){
- if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
- insn->opcode |= val << format->ops[parcnt].offset;
- return(param);
- }
- else
- return(NULL);
- }
- else if(*param == ','){
- if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
- insn->opcode |= val << format->ops[parcnt].offset;
- return(param+1);
- }
- else
- return(NULL);
- }
- return(NULL);
-
- }
-
- static
- char *
- parse_sh(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt)
- {
- int val;
- char *saveptr, save_c;
- expressionS exp;
- segT seg;
-
- saveptr = input_line_pointer;
- input_line_pointer = param;
- while(*param != ',' && *param != '\0')
- param++;
- save_c = *param;
- *param = '\0';
- seg = expression(&exp);
- try_to_make_absolute(&exp);
- seg = exp.X_seg;
- *param = save_c;
- input_line_pointer = saveptr;
-
- val = exp.X_add_number;
- if(seg != SEG_ABSOLUTE){
- error_param_message = "Parameter error: expression must be "
- "absolute (parameter %lu)";
- return(NULL);
- }
- if(val == 64)
- val = 0;
- if(val >= 64 || val < 0){
- error_param_message = "Parameter error: expression out "
- "of range (parameter %lu)";
- return(NULL);
- }
-
- if(*param == '\0'){
- if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
- insn->opcode |= (val & 0x1f) << 11;
- insn->opcode |= ((val >> 5) & 0x1) << 1;
- return(param);
- }
- else
- return(NULL);
- }
- else if(*param == ','){
- if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
- insn->opcode |= (val & 0x1f) << 11;
- insn->opcode |= ((val >> 5) & 0x1) << 1;
- return(param+1);
- }
- else
- return(NULL);
- }
- return(NULL);
-
- }
-
- static
- char *
- parse_mb(
- char *param,
- struct m98k_insn *insn,
- struct m98k_opcode *format,
- unsigned long parcnt)
- {
- int val;
- char *saveptr, save_c;
- expressionS exp;
- segT seg;
-
- saveptr = input_line_pointer;
- input_line_pointer = param;
- while(*param != ',' && *param != '\0')
- param++;
- save_c = *param;
- *param = '\0';
- seg = expression(&exp);
- try_to_make_absolute(&exp);
- seg = exp.X_seg;
- *param = save_c;
- input_line_pointer = saveptr;
-
- val = exp.X_add_number;
- if(seg != SEG_ABSOLUTE){
- error_param_message = "Parameter error: expression must be "
- "absolute (parameter %lu)";
- return(NULL);
- }
- if(val > 64 || val < 0){
- error_param_message = "Parameter error: expression out "
- "of range (parameter %lu)";
- return(NULL);
- }
-
- if(*param == '\0'){
- if(parcnt == 4 || format->ops[parcnt+1].type == NONE){
- insn->opcode |= (val & 0x1f) << 6;
- insn->opcode |= ((val >> 5) & 0x1) << 5;
- return(param);
- }
- else
- return(NULL);
- }
- else if(*param == ','){
- if(parcnt != 4 && format->ops[parcnt+1].type != NONE){
- insn->opcode |= (val & 0x1f) << 6;
- insn->opcode |= ((val >> 5) & 0x1) << 5;
- return(param+1);
- }
- else
- return(NULL);
- }
- return(NULL);
-
- }
-
- /*
- * md_number_to_chars() is the target machine dependent routine that puts out
- * a binary value of size 4, 2, or 1 bytes into the specified buffer. This is
- * done in the target machine's byte sex. In this case the byte order is
- * big endian.
- */
- void
- md_number_to_chars(
- char *buf,
- long val,
- int nbytes)
- {
- switch(nbytes){
- case 4:
- *buf++ = val >> 24;
- *buf++ = val >> 16;
- case 2:
- *buf++ = val >> 8;
- case 1:
- *buf = val;
- break;
-
- default:
- abort();
- }
- }
-
- /*
- * md_number_to_imm() is the target machine dependent routine that puts out
- * a binary value of size 4, 2, or 1 bytes into the specified buffer with
- * reguard to a possible relocation entry (the fixP->fx_r_type field in the fixS
- * structure pointed to by fixP) for the section with the ordinal nsect. This
- * is done in the target machine's byte sex using it's relocation types.
- * In this case the byte order is big endian.
- */
- void
- md_number_to_imm(
- unsigned char *buf,
- long val,
- int nbytes,
- fixS *fixP,
- int nsect)
- {
- unsigned long opcode;
-
- if(fixP->fx_r_type == NO_RELOC ||
- fixP->fx_r_type == M98K_RELOC_VANILLA){
- switch(nbytes){
- case 4:
- *buf++ = val >> 24;
- *buf++ = val >> 16;
- case 2:
- *buf++ = val >> 8;
- case 1:
- *buf = val;
- break;
-
- default:
- abort();
- }
- return;
- }
- switch(fixP->fx_r_type){
- case M98K_RELOC_HI16:
- buf[2] = val >> 24;
- buf[3] = val >> 16;
- break;
-
- case M98K_RELOC_LO16:
- buf[2] = val >> 8;
- buf[3] = val;
- break;
-
- case M98K_RELOC_HA16:
- val += 0x00008000;
- buf[2] = val >> 24;
- buf[3] = val >> 16;
- break;
-
- case M98K_RELOC_LO14:
- buf[2] = val >> 8;
- buf[3] = val & 0xfc;
- break;
-
- case M98K_RELOC_BR14:
- if((val & 0x00008000) != 0){
- opcode = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
- if(((opcode) & 0x03e00000) != 0x02800000){
- opcode ^= Y_BIT;
- buf[0] = opcode >> 24;
- buf[1] = opcode >> 16;
- buf[2] = opcode >> 8;
- buf[3] = opcode;
- }
- }
- if(fixP->fx_pcrel)
- val += 4;
- buf[2] = val >> 8;
- buf[3] |= val & 0xfc;
- break;
-
- case M98K_RELOC_BR24:
- if(fixP->fx_pcrel)
- val += 4;
- buf[0] |= (val >> 24) & 0x03;
- buf[1] = val >> 16;
- buf[2] = val >> 8;
- buf[3] |= val & 0xfc;
- break;
-
- default:
- as_warn("Bad relocation type");
- break;
- }
- }
-
- /*
- * md_atof() turns a string pointed to by input_line_pointer into a floating
- * point constant of type type, and store the appropriate bytes in *litP.
- * The number of LITTLENUMS emitted is stored indirectly through *sizeP.
- * An error message is returned, or a string containg only a '\0' for OK.
- * For this machine only IEEE single and IEEE double floating-point formats
- * are allowed.
- */
- char *
- md_atof(
- int type,
- char *litP,
- int *sizeP)
- {
- int prec;
- LITTLENUM_TYPE words[6];
- LITTLENUM_TYPE *wordP;
- char *t;
-
- switch(type){
- case 'f':
- case 'F':
- case 's':
- case 'S':
- prec = 2;
- break;
-
- case 'd':
- case 'D':
- case 'r':
- case 'R':
- prec = 4;
- break;
-
- default:
- *sizeP = 0;
- return("Bad call to MD_ATOF()");
- }
- t = atof_ieee(input_line_pointer, type, words);
- if(t != NULL)
- input_line_pointer = t;
-
- *sizeP = prec * sizeof(LITTLENUM_TYPE);
- for(wordP = words; prec--; ){
- md_number_to_chars(litP, (long)(*wordP++), sizeof(LITTLENUM_TYPE));
- litP += sizeof(LITTLENUM_TYPE);
- }
- return ""; /* OK */
- }
-
- int
- md_estimate_size_before_relax(
- fragS *fragP,
- int segment_type)
- {
- as_warn("Relaxation should never occur");
- return(sizeof(long));
- }
-
- const relax_typeS md_relax_table[] = { {0} };
-
- void
- md_convert_frag(
- fragS *fragP)
- {
- as_warn("Relaxation should never occur");
- }
-