static void s_common() { register char *name; register char c; register char *p; register int temp; register symbolS * symbolP; name = input_line_pointer; c = get_symbol_end(); /* just after name is now '\0' */ p = input_line_pointer; *p = c; SKIP_WHITESPACE(); if ( * input_line_pointer != ',' ) { as_warn("Expected comma after symbol-name"); ignore_rest_of_line(); return; } input_line_pointer ++; /* skip ',' */ if ( (temp = get_absolute_expression ()) < 0 ) { as_warn(".COMMon length (%d.) <0! Ignored.", temp); ignore_rest_of_line(); return; } *p = 0; symbolP = symbol_find_or_make (name); *p = c; if ( (symbolP->sy_type & N_TYPE) != N_UNDF || symbolP->sy_other != 0 || symbolP->sy_desc != 0) { as_warn( "Ignoring attempt to re-define symbol"); ignore_rest_of_line(); return; } if (symbolP->sy_value) { if (symbolP->sy_value != temp) { as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.", symbolP->sy_name, symbolP->sy_value, temp); } } else { symbolP->sy_value = temp; symbolP->sy_type |= N_EXT; } know(symbolP->sy_frag == &zero_address_frag); if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) { p=input_line_pointer; while(*p && *p!='\n') p++; c= *p; *p='\0'; as_warn("bad .common segment: `%s'", input_line_pointer); *p=c; return; } input_line_pointer += 6; demand_empty_rest_of_line(); return; }
static int parse_register_operand (char **ptr) { int reg; char *s = *ptr; if (*s != '$') { as_bad (_("expecting register")); ignore_rest_of_line (); return -1; } if (s[1] == 'f' && s[2] == 'p') { *ptr += 3; return 0; } if (s[1] == 's' && s[2] == 'p') { *ptr += 3; return 1; } if (s[1] == 'r') { reg = s[2] - '0'; if ((reg < 0) || (reg > 9)) { as_bad (_("illegal register number")); ignore_rest_of_line (); return -1; } if (reg == 1) { int r2 = s[3] - '0'; if ((r2 >= 0) && (r2 <= 3)) { reg = 10 + r2; *ptr += 1; } } } else { as_bad (_("illegal register number")); ignore_rest_of_line (); return -1; } *ptr += 3; return reg + 2; }
/* * sort of like s_lcomm * */ static void s_reserve() { char *name; char c; char *p; int temp; symbolS *symbolP; name = input_line_pointer; c = get_symbol_end(); p = input_line_pointer; *p = c; SKIP_WHITESPACE(); if ( * input_line_pointer != ',' ) { as_warn("Expected comma after name"); ignore_rest_of_line(); return; } input_line_pointer ++; if ((temp = get_absolute_expression()) < 0) { as_warn("BSS length (%d.) <0! Ignored.", temp); ignore_rest_of_line(); return; } *p = 0; symbolP = symbol_find_or_make(name); *p = c; if (strncmp(input_line_pointer, ",\"bss\"", 6) != 0) { as_warn("bad .reserve segment: `%s'", input_line_pointer); return; } input_line_pointer += 6; if (symbolP->sy_other == 0 && symbolP->sy_desc == 0 && ((symbolP->sy_type == N_BSS && symbolP->sy_value == local_bss_counter) || ((symbolP->sy_type & N_TYPE) == N_UNDF && symbolP->sy_value == 0))) { symbolP->sy_value = local_bss_counter; symbolP->sy_type = N_BSS; symbolP->sy_frag = & bss_address_frag; local_bss_counter += temp; } else { as_warn( "Ignoring attempt to re-define symbol from %d. to %d.", symbolP->sy_value, local_bss_counter ); } demand_empty_rest_of_line(); return; }
static int parse_regnum(char **ptr) { int reg; char *s = *ptr; if (*s != '%') { as_bad(_("not a register: %s"), s); return -1; } s++; // %fp alias for %14 if (s[0] == 'f' && s[1] == 'p') { *ptr += 3; return 14; } // %sp alias for %15 if (s[0] == 's' && s[1] == 'p') { *ptr += 3; return 15; } reg = *s - '0'; if ((reg < 0) || (reg > 9)) { as_bad(_("illegal register number 1 %s"), s); ignore_rest_of_line(); return -1; } s++; if ((reg > 0) || (reg < 4)) { int r2 = *s - '0'; if ((r2 >= 0) && (r2 <= 9)) { reg = reg*10 + r2; if (reg > 31) { as_bad(_("illegal register number %d"), reg); ignore_rest_of_line(); return -1; } *ptr += 1; } } *ptr += 2; return reg; }
void read_vertex () { int number; is >> number; // vertex number is terminated by colon is >> std::ws; int colon; if ((colon = is.get ()) != ':') format_error ("expected colon, got %c", colon); // coords double x, y, z; is >> x >> y >> z; // rest of record (i.e. attributes) is ignored for now ignore_rest_of_line (); // z coordinate is ignored int vert_id = b->insert_vertex (vec_t (x, y)); // saved for later reference if ((int)vertex_map.size () <= number) { vertex_map.resize (number + 1, Boundary::INVALID_VERTEX); } vertex_map[number] = vert_id; }
void s_ifdef (int test_defined) { /* Points to name of symbol. */ char *name; /* Points to symbol. */ symbolS *symbolP; struct conditional_frame cframe; char c; /* Leading whitespace is part of operand. */ SKIP_WHITESPACE (); name = input_line_pointer; if (!is_name_beginner (*name)) { as_bad (_("invalid identifier for \".ifdef\"")); obstack_1grow (&cond_obstack, 0); ignore_rest_of_line (); return; } c = get_symbol_end (); symbolP = symbol_find (name); *input_line_pointer = c; initialize_cframe (&cframe); if (cframe.dead_tree) cframe.ignoring = 1; else { int is_defined; /* Use the same definition of 'defined' as .equiv so that a symbol which has been referenced but not yet given a value/address is considered to be undefined. */ is_defined = symbolP != NULL && S_IS_DEFINED (symbolP) && S_GET_SEGMENT (symbolP) != reg_section; cframe.ignoring = ! (test_defined ^ is_defined); } current_cframe = ((struct conditional_frame *) obstack_copy (&cond_obstack, &cframe, sizeof (cframe))); if (LISTING_SKIP_COND () && cframe.ignoring && (cframe.previous_cframe == NULL || ! cframe.previous_cframe->ignoring)) listing_list (2); demand_empty_rest_of_line (); }
static void dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED) { if (frchain_now->frch_cfi_data == NULL) { as_bad (_(".cfi_endproc without corresponding .cfi_startproc")); ignore_rest_of_line (); return; } cfi_end_fde (symbol_temp_new_now ()); demand_empty_rest_of_line (); }
void obj_som_version (int unused ATTRIBUTE_UNUSED) { char *version, c; if (version_seen) { as_bad (_("Only one .version pseudo-op per file!")); ignore_rest_of_line (); return; } SKIP_WHITESPACE (); if (*input_line_pointer == '\"') { version = input_line_pointer; ++input_line_pointer; while (is_a_char (next_char_of_string ())) ; c = *input_line_pointer; *input_line_pointer = '\000'; } else { as_bad (_("Expected quoted string")); ignore_rest_of_line (); return; } version_seen = 1; if (!bfd_som_attach_aux_hdr (stdoutput, VERSION_AUX_ID, version)) as_fatal (_("attaching version header %s: %s"), stdoutput->filename, bfd_errmsg (bfd_get_error ())); *input_line_pointer = c; demand_empty_rest_of_line (); }
void obj_som_copyright (int unused ATTRIBUTE_UNUSED) { char *copyright, c; if (copyright_seen) { as_bad (_("Only one .copyright pseudo-op per file!")); ignore_rest_of_line (); return; } SKIP_WHITESPACE (); if (*input_line_pointer == '\"') { copyright = input_line_pointer; ++input_line_pointer; while (is_a_char (next_char_of_string ())) ; c = *input_line_pointer; *input_line_pointer = '\000'; } else { as_bad (_("Expected quoted string")); ignore_rest_of_line (); return; } copyright_seen = 1; if (!bfd_som_attach_aux_hdr (stdoutput, COPYRIGHT_AUX_ID, copyright)) as_fatal (_("attaching copyright header %s: %s"), stdoutput->filename, bfd_errmsg (bfd_get_error ())); *input_line_pointer = c; demand_empty_rest_of_line (); }
void read_poly () { int number; is >> number; // poly number is terminated by colon is >> std::ws; int colon; if ((colon = is.get ()) != ':') format_error ("PolyFileReader::read_poly: expected colon, got %c", colon); // first two vertices int initial_vertex; is >> initial_vertex; // translate POLY vertices into Boundary vertices initial_vertex = lookup_vertex (initial_vertex); int prev_vertex; is >> prev_vertex >> std::ws; prev_vertex = lookup_vertex (prev_vertex); int initial_edge = b->insert_edge (Boundary::INVALID_EDGE, initial_vertex, prev_vertex, Boundary::INVALID_EDGE); int prev_edge = initial_edge; while (is_digit (is.peek ())) { int vertex; is >> vertex >> std::ws; // translate POLY vertices into Boundary vertices vertex = lookup_vertex (vertex); int edge = b->insert_edge (prev_edge, prev_vertex, vertex, Boundary::INVALID_EDGE); prev_vertex = vertex; prev_edge = edge; } is >> std::ws; int closed_indic = is.peek (); if (closed_indic == '<') { // extract '<' character is.get (); // close contour b->insert_edge (prev_edge, prev_vertex, initial_vertex, initial_edge); } else { std::cerr << "WARNING: non-closed contour " << number << ". this is probably not what you want.\n"; } ignore_rest_of_line (); }
void dwarf2_directive_loc_mark_labels (int dummy ATTRIBUTE_UNUSED) { offsetT value = get_absolute_expression (); if (value != 0 && value != 1) { as_bad (_("expected 0 or 1")); ignore_rest_of_line (); } else { dwarf2_loc_mark_labels = value != 0; demand_empty_rest_of_line (); } }
static void dot_cfi_endproc (int ignored ATTRIBUTE_UNUSED) { struct fde_entry *fde; if (frchain_now->frch_cfi_data == NULL) { as_bad (_(".cfi_endproc without corresponding .cfi_startproc")); ignore_rest_of_line (); return; } fde = frchain_now->frch_cfi_data->cur_fde_data; cfi_end_fde (symbol_temp_new_now ()); demand_empty_rest_of_line (); if ((cfi_sections & CFI_EMIT_target) != 0) tc_cfi_endproc (fde); }
static void dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED) { int simple = 0; if (frchain_now->frch_cfi_data != NULL) { as_bad (_("previous CFI entry not closed (missing .cfi_endproc)")); ignore_rest_of_line (); return; } cfi_new_fde (symbol_temp_new_now ()); SKIP_WHITESPACE (); if (is_name_beginner (*input_line_pointer)) { char *name, c; name = input_line_pointer; c = get_symbol_end (); if (strcmp (name, "simple") == 0) { simple = 1; *input_line_pointer = c; } else input_line_pointer = name; } demand_empty_rest_of_line (); frchain_now->frch_cfi_data->cur_cfa_offset = 0; if (!simple) tc_cfi_frame_initial_instructions (); if ((cfi_sections & CFI_EMIT_target) != 0) tc_cfi_startproc (); }
void s_ifeqs (int arg) { char *s1, *s2; int len1, len2; int res; struct conditional_frame cframe; s1 = demand_copy_C_string (&len1); SKIP_WHITESPACE (); if (*input_line_pointer != ',') { as_bad (_(".ifeqs syntax error")); ignore_rest_of_line (); return; } ++input_line_pointer; s2 = demand_copy_C_string (&len2); res = len1 == len2 && strncmp (s1, s2, len1) == 0; initialize_cframe (&cframe); cframe.ignoring = cframe.dead_tree || ! (res ^ arg); current_cframe = ((struct conditional_frame *) obstack_copy (&cond_obstack, &cframe, sizeof (cframe))); if (LISTING_SKIP_COND () && cframe.ignoring && (cframe.previous_cframe == NULL || ! cframe.previous_cframe->ignoring)) listing_list (2); demand_empty_rest_of_line (); }
static void dot_cfi_escape (int ignored ATTRIBUTE_UNUSED) { struct cfi_escape_data *head, **tail, *e; struct cfi_insn_data *insn; if (frchain_now->frch_cfi_data == NULL) { as_bad (_("CFI instruction used without previous .cfi_startproc")); ignore_rest_of_line (); return; } /* If the last address was not at the current PC, advance to current. */ if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now || S_GET_VALUE (frchain_now->frch_cfi_data->last_address) != frag_now_fix ()) cfi_add_advance_loc (symbol_temp_new_now ()); tail = &head; do { e = xmalloc (sizeof (*e)); do_parse_cons_expression (&e->exp, 1); *tail = e; tail = &e->next; } while (*input_line_pointer++ == ','); *tail = NULL; insn = alloc_cfi_insn_data (); insn->insn = CFI_escape; insn->u.esc = head; --input_line_pointer; demand_empty_rest_of_line (); }
static void obj_coff_weak (int ignore ATTRIBUTE_UNUSED) { char *name; int c; symbolS *symbolP; do { name = input_line_pointer; c = get_symbol_end (); if (*name == 0) { as_warn (_("badly formed .weak directive ignored")); ignore_rest_of_line (); return; } c = 0; symbolP = symbol_find_or_make (name); *input_line_pointer = c; SKIP_WHITESPACE (); S_SET_WEAK (symbolP); if (c == ',') { input_line_pointer++; SKIP_WHITESPACE (); if (*input_line_pointer == '\n') c = '\n'; } } while (c == ','); demand_empty_rest_of_line (); }
static void dot_cfi_lsda (int ignored ATTRIBUTE_UNUSED) { struct fde_entry *fde; offsetT encoding; if (frchain_now->frch_cfi_data == NULL) { as_bad (_("CFI instruction used without previous .cfi_startproc")); ignore_rest_of_line (); return; } fde = frchain_now->frch_cfi_data->cur_fde_data; encoding = get_absolute_expression (); if (encoding == DW_EH_PE_omit) { demand_empty_rest_of_line (); fde->lsda_encoding = encoding; return; } if ((encoding & 0xff) != encoding || ((encoding & 0x70) != 0 #if defined DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr && (encoding & 0x70) != DW_EH_PE_pcrel #endif ) /* leb128 can be handled, but does something actually need it? */ || (encoding & 7) == DW_EH_PE_uleb128 || (encoding & 7) > DW_EH_PE_udata8) { as_bad (_("invalid or unsupported encoding in .cfi_lsda")); ignore_rest_of_line (); return; } if (*input_line_pointer++ != ',') { as_bad (_(".cfi_lsda requires encoding and symbol arguments")); ignore_rest_of_line (); return; } fde->lsda_encoding = encoding; expression_and_evaluate (&fde->lsda); switch (fde->lsda.X_op) { case O_symbol: break; case O_constant: if ((encoding & 0x70) == DW_EH_PE_pcrel) encoding = DW_EH_PE_omit; break; default: encoding = DW_EH_PE_omit; break; } fde->lsda_encoding = encoding; if (encoding == DW_EH_PE_omit) { as_bad (_("wrong second argument to .cfi_lsda")); ignore_rest_of_line (); return; } demand_empty_rest_of_line (); }
static void dot_cfi (int arg) { offsetT offset; unsigned reg1, reg2; if (frchain_now->frch_cfi_data == NULL) { as_bad (_("CFI instruction used without previous .cfi_startproc")); ignore_rest_of_line (); return; } /* If the last address was not at the current PC, advance to current. */ if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now || S_GET_VALUE (frchain_now->frch_cfi_data->last_address) != frag_now_fix ()) cfi_add_advance_loc (symbol_temp_new_now ()); switch (arg) { case DW_CFA_offset: reg1 = cfi_parse_reg (); cfi_parse_separator (); offset = cfi_parse_const (); cfi_add_CFA_offset (reg1, offset); break; case CFI_rel_offset: reg1 = cfi_parse_reg (); cfi_parse_separator (); offset = cfi_parse_const (); cfi_add_CFA_offset (reg1, offset - frchain_now->frch_cfi_data->cur_cfa_offset); break; case DW_CFA_def_cfa: reg1 = cfi_parse_reg (); cfi_parse_separator (); offset = cfi_parse_const (); cfi_add_CFA_def_cfa (reg1, offset); break; case DW_CFA_register: reg1 = cfi_parse_reg (); cfi_parse_separator (); reg2 = cfi_parse_reg (); cfi_add_CFA_register (reg1, reg2); break; case DW_CFA_def_cfa_register: reg1 = cfi_parse_reg (); cfi_add_CFA_def_cfa_register (reg1); break; case DW_CFA_def_cfa_offset: offset = cfi_parse_const (); cfi_add_CFA_def_cfa_offset (offset); break; case CFI_adjust_cfa_offset: offset = cfi_parse_const (); cfi_add_CFA_def_cfa_offset (frchain_now->frch_cfi_data->cur_cfa_offset + offset); break; case DW_CFA_restore: for (;;) { reg1 = cfi_parse_reg (); cfi_add_CFA_restore (reg1); SKIP_WHITESPACE (); if (*input_line_pointer != ',') break; ++input_line_pointer; } break; case DW_CFA_undefined: for (;;) { reg1 = cfi_parse_reg (); cfi_add_CFA_undefined (reg1); SKIP_WHITESPACE (); if (*input_line_pointer != ',') break; ++input_line_pointer; } break; case DW_CFA_same_value: reg1 = cfi_parse_reg (); cfi_add_CFA_same_value (reg1); break; case CFI_return_column: reg1 = cfi_parse_reg (); cfi_set_return_column (reg1); break; case DW_CFA_remember_state: cfi_add_CFA_remember_state (); break; case DW_CFA_restore_state: cfi_add_CFA_restore_state (); break; case DW_CFA_GNU_window_save: cfi_add_CFA_insn (DW_CFA_GNU_window_save); break; case CFI_signal_frame: frchain_now->frch_cfi_data->cur_fde_data->signal_frame = 1; break; default: abort (); } demand_empty_rest_of_line (); }
static void nemaweaver_s_lcomm (int xxx ATTRIBUTE_UNUSED) { char *name; char c; char *p; offsetT size; symbolS *symbolP; offsetT align; char *pfrag; int align2; segT current_seg = now_seg; subsegT current_subseg = now_subseg; name = input_line_pointer; c = get_symbol_end (); /* Just after name is now '\0'. */ p = input_line_pointer; *p = c; SKIP_WHITESPACE (); if (*input_line_pointer != ',') { as_bad (_("Expected comma after symbol-name: rest of line ignored.")); ignore_rest_of_line (); return; } input_line_pointer++; /* skip ',' */ if ((size = get_absolute_expression ()) < 0) { as_warn (_(".COMMon length (%ld.) <0! Ignored."), (long) size); ignore_rest_of_line (); return; } /* The third argument to .lcomm is the alignment. */ if (*input_line_pointer != ',') align = 8; else { ++input_line_pointer; align = get_absolute_expression (); if (align <= 0) { as_warn (_("ignoring bad alignment")); align = 8; } } *p = 0; symbolP = symbol_find_or_make (name); *p = c; if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP)) { as_bad (_("Ignoring attempt to re-define symbol `%s'."), S_GET_NAME (symbolP)); ignore_rest_of_line (); return; } if (S_GET_VALUE (symbolP) && S_GET_VALUE (symbolP) != (valueT) size) { as_bad (_("Length of .lcomm \"%s\" is already %ld. Not changed to %ld."), S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), (long) size); ignore_rest_of_line (); return; } /* Allocate_bss. */ if (align) { /* Convert to a power of 2 alignment. */ for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2); if (align != 1) { as_bad (_("Common alignment not a power of 2")); ignore_rest_of_line (); return; } } else
void obj_som_compiler (int unused ATTRIBUTE_UNUSED) { char *buf; char c; char *filename; char *language_name; char *p; char *version_id; if (compiler_seen) { as_bad (_("Only one .compiler pseudo-op per file!")); ignore_rest_of_line (); return; } SKIP_WHITESPACE (); if (*input_line_pointer == '\"') { buf = input_line_pointer; ++input_line_pointer; while (is_a_char (next_char_of_string ())) ; c = *input_line_pointer; *input_line_pointer = '\000'; } else { as_bad (_("Expected quoted string")); ignore_rest_of_line (); return; } /* Parse the quoted string into its component parts. Skip the quote. */ filename = buf + 1; p = filename; while (*p != ' ' && *p != '\000') p++; if (*p == '\000') { as_bad (_(".compiler directive missing language and version")); return; } *p = '\000'; language_name = ++p; while (*p != ' ' && *p != '\000') p++; if (*p == '\000') { as_bad (_(".compiler directive missing version")); return; } *p = '\000'; version_id = ++p; while (*p != '\000') p++; /* Remove the trailing quote. */ *(--p) = '\000'; compiler_seen = 1; if (! bfd_som_attach_compilation_unit (stdoutput, filename, language_name, "GNU Tools", version_id)) { bfd_perror (stdoutput->filename); as_fatal (_("FATAL: Attaching compiler header %s"), stdoutput->filename); } *input_line_pointer = c; demand_empty_rest_of_line (); }
static void dot_cfi_dummy (int ignored ATTRIBUTE_UNUSED) { as_bad (_("CFI is not supported for this target")); ignore_rest_of_line (); }
static void dot_cfi_val_encoded_addr (int ignored ATTRIBUTE_UNUSED) { struct cfi_insn_data *insn_ptr; offsetT encoding; if (frchain_now->frch_cfi_data == NULL) { as_bad (_("CFI instruction used without previous .cfi_startproc")); ignore_rest_of_line (); return; } /* If the last address was not at the current PC, advance to current. */ if (symbol_get_frag (frchain_now->frch_cfi_data->last_address) != frag_now || S_GET_VALUE (frchain_now->frch_cfi_data->last_address) != frag_now_fix ()) cfi_add_advance_loc (symbol_temp_new_now ()); insn_ptr = alloc_cfi_insn_data (); insn_ptr->insn = CFI_val_encoded_addr; insn_ptr->u.ea.reg = cfi_parse_reg (); cfi_parse_separator (); encoding = cfi_parse_const (); if ((encoding & 0xff) != encoding || ((encoding & 0x70) != 0 #if CFI_DIFF_EXPR_OK || defined tc_cfi_emit_pcrel_expr && (encoding & 0x70) != DW_EH_PE_pcrel #endif ) /* leb128 can be handled, but does something actually need it? */ || (encoding & 7) == DW_EH_PE_uleb128 || (encoding & 7) > DW_EH_PE_udata8) { as_bad (_("invalid or unsupported encoding in .cfi_lsda")); encoding = DW_EH_PE_omit; } cfi_parse_separator (); expression_and_evaluate (&insn_ptr->u.ea.exp); switch (insn_ptr->u.ea.exp.X_op) { case O_symbol: break; case O_constant: if ((encoding & 0x70) != DW_EH_PE_pcrel) break; default: encoding = DW_EH_PE_omit; break; } insn_ptr->u.ea.encoding = encoding; if (encoding == DW_EH_PE_omit) { as_bad (_("wrong third argument to .cfi_val_encoded_addr")); ignore_rest_of_line (); return; } demand_empty_rest_of_line (); }
/* Convert the instructions into frags and bytes */ void md_assemble(char *str) { char *op_start; char *op_end; char op_name[10]; const bexkat1_opc_info_t *opcode; char *p; char pend; unsigned int iword; int nlen = 0; int regnum; expressionS arg; int offset; while (*str == ' ') str++; // mark opcode op_start = str; for (op_end = str; *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' '; op_end++) nlen++; pend = *op_end; *op_end = 0; strncpy(op_name, op_start, 10); *op_end = pend; if (nlen == 0) as_bad(_("can't find opcode ")); while (ISSPACE(*op_end)) op_end++; opcode = (bexkat1_opc_info_t *) hash_find(opcode_hash_control, op_name); if (opcode == NULL) { as_bad(_("unknown opcode %s"), op_name); return; } iword = (opcode->type << 28) | (opcode->opcode << 24) | opcode->size; p = frag_more(4); switch (opcode->type) { case BEXKAT1_INH: if (opcode->args == 0) { md_number_to_chars(p, iword, 4); } if (opcode->args == 1) { op_end = parse_exp_save_ilp(op_end, &arg); if (opcode->size) { md_number_to_chars(p, iword, 4); p = frag_more(4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); } else { if (arg.X_op != O_constant) { as_bad(_("offset is not a constant expression")); ignore_rest_of_line(); return; } offset = arg.X_add_number; if (offset < -16384 || offset > 16383) { as_bad(_("offset is out of range: %d\n"), offset); ignore_rest_of_line(); return; } md_number_to_chars(p, iword, 4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_BEXKAT1_15); } } break; case BEXKAT1_PUSH: if (opcode->args == 1 && opcode->opcode == 2) // bsr goto branch; if (opcode->args == 1) { if (opcode->size) { op_end = parse_exp_save_ilp(op_end, &arg); md_number_to_chars(p, iword, 4); p = frag_more(4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); } else { regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A md_number_to_chars(p, iword, 4); } } if (opcode->args == 2) { if (*op_end != '(') op_end = parse_exp_save_ilp(op_end, &arg); else { // Implicit 0 offset to allow for indirect arg.X_op = O_constant; arg.X_add_number = 0; } if (*op_end != '(') { as_bad(_("missing open paren: %s"), op_end); ignore_rest_of_line(); return; } op_end++; // burn paren while (ISSPACE(*op_end)) op_end++; regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A if (*op_end != ')') { as_bad(_("missing close paren: %s"), op_end); ignore_rest_of_line(); return; } op_end++; if (arg.X_op != O_constant) { as_bad(_("offset is not a constant expression")); ignore_rest_of_line(); return; } offset = arg.X_add_number; if (offset < -16384 || offset > 16383) { as_bad(_("offset is out of range: %d\n"), offset); ignore_rest_of_line(); return; } md_number_to_chars(p, iword, 4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_BEXKAT1_15); } break; case BEXKAT1_POP: if (opcode->args == 0) { md_number_to_chars(p, iword, 4); } if (opcode->args == 1) { regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A md_number_to_chars(p, iword, 4); } break; case BEXKAT1_MOV: if (opcode->opcode == 0) { regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A md_number_to_chars(p, iword, 4); break; } /* __attribute__((fallthrough)); */ case BEXKAT1_CMP: case BEXKAT1_FPU: case BEXKAT1_FP: case BEXKAT1_ALU: case BEXKAT1_INT: case BEXKAT1_INTU: if (opcode->args > 1) { regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A if (*op_end != ',') { as_bad(_("missing comma: %s"), op_end); return; } op_end++; while (ISSPACE(*op_end)) op_end++; } regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 16; // B if (opcode->args > 2) { if (*op_end != ',') { as_bad(_("missing comma: %s"), op_end); return; } op_end++; while (ISSPACE(*op_end)) op_end++; if (opcode->opcode < 8) { regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 12; // C md_number_to_chars(p, iword, 4); } else { op_end = parse_exp_save_ilp(op_end, &arg); if (arg.X_op != O_constant) { as_bad(_("offset is not a constant expression")); ignore_rest_of_line(); return; } offset = arg.X_add_number; if (offset < -16384 || offset > 16383) { as_bad(_("offset is out of range: %d\n"), offset); ignore_rest_of_line(); return; } md_number_to_chars(p, iword, 4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_BEXKAT1_15); } } else { md_number_to_chars(p, iword, 4); } break; branch: case BEXKAT1_BRANCH: md_number_to_chars(p, iword, 4); op_end = parse_exp_save_ilp(op_end, &arg); if (target_big_endian) fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, TRUE, BFD_RELOC_BEXKAT1_15_PCREL); else fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, TRUE, BFD_RELOC_BEXKAT1_15_PCREL); break; case BEXKAT1_LOAD: case BEXKAT1_STORE: // A, regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A if (*op_end != ',') { as_bad(_("missing comma: %s"), op_end); return; } op_end++; while (ISSPACE(*op_end)) op_end++; /* __attribute__((fallthrough)); */ case BEXKAT1_JUMP: if (opcode->size) { // big address md_number_to_chars(p, iword, 4); op_end = parse_exp_save_ilp(op_end, &arg); p = frag_more(4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); } else { // exp(B) if (*op_end != '(') op_end = parse_exp_save_ilp(op_end, &arg); else { // Implicit 0 offset to allow for indirect arg.X_op = O_constant; arg.X_add_number = 0; } if (*op_end != '(') { as_bad(_("missing open paren: %s"), op_end); ignore_rest_of_line(); return; } op_end++; // burn paren while (ISSPACE(*op_end)) op_end++; regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 16; // B if (*op_end != ')') { as_bad(_("missing close paren: %s"), op_end); ignore_rest_of_line(); return; } op_end++; if (arg.X_op != O_constant) { as_bad(_("offset is not a constant expression")); ignore_rest_of_line(); return; } offset = arg.X_add_number; if (offset < -16384 || offset > 16383) { as_bad(_("offset is out of range: %d\n"), offset); ignore_rest_of_line(); return; } md_number_to_chars(p, iword, 4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_BEXKAT1_15); } break; case BEXKAT1_LDI: regnum = parse_regnum(&op_end); if (regnum == -1) return; while (ISSPACE(*op_end)) op_end++; iword |= (regnum & 0xf) << 20; // A if (*op_end != ',') { as_bad(_("missing comma: %s"), op_end); return; } op_end++; while (ISSPACE(*op_end)) op_end++; op_end = parse_exp_save_ilp(op_end, &arg); if (opcode->size) { md_number_to_chars(p, iword, 4); p = frag_more(4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); } else { if (arg.X_op != O_constant) { as_bad(_("offset is not a constant expression")); ignore_rest_of_line(); return; } offset = arg.X_add_number; if (offset >= 32768) { as_bad(_("offset is out of range: %d\n"), offset); ignore_rest_of_line(); return; } md_number_to_chars(p, iword, 4); fix_new_exp(frag_now, (p - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_BEXKAT1_15); } break; } while (ISSPACE(*op_end)) op_end++; if (*op_end != 0) as_warn("extra stuff on line ignored %s %c", op_start, *op_end); if (pending_reloc) as_bad("Something forgot to clean up\n"); return; }
void md_assemble (char *str) { char *op_start; char *op_end; moxie_opc_info_t *opcode; char *p; char pend; unsigned short iword = 0; int nlen = 0; /* Drop leading whitespace. */ while (*str == ' ') str++; /* Find the op code end. */ op_start = str; for (op_end = str; *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' '; op_end++) nlen++; pend = *op_end; *op_end = 0; if (nlen == 0) as_bad (_("can't find opcode ")); opcode = (moxie_opc_info_t *) hash_find (opcode_hash_control, op_start); *op_end = pend; if (opcode == NULL) { as_bad (_("unknown opcode %s"), op_start); return; } p = frag_more (2); switch (opcode->itype) { case MOXIE_F2_A8V: iword = (1<<15) | (opcode->opcode << 12); while (ISSPACE (*op_end)) op_end++; { expressionS arg; int reg; reg = parse_register_operand (&op_end); iword += (reg << 8); if (*op_end != ',') as_warn (_("expecting comma delimited register operands")); op_end++; op_end = parse_exp_save_ilp (op_end, &arg); fix_new_exp (frag_now, ((p + (target_big_endian ? 1 : 0)) - frag_now->fr_literal), 1, &arg, 0, BFD_RELOC_8); } break; case MOXIE_F1_AB: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { int dest, src; dest = parse_register_operand (&op_end); if (*op_end != ',') as_warn (_("expecting comma delimited register operands")); op_end++; src = parse_register_operand (&op_end); iword += (dest << 4) + src; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); } break; case MOXIE_F1_A4: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { expressionS arg; char *where; int regnum; regnum = parse_register_operand (&op_end); while (ISSPACE (*op_end)) op_end++; iword += (regnum << 4); if (*op_end != ',') { as_bad (_("expecting comma delimited operands")); ignore_rest_of_line (); return; } op_end++; op_end = parse_exp_save_ilp (op_end, &arg); where = frag_more (4); fix_new_exp (frag_now, (where - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); } break; case MOXIE_F1_M: case MOXIE_F1_4: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { expressionS arg; char *where; op_end = parse_exp_save_ilp (op_end, &arg); where = frag_more (4); fix_new_exp (frag_now, (where - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); } break; case MOXIE_F1_NARG: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); break; case MOXIE_F1_A: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { int reg; reg = parse_register_operand (&op_end); while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); iword += (reg << 4); } break; case MOXIE_F1_ABi: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { int a, b; a = parse_register_operand (&op_end); if (*op_end != ',') as_warn (_("expecting comma delimited register operands")); op_end++; if (*op_end != '(') { as_bad (_("expecting indirect register `($rA)'")); ignore_rest_of_line (); return; } op_end++; b = parse_register_operand (&op_end); if (*op_end != ')') { as_bad (_("missing closing parenthesis")); ignore_rest_of_line (); return; } op_end++; iword += (a << 4) + b; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); } break; case MOXIE_F1_AiB: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { int a, b; if (*op_end != '(') { as_bad (_("expecting indirect register `($rA)'")); ignore_rest_of_line (); return; } op_end++; a = parse_register_operand (&op_end); if (*op_end != ')') { as_bad (_("missing closing parenthesis")); ignore_rest_of_line (); return; } op_end++; if (*op_end != ',') as_warn (_("expecting comma delimited register operands")); op_end++; b = parse_register_operand (&op_end); iword += (a << 4) + b; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); } break; case MOXIE_F1_4A: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { expressionS arg; char *where; int a; op_end = parse_exp_save_ilp (op_end, &arg); where = frag_more (4); fix_new_exp (frag_now, (where - frag_now->fr_literal), 4, &arg, 0, BFD_RELOC_32); if (*op_end != ',') { as_bad (_("expecting comma delimited operands")); ignore_rest_of_line (); return; } op_end++; a = parse_register_operand (&op_end); while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); iword += (a << 4); } break; case MOXIE_F1_ABi2: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { expressionS arg; char *offset; int a, b; a = parse_register_operand (&op_end); while (ISSPACE (*op_end)) op_end++; if (*op_end != ',') { as_bad (_("expecting comma delimited operands")); ignore_rest_of_line (); return; } op_end++; op_end = parse_exp_save_ilp (op_end, &arg); offset = frag_more (2); fix_new_exp (frag_now, (offset - frag_now->fr_literal), 2, &arg, 0, BFD_RELOC_16); if (*op_end != '(') { as_bad (_("expecting indirect register `($rX)'")); ignore_rest_of_line (); return; } op_end++; b = parse_register_operand (&op_end); if (*op_end != ')') { as_bad (_("missing closing parenthesis")); ignore_rest_of_line (); return; } op_end++; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); iword += (a << 4) + b; } break; case MOXIE_F1_AiB2: iword = opcode->opcode << 8; while (ISSPACE (*op_end)) op_end++; { expressionS arg; char *offset; int a, b; op_end = parse_exp_save_ilp (op_end, &arg); offset = frag_more (2); fix_new_exp (frag_now, (offset - frag_now->fr_literal), 2, &arg, 0, BFD_RELOC_16); if (*op_end != '(') { as_bad (_("expecting indirect register `($rX)'")); ignore_rest_of_line (); return; } op_end++; a = parse_register_operand (&op_end); if (*op_end != ')') { as_bad (_("missing closing parenthesis")); ignore_rest_of_line (); return; } op_end++; if (*op_end != ',') { as_bad (_("expecting comma delimited operands")); ignore_rest_of_line (); return; } op_end++; b = parse_register_operand (&op_end); while (ISSPACE (*op_end)) op_end++; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); iword += (a << 4) + b; } break; case MOXIE_F2_NARG: iword = opcode->opcode << 12; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); break; case MOXIE_F3_PCREL: iword = (3<<14) | (opcode->opcode << 10); while (ISSPACE (*op_end)) op_end++; { expressionS arg; op_end = parse_exp_save_ilp (op_end, &arg); fix_new_exp (frag_now, (p - frag_now->fr_literal), 2, &arg, TRUE, BFD_RELOC_MOXIE_10_PCREL); } break; default: abort (); } md_number_to_chars (p, iword, 2); while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); if (pending_reloc) as_bad (_("Something forgot to clean up\n")); }