1663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include <stdint.h>
2663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include <stdio.h>
3663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
4663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengtypedef struct {
5663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint64_t high;
6663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint64_t low;
7663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} __attribute__((aligned(16))) quad_word;
8663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* CDSG needs quad-word alignment */
11663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengquad_word _op1, _op2, _op3;
12663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
13663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid
14663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengtest(quad_word op1_init, quad_word op2_init, quad_word op3_init,
15663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     int expected_cc)
16663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
17663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   quad_word op1_before, op2_before, op3_before;
18663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int cc = 1 - expected_cc;
19663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
20663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   _op1 = op1_init;
21663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   _op2 = op2_init;
22663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   _op3 = op3_init;
23663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op1_before = _op1;
25663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op2_before = _op2;
26663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op3_before = _op3;
27663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
28663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("before op1 = (%#lx, %#lx)\n", _op1.high, _op1.low);
29663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("before op2 = (%#lx, %#lx)\n", _op2.high, _op2.low);
30663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("before op3 = (%#lx, %#lx)\n", _op3.high, _op3.low);
31663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
32663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   __asm__ volatile (
33663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "lmg     %%r0,%%r1,%1\n\t"
34663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "lmg     %%r2,%%r3,%3\n\t"
35663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "cdsg    %%r0,%%r2,%2\n\t"  //  cdsg 1st,3rd,2nd
36663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "stmg    %%r0,%%r1,%1\n"    // store r0,r1 to _op1
37663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "stmg    %%r2,%%r3,%3\n"    // store r2,r3 to _op3
38663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "ipm     %0\n\t"
39663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "srl     %0,28\n\t"
40663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     : "=d" (cc), "+QS" (_op1), "+QS" (_op2), "+QS" (_op3)
41663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     :
42663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     : "r0", "r1", "r2", "r3", "cc");
43663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
44663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("after  op1 = (%#lx, %#lx)\n", _op1.high, _op1.low);
45663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("after  op2 = (%#lx, %#lx)\n", _op2.high, _op2.low);
46663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("after  op3 = (%#lx, %#lx)\n", _op3.high, _op3.low);
47663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("cc = %d\n", cc);
48663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
49663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (cc != expected_cc) {
50663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf("condition code is incorrect\n");
51663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
52663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
53663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // _op3 never changes
54663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (_op3.low != op3_before.low || _op3.high != op3_before.high) {
55663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf("operand #3 modified\n");
56663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
57663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
58663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (expected_cc == 0) {
59663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 3rd operand stored at 2nd operand location
60663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
61663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // _op1 did not change
62663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (_op1.low != op1_before.low || _op1.high != op1_before.high) {
63663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf("operand #1 modified\n");
64663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
65663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (_op2.high != _op3.high || _op2.low != _op3.low) {
66663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf("operand #2 incorrect\n");
67663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
68663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
69663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 2nd operand stored at 1st operand location
70663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
71663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // _op2 did not change
72663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (_op2.low != op2_before.low || _op2.high != op2_before.high) {
73663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf("operand #2 modified\n");
74663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
75663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
76663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (_op1.high != _op2.high || _op1.low != _op2.low) {
77663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf("operand #1 incorrect\n");
78663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
79663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
80663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
81663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
82663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengint main ()
83663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
84663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   quad_word op1, op2, op3;
85663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
86663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // op1 == op2
87663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op1.high = 0x0011223344556677ull;
88663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op1.low  = 0x8899aabbccddeeffull;
89663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op2 = op1;
90663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op3.high = op3.low = 0xdeadbeefdeadbabeull;
91663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   test(op1, op2, op3, 0);
92663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
93663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // op1 != op2 (only MSB differs)
94663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op1.high = 0x8000000000000000ull;
95663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op1.low  = 0x0000000000000000ull;
96663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op2.high = 0;
97663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op2.low  = 1;
98663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op3.high = op3.low = 0xdeadbeefdeadbabeull;
99663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   test(op1, op2, op3, 1);
100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // op1 != op2 (only LSB differs)
102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op1.high = 0x0000000000000000ull;
103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op1.low  = 0x0000000000000001ull;
104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op2.high = 1;
105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op2.low  = 0;
106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op3.high = op3.low = 0xdeadbeefdeadbabeull;
107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   test(op1, op2, op3, 1);
108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return 0;
110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
111