* arc-dis.c (print_insn): New parameter `big_p'. Callers updated.

Call arc_get_opcode_mach to map bfd mach number to opcode value.
	(print_insn_*): Pass bfd mach number, not opcode version.
	* arc-opc.c (arc_get_opcode_mach): New function.
This commit is contained in:
David Edelsohn 1995-04-07 03:54:08 +00:00
parent 7e87eb1342
commit 1a56be5c4f
3 changed files with 223 additions and 97 deletions

View File

@ -1,3 +1,29 @@
start-sanitize-arc
Thu Apr 6 20:36:08 1995 Doug Evans <dje@chestnut.cygnus.com>
* arc-dis.c (print_insn): New parameter `big_p'. Callers updated.
Call arc_get_opcode_mach to map bfd mach number to opcode value.
(print_insn_*): Pass bfd mach number, not opcode version.
* arc-opc.c (arc_get_opcode_mach): New function.
end-sanitize-arc
Fri Mar 31 14:23:38 1995 Ken Raeburn <raeburn@cujo.cygnus.com>
* alpha-dis.c (print_insn_alpha): Put empty statement after
default label.
Tue Mar 21 10:51:40 1995 Jeff Law (law@snake.cs.utah.edu)
* hppa-dis.c (sign_extend): Delete, redundant with libhppa.h version.
(low_sign_extend): Likewise.
(get_field): Delete unused function.
(set_field, deposit_14, deposit_21): Likewise.
Fri Mar 17 15:55:53 1995 J.T. Conklin <jtc@rtl.cygnus.com>
* i386-dis.c: Support for more pentium opcodes. From Guy Harris
(guy@netapp.com).
Tue Mar 14 00:52:57 1995 Ken Raeburn (raeburn@kr-pc.cygnus.com)
Sat Feb 11 17:22:41 1995 Klaus Kaempf (kkaempf@didymus.rmi.de)

View File

