mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-12-19 01:19:41 +08:00
LoongArch/GAS: Add support for branch relaxation
For the instructions of R_LARCH_B16/B21, if the immediate overflow,
add a B instruction and R_LARCH_B26 relocation.
For example:
.L1
...
blt $t0, $t1, .L1
R_LARCH_B16
change to:
.L1
...
bge $t0, $t1, .L2
b .L1
R_LARCH_B26
.L2
This commit is contained in:
committed by
liuzhensong
parent
9847ba8f08
commit
1fb3cdd87e
@@ -106,6 +106,16 @@ const char *md_shortopts = "O::g::G:";
|
||||
|
||||
static const char default_arch[] = DEFAULT_ARCH;
|
||||
|
||||
/* The lowest 4-bit is the bytes of instructions. */
|
||||
#define RELAX_BRANCH_16 0xc0000014
|
||||
#define RELAX_BRANCH_21 0xc0000024
|
||||
#define RELAX_BRANCH_26 0xc0000048
|
||||
|
||||
#define RELAX_BRANCH(x) \
|
||||
(((x) & 0xf0000000) == 0xc0000000)
|
||||
#define RELAX_BRANCH_ENCODE(x) \
|
||||
(BFD_RELOC_LARCH_B16 == (x) ? RELAX_BRANCH_16 : RELAX_BRANCH_21)
|
||||
|
||||
enum options
|
||||
{
|
||||
OPTION_IGNORE = OPTION_MD_BASE,
|
||||
@@ -953,11 +963,22 @@ append_fixed_insn (struct loongarch_cl_insn *insn)
|
||||
move_insn (insn, frag_now, f - frag_now->fr_literal);
|
||||
}
|
||||
|
||||
/* Add instructions based on the worst-case scenario firstly. */
|
||||
static void
|
||||
append_relaxed_branch_insn (struct loongarch_cl_insn *insn, int max_chars,
|
||||
int var, relax_substateT subtype, symbolS *symbol, offsetT offset)
|
||||
{
|
||||
frag_grow (max_chars);
|
||||
move_insn (insn, frag_now, frag_more (0) - frag_now->fr_literal);
|
||||
frag_var (rs_machine_dependent, max_chars, var,
|
||||
subtype, symbol, offset, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
append_fixp_and_insn (struct loongarch_cl_insn *ip)
|
||||
{
|
||||
reloc_howto_type *howto;
|
||||
bfd_reloc_code_real_type reloc_type;
|
||||
bfd_reloc_code_real_type r_type;
|
||||
struct reloc_info *reloc_info = ip->reloc_info;
|
||||
size_t i;
|
||||
|
||||
@@ -965,14 +986,40 @@ append_fixp_and_insn (struct loongarch_cl_insn *ip)
|
||||
|
||||
for (i = 0; i < ip->reloc_num; i++)
|
||||
{
|
||||
reloc_type = reloc_info[i].type;
|
||||
howto = bfd_reloc_type_lookup (stdoutput, reloc_type);
|
||||
if (howto == NULL)
|
||||
as_fatal (_("no HOWTO loong relocation number %d"), reloc_type);
|
||||
r_type = reloc_info[i].type;
|
||||
|
||||
ip->fixp[i] =
|
||||
fix_new_exp (ip->frag, ip->where, bfd_get_reloc_size (howto),
|
||||
&reloc_info[i].value, FALSE, reloc_type);
|
||||
if (r_type != BFD_RELOC_UNUSED)
|
||||
{
|
||||
|
||||
gas_assert (&(reloc_info[i].value));
|
||||
if (BFD_RELOC_LARCH_B16 == r_type || BFD_RELOC_LARCH_B21 == r_type)
|
||||
{
|
||||
int min_bytes = 4; /* One branch instruction. */
|
||||
unsigned max_bytes = 8; /* Branch and jump instructions. */
|
||||
|
||||
if (now_seg == absolute_section)
|
||||
{
|
||||
as_bad (_("relaxable branches not supported in absolute section"));
|
||||
return;
|
||||
}
|
||||
|
||||
append_relaxed_branch_insn (ip, max_bytes, min_bytes,
|
||||
RELAX_BRANCH_ENCODE (r_type),
|
||||
reloc_info[i].value.X_add_symbol,
|
||||
reloc_info[i].value.X_add_number);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
howto = bfd_reloc_type_lookup (stdoutput, r_type);
|
||||
if (howto == NULL)
|
||||
as_fatal (_("no HOWTO loong relocation number %d"), r_type);
|
||||
|
||||
ip->fixp[i] = fix_new_exp (ip->frag, ip->where,
|
||||
bfd_get_reloc_size (howto),
|
||||
&reloc_info[i].value, FALSE, r_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ip->insn_length < ip->relax_max_length)
|
||||
@@ -1487,14 +1534,6 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
loongarch_relax_frag (asection *sec ATTRIBUTE_UNUSED,
|
||||
fragS *fragp ATTRIBUTE_UNUSED,
|
||||
long stretch ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
|
||||
asection *segtype ATTRIBUTE_UNUSED)
|
||||
@@ -1526,30 +1565,6 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
|
||||
return reloc;
|
||||
}
|
||||
|
||||
/* Convert a machine dependent frag. */
|
||||
void
|
||||
md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec ATTRIBUTE_UNUSED,
|
||||
fragS *fragp)
|
||||
{
|
||||
expressionS exp;
|
||||
exp.X_op = O_symbol;
|
||||
exp.X_add_symbol = fragp->fr_symbol;
|
||||
exp.X_add_number = fragp->fr_offset;
|
||||
bfd_byte *buf = (bfd_byte *)fragp->fr_literal + fragp->fr_fix;
|
||||
|
||||
fixS *fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
|
||||
4, &exp, false, fragp->fr_subtype);
|
||||
buf += 4;
|
||||
|
||||
fixp->fx_file = fragp->fr_file;
|
||||
fixp->fx_line = fragp->fr_line;
|
||||
fragp->fr_fix += fragp->fr_var;
|
||||
|
||||
gas_assert (fragp->fr_next == NULL
|
||||
|| (fragp->fr_next->fr_address - fragp->fr_address
|
||||
== fragp->fr_fix));
|
||||
}
|
||||
|
||||
/* Standard calling conventions leave the CFA at SP on entry. */
|
||||
void
|
||||
loongarch_cfi_frame_initial_instructions (void)
|
||||
@@ -1775,3 +1790,142 @@ loongarch_elf_final_processing (void)
|
||||
{
|
||||
elf_elfheader (stdoutput)->e_flags = LARCH_opts.ase_abi;
|
||||
}
|
||||
|
||||
/* Compute the length of a branch sequence, and adjust the stored length
|
||||
accordingly. If FRAGP is NULL, the worst-case length is returned. */
|
||||
static unsigned
|
||||
loongarch_relaxed_branch_length (fragS *fragp, asection *sec, int update)
|
||||
{
|
||||
int length = 4;
|
||||
|
||||
if (!fragp)
|
||||
return 8;
|
||||
|
||||
if (fragp->fr_symbol != NULL
|
||||
&& S_IS_DEFINED (fragp->fr_symbol)
|
||||
&& !S_IS_WEAK (fragp->fr_symbol)
|
||||
&& sec == S_GET_SEGMENT (fragp->fr_symbol))
|
||||
{
|
||||
offsetT val = S_GET_VALUE (fragp->fr_symbol) + fragp->fr_offset;
|
||||
|
||||
val -= fragp->fr_address + fragp->fr_fix;
|
||||
|
||||
if (RELAX_BRANCH_16 == fragp->fr_subtype
|
||||
&& OUT_OF_RANGE (val, 16, 2))
|
||||
{
|
||||
length = 8;
|
||||
if (update)
|
||||
fragp->fr_subtype = RELAX_BRANCH_26;
|
||||
}
|
||||
|
||||
if (RELAX_BRANCH_21 == fragp->fr_subtype
|
||||
&& OUT_OF_RANGE (val, 21, 2))
|
||||
{
|
||||
length = 8;
|
||||
if (update)
|
||||
fragp->fr_subtype = RELAX_BRANCH_26;
|
||||
}
|
||||
|
||||
if (RELAX_BRANCH_26 == fragp->fr_subtype)
|
||||
length = 8;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
int
|
||||
loongarch_relax_frag (asection *sec ATTRIBUTE_UNUSED,
|
||||
fragS *fragp ATTRIBUTE_UNUSED,
|
||||
long stretch ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (RELAX_BRANCH (fragp->fr_subtype))
|
||||
{
|
||||
offsetT old_var = fragp->fr_var;
|
||||
fragp->fr_var = loongarch_relaxed_branch_length (fragp, sec, true);
|
||||
return fragp->fr_var - old_var;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Expand far branches to multi-instruction sequences.
|
||||
Branch instructions:
|
||||
beq, bne, blt, bgt, bltz, bgtz, ble, bge, blez, bgez
|
||||
bltu, bgtu, bleu, bgeu
|
||||
beqz, bnez, bceqz, bcnez. */
|
||||
|
||||
static void
|
||||
loongarch_convert_frag_branch (fragS *fragp)
|
||||
{
|
||||
bfd_byte *buf;
|
||||
expressionS exp;
|
||||
fixS *fixp;
|
||||
insn_t insn;
|
||||
|
||||
buf = (bfd_byte *)fragp->fr_literal + fragp->fr_fix;
|
||||
|
||||
exp.X_op = O_symbol;
|
||||
exp.X_add_symbol = fragp->fr_symbol;
|
||||
exp.X_add_number = fragp->fr_offset;
|
||||
|
||||
gas_assert ((fragp->fr_subtype & 0xf) == fragp->fr_var);
|
||||
|
||||
/* blt $t0, $t1, .L1
|
||||
nop
|
||||
change to:
|
||||
bge $t0, $t1, .L2
|
||||
b .L1
|
||||
.L2:
|
||||
nop */
|
||||
switch (fragp->fr_subtype)
|
||||
{
|
||||
case RELAX_BRANCH_26:
|
||||
insn = bfd_getl32 (buf);
|
||||
/* Invert the branch condition. */
|
||||
if (LARCH_FLOAT_BRANCH == (insn & LARCH_BRANCH_OPCODE_MASK))
|
||||
insn ^= LARCH_FLOAT_BRANCH_INVERT_BIT;
|
||||
else
|
||||
insn ^= LARCH_BRANCH_INVERT_BIT;
|
||||
insn |= ENCODE_BRANCH16_IMM (8); /* Set target to PC + 8. */
|
||||
bfd_putl32 (insn, buf);
|
||||
buf += 4;
|
||||
|
||||
/* Add the B instruction and jump to the original target. */
|
||||
bfd_putl32 (LARCH_B, buf);
|
||||
fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
|
||||
4, &exp, false, BFD_RELOC_LARCH_B26);
|
||||
buf += 4;
|
||||
break;
|
||||
case RELAX_BRANCH_21:
|
||||
fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
|
||||
4, &exp, false, BFD_RELOC_LARCH_B21);
|
||||
buf += 4;
|
||||
break;
|
||||
case RELAX_BRANCH_16:
|
||||
fixp = fix_new_exp (fragp, buf - (bfd_byte *)fragp->fr_literal,
|
||||
4, &exp, false, BFD_RELOC_LARCH_B16);
|
||||
buf += 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
fixp->fx_file = fragp->fr_file;
|
||||
fixp->fx_line = fragp->fr_line;
|
||||
|
||||
gas_assert (buf == (bfd_byte *)fragp->fr_literal
|
||||
+ fragp->fr_fix + fragp->fr_var);
|
||||
|
||||
fragp->fr_fix += fragp->fr_var;
|
||||
}
|
||||
|
||||
/* Relax a machine dependent frag. This returns the amount by which
|
||||
the current size of the frag should change. */
|
||||
|
||||
void
|
||||
md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec ATTRIBUTE_UNUSED,
|
||||
fragS *fragp)
|
||||
{
|
||||
gas_assert (RELAX_BRANCH (fragp->fr_subtype));
|
||||
loongarch_convert_frag_branch (fragp);
|
||||
}
|
||||
|
||||
64
gas/testsuite/gas/loongarch/la_branch_relax_1.d
Normal file
64
gas/testsuite/gas/loongarch/la_branch_relax_1.d
Normal file
@@ -0,0 +1,64 @@
|
||||
#as:
|
||||
#objdump: -dr
|
||||
|
||||
.*:[ ]+file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0* <.L1>:
|
||||
[ ]+...
|
||||
[ ]+48d158:[ ]+5c00098d[ ]+bne[ ]+\$t0, \$t1, 8[ ]+# 48d160 <.L1\+0x48d160>
|
||||
[ ]+48d15c:[ ]+532ea7ed[ ]+b[ ]+-4772188[ ]+# 0 <.L1>
|
||||
[ ]+48d15c: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d160:[ ]+5800098d[ ]+beq[ ]+\$t0, \$t1, 8[ ]+# 48d168 <.L1\+0x48d168>
|
||||
[ ]+48d164:[ ]+532e9fed[ ]+b[ ]+-4772196[ ]+# 0 <.L1>
|
||||
[ ]+48d164: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d168:[ ]+6400098d[ ]+bge[ ]+\$t0, \$t1, 8[ ]+# 48d170 <.L1\+0x48d170>
|
||||
[ ]+48d16c:[ ]+532e97ed[ ]+b[ ]+-4772204[ ]+# 0 <.L1>
|
||||
[ ]+48d16c: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d170:[ ]+640009ac[ ]+bge[ ]+\$t1, \$t0, 8[ ]+# 48d178 <.L1\+0x48d178>
|
||||
[ ]+48d174:[ ]+532e8fed[ ]+b[ ]+-4772212[ ]+# 0 <.L1>
|
||||
[ ]+48d174: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d178:[ ]+64000980[ ]+bgez[ ]+\$t0, 8[ ]+# 48d180 <.L1\+0x48d180>
|
||||
[ ]+48d17c:[ ]+532e87ed[ ]+b[ ]+-4772220[ ]+# 0 <.L1>
|
||||
[ ]+48d17c: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d180:[ ]+6400080c[ ]+blez[ ]+\$t0, 8[ ]+# 48d188 <.L1\+0x48d188>
|
||||
[ ]+48d184:[ ]+532e7fed[ ]+b[ ]+-4772228[ ]+# 0 <.L1>
|
||||
[ ]+48d184: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d188:[ ]+600009ac[ ]+blt[ ]+\$t1, \$t0, 8[ ]+# 48d190 <.L1\+0x48d190>
|
||||
[ ]+48d18c:[ ]+532e77ed[ ]+b[ ]+-4772236[ ]+# 0 <.L1>
|
||||
[ ]+48d18c: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d190:[ ]+6000098d[ ]+blt[ ]+\$t0, \$t1, 8[ ]+# 48d198 <.L1\+0x48d198>
|
||||
[ ]+48d194:[ ]+532e6fed[ ]+b[ ]+-4772244[ ]+# 0 <.L1>
|
||||
[ ]+48d194: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d198:[ ]+6000080c[ ]+bgtz[ ]+\$t0, 8[ ]+# 48d1a0 <.L1\+0x48d1a0>
|
||||
[ ]+48d19c:[ ]+532e67ed[ ]+b[ ]+-4772252[ ]+# 0 <.L1>
|
||||
[ ]+48d19c: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d1a0:[ ]+60000980[ ]+bltz[ ]+\$t0, 8[ ]+# 48d1a8 <.L1\+0x48d1a8>
|
||||
[ ]+48d1a4:[ ]+532e5fed[ ]+b[ ]+-4772260[ ]+# 0 <.L1>
|
||||
[ ]+48d1a4: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d1a8:[ ]+6c00098d[ ]+bgeu[ ]+\$t0, \$t1, 8[ ]+# 48d1b0 <.L1\+0x48d1b0>
|
||||
[ ]+48d1ac:[ ]+532e57ed[ ]+b[ ]+-4772268[ ]+# 0 <.L1>
|
||||
[ ]+48d1ac: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d1b0:[ ]+6c0009ac[ ]+bgeu[ ]+\$t1, \$t0, 8[ ]+# 48d1b8 <.L1\+0x48d1b8>
|
||||
[ ]+48d1b4:[ ]+532e4fed[ ]+b[ ]+-4772276[ ]+# 0 <.L1>
|
||||
[ ]+48d1b4: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d1b8:[ ]+680009ac[ ]+bltu[ ]+\$t1, \$t0, 8[ ]+# 48d1c0 <.L1\+0x48d1c0>
|
||||
[ ]+48d1bc:[ ]+532e47ed[ ]+b[ ]+-4772284[ ]+# 0 <.L1>
|
||||
[ ]+48d1bc: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d1c0:[ ]+6800098d[ ]+bltu[ ]+\$t0, \$t1, 8[ ]+# 48d1c8 <.L1\+0x48d1c8>
|
||||
[ ]+48d1c4:[ ]+532e3fed[ ]+b[ ]+-4772292[ ]+# 0 <.L1>
|
||||
[ ]+48d1c4: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d1c8:[ ]+44000980[ ]+bnez[ ]+\$t0, 8[ ]+# 48d1d0 <.L1\+0x48d1d0>
|
||||
[ ]+48d1cc:[ ]+532e37ed[ ]+b[ ]+-4772300[ ]+# 0 <.L1>
|
||||
[ ]+48d1cc: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d1d0:[ ]+40000980[ ]+beqz[ ]+\$t0, 8[ ]+# 48d1d8 <.L1\+0x48d1d8>
|
||||
[ ]+48d1d4:[ ]+532e2fed[ ]+b[ ]+-4772308[ ]+# 0 <.L1>
|
||||
[ ]+48d1d4: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d1d8:[ ]+48000900[ ]+bcnez[ ]+\$fcc0, 8[ ]+# 48d1e0 <.L1\+0x48d1e0>
|
||||
[ ]+48d1dc:[ ]+532e27ed[ ]+b[ ]+-4772316[ ]+# 0 <.L1>
|
||||
[ ]+48d1dc: R_LARCH_B26[ ]+.L1
|
||||
[ ]+48d1e0:[ ]+48000800[ ]+bceqz[ ]+\$fcc0, 8[ ]+# 48d1e8 <.L1\+0x48d1e8>
|
||||
[ ]+48d1e4:[ ]+532e1fed[ ]+b[ ]+-4772324[ ]+# 0 <.L1>
|
||||
[ ]+48d1e4: R_LARCH_B26[ ]+.L1
|
||||
33
gas/testsuite/gas/loongarch/la_branch_relax_1.s
Normal file
33
gas/testsuite/gas/loongarch/la_branch_relax_1.s
Normal file
@@ -0,0 +1,33 @@
|
||||
# Instruction and Relocation generating tests
|
||||
|
||||
.L1:
|
||||
.fill 0x123456, 4, 0x0
|
||||
|
||||
# R_LARCH_B16
|
||||
beq $r12, $r13, .L1
|
||||
bne $r12, $r13, .L1
|
||||
|
||||
blt $r12, $r13, .L1
|
||||
bgt $r12, $r13, .L1
|
||||
|
||||
bltz $r12, .L1
|
||||
bgtz $r12, .L1
|
||||
|
||||
ble $r12, $r13, .L1
|
||||
bge $r12, $r13, .L1
|
||||
|
||||
blez $r12, .L1
|
||||
bgez $r12, .L1
|
||||
|
||||
bltu $r12, $r13, .L1
|
||||
bgtu $r12, $r13, .L1
|
||||
|
||||
bleu $r12, $r13, .L1
|
||||
bgeu $r12, $r13, .L1
|
||||
|
||||
# R_LARCH_B21
|
||||
beqz $r12, .L1
|
||||
bnez $r12, .L1
|
||||
|
||||
bceqz $fcc0, .L1
|
||||
bcnez $fcc0, .L1
|
||||
40
gas/testsuite/gas/loongarch/la_branch_relax_2.d
Normal file
40
gas/testsuite/gas/loongarch/la_branch_relax_2.d
Normal file
@@ -0,0 +1,40 @@
|
||||
#as:
|
||||
#objdump: -dr
|
||||
|
||||
.*:[ ]+file format .*
|
||||
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
0* <.L1>:
|
||||
[ ]+...
|
||||
[ ]+20000:[ ]+5a00018d[ ]+beq[ ]+\$t0, \$t1, -131072[ ]+# 0 <.L1>
|
||||
[ ]+20000: R_LARCH_B16[ ]+.L1
|
||||
[ ]+20004:[ ]+5c00098d[ ]+bne[ ]+\$t0, \$t1, 8[ ]+# 2000c <.L1\+0x2000c>
|
||||
[ ]+20008:[ ]+51fffbff[ ]+b[ ]+-131080[ ]+# 0 <.L1>
|
||||
[ ]+20008: R_LARCH_B26[ ]+.L1
|
||||
[ ]+2000c:[ ]+5c00098d[ ]+bne[ ]+\$t0, \$t1, 8[ ]+# 20014 <.L1\+0x20014>
|
||||
[ ]+20010:[ ]+52000000[ ]+b[ ]+131072[ ]+# 40010 <.L2>
|
||||
[ ]+20010: R_LARCH_B26[ ]+.L2
|
||||
[ ]+20014:[ ]+59fffd8d[ ]+beq[ ]+\$t0, \$t1, 131068[ ]+# 40010 <.L2>
|
||||
[ ]+20014: R_LARCH_B16[ ]+.L2
|
||||
[ ]+...
|
||||
0*40010 <.L2>:
|
||||
[ ]+...
|
||||
[ ]+440010:[ ]+40000190[ ]+beqz[ ]+\$t0, -4194304[ ]+# 40010 <.L2>
|
||||
[ ]+440010: R_LARCH_B21[ ]+.L2
|
||||
[ ]+440014:[ ]+44000980[ ]+bnez[ ]+\$t0, 8[ ]+# 44001c <.L2\+0x40000c>
|
||||
[ ]+440018:[ ]+53fffbef[ ]+b[ ]+-4194312[ ]+# 40010 <.L2>
|
||||
[ ]+440018: R_LARCH_B26[ ]+.L2
|
||||
[ ]+44001c:[ ]+44000980[ ]+bnez[ ]+\$t0, 8[ ]+# 440024 <.L2\+0x400014>
|
||||
[ ]+440020:[ ]+50000010[ ]+b[ ]+4194304[ ]+# 840020 <.L3>
|
||||
[ ]+440020: R_LARCH_B26[ ]+.L3
|
||||
[ ]+440024:[ ]+43fffd8f[ ]+beqz[ ]+\$t0, 4194300[ ]+# 840020 <.L3>
|
||||
[ ]+440024: R_LARCH_B21[ ]+.L3
|
||||
[ ]+...
|
||||
0*840020 <.L3>:
|
||||
[ ]+840020:[ ]+5800018d[ ]+beq[ ]+\$t0, \$t1, 0[ ]+# 840020 <.L3>
|
||||
[ ]+840020: R_LARCH_B16[ ]+.L4
|
||||
0*840024 <.L5>:
|
||||
[ ]+840024:[ ]+40000180[ ]+beqz[ ]+\$t0, 0[ ]+# 840024 <.L5>
|
||||
[ ]+840024: R_LARCH_B21[ ]+.L5
|
||||
23
gas/testsuite/gas/loongarch/la_branch_relax_2.s
Normal file
23
gas/testsuite/gas/loongarch/la_branch_relax_2.s
Normal file
@@ -0,0 +1,23 @@
|
||||
# Immediate boundary value tests
|
||||
|
||||
.L1:
|
||||
.fill 0x8000, 4, 0
|
||||
beq $r12, $r13, .L1 # min imm -0x20000
|
||||
beq $r12, $r13, .L1 # out of range
|
||||
beq $r12, $r13, .L2 # out of range
|
||||
beq $r12, $r13, .L2 # max imm 0x1fffc
|
||||
.fill 0x7ffe, 4, 0
|
||||
.L2:
|
||||
.fill 0x100000, 4, 0
|
||||
beqz $r12, .L2 # min imm -0x400000
|
||||
beqz $r12, .L2 # out of range
|
||||
beqz $r12, .L3 # out of range
|
||||
beqz $r12, .L3 # max imm 0x3ffffc
|
||||
.fill 0xffffe, 4, 0
|
||||
.L3:
|
||||
|
||||
# 0 imm
|
||||
.L4:
|
||||
beq $r12, $r13, .L4
|
||||
.L5:
|
||||
beqz $r12, .L5
|
||||
@@ -29,6 +29,18 @@ extern "C"
|
||||
#endif
|
||||
|
||||
#define LARCH_NOP 0x03400000
|
||||
#define LARCH_B 0x50000000
|
||||
/* BCEQZ/BCNEZ. */
|
||||
#define LARCH_FLOAT_BRANCH 0x48000000
|
||||
#define LARCH_BRANCH_OPCODE_MASK 0xfc000000
|
||||
#define LARCH_BRANCH_INVERT_BIT 0x04000000
|
||||
#define LARCH_FLOAT_BRANCH_INVERT_BIT 0x00000100
|
||||
|
||||
#define ENCODE_BRANCH16_IMM(x) (((x) >> 2) << 10)
|
||||
|
||||
#define OUT_OF_RANGE(value, bits, align) \
|
||||
((value) < (-(1 << ((bits) - 1) << align)) \
|
||||
|| (value) > ((((1 << ((bits) - 1)) - 1) << align)))
|
||||
|
||||
typedef uint32_t insn_t;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user