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; case MOXIE_BAD: iword = 0; while (ISSPACE (*op_end)) op_end++; if (*op_end != 0) as_warn (_("extra stuff on line ignored")); break; default: abort (); } md_number_to_chars (p, iword, 2); dwarf2_emit_insn (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")); }
void dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED) { offsetT filenum, line; /* If we see two .loc directives in a row, force the first one to be output now. */ if (dwarf2_loc_directive_seen) dwarf2_emit_insn (0); filenum = get_absolute_expression (); SKIP_WHITESPACE (); line = get_absolute_expression (); if (filenum < 1) { as_bad (_("file number less than one")); return; } if (filenum >= (int) files_in_use || files[filenum].filename == 0) { as_bad (_("unassigned file number %ld"), (long) filenum); return; } current.filenum = filenum; current.line = line; current.discriminator = 0; #ifndef NO_LISTING if (listing) { if (files[filenum].dir) { size_t dir_len = strlen (dirs[files[filenum].dir]); size_t file_len = strlen (files[filenum].filename); char *cp = (char *) alloca (dir_len + 1 + file_len + 1); memcpy (cp, dirs[files[filenum].dir], dir_len); INSERT_DIR_SEPARATOR (cp, dir_len); memcpy (cp + dir_len + 1, files[filenum].filename, file_len); cp[dir_len + file_len + 1] = '\0'; listing_source_file (cp); } else listing_source_file (files[filenum].filename); listing_source_line (line); } #endif SKIP_WHITESPACE (); if (ISDIGIT (*input_line_pointer)) { current.column = get_absolute_expression (); SKIP_WHITESPACE (); } while (ISALPHA (*input_line_pointer)) { char *p, c; offsetT value; p = input_line_pointer; c = get_symbol_end (); if (strcmp (p, "basic_block") == 0) { current.flags |= DWARF2_FLAG_BASIC_BLOCK; *input_line_pointer = c; } else if (strcmp (p, "prologue_end") == 0) { current.flags |= DWARF2_FLAG_PROLOGUE_END; *input_line_pointer = c; } else if (strcmp (p, "epilogue_begin") == 0) { current.flags |= DWARF2_FLAG_EPILOGUE_BEGIN; *input_line_pointer = c; } else if (strcmp (p, "is_stmt") == 0) { *input_line_pointer = c; value = get_absolute_expression (); if (value == 0) current.flags &= ~DWARF2_FLAG_IS_STMT; else if (value == 1) current.flags |= DWARF2_FLAG_IS_STMT; else { as_bad (_("is_stmt value not 0 or 1")); return; } } else if (strcmp (p, "isa") == 0) { *input_line_pointer = c; value = get_absolute_expression (); if (value >= 0) current.isa = value; else { as_bad (_("isa number less than zero")); return; } } else if (strcmp (p, "discriminator") == 0) { *input_line_pointer = c; value = get_absolute_expression (); if (value >= 0) current.discriminator = value; else { as_bad (_("discriminator less than zero")); return; } } else { as_bad (_("unknown .loc sub-directive `%s'"), p); *input_line_pointer = c; return; } SKIP_WHITESPACE (); } demand_empty_rest_of_line (); dwarf2_loc_directive_seen = TRUE; debug_type = DEBUG_NONE; }
void md_assemble (char * str) { static long delayed_load_register = 0; static long prev_delayed_load_register = 0; static int last_insn_had_delay_slot = 0; static int last_insn_in_noncond_delay_slot = 0; static int last_insn_has_load_delay = 0; static int last_insn_was_memory_access = 0; static int last_insn_was_io_insn = 0; static int last_insn_was_arithmetic_or_logic = 0; static int last_insn_was_branch_insn = 0; static int last_insn_was_conditional_branch_insn = 0; mt_insn insn; char * errmsg; /* Initialize GAS's cgen interface for a new instruction. */ gas_cgen_init_parse (); insn.insn = mt_cgen_assemble_insn (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg); if (!insn.insn) { as_bad ("%s", errmsg); return; } /* Doesn't really matter what we pass for RELAX_P here. */ gas_cgen_finish_insn (insn.insn, insn.buffer, CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL); /* Handle Scheduling Restrictions. */ if (!no_scheduling_restrictions) { /* Detect consecutive Memory Accesses. */ if (last_insn_was_memory_access && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MEMORY_ACCESS) && mt_mach == ms1_64_001) as_warn (_("instruction %s may not follow another memory access instruction."), CGEN_INSN_NAME (insn.insn)); /* Detect consecutive I/O Instructions. */ else if (last_insn_was_io_insn && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_IO_INSN)) as_warn (_("instruction %s may not follow another I/O instruction."), CGEN_INSN_NAME (insn.insn)); /* Detect consecutive branch instructions. */ else if (last_insn_was_branch_insn && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN)) as_warn (_("%s may not occupy the delay slot of another branch insn."), CGEN_INSN_NAME (insn.insn)); /* Detect data dependencies on delayed loads: memory and input insns. */ if (last_insn_has_load_delay && delayed_load_register) { if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1) && insn.fields.f_sr1 == delayed_load_register) as_warn (_("operand references R%ld of previous load."), insn.fields.f_sr1); if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2) && insn.fields.f_sr2 == delayed_load_register) as_warn (_("operand references R%ld of previous load."), insn.fields.f_sr2); } /* Detect JAL/RETI hazard */ if (mt_mach == ms2 && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_JAL_HAZARD)) { if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1) && insn.fields.f_sr1 == delayed_load_register) || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2) && insn.fields.f_sr2 == delayed_load_register)) as_warn (_("operand references R%ld of previous instruction."), delayed_load_register); else if ((CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1) && insn.fields.f_sr1 == prev_delayed_load_register) || (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2) && insn.fields.f_sr2 == prev_delayed_load_register)) as_warn (_("operand references R%ld of instruction before previous."), prev_delayed_load_register); } /* Detect data dependency between conditional branch instruction and an immediately preceding arithmetic or logical instruction. */ if (last_insn_was_arithmetic_or_logic && !last_insn_in_noncond_delay_slot && (delayed_load_register != 0) && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN) && mt_arch == ms1_64_001) { if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR1) && insn.fields.f_sr1 == delayed_load_register) as_warn (_("conditional branch or jal insn's operand references R%ld of previous arithmetic or logic insn."), insn.fields.f_sr1); if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2) && insn.fields.f_sr2 == delayed_load_register) as_warn (_("conditional branch or jal insn's operand references R%ld of previous arithmetic or logic insn."), insn.fields.f_sr2); } } /* Keep track of details of this insn for processing next insn. */ last_insn_in_noncond_delay_slot = last_insn_was_branch_insn && !last_insn_was_conditional_branch_insn; last_insn_had_delay_slot = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_DELAY_SLOT); (void) last_insn_had_delay_slot; last_insn_has_load_delay = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_LOAD_DELAY); last_insn_was_memory_access = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_MEMORY_ACCESS); last_insn_was_io_insn = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_IO_INSN); last_insn_was_arithmetic_or_logic = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_AL_INSN); last_insn_was_branch_insn = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN); last_insn_was_conditional_branch_insn = CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_BR_INSN) && CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRSR2); prev_delayed_load_register = delayed_load_register; if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRDR)) delayed_load_register = insn.fields.f_dr; else if (CGEN_INSN_ATTR_VALUE (insn.insn, CGEN_INSN_USES_FRDRRR)) delayed_load_register = insn.fields.f_drrr; else /* Insns has no destination register. */ delayed_load_register = 0; /* Generate dwarf2 line numbers. */ dwarf2_emit_insn (4); }