diff options
-rw-r--r-- | gas/ChangeLog | 16 | ||||
-rw-r--r-- | gas/config/tc-h8300.c | 239 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gas/testsuite/gas/h8300/h8sx_disp2.d | 69 | ||||
-rw-r--r-- | gas/testsuite/gas/h8300/h8sx_disp2.s | 3 |
5 files changed, 154 insertions, 177 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 2d11c7d..f039583 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,19 @@ +2003-07-07 Richard Sandiford <rsandifo@redhat.com> + + * config/tc-h8300.c (h8300sxnmode): Add prototype. + (DSYMMODE): Remove. + (parse_exp): Replace expressionS argument with a h8_op. Parse the + operand size as well. + (skip_colonthing): Remove unused expression argument. Tighten checks + for 2-digit sizes. + (colonmod24): Remove. + (get_mova_operands): Combine calls to parse_exp and skip_colonthing. + (get_operand): Likewise. Use the standard code to read the size of + pc-relative operands. + (fix_operand_size): Include the size-guessing logic that used to be + in colonmod24 and get_operand. Don't apply dd:2 optimizations to + offsets with a symbolic component. + 2003-07-04 Nick Clifton <nickc@redhat.com> * config/tc-i386.c (tc_x86_regname_to_dw2regnum): Use ARRAY_SIZE diff --git a/gas/config/tc-h8300.c b/gas/config/tc-h8300.c index 646b69e..4354b1a 100644 --- a/gas/config/tc-h8300.c +++ b/gas/config/tc-h8300.c @@ -43,14 +43,15 @@ const char comment_chars[] = ";"; const char line_comment_chars[] = "#"; const char line_separator_chars[] = ""; -void cons PARAMS ((int)); -void sbranch PARAMS ((int)); -void h8300hmode PARAMS ((int)); -void h8300smode PARAMS ((int)); -void h8300hnmode PARAMS ((int)); -void h8300snmode PARAMS ((int)); -void h8300sxmode PARAMS ((int)); -static void pint PARAMS ((int)); +void cons PARAMS ((int)); +void sbranch PARAMS ((int)); +void h8300hmode PARAMS ((int)); +void h8300smode PARAMS ((int)); +void h8300hnmode PARAMS ((int)); +void h8300snmode PARAMS ((int)); +void h8300sxmode PARAMS ((int)); +void h8300sxnmode PARAMS ((int)); +static void pint PARAMS ((int)); int Hmode; int Smode; @@ -58,7 +59,6 @@ int Nmode; int SXmode; #define PSIZE (Hmode ? L_32 : L_16) -#define DSYMMODE (Hmode ? L_24 : L_16) int bsize = L_8; /* Default branch displacement. */ @@ -339,12 +339,11 @@ static void build_bytes PARAMS ((const struct h8_instruction *, struct h8_op static void do_a_fix_imm PARAMS ((int, int, struct h8_op *, int)); static void check_operand PARAMS ((struct h8_op *, unsigned int, char *)); static const struct h8_instruction * get_specific PARAMS ((const struct h8_instruction *, struct h8_op *, int)); -static char * get_operands PARAMS ((unsigned, char *, struct h8_op *)); -static void get_operand PARAMS ((char **, struct h8_op *, int)); -static char * skip_colonthing PARAMS ((char *, expressionS *, int *)); -static char * parse_exp PARAMS ((char *, expressionS *)); -static int parse_reg PARAMS ((char *, op_type *, unsigned *, int)); -char * colonmod24 PARAMS ((struct h8_op *, char *)); +static char *get_operands PARAMS ((unsigned, char *, struct h8_op *)); +static void get_operand PARAMS ((char **, struct h8_op *, int)); +static int parse_reg PARAMS ((char *, op_type *, unsigned *, int)); +static char *skip_colonthing PARAMS ((char *, int *)); +static char *parse_exp PARAMS ((char *, struct h8_op *)); static int constant_fits_width_p PARAMS ((struct h8_op *, unsigned int)); static int constant_fits_size_p PARAMS ((struct h8_op *, int, int)); @@ -474,56 +473,65 @@ parse_reg (src, mode, reg, direction) return 0; } + +/* Parse an immediate or address-related constant and store it in OP. + If the user also specifies the operand's size, store that size + in OP->MODE, otherwise leave it for later code to decide. */ + static char * -parse_exp (s, op) - char *s; - expressionS *op; +parse_exp (src, op) + char *src; + struct h8_op *op; { - char *save = input_line_pointer; - char *new; + char *save; - input_line_pointer = s; - expression (op); - if (op->X_op == O_absent) + save = input_line_pointer; + input_line_pointer = src; + expression (&op->exp); + if (op->exp.X_op == O_absent) as_bad (_("missing operand")); - new = input_line_pointer; + src = input_line_pointer; input_line_pointer = save; - return new; + + return skip_colonthing (src, &op->mode); } + +/* If SRC starts with an explicit operand size, skip it and store the size + in *MODE. Leave *MODE unchanged otherwise. */ + static char * -skip_colonthing (ptr, exp, mode) - char *ptr; - expressionS *exp ATTRIBUTE_UNUSED; +skip_colonthing (src, mode) + char *src; int *mode; { - if (*ptr == ':') + if (*src == ':') { - ptr++; + src++; *mode &= ~SIZE; - if (ptr[0] == '8' && ! ISDIGIT (ptr[1])) + if (src[0] == '8' && !ISDIGIT (src[1])) *mode |= L_8; - else if (ptr[0] == '2' && ! ISDIGIT (ptr[1])) + else if (src[0] == '2' && !ISDIGIT (src[1])) *mode |= L_2; - else if (ptr[0] == '3' && ! ISDIGIT (ptr[1])) + else if (src[0] == '3' && !ISDIGIT (src[1])) *mode |= L_3; - else if (ptr[0] == '4' && ! ISDIGIT (ptr[1])) + else if (src[0] == '4' && !ISDIGIT (src[1])) *mode |= L_4; - else if (ptr[0] == '5' && ! ISDIGIT (ptr[1])) + else if (src[0] == '5' && !ISDIGIT (src[1])) *mode |= L_5; - else if (ptr[0] == '2' && ptr[1] == '4') + else if (src[0] == '2' && src[1] == '4' && !ISDIGIT (src[2])) *mode |= L_24; - else if (ptr[0] == '3' && ptr[1] == '2') + else if (src[0] == '3' && src[1] == '2' && !ISDIGIT (src[2])) *mode |= L_32; - else if (ptr[0] == '1' && ptr[1] == '6') + else if (src[0] == '1' && src[1] == '6' && !ISDIGIT (src[2])) *mode |= L_16; else as_bad (_("invalid operand size requested")); - while (ISDIGIT (*ptr)) - ptr++; + while (ISDIGIT (*src)) + src++; } - return ptr; + return src; } /* The many forms of operand: @@ -541,35 +549,6 @@ skip_colonthing (ptr, exp, mode) @(exp:[8], pc) pc rel @@aa[:8] memory indirect. */ -char * -colonmod24 (op, src) - struct h8_op *op; - char *src; -{ - int mode = 0; - src = skip_colonthing (src, &op->exp, &mode); - - if (!mode) - { - /* If the operand is a 16-bit constant integer, leave fix_operand_size - to calculate its size. Otherwise choose a default here. */ - if (op->exp.X_add_number < -32768 - || op->exp.X_add_number > 32767) - { - if (Hmode) - mode = L_24; - else - mode = L_16; - } - else if (op->exp.X_add_symbol - || op->exp.X_op_symbol) - mode = DSYMMODE; - } - - op->mode |= mode; - return src; -} - static int constant_fits_width_p (operand, width) struct h8_op *operand; @@ -707,13 +686,7 @@ get_operand (ptr, op, direction) src++; if (*src == '@') { - src++; - src = parse_exp (src, &op->exp); - - src = skip_colonthing (src, &op->exp, &op->mode); - - *ptr = src; - + *ptr = parse_exp (src + 1, op); if (op->exp.X_add_number >= 0x100) { int divisor; @@ -731,32 +704,26 @@ get_operand (ptr, op, direction) } else op->mode = MEMIND; - return; } if (*src == '-' || *src == '+') { - char c = *src; - src++; - len = parse_reg (src, &mode, &num, direction); + len = parse_reg (src + 1, &mode, &num, direction); if (len == 0) { /* Oops, not a reg after all, must be ordinary exp. */ - src--; - /* Must be a symbol. */ - op->mode = ABS | PSIZE | direction; - *ptr = skip_colonthing (parse_exp (src, &op->exp), - &op->exp, &op->mode); - + op->mode = ABS | direction; + *ptr = parse_exp (src, op); return; } if ((mode & SIZE) != PSIZE) as_bad (_("Wrong size pointer register for architecture.")); - op->mode = c == '-' ? RDPREDEC : RDPREINC; + + op->mode = src[0] == '-' ? RDPREDEC : RDPREINC; op->reg = num; - *ptr = src + len; + *ptr = src + 1 + len; return; } if (*src == '(') @@ -801,15 +768,11 @@ get_operand (ptr, op, direction) /* Start off assuming a 16 bit offset. */ - src = parse_exp (src, &op->exp); - - src = colonmod24 (op, src); - + src = parse_exp (src, op); if (*src == ')') { - src++; op->mode |= ABS | direction; - *ptr = src; + *ptr = src + 1; return; } @@ -817,7 +780,6 @@ get_operand (ptr, op, direction) { as_bad (_("expected @(exp, reg16)")); return; - } src++; @@ -849,7 +811,7 @@ get_operand (ptr, op, direction) } else op->mode |= DISP | direction; - src = skip_colonthing (src, &op->exp, &op->mode); + src = skip_colonthing (src, &op->mode); if (*src != ')' && '(') { @@ -857,7 +819,6 @@ get_operand (ptr, op, direction) return; } *ptr = src + 1; - return; } len = parse_reg (src, &mode, &num, direction); @@ -889,21 +850,15 @@ get_operand (ptr, op, direction) /* must be a symbol */ op->mode = ABS | direction; - src = parse_exp (src, &op->exp); - - *ptr = colonmod24 (op, src); - + *ptr = parse_exp (src, op); return; } } if (*src == '#') { - src++; op->mode = IMM; - src = parse_exp (src, &op->exp); - *ptr = skip_colonthing (src, &op->exp, &op->mode); - + *ptr = parse_exp (src + 1, op); return; } else if (strncmp (src, "mach", 4) == 0 || @@ -918,35 +873,8 @@ get_operand (ptr, op, direction) } else { - src = parse_exp (src, &op->exp); - /* Trailing ':' size ? */ - if (*src == ':') - { - if (src[1] == '1' && src[2] == '6') - { - op->mode = PCREL | L_16; - src += 3; - } - else if (src[1] == '8') - { - op->mode = PCREL | L_8; - src += 2; - } - else - as_bad (_("expect :8 or :16 here")); - } - else - { - int val = op->exp.X_add_number; - - op->mode = PCREL; - if (-128 < val && val < 127) - op->mode |= L_8; - else - op->mode |= L_16; - } - - *ptr = src; + op->mode = PCREL; + *ptr = parse_exp (src, op); } } @@ -1010,8 +938,7 @@ get_mova_operands (char *op_end, struct h8_op *operand) goto error; ptr += 3; operand[0].mode = 0; - ptr = parse_exp (ptr, &operand[0].exp); - ptr = colonmod24 (operand + 0, ptr); + ptr = parse_exp (ptr, &operand[0]); if (*ptr !=',') goto error; @@ -1880,11 +1807,11 @@ clever_message (instruction, operand) } -/* Adjust OPERAND's value and size given that it is accessing a field - of SIZE bytes. +/* If OPERAND is part of an address, adjust its size and value given + that it addresses SIZE bytes. - This function handles the choice between @(d:2,ERn) and @(d:16,ERn) - when no size is explicitly given. It also scales down the assembly-level + This function decides how big non-immediate constants are when no + size was explicitly given. It also scales down the assembly-level displacement in an @(d:2,ERn) operand. */ static void @@ -1892,12 +1819,13 @@ fix_operand_size (operand, size) struct h8_op *operand; int size; { - if ((operand->mode & MODE) == DISP) + if (SXmode && (operand->mode & MODE) == DISP) { /* If the user didn't specify an operand width, see if we can use @(d:2,ERn). */ - if (SXmode - && (operand->mode & SIZE) == 0 + if ((operand->mode & SIZE) == 0 + && operand->exp.X_add_symbol == 0 + && operand->exp.X_op_symbol == 0 && (operand->exp.X_add_number == size || operand->exp.X_add_number == size * 2 || operand->exp.X_add_number == size * 3)) @@ -1913,8 +1841,6 @@ fix_operand_size (operand, size) } } - /* If the operand needs a size but doesn't have one yet, it must be - a 16-bit integer (see colonmod24). */ if ((operand->mode & SIZE) == 0) switch (operand->mode & MODE) { @@ -1923,7 +1849,26 @@ fix_operand_size (operand, size) case INDEXW: case INDEXL: case ABS: - operand->mode |= L_16; + /* Pick a 24-bit address unless we know that a 16-bit address + is safe. get_specific() will relax L_24 into L_32 where + necessary. */ + if (Hmode + && (operand->exp.X_add_number < -32768 + || operand->exp.X_add_number > 32767 + || operand->exp.X_add_symbol != 0 + || operand->exp.X_op_symbol != 0)) + operand->mode |= L_24; + else + operand->mode |= L_16; + break; + + case PCREL: + /* This condition is long standing, though somewhat suspect. */ + if (operand->exp.X_add_number > -128 + && operand->exp.X_add_number < 127) + operand->mode |= L_8; + else + operand->mode |= L_16; break; } } diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 5a878a5..2083d32 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-07-07 Richard Sandiford <rsandifo@redhat.com> + + * gas/h8300/h8sx_disp2.[sd]: Add tests for symbolic displacements. + 2003-07-04 Alan Modra <amodra@bigpond.net.au> * gas/ppc/test2elf64.s: Rename to.. diff --git a/gas/testsuite/gas/h8300/h8sx_disp2.d b/gas/testsuite/gas/h8300/h8sx_disp2.d index b1def76..a3c712c 100644 --- a/gas/testsuite/gas/h8300/h8sx_disp2.d +++ b/gas/testsuite/gas/h8300/h8sx_disp2.d @@ -5,33 +5,42 @@ Disassembly of section \.text: 0+00 <\.text>: - * 0: 01 75 68 08 * 01 75 68 08 80 02 add.b #0x2,@\(0x1:2,r0\) - * 4: 80 02 * - * 6: 01 76 68 08 * 01 76 68 08 80 02 add.b #0x2,@\(0x2:2,r0\) - * a: 80 02 * - * c: 01 77 68 08 * 01 77 68 08 80 02 add.b #0x2,@\(0x3:2,r0\) - *10: 80 02 * - *12: 01 74 6e 08 * 01 74 6e 08 00 04 80 02 add.b #0x2,@\(0x4:16,r0\) - *16: 00 04 80 02 * - *1a: 01 5e c0 10 * 01 5e c0 10 00 01 00 02 add.w #0x2,@\(0x1:16,r0\) - *1e: 00 01 00 02 * - *22: 01 5e 10 10 * 01 5e 10 10 00 02 add.w #0x2,@\(0x2:2,r0\) - *26: 00 02 * - *28: 01 5e 20 10 * 01 5e 20 10 00 02 add.w #0x2,@\(0x4:2,r0\) - *2c: 00 02 * - *2e: 01 5e 30 10 * 01 5e 30 10 00 02 add.w #0x2,@\(0x6:2,r0\) - *32: 00 02 * - *34: 01 5e c0 10 * 01 5e c0 10 00 08 00 02 add.w #0x2,@\(0x8:16,r0\) - *38: 00 08 00 02 * - *3c: 01 0e c0 10 * 01 0e c0 10 00 01 00 02 add.l #0x2,@\(0x1:16,r0\) - *40: 00 01 00 02 * - *44: 01 0e c0 10 * 01 0e c0 10 00 02 00 02 add.l #0x2,@\(0x2:16,r0\) - *48: 00 02 00 02 * - *4c: 01 0e 10 10 * 01 0e 10 10 00 02 add.l #0x2,@\(0x4:2,r0\) - *50: 00 02 * - *52: 01 0e 20 10 * 01 0e 20 10 00 02 add.l #0x2,@\(0x8:2,r0\) - *56: 00 02 * - *58: 01 0e 30 10 * 01 0e 30 10 00 02 add.l #0x2,@\(0xc:2,r0\) - *5c: 00 02 * - *5e: 01 0e c0 10 * 01 0e c0 10 00 10 00 02 add.l #0x2,@\(0x10:16,r0\) - *62: 00 10 00 02 * + .*: 01 75 68 08 * 01 75 68 08 80 02 add.b #0x2,@\(0x1:2,r0\) + .*: 80 02 * + .*: 01 76 68 08 * 01 76 68 08 80 02 add.b #0x2,@\(0x2:2,r0\) + .*: 80 02 * + .*: 01 77 68 08 * 01 77 68 08 80 02 add.b #0x2,@\(0x3:2,r0\) + .*: 80 02 * + .*: 01 74 6e 08 * 01 74 6e 08 00 04 80 02 add.b #0x2,@\(0x4:16,r0\) + .*: 00 04 80 02 * + .*: 78 04 6a 28 * 78 04 6a 28 00 00 00 00 80 02 add.b #0x2,@\(0x0:32,r0\) + .*: 00 00 00 00 * + .*: 80 02 * + .*: 01 5e c0 10 * 01 5e c0 10 00 01 00 02 add.w #0x2,@\(0x1:16,r0\) + .*: 00 01 00 02 * + .*: 01 5e 10 10 * 01 5e 10 10 00 02 add.w #0x2,@\(0x2:2,r0\) + .*: 00 02 * + .*: 01 5e 20 10 * 01 5e 20 10 00 02 add.w #0x2,@\(0x4:2,r0\) + .*: 00 02 * + .*: 01 5e 30 10 * 01 5e 30 10 00 02 add.w #0x2,@\(0x6:2,r0\) + .*: 00 02 * + .*: 01 5e c0 10 * 01 5e c0 10 00 08 00 02 add.w #0x2,@\(0x8:16,r0\) + .*: 00 08 00 02 * + .*: 01 5e c8 10 * 01 5e c8 10 00 00 00 00 00 02 add.w #0x2,@\(0x0:32,r0\) + .*: 00 00 00 00 * + .*: 00 02 * + .*: 01 0e c0 10 * 01 0e c0 10 00 01 00 02 add.l #0x2,@\(0x1:16,r0\) + .*: 00 01 00 02 * + .*: 01 0e c0 10 * 01 0e c0 10 00 02 00 02 add.l #0x2,@\(0x2:16,r0\) + .*: 00 02 00 02 * + .*: 01 0e 10 10 * 01 0e 10 10 00 02 add.l #0x2,@\(0x4:2,r0\) + .*: 00 02 * + .*: 01 0e 20 10 * 01 0e 20 10 00 02 add.l #0x2,@\(0x8:2,r0\) + .*: 00 02 * + .*: 01 0e 30 10 * 01 0e 30 10 00 02 add.l #0x2,@\(0xc:2,r0\) + .*: 00 02 * + .*: 01 0e c0 10 * 01 0e c0 10 00 10 00 02 add.l #0x2,@\(0x10:16,r0\) + .*: 00 10 00 02 * + .*: 01 0e c8 10 * 01 0e c8 10 00 00 00 00 00 02 add.l #0x2,@\(0x0:32,r0\) + .*: 00 00 00 00 * + .*: 00 02 * diff --git a/gas/testsuite/gas/h8300/h8sx_disp2.s b/gas/testsuite/gas/h8300/h8sx_disp2.s index f3d8393..5f6b37d 100644 --- a/gas/testsuite/gas/h8300/h8sx_disp2.s +++ b/gas/testsuite/gas/h8300/h8sx_disp2.s @@ -3,12 +3,14 @@ add.b #2,@(2,er0) ; L_2 add.b #2,@(3,er0) ; L_2 add.b #2,@(4,er0) ; L_16 + add.b #2,@(foo+1,er0) ; L_32 add.w #2,@(1,er0) ; L_16 add.w #2,@(2,er0) ; L_2 add.w #2,@(4,er0) ; L_2 add.w #2,@(6,er0) ; L_2 add.w #2,@(8,er0) ; L_16 + add.w #2,@(foo+2,er0) ; L_32 add.l #2,@(1,er0) ; L_16 add.l #2,@(2,er0) ; L_16 @@ -16,3 +18,4 @@ add.l #2,@(8,er0) ; L_2 add.l #2,@(12,er0) ; L_2 add.l #2,@(16,er0) ; L_16 + add.l #2,@(foo+4,er0) ; L_32 |