summaryrefslogtreecommitdiff
path: root/gas/config/tc-hppa.c
diff options
context:
space:
mode:
authorDave Anglin <dave.anglin@nrc.ca>2009-02-24 23:48:57 +0000
committerDave Anglin <dave.anglin@nrc.ca>2009-02-24 23:48:57 +0000
commit2461986c29ae6ec565aff1b5d9cbc5afd4ed6b64 (patch)
treef3584b5ae08abcd731ede6daffdb4e63aac07792 /gas/config/tc-hppa.c
parentd751b52cbbcc072cc20c295a87a2c66e086eed36 (diff)
downloadbinutils-redhat-2461986c29ae6ec565aff1b5d9cbc5afd4ed6b64.tar.gz
* gas/config/tc-hppa.c (pa_ip): Add check of immediate values.
(SAVE_IMMEDIATE): New define.
Diffstat (limited to 'gas/config/tc-hppa.c')
-rw-r--r--gas/config/tc-hppa.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c
index 7bb7966141..1393a7c581 100644
--- a/gas/config/tc-hppa.c
+++ b/gas/config/tc-hppa.c
@@ -1,6 +1,6 @@
/* tc-hppa.c -- Assemble for the PA
- Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
@@ -995,6 +995,19 @@ static struct default_space_dict pa_def_spaces[] =
#define IS_R_SELECT(S) (*(S) == 'R' || *(S) == 'r')
#define IS_L_SELECT(S) (*(S) == 'L' || *(S) == 'l')
+/* Store immediate values of shift/deposit/extract functions. */
+
+#define SAVE_IMMEDIATE(VALUE) \
+ { \
+ if (immediate_check) \
+ { \
+ if (pos == -1) \
+ pos = (VALUE); \
+ else if (len == -1) \
+ len = (VALUE); \
+ } \
+ }
+
/* Insert FIELD into OPCODE starting at bit START. Continue pa_ip
main loop after insertion. */
@@ -3191,6 +3204,7 @@ pa_ip (char *str)
int match = FALSE;
int comma = 0;
int cmpltr, nullif, flag, cond, num;
+ int immediate_check = 0, pos = -1, len = -1;
unsigned long opcode;
struct pa_opcode *insn;
@@ -3351,6 +3365,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 32, 1, 0);
+ SAVE_IMMEDIATE(num);
INSERT_FIELD_AND_CONTINUE (opcode, 32 - num, 0);
/* Handle a 5 bit immediate at 15. */
@@ -4333,6 +4348,9 @@ pa_ip (char *str)
case 'x':
case 'y':
cmpltr = 0;
+ /* Check immediate values in shift/extract/deposit
+ * instructions if they will give undefined behaviour. */
+ immediate_check = 1;
if (*s == ',')
{
save_s = s++;
@@ -5125,6 +5143,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 31, 0, strict);
+ SAVE_IMMEDIATE(num);
INSERT_FIELD_AND_CONTINUE (opcode, 31 - num, 5);
/* Handle a 6 bit shift count at 20,22:26. */
@@ -5134,6 +5153,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 63, 0, strict);
+ SAVE_IMMEDIATE(num);
num = 63 - num;
opcode |= (num & 0x20) << 6;
INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5);
@@ -5146,6 +5166,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 64, 1, strict);
+ SAVE_IMMEDIATE(num);
num--;
opcode |= (num & 0x20) << 3;
num = 31 - (num & 0x1f);
@@ -5158,6 +5179,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 64, 1, strict);
+ SAVE_IMMEDIATE(num);
num--;
opcode |= (num & 0x20) << 7;
num = 31 - (num & 0x1f);
@@ -5170,6 +5192,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 31, 0, strict);
+ SAVE_IMMEDIATE(num);
INSERT_FIELD_AND_CONTINUE (opcode, num, 5);
/* Handle a 6 bit bit position at 20,22:26. */
@@ -5179,6 +5202,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 63, 0, strict);
+ SAVE_IMMEDIATE(num);
opcode |= (num & 0x20) << 6;
INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5);
@@ -5686,6 +5710,13 @@ pa_ip (char *str)
break;
}
+ if (immediate_check)
+ {
+ if (pos != -1 && len != -1 && pos < len - 1)
+ as_warn (_("Immediates %d and %d will give undefined behavior."),
+ pos, len);
+ }
+
the_insn.opcode = opcode;
}