1 #include <stdint.h>
2 #include <stdio.h>
3
4 typedef struct {
5 uint64_t high;
6 uint64_t low;
7 } __attribute__((aligned(16))) quad_word;
8
9
10 /* CDSG needs quad-word alignment */
11 quad_word _op1, _op2, _op3;
12
13 void
test(quad_word op1_init,quad_word op2_init,quad_word op3_init,int expected_cc)14 test(quad_word op1_init, quad_word op2_init, quad_word op3_init,
15 int expected_cc)
16 {
17 quad_word op1_before, op2_before, op3_before;
18 int cc = 1 - expected_cc;
19
20 _op1 = op1_init;
21 _op2 = op2_init;
22 _op3 = op3_init;
23
24 op1_before = _op1;
25 op2_before = _op2;
26 op3_before = _op3;
27
28 printf("before op1 = (%#lx, %#lx)\n", _op1.high, _op1.low);
29 printf("before op2 = (%#lx, %#lx)\n", _op2.high, _op2.low);
30 printf("before op3 = (%#lx, %#lx)\n", _op3.high, _op3.low);
31
32 __asm__ volatile (
33 "lmg %%r0,%%r1,%1\n\t"
34 "lmg %%r2,%%r3,%3\n\t"
35 "cdsg %%r0,%%r2,%2\n\t" // cdsg 1st,3rd,2nd
36 "stmg %%r0,%%r1,%1\n" // store r0,r1 to _op1
37 "stmg %%r2,%%r3,%3\n" // store r2,r3 to _op3
38 "ipm %0\n\t"
39 "srl %0,28\n\t"
40 : "=d" (cc), "+QS" (_op1), "+QS" (_op2), "+QS" (_op3)
41 :
42 : "r0", "r1", "r2", "r3", "cc");
43
44 printf("after op1 = (%#lx, %#lx)\n", _op1.high, _op1.low);
45 printf("after op2 = (%#lx, %#lx)\n", _op2.high, _op2.low);
46 printf("after op3 = (%#lx, %#lx)\n", _op3.high, _op3.low);
47 printf("cc = %d\n", cc);
48
49 if (cc != expected_cc) {
50 printf("condition code is incorrect\n");
51 }
52
53 // _op3 never changes
54 if (_op3.low != op3_before.low || _op3.high != op3_before.high) {
55 printf("operand #3 modified\n");
56 }
57
58 if (expected_cc == 0) {
59 // 3rd operand stored at 2nd operand location
60
61 // _op1 did not change
62 if (_op1.low != op1_before.low || _op1.high != op1_before.high) {
63 printf("operand #1 modified\n");
64 }
65 if (_op2.high != _op3.high || _op2.low != _op3.low) {
66 printf("operand #2 incorrect\n");
67 }
68 } else {
69 // 2nd operand stored at 1st operand location
70
71 // _op2 did not change
72 if (_op2.low != op2_before.low || _op2.high != op2_before.high) {
73 printf("operand #2 modified\n");
74 }
75
76 if (_op1.high != _op2.high || _op1.low != _op2.low) {
77 printf("operand #1 incorrect\n");
78 }
79 }
80 }
81
main()82 int main ()
83 {
84 quad_word op1, op2, op3;
85
86 // op1 == op2
87 op1.high = 0x0011223344556677ull;
88 op1.low = 0x8899aabbccddeeffull;
89 op2 = op1;
90 op3.high = op3.low = 0xdeadbeefdeadbabeull;
91 test(op1, op2, op3, 0);
92
93 // op1 != op2 (only MSB differs)
94 op1.high = 0x8000000000000000ull;
95 op1.low = 0x0000000000000000ull;
96 op2.high = 0;
97 op2.low = 1;
98 op3.high = op3.low = 0xdeadbeefdeadbabeull;
99 test(op1, op2, op3, 1);
100
101 // op1 != op2 (only LSB differs)
102 op1.high = 0x0000000000000000ull;
103 op1.low = 0x0000000000000001ull;
104 op2.high = 1;
105 op2.low = 0;
106 op3.high = op3.low = 0xdeadbeefdeadbabeull;
107 test(op1, op2, op3, 1);
108
109 return 0;
110 }
111