#include "safe-ctype.h"
#include "as.h"
#include "tc-dlx.h"
#include "opcode/dlx.h"
#define machine_opcode dlx_opcode
#define machine_opcodes dlx_opcodes
#define machine_ip dlx_ip
#define machine_it dlx_it
#define NO_RELOC BFD_RELOC_NONE
#define RELOC_DLX_REL26 BFD_RELOC_DLX_JMP26
#define RELOC_DLX_16 BFD_RELOC_16
#define RELOC_DLX_REL16 BFD_RELOC_16_PCREL_S2
#define RELOC_DLX_HI16 BFD_RELOC_HI16_S
#define RELOC_DLX_LO16 BFD_RELOC_LO16
#define RELOC_DLX_VTINHERIT BFD_RELOC_VTABLE_INHERIT
#define RELOC_DLX_VTENTRY BFD_RELOC_VTABLE_ENTRY
static struct hash_control *op_hash = NULL;
struct machine_it
{
char *error;
unsigned long opcode;
struct nlist *nlistp;
expressionS exp;
int pcrel;
int size;
int reloc_offset;
int reloc;
int HI;
int LO;
}
the_insn;
char * parse_operand PARAMS ((char *, expressionS *));
int md_chars_to_number PARAMS ((unsigned char *, int));
static void machine_ip PARAMS ((char *));
static void s_proc PARAMS ((int));
static void insert_sreg PARAMS ((char *, int));
static int hilo_modifier_ok PARAMS ((char *));
static int is_ldst_registers PARAMS ((char *));
static int match_sft_register PARAMS ((char *));
static void define_some_regs PARAMS ((void));
static char * dlx_parse_loadop PARAMS ((char *));
static char * dlx_parse_storeop PARAMS ((char *));
static char * fix_ld_st_operand PARAMS ((unsigned long, char *));
const pseudo_typeS
dlx_pseudo_table[] =
{
{"asciiz", stringer, 1},
{"half", cons, 2},
{"dword", cons, 8},
{"word", cons, 4},
{"proc", s_proc, 0},
{"endproc", s_proc, 1},
{NULL, 0, 0},
};
const char comment_chars[] = ";";
const char line_comment_chars[] = "#";
const char line_separator_chars[] = "@";
const char EXP_CHARS[] = "eE";
const char FLT_CHARS[] = "rRsSfFdDxXpP";
static void
insert_sreg (regname, regnum)
char *regname;
int regnum;
{
char buf[80];
int i;
symbol_table_insert (symbol_new (regname, reg_section, (valueT) regnum,
&zero_address_frag));
for (i = 0; regname[i]; i++)
buf[i] = ISLOWER (regname[i]) ? TOUPPER (regname[i]) : regname[i];
buf[i] = '\0';
symbol_table_insert (symbol_new (buf, reg_section, (valueT) regnum,
&zero_address_frag));
}
static void
define_some_regs ()
{
insert_sreg ("zero", 0);
insert_sreg ("at", 1);
insert_sreg ("v0", 2);
insert_sreg ("v1", 3);
insert_sreg ("a0", 4);
insert_sreg ("a1", 5);
insert_sreg ("a2", 6);
insert_sreg ("a3", 7);
insert_sreg ("t0", 8);
insert_sreg ("t1", 9);
insert_sreg ("t2", 10);
insert_sreg ("t3", 11);
insert_sreg ("t4", 12);
insert_sreg ("t5", 13);
insert_sreg ("t6", 14);
insert_sreg ("t7", 15);
insert_sreg ("s0", 16);
insert_sreg ("s1", 17);
insert_sreg ("s2", 18);
insert_sreg ("s3", 19);
insert_sreg ("s4", 20);
insert_sreg ("s5", 21);
insert_sreg ("s6", 22);
insert_sreg ("s7", 23);
insert_sreg ("t8", 24);
insert_sreg ("t9", 25);
insert_sreg ("k0", 26);
insert_sreg ("k1", 27);
insert_sreg ("gp", 28);
insert_sreg ("sp", 29);
insert_sreg ("fp", 30);
insert_sreg ("ra", 31);
insert_sreg ("pc", 0);
insert_sreg ("npc", 1);
insert_sreg ("iad", 2);
}
static int
match_sft_register (name)
char *name;
{
#define MAX_REG_NO 35
static char *soft_reg[] =
{
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9",
"s0", "s1", "s2", "s3", "s4", "s5", "s7", "k0", "k1",
"gp", "sp", "fp", "ra", "pc", "npc", "iad",
"EndofTab"
};
char low_name[21], *ptr;
int idx;
for (ptr = name,idx = 0; *ptr != '\0'; ptr++)
low_name[idx++] = TOLOWER (*ptr);
low_name[idx] = '\0';
idx = 0;
while (idx < MAX_REG_NO && strcmp (soft_reg[idx], & low_name [0]))
idx += 1;
return idx < MAX_REG_NO;
}
static int
is_ldst_registers (name)
char *name;
{
char *ptr = name;
if ((ptr[0] == '%' || ptr[0] == '$' || ptr[0] == 'r' || ptr[0] == 'R')
&& ISDIGIT ((unsigned char) ptr[1]))
return 1;
return match_sft_register (ptr);
}
static void
s_proc (end_p)
int end_p;
{
static char *current_name;
static char *current_label;
if (end_p)
{
if (current_name == NULL)
{
as_bad (_("missing .proc"));
ignore_rest_of_line ();
return;
}
current_name = current_label = NULL;
SKIP_WHITESPACE ();
while (!is_end_of_line[(unsigned char) *input_line_pointer])
input_line_pointer++;
}
else
{
char *name, *label;
char delim1, delim2;
if (current_name != NULL)
{
as_bad (_(".endfunc missing for previous .proc"));
ignore_rest_of_line ();
return;
}
name = input_line_pointer;
delim1 = get_symbol_end ();
name = xstrdup (name);
*input_line_pointer = delim1;
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
char leading_char = 0;
leading_char = bfd_get_symbol_leading_char (stdoutput);
if (leading_char)
asprintf (&label, "%c%s", leading_char, name);
else
label = name;
}
else
{
++input_line_pointer;
SKIP_WHITESPACE ();
label = input_line_pointer;
delim2 = get_symbol_end ();
label = xstrdup (label);
*input_line_pointer = delim2;
}
current_name = name;
current_label = label;
}
demand_empty_rest_of_line ();
}
void
md_begin ()
{
const char *retval = NULL;
int lose = 0;
unsigned int i;
op_hash = hash_new ();
for (i = 0; i < num_dlx_opcodes; i++)
{
const char *name = machine_opcodes[i].name;
retval = hash_insert (op_hash, name, (PTR) &machine_opcodes[i]);
if (retval != NULL)
{
fprintf (stderr, "internal error: can't hash `%s': %s\n",
machine_opcodes[i].name, retval);
lose = 1;
}
}
if (lose)
as_fatal (_("Broken assembler. No assembly attempted."));
define_some_regs ();
}
void
md_assemble (str)
char *str;
{
char *toP;
fixS *fixP;
bit_fixS *bitP;
know (str);
machine_ip (str);
toP = frag_more (4);
md_number_to_chars (toP, the_insn.opcode, 4);
if (the_insn.reloc != NO_RELOC)
{
fixP = fix_new_exp (frag_now,
(toP - frag_now->fr_literal + the_insn.reloc_offset),
the_insn.size, & the_insn.exp, the_insn.pcrel,
the_insn.reloc);
switch (the_insn.reloc)
{
case RELOC_DLX_HI16:
case RELOC_DLX_LO16:
fixP->fx_no_overflow = 1;
break;
default:
break;
}
switch (fixP->fx_r_type)
{
case RELOC_DLX_REL26:
bitP = malloc (sizeof (bit_fixS));
bitP->fx_bit_size = 26;
bitP->fx_bit_offset = 25;
bitP->fx_bit_base = the_insn.opcode & 0xFC000000;
bitP->fx_bit_base_adj = 0;
bitP->fx_bit_max = 0;
bitP->fx_bit_min = 0;
bitP->fx_bit_add = 0x03FFFFFF;
fixP->fx_bit_fixP = bitP;
break;
case RELOC_DLX_LO16:
case RELOC_DLX_REL16:
bitP = malloc (sizeof (bit_fixS));
bitP->fx_bit_size = 16;
bitP->fx_bit_offset = 15;
bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
bitP->fx_bit_base_adj = 0;
bitP->fx_bit_max = 0;
bitP->fx_bit_min = 0;
bitP->fx_bit_add = 0x0000FFFF;
fixP->fx_bit_fixP = bitP;
break;
case RELOC_DLX_HI16:
bitP = malloc (sizeof (bit_fixS));
bitP->fx_bit_size = 16;
bitP->fx_bit_offset = 15;
bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000;
bitP->fx_bit_base_adj = 0;
bitP->fx_bit_max = 0;
bitP->fx_bit_min = 0;
bitP->fx_bit_add = 0x0000FFFF;
fixP->fx_bit_fixP = bitP;
break;
default:
fixP->fx_bit_fixP = (bit_fixS *)NULL;
break;
}
}
}
static int
hilo_modifier_ok (s)
char *s;
{
char *ptr = s;
int idx, count = 1;
if (*ptr != '(')
return 1;
for (idx = 1; ptr[idx] != '\0' && ptr[idx] != '[' && idx < 73; idx += 1)
{
if (count == 0)
return count;
if (ptr[idx] == '(')
count += 1;
if (ptr[idx] == ')')
count -= 1;
}
return (count == 0) ? 1:0;
}
char *
parse_operand (s, operandp)
char *s;
expressionS *operandp;
{
char *save = input_line_pointer;
char *new;
the_insn.HI = the_insn.LO = 0;
if (strncmp (s, "%hi", 3) == 0)
{
s += 3;
the_insn.HI = 1;
}
else
{
if (strncmp (s, "%lo", 3) == 0)
{
s += 3;
the_insn.LO = 1;
}
else
the_insn.LO = 0;
}
if (the_insn.HI || the_insn.LO)
{
if (!hilo_modifier_ok (s))
as_bad (_("Expression Error for operand modifier %%hi/%%lo\n"));
}
if ((s[0] == '%' || s[0] == '$' || s[0] == 'r' || s[0] == 'R')
&& ISDIGIT ((unsigned char) s[1]))
{
s += 1;
input_line_pointer = s;
(void) expression (operandp);
if (operandp->X_op != O_constant
|| operandp->X_add_number > 31)
as_bad (_("Invalid expression after %%%%\n"));
operandp->X_op = O_register;
}
else
{
input_line_pointer = s;
(void) expression (operandp);
}
new = input_line_pointer;
input_line_pointer = save;
return new;
}
#define READ_OP 0x100
#define WRITE_OP 0x200
static char iBuf[81];
static char *
dlx_parse_loadop (str)
char * str;
{
char *ptr = str;
int idx = 0;
for (idx = 0; idx < 72 && ptr[idx] != '\0'; idx++)
;
if (idx == 72)
{
badoperand_load:
as_bad (_("Bad operand for a load instruction: <%s>"), str);
return NULL;
}
else
{
int i, pb = 0;
int m2 = 0;
char rs1[7], rd[7], endm, match = '0';
char imm[72];
idx -= 1;
switch (str[idx])
{
case ')':
match = '(';
endm = ')';
break;
case ']':
match = '[';
endm = ']';
break;
default:
rs1[0] = 'r';
rs1[1] = '0';
rs1[2] = '\0';
match = 0;
endm = 0;
m2 = 1;
}
if (!m2)
{
for (pb = idx - 1; str[pb] != match; pb -= 1)
if (str[pb] == endm || pb < (idx - 5))
goto load_no_rs1;
pb += 1;
for (i = 0; (pb + i) < idx; i++)
rs1[i] = str[pb+i];
rs1[i] = '\0';
if (is_ldst_registers (& rs1[0]))
pb -= 1;
else
{
load_no_rs1:
if (match == '[')
goto badoperand_load;
rs1[0] = 'r';
rs1[1] = '0';
rs1[2] = '\0';
m2 = 1;
}
}
for (i = 0; i < 7 && str[i] != ','; i++)
rd[i] = ptr[i];
if (str[i] != ',')
goto badoperand_load;
else
rd[i] = '\0';
if (m2)
pb = idx + 1;
for (i++, m2 = 0; i < pb; m2++,i++)
imm[m2] = ptr[i];
imm[m2] = '\0';
for (i = 0; rd[i] != '\0'; i++)
iBuf[i] = rd[i];
iBuf[i++] = ',';
for (pb = 0 ; rs1[pb] != '\0'; i++, pb++)
iBuf[i] = rs1[pb];
iBuf[i++] = ',';
for (pb = 0; imm[pb] != '\0'; i++, pb++)
iBuf[i] = imm[pb];
iBuf[i] = '\0';
return iBuf;
}
}
static char *
dlx_parse_storeop (str)
char * str;
{
char *ptr = str;
int idx = 0;
for (idx = 0; idx < 72 && ptr[idx] != ','; idx++)
;
if (idx == 72)
{
badoperand_store:
as_bad (_("Bad operand for a store instruction: <%s>"), str);
return NULL;
}
else
{
int i, pb = 0;
int comma = idx;
int m2 = 0;
char rs1[7], rd[7], endm, match = '0';
char imm[72];
idx -= 1;
switch (str[idx])
{
case ')':
match = '(';
endm = ')';
break;
case ']':
match = '[';
endm = ']';
break;
default:
rs1[0] = 'r';
rs1[1] = '0';
rs1[2] = '\0';
match = 0;
endm = 0;
m2 = 1;
}
if (!m2)
{
for (pb = idx - 1; str[pb] != match; pb -= 1)
if (pb < (idx - 5) || str[pb] == endm)
goto store_no_rs1;
pb += 1;
for (i = 0; (pb + i) < idx; i++)
rs1[i] = str[pb + i];
rs1[i] = '\0';
if (is_ldst_registers (& rs1[0]))
pb -= 1;
else
{
store_no_rs1:
if (match == '[')
goto badoperand_store;
rs1[0] = 'r';
rs1[1] = '0';
rs1[2] = '\0';
pb = comma;
}
}
else
pb = comma;
for (i = comma + 1; (str[i] == ' ' || str[i] == '\t'); i++)
;
for (m2 = 0; (m2 < 7 && str[i] != '\0'); i++, m2++)
{
if (str[i] != ' ' && str[i] != '\t')
rd[m2] = str[i];
else
goto badoperand_store;
}
if (str[i] != '\0')
goto badoperand_store;
else
rd[m2] = '\0';
for (i = 0; i < pb; i++)
imm[i] = ptr[i];
imm[i] = '\0';
for (i = 0; rd[i] != '\0'; i++)
iBuf[i] = rd[i];
iBuf[i++] = ',';
for (pb = 0 ; rs1[pb] != '\0'; i++, pb++)
iBuf[i] = rs1[pb];
iBuf[i++] = ',';
for (pb = 0; imm[pb] != '\0'; i++, pb++)
iBuf[i] = imm[pb];
iBuf[i] = '\0';
return iBuf;
}
}
static char *
fix_ld_st_operand (opcode, str)
unsigned long opcode;
char* str;
{
switch ((int) opcode)
{
case LBOP:
case LBUOP:
case LSBUOP:
case LHOP:
case LHUOP:
case LSHUOP:
case LWOP:
case LSWOP:
return dlx_parse_loadop (str);
case SBOP:
case SHOP:
case SWOP:
return dlx_parse_storeop (str);
default:
return str;
}
}
static void
machine_ip (str)
char *str;
{
char *s;
const char *args;
struct machine_opcode *insn;
char *argsStart;
unsigned long opcode;
expressionS the_operand;
expressionS *operand = &the_operand;
unsigned int reg, reg_shift = 0;
s = str;
if (ISALPHA (*s))
for (; ISALNUM (*s); ++s)
if (ISUPPER (*s))
*s = TOLOWER (*s);
switch (*s)
{
case '\0':
break;
case ' ':
*s++ = '\0';
break;
default:
as_bad (_("Unknown opcode: `%s'"), str);
return;
}
if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL)
{
if ((strcmp (str, "ret") == 0) || (strcmp (str, "return") == 0))
{
memset (&the_insn, '\0', sizeof (the_insn));
the_insn.reloc = NO_RELOC;
the_insn.pcrel = 0;
the_insn.opcode =
(unsigned long)(JROP | 0x03e00000);
}
else
as_bad (_("Unknown opcode `%s'."), str);
return;
}
argsStart = s;
opcode = insn->opcode;
memset (&the_insn, '\0', sizeof (the_insn));
the_insn.reloc = NO_RELOC;
the_insn.pcrel = 0;
if (!set_dlx_skip_hi16_flag (1))
as_bad (_("Can not set dlx_skip_hi16_flag"));
s = fix_ld_st_operand (opcode, s);
if (insn->args[0] != '\0' && insn->args[0] != 'N')
{
if (*s == '\0')
{
as_bad (_("Missing arguments for opcode <%s>."), str);
return;
}
else
s = parse_operand (s, operand);
}
else if (insn->args[0] == 'N')
{
the_insn.opcode = opcode;
return;
}
for (args = insn->args;; ++args)
{
switch (*args)
{
case '\0':
if (*s == '\0')
{
the_insn.opcode = opcode;
the_insn.HI = 0;
the_insn.LO = 0;
return;
}
the_insn.HI = 0;
the_insn.LO = 0;
as_bad (_("Too many operands: %s"), s);
break;
case ',':
if (*s++ == ',')
{
s = parse_operand (s, operand);
continue;
}
break;
case 'P':
if (operand->X_op == O_register)
{
reg_shift = 21;
goto general_reg;
}
case 'i':
case 'I':
if (operand->X_op == O_constant)
{
if (the_insn.HI)
operand->X_add_number >>= 16;
opcode |= operand->X_add_number & 0xFFFF;
if (the_insn.HI && the_insn.LO)
as_bad (_("Both the_insn.HI and the_insn.LO are set : %s"), s);
else
{
the_insn.HI = 0;
the_insn.LO = 0;
}
continue;
}
the_insn.reloc = (the_insn.HI) ? RELOC_DLX_HI16
: (the_insn.LO ? RELOC_DLX_LO16 : RELOC_DLX_16);
the_insn.reloc_offset = 2;
the_insn.size = 2;
the_insn.pcrel = 0;
the_insn.exp = * operand;
the_insn.HI = 0;
the_insn.LO = 0;
continue;
case 'd':
if (operand->X_op == O_constant)
{
opcode |= operand->X_add_number & 0xFFFF;
continue;
}
the_insn.reloc = RELOC_DLX_REL16;
the_insn.reloc_offset = 0;
the_insn.size = 4;
the_insn.pcrel = 1;
the_insn.exp = *operand;
continue;
case 'D':
if (operand->X_op == O_constant)
{
opcode |= operand->X_add_number & 0x3FFFFFF;
continue;
}
the_insn.reloc = RELOC_DLX_REL26;
the_insn.reloc_offset = 0;
the_insn.size = 4;
the_insn.pcrel = 1;
the_insn.exp = *operand;
continue;
case 'a':
reg_shift = 21;
goto general_reg;
case 'b':
reg_shift = 16;
goto general_reg;
case 'c':
reg_shift = 11;
general_reg:
know (operand->X_add_symbol == 0);
know (operand->X_op_symbol == 0);
reg = operand->X_add_number;
if (reg & 0xffffffe0)
as_fatal (_("failed regnum sanity check."));
else
opcode |= reg << reg_shift;
switch (*args)
{
case 'a':
case 'b':
case 'c':
case 'P':
continue;
}
as_fatal (_("failed general register sanity check."));
break;
default:
BAD_CASE (*args);
}
as_bad ("Invalid operands");
return;
}
}
#define MAX_LITTLENUMS 6
char *
md_atof (type, litP, sizeP)
char type;
char *litP;
int *sizeP;
{
int prec;
LITTLENUM_TYPE words[MAX_LITTLENUMS];
LITTLENUM_TYPE *wordP;
char *t;
switch (type)
{
case 'f':
case 'F':
case 's':
case 'S':
prec = 2;
break;
case 'd':
case 'D':
case 'r':
case 'R':
prec = 4;
break;
case 'x':
case 'X':
prec = 6;
break;
case 'p':
case 'P':
prec = 6;
break;
default:
*sizeP = 0;
return "Bad call to MD_ATOF()";
}
t = atof_ieee (input_line_pointer, type, words);
if (t)
input_line_pointer = t;
*sizeP = prec * sizeof (LITTLENUM_TYPE);
for (wordP = words; prec--;)
{
md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
litP += sizeof (LITTLENUM_TYPE);
}
return 0;
}
void
md_number_to_chars (buf, val, n)
char *buf;
valueT val;
int n;
{
number_to_chars_bigendian (buf, val, n);
}
int
md_chars_to_number (val, n)
unsigned char *val;
int n;
{
int retval;
for (retval = 0; n--;)
{
retval <<= 8;
retval |= val[n];
}
return retval;
}
bfd_boolean
md_dlx_fix_adjustable (fixP)
fixS *fixP;
{
return (fixP->fx_r_type != BFD_RELOC_VTABLE_INHERIT
&& fixP->fx_r_type != BFD_RELOC_VTABLE_ENTRY);
}
void
md_apply_fix3 (fixP, valP, seg)
fixS *fixP;
valueT *valP;
segT seg ATTRIBUTE_UNUSED;
{
long val = *valP;
char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
switch (fixP->fx_r_type)
{
case RELOC_DLX_LO16:
case RELOC_DLX_REL16:
if (fixP->fx_bit_fixP != (bit_fixS *) NULL)
{
val = (val & 0x0000FFFF) | fixP->fx_bit_fixP->fx_bit_base;
free (fixP->fx_bit_fixP);
fixP->fx_bit_fixP = (bit_fixS *) NULL;
}
#ifdef DEBUG
else
know ((fixP->fx_bit_fixP != (bit_fixS *) NULL));
#endif
break;
case RELOC_DLX_HI16:
if (fixP->fx_bit_fixP != (bit_fixS *) NULL)
{
val = (val >> 16) | fixP->fx_bit_fixP->fx_bit_base;
free (fixP->fx_bit_fixP);
fixP->fx_bit_fixP = (bit_fixS *)NULL;
}
#ifdef DEBUG
else
know ((fixP->fx_bit_fixP != (bit_fixS *) NULL));
#endif
break;
case RELOC_DLX_REL26:
if (fixP->fx_bit_fixP != (bit_fixS *) NULL)
{
val = (val & 0x03FFFFFF) | fixP->fx_bit_fixP->fx_bit_base;
free (fixP->fx_bit_fixP);
fixP->fx_bit_fixP = (bit_fixS *) NULL;
}
#ifdef DEBUG
else
know ((fixP->fx_bit_fixP != (bit_fixS *) NULL));
#endif
break;
case BFD_RELOC_VTABLE_INHERIT:
fixP->fx_done = 0;
if (fixP->fx_addsy
&& !S_IS_DEFINED (fixP->fx_addsy)
&& !S_IS_WEAK (fixP->fx_addsy))
S_SET_WEAK (fixP->fx_addsy);
return;
case BFD_RELOC_VTABLE_ENTRY:
fixP->fx_done = 0;
return;
default:
break;
}
number_to_chars_bigendian (place, val, fixP->fx_size);
if (fixP->fx_addsy == NULL)
fixP->fx_done = 1;
}
const char *md_shortopts = "";
struct option md_longopts[] =
{
{NULL, no_argument, NULL, 0}
};
size_t md_longopts_size = sizeof (md_longopts);
int
md_parse_option (c, arg)
int c ATTRIBUTE_UNUSED;
char *arg ATTRIBUTE_UNUSED;
{
return 0;
}
void
md_show_usage (stream)
FILE *stream ATTRIBUTE_UNUSED;
{
}
int
dlx_unrecognized_line (c)
int c;
{
int lab;
char *s;
if (c != '$' || ! ISDIGIT ((unsigned char) input_line_pointer[0]))
return 0;
s = input_line_pointer;
lab = 0;
while (ISDIGIT ((unsigned char) *s))
{
lab = lab * 10 + *s - '0';
++s;
}
if (*s != ':')
{
return 0;
}
if (dollar_label_defined (lab))
{
as_bad (_("label \"$%d\" redefined"), lab);
return 0;
}
define_dollar_label (lab);
colon (dollar_label_name (lab, 0));
input_line_pointer = s + 1;
return 1;
}
symbolS *
md_undefined_symbol (name)
char *name ATTRIBUTE_UNUSED;
{
return NULL;
}
void
md_operand (expressionP)
expressionS* expressionP;
{
if (input_line_pointer[0] == '#' &&
ISDIGIT ((unsigned char) input_line_pointer[1]))
{
input_line_pointer += 1;
(void) expression (expressionP);
if (expressionP->X_op != O_constant)
as_bad (_("Invalid expression after # number\n"));
}
return;
}
valueT
md_section_align (segment, size)
segT segment ATTRIBUTE_UNUSED;
valueT size;
{
return size;
}
long
md_pcrel_from (fixP)
fixS* fixP;
{
return 4 + fixP->fx_where + fixP->fx_frag->fr_address;
}
arelent *
tc_gen_reloc (section, fixP)
asection *section ATTRIBUTE_UNUSED;
fixS *fixP;
{
arelent * reloc;
reloc = (arelent *) xmalloc (sizeof (arelent));
reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
if (reloc->howto == (reloc_howto_type *) NULL)
{
as_bad_where (fixP->fx_file, fixP->fx_line,
"internal error: can't export reloc type %d (`%s')",
fixP->fx_r_type,
bfd_get_reloc_code_name (fixP->fx_r_type));
return NULL;
}
assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
reloc->address = fixP->fx_offset;
reloc->addend = 0;
return reloc;
}
extern void pop_insert PARAMS ((const pseudo_typeS *));
void
dlx_pop_insert ()
{
pop_insert (dlx_pseudo_table);
return ;
}