OSDN Git Service

daily update
[pf3gnuchains/pf3gnuchains3x.git] / bfd / cpu-ia64-opc.c
index 8c22942..b797e44 100644 (file)
@@ -1,25 +1,27 @@
-/* Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+/* Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2009
+   Free Software Foundation, Inc.
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the 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 of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
 
 /* Logically, this code should be part of libopcode but since some of
    the operand insertion/extraction functions help bfd to implement
-   relocations, this code is included as part of elf64-ia64.c.  This
+   relocations, this code is included as part of cpu-ia64.c.  This
    avoids circular dependencies between libopcode and libbfd and also
    obviates the need for applications to link in libopcode when all
    they really want is libbfd.
@@ -79,19 +81,19 @@ ext_reg (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
 static const char*
 ins_immu (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
 {
-  ia64_insn new = 0;
+  ia64_insn new_insn = 0;
   int i;
 
   for (i = 0; i < NELEMS (self->field) && self->field[i].bits; ++i)
     {
-      new |= ((value & ((((ia64_insn) 1) << self->field[i].bits) - 1))
-             << self->field[i].shift);
+      new_insn |= ((value & ((((ia64_insn) 1) << self->field[i].bits) - 1))
+                 << self->field[i].shift);
       value >>= self->field[i].bits;
     }
   if (value)
     return "integer operand out of range";
 
-  *code |= new;
+  *code |= new_insn;
   return 0;
 }
 
@@ -113,6 +115,29 @@ ext_immu (const struct ia64_operand *self, ia64_insn code, ia64_insn *valuep)
 }
 
 static const char*
+ins_immu5b (const struct ia64_operand *self, ia64_insn value,
+           ia64_insn *code)
+{
+  if (value < 32 || value > 63)
+    return "value must be between 32 and 63";
+  return ins_immu (self, value - 32, code);
+}
+
+static const char*
+ext_immu5b (const struct ia64_operand *self, ia64_insn code,
+           ia64_insn *valuep)
+{
+  const char *result;
+
+  result = ext_immu (self, code, valuep);
+  if (result)
+    return result;
+
+  *valuep = *valuep + 32;
+  return 0;
+}
+
+static const char*
 ins_immus8 (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
 {
   if (value & 0x7)
@@ -138,22 +163,22 @@ ins_imms_scaled (const struct ia64_operand *self, ia64_insn value,
                 ia64_insn *code, int scale)
 {
   BFD_HOST_64_BIT svalue = value, sign_bit = 0;
-  ia64_insn new = 0;
+  ia64_insn new_insn = 0;
   int i;
 
   svalue >>= scale;
 
   for (i = 0; i < NELEMS (self->field) && self->field[i].bits; ++i)
     {
-      new |= ((svalue & ((((ia64_insn) 1) << self->field[i].bits) - 1))
-             << self->field[i].shift);
+      new_insn |= ((svalue & ((((ia64_insn) 1) << self->field[i].bits) - 1))
+                 << self->field[i].shift);
       sign_bit = (svalue >> (self->field[i].bits - 1)) & 1;
       svalue >>= self->field[i].bits;
     }
   if ((!sign_bit && svalue != 0) || (sign_bit && svalue != -1))
     return "integer operand out of range";
 
-  *code |= new;
+  *code |= new_insn;
   return 0;
 }
 
@@ -161,8 +186,8 @@ static const char*
 ext_imms_scaled (const struct ia64_operand *self, ia64_insn code,
                 ia64_insn *valuep, int scale)
 {
-  int i, bits = 0, total = 0, shift;
-  BFD_HOST_64_BIT val = 0;
+  int i, bits = 0, total = 0;
+  BFD_HOST_64_BIT val = 0, sign;
 
   for (i = 0; i < NELEMS (self->field) && self->field[i].bits; ++i)
     {
@@ -172,8 +197,8 @@ ext_imms_scaled (const struct ia64_operand *self, ia64_insn code,
       total += bits;
     }
   /* sign extend: */
-  shift = 8*sizeof (val) - total;
-  val = (val << shift) >> shift;
+  sign = (BFD_HOST_64_BIT) 1 << (total - 1);
+  val = (val ^ sign) - sign;
 
   *valuep = (val << scale);
   return 0;
