diff --git a/backend.h b/backend.h index 55c78c9..6f090cf 100644 --- a/backend.h +++ b/backend.h @@ -5,7 +5,7 @@ void *init_testcase(unsigned long max_insns); void *init_memory(void); long execute_testcase(void *insn, void *gprs, void *mem); void putchar_unbuffered(const char c); -char getchar_unbuffered(void); +int getchar_unbuffered(void); #define MEMPAGE_BASE (64*1024) #define MEMPAGE_SIZE (64*1024) @@ -13,6 +13,20 @@ char getchar_unbuffered(void); #define INSNS_BASE (64*1024) #define MEM_BASE (112*1024) -#define MEM_SIZE 64 +#define MEM_SIZE 1024 -#define NGPRS 36 +#ifndef VECTOR_INSNS +#define VECTOR_INSNS false +#endif + +#ifdef __powerpc64__ +#define SIXTYFOUR_INSNS true +#else +#define SIXTYFOUR_INSNS false +#endif + +#if VECTOR_INSNS +#define NGPRS (36+128) +#else +#define NGPRS (36) +#endif diff --git a/generate.c b/generate.c index 0eb776e..513a911 100644 --- a/generate.c +++ b/generate.c @@ -7,6 +7,7 @@ #include "jenkins.h" #include "helpers.h" #include "mystdio.h" +#include "backend.h" #ifdef DEBUG #include @@ -19,6 +20,8 @@ #define LDST_UPDATE true #define CRLOGICAL_INSNS true #define MTFXER_INSNS true +#define VSX_INSNS (VECTOR_INSNS && SIXTYFOUR_INSNS) +#define STCOND_INSNS false struct insn { uint32_t opcode; @@ -107,84 +110,84 @@ static struct insn insns[] = { { 0x7c000775, 0x03fff800, true, "extsb_rc"}, { 0x7c000734, 0x03fff800, true, "extsh"}, { 0x7c000735, 0x03fff800, true, "extsh_rc"}, - { 0x7c0007b4, 0x03fff800, true, "extsw"}, - { 0x7c0007b5, 0x03fff800, true, "extsw_rc"}, - { 0x7c0006f4, 0x03fff802, false, "extswsli"}, - { 0x7c0006f5, 0x03fff802, false, "extswsli_rc"}, + { 0x7c0007b4, 0x03fff800, SIXTYFOUR_INSNS, "extsw"}, + { 0x7c0007b5, 0x03fff800, SIXTYFOUR_INSNS, "extsw_rc"}, + { 0x7c0006f4, 0x03fff802, SIXTYFOUR_INSNS, "extswsli"}, + { 0x7c0006f5, 0x03fff802, SIXTYFOUR_INSNS, "extswsli_rc"}, /* Count leading/trailing zeroes */ { 0x7c000034, 0x03fff800, true, "cntlzw"}, { 0x7c000035, 0x03fff800, true, "cntlzw_rc"}, { 0x7c000434, 0x03fff800, true, "cnttzw"}, { 0x7c000435, 0x03fff800, true, "cnttzw_rc"}, - { 0x7c000074, 0x03fff800, true, "cntlzd"}, - { 0x7c000075, 0x03fff800, true, "cntlzd_rc"}, - { 0x7c000474, 0x03fff800, true, "cnttzd"}, - { 0x7c000475, 0x03fff800, true, "cnttzd_rc"}, + { 0x7c000074, 0x03fff800, SIXTYFOUR_INSNS, "cntlzd"}, + { 0x7c000075, 0x03fff800, SIXTYFOUR_INSNS, "cntlzd_rc"}, + { 0x7c000474, 0x03fff800, SIXTYFOUR_INSNS, "cnttzd"}, + { 0x7c000475, 0x03fff800, SIXTYFOUR_INSNS, "cnttzd_rc"}, /* Rotate and shift ops */ - { 0x78000010, 0x03ffffe0, true, "rldcl"}, - { 0x78000011, 0x03ffffe0, true, "rldcl_rc"}, - { 0x78000012, 0x03ffffe0, true, "rldcr"}, - { 0x78000013, 0x03ffffe0, true, "rldcr_rc"}, - { 0x78000000, 0x03ffffe2, true, "rldicl"}, - { 0x78000001, 0x03ffffe2, true, "rldicl_rc"}, - { 0x78000004, 0x03ffffe2, true, "rldicr"}, - { 0x78000005, 0x03ffffe2, true, "rldicr_rc"}, - { 0x78000008, 0x03ffffe2, true, "rldic"}, - { 0x78000009, 0x03ffffe2, true, "rldic_rc"}, + { 0x78000010, 0x03ffffe0, SIXTYFOUR_INSNS, "rldcl"}, + { 0x78000011, 0x03ffffe0, SIXTYFOUR_INSNS, "rldcl_rc"}, + { 0x78000012, 0x03ffffe0, SIXTYFOUR_INSNS, "rldcr"}, + { 0x78000013, 0x03ffffe0, SIXTYFOUR_INSNS, "rldcr_rc"}, + { 0x78000000, 0x03ffffe2, SIXTYFOUR_INSNS, "rldicl"}, + { 0x78000001, 0x03ffffe2, SIXTYFOUR_INSNS, "rldicl_rc"}, + { 0x78000004, 0x03ffffe2, SIXTYFOUR_INSNS, "rldicr"}, + { 0x78000005, 0x03ffffe2, SIXTYFOUR_INSNS, "rldicr_rc"}, + { 0x78000008, 0x03ffffe2, SIXTYFOUR_INSNS, "rldic"}, + { 0x78000009, 0x03ffffe2, SIXTYFOUR_INSNS, "rldic_rc"}, { 0x5c000000, 0x03fffffe, true, "rlwnm"}, { 0x5c000001, 0x03fffffe, true, "rlwnm_rc"}, { 0x54000000, 0x03fffffe, true, "rlwinm"}, { 0x54000001, 0x03fffffe, true, "rlwinm_rc"}, - { 0x7800000c, 0x03ffffe2, true, "rldimi"}, - { 0x7800000d, 0x03ffffe2, true, "rldimi_rc"}, + { 0x7800000c, 0x03ffffe2, SIXTYFOUR_INSNS, "rldimi"}, + { 0x7800000d, 0x03ffffe2, SIXTYFOUR_INSNS, "rldimi_rc"}, { 0x50000000, 0x03fffffe, true, "rlwimi"}, { 0x50000001, 0x03fffffe, true, "rlwimi_rc"}, { 0x7c000030, 0x03fff800, true, "slw"}, { 0x7c000031, 0x03fff800, true, "slw_rc"}, - { 0x7c000036, 0x03fff800, true, "sld"}, - { 0x7c000037, 0x03fff800, true, "sld_rc"}, - { 0x7c000634, 0x03fff800, CARRY_INSNS, "srad"}, - { 0x7c000635, 0x03fff800, CARRY_INSNS, "srad_rc"}, - { 0x7c000674, 0x03fff802, CARRY_INSNS, "sradi"}, - { 0x7c000675, 0x03fff802, CARRY_INSNS, "sradi_rc"}, + { 0x7c000036, 0x03fff800, SIXTYFOUR_INSNS, "sld"}, + { 0x7c000037, 0x03fff800, SIXTYFOUR_INSNS, "sld_rc"}, + { 0x7c000634, 0x03fff800, CARRY_INSNS && SIXTYFOUR_INSNS, "srad"}, + { 0x7c000635, 0x03fff800, CARRY_INSNS && SIXTYFOUR_INSNS, "srad_rc"}, + { 0x7c000674, 0x03fff802, CARRY_INSNS && SIXTYFOUR_INSNS, "sradi"}, + { 0x7c000675, 0x03fff802, CARRY_INSNS && SIXTYFOUR_INSNS, "sradi_rc"}, { 0x7c000630, 0x03fff800, CARRY_INSNS, "sraw"}, { 0x7c000631, 0x03fff800, CARRY_INSNS, "sraw_rc"}, { 0x7c000670, 0x03fff800, CARRY_INSNS, "srawi"}, { 0x7c000671, 0x03fff800, CARRY_INSNS, "srawi_rc"}, - { 0x7c000436, 0x03fff800, true, "srd"}, - { 0x7c000437, 0x03fff800, true, "srd_rc"}, + { 0x7c000436, 0x03fff800, SIXTYFOUR_INSNS, "srd"}, + { 0x7c000437, 0x03fff800, SIXTYFOUR_INSNS, "srd_rc"}, { 0x7c000430, 0x03fff800, true, "srw"}, { 0x7c000431, 0x03fff800, true, "srw_rc"}, /* Population count ops */ { 0x7c0000f4, 0x03fff801, true, "popcntb"}, - { 0x7c0003f4, 0x03fff801, true, "popcntd"}, + { 0x7c0003f4, 0x03fff801, SIXTYFOUR_INSNS, "popcntd"}, { 0x7c0002f4, 0x03fff801, true, "popcntw"}, /* Multiply ops */ /* NB this generates reserved forms with OE=1 for mulh* */ - { 0x7c000092, 0x03fffc00, true, "mulhd"}, - { 0x7c000093, 0x03fffc00, true, "mulhd_rc"}, - { 0x7c000012, 0x03fffc00, true, "mulhdu"}, - { 0x7c000013, 0x03fffc00, true, "mulhdu_rc"}, + { 0x7c000092, 0x03fffc00, SIXTYFOUR_INSNS, "mulhd"}, + { 0x7c000093, 0x03fffc00, SIXTYFOUR_INSNS, "mulhd_rc"}, + { 0x7c000012, 0x03fffc00, SIXTYFOUR_INSNS, "mulhdu"}, + { 0x7c000013, 0x03fffc00, SIXTYFOUR_INSNS, "mulhdu_rc"}, { 0x7c000096, 0x03fffc00, true, "mulhw"}, { 0x7c000097, 0x03fffc00, true, "mulhw_rc"}, { 0x7c000016, 0x03fffc00, true, "mulhwu"}, { 0x7c000017, 0x03fffc00, true, "mulhwu_rc"}, { 0x1c000000, 0x03ffffff, true, "mulli"}, - { 0x7c0001d2, 0x03fff800, true, "mulld"}, - { 0x7c0001d3, 0x03fff800, true, "mulld_rc"}, + { 0x7c0001d2, 0x03fff800, SIXTYFOUR_INSNS, "mulld"}, + { 0x7c0001d3, 0x03fff800, SIXTYFOUR_INSNS, "mulld_rc"}, { 0x7c0001d6, 0x03fff800, true, "mullw"}, { 0x7c0001d7, 0x03fff800, true, "mullw_rc"}, - { 0x7c0005d2, 0x03fff800, OVERFLOW_INSNS, "mulldo"}, - { 0x7c0005d3, 0x03fff800, OVERFLOW_INSNS, "mulldo_rc"}, + { 0x7c0005d2, 0x03fff800, SIXTYFOUR_INSNS && OVERFLOW_INSNS, "mulldo"}, + { 0x7c0005d3, 0x03fff800, SIXTYFOUR_INSNS && OVERFLOW_INSNS, "mulldo_rc"}, { 0x7c0005d6, 0x03fff800, OVERFLOW_INSNS, "mullwo"}, { 0x7c0005d7, 0x03fff800, OVERFLOW_INSNS, "mullwo_rc"}, - { 0x10000030, 0x03ffffc0, false, "maddhd"}, - { 0x10000031, 0x03ffffc0, false, "maddhdu"}, - { 0x10000033, 0x03ffffc0, false, "maddld"}, + { 0x10000030, 0x03ffffc0, SIXTYFOUR_INSNS, "maddhd"}, + { 0x10000031, 0x03ffffc0, SIXTYFOUR_INSNS, "maddhdu"}, + { 0x10000033, 0x03ffffc0, SIXTYFOUR_INSNS, "maddld"}, /* SPR read/write ops */ { 0x7c0903a6, 0x03e00001, true, "mtspr_ctr"}, @@ -199,8 +202,8 @@ static struct insn insns[] = { { 0x2c000000, 0x03ffffff, true, "cmpi"}, { 0x7c000040, 0x03fff801, true, "cmpl"}, { 0x28000000, 0x03ffffff, true, "cmpli"}, - { 0x7c000180, 0x03fff801, false, "cmprb"}, - { 0x7c0001c0, 0x03fff801, false, "cmpeqb"}, + { 0x7c000180, 0x03fff801, true, "cmprb"}, + { 0x7c0001c0, 0x03fff801, true, "cmpeqb"}, /* CR ops */ { 0x4c000000, 0x03fff801, true, "mcrf"}, @@ -214,7 +217,8 @@ static struct insn insns[] = { { 0x7c04001e, 0x03fbffc1, true, "isel"}, { 0x7c02001e, 0x03fdffc1, true, "isel"}, { 0x7c01001e, 0x03feffc1, true, "isel"}, - { 0x7c000100, 0x03fff801, false, "setb"}, + { 0x7c000100, 0x03fff801, true, "setb"}, + { 0x7c000480, 0x03fff801, true, "mcrxrx"}, /* BC+8 */ { 0x40000008, 0x03ff0001, true, "bc"}, @@ -230,14 +234,14 @@ static struct insn insns[] = { { 0x4c000182, 0x03fff801, CRLOGICAL_INSNS, "crxor"}, /* Divide and mod */ - { 0x7c0003d2, 0x03fff800, DIVIDE_INSNS, "divd"}, - { 0x7c000352, 0x03fff800, DIVIDE_INSNS, "divde"}, - { 0x7c000353, 0x03fff800, DIVIDE_INSNS, "divde_rc"}, - { 0x7c000312, 0x03fff800, DIVIDE_INSNS, "divdeu"}, - { 0x7c000313, 0x03fff800, DIVIDE_INSNS, "divdeu_rc"}, - { 0x7c0003d3, 0x03fff800, DIVIDE_INSNS, "divd_rc"}, - { 0x7c000392, 0x03fff800, DIVIDE_INSNS, "divdu"}, - { 0x7c000393, 0x03fff800, DIVIDE_INSNS, "divdu_rc"}, + { 0x7c0003d2, 0x03fff800, SIXTYFOUR_INSNS && DIVIDE_INSNS, "divd"}, + { 0x7c000352, 0x03fff800, SIXTYFOUR_INSNS && DIVIDE_INSNS, "divde"}, + { 0x7c000353, 0x03fff800, SIXTYFOUR_INSNS && DIVIDE_INSNS, "divde_rc"}, + { 0x7c000312, 0x03fff800, SIXTYFOUR_INSNS && DIVIDE_INSNS, "divdeu"}, + { 0x7c000313, 0x03fff800, SIXTYFOUR_INSNS && DIVIDE_INSNS, "divdeu_rc"}, + { 0x7c0003d3, 0x03fff800, SIXTYFOUR_INSNS && DIVIDE_INSNS, "divd_rc"}, + { 0x7c000392, 0x03fff800, SIXTYFOUR_INSNS && DIVIDE_INSNS, "divdu"}, + { 0x7c000393, 0x03fff800, SIXTYFOUR_INSNS && DIVIDE_INSNS, "divdu_rc"}, { 0x7c0003d6, 0x03fff800, DIVIDE_INSNS, "divw"}, { 0x7c000356, 0x03fff800, DIVIDE_INSNS, "divwe"}, { 0x7c000357, 0x03fff800, DIVIDE_INSNS, "divwe_rc"}, @@ -246,20 +250,20 @@ static struct insn insns[] = { { 0x7c0003d7, 0x03fff800, DIVIDE_INSNS, "divw_rc"}, { 0x7c000396, 0x03fff800, DIVIDE_INSNS, "divwu"}, { 0x7c000397, 0x03fff800, DIVIDE_INSNS, "divwu_rc"}, - { 0x7c000612, 0x03fff801, DIVIDE_INSNS, "modsd"}, + { 0x7c000612, 0x03fff801, SIXTYFOUR_INSNS && DIVIDE_INSNS, "modsd"}, { 0x7c000616, 0x03fff801, DIVIDE_INSNS, "modsw"}, - { 0x7c000212, 0x03fff801, DIVIDE_INSNS, "modud"}, + { 0x7c000212, 0x03fff801, SIXTYFOUR_INSNS && DIVIDE_INSNS, "modud"}, { 0x7c000216, 0x03fff801, DIVIDE_INSNS, "moduw"}, /* Divide instructions with OE=1 */ - { 0x7c0007d2, 0x03fff800, OVERFLOW_INSNS && DIVIDE_INSNS, "divdo"}, - { 0x7c000752, 0x03fff800, OVERFLOW_INSNS && DIVIDE_INSNS, "divdeo"}, - { 0x7c000753, 0x03fff800, OVERFLOW_INSNS && DIVIDE_INSNS, "divdeo_rc"}, - { 0x7c000712, 0x03fff800, OVERFLOW_INSNS && DIVIDE_INSNS, "divdeuo"}, - { 0x7c000713, 0x03fff800, OVERFLOW_INSNS && DIVIDE_INSNS, "divdeuo_rc"}, - { 0x7c0007d3, 0x03fff800, OVERFLOW_INSNS && DIVIDE_INSNS, "divdo_rc"}, - { 0x7c000792, 0x03fff800, OVERFLOW_INSNS && DIVIDE_INSNS, "divduo"}, - { 0x7c000793, 0x03fff800, OVERFLOW_INSNS && DIVIDE_INSNS, "divduo_rc"}, + { 0x7c0007d2, 0x03fff800, SIXTYFOUR_INSNS && OVERFLOW_INSNS && DIVIDE_INSNS, "divdo"}, + { 0x7c000752, 0x03fff800, SIXTYFOUR_INSNS && OVERFLOW_INSNS && DIVIDE_INSNS, "divdeo"}, + { 0x7c000753, 0x03fff800, SIXTYFOUR_INSNS && OVERFLOW_INSNS && DIVIDE_INSNS, "divdeo_rc"}, + { 0x7c000712, 0x03fff800, SIXTYFOUR_INSNS && OVERFLOW_INSNS && DIVIDE_INSNS, "divdeuo"}, + { 0x7c000713, 0x03fff800, SIXTYFOUR_INSNS && OVERFLOW_INSNS && DIVIDE_INSNS, "divdeuo_rc"}, + { 0x7c0007d3, 0x03fff800, SIXTYFOUR_INSNS && OVERFLOW_INSNS && DIVIDE_INSNS, "divdo_rc"}, + { 0x7c000792, 0x03fff800, SIXTYFOUR_INSNS && OVERFLOW_INSNS && DIVIDE_INSNS, "divduo"}, + { 0x7c000793, 0x03fff800, SIXTYFOUR_INSNS && OVERFLOW_INSNS && DIVIDE_INSNS, "divduo_rc"}, { 0x7c0007d6, 0x03fff800, OVERFLOW_INSNS && DIVIDE_INSNS, "divwo"}, { 0x7c000756, 0x03fff800, OVERFLOW_INSNS && DIVIDE_INSNS, "divweo"}, { 0x7c000757, 0x03fff800, OVERFLOW_INSNS && DIVIDE_INSNS, "divweo_rc"}, @@ -270,12 +274,13 @@ static struct insn insns[] = { { 0x7c000797, 0x03fff800, OVERFLOW_INSNS && DIVIDE_INSNS, "divwuo_rc"}, /* Parity ops */ - { 0x7c000174, 0x03fff801, true, "prtyd"}, + { 0x7c000174, 0x03fff801, SIXTYFOUR_INSNS, "prtyd"}, { 0x7c000134, 0x03fff801, true, "prtyw"}, /* Other misc ops */ { 0x7c0003f8, 0x03fff801, true, "cmpb"}, - { 0x7c0001f8, 0x03fff801, false, "bpermd"}, + { 0x7c0001f8, 0x03fff801, SIXTYFOUR_INSNS, "bpermd"}, + { 0x4c000004, 0x03ffffc1, true, "addpcis" }, /* Cache control ops */ { 0x7c0007ac, 0x03fff801, false, "icbi"}, @@ -284,14 +289,189 @@ static struct insn insns[] = { { 0x7c0004ac, 0x03bff801, true, "sync"}, /* Trap ops */ - { 0x08000000, 0x03ffffff, false, "tdi_ti"}, - { 0x7c000088, 0x03fff801, false, "td_ti"}, + { 0x08000000, 0x03ffffff, false && SIXTYFOUR_INSNS, "tdi_ti"}, + { 0x7c000088, 0x03fff801, false && SIXTYFOUR_INSNS, "td_ti"}, { 0x7c000008, 0x03fff801, false, "tw"}, { 0x0c000000, 0x03ffffff, false, "twi"}, + + /* Vector ops */ + { 0x10000002, 0x03fff800, VECTOR_INSNS, "vmaxub" }, + { 0x10000042, 0x03fff800, VECTOR_INSNS, "vmaxuh" }, + { 0x10000082, 0x03fff800, VECTOR_INSNS, "vmaxuw" }, + { 0x100000c2, 0x03fff800, VECTOR_INSNS, "vmaxud" }, + { 0x10000102, 0x03fff800, VECTOR_INSNS, "vmaxsb" }, + { 0x10000142, 0x03fff800, VECTOR_INSNS, "vmaxsh" }, + { 0x10000182, 0x03fff800, VECTOR_INSNS, "vmaxsw" }, + { 0x100001c2, 0x03fff800, VECTOR_INSNS, "vmaxsd" }, + { 0x10000202, 0x03fff800, VECTOR_INSNS, "vminub" }, + { 0x10000242, 0x03fff800, VECTOR_INSNS, "vminuh" }, + { 0x10000282, 0x03fff800, VECTOR_INSNS, "vminuw" }, + { 0x100002c2, 0x03fff800, VECTOR_INSNS, "vminud" }, + { 0x10000302, 0x03fff800, VECTOR_INSNS, "vminsb" }, + { 0x10000342, 0x03fff800, VECTOR_INSNS, "vminsh" }, + { 0x10000382, 0x03fff800, VECTOR_INSNS, "vminsw" }, + { 0x100003c2, 0x03fff800, VECTOR_INSNS, "vminsd" }, + { 0x10000004, 0x03fff800, VECTOR_INSNS, "vrlb" }, + { 0x10000044, 0x03fff800, VECTOR_INSNS, "vrlh" }, + { 0x10000084, 0x03fff800, VECTOR_INSNS, "vrlw" }, + { 0x100000c4, 0x03fff800, VECTOR_INSNS, "vrld" }, + { 0x10000104, 0x03fff800, VECTOR_INSNS, "vslb" }, + { 0x10000144, 0x03fff800, VECTOR_INSNS, "vslh" }, + { 0x10000184, 0x03fff800, VECTOR_INSNS, "vslw" }, + { 0x100005c4, 0x03fff800, VECTOR_INSNS, "vsld" }, + { 0x10000204, 0x03fff800, VECTOR_INSNS, "vsrb" }, + { 0x10000244, 0x03fff800, VECTOR_INSNS, "vsrh" }, + { 0x10000284, 0x03fff800, VECTOR_INSNS, "vsrw" }, + { 0x100006c4, 0x03fff800, VECTOR_INSNS, "vsrd" }, + { 0x10000304, 0x03fff800, VECTOR_INSNS, "vsrab" }, + { 0x10000344, 0x03fff800, VECTOR_INSNS, "vsrah" }, + { 0x10000384, 0x03fff800, VECTOR_INSNS, "vsraw" }, + { 0x100003c4, 0x03fff800, VECTOR_INSNS, "vsrad" }, + { 0x100001c4, 0x03fff800, VECTOR_INSNS, "vsl" }, + { 0x100002c4, 0x03fff800, VECTOR_INSNS, "vsr" }, + { 0x10000744, 0x03fff800, VECTOR_INSNS, "vslv" }, + { 0x10000704, 0x03fff800, VECTOR_INSNS, "vsrv" }, + { 0x10000404, 0x03fff800, VECTOR_INSNS, "vand" }, + { 0x10000444, 0x03fff800, VECTOR_INSNS, "vandc" }, + { 0x10000484, 0x03fff800, VECTOR_INSNS, "vor" }, + { 0x100004c4, 0x03fff800, VECTOR_INSNS, "vxor" }, + { 0x10000504, 0x03fff800, VECTOR_INSNS, "vnor" }, + { 0x10000544, 0x03fff800, VECTOR_INSNS, "vorc" }, + { 0x10000584, 0x03fff800, VECTOR_INSNS, "vnand" }, + { 0x10000604, 0x03fff800, VECTOR_INSNS, "mfvscr" }, + { 0x10000644, 0x03fff800, VECTOR_INSNS, "mtvscr" }, + { 0x10000006, 0x03fff800, VECTOR_INSNS, "vcmpequb" }, + { 0x10000046, 0x03fff800, VECTOR_INSNS, "vcmpequh" }, + { 0x10000086, 0x03fff800, VECTOR_INSNS, "vcmpequw" }, + { 0x100000c7, 0x03fff800, VECTOR_INSNS, "vcmpequd" }, + { 0x10000206, 0x03fff800, VECTOR_INSNS, "vcmpgtub" }, + { 0x10000246, 0x03fff800, VECTOR_INSNS, "vcmpgtuh" }, + { 0x10000286, 0x03fff800, VECTOR_INSNS, "vcmpgtuw" }, + { 0x100002c7, 0x03fff800, VECTOR_INSNS, "vcmpgtud" }, + { 0x10000306, 0x03fff800, VECTOR_INSNS, "vcmpgtsb" }, + { 0x10000346, 0x03fff800, VECTOR_INSNS, "vcmpgtsh" }, + { 0x10000386, 0x03fff800, VECTOR_INSNS, "vcmpgtsw" }, + { 0x100003c7, 0x03fff800, VECTOR_INSNS, "vcmpgtsd" }, + { 0x10000007, 0x03fff800, VECTOR_INSNS, "vcmpneb" }, + { 0x10000047, 0x03fff800, VECTOR_INSNS, "vcmpneh" }, + { 0x10000087, 0x03fff800, VECTOR_INSNS, "vcmpnew" }, + { 0x10000107, 0x03fff800, VECTOR_INSNS, "vcmpnezb" }, + { 0x10000147, 0x03fff800, VECTOR_INSNS, "vcmpnezh" }, + { 0x10000187, 0x03fff800, VECTOR_INSNS, "vcmpnezw" }, + { 0x10000406, 0x03fff800, VECTOR_INSNS, "vcmpequb." }, + { 0x10000446, 0x03fff800, VECTOR_INSNS, "vcmpequh." }, + { 0x10000486, 0x03fff800, VECTOR_INSNS, "vcmpequw." }, + { 0x100004c7, 0x03fff800, VECTOR_INSNS, "vcmpequd." }, + { 0x10000606, 0x03fff800, VECTOR_INSNS, "vcmpgtub." }, + { 0x10000646, 0x03fff800, VECTOR_INSNS, "vcmpgtuh." }, + { 0x10000686, 0x03fff800, VECTOR_INSNS, "vcmpgtuw." }, + { 0x100006c7, 0x03fff800, VECTOR_INSNS, "vcmpgtud." }, + { 0x10000706, 0x03fff800, VECTOR_INSNS, "vcmpgtsb." }, + { 0x10000746, 0x03fff800, VECTOR_INSNS, "vcmpgtsh." }, + { 0x10000786, 0x03fff800, VECTOR_INSNS, "vcmpgtsw." }, + { 0x100007c7, 0x03fff800, VECTOR_INSNS, "vcmpgtsd." }, + { 0x10000407, 0x03fff800, VECTOR_INSNS, "vcmpneb." }, + { 0x10000447, 0x03fff800, VECTOR_INSNS, "vcmpneh." }, + { 0x10000487, 0x03fff800, VECTOR_INSNS, "vcmpnew." }, + { 0x10000507, 0x03fff800, VECTOR_INSNS, "vcmpnezb." }, + { 0x10000547, 0x03fff800, VECTOR_INSNS, "vcmpnezh." }, + { 0x10000587, 0x03fff800, VECTOR_INSNS, "vcmpnezw." }, + { 0x1000000c, 0x03fff800, VECTOR_INSNS, "vmrghb" }, + { 0x1000004c, 0x03fff800, VECTOR_INSNS, "vmrghh" }, + { 0x1000008c, 0x03fff800, VECTOR_INSNS, "vmrghw" }, + { 0x1000010c, 0x03fff800, VECTOR_INSNS, "vmrglb" }, + { 0x1000014c, 0x03fff800, VECTOR_INSNS, "vmrglh" }, + { 0x1000018c, 0x03fff800, VECTOR_INSNS, "vmrglw" }, + { 0x1000020c, 0x03fff800, VECTOR_INSNS, "vspltb" }, + { 0x1000024c, 0x03fff800, VECTOR_INSNS, "vsplth" }, + { 0x1000028c, 0x03fff800, VECTOR_INSNS, "vspltw" }, + { 0x1000030c, 0x03fff800, VECTOR_INSNS, "vspltisb" }, + { 0x1000034c, 0x03fff800, VECTOR_INSNS, "vspltish" }, + { 0x1000038c, 0x03fff800, VECTOR_INSNS, "vspltisw" }, + { 0x1000040c, 0x03fff800, VECTOR_INSNS, "vslo" }, + { 0x1000044c, 0x03fff800, VECTOR_INSNS, "vsro" }, + { 0x1000050c, 0x03fff800, VECTOR_INSNS, "vgbbd" }, + { 0x1000054c, 0x03fff800, VECTOR_INSNS, "vbpermq" }, + { 0x1000068c, 0x03fff800, VECTOR_INSNS, "vmrgow" }, + { 0x1000078c, 0x03fff800, VECTOR_INSNS, "vmrgew" }, + { 0x1000000e, 0x03fff800, VECTOR_INSNS, "vpkuhum" }, + { 0x1000004e, 0x03fff800, VECTOR_INSNS, "vpkuwum" }, + { 0x1000044e, 0x03fff800, VECTOR_INSNS, "vpkudum" }, + { 0x1000020e, 0x03fff800, VECTOR_INSNS, "vupkhsb" }, + { 0x1000028e, 0x03fff800, VECTOR_INSNS, "vupklsb" }, + { 0x1000024e, 0x03fff800, VECTOR_INSNS, "vupkhsh" }, + { 0x100002ce, 0x03fff800, VECTOR_INSNS, "vupklsh" }, + { 0x1000064e, 0x03fff800, VECTOR_INSNS, "vupkhsw" }, + { 0x100006ce, 0x03fff800, VECTOR_INSNS, "vupklsw" }, + { 0x1000002a, 0x03ffffc0, VECTOR_INSNS, "vsel" }, + { 0x1000002b, 0x03ffffc0, VECTOR_INSNS, "vperm" }, + { 0x1000002c, 0x03ffffc0, VECTOR_INSNS, "vsldoi" }, + { 0x1000003b, 0x03ffffc0, VECTOR_INSNS, "vpermr" }, + { 0x10000000, 0x03fff800, VECTOR_INSNS, "vaddubm" }, + { 0x10000040, 0x03fff800, VECTOR_INSNS, "vadduhm" }, + { 0x10000080, 0x03fff800, VECTOR_INSNS, "vadduwm" }, + { 0x100000c0, 0x03fff800, VECTOR_INSNS, "vaddudm" }, + { 0x10000100, 0x03fff800, VECTOR_INSNS, "vadduqm" }, + { 0x10000200, 0x03fff800, VECTOR_INSNS, "vaddubs" }, + { 0x10000240, 0x03fff800, VECTOR_INSNS, "vadduhs" }, + { 0x10000280, 0x03fff800, VECTOR_INSNS, "vadduws" }, + { 0x10000300, 0x03fff800, VECTOR_INSNS, "vaddsbs" }, + { 0x10000340, 0x03fff800, VECTOR_INSNS, "vaddshs" }, + { 0x10000380, 0x03fff800, VECTOR_INSNS, "vaddsws" }, + { 0x10000400, 0x03fff800, VECTOR_INSNS, "vsububm" }, + { 0x10000440, 0x03fff800, VECTOR_INSNS, "vsubuhm" }, + { 0x10000480, 0x03fff800, VECTOR_INSNS, "vsubuwm" }, + { 0x100004c0, 0x03fff800, VECTOR_INSNS, "vsubudm" }, + { 0x10000500, 0x03fff800, VECTOR_INSNS, "vsubuqm" }, + { 0x10000600, 0x03fff800, VECTOR_INSNS, "vsububs" }, + { 0x10000640, 0x03fff800, VECTOR_INSNS, "vsubuhs" }, + { 0x10000680, 0x03fff800, VECTOR_INSNS, "vsubuws" }, + { 0x10000700, 0x03fff800, VECTOR_INSNS, "vsubsbs" }, + { 0x10000740, 0x03fff800, VECTOR_INSNS, "vsubshs" }, + { 0x10000780, 0x03fff800, VECTOR_INSNS, "vsubsws" }, + { 0x10000703, 0x03fff800, VECTOR_INSNS, "vpopcntb" }, + { 0x10000743, 0x03fff800, VECTOR_INSNS, "vpopcnth" }, + { 0x10000783, 0x03fff800, VECTOR_INSNS, "vpopcntw" }, + { 0x100007c3, 0x03fff800, VECTOR_INSNS, "vpopcntd" }, + { 0x10000788, 0x03fff800, VECTOR_INSNS, "vsumsws" }, + { 0x10000688, 0x03fff800, VECTOR_INSNS, "vsum2sws" }, + { 0x10000708, 0x03fff800, VECTOR_INSNS, "vsum4sbs" }, + { 0x10000608, 0x03fff800, VECTOR_INSNS, "vsum4ubs" }, + { 0x10000648, 0x03fff800, VECTOR_INSNS, "vsum4shs" }, + { 0x10000602, 0x03e0f800, VECTOR_INSNS, "vclzlsbb" }, + { 0x10010602, 0x03e0f800, VECTOR_INSNS, "vctzlsbb" }, + { 0x100007c2, 0x03fff800, VECTOR_INSNS, "vclzd" }, + { 0x7c00000c, 0x03fff800, VECTOR_INSNS, "lvsl" }, + { 0x7c00004c, 0x03fff800, VECTOR_INSNS, "lvsr" }, + { 0xf0000410, 0x03fff807, VSX_INSNS, "xxland" }, + { 0xf0000450, 0x03fff807, VSX_INSNS, "xxlandc" }, + { 0xf00005d0, 0x03fff807, VSX_INSNS, "xxleqv" }, + { 0xf0000590, 0x03fff807, VSX_INSNS, "xxlnand" }, + { 0xf0000550, 0x03fff807, VSX_INSNS, "xxlorc" }, + { 0xf0000510, 0x03fff807, VSX_INSNS, "xxlnor" }, + { 0xf0000490, 0x03fff807, VSX_INSNS, "xxlor" }, + { 0xf00004d0, 0x03fff807, VSX_INSNS, "xxlxor" }, + { 0xf0000010, 0x03fffb07, VSX_INSNS, "xxsldwi" }, + { 0xf0000050, 0x03fffb07, VSX_INSNS, "xxpermdi" }, + { 0xf0000090, 0x03fff803, VSX_INSNS, "xxmrghw" }, + { 0xf0000190, 0x03fff803, VSX_INSNS, "xxmrglw" }, + { 0xf0000290, 0x03fff803, VSX_INSNS, "xxspltw" }, + { 0xf0000464, 0x03fff803, VSX_INSNS, "xsrsp" }, + { 0xf00000d0, 0x03fff803, VSX_INSNS, "xxperm" }, + { 0xf00001d0, 0x03fff803, VSX_INSNS, "xxpermr" }, + { 0xf0000030, 0x03ffffcf, VSX_INSNS, "xxsel" }, + { 0x7c000066, 0x3ffff801, VSX_INSNS, "mfvsrd" }, + { 0x7c000266, 0x3ffff801, VSX_INSNS, "mfvsrld" }, + { 0x7c0000e6, 0x3ffff801, VSX_INSNS, "mfvsrwz" }, + { 0x7c000166, 0x3ffff801, VSX_INSNS, "mtvsrd" }, + { 0x7c000366, 0x3ffff801, VSX_INSNS, "mtvsrdd" }, + { 0x7c0001a6, 0x3ffff801, VSX_INSNS, "mtvsrwa" }, + { 0x7c000326, 0x3ffff801, VSX_INSNS, "mtvsrws" }, + { 0x7c0001e6, 0x3ffff801, VSX_INSNS, "mtvsrwz" }, }; #define NR_INSNS (sizeof(insns) / sizeof(struct insn)) -enum form_t { X, D, DS }; +enum form_t { X, XL, D, DS, DQ }; struct ldst_insn { uint32_t opcode; @@ -307,9 +487,9 @@ struct ldst_insn { static struct ldst_insn ldst_insns[] = { { 0x88000000, 0x03ffffff, D, false, 1, 1, true, "lbz"}, { 0x7c0000ae, 0x03fff801, X, false, 1, 1, true, "lbzx"}, - { 0xe8000000, 0x03fffffc, DS, false, 8, 4, true, "ld"}, - { 0x7c000428, 0x03fff801, X, false, 8, 1, true, "ldbrx"}, - { 0x7c00002a, 0x03fff801, X, false, 8, 1, true, "ldx"}, + { 0xe8000000, 0x03fffffc, DS, false, 8, 4, SIXTYFOUR_INSNS, "ld"}, + { 0x7c000428, 0x03fff801, X, false, 8, 1, SIXTYFOUR_INSNS, "ldbrx"}, + { 0x7c00002a, 0x03fff801, X, false, 8, 1, SIXTYFOUR_INSNS, "ldx"}, { 0x7c00062c, 0x03fff801, X, false, 2, 1, true, "lhbrx"}, { 0xa0000000, 0x03ffffff, D, false, 2, 1, true, "lhz"}, { 0x7c00022e, 0x03fff801, X, false, 2, 1, true, "lhzx"}, @@ -318,9 +498,9 @@ static struct ldst_insn ldst_insns[] = { { 0x7c00002e, 0x03fff801, X, false, 4, 1, true, "lwzx"}, { 0x98000000, 0x03ffffff, D, false, 1, 1, true, "stb"}, { 0x7c0001ae, 0x03fff801, X, false, 1, 1, true, "stbx"}, - { 0xf8000000, 0x03fffffc, DS, false, 8, 4, true, "std"}, - { 0x7c000528, 0x03fff801, X, false, 8, 1, true, "stdbrx"}, - { 0x7c00012a, 0x03fff801, X, false, 8, 1, true, "stdx"}, + { 0xf8000000, 0x03fffffc, DS, false, 8, 4, SIXTYFOUR_INSNS, "std"}, + { 0x7c000528, 0x03fff801, X, false, 8, 1, SIXTYFOUR_INSNS, "stdbrx"}, + { 0x7c00012a, 0x03fff801, X, false, 8, 1, SIXTYFOUR_INSNS, "stdx"}, { 0xb0000000, 0x03ffffff, D, false, 2, 1, true, "sth"}, { 0x7c00072c, 0x03fff801, X, false, 2, 1, true, "sthbrx"}, { 0x7c00032e, 0x03fff801, X, false, 2, 1, true, "sthx"}, @@ -330,9 +510,9 @@ static struct ldst_insn ldst_insns[] = { { 0x7c000068, 0x03fff801, X, false, 1, 1, true, "lbarx"}, { 0x7c0000e8, 0x03fff801, X, false, 2, 2, true, "lharx"}, { 0x7c000028, 0x03fff801, X, false, 4, 4, true, "lwarx"}, - { 0x7c0000a8, 0x03fff801, X, false, 8, 8, true, "ldarx"}, - { 0xe8000001, 0x03fffffc, DS, true, 8, 4, LDST_UPDATE, "ldu"}, - { 0x7c00006a, 0x03fff801, X, true, 8, 1, LDST_UPDATE, "ldux"}, + { 0x7c0000a8, 0x03fff801, X, false, 8, 8, SIXTYFOUR_INSNS, "ldarx"}, + { 0xe8000001, 0x03fffffc, DS, true, 8, 4, SIXTYFOUR_INSNS && LDST_UPDATE, "ldu"}, + { 0x7c00006a, 0x03fff801, X, true, 8, 1, SIXTYFOUR_INSNS && LDST_UPDATE, "ldux"}, { 0xa8000000, 0x03ffffff, D, false, 2, 1, true, "lha"}, { 0x7c0002ae, 0x03fff801, X, false, 2, 1, true, "lhax"}, { 0xe8000002, 0x03fffffc, DS, false, 4, 4, true, "lwa"}, @@ -343,8 +523,8 @@ static struct ldst_insn ldst_insns[] = { { 0x7c0001ee, 0x03fff801, X, true, 1, 1, LDST_UPDATE, "stbux"}, { 0xb4000000, 0x03ffffff, D, true, 2, 1, LDST_UPDATE, "sthu"}, { 0x7c00036e, 0x03fff801, X, true, 2, 1, LDST_UPDATE, "sthux"}, - { 0xf8000001, 0x03fffffc, DS, true, 8, 1, LDST_UPDATE, "stdu"}, - { 0x7c00016a, 0x03fff801, X, true, 8, 1, LDST_UPDATE, "stdux"}, + { 0xf8000001, 0x03fffffc, DS, true, 8, 1, SIXTYFOUR_INSNS && LDST_UPDATE, "stdu"}, + { 0x7c00016a, 0x03fff801, X, true, 8, 1, SIXTYFOUR_INSNS && LDST_UPDATE, "stdux"}, { 0x8c000000, 0x03ffffff, D, true, 1, 1, LDST_UPDATE, "lbzu"}, { 0x7c0000ee, 0x03fff801, X, true, 1, 1, LDST_UPDATE, "lbzux"}, { 0xa4000000, 0x03ffffff, D, true, 2, 1, LDST_UPDATE, "lhzu"}, @@ -354,14 +534,57 @@ static struct ldst_insn ldst_insns[] = { { 0xac000000, 0x03ffffff, D, true, 2, 1, LDST_UPDATE, "lhau"}, { 0x7c0002ee, 0x03fff801, X, true, 2, 1, LDST_UPDATE, "lhaux"}, { 0x7c0002ea, 0x03fff801, X, true, 4, 1, LDST_UPDATE, "lwaux"}, - { 0x7c00056d, 0x03fff800, X, false, 1, 1, true, "stbcx."}, - { 0x7c0005ad, 0x03fff800, X, false, 2, 2, true, "sthcx."}, - { 0x7c00012d, 0x03fff800, X, false, 4, 4, true, "stwcx."}, - { 0x7c0001ad, 0x03fff800, X, false, 8, 8, true, "stdcx."}, + { 0x7c00056d, 0x03fff800, X, false, 1, 1, STCOND_INSNS, "stbcx."}, + { 0x7c0005ad, 0x03fff800, X, false, 2, 2, STCOND_INSNS, "sthcx."}, + { 0x7c00012d, 0x03fff800, X, false, 4, 4, STCOND_INSNS, "stwcx."}, + { 0x7c0001ad, 0x03fff800, X, false, 8, 8, SIXTYFOUR_INSNS && STCOND_INSNS, "stdcx."}, + { 0x7c00000e, 0x03fff800, X, false, 1, 1, VECTOR_INSNS, "lvebx" }, + { 0x7c00004e, 0x03fff800, X, false, 2, 1, VECTOR_INSNS, "lvehx" }, + { 0x7c00008e, 0x03fff800, X, false, 4, 1, VECTOR_INSNS, "lvewx" }, + { 0x7c0000ce, 0x03fff800, X, false, 16, 1, VECTOR_INSNS, "lvx" }, + { 0x7c0002ce, 0x03fff800, X, false, 16, 1, VECTOR_INSNS, "lvxl" }, + { 0x7c00010e, 0x03fff800, X, false, 1, 1, VECTOR_INSNS, "stvebx" }, + { 0x7c00014e, 0x03fff800, X, false, 2, 1, VECTOR_INSNS, "stvehx" }, + { 0x7c00018e, 0x03fff800, X, false, 4, 1, VECTOR_INSNS, "stvewx" }, + { 0x7c0001ce, 0x03fff800, X, false, 16, 1, VECTOR_INSNS, "stvx" }, + { 0x7c0003ce, 0x03fff800, X, false, 16, 1, VECTOR_INSNS, "stvxl" }, + { 0xe4000002, 0x03fffffc, DS, false, 8, 1, VSX_INSNS, "lxsd" }, + { 0xe4000003, 0x03fffffc, DS, false, 4, 1, VSX_INSNS, "lxssp" }, + { 0xf4000001, 0x03fffff8, DQ, false, 16, 1, VSX_INSNS, "lxv" }, + { 0x7c000498, 0x03fff801, X, false, 8, 1, VSX_INSNS, "lxsdx" }, + { 0x7c00061a, 0x03fff801, X, false, 1, 1, VSX_INSNS, "lxsibzx" }, + { 0x7c00065a, 0x03fff801, X, false, 1, 1, VSX_INSNS, "lxsihzx" }, + { 0x7c000098, 0x03fff801, X, false, 1, 1, VSX_INSNS, "lxsiwax" }, + { 0x7c000018, 0x03fff801, X, false, 1, 1, VSX_INSNS, "lxsiwzx" }, + { 0x7c000418, 0x03fff801, X, false, 1, 1, VSX_INSNS, "lxsspx" }, + { 0x7c0006d8, 0x03fff801, X, false, 16, 1, VSX_INSNS, "lxvb16x" }, + { 0x7c000698, 0x03fff801, X, false, 16, 1, VSX_INSNS, "lxvd2x" }, + { 0x7c00021a, 0x03fff801, XL, false, 16, 1, VSX_INSNS, "lxvl" }, + { 0x7c00025a, 0x03fff801, XL, false, 16, 1, VSX_INSNS, "lxvll" }, + { 0x7c000218, 0x03fff841, X, false, 16, 1, VSX_INSNS, "lxvx" }, + { 0x7c000298, 0x03fff801, X, false, 8, 1, VSX_INSNS, "lxvdsx" }, + { 0x7c000658, 0x03fff801, X, false, 16, 1, VSX_INSNS, "lxvh8x" }, + { 0x7c000618, 0x03fff801, X, false, 16, 1, VSX_INSNS, "lxvw4x" }, + { 0x7c0002d8, 0x03fff801, X, false, 4, 1, VSX_INSNS, "lxvwsx" }, + { 0xf4000002, 0x03fffffc, DS, false, 8, 1, VSX_INSNS, "stxsd" }, + { 0xf4000003, 0x03fffffc, DS, false, 4, 1, VSX_INSNS, "stxssp" }, + { 0xf4000005, 0x03fffff8, DQ, false, 16, 1, VSX_INSNS, "stxv" }, + { 0x7c000598, 0x03fff801, X, false, 8, 1, VSX_INSNS, "stxsdx" }, + { 0x7c00071a, 0x03fff801, X, false, 1, 1, VSX_INSNS, "stxsibx" }, + { 0x7c00075a, 0x03fff801, X, false, 2, 1, VSX_INSNS, "stxsihx" }, + { 0x7c000118, 0x03fff801, X, false, 4, 1, VSX_INSNS, "stxsiwx" }, + { 0x7c000518, 0x03fff801, X, false, 4, 1, VSX_INSNS, "stxsspx" }, + { 0x7c0007d8, 0x03fff801, X, false, 16, 1, VSX_INSNS, "stxvb16x" }, + { 0x7c000798, 0x03fff801, X, false, 16, 1, VSX_INSNS, "stxvd2x" }, + { 0x7c000758, 0x03fff801, X, false, 16, 1, VSX_INSNS, "stxvh8x" }, + { 0x7c000718, 0x03fff801, X, false, 16, 1, VSX_INSNS, "stxvw4x" }, + { 0x7c00031a, 0x03fff801, XL, false, 16, 1, VSX_INSNS, "stxvl" }, + { 0x7c00035a, 0x03fff801, XL, false, 16, 1, VSX_INSNS, "stxvll" }, + { 0x7c000318, 0x03fff801, X, false, 16, 1, VSX_INSNS, "stxvx" }, }; #define NR_LDST_INSNS (sizeof(ldst_insns) / sizeof(struct ldst_insn)) -static unsigned long fxvalues[] = { +static uint64_t fxvalues[] = { 0x0000000000000000, /* all zeros */ 0xFFFFFFFFFFFFFFFF, /* all ones */ 0x0000000000000001, /* one */ @@ -390,37 +613,70 @@ static unsigned long fxvalues[] = { }; #define NR_FXVALUES (sizeof(fxvalues)/sizeof(fxvalues[0])) -#define PPC_OPCODE(OPC) ((OPC) << 26) +#define PPC_OPCODE(OPC) ((unsigned)(OPC) << 26) #define PPC_RT(RT) ((RT) << 21) #define PPC_RS(RS) ((RS) << 21) +#define PPC_XS(XS) (((XS) & 0x1f) << 21) #define PPC_RA(RA) ((RA) << 16) #define PPC_RB(RB) ((RB) << 11) #define PPC_SH(SH) ((((SH) >> 5) << 1) | (((SH) & 0x1f) << 11)) #define PPC_ME(ME) ((((ME) >> 5) << 5) | (((ME) & 0x1f) << 6)) +#define PPC_SX(XS) (((XS) >> 5) & 1) +#define PPC_SX2(XS) (((XS) >> 2) & 8) #define ADDIS(RT, RA, UI) (PPC_OPCODE(15) | PPC_RS(RT) | PPC_RA(RA) | ((UI) & 0xffff)) #define ORIS(RS, RA, UI) (PPC_OPCODE(25) | PPC_RS(RS) | PPC_RA(RA) | ((UI) & 0xffff)) #define ORI(RS, RA, UI) (PPC_OPCODE(24) | PPC_RS(RS) | PPC_RA(RA) | ((UI) & 0xffff)) #define STD(RS, RA, DS) (PPC_OPCODE(62) | PPC_RS(RS) | PPC_RA(RA) | DS) +#define STW(RS, RA, DS) (PPC_OPCODE(36) | PPC_RS(RS) | PPC_RA(RA) | D) +#define STFD(FRS, RA, D) (PPC_OPCODE(54) | PPC_RS(FRS) | PPC_RA(RA) | D) +#define STXV(XS, RA, DQ) (PPC_OPCODE(61) | PPC_XS(XS) | PPC_RA(RA) | (DQ) | PPC_SX2(XS) | 5) #define RLDICR(RA, RS, SH, ME) (PPC_OPCODE(30) | PPC_RA(RA) | PPC_RS(RS) | PPC_SH(SH) | PPC_ME(ME) | 4) #define NOP 0x60000000 +#define MFFS(FRT) (PPC_OPCODE(63) | PPC_RT(FRT) | (583 << 1)) +#define MTFSF(FRB) (PPC_OPCODE(63) | (1 << 25) | PPC_RB(FRB) | (711 << 1)) +#define MFVSCR(VRT) (PPC_OPCODE(4) | PPC_RT(VRT) | 1540) +#define MFVSRLD(RA, XS) (PPC_OPCODE(31) | PPC_XS(XS) | PPC_RA(RA) | (307 << 1) | PPC_SX(XS)) -static void *load_64bit_imm(uint32_t *p, int gpr, uint64_t val) +static void *load_reg_imm(uint32_t *p, int gpr, reg_t val) { +#if SIXTYFOUR_INSNS *p++ = ADDIS(gpr, 0, (val >> 48) & 0xffff); *p++ = ORI(gpr, gpr, (val >> 32) & 0xffff); *p++ = RLDICR(gpr, gpr, 32, 31); *p++ = ORIS(gpr, gpr, (val >> 16) & 0xffff); +#else + *p++ = ADDIS(gpr, 0, (val >> 16) & 0xffff); +#endif *p++ = ORI(gpr, gpr, val & 0xffff); return p; } +static void print_insn(uint32_t insn, const char *name, unsigned long addr) +{ + const char *sep = " "; + long int i; + + puthexn(insn, 8); + print(" "); + print(name); + for (i = 0; i < 4; ++i) { + print(sep); + putlong((insn >> (21 - i * 5)) & 0x1f); + sep = ","; + } + print(" @"); + puthexn(addr, 8); + print("\r\n"); +} + static void *do_one_loadstore(uint32_t *p, void *mem, struct ldst_insn *insnp, uint32_t *lfsr, bool print_insns) { uint32_t insn = insnp->opcode; - uint64_t off; + reg_t off; + uint32_t mask = insnp->mask; /* * The preceding instruction might have been a BC+8, put a NOP here @@ -430,7 +686,7 @@ static void *do_one_loadstore(uint32_t *p, void *mem, struct ldst_insn *insnp, /* Form a small positive or negative offset */ *lfsr = mylfsr(32, *lfsr); - off = *lfsr % 32; + off = *lfsr % (MEM_SIZE / 2); /* Align the offset */ off &= ~(insnp->align - 1); @@ -438,9 +694,9 @@ static void *do_one_loadstore(uint32_t *p, void *mem, struct ldst_insn *insnp, /* Use the high bit for the sign of the offset */ if (*lfsr & 0x80000000) off = -off; - else if (off + insnp->size > 32) + else if (off + insnp->size > (MEM_SIZE / 2)) /* make sure we don't access outside our mem array */ - off = 32 - insnp->size; + off = (MEM_SIZE / 2) - insnp->size; if (insnp->form == X) { uint8_t ra, rb, rt; @@ -456,10 +712,31 @@ static void *do_one_loadstore(uint32_t *p, void *mem, struct ldst_insn *insnp, rt = (ra + 1) % 32; /* if RA=R0 the hardware uses 0, so put the base in RB */ - p = load_64bit_imm(p, rb, (unsigned long)mem); + p = load_reg_imm(p, rb, (unsigned long)mem); + + p = load_reg_imm(p, ra, off); + insn |= PPC_RT(rt) | PPC_RA(ra) | PPC_RB(rb); + mask &= ~0x03fff800; + } else if (insnp->form == XL) { + /* VSX load/store with length in RB top byte */ + uint8_t ra, rb, rt; + + *lfsr = mylfsr(32, *lfsr); + rb = *lfsr % 32; + ra = (rb + 1) % 32; + /* RA=0 uses address = 0, so use R1 */ + if (ra == 0) + ra = 1; + rt = (ra + 1) % 32; + + /* address has to go in RA */ + p = load_reg_imm(p, ra, (unsigned long)mem + off); + + /* shift RB left 56 bits */ + *p++ = RLDICR(rb, rb, 56, 7); - p = load_64bit_imm(p, ra, off); insn |= PPC_RT(rt) | PPC_RA(ra) | PPC_RB(rb); + mask &= ~0x03fff800; } else { uint8_t ra, rt; @@ -474,18 +751,29 @@ static void *do_one_loadstore(uint32_t *p, void *mem, struct ldst_insn *insnp, rt = (ra + 1) % 32; - p = load_64bit_imm(p, ra, (unsigned long)mem); + if (insnp->form == DS) { + off &= 0xfffc; + mask &= ~0x03fffffc; + } else if (insnp->form == DQ) { + off &= 0xfff0; + mask &= ~0x03fffff0; + } else { + off &= 0xffff; + mask &= ~0x03ffffff; + } + p = load_reg_imm(p, ra, (unsigned long)mem); - insn |= PPC_RT(rt) | PPC_RA(ra) | (off & 0xffff & insnp->mask); + insn |= PPC_RT(rt) | PPC_RA(ra) | off; } - - if (print_insns) { - puthex(insn); - print(" "); - print(insnp->name); - print("\r\n"); + /* if any variable bits left, fill them in */ + if (mask) { + *lfsr = mylfsr(32, *lfsr); + insn |= *lfsr & mask; } + if (print_insns) + print_insn(insn, insnp->name, (unsigned long)p); + *p++ = insn; return p; @@ -509,11 +797,14 @@ static inline void icache_flush(void *start, void *end) #define TRAP_INSN 0x7fe00008 void *generate_testcase(void *ptr, void *mem, void *save, unsigned long seed, - unsigned long nr_insns, bool print_insns, bool sim) + unsigned long nr_insns, bool print_insns, bool sim, + unsigned long *lenp) { void *start = ptr; uint32_t *p; uint32_t lfsr = seed; + void *orig_ptr = ptr; + unsigned long j; /* LFSR needs a non zero value to work */ if (!lfsr) @@ -540,12 +831,30 @@ void *generate_testcase(void *ptr, void *mem, void *save, unsigned long seed, /* Initialize GPRs */ for (unsigned long i = 0; i < 32; i++) { - uint64_t val; + reg_t val; lfsr = mylfsr(32, lfsr); val = fxvalues[lfsr % NR_FXVALUES]; - ptr = load_64bit_imm(ptr, i, val); + ptr = load_reg_imm(ptr, i, val); + } + + /* Initialize VSCR to 0, and VSRs from the GPRs */ + if (VSX_INSNS) { + p = ptr; + /* vxor v0,v0,v0; mtvscr v0 */ + *p++ = 0x100004c4; + *p++ = 0x10000644; + /* xxlxor 0,0,0; mtfsf 0,0,1,0 */ + *p++ = 0xf00004d0; + *p++ = MTFSF(0); + for (j = 0; j < 64; ++j) { + lfsr = mylfsr(32, lfsr); + /* generate mtvsrdd instruction from random RA/RB */ + *p++ = PPC_OPCODE(31) | PPC_RT(j & 0x1f) | PPC_RB(lfsr & 0x3ff) | + (435 * 2) | (j >> 5); + } + ptr = p; } /* At this point we can start the test */ @@ -570,12 +879,8 @@ void *generate_testcase(void *ptr, void *mem, void *save, unsigned long seed, lfsr = mylfsr(32, lfsr); insn = insns[j].opcode | (lfsr & insns[j].mask); - if (print_insns) { - puthex(insn); - print(" "); - print(insns[j].name); - print("\r\n"); - } + if (print_insns) + print_insn(insn, insns[j].name, (unsigned long)ptr); *(uint32_t *)ptr = insn; ptr += sizeof(uint32_t); @@ -595,12 +900,27 @@ void *generate_testcase(void *ptr, void *mem, void *save, unsigned long seed, * save area and write the GPRs out. Assume address is in * the low 32 bits. */ - ptr = load_64bit_imm(ptr, 31, (uint64_t)save); + ptr = load_reg_imm(ptr, 31, (unsigned long)save); p = ptr; /* Save GPR 0-31 to our save area */ - for (unsigned long i = 0; i < 31; i++) - *p++ = STD(i, 31, i*sizeof(uint64_t)); + for (unsigned long i = 0; i < 31; i++) { + if (SIXTYFOUR_INSNS) + *p++ = STD(i, 31, i*sizeof(reg_t)); + else + *p++ = STW(i, 31, i * sizeof(reg_t)); + } + + /* Save VSR0-63, FPSCR, VSCR to our save area */ + if (VSX_INSNS) { + for (j = 0; j < 64; ++j) + *p++ = STXV(j, 31, 38 * sizeof(reg_t) + j * 16); + *p++ = MFFS(0); + *p++ = STFD(0, 31, 36 * sizeof(reg_t)); + *p++ = MFVSCR(0); + *p++ = MFVSRLD(0, 32); + *p++ = STD(0, 31, 37 * sizeof(reg_t)); + } ptr = p; /* Second epilog */ @@ -610,6 +930,8 @@ void *generate_testcase(void *ptr, void *mem, void *save, unsigned long seed, icache_flush(start, ptr); } + if (lenp) + *lenp += ptr - orig_ptr; return ptr; } diff --git a/generate.h b/generate.h index f7d1115..de3e22a 100644 --- a/generate.h +++ b/generate.h @@ -1,3 +1,6 @@ -void *generate_testcase(void *ptr, void *mem, void *save, unsigned long seed, unsigned long nr_insns, bool print_insns, bool sim); +void *generate_testcase(void *ptr, void *mem, void *save, unsigned long seed, unsigned long nr_insns, + bool print_insns, bool sim, unsigned long *lenp); void enable_insn(const char *insn); void disable_insn(const char *insn); + +typedef unsigned long reg_t; diff --git a/helpers.S b/helpers.S index 8e0f4c0..f378071 100644 --- a/helpers.S +++ b/helpers.S @@ -34,6 +34,8 @@ prolog1_start: std r30,168(r1) std r31,176(r1) + /* We don't save VMX/VSX regs since we compile with -mno-altivec -mno-vsx */ + /* Save our stack pointer into the save area */ std r1,248(r3) .globl prolog1_end diff --git a/lfsr.c b/lfsr.c deleted file mode 100644 index ef086d2..0000000 --- a/lfsr.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Galois LFSR - * From: - * https://en.wikipedia.org/wiki/Linear-feedback_shift_register - */ -const unsigned long lfsr_taps[] = { - 0, - 0, - (1UL << (2-1)) | (1UL << (1-1)), - (1UL << (3-1)) | (1UL << (2-1)), - (1UL << (4-1)) | (1UL << (3-1)), - (1UL << (5-1)) | (1UL << (3-1)), - (1UL << (6-1)) | (1UL << (5-1)), - (1UL << (7-1)) | (1UL << (6-1)), - (1UL << (8-1)) | (1UL << (6-1)) | (1UL << (5-1)) | (1UL << (4-1)), - (1UL << (9-1)) | (1UL << (5-1)), - (1UL << (10-1)) | (1UL << (7-1)), - (1UL << (11-1)) | (1UL << (9-1)), - (1UL << (12-1)) | (1UL << (6-1)) | (1UL << (4-1)) | (1UL << (1-1)), - (1UL << (13-1)) | (1UL << (4-1)) | (1UL << (3-1)) | (1UL << (1-1)), - (1UL << (14-1)) | (1UL << (5-1)) | (1UL << (3-1)) | (1UL << (1-1)), - (1UL << (15-1)) | (1UL << (14-1)), - (1UL << (16-1)) | (1UL << (15-1)) | (1UL << (13-1)) | (1UL << (4-1)), - (1UL << (17-1)) | (1UL << (14-1)), - (1UL << (18-1)) | (1UL << (11-1)), - (1UL << (19-1)) | (1UL << (6-1)) | (1UL << (2-1)) | (1UL << (1-1)), - (1UL << (20-1)) | (1UL << (17-1)), - (1UL << (21-1)) | (1UL << (19-1)), - (1UL << (22-1)) | (1UL << (21-1)), - (1UL << (23-1)) | (1UL << (18-1)), - (1UL << (24-1)) | (1UL << (23-1)) | (1UL << (22-1)) | (1UL << (17-1)), - (1UL << (25-1)) | (1UL << (22-1)), - (1UL << (26-1)) | (1UL << (6-1)) | (1UL << (2-1)) | (1UL << (1-1)), - (1UL << (27-1)) | (1UL << (5-1)) | (1UL << (2-1)) | (1UL << (1-1)), - (1UL << (28-1)) | (1UL << (25-1)), - (1UL << (29-1)) | (1UL << (27-1)), - (1UL << (30-1)) | (1UL << (6-1)) | (1UL << (4-1)) | (1UL << (1-1)), - (1UL << (31-1)) | (1UL << (28-1)), - (1UL << (32-1)) | (1UL << (22-1)) | (1UL << (2-1)) | (1UL << (1-1)), -#ifdef __LP64__ - (1UL << (33-1)) | (1UL << (20-1)), - (1UL << (34-1)) | (1UL << (27-1)) | (1UL << (2-1)) | (1UL << (1-1)), - (1UL << (35-1)) | (1UL << (33-1)), - (1UL << (36-1)) | (1UL << (25-1)), - (1UL << (37-1)) | (1UL << (5-1)) | (1UL << (4-1)) | (1UL << (3-1)) | (1UL << (2-1)) | (1UL << (1-1)), - (1UL << (38-1)) | (1UL << (6-1)) | (1UL << (5-1)) | (1UL << (1-1)), - (1UL << (39-1)) | (1UL << (35-1)), - (1UL << (40-1)) | (1UL << (38-1)) | (1UL << (21-1)) | (1UL << (19-1)), - (1UL << (41-1)) | (1UL << (38-1)), - (1UL << (42-1)) | (1UL << (41-1)) | (1UL << (20-1)) | (1UL << (19-1)), - (1UL << (43-1)) | (1UL << (42-1)) | (1UL << (38-1)) | (1UL << (37-1)), - (1UL << (44-1)) | (1UL << (43-1)) | (1UL << (18-1)) | (1UL << (17-1)), - (1UL << (45-1)) | (1UL << (44-1)) | (1UL << (42-1)) | (1UL << (41-1)), - (1UL << (46-1)) | (1UL << (45-1)) | (1UL << (26-1)) | (1UL << (25-1)), - (1UL << (47-1)) | (1UL << (42-1)), - (1UL << (48-1)) | (1UL << (47-1)) | (1UL << (21-1)) | (1UL << (20-1)), - (1UL << (49-1)) | (1UL << (40-1)), - (1UL << (50-1)) | (1UL << (49-1)) | (1UL << (24-1)) | (1UL << (23-1)), - (1UL << (51-1)) | (1UL << (50-1)) | (1UL << (36-1)) | (1UL << (35-1)), - (1UL << (52-1)) | (1UL << (49-1)), - (1UL << (53-1)) | (1UL << (52-1)) | (1UL << (38-1)) | (1UL << (37-1)), - (1UL << (54-1)) | (1UL << (53-1)) | (1UL << (18-1)) | (1UL << (17-1)), - (1UL << (55-1)) | (1UL << (31-1)), - (1UL << (56-1)) | (1UL << (55-1)) | (1UL << (35-1)) | (1UL << (34-1)), - (1UL << (57-1)) | (1UL << (50-1)), - (1UL << (58-1)) | (1UL << (39-1)), - (1UL << (59-1)) | (1UL << (58-1)) | (1UL << (38-1)) | (1UL << (37-1)), - (1UL << (60-1)) | (1UL << (59-1)), - (1UL << (61-1)) | (1UL << (60-1)) | (1UL << (46-1)) | (1UL << (45-1)), - (1UL << (62-1)) | (1UL << (61-1)) | (1UL << (6-1)) | (1UL << (5-1)), - (1UL << (63-1)) | (1UL << (62-1)), -#endif -}; diff --git a/lfsr.h b/lfsr.h index 476fbae..83fa1c0 100644 --- a/lfsr.h +++ b/lfsr.h @@ -1,23 +1,107 @@ -extern unsigned long lfsr_taps[]; +/* + * Copyright (C) 2020, Anton Blanchard , IBM + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. -static inline unsigned long __mylfsr(unsigned long lfsr_tap, unsigned long prev) + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Galois LFSR + * + * Polynomials verified with https://bitbucket.org/gallen/mlpolygen/ + */ +static inline unsigned long mylfsr(unsigned long bits, unsigned long prev) { + const unsigned long lfsr_taps[] = { + 0x0, + 0x0, + 0x3, + 0x6, + 0xc, + 0x14, + 0x30, + 0x60, + 0xb8, + 0x110, + 0x240, + 0x500, + 0x829, + 0x100d, + 0x2015, + 0x6000, + 0xd008, + 0x12000, + 0x20400, + 0x40023, + 0x90000, + 0x140000, + 0x300000, + 0x420000, + 0xe10000, + 0x1200000, + 0x2000023, + 0x4000013, + 0x9000000, + 0x14000000, + 0x20000029, + 0x48000000, + 0x80200003, +#ifdef __LP64__ + 0x100080000, + 0x204000003, + 0x500000000, + 0x801000000, + 0x100000001f, + 0x2000000031, + 0x4400000000, + 0xa000140000, + 0x12000000000, + 0x300000c0000, + 0x63000000000, + 0xc0000030000, + 0x1b0000000000, + 0x300003000000, + 0x420000000000, + 0xc00000180000, + 0x1008000000000, + 0x3000000c00000, + 0x6000c00000000, + 0x9000000000000, + 0x18003000000000, + 0x30000000030000, + 0x40000040000000, + 0xc0000600000000, + 0x102000000000000, + 0x200004000000000, + 0x600003000000000, + 0xc00000000000000, + 0x1800300000000000, + 0x3000000000000030, + 0x6000000000000000, + 0x800000000000000d +#endif + }; unsigned long lsb = prev & 1; prev >>= 1; -#if 0 - if (lsb == 1) - prev ^= lfsr_tap; -#else - prev ^= (-lsb) & lfsr_tap; -#endif + prev ^= (-lsb) & lfsr_taps[bits]; return prev; } - -static inline unsigned long mylfsr(unsigned long bits, unsigned long prev) -{ - return __mylfsr(lfsr_taps[bits], prev); -} - -unsigned long mylfsr(unsigned long bits, unsigned long prev); diff --git a/microwatt/Makefile b/microwatt/Makefile index 7989b1d..203dc21 100644 --- a/microwatt/Makefile +++ b/microwatt/Makefile @@ -1,17 +1,27 @@ ARCH = $(shell uname -m) ifneq ("$(ARCH)", "ppc64") ifneq ("$(ARCH)", "ppc64le") - CROSS_COMPILE ?= powerpc64le-linux- + CROSS_COMPILE ?= powerpc64le-linux-gnu- + COPTS ?= -mno-vsx -mno-altivec endif endif +MICROWATT = ../.. + +CDEFS= + +# Uncomment the next line to include vector/VSX instructions +CDEFS += -DVECTOR_INSNS=true + CC = $(CROSS_COMPILE)gcc LD = $(CROSS_COMPILE)ld OBJCOPY = $(CROSS_COMPILE)objcopy GIT_VERSION := "$(shell git describe --dirty --always --tags)" -CFLAGS = -DVERSION=\"$(GIT_VERSION)\" -Os -g -Wall -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -mtraceback=no -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -Ilibc/include -I../ -I../microrl +#CFLAGS_TARGET = -mbig-endian -m32 + +CFLAGS = $(CDEFS) -DVERSION=\"$(GIT_VERSION)\" -Os -g -Wall $(CFLAGS_TARGET) -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mtraceback=no -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -Ilibc/include -I../ -I../microrl -I$(MICROWATT)/include -D__USE_LIBC ASFLAGS = $(CFLAGS) LDFLAGS = -N -T powerpc.lds --gc-sections @@ -29,9 +39,6 @@ libc.o: libc_objdir $(LIBC_OBJ) simple_random.o: ../simple_random.c ../generate.h ../backend.h ../jenkins.h ../microrl/microrl.h ../mystdio.h $(CC) $(CFLAGS) -c $< -lfsr.o: ../lfsr.c - $(CC) $(CFLAGS) -c $< - generate.o: ../generate.c ../generate.h ../lfsr.h ../helpers.h $(CC) $(CFLAGS) -c $< @@ -44,7 +51,10 @@ mystdio.o: ../mystdio.c ../mystdio.h microrl.o: ../microrl/microrl.c ../microrl/config.h ../microrl/microrl.h $(CC) $(CFLAGS) -c $< -simple_random.elf: simple_random.o lfsr.o generate.o head.o libc.o uart.o backend_microwatt.o helpers.o microrl.o mystdio.o +console.o: $(MICROWATT)/lib/console.c + $(CC) $(CFLAGS) -c $< + +simple_random.elf: simple_random.o generate.o head.o libc.o console.o backend_microwatt.o helpers.o microrl.o mystdio.o $(LD) $(LDFLAGS) -o $@ $^ simple_random.bin: simple_random.elf diff --git a/microwatt/backend_microwatt.c b/microwatt/backend_microwatt.c index 3ce1322..486585b 100644 --- a/microwatt/backend_microwatt.c +++ b/microwatt/backend_microwatt.c @@ -1,11 +1,16 @@ #include #include +#include #include "backend.h" -#include "uart.h" +#include "console.h" + +#define MSR_VEC (1ul << 25) +#define MSR_VSX (1ul << 23) +#define MSR_FP 0x2000 void init_console(void) { - potato_uart_init(); + console_init(); } void *init_testcase(unsigned long max_insns) @@ -25,6 +30,11 @@ long execute_testcase(void *insns, void *gprs, void *mem_ptr) testfunc func; long tb_start, tb_end; int dummy; + unsigned long msr; + + __asm__ volatile("mfmsr %0" : "=r" (msr)); + msr |= MSR_VSX | MSR_VEC | MSR_FP; + __asm__ volatile("mtmsrd %0" : : "r" (msr)); memset(mem_ptr, 0, MEM_SIZE); func = (testfunc)insns; @@ -34,3 +44,13 @@ long execute_testcase(void *insns, void *gprs, void *mem_ptr) asm volatile("mfspr %0,268" : "=r" (tb_end)); return tb_end - tb_start; } + +int getchar_unbuffered(void) +{ + return getchar(); +} + +void putchar_unbuffered(const char c) +{ + putchar(c); +} diff --git a/microwatt/head.S b/microwatt/head.S index fe81e3e..4635930 100644 --- a/microwatt/head.S +++ b/microwatt/head.S @@ -29,6 +29,7 @@ .long 0x2402004c; /* hrfid */ \ 191: + .machine "power10" /* Load an immediate 64-bit value into a register */ #define LOAD_IMM64(r, e) \ @@ -48,13 +49,35 @@ _start: .global boot_entry boot_entry: - /* setup stack */ - LOAD_IMM64(%r1, STACK_TOP - 0x100) + /* disable interrupts and FE0/1 */ + mfmsr %r0 + li %r3,0 + ori %r3,%r3,0x8900 + andc %r0,%r0,%r3 + mtmsrd %r0 - /* clear BSS */ LOAD_IMM64(%r10, __bss_start) LOAD_IMM64(%r11, __bss_end) + /* see if we are loaded at 0, if not copy ourselves to 0 */ + lnia %r3 + addi %r3,%r3,_start-. + cmpdi %r3,0 + beq 2f + /* XXX we assume the copy doesn't overlap... */ + li %r4,0 + addi %r0,%r10,7 + srdi %r0,%r0,3 + mtctr %r0 +3: ldx %r0,%r4,%r3 + std %r0,0(%r4) + addi %r4,%r4,8 + bdnz 3b +2: + /* setup stack */ + LOAD_IMM64(%r1, STACK_TOP - 0x100) + + /* clear BSS */ subf %r11,%r10,%r11 mtctr %r11 diff --git a/microwatt/uart.c b/microwatt/uart.c deleted file mode 100644 index b3c6415..0000000 --- a/microwatt/uart.c +++ /dev/null @@ -1,119 +0,0 @@ -#include -#include -#include -#include - -/* - * Core UART functions to implement for a port - */ - -static uint64_t potato_uart_base; - -#define PROC_FREQ 100000000 -#define UART_FREQ 115200 -#define UART_BASE 0xc0002000 - -#define POTATO_CONSOLE_TX 0x00 -#define POTATO_CONSOLE_RX 0x08 -#define POTATO_CONSOLE_STATUS 0x10 -#define POTATO_CONSOLE_STATUS_RX_EMPTY 0x01 -#define POTATO_CONSOLE_STATUS_TX_EMPTY 0x02 -#define POTATO_CONSOLE_STATUS_RX_FULL 0x04 -#define POTATO_CONSOLE_STATUS_TX_FULL 0x08 -#define POTATO_CONSOLE_CLOCK_DIV 0x18 -#define POTATO_CONSOLE_IRQ_EN 0x20 - -static uint64_t potato_uart_reg_read(int offset) -{ - uint64_t addr; - uint64_t val; - - addr = potato_uart_base + offset; - - val = *(volatile uint64_t *)addr; - - return val; -} - -static void potato_uart_reg_write(int offset, uint64_t val) -{ - uint64_t addr; - - addr = potato_uart_base + offset; - - *(volatile uint64_t *)addr = val; -} - -static int potato_uart_rx_empty(void) -{ - uint64_t val; - - val = potato_uart_reg_read(POTATO_CONSOLE_STATUS); - - if (val & POTATO_CONSOLE_STATUS_RX_EMPTY) - return 1; - - return 0; -} - -static int potato_uart_tx_full(void) -{ - uint64_t val; - - val = potato_uart_reg_read(POTATO_CONSOLE_STATUS); - - if (val & POTATO_CONSOLE_STATUS_TX_FULL) - return 1; - - return 0; -} - -static char potato_uart_read(void) -{ - uint64_t val; - - val = potato_uart_reg_read(POTATO_CONSOLE_RX); - - return (char)(val & 0x000000ff); -} - -static void potato_uart_write(char c) -{ - uint64_t val; - - val = c; - - potato_uart_reg_write(POTATO_CONSOLE_TX, val); -} - -static unsigned long potato_uart_divisor(unsigned long proc_freq, - unsigned long uart_freq) -{ - return proc_freq / (uart_freq * 16) - 1; -} - -void potato_uart_init(void) -{ - potato_uart_base = UART_BASE; - - potato_uart_reg_write(POTATO_CONSOLE_CLOCK_DIV, - potato_uart_divisor(PROC_FREQ, UART_FREQ)); -} - -int getchar_unbuffered(void) -{ - while (potato_uart_rx_empty()) - /* Do nothing */ ; - - return potato_uart_read(); -} - -int putchar_unbuffered(int c) -{ - while (potato_uart_tx_full()) - /* Do Nothing */; - - potato_uart_write(c); - - return c; -} diff --git a/microwatt/uart.h b/microwatt/uart.h deleted file mode 100644 index cbd6870..0000000 --- a/microwatt/uart.h +++ /dev/null @@ -1,3 +0,0 @@ -void potato_uart_init(void); -char getchar_unbuffered(void); -void putchar_unbuffered(const char c); diff --git a/mystdio.c b/mystdio.c index b397428..c29d2f9 100644 --- a/mystdio.c +++ b/mystdio.c @@ -1,11 +1,11 @@ #include #include #include "backend.h" -#include "stdio.h" +#include "mystdio.h" -void puthex(uint64_t n) +void puthexn(uint64_t n, int ndigits) { - for (long i = 15; i >= 0; i--) { + for (long i = ndigits - 1; i >= 0; i--) { uint8_t x = (n >> (i*4)) & 0xf; if (x > 9) @@ -15,6 +15,11 @@ void puthex(uint64_t n) } } +void puthex(uint64_t n) +{ + puthexn(n, 16); +} + void putlong(uint64_t n) { char str[32]; diff --git a/mystdio.h b/mystdio.h index 647cf04..7e8c7ef 100644 --- a/mystdio.h +++ b/mystdio.h @@ -1,5 +1,6 @@ #include void puthex(uint64_t n); +void puthexn(uint64_t n, int ndigits); void putlong(uint64_t n); void print(const char *str); diff --git a/posix/Makefile b/posix/Makefile index 79935f6..ce34e6c 100644 --- a/posix/Makefile +++ b/posix/Makefile @@ -1,16 +1,24 @@ ARCH = $(shell uname -m) +ifneq ("$(ARCH)", "ppc") ifneq ("$(ARCH)", "ppc64") ifneq ("$(ARCH)", "ppc64le") CROSS_COMPILE ?= powerpc64le-linux- + COPTS ?= -mno-vsx -mno-altivec endif endif +endif + +CDEFS= + +# Uncomment the next line to include vector/VSX instructions +CDEFS += -DVECTOR_INSNS=true CC = $(CROSS_COMPILE)gcc LD = $(CROSS_COMPILE)ld GIT_VERSION := "$(shell git describe --dirty --always --tags)" -CFLAGS = -DVERSION=\"$(GIT_VERSION)\" -O2 -g -Wall -I../ -I../microrl +CFLAGS = $(CDEFS) -DVERSION=\"$(GIT_VERSION)\" -O2 -g -Wall -I../ -I../microrl $(COPTS) ASFLAGS = $(CFLAGS) all: simple_random @@ -18,9 +26,6 @@ all: simple_random simple_random.o: ../simple_random.c ../generate.h ../backend.h ../jenkins.h ../microrl/microrl.h ../mystdio.h $(CC) $(CFLAGS) -c $< -lfsr.o: ../lfsr.c - $(CC) $(CFLAGS) -c $< - generate.o: ../generate.c ../generate.h ../lfsr.h ../helpers.h $(CC) $(CFLAGS) -c $< @@ -35,7 +40,7 @@ microrl.o: ../microrl/microrl.c ../microrl/config.h ../microrl/microrl.h backend_posix.o: backend_posix.c ../backend.h -simple_random: simple_random.o lfsr.o generate.o backend_posix.o helpers.o microrl.o mystdio.o +simple_random: simple_random.o generate.o backend_posix.o helpers.o microrl.o mystdio.o $(CC) $(LDFLAGS) -o $@ $^ clean: diff --git a/posix/backend_posix.c b/posix/backend_posix.c index 5eac886..e02c88c 100644 --- a/posix/backend_posix.c +++ b/posix/backend_posix.c @@ -114,11 +114,12 @@ void putchar_unbuffered(const char c) putchar(c); } -char getchar_unbuffered(void) +int getchar_unbuffered(void) { struct termios oldt, newt; int ch; + fflush(stdout); tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); diff --git a/simple_random.c b/simple_random.c index b797365..acc14f1 100644 --- a/simple_random.c +++ b/simple_random.c @@ -33,9 +33,10 @@ static enum { JENKINS, XOR } hash_type = JENKINS; static void *insns_ptr; static void *mem_ptr; -static const char *extra_names[4] = { "CR", "LR", "CTR", "XER" }; +static const char *extra_names[6] = { "CR", "LR", "CTR", "XER", "FPSCR", "VSCR" }; -static long run_one_test(unsigned long seed, unsigned long nr_insns) +static long run_one_test(unsigned long seed, unsigned long nr_insns, + unsigned long *lenp) { unsigned long gprs[NGPRS]; long tb_diff; @@ -46,7 +47,7 @@ static long run_one_test(unsigned long seed, unsigned long nr_insns) } generate_testcase(insns_ptr, mem_ptr+MEM_SIZE/2, gprs, seed, nr_insns, - insns, false); + insns, false, lenp); tb_diff = execute_testcase(insns_ptr, gprs, mem_ptr); /* GPR 31 was our scratch space, clear it */ @@ -54,13 +55,28 @@ static long run_one_test(unsigned long seed, unsigned long nr_insns) if (registers) { for (unsigned long i = 0; i < NGPRS; i++) { - if (i < 32) - putlong(i); - else - print(extra_names[i-32]); - print(" "); - if (i != 31) + if (i < 38) { + if (i < 32) + putlong(i); + else + print(extra_names[i-32]); + print(" "); + if (i != 31) + puthex(gprs[i]); + } else { + if (i < 102) { + print("F"); + putlong((i - 38) >> 1); + } else { + print("V"); + putlong((i - 102) >> 1); + } + print(" "); + puthex(gprs[i+1]); + print(" "); puthex(gprs[i]); + ++i; + } print("\r\n"); } print("Memory @ "); @@ -76,18 +92,21 @@ static long run_one_test(unsigned long seed, unsigned long nr_insns) print("\r\n\r\n"); } else { uint64_t hash = 0; + int ndig = 8; if (hash_type == XOR) { for (unsigned long i = 0; i < NGPRS; i++) hash ^= gprs[i]; + ndig = 2 * sizeof(unsigned long); } else { hash = jhash2((uint32_t *)gprs, sizeof(gprs)/sizeof(uint32_t), 0); + hash = jhash2(mem_ptr, MEM_SIZE / sizeof(uint32_t), hash); } putlong(seed); print(" "); - puthex(hash); + puthexn(hash, ndig); print("\r\n"); } @@ -98,13 +117,16 @@ static void run_many_tests(unsigned long seed, unsigned long nr_insns, unsigned long nr_tests) { long tb_ticks = 0; + unsigned long total_bytes = 0; for (unsigned long i = 0; i < nr_tests; i++) { - tb_ticks += run_one_test(seed, nr_insns); + tb_ticks += run_one_test(seed, nr_insns, &total_bytes); seed++; } print("timebase delta = "); putlong(tb_ticks); + print(", # instructions = "); + putlong(total_bytes / 4); print("\r\n"); } @@ -131,7 +153,7 @@ static void non_interactive(char *filename, unsigned long seed, return; } - end = generate_testcase(insns_ptr, mem_ptr+MEM_SIZE/2, gprs,seed, nr_insns, insns, true); + end = generate_testcase(insns_ptr, mem_ptr+MEM_SIZE/2, gprs,seed, nr_insns, insns, true, NULL); sprintf(name, "%s.bin", filename); @@ -152,7 +174,7 @@ static void non_interactive(char *filename, unsigned long seed, close(fd); generate_testcase(insns_ptr, mem_ptr+MEM_SIZE/2, gprs, seed, nr_insns, - insns, false); + insns, false, NULL); execute_testcase(insns_ptr, gprs, mem_ptr); /* GPR 31 was our scratch space, clear it */ @@ -396,7 +418,7 @@ static int execute(microrl_t *pThis, int argc, const char *const *argv) seed = __atoi(argv[1], 10); nr_insns = __atoi(argv[2], 10); - run_one_test(seed, nr_insns); + run_one_test(seed, nr_insns, NULL); } else if (!strcmp(argv[0], _CMD_TEST_MANY)) { unsigned long seed; @@ -454,21 +476,23 @@ int main(int argc, char *argv[]) { init_console(); - microrl_init(prl, microrl_print); - microrl_set_execute_callback(prl, execute); -#ifdef _USE_COMPLETE - microrl_set_complete_callback (prl, microrl_complete); -#endif - microrl_set_sigint_callback(prl, sigint); - insns_ptr = init_testcase(MAX_INSNS + SLACK); mem_ptr = init_memory(); #if __STDC_HOSTED__ == 1 - if (argc == 4) { - char *filename = argv[1]; - unsigned long seed = strtoul(argv[2], NULL, 10); - unsigned long nr_insns = strtoul(argv[3], NULL, 10); + if (argc == 4 || argc == 3) { + unsigned long seed = strtoul(argv[1], NULL, 10); + unsigned long nr_insns = strtoul(argv[2], NULL, 10); + unsigned long nr_tests = argc > 3? strtoul(argv[3], NULL, 10): 1; + + run_many_tests(seed, nr_insns, nr_tests); + exit(0); + } + + if (argc == 5 && argv[1][0] == '-') { + char *filename = argv[2]; + unsigned long seed = strtoul(argv[3], NULL, 10); + unsigned long nr_insns = strtoul(argv[4], NULL, 10); non_interactive(filename, seed, nr_insns); @@ -476,9 +500,19 @@ int main(int argc, char *argv[]) } #endif - while (1) - microrl_insert_char(prl, getchar_unbuffered()); + microrl_init(prl, microrl_print); + microrl_set_execute_callback(prl, execute); +#ifdef _USE_COMPLETE + microrl_set_complete_callback (prl, microrl_complete); +#endif + microrl_set_sigint_callback(prl, sigint); + while (1) { + int ch = getchar_unbuffered(); + if (ch == -1) + break; + microrl_insert_char(prl, ch); + } //free_testcase(ptr); return 0; diff --git a/sr_bisect b/sr_bisect new file mode 100755 index 0000000..791700b --- /dev/null +++ b/sr_bisect @@ -0,0 +1,266 @@ +#!/usr/bin/expect + +proc starttest {seed n sid} { + global spawn_id + set spawn_id $sid + send "test $seed $n\r" +} + +proc reaptest {seed sid} { + global spawn_id + set spawn_id $sid + expect -re {test.*\n([0-9]+) ([0-9a-f]+)\r} + set s $expect_out(1,string) + set h $expect_out(2,string) + if {$s != $seed} { + puts -error "oops, didn't expect '$expect_out(0,string)'" + exit + } + return $h +} + +proc test {seed n sid} { + starttest $seed $n $sid + return [reaptest $seed $sid] +} + +proc testri {seed n sid regs {insns {}}} { + global spawn_id + global $regs + global sprs do_vector + + set spawn_id $sid + if {$insns ne {}} { + global $insns + expect "microwatt >" + send "set insns 1\r" + expect "set insns 1" + } + expect "microwatt >" + send "set registers 1\r" + expect "set registers 1" + expect "microwatt >" + send "test $seed $n\r" + expect "test $seed $n" + if {$insns ne {} && $n > 0} { + expect "test $seed $n" exp_continue -re {[0-9a-z_,@ ]+\r} + set $insns [list [string trim $expect_out(0,string)]] + for {set i 1} {$i < $n} {incr i} { + expect -re {[0-9a-z_,@ ]+\r} + lappend $insns [string trim $expect_out(0,string)] + } + } + # cope with the test command coming back again + expect "test $seed $n" exp_continue -re {0 ([0-9a-f]+)} + set v $expect_out(1,string) + set ${regs}(0) $v + for {set i 1} {$i < 31} {incr i} { + expect -re "$i (\[0-9a-f]+)\r" + set v $expect_out(1,string) + set ${regs}($i) $v + } + expect "31" + foreach i $sprs { + expect -re "$i (\[0-9a-f]+)\r" + set v $expect_out(1,string) + set ${regs}($i) $v + } + if {$do_vector} { + for {set i 0} {$i < 32} {incr i} { + expect -re "F$i (\[0-9a-f]+ \[0-9a-f]+)\r" + set v $expect_out(1,string) + set ${regs}(F$i) $v + } + for {set i 0} {$i < 32} {incr i} { + expect -re "V$i (\[0-9a-f]+ \[0-9a-f]+)\r" + set v $expect_out(1,string) + set ${regs}(V$i) $v + } + } + expect -re {Memory @ ([0-9a-f]+)} + set mem {} + for {set i 0} {$i < 32} {incr i} { + expect -re {([0-9a-f]+) ([0-9a-f]+) ([0-9a-f]+) ([0-9a-f]+)\r} + lappend mem $expect_out(1,string) + lappend mem $expect_out(2,string) + lappend mem $expect_out(3,string) + lappend mem $expect_out(4,string) + } + set ${regs}(mem) $mem + if {$insns ne {}} { + expect "microwatt >" + send "set insns 0\r" + expect "set insns 0" + } + if {$regs ne {}} { + expect "microwatt >" + send "set registers 0\r" + expect "set registers 0" + } +} + +proc do_bisect {sr1 sr2 seed insns} { + set lo 0 + set hi $insns + while {$hi > $lo + 1} { + set mid [expr {($lo + $hi) / 2}] + puts "Testing $mid" + set h1 [test $seed $mid $sr1] + set h2 [test $seed $mid $sr2] + if {$h1 eq $h2} { + set lo $mid + } else { + set hi $mid + } + } + return $hi +} + +proc opencmddev {cmd} { + if {[string match "/dev/*" $cmd]} { + puts "Opening $cmd" + if {[catch { + set sp [open $cmd r+] + } err]} { + puts stderr "Couldn't open device $cmd: $err" + exit 1 + } + fconfigure $sp -mode 115200,n,8,1 + stty raw -echo < $cmd + spawn -open $sp + set id $spawn_id + send "\r" + expect "microwatt >" + send "set insns 0\r" + expect -re {set.*\n} + expect "microwatt >" + send "set registers 0\r" + expect -re {set.*\n} + } else { + eval spawn $cmd + set id $spawn_id + expect "microwatt >" + } + puts "" + send "\r" + return $id +} + +set seed_min 0 +set count 1000 +set insns 8000 + +set sprs {CR LR CTR XER} +set do_vector false + +proc usage {} { + puts stderr "Usage: sr_bisect \[-s seed\] \[-c count\] \[-n insns\] cmd/dev1 cmd/dev2" + exit 1 +} + +set cmd1 {} +set cmd2 {} +for {set i 0} {$i < [llength $argv]} {incr i} { + set arg [lindex $argv $i] + if {[string index $arg 0] eq "-"} { + switch $arg { + "-s" - + "--seed" { + if {[incr i] >= [llength $argv]} usage + set seed_min [lindex $argv $i] + } + "-c" - + "--count" { + if {[incr i] >= [llength $argv]} usage + set count [lindex $argv $i] + } + "-n" - + "--insns" { + if {[incr i] >= [llength $argv]} usage + set insns [lindex $argv $i] + } + "-v" - + "--vector" { + if {[incr i] >= [llength $argv]} usage + set do_vector [lindex $argv $i] + } + default { + usage + } + } + } elseif {$arg ne {}} { + if {$cmd1 eq {}} { + set cmd1 $arg + } elseif {$cmd2 eq {}} { + set cmd2 $arg + } else { + usage + } + } else { + usage + } +} + +if {$cmd1 eq {} || $cmd2 eq {}} usage + +if {$do_vector} { + lappend sprs FPSCR VSCR +} + +set rnames {} +for {set r 0} {$r < 31} {incr r} { + lappend rnames $r +} +set rnames [concat $rnames $sprs] +if {$do_vector} { + for {set r 0} {$r < 31} {incr r} { + lappend rnames F$r + } + for {set r 0} {$r < 31} {incr r} { + lappend rnames V$r + } +} + +set sr1 [opencmddev $cmd1] +set sr2 [opencmddev $cmd2] + +log_user 0 + +set ok true +for {set seed $seed_min} {$seed < $seed_min + $count} {incr seed} { + puts "seed=$seed" + starttest $seed $insns $sr1 + starttest $seed $insns $sr2 + set h1 [reaptest $seed $sr1] + set h2 [reaptest $seed $sr2] + if {$h1 ne $h2} { + set ok false + break + } +} + +if {!$ok} { + puts "Seed $seed different; bisecting ($h1 vs $h2)" + set hi [do_bisect $sr1 $sr2 $seed $insns] + puts "Differ at $hi" + testri $seed $hi $sr1 ssh_regs instrs + testri $seed $hi $sr2 tty_regs + foreach r $rnames { + puts -nonewline "$r $ssh_regs($r) $tty_regs($r)" + if {$ssh_regs($r) ne $tty_regs($r)} { + puts -nonewline " ****" + } + puts "" + } + if {$ssh_regs(mem) ne $tty_regs(mem)} { + puts "Memory differs" + } + set i [expr {[llength $instrs] - 10}] + if {$i < 0} {set i 0} + set n [expr {[llength $instrs] - $i}] + puts "Last $n instrs:" + while {$i < [llength $instrs]} { + puts [lindex $instrs $i] + incr i + } +}