/* $Id: table.c,v 1.13 2007/11/24 14:03:31 stefan Exp $ */ /*- * Copyright (c) 2007 Gregory McGarry * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* * A template has five logical sections: * * 1) subtree (operator); goal to achieve (cookie) * 2) left node descendent of operator (node class; type) * 3) right node descendent of operator (node class; type) * 4) resource requirements (number of scratch registers); * subtree rewriting rule * 5) emitted instructions */ #include "pass2.h" #define TUWORD TUNSIGNED|TULONG #define TSWORD TINT|TLONG #define TWORD TUWORD|TSWORD #ifdef ELFABI #define HA16(x) # x "@ha" #define LO16(x) # x "@l" #define COM " # " #else #define HA16(x) "ha16(" # x ")" #define LO16(x) "lo16(" # x ")" #define COM " ; " #endif struct optab table[] = { /* First entry must be an empty entry */ { -1, FOREFF, SANY, TANY, SANY, TANY, 0, 0, "", }, /* PCONVs are not necessary */ { PCONV, INAREG, SAREG, TWORD|TPOINT, SAREG, TWORD|TPOINT, 0, RLEFT, COM "pointer conversion\n", }, /* * Conversions of integral types */ /* convert (u)char to (u)char */ { SCONV, INAREG, SAREG, TCHAR|TUCHAR, SAREG, TCHAR|TUCHAR, 0, RLEFT, COM "convert between (u)char and (u)char\n", }, /* convert (u)short to (u)short */ { SCONV, INAREG, SAREG, TSHORT|TUSHORT, SAREG, TSHORT|TUSHORT, 0, RLEFT, COM "convert between (u)short and (u)short\n", }, /* convert pointers to (u)int/(u)long */ { SCONV, INAREG, SAREG, TPOINT|TWORD, SAREG, TWORD, 0, RLEFT, COM "convert a pointer/word to an int\n", }, /* convert pointers to pointers */ { SCONV, INAREG, SAREG, TPOINT, SAREG, TPOINT, 0, RLEFT, COM "convert pointers\n", }, /* convert (u)longlong to (u)longlong */ { SCONV, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, 0, RLEFT, COM "convert (u)longlong to (u)longlong\n", }, /* convert char to short */ { SCONV, INAREG, SAREG, TCHAR, SAREG, TSHORT|TSWORD, NASL|NAREG, RESC1, " extsb A1,AL" COM "convert char to short/int\n", }, /* convert uchar to short */ { SCONV, INAREG, SAREG, TUCHAR, SAREG, TSHORT|TSWORD, NASL|NAREG, RESC1, COM "convert uchar to short/int\n", }, /* convert uchar to ushort/uint/ulong */ { SCONV, INAREG, SAREG, TUCHAR, SAREG, TUSHORT|TUWORD, 0, RLEFT, COM "convert uchar (AL) to ushort/unsigned (A1)\n", }, /* XXX is this necessary? */ /* convert char to ushort/uint/ulong */ { SCONV, INAREG, SAREG, TCHAR, SAREG, TUSHORT|TUWORD, NASL|NAREG|NSPECIAL, RESC1, " extsb A1,AL" COM "convert char (AL) to ushort/unsigned (A1)\n", }, /* convert uchar/ushort/uint to (u)longlong */ { SCONV, INBREG, SAREG, TUCHAR|TUSHORT|TUNSIGNED, SBREG, TLONGLONG|TULONGLONG, NBREG, RESC1, " mr A1,AL" COM "convert uchar/ushort/uint to (u)longlong\n" " li U1,0\n", }, /* convert char/short/int to (u)longlong */ { SCONV, INBREG, SAREG, TCHAR|TSHORT|TSWORD, SBREG, TULONGLONG|TLONGLONG, NBREG, RESC1, " mr A1,AL" COM "convert char/short/int to ulonglong\n" " srawi U1,AL,31\n", }, /* convert (u)short to (u)char */ { SCONV, INAREG, SAREG, TSHORT|TUSHORT, SAREG, TCHAR|TUCHAR, NSPECIAL|NAREG|NASL, RESC1, " andi. A1,AL,255" COM "convert (u)short to (u)char\n", }, /* XXX is this really necessary? */ /* convert short to (u)int */ { SCONV, INAREG, SAREG, TSHORT, SAREG, TWORD, NAREG|NASL, RESC1, " extsh A1,AL" COM "convert short to int\n", }, /* convert ushort to (u)int. */ { SCONV, INAREG, SAREG, TUSHORT, SAREG, TWORD, NASL|NAREG|NSPECIAL, RESC1, COM "convert ushort to word\n", }, /* convert (u)int to (u)char */ { SCONV, INAREG, SAREG, TWORD, SAREG, TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1, " andi. A1,AL,255" COM "convert (u)int to (u)char\n", }, /* convert (u)int to (u)short */ { SCONV, INAREG, SAREG, TWORD, SAREG, TSHORT|TUSHORT, NAREG|NASL|NSPECIAL, RESC1, " andi. A1,AL,65535" COM "convert (u)int to (u)short\n", }, /* convert (u)longlong to (u)char */ { SCONV, INAREG, SBREG, TLONGLONG|TULONGLONG, SAREG, TCHAR|TUCHAR, NAREG|NSPECIAL, RESC1, " andi. A1,AL,255" COM "(u)longlong to (u)char\n", }, /* convert (u)longlong to (u)short*/ { SCONV, INAREG, SBREG, TLONGLONG|TULONGLONG, SAREG, TSHORT|TUSHORT, NAREG|NSPECIAL, RESC1, " andi. A1,AL,65535" COM "(u)longlong to (u)short\n", }, /* convert (u)longlong to (u)int */ { SCONV, INAREG, SBREG, TLONGLONG|TULONGLONG, SAREG, TWORD, NAREG, RESC1, " mr A1,AL" COM "convert (u)longlong to (u)int/long\n", }, /* conversions on load from memory */ /* char */ { SCONV, INAREG, SOREG, TCHAR, SAREG, TWORD, NASL|NAREG|NSPECIAL, RESC1, " lbz A1,AL" COM "convert char to int/long\n" " extsb A1,A1\n", }, /* uchar */ { SCONV, INAREG, SOREG, TUCHAR, SAREG, TWORD, NASL|NAREG|NSPECIAL, RESC1, " lbz A1,AL" COM "convert uchar to int/long\n", }, /* short */ { SCONV, INAREG, SOREG, TSHORT, SAREG, TWORD, NASL|NAREG|NSPECIAL, RESC1, " lha A1,AL" COM "convert short to int/long\n", }, /* ushort */ { SCONV, INAREG, SOREG, TUSHORT, SAREG, TWORD, NASL|NAREG|NSPECIAL, RESC1, " lhz A1,AL" COM "convert ushort to int/long\n", }, /* (u)longlong to (u)char */ { SCONV, INAREG, SOREG, TLONGLONG|TULONGLONG, SAREG, TCHAR|TUCHAR, NAREG|NSPECIAL, RESC1, " lwz A1,AL" COM "(u)longlong to (u)char\n" " andi. A1,A1,255\n", }, /* (u)longlong to (u)short */ { SCONV, INAREG, SOREG, TLONGLONG|TULONGLONG, SAREG, TSHORT|TUSHORT, NAREG|NSPECIAL, RESC1, " lwz A1,AL" COM "(u)longlong to (u)short\n" " andi. A1,A1,65535\n", }, /* (u)longlong to (u)int */ { SCONV, INAREG, SOREG, TLONGLONG|TULONGLONG, SAREG, TWORD, NAREG|NSPECIAL, RESC1, " lwz A1,AL" COM "(u)longlong to (u)int\n", }, /* XXX where are the other OREG conversions? endianness problems? */ /* * Subroutine calls. */ { CALL, FOREFF, SCON|SNAME, TANY, SANY, TANY, 0, 0, " bl CL" COM "call (args, no result) to scon/sname (CL)\n", }, { UCALL, FOREFF, SCON|SNAME, TANY, SANY, TANY, 0, 0, " bl CL" COM "call (no args, no result) to scon/sname (CL)\n", }, { CALL, INAREG, SCON|SNAME, TANY, SAREG, TWORD|TPOINT|TSHORT|TUSHORT, NAREG|NASL, RESC1, /* should be 0 */ " bl CL" COM "call (args, result in r3) to scon/sname (CL)\n", }, { CALL, INBREG, SCON|SNAME, TANY, SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, /* should be 0 */ " bl CL" COM "call (args, result in r3:r4) to scon/sname (CL)\n", }, { UCALL, INAREG, SCON|SNAME, TANY, SAREG, TWORD|TPOINT|TSHORT|TUSHORT, NAREG|NASL, RESC1, /* should be 0 */ " bl CL" COM "call (no args, result in r3) to scon/sname (CL)\n", }, { UCALL, INBREG, SCON|SNAME, TANY, SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, /* should be 0 */ " bl CL" COM "call (no args, result in r3:r4) to scon/sname (CL)\n", }, /* struct return */ { USTCALL, FOREFF, SCON, TANY, SANY, TANY, NAREG|NASL, 0, "ZP call CL\n", }, { USTCALL, INAREG, SCON, TANY, SANY, TANY, NAREG|NASL, RESC1, /* should be 0 */ "ZP call CL\n", }, { USTCALL, INAREG, SNAME|SAREG, TANY, SANY, TANY, NAREG|NASL, RESC1, /* should be 0 */ "ZP call *AL\n", }, { STCALL, FOREFF, SCON, TANY, SANY, TANY, NAREG|NASL, 0, "ZP call CL\n", }, { STCALL, INAREG, SCON, TANY, SANY, TANY, NAREG|NASL, RESC1, /* should be 0 */ "ZP call CL\n", }, { STCALL, INAREG, SNAME|SAREG, TANY, SANY, TANY, NAREG|NASL, RESC1, /* should be 0 */ "ZP call *AL\n", }, /* * The next rules handle all binop-style operators. */ /* XXX AL cannot be R0 */ { PLUS, INAREG, SAREG, TWORD|TPOINT, SSCON, TANY, NAREG|NASL|NSPECIAL, RESC1, " addi A1,AL,AR" COM "addition of constant\n", }, /* XXX AL cannot be R0 */ { PLUS, INAREG|FORCC, SAREG, TWORD|TPOINT, SSCON, TANY, NAREG|NASL|NSPECIAL, RESC1|RESCC, " addic. A1,AL,AR" COM "addition of constant\n", }, { PLUS, INBREG, SBREG, TLONGLONG|TULONGLONG, SSCON, TANY, NBREG|NBSL, RESC1, " addic A1,AL,AR" COM "64-bit addition of constant\n" " addze U1,UL\n", }, { PLUS, INAREG, SAREG, TWORD|TPOINT, SAREG, TWORD|TPOINT, NAREG|NASL|NSPECIAL, RESC1, " add A1,AL,AR\n", }, { PLUS, INAREG|FORCC, SAREG, TWORD|TPOINT, SAREG, TWORD|TPOINT, NAREG|NASL|NSPECIAL, RESC1|RESCC, " add. A1,AL,AR\n", }, { PLUS, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, " addc A1,AL,AR" COM "64-bit add\n" " adde U1,UL,UR\n", }, { MINUS, INAREG, SAREG, TWORD|TPOINT, SSCON, TANY, NAREG|NASL|NSPECIAL, RESC1, " addi A1,AL,-AR\n", }, { MINUS, INAREG|FORCC, SAREG, TWORD|TPOINT, SSCON, TANY, NAREG|NASL|NSPECIAL, RESC1|RESCC, " addic. A1,AL,-AR\n", }, { MINUS, INBREG, SBREG, TLONGLONG|TULONGLONG, SSCON, TANY, NBREG|NBSL, RESC1, " addic A1,AL,-AR\n" " addme U1,UL\n", }, { MINUS, INAREG, SAREG, TWORD|TPOINT, SAREG, TWORD|TPOINT, NAREG|NASL|NSPECIAL, RESC1, " subf A1,AR,AL\n", }, { MINUS, INAREG|FORCC, SAREG, TWORD|TPOINT, SAREG, TWORD|TPOINT, NAREG|NASL|NSPECIAL, RESC1|RESCC, " subf. A1,AR,AL\n", }, { MINUS, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, " subfc A1,AR,AL" COM "64-bit subtraction\n" " subfe U1,UR,UL\n", }, /* * The next rules handle all shift operators. */ { LS, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL, RESC1, " slw A1,AL,AR" COM "left shift\n", }, { LS, INAREG|FORCC, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL, RESC1, " slw. A1,AL,AR" COM "left shift\n", }, { LS, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SCON, TANY, NAREG|NASL, RESC1, " slwi A1,AL,AR" COM "left shift by constant\n", }, { LS, INAREG|FORCC, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SCON, TANY, NAREG|NASL, RESC1, " slwi. A1,AL,AR" COM "left shift by constant\n", }, { LS, INBREG, SBREG, TLONGLONG|TULONGLONG, SCON, TANY, NBREG, RESC1, "ZO" }, { RS, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL, RESC1, " srw A1,AL,AR" COM "right shift\n", }, { RS, INAREG|FORCC, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL, RESC1, " srw. A1,AL,AR" COM "right shift\n", }, { RS, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SCON, TANY, NAREG|NASL, RESC1, " srwi A1,AL,AR" COM "right shift by constant\n", }, { RS, INAREG|FORCC, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SCON, TANY, NAREG|NASL, RESC1, " srwi. A1,AL,AR" COM "right shift by constant\n", }, { RS, INBREG, SBREG, TLONGLONG|TULONGLONG, SCON, TANY, NBREG, RESC1, "ZO" }, /* * The next rules takes care of assignments. "=". */ /* assign 16-bit constant to register */ { ASSIGN, FOREFF|INAREG, SAREG, TANY, SSCON, TANY, 0, RDEST, " li AL,AR\n", }, /* assign 16-bit constant to register */ { ASSIGN, FOREFF|INBREG, SBREG, TANY, SSCON, TANY, 0, RDEST, " li AL,AR\n" " li UL,UR\n", }, /* assign constant to register */ { ASSIGN, FOREFF|INAREG, SAREG, TANY, SCON, TANY, 0, RDEST, " lis AL," HA16(AR) "\n" " addi AL,AL," LO16(AR) "\n", }, /* assign constant to register */ { ASSIGN, FOREFF|INBREG, SBREG, TANY, SCON, TANY, 0, RDEST, " lis AL," HA16(AR) "\n" " addi AL,AL," LO16(AR) "\n" " lis UL," HA16(UR) "\n"\ " addi UL,UL," LO16(UR) "\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD|TPOINT, SOREG, TWORD|TPOINT, NSPECIAL, RDEST, " lwz AL,AR\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD|TPOINT, SNAME, TWORD|TPOINT, NSPECIAL, RDEST, " lis AL," HA16(AR) COM "assign sname to reg\n" " lwz AL," LO16(AR) "(AL)\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INBREG, SBREG, TLONGLONG|TULONGLONG, SOREG, TLONGLONG|TULONGLONG, NSPECIAL, RDEST, " lwz AL,AR" COM "assign llong to reg\n" " lwz UL,UR\n" }, { ASSIGN, FOREFF|INAREG, SBREG, TLONGLONG|TULONGLONG, SNAME, TLONGLONG|TULONGLONG, NSPECIAL, RDEST, " lis AL," HA16(AR) COM "assign 64-bit sname to reg\n" " lwz AL," LO16(AR) "(AL)\n" " lis UL," HA16(UR) "\n" " lwz UL," LO16(UR) "(UL)\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INBREG, SBREG, TLONGLONG|TULONGLONG, SOREG, TSWORD, NSPECIAL, RDEST, " lwz AL,AR" COM "load int/pointer into llong\n" " srawi UL,AR,31\n" }, /* assign memory to register */ { ASSIGN, FOREFF|INBREG, SBREG, TLONGLONG|TULONGLONG, SOREG, TUNSIGNED|TPOINT, NSPECIAL, RDEST, " lwz AL,AR" COM "load uint/pointer into (u)llong\n" " li UL, 0\n" }, /* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TUCHAR, SOREG, TUCHAR, NSPECIAL, RDEST, " lbz AL,AR\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TUCHAR, SNAME, TUCHAR, NSPECIAL, RDEST, " lis AL," HA16(AR) COM "assign uchar sname to reg\n" " lbz AL," LO16(AR) "(AL)\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TCHAR, SOREG, TCHAR, NSPECIAL, RDEST, " lbz AL,AR\n" " extsb AL,AL\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TCHAR, SNAME, TCHAR, NSPECIAL, RDEST, " lis AL," HA16(AR) COM "assign char sname to reg\n" " lbz AL," LO16(AR) "(AL)\n" " extsb AL,AL\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD|TPOINT, SOREG, TSHORT, NSPECIAL, RDEST, " lha AL,AR\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD|TPOINT, SOREG, TUSHORT, NSPECIAL, RDEST, " lhz AL,AR\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD, SNAME, TSHORT, NSPECIAL, RDEST, " lis AL," HA16(AR) "\n" " lha AL," LO16(AR) "(AL)\n", }, /* assign memory to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD, SNAME, TUSHORT, NSPECIAL, RDEST, " lis AL," HA16(AR) "\n" " lhz AL," LO16(AR) "(AL)\n", }, /* assign register to memory */ { ASSIGN, FOREFF|INAREG, SOREG, TWORD|TPOINT, SAREG, TWORD|TPOINT, NSPECIAL, RDEST, " stw AR,AL\n", }, /* assign register to memory */ { ASSIGN, FOREFF|INAREG, SNAME, TWORD|TPOINT, SAREG, TWORD|TPOINT, NAREG|NSPECIAL, RDEST, " lis A1," HA16(AL) COM "assign reg to sname\n" " stw AR," LO16(AL) "(A1)\n", }, /* assign register to memory */ { ASSIGN, FOREFF|INBREG, SOREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NSPECIAL, RDEST, " stw AR,AL" COM "store 64-bit value\n" " stw UR,UL\n", }, /* assign register to memory */ { ASSIGN, FOREFF|INBREG, SNAME, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NBREG|NSPECIAL, RDEST, " lis A1," HA16(AL) COM "assign reg to 64-bit sname\n" " stw AR," LO16(AL) "(A1)\n" " lis U1," HA16(UL) "\n" " stw UR," LO16(UL) "(U1)\n", }, /* assign register to memory */ { ASSIGN, FOREFF|INAREG, SOREG, TCHAR|TUCHAR, SAREG, TCHAR|TUCHAR, NSPECIAL, RDEST, " stb AR,AL\n", }, /* assign register to memory */ { ASSIGN, FOREFF|INAREG, SNAME, TCHAR|TUCHAR, SAREG, TCHAR|TUCHAR, NAREG|NSPECIAL, RDEST, " lis A1," HA16(AL) "\n" " stb AR," LO16(AL) "(A1)\n", }, /* assign register to memory */ { ASSIGN, FOREFF|INAREG, SOREG, TSHORT|TUSHORT, SAREG, TSHORT|TUSHORT, NSPECIAL, RDEST, " sth AR,AL\n", }, /* assign register to memory */ { ASSIGN, FOREFF|INAREG, SNAME, TSHORT|TUSHORT, SAREG, TSHORT|TUSHORT, NAREG|NSPECIAL, RDEST, " lis A1," HA16(AL) "\n" " sth AR," LO16(AL) "(A1)\n", }, /* assign register to register */ { ASSIGN, FOREFF|INAREG, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, 0, RDEST, " mr AL,AR" COM "assign AR to AL\n", }, { ASSIGN, FOREFF|INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, 0, RDEST, " mr AL,AR" COM "assign UR:AR to UL:AL\n" " mr UL,UR\n", }, #if 0 /* assign register to memory */ { ASSIGN, FOREFF, SAREG, TPOINT, SAREG, TWORD, 0, RDEST, " stw AR,0(AL)" COM "indirect assign\n", }, #endif #if 0 { ASSIGN, FOREFF|INAREG, SFLD, TANY, SAREG, TANY, NAREG, RDEST, "ZE", }, { ASSIGN, FOREFF, SFLD, TANY, SAREG, TANY, NAREG, 0, "ZE", }, #endif /* Do not generate memcpy if return from funcall */ #if 0 { STASG, INAREG|FOREFF, SOREG|SNAME|SAREG, TPTRTO|TSTRUCT, SFUNCALL, TPTRTO|TSTRUCT, 0, RRIGHT, "", }, #endif { STASG, INAREG|FOREFF, SOREG, TANY, SAREG, TPTRTO|TANY, NSPECIAL, RRIGHT, "ZQ", }, /* * DIV/MOD/MUL */ { DIV, INAREG, SAREG, TSWORD, SAREG, TWORD, NAREG|NASL, RESC1, " divw A1,AL,AR\n", }, { DIV, INAREG, SAREG, TUWORD|TPOINT, SAREG, TUWORD|TPOINT, NAREG|NASL, RESC1, " divwu A1,AL,AR\n", }, { MOD, INAREG, SAREG, TSWORD, SAREG, TSWORD, NAREG, RESC1, " divw A1,AL,AR" COM "signed modulo\n" " mullw A1,A1,AR\n" " subf A1,A1,AL\n", }, { MOD, INAREG, SAREG, TWORD|TPOINT, SAREG, TUWORD|TPOINT, NAREG, RESC1, " divwu A1,AL,AR" COM "unsigned modulo\n" " mullw A1,A1,AR\n" " subf A1,A1,AL\n", }, { MUL, INAREG, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SSCON, TANY, NAREG|NASL, RESC1, " mulli A1,AL,AR\n", }, { MUL, INAREG, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL, RESC1, " mullw A1,AL,AR\n", }, { MUL, INBREG, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, NBREG, RESC1, " mullw A1,AL,AR\n" " mulhw U1,AL,AR\n", }, { MUL, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NBREG, RESC1, " mullw A1,AL,AR\n" " mulhw U1,AL,AR\n", }, /* * Indirection operators. */ { UMUL, INAREG, SANY, TANY, SOREG, TWORD|TPOINT, NAREG|NSPECIAL, RESC1, " lwz A1,AL" COM "word load\n", }, { UMUL, INAREG, SANY, TANY, SOREG, TCHAR, NAREG|NSPECIAL, RESC1, " lbz A1,AL" COM "char load\n" " extsb A1,A1\n", }, { UMUL, INAREG, SANY, TANY, SOREG, TUCHAR, NAREG|NSPECIAL, RESC1, " lbz A1,AL" COM "uchar load\n", }, { UMUL, INAREG, SANY, TANY, SOREG, TSHORT, NAREG|NSPECIAL, RESC1, " lha A1,AL" COM "short load\n", }, { UMUL, INAREG, SANY, TANY, SOREG, TUSHORT, NAREG|NSPECIAL, RESC1, " lhz A1,AL" COM "ushort load\n", }, { UMUL, INBREG, SANY, TANY, SOREG, TLONGLONG|TULONGLONG, NBREG, RESC1, " lwz A1,AL" COM "64-bit load\n" " lwz U1,UL\n", }, /* XXX UMUL of SNAME and AREG !!! */ /* * Logical/branching operators */ /* compare with constant */ { OPLOG, FORCC, SAREG, TSWORD|TSHORT|TCHAR, SSCON, TANY, 0, RESCC, " cmpwi AL,AR\n", }, /* compare with constant */ { OPLOG, FORCC, SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, SSCON, TANY, 0, RESCC, " cmplwi AL,AR\n", }, /* compare with register */ { OPLOG, FORCC, SAREG, TSWORD|TSHORT|TCHAR, SAREG, TSWORD|TSHORT|TCHAR, 0, RESCC, " cmpw AL,AR\n", }, /* compare with register */ { OPLOG, FORCC, SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, SAREG, TUWORD|TPOINT|TUSHORT|TUCHAR, 0, RESCC, " cmplw AL,AR\n", }, /* compare with register */ { OPLOG, FORCC, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, 0, 0, "ZD", }, { OPLOG, FORCC, SANY, TANY, SANY, TANY, REWRITE, 0, "diediedie!", }, /* AND/OR/ER */ { AND, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1|RESCC, " and A1,AL,AR\n", }, { AND, INAREG|FORCC, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1, " and. A1,AL,AR\n", }, /* AR must be positive */ { AND, INAREG|FORCC, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, SPCON, TANY, NAREG|NASL|NSPECIAL, RESC1|RESCC, " andi. A1,AL,AR\n", }, { AND, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, " and A1,AL,AR" COM "64-bit and\n" " and U1,UL,UR\n" }, { AND, INBREG|FORCC, SBREG, TLONGLONG|TULONGLONG, SPCON, TANY, NBREG|NBSL, RESC1|RESCC, " andi. A1,AL,AR" COM "64-bit and with constant\n" " li U1,0\n" }, { OR, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1, " or A1,AL,AR\n", }, { OR, INAREG|FORCC, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1|RESCC, " or. A1,AL,AR\n", }, { OR, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, SSCON, TANY, NAREG|NASL|NSPECIAL, RESC1, " ori A1,AL,AR\n", }, { OR, INAREG|FORCC, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, SSCON, TANY, NAREG|NASL|NSPECIAL, RESC1|RESCC, " ori. A1,AL,AR\n", }, { OR, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, " or A1,AL,AR" COM "64-bit or\n" " or U1,UL,UR\n" }, { OR, INBREG, SBREG, TLONGLONG|TULONGLONG, SSCON, TANY, NBREG|NBSL, RESC1, " ori A1,AL,AR" COM "64-bit or with constant\n" }, { OR, INBREG|FORCC, SBREG, TLONGLONG|TULONGLONG, SSCON, TANY, NBREG|NBSL, RESC1|RESCC, " ori. A1,AL,AR" COM "64-bit or with constant\n" }, { ER, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1, " xor A1,AL,AR\n", }, { ER, INAREG|FORCC, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, NAREG|NASL|NSPECIAL, RESC1|RESCC, " xor. A1,AL,AR\n", }, { ER, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, SSCON, TANY, NAREG|NASL|NSPECIAL, RESC1, " xori A1,AL,AR\n", }, { ER, INAREG|FORCC, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TCHAR, SSCON, TANY, NAREG|NASL|NSPECIAL, RESC1|RESCC, " xori. A1,AL,AR\n", }, { ER, INBREG, SBREG, TLONGLONG|TULONGLONG, SBREG, TLONGLONG|TULONGLONG, NBREG|NBSL, RESC1, " xor A1,AL,AR" COM "64-bit xor\n" " xor U1,UL,UR\n" }, { ER, INBREG, SBREG, TLONGLONG|TULONGLONG, SSCON, TANY, NBREG|NBSL, RESC1, " xori A1,AL,AR" COM "64-bit xor with constant\n" }, { ER, INBREG|FORCC, SBREG, TLONGLONG|TULONGLONG, SSCON, TANY, NBREG|NBSL, RESC1|RESCC, " xori. A1,AL,AR" COM "64-bit xor with constant\n" }, /* * Jumps. */ { GOTO, FOREFF, SCON, TANY, SANY, TANY, 0, RNOP, " ba LL\n", }, { GOTO, FOREFF, SAREG, TANY, SANY, TANY, 0, RNOP, " mtctr AL\n" " bctr\n", }, /* * Convert LTYPE to reg. */ { OPLTYPE, INBREG, SANY, TANY, SOREG, TLONGLONG|TULONGLONG, NBREG, RESC1, " lwz A1,AL" COM "load llong from memory\n" " lwz U1,UL\n", }, { OPLTYPE, INBREG, SANY, TANY, SNAME, TLONGLONG|TULONGLONG, NBREG, RESC1, " lis A1," HA16(AL) COM "load llong from sname\n" " lwz A1," LO16(AL) "(A1)\n" " lis U1," HA16(UL) "\n" " lwz U1," LO16(UL) "(U1)\n", }, /* load word from memory */ { OPLTYPE, INAREG, SANY, TANY, SOREG, TWORD|TPOINT, NAREG, RESC1, " lwz A1,AL" COM "load word from memory\n", }, /* load word from memory */ { OPLTYPE, INAREG, SANY, TANY, SNAME, TWORD|TPOINT, NAREG|NSPECIAL, RESC1, " lis A1," HA16(AL) COM "load word from sname\n" " lwz A1," LO16(AL) "(A1)\n", }, /* load char from memory */ { OPLTYPE, INAREG, SANY, TANY, SOREG, TCHAR, NAREG, RESC1, " lbz A1,AL" COM "load char from memory\n" " extsb A1,A1\n", }, /* load char from memory */ { OPLTYPE, INAREG, SANY, TANY, SNAME, TCHAR, NAREG|NSPECIAL, RESC1, " lis A1," HA16(AL) COM "load char from sname\n" " lbz A1," LO16(AL) "(A1)\n" " extsb A1,A1\n", }, /* load uchar from memory */ { OPLTYPE, INAREG, SANY, TANY, SOREG, TUCHAR, NAREG, RESC1, " lbz A1,AL" COM "load uchar from memory\n", }, /* load uchar from memory */ { OPLTYPE, INAREG, SANY, TANY, SNAME, TUCHAR, NAREG|NSPECIAL, RESC1, " lis A1," HA16(AL) COM "load uchar from sname\n" " lbz A1," LO16(AL) "(A1)\n", }, /* load short from memory */ { OPLTYPE, INAREG, SANY, TANY, SOREG, TSHORT, NAREG, RESC1, " lha A1,AL" COM "load short from memory\n", }, /* load ushort from memory */ { OPLTYPE, INAREG, SANY, TANY, SOREG, TUSHORT, NAREG, RESC1, " lhz A1,AL" COM "load ushort from memory\n", }, /* load short from memory */ { OPLTYPE, INAREG, SANY, TANY, SNAME, TSHORT, NAREG|NSPECIAL, RESC1, " lis A1," HA16(AL) COM "load short from sname\n" " lha A1," LO16(AL) "(A1)\n", }, /* load ushort from memory */ { OPLTYPE, INAREG, SANY, TANY, SNAME, TUSHORT, NAREG|NSPECIAL, RESC1, " lis A1," HA16(AL) COM "load ushort from sname\n" " lhz A1," LO16(AL) "(A1)\n", }, /* load from 16-bit constant */ { OPLTYPE, INAREG, SANY, TANY, SSCON, TANY, NAREG, RESC1, " li A1,AL" COM "load 16-bit constant\n", }, /* load from 16-bit constant */ { OPLTYPE, INBREG, SANY, TANY, SSCON, TANY, NBREG, RESC1, " li A1,AL" COM "load 16-bit constant\n" " li U1,UL\n", }, /* load from constant */ { OPLTYPE, INAREG, SANY, TANY, SCON, TANY, NAREG|NASL|NSPECIAL, RESC1, " lis A1," HA16(AL) COM "load constant into register\n" " addi A1,A1," LO16(AL) "\n", }, /* load from constant */ { OPLTYPE, INBREG, SANY, TANY, SCON, TANY, NBREG, RESC1, " lis A1," HA16(AL) COM "load constant into register\n" " addi A1,A1," LO16(AL) "\n" " lis U1," HA16(UL) "\n" " addi U1,U1," LO16(UL) "\n", }, /* load from register */ { OPLTYPE, INAREG, SANY, TANY, SAREG, TANY, NAREG, RESC1, " mr A1,AL" COM "load AL into A1\n" }, /* load from register */ { OPLTYPE, INBREG, SANY, TANY, SBREG, TLONGLONG|TULONGLONG, NBREG, RESC1, " mr A1,AL" COM "load UL:AL into U1:A1\n" " mr U1,UL\n", }, /* * Negate a word. */ { UMINUS, INAREG, SAREG, TWORD|TPOINT|TSHORT|TUSHORT|TCHAR|TUCHAR, SANY, TANY, NAREG|NASL, RESC1, " neg A1,AL\n", }, { UMINUS, INBREG, SBREG, TLONGLONG|TULONGLONG, SANY, TANY, NBREG|NBSL, RESC1, " subfic A1,AL,0\n" " subfze U1,UL\n", }, { COMPL, INAREG, SAREG, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SANY, TANY, NAREG|NASL, RESC1, " not A1,AL\n", }, { COMPL, INBREG, SBREG, TLONGLONG|TULONGLONG, SANY, TANY, NBREG|NBSL, RESC1, " not A1,AL\n" " not U1,UL\n", }, /* * Arguments to functions. */ #if 0 { FUNARG, FOREFF, SCON|SAREG|SNAME|SOREG, TWORD|TPOINT, SANY, TWORD|TPOINT, 0, RNULL, " pushl AL\n", }, { FUNARG, FOREFF, SCON, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, SANY, TWORD|TSHORT|TUSHORT|TCHAR|TUCHAR, 0, RNULL, " pushl AL\n", }, { FUNARG, FOREFF, SAREG|SNAME|SOREG, TSHORT, SANY, TSHORT, NAREG, 0, " movswl AL,ZN\n pushl ZN\n", }, #endif { FUNARG, FOREFF, SAREG|SNAME|SOREG, TUSHORT, SANY, TUSHORT, NAREG, 0, " movzwl AL,ZN\n pushl ZN\n", }, #if 0 { FUNARG, FOREFF, SHCH|SNAME|SOREG, TCHAR, SANY, TCHAR, NAREG, 0, " movsbl AL,A1\n pushl A1\n", }, #endif #if 0 { FUNARG, FOREFF, SHCH|SNAME|SOREG, TUCHAR, SANY, TUCHAR, NAREG, 0, " movzbl AL,A1\n pushl A1\n", }, #endif #if 0 { STARG, FOREFF, SAREG|SOREG|SNAME|SCON, TANY, SANY, TSTRUCT, NSPECIAL|NAREG, 0, "ZF", }, #endif # define DF(x) FORREW,SANY,TANY,SANY,TANY,REWRITE,x,"" { UMUL, DF( UMUL ), }, { ASSIGN, DF(ASSIGN), }, { STASG, DF(STASG), }, { FLD, DF(FLD), }, { OPLEAF, DF(NAME), }, /* { INIT, DF(INIT), }, */ { OPUNARY, DF(UMINUS), }, { OPANY, DF(BITYPE), }, { FREE, FREE, FREE, FREE, FREE, FREE, FREE, FREE, "help; I'm in trouble\n" }, }; int tablesize = sizeof(table)/sizeof(table[0]);