aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-mn10300.c
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>1996-12-11 06:19:43 +0000
committerJeff Law <law@redhat.com>1996-12-11 06:19:43 +0000
commit8ca71631450197f9a9c122c9508bcd3e5c092fc0 (patch)
tree86b7978d00741e8033edc8131c64440659cd6f5e /gas/config/tc-mn10300.c
parent95d18eb74d629b32e817a629fbbf8421d3fbd690 (diff)
downloadgdb-8ca71631450197f9a9c122c9508bcd3e5c092fc0.zip
gdb-8ca71631450197f9a9c122c9508bcd3e5c092fc0.tar.gz
gdb-8ca71631450197f9a9c122c9508bcd3e5c092fc0.tar.bz2
* config/tc-mn10300.c (md_assemble): Update to handle endianness
issues correctly.
Diffstat (limited to 'gas/config/tc-mn10300.c')
-rw-r--r--gas/config/tc-mn10300.c90
1 files changed, 83 insertions, 7 deletions
diff --git a/gas/config/tc-mn10300.c b/gas/config/tc-mn10300.c
index ea97f17..756e3c5 100644
--- a/gas/config/tc-mn10300.c
+++ b/gas/config/tc-mn10300.c
@@ -778,12 +778,88 @@ keep_going:
if (opcode->format == FMT_D4)
size = 6;
- /* Write out the instruction. */
-
+ /* Allocate space for the instruction. */
f = frag_more (size);
- number_to_chars_bigendian (f, insn, size > 4 ? 4 : size);
- if (size > 4)
- number_to_chars_bigendian (f + 4, extension, size - 4);
+
+ /* Fill in bytes for the instruction. Note that opcode fields
+ are written big-endian, 16 & 32bit immediates are written
+ little endian. Egad. */
+ if (opcode->format == FMT_S0
+ || opcode->format == FMT_S1
+ || opcode->format == FMT_D0
+ || opcode->format == FMT_D1)
+ {
+ number_to_chars_bigendian (f, insn, size);
+ }
+ else if (opcode->format == FMT_S2
+ && opcode->opcode != 0xdf0000
+ && opcode->opcode != 0xde0000)
+ {
+ /* A format S2 instruction that is _not_ "ret" and "retf". */
+ number_to_chars_bigendian (f, (insn >> 16) & 0xff, 1);
+ number_to_chars_littleendian (f + 1, insn & 0xffff, 2);
+ }
+ else if (opcode->format == FMT_S2)
+ {
+ /* This must be a ret or retf, which is written entirely in big-endian
+ format. */
+ number_to_chars_bigendian (f, insn, 3);
+ }
+ else if (opcode->format == FMT_S4
+ && opcode->opcode != 0xdc000000)
+ {
+ /* This must be a format S4 "call" instruction. What a pain. */
+ unsigned long temp = (insn >> 8) & 0xffff;
+ number_to_chars_bigendian (f, (insn >> 24) & 0xff, 1);
+ number_to_chars_littleendian (f + 1, temp, 2);
+ number_to_chars_bigendian (f + 3, insn & 0xff, 1);
+ number_to_chars_bigendian (f + 4, extension & 0xff, 1);
+ }
+ else if (opcode->format == FMT_S4)
+ {
+ /* This must be a format S4 "jmp" instruction. */
+ unsigned long temp = ((insn & 0xffffff) << 8) | (extension & 0xff);
+ number_to_chars_bigendian (f, (insn >> 24) & 0xff, 1);
+ number_to_chars_littleendian (f + 1, temp, 4);
+ }
+ else if (opcode->format == FMT_S6)
+ {
+ unsigned long temp = ((insn & 0xffffff) << 8)
+ | ((extension >> 16) & 0xff);
+ number_to_chars_bigendian (f, (insn >> 24) & 0xff, 1);
+ number_to_chars_littleendian (f + 1, temp, 4);
+ number_to_chars_bigendian (f + 5, (extension >> 8) & 0xff, 1);
+ number_to_chars_bigendian (f + 6, extension & 0xff, 1);
+ }
+ else if (opcode->format == FMT_D2
+ && opcode->opcode != 0xfaf80000
+ && opcode->opcode != 0xfaf00000
+ && opcode->opcode != 0xfaf40000)
+ {
+ /* A format D2 instruction where the 16bit immediate is
+ really a single 16bit value, not two 8bit values. */
+ number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
+ number_to_chars_littleendian (f + 2, insn & 0xffff, 2);
+ }
+ else if (opcode->format == FMT_D2)
+ {
+ /* A format D2 instruction where the 16bit immediate
+ is really two 8bit immediates. */
+ number_to_chars_bigendian (f, insn, 4);
+ }
+ else if (opcode->format == FMT_D4)
+ {
+ unsigned long temp = ((insn & 0xffff) << 16) | (extension & 0xffff);
+ number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
+ number_to_chars_littleendian (f + 2, temp, 4);
+ }
+ else if (opcode->format == FMT_D5)
+ {
+ unsigned long temp = ((insn & 0xffff) << 16) | ((extension >> 8) & 0xffff);
+ number_to_chars_bigendian (f, (insn >> 16) & 0xffff, 2);
+ number_to_chars_littleendian (f + 2, temp, 4);
+ number_to_chars_bigendian (f + 6, extension & 0xff, 1);
+ }
/* Create any fixups. */
for (i = 0; i < fc; i++)
@@ -867,9 +943,9 @@ keep_going:
else
{
if (reloc_size == 32)
- reloc = BFD_RELOC_MN10300_32B;
+ reloc = BFD_RELOC_32
else if (reloc_size == 16)
- reloc = BFD_RELOC_MN10300_16B;
+ reloc = BFD_RELOC_16
else if (reloc_size == 8)
reloc = BFD_RELOC_8;
else