version 1.1.1.1, 2016/01/26 17:26:17 |
version 1.1.1.2, 2016/10/26 17:02:50 |
|
|
/* tc-microblaze.c -- Assemble code for Xilinx MicroBlaze |
/* tc-microblaze.c -- Assemble code for Xilinx MicroBlaze |
|
|
Copyright 2009, 2010, 2012 Free Software Foundation. |
Copyright (C) 2009-2015 Free Software Foundation, Inc. |
|
|
This file is part of GAS, the GNU Assembler. |
This file is part of GAS, the GNU Assembler. |
|
|
|
|
#define streq(a,b) (strcmp (a, b) == 0) |
#define streq(a,b) (strcmp (a, b) == 0) |
#endif |
#endif |
|
|
|
#define OPTION_EB (OPTION_MD_BASE + 0) |
|
#define OPTION_EL (OPTION_MD_BASE + 1) |
|
|
void microblaze_generate_symbol (char *sym); |
void microblaze_generate_symbol (char *sym); |
static bfd_boolean check_spl_reg (unsigned *); |
static bfd_boolean check_spl_reg (unsigned *); |
|
|
Line 78 const char FLT_CHARS[] = "rRsSfFdDxXpP"; |
|
Line 81 const char FLT_CHARS[] = "rRsSfFdDxXpP"; |
|
#define GOT_OFFSET 8 |
#define GOT_OFFSET 8 |
#define PLT_OFFSET 9 |
#define PLT_OFFSET 9 |
#define GOTOFF_OFFSET 10 |
#define GOTOFF_OFFSET 10 |
|
#define TLSGD_OFFSET 11 |
|
#define TLSLD_OFFSET 12 |
|
#define TLSDTPMOD_OFFSET 13 |
|
#define TLSDTPREL_OFFSET 14 |
|
#define TLSGOTTPREL_OFFSET 15 |
|
#define TLSTPREL_OFFSET 16 |
|
|
/* Initialize the relax table. */ |
/* Initialize the relax table. */ |
const relax_typeS md_relax_table[] = |
const relax_typeS md_relax_table[] = |
Line 94 const relax_typeS md_relax_table[] = |
|
Line 102 const relax_typeS md_relax_table[] = |
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 8: GOT_OFFSET. */ |
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 8: GOT_OFFSET. */ |
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 9: PLT_OFFSET. */ |
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 9: PLT_OFFSET. */ |
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 10: GOTOFF_OFFSET. */ |
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 10: GOTOFF_OFFSET. */ |
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 11: TLSGD_OFFSET. */ |
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 12: TLSLD_OFFSET. */ |
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*1, 0 }, /* 13: TLSDTPMOD_OFFSET. */ |
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 14: TLSDTPREL_OFFSET. */ |
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 15: TLSGOTTPREL_OFFSET. */ |
|
{ 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 } /* 16: TLSTPREL_OFFSET. */ |
}; |
}; |
|
|
static struct hash_control * opcode_hash_control; /* Opcode mnemonics. */ |
static struct hash_control * opcode_hash_control; /* Opcode mnemonics. */ |
Line 165 microblaze_s_lcomm (int xxx ATTRIBUTE_UN |
|
Line 179 microblaze_s_lcomm (int xxx ATTRIBUTE_UN |
|
segT current_seg = now_seg; |
segT current_seg = now_seg; |
subsegT current_subseg = now_subseg; |
subsegT current_subseg = now_subseg; |
|
|
name = input_line_pointer; |
c = get_symbol_name (&name); |
c = get_symbol_end (); |
|
|
|
/* Just after name is now '\0'. */ |
/* Just after name is now '\0'. */ |
p = input_line_pointer; |
p = input_line_pointer; |
*p = c; |
(void) restore_line_pointer (c); |
SKIP_WHITESPACE (); |
SKIP_WHITESPACE (); |
if (*input_line_pointer != ',') |
if (*input_line_pointer != ',') |
{ |
{ |
Line 301 microblaze_s_bss (int localvar) |
|
Line 314 microblaze_s_bss (int localvar) |
|
static void |
static void |
microblaze_s_func (int end_p ATTRIBUTE_UNUSED) |
microblaze_s_func (int end_p ATTRIBUTE_UNUSED) |
{ |
{ |
*input_line_pointer = get_symbol_end (); |
char *name; |
|
restore_line_pointer (get_symbol_name (&name)); |
s_func (1); |
s_func (1); |
} |
} |
|
|
Line 315 microblaze_s_weakext (int ignore ATTRIBU |
|
Line 329 microblaze_s_weakext (int ignore ATTRIBU |
|
symbolS *symbolP; |
symbolS *symbolP; |
expressionS exp; |
expressionS exp; |
|
|
name = input_line_pointer; |
c = get_symbol_name (&name); |
c = get_symbol_end (); |
|
symbolP = symbol_find_or_make (name); |
symbolP = symbol_find_or_make (name); |
S_SET_WEAK (symbolP); |
S_SET_WEAK (symbolP); |
*input_line_pointer = c; |
(void) restore_line_pointer (c); |
|
|
SKIP_WHITESPACE (); |
SKIP_WHITESPACE (); |
|
|
Line 528 parse_reg (char * s, unsigned * reg) |
|
Line 541 parse_reg (char * s, unsigned * reg) |
|
} |
} |
return s; |
return s; |
} |
} |
|
/* Stack protection registers. */ |
|
else if (strncasecmp (s, "rshr", 4) == 0) |
|
{ |
|
*reg = REG_SHR; |
|
return s + 4; |
|
} |
|
else if (strncasecmp (s, "rslr", 4) == 0) |
|
{ |
|
*reg = REG_SLR; |
|
return s + 4; |
|
} |
else |
else |
{ |
{ |
if (TOLOWER (s[0]) == 'r') |
if (TOLOWER (s[0]) == 'r') |
Line 585 parse_exp (char *s, expressionS *e) |
|
Line 609 parse_exp (char *s, expressionS *e) |
|
} |
} |
|
|
/* Symbol modifiers (@GOT, @PLT, @GOTOFF). */ |
/* Symbol modifiers (@GOT, @PLT, @GOTOFF). */ |
|
#define IMM_NONE 0 |
#define IMM_GOT 1 |
#define IMM_GOT 1 |
#define IMM_PLT 2 |
#define IMM_PLT 2 |
#define IMM_GOTOFF 3 |
#define IMM_GOTOFF 3 |
|
#define IMM_TLSGD 4 |
|
#define IMM_TLSLD 5 |
|
#define IMM_TLSDTPMOD 6 |
|
#define IMM_TLSDTPREL 7 |
|
#define IMM_TLSTPREL 8 |
|
#define IMM_MAX 9 |
|
|
|
struct imm_type { |
|
char *isuffix; /* Suffix String */ |
|
int itype; /* Suffix Type */ |
|
int otype; /* Offset Type */ |
|
}; |
|
|
|
/* These are NOT in assending order of type, GOTOFF is ahead to make |
|
sure @GOTOFF does not get matched with @GOT */ |
|
static struct imm_type imm_types[] = { |
|
{ "NONE", IMM_NONE , 0 }, |
|
{ "GOTOFF", IMM_GOTOFF , GOTOFF_OFFSET }, |
|
{ "GOT", IMM_GOT , GOT_OFFSET }, |
|
{ "PLT", IMM_PLT , PLT_OFFSET }, |
|
{ "TLSGD", IMM_TLSGD , TLSGD_OFFSET }, |
|
{ "TLSLDM", IMM_TLSLD, TLSLD_OFFSET }, |
|
{ "TLSDTPMOD", IMM_TLSDTPMOD, TLSDTPMOD_OFFSET }, |
|
{ "TLSDTPREL", IMM_TLSDTPREL, TLSDTPREL_OFFSET }, |
|
{ "TLSTPREL", IMM_TLSTPREL, TLSTPREL_OFFSET } |
|
}; |
|
|
|
static int |
|
match_imm (const char *s, int *ilen) |
|
{ |
|
int i; |
|
int slen; |
|
|
|
/* Check for matching suffix */ |
|
for (i = 1; i < IMM_MAX; i++) |
|
{ |
|
slen = strlen (imm_types[i].isuffix); |
|
|
|
if (strncmp (imm_types[i].isuffix, s, slen) == 0) |
|
{ |
|
*ilen = slen; |
|
return imm_types[i].itype; |
|
} |
|
} /* for */ |
|
*ilen = 0; |
|
return 0; |
|
} |
|
|
|
static int |
|
get_imm_otype (int itype) |
|
{ |
|
int i, otype; |
|
|
|
otype = 0; |
|
/* Check for matching itype */ |
|
for (i = 1; i < IMM_MAX; i++) |
|
{ |
|
if (imm_types[i].itype == itype) |
|
{ |
|
otype = imm_types[i].otype; |
|
break; |
|
} |
|
} |
|
return otype; |
|
} |
|
|
static symbolS * GOT_symbol; |
static symbolS * GOT_symbol; |
|
|
#define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_" |
#define GOT_SYMBOL_NAME "_GLOBAL_OFFSET_TABLE_" |
|
|
static char * |
static char * |
parse_imm (char * s, expressionS * e, int min, int max) |
parse_imm (char * s, expressionS * e, offsetT min, offsetT max) |
{ |
{ |
char *new_pointer; |
char *new_pointer; |
char *atp; |
char *atp; |
|
int itype, ilen; |
|
|
|
ilen = 0; |
|
|
/* Find the start of "@GOT" or "@PLT" suffix (if any) */ |
/* Find the start of "@GOT" or "@PLT" suffix (if any) */ |
for (atp = s; *atp != '@'; atp++) |
for (atp = s; *atp != '@'; atp++) |
Line 606 parse_imm (char * s, expressionS * e, in |
|
Line 699 parse_imm (char * s, expressionS * e, in |
|
|
|
if (*atp == '@') |
if (*atp == '@') |
{ |
{ |
if (strncmp (atp + 1, "GOTOFF", 5) == 0) |
itype = match_imm (atp + 1, &ilen); |
{ |
if (itype != 0) |
*atp = 0; |
{ |
e->X_md = IMM_GOTOFF; |
*atp = 0; |
} |
e->X_md = itype; |
else if (strncmp (atp + 1, "GOT", 3) == 0) |
} |
{ |
|
*atp = 0; |
|
e->X_md = IMM_GOT; |
|
} |
|
else if (strncmp (atp + 1, "PLT", 3) == 0) |
|
{ |
|
*atp = 0; |
|
e->X_md = IMM_PLT; |
|
} |
|
else |
else |
{ |
{ |
atp = NULL; |
atp = NULL; |
e->X_md = 0; |
e->X_md = 0; |
} |
ilen = 0; |
|
} |
*atp = 0; |
*atp = 0; |
} |
} |
else |
else |
Line 641 parse_imm (char * s, expressionS * e, in |
|
Line 726 parse_imm (char * s, expressionS * e, in |
|
|
|
new_pointer = parse_exp (s, e); |
new_pointer = parse_exp (s, e); |
|
|
|
if (!GOT_symbol && ! strncmp (s, GOT_SYMBOL_NAME, 20)) |
|
{ |
|
GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME); |
|
} |
|
|
if (e->X_op == O_absent) |
if (e->X_op == O_absent) |
; /* An error message has already been emitted. */ |
; /* An error message has already been emitted. */ |
else if ((e->X_op != O_constant && e->X_op != O_symbol) ) |
else if ((e->X_op != O_constant && e->X_op != O_symbol) ) |
as_fatal (_("operand must be a constant or a label")); |
as_fatal (_("operand must be a constant or a label")); |
else if ((e->X_op == O_constant) && ((int) e->X_add_number < min |
else if (e->X_op == O_constant) |
|| (int) e->X_add_number > max)) |
|
{ |
{ |
as_fatal (_("operand must be absolute in range %d..%d, not %d"), |
/* Special case: sign extend negative 32-bit values to 64-bits. */ |
min, max, (int) e->X_add_number); |
if ((e->X_add_number >> 31) == 1) |
|
e->X_add_number |= -((offsetT) 1 << 31); |
|
|
|
if (e->X_add_number < min || e->X_add_number > max) |
|
{ |
|
as_fatal (_("operand must be absolute in range %lx..%lx, not %lx"), |
|
(long) min, (long) max, (long) e->X_add_number); |
|
} |
} |
} |
|
|
if (atp) |
if (atp) |
{ |
{ |
*atp = '@'; /* restore back (needed?) */ |
*atp = '@'; /* restore back (needed?) */ |
if (new_pointer >= atp) |
if (new_pointer >= atp) |
new_pointer += (e->X_md == IMM_GOTOFF)?7:4; |
new_pointer += ilen + 1; /* sizeof (imm_suffix) + 1 for '@' */ |
/* sizeof("@GOTOFF", "@GOT" or "@PLT") */ |
|
|
|
} |
} |
return new_pointer; |
return new_pointer; |
} |
} |
Line 713 check_got (int * got_type, int * got_len |
|
Line 807 check_got (int * got_type, int * got_len |
|
return tmpbuf; |
return tmpbuf; |
} |
} |
|
|
extern void |
extern bfd_reloc_code_real_type |
parse_cons_expression_microblaze (expressionS *exp, int size) |
parse_cons_expression_microblaze (expressionS *exp, int size) |
{ |
{ |
if (size == 4) |
if (size == 4) |
Line 739 parse_cons_expression_microblaze (expres |
|
Line 833 parse_cons_expression_microblaze (expres |
|
} |
} |
else |
else |
expression (exp); |
expression (exp); |
|
return BFD_RELOC_NONE; |
} |
} |
|
|
/* This is the guts of the machine-dependent assembler. STR points to a |
/* This is the guts of the machine-dependent assembler. STR points to a |
Line 757 check_spl_reg (unsigned * reg) |
|
Line 852 check_spl_reg (unsigned * reg) |
|
|| (*reg == REG_PID) || (*reg == REG_ZPR) |
|| (*reg == REG_PID) || (*reg == REG_ZPR) |
|| (*reg == REG_TLBX) || (*reg == REG_TLBLO) |
|| (*reg == REG_TLBX) || (*reg == REG_TLBLO) |
|| (*reg == REG_TLBHI) || (*reg == REG_TLBSX) |
|| (*reg == REG_TLBHI) || (*reg == REG_TLBSX) |
|
|| (*reg == REG_SHR) || (*reg == REG_SLR) |
|| (*reg >= REG_PVR+MIN_PVR_REGNUM && *reg <= REG_PVR+MAX_PVR_REGNUM)) |
|| (*reg >= REG_PVR+MIN_PVR_REGNUM && *reg <= REG_PVR+MAX_PVR_REGNUM)) |
return TRUE; |
return TRUE; |
|
|
Line 777 tc_microblaze_fix_adjustable (struct fix |
|
Line 873 tc_microblaze_fix_adjustable (struct fix |
|
if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOTOFF |
if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOTOFF |
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_GOTOFF |
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_GOTOFF |
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOT |
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GOT |
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_PLT) |
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_PLT |
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSGD |
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSLD |
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_TLSDTPMOD |
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_32_TLSDTPREL |
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSDTPREL |
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL |
|
|| fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_TLSTPREL) |
return 0; |
return 0; |
|
|
return 1; |
return 1; |
Line 925 md_assemble (char * str) |
|
Line 1028 md_assemble (char * str) |
|
opc = str_microblaze_rw_anchor; |
opc = str_microblaze_rw_anchor; |
else |
else |
opc = NULL; |
opc = NULL; |
if (exp.X_md == IMM_GOT) |
if (exp.X_md != 0) |
subtype = GOT_OFFSET; |
subtype = get_imm_otype(exp.X_md); |
else if (exp.X_md == IMM_PLT) |
|
subtype = PLT_OFFSET; |
|
else if (exp.X_md == IMM_GOTOFF) |
|
subtype = GOTOFF_OFFSET; |
|
else |
else |
subtype = opcode->inst_offset_type; |
subtype = opcode->inst_offset_type; |
|
|
Line 1198 md_assemble (char * str) |
|
Line 1297 md_assemble (char * str) |
|
as_fatal (_("Error in statement syntax")); |
as_fatal (_("Error in statement syntax")); |
immed = 0; |
immed = 0; |
} |
} |
/* Check for spl registers. */ |
|
if (check_spl_reg (®1)) |
|
as_fatal (_("Cannot use special register with this instruction")); |
|
inst |= (immed << IMM_LOW) & RFSL_MASK; |
inst |= (immed << IMM_LOW) & RFSL_MASK; |
output = frag_more (isize); |
output = frag_more (isize); |
break; |
break; |
Line 1280 md_assemble (char * str) |
|
Line 1376 md_assemble (char * str) |
|
immed = opcode->immval_mask | REG_TLBLO_MASK; |
immed = opcode->immval_mask | REG_TLBLO_MASK; |
else if (reg2 == REG_TLBHI) |
else if (reg2 == REG_TLBHI) |
immed = opcode->immval_mask | REG_TLBHI_MASK; |
immed = opcode->immval_mask | REG_TLBHI_MASK; |
|
else if (reg2 == REG_SHR) |
|
immed = opcode->immval_mask | REG_SHR_MASK; |
|
else if (reg2 == REG_SLR) |
|
immed = opcode->immval_mask | REG_SLR_MASK; |
else if (reg2 >= (REG_PVR+MIN_PVR_REGNUM) && reg2 <= (REG_PVR+MAX_PVR_REGNUM)) |
else if (reg2 >= (REG_PVR+MIN_PVR_REGNUM) && reg2 <= (REG_PVR+MAX_PVR_REGNUM)) |
immed = opcode->immval_mask | REG_PVR_MASK | reg2; |
immed = opcode->immval_mask | REG_PVR_MASK | reg2; |
else |
else |
Line 1331 md_assemble (char * str) |
|
Line 1431 md_assemble (char * str) |
|
immed = opcode->immval_mask | REG_TLBHI_MASK; |
immed = opcode->immval_mask | REG_TLBHI_MASK; |
else if (reg1 == REG_TLBSX) |
else if (reg1 == REG_TLBSX) |
immed = opcode->immval_mask | REG_TLBSX_MASK; |
immed = opcode->immval_mask | REG_TLBSX_MASK; |
|
else if (reg1 == REG_SHR) |
|
immed = opcode->immval_mask | REG_SHR_MASK; |
|
else if (reg1 == REG_SLR) |
|
immed = opcode->immval_mask | REG_SLR_MASK; |
else |
else |
as_fatal (_("invalid value for special purpose register")); |
as_fatal (_("invalid value for special purpose register")); |
inst |= (reg2 << RA_LOW) & RA_MASK; |
inst |= (reg2 << RA_LOW) & RA_MASK; |
Line 1338 md_assemble (char * str) |
|
Line 1442 md_assemble (char * str) |
|
output = frag_more (isize); |
output = frag_more (isize); |
break; |
break; |
|
|
case INST_TYPE_RD_R1_SPECIAL: |
case INST_TYPE_R1_R2_SPECIAL: |
if (strcmp (op_end, "")) |
if (strcmp (op_end, "")) |
op_end = parse_reg (op_end + 1, ®1); /* Get rd. */ |
op_end = parse_reg (op_end + 1, ®1); /* Get r1. */ |
else |
else |
{ |
{ |
as_fatal (_("Error in statement syntax")); |
as_fatal (_("Error in statement syntax")); |
reg1 = 0; |
reg1 = 0; |
} |
} |
if (strcmp (op_end, "")) |
if (strcmp (op_end, "")) |
op_end = parse_reg (op_end + 1, ®2); /* Get r1. */ |
op_end = parse_reg (op_end + 1, ®2); /* Get r2. */ |
else |
else |
{ |
{ |
as_fatal (_("Error in statement syntax")); |
as_fatal (_("Error in statement syntax")); |
Line 1361 md_assemble (char * str) |
|
Line 1465 md_assemble (char * str) |
|
as_fatal (_("Cannot use special register with this instruction")); |
as_fatal (_("Cannot use special register with this instruction")); |
|
|
/* insn wic ra, rb => wic ra, ra, rb. */ |
/* insn wic ra, rb => wic ra, ra, rb. */ |
inst |= (reg1 << RD_LOW) & RD_MASK; |
|
inst |= (reg1 << RA_LOW) & RA_MASK; |
inst |= (reg1 << RA_LOW) & RA_MASK; |
inst |= (reg2 << RB_LOW) & RB_MASK; |
inst |= (reg2 << RB_LOW) & RB_MASK; |
|
|
Line 1417 md_assemble (char * str) |
|
Line 1520 md_assemble (char * str) |
|
char *opc = NULL; |
char *opc = NULL; |
relax_substateT subtype; |
relax_substateT subtype; |
|
|
if (exp.X_md == IMM_GOT) |
if (exp.X_md != 0) |
subtype = GOT_OFFSET; |
subtype = get_imm_otype(exp.X_md); |
else if (exp.X_md == IMM_PLT) |
|
subtype = PLT_OFFSET; |
|
else |
else |
subtype = opcode->inst_offset_type; |
subtype = opcode->inst_offset_type; |
|
|
output = frag_var (rs_machine_dependent, |
output = frag_var (rs_machine_dependent, |
isize * 2, /* maxm of 2 words. */ |
isize * 2, /* maxm of 2 words. */ |
isize, /* minm of 1 word. */ |
isize, /* minm of 1 word. */ |
Line 1484 md_assemble (char * str) |
|
Line 1586 md_assemble (char * str) |
|
char *opc = NULL; |
char *opc = NULL; |
relax_substateT subtype; |
relax_substateT subtype; |
|
|
if (exp.X_md == IMM_GOT) |
if (exp.X_md != 0) |
subtype = GOT_OFFSET; |
subtype = get_imm_otype(exp.X_md); |
else if (exp.X_md == IMM_PLT) |
else |
subtype = PLT_OFFSET; |
|
else |
|
subtype = opcode->inst_offset_type; |
subtype = opcode->inst_offset_type; |
|
|
output = frag_var (rs_machine_dependent, |
output = frag_var (rs_machine_dependent, |
isize * 2, /* maxm of 2 words. */ |
isize * 2, /* maxm of 2 words. */ |
isize, /* minm of 1 word. */ |
isize, /* minm of 1 word. */ |
Line 1557 md_assemble (char * str) |
|
Line 1658 md_assemble (char * str) |
|
char *opc = NULL; |
char *opc = NULL; |
relax_substateT subtype; |
relax_substateT subtype; |
|
|
if (exp.X_md == IMM_GOT) |
if (exp.X_md != 0) |
subtype = GOT_OFFSET; |
subtype = get_imm_otype(exp.X_md); |
else if (exp.X_md == IMM_PLT) |
else |
subtype = PLT_OFFSET; |
subtype = opcode->inst_offset_type; |
else |
|
subtype = opcode->inst_offset_type; |
|
output = frag_var (rs_machine_dependent, |
output = frag_var (rs_machine_dependent, |
isize * 2, /* maxm of 2 words. */ |
isize * 2, /* maxm of 2 words. */ |
isize, /* minm of 1 word. */ |
isize, /* minm of 1 word. */ |
Line 1605 md_assemble (char * str) |
|
Line 1705 md_assemble (char * str) |
|
output = frag_more (isize); |
output = frag_more (isize); |
break; |
break; |
|
|
|
case INST_TYPE_IMM5: |
|
if (strcmp(op_end, "")) |
|
op_end = parse_imm (op_end + 1, & exp, MIN_IMM5, MAX_IMM5); |
|
else |
|
as_fatal(_("Error in statement syntax")); |
|
if (exp.X_op != O_constant) { |
|
as_warn(_("Symbol used as immediate for mbar instruction")); |
|
} else { |
|
output = frag_more (isize); |
|
immed = exp.X_add_number; |
|
} |
|
if (immed != (immed % 32)) { |
|
as_warn(_("Immediate value for mbar > 32. using <value %% 32>")); |
|
immed = immed % 32; |
|
} |
|
inst |= (immed << IMM_MBAR); |
|
break; |
|
|
default: |
default: |
as_fatal (_("unimplemented opcode \"%s\""), name); |
as_fatal (_("unimplemented opcode \"%s\""), name); |
} |
} |
Line 1710 const char * md_shortopts = ""; |
|
Line 1828 const char * md_shortopts = ""; |
|
|
|
struct option md_longopts[] = |
struct option md_longopts[] = |
{ |
{ |
|
{"EB", no_argument, NULL, OPTION_EB}, |
|
{"EL", no_argument, NULL, OPTION_EL}, |
{ NULL, no_argument, NULL, 0} |
{ NULL, no_argument, NULL, 0} |
}; |
}; |
|
|
Line 1808 md_convert_frag (bfd * abfd ATTRIBUTE_UN |
|
Line 1928 md_convert_frag (bfd * abfd ATTRIBUTE_UN |
|
fragP->fr_fix += INST_WORD_SIZE * 2; |
fragP->fr_fix += INST_WORD_SIZE * 2; |
fragP->fr_var = 0; |
fragP->fr_var = 0; |
break; |
break; |
|
case TLSGD_OFFSET: |
|
fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, |
|
fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSGD); |
|
fragP->fr_fix += INST_WORD_SIZE * 2; |
|
fragP->fr_var = 0; |
|
break; |
|
case TLSLD_OFFSET: |
|
fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, |
|
fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSLD); |
|
fragP->fr_fix += INST_WORD_SIZE * 2; |
|
fragP->fr_var = 0; |
|
break; |
|
case TLSDTPREL_OFFSET: |
|
fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, |
|
fragP->fr_offset, FALSE, BFD_RELOC_MICROBLAZE_64_TLSDTPREL); |
|
fragP->fr_fix += INST_WORD_SIZE * 2; |
|
fragP->fr_var = 0; |
|
break; |
|
|
default: |
default: |
abort (); |
abort (); |
Line 1989 md_apply_fix (fixS * fixP, |
|
Line 2127 md_apply_fix (fixS * fixP, |
|
} |
} |
break; |
break; |
|
|
|
case BFD_RELOC_MICROBLAZE_64_TLSDTPREL: |
|
case BFD_RELOC_MICROBLAZE_64_TLSGD: |
|
case BFD_RELOC_MICROBLAZE_64_TLSLD: |
|
S_SET_THREAD_LOCAL (fixP->fx_addsy); |
|
|
case BFD_RELOC_MICROBLAZE_64_GOTPC: |
case BFD_RELOC_MICROBLAZE_64_GOTPC: |
case BFD_RELOC_MICROBLAZE_64_GOT: |
case BFD_RELOC_MICROBLAZE_64_GOT: |
case BFD_RELOC_MICROBLAZE_64_PLT: |
case BFD_RELOC_MICROBLAZE_64_PLT: |
Line 2065 md_estimate_size_before_relax (fragS * f |
|
Line 2208 md_estimate_size_before_relax (fragS * f |
|
as_bad (_("Absolute PC-relative value in relaxation code. Assembler error.....")); |
as_bad (_("Absolute PC-relative value in relaxation code. Assembler error.....")); |
abort (); |
abort (); |
} |
} |
else if ((S_GET_SEGMENT (fragP->fr_symbol) == segment_type)) |
else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type && |
|
!S_IS_WEAK (fragP->fr_symbol)) |
{ |
{ |
fragP->fr_subtype = DEFINED_PC_OFFSET; |
fragP->fr_subtype = DEFINED_PC_OFFSET; |
/* Don't know now whether we need an imm instruction. */ |
/* Don't know now whether we need an imm instruction. */ |
Line 2166 md_estimate_size_before_relax (fragS * f |
|
Line 2310 md_estimate_size_before_relax (fragS * f |
|
case GOT_OFFSET: |
case GOT_OFFSET: |
case PLT_OFFSET: |
case PLT_OFFSET: |
case GOTOFF_OFFSET: |
case GOTOFF_OFFSET: |
|
case TLSGD_OFFSET: |
|
case TLSLD_OFFSET: |
|
case TLSTPREL_OFFSET: |
|
case TLSDTPREL_OFFSET: |
fragP->fr_var = INST_WORD_SIZE*2; |
fragP->fr_var = INST_WORD_SIZE*2; |
break; |
break; |
case DEFINED_RO_SEGMENT: |
case DEFINED_RO_SEGMENT: |
case DEFINED_RW_SEGMENT: |
case DEFINED_RW_SEGMENT: |
case DEFINED_PC_OFFSET: |
case DEFINED_PC_OFFSET: |
|
case TLSDTPMOD_OFFSET: |
fragP->fr_var = INST_WORD_SIZE; |
fragP->fr_var = INST_WORD_SIZE; |
break; |
break; |
default: |
default: |
Line 2254 tc_gen_reloc (asection * section ATTRIBU |
|
Line 2403 tc_gen_reloc (asection * section ATTRIBU |
|
case BFD_RELOC_MICROBLAZE_64_PLT: |
case BFD_RELOC_MICROBLAZE_64_PLT: |
case BFD_RELOC_MICROBLAZE_64_GOTOFF: |
case BFD_RELOC_MICROBLAZE_64_GOTOFF: |
case BFD_RELOC_MICROBLAZE_32_GOTOFF: |
case BFD_RELOC_MICROBLAZE_32_GOTOFF: |
|
case BFD_RELOC_MICROBLAZE_64_TLSGD: |
|
case BFD_RELOC_MICROBLAZE_64_TLSLD: |
|
case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD: |
|
case BFD_RELOC_MICROBLAZE_32_TLSDTPREL: |
|
case BFD_RELOC_MICROBLAZE_64_TLSDTPREL: |
|
case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL: |
|
case BFD_RELOC_MICROBLAZE_64_TLSTPREL: |
code = fixp->fx_r_type; |
code = fixp->fx_r_type; |
break; |
break; |
|
|
Line 2306 md_parse_option (int c, char * arg ATTRI |
|
Line 2462 md_parse_option (int c, char * arg ATTRI |
|
{ |
{ |
switch (c) |
switch (c) |
{ |
{ |
|
case OPTION_EB: |
|
target_big_endian = 1; |
|
break; |
|
case OPTION_EL: |
|
target_big_endian = 0; |
|
break; |
default: |
default: |
return 0; |
return 0; |
} |
} |
|
|
cons_fix_new_microblaze (fragS * frag, |
cons_fix_new_microblaze (fragS * frag, |
int where, |
int where, |
int size, |
int size, |
expressionS *exp) |
expressionS *exp, |
|
bfd_reloc_code_real_type r) |
{ |
{ |
|
|
bfd_reloc_code_real_type r; |
|
|
|
if ((exp->X_op == O_subtract) && (exp->X_add_symbol) && |
if ((exp->X_op == O_subtract) && (exp->X_add_symbol) && |
(exp->X_op_symbol) && (now_seg != absolute_section) && (size == 4) |
(exp->X_op_symbol) && (now_seg != absolute_section) && (size == 4) |
&& (!S_IS_LOCAL (exp->X_op_symbol))) |
&& (!S_IS_LOCAL (exp->X_op_symbol))) |