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} quad_word;
8663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
9663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid
10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengtest(quad_word op1_init, uint64_t op2_init, quad_word op3_init,
11663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng     int expected_cc)
12663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
13663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int cc = 1 - expected_cc;
14663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
15663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   quad_word op1 = op1_init;
16663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint64_t  op2 = op2_init;
17663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   quad_word op3 = op3_init;
18663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   quad_word op1_before = op1;
20663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint64_t  op2_before = op2;
21663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   quad_word op3_before = op3;
22663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("before op1 = (%#lx, %#lx)\n", op1.high, op1.low);
24663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("before op2 =  %#lx\n", op2);
25663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("before op3 = (%#lx, %#lx)\n", op3.high, op3.low);
26663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
27663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   __asm__ volatile (
28663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "lmg     %%r0,%%r1,%1\n\t"
29663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "lmg     %%r2,%%r3,%3\n\t"
30663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "cds     %%r0,%%r2,%2\n\t"  //  cds 1st,3rd,2nd
31663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "stmg    %%r0,%%r1,%1\n"    // store r0,r1 to op1
32663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "stmg    %%r2,%%r3,%3\n"    // store r2,r3 to op3
33663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "ipm     %0\n\t"
34663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     "srl     %0,28\n\t"
35663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     : "=d" (cc), "+QS" (op1), "+QS" (op2), "+QS" (op3)
36663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     :
37663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                     : "r0", "r1", "r2", "r3", "cc");
38663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
39663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("after  op1 = (%#lx, %#lx)\n", op1.high, op1.low);
40663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("after  op2 = %#lx\n", op2);
41663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("after  op3 = (%#lx, %#lx)\n", op3.high, op3.low);
42663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("cc = %d\n", cc);
43663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
44663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // Check the condition code
45663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (cc != expected_cc) {
46663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf("condition code is incorrect\n");
47663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
48663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
49663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // op3 never changes
50663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (op3.low != op3_before.low || op3.high != op3_before.high) {
51663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf("operand #3 modified\n");
52663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
53663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
54663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (expected_cc == 0) {
55663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 3rd operand stored at 2nd operand location
56663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
57663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // op1 did not change
58663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (op1.low != op1_before.low || op1.high != op1_before.high) {
59663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf("operand #1 modified\n");
60663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
61663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
62663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // lower 32 bits of op2 are the lower 32 bits of op3.low
63663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((op2 & 0xffffffff) != (op3.low & 0xffffffff)) {
64663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf("operand #2 [32:63] incorrect\n");
65663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
66663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // higher 32 bits of op2 are the lower 32 bits of op3.high
67663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((op2 >> 32) != (op3.high & 0xffffffff)) {
68663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf("operand #2 [0:31] incorrect\n");
69663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
70663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   } else {
71663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // 2nd operand stored at 1st operand location
72663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
73663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // op2 did not change
74663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (op2 != op2_before) {
75663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf("operand #2 modified\n");
76663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
77663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
78663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      // bits [0:31] of op1 (both parts) are unchanged
79663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((op1.high >> 32) != (op1_before.high >> 32) ||
80663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng          (op1.low  >> 32) != (op1_before.low >> 32)) {
81663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf("operand #1 [0:31] modified\n");
82663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
83663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
84663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((op1.low & 0xffffffff) != (op2 & 0xffffffff)) {
85663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf("operand #1 low[32:63] incorrect\n");
86663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
87663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if ((op1.high & 0xffffffff) != (op2 >> 32)) {
88663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf("operand #1 high[32:63] not updated\n");
89663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
90663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
91663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
92663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
93663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengint main ()
94663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
95663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   quad_word op1, op3;
96663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint64_t  op2;
97663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
98663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // (op1.high[32:63], op1.low[32:63]) == op2
99663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op1.high = 0x0000000044556677ull;
100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op1.low  = 0x111111118899aabbull;
101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op2      = 0x445566778899aabbull;
102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op3.high = op3.low = 0xdeadbeefdeadbabeull;
104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   test(op1, op2, op3, 0);
105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // (op1.high[32:63], op1.low[32:63]) != op2
107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op1.high = 0x1000000000000000ull;
108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op1.low  = 0x0000000000000000ull;
109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op2      = 0x8000000000000001ull;;
110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   op3.high = op3.low = 0xdeadbeefdeadbabeull;
111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   test(op1, op2, op3, 1);
112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return 0;
114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
115