aboutsummaryrefslogtreecommitdiff
path: root/tests/tcg/s390x/clst.c
blob: ed2fe7326c3bef2626a9949ef9d1f2effd494167 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>

static int clst(char sep, const char **s1, const char **s2)
{
    const char *r1 = *s1;
    const char *r2 = *s2;
    int cc;

    do {
        register int r0 asm("r0") = sep;

        asm("clst %[r1],%[r2]\n"
            "ipm %[cc]\n"
            "srl %[cc],28"
            : [r1] "+r" (r1), [r2] "+r" (r2), "+r" (r0), [cc] "=r" (cc)
            :
            : "cc");
        *s1 = r1;
        *s2 = r2;
    } while (cc == 3);

    return cc;
}

static const struct test {
    const char *name;
    char sep;
    const char *s1;
    const char *s2;
    int exp_cc;
    int exp_off;
} tests[] = {
    {
        .name = "cc0",
        .sep = 0,
        .s1 = "aa",
        .s2 = "aa",
        .exp_cc = 0,
        .exp_off = 0,
    },
    {
        .name = "cc1",
        .sep = 1,
        .s1 = "a\x01",
        .s2 = "aa\x01",
        .exp_cc = 1,
        .exp_off = 1,
    },
    {
        .name = "cc2",
        .sep = 2,
        .s1 = "abc\x02",
        .s2 = "abb\x02",
        .exp_cc = 2,
        .exp_off = 2,
    },
};

int main(void)
{
    const struct test *t;
    const char *s1, *s2;
    size_t i;
    int cc;

    for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
        t = &tests[i];
        s1 = t->s1;
        s2 = t->s2;
        cc = clst(t->sep, &s1, &s2);
        if (cc != t->exp_cc ||
                s1 != t->s1 + t->exp_off ||
                s2 != t->s2 + t->exp_off) {
            fprintf(stderr, "%s\n", t->name);
            return EXIT_FAILURE;
        }
    }

    return EXIT_SUCCESS;
}