X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-ppc.c;h=5849654837a318f3b8a8b89323d4404219f9acc4;hb=b256d4fdd25ed91f9d5edcdd23d3558b4cbca71b;hp=a91420af0870a0732f6fa06b95b35999cca856e9;hpb=adadcc0cc96a9373f7dfb9b7ca3c57d630872730;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index a91420af08..5849654837 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -24,7 +24,7 @@ #include "as.h" #include "safe-ctype.h" #include "subsegs.h" - +#include "dw2gencfi.h" #include "opcode/ppc.h" #ifdef OBJ_ELF @@ -111,7 +111,7 @@ static void ppc_ec PARAMS ((int)); static void ppc_ef PARAMS ((int)); static void ppc_es PARAMS ((int)); static void ppc_csect PARAMS ((int)); -static void ppc_change_csect PARAMS ((symbolS *)); +static void ppc_change_csect PARAMS ((symbolS *, offsetT)); static void ppc_function PARAMS ((int)); static void ppc_extern PARAMS ((int)); static void ppc_lglobl PARAMS ((int)); @@ -186,6 +186,9 @@ const char FLT_CHARS[] = "dD"; /* '+' and '-' can be used as postfix predicate predictors for conditional branches. So they need to be accepted as symbol characters. */ const char ppc_symbol_chars[] = "+-"; + +/* The dwarf2 data alignment, adjusted for 32 or 64 bit. */ +int ppc_cie_data_alignment; /* The target specific pseudo-ops which we support. */ @@ -907,6 +910,9 @@ md_parse_option (c, arg) || strcmp (arg, "405") == 0) ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_403 | PPC_OPCODE_32); + else if (strcmp (arg, "440") == 0) + ppc_cpu = (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32 + | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI); else if (strcmp (arg, "7400") == 0 || strcmp (arg, "7410") == 0 || strcmp (arg, "7450") == 0 @@ -968,7 +974,7 @@ md_parse_option (c, arg) ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32; /* -many means to assemble for any architecture (PWR/PWRX/PPC). */ else if (strcmp (arg, "any") == 0) - ppc_cpu = PPC_OPCODE_ANY | PPC_OPCODE_32; + ppc_cpu |= PPC_OPCODE_ANY; else if (strcmp (arg, "regnames") == 0) reg_names_p = TRUE; @@ -1071,6 +1077,7 @@ PowerPC options:\n\ -mppc, -mppc32, -m603, -m604\n\ generate code for PowerPC 603/604\n\ -m403, -m405 generate code for PowerPC 403/405\n\ +-m440 generate code for PowerPC 440\n\ -m7400, -m7410, -m7450, -m7455\n\ generate code For PowerPC 7400/7410/7450/7455\n")); fprintf (stream, _("\ @@ -1111,23 +1118,23 @@ ppc_set_cpu () const char *default_os = TARGET_OS; const char *default_cpu = TARGET_CPU; - if (ppc_cpu == 0) + if ((ppc_cpu & ~PPC_OPCODE_ANY) == 0) { if (ppc_obj64) - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64; + ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64; else if (strncmp (default_os, "aix", 3) == 0 && default_os[3] >= '4' && default_os[3] <= '9') - ppc_cpu = PPC_OPCODE_COMMON | PPC_OPCODE_32; + ppc_cpu |= PPC_OPCODE_COMMON | PPC_OPCODE_32; else if (strncmp (default_os, "aix3", 4) == 0) - ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32; + ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32; else if (strcmp (default_cpu, "rs6000") == 0) - ppc_cpu = PPC_OPCODE_POWER | PPC_OPCODE_32; + ppc_cpu |= PPC_OPCODE_POWER | PPC_OPCODE_32; else if (strncmp (default_cpu, "powerpc", 7) == 0) { if (default_cpu[7] == '6' && default_cpu[8] == '4') - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64; + ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64; else - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32; + ppc_cpu |= PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32; } else as_fatal (_("Unknown default cpu = %s, os = %s"), @@ -1208,6 +1215,8 @@ md_begin () ppc_set_cpu (); + ppc_cie_data_alignment = ppc_obj64 ? -8 : -4; + #ifdef OBJ_ELF /* Set the ELF flags if desired. */ if (ppc_flags && !msolaris) @@ -1256,6 +1265,10 @@ md_begin () } } + if ((ppc_cpu & PPC_OPCODE_ANY) != 0) + for (op = powerpc_opcodes; op < op_end; op++) + hash_insert (ppc_hash, op->name, (PTR) op); + /* Insert the macros into a hash table. */ ppc_macro_hash = hash_new (); @@ -1342,7 +1355,7 @@ ppc_cleanup () md_number_to_chars (p, (valueT) 8, 4); p = frag_more (4); - md_number_to_chars (p, (valueT) ppc_apuinfo_num, 4); + md_number_to_chars (p, (valueT) ppc_apuinfo_num * 4, 4); p = frag_more (4); md_number_to_chars (p, (valueT) 2, 4); @@ -1613,11 +1626,11 @@ ppc_elf_suffix (str_p, exp_p) *str_p = str; if (reloc == (int) BFD_RELOC_PPC64_TOC - && exp_p->X_op == O_symbol) + && exp_p->X_op == O_symbol + && strcmp (S_GET_NAME (exp_p->X_add_symbol), ".TOC.") == 0) { - /* This reloc type ignores the symbol. Change the symbol - so that the dummy .TOC. symbol can be omitted from the - object file. */ + /* Change the symbol so that the dummy .TOC. symbol can be + omitted from the object file. */ exp_p->X_add_symbol = &abs_symbol; } @@ -3006,6 +3019,7 @@ ppc_csect (ignore) char *name; char endc; symbolS *sym; + offsetT align; name = input_line_pointer; endc = get_symbol_end (); @@ -3020,22 +3034,24 @@ ppc_csect (ignore) symbol_get_tc (sym)->class = XMC_PR; } - ppc_change_csect (sym); - + align = 2; if (*input_line_pointer == ',') { ++input_line_pointer; - symbol_get_tc (sym)->align = get_absolute_expression (); + align = get_absolute_expression (); } + ppc_change_csect (sym, align); + demand_empty_rest_of_line (); } /* Change to a different csect. */ static void -ppc_change_csect (sym) +ppc_change_csect (sym, align) symbolS *sym; + offsetT align; { if (S_IS_DEFINED (sym)) subseg_set (S_GET_SEGMENT (sym), symbol_get_tc (sym)->subseg); @@ -3045,11 +3061,14 @@ ppc_change_csect (sym) int after_toc; int hold_chunksize; symbolS *list; + int is_code; + segT sec; /* This is a new csect. We need to look at the symbol class to figure out whether it should go in the text section or the data section. */ after_toc = 0; + is_code = 0; switch (symbol_get_tc (sym)->class) { case XMC_PR: @@ -3064,6 +3083,7 @@ ppc_change_csect (sym) symbol_get_tc (sym)->subseg = ppc_text_subsegment; ++ppc_text_subsegment; list_ptr = &ppc_text_csects; + is_code = 1; break; case XMC_RW: case XMC_TC0: @@ -3091,18 +3111,24 @@ ppc_change_csect (sym) hold_chunksize = chunksize; chunksize = 64; - subseg_new (segment_name (S_GET_SEGMENT (sym)), - symbol_get_tc (sym)->subseg); + sec = subseg_new (segment_name (S_GET_SEGMENT (sym)), + symbol_get_tc (sym)->subseg); chunksize = hold_chunksize; if (after_toc) ppc_after_toc_frag = frag_now; + record_alignment (sec, align); + if (is_code) + frag_align_code (align, 0); + else + frag_align (align, 0, 0); + symbol_set_frag (sym, frag_now); S_SET_VALUE (sym, (valueT) frag_now_fix ()); - symbol_get_tc (sym)->align = 2; + symbol_get_tc (sym)->align = align; symbol_get_tc (sym)->output = 1; symbol_get_tc (sym)->within = sym; @@ -3140,7 +3166,7 @@ ppc_section (type) sym = symbol_find_or_make (name); - ppc_change_csect (sym); + ppc_change_csect (sym, 2); demand_empty_rest_of_line (); } @@ -3177,7 +3203,7 @@ ppc_named_section (ignore) sym = symbol_find_or_make (real_name); - ppc_change_csect (sym); + ppc_change_csect (sym, 2); demand_empty_rest_of_line (); } @@ -3848,7 +3874,7 @@ ppc_vbyte (dummy) give to this location in the toc; this will be a symbol with class TC. The rest of the arguments are N-byte values to actually put at this location in the TOC; often there is just one more argument, a - relocateable symbol reference. The size of the value to store + relocatable symbol reference. The size of the value to store depends on target word size. A 32-bit target uses 4-byte values, a 64-bit target uses 8-byte values. @@ -5047,8 +5073,9 @@ void ppc_frob_section (sec) asection *sec; { - static bfd_size_type vma = 0; + static bfd_vma vma = 0; + vma = md_section_align (sec, vma); bfd_set_section_vma (stdoutput, sec, vma); vma += bfd_section_size (stdoutput, sec); } @@ -5714,7 +5741,7 @@ md_apply_fix3 (fixP, valP, seg) abort (); { unsigned char *where = fixP->fx_frag->fr_literal + fixP->fx_where; - long val, mask; + unsigned long val, mask; if (target_big_endian) val = bfd_getb32 (where - 2); @@ -5723,7 +5750,7 @@ md_apply_fix3 (fixP, valP, seg) mask = 0xfffc; /* lq insns reserve the four lsbs. */ if ((ppc_cpu & PPC_OPCODE_POWER4) != 0 - && (val & (0x3f << 26)) == (56 << 26)) + && (val & (0x3f << 26)) == (56u << 26)) mask = 0xfff0; val |= value & mask; if (target_big_endian) @@ -5733,6 +5760,12 @@ md_apply_fix3 (fixP, valP, seg) } break; + case BFD_RELOC_PPC_B16_BRTAKEN: + case BFD_RELOC_PPC_B16_BRNTAKEN: + case BFD_RELOC_PPC_BA16_BRTAKEN: + case BFD_RELOC_PPC_BA16_BRNTAKEN: + break; + case BFD_RELOC_PPC_TLS: case BFD_RELOC_PPC_DTPMOD: case BFD_RELOC_PPC_TPREL16: @@ -5899,3 +5932,49 @@ tc_gen_reloc (seg, fixp) return reloc; } + +void +ppc_cfi_frame_initial_instructions () +{ + cfi_add_CFA_def_cfa (1, 0); +} + +int +tc_ppc_regname_to_dw2regnum (const char *regname) +{ + unsigned int regnum = -1; + unsigned int i; + const char *p; + char *q; + static struct { char *name; int dw2regnum; } regnames[] = + { + { "sp", 1 }, { "r.sp", 1 }, { "rtoc", 2 }, { "r.toc", 2 }, + { "mq", 64 }, { "lr", 65 }, { "ctr", 66 }, { "ap", 67 }, + { "cc", 68 }, { "xer", 76 }, { "vrsave", 109 }, { "vscr", 110 }, + { "spe_acc", 111 }, { "spefscr", 112 } + }; + + for (i = 0; i < ARRAY_SIZE (regnames); ++i) + if (strcmp (regnames[i].name, regname) == 0) + return regnames[i].dw2regnum; + + if (regname[0] == 'r' || regname[0] == 'f' || regname[0] == 'v') + { + p = regname + 1 + (regname[1] == '.'); + regnum = strtoul (p, &q, 10); + if (p == q || *q || regnum >= 32) + return -1; + if (regname[0] == 'f') + regnum += 32; + else if (regname[0] == 'v') + regnum += 77; + } + else if (regname[0] == 'c' && regname[1] == 'r') + { + p = regname + 2 + (regname[2] == '.'); + if (p[0] < '0' || p[0] > '7' || p[1]) + return -1; + regnum = p[0] - '0' + 68; + } + return regnum; +}