@ -21,19 +21,26 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "libelf.h"
#include "elf/arc.h"
static int print_insn_arc_base PARAMS ((bfd_vma, disassemble_info *));
static int print_insn_arc_host PARAMS ((bfd_vma, disassemble_info *));
static int print_insn_arc_graphics PARAMS ((bfd_vma, disassemble_info *));
static int print_insn_arc_audio PARAMS ((bfd_vma, disassemble_info *));
static int print_insn_arc_base_little PARAMS ((bfd_vma, disassemble_info *));
static int print_insn_arc_host_little PARAMS ((bfd_vma, disassemble_info *));
static int print_insn_arc_graphics_little PARAMS ((bfd_vma, disassemble_info *));
static int print_insn_arc_audio_little PARAMS ((bfd_vma, disassemble_info *));
static int print_insn_arc_base_big PARAMS ((bfd_vma, disassemble_info *));
static int print_insn_arc_host_big PARAMS ((bfd_vma, disassemble_info *));
static int print_insn_arc_graphics_big PARAMS ((bfd_vma, disassemble_info *));
static int print_insn_arc_audio_big PARAMS ((bfd_vma, disassemble_info *));
static int print_insn PARAMS ((bfd_vma, disassemble_info *, int, int));
/* Print one instruction from PC on INFO->STREAM.
Return the size of the instruction (4 or 8 for the ARC). */
static int
print_insn (pc, info, cpu)
print_insn (pc, info, mach, big_p)
bfd_vma pc;
disassemble_info *info;
int cpu;
int mach;
int big_p;
{
const struct arc_opcode *opcode,*opcode_end;
bfd_byte buffer[4];
@ -44,15 +51,13 @@ print_insn (pc, info, cpu)
arc_insn insn[2];
int got_limm_p = 0;
static int initialized = 0;
static int current_cpu = 0;
/* Not used yet. Here to record byte order dependencies. */
int bigendian_p = 0;
static int current_mach = 0;
if (!initialized || cpu != current_cpu)
if (!initialized || mach != current_mach)
{
arc_opcode_init_tables (cpu);
initialized = 1;
current_cpu = cpu;
current_mach = arc_get_opcode_mach (mach, big_p);
arc_opcode_init_tables (current_mach);
}
status = (*info->read_memory_func) (pc, buffer, 4, info);
@ -61,12 +66,12 @@ print_insn (pc, info, cpu)
(*info->memory_error_func) (status, pc, info);
return -1;
}
if (bigendian_p)
if (big_p)
insn[0] = bfd_getb32 (buffer);
else
insn[0] = bfd_getl32 (buffer);
func (stream, "%08lx\t", insn[0]);
(*func) (stream, "%08lx\t", insn[0]);
opcode_end = arc_opcodes + arc_opcodes_count;
for (opcode = arc_opcodes; opcode < opcode_end; opcode++)
@ -130,7 +135,7 @@ print_insn (pc, info, cpu)
(*info->memory_error_func) (status, pc, info);
return -1;
}
if (bigendian_p)
if (big_p)
insn[1] = bfd_getb32 (buffer);
else
insn[1] = bfd_getl32 (buffer);
@ -141,7 +146,7 @@ print_insn (pc, info, cpu)
{
if (*syn != '%' || *++syn == '%')
{
func (stream, "%c", *syn);
(*func) (stream, "%c", *syn);
continue;
}
@ -190,93 +195,121 @@ print_insn (pc, info, cpu)
aren't defined yet. For these cases just print the
number suitably decorated. */
if (opval)
func (stream, "%s%s",
mods & ARC_MOD_DOT ? "." : "",
opval->name);
(*func) (stream, "%s%s",
mods & ARC_MOD_DOT ? "." : "",
opval->name);
else
func (stream, "%s%c%d",
mods & ARC_MOD_DOT ? "." : "",
operand->fmt, value);
(*func) (stream, "%s%c%d",
mods & ARC_MOD_DOT ? "." : "",
operand->fmt, value);
}
}
else if (operand->flags & ARC_OPERAND_RELATIVE)
else if (operand->flags & ARC_OPERAND_RELATIVE_BRANCH)
(*info->print_address_func) (pc + 4 + value, info);
/* ??? Not all cases of this are currently caught. */
else if (operand->flags & ARC_OPERAND_ABSOLUTE)
else if (operand->flags & ARC_OPERAND_ABSOLUTE_BRANCH)
(*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
else if (operand->flags & ARC_OPERAND_ADDRESS)
(*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
else if (opval)
/* Note that this case catches both normal and auxiliary regs. */
func (stream, "%s", opval->name);
(*func) (stream, "%s", opval->name);
else
func (stream, "%ld", value);
(*func) (stream, "%ld", value);
}
/* We have found and printed an instruction; return. */
return got_limm_p ? 8 : 4;
}
func (stream, "*unknown*");
(*func) (stream, "*unknown*");
return 4;
}
/* Given ABFD, return the print_insn function to use.
/* Given MACH, one of bfd_mach_arc_xxx, return the print_insn function to use.
This does things a non-standard way (the "standard" way would be to copy
this code into disassemble.c). Since there are more than a couple of
variants, hiding all this crud here seems cleaner. */
disassembler_ftype
arc_get_disassembler (bfd *abfd)
arc_get_disassembler (mach, big_p)
int mach;
int big_p;
{
int mach = bfd_get_mach (abfd);
switch (mach)
{
case bfd_mach_arc_base:
return print_insn_arc_base;
return big_p ? print_insn_arc_base_big : print_insn_arc_base_little;
case bfd_mach_arc_host:
return print_insn_arc_host;
return big_p ? print_insn_arc_host_big : print_insn_arc_host_little;
case bfd_mach_arc_graphics:
return print_insn_arc_graphics;
return big_p ? print_insn_arc_graphics_big : print_insn_arc_graphics_little;
case bfd_mach_arc_audio:
return print_insn_arc_audio;
return big_p ? print_insn_arc_audio_big : print_insn_arc_audio_little;
}
return print_insn_arc_base;
return print_insn_arc_base_little;
}
static int
print_insn_arc_base (pc, info)
print_insn_arc_base_little (pc, info)
bfd_vma pc;
disassemble_info *info;
{
return print_insn (pc, info, ARC_MACH_BASE);
return print_insn (pc, info, bfd_mach_arc_base, 0);
}
/* Host CPU. */
static int
print_insn_arc_host (pc, info)
print_insn_arc_host_little (pc, info)
bfd_vma pc;
disassemble_info *info;
{
return print_insn (pc, info, ARC_MACH_HOST);
return print_insn (pc, info, bfd_mach_arc_host, 0);
}
/* Graphics CPU. */
static int
print_insn_arc_graphics (pc, info)
print_insn_arc_graphics_little (pc, info)
bfd_vma pc;
disassemble_info *info;
{
return print_insn (pc, info, ARC_MACH_GRAPHICS);
return print_insn (pc, info, bfd_mach_arc_graphics, 0);
}
/* Audio CPU. */
static int
print_insn_arc_audio (pc, info)
print_insn_arc_audio_little (pc, info)
bfd_vma pc;
disassemble_info *info;
{
return print_insn (pc, info, ARC_MACH_AUDIO);
return print_insn (pc, info, bfd_mach_arc_audio, 0);
}
static int
print_insn_arc_base_big (pc, info)
bfd_vma pc;
disassemble_info *info;
{
return print_insn (pc, info, bfd_mach_arc_base, 1);
}
static int
print_insn_arc_host_big (pc, info)
bfd_vma pc;
disassemble_info *info;
{
return print_insn (pc, info, bfd_mach_arc_host, 1);
}
static int
print_insn_arc_graphics_big (pc, info)
bfd_vma pc;
disassemble_info *info;
{
return print_insn (pc, info, bfd_mach_arc_graphics, 1);
}
static int
print_insn_arc_audio_big (pc, info)
bfd_vma pc;
disassemble_info *info;
{
return print_insn (pc, info, bfd_mach_arc_audio, 1);
}

