• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
do_cu24(uint32_t * dst,uint64_t dst_len,uint16_t * src,uint64_t src_len)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
run_test(uint32_t * dst,uint64_t dst_len,uint16_t * src,uint64_t src_len)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 
main()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