From: Nick Clifton Date: Thu, 15 Jan 1998 01:58:34 +0000 (+0000) Subject: Add support for parallel instructions. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ebde3f62352e9f20cd9f0cc7e6e98faa58052739;p=binutils-gdb.git Add support for parallel instructions. --- diff --git a/gas/ChangeLog b/gas/ChangeLog index b83f30e641e..4d540a86beb 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,9 @@ +Wed Jan 14 17:52:33 1998 Nick Clifton + + * config/tc-m32r.c (md_assemble): Add support for parsing parallel + instructions. + * cgen.c: Formatting changes to improve readability. + Wed Jan 14 15:41:41 1998 Jeffrey A Law (law@cygnus.com) * config/tc-mips.c (macro): Rework division code to avoid unfilled diff --git a/gas/cgen.c b/gas/cgen.c index 0e5c33c4acb..d65526d9932 100644 --- a/gas/cgen.c +++ b/gas/cgen.c @@ -30,13 +30,13 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ void cgen_asm_record_register (name, number) - char *name; - int number; + char * name; + int number; { /* Use symbol_create here instead of symbol_new so we don't try to output registers into the object file's symbol table. */ symbol_table_insert (symbol_create (name, reg_section, - number, &zero_address_frag)); + number, & zero_address_frag)); } /* We need to keep a list of fixups. We can't simply generate them as @@ -52,15 +52,15 @@ cgen_asm_record_register (name, number) struct fixup { - int opindex; - int opinfo; + int opindex; + int opinfo; expressionS exp; }; #define MAX_FIXUPS 5 -static struct fixup fixups[MAX_FIXUPS]; -static int num_fixups; +static struct fixup fixups [MAX_FIXUPS]; +static int num_fixups; /* Prepare to parse an instruction. ??? May wish to make this static and delete calls in md_assemble. */ @@ -75,16 +75,16 @@ cgen_asm_init_parse () void cgen_queue_fixup (opindex, opinfo, expP) - int opindex; - expressionS *expP; + int opindex; + expressionS * expP; { /* We need to generate a fixup for this expression. */ if (num_fixups >= MAX_FIXUPS) as_fatal ("too many fixups"); - fixups[num_fixups].exp = *expP; + fixups[num_fixups].exp = * expP; fixups[num_fixups].opindex = opindex; - fixups[num_fixups].opinfo = opinfo; - ++num_fixups; + fixups[num_fixups].opinfo = opinfo; + ++ num_fixups; } /* Default routine to record a fixup. @@ -102,16 +102,16 @@ cgen_queue_fixup (opindex, opinfo, expP) fixS * cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset) - fragS *frag; - int where; - const CGEN_INSN *insn; - int length; - const CGEN_OPERAND *operand; - int opinfo; - symbolS *symbol; - offsetT offset; + fragS * frag; + int where; + const CGEN_INSN * insn; + int length; + const CGEN_OPERAND * operand; + int opinfo; + symbolS * symbol; + offsetT offset; { - fixS *fixP; + fixS * fixP; /* It may seem strange to use operand->attrs and not insn->attrs here, but it is the operand that has a pc relative relocation. */ @@ -119,7 +119,7 @@ cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset) fixP = fix_new (frag, where, length / 8, symbol, offset, CGEN_OPERAND_ATTR (operand, CGEN_OPERAND_PCREL_ADDR) != 0, (bfd_reloc_code_real_type) ((int) BFD_RELOC_UNUSED + CGEN_OPERAND_INDEX (operand))); - fixP->tc_fix_data.insn = (PTR) insn; + fixP->tc_fix_data.insn = (PTR) insn; fixP->tc_fix_data.opinfo = opinfo; return fixP; @@ -140,15 +140,15 @@ cgen_record_fixup (frag, where, insn, length, operand, opinfo, symbol, offset) fixS * cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp) - fragS *frag; - int where; - const CGEN_INSN *insn; - int length; - const CGEN_OPERAND *operand; - int opinfo; - expressionS *exp; + fragS * frag; + int where; + const CGEN_INSN * insn; + int length; + const CGEN_OPERAND * operand; + int opinfo; + expressionS * exp; { - fixS *fixP; + fixS * fixP; /* It may seem strange to use operand->attrs and not insn->attrs here, but it is the operand that has a pc relative relocation. */ @@ -178,23 +178,23 @@ static jmp_buf expr_jmp_buf; const char * cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP) - enum cgen_parse_operand_type want; - const char **strP; - int opindex; - int opinfo; - enum cgen_parse_operand_result *resultP; - bfd_vma *valueP; + enum cgen_parse_operand_type want; + const char ** strP; + int opindex; + int opinfo; + enum cgen_parse_operand_result * resultP; + bfd_vma * valueP; { #ifdef __STDC__ /* These is volatile to survive the setjmp. */ - char * volatile hold; + char * volatile hold; enum cgen_parse_operand_result * volatile resultP_1; #else - static char *hold; - static enum cgen_parse_operand_result *resultP_1; + static char * hold; + static enum cgen_parse_operand_result * resultP_1; #endif - const char *errmsg = NULL; - expressionS exp; + const char * errmsg = NULL; + expressionS exp; if (want == CGEN_PARSE_OPERAND_INIT) { @@ -204,20 +204,20 @@ cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP) resultP_1 = resultP; hold = input_line_pointer; - input_line_pointer = (char *) *strP; + input_line_pointer = (char *) * strP; /* We rely on md_operand to longjmp back to us. This is done via cgen_md_operand. */ if (setjmp (expr_jmp_buf) != 0) { input_line_pointer = (char *) hold; - *resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR; + * resultP_1 = CGEN_PARSE_OPERAND_RESULT_ERROR; return "illegal operand"; } - expression (&exp); + expression (& exp); - *strP = input_line_pointer; + * strP = input_line_pointer; input_line_pointer = hold; /* FIXME: Need to check `want'. */ @@ -226,24 +226,24 @@ cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP) { case O_illegal : errmsg = "illegal operand"; - *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR; + * resultP = CGEN_PARSE_OPERAND_RESULT_ERROR; break; case O_absent : errmsg = "missing operand"; - *resultP = CGEN_PARSE_OPERAND_RESULT_ERROR; + * resultP = CGEN_PARSE_OPERAND_RESULT_ERROR; break; case O_constant : - *valueP = exp.X_add_number; - *resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER; + * valueP = exp.X_add_number; + * resultP = CGEN_PARSE_OPERAND_RESULT_NUMBER; break; case O_register : - *valueP = exp.X_add_number; - *resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER; + * valueP = exp.X_add_number; + * resultP = CGEN_PARSE_OPERAND_RESULT_REGISTER; break; default : - cgen_queue_fixup (opindex, opinfo, &exp); - *valueP = 0; - *resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED; + cgen_queue_fixup (opindex, opinfo, & exp); + * valueP = 0; + * resultP = CGEN_PARSE_OPERAND_RESULT_QUEUED; break; } @@ -257,7 +257,7 @@ cgen_parse_operand (want, strP, opindex, opinfo, resultP, valueP) void cgen_md_operand (expressionP) - expressionS *expressionP; + expressionS * expressionP; { longjmp (expr_jmp_buf, 1); } @@ -268,12 +268,13 @@ cgen_md_operand (expressionP) void cgen_asm_finish_insn (insn, buf, length) - const CGEN_INSN *insn; - cgen_insn_t *buf; - unsigned int length; + const CGEN_INSN * insn; + cgen_insn_t * buf; + unsigned int length; { - int i, relax_operand; - char *f; + int i; + int relax_operand; + char * f; unsigned int byte_len = length / 8; /* ??? Target foo issues various warnings here, so one might want to provide @@ -299,7 +300,7 @@ cgen_asm_finish_insn (insn, buf, length) /* Scan the fixups for the operand affected by relaxing (i.e. the branch address). */ - for (i = 0; i < num_fixups; ++i) + for (i = 0; i < num_fixups; ++ i) { if (CGEN_OPERAND_ATTR (& CGEN_SYM (operand_table) [fixups[i].opindex], CGEN_OPERAND_RELAX) != 0) @@ -312,8 +313,8 @@ cgen_asm_finish_insn (insn, buf, length) if (relax_operand != -1) { - int max_len; - fragS *old_frag; + int max_len; + fragS * old_frag; #ifdef TC_CGEN_MAX_RELAX max_len = TC_CGEN_MAX_RELAX (insn, byte_len); @@ -323,10 +324,13 @@ cgen_asm_finish_insn (insn, buf, length) /* Ensure variable part and fixed part are in same fragment. */ /* FIXME: Having to do this seems like a hack. */ frag_grow (max_len); + /* Allocate space for the fixed part. */ f = frag_more (byte_len); + /* Create a relaxable fragment for this instruction. */ old_frag = frag_now; + frag_var (rs_machine_dependent, max_len - byte_len /* max chars */, 0 /* variable part already allocated */, @@ -336,11 +340,12 @@ cgen_asm_finish_insn (insn, buf, length) fixups[relax_operand].exp.X_add_symbol, fixups[relax_operand].exp.X_add_number, f); + /* Record the operand number with the fragment so md_convert_frag can use cgen_md_record_fixup to record the appropriate reloc. */ - old_frag->fr_cgen.insn = insn; + old_frag->fr_cgen.insn = insn; old_frag->fr_cgen.opindex = fixups[relax_operand].opindex; - old_frag->fr_cgen.opinfo = fixups[relax_operand].opinfo; + old_frag->fr_cgen.opinfo = fixups[relax_operand].opinfo; } else f = frag_more (byte_len); @@ -352,15 +357,15 @@ cgen_asm_finish_insn (insn, buf, length) { case 16: if (cgen_big_endian_p) - bfd_putb16 ((bfd_vma) *buf, f); + bfd_putb16 ((bfd_vma) * buf, f); else - bfd_putl16 ((bfd_vma) *buf, f); + bfd_putl16 ((bfd_vma) * buf, f); break; case 32: if (cgen_big_endian_p) - bfd_putb32 ((bfd_vma) *buf, f); + bfd_putb32 ((bfd_vma) * buf, f); else - bfd_putl32 ((bfd_vma) *buf, f); + bfd_putl32 ((bfd_vma) * buf, f); break; default: abort (); @@ -388,7 +393,7 @@ cgen_asm_finish_insn (insn, buf, length) insn, length, & CGEN_SYM (operand_table) [fixups[i].opindex], fixups[i].opinfo, - &fixups[i].exp); + & fixups[i].exp); } } @@ -406,12 +411,12 @@ cgen_asm_finish_insn (insn, buf, length) int cgen_md_apply_fix3 (fixP, valueP, seg) - fixS *fixP; - valueT *valueP; - segT seg; + fixS * fixP; + valueT * valueP; + segT seg; { - char *where = fixP->fx_frag->fr_literal + fixP->fx_where; - valueT value; + char * where = fixP->fx_frag->fr_literal + fixP->fx_where; + valueT value; /* FIXME FIXME FIXME: The value we are passed in *valuep includes the symbol values. Since we are using BFD_ASSEMBLER, if we are @@ -426,11 +431,11 @@ cgen_md_apply_fix3 (fixP, valueP, seg) if (fixP->fx_addsy == (symbolS *) NULL) { - value = *valueP; + value = * valueP; fixP->fx_done = 1; } else if (fixP->fx_pcrel) - value = *valueP; + value = * valueP; else { value = fixP->fx_offset; @@ -449,12 +454,12 @@ cgen_md_apply_fix3 (fixP, valueP, seg) if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED) { - int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED; - const CGEN_OPERAND *operand = & CGEN_SYM (operand_table) [opindex]; - const char *errmsg; + int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED; + const CGEN_OPERAND * operand = & CGEN_SYM (operand_table) [opindex]; + const char * errmsg; bfd_reloc_code_real_type reloc_type; - CGEN_FIELDS fields; - const CGEN_INSN *insn = (CGEN_INSN *) fixP->tc_fix_data.insn; + CGEN_FIELDS fields; + const CGEN_INSN * insn = (CGEN_INSN *) fixP->tc_fix_data.insn; /* If the reloc has been fully resolved finish the operand here. */ /* FIXME: This duplicates the capabilities of code in BFD. */ @@ -465,12 +470,12 @@ cgen_md_apply_fix3 (fixP, valueP, seg) { /* This may seem like overkill, and using bfd_install_relocation or some such may be preferable, but this is simple. */ - CGEN_FIELDS_BITSIZE (&fields) = CGEN_INSN_BITSIZE (insn); - CGEN_SYM (set_operand) (opindex, &value, &fields); - errmsg = CGEN_SYM (validate_operand) (opindex, &fields); + CGEN_FIELDS_BITSIZE (& fields) = CGEN_INSN_BITSIZE (insn); + CGEN_SYM (set_operand) (opindex, & value, & fields); + errmsg = CGEN_SYM (validate_operand) (opindex, & fields); if (errmsg) as_warn_where (fixP->fx_file, fixP->fx_line, "%s\n", errmsg); - CGEN_SYM (insert_operand) (opindex, &fields, where); + CGEN_SYM (insert_operand) (opindex, & fields, where); } if (fixP->fx_done) @@ -533,10 +538,10 @@ cgen_md_apply_fix3 (fixP, valueP, seg) arelent * cgen_tc_gen_reloc (section, fixP) - asection *section; - fixS *fixP; + asection * section; + fixS * fixP; { - arelent *reloc; + arelent * reloc; reloc = (arelent *) bfd_alloc (stdoutput, sizeof (arelent)); @@ -551,9 +556,9 @@ cgen_tc_gen_reloc (section, fixP) assert (!fixP->fx_pcrel == !reloc->howto->pc_relative); - reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym; - reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; - reloc->addend = fixP->fx_addnumber; + reloc->sym_ptr_ptr = & fixP->fx_addsy->bsym; + reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; + reloc->addend = fixP->fx_addnumber; return reloc; } diff --git a/gas/config/tc-m32r.c b/gas/config/tc-m32r.c index 466da213247..5053eac0953 100644 --- a/gas/config/tc-m32r.c +++ b/gas/config/tc-m32r.c @@ -24,9 +24,12 @@ #include "subsegs.h" #include "cgen-opc.h" +#include "../../opcodes/m32r-asm.c" +#include "../../opcodes/m32r-asm.in" + /* Non-null if last insn was a 16 bit insn on a 32 bit boundary (i.e. was the first of two 16 bit insns). */ -static const CGEN_INSN *prev_insn = NULL; +static const CGEN_INSN * prev_insn = NULL; /* Non-zero if we've seen a relaxable insn since the last 32 bit alignment request. */ @@ -40,25 +43,24 @@ static int m32r_relax; /* If non-NULL, pointer to cpu description file to read. This allows runtime additions to the assembler. */ -static char *m32r_cpu_desc; +static char * m32r_cpu_desc; /* start-sanitize-m32rx */ /* Non-zero if -m32rx has been specified, in which case support for the extended M32RX instruction set should be enabled. */ -/* Indicates the target BFD machine number. */ static int enable_m32rx = 0; /* end-sanitize-m32rx */ /* stuff for .scomm symbols. */ -static segT sbss_section; +static segT sbss_section; static asection scom_section; -static asymbol scom_symbol; +static asymbol scom_symbol; -const char comment_chars[] = ";"; -const char line_comment_chars[] = "#"; +const char comment_chars[] = ";"; +const char line_comment_chars[] = "#"; const char line_separator_chars[] = ""; -const char EXP_CHARS[] = "eE"; -const char FLT_CHARS[] = "dD"; +const char EXP_CHARS[] = "eE"; +const char FLT_CHARS[] = "dD"; /* Relocations against symbols are done in two parts, with a HI relocation and a LO relocation. Each relocation @@ -73,17 +75,15 @@ const char FLT_CHARS[] = "dD"; struct m32r_hi_fixup { - /* Next HI fixup. */ - struct m32r_hi_fixup *next; - /* This fixup. */ - fixS *fixp; - /* The section this fixup is in. */ - segT seg; + struct m32r_hi_fixup * next; /* Next HI fixup. */ + fixS * fixp; /* This fixup. */ + segT seg; /* The section this fixup is in. */ + }; /* The list of unmatched HI relocs. */ -static struct m32r_hi_fixup *m32r_hi_fixup_list; +static struct m32r_hi_fixup * m32r_hi_fixup_list; static void m32r_record_hi16 PARAMS ((int, fixS *, segT seg)); @@ -95,11 +95,12 @@ allow_m32rx (int on) enable_m32rx = on; if (stdoutput != NULL) - bfd_set_arch_mach (stdoutput, TARGET_ARCH, enable_m32rx ? bfd_mach_m32rx : bfd_mach_m32r); + bfd_set_arch_mach (stdoutput, TARGET_ARCH, + enable_m32rx ? bfd_mach_m32rx : bfd_mach_m32r); } /* end-sanitize-m32rx */ -const char *md_shortopts = ""; +const char * md_shortopts = ""; struct option md_longopts[] = { @@ -117,12 +118,12 @@ struct option md_longopts[] = {NULL, no_argument, NULL, 0} }; -size_t md_longopts_size = sizeof(md_longopts); +size_t md_longopts_size = sizeof (md_longopts); int md_parse_option (c, arg) - int c; - char *arg; + int c; + char * arg; { switch (c) { @@ -148,7 +149,7 @@ md_parse_option (c, arg) void md_show_usage (stream) - FILE *stream; + FILE * stream; { fprintf (stream, "M32R/X options:\n"); /* start-sanitize-m32rx */ @@ -195,12 +196,12 @@ const pseudo_typeS md_pseudo_table[] = int m32r_do_align (n, fill, len, max) - int n; - const char *fill; - int len; - int max; + int n; + const char * fill; + int len; + int max; { - if ((fill == NULL || (*fill == 0 && len == 1)) + if ((fill == NULL || (* fill == 0 && len == 1)) && (now_seg->flags & SEC_CODE) != 0 /* Only do this special handling if aligning to at least a 4 byte boundary. */ @@ -224,7 +225,8 @@ m32r_do_align (n, fill, len, max) nops. */ if (n > 2) { - static const unsigned char multi_nop_pattern[] = { 0x70, 0x00, 0xf0, 0x00 }; + static const unsigned char multi_nop_pattern[] = + { 0x70, 0x00, 0xf0, 0x00 }; frag_align_pattern (n, multi_nop_pattern, sizeof multi_nop_pattern, max ? max - 2 : 0); } @@ -238,7 +240,7 @@ static void assemble_nop (opcode) int opcode; { - char *f = frag_more (2); + char * f = frag_more (2); md_number_to_chars (f, opcode, 2); } @@ -269,17 +271,21 @@ int m32r_fill_insn (done) int done; { - segT seg; + segT seg; subsegT subseg; if (prev_seg != NULL) { - seg = now_seg; + seg = now_seg; subseg = now_subseg; + subseg_set (prev_seg, prev_subseg); + fill_insn (0); + subseg_set (seg, subseg); } + return 1; } @@ -287,22 +293,24 @@ void md_begin () { flagword applicable; - segT seg; - subsegT subseg; + segT seg; + subsegT subseg; /* Initialize the `cgen' interface. */ /* This is a callback from cgen to gas to parse operands. */ cgen_parse_operand_fn = cgen_parse_operand; + /* Set the machine number and endian. */ CGEN_SYM (init_asm) (0 /* mach number */, - target_big_endian ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE); + target_big_endian ? + CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE); #if 0 /* not supported yet */ /* If a runtime cpu description file was provided, parse it. */ if (m32r_cpu_desc != NULL) { - const char *errmsg; + const char * errmsg; errmsg = cgen_read_cpu_file (m32r_cpu_desc); if (errmsg != NULL) @@ -311,15 +319,17 @@ md_begin () #endif /* Save the current subseg so we can restore it [it's the default one and - we don't want the initial section to be .sbss. */ - seg = now_seg; + we don't want the initial section to be .sbss]. */ + seg = now_seg; subseg = now_subseg; /* The sbss section is for local .scomm symbols. */ sbss_section = subseg_new (".sbss", 0); + /* This is copied from perform_an_assembly_pass. */ applicable = bfd_applicable_section_flags (stdoutput); bfd_set_section_flags (stdoutput, sbss_section, applicable & SEC_ALLOC); + #if 0 /* What does this do? [see perform_an_assembly_pass] */ seg_info (bss_section)->bss = 1; #endif @@ -328,51 +338,221 @@ md_begin () /* We must construct a fake section similar to bfd_com_section but with the name .scommon. */ - scom_section = bfd_com_section; - scom_section.name = ".scommon"; - scom_section.output_section = &scom_section; - scom_section.symbol = &scom_symbol; - scom_section.symbol_ptr_ptr = &scom_section.symbol; - scom_symbol = *bfd_com_section.symbol; - scom_symbol.name = ".scommon"; - scom_symbol.section = &scom_section; + scom_section = bfd_com_section; + scom_section.name = ".scommon"; + scom_section.output_section = & scom_section; + scom_section.symbol = & scom_symbol; + scom_section.symbol_ptr_ptr = & scom_section.symbol; + scom_symbol = * bfd_com_section.symbol; + scom_symbol.name = ".scommon"; + scom_symbol.section = & scom_section; /* start-sanitize-m32rx */ allow_m32rx (enable_m32rx); /* end-sanitize-m32rx */ } +/* Returns non zero if the given instruction writes to a destination register. */ +static int +writes_to_dest_reg (insn) + const CGEN_INSN * insn; +{ + unsigned char * syntax = CGEN_SYNTAX_STRING (CGEN_INSN_SYNTAX (insn)); + unsigned char c; + + /* Scan the syntax string looking for a destination register. */ + while ((c = (* syntax ++)) != 0) + if (c == 128 + M32R_OPERAND_DR) + break; + + return c; +} + +/* Returns an integer representing the destination register of + the given insn, or -1 if the insn has no destination. */ +static int +get_dest_reg (insn) + const CGEN_INSN * insn; +{ + /* XXX to be done. */ + return -1; +} + void md_assemble (str) - char *str; + char * str; { #ifdef CGEN_INT_INSN - cgen_insn_t buffer[CGEN_MAX_INSN_SIZE / sizeof (cgen_insn_t)]; + cgen_insn_t buffer [CGEN_MAX_INSN_SIZE / sizeof (cgen_insn_t)]; + cgen_insn_t prev_buffer [CGEN_MAX_INSN_SIZE / sizeof (cgen_insn_t)]; #else - char buffer[CGEN_MAX_INSN_SIZE]; + char buffer [CGEN_MAX_INSN_SIZE]; + char prev_buffer [CGEN_MAX_INSN_SIZE]; #endif - CGEN_FIELDS fields; - const CGEN_INSN *insn; - char *errmsg; - + CGEN_FIELDS fields; + CGEN_FIELDS prev_fields; + const CGEN_INSN * insn; + char * errmsg; + char * str2 = NULL; + int is_parallel = false; + /* Initialize GAS's cgen interface for a new instruction. */ cgen_asm_init_parse (); - insn = CGEN_SYM (assemble_insn) (str, &fields, buffer, &errmsg); + /* Look for a parallel instruction seperator. */ + if ((str2 = strstr (str, "||")) != NULL) + { + char * str3; + + * str2 = 0; /* Seperate the two instructions. */ + + /* If there was a previous 16 bit insn, then fill the following 16 bit slot, + so that the parallel instruction will start on a 32 bit boundary. */ + if (prev_insn) + fill_insn (0); + + /* Assemble the first instruction. */ + prev_insn = CGEN_SYM (assemble_insn) (str, & prev_fields, prev_buffer, & errmsg); + if (! prev_insn) + { + as_bad (errmsg); + return; + } + + /* Check to see if this is an allowable parallel insn. */ + if (CGEN_INSN_ATTR (prev_insn, CGEN_INSN_PIPE) == PIPE_NONE) + { + as_bad ("instruction '%s' cannot be executed in parallel.", str); + return; + } + +/* start-sanitize-m32rx */ + if (! enable_m32rx && + CGEN_INSN_ATTR (prev_insn, CGEN_INSN_MACH) == MACH_M32RX) + { + as_bad ("instruction '%s' is for the M32RX only", str); + return; + } +/* end-sanitize-m32rx */ + + /* fixups = fixups->next; */ + + *str2 = '|'; /* Restore the original assembly text, just in case it is needed. */ + str3 = str; /* Save the original string pointer. */ + str = str2 + 2; /* Advanced past the parsed string. */ + str2 = str3; /* Remember the entire string in case it is needed for error messages. */ + + is_parallel = true; + } + + insn = CGEN_SYM (assemble_insn) (str, & fields, buffer, & errmsg); if (!insn) { as_bad (errmsg); return; } - if (CGEN_INSN_BITSIZE (insn) == 32) +/* start-sanitize-m32rx */ + if (! enable_m32rx + && CGEN_INSN_ATTR (insn, CGEN_INSN_MACH) == (1 << MACH_M32RX)) + { + as_bad ("instruction '%s' is for the M32RX only", str); + return; + } +/* end-sanitize-m32rx */ + + if (is_parallel) + { +/* start-sanitize-m32rx */ + if (! enable_m32rx) + { + if (strcmp (prev_insn->name, "nop") != 0 + && strcmp (insn->name, "nop") != 0) + { + as_bad ("'%s': only the NOP instruction can be issued in parallel on the m32r", str2); + return; + } + } +/* end-sanitize-m32rx */ + + /* Check to see if this is an allowable parallel insn. */ + if (CGEN_INSN_ATTR (insn, CGEN_INSN_PIPE) == PIPE_NONE) + { + as_bad ("instruction '%s', cannot be executed in parallel.", str); + return; + } + + /* Check to see that the two instructions can be placed in parallel. */ + if ((CGEN_INSN_ATTR (insn, CGEN_INSN_PIPE) == CGEN_INSN_ATTR (prev_insn, CGEN_INSN_PIPE)) + && (CGEN_INSN_ATTR (insn, CGEN_INSN_PIPE) != PIPE_OS)) + { + as_bad ("'%s': both instructions use the same execution pipeline", str2); + return; + } +#if 0 + /* Check that the instructions do not write to the same destination register. */ + if (writes_to_dest_reg (insn) + && writes_to_dest_reg (prev_insn) /* This test is actually redundant. */ + && get_dest_reg (insn) == get_dest_reg (prev_insn)) + { + as_bad ("'%s': both instructions write to the same destination register", str2); + return; + } +#endif + + /* Force the top bit of the second insn to be set. */ +#if 0 /*def CGEN_INT_INSN*/ +#define MAKE_PARALLEL(insn) ((insn) |= 0x8000) + switch (CGEN_FIELDS_BITSIZE (& fields)) + { + bfd_vma value; + + case 16: + if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) + { + value = bfd_getb16 ((bfd_vma) * buffer); + MAKE_PARALLEL (value); + bfd_putb16 (value, buffer); + } + else + { + value = bfd_getl16 ((bfd_vma) * buffer); + MAKE_PARALLEL (value); + bfd_putl16 (value, buffer); + } + break; + default: + abort (); + } +#else +#define MAKE_PARALLEL(insn) ((insn) |= 0x80) + MAKE_PARALLEL (buffer [CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG ? 0 : 1]); +#endif + + /* Generate the parallel instructions */ + cgen_asm_finish_insn (prev_insn, prev_buffer, CGEN_FIELDS_BITSIZE (& prev_fields)); + cgen_asm_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (& fields)); + + /* If prev_ins is relaxable (and insn is not), then swap them, so that the test + after the end of this if-then-else section will work. */ + if (CGEN_INSN_ATTR (prev_insn, CGEN_INSN_RELAXABLE)) + insn = prev_insn; + + /* Clear the prev_insn variable, since it only used if the insn was the first + 16 bit insn in a 32 bit word. */ + prev_insn = NULL; + } + else if (CGEN_INSN_BITSIZE (insn) == 32) { /* 32 bit insns must live on 32 bit boundaries. */ - /* FIXME: If calling fill_insn too many times turns us into a memory - pig, can we call assemble_nop instead of !seen_relaxable_p? */ if (prev_insn || seen_relaxable_p) - fill_insn (0); - cgen_asm_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (&fields)); + { + /* FIXME: If calling fill_insn too many times turns us into a memory + pig, can we call assemble_nop instead of !seen_relaxable_p? */ + fill_insn (0); + } + + cgen_asm_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (& fields)); } else { @@ -382,7 +562,8 @@ md_assemble (str) prev_insn = NULL; else prev_insn = insn; - cgen_asm_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (&fields)); + + cgen_asm_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (& fields)); /* If the insn needs the following one to be on a 32 bit boundary (e.g. subroutine calls), fill this insn's slot. */ @@ -398,7 +579,7 @@ md_assemble (str) seen_relaxable_p = 1; /* Set these so m32r_fill_insn can use them. */ - prev_seg = now_seg; + prev_seg = now_seg; prev_subseg = now_subseg; } @@ -407,18 +588,18 @@ md_assemble (str) void md_operand (expressionP) - expressionS *expressionP; + expressionS * expressionP; { - if (*input_line_pointer == '#') + if (* input_line_pointer == '#') { - input_line_pointer++; + input_line_pointer ++; expression (expressionP); } } valueT md_section_align (segment, size) - segT segment; + segT segment; valueT size; { int align = bfd_get_section_alignment (stdoutput, segment); @@ -427,7 +608,7 @@ md_section_align (segment, size) symbolS * md_undefined_symbol (name) - char *name; + char * name; { return 0; } @@ -443,22 +624,22 @@ static void m32r_scomm (ignore) int ignore; { - register char *name; - register char c; - register char *p; - offsetT size; - register symbolS *symbolP; - offsetT align; - int align2; + register char * name; + register char c; + register char * p; + offsetT size; + register symbolS * symbolP; + offsetT align; + int align2; name = input_line_pointer; c = get_symbol_end (); /* just after name is now '\0' */ p = input_line_pointer; - *p = c; + * p = c; SKIP_WHITESPACE (); - if (*input_line_pointer != ',') + if (* input_line_pointer != ',') { as_bad ("Expected comma after symbol-name: rest of line ignored."); ignore_rest_of_line (); @@ -474,11 +655,11 @@ m32r_scomm (ignore) } /* The third argument to .scomm is the alignment. */ - if (*input_line_pointer != ',') + if (* input_line_pointer != ',') align = 8; else { - ++input_line_pointer; + ++ input_line_pointer; align = get_absolute_expression (); if (align <= 0) { @@ -489,7 +670,7 @@ m32r_scomm (ignore) /* Convert to a power of 2 alignment. */ if (align) { - for (align2 = 0; (align & 1) == 0; align >>= 1, ++align2) + for (align2 = 0; (align & 1) == 0; align >>= 1, ++ align2) continue; if (align != 1) { @@ -501,9 +682,9 @@ m32r_scomm (ignore) else align2 = 0; - *p = 0; + * p = 0; symbolP = symbol_find_or_make (name); - *p = c; + * p = c; if (S_IS_DEFINED (symbolP)) { @@ -526,9 +707,9 @@ m32r_scomm (ignore) if (symbolP->local) { - segT old_sec = now_seg; - int old_subsec = now_subseg; - char *pfrag; + segT old_sec = now_seg; + int old_subsec = now_subseg; + char * pfrag; record_alignment (sbss_section, align2); subseg_set (sbss_section, 0); @@ -539,7 +720,7 @@ m32r_scomm (ignore) symbolP->sy_frag = frag_now; pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size, (char *) 0); - *pfrag = 0; + * pfrag = 0; S_SET_SIZE (symbolP, size); S_SET_SEGMENT (symbolP, sbss_section); S_CLEAR_EXTERNAL (symbolP); @@ -588,8 +769,8 @@ const relax_typeS md_relax_table[] = long m32r_relax_frag (fragP, stretch) - fragS *fragP; - long stretch; + fragS * fragP; + long stretch; { /* Address of branch insn. */ long address = fragP->fr_address + fragP->fr_fix - 2; @@ -640,11 +821,11 @@ m32r_relax_frag (fragP, stretch) int md_estimate_size_before_relax (fragP, segment) - fragS *fragP; - segT segment; + fragS * fragP; + segT segment; { - int old_fr_fix = fragP->fr_fix; - char *opcode = fragP->fr_opcode; + int old_fr_fix = fragP->fr_fix; + char * opcode = fragP->fr_opcode; /* The only thing we have to handle here are symbols outside of the current segment. They may be undefined or in a different segment in @@ -678,8 +859,8 @@ md_estimate_size_before_relax (fragP, segment) frag_wane (fragP); #else { - const CGEN_INSN *insn; - int i; + const CGEN_INSN * insn; + int i; /* Update the recorded insn. Fortunately we don't have to look very far. @@ -717,8 +898,12 @@ md_convert_frag (abfd, sec, fragP) segT sec; fragS *fragP; { - char *opcode, *displacement; - int target_address, opcode_address, extension, addend; + char * opcode; + char * displacement; + int target_address; + int opcode_address; + int extension; + int addend; opcode = fragP->fr_opcode; @@ -729,19 +914,19 @@ md_convert_frag (abfd, sec, fragP) { case 1 : extension = 0; - displacement = &opcode[1]; + displacement = & opcode[1]; break; case 2 : opcode[0] |= 0x80; extension = 2; - displacement = &opcode[1]; + displacement = & opcode[1]; break; case 3 : opcode[2] = opcode[0] | 0x80; md_number_to_chars (opcode, PAR_NOP_INSN, 2); opcode_address += 2; extension = 4; - displacement = &opcode[3]; + displacement = & opcode[3]; break; default : abort (); @@ -799,8 +984,8 @@ md_convert_frag (abfd, sec, fragP) long md_pcrel_from_section (fixP, sec) - fixS *fixP; - segT sec; + fixS * fixP; + segT sec; { if (fixP->fx_addsy != (symbolS *) NULL && (! S_IS_DEFINED (fixP->fx_addsy) @@ -820,9 +1005,9 @@ md_pcrel_from_section (fixP, sec) bfd_reloc_code_real_type CGEN_SYM (lookup_reloc) (insn, operand, fixP) - const CGEN_INSN *insn; - const CGEN_OPERAND *operand; - fixS *fixP; + const CGEN_INSN * insn; + const CGEN_OPERAND * operand; + fixS * fixP; { switch (CGEN_OPERAND_TYPE (operand)) { @@ -846,16 +1031,16 @@ CGEN_SYM (lookup_reloc) (insn, operand, fixP) fixS * m32r_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp) - fragS *frag; - int where; - const CGEN_INSN *insn; - int length; - const CGEN_OPERAND *operand; - int opinfo; - expressionS *exp; + fragS * frag; + int where; + const CGEN_INSN * insn; + int length; + const CGEN_OPERAND * operand; + int opinfo; + expressionS * exp; { - fixS *fixP = cgen_record_fixup_exp (frag, where, insn, length, - operand, opinfo, exp); + fixS * fixP = cgen_record_fixup_exp (frag, where, insn, length, + operand, opinfo, exp); switch (CGEN_OPERAND_TYPE (operand)) { @@ -874,11 +1059,11 @@ m32r_cgen_record_fixup_exp (frag, where, insn, length, operand, opinfo, exp) static void m32r_record_hi16 (reloc_type, fixP, seg) - int reloc_type; - fixS *fixP; - segT seg; + int reloc_type; + fixS * fixP; + segT seg; { - struct m32r_hi_fixup *hi_fixup; + struct m32r_hi_fixup * hi_fixup; assert (reloc_type == BFD_RELOC_M32R_HI16_SLO || reloc_type == BFD_RELOC_M32R_HI16_ULO); @@ -886,8 +1071,9 @@ m32r_record_hi16 (reloc_type, fixP, seg) hi_fixup = ((struct m32r_hi_fixup *) xmalloc (sizeof (struct m32r_hi_fixup))); hi_fixup->fixp = fixP; - hi_fixup->seg = now_seg; + hi_fixup->seg = now_seg; hi_fixup->next = m32r_hi_fixup_list; + m32r_hi_fixup_list = hi_fixup; } @@ -903,12 +1089,12 @@ m32r_record_hi16 (reloc_type, fixP, seg) void m32r_frob_file () { - struct m32r_hi_fixup *l; + struct m32r_hi_fixup * l; for (l = m32r_hi_fixup_list; l != NULL; l = l->next) { - segment_info_type *seginfo; - int pass; + segment_info_type * seginfo; + int pass; assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_M32R_HI16_SLO || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_M32R_HI16_ULO); @@ -928,7 +1114,8 @@ m32r_frob_file () seginfo = seg_info (l->seg); for (pass = 0; pass < 2; pass++) { - fixS *f, *prev; + fixS * f; + fixS * prev; prev = NULL; for (f = seginfo->fix_root; f != NULL; f = f->fx_next) @@ -944,15 +1131,15 @@ m32r_frob_file () || prev->fx_addsy != f->fx_addsy || prev->fx_offset != f->fx_offset)) { - fixS **pf; + fixS ** pf; /* Move l->fixp before f. */ for (pf = &seginfo->fix_root; - *pf != l->fixp; - pf = &(*pf)->fx_next) - assert (*pf != NULL); + * pf != l->fixp; + pf = & (* pf)->fx_next) + assert (* pf != NULL); - *pf = l->fixp->fx_next; + * pf = l->fixp->fx_next; l->fixp->fx_next = f; if (prev == NULL) @@ -982,7 +1169,7 @@ m32r_frob_file () int m32r_force_relocation (fix) - fixS *fix; + fixS * fix; { if (! m32r_relax) return 0; @@ -995,9 +1182,9 @@ m32r_force_relocation (fix) void md_number_to_chars (buf, val, n) - char *buf; + char * buf; valueT val; - int n; + int n; { if (target_big_endian) number_to_chars_bigendian (buf, val, n); @@ -1019,11 +1206,12 @@ md_atof (type, litP, sizeP) char *litP; int *sizeP; { - int i,prec; - LITTLENUM_TYPE words[MAX_LITTLENUMS]; - LITTLENUM_TYPE *wordP; - char *t; - char *atof_ieee (); + int i; + int prec; + LITTLENUM_TYPE words [MAX_LITTLENUMS]; + LITTLENUM_TYPE * wordP; + char * t; + char * atof_ieee (); switch (type) { @@ -1044,20 +1232,21 @@ md_atof (type, litP, sizeP) /* FIXME: Some targets allow other format chars for bigger sizes here. */ default: - *sizeP = 0; + * sizeP = 0; return "Bad call to md_atof()"; } t = atof_ieee (input_line_pointer, type, words); if (t) input_line_pointer = t; - *sizeP = prec * sizeof (LITTLENUM_TYPE); + * sizeP = prec * sizeof (LITTLENUM_TYPE); if (target_big_endian) { for (i = 0; i < prec; i++) { - md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE)); + md_number_to_chars (litP, (valueT) words[i], + sizeof (LITTLENUM_TYPE)); litP += sizeof (LITTLENUM_TYPE); } } @@ -1065,7 +1254,8 @@ md_atof (type, litP, sizeP) { for (i = prec - 1; i >= 0; i--) { - md_number_to_chars (litP, (valueT) words[i], sizeof (LITTLENUM_TYPE)); + md_number_to_chars (litP, (valueT) words[i], + sizeof (LITTLENUM_TYPE)); litP += sizeof (LITTLENUM_TYPE); } }