summaryrefslogtreecommitdiff
path: root/usr.bin/pcc/pdp10/table.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/pcc/pdp10/table.c')
-rw-r--r--usr.bin/pcc/pdp10/table.c1153
1 files changed, 1153 insertions, 0 deletions
diff --git a/usr.bin/pcc/pdp10/table.c b/usr.bin/pcc/pdp10/table.c
new file mode 100644
index 00000000000..4cd6ee44061
--- /dev/null
+++ b/usr.bin/pcc/pdp10/table.c
@@ -0,0 +1,1153 @@
+/* $OpenBSD: table.c,v 1.1 2007/10/07 17:58:52 otto Exp $ */
+/*
+ * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+# include "pass2.h"
+
+# define TLL TLONGLONG|TULONGLONG
+# define ANYSIGNED TINT|TLONG|TSHORT|TCHAR
+# define ANYUSIGNED TUNSIGNED|TULONG|TUSHORT|TUCHAR
+# define ANYFIXED ANYSIGNED|ANYUSIGNED
+# define TUWORD TUNSIGNED|TULONG
+# define TSWORD TINT|TLONG
+# define TWORD TUWORD|TSWORD
+
+struct optab table[] = {
+{ -1, FORREW,SANY,TANY,SANY,TANY,REWRITE,-1,"", },
+/*
+ * A bunch of pointer conversions.
+ * First pointer to integer.
+ */
+/* Convert char pointer to int */
+{ SCONV, INTAREG,
+ SAREG|STAREG, TPTRTO|TCHAR|TUCHAR,
+ SANY, TWORD,
+ NAREG, RLEFT,
+ " lsh AL,2\n"
+ " move A1,AL\n"
+ " lsh A1,-040\n"
+ " trz A1,074\n"
+ " ior AL,A1\n"
+ " tlz AL,0740000\n", },
+
+/* Convert short pointer to int */
+{ SCONV, INTAREG,
+ SAREG|STAREG, TPTRTO|TSHORT|TUSHORT,
+ SANY, TWORD,
+ NAREG, RLEFT,
+ " lsh AL,2\n"
+ " move A1,AL\n"
+ " lsh A1,-041\n"
+ " trz A1,2\n"
+ " ior AL,A1\n"
+ " tlz AL,0740000\n", },
+
+/* Convert int/unsigned/long/ulong/struct/union/func ptr to int */
+{ SCONV, INTAREG,
+ SAREG|STAREG, TPTRTO|TWORD|TSTRUCT|TPOINT,
+ SANY, TWORD,
+ 0, RLEFT,
+ " lsh AL,2\n", },
+
+/*
+ * Convert int/long to pointers.
+ */
+/* Convert int to char pointer */
+{ PCONV, INTAREG,
+ STAREG, TWORD,
+ SANY, TPTRTO|TCHAR|TUCHAR,
+ NAREG, RLEFT,
+ " move A1,AL\n"
+ " lsh A1,036\n"
+ " tlo A1,0700000\n"
+ " tlz A1,0040000\n"
+ " lsh AL,-2\n"
+ " ior AL,A1\n", },
+
+/* Convert int/long to short pointer */
+{ PCONV, INTAREG,
+ STAREG, TWORD,
+ SANY, TPTRTO|TSHORT|TUSHORT,
+ NAREG, RLEFT,
+ " move A1,AL\n"
+ " lsh AL,-2\n"
+ " tlo AL,0750000\n"
+ " lsh A1,035\n"
+ " tlz A1,0760000\n"
+ " add AL,A1\n", },
+
+/* Convert int/long to int/struct/multiple ptr */
+{ PCONV, INTAREG,
+ STAREG, TWORD,
+ SANY, TPOINT|TWORD|TSTRUCT,
+ 0, RLEFT,
+ " lsh AL,-2\n", },
+
+/*
+ * Pointer to pointer conversions.
+ */
+/* Convert char ptr to short ptr */
+{ PCONV, INTAREG,
+ STAREG, TPTRTO|TCHAR|TUCHAR,
+ SANY, TPTRTO|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " tlo AL,050000\n"
+ " tlne AL,020000\n"
+ " tlz AL,010000\n", },
+
+/* Convert char/short pointer to int/struct/multiple ptr */
+{ PCONV, INTAREG,
+ STAREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SANY, TPOINT|TWORD|TSTRUCT,
+ 0, RLEFT,
+ " tlz AL,0770000\n", },
+
+/* Convert short pointer to char ptr */
+{ PCONV, INTAREG,
+ STAREG, TPTRTO|TSHORT|TUSHORT,
+ SANY, TPTRTO|TCHAR|TUCHAR,
+ 0, RLEFT,
+ " tlz AL,050000\n", },
+
+/* Convert int/struct/foo pointer to char ptr */
+{ PCONV, INTAREG,
+ STAREG, TPOINT|TWORD|TSTRUCT,
+ SANY, TPTRTO|TCHAR|TUCHAR,
+ 0, RLEFT,
+ " tlo AL,0700000\n", },
+
+/* Convert int/struct/foo pointer to short ptr */
+{ PCONV, INTAREG,
+ STAREG, TPTRTO|TWORD|TSTRUCT,
+ SANY, TPTRTO|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " tlo AL,0750000\n", },
+
+/*
+ * A bunch conversions of integral<->integral types
+ */
+
+/* convert short/char to int. This is done when register is loaded */
+{ SCONV, INTAREG,
+ STAREG, TSHORT|TUSHORT|TCHAR|TUCHAR|TWORD,
+ SANY, TWORD,
+ 0, RLEFT,
+ "", },
+
+/* convert int to short/char. This is done when register is loaded */
+{ SCONV, INTAREG,
+ STAREG, TWORD,
+ SANY, TSHORT|TUSHORT|TCHAR|TUCHAR|TWORD,
+ 0, RLEFT,
+ "", },
+
+/* convert int/long to unsigned long long */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SANY, TULONGLONG,
+ NAREG|NASL, RESC1,
+ " move U1,AL\n"
+ " setz A1,\n"
+ " tlze U1,0400000\n"
+ " tro A1,01\n" , },
+
+/* convert int/long to long long */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SANY, TLONGLONG,
+ NAREG|NASL, RESC1,
+ " move U1,AL\n"
+ " move A1,U1\n"
+ " ash A1,-043\n", },
+
+/* convert uchar/ushort to (unsigned) long long */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TUCHAR|TUSHORT,
+ SANY, TLL,
+ NAREG|NASL, RESC1,
+ " move U1,AL\n"
+ " setz A1,\n", },
+
+/* convert long long to int/long */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SANY, TWORD,
+ NAREG|NASL, RESC1,
+ " move A1,UL\n", },
+
+/* convert long long to unsigned char - XXX - signed char */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SANY, TCHAR|TUCHAR,
+ NAREG|NASL, RESC1,
+ " move A1,UL\n"
+ " andi A1,0777\n", },
+
+/* convert long long to short - XXX - signed short */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SANY, TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " move A1,UL\n"
+ " hrrz A1,A1\n", },
+
+/* floating point conversions */
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TDOUBLE|TFLOAT,
+ SANY, TWORD,
+ NAREG|NASL, RESC1,
+ " fix A1,AL\n", },
+
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SANY, TFLOAT,
+ NAREG|NASL, RESC1,
+ " fltr A1,AL\n", },
+
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SANY, TDOUBLE,
+ NAREG|NASL, RESC1,
+ " fltr A1,AL\n setz U1,\n", },
+
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TDOUBLE,
+ SANY, TFLOAT,
+ NAREG|NASL, RESC1,
+ " move A1,AL\n", },
+
+{ SCONV, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TFLOAT,
+ SANY, TDOUBLE,
+ NAREG|NASL, RESC1,
+ " move A1,AL\n setz U1,\n", },
+
+/*
+ * Store constant initializers.
+ */
+{ INIT, FOREFF,
+ SCON, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SANY, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RNOP,
+ " .long Zd\n", },
+{ INIT, FOREFF,
+ SCON, TANY,
+ SANY, TWORD|TPOINT,
+ 0, RNOP,
+ " .long CL\n", },
+
+{ INIT, FOREFF,
+ SCON, TANY,
+ SANY, TLL,
+ 0, RNOP,
+ " .long UL\n .long CL\n", },
+
+/*
+ * Subroutine calls.
+ */
+
+{ UCALL, INTAREG,
+ SCON, TANY,
+ SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TDOUBLE|TLL|TPOINT,
+ NAREG, RESC1, /* should be 0 */
+ " pushj 017,AL\nZB", },
+
+{ UCALL, INTAREG,
+ SAREG|STAREG, TANY,
+ SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TDOUBLE|TLL|TPOINT,
+ NAREG|NASL, RESC1, /* should be 0 */
+ " pushj 017,(AL)\nZB", },
+
+{ UCALL, INTAREG,
+ SNAME|SOREG, TANY,
+ SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TDOUBLE|TLL|TPOINT,
+ NAREG, RESC1, /* should be 0 */
+ " pushj 017,@AL\nZB", },
+
+/*
+ * MOVE nodes are usually inserted late (at register assignment).
+ */
+{ MOVE, FOREFF,
+ SANY, TWORD,
+ STAREG|SAREG|SNAME|SOREG, TWORD,
+ 0, RRIGHT,
+ " move AR,AL\n", },
+
+{ MOVE, FOREFF,
+ SANY, TLL,
+ STAREG|SAREG|SNAME|SOREG, TLL,
+ 0, RRIGHT,
+ " dmove AR,AL\n", },
+
+/*
+ * INCR can be slightly optimized.
+ */
+{ INCR, INTAREG,
+ STAREG|SAREG|SNAME|SOREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO,
+ SONE, TANY,
+ NAREG, RESC1,
+ " move A1,AL\n"
+ " ibp AL\n", },
+
+#ifdef notyet
+/* Fix check of return value */
+{ INCR, FOREFF,
+ STAREG|SAREG|SNAME|SOREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO,
+ SONE, TANY,
+ 0, 0,
+ " ibp AL\n", },
+#endif
+
+/*
+ * PLUS operators.
+ */
+/* Add a value to a char/short pointer */
+{ PLUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TWORD,
+ 0, RRIGHT,
+ " adjbp AR,AL\n", },
+
+/* No more search for char/short pointer addition */
+{ PLUS, INAREG|INTAREG|FOREFF,
+ SANY, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE!\n", },
+
+/* Add char/short/int to register */
+{ PLUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " add AL,AR\n", },
+
+/* Add char/short/int to memory */
+{ PLUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SAREG|STAREG, TWORD,
+ 0, RLEFT,
+ " addm AR,AL\n", },
+
+/* Add a small constant to a register */
+{ PLUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD|TPOINT,
+ SUSHCON, TWORD,
+ 0, RLEFT,
+ " addi AL,AR\n", },
+
+/* Add a larger constant to a register */
+{ PLUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD|TPOINT,
+ SCON, TWORD,
+ 0, RLEFT,
+ " add AL,[ .long AR ]\n", },
+
+/* Add long long to register */
+{ PLUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " dadd AL,AR\n", },
+
+/* Add int (or int pointer) to register */
+{ PLUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TWORD|TPOINT,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " add AL,AR # foo \n", },
+
+/* char/short are allowed to be added if they are in registers */
+{ PLUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " add AL,AR\n", },
+
+/* get address of an memory position into a register */
+{ PLUS, INAREG|INTAREG,
+ SAREG|STAREG, TWORD|TPTRTO,
+ SCON, TANY,
+ NAREG, RESC1,
+ " xmovei A1,AR(AL)\n", },
+
+/* Safety belt for plus */
+{ PLUS, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/*
+ * MINUS operators.
+ */
+/* Rewrite subtracts from char/short pointers (to negative adds) */
+{ MINUS, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO,
+ SANY, TANY,
+ REWRITE, BITYPE,
+ "DIEDIEDIE", },
+
+/* Subtract char/short/int word in memory from reg */
+{ MINUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TWORD|TPOINT,
+ SAREG|STAREG|SNAME|SOREG, TWORD|TPOINT,
+ 0, RLEFT,
+ " sub AL,AR\n", },
+
+/* Subtract a small constant from reg */
+{ MINUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TWORD|TPOINT,
+ SUSHCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " subi AL,AR\n", },
+
+/* Subtract a large constant from reg */
+{ MINUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TWORD|TPOINT,
+ SCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " sub AL,[ .long AR ]\n", },
+
+/* Subtract char/short/int word in memory from reg, save in memory */
+{ MINUS, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RRIGHT,
+ " subm AL,AR\n", },
+
+/* Subtract long long from register */
+{ MINUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " dsub AL,AR\n", },
+
+/* char/short are allowed to be subtracted if they are in registers */
+{ MINUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " sub AL,AR\n", },
+
+/* Safety belt for plus */
+{ MINUS, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/*
+ * AND/OR/ER operators.
+ * Simpler that the ops above in that they only work on integral types.
+ */
+/* And char/short/int with integer memory */
+{ AND, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " and AL,AR\n", },
+
+/* And char/short/int with register */
+{ AND, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " and AL,AR\n", },
+
+/* And char/short/int with small constant */
+{ AND, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SUSHCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " andi AL,AR\n", },
+
+/* And char/short/int with large constant */
+{ AND, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " and AL,[ .long AR ]\n", },
+
+/* long long AND */
+{ AND, INAREG|FOREFF,
+ SAREG|STAREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " and AL,AR\n"
+ " and UL,UR\n", },
+
+/* Safety belt for AND */
+{ AND, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+
+/* OR char/short/int with integer memory */
+{ OR, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " ior AL,AR\n", },
+
+/* OR char/short/int with register */
+{ OR, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " ior AL,AR\n", },
+
+/* OR char/short/int with small constant */
+{ OR, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SUSHCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " iori AL,AR\n", },
+
+/* OR char/short/int with large constant */
+{ OR, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " ior AL,[ .long AR ]\n", },
+
+/* long long OR */
+{ OR, INAREG|FOREFF,
+ SAREG|STAREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " ior AL,AR\n"
+ " ior UL,UR\n", },
+
+/* Safety belt for OR */
+{ OR, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+
+/* ER char/short/int with integer memory */
+{ ER, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " xor AL,AR\n", },
+
+/* ER char/short/int with register */
+{ ER, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " xor AL,AR\n", },
+
+/* ER char/short/int with small constant */
+{ ER, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SUSHCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " xori AL,AR\n", },
+
+/* ER char/short/int with large constant */
+{ ER, FOREFF|INAREG|INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ SCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
+ 0, RLEFT,
+ " xor AL,[ .long AR ]\n", },
+
+/* long long ER */
+{ ER, INAREG|FOREFF,
+ SAREG|STAREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 0, RLEFT,
+ " xor AL,AR\n"
+ " xor UL,UR\n", },
+
+/* Safety belt for ER */
+{ ER, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/*
+ * The next rules handle all shift operators.
+ */
+{ LS, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " lsh AL,(AR)\n", },
+
+{ LS, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " lsh AL,@AR\n", },
+
+{ LS, INTAREG|INAREG|FOREFF,
+ STAREG|SAREG, TLL,
+ SCON, TANY,
+ 0, RLEFT,
+ " ashc AL,ZH\n", },
+
+{ LS, INTAREG|INAREG|FOREFF,
+ STAREG|SAREG, TLL,
+ SAREG|STAREG /* |SNAME|SOREG */, TANY,
+ 0, RLEFT,
+ " ashc AL,(AR)\n", },
+
+{ RS, INTAREG|INAREG|FOREFF,
+ STAREG|SAREG, TSWORD,
+ SCON, TWORD,
+ 0, RLEFT,
+ " ash AL,-ZH\n", },
+
+{ RS, INTAREG|INAREG|FOREFF,
+ STAREG|SAREG, TUWORD,
+ SCON, TWORD,
+ 0, RLEFT,
+ " lsh AL,-ZH\n", },
+
+/* Safety belt for LS/RS */
+{ LS, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+{ RS, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/*
+ * The next rules takes care of assignments. "=".
+ */
+/* Match zeroed registers first */
+{ ASSIGN, INTAREG|FOREFF,
+ SAREG|STAREG, TUCHAR|TUSHORT|TCHAR|TSHORT|TWORD|TPOINT,
+ SZERO, TANY,
+ 0, RLEFT,
+ " setz AL,\n", },
+
+{ ASSIGN, FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SZERO, TANY,
+ 0, 0,
+ " setzm AL\n", },
+
+{ ASSIGN, INTAREG|FOREFF,
+ SAREG|STAREG, TUCHAR|TUSHORT|TCHAR|TSHORT|TWORD|TPOINT,
+ SMONE, TANY,
+ 0, RLEFT,
+ " setom AL\n", },
+
+{ ASSIGN, FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT,
+ SMONE, TANY,
+ 0, 0,
+ " setom AL\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ STAREG|SAREG, TWORD|TPOINT,
+ SCON, TWORD|TPOINT,
+ 0, RLEFT,
+ " ZC\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT|TFLOAT,
+ SAREG|STAREG, TUCHAR|TUSHORT|TWORD|TPOINT|TFLOAT,
+ 0, RRIGHT,
+ " movem AR,AL\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT|TFLOAT,
+ SAREG|STAREG, TSHORT,
+ 0, 0,
+ " hrrem AR,AL\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TUCHAR|TUSHORT|TCHAR|TSHORT|TWORD|TPOINT,
+ SAREG|STAREG|SNAME|SOREG, TWORD|TPOINT,
+ 0, RLEFT,
+ " move AL,AR\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TUCHAR|TUSHORT|TCHAR|TSHORT,
+ SAREG|STAREG, TUCHAR|TUSHORT|TCHAR|TSHORT,
+ 0, RLEFT,
+ " move AL,AR\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|SNAME|SOREG, TLL|TDOUBLE,
+ SAREG|STAREG, TLL|TDOUBLE,
+ 0, RRIGHT,
+ " dmovem AR,AL\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SOREG|SNAME, TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SAREG|STAREG, TANY,
+ 0, RRIGHT,
+ "ZV", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TUSHORT|TUCHAR,
+ SOREG, TANY,
+ 0, RLEFT,
+ " ldb AL,Zg\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SSCON, TANY,
+ 0, RLEFT,
+ " movei AL,AR\n", },
+
+{ ASSIGN, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RLEFT,
+ " move AL,[ .long AR]\n", },
+
+/*
+ * DIV/MOD/MUL
+ * These can be done way more efficient.
+ */
+/* long long div. XXX - work only with unsigned */
+{ DIV, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ (2*NAREG)|NASL, RESC1,
+ " dmove A2,AL ; dmove A1,[ .long 0,0 ]\n"
+ " ddiv A1,AR\n", },
+
+/* long long div. with constant. XXX - work only with unsigned */
+{ DIV, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SCON, TLL,
+ (2*NAREG)|NASL, RESC1,
+ " dmove A2,AL ; dmove A1,[ .long 0,0 ]\n"
+ " ddiv A1,ZP\n", },
+
+/* Simple divide. XXX - fix so next reg can be free */
+{ DIV, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RRIGHT,
+ " idivm AL,AR\n", },
+
+/* Safety belt for DIV */
+{ DIV, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/* long long MOD */
+{ MOD, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 2*NAREG|NASL, RESC2,
+ " dmove A2,AL ; dmove A1,[ .long 0,0 ]\n"
+ " ddiv A1,AR\n", },
+
+/* integer MOD */
+{ MOD, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 2*NAREG|NASL, RESC2,
+ " move A2,AL\n"
+ " setz A1,\n"
+ " idiv A1,AR\n", },
+
+/* integer MOD for char/short */
+{ MOD, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 2*NAREG|NASL, RESC2,
+ " move A2,AL\n"
+ " setz A1,\n"
+ " idiv A1,AR\n", },
+
+/* Safety belt for MOD */
+{ MOD, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/* long long MUL */
+{ MUL, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ 2*NAREG|NASL, RESC2,
+ " dmove A1,AL\n"
+ " dmul A1,AR\n", },
+
+/* integer multiply to memory*/
+{ MUL, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SAREG|STAREG, TWORD,
+ 0, RLEFT,
+ " imulm AR,AL\n", },
+
+/* integer multiply */
+{ MUL, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ 0, RLEFT,
+ " imul AL,AR\n", },
+
+/* integer multiply for char/short */
+{ MUL, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " imul AL,AR\n", },
+
+/* integer multiply with small constant */
+{ MUL, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD,
+ SUSHCON, TWORD,
+ 0, RLEFT,
+ " imuli AL,AR\n", },
+
+/* integer multiply with large constant */
+{ MUL, INTAREG|INAREG|FOREFF,
+ SAREG|STAREG, TWORD,
+ SCON, TWORD,
+ 0, RLEFT,
+ " imul AL,[ .long AR ]\n", },
+
+/* Safety belt for MUL */
+{ MUL, FORREW|FOREFF|INAREG|INTAREG,
+ SANY, TANY,
+ SANY, TANY,
+ REWRITE, 0,
+ "DIEDIEDIE", },
+
+/* read an indirect long long value into register */
+{ UMUL, INTAREG,
+ SAREG|STAREG, TPTRTO|TLL|TWORD,
+ SANY, TLL,
+ NAREG|NASL, RESC1,
+ " dmove A1,(AL)\n", },
+
+/* read an indirect integer value into register */
+{ UMUL, INTAREG,
+ SAREG|STAREG, TWORD|TPOINT,
+ SANY, TWORD|TPOINT,
+ NAREG|NASL, RESC1,
+ " move A1,(AL)\n", },
+
+/* read an indirect value into register */
+{ UMUL, INTAREG,
+ SOREG, TWORD|TPOINT,
+ SANY, TWORD|TPOINT,
+ NAREG, RESC1,
+ " move A1,@AL\n", },
+
+/* read an indirect value into register */
+{ UMUL, INTAREG,
+ SAREG|STAREG|SOREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO,
+ SANY, TCHAR|TUCHAR|TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " ldb A1,AL\n", },
+
+#ifdef notyet
+/* Match tree shape for ildb */
+{ UMUL, INTAREG,
+ SANY, TANY,
+ SILDB, TUCHAR|TCHAR|TPTRTO,
+ NAREG, RESC1,
+ " ildb A1,ZA\n", },
+#endif
+
+/* Match char/short pointers first, requires special handling */
+{ OPLOG, FORCC,
+ SAREG|STAREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RESCC,
+ "ZZ", },
+
+/* Can check anything by just comparing if EQ/NE */
+{ OPLOG, FORCC,
+ SAREG|STAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SZERO, TANY,
+ 0, RESCC,
+ " jumpZe AL,LC # bu\n", },
+
+{ EQ, FORCC,
+ SAREG|STAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG|SOREG|SNAME|SCON, TWORD|TPOINT,
+ 0, RESCC,
+ "ZR", },
+
+{ NE, FORCC,
+ SAREG|STAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG|SOREG|SNAME|SCON, TWORD|TPOINT,
+ 0, RESCC,
+ "ZR", },
+
+{ OPLOG, FORCC,
+ SAREG|STAREG, TWORD,
+ SAREG|STAREG|SOREG|SNAME|SCON, TSWORD,
+ 0, RESCC,
+ "ZR", },
+
+{ OPLOG, FORCC,
+ SAREG|STAREG, TCHAR|TUCHAR,
+ SCON, TANY,
+ 0, RESCC,
+ "ZR", },
+
+{ OPLOG, FORCC,
+ SAREG|STAREG, TWORD|TPOINT|TFLOAT,
+ SAREG|STAREG|SOREG|SNAME|SCON, TWORD|TPOINT|TFLOAT,
+ 0, RESCC,
+ "ZR", },
+
+{ OPLOG, FORCC,
+ SAREG|STAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SAREG|STAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RESCC,
+ "ZR", },
+
+{ OPLOG, FORCC,
+ SAREG|STAREG, TLL|TDOUBLE, /* XXX - does double work here? */
+ SAREG|STAREG|SOREG|SNAME, TLL|TDOUBLE,
+ 0, RESCC,
+ "ZQ", },
+
+/*
+ * Jumps.
+ */
+{ GOTO, FOREFF,
+ SCON, TANY,
+ SANY, TANY,
+ 0, RNOP,
+ " jrst LL\n", },
+
+/*
+ * Convert LTYPE to reg.
+ */
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SMONE, TLL,
+ NAREG, RESC1,
+ " seto A1,\n seto U1,\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SMONE, TANY,
+ NAREG, RESC1,
+ " seto A1,\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SZERO, TLL,
+ NAREG, RESC1,
+ " setz A1,\n setz U1,\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SZERO, TANY,
+ NAREG, RESC1,
+ " setz A1,\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SUSHCON, TLL,
+ NAREG, RESC1,
+ " setz A1,\n movei U1,AR\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SUSHCON, ANYFIXED,
+ NAREG, RESC1,
+ " movei A1,AR\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, ANYFIXED,
+ SNSHCON, ANYFIXED,
+ NAREG, RESC1,
+ " hrroi A1,AR\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, ANYFIXED,
+ SCON, ANYFIXED,
+ NAREG|NASR, RESC1,
+ " ZD A1,ZE # suspekt\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TWORD|TPOINT|TFLOAT,
+ SAREG|STAREG|SOREG|SNAME, TWORD|TPOINT|TFLOAT,
+ NAREG|NASR, RESC1,
+ " move A1,AR\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TLL,
+ SCON, TLL,
+ NAREG, RESC1,
+ " dmove A1,ZO\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TLL|TDOUBLE,
+ SANY, TLL|TDOUBLE,
+ NAREG|NASR, RESC1,
+ " dmove A1,AR\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SOREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
+ SOREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
+ NAREG|NASR, RESC1,
+ "ZU", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SNAME, TUCHAR,
+ SNAME, TUCHAR,
+ NAREG|NASR, RESC1,
+ " ldb A1,[ .long AL ]\n" },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SNAME, TCHAR,
+ SNAME, TCHAR,
+ NAREG|NASR, RESC1,
+ " ldb A1,[ .long AL ]\n"
+ " ash A1,033\n"
+ " ash A1,-033\n", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TANY,
+ SNAME, TSHORT|TUSHORT,
+ NAREG|NASR, RESC1,
+ "Zi", },
+
+{ OPLTYPE, INAREG|INTAREG,
+ SANY, TWORD|TPOINT,
+ SCON, TWORD|TPOINT,
+ NAREG|NASR, RESC1,
+ "Zc", },
+
+{ OPLTYPE, INAREG,
+ SAREG|STAREG, TUSHORT|TUCHAR,
+ SAREG|STAREG, TUSHORT|TUCHAR|TWORD,
+ NAREG, RESC1,
+ " move A1,AL\n", },
+
+/*
+ * Negate a word.
+ */
+{ UMINUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SANY, TWORD,
+ NAREG|NASL, RESC1,
+ " movn A1,AL\n", },
+
+{ UMINUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG, TWORD,
+ SANY, TCHAR|TUCHAR|TSHORT|TUSHORT,
+ 0, RLEFT,
+ " movn AL,AL\n", },
+
+{ UMINUS, INAREG|INTAREG|FOREFF,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SANY, TLL,
+ NAREG|NASR, RESC1,
+ " dmovn A1,AL\n", },
+
+{ COMPL, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TLL,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " setcm A1,AL\n"
+ " setcm U1,UL\n", },
+
+{ COMPL, INTAREG,
+ SAREG|STAREG|SNAME|SOREG, TWORD,
+ SANY, TANY,
+ NAREG|NASL, RESC1,
+ " setcm A1,AL\n", },
+
+{ COMPL, INTAREG,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SANY, TCHAR|TUCHAR|TSHORT|TUSHORT,
+ NAREG|NASL, RESC1,
+ " setcm A1,AL\n", },
+
+/*
+ * Arguments to functions.
+ */
+{ FUNARG, FOREFF,
+ SAREG|SNAME|SOREG, TWORD|TPOINT|TFLOAT,
+ SANY, TANY,
+ 0, RNULL,
+ " push 017,AL\n", },
+
+{ FUNARG, FOREFF,
+ SAREG|STAREG, TCHAR|TUCHAR|TSHORT|TUSHORT,
+ SANY, TANY,
+ 0, RNULL,
+ " push 017,AL\n", },
+
+{ FUNARG, FOREFF,
+ SCON, TCHAR|TUCHAR|TSHORT|TUSHORT|TPOINT|TWORD,
+ SANY, TANY,
+ 0, RNULL,
+ " push 017,[ .long AL]\n", },
+
+{ FUNARG, FOREFF,
+ SAREG|STAREG, TLL|TDOUBLE,
+ SANY, TANY,
+ 0, RNULL,
+ " push 017,AL\n push 017,UL\n", },
+
+
+# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,""
+
+{ UMUL, DF( UMUL ), },
+
+{ INCR, DF(INCR), },
+
+{ DECR, DF(INCR), },
+
+{ ASSIGN, DF(ASSIGN), },
+
+{ OPLEAF, DF(NAME), },
+
+{ INIT, DF(INIT), },
+
+{ OPUNARY, DF(UMINUS), },
+
+{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" },
+};
+
+int tablesize = sizeof(table)/sizeof(table[0]);