1 /* 2 * Test ADD LOGICAL WITH CARRY instructions. 3 * 4 * SPDX-License-Identifier: GPL-2.0-or-later 5 */ 6 #include <stdio.h> 7 #include <stdlib.h> 8 9 static const struct test { 10 const char *name; 11 unsigned long values[3]; 12 unsigned long exp_sum; 13 int exp_cc; 14 } tests[] = { 15 /* 16 * Each test starts with CC 0 and executes two chained ADD LOGICAL WITH 17 * CARRY instructions on three input values. The values must be compatible 18 * with both 32- and 64-bit test functions. 19 */ 20 21 /* NAME VALUES EXP_SUM EXP_CC */ 22 { "cc0->cc0", {0, 0, 0}, 0, 0, }, 23 { "cc0->cc1", {0, 0, 42}, 42, 1, }, 24 /* cc0->cc2 is not possible */ 25 /* cc0->cc3 is not possible */ 26 /* cc1->cc0 is not possible */ 27 { "cc1->cc1", {-3, 1, 1}, -1, 1, }, 28 { "cc1->cc2", {-3, 1, 2}, 0, 2, }, 29 { "cc1->cc3", {-3, 1, -1}, -3, 3, }, 30 /* cc2->cc0 is not possible */ 31 { "cc2->cc1", {-1, 1, 1}, 2, 1, }, 32 { "cc2->cc2", {-1, 1, -1}, 0, 2, }, 33 /* cc2->cc3 is not possible */ 34 /* cc3->cc0 is not possible */ 35 { "cc3->cc1", {-1, 2, 1}, 3, 1, }, 36 { "cc3->cc2", {-1, 2, -2}, 0, 2, }, 37 { "cc3->cc3", {-1, 2, -1}, 1, 3, }, 38 }; 39 40 /* Test ALCR (register variant) followed by ALC (memory variant). */ 41 static unsigned long test32rm(unsigned long a, unsigned long b, 42 unsigned long c, int *cc) 43 { 44 unsigned int a32 = a, b32 = b, c32 = c; 45 46 asm("xr %[cc],%[cc]\n" 47 "alcr %[a],%[b]\n" 48 "alc %[a],%[c]\n" 49 "ipm %[cc]" 50 : [a] "+&r" (a32), [cc] "+&r" (*cc) 51 : [b] "r" (b32), [c] "T" (c32) 52 : "cc"); 53 *cc >>= 28; 54 55 return (int)a32; 56 } 57 58 /* Test ALC (memory variant) followed by ALCR (register variant). */ 59 static unsigned long test32mr(unsigned long a, unsigned long b, 60 unsigned long c, int *cc) 61 { 62 unsigned int a32 = a, b32 = b, c32 = c; 63 64 asm("xr %[cc],%[cc]\n" 65 "alc %[a],%[b]\n" 66 "alcr %[c],%[a]\n" 67 "ipm %[cc]" 68 : [a] "+&r" (a32), [c] "+&r" (c32), [cc] "+&r" (*cc) 69 : [b] "T" (b32) 70 : "cc"); 71 *cc >>= 28; 72 73 return (int)c32; 74 } 75 76 /* Test ALCGR (register variant) followed by ALCG (memory variant). */ 77 static unsigned long test64rm(unsigned long a, unsigned long b, 78 unsigned long c, int *cc) 79 { 80 asm("xr %[cc],%[cc]\n" 81 "alcgr %[a],%[b]\n" 82 "alcg %[a],%[c]\n" 83 "ipm %[cc]" 84 : [a] "+&r" (a), [cc] "+&r" (*cc) 85 : [b] "r" (b), [c] "T" (c) 86 : "cc"); 87 *cc >>= 28; 88 return a; 89 } 90 91 /* Test ALCG (memory variant) followed by ALCGR (register variant). */ 92 static unsigned long test64mr(unsigned long a, unsigned long b, 93 unsigned long c, int *cc) 94 { 95 asm("xr %[cc],%[cc]\n" 96 "alcg %[a],%[b]\n" 97 "alcgr %[c],%[a]\n" 98 "ipm %[cc]" 99 : [a] "+&r" (a), [c] "+&r" (c), [cc] "+&r" (*cc) 100 : [b] "T" (b) 101 : "cc"); 102 *cc >>= 28; 103 return c; 104 } 105 106 static const struct test_func { 107 const char *name; 108 unsigned long (*ptr)(unsigned long, unsigned long, unsigned long, int *); 109 } test_funcs[] = { 110 { "test32rm", test32rm }, 111 { "test32mr", test32mr }, 112 { "test64rm", test64rm }, 113 { "test64mr", test64mr }, 114 }; 115 116 static const struct test_perm { 117 const char *name; 118 size_t a_idx, b_idx, c_idx; 119 } test_perms[] = { 120 { "a, b, c", 0, 1, 2 }, 121 { "b, a, c", 1, 0, 2 }, 122 }; 123 124 int main(void) 125 { 126 unsigned long a, b, c, sum; 127 int result = EXIT_SUCCESS; 128 const struct test_func *f; 129 const struct test_perm *p; 130 size_t i, j, k; 131 const struct test *t; 132 int cc; 133 134 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { 135 t = &tests[i]; 136 for (j = 0; j < sizeof(test_funcs) / sizeof(test_funcs[0]); j++) { 137 f = &test_funcs[j]; 138 for (k = 0; k < sizeof(test_perms) / sizeof(test_perms[0]); k++) { 139 p = &test_perms[k]; 140 a = t->values[p->a_idx]; 141 b = t->values[p->b_idx]; 142 c = t->values[p->c_idx]; 143 sum = f->ptr(a, b, c, &cc); 144 if (sum != t->exp_sum || cc != t->exp_cc) { 145 fprintf(stderr, 146 "[ FAILED ] %s %s(0x%lx, 0x%lx, 0x%lx) returned 0x%lx cc %d, expected 0x%lx cc %d\n", 147 t->name, f->name, a, b, c, sum, cc, 148 t->exp_sum, t->exp_cc); 149 result = EXIT_FAILURE; 150 } 151 } 152 } 153 } 154 155 return result; 156 } 157