From: Florian Krohm Date: Sat, 4 Feb 2012 17:16:40 +0000 (+0000) Subject: Add testcases for TR, TRE, TRTT, TROT, TRTO insns. X-Git-Tag: svn/VALGRIND_3_8_0~485 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6874ede3707cf520dce7f83d3dd3362a5fbbdd62;p=thirdparty%2Fvalgrind.git Add testcases for TR, TRE, TRTT, TROT, TRTO insns. Fixes #273114. Patch by Divya Vyas (divyvyas@linux.vnet.ibm.com). git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12368 --- diff --git a/NEWS b/NEWS index 19f892d740..f16b25c529 100644 --- a/NEWS +++ b/NEWS @@ -40,6 +40,7 @@ where XXXXXX is the bug number as listed below. 247386 make perf does not run all performance tests 270796 s390x: Removed broken support for the TS insn 271438 Fix configure for proper SSE4.2 detection +273114 s390x: Support TR, TRE, TROO, TROT, TRTO, and TRTT instructions 276993 fix mremap 'no thrash checks' 281482 valgrind's memcheck incorrect byte allocation count in realloc() for silly argument 282230 group allocator for small fixed size, use it for MC_Chunk/SEc vbit diff --git a/none/tests/s390x/Makefile.am b/none/tests/s390x/Makefile.am index 2ede43943b..6f5b95a2fe 100644 --- a/none/tests/s390x/Makefile.am +++ b/none/tests/s390x/Makefile.am @@ -5,7 +5,8 @@ dist_noinst_SCRIPTS = filter_stderr INSN_TESTS = clc clcle cvb cvd icm lpr tcxb lam_stam xc mvst add sub mul \ and or xor insert div srst fold_And16 flogr sub_EI add_EI \ and_EI or_EI xor_EI insert_EI mul_GE add_GE condloadstore \ - op_exception fgx stck stckf stcke stfle cksm mvcl clcl troo + op_exception fgx stck stckf stcke stfle cksm mvcl clcl troo \ + trto trot trtt tr tre check_PROGRAMS = $(INSN_TESTS) \ allexec \ @@ -21,13 +22,13 @@ EXTRA_DIST = \ ex_clone.stdout.exp ex_clone.stderr.exp ex_clone.vgtest \ op00.stderr.exp1 op00.stderr.exp2 op00.vgtest \ test.h opcodes.h add.h and.h div.h insert.h \ - mul.h or.h sub.h test.h xor.h + mul.h or.h sub.h test.h xor.h table.h AM_CFLAGS += @FLAG_M64@ AM_CXXFLAGS += @FLAG_M64@ AM_CCASFLAGS += @FLAG_M64@ -allexec_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_NONNULL@ +allexec_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_NONNULL@ ex_clone_LDFLAGS = -lpthread tcxb_CFLAGS = $(AM_CFLAGS) -std=gnu99 diff --git a/none/tests/s390x/table.h b/none/tests/s390x/table.h new file mode 100644 index 0000000000..f6d475b781 --- /dev/null +++ b/none/tests/s390x/table.h @@ -0,0 +1,75 @@ +char touppercase[256] = +{ + + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32/*50*/, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50/*80*/, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x41/*97*/, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x80, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0x8A, 0x8B, 0xAC, 0xAD, 0xAE, 0x8F, + 0x90, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0x9A, 0x9B, 0x9E, 0x9D, 0x9E, 0x9F, + 0xA0, 0xA1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, + 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, + 0xD8, 0xD9, 0xDA, 0xFB, 0xFC, 0xFD, 0xFE, 0xDF, + 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, + 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF + +}; + +char tolowercase[256] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, + 0x30, 0x31, 0x32/*50*/, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, + 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70/*80*/, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, + 0x70, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9C, 0x9F, + 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xAA, 0xAB, 0x8C, 0x8D, 0x8E, 0xAF, + 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, + 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, + 0xC0, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, + 0xD0, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, + 0xE0, 0xE1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, + 0xA8, 0xA9, 0xEA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xDB, 0xDC, 0xDD, 0xDE, 0xFF +}; + + diff --git a/none/tests/s390x/tr.c b/none/tests/s390x/tr.c new file mode 100644 index 0000000000..5bce0ceec6 --- /dev/null +++ b/none/tests/s390x/tr.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include "table.h" + +uint8_t buff[40]; + +void tr(uint8_t *codepage, uint8_t *addr, uint64_t len) +{ + asm volatile( + " larl 1,1f\n" + "1: tr 0(1,%0),0(%2)\n" + " ex %1,0(1)" + : "+&a" (addr), "+d" (len) + : "a" (codepage) : "cc", "memory", "1"); +} + +void run_test(void *tran_table, void *srcaddr, uint64_t len) +{ + int i; + + tr(tran_table, buff, len); + printf("the translated string is "); + for (i = 0; i < len; i++) { + printf("%c", buff[i]); + } + printf("\n"); +} + +int main() +{ + /* Test 1: length = 0 */ + run_test((char *)&touppercase, &buff, 0); + run_test((char *)&touppercase, &buff, 0); + + /* Test 2 : length > 0 */ + memset(buff, 'a', 1); + run_test((char *)&touppercase, &buff, 1); + + memcpy(buff, "abcdefgh", 8); + run_test((char *)&touppercase, &buff, 3); + run_test((char *)&touppercase, &buff, 3); + run_test((char *)&touppercase, &buff, 8); + + memcpy(buff, "ABCDEFGH", 8); + run_test((char *)&tolowercase, &buff, 3); + run_test((char *)&tolowercase, &buff, 3); + run_test((char *)&tolowercase, &buff, 8); + + memcpy(buff, "0123456789", 9); + run_test((char *)&touppercase, &buff, 9); + run_test((char *)&tolowercase, &buff, 9); + return 0; +} diff --git a/none/tests/s390x/tr.stderr.exp b/none/tests/s390x/tr.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/none/tests/s390x/tr.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/s390x/tr.stdout.exp b/none/tests/s390x/tr.stdout.exp new file mode 100644 index 0000000000..51d906f9c1 --- /dev/null +++ b/none/tests/s390x/tr.stdout.exp @@ -0,0 +1,11 @@ +the translated string is +the translated string is +the translated string is A +the translated string is ABC +the translated string is ABC +the translated string is ABCDEFGH +the translated string is abc +the translated string is abc +the translated string is abcdefgh +the translated string is 012345678 +the translated string is 012345678 diff --git a/none/tests/s390x/tr.vgtest b/none/tests/s390x/tr.vgtest new file mode 100644 index 0000000000..6e3f34cbab --- /dev/null +++ b/none/tests/s390x/tr.vgtest @@ -0,0 +1 @@ +prog: tr diff --git a/none/tests/s390x/tre.c b/none/tests/s390x/tre.c new file mode 100644 index 0000000000..db546dfde0 --- /dev/null +++ b/none/tests/s390x/tre.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include "table.h" + +/* Register contents after executing an TRE insn */ +typedef struct { + uint64_t addr; + uint64_t len; + uint64_t tabaddr; + uint8_t testbyte; + uint64_t cc; +} tre_regs; + +uint8_t buff[40]; + +tre_regs tre(uint8_t *codepage, uint8_t *addr, uint64_t len, uint8_t test_byte) +{ + int cc; + tre_regs regs; + + register uint64_t param asm("0") = test_byte; + register uint64_t a2 asm ("4") = (uint64_t)codepage; + register uint64_t a1 asm ("2") = (uint64_t)addr; + register uint64_t l1 asm ("3") = len; + + asm volatile( + " tre %1,%2\n" + " ipm %0\n" + " srl %0,28\n" + :"=d"(cc),"+&d"(a1) + :"d"(a2),"d"(param),"d"(l1),"d"(test_byte): "memory" ); + + regs.addr = a1; + regs.len = l1; + regs.tabaddr = a2; + regs.testbyte = param; + regs.cc = cc; + + return regs; +} + +void run_test(void *tran_table, void *srcaddr, uint64_t len, uint8_t test) +{ + tre_regs regs; + int i; + + regs = tre(tran_table, buff, len, test); + + if ((uint64_t)tran_table != regs.tabaddr) + printf("translation table address changed\n"); + if (test != regs.testbyte) + printf("test byte changed\n"); + if ((uint64_t)srcaddr + (len - regs.len) != regs.addr) + printf("source address/length not updated properly\n"); + + printf("Resulting cc is %"PRIu64" and the string is ", regs.cc); + for ( i = 0; i < len; i++) { + printf("%c", buff[i]); + } + + printf("\n"); +} + +int main() +{ + + /* Test 1: length = 0 */ + run_test(NULL, NULL, 0, 0x0); + run_test((char *)&touppercase, &buff, 0, 0x0); + run_test((char *)&touppercase, &buff, 0, 'b'); + + /* Test 2 : length > 0 */ + memset(buff, 'a', 1); + run_test((char *)&touppercase, &buff, 1, 'a'); //cc = 1 + run_test((char *)&touppercase, &buff, 1, 'b'); + + memcpy(buff, "abcdefgh", 8); + run_test((char *)&touppercase, &buff, 3, 'a'); //cc = 1 + run_test((char *)&touppercase, &buff, 3, 'f'); //cc = 0 + run_test((char *)&touppercase, &buff, 8, 'l'); //cc = 0 + + memcpy(buff, "ABCDEFGH", 8); + run_test((char *)&tolowercase, &buff, 3, 'A'); // cc = 1 + run_test((char *)&tolowercase, &buff, 3, 'C'); // cc = 0 + run_test((char *)&tolowercase, &buff, 8, 0x0); // cc = 0 + + memcpy(buff, "01234567", 8); + run_test((char *)&touppercase, &buff, 8, 'A'); + run_test((char *)&tolowercase, &buff, 8, 'A'); + return 0; +} diff --git a/none/tests/s390x/tre.stderr.exp b/none/tests/s390x/tre.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/none/tests/s390x/tre.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/s390x/tre.stdout.exp b/none/tests/s390x/tre.stdout.exp new file mode 100644 index 0000000000..f03e622a3c --- /dev/null +++ b/none/tests/s390x/tre.stdout.exp @@ -0,0 +1,14 @@ +source address/length not updated properly +Resulting cc is 0 and the string is +Resulting cc is 0 and the string is +Resulting cc is 0 and the string is +Resulting cc is 1 and the string is a +Resulting cc is 0 and the string is A +Resulting cc is 1 and the string is abc +Resulting cc is 0 and the string is ABC +Resulting cc is 0 and the string is ABCDEFGH +Resulting cc is 1 and the string is ABC +Resulting cc is 1 and the string is abC +Resulting cc is 0 and the string is abcdefgh +Resulting cc is 0 and the string is 01234567 +Resulting cc is 0 and the string is 01234567 diff --git a/none/tests/s390x/tre.vgtest b/none/tests/s390x/tre.vgtest new file mode 100644 index 0000000000..19a4755e99 --- /dev/null +++ b/none/tests/s390x/tre.vgtest @@ -0,0 +1 @@ +prog: tre diff --git a/none/tests/s390x/troo.c b/none/tests/s390x/troo.c index 925c7a7ced..374f3cd20c 100644 --- a/none/tests/s390x/troo.c +++ b/none/tests/s390x/troo.c @@ -5,12 +5,12 @@ /* Register contents after executing an TROO insn */ typedef struct { - uint64_t srcaddr; - uint64_t len; - uint64_t desaddr; - uint64_t tabaddr; - uint8_t testbyte; - uint64_t cc; + uint64_t srcaddr; + uint64_t len; + uint64_t desaddr; + uint64_t tabaddr; + uint8_t testbyte; + uint64_t cc; } troo_regs; uint8_t tran_table[20] = { diff --git a/none/tests/s390x/trot.c b/none/tests/s390x/trot.c new file mode 100644 index 0000000000..b4b44c86ae --- /dev/null +++ b/none/tests/s390x/trot.c @@ -0,0 +1,132 @@ +#include +#include +#include +#include + +/* Register contents after executing an TROT insn */ +typedef struct { + uint64_t srcaddr; + uint64_t len; + uint64_t desaddr; + uint64_t tabaddr; + uint16_t testbyte; + uint64_t cc; +} trot_regs; + +uint16_t tran_table[40] = { + 0xaaaa,0xbbbb,0xcccc,0xccdd,0xffff,0xdada,0xbcbc,0xabab,0xcaca,0xeaea, + 0xbbbb,0xeeee +}; + +uint8_t src[40] = { + 0x01,0x03,0x04,0x02,0x07,0x08,0x06,0x02,0x05,0x09 +}; + +uint16_t des[40]; + +trot_regs tr(uint8_t *addr, uint16_t *codepage, uint16_t *dest, uint64_t len, + uint16_t test) +{ + trot_regs regs; + register uint64_t test_byte asm("0") = test; + register uint64_t length asm("3") = len; + register uint64_t srcaddr asm("4") = (uint64_t)addr; + register uint64_t codepage2 asm("1") = (uint64_t)codepage; + register uint64_t desaddr asm("2") = (uint64_t)dest; + register uint64_t cc asm("5"); + + cc = 2; /* cc result will never be 2 */ + asm volatile( + " trot %1,%2\n" + " ipm %0\n" + " srl %0,28\n" + : "=d"(cc),"+&d"(desaddr) + : "d" (srcaddr),"d"(test_byte),"d" (codepage2),"d"(length) + : "memory" ); + + regs.srcaddr = srcaddr; + regs.len = length; + regs.desaddr = desaddr; + regs.tabaddr = codepage2; + regs.testbyte = test_byte; + regs.cc = cc; + return regs; +} + +int run_test(void *srcaddr, void *tableaddr, void *desaddr, uint64_t len, + uint16_t testbyte) +{ + trot_regs regs; + int i; + + assert(len <= sizeof src); + + if ((testbyte & 0xffff) != testbyte) + printf("testbyte should be 2 byte only\n"); + + regs = tr(srcaddr, tableaddr, desaddr, len, testbyte); + + if ((uint64_t)tableaddr != regs.tabaddr) + printf("translation table address changed\n"); + if ((uint64_t)srcaddr + (len - regs.len) != regs.srcaddr) + printf("source address/length not updated properly\n"); + if ((uint64_t)desaddr + 2*(len - regs.len) != regs.desaddr) + printf("destination address/length not updated properly\n"); + if (regs.cc == 0 && regs.len != 0) + printf("length is not zero but cc is zero\n"); + printf("%u bytes translated\n", (unsigned)(len - regs.len)); + printf("the translated values is"); + for (i = 0; i < len; i++) { + printf(" %hx", des[i]); + } + printf("\n"); + + return regs.cc; +} + + +int main() +{ + int cc; + + assert(sizeof des >= sizeof src); + + /* Test 1 : len == 0 */ + cc = run_test(NULL, NULL, NULL, 0, 0x0); + if (cc != 0) + printf("cc not updated properly:%d", cc); + + cc = run_test(&src, &tran_table, &des, 0, 0x0); + if (cc != 0) + printf("cc not updated properly:%d",cc); + + cc = run_test(&src, &tran_table, &des, 0, 0xcaca); + if (cc != 0) + printf("cc not updated properly:%d",cc); + + /* Test 2 : len > 0, testbyte not matching */ + cc = run_test(&src, &tran_table, &des, 3, 0xeeee); + if (cc != 0) + printf("cc not updated properly:%d",cc); + + cc = run_test(&src, &tran_table, &des, 10, 0xeeee); + if (cc != 0) + printf("cc not updated properly:%d",cc); + + memset((uint16_t *)&des, 0, 10); + + /* Test 3 : len > 0 , testbyte matching */ + cc = run_test(&src, &tran_table, &des, 5, 0xffff); + if (cc != 1) + printf("cc not updated properly:%d",cc); + + cc = run_test(&src, &tran_table, &des, 5, 0xcccc); + if (cc != 1) + printf("cc not updated properly:%d",cc); + + cc = run_test(&src, &tran_table, &des, 10, 0xeaea); + if (cc != 1) + printf("cc not updated properly:%d",cc); + + return 0; +} diff --git a/none/tests/s390x/trot.stderr.exp b/none/tests/s390x/trot.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/none/tests/s390x/trot.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/s390x/trot.stdout.exp b/none/tests/s390x/trot.stdout.exp new file mode 100644 index 0000000000..cdd1c6e534 --- /dev/null +++ b/none/tests/s390x/trot.stdout.exp @@ -0,0 +1,16 @@ +0 bytes translated +the translated values is +0 bytes translated +the translated values is +0 bytes translated +the translated values is +3 bytes translated +the translated values is bbbb ccdd ffff +10 bytes translated +the translated values is bbbb ccdd ffff cccc abab caca bcbc cccc dada eaea +2 bytes translated +the translated values is bbbb ccdd 0 0 0 +3 bytes translated +the translated values is bbbb ccdd ffff 0 0 +9 bytes translated +the translated values is bbbb ccdd ffff cccc abab caca bcbc cccc dada eaea diff --git a/none/tests/s390x/trot.vgtest b/none/tests/s390x/trot.vgtest new file mode 100644 index 0000000000..bf85e5942c --- /dev/null +++ b/none/tests/s390x/trot.vgtest @@ -0,0 +1 @@ +prog: trot diff --git a/none/tests/s390x/trto.c b/none/tests/s390x/trto.c new file mode 100644 index 0000000000..b79721d771 --- /dev/null +++ b/none/tests/s390x/trto.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include + +/* Register contents after executing an TRTO insn */ +typedef struct { + uint64_t srcaddr; + uint64_t len; + uint64_t desaddr; + uint64_t tabaddr; + uint8_t testbyte; + uint64_t cc; +} trto_regs; + +uint8_t tran_table[40] = { + 0xaa,0xbb,0xcc,0xdd,0xff,0xdd,0xbc,0xab,0xca,0xea,0xbb,0xee +}; + +int16_t src[40] = { + 0x2,0x03,0x04,0x02,0x07,0x08,0x06,0x02,0x05,0x09 +}; + +uint8_t des[20]; + +trto_regs tr(uint16_t *addr, uint16_t *codepage, uint8_t *dest, uint64_t len, + uint8_t test) +{ + trto_regs regs; + register uint64_t test_byte asm("0") = test; + register uint64_t length asm("3") = len; + register uint64_t srcaddr asm("4") = (uint64_t)addr; + register uint64_t codepage2 asm("1") = (uint64_t)codepage; + register uint64_t desaddr asm("2") = (uint64_t)dest; + register uint64_t cc asm("5"); + + cc = 2; /* cc result will never be 2 */ + asm volatile( + " trto %1,%2\n" + " ipm %0\n" + " srl %0,28\n" + : "=d"(cc),"+&d"(desaddr) + : "d" (srcaddr),"d"(test_byte),"d" (codepage2),"d"(length) + : "memory" ); + + regs.srcaddr = srcaddr; + regs.len = length; + regs.desaddr = desaddr; + regs.tabaddr = codepage2; + regs.testbyte = test_byte; + regs.cc = cc; + return regs; +} + +int run_test(void *srcaddr, void *tableaddr, void *desaddr, uint64_t len, + uint8_t testbyte) +{ + trto_regs regs; + int i; + + assert(len <= sizeof src); + + if ((testbyte & 0xffff) != testbyte) + printf("testbyte should be 1 byte only\n"); + + regs = tr(srcaddr, tableaddr, desaddr, len, testbyte); + + if ((uint64_t)tableaddr != regs.tabaddr) + printf("translation table address changed\n"); + if ((uint64_t)srcaddr + (len - regs.len) != regs.srcaddr) + printf("source address/length not updated properly\n"); + if ((uint64_t)desaddr + ((len - regs.len)/2) != regs.desaddr) + printf("destination address/length not updated properly\n"); + if (regs.cc == 0 && regs.len != 0) + printf("length is not zero but cc is zero\n"); + printf("%u bytes translated\n", ((unsigned)(len - regs.len)/2)); + printf("the translated values is"); + for (i = 0; i < len/2; i++) { + printf(" %x", des[i]); + } + printf("\n"); + + return regs.cc; +} + +int main() +{ + int cc; + + assert(sizeof des <= sizeof src); + + /* Test 1 : len == 0 */ + cc = run_test(NULL, NULL, NULL, 0, 0x0); + if (cc != 0) + printf("cc not updated properly:%d", cc); + + cc = run_test(&src, &tran_table, &des, 0, 0x0); + if (cc != 0) + printf("cc not updated properly:%d",cc); + + cc = run_test(&src, &tran_table, &des, 0, 0xca); + if (cc != 0) + printf("cc not updated properly:%d",cc); + + /* Test 2 : len > 0, testbyte not matching */ + cc = run_test(&src, &tran_table, &des, 12, 0xee); + if (cc != 0) + printf("cc not updated properly:%d",cc); + + cc = run_test(&src, &tran_table, &des, 20, 0x00); + if (cc != 0) + printf("cc not updated properly:%d",cc); + + memset((uint16_t *)&des, 0, 10); + + /* Test 3 : len > 0 , testbyte matching */ + cc = run_test(&src, &tran_table, &des, 12, 0xff); + if (cc != 1) + printf("cc not updated properly:%d",cc); + + cc = run_test(&src, &tran_table, &des, 12, 0xcc); + if (cc != 1) + printf("cc not updated properly:%d",cc); + + cc = run_test(&src, &tran_table, &des, 20, 0xea); + if (cc != 1) + printf("cc not updated properly:%d",cc); + + return 0; +} diff --git a/none/tests/s390x/trto.stderr.exp b/none/tests/s390x/trto.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/none/tests/s390x/trto.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/s390x/trto.stdout.exp b/none/tests/s390x/trto.stdout.exp new file mode 100644 index 0000000000..d3a4fc0981 --- /dev/null +++ b/none/tests/s390x/trto.stdout.exp @@ -0,0 +1,16 @@ +0 bytes translated +the translated values is +0 bytes translated +the translated values is +0 bytes translated +the translated values is +6 bytes translated +the translated values is cc dd ff cc ab ca +10 bytes translated +the translated values is cc dd ff cc ab ca bc cc dd ea +2 bytes translated +the translated values is cc dd 0 0 0 0 +0 bytes translated +the translated values is cc dd 0 0 0 0 +9 bytes translated +the translated values is cc dd ff cc ab ca bc cc dd 0 diff --git a/none/tests/s390x/trto.vgtest b/none/tests/s390x/trto.vgtest new file mode 100644 index 0000000000..d3fe588da7 --- /dev/null +++ b/none/tests/s390x/trto.vgtest @@ -0,0 +1 @@ +prog: trto diff --git a/none/tests/s390x/trtt.c b/none/tests/s390x/trtt.c new file mode 100644 index 0000000000..e9cb89902c --- /dev/null +++ b/none/tests/s390x/trtt.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include + +/* Register contents after executing an TRTT insn */ +typedef struct { + uint64_t srcaddr; + uint64_t len; + uint64_t desaddr; + uint64_t tabaddr; + uint16_t testbyte; + uint64_t cc; +} trtt_regs; + +uint16_t tran_table[40] = { + 0xaaaa,0xcccc,0xcccc,0xdddd,0xffff,0xdada,0xbcbc,0xabab,0xcaca,0xeaea, + 0xbbbb,0xeeee +}; + +uint16_t src[40] = { + 0x4,0x03,0x04,0x02,0x07,0x08,0x06,0x02,0x05,0x09,0xa +}; + +uint16_t des[20]; + +trtt_regs tr(uint16_t *addr, uint16_t *codepage, uint16_t *dest, uint64_t len, + uint16_t test) +{ + trtt_regs regs; + register uint64_t test_byte asm("0") = test; + register uint64_t length asm("3") = len; + register uint64_t srcaddr asm("4") = (uint64_t)addr; + register uint64_t codepage2 asm("1") = (uint64_t)codepage; + register uint64_t desaddr asm("2") = (uint64_t)dest; + register uint64_t cc asm("5"); + + cc = 2; /* cc result will never be 2 */ + asm volatile( + " trtt %1,%2\n" + " ipm %0\n" + " srl %0,28\n" + : "=d"(cc),"+d"(desaddr),"+d"(srcaddr) + : "d"(test_byte),"d" (codepage2),"d"(length) + : "memory" ); + + regs.srcaddr = srcaddr; + regs.len = length; + regs.desaddr = desaddr; + regs.tabaddr = codepage2; + regs.testbyte = test_byte; + regs.cc = cc; + + return regs; +} + +int run_test(void *srcaddr, void *tableaddr, void *desaddr, uint64_t len, + uint16_t testbyte) +{ + trtt_regs regs; + int i; + + assert(len <= sizeof src); + + if ((testbyte & 0xffff) != testbyte) + printf("testbyte should be 2 byte only\n"); + + regs = tr(srcaddr, tableaddr, desaddr, len, testbyte); + + if ((uint64_t)tableaddr != regs.tabaddr) + printf("translation table address changed\n"); + if ((uint64_t)srcaddr + (len - regs.len) != regs.srcaddr) + printf("source address/length not updated properly\n"); + if ((uint64_t)desaddr + (len - regs.len) != regs.desaddr) + printf("destination address/length not updated properly\n"); + if (regs.cc == 0 && regs.len != 0) + printf("length is not zero but cc is zero\n"); + printf("%u bytes translated\n", ((unsigned)(len - regs.len))/2); + printf("the translated values is"); + for (i = 0; i < len/2; i++) { + printf(" %hx", des[i]); + } + printf("\n"); + + return regs.cc; +} + + +int main() +{ + int cc; + + assert(sizeof des <= sizeof src); + + /* Test 1 : len == 0 */ + cc = run_test(NULL, NULL, NULL, 0, 0x0); + if (cc != 0) + printf("cc not updated properly:%d", cc); + + cc = run_test(&src, &tran_table, &des, 0, 0x0); + if (cc != 0) + printf("cc not updated properly:%d",cc); + + cc = run_test(&src, &tran_table, &des, 0, 0xcaca); + if (cc != 0) + printf("cc not updated properly:%d",cc); + + /* Test 2 : len > 0, testbyte not matching */ + cc = run_test(&src, &tran_table, &des, 4, 0xdada); + if (cc != 0) + printf("cc not updated properly:%d",cc); + + cc = run_test(&src, &tran_table, &des, 10, 0x00); + if (cc != 0) + printf("cc not updated properly:%d",cc); + + memset((uint16_t *)&des, 0, 10); + + /* Test 3 : len > 0 , testbyte matching */ + cc = run_test(&src, &tran_table, &des, 10, 0xffff); + if (cc != 1) + printf("cc not updated properly:%d",cc); + + cc = run_test(&src, &tran_table, &des, 10, 0xcccc); + if (cc != 1) + printf("cc not updated properly:%d",cc); + + cc = run_test(&src, &tran_table, &des, 20, 0xeaea); + if (cc != 1) + printf("cc not updated properly:%d",cc); + + return 0; +} diff --git a/none/tests/s390x/trtt.stderr.exp b/none/tests/s390x/trtt.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/none/tests/s390x/trtt.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/s390x/trtt.stdout.exp b/none/tests/s390x/trtt.stdout.exp new file mode 100644 index 0000000000..068c3f9e9c --- /dev/null +++ b/none/tests/s390x/trtt.stdout.exp @@ -0,0 +1,16 @@ +0 bytes translated +the translated values is +0 bytes translated +the translated values is +0 bytes translated +the translated values is +2 bytes translated +the translated values is ffff dddd +5 bytes translated +the translated values is ffff dddd ffff cccc abab +0 bytes translated +the translated values is 0 0 0 0 0 +3 bytes translated +the translated values is ffff dddd ffff 0 0 +9 bytes translated +the translated values is ffff dddd ffff cccc abab caca bcbc cccc dada 0 diff --git a/none/tests/s390x/trtt.vgtest b/none/tests/s390x/trtt.vgtest new file mode 100644 index 0000000000..5255d787cb --- /dev/null +++ b/none/tests/s390x/trtt.vgtest @@ -0,0 +1 @@ +prog: trtt