diff options
Diffstat (limited to 'misc/pascal/insn32/regm/regm_pass2.c')
-rw-r--r-- | misc/pascal/insn32/regm/regm_pass2.c | 3051 |
1 files changed, 1526 insertions, 1525 deletions
diff --git a/misc/pascal/insn32/regm/regm_pass2.c b/misc/pascal/insn32/regm/regm_pass2.c index 03ef8dcd6..86380984d 100644 --- a/misc/pascal/insn32/regm/regm_pass2.c +++ b/misc/pascal/insn32/regm/regm_pass2.c @@ -1,1525 +1,1526 @@ -/**********************************************************************
- * regm_pass2.c
- * Convert the buffered pcode to the basic register model with an
- * indefinite number of registers (arguments, general, and special
- * registers) and with 32-bit immediate size.
- *
- * Copyright (C) 2008 Gregory Nutt. All rights reserved.
- * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
- *
- * 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. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "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
- * COPYRIGHT OWNER OR CONTRIBUTORS 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.
- *
- *********************************************************************/
-
-/**********************************************************************
- * Included Files
- **********************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "keywords.h"
-#include "pdefs.h"
-#include "pxdefs.h"
-#include "pfdefs.h"
-#include "pedefs.h"
-#include "pofflib.h"
-#include "perr.h"
-
-#include "pinsn32.h"
-#include "builtins.h"
-
-#include "regm.h"
-#include "regm_tree.h"
-#include "regm_registers2.h"
-#include "regm_pass2.h"
-
-/************************************a*********************************
- * Definitions
- **********************************************************************/
-
-/**********************************************************************
- * Private Types
- **********************************************************************/
-
-struct regm_opmap_s;
-
-typedef void (*regm_mapper_t)(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode, struct procdata_s *pNode);
-
-struct regm_opmap_s
-{
- ubyte chOpCode;
- sbyte chImmediate;
- sbyte chSpecial;
- regm_mapper_t pMapper;
-};
-
-/**********************************************************************
- * Private Function Prototypes
- **********************************************************************/
-
-static void regm_NoOperation(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_UnaryOperation(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_BinaryOperation(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_CompareVsZero(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_BinaryComparison(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_LoadImmediate(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_LoadMultiple(uint32 dwRDest, uint32 dwRSrc);
-static void regm_LoadMultipleImmediate(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_StoreMultiple(uint32 dwRDest, uint32 dwRSrc);
-static void regm_StoreImmediate(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_StoreMultipleImmediate(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_Duplicate(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_PushImmediate(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_PopSpecial(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_SetDataCount(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_PushSpecial(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_Return(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_LoadOffset(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_LoadMultipleOffset(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_StoreOffset(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_StoreMultipleOffset(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_LoadIndexed(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode, struct procdata_s *pNode);
-static void regm_LoadMultipleIndexed(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_StoreIndexed(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode, struct procdata_s *pNode);
-static void regm_StoreMultipleIndexed(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_ConditionalBranchVsZero(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_ConditionalBranchBinary(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_UnconditionalBranch(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_IncrementSpecial(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_LoadAddress(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode, struct procdata_s *pNode);
-static void regm_LoadAddressIndexed(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_SetupOutArgs(uint32 nParms, const uint32 *pwArgSize);
-static void regm_MapInRet(uint32 wRetSize);
-static void regm_PCal(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_SysIo(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_LibCall(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_Float(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-static void regm_IllegalPCode(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode);
-
-static void regm_GenerateRegm(struct procdata_s *pNode, void *pvArg);
-static int regm_Pass2Node(struct procdata_s *pNode, void *pvArg);
-
-/**********************************************************************
- * Public Variables
- **********************************************************************/
-
-/* On the initialize passes, the register number will simply be the offset
- * from the top of the stack. The following variable keeps trck of the
- * stack offset.
- */
-
-uint32 g_dwStackOffset;
-uint32 g_dwRegisterCount = 0;
-int g_bRegisterCountValid = 0;
-
-/**********************************************************************
- * Private Variables
- **********************************************************************/
-
-static const struct regm_opmap_s vrgOpMap1[64] =
- {
- /* 0x00: oNOP */ {0, 0, 0, regm_NoOperation},
- /* 0x01: oNEG */ {rRSBI, 0, 0, regm_UnaryOperation},
- /* 0x02: oABS */ {rRSB, 0, 0, regm_UnaryOperation},
- /* 0x03: oINC */ {rADDI, 1, 0, regm_UnaryOperation},
- /* 0x04: oDEC */ {rSUBI, 1, 0, regm_UnaryOperation},
- /* 0x05: oNOT */ {rMVN, 0, 0, regm_UnaryOperation},
- /* 0x06: oADD */ {rADD, 0, 0, regm_BinaryOperation},
- /* 0x07: oSUB */ {rSUB, 0, 0, regm_BinaryOperation},
- /* 0x08: oMUL */ {rMUL, 0, 0, regm_BinaryOperation},
- /* 0x09: oDIV */ {rDIV, 0, 0, regm_BinaryOperation},
- /* 0x0a: oMOD */ {rMOD, 0, 0, regm_BinaryOperation},
- /* 0x0b: oSLL */ {rSLL, 0, 0, regm_BinaryOperation},
- /* 0x0c: oSRL */ {rSRL, 0, 0, regm_BinaryOperation},
- /* 0x0d: oSRA */ {rSRA, 0, 0, regm_BinaryOperation},
- /* 0x0e: oOR */ {rOR, 0, 0, regm_BinaryOperation},
- /* 0x0f: oAND */ {rAND, 0, 0, regm_BinaryOperation},
-
- /* 0x10: oEQUZ */ {rBEQ, 0, 0, regm_CompareVsZero},
- /* 0x11: oNEQZ */ {rBNE, 0, 0, regm_CompareVsZero},
- /* 0x12: oLTZ */ {rBLT, 0, 0, regm_CompareVsZero},
- /* 0x13: oGTEZ */ {rBGTE, 0, 0, regm_CompareVsZero},
- /* 0x14: oGTZ */ {rBGT, 0, 0, regm_CompareVsZero},
- /* 0x15: oLTEZ */ {rBLTE, 0, 0, regm_CompareVsZero},
- /* 0x16: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x17: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x18: oEQU */ {rBEQ, 0, 0, regm_BinaryComparison},
- /* 0x19: oNEQ */ {rBNE, 0, 0, regm_BinaryComparison},
- /* 0x1a: oLT */ {rBLT, 0, 0, regm_BinaryComparison},
- /* 0x1b: oGTE */ {rBGTE, 0, 0, regm_BinaryComparison},
- /* 0x1c: oGT */ {rBGT, 0, 0, regm_BinaryComparison},
- /* 0x1d: oLTE */ {rBLTE, 0, 0, regm_BinaryComparison},
- /* 0x1e: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x1f: oBIT */ {rBEQ, 0, 0, regm_BinaryComparison},
-
- /* 0x20: oLDI */ {rLD, 2, SPB, regm_LoadImmediate},
- /* 0x21: oLDIH */ {rLDH, 1, SPB, regm_LoadImmediate},
- /* 0x22: oLDIB */ {rLDB, 0, SPB, regm_LoadImmediate},
- /* 0x23: oLDIM */ {0, 0, SPB, regm_LoadMultipleImmediate},
- /* 0x24: oSTI */ {rST, 2, SPB, regm_StoreImmediate},
- /* 0x25: oSTIH */ {rSTH, 1, SPB, regm_StoreImmediate},
- /* 0x26: oSTIB */ {rSTB, 0, SPB, regm_StoreImmediate},
- /* 0x27: oSTIM */ {0, 0, SPB, regm_StoreMultipleImmediate},
- /* 0x28: oDUP */ {0, 0, 0, regm_Duplicate},
- /* 0x17: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x2a: oPUSHS */ {0, 0, CSP, regm_PushSpecial},
- /* 0x2b: oPOPS */ {0, 0, CSP, regm_PopSpecial},
- /* 0x2c: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x2d: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x2e: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x2f: oRET */ {0, 0, 0, regm_Return},
-
- /* 0x30: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x31: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x32: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x33: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x34: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x35: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x36: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x37: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x38: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x39: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x3a: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x3b: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x3c: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x3d: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x3e: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x3f: oEND */ {0, 0, 0, regm_Return}
- };
-
-static const struct regm_opmap_s vrgOpMap2[64] =
- {
- /* 0x80: oLD */ {rLD, 2, SPB, regm_LoadOffset},
- /* 0x81: oLDH */ {rLDH, 1, SPB, regm_LoadOffset},
- /* 0x82: oLDB */ {rLDB, 0, SPB, regm_LoadOffset},
- /* 0x83: oLDM */ {0, 0, SPB, regm_LoadMultipleOffset},
- /* 0x84: oST */ {rST, 2, SPB, regm_StoreOffset},
- /* 0x85: oSTH */ {rSTH, 1, SPB, regm_StoreOffset},
- /* 0x86: oSTB */ {rSTB, 0, SPB, regm_StoreOffset},
- /* 0x87: oSTM */ {0, 0, SPB, regm_StoreMultipleOffset},
- /* 0x88: oLDX */ {rLD, 2, SPB, regm_LoadIndexed},
- /* 0x89: oLDXH */ {rLDH, 1, SPB, regm_LoadIndexed},
- /* 0x8a: oLDXB */ {rLDB, 0, SPB, regm_LoadIndexed},
- /* 0x8b: oLDXM */ {0, 0, SPB, regm_LoadMultipleIndexed},
- /* 0x8c: oSTX */ {rST, 2, SPB, regm_StoreIndexed},
- /* 0x8d: oSTXH */ {rSTH, 1, SPB, regm_StoreIndexed},
- /* 0x8e: oSTXB */ {rSTB, 0, SPB, regm_StoreIndexed},
- /* 0x8f: oSTXM */ {0, 0, SPB, regm_StoreMultipleIndexed},
-
- /* 0x90: oJEQUZ */ {rBEQ, 0, 0, regm_ConditionalBranchVsZero},
- /* 0x91: oJNEQZ */ {rBNE, 0, 0, regm_ConditionalBranchVsZero},
- /* 0x92: oJLTZ */ {rBLT, 0, 0, regm_ConditionalBranchVsZero},
- /* 0x93: oJGTEZ */ {rBGTE, 0, 0, regm_ConditionalBranchVsZero},
- /* 0x94: oJGTZ */ {rBGT, 0, 0, regm_ConditionalBranchVsZero},
- /* 0x95: oJLTEZ */ {rBLTE, 0, 0, regm_ConditionalBranchVsZero},
- /* 0x96: oJMP */ {rB, 0, 0, regm_UnconditionalBranch},
- /* 0x97: oPUSH */ {0, 0, 0, regm_PushImmediate},
- /* 0x98: oJEQU */ {rBEQ, 0, 0, regm_ConditionalBranchBinary},
- /* 0x99: oJNEQ */ {rBNE, 0, 0, regm_ConditionalBranchBinary},
- /* 0x9a: oJLT */ {rBLT, 0, 0, regm_ConditionalBranchBinary},
- /* 0x9b: oJGTE */ {rBGTE, 0, 0, regm_ConditionalBranchBinary},
- /* 0x9c: oJGT */ {rBGT, 0, 0, regm_ConditionalBranchBinary},
- /* 0x9d: oJLTE */ {rBLTE, 0, 0, regm_ConditionalBranchBinary},
- /* 0x9e: */ {0, 0, 0, regm_IllegalPCode},
- /* 0x9f: oINDS */ {0, 0, SP, regm_IncrementSpecial},
-
- /* 0xa0: oLDS */ {rLD, 2, LSP, regm_LoadOffset},
- /* 0xa1: oLDSH */ {rLDH, 1, LSP, regm_LoadOffset},
- /* 0xa2: oLDSB */ {rLDB, 0, LSP, regm_LoadOffset},
- /* 0xa3: oLDSM */ {0, 0, LSP, regm_LoadMultipleOffset},
- /* 0xa4: oSTS */ {rST, 2, LSP, regm_StoreOffset},
- /* 0xa5: oSTSH */ {rSTH, 1, LSP, regm_StoreOffset},
- /* 0xa6: oSTSB */ {rSTB, 0, LSP, regm_StoreOffset},
- /* 0xa7: oSTSM */ {0, 0, LSP, regm_StoreMultipleOffset},
- /* 0xa8: oLDSX */ {rLD, 2, LSP, regm_LoadIndexed},
- /* 0xa9: oLDSXH */ {rLDH, 1, LSP, regm_LoadIndexed},
- /* 0xaa: oLDSXB */ {rLDB, 0, LSP, regm_LoadIndexed},
- /* 0xab: oLDSXM */ {0, 0, LSP, regm_LoadMultipleIndexed},
- /* 0xac: oSTSX */ {rST, 2, LSP, regm_StoreIndexed},
- /* 0xad: oSTSXH */ {rSTH, 1, LSP, regm_StoreIndexed},
- /* 0xae: oSTSXB */ {rSTB, 0, LSP, regm_StoreIndexed},
- /* 0xaf: oSTSXM */ {0, 0, LSP, regm_StoreMultipleIndexed},
-
- /* 0xb0: oLA */ {0, 0, SPB, regm_LoadAddress},
- /* 0xb1: oLAS */ {0, 0, LSP, regm_LoadAddress},
- /* 0xb2: oLAC */ {0, 0, CSB, regm_LoadAddress},
- /* 0xb3: */ {0, 0, 0, regm_IllegalPCode},
- /* 0xb4: oLAX */ {0, 0, SPB, regm_LoadAddressIndexed},
- /* 0xb5: oLASX */ {0, 0, LSP, regm_LoadAddressIndexed},
- /* 0xb6: oSLSP */ {0, 0, LSP, regm_PopSpecial},
- /* 0xb7: oSDC */ {0, 0, DC, regm_SetDataCount},
- /* 0xb8: */ {0, 0, 0, regm_IllegalPCode},
- /* 0xb9: oPCAL */ {0, 0, 0, regm_PCal},
- /* 0xba: oSYSIO */ {0, 0, 0, regm_SysIo},
- /* 0xbb: oLIB */ {0, 0, 0, regm_LibCall},
- /* 0xbc: oFLOAT */ {0, 0, 0, regm_Float},
- /* 0xbd: oLABEL */ {0, 0, 0, regm_NoOperation},
- /* 0xbe: oINCLUDE*/ {0, 0, 0, regm_NoOperation},
- /* 0xbf: oLINE */ {0, 0, 0, regm_NoOperation}
- };
-
-static const struct regm_builtin_s g_rgSysIoBuiltIns[MAX_XOP] =
-{
- /* 0x00 */ ILLEGAL_BUILTIN_INIT, xEOF_INIT,
- /* 0x02 */ xEOLN_INIT, xRESET_INIT,
- /* 0x04 */ xREWRITE_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x06 */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x08 */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x0a */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x0c */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x0e */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x10 */ xREADLN_INIT, xREAD_PAGE_INIT,
- /* 0x12 */ xREAD_BINARY_INIT, xREAD_INT_INIT,
- /* 0x14 */ xREAD_CHAR_INIT, xREAD_STRING_INIT,
- /* 0x16 */ xREAD_REAL_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x18 */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x1a */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x1c */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x1e */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x20 */ xWRITELN_INIT, xWRITE_PAGE_INIT,
- /* 0x22 */ xWRITE_BINARY_INIT, xWRITE_INT_INIT,
- /* 0x24 */ xWRITE_CHAR_INIT, xWRITE_STRING_INIT,
- /* 0x25 */ xWRITE_REAL_INIT
-};
-
-static const struct regm_builtin_s g_rgLibCallBuiltIns[MAX_LBOP] =
-{
- /* 0x00 */ lbGETENV_INIT, lbSTR2STR_INIT,
- /* 0x02 */ lbCSTR2STR_INIT, lbSTR2RSTR_INIT,
- /* 0x04 */ lbCSTR2RSTR_INIT, lbVAL_INIT,
- /* 0x06 */ lbMKSTK_INIT, lbMKSTKSTR_INIT,
- /* 0x08 */ lbMKSTKC_INIT, lbSTRCAT_INIT,
- /* 0x0a */ lbSTRCATC_INIT, lbSTRCMP_INIT
-};
-
-static const struct regm_builtin_s g_rgRrFopBuiltIns[MAX_FOP] =
-{
- /* 0x00 */ ILLEGAL_BUILTIN_INIT, fpFLOAT_INIT,
- /* 0x02 */ fpTRUNC_INIT, fpROUND_INIT,
- /* 0x04 */ fpADD_RR_INIT, fpSUB_RR_INIT,
- /* 0x06 */ fpMUL_RR_INIT, fpDIV_RR_INIT,
- /* 0x00 */ fpMOD_RR_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x0a */ fpEQU_RR_INIT, fpNEQ_RR_INIT,
- /* 0x0c */ fpLT_RR_INIT, fpGTE_RR_INIT,
- /* 0x0e */ fpGT_RR_INIT, fpLTE_RR_INIT,
- /* 0x10 */ fpNEG_R_INIT, fpABS_R_INIT,
- /* 0x12 */ fpSQR_R_INIT, fpSQRT_R_INIT,
- /* 0x14 */ fpSIN_R_INIT, fpCOS_R_INIT,
- /* 0x16 */ fpATAN_R_INIT, fpLN_R_INIT,
- /* 0x18 */ fpEXP_R_INIT
-};
-
-static const struct regm_builtin_s g_rgRiFopBuiltIns[MAX_FOP] =
-{
- /* 0x00 */ ILLEGAL_BUILTIN_INIT, fpFLOAT_INIT,
- /* 0x02 */ fpTRUNC_INIT, fpROUND_INIT,
- /* 0x04 */ fpADD_RI_INIT, fpSUB_RI_INIT,
- /* 0x06 */ fpMUL_RI_INIT, fpDIV_RI_INIT,
- /* 0x00 */ fpMOD_RI_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x0a */ fpEQU_RI_INIT, fpNEQ_RI_INIT,
- /* 0x0c */ fpLT_RI_INIT, fpGTE_RI_INIT,
- /* 0x0e */ fpGT_RI_INIT, fpLTE_RI_INIT,
- /* 0x10 */ fpNEG_I_INIT, fpABS_I_INIT,
- /* 0x12 */ fpSQR_I_INIT, fpSQRT_I_INIT,
- /* 0x14 */ fpSIN_I_INIT, fpCOS_I_INIT,
- /* 0x16 */ fpATAN_I_INIT, fpLN_I_INIT,
- /* 0x18 */ fpEXP_I_INIT
-};
-
-static const struct regm_builtin_s g_rgIrFopBuiltIns[MAX_FOP] =
-{
- /* 0x00 */ ILLEGAL_BUILTIN_INIT, fpFLOAT_INIT,
- /* 0x02 */ fpTRUNC_INIT, fpROUND_INIT,
- /* 0x04 */ fpADD_IR_INIT, fpSUB_IR_INIT,
- /* 0x06 */ fpMUL_IR_INIT, fpDIV_IR_INIT,
- /* 0x00 */ fpMOD_IR_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x0a */ fpEQU_IR_INIT, fpNEQ_IR_INIT,
- /* 0x0c */ fpLT_IR_INIT, fpGTE_IR_INIT,
- /* 0x0e */ fpGT_IR_INIT, fpLTE_IR_INIT,
- /* 0x10 */ fpNEG_R_INIT, fpABS_R_INIT,
- /* 0x12 */ fpSQR_R_INIT, fpSQRT_R_INIT,
- /* 0x14 */ fpSIN_R_INIT, fpCOS_R_INIT,
- /* 0x16 */ fpATAN_R_INIT, fpLN_R_INIT,
- /* 0x18 */ fpEXP_R_INIT
-};
-
-static const struct regm_builtin_s g_rgIiFopBuiltIns[MAX_FOP] =
-{
- /* 0x00 */ ILLEGAL_BUILTIN_INIT, fpFLOAT_INIT,
- /* 0x02 */ fpTRUNC_INIT, fpROUND_INIT,
- /* 0x04 */ fpADD_II_INIT, fpSUB_II_INIT,
- /* 0x06 */ fpMUL_II_INIT, fpDIV_II_INIT,
- /* 0x00 */ fpMOD_II_INIT, ILLEGAL_BUILTIN_INIT,
- /* 0x0a */ fpEQU_II_INIT, fpNEQ_II_INIT,
- /* 0x0c */ fpLT_II_INIT, fpGTE_II_INIT,
- /* 0x0e */ fpGT_II_INIT, fpLTE_II_INIT,
- /* 0x10 */ fpNEG_I_INIT, fpABS_I_INIT,
- /* 0x12 */ fpSQR_I_INIT, fpSQRT_I_INIT,
- /* 0x14 */ fpSIN_I_INIT, fpCOS_I_INIT,
- /* 0x16 */ fpATAN_I_INIT, fpLN_I_INIT,
- /* 0x18 */ fpEXP_I_INIT
-};
-
-static const struct regm_builtin_s *g_prgFopBuiltIns[4] =
-{
- /* Real - Real */ g_rgRrFopBuiltIns,
- /* Integer - Real */ g_rgRiFopBuiltIns,
- /* Real - Ingeter */ g_rgIrFopBuiltIns,
- /* Integer - Integer */ g_rgIiFopBuiltIns
-};
-
-/**********************************************************************
- * Private Functions
- **********************************************************************/
-
-/***********************************************************************/
-
-static void regm_NoOperation(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode, struct procdata_s *pNode)
-{
- TRACE(stderr, "[regm_NoOperation]");
-
- /* Do nothing */
-}
-
-/***********************************************************************/
-/* These pcodes are all binary operations in the sense that they take
- * one input and produce one output:
- *
- * INPUT: TOS(0)
- * OUTPUT: TOS(0)
- * Stack is unchanged.
- */
-
-static void regm_UnaryOperation(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode, struct procdata_s *pNode)
-{
- uint32 dwUnaryRegister = MKCCREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwCcRegister = MKCCREG(g_dwStackOffset);
-
- TRACE(stderr, "[regm_UnaryOperation]");
-
- switch (GETOP(pOpCode))
- {
- case oABS:
- regm_GenerateForm1ICc(rCMPI, dwUnaryRegister, 0, dwCcRegister);
- regm_GenerateForm4ICc(rBGTE, 2, dwCcRegister);
-
- default:
- regm_GenerateForm3I(pEntry->chOpCode, dwUnaryRegister,
- dwUnaryRegister, pEntry->chImmediate);
- break;
- }
-}
-
-/***********************************************************************/
-/* These pcodes are all binary operations in the sense that they take
- * two input:
- *
- * INPUT: TOS(0), TOS(-1)
- * OUTPUT: TOS(0)
- * Stack reduced by one.
- *
- * These all generate form 3r instructions:
- */
-
-static void regm_BinaryOperation(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwROperand1 = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwROperand2 = MKREG(g_dwStackOffset - 2*sINT_SIZE);
- uint32 dwRDest = dwROperand2;
-
- TRACE(stderr, "[regm_BinaryOperation]");
-
- /* Generate the binary operation */
-
- regm_GenerateForm3R(pEntry->chOpCode, dwRDest, dwROperand1, dwROperand2);
-
- /* Reduce stack */
-
- g_dwStackOffset -= sINT_SIZE;
-}
-
-/***********************************************************************/
-/* These pcodes are all boolean unary operations in the sense that
- * the pcode form takes one input and generates one output:
- *
- * INPUT: TOS(0)
- * OUTPUT: TOS(0)
- * Stack unchanged
- *
- * The complication is that the resulting boolean is not represented by
- * data in the register model but, rather, as a condition code setting.
- * For now we can, however, force a large number of condition code
- * registers; during a later fixup pass, we can force this to a single
- * condition code register.
- */
-
-static void regm_CompareVsZero(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwUnaryRegister = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwCcRegister = MKCCREG(g_dwStackOffset);
-
- TRACE(stderr, "[regm_CompareVsZero]");
-
- regm_GenerateForm1ICc(rCMPI, dwUnaryRegister, 0, dwCcRegister);
- regm_GenerateForm2I(rMOVI, dwUnaryRegister, 0);
- regm_GenerateForm4ICc(pEntry->chOpCode, 2, dwCcRegister);
- regm_GenerateForm2I(rMOVI, dwUnaryRegister, 1);
-}
-
-/***********************************************************************/
-/* These pcodes are all boolean binary operations in the sense that
- * the pcode form takes two inputs and generates one output:
- *
- * INPUT: TOS(0), TOS(-1)
- * OUTPUT: TOS(0)
- * Stack reduced by one.
- *
- * The complication is that the resulting boolean not represented by
- * data in the register model but, rather, as a condition code setting.
- * For now we can, however, force a large number of condition code
- * registers; during a later fixup pass, we can force this to a single
- * condition code register.
- */
-
-static void regm_BinaryComparison(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwROperand1 = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwROperand2 = MKREG(g_dwStackOffset - 2*sINT_SIZE);
- uint32 dwRDest = dwROperand2;
- uint32 dwCcRegister = MKCCREG(g_dwStackOffset);
-
- TRACE(stderr, "[regm_BinaryComparison]");
-
-
- switch (GETOP(pOpCode))
- {
- case oBIT:
- regm_GenerateForm3R(rAND, dwRDest, dwROperand1, dwROperand2);
- regm_GenerateForm1ICc(rCMPI, dwRDest, 0, dwCcRegister);
- break;
-
- default:
- regm_GenerateForm1RCc(rCMP, dwROperand1, dwROperand2, dwCcRegister);
- break;
- }
-
- regm_GenerateForm2I(rMOVI, dwRDest, 0);
- regm_GenerateForm4ICc(pEntry->chOpCode, 2, dwCcRegister);
- regm_GenerateForm2I(rMOVI, dwRDest, 1);
-
- /* Reduce stack */
-
- g_dwStackOffset -= sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Load from the address on the stack. Stack is unchanged */
-
-static void regm_LoadImmediate(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwROperand1 = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwRDest = dwROperand1;
-
- TRACE(stderr, "[regm_LoadImmediate]");
-
- /* Use the immediate value as an index against the SPB/LSP */
-
- regm_GenerateForm3R(pEntry->chOpCode, dwRDest, dwROperand1,
- MKSPECIAL(pEntry->chSpecial));
-}
-
-/***********************************************************************/
-/* Generic load multiple logic */
-
-static void regm_LoadMultiple(uint32 dwRDest, uint32 dwRSrc)
-{
- TRACE(stderr, "[regm_LoadMultiple]");
-
- if (g_bRegisterCountValid)
- {
- regm_GenerateForm3I(rLDM, dwRDest, dwRSrc, g_dwRegisterCount);
-
- /* Adjust the stack for the g_dwRegisterCount values added to the
- * stack.
- */
-
- g_dwStackOffset += g_dwRegisterCount * sINT_SIZE;
- g_bRegisterCountValid = 0;
- }
- else
- {
- fatal(ePOFFCONFUSION);
- }
-}
-
-/***********************************************************************/
-/* SPB/LSP relative source offset is on the stack. Stack increase determined
- * by content of DC register.
- */
-
-static void regm_LoadMultipleImmediate(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRSrc = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwRDest = dwRSrc;
-
- TRACE(stderr, "[regm_LoadMultipleImmediate]");
-
- /* Adjust the src for the SPB/LSP value and generate the multiple load */
-
- regm_GenerateForm3R(rADD, dwRSrc, dwRSrc, MKSPECIAL(pEntry->chSpecial));
- regm_LoadMultiple(dwRSrc, dwRDest);
-
- /* Stack will be increased by an amount determined by DC in
- * regm_LoadMultiple. However, we need to also account for the
- * immediate stack value that we consume here.
- */
-
- g_dwStackOffset -= sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Store value on stack to address on stack. Stack is reduced by two */
-
-static void regm_StoreImmediate(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRSrc = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwROperand1 = MKREG(g_dwStackOffset - 2*sINT_SIZE);
-
- TRACE(stderr, "[regm_StoreImmediate]");
-
- /* Use the immediate value as an index against the SPB/LSP */
-
- regm_GenerateForm3R(pEntry->chOpCode, dwRSrc, dwROperand1,
- MKSPECIAL(pEntry->chSpecial));
-
- /* Reduce stack */
-
- g_dwStackOffset -= 2*sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Generic store multiple logic */
-
-static void regm_StoreMultiple(uint32 dwRDest, uint32 dwRSrc)
-{
- TRACE(stderr, "[regm_StoreMultiple]");
-
- if (g_bRegisterCountValid)
- {
- regm_GenerateForm3I(rSTM, dwRSrc, dwRDest, g_dwRegisterCount);
-
- /* Adjust the stack for the g_dwRegisterCount values added to the
- * stack.
- */
-
- g_dwStackOffset -= g_dwRegisterCount * sINT_SIZE;
- g_bRegisterCountValid = 0;
- }
- else
- {
- fatal(ePOFFCONFUSION);
- }
-}
-
-/***********************************************************************/
-/* Store multiple values on stack to address on stack. Stack is reduced
- * by an amount determined by the content of DC.
- */
-
-static void regm_StoreMultipleImmediate(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRDest = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwRSrc = MKREG(g_dwStackOffset - (g_dwRegisterCount + 1)*sINT_SIZE);
-
- TRACE(stderr, "[regm_StoreMultipleImmediate]");
-
- /* Adjust the src for the SPB/LSP value and generate the multiple load */
-
- regm_GenerateForm3R(rADD, dwRDest, dwRDest, MKSPECIAL(pEntry->chSpecial));
- regm_StoreMultiple(dwRSrc, dwRDest);
-
- /* Stack will be increased by an amount determined by DC in
- * regm_StoreMultiple. However, we need to also account for the
- * immediate stack value that we consume here.
- */
-
- g_dwStackOffset -= sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Duplicate the TOS. stack increases by one */
-
-static void regm_Duplicate(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwROperand1 = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwRDest = MKREG(g_dwStackOffset);
-
- TRACE(stderr, "[regm_Duplicate]");
-
- /* Generate the binary operation */
-
- regm_GenerateForm2R(rMOV, dwRDest, dwROperand1);
-
- /* Increment the stack */
-
- g_dwStackOffset += sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Put the immediate value at the top of the stack. Increment stack */
-
-static void regm_PushImmediate(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRDest = g_dwStackOffset;
-
- TRACE(stderr, "[regm_PushImmediate]");
-
- /* The value may be too large to represent with a MOVI, but we'll handle
- * that later.
- */
-
- regm_GenerateForm2I(rMOVI, dwRDest, GETARG(pOpCode));
-
- /* Increment the stack */
-
- g_dwStackOffset += sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Push the special register onto the stack. Stack increments by one */
-
-static void regm_PushSpecial(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRDest = g_dwStackOffset;
-
- TRACE(stderr, "[regm_PushSpecial]");
-
- regm_GenerateForm2R(rMOV, dwRDest, MKSPECIAL(pEntry->chSpecial));
-
- /* Increment the stack */
-
- g_dwStackOffset += sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Pop the TOS into the special register. Stack decrements by one */
-
-static void regm_PopSpecial(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwROperand1 = MKREG(g_dwStackOffset - 1*sINT_SIZE);
-
- TRACE(stderr, "[regm_PopSpecial]");
-
- regm_GenerateForm2R(rMOV, MKSPECIAL(pEntry->chSpecial), dwROperand1);
-
- /* Decrement the stack */
-
- g_dwStackOffset -= sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Save the immediate value in the data count register */
-
-static void regm_SetDataCount(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- /* We don't acutally use the DC register. It is an artifact just
- * get here. We save the byte count as a even number of registers.
- */
-
- g_dwRegisterCount = (GETARG(pOpCode) + 3) >> 2;
- g_bRegisterCountValid = 1;
-}
-
-/***********************************************************************/
-
-static void regm_Return(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- TRACE(stderr, "[regm_Return]");
-
- /* This should have been processed by the prologue/epilogue logic */
-
- fatal(ePOFFCONFUSION);
-}
-
-/***********************************************************************/
-/* Load at offset from SPB/LSP. Stack increases by one */
-
-static void regm_LoadOffset(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRDest = g_dwStackOffset;
-
- TRACE(stderr, "[regm_LoadOffset]");
-
- /* Use the immediate value as an index against the SPB/LSP */
-
- regm_GenerateForm3I(pEntry->chOpCode, dwRDest, MKSPECIAL(pEntry->chSpecial),
- GETARG(pOpCode) >> pEntry->chImmediate);
-
- /* Increment the stack */
-
- g_dwStackOffset += sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Load multiple registgers at offset from SPB/LSP. Stack increase depends
- * on value in DC (only)
- */
-
-static void regm_LoadMultipleOffset(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRSrc = MKREG(g_dwStackOffset);
- uint32 dwRDest = dwRSrc;
-
- TRACE(stderr, "[regm_LoadMultipleOffset]");
-
- regm_GenerateForm3R(rADD, dwRSrc, MKSPECIAL(pEntry->chSpecial),
- GETARG(pOpCode));
- regm_LoadMultiple(dwRSrc, dwRDest);
-}
-
-/***********************************************************************/
-/* Store at offset from SPB/LSP. Stack decreases by one */
-
-static void regm_StoreOffset(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRSrc = MKREG(g_dwStackOffset - 1*sINT_SIZE);
-
- TRACE(stderr, "[regm_StoreOffset]");
-
- /* Use the immediate value as an index against the SPB/LSP */
-
- regm_GenerateForm3I(pEntry->chOpCode, dwRSrc,
- MKSPECIAL(pEntry->chSpecial),
- GETARG(pOpCode) >> pEntry->chImmediate);
-
- /* Decrement the stack */
-
- g_dwStackOffset -= sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Store multiple at offset from SPB/LSP. Stack decreases an amount
- * determined by the content of the DC regsiter.
- */
-
-static void regm_StoreMultipleOffset(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRSrc = MKREG(g_dwStackOffset - g_dwRegisterCount*sINT_SIZE);
- uint32 dwRDest;
-
- TRACE(stderr, "[regm_StoreMultipleOffset]");
-
- regm_GenerateForm3R(rADD, dwRDest, MKSPECIAL(pEntry->chSpecial),
- GETARG(pOpCode));
- regm_StoreMultiple(dwRSrc, dwRDest);
-}
-
-/***********************************************************************/
-/* Load value using index on stack + argument + SPB/LSP. Stack is unchanged */
-
-static void regm_LoadIndexed(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRIndex = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwRDest = dwRIndex;
-
- TRACE(stderr, "[regm_LoadIndexed]");
-
- /* Add the SPB/LSP to the index to make it relative to the stack,
- * then use this with the immediate values to obtain the data.
- */
-
- regm_GenerateForm3R(rADD, dwRIndex, dwRIndex,
- MKSPECIAL(pEntry->chSpecial));
- regm_GenerateForm3I(pEntry->chOpCode, dwRDest, dwRDest,
- GETARG(pOpCode) >> pEntry->chImmediate);
-}
-
-/***********************************************************************/
-/* Load multiple values using index on stack + argument + SPB/LSP. Stack
- * will increase my an amount that depends on the contents of DC.
- */
-
-static void regm_LoadMultipleIndexed(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRIndex = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwRSrc = dwRIndex;
- uint32 dwRDest = dwRIndex;
-
- TRACE(stderr, "[regm_LoadMultipleIndexed]");
-
- /* Add the SPB/LSP to the index to make it relative to the stack,
- * add the offset, then generate the multple load.
- */
-
- regm_GenerateForm3R(rADD, dwRSrc, dwRIndex,
- MKSPECIAL(pEntry->chSpecial));
- regm_GenerateForm3I(rADDI, dwRSrc, dwRSrc, GETARG(pOpCode));
- regm_LoadMultiple(dwRSrc, dwRDest);
-
- /* Stack will be increased by an amount determined by DC in
- * regm_LoadMultiple. However, we need to also account for the
- * index stack value that we consume here.
- */
-
- g_dwStackOffset -= sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Store value at TOS to index + offset + SPB/LSP. Stack decreases by two */
-
-static void regm_StoreIndexed(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRSrc = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwRIndex = MKREG(g_dwStackOffset - 2*sINT_SIZE);
-
- TRACE(stderr, "[regm_StoreIndexed]");
-
- /* Add the LSP to the index to make it relative to the stack,
- * then use this with the immediate values to obtain the data.
- */
-
- regm_GenerateForm3R(rADD, dwRIndex, dwRIndex,
- MKSPECIAL(pEntry->chSpecial));
- regm_GenerateForm3I(pEntry->chOpCode, dwRSrc, dwRIndex,
- GETARG(pOpCode) >> pEntry->chImmediate);
-
- /* Decrement the stack */
-
- g_dwStackOffset -= 2*sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Store values at TOS to index + offset + SPB/LSP. Stack decreases by
- * amount determined by the content of the DC register.
- */
-
-static void regm_StoreMultipleIndexed(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRIndex = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwRSrc = MKREG(g_dwStackOffset - (g_dwRegisterCount + 1)*sINT_SIZE);
- uint32 dwRDest;
-
- TRACE(stderr, "[regm_StoreMultipleIndexed]");
-
- /* Adjust the src for the SPB/LSP value and generate the multiple load */
-
- regm_GenerateForm3R(rADD, dwRDest, dwRIndex,
- MKSPECIAL(pEntry->chSpecial));
- regm_GenerateForm3I(rADDI, dwRDest, dwRDest, GETARG(pOpCode));
- regm_StoreMultiple(dwRSrc, dwRDest);
-
- /* Stack will be increased by an amount determined by DC in
- * regm_StoreMultiple. However, we need to also account for the
- * immediate stack value that we consume here.
- */
-
- g_dwStackOffset -= sINT_SIZE;
-}
-
-/***********************************************************************/
-/* These pcodes are all conditional branch operations. The pcode form
- * takes one input (that is compared with zero) and branches based
- * the result. The stack is decremented by one.
- */
-
-static void regm_ConditionalBranchVsZero(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwUnaryRegister = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwCcRegister = MKCCREG(g_dwStackOffset);
-
- TRACE(stderr, "[regm_ConditionalBranchVsZero]");
-
-
- regm_GenerateForm1ICc(rCMPI, dwUnaryRegister, 0, dwCcRegister);
- regm_GenerateForm4ICc(pEntry->chOpCode, GETARG(pOpCode), dwCcRegister);
-
- /* Decrement the stack */
-
- g_dwStackOffset -= sINT_SIZE;
-}
-
-/***********************************************************************/
-/* These pcodes are all conditional branch operations. The pcode form
- * takes two inputs that are compared. The pcode branches on the result
- * of the comparison. The stack is reduced by two.
- */
-
-static void regm_ConditionalBranchBinary(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwROperand1 = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwROperand2 = MKREG(g_dwStackOffset - 2*sINT_SIZE);
- uint32 dwCcRegister = MKCCREG(g_dwStackOffset);
-
- TRACE(stderr, "[regm_BinaryComparison]");
-
- /* Generate the compare and branch */
-
- regm_GenerateForm1RCc(rCMP, dwROperand1, dwROperand2, dwCcRegister);
- regm_GenerateForm4ICc(pEntry->chOpCode, GETARG(pOpCode), dwCcRegister);
-
- /* Reduce stack */
-
- g_dwStackOffset -= 2*sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Branch unconditionally. The stack is not changed */
-
-static void regm_UnconditionalBranch(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- TRACE(stderr, "[regm_UnconditionalBranch]");
- regm_GenerateForm4I(rB, GETARG(pOpCode));
-}
-
-/***********************************************************************/
-/* Add constant value to special register. Stack does not change */
-
-static void regm_IncrementSpecial(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- sint32 dwIncrement = (sint32)(GETOP(pOpCode));
- uint32 dwRSpecial = MKSPECIAL(pEntry->chSpecial);
- TRACE(stderr, "[regm_IncrementSpecial]");
-
- /* The value may be too large to represent with a MOVI, but we'll handle
- * that later.
- */
-
- if (dwIncrement < 0)
- {
- regm_GenerateForm3I(rSUBI, dwRSpecial, dwRSpecial, -dwIncrement);
- }
- else if (dwIncrement > 0)
- {
- regm_GenerateForm3I(rADDI, dwRSpecial, dwRSpecial, dwIncrement);
- }
-
- if (pEntry->chSpecial == SP)
- {
- g_dwStackOffset += dwIncrement;
- }
-}
-
-/***********************************************************************/
-/* Load address at offset from special register. Stack increases by one */
-
-static void regm_LoadAddress(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRDest = g_dwStackOffset;
-
- TRACE(stderr, "[regm_LoadAddress]");
-
- /* Use the immediate value as an index against the SPB/LSP */
-
- regm_GenerateForm3I(rADD, dwRDest, MKSPECIAL(pEntry->chSpecial),
- GETARG(pOpCode));
-
- /* Increment the stack */
-
- g_dwStackOffset += sINT_SIZE;
-}
-
-/***********************************************************************/
-/* Load address at indexed offset from special register. Stack is unchanged */
-
-static void regm_LoadAddressIndexed(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- uint32 dwRIndex = MKREG(g_dwStackOffset - 1*sINT_SIZE);
- uint32 dwRDest = dwRIndex;
-
- TRACE(stderr, "[regm_LoadAddressIndexed]");
-
- /* Add the LSP or SPB to the index to make it relative to the stack,
- * then use this with the immediate values to obtain the data.
- */
-
- regm_GenerateForm3R(rADD, dwRIndex, dwRIndex,
- MKSPECIAL(pEntry->chSpecial));
- regm_GenerateForm3I(rADD, dwRDest, dwRIndex, GETARG(pOpCode));
-}
-
-/***********************************************************************/
-
-static void regm_SetupOutArgs(uint32 nParms, const uint32 *pwArgSize)
-{
- int nArgRegs;
- sint32 dwOffset;
- int i;
-
- for (i = 0, nArgRegs = 0; i < nParms; i++)
- {
- nArgRegs += (pwArgSize[i] + 3) >> 2;
- }
-
- /* Emit move instructions to handle each */
-
- dwOffset = g_dwStackOffset - sINT_SIZE;
- for (i = 0; i < nArgRegs; i++)
- {
- uint32 dwDest = MKOUTARG(i);
- uint32 dwSrc = MKREG(dwOffset);
-
- regm_GenerateForm2R(rMOV, dwDest, dwSrc);
- dwOffset -= sINT_SIZE;
- }
-}
-
-/***********************************************************************/
-
-static void regm_MapInRet(uint32 wRetSize)
-{
- int nRetRegs;
- sint32 dwOffset;
- int i;
-
- /* Get the number of registers that are returned */
-
- nRetRegs += (wRetSize + 3) >> 2;
-
- /* Emit move instructions to handle each */
-#warning "This offset is not correct"
- dwOffset = g_dwStackOffset - sINT_SIZE;
- for (i = 0; i < nRetRegs; i++)
- {
- uint32 dwSrc = MKINRET(i);
- uint32 dwDest = MKREG(dwOffset);
-
- regm_GenerateForm2R(rMOV, dwDest, dwSrc);
- dwOffset -= sINT_SIZE;
- }
-}
-
-/***********************************************************************/
-
-static void regm_PCal(const struct regm_opmap_s *pEntry, OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- poffLibDebugFuncInfo_t *pFuncInfo = pNode->pFuncInfo;
-
- TRACE(stderr, "[regm_PCal]");
-
- if (!pFuncInfo)
- {
- fatal(ePOFFCONFUSION);
- }
-
- /* Map the "output" parameter stack to a set of "output" argument
- * registers.
- */
-
- regm_SetupOutArgs(pFuncInfo->nparms, pFuncInfo->argsize);
-
- regm_GenerateForm3I(rADDI, MKSPECIAL(SP), MKSPECIAL(SP), 3*sINT_SIZE);
- regm_GenerateForm3I(rST, MKSPECIAL(LSP), MKSPECIAL(SP), -3);
- regm_GenerateForm3I(rST, MKSPECIAL(BRG), MKSPECIAL(SP), -2);
- regm_GenerateForm4I(rBL, GETARG(pOpCode));
-
-#warning "This is in the wrong place"
- regm_MapInRet(pFuncInfo->retsize);
-
- /* Increment the stack */
-
- g_dwStackOffset += 3*sINT_SIZE;
-}
-
-/***********************************************************************/
-
-static void regm_SysIo(const struct regm_opmap_s *pEntry, OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- const struct regm_builtin_s *pBuiltIn;
- uint32 xop;
-
- TRACE(stderr, "[regm_SysIo]");
-
- /* Get the function information for this sysio xop */
-
- xop = GETARG(pOpCode);
- if (xop >= MAX_XOP)
- {
- fatal(ePOFFCONFUSION);
- }
-
- pBuiltIn = &g_rgSysIoBuiltIns[xop];
-
- /* Map the "output" parameter stack to a set of "output" argument
- * registers.
- */
-
- regm_SetupOutArgs(pBuiltIn->nParms, pBuiltIn->wArgSize);
-
- /* Generate a call to the runtime library */
-
-#warning "Not implemented"
-
- /* Handled returned values */
-
- regm_MapInRet(pBuiltIn->wRetSize);
-}
-
-/***********************************************************************/
-
-static void regm_LibCall(const struct regm_opmap_s *pEntry, OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- const struct regm_builtin_s *pBuiltIn;
- uint32 lbop;
-
- TRACE(stderr, "[regm_LibCall]");
-
- /* Get the function information for this library op */
-
- lbop = GETARG(pOpCode);
- if (lbop >= MAX_LBOP)
- {
- fatal(ePOFFCONFUSION);
- }
-
- pBuiltIn = &g_rgLibCallBuiltIns[lbop];
-
- /* Map the "output" parameter stack to a set of "output" argument
- * registers.
- */
-
- regm_SetupOutArgs(pBuiltIn->nParms, pBuiltIn->wArgSize);
-
- /* Generate a call to the runtime library */
-
-#warning "Not implemented"
-
- /* Handled returned values */
-
- regm_MapInRet(pBuiltIn->wRetSize);
-}
-
-/***********************************************************************/
-
-static void regm_Float(const struct regm_opmap_s *pEntry, OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- static const struct regm_builtin_s *pFopBuiltIns;
- const struct regm_builtin_s *pBuiltIn;
- uint32 foptab;
- uint32 fop;
-
- TRACE(stderr, "[regm_FLoat]");
-
- /* Select the correct table for the builtin */
-
- foptab = (GETARG(pOpCode) & ~fpMASK) >> fpSHIFT;
- pFopBuiltIns = g_prgFopBuiltIns[foptab];
-
- /* Select the correct function from the table for this floating
- * point operation.
- */
-
- fop = GETARG(pOpCode) & fpMASK;
- if (fop >= MAX_FOP)
- {
- fatal(ePOFFCONFUSION);
- }
- pBuiltIn = &pFopBuiltIns[fop];
-
- /* Map the "output" parameter stack to a set of "output" argument
- * registers.
- */
-
- regm_SetupOutArgs(pBuiltIn->nParms, pBuiltIn->wArgSize);
-
- /* Generate a call to the runtime library */
-
-#warning "Not implemented"
-
- /* Handled returned values */
-
- regm_MapInRet(pBuiltIn->wRetSize);
-}
-
-/***********************************************************************/
-
-static void regm_IllegalPCode(const struct regm_opmap_s *pEntry,
- OPTYPE *pOpCode,
- struct procdata_s *pNode)
-{
- TRACE(stderr, "[regm_IllegalPCode]");
- fatal(eILLEGALOPCODE);
-}
-
-/***********************************************************************/
-
-static void regm_GenerateRegm(struct procdata_s *pNode, void *pvArg)
-{
- sint32 dwFrameSize = 0;
- int i, j;
-
- TRACE(stderr, "[regm_GenerateRegm]");
-
- /* Analyze the proc/func prologue */
-
- i = 0; j = pNode->nPCodes;
- if (GETOP(&pNode->pPCode[0]) == oINDS)
- {
- dwFrameSize = GETARG(&pNode->pPCode[0]);
- i++; j--;
- }
- regm_GeneratePrologue(dwFrameSize);
-
- /* Set the initial stack offset. Parameters will look like
- * negative offsets; local stack will look positive.
- */
-
- g_dwStackOffset = dwFrameSize;
-
- /* Generate regm code for each p-code */
-
- for (; i < j; i++)
- {
- const struct regm_opmap_s *rgOpMap;
- ubyte chOpCode = GETOP(&pNode->pPCode[i]);
-
- /* Select the right decode table */
-
- if ((chOpCode & o32) != 0)
- {
- rgOpMap = vrgOpMap2;
- chOpCode &= ~o32;
- }
- else
- {
- rgOpMap = vrgOpMap1;
- }
-
- /* Make sure that the table index is within range */
-
- if (chOpCode > 63)
- {
- fatal(eBADSHORTINT);
- }
-
- /* Perform the opcode mapping */
-
- rgOpMap->pMapper(rgOpMap, &pNode->pPCode[i], pNode);
- }
-
- /* If a frame was obtained at the beginning, make sure that
- * there is matching frame release logic at the end.
- */
-
- if (dwFrameSize > 0)
- {
- if ((GETOP(&pNode->pPCode[i]) != oINDS) ||
- (dwFrameSize != -(sint32)GETARG(&pNode->pPCode[i])))
- {
- fatal(ePOFFCONFUSION);
- }
- i++;
- }
-
- /* Analyze the proc/func epilogue */
-
- if ((GETOP(&pNode->pPCode[i]) != oRET) &&
- (GETOP(&pNode->pPCode[i]) != oEND))
- {
- fatal(ePOFFCONFUSION);
- }
- regm_GenerateEpilogue(dwFrameSize);
-}
-
-/***********************************************************************/
-
-static int regm_Pass2Node(struct procdata_s *pNode, void *pvArg)
-{
- TRACE(stderr, "[regm_Pass2Node]");
-
- /* Generate code for each child of this proc/func block */
-
- if (pNode->child)
- {
- (void)regm_ForEachChild(pNode->child, regm_Pass2Node, pvArg);
- }
-
- /* Generate code for this node */
-
- regm_GenerateRegm(pNode, pvArg);
-
- /* Does this node have a peer at the same level? If so, then
- * do the same for its peer.
- */
-
- if (pNode->peer)
- {
- (void)regm_Pass2Node(pNode->peer, pvArg);
- }
-
- return 0;
-}
-
-/**********************************************************************
- * Public Functions
- **********************************************************************/
-
-/***********************************************************************/
-/* Pass 2: Convert the buffered pcode to the basic register model with
- * an indefinite number of registers (arguments, general, and special
- * registers) and with 32-bit immediate size.
- */
-
-void regm_Pass2(poffHandle_t hPoff)
-{
- TRACE(stderr, "[regm_Pass2]");
-
- /* Initiate traversal at the root node */
-
- (void)regm_Pass2Node(regm_GetRootNode(), NULL);
-}
-
-/***********************************************************************/
-
+/********************************************************************** + * regm_pass2.c + * Convert the buffered pcode to the basic register model with an + * indefinite number of registers (arguments, general, and special + * registers) and with 32-bit immediate size. + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt <spudmonkey@racsa.co.cr> + * + * 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. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + *********************************************************************/ + +/********************************************************************** + * Included Files + **********************************************************************/ + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "keywords.h" +#include "pdefs.h" +#include "pxdefs.h" +#include "pfdefs.h" +#include "pedefs.h" +#include "pofflib.h" +#include "perr.h" + +#include "pinsn32.h" +#include "builtins.h" + +#include "regm.h" +#include "regm_tree.h" +#include "regm_registers2.h" +#include "regm_pass2.h" + +/************************************a********************************* + * Definitions + **********************************************************************/ + +/********************************************************************** + * Private Types + **********************************************************************/ + +struct regm_opmap_s; + +typedef void (*regm_mapper_t)(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, struct procdata_s *pNode); + +struct regm_opmap_s +{ + uint8_t chOpCode; + int8_t chImmediate; + int8_ chSpecial; + regm_mapper_t pMapper; +}; + +/********************************************************************** + * Private Function Prototypes + **********************************************************************/ + +static void regm_NoOperation(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_UnaryOperation(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_BinaryOperation(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_CompareVsZero(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_BinaryComparison(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_LoadImmediate(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_LoadMultiple(uint32_t dwRDest, uint32_t dwRSrc); +static void regm_LoadMultipleImmediate(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_StoreMultiple(uint32_t dwRDest, uint32_t dwRSrc); +static void regm_StoreImmediate(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_StoreMultipleImmediate(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_Duplicate(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_PushImmediate(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_PopSpecial(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_SetDataCount(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_PushSpecial(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_Return(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_LoadOffset(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_LoadMultipleOffset(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_StoreOffset(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_StoreMultipleOffset(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_LoadIndexed(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, struct procdata_s *pNode); +static void regm_LoadMultipleIndexed(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_StoreIndexed(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, struct procdata_s *pNode); +static void regm_StoreMultipleIndexed(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_ConditionalBranchVsZero(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_ConditionalBranchBinary(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_UnconditionalBranch(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_IncrementSpecial(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_LoadAddress(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, struct procdata_s *pNode); +static void regm_LoadAddressIndexed(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_SetupOutArgs(uint32_t nParms, const uint32_t *pwArgSize); +static void regm_MapInRet(uint32_t wRetSize); +static void regm_PCal(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_SysIo(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_LibCall(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_Float(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); +static void regm_IllegalPCode(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode); + +static void regm_GenerateRegm(struct procdata_s *pNode, void *pvArg); +static int regm_Pass2Node(struct procdata_s *pNode, void *pvArg); + +/********************************************************************** + * Public Variables + **********************************************************************/ + +/* On the initialize passes, the register number will simply be the offset + * from the top of the stack. The following variable keeps trck of the + * stack offset. + */ + +uint32_t g_dwStackOffset; +uint32_t g_dwRegisterCount = 0; +int g_bRegisterCountValid = 0; + +/********************************************************************** + * Private Variables + **********************************************************************/ + +static const struct regm_opmap_s vrgOpMap1[64] = + { + /* 0x00: oNOP */ {0, 0, 0, regm_NoOperation}, + /* 0x01: oNEG */ {rRSBI, 0, 0, regm_UnaryOperation}, + /* 0x02: oABS */ {rRSB, 0, 0, regm_UnaryOperation}, + /* 0x03: oINC */ {rADDI, 1, 0, regm_UnaryOperation}, + /* 0x04: oDEC */ {rSUBI, 1, 0, regm_UnaryOperation}, + /* 0x05: oNOT */ {rMVN, 0, 0, regm_UnaryOperation}, + /* 0x06: oADD */ {rADD, 0, 0, regm_BinaryOperation}, + /* 0x07: oSUB */ {rSUB, 0, 0, regm_BinaryOperation}, + /* 0x08: oMUL */ {rMUL, 0, 0, regm_BinaryOperation}, + /* 0x09: oDIV */ {rDIV, 0, 0, regm_BinaryOperation}, + /* 0x0a: oMOD */ {rMOD, 0, 0, regm_BinaryOperation}, + /* 0x0b: oSLL */ {rSLL, 0, 0, regm_BinaryOperation}, + /* 0x0c: oSRL */ {rSRL, 0, 0, regm_BinaryOperation}, + /* 0x0d: oSRA */ {rSRA, 0, 0, regm_BinaryOperation}, + /* 0x0e: oOR */ {rOR, 0, 0, regm_BinaryOperation}, + /* 0x0f: oAND */ {rAND, 0, 0, regm_BinaryOperation}, + + /* 0x10: oEQUZ */ {rBEQ, 0, 0, regm_CompareVsZero}, + /* 0x11: oNEQZ */ {rBNE, 0, 0, regm_CompareVsZero}, + /* 0x12: oLTZ */ {rBLT, 0, 0, regm_CompareVsZero}, + /* 0x13: oGTEZ */ {rBGTE, 0, 0, regm_CompareVsZero}, + /* 0x14: oGTZ */ {rBGT, 0, 0, regm_CompareVsZero}, + /* 0x15: oLTEZ */ {rBLTE, 0, 0, regm_CompareVsZero}, + /* 0x16: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x17: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x18: oEQU */ {rBEQ, 0, 0, regm_BinaryComparison}, + /* 0x19: oNEQ */ {rBNE, 0, 0, regm_BinaryComparison}, + /* 0x1a: oLT */ {rBLT, 0, 0, regm_BinaryComparison}, + /* 0x1b: oGTE */ {rBGTE, 0, 0, regm_BinaryComparison}, + /* 0x1c: oGT */ {rBGT, 0, 0, regm_BinaryComparison}, + /* 0x1d: oLTE */ {rBLTE, 0, 0, regm_BinaryComparison}, + /* 0x1e: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x1f: oBIT */ {rBEQ, 0, 0, regm_BinaryComparison}, + + /* 0x20: oLDI */ {rLD, 2, SPB, regm_LoadImmediate}, + /* 0x21: oLDIH */ {rLDH, 1, SPB, regm_LoadImmediate}, + /* 0x22: oLDIB */ {rLDB, 0, SPB, regm_LoadImmediate}, + /* 0x23: oLDIM */ {0, 0, SPB, regm_LoadMultipleImmediate}, + /* 0x24: oSTI */ {rST, 2, SPB, regm_StoreImmediate}, + /* 0x25: oSTIH */ {rSTH, 1, SPB, regm_StoreImmediate}, + /* 0x26: oSTIB */ {rSTB, 0, SPB, regm_StoreImmediate}, + /* 0x27: oSTIM */ {0, 0, SPB, regm_StoreMultipleImmediate}, + /* 0x28: oDUP */ {0, 0, 0, regm_Duplicate}, + /* 0x17: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x2a: oPUSHS */ {0, 0, CSP, regm_PushSpecial}, + /* 0x2b: oPOPS */ {0, 0, CSP, regm_PopSpecial}, + /* 0x2c: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x2d: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x2e: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x2f: oRET */ {0, 0, 0, regm_Return}, + + /* 0x30: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x31: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x32: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x33: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x34: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x35: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x36: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x37: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x38: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x39: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x3a: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x3b: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x3c: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x3d: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x3e: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x3f: oEND */ {0, 0, 0, regm_Return} + }; + +static const struct regm_opmap_s vrgOpMap2[64] = + { + /* 0x80: oLD */ {rLD, 2, SPB, regm_LoadOffset}, + /* 0x81: oLDH */ {rLDH, 1, SPB, regm_LoadOffset}, + /* 0x82: oLDB */ {rLDB, 0, SPB, regm_LoadOffset}, + /* 0x83: oLDM */ {0, 0, SPB, regm_LoadMultipleOffset}, + /* 0x84: oST */ {rST, 2, SPB, regm_StoreOffset}, + /* 0x85: oSTH */ {rSTH, 1, SPB, regm_StoreOffset}, + /* 0x86: oSTB */ {rSTB, 0, SPB, regm_StoreOffset}, + /* 0x87: oSTM */ {0, 0, SPB, regm_StoreMultipleOffset}, + /* 0x88: oLDX */ {rLD, 2, SPB, regm_LoadIndexed}, + /* 0x89: oLDXH */ {rLDH, 1, SPB, regm_LoadIndexed}, + /* 0x8a: oLDXB */ {rLDB, 0, SPB, regm_LoadIndexed}, + /* 0x8b: oLDXM */ {0, 0, SPB, regm_LoadMultipleIndexed}, + /* 0x8c: oSTX */ {rST, 2, SPB, regm_StoreIndexed}, + /* 0x8d: oSTXH */ {rSTH, 1, SPB, regm_StoreIndexed}, + /* 0x8e: oSTXB */ {rSTB, 0, SPB, regm_StoreIndexed}, + /* 0x8f: oSTXM */ {0, 0, SPB, regm_StoreMultipleIndexed}, + + /* 0x90: oJEQUZ */ {rBEQ, 0, 0, regm_ConditionalBranchVsZero}, + /* 0x91: oJNEQZ */ {rBNE, 0, 0, regm_ConditionalBranchVsZero}, + /* 0x92: oJLTZ */ {rBLT, 0, 0, regm_ConditionalBranchVsZero}, + /* 0x93: oJGTEZ */ {rBGTE, 0, 0, regm_ConditionalBranchVsZero}, + /* 0x94: oJGTZ */ {rBGT, 0, 0, regm_ConditionalBranchVsZero}, + /* 0x95: oJLTEZ */ {rBLTE, 0, 0, regm_ConditionalBranchVsZero}, + /* 0x96: oJMP */ {rB, 0, 0, regm_UnconditionalBranch}, + /* 0x97: oPUSH */ {0, 0, 0, regm_PushImmediate}, + /* 0x98: oJEQU */ {rBEQ, 0, 0, regm_ConditionalBranchBinary}, + /* 0x99: oJNEQ */ {rBNE, 0, 0, regm_ConditionalBranchBinary}, + /* 0x9a: oJLT */ {rBLT, 0, 0, regm_ConditionalBranchBinary}, + /* 0x9b: oJGTE */ {rBGTE, 0, 0, regm_ConditionalBranchBinary}, + /* 0x9c: oJGT */ {rBGT, 0, 0, regm_ConditionalBranchBinary}, + /* 0x9d: oJLTE */ {rBLTE, 0, 0, regm_ConditionalBranchBinary}, + /* 0x9e: */ {0, 0, 0, regm_IllegalPCode}, + /* 0x9f: oINDS */ {0, 0, SP, regm_IncrementSpecial}, + + /* 0xa0: oLDS */ {rLD, 2, LSP, regm_LoadOffset}, + /* 0xa1: oLDSH */ {rLDH, 1, LSP, regm_LoadOffset}, + /* 0xa2: oLDSB */ {rLDB, 0, LSP, regm_LoadOffset}, + /* 0xa3: oLDSM */ {0, 0, LSP, regm_LoadMultipleOffset}, + /* 0xa4: oSTS */ {rST, 2, LSP, regm_StoreOffset}, + /* 0xa5: oSTSH */ {rSTH, 1, LSP, regm_StoreOffset}, + /* 0xa6: oSTSB */ {rSTB, 0, LSP, regm_StoreOffset}, + /* 0xa7: oSTSM */ {0, 0, LSP, regm_StoreMultipleOffset}, + /* 0xa8: oLDSX */ {rLD, 2, LSP, regm_LoadIndexed}, + /* 0xa9: oLDSXH */ {rLDH, 1, LSP, regm_LoadIndexed}, + /* 0xaa: oLDSXB */ {rLDB, 0, LSP, regm_LoadIndexed}, + /* 0xab: oLDSXM */ {0, 0, LSP, regm_LoadMultipleIndexed}, + /* 0xac: oSTSX */ {rST, 2, LSP, regm_StoreIndexed}, + /* 0xad: oSTSXH */ {rSTH, 1, LSP, regm_StoreIndexed}, + /* 0xae: oSTSXB */ {rSTB, 0, LSP, regm_StoreIndexed}, + /* 0xaf: oSTSXM */ {0, 0, LSP, regm_StoreMultipleIndexed}, + + /* 0xb0: oLA */ {0, 0, SPB, regm_LoadAddress}, + /* 0xb1: oLAS */ {0, 0, LSP, regm_LoadAddress}, + /* 0xb2: oLAC */ {0, 0, CSB, regm_LoadAddress}, + /* 0xb3: */ {0, 0, 0, regm_IllegalPCode}, + /* 0xb4: oLAX */ {0, 0, SPB, regm_LoadAddressIndexed}, + /* 0xb5: oLASX */ {0, 0, LSP, regm_LoadAddressIndexed}, + /* 0xb6: oSLSP */ {0, 0, LSP, regm_PopSpecial}, + /* 0xb7: oSDC */ {0, 0, DC, regm_SetDataCount}, + /* 0xb8: */ {0, 0, 0, regm_IllegalPCode}, + /* 0xb9: oPCAL */ {0, 0, 0, regm_PCal}, + /* 0xba: oSYSIO */ {0, 0, 0, regm_SysIo}, + /* 0xbb: oLIB */ {0, 0, 0, regm_LibCall}, + /* 0xbc: oFLOAT */ {0, 0, 0, regm_Float}, + /* 0xbd: oLABEL */ {0, 0, 0, regm_NoOperation}, + /* 0xbe: oINCLUDE*/ {0, 0, 0, regm_NoOperation}, + /* 0xbf: oLINE */ {0, 0, 0, regm_NoOperation} + }; + +static const struct regm_builtin_s g_rgSysIoBuiltIns[MAX_XOP] = +{ + /* 0x00 */ ILLEGAL_BUILTIN_INIT, xEOF_INIT, + /* 0x02 */ xEOLN_INIT, xRESET_INIT, + /* 0x04 */ xREWRITE_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x06 */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x08 */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x0a */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x0c */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x0e */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x10 */ xREADLN_INIT, xREAD_PAGE_INIT, + /* 0x12 */ xREAD_BINARY_INIT, xREAD_INT_INIT, + /* 0x14 */ xREAD_CHAR_INIT, xREAD_STRING_INIT, + /* 0x16 */ xREAD_REAL_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x18 */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x1a */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x1c */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x1e */ ILLEGAL_BUILTIN_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x20 */ xWRITELN_INIT, xWRITE_PAGE_INIT, + /* 0x22 */ xWRITE_BINARY_INIT, xWRITE_INT_INIT, + /* 0x24 */ xWRITE_CHAR_INIT, xWRITE_STRING_INIT, + /* 0x25 */ xWRITE_REAL_INIT +}; + +static const struct regm_builtin_s g_rgLibCallBuiltIns[MAX_LBOP] = +{ + /* 0x00 */ lbGETENV_INIT, lbSTR2STR_INIT, + /* 0x02 */ lbCSTR2STR_INIT, lbSTR2RSTR_INIT, + /* 0x04 */ lbCSTR2RSTR_INIT, lbVAL_INIT, + /* 0x06 */ lbMKSTK_INIT, lbMKSTKSTR_INIT, + /* 0x08 */ lbMKSTKC_INIT, lbSTRCAT_INIT, + /* 0x0a */ lbSTRCATC_INIT, lbSTRCMP_INIT +}; + +static const struct regm_builtin_s g_rgRrFopBuiltIns[MAX_FOP] = +{ + /* 0x00 */ ILLEGAL_BUILTIN_INIT, fpFLOAT_INIT, + /* 0x02 */ fpTRUNC_INIT, fpROUND_INIT, + /* 0x04 */ fpADD_RR_INIT, fpSUB_RR_INIT, + /* 0x06 */ fpMUL_RR_INIT, fpDIV_RR_INIT, + /* 0x00 */ fpMOD_RR_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x0a */ fpEQU_RR_INIT, fpNEQ_RR_INIT, + /* 0x0c */ fpLT_RR_INIT, fpGTE_RR_INIT, + /* 0x0e */ fpGT_RR_INIT, fpLTE_RR_INIT, + /* 0x10 */ fpNEG_R_INIT, fpABS_R_INIT, + /* 0x12 */ fpSQR_R_INIT, fpSQRT_R_INIT, + /* 0x14 */ fpSIN_R_INIT, fpCOS_R_INIT, + /* 0x16 */ fpATAN_R_INIT, fpLN_R_INIT, + /* 0x18 */ fpEXP_R_INIT +}; + +static const struct regm_builtin_s g_rgRiFopBuiltIns[MAX_FOP] = +{ + /* 0x00 */ ILLEGAL_BUILTIN_INIT, fpFLOAT_INIT, + /* 0x02 */ fpTRUNC_INIT, fpROUND_INIT, + /* 0x04 */ fpADD_RI_INIT, fpSUB_RI_INIT, + /* 0x06 */ fpMUL_RI_INIT, fpDIV_RI_INIT, + /* 0x00 */ fpMOD_RI_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x0a */ fpEQU_RI_INIT, fpNEQ_RI_INIT, + /* 0x0c */ fpLT_RI_INIT, fpGTE_RI_INIT, + /* 0x0e */ fpGT_RI_INIT, fpLTE_RI_INIT, + /* 0x10 */ fpNEG_I_INIT, fpABS_I_INIT, + /* 0x12 */ fpSQR_I_INIT, fpSQRT_I_INIT, + /* 0x14 */ fpSIN_I_INIT, fpCOS_I_INIT, + /* 0x16 */ fpATAN_I_INIT, fpLN_I_INIT, + /* 0x18 */ fpEXP_I_INIT +}; + +static const struct regm_builtin_s g_rgIrFopBuiltIns[MAX_FOP] = +{ + /* 0x00 */ ILLEGAL_BUILTIN_INIT, fpFLOAT_INIT, + /* 0x02 */ fpTRUNC_INIT, fpROUND_INIT, + /* 0x04 */ fpADD_IR_INIT, fpSUB_IR_INIT, + /* 0x06 */ fpMUL_IR_INIT, fpDIV_IR_INIT, + /* 0x00 */ fpMOD_IR_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x0a */ fpEQU_IR_INIT, fpNEQ_IR_INIT, + /* 0x0c */ fpLT_IR_INIT, fpGTE_IR_INIT, + /* 0x0e */ fpGT_IR_INIT, fpLTE_IR_INIT, + /* 0x10 */ fpNEG_R_INIT, fpABS_R_INIT, + /* 0x12 */ fpSQR_R_INIT, fpSQRT_R_INIT, + /* 0x14 */ fpSIN_R_INIT, fpCOS_R_INIT, + /* 0x16 */ fpATAN_R_INIT, fpLN_R_INIT, + /* 0x18 */ fpEXP_R_INIT +}; + +static const struct regm_builtin_s g_rgIiFopBuiltIns[MAX_FOP] = +{ + /* 0x00 */ ILLEGAL_BUILTIN_INIT, fpFLOAT_INIT, + /* 0x02 */ fpTRUNC_INIT, fpROUND_INIT, + /* 0x04 */ fpADD_II_INIT, fpSUB_II_INIT, + /* 0x06 */ fpMUL_II_INIT, fpDIV_II_INIT, + /* 0x00 */ fpMOD_II_INIT, ILLEGAL_BUILTIN_INIT, + /* 0x0a */ fpEQU_II_INIT, fpNEQ_II_INIT, + /* 0x0c */ fpLT_II_INIT, fpGTE_II_INIT, + /* 0x0e */ fpGT_II_INIT, fpLTE_II_INIT, + /* 0x10 */ fpNEG_I_INIT, fpABS_I_INIT, + /* 0x12 */ fpSQR_I_INIT, fpSQRT_I_INIT, + /* 0x14 */ fpSIN_I_INIT, fpCOS_I_INIT, + /* 0x16 */ fpATAN_I_INIT, fpLN_I_INIT, + /* 0x18 */ fpEXP_I_INIT +}; + +static const struct regm_builtin_s *g_prgFopBuiltIns[4] = +{ + /* Real - Real */ g_rgRrFopBuiltIns, + /* Integer - Real */ g_rgRiFopBuiltIns, + /* Real - Ingeter */ g_rgIrFopBuiltIns, + /* Integer - Integer */ g_rgIiFopBuiltIns +}; + +/********************************************************************** + * Private Functions + **********************************************************************/ + +/***********************************************************************/ + +static void regm_NoOperation(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, struct procdata_s *pNode) +{ + TRACE(stderr, "[regm_NoOperation]"); + + /* Do nothing */ +} + +/***********************************************************************/ +/* These pcodes are all binary operations in the sense that they take + * one input and produce one output: + * + * INPUT: TOS(0) + * OUTPUT: TOS(0) + * Stack is unchanged. + */ + +static void regm_UnaryOperation(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, struct procdata_s *pNode) +{ + uint32_t dwUnaryRegister = MKCCREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwCcRegister = MKCCREG(g_dwStackOffset); + + TRACE(stderr, "[regm_UnaryOperation]"); + + switch (GETOP(pOpCode)) + { + case oABS: + regm_GenerateForm1ICc(rCMPI, dwUnaryRegister, 0, dwCcRegister); + regm_GenerateForm4ICc(rBGTE, 2, dwCcRegister); + + default: + regm_GenerateForm3I(pEntry->chOpCode, dwUnaryRegister, + dwUnaryRegister, pEntry->chImmediate); + break; + } +} + +/***********************************************************************/ +/* These pcodes are all binary operations in the sense that they take + * two input: + * + * INPUT: TOS(0), TOS(-1) + * OUTPUT: TOS(0) + * Stack reduced by one. + * + * These all generate form 3r instructions: + */ + +static void regm_BinaryOperation(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwROperand1 = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwROperand2 = MKREG(g_dwStackOffset - 2*sINT_SIZE); + uint32_t dwRDest = dwROperand2; + + TRACE(stderr, "[regm_BinaryOperation]"); + + /* Generate the binary operation */ + + regm_GenerateForm3R(pEntry->chOpCode, dwRDest, dwROperand1, dwROperand2); + + /* Reduce stack */ + + g_dwStackOffset -= sINT_SIZE; +} + +/***********************************************************************/ +/* These pcodes are all boolean unary operations in the sense that + * the pcode form takes one input and generates one output: + * + * INPUT: TOS(0) + * OUTPUT: TOS(0) + * Stack unchanged + * + * The complication is that the resulting boolean is not represented by + * data in the register model but, rather, as a condition code setting. + * For now we can, however, force a large number of condition code + * registers; during a later fixup pass, we can force this to a single + * condition code register. + */ + +static void regm_CompareVsZero(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwUnaryRegister = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwCcRegister = MKCCREG(g_dwStackOffset); + + TRACE(stderr, "[regm_CompareVsZero]"); + + regm_GenerateForm1ICc(rCMPI, dwUnaryRegister, 0, dwCcRegister); + regm_GenerateForm2I(rMOVI, dwUnaryRegister, 0); + regm_GenerateForm4ICc(pEntry->chOpCode, 2, dwCcRegister); + regm_GenerateForm2I(rMOVI, dwUnaryRegister, 1); +} + +/***********************************************************************/ +/* These pcodes are all boolean binary operations in the sense that + * the pcode form takes two inputs and generates one output: + * + * INPUT: TOS(0), TOS(-1) + * OUTPUT: TOS(0) + * Stack reduced by one. + * + * The complication is that the resulting boolean not represented by + * data in the register model but, rather, as a condition code setting. + * For now we can, however, force a large number of condition code + * registers; during a later fixup pass, we can force this to a single + * condition code register. + */ + +static void regm_BinaryComparison(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwROperand1 = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwROperand2 = MKREG(g_dwStackOffset - 2*sINT_SIZE); + uint32_t dwRDest = dwROperand2; + uint32_t dwCcRegister = MKCCREG(g_dwStackOffset); + + TRACE(stderr, "[regm_BinaryComparison]"); + + + switch (GETOP(pOpCode)) + { + case oBIT: + regm_GenerateForm3R(rAND, dwRDest, dwROperand1, dwROperand2); + regm_GenerateForm1ICc(rCMPI, dwRDest, 0, dwCcRegister); + break; + + default: + regm_GenerateForm1RCc(rCMP, dwROperand1, dwROperand2, dwCcRegister); + break; + } + + regm_GenerateForm2I(rMOVI, dwRDest, 0); + regm_GenerateForm4ICc(pEntry->chOpCode, 2, dwCcRegister); + regm_GenerateForm2I(rMOVI, dwRDest, 1); + + /* Reduce stack */ + + g_dwStackOffset -= sINT_SIZE; +} + +/***********************************************************************/ +/* Load from the address on the stack. Stack is unchanged */ + +static void regm_LoadImmediate(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwROperand1 = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwRDest = dwROperand1; + + TRACE(stderr, "[regm_LoadImmediate]"); + + /* Use the immediate value as an index against the SPB/LSP */ + + regm_GenerateForm3R(pEntry->chOpCode, dwRDest, dwROperand1, + MKSPECIAL(pEntry->chSpecial)); +} + +/***********************************************************************/ +/* Generic load multiple logic */ + +static void regm_LoadMultiple(uint32_t dwRDest, uint32_t dwRSrc) +{ + TRACE(stderr, "[regm_LoadMultiple]"); + + if (g_bRegisterCountValid) + { + regm_GenerateForm3I(rLDM, dwRDest, dwRSrc, g_dwRegisterCount); + + /* Adjust the stack for the g_dwRegisterCount values added to the + * stack. + */ + + g_dwStackOffset += g_dwRegisterCount * sINT_SIZE; + g_bRegisterCountValid = 0; + } + else + { + fatal(ePOFFCONFUSION); + } +} + +/***********************************************************************/ +/* SPB/LSP relative source offset is on the stack. Stack increase determined + * by content of DC register. + */ + +static void regm_LoadMultipleImmediate(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRSrc = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwRDest = dwRSrc; + + TRACE(stderr, "[regm_LoadMultipleImmediate]"); + + /* Adjust the src for the SPB/LSP value and generate the multiple load */ + + regm_GenerateForm3R(rADD, dwRSrc, dwRSrc, MKSPECIAL(pEntry->chSpecial)); + regm_LoadMultiple(dwRSrc, dwRDest); + + /* Stack will be increased by an amount determined by DC in + * regm_LoadMultiple. However, we need to also account for the + * immediate stack value that we consume here. + */ + + g_dwStackOffset -= sINT_SIZE; +} + +/***********************************************************************/ +/* Store value on stack to address on stack. Stack is reduced by two */ + +static void regm_StoreImmediate(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRSrc = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwROperand1 = MKREG(g_dwStackOffset - 2*sINT_SIZE); + + TRACE(stderr, "[regm_StoreImmediate]"); + + /* Use the immediate value as an index against the SPB/LSP */ + + regm_GenerateForm3R(pEntry->chOpCode, dwRSrc, dwROperand1, + MKSPECIAL(pEntry->chSpecial)); + + /* Reduce stack */ + + g_dwStackOffset -= 2*sINT_SIZE; +} + +/***********************************************************************/ +/* Generic store multiple logic */ + +static void regm_StoreMultiple(uint32_t dwRDest, uint32_t dwRSrc) +{ + TRACE(stderr, "[regm_StoreMultiple]"); + + if (g_bRegisterCountValid) + { + regm_GenerateForm3I(rSTM, dwRSrc, dwRDest, g_dwRegisterCount); + + /* Adjust the stack for the g_dwRegisterCount values added to the + * stack. + */ + + g_dwStackOffset -= g_dwRegisterCount * sINT_SIZE; + g_bRegisterCountValid = 0; + } + else + { + fatal(ePOFFCONFUSION); + } +} + +/***********************************************************************/ +/* Store multiple values on stack to address on stack. Stack is reduced + * by an amount determined by the content of DC. + */ + +static void regm_StoreMultipleImmediate(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRDest = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwRSrc = MKREG(g_dwStackOffset - (g_dwRegisterCount + 1)*sINT_SIZE); + + TRACE(stderr, "[regm_StoreMultipleImmediate]"); + + /* Adjust the src for the SPB/LSP value and generate the multiple load */ + + regm_GenerateForm3R(rADD, dwRDest, dwRDest, MKSPECIAL(pEntry->chSpecial)); + regm_StoreMultiple(dwRSrc, dwRDest); + + /* Stack will be increased by an amount determined by DC in + * regm_StoreMultiple. However, we need to also account for the + * immediate stack value that we consume here. + */ + + g_dwStackOffset -= sINT_SIZE; +} + +/***********************************************************************/ +/* Duplicate the TOS. stack increases by one */ + +static void regm_Duplicate(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwROperand1 = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwRDest = MKREG(g_dwStackOffset); + + TRACE(stderr, "[regm_Duplicate]"); + + /* Generate the binary operation */ + + regm_GenerateForm2R(rMOV, dwRDest, dwROperand1); + + /* Increment the stack */ + + g_dwStackOffset += sINT_SIZE; +} + +/***********************************************************************/ +/* Put the immediate value at the top of the stack. Increment stack */ + +static void regm_PushImmediate(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRDest = g_dwStackOffset; + + TRACE(stderr, "[regm_PushImmediate]"); + + /* The value may be too large to represent with a MOVI, but we'll handle + * that later. + */ + + regm_GenerateForm2I(rMOVI, dwRDest, GETARG(pOpCode)); + + /* Increment the stack */ + + g_dwStackOffset += sINT_SIZE; +} + +/***********************************************************************/ +/* Push the special register onto the stack. Stack increments by one */ + +static void regm_PushSpecial(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRDest = g_dwStackOffset; + + TRACE(stderr, "[regm_PushSpecial]"); + + regm_GenerateForm2R(rMOV, dwRDest, MKSPECIAL(pEntry->chSpecial)); + + /* Increment the stack */ + + g_dwStackOffset += sINT_SIZE; +} + +/***********************************************************************/ +/* Pop the TOS into the special register. Stack decrements by one */ + +static void regm_PopSpecial(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwROperand1 = MKREG(g_dwStackOffset - 1*sINT_SIZE); + + TRACE(stderr, "[regm_PopSpecial]"); + + regm_GenerateForm2R(rMOV, MKSPECIAL(pEntry->chSpecial), dwROperand1); + + /* Decrement the stack */ + + g_dwStackOffset -= sINT_SIZE; +} + +/***********************************************************************/ +/* Save the immediate value in the data count register */ + +static void regm_SetDataCount(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + /* We don't acutally use the DC register. It is an artifact just + * get here. We save the byte count as a even number of registers. + */ + + g_dwRegisterCount = (GETARG(pOpCode) + 3) >> 2; + g_bRegisterCountValid = 1; +} + +/***********************************************************************/ + +static void regm_Return(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + TRACE(stderr, "[regm_Return]"); + + /* This should have been processed by the prologue/epilogue logic */ + + fatal(ePOFFCONFUSION); +} + +/***********************************************************************/ +/* Load at offset from SPB/LSP. Stack increases by one */ + +static void regm_LoadOffset(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRDest = g_dwStackOffset; + + TRACE(stderr, "[regm_LoadOffset]"); + + /* Use the immediate value as an index against the SPB/LSP */ + + regm_GenerateForm3I(pEntry->chOpCode, dwRDest, MKSPECIAL(pEntry->chSpecial), + GETARG(pOpCode) >> pEntry->chImmediate); + + /* Increment the stack */ + + g_dwStackOffset += sINT_SIZE; +} + +/***********************************************************************/ +/* Load multiple registgers at offset from SPB/LSP. Stack increase depends + * on value in DC (only) + */ + +static void regm_LoadMultipleOffset(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRSrc = MKREG(g_dwStackOffset); + uint32_t dwRDest = dwRSrc; + + TRACE(stderr, "[regm_LoadMultipleOffset]"); + + regm_GenerateForm3R(rADD, dwRSrc, MKSPECIAL(pEntry->chSpecial), + GETARG(pOpCode)); + regm_LoadMultiple(dwRSrc, dwRDest); +} + +/***********************************************************************/ +/* Store at offset from SPB/LSP. Stack decreases by one */ + +static void regm_StoreOffset(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRSrc = MKREG(g_dwStackOffset - 1*sINT_SIZE); + + TRACE(stderr, "[regm_StoreOffset]"); + + /* Use the immediate value as an index against the SPB/LSP */ + + regm_GenerateForm3I(pEntry->chOpCode, dwRSrc, + MKSPECIAL(pEntry->chSpecial), + GETARG(pOpCode) >> pEntry->chImmediate); + + /* Decrement the stack */ + + g_dwStackOffset -= sINT_SIZE; +} + +/***********************************************************************/ +/* Store multiple at offset from SPB/LSP. Stack decreases an amount + * determined by the content of the DC regsiter. + */ + +static void regm_StoreMultipleOffset(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRSrc = MKREG(g_dwStackOffset - g_dwRegisterCount*sINT_SIZE); + uint32_t dwRDest; + + TRACE(stderr, "[regm_StoreMultipleOffset]"); + + regm_GenerateForm3R(rADD, dwRDest, MKSPECIAL(pEntry->chSpecial), + GETARG(pOpCode)); + regm_StoreMultiple(dwRSrc, dwRDest); +} + +/***********************************************************************/ +/* Load value using index on stack + argument + SPB/LSP. Stack is unchanged */ + +static void regm_LoadIndexed(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRIndex = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwRDest = dwRIndex; + + TRACE(stderr, "[regm_LoadIndexed]"); + + /* Add the SPB/LSP to the index to make it relative to the stack, + * then use this with the immediate values to obtain the data. + */ + + regm_GenerateForm3R(rADD, dwRIndex, dwRIndex, + MKSPECIAL(pEntry->chSpecial)); + regm_GenerateForm3I(pEntry->chOpCode, dwRDest, dwRDest, + GETARG(pOpCode) >> pEntry->chImmediate); +} + +/***********************************************************************/ +/* Load multiple values using index on stack + argument + SPB/LSP. Stack + * will increase my an amount that depends on the contents of DC. + */ + +static void regm_LoadMultipleIndexed(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRIndex = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwRSrc = dwRIndex; + uint32_t dwRDest = dwRIndex; + + TRACE(stderr, "[regm_LoadMultipleIndexed]"); + + /* Add the SPB/LSP to the index to make it relative to the stack, + * add the offset, then generate the multple load. + */ + + regm_GenerateForm3R(rADD, dwRSrc, dwRIndex, + MKSPECIAL(pEntry->chSpecial)); + regm_GenerateForm3I(rADDI, dwRSrc, dwRSrc, GETARG(pOpCode)); + regm_LoadMultiple(dwRSrc, dwRDest); + + /* Stack will be increased by an amount determined by DC in + * regm_LoadMultiple. However, we need to also account for the + * index stack value that we consume here. + */ + + g_dwStackOffset -= sINT_SIZE; +} + +/***********************************************************************/ +/* Store value at TOS to index + offset + SPB/LSP. Stack decreases by two */ + +static void regm_StoreIndexed(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRSrc = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwRIndex = MKREG(g_dwStackOffset - 2*sINT_SIZE); + + TRACE(stderr, "[regm_StoreIndexed]"); + + /* Add the LSP to the index to make it relative to the stack, + * then use this with the immediate values to obtain the data. + */ + + regm_GenerateForm3R(rADD, dwRIndex, dwRIndex, + MKSPECIAL(pEntry->chSpecial)); + regm_GenerateForm3I(pEntry->chOpCode, dwRSrc, dwRIndex, + GETARG(pOpCode) >> pEntry->chImmediate); + + /* Decrement the stack */ + + g_dwStackOffset -= 2*sINT_SIZE; +} + +/***********************************************************************/ +/* Store values at TOS to index + offset + SPB/LSP. Stack decreases by + * amount determined by the content of the DC register. + */ + +static void regm_StoreMultipleIndexed(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRIndex = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwRSrc = MKREG(g_dwStackOffset - (g_dwRegisterCount + 1)*sINT_SIZE); + uint32_t dwRDest; + + TRACE(stderr, "[regm_StoreMultipleIndexed]"); + + /* Adjust the src for the SPB/LSP value and generate the multiple load */ + + regm_GenerateForm3R(rADD, dwRDest, dwRIndex, + MKSPECIAL(pEntry->chSpecial)); + regm_GenerateForm3I(rADDI, dwRDest, dwRDest, GETARG(pOpCode)); + regm_StoreMultiple(dwRSrc, dwRDest); + + /* Stack will be increased by an amount determined by DC in + * regm_StoreMultiple. However, we need to also account for the + * immediate stack value that we consume here. + */ + + g_dwStackOffset -= sINT_SIZE; +} + +/***********************************************************************/ +/* These pcodes are all conditional branch operations. The pcode form + * takes one input (that is compared with zero) and branches based + * the result. The stack is decremented by one. + */ + +static void regm_ConditionalBranchVsZero(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwUnaryRegister = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwCcRegister = MKCCREG(g_dwStackOffset); + + TRACE(stderr, "[regm_ConditionalBranchVsZero]"); + + + regm_GenerateForm1ICc(rCMPI, dwUnaryRegister, 0, dwCcRegister); + regm_GenerateForm4ICc(pEntry->chOpCode, GETARG(pOpCode), dwCcRegister); + + /* Decrement the stack */ + + g_dwStackOffset -= sINT_SIZE; +} + +/***********************************************************************/ +/* These pcodes are all conditional branch operations. The pcode form + * takes two inputs that are compared. The pcode branches on the result + * of the comparison. The stack is reduced by two. + */ + +static void regm_ConditionalBranchBinary(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwROperand1 = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwROperand2 = MKREG(g_dwStackOffset - 2*sINT_SIZE); + uint32_t dwCcRegister = MKCCREG(g_dwStackOffset); + + TRACE(stderr, "[regm_BinaryComparison]"); + + /* Generate the compare and branch */ + + regm_GenerateForm1RCc(rCMP, dwROperand1, dwROperand2, dwCcRegister); + regm_GenerateForm4ICc(pEntry->chOpCode, GETARG(pOpCode), dwCcRegister); + + /* Reduce stack */ + + g_dwStackOffset -= 2*sINT_SIZE; +} + +/***********************************************************************/ +/* Branch unconditionally. The stack is not changed */ + +static void regm_UnconditionalBranch(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + TRACE(stderr, "[regm_UnconditionalBranch]"); + regm_GenerateForm4I(rB, GETARG(pOpCode)); +} + +/***********************************************************************/ +/* Add constant value to special register. Stack does not change */ + +static void regm_IncrementSpecial(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + int32_t dwIncrement = (int32_t)(GETOP(pOpCode)); + uint32_t dwRSpecial = MKSPECIAL(pEntry->chSpecial); + TRACE(stderr, "[regm_IncrementSpecial]"); + + /* The value may be too large to represent with a MOVI, but we'll handle + * that later. + */ + + if (dwIncrement < 0) + { + regm_GenerateForm3I(rSUBI, dwRSpecial, dwRSpecial, -dwIncrement); + } + else if (dwIncrement > 0) + { + regm_GenerateForm3I(rADDI, dwRSpecial, dwRSpecial, dwIncrement); + } + + if (pEntry->chSpecial == SP) + { + g_dwStackOffset += dwIncrement; + } +} + +/***********************************************************************/ +/* Load address at offset from special register. Stack increases by one */ + +static void regm_LoadAddress(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRDest = g_dwStackOffset; + + TRACE(stderr, "[regm_LoadAddress]"); + + /* Use the immediate value as an index against the SPB/LSP */ + + regm_GenerateForm3I(rADD, dwRDest, MKSPECIAL(pEntry->chSpecial), + GETARG(pOpCode)); + + /* Increment the stack */ + + g_dwStackOffset += sINT_SIZE; +} + +/***********************************************************************/ +/* Load address at indexed offset from special register. Stack is unchanged */ + +static void regm_LoadAddressIndexed(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + uint32_t dwRIndex = MKREG(g_dwStackOffset - 1*sINT_SIZE); + uint32_t dwRDest = dwRIndex; + + TRACE(stderr, "[regm_LoadAddressIndexed]"); + + /* Add the LSP or SPB to the index to make it relative to the stack, + * then use this with the immediate values to obtain the data. + */ + + regm_GenerateForm3R(rADD, dwRIndex, dwRIndex, + MKSPECIAL(pEntry->chSpecial)); + regm_GenerateForm3I(rADD, dwRDest, dwRIndex, GETARG(pOpCode)); +} + +/***********************************************************************/ + +static void regm_SetupOutArgs(uint32_t nParms, const uint32_t *pwArgSize) +{ + int nArgRegs; + int32_t dwOffset; + int i; + + for (i = 0, nArgRegs = 0; i < nParms; i++) + { + nArgRegs += (pwArgSize[i] + 3) >> 2; + } + + /* Emit move instructions to handle each */ + + dwOffset = g_dwStackOffset - sINT_SIZE; + for (i = 0; i < nArgRegs; i++) + { + uint32_t dwDest = MKOUTARG(i); + uint32_t dwSrc = MKREG(dwOffset); + + regm_GenerateForm2R(rMOV, dwDest, dwSrc); + dwOffset -= sINT_SIZE; + } +} + +/***********************************************************************/ + +static void regm_MapInRet(uint32_t wRetSize) +{ + int nRetRegs; + int32_t dwOffset; + int i; + + /* Get the number of registers that are returned */ + + nRetRegs += (wRetSize + 3) >> 2; + + /* Emit move instructions to handle each */ +#warning "This offset is not correct" + dwOffset = g_dwStackOffset - sINT_SIZE; + for (i = 0; i < nRetRegs; i++) + { + uint32_t dwSrc = MKINRET(i); + uint32_t dwDest = MKREG(dwOffset); + + regm_GenerateForm2R(rMOV, dwDest, dwSrc); + dwOffset -= sINT_SIZE; + } +} + +/***********************************************************************/ + +static void regm_PCal(const struct regm_opmap_s *pEntry, OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + poffLibDebugFuncInfo_t *pFuncInfo = pNode->pFuncInfo; + + TRACE(stderr, "[regm_PCal]"); + + if (!pFuncInfo) + { + fatal(ePOFFCONFUSION); + } + + /* Map the "output" parameter stack to a set of "output" argument + * registers. + */ + + regm_SetupOutArgs(pFuncInfo->nparms, pFuncInfo->argsize); + + regm_GenerateForm3I(rADDI, MKSPECIAL(SP), MKSPECIAL(SP), 3*sINT_SIZE); + regm_GenerateForm3I(rST, MKSPECIAL(LSP), MKSPECIAL(SP), -3); + regm_GenerateForm3I(rST, MKSPECIAL(BRG), MKSPECIAL(SP), -2); + regm_GenerateForm4I(rBL, GETARG(pOpCode)); + +#warning "This is in the wrong place" + regm_MapInRet(pFuncInfo->retsize); + + /* Increment the stack */ + + g_dwStackOffset += 3*sINT_SIZE; +} + +/***********************************************************************/ + +static void regm_SysIo(const struct regm_opmap_s *pEntry, OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + const struct regm_builtin_s *pBuiltIn; + uint32_t xop; + + TRACE(stderr, "[regm_SysIo]"); + + /* Get the function information for this sysio xop */ + + xop = GETARG(pOpCode); + if (xop >= MAX_XOP) + { + fatal(ePOFFCONFUSION); + } + + pBuiltIn = &g_rgSysIoBuiltIns[xop]; + + /* Map the "output" parameter stack to a set of "output" argument + * registers. + */ + + regm_SetupOutArgs(pBuiltIn->nParms, pBuiltIn->wArgSize); + + /* Generate a call to the runtime library */ + +#warning "Not implemented" + + /* Handled returned values */ + + regm_MapInRet(pBuiltIn->wRetSize); +} + +/***********************************************************************/ + +static void regm_LibCall(const struct regm_opmap_s *pEntry, OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + const struct regm_builtin_s *pBuiltIn; + uint32_t lbop; + + TRACE(stderr, "[regm_LibCall]"); + + /* Get the function information for this library op */ + + lbop = GETARG(pOpCode); + if (lbop >= MAX_LBOP) + { + fatal(ePOFFCONFUSION); + } + + pBuiltIn = &g_rgLibCallBuiltIns[lbop]; + + /* Map the "output" parameter stack to a set of "output" argument + * registers. + */ + + regm_SetupOutArgs(pBuiltIn->nParms, pBuiltIn->wArgSize); + + /* Generate a call to the runtime library */ + +#warning "Not implemented" + + /* Handled returned values */ + + regm_MapInRet(pBuiltIn->wRetSize); +} + +/***********************************************************************/ + +static void regm_Float(const struct regm_opmap_s *pEntry, OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + static const struct regm_builtin_s *pFopBuiltIns; + const struct regm_builtin_s *pBuiltIn; + uint32_t foptab; + uint32_t fop; + + TRACE(stderr, "[regm_FLoat]"); + + /* Select the correct table for the builtin */ + + foptab = (GETARG(pOpCode) & ~fpMASK) >> fpSHIFT; + pFopBuiltIns = g_prgFopBuiltIns[foptab]; + + /* Select the correct function from the table for this floating + * point operation. + */ + + fop = GETARG(pOpCode) & fpMASK; + if (fop >= MAX_FOP) + { + fatal(ePOFFCONFUSION); + } + pBuiltIn = &pFopBuiltIns[fop]; + + /* Map the "output" parameter stack to a set of "output" argument + * registers. + */ + + regm_SetupOutArgs(pBuiltIn->nParms, pBuiltIn->wArgSize); + + /* Generate a call to the runtime library */ + +#warning "Not implemented" + + /* Handled returned values */ + + regm_MapInRet(pBuiltIn->wRetSize); +} + +/***********************************************************************/ + +static void regm_IllegalPCode(const struct regm_opmap_s *pEntry, + OPTYPE *pOpCode, + struct procdata_s *pNode) +{ + TRACE(stderr, "[regm_IllegalPCode]"); + fatal(eILLEGALOPCODE); +} + +/***********************************************************************/ + +static void regm_GenerateRegm(struct procdata_s *pNode, void *pvArg) +{ + int32_t dwFrameSize = 0; + int i, j; + + TRACE(stderr, "[regm_GenerateRegm]"); + + /* Analyze the proc/func prologue */ + + i = 0; j = pNode->nPCodes; + if (GETOP(&pNode->pPCode[0]) == oINDS) + { + dwFrameSize = GETARG(&pNode->pPCode[0]); + i++; j--; + } + regm_GeneratePrologue(dwFrameSize); + + /* Set the initial stack offset. Parameters will look like + * negative offsets; local stack will look positive. + */ + + g_dwStackOffset = dwFrameSize; + + /* Generate regm code for each p-code */ + + for (; i < j; i++) + { + const struct regm_opmap_s *rgOpMap; + uint8_t chOpCode = GETOP(&pNode->pPCode[i]); + + /* Select the right decode table */ + + if ((chOpCode & o32) != 0) + { + rgOpMap = vrgOpMap2; + chOpCode &= ~o32; + } + else + { + rgOpMap = vrgOpMap1; + } + + /* Make sure that the table index is within range */ + + if (chOpCode > 63) + { + fatal(eBADSHORTINT); + } + + /* Perform the opcode mapping */ + + rgOpMap->pMapper(rgOpMap, &pNode->pPCode[i], pNode); + } + + /* If a frame was obtained at the beginning, make sure that + * there is matching frame release logic at the end. + */ + + if (dwFrameSize > 0) + { + if ((GETOP(&pNode->pPCode[i]) != oINDS) || + (dwFrameSize != -(int32_t)GETARG(&pNode->pPCode[i]))) + { + fatal(ePOFFCONFUSION); + } + i++; + } + + /* Analyze the proc/func epilogue */ + + if ((GETOP(&pNode->pPCode[i]) != oRET) && + (GETOP(&pNode->pPCode[i]) != oEND)) + { + fatal(ePOFFCONFUSION); + } + regm_GenerateEpilogue(dwFrameSize); +} + +/***********************************************************************/ + +static int regm_Pass2Node(struct procdata_s *pNode, void *pvArg) +{ + TRACE(stderr, "[regm_Pass2Node]"); + + /* Generate code for each child of this proc/func block */ + + if (pNode->child) + { + (void)regm_ForEachChild(pNode->child, regm_Pass2Node, pvArg); + } + + /* Generate code for this node */ + + regm_GenerateRegm(pNode, pvArg); + + /* Does this node have a peer at the same level? If so, then + * do the same for its peer. + */ + + if (pNode->peer) + { + (void)regm_Pass2Node(pNode->peer, pvArg); + } + + return 0; +} + +/********************************************************************** + * Public Functions + **********************************************************************/ + +/***********************************************************************/ +/* Pass 2: Convert the buffered pcode to the basic register model with + * an indefinite number of registers (arguments, general, and special + * registers) and with 32-bit immediate size. + */ + +void regm_Pass2(poffHandle_t hPoff) +{ + TRACE(stderr, "[regm_Pass2]"); + + /* Initiate traversal at the root node */ + + (void)regm_Pass2Node(regm_GetRootNode(), NULL); +} + +/***********************************************************************/ + |