* gas/config/tc-tic4x.c: Fixed proper commandline

parameters. Added support for new opcode-list format. General
	error message fixups.
	(c4x_inst_add): Reject insn not for our CPU
	(md_begin): Added matrix for setting the proper opcode-level &
	device-flags according to cpu type and revision. Rewrite the
	opcode hasher.
	(c4x_operand_parse): Fix opcode bug
	(c4x_operands_match): New function argument. Added dry-run
	mechanism, that is optional error generation. Added constraint 'i'
	and 'j'.
	(c4x_insn_check): Added new function for post-verification of the
	generated insn.
	(md_assemble): Check all opcodes before croaking because of an
	argument mismatch. Need this to be able to fully support
	ortogonally arguments.
	(md_parse_options): Revised commandprompt swicthes and added new
	ones.
	(md_show_usage): Complete rewrite of printout.
	* gas/testsuite/gas/tic4x/addressing.s: Fix bug in one insn
	* gas/testsuite/gas/tic4x/addressing_c3x.d: Update thereafter
	* gas/testsuite/gas/tic4x/addressing_c4x.d: Update thereafter
	* gas/testsuite/gas/tic4x/allopcodes.S: Add support for new
	opclass.h changes
	* gas/testsuite/gas/tic4x/opclasses.h: Added testsuites for
	the new enhanced opcodes.
	* gas/testsuite/gas/tic4x/opcodes.s: Regenerate
	* gas/testsuite/gas/tic4x/opcodes_c3x.d: Update from above
	* gas/testsuite/gas/tic4x/opcodes_c4x.d: Update from above
	* gas/testsuite/gas/tic4x/opcodes_new.d: Added new testsuite for
	the enhanced and special insns.
	* gas/testsuite/gas/tic4x/tic4x.exp: Added the opcodes_new testsuite
	* include/opcode/tic4x.h: File reordering. Added enhanced opcodes.
	* opcodes/tic4x-dis.c: Added support for enhanced and special
	insn.
	(c4x_print_op): Added insn class 'i' and 'j'
	(c4x_hash_opcode_special): Add to support special insn
	(c4x_hash_opcode): Update to support the new opcode-list
	format. Add support for the new special insns.
	(c4x_disassemble): New opcode-list support.
This commit is contained in:
Svein Seldal
2002-11-18 09:09:35 +00:00
parent 48c5eb8a70
commit 9c87d6c7e4
16 changed files with 2719 additions and 1216 deletions

View File

