start-sanitize-d10v

Mon Jul 22 11:32:36 1996  Martin M. Hunt  <hunt@pizza.cygnus.com>

	* config/tc-d10v.c: Many changes to get relocs working.
 	(register_name): No longer creates a symbol for register names.
 	(pre_defined_registers): moved to opcodes/d10v-opc.c.
	(d10v_insert_operand): Now works correctly for either container.
	* config/tc-d10v.h (d10v_cleanup): Declare.

end-sanitize-d10v
This commit is contained in:
Martin Hunt
1996-07-22 18:55:27 +00:00
parent d82a4ac0aa
commit 0ef325594a
3 changed files with 187 additions and 157 deletions

View File

@ -1,3 +1,13 @@
start-sanitize-d10v
Mon Jul 22 11:32:36 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
* config/tc-d10v.c: Many changes to get relocs working.
(register_name): No longer creates a symbol for register names.
(pre_defined_registers): moved to opcodes/d10v-opc.c.
(d10v_insert_operand): Now works correctly for either container.
* config/tc-d10v.h (d10v_cleanup): Declare.
end-sanitize-d10v
Mon Jul 22 14:01:33 1996 Ian Lance Taylor <ian@cygnus.com> Mon Jul 22 14:01:33 1996 Ian Lance Taylor <ian@cygnus.com>
* config/tc-mips.c (tc_gen_reloc): BFD_RELOC_PCREL_HI16_S and * config/tc-mips.c (tc_gen_reloc): BFD_RELOC_PCREL_HI16_S and

View File

