Lines 761-766
enum fix_vr4120_class {
Link Here
|
761 |
NUM_FIX_VR4120_CLASSES |
761 |
NUM_FIX_VR4120_CLASSES |
762 |
}; |
762 |
}; |
763 |
|
763 |
|
|
|
764 |
/* ...likewise -mfix-loongson2f-jump. */ |
765 |
static int mips_fix_loongson2f_jump; |
766 |
|
767 |
/* ...likewise -mfix-loongson2f-nop. */ |
768 |
static int mips_fix_loongson2f_nop; |
769 |
|
770 |
/* True if -mfix-loongson2f-nop or -mfix-loongson2f-jump passed */ |
771 |
static int mips_fix_loongson2f; |
772 |
|
764 |
/* Given two FIX_VR4120_* values X and Y, bit Y of element X is set if |
773 |
/* Given two FIX_VR4120_* values X and Y, bit Y of element X is set if |
765 |
there must be at least one other instruction between an instruction |
774 |
there must be at least one other instruction between an instruction |
766 |
of type X and an instruction of type Y. */ |
775 |
of type X and an instruction of type Y. */ |
Lines 1918-1923
md_begin (void)
Link Here
|
1918 |
if (nop_insn.insn_mo == NULL && strcmp (name, "nop") == 0) |
1927 |
if (nop_insn.insn_mo == NULL && strcmp (name, "nop") == 0) |
1919 |
{ |
1928 |
{ |
1920 |
create_insn (&nop_insn, mips_opcodes + i); |
1929 |
create_insn (&nop_insn, mips_opcodes + i); |
|
|
1930 |
if (mips_fix_loongson2f_nop) |
1931 |
nop_insn.insn_opcode = LOONGSON2F_NOP_INSN; |
1921 |
nop_insn.fixed_p = 1; |
1932 |
nop_insn.fixed_p = 1; |
1922 |
} |
1933 |
} |
1923 |
} |
1934 |
} |
Lines 2731-2736
nops_for_insn_or_target (const struct mips_cl_insn *history,
Link Here
|
2731 |
return nops; |
2742 |
return nops; |
2732 |
} |
2743 |
} |
2733 |
|
2744 |
|
|
|
2745 |
static void |
2746 |
macro_build (expressionS *ep, const char *name, const char *fmt, ...); |
2747 |
|
2748 |
static void fix_loongson2f_nop(struct mips_cl_insn *ip) |
2749 |
{ |
2750 |
/* Fix NOP issue: Replace nops by "or at,at,zero" */ |
2751 |
if (strcmp(ip->insn_mo->name, "nop") == 0) |
2752 |
ip->insn_opcode = LOONGSON2F_NOP_INSN; |
2753 |
} |
2754 |
|
2755 |
static void fix_loongson2f_jump(struct mips_cl_insn *ip) |
2756 |
{ |
2757 |
|
2758 |
/* Fix Jump Issue: Eliminate instruction fetch from outside 256M region |
2759 |
* jr target pc &= 'hffff_ffff_cfff_ffff |
2760 |
*/ |
2761 |
if (strcmp(ip->insn_mo->name, "j") == 0 |
2762 |
|| strcmp(ip->insn_mo->name, "jr") == 0 |
2763 |
|| strcmp(ip->insn_mo->name, "jalr") == 0) |
2764 |
{ |
2765 |
int sreg; |
2766 |
expressionS ep; |
2767 |
|
2768 |
if (! mips_opts.at) |
2769 |
return; |
2770 |
|
2771 |
sreg = EXTRACT_OPERAND (RS, *ip); |
2772 |
if (sreg == ZERO || sreg == KT0 || sreg == KT1 || sreg == ATREG) |
2773 |
return; |
2774 |
|
2775 |
ep.X_op = O_constant; |
2776 |
ep.X_add_number = 0xcfff0000; |
2777 |
macro_build (&ep, "lui", "t,u", ATREG, BFD_RELOC_HI16); |
2778 |
ep.X_add_number = 0xffff; |
2779 |
macro_build (&ep, "ori", "t,r,i", ATREG, ATREG, BFD_RELOC_LO16); |
2780 |
macro_build (NULL, "and", "d,v,t", sreg, sreg, ATREG); |
2781 |
} |
2782 |
} |
2783 |
|
2784 |
static void fix_loongson2f(struct mips_cl_insn *ip) |
2785 |
{ |
2786 |
if (mips_fix_loongson2f_nop) |
2787 |
fix_loongson2f_nop(ip); |
2788 |
if (mips_fix_loongson2f_jump) |
2789 |
fix_loongson2f_jump(ip); |
2790 |
} |
2791 |
|
2734 |
/* Output an instruction. IP is the instruction information. |
2792 |
/* Output an instruction. IP is the instruction information. |
2735 |
ADDRESS_EXPR is an operand of the instruction to be used with |
2793 |
ADDRESS_EXPR is an operand of the instruction to be used with |
2736 |
RELOC_TYPE. */ |
2794 |
RELOC_TYPE. */ |
Lines 2744-2749
append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
Link Here
|
2744 |
bfd_boolean relaxed_branch = FALSE; |
2802 |
bfd_boolean relaxed_branch = FALSE; |
2745 |
segment_info_type *si = seg_info (now_seg); |
2803 |
segment_info_type *si = seg_info (now_seg); |
2746 |
|
2804 |
|
|
|
2805 |
if (mips_fix_loongson2f) |
2806 |
fix_loongson2f(ip); |
2807 |
|
2747 |
/* Mark instruction labels in mips16 mode. */ |
2808 |
/* Mark instruction labels in mips16 mode. */ |
2748 |
mips16_mark_labels (); |
2809 |
mips16_mark_labels (); |
2749 |
|
2810 |
|
Lines 11220-11225
enum options
Link Here
|
11220 |
OPTION_MNO_7000_HILO_FIX, |
11281 |
OPTION_MNO_7000_HILO_FIX, |
11221 |
OPTION_FIX_24K, |
11282 |
OPTION_FIX_24K, |
11222 |
OPTION_NO_FIX_24K, |
11283 |
OPTION_NO_FIX_24K, |
|
|
11284 |
OPTION_FIX_LOONGSON2F_JUMP, |
11285 |
OPTION_NO_FIX_LOONGSON2F_JUMP, |
11286 |
OPTION_FIX_LOONGSON2F_NOP, |
11287 |
OPTION_NO_FIX_LOONGSON2F_NOP, |
11223 |
OPTION_FIX_VR4120, |
11288 |
OPTION_FIX_VR4120, |
11224 |
OPTION_NO_FIX_VR4120, |
11289 |
OPTION_NO_FIX_VR4120, |
11225 |
OPTION_FIX_VR4130, |
11290 |
OPTION_FIX_VR4130, |
Lines 11308-11313
struct option md_longopts[] =
Link Here
|
11308 |
{"mfix7000", no_argument, NULL, OPTION_M7000_HILO_FIX}, |
11373 |
{"mfix7000", no_argument, NULL, OPTION_M7000_HILO_FIX}, |
11309 |
{"no-fix-7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX}, |
11374 |
{"no-fix-7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX}, |
11310 |
{"mno-fix7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX}, |
11375 |
{"mno-fix7000", no_argument, NULL, OPTION_MNO_7000_HILO_FIX}, |
|
|
11376 |
{"mfix-loongson2f-jump", no_argument, NULL, OPTION_FIX_LOONGSON2F_JUMP}, |
11377 |
{"mno-fix-loongson2f-jump", no_argument, NULL, OPTION_NO_FIX_LOONGSON2F_JUMP}, |
11378 |
{"mfix-loongson2f-nop", no_argument, NULL, OPTION_FIX_LOONGSON2F_NOP}, |
11379 |
{"mno-fix-loongson2f-nop", no_argument, NULL, OPTION_NO_FIX_LOONGSON2F_NOP}, |
11311 |
{"mfix-vr4120", no_argument, NULL, OPTION_FIX_VR4120}, |
11380 |
{"mfix-vr4120", no_argument, NULL, OPTION_FIX_VR4120}, |
11312 |
{"mno-fix-vr4120", no_argument, NULL, OPTION_NO_FIX_VR4120}, |
11381 |
{"mno-fix-vr4120", no_argument, NULL, OPTION_NO_FIX_VR4120}, |
11313 |
{"mfix-vr4130", no_argument, NULL, OPTION_FIX_VR4130}, |
11382 |
{"mfix-vr4130", no_argument, NULL, OPTION_FIX_VR4130}, |
Lines 11575-11580
md_parse_option (int c, char *arg)
Link Here
|
11575 |
mips_fix_24k = 0; |
11644 |
mips_fix_24k = 0; |
11576 |
break; |
11645 |
break; |
11577 |
|
11646 |
|
|
|
11647 |
case OPTION_FIX_LOONGSON2F_JUMP: |
11648 |
mips_fix_loongson2f_jump = 1; |
11649 |
break; |
11650 |
|
11651 |
case OPTION_NO_FIX_LOONGSON2F_JUMP: |
11652 |
mips_fix_loongson2f_jump = 0; |
11653 |
break; |
11654 |
|
11655 |
case OPTION_FIX_LOONGSON2F_NOP: |
11656 |
mips_fix_loongson2f_nop = 1; |
11657 |
break; |
11658 |
|
11659 |
case OPTION_NO_FIX_LOONGSON2F_NOP: |
11660 |
mips_fix_loongson2f_nop = 0; |
11661 |
break; |
11662 |
|
11578 |
case OPTION_FIX_VR4120: |
11663 |
case OPTION_FIX_VR4120: |
11579 |
mips_fix_vr4120 = 1; |
11664 |
mips_fix_vr4120 = 1; |
11580 |
break; |
11665 |
break; |
Lines 11789-11794
md_parse_option (int c, char *arg)
Link Here
|
11789 |
return 0; |
11874 |
return 0; |
11790 |
} |
11875 |
} |
11791 |
|
11876 |
|
|
|
11877 |
mips_fix_loongson2f = mips_fix_loongson2f_nop || mips_fix_loongson2f_jump; |
11878 |
|
11792 |
return 1; |
11879 |
return 1; |
11793 |
} |
11880 |
} |
11794 |
|
11881 |
|
Lines 14794-14799
void
Link Here
|
14794 |
mips_handle_align (fragS *fragp) |
14881 |
mips_handle_align (fragS *fragp) |
14795 |
{ |
14882 |
{ |
14796 |
char *p; |
14883 |
char *p; |
|
|
14884 |
int bytes, size, excess; |
14885 |
valueT opcode; |
14797 |
|
14886 |
|
14798 |
if (fragp->fr_type != rs_align_code) |
14887 |
if (fragp->fr_type != rs_align_code) |
14799 |
return; |
14888 |
return; |
Lines 14801-14817
mips_handle_align (fragS *fragp)
Link Here
|
14801 |
p = fragp->fr_literal + fragp->fr_fix; |
14890 |
p = fragp->fr_literal + fragp->fr_fix; |
14802 |
if (*p) |
14891 |
if (*p) |
14803 |
{ |
14892 |
{ |
14804 |
int bytes; |
14893 |
opcode = mips16_nop_insn.insn_opcode; |
|
|
14894 |
size = 2; |
14895 |
} |
14896 |
else |
14897 |
{ |
14898 |
opcode = nop_insn.insn_opcode; |
14899 |
size = 4; |
14900 |
} |
14805 |
|
14901 |
|
14806 |
bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; |
14902 |
bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix; |
14807 |
if (bytes & 1) |
14903 |
excess = bytes % size; |
14808 |
{ |
14904 |
if (excess != 0) |
14809 |
*p++ = 0; |
14905 |
{ |
14810 |
fragp->fr_fix++; |
14906 |
/* If we're not inserting a whole number of instructions, pad the |
14811 |
} |
14907 |
end of the fixed part of the frag with zeros */ |
14812 |
md_number_to_chars (p, mips16_nop_insn.insn_opcode, 2); |
14908 |
memset (p, 0, excess); |
14813 |
fragp->fr_var = 2; |
14909 |
p += excess; |
|
|
14910 |
fragp->fr_fix += excess; |
14814 |
} |
14911 |
} |
|
|
14912 |
md_number_to_chars (p, opcode, size); |
14913 |
fragp->fr_var = size; |
14815 |
} |
14914 |
} |
14816 |
|
14915 |
|
14817 |
static void |
14916 |
static void |
Lines 15523-15528
MIPS options:\n\
Link Here
|
15523 |
-mmt generate MT instructions\n\ |
15622 |
-mmt generate MT instructions\n\ |
15524 |
-mno-mt do not generate MT instructions\n")); |
15623 |
-mno-mt do not generate MT instructions\n")); |
15525 |
fprintf (stream, _("\ |
15624 |
fprintf (stream, _("\ |
|
|
15625 |
-mfix-loongson2f-jump work around Loongson2F JUMP instructions\ |
15626 |
-mfix-loongson2f-nop work around Loongson2F NOP errata\n\ |
15526 |
-mfix-vr4120 work around certain VR4120 errata\n\ |
15627 |
-mfix-vr4120 work around certain VR4120 errata\n\ |
15527 |
-mfix-vr4130 work around VR4130 mflo/mfhi errata\n\ |
15628 |
-mfix-vr4130 work around VR4130 mflo/mfhi errata\n\ |
15528 |
-mfix-24k insert a nop after ERET and DERET instructions\n\ |
15629 |
-mfix-24k insert a nop after ERET and DERET instructions\n\ |