Browse Source

gas/config/

* tc-xgate.c: Revised assembler so that operands
	are collected before the addressing mode is
	determined.

include/opcode/
	* xgate.h: Changed the format string for mode
	XGATE_OP_DYA_MON.

opcodes/
	* xgate-dis.c: Removed an IF statement that will
	always be false due to overlapping operand masks.
	* xgate-opc.c: Corrected 'com' opcode entry and
	fixed spacing.
cygwin-64bit-branch
Sean Keys 14 years ago
parent
commit
3879925e69
  1. 787
      gas/config/tc-xgate.c
  2. 2
      include/opcode/xgate.h
  3. 11
      opcodes/xgate-dis.c
  4. 5
      opcodes/xgate-opc.c

787
gas/config/tc-xgate.c

@ -33,8 +33,9 @@ const char line_separator_chars[] = "";
const char EXP_CHARS[] = "eE";
const char FLT_CHARS[] = "dD";
#define SIXTEENTH_BIT 0x8000
#define N_BITS_IN_WORD 16
#define SIXTEENTH_BIT 0x8000
#define N_BITS_IN_WORD 16
#define MAX_NUM_OPERANDS 3
/* #define STATE_CONDITIONAL_BRANCH (1) */
#define STATE_PC_RELATIVE (2)
@ -59,6 +60,41 @@ struct xgate_opcode_handle
struct xgate_opcode *opc0[MAX_OPCODES];
};
/* XGATE's registers all are 16-bit general purpose. They are numbered according to the specifications. */
typedef enum register_id
{
REG_NONE = -1,
REG_R0 = 0,
REG_R1 = 1,
REG_R2 = 2,
REG_R3 = 3,
REG_R4 = 4,
REG_R5 = 5,
REG_R6 = 6,
REG_R7 = 7,
REG_PC = 8,
REG_CCR = 9
} register_id;
/* Operand Modifiers */
typedef enum op_modifiers
{
MOD_NONE = -1,
MOD_POSTINC = 1,
MOD_PREDEC = 2,
MOD_CONSTANT = 3,
MOD_LOAD_HIGH = 4,
MOD_LOAD_LOW = 5
}op_modifiers;
typedef struct s_operand
{
expressionS exp;
register_id reg;
op_modifiers mod;
} s_operand;
/* LOCAL FUNCTIONS */
static char *
xgate_parse_exp (char *, expressionS *);
@ -73,20 +109,29 @@ xgate_new_instruction (int size);
unsigned short
xgate_apply_operand (unsigned short, unsigned short *, unsigned short,
unsigned char);
void
xgate_operands (struct xgate_opcode *, char **);
static unsigned int
xgate_operand (struct xgate_opcode *, int *, int where, char **, char **);
static struct xgate_opcode *
xgate_find_match (struct xgate_opcode_handle *, int, unsigned int);
static int
cmp_opcode (struct xgate_opcode *, struct xgate_opcode *);
unsigned int
xgate_detect_format (char *);
void
xgate_print_syntax (char *);
void
xgate_print_table (void);
unsigned int
xgate_get_operands (char *, s_operand []);
static register_id
reg_name_search (char *);
op_modifiers
xgate_determine_hi_low(char **);
op_modifiers
xgate_determine_increment(char **);
void
xgate_scan_operands (struct xgate_opcode *opcode, s_operand []);
static unsigned int
xgate_parse_operand (struct xgate_opcode *, int *, int where, char **,
s_operand);
/* LOCAL DATA */
static struct hash_control *xgate_hash;
@ -130,22 +175,6 @@ relax_typeS md_relax_table[] =
{0, 0, 0, 0}
};
/* XGATE's registers all are 16-bit general purpose. They are numbered according to the specifications. */
typedef enum register_id
{
REG_NONE = -1,
REG_R0 = 0,
REG_R1 = 1,
REG_R2 = 2,
REG_R3 = 3,
REG_R4 = 4,
REG_R5 = 5,
REG_R6 = 6,
REG_R7 = 7,
REG_PC = 8,
REG_CCR = 9
} register_id;
/* This table describes all the machine specific pseudo-ops the assembler
has to support. The fields are: pseudo-op name without dot function to
call to execute this pseudo-op Integer arg to pass to the function. */
@ -403,9 +432,6 @@ xgate_print_syntax (char *name)
printf ("\tFormat is %s\tRx, Rx, Rx\n", xgate_opcodes[i].name);
if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_DYA))
printf ("\tFormat is %s\tRx, Rx\n", xgate_opcodes[i].name);
if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_DYA_MON)
|| !strcmp (xgate_opcodes[i].constraints, XGATE_OP_MON))
printf ("\tFormat is %s\tRx\n", xgate_opcodes[i].name);
if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IMM3))
printf ("\tFormat is %s\t<3-bit value>\n", xgate_opcodes[i].name);
if (!strcmp (xgate_opcodes[i].constraints, XGATE_OP_IMM4))
@ -477,6 +503,8 @@ md_assemble (char *input_line)
unsigned int sh_format = 0;
char *p = 0;
s_operand new_operands[MAX_NUM_OPERANDS];
fixup_required = 0;
oper_check = 0; /* set error flags */
input_line = extract_word (input_line, op_name, sizeof(op_name));
@ -492,8 +520,9 @@ md_assemble (char *input_line)
}
else
{
/* Detect operand format so we can pull the proper opcode bin. */
sh_format = xgate_detect_format (input_line);
/* Parse operands so we can find the proper opcode bin. */
sh_format = xgate_get_operands(input_line, new_operands);
opcode = xgate_find_match (opcode_handle, opcode_handle->number_of_modes,
sh_format);
@ -506,7 +535,7 @@ md_assemble (char *input_line)
else if (opcode->size == 2)
{
/* Size is one word - assemble that native insn. */
xgate_operands (opcode, &input_line);
xgate_scan_operands (opcode, new_operands);
}
else
{
@ -543,10 +572,11 @@ md_assemble (char *input_line)
}
else
{
sh_format = xgate_detect_format (input_line);
sh_format = xgate_get_operands(input_line, new_operands);
macro_opcode = xgate_find_match (opcode_handle,
opcode_handle->number_of_modes, sh_format);
xgate_operands (macro_opcode, &input_line);
xgate_scan_operands (macro_opcode, new_operands);
}
}
}
@ -732,7 +762,6 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg ATTRIBUTE_UNUSED)
break;
case BFD_RELOC_32:
bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
/* todo figure out how to make BFD_RELOC_16 the default */
break;
case BFD_RELOC_16:
bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
@ -882,43 +911,200 @@ xgate_parse_exp (char *s, expressionS * op)
return input_line_pointer;
}
/* For testing. Comment out to prevent defined but not used warning
static int
cmp_opcode (struct xgate_opcode *op1, struct xgate_opcode *op2)
{
return strcmp (op1->name, op2->name);
}
static struct xgate_opcode *
xgate_find_match (struct xgate_opcode_handle *opcode_handle,
int numberOfModes,
unsigned int sh_format)
{
int i;
static unsigned int
xgate_get_constant(char *str, int max)
if (numberOfModes == 0)
return opcode_handle->opc0[0];
for (i = 0; i <= numberOfModes; i++)
if (opcode_handle->opc0[i]->sh_format & sh_format)
return opcode_handle->opc0[i];
return NULL;
}
/* Because we are dealing with two different core that view the system
memory with different offsets, we must differentiate what core a
symbol belongs to, in order for the linker to cross-link. */
int
xgate_frob_symbol (symbolS *sym)
{
expressionS ex;
asymbol *bfdsym;
elf_symbol_type *elfsym;
str = skip_whitespace(str);
input_line_pointer = str;
expression (& ex);
bfdsym = symbol_get_bfdsym (sym);
elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
if (ex.X_op != O_constant)
as_bad(_("constant value required"));
gas_assert(elfsym);
if (ex.X_add_number > max || ex.X_add_number < 0)
as_bad(_("number must be positive and less than %d"), max + 1);
/* Mark the symbol as being *from XGATE */
elfsym->internal_elf_sym.st_target_internal = 1;
return ex.X_add_number;
return 0;
}
*/
static int
cmp_opcode (struct xgate_opcode *op1, struct xgate_opcode *op2)
unsigned int
xgate_get_operands (char *line, s_operand oprs[])
{
return strcmp (op1->name, op2->name);
int num_operands;
/* If there are no operands, then it must be inherent. */
if (*line == 0 || *line == '\n' || *line == '\r')
return XG_INH;
for (num_operands = 0; strlen (line) && (num_operands < MAX_NUM_OPERANDS);
num_operands++)
{
line = skip_whitespace (line);
if (*line == '#')
line++;
oprs[num_operands].mod = xgate_determine_hi_low (&line);
oprs[num_operands].mod = xgate_determine_increment (&line);
if ((oprs[num_operands].reg = reg_name_search (line)) == REG_NONE)
line = xgate_parse_exp (line, &oprs[num_operands].exp);
/* skip to next operand */
while (*line != 0)
{
if (*line == ',')
{
line++;
break;
}
line++;
}
}
if (num_operands > MAX_NUM_OPERANDS)
return 0;
switch (num_operands)
{
case 1:
if (oprs[0].reg >= REG_R0 && oprs[0].reg <= REG_R7)
return XG_R;
if (oprs[0].reg == REG_NONE)
return XG_I;
break;
case 2:
if (oprs[0].reg >= REG_R0 && oprs[0].reg <= REG_R7)
{
if (oprs[1].reg >= REG_R0 && oprs[1].reg <= REG_R7)
return XG_R_R;
if (oprs[1].reg == REG_CCR)
return XG_R_C;
if (oprs[1].reg == REG_PC)
return XG_R_P;
if (oprs[1].reg == REG_NONE)
return XG_R_I;
}
if (oprs[0].reg == REG_CCR)
return XG_C_R;
break;
case 3:
if (oprs[0].reg >= REG_R0 && oprs[0].reg <= REG_R7)
{
if (oprs[1].reg >= REG_R0 && oprs[1].reg <= REG_R7)
{
if (oprs[2].reg >= REG_R0 && oprs[2].reg <= REG_R7)
return XG_R_R_R;
if (oprs[2].reg >= REG_NONE)
return XG_R_R_I;
}
}
break;
default:
as_bad (_("unknown operand format"));
break;
}
return 0;
}
/* reg_name_search() finds the register number given its name.
Returns the register number or REG_NONE on failure. */
static register_id
reg_name_search (char *name)
{
if (strncasecmp (name, "r0", 2) == 0)
return REG_R0;
if (strncasecmp (name, "r1", 2) == 0)
return REG_R1;
if (strncasecmp (name, "r2", 2) == 0)
return REG_R2;
if (strncasecmp (name, "r3", 2) == 0)
return REG_R3;
if (strncasecmp (name, "r4", 2) == 0)
return REG_R4;
if (strncasecmp (name, "r5", 2) == 0)
return REG_R5;
if (strncasecmp (name, "r6", 2) == 0)
return REG_R6;
if (strncasecmp (name, "r7", 2) == 0)
return REG_R7;
if (strncasecmp (name, "pc", 2) == 0)
return REG_PC;
if (strncasecmp (name, "ccr", 3) == 0)
return REG_CCR;
return REG_NONE;
}
op_modifiers
xgate_determine_hi_low(char **line)
{
char *local_line = line[0];
if (strncasecmp (local_line, "%hi", 3) == 0)
{
*line += 3;
return MOD_LOAD_HIGH;
}
if (strncasecmp (local_line, "%lo", 3) == 0)
{
*line += 3;
return MOD_LOAD_LOW;
}
return MOD_NONE;
}
op_modifiers
xgate_determine_increment(char **line)
{
char *local_line = line[0];
if (*(local_line + 2) == '+')
return MOD_POSTINC;
if (strncasecmp (local_line, "-r", 2) == 0)
{
*line += 1;
return MOD_PREDEC;
}
return MOD_NONE;
}
/* Parse instruction operands. */
void
xgate_operands (struct xgate_opcode *opcode, char **line)
xgate_scan_operands (struct xgate_opcode *opcode, s_operand oprs[])
{
char *frag = xgate_new_instruction (opcode->size);
int where = frag - frag_now->fr_literal;
char *op = opcode->constraints;
unsigned int bin = (int) opcode->bin_opcode;
char *str = *line;
unsigned short oper_mask = 0;
int operand_bit_length = 0;
unsigned int operand = 0;
@ -942,7 +1128,6 @@ xgate_operands (struct xgate_opcode *opcode, char **line)
}
}
/* Opcode has operands. */
/* Parse first operand. */
if (*op)
{
@ -951,50 +1136,39 @@ xgate_operands (struct xgate_opcode *opcode, char **line)
first_operand_equals_second = 1;
++op;
}
operand = xgate_operand (opcode, &operand_bit_length, where, &op, &str);
operand = xgate_parse_operand (opcode, &operand_bit_length, where, &op, oprs[0]);
++op;
bin = xgate_apply_operand (operand, &oper_mask, bin, operand_bit_length);
if(first_operand_equals_second)
bin = xgate_apply_operand (operand, &oper_mask, bin, operand_bit_length);
/* Parse second operand. */
if (*op)
{
if (*op == ',')
++op;
str = skip_whitespace (str);
if (*str++ != ',')
if (first_operand_equals_second)
{
if (first_operand_equals_second)
{
bin = xgate_apply_operand (operand, &oper_mask, bin,
operand_bit_length);
++op;
}
else
{
as_bad (_("`,' required before second operand"));
}
bin = xgate_apply_operand (operand, &oper_mask, bin,
operand_bit_length);
++op;
}
else
{
str = skip_whitespace (str);
operand = xgate_operand (opcode, &operand_bit_length, where, &op,
&str);
operand = xgate_parse_operand (opcode, &operand_bit_length, where,
&op, oprs[1]);
bin = xgate_apply_operand (operand, &oper_mask, bin,
operand_bit_length);
++op;
}
}
/* Parse the third register. */
if (*op)
{
if (*op == ',')
++op;
str = skip_whitespace (str);
if (*str++ != ',')
as_bad (_("`,' required before third operand"));
str = skip_whitespace (str);
operand = xgate_operand (opcode, &operand_bit_length, where, &op,
&str);
operand = xgate_parse_operand (opcode, &operand_bit_length, where, &op,
oprs[2]);
bin = xgate_apply_operand (operand, &oper_mask, bin,
operand_bit_length);
}
@ -1006,33 +1180,28 @@ xgate_operands (struct xgate_opcode *opcode, char **line)
else if ((opcode->sh_format & XG_PCREL))
{
/* Write our data to a frag for further processing. */
bfd_putl16 (opcode->bin_opcode, frag);
bfd_putl16 (opcode->bin_opcode, frag);
}
else
{
/* Apply operand mask(s)to bin opcode and write the output. */
/* Since we are done write this frag in xgate BE format. */
number_to_chars_bigendian (frag, bin, opcode->size);
number_to_chars_bigendian (frag, bin, opcode->size);
}
prev = bin;
*line = str;
return;
}
static unsigned int
xgate_operand (struct xgate_opcode *opcode,
int *bit_width,
int where,
char **op_con,
char **line)
xgate_parse_operand (struct xgate_opcode *opcode,
int *bit_width,
int where,
char **op_con,
s_operand operand_two)
{
expressionS op_expr;
fixS *fixp = 0;
char *op_constraint = *op_con;
unsigned int op_mask = 0;
char *str = skip_whitespace (*line);
char r_name[20] =
{ 0 };
unsigned int pp_fix = 0;
unsigned short max_size = 0;
int i;
@ -1043,57 +1212,28 @@ xgate_operand (struct xgate_opcode *opcode,
switch (*op_constraint)
{
case '+': /* Indexed register operand +/- or plain r. */
/* TODO should be able to combine with with case R. */
/* Default to neither inc or dec. */
pp_fix = 0;
*bit_width = 5;
str = skip_whitespace (str);
while (*str != ' ' && *str != '\t')
{
if (*str == '-')
pp_fix = DECREMENT;
else if (*str == '+')
pp_fix = INCREMENT;
else if (*str == 'r' || *str == 'R')
{
str = extract_word (str, r_name, sizeof(r_name));
if (ISDIGIT (r_name[1]))
{
if (r_name[2] == '\0' && (r_name[1] - '0' < 8))
op_mask = r_name[1] - '0';
if (r_name[2] != '\0' && (r_name[1] - '0' > 7))
as_bad (_(": expected register name r0-r7 read %s"), r_name);
continue;
}
}
str++;
}
if (operand_two.reg == REG_NONE)
as_bad (_(": expected register name r0-r7 ") );
op_mask = operand_two.reg;
if(operand_two.mod == MOD_POSTINC)
pp_fix = INCREMENT;
if(operand_two.mod == MOD_PREDEC)
pp_fix = DECREMENT;
op_mask <<= 2;
op_mask |= pp_fix;
break;
case 'r': /* Register operand. */
if (*str == 'r' || *str == 'R')
{
*bit_width = 3;
str = extract_word (str, r_name, sizeof(r_name));
op_mask = 0xff;
if (ISDIGIT (r_name[1]))
{
if (r_name[2] == '\0')
op_mask = r_name[1] - '0';
else if (r_name[1] != '0' && ISDIGIT (r_name[2])
&& r_name[3] == '\0')
op_mask = (r_name[1] - '0') * 10 + r_name[2] - '0';
if (op_mask > MAXREGISTER)
as_bad (_(": expected register name r0-r7 read %s "), r_name);
}
}
else
{
as_bad (_(": expected register name r0-r7 read %s "), r_name);
}
if (operand_two.reg == REG_NONE)
as_bad (_(": expected register name r0-r7 "));
*bit_width = 3;
op_mask = operand_two.reg;
break;
case 'i': /* Immediate value or expression expected. */
@ -1101,85 +1241,78 @@ xgate_operand (struct xgate_opcode *opcode,
(*op_con)++;
op_constraint++;
if (ISDIGIT (*op_constraint))
{
*bit_width = (int) *op_constraint - '0';
}
{
*bit_width = (int) *op_constraint - '0';
}
else if (*op_constraint == 'a')
{
*bit_width = 0x0A;
}
{
*bit_width = 0x0A;
}
else if (*op_constraint == 'f')
{
*bit_width = 0x0F;
}
{
*bit_width = 0x0F;
}
/* http://tigcc.ticalc.org/doc/gnuasm.html#SEC31 */
if (*str == '#')
str++;
str = xgate_parse_exp (str, &op_expr);
if (op_expr.X_op == O_constant)
{
if (!ISDIGIT (*op_constraint))
as_bad (
_(":expected bit length with constraint type i(# immediate) read %c"),
*op_constraint);
op_mask = op_expr.X_add_number;
if ((opcode->name[strlen (opcode->name) - 1] == 'l') && macroClipping)
{
op_mask &= 0x00FF;
}
else if ((opcode->name[strlen (opcode->name) - 1]) == 'h'
&& macroClipping)
{
op_mask >>= 8;
}
/* Make sure it fits. */
for (i = *bit_width; i; i--)
{
max_size <<= 1;
max_size += 1;
}
if (op_mask > max_size)
as_bad (_(":operand value(%d) too big for constraint"), op_mask);
}
if (operand_two.exp.X_op == O_constant)
{
op_mask = operand_two.exp.X_add_number;
if ((opcode->name[strlen (opcode->name) - 1] == 'l') && macroClipping)
{
op_mask &= 0x00FF;
}
else if ((opcode->name[strlen (opcode->name) - 1]) == 'h'
&& macroClipping)
{
op_mask >>= 8;
}
/* Make sure it fits. */
for (i = *bit_width; i; i--)
{
max_size <<= 1;
max_size += 1;
}
if (op_mask > max_size)
as_bad (_(":operand value(%d) too big for constraint"), op_mask);
}
else
{
fixup_required = 1;
if (*op_constraint == '8')
{
if ((opcode->name[strlen (opcode->name) - 1] == 'l')
&& macroClipping)
{
fixp = fix_new_exp (frag_now, where, 2, &op_expr, FALSE,
BFD_RELOC_XGATE_24);
/* Should be BFD_RELOC_XGATE_IMM8_LO TODO fix. */
fixp->fx_pcrel_adjust = 0;
}
if ((opcode->name[strlen (opcode->name) - 1]) == 'h'
&& macroClipping)
{
fixp = fix_new_exp (frag_now, where, 2, &op_expr, FALSE,
BFD_RELOC_XGATE_IMM8_HI);
fixp->fx_pcrel_adjust = 0;
}
if (!fixp)
{
fixup_required = 1;
if (*op_constraint == '8')
{
if ((opcode->name[strlen (opcode->name) - 1] == 'l')
&& macroClipping)
{
fixp = fix_new_exp (frag_now, where, 2, &operand_two.exp, FALSE,
BFD_RELOC_XGATE_24);
/* Should be BFD_RELOC_XGATE_IMM8_LO TODO fix. */
fixp->fx_pcrel_adjust = 0;
}
if ((opcode->name[strlen (opcode->name) - 1]) == 'h'
&& macroClipping)
{
fixp = fix_new_exp (frag_now, where, 2, &operand_two.exp, FALSE,
BFD_RELOC_XGATE_IMM8_HI);
fixp->fx_pcrel_adjust = 0;
}
if (!fixp)
as_bad (_(":unknown relocation"));
}
else if (*op_constraint == '5')
{
fixp = fix_new_exp (frag_now, where, 2, &op_expr, FALSE,
BFD_RELOC_XGATE_IMM5);
fixp->fx_pcrel_adjust = 0;
}
else if (*op_constraint == '4')
{
fixp = fix_new_exp (frag_now, where, 2, &op_expr, FALSE,
BFD_RELOC_XGATE_IMM4);
fixp->fx_pcrel_adjust = 0;
}
else if (*op_constraint == '3')
{
fixp = fix_new_exp (frag_now, where, 2, &op_expr, FALSE,
}
else if (*op_constraint == '5')
{
fixp = fix_new_exp (frag_now, where, 2, &operand_two.exp, FALSE,
BFD_RELOC_XGATE_IMM5);
fixp->fx_pcrel_adjust = 0;
}
else if (*op_constraint == '4')
{
fixp = fix_new_exp (frag_now, where, 2, &operand_two.exp, FALSE,
BFD_RELOC_XGATE_IMM4);
fixp->fx_pcrel_adjust = 0;
}
else if (*op_constraint == '3')
{
fixp = fix_new_exp (frag_now, where, 2, &operand_two.exp, FALSE,
BFD_RELOC_XGATE_IMM3);
fixp->fx_pcrel_adjust = 0;
}
@ -1191,243 +1324,47 @@ xgate_operand (struct xgate_opcode *opcode,
break;
case 'c': /* CCR register expected. */
if (*str == 'c' || *str == 'C')
{
*bit_width = 0;
str = extract_word (str, r_name, sizeof(r_name));
if (!(strcmp (r_name, "ccr") || strcmp (r_name, "CCR")))
as_bad (_(": expected register name ccr read %s "), r_name);
}
else
{
as_bad (_(": expected character c or C read %c"), *str);
}
*bit_width = 0;
if (operand_two.reg != REG_CCR)
as_bad (_(": expected register name ccr "));
break;
case 'p': /* PC register expected. */
if (*str == 'p' || *str == 'P')
{
*bit_width = 0;
str = extract_word (str, r_name, sizeof(r_name));
if (!(strcmp (r_name, "pc") || strcmp (r_name, "PC")))
as_bad (_(": expected register name pc read %s "), r_name);
}
else
{
as_bad (_(": expected character p or P read %c "), *str);
}
*bit_width = 0;
if (operand_two.reg != REG_PC)
as_bad (_(": expected register name pc "));
break;
case 'b': /* Branch expected. */
str = xgate_parse_exp (str, &op_expr);
(*op_con)++;
op_constraint++;
if (op_expr.X_op != O_register)
{
if (*op_constraint == '9')
{
/* mode == M68XG_OP_REL9 */
fixp = fix_new_exp (frag_now, where, 2, &op_expr, TRUE,
R_XGATE_PCREL_9);
fixp->fx_pcrel_adjust = 1;
}
else if (*op_constraint == 'a')
{ /* mode == M68XG_OP_REL10 */
fixp = fix_new_exp (frag_now, where, 2, &op_expr, TRUE,
R_XGATE_PCREL_10);
fixp->fx_pcrel_adjust = 1;
}
}
else
{
as_fatal (_("Operand `%x' not recognized in fixup8."), op_expr.X_op);
}
break;
case '?':
break;
default:
as_bad (_("unknown constraint `%c'"), *op_constraint);
break;
}
*line = str;
return op_mask;
}
unsigned int
xgate_detect_format (char *line_in)
{
char num_operands = 0;
char *str = skip_whitespace (line_in);
int i = 0;
int j = 0;
char c = 0;
unsigned int stripped_length = 0;
char sh_format[10] =
{ 0 }; /* Shorthand format. */
char operands_stripped[3][20] =
{
{ 0 }
};
/* Strings. TODO maybe structure this. */
char *i_string =
{ "i" };
char *r_string =
{ "r" };
char *r_r_string =
{ "r,r" };
char *r_r_r_string =
{ "r,r,r" };
char *r_i_string =
{ "r,i" };
char *r_c_string =
{ "r,c" };
char *c_r_string =
{ "c,r" };
char *r_p_string =
{ "r,p" };
char *r_r_i_string =
{ "r,r,i" };
/* If the length is zero this is an inherent instruction. */
if (strlen (str) == 0)
return XG_INH;
for (i = 0, j = 0, num_operands = 1; (c = TOLOWER (*str)) != 0; str++)
{
if (c == ' ' || c == '\t' || c == '(' || c == ')' || c == '-' || c == '+')
continue;
if (c == ',')
{
j++;
num_operands++;
i = 0;
continue;
}
if (i > MAX_DETECT_CHARS)
continue;
operands_stripped[j][i++] = c;
}
/* Process our substrings to see what we have. */
for (i = 0, j = 0; num_operands > i; i++)
{
stripped_length = strlen (&operands_stripped[i][0]);
/* Add separator if we have more than one operand. */
if (i > 0)
sh_format[j++] = ',';
/* Try to process by length first. */
if (stripped_length > 3)
{
sh_format[j++] = 'i';
}
else if (stripped_length == 1)
if (operand_two.exp.X_op != O_register)
{
sh_format[j++] = 'i';
}
else if (stripped_length == 2)
{
if (operands_stripped[i][0]
== 'r' && ISDIGIT (operands_stripped[i][1]))
{
sh_format[j++] = 'r';
}
else if (operands_stripped[i][0] == 'p'
&& operands_stripped[i][1] == 'c')
if (*op_constraint == '9')
{
sh_format[j++] = 'p';
fixp = fix_new_exp (frag_now, where, 2, &operand_two.exp, TRUE,
R_XGATE_PCREL_9);
fixp->fx_pcrel_adjust = 1;
}
else
else if (*op_constraint == 'a')
{
sh_format[j++] = 'i';
fixp = fix_new_exp (frag_now, where, 2, &operand_two.exp, TRUE,
R_XGATE_PCREL_10);
fixp->fx_pcrel_adjust = 1;
}
}
else if (stripped_length == 3)
{
if (operands_stripped[i][0] == 'c'
&& (operands_stripped[i][1] == 'c'
&& operands_stripped[i][2] == 'r'))
{
sh_format[j++] = 'c';
}
else if (operands_stripped[i][0] == '#')
{
sh_format[j++] = 'i';
}
else
{
sh_format[j++] = 'i';
}
}
else /* default to immediate */
else
{
sh_format[j++] = 'i';
as_fatal (_("Operand `%x' not recognized in fixup8."), operand_two.exp.X_op);
}
}
/* See if we have a match. */
if (!strcmp (i_string, sh_format) && num_operands == 1)
return XG_I;
if (!strcmp (r_i_string, sh_format) && num_operands == 2)
return XG_R_I;
if (!strcmp (r_r_r_string, sh_format) && num_operands == 3)
return XG_R_R_R;
if (!strcmp (r_r_string, sh_format) && num_operands == 2)
return XG_R_R;
if (!strcmp (r_string, sh_format) && num_operands == 1)
return XG_R;
if (!strcmp (r_c_string, sh_format) && num_operands == 2)
return XG_R_C;
if (!strcmp (c_r_string, sh_format) && num_operands == 2)
return XG_C_R;
if (!strcmp (r_p_string, sh_format) && num_operands == 2)
return XG_R_P;
if (!strcmp (r_r_i_string, sh_format) && num_operands == 3)
return XG_R_R_I;
return 0;
}
static struct xgate_opcode *
xgate_find_match (struct xgate_opcode_handle *opcode_handle,
int numberOfModes,
unsigned int sh_format)
{
int i;
if (numberOfModes == 0)
return opcode_handle->opc0[0];
for (i = 0; i <= numberOfModes; i++)
if (opcode_handle->opc0[i]->sh_format & sh_format)
return opcode_handle->opc0[i];
return NULL;
}
/* Because we are dealing with two different core that view the system
memory with different offsets, we must differentiate what core a
symbol belongs to, in order for the linker to cross-link. */
int
xgate_frob_symbol (symbolS *sym)
{
asymbol *bfdsym;
elf_symbol_type *elfsym;
bfdsym = symbol_get_bfdsym (sym);
elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
gas_assert(elfsym);
/* Mark the symbol as being *from XGATE */
elfsym->internal_elf_sym.st_target_internal = 1;
break;
case '?':
break;
return 0;
default:
as_bad (_("unknown constraint `%c'"), *op_constraint);
break;
}
return op_mask;
}

2
include/opcode/xgate.h

@ -77,7 +77,7 @@
#define XGATE_OP_IDO5 "r,r,i5"
#define XGATE_OP_REL9 "b9"
#define XGATE_OP_REL10 "ba"
#define XGATE_OP_DYA_MON "=r,r"
#define XGATE_OP_DYA_MON "=r"
/* Macro definitions. */
#define XGATE_OP_IMM16mADD "r,if; addl addh"
#define XGATE_OP_IMM16mAND "r,if; andl andh"

11
opcodes/xgate-dis.c

@ -177,16 +177,7 @@ print_insn (bfd_vma memaddr, struct disassemble_info* info)
}
break;
case XG_R_R:
if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_DYA_MON))
{
operandOne = ripBits (&operMaskReg, 3, decodePTR->opcodePTR,
raw_code);
operandTwo = ripBits (&operMaskReg, 3, decodePTR->opcodePTR,
raw_code);
(*info->fprintf_func)(info->stream, " R%x, R%x", operandOne,
operandTwo);
}
else if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_DYA))
if (!strcmp (decodePTR->opcodePTR->constraints, XGATE_OP_DYA))
{
operandOne = ripBits (&operMaskReg, 3, opcodePTR, raw_code);
operandTwo = ripBits (&operMaskReg, 3, opcodePTR, raw_code);

5
opcodes/xgate-opc.c

@ -74,7 +74,6 @@
#define OP_INH XGATE_OP_INH
#define OP_TRI XGATE_OP_TRI
#define OP_DYA XGATE_OP_DYA
#define OP_DM XGATE_OP_DYA_MON
#define OP_IMM3 XGATE_OP_IMM3
#define OP_IMM4 XGATE_OP_IMM4
#define OP_IMM8 XGATE_OP_IMM8
@ -87,6 +86,7 @@
#define OP_IDO5 XGATE_OP_IDO5
#define OP_REL9 XGATE_OP_REL9
#define OP_REL10 XGATE_OP_REL10
#define OP_DM XGATE_OP_DYA_MON
/* macro operand modes */
#define OP_mADD XGATE_OP_IMM16mADD
#define OP_mAND XGATE_OP_IMM16mAND
@ -190,7 +190,8 @@ const struct xgate_opcode xgate_opcodes[] = {
{ "blo", OP_REL9, "0010001iiiiiiiii", XG_IP, 2, 0x2200, 0, 0, CHG_NONE, ALL},
{ "cmp", OP_mCPC, "----------------", XG_R_I, 4, 0, 0, 0, CHG_NONE, ALL},
{ "cmp", OP_DYA, "00011sssrrrrrr00", XG_R_R, 2, 0x1800, 0, 0, CHG_NZVC, ALL},
{ "com", OP_DM, "00010rrrsssrrr11", XG_R_R, 2, 0x1003, 0, 0, CHG_NZV, ALL},
{ "com", OP_DM, "00010rrrsssrrr11", XG_R, 2, 0x1003, 0, 0, CHG_NZVC, ALL},
{ "com", OP_DYA, "00010rrrsssrrr11", XG_R_R, 2, 0x1003, 0, 0, CHG_NZV, ALL},
{ "cpc", OP_DYA, "00011sssrrrrrr01", XG_R_R, 2, 0x1801, 0, 0, CHG_NZVC, ALL},
{ "ldd", OP_mLDW, "----------------", XG_R_I, 4, 0, 0, 0, CHG_NONE, ALL},
{ "ldw", OP_mLDW, "----------------", XG_R_I, 4, 0, 0, 0, CHG_NONE, ALL},

Loading…
Cancel
Save