1#include <stdint.h> 2#include <stdio.h> 3 4typedef struct { 5 uint64_t high; 6 uint64_t low; 7} quad_word; 8 9void 10test(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 93int 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