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