Archival checkin (semi-working code).
authordtrg <none@none>
Fri, 2 Nov 2007 18:56:58 +0000 (18:56 +0000)
committerdtrg <none@none>
Fri, 2 Nov 2007 18:56:58 +0000 (18:56 +0000)
40 files changed:
1  2 
mach/powerpc/as/.distr
mach/powerpc/as/mach0.c
mach/powerpc/as/mach1.c
mach/powerpc/as/mach2.c
mach/powerpc/as/mach3.c
mach/powerpc/as/mach4.c
mach/powerpc/as/mach5.c
mach/powerpc/libem/.distr
mach/powerpc/libem/aar4.s
mach/powerpc/libem/cfi8.s
mach/powerpc/libem/cfu8.s
mach/powerpc/libem/cif8.s
mach/powerpc/libem/csa.s
mach/powerpc/libem/csb.s
mach/powerpc/libem/cuf8.s
mach/powerpc/libem/fd_00000000.s
mach/powerpc/libem/fd_80000000.s
mach/powerpc/libem/fd_FFFFFFFF.s
mach/powerpc/libem/fef8.c
mach/powerpc/libem/fif8.s
mach/powerpc/libem/los.s
mach/powerpc/libem/pmfile
mach/powerpc/libem/powerpc.h
mach/powerpc/libem/ret.s
mach/powerpc/libem/sts.s
mach/powerpc/libem/tge.s
mach/powerpc/libend/.distr
mach/powerpc/libend/LIST
mach/powerpc/libend/edata.s
mach/powerpc/libend/em_end.s
mach/powerpc/libend/end.s
mach/powerpc/libend/etext.s
mach/powerpc/libend/pmfile
mach/powerpc/ncg/.distr
mach/powerpc/ncg/mach.c
mach/powerpc/ncg/mach.h
mach/powerpc/ncg/table
mach/powerpc/pmfile
mach/powerpc/top/.distr
mach/powerpc/top/table

