Line 1... |
Line 1... |
/* tc-score.c -- Assembler for Score
|
/* tc-score.c -- Assembler for Score
|
Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
Copyright 2006, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
|
Contributed by:
|
Contributed by:
|
Brain.lin (brain.lin@sunplusct.com)
|
Brain.lin (brain.lin@sunplusct.com)
|
Mei Ligang (ligang@sunnorth.com.cn)
|
Mei Ligang (ligang@sunnorth.com.cn)
|
Pei-Lin Tsai (pltsai@sunplus.com)
|
Pei-Lin Tsai (pltsai@sunplus.com)
|
|
|
Line 1183... |
Line 1183... |
|
|
static int
|
static int
|
s3_my_get_expression (expressionS * ep, char **str)
|
s3_my_get_expression (expressionS * ep, char **str)
|
{
|
{
|
char *save_in;
|
char *save_in;
|
segT seg;
|
|
|
|
save_in = input_line_pointer;
|
save_in = input_line_pointer;
|
input_line_pointer = *str;
|
input_line_pointer = *str;
|
s3_in_my_get_expression = 1;
|
s3_in_my_get_expression = 1;
|
seg = expression (ep);
|
(void) expression (ep);
|
s3_in_my_get_expression = 0;
|
s3_in_my_get_expression = 0;
|
|
|
if (ep->X_op == O_illegal)
|
if (ep->X_op == O_illegal)
|
{
|
{
|
*str = input_line_pointer;
|
*str = input_line_pointer;
|
Line 1305... |
Line 1304... |
|
|
case _IMM5_MULTI_LOAD:
|
case _IMM5_MULTI_LOAD:
|
if (val >= 2 && val <= 32)
|
if (val >= 2 && val <= 32)
|
{
|
{
|
if (val == 32)
|
if (val == 32)
|
{
|
|
val = 0;
|
val = 0;
|
}
|
|
return val;
|
return val;
|
}
|
}
|
else
|
|
{
|
|
return (int) s3_FAIL;
|
return (int) s3_FAIL;
|
}
|
|
break;
|
|
|
|
case _IMM32:
|
case _IMM32:
|
if (val >= 0 && val <= 0xffffffff)
|
if (val >= 0 && val <= 0xffffffff)
|
{
|
{
|
return val;
|
return val;
|
Line 1598... |
Line 1591... |
}
|
}
|
/*cmpi.c */
|
/*cmpi.c */
|
else if ((s3_inst.instruction & 0x02040001) == 0x02040001)
|
else if ((s3_inst.instruction & 0x02040001) == 0x02040001)
|
{
|
{
|
/* imm <=0x3f (5 bit<<1)*/
|
/* imm <=0x3f (5 bit<<1)*/
|
if (((s3_inst.instruction & 0x1ffe0)==0)||(((s3_inst.instruction & 0x1ffe0) == 0x1ffe0)&&(s3_inst.instruction & 0x003e) !=0))
|
if (((s3_inst.instruction & 0x1ffe0) == 0)
|
|
|| (((s3_inst.instruction & 0x1ffe0) == 0x1ffe0)
|
|
&& (s3_inst.instruction & 0x003e) != 0))
|
{
|
{
|
s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f;
|
s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f;
|
s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0x1f) << 5);
|
s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0x1f) << 5);
|
s3_inst.relax_size = 2;
|
s3_inst.relax_size = 2;
|
}
|
}
|
Line 1614... |
Line 1609... |
}
|
}
|
/* addi */
|
/* addi */
|
else if (((s3_inst.instruction & 0x2000000) == 0x02000000)&& (s3_inst.relax_inst!=0x8000))
|
else if (((s3_inst.instruction & 0x2000000) == 0x02000000)&& (s3_inst.relax_inst!=0x8000))
|
{
|
{
|
/* rd : 0-16 ; imm <=0x7f (6 bit<<1)*/
|
/* rd : 0-16 ; imm <=0x7f (6 bit<<1)*/
|
if ((((s3_inst.instruction >> 20) & 0x10) != 0x10) &&
|
if ((((s3_inst.instruction >> 20) & 0x10) != 0x10)
|
(((s3_inst.instruction & 0x1ffc0)==0)||(((s3_inst.instruction & 0x1ffc0) == 0x1ffc0)&&(s3_inst.instruction & 0x007e) !=0)))
|
&& (((s3_inst.instruction & 0x1ffc0) == 0)
|
|
|| (((s3_inst.instruction & 0x1ffc0) == 0x1ffc0)
|
|
&& (s3_inst.instruction & 0x007e) != 0)))
|
{
|
{
|
s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x3f;
|
s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x3f;
|
s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 6);
|
s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 6);
|
s3_inst.relax_size = 2;
|
s3_inst.relax_size = 2;
|
}
|
}
|
else
|
else
|
{
|
{
|
s3_inst.relax_inst =0x8000;
|
s3_inst.relax_inst =0x8000;
|
|
|
}
|
}
|
}
|
}
|
|
|
else if (((s3_inst.instruction >> 20) & 0x10) == 0x10)
|
else if (((s3_inst.instruction >> 20) & 0x10) == 0x10)
|
{
|
{
|
Line 1936... |
Line 1932... |
if (((s3_inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv!*/
|
if (((s3_inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv!*/
|
{
|
{
|
/* mv! rd : 5bit , ra : 5bit */
|
/* mv! rd : 5bit , ra : 5bit */
|
s3_inst.relax_inst |= ((s3_inst.instruction >> 15) & 0x1f) | (((s3_inst.instruction >> 20) & 0x1f) << 5);
|
s3_inst.relax_inst |= ((s3_inst.instruction >> 15) & 0x1f) | (((s3_inst.instruction >> 20) & 0x1f) << 5);
|
s3_inst.relax_size = 2;
|
s3_inst.relax_size = 2;
|
|
|
}
|
}
|
else if ((((s3_inst.instruction >> 15) & 0x10) == 0x0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
|
else if ((((s3_inst.instruction >> 15) & 0x10) == 0x0) && (((s3_inst.instruction >> 20) & 0x10) == 0))
|
{
|
{
|
s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 4)
|
s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 4)
|
| (((s3_inst.instruction >> 20) & 0xf) << 8);
|
| (((s3_inst.instruction >> 20) & 0xf) << 8);
|
Line 2938... |
Line 2933... |
{
|
{
|
int pre_inc = 0;
|
int pre_inc = 0;
|
int conflict_reg;
|
int conflict_reg;
|
int value;
|
int value;
|
char * temp;
|
char * temp;
|
char *strbak;
|
|
char *dataptr;
|
char *dataptr;
|
int reg;
|
int reg;
|
int ldst_idx = 0;
|
int ldst_idx = 0;
|
|
|
strbak = str;
|
|
s3_skip_whitespace (str);
|
s3_skip_whitespace (str);
|
|
|
if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
|
if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)
|
|| (s3_skip_past_comma (&str) == (int) s3_FAIL))
|
|| (s3_skip_past_comma (&str) == (int) s3_FAIL))
|
return;
|
return;
|
Line 3409... |
Line 3402... |
|
|
static void
|
static void
|
s3_do16_ldst_insn (char *str)
|
s3_do16_ldst_insn (char *str)
|
{
|
{
|
int conflict_reg=0;
|
int conflict_reg=0;
|
char * temp;
|
|
s3_skip_whitespace (str);
|
s3_skip_whitespace (str);
|
|
|
if ((s3_reglow_required_here (&str, 8) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
|
if ((s3_reglow_required_here (&str, 8) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL))
|
return;
|
return;
|
|
|
Line 3431... |
Line 3423... |
s3_inst.error=s3_err_msg;
|
s3_inst.error=s3_err_msg;
|
return ;
|
return ;
|
}
|
}
|
|
|
s3_skip_whitespace (str);
|
s3_skip_whitespace (str);
|
temp = str + 1; /* The latter will process decimal/hex expression. */
|
|
if (*str == ']')
|
if (*str == ']')
|
{
|
{
|
str++;
|
str++;
|
if (s3_end_of_line (str) == (int) s3_FAIL)
|
if (s3_end_of_line (str) == (int) s3_FAIL)
|
return;
|
return;
|
Line 3482... |
Line 3474... |
|
|
value >>=2;
|
value >>=2;
|
s3_inst.instruction |= value;
|
s3_inst.instruction |= value;
|
}
|
}
|
}
|
}
|
|
|
}
|
}
|
else
|
else
|
{
|
{
|
sprintf (s3_err_msg, _("missing ["));
|
sprintf (s3_err_msg, _("missing ["));
|
s3_inst.error=s3_err_msg;
|
s3_inst.error=s3_err_msg;
|
Line 4486... |
Line 4477... |
sprintf (append_str, " r%d, [r1,0]", reg_rd);
|
sprintf (append_str, " r%d, [r1,0]", reg_rd);
|
s3_do_ldst_insn (append_str);
|
s3_do_ldst_insn (append_str);
|
|
|
s3_nor1 = r1_bak;
|
s3_nor1 = r1_bak;
|
}
|
}
|
|
|
/* Handle bcmpeq / bcmpne */
|
/* Handle bcmpeq / bcmpne */
|
static void
|
static void
|
s3_do_macro_bcmp (char *str)
|
s3_do_macro_bcmp (char *str)
|
{
|
{
|
int reg_a , reg_b;
|
int reg_a , reg_b;
|
Line 4497... |
Line 4489... |
char* ptemp;
|
char* ptemp;
|
int i=0;
|
int i=0;
|
struct s3_score_it inst_expand[2];
|
struct s3_score_it inst_expand[2];
|
struct s3_score_it inst_main;
|
struct s3_score_it inst_main;
|
|
|
|
memset (inst_expand, 0, sizeof inst_expand);
|
s3_skip_whitespace (str);
|
s3_skip_whitespace (str);
|
if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
|
if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
|
|| s3_skip_past_comma (&str) == (int) s3_FAIL
|
|| s3_skip_past_comma (&str) == (int) s3_FAIL
|
||(reg_b = s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
|
||(reg_b = s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
|
|| s3_skip_past_comma (&str) == (int) s3_FAIL)
|
|| s3_skip_past_comma (&str) == (int) s3_FAIL)
|
return;
|
return;
|
ptemp =str;
|
ptemp =str;
|
while(*ptemp!=0)
|
while(*ptemp!=0)
|
{
|
{
|
keep_data[i]=*ptemp;
|
keep_data[i] = *ptemp;
|
i++;
|
i++;
|
ptemp++;
|
ptemp++;
|
}
|
}
|
keep_data[i]=0;
|
keep_data[i]=0;
|
if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
|
if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
|
Line 4531... |
Line 4523... |
s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP;
|
s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP;
|
s3_inst.reloc.pc_rel = 1;
|
s3_inst.reloc.pc_rel = 1;
|
bfd_signed_vma val = s3_inst.reloc.exp.X_add_number;
|
bfd_signed_vma val = s3_inst.reloc.exp.X_add_number;
|
|
|
/* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
|
/* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */
|
s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number>>1) & 0x1) | ((s3_inst.reloc.exp.X_add_number>>2) & 0x7)<<7 |((s3_inst.reloc.exp.X_add_number>>5) & 0x1f)<<20;
|
s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1)
|
|
| ((s3_inst.reloc.exp.X_add_number >> 2) & 0x7) << 7
|
|
| ((s3_inst.reloc.exp.X_add_number >> 5) & 0x1f) << 20;
|
|
|
/* Check and set offset. */
|
/* Check and set offset. */
|
if (((val & 0xfffffe00) != 0)
|
if (((val & 0xfffffe00) != 0)
|
&& ((val & 0xfffffe00) != 0xfffffe00))
|
&& ((val & 0xfffffe00) != 0xfffffe00))
|
{
|
{
|
Line 4651... |
Line 4645... |
char* ptemp;
|
char* ptemp;
|
int i=0;
|
int i=0;
|
struct s3_score_it inst_expand[2];
|
struct s3_score_it inst_expand[2];
|
struct s3_score_it inst_main;
|
struct s3_score_it inst_main;
|
|
|
|
memset (inst_expand, 0, sizeof inst_expand);
|
s3_skip_whitespace (str);
|
s3_skip_whitespace (str);
|
if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
|
if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL
|
|| s3_skip_past_comma (&str) == (int) s3_FAIL )
|
|| s3_skip_past_comma (&str) == (int) s3_FAIL )
|
return;
|
return;
|
ptemp =str;
|
ptemp =str;
|
while(*ptemp!=0)
|
while(*ptemp!=0)
|
{
|
{
|
keep_data[i]=*ptemp;
|
keep_data[i] = *ptemp;
|
i++;
|
i++;
|
ptemp++;
|
ptemp++;
|
}
|
}
|
|
|
keep_data[i]=0;
|
keep_data[i]=0;
|
|
|
if ( s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
|
if ( s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL
|
|| s3_end_of_line (str) == (int) s3_FAIL)
|
|| s3_end_of_line (str) == (int) s3_FAIL)
|
return ;
|
return ;
|
|
|
else if (s3_inst.reloc.exp.X_add_symbol == 0)
|
else if (s3_inst.reloc.exp.X_add_symbol == 0)
|
{
|
{
|
s3_inst.error = _("lacking label ");
|
s3_inst.error = _("lacking label ");
|
return;
|
return;
|
}
|
}
|
Line 4743... |
Line 4739... |
|
|
/* Adjust instruction opcode and to be relaxed instruction opcode. */
|
/* Adjust instruction opcode and to be relaxed instruction opcode. */
|
inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
|
inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type));
|
|
|
for (i = 0; i < 2; i++)
|
for (i = 0; i < 2; i++)
|
inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction , s3_GET_INSN_CLASS (inst_expand[i].type));
|
inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction ,
|
|
s3_GET_INSN_CLASS (inst_expand[i].type));
|
/* Check data dependency. */
|
/* Check data dependency. */
|
s3_handle_dependency (&inst_main);
|
s3_handle_dependency (&inst_main);
|
/* Start a new frag if frag_now is not empty. */
|
/* Start a new frag if frag_now is not empty. */
|
if (frag_now_fix () != 0)
|
if (frag_now_fix () != 0)
|
{
|
{
|
Line 5789... |
Line 5786... |
int maybe_text;
|
int maybe_text;
|
|
|
/* Generate a .pdr section. */
|
/* Generate a .pdr section. */
|
segT saved_seg = now_seg;
|
segT saved_seg = now_seg;
|
subsegT saved_subseg = now_subseg;
|
subsegT saved_subseg = now_subseg;
|
valueT dot;
|
|
expressionS exp;
|
expressionS exp;
|
char *fragp;
|
char *fragp;
|
|
|
if (!is_end_of_line[(unsigned char)*input_line_pointer])
|
if (!is_end_of_line[(unsigned char)*input_line_pointer])
|
{
|
{
|
Line 5840... |
Line 5836... |
(s3_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
|
(s3_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
|
(s3_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s3_cur_proc_ptr->pc_reg == 0xdeafbeaf));
|
(s3_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s3_cur_proc_ptr->pc_reg == 0xdeafbeaf));
|
|
|
else
|
else
|
{
|
{
|
dot = frag_now_fix ();
|
(void) frag_now_fix ();
|
gas_assert (s3_pdr_seg);
|
gas_assert (s3_pdr_seg);
|
subseg_set (s3_pdr_seg, 0);
|
subseg_set (s3_pdr_seg, 0);
|
/* Write the symbol. */
|
/* Write the symbol. */
|
exp.X_op = O_symbol;
|
exp.X_op = O_symbol;
|
exp.X_add_symbol = p;
|
exp.X_add_symbol = p;
|
Line 6939... |
Line 6935... |
{
|
{
|
fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
|
fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype);
|
fragp->fr_fix = 6;
|
fragp->fr_fix = 6;
|
return 2;
|
return 2;
|
}
|
}
|
|
|
else
|
else
|
{
|
{
|
/* Never relax. Modify fr_opcode to NULL to verify it's value in
|
/* Never relax. Modify fr_opcode to NULL to verify it's value in
|
md_apply_fix. */
|
md_apply_fix. */
|
fragp->fr_opcode = NULL;
|
fragp->fr_opcode = NULL;
|
Line 7403... |
Line 7398... |
{
|
{
|
static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */
|
static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */
|
arelent *reloc;
|
arelent *reloc;
|
bfd_reloc_code_real_type code;
|
bfd_reloc_code_real_type code;
|
char *type;
|
char *type;
|
fragS *f;
|
|
symbolS *s;
|
|
expressionS e;
|
|
|
|
reloc = retval[0] = xmalloc (sizeof (arelent));
|
reloc = retval[0] = xmalloc (sizeof (arelent));
|
retval[1] = NULL;
|
retval[1] = NULL;
|
|
|
reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
|
reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
|
Line 7444... |
Line 7436... |
retval[2] = NULL;
|
retval[2] = NULL;
|
retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
|
retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
|
*retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
|
*retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
|
retval[1]->address = (reloc->address + s3_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
|
retval[1]->address = (reloc->address + s3_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
|
|
|
f = fixp->fx_frag;
|
|
s = f->fr_symbol;
|
|
e = s->sy_value;
|
|
|
|
retval[1]->addend = 0;
|
retval[1]->addend = 0;
|
retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
|
retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
|
gas_assert (retval[1]->howto != NULL);
|
gas_assert (retval[1]->howto != NULL);
|
|
|
fixp->fx_r_type = BFD_RELOC_HI16_S;
|
fixp->fx_r_type = BFD_RELOC_HI16_S;
|