@ -33,29 +33,40 @@ const char *md_shortopts = "";
const char EXP_CHARS[] = "eE"; const char EXP_CHARS[] = "eE";
const char FLT_CHARS[] = "dD"; const char FLT_CHARS[] = "dD";
/* local functions */
static int reg_name_search PARAMS ((char *name));
static void register_name PARAMS ((expressionS *expressionP));
static int postfix PARAMS ((char *p));
static bfd_reloc_code_real_type get_reloc PARAMS ((struct d10v_operand *op));
static int get_operands PARAMS ((expressionS exp[]));
static unsigned long build_insn PARAMS ((struct d10v_opcode *opcode, expressionS *opers));
static void write_long PARAMS ((struct d10v_opcode *opcode, unsigned long insn));
static void write_1_short PARAMS ((struct d10v_opcode *opcode, unsigned long insn));
static int write_2_short PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1,
struct d10v_opcode *opcode2, unsigned long insn2, int exec_type));
static unsigned long do_assemble PARAMS ((char *str, struct d10v_opcode **opcode));
/* fixups */ /* fixups */
#define MAX_INSN_FIXUPS (5) #define MAX_INSN_FIXUPS (5)
struct d10v_fixup struct d10v_fixup
{ {
expressionS exp; expressionS exp;
int opindex;
bfd_reloc_code_real_type reloc; bfd_reloc_code_real_type reloc;
}; };
struct d10v_fixup fixups[MAX_INSN_FIXUPS];
static int fc; typedef struct _fixups
{
int fc;
struct d10v_fixup fix[MAX_INSN_FIXUPS];
struct _fixups *next;
} Fixups;
static Fixups FixUps[2];
static Fixups *fixups;
/* local functions */
static int reg_name_search PARAMS ((char *name));
static int register_name PARAMS ((expressionS *expressionP));
static int postfix PARAMS ((char *p));
static bfd_reloc_code_real_type get_reloc PARAMS ((struct d10v_operand *op));
static int get_operands PARAMS ((expressionS exp[]));
static unsigned long build_insn PARAMS ((struct d10v_opcode *opcode, expressionS *opers));
static void write_long PARAMS ((struct d10v_opcode *opcode, unsigned long insn, Fixups *fx));
static void write_1_short PARAMS ((struct d10v_opcode *opcode, unsigned long insn, Fixups *fx));
static int write_2_short PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1,
struct d10v_opcode *opcode2, unsigned long insn2, int exec_type, Fixups *fx));
static unsigned long do_assemble PARAMS ((char *str, struct d10v_opcode **opcode));
static unsigned long d10v_insert_operand PARAMS (( unsigned long insn, int op_type,
offsetT value, int left));
struct option md_longopts[] = { struct option md_longopts[] = {
{NULL, no_argument, NULL, 0} {NULL, no_argument, NULL, 0}
@ -65,71 +76,12 @@ size_t md_longopts_size = sizeof(md_longopts);
/* The target specific pseudo-ops which we support. */ /* The target specific pseudo-ops which we support. */
const pseudo_typeS md_pseudo_table[] = const pseudo_typeS md_pseudo_table[] =
{ {
/*
{ "byte", ppc_byte, 0 },
{ "long", ppc_elf_cons, 4 },
{ "word", ppc_elf_cons, 2 },
{ "short", ppc_elf_cons, 2 },
{ "rdata", ppc_elf_rdata, 0 },
{ "rodata", ppc_elf_rdata, 0 },
{ "lcomm", ppc_elf_lcomm, 0 },
*/
{ NULL, NULL, 0 } { NULL, NULL, 0 }
}; };
/* Opcode hash table. */ /* Opcode hash table. */
static struct hash_control *d10v_hash; static struct hash_control *d10v_hash;
/* Structure to hold information about predefined registers. */
struct pd_reg
{
char *name;
int value;
};
/* an expressionS only has one register type, so we fake it */
/* by setting high bits to indicate type */
#define REGISTER_MASK 0xFF
/* The table is sorted. Suitable for searching by a binary search. */
static const struct pd_reg pre_defined_registers[] =
{
{ "a0", OPERAND_ACC+0 },
{ "a1", OPERAND_ACC+1 },
{ "bpc", OPERAND_CONTROL+3 },
{ "bpsw", OPERAND_CONTROL+1 },
{ "c", OPERAND_FLAG+3 },
{ "f0", OPERAND_FLAG+0 },
{ "f1", OPERAND_FLAG+1 },
{ "iba", OPERAND_CONTROL+14 },
{ "mod_e", OPERAND_CONTROL+11 },
{ "mod_s", OPERAND_CONTROL+10 },
{ "pc", OPERAND_CONTROL+2 },
{ "psw", OPERAND_CONTROL+0 },
{ "r0", 0 },
{ "r1", 1 },
{ "r10", 10 },
{ "r11", 11 },
{ "r12", 12 },
{ "r13", 13 },
{ "r14", 14 },
{ "r15", 15 },
{ "r2", 2 },
{ "r3", 3 },
{ "r4", 4 },
{ "r5", 5 },
{ "r6", 6 },
{ "r7", 7 },
{ "r8", 8 },
{ "r9", 9 },
{ "rpt_c", OPERAND_CONTROL+7 },
{ "rpt_e", OPERAND_CONTROL+9 },
{ "rpt_s", OPERAND_CONTROL+8 },
{ "sp", 15 },
};
#define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct pd_reg))
/* reg_name_search does a binary search of the pre_defined_registers /* reg_name_search does a binary search of the pre_defined_registers
array to see if "name" is a valid regiter name. Returns the register array to see if "name" is a valid regiter name. Returns the register
number from the array on success, or -1 on failure. */ number from the array on success, or -1 on failure. */
@ -142,7 +94,7 @@ reg_name_search (name)
int cmp; int cmp;
low = 0; low = 0;
high = REG_NAME_CNT - 1; high = reg_name_cnt() - 1;
do do
{ {
@ -159,30 +111,37 @@ reg_name_search (name)
return -1; return -1;
} }
/* register_name() checks the string at input_line_pointer
to see if it is a valid register name */
/* register_name check to see if an expression is a valid static int
register name. If it is, it marks the expression type
as O_register. */
static void
register_name (expressionP) register_name (expressionP)
expressionS *expressionP; expressionS *expressionP;
{ {
int reg_number; int reg_number;
char *name; char c, *p = input_line_pointer;
if (expressionP->X_op == O_symbol) while (*p && *p!='\n' && *p!='\r' && *p !=',' && *p!=' ' && *p!=')')
{ p++;
name = (char *)S_GET_NAME (expressionP->X_add_symbol);
reg_number = reg_name_search (name); c = *p;
if (c)
*p++ = 0;
/* look to see if it's in the register table */ /* look to see if it's in the register table */
reg_number = reg_name_search (input_line_pointer);
if (reg_number >= 0) if (reg_number >= 0)
{ {
expressionP->X_op = O_register; expressionP->X_op = O_register;
/* temporarily store a pointer to the string here */
expressionP->X_op_symbol = (struct symbol *)input_line_pointer;
expressionP->X_add_number = reg_number; expressionP->X_add_number = reg_number;
input_line_pointer = p;
return 1;
} }
} if (c)
*(p-1) = c;
return 0;
} }
void void
@ -223,7 +182,7 @@ md_convert_frag (abfd, sec, fragP)
asection *sec; asection *sec;
fragS *fragP; fragS *fragP;
{ {
/* printf ("call to md_convert_frag \n"); */ printf ("call to md_convert_frag \n");
abort (); abort ();
} }
@ -236,6 +195,7 @@ md_section_align (seg, addr)
return ((addr + (1 << align) - 1) & (-1 << align)); return ((addr + (1 << align) - 1) & (-1 << align));
} }
void void
md_begin () md_begin ()
{ {
@ -256,6 +216,10 @@ md_begin ()
hash_insert (d10v_hash, opcode->name, (char *) opcode); hash_insert (d10v_hash, opcode->name, (char *) opcode);
} }
} }
fixups = &FixUps[0];
FixUps[0].next = &FixUps[1];
FixUps[1].next = &FixUps[0];
} }
@ -357,10 +321,14 @@ get_operands (exp)
} }
input_line_pointer = p; input_line_pointer = p;
/* create an expression */
expression (&exp[numops]);
/* check to see if it might be a register name */ /* check to see if it might be a register name */
register_name (&exp[numops]); if (!register_name (&exp[numops]))
{
/* parse as an expression */
expression (&exp[numops]);
}
if (exp[numops].X_op == O_illegal) if (exp[numops].X_op == O_illegal)
as_bad ("illegal operand"); as_bad ("illegal operand");
@ -388,14 +356,18 @@ get_operands (exp)
} }
static unsigned long static unsigned long
d10v_insert_operand (insn, op_type, value) d10v_insert_operand (insn, op_type, value, left)
unsigned long insn; unsigned long insn;
int op_type; int op_type;
offsetT value; offsetT value;
int left;
{ {
int shift, bits; int shift, bits;
shift = d10v_operands[op_type].shift; shift = d10v_operands[op_type].shift;
if (left)
shift += 15;
bits = d10v_operands[op_type].bits; bits = d10v_operands[op_type].bits;
/* truncate to the proper number of bits */ /* truncate to the proper number of bits */
/* FIXME: overflow checking here? */ /* FIXME: overflow checking here? */
@ -443,14 +415,14 @@ build_insn (opcode, opers)
printf("\n"); printf("\n");
*/ */
if (fc >= MAX_INSN_FIXUPS) if (fixups->fc >= MAX_INSN_FIXUPS)
as_fatal ("too many fixups"); as_fatal ("too many fixups");
fixups[fc].exp = opers[i]; fixups->fix[fixups->fc].exp = opers[i];
/* put the operand number here for now. We can look up /* put the operand number here for now. We can look up
the reloc type and/or fixup the instruction in md_apply_fix() */ the reloc type and/or fixup the instruction in md_apply_fix() */
fixups[fc].reloc = opcode->operands[i]; fixups->fix[fixups->fc].reloc = opcode->operands[i];
fc++; (fixups->fc)++;
} }
/* truncate to the proper number of bits */ /* truncate to the proper number of bits */
@ -463,9 +435,10 @@ build_insn (opcode, opers)
/* write out a long form instruction */ /* write out a long form instruction */
static void static void
write_long (opcode, insn) write_long (opcode, insn, fx)
struct d10v_opcode *opcode; struct d10v_opcode *opcode;
unsigned long insn; unsigned long insn;
Fixups *fx;
{ {
int i; int i;
char *f = frag_more(4); char *f = frag_more(4);
@ -474,31 +447,34 @@ write_long (opcode, insn)
/* printf("INSN: %08x\n",insn); */ /* printf("INSN: %08x\n",insn); */
number_to_chars_bigendian (f, insn, 4); number_to_chars_bigendian (f, insn, 4);
for (i=0; i<fc; i++) for (i=0; i < fx->fc; i++)
{ {
if (get_reloc((struct d10v_operand *)&d10v_operands[fixups[i].reloc])) if (get_reloc((struct d10v_operand *)&d10v_operands[fx->fix[i].reloc]))
{ {
/* /*
printf("fix_new_exp: where:%x size:4\n ",f - frag_now->fr_literal); printf("fix_new_exp: where:%x size:4\n ",f - frag_now->fr_literal);
print_expr_1(stdout,&fixups[i].exp); print_expr_1(stdout,&(fx->fix[i].exp));
printf("\n"); printf("\n");
*/ */
fix_new_exp (frag_now, fix_new_exp (frag_now,
f - frag_now->fr_literal, f - frag_now->fr_literal,
4, 4,
&fixups[i].exp, &(fx->fix[i].exp),
1, 1,
fixups[i].reloc); fx->fix[i].reloc);
} }
} }
fx->fc = 0;
} }
/* write out a short form instruction by itself */ /* write out a short form instruction by itself */
static void static void
write_1_short (opcode, insn) write_1_short (opcode, insn, fx)
struct d10v_opcode *opcode; struct d10v_opcode *opcode;
unsigned long insn; unsigned long insn;
Fixups *fx;
{ {
char *f = frag_more(4); char *f = frag_more(4);
int i; int i;
@ -506,41 +482,45 @@ write_1_short (opcode, insn)
insn |= FM00 | (NOP << 15); insn |= FM00 | (NOP << 15);
/* printf("INSN: %08x\n",insn); */ /* printf("INSN: %08x\n",insn); */
number_to_chars_bigendian (f, insn, 4); number_to_chars_bigendian (f, insn, 4);
for (i=0; i<fc; i++) for (i=0; i < fx->fc; i++)
{ {
if (get_reloc((struct d10v_operand *)&d10v_operands[fixups[i].reloc])) if (get_reloc((struct d10v_operand *)&d10v_operands[fx->fix[i].reloc]))
{ {
/* /*
printf("fix_new_exp: where:%x size:4\n ",f - frag_now->fr_literal); printf("fix_new_exp: where:%x size:4\n ",f - frag_now->fr_literal);
print_expr_1(stdout,&fixups[i].exp); print_expr_1(stdout,&(fx->fix[i].exp));
printf("\n"); printf("\n");
*/ */
fix_new_exp (frag_now, fix_new_exp (frag_now,
f - frag_now->fr_literal, f - frag_now->fr_literal,
4, 4,
&fixups[i].exp, &(fx->fix[i].exp),
1, 1,
fixups[i].reloc); fx->fix[i].reloc);
} }
} }
fx->fc = 0;
} }
/* write out a short form instruction if possible */ /* write out a short form instruction if possible */
/* return number of instructions not written out */ /* return number of instructions not written out */
static int static int
write_2_short (opcode1, insn1, opcode2, insn2, exec_type) write_2_short (opcode1, insn1, opcode2, insn2, exec_type, fx)
struct d10v_opcode *opcode1, *opcode2; struct d10v_opcode *opcode1, *opcode2;
unsigned long insn1, insn2; unsigned long insn1, insn2;
int exec_type; int exec_type;
Fixups *fx;
{ {
unsigned long insn; unsigned long insn;
char *f;
int i,j;
if(opcode1->exec_type == BRANCH_LINK) if(opcode1->exec_type == BRANCH_LINK)
{ {
/* subroutines must be called from 32-bit boundaries */ /* subroutines must be called from 32-bit boundaries */
/* so the return address will be correct */ /* so the return address will be correct */
write_1_short (opcode1, insn1); write_1_short (opcode1, insn1, fx->next);
return (1); return (1);
} }
@ -549,18 +529,22 @@ write_2_short (opcode1, insn1, opcode2, insn2, exec_type)
case 0: case 0:
if (opcode1->unit == IU) if (opcode1->unit == IU)
{ {
/* reverse sequential */
insn = FM10 | (insn2 << 15) | insn1; insn = FM10 | (insn2 << 15) | insn1;
} }
else else
{ {
insn = FM01 | (insn1 << 15) | insn2; insn = FM01 | (insn1 << 15) | insn2;
fx = fx->next;
} }
break; break;
case 1: /* parallel */ case 1: /* parallel */
insn = FM00 | (insn1 << 15) | insn2; insn = FM00 | (insn1 << 15) | insn2;
fx = fx->next;
break; break;
case 2: /* sequential */ case 2: /* sequential */
insn = FM01 | (insn1 << 15) | insn2; insn = FM01 | (insn1 << 15) | insn2;
fx = fx->next;
break; break;
case 3: /* reverse sequential */ case 3: /* reverse sequential */
insn = FM10 | (insn1 << 15) | insn2; insn = FM10 | (insn1 << 15) | insn2;
@ -570,7 +554,37 @@ write_2_short (opcode1, insn1, opcode2, insn2, exec_type)
} }
/* printf("INSN: %08x\n",insn); */ /* printf("INSN: %08x\n",insn); */
number_to_chars_bigendian (frag_more(4), insn, 4); f = frag_more(4);
number_to_chars_bigendian (f, insn, 4);
for (j=0; j<2; j++)
{
bfd_reloc_code_real_type reloc;
for (i=0; i < fx->fc; i++)
{
reloc = get_reloc((struct d10v_operand *)&d10v_operands[fx->fix[i].reloc]);
if (reloc)
{
if ( (reloc == BFD_RELOC_D10V_10_PCREL_R) && (j == 0) )
fx->fix[i].reloc |= 1024;
/*
printf("fix_new_exp: where:%x reloc:%d\n ",f - frag_now->fr_literal,fx->fix[i].reloc);
print_expr_1(stdout,&(fx->fix[i].exp));
printf("\n");
*/
fix_new_exp (frag_now,
f - frag_now->fr_literal,
4,
&(fx->fix[i].exp),
1,
fx->fix[i].reloc);
}
}
fx->fc = 0;
fx = fx->next;
}
return (0); return (0);
} }
@ -583,6 +597,8 @@ write_2_short (opcode1, insn1, opcode2, insn2, exec_type)
static unsigned long prev_insn; static unsigned long prev_insn;
static struct d10v_opcode *prev_opcode = 0; static struct d10v_opcode *prev_opcode = 0;
static subsegT prev_subseg;
static segT prev_seg;
void void
md_assemble (str) md_assemble (str)
@ -594,7 +610,6 @@ md_assemble (str)
char *str2; char *str2;
/* printf("md_assemble: str=%s\n",str); */ /* printf("md_assemble: str=%s\n",str); */
fc = 0;
/* look for the special multiple instruction seperators */ /* look for the special multiple instruction seperators */
str2 = strstr (str, "||"); str2 = strstr (str, "||");
@ -622,10 +637,11 @@ md_assemble (str)
/* if two instructions are present and we already have one saved /* if two instructions are present and we already have one saved
then first write it out */ then first write it out */
if (prev_opcode) if (prev_opcode)
write_1_short (prev_opcode, prev_insn); write_1_short (prev_opcode, prev_insn, fixups->next);
/* assemble first instruction and save it */ /* assemble first instruction and save it */
prev_insn = do_assemble (str, &prev_opcode); prev_insn = do_assemble (str, &prev_opcode);
fixups = fixups->next;
str = str2 + 2; str = str2 + 2;
} }
@ -638,15 +654,15 @@ md_assemble (str)
as_fatal("Unable to mix instructions as specified"); as_fatal("Unable to mix instructions as specified");
if (prev_opcode) if (prev_opcode)
{ {
write_1_short (prev_opcode, prev_insn); write_1_short (prev_opcode, prev_insn, fixups->next);
prev_opcode = NULL; prev_opcode = NULL;
} }
write_long (opcode, insn); write_long (opcode, insn, fixups);
prev_opcode = NULL; prev_opcode = NULL;
return; return;
} }
if (prev_opcode && (write_2_short (prev_opcode, prev_insn, opcode, insn, t) == 0)) if (prev_opcode && (write_2_short (prev_opcode, prev_insn, opcode, insn, t, fixups) == 0))
{ {
/* no instructions saved */ /* no instructions saved */
prev_opcode = NULL; prev_opcode = NULL;
@ -658,6 +674,9 @@ md_assemble (str)
/* save off last instruction so it may be packed on next pass */ /* save off last instruction so it may be packed on next pass */
prev_opcode = opcode; prev_opcode = opcode;
prev_insn = insn; prev_insn = insn;
prev_seg = now_seg;
prev_subseg = now_subseg;
fixups = fixups->next;
} }
} }
@ -780,7 +799,9 @@ do_assemble (str, opcode)
if (!(d10v_operands[(*opcode)->operands[i]].flags & OPERAND_REG)) if (!(d10v_operands[(*opcode)->operands[i]].flags & OPERAND_REG))
{ {
myops[i].X_op = O_symbol; myops[i].X_op = O_symbol;
myops[i].X_add_symbol = symbol_find_or_make ((char *)myops[i].X_op_symbol);
myops[i].X_add_number = 0; myops[i].X_add_number = 0;
myops[i].X_op_symbol = NULL;
/* FIXME create a fixup */ /* FIXME create a fixup */
} }
} }
@ -849,6 +870,7 @@ md_apply_fix3 (fixp, valuep, seg)
char *where; char *where;
unsigned long insn; unsigned long insn;
int op_type; int op_type;
int left=0;
if (fixp->fx_addsy == (symbolS *) NULL) if (fixp->fx_addsy == (symbolS *) NULL)
{ {
@ -876,17 +898,22 @@ md_apply_fix3 (fixp, valuep, seg)
/* printf("md_apply_fix: value=0x%x type=%d\n", value, fixp->fx_r_type); */ /* printf("md_apply_fix: value=0x%x type=%d\n", value, fixp->fx_r_type); */
op_type = fixp->fx_r_type; op_type = fixp->fx_r_type;
if (op_type & 1024)
{
op_type -= 1024;
fixp->fx_r_type = BFD_RELOC_D10V_10_PCREL_L;
left = 1;
}
else
fixp->fx_r_type = get_reloc((struct d10v_operand *)&d10v_operands[op_type]); fixp->fx_r_type = get_reloc((struct d10v_operand *)&d10v_operands[op_type]);
/* printf("reloc=%d\n",fixp->fx_r_type); */
/* Fetch the instruction, insert the fully resolved operand /* Fetch the instruction, insert the fully resolved operand
value, and stuff the instruction back again. */ value, and stuff the instruction back again. */
where = fixp->fx_frag->fr_literal + fixp->fx_where; where = fixp->fx_frag->fr_literal + fixp->fx_where;
insn = bfd_getb32 ((unsigned char *) where); insn = bfd_getb32 ((unsigned char *) where);
/* printf(" insn=%x value=%x\n",insn,value); */ /* printf(" insn=%x value=%x\n",insn,value); */
insn = d10v_insert_operand (insn, op_type, (offsetT) value); insn = d10v_insert_operand (insn, op_type, (offsetT) value, left);
/* printf(" new insn=%x\n",insn); */ /* printf(" new insn=%x\n",insn); */
@ -899,29 +926,24 @@ md_apply_fix3 (fixp, valuep, seg)
return 1; return 1;
} }
/* This is called after the assembler has finished parsing the input
file. Because the D10V assembler sometimes saves short instructions /* d10v_cleanup() is called after the assembler has finished parsing the input
to see if it can package them with the next instruction, there may file or after a label is defined. Because the D10V assembler sometimes saves short
instructions to see if it can package them with the next instruction, there may
be a short instruction that still needs written. */ be a short instruction that still needs written. */
int md_after_pass()
{
if (prev_opcode)
{
write_1_short (prev_opcode, prev_insn);
prev_opcode = NULL;
}
}
/* there is a label to be defined. Any saved instruction must
be written out. */
int int
start_label() d10v_cleanup()
{ {
segT seg;
subsegT subseg;
if (prev_opcode) if (prev_opcode)
{ {
write_1_short (prev_opcode, prev_insn); seg = now_seg;
subseg = now_subseg;
subseg_set (prev_seg, prev_subseg);
write_1_short (prev_opcode, prev_insn, fixups);
subseg_set (seg, subseg);
prev_opcode = NULL; prev_opcode = NULL;
} }
return 1; return 1;

View File

@ -46,12 +46,10 @@
/* We don't need to handle .word strangely. */ /* We don't need to handle .word strangely. */
#define WORKING_DOT_WORD #define WORKING_DOT_WORD
#define md_number_to_chars number_to_chars_bigendian #define md_number_to_chars number_to_chars_bigendian
#define md_after_pass_hook md_after_pass int d10v_cleanup PARAMS ((void));
#define md_after_pass_hook() d10v_cleanup()
extern int start_label PARAMS ((void)); #define TC_START_LABEL(ch, ptr) (ch == ':' && d10v_cleanup())
#define TC_START_LABEL(ch, ptr) (ch == ':' && start_label())