v850-opc.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 787 行 · 第 1/2 页

C
787
字号
/* Assemble V850 instructions.   Copyright 1996, 1997, 1998, 2000 Free Software Foundation, Inc.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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */#include "sysdep.h"#include "opcode/v850.h"#include <stdio.h>#include "opintl.h"/* regular opcode */#define OP(x)		((x & 0x3f) << 5)#define OP_MASK		OP (0x3f)/* conditional branch opcode */#define BOP(x)		((0x0b << 7) | (x & 0x0f))#define BOP_MASK	((0x0f << 7) | 0x0f)/* one-word opcodes */#define one(x)		((unsigned int) (x))/* two-word opcodes */#define two(x,y)	((unsigned int) (x) | ((unsigned int) (y) << 16))/* The functions used to insert and extract complicated operands.  *//* Note: There is a conspiracy between these functions and   v850_insert_operand() in gas/config/tc-v850.c.  Error messages   containing the string 'out of range' will be ignored unless a   specific command line option is given to GAS.  */static const char * not_valid    = N_ ("displacement value is not in range and is not aligned");static const char * out_of_range = N_ ("displacement value is out of range");static const char * not_aligned  = N_ ("displacement value is not aligned");static const char * immediate_out_of_range = N_ ("immediate value is out of range");static unsigned longinsert_d9 (insn, value, errmsg)     unsigned long insn;     long          value;     const char ** errmsg;{  if (value > 0xff || value < -0x100)    {      if ((value % 2) != 0)	* errmsg = _("branch value not in range and to odd offset");      else	* errmsg = _("branch value out of range");    }  else if ((value % 2) != 0)    * errmsg = _("branch to odd offset");  return (insn | ((value & 0x1f0) << 7) | ((value & 0x0e) << 3));}static unsigned longextract_d9 (insn, invalid)     unsigned long insn;     int *         invalid;{  unsigned long ret = ((insn & 0xf800) >> 7) | ((insn & 0x0070) >> 3);  if ((insn & 0x8000) != 0)    ret -= 0x0200;  return ret;}static unsigned longinsert_d22 (insn, value, errmsg)     unsigned long insn;     long          value;     const char ** errmsg;{  if (value > 0x1fffff || value < -0x200000)    {      if ((value % 2) != 0)	* errmsg = _("branch value not in range and to an odd offset");      else	* errmsg = _("branch value out of range");    }  else if ((value % 2) != 0)    * errmsg = _("branch to odd offset");  return (insn | ((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16));}static unsigned longextract_d22 (insn, invalid)     unsigned long insn;     int *         invalid;{  signed long ret = ((insn & 0xfffe0000) >> 16) | ((insn & 0x3f) << 16);  return (unsigned long) ((ret << 10) >> 10);}static unsigned longinsert_d16_15 (insn, value, errmsg)     unsigned long insn;     long          value;     const char ** errmsg;{  if (value > 0x7fff || value < -0x8000)    {      if ((value % 2) != 0)	* errmsg = _(not_valid);      else	* errmsg = _(out_of_range);    }  else if ((value % 2) != 0)    * errmsg = _(not_aligned);  return insn | ((value & 0xfffe) << 16);}static unsigned longextract_d16_15 (insn, invalid)     unsigned long insn;     int *         invalid;{  signed long ret = (insn & 0xfffe0000);  return ret >> 16;}static unsigned longinsert_d8_7 (insn, value, errmsg)     unsigned long insn;     long          value;     const char ** errmsg;{  if (value > 0xff || value < 0)    {      if ((value % 2) != 0)	* errmsg = _(not_valid);      else	* errmsg = _(out_of_range);    }  else if ((value % 2) != 0)    * errmsg = _(not_aligned);  value >>= 1;  return (insn | (value & 0x7f));}static unsigned longextract_d8_7 (insn, invalid)     unsigned long insn;     int *         invalid;{  unsigned long ret = (insn & 0x7f);  return ret << 1;}static unsigned longinsert_d8_6 (insn, value, errmsg)     unsigned long insn;     long          value;     const char ** errmsg;{  if (value > 0xff || value < 0)    {      if ((value % 4) != 0)	*errmsg = _(not_valid);      else	* errmsg = _(out_of_range);    }  else if ((value % 4) != 0)    * errmsg = _(not_aligned);  value >>= 1;  return (insn | (value & 0x7e));}static unsigned longextract_d8_6 (insn, invalid)     unsigned long insn;     int *         invalid;{  unsigned long ret = (insn & 0x7e);  return ret << 1;}static unsigned longinsert_d5_4 (insn, value, errmsg)     unsigned long insn;     long          value;     const char ** errmsg;{  if (value > 0x1f || value < 0)    {      if (value & 1)	* errmsg = _(not_valid);      else	*errmsg = _(out_of_range);    }  else if (value & 1)    * errmsg = _(not_aligned);  value >>= 1;  return (insn | (value & 0x0f));}static unsigned longextract_d5_4 (insn, invalid)     unsigned long insn;     int *         invalid;{  unsigned long ret = (insn & 0x0f);  return ret << 1;}static unsigned longinsert_d16_16 (insn, value, errmsg)     unsigned long insn;     signed long   value;     const char ** errmsg;{  if (value > 0x7fff || value < -0x8000)    * errmsg = _(out_of_range);  return (insn | ((value & 0xfffe) << 16) | ((value & 1) << 5));}static unsigned longextract_d16_16 (insn, invalid)     unsigned long insn;     int *         invalid;{  signed long ret = insn & 0xfffe0000;  ret >>= 16;  ret |= ((insn & 0x20) >> 5);    return ret;}static unsigned longinsert_i9 (insn, value, errmsg)     unsigned long insn;     signed long   value;     const char ** errmsg;{  if (value > 0xff || value < -0x100)    * errmsg = _(immediate_out_of_range);  return insn | ((value & 0x1e0) << 13) | (value & 0x1f);}static unsigned longextract_i9 (insn, invalid)     unsigned long insn;     int *         invalid;{  signed long ret = insn & 0x003c0000;  ret <<= 10;  ret >>= 23;  ret |= (insn & 0x1f);    return ret;}static unsigned longinsert_u9 (insn, value, errmsg)     unsigned long insn;     unsigned long value;     const char ** errmsg;{  if (value > 0x1ff)    * errmsg = _(immediate_out_of_range);  return insn | ((value & 0x1e0) << 13) | (value & 0x1f);}static unsigned longextract_u9 (insn, invalid)     unsigned long insn;     int *         invalid;{  unsigned long ret = insn & 0x003c0000;  ret >>= 13;  ret |= (insn & 0x1f);    return ret;}static unsigned longinsert_spe (insn, value, errmsg)     unsigned long insn;     unsigned long value;     const char ** errmsg;{  if (value != 3)    * errmsg = _("invalid register for stack adjustment");  return insn & (~ 0x180000);}static unsigned longextract_spe (insn, invalid)     unsigned long insn;     int *         invalid;{  return 3;}static unsigned longinsert_i5div (insn, value, errmsg)     unsigned long insn;     unsigned long value;     const char ** errmsg;{  if (value > 0x1ff)    {      if (value & 1)	* errmsg = _("immediate value not in range and not even");      else	* errmsg = _(immediate_out_of_range);    }  else if (value & 1)    * errmsg = _("immediate value must be even");  value = 32 - value;    return insn | ((value & 0x1e) << 17);}static unsigned longextract_i5div (insn, invalid)     unsigned long insn;     int *         invalid;{  unsigned long ret = insn & 0x3c0000;  ret >>= 17;  ret = 32 - ret;    return ret;}/* Warning: code in gas/config/tc-v850.c examines the contents of this array.   If you change any of the values here, be sure to look for side effects in   that code. */const struct v850_operand v850_operands[] ={#define UNUSED	0  { 0, 0, NULL, NULL, 0 }, /* The R1 field in a format 1, 6, 7, or 9 insn. */#define R1	(UNUSED + 1)  { 5, 0, NULL, NULL, V850_OPERAND_REG }, /* As above, but register 0 is not allowed.  */#define R1_NOTR0 (R1 + 1)  { 5, 0, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0 }, /* The R2 field in a format 1, 2, 4, 5, 6, 7, 9 insn. */#define R2	(R1_NOTR0 + 1)  { 5, 11, NULL, NULL, V850_OPERAND_REG },/* As above, but register 0 is not allowed.  */#define R2_NOTR0 (R2 + 1)  { 5, 11, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0 },/* The imm5 field in a format 2 insn. */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?