diff options
-rw-r--r-- | gas/ChangeLog | 25 | ||||
-rw-r--r-- | gas/config/tc-ppc.c | 182 | ||||
-rw-r--r-- | gas/config/tc-ppc.h | 4 |
3 files changed, 195 insertions, 16 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index c865ccd..b6d55a1 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,28 @@ +2002-08-19 Elena Zannoni <ezannoni@redhat.com> + + From matthew green <mrg@redhat.com> + + * config/tc-ppc.c (PPC_OPCODE_CLASSIC): Enable this everywhere + PPC_OPCODE_PPC is, except for BookE architectures. + (md_parse_option): Add support for -mspe. + (md_show_usage): Add -mspe. + (md_parse_option): Add support for -me500 and + -me500x2 to generate code for Motorola e500 core complex. + (md_show_usage): Add -me500 and -me500x2. + + (PPC_APUINFO_ISEL, PPC_APUINFO_PMR, PPC_APUINFO_RFMCI, + PPC_APUINFO_CACHELCK, PPC_APUINFO_SPE, PPC_APUINFO_EFS, + PPC_APUINFO_BRLOCK): New macros. + + (ppc_cleanup): New function. + (ppc_apuinfo_section_add): New function. + (APUID): New macro. + (md_assemble): Collect info and write the APUinfo section. + + * config/tc-ppc.h (md_cleanup): Define. + (ppc_cleanup): Export. + (ELF_TC_SPECIAL_SECTIONS): Add .PPC.EMB.apuinfo section. + 2002-08-17 Stan Cox <scox@redhat.com> * config/obj-elf.c (obj_elf_change_section): Make non-static. diff --git a/gas/config/tc-ppc.c b/gas/config/tc-ppc.c index fb10737..6be2b43 100644 --- a/gas/config/tc-ppc.c +++ b/gas/config/tc-ppc.c @@ -130,6 +130,7 @@ static void ppc_elf_cons PARAMS ((int)); static void ppc_elf_rdata PARAMS ((int)); static void ppc_elf_lcomm PARAMS ((int)); static void ppc_elf_validate_fix PARAMS ((fixS *, segT)); +static void ppc_apuinfo_section_add PARAMS((unsigned int apu, unsigned int version)); #endif #ifdef TE_PE @@ -787,6 +788,20 @@ static segT ppc_current_section; #ifdef OBJ_ELF symbolS *GOT_symbol; /* Pre-defined "_GLOBAL_OFFSET_TABLE" */ +#define PPC_APUINFO_ISEL 0x40 +#define PPC_APUINFO_PMR 0x41 +#define PPC_APUINFO_RFMCI 0x42 +#define PPC_APUINFO_CACHELCK 0x43 +#define PPC_APUINFO_SPE 0x100 +#define PPC_APUINFO_EFS 0x101 +#define PPC_APUINFO_BRLOCK 0x102 + +/* + * We keep a list of APUinfo + */ +unsigned long *ppc_apuinfo_list; +unsigned int ppc_apuinfo_num; +unsigned int ppc_apuinfo_num_alloc; #endif /* OBJ_ELF */ #ifdef OBJ_ELF @@ -870,43 +885,62 @@ md_parse_option (c, arg) /* -m601 means to assemble for the PowerPC 601, which includes instructions that are holdovers from the Power. */ else if (strcmp (arg, "601") == 0) - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_601 | PPC_OPCODE_32; + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC + | PPC_OPCODE_601 | PPC_OPCODE_32; /* -mppc, -mppc32, -m603, and -m604 mean to assemble for the PowerPC 603/604. */ else if (strcmp (arg, "ppc") == 0 || strcmp (arg, "ppc32") == 0 || strcmp (arg, "603") == 0 || strcmp (arg, "604") == 0) - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_32; + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32; /* -m403 and -m405 mean to assemble for the PowerPC 403/405. */ else if (strcmp (arg, "403") == 0 || strcmp (arg, "405") == 0) - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_403 | PPC_OPCODE_32; + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC + | PPC_OPCODE_403 | PPC_OPCODE_32; else if (strcmp (arg, "7400") == 0 || strcmp (arg, "7410") == 0 || strcmp (arg, "7450") == 0 || strcmp (arg, "7455") == 0) - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC | PPC_OPCODE_32; + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC + | PPC_OPCODE_ALTIVEC | PPC_OPCODE_32; else if (strcmp (arg, "altivec") == 0) { if (ppc_cpu == 0) - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_ALTIVEC; + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_ALTIVEC; else ppc_cpu |= PPC_OPCODE_ALTIVEC; } + else if (strcmp (arg, "e500") == 0 || strcmp (arg, "e500x2") == 0) + { + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE + | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK + | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI; + } + else if (strcmp (arg, "spe") == 0) + { + if (ppc_cpu == 0) + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_SPE | PPC_OPCODE_EFS; + else + ppc_cpu |= PPC_OPCODE_SPE; + } /* -mppc64 and -m620 mean to assemble for the 64-bit PowerPC 620. */ else if (strcmp (arg, "ppc64") == 0 || strcmp (arg, "620") == 0) { - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64; + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64; } else if (strcmp (arg, "ppc64bridge") == 0) { - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64_BRIDGE | PPC_OPCODE_64; + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC + | PPC_OPCODE_64_BRIDGE | PPC_OPCODE_64; } /* -mbooke/-mbooke32 mean enable 32-bit BookE support. */ else if (strcmp (arg, "booke") == 0 || strcmp (arg, "booke32") == 0) - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32; + { + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_32; + } /* -mbooke64 means enable 64-bit BookE support. */ else if (strcmp (arg, "booke64") == 0) { @@ -915,7 +949,8 @@ md_parse_option (c, arg) } else if (strcmp (arg, "power4") == 0) { - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_64 | PPC_OPCODE_POWER4; + ppc_cpu = PPC_OPCODE_PPC| PPC_OPCODE_CLASSIC + | PPC_OPCODE_64 | PPC_OPCODE_POWER4; } /* -mcom means assemble for the common intersection between Power and PowerPC. At present, we just allow the union, rather @@ -1037,6 +1072,9 @@ PowerPC options:\n\ -many generate code for any architecture (PWR/PWRX/PPC)\n\ -mregnames Allow symbolic names for registers\n\ -mno-regnames Do not allow symbolic names for registers\n")); + fprintf (stream, _("\ +-me500, -me500x2 generate code for Motorola e500 core complex\n\ +-mspe generate code for Motorola SPE instructions\n")); #ifdef OBJ_ELF fprintf (stream, _("\ -mrelocatable support for GCC's -mrelocatble option\n\ @@ -1070,12 +1108,12 @@ ppc_set_cpu () else if (strcmp (default_cpu, "rs6000") == 0) 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_64; - else - ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_32; - } + { + if (default_cpu[7] == '6' && default_cpu[8] == '4') + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_64; + else + ppc_cpu = PPC_OPCODE_PPC | PPC_OPCODE_CLASSIC | PPC_OPCODE_32; + } else as_fatal (_("Unknown default cpu = %s, os = %s"), default_cpu, default_os); @@ -1240,6 +1278,64 @@ md_begin () #endif } +void +ppc_cleanup () +{ + if (ppc_apuinfo_list == NULL) + return; + + /* Ok, so write the section info out. We have this layout: + + byte data what + ---- ---- ---- + 0 8 length of "APUinfo\0" + 4 (n*4) number of APU's (4 bytes each) + 8 2 note type 2 + 12 "APUinfo\0" name + 20 APU#1 first APU's info + 24 APU#2 second APU's info + ... ... + */ + { + char *p; + asection *seg = now_seg; + subsegT subseg = now_subseg; + asection *apuinfo_secp = (asection *) NULL; + int i; + + /* Create the .PPC.EMB.apuinfo section. */ + apuinfo_secp = subseg_new (".PPC.EMB.apuinfo", 0); + bfd_set_section_flags (stdoutput, + apuinfo_secp, + SEC_HAS_CONTENTS | SEC_READONLY | SEC_MERGE); + + p = frag_more (4); + md_number_to_chars (p, (valueT) 8, 4); + + p = frag_more (4); + md_number_to_chars (p, (valueT) ppc_apuinfo_num, 4); + + p = frag_more (4); + md_number_to_chars (p, (valueT) 2, 4); + + p = frag_more (8); + strcpy (p, "APUinfo"); + + for (i = 0; i < ppc_apuinfo_num; i++) + { + p = frag_more (4); + md_number_to_chars (p, (valueT) ppc_apuinfo_list[i], 4); + } + + frag_align (2, 0, 0); + + /* We probably can't restore the current segment, for there likely + isn't one yet... */ + if (seg && subseg) + subseg_set (seg, subseg); + } +} + /* Insert an operand value into an instruction. */ static unsigned long @@ -1837,6 +1933,38 @@ parse_toc_entry (toc_kind) #endif +#define APUID(a,v) ((((a) & 0xffff) << 16) | ((v) & 0xffff)) +static void +ppc_apuinfo_section_add(apu, version) + unsigned int apu, version; +{ + unsigned int i; + + /* Check we don't already exist. */ + for (i = 0; i < ppc_apuinfo_num; i++) + if (ppc_apuinfo_list[i] == APUID(apu, version)) + return; + + if (ppc_apuinfo_num == ppc_apuinfo_num_alloc) + { + if (ppc_apuinfo_num_alloc == 0) + { + ppc_apuinfo_num_alloc = 4; + ppc_apuinfo_list = (unsigned long *) + xmalloc (sizeof (unsigned long) * ppc_apuinfo_num_alloc); + } + else + { + ppc_apuinfo_num_alloc += 4; + ppc_apuinfo_list = (unsigned long *) xrealloc (ppc_apuinfo_list, + sizeof (unsigned long) * ppc_apuinfo_num_alloc); + } + } + ppc_apuinfo_list[ppc_apuinfo_num++] = APUID(apu, version); +} +#undef APUID + + /* We need to keep a list of fixups. We can't simply generate them as we go, because that would require us to first create the frag, and that would screw up references to ``.''. */ @@ -1961,7 +2089,6 @@ md_assemble (str) operand = &powerpc_operands[next_opindex]; next_opindex = 0; } - errmsg = NULL; /* If this is a fake operand, then we do not expect anything @@ -2322,6 +2449,29 @@ md_assemble (str) if (*str != '\0') as_bad (_("junk at end of line: `%s'"), str); + /* Do we need/want a APUinfo section? */ + if (ppc_cpu & (PPC_OPCODE_SPE + | PPC_OPCODE_ISEL | PPC_OPCODE_EFS + | PPC_OPCODE_BRLOCK | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK + | PPC_OPCODE_RFMCI)) + { + /* These are all version "1". */ + if (opcode->flags & PPC_OPCODE_SPE) + ppc_apuinfo_section_add(PPC_APUINFO_SPE, 1); + if (opcode->flags & PPC_OPCODE_ISEL) + ppc_apuinfo_section_add(PPC_APUINFO_ISEL, 1); + if (opcode->flags & PPC_OPCODE_EFS) + ppc_apuinfo_section_add(PPC_APUINFO_EFS, 1); + if (opcode->flags & PPC_OPCODE_BRLOCK) + ppc_apuinfo_section_add(PPC_APUINFO_BRLOCK, 1); + if (opcode->flags & PPC_OPCODE_PMR) + ppc_apuinfo_section_add(PPC_APUINFO_PMR, 1); + if (opcode->flags & PPC_OPCODE_CACHELCK) + ppc_apuinfo_section_add(PPC_APUINFO_CACHELCK, 1); + if (opcode->flags & PPC_OPCODE_RFMCI) + ppc_apuinfo_section_add(PPC_APUINFO_RFMCI, 1); + } + /* Write out the instruction. */ f = frag_more (4); md_number_to_chars (f, insn, 4); diff --git a/gas/config/tc-ppc.h b/gas/config/tc-ppc.h index b6dd640..0e8ee5a 100644 --- a/gas/config/tc-ppc.h +++ b/gas/config/tc-ppc.h @@ -248,6 +248,7 @@ extern int ppc_section_flags PARAMS ((int, int, int)); { ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE }, \ { ".sdata2", SHT_PROGBITS, SHF_ALLOC }, \ { ".sbss2", SHT_PROGBITS, SHF_ALLOC }, \ + { ".PPC.EMB.apuinfo", SHT_NOTE, 0 }, \ { ".PPC.EMB.sdata0", SHT_PROGBITS, SHF_ALLOC }, \ { ".PPC.EMB.sbss0", SHT_PROGBITS, SHF_ALLOC }, \ /* Extra sections for 64-bit ELF PPC. */ \ @@ -285,3 +286,6 @@ extern long md_pcrel_from_section PARAMS ((struct fix *, segT)); extern int ppc_parse_name PARAMS ((const char *, struct expressionS *)); #define md_operand(x) + +#define md_cleanup() ppc_cleanup () + extern void ppc_cleanup PARAMS ((void)); |