if (bpf_has_sdiv == -1)
bpf_has_sdiv = (bpf_isa >= ISA_V4);
+ if (bpf_has_smov == -1)
+ bpf_has_smov = (bpf_isa >= ISA_V4);
+
/* Disable -fstack-protector as it is not supported in BPF. */
if (flag_stack_protect)
{
DONE;
})
+;; ISA V4 introduces sign-extending move and load operations.
+
+(define_insn "*extendsidi2"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,q")))]
+ "bpf_has_smov"
+ "@
+ {movs\t%0,%1,32|%0 = (s32) %1}
+ {ldxsw\t%0,%1|%0 = *(s32 *) (%1)}"
+ [(set_attr "type" "alu,ldx")])
+
+(define_insn "extendhidi2"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,q")))]
+ "bpf_has_smov"
+ "@
+ {movs\t%0,%1,16|%0 = (s16) %1}
+ {ldxsh\t%0,%1|%0 = *(s16 *) (%1)}"
+ [(set_attr "type" "alu,ldx")])
+
+(define_insn "extendqidi2"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,q")))]
+ "bpf_has_smov"
+ "@
+ {movs\t%0,%1,8|%0 = (s8) %1}
+ {ldxsb\t%0,%1|%0 = *(s8 *) (%1)}"
+ [(set_attr "type" "alu,ldx")])
+
+(define_insn "extendsisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:SI 1 "register_operand" "r")))]
+ "bpf_has_smov"
+ "{movs32\t%0,%1,32|%w0 = (s32) %w1}"
+ [(set_attr "type" "alu")])
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
+ "bpf_has_smov"
+ "{movs32\t%0,%1,16|%w0 = (s16) %w1}"
+ [(set_attr "type" "alu")])
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
+ "bpf_has_smov"
+ "{movs32\t%0,%1,8|%w0 = (s8) %w1}"
+ [(set_attr "type" "alu")])
+
;;;; Data movement
(define_mode_iterator MM [QI HI SI DI SF DF])
Target Var(bpf_has_sdiv) Init(-1)
Enable signed division and modulus instructions.
+msmov
+Target Var(bpf_has_smov) Init(-1)
+Enable signed move and memory load instructions.
+
mcpu=
Target RejectNegative Joined Var(bpf_isa) Enum(bpf_isa) Init(ISA_V4)
@emph{eBPF Options}
@gccoptlist{-mbig-endian -mlittle-endian
-mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re -mjmpext
--mjmp32 -malu32 -mv3-atomics -mbswap -msdiv -mcpu=@var{version}
+-mjmp32 -malu32 -mv3-atomics -mbswap -msdiv -msmov -mcpu=@var{version}
-masm=@var{dialect}}
@emph{FR30 Options}
Enable or disable signed division and modulus instructions. Enabled for
CPU v4 and above.
+@opindex msmov
+@item -msmov
+@itemx -mno-smov
+Enable or disable sign-extending move and memory load instructions.
+Enabled for CPU v4 and above.
+
@opindex mcpu
@item -mcpu=@var{version}
This specifies which version of the eBPF ISA to target. Newer versions
@itemize @minus
@item Byte swap instructions, as in @option{-mbswap}
@item Signed division and modulus instructions, as in @option{-msdiv}
+@item Sign-extending move and memory load instructions, as in @option{-msmov}
@end itemize
@end table
--- /dev/null
+/* Check ISA V4 signed load instructions. */
+/* { dg-do compile } */
+/* { dg-options "-mcpu=v4 -O2" } */
+
+long foo (char *p1, short *p2, int *p3)
+{
+ long x = *p1;
+ long y = *p2;
+ long z = *p3;
+
+ return x + y + z;
+}
+
+/* { dg-final { scan-assembler {ldxsb\t%r.,\[%r.\+-?[0-9]+\]\n} } } */
+/* { dg-final { scan-assembler {ldxsh\t%r.,\[%r.\+-?[0-9]+\]\n} } } */
+/* { dg-final { scan-assembler {ldxsw\t%r.,\[%r.\+-?[0-9]+\]\n} } } */
--- /dev/null
+/* Check ISA V4 signed load instructions (pseudo-C dialect). */
+/* { dg-do compile } */
+/* { dg-options "-mcpu=v4 -O2 -masm=pseudoc" } */
+
+long foo (char *p1, short *p2, int *p3)
+{
+ long x = *p1;
+ long y = *p2;
+ long z = *p3;
+
+ return x + y + z;
+}
+
+/* { dg-final { scan-assembler {r. = \*\(s8 \*\) \(r.\+-?[0-9]+\)\n} } } */
+/* { dg-final { scan-assembler {r. = \*\(s16 \*\) \(r.\+-?[0-9]+\)\n} } } */
+/* { dg-final { scan-assembler {r. = \*\(s32 \*\) \(r.\+-?[0-9]+\)\n} } } */
--- /dev/null
+/* Check signed mov instructions. */
+/* { dg-do compile } */
+/* { dg-options "-mcpu=v4 -O2" } */
+
+long
+foo (char a, short b, int c, unsigned long d)
+{
+ long x = a;
+ long y = b;
+ long z = c;
+ long w = (long) d;
+
+ return x + y + z + w;
+}
+
+/* { dg-final { scan-assembler {movs\t%r.,%r.,8\n} } } */
+/* { dg-final { scan-assembler {movs\t%r.,%r.,16\n} } } */
+/* { dg-final { scan-assembler {movs\t%r.,%r.,32\n} } } */
--- /dev/null
+/* Check signed mov instructions (pseudo-C asm dialect). */
+/* { dg-do compile } */
+/* { dg-options "-mcpu=v4 -O2 -masm=pseudoc" } */
+
+long
+foo (char a, short b, int c, unsigned long d)
+{
+ long x = a;
+ long y = b;
+ long z = c;
+ long w = (long) d;
+
+ return x + y + z + w;
+}
+
+/* { dg-final { scan-assembler {r. = \(s8\) r.\n} } } */
+/* { dg-final { scan-assembler {r. = \(s16\) r.\n} } } */
+/* { dg-final { scan-assembler {r. = \(s32\) r.\n} } } */