1663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include <stdint.h>
2663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include <inttypes.h>
3663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include <stdlib.h>
4663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include <string.h>
5663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include <stdio.h>
6663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "opcodes.h"
7663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
8663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#ifndef M3
9663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#define M3 0
10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#endif
11663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
12663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* The abstracted result of an CU24 insn */
13663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengtypedef struct {
14663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint64_t addr1;  // target
15663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint64_t len1;
16663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint64_t addr2;  // source
17663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint64_t len2;
18663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint32_t cc;
19663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} cu24_t;
20663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Define various input buffers. */
22663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Single UTF-16 value */
24663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint16_t pattern1[] = {
25663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x0000, 0xd7ff,    /* [0000 ... d7ff]  corner cases */
26663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xdc00, 0xffff,    /* [dc00 ... ffff]  corner cases */
27663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x0047, 0x0156, 0x1245, 0xa021, 0xfffe /* misc */
28663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng};
29663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
30663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* UTF-16 surrogate pair */
31663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint16_t pattern2[] = {
32663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xd800, 0xdc00,    /* left  corner case */
33663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xdbff, 0xdfff,    /* right corner case */
34663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xdada, 0xdddd, 0xdeaf, 0xdcdc  /* misc */
35663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng};
36663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
37663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Invalid low surrogate */
38663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint16_t invalid[] = { 0xd801, 0x0098 };
39663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
40663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Mixed bytes */
41663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint16_t mixed[] = {
42663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x0078,
43663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x0200,
44663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xffff,
45663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xd800, 0xdc01,
46663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xde00, 0xdd00,
47663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc0c0
48663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng};
49663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
50663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* This is the buffer for the converted bytes. */
51663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint32_t buff[1000];  /* Large so we con'don't have to worry about it */
52663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
53663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
54663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic cu24_t
55663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengdo_cu24(uint32_t *dst, uint64_t dst_len, uint16_t *src, uint64_t src_len)
56663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
57663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int cc = 42;
58663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   cu24_t regs;
59663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
60663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* build up the register pairs */
61663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   register uint16_t *source     asm("4") = src;
62663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   register uint64_t  source_len asm("5") = src_len;
63663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   register uint32_t *dest       asm("2") = dst;
64663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   register uint64_t  dest_len   asm("3") = dst_len;
65663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
66663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   asm volatile(
67663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                CU24(M3,2,4)
68663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                "ipm %2\n\t"
69663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                "srl %2,28\n\t"
70663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                : "+d"(dest), "+d"(source), "=d"(cc),
71663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  "+d"(source_len), "+d"(dest_len)
72663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                :
73663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                : "memory", "cc");
74663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
75663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Capture register contents at end of cu24 */
76663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.addr1 = (uint64_t)dest;
77663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.len1  = dest_len;
78663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.addr2 = (uint64_t)source;
79663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.len2  = source_len;
80663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.cc = cc;
81663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
82663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return regs;
83663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
84663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
85663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid
86663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengrun_test(uint32_t *dst, uint64_t dst_len, uint16_t *src, uint64_t src_len)
87663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
88663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int i;
89663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   cu24_t result;
90663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
91663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   result = do_cu24(dst, dst_len, src, src_len);
92663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
93663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // Write out the converted byte, if any
94663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("UTF32: ");
95663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (dst_len - result.len1 == 0)
96663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf(" <none>");
97663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else {
98663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint64_t num_bytes = dst_len - result.len1;
99663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* The number of bytes that were written must be divisible by 4 */
101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (num_bytes % 4 != 0)
102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fprintf(stderr, "*** number of bytes is not a multiple of 4\n");
103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (i = 0; i < num_bytes / 4; i++) {
105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf(" %02x", dst[i]);
106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n");
109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("  cc = %d\n", result.cc);
111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (dst != NULL)
112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf("  dst address difference: %"PRId64, result.addr1 - (uint64_t)dst);
113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("  dst len: %"PRId64"\n", result.len1);
114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (src != NULL)
116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf("  src address difference: %"PRId64, result.addr2 - (uint64_t)src);
117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("  src len: %"PRId64"\n", result.len2);
118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengint main()
121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Length == 0, no memory should be read or written */
123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test1 ----------------\n");
124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 0, NULL, 0);
125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Test exhaustion of source length (source bytes are valid) */
127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test2.1 ----------------\n");
128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* No character will be written to BUFF, i.e. loop in jitted code
130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      is not iterated */
131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, NULL,     1);
132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern1, 1);
133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern2, 1);
134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern2, 2);
135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern2, 3);
136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test2.2 ----------------\n");
138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* At least one character will be written to BUFF, i.e. loop in jitted
139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      code is iterated */
140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern1, 3);
141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern1, 5);
142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern2, 2);
143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern2, 5);
144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern2, 7);
145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Test exhaustion of destination length (source bytes are valid) */
147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test3.1 ----------------\n");
148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* No character will be written to BUFF, i.e. loop in jitted code
150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      is not iterated */
151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Want to write 4 bytes at a time */
153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 0, pattern1, sizeof pattern1);
154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 1, pattern1, sizeof pattern1);
155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 2, pattern1, sizeof pattern1);
156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 3, pattern1, sizeof pattern1);
157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test3.2 ----------------\n");
159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* At least one character will be written to BUFF, i.e. loop in jitted
160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      code is iterated */
161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 4, pattern1, sizeof pattern1);
162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 5, pattern1, sizeof pattern1);
163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 6, pattern1, sizeof pattern1);
164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 7, pattern1, sizeof pattern1);
165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* When both operands are exhausted, cc=0 takes precedence.
167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      (test1 tests this for len == 0) */
168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test4 ----------------\n");
169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 4, pattern1, 2);   // no iteration
170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 8, pattern1, 4);   // iteration
171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Input has invalid low surrogate. */
173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test5 ----------------\n");
174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, invalid, sizeof invalid);
175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 0, invalid, sizeof invalid);
176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Convert all pattern buffers */
178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test6 ----------------\n");
179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern1, sizeof pattern1);
180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern2, sizeof pattern2);
181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return 0;
183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
184