@@ -42,22 +42,7 @@
o Evaluation of constant floating point expressions (expr.c needs
work!)
o Warnings issued if parallel load of same register. Applies to LL
class. Can be applied to destination of the LS class as well, but
the test will be more complex.
o Support 'abc' constants?
o Support new opcodes and implement a silicon version switch (maybe
-mpg)
o Disallow non-float registers in float instructions.
o Make sure the source and destination register is NOT equal when
the C4X LDA insn is used (arg mode Q,Y)
o Merge the C3x op-table and the c4x op-table, and adhere to the
last argument when parsing the hash.
o Support 'abc' constants (that is 0x616263)
*/
#include <stdio.h>
@@ -88,8 +73,42 @@ static struct hash_control *c4x_op_hash = NULL;
static struct hash_control *c4x_asg_hash = NULL;
static unsigned int c4x_cpu = 0; /* Default to TMS320C40. */
static unsigned int c4x_revision = 0; /* CPU revision */
static unsigned int c4x_idle2 = 0; /* Idle2 support */
static unsigned int c4x_lowpower = 0; /* Lowpower support */
static unsigned int c4x_enhanced = 0; /* Enhanced opcode support */
static unsigned int c4x_big_model = 0; /* Default to small memory model. */
static unsigned int c4x_reg_args = 0; /* Default to args passed on stack. */
static unsigned long c4x_oplevel = 0; /* Opcode level */
#define OPTION_CPU 'm'
#define OPTION_BIG (OPTION_MD_BASE + 1)
#define OPTION_SMALL (OPTION_MD_BASE + 2)
#define OPTION_MEMPARM (OPTION_MD_BASE + 3)
#define OPTION_REGPARM (OPTION_MD_BASE + 4)
#define OPTION_IDLE2 (OPTION_MD_BASE + 5)
#define OPTION_LOWPOWER (OPTION_MD_BASE + 6)
#define OPTION_ENHANCED (OPTION_MD_BASE + 7)
#define OPTION_REV (OPTION_MD_BASE + 8)
CONST char *md_shortopts = "bm:prs";
struct option md_longopts[] =
{
{ "mcpu", required_argument, NULL, OPTION_CPU },
{ "mdsp", required_argument, NULL, OPTION_CPU },
{ "mbig", no_argument, NULL, OPTION_BIG },
{ "msmall", no_argument, NULL, OPTION_SMALL },
{ "mmemparm", no_argument, NULL, OPTION_MEMPARM },
{ "mregparm", no_argument, NULL, OPTION_REGPARM },
{ "midle2", no_argument, NULL, OPTION_IDLE2 },
{ "mlowpower", no_argument, NULL, OPTION_LOWPOWER },
{ "menhanced", no_argument, NULL, OPTION_ENHANCED },
{ "mrev", required_argument, NULL, OPTION_REV },
{ NULL, no_argument, NULL, 0 }
};
size_t md_longopts_size = sizeof (md_longopts);
typedef enum
{
@@ -185,7 +204,9 @@ static int c4x_indirect_parse
static char *c4x_operand_parse
PARAMS ((char *, c4x_operand_t *));
static int c4x_operands_match
PARAMS ((c4x_inst_t *, c4x_insn_t *));
PARAMS ((c4x_inst_t *, c4x_insn_t *, int));
static void c4x_insn_check
PARAMS ((c4x_insn_t *));
static void c4x_insn_output
PARAMS ((c4x_insn_t *));
static int c4x_operands_parse
@@ -1239,11 +1260,11 @@ c4x_version (x)
input_line_pointer =
c4x_expression_abs (input_line_pointer, &temp);
if (!IS_CPU_C3X (temp) && !IS_CPU_C4X (temp))
as_bad ("This assembler does not support processor generation %d\n",
as_bad ("This assembler does not support processor generation %d",
temp);
if (c4x_cpu && temp != c4x_cpu)
as_warn ("Changing processor generation on fly not supported...\n");
as_warn ("Changing processor generation on fly not supported...");
c4x_cpu = temp;
demand_empty_rest_of_line ();
}
@@ -1389,6 +1410,11 @@ c4x_inst_add (insts)
d = name;
/* We do not care about INSNs that is not a part of our
oplevel setting */
if (!insts->oplevel & c4x_oplevel)
return ok;
while (1)
{
switch (*s)
@@ -1450,6 +1476,34 @@ md_begin ()
int ok = 1;
unsigned int i;
/* Setup the proper opcode level according to the
commandline parameters */
c4x_oplevel = OP_C3X;
if ( IS_CPU_C4X(c4x_cpu) )
c4x_oplevel |= OP_C4X;
if ( ( c4x_cpu == 31 && c4x_revision >= 6)
|| (c4x_cpu == 32 && c4x_revision >= 2)
|| (c4x_cpu == 33)
|| c4x_enhanced )
c4x_oplevel |= OP_ENH;
if ( ( c4x_cpu == 30 && c4x_revision >= 7)
|| (c4x_cpu == 31 && c4x_revision >= 5)
|| (c4x_cpu == 32)
|| c4x_lowpower )
c4x_oplevel |= OP_LPWR;
if ( ( c4x_cpu == 30 && c4x_revision >= 7)
|| (c4x_cpu == 31 && c4x_revision >= 5)
|| (c4x_cpu == 32)
|| (c4x_cpu == 33)
|| (c4x_cpu == 40 && c4x_revision >= 5)
|| (c4x_cpu == 44)
|| c4x_idle2 )
c4x_oplevel |= OP_IDLE2;
/* Create hash table for mnemonics. */
c4x_op_hash = hash_new ();
@@ -1457,14 +1511,8 @@ md_begin ()
c4x_asg_hash = hash_new ();
/* Add mnemonics to hash table, expanding conditional mnemonics on fly. */
for (i = 0; i < c3x_num_insts; i++)
ok &= c4x_inst_add ((void *) &c3x_insts[i]);
if (IS_CPU_C4X (c4x_cpu))
{
for (i = 0; i < c4x_num_insts; i++)
ok &= c4x_inst_add ((void *) &c4x_insts[i]);
}
for (i = 0; i < c4x_num_insts; i++)
ok &= c4x_inst_add ((void *) &c4x_insts[i]);
/* Create dummy inst to avoid errors accessing end of table. */
c4x_inst_make ("", 0, "");
@@ -1695,12 +1743,12 @@ c4x_operand_parse (s, operand)
case '*':
ret = -1;
for (i = 0; i < num_indirects; i++)
for (i = 0; i < c4x_num_indirects; i++)
if ((ret = c4x_indirect_parse (operand, &c4x_indirects[i])))
break;
if (ret < 0)
break;
if (i < num_indirects)
if (i < c4x_num_indirects)
{
operand->mode = M_INDIRECT;
/* Indirect addressing mode number. */
@@ -1753,9 +1801,10 @@ c4x_operand_parse (s, operand)
}
static int
c4x_operands_match (inst, insn)
c4x_operands_match (inst, insn, check)
c4x_inst_t *inst;
c4x_insn_t *insn;
int check;
{
const char *args = inst->args;
unsigned long opcode = inst->opcode;
@@ -1809,8 +1858,9 @@ c4x_operands_match (inst, insn)
}
else
{
as_bad ("LDF's immediate value of %ld is too large",
(long) exp->X_add_number);
if (!check)
as_bad ("Immediate value of %ld is too large for ldf",
(long) exp->X_add_number);
ret = -1;
continue;
}
@@ -1836,8 +1886,9 @@ c4x_operands_match (inst, insn)
}
else
{
as_bad ("Direct value of %ld is too large",
(long) exp->X_add_number);
if (!check)
as_bad ("Direct value of %ld is too large",
(long) exp->X_add_number);
ret = -1;
continue;
}
@@ -1858,7 +1909,8 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, reg - REG_AR0, 24, 22);
else
{
as_bad ("Destination register must be ARn");
if (!check)
as_bad ("Destination register must be ARn");
ret = -1;
}
continue;
@@ -1876,8 +1928,9 @@ c4x_operands_match (inst, insn)
}
else
{
as_bad ("Immediate value of %ld is too large",
(long) exp->X_add_number);
if (!check)
as_bad ("Immediate value of %ld is too large",
(long) exp->X_add_number);
ret = -1;
continue;
}
@@ -1904,8 +1957,9 @@ c4x_operands_match (inst, insn)
if (operand->expr.X_add_number != 0
&& operand->expr.X_add_number != 0x18)
{
as_bad ("Invalid indirect addressing mode");
ret = -1;
if (!check)
as_bad ("Invalid indirect addressing mode");
ret = -1;
continue;
}
INSERTU (opcode, operand->aregno - REG_AR0, 2, 0);
@@ -1927,7 +1981,8 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, reg, 7, 0);
else
{
as_bad ("Register must be Rn");
if (!check)
as_bad ("Register must be Rn");
ret = -1;
}
continue;
@@ -1966,7 +2021,8 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, reg, 15, 8);
else
{
as_bad ("Register must be Rn");
if (!check)
as_bad ("Register must be Rn");
ret = -1;
}
continue;
@@ -1979,11 +2035,23 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, reg - REG_R0, 18, 16);
else
{
as_bad ("Register must be R0--R7");
if (!check)
as_bad ("Register must be R0--R7");
ret = -1;
}
continue;
case 'i':
if ( operand->mode == M_REGISTER
&& c4x_oplevel & OP_ENH )
{
reg = exp->X_add_number;
INSERTU (opcode, reg, 4, 0);
INSERTU (opcode, 7, 7, 5);
continue;
}
/* Fallthrough */
case 'I':
if (operand->mode != M_INDIRECT)
break;
@@ -1991,8 +2059,9 @@ c4x_operands_match (inst, insn)
{
if (IS_CPU_C4X (c4x_cpu))
break;
as_bad ("Invalid indirect addressing mode displacement %d",
operand->disp);
if (!check)
as_bad ("Invalid indirect addressing mode displacement %d",
operand->disp);
ret = -1;
continue;
}
@@ -2000,6 +2069,17 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, operand->expr.X_add_number, 7, 3);
continue;
case 'j':
if ( operand->mode == M_REGISTER
&& c4x_oplevel & OP_ENH )
{
reg = exp->X_add_number;
INSERTU (opcode, reg, 12, 8);
INSERTU (opcode, 7, 15, 13);
continue;
}
/* Fallthrough */
case 'J':
if (operand->mode != M_INDIRECT)
break;
@@ -2007,8 +2087,9 @@ c4x_operands_match (inst, insn)
{
if (IS_CPU_C4X (c4x_cpu))
break;
as_bad ("Invalid indirect addressing mode displacement %d",
operand->disp);
if (!check)
as_bad ("Invalid indirect addressing mode displacement %d",
operand->disp);
ret = -1;
continue;
}
@@ -2024,7 +2105,8 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, reg - REG_R0, 21, 19);
else
{
as_bad ("Register must be R0--R7");
if (!check)
as_bad ("Register must be R0--R7");
ret = -1;
}
continue;
@@ -2037,7 +2119,8 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, reg - REG_R0, 24, 22);
else
{
as_bad ("Register must be R0--R7");
if (!check)
as_bad ("Register must be R0--R7");
ret = -1;
}
continue;
@@ -2050,7 +2133,8 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, reg - REG_R2, 22, 22);
else
{
as_bad ("Destination register must be R2 or R3");
if (!check)
as_bad ("Destination register must be R2 or R3");
ret = -1;
}
continue;
@@ -2063,7 +2147,8 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, reg - REG_R0, 23, 23);
else
{
as_bad ("Destination register must be R0 or R1");
if (!check)
as_bad ("Destination register must be R0 or R1");
ret = -1;
}
continue;
@@ -2077,7 +2162,8 @@ c4x_operands_match (inst, insn)
if (operand->expr.X_add_number != 0
&& operand->expr.X_add_number != 0x18)
{
as_bad ("Invalid indirect addressing mode");
if (!check)
as_bad ("Invalid indirect addressing mode");
ret = -1;
continue;
}
@@ -2098,8 +2184,9 @@ c4x_operands_match (inst, insn)
}
else
{
as_bad ("Displacement value of %ld is too large",
(long) exp->X_add_number);
if (!check)
as_bad ("Displacement value of %ld is too large",
(long) exp->X_add_number);
ret = -1;
continue;
}
@@ -2125,7 +2212,8 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, reg, 15, 0);
else
{
as_bad ("Register must be Rn");
if (!check)
as_bad ("Register must be Rn");
ret = -1;
}
continue;
@@ -2146,7 +2234,8 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, reg, 20, 16);
else
{
as_bad ("Register must be Rn");
if (!check)
as_bad ("Register must be Rn");
ret = -1;
}
continue;
@@ -2156,7 +2245,8 @@ c4x_operands_match (inst, insn)
break;
if (exp->X_op == O_big)
{
as_bad ("Floating point number not valid in expression");
if (!check)
as_bad ("Floating point number not valid in expression");
ret = -1;
continue;
}
@@ -2169,8 +2259,9 @@ c4x_operands_match (inst, insn)
}
else
{
as_bad ("Signed immediate value %ld too large",
(long) exp->X_add_number);
if (!check)
as_bad ("Signed immediate value %ld too large",
(long) exp->X_add_number);
ret = -1;
continue;
}
@@ -2210,8 +2301,9 @@ c4x_operands_match (inst, insn)
}
else
{
as_bad ("Immediate value of %ld is too large",
(long) exp->X_add_number);
if (!check)
as_bad ("Immediate value of %ld is too large",
(long) exp->X_add_number);
ret = -1;
continue;
}
@@ -2230,8 +2322,9 @@ c4x_operands_match (inst, insn)
}
else
{
as_bad ("Unsigned immediate value %ld too large",
(long) exp->X_add_number);
if (!check)
as_bad ("Unsigned immediate value %ld too large",
(long) exp->X_add_number);
ret = -1;
continue;
}
@@ -2267,8 +2360,9 @@ c4x_operands_match (inst, insn)
}
else
{
as_bad ("Immediate value of %ld is too large",
(long) exp->X_add_number);
if (!check)
as_bad ("Immediate value of %ld is too large",
(long) exp->X_add_number);
ret = -1;
continue;
}
@@ -2282,7 +2376,8 @@ c4x_operands_match (inst, insn)
break;
if (exp->X_op == O_big)
{
as_bad ("Floating point number not valid in expression");
if (!check)
as_bad ("Floating point number not valid in expression");
ret = -1;
continue;
}
@@ -2295,8 +2390,9 @@ c4x_operands_match (inst, insn)
}
else
{
as_bad ("Immediate value %ld too large",
(long) exp->X_add_number);
if (!check)
as_bad ("Immediate value %ld too large",
(long) exp->X_add_number);
ret = -1;
continue;
}
@@ -2313,7 +2409,8 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, reg - REG_IVTP, 4, 0);
else
{
as_bad ("Register must be ivtp or tvtp");
if (!check)
as_bad ("Register must be ivtp or tvtp");
ret = -1;
}
continue;
@@ -2326,7 +2423,8 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, reg, 20, 16);
else
{
as_bad ("Register must be address register");
if (!check)
as_bad ("Register must be address register");
ret = -1;
}
continue;
@@ -2339,7 +2437,8 @@ c4x_operands_match (inst, insn)
INSERTU (opcode, reg - REG_IVTP, 20, 16);
else
{
as_bad ("Register must be ivtp or tvtp");
if (!check)
as_bad ("Register must be ivtp or tvtp");
ret = -1;
}
continue;
@@ -2386,6 +2485,38 @@ c4x_operands_match (inst, insn)
}
}
static void
c4x_insn_check (insn)
c4x_insn_t *insn;
{
if (!strcmp(insn->name, "lda"))
{
if (insn->num_operands < 2 || insn->num_operands > 2)
as_fatal ("Illegal internal LDA insn definition");
if ( insn->operands[0].mode == M_REGISTER
&& insn->operands[1].mode == M_REGISTER
&& insn->operands[0].expr.X_add_number == insn->operands[1].expr.X_add_number )
as_bad ("Source and destination register should not be equal");
}
else if( !strcmp(insn->name, "ldi_ldi")
|| !strcmp(insn->name, "ldi1_ldi2")
|| !strcmp(insn->name, "ldi2_ldi1")
|| !strcmp(insn->name, "ldf_ldf")
|| !strcmp(insn->name, "ldf1_ldf2")
|| !strcmp(insn->name, "ldf2_ldf1") )
{
if ( insn->num_operands < 4 && insn->num_operands > 5 )
as_fatal ("Illegal internal %s insn definition", insn->name);
if ( insn->operands[1].mode == M_REGISTER
&& insn->operands[insn->num_operands-1].mode == M_REGISTER
&& insn->operands[1].expr.X_add_number == insn->operands[insn->num_operands-1].expr.X_add_number )
as_warn ("Equal parallell destination registers, one result will be discarded");
}
}
static void
c4x_insn_output (insn)
c4x_insn_t *insn;
@@ -2445,6 +2576,7 @@ md_assemble (str)
int i;
int parsed = 0;
c4x_inst_t *inst; /* Instruction template. */
c4x_inst_t *first_inst;
if (str && insn->parallel)
{
@@ -2491,23 +2623,30 @@ md_assemble (str)
return;
}
/* FIXME: The list of templates should be scanned
for the candidates with the desired number of operands.
We shouldn't issue error messages until we have
whittled the list of candidate templates to the most
likely one... We could cache a parsed form of the templates
to reduce the time required to match a template. */
inst = insn->inst;
first_inst = NULL;
do
ok = c4x_operands_match (inst, insn);
while (!ok && !strcmp (inst->name, inst[1].name) && inst++);
{
ok = c4x_operands_match (inst, insn, 1);
if (ok < 0)
{
if (!first_inst)
first_inst = inst;
ok = 0;
}
} while (!ok && !strcmp (inst->name, inst[1].name) && inst++);
if (ok > 0)
c4x_insn_output (insn);
{
c4x_insn_check (insn);
c4x_insn_output (insn);
}
else if (!ok)
as_bad ("Invalid operands for %s", insn->name);
{
if (first_inst)
c4x_operands_match (first_inst, insn, 0);
as_bad ("Invalid operands for %s", insn->name);
}
else
as_bad ("Invalid instruction %s", insn->name);
}
@@ -2715,13 +2854,6 @@ md_estimate_size_before_relax (fragP, segtype)
return 0;
}
CONST char *md_shortopts = "bm:prs";
struct option md_longopts[] =
{
{NULL, no_argument, NULL, 0}
};
size_t md_longopts_size = sizeof (md_longopts);
int
md_parse_option (c, arg)
@@ -2730,25 +2862,54 @@ md_parse_option (c, arg)
{
switch (c)
{
case 'b': /* big model */
c4x_big_model = 1;
break;
case 'm': /* -m[c][34]x */
case OPTION_CPU: /* cpu brand */
if (tolower (*arg) == 'c')
arg++;
c4x_cpu = atoi (arg);
if (!IS_CPU_C3X (c4x_cpu) && !IS_CPU_C4X (c4x_cpu))
as_warn ("Unsupported processor generation %d\n", c4x_cpu);
as_warn ("Unsupported processor generation %d", c4x_cpu);
break;
case 'p': /* push args */
case OPTION_REV: /* cpu revision */
c4x_revision = atoi (arg);
break;
case 'b':
as_warn ("Option -b is depreciated, please use -mbig");
case OPTION_BIG: /* big model */
c4x_big_model = 1;
break;
case 'p':
as_warn ("Option -p is depreciated, please use -mmemparm");
case OPTION_MEMPARM: /* push args */
c4x_reg_args = 0;
break;
case 'r': /* register args */
case 'r':
as_warn ("Option -r is depreciated, please use -mregparm");
case OPTION_REGPARM: /* register args */
c4x_reg_args = 1;
break;
case 's': /* small model */
case 's':
as_warn ("Option -s is depreciated, please use -msmall");
case OPTION_SMALL: /* small model */
c4x_big_model = 0;
break;
case OPTION_IDLE2:
c4x_idle2 = 1;
break;
case OPTION_LOWPOWER:
c4x_lowpower = 1;
break;
case OPTION_ENHANCED:
c4x_enhanced = 1;
break;
default:
return 0;
}
@@ -2760,15 +2921,26 @@ void
md_show_usage (stream)
FILE *stream;
{
fputs ("\
C[34]x options:\n\
-m30 | -m31 | -m32 | -m33 | -m40 | -m44\n\
specify variant of architecture\n\
-b big memory model\n\
-p pass arguments on stack\n\
-r pass arguments in registers (default)\n\
-s small memory model (default)\n",
stream);
fprintf (stream,
_("\nTIC4X options:\n"
" -mcpu=CPU -mCPU select architecture variant. CPU can be:\n"
" 30 - TMS320C30\n"
" 31 - TMS320C31, TMS320LC31\n"
" 32 - TMS320C32\n"
" 33 - TMS320VC33\n"
" 40 - TMS320C40\n"
" 44 - TMS320C44\n"
" -mrev=REV set cpu hardware revision (integer numbers).\n"
" Combinations of -mcpu and -mrev will enable/disable\n"
" the appropriate options (-midle2, -mlowpower and\n"
" -menhanced) according to the selected type\n"
" -mbig select big memory model\n"
" -msmall select small memory model (default)\n"
" -mregparm select register parameters (default)\n"
" -mmemparm select memory parameters\n"
" -midle2 enable IDLE2 support\n"
" -mlowpower enable LOPOWER and MAXSPEED support\n"
" -menhanced enable enhanced opcode support\n"));
}
/* This is called when a line is unrecognized. This is used to handle
@@ -3010,7 +3182,7 @@ tc_gen_reloc (seg, fixP)
if (reloc->howto == (reloc_howto_type *) NULL)
{
as_bad_where (fixP->fx_file, fixP->fx_line,
"reloc %d not supported by object file format",
"Reloc %d not supported by object file format",
(int) fixP->fx_r_type);
return NULL;
}