qemu-s390x
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 2/2] tests/tcg/s390x: Add ex-relative-long.c


From: Nina Schoetterl-Glausch
Subject: Re: [PATCH v2 2/2] tests/tcg/s390x: Add ex-relative-long.c
Date: Thu, 16 Mar 2023 18:50:00 +0100
User-agent: Evolution 3.46.4 (3.46.4-1.fc37)

On Wed, 2023-03-15 at 01:11 +0100, Ilya Leoshkevich wrote:
> > Test EXECUTE and EXECUTE RELATIVE LONG with relative long instructions
> > as targets.
> > 
> > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>

Reviewed-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>

Some comments below.

> > ---
> >  tests/tcg/s390x/Makefile.target    |   1 +
> >  tests/tcg/s390x/ex-relative-long.c | 159 +++++++++++++++++++++++++++++
> >  2 files changed, 160 insertions(+)
> >  create mode 100644 tests/tcg/s390x/ex-relative-long.c
> > 
> > diff --git a/tests/tcg/s390x/Makefile.target 
> > b/tests/tcg/s390x/Makefile.target
> > index cf93b966862..90bc48227db 100644
> > --- a/tests/tcg/s390x/Makefile.target
> > +++ b/tests/tcg/s390x/Makefile.target
> > @@ -29,6 +29,7 @@ TESTS+=clst
> >  TESTS+=long-double
> >  TESTS+=cdsg
> >  TESTS+=chrl
> > +TESTS+=ex-relative-long
> >  
> >  cdsg: CFLAGS+=-pthread
> >  cdsg: LDFLAGS+=-pthread
> > diff --git a/tests/tcg/s390x/ex-relative-long.c 
> > b/tests/tcg/s390x/ex-relative-long.c
> > new file mode 100644
> > index 00000000000..4caa8c1b962
> > --- /dev/null
> > +++ b/tests/tcg/s390x/ex-relative-long.c
> > @@ -0,0 +1,159 @@
> > +/* Check EXECUTE with relative long instructions as targets. */
> > +#include <stdlib.h>
> > +#include <stdio.h>
> > +
> > +struct test {
> > +    const char *name;
> > +    long (*func)(long reg, long *cc);
> > +    long exp_reg;
> > +    long exp_mem;
> > +    long exp_cc;
> > +};
> > +
> > +/*
> > + * Each test sets the MEM_IDXth element of the mem array to MEM and uses a
> > + * single relative long instruction on it. The other elements remain zero.
> > + * This is in order to prevent stumbling upon MEM in random memory in case
> > + * there is an off-by-a-small-value bug.
> > + *
> > + * Note that while gcc supports the ZL constraint for relative long 
> > operands,
> > + * clang doesn't, so the assembly code accesses mem[MEM_IDX] using MEM_ASM.
> > + */
> > +long mem[0x1000];

This could be static, no?

> > +#define MEM_IDX 0x800
> > +#define MEM_ASM "mem+0x800*8"
> > +
> > +/* Initial %r2 value. */
> > +#define REG 0x1234567887654321
> > +
> > +/* Initial mem[MEM_IDX] value. */
> > +#define MEM 0xfedcba9889abcdef
> > +
> > +/* Initial cc value. */
> > +#define CC 0
> > +
> > +/* Relative long instructions and their expected effects. */
> > +#define FOR_EACH_INSN(F)                                                   
> >     \

You could define some macros and then calculate a bunch of values in the table, 
i.e.
#define SL(v) ((long)(v))
#define UL(v) ((unsigned long)(v))
#define SI(v, i) ((int)(v >> ((1 - i) * 32)))
#define UI(v, i) ((unsigned int)(v >> ((1 - i) * 32)))
#define SH(v, i) ((short)(v >> ((3 - i) * 16)))
#define UH(v, i) ((unsigned short)(v >> ((3 - i) * 16)))
#define CMP(f, s) ((f) == (s) ? 0 : ((f) < (s) ? 1 : 2 ))

