Message ID | 20191114100716.28827-6-richard.henderson@linaro.org |
---|---|
State | New |
Headers | show |
Series | Implement asm flag outputs for arm + aarch64 | expand |
On 14/11/2019 10:07, Richard Henderson wrote: > Inspired by the tests in gcc.target/i386. Testing code generation, > diagnostics, and execution. > > * gcc.target/arm/asm-flag-1.c: New test. > * gcc.target/arm/asm-flag-3.c: New test. > * gcc.target/arm/asm-flag-5.c: New test. > * gcc.target/arm/asm-flag-6.c: New test. > --- > gcc/testsuite/gcc.target/arm/asm-flag-1.c | 36 +++++++++++++ > gcc/testsuite/gcc.target/arm/asm-flag-3.c | 38 ++++++++++++++ > gcc/testsuite/gcc.target/arm/asm-flag-5.c | 30 +++++++++++ > gcc/testsuite/gcc.target/arm/asm-flag-6.c | 62 +++++++++++++++++++++++ > 4 files changed, 166 insertions(+) > create mode 100644 gcc/testsuite/gcc.target/arm/asm-flag-1.c > create mode 100644 gcc/testsuite/gcc.target/arm/asm-flag-3.c > create mode 100644 gcc/testsuite/gcc.target/arm/asm-flag-5.c > create mode 100644 gcc/testsuite/gcc.target/arm/asm-flag-6.c These will/should clearly not work on thumb1 targets where the condition register is not exposed. On thumb2 I'd expect to see some testing for the correct IT instruction. R. > > diff --git a/gcc/testsuite/gcc.target/arm/asm-flag-1.c b/gcc/testsuite/gcc.target/arm/asm-flag-1.c > new file mode 100644 > index 00000000000..9707ebfcebb > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/asm-flag-1.c > @@ -0,0 +1,36 @@ > +/* Test the valid @cc<cc> asm flag outputs. */ > +/* { dg-do compile } */ > +/* { dg-options "-O" } */ > + > +#ifndef __GCC_ASM_FLAG_OUTPUTS__ > +#error "missing preprocessor define" > +#endif > + > +void f(char *out) > +{ > + asm("" > + : "=@ccne"(out[0]), "=@cceq"(out[1]), > + "=@cccs"(out[2]), "=@cccc"(out[3]), > + "=@ccmi"(out[4]), "=@ccpl"(out[5]), > + "=@ccvs"(out[6]), "=@ccvc"(out[7]), > + "=@cchi"(out[8]), "=@ccls"(out[9]), > + "=@ccge"(out[10]), "=@cclt"(out[11]), > + "=@ccgt"(out[12]), "=@ccle"(out[13]), > + "=@cchs"(out[14]), "=@cclo"(out[15])); > +} > + > +/* There will be at least one of each. */ > +/* { dg-final { scan-assembler "movne" } } */ > +/* { dg-final { scan-assembler "moveq" } } */ > +/* { dg-final { scan-assembler "movcs" } } */ > +/* { dg-final { scan-assembler "movcc" } } */ > +/* { dg-final { scan-assembler "movmi" } } */ > +/* { dg-final { scan-assembler "movpl" } } */ > +/* { dg-final { scan-assembler "movvs" } } */ > +/* { dg-final { scan-assembler "movvc" } } */ > +/* { dg-final { scan-assembler "movhi" } } */ > +/* { dg-final { scan-assembler "movls" } } */ > +/* { dg-final { scan-assembler "movge" } } */ > +/* { dg-final { scan-assembler "movls" } } */ > +/* { dg-final { scan-assembler "movgt" } } */ > +/* { dg-final { scan-assembler "movle" } } */ > diff --git a/gcc/testsuite/gcc.target/arm/asm-flag-3.c b/gcc/testsuite/gcc.target/arm/asm-flag-3.c > new file mode 100644 > index 00000000000..e84e3431277 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/asm-flag-3.c > @@ -0,0 +1,38 @@ > +/* Test some of the valid @cc<cc> asm flag outputs. */ > +/* { dg-do compile } */ > +/* { dg-options "-O" } */ > + > +#define DO(C) \ > +void f##C(void) { char x; asm("" : "=@cc"#C(x)); if (!x) asm(""); asm(""); } > + > +DO(ne) > +DO(eq) > +DO(cs) > +DO(cc) > +DO(hs) > +DO(lo) > +DO(mi) > +DO(pl) > +DO(vs) > +DO(vc) > +DO(hi) > +DO(ls) > +DO(ge) > +DO(lt) > +DO(gt) > +DO(le) > + > +/* { dg-final { scan-assembler "bne" } } */ > +/* { dg-final { scan-assembler "beq" } } */ > +/* { dg-final { scan-assembler "bcs" } } */ > +/* { dg-final { scan-assembler "bcc" } } */ > +/* { dg-final { scan-assembler "bmi" } } */ > +/* { dg-final { scan-assembler "bpl" } } */ > +/* { dg-final { scan-assembler "bvs" } } */ > +/* { dg-final { scan-assembler "bvc" } } */ > +/* { dg-final { scan-assembler "bhi" } } */ > +/* { dg-final { scan-assembler "bls" } } */ > +/* { dg-final { scan-assembler "bge" } } */ > +/* { dg-final { scan-assembler "blt" } } */ > +/* { dg-final { scan-assembler "bgt" } } */ > +/* { dg-final { scan-assembler "ble" } } */ > diff --git a/gcc/testsuite/gcc.target/arm/asm-flag-5.c b/gcc/testsuite/gcc.target/arm/asm-flag-5.c > new file mode 100644 > index 00000000000..4d4394e1478 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/asm-flag-5.c > @@ -0,0 +1,30 @@ > +/* Test error conditions of asm flag outputs. */ > +/* { dg-do compile } */ > +/* { dg-options "" } */ > + > +void f_B(void) { _Bool x; asm("" : "=@cccc"(x)); } > +void f_c(void) { char x; asm("" : "=@cccc"(x)); } > +void f_s(void) { short x; asm("" : "=@cccc"(x)); } > +void f_i(void) { int x; asm("" : "=@cccc"(x)); } > +void f_l(void) { long x; asm("" : "=@cccc"(x)); } > +void f_ll(void) { long long x; asm("" : "=@cccc"(x)); } > + > +void f_f(void) > +{ > + float x; > + asm("" : "=@cccc"(x)); /* { dg-error invalid type } */ > +} > + > +void f_d(void) > +{ > + double x; > + asm("" : "=@cccc"(x)); /* { dg-error invalid type } */ > +} > + > +struct S { int x[3]; }; > + > +void f_S(void) > +{ > + struct S x; > + asm("" : "=@cccc"(x)); /* { dg-error invalid type } */ > +} > diff --git a/gcc/testsuite/gcc.target/arm/asm-flag-6.c b/gcc/testsuite/gcc.target/arm/asm-flag-6.c > new file mode 100644 > index 00000000000..09174e04ae6 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/asm-flag-6.c > @@ -0,0 +1,62 @@ > +/* Executable testcase for 'output flags.' */ > +/* { dg-do run } */ > + > +int test_bits (long nzcv) > +{ > + long n, z, c, v; > + > + __asm__ ("msr APSR_nzcvq, %[in]" > + : "=@ccmi"(n), "=@cceq"(z), "=@cccs"(c), "=@ccvs"(v) > + : [in] "r"(nzcv << 28)); > + > + return n * 8 + z * 4 + c * 2 + v == nzcv; > +} > + > +int test_cmps (long x, long y) > +{ > + long gt, lt, ge, le; > + > + __asm__ ("cmp %[x], %[y]" > + : "=@ccgt"(gt), "=@cclt"(lt), "=@ccge"(ge), "=@ccle"(le) > + : [x] "r"(x), [y] "r"(y)); > + > + return (gt == (x > y) > + && lt == (x < y) > + && ge == (x >= y) > + && le == (x <= y)); > +} > + > +int test_cmpu (unsigned long x, unsigned long y) > +{ > + long gt, lt, ge, le; > + > + __asm__ ("cmp %[x], %[y]" > + : "=@cchi"(gt), "=@cclo"(lt), "=@cchs"(ge), "=@ccls"(le) > + : [x] "r"(x), [y] "r"(y)); > + > + return (gt == (x > y) > + && lt == (x < y) > + && ge == (x >= y) > + && le == (x <= y)); > +} > + > +int main () > +{ > + long i, j; > + > + for (i = 0; i < 16; ++i) > + if (!test_bits (i)) > + __builtin_abort (); > + > + for (i = -1; i <= 1; ++i) > + for (j = -1; j <= 1; ++j) > + if (!test_cmps (i, j)) > + __builtin_abort (); > + > + for (i = 0; i <= 2; ++i) > + for (j = 0; j <= 2; ++j) > + if (!test_cmpu (i, j)) > + __builtin_abort (); > + > + return 0; > +} >
Hi Richard On Thu, 14 Nov 2019 at 11:08, Richard Henderson <richard.henderson@linaro.org> wrote: > > Inspired by the tests in gcc.target/i386. Testing code generation, > diagnostics, and execution. > > * gcc.target/arm/asm-flag-1.c: New test. > * gcc.target/arm/asm-flag-3.c: New test. > * gcc.target/arm/asm-flag-5.c: New test. > * gcc.target/arm/asm-flag-6.c: New test. I've noticed ICEs when using -march=armv5t, but I believe these are fixed by your follow-up patch for thumb1. However, I've also noticed that asm-flag-6 fails at execution time when generating code for cortex-m (I have m3, m4, and m33 in my list) QEMU complains with: qemu: fatal: v7m_msr 2048 Indeed, it crashes on 0x000081c4: f383 8800 msr apsr, r3 Which looks like a qemu bug, probably similar to the vmsr one I fixed recently. While reading the ARM ARM, I also noticed that "apsr" is deprecated and should be "APSR_nzcvq" (as emitted by GCC), so it seems qemu's disassembler needs an update too. Do you want me to have a look at the qemu problems, or will you handle them? Thanks, Christophe > --- > gcc/testsuite/gcc.target/arm/asm-flag-1.c | 36 +++++++++++++ > gcc/testsuite/gcc.target/arm/asm-flag-3.c | 38 ++++++++++++++ > gcc/testsuite/gcc.target/arm/asm-flag-5.c | 30 +++++++++++ > gcc/testsuite/gcc.target/arm/asm-flag-6.c | 62 +++++++++++++++++++++++ > 4 files changed, 166 insertions(+) > create mode 100644 gcc/testsuite/gcc.target/arm/asm-flag-1.c > create mode 100644 gcc/testsuite/gcc.target/arm/asm-flag-3.c > create mode 100644 gcc/testsuite/gcc.target/arm/asm-flag-5.c > create mode 100644 gcc/testsuite/gcc.target/arm/asm-flag-6.c > > diff --git a/gcc/testsuite/gcc.target/arm/asm-flag-1.c b/gcc/testsuite/gcc.target/arm/asm-flag-1.c > new file mode 100644 > index 00000000000..9707ebfcebb > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/asm-flag-1.c > @@ -0,0 +1,36 @@ > +/* Test the valid @cc<cc> asm flag outputs. */ > +/* { dg-do compile } */ > +/* { dg-options "-O" } */ > + > +#ifndef __GCC_ASM_FLAG_OUTPUTS__ > +#error "missing preprocessor define" > +#endif > + > +void f(char *out) > +{ > + asm("" > + : "=@ccne"(out[0]), "=@cceq"(out[1]), > + "=@cccs"(out[2]), "=@cccc"(out[3]), > + "=@ccmi"(out[4]), "=@ccpl"(out[5]), > + "=@ccvs"(out[6]), "=@ccvc"(out[7]), > + "=@cchi"(out[8]), "=@ccls"(out[9]), > + "=@ccge"(out[10]), "=@cclt"(out[11]), > + "=@ccgt"(out[12]), "=@ccle"(out[13]), > + "=@cchs"(out[14]), "=@cclo"(out[15])); > +} > + > +/* There will be at least one of each. */ > +/* { dg-final { scan-assembler "movne" } } */ > +/* { dg-final { scan-assembler "moveq" } } */ > +/* { dg-final { scan-assembler "movcs" } } */ > +/* { dg-final { scan-assembler "movcc" } } */ > +/* { dg-final { scan-assembler "movmi" } } */ > +/* { dg-final { scan-assembler "movpl" } } */ > +/* { dg-final { scan-assembler "movvs" } } */ > +/* { dg-final { scan-assembler "movvc" } } */ > +/* { dg-final { scan-assembler "movhi" } } */ > +/* { dg-final { scan-assembler "movls" } } */ > +/* { dg-final { scan-assembler "movge" } } */ > +/* { dg-final { scan-assembler "movls" } } */ > +/* { dg-final { scan-assembler "movgt" } } */ > +/* { dg-final { scan-assembler "movle" } } */ > diff --git a/gcc/testsuite/gcc.target/arm/asm-flag-3.c b/gcc/testsuite/gcc.target/arm/asm-flag-3.c > new file mode 100644 > index 00000000000..e84e3431277 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/asm-flag-3.c > @@ -0,0 +1,38 @@ > +/* Test some of the valid @cc<cc> asm flag outputs. */ > +/* { dg-do compile } */ > +/* { dg-options "-O" } */ > + > +#define DO(C) \ > +void f##C(void) { char x; asm("" : "=@cc"#C(x)); if (!x) asm(""); asm(""); } > + > +DO(ne) > +DO(eq) > +DO(cs) > +DO(cc) > +DO(hs) > +DO(lo) > +DO(mi) > +DO(pl) > +DO(vs) > +DO(vc) > +DO(hi) > +DO(ls) > +DO(ge) > +DO(lt) > +DO(gt) > +DO(le) > + > +/* { dg-final { scan-assembler "bne" } } */ > +/* { dg-final { scan-assembler "beq" } } */ > +/* { dg-final { scan-assembler "bcs" } } */ > +/* { dg-final { scan-assembler "bcc" } } */ > +/* { dg-final { scan-assembler "bmi" } } */ > +/* { dg-final { scan-assembler "bpl" } } */ > +/* { dg-final { scan-assembler "bvs" } } */ > +/* { dg-final { scan-assembler "bvc" } } */ > +/* { dg-final { scan-assembler "bhi" } } */ > +/* { dg-final { scan-assembler "bls" } } */ > +/* { dg-final { scan-assembler "bge" } } */ > +/* { dg-final { scan-assembler "blt" } } */ > +/* { dg-final { scan-assembler "bgt" } } */ > +/* { dg-final { scan-assembler "ble" } } */ > diff --git a/gcc/testsuite/gcc.target/arm/asm-flag-5.c b/gcc/testsuite/gcc.target/arm/asm-flag-5.c > new file mode 100644 > index 00000000000..4d4394e1478 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/asm-flag-5.c > @@ -0,0 +1,30 @@ > +/* Test error conditions of asm flag outputs. */ > +/* { dg-do compile } */ > +/* { dg-options "" } */ > + > +void f_B(void) { _Bool x; asm("" : "=@cccc"(x)); } > +void f_c(void) { char x; asm("" : "=@cccc"(x)); } > +void f_s(void) { short x; asm("" : "=@cccc"(x)); } > +void f_i(void) { int x; asm("" : "=@cccc"(x)); } > +void f_l(void) { long x; asm("" : "=@cccc"(x)); } > +void f_ll(void) { long long x; asm("" : "=@cccc"(x)); } > + > +void f_f(void) > +{ > + float x; > + asm("" : "=@cccc"(x)); /* { dg-error invalid type } */ > +} > + > +void f_d(void) > +{ > + double x; > + asm("" : "=@cccc"(x)); /* { dg-error invalid type } */ > +} > + > +struct S { int x[3]; }; > + > +void f_S(void) > +{ > + struct S x; > + asm("" : "=@cccc"(x)); /* { dg-error invalid type } */ > +} > diff --git a/gcc/testsuite/gcc.target/arm/asm-flag-6.c b/gcc/testsuite/gcc.target/arm/asm-flag-6.c > new file mode 100644 > index 00000000000..09174e04ae6 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/arm/asm-flag-6.c > @@ -0,0 +1,62 @@ > +/* Executable testcase for 'output flags.' */ > +/* { dg-do run } */ > + > +int test_bits (long nzcv) > +{ > + long n, z, c, v; > + > + __asm__ ("msr APSR_nzcvq, %[in]" > + : "=@ccmi"(n), "=@cceq"(z), "=@cccs"(c), "=@ccvs"(v) > + : [in] "r"(nzcv << 28)); > + > + return n * 8 + z * 4 + c * 2 + v == nzcv; > +} > + > +int test_cmps (long x, long y) > +{ > + long gt, lt, ge, le; > + > + __asm__ ("cmp %[x], %[y]" > + : "=@ccgt"(gt), "=@cclt"(lt), "=@ccge"(ge), "=@ccle"(le) > + : [x] "r"(x), [y] "r"(y)); > + > + return (gt == (x > y) > + && lt == (x < y) > + && ge == (x >= y) > + && le == (x <= y)); > +} > + > +int test_cmpu (unsigned long x, unsigned long y) > +{ > + long gt, lt, ge, le; > + > + __asm__ ("cmp %[x], %[y]" > + : "=@cchi"(gt), "=@cclo"(lt), "=@cchs"(ge), "=@ccls"(le) > + : [x] "r"(x), [y] "r"(y)); > + > + return (gt == (x > y) > + && lt == (x < y) > + && ge == (x >= y) > + && le == (x <= y)); > +} > + > +int main () > +{ > + long i, j; > + > + for (i = 0; i < 16; ++i) > + if (!test_bits (i)) > + __builtin_abort (); > + > + for (i = -1; i <= 1; ++i) > + for (j = -1; j <= 1; ++j) > + if (!test_cmps (i, j)) > + __builtin_abort (); > + > + for (i = 0; i <= 2; ++i) > + for (j = 0; j <= 2; ++j) > + if (!test_cmpu (i, j)) > + __builtin_abort (); > + > + return 0; > +} > -- > 2.17.1 >
On 11/18/19 1:25 PM, Christophe Lyon wrote: > Hi Richard > > On Thu, 14 Nov 2019 at 11:08, Richard Henderson > <richard.henderson@linaro.org> wrote: >> >> Inspired by the tests in gcc.target/i386. Testing code generation, >> diagnostics, and execution. >> >> * gcc.target/arm/asm-flag-1.c: New test. >> * gcc.target/arm/asm-flag-3.c: New test. >> * gcc.target/arm/asm-flag-5.c: New test. >> * gcc.target/arm/asm-flag-6.c: New test. > > I've noticed ICEs when using -march=armv5t, but I believe these are > fixed by your follow-up patch for thumb1. > > However, I've also noticed that asm-flag-6 fails at execution time > when generating code for cortex-m (I have m3, m4, and m33 in my list) > QEMU complains with: > qemu: fatal: v7m_msr 2048 > > Indeed, it crashes on > 0x000081c4: f383 8800 msr apsr, r3 > > Which looks like a qemu bug, probably similar to the vmsr one I fixed > recently. While reading the ARM ARM, I also noticed that "apsr" is > deprecated and should be "APSR_nzcvq" (as emitted by GCC), so it seems > qemu's disassembler needs an update too. Do you want me to have a look > at the qemu problems, or will you handle them? I can handle them. Thanks for the report. r~
diff --git a/gcc/testsuite/gcc.target/arm/asm-flag-1.c b/gcc/testsuite/gcc.target/arm/asm-flag-1.c new file mode 100644 index 00000000000..9707ebfcebb --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/asm-flag-1.c @@ -0,0 +1,36 @@ +/* Test the valid @cc<cc> asm flag outputs. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +#ifndef __GCC_ASM_FLAG_OUTPUTS__ +#error "missing preprocessor define" +#endif + +void f(char *out) +{ + asm("" + : "=@ccne"(out[0]), "=@cceq"(out[1]), + "=@cccs"(out[2]), "=@cccc"(out[3]), + "=@ccmi"(out[4]), "=@ccpl"(out[5]), + "=@ccvs"(out[6]), "=@ccvc"(out[7]), + "=@cchi"(out[8]), "=@ccls"(out[9]), + "=@ccge"(out[10]), "=@cclt"(out[11]), + "=@ccgt"(out[12]), "=@ccle"(out[13]), + "=@cchs"(out[14]), "=@cclo"(out[15])); +} + +/* There will be at least one of each. */ +/* { dg-final { scan-assembler "movne" } } */ +/* { dg-final { scan-assembler "moveq" } } */ +/* { dg-final { scan-assembler "movcs" } } */ +/* { dg-final { scan-assembler "movcc" } } */ +/* { dg-final { scan-assembler "movmi" } } */ +/* { dg-final { scan-assembler "movpl" } } */ +/* { dg-final { scan-assembler "movvs" } } */ +/* { dg-final { scan-assembler "movvc" } } */ +/* { dg-final { scan-assembler "movhi" } } */ +/* { dg-final { scan-assembler "movls" } } */ +/* { dg-final { scan-assembler "movge" } } */ +/* { dg-final { scan-assembler "movls" } } */ +/* { dg-final { scan-assembler "movgt" } } */ +/* { dg-final { scan-assembler "movle" } } */ diff --git a/gcc/testsuite/gcc.target/arm/asm-flag-3.c b/gcc/testsuite/gcc.target/arm/asm-flag-3.c new file mode 100644 index 00000000000..e84e3431277 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/asm-flag-3.c @@ -0,0 +1,38 @@ +/* Test some of the valid @cc<cc> asm flag outputs. */ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +#define DO(C) \ +void f##C(void) { char x; asm("" : "=@cc"#C(x)); if (!x) asm(""); asm(""); } + +DO(ne) +DO(eq) +DO(cs) +DO(cc) +DO(hs) +DO(lo) +DO(mi) +DO(pl) +DO(vs) +DO(vc) +DO(hi) +DO(ls) +DO(ge) +DO(lt) +DO(gt) +DO(le) + +/* { dg-final { scan-assembler "bne" } } */ +/* { dg-final { scan-assembler "beq" } } */ +/* { dg-final { scan-assembler "bcs" } } */ +/* { dg-final { scan-assembler "bcc" } } */ +/* { dg-final { scan-assembler "bmi" } } */ +/* { dg-final { scan-assembler "bpl" } } */ +/* { dg-final { scan-assembler "bvs" } } */ +/* { dg-final { scan-assembler "bvc" } } */ +/* { dg-final { scan-assembler "bhi" } } */ +/* { dg-final { scan-assembler "bls" } } */ +/* { dg-final { scan-assembler "bge" } } */ +/* { dg-final { scan-assembler "blt" } } */ +/* { dg-final { scan-assembler "bgt" } } */ +/* { dg-final { scan-assembler "ble" } } */ diff --git a/gcc/testsuite/gcc.target/arm/asm-flag-5.c b/gcc/testsuite/gcc.target/arm/asm-flag-5.c new file mode 100644 index 00000000000..4d4394e1478 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/asm-flag-5.c @@ -0,0 +1,30 @@ +/* Test error conditions of asm flag outputs. */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void f_B(void) { _Bool x; asm("" : "=@cccc"(x)); } +void f_c(void) { char x; asm("" : "=@cccc"(x)); } +void f_s(void) { short x; asm("" : "=@cccc"(x)); } +void f_i(void) { int x; asm("" : "=@cccc"(x)); } +void f_l(void) { long x; asm("" : "=@cccc"(x)); } +void f_ll(void) { long long x; asm("" : "=@cccc"(x)); } + +void f_f(void) +{ + float x; + asm("" : "=@cccc"(x)); /* { dg-error invalid type } */ +} + +void f_d(void) +{ + double x; + asm("" : "=@cccc"(x)); /* { dg-error invalid type } */ +} + +struct S { int x[3]; }; + +void f_S(void) +{ + struct S x; + asm("" : "=@cccc"(x)); /* { dg-error invalid type } */ +} diff --git a/gcc/testsuite/gcc.target/arm/asm-flag-6.c b/gcc/testsuite/gcc.target/arm/asm-flag-6.c new file mode 100644 index 00000000000..09174e04ae6 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/asm-flag-6.c @@ -0,0 +1,62 @@ +/* Executable testcase for 'output flags.' */ +/* { dg-do run } */ + +int test_bits (long nzcv) +{ + long n, z, c, v; + + __asm__ ("msr APSR_nzcvq, %[in]" + : "=@ccmi"(n), "=@cceq"(z), "=@cccs"(c), "=@ccvs"(v) + : [in] "r"(nzcv << 28)); + + return n * 8 + z * 4 + c * 2 + v == nzcv; +} + +int test_cmps (long x, long y) +{ + long gt, lt, ge, le; + + __asm__ ("cmp %[x], %[y]" + : "=@ccgt"(gt), "=@cclt"(lt), "=@ccge"(ge), "=@ccle"(le) + : [x] "r"(x), [y] "r"(y)); + + return (gt == (x > y) + && lt == (x < y) + && ge == (x >= y) + && le == (x <= y)); +} + +int test_cmpu (unsigned long x, unsigned long y) +{ + long gt, lt, ge, le; + + __asm__ ("cmp %[x], %[y]" + : "=@cchi"(gt), "=@cclo"(lt), "=@cchs"(ge), "=@ccls"(le) + : [x] "r"(x), [y] "r"(y)); + + return (gt == (x > y) + && lt == (x < y) + && ge == (x >= y) + && le == (x <= y)); +} + +int main () +{ + long i, j; + + for (i = 0; i < 16; ++i) + if (!test_bits (i)) + __builtin_abort (); + + for (i = -1; i <= 1; ++i) + for (j = -1; j <= 1; ++j) + if (!test_cmps (i, j)) + __builtin_abort (); + + for (i = 0; i <= 2; ++i) + for (j = 0; j <= 2; ++j) + if (!test_cmpu (i, j)) + __builtin_abort (); + + return 0; +}