diff options
Diffstat (limited to 'gas/config/tc-hppa.c')
-rw-r--r-- | gas/config/tc-hppa.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c index 7bb7966..1393a7c 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; } |