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