aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2010-07-23 14:52:54 +0000
committerNick Clifton <nickc@redhat.com>2010-07-23 14:52:54 +0000
commit1cd986c58543909402a33d84b7821d0d7be17005 (patch)
tree6b28231d7f9342779aacd6177e7ec222206c82b5 /gas
parent8fd447e6d3982e728cd4005cf63d42fa3a0c2504 (diff)
downloadgdb-1cd986c58543909402a33d84b7821d0d7be17005.zip
gdb-1cd986c58543909402a33d84b7821d0d7be17005.tar.gz
gdb-1cd986c58543909402a33d84b7821d0d7be17005.tar.bz2
Add support for v850E2 and v850E2V3
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog47
-rw-r--r--gas/NEWS2
-rw-r--r--gas/config/tc-v850.c1950
-rw-r--r--gas/configure.tgt4
-rw-r--r--gas/doc/c-v850.texi24
-rw-r--r--gas/testsuite/ChangeLog7
-rw-r--r--gas/testsuite/gas/all/byte.d3
-rw-r--r--gas/testsuite/gas/rx/rx-asm-good.d4
-rw-r--r--gas/testsuite/gas/v850/split-lo16.d12
-rw-r--r--gas/testsuite/gas/v850/v850e1.d8
10 files changed, 1522 insertions, 539 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index a157d02..5ad0269 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,50 @@
+2010-07-23 Naveen.H.S <naveen.S@kpitcummins.com>
+ Ina Pandit <ina.pandit@kpitcummins.com>
+
+ * config/tc-v850.c: Update processor_mask.
+ (reg_name): Update the structure to use processors field.
+ (md_relax_table): Define SUBYPTE_COND_9_22, SUBYPTE_SA_9_22,
+ SUBYPTE_UNCOND_9_22, SUBYPTE_COND_9_22_32, SUBYPTE_SA_9_22_32,
+ SUBYPTE_UNCOND_9_22_32, SUBYPTE_COND_9_17_22,
+ SUBYPTE_SA_9_17_22, SUBYPTE_COND_9_17_22_32 and
+ SUBYPTE_SA_9_17_22_32.
+ (set_machine): Add support for V850E2 and V850E2V3.
+ (md_pseudo_table): Likewise.
+ (pre_defined_registers): Update pre defined registers suitable
+ for each family of registers.
+ (system_registers): Likewise.
+ (cc_names): Update the condition code.
+ (float_cc_names): Update the condition code for float.
+ (reg_name_search): Update based on current modifications.
+ (register_name): Likewise.
+ (system_register_name): Update to support new system registers
+ and supported families.
+ (cc_name): Update to support new condition codes.
+ (float_cc_name): New function to support float condition codes.
+ (parse_register_list): Update to support newly added registers.
+ (md_show_usage): Define support for V850E2 and V850E2V3 targets.
+ Also support added for disp-size-default-22, disp-size-default-32,
+ mextension, mno-bcond17 and mno-stld23.
+ (md_parse_option): Implement the support for above options defined
+ in md_show-usage.
+ (md_convert_frag): Implement support for subtypes defined in
+ md_relax_table to support branch operations.
+ (md_begin): Add support for V850E2 and V850E2V3.
+ (handle_hi016, handle_hi16): new relocation handling functions
+ (handle_lo16, handle_ctoff, handle_sdaoff, handle_zdaoff,
+ handle_tdaoff): Updated relocation handling functions for newly
+ added relocations.
+ (v850_reloc_prefix): Update the relocation handling functions.
+ (v850_insert_operand): Updated the functions with error message
+ parameter and modified the function to use it.
+ (md_assemble): Update according to the latest modifications.
+ (md_apply_fix): Updated the functions with error message parameter
+ and modified the function to use it.
+ (v850_force_relocation): Update with newly added relocations.
+ * configure.tgt: Match all v850 targets.
+ * doc/c-v850.texi: Document the newly added targets.
+ * NEWS: Likewise.
+
2010-07-23 Alan Modra <amodra@gmail.com>
PR gas/11834
diff --git a/gas/NEWS b/gas/NEWS
index db6b6d4..c7280bb 100644
--- a/gas/NEWS
+++ b/gas/NEWS
@@ -16,6 +16,8 @@
Changes in 2.20:
+* Added support for v850e2 and v850e2v3.
+
* GNU/Linux targets now supports "gnu_unique_object" as a value in the .type
pseudo op. It marks the symbol as being globally unique in the entire
process.
diff --git a/gas/config/tc-v850.c b/gas/config/tc-v850.c
index e0ac162..d792769 100644
--- a/gas/config/tc-v850.c
+++ b/gas/config/tc-v850.c
@@ -1,6 +1,6 @@
/* tc-v850.c -- Assembler code for the NEC V850
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2009 Free Software Foundation, Inc.
+ 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -39,13 +39,14 @@ static bfd_boolean warn_unsigned_overflows = FALSE;
static int machine = -1;
/* Indicates the target processor(s) for the assemble. */
-static int processor_mask = -1;
+static int processor_mask = 0;
/* Structure to hold information about predefined registers. */
struct reg_name
{
const char *name;
int value;
+ unsigned int processors;
};
/* Generic assembler global variables which must be defined by all
@@ -71,15 +72,67 @@ const char FLT_CHARS[] = "dD";
const relax_typeS md_relax_table[] =
{
- /* Conditional branches. */
- {0xff, -0x100, 2, 1},
- {0x1fffff, -0x200000, 6, 0},
- /* Unconditional branches. */
- {0xff, -0x100, 2, 3},
- {0x1fffff, -0x200000, 4, 0},
+ /* Conditional branches.(V850/V850E, max 22bit) */
+#define SUBYPTE_COND_9_22 0
+ {0xfe, -0x100, 2, SUBYPTE_COND_9_22 + 1},
+ {0x1ffffe + 2, -0x200000 + 2, 6, 0},
+ /* Conditional branches.(V850/V850E, max 22bit) */
+#define SUBYPTE_SA_9_22 2
+ {0xfe, -0x100, 2, SUBYPTE_SA_9_22 + 1},
+ {0x1ffffe + 4, -0x200000 + 4, 8, 0},
+ /* Unconditional branches.(V850/V850E, max 22bit) */
+#define SUBYPTE_UNCOND_9_22 4
+ {0xfe, -0x100, 2, SUBYPTE_UNCOND_9_22 + 1},
+ {0x1ffffe, -0x200000, 4, 0},
+ /* Conditional branches.(V850E2, max 32bit) */
+#define SUBYPTE_COND_9_22_32 6
+ {0xfe, -0x100, 2, SUBYPTE_COND_9_22_32 + 1},
+ {0x1fffff + 2, -0x200000 + 2, 6, SUBYPTE_COND_9_22_32 + 2},
+ {0x7ffffffe, -0x80000000, 8, 0},
+ /* Conditional branches.(V850E2, max 32bit) */
+#define SUBYPTE_SA_9_22_32 9
+ {0xfe, -0x100, 2, SUBYPTE_SA_9_22_32 + 1},
+ {0x1ffffe + 4, -0x200000 + 4, 8, SUBYPTE_SA_9_22_32 + 2},
+ {0x7ffffffe, -0x80000000, 10, 0},
+ /* Unconditional branches.(V850E2, max 32bit) */
+#define SUBYPTE_UNCOND_9_22_32 12
+ {0xfe, -0x100, 2, SUBYPTE_UNCOND_9_22_32 + 1},
+ {0x1ffffe, -0x200000, 4, SUBYPTE_UNCOND_9_22_32 + 2},
+ {0x7ffffffe, -0x80000000, 6, 0},
+ /* Conditional branches.(V850E2R max 22bit) */
+#define SUBYPTE_COND_9_17_22 15
+ {0xfe, -0x100, 2, SUBYPTE_COND_9_17_22 + 1},
+ {0xfffe, -0x10000, 4, SUBYPTE_COND_9_17_22 + 2},
+ {0x1ffffe + 2, -0x200000 + 2, 6, 0},
+ /* Conditional branches.(V850E2R max 22bit) */
+#define SUBYPTE_SA_9_17_22 18
+ {0xfe, -0x100, 2, SUBYPTE_SA_9_17_22 + 1},
+ {0xfffe, -0x10000, 4, SUBYPTE_SA_9_17_22 + 2},
+ {0x1ffffe + 4, -0x200000 + 4, 8, 0},
+ /* Conditional branches.(V850E2R max 32bit) */
+#define SUBYPTE_COND_9_17_22_32 21
+ {0xfe, -0x100, 2, SUBYPTE_COND_9_17_22_32 + 1},
+ {0xfffe, -0x10000, 4, SUBYPTE_COND_9_17_22_32 + 2},
+ {0x1ffffe + 2, -0x200000 + 2, 6, SUBYPTE_COND_9_17_22_32 + 3},
+ {0x7ffffffe, -0x80000000, 8, 0},
+ /* Conditional branches.(V850E2R max 32bit) */
+#define SUBYPTE_SA_9_17_22_32 25
+ {0xfe, -0x100, 2, SUBYPTE_SA_9_17_22_32 + 1},
+ {0xfffe, -0x10000, 4, SUBYPTE_SA_9_17_22_32 + 2},
+ {0x1ffffe + 4, -0x200000 + 4, 8, SUBYPTE_SA_9_17_22_32 + 3},
+ {0x7ffffffe, -0x80000000, 10, 0},
};
-static int v850_relax = 0;
+static int v850_relax = 0;
+
+/* Default branch disp size 22 or 32. */
+static int default_disp_size = 22;
+
+/* Default no using bcond17. */
+static int no_bcond17 = 0;
+
+/* Default no using ld/st 23bit offset. */
+static int no_stld23 = 0;
/* Fixups. */
#define MAX_INSN_FIXUPS 5
@@ -463,9 +516,12 @@ set_machine (int number)
switch (machine)
{
- case 0: processor_mask = PROCESSOR_V850; break;
- case bfd_mach_v850e: processor_mask = PROCESSOR_V850E; break;
- case bfd_mach_v850e1: processor_mask = PROCESSOR_V850E; break;
+ case 0: SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850); break;
+ case bfd_mach_v850: SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850); break;
+ case bfd_mach_v850e: SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E); break;
+ case bfd_mach_v850e1: SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E); break;
+ case bfd_mach_v850e2: SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E2); break;
+ case bfd_mach_v850e2v3:SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E2V3); break;
}
}
@@ -523,7 +579,9 @@ const pseudo_typeS md_pseudo_table[] =
{ "call_table_data", v850_seg, CALL_TABLE_DATA_SECTION },
{ "call_table_text", v850_seg, CALL_TABLE_TEXT_SECTION },
{ "v850e", set_machine, bfd_mach_v850e },
- { "v850e1", set_machine, bfd_mach_v850e1 },
+ { "v850e1", set_machine, bfd_mach_v850e1 },
+ { "v850e2", set_machine, bfd_mach_v850e2 },
+ { "v850e2v3", set_machine, bfd_mach_v850e2v3 },
{ "longcall", v850_longcode, 1 },
{ "longjump", v850_longcode, 2 },
{ NULL, NULL, 0 }
@@ -535,45 +593,45 @@ static struct hash_control *v850_hash;
/* This table is sorted. Suitable for searching by a binary search. */
static const struct reg_name pre_defined_registers[] =
{
- { "ep", 30 }, /* ep - element ptr. */
- { "gp", 4 }, /* gp - global ptr. */
- { "hp", 2 }, /* hp - handler stack ptr. */
- { "lp", 31 }, /* lp - link ptr. */
- { "r0", 0 },
- { "r1", 1 },
- { "r10", 10 },
- { "r11", 11 },
- { "r12", 12 },
- { "r13", 13 },
- { "r14", 14 },
- { "r15", 15 },
- { "r16", 16 },
- { "r17", 17 },
- { "r18", 18 },
- { "r19", 19 },
- { "r2", 2 },
- { "r20", 20 },
- { "r21", 21 },
- { "r22", 22 },
- { "r23", 23 },
- { "r24", 24 },
- { "r25", 25 },
- { "r26", 26 },
- { "r27", 27 },
- { "r28", 28 },
- { "r29", 29 },
- { "r3", 3 },
- { "r30", 30 },
- { "r31", 31 },
- { "r4", 4 },
- { "r5", 5 },
- { "r6", 6 },
- { "r7", 7 },
- { "r8", 8 },
- { "r9", 9 },
- { "sp", 3 }, /* sp - stack ptr. */
- { "tp", 5 }, /* tp - text ptr. */
- { "zero", 0 },
+ { "ep", 30, PROCESSOR_ALL }, /* ep - element ptr. */
+ { "gp", 4, PROCESSOR_ALL }, /* gp - global ptr. */
+ { "hp", 2, PROCESSOR_ALL }, /* hp - handler stack ptr. */
+ { "lp", 31, PROCESSOR_ALL }, /* lp - link ptr. */
+ { "r0", 0, PROCESSOR_ALL },
+ { "r1", 1, PROCESSOR_ALL },
+ { "r10", 10, PROCESSOR_ALL },
+ { "r11", 11, PROCESSOR_ALL },
+ { "r12", 12, PROCESSOR_ALL },
+ { "r13", 13, PROCESSOR_ALL },
+ { "r14", 14, PROCESSOR_ALL },
+ { "r15", 15, PROCESSOR_ALL },
+ { "r16", 16, PROCESSOR_ALL },
+ { "r17", 17, PROCESSOR_ALL },
+ { "r18", 18, PROCESSOR_ALL },
+ { "r19", 19, PROCESSOR_ALL },
+ { "r2", 2, PROCESSOR_ALL },
+ { "r20", 20, PROCESSOR_ALL },
+ { "r21", 21, PROCESSOR_ALL },
+ { "r22", 22, PROCESSOR_ALL },
+ { "r23", 23, PROCESSOR_ALL },
+ { "r24", 24, PROCESSOR_ALL },
+ { "r25", 25, PROCESSOR_ALL },
+ { "r26", 26, PROCESSOR_ALL },
+ { "r27", 27, PROCESSOR_ALL },
+ { "r28", 28, PROCESSOR_ALL },
+ { "r29", 29, PROCESSOR_ALL },
+ { "r3", 3, PROCESSOR_ALL },
+ { "r30", 30, PROCESSOR_ALL },
+ { "r31", 31, PROCESSOR_ALL },
+ { "r4", 4, PROCESSOR_ALL },
+ { "r5", 5, PROCESSOR_ALL },
+ { "r6", 6, PROCESSOR_ALL },
+ { "r7", 7, PROCESSOR_ALL },
+ { "r8", 8, PROCESSOR_ALL },
+ { "r9", 9, PROCESSOR_ALL },
+ { "sp", 3, PROCESSOR_ALL }, /* sp - stack ptr. */
+ { "tp", 5, PROCESSOR_ALL }, /* tp - text ptr. */
+ { "zero", 0, PROCESSOR_ALL },
};
#define REG_NAME_CNT \
@@ -581,67 +639,220 @@ static const struct reg_name pre_defined_registers[] =
static const struct reg_name system_registers[] =
{
- { "asid", 23 },
- { "bpc", 22 },
- { "bpav", 24 },
- { "bpam", 25 },
- { "bpdv", 26 },
- { "bpdm", 27 },
- { "ctbp", 20 },
- { "ctpc", 16 },
- { "ctpsw", 17 },
- { "dbpc", 18 },
- { "dbpsw", 19 },
- { "dir", 21 },
- { "ecr", 4 },
- { "eipc", 0 },
- { "eipsw", 1 },
- { "fepc", 2 },
- { "fepsw", 3 },
- { "psw", 5 },
+ { "asid", 23, PROCESSOR_NOT_V850 },
+ { "bpam", 25, PROCESSOR_NOT_V850 },
+ { "bpav", 24, PROCESSOR_NOT_V850 },
+ { "bpc", 22, PROCESSOR_NOT_V850 },
+ { "bpdm", 27, PROCESSOR_NOT_V850 },
+ { "bpdv", 26, PROCESSOR_NOT_V850 },
+ { "bsel", 31, PROCESSOR_V850E2_ALL },
+ { "cfg", 7, PROCESSOR_V850E2V3 },
+ { "ctbp", 20, PROCESSOR_NOT_V850 },
+ { "ctpc", 16, PROCESSOR_NOT_V850 },
+ { "ctpsw", 17, PROCESSOR_NOT_V850 },
+ { "dbic", 15, PROCESSOR_V850E2_ALL },
+ { "dbpc", 18, PROCESSOR_NOT_V850 },
+ { "dbpsw", 19, PROCESSOR_NOT_V850 },
+ { "dbwr", 30, PROCESSOR_V850E2_ALL },
+ { "dir", 21, PROCESSOR_NOT_V850 },
+ { "dpa0l", 16, PROCESSOR_V850E2V3 },
+ { "dpa0u", 17, PROCESSOR_V850E2V3 },
+ { "dpa1l", 18, PROCESSOR_V850E2V3 },
+ { "dpa1u", 19, PROCESSOR_V850E2V3 },
+ { "dpa2l", 20, PROCESSOR_V850E2V3 },
+ { "dpa2u", 21, PROCESSOR_V850E2V3 },
+ { "dpa3l", 22, PROCESSOR_V850E2V3 },
+ { "dpa3u", 23, PROCESSOR_V850E2V3 },
+ { "dpa4l", 24, PROCESSOR_V850E2V3 },
+ { "dpa4u", 25, PROCESSOR_V850E2V3 },
+ { "dpa5l", 26, PROCESSOR_V850E2V3 },
+ { "dpa5u", 27, PROCESSOR_V850E2V3 },
+ { "ecr", 4, PROCESSOR_ALL },
+ { "eh_base", 3, PROCESSOR_V850E2V3 },
+ { "eh_cfg", 1, PROCESSOR_V850E2V3 },
+ { "eh_reset", 2, PROCESSOR_V850E2V3 },
+ { "eiic", 13, PROCESSOR_V850E2_ALL },
+ { "eipc", 0, PROCESSOR_ALL },
+ { "eipsw", 1, PROCESSOR_ALL },
+ { "eiwr", 28, PROCESSOR_V850E2_ALL },
+ { "feic", 14, PROCESSOR_V850E2_ALL },
+ { "fepc", 2, PROCESSOR_ALL },
+ { "fepsw", 3, PROCESSOR_ALL },
+ { "fewr", 29, PROCESSOR_V850E2_ALL },
+ { "fpcc", 9, PROCESSOR_V850E2V3 },
+ { "fpcfg", 10, PROCESSOR_V850E2V3 },
+ { "fpec", 11, PROCESSOR_V850E2V3 },
+ { "fpepc", 7, PROCESSOR_V850E2V3 },
+ { "fpspc", 27, PROCESSOR_V850E2V3 },
+ { "fpsr", 6, PROCESSOR_V850E2V3 },
+ { "fpst", 8, PROCESSOR_V850E2V3 },
+ { "ipa0l", 6, PROCESSOR_V850E2V3 },
+ { "ipa0u", 7, PROCESSOR_V850E2V3 },
+ { "ipa1l", 8, PROCESSOR_V850E2V3 },
+ { "ipa1u", 9, PROCESSOR_V850E2V3 },
+ { "ipa2l", 10, PROCESSOR_V850E2V3 },
+ { "ipa2u", 11, PROCESSOR_V850E2V3 },
+ { "ipa3l", 12, PROCESSOR_V850E2V3 },
+ { "ipa3u", 13, PROCESSOR_V850E2V3 },
+ { "ipa4l", 14, PROCESSOR_V850E2V3 },
+ { "ipa4u", 15, PROCESSOR_V850E2V3 },
+ { "mca", 24, PROCESSOR_V850E2V3 },
+ { "mcc", 26, PROCESSOR_V850E2V3 },
+ { "mcr", 27, PROCESSOR_V850E2V3 },
+ { "mcs", 25, PROCESSOR_V850E2V3 },
+ { "mpc", 1, PROCESSOR_V850E2V3 },
+ { "mpm", 0, PROCESSOR_V850E2V3 },
+ { "mpu10_dpa0l", 16, PROCESSOR_V850E2V3 },
+ { "mpu10_dpa0u", 17, PROCESSOR_V850E2V3 },
+ { "mpu10_dpa1l", 18, PROCESSOR_V850E2V3 },
+ { "mpu10_dpa1u", 19, PROCESSOR_V850E2V3 },
+ { "mpu10_dpa2l", 20, PROCESSOR_V850E2V3 },
+ { "mpu10_dpa2u", 21, PROCESSOR_V850E2V3 },
+ { "mpu10_dpa3l", 22, PROCESSOR_V850E2V3 },
+ { "mpu10_dpa3u", 23, PROCESSOR_V850E2V3 },
+ { "mpu10_dpa4l", 24, PROCESSOR_V850E2V3 },
+ { "mpu10_dpa4u", 25, PROCESSOR_V850E2V3 },
+ { "mpu10_dpa5l", 26, PROCESSOR_V850E2V3 },
+ { "mpu10_dpa5u", 27, PROCESSOR_V850E2V3 },
+ { "mpu10_ipa0l", 6, PROCESSOR_V850E2V3 },
+ { "mpu10_ipa0u", 7, PROCESSOR_V850E2V3 },
+ { "mpu10_ipa1l", 8, PROCESSOR_V850E2V3 },
+ { "mpu10_ipa1u", 9, PROCESSOR_V850E2V3 },
+ { "mpu10_ipa2l", 10, PROCESSOR_V850E2V3 },
+ { "mpu10_ipa2u", 11, PROCESSOR_V850E2V3 },
+ { "mpu10_ipa3l", 12, PROCESSOR_V850E2V3 },
+ { "mpu10_ipa3u", 13, PROCESSOR_V850E2V3 },
+ { "mpu10_ipa4l", 14, PROCESSOR_V850E2V3 },
+ { "mpu10_ipa4u", 15, PROCESSOR_V850E2V3 },
+ { "mpu10_mpc", 1, PROCESSOR_V850E2V3 },
+ { "mpu10_mpm", 0, PROCESSOR_V850E2V3 },
+ { "mpu10_tid", 2, PROCESSOR_V850E2V3 },
+ { "mpu10_vmadr", 5, PROCESSOR_V850E2V3 },
+ { "mpu10_vmecr", 3, PROCESSOR_V850E2V3 },
+ { "mpu10_vmtid", 4, PROCESSOR_V850E2V3 },
+ { "pid", 6, PROCESSOR_V850E2V3 },
+ { "pmcr0", 4, PROCESSOR_V850E2V3 },
+ { "pmis2", 14, PROCESSOR_V850E2V3 },
+ { "psw", 5, PROCESSOR_ALL },
+ { "scbp", 12, PROCESSOR_V850E2V3 },
+ { "sccfg", 11, PROCESSOR_V850E2V3 },
+ { "sr0", 0, PROCESSOR_ALL },
+ { "sr1", 1, PROCESSOR_ALL },
+ { "sr10", 10, PROCESSOR_ALL },
+ { "sr11", 11, PROCESSOR_ALL },
+ { "sr12", 12, PROCESSOR_ALL },
+ { "sr13", 13, PROCESSOR_ALL },
+ { "sr14", 14, PROCESSOR_ALL },
+ { "sr15", 15, PROCESSOR_ALL },
+ { "sr16", 16, PROCESSOR_ALL },
+ { "sr17", 17, PROCESSOR_ALL },
+ { "sr18", 18, PROCESSOR_ALL },
+ { "sr19", 19, PROCESSOR_ALL },
+ { "sr2", 2, PROCESSOR_ALL },
+ { "sr20", 20, PROCESSOR_ALL },
+ { "sr21", 21, PROCESSOR_ALL },
+ { "sr22", 22, PROCESSOR_ALL },
+ { "sr23", 23, PROCESSOR_ALL },
+ { "sr24", 24, PROCESSOR_ALL },
+ { "sr25", 25, PROCESSOR_ALL },
+ { "sr26", 26, PROCESSOR_ALL },
+ { "sr27", 27, PROCESSOR_ALL },
+ { "sr28", 28, PROCESSOR_ALL },
+ { "sr29", 29, PROCESSOR_ALL },
+ { "sr3", 3, PROCESSOR_ALL },
+ { "sr30", 30, PROCESSOR_ALL },
+ { "sr31", 31, PROCESSOR_ALL },
+ { "sr4", 4, PROCESSOR_ALL },
+ { "sr5", 5, PROCESSOR_ALL },
+ { "sr6", 6, PROCESSOR_ALL },
+ { "sr7", 7, PROCESSOR_ALL },
+ { "sr8", 8, PROCESSOR_ALL },
+ { "sr9", 9, PROCESSOR_ALL },
+ { "sw_base", 3, PROCESSOR_V850E2V3 },
+ { "sw_cfg", 1, PROCESSOR_V850E2V3 },
+ { "sw_ctl", 0, PROCESSOR_V850E2V3 },
+ { "tid", 2, PROCESSOR_V850E2V3 },
+ { "vmadr", 6, PROCESSOR_V850E2V3 },
+ { "vmecr", 4, PROCESSOR_V850E2V3 },
+ { "vmtid", 5, PROCESSOR_V850E2V3 },
+ { "vsadr", 2, PROCESSOR_V850E2V3 },
+ { "vsecr", 0, PROCESSOR_V850E2V3 },
+ { "vstid", 1, PROCESSOR_V850E2V3 },
};
#define SYSREG_NAME_CNT \
(sizeof (system_registers) / sizeof (struct reg_name))
-static const struct reg_name system_list_registers[] =
-{
- {"PS", 5 },
- {"SR", 0 + 1}
-};
-
-#define SYSREGLIST_NAME_CNT \
- (sizeof (system_list_registers) / sizeof (struct reg_name))
static const struct reg_name cc_names[] =
{
- { "c", 0x1 },
- { "e", 0x2 },
- { "ge", 0xe },
- { "gt", 0xf },
- { "h", 0xb },
- { "l", 0x1 },
- { "le", 0x7 },
- { "lt", 0x6 },
- { "n", 0x4 },
- { "nc", 0x9 },
- { "ne", 0xa },
- { "nh", 0x3 },
- { "nl", 0x9 },
- { "ns", 0xc },
- { "nv", 0x8 },
- { "nz", 0xa },
- { "p", 0xc },
- { "s", 0x4 },
- { "sa", 0xd },
- { "t", 0x5 },
- { "v", 0x0 },
- { "z", 0x2 },
+ { "c", 0x1, PROCESSOR_ALL },
+ { "e", 0x2, PROCESSOR_ALL },
+ { "ge", 0xe, PROCESSOR_ALL },
+ { "gt", 0xf, PROCESSOR_ALL },
+ { "h", 0xb, PROCESSOR_ALL },
+ { "l", 0x1, PROCESSOR_ALL },
+ { "le", 0x7, PROCESSOR_ALL },
+ { "lt", 0x6, PROCESSOR_ALL },
+ { "n", 0x4, PROCESSOR_ALL },
+ { "nc", 0x9, PROCESSOR_ALL },
+ { "ne", 0xa, PROCESSOR_ALL },
+ { "nh", 0x3, PROCESSOR_ALL },
+ { "nl", 0x9, PROCESSOR_ALL },
+ { "ns", 0xc, PROCESSOR_ALL },
+ { "nv", 0x8, PROCESSOR_ALL },
+ { "nz", 0xa, PROCESSOR_ALL },
+ { "p", 0xc, PROCESSOR_ALL },
+ { "s", 0x4, PROCESSOR_ALL },
+#define COND_SA_NUM 0xd
+ { "sa", COND_SA_NUM, PROCESSOR_ALL },
+ { "t", 0x5, PROCESSOR_ALL },
+ { "v", 0x0, PROCESSOR_ALL },
+ { "z", 0x2, PROCESSOR_ALL },
};
#define CC_NAME_CNT \
(sizeof (cc_names) / sizeof (struct reg_name))
+static const struct reg_name float_cc_names[] =
+{
+ { "eq", 0x2, PROCESSOR_V850E2V3 }, /* true. */
+ { "f", 0x0, PROCESSOR_V850E2V3 }, /* true. */
+ { "ge", 0xd, PROCESSOR_V850E2V3 }, /* false. */
+ { "gl", 0xb, PROCESSOR_V850E2V3 }, /* false. */
+ { "gle", 0x9, PROCESSOR_V850E2V3 }, /* false. */
+ { "gt", 0xf, PROCESSOR_V850E2V3 }, /* false. */
+ { "le", 0xe, PROCESSOR_V850E2V3 }, /* true. */
+ { "lt", 0xc, PROCESSOR_V850E2V3 }, /* true. */
+ { "neq", 0x2, PROCESSOR_V850E2V3 }, /* false. */
+ { "nge", 0xd, PROCESSOR_V850E2V3 }, /* true. */
+ { "ngl", 0xb, PROCESSOR_V850E2V3 }, /* true. */
+ { "ngle",0x9, PROCESSOR_V850E2V3 }, /* true. */
+ { "ngt", 0xf, PROCESSOR_V850E2V3 }, /* true. */
+ { "nle", 0xe, PROCESSOR_V850E2V3 }, /* false. */
+ { "nlt", 0xc, PROCESSOR_V850E2V3 }, /* false. */
+ { "oge", 0x5, PROCESSOR_V850E2V3 }, /* false. */
+ { "ogl", 0x3, PROCESSOR_V850E2V3 }, /* false. */
+ { "ogt", 0x7, PROCESSOR_V850E2V3 }, /* false. */
+ { "ole", 0x6, PROCESSOR_V850E2V3 }, /* true. */
+ { "olt", 0x4, PROCESSOR_V850E2V3 }, /* true. */
+ { "or", 0x1, PROCESSOR_V850E2V3 }, /* false. */
+ { "seq", 0xa, PROCESSOR_V850E2V3 }, /* true. */
+ { "sf", 0x8, PROCESSOR_V850E2V3 }, /* true. */
+ { "sne", 0xa, PROCESSOR_V850E2V3 }, /* false. */
+ { "st", 0x8, PROCESSOR_V850E2V3 }, /* false. */
+ { "t", 0x0, PROCESSOR_V850E2V3 }, /* false. */
+ { "ueq", 0x3, PROCESSOR_V850E2V3 }, /* true. */
+ { "uge", 0x4, PROCESSOR_V850E2V3 }, /* false. */
+ { "ugt", 0x6, PROCESSOR_V850E2V3 }, /* false. */
+ { "ule", 0x7, PROCESSOR_V850E2V3 }, /* true. */
+ { "ult", 0x5, PROCESSOR_V850E2V3 }, /* true. */
+ { "un", 0x1, PROCESSOR_V850E2V3 }, /* true. */
+};
+
+#define FLOAT_CC_NAME_CNT \
+ (sizeof (float_cc_names) / sizeof (struct reg_name))
+
/* Do a binary search of the given register table to see if NAME is a
valid regiter name. Return the register number from the array on
success, or -1 on failure. */
@@ -667,9 +878,7 @@ reg_name_search (const struct reg_name *regs,
else if (accept_numbers)
{
int reg = S_GET_VALUE (symbolP);
-
- if (reg >= 0 && reg <= 31)
- return reg;
+ return reg;
}
/* Otherwise drop through and try parsing name normally. */
@@ -687,7 +896,9 @@ reg_name_search (const struct reg_name *regs,
else if (cmp > 0)
low = middle + 1;
else
- return regs[middle].value;
+ return ((regs[middle].processors & processor_mask)
+ ? regs[middle].value
+ : -1);
}
while (low <= high);
return -1;
@@ -722,25 +933,24 @@ register_name (expressionS *expressionP)
/* Put back the delimiting char. */
*input_line_pointer = c;
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+
/* Look to see if it's in the register table. */
if (reg_number >= 0)
{
expressionP->X_op = O_register;
expressionP->X_add_number = reg_number;
- /* Make the rest nice. */
- expressionP->X_add_symbol = NULL;
- expressionP->X_op_symbol = NULL;
-
return TRUE;
}
- else
- {
- /* Reset the line as if we had not done anything. */
- input_line_pointer = start;
- return FALSE;
- }
+ /* Reset the line as if we had not done anything. */
+ input_line_pointer = start;
+
+ expressionP->X_op = O_illegal;
+
+ return FALSE;
}
/* Summary of system_register_name().
@@ -748,8 +958,6 @@ register_name (expressionS *expressionP)
in: INPUT_LINE_POINTER points to 1st char of operand.
EXPRESSIONP points to an expression structure to be filled in.
ACCEPT_NUMBERS is true iff numerical register names may be used.
- ACCEPT_LIST_NAMES is true iff the special names PS and SR may be
- accepted.
out: An expressionS structure in expressionP.
The operand may have been a register: in this case, X_op == O_register,
@@ -759,8 +967,7 @@ register_name (expressionS *expressionP)
static bfd_boolean
system_register_name (expressionS *expressionP,
- bfd_boolean accept_numbers,
- bfd_boolean accept_list_names)
+ bfd_boolean accept_numbers)
{
int reg_number;
char *name;
@@ -785,44 +992,28 @@ system_register_name (expressionS *expressionP,
if (ISDIGIT (*input_line_pointer))
{
- reg_number = strtol (input_line_pointer, &input_line_pointer, 10);
-
- /* Make sure that the register number is allowable. */
- if (reg_number < 0
- || (reg_number > 5 && reg_number < 16)
- || reg_number > 27)
- reg_number = -1;
- }
- else if (accept_list_names)
- {
- c = get_symbol_end ();
- reg_number = reg_name_search (system_list_registers,
- SYSREGLIST_NAME_CNT, name, FALSE);
-
- /* Put back the delimiting char. */
- *input_line_pointer = c;
+ reg_number = strtol (input_line_pointer, &input_line_pointer, 0);
}
}
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+
/* Look to see if it's in the register table. */
if (reg_number >= 0)
{
expressionP->X_op = O_register;
expressionP->X_add_number = reg_number;
- /* Make the rest nice. */
- expressionP->X_add_symbol = NULL;
- expressionP->X_op_symbol = NULL;
-
return TRUE;
}
- else
- {
- /* Reset the line as if we had not done anything. */
- input_line_pointer = start;
- return FALSE;
- }
+ /* Reset the line as if we had not done anything. */
+ input_line_pointer = start;
+
+ expressionP->X_op = O_illegal;
+
+ return FALSE;
}
/* Summary of cc_name().
@@ -836,7 +1027,8 @@ system_register_name (expressionS *expressionP,
its original state. */
static bfd_boolean
-cc_name (expressionS *expressionP)
+cc_name (expressionS *expressionP,
+ bfd_boolean accept_numbers)
{
int reg_number;
char *name;
@@ -847,30 +1039,93 @@ cc_name (expressionS *expressionP)
start = name = input_line_pointer;
c = get_symbol_end ();
- reg_number = reg_name_search (cc_names, CC_NAME_CNT, name, FALSE);
+ reg_number = reg_name_search (cc_names, CC_NAME_CNT, name, accept_numbers);
/* Put back the delimiting char. */
*input_line_pointer = c;
+ if (reg_number < 0
+ && accept_numbers)
+ {
+ /* Reset input_line pointer. */
+ input_line_pointer = start;
+
+ if (ISDIGIT (*input_line_pointer))
+ {
+ reg_number = strtol (input_line_pointer, &input_line_pointer, 0);
+ }
+ }
+
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+
/* Look to see if it's in the register table. */
if (reg_number >= 0)
{
expressionP->X_op = O_constant;
expressionP->X_add_number = reg_number;
- /* Make the rest nice. */
- expressionP->X_add_symbol = NULL;
- expressionP->X_op_symbol = NULL;
-
return TRUE;
}
- else
+
+ /* Reset the line as if we had not done anything. */
+ input_line_pointer = start;
+
+ expressionP->X_op = O_illegal;
+ expressionP->X_add_number = 0;
+
+ return FALSE;
+}
+
+static bfd_boolean
+float_cc_name (expressionS *expressionP,
+ bfd_boolean accept_numbers)
+{
+ int reg_number;
+ char *name;
+ char *start;
+ char c;
+
+ /* Find the spelling of the operand. */
+ start = name = input_line_pointer;
+
+ c = get_symbol_end ();
+ reg_number = reg_name_search (float_cc_names, FLOAT_CC_NAME_CNT, name, accept_numbers);
+
+ /* Put back the delimiting char. */
+ *input_line_pointer = c;
+
+ if (reg_number < 0
+ && accept_numbers)
{
- /* Reset the line as if we had not done anything. */
+ /* Reset input_line pointer. */
input_line_pointer = start;
- return FALSE;
+ if (ISDIGIT (*input_line_pointer))
+ {
+ reg_number = strtol (input_line_pointer, &input_line_pointer, 0);
+ }
+ }
+
+ expressionP->X_add_symbol = NULL;
+ expressionP->X_op_symbol = NULL;
+
+ /* Look to see if it's in the register table. */
+ if (reg_number >= 0)
+ {
+ expressionP->X_op = O_constant;
+ expressionP->X_add_number = reg_number;
+
+ return TRUE;
}
+
+ /* Reset the line as if we had not done anything. */
+ input_line_pointer = start;
+
+ expressionP->X_op = O_illegal;
+ expressionP->X_add_number = 0;
+
+ return FALSE;
}
static void
@@ -915,16 +1170,7 @@ parse_register_list (unsigned long *insn,
30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24
};
- static int type2_regs[32] =
- {
- 19, 18, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 30, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24
- };
- static int type3_regs[32] =
- {
- 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 14, 15, 13, 12, 7, 6, 5, 4, 11, 10, 9, 8
- };
+
int *regs;
expressionS exp;
@@ -932,8 +1178,6 @@ parse_register_list (unsigned long *insn,
switch (operand->shift)
{
case 0xffe00001: regs = type1_regs; break;
- case 0xfff8000f: regs = type2_regs; break;
- case 0xfff8001f: regs = type3_regs; break;
default:
as_bad (_("unknown operand shift: %x\n"), operand->shift);
return _("internal failure in parse_register_list");
@@ -967,41 +1211,6 @@ parse_register_list (unsigned long *insn,
*insn |= (1 << i);
}
}
- else if (regs == type2_regs)
- {
- if (exp.X_add_number & 0xFFFE0000)
- return _("high bits set in register list expression");
-
- for (reg = 1; reg < 16; reg++)
- if (exp.X_add_number & (1 << (reg - 1)))
- {
- for (i = 0; i < 32; i++)
- if (regs[i] == reg)
- *insn |= (1 << i);
- }
-
- if (exp.X_add_number & (1 << 15))
- *insn |= (1 << 3);
-
- if (exp.X_add_number & (1 << 16))
- *insn |= (1 << 19);
- }
- else /* regs == type3_regs */
- {
- if (exp.X_add_number & 0xFFFE0000)
- return _("high bits set in register list expression");
-
- for (reg = 16; reg < 32; reg++)
- if (exp.X_add_number & (1 << (reg - 16)))
- {
- for (i = 0; i < 32; i++)
- if (regs[i] == reg)
- *insn |= (1 << i);
- }
-
- if (exp.X_add_number & (1 << 16))
- *insn |= (1 << 19);
- }
return NULL;
}
@@ -1012,6 +1221,8 @@ parse_register_list (unsigned long *insn,
new-line) is found. */
for (;;)
{
+ skip_white_space ();
+
if (register_name (&exp))
{
int i;
@@ -1030,25 +1241,15 @@ parse_register_list (unsigned long *insn,
if (i == 32)
return _("illegal register included in list");
}
- else if (system_register_name (&exp, TRUE, TRUE))
+ else if (system_register_name (&exp, TRUE))
{
if (regs == type1_regs)
{
return _("system registers cannot be included in list");
}
- else if (exp.X_add_number == 5)
- {
- if (regs == type2_regs)
- return _("PSW cannot be included in list");
- else
- *insn |= 0x8;
- }
- else if (exp.X_add_number < 4)
- *insn |= 0x80000;
- else
- return _("High value system registers cannot be included in list");
}
- else if (*input_line_pointer == '}')
+
+ if (*input_line_pointer == '}')
{
input_line_pointer++;
break;
@@ -1071,7 +1272,11 @@ parse_register_list (unsigned long *insn,
if (! register_name (&exp2))
{
return _("second register should follow dash in register list");
- exp2.X_add_number = exp.X_add_number;
+ }
+
+ if (exp.X_add_number > exp2.X_add_number)
+ {
+ return _("second register should greater tahn first register");
}
/* Add the rest of the registers in the range. */
@@ -1093,11 +1298,11 @@ parse_register_list (unsigned long *insn,
if (i == 32)
return _("illegal register included in list");
}
+
+ exp = exp2;
}
else
break;
-
- skip_white_space ();
}
return NULL;
@@ -1107,6 +1312,10 @@ const char *md_shortopts = "m:";
struct option md_longopts[] =
{
+#define OPTION_DISP_SIZE_DEFAULT_22 (OPTION_MD_BASE)
+ {"disp-size-default-22", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_22},
+#define OPTION_DISP_SIZE_DEFAULT_32 (OPTION_MD_BASE + 1)
+ {"disp-size-default-32", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_32},
{NULL, no_argument, NULL, 0}
};
@@ -1121,15 +1330,33 @@ md_show_usage (FILE *stream)
fprintf (stream, _(" -mv850 The code is targeted at the v850\n"));
fprintf (stream, _(" -mv850e The code is targeted at the v850e\n"));
fprintf (stream, _(" -mv850e1 The code is targeted at the v850e1\n"));
- fprintf (stream, _(" -mv850any The code is generic, despite any processor specific instructions\n"));
+ fprintf (stream, _(" -mv850e2 The code is targeted at the v850e2\n"));
+ fprintf (stream, _(" -mv850e2v3 The code is targeted at the v850e2v3\n"));
fprintf (stream, _(" -mrelax Enable relaxation\n"));
+ fprintf (stream, _(" --disp-size-default-22 branch displacement with unknown size is 22 bits (default)\n"));
+ fprintf (stream, _(" --disp-size-default-32 branch displacement with unknown size is 32 bits\n"));
+ fprintf (stream, _(" -mextension enable extension opcode support\n"));
+ fprintf (stream, _(" -mno-bcond17 disable b<cond> disp17 instruction\n"));
+ fprintf (stream, _(" -mno-stld23 disable st/ld offset23 instruction\n"));
}
int
md_parse_option (int c, char *arg)
{
if (c != 'm')
- return 0;
+ {
+ switch (c)
+ {
+ case OPTION_DISP_SIZE_DEFAULT_22:
+ default_disp_size = 22;
+ return 1;
+
+ case OPTION_DISP_SIZE_DEFAULT_32:
+ default_disp_size = 32;
+ return 1;
+ }
+ return 0;
+ }
if (strcmp (arg, "warn-signed-overflow") == 0)
warn_signed_overflows = TRUE;
@@ -1140,26 +1367,39 @@ md_parse_option (int c, char *arg)
else if (strcmp (arg, "v850") == 0)
{
machine = 0;
- processor_mask = PROCESSOR_V850;
+ SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850);
}
else if (strcmp (arg, "v850e") == 0)
{
machine = bfd_mach_v850e;
- processor_mask = PROCESSOR_V850E;
+ SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E);
}
else if (strcmp (arg, "v850e1") == 0)
{
machine = bfd_mach_v850e1;
- processor_mask = PROCESSOR_V850E1;
+ SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E1);
}
- else if (strcmp (arg, "v850any") == 0)
+ else if (strcmp (arg, "v850e2") == 0)
{
- /* Tell the world that this is for any v850 chip. */
- machine = 0;
-
- /* But support instructions for the extended versions. */
- processor_mask = PROCESSOR_V850E;
- processor_mask |= PROCESSOR_V850E1;
+ machine = bfd_mach_v850e2;
+ SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E2);
+ }
+ else if (strcmp (arg, "v850e2v3") == 0)
+ {
+ machine = bfd_mach_v850e2v3;
+ SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E2V3);
+ }
+ else if (strcmp (arg, "extension") == 0)
+ {
+ processor_mask |= PROCESSOR_OPTION_EXTENSION | PROCESSOR_OPTION_ALIAS;;
+ }
+ else if (strcmp (arg, "no-bcond17") == 0)
+ {
+ no_bcond17 = 1;
+ }
+ else if (strcmp (arg, "no-stld23") == 0)
+ {
+ no_stld23 = 1;
}
else if (strcmp (arg, "relax") == 0)
v850_relax = 1;
@@ -1188,13 +1428,6 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
asection *sec,
fragS *fragP)
{
- /* This code performs some nasty type punning between the
- fr_opcode field of the frag structure (a char *) and the
- fx_r_type field of the fix structure (a bfd_reloc_code_real_type)
- On a 64bit host this causes problems because these two fields
- are not the same size, but since we know that we are only
- ever storing small integers in the fields, it is safe to use
- a union to convert between them. */
union u
{
bfd_reloc_code_real_type fx_r_type;
@@ -1204,17 +1437,52 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
subseg_change (sec, 0);
opcode_converter.fr_opcode = fragP->fr_opcode;
-
+
+ subseg_change (sec, 0);
+
/* In range conditional or unconditional branch. */
- if (fragP->fr_subtype == 0 || fragP->fr_subtype == 2)
+ if (fragP->fr_subtype == SUBYPTE_COND_9_22
+ || fragP->fr_subtype == SUBYPTE_UNCOND_9_22
+ || fragP->fr_subtype == SUBYPTE_COND_9_22_32
+ || fragP->fr_subtype == SUBYPTE_UNCOND_9_22_32
+ || fragP->fr_subtype == SUBYPTE_COND_9_17_22
+ || fragP->fr_subtype == SUBYPTE_COND_9_17_22_32
+ || fragP->fr_subtype == SUBYPTE_SA_9_22
+ || fragP->fr_subtype == SUBYPTE_SA_9_22_32
+ || fragP->fr_subtype == SUBYPTE_SA_9_17_22
+ || fragP->fr_subtype == SUBYPTE_SA_9_17_22_32)
+
{
fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
fragP->fr_offset, 1,
BFD_RELOC_UNUSED + opcode_converter.fx_r_type);
fragP->fr_fix += 2;
}
- /* Out of range conditional branch. Emit a branch around a jump. */
- else if (fragP->fr_subtype == 1)
+ /* V850e2r-v3 17bit conditional branch. */
+ else if (fragP->fr_subtype == SUBYPTE_COND_9_17_22 + 1
+ || fragP->fr_subtype == SUBYPTE_COND_9_17_22_32 + 1
+ || fragP->fr_subtype == SUBYPTE_SA_9_17_22 + 1
+ || fragP->fr_subtype == SUBYPTE_SA_9_17_22_32 + 1)
+ {
+ unsigned char *buffer =
+ (unsigned char *) (fragP->fr_fix + fragP->fr_literal);
+
+ buffer[0] &= 0x0f; /* Use condition. */
+ buffer[0] |= 0xe0;
+ buffer[1] = 0x07;
+
+ /* Now create the unconditional branch + fixup to the final
+ target. */
+ md_number_to_chars ((char *) buffer + 2, 0x0001, 2);
+ fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1, BFD_RELOC_V850_17_PCREL);
+ fragP->fr_fix += 4;
+ }
+ /* Out of range conditional branch. Emit a branch around a 22bit jump. */
+ else if (fragP->fr_subtype == SUBYPTE_COND_9_22 + 1
+ || fragP->fr_subtype == SUBYPTE_COND_9_22_32 + 1
+ || fragP->fr_subtype == SUBYPTE_COND_9_17_22 + 2
+ || fragP->fr_subtype == SUBYPTE_COND_9_17_22_32 + 2)
{
unsigned char *buffer =
(unsigned char *) (fragP->fr_fix + fragP->fr_literal);
@@ -1232,19 +1500,99 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
target. */
md_number_to_chars ((char *) buffer + 2, 0x00000780, 4);
fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol,
- fragP->fr_offset, 1,
- BFD_RELOC_UNUSED + opcode_converter.fx_r_type + 1);
+ fragP->fr_offset, 1, BFD_RELOC_V850_22_PCREL);
fragP->fr_fix += 6;
}
- /* Out of range unconditional branch. Emit a jump. */
- else if (fragP->fr_subtype == 3)
+ /* Out of range conditional branch. Emit a branch around a 32bit jump. */
+ else if (fragP->fr_subtype == SUBYPTE_COND_9_22_32 + 2
+ || fragP->fr_subtype == SUBYPTE_COND_9_17_22_32 + 3)
+ {
+ unsigned char *buffer =
+ (unsigned char *) (fragP->fr_fix + fragP->fr_literal);
+
+ /* Reverse the condition of the first branch. */
+ buffer[0] ^= 0x08;
+ /* Mask off all the displacement bits. */
+ buffer[0] &= 0x8f;
+ buffer[1] &= 0x07;
+ /* Now set the displacement bits so that we branch
+ around the unconditional branch. */
+ buffer[0] |= 0x40;
+
+ /* Now create the unconditional branch + fixup to the final
+ target. */
+ md_number_to_chars ((char *) buffer + 2, 0x02e0, 2);
+ fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol,
+ fragP->fr_offset + 2, 1, BFD_RELOC_V850_32_PCREL);
+ fragP->fr_fix += 8;
+ }
+ /* Out of range unconditional branch. Emit a 22bit jump. */
+ else if (fragP->fr_subtype == SUBYPTE_UNCOND_9_22 + 1
+ || fragP->fr_subtype == SUBYPTE_UNCOND_9_22_32 + 1)
{
md_number_to_chars (fragP->fr_fix + fragP->fr_literal, 0x00000780, 4);
fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol,
- fragP->fr_offset, 1,
- BFD_RELOC_UNUSED + opcode_converter.fx_r_type + 1);
+ fragP->fr_offset, 1, BFD_RELOC_V850_22_PCREL);
fragP->fr_fix += 4;
}
+ /* Out of range unconditional branch. Emit a 32bit jump. */
+ else if (fragP->fr_subtype == SUBYPTE_UNCOND_9_22_32 + 2)
+ {
+ md_number_to_chars (fragP->fr_fix + fragP->fr_literal, 0x02e0, 2);
+ fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol,
+ fragP->fr_offset + 2, 1, BFD_RELOC_V850_32_PCREL);
+ fragP->fr_fix += 6;
+ }
+ /* Out of range SA conditional branch. Emit a branch to a 22bit jump. */
+ else if (fragP->fr_subtype == SUBYPTE_SA_9_22 + 1
+ || fragP->fr_subtype == SUBYPTE_SA_9_22_32 + 1
+ || fragP->fr_subtype == SUBYPTE_SA_9_17_22 + 2
+ || fragP->fr_subtype == SUBYPTE_SA_9_17_22_32 + 2)
+ {
+ unsigned char *buffer =
+ (unsigned char *) (fragP->fr_fix + fragP->fr_literal);
+
+ /* bsa .+4 */
+ buffer[0] &= 0x8f;
+ buffer[0] |= 0x20;
+ buffer[1] &= 0x07;
+
+ /* br .+6 */
+ md_number_to_chars ((char *) buffer + 2, 0x05b5, 2);
+
+ /* Now create the unconditional branch + fixup to the final
+ target. */
+ /* jr SYM */
+ md_number_to_chars ((char *) buffer + 4, 0x00000780, 4);
+ fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol,
+ fragP->fr_offset, 1,
+ BFD_RELOC_V850_22_PCREL);
+ fragP->fr_fix += 8;
+ }
+ /* Out of range SA conditional branch. Emit a branch around a 32bit jump. */
+ else if (fragP->fr_subtype == SUBYPTE_SA_9_22_32 + 2
+ || fragP->fr_subtype == SUBYPTE_SA_9_17_22_32 + 3)
+ {
+ unsigned char *buffer =
+ (unsigned char *) (fragP->fr_fix + fragP->fr_literal);
+
+ /* bsa .+2 */
+ buffer[0] &= 0x8f;
+ buffer[0] |= 0x20;
+ buffer[1] &= 0x07;
+
+ /* br .+8 */
+ md_number_to_chars ((char *) buffer + 2, 0x05c5, 2);
+
+ /* Now create the unconditional branch + fixup to the final
+ target. */
+ /* jr SYM */
+ md_number_to_chars ((char *) buffer + 4, 0x02e0, 2);
+ fix_new (fragP, fragP->fr_fix + 6, 4, fragP->fr_symbol,
+ fragP->fr_offset + 2, 1, BFD_RELOC_V850_32_PCREL);
+
+ fragP->fr_fix += 10;
+ }
else
abort ();
}
@@ -1262,29 +1610,45 @@ md_begin (void)
char *prev_name = "";
const struct v850_opcode *op;
- if (strncmp (TARGET_CPU, "v850e1", 6) == 0)
+ if (strncmp (TARGET_CPU, "v850e2v3", 8) == 0)
+ {
+ if (machine == -1)
+ machine = bfd_mach_v850e2v3;
+
+ if (!processor_mask)
+ SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E2V3);
+ }
+ else if (strncmp (TARGET_CPU, "v850e2", 6) == 0)
+ {
+ if (machine == -1)
+ machine = bfd_mach_v850e2;
+
+ if (!processor_mask)
+ SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E2);
+ }
+ else if (strncmp (TARGET_CPU, "v850e1", 6) == 0)
{
if (machine == -1)
- machine = bfd_mach_v850e1;
+ machine = bfd_mach_v850e1;
- if (processor_mask == -1)
- processor_mask = PROCESSOR_V850E1;
+ if (!processor_mask)
+ SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E1);
}
else if (strncmp (TARGET_CPU, "v850e", 5) == 0)
{
if (machine == -1)
machine = bfd_mach_v850e;
- if (processor_mask == -1)
- processor_mask = PROCESSOR_V850E;
+ if (!processor_mask)
+ SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E);
}
else if (strncmp (TARGET_CPU, "v850", 4) == 0)
{
if (machine == -1)
machine = 0;
- if (processor_mask == -1)
- processor_mask = PROCESSOR_V850;
+ if (!processor_mask)
+ SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850);
}
else
/* xgettext:c-format */
@@ -1312,119 +1676,158 @@ md_begin (void)
bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine);
}
+
static bfd_reloc_code_real_type
-handle_lo16 (const struct v850_operand *operand)
+handle_hi016 (const struct v850_operand *operand, const char **errmsg)
{
- if (operand != NULL)
- {
- if (operand->bits == -1)
- return BFD_RELOC_V850_LO16_SPLIT_OFFSET;
+ if (operand == NULL)
+ return BFD_RELOC_HI16;
- if (!(operand->bits == 16 && operand->shift == 16)
- && !(operand->bits == 15 && operand->shift == 17))
- {
- as_bad (_("lo() relocation used on an instruction which does "
- "not support it"));
- return BFD_RELOC_64; /* Used to indicate an error condition. */
- }
- }
- return BFD_RELOC_LO16;
+ if (operand->default_reloc == BFD_RELOC_HI16)
+ return BFD_RELOC_HI16;
+
+ if (operand->default_reloc == BFD_RELOC_HI16_S)
+ return BFD_RELOC_HI16;
+
+ if (operand->default_reloc == BFD_RELOC_16)
+ return BFD_RELOC_HI16;
+
+ *errmsg = _("hi0() relocation used on an instruction which does "
+ "not support it");
+ return BFD_RELOC_64; /* Used to indicate an error condition. */
}
static bfd_reloc_code_real_type
-handle_ctoff (const struct v850_operand *operand)
+handle_hi16 (const struct v850_operand *operand, const char **errmsg)
+{
+ if (operand == NULL)
+ return BFD_RELOC_HI16_S;
+
+ if (operand->default_reloc == BFD_RELOC_HI16_S)
+ return BFD_RELOC_HI16_S;
+
+ if (operand->default_reloc == BFD_RELOC_HI16)
+ return BFD_RELOC_HI16_S;
+
+ if (operand->default_reloc == BFD_RELOC_16)
+ return BFD_RELOC_HI16_S;
+
+ *errmsg = _("hi() relocation used on an instruction which does "
+ "not support it");
+ return BFD_RELOC_64; /* Used to indicate an error condition. */
+}
+
+static bfd_reloc_code_real_type
+handle_lo16 (const struct v850_operand *operand, const char **errmsg)
+{
+ if (operand == NULL)
+ return BFD_RELOC_LO16;
+
+ if (operand->default_reloc == BFD_RELOC_LO16)
+ return BFD_RELOC_LO16;
+
+ if (operand->default_reloc == BFD_RELOC_V850_16_SPLIT_OFFSET)
+ return BFD_RELOC_V850_LO16_SPLIT_OFFSET;
+
+ if (operand->default_reloc == BFD_RELOC_V850_16_S1)
+ return BFD_RELOC_V850_LO16_S1;
+
+ if (operand->default_reloc == BFD_RELOC_16)
+ return BFD_RELOC_LO16;
+
+ *errmsg = _("lo() relocation used on an instruction which does "
+ "not support it");
+ return BFD_RELOC_64; /* Used to indicate an error condition. */
+}
+
+static bfd_reloc_code_real_type
+handle_ctoff (const struct v850_operand *operand, const char **errmsg)
{
if (operand == NULL)
return BFD_RELOC_V850_CALLT_16_16_OFFSET;
- if (operand->bits != 6
- || operand->shift != 0)
- {
- as_bad (_("ctoff() relocation used on an instruction which does not support it"));
- return BFD_RELOC_64; /* Used to indicate an error condition. */
- }
+ if (operand->default_reloc == BFD_RELOC_V850_CALLT_6_7_OFFSET)
+ return operand->default_reloc;
- return BFD_RELOC_V850_CALLT_6_7_OFFSET;
+ if (operand->default_reloc == BFD_RELOC_V850_16_S1)
+ return BFD_RELOC_V850_CALLT_15_16_OFFSET;
+
+ if (operand->default_reloc == BFD_RELOC_16)
+ return BFD_RELOC_V850_CALLT_16_16_OFFSET;
+
+ *errmsg = _("ctoff() relocation used on an instruction which does not support it");
+ return BFD_RELOC_64; /* Used to indicate an error condition. */
}
static bfd_reloc_code_real_type
-handle_sdaoff (const struct v850_operand *operand)
+handle_sdaoff (const struct v850_operand *operand, const char **errmsg)
{
if (operand == NULL)
return BFD_RELOC_V850_SDA_16_16_OFFSET;
- if (operand->bits == 15 && operand->shift == 17)
- return BFD_RELOC_V850_SDA_15_16_OFFSET;
-
- if (operand->bits == -1)
+ if (operand->default_reloc == BFD_RELOC_V850_16_SPLIT_OFFSET)
return BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET;
- if (operand->bits != 16
- || operand->shift != 16)
- {
- as_bad (_("sdaoff() relocation used on an instruction which does not support it"));
- return BFD_RELOC_64; /* Used to indicate an error condition. */
- }
+ if (operand->default_reloc == BFD_RELOC_16)
+ return BFD_RELOC_V850_SDA_16_16_OFFSET;
+
+ if (operand->default_reloc == BFD_RELOC_V850_16_S1)
+ return BFD_RELOC_V850_SDA_15_16_OFFSET;
- return BFD_RELOC_V850_SDA_16_16_OFFSET;
+ *errmsg = _("sdaoff() relocation used on an instruction which does not support it");
+ return BFD_RELOC_64; /* Used to indicate an error condition. */
}
static bfd_reloc_code_real_type
-handle_zdaoff (const struct v850_operand *operand)
+handle_zdaoff (const struct v850_operand *operand, const char **errmsg)
{
if (operand == NULL)
return BFD_RELOC_V850_ZDA_16_16_OFFSET;
- if (operand->bits == 15 && operand->shift == 17)
- return BFD_RELOC_V850_ZDA_15_16_OFFSET;
-
- if (operand->bits == -1)
+ if (operand->default_reloc == BFD_RELOC_V850_16_SPLIT_OFFSET)
return BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET;
- if (operand->bits != 16
- || operand->shift != 16)
- {
- as_bad (_("zdaoff() relocation used on an instruction which does not support it"));
- /* Used to indicate an error condition. */
- return BFD_RELOC_64;
- }
+ if (operand->default_reloc == BFD_RELOC_16)
+ return BFD_RELOC_V850_ZDA_16_16_OFFSET;
+
+ if (operand->default_reloc == BFD_RELOC_V850_16_S1)
+ return BFD_RELOC_V850_ZDA_15_16_OFFSET;
- return BFD_RELOC_V850_ZDA_16_16_OFFSET;
+ *errmsg = _("zdaoff() relocation used on an instruction which does not support it");
+ return BFD_RELOC_64; /* Used to indicate an error condition. */
}
static bfd_reloc_code_real_type
-handle_tdaoff (const struct v850_operand *operand)
+handle_tdaoff (const struct v850_operand *operand, const char **errmsg)
{
if (operand == NULL)
/* Data item, not an instruction. */
- return BFD_RELOC_V850_TDA_7_7_OFFSET;
+ return BFD_RELOC_V850_TDA_16_16_OFFSET;
- if (operand->bits == 6 && operand->shift == 1)
+ switch (operand->default_reloc)
+ {
+ /* sld.hu, operand: D5-4. */
+ case BFD_RELOC_V850_TDA_4_5_OFFSET:
+ /* sld.bu, operand: D4. */
+ case BFD_RELOC_V850_TDA_4_4_OFFSET:
/* sld.w/sst.w, operand: D8_6. */
- return BFD_RELOC_V850_TDA_6_8_OFFSET;
-
- if (operand->bits == 4 && operand->insert != NULL)
- /* sld.hu, operand: D5-4. */
- return BFD_RELOC_V850_TDA_4_5_OFFSET;
-
- if (operand->bits == 4 && operand->insert == NULL)
- /* sld.bu, operand: D4. */
- return BFD_RELOC_V850_TDA_4_4_OFFSET;
+ case BFD_RELOC_V850_TDA_6_8_OFFSET:
+ /* sld.h/sst.h, operand: D8_7. */
+ case BFD_RELOC_V850_TDA_7_8_OFFSET:
+ /* sld.b/sst.b, operand: D7. */
+ case BFD_RELOC_V850_TDA_7_7_OFFSET:
+ return operand->default_reloc;
+ default:
+ break;
+ }
- if (operand->bits == 16 && operand->shift == 16)
+ if (operand->default_reloc == BFD_RELOC_16 && operand->shift == 16)
/* set1 & chums, operands: D16. */
return BFD_RELOC_V850_TDA_16_16_OFFSET;
- if (operand->bits != 7)
- {
- as_bad (_("tdaoff() relocation used on an instruction which does not support it"));
- /* Used to indicate an error condition. */
- return BFD_RELOC_64;
- }
-
- return operand->insert != NULL
- ? BFD_RELOC_V850_TDA_7_8_OFFSET /* sld.h/sst.h, operand: D8_7. */
- : BFD_RELOC_V850_TDA_7_7_OFFSET; /* sld.b/sst.b, operand: D7. */
+ *errmsg = _("tdaoff() relocation used on an instruction which does not support it");
+ /* Used to indicate an error condition. */
+ return BFD_RELOC_64;
}
/* Warning: The code in this function relies upon the definitions
@@ -1432,7 +1835,7 @@ handle_tdaoff (const struct v850_operand *operand)
matching the hard coded values contained herein. */
static bfd_reloc_code_real_type
-v850_reloc_prefix (const struct v850_operand *operand)
+v850_reloc_prefix (const struct v850_operand *operand, const char **errmsg)
{
bfd_boolean paren_skipped = FALSE;
@@ -1450,14 +1853,15 @@ v850_reloc_prefix (const struct v850_operand *operand)
return reloc; \
}
- CHECK_ ("hi0", BFD_RELOC_HI16 );
- CHECK_ ("hi", BFD_RELOC_HI16_S );
- CHECK_ ("lo", handle_lo16 (operand) );
- CHECK_ ("sdaoff", handle_sdaoff (operand));
- CHECK_ ("zdaoff", handle_zdaoff (operand));
- CHECK_ ("tdaoff", handle_tdaoff (operand));
- CHECK_ ("hilo", BFD_RELOC_32 );
- CHECK_ ("ctoff", handle_ctoff (operand) );
+ CHECK_ ("hi0", handle_hi016(operand, errmsg) );
+ CHECK_ ("hi", handle_hi16(operand, errmsg) );
+ CHECK_ ("lo", handle_lo16 (operand, errmsg) );
+ CHECK_ ("sdaoff", handle_sdaoff (operand, errmsg));
+ CHECK_ ("zdaoff", handle_zdaoff (operand, errmsg));
+ CHECK_ ("tdaoff", handle_tdaoff (operand, errmsg));
+ CHECK_ ("hilo", BFD_RELOC_32);
+ CHECK_ ("lo23", BFD_RELOC_V850_23);
+ CHECK_ ("ctoff", handle_ctoff (operand, errmsg) );
/* Restore skipped parenthesis. */
if (paren_skipped)
@@ -1472,9 +1876,7 @@ static unsigned long
v850_insert_operand (unsigned long insn,
const struct v850_operand *operand,
offsetT val,
- char *file,
- unsigned int line,
- char *str)
+ const char **errmsg)
{
if (operand->insert)
{
@@ -1485,35 +1887,33 @@ v850_insert_operand (unsigned long insn,
{
if ((operand->flags & V850_OPERAND_SIGNED)
&& ! warn_signed_overflows
- && strstr (message, "out of range") != NULL)
+ && v850_msg_is_out_of_range (message))
{
/* Skip warning... */
}
else if ((operand->flags & V850_OPERAND_SIGNED) == 0
&& ! warn_unsigned_overflows
- && strstr (message, "out of range") != NULL)
+ && v850_msg_is_out_of_range (message))
{
/* Skip warning... */
}
- else if (str)
- {
- if (file == (char *) NULL)
- as_warn ("%s: %s", str, message);
- else
- as_warn_where (file, line, "%s: %s", str, message);
- }
else
{
- if (file == (char *) NULL)
- as_warn ("%s", message);
- else
- as_warn_where (file, line, "%s", message);
+ if (errmsg != NULL)
+ *errmsg = message;
}
}
}
+ else if (operand->bits == -1
+ || operand->flags & V850E_IMMEDIATE16
+ || operand->flags & V850E_IMMEDIATE23
+ || operand->flags & V850E_IMMEDIATE32)
+ {
+ abort ();
+ }
else
{
- if (operand->bits != 32)
+ if (operand->bits < 32)
{
long min, max;
@@ -1566,17 +1966,17 @@ v850_insert_operand (unsigned long insn,
&& ! warn_unsigned_overflows)
min = 0;
- if (str)
- sprintf (buf, "%s: ", str);
- else
- buf[0] = 0;
- strcat (buf, _("operand"));
-
- as_bad_value_out_of_range (buf, val, (offsetT) min, (offsetT) max, file, line);
+ sprintf (buf, _("operand out of range (%d is not between %d and %d)"),
+ (int) val, (int) min, (int) max);
+ *errmsg = buf;
}
- }
- insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
+ insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift);
+ }
+ else
+ {
+ insn |= (((long) val) << operand->shift);
+ }
}
return insn;
@@ -1603,8 +2003,11 @@ md_assemble (char *str)
unsigned extra_data_len = 0;
unsigned long extra_data = 0;
char *saved_input_line_pointer;
+ char most_match_errmsg[1024];
+ int most_match_count = -1;
strncpy (copy_of_instruction, str, sizeof (copy_of_instruction) - 1);
+ most_match_errmsg[0] = 0;
/* Get the opcode. */
for (s = str; *s != '\0' && ! ISSPACE (*s); s++)
@@ -1634,10 +2037,26 @@ md_assemble (char *str)
for (;;)
{
const char *errmsg = NULL;
+ const char *warningmsg = NULL;
match = 0;
+ opindex_ptr = opcode->operands;
- if ((opcode->processors & processor_mask) == 0)
+ if (no_stld23)
+ {
+ if ((strncmp (opcode->name, "st.", 3) == 0
+ && v850_operands[opcode->operands[1]].bits == 23)
+ || (strncmp (opcode->name, "ld.", 3) == 0
+ && v850_operands[opcode->operands[0]].bits == 23))
+ {
+ errmsg = _("st/ld offset 23 instruction was disabled .");
+ goto error;
+ }
+ }
+
+ if ((opcode->processors & processor_mask & PROCESSOR_MASK) == 0
+ || (((opcode->processors & ~PROCESSOR_MASK) != 0)
+ && ((opcode->processors & processor_mask & ~PROCESSOR_MASK) == 0)))
{
errmsg = _("Target processor does not support this instruction.");
goto error;
@@ -1647,6 +2066,7 @@ md_assemble (char *str)
fc = 0;
next_opindex = 0;
insn = opcode->opcode;
+ extra_data_len = 0;
extra_data_after_insn = FALSE;
input_line_pointer = str = start_of_operands;
@@ -1668,7 +2088,20 @@ md_assemble (char *str)
errmsg = NULL;
- while (*str == ' ' || *str == ',' || *str == '[' || *str == ']')
+ while (*str == ' ')
+ ++str;
+
+ if (operand->flags & V850_OPERAND_BANG
+ && *str == '!')
+ ++str;
+ else if (operand->flags & V850_OPERAND_PERCENT
+ && *str == '%')
+ ++str;
+
+ if (*str == ',' || *str == '[' || *str == ']')
+ ++str;
+
+ while (*str == ' ')
++str;
if (operand->flags & V850_OPERAND_RELAX)
@@ -1679,12 +2112,12 @@ md_assemble (char *str)
input_line_pointer = str;
/* lo(), hi(), hi0(), etc... */
- if ((reloc = v850_reloc_prefix (operand)) != BFD_RELOC_UNUSED)
+ if ((reloc = v850_reloc_prefix (operand, &errmsg)) != BFD_RELOC_UNUSED)
{
/* This is a fake reloc, used to indicate an error condition. */
if (reloc == BFD_RELOC_64)
{
- match = 1;
+ /* match = 1; */
goto error;
}
@@ -1695,11 +2128,14 @@ md_assemble (char *str)
switch (reloc)
{
case BFD_RELOC_V850_ZDA_16_16_OFFSET:
+ case BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET:
+ case BFD_RELOC_V850_ZDA_15_16_OFFSET:
/* To cope with "not1 7, zdaoff(0xfffff006)[r0]"
and the like. */
/* Fall through. */
case BFD_RELOC_LO16:
+ case BFD_RELOC_V850_LO16_S1:
case BFD_RELOC_V850_LO16_SPLIT_OFFSET:
{
/* Truncate, then sign extend the value. */
@@ -1725,16 +2161,23 @@ md_assemble (char *str)
break;
}
+ case BFD_RELOC_V850_23:
+ if ((operand->flags & V850E_IMMEDIATE23) == 0)
+ {
+ errmsg = _("immediate operand is too large");
+ goto error;
+ }
+ break;
+
case BFD_RELOC_32:
+ case BFD_RELOC_V850_32_ABS:
+ case BFD_RELOC_V850_32_PCREL:
if ((operand->flags & V850E_IMMEDIATE32) == 0)
{
errmsg = _("immediate operand is too large");
goto error;
}
- extra_data_after_insn = TRUE;
- extra_data_len = 4;
- extra_data = 0;
break;
default:
@@ -1743,6 +2186,45 @@ md_assemble (char *str)
break;
}
+ if (operand->flags & V850E_IMMEDIATE32)
+ {
+ extra_data_after_insn = TRUE;
+ extra_data_len = 4;
+ extra_data = 0;
+ }
+ else if (operand->flags & V850E_IMMEDIATE23)
+ {
+ if (reloc != BFD_RELOC_V850_23)
+ {
+ errmsg = _("immediate operand is too large");
+ goto error;
+ }
+ extra_data_after_insn = TRUE;
+ extra_data_len = 2;
+ extra_data = 0;
+ }
+ else if ((operand->flags & V850E_IMMEDIATE16)
+ || (operand->flags & V850E_IMMEDIATE16HI))
+ {
+ if (operand->flags & V850E_IMMEDIATE16HI
+ && reloc != BFD_RELOC_HI16
+ && reloc != BFD_RELOC_HI16_S)
+ {
+ errmsg = _("immediate operand is too large");
+ goto error;
+ }
+ else if (operand->flags & V850E_IMMEDIATE16
+ && reloc != BFD_RELOC_LO16)
+ {
+ errmsg = _("immediate operand is too large");
+ goto error;
+ }
+
+ extra_data_after_insn = TRUE;
+ extra_data_len = 2;
+ extra_data = 0;
+ }
+
if (fc > MAX_INSN_FIXUPS)
as_fatal (_("too many fixups"));
@@ -1751,19 +2233,67 @@ md_assemble (char *str)
fixups[fc].reloc = reloc;
fc++;
}
- else
+ else /* ex.X_op != O_constant. */
{
- if (reloc == BFD_RELOC_32)
+ if ((reloc == BFD_RELOC_32
+ || reloc == BFD_RELOC_V850_32_ABS
+ || reloc == BFD_RELOC_V850_32_PCREL)
+ && operand->bits < 32)
{
- if ((operand->flags & V850E_IMMEDIATE32) == 0)
+ errmsg = _("immediate operand is too large");
+ goto error;
+ }
+ else if (reloc == BFD_RELOC_V850_23
+ && (operand->flags & V850E_IMMEDIATE23) == 0)
+ {
+ errmsg = _("immediate operand is too large");
+ goto error;
+ }
+ else if ((reloc == BFD_RELOC_HI16
+ || reloc == BFD_RELOC_HI16_S)
+ && operand->bits < 16)
+ {
+ errmsg = _("immediate operand is too large");
+ goto error;
+ }
+
+ if (operand->flags & V850E_IMMEDIATE32)
+ {
+ extra_data_after_insn = TRUE;
+ extra_data_len = 4;
+ extra_data = 0;
+ }
+ else if (operand->flags & V850E_IMMEDIATE23)
+ {
+ if (reloc != BFD_RELOC_V850_23)
+ {
+ errmsg = _("immediate operand is too large");
+ goto error;
+ }
+ extra_data_after_insn = TRUE;
+ extra_data_len = 2;
+ extra_data = 0;
+ }
+ else if ((operand->flags & V850E_IMMEDIATE16)
+ || (operand->flags & V850E_IMMEDIATE16HI))
+ {
+ if (operand->flags & V850E_IMMEDIATE16HI
+ && reloc != BFD_RELOC_HI16
+ && reloc != BFD_RELOC_HI16_S)
+ {
+ errmsg = _("immediate operand is too large");
+ goto error;
+ }
+ else if (operand->flags & V850E_IMMEDIATE16
+ && reloc != BFD_RELOC_LO16)
{
errmsg = _("immediate operand is too large");
goto error;
}
extra_data_after_insn = TRUE;
- extra_data_len = 4;
- extra_data = ex.X_add_number;
+ extra_data_len = 2;
+ extra_data = 0;
}
if (fc > MAX_INSN_FIXUPS)
@@ -1775,6 +2305,140 @@ md_assemble (char *str)
fc++;
}
}
+ else if (operand->flags & V850E_IMMEDIATE16
+ || operand->flags & V850E_IMMEDIATE16HI)
+ {
+ expression (&ex);
+
+ switch (ex.X_op)
+ {
+ case O_constant:
+ if (operand->flags & V850E_IMMEDIATE16HI)
+ {
+ if (ex.X_add_number & 0xffff)
+ {
+ errmsg = _("constant too big to fit into instruction");
+ goto error;
+ }
+
+ ex.X_add_number >>= 16;
+ }
+ if (operand->flags & V850E_IMMEDIATE16)
+ {
+ if (ex.X_add_number & 0xffff0000)
+ {
+ errmsg = _("constant too big to fit into instruction");
+ goto error;
+ }
+ }
+ break;
+
+ case O_illegal:
+ errmsg = _("illegal operand");
+ goto error;
+
+ case O_absent:
+ errmsg = _("missing operand");
+ goto error;
+
+ default:
+ if (fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+
+ fixups[fc].exp = ex;
+ fixups[fc].opindex = *opindex_ptr;
+ fixups[fc].reloc = operand->default_reloc;
+ ++fc;
+
+ ex.X_add_number = 0;
+ break;
+ }
+
+ extra_data_after_insn = TRUE;
+ extra_data_len = 2;
+ extra_data = ex.X_add_number;
+ }
+ else if (operand->flags & V850E_IMMEDIATE23)
+ {
+ expression (&ex);
+
+ switch (ex.X_op)
+ {
+ case O_constant:
+ break;
+
+ case O_illegal:
+ errmsg = _("illegal operand");
+ goto error;
+
+ case O_absent:
+ errmsg = _("missing operand");
+ goto error;
+
+ default:
+ break;
+ }
+
+ if (fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+
+ fixups[fc].exp = ex;
+ fixups[fc].opindex = *opindex_ptr;
+ fixups[fc].reloc = operand->default_reloc;
+ ++fc;
+
+ extra_data_after_insn = TRUE;
+ extra_data_len = 2;
+ extra_data = 0;
+ }
+ else if (operand->flags & V850E_IMMEDIATE32)
+ {
+ expression (&ex);
+
+ switch (ex.X_op)
+ {
+ case O_constant:
+ if ((operand->default_reloc == BFD_RELOC_V850_32_ABS
+ || operand->default_reloc == BFD_RELOC_V850_32_PCREL)
+ && (ex.X_add_number & 1))
+ {
+ errmsg = _("odd number cannot be used here");
+ goto error;
+ }
+ break;
+
+ case O_illegal:
+ errmsg = _("illegal operand");
+ goto error;
+
+ case O_absent:
+ errmsg = _("missing operand");
+ goto error;
+
+ default:
+ if (fc >= MAX_INSN_FIXUPS)
+ as_fatal (_("too many fixups"));
+
+ fixups[fc].exp = ex;
+ fixups[fc].opindex = *opindex_ptr;
+ fixups[fc].reloc = operand->default_reloc;
+ ++fc;
+
+ ex.X_add_number = 0;
+ break;
+ }
+
+ extra_data_after_insn = TRUE;
+ extra_data_len = 4;
+ extra_data = ex.X_add_number;
+ }
+ else if (operand->flags & V850E_OPERAND_REG_LIST)
+ {
+ errmsg = parse_register_list (&insn, operand);
+
+ if (errmsg)
+ goto error;
+ }
else
{
errmsg = NULL;
@@ -1782,22 +2446,30 @@ md_assemble (char *str)
if ((operand->flags & V850_OPERAND_REG) != 0)
{
if (!register_name (&ex))
- errmsg = _("invalid register name");
- else if ((operand->flags & V850_NOT_R0)
+ {
+ errmsg = _("invalid register name");
+ }
+
+ if ((operand->flags & V850_NOT_R0)
&& ex.X_add_number == 0)
{
errmsg = _("register r0 cannot be used here");
+ }
- /* Force an error message to be generated by
- skipping over any following potential matches
- for this opcode. */
- opcode += 3;
+ if (operand->flags & V850_REG_EVEN)
+ {
+ if (ex.X_add_number % 2)
+ errmsg = _("odd register cannot be used here");
+ ex.X_add_number = ex.X_add_number / 2;
}
+
}
else if ((operand->flags & V850_OPERAND_SRG) != 0)
{
- if (!system_register_name (&ex, TRUE, FALSE))
- errmsg = _("invalid system register name");
+ if (!system_register_name (&ex, TRUE))
+ {
+ errmsg = _("invalid system register name");
+ }
}
else if ((operand->flags & V850_OPERAND_EP) != 0)
{
@@ -1824,53 +2496,26 @@ md_assemble (char *str)
}
else if ((operand->flags & V850_OPERAND_CC) != 0)
{
- if (!cc_name (&ex))
- errmsg = _("invalid condition code name");
- }
- else if (operand->flags & V850E_PUSH_POP)
- {
- errmsg = parse_register_list (&insn, operand);
-
- /* The parse_register_list() function has already done
- everything, so fake a dummy expression. */
- ex.X_op = O_constant;
- ex.X_add_number = 0;
- }
- else if (operand->flags & V850E_IMMEDIATE16)
- {
- expression (&ex);
-
- if (ex.X_op != O_constant)
- errmsg = _("constant expression expected");
- else if (ex.X_add_number & 0xffff0000)
+ if (!cc_name (&ex, TRUE))
{
- if (ex.X_add_number & 0xffff)
- errmsg = _("constant too big to fit into instruction");
- else if ((insn & 0x001fffc0) == 0x00130780)
- ex.X_add_number >>= 16;
- else
- errmsg = _("constant too big to fit into instruction");
+ errmsg = _("invalid condition code name");
}
- extra_data_after_insn = TRUE;
- extra_data_len = 2;
- extra_data = ex.X_add_number;
- ex.X_add_number = 0;
+ if ((operand->flags & V850_NOT_SA)
+ && ex.X_add_number == COND_SA_NUM)
+ {
+ errmsg = _("condition sa cannot be used here");
+ }
}
- else if (operand->flags & V850E_IMMEDIATE32)
+ else if ((operand->flags & V850_OPERAND_FLOAT_CC) != 0)
{
- expression (&ex);
-
- if (ex.X_op != O_constant)
- errmsg = _("constant expression expected");
-
- extra_data_after_insn = TRUE;
- extra_data_len = 4;
- extra_data = ex.X_add_number;
- ex.X_add_number = 0;
+ if (!float_cc_name (&ex, TRUE))
+ {
+ errmsg = _("invalid condition code name");
+ }
}
- else if (register_name (&ex)
- && (operand->flags & V850_OPERAND_REG) == 0)
+ else if ((register_name (&ex)
+ && (operand->flags & V850_OPERAND_REG) == 0))
{
char c;
int exists = 0;
@@ -1900,8 +2545,10 @@ md_assemble (char *str)
the parsing of the instruction, (because another
field is missing) then report this. */
if (opindex_ptr[1] != 0
- && (v850_operands[opindex_ptr[1]].flags
- & V850_OPERAND_REG))
+ && ((v850_operands[opindex_ptr[1]].flags
+ & V850_OPERAND_REG)
+ ||(v850_operands[opindex_ptr[1]].flags
+ & V850_OPERAND_VREG)))
errmsg = _("syntax error: value is missing before the register name");
else
errmsg = _("syntax error: register not expected");
@@ -1915,29 +2562,55 @@ md_assemble (char *str)
&symbol_rootP, &symbol_lastP);
}
}
- else if (system_register_name (&ex, FALSE, FALSE)
+ else if (system_register_name (&ex, FALSE)
&& (operand->flags & V850_OPERAND_SRG) == 0)
- errmsg = _("syntax error: system register not expected");
-
- else if (cc_name (&ex)
+ {
+ errmsg = _("syntax error: system register not expected");
+ }
+ else if (cc_name (&ex, FALSE)
&& (operand->flags & V850_OPERAND_CC) == 0)
- errmsg = _("syntax error: condition code not expected");
-
+ {
+ errmsg = _("syntax error: condition code not expected");
+ }
+ else if (float_cc_name (&ex, FALSE)
+ && (operand->flags & V850_OPERAND_FLOAT_CC) == 0)
+ {
+ errmsg = _("syntax error: condition code not expected");
+ }
else
{
expression (&ex);
+
+ if ((operand->flags & V850_NOT_IMM0)
+ && ex.X_op == O_constant
+ && ex.X_add_number == 0)
+ {
+ errmsg = _("immediate 0 cannot be used here");
+ }
+
/* Special case:
- If we are assembling a MOV instruction and the immediate
+ If we are assembling a MOV/JARL/JR instruction and the immediate
value does not fit into the bits available then create a
- fake error so that the next MOV instruction will be
+ fake error so that the next MOV/JARL/JR instruction will be
selected. This one has a 32 bit immediate field. */
- if (((insn & 0x07e0) == 0x0200)
- && operand->bits == 5 /* Do not match the CALLT instruction. */
+ if ((strcmp (opcode->name, "mov") == 0
+ || strcmp (opcode->name, "jarl") == 0
+ || strcmp (opcode->name, "jr") == 0)
&& ex.X_op == O_constant
&& (ex.X_add_number < (-(1 << (operand->bits - 1)))
|| ex.X_add_number > ((1 << (operand->bits - 1)) - 1)))
- errmsg = _("immediate operand is too large");
+ {
+ errmsg = _("immediate operand is too large");
+ }
+
+ if ((strcmp (opcode->name, "jarl") == 0
+ || strcmp (opcode->name, "jr") == 0)
+ && ex.X_op != O_constant
+ && operand->bits != default_disp_size)
+ {
+ errmsg = _("immediate operand is not match");
+ }
}
if (errmsg)
@@ -1953,18 +2626,21 @@ md_assemble (char *str)
goto error;
case O_register:
if ((operand->flags
- & (V850_OPERAND_REG | V850_OPERAND_SRG)) == 0)
+ & (V850_OPERAND_REG | V850_OPERAND_SRG | V850_OPERAND_VREG)) == 0)
{
errmsg = _("invalid operand");
goto error;
}
- insn = v850_insert_operand (insn, operand, ex.X_add_number,
- NULL, 0, copy_of_instruction);
+
+ insn = v850_insert_operand (insn, operand,
+ ex.X_add_number,
+ &warningmsg);
+
break;
case O_constant:
insn = v850_insert_operand (insn, operand, ex.X_add_number,
- NULL, 0, copy_of_instruction);
+ &warningmsg);
break;
default:
@@ -1987,11 +2663,23 @@ md_assemble (char *str)
|| *str == ')')
++str;
}
- match = 1;
+
+ while (ISSPACE (*str))
+ ++str;
+
+ if (*str == '\0')
+ match = 1;
error:
if (match == 0)
{
+ if ((opindex_ptr - opcode->operands) >= most_match_count)
+ {
+ most_match_count = opindex_ptr - opcode->operands;
+ if (errmsg != NULL)
+ strncpy (most_match_errmsg, errmsg, sizeof (most_match_errmsg)-1);
+ }
+
next_opcode = opcode + 1;
if (next_opcode->name != NULL
&& strcmp (next_opcode->name, opcode->name) == 0)
@@ -2006,7 +2694,11 @@ md_assemble (char *str)
continue;
}
- as_bad ("%s: %s", copy_of_instruction, errmsg);
+ if (most_match_errmsg[0] == 0)
+ /* xgettext:c-format. */
+ as_bad (_("junk at end of line: `%s'"), str);
+ else
+ as_bad ("%s: %s", copy_of_instruction, most_match_errmsg);
if (*input_line_pointer == ']')
++input_line_pointer;
@@ -2015,16 +2707,12 @@ md_assemble (char *str)
input_line_pointer = saved_input_line_pointer;
return;
}
+
+ if (warningmsg != NULL)
+ as_warn (warningmsg);
break;
}
- while (ISSPACE (*str))
- ++str;
-
- if (*str != '\0')
- /* xgettext:c-format */
- as_bad (_("junk at end of line: `%s'"), str);
-
input_line_pointer = str;
/* Tie dwarf2 debug info to the address at the start of the insn.
@@ -2036,40 +2724,124 @@ md_assemble (char *str)
if (relaxable && fc > 0)
{
- /* On a 64-bit host the size of an 'int' is not the same
- as the size of a pointer, so we need a union to convert
- the opindex field of the fr_cgen structure into a char *
- so that it can be stored in the frag. We do not have
- to worry about loosing accuracy as we are not going to
- be even close to the 32bit limit of the int. */
- union
- {
- int opindex;
- char * ptr;
- }
- opindex_converter;
-
- opindex_converter.opindex = fixups[0].opindex;
insn_size = 2;
fc = 0;
- if (!strcmp (opcode->name, "br"))
+ if (strcmp (opcode->name, "br") == 0
+ || strcmp (opcode->name, "jbr") == 0)
{
- f = frag_var (rs_machine_dependent, 4, 2, 2,
- fixups[0].exp.X_add_symbol,
- fixups[0].exp.X_add_number,
- opindex_converter.ptr);
- md_number_to_chars (f, insn, insn_size);
- md_number_to_chars (f + 2, 0, 2);
+ if ((processor_mask & PROCESSOR_V850E2_ALL) == 0 || default_disp_size == 22)
+ {
+ f = frag_var (rs_machine_dependent, 4, 2, SUBYPTE_UNCOND_9_22,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)(size_t) fixups[0].opindex);
+ md_number_to_chars (f, insn, insn_size);
+ md_number_to_chars (f + 2, 0, 2);
+ }
+ else
+ {
+ f = frag_var (rs_machine_dependent, 6, 4, SUBYPTE_UNCOND_9_22_32,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)(size_t) fixups[0].opindex);
+ md_number_to_chars (f, insn, insn_size);
+ md_number_to_chars (f + 2, 0, 4);
+ }
}
- else
+ else /* b<cond>, j<cond>. */
{
- f = frag_var (rs_machine_dependent, 6, 4, 0,
- fixups[0].exp.X_add_symbol,
- fixups[0].exp.X_add_number,
- opindex_converter.ptr);
- md_number_to_chars (f, insn, insn_size);
- md_number_to_chars (f + 2, 0, 4);
+ if (default_disp_size == 22
+ || (processor_mask & PROCESSOR_V850E2_ALL) == 0)
+ {
+ if (processor_mask & PROCESSOR_V850E2V3 && !no_bcond17)
+ {
+ if (strcmp (opcode->name, "bsa") == 0)
+ {
+ f = frag_var (rs_machine_dependent, 8, 6, SUBYPTE_SA_9_17_22,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)(size_t) fixups[0].opindex);
+ md_number_to_chars (f, insn, insn_size);
+ md_number_to_chars (f + 2, 0, 6);
+ }
+ else
+ {
+ f = frag_var (rs_machine_dependent, 6, 4, SUBYPTE_COND_9_17_22,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)(size_t) fixups[0].opindex);
+ md_number_to_chars (f, insn, insn_size);
+ md_number_to_chars (f + 2, 0, 4);
+ }
+ }
+ else
+ {
+ if (strcmp (opcode->name, "bsa") == 0)
+ {
+ f = frag_var (rs_machine_dependent, 8, 6, SUBYPTE_SA_9_22,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)(size_t) fixups[0].opindex);
+ md_number_to_chars (f, insn, insn_size);
+ md_number_to_chars (f + 2, 0, 6);
+ }
+ else
+ {
+ f = frag_var (rs_machine_dependent, 6, 4, SUBYPTE_COND_9_22,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)(size_t) fixups[0].opindex);
+ md_number_to_chars (f, insn, insn_size);
+ md_number_to_chars (f + 2, 0, 4);
+ }
+ }
+ }
+ else
+ {
+ if (processor_mask & PROCESSOR_V850E2V3 && !no_bcond17)
+ {
+ if (strcmp (opcode->name, "bsa") == 0)
+ {
+ f = frag_var (rs_machine_dependent, 10, 8, SUBYPTE_SA_9_17_22_32,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)(size_t) fixups[0].opindex);
+ md_number_to_chars (f, insn, insn_size);
+ md_number_to_chars (f + 2, 0, 8);
+ }
+ else
+ {
+ f = frag_var (rs_machine_dependent, 8, 6, SUBYPTE_COND_9_17_22_32,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)(size_t) fixups[0].opindex);
+ md_number_to_chars (f, insn, insn_size);
+ md_number_to_chars (f + 2, 0, 6);
+ }
+ }
+ else
+ {
+ if (strcmp (opcode->name, "bsa") == 0)
+ {
+ f = frag_var (rs_machine_dependent, 10, 8, SUBYPTE_SA_9_22_32,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)(size_t) fixups[0].opindex);
+ md_number_to_chars (f, insn, insn_size);
+ md_number_to_chars (f + 2, 0, 8);
+ }
+ else
+ {
+ f = frag_var (rs_machine_dependent, 8, 6, SUBYPTE_COND_9_22_32,
+ fixups[0].exp.X_add_symbol,
+ fixups[0].exp.X_add_number,
+ (char *)(size_t) fixups[0].opindex);
+ md_number_to_chars (f, insn, insn_size);
+ md_number_to_chars (f + 2, 0, 6);
+ }
+ }
+ }
}
}
else
@@ -2084,6 +2856,12 @@ md_assemble (char *str)
if ((insn & 0xffe0) == 0x0620)
insn_size = 2;
+ /* Special case: 32 bit JARL,JMP,JR. */
+ if ((insn & 0x1ffe0) == 0x2e0 /* JARL. */
+ || (insn & 0x1ffe0) == 0x6e0 /* JMP. */
+ || (insn & 0x1ffff) == 0x2e0) /* JR. */
+ insn_size = 2;
+
f = frag_more (insn_size);
md_number_to_chars (f, insn, insn_size);
@@ -2129,11 +2907,26 @@ md_assemble (char *str)
if (size != 2 && size != 4)
abort ();
- address = (f - frag_now->fr_literal) + insn_size - size;
+ if (extra_data_len == 0)
+ {
+ address = (f - frag_now->fr_literal) + insn_size - size;
+ }
+ else
+ {
+ address = (f - frag_now->fr_literal) + extra_data_len - size;
+ }
- if (reloc == BFD_RELOC_32)
- address += 2;
+ if ((operand->flags & V850E_IMMEDIATE32) && (operand->flags & V850_PCREL))
+ {
+ fixups[i].exp.X_add_number += 2;
+ }
+ else if (operand->default_reloc == BFD_RELOC_V850_16_PCREL)
+ {
+ fixups[i].exp.X_add_number += 2;
+ address += 2;
+ }
+ /* fprintf (stderr, "0x%x %d %ld\n", address, size, fixups[i].exp.X_add_number); */
fixP = fix_new_exp (frag_now, address, size,
&fixups[i].exp,
reloc_howto->pc_relative,
@@ -2144,6 +2937,7 @@ md_assemble (char *str)
switch (reloc)
{
case BFD_RELOC_LO16:
+ case BFD_RELOC_V850_LO16_S1:
case BFD_RELOC_V850_LO16_SPLIT_OFFSET:
case BFD_RELOC_HI16:
case BFD_RELOC_HI16_S:
@@ -2158,7 +2952,7 @@ md_assemble (char *str)
fix_new_exp (frag_now,
f - frag_now->fr_literal, 4,
& fixups[i].exp,
- (operand->flags & V850_OPERAND_DISP) != 0,
+ (operand->flags & V850_PCREL) != 0,
(bfd_reloc_code_real_type) (fixups[i].opindex
+ (int) BFD_RELOC_UNUSED));
}
@@ -2188,9 +2982,11 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
reloc->addend = fixp->fx_offset;
else
{
+#if 0
if (fixp->fx_r_type == BFD_RELOC_32
&& fixp->fx_pcrel)
fixp->fx_r_type = BFD_RELOC_32_PCREL;
+#endif
reloc->addend = fixp->fx_addnumber;
}
@@ -2295,6 +3091,7 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
int opindex;
const struct v850_operand *operand;
unsigned long insn;
+ const char *errmsg = NULL;
opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
operand = &v850_operands[opindex];
@@ -2306,10 +3103,20 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
format! */
where = fixP->fx_frag->fr_literal + fixP->fx_where;
- insn = bfd_getl32 ((unsigned char *) where);
+ if (fixP->fx_size > 2)
+ insn = bfd_getl32 ((unsigned char *) where);
+ else
+ insn = bfd_getl16 ((unsigned char *) where);
+
insn = v850_insert_operand (insn, operand, (offsetT) value,
- fixP->fx_file, fixP->fx_line, NULL);
- bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
+ &errmsg);
+ if (errmsg)
+ as_warn_where (fixP->fx_file, fixP->fx_line, errmsg);
+
+ if (fixP->fx_size > 2)
+ bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
+ else
+ bfd_putl16 ((bfd_vma) insn, (unsigned char *) where);
if (fixP->fx_done)
/* Nothing else to do here. */
@@ -2318,17 +3125,23 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
/* Determine a BFD reloc value based on the operand information.
We are only prepared to turn a few of the operands into relocs. */
- if (operand->bits == 22)
- fixP->fx_r_type = BFD_RELOC_V850_22_PCREL;
- else if (operand->bits == 9)
- fixP->fx_r_type = BFD_RELOC_V850_9_PCREL;
- else
+ if (operand->default_reloc == BFD_RELOC_NONE)
{
as_bad_where (fixP->fx_file, fixP->fx_line,
_("unresolved expression that must be resolved"));
fixP->fx_done = 1;
return;
}
+
+ {
+ fixP->fx_r_type = operand->default_reloc;
+ if (operand->default_reloc == BFD_RELOC_V850_16_PCREL)
+ {
+ fixP->fx_where += 2;
+ fixP->fx_size = 2;
+ fixP->fx_addnumber += 2;
+ }
+ }
}
else if (fixP->fx_done)
{
@@ -2336,54 +3149,140 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED)
where = fixP->fx_frag->fr_literal + fixP->fx_where;
if (fixP->tc_fix_data != NULL
- && ((struct v850_operand *) fixP->tc_fix_data)->insert != NULL)
- {
- const char * message = NULL;
- struct v850_operand * operand = (struct v850_operand *) fixP->tc_fix_data;
- unsigned long insn;
-
- /* The variable "where" currently points at the exact point inside
- the insn where we need to insert the value. But we need to
- extract the entire insn so we probably need to move "where"
- back a few bytes. */
- if (fixP->fx_size == 2)
- where -= 2;
- else if (fixP->fx_size == 1)
- where -= 3;
-
- insn = bfd_getl32 ((unsigned char *) where);
-
- /* Use the operand's insertion procedure, if present, in order to
- make sure that the value is correctly stored in the insn. */
- insn = operand->insert (insn, (offsetT) value, & message);
- /* Ignore message even if it is set. */
-
- bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
- }
+ && ((struct v850_operand *) fixP->tc_fix_data)->insert != NULL)
+ {
+ const char * message = NULL;
+ struct v850_operand * operand = (struct v850_operand *) fixP->tc_fix_data;
+ unsigned long insn;
+
+ /* The variable "where" currently points at the exact point inside
+ the insn where we need to insert the value. But we need to
+ extract the entire insn so we probably need to move "where"
+ back a few bytes. */
+
+ if (fixP->fx_size == 2)
+ where -= 2;
+ else if (fixP->fx_size == 1)
+ where -= 3;
+
+ insn = bfd_getl32 ((unsigned char *) where);
+
+ /* Use the operand's insertion procedure, if present, in order to
+ make sure that the value is correctly stored in the insn. */
+ insn = operand->insert (insn, (offsetT) value, & message);
+ /* Ignore message even if it is set. */
+
+ bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
+ }
else
- {
- if (fixP->fx_r_type == BFD_RELOC_V850_LO16_SPLIT_OFFSET)
- bfd_putl32 (((value << 16) & 0xfffe0000)
- | ((value << 5) & 0x20)
- | (bfd_getl32 (where) & ~0xfffe0020), where);
- else if (fixP->fx_size == 1)
- *where = value & 0xff;
- else if (fixP->fx_size == 2)
- bfd_putl16 (value & 0xffff, (unsigned char *) where);
- else if (fixP->fx_size == 4)
- bfd_putl32 (value, (unsigned char *) where);
- }
+ {
+ switch (fixP->fx_r_type)
+ {
+ case BFD_RELOC_V850_32_ABS:
+ case BFD_RELOC_V850_32_PCREL:
+ bfd_putl32 (value & 0xfffffffe, (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_32:
+ bfd_putl32 (value, (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_V850_23:
+ bfd_putl32 (((value & 0x7f) << 4) | ((value & 0x7fff80) << (16-7))
+ | (bfd_getl32 (where) & ~((0x7f << 4) | (0xffff << 16))),
+ (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_16:
+ case BFD_RELOC_HI16:
+ case BFD_RELOC_HI16_S:
+ case BFD_RELOC_LO16:
+ case BFD_RELOC_V850_ZDA_16_16_OFFSET:
+ case BFD_RELOC_V850_SDA_16_16_OFFSET:
+ case BFD_RELOC_V850_TDA_16_16_OFFSET:
+ case BFD_RELOC_V850_CALLT_16_16_OFFSET:
+ bfd_putl16 (value & 0xffff, (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_8:
+ *where = value & 0xff;
+ break;
+
+ case BFD_RELOC_V850_9_PCREL:
+ bfd_putl16 (((value & 0x1f0) << 7) | ((value & 0x0e) << 3)
+ | (bfd_getl16 (where) & ~((0x1f0 << 7) | (0x0e << 3))), where);
+ break;
+
+ case BFD_RELOC_V850_17_PCREL:
+ bfd_putl32 (((value & 0x10000) >> (16 - 4)) | ((value & 0xfffe) << 16)
+ | (bfd_getl32 (where) & ~((0x10000 >> (16 - 4)) | (0xfffe << 16))), where);
+ break;
+
+ case BFD_RELOC_V850_16_PCREL:
+ bfd_putl16 (-value & 0xfffe, (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_V850_22_PCREL:
+ bfd_putl32 (((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16)
+ | (bfd_getl32 (where) & ~((0xfffe << 16) | (0x3f0000 >> 16))), where);
+ break;
+
+ case BFD_RELOC_V850_16_S1:
+ case BFD_RELOC_V850_LO16_S1:
+ case BFD_RELOC_V850_ZDA_15_16_OFFSET:
+ case BFD_RELOC_V850_SDA_15_16_OFFSET:
+ bfd_putl16 (value & 0xfffe, (unsigned char *) where);
+ break;
+
+ case BFD_RELOC_V850_16_SPLIT_OFFSET:
+ case BFD_RELOC_V850_LO16_SPLIT_OFFSET:
+ case BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET:
+ case BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET:
+ bfd_putl32 (((value << 16) & 0xfffe0000)
+ | ((value << 5) & 0x20)
+ | (bfd_getl32 (where) & ~0xfffe0020), where);
+ break;
+
+ case BFD_RELOC_V850_TDA_6_8_OFFSET:
+ *where = (*where & ~0x7e) | ((value >> 1) & 0x7e);
+ break;
+
+ case BFD_RELOC_V850_TDA_7_8_OFFSET:
+ *where = (*where & ~0x7f) | ((value >> 1) & 0x7f);
+ break;
+
+ case BFD_RELOC_V850_TDA_7_7_OFFSET:
+ *where = (*where & ~0x7f) | (value & 0x7f);
+ break;
+
+ case BFD_RELOC_V850_TDA_4_5_OFFSET:
+ *where = (*where & ~0xf) | ((value >> 1) & 0xf);
+ break;
+
+ case BFD_RELOC_V850_TDA_4_4_OFFSET:
+ *where = (*where & ~0xf) | (value & 0xf);
+ break;
+
+ case BFD_RELOC_V850_CALLT_6_7_OFFSET:
+ *where = (*where & ~0x3f) | (value & 0x3f);
+ break;
+
+ default:
+ abort ();
+ }
+ }
}
}
-
+
/* Parse a cons expression. We have to handle hi(), lo(), etc
on the v850. */
void
parse_cons_expression_v850 (expressionS *exp)
{
+ const char *errmsg;
/* See if there's a reloc prefix like hi() we have to handle. */
- hold_cons_reloc = v850_reloc_prefix (NULL);
+ hold_cons_reloc = v850_reloc_prefix (NULL, &errmsg);
/* Do normal expression parsing. */
expression (exp);
@@ -2445,8 +3344,11 @@ v850_force_relocation (struct fix *fixP)
if (v850_relax
&& (fixP->fx_pcrel
|| fixP->fx_r_type == BFD_RELOC_V850_ALIGN
- || fixP->fx_r_type == BFD_RELOC_V850_22_PCREL
|| fixP->fx_r_type == BFD_RELOC_V850_9_PCREL
+ || fixP->fx_r_type == BFD_RELOC_V850_16_PCREL
+ || fixP->fx_r_type == BFD_RELOC_V850_17_PCREL
+ || fixP->fx_r_type == BFD_RELOC_V850_22_PCREL
+ || fixP->fx_r_type == BFD_RELOC_V850_32_PCREL
|| fixP->fx_r_type >= BFD_RELOC_UNUSED))
return 1;
diff --git a/gas/configure.tgt b/gas/configure.tgt
index 55be314..1909160 100644
--- a/gas/configure.tgt
+++ b/gas/configure.tgt
@@ -400,9 +400,7 @@ case ${generic_target} in
tic54x-*-* | c54x*-*-*) fmt=coff bfd_gas=yes need_libm=yes;;
tic6x-*-*) fmt=elf ;;
- v850-*-*) fmt=elf ;;
- v850e-*-*) fmt=elf ;;
- v850ea-*-*) fmt=elf ;;
+ v850*-*-*) fmt=elf ;;
vax-*-netbsdelf*) fmt=elf em=nbsd ;;
vax-*-linux-*) fmt=elf em=linux ;;
diff --git a/gas/doc/c-v850.texi b/gas/doc/c-v850.texi
index b641f8e..e92fbed 100644
--- a/gas/doc/c-v850.texi
+++ b/gas/doc/c-v850.texi
@@ -68,6 +68,18 @@ routines used by the code produced by GCC for all versions of the v850
architecture, together with support routines only used by the V850E
architecture.
+@cindex @code{-mv850e2} command line option, V850
+@item -mv850e2
+Specifies that the assembled code should be marked as being targeted at
+the V850E2 processor. This allows the linker to detect attempts to link
+such code with code assembled for other processors.
+
+@cindex @code{-mv850e2v3} command line option, V850
+@item -mv850e2v3
+Specifies that the assembled code should be marked as being targeted at
+the V850E2V3 processor. This allows the linker to detect attempts to link
+such code with code assembled for other processors.
+
@cindex @code{-mrelax} command line option, V850
@item -mrelax
Enables relaxation. This allows the .longcall and .longjump pseudo
@@ -245,6 +257,18 @@ Specifies that the assembled code should be marked as being targeted at
the V850E1 processor. This allows the linker to detect attempts to link
such code with code assembled for other processors.
+@cindex @code{.v850e2} directive, V850
+@item .v850e2
+Specifies that the assembled code should be marked as being targeted at
+the V850E2 processor. This allows the linker to detect attempts to link
+such code with code assembled for other processors.
+
+@cindex @code{.v850e2v3} directive, V850
+@item .v850e2v3
+Specifies that the assembled code should be marked as being targeted at
+the V850E2V3 processor. This allows the linker to detect attempts to link
+such code with code assembled for other processors.
+
@end table
@node V850 Opcodes
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index 63058013..70973c9 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2010-07-23 Naveen.H.S <naveen.S@kpitcummins.com>
+ Ina Pandit <ina.pandit@kpitcummins.com>
+
+ * gas/v850/split-lo16.d: Update the "ld" instructions with a space
+ for second operand.
+ * gas/v850/v850e1.d: Likewise.
+
2010-07-22 Alan Modra <amodra@gmail.com>
* gas/arm/mapdir.s: Don't specify attr/type for .fini_array.
diff --git a/gas/testsuite/gas/all/byte.d b/gas/testsuite/gas/all/byte.d
index 739b9ce..9e23fea 100644
--- a/gas/testsuite/gas/all/byte.d
+++ b/gas/testsuite/gas/all/byte.d
@@ -1,2 +1,5 @@
#name: bad byte directive
#error-output: byte.l
+# The RX target allows quoted ASCII strings inside .byte directives
+# for compatibily with the Renesas assembler.
+#skip: rx-*-*
diff --git a/gas/testsuite/gas/rx/rx-asm-good.d b/gas/testsuite/gas/rx/rx-asm-good.d
index d515f24..6733bbf 100644
--- a/gas/testsuite/gas/rx/rx-asm-good.d
+++ b/gas/testsuite/gas/rx/rx-asm-good.d
@@ -10,8 +10,8 @@ Disassembly of section .text:
0+0108 <mem\+0x8> 66 20[ ]+mov.l[ ]+#2, r0
0+010a <mem\+0xa> 66 10[ ]+mov.l[ ]+#1, r0
0+010c <mem\+0xc> 66 00[ ]+mov.l[ ]+#0, r0
-0+010e <mem\+0xe> 05 f2 fe ff[ ]+bsr.a[ ]+0+0000 <mem-0x100>
-0+0112 <mem\+0x12> 05 ee fe ff[ ]+bsr.a[ ]+0+0000 <mem-0x100>
+0+010e <mem\+0xe> 05 .. .. ..[ ]+bsr.a[ ]+[0-9a-f]+ <mem.0x[0-9a-f]+>
+0+0112 <mem\+0x12> 05 .. .. ..[ ]+bsr.a[ ]+[0-9a-f]+ <mem.0x[0-9a-f]+>
0+0116 <mem\+0x16> 62 65[ ]+add[ ]+#6, r5
0+0118 <mem\+0x18> 72 74 0b 2e[ ]+add[ ]+#0x2e0b, r7, r4
0+011c <mem\+0x1c> ff 2e 00[ ]+add[ ]+r0, r0, r14
diff --git a/gas/testsuite/gas/v850/split-lo16.d b/gas/testsuite/gas/v850/split-lo16.d
index 5ed195c..617dfd8 100644
--- a/gas/testsuite/gas/v850/split-lo16.d
+++ b/gas/testsuite/gas/v850/split-lo16.d
@@ -7,12 +7,12 @@
2: R_V850_HI16_S foo
4: 01 16 00 00 addi 0, r1, r2
6: R_V850_LO16 foo
- 8: 01 17 00 00 ld\.b 0\[r1\],r2
+ 8: 01 17 00 00 ld\.b 0\[r1\], r2
a: R_V850_LO16 foo
- c: 81 17 01 00 ld\.bu 0\[r1\],r2
+ c: 81 17 01 00 ld\.bu 0\[r1\], r2
c: R_V850_LO16_SPLIT_OFFSET foo
- 10: a1 17 45 23 ld\.bu 9029\[r1\],r2
- 14: 81 17 57 34 ld\.bu 13398\[r1\],r2
- 18: 20 57 01 00 ld.w 0\[r0\],r10
- 1c: 20 57 79 56 ld.w 22136\[r0\],r10
+ 10: a1 17 45 23 ld\.bu 9029\[r1\], r2
+ 14: 81 17 57 34 ld\.bu 13398\[r1\], r2
+ 18: 20 57 01 00 ld.w 0\[r0\], r10
+ 1c: 20 57 79 56 ld.w 22136\[r0\], r10
#pass
diff --git a/gas/testsuite/gas/v850/v850e1.d b/gas/testsuite/gas/v850/v850e1.d
index 9fb689b..8172b09 100644
--- a/gas/testsuite/gas/v850/v850e1.d
+++ b/gas/testsuite/gas/v850/v850e1.d
@@ -23,8 +23,8 @@ Disassembly of section .text:
0x0+30 e7 47 82 4a [ ]*divhu r7, r8, r9
0x0+34 ea 5f c2 62 [ ]*divu r10, r11, r12
0x0+38 e0 6f 44 73 [ ]*hsw r13, r14
-0x0+3c a1 17 0d 00 [ ]*ld.bu 13\[r1\],r2
-0x0+40 e3 27 11 00 [ ]*ld.hu 16\[sp\],gp
+0x0+3c a1 17 0d 00 [ ]*ld.bu 13\[r1\], r2
+0x0+40 e3 27 11 00 [ ]*ld.hu 16\[sp\], gp
0x0+44 21 06 78 56 34 12 [ ]*mov 0x12345678, r1
0x0+4a e5 17 40 1a [ ]*mul 5, r2, sp
0x0+4e e1 17 20 1a [ ]*mul r1, r2, sp
@@ -35,8 +35,8 @@ Disassembly of section .text:
0x0+62 a8 07 03 70 [ ]*prepare {r25 - r27}, 20, sp
0x0+66 e1 4f e0 00 [ ]*set1 r9, r1
0x0+6a ea 47 00 02 [ ]*sasf nz, r8
-0x0+6e 60 20 [ ]*sld.bu 0\[ep\],gp
-0x0+70 77 28 [ ]*sld.hu 14\[ep\],r5
+0x0+6e 60 20 [ ]*sld.bu 0\[ep\], gp
+0x0+70 77 28 [ ]*sld.hu 14\[ep\], r5
0x0+72 a1 00 [ ]*sxb r1
0x0+74 e2 00 [ ]*sxh r2
0x0+76 ff 07 e6 00 [ ]*tst1 r0, lp