OpenBSD-4.6/usr.bin/pcc/m16c/table.c
/* $OpenBSD: table.c,v 1.1 2007/10/07 17:58:51 otto Exp $ */
#include "pass2.h"
# define ANYSIGNED TINT|TLONG|TCHAR
# define ANYUSIGNED TUNSIGNED|TULONG|TUCHAR
# define ANYFIXED ANYSIGNED|ANYUSIGNED
# define TL TLONG|TULONG
# define TWORD TUNSIGNED|TINT
# define TCH TCHAR|TUCHAR
struct optab table[] = {
/* First entry must be an empty entry */
{ -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", },
/* (signed) char -> int/pointer */
{ SCONV, INAREG,
SCREG, TCHAR,
SANY, TINT|TPOINT,
NAREG, RESC1,
" mov.b AL, A1\n\texts.b A1\n", },
/* (unsigned) char -> int/pointer */
{ SCONV, INAREG,
SCREG, TUCHAR,
SANY, TINT|TPOINT,
NAREG, RESC1,
" mov.b AL, A1\n", },
/* unsigned char -> long */
{ SCONV, INAREG,
SCREG, TUCHAR,
SANY, TL,
NAREG|NASL, RESC1,
" mov.b AL, A1\n mov.w #0,U1\n", },
/* int or pointer -> (unsigned) long */
{ SCONV, INAREG,
SAREG|SNAME, TWORD|TPOINT,
SANY, TL,
NAREG|NASL, RESC1,
" mov.w AL,A1\n mov.w #0,U1\n", },
/* char -> (signed) long */
{ SCONV, INAREG,
SAREG|SNAME, TCHAR,
SANY, TLONG,
NAREG|NASL, RESC1,
" exts.b AL\n exts.w AL\n", },
/* long -> ulong */
{ SCONV, INAREG,
SAREG, TL,
SANY, TL,
0, RLEFT,
"", },
/* long -> int or pointer */
{ SCONV, INAREG,
SAREG|SOREG|SNAME, TL,
SANY, TWORD|TPOINT,
NAREG|NASL, RESC1,
" mov.w AL,A1\n", },
/* int -> char */
{ SCONV, INCREG,
SAREG, TWORD,
SANY, TCH,
NCREG, RESC1,
" mov.b AL, A1\n", },
/* int -> long */
{ SCONV, INAREG,
SAREG, TWORD,
SANY, TLONG,
NAREG|NASL, RESC1,
" exts.w AL", },
/* long -> char */
{ SCONV, INAREG,
SAREG, TL,
SANY, TCH,
NAREG|NASL, RESC1,
"", },
{ SCONV, INAREG,
SAREG, TPOINT,
SANY, TWORD,
0, RLEFT,
"", },
{ PLUS, INAREG|FOREFF,
SAREG, TL,
SCON|SNAME|SOREG, TL,
0, RLEFT,
" add.w AR,AL\n adc.w UR,UL\n", },
{ MINUS, INAREG|FOREFF,
SAREG, TL,
SCON|SNAME|SOREG, TL,
0, RLEFT,
" sub.w AR,AL\n sbb.w UR,UL\n", },
{ AND, INAREG|FOREFF,
SAREG, TL,
SAREG|SNAME|SOREG, TL,
0, RLEFT,
" and.w AR,AL\n and.w UR,UL\n", },
{ ER, INAREG|FOREFF,
SAREG, TL,
SAREG|SNAME|SOREG, TL,
0, RLEFT,
" xor.w AR,AL\n xor.w UR,UL\n", },
{ OR, INAREG|FOREFF,
SAREG, TL,
SAREG|SNAME|SOREG, TL,
0, RLEFT,
" xor.w AR,AL\n xor.w UR,UL\n", },
{ COMPL, INAREG|FOREFF,
SAREG, TL,
SAREG|SNAME|SOREG, TL,
0, RLEFT,
" not.w AR,AL\n not.w UR,UL\n", },
{ OPSIMP, INAREG|FOREFF,
SAREG, TWORD|TPOINT,
SAREG|SNAME|SOREG|SCON, TWORD|TPOINT,
0, RLEFT,
" Ow AR,AL\n", },
/* XXX - Is this rule really correct? Having a SAREG shape seems kind of
strange. Doesn't work. Gives a areg as A1. */
#if 0
{ OPSIMP, INBREG,
SAREG, TWORD|TPOINT,
SAREG|SBREG|SNAME|SOREG|SCON, TWORD|TPOINT,
NBREG, RESC1,
" ++Ow AR,A1\n", },
#endif
{ OPSIMP, INBREG,
SBREG, TWORD|TPOINT,
SAREG|SBREG|SNAME|SOREG|SCON, TWORD|TPOINT,
0, RLEFT,
" Ow AR,AL\n", },
{ OPSIMP, INCREG|FOREFF,
SCREG, TCH,
SCREG|SNAME|SOREG|SCON, TCH,
0, RLEFT,
" Ob AR,AL\n", },
/* XXX - Do these work? check nspecial in order.c */
/* signed integer division */
{ DIV, INAREG,
SAREG, TINT,
SAREG|SNAME|SOREG, TWORD,
/*2*NAREG|NASL|*/NSPECIAL, RLEFT,
" div.w AR\n mov.w r0,AL\n", },
// " xor.w r2\n div.w AR\n", },
/* signed integer/char division - separate entry for FOREFF */
{ DIV, FOREFF,
SAREG, TINT,
SAREG|SNAME|SOREG, TWORD,
0, 0,
"", },
#if 0
/* signed char division */
{ DIV, INCREG,
SCREG, TCHAR,
SCREG|SNAME|SOREG, TCH,
2*NCREG|NCSL|NSPECIAL, RLEFT,
" div.b AR\n\tmov.b r0l,AL\n", },
// " xor.w r2\n div.w AR\n", },
#endif
/* signed integer modulus, equal to above */
{ MOD, INAREG,
SAREG, TINT,
SAREG|SNAME|SOREG, TWORD,
/*2*NAREG|NASL|*/NSPECIAL, RLEFT,
" div.w AR\n\tmov r2,AL\n", },
/* signed integer modulus - separate entry for FOREFF */
{ MOD, FOREFF,
SAREG, TINT,
SAREG|SNAME|SOREG, TWORD,
0, 0,
"", },
/* signed integer multiplication */
{ MUL, INAREG,
SAREG, TINT,
SAREG|SNAME|SOREG, TWORD,
2*NAREG|NASL|NSPECIAL, RESC1,
" mul.w AL,AR\n", },
{ MUL, FOREFF,
SAREG, TINT,
SAREG|SNAME|SOREG, TWORD,
0, 0,
"", },
#if 0
{ LS, INAREG,
SAREG, TWORD,
SCON, TANY,
0, RLEFT,
" shl.w AR,AL\n", },
#endif
{ LS, INAREG,
SAREG, TWORD,
SAREG, TWORD,
0, RLEFT,
" push.b r1h\n"
" mov.b AR,r1h\n"
" shl.w r1h,AL\n"
" pop.b r1h\n", },
{ LS, INAREG,
SAREG, TL,
SAREG, TWORD,
0, RLEFT,
" push.b r1h\n"
" mov.b AR,r1h\n"
" shl.l r1h,ZG\n"
" pop.b r1h\n", },
{ RS, INAREG,
SAREG, TWORD,
SAREG, TWORD,
0, RLEFT,
" push.b r1h\n"
" mov.b AR,r1h\n"
" neg.b r1h\n"
" shl.w r1h,AL\n"
" pop.b r1h\n", },
{ RS, INAREG,
SAREG, TL,
SAREG, TWORD,
0, RLEFT,
" push.b r1h\n"
" mov.b AR,r1h\n"
" neg.b r1h\n"
" shl.l r1h,ZG\n"
" pop.b r1h\n", },
#if 0
{ RS, INAREG,
SAREG, TUNSIGNED,
SCON, TANY,
0, RLEFT,
" shl ZA,AL\n", },
{ RS, INAREG,
SAREG, TINT,
SCON, TANY,
0, RLEFT,
" sha ZA,AL\n", },
#endif
{ OPLOG, FORCC,
SAREG|SBREG|SOREG|SNAME, TL,
SAREG|SBREG|SOREG|SNAME, TL,
0, 0,
"ZF", },
{ OPLOG, FORCC,
SBREG|SOREG, TWORD|TPOINT,
SCON, TWORD|TPOINT,
0, RESCC,
" cmp.w AR,AL\n", },
{ OPLOG, FORCC,
SAREG|SBREG|SOREG|SNAME, TWORD|TPOINT,
SAREG|SBREG|SOREG|SNAME, TWORD|TPOINT,
0, RESCC,
" cmp.w AR,AL\n", },
{ OPLOG, FORCC,
SCREG|SOREG|SNAME, TCH,
SCREG|SOREG|SNAME, TCH,
0, RESCC,
" cmp.b AR,AL\n", },
{ OPLOG, FORCC,
SCREG|SOREG|SNAME, TCH,
SCREG|SOREG|SNAME, TCH,
0, RESCC,
" cmp.b AR,AL\n", },
{ GOTO, FOREFF,
SCON, TANY,
SANY, TANY,
0, RNOP,
" jmp.w ZC\n", },
{ OPLTYPE, INAREG,
SANY, TANY,
SCON|SNAME|SOREG|SAREG, TL|TFTN,
NAREG, RESC1,
" mov.w AR,A1\n mov.w UR,U1\n", },
{ OPLTYPE, INAREG,
SANY, TANY,
SCON|SNAME|SOREG|SAREG|SBREG, TWORD|TPOINT,
NAREG, RESC1,
" mov.w AR,A1\n", },
{ OPLTYPE, INBREG,
SANY, TANY,
SBREG|SCON|SNAME|SOREG|SAREG, TWORD|TPOINT,
NBREG, RESC1,
" mov.w AR,A1\n", },
/*
{ OPLTYPE, INAREG,
SANY, TANY,
SCON|SNAME|SOREG, TCH,
NAREG, RESC1,
" mov.b AR, A1\n", },
{ OPLTYPE, INBREG,
SANY, TANY,
SCON|SNAME|SOREG, TCHAR|TUCHAR,
NBREG, RESC1,
" mov.b AR,A1\n", },
*/
{ OPLTYPE, INCREG,
SANY, TANY,
SCON|SNAME|SOREG, TCHAR|TUCHAR,
NCREG, RESC1,
" mov.b AR,A1\n", },
{ COMPL, INAREG,
SAREG, TWORD,
SANY, TANY,
0, RLEFT,
" not.w AL\n", },
{ COMPL, INCREG,
SCREG, TCH,
SANY, TANY,
0, RLEFT,
" not.b AL\n", },
/* Push function address */
{ FUNARG, FOREFF,
SCON, TFTN,
SANY, TANY,
0, RNULL,
"ZH", },
{ FUNARG, FOREFF,
SOREG, TFTN,
SANY, TANY,
0, RNULL,
"ZI", },
{ FUNARG, FOREFF,
SNAME|SAREG, TL|TFTN,
SANY, TANY,
0, RNULL,
" push.w UL\n push.w AL\n", },
{ FUNARG, FOREFF,
SCON|SAREG|SNAME|SOREG, TWORD|TPOINT,
SANY, TANY,
0, RNULL,
" push.w AL\n", },
{ FUNARG, FOREFF,
SAREG|SNAME|SOREG, TCHAR|TUCHAR,
SANY, TANY,
0, RNULL,
" push.b AL\n", },
/* Match function pointers first */
#if 0
{ ASSIGN, FOREFF,
SFTN, TWORD|TPOINT,
SFTN, TWORD|TPOINT,
NAREG, 0,
"ZD", },
#endif
{ ASSIGN, INAREG,
SAREG, TFTN,
SCON, TFTN,
0, RLEFT,
"ZD", },
{ ASSIGN, INBREG,
SBREG, TFTN,
SCON, TFTN,
0, RLEFT,
"ZD", },
{ ASSIGN, INAREG,
SAREG, TFTN,
SBREG|SAREG|SOREG|SNAME, TFTN,
0, RLEFT,
" mov.w AR,AL\n mov.w UR,UL\n", },
{ ASSIGN, INBREG,
SBREG, TFTN,
SBREG|SAREG|SOREG|SNAME, TFTN,
0, RLEFT,
" mov.w AR,AL\n mov.w UR,UL\n", },
{ ASSIGN, INAREG,
SBREG|SAREG|SOREG|SNAME, TFTN,
SAREG, TFTN,
0, RRIGHT,
" mov.w AR,AL\n mov.w UR,UL\n", },
{ ASSIGN, INBREG,
SBREG|SAREG|SOREG|SNAME, TFTN,
SBREG, TFTN,
0, RRIGHT,
" mov.w AR,AL\n mov.w UR,UL\n", },
/* a reg -> a reg */
{ ASSIGN, FOREFF|INAREG,
SAREG, TWORD|TPOINT,
SAREG, TWORD|TPOINT,
0, RLEFT,
" mov.w AR,AL\n", },
{ ASSIGN, INAREG,
SBREG|SAREG|SOREG|SNAME, TL,
SAREG, TL,
0, RRIGHT,
" mov.w AR,AL\n mov.w UR,UL\n", },
{ ASSIGN, INBREG,
SBREG|SAREG|SOREG|SNAME, TL,
SBREG, TL,
0, RRIGHT,
" mov.w AR,AL\n mov.w UR,UL\n", },
{ ASSIGN, FOREFF,
SBREG|SAREG|SOREG|SNAME, TL,
SCON|SBREG|SAREG|SOREG|SNAME, TL,
0, 0,
" mov.w AR,AL\n mov.w UR,UL\n", },
{ ASSIGN, INAREG|FOREFF,
SAREG, TWORD|TPOINT,
SCON, TANY,
0, RLEFT,
" mov.w AR,AL\n", },
{ ASSIGN, INBREG|FOREFF,
SBREG, TWORD|TPOINT,
SCON, TANY,
0, RLEFT,
" mov.w AR,AL\n", },
{ ASSIGN, FOREFF,
SNAME|SOREG, TWORD|TPOINT,
SCON, TANY,
0, 0,
" mov.w AR,AL\n", },
/* char, oreg/name -> c reg */
{ ASSIGN, FOREFF|INCREG,
SCREG, TCHAR|TUCHAR,
SOREG|SNAME|SCON, TCHAR|TUCHAR,
0, RLEFT,
" mov.b AR,AL\n", },
/* int, oreg/name -> a reg */
{ ASSIGN, FOREFF|INAREG,
SAREG, TWORD|TPOINT,
SOREG|SNAME, TWORD|TPOINT,
0, RLEFT,
" mov.w AR,AL\n", },
{ ASSIGN, FOREFF|INBREG,
SBREG, TWORD|TPOINT,
SOREG|SNAME, TWORD|TPOINT,
0, RLEFT,
" mov.w AR,AL\n", },
{ ASSIGN, FOREFF|INAREG,
SOREG|SNAME, TWORD|TPOINT,
SAREG, TWORD|TPOINT,
0, RRIGHT,
" mov.w AR,AL\n", },
{ ASSIGN, FOREFF|INBREG,
SOREG|SNAME, TWORD|TPOINT,
SBREG, TWORD|TPOINT,
0, RRIGHT,
" mov.w AR,AL\n", },
{ ASSIGN, FOREFF|INCREG,
SOREG|SNAME, TCHAR|TUCHAR,
SCREG, TCHAR|TUCHAR,
0, RRIGHT,
" mov.b AR,AL\n", },
{ ASSIGN, FOREFF|INCREG,
SCREG, TCHAR|TUCHAR,
SCREG, TCHAR|TUCHAR,
0, RRIGHT,
" mov.b AR,AL\n", },
{ ASSIGN, FOREFF|INBREG,
SBREG, TWORD|TPOINT,
SBREG, TWORD|TPOINT,
0, RRIGHT,
" mov.w AR,AL\n", },
/*
{ MOVE, FOREFF|INAREG,
SAREG|SBREG, TWORD|TPOINT,
SAREG, TWORD|TPOINT,
NAREG, RESC1,
" mov.w AL, AR\n", },
*/
{ UMUL, INAREG,
SBREG, TPOINT|TWORD,
SANY, TFTN,
NAREG, RESC1,
" mov.w [AL],A1\n mov.w 2[AL],U1\n", },
{ UMUL, INAREG,
SBREG, TPOINT|TWORD,
SANY, TPOINT|TWORD,
NAREG, RESC1,
" mov.w [AL],A1\n", },
{ UMUL, INBREG,
SBREG, TPOINT|TWORD,
SANY, TPOINT|TWORD,
NBREG|NBSL, RESC1,
" mov.w [AL],A1\n", },
{ UMUL, INAREG,
SBREG, TCHAR|TUCHAR|TPTRTO,
SANY, TCHAR|TUCHAR,
NAREG, RESC1,
" mov.b [AL], A1\n", },
{ UCALL, FOREFF,
SCON, TANY,
SANY, TANY,
0, 0,
" jsr.w CL\nZB", },
{ UCALL, INAREG,
SCON, TANY,
SANY, TANY,
NAREG, RESC1,
" jsr.w CL\nZB", },
{ UCALL, INAREG,
SNAME|SOREG, TANY,
SANY, TANY,
NAREG|NASL, RESC1, /* should be 0 */
" jsri.a AL\nZB", },
{ UCALL, FOREFF,
SNAME|SOREG, TANY,
SANY, TANY,
0, 0,
" jsri.a AL\nZB", },
{ UCALL, INAREG,
SBREG, TANY,
SANY, TANY,
NAREG|NASL, RESC1, /* should be 0 */
" jsri.a [AL]\nZB", },
{ UCALL, FOREFF,
SBREG, TANY,
SANY, TANY,
0, 0,
" jsri.a [AL]\nZB", },
{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" },
};
int tablesize = sizeof(table)/sizeof(table[0]);