* expr.h: Fix comments in operatorT typedef.

* config/tc-z8k.c: Add 2003 to copyright message.
	Fold s_segm() and s_unseg() into one function s_segm(parm) which
	decides by the parameter.
	(md_begin): Don't set linkrelax.  Only set Z8002 default if no
	command line argument was given to select the intended
	architecure.
	(get_interrupt_operand): Warn if NOP type code is emitted.
	(newfix): New parameter 'size', forward it to 'fix_new_exp'.
	(apply_fix): Call newfix with additional 'size' parameter.
	(build_bytes): Remove unused variable 'nib'.  Detect overflow in
	4 bit immediate arguments.
	(md_longopts): Add 'linkrelax' option.
	(md_parse_option): Adapt to new s_segm function.  Set 'linkrelax'
	variable when 'linkrelax' command line option is specified.
	(md_show_usage): Display 'linkrelax' option.
	(md_apply_fix3): Fix cases R_IMM4L, R_JR, and R_IMM8.  Add cases
	R_CALLR and R_REL16.
	* config/tc-z8k.h: Undef WARN_SIGNED_OVERFLOW_WORD.
This commit is contained in:
Christian Groessler
2003-05-01 19:59:33 +00:00
parent 6ae2f58071
commit 7f31df7cab
4 changed files with 131 additions and 68 deletions

