diff --git a/mach/powerpc/as/.distr b/mach/powerpc/as/.distr new file mode 100644 index 000000000..8ebe3797c --- /dev/null +++ b/mach/powerpc/as/.distr @@ -0,0 +1,6 @@ +mach0.c +mach1.c +mach2.c +mach3.c +mach4.c +mach5.c diff --git a/mach/powerpc/as/mach0.c b/mach/powerpc/as/mach0.c new file mode 100644 index 000000000..3a42f1dd8 --- /dev/null +++ b/mach/powerpc/as/mach0.c @@ -0,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 --git a/mach/powerpc/as/mach1.c b/mach/powerpc/as/mach1.c new file mode 100644 index 000000000..998cd8d9c --- /dev/null +++ b/mach/powerpc/as/mach1.c @@ -0,0 +1,5 @@ +/* + * $Source$ + * $State$ + */ + diff --git a/mach/powerpc/as/mach2.c b/mach/powerpc/as/mach2.c new file mode 100644 index 000000000..43ea8d757 --- /dev/null +++ b/mach/powerpc/as/mach2.c @@ -0,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 --git a/mach/powerpc/as/mach3.c b/mach/powerpc/as/mach3.c new file mode 100644 index 000000000..d7f5161dd --- /dev/null +++ b/mach/powerpc/as/mach3.c @@ -0,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 --git a/mach/powerpc/as/mach4.c b/mach/powerpc/as/mach4.c new file mode 100644 index 000000000..b105aa2ae --- /dev/null +++ b/mach/powerpc/as/mach4.c @@ -0,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 --git a/mach/powerpc/as/mach5.c b/mach/powerpc/as/mach5.c new file mode 100644 index 000000000..998cd8d9c --- /dev/null +++ b/mach/powerpc/as/mach5.c @@ -0,0 +1,5 @@ +/* + * $Source$ + * $State$ + */ + diff --git a/mach/powerpc/libem/.distr b/mach/powerpc/libem/.distr new file mode 100644 index 000000000..d2b4f2884 --- /dev/null +++ b/mach/powerpc/libem/.distr @@ -0,0 +1,2 @@ +LIST +libem_s.a diff --git a/mach/powerpc/libem/aar4.s b/mach/powerpc/libem/aar4.s new file mode 100644 index 000000000..72af86f55 --- /dev/null +++ b/mach/powerpc/libem/aar4.s @@ -0,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 --git a/mach/powerpc/libem/cfi8.s b/mach/powerpc/libem/cfi8.s new file mode 100644 index 000000000..7142c694b --- /dev/null +++ b/mach/powerpc/libem/cfi8.s @@ -0,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 --git a/mach/powerpc/libem/cfu8.s b/mach/powerpc/libem/cfu8.s new file mode 100644 index 000000000..8b60f69e8 --- /dev/null +++ b/mach/powerpc/libem/cfu8.s @@ -0,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 --git a/mach/powerpc/libem/cif8.s b/mach/powerpc/libem/cif8.s new file mode 100644 index 000000000..01b503e0b --- /dev/null +++ b/mach/powerpc/libem/cif8.s @@ -0,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 --git a/mach/powerpc/libem/csa.s b/mach/powerpc/libem/csa.s new file mode 100644 index 000000000..64954ff4e --- /dev/null +++ b/mach/powerpc/libem/csa.s @@ -0,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 --git a/mach/powerpc/libem/csb.s b/mach/powerpc/libem/csb.s new file mode 100644 index 000000000..cbedc8c11 --- /dev/null +++ b/mach/powerpc/libem/csb.s @@ -0,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 --git a/mach/powerpc/libem/cuf8.s b/mach/powerpc/libem/cuf8.s new file mode 100644 index 000000000..7adbb7bc4 --- /dev/null +++ b/mach/powerpc/libem/cuf8.s @@ -0,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 --git a/mach/powerpc/libem/fd_00000000.s b/mach/powerpc/libem/fd_00000000.s new file mode 100644 index 000000000..cefa91b8e --- /dev/null +++ b/mach/powerpc/libem/fd_00000000.s @@ -0,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 --git a/mach/powerpc/libem/fd_80000000.s b/mach/powerpc/libem/fd_80000000.s new file mode 100644 index 000000000..50eacd586 --- /dev/null +++ b/mach/powerpc/libem/fd_80000000.s @@ -0,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 --git a/mach/powerpc/libem/fd_FFFFFFFF.s b/mach/powerpc/libem/fd_FFFFFFFF.s new file mode 100644 index 000000000..9218f2726 --- /dev/null +++ b/mach/powerpc/libem/fd_FFFFFFFF.s @@ -0,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 --git a/mach/powerpc/libem/fef8.c b/mach/powerpc/libem/fef8.c new file mode 100644 index 000000000..244d0fac8 --- /dev/null +++ b/mach/powerpc/libem/fef8.c @@ -0,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 --git a/mach/powerpc/libem/fif8.s b/mach/powerpc/libem/fif8.s new file mode 100644 index 000000000..052c38cf2 --- /dev/null +++ b/mach/powerpc/libem/fif8.s @@ -0,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 --git a/mach/powerpc/libem/los.s b/mach/powerpc/libem/los.s new file mode 100644 index 000000000..f867fe770 --- /dev/null +++ b/mach/powerpc/libem/los.s @@ -0,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 --git a/mach/powerpc/libem/pmfile b/mach/powerpc/libem/pmfile new file mode 100644 index 000000000..8c851f81e --- /dev/null +++ b/mach/powerpc/libem/pmfile @@ -0,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 --git a/mach/powerpc/libem/powerpc.h b/mach/powerpc/libem/powerpc.h new file mode 100644 index 000000000..ddc4064f9 --- /dev/null +++ b/mach/powerpc/libem/powerpc.h @@ -0,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 --git a/mach/powerpc/libem/ret.s b/mach/powerpc/libem/ret.s new file mode 100644 index 000000000..cca79ae86 --- /dev/null +++ b/mach/powerpc/libem/ret.s @@ -0,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 --git a/mach/powerpc/libem/sts.s b/mach/powerpc/libem/sts.s new file mode 100644 index 000000000..2f8022ad9 --- /dev/null +++ b/mach/powerpc/libem/sts.s @@ -0,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 --git a/mach/powerpc/libem/tge.s b/mach/powerpc/libem/tge.s new file mode 100644 index 000000000..4740d8436 --- /dev/null +++ b/mach/powerpc/libem/tge.s @@ -0,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 --git a/mach/powerpc/libend/.distr b/mach/powerpc/libend/.distr new file mode 100644 index 000000000..1508ebdc7 --- /dev/null +++ b/mach/powerpc/libend/.distr @@ -0,0 +1,5 @@ +pmfile +edata.s +em_end.s +end.s +etext.s diff --git a/mach/powerpc/libend/LIST b/mach/powerpc/libend/LIST new file mode 100644 index 000000000..2efbd3eb2 --- /dev/null +++ b/mach/powerpc/libend/LIST @@ -0,0 +1,5 @@ +end_s.a +edata.s +em_end.s +end.s +etext.s diff --git a/mach/powerpc/libend/edata.s b/mach/powerpc/libend/edata.s new file mode 100644 index 000000000..f53adc109 --- /dev/null +++ b/mach/powerpc/libend/edata.s @@ -0,0 +1,9 @@ +.sect .text +.sect .rom +.sect .data +.sect .bss +.define _edata +.sect .data + .align 4 + .sect .data +_edata: diff --git a/mach/powerpc/libend/em_end.s b/mach/powerpc/libend/em_end.s new file mode 100644 index 000000000..0271f09f6 --- /dev/null +++ b/mach/powerpc/libend/em_end.s @@ -0,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 --git a/mach/powerpc/libend/end.s b/mach/powerpc/libend/end.s new file mode 100644 index 000000000..93a1e6e00 --- /dev/null +++ b/mach/powerpc/libend/end.s @@ -0,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 --git a/mach/powerpc/libend/etext.s b/mach/powerpc/libend/etext.s new file mode 100644 index 000000000..8c7453cb4 --- /dev/null +++ b/mach/powerpc/libend/etext.s @@ -0,0 +1,9 @@ +.sect .text +.sect .rom +.sect .data +.sect .bss +.define _etext +.sect .text + .align 4 + .sect .text +_etext: diff --git a/mach/powerpc/libend/pmfile b/mach/powerpc/libend/pmfile new file mode 100644 index 000000000..83f1c038d --- /dev/null +++ b/mach/powerpc/libend/pmfile @@ -0,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 --git a/mach/powerpc/ncg/.distr b/mach/powerpc/ncg/.distr new file mode 100644 index 000000000..ccdf9bf7e --- /dev/null +++ b/mach/powerpc/ncg/.distr @@ -0,0 +1,3 @@ +mach.c +mach.h +table diff --git a/mach/powerpc/ncg/mach.c b/mach/powerpc/ncg/mach.c new file mode 100644 index 000000000..39c6362e6 --- /dev/null +++ b/mach/powerpc/ncg/mach.c @@ -0,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 --git a/mach/powerpc/ncg/mach.h b/mach/powerpc/ncg/mach.h new file mode 100644 index 000000000..0bca86fae --- /dev/null +++ b/mach/powerpc/ncg/mach.h @@ -0,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 --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table new file mode 100644 index 000000000..c35ea728e --- /dev/null +++ b/mach/powerpc/ncg/table @@ -0,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"} + + \ No newline at end of file diff --git a/mach/powerpc/pmfile b/mach/powerpc/pmfile new file mode 100644 index 000000000..8e4913560 --- /dev/null +++ b/mach/powerpc/pmfile @@ -0,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 --git a/mach/powerpc/top/.distr b/mach/powerpc/top/.distr new file mode 100644 index 000000000..ecbe2e6d5 --- /dev/null +++ b/mach/powerpc/top/.distr @@ -0,0 +1 @@ +table diff --git a/mach/powerpc/top/table b/mach/powerpc/top/table new file mode 100644 index 000000000..e735afee6 --- /dev/null +++ b/mach/powerpc/top/table @@ -0,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 ; + +%%;