index 0000000,0000000..8ebe379
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,6 @@@
++mach0.c
++mach1.c
++mach2.c
++mach3.c
++mach4.c
++mach5.c
index 0000000,0000000..3a42f1d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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)
index 0000000,0000000..998cd8d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++/*
++ * $Source$
++ * $State$
++ */
++
index 0000000,0000000..43ea8d7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,89 @@@
++/*
++ * $Source$
++ * $State$
++ */
++
++%token <y_word> GPR
++%token <y_word> SPR
++%token <y_word> FPR
++%token <y_word> CR
++%token <y_word> C
++
++%token <y_word> OP
++%token <y_word> OP_BF
++%token <y_word> OP_BF_BFA
++%token <y_word> OP_BF_FRA_FRB
++%token <y_word> OP_BF_L_RA_RB
++%token <y_word> OP_BF_L_RA_SI
++%token <y_word> OP_BF_L_RA_UI
++%token <y_word> OP_BF_U_C
++%token <y_word> OP_BO_BI_BDA
++%token <y_word> OP_BO_BI_BDL
++%token <y_word> OP_BO_BI_BH
++%token <y_word> OP_BT_C
++%token <y_word> OP_BT_BA_BB
++%token <y_word> OP_FLM_FRB_C
++%token <y_word> OP_FRS_RA_D
++%token <y_word> OP_FRS_RA_RB
++%token <y_word> OP_FRT_C
++%token <y_word> OP_FRT_FRA_FRB_C
++%token <y_word> OP_FRT_FRA_FRC_FRB_C
++%token <y_word> OP_FRT_FRA_FRC_C
++%token <y_word> OP_FRT_FRB_C
++%token <y_word> OP_FRT_RA_D
++%token <y_word> OP_FRT_RA_RB
++%token <y_word> OP_L
++%token <y_word> OP_LEV
++%token <y_word> OP_LIA
++%token <y_word> OP_LIL
++%token <y_word> OP_L_RB
++%token <y_word> OP_RA_RB
++%token <y_word> OP_RB
++%token <y_word> OP_RS
++%token <y_word> OP_RS_FXM
++%token <y_word> OP_RS_L
++%token <y_word> OP_RS_RA
++%token <y_word> OP_RS_RA_C
++%token <y_word> OP_RS_RA_D
++%token <y_word> OP_RS_RA_DS
++%token <y_word> OP_RS_RA_NB
++%token <y_word> OP_RS_RA_RB
++%token <y_word> OP_RS_RA_RB_C
++%token <y_word> OP_RS_RA_RB_MB5_ME5_C
++%token <y_word> OP_RS_RA_RB_MB6_C
++%token <y_word> OP_RS_RA_RB_ME6_C
++%token <y_word> OP_RS_RA_SH_MB5_ME5_C
++%token <y_word> OP_RS_RA_SH_MB6_SH_C
++%token <y_word> OP_RS_RA_SH_ME6_SH_C
++%token <y_word> OP_RS_RA_SH5_C
++%token <y_word> OP_RS_RA_SH6_C
++%token <y_word> OP_RS_RA_UI
++%token <y_word> OP_RS_RA_UI_CC
++%token <y_word> OP_RS_RB
++%token <y_word> OP_RS_SPR
++%token <y_word> OP_RS_SR
++%token <y_word> OP_RT
++%token <y_word> OP_RT_FXM
++%token <y_word> OP_RT_RA_C
++%token <y_word> OP_RT_RA_D
++%token <y_word> OP_RT_RA_DS
++%token <y_word> OP_RT_RA_NB
++%token <y_word> OP_RT_RA_RB
++%token <y_word> OP_RT_RA_RB_C
++%token <y_word> OP_RT_RA_SI
++%token <y_word> OP_RT_RA_SI_addic
++%token <y_word> OP_RT_RB
++%token <y_word> OP_RT_SPR
++%token <y_word> OP_RT_SR
++%token <y_word> OP_RT_TBR
++%token <y_word> OP_TH_RA_RB
++%token <y_word> OP_TO_RA_RB
++%token <y_word> OP_TO_RA_SI
++
++%token <y_word> OP_la
++
++/* Other token types */
++
++%type <y_word> c
++%type <y_word> e16 u8 u7 u6 u5 u4 u2 u1
++%type <y_word> nb ds bda bdl lia lil
index 0000000,0000000..d7f5161
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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 */
index 0000000,0000000..b105aa2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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;
++      }
++      ;
++      
index 0000000,0000000..998cd8d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++/*
++ * $Source$
++ * $State$
++ */
++
index 0000000,0000000..d2b4f28
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2 @@@
++LIST
++libem_s.a
index 0000000,0000000..72af86f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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
index 0000000,0000000..7142c69
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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 
index 0000000,0000000..8b60f69
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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 
index 0000000,0000000..01b503e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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
index 0000000,0000000..64954ff
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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
index 0000000,0000000..cbedc8c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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
index 0000000,0000000..7adbb7b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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
index 0000000,0000000..cefa91b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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
index 0000000,0000000..50eacd5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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
index 0000000,0000000..9218f27
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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
index 0000000,0000000..244d0fa
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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;
++}
index 0000000,0000000..052c38c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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
index 0000000,0000000..f867fe7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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
index 0000000,0000000..8c851f8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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"),
++}
index 0000000,0000000..ddc4064
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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; ori reg, reg, >val
index 0000000,0000000..cca79ae
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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
index 0000000,0000000..2f8022a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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
index 0000000,0000000..4740d84
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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 .
index 0000000,0000000..1508ebd
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++pmfile
++edata.s
++em_end.s
++end.s
++etext.s
index 0000000,0000000..2efbd3e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++end_s.a
++edata.s
++em_end.s
++end.s
++etext.s
index 0000000,0000000..f53adc1
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,9 @@@
++.sect .text
++.sect .rom
++.sect .data
++.sect .bss
++.define       _edata
++.sect .data
++      .align 4
++      .sect .data
++_edata:
index 0000000,0000000..0271f09
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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:
index 0000000,0000000..93a1e6e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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:
index 0000000,0000000..8c7453c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,9 @@@
++.sect .text
++.sect .rom
++.sect .data
++.sect .bss
++.define       _etext
++.sect .text
++      .align 4
++      .sect .text
++_etext:
index 0000000,0000000..83f1c03
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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"),
++}
index 0000000,0000000..ccdf9bf
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,3 @@@
++mach.c
++mach.h
++table
index 0000000,0000000..39c6362
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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 <stdlib.h>
++#include <limits.h>
++
++#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 <con_float>
++
++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
index 0000000,0000000..0bca86f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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
index 0000000,0000000..c35ea72
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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"}
++                              
++              
index 0000000,0000000..8e49135
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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,
++}
index 0000000,0000000..ecbe2e6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1 @@@
++table
index 0000000,0000000..e735afe
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -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 ;
++
++%%;