@ -1,5 +1,5 @@
/* tc-z8k.c -- Assemble code for the Zilog Z800n /* tc-z8k.c -- Assemble code for the Zilog Z800n
Copyright 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001, 2002 Copyright 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001, 2002, 2003
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler. This file is part of GAS, the GNU Assembler.
@ -38,28 +38,30 @@ extern int coff_flags;
int segmented_mode; int segmented_mode;
const int md_reloc_size; const int md_reloc_size;
/* This is non-zero if target was set from the command line. */
static int z8k_target_from_cmdline;
static void s_segm PARAMS ((int)); static void s_segm PARAMS ((int));
static void s_unseg PARAMS ((int));
static void even PARAMS ((int)); static void even PARAMS ((int));
static int tohex PARAMS ((int)); static int tohex PARAMS ((int));
static void sval PARAMS ((int)); static void sval PARAMS ((int));
static void static void
s_segm (ignore) s_segm (segm)
int ignore ATTRIBUTE_UNUSED; int segm;
{ {
if (segm)
{
segmented_mode = 1; segmented_mode = 1;
machine = bfd_mach_z8001; machine = bfd_mach_z8001;
coff_flags = F_Z8001; coff_flags = F_Z8001;
} }
else
static void {
s_unseg (ignore)
int ignore ATTRIBUTE_UNUSED;
{
segmented_mode = 0; segmented_mode = 0;
machine = bfd_mach_z8002; machine = bfd_mach_z8002;
coff_flags = F_Z8002; coff_flags = F_Z8002;
}
} }
static void static void
@ -123,12 +125,12 @@ const pseudo_typeS md_pseudo_table[] = {
{"import" , s_ignore , 0}, {"import" , s_ignore , 0},
{"page" , listing_eject , 0}, {"page" , listing_eject , 0},
{"program", s_ignore , 0}, {"program", s_ignore , 0},
{"z8001" , s_segm , 0}, {"z8001" , s_segm , 1},
{"z8002" , s_unseg , 0}, {"z8002" , s_segm , 0},
{"segm" , s_segm , 0}, {"segm" , s_segm , 1},
{"unsegm" , s_unseg , 0}, {"unsegm" , s_segm , 0},
{"unseg" , s_unseg , 0}, {"unseg" , s_segm , 0},
{"name" , s_app_file , 0}, {"name" , s_app_file , 0},
{"global" , s_globl , 0}, {"global" , s_globl , 0},
{"wval" , cons , 2}, {"wval" , cons , 2},
@ -169,7 +171,8 @@ md_begin ()
} }
/* Default to z8002. */ /* Default to z8002. */
s_unseg (0); if (! z8k_target_from_cmdline)
s_segm (0);
/* Insert the pseudo ops, too. */ /* Insert the pseudo ops, too. */
for (idx = 0; md_pseudo_table[idx].poc_name; idx++) for (idx = 0; md_pseudo_table[idx].poc_name; idx++)
@ -181,8 +184,6 @@ md_begin ()
fake_opcode->opcode = 250; fake_opcode->opcode = 250;
hash_insert (opcode_hash_control, fake_opcode->name, fake_opcode); hash_insert (opcode_hash_control, fake_opcode->name, fake_opcode);
} }
linkrelax = 1;
} }
struct z8k_exp { struct z8k_exp {
@ -237,7 +238,7 @@ static char *get_operands
static opcode_entry_type *get_specific static opcode_entry_type *get_specific
PARAMS ((opcode_entry_type *, op_type *)); PARAMS ((opcode_entry_type *, op_type *));
static void newfix static void newfix
PARAMS ((int, int, expressionS *)); PARAMS ((int, int, int, expressionS *));
static char *apply_fix static char *apply_fix
PARAMS ((char *, int, expressionS *, int)); PARAMS ((char *, int, expressionS *, int));
static void build_bytes static void build_bytes
@ -576,6 +577,8 @@ get_interrupt_operand (ptr, mode, dst)
fail: fail:
; ;
} }
/* No interrupt type specified, opcode won't do anything. */
as_warn (_("opcode has no effect."));
the_interrupt = 0x0; the_interrupt = 0x0;
return; return;
} }
@ -583,7 +586,6 @@ get_interrupt_operand (ptr, mode, dst)
struct cc_names { struct cc_names {
int value; int value;
char *name; char *name;
}; };
struct cc_names table[] = { struct cc_names table[] = {
@ -960,9 +962,10 @@ check_operand (operand, width, string)
static char buffer[20]; static char buffer[20];
static void static void
newfix (ptr, type, operand) newfix (ptr, type, size, operand)
int ptr; int ptr;
int type; int type;
int size; /* nibbles. */
expressionS *operand; expressionS *operand;
{ {
if (operand->X_add_symbol if (operand->X_add_symbol
@ -971,7 +974,7 @@ newfix (ptr, type, operand)
{ {
fix_new_exp (frag_now, fix_new_exp (frag_now,
ptr, ptr,
1, size / 2,
operand, operand,
0, 0,
type); type);
@ -983,11 +986,11 @@ apply_fix (ptr, type, operand, size)
char *ptr; char *ptr;
int type; int type;
expressionS *operand; 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) switch (size)
{ {
case 8: /* 8 nibbles == 32 bits. */ case 8: /* 8 nibbles == 32 bits. */
@ -1018,7 +1021,6 @@ build_bytes (this_try, operand)
{ {
char *output_ptr = buffer; char *output_ptr = buffer;
int c; int c;
int nib;
int nibble; int nibble;
unsigned int *class_ptr; unsigned int *class_ptr;
@ -1134,36 +1136,39 @@ build_bytes (this_try, operand)
case CLASS_IMM: case CLASS_IMM:
{ {
nib = 0;
switch (c & ARG_MASK) switch (c & ARG_MASK)
{ {
case ARG_NIM4: 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; imm_operand->X_add_number = -imm_operand->X_add_number;
/* Drop through. */
case ARG_IMM4:
output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1); output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1);
break; break;
/*case ARG_IMMNMINUS1: not used. */
case ARG_IMM4M1: case ARG_IMM4M1:
imm_operand->X_add_number--; imm_operand->X_add_number--;
output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1); /* Drop through. */
break; case ARG_IMM4:
case ARG_IMMNMINUS1: if (imm_operand->X_add_number > 15)
imm_operand->X_add_number--; {
as_bad (_("immediate value out of range"));
}
output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1); output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1);
break; break;
case ARG_NIM8: case ARG_NIM8:
imm_operand->X_add_number = -imm_operand->X_add_number; imm_operand->X_add_number = -imm_operand->X_add_number;
/* Drop through. */
case ARG_IMM8: case ARG_IMM8:
output_ptr = apply_fix (output_ptr, R_IMM8, imm_operand, 2); output_ptr = apply_fix (output_ptr, R_IMM8, imm_operand, 2);
break; break;
case ARG_IMM16: case ARG_IMM16:
output_ptr = apply_fix (output_ptr, R_IMM16, imm_operand, 4); output_ptr = apply_fix (output_ptr, R_IMM16, imm_operand, 4);
break; break;
case ARG_IMM32: case ARG_IMM32:
output_ptr = apply_fix (output_ptr, R_IMM32, imm_operand, 8); output_ptr = apply_fix (output_ptr, R_IMM32, imm_operand, 8);
break; break;
default: default:
abort (); abort ();
} }
@ -1255,7 +1260,7 @@ md_assemble (str)
new_input_line_pointer = get_operands (opcode, op_end, operand); new_input_line_pointer = get_operands (opcode, op_end, operand);
if (new_input_line_pointer) if (new_input_line_pointer)
input_line_pointer = new_input_line_pointer; input_line_pointer = new_input_line_pointer;
prev_opcode = opcode; prev_opcode = opcode; /* XXX is this used ?? */
opcode = get_specific (opcode, operand); opcode = get_specific (opcode, operand);
@ -1282,6 +1287,8 @@ tc_crawl_symbol_chain (headers)
printf (_("call to tc_crawl_symbol_chain \n")); printf (_("call to tc_crawl_symbol_chain \n"));
} }
/* We have no need to default values of symbols. */
symbolS * symbolS *
md_undefined_symbol (name) md_undefined_symbol (name)
char *name ATTRIBUTE_UNUSED; char *name ATTRIBUTE_UNUSED;
@ -1363,6 +1370,8 @@ const char *md_shortopts = "z:";
struct option md_longopts[] = struct option md_longopts[] =
{ {
#define OPTION_RELAX (OPTION_MD_BASE)
{"linkrelax", no_argument, NULL, OPTION_RELAX},
{NULL, no_argument, NULL, 0} {NULL, no_argument, NULL, 0}
}; };
@ -1377,14 +1386,19 @@ md_parse_option (c, arg)
{ {
case 'z': case 'z':
if (!strcmp (arg, "8001")) if (!strcmp (arg, "8001"))
s_segm (0); s_segm (1);
else if (!strcmp (arg, "8002")) else if (!strcmp (arg, "8002"))
s_unseg (0); s_segm (0);
else else
{ {
as_bad (_("invalid architecture -z%s"), arg); as_bad (_("invalid architecture -z%s"), arg);
return 0; return 0;
} }
z8k_target_from_cmdline = 1;
break;
case OPTION_RELAX:
linkrelax = 1;
break; break;
default: default:
@ -1399,9 +1413,10 @@ md_show_usage (stream)
FILE *stream; FILE *stream;
{ {
fprintf (stream, _("\ fprintf (stream, _("\
Z8K options:\n\ Z8K options:\n\
-z8001 generate segmented code\n\ -z8001 generate segmented code\n\
-z8002 generate unsegmented code\n")); -z8002 generate unsegmented code\n\
-linkrelax create linker relaxable code\n"));
} }
void void
@ -1410,7 +1425,7 @@ md_convert_frag (headers, seg, fragP)
segT seg ATTRIBUTE_UNUSED; segT seg ATTRIBUTE_UNUSED;
fragS *fragP ATTRIBUTE_UNUSED; fragS *fragP ATTRIBUTE_UNUSED;
{ {
printf (_("call to md_convert_frag \n")); printf (_("call to md_convert_frag\n"));
abort (); abort ();
} }
@ -1435,40 +1450,64 @@ md_apply_fix3 (fixP, valP, segment)
switch (fixP->fx_r_type) switch (fixP->fx_r_type)
{ {
case R_IMM4L: case R_IMM4L:
buf[0] = (buf[0] & 0xf0) | ((buf[0] + val) & 0xf); buf[0] = (buf[0] & 0xf0) | (val & 0xf);
break; break;
case R_JR: 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; *buf++ = val;
#if 0 fixP->fx_no_overflow = 1;
if (val != 0)
abort ();
#endif
break; break;
case R_DISP7: 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; case R_CALLR:
#if 0 if (val > 8191 || val < -8192)
if (val != 0) as_bad (_("relative call out of range"));
abort (); val = -val;
#endif *buf++ = (buf[0] & 0xf0) | ((val >> 8) & 0xf);
*buf++ = val & 0xff;
break; break;
case R_IMM8: case R_IMM8:
buf[0] += val; *buf++ = val;
break; break;
case R_IMM16: case R_IMM16:
*buf++ = (val >> 8); *buf++ = (val >> 8);
*buf++ = val; *buf++ = val;
break; break;
case R_IMM32: case R_IMM32:
*buf++ = (val >> 24); *buf++ = (val >> 24);
*buf++ = (val >> 16); *buf++ = (val >> 16);
*buf++ = (val >> 8); *buf++ = (val >> 8);
*buf++ = val; *buf++ = val;
break; 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 #if 0
case R_DA | R_SEG: case R_DA | R_SEG:
*buf++ = (val >> 16); *buf++ = (val >> 16);
@ -1483,6 +1522,7 @@ md_apply_fix3 (fixP, valP, segment)
break; break;
default: default:
printf(_("md_apply_fix3: unknown r_type 0x%x\n"), fixP->fx_r_type);
abort (); abort ();
} }
@ -1495,7 +1535,7 @@ md_estimate_size_before_relax (fragP, segment_type)
register fragS *fragP ATTRIBUTE_UNUSED; register fragS *fragP ATTRIBUTE_UNUSED;
register segT segment_type 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 (); abort ();
} }

@ -40,6 +40,7 @@ struct internal_reloc;
#define COFF_MAGIC 0x8000 #define COFF_MAGIC 0x8000
#define TC_COUNT_RELOC(x) (1) #define TC_COUNT_RELOC(x) (1)
#define IGNORE_NONSTANDARD_ESCAPES #define IGNORE_NONSTANDARD_ESCAPES
#undef WARN_SIGNED_OVERFLOW_WORD
#define TC_RELOC_MANGLE(s,a,b,c) tc_reloc_mangle(a,b,c) #define TC_RELOC_MANGLE(s,a,b,c) tc_reloc_mangle(a,b,c)
extern void tc_reloc_mangle extern void tc_reloc_mangle

@ -68,23 +68,23 @@ typedef enum {
O_multiply, O_multiply,
/* (X_add_symbol / X_op_symbol) + X_add_number. */ /* (X_add_symbol / X_op_symbol) + X_add_number. */
O_divide, O_divide,
/* X_add_symbol % X_op_symbol) + X_add_number. */ /* (X_add_symbol % X_op_symbol) + X_add_number. */
O_modulus, O_modulus,
/* X_add_symbol << X_op_symbol) + X_add_number. */ /* (X_add_symbol << X_op_symbol) + X_add_number. */
O_left_shift, O_left_shift,
/* X_add_symbol >> X_op_symbol) + X_add_number. */ /* (X_add_symbol >> X_op_symbol) + X_add_number. */
O_right_shift, O_right_shift,
/* X_add_symbol | X_op_symbol) + X_add_number. */ /* (X_add_symbol | X_op_symbol) + X_add_number. */
O_bit_inclusive_or, O_bit_inclusive_or,
/* X_add_symbol |~ X_op_symbol) + X_add_number. */ /* (X_add_symbol |~ X_op_symbol) + X_add_number. */
O_bit_or_not, O_bit_or_not,
/* X_add_symbol ^ X_op_symbol) + X_add_number. */ /* (X_add_symbol ^ X_op_symbol) + X_add_number. */
O_bit_exclusive_or, O_bit_exclusive_or,
/* X_add_symbol & X_op_symbol) + X_add_number. */ /* (X_add_symbol & X_op_symbol) + X_add_number. */
O_bit_and, O_bit_and,
/* X_add_symbol + X_op_symbol) + X_add_number. */ /* (X_add_symbol + X_op_symbol) + X_add_number. */
O_add, O_add,
/* X_add_symbol - X_op_symbol) + X_add_number. */ /* (X_add_symbol - X_op_symbol) + X_add_number. */
O_subtract, O_subtract,
/* (X_add_symbol == X_op_symbol) + X_add_number. */ /* (X_add_symbol == X_op_symbol) + X_add_number. */
O_eq, O_eq,

@ -209,11 +209,13 @@ z8k_lookup_instr (nibbles, info)
int nibl_index, tabl_index; int nibl_index, tabl_index;
int nibl_matched; int nibl_matched;
int need_fetch = 0;
unsigned short instr_nibl; unsigned short instr_nibl;
unsigned short tabl_datum, datum_class, datum_value; unsigned short tabl_datum, datum_class, datum_value;
nibl_matched = 0; nibl_matched = 0;
tabl_index = 0; tabl_index = 0;
FETCH_DATA (info, 4);
while (!nibl_matched && z8k_table[tabl_index].name) while (!nibl_matched && z8k_table[tabl_index].name)
{ {
nibl_matched = 1; nibl_matched = 1;
@ -222,8 +224,15 @@ z8k_lookup_instr (nibbles, info)
nibl_index++) nibl_index++)
{ {
if ((nibl_index % 4) == 0) if ((nibl_index % 4) == 0)
/* Fetch one word at a time. */ {
FETCH_DATA (info, nibl_index + 4); /* Fetch data only if it isn't already there. */
if (nibl_index >= 4 || (nibl_index < 4 && need_fetch))
FETCH_DATA (info, nibl_index + 4); /* Fetch one word at a time. */
if (nibl_index < 4)
need_fetch = 0;
else
need_fetch = 1;
}
instr_nibl = nibbles[nibl_index]; instr_nibl = nibbles[nibl_index];
tabl_datum = z8k_table[tabl_index].byte_info[nibl_index]; tabl_datum = z8k_table[tabl_index].byte_info[nibl_index];
@ -414,14 +423,14 @@ unpack_instr (instr_data, is_segmented, info)
FETCH_DATA (info, nibl_count + 8); FETCH_DATA (info, nibl_count + 8);
instr_long = (instr_data->words[nibl_count] << 16) instr_long = (instr_data->words[nibl_count] << 16)
| (instr_data->words[nibl_count + 4]); | (instr_data->words[nibl_count + 4]);
instr_data->address = ((instr_word & 0x7f00) << 8) instr_data->address = ((instr_word & 0x7f00) << 16)
+ (instr_long & 0xffff); + (instr_long & 0xffff);
nibl_count += 7; nibl_count += 7;
seg_length = 2; seg_length = 2;
} }
else else
{ {
instr_data->address = ((instr_word & 0x7f00) << 8) instr_data->address = ((instr_word & 0x7f00) << 16)
+ (instr_word & 0x00ff); + (instr_word & 0x00ff);
nibl_count += 3; nibl_count += 3;
} }
@ -484,6 +493,13 @@ unpack_instr (instr_data, is_segmented, info)
} }
} }
static char *intr_names[] = {
"all", /* 0 */
"vi", /* 1 */
"nvi", /* 2 */
"none" /* 3 */
};
static void static void
unparse_instr (instr_data, is_segmented) unparse_instr (instr_data, is_segmented)
instr_data_s *instr_data; instr_data_s *instr_data;
@ -536,6 +552,12 @@ unparse_instr (instr_data, is_segmented)
strcat (out_str, tmp_str); strcat (out_str, tmp_str);
break; break;
case CLASS_IMM: case CLASS_IMM:
if (datum_value == ARG_IMM2) /* True with EI/DI instructions only. */
{
sprintf (tmp_str, "%s", intr_names[instr_data->interrupts]);
strcat (out_str, tmp_str);
break;
}
sprintf (tmp_str, "#0x%0lx", instr_data->immediate); sprintf (tmp_str, "#0x%0lx", instr_data->immediate);
strcat (out_str, tmp_str); strcat (out_str, tmp_str);
break; break;