cu12.c revision 663860b1408516d02ebfcb3a9999a134e6cfb223
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 CU12 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} cu12_t;
20663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
21663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Define various input buffers. */
22663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
23663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 1-byte UTF-8 character */
24663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint8_t pattern1[] = {
25663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x00, 0x01, 0x02, 0x03
26663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng};
27663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
28663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 2-byte UTF-8 character */
29663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint8_t pattern2[] = {
30663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc2, 0x80,
31663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc2, 0x81,
32663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc2, 0x82,
33663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc2, 0x83,
34663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng};
35663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
36663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 3-byte UTF-8 character */
37663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint8_t pattern3[] = {
38663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe1, 0x80, 0x80,
39663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe1, 0x80, 0x81,
40663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe1, 0x80, 0x82,
41663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe1, 0x80, 0x83,
42663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng};
43663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
44663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* 4-byte UTF-8 character */
45663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint8_t pattern4[] = {
46663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xf4, 0x80, 0x80, 0x80,
47663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xf4, 0x80, 0x80, 0x81,
48663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xf4, 0x80, 0x80, 0x82,
49663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xf4, 0x80, 0x80, 0x83,
50663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng};
51663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
52663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
53663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Mixed bytes */
54663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint8_t mixed[] = {
55663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x01,                    // 1 byte
56663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc3, 0x80,              // 2 bytes
57663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x12,                    // 1 byte
58663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe1, 0x90, 0x93,        // 3 bytes
59663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x23,                    // 1 byte
60663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xf4, 0x80, 0x90, 0x8a,  // 4 bytes
61663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0x34,                    // 1 byte
62663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc4, 0x8c,              // 2 bytes
63663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe1, 0x91, 0x94,        // 3 bytes
64663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc5, 0x8a,              // 2 bytes
65663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xf4, 0x80, 0x90, 0x8a,  // 4 bytes
66663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xc5, 0x8a,              // 2 bytes
67663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe1, 0x91, 0x94,        // 3 bytes
68663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xf4, 0x80, 0x90, 0x8a,  // 4 bytes
69663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   0xe1, 0x91, 0x94,        // 3 bytes
70663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng};
71663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
72663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* This is the buffer for the converted bytes. */
73663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint16_t buff[1000];  /* Large so we con'don't have to worry about it */
74663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
75663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
76663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengstatic cu12_t
77663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengdo_cu12(uint16_t *dst, uint64_t dst_len, uint8_t *src, uint64_t src_len)
78663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
79663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int cc = 42;
80663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   cu12_t regs;
81663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
82663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* build up the register pairs */
83663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   register uint8_t  *source     asm("4") = src;
84663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   register uint64_t  source_len asm("5") = src_len;
85663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   register uint16_t *dest       asm("2") = dst;
86663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   register uint64_t  dest_len   asm("3") = dst_len;
87663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
88663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   asm volatile(
89663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                CU12(M3,2,4)
90663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                "ipm %2\n\t"
91663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                "srl %2,28\n\t"
92663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                : "+d"(dest), "+d"(source), "=d"(cc),
93663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                  "+d"(source_len), "+d"(dest_len)
94663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                :
95663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                : "memory", "cc");
96663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
97663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Capture register contents at end of cu12 */
98663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.addr1 = (uint64_t)dest;
99663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.len1  = dest_len;
100663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.addr2 = (uint64_t)source;
101663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.len2  = source_len;
102663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.cc = cc;
103663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
104663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return regs;
105663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
106663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
107663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid
108663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengrun_test(uint16_t *dst, uint64_t dst_len, uint8_t *src, uint64_t src_len)
109663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
110663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int i;
111663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   cu12_t result;
112663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
113663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("UTF8:  ");
114663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (src_len == 0)
115663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf(" <none>");
116663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else {
117663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for(i = 0; i < src_len; ++i)
118663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf(" %02x", src[i]);
119663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
120663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n");
121663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
122663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   result = do_cu12(dst, dst_len, src, src_len);
123663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
124663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // Write out the converted byte, if any
125663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("UTF16: ");
126663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (dst_len - result.len1 == 0)
127663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf(" <none>");
128663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   else {
129663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint64_t num_bytes = dst_len - result.len1;
130663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
131663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      /* The number of bytes that were written must be divisible by 2 */
132663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (num_bytes % 2 != 0)
133663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         fprintf(stderr, "*** number of bytes is not a multiple of 2\n");
134663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
135663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (i = 0; i < num_bytes / 2; i++) {
136663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         printf(" %04x", dst[i]);
137663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
138663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
139663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n");
140663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
141663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("  cc = %d\n", result.cc);
142663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (dst != NULL)
143663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf("  dst address difference: %"PRId64, result.addr1 - (uint64_t)dst);
144663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("  dst len: %"PRId64"\n", result.len1);
145663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
146663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (src != NULL)
147663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf("  src address difference: %"PRId64, result.addr2 - (uint64_t)src);
148663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("  src len: %"PRId64"\n", result.len2);
149663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
150663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
151663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// Test conversion of a one-byte character
152663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid convert_1_byte(void)
153663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
154663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int i;
155663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
156663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("===== Conversion of a one-byte character =====\n");
157663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
158663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Valid characters -----\n");
159663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t valid[] = {
160663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0x00, 0x7f,              // corner cases
161663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0x01, 0x10, 0x7e, 0x5d   // misc
162663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
163663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, valid, sizeof valid);
164663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
165663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // As conversion stops upon encountering an invalid character, we
166663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // need to test each invalid character separately, to make sure it
167663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // is recognized as invalid.
168663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
169663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Invalid characters -----\n");
170663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t always_invalid[] = {
171663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0x80, 0xbf,              // corner cases
172663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xf8, 0xff,              // corner cases
173663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0x81, 0xbe, 0x95, 0xab   // misc
174663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
175663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < sizeof always_invalid; ++i) {
176663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t invalid_char[1];
177663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      invalid_char[0] = always_invalid[i];
178663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, invalid_char, sizeof invalid_char);
179663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
180663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
181663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // In case of m3 == 0 we get cc=0 indicating exhaustion of source
182663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Invalid characters if m3 == 1 -----\n");
183663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t invalid_if_m3[] = {  // contains all such invalid characters
184663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc0, 0xc1,
185663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xf5, 0xf6, 0xf7
186663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
187663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < sizeof invalid_if_m3; ++i) {
188663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t invalid_char[1];
189663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      invalid_char[0] = invalid_if_m3[i];
190663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, invalid_char, sizeof invalid_char);
191663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
192663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
193663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- 1st char valid, 2nd char invalid -----\n");
194663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t valid_invalid[] = {
195663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0x10, // valid
196663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xaa  // invalid
197663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
198663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, valid_invalid, sizeof valid_invalid);
199663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
200663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
201663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// Test conversion of a two-byte character
202663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid convert_2_bytes(void)
203663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
204663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int i;
205663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
206663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n===== Conversion of a two-byte character =====\n");
207663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
208663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Valid characters -----\n");
209663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t valid[] = {
210663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc2, 0x80,             // corner case
211663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc2, 0xbf,             // corner case
212663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xdf, 0x80,             // corner case
213663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xdf, 0xbf,             // corner case
214663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc3, 0xbe, 0xda, 0xbc  // misc
215663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
216663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, valid, sizeof valid);
217663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
218663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Valid characters if m3 == 0 -----\n");
219663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // First char is 0xc0 or 0xc1
220663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t valid_if_not_m3[] = {
221663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc0, 0x80,
222663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc0, 0xbf,
223663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc1, 0x80,
224663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc0, 0xbf
225663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
226663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, valid_if_not_m3, sizeof valid_if_not_m3);
227663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
228663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // Test for invalid two-byte characters where the 1st byte is valid
229663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // The 2nd byte is invalid if not in range 0x80..0xbf, inclusive
230663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
231663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // As conversion stops upon encountering an invalid character, we
232663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // need to test each invalid character separately, to make sure it
233663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // is recognized as invalid.
234663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
235663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Invalid characters if m3 == 1 -----\n");
236663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t always_invalid[] = {
237663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc2, 0x00,
238663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc2, 0x7f,
239663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc2, 0xc0,
240663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc2, 0xff
241663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
242663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i < sizeof always_invalid; i += 2) {
243663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t invalid_char[2];
244663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      invalid_char[0] = always_invalid[i];
245663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      invalid_char[1] = always_invalid[i+1];
246663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, invalid_char, sizeof invalid_char);
247663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
248663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
249663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Nb: for a two-byte character we need not test the case where
250663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      invalidity of the character (cc=2) takes precedence over exhaustion
251663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      of the 1st operand (cc=1). Invalidity of the character has already
252663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      been tested when testing the 1st byte. */
253663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
254663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- 1st char valid, 2nd char invalid -----\n");
255663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t valid_invalid[] = {
256663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc3, 0x81, // valid
257663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xc4, 0x00  // invalid
258663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
259663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, valid_invalid, sizeof valid_invalid);
260663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
261663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
262663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// Test conversion of a three-byte character
263663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid
264663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengconvert_3_bytes(void)
265663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
266663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int i;
267663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
268663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n===== Conversion of a three-byte character =====\n");
269663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
270663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Exhaustively test the 1st byte E0 - EF, and the interval boundaries for
271663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      the 2nd and 3rd bytes */
272663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Valid characters -----\n");
273663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t e0[] = {
274663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xe0, 0xa0, 0x80,
275663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xe0, 0xbf, 0x80,
276663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xe0, 0xa0, 0xbf,
277663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xe0, 0xbf, 0xbf,
278663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xe0, 0xaa, 0xbb,   // random  e0 .. ..
279663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
280663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, e0, sizeof e0);
281663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
282663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t ed[] = {
283663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xed, 0x80, 0x80,
284663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xed, 0x9f, 0x80,
285663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xed, 0x80, 0xbf,
286663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xed, 0x9f, 0xbf,
287663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xed, 0x8a, 0xbb,   // random  ed .. ..
288663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
289663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, ed, sizeof ed);
290663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
291663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i <= 0xf; ++i) {
292663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t exxx_1[3] = { 0x0, 0x80, 0x80 };
293663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t exxx_2[3] = { 0x0, 0xbf, 0x80 };
294663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t exxx_3[3] = { 0x0, 0x80, 0xbf };
295663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t exxx_4[3] = { 0x0, 0xbf, 0xbf };
296663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
297663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (i == 0x00) continue;   // special case e0
298663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (i == 0x0d) continue;   // special case ed
299663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
300663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exxx_1[0] = 0xe0 | i;
301663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exxx_2[0] = 0xe0 | i;
302663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exxx_3[0] = 0xe0 | i;
303663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exxx_4[0] = 0xe0 | i;
304663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, exxx_1, sizeof exxx_1);
305663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, exxx_2, sizeof exxx_2);
306663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, exxx_3, sizeof exxx_3);
307663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, exxx_4, sizeof exxx_4);
308663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
309663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
310663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Invalid characters (2nd byte is invalid) -----\n");
311663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // Test for invalid three-byte characters where the 1st byte is valid
312663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // The 2nd byte is invalid.
313663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
314663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // As conversion stops upon encountering an invalid character, we
315663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // need to test each invalid character separately, to make sure it
316663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // is recognized as invalid.
317663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
318663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   e0[0] = 0xe0;  // valid
319663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   e0[1] = 0x9f;  // invalid  because outside [0xa0 .. 0xbf]
320663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   e0[2] = 0x80;  // valid
321663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, e0, sizeof e0);
322663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   e0[1] = 0xc0;  // invalid  because outside [0xa0 .. 0xbf]
323663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, e0, sizeof e0);
324663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
325663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ed[0] = 0xed;  // valid
326663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ed[1] = 0x7f;  // invalid  because outside [0x80 .. 0x9f]
327663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ed[2] = 0x80;  // valid
328663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, ed, sizeof ed);
329663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   ed[1] = 0xa0;  // invalid  because outside [0x80 .. 0x9f]
330663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, ed, sizeof ed);
331663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
332663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i <= 0xf; ++i) {
333663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t exxx_1[3] = { 0x0, 0x7f, 0x80 };
334663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t exxx_2[3] = { 0x0, 0xc0, 0x80 };
335663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
336663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (i == 0x00) continue;   // special case e0
337663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (i == 0x0d) continue;   // special case ed
338663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
339663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exxx_1[0] = 0xe0 | i;
340663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exxx_2[0] = 0xe0 | i;
341663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, exxx_1, sizeof exxx_1);
342663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, exxx_2, sizeof exxx_2);
343663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
344663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
345663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Invalid characters (3rd byte is invalid) -----\n");
346663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // For all 1st bytes 0xe0 .. 0xef the 3rd bytes must be in [0x80 .. 0xbf]
347663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // No need to special case 0xe0 and 0xed
348663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i <= 0xf; ++i) {
349663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t exxx_1[3] = { 0x0, 0xab, 0x7f };
350663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t exxx_2[3] = { 0x0, 0xab, 0xc0 };
351663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
352663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exxx_1[0] = 0xe0 | i;
353663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exxx_2[0] = 0xe0 | i;
354663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, exxx_1, sizeof exxx_1);
355663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, exxx_2, sizeof exxx_2);
356663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
357663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
358663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Invalid 2nd char AND output exhausted -----\n");
359663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* The character is invalid in its 2nd byte AND the output buffer is
360663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exhausted (2 bytes are needed) */
361663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t pat1[] = {
362663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xe0, 0x00, 0x80
363663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
364663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 1, pat1, 3);
365663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
366663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Invalid 3rd char AND output exhausted -----\n");
367663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* The character is invalid in its 3rd byte AND the output buffer is
368663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exhausted (2 bytes are needed) */
369663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t pat2[] = {
370663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xe4, 0x84, 0x00
371663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
372663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 1, pat2, 3);
373663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
374663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- 1st char valid, 2nd char invalid -----\n");
375663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t valid_invalid[] = {
376663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xe1, 0x90, 0x90, // valid
377663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xe1, 0x00, 0x90  // invalid
378663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
379663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, valid_invalid, sizeof valid_invalid);
380663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
381663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
382663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng// Test conversion of a four-byte character
383663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid
384663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengconvert_4_bytes(void)
385663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
386663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int i, j;
387663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
388663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n===== Conversion of a four-byte character =====\n");
389663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
390663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Valid characters -----\n");
391663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i <= 4; ++i) {
392663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t valid[4];
393663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
394663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      valid[0] = 0xf0 | i;
395663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
396663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      for (j = 0; j <= 1; ++j) {
397663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // Byte 2
398663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         if (i == 0) {
399663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            valid[1] = j == 0 ? 0x90 : 0xbf;    // 0xf0
400663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else if (i == 4) {
401663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            valid[1] = j == 0 ? 0x80 : 0x8f;    // 0xf4
402663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         } else {
403663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng            valid[1] = j == 0 ? 0x80 : 0xbf;    // 0xf1 .. 0xf3
404663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         }
405663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         // Byte 3 and byte 4 have same interval 0x80 .. 0xbf
406663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         valid[2] = 0x80;
407663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         valid[3] = 0x80;
408663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         run_test(buff, sizeof buff, valid, sizeof valid);
409663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         valid[2] = 0x80;
410663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         valid[3] = 0xbf;
411663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         run_test(buff, sizeof buff, valid, sizeof valid);
412663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         valid[2] = 0xbf;
413663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         valid[3] = 0x80;
414663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         run_test(buff, sizeof buff, valid, sizeof valid);
415663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         valid[2] = 0xbf;
416663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         valid[3] = 0xbf;
417663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng         run_test(buff, sizeof buff, valid, sizeof valid);
418663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      }
419663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
420663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
421663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Valid characters if m3 == 0 -----\n");
422663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // First char is 0xf5 .. 0xf7
423663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t valid_if_not_m3[] = {
424663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xf5, 0x00, 0x00, 0x00,
425663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xf6, 0x11, 0x22, 0x33,
426663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xf7, 0x44, 0x55, 0x66,
427663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
428663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, valid_if_not_m3, sizeof valid_if_not_m3);
429663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
430663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // As conversion stops upon encountering an invalid character, we
431663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // need to test each invalid character separately, to make sure it
432663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // is recognized as invalid.
433663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
434663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Invalid characters (2nd byte is invalid) -----\n");
435663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // Test for invalid four-byte characters where the 2nd byte is invalid.
436663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // All other bytes are valid
437663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t f0[4], f4[4];
438663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
439663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   f0[0] = 0xf0;  // valid
440663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   f0[1] = 0x8f;  // invalid  because outside [0x90 .. 0xbf]
441663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   f0[2] = 0x80;  // valid
442663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   f0[3] = 0x80;  // valid
443663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, f0, sizeof f0);
444663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   f0[1] = 0xc0;  // invalid  because outside [0x90 .. 0xbf]
445663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, f0, sizeof f0);
446663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
447663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   f4[0] = 0xf4;  // valid
448663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   f4[1] = 0x7f;  // invalid  because outside [0x80 .. 0x8f]
449663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   f4[2] = 0x80;  // valid
450663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   f4[3] = 0x80;  // valid
451663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, f4, sizeof f4);
452663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   f4[1] = 0x90;  // invalid  because outside [0x80 .. 0x9f]
453663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, f4, sizeof f4);
454663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
455663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i <= 0x4; ++i) {
456663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t fxxx_1[4] = { 0x0, 0x7f, 0x80, 0x80 };
457663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t fxxx_2[4] = { 0x0, 0xc0, 0x80, 0x80 };
458663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
459663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (i == 0) continue;   // special case f0
460663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      if (i == 4) continue;   // special case f4
461663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
462663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      fxxx_1[0] = 0xf0 | i;
463663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      fxxx_2[0] = 0xf0 | i;
464663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, fxxx_1, sizeof fxxx_1);
465663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, fxxx_2, sizeof fxxx_2);
466663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
467663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
468663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Invalid characters (3rd byte is invalid) -----\n");
469663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // Test for invalid four-byte characters where the 3rd byte is invalid.
470663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // All other bytes are valid
471663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i <= 0x4; ++i) {
472663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t fxxx[4] = { 0x0, 0x0, 0x0, 0x80 };
473663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
474663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      fxxx[0] = 0xf0 | i;
475663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      fxxx[1] = (i == 0) ? 0x94 : 0x84;
476663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      fxxx[2] = 0x7f;
477663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, fxxx, sizeof fxxx);
478663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      fxxx[2] = 0xc0;
479663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, fxxx, sizeof fxxx);
480663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
481663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
482663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Invalid characters (4th byte is invalid) -----\n");
483663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // Test for invalid four-byte characters where the 3rd byte is invalid.
484663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   // All other bytes are valid
485663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for (i = 0; i <= 0x4; ++i) {
486663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      uint8_t fxxx[4] = { 0x0, 0x0, 0x80, 0x0 };
487663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
488663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      fxxx[0] = 0xf0 | i;
489663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      fxxx[1] = (i == 0) ? 0x94 : 0x84;
490663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      fxxx[3] = 0x7f;
491663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, fxxx, sizeof fxxx);
492663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      fxxx[3] = 0xc0;
493663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      run_test(buff, sizeof buff, fxxx, sizeof fxxx);
494663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
495663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
496663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Invalid 2nd char AND output exhausted -----\n");
497663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* The character is invalid in its 2nd byte AND the output buffer is
498663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exhausted (4 bytes are needed) */
499663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t pat1[] = {
500663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xf0, 0x00, 0x80, 0x80
501663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
502663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 1, pat1, 4);
503663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
504663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Invalid 3rd char AND output exhausted -----\n");
505663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* The character is invalid in its 3rd byte AND the output buffer is
506663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exhausted (4 bytes are needed) */
507663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t pat2[] = {
508663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xf0, 0xaa, 0x00, 0x80
509663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
510663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 3, pat2, 4);
511663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
512663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- Invalid 4th char AND output exhausted -----\n");
513663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* The character is invalid in its 4th byte AND the output buffer is
514663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      exhausted (4 bytes are needed) */
515663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t pat3[] = {
516663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xf0, 0xaa, 0xaa, 0x00
517663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
518663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 3, pat3, 4);
519663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
520663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n----- 1st char valid, 2nd char invalid -----\n");
521663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t valid_invalid[] = {
522663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xf0, 0xaa, 0xaa, 0xaa, // valid
523663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      0xf0, 0x00, 0x00, 0x00  // invalid
524663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   };
525663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, valid_invalid, sizeof valid_invalid);
526663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
527663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
528663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
529663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengint main()
530663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
531663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   convert_1_byte();
532663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   convert_2_bytes();
533663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   convert_3_bytes();
534663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   convert_4_bytes();
535663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
536663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Length == 0, no memory should be read or written */
537663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test1 ----------------\n");
538663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 0, NULL, 0);
539663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
540663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Test exhaustion of source length (source bytes are valid) */
541663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test2.1 ----------------\n");
542663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
543663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* No character will be written to BUFF, i.e. loop in jitted code
544663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      is not iterated */
545663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, NULL,     0);
546663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern1, 0);
547663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern2, 0);
548663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern2, 1);
549663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern3, 0);
550663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern3, 1);
551663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern3, 2);
552663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern4, 0);
553663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern4, 1);
554663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern4, 2);
555663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern4, 3);
556663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
557663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test2.2 ----------------\n");
558663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* At least one character will be written to BUFF, i.e. loop in jitted
559663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      code is iterated */
560663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern1, 2);
561663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern2, 5);
562663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern3, 6);
563663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, pattern4, 9);
564663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
565663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Test exhaustion of destination length (source bytes are valid) */
566663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test3.1 ----------------\n");
567663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
568663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* No character will be written to BUFF, i.e. loop in jitted code
569663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      is not iterated */
570663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
571663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Want to write 2 or 4 bytes at a time */
572663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 0, pattern1, sizeof pattern1);  // 2-byte result
573663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 0, pattern2, sizeof pattern2);  // 2-byte result
574663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 1, pattern2, sizeof pattern2);  // 2-byte result
575663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 0, pattern3, sizeof pattern3);  // 2-byte result
576663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 1, pattern3, sizeof pattern3);  // 2-byte result
577663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 0, pattern4, sizeof pattern4);  // 4-byte result
578663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 1, pattern4, sizeof pattern4);  // 4-byte result
579663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 2, pattern4, sizeof pattern4);  // 4-byte result
580663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, 3, pattern4, sizeof pattern4);  // 4-byte result
581663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
582663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test3.2 ----------------\n");
583663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* At least one character will be written to BUFF, i.e. loop in jitted
584663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      code is iterated */
585663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 4, pattern1, sizeof pattern1);
586663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 5, pattern1, sizeof pattern2);
587663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 6, pattern1, sizeof pattern3);
588663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, 7, pattern1, sizeof pattern4);
589663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
590663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Convert buffer with mixed characters */
591663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n------------- test4 ----------------\n");
592663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(buff, sizeof buff, mixed, sizeof mixed);
593663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
594663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return 0;
595663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
596