Commit 1a7a35c7 by Richard Henderson Committed by Richard Henderson

arm, aarch64: Add support for __GCC_ASM_FLAG_OUTPUTS__

Since all but a couple of lines is shared between the two targets,
enable them both at once.

	* config/arm/aarch-common-protos.h (arm_md_asm_adjust): Declare.
	* config/arm/aarch-common.c (arm_md_asm_adjust): New.
	* config/arm/arm-c.c (arm_cpu_builtins): Define
	__GCC_ASM_FLAG_OUTPUTS__.
	* config/arm/arm.c (TARGET_MD_ASM_ADJUST): New.
	* config/aarch64/aarch64-c.c (aarch64_define_unconditional_macros):
	Define __GCC_ASM_FLAG_OUTPUTS__.
	* config/aarch64/aarch64.c (TARGET_MD_ASM_ADJUST): New.
	* doc/extend.texi (FlagOutputOperands): Add documentation
	for ARM and AArch64.

From-SVN: r278226
parent 54138d95
2019-11-14 Richard Henderson <richard.henderson@linaro.org>
* config/arm/aarch-common-protos.h (arm_md_asm_adjust): Declare.
* config/arm/aarch-common.c (arm_md_asm_adjust): New.
* config/arm/arm-c.c (arm_cpu_builtins): Define
__GCC_ASM_FLAG_OUTPUTS__.
* config/arm/arm.c (TARGET_MD_ASM_ADJUST): New.
* config/aarch64/aarch64-c.c (aarch64_define_unconditional_macros):
Define __GCC_ASM_FLAG_OUTPUTS__.
* config/aarch64/aarch64.c (TARGET_MD_ASM_ADJUST): New.
* doc/extend.texi (FlagOutputOperands): Add documentation
for ARM and AArch64.
* config/arm/arm-modes.def (CC_NZ): Rename from CC_NOOV.
* config/arm/predicates.md (nz_comparison_operator): Rename
from noov_comparison_operator.
......@@ -69,6 +69,8 @@ aarch64_define_unconditional_macros (cpp_reader *pfile)
builtin_define ("__ARM_FEATURE_UNALIGNED");
builtin_define ("__ARM_PCS_AAPCS64");
builtin_define_with_int_value ("__ARM_SIZEOF_WCHAR_T", WCHAR_TYPE_SIZE / 8);
builtin_define ("__GCC_ASM_FLAG_OUTPUTS__");
}
/* Undefine/redefine macros that depend on the current backend state and may
......
......@@ -21933,6 +21933,9 @@ aarch64_libgcc_floating_mode_supported_p
#undef TARGET_STRICT_ARGUMENT_NAMING
#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
#undef TARGET_MD_ASM_ADJUST
#define TARGET_MD_ASM_ADJUST arm_md_asm_adjust
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-aarch64.h"
......@@ -23,6 +23,8 @@
#ifndef GCC_AARCH_COMMON_PROTOS_H
#define GCC_AARCH_COMMON_PROTOS_H
#include "hard-reg-set.h"
extern int aarch_accumulator_forwarding (rtx_insn *, rtx_insn *);
extern bool aarch_rev16_p (rtx);
extern bool aarch_rev16_shleft_mask_imm_p (rtx, machine_mode);
......@@ -141,5 +143,9 @@ struct cpu_cost_table
const struct vector_cost_table vect;
};
rtx_insn *
arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &/*inputs*/,
vec<const char *> &constraints,
vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs);
#endif /* GCC_AARCH_COMMON_PROTOS_H */
......@@ -26,10 +26,16 @@
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "insn-modes.h"
#include "tm.h"
#include "rtl.h"
#include "rtl-iter.h"
#include "memmodel.h"
#include "diagnostic.h"
#include "tree.h"
#include "expr.h"
#include "function.h"
#include "emit-rtl.h"
/* Return TRUE if X is either an arithmetic shift left, or
is a multiplication by a power of two. */
......@@ -520,3 +526,133 @@ arm_mac_accumulator_is_mul_result (rtx producer, rtx consumer)
&& !reg_overlap_mentioned_p (mul_result, mac_op0)
&& !reg_overlap_mentioned_p (mul_result, mac_op1));
}
/* Worker function for TARGET_MD_ASM_ADJUST.
We implement asm flag outputs. */
rtx_insn *
arm_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &/*inputs*/,
vec<const char *> &constraints,
vec<rtx> &/*clobbers*/, HARD_REG_SET &/*clobbered_regs*/)
{
bool saw_asm_flag = false;
start_sequence ();
for (unsigned i = 0, n = outputs.length (); i < n; ++i)
{
const char *con = constraints[i];
if (strncmp (con, "=@cc", 4) != 0)
continue;
con += 4;
if (strchr (con, ',') != NULL)
{
error ("alternatives not allowed in %<asm%> flag output");
continue;
}
machine_mode mode;
rtx_code code;
int con01 = 0;
#define C(X, Y) (unsigned char)(X) * 256 + (unsigned char)(Y)
/* All of the condition codes are two characters. */
if (con[0] != 0 && con[1] != 0 && con[2] == 0)
con01 = C(con[0], con[1]);
switch (con01)
{
case C('c', 'c'):
case C('l', 'o'):
mode = CC_Cmode, code = GEU;
break;
case C('c', 's'):
case C('h', 's'):
mode = CC_Cmode, code = LTU;
break;
case C('e', 'q'):
mode = CC_NZmode, code = EQ;
break;
case C('g', 'e'):
mode = CCmode, code = GE;
break;
case C('g', 't'):
mode = CCmode, code = GT;
break;
case C('h', 'i'):
mode = CCmode, code = GTU;
break;
case C('l', 'e'):
mode = CCmode, code = LE;
break;
case C('l', 's'):
mode = CCmode, code = LEU;
break;
case C('l', 't'):
mode = CCmode, code = LT;
break;
case C('m', 'i'):
mode = CC_NZmode, code = LT;
break;
case C('n', 'e'):
mode = CC_NZmode, code = NE;
break;
case C('p', 'l'):
mode = CC_NZmode, code = GE;
break;
case C('v', 'c'):
mode = CC_Vmode, code = EQ;
break;
case C('v', 's'):
mode = CC_Vmode, code = NE;
break;
default:
error ("unknown %<asm%> flag output %qs", constraints[i]);
continue;
}
#undef C
rtx dest = outputs[i];
machine_mode dest_mode = GET_MODE (dest);
if (!SCALAR_INT_MODE_P (dest_mode))
{
error ("invalid type for %<asm%> flag output");
continue;
}
if (!saw_asm_flag)
{
/* This is the first asm flag output. Here we put the flags
register in as the real output and adjust the condition to
allow it. */
constraints[i] = "=c";
outputs[i] = gen_rtx_REG (CCmode, CC_REGNUM);
saw_asm_flag = true;
}
else
{
/* We don't need the flags register as output twice. */
constraints[i] = "=X";
outputs[i] = gen_rtx_SCRATCH (word_mode);
}
rtx x = gen_rtx_REG (mode, CC_REGNUM);
x = gen_rtx_fmt_ee (code, word_mode, x, const0_rtx);
if (dest_mode == word_mode)
emit_insn (gen_rtx_SET (dest, x));
else
{
rtx tmp = gen_reg_rtx (word_mode);
emit_insn (gen_rtx_SET (tmp, x));
tmp = convert_modes (dest_mode, word_mode, tmp, true);
emit_move_insn (dest, tmp);
}
}
rtx_insn *seq = get_insns ();
end_sequence ();
return saw_asm_flag ? seq : NULL;
}
......@@ -122,6 +122,7 @@ arm_cpu_builtins (struct cpp_reader* pfile)
if (arm_arch_notm)
builtin_define ("__ARM_ARCH_ISA_ARM");
builtin_define ("__APCS_32__");
builtin_define ("__GCC_ASM_FLAG_OUTPUTS__");
def_or_undef_macro (pfile, "__thumb__", TARGET_THUMB);
def_or_undef_macro (pfile, "__thumb2__", TARGET_THUMB2);
......
......@@ -816,6 +816,9 @@ static const struct attribute_spec arm_attribute_table[] =
#undef TARGET_CONSTANT_ALIGNMENT
#define TARGET_CONSTANT_ALIGNMENT arm_constant_alignment
#undef TARGET_MD_ASM_ADJUST
#define TARGET_MD_ASM_ADJUST arm_md_asm_adjust
/* Obstack for minipool constant handling. */
static struct obstack minipool_obstack;
......
......@@ -9771,6 +9771,45 @@ referenced within the assembler template via @code{%0} etc, as there's
no corresponding text in the assembly language.
@table @asis
@item ARM
@itemx AArch64
The flag output constraints for the ARM family are of the form
@samp{=@@cc@var{cond}} where @var{cond} is one of the standard
conditions defined in the ARM ARM for @code{ConditionHolds}.
@table @code
@item eq
Z flag set, or equal
@item ne
Z flag clear or not equal
@item cs
@itemx hs
C flag set or unsigned greater than equal
@item cc
@itemx lo
C flag clear or unsigned less than
@item mi
N flag set or ``minus''
@item pl
N flag clear or ``plus''
@item vs
V flag set or signed overflow
@item vc
V flag clear
@item hi
unsigned greater than
@item ls
unsigned less than equal
@item ge
signed greater than equal
@item lt
signed less than
@item gt
signed greater than
@item le
signed less than equal
@end table
@item x86 family
The flag output constraints for the x86 family are of the form
@samp{=@@cc@var{cond}} where @var{cond} is one of the standard
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment