From: dtrg Date: Fri, 2 Nov 2007 18:56:58 +0000 (+0000) Subject: Archival checkin (semi-working code). X-Git-Tag: release-6-0-pre-4~9 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=4dd1ff6d808d0a94e6bfd96bb64eeefc11d82d70;p=ack.git Archival checkin (semi-working code). --- 4dd1ff6d808d0a94e6bfd96bb64eeefc11d82d70 diff --cc mach/powerpc/as/.distr index 000000000,000000000..8ebe3797c new file mode 100644 --- /dev/null +++ b/mach/powerpc/as/.distr @@@ -1,0 -1,0 +1,6 @@@ ++mach0.c ++mach1.c ++mach2.c ++mach3.c ++mach4.c ++mach5.c diff --cc mach/powerpc/as/mach0.c index 000000000,000000000..3a42f1dd8 new file mode 100644 --- /dev/null +++ b/mach/powerpc/as/mach0.c @@@ -1,0 -1,0 +1,31 @@@ ++/* ++ * $Source$ ++ * $State$ ++ */ ++ ++#define THREE_PASS /* branch and offset optimization */ ++#define BYTES_REVERSED /* high order byte has lowest address */ ++#define WORDS_REVERSED /* high order word has lowest address */ ++#define LISTING /* enable listing facilities */ ++#define RELOCATION /* generate relocatable code */ ++#define DEBUG 0 ++ ++#undef valu_t ++#define valu_t long ++ ++#undef ADDR_T ++#define ADDR_T long ++ ++#undef word_t ++#define word_t long ++ ++#undef ALIGNWORD ++#define ALIGNWORD 4 ++ ++#undef ALIGNSECT ++#define ALIGNSECT 4 ++ ++#undef VALWIDTH ++#define VALWIDTH 8 ++ ++#define FIXUPFLAGS (RELBR | RELWR) diff --cc mach/powerpc/as/mach1.c index 000000000,000000000..998cd8d9c new file mode 100644 --- /dev/null +++ b/mach/powerpc/as/mach1.c @@@ -1,0 -1,0 +1,5 @@@ ++/* ++ * $Source$ ++ * $State$ ++ */ ++ diff --cc mach/powerpc/as/mach2.c index 000000000,000000000..43ea8d757 new file mode 100644 --- /dev/null +++ b/mach/powerpc/as/mach2.c @@@ -1,0 -1,0 +1,89 @@@ ++/* ++ * $Source$ ++ * $State$ ++ */ ++ ++%token GPR ++%token SPR ++%token FPR ++%token CR ++%token C ++ ++%token OP ++%token OP_BF ++%token OP_BF_BFA ++%token OP_BF_FRA_FRB ++%token OP_BF_L_RA_RB ++%token OP_BF_L_RA_SI ++%token OP_BF_L_RA_UI ++%token OP_BF_U_C ++%token OP_BO_BI_BDA ++%token OP_BO_BI_BDL ++%token OP_BO_BI_BH ++%token OP_BT_C ++%token OP_BT_BA_BB ++%token OP_FLM_FRB_C ++%token OP_FRS_RA_D ++%token OP_FRS_RA_RB ++%token OP_FRT_C ++%token OP_FRT_FRA_FRB_C ++%token OP_FRT_FRA_FRC_FRB_C ++%token OP_FRT_FRA_FRC_C ++%token OP_FRT_FRB_C ++%token OP_FRT_RA_D ++%token OP_FRT_RA_RB ++%token OP_L ++%token OP_LEV ++%token OP_LIA ++%token OP_LIL ++%token OP_L_RB ++%token OP_RA_RB ++%token OP_RB ++%token OP_RS ++%token OP_RS_FXM ++%token OP_RS_L ++%token OP_RS_RA ++%token OP_RS_RA_C ++%token OP_RS_RA_D ++%token OP_RS_RA_DS ++%token OP_RS_RA_NB ++%token OP_RS_RA_RB ++%token OP_RS_RA_RB_C ++%token OP_RS_RA_RB_MB5_ME5_C ++%token OP_RS_RA_RB_MB6_C ++%token OP_RS_RA_RB_ME6_C ++%token OP_RS_RA_SH_MB5_ME5_C ++%token OP_RS_RA_SH_MB6_SH_C ++%token OP_RS_RA_SH_ME6_SH_C ++%token OP_RS_RA_SH5_C ++%token OP_RS_RA_SH6_C ++%token OP_RS_RA_UI ++%token OP_RS_RA_UI_CC ++%token OP_RS_RB ++%token OP_RS_SPR ++%token OP_RS_SR ++%token OP_RT ++%token OP_RT_FXM ++%token OP_RT_RA_C ++%token OP_RT_RA_D ++%token OP_RT_RA_DS ++%token OP_RT_RA_NB ++%token OP_RT_RA_RB ++%token OP_RT_RA_RB_C ++%token OP_RT_RA_SI ++%token OP_RT_RA_SI_addic ++%token OP_RT_RB ++%token OP_RT_SPR ++%token OP_RT_SR ++%token OP_RT_TBR ++%token OP_TH_RA_RB ++%token OP_TO_RA_RB ++%token OP_TO_RA_SI ++ ++%token OP_la ++ ++/* Other token types */ ++ ++%type c ++%type e16 u8 u7 u6 u5 u4 u2 u1 ++%type nb ds bda bdl lia lil diff --cc mach/powerpc/as/mach3.c index 000000000,000000000..d7f5161dd new file mode 100644 --- /dev/null +++ b/mach/powerpc/as/mach3.c @@@ -1,0 -1,0 +1,358 @@@ ++/* ++ * $Source$ ++ * $State$ ++ */ ++ ++/* Integer registers */ ++ ++0, GPR, 0, "r0", ++0, GPR, 1, "r1", ++0, GPR, 1, "sp", ++0, GPR, 2, "r2", ++0, GPR, 2, "fp", ++0, GPR, 3, "r3", ++0, GPR, 4, "r4", ++0, GPR, 5, "r5", ++0, GPR, 6, "r6", ++0, GPR, 7, "r7", ++0, GPR, 8, "r8", ++0, GPR, 9, "r9", ++0, GPR, 10, "r10", ++0, GPR, 11, "r11", ++0, GPR, 12, "r12", ++0, GPR, 13, "r13", ++0, GPR, 14, "r14", ++0, GPR, 15, "r15", ++0, GPR, 16, "r16", ++0, GPR, 17, "r17", ++0, GPR, 18, "r18", ++0, GPR, 19, "r19", ++0, GPR, 20, "r20", ++0, GPR, 21, "r21", ++0, GPR, 22, "r22", ++0, GPR, 23, "r23", ++0, GPR, 24, "r24", ++0, GPR, 25, "r25", ++0, GPR, 26, "r26", ++0, GPR, 27, "r27", ++0, GPR, 28, "r28", ++0, GPR, 29, "r29", ++0, GPR, 30, "r30", ++0, GPR, 31, "r31", ++ ++/* Floating-point registers */ ++ ++0, FPR, 0, "f0", ++0, FPR, 1, "f1", ++0, FPR, 2, "f2", ++0, FPR, 3, "f3", ++0, FPR, 4, "f4", ++0, FPR, 5, "f5", ++0, FPR, 6, "f6", ++0, FPR, 7, "f7", ++0, FPR, 8, "f8", ++0, FPR, 9, "f9", ++0, FPR, 10, "f10", ++0, FPR, 11, "f11", ++0, FPR, 12, "f12", ++0, FPR, 13, "f13", ++0, FPR, 14, "f14", ++0, FPR, 15, "f15", ++0, FPR, 16, "f16", ++0, FPR, 17, "f17", ++0, FPR, 18, "f18", ++0, FPR, 19, "f19", ++0, FPR, 20, "f20", ++0, FPR, 21, "f21", ++0, FPR, 22, "f22", ++0, FPR, 23, "f23", ++0, FPR, 24, "f24", ++0, FPR, 25, "f25", ++0, FPR, 26, "f26", ++0, FPR, 27, "f27", ++0, FPR, 28, "f28", ++0, FPR, 29, "f29", ++0, FPR, 30, "f30", ++0, FPR, 31, "f31", ++ ++/* Special registers */ ++ ++0, SPR, 32, "xer", ++0, SPR, 256, "lr", ++0, SPR, 288, "ctr", ++ ++/* Condition registers */ ++ ++0, CR, 0, "cr0", ++0, CR, 1, "cr1", ++0, CR, 2, "cr2", ++0, CR, 3, "cr3", ++0, CR, 4, "cr4", ++0, CR, 5, "cr5", ++0, CR, 6, "cr6", ++0, CR, 7, "cr7", ++ ++/* Condition code flag */ ++ ++0, C, 0, ".", ++ ++/* Special instructions */ ++ ++0, OP_la, 0, "la", ++ ++/* Branch processor instructions (page 20) */ ++ ++0, OP_LIL, 18<<26 | 0<<1 | 0<<0, "b", ++0, OP_LIA, 18<<26 | 1<<1 | 0<<0, "ba", ++0, OP_LIL, 18<<26 | 0<<1 | 1<<0, "bl", ++0, OP_LIA, 18<<26 | 1<<1 | 1<<0, "bla", ++0, OP_BO_BI_BDL, 16<<26 | 0<<1 | 0<<0, "bc", ++0, OP_BO_BI_BDA, 16<<26 | 1<<1 | 0<<0, "bca", ++0, OP_BO_BI_BDL, 16<<26 | 0<<1 | 1<<0, "bcl", ++0, OP_BO_BI_BDA, 16<<26 | 1<<1 | 1<<0, "bcla", ++0, OP_BO_BI_BH, 19<<26 | 16<<1 | 0<<0, "bclr", ++0, OP_BO_BI_BH, 19<<26 | 16<<1 | 1<<0, "bclrl", ++0, OP_BO_BI_BH, 19<<26 | 528<<1 | 0<<0, "bcctr", ++0, OP_BO_BI_BH, 19<<26 | 528<<1 | 1<<0, "bcctrl", ++0, OP_LEV, 17<<26 | 1<<1, "sc", ++0, OP_BT_BA_BB, 19<<26 | 257<<1, "crand", ++0, OP_BT_BA_BB, 19<<26 | 449<<1, "cror", ++0, OP_BT_BA_BB, 19<<26 | 193<<1, "crxor", ++0, OP_BT_BA_BB, 19<<26 | 225<<1, "crnand", ++0, OP_BT_BA_BB, 19<<26 | 33<<1, "crnor", ++0, OP_BT_BA_BB, 19<<26 | 289<<1, "crneqv", ++0, OP_BT_BA_BB, 19<<26 | 129<<1, "crandc", ++0, OP_BT_BA_BB, 19<<26 | 417<<1, "crorc", ++0, OP_BF_BFA, 19<<26 | 0<<1, "mcrf", ++ ++/* Fixed point instructions (page 29) */ ++ ++0, OP_RT_RA_D, 34<<26, "lbz", ++0, OP_RT_RA_RB, 31<<26 | 87<<1, "lbzx", ++0, OP_RT_RA_D, 35<<26, "lbzu", ++0, OP_RT_RA_RB, 31<<26 | 119<<1, "lbzux", ++0, OP_RT_RA_D, 40<<26, "lhz", ++0, OP_RT_RA_RB, 31<<26 | 279<<1, "lhzx", ++0, OP_RT_RA_D, 41<<26, "lhzu", ++0, OP_RT_RA_RB, 31<<26 | 311<<1, "lhzux", ++0, OP_RT_RA_D, 42<<26, "lha", ++0, OP_RT_RA_RB, 31<<26 | 343<<1, "lhax", ++0, OP_RT_RA_D, 43<<26, "lhau", ++0, OP_RT_RA_RB, 31<<26 | 375<<1, "lhaux", ++0, OP_RT_RA_D, 32<<26, "lwz", ++0, OP_RT_RA_RB, 31<<26 | 23<<1, "lwzx", ++0, OP_RT_RA_D, 33<<26, "lwzu", ++0, OP_RT_RA_RB, 31<<26 | 55<<1, "lwzux", ++0, OP_RT_RA_DS, 58<<26 | 2<<0, "lwa", ++0, OP_RT_RA_RB, 31<<26 | 341<<1, "lwax", ++0, OP_RT_RA_RB, 31<<26 | 363<<1, "lwaux", ++0, OP_RT_RA_DS, 58<<26, "ld", ++0, OP_RT_RA_RB, 31<<26 | 21<<1, "ldx", ++0, OP_RT_RA_DS, 58<<26 | 1<<0, "ldu", ++0, OP_RT_RA_RB, 31<<26 | 53<<1, "ldux", ++ ++0, OP_RS_RA_D, 38<<26, "stb", ++0, OP_RS_RA_RB, 31<<26 | 215<<1, "stbx", ++0, OP_RS_RA_D, 39<<26, "stbu", ++0, OP_RS_RA_RB, 31<<26 | 247<<1, "stbux", ++0, OP_RS_RA_D, 44<<26, "sth", ++0, OP_RS_RA_RB, 31<<26 | 407<<1, "sthx", ++0, OP_RS_RA_D, 45<<26, "sthu", ++0, OP_RS_RA_RB, 31<<26 | 439<<1, "sthux", ++0, OP_RS_RA_D, 36<<26, "stw", ++0, OP_RS_RA_RB, 31<<26 | 151<<1, "stwx", ++0, OP_RS_RA_D, 37<<26, "stwu", ++0, OP_RS_RA_RB, 31<<26 | 183<<1, "stwux", ++0, OP_RS_RA_DS, 62<<26, "std", ++0, OP_RS_RA_RB, 31<<26 | 149<<1, "stdx", ++0, OP_RS_RA_DS, 62<<26 | 1<<0, "stdu", ++0, OP_RS_RA_RB, 31<<26 | 181<<1, "stdux", ++ ++/* page 42 */ ++0, OP_RT_RA_RB, 31<<26 | 790<<1, "lhbrx", ++0, OP_RT_RA_RB, 31<<26 | 534<<1, "lwbrx", ++0, OP_RS_RA_RB, 31<<26 | 918<<1, "sthbrx", ++0, OP_RS_RA_RB, 31<<26 | 662<<1, "stwbrx", ++ ++/* page 44 */ ++0, OP_RT_RA_D, 46<<26, "lmw", ++0, OP_RS_RA_D, 47<<26, "stmw", ++ ++/* page 45 */ ++0, OP_RT_RA_NB, 31<<26 | 597<<1, "lswi", ++0, OP_RT_RA_RB, 31<<26 | 533<<1, "lswx", ++0, OP_RS_RA_NB, 31<<26 | 725<<1, "stswi", ++0, OP_RS_RA_RB, 31<<26 | 661<<1, "stswx", ++ ++/* page 49 */ ++0, OP_RT_RA_SI, 14<<26, "addi", ++0, OP_RT_RA_SI, 15<<26, "addis", ++0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 266<<1, "add", ++0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 266<<1, "addo", ++0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 40<<1, "subf", ++0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 40<<1, "subfo", ++0, OP_RT_RA_SI_addic, 12<<26, "addic", /* special case C */ ++0, OP_RT_RA_SI, 8<<26, "subfic", ++0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 138<<1, "adde", ++0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 138<<1, "addeo", ++0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 136<<1, "subfe", ++0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 136<<1, "subfeo", ++0, OP_RT_RA_C, 31<<26 | 0<<10 | 234<<1, "addme", ++0, OP_RT_RA_C, 31<<26 | 1<<10 | 234<<1, "addmeo", ++0, OP_RT_RA_C, 31<<26 | 0<<10 | 232<<1, "subfme", ++0, OP_RT_RA_C, 31<<26 | 1<<10 | 232<<1, "subfmeo", ++0, OP_RT_RA_C, 31<<26 | 0<<10 | 202<<1, "addze", ++0, OP_RT_RA_C, 31<<26 | 1<<10 | 202<<1, "addzeo", ++0, OP_RT_RA_C, 31<<26 | 0<<10 | 200<<1, "subfze", ++0, OP_RT_RA_C, 31<<26 | 1<<10 | 200<<1, "subfzeo", ++0, OP_RT_RA_C, 31<<26 | 0<<10 | 104<<1, "neg", ++0, OP_RT_RA_C, 31<<26 | 1<<10 | 104<<1, "nego", ++ ++/* page 54 */ ++0, OP_RT_RA_SI, 7<<26, "mulli", ++0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 233<<1, "mulld", ++0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 233<<1, "mulldo", ++0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 235<<1, "mullw", ++0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 235<<1, "mullwo", ++0, OP_RT_RA_RB_C, 31<<26 | 73<<1, "mulhd", ++0, OP_RT_RA_RB_C, 31<<26 | 75<<1, "mulhw", ++0, OP_RT_RA_RB_C, 31<<26 | 9<<1, "mulhdu", ++0, OP_RT_RA_RB_C, 31<<26 | 11<<1, "mulhwu", ++ ++/* page 56 */ ++0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 489<<1, "divd", ++0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 489<<1, "divdo", ++0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 491<<1, "divw", ++0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 491<<1, "divwo", ++0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 457<<1, "divdu", ++0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 457<<1, "divduo", ++0, OP_RT_RA_RB_C, 31<<26 | 0<<10 | 459<<1, "divwu", ++0, OP_RT_RA_RB_C, 31<<26 | 1<<10 | 459<<1, "divwuo", ++ ++/* page 58 */ ++0, OP_BF_L_RA_SI, 11<<26, "cmpi", ++0, OP_BF_L_RA_RB, 31<<26 | 0<<1, "cmp", ++0, OP_BF_L_RA_UI, 10<<26, "cmpli", ++0, OP_BF_L_RA_RB, 31<<26 | 32<<1, "cmpl", ++ ++/* page 60 */ ++0, OP_TO_RA_SI, 2<<26, "tdi", ++0, OP_TO_RA_SI, 3<<26, "twi", ++0, OP_TO_RA_RB, 31<<26 | 68<<1, "td", ++0, OP_TO_RA_RB, 31<<26 | 4<<1, "tw", ++ ++/* page 62 */ ++0, OP_RS_RA_UI_CC, 28<<26, "andi", /* C compulsory */ ++0, OP_RS_RA_UI_CC, 29<<26, "andis", /* C compulsory */ ++0, OP_RS_RA_UI, 24<<26, "ori", ++0, OP_RS_RA_UI, 25<<26, "oris", ++0, OP_RS_RA_UI, 26<<26, "xori", ++0, OP_RS_RA_UI, 27<<26, "xoris", ++0, OP_RS_RA_RB_C, 31<<26 | 28<<1, "and", ++0, OP_RS_RA_RB_C, 31<<26 | 444<<1, "or", ++0, OP_RS_RA_RB_C, 31<<26 | 316<<1, "xor", ++0, OP_RS_RA_RB_C, 31<<26 | 476<<1, "nand", ++0, OP_RS_RA_RB_C, 31<<26 | 124<<1, "nor", ++0, OP_RS_RA_RB_C, 31<<26 | 284<<1, "eqv", ++0, OP_RS_RA_RB_C, 31<<26 | 60<<1, "andc", ++0, OP_RS_RA_RB_C, 31<<26 | 412<<1, "orc", ++0, OP_RS_RA_C, 31<<26 | 954<<1, "extsb", ++0, OP_RS_RA_C, 31<<26 | 922<<1, "extsh", ++0, OP_RS_RA_C, 31<<26 | 986<<1, "extsw", ++0, OP_RS_RA_C, 31<<26 | 58<<1, "cntlzd", ++0, OP_RS_RA_C, 31<<26 | 26<<1, "cntlzw", ++ ++/* page 69 */ ++0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 0<<2, "rldicl", ++0, OP_RS_RA_SH_ME6_SH_C, 30<<26 | 1<<2, "rldicr", ++0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 2<<2, "rldic", ++0, OP_RS_RA_SH_MB5_ME5_C, 21<<26, "rlwinm", ++0, OP_RS_RA_RB_MB6_C, 30<<26 | 8<<1, "rldcl", ++0, OP_RS_RA_RB_ME6_C, 30<<26 | 9<<1, "rldcr", ++0, OP_RS_RA_RB_MB5_ME5_C, 23<<26, "rlwnm", ++0, OP_RS_RA_SH_MB6_SH_C, 30<<26 | 3<<2, "rldimi", ++0, OP_RS_RA_SH_MB5_ME5_C, 20<<26, "rlwimi", ++ ++/* page 74 */ ++0, OP_RS_RA_RB_C, 31<<26 | 27<<1, "sld", ++0, OP_RS_RA_RB_C, 31<<26 | 24<<1, "slw", ++0, OP_RS_RA_RB_C, 31<<26 | 539<<1, "srd", ++0, OP_RS_RA_RB_C, 31<<26 | 536<<1, "srw", ++0, OP_RS_RA_SH6_C, 31<<26 | 413<<2, "sradi", ++0, OP_RS_RA_SH5_C, 31<<26 | 824<<1, "srawi", ++0, OP_RS_RA_RB_C, 31<<26 | 794<<1, "srad", ++0, OP_RS_RA_RB_C, 31<<26 | 792<<1, "sraw", ++ ++/* page 78 */ ++0, OP_RS_SPR, 31<<26 | 467<<1, "mtspr", ++0, OP_RT_SPR, 31<<26 | 339<<1, "mfspr", ++0, OP_RS_FXM, 31<<26 | 0<<21 | 144<<1, "mtcrf", ++0, OP_RT, 31<<26 | 0<<21 | 19<<1, "mfcr", ++ ++/* Floating point instructions (page 83) */ ++ ++0, OP_FRT_RA_D, 48<<26, "lfs", ++0, OP_FRT_RA_RB, 31<<26 | 535<<1, "lfsx", ++0, OP_FRT_RA_D, 49<<26, "lfsu", ++0, OP_FRT_RA_RB, 31<<26 | 567<<1, "lfsux", ++0, OP_FRT_RA_D, 50<<26, "lfd", ++0, OP_FRT_RA_RB, 31<<26 | 599<<1, "lfdx", ++0, OP_FRT_RA_D, 51<<26, "lfdu", ++0, OP_FRT_RA_RB, 31<<26 | 631<<1, "lfdux", ++0, OP_FRS_RA_D, 52<<26, "stfs", ++0, OP_FRS_RA_RB, 31<<26 | 663<<1, "stfsx", ++0, OP_FRS_RA_D, 53<<26, "stfsu", ++0, OP_FRS_RA_RB, 31<<26 | 695<<1, "stfsux", ++0, OP_FRS_RA_D, 54<<26, "stfd", ++0, OP_FRS_RA_RB, 31<<26 | 727<<1, "stfdx", ++0, OP_FRS_RA_D, 55<<26, "stfdu", ++0, OP_FRS_RA_RB, 31<<26 | 759<<1, "stfdux", ++0, OP_FRS_RA_RB, 31<<26 | 983<<1, "stfiwx", ++ ++0, OP_FRT_FRB_C, 63<<26 | 72<<1, "fmr", ++0, OP_FRT_FRB_C, 63<<26 | 40<<1, "fneg", ++0, OP_FRT_FRB_C, 63<<26 | 264<<1, "fabs", ++0, OP_FRT_FRB_C, 63<<26 | 136<<1, "fnabs", ++ ++0, OP_FRT_FRA_FRB_C, 63<<26 | 21<<1, "fadd", ++0, OP_FRT_FRA_FRB_C, 59<<26 | 21<<1, "fadds", ++0, OP_FRT_FRA_FRB_C, 63<<26 | 20<<1, "fsub", ++0, OP_FRT_FRA_FRB_C, 59<<26 | 20<<1, "fsubs", ++0, OP_FRT_FRA_FRC_C, 63<<26 | 25<<1, "fmul", ++0, OP_FRT_FRA_FRC_C, 59<<26 | 25<<1, "fmuls", ++0, OP_FRT_FRA_FRB_C, 63<<26 | 18<<1, "fdiv", ++0, OP_FRT_FRA_FRB_C, 59<<26 | 18<<1, "fdivs", ++ ++0, OP_FRT_FRA_FRC_FRB_C, 63<<26 | 29<<1, "fmadd", ++0, OP_FRT_FRA_FRC_FRB_C, 59<<26 | 29<<1, "fmadds", ++0, OP_FRT_FRA_FRC_FRB_C, 63<<26 | 28<<1, "fmsub", ++0, OP_FRT_FRA_FRC_FRB_C, 59<<26 | 28<<1, "fmsubs", ++0, OP_FRT_FRA_FRC_FRB_C, 63<<26 | 31<<1, "fnmadd", ++0, OP_FRT_FRA_FRC_FRB_C, 59<<26 | 31<<1, "fnmadds", ++0, OP_FRT_FRA_FRC_FRB_C, 63<<26 | 30<<1, "fnmsub", ++0, OP_FRT_FRA_FRC_FRB_C, 59<<26 | 30<<1, "fnmsubs", ++ ++0, OP_FRT_FRB_C, 63<<26 | 12<<1, "frsp", ++0, OP_FRT_FRB_C, 63<<26 | 814<<1, "fctid", ++0, OP_FRT_FRB_C, 63<<26 | 815<<1, "fctidz", ++0, OP_FRT_FRB_C, 63<<26 | 14<<1, "fctiw", ++0, OP_FRT_FRB_C, 63<<26 | 15<<1, "fctiwz", ++0, OP_FRT_FRB_C, 63<<26 | 846<<1, "fcfid", ++ ++0, OP_BF_FRA_FRB, 63<<26 | 0<<1, "fcmpu", ++0, OP_BF_FRA_FRB, 63<<26 | 32<<1, "fcmpo", ++ ++0, OP_FRT_C, 63<<26 | 583<<1, "mffs", ++0, OP_BF_BFA, 63<<26 | 64<<1, "mcrfs", ++0, OP_BF_U_C, 63<<26 | 134<<1, "mtfsfi", ++0, OP_FLM_FRB_C, 63<<26 | 711<<1, "mtfsf", ++0, OP_BT_C, 63<<26 | 70<<1, "mtfsb0", ++0, OP_BT_C, 63<<26 | 38<<1, "mtfsb1", ++ ++0, OP_FRT_FRB_C, 63<<26 | 22<<1, "fsqrt", ++0, OP_FRT_FRB_C, 59<<26 | 22<<1, "fsqrts", ++0, OP_FRT_FRB_C, 59<<26 | 24<<1, "fres", ++0, OP_FRT_FRB_C, 63<<26 | 26<<1, "frsqrte", ++0, OP_FRT_FRA_FRC_FRB_C, 63<<26 | 23<<1, "fsel", ++ ++/* page 98 */ diff --cc mach/powerpc/as/mach4.c index 000000000,000000000..b105aa2ae new file mode 100644 --- /dev/null +++ b/mach/powerpc/as/mach4.c @@@ -1,0 -1,0 +1,236 @@@ ++/* ++ * $Source$ ++ * $State$ ++ */ ++ ++operation ++ : OP_BF_BFA CR ',' CR { emit4($1 | ($2<<23) | ($4<<18)); } ++ | OP_BF_FRA_FRB CR ',' FPR ',' FPR { emit4($1 | ($2<<23) | ($4<<16) | ($6<<11)); } ++ | OP_BF_L_RA_RB CR ',' u1 ',' GPR ',' GPR { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | ($8<<11)); } ++ | OP_BF_L_RA_SI CR ',' u1 ',' GPR ',' e16 { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } ++ | OP_BF_L_RA_UI CR ',' u1 ',' GPR ',' e16 { emit4($1 | ($2<<23) | ($4<<21) | ($6<<16) | $8); } ++ | OP_BF_U_C c CR ',' u4 { emit4($1 | $2 | ($3<<23) | ($5<<12)); } ++ | OP_BO_BI_BDA u5 ',' u5 ',' bda { emit4($1 | ($2<<21) | ($4<<16) | $6); } ++ | OP_BO_BI_BDL u5 ',' u5 ',' bdl { emit4($1 | ($2<<21) | ($4<<16) | $6); } ++ | OP_BO_BI_BH u5 ',' u5 ',' u2 { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } ++ | OP_BT_BA_BB u5 ',' u5 ',' u5 { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } ++ | OP_BT_C c u5 { emit4($1 | $2 | ($3<<21)); } ++ | OP_FLM_FRB_C c u8 ',' FPR { emit4($1 | $2 | ($3<<17) | ($5<<11)); } ++ | OP_FRS_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } ++ | OP_FRS_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } ++ | OP_FRT_FRA_FRB_C c FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } ++ | OP_FRT_FRA_FRC_FRB_C c FPR ',' FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($9<<11) | ($7<<6)); } ++ | OP_FRT_FRA_FRC_C c FPR ',' FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<6)); } ++ | OP_FRT_FRB_C c FPR ',' FPR { emit4($1 | $2 | ($3<<21) | ($5<<11)); } ++ | OP_FRT_RA_D FPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } ++ | OP_FRT_RA_RB FPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } ++ | OP_FRT_C c FPR { emit4($1 | $2 | ($3<<21)); } ++ | OP_RT GPR { emit4($1 | ($2<<21)); } ++ | OP_RT_RA_C c GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16)); } ++ | OP_RT_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } ++ | OP_RT_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } ++ | OP_RT_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } ++ | OP_RT_RA_RB GPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } ++ | OP_RT_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($3<<21) | ($5<<16) | ($7<<11)); } ++ | OP_RT_RA_SI GPR ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } ++ | OP_RT_RA_SI_addic c GPR ',' GPR ',' e16 { emit4($1 | ($2<<26) | ($3<<21) | ($5<<16) | $7); } ++ | OP_RT_SPR GPR ',' SPR { emit4($1 | ($2<<21) | ($4<<11)); } ++ | OP_RS_FXM u7 ',' GPR { emit4($1 | ($4<<21) | ($2<<12)); } ++ | OP_RS_RA_C c GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16)); } ++ | OP_RS_RA_D GPR ',' e16 '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } ++ | OP_RS_RA_DS GPR ',' ds '(' GPR ')' { emit4($1 | ($2<<21) | ($6<<16) | $4); } ++ | OP_RS_RA_NB GPR ',' GPR ',' nb { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } ++ | OP_RS_RA_UI GPR ',' GPR ',' e16 { emit4($1 | ($4<<21) | ($2<<16) | $6); } ++ | OP_RS_RA_UI_CC C GPR ',' GPR ',' e16 { emit4($1 | ($5<<21) | ($3<<16) | $7); } ++ | OP_RS_RA_RB GPR ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } ++ | OP_RS_RA_RB_C c GPR ',' GPR ',' GPR { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } ++ | OP_RS_RA_RB_MB5_ME5_C c GPR ',' GPR ',' GPR ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } ++ | OP_RS_RA_RB_MB6_C c GPR ',' GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | (($9&0x1F)<<6) | (($9&0x20)>>0)); } ++ | OP_RS_RA_RB_ME6_C c GPR ',' GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | (($9&0x1F)<<6) | (($9&0x20)>>0)); } ++ | OP_RS_RA_SH_MB5_ME5_C c GPR ',' GPR ',' u5 ',' u5 ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11) | ($9<<6) | ($11<<1)); } ++ | OP_RS_RA_SH_MB6_SH_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | ($9<<6) | (($7&0x20)>>4)); } ++ | OP_RS_RA_SH_ME6_SH_C c GPR ',' GPR ',' u6 ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | ($9<<6) | (($7&0x20)>>4)); } ++ | OP_RS_RA_SH5_C c GPR ',' GPR ',' u5 { emit4($1 | $2 | ($5<<21) | ($3<<16) | ($7<<11)); } ++ | OP_RS_RA_SH6_C c GPR ',' GPR ',' u6 { emit4($1 | $2 | ($5<<21) | ($3<<16) | (($7&0x1F)<<11) | (($7&0x20)>>4)); } ++ | OP_RS_SPR SPR ',' GPR { emit4($1 | ($4<<21) | ($2<<11)); } ++ | OP_TO_RA_RB u5 ',' GPR ',' GPR { emit4($1 | ($2<<21) | ($4<<16) | ($6<<11)); } ++ | OP_TO_RA_SI u5 ',' GPR ',' e16 { emit4($1 | ($2<<21) | ($4<<16) | $6); } ++ | OP_LEV u7 { emit4($1 | ($2<<5)); } ++ | OP_LIA lia { emit4($1 | $2); } ++ | OP_LIL lil { emit4($1 | $2); } ++ ; ++ ++c ++ : /* nothing */ { $$ = 0; } ++ | C { $$ = 1; } ++ ; ++ ++e16 ++ : '<' expr ++ { ++ DOTVAL += 2; ++ newrelo($2.typ, RELOH2 | FIXUPFLAGS); ++ DOTVAL -= 2; ++ $$ = ($2.val >> 16) & 0xFFFF; ++ } ++ | '>' expr ++ { ++ DOTVAL += 2; ++ newrelo($2.typ, RELO2 | FIXUPFLAGS); ++ DOTVAL -= 2; ++ $$ = $2.val & 0xFFFF; ++ } ++ | expr ++ { ++ DOTVAL += 2; ++ newrelo($1.typ, RELO2 | FIXUPFLAGS); ++ DOTVAL -= 2; ++ $$ = $1.val & 0xFFFF; ++ } ++ ; ++ ++u8 ++ : absexp ++ { ++ if (($1 < 0) || ($1 > 0xFF)) ++ serror("8-bit unsigned value out of range"); ++ $$ = $1; ++ } ++ ; ++ ++u7 ++ : absexp ++ { ++ if (($1 < 0) || ($1 > 0x7F)) ++ serror("7-bit unsigned value out of range"); ++ $$ = $1; ++ } ++ ; ++ ++u6 ++ : absexp ++ { ++ if (($1 < 0) || ($1 > 0x3F)) ++ serror("6-bit unsigned value out of range"); ++ $$ = $1; ++ } ++ ; ++ ++u5 ++ : absexp ++ { ++ if (($1 < 0) || ($1 > 0x1F)) ++ serror("5-bit unsigned value out of range"); ++ $$ = $1; ++ } ++ ; ++ ++u4 ++ : absexp ++ { ++ if (($1 < 0) || ($1 > 0xF)) ++ serror("4-bit unsigned value out of range"); ++ $$ = $1; ++ } ++ ; ++ ++u1 ++ : absexp ++ { ++ if (($1 < 0) || ($1 > 1)) ++ serror("1-bit unsigned value out of range"); ++ $$ = $1; ++ } ++ ; ++ ++u2 ++ : absexp ++ { ++ if (($1 < 0) || ($1 > 0x3)) ++ serror("2-bit unsigned value out of range"); ++ $$ = $1; ++ } ++ ; ++ ++ds ++ : e16 ++ { ++ if ($1 & 3) ++ serror("value must be 4-aligned"); ++ $$ = $1; ++ } ++ ; ++ ++nb ++ : absexp ++ { ++ if (($1 < 1) || ($1 > 32)) ++ serror("register count must be in the range 1..32"); ++ ++ if ($1 == 32) ++ $$ = 0; ++ else ++ $$ = $1; ++ } ++ ; ++ ++bdl ++ : expr ++ { ++ int dist = $1.val - DOTVAL; ++ fit(fitx(dist, 25)); ++ ++ if (dist & 0x3) ++ serror("jump targets must be 4-aligned"); ++ ++ DOTVAL += 2; ++ newrelo($1.typ, RELO2 | RELPC | FIXUPFLAGS); ++ DOTVAL -= 2; ++ $$ = dist & 0xFFFD; ++ } ++ ; ++ ++bda ++ : expr ++ { ++ int target = $1.val; ++ fit(fitx(target, 16)); ++ ++ if (target & 0x3) ++ serror("jump targets must be 4-aligned"); ++ ++ DOTVAL += 2; ++ newrelo($1.typ, RELO2 | FIXUPFLAGS); ++ DOTVAL -= 2; ++ $$ = target & 0xFFFD; ++ } ++ ; ++ ++lil ++ : expr ++ { ++ int dist = $1.val - DOTVAL; ++ fit(fitx(dist, 26)); ++ ++ if (dist & 0x3) ++ serror("jump targets must be 4-aligned"); ++ ++ newrelo($1.typ, RELOPPC | RELPC | FIXUPFLAGS); ++ $$ = dist & 0x03FFFFFD; ++ } ++ ; ++ ++lia ++ : expr ++ { ++ int target = $1.val; ++ fit(fitx(target, 26)); ++ ++ if (target & 0x3) ++ serror("jump targets must be 4-aligned"); ++ ++ newrelo($1.typ, RELOPPC | FIXUPFLAGS); ++ $$ = target & 0x03FFFFFD; ++ } ++ ; ++ diff --cc mach/powerpc/as/mach5.c index 000000000,000000000..998cd8d9c new file mode 100644 --- /dev/null +++ b/mach/powerpc/as/mach5.c @@@ -1,0 -1,0 +1,5 @@@ ++/* ++ * $Source$ ++ * $State$ ++ */ ++ diff --cc mach/powerpc/libem/.distr index 000000000,000000000..d2b4f2884 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/.distr @@@ -1,0 -1,0 +1,2 @@@ ++LIST ++libem_s.a diff --cc mach/powerpc/libem/aar4.s index 000000000,000000000..72af86f55 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/aar4.s @@@ -1,0 -1,0 +1,35 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .text ++ ++! Index into a bounds-checked array. ++! ++! On entry: ++! r3 = ptr to descriptor ++! r4 = index ++! r5 = address of array ++ ++.define .aar4 ++.aar4: ++ addis r0, r0, <.trap_earray ++ ori r0, r0, >.trap_earray ++ mtspr ctr, r0 ! load CTR with trap address ++ ++ lwz r0, 0(r3) ++ subf. r4, r0, r4 ! adjust range ++ bcctr IFTRUE, LT, 0 ! check lower bound ++ ++ lwz r0, 4(r3) ++ cmpl cr0, 0, r4, r3 ++ bcctr IFFALSE, LT, 0 ! check upper bound ++ ++ lwz r0, 8(r3) ++ mullw r4, r4, r0 ! scale index ++ add r3, r4, r5 ! calculate element address ++ ++ bclr ALWAYS, 0, 0 diff --cc mach/powerpc/libem/cfi8.s index 000000000,000000000..7142c694b new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/cfi8.s @@@ -1,0 -1,0 +1,20 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .text ++ ++! Converts a 64-bit double into a 32-bit integer. ++! ++! Stack: ( double -- int ) ++ ++.define .cfi8 ++.cfi8: ++ lfd f0, 0(sp) ++ fctiwz f0, f0 ++ stfd f0, 0(sp) ++ addi sp, sp, 4 ++ bclr ALWAYS, 0, 0 ! ...and return diff --cc mach/powerpc/libem/cfu8.s index 000000000,000000000..8b60f69e8 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/cfu8.s @@@ -1,0 -1,0 +1,44 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .text ++ ++! Converts a 64-bit double into a 32-bit unsigned integer. ++! ++! Stack: ( double -- uint ) ++ ++.define .cfu8 ++.cfu8: ++ la(r3, .fd_00000000) ++ lfd f0, 0(r3) ! f0 = 0.0 ++ ++ lfd f1, 0(sp) ! value to be converted ++ ++ la(r3, .fd_FFFFFFFF) ++ lfd f3, 0(r3) ! f3 = 0xFFFFFFFF ++ ++ la(r3, .fd_80000000) ++ lfd f4, 0(r3) ! f4 = 0x80000000 ++ ++ fsel f2, f1, f1, f0 ++ fsub f5, f3, f1 ++ fsel f2, f5, f2, f3 ++ fsub f5, f2, f4 ++ fcmpu cr0, f2, f4 ++ fsel f2, f5, f5, f2 ++ fctiwz f2, f2 ++ ++ stfd f2, 0(sp) ++ addi sp, sp, 4 ++ ++ bclr IFTRUE, LT, 0 ++ ++ lwz r3, 0(sp) ++ xoris r3, r3, 0x8000 ++ stw r3, 0(sp) ++ ++ bclr ALWAYS, 0, 0 diff --cc mach/powerpc/libem/cif8.s index 000000000,000000000..01b503e0b new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/cif8.s @@@ -1,0 -1,0 +1,37 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .text ++ ++! Converts a 32-bit integer into a 64-bit double. ++! ++! Stack: ( int -- double ) ++ ++.define .cif8 ++.cif8: ++ addi sp, sp, -4 ! make space for the double ++ ++ lwz r3, 4(sp) ++ xoris r3, r3, 0x8000 ++ stw r3, 4(sp) ! flip sign of integer value ++ ++ addis r3, r0, 0x4330 ++ stw r3, 0(sp) ! set high word to construct a double ++ ++ lfd f0, 0(sp) ! load value ++ ++ la (r3, pivot) ++ lfd f1, 0(r3) ! load pivot value ++ fsub f0, f0, f1 ! adjust ++ ++ stfd f0, 0(sp) ! save value again... ++ bclr ALWAYS, 0, 0 ! ...and return ++ ++.sect .rom ++pivot: ++ .data4 0x43300000 ++ .data4 0x80000000 diff --cc mach/powerpc/libem/csa.s index 000000000,000000000..64954ff4e new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/csa.s @@@ -1,0 -1,0 +1,44 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .text ++ ++! this is not a subroutine, but just a ++! piece of code that computes the jump- ++! address and jumps to it. ++! traps if resulting address is zero ++! ++! On entry: r3 = address of CSA table ++! r4 = value ++ ++.define .csa ++.csa: ++ lwz r5, 0(r3) ! load default ++ mtspr ctr, r5 ++ ++ lwz r5, 4(r3) ! fetch lower bound ++ subf. r4, r5, r4 ! adjust value ++ bcctr IFTRUE, LT, 0 ! jump to default if out of range ++ ++ lwz r5, 8(r3) ! fetch range ++ cmp cr0, 0, r4, r5 ++ bcctr IFTRUE, GT, 0 ! jump to default if out of range ++ ++ addi r3, r3, 12 ! skip header ++ rlwinm r4, r4, 2, 0, 31-2 ! scale value (<<2) ++ b 1f ++1: ++ lwzx r5, r3, r4 ! load target ++ b 1f ++1: ++ mtspr ctr, r5 ++ ++ or. r5, r5, r5 ! test it ++ b 1f ++1: ++ bcctr IFFALSE, EQ, 0 ! jump to target if non-zero ++ b .trap_ecase ! otherwise trap diff --cc mach/powerpc/libem/csb.s index 000000000,000000000..cbedc8c11 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/csb.s @@@ -1,0 -1,0 +1,39 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .text ++ ++! this is not a subroutine, but just a ++! piece of code that computes the jump- ++! address and jumps to it. ++! traps if resulting address is zero ++! ++! On entry: r3 = address of CSB table ++! r4 = value ++ ++.define .csb ++.csb: ++ lwz r5, 0(r3) ! load default ++ mtspr ctr, r5 ++ ++ lwz r6, 4(r3) ! fetch count ++ ++1: ++ or. r6, r6, r6 ! test count ++ bcctr IFTRUE, EQ, 0 ! exit if zero ++ addi r6, r6, -1 ! otherwise decrement ++ ++ lwzu r7, 8(r3) ! fetch target index, increment pointer ++ cmp cr0, 0, r4, r7 ! compare with value ++ bc IFFALSE, EQ, 1b ! if not equal, go again ++ ++ lwz r7, 4(r3) ! fetch target address ++ mtspr ctr, r7 ++ ++ or. r7, r7, r7 ! test it ++ bcctr IFFALSE, EQ, 0 ! jump to target if non-zero ++ b .trap_ecase ! otherwise trap diff --cc mach/powerpc/libem/cuf8.s index 000000000,000000000..7adbb7bc4 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/cuf8.s @@@ -1,0 -1,0 +1,33 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .text ++ ++! Converts a 32-bit unsigned integer into a 64-bit double. ++! ++! Stack: ( uint -- double ) ++ ++.define .cuf8 ++.cuf8: ++ addi sp, sp, -4 ! make space for the double ++ ++ addis r3, r0, 0x4330 ++ stw r3, 0(sp) ! set high word to construct a double ++ ++ lfd f0, 0(sp) ! load value ++ ++ la (r3, pivot) ++ lfd f1, 0(r3) ! load pivot value ++ fsub f0, f0, f1 ! adjust ++ ++ stfd f0, 0(sp) ! save value again... ++ bclr ALWAYS, 0, 0 ! ...and return ++ ++.sect .rom ++pivot: ++ .data4 0x43300000 ++ .data4 0x00000000 diff --cc mach/powerpc/libem/fd_00000000.s index 000000000,000000000..cefa91b8e new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/fd_00000000.s @@@ -1,0 -1,0 +1,17 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .rom ++ ++! Contains a handy double-precision zero. (Also works as a single-precision ++! zero.) ++ ++.define .fd_00000000, .fs_00000000 ++.fd_00000000: ++.fs_00000000: ++ .data4 0x00000000 ++ .data4 0x00000000 diff --cc mach/powerpc/libem/fd_80000000.s index 000000000,000000000..50eacd586 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/fd_80000000.s @@@ -1,0 -1,0 +1,15 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .rom ++ ++! Contains a handy double-precision 0x80000000. ++ ++.define .fd_80000000 ++.fd_80000000: ++ !float 2.147483648e+9 sz 8 ++ .data1 0101,0340,00,00,00,00,00,00 diff --cc mach/powerpc/libem/fd_FFFFFFFF.s index 000000000,000000000..9218f2726 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/fd_FFFFFFFF.s @@@ -1,0 -1,0 +1,15 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .rom ++ ++! Contains a handy double-precision 0xFFFFFFFF. ++ ++.define .fd_FFFFFFFF ++.fd_FFFFFFFF: ++ !float 4.294967295e+9 sz 8 ++ .data1 0101,0357,0377,0377,0377,0340,00,00 diff --cc mach/powerpc/libem/fef8.c index 000000000,000000000..244d0fac8 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/fef8.c @@@ -1,0 -1,0 +1,46 @@@ ++/* ++ * $Source$ ++ * $State$ ++ * $Revision$ ++ */ ++ ++/* no headers allowed! */ ++ ++/* Given a double, calculates the mantissa and exponent. ++ * ++ * This function is intended to be called internally by the code generator, ++ * so the calling convention is odd. ++ */ ++ ++int __fef8(double* fp) ++{ ++ double f = *fp; ++ int exponent, sign; ++ ++ if (f == 0.0) ++ return 0; ++ ++ if (f < 0.0) ++ { ++ sign = -1; ++ f = -f; ++ } ++ else ++ sign = 0; ++ ++ exponent = 0; ++ while (f >= 1.0) ++ { ++ f /= 2.0; ++ exponent++; ++ } ++ ++ while (f < 0.5) ++ { ++ f *= 2.0; ++ exponent--; ++ } ++ ++ *fp = (sign) ? -f : f; ++ return exponent; ++} diff --cc mach/powerpc/libem/fif8.s index 000000000,000000000..052c38cf2 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/fif8.s @@@ -1,0 -1,0 +1,38 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .text ++ ++! Multiplies two floats, and returns the fraction and integer. ++ ++.define .fif8 ++.fif8: ++ lfd f0, 8(sp) ++ lfd f1, 0(sp) ++ fmul f0, f0, f1 ++ fabs f1, f0 ! f0 = result ++ ++ ! The following chunk does f1 = floor(f1). See page 158 of the book. ++ ++ mtfsfi cr7, 3 ! set rounding mode to -inf. ++ mtfsb0 23 ++ fctid f2, f1 ++ fcfid f2, f2 ++ mcrfs cr7, cr5 ++ bc IFFALSE, 31, toobig ++ fmr f1, f2 ++toobig: ++ ++ fabs f2, f1 ! f2 = fabs(f1) ++ fsub f2, f2, f1 ++ stfd f2, 8(sp) ++ ++ fneg f2, f1 ++ fsel f2, f0, f1, f2 ++ stfd f2, 0(sp) ++ ++ bclr ALWAYS, 0, 0 diff --cc mach/powerpc/libem/los.s index 000000000,000000000..f867fe770 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/los.s @@@ -1,0 -1,0 +1,54 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .text ++ ++! Loads a variable-sized structure onto the stack. ++! ++! r3 = size ++! r4 = address ++ ++.define .los ++.los: ++ ! These sizes are handled specially. ++ ++ cmpi cr0, 0, r3, 1 ++ bc IFFALSE, GT, size1 ++ ++ cmpi cr0, 0, r3, 2 ++ bc IFFALSE, GT, size2 ++ ++ cmpi cr0, 0, r3, 4 ++ bc IFFALSE, GT, size4 ++ ++ ! Variable-sized structure. ++ ++ addi r3, r3, 3 ++ andi. r3, r3, ~3 ! align size ++ ++ add r4, r4, r3 ! adjust address to top of block ++ ++ srawi r3, r3, 2 ! convert size to the number of words ++ mtspr ctr, r3 ++ ++1: ++ lwzu r5, -4(r4) ++ stwu r5, -4(sp) ++ bc DNZ, 0, 1b ! decrement CTR, jump if non-zero ++ bclr ALWAYS, 0, 0 ++ ++size1: ++ lbz r3, 0(r4) ++ b 1f ++size2: ++ lhz r3, 0(r4) ++ b 1f ++size4: ++ lwz r3, 0(r4) ++1: ++ stwu r3, -4(sp) ++ bclr ALWAYS, 0, 0 diff --cc mach/powerpc/libem/pmfile index 000000000,000000000..8c851f81e new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/pmfile @@@ -1,0 -1,0 +1,30 @@@ ++-- $Source$ ++-- $State$ ++-- $Revision$ ++ ++local d = ROOTDIR.."mach/powerpc/libem/" ++ ++libem_powerpc = acklibrary { ++ outputs = {"%U%/libem-%PLATFORM%.a"}, ++ ++ ACKINCLUDES = {PARENT, d}, ++ ++ ackfile (d.."ret.s"), ++ ackfile (d.."tge.s"), ++ ackfile (d.."csa.s"), ++ ackfile (d.."csb.s"), ++ ackfile (d.."los.s"), ++ ackfile (d.."sts.s"), ++ ackfile (d.."aar4.s"), ++ ackfile (d.."fef8.c"), ++ ackfile (d.."fif8.s"), ++ ackfile (d.."cif8.s"), ++ ackfile (d.."cuf8.s"), ++ ackfile (d.."cfi8.s"), ++ ackfile (d.."cfu8.s"), ++ ackfile (d.."fd_00000000.s"), ++ ackfile (d.."fd_80000000.s"), ++ ackfile (d.."fd_FFFFFFFF.s"), ++ ++ install = pm.install("%BINDIR%lib/%PLATFORM%/libem.a"), ++} diff --cc mach/powerpc/libem/powerpc.h index 000000000,000000000..ddc4064f9 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/powerpc.h @@@ -1,0 -1,0 +1,23 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++! Declare segments (the order is important). ++ ++.sect .text ++.sect .rom ++.sect .data ++.sect .bss ++ ++#define IFFALSE 4 ++#define IFTRUE 12 ++#define ALWAYS 20 ++#define DNZ 16 ++ ++#define LT 0 ++#define GT 1 ++#define EQ 2 ++#define OV 3 ++ ++#define la(reg, val) addis reg, r0, val diff --cc mach/powerpc/libem/ret.s index 000000000,000000000..cca79ae86 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/ret.s @@@ -1,0 -1,0 +1,19 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .text ++ ++! Standard boilerplate for returning from functions. ++ ++.define .ret ++.ret: ++ lwz r0, 4(fp) ++ mtspr lr, r0 ++ lwz r0, 0(fp) ! our stack frame becomes invalid as soon as... ++ addi sp, fp, 8 ! ...we change sp ++ or fp, r0, r0 ++ bclr ALWAYS, 0, 0 diff --cc mach/powerpc/libem/sts.s index 000000000,000000000..2f8022ad9 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/sts.s @@@ -1,0 -1,0 +1,57 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .text ++ ++! Stores a variable-sized structure from the stack. ++! ++! r3 = size ++! r4 = address ++ ++.define .sts ++.sts: ++ ! These sizes are handled specially. ++ ++ lwz r5, 0(sp) ++ ++ cmpi cr0, 0, r3, 1 ++ bc IFFALSE, GT, size1 ++ ++ cmpi cr0, 0, r3, 2 ++ bc IFFALSE, GT, size2 ++ ++ cmpi cr0, 0, r3, 4 ++ bc IFFALSE, GT, size4 ++ ++ ! Variable-sized structure. ++ ++ addi r3, r3, 3 ++ andi. r3, r3, ~3 ! align size ++ ++ srawi r3, r3, 2 ! convert size to the number of words ++ mtspr ctr, r3 ++ ++1: ++ lwz r5, 0(sp) ++ addi sp, sp, 4 ++ stw r5, 0(r4) ++ addi r4, r4, 4 ++ ++ bc DNZ, 0, 1b ! decrement CTR, jump if non-zero ++ bclr ALWAYS, 0, 0 ++ ++size1: ++ stb r5, 0(r4) ++ b 1f ++size2: ++ sth r5, 0(r4) ++ b 1f ++size4: ++ stw r5, 0(r4) ++1: ++ addi sp, sp, 4 ++ bclr ALWAYS, 0, 0 diff --cc mach/powerpc/libem/tge.s index 000000000,000000000..4740d8436 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libem/tge.s @@@ -1,0 -1,0 +1,46 @@@ ++# ++! $Source$ ++! $State$ ++! $Revision$ ++ ++#include "powerpc.h" ++ ++.sect .rom ++ ++! Lookup table for tge. ++ ++.define .teq_table ++.teq_table: ++ .data4 1 ! . . ++ .data4 0 ! . G ++ .data4 0 ! L . ++ ++.define .tne_table ++.tne_table: ++ .data4 0 ! . . ++ .data4 1 ! . G ++ .data4 1 ! L . ++ ++.define .tgt_table ++.tgt_table: ++ .data4 0 ! . . ++ .data4 1 ! . G ++ .data4 0 ! L . ++ ++.define .tge_table ++.tge_table: ++ .data4 1 ! . . ++ .data4 1 ! . G ++ .data4 0 ! L . ++ ++.define .tlt_table ++.tlt_table: ++ .data4 0 ! . . ++ .data4 0 ! . G ++ .data4 1 ! L . ++ ++.define .tle_table ++.tle_table: ++ .data4 1 ! . . ++ .data4 0 ! . G ++ .data4 1 ! L . diff --cc mach/powerpc/libend/.distr index 000000000,000000000..1508ebdc7 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libend/.distr @@@ -1,0 -1,0 +1,5 @@@ ++pmfile ++edata.s ++em_end.s ++end.s ++etext.s diff --cc mach/powerpc/libend/LIST index 000000000,000000000..2efbd3eb2 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libend/LIST @@@ -1,0 -1,0 +1,5 @@@ ++end_s.a ++edata.s ++em_end.s ++end.s ++etext.s diff --cc mach/powerpc/libend/edata.s index 000000000,000000000..f53adc109 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libend/edata.s @@@ -1,0 -1,0 +1,9 @@@ ++.sect .text ++.sect .rom ++.sect .data ++.sect .bss ++.define _edata ++.sect .data ++ .align 4 ++ .sect .data ++_edata: diff --cc mach/powerpc/libend/em_end.s index 000000000,000000000..0271f09f6 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libend/em_end.s @@@ -1,0 -1,0 +1,24 @@@ ++! $Source$ ++! $State$ ++! $Revision$ ++ ++.sect .text ++.sect .rom ++.sect .data ++.sect .bss ++.sect .end ! only for declaration of _end, __end and endbss. ++.define endtext, endrom, enddata, endbss, __end ++ ++ .sect .text ++ .align 4 ++endtext: ++ .sect .rom ++ .align 4 ++endrom: ++ .sect .data ++ .align 4 ++enddata: ++ .sect .end ++ .align 4 ++__end: ++endbss: diff --cc mach/powerpc/libend/end.s index 000000000,000000000..93a1e6e00 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libend/end.s @@@ -1,0 -1,0 +1,7 @@@ ++.sect .text ++.sect .rom ++.sect .data ++.sect .bss ++.define _end ++.sect .end ! only for declaration of _end, __end and endbss. ++_end: diff --cc mach/powerpc/libend/etext.s index 000000000,000000000..8c7453cb4 new file mode 100644 --- /dev/null +++ b/mach/powerpc/libend/etext.s @@@ -1,0 -1,0 +1,9 @@@ ++.sect .text ++.sect .rom ++.sect .data ++.sect .bss ++.define _etext ++.sect .text ++ .align 4 ++ .sect .text ++_etext: diff --cc mach/powerpc/libend/pmfile index 000000000,000000000..83f1c038d new file mode 100644 --- /dev/null +++ b/mach/powerpc/libend/pmfile @@@ -1,0 -1,0 +1,16 @@@ ++-- $Source$ ++-- $State$ ++-- $Revision$ ++ ++local d = ROOTDIR.."mach/powerpc/libend/" ++ ++libend_powerpc = acklibrary { ++ outputs = {"%U%/libend-%PLATFORM%.a"}, ++ ++ ackfile (d.."edata.s"), ++ ackfile (d.."em_end.s"), ++ ackfile (d.."end.s"), ++ ackfile (d.."etext.s"), ++ ++ install = pm.install("%BINDIR%lib/%PLATFORM%/libend.a"), ++} diff --cc mach/powerpc/ncg/.distr index 000000000,000000000..ccdf9bf7e new file mode 100644 --- /dev/null +++ b/mach/powerpc/ncg/.distr @@@ -1,0 -1,0 +1,3 @@@ ++mach.c ++mach.h ++table diff --cc mach/powerpc/ncg/mach.c index 000000000,000000000..39c6362e6 new file mode 100644 --- /dev/null +++ b/mach/powerpc/ncg/mach.c @@@ -1,0 -1,0 +1,209 @@@ ++/* ++ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. ++ * See the copyright notice in the ACK home directory, in the file "Copyright". ++ * ++ */ ++ ++#include ++#include ++ ++#ifndef NORCSID ++static char rcsid[]= "$Id$" ; ++#endif ++ ++int framesize; ++ ++/* ++ * machine dependent back end routines for the Zilog Z80. ++ */ ++ ++con_part(int sz, word w) ++{ ++ while (part_size % sz) ++ part_size++; ++ if (part_size == TEM_WSIZE) ++ part_flush(); ++ if (sz == 1) { ++ w &= 0xFF; ++ w <<= 8*(3-part_size); ++ part_word |= w; ++ } else if (sz == 2) { ++ w &= 0xFFFF; ++ if (part_size == 0) { ++ /* Shift 8 for m68k2, 16 otherwise */ ++ w <<= 4 * TEM_WSIZE; ++ } ++ part_word |= w; ++ } else { ++ assert(sz == TEM_WSIZE); ++ part_word = w; ++ } ++ part_size += sz; ++} ++ ++con_mult(word sz) ++{ ++ ++ if (argval != 4) ++ fatal("bad icon/ucon size"); ++ fprintf(codefile,".data4 %s\n", str); ++} ++ ++#define CODE_GENERATOR ++#define IEEEFLOAT ++#define FL_MSL_AT_LOW_ADDRESS 1 ++#define FL_MSW_AT_LOW_ADDRESS 1 ++#define FL_MSB_AT_LOW_ADDRESS 1 ++#include ++ ++prolog(full nlocals) ++{ ++ int ss = nlocals + 8; ++ fprintf(codefile, "addi sp, sp, %d\n", -ss); ++ fprintf(codefile, "stw fp, %d(sp)\n", nlocals); ++ fprintf(codefile, "mfspr r0, lr\n" ++ "stw r0, %d(sp)\n", nlocals+4); ++ fprintf(codefile, "addi fp, sp, %d\n", nlocals); ++ ++ framesize = nlocals; ++} ++ ++mes(word type) ++{ ++ int argt ; ++ ++ switch ( (int)type ) { ++ case ms_ext : ++ for (;;) { ++ switch ( argt=getarg( ++ ptyp(sp_cend)|ptyp(sp_pnam)|sym_ptyp) ) { ++ case sp_cend : ++ return ; ++ default: ++ strarg(argt) ; ++ fprintf(codefile,".define %s\n",argstr) ; ++ break ; ++ } ++ } ++ default : ++ while ( getarg(any_ptyp) != sp_cend ) ; ++ break ; ++ } ++} ++ ++char *segname[] = { ++ ".sect .text", ++ ".sect .data", ++ ".sect .rom", ++ ".sect .bss" ++}; ++ ++#ifdef REGVARS ++ ++static int savedregsi[32]; ++static int numsaved; ++ ++/* Initialise regvar system for one function. */ ++ ++i_regsave() ++{ ++ int i; ++ ++ fprintf(codefile, "! i_regsave()\n"); ++ for (i=0; i<32; i++) ++ savedregsi[i] = INT_MAX; ++ numsaved = 0; ++} ++ ++/* Mark a register as being saved. */ ++ ++regsave(const char* regname, full offset, int size) ++{ ++ int regnum = atoi(regname+1); ++ savedregsi[regnum] = offset; ++ numsaved++; ++ ++ fprintf(codefile, "! %d is saved in %s\n", offset, regname); ++#if 0 ++ fprintf(codefile, "stwu %s, -4(sp)\n", regname); ++ if (offset >= 0) ++ fprintf(codefile, "lwz %s, %d(fp)\n", regname, offset); ++#endif ++} ++ ++/* Finish saving ragisters. */ ++ ++void saveloadregs(const char* ops, const char* opm) ++{ ++ int offset = -(framesize + numsaved*4); ++ int reg = 32; ++ ++ /* Check for the possibility of a multiple. */ ++ ++ do ++ { ++ reg--; ++ } ++ while ((reg > 0) && (savedregsi[reg] != INT_MAX)); ++ if (reg < 31) ++ { ++ fprintf(codefile, "%s r%d, %d(fp)\n", opm, reg+1, offset); ++ offset += (31-reg)*4; ++ } ++ ++ /* Saved everything else singly. */ ++ ++ while (reg > 0) ++ { ++ if (savedregsi[reg] != INT_MAX) ++ { ++ fprintf(codefile, "%s r%d, %d(fp)\n", ops, reg, offset); ++ offset += 4; ++ } ++ reg--; ++ } ++} ++ ++f_regsave() ++{ ++ int i; ++ fprintf(codefile, "! f_regsave()\n"); ++ fprintf(codefile, "addi sp, sp, %d\n", -numsaved*4); ++ ++ saveloadregs("stw", "stmw"); ++ ++ for (i=0; i<32; i++) ++ if ((savedregsi[i] != INT_MAX) && (savedregsi[i] > 0)) ++ fprintf(codefile, "lwz r%d, %d(fp)\n", i, savedregsi[i]); ++} ++ ++/* Restore all saved registers. */ ++ ++regreturn() ++{ ++ fprintf(codefile, "! regreturn()\n"); ++ saveloadregs("lwz", "lmw"); ++} ++ ++/* Calculate the score of a given register. */ ++ ++int regscore(full offset, int size, int type, int frequency, int totype) ++{ ++ int score; ++ ++ fprintf(codefile, "! regscore(%ld, %d, %d, %d, %d)\n", offset, size, type, frequency, totype); ++ ++ if (size != 4) ++ return -1; ++ ++ /* Per use: 6 bytes (on average) ++ * Overhead in prologue: 4 bytes, plus 4 if a parameter ++ * Overhead in epilogue: 0 bytes ++ */ ++ ++ score = frequency*6 - 4 - ((offset>=0) ? 4 : 0); ++ fprintf(codefile, "! local at offset %d has regvar score %d\n", offset, score); ++ return score; ++} ++ ++#endif diff --cc mach/powerpc/ncg/mach.h index 000000000,000000000..0bca86fae new file mode 100644 --- /dev/null +++ b/mach/powerpc/ncg/mach.h @@@ -1,0 -1,0 +1,30 @@@ ++/* ++ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. ++ * See the copyright notice in the ACK home directory, in the file "Copyright". ++ */ ++/* $Id$ */ ++#define ex_ap(y) fprintf(codefile,".extern %s\n",y) ++#define in_ap(y) /* nothing */ ++ ++#define newilb(x) fprintf(codefile,"%s:\n",x) ++#define newdlb(x) fprintf(codefile,"%s:\n",x) ++#define dlbdlb(x,y) fprintf(codefile,"%s = %s\n",x,y) ++#define newlbss(l,x) fprintf(codefile,".comm %s,%u\n",l,x); ++ ++#define cst_fmt "%d" ++#define off_fmt "%d" ++#define ilb_fmt "I%x_%x" ++#define dlb_fmt "_%d" ++#define hol_fmt "hol%d" ++ ++#define hol_off "%ld+hol%d" ++ ++#define con_cst(x) fprintf(codefile,".data4\t%ld\n",x) ++#define con_ilb(x) fprintf(codefile,".data4\t%s\n",x) ++#define con_dlb(x) fprintf(codefile,".data4\t%s\n",x) ++ ++#define fmt_id(sf, st) sprintf(st,"_%s",sf) ++ ++#define modhead ".sect .text; .sect .rom; .sect .data; .sect .bss\n" ++ ++#define BSS_INIT 0 diff --cc mach/powerpc/ncg/table index 000000000,000000000..c35ea728e new file mode 100644 --- /dev/null +++ b/mach/powerpc/ncg/table @@@ -1,0 -1,0 +1,2161 @@@ ++EM_WSIZE = 4 ++EM_PSIZE = 4 ++EM_BSIZE = 8 /* two words saved in call frame */ ++ ++INT8 = 1 /* Size of values */ ++INT16 = 2 ++INT32 = 4 ++INT64 = 8 ++ ++FP_OFFSET = 0 /* Offset of saved FP relative to our FP */ ++PC_OFFSET = 4 /* Offset of saved PC relative to our FP */ ++ ++#define COMMENT(n) /* noop */ ++ ++ ++#define nicesize(x) ((x)==INT8 || (x)==INT16 || (x)==INT32 || (x)==INT64) ++ ++#define smalls(n) sfit(n, 16) ++#define smallu(n) ufit(n, 16) ++ ++#define lo(n) (n & 0xFFFF) ++#define hi(n) ((n>>16) & 0xFFFF) ++ ++/* Use these for instructions that treat the low half as signed --- his() ++ * includes a modifier to produce the correct value when the low half gets ++ * sign extended. Er, do make sure you load the low half second. */ ++#define los(n) (n & 0xFFFF) ++#define his(n) ((hi(n) - (lo(n)>>15)) & 0xFFFF) ++ ++#define IFFALSE {CONST, 4} ++#define IFTRUE {CONST, 12} ++#define ALWAYS {CONST, 20} ++#define DCTRZ {CONST, 34} ++ ++#define LT {CONST, 0} ++#define GT {CONST, 1} ++#define EQ {CONST, 2} ++ ++ ++ ++PROPERTIES ++ ++ GPR /* any GPR */ ++ REG /* any allocatable GPR */ ++ FPR /* any FPR */ ++ FREG /* any allocatable FPR */ ++ SPR /* any SPR */ ++ CR /* any CR */ ++ ++ GPR0 GPRSP GPRFP GPR3 GPR4 GPR5 GPR6 GPR7 ++ GPR8 GPR9 GPR10 GPR11 GPR12 GPR13 GPR14 GPR15 ++ GPR16 GPR17 GPR18 GPR19 GPR20 GPR21 GPR22 GPR23 ++ GPR24 GPR25 GPR26 GPR27 GPR28 GPR29 GPR30 GPR31 ++ ++ CR0 CR1 ++ ++ FPR0 FPR1 FPR2 FPR3 FPR4 FPR5 FPR6 FPR7 ++ FPR8 FPR9 FPR10 FPR11 FPR12 FPR13 FPR14 FPR15 ++ FPR16 FPR17 FPR18 FPR19 FPR20 FPR21 FPR22 FPR23 ++ FPR24 FPR25 FPR26 FPR27 FPR28 FPR29 FPR30 FPR31 ++ ++REGISTERS ++ ++ /* Reverse order to encourage ncg to allocate them from r31 down */ ++ ++ R31("r31") : GPR, REG, GPR31 regvar. ++ R30("r30") : GPR, REG, GPR30 regvar. ++ R29("r29") : GPR, REG, GPR29 regvar. ++ R28("r28") : GPR, REG, GPR28 regvar. ++ R27("r27") : GPR, REG, GPR27 regvar. ++ R26("r26") : GPR, REG, GPR26 regvar. ++ R25("r25") : GPR, REG, GPR25 regvar. ++ R24("r24") : GPR, REG, GPR24 regvar. ++ R23("r23") : GPR, REG, GPR23 regvar. ++ R22("r22") : GPR, REG, GPR22 regvar. ++ R21("r21") : GPR, REG, GPR21 regvar. ++ R20("r20") : GPR, REG, GPR20 regvar. ++ R19("r19") : GPR, REG, GPR19 regvar. ++ R18("r18") : GPR, REG, GPR18 regvar. ++ R17("r17") : GPR, REG, GPR17 regvar. ++ R16("r16") : GPR, REG, GPR16 regvar. ++ R15("r15") : GPR, REG, GPR15 regvar. ++ R14("r14") : GPR, REG, GPR14 regvar. ++ R13("r13") : GPR, REG, GPR13 regvar. ++ R12("r12") : GPR, REG, GPR12. ++ R11("r11") : GPR, GPR11. ++ R10("r10") : GPR, REG, GPR10. ++ R9("r9") : GPR, REG, GPR9. ++ R8("r8") : GPR, REG, GPR8. ++ R7("r7") : GPR, REG, GPR7. ++ R6("r6") : GPR, REG, GPR6. ++ R5("r5") : GPR, REG, GPR5. ++ R4("r4") : GPR, REG, GPR4. ++ R3("r3") : GPR, REG, GPR3. ++ FP("fp") : GPR, GPRFP. ++ SP("sp") : GPR, GPRSP. ++ R0("r0") : GPR, GPR0. ++ ++ F31("f31") : FPR, FREG, FPR31. ++ F30("f30") : FPR, FREG, FPR30. ++ F29("f29") : FPR, FREG, FPR29. ++ F28("f28") : FPR, FREG, FPR28. ++ F27("f27") : FPR, FREG, FPR27. ++ F26("f26") : FPR, FREG, FPR26. ++ F25("f25") : FPR, FREG, FPR25. ++ F24("f24") : FPR, FREG, FPR24. ++ F23("f23") : FPR, FREG, FPR23. ++ F22("f22") : FPR, FREG, FPR22. ++ F21("f21") : FPR, FREG, FPR21. ++ F20("f20") : FPR, FREG, FPR20. ++ F19("f19") : FPR, FREG, FPR19. ++ F18("f18") : FPR, FREG, FPR18. ++ F17("f17") : FPR, FREG, FPR17. ++ F16("f16") : FPR, FREG, FPR16. ++ F15("f15") : FPR, FREG, FPR15. ++ F14("f14") : FPR, FREG, FPR14. ++ F13("f13") : FPR, FREG, FPR13. ++ F12("f12") : FPR, FREG, FPR12. ++ F11("f11") : FPR, FREG, FPR11. ++ F10("f10") : FPR, FREG, FPR10. ++ F9("f9") : FPR, FREG, FPR9. ++ F8("f8") : FPR, FREG, FPR8. ++ F7("f7") : FPR, FREG, FPR7. ++ F6("f6") : FPR, FREG, FPR6. ++ F5("f5") : FPR, FREG, FPR5. ++ F4("f4") : FPR, FREG, FPR4. ++ F3("f3") : FPR, FREG, FPR3. ++ F2("f2") : FPR, FREG, FPR2. ++ F1("f1") : FPR, FREG, FPR1. ++ F0("f0") : FPR, FREG, FPR0. ++ ++ LR("lr") : SPR. ++ CTR("ctr") : SPR. ++ C0("cr0") : CR, CR0. ++ ++#define SCRATCH R11 ++#define FSCRATCH F0 ++ ++ ++TOKENS ++ ++/* Used only in instruction descriptions (to generate the correct syntax). */ ++ ++ GPRINDIRECT = { GPR reg; INT off; } 4 off "(" reg ")". ++ GPRINDIRECTLO = { GPR reg; ADDR adr; } 4 ">" adr "(" reg ")". /* Warning! Do not use on labels. */ ++ HILABEL = { ADDR adr; } 4 "<" adr. ++ LOLABEL = { ADDR adr; } 4 ">" adr. ++ ++/* Primitives */ ++ ++ LABEL = { ADDR adr; } 4 adr. ++ CONST = { INT val; } 4 val. ++ LOCAL = { INT off; } 4. ++ ++/* Allows us to use regvar() to refer to registers */ ++ ++ GPRE = { GPR reg; } 4 reg. ++ ++/* Expression partial results */ ++ ++ SUM_RC = { GPR reg; INT off; } 4. ++ SUM_RR = { GPR reg1; GPR reg2; } 4. ++ ++ TRISTATE_RC_S = { GPR reg; INT val; } 4. ++ TRISTATE_RC_U = { GPR reg; INT val; } 4. ++ TRISTATE_RR_S = { GPR reg1; GPR reg2; } 4. ++ TRISTATE_RR_U = { GPR reg1; GPR reg2; } 4. ++ ++ TRISTATE_FF = { FPR reg1; FPR reg2; } 4. ++ ++ SEX_B = { GPR reg; } 4. ++ SEX_H = { GPR reg; } 4. ++ ++ IND_RC_B = { GPR reg; INT off; } 4. ++ IND_RC_H = { GPR reg; INT off; } 4. ++ IND_RC_H_S = { GPR reg; INT off; } 4. ++ IND_RC_W = { GPR reg; INT off; } 4. ++ IND_RR_W = { GPR reg1; GPR reg2; } 4. ++ IND_LABEL_W = { ADDR adr; } 4. ++ IND_RC_D = { GPR reg; INT off; } 8. ++ IND_RR_D = { GPR reg1; GPR reg2; } 8. ++ IND_LABEL_D = { ADDR adr; } 8. ++ ++ NOT_R = { GPR reg; } 4. ++ ++ AND_RR = { GPR reg1; GPR reg2; } 4. ++ AND_RC = { GPR reg; INT val; } 4. ++ OR_RR = { GPR reg1; GPR reg2; } 4. ++ OR_RC = { GPR reg; INT val; } 4. ++ XOR_RR = { GPR reg1; GPR reg2; } 4. ++ XOR_RC = { GPR reg; INT val; } 4. ++ ++/* Floats */ ++ ++ FD = { FPR reg; } 8 reg. ++ FS = { FPR reg; } 4 reg. ++ ++/* Comments */ ++ ++ LABELI = { ADDR msg; INT num; } 4 msg " " num. ++ ++ ++ ++ ++SETS ++ ++ TOKEN = LABEL + CONST + LOCAL. ++ GPRI = GPR + GPRE. ++ ++ SUM_ALL = SUM_RC + SUM_RR. ++ ++ TRISTATE_ALL = TRISTATE_RC_S + TRISTATE_RC_U + TRISTATE_RR_S + ++ TRISTATE_RR_U + TRISTATE_FF. ++ ++ SEX_ALL = SEX_B + SEX_H. ++ ++ LOGICAL_ALL = NOT_R + AND_RR + AND_RC + OR_RR + OR_RC + XOR_RR + ++ XOR_RC. ++ ++ IND_ALL_W = IND_RC_W + IND_RR_W + IND_LABEL_W. ++ ++ IND_ALL_D = IND_RC_D + IND_RR_D + IND_LABEL_D. ++ ++ OP_ALL_W = SUM_ALL + TRISTATE_ALL + SEX_ALL + LOGICAL_ALL + ++ IND_ALL_W. ++ ++ ++INSTRUCTIONS ++ ++ add GPRI:wo, GPRI:ro, GPRI:ro. ++ addX "add." GPRI:wo, GPRI:ro, GPRI:ro. ++ addi GPRI:wo, GPRI:ro, CONST:ro. ++ addis GPRI:wo, GPRI:ro, CONST+HILABEL:ro. ++ and GPRI:wo, GPRI:ro, GPRI:ro. ++ andc GPRI:wo, GPRI:ro, GPRI:ro. ++ andiX "andi." GPRI:wo, GPRI:ro, CONST:ro kills :cc. ++ andisX "andis." GPRI:wo, GPRI:ro, CONST:ro kills :cc. ++ b LABEL:ro. ++ bc CONST:ro, CONST:ro, LABEL:ro. ++ bcctr CONST:ro, CONST:ro, CONST:ro. ++ bcctrl CONST:ro, CONST:ro, CONST:ro. ++ bclr CONST:ro, CONST:ro, CONST:ro. ++ bl LABEL:ro. ++ cmp CR:ro, CONST:ro, GPRI:ro, GPR:ro kills :cc. ++ cmpi CR:ro, CONST:ro, GPRI:ro, CONST:ro kills :cc. ++ cmpl CR:ro, CONST:ro, GPRI:ro, GPR:ro kills :cc. ++ cmpli CR:ro, CONST:ro, GPRI:ro, CONST:ro kills :cc. ++ divw GPRI:wo, GPRI:ro, GPRI:ro. ++ divwu GPRI:wo, GPRI:ro, GPRI:ro. ++ eqv GPRI:wo, GPRI:ro, GPRI:ro. ++ extsb GPRI:wo, GPRI:ro. ++ extsh GPRI:wo, GPRI:ro. ++ fadd FD:wo, FD:ro, FD:ro. ++ fadds FS:wo, FS:ro, FS:ro. ++ fcmpo CR:wo, FD:ro, FD:ro. ++ fdiv FD:wo, FD:ro, FD:ro. ++ fdivs FS:wo, FS:ro, FS:ro. ++ fneg FS+FD:wo, FS+FD:ro. ++ fmul FD:wo, FD:ro, FD:ro. ++ fmuls FS:wo, FS:ro, FS:ro. ++ frsp FS:wo, FD:ro. ++ fsub FD:wo, FD:ro, FD:ro. ++ fsubs FS:wo, FS:ro, FS:ro. ++ fmr FS+FD:wo, FS+FD:ro. ++ lbzx GPRI:wo, GPR:ro, GPR:ro. ++ lbz GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro. ++ lfd FD:wo, GPRINDIRECT+GPRINDIRECTLO:ro. ++ lfdu FD:wo, GPRINDIRECT+GPRINDIRECTLO:ro. ++ lfdx FD:wo, GPR:ro, GPR:ro. ++ lfs FS:wo, GPRINDIRECT+GPRINDIRECTLO:ro. ++ lfsu FS:wo, GPRINDIRECT+GPRINDIRECTLO:rw. ++ lfsx FS:wo, GPR:ro, GPR:ro. ++ lhzx GPRI:wo, GPR:ro, GPR:ro. ++ lhax GPRI:wo, GPR:ro, GPR:ro. ++ lha GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro. ++ lhz GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro. ++ lwzu GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro. ++ lwzx GPRI:wo, GPR:ro, GPR:ro. ++ lwz GPRI:wo, GPRINDIRECT+GPRINDIRECTLO:ro. ++ nand GPRI:wo, GPRI:ro, GPRI:ro. ++ neg GPRI:wo, GPRI:ro. ++ nor GPRI:wo, GPRI:ro, GPRI:ro. ++ mfcr GPRI:wo. ++ mullw GPRI:wo, GPRI:ro, GPRI:ro. ++ mfspr GPRI:wo, SPR:ro. ++ mtspr SPR:wo, GPRI:ro. ++ or GPRI:wo, GPRI:ro, GPRI:ro. ++ orc GPRI:wo, GPRI:ro, GPRI:ro. ++ ori GPRI:wo, GPRI:ro, CONST+LOLABEL:ro. ++ orX "or." GPRI:wo, GPRI:ro, GPRI:ro kills :cc. ++ rlwinm GPRI:wo, GPRI:ro, CONST:ro, CONST:ro, CONST:ro. ++ slw GPRI:wo, GPRI:ro, GPRI:ro. ++ subf GPRI:wo, GPRI:ro, GPRI:ro. ++ sraw GPRI:wo, GPRI:ro, GPRI:ro. ++ srawi GPRI:wo, GPRI:ro, CONST:ro. ++ srw GPRI:wo, GPRI:ro, GPRI:ro. ++ stb GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw. ++ stbx GPRI:ro, GPR:ro, GPR:ro. ++ stfd FD:ro, GPRINDIRECT+GPRINDIRECTLO:rw. ++ stfdu FD:ro, GPRINDIRECT+GPRINDIRECTLO:rw. ++ stfdx FD:ro, GPR:ro, GPR:ro. ++ stfs FS:ro, GPRINDIRECT+GPRINDIRECTLO:rw. ++ stfsu FS:ro, GPRINDIRECT+GPRINDIRECTLO:rw. ++ stfsx FS:ro, GPR:ro, GPR:ro. ++ sth GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw. ++ sthx GPRI:ro, GPR:ro, GPR:ro. ++ stw GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw. ++ stwx GPRI:ro, GPR:ro, GPR:ro. ++ stwu GPRI:ro, GPRINDIRECT+GPRINDIRECTLO:rw. ++ xor GPRI:wo, GPRI:ro, GPRI:ro. ++ xori GPRI:wo, GPRI:ro, CONST:ro. ++ ++ gpr_gpr_gpr GPRI:wo, GPRI:ro, GPRI:ro. ++ gpr_gpr_si GPRI:wo, GPRI:ro, CONST:ro. ++ gpr_ro_gprindirect GPRI:ro, GPRINDIRECT:rw. ++ gpr_ro_gpr_gpr GPRI:ro, GPRI:ro, GPRI:ro. ++ gpr_wo_gprindirect GPRI:wo, GPRINDIRECT:ro. ++ gpr_wo_gpr_gpr GPRI:wo, GPRI:ro, GPRI:ro. ++ ++ invalid "invalid". ++ comment "!" LABEL+LABELI:ro. ++ ++ ++ ++MOVES ++ ++ from GPR to GPR ++ gen ++ COMMENT("move GPR->GPR") ++ or %2, %1, %1 ++ ++/* GPRE exists solely to allow us to use regvar() (which can only be used in ++ an expression) as a register constant. */ ++ ++ from GPR to GPRE ++ gen ++ COMMENT("move GPR->GPRE") ++ or %2, %1, %1 ++ ++/* Constants */ ++ ++ from CONST smalls(%val) to GPR ++ gen ++ COMMENT("move CONST->GPRE") ++ addi %2, R0, {CONST, lo(%1.val)} ++ ++ from CONST to GPR ++ gen ++ COMMENT("move CONST->GPRE") ++ addis %2, R0, {CONST, hi(%1.val)} ++ ori %2, %2, {CONST, lo(%1.val)} ++ ++ from LABEL to GPR ++ gen ++ COMMENT("move LABEL->GPR") ++ addis %2, R0, {HILABEL, %1.adr} ++ ori %2, %2, {LOLABEL, %1.adr} ++ ++/* Sign extension */ ++ ++ from SEX_B to GPR ++ gen ++ COMMENT("move SEX_B->GPR") ++ extsb %2, %1.reg ++ ++ from SEX_H to GPR ++ gen ++ COMMENT("move SEX_H->GPR") ++ extsh %2, %1.reg ++ ++/* Register + something */ ++ ++ from SUM_RC smalls(%off) to GPR ++ gen ++ COMMENT("move SUM_RC->GPR smalls") ++ addi %2, %1.reg, {CONST, lo(%1.off)} ++ ++ from SUM_RC to GPR ++ gen ++ COMMENT("move SUM_RC->GPR large") ++ addi %2, %1.reg, {CONST, los(%1.off)} ++ addis %2, %2, {CONST, his(%1.off)} ++ ++ from SUM_RR to GPR ++ gen ++ COMMENT("move SUM_RR->GPR") ++ add %2, %1.reg1, %1.reg2 ++ ++ from SUM_RR to GPR ++ gen ++ COMMENT("move SUM_RR->GPRE") ++ add %2, %1.reg1, %1.reg2 ++ ++/* Read/write byte */ ++ ++ from IND_RC_B smalls(%off) to GPR ++ gen ++ COMMENT("move IND_RC_B->GPR small") ++ lbz %2, {GPRINDIRECT, %1.reg, %1.off} ++ ++ from IND_RC_B to GPR ++ gen ++ COMMENT("move IND_RC_B->GPR large") ++ addis SCRATCH, %1.reg, {CONST, his(%1.off)} ++ lbz %2, {GPRINDIRECT, SCRATCH, los(%1.off)} ++ ++ from GPR to IND_RC_B smalls(%off) ++ gen ++ COMMENT("move GPR->IND_RC_B small") ++ stb %1, {GPRINDIRECT, %2.reg, %2.off} ++ ++ from GPR to IND_RC_B ++ gen ++ COMMENT("move GPR->IND_RC_B large") ++ addis SCRATCH, %2.reg, {CONST, his(%2.off)} ++ stb %1, {GPRINDIRECT, SCRATCH, los(%2.off)} ++ ++/* Read/write short */ ++ ++ from IND_RC_H smalls(%off) to GPR ++ gen ++ COMMENT("move IND_RC_H->GPR small") ++ lhz %2, {GPRINDIRECT, %1.reg, %1.off} ++ ++ from IND_RC_H to GPR ++ gen ++ COMMENT("move IND_RC_H->GPR large") ++ addis SCRATCH, %1.reg, {CONST, his(%1.off)} ++ lhz %2, {GPRINDIRECT, SCRATCH, los(%1.off)} ++ ++ from IND_RC_H_S smalls(%off) to GPR ++ gen ++ COMMENT("move IND_RC_H_S->GPR small") ++ lha %2, {GPRINDIRECT, %1.reg, %1.off} ++ ++ from IND_RC_H_S to GPR ++ gen ++ COMMENT("move IND_RC_H_S->GPR large") ++ addis SCRATCH, %1.reg, {CONST, his(%1.off)} ++ lha %2, {GPRINDIRECT, SCRATCH, los(%1.off)} ++ ++ from GPR to IND_RC_H smalls(%off) ++ gen ++ COMMENT("move GPR->IND_RC_H small") ++ sth %1, {GPRINDIRECT, %2.reg, %2.off} ++ ++ from GPR to IND_RC_H ++ gen ++ COMMENT("move GPR->IND_RC_H large") ++ addis SCRATCH, %2.reg, {CONST, his(%2.off)} ++ sth %1, {GPRINDIRECT, SCRATCH, los(%2.off)} ++ ++/* Read word */ ++ ++ from IND_RC_W smalls(%off) to GPR ++ gen ++ COMMENT("move IND_RC_W->GPR small") ++ lwz %2, {GPRINDIRECT, %1.reg, %1.off} ++ ++ from IND_RC_W to GPR ++ gen ++ COMMENT("move IND_RC_W->GPR large") ++ addis %2, %1.reg, {CONST, his(%1.off)} ++ lwz %2, {GPRINDIRECT, %2, los(%1.off)} ++ ++ from IND_RR_W to GPR ++ gen ++ COMMENT("move IND_RR_W->GPR") ++ lwzx %2, %1.reg1, %1.reg2 ++ ++ from IND_LABEL_W to GPR ++ gen ++ COMMENT("move IND_LABEL_W->GPR") ++ move {LABEL, %1.adr}, SCRATCH ++ lwz %2, {GPRINDIRECT, SCRATCH, 0} ++ ++ from IND_RC_W smalls(%off) to FS ++ gen ++ COMMENT("move IND_RC_W->FS small") ++ lfs %2, {GPRINDIRECT, %1.reg, %1.off} ++ ++ from IND_RC_W to FS ++ gen ++ COMMENT("move IND_RC_W->FS large") ++ addis SCRATCH, %1.reg, {CONST, his(%1.off)} ++ lfs %2, {GPRINDIRECT, SCRATCH, los(%1.off)} ++ ++ from IND_RR_W to FS ++ gen ++ COMMENT("move IND_RR_W->FS") ++ lfsx %2, %1.reg1, %1.reg2 ++ ++ from IND_LABEL_W to FS ++ gen ++ COMMENT("move IND_LABEL_W->FS") ++ move {LABEL, %1.adr}, SCRATCH ++ lfs %2, {GPRINDIRECT, SCRATCH, 0} ++ ++/* Write word */ ++ ++ from GPR to IND_RC_W smalls(%off) ++ gen ++ COMMENT("move GPR->IND_RC_W small") ++ stw %1, {GPRINDIRECT, %2.reg, %2.off} ++ ++ from GPR to IND_RC_W ++ gen ++ COMMENT("move GPR->IND_RC_W large") ++ addis SCRATCH, %2.reg, {CONST, his(%2.off)} ++ stw %1, {GPRINDIRECT, SCRATCH, los(%2.off)} ++ ++ from GPR to IND_RR_W ++ gen ++ COMMENT("move GPR->IND_RR_W") ++ stwx %1, %2.reg1, %2.reg2 ++ ++ from GPR to IND_LABEL_W ++ gen ++ COMMENT("move GPR->IND_LABEL_D") ++ move {LABEL, %2.adr}, SCRATCH ++ stw %1, {GPRINDIRECT, SCRATCH, 0} ++ ++ from FS to IND_RC_W smalls(%off) ++ gen ++ COMMENT("move FS->IND_RC_W small") ++ stfs %1, {GPRINDIRECT, %2.reg, %2.off} ++ ++ from FS to IND_RC_W ++ gen ++ COMMENT("move FS->IND_RC_W large") ++ addis SCRATCH, %2.reg, {CONST, his(%2.off)} ++ stfs %1, {GPRINDIRECT, SCRATCH, los(%2.off)} ++ ++ from FS to IND_RR_W ++ gen ++ COMMENT("move FS->IND_RR_W") ++ stfsx %1, %2.reg1, %2.reg2 ++ ++ from FS to IND_LABEL_W ++ gen ++ COMMENT("move FS->IND_LABEL_D") ++ move {LABEL, %2.adr}, SCRATCH ++ stfs %1, {GPRINDIRECT, SCRATCH, 0} ++ ++/* Read double */ ++ ++ from IND_RC_D smalls(%off) to FD ++ gen ++ COMMENT("move IND_RC_D->FD small") ++ lfd %2, {GPRINDIRECT, %1.reg, %1.off} ++ ++ from IND_RC_D to FD ++ gen ++ COMMENT("move IND_RC_D->FD large") ++ addis SCRATCH, %1.reg, {CONST, his(%1.off)} ++ lfd %2, {GPRINDIRECT, SCRATCH, los(%1.off)} ++ ++ from IND_RR_D to FD ++ gen ++ COMMENT("move IND_RR_D->FD") ++ lfdx %2, %1.reg1, %1.reg2 ++ ++ from IND_LABEL_D to FD ++ gen ++ COMMENT("move IND_LABEL_D->FD") ++ move {LABEL, %1.adr}, SCRATCH ++ lfd %2, {GPRINDIRECT, SCRATCH, 0} ++ ++/* Write double */ ++ ++ from FD to IND_RC_D smalls(%off) ++ gen ++ COMMENT("move FD->IND_RC_D small") ++ stfd %1, {GPRINDIRECT, %2.reg, %2.off} ++ ++ from FD to IND_RC_D ++ gen ++ COMMENT("move FD->IND_RC_D large") ++ addis SCRATCH, %2.reg, {CONST, his(%2.off)} ++ stfd %1, {GPRINDIRECT, SCRATCH, los(%2.off)} ++ ++ from FD to IND_RR_D ++ gen ++ COMMENT("move FD->IND_RR_W") ++ stfdx %1, %2.reg1, %2.reg2 ++ ++ from FD to IND_LABEL_D ++ gen ++ COMMENT("move FD->IND_LABEL_D") ++ move {LABEL, %2.adr}, SCRATCH ++ stfd %1, {GPRINDIRECT, SCRATCH, 0} ++ ++/* Extract condition code field (actually produces (CC&3)<<2) */ ++ ++ from CR0 to GPR ++ gen ++ COMMENT("move CR0->GPR") ++ mfcr %2 ++ rlwinm %2, %2, {CONST, 4}, {CONST, 32-4}, {CONST, 31-2} ++ ++/* Comparisons */ ++ ++ from TRISTATE_RR_S to CR0 ++ gen ++ cmp %2, {CONST, 0}, %1.reg1, %1.reg2 ++ ++ from TRISTATE_RR_U to CR0 ++ gen ++ cmpl %2, {CONST, 0}, %1.reg1, %1.reg2 ++ ++ from TRISTATE_RC_S to CR0 ++ gen ++ COMMENT("move TRISTATE_RC_S->CR0 large") ++ move {CONST, %1.val}, SCRATCH ++ cmp %2, {CONST, 0}, %1.reg, SCRATCH ++ ++ from TRISTATE_RC_U smallu(%val) to CR0 ++ gen ++ COMMENT("move TRISTATE_RC_U->CR0 small") ++ cmpli %2, {CONST, 0}, %1.reg, {CONST, %1.val} ++ ++ from TRISTATE_RC_U to CR0 ++ gen ++ COMMENT("move TRISTATE_RC_U->CR0") ++ move {CONST, %1.val}, SCRATCH ++ cmpl %2, {CONST, 0}, %1.reg, SCRATCH ++ ++ from TRISTATE_FF to CR0 ++ gen ++ COMMENT("move TRISTATE_FF->CR0") ++ fcmpo %2, {FD, %1.reg1}, {FD, %1.reg2} ++ ++ from GPR to CR0 ++ gen ++ COMMENT("move GPR->CR0") ++ orX SCRATCH, %1, %1 /* alas, can't call test */ ++ ++ from TRISTATE_RR_S + TRISTATE_RC_S + TRISTATE_FF to GPR ++ gen ++ COMMENT("move TRISTATE_R*_S->GPR") ++ move %1, C0 ++ move C0, SCRATCH ++ move {LABEL, ".tristate_s_table"}, %2 ++ lwzx %2, %2, SCRATCH ++ ++ from TRISTATE_RR_U + TRISTATE_RC_U to GPR ++ gen ++ COMMENT("move TRISTATE_R*_U->GPR") ++ move %1, C0 ++ move C0, SCRATCH ++ move {LABEL, ".tristate_u_table"}, %2 ++ lwzx %2, %2, SCRATCH ++ ++/* Logicals */ ++ ++ from NOT_R to GPR ++ gen ++ COMMENT("move NOT_R->GPR") ++ nor %2, %1.reg, %1.reg ++ ++ from AND_RR to GPR ++ gen ++ COMMENT("move AND_RR->GPR") ++ and %2, %1.reg1, %1.reg2 ++ ++ from AND_RC smallu(%val) to GPR ++ gen ++ COMMENT("move AND_RC->GPR small") ++ andiX %2, %1.reg, {CONST, %1.val} ++ ++ from AND_RC to GPR ++ gen ++ COMMENT("move AND_RC->GPR") ++ move {CONST, %1.val}, SCRATCH ++ and %2, %1.reg, SCRATCH ++ ++ from OR_RR to GPR ++ gen ++ COMMENT("move OR_RR->GPR") ++ or %2, %1.reg1, %1.reg2 ++ ++ from OR_RC smallu(%val) to GPR ++ gen ++ COMMENT("move OR_RC->GPR small") ++ ori %2, %1.reg, {CONST, %1.val} ++ ++ from OR_RC to GPR ++ gen ++ COMMENT("move OR_RC->GPR") ++ move {CONST, %1.val}, SCRATCH ++ or %2, %1.reg, SCRATCH ++ ++ from XOR_RR to GPR ++ gen ++ COMMENT("move XOR_RR->GPR") ++ xor %2, %1.reg1, %1.reg2 ++ ++ from XOR_RC smallu(%val) to GPR ++ gen ++ COMMENT("move XOR_RC->GPR small") ++ xori %2, %1.reg, {CONST, %1.val} ++ ++ from XOR_RC to GPR ++ gen ++ COMMENT("move XOR_RC->GPR") ++ move {CONST, %1.val}, SCRATCH ++ xor %2, %1.reg, SCRATCH ++ ++/* Miscellaneous */ ++ ++ from OP_ALL_W + LABEL + CONST to GPRE ++ gen ++ move %1, %2.reg ++ ++ ++TESTS ++ ++ to test GPR ++ gen ++ orX SCRATCH, %1, %1 ++ ++ ++ ++STACKINGRULES ++ ++ from GPR to STACK ++ gen ++ COMMENT("stack GPR") ++ stwu %1, {GPRINDIRECT, SP, 0-4} ++ ++ from CONST to STACK ++ uses REG ++ gen ++ COMMENT("stack CONST") ++ move %1, %a ++ stwu %a, {GPRINDIRECT, SP, 0-4} ++ ++ from LABEL to STACK ++ uses REG ++ gen ++ COMMENT("stack LABEL") ++ move %1, {GPRE, %a} ++ stwu %a, {GPRINDIRECT, SP, 0-4} ++ ++ from SEX_B to STACK ++ gen ++ COMMENT("stack SEX_B") ++ extsb SCRATCH, %1.reg ++ stwu SCRATCH, {GPRINDIRECT, SP, 0-4} ++ ++ from SEX_H to STACK ++ gen ++ COMMENT("stack SEX_H") ++ extsh SCRATCH, %1.reg ++ stwu SCRATCH, {GPRINDIRECT, SP, 0-4} ++ ++ from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL to STACK ++ gen ++ move %1, {GPRE, SCRATCH} ++ stwu SCRATCH, {GPRINDIRECT, SP, 0-4} ++ ++ from IND_ALL_W to STACK ++ gen ++ move %1, SCRATCH ++ stwu SCRATCH, {GPRINDIRECT, SP, 0-4} ++ ++ from IND_ALL_D to STACK ++ gen ++ move %1, {FD, FSCRATCH} ++ stfdu {FD, FSCRATCH}, {GPRINDIRECT, SP, 0-8} ++ ++ from FD to STACK ++ gen ++ COMMENT("stack FD") ++ stfdu %1, {GPRINDIRECT, SP, 0-8} ++ ++ from FS to STACK ++ gen ++ COMMENT("stack FS") ++ stfsu %1, {GPRINDIRECT, SP, 0-4} ++ ++ from TOKEN to STACK ++ gen ++ invalid. ++ ++ ++ ++COERCIONS ++ ++ from REG ++ uses REG ++ gen ++ COMMENT("coerce REG->REG") ++ move %1, %a ++ yields %a ++ ++ from CONST ++ uses REG ++ gen ++ COMMENT("coerce CONST->REG") ++ move %1, %a ++ yields %a ++ ++ from LABEL ++ uses REG ++ gen ++ COMMENT("coerce LABEL->REG") ++ move %1, {GPRE, %a} ++ yields %a ++ ++ from STACK ++ uses REG ++ gen ++ COMMENT("coerce STACK->REG") ++ lwz %a, {GPRINDIRECT, SP, 0} ++ addi SP, SP, {CONST, 4} ++ yields %a ++ ++ from SEX_B ++ uses REG ++ gen ++ COMMENT("coerce SEX_B->REG") ++ extsb %a, %1.reg ++ yields %a ++ ++ from SEX_H ++ uses REG ++ gen ++ COMMENT("coerce SEX_H->REG") ++ extsh %a, %1.reg ++ yields %a ++ ++ from SUM_ALL + TRISTATE_ALL + LOGICAL_ALL ++ uses REG ++ gen ++ move %1, {GPRE, %a} ++ yields %a ++ ++ from FS ++ uses FREG ++ gen ++ fmr {FS, %a}, %1 ++ yields {FS, %a} ++ ++ from FD ++ uses FREG ++ gen ++ fmr {FD, %a}, %1 ++ yields {FD, %a} ++ ++ from STACK ++ uses FREG ++ gen ++ COMMENT("coerce STACK->FD") ++ lfd {FD, %a}, {GPRINDIRECT, SP, 0} ++ addi SP, SP, {CONST, 8} ++ yields {FD, %a} ++ ++ from STACK ++ uses FREG ++ gen ++ COMMENT("coerce STACK->FS") ++ lfs {FS, %a}, {GPRINDIRECT, SP, 0} ++ addi SP, SP, {CONST, 4} ++ yields {FS, %a} ++ ++ from IND_ALL_W ++ uses REG ++ gen ++ move %1, %a ++ yields %a ++ ++ from IND_ALL_W ++ uses FREG ++ gen ++ move %1, {FS, %a} ++ yields {FS, %a} ++ ++ from IND_ALL_D ++ uses FREG ++ gen ++ move %1, {FD, %a} ++ yields {FD, %a} ++ ++ ++ ++ ++PATTERNS ++ ++/* Intrinsics */ ++ ++ pat loc /* Load constant */ ++ yields {CONST, $1} ++ ++ pat dup $1==INT32 /* Duplicate word on top of stack */ ++ with GPR ++ yields %1 %1 ++ ++ pat dup $1==INT64 /* Duplicate double-word on top of stack */ ++ with GPR GPR ++ yields %2 %1 %2 %1 ++ ++ pat exg $1==INT32 /* Exchange top two words on stack */ ++ with GPR GPR ++ yields %1 %2 ++ ++ pat stl lol $1==$2 /* Store then load local */ ++ leaving ++ dup 4 ++ stl $1 ++ ++ pat lal sti lal loi $1==$3 && $2==$4 /* Store then load local, of a different size */ ++ leaving ++ dup INT32 ++ lal $1 ++ sti $2 ++ ++ pat ste loe $1==$2 /* Store then load external */ ++ leaving ++ dup 4 ++ ste $1 ++ ++ ++/* Type conversions */ ++ ++ pat loc loc cii loc loc cii $1==$4 && $2==$5 /* madness, generated by the C compiler */ ++ leaving ++ loc $1 ++ loc $2 ++ cii ++ ++ pat loc loc cii loc loc cii $2==INT32 && $5==INT32 && $4<$2 /* madness, generated by the C compiler */ ++ leaving ++ loc $4 ++ loc $5 ++ cii ++ ++ pat loc loc ciu /* signed X -> unsigned X */ ++ leaving ++ loc $1 ++ loc $2 ++ cuu ++ ++ pat loc loc cuu $1==$2 /* unsigned X -> unsigned X */ ++ /* nop */ ++ ++ pat loc loc cii $1==$2 /* signed X -> signed X */ ++ /* nop */ ++ ++ pat loc loc cui $1==$2 /* unsigned X -> signed X */ ++ /* nop */ ++ ++ pat loc loc cui $1==INT8 && $2==INT32 /* unsigned char -> signed int */ ++ /* nop */ ++ ++ pat loc loc cui $1==INT16 && $2==INT32 /* unsigned short -> signed int */ ++ /* nop */ ++ ++ pat loc loc cii $1==INT8 && $2==INT32 /* signed char -> signed int */ ++ with GPR ++ yields {SEX_B, %1} ++ ++ pat loc loc cii $1==2 && $2==4 /* signed char -> signed short */ ++ with GPR ++ yields {SEX_H, %1} ++ ++ ++ ++ ++ ++/* Local variables */ ++ ++ pat lal /* Load address of local */ ++ yields {SUM_RC, FP, $1} ++ ++ pat lol inreg($1)>0 /* Load from local */ ++ yields {LOCAL, $1} ++ ++ pat lol /* Load from local */ ++ leaving ++ lal $1 ++ loi INT32 ++ ++ pat ldl /* Load double-word from local */ ++ leaving ++ lal $1 ++ loi INT32*2 ++ ++ pat stl inreg($1)>0 /* Store to local */ ++ with CONST + LABEL + GPR + OP_ALL_W ++ kills regvar($1), LOCAL %off==$1 ++ gen ++ move %1, {GPRE, regvar($1)} ++ ++ pat stl /* Store to local */ ++ leaving ++ lal $1 ++ sti INT32 ++ ++ pat sdl /* Store double-word to local */ ++ leaving ++ lal $1 ++ sti INT32*2 ++ ++ pat lil inreg($1)>0 /* Load from indirected local */ ++ uses REG ++ gen ++ lwz %a, {GPRINDIRECT, regvar($1), 0} ++ yields %a ++ ++ pat lil /* Load from indirected local */ ++ leaving ++ lol $1 ++ loi INT32 ++ ++ pat sil /* Save to indirected local */ ++ leaving ++ lol $1 ++ sti INT32 ++ ++ pat stl lol $1==$2 /* Save then load (generated by C compiler) */ ++ leaving ++ dup 4 ++ stl $1 ++ ++ pat zrl /* Zero local */ ++ leaving ++ loc 0 ++ stl $1 ++ ++ pat inl /* Increment local */ ++ leaving ++ lol $1 ++ loc 1 ++ adi 4 ++ stl $1 ++ ++ pat del /* Decrement local */ ++ leaving ++ lol $1 ++ loc 1 ++ sbi 4 ++ stl $1 ++ ++ ++/* Global variables */ ++ ++ pat lpi /* Load address of external function */ ++ leaving ++ lae $1 ++ ++ pat lae /* Load address of external */ ++ yields {LABEL, $1} ++ ++ pat loe /* Load word external */ ++ leaving ++ lae $1 ++ loi INT32 ++ ++ pat ste /* Store word external */ ++ leaving ++ lae $1 ++ sti INT32 ++ ++ pat lde /* Load double-word external */ ++ leaving ++ lae $1 ++ loi INT64 ++ ++ pat sde /* Store double-word external */ ++ leaving ++ lae $1 ++ sti INT64 ++ ++ pat zre /* Zero external */ ++ leaving ++ loc 0 ++ ste $1 ++ ++ pat ine /* Increment external */ ++ uses REG={LABEL, $1}, REG ++ gen ++ lwz %b, {GPRINDIRECT, %a, 0} ++ addi %b, %b, {CONST, 1} ++ stw %b, {GPRINDIRECT, %a, 0} ++ ++ pat dee /* Decrement external */ ++ uses REG={LABEL, $1}, REG ++ gen ++ lwz %b, {GPRINDIRECT, %a, 0} ++ addi %b, %b, {CONST, 0-1} ++ stw %b, {GPRINDIRECT, %a, 0} ++ ++ ++ ++/* Structures */ ++ ++ pat lof /* Load word offsetted */ ++ leaving ++ adp $1 ++ loi INT32 ++ ++ pat ldf /* Load double-word offsetted */ ++ leaving ++ adp $1 ++ loi INT64 ++ ++ pat stf /* Store word offsetted */ ++ leaving ++ adp $1 ++ sti INT32 ++ ++ pat sdf /* Store double-word offsetted */ ++ leaving ++ adp $1 ++ sti INT64 ++ ++ ++ ++/* Loads and stores */ ++ ++ pat loi $1==INT8 /* Load byte indirect */ ++ with GPR ++ uses REG ++ gen ++ lbz %a, {GPRINDIRECT, %1, 0} ++ yields %a ++ with SUM_RR ++ uses reusing %1, REG ++ gen ++ lbzx %a, %1.reg1, %1.reg2 ++ yields %a ++ with SUM_RC ++ uses REG ++ gen ++ move {IND_RC_B, %1.reg, %1.off}, %a ++ yields %a ++ ++ pat loi loc loc cii $1==INT16 && $2==INT16 && $3==INT32 /* Load half-word indirect and sign extend */ ++ with GPR ++ uses REG ++ gen ++ lha %a, {GPRINDIRECT, %1, 0} ++ yields %a ++ with SUM_RR ++ uses reusing %1, REG ++ gen ++ lhax %a, %1.reg1, %1.reg2 ++ yields %a ++ with SUM_RC ++ uses REG ++ gen ++ move {IND_RC_H_S, %1.reg, %1.off}, %a ++ yields %a ++ ++ pat loi $1==INT16 /* Load half-word indirect */ ++ with GPR ++ uses REG ++ gen ++ lhz %a, {GPRINDIRECT, %1, 0} ++ yields %a ++ with SUM_RR ++ uses reusing %1, REG ++ gen ++ lhzx %a, %1.reg1, %1.reg2 ++ yields %a ++ with SUM_RC ++ uses REG ++ gen ++ move {IND_RC_H, %1.reg, %1.off}, %a ++ yields %a ++ ++ pat loi $1==INT32 /* Load word indirect */ ++ with GPR ++ yields {IND_RC_W, %1, 0} ++ with SUM_RC ++ yields {IND_RC_W, %1.reg, %1.off} ++ with SUM_RR ++ yields {IND_RR_W, %1.reg1, %1.reg2} ++ with LABEL ++ yields {IND_LABEL_W, %1.adr} ++ ++ pat loi $1==INT64 /* Load double-word indirect */ ++ with GPR ++ yields {IND_RC_D, %1, 0} ++ with SUM_RC ++ yields {IND_RC_D, %1.reg, %1.off} ++ with SUM_RR ++ yields {IND_RR_D, %1.reg1, %1.reg2} ++ with LABEL ++ yields {IND_LABEL_D, %1.adr} ++ ++ pat loi /* Load arbitrary size */ ++ leaving ++ loc $1 ++ los INT32 ++ ++ pat los /* Load arbitrary size */ ++ with GPR3 GPR4 STACK ++ kills ALL ++ gen ++ bl {LABEL, ".los"} ++ ++ pat sti $1==INT8 /* Store byte indirect */ ++ with GPR GPR ++ gen ++ stb %2, {GPRINDIRECT, %1, 0} ++ with SUM_RR GPR ++ gen ++ stbx %2, %1.reg1, %1.reg2 ++ with SUM_RC GPR ++ gen ++ move %2, {IND_RC_B, %1.reg, %1.off} ++ with GPR SEX_B ++ gen ++ stb %2.reg, {GPRINDIRECT, %1, 0} ++ with SUM_RR SEX_B ++ gen ++ stbx %2.reg, %1.reg1, %1.reg2 ++ with SUM_RC SEX_B ++ gen ++ move %2.reg, {IND_RC_B, %1.reg, %1.off} ++ ++ pat sti $1==INT16 /* Store half-word indirect */ ++ with GPR GPR ++ gen ++ sth %2, {GPRINDIRECT, %1, 0} ++ with SUM_RR GPR ++ gen ++ sthx %2, %1.reg1, %1.reg2 ++ with SUM_RC GPR ++ gen ++ move %2, {IND_RC_H, %1.reg, %1.off} ++ with GPR SEX_H ++ gen ++ sth %2.reg, {GPRINDIRECT, %1, 0} ++ with SUM_RR SEX_H ++ gen ++ sthx %2.reg, %1.reg1, %1.reg2 ++ with SUM_RC SEX_H ++ gen ++ move %2.reg, {IND_RC_H, %1.reg, %1.off} ++ ++ pat sti $1==INT32 /* Store word indirect */ ++ with GPR GPR+FS ++ gen ++ move %2, {IND_RC_W, %1, 0} ++ with SUM_RR GPR+FS ++ gen ++ move %2, {IND_RR_W, %1.reg1, %1.reg2} ++ with SUM_RC GPR+FS ++ gen ++ move %2, {IND_RC_W, %1.reg, %1.off} ++ with LABEL GPR+FS ++ gen ++ move %2, {IND_LABEL_W, %1.adr} ++ ++ pat sti $1==INT64 /* Store double-word indirect */ ++ with GPR FD ++ gen ++ move %2, {IND_RC_D, %1, 0} ++ with SUM_RR FD ++ gen ++ move %2, {IND_RR_D, %1.reg1, %1.reg2} ++ with SUM_RC FD ++ gen ++ move %2, {IND_RC_D, %1.reg, %1.off} ++ with GPR GPR GPR ++ gen ++ stw %2, {GPRINDIRECT, %1, 0} ++ stw %3, {GPRINDIRECT, %1, 4} ++ with SUM_RC GPR GPR ++ gen ++ move %2, {IND_RC_W, %1.reg, %1.off} ++ move %3, {IND_RC_W, %1.reg, %1.off+4} ++ with LABEL FD ++ gen ++ move %2, {IND_LABEL_D, %1.adr} ++ ++ ++ pat sti /* Store arbitrary size */ ++ leaving ++ loc $1 ++ sts INT32 ++ ++ pat sts /* Load arbitrary size */ ++ with GPR3 GPR4 STACK ++ kills ALL ++ gen ++ bl {LABEL, ".sts"} ++ ++ ++ ++/* Arithmetic wrappers */ ++ ++ pat ads $1==4 /* Add var to pointer */ ++ leaving adi $1 ++ ++ pat sbs $1==4 /* Subtract var from pointer */ ++ leaving sbi $1 ++ ++ pat adp /* Add constant to pointer */ ++ leaving ++ loc $1 ++ adi 4 ++ ++ pat adu /* Add unsigned */ ++ leaving ++ adi $1 ++ ++ pat sbu /* Subtract unsigned */ ++ leaving ++ sbi $1 ++ ++ pat inc /* Add 1 */ ++ leaving ++ loc 1 ++ adi 4 ++ ++ pat dec /* Subtract 1 */ ++ leaving ++ loc 1 ++ sbi 4 ++ ++ pat loc mlu $2==2 /* Unsigned multiply by constant */ ++ leaving ++ loc $1 ++ mli 4 ++ ++ pat mlu /* Unsigned multiply by var */ ++ leaving ++ mli $1 ++ ++ pat loc slu /* Shift left unsigned by constant amount */ ++ leaving ++ loc $1 ++ sli $2 ++ ++ pat slu /* Shift left unsigned by variable amount */ ++ leaving ++ sli $1 ++ ++ ++ ++/* Word arithmetic */ ++ ++ pat adi $1==4 /* Add word (second + top) */ ++ with REG REG ++ yields {SUM_RR, %1, %2} ++ with CONST REG ++ yields {SUM_RC, %2, %1.val} ++ with REG CONST ++ yields {SUM_RC, %1, %2.val} ++ with CONST SUM_RC ++ yields {SUM_RC, %2.reg, %2.off+%1.val} ++ with CONST LABEL ++ yields {LABEL, %2.adr+%1.val} ++ ++ pat sbi $1==4 /* Subtract word (second - top) */ ++ with REG REG ++ uses reusing %2, REG ++ gen ++ subf %a, %1, %2 ++ yields %a ++ with CONST REG ++ yields {SUM_RC, %2, 0-%1.val} ++ with CONST SUM_RC ++ yields {SUM_RC, %2.reg, %2.off-%1.val} ++ with CONST LABEL ++ yields {LABEL, %2.adr+(0-%1.val)} ++ ++ pat ngi $1==4 /* Negate word */ ++ with REG ++ uses reusing %1, REG ++ gen ++ neg %a, %1 ++ yields %a ++ ++ pat mli $1==4 /* Multiply word (second * top) */ ++ with REG REG ++ uses reusing %2, REG ++ gen ++ mullw %a, %2, %1 ++ yields %a ++ ++ pat dvi $1==4 /* Divide word (second / top) */ ++ with REG REG ++ uses reusing %2, REG ++ gen ++ divw %a, %2, %1 ++ yields %a ++ ++ pat dvu $1==4 /* Divide unsigned word (second / top) */ ++ with REG REG ++ uses reusing %2, REG ++ gen ++ divwu %a, %2, %1 ++ yields %a ++ ++ pat rmi $1==4 /* Remainder word (second % top) */ ++ with REG REG ++ uses REG ++ gen ++ divw %a, %2, %1 ++ mullw %a, %a, %1 ++ subf %a, %a, %2 ++ yields %a ++ ++ pat rmu $1==4 /* Remainder unsigned word (second % top) */ ++ with REG REG ++ uses REG ++ gen ++ divwu %a, %2, %1 ++ mullw %a, %a, %1 ++ subf %a, %a, %2 ++ yields %a ++ ++ pat and $1==4 /* AND word */ ++ with GPR NOT_R ++ uses reusing %1, REG ++ gen ++ andc %a, %1, %2.reg ++ yields %a ++ with NOT_R GPR ++ uses reusing %1, REG ++ gen ++ andc %a, %2, %1.reg ++ yields %a ++ with GPR GPR ++ yields {AND_RR, %1, %2} ++ with GPR CONST ++ yields {AND_RC, %1, %2.val} ++ with CONST GPR ++ yields {AND_RC, %2, %1.val} ++ ++ pat and !defined($1) /* AND set */ ++ with STACK ++ gen ++ bl {LABEL, ".and"} ++ ++ pat ior $1==4 /* OR word */ ++ with GPR NOT_R ++ uses reusing %1, REG ++ gen ++ orc %a, %1, %2.reg ++ yields %a ++ with NOT_R GPR ++ uses reusing %2, REG ++ gen ++ orc %a, %2, %1.reg ++ yields %a ++ with GPR GPR ++ yields {OR_RR, %1, %2} ++ with GPR CONST ++ yields {OR_RC, %1, %2.val} ++ with CONST GPR ++ yields {OR_RC, %2, %1.val} ++ ++ pat ior !defined($1) /* OR set */ ++ with STACK ++ gen ++ bl {LABEL, ".ior"} ++ ++ pat xor $1==4 /* XOR word */ ++ with GPR GPR ++ yields {XOR_RR, %1, %2} ++ with GPR CONST ++ yields {XOR_RC, %1, %2.val} ++ with CONST GPR ++ yields {XOR_RC, %2, %1.val} ++ ++ pat xor !defined($1) /* XOR set */ ++ with STACK ++ gen ++ bl {LABEL, ".xor"} ++ ++ pat com $1==INT32 /* NOT word */ ++ with AND_RR ++ uses REG ++ gen ++ nand %a, %1.reg1, %1.reg2 ++ yields %a ++ with OR_RR ++ uses REG ++ gen ++ nor %a, %1.reg1, %1.reg2 ++ yields %a ++ with XOR_RR ++ uses REG ++ gen ++ eqv %a, %1.reg1, %1.reg2 ++ yields %a ++ with GPR ++ yields {NOT_R, %1} ++ ++ pat com !defined($1) /* NOT set */ ++ with STACK ++ gen ++ bl {LABEL, ".com"} ++ ++ pat sli $1==4 /* Shift left (second << top) */ ++ with CONST GPR ++ uses reusing %2, REG ++ gen ++ rlwinm %a, %2, {CONST, (%1.val & 0x1F)}, {CONST, 0}, {CONST, 31-(%1.val & 0x1F)} ++ yields %a ++ with GPR GPR ++ uses reusing %2, REG ++ gen ++ slw %a, %2, %1 ++ yields %a ++ ++ pat sri $1==4 /* Shift right signed (second >> top) */ ++ with CONST GPR ++ uses reusing %2, REG ++ gen ++ srawi %a, %2, {CONST, %1.val & 0x1F} ++ yields %a ++ with GPR GPR ++ uses reusing %2, REG ++ gen ++ sraw %a, %2, %1 ++ yields %a ++ ++ pat sru $1==4 /* Shift right unsigned (second >> top) */ ++ with CONST GPR ++ uses reusing %2, REG ++ gen ++ rlwinm %a, %2, {CONST, 32-(%1.val & 0x1F)}, {CONST, (%1.val & 0x1F)}, {CONST, 31} ++ yields %a ++ with GPR GPR ++ uses reusing %2, REG ++ gen ++ srw %a, %2, %1 ++ yields %a ++ ++ ++ ++/* Arrays */ ++ ++ pat aar $1==INT32 /* Index array */ ++ with GPR3 GPR4 GPR5 ++ gen ++ bl {LABEL, ".aar4"} ++ yields R3 ++ ++ pat lae lar $2==INT32 && nicesize(rom($1, 3)) /* Load array */ ++ leaving ++ lae $1 ++ aar INT32 ++ loi rom($1, 3) ++ ++ pat lar $1==INT32 /* Load array */ ++ with GPR3 GPR4 GPR5 STACK ++ kills ALL ++ gen ++ bl {LABEL, ".lar4"} ++ ++ pat lae sar $2==INT32 && nicesize(rom($1, 3)) /* Store array */ ++ leaving ++ lae $1 ++ aar INT32 ++ sti rom($1, 3) ++ ++ pat sar $1==INT32 /* Store array */ ++ with GPR3 GPR4 GPR5 STACK ++ kills ALL ++ gen ++ bl {LABEL, ".sar4"} ++ ++ ++ ++ ++/* Sets */ ++ ++ pat set defined($1) /* Create word with set bit */ ++ leaving ++ loc 1 ++ exg INT32 ++ sli INT32 ++ ++ pat set !defined($1) /* Create structure with set bit (variable) */ ++ with GPR3 GPR4 STACK ++ gen ++ bl {LABEL, ".set"} ++ ++ pat inn defined($1) /* Test for set bit */ ++ leaving ++ set INT32 ++ and INT32 ++ ++ pat inn !defined($1) /* Test for set bit (variable) */ ++ with GPR3 STACK ++ gen ++ bl {LABEL, ".inn"} ++ ++ ++ ++/* Boolean resolutions */ ++ ++ pat teq /* top = (top == 0) */ ++ with TRISTATE_ALL + GPR ++ uses reusing %1, REG ++ gen ++ move %1, C0 ++ move C0, SCRATCH ++ move {LABEL, ".teq_table"}, %a ++ lwzx %a, %a, SCRATCH ++ yields %a ++ ++ pat tne /* top = (top != 0) */ ++ with TRISTATE_ALL + GPR ++ uses reusing %1, REG ++ gen ++ move %1, C0 ++ move C0, SCRATCH ++ move {LABEL, ".tne_table"}, %a ++ lwzx %a, %a, SCRATCH ++ yields %a ++ ++ pat tlt /* top = (top < 0) */ ++ with TRISTATE_ALL + GPR ++ uses reusing %1, REG ++ gen ++ move %1, C0 ++ move C0, SCRATCH ++ move {LABEL, ".tlt_table"}, %a ++ lwzx %a, %a, SCRATCH ++ yields %a ++ ++ pat tle /* top = (top <= 0) */ ++ with TRISTATE_ALL + GPR ++ uses reusing %1, REG ++ gen ++ move %1, C0 ++ move C0, SCRATCH ++ move {LABEL, ".tle_table"}, %a ++ lwzx %a, %a, SCRATCH ++ yields %a ++ ++ pat tgt /* top = (top > 0) */ ++ with TRISTATE_ALL + GPR ++ uses reusing %1, REG ++ gen ++ move %1, C0 ++ move C0, SCRATCH ++ move {LABEL, ".tgt_table"}, %a ++ lwzx %a, %a, SCRATCH ++ yields %a ++ ++ pat tge /* top = (top >= 0) */ ++ with TRISTATE_ALL + GPR ++ uses reusing %1, REG ++ gen ++ move %1, C0 ++ move C0, SCRATCH ++ move {LABEL, ".tge_table"}, %a ++ lwzx %a, %a, SCRATCH ++ yields %a ++ ++ ++ ++ ++/* Simple branches */ ++ ++ pat zeq /* Branch if signed top == 0 */ ++ with TRISTATE_ALL+GPR STACK ++ gen ++ move %1, C0 ++ bc IFTRUE, EQ, {LABEL, $1} ++ ++ pat beq ++ leaving ++ cmi INT32 ++ zeq $1 ++ ++ pat zne /* Branch if signed top != 0 */ ++ with TRISTATE_ALL+GPR STACK ++ gen ++ move %1, C0 ++ bc IFFALSE, EQ, {LABEL, $1} ++ ++ pat bne ++ leaving ++ cmi INT32 ++ zne $1 ++ ++ pat zgt /* Branch if signed top > 0 */ ++ with TRISTATE_ALL+GPR STACK ++ gen ++ move %1, C0 ++ bc IFTRUE, GT, {LABEL, $1} ++ ++ pat bgt ++ leaving ++ cmi INT32 ++ zgt $1 ++ ++ pat zge /* Branch if signed top >= 0 */ ++ with TRISTATE_ALL+GPR STACK ++ gen ++ move %1, C0 ++ bc IFFALSE, LT, {LABEL, $1} ++ ++ pat bge ++ leaving ++ cmi INT32 ++ zge $1 ++ ++ pat zlt /* Branch if signed top < 0 */ ++ with TRISTATE_ALL+GPR STACK ++ gen ++ move %1, C0 ++ bc IFTRUE, LT, {LABEL, $1} ++ ++ pat blt ++ leaving ++ cmi INT32 ++ zlt $1 ++ ++ pat zle /* Branch if signed top >= 0 */ ++ with TRISTATE_ALL+GPR STACK ++ gen ++ move %1, C0 ++ bc IFFALSE, GT, {LABEL, $1} ++ ++ pat ble ++ leaving ++ cmi INT32 ++ zle $1 ++ ++ ++/* Compare and jump */ ++ ++ pat cmi /* Signed tristate compare */ ++ with CONST GPR ++ yields {TRISTATE_RC_S, %2, %1.val} ++ with GPR GPR ++ yields {TRISTATE_RR_S, %2, %1} ++ ++ pat cmu /* Unsigned tristate compare */ ++ with CONST GPR ++ yields {TRISTATE_RC_U, %2, %1.val} ++ with GPR GPR ++ yields {TRISTATE_RR_U, %2, %1} ++ ++ pat cmp /* Compare pointers */ ++ leaving ++ cmu INT32 ++ ++ pat cms $1==INT32 /* Compare blocks (word sized) */ ++ leaving ++ cmi INT32 ++ ++ ++ ++ ++/* Other branching and labelling */ ++ ++ pat lab topeltsize($1)==4 && !fallthrough($1) ++ gen ++ labeldef $1 ++ yields R3 ++ ++ pat lab topeltsize($1)==4 && fallthrough($1) ++ with GPR3 ++ gen ++ labeldef $1 ++ yields %1 ++ ++ pat lab topeltsize($1)!=4 ++ with STACK ++ kills ALL ++ gen ++ labeldef $1 ++ ++ pat bra topeltsize($1)==4 /* Unconditional jump with TOS GPRister */ ++ with GPR3 STACK ++ gen ++ b {LABEL, $1} ++ ++ pat bra topeltsize($1)!=4 /* Unconditional jump without TOS GPRister */ ++ with STACK ++ gen ++ b {LABEL, $1} ++ ++ ++ ++/* Miscellaneous */ ++ ++ pat cal /* Call procedure */ ++ with STACK ++ kills ALL ++ gen ++ bl {LABEL, $1} ++ ++ pat cai /* Call procedure indirect */ ++ with GPR STACK ++ kills ALL ++ gen ++ mtspr CTR, %1 ++ bcctrl ALWAYS, {CONST, 0}, {CONST, 0} ++ ++ pat lfr $1==INT32 /* Load function result, word */ ++ yields R3 ++ ++ pat lfr $1==INT64 /* Load function result, double-word */ ++ yields R4 R3 ++ ++ pat ret $1==0 /* Return from procedure */ ++ gen ++ return ++ b {LABEL, ".ret"} ++ ++ pat ret $1==INT32 /* Return from procedure, word */ ++ with GPR3 ++ gen ++ return ++ b {LABEL, ".ret"} ++ ++ pat ret $1==INT64 /* Return from procedure, double-word */ ++ with GPR3 GPR4 ++ gen ++ return ++ b {LABEL, ".ret"} ++ ++ pat blm /* Block move constant length */ ++ with GPR GPR STACK ++ uses REG ++ gen ++ move {CONST, $1}, %a ++ stwu %a, {GPRINDIRECT, SP, 0-4} ++ stwu %2, {GPRINDIRECT, SP, 0-4} ++ stwu %1, {GPRINDIRECT, SP, 0-4} ++ bl {LABEL, "_memmove"} ++ addi SP, SP, {CONST, 12} ++ ++ pat bls /* Block move variable length */ ++ with GPR GPR GPR STACK ++ gen ++ stwu %1, {GPRINDIRECT, SP, 0-4} ++ stwu %3, {GPRINDIRECT, SP, 0-4} ++ stwu %2, {GPRINDIRECT, SP, 0-4} ++ bl {LABEL, "_memmove"} ++ addi SP, SP, {CONST, 12} ++ ++ pat csa /* Array-lookup switch */ ++ with GPR3 GPR4 STACK ++ gen ++ b {LABEL, ".csa"} ++ ++ pat csb /* Table-lookup switch */ ++ with GPR3 GPR4 STACK ++ gen ++ b {LABEL, ".csb"} ++ ++ ++ ++/* EM specials */ ++ ++ pat fil /* Set current filename */ ++ leaving ++ lae $1 ++ ste ".filename" ++ ++ pat lin /* Set current line number */ ++ leaving ++ loc $1 ++ ste ".linenumber" ++ ++ pat lni /* Increment line number */ ++ leaving ++ ine ".linenumber" ++ ++ pat lim /* Load EM trap ignore mask */ ++ leaving ++ lde ".ignmask" ++ ++ pat sim /* Store EM trap ignore mask */ ++ leaving ++ ste ".ignmask" ++ ++ pat trp /* Raise EM trap */ ++ with GPR3 ++ gen ++ bl {LABEL, ".trap"} ++ ++ pat sig /* Set trap handler */ ++ leaving ++ ste ".trppc" ++ ++ pat rtt /* Return from trap */ ++ leaving ++ ret 0 ++ ++ pat lxl $1==0 /* Load FP */ ++ leaving ++ lor 0 ++ ++ pat lxl $1==1 /* Load caller's FP */ ++ leaving ++ lxl 0 ++ dch ++ ++ pat dch /* FP -> caller FP */ ++ with GPR ++ uses reusing %1, REG ++ gen ++ lwz %a, {GPRINDIRECT, %1, FP_OFFSET} ++ yields %a ++ ++ pat lpb /* Convert FP to argument address */ ++ leaving ++ adp EM_BSIZE ++ ++ pat lxa /* Load caller's SP */ ++ leaving ++ lxl $1 ++ lpb ++ ++ pat gto /* longjmp */ ++ uses REG ++ gen ++ move {LABEL, $1}, %a ++ move {IND_RC_W, %a, 8}, FP ++ move {IND_RC_W, %a, 4}, SP ++ move {IND_RC_W, %a, 0}, %a ++ mtspr CTR, %a ++ bcctr ALWAYS, {CONST, 0}, {CONST, 0} ++ ++#if 0 ++ ++ pat gto /* longjmp */ ++ with STACK ++ gen ++ ld {LABEL, $1+2} ++ wspec {CONST, 1} ++ ld {LABEL, $1+4} ++ wspec {CONST, 0} ++ ld {LABEL, $1+0} ++ wspec {CONST, 2} ++ ++ pat str $1==1 /* Store special GPRister */ ++ with GPR0 ++ gen ++ wspec {CONST, $1} ++ ++#endif ++ ++ pat lor $1==0 /* Load FP */ ++ uses REG ++ gen ++ move FP, %a ++ yields %a ++ ++ pat lor $1==1 /* Load SP */ ++ uses REG ++ gen ++ move SP, %a ++ yields %a ++ ++ pat lor $1==2 /* Load HP */ ++ leaving ++ loe ".reghp" ++ ++ pat str $1==0 /* Store FP */ ++ with GPR ++ gen ++ move %1, FP ++ ++ pat str $1==1 /* Store SP */ ++ with GPR ++ gen ++ move %1, SP ++ ++ pat str $1==2 /* Store HP */ ++ leaving ++ ste ".reghp" ++ ++ pat ass /* Adjust stack by variable amount */ ++ with CONST ++ gen ++ move {SUM_RC, SP, %1.val}, {GPRE, SP} ++ with GPR ++ gen ++ move {SUM_RR, SP, %1}, {GPRE, SP} ++ ++ pat asp /* Adjust stack by constant amount */ ++ leaving ++ loc $1 ++ ass ++ ++ ++ ++/* Floating point support */ ++ ++ /* All very cheap and nasty --- this needs to be properly integrated into ++ * the code generator. ncg doesn't like having separate FPU registers. */ ++ ++ /* Single-precision */ ++ ++ pat zrf $1==INT32 /* Push zero */ ++ leaving ++ loe ".fs_00000000" ++ ++ pat adf $1==INT32 /* Add single */ ++ with FS FS ++ uses reusing %1, FREG ++ gen ++ fadds {FS, %a}, %2, %1 ++ yields {FS, %a} ++ ++ pat sbf $1==INT32 /* Subtract single */ ++ with FS FS ++ uses reusing %1, FREG ++ gen ++ fsubs {FS, %a}, %2, %1 ++ yields {FS, %a} ++ ++ pat mlf $1==INT32 /* Multiply single */ ++ with FS FS ++ uses reusing %1, FREG ++ gen ++ fmuls {FS, %a}, %2, %1 ++ yields {FS, %a} ++ ++ pat dvf $1==INT32 /* Divide single */ ++ with FS FS ++ uses reusing %1, FREG ++ gen ++ fdivs {FS, %a}, %2, %1 ++ yields {FS, %a} ++ ++ pat ngf $1==INT32 /* Negate single */ ++ with FS ++ uses reusing %1, FREG ++ gen ++ fneg {FS, %a}, %1 ++ yields {FS, %a} ++ ++ pat cmf $1==INT32 /* Compare single */ ++ with FS FS ++ yields {TRISTATE_FF, %2.reg, %1.reg} ++ ++ pat loc loc cff $1==INT32 && $2==INT64 /* Convert single to double */ ++ with FS ++ yields {FD, %1.reg} ++ ++ pat loc loc cfu $1==INT32 && $2==INT32 /* Convert single to unsigned int */ ++ with STACK ++ gen ++ bl {LABEL, ".cfu4"} ++ ++ pat loc loc cfi $1==INT32 && $2==INT32 /* Convert single to signed int */ ++ with STACK ++ gen ++ bl {LABEL, ".cfi4"} ++ ++ pat loc loc cif $1==INT32 && $2==INT32 /* Convert integer to single */ ++ with STACK ++ gen ++ bl {LABEL, ".cif4"} ++ ++ pat loc loc cuf $1==INT32 && $2==INT32 /* Convert unsigned int to single */ ++ with STACK ++ gen ++ bl {LABEL, ".cuf4"} ++ ++ pat fef $1==INT32 /* Split single */ ++ with STACK ++ gen ++ bl {LABEL, ".fef4"} ++ ++ /* Double-precision */ ++ ++ pat zrf $1==INT64 /* Push zero */ ++ leaving ++ lde ".fd_00000000" ++ ++ pat adf $1==INT64 /* Add double */ ++ with FD FD ++ uses FREG ++ gen ++ fadd {FD, %a}, %2, %1 ++ yields {FD, %a} ++ ++ pat sbf $1==INT64 /* Subtract double */ ++ with FD FD ++ uses FREG ++ gen ++ fsub {FD, %a}, %2, %1 ++ yields {FD, %a} ++ ++ pat mlf $1==INT64 /* Multiply double */ ++ with FD FD ++ uses reusing %1, FREG ++ gen ++ fmul {FD, %a}, %2, %1 ++ yields {FD, %a} ++ ++ pat dvf $1==INT64 /* Divide double */ ++ with FD FD ++ uses reusing %1, FREG ++ gen ++ fdiv {FD, %a}, %2, %1 ++ yields {FD, %a} ++ ++ pat ngf $1==INT64 /* Negate double */ ++ with FD ++ uses reusing %1, FREG ++ gen ++ fneg {FD, %a}, %1 ++ yields {FD, %a} ++ ++ pat cmf $1==INT64 /* Compare double */ ++ with FD FD ++ yields {TRISTATE_FF, %2.reg, %1.reg} ++ ++ pat loc loc cff $1==INT64 && $2==INT32 /* Convert double to single */ ++ with FD ++ uses reusing %1, FREG ++ gen ++ frsp {FS, %a}, %1 ++ yields {FS, %a} ++ ++ pat loc loc cfu $1==INT64 && $2==INT32 /* Convert double to unsigned int */ ++ with STACK ++ gen ++ bl {LABEL, ".cfu8"} ++ ++ pat loc loc cfi $1==INT64 && $2==INT32 /* Convert double to signed int */ ++ with STACK ++ gen ++ bl {LABEL, ".cfi8"} ++ ++ pat loc loc cif $1==INT32 && $2==INT64 /* Convert integer to double */ ++ with STACK ++ kills ALL ++ gen ++ bl {LABEL, ".cif8"} ++ ++ pat loc loc cuf $1==INT32 && $2==INT64 /* Convert unsigned int to double */ ++ with STACK ++ gen ++ bl {LABEL, ".cuf8"} ++ ++ pat fef $1==INT64 /* Split double */ ++ with FD ++ gen ++ addi SP, SP, {CONST, 0-8} ++ stfd %1, {GPRINDIRECT, SP, 0} ++ stwu SP, {GPRINDIRECT, SP, 0-4} ++ bl {LABEL, "___fef8"} ++ stw R3, {GPRINDIRECT, SP, 0} ++ ++ pat fif $1==INT64 /* Multiply and split double (?) */ ++ with STACK ++ gen ++ bl {LABEL, ".fif8"} ++ ++ diff --cc mach/powerpc/pmfile index 000000000,000000000..8e4913560 new file mode 100644 --- /dev/null +++ b/mach/powerpc/pmfile @@@ -1,0 -1,0 +1,23 @@@ ++-- $Source$ ++-- $State$ ++ ++local d = ROOTDIR.."mach/powerpc/" ++ ++include (d.."libem/pmfile") ++include (d.."libend/pmfile") ++ ++mach_powerpc = group { ++ ARCH = "powerpc", ++ ++ proto_as, ++ proto_ncg { ARCHDIR = "powerpc" }, ++ proto_top, ++-- ego_descr, ++} ++ ++support_powerpc = group { ++ OPTIMISATION = "-O", ++ ++ libem_powerpc, ++ libend_powerpc, ++} diff --cc mach/powerpc/top/.distr index 000000000,000000000..ecbe2e6d5 new file mode 100644 --- /dev/null +++ b/mach/powerpc/top/.distr @@@ -1,0 -1,0 +1,1 @@@ ++table diff --cc mach/powerpc/top/table index 000000000,000000000..e735afee6 new file mode 100644 --- /dev/null +++ b/mach/powerpc/top/table @@@ -1,0 -1,0 +1,20 @@@ ++ ++/* 68020 desciptor table for ACK target optimizer */ ++ ++MAXOP 3; ++ ++%%; ++ ++P, Q, R { TRUE }; ++X, Y, Z { TRUE }; ++ ++%%; ++ ++/* Whitespace is significant here! */ ++ ++addi X, X, 0 -> ; ++addis X, X, 0 -> ; ++ ++or X, Y, Z : or. X, X, X -> or. X, Y, Z ; ++ ++%%;