This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[Patch - hppa] add compile time check for immediate values of shift/deposit/extract functions
- From: Helge Deller <deller at gmx dot de>
- To: binutils at sourceware dot org, Dave Anglin <dave dot anglin at nrc dot ca>, Alan Modra <amodra at bigpond dot net dot au>
- Date: Sun, 22 Feb 2009 18:22:44 +0100
- Subject: [Patch - hppa] add compile time check for immediate values of shift/deposit/extract functions
On the parisc linux port I faces some time back the problem
that we generated an assembly statement like this one:
extrw,u r8,9,11,r5
which has undefined runtime behavior since the length value (11)
extends beyond the leftmost bit (9): (11-1 > 9)
Interestingly my PA2.0 processor didn't seemed to care and just
zero-extend the value at runtime, while my PA1.1 processors didn't
and just filled in random values into %r5 which led to crashes.
The patch below adds compile time checks to gas which (where possible)
will check the constant immediate values of the shift/deposit/extract
functions and warn the user if he coded a dangerous combination.
Compiling the testsuite by hand produces the expected additional warnings:
[deller@halden gas]$ ./as-new /mnt/sda6/home/cvs/LINUX/binutils/gas/testsuite/gas/hppa/basic/deposit.s
/mnt/sda6/home/cvs/LINUX/binutils/gas/testsuite/gas/hppa/basic/deposit.s: Assembler messages:
/mnt/sda6/home/cvs/LINUX/binutils/gas/testsuite/gas/hppa/basic/deposit.s:8: Warning: Immediates 5 and 10 will give undefined behavior.
/mnt/sda6/home/cvs/LINUX/binutils/gas/testsuite/gas/hppa/basic/deposit.s:9: Warning: Immediates 5 and 10 will give undefined behavior.
(and so on)
2009-02-22 Helge Deller <deller@gmx.de>
* gas/config/tc-hppa.c: Add check of immediate values.
Index: gas/config/tc-hppa.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-hppa.c,v
retrieving revision 1.142
diff -u -p -r1.142 tc-hppa.c
--- gas/config/tc-hppa.c 9 Sep 2008 00:53:35 -0000 1.142
+++ gas/config/tc-hppa.c 22 Feb 2009 17:15:32 -0000
@@ -995,6 +995,16 @@ static struct default_space_dict pa_def_
#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 INSERT_IMMEDIATE(VALUE) \
+ { \
+ if (immediate_check) \
+ { if (sv1 == -1) sv1 = VALUE; \
+ else if (sv2 == -1) sv2 = VALUE; \
+ } \
+ }
+
/* Insert FIELD into OPCODE starting at bit START. Continue pa_ip
main loop after insertion. */
@@ -3191,6 +3201,7 @@ pa_ip (char *str)
int match = FALSE;
int comma = 0;
int cmpltr, nullif, flag, cond, num;
+ int immediate_check = 0, sv1 = -1, sv2 = -1;
unsigned long opcode;
struct pa_opcode *insn;
@@ -3351,6 +3362,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 32, 1, 0);
+ INSERT_IMMEDIATE(num);
INSERT_FIELD_AND_CONTINUE (opcode, 32 - num, 0);
/* Handle a 5 bit immediate at 15. */
@@ -4333,6 +4345,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 +5140,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 31, 0, strict);
+ INSERT_IMMEDIATE(num);
INSERT_FIELD_AND_CONTINUE (opcode, 31 - num, 5);
/* Handle a 6 bit shift count at 20,22:26. */
@@ -5134,6 +5150,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 63, 0, strict);
+ INSERT_IMMEDIATE(num);
num = 63 - num;
opcode |= (num & 0x20) << 6;
INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5);
@@ -5146,6 +5163,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 64, 1, strict);
+ INSERT_IMMEDIATE(num);
num--;
opcode |= (num & 0x20) << 3;
num = 31 - (num & 0x1f);
@@ -5158,6 +5176,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 64, 1, strict);
+ INSERT_IMMEDIATE(num);
num--;
opcode |= (num & 0x20) << 7;
num = 31 - (num & 0x1f);
@@ -5170,6 +5189,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 31, 0, strict);
+ INSERT_IMMEDIATE(num);
INSERT_FIELD_AND_CONTINUE (opcode, num, 5);
/* Handle a 6 bit bit position at 20,22:26. */
@@ -5179,6 +5199,7 @@ pa_ip (char *str)
break;
s = expr_end;
CHECK_FIELD (num, 63, 0, strict);
+ INSERT_IMMEDIATE(num);
opcode |= (num & 0x20) << 6;
INSERT_FIELD_AND_CONTINUE (opcode, num & 0x1f, 5);
@@ -5686,6 +5707,12 @@ pa_ip (char *str)
break;
}
+ if (immediate_check) {
+ if (sv1 != -1 && sv2 != -1 && (sv2-1) > sv1)
+ as_warn (_("Immediates %d and %d will give undefined behavior."),
+ sv1, sv2);
+ }
+
the_insn.opcode = opcode;
}