URL
https://opencores.org/ocsvn/altor32/altor32/trunk
Subversion Repositories altor32
Compare Revisions
- This comparison shows the changes necessary to convert path
/altor32/trunk
- from Rev 1 to Rev 2
- ↔ Reverse comparison
Rev 1 → Rev 2
tools
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: rtl
===================================================================
--- rtl (nonexistent)
+++ rtl (revision 2)
rtl
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: docs
===================================================================
--- docs (nonexistent)
+++ docs (revision 2)
docs
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: sw
===================================================================
--- sw (nonexistent)
+++ sw (revision 2)
sw
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property
Index: or32-sim/test_firmware.bin
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: or32-sim/test_firmware.bin
===================================================================
--- or32-sim/test_firmware.bin (nonexistent)
+++ or32-sim/test_firmware.bin (revision 2)
or32-sim/test_firmware.bin
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: or32-sim/getopt_win32.c
===================================================================
--- or32-sim/getopt_win32.c (nonexistent)
+++ or32-sim/getopt_win32.c (revision 2)
@@ -0,0 +1,218 @@
+// XGetopt.c Version 1.2
+//
+// Author: Hans Dietrich
+// hdietrich2@hotmail.com
+//
+// Description:
+// XGetopt.cpp implements getopt(), a function to parse command lines.
+//
+// History
+// Version 1.2 - 2003 May 17
+// - Added Unicode support
+//
+// Version 1.1 - 2002 March 10
+// - Added example to XGetopt.cpp module header
+//
+// This software is released into the public domain.
+// You are free to use it in any way you like.
+//
+// This software is provided "as is" with no expressed
+// or implied warranty. I accept no liability for any
+// damage or loss of business that this software may cause.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifdef WIN32
+
+///////////////////////////////////////////////////////////////////////////////
+// if you are not using precompiled headers then include these lines:
+#include
+#include
+#include
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "getopt_win32.h"
+
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// X G e t o p t . c
+//
+//
+// NAME
+// getopt -- parse command line options
+//
+// SYNOPSIS
+// int getopt(int argc, TCHAR *argv[], TCHAR *optstring)
+//
+// extern TCHAR *optarg;
+// extern int optind;
+//
+// DESCRIPTION
+// The getopt() function parses the command line arguments. Its
+// arguments argc and argv are the argument count and array as
+// passed into the application on program invocation. In the case
+// of Visual C++ programs, argc and argv are available via the
+// variables __argc and __argv (double underscores), respectively.
+// getopt returns the next option letter in argv that matches a
+// letter in optstring. (Note: Unicode programs should use
+// __targv instead of __argv. Also, all character and string
+// literals should be enclosed in _T( ) ).
+//
+// optstring is a string of recognized option letters; if a letter
+// is followed by a colon, the option is expected to have an argument
+// that may or may not be separated from it by white space. optarg
+// is set to point to the start of the option argument on return from
+// getopt.
+//
+// Option letters may be combined, e.g., "-ab" is equivalent to
+// "-a -b". Option letters are case sensitive.
+//
+// getopt places in the external variable optind the argv index
+// of the next argument to be processed. optind is initialized
+// to 0 before the first call to getopt.
+//
+// When all options have been processed (i.e., up to the first
+// non-option argument), getopt returns EOF, optarg will point
+// to the argument, and optind will be set to the argv index of
+// the argument. If there are no non-option arguments, optarg
+// will be set to NULL.
+//
+// The special option "--" may be used to delimit the end of the
+// options; EOF will be returned, and "--" (and everything after it)
+// will be skipped.
+//
+// RETURN VALUE
+// For option letters contained in the string optstring, getopt
+// will return the option letter. getopt returns a question mark (?)
+// when it encounters an option letter not included in optstring.
+// EOF is returned when processing is finished.
+//
+// BUGS
+// 1) Long options are not supported.
+// 2) The GNU double-colon extension is not supported.
+// 3) The environment variable POSIXLY_CORRECT is not supported.
+// 4) The + syntax is not supported.
+// 5) The automatic permutation of arguments is not supported.
+// 6) This implementation of getopt() returns EOF if an error is
+// encountered, instead of -1 as the latest standard requires.
+//
+// EXAMPLE
+// BOOL CMyApp::ProcessCommandLine(int argc, TCHAR *argv[])
+// {
+// int c;
+//
+// while ((c = getopt(argc, argv, _T("aBn:"))) != EOF)
+// {
+// switch (c)
+// {
+// case _T('a'):
+// TRACE(_T("option a\n"));
+// //
+// // set some flag here
+// //
+// break;
+//
+// case _T('B'):
+// TRACE( _T("option B\n"));
+// //
+// // set some other flag here
+// //
+// break;
+//
+// case _T('n'):
+// TRACE(_T("option n: value=%d\n"), atoi(optarg));
+// //
+// // do something with value here
+// //
+// break;
+//
+// case _T('?'):
+// TRACE(_T("ERROR: illegal option %s\n"), argv[optind-1]);
+// return FALSE;
+// break;
+//
+// default:
+// TRACE(_T("WARNING: no handler for option %c\n"), c);
+// return FALSE;
+// break;
+// }
+// }
+// //
+// // check for non-option args here
+// //
+// return TRUE;
+// }
+//
+///////////////////////////////////////////////////////////////////////////////
+
+TCHAR *optarg; // global argument pointer
+int optind = 0; // global argv index
+
+int getopt(int argc, TCHAR *argv[], TCHAR *optstring)
+{
+ static TCHAR *next = NULL;
+ TCHAR c;
+ TCHAR *cp;
+
+ if (optind == 0)
+ next = NULL;
+
+ optarg = NULL;
+
+ if (next == NULL || *next == _T('\0'))
+ {
+ if (optind == 0)
+ optind++;
+
+ if (optind >= argc || argv[optind][0] != _T('-') || argv[optind][1] == _T('\0'))
+ {
+ optarg = NULL;
+ if (optind < argc)
+ optarg = argv[optind];
+ return EOF;
+ }
+
+ if (_tcscmp(argv[optind], _T("--")) == 0)
+ {
+ optind++;
+ optarg = NULL;
+ if (optind < argc)
+ optarg = argv[optind];
+ return EOF;
+ }
+
+ next = argv[optind];
+ next++; // skip past -
+ optind++;
+ }
+
+ c = *next++;
+ cp = _tcschr(optstring, c);
+
+ if (cp == NULL || c == _T(':'))
+ return _T('?');
+
+ cp++;
+ if (*cp == _T(':'))
+ {
+ if (*next != _T('\0'))
+ {
+ optarg = next;
+ next = NULL;
+ }
+ else if (optind < argc)
+ {
+ optarg = argv[optind];
+ optind++;
+ }
+ else
+ {
+ return _T('?');
+ }
+ }
+
+ return c;
+}
+#endif
\ No newline at end of file
Index: or32-sim/main.cpp
===================================================================
--- or32-sim/main.cpp (nonexistent)
+++ or32-sim/main.cpp (revision 2)
@@ -0,0 +1,181 @@
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// AltOR32 OpenRisc Simulator
+// V0.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2012
+//
+// Email: admin@ultra-embedded.com
+//
+// License: GPL
+// Please contact the above address if you would like a version of this
+// software with a more permissive license for use in closed source commercial
+// applications.
+//-----------------------------------------------------------------------------
+//
+// This file is part of AltOR32 OpenRisc Simulator.
+//
+// AltOR32 OpenRisc Simulator is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// AltOR32 OpenRisc Simulator is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with AltOR32 OpenRisc Simulator; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#include
+#include
+#include
+#include
+
+#include "or32.h"
+
+#ifdef WIN32
+#include "getopt_win32.h"
+#else
+#include
+#endif
+
+//-----------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------
+#define DEFAULT_MEM_BASE 0x00000000
+#define DEFAULT_MEM_SIZE (10 << 20)
+#define DEFAULT_LOAD_ADDR 0x00000000
+#define DEFAULT_FILENAME NULL
+
+//-----------------------------------------------------------------
+// Locals
+//-----------------------------------------------------------------
+
+//-----------------------------------------------------------------
+// main
+//-----------------------------------------------------------------
+int main(int argc, char *argv[])
+{
+ int c;
+ unsigned int loadAddr = DEFAULT_LOAD_ADDR;
+ unsigned int memBase = DEFAULT_MEM_BASE;
+ unsigned int memSize = DEFAULT_MEM_SIZE;
+ int max_cycles = -1;
+ char *filename = DEFAULT_FILENAME;
+ int help = 0;
+ int trace = 0;
+ unsigned int trace_mask = 1;
+ int exitcode = 0;
+ OR32 *sim = NULL;
+
+ while ((c = getopt (argc, argv, "tv:l:b:s:f:c:")) != -1)
+ {
+ switch(c)
+ {
+ case 't':
+ trace = 1;
+ break;
+ case 'v':
+ trace_mask = strtoul(optarg, NULL, 0);
+ break;
+ case 'l':
+ loadAddr = strtoul(optarg, NULL, 0);
+ break;
+ case 'b':
+ memBase = strtoul(optarg, NULL, 0);
+ break;
+ case 's':
+ memSize = strtoul(optarg, NULL, 0);
+ break;
+ case 'f':
+ filename = optarg;
+ break;
+ case 'c':
+ max_cycles = (int)strtoul(optarg, NULL, 0);
+ break;
+ case '?':
+ default:
+ help = 1;
+ break;
+ }
+ }
+
+ if (help || filename == NULL)
+ {
+ fprintf (stderr,"Usage:\n");
+ fprintf (stderr,"-f filename.bin = Executable to load (binary)\n");
+ fprintf (stderr,"-t = Enable program trace\n");
+ fprintf (stderr,"-v 0xX = Trace Mask\n");
+ fprintf (stderr,"-b 0xnnnn = Memory base address\n");
+ fprintf (stderr,"-s 0xnnnn = Memory size\n");
+ fprintf (stderr,"-l 0xnnnn = Executable load address\n");
+ fprintf (stderr,"-c nnnn = Max instructions to execute\n");
+
+ exit(-1);
+ }
+
+ sim = new OR32(memBase, memSize);
+ sim->Reset(loadAddr + VECTOR_RESET);
+
+ if (trace)
+ sim->EnableTrace(trace_mask);
+
+ FILE *f = fopen(filename, "rb");
+ if (f)
+ {
+ long size;
+ char *buf;
+
+ // Get size
+ fseek(f, 0, SEEK_END);
+ size = ftell(f);
+ rewind(f);
+
+ buf = (char*)malloc(size+1);
+ if (buf)
+ {
+ int wait_for_input = 0;
+
+ // Read file data in
+ int len = fread(buf, 1, size, f);
+ buf[len] = 0;
+
+ if (sim->Load(loadAddr, (unsigned char *)buf, len))
+ {
+ int cycles = 0;
+
+ while (!sim->GetBreak() && !sim->GetFault())
+ {
+ sim->Step();
+ cycles++;
+
+ if (max_cycles != -1 && max_cycles == cycles)
+ break;
+ }
+ }
+ else
+ fprintf (stderr,"Error: Could not load image to memory\n");
+
+ free(buf);
+ fclose(f);
+ }
+ // Show execution stats
+ sim->DumpStats();
+
+ if (sim->GetBreak())
+ {
+ printf("Exit code = %d\n", 0);
+ }
+ }
+ else
+ fprintf (stderr,"Error: Could not open %s\n", filename);
+
+ delete sim;
+
+ return exitcode;
+}
+
Index: or32-sim/or32-sim.sln
===================================================================
--- or32-sim/or32-sim.sln (nonexistent)
+++ or32-sim/or32-sim.sln (revision 2)
@@ -0,0 +1,21 @@
+Microsoft Visual Studio Solution File, Format Version 8.00
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "or32-sim", "or32-sim.vcproj", "{89C139EF-A20E-47A7-B531-605BE0FD7D61}"
+ ProjectSection(ProjectDependencies) = postProject
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfiguration) = preSolution
+ Debug = Debug
+ Release = Release
+ EndGlobalSection
+ GlobalSection(ProjectConfiguration) = postSolution
+ {89C139EF-A20E-47A7-B531-605BE0FD7D61}.Debug.ActiveCfg = Debug|Win32
+ {89C139EF-A20E-47A7-B531-605BE0FD7D61}.Debug.Build.0 = Debug|Win32
+ {89C139EF-A20E-47A7-B531-605BE0FD7D61}.Release.ActiveCfg = Release|Win32
+ {89C139EF-A20E-47A7-B531-605BE0FD7D61}.Release.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ EndGlobalSection
+ GlobalSection(ExtensibilityAddIns) = postSolution
+ EndGlobalSection
+EndGlobal
Index: or32-sim/or32.cpp
===================================================================
--- or32-sim/or32.cpp (nonexistent)
+++ or32-sim/or32.cpp (revision 2)
@@ -0,0 +1,1096 @@
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+// AltOR32 OpenRisc Simulator
+// V0.1
+// Ultra-Embedded.com
+// Copyright 2011 - 2012
+//
+// Email: admin@ultra-embedded.com
+//
+// License: GPL
+// Please contact the above address if you would like a version of this
+// software with a more permissive license for use in closed source commercial
+// applications.
+//-----------------------------------------------------------------------------
+//
+// This file is part of AltOR32 OpenRisc Simulator.
+//
+// AltOR32 OpenRisc Simulator is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// AltOR32 OpenRisc Simulator is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with AltOR32 OpenRisc Simulator; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#include
+#include
+#include
+#include
+#include "or32.h"
+#include "or32_inst_dump.h"
+
+//-----------------------------------------------------------------
+// Defines:
+//-----------------------------------------------------------------
+#define DPRINTF(l,a) do { if (Trace & l) printf a; } while (0)
+#define TRACE_ENABLED(l) (Trace & l)
+
+//-----------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------
+OR32::OR32(unsigned int baseAddr, unsigned int len)
+{
+ MemBase = baseAddr;
+ MemSize = len;
+ Mem = new TMemory[len/4];
+ Trace = 0;
+
+ assert(Mem);
+
+ Reset();
+}
+//-----------------------------------------------------------------
+// Deconstructor
+//-----------------------------------------------------------------
+OR32::~OR32()
+{
+ if (Mem)
+ delete Mem;
+ Mem = NULL;
+}
+//-----------------------------------------------------------------
+// Reset: Reset CPU state
+//-----------------------------------------------------------------
+void OR32::Reset(TRegister start_addr /*= VECTOR_RESET*/)
+{
+ int i;
+
+ r_pc = start_addr;
+ r_pc_next = start_addr;
+ r_pc_last = start_addr;
+ r_sr = 0;
+ r_epc = 0;
+ r_esr = 0;
+
+ for (i=0;i= MemBase) && (startAddr + len) <= (MemBase + MemSize))
+ {
+ // Zero memory first
+ memset(Mem, 0, sizeof(Mem));
+
+ // Make relative to start of memory
+ startAddr -= MemBase;
+
+ // Convert to word address
+ startAddr /= 4;
+
+ for (i=0;i= MemBase && addr < (MemBase + MemSize))
+ {
+ word = (addr - MemBase) / 4;
+ for (i=0;i= MemBase && addr < (MemBase + MemSize))
+ {
+ word = (addr - MemBase) / 4;
+ for (i=0;i> 24;
+ *data++ = Mem[word + i] >> 16;
+ *data++ = Mem[word + i] >> 8;
+ *data++ = Mem[word + i] >> 0;
+ }
+
+ return true;
+ }
+ else
+ return false;
+}
+//-----------------------------------------------------------------
+// Decode: Instruction decode stage
+//-----------------------------------------------------------------
+void OR32::Decode(void)
+{
+ // Instruction opcode read complete
+ mem_wr = 0;
+ mem_rd = 0;
+
+ // Fetch instruction from 'memory bus'
+ r_opcode = mem_data_in;
+ mem_data_in = 0;
+
+ // Decode opcode in-order to perform register reads
+ r_ra = (r_opcode >> OR32_REG_A_SHIFT) & OR32_REG_A_MASK;
+ r_rb = (r_opcode >> OR32_REG_B_SHIFT) & OR32_REG_B_MASK;
+ r_rd = (r_opcode >> OR32_REG_D_SHIFT) & OR32_REG_D_MASK;
+}
+//-----------------------------------------------------------------
+// Execute: Instruction execution stage
+//-----------------------------------------------------------------
+void OR32::Execute(void)
+{
+ TRegister v_ra = 0;
+ TRegister v_rb = 0;
+ TRegister v_rd = 0;
+ TRegister v_inst = 0;
+ TRegister v_op = 0;
+ TRegister v_target = 0;
+ TRegister v_pc = 0;
+ TRegister v_pc_next = 0;
+ TRegister v_imm = 0;
+ TRegister v_imm_uint32 = 0;
+ TRegister v_imm_int32 = 0;
+ TRegister v_offset = 0;
+ TRegister v_reg_ra = 0;
+ TRegister v_reg_rb = 0;
+ TRegister v_reg_result = 0;
+ TRegister v_store_imm = 0;
+ int v_branch = 0;
+ int v_jmp = 0;
+ int v_exception = 0;
+ TRegister v_vector = 0;
+ int v_write_rd = 0;
+
+ TRegister v_alu_op = 0;
+ TRegister v_shift_op = 0;
+ TRegister v_sfxx_op = 0;
+
+ // Notify observers of instruction execution
+ MonInstructionExecute(r_pc, r_opcode);
+
+ StatsInstructions++;
+
+ DPRINTF(LOG_INST, ("%08x: %08x\n", r_pc, r_opcode));
+
+ // Decode opcode fields
+ v_inst = (r_opcode >> OR32_OPCODE_SHIFT) & OR32_OPCODE_MASK;
+ v_rd = (r_opcode >> OR32_REG_D_SHIFT) & OR32_REG_D_MASK;
+ v_ra = (r_opcode >> OR32_REG_A_SHIFT) & OR32_REG_A_MASK;
+ v_rb = (r_opcode >> OR32_REG_B_SHIFT) & OR32_REG_B_MASK;
+ v_imm = (r_opcode >> OR32_IMM16_SHIFT) & OR32_IMM16_MASK;
+ v_target = (r_opcode >> OR32_ADDR_SHIFT) & OR32_ADDR_MASK;
+ v_sfxx_op = (r_opcode >> OR32_SFXXX_OP_SHIFT) & OR32_SFXXX_OP_MASK;
+ v_alu_op = (r_opcode >> OR32_ALU_OP_L_SHIFT) & OR32_ALU_OP_L_MASK;
+ v_alu_op |= (r_opcode >> OR32_ALU_OP_H_SHIFT) & OR32_ALU_OP_H_MASK;
+ v_shift_op = (r_opcode >> OR32_SHIFT_OP_SHIFT) & OR32_SHIFT_OP_MASK;
+ v_store_imm = (r_opcode >> OR32_STORE_IMM_L_SHIFT) & OR32_STORE_IMM_L_MASK;
+ v_store_imm|= (r_opcode >> OR32_STORE_IMM_H_SHIFT) & OR32_STORE_IMM_H_MASK;
+
+ // Sign extend store immediate
+ v_store_imm = (unsigned int)(signed short)v_store_imm;
+
+ // Sign extend target immediate
+ if (v_target & (1 << OR32_ADDR_SIGN_SHIFT))
+ v_target |= ~OR32_ADDR_MASK;
+
+ // Signed & unsigned imm -> 32-bits
+ v_imm_int32 = (unsigned int)(signed short)v_imm;
+ v_imm_uint32 = v_imm;
+
+ // Load register[ra]
+ v_reg_ra = r_reg_ra;
+
+ // Load register[rb]
+ v_reg_rb = r_reg_rb;
+
+ // Zero result
+ v_reg_result = 0;
+
+ // Update PC to next value
+ v_pc = r_pc_next;
+
+ // Increment next PC value (might be overriden by branch)
+ v_pc_next = r_pc_next + 4;
+
+ // Default target is r_rd
+ r_rd_wb = r_rd;
+
+ // Execute instruction
+ switch(v_inst)
+ {
+ case INST_OR32_ALU:
+ switch (v_alu_op)
+ {
+ case INST_OR32_ADD: // l.add
+ v_reg_result = v_reg_ra + v_reg_rb;
+ v_write_rd = 1;
+ break;
+ case INST_OR32_AND: // l.and
+ v_reg_result = v_reg_ra & v_reg_rb;
+ v_write_rd = 1;
+ break;
+ case INST_OR32_OR: // l.or
+ v_reg_result = v_reg_ra | v_reg_rb;
+ v_write_rd = 1;
+ break;
+ case INST_OR32_SLL: // l.sll
+ v_reg_result = v_reg_ra << (v_reg_rb & 0x3F);
+ v_write_rd = 1;
+ break;
+ case INST_OR32_SRA: // l.sra
+ v_reg_result = (int)v_reg_ra >> (v_reg_rb & 0x3F);
+ v_write_rd = 1;
+ break;
+ case INST_OR32_SRL: // l.srl
+ v_reg_result = v_reg_ra >> (v_reg_rb & 0x3F);
+ v_write_rd = 1;
+ break;
+ case INST_OR32_SUB: // l.sub
+ v_reg_result = v_reg_ra + ~v_reg_rb + 1;
+ v_write_rd = 1;
+ break;
+ case INST_OR32_XOR: // l.xor
+ v_reg_result = v_reg_ra ^ v_reg_rb;
+ v_write_rd = 1;
+ break;
+ default:
+ fprintf (stderr,"Bad ALU instruction @ PC %x\n", r_pc);
+ Fault = 1;
+ v_exception = 1;
+ v_vector = VECTOR_ILLEGAL_INST;
+ break;
+ }
+ break;
+
+ case INST_OR32_ADDI: // l.addi
+ v_reg_result = v_reg_ra + v_imm_int32;
+ v_write_rd = 1;
+ break;
+
+ case INST_OR32_ANDI: // l.andi
+ v_reg_result = v_reg_ra & v_imm_uint32;
+ v_write_rd = 1;
+ break;
+
+ case INST_OR32_BF: // l.bf
+ if (r_sr & OR32_SR_F_BIT)
+ v_branch = 1;
+ break;
+
+ case INST_OR32_BNF: // l.bnf
+ if (!(r_sr & OR32_SR_F_BIT))
+ v_branch = 1;
+ break;
+
+ case INST_OR32_J: // l.j
+ v_branch = 1;
+ break;
+
+ case INST_OR32_JAL: // l.jal
+ // Write next instruction address to LR
+ v_reg_result = v_pc_next;
+ r_rd_wb = REG_9_LR;
+ v_write_rd = 1;
+
+ v_branch = 1;
+ break;
+
+ case INST_OR32_JALR: // l.jalr
+ // Write next instruction address to LR
+ v_reg_result = v_pc_next;
+ r_rd_wb = REG_9_LR;
+ v_write_rd = 1;
+
+ v_pc_next = v_reg_rb;
+ v_jmp = 1;
+ break;
+
+ case INST_OR32_JR: // l.jr
+ v_pc_next = v_reg_rb;
+ v_jmp = 1;
+ break;
+
+ case INST_OR32_LBS: // l.lbs
+ case INST_OR32_LHS: // l.lhs
+ case INST_OR32_LWS: // l.lws
+ case INST_OR32_LBZ: // l.lbz
+ case INST_OR32_LHZ: // l.lhz
+ case INST_OR32_LWZ: // l.lwz
+ mem_addr = v_reg_ra + (int)v_imm_int32;
+ mem_offset = mem_addr & 0x3;
+ mem_wr = 0;
+ mem_rd = 1;
+ mem_data_out = 0;
+ v_write_rd = 1;
+ StatsMem++;
+ break;
+
+ case INST_OR32_MFSPR: // l.mfspr
+ // Move from SPR register
+ switch ((v_reg_ra | (v_imm_uint32 & OR32_MFSPR_IMM_MASK)))
+ {
+ // VR - Version register
+ case SPR_REG_VR:
+ v_reg_result = SPR_VERSION_CURRENT;
+ v_write_rd = 1;
+ break;
+ // SR - Supervision register
+ case SPR_REG_SR:
+ v_reg_result = r_sr;
+ v_write_rd = 1;
+ break;
+ // EPCR - EPC Exception saved PC
+ case SPR_REG_EPCR:
+ v_reg_result = r_epc;
+ v_write_rd = 1;
+ break;
+ // ESR - Exception saved SR
+ case SPR_REG_ESR:
+ v_reg_result = r_esr;
+ v_write_rd = 1;
+ break;
+ default:
+ fprintf (stderr,"Unsupported SPR register (0x%x) access @ PC %x\n", (v_reg_ra | v_imm_uint32), r_pc);
+ Fault = 1;
+ v_exception = 1;
+ v_vector = VECTOR_ILLEGAL_INST;
+ break;
+ }
+ break;
+
+ case INST_OR32_MTSPR: // l.mtspr
+ // Move to SPR register
+ switch ((v_reg_ra | (v_imm_uint32 & OR32_MTSPR_IMM_MASK)))
+ {
+ // SR - Supervision register
+ case SPR_REG_SR:
+ r_sr = v_reg_rb;
+ break;
+ // EPCR - EPC Exception saved PC
+ case SPR_REG_EPCR:
+ r_epc = v_reg_rb;
+ break;
+ // ESR - Exception saved SR
+ case SPR_REG_ESR:
+ r_esr = v_reg_rb;
+ break;
+ default:
+ fprintf (stderr,"Unsupported SPR register (0x%x) access @ PC %x\n", (v_reg_ra | v_imm_uint32), r_pc);
+ Fault = 1;
+ v_exception = 1;
+ v_vector = VECTOR_ILLEGAL_INST;
+ break;
+ }
+ break;
+
+ case INST_OR32_MOVHI: // l.movhi
+ v_reg_result = v_imm_uint32 << 16;
+ v_write_rd = 1;
+ break;
+
+ case INST_OR32_NOP: // l.nop
+ StatsNop++;
+
+ // NOP with simulator instruction?
+ if (v_imm != NOP_NOP)
+ MonNop(v_imm);
+ break;
+
+ case INST_OR32_ORI: // l.ori
+ v_reg_result = v_reg_ra | v_imm_uint32;
+ v_write_rd = 1;
+ break;
+
+ case INST_OR32_RFE: // l.rfe
+ // Restore PC & SR from EPC & ESR
+ v_pc_next = r_epc;
+ r_sr = r_esr;
+ v_jmp = 1;
+
+ // TODO: Handle branch delay & next instruction flush
+ break;
+
+ case INST_OR32_SHIFTI:
+ switch (v_shift_op)
+ {
+ case INST_OR32_SLLI: // l.slli
+ v_reg_result = v_reg_ra << (r_opcode & 0x3F);
+ v_write_rd = 1;
+ break;
+ case INST_OR32_SRAI: // l.srai
+ v_reg_result = (int)v_reg_ra >> (r_opcode & 0x3F);
+ v_write_rd = 1;
+ break;
+ case INST_OR32_SRLI: // l.srli
+ v_reg_result = v_reg_ra >> (r_opcode & 0x3F);
+ v_write_rd = 1;
+ break;
+ default:
+ fprintf (stderr,"Bad shift instruction @ PC %x\n", r_pc);
+ Fault = 1;
+ v_exception = 1;
+ v_vector = VECTOR_ILLEGAL_INST;
+ break;
+ }
+ break;
+
+ case INST_OR32_SB: // l.sb
+ mem_addr = v_reg_ra + (int)v_store_imm;
+ mem_offset = mem_addr & 0x3;
+ mem_rd = 0;
+ switch (mem_offset)
+ {
+ case 0x0:
+ mem_data_out = (v_reg_rb & 0xFF) << 24;
+ mem_wr = 8;
+ break;
+ case 0x1:
+ mem_data_out = (v_reg_rb & 0xFF) << 16;
+ mem_wr = 4;
+ break;
+ case 0x2:
+ mem_data_out = (v_reg_rb & 0xFF) << 8;
+ mem_wr = 2;
+ break;
+ case 0x3:
+ mem_data_out = (v_reg_rb & 0xFF) << 0;
+ mem_wr = 1;
+ break;
+ }
+ StatsMem++;
+ break;
+
+ case INST_OR32_SFXX:
+ case INST_OR32_SFXXI:
+ switch (v_sfxx_op)
+ {
+ case INST_OR32_SFEQ: // l.sfeq
+ if (v_reg_ra == v_reg_rb)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFEQI: // l.sfeqi
+ if (v_reg_ra == v_imm_int32)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFGES: // l.sfges
+ if ((int)v_reg_ra >= (int)v_reg_rb)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFGESI: // l.sfgesi
+ if ((int)v_reg_ra >= (int)v_imm_int32)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFGEU: // l.sfgeu
+ if (v_reg_ra >= v_reg_rb)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFGEUI: // l.sfgeui
+ if (v_reg_ra >= v_imm_uint32)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFGTS: // l.sfgts
+ if ((int)v_reg_ra > (int)v_reg_rb)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFGTSI: // l.sfgtsi
+ if ((int)v_reg_ra > (int)v_imm_int32)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFGTU: // l.sfgtu
+ if (v_reg_ra > v_reg_rb)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFGTUI: // l.sfgtui
+ if (v_reg_ra > v_imm_uint32)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFLES: // l.sfles
+ if ((int)v_reg_ra <= (int)v_reg_rb)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFLESI: // l.sflesi
+ if ((int)v_reg_ra <= (int)v_imm_int32)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFLEU: // l.sfleu
+ if (v_reg_ra <= v_reg_rb)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFLEUI: // l.sfleui
+ if (v_reg_ra <= v_imm_uint32)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFLTS: // l.sflts
+ if ((int)v_reg_ra < (int)v_reg_rb)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFLTSI: // l.sfltsi
+ if ((int)v_reg_ra < (int)v_imm_int32)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFLTU: // l.sfltu
+ if (v_reg_ra < v_reg_rb)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFLTUI: // l.sfltui
+ if (v_reg_ra < v_imm_uint32)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFNE: // l.sfne
+ if (v_reg_ra != v_reg_rb)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ case INST_OR32_SFNEI: // l.sfnei
+ if (v_reg_ra != v_imm_int32)
+ r_sr |= OR32_SR_F_BIT;
+ else
+ r_sr &=~OR32_SR_F_BIT;
+ break;
+ default:
+ fprintf (stderr,"Bad SFxx instruction @ PC %x\n", r_pc);
+ Fault = 1;
+ v_exception = 1;
+ v_vector = VECTOR_ILLEGAL_INST;
+ break;
+ }
+ break;
+
+ case INST_OR32_SH: // l.sh
+ mem_addr = v_reg_ra + (int)v_store_imm;
+ mem_offset = mem_addr & 0x3;
+ mem_rd = 0;
+ switch (mem_offset)
+ {
+ case 0x0:
+ mem_data_out = (v_reg_rb & 0xFFFF) << 16;
+ mem_wr = 0xC;
+ break;
+ case 0x2:
+ mem_data_out = (v_reg_rb & 0xFFFF) << 0;
+ mem_wr = 0x3;
+ break;
+ default:
+ fprintf (stderr,"Bad mem access @ PC %x (%x)\n", r_pc, mem_offset);
+ Fault = 1;
+ mem_wr = 0;
+ break;
+ }
+ StatsMem++;
+ break;
+
+ case INST_OR32_SW: // l.sw
+ mem_addr = v_reg_ra + (int)v_store_imm;
+ mem_offset = mem_addr & 0x3;
+ mem_rd = 0;
+ mem_wr = 0xF;
+ mem_data_out = v_reg_rb;
+ if (mem_offset != 0)
+ {
+ fprintf (stderr,"Bad mem access @ PC %x (%x)\n", r_pc, mem_offset);
+ Fault = 1;
+ mem_wr = 0;
+ }
+ StatsMem++;
+ break;
+
+ case INST_OR32_MISC:
+ switch (r_opcode >> 24)
+ {
+ case INST_OR32_SYS: // l.sys
+ v_exception = 1;
+ v_vector = VECTOR_SYSCALL;
+ break;
+
+ case INST_OR32_TRAP: // l.trap
+ Break = 1;
+ BreakValue = v_imm_uint32;
+ v_exception = 1;
+ v_vector = VECTOR_TRAP;
+ break;
+ }
+ break;
+
+ case INST_OR32_XORI: // l.xori
+ v_reg_result = v_reg_ra ^ v_imm_int32;
+ v_write_rd = 1;
+ break;
+
+ default:
+ fprintf (stderr,"Fault @ PC %x\n", r_pc);
+ Fault = 1;
+ v_exception = 1;
+ v_vector = VECTOR_ILLEGAL_INST;
+ break;
+ }
+
+ // Notify observer of fault
+ if (Fault)
+ MonFault(r_pc, r_opcode);
+
+ // Handle branches (jumps relative to current PC)
+ if (v_branch == 1)
+ {
+ v_offset = v_target << 2;
+ v_pc_next = r_pc + v_offset;
+ StatsBranches++;
+ }
+ // If not branching, handle interrupts / exceptions
+ else if (v_jmp == 0)
+ {
+ // External interrupt (and not handling an exception)?
+ if (PeripheralInt() == 1 && (r_sr & (1 << OR32_SR_IEE)) && v_exception == 0)
+ {
+ v_exception = 1;
+ v_vector = VECTOR_EXTINT;
+ }
+
+ // Interrupt / Exception
+ if (v_exception == 1)
+ {
+ // Save PC & SR
+ r_epc = v_pc;
+ r_esr = r_sr;
+
+ v_pc = v_vector;
+ v_pc_next = v_pc + 4;
+
+ // Disable further interrupts
+ r_sr = 0;
+
+ StatsExceptions++;
+ StatsBranches++;
+ }
+ }
+ else
+ StatsBranches++;
+
+ // Update registers with variable values
+ r_pc_last = r_pc;
+ r_pc = v_pc;
+ r_pc_next = v_pc_next;
+ r_reg_result = v_reg_result;
+
+ // No writeback required?
+ if (v_write_rd == 0)
+ {
+ // Target register is $0 which is read-only
+ r_rd_wb = 0;
+ }
+}
+//-----------------------------------------------------------------
+// WriteBack: Register write back stage
+//-----------------------------------------------------------------
+void OR32::WriteBack(void)
+{
+ TRegister v_inst;
+ TRegister v_reg_result;
+
+ mem_wr = 0;
+ mem_rd = 0;
+
+ v_inst = (r_opcode >> OR32_OPCODE_SHIFT) & OR32_OPCODE_MASK;
+
+ // Writeback read result
+ switch(v_inst)
+ {
+ case INST_OR32_LBS: // l.lbs
+ switch (mem_offset)
+ {
+ case 0x0:
+ v_reg_result = (int)((signed char)(mem_data_in >> 24));
+ break;
+ case 0x1:
+ v_reg_result = (int)((signed char)(mem_data_in >> 16));
+ break;
+ case 0x2:
+ v_reg_result = (int)((signed char)(mem_data_in >> 8));
+ break;
+ case 0x3:
+ v_reg_result = (int)((signed char)(mem_data_in >> 0));
+ break;
+ }
+ break;
+
+ case INST_OR32_LBZ: // l.lbz
+ switch (mem_offset)
+ {
+ case 0x0:
+ v_reg_result = ((unsigned char)(mem_data_in >> 24));
+ break;
+ case 0x1:
+ v_reg_result = ((unsigned char)(mem_data_in >> 16));
+ break;
+ case 0x2:
+ v_reg_result = ((unsigned char)(mem_data_in >> 8));
+ break;
+ case 0x3:
+ v_reg_result = ((unsigned char)(mem_data_in >> 0));
+ break;
+ }
+ break;
+
+ case INST_OR32_LHS: // l.lhs
+ switch (mem_offset)
+ {
+ case 0x0:
+ v_reg_result = (int)((signed short)(mem_data_in >> 16));
+ break;
+ case 0x2:
+ v_reg_result = (int)((signed short)(mem_data_in >> 0));
+ break;
+ default:
+ fprintf (stderr,"Bad mem access @ PC %x (%x)\n", r_pc, mem_offset);
+ Fault = 1;
+ break;
+ }
+ break;
+
+ case INST_OR32_LHZ: // l.lhz
+ switch (mem_offset)
+ {
+ case 0x0:
+ v_reg_result = ((unsigned short)(mem_data_in >> 16));
+ break;
+ case 0x2:
+ v_reg_result = ((unsigned short)(mem_data_in >> 0));
+ break;
+ default:
+ fprintf (stderr,"Bad mem access @ PC %x (%x)\n", r_pc, mem_offset);
+ Fault = 1;
+ break;
+ }
+ break;
+
+ case INST_OR32_LWZ: // l.lwz
+ case INST_OR32_LWS: // l.lws
+ v_reg_result = mem_data_in;
+ if (mem_offset != 0)
+ {
+ fprintf (stderr,"Bad mem access @ PC %x (%x)\n", r_pc, mem_offset);
+ Fault = 1;
+ }
+ break;
+
+ default:
+ v_reg_result = r_reg_result;
+ break;
+ }
+
+ // Decode instruction to full text?
+ if (TRACE_ENABLED(LOG_OR1K))
+ or32_instruction_dump(r_pc_last, r_opcode, r_gpr, r_rd_wb, v_reg_result, r_sr);
+
+ // Register writeback required?
+ r_reg_rd_out = v_reg_result;
+ if (r_rd_wb != 0)
+ r_writeback = 1;
+
+ // Fetch next instruction
+ mem_addr = r_pc;
+ mem_data_out = 0;
+ mem_rd = 1;
+}
+//-----------------------------------------------------------------
+// Clock: Execute a single instruction (including load / store)
+//-----------------------------------------------------------------
+bool OR32::Clock(void)
+{
+ bool writeback = false;
+
+ switch (Cycle)
+ {
+ // Instruction decode
+ case 0:
+ Cycle++;
+ Decode();
+ break;
+
+ // Execute
+ case 1:
+ Cycle++;
+ Execute();
+ break;
+
+ // Writeback & fetch next
+ case 2:
+ Cycle = 0;
+ WriteBack();
+ writeback = true;
+ break;
+ }
+
+ // Notify observers if memory write will occur
+ if (mem_wr)
+ {
+ DPRINTF(LOG_MEM, ("MEM: Write Addr %x Value %x Mask %x\n", mem_addr, mem_data_out, mem_wr));
+ MonDataStore(mem_addr, mem_wr, mem_data_out);
+ }
+
+ // Internal Memory?
+ if (mem_addr >= MemBase && mem_addr < (MemBase + MemSize))
+ {
+ TAddress wordAddress = (mem_addr - MemBase) / 4;
+
+ // Write
+ switch (mem_wr)
+ {
+ case 0xF:
+ Mem[wordAddress] = mem_data_out;
+ break;
+ case 0x3:
+ mem_data_out &= 0x0000FFFF;
+ Mem[wordAddress] &=~ 0x0000FFFF;
+ Mem[wordAddress] |= mem_data_out;
+ break;
+ case 0xC:
+ mem_data_out &= 0xFFFF0000;
+ Mem[wordAddress] &=~ 0xFFFF0000;
+ Mem[wordAddress] |= mem_data_out;
+ break;
+ case 0x1:
+ mem_data_out &= 0x000000FF;
+ Mem[wordAddress] &=~ 0x000000FF;
+ Mem[wordAddress] |= mem_data_out;
+ break;
+ case 0x2:
+ mem_data_out &= 0x0000FF00;
+ Mem[wordAddress] &=~ 0x0000FF00;
+ Mem[wordAddress] |= mem_data_out;
+ break;
+ case 0x4:
+ mem_data_out &= 0x00FF0000;
+ Mem[wordAddress] &=~ 0x00FF0000;
+ Mem[wordAddress] |= mem_data_out;
+ break;
+ case 0x8:
+ mem_data_out &= 0xFF000000;
+ Mem[wordAddress] &=~ 0xFF000000;
+ Mem[wordAddress] |= mem_data_out;
+ break;
+ }
+
+ // Read
+ mem_data_in = Mem[wordAddress];
+ }
+ // External / Peripheral memory
+ else
+ {
+ mem_data_in = PeripheralAccess(mem_addr, mem_data_out, mem_wr, mem_rd);
+ }
+
+ // Notify observers if memory read has occurred
+ if (mem_rd)
+ {
+ DPRINTF(LOG_MEM, ("MEM: Read Addr %x Value %x\n", mem_addr, mem_data_in));
+ MonDataLoad(mem_addr, 0xF, mem_data_in);
+ }
+
+ // Clock peripherals
+ PeripheralClock();
+
+ // Writeback (if target is not R0)
+ if (r_writeback && r_rd_wb != REG_0_ZERO)
+ {
+ r_gpr[r_rd_wb] = r_reg_rd_out;
+ r_writeback = 0;
+ }
+
+ // If write-back stage just completed, show register state...
+ if (writeback && TRACE_ENABLED(LOG_REGISTERS))
+ {
+ // Register trace
+ int i;
+ for (i=0;i
+#include
+#include
+#include
+#include "or32_isa.h"
+#include "or32_inst_dump.h"
+
+//-----------------------------------------------------------------
+// or32_instruction_to_string: Decode instruction to string
+//-----------------------------------------------------------------
+int or32_instruction_to_string(TRegister opcode, char *output, int max_len)
+{
+ TRegister v_ra = 0;
+ TRegister v_rb = 0;
+ TRegister v_rd = 0;
+ TRegister v_inst = 0;
+ TRegister v_op = 0;
+ TRegister v_target = 0;
+ TRegister v_pc = 0;
+ TRegister v_pc_next = 0;
+ TRegister v_imm = 0;
+ TRegister v_imm_uint32 = 0;
+ TRegister v_imm_int32 = 0;
+ TRegister v_offset = 0;
+ TRegister v_store_imm = 0;
+ int v_branch = 0;
+ int v_jmp = 0;
+
+ TRegister v_alu_op = 0;
+ TRegister v_shift_op = 0;
+ TRegister v_sfxx_op = 0;
+
+ // Decode opcode
+ v_inst = (opcode >> OR32_OPCODE_SHIFT) & OR32_OPCODE_MASK;
+ v_rd = (opcode >> OR32_REG_D_SHIFT) & OR32_REG_D_MASK;
+ v_ra = (opcode >> OR32_REG_A_SHIFT) & OR32_REG_A_MASK;
+ v_rb = (opcode >> OR32_REG_B_SHIFT) & OR32_REG_B_MASK;
+ v_imm = (opcode >> OR32_IMM16_SHIFT) & OR32_IMM16_MASK;
+ v_target = (opcode >> OR32_ADDR_SHIFT) & OR32_ADDR_MASK;
+ v_sfxx_op = (opcode >> OR32_SFXXX_OP_SHIFT) & OR32_SFXXX_OP_MASK;
+ v_alu_op = (opcode >> OR32_ALU_OP_L_SHIFT) & OR32_ALU_OP_L_MASK;
+ v_alu_op |= (opcode >> OR32_ALU_OP_H_SHIFT) & OR32_ALU_OP_H_MASK;
+ v_shift_op = (opcode >> OR32_SHIFT_OP_SHIFT) & OR32_SHIFT_OP_MASK;
+ v_store_imm = (opcode >> OR32_STORE_IMM_L_SHIFT) & OR32_STORE_IMM_L_MASK;
+ v_store_imm|= (opcode >> OR32_STORE_IMM_H_SHIFT) & OR32_STORE_IMM_H_MASK;
+
+ // Sign extend store immediate
+ v_store_imm = (unsigned int)(signed short)v_store_imm;
+
+ // Sign extend target immediate
+ if (v_target & (1 << 25))
+ v_target |= ~OR32_ADDR_MASK;
+
+ // Signed & unsigned imm -> 32-bits
+ v_imm_int32 = (unsigned int)(signed short)v_imm;
+ v_imm_uint32 = v_imm;
+
+ output[0] = 0;
+
+ // Execute instruction
+ switch(v_inst)
+ {
+ case INST_OR32_ALU:
+ switch (v_alu_op)
+ {
+ case INST_OR32_ADD: // l.add
+ sprintf(output, "l.add r%d,r%d,r%d", v_rd, v_ra, v_rb);
+ break;
+ case INST_OR32_ADDC: // l.addc
+ sprintf(output, "l.addc r%d,r%d,r%d", v_rd, v_ra, v_rb);
+ break;
+ case INST_OR32_AND: // l.and
+ sprintf(output, "l.and r%d,r%d,r%d", v_rd, v_ra, v_rb);
+ break;
+ case INST_OR32_OR: // l.or
+ sprintf(output, "l.or r%d,r%d,r%d", v_rd, v_ra, v_rb);
+ break;
+ case INST_OR32_SLL: // l.sll
+ sprintf(output, "l.sll r%d,r%d,r%d", v_rd, v_ra, v_rb);
+ break;
+ case INST_OR32_SRA: // l.sra
+ sprintf(output, "l.sra r%d,r%d,r%d", v_rd, v_ra, v_rb);
+ break;
+ case INST_OR32_SRL: // l.srl
+ sprintf(output, "l.srl r%d,r%d,r%d", v_rd, v_ra, v_rb);
+ break;
+ case INST_OR32_SUB: // l.sub
+ sprintf(output, "l.sub r%d,r%d,r%d", v_rd, v_ra, v_rb);
+ break;
+ case INST_OR32_XOR: // l.xor
+ sprintf(output, "l.xor r%d,r%d,r%d", v_rd, v_ra, v_rb);
+ break;
+ }
+ break;
+
+ case INST_OR32_ADDI: // l.addi
+ if ((int)v_imm_int32 < 0)
+ sprintf(output, "l.addi r%d,r%d,%d", v_rd, v_ra, v_imm_int32);
+ else
+ sprintf(output, "l.addi r%d,r%d,0x%x", v_rd, v_ra, v_imm_int32);
+ break;
+
+ case INST_OR32_ANDI: // l.andi
+ sprintf(output, "l.andi r%d,r%d,0x%x", v_rd, v_ra, v_imm_uint32);
+ break;
+
+ case INST_OR32_BF: // l.bf
+ if ((int)v_target <= 0)
+ sprintf(output, "l.bf %d", (int)v_target);
+ else
+ sprintf(output, "l.bf 0x%x", (int)v_target);
+ break;
+
+ case INST_OR32_BNF: // l.bnf
+ if ((int)v_target <= 0)
+ sprintf(output, "l.bnf %d", (int)v_target);
+ else
+ sprintf(output, "l.bnf 0x%x", (int)v_target);
+ break;
+
+ case INST_OR32_J: // l.j
+ if ((int)v_target <= 0)
+ sprintf(output, "l.j %d", (int)v_target);
+ else
+ sprintf(output, "l.j 0x%x", (int)v_target);
+ break;
+
+ case INST_OR32_JAL: // l.jal
+ if ((int)v_target <= 0)
+ sprintf(output, "l.jal %d", (int)v_target);
+ else
+ sprintf(output, "l.jal 0x%x", (int)v_target);
+ break;
+
+ case INST_OR32_JALR: // l.jalr
+ sprintf(output, "l.jalr r%d", v_rb);
+ break;
+
+ case INST_OR32_JR: // l.jr
+ sprintf(output, "l.jr r%d", v_rb);
+ break;
+
+ case INST_OR32_LBS: // l.lbs
+ if ((int)v_imm_int32 < 0)
+ sprintf(output, "l.lbs r%d,%d(r%d)", v_rd, (int)v_imm_int32, v_ra, v_rd);
+ else
+ sprintf(output, "l.lbs r%d,0x%x(r%d)", v_rd, (int)v_imm_int32, v_ra, v_rd);
+ break;
+
+ case INST_OR32_LHS: // l.lhs
+ if ((int)v_imm_int32 < 0)
+ sprintf(output, "l.lhs r%d,%d(r%d)", v_rd, (int)v_imm_int32, v_ra, v_rd);
+ else
+ sprintf(output, "l.lhs r%d,0x%x(r%d)", v_rd, (int)v_imm_int32, v_ra, v_rd);
+ break;
+
+ case INST_OR32_LWS: // l.lws
+ if ((int)v_imm_int32 < 0)
+ sprintf(output, "l.lws r%d,%d(r%d)", v_rd, (int)v_imm_int32, v_ra, v_rd);
+ else
+ sprintf(output, "l.lws r%d,0x%x(r%d)", v_rd, (int)v_imm_int32, v_ra, v_rd);
+ break;
+
+ case INST_OR32_LBZ: // l.lbz
+ if ((int)v_imm_int32 < 0)
+ sprintf(output, "l.lbz r%d,%d(r%d)", v_rd, (int)v_imm_int32, v_ra, v_rd);
+ else
+ sprintf(output, "l.lbz r%d,0x%x(r%d)", v_rd, (int)v_imm_int32, v_ra, v_rd);
+ break;
+
+ case INST_OR32_LHZ: // l.lhz
+ if ((int)v_imm_int32 < 0)
+ sprintf(output, "l.lhz r%d,%d(r%d)", v_rd, (int)v_imm_int32, v_ra, v_rd);
+ else
+ sprintf(output, "l.lhz r%d,0x%x(r%d)", v_rd, (int)v_imm_int32, v_ra, v_rd);
+ break;
+
+ case INST_OR32_LWZ: // l.lwz
+ if ((int)v_imm_int32 < 0)
+ sprintf(output, "l.lwz r%d,%d(r%d)", v_rd, (int)v_imm_int32, v_ra, v_rd);
+ else
+ sprintf(output, "l.lwz r%d,0x%x(r%d)", v_rd, (int)v_imm_int32, v_ra, v_rd);
+ break;
+
+ case INST_OR32_MFSPR: // l.mfspr
+ break;
+
+ case INST_OR32_MOVHI: // l.movhi
+ if (v_imm_uint32 == 0)
+ sprintf(output, "l.movhi r%d,%d", v_rd, v_imm_uint32);
+ else
+ sprintf(output, "l.movhi r%d,0x%x", v_rd, v_imm_uint32);
+ break;
+
+ case INST_OR32_MTSPR: // l.mtspr
+ break;
+
+ case INST_OR32_NOP: // l.nop
+ if (v_imm != 0)
+ sprintf(output, "l.nop 0x%x", v_imm);
+ else
+ sprintf(output, "l.nop 0");
+ break;
+
+ case INST_OR32_ORI: // l.ori
+ if (v_imm_uint32 == 0)
+ sprintf(output, "l.ori r%d,r%d,%d", v_rd, v_ra, v_imm_uint32);
+ else
+ sprintf(output, "l.ori r%d,r%d,0x%x", v_rd, v_ra, v_imm_uint32);
+ break;
+
+ case INST_OR32_RFE: // l.rfe
+ sprintf(output, "l.rfe");
+ break;
+
+ case INST_OR32_SHIFTI:
+ switch (v_shift_op)
+ {
+ case INST_OR32_SLLI: // l.slli
+ sprintf(output, "l.slli r%d,r%d,0x%x", v_rd, v_ra, (opcode & 0x3F));
+ break;
+ case INST_OR32_SRAI: // l.srai
+ sprintf(output, "l.srai r%d,r%d,0x%x", v_rd, v_ra, (opcode & 0x3F));
+ break;
+ case INST_OR32_SRLI: // l.srli
+ sprintf(output, "l.srli r%d,r%d,0x%x", v_rd, v_ra, (opcode & 0x3F));
+ break;
+ }
+ break;
+
+ case INST_OR32_SB: // l.sb
+ if ((int)v_store_imm < 0)
+ sprintf(output, "l.sb %d(r%d),r%d", (int)v_store_imm, v_ra, v_rb);
+ else
+ sprintf(output, "l.sb 0x%x(r%d),r%d", (int)v_store_imm, v_ra, v_rb);
+ break;
+
+ case INST_OR32_SFXX:
+ case INST_OR32_SFXXI:
+ switch (v_sfxx_op)
+ {
+ case INST_OR32_SFEQ: // l.sfeq
+ sprintf(output, "l.sfeq r%d,r%d", v_ra, v_rb);
+ break;
+ case INST_OR32_SFEQI: // l.sfeqi
+ sprintf(output, "l.sfeqi r%d,0x%x", v_ra, (int)v_imm_int32);
+ break;
+ case INST_OR32_SFGES: // l.sfges
+ sprintf(output, "l.sfges r%d,r%d", v_ra, v_rb);
+ break;
+ case INST_OR32_SFGESI: // l.sfgesi
+ sprintf(output, "l.sfgesi r%d,0x%x", v_ra, (int)v_imm_int32);
+ break;
+ case INST_OR32_SFGEU: // l.sfgeu
+ sprintf(output, "l.sfgeu r%d,r%d", v_ra, v_rb);
+ break;
+ case INST_OR32_SFGEUI: // l.sfgeui
+ sprintf(output, "l.sfgeui r%d,0x%x", v_ra, v_imm_uint32);
+ break;
+ case INST_OR32_SFGTS: // l.sfgts
+ sprintf(output, "l.sfgts r%d,r%d", v_ra, v_rb);
+ break;
+ case INST_OR32_SFGTSI: // l.sfgtsi
+ sprintf(output, "l.sfgtsi r%d,0x%x", v_ra, (int)v_imm_int32);
+ break;
+ case INST_OR32_SFGTU: // l.sfgtu
+ sprintf(output, "l.sfgtu r%d,r%d", v_ra, v_rb);
+ break;
+ case INST_OR32_SFGTUI: // l.sfgtui
+ sprintf(output, "l.sfgtui r%d,0x%x", v_ra, v_imm_uint32);
+ break;
+ case INST_OR32_SFLES: // l.sfles
+ sprintf(output, "l.sfles r%d,r%d", v_ra, v_rb);
+ break;
+ case INST_OR32_SFLESI: // l.sflesi
+ sprintf(output, "l.sflesi r%d,0x%x", v_ra, (int)v_imm_int32);
+ break;
+ case INST_OR32_SFLEU: // l.sfleu
+ sprintf(output, "l.sfleu r%d,r%d", v_ra, v_rb);
+ break;
+ case INST_OR32_SFLEUI: // l.sfleui
+ sprintf(output, "l.sfleui r%d,0x%x", v_ra, v_imm_uint32);
+ break;
+ case INST_OR32_SFLTS: // l.sflts
+ sprintf(output, "l.sflts r%d,r%d", v_ra, v_rb);
+ break;
+ case INST_OR32_SFLTSI: // l.sfltsi
+ sprintf(output, "l.sfltsi r%d,0x%x", v_ra, (int)v_imm_int32);
+ break;
+ case INST_OR32_SFLTU: // l.sfltu
+ sprintf(output, "l.sfltu r%d,r%d", v_ra, v_rb);
+ break;
+ case INST_OR32_SFLTUI: // l.sfltui
+ sprintf(output, "l.sfltui r%d,0x%x", v_ra, v_imm_uint32);
+ break;
+ case INST_OR32_SFNE: // l.sfne
+ sprintf(output, "l.sfne r%d,r%d", v_ra, v_rb);
+ break;
+ case INST_OR32_SFNEI: // l.sfnei
+ sprintf(output, "l.sfnei r%d,0x%x", v_ra, v_imm_uint32);
+ break;
+ }
+ break;
+
+ case INST_OR32_SH: // l.sh
+ if ((int)v_store_imm < 0)
+ sprintf(output, "l.sh %d(r%d),r%d", (int)v_store_imm, v_ra, v_rb);
+ else
+ sprintf(output, "l.sh 0x%x(r%d),r%d", (int)v_store_imm, v_ra, v_rb);
+ break;
+
+ case INST_OR32_SW: // l.sw
+ if ((int)v_store_imm < 0)
+ sprintf(output, "l.sw %d(r%d),r%d", (int)v_store_imm, v_ra, v_rb);
+ else
+ sprintf(output, "l.sw 0x%x(r%d),r%d", (int)v_store_imm, v_ra, v_rb);
+ break;
+
+ case INST_OR32_MISC:
+ switch (opcode >> 24)
+ {
+ case INST_OR32_SYS: // l.sys
+ sprintf(output, "l.sys");
+ break;
+
+ case INST_OR32_TRAP: // l.trap
+ sprintf(output, "l.trap");
+ break;
+ }
+ break;
+
+ case INST_OR32_XORI: // l.xori
+ if ((int)v_imm_int32 < 0)
+ sprintf(output, "l.xori r%d,r%d,%d", v_rd, v_ra, v_imm_int32);
+ else
+ sprintf(output, "l.xori r%d,r%d,0x%x", v_rd, v_ra, v_imm_int32);
+ break;
+ }
+
+ return (output[0] != 0);
+}
+//-----------------------------------------------------------------
+// or32_instruction_to_string: Decode instruction to string
+//-----------------------------------------------------------------
+void or32_instruction_dump(TRegister pc, TRegister opcode, TRegister gpr[REGISTERS], TRegister rd, TRegister result, TRegister sr)
+{
+ char output[1024];
+
+ // Decode opcode in-order to perform register reads
+ TRegister ra = (opcode >> OR32_REG_A_SHIFT) & OR32_REG_A_MASK;
+ TRegister rb = (opcode >> OR32_REG_B_SHIFT) & OR32_REG_B_MASK;
+ TRegister v_inst = (opcode >> OR32_OPCODE_SHIFT) & OR32_OPCODE_MASK;
+
+ TRegister v_store_imm = (opcode >> OR32_STORE_IMM_L_SHIFT) & OR32_STORE_IMM_L_MASK;
+ v_store_imm|= (opcode >> OR32_STORE_IMM_H_SHIFT) & OR32_STORE_IMM_H_MASK;
+ v_store_imm = (unsigned int)(signed short)v_store_imm;
+
+ // Decode instruction in or1ksim trace format
+ or32_instruction_to_string(opcode, output, sizeof(output)-1);
+
+ if (rd != 0 && v_inst != INST_OR32_JAL && v_inst != INST_OR32_JALR)
+ printf("S %08x: %08x %-23s r%d = %08x flag: %d\n", pc, opcode, output, rd, result, sr & OR32_SR_F_BIT ? 1: 0);
+ else if (v_inst == INST_OR32_SB || v_inst == INST_OR32_SH || v_inst == INST_OR32_SW)
+ {
+ if (v_inst == INST_OR32_SB)
+ printf("S %08x: %08x %-23s [%08x] = %02x flag: %d\n", pc, opcode, output, gpr[ra] + (int)v_store_imm, gpr[rb], sr & OR32_SR_F_BIT ? 1: 0);
+ else if (v_inst == INST_OR32_SH)
+ printf("S %08x: %08x %-23s [%08x] = %04x flag: %d\n", pc, opcode, output, gpr[ra] + (int)v_store_imm, gpr[rb], sr & OR32_SR_F_BIT ? 1: 0);
+ else
+ printf("S %08x: %08x %-23s [%08x] = %08x flag: %d\n", pc, opcode, output, gpr[ra] + (int)v_store_imm, gpr[rb], sr & OR32_SR_F_BIT ? 1: 0);
+ }
+ else
+ printf("S %08x: %08x %-45s flag: %d\n", pc, opcode, output, sr & OR32_SR_F_BIT ? 1: 0);
+}
Index: or32-sim/getopt_win32.h
===================================================================
--- or32-sim/getopt_win32.h (nonexistent)
+++ or32-sim/getopt_win32.h (revision 2)
@@ -0,0 +1,37 @@
+// XGetopt.h Version 1.2
+//
+// Author: Hans Dietrich
+// hdietrich2@hotmail.com
+//
+// This software is released into the public domain.
+// You are free to use it in any way you like.
+//
+// This software is provided "as is" with no expressed
+// or implied warranty. I accept no liability for any
+// damage or loss of business that this software may cause.
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef XGETOPT_H
+#define XGETOPT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef WIN32
+
+#include
+
+extern int optind, opterr;
+extern TCHAR *optarg;
+
+int getopt(int argc, TCHAR *argv[], TCHAR *optstring);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //XGETOPT_H
Index: or32-sim/README.txt
===================================================================
--- or32-sim/README.txt (nonexistent)
+++ or32-sim/README.txt (revision 2)
@@ -0,0 +1,45 @@
+AltOR32 OpenRisc Simulator
+--------------------------
+
+Details
+-------
+
+- Simple simulator for OpenRisc instructions, where only the essentials have been implemented.
+- Compiles under Linux (make) or Windows (VS2003+).
+- Able to execute OpenRisc 1000 (ORBIS32) code compiled with the following options:
+ -msoft-div -msoft-float -msoft-mul -mno-ror -mno-cmov -mno-sext
+
+Usage
+-----
+
+-f filename.bin = Executable to load (binary) [Required]
+-t = Enable program trace [Optional]
+-v 0xX = Trace Mask [Optional]
+-b 0xnnnn = Memory base address [Optional]
+-s 0xnnnn = Memory size [Optional]
+-l 0xnnnn = Executable load address [Optional]
+-c nnnn = Max instructions to execute [Optional]
+
+Console Output
+--------------
+
+This simulator implements some of the basic l.nop extensions such as NOP_PUTC(4).
+
+Example:
+
+ register char t1 asm ("r3") = c;
+ asm volatile ("\tl.nop\t%0" : : "K" (4), "r" (t1));
+
+
+Implementing Peripherals
+------------------------
+
+Peripherals can be implemented creating a new class which inherits from OR32 and overrides the following functions
+to provide memory mapped I/O extensions;
+
+ // Peripheral access
+ virtual void PeripheralReset(void) { }
+ virtual void PeripheralClock(void) { }
+ virtual TRegister PeripheralAccess(TAddress addr, TRegister data_in, TRegister wr, TRegister rd) { return 0; }
+ virtual bool PeripheralInt(void) { return false; }
+
Index: or32-sim/or32.h
===================================================================
--- or32-sim/or32.h (nonexistent)
+++ or32-sim/or32.h (revision 2)
@@ -0,0 +1,111 @@
+#ifndef __OR32_H__
+#define __OR32_H__
+
+#include "or32_isa.h"
+
+//--------------------------------------------------------------------
+// Defines:
+//--------------------------------------------------------------------
+#define LOG_OR1K (1 << 0)
+#define LOG_INST (1 << 1)
+#define LOG_REGISTERS (1 << 2)
+#define LOG_MEM (1 << 3)
+
+//--------------------------------------------------------------------
+// Class
+//--------------------------------------------------------------------
+class OR32
+{
+public:
+ OR32(unsigned int baseAddr, unsigned int len);
+ virtual ~OR32();
+
+ bool Load(unsigned int startAddr, unsigned char *data, int len);
+ bool WriteMem(TAddress addr, unsigned char *data, int len);
+ bool ReadMem(TAddress addr, unsigned char *data, int len);
+
+ void Reset(TRegister start_addr = VECTOR_RESET);
+ bool Clock(void);
+ bool Step(void);
+
+ int GetFault(void) { return Fault; }
+ int GetBreak(void) { return Break; }
+ TRegister GetRegister(int r) { return (r < REGISTERS) ? r_gpr[r] : 0; }
+
+ void EnableTrace(unsigned mask) { Trace = mask; }
+
+ void DumpStats(void);
+
+protected:
+ void Decode(void);
+ void Execute(void);
+ void WriteBack(void);
+
+protected:
+ // Peripheral access
+ virtual void PeripheralReset(void) { }
+ virtual void PeripheralClock(void) { }
+ virtual TRegister PeripheralAccess(TAddress addr, TRegister data_in, TRegister wr, TRegister rd) { return 0; }
+ virtual bool PeripheralInt(void) { return false; }
+
+protected:
+ // Execution monitoring
+ virtual void MonInstructionExecute(TAddress addr, TRegister instr) { }
+ virtual void MonDataLoad(TAddress addr, TRegister mask, TAddress value) { }
+ virtual void MonDataStore(TAddress addr, TRegister mask, TAddress value) { }
+ virtual void MonFault(TAddress addr, TRegister instr) { }
+ virtual void MonExit(void) { }
+ virtual void MonNop(TRegister imm);
+
+private:
+
+ // CPU Registers
+ TRegister r_gpr[REGISTERS];
+ TRegister r_pc;
+ TRegister r_pc_next;
+ TRegister r_pc_last;
+ TRegister r_sr;
+ TRegister r_epc;
+ TRegister r_esr;
+
+ // Register file access
+ TRegister r_ra;
+ TRegister r_rd;
+ TRegister r_rd_wb;
+ TRegister r_rb;
+ TRegister r_reg_ra;
+ TRegister r_reg_rb;
+ TRegister r_reg_result;
+ TRegister r_reg_rd_out;
+ int r_writeback;
+ TInstruction r_opcode;
+
+ // Memory
+ TMemory *Mem;
+ TAddress MemBase;
+ unsigned int MemSize;
+
+ // Memory access
+ TAddress mem_addr;
+ TRegister mem_data_out;
+ TRegister mem_data_in;
+ TRegister mem_offset;
+ TRegister mem_wr;
+ TRegister mem_rd;
+
+ // Status
+ int Fault;
+ int Break;
+ TRegister BreakValue;
+ unsigned Trace;
+ int Cycle;
+
+ // Stats
+ int StatsMem;
+ int StatsInstructions;
+ int StatsNop;
+ int StatsBranches;
+ int StatsExceptions;
+};
+
+#endif
Index: or32-sim/makefile
===================================================================
--- or32-sim/makefile (nonexistent)
+++ or32-sim/makefile (revision 2)
@@ -0,0 +1,31 @@
+###############################################################################
+## Simulator Makefile
+###############################################################################
+
+# Target
+TARGET = or32-sim
+
+# Options
+CFLAGS =
+LDFLAGS =
+
+# Source Files
+OBJ = main.o or32.o or32_inst_dump.o
+
+###############################################################################
+# Rules
+###############################################################################
+all: $(TARGET)
+
+clean:
+ -rm *.o $(TARGET)
+
+%.o : %.c
+ gcc -c $(CFLAGS) $< -o $@
+
+%.o : %.cpp
+ g++ -c $(CFLAGS) $< -o $@
+
+$(TARGET): $(OBJ) makefile
+ g++ $(LDFLAGS) $(LIBS) $(OBJ) -o $@
+
Index: or32-sim/or32-sim.vcproj
===================================================================
--- or32-sim/or32-sim.vcproj (nonexistent)
+++ or32-sim/or32-sim.vcproj (revision 2)
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: or32-sim/or32_inst_dump.h
===================================================================
--- or32-sim/or32_inst_dump.h (nonexistent)
+++ or32-sim/or32_inst_dump.h (revision 2)
@@ -0,0 +1,13 @@
+#ifndef _OR32_INST_DUMP_H_
+#define _OR32_INST_DUMP_H_
+
+#include "or32_isa.h"
+
+//-----------------------------------------------------------------
+// Prototypes:
+//-----------------------------------------------------------------
+int or32_instruction_to_string(TRegister opcode, char *output, int max_len);
+void or32_instruction_dump(TRegister pc, TRegister opcode, TRegister gpr[REGISTERS], TRegister rd, TRegister result, TRegister sr);
+
+#endif
+
Index: or32-sim
===================================================================
--- or32-sim (nonexistent)
+++ or32-sim (revision 2)
or32-sim
Property changes :
Added: bugtraq:number
## -0,0 +1 ##
+true
\ No newline at end of property