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 } __attribute__((aligned(16))) quad_word;
      8 
      9 
     10 /* CDSG needs quad-word alignment */
     11 quad_word _op1, _op2, _op3;
     12 
     13 void
     14 test(quad_word op1_init, quad_word op2_init, quad_word op3_init,
     15      int expected_cc)
     16 {
     17    quad_word op1_before, op2_before, op3_before;
     18    int cc = 1 - expected_cc;
     19 
     20    _op1 = op1_init;
     21    _op2 = op2_init;
     22    _op3 = op3_init;
     23 
     24    op1_before = _op1;
     25    op2_before = _op2;
     26    op3_before = _op3;
     27 
     28    printf("before op1 = (%#lx, %#lx)\n", _op1.high, _op1.low);
     29    printf("before op2 = (%#lx, %#lx)\n", _op2.high, _op2.low);
     30    printf("before op3 = (%#lx, %#lx)\n", _op3.high, _op3.low);
     31 
     32    __asm__ volatile (
     33                      "lmg     %%r0,%%r1,%1\n\t"
     34                      "lmg     %%r2,%%r3,%3\n\t"
     35                      "cdsg    %%r0,%%r2,%2\n\t"  //  cdsg 1st,3rd,2nd
     36                      "stmg    %%r0,%%r1,%1\n"    // store r0,r1 to _op1
     37                      "stmg    %%r2,%%r3,%3\n"    // store r2,r3 to _op3
     38                      "ipm     %0\n\t"
     39                      "srl     %0,28\n\t"
     40                      : "=d" (cc), "+QS" (_op1), "+QS" (_op2), "+QS" (_op3)
     41                      :
     42                      : "r0", "r1", "r2", "r3", "cc");
     43 
     44    printf("after  op1 = (%#lx, %#lx)\n", _op1.high, _op1.low);
     45    printf("after  op2 = (%#lx, %#lx)\n", _op2.high, _op2.low);
     46    printf("after  op3 = (%#lx, %#lx)\n", _op3.high, _op3.low);
     47    printf("cc = %d\n", cc);
     48 
     49    if (cc != expected_cc) {
     50       printf("condition code is incorrect\n");
     51    }
     52 
     53    // _op3 never changes
     54    if (_op3.low != op3_before.low || _op3.high != op3_before.high) {
     55       printf("operand #3 modified\n");
     56    }
     57 
     58    if (expected_cc == 0) {
     59       // 3rd operand stored at 2nd operand location
     60 
     61       // _op1 did not change
     62       if (_op1.low != op1_before.low || _op1.high != op1_before.high) {
     63          printf("operand #1 modified\n");
     64       }
     65       if (_op2.high != _op3.high || _op2.low != _op3.low) {
     66          printf("operand #2 incorrect\n");
     67       }
     68    } else {
     69       // 2nd operand stored at 1st operand location
     70 
     71       // _op2 did not change
     72       if (_op2.low != op2_before.low || _op2.high != op2_before.high) {
     73          printf("operand #2 modified\n");
     74       }
     75 
     76       if (_op1.high != _op2.high || _op1.low != _op2.low) {
     77          printf("operand #1 incorrect\n");
     78       }
     79    }
     80 }
     81 
     82 int main ()
     83 {
     84    quad_word op1, op2, op3;
     85 
     86    // op1 == op2
     87    op1.high = 0x0011223344556677ull;
     88    op1.low  = 0x8899aabbccddeeffull;
     89    op2 = op1;
     90    op3.high = op3.low = 0xdeadbeefdeadbabeull;
     91    test(op1, op2, op3, 0);
     92 
     93    // op1 != op2 (only MSB differs)
     94    op1.high = 0x8000000000000000ull;
     95    op1.low  = 0x0000000000000000ull;
     96    op2.high = 0;
     97    op2.low  = 1;
     98    op3.high = op3.low = 0xdeadbeefdeadbabeull;
     99    test(op1, op2, op3, 1);
    100 
    101    // op1 != op2 (only LSB differs)
    102    op1.high = 0x0000000000000000ull;
    103    op1.low  = 0x0000000000000001ull;
    104    op2.high = 1;
    105    op2.low  = 0;
    106    op3.high = op3.low = 0xdeadbeefdeadbabeull;
    107    test(op1, op2, op3, 1);
    108 
    109    return 0;
    110 }
    111