From: ceriel Date: Tue, 13 Jan 1987 09:24:13 +0000 (+0000) Subject: Initial revision X-Git-Tag: release-5-5~5012 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=177e335cad9585d5059b64eb017c759f7c784b96;p=ack.git Initial revision --- diff --git a/mach/m68020/ncg/mach.c b/mach/m68020/ncg/mach.c new file mode 100644 index 000000000..ec51f8bf1 --- /dev/null +++ b/mach/m68020/ncg/mach.c @@ -0,0 +1,236 @@ +/* + * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands. + * + * This product is part of the Amsterdam Compiler Kit. + * + * Permission to use, sell, duplicate or disclose this software must be + * obtained in writing. Requests for such permissions may be sent to + * + * Dr. Andrew S. Tanenbaum + * Wiskundig Seminarium + * Vrije Universiteit + * Postbox 7161 + * 1007 MC Amsterdam + * The Netherlands + * + */ + +/* + * machine dependent back end routines for the Motorola 68000, 68010 or 68020 + */ + +#ifndef m68k4 +#define m68020 +#endif + /* use m68020 when you want a m68020 cg, don't if you want a + * m68k4 cg. The m68k4 cg can be used for both the MC68000 + * and the MC68010. + */ + +con_part(sz,w) register sz; word w; { + + while (part_size % sz) + part_size++; + if (part_size == 4) + 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) + w <<= 16; + part_word |= w; + } else { + assert(sz == 4); + part_word = w; + } + part_size += sz; +} + +con_mult(sz) word sz; { + + if (sz != 4) + fatal("bad icon/ucon size"); + fprintf(codefile,".data4 %s\n",str); +} + +con_float() { + +static int been_here; + if (argval != 4 && argval != 8) + fatal("bad fcon size"); + fprintf(codefile,".data4\t"); + if (argval == 8) + fprintf(codefile,"F_DUM,"); + fprintf(codefile,"F_DUM\n"); + if ( !been_here++) + { + fprintf(stderr,"Warning : dummy float-constant(s)\n"); + } +} + +regscore(off,size,typ,score,totyp) + long off; +{ + if (score == 0) return -1; + switch(typ) { + case reg_float: + return -1; + case reg_pointer: + if (size != 4 || totyp != reg_pointer) return -1; + score *= 2; + break; + case reg_loop: + score += 5; + /* fall through .. */ + case reg_any: + if (size != 4 || totyp == reg_pointer) return -1; + break; + } + if (off >= 0) { + /* parameters must be initialised with an instruction + * like "move.l 4(a6),d0", which costs 2 words. + */ + score -= 2; + } + score -= 1; /* take save/restore into account */ + return score; +} +struct regsav_t { + char *rs_reg; /* e.g. "a3" or "d5" */ + long rs_off; /* offset of variable */ + int rs_size; /* 2 or 4 bytes */ +} regsav[9]; + + +int regnr; + +i_regsave() +{ + regnr = 0; +} + +#define MOVEM_LIMIT 2 +/* If #registers to be saved exceeds MOVEM_LIMIT, we +* use the movem instruction to save registers; else +* we simply use several move.l's. +*/ + +save() +{ + register struct regsav_t *p; + + if (regnr > MOVEM_LIMIT) { + fprintf(codefile,"movem.l "); + for (p = regsav; ;) { + fprintf(codefile,"%s",p->rs_reg); + if (++p == ®sav[regnr]) break; + putc('/',codefile); + } + fprintf(codefile,",-(sp)\n"); + } else { + for (p = regsav; p < ®sav[regnr]; p++) { + fprintf(codefile,"move.l %s,-(sp)\n",p->rs_reg); + } + } + /* initialise register-parameters */ + for (p = regsav; p < ®sav[regnr]; p++) { + if (p->rs_off >= 0) { +#ifdef m68020 + fprintf(codefile,"move.%c (%ld,a6),%s\n", +#else + fprintf(codefile,"move.%c %ld(a6),%s\n", +#endif + (p->rs_size == 4 ? 'l' : 'w'), + p->rs_off, + p->rs_reg); + } + } +} + +restr() +{ + register struct regsav_t *p; + + if (regnr > MOVEM_LIMIT) { + fprintf(codefile,"movem.l (sp)+,"); + for (p = regsav; ;) { + fprintf(codefile,"%s",p->rs_reg); + if (++p == ®sav[regnr]) break; + putc('/',codefile); + } + putc('\n',codefile); + } else { + for (p = ®sav[regnr-1]; p >= regsav; p--) { + fprintf(codefile,"move.l (sp)+,%s\n",p->rs_reg); + } + } + fprintf(codefile,"unlk a6\n"); + fprintf(codefile,"rts\n"); +} + + +f_regsave() +{ + save(); +} + +regsave(str,off,size) + char *str; + long off; +{ + assert (regnr < 9); + regsav[regnr].rs_reg = str; + regsav[regnr].rs_off = off; + regsav[regnr++].rs_size = size; + fprintf(codefile, "!Local %ld into %s\n",off,str); +} + +regreturn() +{ + restr(); +} + + +prolog(nlocals) full nlocals; { + +#ifdef m68020 + fprintf(codefile,"tst.b (-%ld,sp)\nlink\ta6,#-%ld\n",nlocals+40,nlocals); +#else + fprintf(codefile,"tst.b -%ld(sp)\nlink\ta6,#-%ld\n",nlocals+40,nlocals); +#endif +} + + + +mes(type) 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", /* SEGTXT */ + ".sect .data", /* SEGCON */ + ".sect .rom", /* SEGROM */ + ".sect .bss" /* SEGBSS */ +}; diff --git a/mach/m68020/ncg/mach.h b/mach/m68020/ncg/mach.h new file mode 100644 index 000000000..ff2cf66ca --- /dev/null +++ b/mach/m68020/ncg/mach.h @@ -0,0 +1,39 @@ +#ifndef m68k4 +#define m68020 +#endif + /* m68020 should be used for a m68020 cg, and it should + * not be used for a m68k4 cg + */ + +#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,"%s:.space\t%ld\n",l,x); + +#define pop_fmt "(sp)+" +#define cst_fmt "%ld" +#define off_fmt "%ld" +#define ilb_fmt "I%03x%x" +#define dlb_fmt "_%d" +#define hol_fmt "hol%d" + +#ifdef m68020 +#define loc_off "(%d,a6)" +#define arg_off "(8+%d,a6)" +#else +#define loc_off "%d(a6)" +#define arg_off "8+%d(a6)" +#endif +#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 modhead ".sect .text\n.sect .rom\n.sect .data\n.sect .bss\n" + +#define id_first '_' +#define BSS_INIT 0 diff --git a/mach/m68020/ncg/table b/mach/m68020/ncg/table new file mode 100644 index 000000000..6518487ad --- /dev/null +++ b/mach/m68020/ncg/table @@ -0,0 +1,3288 @@ + /******************************** + * * + * 68000, 68010 and 68020 * + * back end table * + * * + ********************************/ + + +#ifndef m68k4 +#define m68020 +#endif + /* m68020 to be defined if this is the 68020 table. + * The 68000 and 68010 tables are identical. + */ + + +#define small(x) ((x)>=1 && (x)<=8) +#define nicesize(x) ((x)==1||(x)==2||(x)==4||(x)==8) +#define lowb(x) (((x)<<24)>>24) +#define loww(x) (((x)<<16)>>16) +#define in_1(x) ((x)>=0-128 && (x)<128) +#define in_2(x) ((x)>=0-32768 && (x)<32768) + + +EM_WSIZE = 4 +EM_PSIZE = 4 +EM_BSIZE = 8 + +SL = 8 + +TIMEFACTOR = 1/2 + + +PROPERTIES + +D_REG /* data registers */ +A_REG /* address registers */ +DD_REG /* allocatable D_REG, may not be a register variable */ +AA_REG /* allocatable A_REG, may not be a register variable */ + + + +REGISTERS + +d0, d1, d2 :D_REG, DD_REG. +d3, d4, d5, d6, d7 :D_REG regvar. +a0, a1 :A_REG, AA_REG. +a2, a3, a4, a5 :A_REG regvar(reg_pointer). +lb ("a6"), sp :A_REG. /* localbase and stack pointer */ + + + + +TOKENS + + /* Not all addressing modes available on the MC68020 are used in this + * table. E.g (Dn), data register indirect is not used. Compared to + * (An), address register indirect, (Dn) requires two more bytes and + * several more clock cycles. Using (Dn) is even more expensive in + * time than first moving Dn to an address register An, and then using + * (An). For this kind of reasons several addressing modes are + * not used in this table. + * + * Cost in bytes may sometimes be incorrect. Several effective addresses + * use displacements that can occupy either 2 or 4 bytes. These are not + * considered different TOKENS in this table. + * + * Data registers are the only registers used as index registers in this + * table; address registers are only used to hold addresses. + * + * For the m68k4 table: the MC68000 and MC68010 have two modes that use + * displacements (offsets) of limited size: + * - offset(A_REG, Index_reg), where offset is only 8 bits, and + * - offset(A_REG), where offset can only be 16 bits. + * To make sure that no output is given with offsets too large, two + * extra tokens are declared: t_regAregXcon and t_regAcon. These are + * used as addresses to these modes. Whenever the displacements become + * too large, they are transformed into different tokens. + * + * Sometimes some TOKENS are used with displacements (offsets) of 0. + * It would have been possible to provide separate TOKENS for these, in + * case the assembler doesn't handle zero offsets optimally. This + * however would mean a very large amount of extra TOKENS and SETS for + * a very small profit in code bytes, so we won't do that. + * + * To prevent the TOKENS list from getting too unreadable, #ifdefs are + * used to form three parts: + * (i) the common part; + * (ii) the m68k4 part; + * (iii) the m68020 part; + */ + + /* Part (i) */ +const = {INT num;} 4 cost(4,4) "#" num . +indirect4 = {A_REG reg;} 4 cost(0,4) "(" reg ")" . +post_inc4 = {A_REG reg;} 4 cost(0,4) "(" reg ")+" . +pre_dec4 = {A_REG reg;} 4 cost(0,5) "-(" reg ")" . +indirect2 = {A_REG reg;} 4 cost(0,4) "(" reg ")" . +post_inc2 = {A_REG reg;} 4 cost(0,4) "(" reg ")+" . +pre_dec2 = {A_REG reg;} 4 cost(0,5) "-(" reg ")" . +indirect1 = {A_REG reg;} 4 cost(0,4) "(" reg ")" . +post_inc1 = {A_REG reg;} 4 cost(0,4) "(" reg ")+" . +pre_dec1 = {A_REG reg;} 4 cost(0,5) "-(" reg ")" . + +ext_addr = {ADDR bd;} 4 cost(4,5) "#" bd . +llabel = {ADDR bd;} 4 cost(2,0) bd . +slabel = {ADDR bd;} 4 cost(0,0) bd . +shconst = {INT num;} 4 cost(0,0) "#" num . + +#ifndef m68020 + /* Part (ii) */ +absolute4 = {ADDR bd;} 4 cost(4,8) bd . +offsetted4 = {A_REG reg; INT bd;} 4 cost(2,6) bd "(" reg ")" . +index_off4 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,7) + bd "(" reg "," xreg ".l)" . +absolute2 = {ADDR bd;} 4 cost(4,6) bd . +offsetted2 = {A_REG reg; INT bd;} 4 cost(2,4) bd "(" reg ")" . +index_off2 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,5) + bd "(" reg "," xreg ".l)" . +absolute1 = {ADDR bd;} 4 cost(4,6) bd . +offsetted1 = {A_REG reg; INT bd;} 4 cost(2,4) bd "(" reg ")" . +index_off1 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,5) + bd "(" reg "," xreg ".l)" . + +LOCAL = {INT bd;} 4 cost(2,6) bd "(a6)" . + +local_addr = {INT bd;} 4 cost(2,6) bd "(a6)" . +regAcon = {A_REG reg; INT bd;} 4 cost(2,6) bd "(" reg ")" . +regAregXcon = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,8) + bd "(" reg "," xreg ".l)" . + /* note: in the m68k4 version %sc always equals 1 */ + +t_regAregXcon = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,8) . +t_regAcon = {A_REG reg; INT bd;} 4 cost(2,6) . + +#else m68020 + /* Part (iii) */ +absolute4 = {ADDR bd;} 4 cost(4,7) "(" bd ")" . +offsetted4 = {A_REG reg; INT bd;} 4 cost(2,6) "(" bd "," reg ")" . +index_off4 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(4,9) + "(" bd "," reg "," xreg ".l*" sc ")" . +abs_index4 = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,9) + "(" bd "," xreg ".l*" sc ")" . +OFF_off4 = {A_REG reg; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," od ")" . +OFF_indoff4 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +INDOFF_off4 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +ABS_off4 = {ADDR bd; ADDR od;} 4 cost(8,22) "([" bd "]," od ")" . +ABS_indoff4 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "]," xreg ".l*" sc "," od ")" . +ABSIND_off4 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "," xreg ".l*" sc "]," od ")" . + +absolute2 = {ADDR bd;} 4 cost(4,7) "(" bd ")" . +offsetted2 = {A_REG reg; INT bd;} 4 cost(2,6) "(" bd "," reg ")" . +index_off2 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(4,9) + "(" bd "," reg "," xreg ".l*" sc ")" . +abs_index2 = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,9) + "(" bd "," xreg ".l*" sc ")" . +OFF_off2 = {A_REG reg; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," od ")" . +OFF_indoff2 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +INDOFF_off2 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +ABS_off2 = {ADDR bd; ADDR od;} 4 cost(8,22) "([" bd "]," od ")" . +ABS_indoff2 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "]," xreg ".l*" sc "," od ")" . +ABSIND_off2 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "," xreg ".l*" sc "]," od ")" . + +absolute1 = {ADDR bd;} 4 cost(4,7) "(" bd ")" . +offsetted1 = {A_REG reg; INT bd;} 4 cost(2,6) "(" bd "," reg ")" . +index_off1 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(4,9) + "(" bd "," reg "," xreg ".l*" sc ")" . +abs_index1 = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,9) + "(" bd "," xreg ".l*" sc ")" . +OFF_off1 = {A_REG reg; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," od ")" . +OFF_indoff1 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +INDOFF_off1 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +ABS_off1 = {ADDR bd; ADDR od;} 4 cost(8,22) "([" bd "]," od ")" . +ABS_indoff1 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "]," xreg ".l*" sc "," od ")" . +ABSIND_off1 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "," xreg ".l*" sc "]," od ")" . + +LOCAL = {INT bd;} 4 cost(2,6) "(" bd ",a6)" . +ILOCAL = {INT bd;} 4 cost(4,16) "([" bd ",a6])" . + +local_addr = {INT bd;} 4 cost(2,3) "(" bd ",a6)" . +regAcon = {A_REG reg; INT bd;} 4 cost(2,3) "(" bd "," reg ")" . +regAregXcon = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,7) + "(" bd "," reg "," xreg ".l*" sc ")" . +off_con = {A_REG reg; INT bd; ADDR od;} 4 cost(6,18) + "([" bd "," reg "]," od ")". +off_regXcon = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,18) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +indoff_con = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,18) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +abs_con = {ADDR bd; ADDR od;} 4 cost(8,21) "([" bd "]," od ")" . +abs_regXcon = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,21) + "([" bd "]," xreg ".l*" sc "," od ")" . +absind_con = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,21) + "([" bd "," xreg ".l*" sc "]," od ")" . +ext_regX = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,15) + "(" bd "," xreg ".l*" sc ")" . + +regX = {INT sc; D_REG xreg;} 4 cost(2,7) "(" xreg ".l*" sc ")" . +DREG_pair = {D_REG reg1; D_REG reg2;} 8 cost(2,0) reg1 ":" reg2 . + +#define t_regAregXcon regAregXcon +#define t_regAcon regAcon + +#endif m68020 + +SETS + + /* The SETS list cannot be kept as 'readable' as the TOKENS list + * because cgg is one pass. + */ + +#ifndef m68020 + /* A m68k4 part */ +data4 = D_REG + LOCAL + const + post_inc4 + pre_dec4 + + indirect4 + offsetted4 + index_off4 + absolute4 + + ext_addr . +memory4 = data4 - D_REG . +control4 = indirect4 + offsetted4 + index_off4 + absolute4 + + LOCAL . +alterable4 = data4 + A_REG - const - ext_addr . +any4 = data4 + A_REG . /* all four above together */ + +data2 = D_REG + post_inc2 + pre_dec2 + indirect2 + + offsetted2 + index_off2 + absolute2 + const . +memory2 = data2 - D_REG . +control2 = indirect2 + offsetted2 + index_off2 + absolute2 . +alterable2 = data2 + A_REG - const . +any2 = data2 + A_REG . + +data1 = D_REG + post_inc1 + pre_dec1 + indirect1 + + offsetted1 + index_off1 + absolute1 + const . +memory1 = data1 - D_REG . +control1 = indirect1 + offsetted1 + index_off1 + absolute1 . +alterable1 = data1 - const . +any1 = data1 . + +#else m68020 + +data4 = D_REG + indirect4 + post_inc4 + pre_dec4 + index_off4 + + offsetted4 + OFF_off4 + OFF_indoff4 + + INDOFF_off4 + + ABS_off4 + ABS_indoff4 + ABSIND_off4 + + absolute4 + abs_index4 + const + ext_addr + + LOCAL + ILOCAL . +memory4 = data4 - D_REG . +control4 = memory4 - (post_inc4 + pre_dec4 + const + ext_addr) . +alterable4 = data4 + A_REG - const - ext_addr . +any4 = data4 + A_REG . /* all four above together */ + +data2 = D_REG + indirect2 + post_inc2 + pre_dec2 + index_off2 + + offsetted2 + OFF_off2 + OFF_indoff2 + + INDOFF_off2 + + ABS_off2 + ABS_indoff2 + ABSIND_off2 + + absolute2 + abs_index2 + const . +memory2 = data2 - D_REG . +control2 = memory2 - (post_inc2 + pre_dec2 + const) . +alterable2 = data2 + A_REG - const . +any2 = data2 + A_REG . /* all four above together */ + +data1 = D_REG + indirect1 + post_inc1 + pre_dec1 + index_off1 + + offsetted1 + OFF_off1 + OFF_indoff1 + + INDOFF_off1 + + ABS_off1 + ABS_indoff1 + ABSIND_off1 + + absolute1 + abs_index1 + const . +memory1 = data1 - D_REG . +control1 = memory1 - (post_inc1 + pre_dec1 + const) . +alterable1 = data1 - const . +any1 = data1 . /* all four above together */ + +#endif m68020 + /* This is a common part */ +any = any4 + any2 + any1 . +absolute = absolute4 + absolute2 + absolute1 . +control = control4 + control2 + control1 . +indirect = indirect4 + indirect2 + indirect1 . +pre_post = pre_dec4 + pre_dec2 + pre_dec1 + + post_inc4 + post_inc2 + post_inc1 . +offsetted = offsetted4 + offsetted2 + offsetted1 . +index_off = index_off4 + index_off2 + index_off1 . + +#ifndef m68020 + /* A m68k4 part */ +regind_addr = regAcon + regAregXcon + t_regAcon + t_regAregXcon . +address = ext_addr + local_addr + regAcon + regAregXcon . +all_regind = indirect + offsetted + pre_post + index_off + + regind_addr . +all_indir = all_regind . +allexceptcon = ALL - ( D_REG + A_REG + const + + local_addr + ext_addr + regAcon + regAregXcon + + t_regAcon + t_regAregXcon ) . +use_index = index_off4 + index_off2 + index_off1 . + +#else m68020 + +reg_memind4 = OFF_off4 + OFF_indoff4 + INDOFF_off4 . +memind4 = reg_memind4 + + ABS_off4 + ABS_indoff4 . +reg_memind2 = OFF_off2 + OFF_indoff2 + INDOFF_off2 . +memind2 = reg_memind2 + + ABS_off2 + ABS_indoff2 . +reg_memind1 = OFF_off1 + OFF_indoff1 + INDOFF_off1 . +memind1 = reg_memind1 + + ABS_off1 + ABS_indoff1 . +reg_memind = reg_memind4 + reg_memind2 + reg_memind1 . +memind = memind4 + memind2 + memind1 . +regind_addr = regAcon + regAregXcon + + off_con + off_regXcon + + indoff_con . +address = regind_addr + + ext_addr + local_addr + + abs_con + abs_regXcon + + absind_con + + ext_regX . +all_regind = indirect + offsetted + index_off + pre_post + + reg_memind + regind_addr . +all_indir = all_regind + memind + ILOCAL . +allexceptcon = ALL - ( D_REG + A_REG + const + + local_addr + ext_addr + regAcon + regAregXcon + ext_regX ) . +use_index4 = index_off4 + abs_index4 + + OFF_indoff4 + INDOFF_off4 + + ABS_indoff4 + ABSIND_off4 . +use_index2 = index_off2 + abs_index2 + + OFF_indoff2 + INDOFF_off2 + + ABS_indoff2 + ABSIND_off2 . +use_index1 = index_off1 + abs_index1 + + OFF_indoff1 + INDOFF_off1 + + ABS_indoff1 + ABSIND_off1 . +use_indaddr = regAregXcon + + off_regXcon + indoff_con + + abs_regXcon + absind_con + + ext_regX . + +use_index = use_index4 + use_index2 + use_index1 + use_indaddr + regX . + +#endif m68020 + /* A common part */ +posextern = absolute + all_indir . + +genreg = D_REG + A_REG. +label = llabel + slabel . +immediate4 = const + ext_addr . +conreg4 = D_REG + immediate4 . +conreg2 = D_REG + const . +conreg1 = D_REG + const . +shconreg = D_REG + shconst . +datalt4 = data4 * alterable4 . +datalt2 = data2 * alterable2 . +datalt1 = data1 * alterable1 . +datalt = datalt4 + datalt2 + datalt1 . +memalt4 = memory4 * alterable4 . +memalt2 = memory2 * alterable2 . +memalt1 = memory1 * alterable1 . + +#ifndef m68020 + /* A m68k4 part */ +imm_cmp4 = alterable4 . +imm_cmp2 = alterable2 . +imm_cmp1 = datalt1 . + +test_set4 = datalt4 . +test_set2 = datalt2 . +test_set1 = datalt1 . + +#else m68020 + +imm_cmp4 = any4 - immediate4 . +imm_cmp2 = any2 - const . +imm_cmp1 = data1 - const . + +test_set4 = data4 - immediate4 . +test_set2 = data2 - const . +test_set1 = data1 - const . + +#endif m68020 + +test_set = test_set4 + test_set2 + test_set1 . + +#ifndef m68020 +t_address = address + t_regAregXcon + t_regAcon . +#else m68020 +#define t_address address +#endif m68020 + + +INSTRUCTIONS + + /* Since the 68000 , the 68010 and the 68020 instruction sets are rather + * extensive, especially because e.g. 'add.l' and 'add.w' are + * considered different instructions, only those instructions are + * listed here that are used in the rest of this table. + * + * Instruction timing cost cannot be accurately given, nor the timing + * cost for getting operands. Detailed information about this can be + * found in the "MC68020 User's Manual", section 9, about instruction + * timing. The cost used in this table are 'worst case' cost, as + * mentioned in section 9 of the user's manual. + * + * The first few instructions had to be added because register + * variables are used. The LOCALs below are register variables. + * One may not conclude that these operations are also allowed + * on LOCALs that are not register variables. + * The cost have been adapted, but are not accurate; when 'real' + * LOCALs are used the cost are very inaccurate. + */ + +add_l "add.l" any4:ro, LOCAL:rw:cc cost(0,0). +lea address:ro, LOCAL:wo cost(0,0). +sub_l "sub.l" any4:ro, LOCAL:rw:cc cost(0,0). +sh "illegal" shconreg:ro, LOCAL:rw:cc cost(0,0). +sh "illegal" LOCAL:ro, LOCAL:rw:cc cost(0,0). +xxx "illegal" data4:ro, LOCAL:rw:cc cost(0,0). +xxx "illegal" LOCAL:ro, alterable4:rw:cc cost(0,0). +#ifdef m68020 +divs_l "divs.l" data4:ro, LOCAL:rw:cc cost(0,90). +divu_l "divu.l" data4:ro, LOCAL:rw:cc cost(0,78). +muls_l "muls.l" data4:ro, LOCAL:rw:cc cost(0,44). +mulu_l "mulu.l" data4:ro, LOCAL:rw:cc cost(0,44). +#endif m68020 + +add_l "add.l" any4:ro, D_REG:rw:cc cost(2,3). +add_l "add.l" any4:ro, A_REG:rw cost(2,3). +add_l "add.l" conreg4:ro, alterable4:rw:cc cost(2,6). +and_l "and.l" data4:ro, D_REG:rw:cc cost(2,3). +and_l "and.l" D_REG:ro, memalt4:rw:cc cost(2,6). +and_l "and.l" const:ro, datalt4:rw:cc cost(2,6). +asl_l "asl.l" shconreg:ro, D_REG:rw:cc cost(2,5). +asl "asl #1," memalt2:rw:cc cost(2,4). +asr_l "asr.l" shconreg:ro, D_REG:rw:cc cost(2,4). +asr "asr #1," memalt2:rw:cc cost(2,4). +bra label cost(2,5). +bcc label cost(2,5). +bcs label cost(2,5). +beq label cost(2,5). +bge label cost(2,5). +bgt label cost(2,5). +bhi label cost(2,5). +ble label cost(2,5). +bls label cost(2,5). +blt label cost(2,5). +bmi label cost(2,5). +bne label cost(2,5). +bpl label cost(2,5). +bvc label cost(2,5). +bvs label cost(2,5). +bset conreg2:ro, D_REG:rw kills :cc cost(2,4). +btst conreg2:ro, data1:rw kills :cc cost(2,3). +clr_l "clr.l" D_REG:wo:cc cost(2,3). +clr_l "clr.l" memalt4:wo:cc cost(2,6). +clr_w "clr.w" D_REG:wo:cc cost(2,2). +clr_w "clr.w" memalt2:wo:cc cost(2,4). +clr_b "clr.b" D_REG:wo:cc cost(2,2). +clr_b "clr.b" memalt1:wo:cc cost(2,4). +cmp_l "cmp.l" any4:ro, genreg:ro kills :cc cost(2,3). +cmp_l "cmp.l" post_inc4:ro, post_inc4:ro kills :cc cost(2,2). +cmp_l "cmp.l" immediate4:ro, imm_cmp4:ro kills :cc cost(2,2). +cmp_w "cmp.w" any2:ro, genreg:ro kills :cc cost(2,3). +cmp_w "cmp.w" post_inc2:ro, post_inc2:ro kills :cc cost(2,2). +cmp_w "cmp.w" const:ro, imm_cmp2:ro kills :cc cost(2,2). +cmp_b "cmp.b" data1:ro, D_REG:ro kills :cc cost(2,3). +cmp_b "cmp.b" post_inc1:ro, post_inc1:ro kills :cc cost(2,2). +cmp_b "cmp.b" const:ro, imm_cmp1:ro kills :cc cost(2,2). +dbf D_REG:rw, label cost(2,5). +eor_l "eor.l" conreg4:ro, datalt4:rw:cc cost(2,6). +ext_l "ext.l" D_REG:rw:cc cost(2,2). +ext_w "ext.w" D_REG:rw:cc cost(2,2). +jmp address+control4 cost(2,0). +jsr address+control4 kills :cc cost(2,3). +lea address+control4:ro, A_REG:wo cost(2,0). +lsl_l "lsl.l" shconreg:ro, D_REG:rw:cc cost(2,4). +lsl "lsl #1," memalt2:rw:cc cost(2,4). +lsr_l "lsr.l" shconreg:ro, D_REG:rw:cc cost(2,4). +lsr "lsr #1," memalt2:rw:cc cost(2,4). +move_l "move.l" any4:ro, alterable4:wo:cc cost(2,2). +move_w "move.w" any2:ro, alterable2:wo:cc cost(2,2). +move_b "move.b" data1:ro, alterable1:wo:cc cost(2,2). +neg_l "neg.l" D_REG:rw:cc cost(2,3). +neg_l "neg.l" memory4:rw:cc cost(2,6). +not_l "not.l" D_REG:rw:cc cost(2,3). +not_l "not.l" memory4:rw:cc cost(2,6). +or_l "or.l" data4:ro, D_REG:rw:cc cost(2,3). +or_l "or.l" D_REG:ro, memalt4:rw:cc cost(2,6). +or_l "or.l" const:ro, datalt4:rw:cc cost(2,6). +rol_l "rol.l" shconreg:ro, D_REG:rw:cc cost(2,4). +rol "rol #1," memalt2:rw:cc cost(2,4). +ror_l "ror.l" shconreg:ro, D_REG:rw:cc cost(2,4). +ror "ror #1," memalt2:rw:cc cost(2,4). +roxl "roxl #1," memalt2:rw:cc cost(2,4). +roxr "roxr #1," memalt2:rw:cc cost(2,4). +sne datalt1:rw cost(2,3). +sub_l "sub.l" any4:ro, D_REG:rw:cc cost(2,3). +sub_l "sub.l" any4:ro, A_REG:rw cost(2,3). +sub_l "sub.l" conreg4:ro, alterable4:rw:cc cost(2,6). +tst_l "tst.l" test_set4:ro:cc cost(2,3). +tst_w "tst.w" test_set2:ro:cc cost(2,3). +tst_b "tst.b" test_set1:ro:cc cost(2,3). +unlk A_REG cost(2,6). + +bxx "illegal" label cost(2,5). +xxx "illegal" data4:ro, D_REG:rw:cc cost(2,3). +xxx "illegal" conreg4:ro, memalt4:rw:cc cost(2,6). +bit "illegal" control4:rw:cc cost(2,6). +sh "illegal" shconreg:ro, D_REG:rw:cc cost(2,4). +shw "illegal" control2:rw:cc cost(2,4). + +#ifdef m68020 +cmp2_l "cmp2.l" address+control4:ro, genreg:ro kills :cc cost(2,18). +divs_l "divs.l" data4:ro, D_REG:rw:cc cost(2,90). +divsl_l "divsl.l" data4:ro, DREG_pair:rw kills :cc cost(2,90). +divu_l "divu.l" data4:ro, D_REG:rw:cc cost(2,78). +divul_l "divul.l" data4:ro, DREG_pair:rw kills :cc cost(2,78). +extb_l "extb.l" D_REG:rw:cc cost(2,4). +muls_l "muls.l" data4:ro, D_REG:rw:cc cost(2,44). +mulu_l "mulu.l" data4:ro, D_REG:rw:cc cost(2,44). +pea address+control4+regX cost(2,4). +#else m68020 +pea address+control4 cost(2,4). +#endif m68020 + + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * Extra pseudo instruction; it just kills a D_REG; + * it is necessary with long divides where remainders are important; + * see also: 'pat rmi' and 'pat rmu' + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ +killreg "! kill" D_REG:wo cost(0,0). + + +MOVES + +from const %num==0 to D_REG + gen clr_l %2 + +from const %num==0 to memalt4 + gen clr_l %2 + +from const %num==0 to memalt2 + gen clr_w %2 + +from const %num==0 to memalt1 + gen clr_b %2 + +from const to memalt1 + gen move_b {const, lowb(%1.num)}, %2 + +from const to memalt2 + gen move_w {const, loww(%1.num)}, %2 + +from regAcon %bd==0 to A_REG + gen move_l %1.reg, %2 + +#ifndef m68020 +from t_regAregXcon sfit(%bd, 8) to A_REG + gen lea {regAregXcon, %1.reg, %1.xreg, 1, %1.bd}, %2 + +from t_regAregXcon to A_REG + gen lea {regAregXcon, %1.reg, %1.xreg, 1, 0}, %2 + add_l {const, %1.bd}, %2 + +from t_regAcon sfit(%bd, 16) to A_REG + gen lea {regAcon, %1.reg, %1.bd}, %2 + +from t_regAcon to A_REG + gen move_l %1.reg, %2 + add_l {const, %1.bd}, %2 +#endif m68020 + +from address - ext_addr to A_REG + gen lea %1, %2 + +from any4 to alterable4 + gen move_l %1, %2 + +from any2 to datalt2 + gen move_w %1, %2 + +from data1 to datalt1 + gen move_b %1, %2 + + + + +TESTS + + +to test test_set4 + gen tst_l %1 + +to test test_set2 + gen tst_w %1 + +to test test_set1 + gen tst_b %1 + + +STACKINGRULES + + +from const %num==0 to STACK + gen clr_l {pre_dec4, sp} + +#ifndef m68020 +from t_regAregXcon sfit(%bd, 8) to STACK + gen pea {regAregXcon, %1.reg, %1.xreg, 1, %1.bd} + +from t_regAregXcon to STACK + gen pea {regAregXcon, %1.reg, %1.xreg, 1, 0} + add_l {const, %1.bd}, {indirect4, sp} + +from t_regAcon sfit(%bd, 16) to STACK + gen pea {regAcon, %1.reg, %1.bd} + +from t_regAcon to STACK + gen move_l %1.reg, {pre_dec4, sp} + add_l {const, %1.bd}, {indirect4, sp} +#endif m68020 + +from address - ext_addr to STACK + gen pea %1 + +from ext_addr to STACK + gen pea {absolute4, %1.bd} + +from const to STACK + gen pea {absolute4, %1.num} + +from any4 to STACK + gen move_l %1, {pre_dec4, sp} + +from any2 to STACK + gen clr_l {pre_dec4, sp} + move_w %1, {offsetted2, sp, 2} + +from data1 to STACK + gen clr_l {pre_dec4, sp} + move_b %1, {offsetted1, sp, 3} + +#ifdef m68020 +from regX to STACK + gen pea %1 +#endif m68020 + /* This last stackingrule is never used: whenever regX is put on + * the fakestack, some em-instuctions are left that remove it + * immediately. However cgg complained about not having a + * stackingrule for regX, so here it is + */ + + +COERCIONS + + +from STACK + uses DD_REG + gen move_l {post_inc4, sp}, %a + yields %a + +from STACK + uses AA_REG + gen move_l {post_inc4, sp}, %a + yields %a + +#ifndef m68020 +from t_regAregXcon sfit(%bd, 8) + yields {regAregXcon, %1.reg, %1.xreg, 1, %1.bd} + +from t_regAregXcon + uses AA_REG=%1.reg + gen add_l {const, %1.bd}, %a + yields {regAregXcon, %a, %1.xreg, 1, 0} + +from t_regAcon sfit(%bd, 16) + yields {regAcon, %1.reg, %1.bd} + +from t_regAcon + uses reusing %1, AA_REG=%1.reg + gen add_l {const, %1.bd}, %a + yields %a +#endif m68020 + +from t_address + uses reusing %1, AA_REG = %1 + yields %a + +from any4 + uses reusing %1, DD_REG = %1 + yields %a + +from any4 + uses reusing %1, AA_REG = %1 + yields %a + +from memory2 + uses DD_REG = {const, 0} + gen move_w %1, %a yields %a + +from memory1 + uses DD_REG = {const, 0} + gen move_b %1, %a yields %a + + + + +PATTERNS + +/************************************************ + * Group 0: rules for register variables * + * LOCALs mentioned here refer to registers * + ************************************************/ + +pat lol inreg($1)==reg_pointer + kills pre_post %reg==regvar($1, reg_pointer) + yields {LOCAL, $1} + +pat lil inreg($1)==reg_pointer + kills pre_post %reg==regvar($1, reg_pointer) + yields {indirect4, regvar($1, reg_pointer)} + +pat stl inreg($1)==reg_any +with any4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen move %1, {LOCAL, $1} + +pat stl inreg($1)==reg_pointer +with any4 + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen move %1, {LOCAL, $1} +with exact ext_addr + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen move %1, {LOCAL, $1} +with exact address-ext_addr + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen lea %1, {LOCAL, $1} + +pat sil inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move %1, {indirect4, regvar($1, reg_pointer)} + + +pat lol sbi stl $1==$3 && $2==4 && inreg($1)==reg_any +with any4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sub_l %1, {LOCAL, $1} + neg_l {LOCAL, $1} + +pat lol sbu stl $1==$3 && $2==4 && inreg($1)==reg_any +with any4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sub_l %1, {LOCAL, $1} + neg_l {LOCAL, $1} + +pat lil sbi sil $1==$3 && $2==4 && inreg($1)==reg_pointer +with conreg4 + kills allexceptcon + gen sub_l %1, {indirect4, regvar($1, reg_pointer)} + neg_l {indirect4, regvar($1, reg_pointer)} + +pat lil sbu sil $1==$3 && $2==4 && inreg($1)==reg_pointer +with conreg4 + kills allexceptcon + gen sub_l %1, {indirect4, regvar($1, reg_pointer)} + neg_l {indirect4, regvar($1, reg_pointer)} + + +pat lil ngi sil $1==$3 && $2==4 && inreg($1)==reg_pointer + kills allexceptcon + gen neg_l {indirect4, regvar($1, reg_pointer)} + +pat lil com sil $1==$3 && $2==4 && inreg($1)==reg_pointer + kills allexceptcon + gen not_l {indirect4, regvar($1, reg_pointer)} + + +proc lolcshstl example lol loc sli stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sh* {shconst, $2}, {LOCAL, $1} + +proc lolrshstl example lol lol sli stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sh* {LOCAL, $2}, {LOCAL, $1} + +proc lil1shlsil example lil loc sli sil /* only left */ + kills allexceptcon + gen shw* {offsetted2, regvar($1, reg_pointer), 2} + roxl {indirect2, regvar($1, reg_pointer)} + +proc lil1shrsil example lil loc sli sil /* only right */ + kills allexceptcon + gen shw* {indirect2, regvar($1, reg_pointer)} + roxr {offsetted2, regvar($1, reg_pointer), 2} + +pat lol loc sli stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("asl.l") +pat lol loc slu stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("asl.l") +pat lol lol sli stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("asl.l") +pat lol lol slu stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("asl.l") +pat lil loc sli sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shlsil("asl #1,") +pat lil loc slu sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shlsil("asl #1,") +pat lol loc sri stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("asr.l") +pat lol loc sru stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("lsr.l") +pat lol lol sri stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("asr.l") +pat lol lol sru stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("lsr.l") +pat lil loc sri sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shrsil("asr #1,") +pat lil loc sru sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shrsil("lsr #1,") +pat lol loc rol stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("rol.l") +pat lol lol rol stl $1==$4 && inreg($2)==reg_any && $3==4 && inreg($1)==reg_any + call lolrshstl("rol.l") +pat lol loc ror stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("ror.l") +pat lol lol ror stl $1==$4 && inreg($2)==reg_any && $3==4 && inreg($1)==reg_any + call lolrshstl("ror.l") + +#ifdef m68020 +pat lol loc dvi stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen divs_l {const, $2}, {LOCAL, $1} + +pat lol loc dvu stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen divu_l {const, $2}, {LOCAL, $1} + +pat lol loc mli stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen muls_l {const, $2}, {LOCAL, $1} + +pat lol loc mlu stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen mulu_l {const, $2}, {LOCAL, $1} + +pat lol mli stl $1==$3 && $2==4 && inreg($1)==reg_any + with data4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen muls_l %1, {LOCAL, $1} + +pat lol mlu stl $1==$3 && $2==4 && inreg($1)==reg_any + with data4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen mulu_l %1, {LOCAL, $1} +#endif m68020 + + +pat lil inc sil $1==$3 && inreg($1)==reg_pointer + kills allexceptcon + gen add_l {const, 1}, {indirect4, regvar($1, reg_pointer)} + +pat lil dec sil $1==$3 && inreg($1)==reg_pointer + kills allexceptcon + gen sub_l {const, 1}, {indirect4, regvar($1, reg_pointer)} + +pat inl inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen add_l {const, 1}, {LOCAL, $1} + +pat del inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sub_l {const, 1}, {LOCAL, $1} + +pat zrl inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen clr_l {LOCAL, $1} + +pat zrl inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen move_l {const, 0}, {LOCAL, $1} + + +proc lolxxstl example lol and stl +with data4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen xxx* %1, {LOCAL, $1} + +proc lilxxsil example lil and sil +with conreg4 + kills allexceptcon + gen xxx* %1, {indirect4, regvar($1, reg_pointer)} + +proc lolcxxstl example lol loc and stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen xxx* {const, $2}, {LOCAL, $1} + +proc lilcxxsil example lil loc and sil + kills allexceptcon + gen xxx* {const, $2}, {indirect4, regvar($1, reg_pointer)} + +proc lolrxxstl example lol lol and stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen xxx* {LOCAL, $2}, {LOCAL, $1} + +proc lilrxxsil example lil lol and sil + kills allexceptcon + gen xxx* {LOCAL, $2}, {indirect4, regvar($1, reg_pointer)} + +pat lol adi stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("add.l") +pat lol loc adi stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("add.l") +pat lil adi sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("add.l") +pat lil loc adi sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("add.l") +pat lol lol adi stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("add.l") +pat lil lol adi sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("add.l") +pat lol adu stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("add.l") +pat lol loc adu stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("add.l") +pat lil adu sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("add.l") +pat lil loc adu sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("add.l") +pat lol lol adu stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("add.l") +pat lil lol adu sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("add.l") +pat lol loc sbi stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("sub.l") +pat lil loc sbi sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("sub.l") +pat lol lol sbi stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("sub.l") +pat lil lol sbi sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("sub.l") +pat lol loc sbu stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("sub.l") +pat lil loc sbu sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("sub.l") +pat lol lol sbu stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("sub.l") +pat lil lol sbu sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("sub.l") +pat lol and stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("and.l") +pat lol loc and stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("and.l") +pat lil and sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("and.l") +pat lil loc and sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("and.l") +pat lol lol and stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("and.l") +pat lil lol and sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("and.l") +pat lol ior stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("or.l") +pat lol loc ior stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("or.l") +pat lil ior sil $1==$3 && $2==4 && inreg($1)==reg_pointer + call lilxxsil("or.l") +pat lil loc ior sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("or.l") +pat lol lol ior stl $1==$4 && $3==4 && inreg($1)==reg_any && + inreg($2)==reg_any + call lolrxxstl("or.l") +pat lil lol ior sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("or.l") +pat lol xor stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("eor.l") +pat lol loc xor stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("eor.l") +pat lil xor sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("eor.l") +pat lil loc xor sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("eor.l") +pat lol lol xor stl $1==$4 && $3==4 && inreg($1)==reg_any && + inreg($2)==reg_any + call lolrxxstl("eor.l") +pat lil lol xor sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("eor.l") + +pat lil adp sil $1==$3 && inreg($1)==reg_pointer + kills allexceptcon + gen add_l {const, $2}, {indirect4, regvar($1, reg_pointer)} + +pat lil lil adp sil $1==$2 && $1==$4 && inreg($1)==reg_pointer + kills allexceptcon + uses AA_REG = {indirect4, regvar($1, reg_pointer)} + gen add_l {const, $3}, {indirect4, regvar($1, reg_pointer)} + yields %a + +pat lol lol adp stl loi $1==$2 && $1==$4 && $3==1 && $5==1 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc1, regvar($1, reg_pointer)} + +pat lol loi lol adp stl $1==$3 && $1==$5 && $2==1 && $4==1 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc1, regvar($1, reg_pointer)} + +pat lol lol adp stl loi $1==$2 && $1==$4 && $3==2 && $5==2 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc2, regvar($1, reg_pointer)} + +pat lol loi lol adp stl $1==$3 && $1==$5 && $2==2 && $4==2 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc2, regvar($1, reg_pointer)} + +pat lol lol adp stl loi $1==$2 && $1==$4 && $3==4 && $5==4 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc4, regvar($1, reg_pointer)} + +pat lil lol adp stl $1==$2 && $1==$4 && $3==4 && inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc4, regvar($1, reg_pointer)} + +pat lol lol adp stl sti $1==$2 && $1==$4 && $3==1 && $5==1 && + inreg($1)==reg_pointer +with data1 + kills allexceptcon + gen move %1, {post_inc1, regvar($1, reg_pointer)} + +pat lol sti lol adp stl $1==$3 && $1==$5 && $2==1 && $4==1 && + inreg($1)==reg_pointer +with data1 + kills allexceptcon + gen move %1, {post_inc1, regvar($1, reg_pointer)} + +pat lol lol adp stl sti $1==$2 && $1==$4 && $3==2 && $5==2 && + inreg($1)==reg_pointer +with any2 + kills allexceptcon + gen move %1, {post_inc2, regvar($1, reg_pointer)} + +pat lol sti lol adp stl $1==$3 && $1==$5 && $2==2 && $4==2 && + inreg($1)==reg_pointer +with any2 + kills allexceptcon + gen move %1, {post_inc2, regvar($1, reg_pointer)} + +pat lol lol adp stl sti $1==$2 && $1==$4 && $3==4 && $5==4 && + inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move_l %1, {post_inc4, regvar($1, reg_pointer)} + +pat sil lol adp stl $1==$2 && $1==$4 && $3==4 && inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move_l %1, {post_inc4, regvar($1, reg_pointer)} + +pat lol adp stl lol loi $1==$3 && $1==$4 && $2==0-1 && $5==1 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {pre_dec1, regvar($1, reg_pointer)} + +pat lol adp stl lol loi $1==$3 && $1==$4 && $2==0-2 && $5==2 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {pre_dec2, regvar($1, reg_pointer)} + +pat lol adp stl lil $1==$3 && $1==$4 && $2==0-4 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {pre_dec4, regvar($1, reg_pointer)} + +pat lol adp stl lol sti $1==$3 && $1==$4 && $2==0-1 && $5==1 && + inreg($1)==reg_pointer +with data1 + kills allexceptcon + gen move %1, {pre_dec1, regvar($1, reg_pointer)} + +pat lol adp stl lol sti $1==$3 && $1==$4 && $2==0-2 && $5==2 && + inreg($1)==reg_pointer +with any2 + kills allexceptcon + gen move %1, {pre_dec2, regvar($1, reg_pointer)} + +pat lol adp stl sil $1==$3 && $1==$4 && $2==0-4 && + inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move_l %1, {pre_dec4, regvar($1, reg_pointer)} + + + + +/************************************************ + * Group 1: load instructions * + ************************************************/ + +pat loc yields {const, $1} + +pat ldc leaving loc 18 trp + +pat lol yields {LOCAL, $1} + +pat ldl leaving lol $1+4 lol $1 + +pat loe yields {absolute4, $1} + +pat lil +#ifdef m68020 + yields {ILOCAL, $1} +#else m68020 + uses AA_REG = {LOCAL, $1} + yields {indirect4, %a} +#endif m68020 + + /* When using the 'offsetted' intructions regAregXcon cannot be used + * for the m68k4; there is no way of knowing about the size of + * %1.bd+$1, because expressions are not allowed in stack patterns, and + * this may lead to outputting too large displacements. With regAcon + * the chance that this will happen is very slim, because it can + * have displacements of 16 bits. Besides, leaving out regAcon here + * would make it very hard to handle this instruction efficiently. + */ +pat lof +with A_REG yields {offsetted4, %1, $1} +with exact local_addr yields {LOCAL, %1.bd+$1} +with exact ext_addr yields {absolute4, %1.bd+$1} +#ifndef m68020 +with regAcon yields {offsetted4, %1.reg, %1.bd+$1} +#else m68020 +with exact regAcon yields {offsetted4, %1.reg, %1.bd+$1} +with exact regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} +with exact offsetted4 yields {OFF_off4, %1.reg, %1.bd, $1} +with exact indirect yields {OFF_off4, %1.reg, 0, $1} +with exact LOCAL yields {OFF_off4, lb, %1.bd, $1} +with exact off_con yields {OFF_off4, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon yields {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 yields {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con yields {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 yields {ABS_off4, %1.bd, $1} +with exact abs_con yields {ABS_off4, %1.bd, %1.od+$1} +with exact abs_regXcon yields {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX yields {abs_index4, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat lal yields {local_addr, $1} + +pat lae yields {ext_addr, $1} + +pat lxl $1==0 yields lb + +pat lxl $1==1 yields {LOCAL, SL} + +pat lxl $1==2 +#ifdef m68020 + yields {OFF_off4, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + yields {offsetted4, %a, SL} +#endif m68020 + +pat lxl $1==3 +#ifdef m68020 + uses AA_REG = {OFF_off4, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + gen move {offsetted4, %a, SL}, %a +#endif m68020 + yields {offsetted4, %a, SL} + +pat lxl $1>3 + uses AA_REG = {LOCAL, SL}, + DD_REG = {const, $1-2} + gen 1: + move_l {offsetted4, %a, SL} ,%a + dbf %b, {slabel, 1b} + yields %a + +pat lxa $1==0 yields {local_addr, SL} + +pat lxa $1==1 +#ifdef m68020 + yields {off_con, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + yields {regAcon, %a, SL} +#endif m68020 + +pat lxa $1==2 +#ifdef m68020 + uses AA_REG = {OFF_off4, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + gen move {offsetted4, %a, SL}, %a +#endif m68020 + yields {regAcon, %a, SL} + +pat lxa $1>2 + uses AA_REG = {LOCAL, SL}, + DD_REG = {const, $1-1} + gen 1: + move_l {offsetted4, %a, SL} ,%a + dbf %b, {slabel, 1b} + yields {regAcon, %a, SL} + +pat loi $1==1 +with A_REG yields {indirect1, %1} +with exact local_addr yields {offsetted1, lb, %1.bd} +with exact ext_addr yields {absolute1, %1.bd} +#ifndef m68020 +with regAcon yields {offsetted1, %1.reg, %1.bd} +with regAregXcon yields {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon yields {offsetted1, %1.reg, %1.bd} +with exact regAregXcon yields {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 yields {OFF_off1, %1.reg, 0, 0} +with exact offsetted4 yields {OFF_off1, %1.reg, %1.bd, 0} +with exact LOCAL yields {OFF_off1, lb, %1.bd, 0} +with exact off_con yields {OFF_off1, %1.reg, %1.bd, %1.od} +with exact off_regXcon yields {OFF_indoff1, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 yields {INDOFF_off1, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con yields {INDOFF_off1, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 yields {ABS_off1, %1.bd, 0} +with exact abs_con yields {ABS_off1, %1.bd, %1.od} +with exact abs_regXcon yields {ABS_indoff1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 yields {ABSIND_off1, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con yields {ABSIND_off1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX yields {abs_index1, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat loi $1==2 +with A_REG yields {indirect2, %1} +with exact local_addr yields {offsetted2, lb, %1.bd} +with exact ext_addr yields {absolute2, %1.bd} +#ifndef m68020 +with regAcon yields {offsetted2, %1.reg, %1.bd} +with regAregXcon yields {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon yields {offsetted2, %1.reg, %1.bd} +with exact regAregXcon yields {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 yields {OFF_off2, %1.reg, 0, 0} +with exact offsetted4 yields {OFF_off2, %1.reg, %1.bd, 0} +with exact LOCAL yields {OFF_off2, lb, %1.bd, 0} +with exact off_con yields {OFF_off2, %1.reg, %1.bd, %1.od} +with exact off_regXcon yields {OFF_indoff2, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 yields {INDOFF_off2, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con yields {INDOFF_off2, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 yields {ABS_off2, %1.bd, 0} +with exact abs_con yields {ABS_off2, %1.bd, %1.od} +with exact abs_regXcon yields {ABS_indoff2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 yields {ABSIND_off2, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con yields {ABSIND_off2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX yields {abs_index2, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat loi $1==4 +with A_REG yields {indirect4, %1} +with exact local_addr yields {LOCAL, %1.bd} +with exact ext_addr yields {absolute4, %1.bd} +#ifndef m68020 +with regAcon yields {offsetted4, %1.reg, %1.bd} +with regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon yields {offsetted4, %1.reg, %1.bd} +with exact regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact LOCAL yields {ILOCAL, %1.bd} +with exact indirect4 yields {OFF_off4, %1.reg, 0, 0} +with exact offsetted4 yields {OFF_off4, %1.reg, %1.bd, 0} +with exact off_con yields {OFF_off4, %1.reg, %1.bd, %1.od} +with exact off_regXcon yields {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 yields {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con yields {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 yields {ABS_off4, %1.bd, 0} +with exact abs_con yields {ABS_off4, %1.bd, %1.od} +with exact abs_regXcon yields {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX yields {abs_index4, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat loi $1==8 +with A_REG yields {offsetted4, %1, 4} + {indirect4, %1} +pat loi $1>8 +with AA_REG STACK + uses DD_REG = {const, $1/4 -1} + gen add_l {const, $1}, %1 + 1: + move_l {pre_dec4, %1}, {pre_dec4, sp} + dbf %a, {slabel, 1b} + +pat los $1==4 +with STACK + gen jsr {absolute4, ".los"} + +pat lde yields {absolute4, $1+4} + {absolute4, $1} + +pat ldf +with A_REG yields {offsetted4, %1, $1+4} + {offsetted4, %1, $1} +with exact local_addr yields {LOCAL, %1.bd+$1+4} + {LOCAL, %1.bd+$1} +with exact ext_addr yields {absolute4, %1.bd+$1+4} + {absolute4, %1.bd+$1} +#ifndef m68020 +with regAcon yields {offsetted4, %1.reg, %1.bd+$1+4} + {offsetted4, %1.reg, %1.bd+$1} +#else m68020 +with exact regAcon yields {offsetted4, %1.reg, %1.bd+$1+4} + {offsetted4, %1.reg, %1.bd+$1} +with exact regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1+4} + {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} +with exact indirect4 yields {OFF_off4, %1.reg, 0, $1+4} + {OFF_off4, %1.reg, 0, $1} +with exact offsetted4 yields {OFF_off4, %1.reg, %1.bd, $1+4} + {OFF_off4, %1.reg, %1.bd, $1} +with exact LOCAL yields {OFF_off4, lb, %1.bd, $1+4} + {OFF_off4, lb, %1.bd, $1} +with exact off_con yields {OFF_off4, %1.reg, %1.bd, %1.od+$1+4} + {OFF_off4, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon yields {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} + {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 yields {INDOFF_off4, %1.reg, %1.xreg, %1.sc,%1.bd,$1+4} + {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con yields {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} + {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 yields {ABS_off4, %1.bd, $1+4} + {ABS_off4, %1.bd, $1} +with exact abs_con yields {ABS_off4, %1.bd, %1.od+$1+4} + {ABS_off4, %1.bd, %1.od+$1} +with exact abs_regXcon yields {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} + {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1+4} + {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} + {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX yields {abs_index4, %1.sc, %1.xreg, %1.bd+$1+4} + {abs_index4, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat lpi yields {ext_addr, $1} + + + +/************************************************ + * Group 2: store instructions * + ************************************************/ + +pat stl +with any4 + kills all_indir, LOCAL %bd==$1 + gen move %1, {LOCAL, $1} +with exact STACK + gen move {post_inc4,sp}, {LOCAL, $1} + +pat ste +with any4 + kills posextern + gen move %1, {absolute4, $1} +with exact STACK + gen move {post_inc4, sp}, {absolute4, $1} + +pat sil +#ifdef m68020 +with any4 + kills allexceptcon + gen move %1, {ILOCAL, $1} +with exact STACK + gen move {post_inc4, sp}, {ILOCAL, $1} +#else m68020 +with any4 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen move %1, {indirect4, %a} +with exact STACK + uses AA_REG = {LOCAL, $1} + gen move {post_inc4, sp}, {indirect4, %a} +#endif m68020 + +pat stf +with A_REG any4 + kills allexceptcon + gen move %2, {offsetted4, %1, $1} +with A_REG STACK + gen move {post_inc4, sp}, {offsetted4, %1, $1} +with exact local_addr any4 + kills allexceptcon + gen move %2, {LOCAL, %1.bd+$1} +with exact ext_addr any4 + kills allexceptcon + gen move %2, {absolute4, %1.bd+$1} +#ifndef m68020 +with regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} +#else m68020 +with exact regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} +with exact regAregXcon any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} +with exact indirect4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, 0, $1} +with exact offsetted4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, $1} +with exact LOCAL any4 + kills allexceptcon + gen move %2, {OFF_off4, lb, %1.bd, $1} +with exact off_con any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon any4 + kills allexceptcon + gen move %2, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, $1} +with exact abs_con any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, %1.od+$1} +with exact abs_regXcon any4 + kills allexceptcon + gen move %2, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX any4 + kills allexceptcon + gen move %2, {abs_index4, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat sti $1==1 +with A_REG data1 + kills allexceptcon + gen move %2, {indirect1, %1} +with exact local_addr data1 + kills allexceptcon + gen move %2, {offsetted1, lb, %1.bd} +with exact ext_addr data1 + kills allexceptcon + gen move %2, {absolute1, %1.bd} +#ifndef m68020 +with regAcon data1 + kills allexceptcon + gen move %2, {offsetted1, %1.reg, %1.bd} +with regAregXcon data1 + kills allexceptcon + gen move %2, {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon data1 + kills allexceptcon + gen move %2, {offsetted1, %1.reg, %1.bd} +with exact regAregXcon data1 + kills allexceptcon + gen move %2, {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 data1 + kills allexceptcon + gen move %2, {OFF_off1, %1.reg, 0, 0} +with exact offsetted4 data1 + kills allexceptcon + gen move %2, {OFF_off1, %1.reg, %1.bd, 0} +with exact LOCAL data1 + kills allexceptcon + gen move %2, {OFF_off1, lb, %1.bd, 0} +with exact off_con data1 + kills allexceptcon + gen move %2, {OFF_off1, %1.reg, %1.bd, %1.od} +with exact off_regXcon data1 + kills allexceptcon + gen move %2, {OFF_indoff1, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 data1 + kills allexceptcon + gen move %2, {INDOFF_off1, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con data1 + kills allexceptcon + gen move %2, {INDOFF_off1, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 data1 + kills allexceptcon + gen move %2, {ABS_off1, %1.bd, 0} +with exact abs_con data1 + kills allexceptcon + gen move %2, {ABS_off1, %1.bd, %1.od} +with exact abs_regXcon data1 + kills allexceptcon + gen move %2, {ABS_indoff1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 data1 + kills allexceptcon + gen move %2, {ABSIND_off1, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con data1 + kills allexceptcon + gen move %2, {ABSIND_off1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX data1 + kills allexceptcon + gen move %2, {abs_index1, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat sti $1==2 +with A_REG any2 + kills allexceptcon + gen move %2, {indirect2, %1} +with exact local_addr any2 + kills allexceptcon + gen move %2, {offsetted2, lb, %1.bd} +with exact ext_addr any2 + kills allexceptcon + gen move %2, {absolute2, %1.bd} +#ifndef m68020 +with regAcon any2 + kills allexceptcon + gen move %2, {offsetted2, %1.reg, %1.bd} +with regAregXcon any2 + kills allexceptcon + gen move %2, {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon any2 + kills allexceptcon + gen move %2, {offsetted2, %1.reg, %1.bd} +with exact regAregXcon any2 + kills allexceptcon + gen move %2, {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 any2 + kills allexceptcon + gen move %2, {OFF_off2, %1.reg, 0, 0} +with exact offsetted4 any2 + kills allexceptcon + gen move %2, {OFF_off2, %1.reg, %1.bd, 0} +with exact LOCAL any2 + kills allexceptcon + gen move %2, {OFF_off2, lb, %1.bd, 0} +with exact off_con any2 + kills allexceptcon + gen move %2, {OFF_off2, %1.reg, %1.bd, %1.od} +with exact index_off4 any2 + kills allexceptcon + gen move %2, {INDOFF_off2, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact off_regXcon any2 + kills allexceptcon + gen move %2, {OFF_indoff2, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact indoff_con any2 + kills allexceptcon + gen move %2, {INDOFF_off2, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 any2 + kills allexceptcon + gen move %2, {ABS_off2, %1.bd, 0} +with exact abs_con any2 + kills allexceptcon + gen move %2, {ABS_off2, %1.bd, %1.od} +with exact abs_regXcon any2 + kills allexceptcon + gen move %2, {ABS_indoff2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 any2 + kills allexceptcon + gen move %2, {ABSIND_off2, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con any2 + kills allexceptcon + gen move %2, {ABSIND_off2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX any2 + kills allexceptcon + gen move %2, {abs_index2, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat sti $1==4 +with A_REG any4 + kills allexceptcon + gen move %2, {indirect4, %1} +with A_REG STACK + gen move {post_inc4, sp}, {indirect4, %1} +with exact local_addr any4 + kills allexceptcon + gen move %2, {LOCAL, %1.bd} +with exact ext_addr any4 + kills allexceptcon + gen move %2, {absolute4, %1.bd} +#ifndef m68020 +with regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd} +with regAregXcon any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd} +with exact regAregXcon any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact LOCAL any4 + kills allexceptcon + gen move %2, {ILOCAL, %1.bd} +with exact indirect4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, 0, 0} +with exact offsetted4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, 0} +with exact off_con any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, %1.od} +with exact off_regXcon any4 + kills allexceptcon + gen move %2, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, 0} +with exact abs_con any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, %1.od} +with exact abs_regXcon any4 + kills allexceptcon + gen move %2, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX any4 + kills allexceptcon + gen move %2, {abs_index4, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat sti $1>4 +with AA_REG STACK + uses DD_REG = {const, $1/4 -1} + gen 1: + move_l {post_inc4, sp}, {post_inc4, %1} + dbf %a, {slabel, 1b} + +pat sts $1==4 +with STACK + gen jsr {absolute4, ".sts"} + +pat sdl +with any4 any4 + kills all_indir, LOCAL %bd==$1 + gen move %1, {LOCAL, $1} + move %2, {LOCAL, $1+4} + +pat sde +with any4 any4 + kills posextern + gen move %1, {absolute4, $1} + move %2, {absolute4, $1+4} + +pat sdf +with A_REG any4 any4 + kills allexceptcon + gen move %2, {offsetted4, %1, $1} + move %3, {offsetted4, %1, $1+4} +with exact local_addr any4 any4 + kills allexceptcon + gen move %2, {LOCAL, %1.bd+$1} + move %3, {LOCAL, %1.bd+$1+4} +with exact ext_addr any4 any4 + kills allexceptcon + gen move %2, {absolute4, %1.bd+$1} + move %3, {absolute4, %1.bd+$1+4} +#ifndef m68020 +with regAcon any4 any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} + move %3, {offsetted4, %1.reg, %1.bd+$1+4} +#else m68020 +with exact regAcon any4 any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} + move %3, {offsetted4, %1.reg, %1.bd+$1+4} +with exact regAregXcon any4 any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} + move %3, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1+4} +with exact indirect4 any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, 0, $1} + move %3, {OFF_off4, %1.reg, 0, $1+4} +with exact offsetted4 any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, $1} + move %3, {OFF_off4, %1.reg, %1.bd, $1+4} +with exact LOCAL any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, lb, %1.bd, $1} + move %3, {OFF_off4, lb, %1.bd, $1+4} +with exact off_con any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, %1.od+$1} + move %3, {OFF_off4, %1.reg, %1.bd, %1.od+$1+4} +with exact off_regXcon any4 any4 + kills allexceptcon + gen move %2, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} + move %3, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} +with exact index_off4 any4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} + move %3, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1+4} +with exact indoff_con any4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} + move %3, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} +with exact absolute4 any4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, $1} + move %3, {ABS_off4, %1.bd, $1+4} +with exact abs_con any4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, %1.od+$1} + move %3, {ABS_off4, %1.bd, %1.od+$1+4} +with exact abs_regXcon any4 any4 + kills allexceptcon + gen move %2, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} + move %3, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} +with exact abs_index4 any4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} + move %3, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1+4} +with exact absind_con any4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} + move %3, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} +with exact ext_regX any4 any4 + kills allexceptcon + gen move %2, {abs_index4, %1.sc, %1.xreg, %1.bd+$1} + move %3, {abs_index4, %1.sc, %1.xreg, %1.bd+$1+4} +#endif m68020 + + + +/************************************************ + * Group 3: integer arithmetic. * + ************************************************/ + + +pat adi $1==4 +with any4 DD_REG + gen add_l %1, %2 yields %2 +with DD_REG any4-DD_REG + gen add_l %2, %1 yields %1 +with DD_REG STACK + gen add_l {post_inc4, sp}, %1 + yields %1 + +pat sbi $1==4 +with any4 DD_REG + gen sub_l %1, %2 yields %2 +with DD_REG any4-DD_REG + gen sub_l %2, %1 + neg_l %1 yields %1 +with DD_REG STACK + gen sub_l {post_inc4, sp}, %1 + neg_l %1 yields %1 +with any4 AA_REG + gen sub_l %1, %2 yields %2 + +pat mli $1==4 +#ifdef m68020 +with data4 DD_REG + gen muls_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".mli"} + yields d1 +#endif m68020 + +pat dvi $1==4 +#ifdef m68020 +with data4 DD_REG + gen divs_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".dvi"} + yields d1 +#endif m68020 + +pat rmi $1==4 +#ifdef m68020 +with data4 DD_REG + uses DD_REG + gen divsl_l %1, {DREG_pair, %a, %2} + killreg %2 + /* !!!! contents of %2 have changed: make this known to cg */ + yields %a +#else m68020 +with STACK + gen jsr {absolute4, ".dvi"} + yields d0 +#endif m68020 + +pat ngi $1==4 +with DD_REG + gen neg_l %1 yields %1 + +pat sli $1==4 +with D_REG DD_REG + gen asl_l %1, %2 yields %2 + +pat sri $1==4 +with D_REG DD_REG + gen asr_l %1, %2 yields %2 + + + +/************************************************ + * Group 4: unsigned arithmetic. * + ************************************************/ + + +pat adu leaving adi $1 + +pat sbu leaving sbi $1 + +pat mlu $1==4 +#ifdef m68020 +with data4 DD_REG + gen mulu_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".mlu"} + yields d1 +#endif m68020 + +pat dvu $1==4 +#ifdef m68020 +with data4 DD_REG + gen divu_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".dvu"} + yields d1 +#endif m68020 + +pat rmu $1==4 +#ifdef m68020 +with data4 DD_REG + uses DD_REG + gen divul_l %1, {DREG_pair, %a, %2} + killreg %2 + /* !!!! contents of %2 have changed: make this known to cg */ + yields %a +#else m68020 +with STACK + gen jsr {absolute4, ".dvu"} + yields d0 +#endif m68020 + +pat slu leaving sli $1 + +pat sru $1==4 +with D_REG DD_REG + gen lsr_l %1, %2 yields %2 + + + +/************************************************ + * Group 5: floating point arithmetic * + * * + * is not available on 68000, 68010 or 68020 * + * so traps will be generated * + ************************************************/ + +pat adf leaving loc 18 trp +pat sbf leaving loc 18 trp +pat mlf leaving loc 18 trp +pat dvf leaving loc 18 trp +pat ngf leaving loc 18 trp +pat fif leaving loc 18 trp +pat fef leaving loc 18 trp + + + +/************************************************ + * Group 6: pointer arithmetic * + ************************************************/ + +pat adp $1==0 /* skip; array instructions might 'leave' this */ + +pat adp +with A_REG yields {t_regAcon, %1, $1} +with exact local_addr yields {local_addr, %1.bd+$1} +with exact ext_addr yields {ext_addr, %1.bd+$1} +with exact regAcon + t_regAcon + yields {t_regAcon, %1.reg, %1.bd+$1} +with exact regAregXcon + t_regAregXcon + yields {t_regAregXcon,%1.reg, %1.xreg, %1.sc, %1.bd+$1} +#ifdef m68020 +with exact indirect4 yields {off_con, %1.reg, 0, $1} +with exact LOCAL yields {off_con, lb, %1.bd, $1} +with exact offsetted4 yields {off_con, %1.reg, %1.bd, $1} +with exact off_con yields {off_con, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon yields {off_regXcon, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 yields {indoff_con, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con yields {indoff_con, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 yields {abs_con, %1.bd, $1} +with exact abs_con yields {abs_con, %1.bd, %1.od+$1} +with exact abs_regXcon yields {abs_regXcon, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 yields {absind_con, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con yields {absind_con, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX yields {ext_regX, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat ads $1==4 +with D_REG A_REG yields {regAregXcon, %2, %1, 1, 0} +with D_REG regAcon + t_regAcon + yields {t_regAregXcon, %2.reg, %1, 1, %2.bd} +with D_REG local_addr yields {t_regAregXcon, lb, %1, 1, %2.bd} +with any4-D_REG AA_REG + gen add_l %1, %2 yields %2 + +#ifdef m68020 + +with D_REG yields {regX, 1, %1} + leaving ads 4 +with regX A_REG yields {regAregXcon, %2, %1.xreg, %1.sc, 0} +with exact regX regAcon yields {regAregXcon, %2.reg, %1.xreg, %1.sc, %2.bd} +with exact regX local_addr + yields {regAregXcon, lb, %1.xreg, %1.sc, %2.bd} +with exact regX ext_addr + yields {ext_regX, %1.sc, %1.xreg, %2.bd} +with exact regX indirect4 + yields {off_regXcon, %2.reg, %1.xreg,%1.sc,0,0} +with exact regX offsetted4 + yields {off_regXcon, %2.reg, %1.xreg, %1.sc, %2.bd, 0} +with exact regX LOCAL yields {off_regXcon, lb, %1.xreg, %1.sc, %2.bd, 0} +with exact regX off_con yields {off_regXcon, %2.reg, %1.xreg,%1.sc,%2.bd,%2.od} +with exact regX absolute4 + yields {abs_regXcon, %1.sc, %1.xreg, %2.bd, 0} +with exact regX abs_con yields {abs_regXcon, %1.sc, %1.xreg, %2.bd, %2.od} +with exact indirect4 ext_addr + yields {off_con, %1.reg, 0, %2.bd} +with exact offsetted4 ext_addr + yields {off_con, %1.reg, %1.bd, %2.bd} +with exact LOCAL ext_addr + yields {off_con, lb, %1.bd, %2.bd} +with exact index_off4 ext_addr + yields {indoff_con, %1.reg, %1.xreg, %1.sc,%1.bd,%2.bd} +with exact absolute4 ext_addr + yields {abs_con, %1.bd, %2.bd} +with exact abs_index4 ext_addr + yields {absind_con, %1.sc, %1.xreg, %1.bd, %2.bd} +with exact indirect4 ext_regX + yields {off_regXcon, %1.reg, %2.xreg, %2.sc, 0, %2.bd} +with exact offsetted4 ext_regX + yields {off_regXcon, %1.reg, %2.xreg,%2.sc,%1.bd,%2.bd} +with exact LOCAL ext_regX + yields {off_regXcon, lb, %2.xreg, %2.sc, %1.bd, %2.bd} +with exact absolute4 ext_regX + yields {abs_regXcon, %2.sc, %2.xreg, %1.bd, %2.bd} +#endif m68020 + + /* I WOULD ALSO LIKE THIS: + * pat ads + * with const leaving adp %1.num + * BUT THAT DOESN'T WORK. + */ + +pat sbs $1==4 leaving sbi 4 + +#ifdef m68020 +pat loc sli ads $1==1 && $2==4 && $3==4 +with D_REG yields {regX, 2, %1} + leaving ads 4 + +pat loc sli ads $1==2 && $2==4 && $3==4 +with D_REG yields {regX, 4, %1} + leaving ads 4 + +pat loc sli ads $1==3 && $2==4 && $3==4 +with D_REG yields {regX, 8, %1} + leaving ads 4 +#endif m68020 + + +/************************************************ + * Group 7: increment / decrement / zero * + ************************************************/ + +pat inc +with exact STACK + gen add_l {const, 1}, {indirect4, sp} +with DD_REG+AA_REG + gen add_l {const, 1}, %1 + yields %1 + +pat inl + kills all_indir, LOCAL %bd==$1 + gen add_l {const, 1}, {LOCAL, $1} + +pat ine + kills posextern + gen add_l {const, 1}, {absolute4, $1} + +pat dec +with exact STACK + gen sub_l {const, 1}, {indirect4, sp} +with DD_REG+AA_REG + gen sub_l {const, 1}, %1 + yields %1 + +pat del + kills all_indir, LOCAL %bd==$1 + gen sub_l {const, 1}, {LOCAL, $1} + +pat dee + kills posextern + gen sub_l {const, 1}, {absolute4, $1} + +pat zrl + kills all_indir, LOCAL %bd==$1 + gen clr_l {LOCAL, $1} + +pat zre + kills posextern + gen clr_l {absolute4, $1} + +pat zer $1==4 yields {const, 0} +pat zer $1==8 yields {const, 0} {const, 0} +pat zer $1==12 yields {const, 0} {const, 0} {const, 0} + +pat zer +with STACK + uses DD_REG = {const, $1/4 -1} + gen 1: + clr_l {pre_dec4, sp} + dbf %a, {slabel, 1b} + + +pat zrf leaving loc 18 trp + + + +/************************************************ + * Group 8: convert instructions * + * for float conversions traps are generated * + ************************************************/ + + + +pat cii +with STACK + gen jsr {absolute4, ".cii"} + +pat cuu +with STACK + gen jsr {absolute4, ".cuu"} + +pat ciu leaving cuu + +pat cui leaving cuu + +pat cfi leaving loc 18 trp +pat cif leaving loc 18 trp +pat cfu leaving loc 18 trp +pat cuf leaving loc 18 trp +pat cff leaving loc 18 trp + + +/************************************************ + * Group 9: logical instructions * + ************************************************/ + + +proc log4 +with datalt4+const DD_REG + gen xxx* %1, %2 yields %2 +with DD_REG datalt4+const + gen xxx* %2, %1 yields %1 + +proc logdef example and +with STACK + uses DD_REG = {const, $1/4 -1}, + AA_REG = {regAcon, sp, $1}, + DD_REG + gen 1: + move_l {post_inc4, sp}, %c + xxx* %c, {post_inc4, %b} + dbf %a, {slabel, 1b} + +proc logndef +with DD_REG STACK + uses AA_REG = {regAregXcon, sp, %1, 1, 0}, + DD_REG + gen asr_l {shconst, 2}, %1 + sub_l {const, 1}, %1 + 1: + move_l {post_inc4, sp}, %b + xxx* %b, {post_inc4, %a} + dbf %1, {slabel, 1b} + +pat and $1==4 call log4("and.l") +pat and $1>4 call logdef("and.l") +pat and !defined($1) call logndef("and.l") +pat ior $1==4 call log4("or.l") +pat ior $1>4 call logdef("or.l") +pat ior !defined($1) call logndef("or.l") + +pat xor $1==4 +with conreg4 DD_REG + gen eor_l %1, %2 yields %2 +with DD_REG conreg4 + gen eor_l %2, %1 yields %1 + +pat xor $1>4 call logdef("eor.l") +pat xor !defined($1) call logndef("eor.l") + +pat com $1==4 +with DD_REG + gen not_l %1 yields %1 + +pat com $1==8 +with DD_REG DD_REG + gen not_l %1 + not_l %2 yields %2 %1 + +pat com $1>4 +with STACK + uses AA_REG, + DD_REG = {const, $1/4 -1} + gen move_l sp, %a + 1: + not_l {post_inc4, %a} + dbf %b, {slabel, 1b} + +pat com !defined($1) +with DD_REG STACK + uses AA_REG + gen move_l sp, %a + asr_l {shconst, 2}, %1 + sub_l {const, 1}, %1 + 1: + not_l {post_inc4, %a} + dbf %1, {slabel, 1b} + +pat rol $1==4 +with D_REG DD_REG + gen rol_l %1, %2 yields %2 + +pat ror $1==4 +with D_REG DD_REG + gen ror_l %1, %2 yields %2 + + + + +/************************************************ + * Group 10: sets * + ************************************************/ + + +pat inn $1==4 +with conreg2 DD_REG + gen btst %1, %2 + sne %2 + and_l {const, 1}, %2 + yields %2 + +pat inn defined($1) +with any4 STACK + gen move %1, d0 + move {const, $1}, d1 + jsr {absolute4, ".inn"} + yields d0 + +pat inn !defined($1) +with any4 any4 STACK + gen move %2, d0 + move %1, d1 + jsr {absolute4, ".inn"} + yields d0 + +pat loc inn $2==4 && small($1) +with DD_REG + gen asr_l {shconst, $1}, %1 + and_l {const, 1}, %1 + yields %1 + +pat set $1==4 +with conreg2 + uses DD_REG = {const, 0} + gen bset %1, %a yields %a + +pat set $1>4 +with any4 STACK + gen move %1, d0 + move {const, $1}, d1 + jsr {absolute4, ".set"} + +pat set !defined($1) +with any4 any4 STACK + gen move %2, d0 + move %1, d1 + jsr {absolute4, ".set"} + + + + +/************************************************ + * Group 11: arrays * + ************************************************/ + + +pat lar defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".lar"} + +pat lar !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".lar"} + +pat sar defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".sar"} + +pat sar !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".sar"} + +pat aar defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".aar"} + yields a0 + +pat aar !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".aar"} + yields a0 + +pat lae lar $2==4 && nicesize(rom($1,3)) + leaving lae $1 aar 4 loi rom($1, 3) +pat lae sar $2==4 && nicesize(rom($1,3)) + leaving lae $1 aar 4 sti rom($1, 3) + +pat lae aar $2==4 && rom($1,3)==1 + leaving ads 4 adp 0-rom($1,1) + +#ifdef m68020 +pat lae aar $2==4 && nicesize(rom($1,3)) +with D_REG yields {regX, rom($1,3), %1} + leaving ads 4 adp rom($1,3)*(0-rom($1,1)) +#else m68020 +pat lae aar $2==4 && rom($1,3)==2 +with DD_REG + gen asl_l {shconst, 1}, %1 + yields %1 + leaving ads 4 adp (0 - rom($1,1))<<1 + +pat lae aar $2==4 && rom($1,3)==4 +with DD_REG + gen asl_l {shconst, 2}, %1 + yields %1 + leaving ads 4 adp (0 - rom($1,1))<<2 + +pat lae aar $2==4 && rom($1,3)==8 +with DD_REG + gen asl_l {shconst, 3}, %1 + yields %1 + leaving ads 4 adp (0 - rom($1,1))<<3 +#endif m68020 + + /* I WOULD ALSO LIKE THESE: + * pat lae aar $2==4 && defined(rom($1,3)) + * with const leaving adp rom($1,3)*(%1.num-rom($1,1)) + * pat lae lar $2==4 && defined(rom($1,3)) + * with const leaving adp rom($1,3)*(%1.num-rom($1,1)) + * loi rom($1,3) + * pat lae sar $2==4 && defined(rom($1,3)) + * with const leaving adp rom($1,3)*(%1.num-rom($1,1)) + * sti rom($1,3) + * BUT THEY DON'T WORK. + */ + + + +/************************************************ + * Group 12: compare instructions * + ************************************************/ + + +pat cmi $1==4 leaving sbi 4 + +pat cmi defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".cmi"} + yields d0 + +pat cmi !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".cmi"} + yields d0 + +pat cmu $1==4 leaving sbi 4 + +pat cmu defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".cmu"} + yields d0 + +pat cmu !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".cmu"} + yields d0 + +pat cms $1==4 leaving sbi 4 + +pat cms defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".cms"} + yields d0 + +pat cms !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".cms"} + yields d0 + +pat cmp leaving cmu 4 + +proc txx +with test_set + uses DD_REG = {const, 1} + gen test %1 + bxx* {slabel, 1f} + clr_l %a + 1: + yields %a + +pat tlt call txx("blt") +pat tle call txx("ble") +pat teq call txx("beq") +pat tne call txx("bne") +pat tge call txx("bge") +pat tgt call txx("bgt") + +pat cmf leaving loc 18 trp + + + +/************************************************ + * Group 13: branch instructions * + ************************************************/ + +pat bra +with STACK + gen bra {llabel, $1} + +proc brxx example beq +with any4 genreg STACK + gen cmp_l %1, %2 + bxx[1] {llabel, $1} +with genreg any4 STACK + gen cmp_l %2, %1 + bxx[2] {llabel, $1} +with exact immediate4 imm_cmp4 + kills ALL + gen cmp_l %1, %2 + bxx[1] {llabel, $1} +with exact imm_cmp4 immediate4 + kills ALL + gen cmp_l %2, %1 + bxx[2] {llabel, $1} +with genreg STACK + gen cmp_l {post_inc4, sp}, %1 + bxx[2] {llabel, $1} +with exact immediate4 STACK + gen cmp_l %1, {post_inc4, sp} + bxx[1] {llabel, $1} +with any2-conreg2 genreg STACK + gen cmp_w %1, %2 + bxx[1] {llabel, $1} +with genreg any2-conreg2 STACK + gen cmp_w %2, %1 + bxx[2] {llabel, $1} +with exact const imm_cmp2 + kills ALL + gen cmp_w {const, loww(%1.num)}, %2 + bxx[1] {llabel, $1} +with exact imm_cmp2 const + kills ALL + gen cmp_w {const, loww(%2.num)}, %1 + bxx[2] {llabel, $1} +with data1-conreg1 D_REG STACK + gen cmp_b %1, %2 + bxx[1] {llabel, $1} +with D_REG data1-conreg1 STACK + gen cmp_b %2, %1 + bxx[2] {llabel, $1} +with exact const imm_cmp1 + kills ALL + gen cmp_b {const, lowb(%1.num)}, %2 + bxx[1] {llabel, $1} +with exact imm_cmp1 const + kills ALL + gen cmp_b {const, lowb(%2.num)}, %1 + bxx[2] {llabel, $1} + +pat blt call brxx("blt","bgt") +pat ble call brxx("ble","bge") +pat beq call brxx("beq","beq") +pat bne call brxx("bne","bne") +pat bge call brxx("bge","ble") +pat bgt call brxx("bgt","blt") + +proc zxx example zeq +with test_set STACK + gen test %1 + bxx* {llabel, $1} +with exact STACK + gen test {post_inc4, sp} + bxx* {llabel, $1} + +pat zlt call zxx("blt") +pat zle call zxx("ble") +pat zeq call zxx("beq") +pat zne call zxx("bne") +pat zge call zxx("bge") +pat zgt call zxx("bgt") + +/************************************************ + * Group 14: procedure calls instructions * + ************************************************/ + + +pat cai +with exact ext_addr + kills ALL + gen jsr {absolute4, %1.bd} +with A_REG STACK + gen jsr {indirect4, %1} +with STACK + uses AA_REG = {post_inc4, sp} + gen jsr {indirect4, %a} +#ifdef m68020 +with exact address + kills ALL + gen jsr %1 +#else m68020 +with address STACK + gen jsr %1 +#endif m68020 + +pat cal +with STACK + gen jsr {absolute4, $1} + +pat lfr $1==4 yields d0 +pat lfr $1==8 yields d1 d0 + +pat ret $1==0 +with STACK + gen return + +pat ret $1==4 +with any4 STACK + gen move %1, d0 + return +with STACK + gen move {post_inc4, sp}, d0 + return + +pat ret $1==8 +with any4 any4 STACK + gen move %1, d0 + move %2, d1 + return +with any4 STACK + gen move %1, d0 + move {post_inc4, sp}, d1 + return +with STACK + gen move {post_inc4, sp}, d0 + move {post_inc4, sp}, d1 + return + + +/************************************************ + * Group 15: miscellaneous instructions * + ************************************************/ + +pat asp small($1) +with STACK + gen add_l {const, $1}, sp +pat asp +with STACK + gen move {regAcon, sp, $1}, sp + +pat ass $1==4 +with any4 STACK + gen add_l %1, sp + +pat blm $1==4 +with A_REG A_REG + kills allexceptcon + gen move_l {indirect4, %2}, {indirect4, %1} + +pat blm $1==8 +with A_REG A_REG + kills allexceptcon + gen move_l {indirect4, %2}, {indirect4, %1} + move_l {offsetted4, %2, 4}, {offsetted4, %1, 4} + +pat blm $1>8 +with AA_REG AA_REG + kills allexceptcon + uses DD_REG={const, $1/4 -1} + gen 1: + move_l {post_inc4, %2}, {post_inc4, %1} + dbf %a, {slabel, 1b} + +pat bls $1==4 +with DD_REG AA_REG AA_REG + kills allexceptcon + gen asr_l {shconst, 2}, %1 + beq {slabel, 2f} + sub_l {const, 1}, %1 + 1: + move_l {post_inc4, %3}, {post_inc4, %2} + dbf %1, {slabel, 1b} + 2: + +pat csa $1==4 +with STACK + gen jmp {absolute4, ".csa"} + +pat csb $1==4 +with STACK + gen jmp {absolute4, ".csb"} + +pat dch leaving loi 4 + +pat dup $1==4 +with exact STACK + gen move_l {indirect4, sp}, {pre_dec4, sp} +with any4 yields %1 %1 + +pat dup $1==8 +with exact STACK + gen move_l {offsetted4, sp, 4}, {pre_dec4, sp} + move_l {offsetted4, sp, 4}, {pre_dec4, sp} +with any4 any4 yields %2 %1 %2 %1 + +pat dup $1>8 +with STACK + uses DD_REG = {const, $1/4 -1} + gen 1: + move_l {offsetted4, sp, $1 -4}, {pre_dec4, sp} + dbf %a, {slabel, 1b} + +pat dus $1==4 +with DD_REG STACK + uses AA_REG = {regAregXcon, sp, %1, 1, 0} + gen asr_l {shconst, 2}, %1 + beq {slabel, 2f} + sub_l {const, 1}, %1 + 1: + move_l {pre_dec4, %a}, {pre_dec4, sp} + dbf %1, {slabel, 1b} + 2: + +pat exg $1==4 +with any4 any4 yields %1 %2 + +pat exg defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".exg"} + +pat exg !defined($1) +with any4 STACK + gen move_l %1, d0 + jsr {absolute4, ".exg"} + +pat fil + gen move_l {ext_addr, $1}, {absolute4, ".filn"} + +pat gto +with STACK + uses AA_REG = {ext_addr, $1} + gen move_l {offsetted4, %a, 8}, lb + move_l {offsetted4, %a, 4}, sp +#ifdef m68020 + jmp {OFF_off4, %a, 0, 0} +#else m68020 + move_l {indirect4, %a}, %a + jmp {indirect4, %a} +#endif m68020 + +pat lim yields {absolute4, ".trpim"} + +pat lin + gen move {const, $1}, {absolute4, ".lino"} + +pat lni + gen add_l {const, 1}, {absolute4, ".lino"} + +pat lor $1==0 yields lb + +pat lor $1==1 +with STACK + uses AA_REG = sp yields %a + +pat lor $1==2 yields {absolute4, ".reghp"} + +pat lpb leaving adp 8 + +pat mon +with STACK + gen jsr {absolute4, ".mon"} + +pat nop +with STACK + gen jsr {absolute4, ".nop"} + +pat rck +#ifdef m68020 +with ext_addr D_REG + gen cmp2_l {absolute4, %1.bd}, %2 + bcc {slabel, 1f} + pea {absolute4, 1} /* push constant 1 == ERANGE */ + jsr {absolute4, ".trp"} + 1: yields %2 +with address-ext_addr D_REG + gen cmp2_l %1, %2 + bcc {slabel, 1f} + pea {absolute4, 1} /* push constant 1 == ERANGE */ + jsr {absolute4, ".trp"} + 1: yields %2 +with A_REG D_REG + gen cmp2_l {indirect4, %1}, %2 + bcc {slabel, 1f} + pea {absolute4, 1} /* push constant 1 == ERANGE */ + jsr {absolute4, ".trp"} + 1: yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".rck"} +#endif m68020 + +pat rtt leaving ret 0 + +pat sig +with any4 + uses AA_REG + gen move {absolute4, ".trppc"}, %a + move %1, {absolute4, ".trppc"} + yields %a + +pat sim +with any4 + gen move_l %1, {absolute4, ".trpim"} + +pat str $1==0 +with any4 +#ifdef m68020 + kills LOCAL, ILOCAL, all_regind %reg==lb, local_addr +#else m68020 + kills LOCAL, all_regind %reg==lb, local_addr +#endif m68020 + gen move %1, lb + +pat str $1==1 +with any4 STACK + gen move %1, sp + +pat str $1==2 +with STACK + gen jsr {absolute4, ".strhp"} + +pat trp +with STACK + gen jsr {absolute4, ".trp"} + + + +/************************************************ + * rules for long EM-patterns * + ************************************************/ + +proc lolxxxstl example lol adi stl +with conreg4 + kills all_indir, LOCAL %bd==$1 + gen xxx* %1, {LOCAL, $1} + +proc loexxxste example loe adi ste +with conreg4 + kills posextern + gen xxx* %1, {absolute4, $1} + +proc lilxxxsil example lil adi sil +with conreg4 +#ifdef m68020 + kills allexceptcon + gen xxx* %1, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen xxx* %1, {indirect4, %a} +#endif m68020 + +proc lolcxxxstl example lol loc adi stl + kills all_indir, LOCAL %bd==$1 + gen xxx* {const, $2}, {LOCAL, $1} + +proc loecxxxste example loe loc adi ste + kills posextern + gen xxx* {const, $2}, {absolute4, $1} + +proc lilcxxxsil example lil loc adi sil +#ifdef m68020 + kills allexceptcon + gen xxx* {const, $2}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen xxx* {const, $2}, {indirect4, %a} +#endif m68020 + +proc lolrxxxstl example lol lol adi stl + kills all_indir, LOCAL %bd==$1 + gen xxx* {LOCAL, $2}, {LOCAL, $1} + +proc loerxxxste example loe lol adi ste + kills posextern + gen xxx* {LOCAL, $2}, {absolute4, $1} + +proc lilrxxxsil example lil lol adi sil +#ifdef m68020 + kills allexceptcon + gen xxx* {LOCAL, $2}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen xxx* {LOCAL, $2}, {indirect4, %a} +#endif m68020 + +pat lol adi stl $1==$3 && $2==4 call lolxxxstl("add.l") +pat loe adi ste $1==$3 && $2==4 call loexxxste("add.l") +pat lil adi sil $1==$3 && $2==4 call lilxxxsil("add.l") +pat lol loc adi stl $1==$4 && $3==4 call lolcxxxstl("add.l") +pat loe loc adi ste $1==$4 && $3==4 call loecxxxste("add.l") +pat lil loc adi sil $1==$4 && $3==4 call lilcxxxsil("add.l") +pat lol lol adi stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("add.l") +pat loe lol adi ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("add.l") +pat lil lol adi sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("add.l") + +pat lol adu stl $1==$3 && $2==4 call lolxxxstl("add.l") +pat loe adu ste $1==$3 && $2==4 call loexxxste("add.l") +pat lil adu sil $1==$3 && $2==4 call lilxxxsil("add.l") +pat lol loc adu stl $1==$4 && $3==4 call lolcxxxstl("add.l") +pat loe loc adu ste $1==$4 && $3==4 call loecxxxste("add.l") +pat lil loc adu sil $1==$4 && $3==4 call lilcxxxsil("add.l") +pat lol lol adu stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("add.l") +pat loe lol adu ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("add.l") +pat lil lol adu sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("add.l") + + +pat lol adp stl $1==$3 + kills all_indir, LOCAL %bd==$1 + gen add_l {const, $2}, {LOCAL, $1} + +pat lil adp sil $1==$3 + kills allexceptcon +#ifdef m68020 + gen add_l {const, $2}, {ILOCAL, $1} +#else m68020 + uses AA_REG = {LOCAL, $1} + gen add_l {const, $2}, {indirect4, %a} +#endif m68020 + +pat loe adp ste $1==$3 + kills posextern + gen add_l {const, $2}, {absolute4, $1} + +pat lol lol adp stl $1==$2 && $1==$4 + kills all_indir, LOCAL %bd==$1 + uses AA_REG = {LOCAL, $1} + gen add_l {const, $3}, {LOCAL, $1} + yields %a + +pat lil lil adp sti $1==$2 && $1==$4 + kills allexceptcon +#ifdef m68020 + uses AA_REG = {ILOCAL, $1} + gen add_l {const, $3}, {ILOCAL, $1} +#else m68020 + uses AA_REG, AA_REG = {LOCAL, $1} + gen move {indirect4, %b}, %a + add_l {const, $3}, {indirect4, %b} +#endif m68020 + yields %a + +pat loe loe adp ste $1==$2 && $1==$4 + kills posextern + uses AA_REG = {absolute4, $1} + gen add_l {const, $3}, {absolute4, $1} + yields %a + + +pat lol loc sbi stl $1==$4 && $3==4 call lolcxxxstl("sub.l") +pat loe loc sbi ste $1==$4 && $3==4 call loecxxxste("sub.l") +pat lil loc sbi sil $1==$4 && $3==4 call lilcxxxsil("sub.l") +pat lol lol sbi stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("sub.l") +pat loe lol sbi ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("sub.l") +pat lil lol sbi sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("sub.l") + +pat lol loc sbu stl $1==$4 && $3==4 call lolcxxxstl("sub.l") +pat loe loc sbu ste $1==$4 && $3==4 call loecxxxste("sub.l") +pat lil loc sbu sil $1==$4 && $3==4 call lilcxxxsil("sub.l") +pat lol lol sbu stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("sub.l") +pat loe lol sbu ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("sub.l") +pat lil lol sbu sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("sub.l") + +pat lol and stl $1==$3 && $2==4 call lolxxxstl("and.l") +pat loe and ste $1==$3 && $2==4 call loexxxste("and.l") +pat lil and sil $1==$3 && $2==4 call lilxxxsil("and.l") +pat lol loc and stl $1==$4 && $3==4 call lolcxxxstl("and.l") +pat loe loc and ste $1==$4 && $3==4 call loecxxxste("and.l") +pat lil loc and sil $1==$4 && $3==4 call lilcxxxsil("and.l") +pat lol lol and stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("and.l") +pat loe lol and ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("and.l") +pat lil lol and sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("and.l") + +pat lol ior stl $1==$3 && $2==4 call lolxxxstl("or.l") +pat loe ior ste $1==$3 && $2==4 call loexxxste("or.l") +pat lil ior sil $1==$3 && $2==4 call lilxxxsil("or.l") +pat lol loc ior stl $1==$4 && $3==4 call lolcxxxstl("or.l") +pat loe loc ior ste $1==$4 && $3==4 call loecxxxste("or.l") +pat lil loc ior sil $1==$4 && $3==4 call lilcxxxsil("or.l") +pat lol lol ior stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("or.l") +pat loe lol ior ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("or.l") +pat lil lol ior sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("or.l") + +pat lol xor stl $1==$3 && $2==4 call lolxxxstl("eor.l") +pat loe xor ste $1==$3 && $2==4 call loexxxste("eor.l") +pat lil xor sil $1==$3 && $2==4 call lilxxxsil("eor.l") +pat lol loc xor stl $1==$4 && $3==4 call lolcxxxstl("eor.l") +pat loe loc xor ste $1==$4 && $3==4 call loecxxxste("eor.l") +pat lil loc xor sil $1==$4 && $3==4 call lilcxxxsil("eor.l") +pat lol lol xor stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("eor.l") +pat loe lol xor ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("eor.l") +pat lil lol xor sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("eor.l") + +proc llol1shstl example lol loc sli stl /* only left */ + kills all_indir, LOCAL %bd==$1 + gen shw* {offsetted2, lb, $1+2} + roxl {offsetted2, lb, $1} + +proc lloe1shste example loe loc sli ste /* only left */ + kills posextern + gen shw* {absolute2, $1+2} + roxl {absolute2, $1} + +proc llil1shsil example lil loc sli sil /* only left */ +#ifdef m68020 + kills allexceptcon + gen shw* {OFF_off2, lb, $1, 2} + roxl {OFF_off2, lb, $1, 0} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen shw* {offsetted2, %a, 2} + roxl {indirect2, %a} +#endif m68020 + +proc rlol1shstl example lol loc sri stl /* only right */ + kills all_indir, LOCAL %bd==$1 + gen shw* {offsetted2, lb, $1} + roxr {offsetted2, lb, $1+2} + +proc rloe1shste example loe loc sri ste /* only right */ + kills posextern + gen shw* {absolute2, $1} + roxr {absolute2, $1+2} + +proc rlil1shsil example lil loc sri sil /* only right */ +#ifdef m68020 + kills allexceptcon + gen shw* {OFF_off2, lb, $1, 0} + roxr {OFF_off2, lb, $1, 2} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen shw* {indirect2, %a} + roxr {offsetted2, %a, 2} +#endif m68020 + +pat lol loc sli stl $1==$4 && $2==1 && $3==4 call llol1shstl("asl #1,") +pat loe loc sli ste $1==$4 && $2==1 && $3==4 call lloe1shste("asl #1,") +pat lil loc sli sil $1==$4 && $2==1 && $3==4 call llil1shsil("asl #1,") +pat lol loc sri stl $1==$4 && $2==1 && $3==4 call rlol1shstl("asr #1,") +pat loe loc sri ste $1==$4 && $2==1 && $3==4 call rloe1shste("asr #1,") +pat lil loc sri sil $1==$4 && $2==1 && $3==4 call rlil1shsil("asr #1,") +pat lol loc slu stl $1==$4 && $2==1 && $3==4 call llol1shstl("asl #1,") +pat loe loc slu ste $1==$4 && $2==1 && $3==4 call lloe1shste("asl #1,") +pat lil loc slu sil $1==$4 && $2==1 && $3==4 call llil1shsil("asl #1,") +pat lol loc sru stl $1==$4 && $2==1 && $3==4 call rlol1shstl("lsr #1,") +pat loe loc sru ste $1==$4 && $2==1 && $3==4 call rloe1shste("lsr #1,") +pat lil loc sru sil $1==$4 && $2==1 && $3==4 call rlil1shsil("lsr #1,") + +proc locsh example loc sli +with DD_REG + gen sh* {shconst, $1}, %1 + yields %1 + +pat loc sli small($1) && $2==4 call locsh("asl.l") +pat loc sri small($1) && $2==4 call locsh("asr.l") +pat loc slu small($1) && $2==4 call locsh("asl.l") +pat loc sru small($1) && $2==4 call locsh("lsr.l") +pat loc rol small($1) && $2==4 call locsh("rol.l") +pat loc ror small($1) && $2==4 call locsh("ror.l") + +proc lolbitstl example lol ngi stl + kills all_indir, LOCAL %bd==$1 + gen bit* {LOCAL, $1} + +proc loebitste example loe ngi ste + kills posextern + gen bit* {absolute4, $1} + +proc lilbitsil example lil ngi sil +#ifdef m68020 + kills allexceptcon + gen bit* {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen bit* {indirect4, %a} +#endif m68020 + +pat lol ngi stl $1==$3 && $2==4 call lolbitstl("neg.l") +pat loe ngi ste $1==$3 && $2==4 call loebitste("neg.l") +pat lil ngi sil $1==$3 && $2==4 call lilbitsil("neg.l") +pat lol com stl $1==$3 && $2==4 call lolbitstl("not.l") +pat loe com ste $1==$3 && $2==4 call loebitste("not.l") +pat lil com sil $1==$3 && $2==4 call lilbitsil("not.l") + +pat lil inc sil $1==$3 +#ifdef m68020 + kills allexceptcon + gen add_l {const, 1}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen add_l {const, 1}, {indirect4, %a} +#endif m68020 + +pat lil dec sil $1==$3 +#ifdef m68020 + kills allexceptcon + gen sub_l {const, 1}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen sub_l {const, 1}, {indirect4, %a} +#endif m68020 + + +proc txxand +with test_set DD_REG + gen test %1 + bxx* {slabel, 1f} + clr_l %2 + 1: yields %2 + +proc txxior +with test_set DD_REG + gen test %1 + bxx* {slabel, 1f} + bset {const, 0}, %2 + 1: yields %2 + +pat tlt and $2==4 call txxand("blt") +pat tle and $2==4 call txxand("ble") +pat teq and $2==4 call txxand("beq") +pat tne and $2==4 call txxand("bne") +pat tge and $2==4 call txxand("bge") +pat tgt and $2==4 call txxand("bgt") + +pat tlt ior $2==4 call txxior("bge") +pat tle ior $2==4 call txxior("bgt") +pat teq ior $2==4 call txxior("bne") +pat tne ior $2==4 call txxior("beq") +pat tge ior $2==4 call txxior("blt") +pat tgt ior $2==4 call txxior("ble") + +proc cmxtxxand +with any4 genreg DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %3 + 1: yields %3 +with genreg any4-genreg DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %3 + 1: yields %3 +with exact immediate4 imm_cmp4 DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %3 + 1: yields %3 +with exact imm_cmp4 immediate4 DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %3 + 1: yields %3 + +proc cmxtxxior +with any4 genreg DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 +with genreg any4-genreg DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 +with exact immediate4 imm_cmp4 DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 +with exact imm_cmp4 immediate4 DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 + +proc cmxtxx +with any4 genreg + uses DD_REG = {const, 1} + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %a + 1: yields %a +with genreg any4-genreg + uses DD_REG = {const, 1} + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %a + 1: yields %a +with exact immediate4 imm_cmp4 + uses DD_REG = {const, 1} + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %a + 1: yields %a +with exact imm_cmp4 immediate4 + uses DD_REG = {const, 1} + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %a + 1: yields %a +with genreg STACK + uses DD_REG = {const, 1} + gen cmp_l {post_inc4, sp}, %1 + bxx[2] {slabel, 1f} + clr_l %a + 1: yields %a +with exact immediate4 STACK + uses DD_REG = {const, 1} + gen cmp_l %1, {post_inc4, sp} + bxx[1] {slabel, 1f} + clr_l %a + 1: yields %a + +pat cmi tlt and $1==4 && $3==4 call cmxtxxand("blt","bgt") +pat cmi tle and $1==4 && $3==4 call cmxtxxand("ble","bge") +pat cmi teq and $1==4 && $3==4 call cmxtxxand("beq","beq") +pat cmi tne and $1==4 && $3==4 call cmxtxxand("bne","bne") +pat cmi tge and $1==4 && $3==4 call cmxtxxand("bge","ble") +pat cmi tgt and $1==4 && $3==4 call cmxtxxand("bgt","blt") + +pat cmu tlt and $1==4 && $3==4 call cmxtxxand("bcs","bhi") +pat cmu tle and $1==4 && $3==4 call cmxtxxand("bls","bcc") +pat cmu teq and $1==4 && $3==4 call cmxtxxand("beq","beq") +pat cmu tne and $1==4 && $3==4 call cmxtxxand("bne","bne") +pat cmu tge and $1==4 && $3==4 call cmxtxxand("bcc","bls") +pat cmu tgt and $1==4 && $3==4 call cmxtxxand("bhi","bcs") + +pat cmi tlt ior $1==4 && $3==4 call cmxtxxior("bge","ble") +pat cmi tle ior $1==4 && $3==4 call cmxtxxior("bgt","blt") +pat cmi teq ior $1==4 && $3==4 call cmxtxxior("bne","bne") +pat cmi tne ior $1==4 && $3==4 call cmxtxxior("beq","beq") +pat cmi tge ior $1==4 && $3==4 call cmxtxxior("blt","bgt") +pat cmi tgt ior $1==4 && $3==4 call cmxtxxior("ble","bge") + +pat cmu tlt ior $1==4 && $3==4 call cmxtxxior("bcc","bls") +pat cmu tle ior $1==4 && $3==4 call cmxtxxior("bhi","bcs") +pat cmu teq ior $1==4 && $3==4 call cmxtxxior("bne","bne") +pat cmu tne ior $1==4 && $3==4 call cmxtxxior("beq","beq") +pat cmu tge ior $1==4 && $3==4 call cmxtxxior("bcs","bhi") +pat cmu tgt ior $1==4 && $3==4 call cmxtxxior("bls","bcc") + +pat cmi tlt $1==4 call cmxtxx("blt","bgt") +pat cmi tle $1==4 call cmxtxx("ble","bge") +pat cmi teq $1==4 call cmxtxx("beq","beq") +pat cmi tne $1==4 call cmxtxx("bne","bne") +pat cmi tge $1==4 call cmxtxx("bge","blt") +pat cmi tgt $1==4 call cmxtxx("bgt","blt") + +pat cmu tlt $1==4 call cmxtxx("bcs","bhi") +pat cmu tle $1==4 call cmxtxx("bls","bcc") +pat cmu teq $1==4 call cmxtxx("beq","beq") +pat cmu tne $1==4 call cmxtxx("bne","bne") +pat cmu tge $1==4 call cmxtxx("bcc","bls") +pat cmu tgt $1==4 call cmxtxx("bhi","bcs") + +proc cmxzxx example cmu zlt +with any4 genreg STACK + gen cmp_l %1, %2 + bxx[1] {llabel, $2} +with genreg any4-genreg STACK + gen cmp_l %2, %1 + bxx[2] {llabel, $2} +with exact immediate4 imm_cmp4 + kills ALL + gen cmp_l %1, %2 + bxx[1] {llabel, $2} +with exact imm_cmp4 immediate4 + kills ALL + gen cmp_l %2, %1 + bxx[2] {llabel, $2} +with genreg STACK + gen cmp_l {post_inc4, sp}, %1 + bxx[2] {llabel, $2} +with exact immediate4 STACK + gen cmp_l %1, {post_inc4, sp} + bxx[1] {llabel, $2} + +pat cmu zlt $1==4 call cmxzxx("bcs","bhi") +pat cmu zle $1==4 call cmxzxx("bls","bcc") +pat cmu zeq $1==4 call cmxzxx("beq","beq") +pat cmu zne $1==4 call cmxzxx("bne","bne") +pat cmu zge $1==4 call cmxzxx("bcc","bls") +pat cmu zgt $1==4 call cmxzxx("bhi","bcs") + + +proc bxx1_in example loc loc cii loc bne +with imm_cmp1 STACK + gen cmp_b {const, lowb($4)}, %1 + bxx* {llabel, $5} + +proc bxx2_in example loc loc cii loc bne +with imm_cmp2 STACK + gen cmp_w {const, loww($4)}, %1 + bxx* {llabel, $5} + +pat loc loc cii loc blt $1==1 && $2==4 && in_1($4) call bxx1_in("blt") +pat loc loc cii loc ble $1==1 && $2==4 && in_1($4) call bxx1_in("ble") +pat loc loc cii loc beq $1==1 && $2==4 && in_1($4) call bxx1_in("beq") +pat loc loc cii loc bne $1==1 && $2==4 && in_1($4) call bxx1_in("bne") +pat loc loc cii loc bge $1==1 && $2==4 && in_1($4) call bxx1_in("bge") +pat loc loc cii loc bgt $1==1 && $2==4 && in_1($4) call bxx1_in("bgt") + +pat loc loc cii loc blt $1==2 && $2==4 && in_2($4) call bxx2_in("blt") +pat loc loc cii loc ble $1==2 && $2==4 && in_2($4) call bxx2_in("ble") +pat loc loc cii loc beq $1==2 && $2==4 && in_2($4) call bxx2_in("beq") +pat loc loc cii loc bne $1==2 && $2==4 && in_2($4) call bxx2_in("bne") +pat loc loc cii loc bge $1==2 && $2==4 && in_2($4) call bxx2_in("bge") +pat loc loc cii loc bgt $1==2 && $2==4 && in_2($4) call bxx2_in("bgt") + +pat loc loc cii $1==1 && $2==2 +with DD_REG + gen ext_w %1 yields %1 + +pat loc loc cii $1==2 && $2==4 +with DD_REG + gen ext_l %1 yields %1 + +pat loc loc cii $1==1 && $2==4 +with DD_REG +#ifdef m68020 + gen extb_l %1 yields %1 +#else m68020 + gen ext_w %1 + ext_l %1 yields %1 +#endif m68020 + +pat loc loc ciu $1==$2 /* skip this */ +pat loc loc cui $1==$2 /* skip this */ + + +/* The following rules should be handled by the peephole optimizer, I think */ + +pat loc dvi $1==2 && $2==4 leaving loc 1 sri 4 +pat loc dvi $1==4 && $2==4 leaving loc 2 sri 4 +pat loc dvi $1==8 && $2==4 leaving loc 3 sri 4 +pat loc dvi $1==16 && $2==4 leaving loc 4 sri 4 +pat loc dvi $1==32 && $2==4 leaving loc 5 sri 4 +pat loc dvi $1==64 && $2==4 leaving loc 6 sri 4 +pat loc dvi $1==128 && $2==4 leaving loc 7 sri 4 +pat loc dvi $1==256 && $2==4 leaving loc 8 sri 4 + +pat loc dvu $1==2 && $2==4 leaving loc 1 sru 4 +pat loc dvu $1==4 && $2==4 leaving loc 2 sru 4 +pat loc dvu $1==8 && $2==4 leaving loc 3 sru 4 +pat loc dvu $1==16 && $2==4 leaving loc 4 sru 4 +pat loc dvu $1==32 && $2==4 leaving loc 5 sru 4 +pat loc dvu $1==64 && $2==4 leaving loc 6 sru 4 +pat loc dvu $1==128 && $2==4 leaving loc 7 sru 4 +pat loc dvu $1==256 && $2==4 leaving loc 8 sru 4 diff --git a/mach/m68k2/ncg/mach.c b/mach/m68k2/ncg/mach.c new file mode 100644 index 000000000..ec51f8bf1 --- /dev/null +++ b/mach/m68k2/ncg/mach.c @@ -0,0 +1,236 @@ +/* + * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands. + * + * This product is part of the Amsterdam Compiler Kit. + * + * Permission to use, sell, duplicate or disclose this software must be + * obtained in writing. Requests for such permissions may be sent to + * + * Dr. Andrew S. Tanenbaum + * Wiskundig Seminarium + * Vrije Universiteit + * Postbox 7161 + * 1007 MC Amsterdam + * The Netherlands + * + */ + +/* + * machine dependent back end routines for the Motorola 68000, 68010 or 68020 + */ + +#ifndef m68k4 +#define m68020 +#endif + /* use m68020 when you want a m68020 cg, don't if you want a + * m68k4 cg. The m68k4 cg can be used for both the MC68000 + * and the MC68010. + */ + +con_part(sz,w) register sz; word w; { + + while (part_size % sz) + part_size++; + if (part_size == 4) + 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) + w <<= 16; + part_word |= w; + } else { + assert(sz == 4); + part_word = w; + } + part_size += sz; +} + +con_mult(sz) word sz; { + + if (sz != 4) + fatal("bad icon/ucon size"); + fprintf(codefile,".data4 %s\n",str); +} + +con_float() { + +static int been_here; + if (argval != 4 && argval != 8) + fatal("bad fcon size"); + fprintf(codefile,".data4\t"); + if (argval == 8) + fprintf(codefile,"F_DUM,"); + fprintf(codefile,"F_DUM\n"); + if ( !been_here++) + { + fprintf(stderr,"Warning : dummy float-constant(s)\n"); + } +} + +regscore(off,size,typ,score,totyp) + long off; +{ + if (score == 0) return -1; + switch(typ) { + case reg_float: + return -1; + case reg_pointer: + if (size != 4 || totyp != reg_pointer) return -1; + score *= 2; + break; + case reg_loop: + score += 5; + /* fall through .. */ + case reg_any: + if (size != 4 || totyp == reg_pointer) return -1; + break; + } + if (off >= 0) { + /* parameters must be initialised with an instruction + * like "move.l 4(a6),d0", which costs 2 words. + */ + score -= 2; + } + score -= 1; /* take save/restore into account */ + return score; +} +struct regsav_t { + char *rs_reg; /* e.g. "a3" or "d5" */ + long rs_off; /* offset of variable */ + int rs_size; /* 2 or 4 bytes */ +} regsav[9]; + + +int regnr; + +i_regsave() +{ + regnr = 0; +} + +#define MOVEM_LIMIT 2 +/* If #registers to be saved exceeds MOVEM_LIMIT, we +* use the movem instruction to save registers; else +* we simply use several move.l's. +*/ + +save() +{ + register struct regsav_t *p; + + if (regnr > MOVEM_LIMIT) { + fprintf(codefile,"movem.l "); + for (p = regsav; ;) { + fprintf(codefile,"%s",p->rs_reg); + if (++p == ®sav[regnr]) break; + putc('/',codefile); + } + fprintf(codefile,",-(sp)\n"); + } else { + for (p = regsav; p < ®sav[regnr]; p++) { + fprintf(codefile,"move.l %s,-(sp)\n",p->rs_reg); + } + } + /* initialise register-parameters */ + for (p = regsav; p < ®sav[regnr]; p++) { + if (p->rs_off >= 0) { +#ifdef m68020 + fprintf(codefile,"move.%c (%ld,a6),%s\n", +#else + fprintf(codefile,"move.%c %ld(a6),%s\n", +#endif + (p->rs_size == 4 ? 'l' : 'w'), + p->rs_off, + p->rs_reg); + } + } +} + +restr() +{ + register struct regsav_t *p; + + if (regnr > MOVEM_LIMIT) { + fprintf(codefile,"movem.l (sp)+,"); + for (p = regsav; ;) { + fprintf(codefile,"%s",p->rs_reg); + if (++p == ®sav[regnr]) break; + putc('/',codefile); + } + putc('\n',codefile); + } else { + for (p = ®sav[regnr-1]; p >= regsav; p--) { + fprintf(codefile,"move.l (sp)+,%s\n",p->rs_reg); + } + } + fprintf(codefile,"unlk a6\n"); + fprintf(codefile,"rts\n"); +} + + +f_regsave() +{ + save(); +} + +regsave(str,off,size) + char *str; + long off; +{ + assert (regnr < 9); + regsav[regnr].rs_reg = str; + regsav[regnr].rs_off = off; + regsav[regnr++].rs_size = size; + fprintf(codefile, "!Local %ld into %s\n",off,str); +} + +regreturn() +{ + restr(); +} + + +prolog(nlocals) full nlocals; { + +#ifdef m68020 + fprintf(codefile,"tst.b (-%ld,sp)\nlink\ta6,#-%ld\n",nlocals+40,nlocals); +#else + fprintf(codefile,"tst.b -%ld(sp)\nlink\ta6,#-%ld\n",nlocals+40,nlocals); +#endif +} + + + +mes(type) 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", /* SEGTXT */ + ".sect .data", /* SEGCON */ + ".sect .rom", /* SEGROM */ + ".sect .bss" /* SEGBSS */ +}; diff --git a/mach/m68k2/ncg/mach.h b/mach/m68k2/ncg/mach.h new file mode 100644 index 000000000..ff2cf66ca --- /dev/null +++ b/mach/m68k2/ncg/mach.h @@ -0,0 +1,39 @@ +#ifndef m68k4 +#define m68020 +#endif + /* m68020 should be used for a m68020 cg, and it should + * not be used for a m68k4 cg + */ + +#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,"%s:.space\t%ld\n",l,x); + +#define pop_fmt "(sp)+" +#define cst_fmt "%ld" +#define off_fmt "%ld" +#define ilb_fmt "I%03x%x" +#define dlb_fmt "_%d" +#define hol_fmt "hol%d" + +#ifdef m68020 +#define loc_off "(%d,a6)" +#define arg_off "(8+%d,a6)" +#else +#define loc_off "%d(a6)" +#define arg_off "8+%d(a6)" +#endif +#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 modhead ".sect .text\n.sect .rom\n.sect .data\n.sect .bss\n" + +#define id_first '_' +#define BSS_INIT 0 diff --git a/mach/m68k2/ncg/table b/mach/m68k2/ncg/table new file mode 100644 index 000000000..6518487ad --- /dev/null +++ b/mach/m68k2/ncg/table @@ -0,0 +1,3288 @@ + /******************************** + * * + * 68000, 68010 and 68020 * + * back end table * + * * + ********************************/ + + +#ifndef m68k4 +#define m68020 +#endif + /* m68020 to be defined if this is the 68020 table. + * The 68000 and 68010 tables are identical. + */ + + +#define small(x) ((x)>=1 && (x)<=8) +#define nicesize(x) ((x)==1||(x)==2||(x)==4||(x)==8) +#define lowb(x) (((x)<<24)>>24) +#define loww(x) (((x)<<16)>>16) +#define in_1(x) ((x)>=0-128 && (x)<128) +#define in_2(x) ((x)>=0-32768 && (x)<32768) + + +EM_WSIZE = 4 +EM_PSIZE = 4 +EM_BSIZE = 8 + +SL = 8 + +TIMEFACTOR = 1/2 + + +PROPERTIES + +D_REG /* data registers */ +A_REG /* address registers */ +DD_REG /* allocatable D_REG, may not be a register variable */ +AA_REG /* allocatable A_REG, may not be a register variable */ + + + +REGISTERS + +d0, d1, d2 :D_REG, DD_REG. +d3, d4, d5, d6, d7 :D_REG regvar. +a0, a1 :A_REG, AA_REG. +a2, a3, a4, a5 :A_REG regvar(reg_pointer). +lb ("a6"), sp :A_REG. /* localbase and stack pointer */ + + + + +TOKENS + + /* Not all addressing modes available on the MC68020 are used in this + * table. E.g (Dn), data register indirect is not used. Compared to + * (An), address register indirect, (Dn) requires two more bytes and + * several more clock cycles. Using (Dn) is even more expensive in + * time than first moving Dn to an address register An, and then using + * (An). For this kind of reasons several addressing modes are + * not used in this table. + * + * Cost in bytes may sometimes be incorrect. Several effective addresses + * use displacements that can occupy either 2 or 4 bytes. These are not + * considered different TOKENS in this table. + * + * Data registers are the only registers used as index registers in this + * table; address registers are only used to hold addresses. + * + * For the m68k4 table: the MC68000 and MC68010 have two modes that use + * displacements (offsets) of limited size: + * - offset(A_REG, Index_reg), where offset is only 8 bits, and + * - offset(A_REG), where offset can only be 16 bits. + * To make sure that no output is given with offsets too large, two + * extra tokens are declared: t_regAregXcon and t_regAcon. These are + * used as addresses to these modes. Whenever the displacements become + * too large, they are transformed into different tokens. + * + * Sometimes some TOKENS are used with displacements (offsets) of 0. + * It would have been possible to provide separate TOKENS for these, in + * case the assembler doesn't handle zero offsets optimally. This + * however would mean a very large amount of extra TOKENS and SETS for + * a very small profit in code bytes, so we won't do that. + * + * To prevent the TOKENS list from getting too unreadable, #ifdefs are + * used to form three parts: + * (i) the common part; + * (ii) the m68k4 part; + * (iii) the m68020 part; + */ + + /* Part (i) */ +const = {INT num;} 4 cost(4,4) "#" num . +indirect4 = {A_REG reg;} 4 cost(0,4) "(" reg ")" . +post_inc4 = {A_REG reg;} 4 cost(0,4) "(" reg ")+" . +pre_dec4 = {A_REG reg;} 4 cost(0,5) "-(" reg ")" . +indirect2 = {A_REG reg;} 4 cost(0,4) "(" reg ")" . +post_inc2 = {A_REG reg;} 4 cost(0,4) "(" reg ")+" . +pre_dec2 = {A_REG reg;} 4 cost(0,5) "-(" reg ")" . +indirect1 = {A_REG reg;} 4 cost(0,4) "(" reg ")" . +post_inc1 = {A_REG reg;} 4 cost(0,4) "(" reg ")+" . +pre_dec1 = {A_REG reg;} 4 cost(0,5) "-(" reg ")" . + +ext_addr = {ADDR bd;} 4 cost(4,5) "#" bd . +llabel = {ADDR bd;} 4 cost(2,0) bd . +slabel = {ADDR bd;} 4 cost(0,0) bd . +shconst = {INT num;} 4 cost(0,0) "#" num . + +#ifndef m68020 + /* Part (ii) */ +absolute4 = {ADDR bd;} 4 cost(4,8) bd . +offsetted4 = {A_REG reg; INT bd;} 4 cost(2,6) bd "(" reg ")" . +index_off4 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,7) + bd "(" reg "," xreg ".l)" . +absolute2 = {ADDR bd;} 4 cost(4,6) bd . +offsetted2 = {A_REG reg; INT bd;} 4 cost(2,4) bd "(" reg ")" . +index_off2 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,5) + bd "(" reg "," xreg ".l)" . +absolute1 = {ADDR bd;} 4 cost(4,6) bd . +offsetted1 = {A_REG reg; INT bd;} 4 cost(2,4) bd "(" reg ")" . +index_off1 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,5) + bd "(" reg "," xreg ".l)" . + +LOCAL = {INT bd;} 4 cost(2,6) bd "(a6)" . + +local_addr = {INT bd;} 4 cost(2,6) bd "(a6)" . +regAcon = {A_REG reg; INT bd;} 4 cost(2,6) bd "(" reg ")" . +regAregXcon = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,8) + bd "(" reg "," xreg ".l)" . + /* note: in the m68k4 version %sc always equals 1 */ + +t_regAregXcon = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,8) . +t_regAcon = {A_REG reg; INT bd;} 4 cost(2,6) . + +#else m68020 + /* Part (iii) */ +absolute4 = {ADDR bd;} 4 cost(4,7) "(" bd ")" . +offsetted4 = {A_REG reg; INT bd;} 4 cost(2,6) "(" bd "," reg ")" . +index_off4 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(4,9) + "(" bd "," reg "," xreg ".l*" sc ")" . +abs_index4 = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,9) + "(" bd "," xreg ".l*" sc ")" . +OFF_off4 = {A_REG reg; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," od ")" . +OFF_indoff4 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +INDOFF_off4 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +ABS_off4 = {ADDR bd; ADDR od;} 4 cost(8,22) "([" bd "]," od ")" . +ABS_indoff4 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "]," xreg ".l*" sc "," od ")" . +ABSIND_off4 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "," xreg ".l*" sc "]," od ")" . + +absolute2 = {ADDR bd;} 4 cost(4,7) "(" bd ")" . +offsetted2 = {A_REG reg; INT bd;} 4 cost(2,6) "(" bd "," reg ")" . +index_off2 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(4,9) + "(" bd "," reg "," xreg ".l*" sc ")" . +abs_index2 = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,9) + "(" bd "," xreg ".l*" sc ")" . +OFF_off2 = {A_REG reg; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," od ")" . +OFF_indoff2 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +INDOFF_off2 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +ABS_off2 = {ADDR bd; ADDR od;} 4 cost(8,22) "([" bd "]," od ")" . +ABS_indoff2 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "]," xreg ".l*" sc "," od ")" . +ABSIND_off2 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "," xreg ".l*" sc "]," od ")" . + +absolute1 = {ADDR bd;} 4 cost(4,7) "(" bd ")" . +offsetted1 = {A_REG reg; INT bd;} 4 cost(2,6) "(" bd "," reg ")" . +index_off1 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(4,9) + "(" bd "," reg "," xreg ".l*" sc ")" . +abs_index1 = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,9) + "(" bd "," xreg ".l*" sc ")" . +OFF_off1 = {A_REG reg; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," od ")" . +OFF_indoff1 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +INDOFF_off1 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +ABS_off1 = {ADDR bd; ADDR od;} 4 cost(8,22) "([" bd "]," od ")" . +ABS_indoff1 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "]," xreg ".l*" sc "," od ")" . +ABSIND_off1 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "," xreg ".l*" sc "]," od ")" . + +LOCAL = {INT bd;} 4 cost(2,6) "(" bd ",a6)" . +ILOCAL = {INT bd;} 4 cost(4,16) "([" bd ",a6])" . + +local_addr = {INT bd;} 4 cost(2,3) "(" bd ",a6)" . +regAcon = {A_REG reg; INT bd;} 4 cost(2,3) "(" bd "," reg ")" . +regAregXcon = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,7) + "(" bd "," reg "," xreg ".l*" sc ")" . +off_con = {A_REG reg; INT bd; ADDR od;} 4 cost(6,18) + "([" bd "," reg "]," od ")". +off_regXcon = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,18) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +indoff_con = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,18) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +abs_con = {ADDR bd; ADDR od;} 4 cost(8,21) "([" bd "]," od ")" . +abs_regXcon = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,21) + "([" bd "]," xreg ".l*" sc "," od ")" . +absind_con = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,21) + "([" bd "," xreg ".l*" sc "]," od ")" . +ext_regX = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,15) + "(" bd "," xreg ".l*" sc ")" . + +regX = {INT sc; D_REG xreg;} 4 cost(2,7) "(" xreg ".l*" sc ")" . +DREG_pair = {D_REG reg1; D_REG reg2;} 8 cost(2,0) reg1 ":" reg2 . + +#define t_regAregXcon regAregXcon +#define t_regAcon regAcon + +#endif m68020 + +SETS + + /* The SETS list cannot be kept as 'readable' as the TOKENS list + * because cgg is one pass. + */ + +#ifndef m68020 + /* A m68k4 part */ +data4 = D_REG + LOCAL + const + post_inc4 + pre_dec4 + + indirect4 + offsetted4 + index_off4 + absolute4 + + ext_addr . +memory4 = data4 - D_REG . +control4 = indirect4 + offsetted4 + index_off4 + absolute4 + + LOCAL . +alterable4 = data4 + A_REG - const - ext_addr . +any4 = data4 + A_REG . /* all four above together */ + +data2 = D_REG + post_inc2 + pre_dec2 + indirect2 + + offsetted2 + index_off2 + absolute2 + const . +memory2 = data2 - D_REG . +control2 = indirect2 + offsetted2 + index_off2 + absolute2 . +alterable2 = data2 + A_REG - const . +any2 = data2 + A_REG . + +data1 = D_REG + post_inc1 + pre_dec1 + indirect1 + + offsetted1 + index_off1 + absolute1 + const . +memory1 = data1 - D_REG . +control1 = indirect1 + offsetted1 + index_off1 + absolute1 . +alterable1 = data1 - const . +any1 = data1 . + +#else m68020 + +data4 = D_REG + indirect4 + post_inc4 + pre_dec4 + index_off4 + + offsetted4 + OFF_off4 + OFF_indoff4 + + INDOFF_off4 + + ABS_off4 + ABS_indoff4 + ABSIND_off4 + + absolute4 + abs_index4 + const + ext_addr + + LOCAL + ILOCAL . +memory4 = data4 - D_REG . +control4 = memory4 - (post_inc4 + pre_dec4 + const + ext_addr) . +alterable4 = data4 + A_REG - const - ext_addr . +any4 = data4 + A_REG . /* all four above together */ + +data2 = D_REG + indirect2 + post_inc2 + pre_dec2 + index_off2 + + offsetted2 + OFF_off2 + OFF_indoff2 + + INDOFF_off2 + + ABS_off2 + ABS_indoff2 + ABSIND_off2 + + absolute2 + abs_index2 + const . +memory2 = data2 - D_REG . +control2 = memory2 - (post_inc2 + pre_dec2 + const) . +alterable2 = data2 + A_REG - const . +any2 = data2 + A_REG . /* all four above together */ + +data1 = D_REG + indirect1 + post_inc1 + pre_dec1 + index_off1 + + offsetted1 + OFF_off1 + OFF_indoff1 + + INDOFF_off1 + + ABS_off1 + ABS_indoff1 + ABSIND_off1 + + absolute1 + abs_index1 + const . +memory1 = data1 - D_REG . +control1 = memory1 - (post_inc1 + pre_dec1 + const) . +alterable1 = data1 - const . +any1 = data1 . /* all four above together */ + +#endif m68020 + /* This is a common part */ +any = any4 + any2 + any1 . +absolute = absolute4 + absolute2 + absolute1 . +control = control4 + control2 + control1 . +indirect = indirect4 + indirect2 + indirect1 . +pre_post = pre_dec4 + pre_dec2 + pre_dec1 + + post_inc4 + post_inc2 + post_inc1 . +offsetted = offsetted4 + offsetted2 + offsetted1 . +index_off = index_off4 + index_off2 + index_off1 . + +#ifndef m68020 + /* A m68k4 part */ +regind_addr = regAcon + regAregXcon + t_regAcon + t_regAregXcon . +address = ext_addr + local_addr + regAcon + regAregXcon . +all_regind = indirect + offsetted + pre_post + index_off + + regind_addr . +all_indir = all_regind . +allexceptcon = ALL - ( D_REG + A_REG + const + + local_addr + ext_addr + regAcon + regAregXcon + + t_regAcon + t_regAregXcon ) . +use_index = index_off4 + index_off2 + index_off1 . + +#else m68020 + +reg_memind4 = OFF_off4 + OFF_indoff4 + INDOFF_off4 . +memind4 = reg_memind4 + + ABS_off4 + ABS_indoff4 . +reg_memind2 = OFF_off2 + OFF_indoff2 + INDOFF_off2 . +memind2 = reg_memind2 + + ABS_off2 + ABS_indoff2 . +reg_memind1 = OFF_off1 + OFF_indoff1 + INDOFF_off1 . +memind1 = reg_memind1 + + ABS_off1 + ABS_indoff1 . +reg_memind = reg_memind4 + reg_memind2 + reg_memind1 . +memind = memind4 + memind2 + memind1 . +regind_addr = regAcon + regAregXcon + + off_con + off_regXcon + + indoff_con . +address = regind_addr + + ext_addr + local_addr + + abs_con + abs_regXcon + + absind_con + + ext_regX . +all_regind = indirect + offsetted + index_off + pre_post + + reg_memind + regind_addr . +all_indir = all_regind + memind + ILOCAL . +allexceptcon = ALL - ( D_REG + A_REG + const + + local_addr + ext_addr + regAcon + regAregXcon + ext_regX ) . +use_index4 = index_off4 + abs_index4 + + OFF_indoff4 + INDOFF_off4 + + ABS_indoff4 + ABSIND_off4 . +use_index2 = index_off2 + abs_index2 + + OFF_indoff2 + INDOFF_off2 + + ABS_indoff2 + ABSIND_off2 . +use_index1 = index_off1 + abs_index1 + + OFF_indoff1 + INDOFF_off1 + + ABS_indoff1 + ABSIND_off1 . +use_indaddr = regAregXcon + + off_regXcon + indoff_con + + abs_regXcon + absind_con + + ext_regX . + +use_index = use_index4 + use_index2 + use_index1 + use_indaddr + regX . + +#endif m68020 + /* A common part */ +posextern = absolute + all_indir . + +genreg = D_REG + A_REG. +label = llabel + slabel . +immediate4 = const + ext_addr . +conreg4 = D_REG + immediate4 . +conreg2 = D_REG + const . +conreg1 = D_REG + const . +shconreg = D_REG + shconst . +datalt4 = data4 * alterable4 . +datalt2 = data2 * alterable2 . +datalt1 = data1 * alterable1 . +datalt = datalt4 + datalt2 + datalt1 . +memalt4 = memory4 * alterable4 . +memalt2 = memory2 * alterable2 . +memalt1 = memory1 * alterable1 . + +#ifndef m68020 + /* A m68k4 part */ +imm_cmp4 = alterable4 . +imm_cmp2 = alterable2 . +imm_cmp1 = datalt1 . + +test_set4 = datalt4 . +test_set2 = datalt2 . +test_set1 = datalt1 . + +#else m68020 + +imm_cmp4 = any4 - immediate4 . +imm_cmp2 = any2 - const . +imm_cmp1 = data1 - const . + +test_set4 = data4 - immediate4 . +test_set2 = data2 - const . +test_set1 = data1 - const . + +#endif m68020 + +test_set = test_set4 + test_set2 + test_set1 . + +#ifndef m68020 +t_address = address + t_regAregXcon + t_regAcon . +#else m68020 +#define t_address address +#endif m68020 + + +INSTRUCTIONS + + /* Since the 68000 , the 68010 and the 68020 instruction sets are rather + * extensive, especially because e.g. 'add.l' and 'add.w' are + * considered different instructions, only those instructions are + * listed here that are used in the rest of this table. + * + * Instruction timing cost cannot be accurately given, nor the timing + * cost for getting operands. Detailed information about this can be + * found in the "MC68020 User's Manual", section 9, about instruction + * timing. The cost used in this table are 'worst case' cost, as + * mentioned in section 9 of the user's manual. + * + * The first few instructions had to be added because register + * variables are used. The LOCALs below are register variables. + * One may not conclude that these operations are also allowed + * on LOCALs that are not register variables. + * The cost have been adapted, but are not accurate; when 'real' + * LOCALs are used the cost are very inaccurate. + */ + +add_l "add.l" any4:ro, LOCAL:rw:cc cost(0,0). +lea address:ro, LOCAL:wo cost(0,0). +sub_l "sub.l" any4:ro, LOCAL:rw:cc cost(0,0). +sh "illegal" shconreg:ro, LOCAL:rw:cc cost(0,0). +sh "illegal" LOCAL:ro, LOCAL:rw:cc cost(0,0). +xxx "illegal" data4:ro, LOCAL:rw:cc cost(0,0). +xxx "illegal" LOCAL:ro, alterable4:rw:cc cost(0,0). +#ifdef m68020 +divs_l "divs.l" data4:ro, LOCAL:rw:cc cost(0,90). +divu_l "divu.l" data4:ro, LOCAL:rw:cc cost(0,78). +muls_l "muls.l" data4:ro, LOCAL:rw:cc cost(0,44). +mulu_l "mulu.l" data4:ro, LOCAL:rw:cc cost(0,44). +#endif m68020 + +add_l "add.l" any4:ro, D_REG:rw:cc cost(2,3). +add_l "add.l" any4:ro, A_REG:rw cost(2,3). +add_l "add.l" conreg4:ro, alterable4:rw:cc cost(2,6). +and_l "and.l" data4:ro, D_REG:rw:cc cost(2,3). +and_l "and.l" D_REG:ro, memalt4:rw:cc cost(2,6). +and_l "and.l" const:ro, datalt4:rw:cc cost(2,6). +asl_l "asl.l" shconreg:ro, D_REG:rw:cc cost(2,5). +asl "asl #1," memalt2:rw:cc cost(2,4). +asr_l "asr.l" shconreg:ro, D_REG:rw:cc cost(2,4). +asr "asr #1," memalt2:rw:cc cost(2,4). +bra label cost(2,5). +bcc label cost(2,5). +bcs label cost(2,5). +beq label cost(2,5). +bge label cost(2,5). +bgt label cost(2,5). +bhi label cost(2,5). +ble label cost(2,5). +bls label cost(2,5). +blt label cost(2,5). +bmi label cost(2,5). +bne label cost(2,5). +bpl label cost(2,5). +bvc label cost(2,5). +bvs label cost(2,5). +bset conreg2:ro, D_REG:rw kills :cc cost(2,4). +btst conreg2:ro, data1:rw kills :cc cost(2,3). +clr_l "clr.l" D_REG:wo:cc cost(2,3). +clr_l "clr.l" memalt4:wo:cc cost(2,6). +clr_w "clr.w" D_REG:wo:cc cost(2,2). +clr_w "clr.w" memalt2:wo:cc cost(2,4). +clr_b "clr.b" D_REG:wo:cc cost(2,2). +clr_b "clr.b" memalt1:wo:cc cost(2,4). +cmp_l "cmp.l" any4:ro, genreg:ro kills :cc cost(2,3). +cmp_l "cmp.l" post_inc4:ro, post_inc4:ro kills :cc cost(2,2). +cmp_l "cmp.l" immediate4:ro, imm_cmp4:ro kills :cc cost(2,2). +cmp_w "cmp.w" any2:ro, genreg:ro kills :cc cost(2,3). +cmp_w "cmp.w" post_inc2:ro, post_inc2:ro kills :cc cost(2,2). +cmp_w "cmp.w" const:ro, imm_cmp2:ro kills :cc cost(2,2). +cmp_b "cmp.b" data1:ro, D_REG:ro kills :cc cost(2,3). +cmp_b "cmp.b" post_inc1:ro, post_inc1:ro kills :cc cost(2,2). +cmp_b "cmp.b" const:ro, imm_cmp1:ro kills :cc cost(2,2). +dbf D_REG:rw, label cost(2,5). +eor_l "eor.l" conreg4:ro, datalt4:rw:cc cost(2,6). +ext_l "ext.l" D_REG:rw:cc cost(2,2). +ext_w "ext.w" D_REG:rw:cc cost(2,2). +jmp address+control4 cost(2,0). +jsr address+control4 kills :cc cost(2,3). +lea address+control4:ro, A_REG:wo cost(2,0). +lsl_l "lsl.l" shconreg:ro, D_REG:rw:cc cost(2,4). +lsl "lsl #1," memalt2:rw:cc cost(2,4). +lsr_l "lsr.l" shconreg:ro, D_REG:rw:cc cost(2,4). +lsr "lsr #1," memalt2:rw:cc cost(2,4). +move_l "move.l" any4:ro, alterable4:wo:cc cost(2,2). +move_w "move.w" any2:ro, alterable2:wo:cc cost(2,2). +move_b "move.b" data1:ro, alterable1:wo:cc cost(2,2). +neg_l "neg.l" D_REG:rw:cc cost(2,3). +neg_l "neg.l" memory4:rw:cc cost(2,6). +not_l "not.l" D_REG:rw:cc cost(2,3). +not_l "not.l" memory4:rw:cc cost(2,6). +or_l "or.l" data4:ro, D_REG:rw:cc cost(2,3). +or_l "or.l" D_REG:ro, memalt4:rw:cc cost(2,6). +or_l "or.l" const:ro, datalt4:rw:cc cost(2,6). +rol_l "rol.l" shconreg:ro, D_REG:rw:cc cost(2,4). +rol "rol #1," memalt2:rw:cc cost(2,4). +ror_l "ror.l" shconreg:ro, D_REG:rw:cc cost(2,4). +ror "ror #1," memalt2:rw:cc cost(2,4). +roxl "roxl #1," memalt2:rw:cc cost(2,4). +roxr "roxr #1," memalt2:rw:cc cost(2,4). +sne datalt1:rw cost(2,3). +sub_l "sub.l" any4:ro, D_REG:rw:cc cost(2,3). +sub_l "sub.l" any4:ro, A_REG:rw cost(2,3). +sub_l "sub.l" conreg4:ro, alterable4:rw:cc cost(2,6). +tst_l "tst.l" test_set4:ro:cc cost(2,3). +tst_w "tst.w" test_set2:ro:cc cost(2,3). +tst_b "tst.b" test_set1:ro:cc cost(2,3). +unlk A_REG cost(2,6). + +bxx "illegal" label cost(2,5). +xxx "illegal" data4:ro, D_REG:rw:cc cost(2,3). +xxx "illegal" conreg4:ro, memalt4:rw:cc cost(2,6). +bit "illegal" control4:rw:cc cost(2,6). +sh "illegal" shconreg:ro, D_REG:rw:cc cost(2,4). +shw "illegal" control2:rw:cc cost(2,4). + +#ifdef m68020 +cmp2_l "cmp2.l" address+control4:ro, genreg:ro kills :cc cost(2,18). +divs_l "divs.l" data4:ro, D_REG:rw:cc cost(2,90). +divsl_l "divsl.l" data4:ro, DREG_pair:rw kills :cc cost(2,90). +divu_l "divu.l" data4:ro, D_REG:rw:cc cost(2,78). +divul_l "divul.l" data4:ro, DREG_pair:rw kills :cc cost(2,78). +extb_l "extb.l" D_REG:rw:cc cost(2,4). +muls_l "muls.l" data4:ro, D_REG:rw:cc cost(2,44). +mulu_l "mulu.l" data4:ro, D_REG:rw:cc cost(2,44). +pea address+control4+regX cost(2,4). +#else m68020 +pea address+control4 cost(2,4). +#endif m68020 + + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * Extra pseudo instruction; it just kills a D_REG; + * it is necessary with long divides where remainders are important; + * see also: 'pat rmi' and 'pat rmu' + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ +killreg "! kill" D_REG:wo cost(0,0). + + +MOVES + +from const %num==0 to D_REG + gen clr_l %2 + +from const %num==0 to memalt4 + gen clr_l %2 + +from const %num==0 to memalt2 + gen clr_w %2 + +from const %num==0 to memalt1 + gen clr_b %2 + +from const to memalt1 + gen move_b {const, lowb(%1.num)}, %2 + +from const to memalt2 + gen move_w {const, loww(%1.num)}, %2 + +from regAcon %bd==0 to A_REG + gen move_l %1.reg, %2 + +#ifndef m68020 +from t_regAregXcon sfit(%bd, 8) to A_REG + gen lea {regAregXcon, %1.reg, %1.xreg, 1, %1.bd}, %2 + +from t_regAregXcon to A_REG + gen lea {regAregXcon, %1.reg, %1.xreg, 1, 0}, %2 + add_l {const, %1.bd}, %2 + +from t_regAcon sfit(%bd, 16) to A_REG + gen lea {regAcon, %1.reg, %1.bd}, %2 + +from t_regAcon to A_REG + gen move_l %1.reg, %2 + add_l {const, %1.bd}, %2 +#endif m68020 + +from address - ext_addr to A_REG + gen lea %1, %2 + +from any4 to alterable4 + gen move_l %1, %2 + +from any2 to datalt2 + gen move_w %1, %2 + +from data1 to datalt1 + gen move_b %1, %2 + + + + +TESTS + + +to test test_set4 + gen tst_l %1 + +to test test_set2 + gen tst_w %1 + +to test test_set1 + gen tst_b %1 + + +STACKINGRULES + + +from const %num==0 to STACK + gen clr_l {pre_dec4, sp} + +#ifndef m68020 +from t_regAregXcon sfit(%bd, 8) to STACK + gen pea {regAregXcon, %1.reg, %1.xreg, 1, %1.bd} + +from t_regAregXcon to STACK + gen pea {regAregXcon, %1.reg, %1.xreg, 1, 0} + add_l {const, %1.bd}, {indirect4, sp} + +from t_regAcon sfit(%bd, 16) to STACK + gen pea {regAcon, %1.reg, %1.bd} + +from t_regAcon to STACK + gen move_l %1.reg, {pre_dec4, sp} + add_l {const, %1.bd}, {indirect4, sp} +#endif m68020 + +from address - ext_addr to STACK + gen pea %1 + +from ext_addr to STACK + gen pea {absolute4, %1.bd} + +from const to STACK + gen pea {absolute4, %1.num} + +from any4 to STACK + gen move_l %1, {pre_dec4, sp} + +from any2 to STACK + gen clr_l {pre_dec4, sp} + move_w %1, {offsetted2, sp, 2} + +from data1 to STACK + gen clr_l {pre_dec4, sp} + move_b %1, {offsetted1, sp, 3} + +#ifdef m68020 +from regX to STACK + gen pea %1 +#endif m68020 + /* This last stackingrule is never used: whenever regX is put on + * the fakestack, some em-instuctions are left that remove it + * immediately. However cgg complained about not having a + * stackingrule for regX, so here it is + */ + + +COERCIONS + + +from STACK + uses DD_REG + gen move_l {post_inc4, sp}, %a + yields %a + +from STACK + uses AA_REG + gen move_l {post_inc4, sp}, %a + yields %a + +#ifndef m68020 +from t_regAregXcon sfit(%bd, 8) + yields {regAregXcon, %1.reg, %1.xreg, 1, %1.bd} + +from t_regAregXcon + uses AA_REG=%1.reg + gen add_l {const, %1.bd}, %a + yields {regAregXcon, %a, %1.xreg, 1, 0} + +from t_regAcon sfit(%bd, 16) + yields {regAcon, %1.reg, %1.bd} + +from t_regAcon + uses reusing %1, AA_REG=%1.reg + gen add_l {const, %1.bd}, %a + yields %a +#endif m68020 + +from t_address + uses reusing %1, AA_REG = %1 + yields %a + +from any4 + uses reusing %1, DD_REG = %1 + yields %a + +from any4 + uses reusing %1, AA_REG = %1 + yields %a + +from memory2 + uses DD_REG = {const, 0} + gen move_w %1, %a yields %a + +from memory1 + uses DD_REG = {const, 0} + gen move_b %1, %a yields %a + + + + +PATTERNS + +/************************************************ + * Group 0: rules for register variables * + * LOCALs mentioned here refer to registers * + ************************************************/ + +pat lol inreg($1)==reg_pointer + kills pre_post %reg==regvar($1, reg_pointer) + yields {LOCAL, $1} + +pat lil inreg($1)==reg_pointer + kills pre_post %reg==regvar($1, reg_pointer) + yields {indirect4, regvar($1, reg_pointer)} + +pat stl inreg($1)==reg_any +with any4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen move %1, {LOCAL, $1} + +pat stl inreg($1)==reg_pointer +with any4 + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen move %1, {LOCAL, $1} +with exact ext_addr + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen move %1, {LOCAL, $1} +with exact address-ext_addr + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen lea %1, {LOCAL, $1} + +pat sil inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move %1, {indirect4, regvar($1, reg_pointer)} + + +pat lol sbi stl $1==$3 && $2==4 && inreg($1)==reg_any +with any4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sub_l %1, {LOCAL, $1} + neg_l {LOCAL, $1} + +pat lol sbu stl $1==$3 && $2==4 && inreg($1)==reg_any +with any4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sub_l %1, {LOCAL, $1} + neg_l {LOCAL, $1} + +pat lil sbi sil $1==$3 && $2==4 && inreg($1)==reg_pointer +with conreg4 + kills allexceptcon + gen sub_l %1, {indirect4, regvar($1, reg_pointer)} + neg_l {indirect4, regvar($1, reg_pointer)} + +pat lil sbu sil $1==$3 && $2==4 && inreg($1)==reg_pointer +with conreg4 + kills allexceptcon + gen sub_l %1, {indirect4, regvar($1, reg_pointer)} + neg_l {indirect4, regvar($1, reg_pointer)} + + +pat lil ngi sil $1==$3 && $2==4 && inreg($1)==reg_pointer + kills allexceptcon + gen neg_l {indirect4, regvar($1, reg_pointer)} + +pat lil com sil $1==$3 && $2==4 && inreg($1)==reg_pointer + kills allexceptcon + gen not_l {indirect4, regvar($1, reg_pointer)} + + +proc lolcshstl example lol loc sli stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sh* {shconst, $2}, {LOCAL, $1} + +proc lolrshstl example lol lol sli stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sh* {LOCAL, $2}, {LOCAL, $1} + +proc lil1shlsil example lil loc sli sil /* only left */ + kills allexceptcon + gen shw* {offsetted2, regvar($1, reg_pointer), 2} + roxl {indirect2, regvar($1, reg_pointer)} + +proc lil1shrsil example lil loc sli sil /* only right */ + kills allexceptcon + gen shw* {indirect2, regvar($1, reg_pointer)} + roxr {offsetted2, regvar($1, reg_pointer), 2} + +pat lol loc sli stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("asl.l") +pat lol loc slu stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("asl.l") +pat lol lol sli stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("asl.l") +pat lol lol slu stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("asl.l") +pat lil loc sli sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shlsil("asl #1,") +pat lil loc slu sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shlsil("asl #1,") +pat lol loc sri stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("asr.l") +pat lol loc sru stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("lsr.l") +pat lol lol sri stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("asr.l") +pat lol lol sru stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("lsr.l") +pat lil loc sri sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shrsil("asr #1,") +pat lil loc sru sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shrsil("lsr #1,") +pat lol loc rol stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("rol.l") +pat lol lol rol stl $1==$4 && inreg($2)==reg_any && $3==4 && inreg($1)==reg_any + call lolrshstl("rol.l") +pat lol loc ror stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("ror.l") +pat lol lol ror stl $1==$4 && inreg($2)==reg_any && $3==4 && inreg($1)==reg_any + call lolrshstl("ror.l") + +#ifdef m68020 +pat lol loc dvi stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen divs_l {const, $2}, {LOCAL, $1} + +pat lol loc dvu stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen divu_l {const, $2}, {LOCAL, $1} + +pat lol loc mli stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen muls_l {const, $2}, {LOCAL, $1} + +pat lol loc mlu stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen mulu_l {const, $2}, {LOCAL, $1} + +pat lol mli stl $1==$3 && $2==4 && inreg($1)==reg_any + with data4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen muls_l %1, {LOCAL, $1} + +pat lol mlu stl $1==$3 && $2==4 && inreg($1)==reg_any + with data4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen mulu_l %1, {LOCAL, $1} +#endif m68020 + + +pat lil inc sil $1==$3 && inreg($1)==reg_pointer + kills allexceptcon + gen add_l {const, 1}, {indirect4, regvar($1, reg_pointer)} + +pat lil dec sil $1==$3 && inreg($1)==reg_pointer + kills allexceptcon + gen sub_l {const, 1}, {indirect4, regvar($1, reg_pointer)} + +pat inl inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen add_l {const, 1}, {LOCAL, $1} + +pat del inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sub_l {const, 1}, {LOCAL, $1} + +pat zrl inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen clr_l {LOCAL, $1} + +pat zrl inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen move_l {const, 0}, {LOCAL, $1} + + +proc lolxxstl example lol and stl +with data4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen xxx* %1, {LOCAL, $1} + +proc lilxxsil example lil and sil +with conreg4 + kills allexceptcon + gen xxx* %1, {indirect4, regvar($1, reg_pointer)} + +proc lolcxxstl example lol loc and stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen xxx* {const, $2}, {LOCAL, $1} + +proc lilcxxsil example lil loc and sil + kills allexceptcon + gen xxx* {const, $2}, {indirect4, regvar($1, reg_pointer)} + +proc lolrxxstl example lol lol and stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen xxx* {LOCAL, $2}, {LOCAL, $1} + +proc lilrxxsil example lil lol and sil + kills allexceptcon + gen xxx* {LOCAL, $2}, {indirect4, regvar($1, reg_pointer)} + +pat lol adi stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("add.l") +pat lol loc adi stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("add.l") +pat lil adi sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("add.l") +pat lil loc adi sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("add.l") +pat lol lol adi stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("add.l") +pat lil lol adi sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("add.l") +pat lol adu stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("add.l") +pat lol loc adu stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("add.l") +pat lil adu sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("add.l") +pat lil loc adu sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("add.l") +pat lol lol adu stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("add.l") +pat lil lol adu sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("add.l") +pat lol loc sbi stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("sub.l") +pat lil loc sbi sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("sub.l") +pat lol lol sbi stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("sub.l") +pat lil lol sbi sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("sub.l") +pat lol loc sbu stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("sub.l") +pat lil loc sbu sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("sub.l") +pat lol lol sbu stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("sub.l") +pat lil lol sbu sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("sub.l") +pat lol and stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("and.l") +pat lol loc and stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("and.l") +pat lil and sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("and.l") +pat lil loc and sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("and.l") +pat lol lol and stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("and.l") +pat lil lol and sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("and.l") +pat lol ior stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("or.l") +pat lol loc ior stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("or.l") +pat lil ior sil $1==$3 && $2==4 && inreg($1)==reg_pointer + call lilxxsil("or.l") +pat lil loc ior sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("or.l") +pat lol lol ior stl $1==$4 && $3==4 && inreg($1)==reg_any && + inreg($2)==reg_any + call lolrxxstl("or.l") +pat lil lol ior sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("or.l") +pat lol xor stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("eor.l") +pat lol loc xor stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("eor.l") +pat lil xor sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("eor.l") +pat lil loc xor sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("eor.l") +pat lol lol xor stl $1==$4 && $3==4 && inreg($1)==reg_any && + inreg($2)==reg_any + call lolrxxstl("eor.l") +pat lil lol xor sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("eor.l") + +pat lil adp sil $1==$3 && inreg($1)==reg_pointer + kills allexceptcon + gen add_l {const, $2}, {indirect4, regvar($1, reg_pointer)} + +pat lil lil adp sil $1==$2 && $1==$4 && inreg($1)==reg_pointer + kills allexceptcon + uses AA_REG = {indirect4, regvar($1, reg_pointer)} + gen add_l {const, $3}, {indirect4, regvar($1, reg_pointer)} + yields %a + +pat lol lol adp stl loi $1==$2 && $1==$4 && $3==1 && $5==1 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc1, regvar($1, reg_pointer)} + +pat lol loi lol adp stl $1==$3 && $1==$5 && $2==1 && $4==1 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc1, regvar($1, reg_pointer)} + +pat lol lol adp stl loi $1==$2 && $1==$4 && $3==2 && $5==2 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc2, regvar($1, reg_pointer)} + +pat lol loi lol adp stl $1==$3 && $1==$5 && $2==2 && $4==2 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc2, regvar($1, reg_pointer)} + +pat lol lol adp stl loi $1==$2 && $1==$4 && $3==4 && $5==4 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc4, regvar($1, reg_pointer)} + +pat lil lol adp stl $1==$2 && $1==$4 && $3==4 && inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc4, regvar($1, reg_pointer)} + +pat lol lol adp stl sti $1==$2 && $1==$4 && $3==1 && $5==1 && + inreg($1)==reg_pointer +with data1 + kills allexceptcon + gen move %1, {post_inc1, regvar($1, reg_pointer)} + +pat lol sti lol adp stl $1==$3 && $1==$5 && $2==1 && $4==1 && + inreg($1)==reg_pointer +with data1 + kills allexceptcon + gen move %1, {post_inc1, regvar($1, reg_pointer)} + +pat lol lol adp stl sti $1==$2 && $1==$4 && $3==2 && $5==2 && + inreg($1)==reg_pointer +with any2 + kills allexceptcon + gen move %1, {post_inc2, regvar($1, reg_pointer)} + +pat lol sti lol adp stl $1==$3 && $1==$5 && $2==2 && $4==2 && + inreg($1)==reg_pointer +with any2 + kills allexceptcon + gen move %1, {post_inc2, regvar($1, reg_pointer)} + +pat lol lol adp stl sti $1==$2 && $1==$4 && $3==4 && $5==4 && + inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move_l %1, {post_inc4, regvar($1, reg_pointer)} + +pat sil lol adp stl $1==$2 && $1==$4 && $3==4 && inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move_l %1, {post_inc4, regvar($1, reg_pointer)} + +pat lol adp stl lol loi $1==$3 && $1==$4 && $2==0-1 && $5==1 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {pre_dec1, regvar($1, reg_pointer)} + +pat lol adp stl lol loi $1==$3 && $1==$4 && $2==0-2 && $5==2 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {pre_dec2, regvar($1, reg_pointer)} + +pat lol adp stl lil $1==$3 && $1==$4 && $2==0-4 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {pre_dec4, regvar($1, reg_pointer)} + +pat lol adp stl lol sti $1==$3 && $1==$4 && $2==0-1 && $5==1 && + inreg($1)==reg_pointer +with data1 + kills allexceptcon + gen move %1, {pre_dec1, regvar($1, reg_pointer)} + +pat lol adp stl lol sti $1==$3 && $1==$4 && $2==0-2 && $5==2 && + inreg($1)==reg_pointer +with any2 + kills allexceptcon + gen move %1, {pre_dec2, regvar($1, reg_pointer)} + +pat lol adp stl sil $1==$3 && $1==$4 && $2==0-4 && + inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move_l %1, {pre_dec4, regvar($1, reg_pointer)} + + + + +/************************************************ + * Group 1: load instructions * + ************************************************/ + +pat loc yields {const, $1} + +pat ldc leaving loc 18 trp + +pat lol yields {LOCAL, $1} + +pat ldl leaving lol $1+4 lol $1 + +pat loe yields {absolute4, $1} + +pat lil +#ifdef m68020 + yields {ILOCAL, $1} +#else m68020 + uses AA_REG = {LOCAL, $1} + yields {indirect4, %a} +#endif m68020 + + /* When using the 'offsetted' intructions regAregXcon cannot be used + * for the m68k4; there is no way of knowing about the size of + * %1.bd+$1, because expressions are not allowed in stack patterns, and + * this may lead to outputting too large displacements. With regAcon + * the chance that this will happen is very slim, because it can + * have displacements of 16 bits. Besides, leaving out regAcon here + * would make it very hard to handle this instruction efficiently. + */ +pat lof +with A_REG yields {offsetted4, %1, $1} +with exact local_addr yields {LOCAL, %1.bd+$1} +with exact ext_addr yields {absolute4, %1.bd+$1} +#ifndef m68020 +with regAcon yields {offsetted4, %1.reg, %1.bd+$1} +#else m68020 +with exact regAcon yields {offsetted4, %1.reg, %1.bd+$1} +with exact regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} +with exact offsetted4 yields {OFF_off4, %1.reg, %1.bd, $1} +with exact indirect yields {OFF_off4, %1.reg, 0, $1} +with exact LOCAL yields {OFF_off4, lb, %1.bd, $1} +with exact off_con yields {OFF_off4, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon yields {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 yields {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con yields {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 yields {ABS_off4, %1.bd, $1} +with exact abs_con yields {ABS_off4, %1.bd, %1.od+$1} +with exact abs_regXcon yields {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX yields {abs_index4, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat lal yields {local_addr, $1} + +pat lae yields {ext_addr, $1} + +pat lxl $1==0 yields lb + +pat lxl $1==1 yields {LOCAL, SL} + +pat lxl $1==2 +#ifdef m68020 + yields {OFF_off4, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + yields {offsetted4, %a, SL} +#endif m68020 + +pat lxl $1==3 +#ifdef m68020 + uses AA_REG = {OFF_off4, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + gen move {offsetted4, %a, SL}, %a +#endif m68020 + yields {offsetted4, %a, SL} + +pat lxl $1>3 + uses AA_REG = {LOCAL, SL}, + DD_REG = {const, $1-2} + gen 1: + move_l {offsetted4, %a, SL} ,%a + dbf %b, {slabel, 1b} + yields %a + +pat lxa $1==0 yields {local_addr, SL} + +pat lxa $1==1 +#ifdef m68020 + yields {off_con, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + yields {regAcon, %a, SL} +#endif m68020 + +pat lxa $1==2 +#ifdef m68020 + uses AA_REG = {OFF_off4, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + gen move {offsetted4, %a, SL}, %a +#endif m68020 + yields {regAcon, %a, SL} + +pat lxa $1>2 + uses AA_REG = {LOCAL, SL}, + DD_REG = {const, $1-1} + gen 1: + move_l {offsetted4, %a, SL} ,%a + dbf %b, {slabel, 1b} + yields {regAcon, %a, SL} + +pat loi $1==1 +with A_REG yields {indirect1, %1} +with exact local_addr yields {offsetted1, lb, %1.bd} +with exact ext_addr yields {absolute1, %1.bd} +#ifndef m68020 +with regAcon yields {offsetted1, %1.reg, %1.bd} +with regAregXcon yields {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon yields {offsetted1, %1.reg, %1.bd} +with exact regAregXcon yields {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 yields {OFF_off1, %1.reg, 0, 0} +with exact offsetted4 yields {OFF_off1, %1.reg, %1.bd, 0} +with exact LOCAL yields {OFF_off1, lb, %1.bd, 0} +with exact off_con yields {OFF_off1, %1.reg, %1.bd, %1.od} +with exact off_regXcon yields {OFF_indoff1, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 yields {INDOFF_off1, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con yields {INDOFF_off1, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 yields {ABS_off1, %1.bd, 0} +with exact abs_con yields {ABS_off1, %1.bd, %1.od} +with exact abs_regXcon yields {ABS_indoff1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 yields {ABSIND_off1, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con yields {ABSIND_off1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX yields {abs_index1, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat loi $1==2 +with A_REG yields {indirect2, %1} +with exact local_addr yields {offsetted2, lb, %1.bd} +with exact ext_addr yields {absolute2, %1.bd} +#ifndef m68020 +with regAcon yields {offsetted2, %1.reg, %1.bd} +with regAregXcon yields {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon yields {offsetted2, %1.reg, %1.bd} +with exact regAregXcon yields {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 yields {OFF_off2, %1.reg, 0, 0} +with exact offsetted4 yields {OFF_off2, %1.reg, %1.bd, 0} +with exact LOCAL yields {OFF_off2, lb, %1.bd, 0} +with exact off_con yields {OFF_off2, %1.reg, %1.bd, %1.od} +with exact off_regXcon yields {OFF_indoff2, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 yields {INDOFF_off2, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con yields {INDOFF_off2, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 yields {ABS_off2, %1.bd, 0} +with exact abs_con yields {ABS_off2, %1.bd, %1.od} +with exact abs_regXcon yields {ABS_indoff2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 yields {ABSIND_off2, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con yields {ABSIND_off2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX yields {abs_index2, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat loi $1==4 +with A_REG yields {indirect4, %1} +with exact local_addr yields {LOCAL, %1.bd} +with exact ext_addr yields {absolute4, %1.bd} +#ifndef m68020 +with regAcon yields {offsetted4, %1.reg, %1.bd} +with regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon yields {offsetted4, %1.reg, %1.bd} +with exact regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact LOCAL yields {ILOCAL, %1.bd} +with exact indirect4 yields {OFF_off4, %1.reg, 0, 0} +with exact offsetted4 yields {OFF_off4, %1.reg, %1.bd, 0} +with exact off_con yields {OFF_off4, %1.reg, %1.bd, %1.od} +with exact off_regXcon yields {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 yields {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con yields {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 yields {ABS_off4, %1.bd, 0} +with exact abs_con yields {ABS_off4, %1.bd, %1.od} +with exact abs_regXcon yields {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX yields {abs_index4, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat loi $1==8 +with A_REG yields {offsetted4, %1, 4} + {indirect4, %1} +pat loi $1>8 +with AA_REG STACK + uses DD_REG = {const, $1/4 -1} + gen add_l {const, $1}, %1 + 1: + move_l {pre_dec4, %1}, {pre_dec4, sp} + dbf %a, {slabel, 1b} + +pat los $1==4 +with STACK + gen jsr {absolute4, ".los"} + +pat lde yields {absolute4, $1+4} + {absolute4, $1} + +pat ldf +with A_REG yields {offsetted4, %1, $1+4} + {offsetted4, %1, $1} +with exact local_addr yields {LOCAL, %1.bd+$1+4} + {LOCAL, %1.bd+$1} +with exact ext_addr yields {absolute4, %1.bd+$1+4} + {absolute4, %1.bd+$1} +#ifndef m68020 +with regAcon yields {offsetted4, %1.reg, %1.bd+$1+4} + {offsetted4, %1.reg, %1.bd+$1} +#else m68020 +with exact regAcon yields {offsetted4, %1.reg, %1.bd+$1+4} + {offsetted4, %1.reg, %1.bd+$1} +with exact regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1+4} + {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} +with exact indirect4 yields {OFF_off4, %1.reg, 0, $1+4} + {OFF_off4, %1.reg, 0, $1} +with exact offsetted4 yields {OFF_off4, %1.reg, %1.bd, $1+4} + {OFF_off4, %1.reg, %1.bd, $1} +with exact LOCAL yields {OFF_off4, lb, %1.bd, $1+4} + {OFF_off4, lb, %1.bd, $1} +with exact off_con yields {OFF_off4, %1.reg, %1.bd, %1.od+$1+4} + {OFF_off4, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon yields {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} + {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 yields {INDOFF_off4, %1.reg, %1.xreg, %1.sc,%1.bd,$1+4} + {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con yields {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} + {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 yields {ABS_off4, %1.bd, $1+4} + {ABS_off4, %1.bd, $1} +with exact abs_con yields {ABS_off4, %1.bd, %1.od+$1+4} + {ABS_off4, %1.bd, %1.od+$1} +with exact abs_regXcon yields {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} + {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1+4} + {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} + {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX yields {abs_index4, %1.sc, %1.xreg, %1.bd+$1+4} + {abs_index4, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat lpi yields {ext_addr, $1} + + + +/************************************************ + * Group 2: store instructions * + ************************************************/ + +pat stl +with any4 + kills all_indir, LOCAL %bd==$1 + gen move %1, {LOCAL, $1} +with exact STACK + gen move {post_inc4,sp}, {LOCAL, $1} + +pat ste +with any4 + kills posextern + gen move %1, {absolute4, $1} +with exact STACK + gen move {post_inc4, sp}, {absolute4, $1} + +pat sil +#ifdef m68020 +with any4 + kills allexceptcon + gen move %1, {ILOCAL, $1} +with exact STACK + gen move {post_inc4, sp}, {ILOCAL, $1} +#else m68020 +with any4 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen move %1, {indirect4, %a} +with exact STACK + uses AA_REG = {LOCAL, $1} + gen move {post_inc4, sp}, {indirect4, %a} +#endif m68020 + +pat stf +with A_REG any4 + kills allexceptcon + gen move %2, {offsetted4, %1, $1} +with A_REG STACK + gen move {post_inc4, sp}, {offsetted4, %1, $1} +with exact local_addr any4 + kills allexceptcon + gen move %2, {LOCAL, %1.bd+$1} +with exact ext_addr any4 + kills allexceptcon + gen move %2, {absolute4, %1.bd+$1} +#ifndef m68020 +with regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} +#else m68020 +with exact regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} +with exact regAregXcon any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} +with exact indirect4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, 0, $1} +with exact offsetted4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, $1} +with exact LOCAL any4 + kills allexceptcon + gen move %2, {OFF_off4, lb, %1.bd, $1} +with exact off_con any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon any4 + kills allexceptcon + gen move %2, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, $1} +with exact abs_con any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, %1.od+$1} +with exact abs_regXcon any4 + kills allexceptcon + gen move %2, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX any4 + kills allexceptcon + gen move %2, {abs_index4, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat sti $1==1 +with A_REG data1 + kills allexceptcon + gen move %2, {indirect1, %1} +with exact local_addr data1 + kills allexceptcon + gen move %2, {offsetted1, lb, %1.bd} +with exact ext_addr data1 + kills allexceptcon + gen move %2, {absolute1, %1.bd} +#ifndef m68020 +with regAcon data1 + kills allexceptcon + gen move %2, {offsetted1, %1.reg, %1.bd} +with regAregXcon data1 + kills allexceptcon + gen move %2, {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon data1 + kills allexceptcon + gen move %2, {offsetted1, %1.reg, %1.bd} +with exact regAregXcon data1 + kills allexceptcon + gen move %2, {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 data1 + kills allexceptcon + gen move %2, {OFF_off1, %1.reg, 0, 0} +with exact offsetted4 data1 + kills allexceptcon + gen move %2, {OFF_off1, %1.reg, %1.bd, 0} +with exact LOCAL data1 + kills allexceptcon + gen move %2, {OFF_off1, lb, %1.bd, 0} +with exact off_con data1 + kills allexceptcon + gen move %2, {OFF_off1, %1.reg, %1.bd, %1.od} +with exact off_regXcon data1 + kills allexceptcon + gen move %2, {OFF_indoff1, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 data1 + kills allexceptcon + gen move %2, {INDOFF_off1, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con data1 + kills allexceptcon + gen move %2, {INDOFF_off1, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 data1 + kills allexceptcon + gen move %2, {ABS_off1, %1.bd, 0} +with exact abs_con data1 + kills allexceptcon + gen move %2, {ABS_off1, %1.bd, %1.od} +with exact abs_regXcon data1 + kills allexceptcon + gen move %2, {ABS_indoff1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 data1 + kills allexceptcon + gen move %2, {ABSIND_off1, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con data1 + kills allexceptcon + gen move %2, {ABSIND_off1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX data1 + kills allexceptcon + gen move %2, {abs_index1, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat sti $1==2 +with A_REG any2 + kills allexceptcon + gen move %2, {indirect2, %1} +with exact local_addr any2 + kills allexceptcon + gen move %2, {offsetted2, lb, %1.bd} +with exact ext_addr any2 + kills allexceptcon + gen move %2, {absolute2, %1.bd} +#ifndef m68020 +with regAcon any2 + kills allexceptcon + gen move %2, {offsetted2, %1.reg, %1.bd} +with regAregXcon any2 + kills allexceptcon + gen move %2, {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon any2 + kills allexceptcon + gen move %2, {offsetted2, %1.reg, %1.bd} +with exact regAregXcon any2 + kills allexceptcon + gen move %2, {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 any2 + kills allexceptcon + gen move %2, {OFF_off2, %1.reg, 0, 0} +with exact offsetted4 any2 + kills allexceptcon + gen move %2, {OFF_off2, %1.reg, %1.bd, 0} +with exact LOCAL any2 + kills allexceptcon + gen move %2, {OFF_off2, lb, %1.bd, 0} +with exact off_con any2 + kills allexceptcon + gen move %2, {OFF_off2, %1.reg, %1.bd, %1.od} +with exact index_off4 any2 + kills allexceptcon + gen move %2, {INDOFF_off2, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact off_regXcon any2 + kills allexceptcon + gen move %2, {OFF_indoff2, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact indoff_con any2 + kills allexceptcon + gen move %2, {INDOFF_off2, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 any2 + kills allexceptcon + gen move %2, {ABS_off2, %1.bd, 0} +with exact abs_con any2 + kills allexceptcon + gen move %2, {ABS_off2, %1.bd, %1.od} +with exact abs_regXcon any2 + kills allexceptcon + gen move %2, {ABS_indoff2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 any2 + kills allexceptcon + gen move %2, {ABSIND_off2, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con any2 + kills allexceptcon + gen move %2, {ABSIND_off2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX any2 + kills allexceptcon + gen move %2, {abs_index2, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat sti $1==4 +with A_REG any4 + kills allexceptcon + gen move %2, {indirect4, %1} +with A_REG STACK + gen move {post_inc4, sp}, {indirect4, %1} +with exact local_addr any4 + kills allexceptcon + gen move %2, {LOCAL, %1.bd} +with exact ext_addr any4 + kills allexceptcon + gen move %2, {absolute4, %1.bd} +#ifndef m68020 +with regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd} +with regAregXcon any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd} +with exact regAregXcon any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact LOCAL any4 + kills allexceptcon + gen move %2, {ILOCAL, %1.bd} +with exact indirect4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, 0, 0} +with exact offsetted4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, 0} +with exact off_con any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, %1.od} +with exact off_regXcon any4 + kills allexceptcon + gen move %2, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, 0} +with exact abs_con any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, %1.od} +with exact abs_regXcon any4 + kills allexceptcon + gen move %2, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX any4 + kills allexceptcon + gen move %2, {abs_index4, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat sti $1>4 +with AA_REG STACK + uses DD_REG = {const, $1/4 -1} + gen 1: + move_l {post_inc4, sp}, {post_inc4, %1} + dbf %a, {slabel, 1b} + +pat sts $1==4 +with STACK + gen jsr {absolute4, ".sts"} + +pat sdl +with any4 any4 + kills all_indir, LOCAL %bd==$1 + gen move %1, {LOCAL, $1} + move %2, {LOCAL, $1+4} + +pat sde +with any4 any4 + kills posextern + gen move %1, {absolute4, $1} + move %2, {absolute4, $1+4} + +pat sdf +with A_REG any4 any4 + kills allexceptcon + gen move %2, {offsetted4, %1, $1} + move %3, {offsetted4, %1, $1+4} +with exact local_addr any4 any4 + kills allexceptcon + gen move %2, {LOCAL, %1.bd+$1} + move %3, {LOCAL, %1.bd+$1+4} +with exact ext_addr any4 any4 + kills allexceptcon + gen move %2, {absolute4, %1.bd+$1} + move %3, {absolute4, %1.bd+$1+4} +#ifndef m68020 +with regAcon any4 any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} + move %3, {offsetted4, %1.reg, %1.bd+$1+4} +#else m68020 +with exact regAcon any4 any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} + move %3, {offsetted4, %1.reg, %1.bd+$1+4} +with exact regAregXcon any4 any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} + move %3, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1+4} +with exact indirect4 any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, 0, $1} + move %3, {OFF_off4, %1.reg, 0, $1+4} +with exact offsetted4 any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, $1} + move %3, {OFF_off4, %1.reg, %1.bd, $1+4} +with exact LOCAL any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, lb, %1.bd, $1} + move %3, {OFF_off4, lb, %1.bd, $1+4} +with exact off_con any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, %1.od+$1} + move %3, {OFF_off4, %1.reg, %1.bd, %1.od+$1+4} +with exact off_regXcon any4 any4 + kills allexceptcon + gen move %2, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} + move %3, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} +with exact index_off4 any4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} + move %3, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1+4} +with exact indoff_con any4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} + move %3, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} +with exact absolute4 any4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, $1} + move %3, {ABS_off4, %1.bd, $1+4} +with exact abs_con any4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, %1.od+$1} + move %3, {ABS_off4, %1.bd, %1.od+$1+4} +with exact abs_regXcon any4 any4 + kills allexceptcon + gen move %2, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} + move %3, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} +with exact abs_index4 any4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} + move %3, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1+4} +with exact absind_con any4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} + move %3, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} +with exact ext_regX any4 any4 + kills allexceptcon + gen move %2, {abs_index4, %1.sc, %1.xreg, %1.bd+$1} + move %3, {abs_index4, %1.sc, %1.xreg, %1.bd+$1+4} +#endif m68020 + + + +/************************************************ + * Group 3: integer arithmetic. * + ************************************************/ + + +pat adi $1==4 +with any4 DD_REG + gen add_l %1, %2 yields %2 +with DD_REG any4-DD_REG + gen add_l %2, %1 yields %1 +with DD_REG STACK + gen add_l {post_inc4, sp}, %1 + yields %1 + +pat sbi $1==4 +with any4 DD_REG + gen sub_l %1, %2 yields %2 +with DD_REG any4-DD_REG + gen sub_l %2, %1 + neg_l %1 yields %1 +with DD_REG STACK + gen sub_l {post_inc4, sp}, %1 + neg_l %1 yields %1 +with any4 AA_REG + gen sub_l %1, %2 yields %2 + +pat mli $1==4 +#ifdef m68020 +with data4 DD_REG + gen muls_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".mli"} + yields d1 +#endif m68020 + +pat dvi $1==4 +#ifdef m68020 +with data4 DD_REG + gen divs_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".dvi"} + yields d1 +#endif m68020 + +pat rmi $1==4 +#ifdef m68020 +with data4 DD_REG + uses DD_REG + gen divsl_l %1, {DREG_pair, %a, %2} + killreg %2 + /* !!!! contents of %2 have changed: make this known to cg */ + yields %a +#else m68020 +with STACK + gen jsr {absolute4, ".dvi"} + yields d0 +#endif m68020 + +pat ngi $1==4 +with DD_REG + gen neg_l %1 yields %1 + +pat sli $1==4 +with D_REG DD_REG + gen asl_l %1, %2 yields %2 + +pat sri $1==4 +with D_REG DD_REG + gen asr_l %1, %2 yields %2 + + + +/************************************************ + * Group 4: unsigned arithmetic. * + ************************************************/ + + +pat adu leaving adi $1 + +pat sbu leaving sbi $1 + +pat mlu $1==4 +#ifdef m68020 +with data4 DD_REG + gen mulu_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".mlu"} + yields d1 +#endif m68020 + +pat dvu $1==4 +#ifdef m68020 +with data4 DD_REG + gen divu_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".dvu"} + yields d1 +#endif m68020 + +pat rmu $1==4 +#ifdef m68020 +with data4 DD_REG + uses DD_REG + gen divul_l %1, {DREG_pair, %a, %2} + killreg %2 + /* !!!! contents of %2 have changed: make this known to cg */ + yields %a +#else m68020 +with STACK + gen jsr {absolute4, ".dvu"} + yields d0 +#endif m68020 + +pat slu leaving sli $1 + +pat sru $1==4 +with D_REG DD_REG + gen lsr_l %1, %2 yields %2 + + + +/************************************************ + * Group 5: floating point arithmetic * + * * + * is not available on 68000, 68010 or 68020 * + * so traps will be generated * + ************************************************/ + +pat adf leaving loc 18 trp +pat sbf leaving loc 18 trp +pat mlf leaving loc 18 trp +pat dvf leaving loc 18 trp +pat ngf leaving loc 18 trp +pat fif leaving loc 18 trp +pat fef leaving loc 18 trp + + + +/************************************************ + * Group 6: pointer arithmetic * + ************************************************/ + +pat adp $1==0 /* skip; array instructions might 'leave' this */ + +pat adp +with A_REG yields {t_regAcon, %1, $1} +with exact local_addr yields {local_addr, %1.bd+$1} +with exact ext_addr yields {ext_addr, %1.bd+$1} +with exact regAcon + t_regAcon + yields {t_regAcon, %1.reg, %1.bd+$1} +with exact regAregXcon + t_regAregXcon + yields {t_regAregXcon,%1.reg, %1.xreg, %1.sc, %1.bd+$1} +#ifdef m68020 +with exact indirect4 yields {off_con, %1.reg, 0, $1} +with exact LOCAL yields {off_con, lb, %1.bd, $1} +with exact offsetted4 yields {off_con, %1.reg, %1.bd, $1} +with exact off_con yields {off_con, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon yields {off_regXcon, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 yields {indoff_con, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con yields {indoff_con, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 yields {abs_con, %1.bd, $1} +with exact abs_con yields {abs_con, %1.bd, %1.od+$1} +with exact abs_regXcon yields {abs_regXcon, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 yields {absind_con, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con yields {absind_con, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX yields {ext_regX, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat ads $1==4 +with D_REG A_REG yields {regAregXcon, %2, %1, 1, 0} +with D_REG regAcon + t_regAcon + yields {t_regAregXcon, %2.reg, %1, 1, %2.bd} +with D_REG local_addr yields {t_regAregXcon, lb, %1, 1, %2.bd} +with any4-D_REG AA_REG + gen add_l %1, %2 yields %2 + +#ifdef m68020 + +with D_REG yields {regX, 1, %1} + leaving ads 4 +with regX A_REG yields {regAregXcon, %2, %1.xreg, %1.sc, 0} +with exact regX regAcon yields {regAregXcon, %2.reg, %1.xreg, %1.sc, %2.bd} +with exact regX local_addr + yields {regAregXcon, lb, %1.xreg, %1.sc, %2.bd} +with exact regX ext_addr + yields {ext_regX, %1.sc, %1.xreg, %2.bd} +with exact regX indirect4 + yields {off_regXcon, %2.reg, %1.xreg,%1.sc,0,0} +with exact regX offsetted4 + yields {off_regXcon, %2.reg, %1.xreg, %1.sc, %2.bd, 0} +with exact regX LOCAL yields {off_regXcon, lb, %1.xreg, %1.sc, %2.bd, 0} +with exact regX off_con yields {off_regXcon, %2.reg, %1.xreg,%1.sc,%2.bd,%2.od} +with exact regX absolute4 + yields {abs_regXcon, %1.sc, %1.xreg, %2.bd, 0} +with exact regX abs_con yields {abs_regXcon, %1.sc, %1.xreg, %2.bd, %2.od} +with exact indirect4 ext_addr + yields {off_con, %1.reg, 0, %2.bd} +with exact offsetted4 ext_addr + yields {off_con, %1.reg, %1.bd, %2.bd} +with exact LOCAL ext_addr + yields {off_con, lb, %1.bd, %2.bd} +with exact index_off4 ext_addr + yields {indoff_con, %1.reg, %1.xreg, %1.sc,%1.bd,%2.bd} +with exact absolute4 ext_addr + yields {abs_con, %1.bd, %2.bd} +with exact abs_index4 ext_addr + yields {absind_con, %1.sc, %1.xreg, %1.bd, %2.bd} +with exact indirect4 ext_regX + yields {off_regXcon, %1.reg, %2.xreg, %2.sc, 0, %2.bd} +with exact offsetted4 ext_regX + yields {off_regXcon, %1.reg, %2.xreg,%2.sc,%1.bd,%2.bd} +with exact LOCAL ext_regX + yields {off_regXcon, lb, %2.xreg, %2.sc, %1.bd, %2.bd} +with exact absolute4 ext_regX + yields {abs_regXcon, %2.sc, %2.xreg, %1.bd, %2.bd} +#endif m68020 + + /* I WOULD ALSO LIKE THIS: + * pat ads + * with const leaving adp %1.num + * BUT THAT DOESN'T WORK. + */ + +pat sbs $1==4 leaving sbi 4 + +#ifdef m68020 +pat loc sli ads $1==1 && $2==4 && $3==4 +with D_REG yields {regX, 2, %1} + leaving ads 4 + +pat loc sli ads $1==2 && $2==4 && $3==4 +with D_REG yields {regX, 4, %1} + leaving ads 4 + +pat loc sli ads $1==3 && $2==4 && $3==4 +with D_REG yields {regX, 8, %1} + leaving ads 4 +#endif m68020 + + +/************************************************ + * Group 7: increment / decrement / zero * + ************************************************/ + +pat inc +with exact STACK + gen add_l {const, 1}, {indirect4, sp} +with DD_REG+AA_REG + gen add_l {const, 1}, %1 + yields %1 + +pat inl + kills all_indir, LOCAL %bd==$1 + gen add_l {const, 1}, {LOCAL, $1} + +pat ine + kills posextern + gen add_l {const, 1}, {absolute4, $1} + +pat dec +with exact STACK + gen sub_l {const, 1}, {indirect4, sp} +with DD_REG+AA_REG + gen sub_l {const, 1}, %1 + yields %1 + +pat del + kills all_indir, LOCAL %bd==$1 + gen sub_l {const, 1}, {LOCAL, $1} + +pat dee + kills posextern + gen sub_l {const, 1}, {absolute4, $1} + +pat zrl + kills all_indir, LOCAL %bd==$1 + gen clr_l {LOCAL, $1} + +pat zre + kills posextern + gen clr_l {absolute4, $1} + +pat zer $1==4 yields {const, 0} +pat zer $1==8 yields {const, 0} {const, 0} +pat zer $1==12 yields {const, 0} {const, 0} {const, 0} + +pat zer +with STACK + uses DD_REG = {const, $1/4 -1} + gen 1: + clr_l {pre_dec4, sp} + dbf %a, {slabel, 1b} + + +pat zrf leaving loc 18 trp + + + +/************************************************ + * Group 8: convert instructions * + * for float conversions traps are generated * + ************************************************/ + + + +pat cii +with STACK + gen jsr {absolute4, ".cii"} + +pat cuu +with STACK + gen jsr {absolute4, ".cuu"} + +pat ciu leaving cuu + +pat cui leaving cuu + +pat cfi leaving loc 18 trp +pat cif leaving loc 18 trp +pat cfu leaving loc 18 trp +pat cuf leaving loc 18 trp +pat cff leaving loc 18 trp + + +/************************************************ + * Group 9: logical instructions * + ************************************************/ + + +proc log4 +with datalt4+const DD_REG + gen xxx* %1, %2 yields %2 +with DD_REG datalt4+const + gen xxx* %2, %1 yields %1 + +proc logdef example and +with STACK + uses DD_REG = {const, $1/4 -1}, + AA_REG = {regAcon, sp, $1}, + DD_REG + gen 1: + move_l {post_inc4, sp}, %c + xxx* %c, {post_inc4, %b} + dbf %a, {slabel, 1b} + +proc logndef +with DD_REG STACK + uses AA_REG = {regAregXcon, sp, %1, 1, 0}, + DD_REG + gen asr_l {shconst, 2}, %1 + sub_l {const, 1}, %1 + 1: + move_l {post_inc4, sp}, %b + xxx* %b, {post_inc4, %a} + dbf %1, {slabel, 1b} + +pat and $1==4 call log4("and.l") +pat and $1>4 call logdef("and.l") +pat and !defined($1) call logndef("and.l") +pat ior $1==4 call log4("or.l") +pat ior $1>4 call logdef("or.l") +pat ior !defined($1) call logndef("or.l") + +pat xor $1==4 +with conreg4 DD_REG + gen eor_l %1, %2 yields %2 +with DD_REG conreg4 + gen eor_l %2, %1 yields %1 + +pat xor $1>4 call logdef("eor.l") +pat xor !defined($1) call logndef("eor.l") + +pat com $1==4 +with DD_REG + gen not_l %1 yields %1 + +pat com $1==8 +with DD_REG DD_REG + gen not_l %1 + not_l %2 yields %2 %1 + +pat com $1>4 +with STACK + uses AA_REG, + DD_REG = {const, $1/4 -1} + gen move_l sp, %a + 1: + not_l {post_inc4, %a} + dbf %b, {slabel, 1b} + +pat com !defined($1) +with DD_REG STACK + uses AA_REG + gen move_l sp, %a + asr_l {shconst, 2}, %1 + sub_l {const, 1}, %1 + 1: + not_l {post_inc4, %a} + dbf %1, {slabel, 1b} + +pat rol $1==4 +with D_REG DD_REG + gen rol_l %1, %2 yields %2 + +pat ror $1==4 +with D_REG DD_REG + gen ror_l %1, %2 yields %2 + + + + +/************************************************ + * Group 10: sets * + ************************************************/ + + +pat inn $1==4 +with conreg2 DD_REG + gen btst %1, %2 + sne %2 + and_l {const, 1}, %2 + yields %2 + +pat inn defined($1) +with any4 STACK + gen move %1, d0 + move {const, $1}, d1 + jsr {absolute4, ".inn"} + yields d0 + +pat inn !defined($1) +with any4 any4 STACK + gen move %2, d0 + move %1, d1 + jsr {absolute4, ".inn"} + yields d0 + +pat loc inn $2==4 && small($1) +with DD_REG + gen asr_l {shconst, $1}, %1 + and_l {const, 1}, %1 + yields %1 + +pat set $1==4 +with conreg2 + uses DD_REG = {const, 0} + gen bset %1, %a yields %a + +pat set $1>4 +with any4 STACK + gen move %1, d0 + move {const, $1}, d1 + jsr {absolute4, ".set"} + +pat set !defined($1) +with any4 any4 STACK + gen move %2, d0 + move %1, d1 + jsr {absolute4, ".set"} + + + + +/************************************************ + * Group 11: arrays * + ************************************************/ + + +pat lar defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".lar"} + +pat lar !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".lar"} + +pat sar defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".sar"} + +pat sar !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".sar"} + +pat aar defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".aar"} + yields a0 + +pat aar !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".aar"} + yields a0 + +pat lae lar $2==4 && nicesize(rom($1,3)) + leaving lae $1 aar 4 loi rom($1, 3) +pat lae sar $2==4 && nicesize(rom($1,3)) + leaving lae $1 aar 4 sti rom($1, 3) + +pat lae aar $2==4 && rom($1,3)==1 + leaving ads 4 adp 0-rom($1,1) + +#ifdef m68020 +pat lae aar $2==4 && nicesize(rom($1,3)) +with D_REG yields {regX, rom($1,3), %1} + leaving ads 4 adp rom($1,3)*(0-rom($1,1)) +#else m68020 +pat lae aar $2==4 && rom($1,3)==2 +with DD_REG + gen asl_l {shconst, 1}, %1 + yields %1 + leaving ads 4 adp (0 - rom($1,1))<<1 + +pat lae aar $2==4 && rom($1,3)==4 +with DD_REG + gen asl_l {shconst, 2}, %1 + yields %1 + leaving ads 4 adp (0 - rom($1,1))<<2 + +pat lae aar $2==4 && rom($1,3)==8 +with DD_REG + gen asl_l {shconst, 3}, %1 + yields %1 + leaving ads 4 adp (0 - rom($1,1))<<3 +#endif m68020 + + /* I WOULD ALSO LIKE THESE: + * pat lae aar $2==4 && defined(rom($1,3)) + * with const leaving adp rom($1,3)*(%1.num-rom($1,1)) + * pat lae lar $2==4 && defined(rom($1,3)) + * with const leaving adp rom($1,3)*(%1.num-rom($1,1)) + * loi rom($1,3) + * pat lae sar $2==4 && defined(rom($1,3)) + * with const leaving adp rom($1,3)*(%1.num-rom($1,1)) + * sti rom($1,3) + * BUT THEY DON'T WORK. + */ + + + +/************************************************ + * Group 12: compare instructions * + ************************************************/ + + +pat cmi $1==4 leaving sbi 4 + +pat cmi defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".cmi"} + yields d0 + +pat cmi !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".cmi"} + yields d0 + +pat cmu $1==4 leaving sbi 4 + +pat cmu defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".cmu"} + yields d0 + +pat cmu !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".cmu"} + yields d0 + +pat cms $1==4 leaving sbi 4 + +pat cms defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".cms"} + yields d0 + +pat cms !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".cms"} + yields d0 + +pat cmp leaving cmu 4 + +proc txx +with test_set + uses DD_REG = {const, 1} + gen test %1 + bxx* {slabel, 1f} + clr_l %a + 1: + yields %a + +pat tlt call txx("blt") +pat tle call txx("ble") +pat teq call txx("beq") +pat tne call txx("bne") +pat tge call txx("bge") +pat tgt call txx("bgt") + +pat cmf leaving loc 18 trp + + + +/************************************************ + * Group 13: branch instructions * + ************************************************/ + +pat bra +with STACK + gen bra {llabel, $1} + +proc brxx example beq +with any4 genreg STACK + gen cmp_l %1, %2 + bxx[1] {llabel, $1} +with genreg any4 STACK + gen cmp_l %2, %1 + bxx[2] {llabel, $1} +with exact immediate4 imm_cmp4 + kills ALL + gen cmp_l %1, %2 + bxx[1] {llabel, $1} +with exact imm_cmp4 immediate4 + kills ALL + gen cmp_l %2, %1 + bxx[2] {llabel, $1} +with genreg STACK + gen cmp_l {post_inc4, sp}, %1 + bxx[2] {llabel, $1} +with exact immediate4 STACK + gen cmp_l %1, {post_inc4, sp} + bxx[1] {llabel, $1} +with any2-conreg2 genreg STACK + gen cmp_w %1, %2 + bxx[1] {llabel, $1} +with genreg any2-conreg2 STACK + gen cmp_w %2, %1 + bxx[2] {llabel, $1} +with exact const imm_cmp2 + kills ALL + gen cmp_w {const, loww(%1.num)}, %2 + bxx[1] {llabel, $1} +with exact imm_cmp2 const + kills ALL + gen cmp_w {const, loww(%2.num)}, %1 + bxx[2] {llabel, $1} +with data1-conreg1 D_REG STACK + gen cmp_b %1, %2 + bxx[1] {llabel, $1} +with D_REG data1-conreg1 STACK + gen cmp_b %2, %1 + bxx[2] {llabel, $1} +with exact const imm_cmp1 + kills ALL + gen cmp_b {const, lowb(%1.num)}, %2 + bxx[1] {llabel, $1} +with exact imm_cmp1 const + kills ALL + gen cmp_b {const, lowb(%2.num)}, %1 + bxx[2] {llabel, $1} + +pat blt call brxx("blt","bgt") +pat ble call brxx("ble","bge") +pat beq call brxx("beq","beq") +pat bne call brxx("bne","bne") +pat bge call brxx("bge","ble") +pat bgt call brxx("bgt","blt") + +proc zxx example zeq +with test_set STACK + gen test %1 + bxx* {llabel, $1} +with exact STACK + gen test {post_inc4, sp} + bxx* {llabel, $1} + +pat zlt call zxx("blt") +pat zle call zxx("ble") +pat zeq call zxx("beq") +pat zne call zxx("bne") +pat zge call zxx("bge") +pat zgt call zxx("bgt") + +/************************************************ + * Group 14: procedure calls instructions * + ************************************************/ + + +pat cai +with exact ext_addr + kills ALL + gen jsr {absolute4, %1.bd} +with A_REG STACK + gen jsr {indirect4, %1} +with STACK + uses AA_REG = {post_inc4, sp} + gen jsr {indirect4, %a} +#ifdef m68020 +with exact address + kills ALL + gen jsr %1 +#else m68020 +with address STACK + gen jsr %1 +#endif m68020 + +pat cal +with STACK + gen jsr {absolute4, $1} + +pat lfr $1==4 yields d0 +pat lfr $1==8 yields d1 d0 + +pat ret $1==0 +with STACK + gen return + +pat ret $1==4 +with any4 STACK + gen move %1, d0 + return +with STACK + gen move {post_inc4, sp}, d0 + return + +pat ret $1==8 +with any4 any4 STACK + gen move %1, d0 + move %2, d1 + return +with any4 STACK + gen move %1, d0 + move {post_inc4, sp}, d1 + return +with STACK + gen move {post_inc4, sp}, d0 + move {post_inc4, sp}, d1 + return + + +/************************************************ + * Group 15: miscellaneous instructions * + ************************************************/ + +pat asp small($1) +with STACK + gen add_l {const, $1}, sp +pat asp +with STACK + gen move {regAcon, sp, $1}, sp + +pat ass $1==4 +with any4 STACK + gen add_l %1, sp + +pat blm $1==4 +with A_REG A_REG + kills allexceptcon + gen move_l {indirect4, %2}, {indirect4, %1} + +pat blm $1==8 +with A_REG A_REG + kills allexceptcon + gen move_l {indirect4, %2}, {indirect4, %1} + move_l {offsetted4, %2, 4}, {offsetted4, %1, 4} + +pat blm $1>8 +with AA_REG AA_REG + kills allexceptcon + uses DD_REG={const, $1/4 -1} + gen 1: + move_l {post_inc4, %2}, {post_inc4, %1} + dbf %a, {slabel, 1b} + +pat bls $1==4 +with DD_REG AA_REG AA_REG + kills allexceptcon + gen asr_l {shconst, 2}, %1 + beq {slabel, 2f} + sub_l {const, 1}, %1 + 1: + move_l {post_inc4, %3}, {post_inc4, %2} + dbf %1, {slabel, 1b} + 2: + +pat csa $1==4 +with STACK + gen jmp {absolute4, ".csa"} + +pat csb $1==4 +with STACK + gen jmp {absolute4, ".csb"} + +pat dch leaving loi 4 + +pat dup $1==4 +with exact STACK + gen move_l {indirect4, sp}, {pre_dec4, sp} +with any4 yields %1 %1 + +pat dup $1==8 +with exact STACK + gen move_l {offsetted4, sp, 4}, {pre_dec4, sp} + move_l {offsetted4, sp, 4}, {pre_dec4, sp} +with any4 any4 yields %2 %1 %2 %1 + +pat dup $1>8 +with STACK + uses DD_REG = {const, $1/4 -1} + gen 1: + move_l {offsetted4, sp, $1 -4}, {pre_dec4, sp} + dbf %a, {slabel, 1b} + +pat dus $1==4 +with DD_REG STACK + uses AA_REG = {regAregXcon, sp, %1, 1, 0} + gen asr_l {shconst, 2}, %1 + beq {slabel, 2f} + sub_l {const, 1}, %1 + 1: + move_l {pre_dec4, %a}, {pre_dec4, sp} + dbf %1, {slabel, 1b} + 2: + +pat exg $1==4 +with any4 any4 yields %1 %2 + +pat exg defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".exg"} + +pat exg !defined($1) +with any4 STACK + gen move_l %1, d0 + jsr {absolute4, ".exg"} + +pat fil + gen move_l {ext_addr, $1}, {absolute4, ".filn"} + +pat gto +with STACK + uses AA_REG = {ext_addr, $1} + gen move_l {offsetted4, %a, 8}, lb + move_l {offsetted4, %a, 4}, sp +#ifdef m68020 + jmp {OFF_off4, %a, 0, 0} +#else m68020 + move_l {indirect4, %a}, %a + jmp {indirect4, %a} +#endif m68020 + +pat lim yields {absolute4, ".trpim"} + +pat lin + gen move {const, $1}, {absolute4, ".lino"} + +pat lni + gen add_l {const, 1}, {absolute4, ".lino"} + +pat lor $1==0 yields lb + +pat lor $1==1 +with STACK + uses AA_REG = sp yields %a + +pat lor $1==2 yields {absolute4, ".reghp"} + +pat lpb leaving adp 8 + +pat mon +with STACK + gen jsr {absolute4, ".mon"} + +pat nop +with STACK + gen jsr {absolute4, ".nop"} + +pat rck +#ifdef m68020 +with ext_addr D_REG + gen cmp2_l {absolute4, %1.bd}, %2 + bcc {slabel, 1f} + pea {absolute4, 1} /* push constant 1 == ERANGE */ + jsr {absolute4, ".trp"} + 1: yields %2 +with address-ext_addr D_REG + gen cmp2_l %1, %2 + bcc {slabel, 1f} + pea {absolute4, 1} /* push constant 1 == ERANGE */ + jsr {absolute4, ".trp"} + 1: yields %2 +with A_REG D_REG + gen cmp2_l {indirect4, %1}, %2 + bcc {slabel, 1f} + pea {absolute4, 1} /* push constant 1 == ERANGE */ + jsr {absolute4, ".trp"} + 1: yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".rck"} +#endif m68020 + +pat rtt leaving ret 0 + +pat sig +with any4 + uses AA_REG + gen move {absolute4, ".trppc"}, %a + move %1, {absolute4, ".trppc"} + yields %a + +pat sim +with any4 + gen move_l %1, {absolute4, ".trpim"} + +pat str $1==0 +with any4 +#ifdef m68020 + kills LOCAL, ILOCAL, all_regind %reg==lb, local_addr +#else m68020 + kills LOCAL, all_regind %reg==lb, local_addr +#endif m68020 + gen move %1, lb + +pat str $1==1 +with any4 STACK + gen move %1, sp + +pat str $1==2 +with STACK + gen jsr {absolute4, ".strhp"} + +pat trp +with STACK + gen jsr {absolute4, ".trp"} + + + +/************************************************ + * rules for long EM-patterns * + ************************************************/ + +proc lolxxxstl example lol adi stl +with conreg4 + kills all_indir, LOCAL %bd==$1 + gen xxx* %1, {LOCAL, $1} + +proc loexxxste example loe adi ste +with conreg4 + kills posextern + gen xxx* %1, {absolute4, $1} + +proc lilxxxsil example lil adi sil +with conreg4 +#ifdef m68020 + kills allexceptcon + gen xxx* %1, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen xxx* %1, {indirect4, %a} +#endif m68020 + +proc lolcxxxstl example lol loc adi stl + kills all_indir, LOCAL %bd==$1 + gen xxx* {const, $2}, {LOCAL, $1} + +proc loecxxxste example loe loc adi ste + kills posextern + gen xxx* {const, $2}, {absolute4, $1} + +proc lilcxxxsil example lil loc adi sil +#ifdef m68020 + kills allexceptcon + gen xxx* {const, $2}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen xxx* {const, $2}, {indirect4, %a} +#endif m68020 + +proc lolrxxxstl example lol lol adi stl + kills all_indir, LOCAL %bd==$1 + gen xxx* {LOCAL, $2}, {LOCAL, $1} + +proc loerxxxste example loe lol adi ste + kills posextern + gen xxx* {LOCAL, $2}, {absolute4, $1} + +proc lilrxxxsil example lil lol adi sil +#ifdef m68020 + kills allexceptcon + gen xxx* {LOCAL, $2}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen xxx* {LOCAL, $2}, {indirect4, %a} +#endif m68020 + +pat lol adi stl $1==$3 && $2==4 call lolxxxstl("add.l") +pat loe adi ste $1==$3 && $2==4 call loexxxste("add.l") +pat lil adi sil $1==$3 && $2==4 call lilxxxsil("add.l") +pat lol loc adi stl $1==$4 && $3==4 call lolcxxxstl("add.l") +pat loe loc adi ste $1==$4 && $3==4 call loecxxxste("add.l") +pat lil loc adi sil $1==$4 && $3==4 call lilcxxxsil("add.l") +pat lol lol adi stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("add.l") +pat loe lol adi ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("add.l") +pat lil lol adi sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("add.l") + +pat lol adu stl $1==$3 && $2==4 call lolxxxstl("add.l") +pat loe adu ste $1==$3 && $2==4 call loexxxste("add.l") +pat lil adu sil $1==$3 && $2==4 call lilxxxsil("add.l") +pat lol loc adu stl $1==$4 && $3==4 call lolcxxxstl("add.l") +pat loe loc adu ste $1==$4 && $3==4 call loecxxxste("add.l") +pat lil loc adu sil $1==$4 && $3==4 call lilcxxxsil("add.l") +pat lol lol adu stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("add.l") +pat loe lol adu ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("add.l") +pat lil lol adu sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("add.l") + + +pat lol adp stl $1==$3 + kills all_indir, LOCAL %bd==$1 + gen add_l {const, $2}, {LOCAL, $1} + +pat lil adp sil $1==$3 + kills allexceptcon +#ifdef m68020 + gen add_l {const, $2}, {ILOCAL, $1} +#else m68020 + uses AA_REG = {LOCAL, $1} + gen add_l {const, $2}, {indirect4, %a} +#endif m68020 + +pat loe adp ste $1==$3 + kills posextern + gen add_l {const, $2}, {absolute4, $1} + +pat lol lol adp stl $1==$2 && $1==$4 + kills all_indir, LOCAL %bd==$1 + uses AA_REG = {LOCAL, $1} + gen add_l {const, $3}, {LOCAL, $1} + yields %a + +pat lil lil adp sti $1==$2 && $1==$4 + kills allexceptcon +#ifdef m68020 + uses AA_REG = {ILOCAL, $1} + gen add_l {const, $3}, {ILOCAL, $1} +#else m68020 + uses AA_REG, AA_REG = {LOCAL, $1} + gen move {indirect4, %b}, %a + add_l {const, $3}, {indirect4, %b} +#endif m68020 + yields %a + +pat loe loe adp ste $1==$2 && $1==$4 + kills posextern + uses AA_REG = {absolute4, $1} + gen add_l {const, $3}, {absolute4, $1} + yields %a + + +pat lol loc sbi stl $1==$4 && $3==4 call lolcxxxstl("sub.l") +pat loe loc sbi ste $1==$4 && $3==4 call loecxxxste("sub.l") +pat lil loc sbi sil $1==$4 && $3==4 call lilcxxxsil("sub.l") +pat lol lol sbi stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("sub.l") +pat loe lol sbi ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("sub.l") +pat lil lol sbi sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("sub.l") + +pat lol loc sbu stl $1==$4 && $3==4 call lolcxxxstl("sub.l") +pat loe loc sbu ste $1==$4 && $3==4 call loecxxxste("sub.l") +pat lil loc sbu sil $1==$4 && $3==4 call lilcxxxsil("sub.l") +pat lol lol sbu stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("sub.l") +pat loe lol sbu ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("sub.l") +pat lil lol sbu sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("sub.l") + +pat lol and stl $1==$3 && $2==4 call lolxxxstl("and.l") +pat loe and ste $1==$3 && $2==4 call loexxxste("and.l") +pat lil and sil $1==$3 && $2==4 call lilxxxsil("and.l") +pat lol loc and stl $1==$4 && $3==4 call lolcxxxstl("and.l") +pat loe loc and ste $1==$4 && $3==4 call loecxxxste("and.l") +pat lil loc and sil $1==$4 && $3==4 call lilcxxxsil("and.l") +pat lol lol and stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("and.l") +pat loe lol and ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("and.l") +pat lil lol and sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("and.l") + +pat lol ior stl $1==$3 && $2==4 call lolxxxstl("or.l") +pat loe ior ste $1==$3 && $2==4 call loexxxste("or.l") +pat lil ior sil $1==$3 && $2==4 call lilxxxsil("or.l") +pat lol loc ior stl $1==$4 && $3==4 call lolcxxxstl("or.l") +pat loe loc ior ste $1==$4 && $3==4 call loecxxxste("or.l") +pat lil loc ior sil $1==$4 && $3==4 call lilcxxxsil("or.l") +pat lol lol ior stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("or.l") +pat loe lol ior ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("or.l") +pat lil lol ior sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("or.l") + +pat lol xor stl $1==$3 && $2==4 call lolxxxstl("eor.l") +pat loe xor ste $1==$3 && $2==4 call loexxxste("eor.l") +pat lil xor sil $1==$3 && $2==4 call lilxxxsil("eor.l") +pat lol loc xor stl $1==$4 && $3==4 call lolcxxxstl("eor.l") +pat loe loc xor ste $1==$4 && $3==4 call loecxxxste("eor.l") +pat lil loc xor sil $1==$4 && $3==4 call lilcxxxsil("eor.l") +pat lol lol xor stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("eor.l") +pat loe lol xor ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("eor.l") +pat lil lol xor sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("eor.l") + +proc llol1shstl example lol loc sli stl /* only left */ + kills all_indir, LOCAL %bd==$1 + gen shw* {offsetted2, lb, $1+2} + roxl {offsetted2, lb, $1} + +proc lloe1shste example loe loc sli ste /* only left */ + kills posextern + gen shw* {absolute2, $1+2} + roxl {absolute2, $1} + +proc llil1shsil example lil loc sli sil /* only left */ +#ifdef m68020 + kills allexceptcon + gen shw* {OFF_off2, lb, $1, 2} + roxl {OFF_off2, lb, $1, 0} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen shw* {offsetted2, %a, 2} + roxl {indirect2, %a} +#endif m68020 + +proc rlol1shstl example lol loc sri stl /* only right */ + kills all_indir, LOCAL %bd==$1 + gen shw* {offsetted2, lb, $1} + roxr {offsetted2, lb, $1+2} + +proc rloe1shste example loe loc sri ste /* only right */ + kills posextern + gen shw* {absolute2, $1} + roxr {absolute2, $1+2} + +proc rlil1shsil example lil loc sri sil /* only right */ +#ifdef m68020 + kills allexceptcon + gen shw* {OFF_off2, lb, $1, 0} + roxr {OFF_off2, lb, $1, 2} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen shw* {indirect2, %a} + roxr {offsetted2, %a, 2} +#endif m68020 + +pat lol loc sli stl $1==$4 && $2==1 && $3==4 call llol1shstl("asl #1,") +pat loe loc sli ste $1==$4 && $2==1 && $3==4 call lloe1shste("asl #1,") +pat lil loc sli sil $1==$4 && $2==1 && $3==4 call llil1shsil("asl #1,") +pat lol loc sri stl $1==$4 && $2==1 && $3==4 call rlol1shstl("asr #1,") +pat loe loc sri ste $1==$4 && $2==1 && $3==4 call rloe1shste("asr #1,") +pat lil loc sri sil $1==$4 && $2==1 && $3==4 call rlil1shsil("asr #1,") +pat lol loc slu stl $1==$4 && $2==1 && $3==4 call llol1shstl("asl #1,") +pat loe loc slu ste $1==$4 && $2==1 && $3==4 call lloe1shste("asl #1,") +pat lil loc slu sil $1==$4 && $2==1 && $3==4 call llil1shsil("asl #1,") +pat lol loc sru stl $1==$4 && $2==1 && $3==4 call rlol1shstl("lsr #1,") +pat loe loc sru ste $1==$4 && $2==1 && $3==4 call rloe1shste("lsr #1,") +pat lil loc sru sil $1==$4 && $2==1 && $3==4 call rlil1shsil("lsr #1,") + +proc locsh example loc sli +with DD_REG + gen sh* {shconst, $1}, %1 + yields %1 + +pat loc sli small($1) && $2==4 call locsh("asl.l") +pat loc sri small($1) && $2==4 call locsh("asr.l") +pat loc slu small($1) && $2==4 call locsh("asl.l") +pat loc sru small($1) && $2==4 call locsh("lsr.l") +pat loc rol small($1) && $2==4 call locsh("rol.l") +pat loc ror small($1) && $2==4 call locsh("ror.l") + +proc lolbitstl example lol ngi stl + kills all_indir, LOCAL %bd==$1 + gen bit* {LOCAL, $1} + +proc loebitste example loe ngi ste + kills posextern + gen bit* {absolute4, $1} + +proc lilbitsil example lil ngi sil +#ifdef m68020 + kills allexceptcon + gen bit* {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen bit* {indirect4, %a} +#endif m68020 + +pat lol ngi stl $1==$3 && $2==4 call lolbitstl("neg.l") +pat loe ngi ste $1==$3 && $2==4 call loebitste("neg.l") +pat lil ngi sil $1==$3 && $2==4 call lilbitsil("neg.l") +pat lol com stl $1==$3 && $2==4 call lolbitstl("not.l") +pat loe com ste $1==$3 && $2==4 call loebitste("not.l") +pat lil com sil $1==$3 && $2==4 call lilbitsil("not.l") + +pat lil inc sil $1==$3 +#ifdef m68020 + kills allexceptcon + gen add_l {const, 1}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen add_l {const, 1}, {indirect4, %a} +#endif m68020 + +pat lil dec sil $1==$3 +#ifdef m68020 + kills allexceptcon + gen sub_l {const, 1}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen sub_l {const, 1}, {indirect4, %a} +#endif m68020 + + +proc txxand +with test_set DD_REG + gen test %1 + bxx* {slabel, 1f} + clr_l %2 + 1: yields %2 + +proc txxior +with test_set DD_REG + gen test %1 + bxx* {slabel, 1f} + bset {const, 0}, %2 + 1: yields %2 + +pat tlt and $2==4 call txxand("blt") +pat tle and $2==4 call txxand("ble") +pat teq and $2==4 call txxand("beq") +pat tne and $2==4 call txxand("bne") +pat tge and $2==4 call txxand("bge") +pat tgt and $2==4 call txxand("bgt") + +pat tlt ior $2==4 call txxior("bge") +pat tle ior $2==4 call txxior("bgt") +pat teq ior $2==4 call txxior("bne") +pat tne ior $2==4 call txxior("beq") +pat tge ior $2==4 call txxior("blt") +pat tgt ior $2==4 call txxior("ble") + +proc cmxtxxand +with any4 genreg DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %3 + 1: yields %3 +with genreg any4-genreg DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %3 + 1: yields %3 +with exact immediate4 imm_cmp4 DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %3 + 1: yields %3 +with exact imm_cmp4 immediate4 DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %3 + 1: yields %3 + +proc cmxtxxior +with any4 genreg DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 +with genreg any4-genreg DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 +with exact immediate4 imm_cmp4 DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 +with exact imm_cmp4 immediate4 DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 + +proc cmxtxx +with any4 genreg + uses DD_REG = {const, 1} + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %a + 1: yields %a +with genreg any4-genreg + uses DD_REG = {const, 1} + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %a + 1: yields %a +with exact immediate4 imm_cmp4 + uses DD_REG = {const, 1} + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %a + 1: yields %a +with exact imm_cmp4 immediate4 + uses DD_REG = {const, 1} + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %a + 1: yields %a +with genreg STACK + uses DD_REG = {const, 1} + gen cmp_l {post_inc4, sp}, %1 + bxx[2] {slabel, 1f} + clr_l %a + 1: yields %a +with exact immediate4 STACK + uses DD_REG = {const, 1} + gen cmp_l %1, {post_inc4, sp} + bxx[1] {slabel, 1f} + clr_l %a + 1: yields %a + +pat cmi tlt and $1==4 && $3==4 call cmxtxxand("blt","bgt") +pat cmi tle and $1==4 && $3==4 call cmxtxxand("ble","bge") +pat cmi teq and $1==4 && $3==4 call cmxtxxand("beq","beq") +pat cmi tne and $1==4 && $3==4 call cmxtxxand("bne","bne") +pat cmi tge and $1==4 && $3==4 call cmxtxxand("bge","ble") +pat cmi tgt and $1==4 && $3==4 call cmxtxxand("bgt","blt") + +pat cmu tlt and $1==4 && $3==4 call cmxtxxand("bcs","bhi") +pat cmu tle and $1==4 && $3==4 call cmxtxxand("bls","bcc") +pat cmu teq and $1==4 && $3==4 call cmxtxxand("beq","beq") +pat cmu tne and $1==4 && $3==4 call cmxtxxand("bne","bne") +pat cmu tge and $1==4 && $3==4 call cmxtxxand("bcc","bls") +pat cmu tgt and $1==4 && $3==4 call cmxtxxand("bhi","bcs") + +pat cmi tlt ior $1==4 && $3==4 call cmxtxxior("bge","ble") +pat cmi tle ior $1==4 && $3==4 call cmxtxxior("bgt","blt") +pat cmi teq ior $1==4 && $3==4 call cmxtxxior("bne","bne") +pat cmi tne ior $1==4 && $3==4 call cmxtxxior("beq","beq") +pat cmi tge ior $1==4 && $3==4 call cmxtxxior("blt","bgt") +pat cmi tgt ior $1==4 && $3==4 call cmxtxxior("ble","bge") + +pat cmu tlt ior $1==4 && $3==4 call cmxtxxior("bcc","bls") +pat cmu tle ior $1==4 && $3==4 call cmxtxxior("bhi","bcs") +pat cmu teq ior $1==4 && $3==4 call cmxtxxior("bne","bne") +pat cmu tne ior $1==4 && $3==4 call cmxtxxior("beq","beq") +pat cmu tge ior $1==4 && $3==4 call cmxtxxior("bcs","bhi") +pat cmu tgt ior $1==4 && $3==4 call cmxtxxior("bls","bcc") + +pat cmi tlt $1==4 call cmxtxx("blt","bgt") +pat cmi tle $1==4 call cmxtxx("ble","bge") +pat cmi teq $1==4 call cmxtxx("beq","beq") +pat cmi tne $1==4 call cmxtxx("bne","bne") +pat cmi tge $1==4 call cmxtxx("bge","blt") +pat cmi tgt $1==4 call cmxtxx("bgt","blt") + +pat cmu tlt $1==4 call cmxtxx("bcs","bhi") +pat cmu tle $1==4 call cmxtxx("bls","bcc") +pat cmu teq $1==4 call cmxtxx("beq","beq") +pat cmu tne $1==4 call cmxtxx("bne","bne") +pat cmu tge $1==4 call cmxtxx("bcc","bls") +pat cmu tgt $1==4 call cmxtxx("bhi","bcs") + +proc cmxzxx example cmu zlt +with any4 genreg STACK + gen cmp_l %1, %2 + bxx[1] {llabel, $2} +with genreg any4-genreg STACK + gen cmp_l %2, %1 + bxx[2] {llabel, $2} +with exact immediate4 imm_cmp4 + kills ALL + gen cmp_l %1, %2 + bxx[1] {llabel, $2} +with exact imm_cmp4 immediate4 + kills ALL + gen cmp_l %2, %1 + bxx[2] {llabel, $2} +with genreg STACK + gen cmp_l {post_inc4, sp}, %1 + bxx[2] {llabel, $2} +with exact immediate4 STACK + gen cmp_l %1, {post_inc4, sp} + bxx[1] {llabel, $2} + +pat cmu zlt $1==4 call cmxzxx("bcs","bhi") +pat cmu zle $1==4 call cmxzxx("bls","bcc") +pat cmu zeq $1==4 call cmxzxx("beq","beq") +pat cmu zne $1==4 call cmxzxx("bne","bne") +pat cmu zge $1==4 call cmxzxx("bcc","bls") +pat cmu zgt $1==4 call cmxzxx("bhi","bcs") + + +proc bxx1_in example loc loc cii loc bne +with imm_cmp1 STACK + gen cmp_b {const, lowb($4)}, %1 + bxx* {llabel, $5} + +proc bxx2_in example loc loc cii loc bne +with imm_cmp2 STACK + gen cmp_w {const, loww($4)}, %1 + bxx* {llabel, $5} + +pat loc loc cii loc blt $1==1 && $2==4 && in_1($4) call bxx1_in("blt") +pat loc loc cii loc ble $1==1 && $2==4 && in_1($4) call bxx1_in("ble") +pat loc loc cii loc beq $1==1 && $2==4 && in_1($4) call bxx1_in("beq") +pat loc loc cii loc bne $1==1 && $2==4 && in_1($4) call bxx1_in("bne") +pat loc loc cii loc bge $1==1 && $2==4 && in_1($4) call bxx1_in("bge") +pat loc loc cii loc bgt $1==1 && $2==4 && in_1($4) call bxx1_in("bgt") + +pat loc loc cii loc blt $1==2 && $2==4 && in_2($4) call bxx2_in("blt") +pat loc loc cii loc ble $1==2 && $2==4 && in_2($4) call bxx2_in("ble") +pat loc loc cii loc beq $1==2 && $2==4 && in_2($4) call bxx2_in("beq") +pat loc loc cii loc bne $1==2 && $2==4 && in_2($4) call bxx2_in("bne") +pat loc loc cii loc bge $1==2 && $2==4 && in_2($4) call bxx2_in("bge") +pat loc loc cii loc bgt $1==2 && $2==4 && in_2($4) call bxx2_in("bgt") + +pat loc loc cii $1==1 && $2==2 +with DD_REG + gen ext_w %1 yields %1 + +pat loc loc cii $1==2 && $2==4 +with DD_REG + gen ext_l %1 yields %1 + +pat loc loc cii $1==1 && $2==4 +with DD_REG +#ifdef m68020 + gen extb_l %1 yields %1 +#else m68020 + gen ext_w %1 + ext_l %1 yields %1 +#endif m68020 + +pat loc loc ciu $1==$2 /* skip this */ +pat loc loc cui $1==$2 /* skip this */ + + +/* The following rules should be handled by the peephole optimizer, I think */ + +pat loc dvi $1==2 && $2==4 leaving loc 1 sri 4 +pat loc dvi $1==4 && $2==4 leaving loc 2 sri 4 +pat loc dvi $1==8 && $2==4 leaving loc 3 sri 4 +pat loc dvi $1==16 && $2==4 leaving loc 4 sri 4 +pat loc dvi $1==32 && $2==4 leaving loc 5 sri 4 +pat loc dvi $1==64 && $2==4 leaving loc 6 sri 4 +pat loc dvi $1==128 && $2==4 leaving loc 7 sri 4 +pat loc dvi $1==256 && $2==4 leaving loc 8 sri 4 + +pat loc dvu $1==2 && $2==4 leaving loc 1 sru 4 +pat loc dvu $1==4 && $2==4 leaving loc 2 sru 4 +pat loc dvu $1==8 && $2==4 leaving loc 3 sru 4 +pat loc dvu $1==16 && $2==4 leaving loc 4 sru 4 +pat loc dvu $1==32 && $2==4 leaving loc 5 sru 4 +pat loc dvu $1==64 && $2==4 leaving loc 6 sru 4 +pat loc dvu $1==128 && $2==4 leaving loc 7 sru 4 +pat loc dvu $1==256 && $2==4 leaving loc 8 sru 4 diff --git a/mach/m68k4/ncg/mach.c b/mach/m68k4/ncg/mach.c new file mode 100644 index 000000000..ec51f8bf1 --- /dev/null +++ b/mach/m68k4/ncg/mach.c @@ -0,0 +1,236 @@ +/* + * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands. + * + * This product is part of the Amsterdam Compiler Kit. + * + * Permission to use, sell, duplicate or disclose this software must be + * obtained in writing. Requests for such permissions may be sent to + * + * Dr. Andrew S. Tanenbaum + * Wiskundig Seminarium + * Vrije Universiteit + * Postbox 7161 + * 1007 MC Amsterdam + * The Netherlands + * + */ + +/* + * machine dependent back end routines for the Motorola 68000, 68010 or 68020 + */ + +#ifndef m68k4 +#define m68020 +#endif + /* use m68020 when you want a m68020 cg, don't if you want a + * m68k4 cg. The m68k4 cg can be used for both the MC68000 + * and the MC68010. + */ + +con_part(sz,w) register sz; word w; { + + while (part_size % sz) + part_size++; + if (part_size == 4) + 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) + w <<= 16; + part_word |= w; + } else { + assert(sz == 4); + part_word = w; + } + part_size += sz; +} + +con_mult(sz) word sz; { + + if (sz != 4) + fatal("bad icon/ucon size"); + fprintf(codefile,".data4 %s\n",str); +} + +con_float() { + +static int been_here; + if (argval != 4 && argval != 8) + fatal("bad fcon size"); + fprintf(codefile,".data4\t"); + if (argval == 8) + fprintf(codefile,"F_DUM,"); + fprintf(codefile,"F_DUM\n"); + if ( !been_here++) + { + fprintf(stderr,"Warning : dummy float-constant(s)\n"); + } +} + +regscore(off,size,typ,score,totyp) + long off; +{ + if (score == 0) return -1; + switch(typ) { + case reg_float: + return -1; + case reg_pointer: + if (size != 4 || totyp != reg_pointer) return -1; + score *= 2; + break; + case reg_loop: + score += 5; + /* fall through .. */ + case reg_any: + if (size != 4 || totyp == reg_pointer) return -1; + break; + } + if (off >= 0) { + /* parameters must be initialised with an instruction + * like "move.l 4(a6),d0", which costs 2 words. + */ + score -= 2; + } + score -= 1; /* take save/restore into account */ + return score; +} +struct regsav_t { + char *rs_reg; /* e.g. "a3" or "d5" */ + long rs_off; /* offset of variable */ + int rs_size; /* 2 or 4 bytes */ +} regsav[9]; + + +int regnr; + +i_regsave() +{ + regnr = 0; +} + +#define MOVEM_LIMIT 2 +/* If #registers to be saved exceeds MOVEM_LIMIT, we +* use the movem instruction to save registers; else +* we simply use several move.l's. +*/ + +save() +{ + register struct regsav_t *p; + + if (regnr > MOVEM_LIMIT) { + fprintf(codefile,"movem.l "); + for (p = regsav; ;) { + fprintf(codefile,"%s",p->rs_reg); + if (++p == ®sav[regnr]) break; + putc('/',codefile); + } + fprintf(codefile,",-(sp)\n"); + } else { + for (p = regsav; p < ®sav[regnr]; p++) { + fprintf(codefile,"move.l %s,-(sp)\n",p->rs_reg); + } + } + /* initialise register-parameters */ + for (p = regsav; p < ®sav[regnr]; p++) { + if (p->rs_off >= 0) { +#ifdef m68020 + fprintf(codefile,"move.%c (%ld,a6),%s\n", +#else + fprintf(codefile,"move.%c %ld(a6),%s\n", +#endif + (p->rs_size == 4 ? 'l' : 'w'), + p->rs_off, + p->rs_reg); + } + } +} + +restr() +{ + register struct regsav_t *p; + + if (regnr > MOVEM_LIMIT) { + fprintf(codefile,"movem.l (sp)+,"); + for (p = regsav; ;) { + fprintf(codefile,"%s",p->rs_reg); + if (++p == ®sav[regnr]) break; + putc('/',codefile); + } + putc('\n',codefile); + } else { + for (p = ®sav[regnr-1]; p >= regsav; p--) { + fprintf(codefile,"move.l (sp)+,%s\n",p->rs_reg); + } + } + fprintf(codefile,"unlk a6\n"); + fprintf(codefile,"rts\n"); +} + + +f_regsave() +{ + save(); +} + +regsave(str,off,size) + char *str; + long off; +{ + assert (regnr < 9); + regsav[regnr].rs_reg = str; + regsav[regnr].rs_off = off; + regsav[regnr++].rs_size = size; + fprintf(codefile, "!Local %ld into %s\n",off,str); +} + +regreturn() +{ + restr(); +} + + +prolog(nlocals) full nlocals; { + +#ifdef m68020 + fprintf(codefile,"tst.b (-%ld,sp)\nlink\ta6,#-%ld\n",nlocals+40,nlocals); +#else + fprintf(codefile,"tst.b -%ld(sp)\nlink\ta6,#-%ld\n",nlocals+40,nlocals); +#endif +} + + + +mes(type) 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", /* SEGTXT */ + ".sect .data", /* SEGCON */ + ".sect .rom", /* SEGROM */ + ".sect .bss" /* SEGBSS */ +}; diff --git a/mach/m68k4/ncg/mach.h b/mach/m68k4/ncg/mach.h new file mode 100644 index 000000000..ff2cf66ca --- /dev/null +++ b/mach/m68k4/ncg/mach.h @@ -0,0 +1,39 @@ +#ifndef m68k4 +#define m68020 +#endif + /* m68020 should be used for a m68020 cg, and it should + * not be used for a m68k4 cg + */ + +#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,"%s:.space\t%ld\n",l,x); + +#define pop_fmt "(sp)+" +#define cst_fmt "%ld" +#define off_fmt "%ld" +#define ilb_fmt "I%03x%x" +#define dlb_fmt "_%d" +#define hol_fmt "hol%d" + +#ifdef m68020 +#define loc_off "(%d,a6)" +#define arg_off "(8+%d,a6)" +#else +#define loc_off "%d(a6)" +#define arg_off "8+%d(a6)" +#endif +#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 modhead ".sect .text\n.sect .rom\n.sect .data\n.sect .bss\n" + +#define id_first '_' +#define BSS_INIT 0 diff --git a/mach/m68k4/ncg/table b/mach/m68k4/ncg/table new file mode 100644 index 000000000..6518487ad --- /dev/null +++ b/mach/m68k4/ncg/table @@ -0,0 +1,3288 @@ + /******************************** + * * + * 68000, 68010 and 68020 * + * back end table * + * * + ********************************/ + + +#ifndef m68k4 +#define m68020 +#endif + /* m68020 to be defined if this is the 68020 table. + * The 68000 and 68010 tables are identical. + */ + + +#define small(x) ((x)>=1 && (x)<=8) +#define nicesize(x) ((x)==1||(x)==2||(x)==4||(x)==8) +#define lowb(x) (((x)<<24)>>24) +#define loww(x) (((x)<<16)>>16) +#define in_1(x) ((x)>=0-128 && (x)<128) +#define in_2(x) ((x)>=0-32768 && (x)<32768) + + +EM_WSIZE = 4 +EM_PSIZE = 4 +EM_BSIZE = 8 + +SL = 8 + +TIMEFACTOR = 1/2 + + +PROPERTIES + +D_REG /* data registers */ +A_REG /* address registers */ +DD_REG /* allocatable D_REG, may not be a register variable */ +AA_REG /* allocatable A_REG, may not be a register variable */ + + + +REGISTERS + +d0, d1, d2 :D_REG, DD_REG. +d3, d4, d5, d6, d7 :D_REG regvar. +a0, a1 :A_REG, AA_REG. +a2, a3, a4, a5 :A_REG regvar(reg_pointer). +lb ("a6"), sp :A_REG. /* localbase and stack pointer */ + + + + +TOKENS + + /* Not all addressing modes available on the MC68020 are used in this + * table. E.g (Dn), data register indirect is not used. Compared to + * (An), address register indirect, (Dn) requires two more bytes and + * several more clock cycles. Using (Dn) is even more expensive in + * time than first moving Dn to an address register An, and then using + * (An). For this kind of reasons several addressing modes are + * not used in this table. + * + * Cost in bytes may sometimes be incorrect. Several effective addresses + * use displacements that can occupy either 2 or 4 bytes. These are not + * considered different TOKENS in this table. + * + * Data registers are the only registers used as index registers in this + * table; address registers are only used to hold addresses. + * + * For the m68k4 table: the MC68000 and MC68010 have two modes that use + * displacements (offsets) of limited size: + * - offset(A_REG, Index_reg), where offset is only 8 bits, and + * - offset(A_REG), where offset can only be 16 bits. + * To make sure that no output is given with offsets too large, two + * extra tokens are declared: t_regAregXcon and t_regAcon. These are + * used as addresses to these modes. Whenever the displacements become + * too large, they are transformed into different tokens. + * + * Sometimes some TOKENS are used with displacements (offsets) of 0. + * It would have been possible to provide separate TOKENS for these, in + * case the assembler doesn't handle zero offsets optimally. This + * however would mean a very large amount of extra TOKENS and SETS for + * a very small profit in code bytes, so we won't do that. + * + * To prevent the TOKENS list from getting too unreadable, #ifdefs are + * used to form three parts: + * (i) the common part; + * (ii) the m68k4 part; + * (iii) the m68020 part; + */ + + /* Part (i) */ +const = {INT num;} 4 cost(4,4) "#" num . +indirect4 = {A_REG reg;} 4 cost(0,4) "(" reg ")" . +post_inc4 = {A_REG reg;} 4 cost(0,4) "(" reg ")+" . +pre_dec4 = {A_REG reg;} 4 cost(0,5) "-(" reg ")" . +indirect2 = {A_REG reg;} 4 cost(0,4) "(" reg ")" . +post_inc2 = {A_REG reg;} 4 cost(0,4) "(" reg ")+" . +pre_dec2 = {A_REG reg;} 4 cost(0,5) "-(" reg ")" . +indirect1 = {A_REG reg;} 4 cost(0,4) "(" reg ")" . +post_inc1 = {A_REG reg;} 4 cost(0,4) "(" reg ")+" . +pre_dec1 = {A_REG reg;} 4 cost(0,5) "-(" reg ")" . + +ext_addr = {ADDR bd;} 4 cost(4,5) "#" bd . +llabel = {ADDR bd;} 4 cost(2,0) bd . +slabel = {ADDR bd;} 4 cost(0,0) bd . +shconst = {INT num;} 4 cost(0,0) "#" num . + +#ifndef m68020 + /* Part (ii) */ +absolute4 = {ADDR bd;} 4 cost(4,8) bd . +offsetted4 = {A_REG reg; INT bd;} 4 cost(2,6) bd "(" reg ")" . +index_off4 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,7) + bd "(" reg "," xreg ".l)" . +absolute2 = {ADDR bd;} 4 cost(4,6) bd . +offsetted2 = {A_REG reg; INT bd;} 4 cost(2,4) bd "(" reg ")" . +index_off2 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,5) + bd "(" reg "," xreg ".l)" . +absolute1 = {ADDR bd;} 4 cost(4,6) bd . +offsetted1 = {A_REG reg; INT bd;} 4 cost(2,4) bd "(" reg ")" . +index_off1 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,5) + bd "(" reg "," xreg ".l)" . + +LOCAL = {INT bd;} 4 cost(2,6) bd "(a6)" . + +local_addr = {INT bd;} 4 cost(2,6) bd "(a6)" . +regAcon = {A_REG reg; INT bd;} 4 cost(2,6) bd "(" reg ")" . +regAregXcon = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,8) + bd "(" reg "," xreg ".l)" . + /* note: in the m68k4 version %sc always equals 1 */ + +t_regAregXcon = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,8) . +t_regAcon = {A_REG reg; INT bd;} 4 cost(2,6) . + +#else m68020 + /* Part (iii) */ +absolute4 = {ADDR bd;} 4 cost(4,7) "(" bd ")" . +offsetted4 = {A_REG reg; INT bd;} 4 cost(2,6) "(" bd "," reg ")" . +index_off4 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(4,9) + "(" bd "," reg "," xreg ".l*" sc ")" . +abs_index4 = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,9) + "(" bd "," xreg ".l*" sc ")" . +OFF_off4 = {A_REG reg; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," od ")" . +OFF_indoff4 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +INDOFF_off4 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +ABS_off4 = {ADDR bd; ADDR od;} 4 cost(8,22) "([" bd "]," od ")" . +ABS_indoff4 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "]," xreg ".l*" sc "," od ")" . +ABSIND_off4 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "," xreg ".l*" sc "]," od ")" . + +absolute2 = {ADDR bd;} 4 cost(4,7) "(" bd ")" . +offsetted2 = {A_REG reg; INT bd;} 4 cost(2,6) "(" bd "," reg ")" . +index_off2 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(4,9) + "(" bd "," reg "," xreg ".l*" sc ")" . +abs_index2 = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,9) + "(" bd "," xreg ".l*" sc ")" . +OFF_off2 = {A_REG reg; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," od ")" . +OFF_indoff2 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +INDOFF_off2 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +ABS_off2 = {ADDR bd; ADDR od;} 4 cost(8,22) "([" bd "]," od ")" . +ABS_indoff2 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "]," xreg ".l*" sc "," od ")" . +ABSIND_off2 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "," xreg ".l*" sc "]," od ")" . + +absolute1 = {ADDR bd;} 4 cost(4,7) "(" bd ")" . +offsetted1 = {A_REG reg; INT bd;} 4 cost(2,6) "(" bd "," reg ")" . +index_off1 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(4,9) + "(" bd "," reg "," xreg ".l*" sc ")" . +abs_index1 = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,9) + "(" bd "," xreg ".l*" sc ")" . +OFF_off1 = {A_REG reg; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," od ")" . +OFF_indoff1 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +INDOFF_off1 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +ABS_off1 = {ADDR bd; ADDR od;} 4 cost(8,22) "([" bd "]," od ")" . +ABS_indoff1 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "]," xreg ".l*" sc "," od ")" . +ABSIND_off1 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "," xreg ".l*" sc "]," od ")" . + +LOCAL = {INT bd;} 4 cost(2,6) "(" bd ",a6)" . +ILOCAL = {INT bd;} 4 cost(4,16) "([" bd ",a6])" . + +local_addr = {INT bd;} 4 cost(2,3) "(" bd ",a6)" . +regAcon = {A_REG reg; INT bd;} 4 cost(2,3) "(" bd "," reg ")" . +regAregXcon = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,7) + "(" bd "," reg "," xreg ".l*" sc ")" . +off_con = {A_REG reg; INT bd; ADDR od;} 4 cost(6,18) + "([" bd "," reg "]," od ")". +off_regXcon = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,18) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +indoff_con = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,18) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +abs_con = {ADDR bd; ADDR od;} 4 cost(8,21) "([" bd "]," od ")" . +abs_regXcon = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,21) + "([" bd "]," xreg ".l*" sc "," od ")" . +absind_con = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,21) + "([" bd "," xreg ".l*" sc "]," od ")" . +ext_regX = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,15) + "(" bd "," xreg ".l*" sc ")" . + +regX = {INT sc; D_REG xreg;} 4 cost(2,7) "(" xreg ".l*" sc ")" . +DREG_pair = {D_REG reg1; D_REG reg2;} 8 cost(2,0) reg1 ":" reg2 . + +#define t_regAregXcon regAregXcon +#define t_regAcon regAcon + +#endif m68020 + +SETS + + /* The SETS list cannot be kept as 'readable' as the TOKENS list + * because cgg is one pass. + */ + +#ifndef m68020 + /* A m68k4 part */ +data4 = D_REG + LOCAL + const + post_inc4 + pre_dec4 + + indirect4 + offsetted4 + index_off4 + absolute4 + + ext_addr . +memory4 = data4 - D_REG . +control4 = indirect4 + offsetted4 + index_off4 + absolute4 + + LOCAL . +alterable4 = data4 + A_REG - const - ext_addr . +any4 = data4 + A_REG . /* all four above together */ + +data2 = D_REG + post_inc2 + pre_dec2 + indirect2 + + offsetted2 + index_off2 + absolute2 + const . +memory2 = data2 - D_REG . +control2 = indirect2 + offsetted2 + index_off2 + absolute2 . +alterable2 = data2 + A_REG - const . +any2 = data2 + A_REG . + +data1 = D_REG + post_inc1 + pre_dec1 + indirect1 + + offsetted1 + index_off1 + absolute1 + const . +memory1 = data1 - D_REG . +control1 = indirect1 + offsetted1 + index_off1 + absolute1 . +alterable1 = data1 - const . +any1 = data1 . + +#else m68020 + +data4 = D_REG + indirect4 + post_inc4 + pre_dec4 + index_off4 + + offsetted4 + OFF_off4 + OFF_indoff4 + + INDOFF_off4 + + ABS_off4 + ABS_indoff4 + ABSIND_off4 + + absolute4 + abs_index4 + const + ext_addr + + LOCAL + ILOCAL . +memory4 = data4 - D_REG . +control4 = memory4 - (post_inc4 + pre_dec4 + const + ext_addr) . +alterable4 = data4 + A_REG - const - ext_addr . +any4 = data4 + A_REG . /* all four above together */ + +data2 = D_REG + indirect2 + post_inc2 + pre_dec2 + index_off2 + + offsetted2 + OFF_off2 + OFF_indoff2 + + INDOFF_off2 + + ABS_off2 + ABS_indoff2 + ABSIND_off2 + + absolute2 + abs_index2 + const . +memory2 = data2 - D_REG . +control2 = memory2 - (post_inc2 + pre_dec2 + const) . +alterable2 = data2 + A_REG - const . +any2 = data2 + A_REG . /* all four above together */ + +data1 = D_REG + indirect1 + post_inc1 + pre_dec1 + index_off1 + + offsetted1 + OFF_off1 + OFF_indoff1 + + INDOFF_off1 + + ABS_off1 + ABS_indoff1 + ABSIND_off1 + + absolute1 + abs_index1 + const . +memory1 = data1 - D_REG . +control1 = memory1 - (post_inc1 + pre_dec1 + const) . +alterable1 = data1 - const . +any1 = data1 . /* all four above together */ + +#endif m68020 + /* This is a common part */ +any = any4 + any2 + any1 . +absolute = absolute4 + absolute2 + absolute1 . +control = control4 + control2 + control1 . +indirect = indirect4 + indirect2 + indirect1 . +pre_post = pre_dec4 + pre_dec2 + pre_dec1 + + post_inc4 + post_inc2 + post_inc1 . +offsetted = offsetted4 + offsetted2 + offsetted1 . +index_off = index_off4 + index_off2 + index_off1 . + +#ifndef m68020 + /* A m68k4 part */ +regind_addr = regAcon + regAregXcon + t_regAcon + t_regAregXcon . +address = ext_addr + local_addr + regAcon + regAregXcon . +all_regind = indirect + offsetted + pre_post + index_off + + regind_addr . +all_indir = all_regind . +allexceptcon = ALL - ( D_REG + A_REG + const + + local_addr + ext_addr + regAcon + regAregXcon + + t_regAcon + t_regAregXcon ) . +use_index = index_off4 + index_off2 + index_off1 . + +#else m68020 + +reg_memind4 = OFF_off4 + OFF_indoff4 + INDOFF_off4 . +memind4 = reg_memind4 + + ABS_off4 + ABS_indoff4 . +reg_memind2 = OFF_off2 + OFF_indoff2 + INDOFF_off2 . +memind2 = reg_memind2 + + ABS_off2 + ABS_indoff2 . +reg_memind1 = OFF_off1 + OFF_indoff1 + INDOFF_off1 . +memind1 = reg_memind1 + + ABS_off1 + ABS_indoff1 . +reg_memind = reg_memind4 + reg_memind2 + reg_memind1 . +memind = memind4 + memind2 + memind1 . +regind_addr = regAcon + regAregXcon + + off_con + off_regXcon + + indoff_con . +address = regind_addr + + ext_addr + local_addr + + abs_con + abs_regXcon + + absind_con + + ext_regX . +all_regind = indirect + offsetted + index_off + pre_post + + reg_memind + regind_addr . +all_indir = all_regind + memind + ILOCAL . +allexceptcon = ALL - ( D_REG + A_REG + const + + local_addr + ext_addr + regAcon + regAregXcon + ext_regX ) . +use_index4 = index_off4 + abs_index4 + + OFF_indoff4 + INDOFF_off4 + + ABS_indoff4 + ABSIND_off4 . +use_index2 = index_off2 + abs_index2 + + OFF_indoff2 + INDOFF_off2 + + ABS_indoff2 + ABSIND_off2 . +use_index1 = index_off1 + abs_index1 + + OFF_indoff1 + INDOFF_off1 + + ABS_indoff1 + ABSIND_off1 . +use_indaddr = regAregXcon + + off_regXcon + indoff_con + + abs_regXcon + absind_con + + ext_regX . + +use_index = use_index4 + use_index2 + use_index1 + use_indaddr + regX . + +#endif m68020 + /* A common part */ +posextern = absolute + all_indir . + +genreg = D_REG + A_REG. +label = llabel + slabel . +immediate4 = const + ext_addr . +conreg4 = D_REG + immediate4 . +conreg2 = D_REG + const . +conreg1 = D_REG + const . +shconreg = D_REG + shconst . +datalt4 = data4 * alterable4 . +datalt2 = data2 * alterable2 . +datalt1 = data1 * alterable1 . +datalt = datalt4 + datalt2 + datalt1 . +memalt4 = memory4 * alterable4 . +memalt2 = memory2 * alterable2 . +memalt1 = memory1 * alterable1 . + +#ifndef m68020 + /* A m68k4 part */ +imm_cmp4 = alterable4 . +imm_cmp2 = alterable2 . +imm_cmp1 = datalt1 . + +test_set4 = datalt4 . +test_set2 = datalt2 . +test_set1 = datalt1 . + +#else m68020 + +imm_cmp4 = any4 - immediate4 . +imm_cmp2 = any2 - const . +imm_cmp1 = data1 - const . + +test_set4 = data4 - immediate4 . +test_set2 = data2 - const . +test_set1 = data1 - const . + +#endif m68020 + +test_set = test_set4 + test_set2 + test_set1 . + +#ifndef m68020 +t_address = address + t_regAregXcon + t_regAcon . +#else m68020 +#define t_address address +#endif m68020 + + +INSTRUCTIONS + + /* Since the 68000 , the 68010 and the 68020 instruction sets are rather + * extensive, especially because e.g. 'add.l' and 'add.w' are + * considered different instructions, only those instructions are + * listed here that are used in the rest of this table. + * + * Instruction timing cost cannot be accurately given, nor the timing + * cost for getting operands. Detailed information about this can be + * found in the "MC68020 User's Manual", section 9, about instruction + * timing. The cost used in this table are 'worst case' cost, as + * mentioned in section 9 of the user's manual. + * + * The first few instructions had to be added because register + * variables are used. The LOCALs below are register variables. + * One may not conclude that these operations are also allowed + * on LOCALs that are not register variables. + * The cost have been adapted, but are not accurate; when 'real' + * LOCALs are used the cost are very inaccurate. + */ + +add_l "add.l" any4:ro, LOCAL:rw:cc cost(0,0). +lea address:ro, LOCAL:wo cost(0,0). +sub_l "sub.l" any4:ro, LOCAL:rw:cc cost(0,0). +sh "illegal" shconreg:ro, LOCAL:rw:cc cost(0,0). +sh "illegal" LOCAL:ro, LOCAL:rw:cc cost(0,0). +xxx "illegal" data4:ro, LOCAL:rw:cc cost(0,0). +xxx "illegal" LOCAL:ro, alterable4:rw:cc cost(0,0). +#ifdef m68020 +divs_l "divs.l" data4:ro, LOCAL:rw:cc cost(0,90). +divu_l "divu.l" data4:ro, LOCAL:rw:cc cost(0,78). +muls_l "muls.l" data4:ro, LOCAL:rw:cc cost(0,44). +mulu_l "mulu.l" data4:ro, LOCAL:rw:cc cost(0,44). +#endif m68020 + +add_l "add.l" any4:ro, D_REG:rw:cc cost(2,3). +add_l "add.l" any4:ro, A_REG:rw cost(2,3). +add_l "add.l" conreg4:ro, alterable4:rw:cc cost(2,6). +and_l "and.l" data4:ro, D_REG:rw:cc cost(2,3). +and_l "and.l" D_REG:ro, memalt4:rw:cc cost(2,6). +and_l "and.l" const:ro, datalt4:rw:cc cost(2,6). +asl_l "asl.l" shconreg:ro, D_REG:rw:cc cost(2,5). +asl "asl #1," memalt2:rw:cc cost(2,4). +asr_l "asr.l" shconreg:ro, D_REG:rw:cc cost(2,4). +asr "asr #1," memalt2:rw:cc cost(2,4). +bra label cost(2,5). +bcc label cost(2,5). +bcs label cost(2,5). +beq label cost(2,5). +bge label cost(2,5). +bgt label cost(2,5). +bhi label cost(2,5). +ble label cost(2,5). +bls label cost(2,5). +blt label cost(2,5). +bmi label cost(2,5). +bne label cost(2,5). +bpl label cost(2,5). +bvc label cost(2,5). +bvs label cost(2,5). +bset conreg2:ro, D_REG:rw kills :cc cost(2,4). +btst conreg2:ro, data1:rw kills :cc cost(2,3). +clr_l "clr.l" D_REG:wo:cc cost(2,3). +clr_l "clr.l" memalt4:wo:cc cost(2,6). +clr_w "clr.w" D_REG:wo:cc cost(2,2). +clr_w "clr.w" memalt2:wo:cc cost(2,4). +clr_b "clr.b" D_REG:wo:cc cost(2,2). +clr_b "clr.b" memalt1:wo:cc cost(2,4). +cmp_l "cmp.l" any4:ro, genreg:ro kills :cc cost(2,3). +cmp_l "cmp.l" post_inc4:ro, post_inc4:ro kills :cc cost(2,2). +cmp_l "cmp.l" immediate4:ro, imm_cmp4:ro kills :cc cost(2,2). +cmp_w "cmp.w" any2:ro, genreg:ro kills :cc cost(2,3). +cmp_w "cmp.w" post_inc2:ro, post_inc2:ro kills :cc cost(2,2). +cmp_w "cmp.w" const:ro, imm_cmp2:ro kills :cc cost(2,2). +cmp_b "cmp.b" data1:ro, D_REG:ro kills :cc cost(2,3). +cmp_b "cmp.b" post_inc1:ro, post_inc1:ro kills :cc cost(2,2). +cmp_b "cmp.b" const:ro, imm_cmp1:ro kills :cc cost(2,2). +dbf D_REG:rw, label cost(2,5). +eor_l "eor.l" conreg4:ro, datalt4:rw:cc cost(2,6). +ext_l "ext.l" D_REG:rw:cc cost(2,2). +ext_w "ext.w" D_REG:rw:cc cost(2,2). +jmp address+control4 cost(2,0). +jsr address+control4 kills :cc cost(2,3). +lea address+control4:ro, A_REG:wo cost(2,0). +lsl_l "lsl.l" shconreg:ro, D_REG:rw:cc cost(2,4). +lsl "lsl #1," memalt2:rw:cc cost(2,4). +lsr_l "lsr.l" shconreg:ro, D_REG:rw:cc cost(2,4). +lsr "lsr #1," memalt2:rw:cc cost(2,4). +move_l "move.l" any4:ro, alterable4:wo:cc cost(2,2). +move_w "move.w" any2:ro, alterable2:wo:cc cost(2,2). +move_b "move.b" data1:ro, alterable1:wo:cc cost(2,2). +neg_l "neg.l" D_REG:rw:cc cost(2,3). +neg_l "neg.l" memory4:rw:cc cost(2,6). +not_l "not.l" D_REG:rw:cc cost(2,3). +not_l "not.l" memory4:rw:cc cost(2,6). +or_l "or.l" data4:ro, D_REG:rw:cc cost(2,3). +or_l "or.l" D_REG:ro, memalt4:rw:cc cost(2,6). +or_l "or.l" const:ro, datalt4:rw:cc cost(2,6). +rol_l "rol.l" shconreg:ro, D_REG:rw:cc cost(2,4). +rol "rol #1," memalt2:rw:cc cost(2,4). +ror_l "ror.l" shconreg:ro, D_REG:rw:cc cost(2,4). +ror "ror #1," memalt2:rw:cc cost(2,4). +roxl "roxl #1," memalt2:rw:cc cost(2,4). +roxr "roxr #1," memalt2:rw:cc cost(2,4). +sne datalt1:rw cost(2,3). +sub_l "sub.l" any4:ro, D_REG:rw:cc cost(2,3). +sub_l "sub.l" any4:ro, A_REG:rw cost(2,3). +sub_l "sub.l" conreg4:ro, alterable4:rw:cc cost(2,6). +tst_l "tst.l" test_set4:ro:cc cost(2,3). +tst_w "tst.w" test_set2:ro:cc cost(2,3). +tst_b "tst.b" test_set1:ro:cc cost(2,3). +unlk A_REG cost(2,6). + +bxx "illegal" label cost(2,5). +xxx "illegal" data4:ro, D_REG:rw:cc cost(2,3). +xxx "illegal" conreg4:ro, memalt4:rw:cc cost(2,6). +bit "illegal" control4:rw:cc cost(2,6). +sh "illegal" shconreg:ro, D_REG:rw:cc cost(2,4). +shw "illegal" control2:rw:cc cost(2,4). + +#ifdef m68020 +cmp2_l "cmp2.l" address+control4:ro, genreg:ro kills :cc cost(2,18). +divs_l "divs.l" data4:ro, D_REG:rw:cc cost(2,90). +divsl_l "divsl.l" data4:ro, DREG_pair:rw kills :cc cost(2,90). +divu_l "divu.l" data4:ro, D_REG:rw:cc cost(2,78). +divul_l "divul.l" data4:ro, DREG_pair:rw kills :cc cost(2,78). +extb_l "extb.l" D_REG:rw:cc cost(2,4). +muls_l "muls.l" data4:ro, D_REG:rw:cc cost(2,44). +mulu_l "mulu.l" data4:ro, D_REG:rw:cc cost(2,44). +pea address+control4+regX cost(2,4). +#else m68020 +pea address+control4 cost(2,4). +#endif m68020 + + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * Extra pseudo instruction; it just kills a D_REG; + * it is necessary with long divides where remainders are important; + * see also: 'pat rmi' and 'pat rmu' + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ +killreg "! kill" D_REG:wo cost(0,0). + + +MOVES + +from const %num==0 to D_REG + gen clr_l %2 + +from const %num==0 to memalt4 + gen clr_l %2 + +from const %num==0 to memalt2 + gen clr_w %2 + +from const %num==0 to memalt1 + gen clr_b %2 + +from const to memalt1 + gen move_b {const, lowb(%1.num)}, %2 + +from const to memalt2 + gen move_w {const, loww(%1.num)}, %2 + +from regAcon %bd==0 to A_REG + gen move_l %1.reg, %2 + +#ifndef m68020 +from t_regAregXcon sfit(%bd, 8) to A_REG + gen lea {regAregXcon, %1.reg, %1.xreg, 1, %1.bd}, %2 + +from t_regAregXcon to A_REG + gen lea {regAregXcon, %1.reg, %1.xreg, 1, 0}, %2 + add_l {const, %1.bd}, %2 + +from t_regAcon sfit(%bd, 16) to A_REG + gen lea {regAcon, %1.reg, %1.bd}, %2 + +from t_regAcon to A_REG + gen move_l %1.reg, %2 + add_l {const, %1.bd}, %2 +#endif m68020 + +from address - ext_addr to A_REG + gen lea %1, %2 + +from any4 to alterable4 + gen move_l %1, %2 + +from any2 to datalt2 + gen move_w %1, %2 + +from data1 to datalt1 + gen move_b %1, %2 + + + + +TESTS + + +to test test_set4 + gen tst_l %1 + +to test test_set2 + gen tst_w %1 + +to test test_set1 + gen tst_b %1 + + +STACKINGRULES + + +from const %num==0 to STACK + gen clr_l {pre_dec4, sp} + +#ifndef m68020 +from t_regAregXcon sfit(%bd, 8) to STACK + gen pea {regAregXcon, %1.reg, %1.xreg, 1, %1.bd} + +from t_regAregXcon to STACK + gen pea {regAregXcon, %1.reg, %1.xreg, 1, 0} + add_l {const, %1.bd}, {indirect4, sp} + +from t_regAcon sfit(%bd, 16) to STACK + gen pea {regAcon, %1.reg, %1.bd} + +from t_regAcon to STACK + gen move_l %1.reg, {pre_dec4, sp} + add_l {const, %1.bd}, {indirect4, sp} +#endif m68020 + +from address - ext_addr to STACK + gen pea %1 + +from ext_addr to STACK + gen pea {absolute4, %1.bd} + +from const to STACK + gen pea {absolute4, %1.num} + +from any4 to STACK + gen move_l %1, {pre_dec4, sp} + +from any2 to STACK + gen clr_l {pre_dec4, sp} + move_w %1, {offsetted2, sp, 2} + +from data1 to STACK + gen clr_l {pre_dec4, sp} + move_b %1, {offsetted1, sp, 3} + +#ifdef m68020 +from regX to STACK + gen pea %1 +#endif m68020 + /* This last stackingrule is never used: whenever regX is put on + * the fakestack, some em-instuctions are left that remove it + * immediately. However cgg complained about not having a + * stackingrule for regX, so here it is + */ + + +COERCIONS + + +from STACK + uses DD_REG + gen move_l {post_inc4, sp}, %a + yields %a + +from STACK + uses AA_REG + gen move_l {post_inc4, sp}, %a + yields %a + +#ifndef m68020 +from t_regAregXcon sfit(%bd, 8) + yields {regAregXcon, %1.reg, %1.xreg, 1, %1.bd} + +from t_regAregXcon + uses AA_REG=%1.reg + gen add_l {const, %1.bd}, %a + yields {regAregXcon, %a, %1.xreg, 1, 0} + +from t_regAcon sfit(%bd, 16) + yields {regAcon, %1.reg, %1.bd} + +from t_regAcon + uses reusing %1, AA_REG=%1.reg + gen add_l {const, %1.bd}, %a + yields %a +#endif m68020 + +from t_address + uses reusing %1, AA_REG = %1 + yields %a + +from any4 + uses reusing %1, DD_REG = %1 + yields %a + +from any4 + uses reusing %1, AA_REG = %1 + yields %a + +from memory2 + uses DD_REG = {const, 0} + gen move_w %1, %a yields %a + +from memory1 + uses DD_REG = {const, 0} + gen move_b %1, %a yields %a + + + + +PATTERNS + +/************************************************ + * Group 0: rules for register variables * + * LOCALs mentioned here refer to registers * + ************************************************/ + +pat lol inreg($1)==reg_pointer + kills pre_post %reg==regvar($1, reg_pointer) + yields {LOCAL, $1} + +pat lil inreg($1)==reg_pointer + kills pre_post %reg==regvar($1, reg_pointer) + yields {indirect4, regvar($1, reg_pointer)} + +pat stl inreg($1)==reg_any +with any4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen move %1, {LOCAL, $1} + +pat stl inreg($1)==reg_pointer +with any4 + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen move %1, {LOCAL, $1} +with exact ext_addr + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen move %1, {LOCAL, $1} +with exact address-ext_addr + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen lea %1, {LOCAL, $1} + +pat sil inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move %1, {indirect4, regvar($1, reg_pointer)} + + +pat lol sbi stl $1==$3 && $2==4 && inreg($1)==reg_any +with any4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sub_l %1, {LOCAL, $1} + neg_l {LOCAL, $1} + +pat lol sbu stl $1==$3 && $2==4 && inreg($1)==reg_any +with any4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sub_l %1, {LOCAL, $1} + neg_l {LOCAL, $1} + +pat lil sbi sil $1==$3 && $2==4 && inreg($1)==reg_pointer +with conreg4 + kills allexceptcon + gen sub_l %1, {indirect4, regvar($1, reg_pointer)} + neg_l {indirect4, regvar($1, reg_pointer)} + +pat lil sbu sil $1==$3 && $2==4 && inreg($1)==reg_pointer +with conreg4 + kills allexceptcon + gen sub_l %1, {indirect4, regvar($1, reg_pointer)} + neg_l {indirect4, regvar($1, reg_pointer)} + + +pat lil ngi sil $1==$3 && $2==4 && inreg($1)==reg_pointer + kills allexceptcon + gen neg_l {indirect4, regvar($1, reg_pointer)} + +pat lil com sil $1==$3 && $2==4 && inreg($1)==reg_pointer + kills allexceptcon + gen not_l {indirect4, regvar($1, reg_pointer)} + + +proc lolcshstl example lol loc sli stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sh* {shconst, $2}, {LOCAL, $1} + +proc lolrshstl example lol lol sli stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sh* {LOCAL, $2}, {LOCAL, $1} + +proc lil1shlsil example lil loc sli sil /* only left */ + kills allexceptcon + gen shw* {offsetted2, regvar($1, reg_pointer), 2} + roxl {indirect2, regvar($1, reg_pointer)} + +proc lil1shrsil example lil loc sli sil /* only right */ + kills allexceptcon + gen shw* {indirect2, regvar($1, reg_pointer)} + roxr {offsetted2, regvar($1, reg_pointer), 2} + +pat lol loc sli stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("asl.l") +pat lol loc slu stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("asl.l") +pat lol lol sli stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("asl.l") +pat lol lol slu stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("asl.l") +pat lil loc sli sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shlsil("asl #1,") +pat lil loc slu sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shlsil("asl #1,") +pat lol loc sri stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("asr.l") +pat lol loc sru stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("lsr.l") +pat lol lol sri stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("asr.l") +pat lol lol sru stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("lsr.l") +pat lil loc sri sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shrsil("asr #1,") +pat lil loc sru sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shrsil("lsr #1,") +pat lol loc rol stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("rol.l") +pat lol lol rol stl $1==$4 && inreg($2)==reg_any && $3==4 && inreg($1)==reg_any + call lolrshstl("rol.l") +pat lol loc ror stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("ror.l") +pat lol lol ror stl $1==$4 && inreg($2)==reg_any && $3==4 && inreg($1)==reg_any + call lolrshstl("ror.l") + +#ifdef m68020 +pat lol loc dvi stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen divs_l {const, $2}, {LOCAL, $1} + +pat lol loc dvu stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen divu_l {const, $2}, {LOCAL, $1} + +pat lol loc mli stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen muls_l {const, $2}, {LOCAL, $1} + +pat lol loc mlu stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen mulu_l {const, $2}, {LOCAL, $1} + +pat lol mli stl $1==$3 && $2==4 && inreg($1)==reg_any + with data4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen muls_l %1, {LOCAL, $1} + +pat lol mlu stl $1==$3 && $2==4 && inreg($1)==reg_any + with data4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen mulu_l %1, {LOCAL, $1} +#endif m68020 + + +pat lil inc sil $1==$3 && inreg($1)==reg_pointer + kills allexceptcon + gen add_l {const, 1}, {indirect4, regvar($1, reg_pointer)} + +pat lil dec sil $1==$3 && inreg($1)==reg_pointer + kills allexceptcon + gen sub_l {const, 1}, {indirect4, regvar($1, reg_pointer)} + +pat inl inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen add_l {const, 1}, {LOCAL, $1} + +pat del inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sub_l {const, 1}, {LOCAL, $1} + +pat zrl inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen clr_l {LOCAL, $1} + +pat zrl inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen move_l {const, 0}, {LOCAL, $1} + + +proc lolxxstl example lol and stl +with data4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen xxx* %1, {LOCAL, $1} + +proc lilxxsil example lil and sil +with conreg4 + kills allexceptcon + gen xxx* %1, {indirect4, regvar($1, reg_pointer)} + +proc lolcxxstl example lol loc and stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen xxx* {const, $2}, {LOCAL, $1} + +proc lilcxxsil example lil loc and sil + kills allexceptcon + gen xxx* {const, $2}, {indirect4, regvar($1, reg_pointer)} + +proc lolrxxstl example lol lol and stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen xxx* {LOCAL, $2}, {LOCAL, $1} + +proc lilrxxsil example lil lol and sil + kills allexceptcon + gen xxx* {LOCAL, $2}, {indirect4, regvar($1, reg_pointer)} + +pat lol adi stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("add.l") +pat lol loc adi stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("add.l") +pat lil adi sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("add.l") +pat lil loc adi sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("add.l") +pat lol lol adi stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("add.l") +pat lil lol adi sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("add.l") +pat lol adu stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("add.l") +pat lol loc adu stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("add.l") +pat lil adu sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("add.l") +pat lil loc adu sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("add.l") +pat lol lol adu stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("add.l") +pat lil lol adu sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("add.l") +pat lol loc sbi stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("sub.l") +pat lil loc sbi sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("sub.l") +pat lol lol sbi stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("sub.l") +pat lil lol sbi sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("sub.l") +pat lol loc sbu stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("sub.l") +pat lil loc sbu sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("sub.l") +pat lol lol sbu stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("sub.l") +pat lil lol sbu sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("sub.l") +pat lol and stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("and.l") +pat lol loc and stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("and.l") +pat lil and sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("and.l") +pat lil loc and sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("and.l") +pat lol lol and stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("and.l") +pat lil lol and sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("and.l") +pat lol ior stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("or.l") +pat lol loc ior stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("or.l") +pat lil ior sil $1==$3 && $2==4 && inreg($1)==reg_pointer + call lilxxsil("or.l") +pat lil loc ior sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("or.l") +pat lol lol ior stl $1==$4 && $3==4 && inreg($1)==reg_any && + inreg($2)==reg_any + call lolrxxstl("or.l") +pat lil lol ior sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("or.l") +pat lol xor stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("eor.l") +pat lol loc xor stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("eor.l") +pat lil xor sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("eor.l") +pat lil loc xor sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("eor.l") +pat lol lol xor stl $1==$4 && $3==4 && inreg($1)==reg_any && + inreg($2)==reg_any + call lolrxxstl("eor.l") +pat lil lol xor sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("eor.l") + +pat lil adp sil $1==$3 && inreg($1)==reg_pointer + kills allexceptcon + gen add_l {const, $2}, {indirect4, regvar($1, reg_pointer)} + +pat lil lil adp sil $1==$2 && $1==$4 && inreg($1)==reg_pointer + kills allexceptcon + uses AA_REG = {indirect4, regvar($1, reg_pointer)} + gen add_l {const, $3}, {indirect4, regvar($1, reg_pointer)} + yields %a + +pat lol lol adp stl loi $1==$2 && $1==$4 && $3==1 && $5==1 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc1, regvar($1, reg_pointer)} + +pat lol loi lol adp stl $1==$3 && $1==$5 && $2==1 && $4==1 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc1, regvar($1, reg_pointer)} + +pat lol lol adp stl loi $1==$2 && $1==$4 && $3==2 && $5==2 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc2, regvar($1, reg_pointer)} + +pat lol loi lol adp stl $1==$3 && $1==$5 && $2==2 && $4==2 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc2, regvar($1, reg_pointer)} + +pat lol lol adp stl loi $1==$2 && $1==$4 && $3==4 && $5==4 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc4, regvar($1, reg_pointer)} + +pat lil lol adp stl $1==$2 && $1==$4 && $3==4 && inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc4, regvar($1, reg_pointer)} + +pat lol lol adp stl sti $1==$2 && $1==$4 && $3==1 && $5==1 && + inreg($1)==reg_pointer +with data1 + kills allexceptcon + gen move %1, {post_inc1, regvar($1, reg_pointer)} + +pat lol sti lol adp stl $1==$3 && $1==$5 && $2==1 && $4==1 && + inreg($1)==reg_pointer +with data1 + kills allexceptcon + gen move %1, {post_inc1, regvar($1, reg_pointer)} + +pat lol lol adp stl sti $1==$2 && $1==$4 && $3==2 && $5==2 && + inreg($1)==reg_pointer +with any2 + kills allexceptcon + gen move %1, {post_inc2, regvar($1, reg_pointer)} + +pat lol sti lol adp stl $1==$3 && $1==$5 && $2==2 && $4==2 && + inreg($1)==reg_pointer +with any2 + kills allexceptcon + gen move %1, {post_inc2, regvar($1, reg_pointer)} + +pat lol lol adp stl sti $1==$2 && $1==$4 && $3==4 && $5==4 && + inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move_l %1, {post_inc4, regvar($1, reg_pointer)} + +pat sil lol adp stl $1==$2 && $1==$4 && $3==4 && inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move_l %1, {post_inc4, regvar($1, reg_pointer)} + +pat lol adp stl lol loi $1==$3 && $1==$4 && $2==0-1 && $5==1 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {pre_dec1, regvar($1, reg_pointer)} + +pat lol adp stl lol loi $1==$3 && $1==$4 && $2==0-2 && $5==2 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {pre_dec2, regvar($1, reg_pointer)} + +pat lol adp stl lil $1==$3 && $1==$4 && $2==0-4 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {pre_dec4, regvar($1, reg_pointer)} + +pat lol adp stl lol sti $1==$3 && $1==$4 && $2==0-1 && $5==1 && + inreg($1)==reg_pointer +with data1 + kills allexceptcon + gen move %1, {pre_dec1, regvar($1, reg_pointer)} + +pat lol adp stl lol sti $1==$3 && $1==$4 && $2==0-2 && $5==2 && + inreg($1)==reg_pointer +with any2 + kills allexceptcon + gen move %1, {pre_dec2, regvar($1, reg_pointer)} + +pat lol adp stl sil $1==$3 && $1==$4 && $2==0-4 && + inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move_l %1, {pre_dec4, regvar($1, reg_pointer)} + + + + +/************************************************ + * Group 1: load instructions * + ************************************************/ + +pat loc yields {const, $1} + +pat ldc leaving loc 18 trp + +pat lol yields {LOCAL, $1} + +pat ldl leaving lol $1+4 lol $1 + +pat loe yields {absolute4, $1} + +pat lil +#ifdef m68020 + yields {ILOCAL, $1} +#else m68020 + uses AA_REG = {LOCAL, $1} + yields {indirect4, %a} +#endif m68020 + + /* When using the 'offsetted' intructions regAregXcon cannot be used + * for the m68k4; there is no way of knowing about the size of + * %1.bd+$1, because expressions are not allowed in stack patterns, and + * this may lead to outputting too large displacements. With regAcon + * the chance that this will happen is very slim, because it can + * have displacements of 16 bits. Besides, leaving out regAcon here + * would make it very hard to handle this instruction efficiently. + */ +pat lof +with A_REG yields {offsetted4, %1, $1} +with exact local_addr yields {LOCAL, %1.bd+$1} +with exact ext_addr yields {absolute4, %1.bd+$1} +#ifndef m68020 +with regAcon yields {offsetted4, %1.reg, %1.bd+$1} +#else m68020 +with exact regAcon yields {offsetted4, %1.reg, %1.bd+$1} +with exact regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} +with exact offsetted4 yields {OFF_off4, %1.reg, %1.bd, $1} +with exact indirect yields {OFF_off4, %1.reg, 0, $1} +with exact LOCAL yields {OFF_off4, lb, %1.bd, $1} +with exact off_con yields {OFF_off4, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon yields {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 yields {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con yields {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 yields {ABS_off4, %1.bd, $1} +with exact abs_con yields {ABS_off4, %1.bd, %1.od+$1} +with exact abs_regXcon yields {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX yields {abs_index4, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat lal yields {local_addr, $1} + +pat lae yields {ext_addr, $1} + +pat lxl $1==0 yields lb + +pat lxl $1==1 yields {LOCAL, SL} + +pat lxl $1==2 +#ifdef m68020 + yields {OFF_off4, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + yields {offsetted4, %a, SL} +#endif m68020 + +pat lxl $1==3 +#ifdef m68020 + uses AA_REG = {OFF_off4, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + gen move {offsetted4, %a, SL}, %a +#endif m68020 + yields {offsetted4, %a, SL} + +pat lxl $1>3 + uses AA_REG = {LOCAL, SL}, + DD_REG = {const, $1-2} + gen 1: + move_l {offsetted4, %a, SL} ,%a + dbf %b, {slabel, 1b} + yields %a + +pat lxa $1==0 yields {local_addr, SL} + +pat lxa $1==1 +#ifdef m68020 + yields {off_con, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + yields {regAcon, %a, SL} +#endif m68020 + +pat lxa $1==2 +#ifdef m68020 + uses AA_REG = {OFF_off4, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + gen move {offsetted4, %a, SL}, %a +#endif m68020 + yields {regAcon, %a, SL} + +pat lxa $1>2 + uses AA_REG = {LOCAL, SL}, + DD_REG = {const, $1-1} + gen 1: + move_l {offsetted4, %a, SL} ,%a + dbf %b, {slabel, 1b} + yields {regAcon, %a, SL} + +pat loi $1==1 +with A_REG yields {indirect1, %1} +with exact local_addr yields {offsetted1, lb, %1.bd} +with exact ext_addr yields {absolute1, %1.bd} +#ifndef m68020 +with regAcon yields {offsetted1, %1.reg, %1.bd} +with regAregXcon yields {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon yields {offsetted1, %1.reg, %1.bd} +with exact regAregXcon yields {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 yields {OFF_off1, %1.reg, 0, 0} +with exact offsetted4 yields {OFF_off1, %1.reg, %1.bd, 0} +with exact LOCAL yields {OFF_off1, lb, %1.bd, 0} +with exact off_con yields {OFF_off1, %1.reg, %1.bd, %1.od} +with exact off_regXcon yields {OFF_indoff1, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 yields {INDOFF_off1, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con yields {INDOFF_off1, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 yields {ABS_off1, %1.bd, 0} +with exact abs_con yields {ABS_off1, %1.bd, %1.od} +with exact abs_regXcon yields {ABS_indoff1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 yields {ABSIND_off1, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con yields {ABSIND_off1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX yields {abs_index1, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat loi $1==2 +with A_REG yields {indirect2, %1} +with exact local_addr yields {offsetted2, lb, %1.bd} +with exact ext_addr yields {absolute2, %1.bd} +#ifndef m68020 +with regAcon yields {offsetted2, %1.reg, %1.bd} +with regAregXcon yields {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon yields {offsetted2, %1.reg, %1.bd} +with exact regAregXcon yields {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 yields {OFF_off2, %1.reg, 0, 0} +with exact offsetted4 yields {OFF_off2, %1.reg, %1.bd, 0} +with exact LOCAL yields {OFF_off2, lb, %1.bd, 0} +with exact off_con yields {OFF_off2, %1.reg, %1.bd, %1.od} +with exact off_regXcon yields {OFF_indoff2, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 yields {INDOFF_off2, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con yields {INDOFF_off2, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 yields {ABS_off2, %1.bd, 0} +with exact abs_con yields {ABS_off2, %1.bd, %1.od} +with exact abs_regXcon yields {ABS_indoff2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 yields {ABSIND_off2, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con yields {ABSIND_off2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX yields {abs_index2, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat loi $1==4 +with A_REG yields {indirect4, %1} +with exact local_addr yields {LOCAL, %1.bd} +with exact ext_addr yields {absolute4, %1.bd} +#ifndef m68020 +with regAcon yields {offsetted4, %1.reg, %1.bd} +with regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon yields {offsetted4, %1.reg, %1.bd} +with exact regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact LOCAL yields {ILOCAL, %1.bd} +with exact indirect4 yields {OFF_off4, %1.reg, 0, 0} +with exact offsetted4 yields {OFF_off4, %1.reg, %1.bd, 0} +with exact off_con yields {OFF_off4, %1.reg, %1.bd, %1.od} +with exact off_regXcon yields {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 yields {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con yields {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 yields {ABS_off4, %1.bd, 0} +with exact abs_con yields {ABS_off4, %1.bd, %1.od} +with exact abs_regXcon yields {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX yields {abs_index4, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat loi $1==8 +with A_REG yields {offsetted4, %1, 4} + {indirect4, %1} +pat loi $1>8 +with AA_REG STACK + uses DD_REG = {const, $1/4 -1} + gen add_l {const, $1}, %1 + 1: + move_l {pre_dec4, %1}, {pre_dec4, sp} + dbf %a, {slabel, 1b} + +pat los $1==4 +with STACK + gen jsr {absolute4, ".los"} + +pat lde yields {absolute4, $1+4} + {absolute4, $1} + +pat ldf +with A_REG yields {offsetted4, %1, $1+4} + {offsetted4, %1, $1} +with exact local_addr yields {LOCAL, %1.bd+$1+4} + {LOCAL, %1.bd+$1} +with exact ext_addr yields {absolute4, %1.bd+$1+4} + {absolute4, %1.bd+$1} +#ifndef m68020 +with regAcon yields {offsetted4, %1.reg, %1.bd+$1+4} + {offsetted4, %1.reg, %1.bd+$1} +#else m68020 +with exact regAcon yields {offsetted4, %1.reg, %1.bd+$1+4} + {offsetted4, %1.reg, %1.bd+$1} +with exact regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1+4} + {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} +with exact indirect4 yields {OFF_off4, %1.reg, 0, $1+4} + {OFF_off4, %1.reg, 0, $1} +with exact offsetted4 yields {OFF_off4, %1.reg, %1.bd, $1+4} + {OFF_off4, %1.reg, %1.bd, $1} +with exact LOCAL yields {OFF_off4, lb, %1.bd, $1+4} + {OFF_off4, lb, %1.bd, $1} +with exact off_con yields {OFF_off4, %1.reg, %1.bd, %1.od+$1+4} + {OFF_off4, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon yields {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} + {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 yields {INDOFF_off4, %1.reg, %1.xreg, %1.sc,%1.bd,$1+4} + {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con yields {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} + {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 yields {ABS_off4, %1.bd, $1+4} + {ABS_off4, %1.bd, $1} +with exact abs_con yields {ABS_off4, %1.bd, %1.od+$1+4} + {ABS_off4, %1.bd, %1.od+$1} +with exact abs_regXcon yields {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} + {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1+4} + {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} + {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX yields {abs_index4, %1.sc, %1.xreg, %1.bd+$1+4} + {abs_index4, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat lpi yields {ext_addr, $1} + + + +/************************************************ + * Group 2: store instructions * + ************************************************/ + +pat stl +with any4 + kills all_indir, LOCAL %bd==$1 + gen move %1, {LOCAL, $1} +with exact STACK + gen move {post_inc4,sp}, {LOCAL, $1} + +pat ste +with any4 + kills posextern + gen move %1, {absolute4, $1} +with exact STACK + gen move {post_inc4, sp}, {absolute4, $1} + +pat sil +#ifdef m68020 +with any4 + kills allexceptcon + gen move %1, {ILOCAL, $1} +with exact STACK + gen move {post_inc4, sp}, {ILOCAL, $1} +#else m68020 +with any4 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen move %1, {indirect4, %a} +with exact STACK + uses AA_REG = {LOCAL, $1} + gen move {post_inc4, sp}, {indirect4, %a} +#endif m68020 + +pat stf +with A_REG any4 + kills allexceptcon + gen move %2, {offsetted4, %1, $1} +with A_REG STACK + gen move {post_inc4, sp}, {offsetted4, %1, $1} +with exact local_addr any4 + kills allexceptcon + gen move %2, {LOCAL, %1.bd+$1} +with exact ext_addr any4 + kills allexceptcon + gen move %2, {absolute4, %1.bd+$1} +#ifndef m68020 +with regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} +#else m68020 +with exact regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} +with exact regAregXcon any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} +with exact indirect4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, 0, $1} +with exact offsetted4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, $1} +with exact LOCAL any4 + kills allexceptcon + gen move %2, {OFF_off4, lb, %1.bd, $1} +with exact off_con any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon any4 + kills allexceptcon + gen move %2, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, $1} +with exact abs_con any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, %1.od+$1} +with exact abs_regXcon any4 + kills allexceptcon + gen move %2, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX any4 + kills allexceptcon + gen move %2, {abs_index4, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat sti $1==1 +with A_REG data1 + kills allexceptcon + gen move %2, {indirect1, %1} +with exact local_addr data1 + kills allexceptcon + gen move %2, {offsetted1, lb, %1.bd} +with exact ext_addr data1 + kills allexceptcon + gen move %2, {absolute1, %1.bd} +#ifndef m68020 +with regAcon data1 + kills allexceptcon + gen move %2, {offsetted1, %1.reg, %1.bd} +with regAregXcon data1 + kills allexceptcon + gen move %2, {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon data1 + kills allexceptcon + gen move %2, {offsetted1, %1.reg, %1.bd} +with exact regAregXcon data1 + kills allexceptcon + gen move %2, {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 data1 + kills allexceptcon + gen move %2, {OFF_off1, %1.reg, 0, 0} +with exact offsetted4 data1 + kills allexceptcon + gen move %2, {OFF_off1, %1.reg, %1.bd, 0} +with exact LOCAL data1 + kills allexceptcon + gen move %2, {OFF_off1, lb, %1.bd, 0} +with exact off_con data1 + kills allexceptcon + gen move %2, {OFF_off1, %1.reg, %1.bd, %1.od} +with exact off_regXcon data1 + kills allexceptcon + gen move %2, {OFF_indoff1, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 data1 + kills allexceptcon + gen move %2, {INDOFF_off1, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con data1 + kills allexceptcon + gen move %2, {INDOFF_off1, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 data1 + kills allexceptcon + gen move %2, {ABS_off1, %1.bd, 0} +with exact abs_con data1 + kills allexceptcon + gen move %2, {ABS_off1, %1.bd, %1.od} +with exact abs_regXcon data1 + kills allexceptcon + gen move %2, {ABS_indoff1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 data1 + kills allexceptcon + gen move %2, {ABSIND_off1, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con data1 + kills allexceptcon + gen move %2, {ABSIND_off1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX data1 + kills allexceptcon + gen move %2, {abs_index1, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat sti $1==2 +with A_REG any2 + kills allexceptcon + gen move %2, {indirect2, %1} +with exact local_addr any2 + kills allexceptcon + gen move %2, {offsetted2, lb, %1.bd} +with exact ext_addr any2 + kills allexceptcon + gen move %2, {absolute2, %1.bd} +#ifndef m68020 +with regAcon any2 + kills allexceptcon + gen move %2, {offsetted2, %1.reg, %1.bd} +with regAregXcon any2 + kills allexceptcon + gen move %2, {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon any2 + kills allexceptcon + gen move %2, {offsetted2, %1.reg, %1.bd} +with exact regAregXcon any2 + kills allexceptcon + gen move %2, {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 any2 + kills allexceptcon + gen move %2, {OFF_off2, %1.reg, 0, 0} +with exact offsetted4 any2 + kills allexceptcon + gen move %2, {OFF_off2, %1.reg, %1.bd, 0} +with exact LOCAL any2 + kills allexceptcon + gen move %2, {OFF_off2, lb, %1.bd, 0} +with exact off_con any2 + kills allexceptcon + gen move %2, {OFF_off2, %1.reg, %1.bd, %1.od} +with exact index_off4 any2 + kills allexceptcon + gen move %2, {INDOFF_off2, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact off_regXcon any2 + kills allexceptcon + gen move %2, {OFF_indoff2, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact indoff_con any2 + kills allexceptcon + gen move %2, {INDOFF_off2, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 any2 + kills allexceptcon + gen move %2, {ABS_off2, %1.bd, 0} +with exact abs_con any2 + kills allexceptcon + gen move %2, {ABS_off2, %1.bd, %1.od} +with exact abs_regXcon any2 + kills allexceptcon + gen move %2, {ABS_indoff2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 any2 + kills allexceptcon + gen move %2, {ABSIND_off2, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con any2 + kills allexceptcon + gen move %2, {ABSIND_off2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX any2 + kills allexceptcon + gen move %2, {abs_index2, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat sti $1==4 +with A_REG any4 + kills allexceptcon + gen move %2, {indirect4, %1} +with A_REG STACK + gen move {post_inc4, sp}, {indirect4, %1} +with exact local_addr any4 + kills allexceptcon + gen move %2, {LOCAL, %1.bd} +with exact ext_addr any4 + kills allexceptcon + gen move %2, {absolute4, %1.bd} +#ifndef m68020 +with regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd} +with regAregXcon any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd} +with exact regAregXcon any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact LOCAL any4 + kills allexceptcon + gen move %2, {ILOCAL, %1.bd} +with exact indirect4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, 0, 0} +with exact offsetted4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, 0} +with exact off_con any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, %1.od} +with exact off_regXcon any4 + kills allexceptcon + gen move %2, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, 0} +with exact abs_con any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, %1.od} +with exact abs_regXcon any4 + kills allexceptcon + gen move %2, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX any4 + kills allexceptcon + gen move %2, {abs_index4, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat sti $1>4 +with AA_REG STACK + uses DD_REG = {const, $1/4 -1} + gen 1: + move_l {post_inc4, sp}, {post_inc4, %1} + dbf %a, {slabel, 1b} + +pat sts $1==4 +with STACK + gen jsr {absolute4, ".sts"} + +pat sdl +with any4 any4 + kills all_indir, LOCAL %bd==$1 + gen move %1, {LOCAL, $1} + move %2, {LOCAL, $1+4} + +pat sde +with any4 any4 + kills posextern + gen move %1, {absolute4, $1} + move %2, {absolute4, $1+4} + +pat sdf +with A_REG any4 any4 + kills allexceptcon + gen move %2, {offsetted4, %1, $1} + move %3, {offsetted4, %1, $1+4} +with exact local_addr any4 any4 + kills allexceptcon + gen move %2, {LOCAL, %1.bd+$1} + move %3, {LOCAL, %1.bd+$1+4} +with exact ext_addr any4 any4 + kills allexceptcon + gen move %2, {absolute4, %1.bd+$1} + move %3, {absolute4, %1.bd+$1+4} +#ifndef m68020 +with regAcon any4 any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} + move %3, {offsetted4, %1.reg, %1.bd+$1+4} +#else m68020 +with exact regAcon any4 any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} + move %3, {offsetted4, %1.reg, %1.bd+$1+4} +with exact regAregXcon any4 any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} + move %3, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1+4} +with exact indirect4 any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, 0, $1} + move %3, {OFF_off4, %1.reg, 0, $1+4} +with exact offsetted4 any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, $1} + move %3, {OFF_off4, %1.reg, %1.bd, $1+4} +with exact LOCAL any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, lb, %1.bd, $1} + move %3, {OFF_off4, lb, %1.bd, $1+4} +with exact off_con any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, %1.od+$1} + move %3, {OFF_off4, %1.reg, %1.bd, %1.od+$1+4} +with exact off_regXcon any4 any4 + kills allexceptcon + gen move %2, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} + move %3, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} +with exact index_off4 any4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} + move %3, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1+4} +with exact indoff_con any4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} + move %3, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} +with exact absolute4 any4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, $1} + move %3, {ABS_off4, %1.bd, $1+4} +with exact abs_con any4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, %1.od+$1} + move %3, {ABS_off4, %1.bd, %1.od+$1+4} +with exact abs_regXcon any4 any4 + kills allexceptcon + gen move %2, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} + move %3, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} +with exact abs_index4 any4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} + move %3, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1+4} +with exact absind_con any4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} + move %3, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} +with exact ext_regX any4 any4 + kills allexceptcon + gen move %2, {abs_index4, %1.sc, %1.xreg, %1.bd+$1} + move %3, {abs_index4, %1.sc, %1.xreg, %1.bd+$1+4} +#endif m68020 + + + +/************************************************ + * Group 3: integer arithmetic. * + ************************************************/ + + +pat adi $1==4 +with any4 DD_REG + gen add_l %1, %2 yields %2 +with DD_REG any4-DD_REG + gen add_l %2, %1 yields %1 +with DD_REG STACK + gen add_l {post_inc4, sp}, %1 + yields %1 + +pat sbi $1==4 +with any4 DD_REG + gen sub_l %1, %2 yields %2 +with DD_REG any4-DD_REG + gen sub_l %2, %1 + neg_l %1 yields %1 +with DD_REG STACK + gen sub_l {post_inc4, sp}, %1 + neg_l %1 yields %1 +with any4 AA_REG + gen sub_l %1, %2 yields %2 + +pat mli $1==4 +#ifdef m68020 +with data4 DD_REG + gen muls_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".mli"} + yields d1 +#endif m68020 + +pat dvi $1==4 +#ifdef m68020 +with data4 DD_REG + gen divs_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".dvi"} + yields d1 +#endif m68020 + +pat rmi $1==4 +#ifdef m68020 +with data4 DD_REG + uses DD_REG + gen divsl_l %1, {DREG_pair, %a, %2} + killreg %2 + /* !!!! contents of %2 have changed: make this known to cg */ + yields %a +#else m68020 +with STACK + gen jsr {absolute4, ".dvi"} + yields d0 +#endif m68020 + +pat ngi $1==4 +with DD_REG + gen neg_l %1 yields %1 + +pat sli $1==4 +with D_REG DD_REG + gen asl_l %1, %2 yields %2 + +pat sri $1==4 +with D_REG DD_REG + gen asr_l %1, %2 yields %2 + + + +/************************************************ + * Group 4: unsigned arithmetic. * + ************************************************/ + + +pat adu leaving adi $1 + +pat sbu leaving sbi $1 + +pat mlu $1==4 +#ifdef m68020 +with data4 DD_REG + gen mulu_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".mlu"} + yields d1 +#endif m68020 + +pat dvu $1==4 +#ifdef m68020 +with data4 DD_REG + gen divu_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".dvu"} + yields d1 +#endif m68020 + +pat rmu $1==4 +#ifdef m68020 +with data4 DD_REG + uses DD_REG + gen divul_l %1, {DREG_pair, %a, %2} + killreg %2 + /* !!!! contents of %2 have changed: make this known to cg */ + yields %a +#else m68020 +with STACK + gen jsr {absolute4, ".dvu"} + yields d0 +#endif m68020 + +pat slu leaving sli $1 + +pat sru $1==4 +with D_REG DD_REG + gen lsr_l %1, %2 yields %2 + + + +/************************************************ + * Group 5: floating point arithmetic * + * * + * is not available on 68000, 68010 or 68020 * + * so traps will be generated * + ************************************************/ + +pat adf leaving loc 18 trp +pat sbf leaving loc 18 trp +pat mlf leaving loc 18 trp +pat dvf leaving loc 18 trp +pat ngf leaving loc 18 trp +pat fif leaving loc 18 trp +pat fef leaving loc 18 trp + + + +/************************************************ + * Group 6: pointer arithmetic * + ************************************************/ + +pat adp $1==0 /* skip; array instructions might 'leave' this */ + +pat adp +with A_REG yields {t_regAcon, %1, $1} +with exact local_addr yields {local_addr, %1.bd+$1} +with exact ext_addr yields {ext_addr, %1.bd+$1} +with exact regAcon + t_regAcon + yields {t_regAcon, %1.reg, %1.bd+$1} +with exact regAregXcon + t_regAregXcon + yields {t_regAregXcon,%1.reg, %1.xreg, %1.sc, %1.bd+$1} +#ifdef m68020 +with exact indirect4 yields {off_con, %1.reg, 0, $1} +with exact LOCAL yields {off_con, lb, %1.bd, $1} +with exact offsetted4 yields {off_con, %1.reg, %1.bd, $1} +with exact off_con yields {off_con, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon yields {off_regXcon, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 yields {indoff_con, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con yields {indoff_con, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 yields {abs_con, %1.bd, $1} +with exact abs_con yields {abs_con, %1.bd, %1.od+$1} +with exact abs_regXcon yields {abs_regXcon, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 yields {absind_con, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con yields {absind_con, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX yields {ext_regX, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat ads $1==4 +with D_REG A_REG yields {regAregXcon, %2, %1, 1, 0} +with D_REG regAcon + t_regAcon + yields {t_regAregXcon, %2.reg, %1, 1, %2.bd} +with D_REG local_addr yields {t_regAregXcon, lb, %1, 1, %2.bd} +with any4-D_REG AA_REG + gen add_l %1, %2 yields %2 + +#ifdef m68020 + +with D_REG yields {regX, 1, %1} + leaving ads 4 +with regX A_REG yields {regAregXcon, %2, %1.xreg, %1.sc, 0} +with exact regX regAcon yields {regAregXcon, %2.reg, %1.xreg, %1.sc, %2.bd} +with exact regX local_addr + yields {regAregXcon, lb, %1.xreg, %1.sc, %2.bd} +with exact regX ext_addr + yields {ext_regX, %1.sc, %1.xreg, %2.bd} +with exact regX indirect4 + yields {off_regXcon, %2.reg, %1.xreg,%1.sc,0,0} +with exact regX offsetted4 + yields {off_regXcon, %2.reg, %1.xreg, %1.sc, %2.bd, 0} +with exact regX LOCAL yields {off_regXcon, lb, %1.xreg, %1.sc, %2.bd, 0} +with exact regX off_con yields {off_regXcon, %2.reg, %1.xreg,%1.sc,%2.bd,%2.od} +with exact regX absolute4 + yields {abs_regXcon, %1.sc, %1.xreg, %2.bd, 0} +with exact regX abs_con yields {abs_regXcon, %1.sc, %1.xreg, %2.bd, %2.od} +with exact indirect4 ext_addr + yields {off_con, %1.reg, 0, %2.bd} +with exact offsetted4 ext_addr + yields {off_con, %1.reg, %1.bd, %2.bd} +with exact LOCAL ext_addr + yields {off_con, lb, %1.bd, %2.bd} +with exact index_off4 ext_addr + yields {indoff_con, %1.reg, %1.xreg, %1.sc,%1.bd,%2.bd} +with exact absolute4 ext_addr + yields {abs_con, %1.bd, %2.bd} +with exact abs_index4 ext_addr + yields {absind_con, %1.sc, %1.xreg, %1.bd, %2.bd} +with exact indirect4 ext_regX + yields {off_regXcon, %1.reg, %2.xreg, %2.sc, 0, %2.bd} +with exact offsetted4 ext_regX + yields {off_regXcon, %1.reg, %2.xreg,%2.sc,%1.bd,%2.bd} +with exact LOCAL ext_regX + yields {off_regXcon, lb, %2.xreg, %2.sc, %1.bd, %2.bd} +with exact absolute4 ext_regX + yields {abs_regXcon, %2.sc, %2.xreg, %1.bd, %2.bd} +#endif m68020 + + /* I WOULD ALSO LIKE THIS: + * pat ads + * with const leaving adp %1.num + * BUT THAT DOESN'T WORK. + */ + +pat sbs $1==4 leaving sbi 4 + +#ifdef m68020 +pat loc sli ads $1==1 && $2==4 && $3==4 +with D_REG yields {regX, 2, %1} + leaving ads 4 + +pat loc sli ads $1==2 && $2==4 && $3==4 +with D_REG yields {regX, 4, %1} + leaving ads 4 + +pat loc sli ads $1==3 && $2==4 && $3==4 +with D_REG yields {regX, 8, %1} + leaving ads 4 +#endif m68020 + + +/************************************************ + * Group 7: increment / decrement / zero * + ************************************************/ + +pat inc +with exact STACK + gen add_l {const, 1}, {indirect4, sp} +with DD_REG+AA_REG + gen add_l {const, 1}, %1 + yields %1 + +pat inl + kills all_indir, LOCAL %bd==$1 + gen add_l {const, 1}, {LOCAL, $1} + +pat ine + kills posextern + gen add_l {const, 1}, {absolute4, $1} + +pat dec +with exact STACK + gen sub_l {const, 1}, {indirect4, sp} +with DD_REG+AA_REG + gen sub_l {const, 1}, %1 + yields %1 + +pat del + kills all_indir, LOCAL %bd==$1 + gen sub_l {const, 1}, {LOCAL, $1} + +pat dee + kills posextern + gen sub_l {const, 1}, {absolute4, $1} + +pat zrl + kills all_indir, LOCAL %bd==$1 + gen clr_l {LOCAL, $1} + +pat zre + kills posextern + gen clr_l {absolute4, $1} + +pat zer $1==4 yields {const, 0} +pat zer $1==8 yields {const, 0} {const, 0} +pat zer $1==12 yields {const, 0} {const, 0} {const, 0} + +pat zer +with STACK + uses DD_REG = {const, $1/4 -1} + gen 1: + clr_l {pre_dec4, sp} + dbf %a, {slabel, 1b} + + +pat zrf leaving loc 18 trp + + + +/************************************************ + * Group 8: convert instructions * + * for float conversions traps are generated * + ************************************************/ + + + +pat cii +with STACK + gen jsr {absolute4, ".cii"} + +pat cuu +with STACK + gen jsr {absolute4, ".cuu"} + +pat ciu leaving cuu + +pat cui leaving cuu + +pat cfi leaving loc 18 trp +pat cif leaving loc 18 trp +pat cfu leaving loc 18 trp +pat cuf leaving loc 18 trp +pat cff leaving loc 18 trp + + +/************************************************ + * Group 9: logical instructions * + ************************************************/ + + +proc log4 +with datalt4+const DD_REG + gen xxx* %1, %2 yields %2 +with DD_REG datalt4+const + gen xxx* %2, %1 yields %1 + +proc logdef example and +with STACK + uses DD_REG = {const, $1/4 -1}, + AA_REG = {regAcon, sp, $1}, + DD_REG + gen 1: + move_l {post_inc4, sp}, %c + xxx* %c, {post_inc4, %b} + dbf %a, {slabel, 1b} + +proc logndef +with DD_REG STACK + uses AA_REG = {regAregXcon, sp, %1, 1, 0}, + DD_REG + gen asr_l {shconst, 2}, %1 + sub_l {const, 1}, %1 + 1: + move_l {post_inc4, sp}, %b + xxx* %b, {post_inc4, %a} + dbf %1, {slabel, 1b} + +pat and $1==4 call log4("and.l") +pat and $1>4 call logdef("and.l") +pat and !defined($1) call logndef("and.l") +pat ior $1==4 call log4("or.l") +pat ior $1>4 call logdef("or.l") +pat ior !defined($1) call logndef("or.l") + +pat xor $1==4 +with conreg4 DD_REG + gen eor_l %1, %2 yields %2 +with DD_REG conreg4 + gen eor_l %2, %1 yields %1 + +pat xor $1>4 call logdef("eor.l") +pat xor !defined($1) call logndef("eor.l") + +pat com $1==4 +with DD_REG + gen not_l %1 yields %1 + +pat com $1==8 +with DD_REG DD_REG + gen not_l %1 + not_l %2 yields %2 %1 + +pat com $1>4 +with STACK + uses AA_REG, + DD_REG = {const, $1/4 -1} + gen move_l sp, %a + 1: + not_l {post_inc4, %a} + dbf %b, {slabel, 1b} + +pat com !defined($1) +with DD_REG STACK + uses AA_REG + gen move_l sp, %a + asr_l {shconst, 2}, %1 + sub_l {const, 1}, %1 + 1: + not_l {post_inc4, %a} + dbf %1, {slabel, 1b} + +pat rol $1==4 +with D_REG DD_REG + gen rol_l %1, %2 yields %2 + +pat ror $1==4 +with D_REG DD_REG + gen ror_l %1, %2 yields %2 + + + + +/************************************************ + * Group 10: sets * + ************************************************/ + + +pat inn $1==4 +with conreg2 DD_REG + gen btst %1, %2 + sne %2 + and_l {const, 1}, %2 + yields %2 + +pat inn defined($1) +with any4 STACK + gen move %1, d0 + move {const, $1}, d1 + jsr {absolute4, ".inn"} + yields d0 + +pat inn !defined($1) +with any4 any4 STACK + gen move %2, d0 + move %1, d1 + jsr {absolute4, ".inn"} + yields d0 + +pat loc inn $2==4 && small($1) +with DD_REG + gen asr_l {shconst, $1}, %1 + and_l {const, 1}, %1 + yields %1 + +pat set $1==4 +with conreg2 + uses DD_REG = {const, 0} + gen bset %1, %a yields %a + +pat set $1>4 +with any4 STACK + gen move %1, d0 + move {const, $1}, d1 + jsr {absolute4, ".set"} + +pat set !defined($1) +with any4 any4 STACK + gen move %2, d0 + move %1, d1 + jsr {absolute4, ".set"} + + + + +/************************************************ + * Group 11: arrays * + ************************************************/ + + +pat lar defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".lar"} + +pat lar !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".lar"} + +pat sar defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".sar"} + +pat sar !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".sar"} + +pat aar defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".aar"} + yields a0 + +pat aar !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".aar"} + yields a0 + +pat lae lar $2==4 && nicesize(rom($1,3)) + leaving lae $1 aar 4 loi rom($1, 3) +pat lae sar $2==4 && nicesize(rom($1,3)) + leaving lae $1 aar 4 sti rom($1, 3) + +pat lae aar $2==4 && rom($1,3)==1 + leaving ads 4 adp 0-rom($1,1) + +#ifdef m68020 +pat lae aar $2==4 && nicesize(rom($1,3)) +with D_REG yields {regX, rom($1,3), %1} + leaving ads 4 adp rom($1,3)*(0-rom($1,1)) +#else m68020 +pat lae aar $2==4 && rom($1,3)==2 +with DD_REG + gen asl_l {shconst, 1}, %1 + yields %1 + leaving ads 4 adp (0 - rom($1,1))<<1 + +pat lae aar $2==4 && rom($1,3)==4 +with DD_REG + gen asl_l {shconst, 2}, %1 + yields %1 + leaving ads 4 adp (0 - rom($1,1))<<2 + +pat lae aar $2==4 && rom($1,3)==8 +with DD_REG + gen asl_l {shconst, 3}, %1 + yields %1 + leaving ads 4 adp (0 - rom($1,1))<<3 +#endif m68020 + + /* I WOULD ALSO LIKE THESE: + * pat lae aar $2==4 && defined(rom($1,3)) + * with const leaving adp rom($1,3)*(%1.num-rom($1,1)) + * pat lae lar $2==4 && defined(rom($1,3)) + * with const leaving adp rom($1,3)*(%1.num-rom($1,1)) + * loi rom($1,3) + * pat lae sar $2==4 && defined(rom($1,3)) + * with const leaving adp rom($1,3)*(%1.num-rom($1,1)) + * sti rom($1,3) + * BUT THEY DON'T WORK. + */ + + + +/************************************************ + * Group 12: compare instructions * + ************************************************/ + + +pat cmi $1==4 leaving sbi 4 + +pat cmi defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".cmi"} + yields d0 + +pat cmi !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".cmi"} + yields d0 + +pat cmu $1==4 leaving sbi 4 + +pat cmu defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".cmu"} + yields d0 + +pat cmu !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".cmu"} + yields d0 + +pat cms $1==4 leaving sbi 4 + +pat cms defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".cms"} + yields d0 + +pat cms !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".cms"} + yields d0 + +pat cmp leaving cmu 4 + +proc txx +with test_set + uses DD_REG = {const, 1} + gen test %1 + bxx* {slabel, 1f} + clr_l %a + 1: + yields %a + +pat tlt call txx("blt") +pat tle call txx("ble") +pat teq call txx("beq") +pat tne call txx("bne") +pat tge call txx("bge") +pat tgt call txx("bgt") + +pat cmf leaving loc 18 trp + + + +/************************************************ + * Group 13: branch instructions * + ************************************************/ + +pat bra +with STACK + gen bra {llabel, $1} + +proc brxx example beq +with any4 genreg STACK + gen cmp_l %1, %2 + bxx[1] {llabel, $1} +with genreg any4 STACK + gen cmp_l %2, %1 + bxx[2] {llabel, $1} +with exact immediate4 imm_cmp4 + kills ALL + gen cmp_l %1, %2 + bxx[1] {llabel, $1} +with exact imm_cmp4 immediate4 + kills ALL + gen cmp_l %2, %1 + bxx[2] {llabel, $1} +with genreg STACK + gen cmp_l {post_inc4, sp}, %1 + bxx[2] {llabel, $1} +with exact immediate4 STACK + gen cmp_l %1, {post_inc4, sp} + bxx[1] {llabel, $1} +with any2-conreg2 genreg STACK + gen cmp_w %1, %2 + bxx[1] {llabel, $1} +with genreg any2-conreg2 STACK + gen cmp_w %2, %1 + bxx[2] {llabel, $1} +with exact const imm_cmp2 + kills ALL + gen cmp_w {const, loww(%1.num)}, %2 + bxx[1] {llabel, $1} +with exact imm_cmp2 const + kills ALL + gen cmp_w {const, loww(%2.num)}, %1 + bxx[2] {llabel, $1} +with data1-conreg1 D_REG STACK + gen cmp_b %1, %2 + bxx[1] {llabel, $1} +with D_REG data1-conreg1 STACK + gen cmp_b %2, %1 + bxx[2] {llabel, $1} +with exact const imm_cmp1 + kills ALL + gen cmp_b {const, lowb(%1.num)}, %2 + bxx[1] {llabel, $1} +with exact imm_cmp1 const + kills ALL + gen cmp_b {const, lowb(%2.num)}, %1 + bxx[2] {llabel, $1} + +pat blt call brxx("blt","bgt") +pat ble call brxx("ble","bge") +pat beq call brxx("beq","beq") +pat bne call brxx("bne","bne") +pat bge call brxx("bge","ble") +pat bgt call brxx("bgt","blt") + +proc zxx example zeq +with test_set STACK + gen test %1 + bxx* {llabel, $1} +with exact STACK + gen test {post_inc4, sp} + bxx* {llabel, $1} + +pat zlt call zxx("blt") +pat zle call zxx("ble") +pat zeq call zxx("beq") +pat zne call zxx("bne") +pat zge call zxx("bge") +pat zgt call zxx("bgt") + +/************************************************ + * Group 14: procedure calls instructions * + ************************************************/ + + +pat cai +with exact ext_addr + kills ALL + gen jsr {absolute4, %1.bd} +with A_REG STACK + gen jsr {indirect4, %1} +with STACK + uses AA_REG = {post_inc4, sp} + gen jsr {indirect4, %a} +#ifdef m68020 +with exact address + kills ALL + gen jsr %1 +#else m68020 +with address STACK + gen jsr %1 +#endif m68020 + +pat cal +with STACK + gen jsr {absolute4, $1} + +pat lfr $1==4 yields d0 +pat lfr $1==8 yields d1 d0 + +pat ret $1==0 +with STACK + gen return + +pat ret $1==4 +with any4 STACK + gen move %1, d0 + return +with STACK + gen move {post_inc4, sp}, d0 + return + +pat ret $1==8 +with any4 any4 STACK + gen move %1, d0 + move %2, d1 + return +with any4 STACK + gen move %1, d0 + move {post_inc4, sp}, d1 + return +with STACK + gen move {post_inc4, sp}, d0 + move {post_inc4, sp}, d1 + return + + +/************************************************ + * Group 15: miscellaneous instructions * + ************************************************/ + +pat asp small($1) +with STACK + gen add_l {const, $1}, sp +pat asp +with STACK + gen move {regAcon, sp, $1}, sp + +pat ass $1==4 +with any4 STACK + gen add_l %1, sp + +pat blm $1==4 +with A_REG A_REG + kills allexceptcon + gen move_l {indirect4, %2}, {indirect4, %1} + +pat blm $1==8 +with A_REG A_REG + kills allexceptcon + gen move_l {indirect4, %2}, {indirect4, %1} + move_l {offsetted4, %2, 4}, {offsetted4, %1, 4} + +pat blm $1>8 +with AA_REG AA_REG + kills allexceptcon + uses DD_REG={const, $1/4 -1} + gen 1: + move_l {post_inc4, %2}, {post_inc4, %1} + dbf %a, {slabel, 1b} + +pat bls $1==4 +with DD_REG AA_REG AA_REG + kills allexceptcon + gen asr_l {shconst, 2}, %1 + beq {slabel, 2f} + sub_l {const, 1}, %1 + 1: + move_l {post_inc4, %3}, {post_inc4, %2} + dbf %1, {slabel, 1b} + 2: + +pat csa $1==4 +with STACK + gen jmp {absolute4, ".csa"} + +pat csb $1==4 +with STACK + gen jmp {absolute4, ".csb"} + +pat dch leaving loi 4 + +pat dup $1==4 +with exact STACK + gen move_l {indirect4, sp}, {pre_dec4, sp} +with any4 yields %1 %1 + +pat dup $1==8 +with exact STACK + gen move_l {offsetted4, sp, 4}, {pre_dec4, sp} + move_l {offsetted4, sp, 4}, {pre_dec4, sp} +with any4 any4 yields %2 %1 %2 %1 + +pat dup $1>8 +with STACK + uses DD_REG = {const, $1/4 -1} + gen 1: + move_l {offsetted4, sp, $1 -4}, {pre_dec4, sp} + dbf %a, {slabel, 1b} + +pat dus $1==4 +with DD_REG STACK + uses AA_REG = {regAregXcon, sp, %1, 1, 0} + gen asr_l {shconst, 2}, %1 + beq {slabel, 2f} + sub_l {const, 1}, %1 + 1: + move_l {pre_dec4, %a}, {pre_dec4, sp} + dbf %1, {slabel, 1b} + 2: + +pat exg $1==4 +with any4 any4 yields %1 %2 + +pat exg defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".exg"} + +pat exg !defined($1) +with any4 STACK + gen move_l %1, d0 + jsr {absolute4, ".exg"} + +pat fil + gen move_l {ext_addr, $1}, {absolute4, ".filn"} + +pat gto +with STACK + uses AA_REG = {ext_addr, $1} + gen move_l {offsetted4, %a, 8}, lb + move_l {offsetted4, %a, 4}, sp +#ifdef m68020 + jmp {OFF_off4, %a, 0, 0} +#else m68020 + move_l {indirect4, %a}, %a + jmp {indirect4, %a} +#endif m68020 + +pat lim yields {absolute4, ".trpim"} + +pat lin + gen move {const, $1}, {absolute4, ".lino"} + +pat lni + gen add_l {const, 1}, {absolute4, ".lino"} + +pat lor $1==0 yields lb + +pat lor $1==1 +with STACK + uses AA_REG = sp yields %a + +pat lor $1==2 yields {absolute4, ".reghp"} + +pat lpb leaving adp 8 + +pat mon +with STACK + gen jsr {absolute4, ".mon"} + +pat nop +with STACK + gen jsr {absolute4, ".nop"} + +pat rck +#ifdef m68020 +with ext_addr D_REG + gen cmp2_l {absolute4, %1.bd}, %2 + bcc {slabel, 1f} + pea {absolute4, 1} /* push constant 1 == ERANGE */ + jsr {absolute4, ".trp"} + 1: yields %2 +with address-ext_addr D_REG + gen cmp2_l %1, %2 + bcc {slabel, 1f} + pea {absolute4, 1} /* push constant 1 == ERANGE */ + jsr {absolute4, ".trp"} + 1: yields %2 +with A_REG D_REG + gen cmp2_l {indirect4, %1}, %2 + bcc {slabel, 1f} + pea {absolute4, 1} /* push constant 1 == ERANGE */ + jsr {absolute4, ".trp"} + 1: yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".rck"} +#endif m68020 + +pat rtt leaving ret 0 + +pat sig +with any4 + uses AA_REG + gen move {absolute4, ".trppc"}, %a + move %1, {absolute4, ".trppc"} + yields %a + +pat sim +with any4 + gen move_l %1, {absolute4, ".trpim"} + +pat str $1==0 +with any4 +#ifdef m68020 + kills LOCAL, ILOCAL, all_regind %reg==lb, local_addr +#else m68020 + kills LOCAL, all_regind %reg==lb, local_addr +#endif m68020 + gen move %1, lb + +pat str $1==1 +with any4 STACK + gen move %1, sp + +pat str $1==2 +with STACK + gen jsr {absolute4, ".strhp"} + +pat trp +with STACK + gen jsr {absolute4, ".trp"} + + + +/************************************************ + * rules for long EM-patterns * + ************************************************/ + +proc lolxxxstl example lol adi stl +with conreg4 + kills all_indir, LOCAL %bd==$1 + gen xxx* %1, {LOCAL, $1} + +proc loexxxste example loe adi ste +with conreg4 + kills posextern + gen xxx* %1, {absolute4, $1} + +proc lilxxxsil example lil adi sil +with conreg4 +#ifdef m68020 + kills allexceptcon + gen xxx* %1, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen xxx* %1, {indirect4, %a} +#endif m68020 + +proc lolcxxxstl example lol loc adi stl + kills all_indir, LOCAL %bd==$1 + gen xxx* {const, $2}, {LOCAL, $1} + +proc loecxxxste example loe loc adi ste + kills posextern + gen xxx* {const, $2}, {absolute4, $1} + +proc lilcxxxsil example lil loc adi sil +#ifdef m68020 + kills allexceptcon + gen xxx* {const, $2}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen xxx* {const, $2}, {indirect4, %a} +#endif m68020 + +proc lolrxxxstl example lol lol adi stl + kills all_indir, LOCAL %bd==$1 + gen xxx* {LOCAL, $2}, {LOCAL, $1} + +proc loerxxxste example loe lol adi ste + kills posextern + gen xxx* {LOCAL, $2}, {absolute4, $1} + +proc lilrxxxsil example lil lol adi sil +#ifdef m68020 + kills allexceptcon + gen xxx* {LOCAL, $2}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen xxx* {LOCAL, $2}, {indirect4, %a} +#endif m68020 + +pat lol adi stl $1==$3 && $2==4 call lolxxxstl("add.l") +pat loe adi ste $1==$3 && $2==4 call loexxxste("add.l") +pat lil adi sil $1==$3 && $2==4 call lilxxxsil("add.l") +pat lol loc adi stl $1==$4 && $3==4 call lolcxxxstl("add.l") +pat loe loc adi ste $1==$4 && $3==4 call loecxxxste("add.l") +pat lil loc adi sil $1==$4 && $3==4 call lilcxxxsil("add.l") +pat lol lol adi stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("add.l") +pat loe lol adi ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("add.l") +pat lil lol adi sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("add.l") + +pat lol adu stl $1==$3 && $2==4 call lolxxxstl("add.l") +pat loe adu ste $1==$3 && $2==4 call loexxxste("add.l") +pat lil adu sil $1==$3 && $2==4 call lilxxxsil("add.l") +pat lol loc adu stl $1==$4 && $3==4 call lolcxxxstl("add.l") +pat loe loc adu ste $1==$4 && $3==4 call loecxxxste("add.l") +pat lil loc adu sil $1==$4 && $3==4 call lilcxxxsil("add.l") +pat lol lol adu stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("add.l") +pat loe lol adu ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("add.l") +pat lil lol adu sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("add.l") + + +pat lol adp stl $1==$3 + kills all_indir, LOCAL %bd==$1 + gen add_l {const, $2}, {LOCAL, $1} + +pat lil adp sil $1==$3 + kills allexceptcon +#ifdef m68020 + gen add_l {const, $2}, {ILOCAL, $1} +#else m68020 + uses AA_REG = {LOCAL, $1} + gen add_l {const, $2}, {indirect4, %a} +#endif m68020 + +pat loe adp ste $1==$3 + kills posextern + gen add_l {const, $2}, {absolute4, $1} + +pat lol lol adp stl $1==$2 && $1==$4 + kills all_indir, LOCAL %bd==$1 + uses AA_REG = {LOCAL, $1} + gen add_l {const, $3}, {LOCAL, $1} + yields %a + +pat lil lil adp sti $1==$2 && $1==$4 + kills allexceptcon +#ifdef m68020 + uses AA_REG = {ILOCAL, $1} + gen add_l {const, $3}, {ILOCAL, $1} +#else m68020 + uses AA_REG, AA_REG = {LOCAL, $1} + gen move {indirect4, %b}, %a + add_l {const, $3}, {indirect4, %b} +#endif m68020 + yields %a + +pat loe loe adp ste $1==$2 && $1==$4 + kills posextern + uses AA_REG = {absolute4, $1} + gen add_l {const, $3}, {absolute4, $1} + yields %a + + +pat lol loc sbi stl $1==$4 && $3==4 call lolcxxxstl("sub.l") +pat loe loc sbi ste $1==$4 && $3==4 call loecxxxste("sub.l") +pat lil loc sbi sil $1==$4 && $3==4 call lilcxxxsil("sub.l") +pat lol lol sbi stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("sub.l") +pat loe lol sbi ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("sub.l") +pat lil lol sbi sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("sub.l") + +pat lol loc sbu stl $1==$4 && $3==4 call lolcxxxstl("sub.l") +pat loe loc sbu ste $1==$4 && $3==4 call loecxxxste("sub.l") +pat lil loc sbu sil $1==$4 && $3==4 call lilcxxxsil("sub.l") +pat lol lol sbu stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("sub.l") +pat loe lol sbu ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("sub.l") +pat lil lol sbu sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("sub.l") + +pat lol and stl $1==$3 && $2==4 call lolxxxstl("and.l") +pat loe and ste $1==$3 && $2==4 call loexxxste("and.l") +pat lil and sil $1==$3 && $2==4 call lilxxxsil("and.l") +pat lol loc and stl $1==$4 && $3==4 call lolcxxxstl("and.l") +pat loe loc and ste $1==$4 && $3==4 call loecxxxste("and.l") +pat lil loc and sil $1==$4 && $3==4 call lilcxxxsil("and.l") +pat lol lol and stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("and.l") +pat loe lol and ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("and.l") +pat lil lol and sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("and.l") + +pat lol ior stl $1==$3 && $2==4 call lolxxxstl("or.l") +pat loe ior ste $1==$3 && $2==4 call loexxxste("or.l") +pat lil ior sil $1==$3 && $2==4 call lilxxxsil("or.l") +pat lol loc ior stl $1==$4 && $3==4 call lolcxxxstl("or.l") +pat loe loc ior ste $1==$4 && $3==4 call loecxxxste("or.l") +pat lil loc ior sil $1==$4 && $3==4 call lilcxxxsil("or.l") +pat lol lol ior stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("or.l") +pat loe lol ior ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("or.l") +pat lil lol ior sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("or.l") + +pat lol xor stl $1==$3 && $2==4 call lolxxxstl("eor.l") +pat loe xor ste $1==$3 && $2==4 call loexxxste("eor.l") +pat lil xor sil $1==$3 && $2==4 call lilxxxsil("eor.l") +pat lol loc xor stl $1==$4 && $3==4 call lolcxxxstl("eor.l") +pat loe loc xor ste $1==$4 && $3==4 call loecxxxste("eor.l") +pat lil loc xor sil $1==$4 && $3==4 call lilcxxxsil("eor.l") +pat lol lol xor stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("eor.l") +pat loe lol xor ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("eor.l") +pat lil lol xor sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("eor.l") + +proc llol1shstl example lol loc sli stl /* only left */ + kills all_indir, LOCAL %bd==$1 + gen shw* {offsetted2, lb, $1+2} + roxl {offsetted2, lb, $1} + +proc lloe1shste example loe loc sli ste /* only left */ + kills posextern + gen shw* {absolute2, $1+2} + roxl {absolute2, $1} + +proc llil1shsil example lil loc sli sil /* only left */ +#ifdef m68020 + kills allexceptcon + gen shw* {OFF_off2, lb, $1, 2} + roxl {OFF_off2, lb, $1, 0} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen shw* {offsetted2, %a, 2} + roxl {indirect2, %a} +#endif m68020 + +proc rlol1shstl example lol loc sri stl /* only right */ + kills all_indir, LOCAL %bd==$1 + gen shw* {offsetted2, lb, $1} + roxr {offsetted2, lb, $1+2} + +proc rloe1shste example loe loc sri ste /* only right */ + kills posextern + gen shw* {absolute2, $1} + roxr {absolute2, $1+2} + +proc rlil1shsil example lil loc sri sil /* only right */ +#ifdef m68020 + kills allexceptcon + gen shw* {OFF_off2, lb, $1, 0} + roxr {OFF_off2, lb, $1, 2} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen shw* {indirect2, %a} + roxr {offsetted2, %a, 2} +#endif m68020 + +pat lol loc sli stl $1==$4 && $2==1 && $3==4 call llol1shstl("asl #1,") +pat loe loc sli ste $1==$4 && $2==1 && $3==4 call lloe1shste("asl #1,") +pat lil loc sli sil $1==$4 && $2==1 && $3==4 call llil1shsil("asl #1,") +pat lol loc sri stl $1==$4 && $2==1 && $3==4 call rlol1shstl("asr #1,") +pat loe loc sri ste $1==$4 && $2==1 && $3==4 call rloe1shste("asr #1,") +pat lil loc sri sil $1==$4 && $2==1 && $3==4 call rlil1shsil("asr #1,") +pat lol loc slu stl $1==$4 && $2==1 && $3==4 call llol1shstl("asl #1,") +pat loe loc slu ste $1==$4 && $2==1 && $3==4 call lloe1shste("asl #1,") +pat lil loc slu sil $1==$4 && $2==1 && $3==4 call llil1shsil("asl #1,") +pat lol loc sru stl $1==$4 && $2==1 && $3==4 call rlol1shstl("lsr #1,") +pat loe loc sru ste $1==$4 && $2==1 && $3==4 call rloe1shste("lsr #1,") +pat lil loc sru sil $1==$4 && $2==1 && $3==4 call rlil1shsil("lsr #1,") + +proc locsh example loc sli +with DD_REG + gen sh* {shconst, $1}, %1 + yields %1 + +pat loc sli small($1) && $2==4 call locsh("asl.l") +pat loc sri small($1) && $2==4 call locsh("asr.l") +pat loc slu small($1) && $2==4 call locsh("asl.l") +pat loc sru small($1) && $2==4 call locsh("lsr.l") +pat loc rol small($1) && $2==4 call locsh("rol.l") +pat loc ror small($1) && $2==4 call locsh("ror.l") + +proc lolbitstl example lol ngi stl + kills all_indir, LOCAL %bd==$1 + gen bit* {LOCAL, $1} + +proc loebitste example loe ngi ste + kills posextern + gen bit* {absolute4, $1} + +proc lilbitsil example lil ngi sil +#ifdef m68020 + kills allexceptcon + gen bit* {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen bit* {indirect4, %a} +#endif m68020 + +pat lol ngi stl $1==$3 && $2==4 call lolbitstl("neg.l") +pat loe ngi ste $1==$3 && $2==4 call loebitste("neg.l") +pat lil ngi sil $1==$3 && $2==4 call lilbitsil("neg.l") +pat lol com stl $1==$3 && $2==4 call lolbitstl("not.l") +pat loe com ste $1==$3 && $2==4 call loebitste("not.l") +pat lil com sil $1==$3 && $2==4 call lilbitsil("not.l") + +pat lil inc sil $1==$3 +#ifdef m68020 + kills allexceptcon + gen add_l {const, 1}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen add_l {const, 1}, {indirect4, %a} +#endif m68020 + +pat lil dec sil $1==$3 +#ifdef m68020 + kills allexceptcon + gen sub_l {const, 1}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen sub_l {const, 1}, {indirect4, %a} +#endif m68020 + + +proc txxand +with test_set DD_REG + gen test %1 + bxx* {slabel, 1f} + clr_l %2 + 1: yields %2 + +proc txxior +with test_set DD_REG + gen test %1 + bxx* {slabel, 1f} + bset {const, 0}, %2 + 1: yields %2 + +pat tlt and $2==4 call txxand("blt") +pat tle and $2==4 call txxand("ble") +pat teq and $2==4 call txxand("beq") +pat tne and $2==4 call txxand("bne") +pat tge and $2==4 call txxand("bge") +pat tgt and $2==4 call txxand("bgt") + +pat tlt ior $2==4 call txxior("bge") +pat tle ior $2==4 call txxior("bgt") +pat teq ior $2==4 call txxior("bne") +pat tne ior $2==4 call txxior("beq") +pat tge ior $2==4 call txxior("blt") +pat tgt ior $2==4 call txxior("ble") + +proc cmxtxxand +with any4 genreg DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %3 + 1: yields %3 +with genreg any4-genreg DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %3 + 1: yields %3 +with exact immediate4 imm_cmp4 DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %3 + 1: yields %3 +with exact imm_cmp4 immediate4 DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %3 + 1: yields %3 + +proc cmxtxxior +with any4 genreg DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 +with genreg any4-genreg DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 +with exact immediate4 imm_cmp4 DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 +with exact imm_cmp4 immediate4 DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 + +proc cmxtxx +with any4 genreg + uses DD_REG = {const, 1} + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %a + 1: yields %a +with genreg any4-genreg + uses DD_REG = {const, 1} + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %a + 1: yields %a +with exact immediate4 imm_cmp4 + uses DD_REG = {const, 1} + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %a + 1: yields %a +with exact imm_cmp4 immediate4 + uses DD_REG = {const, 1} + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %a + 1: yields %a +with genreg STACK + uses DD_REG = {const, 1} + gen cmp_l {post_inc4, sp}, %1 + bxx[2] {slabel, 1f} + clr_l %a + 1: yields %a +with exact immediate4 STACK + uses DD_REG = {const, 1} + gen cmp_l %1, {post_inc4, sp} + bxx[1] {slabel, 1f} + clr_l %a + 1: yields %a + +pat cmi tlt and $1==4 && $3==4 call cmxtxxand("blt","bgt") +pat cmi tle and $1==4 && $3==4 call cmxtxxand("ble","bge") +pat cmi teq and $1==4 && $3==4 call cmxtxxand("beq","beq") +pat cmi tne and $1==4 && $3==4 call cmxtxxand("bne","bne") +pat cmi tge and $1==4 && $3==4 call cmxtxxand("bge","ble") +pat cmi tgt and $1==4 && $3==4 call cmxtxxand("bgt","blt") + +pat cmu tlt and $1==4 && $3==4 call cmxtxxand("bcs","bhi") +pat cmu tle and $1==4 && $3==4 call cmxtxxand("bls","bcc") +pat cmu teq and $1==4 && $3==4 call cmxtxxand("beq","beq") +pat cmu tne and $1==4 && $3==4 call cmxtxxand("bne","bne") +pat cmu tge and $1==4 && $3==4 call cmxtxxand("bcc","bls") +pat cmu tgt and $1==4 && $3==4 call cmxtxxand("bhi","bcs") + +pat cmi tlt ior $1==4 && $3==4 call cmxtxxior("bge","ble") +pat cmi tle ior $1==4 && $3==4 call cmxtxxior("bgt","blt") +pat cmi teq ior $1==4 && $3==4 call cmxtxxior("bne","bne") +pat cmi tne ior $1==4 && $3==4 call cmxtxxior("beq","beq") +pat cmi tge ior $1==4 && $3==4 call cmxtxxior("blt","bgt") +pat cmi tgt ior $1==4 && $3==4 call cmxtxxior("ble","bge") + +pat cmu tlt ior $1==4 && $3==4 call cmxtxxior("bcc","bls") +pat cmu tle ior $1==4 && $3==4 call cmxtxxior("bhi","bcs") +pat cmu teq ior $1==4 && $3==4 call cmxtxxior("bne","bne") +pat cmu tne ior $1==4 && $3==4 call cmxtxxior("beq","beq") +pat cmu tge ior $1==4 && $3==4 call cmxtxxior("bcs","bhi") +pat cmu tgt ior $1==4 && $3==4 call cmxtxxior("bls","bcc") + +pat cmi tlt $1==4 call cmxtxx("blt","bgt") +pat cmi tle $1==4 call cmxtxx("ble","bge") +pat cmi teq $1==4 call cmxtxx("beq","beq") +pat cmi tne $1==4 call cmxtxx("bne","bne") +pat cmi tge $1==4 call cmxtxx("bge","blt") +pat cmi tgt $1==4 call cmxtxx("bgt","blt") + +pat cmu tlt $1==4 call cmxtxx("bcs","bhi") +pat cmu tle $1==4 call cmxtxx("bls","bcc") +pat cmu teq $1==4 call cmxtxx("beq","beq") +pat cmu tne $1==4 call cmxtxx("bne","bne") +pat cmu tge $1==4 call cmxtxx("bcc","bls") +pat cmu tgt $1==4 call cmxtxx("bhi","bcs") + +proc cmxzxx example cmu zlt +with any4 genreg STACK + gen cmp_l %1, %2 + bxx[1] {llabel, $2} +with genreg any4-genreg STACK + gen cmp_l %2, %1 + bxx[2] {llabel, $2} +with exact immediate4 imm_cmp4 + kills ALL + gen cmp_l %1, %2 + bxx[1] {llabel, $2} +with exact imm_cmp4 immediate4 + kills ALL + gen cmp_l %2, %1 + bxx[2] {llabel, $2} +with genreg STACK + gen cmp_l {post_inc4, sp}, %1 + bxx[2] {llabel, $2} +with exact immediate4 STACK + gen cmp_l %1, {post_inc4, sp} + bxx[1] {llabel, $2} + +pat cmu zlt $1==4 call cmxzxx("bcs","bhi") +pat cmu zle $1==4 call cmxzxx("bls","bcc") +pat cmu zeq $1==4 call cmxzxx("beq","beq") +pat cmu zne $1==4 call cmxzxx("bne","bne") +pat cmu zge $1==4 call cmxzxx("bcc","bls") +pat cmu zgt $1==4 call cmxzxx("bhi","bcs") + + +proc bxx1_in example loc loc cii loc bne +with imm_cmp1 STACK + gen cmp_b {const, lowb($4)}, %1 + bxx* {llabel, $5} + +proc bxx2_in example loc loc cii loc bne +with imm_cmp2 STACK + gen cmp_w {const, loww($4)}, %1 + bxx* {llabel, $5} + +pat loc loc cii loc blt $1==1 && $2==4 && in_1($4) call bxx1_in("blt") +pat loc loc cii loc ble $1==1 && $2==4 && in_1($4) call bxx1_in("ble") +pat loc loc cii loc beq $1==1 && $2==4 && in_1($4) call bxx1_in("beq") +pat loc loc cii loc bne $1==1 && $2==4 && in_1($4) call bxx1_in("bne") +pat loc loc cii loc bge $1==1 && $2==4 && in_1($4) call bxx1_in("bge") +pat loc loc cii loc bgt $1==1 && $2==4 && in_1($4) call bxx1_in("bgt") + +pat loc loc cii loc blt $1==2 && $2==4 && in_2($4) call bxx2_in("blt") +pat loc loc cii loc ble $1==2 && $2==4 && in_2($4) call bxx2_in("ble") +pat loc loc cii loc beq $1==2 && $2==4 && in_2($4) call bxx2_in("beq") +pat loc loc cii loc bne $1==2 && $2==4 && in_2($4) call bxx2_in("bne") +pat loc loc cii loc bge $1==2 && $2==4 && in_2($4) call bxx2_in("bge") +pat loc loc cii loc bgt $1==2 && $2==4 && in_2($4) call bxx2_in("bgt") + +pat loc loc cii $1==1 && $2==2 +with DD_REG + gen ext_w %1 yields %1 + +pat loc loc cii $1==2 && $2==4 +with DD_REG + gen ext_l %1 yields %1 + +pat loc loc cii $1==1 && $2==4 +with DD_REG +#ifdef m68020 + gen extb_l %1 yields %1 +#else m68020 + gen ext_w %1 + ext_l %1 yields %1 +#endif m68020 + +pat loc loc ciu $1==$2 /* skip this */ +pat loc loc cui $1==$2 /* skip this */ + + +/* The following rules should be handled by the peephole optimizer, I think */ + +pat loc dvi $1==2 && $2==4 leaving loc 1 sri 4 +pat loc dvi $1==4 && $2==4 leaving loc 2 sri 4 +pat loc dvi $1==8 && $2==4 leaving loc 3 sri 4 +pat loc dvi $1==16 && $2==4 leaving loc 4 sri 4 +pat loc dvi $1==32 && $2==4 leaving loc 5 sri 4 +pat loc dvi $1==64 && $2==4 leaving loc 6 sri 4 +pat loc dvi $1==128 && $2==4 leaving loc 7 sri 4 +pat loc dvi $1==256 && $2==4 leaving loc 8 sri 4 + +pat loc dvu $1==2 && $2==4 leaving loc 1 sru 4 +pat loc dvu $1==4 && $2==4 leaving loc 2 sru 4 +pat loc dvu $1==8 && $2==4 leaving loc 3 sru 4 +pat loc dvu $1==16 && $2==4 leaving loc 4 sru 4 +pat loc dvu $1==32 && $2==4 leaving loc 5 sru 4 +pat loc dvu $1==64 && $2==4 leaving loc 6 sru 4 +pat loc dvu $1==128 && $2==4 leaving loc 7 sru 4 +pat loc dvu $1==256 && $2==4 leaving loc 8 sru 4 diff --git a/mach/moon3/ncg/mach.c b/mach/moon3/ncg/mach.c new file mode 100644 index 000000000..ec51f8bf1 --- /dev/null +++ b/mach/moon3/ncg/mach.c @@ -0,0 +1,236 @@ +/* + * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands. + * + * This product is part of the Amsterdam Compiler Kit. + * + * Permission to use, sell, duplicate or disclose this software must be + * obtained in writing. Requests for such permissions may be sent to + * + * Dr. Andrew S. Tanenbaum + * Wiskundig Seminarium + * Vrije Universiteit + * Postbox 7161 + * 1007 MC Amsterdam + * The Netherlands + * + */ + +/* + * machine dependent back end routines for the Motorola 68000, 68010 or 68020 + */ + +#ifndef m68k4 +#define m68020 +#endif + /* use m68020 when you want a m68020 cg, don't if you want a + * m68k4 cg. The m68k4 cg can be used for both the MC68000 + * and the MC68010. + */ + +con_part(sz,w) register sz; word w; { + + while (part_size % sz) + part_size++; + if (part_size == 4) + 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) + w <<= 16; + part_word |= w; + } else { + assert(sz == 4); + part_word = w; + } + part_size += sz; +} + +con_mult(sz) word sz; { + + if (sz != 4) + fatal("bad icon/ucon size"); + fprintf(codefile,".data4 %s\n",str); +} + +con_float() { + +static int been_here; + if (argval != 4 && argval != 8) + fatal("bad fcon size"); + fprintf(codefile,".data4\t"); + if (argval == 8) + fprintf(codefile,"F_DUM,"); + fprintf(codefile,"F_DUM\n"); + if ( !been_here++) + { + fprintf(stderr,"Warning : dummy float-constant(s)\n"); + } +} + +regscore(off,size,typ,score,totyp) + long off; +{ + if (score == 0) return -1; + switch(typ) { + case reg_float: + return -1; + case reg_pointer: + if (size != 4 || totyp != reg_pointer) return -1; + score *= 2; + break; + case reg_loop: + score += 5; + /* fall through .. */ + case reg_any: + if (size != 4 || totyp == reg_pointer) return -1; + break; + } + if (off >= 0) { + /* parameters must be initialised with an instruction + * like "move.l 4(a6),d0", which costs 2 words. + */ + score -= 2; + } + score -= 1; /* take save/restore into account */ + return score; +} +struct regsav_t { + char *rs_reg; /* e.g. "a3" or "d5" */ + long rs_off; /* offset of variable */ + int rs_size; /* 2 or 4 bytes */ +} regsav[9]; + + +int regnr; + +i_regsave() +{ + regnr = 0; +} + +#define MOVEM_LIMIT 2 +/* If #registers to be saved exceeds MOVEM_LIMIT, we +* use the movem instruction to save registers; else +* we simply use several move.l's. +*/ + +save() +{ + register struct regsav_t *p; + + if (regnr > MOVEM_LIMIT) { + fprintf(codefile,"movem.l "); + for (p = regsav; ;) { + fprintf(codefile,"%s",p->rs_reg); + if (++p == ®sav[regnr]) break; + putc('/',codefile); + } + fprintf(codefile,",-(sp)\n"); + } else { + for (p = regsav; p < ®sav[regnr]; p++) { + fprintf(codefile,"move.l %s,-(sp)\n",p->rs_reg); + } + } + /* initialise register-parameters */ + for (p = regsav; p < ®sav[regnr]; p++) { + if (p->rs_off >= 0) { +#ifdef m68020 + fprintf(codefile,"move.%c (%ld,a6),%s\n", +#else + fprintf(codefile,"move.%c %ld(a6),%s\n", +#endif + (p->rs_size == 4 ? 'l' : 'w'), + p->rs_off, + p->rs_reg); + } + } +} + +restr() +{ + register struct regsav_t *p; + + if (regnr > MOVEM_LIMIT) { + fprintf(codefile,"movem.l (sp)+,"); + for (p = regsav; ;) { + fprintf(codefile,"%s",p->rs_reg); + if (++p == ®sav[regnr]) break; + putc('/',codefile); + } + putc('\n',codefile); + } else { + for (p = ®sav[regnr-1]; p >= regsav; p--) { + fprintf(codefile,"move.l (sp)+,%s\n",p->rs_reg); + } + } + fprintf(codefile,"unlk a6\n"); + fprintf(codefile,"rts\n"); +} + + +f_regsave() +{ + save(); +} + +regsave(str,off,size) + char *str; + long off; +{ + assert (regnr < 9); + regsav[regnr].rs_reg = str; + regsav[regnr].rs_off = off; + regsav[regnr++].rs_size = size; + fprintf(codefile, "!Local %ld into %s\n",off,str); +} + +regreturn() +{ + restr(); +} + + +prolog(nlocals) full nlocals; { + +#ifdef m68020 + fprintf(codefile,"tst.b (-%ld,sp)\nlink\ta6,#-%ld\n",nlocals+40,nlocals); +#else + fprintf(codefile,"tst.b -%ld(sp)\nlink\ta6,#-%ld\n",nlocals+40,nlocals); +#endif +} + + + +mes(type) 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", /* SEGTXT */ + ".sect .data", /* SEGCON */ + ".sect .rom", /* SEGROM */ + ".sect .bss" /* SEGBSS */ +}; diff --git a/mach/moon3/ncg/mach.h b/mach/moon3/ncg/mach.h new file mode 100644 index 000000000..ff2cf66ca --- /dev/null +++ b/mach/moon3/ncg/mach.h @@ -0,0 +1,39 @@ +#ifndef m68k4 +#define m68020 +#endif + /* m68020 should be used for a m68020 cg, and it should + * not be used for a m68k4 cg + */ + +#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,"%s:.space\t%ld\n",l,x); + +#define pop_fmt "(sp)+" +#define cst_fmt "%ld" +#define off_fmt "%ld" +#define ilb_fmt "I%03x%x" +#define dlb_fmt "_%d" +#define hol_fmt "hol%d" + +#ifdef m68020 +#define loc_off "(%d,a6)" +#define arg_off "(8+%d,a6)" +#else +#define loc_off "%d(a6)" +#define arg_off "8+%d(a6)" +#endif +#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 modhead ".sect .text\n.sect .rom\n.sect .data\n.sect .bss\n" + +#define id_first '_' +#define BSS_INIT 0 diff --git a/mach/moon3/ncg/table b/mach/moon3/ncg/table new file mode 100644 index 000000000..6518487ad --- /dev/null +++ b/mach/moon3/ncg/table @@ -0,0 +1,3288 @@ + /******************************** + * * + * 68000, 68010 and 68020 * + * back end table * + * * + ********************************/ + + +#ifndef m68k4 +#define m68020 +#endif + /* m68020 to be defined if this is the 68020 table. + * The 68000 and 68010 tables are identical. + */ + + +#define small(x) ((x)>=1 && (x)<=8) +#define nicesize(x) ((x)==1||(x)==2||(x)==4||(x)==8) +#define lowb(x) (((x)<<24)>>24) +#define loww(x) (((x)<<16)>>16) +#define in_1(x) ((x)>=0-128 && (x)<128) +#define in_2(x) ((x)>=0-32768 && (x)<32768) + + +EM_WSIZE = 4 +EM_PSIZE = 4 +EM_BSIZE = 8 + +SL = 8 + +TIMEFACTOR = 1/2 + + +PROPERTIES + +D_REG /* data registers */ +A_REG /* address registers */ +DD_REG /* allocatable D_REG, may not be a register variable */ +AA_REG /* allocatable A_REG, may not be a register variable */ + + + +REGISTERS + +d0, d1, d2 :D_REG, DD_REG. +d3, d4, d5, d6, d7 :D_REG regvar. +a0, a1 :A_REG, AA_REG. +a2, a3, a4, a5 :A_REG regvar(reg_pointer). +lb ("a6"), sp :A_REG. /* localbase and stack pointer */ + + + + +TOKENS + + /* Not all addressing modes available on the MC68020 are used in this + * table. E.g (Dn), data register indirect is not used. Compared to + * (An), address register indirect, (Dn) requires two more bytes and + * several more clock cycles. Using (Dn) is even more expensive in + * time than first moving Dn to an address register An, and then using + * (An). For this kind of reasons several addressing modes are + * not used in this table. + * + * Cost in bytes may sometimes be incorrect. Several effective addresses + * use displacements that can occupy either 2 or 4 bytes. These are not + * considered different TOKENS in this table. + * + * Data registers are the only registers used as index registers in this + * table; address registers are only used to hold addresses. + * + * For the m68k4 table: the MC68000 and MC68010 have two modes that use + * displacements (offsets) of limited size: + * - offset(A_REG, Index_reg), where offset is only 8 bits, and + * - offset(A_REG), where offset can only be 16 bits. + * To make sure that no output is given with offsets too large, two + * extra tokens are declared: t_regAregXcon and t_regAcon. These are + * used as addresses to these modes. Whenever the displacements become + * too large, they are transformed into different tokens. + * + * Sometimes some TOKENS are used with displacements (offsets) of 0. + * It would have been possible to provide separate TOKENS for these, in + * case the assembler doesn't handle zero offsets optimally. This + * however would mean a very large amount of extra TOKENS and SETS for + * a very small profit in code bytes, so we won't do that. + * + * To prevent the TOKENS list from getting too unreadable, #ifdefs are + * used to form three parts: + * (i) the common part; + * (ii) the m68k4 part; + * (iii) the m68020 part; + */ + + /* Part (i) */ +const = {INT num;} 4 cost(4,4) "#" num . +indirect4 = {A_REG reg;} 4 cost(0,4) "(" reg ")" . +post_inc4 = {A_REG reg;} 4 cost(0,4) "(" reg ")+" . +pre_dec4 = {A_REG reg;} 4 cost(0,5) "-(" reg ")" . +indirect2 = {A_REG reg;} 4 cost(0,4) "(" reg ")" . +post_inc2 = {A_REG reg;} 4 cost(0,4) "(" reg ")+" . +pre_dec2 = {A_REG reg;} 4 cost(0,5) "-(" reg ")" . +indirect1 = {A_REG reg;} 4 cost(0,4) "(" reg ")" . +post_inc1 = {A_REG reg;} 4 cost(0,4) "(" reg ")+" . +pre_dec1 = {A_REG reg;} 4 cost(0,5) "-(" reg ")" . + +ext_addr = {ADDR bd;} 4 cost(4,5) "#" bd . +llabel = {ADDR bd;} 4 cost(2,0) bd . +slabel = {ADDR bd;} 4 cost(0,0) bd . +shconst = {INT num;} 4 cost(0,0) "#" num . + +#ifndef m68020 + /* Part (ii) */ +absolute4 = {ADDR bd;} 4 cost(4,8) bd . +offsetted4 = {A_REG reg; INT bd;} 4 cost(2,6) bd "(" reg ")" . +index_off4 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,7) + bd "(" reg "," xreg ".l)" . +absolute2 = {ADDR bd;} 4 cost(4,6) bd . +offsetted2 = {A_REG reg; INT bd;} 4 cost(2,4) bd "(" reg ")" . +index_off2 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,5) + bd "(" reg "," xreg ".l)" . +absolute1 = {ADDR bd;} 4 cost(4,6) bd . +offsetted1 = {A_REG reg; INT bd;} 4 cost(2,4) bd "(" reg ")" . +index_off1 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,5) + bd "(" reg "," xreg ".l)" . + +LOCAL = {INT bd;} 4 cost(2,6) bd "(a6)" . + +local_addr = {INT bd;} 4 cost(2,6) bd "(a6)" . +regAcon = {A_REG reg; INT bd;} 4 cost(2,6) bd "(" reg ")" . +regAregXcon = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,8) + bd "(" reg "," xreg ".l)" . + /* note: in the m68k4 version %sc always equals 1 */ + +t_regAregXcon = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,8) . +t_regAcon = {A_REG reg; INT bd;} 4 cost(2,6) . + +#else m68020 + /* Part (iii) */ +absolute4 = {ADDR bd;} 4 cost(4,7) "(" bd ")" . +offsetted4 = {A_REG reg; INT bd;} 4 cost(2,6) "(" bd "," reg ")" . +index_off4 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(4,9) + "(" bd "," reg "," xreg ".l*" sc ")" . +abs_index4 = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,9) + "(" bd "," xreg ".l*" sc ")" . +OFF_off4 = {A_REG reg; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," od ")" . +OFF_indoff4 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +INDOFF_off4 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +ABS_off4 = {ADDR bd; ADDR od;} 4 cost(8,22) "([" bd "]," od ")" . +ABS_indoff4 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "]," xreg ".l*" sc "," od ")" . +ABSIND_off4 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "," xreg ".l*" sc "]," od ")" . + +absolute2 = {ADDR bd;} 4 cost(4,7) "(" bd ")" . +offsetted2 = {A_REG reg; INT bd;} 4 cost(2,6) "(" bd "," reg ")" . +index_off2 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(4,9) + "(" bd "," reg "," xreg ".l*" sc ")" . +abs_index2 = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,9) + "(" bd "," xreg ".l*" sc ")" . +OFF_off2 = {A_REG reg; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," od ")" . +OFF_indoff2 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +INDOFF_off2 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +ABS_off2 = {ADDR bd; ADDR od;} 4 cost(8,22) "([" bd "]," od ")" . +ABS_indoff2 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "]," xreg ".l*" sc "," od ")" . +ABSIND_off2 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "," xreg ".l*" sc "]," od ")" . + +absolute1 = {ADDR bd;} 4 cost(4,7) "(" bd ")" . +offsetted1 = {A_REG reg; INT bd;} 4 cost(2,6) "(" bd "," reg ")" . +index_off1 = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(4,9) + "(" bd "," reg "," xreg ".l*" sc ")" . +abs_index1 = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,9) + "(" bd "," xreg ".l*" sc ")" . +OFF_off1 = {A_REG reg; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," od ")" . +OFF_indoff1 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +INDOFF_off1 = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,19) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +ABS_off1 = {ADDR bd; ADDR od;} 4 cost(8,22) "([" bd "]," od ")" . +ABS_indoff1 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "]," xreg ".l*" sc "," od ")" . +ABSIND_off1 = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,22) + "([" bd "," xreg ".l*" sc "]," od ")" . + +LOCAL = {INT bd;} 4 cost(2,6) "(" bd ",a6)" . +ILOCAL = {INT bd;} 4 cost(4,16) "([" bd ",a6])" . + +local_addr = {INT bd;} 4 cost(2,3) "(" bd ",a6)" . +regAcon = {A_REG reg; INT bd;} 4 cost(2,3) "(" bd "," reg ")" . +regAregXcon = {A_REG reg; D_REG xreg; INT sc; INT bd;} 4 cost(2,7) + "(" bd "," reg "," xreg ".l*" sc ")" . +off_con = {A_REG reg; INT bd; ADDR od;} 4 cost(6,18) + "([" bd "," reg "]," od ")". +off_regXcon = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,18) + "([" bd "," reg "]," xreg ".l*" sc "," od ")" . +indoff_con = {A_REG reg; D_REG xreg; INT sc; INT bd; ADDR od;} 4 cost(6,18) + "([" bd "," reg "," xreg ".l*" sc "]," od ")" . +abs_con = {ADDR bd; ADDR od;} 4 cost(8,21) "([" bd "]," od ")" . +abs_regXcon = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,21) + "([" bd "]," xreg ".l*" sc "," od ")" . +absind_con = {INT sc; D_REG xreg; ADDR bd; ADDR od;} 4 cost(8,21) + "([" bd "," xreg ".l*" sc "]," od ")" . +ext_regX = {INT sc; D_REG xreg; ADDR bd;} 4 cost(6,15) + "(" bd "," xreg ".l*" sc ")" . + +regX = {INT sc; D_REG xreg;} 4 cost(2,7) "(" xreg ".l*" sc ")" . +DREG_pair = {D_REG reg1; D_REG reg2;} 8 cost(2,0) reg1 ":" reg2 . + +#define t_regAregXcon regAregXcon +#define t_regAcon regAcon + +#endif m68020 + +SETS + + /* The SETS list cannot be kept as 'readable' as the TOKENS list + * because cgg is one pass. + */ + +#ifndef m68020 + /* A m68k4 part */ +data4 = D_REG + LOCAL + const + post_inc4 + pre_dec4 + + indirect4 + offsetted4 + index_off4 + absolute4 + + ext_addr . +memory4 = data4 - D_REG . +control4 = indirect4 + offsetted4 + index_off4 + absolute4 + + LOCAL . +alterable4 = data4 + A_REG - const - ext_addr . +any4 = data4 + A_REG . /* all four above together */ + +data2 = D_REG + post_inc2 + pre_dec2 + indirect2 + + offsetted2 + index_off2 + absolute2 + const . +memory2 = data2 - D_REG . +control2 = indirect2 + offsetted2 + index_off2 + absolute2 . +alterable2 = data2 + A_REG - const . +any2 = data2 + A_REG . + +data1 = D_REG + post_inc1 + pre_dec1 + indirect1 + + offsetted1 + index_off1 + absolute1 + const . +memory1 = data1 - D_REG . +control1 = indirect1 + offsetted1 + index_off1 + absolute1 . +alterable1 = data1 - const . +any1 = data1 . + +#else m68020 + +data4 = D_REG + indirect4 + post_inc4 + pre_dec4 + index_off4 + + offsetted4 + OFF_off4 + OFF_indoff4 + + INDOFF_off4 + + ABS_off4 + ABS_indoff4 + ABSIND_off4 + + absolute4 + abs_index4 + const + ext_addr + + LOCAL + ILOCAL . +memory4 = data4 - D_REG . +control4 = memory4 - (post_inc4 + pre_dec4 + const + ext_addr) . +alterable4 = data4 + A_REG - const - ext_addr . +any4 = data4 + A_REG . /* all four above together */ + +data2 = D_REG + indirect2 + post_inc2 + pre_dec2 + index_off2 + + offsetted2 + OFF_off2 + OFF_indoff2 + + INDOFF_off2 + + ABS_off2 + ABS_indoff2 + ABSIND_off2 + + absolute2 + abs_index2 + const . +memory2 = data2 - D_REG . +control2 = memory2 - (post_inc2 + pre_dec2 + const) . +alterable2 = data2 + A_REG - const . +any2 = data2 + A_REG . /* all four above together */ + +data1 = D_REG + indirect1 + post_inc1 + pre_dec1 + index_off1 + + offsetted1 + OFF_off1 + OFF_indoff1 + + INDOFF_off1 + + ABS_off1 + ABS_indoff1 + ABSIND_off1 + + absolute1 + abs_index1 + const . +memory1 = data1 - D_REG . +control1 = memory1 - (post_inc1 + pre_dec1 + const) . +alterable1 = data1 - const . +any1 = data1 . /* all four above together */ + +#endif m68020 + /* This is a common part */ +any = any4 + any2 + any1 . +absolute = absolute4 + absolute2 + absolute1 . +control = control4 + control2 + control1 . +indirect = indirect4 + indirect2 + indirect1 . +pre_post = pre_dec4 + pre_dec2 + pre_dec1 + + post_inc4 + post_inc2 + post_inc1 . +offsetted = offsetted4 + offsetted2 + offsetted1 . +index_off = index_off4 + index_off2 + index_off1 . + +#ifndef m68020 + /* A m68k4 part */ +regind_addr = regAcon + regAregXcon + t_regAcon + t_regAregXcon . +address = ext_addr + local_addr + regAcon + regAregXcon . +all_regind = indirect + offsetted + pre_post + index_off + + regind_addr . +all_indir = all_regind . +allexceptcon = ALL - ( D_REG + A_REG + const + + local_addr + ext_addr + regAcon + regAregXcon + + t_regAcon + t_regAregXcon ) . +use_index = index_off4 + index_off2 + index_off1 . + +#else m68020 + +reg_memind4 = OFF_off4 + OFF_indoff4 + INDOFF_off4 . +memind4 = reg_memind4 + + ABS_off4 + ABS_indoff4 . +reg_memind2 = OFF_off2 + OFF_indoff2 + INDOFF_off2 . +memind2 = reg_memind2 + + ABS_off2 + ABS_indoff2 . +reg_memind1 = OFF_off1 + OFF_indoff1 + INDOFF_off1 . +memind1 = reg_memind1 + + ABS_off1 + ABS_indoff1 . +reg_memind = reg_memind4 + reg_memind2 + reg_memind1 . +memind = memind4 + memind2 + memind1 . +regind_addr = regAcon + regAregXcon + + off_con + off_regXcon + + indoff_con . +address = regind_addr + + ext_addr + local_addr + + abs_con + abs_regXcon + + absind_con + + ext_regX . +all_regind = indirect + offsetted + index_off + pre_post + + reg_memind + regind_addr . +all_indir = all_regind + memind + ILOCAL . +allexceptcon = ALL - ( D_REG + A_REG + const + + local_addr + ext_addr + regAcon + regAregXcon + ext_regX ) . +use_index4 = index_off4 + abs_index4 + + OFF_indoff4 + INDOFF_off4 + + ABS_indoff4 + ABSIND_off4 . +use_index2 = index_off2 + abs_index2 + + OFF_indoff2 + INDOFF_off2 + + ABS_indoff2 + ABSIND_off2 . +use_index1 = index_off1 + abs_index1 + + OFF_indoff1 + INDOFF_off1 + + ABS_indoff1 + ABSIND_off1 . +use_indaddr = regAregXcon + + off_regXcon + indoff_con + + abs_regXcon + absind_con + + ext_regX . + +use_index = use_index4 + use_index2 + use_index1 + use_indaddr + regX . + +#endif m68020 + /* A common part */ +posextern = absolute + all_indir . + +genreg = D_REG + A_REG. +label = llabel + slabel . +immediate4 = const + ext_addr . +conreg4 = D_REG + immediate4 . +conreg2 = D_REG + const . +conreg1 = D_REG + const . +shconreg = D_REG + shconst . +datalt4 = data4 * alterable4 . +datalt2 = data2 * alterable2 . +datalt1 = data1 * alterable1 . +datalt = datalt4 + datalt2 + datalt1 . +memalt4 = memory4 * alterable4 . +memalt2 = memory2 * alterable2 . +memalt1 = memory1 * alterable1 . + +#ifndef m68020 + /* A m68k4 part */ +imm_cmp4 = alterable4 . +imm_cmp2 = alterable2 . +imm_cmp1 = datalt1 . + +test_set4 = datalt4 . +test_set2 = datalt2 . +test_set1 = datalt1 . + +#else m68020 + +imm_cmp4 = any4 - immediate4 . +imm_cmp2 = any2 - const . +imm_cmp1 = data1 - const . + +test_set4 = data4 - immediate4 . +test_set2 = data2 - const . +test_set1 = data1 - const . + +#endif m68020 + +test_set = test_set4 + test_set2 + test_set1 . + +#ifndef m68020 +t_address = address + t_regAregXcon + t_regAcon . +#else m68020 +#define t_address address +#endif m68020 + + +INSTRUCTIONS + + /* Since the 68000 , the 68010 and the 68020 instruction sets are rather + * extensive, especially because e.g. 'add.l' and 'add.w' are + * considered different instructions, only those instructions are + * listed here that are used in the rest of this table. + * + * Instruction timing cost cannot be accurately given, nor the timing + * cost for getting operands. Detailed information about this can be + * found in the "MC68020 User's Manual", section 9, about instruction + * timing. The cost used in this table are 'worst case' cost, as + * mentioned in section 9 of the user's manual. + * + * The first few instructions had to be added because register + * variables are used. The LOCALs below are register variables. + * One may not conclude that these operations are also allowed + * on LOCALs that are not register variables. + * The cost have been adapted, but are not accurate; when 'real' + * LOCALs are used the cost are very inaccurate. + */ + +add_l "add.l" any4:ro, LOCAL:rw:cc cost(0,0). +lea address:ro, LOCAL:wo cost(0,0). +sub_l "sub.l" any4:ro, LOCAL:rw:cc cost(0,0). +sh "illegal" shconreg:ro, LOCAL:rw:cc cost(0,0). +sh "illegal" LOCAL:ro, LOCAL:rw:cc cost(0,0). +xxx "illegal" data4:ro, LOCAL:rw:cc cost(0,0). +xxx "illegal" LOCAL:ro, alterable4:rw:cc cost(0,0). +#ifdef m68020 +divs_l "divs.l" data4:ro, LOCAL:rw:cc cost(0,90). +divu_l "divu.l" data4:ro, LOCAL:rw:cc cost(0,78). +muls_l "muls.l" data4:ro, LOCAL:rw:cc cost(0,44). +mulu_l "mulu.l" data4:ro, LOCAL:rw:cc cost(0,44). +#endif m68020 + +add_l "add.l" any4:ro, D_REG:rw:cc cost(2,3). +add_l "add.l" any4:ro, A_REG:rw cost(2,3). +add_l "add.l" conreg4:ro, alterable4:rw:cc cost(2,6). +and_l "and.l" data4:ro, D_REG:rw:cc cost(2,3). +and_l "and.l" D_REG:ro, memalt4:rw:cc cost(2,6). +and_l "and.l" const:ro, datalt4:rw:cc cost(2,6). +asl_l "asl.l" shconreg:ro, D_REG:rw:cc cost(2,5). +asl "asl #1," memalt2:rw:cc cost(2,4). +asr_l "asr.l" shconreg:ro, D_REG:rw:cc cost(2,4). +asr "asr #1," memalt2:rw:cc cost(2,4). +bra label cost(2,5). +bcc label cost(2,5). +bcs label cost(2,5). +beq label cost(2,5). +bge label cost(2,5). +bgt label cost(2,5). +bhi label cost(2,5). +ble label cost(2,5). +bls label cost(2,5). +blt label cost(2,5). +bmi label cost(2,5). +bne label cost(2,5). +bpl label cost(2,5). +bvc label cost(2,5). +bvs label cost(2,5). +bset conreg2:ro, D_REG:rw kills :cc cost(2,4). +btst conreg2:ro, data1:rw kills :cc cost(2,3). +clr_l "clr.l" D_REG:wo:cc cost(2,3). +clr_l "clr.l" memalt4:wo:cc cost(2,6). +clr_w "clr.w" D_REG:wo:cc cost(2,2). +clr_w "clr.w" memalt2:wo:cc cost(2,4). +clr_b "clr.b" D_REG:wo:cc cost(2,2). +clr_b "clr.b" memalt1:wo:cc cost(2,4). +cmp_l "cmp.l" any4:ro, genreg:ro kills :cc cost(2,3). +cmp_l "cmp.l" post_inc4:ro, post_inc4:ro kills :cc cost(2,2). +cmp_l "cmp.l" immediate4:ro, imm_cmp4:ro kills :cc cost(2,2). +cmp_w "cmp.w" any2:ro, genreg:ro kills :cc cost(2,3). +cmp_w "cmp.w" post_inc2:ro, post_inc2:ro kills :cc cost(2,2). +cmp_w "cmp.w" const:ro, imm_cmp2:ro kills :cc cost(2,2). +cmp_b "cmp.b" data1:ro, D_REG:ro kills :cc cost(2,3). +cmp_b "cmp.b" post_inc1:ro, post_inc1:ro kills :cc cost(2,2). +cmp_b "cmp.b" const:ro, imm_cmp1:ro kills :cc cost(2,2). +dbf D_REG:rw, label cost(2,5). +eor_l "eor.l" conreg4:ro, datalt4:rw:cc cost(2,6). +ext_l "ext.l" D_REG:rw:cc cost(2,2). +ext_w "ext.w" D_REG:rw:cc cost(2,2). +jmp address+control4 cost(2,0). +jsr address+control4 kills :cc cost(2,3). +lea address+control4:ro, A_REG:wo cost(2,0). +lsl_l "lsl.l" shconreg:ro, D_REG:rw:cc cost(2,4). +lsl "lsl #1," memalt2:rw:cc cost(2,4). +lsr_l "lsr.l" shconreg:ro, D_REG:rw:cc cost(2,4). +lsr "lsr #1," memalt2:rw:cc cost(2,4). +move_l "move.l" any4:ro, alterable4:wo:cc cost(2,2). +move_w "move.w" any2:ro, alterable2:wo:cc cost(2,2). +move_b "move.b" data1:ro, alterable1:wo:cc cost(2,2). +neg_l "neg.l" D_REG:rw:cc cost(2,3). +neg_l "neg.l" memory4:rw:cc cost(2,6). +not_l "not.l" D_REG:rw:cc cost(2,3). +not_l "not.l" memory4:rw:cc cost(2,6). +or_l "or.l" data4:ro, D_REG:rw:cc cost(2,3). +or_l "or.l" D_REG:ro, memalt4:rw:cc cost(2,6). +or_l "or.l" const:ro, datalt4:rw:cc cost(2,6). +rol_l "rol.l" shconreg:ro, D_REG:rw:cc cost(2,4). +rol "rol #1," memalt2:rw:cc cost(2,4). +ror_l "ror.l" shconreg:ro, D_REG:rw:cc cost(2,4). +ror "ror #1," memalt2:rw:cc cost(2,4). +roxl "roxl #1," memalt2:rw:cc cost(2,4). +roxr "roxr #1," memalt2:rw:cc cost(2,4). +sne datalt1:rw cost(2,3). +sub_l "sub.l" any4:ro, D_REG:rw:cc cost(2,3). +sub_l "sub.l" any4:ro, A_REG:rw cost(2,3). +sub_l "sub.l" conreg4:ro, alterable4:rw:cc cost(2,6). +tst_l "tst.l" test_set4:ro:cc cost(2,3). +tst_w "tst.w" test_set2:ro:cc cost(2,3). +tst_b "tst.b" test_set1:ro:cc cost(2,3). +unlk A_REG cost(2,6). + +bxx "illegal" label cost(2,5). +xxx "illegal" data4:ro, D_REG:rw:cc cost(2,3). +xxx "illegal" conreg4:ro, memalt4:rw:cc cost(2,6). +bit "illegal" control4:rw:cc cost(2,6). +sh "illegal" shconreg:ro, D_REG:rw:cc cost(2,4). +shw "illegal" control2:rw:cc cost(2,4). + +#ifdef m68020 +cmp2_l "cmp2.l" address+control4:ro, genreg:ro kills :cc cost(2,18). +divs_l "divs.l" data4:ro, D_REG:rw:cc cost(2,90). +divsl_l "divsl.l" data4:ro, DREG_pair:rw kills :cc cost(2,90). +divu_l "divu.l" data4:ro, D_REG:rw:cc cost(2,78). +divul_l "divul.l" data4:ro, DREG_pair:rw kills :cc cost(2,78). +extb_l "extb.l" D_REG:rw:cc cost(2,4). +muls_l "muls.l" data4:ro, D_REG:rw:cc cost(2,44). +mulu_l "mulu.l" data4:ro, D_REG:rw:cc cost(2,44). +pea address+control4+regX cost(2,4). +#else m68020 +pea address+control4 cost(2,4). +#endif m68020 + + /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + * Extra pseudo instruction; it just kills a D_REG; + * it is necessary with long divides where remainders are important; + * see also: 'pat rmi' and 'pat rmu' + * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/ +killreg "! kill" D_REG:wo cost(0,0). + + +MOVES + +from const %num==0 to D_REG + gen clr_l %2 + +from const %num==0 to memalt4 + gen clr_l %2 + +from const %num==0 to memalt2 + gen clr_w %2 + +from const %num==0 to memalt1 + gen clr_b %2 + +from const to memalt1 + gen move_b {const, lowb(%1.num)}, %2 + +from const to memalt2 + gen move_w {const, loww(%1.num)}, %2 + +from regAcon %bd==0 to A_REG + gen move_l %1.reg, %2 + +#ifndef m68020 +from t_regAregXcon sfit(%bd, 8) to A_REG + gen lea {regAregXcon, %1.reg, %1.xreg, 1, %1.bd}, %2 + +from t_regAregXcon to A_REG + gen lea {regAregXcon, %1.reg, %1.xreg, 1, 0}, %2 + add_l {const, %1.bd}, %2 + +from t_regAcon sfit(%bd, 16) to A_REG + gen lea {regAcon, %1.reg, %1.bd}, %2 + +from t_regAcon to A_REG + gen move_l %1.reg, %2 + add_l {const, %1.bd}, %2 +#endif m68020 + +from address - ext_addr to A_REG + gen lea %1, %2 + +from any4 to alterable4 + gen move_l %1, %2 + +from any2 to datalt2 + gen move_w %1, %2 + +from data1 to datalt1 + gen move_b %1, %2 + + + + +TESTS + + +to test test_set4 + gen tst_l %1 + +to test test_set2 + gen tst_w %1 + +to test test_set1 + gen tst_b %1 + + +STACKINGRULES + + +from const %num==0 to STACK + gen clr_l {pre_dec4, sp} + +#ifndef m68020 +from t_regAregXcon sfit(%bd, 8) to STACK + gen pea {regAregXcon, %1.reg, %1.xreg, 1, %1.bd} + +from t_regAregXcon to STACK + gen pea {regAregXcon, %1.reg, %1.xreg, 1, 0} + add_l {const, %1.bd}, {indirect4, sp} + +from t_regAcon sfit(%bd, 16) to STACK + gen pea {regAcon, %1.reg, %1.bd} + +from t_regAcon to STACK + gen move_l %1.reg, {pre_dec4, sp} + add_l {const, %1.bd}, {indirect4, sp} +#endif m68020 + +from address - ext_addr to STACK + gen pea %1 + +from ext_addr to STACK + gen pea {absolute4, %1.bd} + +from const to STACK + gen pea {absolute4, %1.num} + +from any4 to STACK + gen move_l %1, {pre_dec4, sp} + +from any2 to STACK + gen clr_l {pre_dec4, sp} + move_w %1, {offsetted2, sp, 2} + +from data1 to STACK + gen clr_l {pre_dec4, sp} + move_b %1, {offsetted1, sp, 3} + +#ifdef m68020 +from regX to STACK + gen pea %1 +#endif m68020 + /* This last stackingrule is never used: whenever regX is put on + * the fakestack, some em-instuctions are left that remove it + * immediately. However cgg complained about not having a + * stackingrule for regX, so here it is + */ + + +COERCIONS + + +from STACK + uses DD_REG + gen move_l {post_inc4, sp}, %a + yields %a + +from STACK + uses AA_REG + gen move_l {post_inc4, sp}, %a + yields %a + +#ifndef m68020 +from t_regAregXcon sfit(%bd, 8) + yields {regAregXcon, %1.reg, %1.xreg, 1, %1.bd} + +from t_regAregXcon + uses AA_REG=%1.reg + gen add_l {const, %1.bd}, %a + yields {regAregXcon, %a, %1.xreg, 1, 0} + +from t_regAcon sfit(%bd, 16) + yields {regAcon, %1.reg, %1.bd} + +from t_regAcon + uses reusing %1, AA_REG=%1.reg + gen add_l {const, %1.bd}, %a + yields %a +#endif m68020 + +from t_address + uses reusing %1, AA_REG = %1 + yields %a + +from any4 + uses reusing %1, DD_REG = %1 + yields %a + +from any4 + uses reusing %1, AA_REG = %1 + yields %a + +from memory2 + uses DD_REG = {const, 0} + gen move_w %1, %a yields %a + +from memory1 + uses DD_REG = {const, 0} + gen move_b %1, %a yields %a + + + + +PATTERNS + +/************************************************ + * Group 0: rules for register variables * + * LOCALs mentioned here refer to registers * + ************************************************/ + +pat lol inreg($1)==reg_pointer + kills pre_post %reg==regvar($1, reg_pointer) + yields {LOCAL, $1} + +pat lil inreg($1)==reg_pointer + kills pre_post %reg==regvar($1, reg_pointer) + yields {indirect4, regvar($1, reg_pointer)} + +pat stl inreg($1)==reg_any +with any4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen move %1, {LOCAL, $1} + +pat stl inreg($1)==reg_pointer +with any4 + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen move %1, {LOCAL, $1} +with exact ext_addr + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen move %1, {LOCAL, $1} +with exact address-ext_addr + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen lea %1, {LOCAL, $1} + +pat sil inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move %1, {indirect4, regvar($1, reg_pointer)} + + +pat lol sbi stl $1==$3 && $2==4 && inreg($1)==reg_any +with any4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sub_l %1, {LOCAL, $1} + neg_l {LOCAL, $1} + +pat lol sbu stl $1==$3 && $2==4 && inreg($1)==reg_any +with any4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sub_l %1, {LOCAL, $1} + neg_l {LOCAL, $1} + +pat lil sbi sil $1==$3 && $2==4 && inreg($1)==reg_pointer +with conreg4 + kills allexceptcon + gen sub_l %1, {indirect4, regvar($1, reg_pointer)} + neg_l {indirect4, regvar($1, reg_pointer)} + +pat lil sbu sil $1==$3 && $2==4 && inreg($1)==reg_pointer +with conreg4 + kills allexceptcon + gen sub_l %1, {indirect4, regvar($1, reg_pointer)} + neg_l {indirect4, regvar($1, reg_pointer)} + + +pat lil ngi sil $1==$3 && $2==4 && inreg($1)==reg_pointer + kills allexceptcon + gen neg_l {indirect4, regvar($1, reg_pointer)} + +pat lil com sil $1==$3 && $2==4 && inreg($1)==reg_pointer + kills allexceptcon + gen not_l {indirect4, regvar($1, reg_pointer)} + + +proc lolcshstl example lol loc sli stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sh* {shconst, $2}, {LOCAL, $1} + +proc lolrshstl example lol lol sli stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sh* {LOCAL, $2}, {LOCAL, $1} + +proc lil1shlsil example lil loc sli sil /* only left */ + kills allexceptcon + gen shw* {offsetted2, regvar($1, reg_pointer), 2} + roxl {indirect2, regvar($1, reg_pointer)} + +proc lil1shrsil example lil loc sli sil /* only right */ + kills allexceptcon + gen shw* {indirect2, regvar($1, reg_pointer)} + roxr {offsetted2, regvar($1, reg_pointer), 2} + +pat lol loc sli stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("asl.l") +pat lol loc slu stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("asl.l") +pat lol lol sli stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("asl.l") +pat lol lol slu stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("asl.l") +pat lil loc sli sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shlsil("asl #1,") +pat lil loc slu sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shlsil("asl #1,") +pat lol loc sri stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("asr.l") +pat lol loc sru stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("lsr.l") +pat lol lol sri stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("asr.l") +pat lol lol sru stl $1==$4 && inreg($1)==reg_any && $3==4 && inreg($2)==reg_any + call lolrshstl("lsr.l") +pat lil loc sri sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shrsil("asr #1,") +pat lil loc sru sil $1==$4 && $2==1 && $3==4 && inreg($1)==reg_pointer + call lil1shrsil("lsr #1,") +pat lol loc rol stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("rol.l") +pat lol lol rol stl $1==$4 && inreg($2)==reg_any && $3==4 && inreg($1)==reg_any + call lolrshstl("rol.l") +pat lol loc ror stl $1==$4 && small($2) && $3==4 && inreg($1)==reg_any + call lolcshstl("ror.l") +pat lol lol ror stl $1==$4 && inreg($2)==reg_any && $3==4 && inreg($1)==reg_any + call lolrshstl("ror.l") + +#ifdef m68020 +pat lol loc dvi stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen divs_l {const, $2}, {LOCAL, $1} + +pat lol loc dvu stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen divu_l {const, $2}, {LOCAL, $1} + +pat lol loc mli stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen muls_l {const, $2}, {LOCAL, $1} + +pat lol loc mlu stl $1==$4 && $3==4 && inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen mulu_l {const, $2}, {LOCAL, $1} + +pat lol mli stl $1==$3 && $2==4 && inreg($1)==reg_any + with data4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen muls_l %1, {LOCAL, $1} + +pat lol mlu stl $1==$3 && $2==4 && inreg($1)==reg_any + with data4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen mulu_l %1, {LOCAL, $1} +#endif m68020 + + +pat lil inc sil $1==$3 && inreg($1)==reg_pointer + kills allexceptcon + gen add_l {const, 1}, {indirect4, regvar($1, reg_pointer)} + +pat lil dec sil $1==$3 && inreg($1)==reg_pointer + kills allexceptcon + gen sub_l {const, 1}, {indirect4, regvar($1, reg_pointer)} + +pat inl inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen add_l {const, 1}, {LOCAL, $1} + +pat del inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen sub_l {const, 1}, {LOCAL, $1} + +pat zrl inreg($1)==reg_any + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen clr_l {LOCAL, $1} + +pat zrl inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + gen move_l {const, 0}, {LOCAL, $1} + + +proc lolxxstl example lol and stl +with data4 + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen xxx* %1, {LOCAL, $1} + +proc lilxxsil example lil and sil +with conreg4 + kills allexceptcon + gen xxx* %1, {indirect4, regvar($1, reg_pointer)} + +proc lolcxxstl example lol loc and stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen xxx* {const, $2}, {LOCAL, $1} + +proc lilcxxsil example lil loc and sil + kills allexceptcon + gen xxx* {const, $2}, {indirect4, regvar($1, reg_pointer)} + +proc lolrxxstl example lol lol and stl + kills LOCAL %bd==$1, use_index %xreg==regvar($1, reg_any) + gen xxx* {LOCAL, $2}, {LOCAL, $1} + +proc lilrxxsil example lil lol and sil + kills allexceptcon + gen xxx* {LOCAL, $2}, {indirect4, regvar($1, reg_pointer)} + +pat lol adi stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("add.l") +pat lol loc adi stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("add.l") +pat lil adi sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("add.l") +pat lil loc adi sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("add.l") +pat lol lol adi stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("add.l") +pat lil lol adi sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("add.l") +pat lol adu stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("add.l") +pat lol loc adu stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("add.l") +pat lil adu sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("add.l") +pat lil loc adu sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("add.l") +pat lol lol adu stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("add.l") +pat lil lol adu sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("add.l") +pat lol loc sbi stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("sub.l") +pat lil loc sbi sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("sub.l") +pat lol lol sbi stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("sub.l") +pat lil lol sbi sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("sub.l") +pat lol loc sbu stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("sub.l") +pat lil loc sbu sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("sub.l") +pat lol lol sbu stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("sub.l") +pat lil lol sbu sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("sub.l") +pat lol and stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("and.l") +pat lol loc and stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("and.l") +pat lil and sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("and.l") +pat lil loc and sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("and.l") +pat lol lol and stl $1==$4 && $3==4 && inreg($1)==reg_any && inreg($2)==reg_any + call lolrxxstl("and.l") +pat lil lol and sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("and.l") +pat lol ior stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("or.l") +pat lol loc ior stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("or.l") +pat lil ior sil $1==$3 && $2==4 && inreg($1)==reg_pointer + call lilxxsil("or.l") +pat lil loc ior sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("or.l") +pat lol lol ior stl $1==$4 && $3==4 && inreg($1)==reg_any && + inreg($2)==reg_any + call lolrxxstl("or.l") +pat lil lol ior sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("or.l") +pat lol xor stl $1==$3 && $2==4 && inreg($1)==reg_any + call lolxxstl("eor.l") +pat lol loc xor stl $1==$4 && $3==4 && inreg($1)==reg_any + call lolcxxstl("eor.l") +pat lil xor sil $1==$3 && $2==4 &&inreg($1)==reg_pointer + call lilxxsil("eor.l") +pat lil loc xor sil $1==$4 && $3==4 && inreg($1)==reg_pointer + call lilcxxsil("eor.l") +pat lol lol xor stl $1==$4 && $3==4 && inreg($1)==reg_any && + inreg($2)==reg_any + call lolrxxstl("eor.l") +pat lil lol xor sil $1==$4 && $3==4 && inreg($1)==reg_pointer && + inreg($2)==reg_any + call lilrxxsil("eor.l") + +pat lil adp sil $1==$3 && inreg($1)==reg_pointer + kills allexceptcon + gen add_l {const, $2}, {indirect4, regvar($1, reg_pointer)} + +pat lil lil adp sil $1==$2 && $1==$4 && inreg($1)==reg_pointer + kills allexceptcon + uses AA_REG = {indirect4, regvar($1, reg_pointer)} + gen add_l {const, $3}, {indirect4, regvar($1, reg_pointer)} + yields %a + +pat lol lol adp stl loi $1==$2 && $1==$4 && $3==1 && $5==1 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc1, regvar($1, reg_pointer)} + +pat lol loi lol adp stl $1==$3 && $1==$5 && $2==1 && $4==1 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc1, regvar($1, reg_pointer)} + +pat lol lol adp stl loi $1==$2 && $1==$4 && $3==2 && $5==2 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc2, regvar($1, reg_pointer)} + +pat lol loi lol adp stl $1==$3 && $1==$5 && $2==2 && $4==2 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc2, regvar($1, reg_pointer)} + +pat lol lol adp stl loi $1==$2 && $1==$4 && $3==4 && $5==4 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc4, regvar($1, reg_pointer)} + +pat lil lol adp stl $1==$2 && $1==$4 && $3==4 && inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {post_inc4, regvar($1, reg_pointer)} + +pat lol lol adp stl sti $1==$2 && $1==$4 && $3==1 && $5==1 && + inreg($1)==reg_pointer +with data1 + kills allexceptcon + gen move %1, {post_inc1, regvar($1, reg_pointer)} + +pat lol sti lol adp stl $1==$3 && $1==$5 && $2==1 && $4==1 && + inreg($1)==reg_pointer +with data1 + kills allexceptcon + gen move %1, {post_inc1, regvar($1, reg_pointer)} + +pat lol lol adp stl sti $1==$2 && $1==$4 && $3==2 && $5==2 && + inreg($1)==reg_pointer +with any2 + kills allexceptcon + gen move %1, {post_inc2, regvar($1, reg_pointer)} + +pat lol sti lol adp stl $1==$3 && $1==$5 && $2==2 && $4==2 && + inreg($1)==reg_pointer +with any2 + kills allexceptcon + gen move %1, {post_inc2, regvar($1, reg_pointer)} + +pat lol lol adp stl sti $1==$2 && $1==$4 && $3==4 && $5==4 && + inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move_l %1, {post_inc4, regvar($1, reg_pointer)} + +pat sil lol adp stl $1==$2 && $1==$4 && $3==4 && inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move_l %1, {post_inc4, regvar($1, reg_pointer)} + +pat lol adp stl lol loi $1==$3 && $1==$4 && $2==0-1 && $5==1 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {pre_dec1, regvar($1, reg_pointer)} + +pat lol adp stl lol loi $1==$3 && $1==$4 && $2==0-2 && $5==2 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {pre_dec2, regvar($1, reg_pointer)} + +pat lol adp stl lil $1==$3 && $1==$4 && $2==0-4 && + inreg($1)==reg_pointer + kills LOCAL %bd==$1, all_regind %reg==regvar($1, reg_pointer) + yields {pre_dec4, regvar($1, reg_pointer)} + +pat lol adp stl lol sti $1==$3 && $1==$4 && $2==0-1 && $5==1 && + inreg($1)==reg_pointer +with data1 + kills allexceptcon + gen move %1, {pre_dec1, regvar($1, reg_pointer)} + +pat lol adp stl lol sti $1==$3 && $1==$4 && $2==0-2 && $5==2 && + inreg($1)==reg_pointer +with any2 + kills allexceptcon + gen move %1, {pre_dec2, regvar($1, reg_pointer)} + +pat lol adp stl sil $1==$3 && $1==$4 && $2==0-4 && + inreg($1)==reg_pointer +with any4 + kills allexceptcon + gen move_l %1, {pre_dec4, regvar($1, reg_pointer)} + + + + +/************************************************ + * Group 1: load instructions * + ************************************************/ + +pat loc yields {const, $1} + +pat ldc leaving loc 18 trp + +pat lol yields {LOCAL, $1} + +pat ldl leaving lol $1+4 lol $1 + +pat loe yields {absolute4, $1} + +pat lil +#ifdef m68020 + yields {ILOCAL, $1} +#else m68020 + uses AA_REG = {LOCAL, $1} + yields {indirect4, %a} +#endif m68020 + + /* When using the 'offsetted' intructions regAregXcon cannot be used + * for the m68k4; there is no way of knowing about the size of + * %1.bd+$1, because expressions are not allowed in stack patterns, and + * this may lead to outputting too large displacements. With regAcon + * the chance that this will happen is very slim, because it can + * have displacements of 16 bits. Besides, leaving out regAcon here + * would make it very hard to handle this instruction efficiently. + */ +pat lof +with A_REG yields {offsetted4, %1, $1} +with exact local_addr yields {LOCAL, %1.bd+$1} +with exact ext_addr yields {absolute4, %1.bd+$1} +#ifndef m68020 +with regAcon yields {offsetted4, %1.reg, %1.bd+$1} +#else m68020 +with exact regAcon yields {offsetted4, %1.reg, %1.bd+$1} +with exact regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} +with exact offsetted4 yields {OFF_off4, %1.reg, %1.bd, $1} +with exact indirect yields {OFF_off4, %1.reg, 0, $1} +with exact LOCAL yields {OFF_off4, lb, %1.bd, $1} +with exact off_con yields {OFF_off4, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon yields {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 yields {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con yields {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 yields {ABS_off4, %1.bd, $1} +with exact abs_con yields {ABS_off4, %1.bd, %1.od+$1} +with exact abs_regXcon yields {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX yields {abs_index4, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat lal yields {local_addr, $1} + +pat lae yields {ext_addr, $1} + +pat lxl $1==0 yields lb + +pat lxl $1==1 yields {LOCAL, SL} + +pat lxl $1==2 +#ifdef m68020 + yields {OFF_off4, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + yields {offsetted4, %a, SL} +#endif m68020 + +pat lxl $1==3 +#ifdef m68020 + uses AA_REG = {OFF_off4, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + gen move {offsetted4, %a, SL}, %a +#endif m68020 + yields {offsetted4, %a, SL} + +pat lxl $1>3 + uses AA_REG = {LOCAL, SL}, + DD_REG = {const, $1-2} + gen 1: + move_l {offsetted4, %a, SL} ,%a + dbf %b, {slabel, 1b} + yields %a + +pat lxa $1==0 yields {local_addr, SL} + +pat lxa $1==1 +#ifdef m68020 + yields {off_con, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + yields {regAcon, %a, SL} +#endif m68020 + +pat lxa $1==2 +#ifdef m68020 + uses AA_REG = {OFF_off4, lb, SL, SL} +#else m68020 + uses AA_REG = {LOCAL, SL} + gen move {offsetted4, %a, SL}, %a +#endif m68020 + yields {regAcon, %a, SL} + +pat lxa $1>2 + uses AA_REG = {LOCAL, SL}, + DD_REG = {const, $1-1} + gen 1: + move_l {offsetted4, %a, SL} ,%a + dbf %b, {slabel, 1b} + yields {regAcon, %a, SL} + +pat loi $1==1 +with A_REG yields {indirect1, %1} +with exact local_addr yields {offsetted1, lb, %1.bd} +with exact ext_addr yields {absolute1, %1.bd} +#ifndef m68020 +with regAcon yields {offsetted1, %1.reg, %1.bd} +with regAregXcon yields {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon yields {offsetted1, %1.reg, %1.bd} +with exact regAregXcon yields {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 yields {OFF_off1, %1.reg, 0, 0} +with exact offsetted4 yields {OFF_off1, %1.reg, %1.bd, 0} +with exact LOCAL yields {OFF_off1, lb, %1.bd, 0} +with exact off_con yields {OFF_off1, %1.reg, %1.bd, %1.od} +with exact off_regXcon yields {OFF_indoff1, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 yields {INDOFF_off1, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con yields {INDOFF_off1, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 yields {ABS_off1, %1.bd, 0} +with exact abs_con yields {ABS_off1, %1.bd, %1.od} +with exact abs_regXcon yields {ABS_indoff1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 yields {ABSIND_off1, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con yields {ABSIND_off1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX yields {abs_index1, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat loi $1==2 +with A_REG yields {indirect2, %1} +with exact local_addr yields {offsetted2, lb, %1.bd} +with exact ext_addr yields {absolute2, %1.bd} +#ifndef m68020 +with regAcon yields {offsetted2, %1.reg, %1.bd} +with regAregXcon yields {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon yields {offsetted2, %1.reg, %1.bd} +with exact regAregXcon yields {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 yields {OFF_off2, %1.reg, 0, 0} +with exact offsetted4 yields {OFF_off2, %1.reg, %1.bd, 0} +with exact LOCAL yields {OFF_off2, lb, %1.bd, 0} +with exact off_con yields {OFF_off2, %1.reg, %1.bd, %1.od} +with exact off_regXcon yields {OFF_indoff2, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 yields {INDOFF_off2, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con yields {INDOFF_off2, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 yields {ABS_off2, %1.bd, 0} +with exact abs_con yields {ABS_off2, %1.bd, %1.od} +with exact abs_regXcon yields {ABS_indoff2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 yields {ABSIND_off2, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con yields {ABSIND_off2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX yields {abs_index2, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat loi $1==4 +with A_REG yields {indirect4, %1} +with exact local_addr yields {LOCAL, %1.bd} +with exact ext_addr yields {absolute4, %1.bd} +#ifndef m68020 +with regAcon yields {offsetted4, %1.reg, %1.bd} +with regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon yields {offsetted4, %1.reg, %1.bd} +with exact regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact LOCAL yields {ILOCAL, %1.bd} +with exact indirect4 yields {OFF_off4, %1.reg, 0, 0} +with exact offsetted4 yields {OFF_off4, %1.reg, %1.bd, 0} +with exact off_con yields {OFF_off4, %1.reg, %1.bd, %1.od} +with exact off_regXcon yields {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 yields {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con yields {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 yields {ABS_off4, %1.bd, 0} +with exact abs_con yields {ABS_off4, %1.bd, %1.od} +with exact abs_regXcon yields {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX yields {abs_index4, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat loi $1==8 +with A_REG yields {offsetted4, %1, 4} + {indirect4, %1} +pat loi $1>8 +with AA_REG STACK + uses DD_REG = {const, $1/4 -1} + gen add_l {const, $1}, %1 + 1: + move_l {pre_dec4, %1}, {pre_dec4, sp} + dbf %a, {slabel, 1b} + +pat los $1==4 +with STACK + gen jsr {absolute4, ".los"} + +pat lde yields {absolute4, $1+4} + {absolute4, $1} + +pat ldf +with A_REG yields {offsetted4, %1, $1+4} + {offsetted4, %1, $1} +with exact local_addr yields {LOCAL, %1.bd+$1+4} + {LOCAL, %1.bd+$1} +with exact ext_addr yields {absolute4, %1.bd+$1+4} + {absolute4, %1.bd+$1} +#ifndef m68020 +with regAcon yields {offsetted4, %1.reg, %1.bd+$1+4} + {offsetted4, %1.reg, %1.bd+$1} +#else m68020 +with exact regAcon yields {offsetted4, %1.reg, %1.bd+$1+4} + {offsetted4, %1.reg, %1.bd+$1} +with exact regAregXcon yields {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1+4} + {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} +with exact indirect4 yields {OFF_off4, %1.reg, 0, $1+4} + {OFF_off4, %1.reg, 0, $1} +with exact offsetted4 yields {OFF_off4, %1.reg, %1.bd, $1+4} + {OFF_off4, %1.reg, %1.bd, $1} +with exact LOCAL yields {OFF_off4, lb, %1.bd, $1+4} + {OFF_off4, lb, %1.bd, $1} +with exact off_con yields {OFF_off4, %1.reg, %1.bd, %1.od+$1+4} + {OFF_off4, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon yields {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} + {OFF_indoff4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 yields {INDOFF_off4, %1.reg, %1.xreg, %1.sc,%1.bd,$1+4} + {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con yields {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} + {INDOFF_off4, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 yields {ABS_off4, %1.bd, $1+4} + {ABS_off4, %1.bd, $1} +with exact abs_con yields {ABS_off4, %1.bd, %1.od+$1+4} + {ABS_off4, %1.bd, %1.od+$1} +with exact abs_regXcon yields {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} + {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1+4} + {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con yields {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} + {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX yields {abs_index4, %1.sc, %1.xreg, %1.bd+$1+4} + {abs_index4, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat lpi yields {ext_addr, $1} + + + +/************************************************ + * Group 2: store instructions * + ************************************************/ + +pat stl +with any4 + kills all_indir, LOCAL %bd==$1 + gen move %1, {LOCAL, $1} +with exact STACK + gen move {post_inc4,sp}, {LOCAL, $1} + +pat ste +with any4 + kills posextern + gen move %1, {absolute4, $1} +with exact STACK + gen move {post_inc4, sp}, {absolute4, $1} + +pat sil +#ifdef m68020 +with any4 + kills allexceptcon + gen move %1, {ILOCAL, $1} +with exact STACK + gen move {post_inc4, sp}, {ILOCAL, $1} +#else m68020 +with any4 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen move %1, {indirect4, %a} +with exact STACK + uses AA_REG = {LOCAL, $1} + gen move {post_inc4, sp}, {indirect4, %a} +#endif m68020 + +pat stf +with A_REG any4 + kills allexceptcon + gen move %2, {offsetted4, %1, $1} +with A_REG STACK + gen move {post_inc4, sp}, {offsetted4, %1, $1} +with exact local_addr any4 + kills allexceptcon + gen move %2, {LOCAL, %1.bd+$1} +with exact ext_addr any4 + kills allexceptcon + gen move %2, {absolute4, %1.bd+$1} +#ifndef m68020 +with regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} +#else m68020 +with exact regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} +with exact regAregXcon any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} +with exact indirect4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, 0, $1} +with exact offsetted4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, $1} +with exact LOCAL any4 + kills allexceptcon + gen move %2, {OFF_off4, lb, %1.bd, $1} +with exact off_con any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon any4 + kills allexceptcon + gen move %2, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, $1} +with exact abs_con any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, %1.od+$1} +with exact abs_regXcon any4 + kills allexceptcon + gen move %2, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX any4 + kills allexceptcon + gen move %2, {abs_index4, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat sti $1==1 +with A_REG data1 + kills allexceptcon + gen move %2, {indirect1, %1} +with exact local_addr data1 + kills allexceptcon + gen move %2, {offsetted1, lb, %1.bd} +with exact ext_addr data1 + kills allexceptcon + gen move %2, {absolute1, %1.bd} +#ifndef m68020 +with regAcon data1 + kills allexceptcon + gen move %2, {offsetted1, %1.reg, %1.bd} +with regAregXcon data1 + kills allexceptcon + gen move %2, {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon data1 + kills allexceptcon + gen move %2, {offsetted1, %1.reg, %1.bd} +with exact regAregXcon data1 + kills allexceptcon + gen move %2, {index_off1, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 data1 + kills allexceptcon + gen move %2, {OFF_off1, %1.reg, 0, 0} +with exact offsetted4 data1 + kills allexceptcon + gen move %2, {OFF_off1, %1.reg, %1.bd, 0} +with exact LOCAL data1 + kills allexceptcon + gen move %2, {OFF_off1, lb, %1.bd, 0} +with exact off_con data1 + kills allexceptcon + gen move %2, {OFF_off1, %1.reg, %1.bd, %1.od} +with exact off_regXcon data1 + kills allexceptcon + gen move %2, {OFF_indoff1, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 data1 + kills allexceptcon + gen move %2, {INDOFF_off1, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con data1 + kills allexceptcon + gen move %2, {INDOFF_off1, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 data1 + kills allexceptcon + gen move %2, {ABS_off1, %1.bd, 0} +with exact abs_con data1 + kills allexceptcon + gen move %2, {ABS_off1, %1.bd, %1.od} +with exact abs_regXcon data1 + kills allexceptcon + gen move %2, {ABS_indoff1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 data1 + kills allexceptcon + gen move %2, {ABSIND_off1, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con data1 + kills allexceptcon + gen move %2, {ABSIND_off1, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX data1 + kills allexceptcon + gen move %2, {abs_index1, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat sti $1==2 +with A_REG any2 + kills allexceptcon + gen move %2, {indirect2, %1} +with exact local_addr any2 + kills allexceptcon + gen move %2, {offsetted2, lb, %1.bd} +with exact ext_addr any2 + kills allexceptcon + gen move %2, {absolute2, %1.bd} +#ifndef m68020 +with regAcon any2 + kills allexceptcon + gen move %2, {offsetted2, %1.reg, %1.bd} +with regAregXcon any2 + kills allexceptcon + gen move %2, {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon any2 + kills allexceptcon + gen move %2, {offsetted2, %1.reg, %1.bd} +with exact regAregXcon any2 + kills allexceptcon + gen move %2, {index_off2, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact indirect4 any2 + kills allexceptcon + gen move %2, {OFF_off2, %1.reg, 0, 0} +with exact offsetted4 any2 + kills allexceptcon + gen move %2, {OFF_off2, %1.reg, %1.bd, 0} +with exact LOCAL any2 + kills allexceptcon + gen move %2, {OFF_off2, lb, %1.bd, 0} +with exact off_con any2 + kills allexceptcon + gen move %2, {OFF_off2, %1.reg, %1.bd, %1.od} +with exact index_off4 any2 + kills allexceptcon + gen move %2, {INDOFF_off2, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact off_regXcon any2 + kills allexceptcon + gen move %2, {OFF_indoff2, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact indoff_con any2 + kills allexceptcon + gen move %2, {INDOFF_off2, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 any2 + kills allexceptcon + gen move %2, {ABS_off2, %1.bd, 0} +with exact abs_con any2 + kills allexceptcon + gen move %2, {ABS_off2, %1.bd, %1.od} +with exact abs_regXcon any2 + kills allexceptcon + gen move %2, {ABS_indoff2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 any2 + kills allexceptcon + gen move %2, {ABSIND_off2, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con any2 + kills allexceptcon + gen move %2, {ABSIND_off2, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX any2 + kills allexceptcon + gen move %2, {abs_index2, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat sti $1==4 +with A_REG any4 + kills allexceptcon + gen move %2, {indirect4, %1} +with A_REG STACK + gen move {post_inc4, sp}, {indirect4, %1} +with exact local_addr any4 + kills allexceptcon + gen move %2, {LOCAL, %1.bd} +with exact ext_addr any4 + kills allexceptcon + gen move %2, {absolute4, %1.bd} +#ifndef m68020 +with regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd} +with regAregXcon any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +#else m68020 +with exact regAcon any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd} +with exact regAregXcon any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd} +with exact LOCAL any4 + kills allexceptcon + gen move %2, {ILOCAL, %1.bd} +with exact indirect4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, 0, 0} +with exact offsetted4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, 0} +with exact off_con any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, %1.od} +with exact off_regXcon any4 + kills allexceptcon + gen move %2, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact index_off4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, 0} +with exact indoff_con any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od} +with exact absolute4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, 0} +with exact abs_con any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, %1.od} +with exact abs_regXcon any4 + kills allexceptcon + gen move %2, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact abs_index4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, 0} +with exact absind_con any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od} +with exact ext_regX any4 + kills allexceptcon + gen move %2, {abs_index4, %1.sc, %1.xreg, %1.bd} +#endif m68020 + +pat sti $1>4 +with AA_REG STACK + uses DD_REG = {const, $1/4 -1} + gen 1: + move_l {post_inc4, sp}, {post_inc4, %1} + dbf %a, {slabel, 1b} + +pat sts $1==4 +with STACK + gen jsr {absolute4, ".sts"} + +pat sdl +with any4 any4 + kills all_indir, LOCAL %bd==$1 + gen move %1, {LOCAL, $1} + move %2, {LOCAL, $1+4} + +pat sde +with any4 any4 + kills posextern + gen move %1, {absolute4, $1} + move %2, {absolute4, $1+4} + +pat sdf +with A_REG any4 any4 + kills allexceptcon + gen move %2, {offsetted4, %1, $1} + move %3, {offsetted4, %1, $1+4} +with exact local_addr any4 any4 + kills allexceptcon + gen move %2, {LOCAL, %1.bd+$1} + move %3, {LOCAL, %1.bd+$1+4} +with exact ext_addr any4 any4 + kills allexceptcon + gen move %2, {absolute4, %1.bd+$1} + move %3, {absolute4, %1.bd+$1+4} +#ifndef m68020 +with regAcon any4 any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} + move %3, {offsetted4, %1.reg, %1.bd+$1+4} +#else m68020 +with exact regAcon any4 any4 + kills allexceptcon + gen move %2, {offsetted4, %1.reg, %1.bd+$1} + move %3, {offsetted4, %1.reg, %1.bd+$1+4} +with exact regAregXcon any4 any4 + kills allexceptcon + gen move %2, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1} + move %3, {index_off4, %1.reg, %1.xreg, %1.sc, %1.bd+$1+4} +with exact indirect4 any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, 0, $1} + move %3, {OFF_off4, %1.reg, 0, $1+4} +with exact offsetted4 any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, $1} + move %3, {OFF_off4, %1.reg, %1.bd, $1+4} +with exact LOCAL any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, lb, %1.bd, $1} + move %3, {OFF_off4, lb, %1.bd, $1+4} +with exact off_con any4 any4 + kills allexceptcon + gen move %2, {OFF_off4, %1.reg, %1.bd, %1.od+$1} + move %3, {OFF_off4, %1.reg, %1.bd, %1.od+$1+4} +with exact off_regXcon any4 any4 + kills allexceptcon + gen move %2, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} + move %3, {OFF_indoff4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} +with exact index_off4 any4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1} + move %3, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, $1+4} +with exact indoff_con any4 any4 + kills allexceptcon + gen move %2, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} + move %3, {INDOFF_off4, %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1+4} +with exact absolute4 any4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, $1} + move %3, {ABS_off4, %1.bd, $1+4} +with exact abs_con any4 any4 + kills allexceptcon + gen move %2, {ABS_off4, %1.bd, %1.od+$1} + move %3, {ABS_off4, %1.bd, %1.od+$1+4} +with exact abs_regXcon any4 any4 + kills allexceptcon + gen move %2, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1} + move %3, {ABS_indoff4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} +with exact abs_index4 any4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1} + move %3, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, $1+4} +with exact absind_con any4 any4 + kills allexceptcon + gen move %2, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1} + move %3, {ABSIND_off4, %1.sc, %1.xreg, %1.bd, %1.od+$1+4} +with exact ext_regX any4 any4 + kills allexceptcon + gen move %2, {abs_index4, %1.sc, %1.xreg, %1.bd+$1} + move %3, {abs_index4, %1.sc, %1.xreg, %1.bd+$1+4} +#endif m68020 + + + +/************************************************ + * Group 3: integer arithmetic. * + ************************************************/ + + +pat adi $1==4 +with any4 DD_REG + gen add_l %1, %2 yields %2 +with DD_REG any4-DD_REG + gen add_l %2, %1 yields %1 +with DD_REG STACK + gen add_l {post_inc4, sp}, %1 + yields %1 + +pat sbi $1==4 +with any4 DD_REG + gen sub_l %1, %2 yields %2 +with DD_REG any4-DD_REG + gen sub_l %2, %1 + neg_l %1 yields %1 +with DD_REG STACK + gen sub_l {post_inc4, sp}, %1 + neg_l %1 yields %1 +with any4 AA_REG + gen sub_l %1, %2 yields %2 + +pat mli $1==4 +#ifdef m68020 +with data4 DD_REG + gen muls_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".mli"} + yields d1 +#endif m68020 + +pat dvi $1==4 +#ifdef m68020 +with data4 DD_REG + gen divs_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".dvi"} + yields d1 +#endif m68020 + +pat rmi $1==4 +#ifdef m68020 +with data4 DD_REG + uses DD_REG + gen divsl_l %1, {DREG_pair, %a, %2} + killreg %2 + /* !!!! contents of %2 have changed: make this known to cg */ + yields %a +#else m68020 +with STACK + gen jsr {absolute4, ".dvi"} + yields d0 +#endif m68020 + +pat ngi $1==4 +with DD_REG + gen neg_l %1 yields %1 + +pat sli $1==4 +with D_REG DD_REG + gen asl_l %1, %2 yields %2 + +pat sri $1==4 +with D_REG DD_REG + gen asr_l %1, %2 yields %2 + + + +/************************************************ + * Group 4: unsigned arithmetic. * + ************************************************/ + + +pat adu leaving adi $1 + +pat sbu leaving sbi $1 + +pat mlu $1==4 +#ifdef m68020 +with data4 DD_REG + gen mulu_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".mlu"} + yields d1 +#endif m68020 + +pat dvu $1==4 +#ifdef m68020 +with data4 DD_REG + gen divu_l %1, %2 yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".dvu"} + yields d1 +#endif m68020 + +pat rmu $1==4 +#ifdef m68020 +with data4 DD_REG + uses DD_REG + gen divul_l %1, {DREG_pair, %a, %2} + killreg %2 + /* !!!! contents of %2 have changed: make this known to cg */ + yields %a +#else m68020 +with STACK + gen jsr {absolute4, ".dvu"} + yields d0 +#endif m68020 + +pat slu leaving sli $1 + +pat sru $1==4 +with D_REG DD_REG + gen lsr_l %1, %2 yields %2 + + + +/************************************************ + * Group 5: floating point arithmetic * + * * + * is not available on 68000, 68010 or 68020 * + * so traps will be generated * + ************************************************/ + +pat adf leaving loc 18 trp +pat sbf leaving loc 18 trp +pat mlf leaving loc 18 trp +pat dvf leaving loc 18 trp +pat ngf leaving loc 18 trp +pat fif leaving loc 18 trp +pat fef leaving loc 18 trp + + + +/************************************************ + * Group 6: pointer arithmetic * + ************************************************/ + +pat adp $1==0 /* skip; array instructions might 'leave' this */ + +pat adp +with A_REG yields {t_regAcon, %1, $1} +with exact local_addr yields {local_addr, %1.bd+$1} +with exact ext_addr yields {ext_addr, %1.bd+$1} +with exact regAcon + t_regAcon + yields {t_regAcon, %1.reg, %1.bd+$1} +with exact regAregXcon + t_regAregXcon + yields {t_regAregXcon,%1.reg, %1.xreg, %1.sc, %1.bd+$1} +#ifdef m68020 +with exact indirect4 yields {off_con, %1.reg, 0, $1} +with exact LOCAL yields {off_con, lb, %1.bd, $1} +with exact offsetted4 yields {off_con, %1.reg, %1.bd, $1} +with exact off_con yields {off_con, %1.reg, %1.bd, %1.od+$1} +with exact off_regXcon yields {off_regXcon, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact index_off4 yields {indoff_con, %1.reg, %1.xreg, %1.sc, %1.bd, $1} +with exact indoff_con yields {indoff_con, + %1.reg, %1.xreg, %1.sc, %1.bd, %1.od+$1} +with exact absolute4 yields {abs_con, %1.bd, $1} +with exact abs_con yields {abs_con, %1.bd, %1.od+$1} +with exact abs_regXcon yields {abs_regXcon, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact abs_index4 yields {absind_con, %1.sc, %1.xreg, %1.bd, $1} +with exact absind_con yields {absind_con, %1.sc, %1.xreg, %1.bd, %1.od+$1} +with exact ext_regX yields {ext_regX, %1.sc, %1.xreg, %1.bd+$1} +#endif m68020 + +pat ads $1==4 +with D_REG A_REG yields {regAregXcon, %2, %1, 1, 0} +with D_REG regAcon + t_regAcon + yields {t_regAregXcon, %2.reg, %1, 1, %2.bd} +with D_REG local_addr yields {t_regAregXcon, lb, %1, 1, %2.bd} +with any4-D_REG AA_REG + gen add_l %1, %2 yields %2 + +#ifdef m68020 + +with D_REG yields {regX, 1, %1} + leaving ads 4 +with regX A_REG yields {regAregXcon, %2, %1.xreg, %1.sc, 0} +with exact regX regAcon yields {regAregXcon, %2.reg, %1.xreg, %1.sc, %2.bd} +with exact regX local_addr + yields {regAregXcon, lb, %1.xreg, %1.sc, %2.bd} +with exact regX ext_addr + yields {ext_regX, %1.sc, %1.xreg, %2.bd} +with exact regX indirect4 + yields {off_regXcon, %2.reg, %1.xreg,%1.sc,0,0} +with exact regX offsetted4 + yields {off_regXcon, %2.reg, %1.xreg, %1.sc, %2.bd, 0} +with exact regX LOCAL yields {off_regXcon, lb, %1.xreg, %1.sc, %2.bd, 0} +with exact regX off_con yields {off_regXcon, %2.reg, %1.xreg,%1.sc,%2.bd,%2.od} +with exact regX absolute4 + yields {abs_regXcon, %1.sc, %1.xreg, %2.bd, 0} +with exact regX abs_con yields {abs_regXcon, %1.sc, %1.xreg, %2.bd, %2.od} +with exact indirect4 ext_addr + yields {off_con, %1.reg, 0, %2.bd} +with exact offsetted4 ext_addr + yields {off_con, %1.reg, %1.bd, %2.bd} +with exact LOCAL ext_addr + yields {off_con, lb, %1.bd, %2.bd} +with exact index_off4 ext_addr + yields {indoff_con, %1.reg, %1.xreg, %1.sc,%1.bd,%2.bd} +with exact absolute4 ext_addr + yields {abs_con, %1.bd, %2.bd} +with exact abs_index4 ext_addr + yields {absind_con, %1.sc, %1.xreg, %1.bd, %2.bd} +with exact indirect4 ext_regX + yields {off_regXcon, %1.reg, %2.xreg, %2.sc, 0, %2.bd} +with exact offsetted4 ext_regX + yields {off_regXcon, %1.reg, %2.xreg,%2.sc,%1.bd,%2.bd} +with exact LOCAL ext_regX + yields {off_regXcon, lb, %2.xreg, %2.sc, %1.bd, %2.bd} +with exact absolute4 ext_regX + yields {abs_regXcon, %2.sc, %2.xreg, %1.bd, %2.bd} +#endif m68020 + + /* I WOULD ALSO LIKE THIS: + * pat ads + * with const leaving adp %1.num + * BUT THAT DOESN'T WORK. + */ + +pat sbs $1==4 leaving sbi 4 + +#ifdef m68020 +pat loc sli ads $1==1 && $2==4 && $3==4 +with D_REG yields {regX, 2, %1} + leaving ads 4 + +pat loc sli ads $1==2 && $2==4 && $3==4 +with D_REG yields {regX, 4, %1} + leaving ads 4 + +pat loc sli ads $1==3 && $2==4 && $3==4 +with D_REG yields {regX, 8, %1} + leaving ads 4 +#endif m68020 + + +/************************************************ + * Group 7: increment / decrement / zero * + ************************************************/ + +pat inc +with exact STACK + gen add_l {const, 1}, {indirect4, sp} +with DD_REG+AA_REG + gen add_l {const, 1}, %1 + yields %1 + +pat inl + kills all_indir, LOCAL %bd==$1 + gen add_l {const, 1}, {LOCAL, $1} + +pat ine + kills posextern + gen add_l {const, 1}, {absolute4, $1} + +pat dec +with exact STACK + gen sub_l {const, 1}, {indirect4, sp} +with DD_REG+AA_REG + gen sub_l {const, 1}, %1 + yields %1 + +pat del + kills all_indir, LOCAL %bd==$1 + gen sub_l {const, 1}, {LOCAL, $1} + +pat dee + kills posextern + gen sub_l {const, 1}, {absolute4, $1} + +pat zrl + kills all_indir, LOCAL %bd==$1 + gen clr_l {LOCAL, $1} + +pat zre + kills posextern + gen clr_l {absolute4, $1} + +pat zer $1==4 yields {const, 0} +pat zer $1==8 yields {const, 0} {const, 0} +pat zer $1==12 yields {const, 0} {const, 0} {const, 0} + +pat zer +with STACK + uses DD_REG = {const, $1/4 -1} + gen 1: + clr_l {pre_dec4, sp} + dbf %a, {slabel, 1b} + + +pat zrf leaving loc 18 trp + + + +/************************************************ + * Group 8: convert instructions * + * for float conversions traps are generated * + ************************************************/ + + + +pat cii +with STACK + gen jsr {absolute4, ".cii"} + +pat cuu +with STACK + gen jsr {absolute4, ".cuu"} + +pat ciu leaving cuu + +pat cui leaving cuu + +pat cfi leaving loc 18 trp +pat cif leaving loc 18 trp +pat cfu leaving loc 18 trp +pat cuf leaving loc 18 trp +pat cff leaving loc 18 trp + + +/************************************************ + * Group 9: logical instructions * + ************************************************/ + + +proc log4 +with datalt4+const DD_REG + gen xxx* %1, %2 yields %2 +with DD_REG datalt4+const + gen xxx* %2, %1 yields %1 + +proc logdef example and +with STACK + uses DD_REG = {const, $1/4 -1}, + AA_REG = {regAcon, sp, $1}, + DD_REG + gen 1: + move_l {post_inc4, sp}, %c + xxx* %c, {post_inc4, %b} + dbf %a, {slabel, 1b} + +proc logndef +with DD_REG STACK + uses AA_REG = {regAregXcon, sp, %1, 1, 0}, + DD_REG + gen asr_l {shconst, 2}, %1 + sub_l {const, 1}, %1 + 1: + move_l {post_inc4, sp}, %b + xxx* %b, {post_inc4, %a} + dbf %1, {slabel, 1b} + +pat and $1==4 call log4("and.l") +pat and $1>4 call logdef("and.l") +pat and !defined($1) call logndef("and.l") +pat ior $1==4 call log4("or.l") +pat ior $1>4 call logdef("or.l") +pat ior !defined($1) call logndef("or.l") + +pat xor $1==4 +with conreg4 DD_REG + gen eor_l %1, %2 yields %2 +with DD_REG conreg4 + gen eor_l %2, %1 yields %1 + +pat xor $1>4 call logdef("eor.l") +pat xor !defined($1) call logndef("eor.l") + +pat com $1==4 +with DD_REG + gen not_l %1 yields %1 + +pat com $1==8 +with DD_REG DD_REG + gen not_l %1 + not_l %2 yields %2 %1 + +pat com $1>4 +with STACK + uses AA_REG, + DD_REG = {const, $1/4 -1} + gen move_l sp, %a + 1: + not_l {post_inc4, %a} + dbf %b, {slabel, 1b} + +pat com !defined($1) +with DD_REG STACK + uses AA_REG + gen move_l sp, %a + asr_l {shconst, 2}, %1 + sub_l {const, 1}, %1 + 1: + not_l {post_inc4, %a} + dbf %1, {slabel, 1b} + +pat rol $1==4 +with D_REG DD_REG + gen rol_l %1, %2 yields %2 + +pat ror $1==4 +with D_REG DD_REG + gen ror_l %1, %2 yields %2 + + + + +/************************************************ + * Group 10: sets * + ************************************************/ + + +pat inn $1==4 +with conreg2 DD_REG + gen btst %1, %2 + sne %2 + and_l {const, 1}, %2 + yields %2 + +pat inn defined($1) +with any4 STACK + gen move %1, d0 + move {const, $1}, d1 + jsr {absolute4, ".inn"} + yields d0 + +pat inn !defined($1) +with any4 any4 STACK + gen move %2, d0 + move %1, d1 + jsr {absolute4, ".inn"} + yields d0 + +pat loc inn $2==4 && small($1) +with DD_REG + gen asr_l {shconst, $1}, %1 + and_l {const, 1}, %1 + yields %1 + +pat set $1==4 +with conreg2 + uses DD_REG = {const, 0} + gen bset %1, %a yields %a + +pat set $1>4 +with any4 STACK + gen move %1, d0 + move {const, $1}, d1 + jsr {absolute4, ".set"} + +pat set !defined($1) +with any4 any4 STACK + gen move %2, d0 + move %1, d1 + jsr {absolute4, ".set"} + + + + +/************************************************ + * Group 11: arrays * + ************************************************/ + + +pat lar defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".lar"} + +pat lar !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".lar"} + +pat sar defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".sar"} + +pat sar !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".sar"} + +pat aar defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".aar"} + yields a0 + +pat aar !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".aar"} + yields a0 + +pat lae lar $2==4 && nicesize(rom($1,3)) + leaving lae $1 aar 4 loi rom($1, 3) +pat lae sar $2==4 && nicesize(rom($1,3)) + leaving lae $1 aar 4 sti rom($1, 3) + +pat lae aar $2==4 && rom($1,3)==1 + leaving ads 4 adp 0-rom($1,1) + +#ifdef m68020 +pat lae aar $2==4 && nicesize(rom($1,3)) +with D_REG yields {regX, rom($1,3), %1} + leaving ads 4 adp rom($1,3)*(0-rom($1,1)) +#else m68020 +pat lae aar $2==4 && rom($1,3)==2 +with DD_REG + gen asl_l {shconst, 1}, %1 + yields %1 + leaving ads 4 adp (0 - rom($1,1))<<1 + +pat lae aar $2==4 && rom($1,3)==4 +with DD_REG + gen asl_l {shconst, 2}, %1 + yields %1 + leaving ads 4 adp (0 - rom($1,1))<<2 + +pat lae aar $2==4 && rom($1,3)==8 +with DD_REG + gen asl_l {shconst, 3}, %1 + yields %1 + leaving ads 4 adp (0 - rom($1,1))<<3 +#endif m68020 + + /* I WOULD ALSO LIKE THESE: + * pat lae aar $2==4 && defined(rom($1,3)) + * with const leaving adp rom($1,3)*(%1.num-rom($1,1)) + * pat lae lar $2==4 && defined(rom($1,3)) + * with const leaving adp rom($1,3)*(%1.num-rom($1,1)) + * loi rom($1,3) + * pat lae sar $2==4 && defined(rom($1,3)) + * with const leaving adp rom($1,3)*(%1.num-rom($1,1)) + * sti rom($1,3) + * BUT THEY DON'T WORK. + */ + + + +/************************************************ + * Group 12: compare instructions * + ************************************************/ + + +pat cmi $1==4 leaving sbi 4 + +pat cmi defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".cmi"} + yields d0 + +pat cmi !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".cmi"} + yields d0 + +pat cmu $1==4 leaving sbi 4 + +pat cmu defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".cmu"} + yields d0 + +pat cmu !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".cmu"} + yields d0 + +pat cms $1==4 leaving sbi 4 + +pat cms defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".cms"} + yields d0 + +pat cms !defined($1) +with any4 STACK + gen move %1, d0 + jsr {absolute4, ".cms"} + yields d0 + +pat cmp leaving cmu 4 + +proc txx +with test_set + uses DD_REG = {const, 1} + gen test %1 + bxx* {slabel, 1f} + clr_l %a + 1: + yields %a + +pat tlt call txx("blt") +pat tle call txx("ble") +pat teq call txx("beq") +pat tne call txx("bne") +pat tge call txx("bge") +pat tgt call txx("bgt") + +pat cmf leaving loc 18 trp + + + +/************************************************ + * Group 13: branch instructions * + ************************************************/ + +pat bra +with STACK + gen bra {llabel, $1} + +proc brxx example beq +with any4 genreg STACK + gen cmp_l %1, %2 + bxx[1] {llabel, $1} +with genreg any4 STACK + gen cmp_l %2, %1 + bxx[2] {llabel, $1} +with exact immediate4 imm_cmp4 + kills ALL + gen cmp_l %1, %2 + bxx[1] {llabel, $1} +with exact imm_cmp4 immediate4 + kills ALL + gen cmp_l %2, %1 + bxx[2] {llabel, $1} +with genreg STACK + gen cmp_l {post_inc4, sp}, %1 + bxx[2] {llabel, $1} +with exact immediate4 STACK + gen cmp_l %1, {post_inc4, sp} + bxx[1] {llabel, $1} +with any2-conreg2 genreg STACK + gen cmp_w %1, %2 + bxx[1] {llabel, $1} +with genreg any2-conreg2 STACK + gen cmp_w %2, %1 + bxx[2] {llabel, $1} +with exact const imm_cmp2 + kills ALL + gen cmp_w {const, loww(%1.num)}, %2 + bxx[1] {llabel, $1} +with exact imm_cmp2 const + kills ALL + gen cmp_w {const, loww(%2.num)}, %1 + bxx[2] {llabel, $1} +with data1-conreg1 D_REG STACK + gen cmp_b %1, %2 + bxx[1] {llabel, $1} +with D_REG data1-conreg1 STACK + gen cmp_b %2, %1 + bxx[2] {llabel, $1} +with exact const imm_cmp1 + kills ALL + gen cmp_b {const, lowb(%1.num)}, %2 + bxx[1] {llabel, $1} +with exact imm_cmp1 const + kills ALL + gen cmp_b {const, lowb(%2.num)}, %1 + bxx[2] {llabel, $1} + +pat blt call brxx("blt","bgt") +pat ble call brxx("ble","bge") +pat beq call brxx("beq","beq") +pat bne call brxx("bne","bne") +pat bge call brxx("bge","ble") +pat bgt call brxx("bgt","blt") + +proc zxx example zeq +with test_set STACK + gen test %1 + bxx* {llabel, $1} +with exact STACK + gen test {post_inc4, sp} + bxx* {llabel, $1} + +pat zlt call zxx("blt") +pat zle call zxx("ble") +pat zeq call zxx("beq") +pat zne call zxx("bne") +pat zge call zxx("bge") +pat zgt call zxx("bgt") + +/************************************************ + * Group 14: procedure calls instructions * + ************************************************/ + + +pat cai +with exact ext_addr + kills ALL + gen jsr {absolute4, %1.bd} +with A_REG STACK + gen jsr {indirect4, %1} +with STACK + uses AA_REG = {post_inc4, sp} + gen jsr {indirect4, %a} +#ifdef m68020 +with exact address + kills ALL + gen jsr %1 +#else m68020 +with address STACK + gen jsr %1 +#endif m68020 + +pat cal +with STACK + gen jsr {absolute4, $1} + +pat lfr $1==4 yields d0 +pat lfr $1==8 yields d1 d0 + +pat ret $1==0 +with STACK + gen return + +pat ret $1==4 +with any4 STACK + gen move %1, d0 + return +with STACK + gen move {post_inc4, sp}, d0 + return + +pat ret $1==8 +with any4 any4 STACK + gen move %1, d0 + move %2, d1 + return +with any4 STACK + gen move %1, d0 + move {post_inc4, sp}, d1 + return +with STACK + gen move {post_inc4, sp}, d0 + move {post_inc4, sp}, d1 + return + + +/************************************************ + * Group 15: miscellaneous instructions * + ************************************************/ + +pat asp small($1) +with STACK + gen add_l {const, $1}, sp +pat asp +with STACK + gen move {regAcon, sp, $1}, sp + +pat ass $1==4 +with any4 STACK + gen add_l %1, sp + +pat blm $1==4 +with A_REG A_REG + kills allexceptcon + gen move_l {indirect4, %2}, {indirect4, %1} + +pat blm $1==8 +with A_REG A_REG + kills allexceptcon + gen move_l {indirect4, %2}, {indirect4, %1} + move_l {offsetted4, %2, 4}, {offsetted4, %1, 4} + +pat blm $1>8 +with AA_REG AA_REG + kills allexceptcon + uses DD_REG={const, $1/4 -1} + gen 1: + move_l {post_inc4, %2}, {post_inc4, %1} + dbf %a, {slabel, 1b} + +pat bls $1==4 +with DD_REG AA_REG AA_REG + kills allexceptcon + gen asr_l {shconst, 2}, %1 + beq {slabel, 2f} + sub_l {const, 1}, %1 + 1: + move_l {post_inc4, %3}, {post_inc4, %2} + dbf %1, {slabel, 1b} + 2: + +pat csa $1==4 +with STACK + gen jmp {absolute4, ".csa"} + +pat csb $1==4 +with STACK + gen jmp {absolute4, ".csb"} + +pat dch leaving loi 4 + +pat dup $1==4 +with exact STACK + gen move_l {indirect4, sp}, {pre_dec4, sp} +with any4 yields %1 %1 + +pat dup $1==8 +with exact STACK + gen move_l {offsetted4, sp, 4}, {pre_dec4, sp} + move_l {offsetted4, sp, 4}, {pre_dec4, sp} +with any4 any4 yields %2 %1 %2 %1 + +pat dup $1>8 +with STACK + uses DD_REG = {const, $1/4 -1} + gen 1: + move_l {offsetted4, sp, $1 -4}, {pre_dec4, sp} + dbf %a, {slabel, 1b} + +pat dus $1==4 +with DD_REG STACK + uses AA_REG = {regAregXcon, sp, %1, 1, 0} + gen asr_l {shconst, 2}, %1 + beq {slabel, 2f} + sub_l {const, 1}, %1 + 1: + move_l {pre_dec4, %a}, {pre_dec4, sp} + dbf %1, {slabel, 1b} + 2: + +pat exg $1==4 +with any4 any4 yields %1 %2 + +pat exg defined($1) +with STACK + gen move {const, $1}, d0 + jsr {absolute4, ".exg"} + +pat exg !defined($1) +with any4 STACK + gen move_l %1, d0 + jsr {absolute4, ".exg"} + +pat fil + gen move_l {ext_addr, $1}, {absolute4, ".filn"} + +pat gto +with STACK + uses AA_REG = {ext_addr, $1} + gen move_l {offsetted4, %a, 8}, lb + move_l {offsetted4, %a, 4}, sp +#ifdef m68020 + jmp {OFF_off4, %a, 0, 0} +#else m68020 + move_l {indirect4, %a}, %a + jmp {indirect4, %a} +#endif m68020 + +pat lim yields {absolute4, ".trpim"} + +pat lin + gen move {const, $1}, {absolute4, ".lino"} + +pat lni + gen add_l {const, 1}, {absolute4, ".lino"} + +pat lor $1==0 yields lb + +pat lor $1==1 +with STACK + uses AA_REG = sp yields %a + +pat lor $1==2 yields {absolute4, ".reghp"} + +pat lpb leaving adp 8 + +pat mon +with STACK + gen jsr {absolute4, ".mon"} + +pat nop +with STACK + gen jsr {absolute4, ".nop"} + +pat rck +#ifdef m68020 +with ext_addr D_REG + gen cmp2_l {absolute4, %1.bd}, %2 + bcc {slabel, 1f} + pea {absolute4, 1} /* push constant 1 == ERANGE */ + jsr {absolute4, ".trp"} + 1: yields %2 +with address-ext_addr D_REG + gen cmp2_l %1, %2 + bcc {slabel, 1f} + pea {absolute4, 1} /* push constant 1 == ERANGE */ + jsr {absolute4, ".trp"} + 1: yields %2 +with A_REG D_REG + gen cmp2_l {indirect4, %1}, %2 + bcc {slabel, 1f} + pea {absolute4, 1} /* push constant 1 == ERANGE */ + jsr {absolute4, ".trp"} + 1: yields %2 +#else m68020 +with STACK + gen jsr {absolute4, ".rck"} +#endif m68020 + +pat rtt leaving ret 0 + +pat sig +with any4 + uses AA_REG + gen move {absolute4, ".trppc"}, %a + move %1, {absolute4, ".trppc"} + yields %a + +pat sim +with any4 + gen move_l %1, {absolute4, ".trpim"} + +pat str $1==0 +with any4 +#ifdef m68020 + kills LOCAL, ILOCAL, all_regind %reg==lb, local_addr +#else m68020 + kills LOCAL, all_regind %reg==lb, local_addr +#endif m68020 + gen move %1, lb + +pat str $1==1 +with any4 STACK + gen move %1, sp + +pat str $1==2 +with STACK + gen jsr {absolute4, ".strhp"} + +pat trp +with STACK + gen jsr {absolute4, ".trp"} + + + +/************************************************ + * rules for long EM-patterns * + ************************************************/ + +proc lolxxxstl example lol adi stl +with conreg4 + kills all_indir, LOCAL %bd==$1 + gen xxx* %1, {LOCAL, $1} + +proc loexxxste example loe adi ste +with conreg4 + kills posextern + gen xxx* %1, {absolute4, $1} + +proc lilxxxsil example lil adi sil +with conreg4 +#ifdef m68020 + kills allexceptcon + gen xxx* %1, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen xxx* %1, {indirect4, %a} +#endif m68020 + +proc lolcxxxstl example lol loc adi stl + kills all_indir, LOCAL %bd==$1 + gen xxx* {const, $2}, {LOCAL, $1} + +proc loecxxxste example loe loc adi ste + kills posextern + gen xxx* {const, $2}, {absolute4, $1} + +proc lilcxxxsil example lil loc adi sil +#ifdef m68020 + kills allexceptcon + gen xxx* {const, $2}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen xxx* {const, $2}, {indirect4, %a} +#endif m68020 + +proc lolrxxxstl example lol lol adi stl + kills all_indir, LOCAL %bd==$1 + gen xxx* {LOCAL, $2}, {LOCAL, $1} + +proc loerxxxste example loe lol adi ste + kills posextern + gen xxx* {LOCAL, $2}, {absolute4, $1} + +proc lilrxxxsil example lil lol adi sil +#ifdef m68020 + kills allexceptcon + gen xxx* {LOCAL, $2}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen xxx* {LOCAL, $2}, {indirect4, %a} +#endif m68020 + +pat lol adi stl $1==$3 && $2==4 call lolxxxstl("add.l") +pat loe adi ste $1==$3 && $2==4 call loexxxste("add.l") +pat lil adi sil $1==$3 && $2==4 call lilxxxsil("add.l") +pat lol loc adi stl $1==$4 && $3==4 call lolcxxxstl("add.l") +pat loe loc adi ste $1==$4 && $3==4 call loecxxxste("add.l") +pat lil loc adi sil $1==$4 && $3==4 call lilcxxxsil("add.l") +pat lol lol adi stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("add.l") +pat loe lol adi ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("add.l") +pat lil lol adi sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("add.l") + +pat lol adu stl $1==$3 && $2==4 call lolxxxstl("add.l") +pat loe adu ste $1==$3 && $2==4 call loexxxste("add.l") +pat lil adu sil $1==$3 && $2==4 call lilxxxsil("add.l") +pat lol loc adu stl $1==$4 && $3==4 call lolcxxxstl("add.l") +pat loe loc adu ste $1==$4 && $3==4 call loecxxxste("add.l") +pat lil loc adu sil $1==$4 && $3==4 call lilcxxxsil("add.l") +pat lol lol adu stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("add.l") +pat loe lol adu ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("add.l") +pat lil lol adu sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("add.l") + + +pat lol adp stl $1==$3 + kills all_indir, LOCAL %bd==$1 + gen add_l {const, $2}, {LOCAL, $1} + +pat lil adp sil $1==$3 + kills allexceptcon +#ifdef m68020 + gen add_l {const, $2}, {ILOCAL, $1} +#else m68020 + uses AA_REG = {LOCAL, $1} + gen add_l {const, $2}, {indirect4, %a} +#endif m68020 + +pat loe adp ste $1==$3 + kills posextern + gen add_l {const, $2}, {absolute4, $1} + +pat lol lol adp stl $1==$2 && $1==$4 + kills all_indir, LOCAL %bd==$1 + uses AA_REG = {LOCAL, $1} + gen add_l {const, $3}, {LOCAL, $1} + yields %a + +pat lil lil adp sti $1==$2 && $1==$4 + kills allexceptcon +#ifdef m68020 + uses AA_REG = {ILOCAL, $1} + gen add_l {const, $3}, {ILOCAL, $1} +#else m68020 + uses AA_REG, AA_REG = {LOCAL, $1} + gen move {indirect4, %b}, %a + add_l {const, $3}, {indirect4, %b} +#endif m68020 + yields %a + +pat loe loe adp ste $1==$2 && $1==$4 + kills posextern + uses AA_REG = {absolute4, $1} + gen add_l {const, $3}, {absolute4, $1} + yields %a + + +pat lol loc sbi stl $1==$4 && $3==4 call lolcxxxstl("sub.l") +pat loe loc sbi ste $1==$4 && $3==4 call loecxxxste("sub.l") +pat lil loc sbi sil $1==$4 && $3==4 call lilcxxxsil("sub.l") +pat lol lol sbi stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("sub.l") +pat loe lol sbi ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("sub.l") +pat lil lol sbi sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("sub.l") + +pat lol loc sbu stl $1==$4 && $3==4 call lolcxxxstl("sub.l") +pat loe loc sbu ste $1==$4 && $3==4 call loecxxxste("sub.l") +pat lil loc sbu sil $1==$4 && $3==4 call lilcxxxsil("sub.l") +pat lol lol sbu stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("sub.l") +pat loe lol sbu ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("sub.l") +pat lil lol sbu sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("sub.l") + +pat lol and stl $1==$3 && $2==4 call lolxxxstl("and.l") +pat loe and ste $1==$3 && $2==4 call loexxxste("and.l") +pat lil and sil $1==$3 && $2==4 call lilxxxsil("and.l") +pat lol loc and stl $1==$4 && $3==4 call lolcxxxstl("and.l") +pat loe loc and ste $1==$4 && $3==4 call loecxxxste("and.l") +pat lil loc and sil $1==$4 && $3==4 call lilcxxxsil("and.l") +pat lol lol and stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("and.l") +pat loe lol and ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("and.l") +pat lil lol and sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("and.l") + +pat lol ior stl $1==$3 && $2==4 call lolxxxstl("or.l") +pat loe ior ste $1==$3 && $2==4 call loexxxste("or.l") +pat lil ior sil $1==$3 && $2==4 call lilxxxsil("or.l") +pat lol loc ior stl $1==$4 && $3==4 call lolcxxxstl("or.l") +pat loe loc ior ste $1==$4 && $3==4 call loecxxxste("or.l") +pat lil loc ior sil $1==$4 && $3==4 call lilcxxxsil("or.l") +pat lol lol ior stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("or.l") +pat loe lol ior ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("or.l") +pat lil lol ior sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("or.l") + +pat lol xor stl $1==$3 && $2==4 call lolxxxstl("eor.l") +pat loe xor ste $1==$3 && $2==4 call loexxxste("eor.l") +pat lil xor sil $1==$3 && $2==4 call lilxxxsil("eor.l") +pat lol loc xor stl $1==$4 && $3==4 call lolcxxxstl("eor.l") +pat loe loc xor ste $1==$4 && $3==4 call loecxxxste("eor.l") +pat lil loc xor sil $1==$4 && $3==4 call lilcxxxsil("eor.l") +pat lol lol xor stl $1==$4 && $3==4 && inreg($2)==reg_any + call lolrxxxstl("eor.l") +pat loe lol xor ste $1==$4 && $3==4 && inreg($2)==reg_any + call loerxxxste("eor.l") +pat lil lol xor sil $1==$4 && $3==4 && inreg($2)==reg_any + call lilrxxxsil("eor.l") + +proc llol1shstl example lol loc sli stl /* only left */ + kills all_indir, LOCAL %bd==$1 + gen shw* {offsetted2, lb, $1+2} + roxl {offsetted2, lb, $1} + +proc lloe1shste example loe loc sli ste /* only left */ + kills posextern + gen shw* {absolute2, $1+2} + roxl {absolute2, $1} + +proc llil1shsil example lil loc sli sil /* only left */ +#ifdef m68020 + kills allexceptcon + gen shw* {OFF_off2, lb, $1, 2} + roxl {OFF_off2, lb, $1, 0} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen shw* {offsetted2, %a, 2} + roxl {indirect2, %a} +#endif m68020 + +proc rlol1shstl example lol loc sri stl /* only right */ + kills all_indir, LOCAL %bd==$1 + gen shw* {offsetted2, lb, $1} + roxr {offsetted2, lb, $1+2} + +proc rloe1shste example loe loc sri ste /* only right */ + kills posextern + gen shw* {absolute2, $1} + roxr {absolute2, $1+2} + +proc rlil1shsil example lil loc sri sil /* only right */ +#ifdef m68020 + kills allexceptcon + gen shw* {OFF_off2, lb, $1, 0} + roxr {OFF_off2, lb, $1, 2} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen shw* {indirect2, %a} + roxr {offsetted2, %a, 2} +#endif m68020 + +pat lol loc sli stl $1==$4 && $2==1 && $3==4 call llol1shstl("asl #1,") +pat loe loc sli ste $1==$4 && $2==1 && $3==4 call lloe1shste("asl #1,") +pat lil loc sli sil $1==$4 && $2==1 && $3==4 call llil1shsil("asl #1,") +pat lol loc sri stl $1==$4 && $2==1 && $3==4 call rlol1shstl("asr #1,") +pat loe loc sri ste $1==$4 && $2==1 && $3==4 call rloe1shste("asr #1,") +pat lil loc sri sil $1==$4 && $2==1 && $3==4 call rlil1shsil("asr #1,") +pat lol loc slu stl $1==$4 && $2==1 && $3==4 call llol1shstl("asl #1,") +pat loe loc slu ste $1==$4 && $2==1 && $3==4 call lloe1shste("asl #1,") +pat lil loc slu sil $1==$4 && $2==1 && $3==4 call llil1shsil("asl #1,") +pat lol loc sru stl $1==$4 && $2==1 && $3==4 call rlol1shstl("lsr #1,") +pat loe loc sru ste $1==$4 && $2==1 && $3==4 call rloe1shste("lsr #1,") +pat lil loc sru sil $1==$4 && $2==1 && $3==4 call rlil1shsil("lsr #1,") + +proc locsh example loc sli +with DD_REG + gen sh* {shconst, $1}, %1 + yields %1 + +pat loc sli small($1) && $2==4 call locsh("asl.l") +pat loc sri small($1) && $2==4 call locsh("asr.l") +pat loc slu small($1) && $2==4 call locsh("asl.l") +pat loc sru small($1) && $2==4 call locsh("lsr.l") +pat loc rol small($1) && $2==4 call locsh("rol.l") +pat loc ror small($1) && $2==4 call locsh("ror.l") + +proc lolbitstl example lol ngi stl + kills all_indir, LOCAL %bd==$1 + gen bit* {LOCAL, $1} + +proc loebitste example loe ngi ste + kills posextern + gen bit* {absolute4, $1} + +proc lilbitsil example lil ngi sil +#ifdef m68020 + kills allexceptcon + gen bit* {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen bit* {indirect4, %a} +#endif m68020 + +pat lol ngi stl $1==$3 && $2==4 call lolbitstl("neg.l") +pat loe ngi ste $1==$3 && $2==4 call loebitste("neg.l") +pat lil ngi sil $1==$3 && $2==4 call lilbitsil("neg.l") +pat lol com stl $1==$3 && $2==4 call lolbitstl("not.l") +pat loe com ste $1==$3 && $2==4 call loebitste("not.l") +pat lil com sil $1==$3 && $2==4 call lilbitsil("not.l") + +pat lil inc sil $1==$3 +#ifdef m68020 + kills allexceptcon + gen add_l {const, 1}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen add_l {const, 1}, {indirect4, %a} +#endif m68020 + +pat lil dec sil $1==$3 +#ifdef m68020 + kills allexceptcon + gen sub_l {const, 1}, {ILOCAL, $1} +#else m68020 + kills allexceptcon + uses AA_REG = {LOCAL, $1} + gen sub_l {const, 1}, {indirect4, %a} +#endif m68020 + + +proc txxand +with test_set DD_REG + gen test %1 + bxx* {slabel, 1f} + clr_l %2 + 1: yields %2 + +proc txxior +with test_set DD_REG + gen test %1 + bxx* {slabel, 1f} + bset {const, 0}, %2 + 1: yields %2 + +pat tlt and $2==4 call txxand("blt") +pat tle and $2==4 call txxand("ble") +pat teq and $2==4 call txxand("beq") +pat tne and $2==4 call txxand("bne") +pat tge and $2==4 call txxand("bge") +pat tgt and $2==4 call txxand("bgt") + +pat tlt ior $2==4 call txxior("bge") +pat tle ior $2==4 call txxior("bgt") +pat teq ior $2==4 call txxior("bne") +pat tne ior $2==4 call txxior("beq") +pat tge ior $2==4 call txxior("blt") +pat tgt ior $2==4 call txxior("ble") + +proc cmxtxxand +with any4 genreg DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %3 + 1: yields %3 +with genreg any4-genreg DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %3 + 1: yields %3 +with exact immediate4 imm_cmp4 DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %3 + 1: yields %3 +with exact imm_cmp4 immediate4 DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %3 + 1: yields %3 + +proc cmxtxxior +with any4 genreg DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 +with genreg any4-genreg DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 +with exact immediate4 imm_cmp4 DD_REG + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 +with exact imm_cmp4 immediate4 DD_REG + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + move {const, 1}, %3 + 1: yields %3 + +proc cmxtxx +with any4 genreg + uses DD_REG = {const, 1} + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %a + 1: yields %a +with genreg any4-genreg + uses DD_REG = {const, 1} + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %a + 1: yields %a +with exact immediate4 imm_cmp4 + uses DD_REG = {const, 1} + gen cmp_l %1, %2 + bxx[1] {slabel, 1f} + clr_l %a + 1: yields %a +with exact imm_cmp4 immediate4 + uses DD_REG = {const, 1} + gen cmp_l %2, %1 + bxx[2] {slabel, 1f} + clr_l %a + 1: yields %a +with genreg STACK + uses DD_REG = {const, 1} + gen cmp_l {post_inc4, sp}, %1 + bxx[2] {slabel, 1f} + clr_l %a + 1: yields %a +with exact immediate4 STACK + uses DD_REG = {const, 1} + gen cmp_l %1, {post_inc4, sp} + bxx[1] {slabel, 1f} + clr_l %a + 1: yields %a + +pat cmi tlt and $1==4 && $3==4 call cmxtxxand("blt","bgt") +pat cmi tle and $1==4 && $3==4 call cmxtxxand("ble","bge") +pat cmi teq and $1==4 && $3==4 call cmxtxxand("beq","beq") +pat cmi tne and $1==4 && $3==4 call cmxtxxand("bne","bne") +pat cmi tge and $1==4 && $3==4 call cmxtxxand("bge","ble") +pat cmi tgt and $1==4 && $3==4 call cmxtxxand("bgt","blt") + +pat cmu tlt and $1==4 && $3==4 call cmxtxxand("bcs","bhi") +pat cmu tle and $1==4 && $3==4 call cmxtxxand("bls","bcc") +pat cmu teq and $1==4 && $3==4 call cmxtxxand("beq","beq") +pat cmu tne and $1==4 && $3==4 call cmxtxxand("bne","bne") +pat cmu tge and $1==4 && $3==4 call cmxtxxand("bcc","bls") +pat cmu tgt and $1==4 && $3==4 call cmxtxxand("bhi","bcs") + +pat cmi tlt ior $1==4 && $3==4 call cmxtxxior("bge","ble") +pat cmi tle ior $1==4 && $3==4 call cmxtxxior("bgt","blt") +pat cmi teq ior $1==4 && $3==4 call cmxtxxior("bne","bne") +pat cmi tne ior $1==4 && $3==4 call cmxtxxior("beq","beq") +pat cmi tge ior $1==4 && $3==4 call cmxtxxior("blt","bgt") +pat cmi tgt ior $1==4 && $3==4 call cmxtxxior("ble","bge") + +pat cmu tlt ior $1==4 && $3==4 call cmxtxxior("bcc","bls") +pat cmu tle ior $1==4 && $3==4 call cmxtxxior("bhi","bcs") +pat cmu teq ior $1==4 && $3==4 call cmxtxxior("bne","bne") +pat cmu tne ior $1==4 && $3==4 call cmxtxxior("beq","beq") +pat cmu tge ior $1==4 && $3==4 call cmxtxxior("bcs","bhi") +pat cmu tgt ior $1==4 && $3==4 call cmxtxxior("bls","bcc") + +pat cmi tlt $1==4 call cmxtxx("blt","bgt") +pat cmi tle $1==4 call cmxtxx("ble","bge") +pat cmi teq $1==4 call cmxtxx("beq","beq") +pat cmi tne $1==4 call cmxtxx("bne","bne") +pat cmi tge $1==4 call cmxtxx("bge","blt") +pat cmi tgt $1==4 call cmxtxx("bgt","blt") + +pat cmu tlt $1==4 call cmxtxx("bcs","bhi") +pat cmu tle $1==4 call cmxtxx("bls","bcc") +pat cmu teq $1==4 call cmxtxx("beq","beq") +pat cmu tne $1==4 call cmxtxx("bne","bne") +pat cmu tge $1==4 call cmxtxx("bcc","bls") +pat cmu tgt $1==4 call cmxtxx("bhi","bcs") + +proc cmxzxx example cmu zlt +with any4 genreg STACK + gen cmp_l %1, %2 + bxx[1] {llabel, $2} +with genreg any4-genreg STACK + gen cmp_l %2, %1 + bxx[2] {llabel, $2} +with exact immediate4 imm_cmp4 + kills ALL + gen cmp_l %1, %2 + bxx[1] {llabel, $2} +with exact imm_cmp4 immediate4 + kills ALL + gen cmp_l %2, %1 + bxx[2] {llabel, $2} +with genreg STACK + gen cmp_l {post_inc4, sp}, %1 + bxx[2] {llabel, $2} +with exact immediate4 STACK + gen cmp_l %1, {post_inc4, sp} + bxx[1] {llabel, $2} + +pat cmu zlt $1==4 call cmxzxx("bcs","bhi") +pat cmu zle $1==4 call cmxzxx("bls","bcc") +pat cmu zeq $1==4 call cmxzxx("beq","beq") +pat cmu zne $1==4 call cmxzxx("bne","bne") +pat cmu zge $1==4 call cmxzxx("bcc","bls") +pat cmu zgt $1==4 call cmxzxx("bhi","bcs") + + +proc bxx1_in example loc loc cii loc bne +with imm_cmp1 STACK + gen cmp_b {const, lowb($4)}, %1 + bxx* {llabel, $5} + +proc bxx2_in example loc loc cii loc bne +with imm_cmp2 STACK + gen cmp_w {const, loww($4)}, %1 + bxx* {llabel, $5} + +pat loc loc cii loc blt $1==1 && $2==4 && in_1($4) call bxx1_in("blt") +pat loc loc cii loc ble $1==1 && $2==4 && in_1($4) call bxx1_in("ble") +pat loc loc cii loc beq $1==1 && $2==4 && in_1($4) call bxx1_in("beq") +pat loc loc cii loc bne $1==1 && $2==4 && in_1($4) call bxx1_in("bne") +pat loc loc cii loc bge $1==1 && $2==4 && in_1($4) call bxx1_in("bge") +pat loc loc cii loc bgt $1==1 && $2==4 && in_1($4) call bxx1_in("bgt") + +pat loc loc cii loc blt $1==2 && $2==4 && in_2($4) call bxx2_in("blt") +pat loc loc cii loc ble $1==2 && $2==4 && in_2($4) call bxx2_in("ble") +pat loc loc cii loc beq $1==2 && $2==4 && in_2($4) call bxx2_in("beq") +pat loc loc cii loc bne $1==2 && $2==4 && in_2($4) call bxx2_in("bne") +pat loc loc cii loc bge $1==2 && $2==4 && in_2($4) call bxx2_in("bge") +pat loc loc cii loc bgt $1==2 && $2==4 && in_2($4) call bxx2_in("bgt") + +pat loc loc cii $1==1 && $2==2 +with DD_REG + gen ext_w %1 yields %1 + +pat loc loc cii $1==2 && $2==4 +with DD_REG + gen ext_l %1 yields %1 + +pat loc loc cii $1==1 && $2==4 +with DD_REG +#ifdef m68020 + gen extb_l %1 yields %1 +#else m68020 + gen ext_w %1 + ext_l %1 yields %1 +#endif m68020 + +pat loc loc ciu $1==$2 /* skip this */ +pat loc loc cui $1==$2 /* skip this */ + + +/* The following rules should be handled by the peephole optimizer, I think */ + +pat loc dvi $1==2 && $2==4 leaving loc 1 sri 4 +pat loc dvi $1==4 && $2==4 leaving loc 2 sri 4 +pat loc dvi $1==8 && $2==4 leaving loc 3 sri 4 +pat loc dvi $1==16 && $2==4 leaving loc 4 sri 4 +pat loc dvi $1==32 && $2==4 leaving loc 5 sri 4 +pat loc dvi $1==64 && $2==4 leaving loc 6 sri 4 +pat loc dvi $1==128 && $2==4 leaving loc 7 sri 4 +pat loc dvi $1==256 && $2==4 leaving loc 8 sri 4 + +pat loc dvu $1==2 && $2==4 leaving loc 1 sru 4 +pat loc dvu $1==4 && $2==4 leaving loc 2 sru 4 +pat loc dvu $1==8 && $2==4 leaving loc 3 sru 4 +pat loc dvu $1==16 && $2==4 leaving loc 4 sru 4 +pat loc dvu $1==32 && $2==4 leaving loc 5 sru 4 +pat loc dvu $1==64 && $2==4 leaving loc 6 sru 4 +pat loc dvu $1==128 && $2==4 leaving loc 7 sru 4 +pat loc dvu $1==256 && $2==4 leaving loc 8 sru 4