1#include <stdio.h>
2#include <stdint.h>
3#include <string.h>
4#include <assert.h>
5
6/* Register contents after executing an TROO insn */
7typedef struct {
8   uint64_t srcaddr;
9   uint64_t len;
10   uint64_t desaddr;
11   uint64_t tabaddr;
12   uint8_t testbyte;
13   uint64_t cc;
14} troo_regs;
15
16uint8_t tran_table[20] = {
17   0xaa,0xbb,0xcc,0xdd,0xff,0xda,0xbc,0xab,0xca,0xea,0xcc,0xee
18};
19
20uint8_t src[20] = {
21   0x04,0x01,0x03,0x07,0x08,0x06,0x02,0x05,0x09
22};
23
24uint8_t des[20];
25
26troo_regs tr(uint8_t *addr, uint8_t *codepage, uint8_t *dest, uint64_t len,
27             uint8_t test)
28{
29   troo_regs regs;
30   register uint64_t test_byte asm("0") = test;
31   register uint64_t length asm("3") = len;
32   register uint64_t srcaddr asm("4") = (uint64_t)addr;
33   register uint64_t codepage2 asm("1") = (uint64_t)codepage;
34   register uint64_t desaddr asm("2") = (uint64_t)dest;
35   register uint64_t cc asm("5");
36
37   cc = 2;  /* cc result will never be 2 */
38   asm volatile(
39                " troo %1,%2\n"
40                " ipm   %0\n"
41                " srl   %0,28\n"
42                : "=d"(cc),"+&d"(desaddr)
43                : "d" (srcaddr),"d"(test_byte),"d" (codepage2),"d"(length)
44                : "memory" );
45
46   regs.srcaddr = srcaddr;
47   regs.len = length;
48   regs.desaddr = desaddr;
49   regs.tabaddr = codepage2;
50   regs.testbyte = test_byte;
51   regs.cc = cc;
52   return regs;
53}
54
55int run_test(void *srcaddr, void *tableaddr, void *desaddr, uint64_t len,
56             uint8_t testbyte)
57{
58   troo_regs regs;
59   int i;
60
61   assert(len <= sizeof src);
62
63   if ((testbyte & 0xff) != testbyte)
64      printf("testbyte should be 1 byte only\n");
65
66   regs = tr(srcaddr, tableaddr, desaddr, len, testbyte);
67
68   if ((uint64_t)tableaddr != regs.tabaddr)
69      printf("translation table address changed\n");
70   if ((uint64_t)srcaddr + (len - regs.len) != regs.srcaddr)
71      printf("source address/length not updated properly\n");
72   if ((uint64_t)desaddr + (len - regs.len) != regs.desaddr)
73      printf("destination address/length not updated properly\n");
74   if (regs.cc == 0  && regs.len != 0)
75      printf("length is not zero but cc is zero\n");
76   printf("%u bytes translated\n", (unsigned)(len - regs.len));
77   printf("the translated values are");
78   for (i = 0; i < len - regs.len; i++) {
79      printf(" %x", des[i]);
80   }
81   printf("\n");
82
83   return regs.cc;
84}
85
86int main()
87{
88   int cc;
89
90   assert(sizeof des >= sizeof src);
91
92   /* Test 1 : len == 0 */
93   cc = run_test(NULL, NULL, NULL, 0, 0x0);
94   if (cc != 0)
95      printf("cc not updated properly:%d", cc);
96
97   cc = run_test(&src, &tran_table, &des, 0, 0xca);
98   if (cc != 0)
99      printf("cc not updated properly:%d",cc);
100
101   /* Test 2 : len > 0, testbyte not matching */
102   cc = run_test(&src, &tran_table, &des, 5, 0xee);
103   if (cc != 0)
104      printf("cc not updated properly:%d",cc);
105
106   cc = run_test(&src, &tran_table, &des, 10, 0x00);
107   if (cc != 0)
108      printf("cc not updated properly:%d",cc);
109
110   memset((char *)&des, 0, 10);
111
112   /* Test 3 : len > 0, testbyte matching */
113   cc = run_test(&src, &tran_table, &des, 5, 0xff);  /* 1st byte matches */
114   if (cc != 1)
115      printf("cc not updated properly:%d",cc);
116
117   cc = run_test(&src, &tran_table, &des, 5, 0xbb);  /* 2nd byte matches */
118   if (cc != 1)
119      printf("cc not updated properly:%d",cc);
120
121   cc = run_test(&src, &tran_table, &des, 10, 0xea);
122   if (cc != 1)
123      printf("cc not updated properly:%d",cc);
124
125   return 0;
126}
127