diff options
author | Sean Keys <skeys@ipdatasys.com> | 2012-07-05 19:37:52 +0000 |
---|---|---|
committer | Sean Keys <skeys@ipdatasys.com> | 2012-07-05 19:37:52 +0000 |
commit | 3879925e690102682c05d7f61997dae9eaf23b98 (patch) | |
tree | a154e9b8632ae32330ee15f32a61e4926fa40d88 /gas/config/tc-xgate.c | |
parent | f4263ca2cd6e7ad1c17050f13e93458a59a31884 (diff) | |
download | gdb-3879925e690102682c05d7f61997dae9eaf23b98.zip gdb-3879925e690102682c05d7f61997dae9eaf23b98.tar.gz gdb-3879925e690102682c05d7f61997dae9eaf23b98.tar.bz2 |
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.
Diffstat (limited to 'gas/config/tc-xgate.c')
-rw-r--r-- | gas/config/tc-xgate.c | 787 |
1 files changed, 362 insertions, 425 deletions
diff --git a/gas/config/tc-xgate.c b/gas/config/tc-xgate.c index 84bac42..7db84ea 100644 --- a/gas/config/tc-xgate.c +++ b/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; } |