📄 tc-mips.c
字号:
{"stabn", s_mips_stab, 'n'}, {"text", s_change_sec, 't'}, {"word", s_cons, 2},#ifdef MIPS_STABS_ELF { "extern", ecoff_directive_extern, 0},#endif { NULL, NULL, 0 },};static const pseudo_typeS mips_nonecoff_pseudo_table[] ={ /* These pseudo-ops should be defined by the object file format. However, a.out doesn't support them, so we have versions here. */ {"aent", s_mips_ent, 1}, {"bgnb", s_ignore, 0}, {"end", s_mips_end, 0}, {"endb", s_ignore, 0}, {"ent", s_mips_ent, 0}, {"file", s_file, 0}, {"fmask", s_mips_mask, 'F'}, {"frame", s_mips_frame, 0}, {"loc", s_ignore, 0}, {"mask", s_mips_mask, 'R'}, {"verstamp", s_ignore, 0}, { NULL, NULL, 0 },};extern void pop_insert PARAMS ((const pseudo_typeS *));voidmips_pop_insert (){ pop_insert (mips_pseudo_table); if (! ECOFF_DEBUGGING) pop_insert (mips_nonecoff_pseudo_table);}/* Symbols labelling the current insn. */struct insn_label_list{ struct insn_label_list *next; symbolS *label;};static struct insn_label_list *insn_labels;static struct insn_label_list *free_insn_labels;static void mips_clear_insn_labels PARAMS ((void));static inline voidmips_clear_insn_labels (){ register struct insn_label_list **pl; for (pl = &free_insn_labels; *pl != NULL; pl = &(*pl)->next) ; *pl = insn_labels; insn_labels = NULL;}static char *expr_end;/* Expressions which appear in instructions. These are set by mips_ip. */static expressionS imm_expr;static expressionS offset_expr;/* Relocs associated with imm_expr and offset_expr. */static bfd_reloc_code_real_type imm_reloc;static bfd_reloc_code_real_type offset_reloc;/* This is set by mips_ip if imm_reloc is an unmatched HI16_S reloc. */static boolean imm_unmatched_hi;/* These are set by mips16_ip if an explicit extension is used. */static boolean mips16_small, mips16_ext;#ifdef MIPS_STABS_ELF/* The pdr segment for per procedure frame/regmask info */static segT pdr_seg;#endifstatic const char *mips_isa_to_str (isa) int isa;{ const struct mips_cpu_info *ci; static char s[20]; ci = mips_cpu_info_from_isa (isa); if (ci != NULL) return (ci->name); sprintf (s, "ISA#%d", isa); return s;}static const char *mips_cpu_to_str (cpu) int cpu;{ const struct mips_cpu_info *ci; static char s[16]; ci = mips_cpu_info_from_cpu (cpu); if (ci != NULL) return (ci->name); sprintf (s, "CPU#%d", cpu); return s;}/* This function is called once, at assembler startup time. It should set up all the tables, etc. that the MD part of the assembler will need. */voidmd_begin (){ register const char *retval = NULL; int i = 0; const char *cpu; char *a = NULL; int broken = 0; int mips_isa_from_cpu; int target_cpu_had_mips16 = 0; const struct mips_cpu_info *ci; /* GP relative stuff not working for PE */ if (strncmp (TARGET_OS, "pe", 2) == 0 && g_switch_value != 0) { if (g_switch_seen) as_bad (_("-G not supported in this configuration.")); g_switch_value = 0; } cpu = TARGET_CPU; if (strcmp (cpu + (sizeof TARGET_CPU) - 3, "el") == 0) { a = xmalloc (sizeof TARGET_CPU); strcpy (a, TARGET_CPU); a[(sizeof TARGET_CPU) - 3] = '\0'; cpu = a; } if (strncmp (cpu, "mips16", sizeof "mips16" - 1) == 0) { target_cpu_had_mips16 = 1; cpu += sizeof "mips16" - 1; } if (mips_opts.mips16 < 0) mips_opts.mips16 = target_cpu_had_mips16; /* At this point, mips_cpu will either be CPU_UNKNOWN if no CPU was specified on the command line, or some other value if one was. Similarly, mips_opts.isa will be ISA_UNKNOWN if not specified on the command line, or will be set otherwise if one was. */ if (mips_cpu != CPU_UNKNOWN && mips_opts.isa != ISA_UNKNOWN) { /* We have it all. There's nothing to do. */ } else if (mips_cpu != CPU_UNKNOWN && mips_opts.isa == ISA_UNKNOWN) { /* We have CPU, we need ISA. */ ci = mips_cpu_info_from_cpu (mips_cpu); assert (ci != NULL); mips_opts.isa = ci->isa; } else if (mips_cpu == CPU_UNKNOWN && mips_opts.isa != ISA_UNKNOWN) { /* We have ISA, we need default CPU. */ ci = mips_cpu_info_from_isa (mips_opts.isa); assert (ci != NULL); mips_cpu = ci->cpu; } else { /* We need to set both ISA and CPU from target cpu. */ ci = mips_cpu_info_from_name (cpu); if (ci == NULL) ci = mips_cpu_info_from_cpu (CPU_R3000); assert (ci != NULL); mips_opts.isa = ci->isa; mips_cpu = ci->cpu; } ci = mips_cpu_info_from_cpu (mips_cpu); assert (ci != NULL); mips_isa_from_cpu = ci->isa; /* End of TARGET_CPU processing, get rid of malloced memory if necessary. */ cpu = NULL; if (a != NULL) { free (a); a = NULL; } if (mips_opts.isa == ISA_MIPS1 && mips_trap) as_bad (_("trap exception not supported at ISA 1")); /* Set the EABI kind based on the ISA before the user gets to change the ISA with directives. This isn't really the best, but then neither is basing the abi on the isa. */ if (ISA_HAS_64BIT_REGS (mips_opts.isa) && mips_abi_string && 0 == strcmp (mips_abi_string, "eabi")) mips_eabi64 = 1; /* If they asked for mips1 or mips2 and a cpu that is mips3 or greater, then mark the object file 32BITMODE. */ if (mips_isa_from_cpu != ISA_UNKNOWN && ! ISA_HAS_64BIT_REGS (mips_opts.isa) && ISA_HAS_64BIT_REGS (mips_isa_from_cpu)) mips_32bitmode = 1; if (! bfd_set_arch_mach (stdoutput, bfd_arch_mips, mips_cpu)) as_warn (_("Could not set architecture and machine")); file_mips_isa = mips_opts.isa; op_hash = hash_new (); for (i = 0; i < NUMOPCODES;) { const char *name = mips_opcodes[i].name; retval = hash_insert (op_hash, name, (PTR) &mips_opcodes[i]); if (retval != NULL) { fprintf (stderr, _("internal error: can't hash `%s': %s\n"), mips_opcodes[i].name, retval); /* Probably a memory allocation problem? Give up now. */ as_fatal (_("Broken assembler. No assembly attempted.")); } do { if (mips_opcodes[i].pinfo != INSN_MACRO) { if (!validate_mips_insn (&mips_opcodes[i])) broken = 1; } ++i; } while ((i < NUMOPCODES) && !strcmp (mips_opcodes[i].name, name)); } mips16_op_hash = hash_new (); i = 0; while (i < bfd_mips16_num_opcodes) { const char *name = mips16_opcodes[i].name; retval = hash_insert (mips16_op_hash, name, (PTR) &mips16_opcodes[i]); if (retval != NULL) as_fatal (_("internal: can't hash `%s': %s"), mips16_opcodes[i].name, retval); do { if (mips16_opcodes[i].pinfo != INSN_MACRO && ((mips16_opcodes[i].match & mips16_opcodes[i].mask) != mips16_opcodes[i].match)) { fprintf (stderr, _("internal error: bad mips16 opcode: %s %s\n"), mips16_opcodes[i].name, mips16_opcodes[i].args); broken = 1; } ++i; } while (i < bfd_mips16_num_opcodes && strcmp (mips16_opcodes[i].name, name) == 0); } if (broken) as_fatal (_("Broken assembler. No assembly attempted.")); /* We add all the general register names to the symbol table. This helps us detect invalid uses of them. */ for (i = 0; i < 32; i++) { char buf[5]; sprintf (buf, "$%d", i); symbol_table_insert (symbol_new (buf, reg_section, i, &zero_address_frag)); } symbol_table_insert (symbol_new ("$fp", reg_section, FP, &zero_address_frag)); symbol_table_insert (symbol_new ("$sp", reg_section, SP, &zero_address_frag)); symbol_table_insert (symbol_new ("$gp", reg_section, GP, &zero_address_frag)); symbol_table_insert (symbol_new ("$at", reg_section, AT, &zero_address_frag)); symbol_table_insert (symbol_new ("$kt0", reg_section, KT0, &zero_address_frag)); symbol_table_insert (symbol_new ("$kt1", reg_section, KT1, &zero_address_frag)); symbol_table_insert (symbol_new ("$pc", reg_section, -1, &zero_address_frag)); mips_no_prev_insn (false); mips_gprmask = 0; mips_cprmask[0] = 0; mips_cprmask[1] = 0; mips_cprmask[2] = 0; mips_cprmask[3] = 0; /* set the default alignment for the text section (2**2) */ record_alignment (text_section, 2); if (USE_GLOBAL_POINTER_OPT) bfd_set_gp_size (stdoutput, g_switch_value); if (OUTPUT_FLAVOR == bfd_target_elf_flavour) { /* On a native system, sections must be aligned to 16 byte boundaries. When configured for an embedded ELF target, we don't bother. */ if (strcmp (TARGET_OS, "elf") != 0) { (void) bfd_set_section_alignment (stdoutput, text_section, 4); (void) bfd_set_section_alignment (stdoutput, data_section, 4); (void) bfd_set_section_alignment (stdoutput, bss_section, 4); } /* Create a .reginfo section for register masks and a .mdebug section for debugging information. */ { segT seg; subsegT subseg; flagword flags; segT sec; seg = now_seg; subseg = now_subseg; /* The ABI says this section should be loaded so that the running program can access it. However, we don't load it if we are configured for an embedded target */ flags = SEC_READONLY | SEC_DATA; if (strcmp (TARGET_OS, "elf") != 0) flags |= SEC_ALLOC | SEC_LOAD; if (! mips_64) { sec = subseg_new (".reginfo", (subsegT) 0); (void) bfd_set_section_flags (stdoutput, sec, flags); (void) bfd_set_section_alignment (stdoutput, sec, 2);#ifdef OBJ_ELF mips_regmask_frag = frag_more (sizeof (Elf32_External_RegInfo));#endif } else { /* The 64-bit ABI uses a .MIPS.options section rather than .reginfo section. */ sec = subseg_new (".MIPS.options", (subsegT) 0); (void) bfd_set_section_flags (stdoutput, sec, flags); (void) bfd_set_section_alignment (stdoutput, sec, 3);#ifdef OBJ_ELF /* Set up the option header. */ { Elf_Internal_Options opthdr; char *f; opthdr.kind = ODK_REGINFO; opthdr.size = (sizeof (Elf_External_Options) + sizeof (Elf64_External_RegInfo)); opthdr.section = 0; opthdr.info = 0; f = frag_more (sizeof (Elf_External_Options)); bfd_mips_elf_swap_options_out (stdoutput, &opthdr, (Elf_External_Options *) f); mips_regmask_frag = frag_more (sizeof (Elf64_External_RegInfo)); }#endif } if (ECOFF_DEBUGGING)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -