OpenBSD-4.6/usr.bin/pcc/pdp10/table.c
/* $OpenBSD: table.c,v 1.2 2007/11/16 09:00:13 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, INAREG,
SAREG|SAREG, 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, INAREG,
SAREG|SAREG, 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, INAREG,
SAREG|SAREG, TPTRTO|TWORD|TSTRUCT|TPOINT,
SANY, TWORD,
0, RLEFT,
" lsh AL,2\n", },
/*
* Convert int/long to pointers.
*/
/* Convert int to char pointer */
{ PCONV, INAREG,
SAREG, 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, INAREG,
SAREG, 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, INAREG,
SAREG, TWORD,
SANY, TPOINT|TWORD|TSTRUCT,
0, RLEFT,
" lsh AL,-2\n", },
/*
* Pointer to pointer conversions.
*/
/* Convert char ptr to short ptr */
{ PCONV, INAREG,
SAREG, 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, INAREG,
SAREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
SANY, TPOINT|TWORD|TSTRUCT,
0, RLEFT,
" tlz AL,0770000\n", },
/* Convert short pointer to char ptr */
{ PCONV, INAREG,
SAREG, TPTRTO|TSHORT|TUSHORT,
SANY, TPTRTO|TCHAR|TUCHAR,
0, RLEFT,
" tlz AL,050000\n", },
/* Convert int/struct/foo pointer to char ptr */
{ PCONV, INAREG,
SAREG, TPOINT|TWORD|TSTRUCT,
SANY, TPTRTO|TCHAR|TUCHAR,
0, RLEFT,
" tlo AL,0700000\n", },
/* Convert int/struct/foo pointer to short ptr */
{ PCONV, INAREG,
SAREG, 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, INAREG,
SAREG, TSHORT|TUSHORT|TCHAR|TUCHAR|TWORD,
SANY, TWORD,
0, RLEFT,
"", },
/* convert int to short/char. This is done when register is loaded */
{ SCONV, INAREG,
SAREG, TWORD,
SANY, TSHORT|TUSHORT|TCHAR|TUCHAR|TWORD,
0, RLEFT,
"", },
/* convert int/long to unsigned long long */
{ SCONV, INAREG,
SAREG|SAREG|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, INAREG,
SAREG|SAREG|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, INAREG,
SAREG|SAREG|SNAME|SOREG, TUCHAR|TUSHORT,
SANY, TLL,
NAREG|NASL, RESC1,
" move U1,AL\n"
" setz A1,\n", },
/* convert long long to int/long */
{ SCONV, INAREG,
SAREG|SAREG|SNAME|SOREG, TLL,
SANY, TWORD,
NAREG|NASL, RESC1,
" move A1,UL\n", },
/* convert long long to unsigned char - XXX - signed char */
{ SCONV, INAREG,
SAREG|SAREG|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, INAREG,
SAREG|SAREG|SNAME|SOREG, TLL,
SANY, TSHORT|TUSHORT,
NAREG|NASL, RESC1,
" move A1,UL\n"
" hrrz A1,A1\n", },
/* floating point conversions */
{ SCONV, INAREG,
SAREG|SAREG|SNAME|SOREG, TDOUBLE|TFLOAT,
SANY, TWORD,
NAREG|NASL, RESC1,
" fix A1,AL\n", },
{ SCONV, INAREG,
SAREG|SAREG|SNAME|SOREG, TWORD,
SANY, TFLOAT,
NAREG|NASL, RESC1,
" fltr A1,AL\n", },
{ SCONV, INAREG,
SAREG|SAREG|SNAME|SOREG, TWORD,
SANY, TDOUBLE,
NAREG|NASL, RESC1,
" fltr A1,AL\n setz U1,\n", },
{ SCONV, INAREG,
SAREG|SAREG|SNAME|SOREG, TDOUBLE,
SANY, TFLOAT,
NAREG|NASL, RESC1,
" move A1,AL\n", },
{ SCONV, INAREG,
SAREG|SAREG|SNAME|SOREG, TFLOAT,
SANY, TDOUBLE,
NAREG|NASL, RESC1,
" move A1,AL\n setz U1,\n", },
/*
* Subroutine calls.
*/
{ UCALL, FOREFF,
SCON, TANY,
SANY, TANY,
0, 0, /* should be 0 */
" pushj 017,AL\nZB", },
{ CALL, FOREFF,
SCON, TANY,
SANY, TANY,
0, 0, /* should be 0 */
" pushj 017,AL\nZB", },
{ UCALL, INAREG,
SCON, TANY,
SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TDOUBLE|TLL|TPOINT,
NAREG, RESC1, /* should be 0 */
" pushj 017,AL\nZB", },
{ UCALL, INAREG,
SAREG|SAREG, TANY,
SANY, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT|TFLOAT|TDOUBLE|TLL|TPOINT,
NAREG|NASL, RESC1, /* should be 0 */
" pushj 017,(AL)\nZB", },
{ UCALL, INAREG,
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,
SAREG|SAREG|SNAME|SOREG, TWORD,
0, RRIGHT,
" move AR,AL\n", },
{ MOVE, FOREFF,
SANY, TLL,
SAREG|SAREG|SNAME|SOREG, TLL,
0, RRIGHT,
" dmove AR,AL\n", },
#ifdef notyet
/*
* INCR can be slightly optimized.
*/
{ INCR, INAREG,
SAREG|SAREG|SNAME|SOREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO,
SONE, TANY,
NAREG, RESC1,
" move A1,AL\n"
" ibp AL\n", },
/* Fix check of return value */
{ INCR, FOREFF,
SAREG|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|INAREG|FOREFF,
SAREG|SAREG|SNAME|SOREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
SAREG|SAREG, TWORD,
0, RRIGHT,
" adjbp AR,AL\n", },
/* No more search for char/short pointer addition */
{ PLUS, INAREG|INAREG|FOREFF,
SANY, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
SANY, TANY,
REWRITE, 0,
"DIEDIEDIE!\n", },
/* Add char/short/int to register */
{ PLUS, FOREFF|INAREG|INAREG,
SAREG|SAREG, TWORD,
SAREG|SAREG|SNAME|SOREG, TWORD,
0, RLEFT,
" add AL,AR\n", },
/* Add char/short/int to memory */
{ PLUS, FOREFF|INAREG|INAREG,
SAREG|SAREG|SNAME|SOREG, TWORD,
SAREG|SAREG, TWORD,
0, RLEFT,
" addm AR,AL\n", },
/* Add a small constant to a register */
{ PLUS, FOREFF|INAREG|INAREG,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD|TPOINT,
SUSHCON, TWORD,
0, RLEFT,
" addi AL,AR\n", },
/* Add a larger constant to a register */
{ PLUS, FOREFF|INAREG|INAREG,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD|TPOINT,
SCON, TWORD,
0, RLEFT,
" add AL,[ .long AR ]\n", },
/* Add long long to register */
{ PLUS, INAREG|INAREG|FOREFF,
SAREG|SAREG, TLL,
SAREG|SAREG|SNAME|SOREG, TLL,
0, RLEFT,
" dadd AL,AR\n", },
/* Add int (or int pointer) to register */
{ PLUS, FOREFF|INAREG|INAREG,
SAREG|SAREG, TWORD|TPOINT,
SAREG|SAREG|SNAME|SOREG, TWORD,
0, RLEFT,
" add AL,AR # foo \n", },
/* char/short are allowed to be added if they are in registers */
{ PLUS, INAREG|INAREG|FOREFF,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
0, RLEFT,
" add AL,AR\n", },
/* get address of an memory position into a register */
{ PLUS, INAREG|INAREG,
SAREG|SAREG, TWORD|TPTRTO,
SCON, TANY,
NAREG, RESC1,
" xmovei A1,AR(AL)\n", },
/* Safety belt for plus */
{ PLUS, FORREW|FOREFF|INAREG|INAREG,
SANY, TANY,
SANY, TANY,
REWRITE, 0,
"DIEDIEDIE", },
/*
* MINUS operators.
*/
/* Rewrite subtracts from char/short pointers (to negative adds) */
{ MINUS, FORREW|FOREFF|INAREG|INAREG,
SANY, TCHAR|TUCHAR|TSHORT|TUSHORT|TPTRTO,
SANY, TANY,
REWRITE, 0,
"DIEDIEDIE", },
/* Subtract char/short/int word in memory from reg */
{ MINUS, FOREFF|INAREG|INAREG,
SAREG|SAREG, TWORD|TPOINT,
SAREG|SAREG|SNAME|SOREG, TWORD|TPOINT,
0, RLEFT,
" sub AL,AR\n", },
/* Subtract a small constant from reg */
{ MINUS, FOREFF|INAREG|INAREG,
SAREG|SAREG, TWORD|TPOINT,
SUSHCON, TWORD|TPOINT,
0, RLEFT,
" subi AL,AR\n", },
/* Subtract a large constant from reg */
{ MINUS, FOREFF|INAREG|INAREG,
SAREG|SAREG, 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|INAREG,
SAREG|SAREG, TWORD,
SAREG|SAREG|SNAME|SOREG, TWORD,
0, RRIGHT,
" subm AL,AR\n", },
/* Subtract long long from register */
{ MINUS, INAREG|INAREG|FOREFF,
SAREG|SAREG, TLL,
SAREG|SAREG|SNAME|SOREG, TLL,
0, RLEFT,
" dsub AL,AR\n", },
/* char/short are allowed to be subtracted if they are in registers */
{ MINUS, INAREG|INAREG|FOREFF,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
0, RLEFT,
" sub AL,AR\n", },
/* Safety belt for plus */
{ MINUS, FORREW|FOREFF|INAREG|INAREG,
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|INAREG,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
SAREG|SAREG|SNAME|SOREG, TWORD,
0, RLEFT,
" and AL,AR\n", },
/* And char/short/int with register */
{ AND, FOREFF|INAREG|INAREG,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
0, RLEFT,
" and AL,AR\n", },
/* And char/short/int with small constant */
{ AND, FOREFF|INAREG|INAREG,
SAREG|SAREG, 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|INAREG,
SAREG|SAREG, 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|SAREG, TLL,
SAREG|SAREG|SNAME|SOREG, TLL,
0, RLEFT,
" and AL,AR\n"
" and UL,UR\n", },
/* Safety belt for AND */
{ AND, FORREW|FOREFF|INAREG|INAREG,
SANY, TANY,
SANY, TANY,
REWRITE, 0,
"DIEDIEDIE", },
/* OR char/short/int with integer memory */
{ OR, FOREFF|INAREG|INAREG,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
SAREG|SAREG|SNAME|SOREG, TWORD,
0, RLEFT,
" ior AL,AR\n", },
/* OR char/short/int with register */
{ OR, FOREFF|INAREG|INAREG,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
0, RLEFT,
" ior AL,AR\n", },
/* OR char/short/int with small constant */
{ OR, FOREFF|INAREG|INAREG,
SAREG|SAREG, 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|INAREG,
SAREG|SAREG, 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|SAREG, TLL,
SAREG|SAREG|SNAME|SOREG, TLL,
0, RLEFT,
" ior AL,AR\n"
" ior UL,UR\n", },
/* Safety belt for OR */
{ OR, FORREW|FOREFF|INAREG|INAREG,
SANY, TANY,
SANY, TANY,
REWRITE, 0,
"DIEDIEDIE", },
/* ER char/short/int with integer memory */
{ ER, FOREFF|INAREG|INAREG,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
SAREG|SAREG|SNAME|SOREG, TWORD,
0, RLEFT,
" xor AL,AR\n", },
/* ER char/short/int with register */
{ ER, FOREFF|INAREG|INAREG,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
SAREG|SAREG, TCHAR|TUCHAR|TSHORT|TUSHORT|TWORD,
0, RLEFT,
" xor AL,AR\n", },
/* ER char/short/int with small constant */
{ ER, FOREFF|INAREG|INAREG,
SAREG|SAREG, 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|INAREG,
SAREG|SAREG, 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|SAREG, TLL,
SAREG|SAREG|SNAME|SOREG, TLL,
0, RLEFT,
" xor AL,AR\n"
" xor UL,UR\n", },
/* Safety belt for ER */
{ ER, FORREW|FOREFF|INAREG|INAREG,
SANY, TANY,
SANY, TANY,
REWRITE, 0,
"DIEDIEDIE", },
/*
* The next rules handle all shift operators.
*/
{ LS, INAREG|INAREG|FOREFF,
SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
0, RLEFT,
" lsh AL,(AR)\n", },
{ LS, INAREG|INAREG|FOREFF,
SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
SNAME|SOREG, TWORD,
0, RLEFT,
" lsh AL,@AR\n", },
{ LS, INAREG|INAREG|FOREFF,
SAREG|SAREG, TLL,
SCON, TANY,
0, RLEFT,
" ashc AL,ZH\n", },
{ LS, INAREG|INAREG|FOREFF,
SAREG|SAREG, TLL,
SAREG|SAREG /* |SNAME|SOREG */, TANY,
0, RLEFT,
" ashc AL,(AR)\n", },
{ RS, INAREG|INAREG|FOREFF,
SAREG|SAREG, TSWORD,
SCON, TWORD,
0, RLEFT,
" ash AL,-ZH\n", },
{ RS, INAREG|INAREG|FOREFF,
SAREG|SAREG, TUWORD,
SCON, TWORD,
0, RLEFT,
" lsh AL,-ZH\n", },
/* Safety belt for LS/RS */
{ LS, FORREW|FOREFF|INAREG|INAREG,
SANY, TANY,
SANY, TANY,
REWRITE, 0,
"DIEDIEDIE", },
{ RS, FORREW|FOREFF|INAREG|INAREG,
SANY, TANY,
SANY, TANY,
REWRITE, 0,
"DIEDIEDIE", },
/*
* The next rules takes care of assignments. "=".
*/
/* Match zeroed registers first */
{ ASSIGN, INAREG|FOREFF,
SAREG, TUCHAR|TUSHORT|TCHAR|TSHORT|TWORD|TPOINT,
SZERO, TANY,
0, RDEST,
" setz AL,\n", },
{ ASSIGN, FOREFF,
SAREG|SNAME|SOREG, TWORD|TPOINT,
SZERO, TANY,
0, 0,
" setzm AL\n", },
{ ASSIGN, INAREG|FOREFF,
SAREG|SAREG, TUCHAR|TUSHORT|TCHAR|TSHORT|TWORD|TPOINT,
SMONE, TANY,
0, RDEST,
" setom AL\n", },
{ ASSIGN, FOREFF,
SAREG|SNAME|SOREG, TWORD|TPOINT,
SMONE, TANY,
0, 0,
" setom AL\n", },
{ ASSIGN, INAREG|INAREG|FOREFF,
SAREG|SAREG, TWORD|TPOINT,
SCON, TWORD|TPOINT,
0, RDEST,
" ZC\n", },
{ ASSIGN, INAREG|INAREG|FOREFF,
SAREG|SNAME|SOREG, TWORD|TPOINT|TFLOAT,
SAREG|SAREG, TUCHAR|TUSHORT|TWORD|TPOINT|TFLOAT,
0, RDEST,
" movem AR,AL\n", },
{ ASSIGN, INAREG|INAREG|FOREFF,
SAREG|SNAME|SOREG, TWORD|TPOINT|TFLOAT,
SAREG|SAREG, TSHORT,
0, RDEST,
" hrrem AR,AL\n", },
{ ASSIGN, INAREG|INAREG|FOREFF,
SAREG|SAREG, TUCHAR|TUSHORT|TCHAR|TSHORT|TWORD|TPOINT,
SAREG|SAREG|SNAME|SOREG, TWORD|TPOINT,
0, RDEST,
" move AL,AR\n", },
{ ASSIGN, INAREG|INAREG|FOREFF,
SAREG|SAREG, TUCHAR|TUSHORT|TCHAR|TSHORT,
SAREG|SAREG, TUCHAR|TUSHORT|TCHAR|TSHORT,
0, RDEST,
" move AL,AR\n", },
{ ASSIGN, INBREG|FOREFF,
SBREG|SNAME|SOREG, TLL|TDOUBLE,
SBREG, TLL|TDOUBLE,
0, RDEST,
" dmovem AR,AL\n", },
{ ASSIGN, INAREG|INAREG|FOREFF,
SOREG|SNAME, TSHORT|TUSHORT|TCHAR|TUCHAR,
SAREG|SAREG, TANY,
0, RDEST,
"ZV", },
{ ASSIGN, INAREG|INAREG|FOREFF,
SAREG|SAREG, TUSHORT|TUCHAR,
SOREG, TANY,
0, RDEST,
" ldb AL,Zg\n", },
{ ASSIGN, INAREG|INAREG|FOREFF,
SAREG|SAREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
SSCON, TANY,
0, RDEST,
" movei AL,AR\n", },
{ ASSIGN, INAREG|INAREG|FOREFF,
SAREG|SAREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
SCON, TANY,
0, RDEST,
" move AL,[ .long AR]\n", },
/*
* DIV/MOD/MUL
* These can be done way more efficient.
*/
/* long long div. XXX - work only with unsigned */
{ DIV, INBREG,
SBREG|SNAME|SOREG, TLL,
SBREG|SNAME|SOREG, TLL,
(2*NBREG)|NBSL, 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, INBREG,
SBREG|SNAME|SOREG, TLL,
SCON, TLL,
(2*NBREG)|NBSL, 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|INAREG|FOREFF,
SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
0, RRIGHT,
" idivm AL,AR\n", },
/* Safety belt for DIV */
{ DIV, FORREW|FOREFF|INAREG|INAREG,
SANY, TANY,
SANY, TANY,
REWRITE, 0,
"DIEDIEDIE", },
/* long long MOD */
{ MOD, INBREG,
SBREG|SNAME|SOREG, TLL,
SBREG|SNAME|SOREG, TLL,
2*NBREG|NBSL, RESC2,
" dmove A2,AL ; dmove A1,[ .long 0,0 ]\n"
" ddiv A1,AR\n", },
/* integer MOD */
{ MOD, INAREG,
SAREG|SNAME|SOREG, TWORD,
SAREG|SNAME|SOREG, TWORD,
2*NAREG|NASL, RESC2,
" move A2,AL\n"
" setz A1,\n"
" idiv A1,AR\n", },
/* integer MOD for char/short */
{ MOD, INAREG,
SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
SAREG, 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, FOREFF,
SANY, TANY,
SANY, TANY,
REWRITE, 0,
"DIEDIEDIE", },
/* long long MUL */
{ MUL, INBREG,
SBREG|SNAME|SOREG, TLL,
SBREG|SNAME|SOREG, TLL,
2*NBREG|NBSL, RESC2,
" dmove A1,AL\n"
" dmul A1,AR\n", },
/* integer multiply to memory*/
{ MUL, INAREG|INAREG|FOREFF,
SAREG|SAREG|SNAME|SOREG, TWORD,
SAREG|SAREG, TWORD,
0, RLEFT,
" imulm AR,AL\n", },
/* integer multiply */
{ MUL, INAREG|INAREG|FOREFF,
SAREG|SAREG, TWORD,
SAREG|SAREG|SNAME|SOREG, TWORD,
0, RLEFT,
" imul AL,AR\n", },
/* integer multiply for char/short */
{ MUL, INAREG|INAREG|FOREFF,
SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
SAREG|SAREG, TWORD|TCHAR|TUCHAR|TSHORT|TUSHORT,
0, RLEFT,
" imul AL,AR\n", },
/* integer multiply with small constant */
{ MUL, INAREG|INAREG|FOREFF,
SAREG|SAREG, TWORD,
SUSHCON, TWORD,
0, RLEFT,
" imuli AL,AR\n", },
/* integer multiply with large constant */
{ MUL, INAREG|INAREG|FOREFF,
SAREG|SAREG, TWORD,
SCON, TWORD,
0, RLEFT,
" imul AL,[ .long AR ]\n", },
/* Safety belt for MUL */
{ MUL, FORREW|FOREFF|INAREG|INAREG,
SANY, TANY,
SANY, TANY,
REWRITE, 0,
"DIEDIEDIE", },
/* read an indirect long long value into register */
{ UMUL, INAREG,
SAREG|SAREG, TPTRTO|TLL|TWORD,
SANY, TLL,
NAREG|NASL, RESC1,
" dmove A1,(AL)\n", },
/* read an indirect integer value into register */
{ UMUL, INAREG,
SAREG|SAREG, TWORD|TPOINT,
SANY, TWORD|TPOINT,
NAREG|NASL, RESC1,
" move A1,(AL)\n", },
/* read an indirect value into register */
{ UMUL, INAREG,
SOREG, TWORD|TPOINT,
SANY, TWORD|TPOINT,
NAREG, RESC1,
" move A1,@AL\n", },
/* read an indirect value into register */
{ UMUL, INAREG,
SAREG|SAREG|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, INAREG,
SANY, TANY,
SILDB, TUCHAR|TCHAR|TPTRTO,
NAREG, RESC1,
" ildb A1,ZA\n", },
#endif
/* Match char/short pointers first, requires special handling */
{ OPLOG, FORCC,
SAREG|SAREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
SAREG|SAREG, TPTRTO|TCHAR|TUCHAR|TSHORT|TUSHORT,
0, RESCC,
"ZZ", },
/* Can check anything by just comparing if EQ/NE */
{ OPLOG, FORCC,
SAREG|SAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
SZERO, TANY,
0, RESCC,
" jumpZe AL,LC # bu\n", },
{ EQ, FORCC,
SAREG|SAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
SAREG|SAREG|SOREG|SNAME|SCON, TWORD|TPOINT,
0, RESCC,
"ZR", },
{ NE, FORCC,
SAREG|SAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
SAREG|SAREG|SOREG|SNAME|SCON, TWORD|TPOINT,
0, RESCC,
"ZR", },
{ OPLOG, FORCC,
SAREG|SAREG, TWORD,
SAREG|SAREG|SOREG|SNAME|SCON, TSWORD,
0, RESCC,
"ZR", },
{ OPLOG, FORCC,
SAREG|SAREG, TCHAR|TUCHAR,
SCON, TANY,
0, RESCC,
"ZR", },
{ OPLOG, FORCC,
SAREG|SAREG, TWORD|TPOINT|TFLOAT,
SAREG|SAREG|SOREG|SNAME|SCON, TWORD|TPOINT|TFLOAT,
0, RESCC,
"ZR", },
{ OPLOG, FORCC,
SAREG|SAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
SAREG|SAREG, TWORD|TPOINT|TCHAR|TUCHAR|TSHORT|TUSHORT,
0, RESCC,
"ZR", },
{ OPLOG, FORCC,
SAREG|SAREG, TLL|TDOUBLE, /* XXX - does double work here? */
SAREG|SAREG|SOREG|SNAME, TLL|TDOUBLE,
0, RESCC,
"ZQ", },
/*
* Jumps.
*/
{ GOTO, FOREFF,
SCON, TANY,
SANY, TANY,
0, RNOP,
" jrst LL\n", },
/*
* Convert LTYPE to reg.
*/
{ OPLTYPE, INBREG,
SANY, TANY,
SMONE, TLL,
NBREG, RESC1,
" seto A1,\n seto U1,\n", },
{ OPLTYPE, INAREG,
SANY, TANY,
SMONE, TANY,
NAREG, RESC1,
" seto A1,\n", },
{ OPLTYPE, INBREG,
SANY, TANY,
SZERO, TLL,
NBREG, RESC1,
" setz A1,\n setz U1,\n", },
{ OPLTYPE, INAREG,
SANY, TANY,
SZERO, TANY,
NAREG, RESC1,
" setz A1,\n", },
{ OPLTYPE, INBREG,
SANY, TANY,
SUSHCON, TLL,
NBREG, RESC1,
" setz A1,\n movei U1,AR\n", },
{ OPLTYPE, INAREG,
SANY, TANY,
SUSHCON, ANYFIXED,
NAREG, RESC1,
" movei A1,AR\n", },
{ OPLTYPE, INAREG,
SANY, ANYFIXED,
SNSHCON, ANYFIXED,
NAREG, RESC1,
" hrroi A1,AR\n", },
{ OPLTYPE, INAREG,
SANY, ANYFIXED,
SCON, ANYFIXED,
NAREG|NASR, RESC1,
" ZD A1,ZE # suspekt\n", },
{ OPLTYPE, INAREG,
SANY, TWORD|TPOINT|TFLOAT,
SAREG|SAREG|SOREG|SNAME, TWORD|TPOINT|TFLOAT,
NAREG|NASR, RESC1,
" move A1,AR\n", },
{ OPLTYPE, INBREG,
SANY, TLL,
SCON, TLL,
NBREG, RESC1,
" dmove A1,ZO\n", },
{ OPLTYPE, INBREG,
SANY, TLL|TDOUBLE,
SANY, TLL|TDOUBLE,
NBREG|NBSR, RESC1,
" dmove A1,AR\n", },
{ OPLTYPE, INAREG,
SOREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
SOREG, TSHORT|TUSHORT|TCHAR|TUCHAR,
NASR, RESC1,
"ZU", },
{ OPLTYPE, INAREG,
SNAME, TUCHAR,
SNAME, TUCHAR,
NAREG|NASR, RESC1,
" ldb A1,[ .long AL ]\n" },
{ OPLTYPE, INAREG,
SNAME, TCHAR,
SNAME, TCHAR,
NAREG|NASR, RESC1,
" ldb A1,[ .long AL ]\n"
" ash A1,033\n"
" ash A1,-033\n", },
{ OPLTYPE, INAREG,
SANY, TANY,
SNAME, TSHORT|TUSHORT,
NAREG|NASR, RESC1,
"Zi", },
{ OPLTYPE, INAREG,
SANY, TWORD|TPOINT,
SCON, TWORD|TPOINT,
NAREG|NASR, RESC1,
"Zc", },
{ OPLTYPE, INAREG,
SAREG|SAREG, TUSHORT|TUCHAR,
SAREG|SAREG, TUSHORT|TUCHAR|TWORD,
NAREG, RESC1,
" move A1,AL\n", },
/*
* Negate a word.
*/
{ UMINUS, INAREG,
SAREG|SAREG|SNAME|SOREG, TWORD,
SANY, TWORD,
NAREG|NASL, RESC1,
" movn A1,AL\n", },
{ UMINUS, INAREG,
SAREG|SAREG, TWORD,
SANY, TCHAR|TUCHAR|TSHORT|TUSHORT,
0, RLEFT,
" movn AL,AL\n", },
{ UMINUS, INAREG,
SAREG|SNAME|SOREG, TLL,
SANY, TLL,
NAREG|NASR, RESC1,
" dmovn A1,AL\n", },
{ COMPL, INAREG,
SAREG|SAREG|SNAME|SOREG, TLL,
SANY, TANY,
NAREG|NASL, RESC1,
" setcm A1,AL\n"
" setcm U1,UL\n", },
{ COMPL, INAREG,
SAREG|SAREG|SNAME|SOREG, TWORD,
SANY, TANY,
NAREG|NASL, RESC1,
" setcm A1,AL\n", },
{ COMPL, INAREG,
SAREG|SAREG, 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|SAREG, 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,
SBREG, TLL|TDOUBLE,
SANY, TANY,
0, RNULL,
" push 017,AL\n push 017,UL\n", },
{ STARG, FOREFF,
SAREG|SOREG|SNAME|SCON, TANY,
SANY, TSTRUCT,
0, 0,
"ZG", },
# define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,""
{ UMUL, DF( UMUL ), },
{ ASSIGN, DF(ASSIGN), },
{ OPLEAF, DF(NAME), },
{ OPUNARY, DF(UMINUS), },
{ FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" },
};
int tablesize = sizeof(table)/sizeof(table[0]);