@@ -188,10 +213,7 @@ ins_imms (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
 static const char*
 ins_immsu4 (const struct ia64_operand *self, ia64_insn value, ia64_insn *code)
 {
-  if (value == (BFD_HOST_U_64_BIT) 0x100000000)
-    value = 0;
-  else
-    value = (((BFD_HOST_64_BIT)value << 32) >> 32);
+  value = ((value & 0xffffffff) ^ 0x80000000) - 0x80000000;
 
   return ins_imms_scaled (self, value, code, 0);
 }
@@ -213,10 +235,7 @@ static const char*
 ins_immsm1u4 (const struct ia64_operand *self, ia64_insn value,
              ia64_insn *code)
 {
-  if (value == (BFD_HOST_U_64_BIT) 0x100000000)
-    value = 0;
-  else
-    value = (((BFD_HOST_64_BIT)value << 32) >> 32);
+  value = ((value & 0xffffffff) ^ 0x80000000) - 0x80000000;
 
   --value;
   return ins_imms_scaled (self, value, code, 0);
@@ -418,6 +437,7 @@ const struct ia64_operand elf64_ia64_operands[IA64_OPND_COUNT] =
   {
     /* constants: */
     { CST, ins_const, ext_const, "NIL",                {{ 0, 0}}, 0, "<none>" },
+    { CST, ins_const, ext_const, "ar.csd",     {{ 0, 0}}, 0, "ar.csd" },
     { CST, ins_const, ext_const, "ar.ccv",     {{ 0, 0}}, 0, "ar.ccv" },
     { CST, ins_const, ext_const, "ar.pfs",     {{ 0, 0}}, 0, "ar.pfs" },
     { CST, ins_const, ext_const, "1",          {{ 0, 0}}, 0, "1" },
@@ -461,6 +481,10 @@ const struct ia64_operand elf64_ia64_operands[IA64_OPND_COUNT] =
     { REG, ins_reg,   ext_reg,  "r", {{ 2, 20}}, 0,            /* R3_2 */
       "a general register r0-r3" },
 
+    /* memory operands: */
+    { IND, ins_reg,   ext_reg, "",      {{7, 20}}, 0,          /* MR3 */
+      "a memory address" },
+
     /* indirect operands: */
     { IND, ins_reg,   ext_reg, "cpuid", {{7, 20}}, 0,          /* CPUID_R3 */
       "a cpuid register" },
@@ -472,8 +496,6 @@ const struct ia64_operand elf64_ia64_operands[IA64_OPND_COUNT] =
       "an itr register" },
     { IND, ins_reg,   ext_reg, "ibr",   {{7, 20}}, 0,          /* IBR_R3 */
       "an ibr register" },
-    { IND, ins_reg,   ext_reg, "",      {{7, 20}}, 0,          /* MR3 */
-      "an indirect memory address" },
     { IND, ins_reg,   ext_reg, "msr",   {{7, 20}}, 0,          /* MSR_R3 */
       "an msr register" },
     { IND, ins_reg,   ext_reg, "pkr",   {{7, 20}}, 0,          /* PKR_R3 */
@@ -508,6 +530,8 @@ const struct ia64_operand elf64_ia64_operands[IA64_OPND_COUNT] =
       "a 1-bit integer (-1, 0)" },
     { ABS, ins_immu,  ext_immu,  0, {{ 2, 13}}, UDEC,          /* IMMU2 */
       "a 2-bit unsigned (0-3)" },
+    { ABS, ins_immu5b,  ext_immu5b,  0, {{ 5, 14}}, UDEC,      /* IMMU5b */
+      "a 5-bit unsigned (32 + (0-31))" },
     { ABS, ins_immu,  ext_immu,  0, {{ 7, 13}}, 0,             /* IMMU7a */
       "a 7-bit unsigned (0-127)" },
     { ABS, ins_immu,  ext_immu,  0, {{ 7, 20}}, 0,             /* IMMU7b */
@@ -586,4 +610,7 @@ const struct ia64_operand elf64_ia64_operands[IA64_OPND_COUNT] =
       "a branch target" },
     { REL, ins_rsvd, ext_rsvd, 0, {{0, 0}}, 0,                  /* TGT64  */
       "a branch target" },
+
+    { ABS, ins_const, ext_const, 0, {{0, 0}}, 0,               /* LDXMOV */
+      "ldxmov target" },
   };