1663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include<stdio.h>
2663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include<stdlib.h>
3663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include<stdint.h>
4663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include<inttypes.h>
5663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include<string.h>
6663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng#include "table.h"
7663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
8663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng/* Register contents after executing an TRE insn */
9663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengtypedef struct {
10663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint64_t addr;
11663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint64_t len;
12663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint64_t tabaddr;
13663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint8_t testbyte;
14663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   uint64_t cc;
15663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng} tre_regs;
16663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
17663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chenguint8_t buff[40];
18663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
19663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengtre_regs tre(uint8_t *codepage, uint8_t *addr, uint64_t len, uint8_t test_byte)
20663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
21663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int cc;
22663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tre_regs regs;
23663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
24663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   register uint64_t param asm("0") = test_byte;
25663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   register uint64_t a2 asm ("4") = (uint64_t)codepage;
26663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   register uint64_t a1 asm ("2") = (uint64_t)addr;
27663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   register uint64_t l1 asm ("3") = len;
28663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
29663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   asm volatile(
30663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                " tre  %1,%2\n"
31663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                " ipm  %0\n"
32663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                " srl  %0,28\n"
33663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng		:"=d"(cc),"+&d"(a1)
34663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng                :"d"(a2),"d"(param),"d"(l1),"d"(test_byte):  "memory" );
35663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
36663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.addr = a1;
37663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.len = l1;
38663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.tabaddr = a2;
39663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.testbyte = param;
40663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs.cc = cc;
41663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
42663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return regs;
43663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
44663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
45663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengvoid run_test(void *tran_table, void *srcaddr, uint64_t len, uint8_t test)
46663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
47663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   tre_regs regs;
48663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   int i;
49663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
50663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   regs = tre(tran_table, srcaddr, len, test);
51663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
52663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ((uint64_t)tran_table != regs.tabaddr)
53663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf("translation table address changed\n");
54663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if (test != regs.testbyte)
55663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf("test byte changed\n");
56663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   if ((uint64_t)srcaddr + (len - regs.len) != regs.addr)
57663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf("source address/length not updated properly\n");
58663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
59663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("Resulting cc is %"PRIu64" and the string is ", regs.cc);
60663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   for ( i = 0; i < len; i++) {
61663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng      printf("%c", buff[i]);
62663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   }
63663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
64663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   printf("\n");
65663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
66663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
67663860b1408516d02ebfcb3a9999a134e6cfb223Ben Chengint main()
68663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng{
69663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
70663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Test 1: length = 0 */
71663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test(NULL, NULL, 0, 0x0);
72663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test((char *)&touppercase, &buff, 0, 0x0);
73663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test((char *)&touppercase, &buff, 0, 'b');
74663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
75663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   /* Test 2 : length > 0 */
76663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   memset(buff, 'a', 1);
77663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test((char *)&touppercase, &buff, 1, 'a');   //cc = 1
78663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test((char *)&touppercase, &buff, 1, 'b');
79663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
80663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   memcpy(buff, "abcdefgh", 8);
81663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test((char *)&touppercase, &buff, 3, 'a');   //cc = 1
82663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test((char *)&touppercase, &buff, 3, 'f');   //cc = 0
83663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test((char *)&touppercase, &buff, 8, 'l');   //cc = 0
84663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
85663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   memcpy(buff, "ABCDEFGH", 8);
86663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test((char *)&tolowercase, &buff, 3, 'A');   // cc = 1
87663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test((char *)&tolowercase, &buff, 3, 'C');   // cc = 0
88663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test((char *)&tolowercase, &buff, 8, 0x0);   // cc = 0
89663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng
90663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   memcpy(buff, "01234567", 8);
91663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test((char *)&touppercase, &buff, 8, 'A');
92663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   run_test((char *)&tolowercase, &buff, 8, 'A');
93663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng   return 0;
94663860b1408516d02ebfcb3a9999a134e6cfb223Ben Cheng}
95