URL
https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk
Subversion Repositories openrisc_me
[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [cpu/] [mt.opc] - Rev 205
Compare with Previous | Blame | View Log
/* Morpho Technologies mRISC opcode support, for GNU Binutils. -*- C -*-Copyright 2001, 2007, 2008, 2009 Free Software Foundation, Inc.Contributed by Red Hat Inc; developed under contract fromMorpho Technologies.This file is part of the GNU Binutils.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 3 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin Street - Fifth Floor, Boston,MA 02110-1301, USA. *//* Each section is delimited with start and end markers.<arch>-opc.h additions use: "-- opc.h"<arch>-opc.c additions use: "-- opc.c"<arch>-asm.c additions use: "-- asm.c"<arch>-dis.c additions use: "-- dis.c"<arch>-ibd.h additions use: "-- ibd.h" *//* -- opc.h *//* Check applicability of instructions against machines. */#define CGEN_VALIDATE_INSN_SUPPORTED/* Allows reason codes to be output when assembler errors occur. */#define CGEN_VERBOSE_ASSEMBLER_ERRORS/* Override disassembly hashing - there are variable bits in the topbyte of these instructions. */#define CGEN_DIS_HASH_SIZE 8#define CGEN_DIS_HASH(buf, value) (((* (unsigned char *) (buf)) >> 5) % CGEN_DIS_HASH_SIZE)#define CGEN_ASM_HASH_SIZE 127#define CGEN_ASM_HASH(insn) mt_asm_hash (insn)extern unsigned int mt_asm_hash (const char *);extern int mt_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);/* -- opc.c */#include "safe-ctype.h"/* Special check to ensure that instruction exists for given machine. */intmt_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn){int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);/* No mach attribute? Assume it's supported for all machs. */if (machs == 0)return 1;return ((machs & cd->machs) != 0);}/* A better hash function for instruction mnemonics. */unsigned intmt_asm_hash (const char* insn){unsigned int hash;const char* m = insn;for (hash = 0; *m && ! ISSPACE (*m); m++)hash = (hash * 23) ^ (0x1F & TOLOWER (*m));/* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */return hash % CGEN_ASM_HASH_SIZE;}/* -- asm.c *//* Range checking for signed numbers. Returns 0 if acceptableand 1 if the value is out of bounds for a signed quantity. */static intsigned_out_of_bounds (long val){if ((val < -32768) || (val > 32767))return 1;return 0;}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 ();}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, thenwe 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 unsigneddepending 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;elseerrmsg = _("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;}}*valuep = value;}else{/* Parse hex values like 0xffff as unsigned, and sign extendthem manually. */int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MT_OPERAND_IMM16);if ((*strp)[0] == '0'&& ((*strp)[1] == 'x' || (*strp)[1] == 'X'))parse_signed = 0;/* No relocating operator. Parse as an number. */if (parse_signed){/* Parse as as signed integer. */errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);if (errmsg == NULL){#if 0/* Manual range checking is needed for the signed case. */if (*valuep & 0x8000)value = 0xffff0000 | *valuep;elsevalue = *valuep;if (signed_out_of_bounds (value))errmsg = _("Operand out of range. Must be between -32768 and 32767.");/* Truncate to 16 bits. This is necessarybecause cgen will have sign extended *valuep. */*valuep &= 0xFFFF;#endif}}else{/* MT_OPERAND_IMM16Z. Parse as an unsigned integer. */errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);if (opindex == (CGEN_OPERAND_TYPE) MT_OPERAND_IMM16&& *valuep >= 0x8000&& *valuep <= 0xffff)*valuep -= 0x10000;}}return errmsg;}static const char *parse_dup (CGEN_CPU_DESC cd,const char **strp,int opindex,unsigned long *valuep){const char *errmsg = NULL;if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0){*strp += 3;*valuep = 1;}else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0){*strp += 2;*valuep = 0;}elseerrmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);return errmsg;}static const char *parse_ball (CGEN_CPU_DESC cd,const char **strp,int opindex,unsigned long *valuep){const char *errmsg = NULL;if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0){*strp += 3;*valuep = 1;}else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0){*strp += 3;*valuep = 0;}elseerrmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);return errmsg;}static const char *parse_xmode (CGEN_CPU_DESC cd,const char **strp,int opindex,unsigned long *valuep){const char *errmsg = NULL;if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0){*strp += 2;*valuep = 1;}else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0){*strp += 2;*valuep = 0;}elseerrmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);return errmsg;}static const char *parse_rc (CGEN_CPU_DESC cd,const char **strp,int opindex,unsigned long *valuep){const char *errmsg = NULL;if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0){*strp += 1;*valuep = 1;}else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0){*strp += 1;*valuep = 0;}elseerrmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);return errmsg;}static const char *parse_cbrb (CGEN_CPU_DESC cd,const char **strp,int opindex,unsigned long *valuep){const char *errmsg = NULL;if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0){*strp += 2;*valuep = 1;}else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0){*strp += 2;*valuep = 0;}elseerrmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);return errmsg;}static const char *parse_rbbc (CGEN_CPU_DESC cd,const char **strp,int opindex,unsigned long *valuep){const char *errmsg = NULL;if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0){*strp += 2;*valuep = 0;}else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0){*strp += 3;*valuep = 1;}else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0){*strp += 3;*valuep = 2;}else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0){*strp += 2;*valuep = 3;}elseerrmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);return errmsg;}static const char *parse_type (CGEN_CPU_DESC cd,const char **strp,int opindex,unsigned long *valuep){const char *errmsg = NULL;if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0){*strp += 3;*valuep = 0;}else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0){*strp += 4;*valuep = 1;}else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0){*strp += 2;*valuep = 2;}elseerrmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);if ((errmsg == NULL) && (*valuep == 3))errmsg = _("invalid operand. type may have values 0,1,2 only.");return errmsg;}/* -- dis.c */static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);static void print_pcrel (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);static voidprint_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value,unsigned int attrs ATTRIBUTE_UNUSED,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED){disassemble_info *info = (disassemble_info *) dis_info;info->fprintf_func (info->stream, "$%lx", value);if (0)print_normal (cd, dis_info, value, attrs, pc, length);}static voidprint_pcrel (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value,unsigned int attrs ATTRIBUTE_UNUSED,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED){print_address (cd, dis_info, value + pc, attrs, pc, length);}/* -- */
