Home | History | Annotate | Download | only in s390x
      1 #include <stdint.h>
      2 #include <inttypes.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <stdio.h>
      6 #include "opcodes.h"
      7 
      8 #ifndef M3
      9 #define M3 0
     10 #endif
     11 
     12 /* The abstracted result of an CU24 insn */
     13 typedef struct {
     14    uint64_t addr1;  // target
     15    uint64_t len1;
     16    uint64_t addr2;  // source
     17    uint64_t len2;
     18    uint32_t cc;
     19 } cu24_t;
     20 
     21 /* Define various input buffers. */
     22 
     23 /* Single UTF-16 value */
     24 uint16_t pattern1[] = {
     25    0x0000, 0xd7ff,    /* [0000 ... d7ff]  corner cases */
     26    0xdc00, 0xffff,    /* [dc00 ... ffff]  corner cases */
     27    0x0047, 0x0156, 0x1245, 0xa021, 0xfffe /* misc */
     28 };
     29 
     30 /* UTF-16 surrogate pair */
     31 uint16_t pattern2[] = {
     32    0xd800, 0xdc00,    /* left  corner case */
     33    0xdbff, 0xdfff,    /* right corner case */
     34    0xdada, 0xdddd, 0xdeaf, 0xdcdc  /* misc */
     35 };
     36 
     37 /* Invalid low surrogate */
     38 uint16_t invalid[] = { 0xd801, 0x0098 };
     39 
     40 /* Mixed bytes */
     41 uint16_t mixed[] = {
     42    0x0078,
     43    0x0200,
     44    0xffff,
     45    0xd800, 0xdc01,
     46    0xde00, 0xdd00,
     47    0xc0c0
     48 };
     49 
     50 /* This is the buffer for the converted bytes. */
     51 uint32_t buff[1000];  /* Large so we con'don't have to worry about it */
     52 
     53 
     54 static cu24_t
     55 do_cu24(uint32_t *dst, uint64_t dst_len, uint16_t *src, uint64_t src_len)
     56 {
     57    int cc = 42;
     58    cu24_t regs;
     59 
     60    /* build up the register pairs */
     61    register uint16_t *source     asm("4") = src;
     62    register uint64_t  source_len asm("5") = src_len;
     63    register uint32_t *dest       asm("2") = dst;
     64    register uint64_t  dest_len   asm("3") = dst_len;
     65 
     66    asm volatile(
     67                 CU24(M3,2,4)
     68                 "ipm %2\n\t"
     69                 "srl %2,28\n\t"
     70                 : "+d"(dest), "+d"(source), "=d"(cc),
     71                   "+d"(source_len), "+d"(dest_len)
     72                 :
     73                 : "memory", "cc");
     74 
     75    /* Capture register contents at end of cu24 */
     76    regs.addr1 = (uint64_t)dest;
     77    regs.len1  = dest_len;
     78    regs.addr2 = (uint64_t)source;
     79    regs.len2  = source_len;
     80    regs.cc = cc;
     81 
     82    return regs;
     83 }
     84 
     85 void
     86 run_test(uint32_t *dst, uint64_t dst_len, uint16_t *src, uint64_t src_len)
     87 {
     88    int i;
     89    cu24_t result;
     90 
     91    result = do_cu24(dst, dst_len, src, src_len);
     92 
     93    // Write out the converted byte, if any
     94    printf("UTF32: ");
     95    if (dst_len - result.len1 == 0)
     96       printf(" <none>");
     97    else {
     98       uint64_t num_bytes = dst_len - result.len1;
     99 
    100       /* The number of bytes that were written must be divisible by 4 */
    101       if (num_bytes % 4 != 0)
    102          fprintf(stderr, "*** number of bytes is not a multiple of 4\n");
    103 
    104       for (i = 0; i < num_bytes / 4; i++) {
    105          printf(" %02x", dst[i]);
    106       }
    107    }
    108    printf("\n");
    109 
    110    printf("  cc = %d\n", result.cc);
    111    if (dst != NULL)
    112       printf("  dst address difference: %"PRId64, result.addr1 - (uint64_t)dst);
    113    printf("  dst len: %"PRId64"\n", result.len1);
    114 
    115    if (src != NULL)
    116       printf("  src address difference: %"PRId64, result.addr2 - (uint64_t)src);
    117    printf("  src len: %"PRId64"\n", result.len2);
    118 }
    119 
    120 int main()
    121 {
    122    /* Length == 0, no memory should be read or written */
    123    printf("\n------------- test1 ----------------\n");
    124    run_test(NULL, 0, NULL, 0);
    125 
    126    /* Test exhaustion of source length (source bytes are valid) */
    127    printf("\n------------- test2.1 ----------------\n");
    128 
    129    /* No character will be written to BUFF, i.e. loop in jitted code
    130       is not iterated */
    131    run_test(buff, sizeof buff, NULL,     1);
    132    run_test(buff, sizeof buff, pattern1, 1);
    133    run_test(buff, sizeof buff, pattern2, 1);
    134    run_test(buff, sizeof buff, pattern2, 2);
    135    run_test(buff, sizeof buff, pattern2, 3);
    136 
    137    printf("\n------------- test2.2 ----------------\n");
    138    /* At least one character will be written to BUFF, i.e. loop in jitted
    139       code is iterated */
    140    run_test(buff, sizeof buff, pattern1, 3);
    141    run_test(buff, sizeof buff, pattern1, 5);
    142    run_test(buff, sizeof buff, pattern2, 2);
    143    run_test(buff, sizeof buff, pattern2, 5);
    144    run_test(buff, sizeof buff, pattern2, 7);
    145 
    146    /* Test exhaustion of destination length (source bytes are valid) */
    147    printf("\n------------- test3.1 ----------------\n");
    148 
    149    /* No character will be written to BUFF, i.e. loop in jitted code
    150       is not iterated */
    151 
    152    /* Want to write 4 bytes at a time */
    153    run_test(NULL, 0, pattern1, sizeof pattern1);
    154    run_test(NULL, 1, pattern1, sizeof pattern1);
    155    run_test(NULL, 2, pattern1, sizeof pattern1);
    156    run_test(NULL, 3, pattern1, sizeof pattern1);
    157 
    158    printf("\n------------- test3.2 ----------------\n");
    159    /* At least one character will be written to BUFF, i.e. loop in jitted
    160       code is iterated */
    161    run_test(buff, 4, pattern1, sizeof pattern1);
    162    run_test(buff, 5, pattern1, sizeof pattern1);
    163    run_test(buff, 6, pattern1, sizeof pattern1);
    164    run_test(buff, 7, pattern1, sizeof pattern1);
    165 
    166    /* When both operands are exhausted, cc=0 takes precedence.
    167       (test1 tests this for len == 0) */
    168    printf("\n------------- test4 ----------------\n");
    169    run_test(buff, 4, pattern1, 2);   // no iteration
    170    run_test(buff, 8, pattern1, 4);   // iteration
    171 
    172    /* Input has invalid low surrogate. */
    173    printf("\n------------- test5 ----------------\n");
    174    run_test(buff, sizeof buff, invalid, sizeof invalid);
    175    run_test(buff, 0, invalid, sizeof invalid);
    176 
    177    /* Convert all pattern buffers */
    178    printf("\n------------- test6 ----------------\n");
    179    run_test(buff, sizeof buff, pattern1, sizeof pattern1);
    180    run_test(buff, sizeof buff, pattern2, sizeof pattern2);
    181 
    182    return 0;
    183 }
    184