(set (match_dup 1)
(match_operand:AMO 2 "nonmemory_operand" "0"))]
"bpf_has_v3_atomics"
- "{axchg<msuffix>\t%1,%0|%w0 = xchg<pcaxsuffix>(%1, %w0)}")
+ "{axchg<msuffix>\t%1,%0|%w0 = xchg<pcaxsuffix>(%M1, %w0)}")
;; The eBPF atomic-compare-and-exchange instruction has the form
;; acmp [%dst+offset], %src
(match_operand:AMO 3 "register_operand")] ;; desired
UNSPEC_ACMP))]
"bpf_has_v3_atomics"
- "{acmp<msuffix>\t%1,%3|%w0 = cmpxchg<pcaxsuffix>(%1, %w0, %w3)}")
+ "{acmp<msuffix>\t%1,%3|%w0 = cmpxchg<pcaxsuffix>(%M1, %w0, %w3)}")
}
}
+/* Variable defined to implement 'M' operand modifier for the special cases
+ where the parentheses should not be printed surrounding a memory address
+ operand. */
+static bool no_parentheses_mem_operand;
+
/* Print an instruction operand. This function is called in the macro
PRINT_OPERAND defined in bpf.h */
bpf_print_register (file, op, code);
break;
case MEM:
+ no_parentheses_mem_operand = (code == 'M');
output_address (GET_MODE (op), XEXP (op, 0));
break;
case CONST_DOUBLE:
}
}
+#define PAREN_OPEN (asm_dialect == ASM_NORMAL ? "[" : no_parentheses_mem_operand ? "" : "(")
+#define PAREN_CLOSE (asm_dialect == ASM_NORMAL ? "]" : no_parentheses_mem_operand ? "" : ")")
+
/* Print an operand which is an address. This function should handle
any legit address, as accepted by bpf_legitimate_address_p, and
also addresses that are valid in CALL instructions.
switch (GET_CODE (addr))
{
case REG:
- fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "(");
+ fprintf (file, "%s", PAREN_OPEN);
bpf_print_register (file, addr, 0);
- fprintf (file, asm_dialect == ASM_NORMAL ? "+0]" : "+0)");
+ fprintf (file, "+0%s", PAREN_CLOSE);
break;
case PLUS:
{
|| (GET_CODE (op1) == UNSPEC
&& XINT (op1, 1) == UNSPEC_CORE_RELOC)))
{
- fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "(");
+ fprintf (file, "%s", PAREN_OPEN);
bpf_print_register (file, op0, 0);
fprintf (file, "+");
if (GET_CODE (op1) == UNSPEC)
output_addr_const (file, XVECEXP (op1, 0, 0));
else
output_addr_const (file, op1);
- fprintf (file, asm_dialect == ASM_NORMAL ? "]" : ")");
+ fprintf (file, "%s", PAREN_CLOSE);
}
else
fatal_insn ("invalid address in operand", addr);
}
}
+#undef PAREN_OPEN
+#undef PAREN_CLOSE
+
/* Add a BPF builtin function with NAME, CODE and TYPE. Return
the function decl or NULL_TREE if the builtin was not added. */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mv3-atomics -O2 -masm=pseudoc" } */
+
+int
+foo (int *p, int *expected, int desired)
+{
+ return __atomic_compare_exchange (p, expected, &desired, 0,
+ __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
+}
+
+int
+foo64 (long *p, long *expected, long desired)
+{
+ return __atomic_compare_exchange (p, expected, &desired, 0,
+ __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
+}
+
+int
+bar (int *p, int *new)
+{
+ int old;
+ __atomic_exchange (p, new, &old, __ATOMIC_RELAXED);
+ return old;
+}
+
+int
+bar64 (long *p, long *new)
+{
+ long old;
+ __atomic_exchange (p, new, &old, __ATOMIC_SEQ_CST);
+ return old;
+}
+
+/* { dg-final { scan-assembler "r. = cmpxchg_64\\(r.\\+0, r., r.\\)" } } */
+/* { dg-final { scan-assembler "w. = cmpxchg32_32\\(r.\\+0, w., w.\\)" } } */
+/* { dg-final { scan-assembler-times "w. = xchg32_32\\(r.\\+0, w.\\)" 1 } } */
+/* { dg-final { scan-assembler-times "r. = xchg_64\\(r.\\+0, r.\\)" 1 } } */
+