From 9684605c30d1f7f2f7120d8c1b5645e7ca4eb54f Mon Sep 17 00:00:00 2001 From: patacongo Date: Sat, 5 Jan 2008 16:30:55 +0000 Subject: Register model git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@503 42af7a65-404d-4744-a932-0658087f49c3 --- misc/pascal/insn32/regm/Makefile | 94 ++ misc/pascal/insn32/regm/regm.c | 341 +++++++ misc/pascal/insn32/regm/regm.h | 65 ++ misc/pascal/insn32/regm/regm_pass1.c | 279 ++++++ misc/pascal/insn32/regm/regm_pass1.h | 58 ++ misc/pascal/insn32/regm/regm_pass2.c | 1525 +++++++++++++++++++++++++++++ misc/pascal/insn32/regm/regm_pass2.h | 66 ++ misc/pascal/insn32/regm/regm_registers2.c | 541 ++++++++++ misc/pascal/insn32/regm/regm_registers2.h | 317 ++++++ misc/pascal/insn32/regm/regm_tree.c | 337 +++++++ misc/pascal/insn32/regm/regm_tree.h | 121 +++ 11 files changed, 3744 insertions(+) create mode 100644 misc/pascal/insn32/regm/Makefile create mode 100644 misc/pascal/insn32/regm/regm.c create mode 100644 misc/pascal/insn32/regm/regm.h create mode 100644 misc/pascal/insn32/regm/regm_pass1.c create mode 100644 misc/pascal/insn32/regm/regm_pass1.h create mode 100644 misc/pascal/insn32/regm/regm_pass2.c create mode 100644 misc/pascal/insn32/regm/regm_pass2.h create mode 100644 misc/pascal/insn32/regm/regm_registers2.c create mode 100644 misc/pascal/insn32/regm/regm_registers2.h create mode 100644 misc/pascal/insn32/regm/regm_tree.c create mode 100644 misc/pascal/insn32/regm/regm_tree.h (limited to 'misc/pascal') diff --git a/misc/pascal/insn32/regm/Makefile b/misc/pascal/insn32/regm/Makefile new file mode 100644 index 000000000..3b06fc88f --- /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 +# +# 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 000000000..eefc5e953 --- /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 + * + * 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 +#include +#include + +#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] \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 000000000..e90134516 --- /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 + * + * 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 000000000..0ed1386d3 --- /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 + * + * 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 +#include +#include + +#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 000000000..f1998b1cb --- /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 + * + * 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 000000000..03ef8dcd6 --- /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 + * + * 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 +#include +#include + +#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 000000000..ab580d42d --- /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 + * + * 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 000000000..2973dc7c3 --- /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 + * + * 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 +#include +#include + +#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: , + */ + +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: , + */ + +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: , + */ + +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: , +*/ + +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: , , + * , , + */ + +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: , , + * , , + */ + +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: + */ + +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: + */ + +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 000000000..ec13e8cf2 --- /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 + * + * 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, /* , */ + eFORM_1ICc, /* , */ + eFORM_2R, /* , */ + eFORM_2I, /* , */ + eFORM_3R, /* , , */ + eFORM_3I, /* , , */ + eFORM_4I, /* */ + eFORM_4ICc, /* */ +}; + +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: , */ + +extern void regm_GenerateForm1RCc(ubyte chOp, uint32 dwROperand1, + uint32 dwROperand2, uint32 dwRCc); + +/* FORM 1I: , */ + +extern void regm_GenerateForm1ICc(ubyte chOp, uint32 dwROperand1, + uint32 dwImmediate, uint32 dwRCc); + +/* FORM 2R: , */ + +extern void regm_GenerateForm2R(ubyte chOp, uint32 dwRDest, + uint32 dwROperand2); + +/* FORM 2I: , */ + +extern void regm_GenerateForm2I(ubyte chOp, uint32 dwRDest, + uint32 dwImmediate); + +/* FORM 3R: , , + * , , + */ + +extern void regm_GenerateForm3R(ubyte chOp, uint32 dwRSrcDest, + uint32 dwROperand1, uint32 dwROperand2); + +/* FORM 3I: , , + * , , + */ + +extern void regm_GenerateForm3I(ubyte chOp, uint32 dwRSrcDest, + uint32 dwROperand1, uint32 dwImmediate); + +/* FORM 4I: */ + +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 000000000..e2fdff56b --- /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 + * + * 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 +#include +#include + +#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 000000000..bcc869890 --- /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 + * + * 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 */ -- cgit v1.2.3