OpenCores
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.