142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian#include <stdint.h> 242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian#include <inttypes.h> 342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian#include <stdlib.h> 442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian#include <string.h> 542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian#include <stdio.h> 642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian#include "opcodes.h" 742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian#ifndef M3 942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian#define M3 0 1042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian#endif 1142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 1242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian/* The abstracted result of an CU24 insn */ 1342d6ce6817bb4cfc9c0284f136592f6c55568bf7floriantypedef struct { 1442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian uint64_t addr1; // target 1542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian uint64_t len1; 1642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian uint64_t addr2; // source 1742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian uint64_t len2; 1842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian uint32_t cc; 1942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian} cu24_t; 2042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 2142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian/* Define various input buffers. */ 2242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 2342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian/* Single UTF-16 value */ 2442d6ce6817bb4cfc9c0284f136592f6c55568bf7florianuint16_t pattern1[] = { 2542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 0x0000, 0xd7ff, /* [0000 ... d7ff] corner cases */ 2642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 0xdc00, 0xffff, /* [dc00 ... ffff] corner cases */ 2742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 0x0047, 0x0156, 0x1245, 0xa021, 0xfffe /* misc */ 2842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian}; 2942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 3042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian/* UTF-16 surrogate pair */ 3142d6ce6817bb4cfc9c0284f136592f6c55568bf7florianuint16_t pattern2[] = { 3242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 0xd800, 0xdc00, /* left corner case */ 3342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 0xdbff, 0xdfff, /* right corner case */ 3442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 0xdada, 0xdddd, 0xdeaf, 0xdcdc /* misc */ 3542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian}; 3642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 3742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian/* Invalid low surrogate */ 3842d6ce6817bb4cfc9c0284f136592f6c55568bf7florianuint16_t invalid[] = { 0xd801, 0x0098 }; 3942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 4042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian/* Mixed bytes */ 4142d6ce6817bb4cfc9c0284f136592f6c55568bf7florianuint16_t mixed[] = { 4242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 0x0078, 4342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 0x0200, 4442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 0xffff, 4542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 0xd800, 0xdc01, 4642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 0xde00, 0xdd00, 4742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 0xc0c0 4842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian}; 4942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 5042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian/* This is the buffer for the converted bytes. */ 5142d6ce6817bb4cfc9c0284f136592f6c55568bf7florianuint32_t buff[1000]; /* Large so we con'don't have to worry about it */ 5242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 5342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 5442d6ce6817bb4cfc9c0284f136592f6c55568bf7florianstatic cu24_t 5542d6ce6817bb4cfc9c0284f136592f6c55568bf7floriando_cu24(uint32_t *dst, uint64_t dst_len, uint16_t *src, uint64_t src_len) 5642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian{ 5742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian int cc = 42; 5842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian cu24_t regs; 5942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 6042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* build up the register pairs */ 6142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian register uint16_t *source asm("4") = src; 6242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian register uint64_t source_len asm("5") = src_len; 6342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian register uint32_t *dest asm("2") = dst; 6442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian register uint64_t dest_len asm("3") = dst_len; 6542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 6642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian asm volatile( 6742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian CU24(M3,2,4) 6842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian "ipm %2\n\t" 6942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian "srl %2,28\n\t" 7042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian : "+d"(dest), "+d"(source), "=d"(cc), 7142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian "+d"(source_len), "+d"(dest_len) 7242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian : 7342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian : "memory", "cc"); 7442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 7542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* Capture register contents at end of cu24 */ 7642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian regs.addr1 = (uint64_t)dest; 7742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian regs.len1 = dest_len; 7842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian regs.addr2 = (uint64_t)source; 7942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian regs.len2 = source_len; 8042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian regs.cc = cc; 8142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 8242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian return regs; 8342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian} 8442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 8542d6ce6817bb4cfc9c0284f136592f6c55568bf7florianvoid 8642d6ce6817bb4cfc9c0284f136592f6c55568bf7florianrun_test(uint32_t *dst, uint64_t dst_len, uint16_t *src, uint64_t src_len) 8742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian{ 8842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian int i; 8942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian cu24_t result; 9042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 9142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian result = do_cu24(dst, dst_len, src, src_len); 9242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 9342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian // Write out the converted byte, if any 9442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf("UTF32: "); 9542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian if (dst_len - result.len1 == 0) 9642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf(" <none>"); 9742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian else { 9842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian uint64_t num_bytes = dst_len - result.len1; 9942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 10042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* The number of bytes that were written must be divisible by 4 */ 10142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian if (num_bytes % 4 != 0) 10242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian fprintf(stderr, "*** number of bytes is not a multiple of 4\n"); 10342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 10442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian for (i = 0; i < num_bytes / 4; i++) { 10542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf(" %02x", dst[i]); 10642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian } 10742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian } 10842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf("\n"); 10942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 11042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf(" cc = %d\n", result.cc); 11142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian if (dst != NULL) 11242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf(" dst address difference: %"PRId64, result.addr1 - (uint64_t)dst); 11342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf(" dst len: %"PRId64"\n", result.len1); 11442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 11542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian if (src != NULL) 11642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf(" src address difference: %"PRId64, result.addr2 - (uint64_t)src); 11742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf(" src len: %"PRId64"\n", result.len2); 11842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian} 11942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 12042d6ce6817bb4cfc9c0284f136592f6c55568bf7florianint main() 12142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian{ 12242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* Length == 0, no memory should be read or written */ 12342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf("\n------------- test1 ----------------\n"); 12442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(NULL, 0, NULL, 0); 12542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 12642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* Test exhaustion of source length (source bytes are valid) */ 12742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf("\n------------- test2.1 ----------------\n"); 12842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 12942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* No character will be written to BUFF, i.e. loop in jitted code 13042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian is not iterated */ 13142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, sizeof buff, NULL, 1); 13242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, sizeof buff, pattern1, 1); 13342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, sizeof buff, pattern2, 1); 13442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, sizeof buff, pattern2, 2); 13542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, sizeof buff, pattern2, 3); 13642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 13742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf("\n------------- test2.2 ----------------\n"); 13842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* At least one character will be written to BUFF, i.e. loop in jitted 13942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian code is iterated */ 14042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, sizeof buff, pattern1, 3); 14142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, sizeof buff, pattern1, 5); 14242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, sizeof buff, pattern2, 2); 14342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, sizeof buff, pattern2, 5); 14442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, sizeof buff, pattern2, 7); 14542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 14642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* Test exhaustion of destination length (source bytes are valid) */ 14742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf("\n------------- test3.1 ----------------\n"); 14842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 14942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* No character will be written to BUFF, i.e. loop in jitted code 15042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian is not iterated */ 15142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 15242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* Want to write 4 bytes at a time */ 15342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(NULL, 0, pattern1, sizeof pattern1); 15442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(NULL, 1, pattern1, sizeof pattern1); 15542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(NULL, 2, pattern1, sizeof pattern1); 15642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(NULL, 3, pattern1, sizeof pattern1); 15742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 15842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf("\n------------- test3.2 ----------------\n"); 15942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* At least one character will be written to BUFF, i.e. loop in jitted 16042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian code is iterated */ 16142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, 4, pattern1, sizeof pattern1); 16242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, 5, pattern1, sizeof pattern1); 16342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, 6, pattern1, sizeof pattern1); 16442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, 7, pattern1, sizeof pattern1); 16542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 16642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* When both operands are exhausted, cc=0 takes precedence. 16742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian (test1 tests this for len == 0) */ 16842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf("\n------------- test4 ----------------\n"); 16942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, 4, pattern1, 2); // no iteration 17042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, 8, pattern1, 4); // iteration 17142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 17242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* Input has invalid low surrogate. */ 17342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf("\n------------- test5 ----------------\n"); 17442d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, sizeof buff, invalid, sizeof invalid); 17542d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, 0, invalid, sizeof invalid); 17642d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 17742d6ce6817bb4cfc9c0284f136592f6c55568bf7florian /* Convert all pattern buffers */ 17842d6ce6817bb4cfc9c0284f136592f6c55568bf7florian printf("\n------------- test6 ----------------\n"); 17942d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, sizeof buff, pattern1, sizeof pattern1); 18042d6ce6817bb4cfc9c0284f136592f6c55568bf7florian run_test(buff, sizeof buff, pattern2, sizeof pattern2); 18142d6ce6817bb4cfc9c0284f136592f6c55568bf7florian 18242d6ce6817bb4cfc9c0284f136592f6c55568bf7florian return 0; 18342d6ce6817bb4cfc9c0284f136592f6c55568bf7florian} 184