* 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

View File

@ -1,5 +1,5 @@
/* 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.
This file is part of GAS, the GNU Assembler.
@ -38,28 +38,30 @@ extern int coff_flags;
int segmented_mode;
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_unseg PARAMS ((int));
static void even PARAMS ((int));
static int tohex PARAMS ((int));
static void sval PARAMS ((int));
static void
s_segm (ignore)
int ignore ATTRIBUTE_UNUSED;
s_segm (segm)
int segm;
{
if (segm)
{
segmented_mode = 1;
machine = bfd_mach_z8001;
coff_flags = F_Z8001;
}
static void
s_unseg (ignore)
int ignore ATTRIBUTE_UNUSED;
{
}
else
{
segmented_mode = 0;
machine = bfd_mach_z8002;
coff_flags = F_Z8002;
}
}
static void
@ -123,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},
@ -169,7 +171,8 @@ md_begin ()
}
/* Default to z8002. */
s_unseg (0);
if (! z8k_target_from_cmdline)
s_segm (0);
/* Insert the pseudo ops, too. */
for (idx = 0; md_pseudo_table[idx].poc_name; idx++)
@ -181,8 +184,6 @@ md_begin ()
fake_opcode->opcode = 250;
hash_insert (opcode_hash_control, fake_opcode->name, fake_opcode);
}
linkrelax = 1;
}
struct z8k_exp {
@ -237,7 +238,7 @@ static char *get_operands
static opcode_entry_type *get_specific
PARAMS ((opcode_entry_type *, op_type *));
static void newfix
PARAMS ((int, int, expressionS *));
PARAMS ((int, int, int, expressionS *));
static char *apply_fix
PARAMS ((char *, int, expressionS *, int));
static void build_bytes
@ -576,6 +577,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;
}
@ -583,7 +586,6 @@ get_interrupt_operand (ptr, mode, dst)
struct cc_names {
int value;
char *name;
};
struct cc_names table[] = {
@ -960,9 +962,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
@ -971,7 +974,7 @@ newfix (ptr, type, operand)
{
fix_new_exp (frag_now,
ptr,
1,
size / 2,
operand,
0,
type);
@ -983,11 +986,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. */
@ -1018,7 +1021,6 @@ build_bytes (this_try, operand)
{
char *output_ptr = buffer;
int c;
int nib;
int nibble;
unsigned int *class_ptr;
@ -1134,36 +1136,39 @@ build_bytes (this_try, operand)
case CLASS_IMM:
{
nib = 0;
switch (c & ARG_MASK)
{
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;
/* Drop through. */
case ARG_IMM4:
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 ();
}
@ -1255,7 +1260,7 @@ md_assemble (str)
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;
prev_opcode = opcode; /* XXX is this used ?? */
opcode = get_specific (opcode, operand);
@ -1282,6 +1287,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;
@ -1363,6 +1370,8 @@ const char *md_shortopts = "z:";
struct option md_longopts[] =
{
#define OPTION_RELAX (OPTION_MD_BASE)
{"linkrelax", no_argument, NULL, OPTION_RELAX},
{NULL, no_argument, NULL, 0}
};
@ -1377,14 +1386,19 @@ md_parse_option (c, arg)
{
case 'z':
if (!strcmp (arg, "8001"))
s_segm (0);
s_segm (1);
else if (!strcmp (arg, "8002"))
s_unseg (0);
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:
@ -1399,9 +1413,10 @@ 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
@ -1410,7 +1425,7 @@ md_convert_frag (headers, seg, fragP)
segT seg ATTRIBUTE_UNUSED;
fragS *fragP ATTRIBUTE_UNUSED;
{
printf (_("call to md_convert_frag \n"));
printf (_("call to md_convert_frag\n"));
abort ();
}
@ -1435,40 +1450,64 @@ md_apply_fix3 (fixP, valP, segment)
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[0] & 0xf0) | ((val >> 8) & 0xf);
*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);
@ -1483,6 +1522,7 @@ md_apply_fix3 (fixP, valP, segment)
break;
default:
printf(_("md_apply_fix3: unknown r_type 0x%x\n"), fixP->fx_r_type);
abort ();
}
@ -1495,7 +1535,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 ();
}

View File

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

View File

@ -68,23 +68,23 @@ typedef enum {
O_multiply,
/* (X_add_symbol / X_op_symbol) + X_add_number. */
O_divide,
/* X_add_symbol % X_op_symbol) + X_add_number. */
/* (X_add_symbol % X_op_symbol) + X_add_number. */
O_modulus,
/* X_add_symbol << X_op_symbol) + X_add_number. */
/* (X_add_symbol << X_op_symbol) + X_add_number. */
O_left_shift,
/* X_add_symbol >> X_op_symbol) + X_add_number. */
/* (X_add_symbol >> X_op_symbol) + X_add_number. */
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,
/* X_add_symbol |~ X_op_symbol) + X_add_number. */
/* (X_add_symbol |~ X_op_symbol) + X_add_number. */
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,
/* X_add_symbol & X_op_symbol) + X_add_number. */
/* (X_add_symbol & X_op_symbol) + X_add_number. */
O_bit_and,
/* X_add_symbol + X_op_symbol) + X_add_number. */
/* (X_add_symbol + X_op_symbol) + X_add_number. */
O_add,
/* X_add_symbol - X_op_symbol) + X_add_number. */
/* (X_add_symbol - X_op_symbol) + X_add_number. */
O_subtract,
/* (X_add_symbol == X_op_symbol) + X_add_number. */
O_eq,

View File

@ -209,11 +209,13 @@ z8k_lookup_instr (nibbles, info)
int nibl_index, tabl_index;
int nibl_matched;
int need_fetch = 0;
unsigned short instr_nibl;
unsigned short tabl_datum, datum_class, datum_value;
nibl_matched = 0;
tabl_index = 0;
FETCH_DATA (info, 4);
while (!nibl_matched && z8k_table[tabl_index].name)
{
nibl_matched = 1;
@ -222,8 +224,15 @@ z8k_lookup_instr (nibbles, info)
nibl_index++)
{
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];
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);
instr_long = (instr_data->words[nibl_count] << 16)
| (instr_data->words[nibl_count + 4]);
instr_data->address = ((instr_word & 0x7f00) << 8)
instr_data->address = ((instr_word & 0x7f00) << 16)
+ (instr_long & 0xffff);
nibl_count += 7;
seg_length = 2;
}
else
{
instr_data->address = ((instr_word & 0x7f00) << 8)
instr_data->address = ((instr_word & 0x7f00) << 16)
+ (instr_word & 0x00ff);
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
unparse_instr (instr_data, is_segmented)
instr_data_s *instr_data;
@ -536,6 +552,12 @@ unparse_instr (instr_data, is_segmented)
strcat (out_str, tmp_str);
break;
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);
strcat (out_str, tmp_str);
break;