summaryrefslogtreecommitdiffstats
path: root/misc/pascal/insn32
diff options
context:
space:
mode:
authorpatacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679>2008-01-05 16:30:55 +0000
committerpatacongo <patacongo@7fd9a85b-ad96-42d3-883c-3090e2eb8679>2008-01-05 16:30:55 +0000
commit866da8a689d781c699ab82d99fc9f6ba2625e99d (patch)
tree02ecc652678a6422b2894fa9558c69baeef36ea6 /misc/pascal/insn32
parent75d33dd845b5dc1d23153366234f973f155cbd9c (diff)
Register model
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@503 7fd9a85b-ad96-42d3-883c-3090e2eb8679
Diffstat (limited to 'misc/pascal/insn32')
-rw-r--r--misc/pascal/insn32/regm/Makefile94
-rw-r--r--misc/pascal/insn32/regm/regm.c341
-rw-r--r--misc/pascal/insn32/regm/regm.h65
-rw-r--r--misc/pascal/insn32/regm/regm_pass1.c279
-rw-r--r--misc/pascal/insn32/regm/regm_pass1.h58
-rw-r--r--misc/pascal/insn32/regm/regm_pass2.c1525
-rw-r--r--misc/pascal/insn32/regm/regm_pass2.h66
-rw-r--r--misc/pascal/insn32/regm/regm_registers2.c541
-rw-r--r--misc/pascal/insn32/regm/regm_registers2.h317
-rw-r--r--misc/pascal/insn32/regm/regm_tree.c337
-rw-r--r--misc/pascal/insn32/regm/regm_tree.h121
11 files changed, 3744 insertions, 0 deletions
diff --git a/misc/pascal/insn32/regm/Makefile b/misc/pascal/insn32/regm/Makefile
new file mode 100644
index 0000000000..3b06fc88f3
--- /dev/null
+++ b/misc/pascal/insn32/regm/Makefile
@@ -0,0 +1,94 @@
+############################################################################
+# insn32/regm/Makefile
+#
+# 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.
+#
+############################################################################
+#
+# Directories
+#
+REGMDIR = ${shell pwd}
+INSNDIR = $(REGMDIR)/..
+PASCAL = $(REGMDIR)/../..
+
+include $(PASCAL)/Make.config
+include $(PASCAL)/Make.defs
+
+INCDIR = $(PASCAL)/include
+LIBDIR = $(PASCAL)/lib
+BINDIR = $(PASCAL)/bin32
+
+# ----------------------------------------------------------------------
+# Tools
+
+EXTRA_INCLUDES = -I$(INSNDIR)/include
+INCLUDES += $(EXTRA_INCLUDES)
+CFLAGS += $(EXTRA_INCLUDES)
+
+# ----------------------------------------------------------------------
+# Objects and targets
+
+REGMSRCS = regm.c regm_pass1.c regm_pass2.c regm_registers2.c \
+ regm_tree.c
+REGMOBJS = $(REGMSRCS:.c=.o)
+
+OBJS = $(REGMOBJS)
+LIBS = libpoff.a libpas.a
+
+all: regm
+.PHONY: all check_libs regm clean
+
+$(OBJS): %.o: %.c
+ $(CC) -c $(CFLAGS) $< -o $@
+
+check_libs:
+ @if [ ! -f $(LIBDIR)/libpoff.a ] ; then \
+ echo "$(LIBDIR)/libpoff.a does not exist" ; \
+ exit 1 ; \
+ fi
+ @if [ ! -f $(LIBDIR)/libpas.a ] ; then \
+ echo "$(LIBDIR)/libpas.a does not exist" ; \
+ exit 1 ; \
+ fi
+ @if [ ! -f $(LIBDIR)/libinsn.a ] ; then \
+ echo "$(LIBDIR)/libinsn.a does not exist" ; \
+ exit 1 ; \
+ fi
+
+$(BINDIR)/regm: check_libs $(REGMOBJS)
+ $(CC) -o $@ $(LDFLAGS) $(REGMOBJS) -lpas -linsn -lpoff
+
+regm: $(BINDIR)/regm
+
+clean:
+ $(RM) regm *.o core *~
+
+# ----------------------------------------------------------------------
diff --git a/misc/pascal/insn32/regm/regm.c b/misc/pascal/insn32/regm/regm.c
new file mode 100644
index 0000000000..eefc5e9530
--- /dev/null
+++ b/misc/pascal/insn32/regm/regm.c
@@ -0,0 +1,341 @@
+/**********************************************************************
+ * regm.c
+ * Convert 32-bit pcode defintions to a register model
+ *
+ * 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 "pedefs.h"
+#include "paslib.h"
+#include "pofflib.h"
+#include "perr.h"
+
+#include "regm.h"
+#include "regm_tree.h"
+#include "regm_pass1.h"
+#include "regm_pass2.h"
+
+/**********************************************************************
+ * Private Function Prototypes
+ **********************************************************************/
+
+static void regm_ShowUsage(const char *progname, int errcode);
+static int regm_CheckPoffFile(poffHandle_t hPoff);
+static poffHandle_t regm_ReadPoffFile(const char *filename);
+static void regm_Pass3(poffHandle_t hPoff);
+static void regm_Pass4(poffHandle_t hPoff);
+static void regm_Pass5(poffHandle_t hPoff);
+static void regm_WritePoffFile(poffHandle_t hPoff,
+ const char *filename);
+
+/**********************************************************************
+ * Public Variables
+ **********************************************************************/
+
+int vRegmDebug = 0;
+
+/**********************************************************************
+ * Private Variables
+ **********************************************************************/
+
+/**********************************************************************
+ * Private Functions
+ **********************************************************************/
+
+/***********************************************************************/
+
+static void regm_ShowUsage(const char *progname, int errcode)
+{
+ fprintf(stderr, "USAGE:\n");
+ fprintf(stderr, " %s -h\n", progname);
+ fprintf(stderr, " %s [-d] <poff-filename>\n", progname);
+ fprintf(stderr, "WHERE:\n");
+ fprintf(stderr, " -d: Enables debug output\n");
+ fprintf(stderr, " -h: Shows this message\n");
+ exit(errcode);
+}
+
+/***********************************************************************/
+
+static poffHandle_t regm_ReadPoffFile(const char *filename)
+{
+ poffHandle_t hPoff;
+ char objname [FNAME_SIZE+1];
+ FILE *objFile;
+ int errcode;
+
+ TRACE(stderr, "[regm_ReadPoffFile]");
+
+ /* Open the optimized POFF object file -- Use the .o extension */
+
+ (void)extension(filename, "o", objname, 1);
+ if (!(objFile = fopen(objname, "rb")))
+ {
+ printf("Error Opening %s\n", objname);
+ exit(1);
+ }
+
+ /* Get a handle to a POFF input object */
+
+ hPoff = poffCreateHandle();
+ if (!hPoff)
+ {
+ printf("Could not get POFF handle\n");
+ exit(1);
+ }
+
+ /* Read the POFF file into memory */
+
+ errcode = poffReadFile(hPoff, objFile);
+ if (errcode != 0)
+ {
+ printf("Could not read POFF file, errcode=0x%02x\n", errcode);
+ exit(1);
+ }
+
+ /* Close the input file */
+
+ fclose(objFile);
+ return hPoff;
+}
+
+/***********************************************************************/
+
+static int regm_CheckPoffFile(poffHandle_t hPoff)
+{
+ ubyte fileArch = poffGetArchitecture(hPoff);
+ if (fileArch != FHA_PCODE_INSN32)
+ {
+ fprintf(stderr, "ERROR: File is not 32-bit pcode (%d)\n",
+ fileArch);
+ return -1;
+ }
+ return 0;
+}
+
+/***********************************************************************/
+/* Pass3: Perform local optimization */
+
+static void regm_Pass3(poffHandle_t hPoff)
+{
+ TRACE(stderr, "[regm_Pass3]");
+}
+
+/***********************************************************************/
+/* Pass 4: Fixup register usage, force to use a fixed number of registers
+ * (arguments, static registers, volatile registers, special registers),
+ * and add logic to handle large immediate values.
+ */
+
+static void regm_Pass4(poffHandle_t hPoff)
+{
+ TRACE(stderr, "[regm_Pass4]");
+}
+
+/***********************************************************************/
+/* Pass 5: Fixup BL and B offsets, section headers, relocation entries,
+ * symbol values
+ */
+
+static void regm_Pass5(poffHandle_t hPoff)
+{
+ TRACE(stderr, "[regm_Pass5]");
+}
+
+/***********************************************************************/
+
+static void regm_WritePoffFile(poffHandle_t hPoff, const char *filename)
+{
+#if 0
+ char rexname [FNAME_SIZE+1];
+ FILE *rexFile;
+
+ TRACE(stderr, "[regm_WritePoffFile]");
+
+ /* Open optimized p-code file -- Use .o extension */
+
+ (void)extension(filename, ".rex", rexname, 1);
+ if (!(rexFile = fopen(rexname, "wb")))
+ {
+ printf("Error Opening %s\n", rexname);
+ exit(1);
+ }
+
+ /* Then write the new POFF file */
+
+ poffWritePoffFile(hPoff, rexFile);
+
+ /* Destroy the POFF object */
+
+ poffDestroyHandle(hPoff);
+
+ /* Close the files used on regm_WritePoffFile */
+
+ (void)fclose(rexFile);
+#endif
+}
+
+/**********************************************************************
+ * Public Functions
+ **********************************************************************/
+
+/***********************************************************************/
+
+int main(int argc, char *argv[], char *envp[])
+{
+ const char *outfilename;
+ poffHandle_t hPoff;
+ TRACE(stderr, "[main]");
+ int option;
+
+ /* Process command line argruments */
+
+ while ((option = getopt(argc, argv, "dh")) > 0)
+ {
+ switch (option)
+ {
+ case 'd' :
+ vRegmDebug++;
+ break;
+ case 'h' :
+ regm_ShowUsage(argv[0], 0);
+ default:
+ fprintf(stderr, "Unrecognized option\n");
+ regm_ShowUsage(argv[0], -1);
+ }
+ }
+
+ /* Check for existence of filename argument */
+
+ if (optind != argc - 1)
+ {
+ fprintf(stderr, "Filename required at end of command line.\n");
+ regm_ShowUsage(argv[0], -1);
+ }
+
+ /* Read the POFF file into memory */
+
+ outfilename = argv[optind];
+ hPoff = regm_ReadPoffFile(outfilename);
+
+ /* Verify that it is the kind of file that we can handle */
+
+ if (regm_CheckPoffFile(hPoff) != 0)
+ {
+ fprintf(stderr, "File is not the correct type\n");
+ regm_ShowUsage(argv[0], -1);
+ }
+
+ /* Read the debug info into a more usable structure. And release
+ * the debug info in the POFF object (we will be replacing it later)
+ */
+
+ poffReadDebugFuncInfoTable(hPoff);
+ poffDiscardDebugFuncInfo(hPoff);
+
+ /* Pass 1: Break the POFF program data into sections and buffer in
+ * a tree structure.
+ */
+
+ regm_InitTree();
+ regm_Pass1(hPoff);
+ regm_DumpTree();
+
+ /* We can eliminate the buffered pcode data because we have
+ * a copy in the tree and we will be replacing it before we
+ * save the file.
+ */
+
+ poffReleaseProgData(hPoff);
+
+ /* 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.
+ */
+
+ regm_Pass2(hPoff);
+
+ /* Pass3: Perform local optimization */
+
+ regm_Pass3(hPoff);
+
+ /* Pass 4: Fixup register usage, force to use a fixed number of registers
+ * (arguments, static registers, volatile registers, special registers),
+ * and add logic to handle large immediate values.
+ */
+
+ regm_Pass4(hPoff);
+
+ /* Pass 5: Fixup BL and B offsets, section headers, relocation entries,
+ * symbol values
+ */
+
+ regm_Pass5(hPoff);
+
+ /* Replace the debug info in the POFF object with the debug info
+ * we have modified. We no longer need the buffered debug info after
+ * this point.
+ */
+
+ poffReplaceDebugFuncInfo(hPoff);
+ poffReleaseDebugFuncInfoTable();
+
+ /* Write the REGM POFF file */
+
+ poffSetArchitecture(hPoff, FHA_REGM_INSN32);
+ regm_WritePoffFile(hPoff, outfilename);
+ return 0;
+}
+
+/***********************************************************************/
+
+void regm_ProgSeek(poffHandle_t hPoff, uint32 dwOffset)
+{
+ insn_ResetOpCodeRead(hPoff);
+ if (poffProgSeek(hPoff, dwOffset) < 0)
+ {
+ fatal(eSEEKFAIL);
+ }
+}
+
+/***********************************************************************/
+
diff --git a/misc/pascal/insn32/regm/regm.h b/misc/pascal/insn32/regm/regm.h
new file mode 100644
index 0000000000..e901345169
--- /dev/null
+++ b/misc/pascal/insn32/regm/regm.h
@@ -0,0 +1,65 @@
+/***************************************************************************
+ * regm.h
+ * External Declarations associated with regm.c
+ *
+ * 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.
+ *
+ ***************************************************************************/
+
+#ifndef __REGM_H
+#define __REGM_H
+
+/***************************************************************************
+ * Included Files
+ ***************************************************************************/
+
+/***************************************************************************
+ * Definitions
+ ***************************************************************************/
+
+#define dbg(format, arg...) \
+ if (vRegmDebug) printf("%s: " format, __FUNCTION__, ##arg)
+
+#define DEBUG_FILE stdout
+
+/***************************************************************************
+ * Global Variables
+ ***************************************************************************/
+
+extern int vRegmDebug;
+
+/***************************************************************************
+ * Global Function Prototypes
+ ***************************************************************************/
+
+extern void regm_ProgSeek(poffHandle_t handle, uint32 dwOffset);
+
+#endif /* __REGM_H */
diff --git a/misc/pascal/insn32/regm/regm_pass1.c b/misc/pascal/insn32/regm/regm_pass1.c
new file mode 100644
index 0000000000..0ed1386d3e
--- /dev/null
+++ b/misc/pascal/insn32/regm/regm_pass1.c
@@ -0,0 +1,279 @@
+/**********************************************************************
+ * regm_pass1.c
+ * Break the pcode data into sections
+ *
+ * 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 "podefs.h"
+#include "pedefs.h"
+#include "paslib.h"
+#include "pofflib.h"
+#include "pinsn.h"
+#include "pinsn32.h"
+#include "perr.h"
+
+#include "regm.h"
+#include "regm_tree.h"
+#include "regm_pass1.h"
+
+/**********************************************************************
+ * Private Function Prototypes
+ **********************************************************************/
+
+static void regm_Pass1Child(poffHandle_t hPoff,
+ struct procdata_s *pParent,
+ uint32 dwStartOffset,
+ uint32 dwEndOffset);
+static void regm_Pass1Peer(poffHandle_t hPoff,
+ struct procdata_s *pPeer,
+ uint32 dwStartOffset,
+ uint32 dwEndOffset);
+static struct procdata_s *regm_Pass1Node(poffHandle_t hPoff,
+ uint32 dwStartOffset,
+ uint32 pdwEndOffset,
+ ubyte chTerminator);
+static uint32 regm_CheckSection1(poffHandle_t hPoff, uint32 dwOffset);
+static void regm_Pass1Family(poffHandle_t hPoff,
+ struct procdata_s *pNode,
+ uint32 dwEndOffset);
+/**********************************************************************
+ * Global Variables
+ **********************************************************************/
+
+/**********************************************************************
+ * Private Variables
+ **********************************************************************/
+
+/**********************************************************************
+ * Private Functions
+ **********************************************************************/
+
+/***********************************************************************/
+
+static void regm_Pass1Child(poffHandle_t hPoff, struct procdata_s *pParent,
+ uint32 dwStartOffset, uint32 dwEndOffset)
+
+{
+ struct procdata_s *pNode;
+
+ TRACE(stderr, "[regm_Pass1Child]");
+
+ /* Read the proc/func body */
+
+ pNode = regm_Pass1Node(hPoff, dwStartOffset, dwEndOffset, oRET);
+
+ /* Put the func/proc body section into the tree */
+
+ regm_AddProgChild(pParent, pNode);
+
+ /* Handle nested and child proc/func blocks */
+
+ regm_Pass1Family(hPoff, pNode, dwEndOffset);
+}
+
+/***********************************************************************/
+
+static void regm_Pass1Peer(poffHandle_t hPoff, struct procdata_s *pPeer,
+ uint32 dwStartOffset, uint32 dwEndOffset)
+
+{
+ struct procdata_s *pNode;
+
+ TRACE(stderr, "[regm_Pass1Peer]");
+
+ /* Read the proc/func body */
+
+ pNode = regm_Pass1Node(hPoff, dwStartOffset, dwEndOffset, oRET);
+
+ /* Put the func/proc body section into the tree */
+
+ regm_AddProgPeer(pPeer, pNode);
+
+ /* Handle nested and child proc/func blocks */
+
+ regm_Pass1Family(hPoff, pNode, dwEndOffset);
+}
+
+/***********************************************************************/
+
+static struct procdata_s *regm_Pass1Node(poffHandle_t hPoff,
+ uint32 dwStartOffset,
+ uint32 pdwEndOffset,
+ ubyte chTerminator)
+
+{
+ struct procdata_s *pNode;
+ uint32 dwActualEndOffset;
+
+ TRACE(stderr, "[regm_Pass1Node]");
+
+ /* Create a container for the proc/func body, and read the data */
+
+ pNode = regm_CreateProgSection();
+
+ /* Check if there is a jump at the beginning of the segment */
+
+ pNode->section[0].dwOffset = dwStartOffset;
+ pNode->section[1].dwOffset = regm_CheckSection1(hPoff, dwStartOffset);
+
+ /* Read all of the p-codes associated with the node */
+
+ dwActualEndOffset = regm_ReadNodePCodes(pNode, hPoff,
+ pNode->section[1].dwOffset,
+ pdwEndOffset, chTerminator);
+
+ /* Now calculate the size of each part of the program section */
+
+ pNode->section[1].dwSize = dwActualEndOffset - pNode->section[1].dwOffset;
+
+ if (pNode->section[0].dwOffset == pNode->section[1].dwOffset)
+ pNode->section[0].dwSize = 0;
+ else
+ pNode->section[0].dwSize = 5;
+
+ /* Associate debug info with the program section. */
+
+ pNode->pFuncInfo = poffFindDebugFuncInfo(pNode->section[0].dwOffset);
+ if (!pNode->pFuncInfo)
+ {
+ /* This debug information should always be present at this
+ * point. We will need it.
+ */
+
+ fatal(ePOFFCONFUSION);
+ }
+
+ return pNode;
+}
+
+/***********************************************************************/
+
+static uint32 regm_CheckSection1 (poffHandle_t hPoff, uint32 dwOffset)
+{
+ OPTYPE op;
+
+ /* Seek to the beginning of the section. */
+
+ regm_ProgSeek(hPoff, dwOffset);
+
+ /* Read the opcode at that position. */
+
+ (void)insn_GetOpCode(hPoff, &op);
+
+ /* Is it a oJMP instruction? This happens when there are nested
+ * functions. The entry point into the parent function is a jump
+ * around the nested functions.
+ */
+
+ if (GETOP(&op) == oJMP)
+ {
+ /* Yes, then the block really begins at the target of the jump */
+
+ return GETARG(&op);
+ }
+ else
+ {
+ /* No, then the block really begins right here */
+
+ return dwOffset;
+ }
+}
+
+/***********************************************************************/
+
+static void regm_Pass1Family(poffHandle_t hPoff, struct procdata_s *pNode,
+ uint32 dwEndOffset)
+{
+ uint32 dwSectionEnd;
+
+ /* Process any nested functions */
+
+ if (pNode->section[0].dwOffset != pNode->section[1].dwOffset)
+ {
+ dwSectionEnd = pNode->section[0].dwOffset + pNode->section[0].dwSize;
+ regm_Pass1Child(hPoff, pNode, dwSectionEnd, pNode->section[1].dwOffset);
+ }
+
+ /* Process any peer functions */
+
+ dwSectionEnd = pNode->section[1].dwOffset + pNode->section[1].dwSize;
+ if (dwSectionEnd < dwEndOffset)
+ {
+ regm_Pass1Peer(hPoff, pNode, dwSectionEnd, dwEndOffset);
+ }
+}
+
+/**********************************************************************
+ * Global Functions
+ **********************************************************************/
+
+/***********************************************************************/
+
+void regm_Pass1(poffHandle_t hPoff)
+{
+ struct procdata_s *pNode;
+ uint32 dwEntryPoint;
+
+ TRACE(stderr, "[regm_Pass1]");
+
+ /* Get the program entry point from the poff header */
+
+ dwEntryPoint = poffGetEntryPoint(hPoff);
+
+ /* Read the main program body */
+
+ pNode = regm_Pass1Node(hPoff, dwEntryPoint, 0xffffffff, oEND);
+
+ /* Put the main program section into the tree (at the root) */
+
+ regm_SetProgRoot(pNode);
+
+ /* Then process any nested functions */
+
+ if (dwEntryPoint != 0)
+ {
+ regm_Pass1Child(hPoff, pNode, 0, dwEntryPoint);
+ }
+}
+
+/***********************************************************************/
+
diff --git a/misc/pascal/insn32/regm/regm_pass1.h b/misc/pascal/insn32/regm/regm_pass1.h
new file mode 100644
index 0000000000..f1998b1cbd
--- /dev/null
+++ b/misc/pascal/insn32/regm/regm_pass1.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * regm_pass1.h
+ * External Declarations associated with regm_pass1.c
+ *
+ * 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.
+ *
+ ***************************************************************************/
+
+#ifndef __REGM_PASS1_H
+#define __REGM_PASS1_H
+
+/***************************************************************************
+ * Included Files
+ ***************************************************************************/
+
+/***************************************************************************
+ * Definitions
+ ***************************************************************************/
+
+/***************************************************************************
+ * Global Variables
+ ***************************************************************************/
+
+/***************************************************************************
+ * Global Function Prototypes
+ ***************************************************************************/
+
+extern void regm_Pass1(poffHandle_t hPoff);
+
+#endif /* __REGM_PASS1_H */
diff --git a/misc/pascal/insn32/regm/regm_pass2.c b/misc/pascal/insn32/regm/regm_pass2.c
new file mode 100644
index 0000000000..03ef8dcd6a
--- /dev/null
+++ b/misc/pascal/insn32/regm/regm_pass2.c
@@ -0,0 +1,1525 @@
+/**********************************************************************
+ * 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);
+}
+
+/***********************************************************************/
+
diff --git a/misc/pascal/insn32/regm/regm_pass2.h b/misc/pascal/insn32/regm/regm_pass2.h
new file mode 100644
index 0000000000..ab580d42d9
--- /dev/null
+++ b/misc/pascal/insn32/regm/regm_pass2.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+ * regm_pass2.h
+ * External Declarations associated with regm_pass2.c
+ *
+ * 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.
+ *
+ ***************************************************************************/
+
+#ifndef __REGM_PASS2_H
+#define __REGM_PASS2_H
+
+/***************************************************************************
+ * Included Files
+ ***************************************************************************/
+
+/***************************************************************************
+ * Definitions
+ ***************************************************************************/
+
+/***************************************************************************
+ * Public Types
+ ***************************************************************************/
+
+/***************************************************************************
+ * Public Variables
+ ***************************************************************************/
+
+extern uint32 g_dwStackOffset;
+extern uint32 g_dwRegisterCount;
+extern int g_bRegisterCountValid;
+
+/***************************************************************************
+ * Public Function Prototypes
+ ***************************************************************************/
+
+extern void regm_Pass2(poffHandle_t hPoff);
+
+#endif /* __REGM_PASS2_H */
diff --git a/misc/pascal/insn32/regm/regm_registers2.c b/misc/pascal/insn32/regm/regm_registers2.c
new file mode 100644
index 0000000000..2973dc7c32
--- /dev/null
+++ b/misc/pascal/insn32/regm/regm_registers2.c
@@ -0,0 +1,541 @@
+/**********************************************************************
+ * regm_registers.c
+ * Pass 2 register management functions
+ *
+ * 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 "pofflib.h"
+#include "pedefs.h"
+#include "perr.h"
+
+#include "rinsn32.h"
+
+#include "regm.h"
+#include "regm_pass2.h"
+#include "regm_registers2.h"
+
+/**********************************************************************
+ * Definitions
+ **********************************************************************/
+
+#define INITIAL_RCODE2_ALLOC 150
+#define RCODE2_REALLOC 50
+
+/**********************************************************************
+ * Private Function Prototypes
+ **********************************************************************/
+
+/**********************************************************************
+ * Public Variables
+ **********************************************************************/
+
+struct regm_rcode2_s *g_pRCode2 = NULL;
+uint32 g_nRCode2 = 0;
+
+/**********************************************************************
+ * Private Variables
+ **********************************************************************/
+
+static uint32 g_nRCode2Alloc = 0;
+
+static const char * const g_prgReg2Names[NREGISTER_TYPES] =
+ { "Z", "X", "CC", "A", "R", "V", "V", "S" };
+
+static const char * const g_prgSpecialReg2Names[NSPECIAL_REGISTERS2] =
+ { "SPB", "SP", "BRG", "LSP", "CSB", "CSP", "PC", "DC", "LR", "CC"};
+
+/**********************************************************************
+ * Private Functions
+ **********************************************************************/
+
+/***********************************************************************/
+
+static void regm_CheckRCode2Alloc(void)
+{
+ /* If the RCode buffer has never been allocated, allocate it now. */
+
+ if (!g_pRCode2)
+ {
+ /* Allocate an inital buffer to hold the instructions */
+
+ g_pRCode2 = (struct regm_rcode2_s*)
+ malloc(INITIAL_RCODE2_ALLOC*sizeof(struct regm_rcode2_s));
+ if (!g_pRCode2)
+ {
+ fatal(eNOMEMORY);
+ }
+
+ g_nRCode2Alloc = INITIAL_RCODE2_ALLOC;
+ }
+
+ /* The buffer has already been allocated, is there space for one
+ * more RCode?
+ */
+
+ else if (g_nRCode2 >= g_nRCode2Alloc)
+ {
+ /* If not, then reallocate the array */
+
+ g_pRCode2 = (struct regm_rcode2_s*)
+ realloc(g_pRCode2, g_nRCode2Alloc*sizeof(struct regm_rcode2_s));
+ if (!g_pRCode2)
+ {
+ fatal(eNOMEMORY);
+ }
+
+ g_nRCode2Alloc += RCODE2_REALLOC;
+ }
+}
+
+/***********************************************************************/
+
+struct regm_rcode2_s *regm_AllocateRCode2(void)
+{
+ struct regm_rcode2_s *pRetSlot;
+
+ /* Make sure we have memory allocated in the array for another
+ * RCode.
+ */
+
+ regm_CheckRCode2Alloc();
+
+ /* Return the reference to the next RCode slot */
+
+ pRetSlot = &g_pRCode2[g_nRCode2];
+ g_nRCode2++;
+ return pRetSlot;
+}
+
+static void regm_PrintSpecialReg2(FILE *pStream, uint32 dwRegister)
+{
+ int wRegNo = regm_GetRegNo(dwRegister);
+ if (wRegNo >= NSPECIAL_REGISTERS2)
+ fputc('?', pStream);
+ else
+ fputs(g_prgSpecialRegNames[wRegNo], pStream);
+}
+
+static void regm_PrintReg2(FILE *pStream, uint32 dwRegister)
+{
+ int wKind = regm_GetKind(dwRegister);
+ int wRegNo = regm_GetRegNo(dwRegister)
+ if (wKind >= REGISTERS_TYPES)
+ fprintf(pStream, "?%d", wRegNo);
+ else if (wKind == SPECIAL_REG)
+ regm_PrintSpecialReg(fg, dwRegister);
+ else
+ fprintf(pStream, "%s%d", g_prgRegNames[wKind], wRegNo);
+}
+
+static void regm_PrintDebugReg(const char *string, uint32 dwRegister)
+{
+ if (vRegmDebug)
+ {
+ fputs(string, DEBUG_FILE);
+ regm_PrintReg2(DEBUG_FILE, dwRegister);
+ fputc('\n', DEBUG_FILE);
+ }
+}
+
+/***********************************************************************/
+
+static void regm_MarkRegisterUsed(struct regm_rcode2_s *pReg,
+ uint32 dwRegister)
+{
+ regm_PrintDebugReg("Register used: ", dwRegister);
+
+ switch (regm_GetKind(dwRegister))
+ {
+ case SPECIAL_REG : /* Special "global" registers */
+ break; /* (ignored) */
+
+ case CC_REG : /* Condition code register instance (fake) */
+ break;
+
+ case INARG_REG : /* Volatile register for input arguments */
+ /* and output values from/to callee */
+ break;
+
+ case OUTARG_REG : /* Volatile register for output arguments */
+ /* and input values to/from called */
+ /* function (fake) */
+ break;
+
+ case SCRATCH_REG : /* Volatile register for general usage */
+ break;
+
+ case VOLATILE_REG : /* Volatile registers in general */
+ case STATIC_REG : /* Static register */
+ default:
+ fatal(ePOFFCONFUSION);
+ break;
+ }
+#warning "Not Implemeted"
+}
+
+/***********************************************************************/
+
+static void regm_MarkRegisterModified(struct regm_rcode2_s *pReg,
+ uint32 dwRegister)
+{
+ regm_PrintDebugReg("Register modified: ", dwRegister);
+
+ switch (regm_GetKind(dwRegister))
+ {
+ case SPECIAL_REG : /* Special "global" registers */
+ break; /* (ignored) */
+
+ case CC_REG : /* Condition code register instance (fake) */
+ break;
+
+ case INARG_REG : /* Volatile register for input arguments */
+ /* and output values from/to callee */
+ break;
+
+ case OUTARG_REG : /* Volatile register for output arguments */
+ /* and input values to/from called */
+ /* function (fake) */
+ break;
+
+ case SCRATCH_REG : /* Volatile register for general usage */
+ break;
+
+ case VOLATILE_REG : /* Volatile registers in general */
+ case STATIC_REG : /* Static register */
+ default:
+ fatal(ePOFFCONFUSION);
+ break;
+ }
+#warning "Not Implemeted"
+}
+
+/**********************************************************************
+ * Public Functions
+ **********************************************************************/
+
+/***********************************************************************/
+/* Generate function prologue: Save return address, create stack frame
+ * for local variables, and save static registers that till be used.
+ */
+
+void regm_GeneratePrologue(uint32 dwFrameSize)
+{
+#warning "Not implemented"
+}
+
+/***********************************************************************/
+/* Restore static registers, release stack frame and return */
+
+void regm_GenerateEpilogue(uint32 dwFrameSize)
+{
+#warning "Not implemented"
+}
+
+/***********************************************************************/
+/* Register-to-register comparisons (e.g., cmp r1, r2)
+ *
+ * FORM 1R: <op> <roperand1>, <roperand2>
+ */
+
+void regm_GenerateForm1RCc(ubyte chOp, uint32 dwROperand1,
+ uint32 dwROperand2, uint32 dwRCc)
+{
+ struct regm_rcode2_s *pReg = regm_AllocateRCode2();
+ pReg->eForm = eFORM_1RCc;
+ pReg->chOp = chOp;
+ pReg->u.f1rcc.dwROperand1 = dwROperand1;
+ pReg->u.f1rcc.dwROperand2 = dwROperand2;
+ pReg->u.f1rcc.dwRCc = dwRCc;
+
+ regm_MarkRegisterUsed(pReg, dwROperand1);
+ regm_MarkRegisterUsed(pReg, dwROperand2);
+ regm_MarkRegisterModified(pReg, dwRCc);
+}
+
+/***********************************************************************/
+/* Register-to-immediate comparisons (e.g., cmpi r1, 1)
+ *
+ * FORM 1I: <op> <roperand1>, <immediate>
+ */
+
+void regm_GenerateForm1ICc(ubyte chOp, uint32 dwROperand1,
+ uint32 dwImmediate, uint32 dwRCc)
+{
+ struct regm_rcode2_s *pReg = regm_AllocateRCode2();
+ pReg->eForm = eFORM_1ICc;
+ pReg->chOp = chOp;
+ pReg->u.f1icc.dwROperand1 = dwROperand1;
+ pReg->u.f1icc.dwImmediate = dwImmediate;
+ pReg->u.f1icc.dwRCc = dwRCc;
+
+ regm_MarkRegisterUsed(pReg, dwROperand1);
+ regm_MarkRegisterModified(pReg, dwRCc);
+}
+
+/***********************************************************************/
+/* Register-to-register mov instructions (e.g, mov r1, r2)
+ *
+ * FORM 2R: <op> <rdest>, <roperand2>
+ */
+
+void regm_GenerateForm2R(ubyte chOp, uint32 dwRDest,
+ uint32 dwROperand2)
+{
+ struct regm_rcode2_s *pReg = regm_AllocateRCode2();
+ pReg->eForm = eFORM_2R;
+ pReg->chOp = chOp;
+ pReg->u.f2r.dwRDest = dwRDest;
+ pReg->u.f2r.dwROperand2 = dwROperand2;
+
+ regm_MarkRegisterModified(pReg, dwRDest);
+ regm_MarkRegisterUsed(pReg, dwROperand2);
+}
+
+/***********************************************************************/
+/* Immediate-to-register mov instructions (e.g, movi r1, 1)
+ *
+/* FORM 2I: <op> <rdest>, <immediate>
+*/
+
+void regm_GenerateForm2I(ubyte chOp, uint32 dwRDest,
+ uint32 dwImmediate)
+{
+ struct regm_rcode2_s *pReg = regm_AllocateRCode2();
+ pReg->eForm = eFORM_2I;
+ pReg->chOp = chOp;
+ pReg->u.f2i.dwRDest = dwRDest;
+ pReg->u.f2i.dwImmediate = dwImmediate;
+
+ regm_MarkRegisterModified(pReg, dwRDest);
+}
+
+/***********************************************************************/
+/* Binary operations (e.g., add r0, r1, r2)
+ * Load operations (e.g., ld r0, [r1, r2])
+ * Store operations (e.g., st r0, [r1, r2])
+ *
+ * FORM 3R: <op> <rdest>, <roperand1>, <roperand2>
+ * <rsrc>, <roperand1>, <roperand2>
+ */
+
+void regm_GenerateForm3R(ubyte chOp, uint32 dwRSrcDest,
+ uint32 dwROperand1, uint32 dwROperand2)
+{
+ struct regm_rcode2_s *pReg = regm_AllocateRCode2();
+ pReg->eForm = eFORM_3R;
+ pReg->chOp = chOp;
+ pReg->u.f3r.dwRSrcDest = dwRSrcDest;
+ pReg->u.f3r.dwROperand1 = dwROperand1;
+ pReg->u.f3r.dwROperand2 = dwROperand2;
+
+ switch (chOp)
+ {
+ /* FORM 3: Arithmetic and logical operations */
+ /* FORM 3: Loads */
+
+ case rADD :
+ case rSUB :
+ case rRSB :
+ case rMUL :
+ case rDIV :
+ case rMOD :
+ case rSLL :
+ case rSRL :
+ case rSRA :
+ case rOR :
+ case rAND :
+ case rXOR :
+ case rANDN :
+ case rLD :
+ case rLDH :
+ case rLDB :
+ regm_MarkRegisterModified(pReg, dwRSrcDest);
+ break;
+
+ /* FORM 3: Loads multiple */
+ case rLDM :
+ {
+ uint32 dwRDest = dwRSrcDest;
+ int i;
+ for (i = 0; i < g_dwRegisterCount; i++)
+ {
+ regm_MarkRegisterModified(pReg, dwRDest);
+ dwRDest++;
+ }
+ }
+ break;
+
+ /* FORM 3: Stores */
+ case rST :
+ case rSTH :
+ case rSTB :
+ regm_MarkRegisterUsed(pReg, dwRSrcDest);
+ break;
+
+ /* FORM 3: Store multipole */
+ case rSTM :
+ {
+ uint32 dwRSrc = dwRSrcDest;
+ int i;
+ for (i = 0; i < g_dwRegisterCount; i++)
+ {
+ regm_MarkRegisterUsed(pReg, dwRSrc);
+ dwRSrc++;
+ }
+ }
+ break;
+
+ default:
+ fatal(ePOFFCONFUSION);
+ }
+
+ regm_MarkRegisterUsed(pReg, dwROperand1);
+ regm_MarkRegisterUsed(pReg, dwROperand2);
+}
+
+/***********************************************************************/
+/* Binary operations (e.g., addi r0, r1, 1)
+ * Load operations (e.g., ldi r0, [r1, 4])
+ * Store operations (e.g., sti r0, [r1, 4])
+ *
+ * FORM 3I: <op> <rdest>, <roperand1>, <immediate>
+ * <rsrc>, <roperand1>, <immediate>
+ */
+
+void regm_GenerateForm3I(ubyte chOp, uint32 dwRSrcDest,
+ uint32 dwROperand1, uint32 dwImmediate)
+{
+ struct regm_rcode2_s *pReg = regm_AllocateRCode2();
+ pReg->eForm = eFORM_3I;
+ pReg->chOp = chOp;
+ pReg->u.f3i.dwRSrcDest = dwRSrcDest;
+ pReg->u.f3i.dwROperand1 = dwROperand1;
+ pReg->u.f3i.dwImmediate = dwImmediate;
+
+ switch (chOp)
+ {
+ /* FORM 3: Arithmetic and logical operations */
+ /* FORM 3: Loads */
+
+ case rADDI :
+ case rSUBI :
+ case rRSBI :
+ case rMULI :
+ case rDIVI :
+ case rMODI :
+ case rSLLI :
+ case rSRLI :
+ case rSRAI :
+ case rORI :
+ case rANDI :
+ case rXORI :
+ case rANDNI :
+ case rLDI :
+ case rLDIH :
+ case rLDIB :
+ regm_MarkRegisterModified(pReg, dwRSrcDest);
+ break;
+
+ /* FORM 3: Stores */
+ case rSTI :
+ case rSTIH :
+ case rSTIB :
+ regm_MarkRegisterUsed(pReg, dwRSrcDest);
+ break;
+
+ default:
+ fatal(ePOFFCONFUSION);
+ }
+
+ regm_MarkRegisterUsed(pReg, dwROperand1);
+}
+
+/***********************************************************************/
+/* Unconditional branch operations (b offset, bl offset)
+ *
+ * FORM 4I: <op> <pc-offset>
+ */
+
+void regm_GenerateForm4I(ubyte chOp, uint32 dwOffset)
+{
+ struct regm_rcode2_s *pReg = regm_AllocateRCode2();
+ pReg->eForm = eFORM_4I;
+ pReg->chOp = chOp;
+ pReg->u.f4i.dwOffset = dwOffset;
+}
+
+/***********************************************************************/
+/* Conditional branch operations (e.g., beq offset)
+ *
+ * FORM 4I: <op> <pc-offset>
+ */
+
+void regm_GenerateForm4ICc(ubyte chOp, uint32 dwOffset,
+ uint32 dwRCc)
+{
+ struct regm_rcode2_s *pReg = regm_AllocateRCode2();
+ pReg->eForm = eFORM_4ICc;
+ pReg->chOp = chOp;
+ pReg->u.f4icc.dwOffset = dwOffset;
+ pReg->u.f4icc.dwRCc = dwRCc;
+
+ regm_MarkRegisterUsed(pReg, dwRCc);
+}
+
+/***********************************************************************/
+
+int regm_ForEachRCode2(regm_rcode2_node_t pNode, void *arg)
+{
+ int ret;
+ int i;
+ for (i = 0; i < g_nRCode2; i++)
+ {
+ ret = pNode(&g_pRCode2[i], arg);
+ if (ret != 0)
+ {
+ return ret;
+ }
+ }
+ return 0;
+}
+
+/***********************************************************************/
diff --git a/misc/pascal/insn32/regm/regm_registers2.h b/misc/pascal/insn32/regm/regm_registers2.h
new file mode 100644
index 0000000000..ec13e8cf24
--- /dev/null
+++ b/misc/pascal/insn32/regm/regm_registers2.h
@@ -0,0 +1,317 @@
+/***************************************************************************
+ * regm_registers2.h
+ * Definitions for management of registers
+ *
+ * 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.
+ *
+ ***************************************************************************/
+
+#ifndef __REGM_REGISTERS2_H
+#define __REGM_REGISTERS2_H
+
+/***************************************************************************
+ * Included Files
+ ***************************************************************************/
+
+/***************************************************************************
+ * Definitions
+ ***************************************************************************/
+
+/* Register types */
+
+#define NULL_REG 0
+#define SPECIAL_REG 1 /* Special "global" registers */
+#define CC_REG 2 /* Condition code register instance (fake) */
+#define ARG_REG 3 /* Volatile register for input arguments */
+#define INARG_REG ARG_REG /* from callee */
+#define OUTARG_REG 4 /* Volatile register for output arguments */
+ /* to called function (fake) */
+#define RET_REG ARG_REG /* Volatile register for output values */
+#define OUTRET_REG ARG_REG /* to callee */
+#define INRET_REG OUTARG_REG /* Volatile register for input return */
+ /* from called functions (fake) */
+#define SCRATCH_REG 5 /* Volatile register for general usage */
+#define VOLATILE_REG 6 /* Volatile registers in general */
+#define STATIC_REG 7 /* Static register */
+
+#define NREGISTER_TYPES 8
+
+/* Special registers */
+
+#define SPB 0 /* 32-bit Pascal stack base address */
+#define SP 1 /* 32-bit Pascal stack pointer */
+#define BRG 2 /* 32-bit base register (related to parent level) */
+#define LSP 3 /* 32-bit Level stack pointer */
+#define CSB 4 /* 32-bit Character stack base address */
+#define CSP 5 /* 32-bit Character stack pointer */
+#define PC 6 /* 32-bit Program counter */
+
+#define NSPECIAL_REGISTERS 7
+
+#define DC 7 /* 32-bit Data count register -- disappears quickly */
+#define LR 8 /* 32-bit Link register -- same as SCRATCH(0) */
+#define CC 9 /* Condition code register -- not a normal register */
+
+#define NSPECIAL_REGISTERS2 10
+
+/* During pass2, we allow an indefinite number of registers. Eventually,
+ * these need to be compressed into a smaller number of registers. These
+ * define the number of registers available in the architecture.
+ */
+
+#define NTOTAL_REGISTERS 32
+#define NGENERAL_REGISTERS (NTOTAL_REGISTERS-NSPECIAL_REGISTERS)
+#define NARGUMENT_REGISTERS 4
+#define NSCRATCH_REGISTERS 4
+#define NVOLATILE_REGISTERS (NARGUMENT_REGISTERS+NSCRATCH_REGISTERS)
+#define NSTATIC_REGISTERS (NGENERAL_REGISTERS-NVOLATILE_REGISTERS)
+
+/* Register creation macros */
+
+#define MKSPECIAL(n) regm_MkRegister(SPECIAL_REG, (n))
+#define MKCC(n) regm_MkRegister(CC_REG, (n))
+#define MKINARG(n) regm_MkRegister(INARG_REG, (n))
+#define MKOUTARG(n) regm_MkRegister(OUTARG_REG, (n))
+#define MKINRET(n) regm_MkRegister(INRET_REG, (n))
+#define MKOUTRET(n) regm_MkRegister(OUTRET_REG, (n))
+#define MKSCRATCH(n) regm_MkRegister(SCRATCH_REG, (n))
+#define MKVOLATILE(n) regm_MkRegister(VOLATILE_REG, (n))
+
+/* Make a register from a stack offset */
+
+#define MKREG(n) MKSCRATCH((n) >> 2)
+#define MKCCREG(n) MKCC((n) >> 2)
+
+/* Check register type */
+
+#define ISSPECIAL(n) regm_IsKind(SPECIAL_REG, (n))
+#define ISCC(n) regm_IsKind(CC_REG, (n))
+#define ISARG(n) regm_IsKind(ARG_REG, (n))
+#define ISSCATCH(n) regm_IsKind(SCRATCH_REG, (n))
+#define ISVOLATILE(n) regm_IsKind(VOLATILE_REG, (n))
+
+/***************************************************************************
+ * Global Types
+ ***************************************************************************/
+
+struct regm32_t
+{
+ uint32 kind : 3; /* Kind of register */
+ uint32 regno : 29; /* Register identifier */
+};
+
+union regm32_u
+{
+ struct regm32_t f;
+ uint32 dw;
+};
+
+enum regm_formtag_e
+{
+ eFORM_1RCc, /* <op> <roperand1>, <roperand2> */
+ eFORM_1ICc, /* <op> <roperand1>, <immediate> */
+ eFORM_2R, /* <op> <rdest>, <roperand2> */
+ eFORM_2I, /* <op> <rdest>, <immediate> */
+ eFORM_3R, /* <op> <rsrc/rdest>, <roperand1>, <roperand2> */
+ eFORM_3I, /* <op> <rsrc/rdest>, <roperand1>, <immediate> */
+ eFORM_4I, /* <op> <pc-offset> */
+ eFORM_4ICc, /* <op> <pc-offset> */
+};
+
+struct regm_form1rcc_s
+{
+ uint32 dwROperand1, dwROperand2, dwRCc;
+};
+
+struct regm_form1icc_s
+{
+ uint32 dwROperand1, dwImmediate, dwRCc;
+};
+
+struct regm_form2r_s
+{
+ uint32 dwRDest, dwROperand2;
+};
+
+struct regm_form2i_s
+{
+ uint32 dwRDest, dwImmediate;
+};
+
+struct regm_form3r_s
+{
+ uint32 dwRSrcDest, dwROperand1, dwROperand2;
+};
+
+struct regm_form3i_s
+{
+ uint32 dwRSrcDest, dwROperand1, dwImmediate;
+};
+
+struct regm_form4i_s
+{
+ uint32 dwRDest, dwOffset;
+};
+
+struct regm_form4icc_s
+{
+ uint32 dwRDest, dwOffset, dwRCc;
+};
+
+struct regm_rcode2_s
+{
+ ubyte eForm; /* See enum regm_formtag_e */
+ ubyte chOp; /* Regm opcode */
+ union
+ {
+ struct regm_form1rcc_s f1rcc;
+ struct regm_form1icc_s f1icc;
+ struct regm_form2r_s f2r;
+ struct regm_form2i_s f2i;
+ struct regm_form3r_s f3r;
+ struct regm_form3i_s f3i;
+ struct regm_form4i_s f4i;
+ struct regm_form4icc_s f4icc;
+ } u;
+};
+
+typedef int (*regm_rcode2_node_t)(struct regm_rcode2_s*, void*);
+
+/***************************************************************************
+ * Global Variables
+ ***************************************************************************/
+
+extern struct regm_rcode2_s *g_pRCode2;
+extern uint32 g_nRCode2;
+
+/***************************************************************************
+ * Inline Functions
+ ***************************************************************************/
+
+static inline uint32 regm_MkRegister(int wKind, int wRegNo)
+{
+ union regm32_u u;
+ u.f.kind = wKind;
+ u.f.regno = wRegNo;
+ return u.dw;
+}
+
+static inline int regm_IsKind(int wKind, uint32 dwRegister)
+{
+ union regm32_u u;
+ u.dw = dwRegister;
+ return (u.f.kind == wKind);
+}
+
+static inline int regm_GetKind(uint32 dwRegister)
+{
+ union regm32_u u;
+ u.dw = dwRegister;
+ return u.f.kind;
+}
+
+static inline void regm_SetKind(int wKind, uint32 *pdwRegister)
+{
+ union regm32_u *pu = (union regm32_u *)pdwRegister;
+ pu->f.kind = wKind;
+}
+
+static inline int regm_GetRegNo(uint32 dwRegister)
+{
+ union regm32_u u;
+ u.dw = dwRegister;
+ return u.f.regno;
+}
+
+static inline void regm_SetRegNo(int wRegNo, uint32 *pdwRegister)
+{
+ union regm32_u *pu = (union regm32_u *)pdwRegister;
+ pu->f.regno = wRegNo;
+}
+
+/***************************************************************************
+ * Global Function Prototypes
+ ***************************C***********************************************/
+
+/* Generate function prologue: Save return address, create stack frame
+ * for local variables, and save static registers that till be used.
+ */
+
+extern void regm_GeneratePrologue(uint32 dwFrameSize);
+
+/* Restore static registers, release stack frame and return */
+
+extern void regm_GenerateEpilogue(uint32 dwFrameSize);
+
+/* FORM 1R: <op> <roperand1>, <roperand2> */
+
+extern void regm_GenerateForm1RCc(ubyte chOp, uint32 dwROperand1,
+ uint32 dwROperand2, uint32 dwRCc);
+
+/* FORM 1I: <op> <roperand1>, <immediate> */
+
+extern void regm_GenerateForm1ICc(ubyte chOp, uint32 dwROperand1,
+ uint32 dwImmediate, uint32 dwRCc);
+
+/* FORM 2R: <op> <rdest>, <roperand2> */
+
+extern void regm_GenerateForm2R(ubyte chOp, uint32 dwRDest,
+ uint32 dwROperand2);
+
+/* FORM 2I: <op> <rdest>, <immediate> */
+
+extern void regm_GenerateForm2I(ubyte chOp, uint32 dwRDest,
+ uint32 dwImmediate);
+
+/* FORM 3R: <op> <rdest>, <roperand1>, <roperand2>
+ * <rsrc>, <roperand1>, <roperand2>
+ */
+
+extern void regm_GenerateForm3R(ubyte chOp, uint32 dwRSrcDest,
+ uint32 dwROperand1, uint32 dwROperand2);
+
+/* FORM 3I: <op> <rdest>, <roperand1>, <immediate>
+ * <rsrc>, <roperand1>, <immediate>
+ */
+
+extern void regm_GenerateForm3I(ubyte chOp, uint32 dwRSrcDest,
+ uint32 dwROperand1, uint32 dwImmediate);
+
+/* FORM 4I: <op> <pc-offset> */
+
+extern void regm_GenerateForm4I(ubyte chOp, uint32 dwOffset);
+
+extern void regm_GenerateForm4ICc(ubyte chOp, uint32 dwOffset,
+ uint32 dwRCc);
+
+extern int regm_ForEachRCode2(regm_rcode2_node_t pNode, void *arg);
+
+#endif /* __REGM_REGISTERS2_H */
diff --git a/misc/pascal/insn32/regm/regm_tree.c b/misc/pascal/insn32/regm/regm_tree.c
new file mode 100644
index 0000000000..e2fdff56bb
--- /dev/null
+++ b/misc/pascal/insn32/regm/regm_tree.c
@@ -0,0 +1,337 @@
+/**********************************************************************
+ * regm_tree.c
+ * Tree managmenet
+ *
+ * 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 <string.h>
+
+#include "keywords.h"
+#include "pdefs.h" /* Types needed for unused protos in pinsn.h */
+#include "podefs.h" /* Types needed for unused protos in pinsh.h */
+#include "pedefs.h"
+#include "pofflib.h"
+#include "paslib.h"
+#include "pinsn.h" /* Folr insn_GetOpCode */
+#include "perr.h"
+
+#include "pinsn32.h"
+#include "regm.h"
+#include "regm_tree.h"
+
+/**********************************************************************
+ * Definitions
+ **********************************************************************/
+
+#define INITIAL_PCODE_ALLOC 250
+#define PCODE_RELLALLOC 100
+
+/**********************************************************************
+ * Private Types
+ **********************************************************************/
+
+/**********************************************************************
+ * Private Function Prototypes
+ **********************************************************************/
+
+/**********************************************************************
+ * Global Variables
+ **********************************************************************/
+
+/**********************************************************************
+ * Private Variables
+ **********************************************************************/
+
+static struct procdata_s *g_pProgramHead = NULL;
+
+/**********************************************************************
+ * Private Functions
+ **********************************************************************/
+
+/***********************************************************************/
+
+static inline void regm_DumpIndent(uint32 dwIndent)
+{
+ while (dwIndent--) putchar(' ');
+}
+
+/***********************************************************************/
+
+void regm_DumpNode(struct procdata_s *pNode, unsigned long dwIndent)
+{
+ if (pNode)
+ {
+ if (pNode->section[0].dwOffset != pNode->section[1].dwOffset)
+ {
+ regm_DumpIndent(dwIndent);
+ printf("%08lx:%08lx\n",
+ pNode->section[0].dwOffset,
+ pNode->section[0].dwOffset + pNode->section[0].dwSize - 1);
+ }
+ regm_DumpIndent(dwIndent);
+ printf("%08lx:%08lx\n",
+ pNode->section[1].dwOffset,
+ pNode->section[1].dwOffset + pNode->section[1].dwSize - 1);
+
+ regm_DumpNode(pNode->child, dwIndent + 3);
+ regm_DumpNode(pNode->peer, dwIndent);
+ }
+}
+
+/***********************************************************************/
+
+/**********************************************************************
+ * Global Functions
+ **********************************************************************/
+
+/***********************************************************************/
+
+void regm_InitTree(void)
+{
+ g_pProgramHead = NULL;
+}
+
+/***********************************************************************/
+
+struct procdata_s *regm_CreateProgSection(void)
+{
+ struct procdata_s *pNode;
+ pNode = (struct procdata_s *)malloc(sizeof(struct procdata_s));
+ if (!pNode)
+ {
+ fatal(eNOMEMORY);
+ }
+ memset(pNode, 0, sizeof(struct procdata_s));
+ return pNode;
+}
+
+/***********************************************************************/
+
+void regm_SetProgRoot(struct procdata_s *pNode)
+{
+ g_pProgramHead = pNode;
+ pNode->child = NULL;
+ pNode->peer = NULL;
+}
+
+/***********************************************************************/
+
+void regm_AddProgChild(struct procdata_s *pParent, struct procdata_s *pNode)
+{
+ struct procdata_s *pPrev = pParent;
+
+ /* Go to the end of the list */
+
+ while (pPrev->child != NULL) pPrev = pPrev->child;
+
+ /* Deposit the new node at the end of the list */
+
+ pPrev->child = pNode;
+ pNode->child = NULL;
+ pNode->peer = NULL;
+}
+
+/***********************************************************************/
+
+void regm_AddProgPeer(struct procdata_s *pPeer, struct procdata_s *pNode)
+{
+ struct procdata_s *pPrev = pPeer;
+
+ /* Go to the end of the list */
+
+ while (pPrev->peer != NULL) pPrev = pPrev->peer;
+
+ /* Deposit the new node at the end of the list */
+
+ pPrev->peer = pNode;
+ pNode->child = NULL;
+ pNode->peer = NULL;
+}
+
+/***********************************************************************/
+
+struct procdata_s *regm_GetRootNode(void)
+{
+ return g_pProgramHead;
+}
+
+/***********************************************************************/
+
+int regm_ForEachPeer(struct procdata_s *pPeer,
+ int (*pfPeerFunc)(struct procdata_s*, void*),
+ void *arg)
+{
+ struct procdata_s *pCurr = pPeer;
+ struct procdata_s *pNext;
+ int retval;
+
+ while (pCurr->peer)
+ {
+ pNext = pCurr->peer;
+ retval = pfPeerFunc(pCurr, arg);
+ if (retval)
+ {
+ return retval;
+ }
+ pCurr = pNext;
+ }
+ return 0;
+}
+
+/***********************************************************************/
+
+int regm_ForEachChild(struct procdata_s *pParent,
+ int (*pfChildFunc)(struct procdata_s*, void*),
+ void *arg)
+{
+ struct procdata_s *pCurr = pParent;
+ struct procdata_s *pNext;
+ int retval;
+
+ while (pCurr->child)
+ {
+ pNext = pCurr->child;
+ retval = pfChildFunc(pCurr, arg);
+ if (retval)
+ {
+ return retval;
+ }
+ pCurr = pNext;
+ }
+ return 0;
+}
+
+/***********************************************************************/
+
+uint32 regm_ReadNodePCodes(struct procdata_s *pNode, poffHandle_t hPoff,
+ uint32 dwStartOffset, uint32 dwEndOffset,
+ ubyte cTerminalOpcode)
+{
+ uint32 dwOffset = dwStartOffset;
+ long nAlloc = INITIAL_PCODE_ALLOC;
+ long nPCodes;
+ ubyte bTerminatorFound;
+
+ dbg("Reading Node: %08lx %08lx %02x\n",
+ dwStartOffset, dwEndOffset, cTerminalOpcode);
+
+ /* Allocate an inital buffer to hold the instructions */
+
+ pNode->pPCode = (OPTYPE*)
+ malloc(INITIAL_PCODE_ALLOC*sizeof(struct procinsn_s*));
+ if (!pNode->pPCode)
+ {
+ fatal(eNOMEMORY);
+ }
+
+ /* Seek to the beginning of the data */
+
+ regm_ProgSeek(hPoff, dwStartOffset);
+
+ /* Read all of the instructions in the main program section */
+
+ nPCodes = 0;
+ bTerminatorFound = 0;
+ do
+ {
+ /* Make sure that there is space for another pcode */
+
+ if (nPCodes > nAlloc)
+ {
+ /* If not, then reallocate the array */
+
+ nAlloc += PCODE_RELLALLOC;
+ pNode->pPCode = (OPTYPE*)
+ realloc(pNode->pPCode, nAlloc*sizeof(OPTYPE));
+ }
+
+ /* Ready the pcode ito the array */
+
+ dwOffset += insn_GetOpCode(hPoff, &pNode->pPCode[nPCodes]);
+
+ /* Check for a terminating pcode */
+
+ if ((GETOP(&pNode->pPCode[nPCodes]) == cTerminalOpcode) ||
+ (GETOP(&pNode->pPCode[nPCodes]) == oEND))
+ {
+ bTerminatorFound++;
+ }
+
+ /* Increment the count of pcodes read */
+
+ nPCodes++;
+ }
+ while (!bTerminatorFound && (dwOffset < dwEndOffset));
+
+ dbg(" %08lx %08lx %02x\n",
+ dwStartOffset, dwOffset, GETOP(&pNode->pPCode[nPCodes-1]));
+
+ /* Save the number of pcodes that we found */
+
+ pNode->nPCodes = nPCodes;
+
+ /* Check for the correct terminator */
+
+ if (GETOP(&pNode->pPCode[nPCodes-1]) != cTerminalOpcode)
+ {
+ fatal(ePOFFCONFUSION);
+ }
+
+ /* Return any unused space in the allocation */
+
+ pNode->pPCode = (OPTYPE*)
+ realloc(pNode->pPCode, nPCodes*sizeof(OPTYPE));
+
+ /* Return the actual end offset */
+
+ return dwOffset;
+}
+
+/***********************************************************************/
+
+void regm_DumpTree(void)
+{
+ if (vRegmDebug)
+ {
+ regm_DumpNode(g_pProgramHead, 0);
+ }
+}
+
+/***********************************************************************/
+
diff --git a/misc/pascal/insn32/regm/regm_tree.h b/misc/pascal/insn32/regm/regm_tree.h
new file mode 100644
index 0000000000..bcc869890d
--- /dev/null
+++ b/misc/pascal/insn32/regm/regm_tree.h
@@ -0,0 +1,121 @@
+/***************************************************************************
+ * regm_tree.h
+ * External Declarations associated with regm_tree.c
+ *
+ * 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.
+ *
+ ***************************************************************************/
+
+#ifndef __REGM_TREE_H
+#define __REGM_TREE_H
+
+/***************************************************************************
+ * Included Files
+ ***************************************************************************/
+
+#include "keywords.h"
+#include "pofflib.h"
+#include "rinsn32.h"
+
+/***************************************************************************
+ * Definitions
+ ***************************************************************************/
+
+/***************************************************************************
+ * Global Types
+ ***************************************************************************/
+
+/* This structure retains information about a specific function */
+
+struct procinsn_s
+{
+ RINSN32 sRegOp;
+ uint32 dwRegModified;
+ uint32 dwRegsUsed[2];
+};
+
+/* Each program section is described by an entry point offset, a
+ * file offset, a size in bytes, and a list of instructions (but
+ * we ignore the instructions at the trivial entry point which
+ * will be one or zero pcodes).
+ */
+
+struct procsection_s
+{
+ uint32 dwOffset; /* File offset to section */
+ uint32 dwSize; /* Size of section in bytes */
+};
+
+/* But each pascal procedure may contain two program sections:
+ * one before any nested functions/procedures. and one for the
+ * main body.
+ */
+
+struct procdata_s
+{
+ struct procdata_s *peer; /* Next proc/func at this level */
+ struct procdata_s *child; /* First nested proc/func */
+ struct procsection_s section[2];
+ poffLibDebugFuncInfo_t *pFuncInfo;
+ int nPCodes;
+ OPTYPE *pPCode;
+ struct procinsn_s *pRegOps;
+};
+
+/***************************************************************************
+ * Global Variables
+ ***************************************************************************/
+
+/***************************************************************************
+ * Global Function Prototypes
+ ***************************************************************************/
+
+extern void regm_InitTree(void);
+extern struct procdata_s *regm_CreateProgSection(void);
+extern void regm_SetProgRoot(struct procdata_s *pNode);
+extern void regm_AddProgChild(struct procdata_s *pParent,
+ struct procdata_s *pNode);
+extern void regm_AddProgPeer(struct procdata_s *pPeer,
+ struct procdata_s *pNode);
+extern struct procdata_s *regm_GetRootNode(void);
+extern int regm_ForEachPeer(struct procdata_s *pPeer,
+ int (*pfPeerFunc)(struct procdata_s*, void*),
+ void *arg);
+extern int regm_ForEachChild(struct procdata_s *pParent,
+ int (*pfChildFunc)(struct procdata_s*, void*),
+ void *arg);
+extern uint32 regm_ReadNodePCodes(struct procdata_s *pNode,
+ poffHandle_t hPoff,
+ uint32 dwStartOffset, uint32 dwEndOffset,
+ ubyte cTerminalOpcode);
+extern void regm_DumpTree(void);
+
+#endif /* __REGM_TREE_H */