static const char * parse_uhi16 (CGEN_CPU_DESC cd, const char **strp, int opindex, unsigned long *valuep) { const char *errmsg; enum cgen_parse_operand_result result_type; bfd_vma value; if (**strp == '#' || **strp == '%') { if (strncasecmp (*strp + 1, "hi(", 3) == 0) { *strp += 4; errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16, & result_type, & value); if (**strp != ')') return "missing `)'"; ++*strp; if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) { /* If bfd_vma is wider than 32 bits, but we have a sign- or zero-extension, truncate it. */ if (value >= - ((bfd_vma)1 << 31) || value <= ((bfd_vma)1 << 31) - (bfd_vma)1) value &= (((bfd_vma)1 << 16) << 16) - 1; value >>= 16; } *valuep = value; return errmsg; } else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
static const char * parse_imm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, bfd_reloc_code_real_type code ATTRIBUTE_UNUSED, enum cgen_parse_operand_result * result_type, bfd_vma * valuep) { const char * errmsg; enum cgen_parse_operand_result rt; long dummyval; if (!result_type) result_type = &rt; if (strncasecmp (*strp, "%high(", 6) == 0) { *strp += 6; errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_EPIPHANY_HIGH, result_type, valuep); if (**strp != ')') return MISSING_CLOSE_PARENTHESIS; ++*strp; *valuep >>= 16; }
static const char * parse_hi16 (CGEN_CPU_DESC cd, const char **strp, int opindex, unsigned long *valuep) { if (strncasecmp (*strp, "hi(", 3) == 0) { enum cgen_parse_operand_result result_type; bfd_vma value; const char *errmsg; *strp += 3; errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16, &result_type, &value); if (**strp != ')') return _("missing `)'"); ++*strp; if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) value = (value >> 16) & 0xffff; *valuep = value; return errmsg; } return parse_imm (cd, strp, opindex, valuep); }
static const char * parse_imm8 (CGEN_CPU_DESC cd, const char ** strp, int opindex, bfd_reloc_code_real_type code, enum cgen_parse_operand_result * result_type, bfd_vma * valuep) { const char * errmsg; enum cgen_parse_operand_result rt; long dummyval; if (!result_type) result_type = &rt; code = BFD_RELOC_NONE; if (!cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_gr_names, &dummyval) || !cgen_parse_keyword (cd, strp, &epiphany_cgen_opval_cr_names, &dummyval)) /* Don't treat "mov ip,ip" as a move-immediate. */ return _("register source in immediate move"); errmsg = cgen_parse_address (cd, strp, opindex, code, result_type, valuep); if (errmsg) return errmsg; if (*result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) errmsg = cgen_validate_unsigned_integer (*valuep, 0, 0xff); else errmsg = _("byte relocation unsupported"); *valuep &= 0xff; return errmsg; }
static const char * parse_gotoff_lo16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep) { if (strncasecmp (*strp, "gotofflo16(", 11) == 0) { const char *errmsg; enum cgen_parse_operand_result result_type; bfd_vma value; *strp += 11; errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LM32_GOTOFF_LO16, &result_type, &value); if (**strp != ')') return _("missing `)'"); ++*strp; if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) value &= 0xffff; *valuep = value; return errmsg; } return _("expecting got relative address: gotofflo16(symbol)"); }
static const char * parse_uhi16 (CGEN_CPU_DESC cd, const char **strp, int opindex, unsigned long *valuep) { const char *errmsg; enum cgen_parse_operand_result result_type; bfd_vma value; if (**strp == '#' || **strp == '%') { if (strncasecmp (*strp + 1, "hi(", 3) == 0) { *strp += 4; errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16, & result_type, & value); if (**strp != ')') return "missing `)'"; ++*strp; if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) { /* If value is wider than 32 bits then be careful about how we extract bits 16-31. */ if (sizeof (value) > 4) value &= (((bfd_vma)1 << 16) << 16) - 1; value >>= 16; } *valuep = value; return errmsg; } else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
static const char * parse_immediate16 (CGEN_CPU_DESC cd, const char **strp, int opindex, unsigned long *valuep) { const char *errmsg; enum cgen_parse_operand_result result; bfd_reloc_code_real_type code = BFD_RELOC_NONE; bfd_vma value; if (strncmp (*strp, "@hi(", 4) == 0) { *strp += 4; code = BFD_RELOC_HI16; } else if (strncmp (*strp, "@lo(", 4) == 0) { *strp += 4; code = BFD_RELOC_LO16; } if (code == BFD_RELOC_NONE) errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep); else { errmsg = cgen_parse_address (cd, strp, opindex, code, &result, &value); if ((errmsg == NULL) && (result != CGEN_PARSE_OPERAND_RESULT_QUEUED)) errmsg = _("Operand is not a symbol"); *valuep = value; if ((code == BFD_RELOC_HI16 || code == BFD_RELOC_LO16) && **strp == ')') *strp += 1; else { errmsg = _("Syntax error: No trailing ')'"); return errmsg; } } return errmsg; }
static const char * parse_loopsize (CGEN_CPU_DESC cd, const char **strp, int opindex, void *arg) { signed long * valuep = (signed long *) arg; const char *errmsg; bfd_reloc_code_real_type code = BFD_RELOC_NONE; enum cgen_parse_operand_result result_type; bfd_vma value; /* Is it a control transfer instructions? */ if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_LOOPSIZE) { code = BFD_RELOC_MT_PCINSN8; errmsg = cgen_parse_address (cd, strp, opindex, code, & result_type, & value); *valuep = value; return errmsg; } abort (); }
/* Handle iq10 21-bit jmp offset. */ static const char * parse_jtargq10 (CGEN_CPU_DESC cd, const char **strp, int opindex, int reloc ATTRIBUTE_UNUSED, enum cgen_parse_operand_result *type_addr ATTRIBUTE_UNUSED, bfd_vma *valuep) { const char *errmsg; bfd_vma value; enum cgen_parse_operand_result result_type = CGEN_PARSE_OPERAND_RESULT_NUMBER; errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IQ2000_OFFSET_21, & result_type, & value); if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) { /* Check value is within 23-bits (remembering that 2-bit shift right will occur). */ if (value > 0x7fffff) return _("21-bit offset out of range"); } *valuep = (value & 0x7FFFFF); return errmsg; } /* Handle high(). */ static const char * parse_hi16 (CGEN_CPU_DESC cd,
static const char * parse_uslo16 (CGEN_CPU_DESC cd, const char **strp, int opindex, signed long *valuep) { const char *errmsg; enum cgen_parse_operand_result result_type; bfd_vma value; if (**strp == '#' || **strp == '%') { if (strncasecmp (*strp + 1, "lo(", 3) == 0) { *strp += 4; errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16, & result_type, & value); if (**strp != ')') return "missing `)'"; ++*strp; if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER) value &= 0xffff; *valuep = value; return errmsg; } else if (strncasecmp (*strp + 1, "gprello(", 8) == 0) { *strp += 9; errmsg = parse_symbolic_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO, & result_type, & value); if (**strp != ')') return "missing ')'"; ++*strp; *valuep = value; return errmsg; } else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0) { *strp += 7; errmsg = parse_symbolic_address (cd, strp, opindex, BFD_RELOC_FRV_GOTLO, & result_type, & value); if (**strp != ')') return "missing ')'"; ++*strp; *valuep = value; return errmsg; } else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0) { *strp += 15; errmsg = parse_symbolic_address (cd, strp, opindex, BFD_RELOC_FRV_FUNCDESC_GOTLO, & result_type, & value); if (**strp != ')') return "missing ')'"; ++*strp; *valuep = value; return errmsg; } else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0) { *strp += 10; errmsg = parse_symbolic_address (cd, strp, opindex, BFD_RELOC_FRV_GOTOFFLO, & result_type, & value); if (**strp != ')') return "missing ')'"; ++*strp; *valuep = value; return errmsg; } else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0) { *strp += 18; errmsg = parse_symbolic_address (cd, strp, opindex, BFD_RELOC_FRV_FUNCDESC_GOTOFFLO, & result_type, & value); if (**strp != ')') return "missing ')'"; ++*strp; *valuep = value; return errmsg; } else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0) { *strp += 14; errmsg = parse_symbolic_address (cd, strp, opindex, BFD_RELOC_FRV_GOTTLSDESCLO, & result_type, & value); if (**strp != ')') return "missing ')'"; ++*strp; *valuep = value; return errmsg; } else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0) { *strp += 11; errmsg = parse_symbolic_address (cd, strp, opindex, BFD_RELOC_FRV_TLSMOFFLO, & result_type, & value); if (**strp != ')') return "missing ')'"; ++*strp; *valuep = value; return errmsg; } else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0) { *strp += 13; errmsg = parse_symbolic_address (cd, strp, opindex, BFD_RELOC_FRV_GOTTLSOFFLO, & result_type, & value); if (**strp != ')') return "missing ')'"; ++*strp; *valuep = value; return errmsg; } } return cgen_parse_signed_integer (cd, strp, opindex, valuep); }
const char * lm32_cgen_parse_operand (CGEN_CPU_DESC cd, int opindex, const char ** strp, CGEN_FIELDS * fields) { const char * errmsg = NULL; /* Used by scalar operands that still need to be parsed. */ long junk ATTRIBUTE_UNUSED; switch (opindex) { case LM32_OPERAND_BRANCH : { bfd_vma value = 0; errmsg = cgen_parse_address (cd, strp, LM32_OPERAND_BRANCH, 0, NULL, & value); fields->f_branch = value; } break; case LM32_OPERAND_CALL : { bfd_vma value = 0; errmsg = cgen_parse_address (cd, strp, LM32_OPERAND_CALL, 0, NULL, & value); fields->f_call = value; } break; case LM32_OPERAND_CSR : errmsg = cgen_parse_keyword (cd, strp, & lm32_cgen_opval_h_csr, & fields->f_csr); break; case LM32_OPERAND_EXCEPTION : errmsg = cgen_parse_unsigned_integer (cd, strp, LM32_OPERAND_EXCEPTION, (unsigned long *) (& fields->f_exception)); break; case LM32_OPERAND_GOT16 : errmsg = parse_got16 (cd, strp, LM32_OPERAND_GOT16, (long *) (& fields->f_imm)); break; case LM32_OPERAND_GOTOFFHI16 : errmsg = parse_gotoff_hi16 (cd, strp, LM32_OPERAND_GOTOFFHI16, (long *) (& fields->f_imm)); break; case LM32_OPERAND_GOTOFFLO16 : errmsg = parse_gotoff_lo16 (cd, strp, LM32_OPERAND_GOTOFFLO16, (long *) (& fields->f_imm)); break; case LM32_OPERAND_GP16 : errmsg = parse_gp16 (cd, strp, LM32_OPERAND_GP16, (long *) (& fields->f_imm)); break; case LM32_OPERAND_HI16 : errmsg = parse_hi16 (cd, strp, LM32_OPERAND_HI16, (unsigned long *) (& fields->f_uimm)); break; case LM32_OPERAND_IMM : errmsg = cgen_parse_signed_integer (cd, strp, LM32_OPERAND_IMM, (long *) (& fields->f_imm)); break; case LM32_OPERAND_LO16 : errmsg = parse_lo16 (cd, strp, LM32_OPERAND_LO16, (unsigned long *) (& fields->f_uimm)); break; case LM32_OPERAND_R0 : errmsg = cgen_parse_keyword (cd, strp, & lm32_cgen_opval_h_gr, & fields->f_r0); break; case LM32_OPERAND_R1 : errmsg = cgen_parse_keyword (cd, strp, & lm32_cgen_opval_h_gr, & fields->f_r1); break; case LM32_OPERAND_R2 : errmsg = cgen_parse_keyword (cd, strp, & lm32_cgen_opval_h_gr, & fields->f_r2); break; case LM32_OPERAND_SHIFT : errmsg = cgen_parse_unsigned_integer (cd, strp, LM32_OPERAND_SHIFT, (unsigned long *) (& fields->f_shift)); break; case LM32_OPERAND_UIMM : errmsg = cgen_parse_unsigned_integer (cd, strp, LM32_OPERAND_UIMM, (unsigned long *) (& fields->f_uimm)); break; case LM32_OPERAND_USER : errmsg = cgen_parse_unsigned_integer (cd, strp, LM32_OPERAND_USER, (unsigned long *) (& fields->f_user)); break; default : /* xgettext:c-format */ fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex); abort (); } return errmsg; }
static const char * parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, void *arg) { signed long * valuep = (signed long *) arg; const char *errmsg; enum cgen_parse_operand_result result_type; bfd_reloc_code_real_type code = BFD_RELOC_NONE; bfd_vma value; /* Is it a control transfer instructions? */ if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16O) { code = BFD_RELOC_16_PCREL; errmsg = cgen_parse_address (cd, strp, opindex, code, & result_type, & value); if (errmsg == NULL) { if (signed_out_of_bounds (value)) errmsg = _("Operand out of range. Must be between -32768 and 32767."); } *valuep = value; return errmsg; } /* If it's not a control transfer instruction, then we have to check for %OP relocating operators. */ if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16L) ; else if (strncmp (*strp, "%hi16", 5) == 0) { *strp += 5; code = BFD_RELOC_HI16; } else if (strncmp (*strp, "%lo16", 5) == 0) { *strp += 5; code = BFD_RELOC_LO16; } /* If we found a %OP relocating operator, then parse it as an address. If not, we need to parse it as an integer, either signed or unsigned depending on which operand type we have. */ if (code != BFD_RELOC_NONE) { /* %OP relocating operator found. */ errmsg = cgen_parse_address (cd, strp, opindex, code, & result_type, & value); if (errmsg == NULL) { switch (result_type) { case (CGEN_PARSE_OPERAND_RESULT_NUMBER): if (code == BFD_RELOC_HI16) value = (value >> 16) & 0xFFFF; else if (code == BFD_RELOC_LO16) value = value & 0xFFFF; else errmsg = _("Biiiig Trouble in parse_imm16!"); break; case (CGEN_PARSE_OPERAND_RESULT_QUEUED): /* No special processing for this case. */ break; default: errmsg = _("The percent-operator's operand is not a symbol"); break; } }