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 */ 13typedef 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 */ 24uint16_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 */ 31uint16_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 */ 38uint16_t invalid[] = { 0xd801, 0x0098 }; 39 40/* Mixed bytes */ 41uint16_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. */ 51uint32_t buff[1000]; /* Large so we con'don't have to worry about it */ 52 53 54static cu24_t 55do_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 85void 86run_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 120int 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