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