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