Home | History | Annotate | Download | only in s390x
      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
     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 
     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