F(cgfrl,  REG,                 MEM,                CMP(SL(REG), SI(MEM, 0))

But everything checks out, so no need.

> > +    F(cgfrl,  REG,                 MEM,                2)                  
> >     \
> > +    F(cghrl,  REG,                 MEM,                2)                  
> >     \
> > +    F(cgrl,   REG,                 MEM,                2)                  
> >     \
> > +    F(chrl,   REG,                 MEM,                1)                  
> >     \
> > +    F(clgfrl, REG,                 MEM,                2)                  
> >     \
> > +    F(clghrl, REG,                 MEM,                2)                  
> >     \
> > +    F(clgrl,  REG,                 MEM,                1)                  
> >     \
> > +    F(clhrl,  REG,                 MEM,                2)                  
> >     \
> > +    F(clrl,   REG,                 MEM,                1)                  
> >     \
> > +    F(crl,    REG,                 MEM,                1)                  
> >     \
> > +    F(larl,   (long)&mem[MEM_IDX], MEM,                CC)                 
> >     \
> > +    F(lgfrl,  0xfffffffffedcba98,  MEM,                CC)                 
> >     \
> > +    F(lghrl,  0xfffffffffffffedc,  MEM,                CC)                 
> >     \
> > +    F(lgrl,   MEM,                 MEM,                CC)                 
> >     \
> > +    F(lhrl,   0x12345678fffffedc,  MEM,                CC)                 
> >     \
> > +    F(llghrl, 0x000000000000fedc,  MEM,                CC)                 
> >     \
> > +    F(llhrl,  0x123456780000fedc,  MEM,                CC)                 
> >     \
> > +    F(lrl,    0x12345678fedcba98,  MEM,                CC)                 
> >     \
> > +    F(stgrl,  REG,                 REG,                CC)                 
> >     \
> > +    F(sthrl,  REG,                 0x4321ba9889abcdef, CC)                 
> >     \
> > +    F(strl,   REG,                 0x8765432189abcdef, CC)
> > +
> > +/* Test functions. */
> > +#define DEFINE_EX_TEST(insn, exp_reg, exp_mem, exp_cc)                     
> >     \
> > +    static long test_ex_ ## insn(long reg, long *cc)                       
> >     \
> > +    {                                                                      
> >     \
> > +        register long reg_val asm("r2");                                   
> >     \
> > +        long cc_val, mask, target;                                         
> >     \
> > +                                                                           
> >     \
> > +        reg_val = reg;                                                     
> >     \
> > +        asm("xgr %[cc_val],%[cc_val]\n"  /* initial cc */                  
> >     \

This confused me for a bit because it's not about cc_val at all.
Maybe do "cr %%r0,%%r0\n" instead?
Could also push it down before the ex, since that's where the change we care 
about
takes place.

> > +            "lghi %[mask],0x20\n"        /* make target use %r2 */         
> >     \
> > +            "larl %[target],0f\n"                                          
> >     \
> > +            "ex %[mask],0(%[target])\n"                                    
> >     \
> > +            "jg 1f\n"                                                      
> >     \
> > +            "0: " #insn " %%r0," MEM_ASM "\n"                              
> >     \
> > +            "1: ipm %[cc_val]\n"                                           
> >     \
> > +            : [cc_val] "=&r" (cc_val)                                      
> >     \
> > +            , [mask] "=&r" (mask)                                          
> >     \
> > +            , [target] "=&r" (target)                                      
> >     \
> > +            , [reg_val] "+&r" (reg_val)                                    
> >     \
> > +            : : "cc", "memory");                                           
> >     \
> > +        reg = reg_val;                                                     
> >     \

What is the point of this assignment?

> > +        *cc = (cc_val >> 28) & 3;                                          
> >     \
> > +                                                                           
> >     \
> > +        return reg_val;                                                    
> >     \
> > +    }
> > +
> > +#define DEFINE_EXRL_TEST(insn, exp_reg, exp_mem, exp_cc)                   
> >     \
> > +    static long test_exrl_ ## insn(long reg, long *cc)                     
> >     \
> > +    {                                                                      
> >     \
> > +        register long reg_val asm("r2");                                   
> >     \
> > +        long cc_val, mask;                                                 
> >     \
> > +                                                                           
> >     \
> > +        reg_val = reg;                                                     
> >     \
> > +        asm("xgr %[cc_val],%[cc_val]\n"  /* initial cc */                  
> >     \
> > +            "lghi %[mask],0x20\n"        /* make target use %r2 */         
> >     \
> > +            "exrl %[mask],0f\n"                                            
> >     \
> > +            "jg 1f\n"                                                      
> >     \
> > +            "0: " #insn " %%r0," MEM_ASM "\n"                              
> >     \
> > +            "1: ipm %[cc_val]\n"                                           
> >     \
> > +            : [cc_val] "=&r" (cc_val)                                      
> >     \
> > +            , [mask] "=&r" (mask)                                          
> >     \
> > +            , [reg_val] "+&r" (reg_val)                                    
> >     \
> > +            : : "cc", "memory");                                           
> >     \
> > +        reg = reg_val;                                                     
> >     \
> > +        *cc = (cc_val >> 28) & 3;                                          
> >     \
> > +                                                                           
> >     \
> > +        return reg_val;                                                    
> >     \
> > +    }
> > +
> > +FOR_EACH_INSN(DEFINE_EX_TEST)
> > +FOR_EACH_INSN(DEFINE_EXRL_TEST)
> > +
> > +/* Test definitions. */
> > +#define REGISTER_EX_EXRL_TEST(ex_insn, insn, _exp_reg, _exp_mem, _exp_cc)  
> >     \
> > +    {                                                                      
> >     \
> > +        .name = #ex_insn " " #insn,                                        
> >     \
> > +        .func = test_ ## ex_insn ## _ ## insn,                             
> >     \
> > +        .exp_reg = (long)(_exp_reg),                                       
> >     \
> > +        .exp_mem = (long)(_exp_mem),                                       
> >     \
> > +        .exp_cc = (long)(_exp_cc),                                         
> >     \

You don't need the casts, do you?

> > +    },
> > +
> > +#define REGISTER_EX_TEST(insn, exp_reg, exp_mem, exp_cc)                   
> >     \
> > +    REGISTER_EX_EXRL_TEST(ex, insn, exp_reg, exp_mem, exp_cc)
> > +
> > +#define REGISTER_EXRL_TEST(insn, exp_reg, exp_mem, exp_cc)                 
> >     \
> > +    REGISTER_EX_EXRL_TEST(exrl, insn, exp_reg, exp_mem, exp_cc)
> > +
> > +static const struct test tests[] = {
> > +    FOR_EACH_INSN(REGISTER_EX_TEST)
> > +    FOR_EACH_INSN(REGISTER_EXRL_TEST)
> > +};
> > +
> > +/* Loop over all tests and run them. */
> > +int main(void)
> > +{
> > +    const struct test *test;
> > +    int ret = EXIT_SUCCESS;
> > +    long reg, cc;
> > +    size_t i;
> > +
> > +    for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
> > +        test = &tests[i];
> > +        mem[MEM_IDX] = MEM;
> > +        cc = -1;
> > +        reg = test->func(REG, &cc);
> > +#define ASSERT_EQ(expected, actual) do {                                   
> >     \
> > +    if (expected != actual) {                                              
> >     \
> > +        fprintf(stderr, "%s: " #expected " (0x%lx) != " #actual " 
> > (0x%lx)\n",  \
> > +                test->name, expected, actual);                             
> >     \
> > +        ret = EXIT_FAILURE;                                                
> >     \
> > +    }                                                                      
> >     \
> > +} while (0)
> > +        ASSERT_EQ(test->exp_reg, reg);
> > +        ASSERT_EQ(test->exp_mem, mem[MEM_IDX]);
> > +        ASSERT_EQ(test->exp_cc, cc);
> > +#undef ASSERT_EQ
> > +    }
> > +
> > +    return ret;
> > +}





reply via email to

[Prev in Thread] Current Thread [Next in Thread]