X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fconfig%2Ftc-z8k.c;h=451cb8a1edaf434679b269ce85bc31c7d7a2257c;hb=0c0b9be0518290ff1ed6e9c7ca3fecc8ae7480bc;hp=bf83b2719560b4feb76b97ef6d693f869aaf8427;hpb=a5d2034ac06088a4c378d015b838e9eee1908fe1;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/config/tc-z8k.c b/gas/config/tc-z8k.c index bf83b27195..451cb8a1ed 100644 --- a/gas/config/tc-z8k.c +++ b/gas/config/tc-z8k.c @@ -1,5 +1,5 @@ /* tc-z8k.c -- Assemble code for the Zilog Z800n - Copyright 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001 + Copyright 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -38,34 +38,41 @@ extern int coff_flags; int segmented_mode; const int md_reloc_size; -void cons (); +/* This is non-zero if target was set from the command line. */ +static int z8k_target_from_cmdline; -void -s_segm () +static void s_segm PARAMS ((int)); +static void even PARAMS ((int)); +static int tohex PARAMS ((int)); +static void sval PARAMS ((int)); + +static void +s_segm (segm) + int segm; { + if (segm) + { segmented_mode = 1; machine = bfd_mach_z8001; coff_flags = F_Z8001; -} - -void -s_unseg () -{ + } + else + { segmented_mode = 0; machine = bfd_mach_z8002; coff_flags = F_Z8002; + } } static void -even () +even (ignore) + int ignore ATTRIBUTE_UNUSED; { frag_align (1, 0, 0); record_alignment (now_seg, 1); } -void obj_coff_section (); - -int +static int tohex (c) int c; { @@ -76,8 +83,9 @@ tohex (c) return c - 'A' + 10; } -void -sval () +static void +sval (ignore) + int ignore ATTRIBUTE_UNUSED; { SKIP_WHITESPACE (); if (*input_line_pointer == '\'') @@ -117,12 +125,12 @@ const pseudo_typeS md_pseudo_table[] = { {"import" , s_ignore , 0}, {"page" , listing_eject , 0}, {"program", s_ignore , 0}, - {"z8001" , s_segm , 0}, - {"z8002" , s_unseg , 0}, + {"z8001" , s_segm , 1}, + {"z8002" , s_segm , 0}, - {"segm" , s_segm , 0}, - {"unsegm" , s_unseg , 0}, - {"unseg" , s_unseg , 0}, + {"segm" , s_segm , 1}, + {"unsegm" , s_segm , 0}, + {"unseg" , s_segm , 0}, {"name" , s_app_file , 0}, {"global" , s_globl , 0}, {"wval" , cons , 2}, @@ -149,26 +157,22 @@ static struct hash_control *opcode_hash_control; void md_begin () { - opcode_entry_type *opcode; - char *prev_name = ""; - int idx = 0; + const opcode_entry_type *opcode; + int idx = -1; opcode_hash_control = hash_new (); for (opcode = z8k_table; opcode->name; opcode++) { /* Only enter unique codes into the table. */ - if (strcmp (opcode->name, prev_name)) - { - hash_insert (opcode_hash_control, opcode->name, (char *) opcode); - idx++; - } - opcode->idx = idx; - prev_name = opcode->name; + if (idx != opcode->idx) + hash_insert (opcode_hash_control, opcode->name, (char *) opcode); + idx = opcode->idx; } /* Default to z8002. */ - s_unseg (); + if (! z8k_target_from_cmdline) + s_segm (0); /* Insert the pseudo ops, too. */ for (idx = 0; md_pseudo_table[idx].poc_name; idx++) @@ -180,8 +184,6 @@ md_begin () fake_opcode->opcode = 250; hash_insert (opcode_hash_control, fake_opcode->name, fake_opcode); } - - linkrelax = 1; } struct z8k_exp { @@ -191,8 +193,8 @@ struct z8k_exp { }; typedef struct z8k_op { - /* 'b','w','r','q'. */ - char regsize; + /* CLASS_REG_xxx. */ + int regsize; /* 0 .. 15. */ unsigned int reg; @@ -215,7 +217,34 @@ int the_ctrl; int the_flags; int the_interrupt; -char * +static char *whatreg PARAMS ((int *, char *)); +static char *parse_reg PARAMS ((char *, int *, unsigned int *)); +static char *parse_exp PARAMS ((char *, expressionS *)); +static char *checkfor PARAMS ((char *, char)); +static void regword PARAMS ((int, char *)); +static void regaddr PARAMS ((int, char *)); +static void get_ctrl_operand + PARAMS ((char **, struct z8k_op *, unsigned int)); +static void get_flags_operand + PARAMS ((char **, struct z8k_op *, unsigned int)); +static void get_interrupt_operand + PARAMS ((char **, struct z8k_op *, unsigned int)); +static void get_cc_operand + PARAMS ((char **, struct z8k_op *, unsigned int)); +static void get_operand + PARAMS ((char **, struct z8k_op *, unsigned int)); +static char *get_operands + PARAMS ((const opcode_entry_type *, char *, op_type *)); +static opcode_entry_type *get_specific + PARAMS ((opcode_entry_type *, op_type *)); +static void newfix + PARAMS ((int, int, int, expressionS *)); +static char *apply_fix + PARAMS ((char *, int, expressionS *, int)); +static void build_bytes + PARAMS ((opcode_entry_type *, struct z8k_op *)); + +static char * whatreg (reg, src) int *reg; char *src; @@ -249,7 +278,7 @@ whatreg (reg, src) /* Try to parse a reg name. Return a pointer to the first character in SRC after the reg name. */ -char * +static char * parse_reg (src, mode, reg) char *src; int *mode; @@ -282,7 +311,9 @@ parse_reg (src, mode, reg) res = whatreg (reg, src + 2); regno = *reg; if (regno > 14) - as_warn (_("register rr%d, out of range."), regno); + as_bad (_("register rr%d out of range"), regno); + if (regno & 1) + as_bad (_("register rr%d does not exist"), regno); } else if (src[1] == 'h') { @@ -292,7 +323,7 @@ parse_reg (src, mode, reg) res = whatreg (reg, src + 2); regno = *reg; if (regno > 7) - as_warn (_("register rh%d, out of range."), regno); + as_bad (_("register rh%d out of range"), regno); } else if (src[1] == 'l') { @@ -302,7 +333,7 @@ parse_reg (src, mode, reg) res = whatreg (reg, src + 2); regno = *reg; if (regno > 7) - as_warn (_("register rl%d, out of range."), regno); + as_bad (_("register rl%d out of range"), regno); *reg += 8; } else if (src[1] == 'q') @@ -313,7 +344,9 @@ parse_reg (src, mode, reg) res = whatreg (reg, src + 2); regno = *reg; if (regno > 12) - as_warn (_("register rq%d, out of range."), regno); + as_bad (_("register rq%d out of range"), regno); + if (regno & 3) + as_bad (_("register rq%d does not exist"), regno); } else { @@ -323,13 +356,13 @@ parse_reg (src, mode, reg) res = whatreg (reg, src + 1); regno = *reg; if (regno > 15) - as_warn (_("register r%d, out of range."), regno); + as_bad (_("register r%d out of range"), regno); } } return res; } -char * +static char * parse_exp (s, op) char *s; expressionS *op; @@ -548,6 +581,8 @@ get_interrupt_operand (ptr, mode, dst) fail: ; } + /* No interrupt type specified, opcode won't do anything. */ + as_warn (_("opcode has no effect")); the_interrupt = 0x0; return; } @@ -555,7 +590,6 @@ get_interrupt_operand (ptr, mode, dst) struct cc_names { int value; char *name; - }; struct cc_names table[] = { @@ -636,10 +670,8 @@ get_operand (ptr, mode, dst) } else if (*src == '@') { - int d; - mode->mode = CLASS_IR; - src = parse_reg (src + 1, &d, &mode->reg); + src = parse_reg (src + 1, &mode->regsize, &mode->reg); } else { @@ -724,13 +756,14 @@ get_operand (ptr, mode, dst) static char * get_operands (opcode, op_end, operand) - opcode_entry_type *opcode; + const opcode_entry_type *opcode; char *op_end; op_type *operand; { char *ptr = op_end; char *savptr; + ptr++; switch (opcode->noperands) { case 0: @@ -739,40 +772,35 @@ get_operands (opcode, op_end, operand) break; case 1: - ptr++; if (opcode->arg_info[0] == CLASS_CC) - { - get_cc_operand (&ptr, operand + 0, 0); - } + get_cc_operand (&ptr, operand + 0, 0); + else if (opcode->arg_info[0] == CLASS_FLAGS) - { - get_flags_operand (&ptr, operand + 0, 0); - } + get_flags_operand (&ptr, operand + 0, 0); + else if (opcode->arg_info[0] == (CLASS_IMM + (ARG_IMM2))) - { - get_interrupt_operand (&ptr, operand + 0, 0); - } + get_interrupt_operand (&ptr, operand + 0, 0); + else - { - get_operand (&ptr, operand + 0, 0); - } + get_operand (&ptr, operand + 0, 0); + operand[1].mode = 0; break; case 2: - ptr++; savptr = ptr; if (opcode->arg_info[0] == CLASS_CC) - { - get_cc_operand (&ptr, operand + 0, 0); - } + get_cc_operand (&ptr, operand + 0, 0); + else if (opcode->arg_info[0] == CLASS_CTRL) { get_ctrl_operand (&ptr, operand + 0, 0); + if (the_ctrl == 0) { ptr = savptr; get_operand (&ptr, operand + 0, 0); + if (ptr == 0) return NULL; if (*ptr == ',') @@ -782,9 +810,8 @@ get_operands (opcode, op_end, operand) } } else - { - get_operand (&ptr, operand + 0, 0); - } + get_operand (&ptr, operand + 0, 0); + if (ptr == 0) return NULL; if (*ptr == ',') @@ -793,7 +820,6 @@ get_operands (opcode, op_end, operand) break; case 3: - ptr++; get_operand (&ptr, operand + 0, 0); if (*ptr == ',') ptr++; @@ -804,7 +830,6 @@ get_operands (opcode, op_end, operand) break; case 4: - ptr++; get_operand (&ptr, operand + 0, 0); if (*ptr == ',') ptr++; @@ -832,7 +857,6 @@ static opcode_entry_type * get_specific (opcode, operands) opcode_entry_type *opcode; op_type *operands; - { opcode_entry_type *this_try = opcode; int found = 0; @@ -849,9 +873,14 @@ get_specific (opcode, operands) { unsigned int mode = operands[i].mode; + if (((mode & CLASS_MASK) == CLASS_IR) && ((this_try->arg_info[i] & CLASS_MASK) == CLASS_IRO)) + { + mode = operands[i].mode = (operands[i].mode & ~CLASS_MASK) | CLASS_IRO; + } + if ((mode & CLASS_MASK) != (this_try->arg_info[i] & CLASS_MASK)) { - /* It could be an pc rel operand, if this is a da mode + /* It could be a pc rel operand, if this is a da mode and we like disps, then insert it. */ if (mode == CLASS_DA && this_try->arg_info[i] == CLASS_DISP) @@ -885,8 +914,18 @@ get_specific (opcode, operands) { default: break; - case CLASS_X: + case CLASS_IRO: + if (operands[i].regsize != CLASS_REG_WORD) + as_bad (_("invalid indirect register size")); + reg[this_try->arg_info[i] & ARG_MASK] = operands[i].reg; + break; case CLASS_IR: + if ((segmented_mode && operands[i].regsize != CLASS_REG_LONG) + || (!segmented_mode && operands[i].regsize != CLASS_REG_WORD)) + as_bad (_("invalid indirect register size")); + reg[this_try->arg_info[i] & ARG_MASK] = operands[i].reg; + break; + case CLASS_X: case CLASS_BA: case CLASS_BX: case CLASS_DISP: @@ -929,7 +968,7 @@ check_operand (operand, width, string) if ((operand->exp.X_add_number & ~width) != 0 && (operand->exp.X_add_number | width) != (~0)) { - as_warn (_("operand %s0x%x out of range."), + as_warn (_("operand %s0x%x out of range"), string, operand->exp.X_add_number); } } @@ -940,9 +979,10 @@ check_operand (operand, width, string) static char buffer[20]; static void -newfix (ptr, type, operand) +newfix (ptr, type, size, operand) int ptr; int type; + int size; /* nibbles. */ expressionS *operand; { if (operand->X_add_symbol @@ -951,7 +991,7 @@ newfix (ptr, type, operand) { fix_new_exp (frag_now, ptr, - 1, + size / 2, operand, 0, type); @@ -963,11 +1003,11 @@ apply_fix (ptr, type, operand, size) char *ptr; int type; expressionS *operand; - int size; + int size; /* nibbles. */ { - int n = operand->X_add_number; + long n = operand->X_add_number; - newfix ((ptr - buffer) / 2, type, operand); + newfix ((ptr - buffer) / 2, type, size + 1, operand); switch (size) { case 8: /* 8 nibbles == 32 bits. */ @@ -998,14 +1038,13 @@ build_bytes (this_try, operand) { char *output_ptr = buffer; int c; - int nib; int nibble; unsigned int *class_ptr; frag_wane (frag_now); frag_new (0); - memset (buffer, 20, 0); + memset (buffer, 0, sizeof (buffer)); class_ptr = this_try->byte_info; for (nibble = 0; (c = *class_ptr++); nibble++) @@ -1081,6 +1120,7 @@ build_bytes (this_try, operand) case CLASS_FLAGS: *output_ptr++ = the_flags; break; + case CLASS_IGNORE: case CLASS_BIT: *output_ptr++ = c & 0xf; break; @@ -1113,33 +1153,39 @@ build_bytes (this_try, operand) case CLASS_IMM: { - nib = 0; switch (c & ARG_MASK) { - case ARG_IMM4: + case ARG_NIM4: + if (imm_operand->X_add_number > 15) + { + as_bad (_("immediate value out of range")); + } + imm_operand->X_add_number = -imm_operand->X_add_number; output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1); break; + /*case ARG_IMMNMINUS1: not used. */ case ARG_IMM4M1: imm_operand->X_add_number--; - output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1); - break; - case ARG_IMMNMINUS1: - imm_operand->X_add_number--; + /* Drop through. */ + case ARG_IMM4: + if (imm_operand->X_add_number > 15) + { + as_bad (_("immediate value out of range")); + } output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1); break; case ARG_NIM8: imm_operand->X_add_number = -imm_operand->X_add_number; + /* Drop through. */ case ARG_IMM8: output_ptr = apply_fix (output_ptr, R_IMM8, imm_operand, 2); break; case ARG_IMM16: output_ptr = apply_fix (output_ptr, R_IMM16, imm_operand, 4); break; - case ARG_IMM32: output_ptr = apply_fix (output_ptr, R_IMM32, imm_operand, 8); break; - default: abort (); } @@ -1205,14 +1251,13 @@ md_assemble (str) if (opcode->opcode == 250) { - /* Was really a pseudo op. */ - pseudo_typeS *p; char oc; - char *old = input_line_pointer; *op_end = c; + /* Was really a pseudo op. */ + input_line_pointer = op_end; oc = *old; @@ -1227,8 +1272,12 @@ md_assemble (str) } else { - input_line_pointer = get_operands (opcode, op_end, operand); - prev_opcode = opcode; + char *new_input_line_pointer; + + new_input_line_pointer = get_operands (opcode, op_end, operand); + if (new_input_line_pointer) + input_line_pointer = new_input_line_pointer; + prev_opcode = opcode; /* XXX is this used ?? */ opcode = get_specific (opcode, operand); @@ -1255,6 +1304,8 @@ tc_crawl_symbol_chain (headers) printf (_("call to tc_crawl_symbol_chain \n")); } +/* We have no need to default values of symbols. */ + symbolS * md_undefined_symbol (name) char *name ATTRIBUTE_UNUSED; @@ -1288,7 +1339,6 @@ md_atof (type, litP, sizeP) LITTLENUM_TYPE words[MAX_LITTLENUMS]; LITTLENUM_TYPE *wordP; char *t; - char *atof_ieee (); switch (type) { @@ -1333,11 +1383,14 @@ md_atof (type, litP, sizeP) return 0; } -CONST char *md_shortopts = "z:"; +const char *md_shortopts = "z:"; -struct option md_longopts[] = { - {NULL, no_argument, NULL, 0} -}; +struct option md_longopts[] = + { +#define OPTION_RELAX (OPTION_MD_BASE) + {"linkrelax", no_argument, NULL, OPTION_RELAX}, + {NULL, no_argument, NULL, 0} + }; size_t md_longopts_size = sizeof (md_longopts); @@ -1350,14 +1403,19 @@ md_parse_option (c, arg) { case 'z': if (!strcmp (arg, "8001")) - s_segm (); + s_segm (1); else if (!strcmp (arg, "8002")) - s_unseg (); + s_segm (0); else { as_bad (_("invalid architecture -z%s"), arg); return 0; } + z8k_target_from_cmdline = 1; + break; + + case OPTION_RELAX: + linkrelax = 1; break; default: @@ -1372,25 +1430,19 @@ md_show_usage (stream) FILE *stream; { fprintf (stream, _("\ -Z8K options:\n\ --z8001 generate segmented code\n\ --z8002 generate unsegmented code\n")); + Z8K options:\n\ + -z8001 generate segmented code\n\ + -z8002 generate unsegmented code\n\ + -linkrelax create linker relaxable code\n")); } -void -tc_aout_fix_to_chars () -{ - printf (_("call to tc_aout_fix_to_chars \n")); - abort (); -} - void md_convert_frag (headers, seg, fragP) object_headers *headers ATTRIBUTE_UNUSED; segT seg ATTRIBUTE_UNUSED; fragS *fragP ATTRIBUTE_UNUSED; { - printf (_("call to md_convert_frag \n")); + printf (_("call to md_convert_frag\n")); abort (); } @@ -1401,53 +1453,79 @@ md_section_align (seg, size) { return ((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg])); - } void -md_apply_fix (fixP, val) - fixS *fixP; - long val; +md_apply_fix3 (fixP, valP, segment) + fixS * fixP; + valueT * valP; + segT segment ATTRIBUTE_UNUSED; { + long val = * (long *) valP; char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; switch (fixP->fx_r_type) { case R_IMM4L: - buf[0] = (buf[0] & 0xf0) | ((buf[0] + val) & 0xf); + buf[0] = (buf[0] & 0xf0) | (val & 0xf); break; case R_JR: - + val = val - fixP->fx_frag->fr_address + fixP->fx_where - fixP->fx_size; + if (val & 1) + as_bad (_("cannot branch to odd address")); + val /= 2; + if (val > 127 || val < -128) + as_bad (_("relative jump out of range")); *buf++ = val; -#if 0 - if (val != 0) - abort (); -#endif + fixP->fx_no_overflow = 1; break; case R_DISP7: + val = val - fixP->fx_frag->fr_address + fixP->fx_where - fixP->fx_size; + if (val & 1) + as_bad (_("cannot branch to odd address")); + val /= 2; + if (val > 0 || val < -128) + as_bad (_("relative jump out of range")); + *buf = (*buf & 0x80) | (val & 0x7f); + fixP->fx_no_overflow = 1; + break; - *buf++ += val; -#if 0 - if (val != 0) - abort (); -#endif + case R_CALLR: + if (val > 8191 || val < -8192) + as_bad (_("relative call out of range")); + val = -val; + *buf = (*buf & 0xf0) | ((val >> 8) & 0xf); + buf++; + *buf++ = val & 0xff; break; case R_IMM8: - buf[0] += val; + *buf++ = val; break; + case R_IMM16: *buf++ = (val >> 8); *buf++ = val; break; + case R_IMM32: *buf++ = (val >> 24); *buf++ = (val >> 16); *buf++ = (val >> 8); *buf++ = val; break; + + case R_REL16: + val = val - fixP->fx_frag->fr_address + fixP->fx_where - fixP->fx_size; + if (val > 32767 || val < -32768) + as_bad (_("relative address out of range")); + *buf++ = (val >> 8); + *buf++ = val; + fixP->fx_no_overflow = 1; + break; + #if 0 case R_DA | R_SEG: *buf++ = (val >> 16); @@ -1462,8 +1540,12 @@ md_apply_fix (fixP, val) break; default: + printf(_("md_apply_fix3: unknown r_type 0x%x\n"), fixP->fx_r_type); abort (); } + + if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) + fixP->fx_done = 1; } int @@ -1471,7 +1553,7 @@ md_estimate_size_before_relax (fragP, segment_type) register fragS *fragP ATTRIBUTE_UNUSED; register segT segment_type ATTRIBUTE_UNUSED; { - printf (_("call tomd_estimate_size_before_relax \n")); + printf (_("call to md_estimate_size_before_relax\n")); abort (); }