View File

@ -16,9 +16,6 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* The ARC may eventually be bi-endian.
Keep this file byte order independent. */
#include "ansidecl.h"
#include "opcode/arc.h"
@ -40,6 +37,7 @@ INSERT_FN (insert_flagfinish);
INSERT_FN (insert_cond);
INSERT_FN (insert_forcelimm);
INSERT_FN (insert_reladdr);
INSERT_FN (insert_absaddr);
INSERT_FN (insert_unopmacro);
INSERT_FN (insert_multshift);
@ -67,7 +65,8 @@ EXTRACT_FN (extract_multshift);
'n' DELAY N field (nullify field)
'q' COND condition code field
'Q' FORCELIMM set `cond_p' to 1 to ensure a constant is a limm
'B' BRANCH branch address
'B' BRANCH branch address (22 bit pc relative)
'J' JUMP jump address (26 bit absolute)
'z' SIZE1 size field in ld a,[b,c]
'Z' SIZE10 size field in ld a,[b,shimm]
'y' SIZE22 size field in st c,[b,shimm]
@ -76,9 +75,9 @@ EXTRACT_FN (extract_multshift);
'w' ADDRESS3 write-back field in ld a,[b,c]
'W' ADDRESS12 write-back field in ld a,[b,shimm]
'v' ADDRESS24 write-back field in st c,[b,shimm]
'D' CACHEBYPASS5 direct to memory enable (cache bypass) in ld a,[b,c]
'e' CACHEBYPASS14 direct to memory enable (cache bypass) in ld a,[b,shimm]
'E' CACHEBYPASS26 direct to memory enable (cache bypass) in st c,[b,shimm]
'e' CACHEBYPASS5 cache bypass in ld a,[b,c]
'E' CACHEBYPASS14 cache bypass in ld a,[b,shimm]
'D' CACHEBYPASS26 cache bypass in st c,[b,shimm]
'u' UNSIGNED unsigned multiply
's' SATURATION saturation limit in audio arc mac insn
'U' UNOPMACRO fake operand to copy REGB to REGC for unop macros
@ -116,9 +115,10 @@ const struct arc_operand arc_operands[] =
#define SHIMMFINISH (REGC + 1)
{ 'S', 9, 0, ARC_OPERAND_SIGNED + ARC_OPERAND_FAKE, insert_shimmfinish, 0 },
/* fake operand used to insert limm value into most instructions */
/* fake operand used to insert limm value into most instructions;
this is also used for .word handling */
#define LIMMFINISH (SHIMMFINISH + 1)
{ 'L', 32, 32, ARC_OPERAND_ABSOLUTE + ARC_OPERAND_FAKE, insert_limmfinish, 0 },
{ 'L', 32, 32, ARC_OPERAND_ADDRESS + ARC_OPERAND_LIMM + ARC_OPERAND_FAKE, insert_limmfinish, 0 },
/* shimm operand when there is no reg indicator (ld,st) */
#define SHIMMOFFSET (LIMMFINISH + 1)
@ -152,12 +152,17 @@ const struct arc_operand arc_operands[] =
#define FORCELIMM (COND + 1)
{ 'Q', 0, 0, ARC_OPERAND_FAKE, insert_forcelimm },
/* branch address b, bl, and lp insns */
/* branch address; b, bl, and lp insns */
#define BRANCH (FORCELIMM + 1)
{ 'B', 20, 7, ARC_OPERAND_RELATIVE + ARC_OPERAND_SIGNED, insert_reladdr, extract_reladdr },
{ 'B', 20, 7, ARC_OPERAND_RELATIVE_BRANCH + ARC_OPERAND_SIGNED, insert_reladdr, extract_reladdr },
/* jump address; j insn (this is basically the same as 'L' except that the
value is right shifted by 2); this is also used for .word handling */
#define JUMP (BRANCH + 1)
{ 'J', 24, 32, ARC_OPERAND_ABSOLUTE_BRANCH + ARC_OPERAND_LIMM + ARC_OPERAND_FAKE, insert_absaddr },
/* size field, stored in bit 1,2 */
#define SIZE1 (BRANCH + 1)
#define SIZE1 (JUMP + 1)
{ 'z', 2, 1, ARC_OPERAND_SUFFIX },
/* size field, stored in bit 10,11 */
@ -190,15 +195,15 @@ const struct arc_operand arc_operands[] =
/* cache bypass, stored in bit 5 */
#define CACHEBYPASS5 (ADDRESS24 + 1)
{ 'D', 1, 5, ARC_OPERAND_SUFFIX },
{ 'e', 1, 5, ARC_OPERAND_SUFFIX },
/* cache bypass, stored in bit 14 */
#define CACHEBYPASS14 (CACHEBYPASS5 + 1)
{ 'e', 1, 14, ARC_OPERAND_SUFFIX },
{ 'E', 1, 14, ARC_OPERAND_SUFFIX },
/* cache bypass, stored in bit 26 */
#define CACHEBYPASS26 (CACHEBYPASS14 + 1)
{ 'E', 1, 26, ARC_OPERAND_SUFFIX },
{ 'D', 1, 26, ARC_OPERAND_SUFFIX },
/* unsigned multiply */
#define UNSIGNED (CACHEBYPASS26 + 1)
@ -229,7 +234,7 @@ const struct arc_operand arc_operands[] =
/* end of list place holder */
{ 0 }
};
/* Given a format letter, yields the index into `arc_operands'.
eg: arc_operand_map['a'] = REGA. */
unsigned char arc_operand_map[256];
@ -252,7 +257,10 @@ unsigned char arc_operand_map[256];
Longer versions of insns must appear before shorter ones (if gas sees
"lsr r2,r3,1" when it's parsing "lsr %a,%b" it will think the ",1" is
junk). */
junk).
This table is best viewed on a wide screen (161 columns).
I'd prefer to keep it this way. */
/* ??? This table also includes macros: asl, lsl, and mov. The ppc port has
a more general facility for dealing with macros which could be used if
@ -287,12 +295,13 @@ const struct arc_opcode arc_opcodes[] = {
{ "extw%.q%.f %a,%b%F%S%L", I(-1)+C(-1), I(3)+C(8) },
{ "flag%.q %b%G%S%L", I(-1)+A(-1)+C(-1), I(3)+A(ARC_REG_SHIMM_UPDATE)+C(0) },
/* %Q: force cond_p=1 --> no shimm values */
{ "j%q%Q%.n%.f %b%L", I(-1)+A(-1)+C(-1)+R(-1,7,1), I(7)+A(0)+C(0)+R(0,7,1) },
/* ??? This insn allows an optional flags spec. */
{ "j%q%Q%.n%.f %b%J", I(-1)+A(-1)+C(-1)+R(-1,7,1), I(7)+A(0)+C(0)+R(0,7,1) },
/* Put opcode 1 ld insns first so shimm gets prefered over limm. */
/* "[%b]" is before "[%b,%d]" so 0 offsets don't get printed. */
{ "ld%Z%.X%.v%.e %0%a,[%b]%L", I(-1)+R(-1,13,1)+R(-1,0,511), I(1)+R(0,13,1)+R(0,0,511) },
{ "ld%Z%.X%.v%.e %a,[%b,%d]%S%L", I(-1)+R(-1,13,1), I(1)+R(0,13,1) },
{ "ld%z%.x%.u%.D %a,[%b,%c]", I(-1)+R(-1,4,1)+R(-1,6,7), I(0)+R(0,4,1)+R(0,6,7) },
{ "ld%Z%.X%.W%.E %0%a,[%b]%L", I(-1)+R(-1,13,1)+R(-1,0,511), I(1)+R(0,13,1)+R(0,0,511) },
{ "ld%Z%.X%.W%.E %a,[%b,%d]%S%L", I(-1)+R(-1,13,1), I(1)+R(0,13,1) },
{ "ld%z%.x%.w%.e %a,[%b,%c]", I(-1)+R(-1,4,1)+R(-1,6,7), I(0)+R(0,4,1)+R(0,6,7) },
{ "lp%q%.n %B", I(-1), I(6), },
{ "lr %a,[%Ab]%S%L", I(-1)+C(-1), I(1)+C(0x10) },
/* Note that "lsl" is really an "add". */
@ -320,13 +329,13 @@ const struct arc_opcode arc_opcodes[] = {
{ "sexw%.q%.f %a,%b%F%S%L", I(-1)+C(-1), I(3)+C(6) },
{ "sr %c,[%Ab]%S%L", I(-1)+A(-1), I(2)+A(0x10) },
/* "[%b]" is before "[%b,%d]" so 0 offsets don't get printed. */
{ "st%y%.w%.E %0%c,[%b]%L", I(-1)+R(-1,25,3)+R(-1,21,1)+R(-1,0,511), I(2)+R(0,25,3)+R(0,21,1)+R(0,0,511) },
{ "st%y%.w%.E %c,[%b,%d]%S%L", I(-1)+R(-1,25,3)+R(-1,21,1), I(2)+R(0,25,3)+R(0,21,1) },
{ "st%y%.v%.D %0%c,[%b]%L", I(-1)+R(-1,25,3)+R(-1,21,1)+R(-1,0,511), I(2)+R(0,25,3)+R(0,21,1)+R(0,0,511) },
{ "st%y%.v%.D %c,[%b,%d]%S%L", I(-1)+R(-1,25,3)+R(-1,21,1), I(2)+R(0,25,3)+R(0,21,1) },
{ "sub%.q%.f %a,%b,%c%F%S%L", I(-1), I(10) },
{ "swap%.q%.f %a,%b%F%S%L", I(-1)+C(-1), I(3)+C(9), ARC_MACH_AUDIO },
{ "xor%.q%.f %a,%b,%c%F%S%L", I(-1), I(15) }
};
int arc_opcodes_count = sizeof (arc_opcodes) / sizeof (arc_opcodes[0]);
const int arc_opcodes_count = sizeof (arc_opcodes) / sizeof (arc_opcodes[0]);
const struct arc_operand_value arc_reg_names[] =
{
@ -432,7 +441,7 @@ const struct arc_operand_value arc_reg_names[] =
{ "sram", 0x400, AUXREG, ARC_MACH_AUDIO },
{ "reg_file", 0x800, AUXREG, ARC_MACH_AUDIO },
};
int arc_reg_names_count = sizeof (arc_reg_names) / sizeof (arc_reg_names[0]);
const int arc_reg_names_count = sizeof (arc_reg_names) / sizeof (arc_reg_names[0]);
/* The suffix table.
Operands with the same name must be stored together. */
@ -472,13 +481,13 @@ const struct arc_operand_value arc_suffixes[] =
{ "nd", 0, DELAY },
{ "d", 1, DELAY },
{ "jd", 2, DELAY },
/* { "b", 7, SIZEEXT },*/
/* { "b", 5, SIZESEX },*/
/*{ "b", 7, SIZEEXT },*/
/*{ "b", 5, SIZESEX },*/
{ "b", 1, SIZE1 },
{ "b", 1, SIZE10 },
{ "b", 1, SIZE22 },
/* { "w", 8, SIZEEXT },*/
/* { "w", 6, SIZESEX },*/
/*{ "w", 8, SIZEEXT },*/
/*{ "w", 6, SIZESEX },*/
{ "w", 2, SIZE1 },
{ "w", 2, SIZE10 },
{ "w", 2, SIZE22 },
@ -498,30 +507,53 @@ const struct arc_operand_value arc_suffixes[] =
{ "mh", 18, COND, ARC_MACH_AUDIO },
{ "ml", 19, COND, ARC_MACH_AUDIO },
};
int arc_suffixes_count = sizeof (arc_suffixes) / sizeof (arc_suffixes[0]);
const int arc_suffixes_count = sizeof (arc_suffixes) / sizeof (arc_suffixes[0]);
/* Configuration flags. */
/* Various ARC_HAVE_XXX bits. */
static int cpu_type;
/* Translate a bfd_mach_arc_xxx value to a ARC_MACH_XXX value. */
int
arc_get_opcode_mach (bfd_mach, big_p)
int bfd_mach, big_p;
{
static int mach_type_map[] =
{
ARC_MACH_BASE, ARC_MACH_HOST, ARC_MACH_GRAPHICS, ARC_MACH_AUDIO
};
return mach_type_map[bfd_mach] | (big_p ? ARC_MACH_BIG : 0);
}
/* Initialize any tables that need it.
Must be called once at start up (or when first needed).
FLAGS is a set of bits that say what version of the cpu we have. */
FLAGS is a set of bits that say what version of the cpu we have,
and in particular at least (one of) ARC_MACH_XXX. */
void
arc_opcode_init_tables (flags)
int flags;
{
register int i,n;
static int map_init_p = 0;
cpu_type = flags;
memset (arc_operand_map, 0, sizeof (arc_operand_map));
n = sizeof (arc_operands) / sizeof (arc_operands[0]);
for (i = 0; i < n; i++)
arc_operand_map[arc_operands[i].fmt] = i;
/* We may be intentionally called more than once (for example gdb will call
us each time the user switches cpu). This table only needs to be init'd
once though. */
if (!map_init_p)
{
memset (arc_operand_map, 0, sizeof (arc_operand_map));
n = sizeof (arc_operands) / sizeof (arc_operands[0]);
for (i = 0; i < n; i++)
arc_operand_map[arc_operands[i].fmt] = i;
map_init_p = 1;
}
}
/* Return non-zero if OPCODE is supported on the specified cpu.
@ -531,9 +563,9 @@ int
arc_opcode_supported (opcode)
const struct arc_opcode *opcode;
{
if (ARC_OPCODE_MACH (opcode->flags) == 0)
if (ARC_OPCODE_CPU (opcode->flags) == 0)
return 1;
if (ARC_OPCODE_MACH (opcode->flags) & ARC_HAVE_MACH (cpu_type))
if (ARC_OPCODE_CPU (opcode->flags) & ARC_HAVE_CPU (cpu_type))
return 1;
return 0;
}
@ -545,9 +577,9 @@ int
arc_opval_supported (opval)
const struct arc_operand_value *opval;
{
if (ARC_OPVAL_MACH (opval->flags) == 0)
if (ARC_OPVAL_CPU (opval->flags) == 0)
return 1;
if (ARC_OPVAL_MACH (opval->flags) & ARC_HAVE_MACH (cpu_type))
if (ARC_OPVAL_CPU (opval->flags) & ARC_HAVE_CPU (cpu_type))
return 1;
return 0;
}
@ -575,6 +607,8 @@ static int limm_p;
/* The value of the limm we inserted. Each insn only gets one but it can
appear multiple times. */
static long limm;
/* Insertion functions. */
/* Called by the assembler before parsing an instruction. */
@ -806,10 +840,16 @@ insert_shimmfinish (insn, operand, mods, reg, value, errmsg)
}
/* Called at the end of processing normal insns (eg: add) to insert a limm
value (if present) into the insn. Actually, there's nothing for us to do
as we can't call frag_more, the caller must do that. */
/* ??? The extract fns take a pointer to two words. The insert insns could be
converted and then we could do something useful. Not sure it's worth it. */
value (if present) into the insn.
Note that this function is only intended to handle instructions (with 4 byte
immediate operands). It is not intended to handle data. */
/* ??? Actually, there's nothing for us to do as we can't call frag_more, the
caller must do that. The extract fns take a pointer to two words. The
insert fns could be converted and then we could do something useful, but
then the reloc handlers would have to know to work on the second word of
a 2 word quantity. That's too much so we don't handle them. */
static arc_insn
insert_limmfinish (insn, operand, mods, reg, value, errmsg)
@ -821,7 +861,8 @@ insert_limmfinish (insn, operand, mods, reg, value, errmsg)
const char **errmsg;
{
if (limm_p)
; /* nothing to do */
/* FIXME: put an abort here and see what happens. */
; /* nothing to do, gas does it */
return insn;
}
@ -856,6 +897,32 @@ insert_reladdr (insn, operand, mods, reg, value, errmsg)
insn |= ((value >> 2) & ((1 << operand->bits) - 1)) << operand->shift;
return insn;
}
/* Insert a limm value as a 26 bit address right shifted 2 into the insn.
Note that this function is only intended to handle instructions (with 4 byte
immediate operands). It is not intended to handle data. */
/* ??? Actually, there's nothing for us to do as we can't call frag_more, the
caller must do that. The extract fns take a pointer to two words. The
insert fns could be converted and then we could do something useful, but
then the reloc handlers would have to know to work on the second word of
a 2 word quantity. That's too much so we don't handle them. */
static arc_insn
insert_absaddr (insn, operand, mods, reg, value, errmsg)
arc_insn insn;
const struct arc_operand *operand;
int mods;
const struct arc_operand_value *reg;
long value;
const char **errmsg;
{
if (limm_p)
/* FIXME: put an abort here and see what happens. */
; /* nothing to do */
return insn;
}
/* Extraction functions.
@ -1000,8 +1067,8 @@ extract_cond (insn, operand, mods, opval, invalid)
cond = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
val = arc_opcode_lookup_suffix (operand, cond);
/* Ignore NULL values of `val'. Several condition code values aren't
implemented yet. */
/* Ignore NULL values of `val'. Several condition code values are
reserved for extensions. */
if (opval && val)
*opval = val;
return cond;