URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/or1k/tags/nog_patch_67/or1ksim/cpu/common
- from Rev 1460 to Rev 1765
- ↔ Reverse comparison
Rev 1460 → Rev 1765
/abstract.c
0,0 → 1,1210
/* abstract.c -- Abstract entities |
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program 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. |
|
This program 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 this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
/* Abstract memory and routines that go with this. I need to |
add all sorts of other abstract entities. Currently we have |
only memory. */ |
|
#include <stdlib.h> |
#include <stdio.h> |
#include <ctype.h> |
#include <string.h> |
|
#include "config.h" |
|
#ifdef HAVE_INTTYPES_H |
#include <inttypes.h> |
#endif |
|
#include "port.h" |
|
#include "arch.h" |
#include "parse.h" |
#include "abstract.h" |
#include "sim-config.h" |
#include "labels.h" |
#include "except.h" |
#include "debug_unit.h" |
#include "opcode/or32.h" |
#include "spr_defs.h" |
#include "execute.h" |
#include "sprs.h" |
#include "support/profile.h" |
#include "dmmu.h" |
#include "immu.h" |
#include "dcache_model.h" |
#include "icache_model.h" |
#include "debug.h" |
#include "stats.h" |
|
#if DYNAMIC_EXECUTION |
#include "dyn_rec.h" |
#endif |
|
extern char *disassembled; |
|
/* Pointer to memory area descriptions that are assigned to individual |
peripheral devices. */ |
struct dev_memarea *dev_list; |
|
/* Temporary variable to increase speed. */ |
struct dev_memarea *cur_area; |
|
/* Pointer to memory controller device descriptor. */ |
struct dev_memarea *mc_area = (struct dev_memarea *)0; |
|
/* These are set by mmu if cache inhibit bit is set for current acces. */ |
int data_ci, insn_ci; |
|
/* Virtual address of current access. */ |
oraddr_t cur_vadd; |
|
/* Calculates bit mask to fit the data */ |
unsigned int bit_mask (uint32_t data) { |
int i = 0; |
data--; |
while (data >> i) |
data |= 1 << i++; |
return data; |
} |
|
/* Register read and write function for a memory area. |
addr is inside the area, if addr & addr_mask == addr_compare |
(used also by peripheral devices like 16450 UART etc.) */ |
void register_memoryarea_mask(oraddr_t addr_mask, oraddr_t addr_compare, |
uint32_t size, unsigned granularity, unsigned mc_dev, |
uint32_t (readfunc)(oraddr_t, void *), |
void (writefunc)(oraddr_t, uint32_t, void *), |
void *dat) |
{ |
struct dev_memarea **pptmp; |
unsigned int size_mask = bit_mask (size); |
int found_error = 0; |
addr_compare &= addr_mask; |
|
debug(5, "addr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR", size %08"PRIx32", gran %iB\n", |
addr_mask, addr_compare, addr_compare | bit_mask (size), size, |
granularity); |
/* Go to the end of the list. */ |
for(pptmp = &dev_list; *pptmp; pptmp = &(*pptmp)->next) |
if ((addr_compare >= (*pptmp)->addr_compare) && (addr_compare < (*pptmp)->addr_compare + (*pptmp)->size) |
|| (addr_compare + size > (*pptmp)->addr_compare) && (addr_compare < (*pptmp)->addr_compare + (*pptmp)->size)) { |
if (!found_error) { |
fprintf (stderr, "ERROR: Overlapping memory area(s):\n"); |
fprintf (stderr, "\taddr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR |
", size %08"PRIx32", gran %iB\n", |
addr_mask, addr_compare, addr_compare | bit_mask (size), size, |
granularity); |
} |
found_error = 1; |
fprintf (stderr, "and\taddr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR |
", size %08"PRIx32", gran %iB\n", |
(*pptmp)->addr_mask, (*pptmp)->addr_compare, |
(*pptmp)->addr_compare | (*pptmp)->size_mask, |
(*pptmp)->size, (*pptmp)->granularity); |
} |
|
if (found_error) |
exit (-1); |
|
cur_area = *pptmp = (struct dev_memarea *)malloc(sizeof(struct dev_memarea)); |
|
if (mc_dev) |
mc_area = *pptmp; |
|
(*pptmp)->addr_mask = addr_mask; |
(*pptmp)->addr_compare = addr_compare; |
(*pptmp)->size = size; |
(*pptmp)->size_mask = size_mask; |
(*pptmp)->granularity = granularity; |
(*pptmp)->readfunc = readfunc; |
(*pptmp)->writefunc = writefunc; |
(*pptmp)->log = 0; |
(*pptmp)->delayr = 2; |
(*pptmp)->delayw = 2; |
(*pptmp)->priv_dat = dat; |
(*pptmp)->chip_select = -1; |
(*pptmp)->next = NULL; |
} |
|
/* Register read and write function for a memory area. |
Memory areas should be aligned. Memory area is rounded up to |
fit the nearest 2^n aligment. |
(used also by peripheral devices like 16450 UART etc.) |
If mc_dev is 1, this means that this device will be checked first for match |
and will be accessed in case of overlaping memory spaces. |
Only one device can have this set to 1 (used for memory controller) */ |
void register_memoryarea(oraddr_t addr, uint32_t size, unsigned granularity, |
unsigned mc_dev, |
uint32_t (readfunc)(oraddr_t, void *), |
void (writefunc)(oraddr_t, uint32_t, void *), |
void *dat) |
{ |
unsigned int size_mask = bit_mask (size); |
unsigned int addr_mask = ~size_mask; |
register_memoryarea_mask (addr_mask, addr & addr_mask, |
size_mask + 1, granularity, mc_dev, |
readfunc, writefunc, dat); |
} |
|
|
/* Check if access is to registered area of memory. */ |
inline struct dev_memarea *verify_memoryarea(oraddr_t addr) |
{ |
struct dev_memarea *ptmp; |
|
/* Check memory controller space first */ |
if (mc_area && (addr & mc_area->addr_mask) == (mc_area->addr_compare & mc_area->addr_mask)) |
return cur_area = mc_area; |
|
/* Check cached value */ |
if (cur_area && (addr & cur_area->addr_mask) == (cur_area->addr_compare & cur_area->addr_mask)) |
return cur_area; |
|
/* When mc is enabled, we must check valid also, otherwise we assume it is nonzero */ |
/* Check list of registered devices. */ |
for(ptmp = dev_list; ptmp; ptmp = ptmp->next) |
if ((addr & ptmp->addr_mask) == (ptmp->addr_compare & ptmp->addr_mask) && ptmp->valid) |
return cur_area = ptmp; |
return cur_area = NULL; |
} |
|
/* Finds the memory area for the address and adjust the read and write delays for it. */ |
void adjust_rw_delay(oraddr_t memaddr, unsigned int delayr, unsigned int delayw) |
{ |
if (verify_memoryarea(memaddr)) { |
cur_area->delayr = delayr; |
cur_area->delayw = delayw; |
} |
} |
|
/* for cpu accesses |
* |
* STATISTICS: check cpu/common/parse.c |
*/ |
inline uint32_t evalsim_mem32(oraddr_t memaddr) |
{ |
return(evalsim_mem32_atomic(memaddr, 1)); |
} |
|
/* for simulator accesses, the ones that cpu wouldn't do */ |
inline uint32_t evalsim_mem32_void(oraddr_t memaddr) |
{ |
return(evalsim_mem32_atomic(memaddr, 0)); |
} |
|
uint32_t evalsim_mem32_atomic(oraddr_t memaddr, int cpu_access) |
{ |
uint32_t temp = 0; |
|
if (verify_memoryarea(memaddr)) { |
switch(cur_area->granularity) { |
case 4: |
temp = cur_area->readfunc(memaddr, cur_area->priv_dat); |
break; |
case 1: |
temp = cur_area->readfunc(memaddr, cur_area->priv_dat) << 24; |
temp |= cur_area->readfunc(memaddr + 1, cur_area->priv_dat) << 16; |
temp |= cur_area->readfunc(memaddr + 2, cur_area->priv_dat) << 8; |
temp |= cur_area->readfunc(memaddr + 3, cur_area->priv_dat); |
break; |
case 2: |
temp = cur_area->readfunc(memaddr, cur_area->priv_dat) << 16; |
temp |= cur_area->readfunc(memaddr + 2, cur_area->priv_dat); |
break; |
default: |
/* if you add new memory granularity be sure to check the formula |
* below for the read delay and fix it if necessery |
*/ |
PRINTF("unknown/unhandled memory granularuty\n"); |
exit(-1); |
} |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayr * (4 / cur_area->granularity); |
} |
return temp; |
} |
|
/* for cpu accesses */ |
inline uint16_t evalsim_mem16(oraddr_t memaddr) |
{ |
return(evalsim_mem16_atomic(memaddr, 1)); |
} |
|
/* for simulator accesses, the ones that cpu wouldn't do */ |
inline uint16_t evalsim_mem16_void(oraddr_t memaddr) |
{ |
return(evalsim_mem16_atomic(memaddr, 0)); |
} |
|
uint16_t evalsim_mem16_atomic(oraddr_t memaddr, int cpu_access) |
{ |
uint32_t temp = 0; |
|
if (verify_memoryarea(memaddr)) { |
switch(cur_area->granularity) { |
case 1: |
temp = cur_area->readfunc(memaddr, cur_area->priv_dat) << 8; |
temp |= cur_area->readfunc(memaddr + 1, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayr * 2; |
break; |
case 2: |
temp = cur_area->readfunc(memaddr, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayr; |
break; |
case 4: |
temp = evalsim_mem32_atomic (memaddr & ~UINT32_C(3), cpu_access); |
if (memaddr & 2) |
temp &= 0xffff; |
else |
temp >>= 16; |
break; |
default: |
/* if you add new memory granularity be sure to check the formula |
* below for the read delay and fix it if necessery |
*/ |
PRINTF("unknown/unhandled memory granularuty\n"); |
exit(-1); |
} |
} |
return temp; |
} |
|
/* for cpu accesses */ |
inline uint8_t evalsim_mem8(oraddr_t memaddr) |
{ |
return(evalsim_mem8_atomic(memaddr, 1)); |
} |
|
/* for simulator accesses, the ones that cpu wouldn't do */ |
inline uint8_t evalsim_mem8_void(oraddr_t memaddr) |
{ |
return(evalsim_mem8_atomic(memaddr, 0)); |
} |
|
uint8_t evalsim_mem8_atomic(oraddr_t memaddr, int cpu_access) |
{ |
uint32_t temp = 0; |
|
if (verify_memoryarea(memaddr)) { |
switch(cur_area->granularity) { |
case 1: |
temp = cur_area->readfunc(memaddr, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayr; |
break; |
case 2: |
temp = evalsim_mem16_atomic (memaddr & ~ADDR_C(1), cpu_access); |
if (memaddr & 1) |
temp &= 0xff; |
else |
temp >>= 8; |
break; |
case 4: |
temp = evalsim_mem32_atomic (memaddr & ~ADDR_C(3), cpu_access); |
temp >>= 8 * (3 - (memaddr & 3)); |
temp &= 0xff; |
break; |
default: |
/* if you add new memory granularity be sure to check the formula |
* below for the read delay and fix it if necessery |
*/ |
PRINTF("unknown/unhandled memory granularuty\n"); |
exit(-1); |
} |
} |
return temp; |
} |
|
/* Returns 32-bit values from mem array. Big endian version. |
* |
* this function is only used in dumpmemory() below, so it's |
* safe to asume it's for simulator purposes access only, |
* hence the use of eval_mem32_void() |
* |
* STATISTICS OK. |
*/ |
static uint32_t read_mem(oraddr_t memaddr, int* breakpoint) |
{ |
uint32_t temp; |
|
cur_vadd = memaddr; |
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */ |
temp = evalsim_mem32_void(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} else if (cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", memaddr, temp); |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */ |
return temp; |
} |
|
/* Returns 32-bit values from mem array. Big endian version. |
* |
* STATISTICS OK (only used for cpu_access, that is architectural access) |
*/ |
uint32_t eval_mem32(oraddr_t memaddr,int* breakpoint) |
{ |
uint32_t temp; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_32 | MPROF_READ); |
|
if (memaddr & 3) { |
except_handle (EXCEPT_ALIGN, memaddr); |
return 0; |
} |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */ |
|
cur_vadd = memaddr; |
|
memaddr = dmmu_translate(memaddr, 0); |
if (except_pending) |
return 0; |
|
if (config.dc.enabled) |
temp = dc_simulate_read(memaddr, 4); |
else { |
temp = evalsim_mem32(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
} |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */ |
return temp; |
} |
|
/* for simulator accesses, the ones that cpu wouldn't do |
* |
* STATISTICS OK |
*/ |
uint32_t eval_direct32(oraddr_t memaddr, int *breakpoint, int through_mmu, |
int through_dc) |
{ |
uint32_t temp; |
|
if (memaddr & 3) { |
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__); |
return 0; |
} |
|
cur_vadd = memaddr; |
|
if (through_mmu) |
memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
|
if (through_dc) |
temp = dc_simulate_read(memaddr, 4); |
else { |
temp = evalsim_mem32_void(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR |
") in eval_direct32()\n", memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
} |
|
return temp; |
} |
|
|
/* Returns 32-bit values from mem array. Big endian version. |
* |
* STATISTICS OK (only used for cpu_access, that is architectural access) |
*/ |
uint32_t eval_insn(oraddr_t memaddr, int* breakpoint) |
{ |
uint32_t temp; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_32 | MPROF_FETCH); |
// memaddr = simulate_ic_mmu_fetch(memaddr); |
|
cur_vadd = memaddr; |
|
#if !(DYNAMIC_EXECUTION) |
memaddr = immu_translate(memaddr); |
|
if (except_pending) |
return 0; |
#endif |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); |
|
if (config.ic.enabled) |
temp = ic_simulate_fetch(memaddr); |
else { |
temp = evalsim_mem32(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
} |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadData,temp); |
return temp; |
} |
|
/* Returns 32-bit values from mem array. Big endian version. |
* |
* STATISTICS OK |
*/ |
uint32_t eval_insn_direct(oraddr_t memaddr, int* breakpoint, int through_mmu) |
{ |
uint32_t temp; |
int brk; |
|
cur_vadd = memaddr; |
|
if(through_mmu) |
memaddr = peek_into_itlb(memaddr); |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadAddress, memaddr); |
|
temp = eval_direct32(memaddr, &brk, 0, 0); |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadData, temp); |
|
return temp; |
} |
|
|
/* Returns 16-bit values from mem array. Big endian version. |
* |
* STATISTICS OK (only used for cpu_access, that is architectural access) |
*/ |
uint16_t eval_mem16(oraddr_t memaddr,int* breakpoint) |
{ |
uint16_t temp; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_16 | MPROF_READ); |
|
if (memaddr & 1) { |
except_handle (EXCEPT_ALIGN, memaddr); |
return 0; |
} |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */ |
|
cur_vadd = memaddr; |
|
memaddr = dmmu_translate(memaddr, 0); |
if (except_pending) |
return 0; |
|
if (config.dc.enabled) |
temp = (uint16_t)dc_simulate_read(memaddr, 2); |
else { |
temp = evalsim_mem16(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (16-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
} |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */ |
return temp; |
} |
|
/* for simulator accesses, the ones that cpu wouldn't do |
* |
* STATISTICS OK. |
*/ |
uint16_t eval_direct16(oraddr_t memaddr, int *breakpoint, int through_mmu, |
int through_dc) |
{ |
uint32_t temp; |
|
if (memaddr & 1) { |
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__); |
return 0; |
} |
|
cur_vadd = memaddr; |
|
if (through_mmu) |
memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
|
if (through_dc) |
temp = dc_simulate_read(memaddr, 2); |
else { |
temp = evalsim_mem16_void(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (16-bit access to %"PRIxADDR |
") in eval_direct16()\n", memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
} |
|
return temp; |
} |
|
|
/* Returns 8-bit values from mem array. |
* |
* STATISTICS OK (only used for cpu_access, that is architectural access) |
*/ |
uint8_t eval_mem8(oraddr_t memaddr,int* breakpoint) |
{ |
uint8_t temp; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_8 | MPROF_READ); |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */ |
|
cur_vadd = memaddr; |
|
memaddr = dmmu_translate(memaddr, 0); |
if (except_pending) |
return 0; |
|
if (config.dc.enabled) |
temp = (uint8_t)dc_simulate_read(memaddr, 1); |
else { |
temp = evalsim_mem8(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (8-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
} |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */ |
return temp; |
} |
|
/* for simulator accesses, the ones that cpu wouldn't do |
* |
* STATISTICS OK. |
*/ |
uint8_t eval_direct8(oraddr_t memaddr, int *breakpoint, int through_mmu, |
int through_dc) |
{ |
uint8_t temp; |
|
cur_vadd = memaddr; |
|
if (through_mmu) |
memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
|
if (through_dc) |
temp = (unsigned char)dc_simulate_read(memaddr, 1); |
else { |
temp = evalsim_mem8_void(memaddr); |
if (!cur_area) { |
PRINTF("EXCEPTION: read out of memory (8-bit access to %"PRIxADDR |
") in eval_direct8()\n", memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
temp = 0; |
} |
} |
return temp; |
} |
|
/* for cpu accesses */ |
inline void setsim_mem32(oraddr_t memaddr, uint32_t value) |
{ |
return(setsim_mem32_atomic(memaddr, value, 1)); |
} |
|
/* for simulator accesses, the ones that cpu wouldn't do */ |
inline void setsim_mem32_void(oraddr_t memaddr, uint32_t value) |
{ |
return(setsim_mem32_atomic(memaddr, value, 0)); |
} |
|
void setsim_mem32_atomic(oraddr_t memaddr, uint32_t value, int cpu_access) |
{ |
if (verify_memoryarea(memaddr)) { |
switch(cur_area->granularity) { |
case 4: |
cur_area->writefunc(memaddr, value, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayw; |
break; |
case 1: |
cur_area->writefunc(memaddr , (value >> 24) & 0xFF, cur_area->priv_dat); |
cur_area->writefunc(memaddr + 1, (value >> 16) & 0xFF, cur_area->priv_dat); |
cur_area->writefunc(memaddr + 2, (value >> 8) & 0xFF, cur_area->priv_dat); |
cur_area->writefunc(memaddr + 3, (value ) & 0xFF, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayw * 4; |
break; |
case 2: |
cur_area->writefunc(memaddr, (value >> 16) & 0xFFFF, cur_area->priv_dat); |
cur_area->writefunc(memaddr + 2, value & 0xFFFF, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayw * 2; |
break; |
default: |
/* if you add new memory granularity be sure to check the formula |
* below for the read delay and fix it if necessery |
*/ |
PRINTF("unknown/unhandled memory granularuty\n"); |
exit(-1); |
} |
#if DYNAMIC_EXECUTION |
/* FIXME: Do this with mprotect() */ |
struct dyn_page *dp; |
|
/* Since the locations 0x0-0xff are nearly always written to in an exception |
* handler, ignore any writes to these locations. If code ends up jumping |
* out there, we'll recompile when the jump actually happens. */ |
if((memaddr > 0x100) && (dp = find_dynd_page(memaddr)) && !dp->dirty) |
dirtyfy_page(dp); |
#endif |
} else { |
PRINTF("EXCEPTION: write out of memory (32-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
} |
} |
|
/* for cpu accesses */ |
inline void setsim_mem16(oraddr_t memaddr, uint16_t value) |
{ |
return(setsim_mem16_atomic(memaddr, value, 1)); |
} |
|
/* for simulator accesses, the ones that cpu wouldn't do */ |
inline void setsim_mem16_void(oraddr_t memaddr, uint16_t value) |
{ |
return(setsim_mem16_atomic(memaddr, value, 0)); |
} |
|
void setsim_mem16_atomic(oraddr_t memaddr, uint16_t value, int cpu_access) |
{ |
uint32_t temp; |
if (verify_memoryarea(memaddr)) { |
switch(cur_area->granularity) { |
case 1: |
cur_area->writefunc(memaddr, (value >> 8) & 0xFF, cur_area->priv_dat); |
cur_area->writefunc(memaddr + 1, value & 0xFF, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayw * 2; |
break; |
case 2: |
cur_area->writefunc(memaddr, value & 0xFFFF, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayw; |
break; |
case 4: |
temp = evalsim_mem32_void(memaddr & ~ADDR_C(3)); |
temp &= 0xffff << ((memaddr & 2) ? 16 : 0); |
temp |= (unsigned long)(value & 0xffff) << ((memaddr & 2) ? 0 : 16); |
setsim_mem32_atomic(memaddr & ~ADDR_C(3), temp, cpu_access); |
break; |
default: |
/* if you add new memory granularity be sure to check the formula |
* below for the read delay and fix it if necessery |
*/ |
PRINTF("unknown/unhandled memory granularuty\n"); |
exit(-1); |
} |
#if DYNAMIC_EXECUTION |
/* FIXME: Do this with mprotect() */ |
struct dyn_page *dp; |
|
/* Since the locations 0x0-0xff are nearly always written to in an exception |
* handler, ignore any writes to these locations. If code ends up jumping |
* out there, we'll recompile when the jump actually happens. */ |
|
if((memaddr > 0x100) && (dp = find_dynd_page(memaddr)) && !dp->dirty) |
dirtyfy_page(dp); |
#endif |
} else { |
PRINTF("EXCEPTION: write out of memory (16-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
} |
} |
|
/* for cpu accesses */ |
inline void setsim_mem8(oraddr_t memaddr, uint8_t value) |
{ |
return(setsim_mem8_atomic(memaddr, value, 1)); |
} |
|
/* for simulator accesses, the ones that cpu wouldn't do */ |
inline void setsim_mem8_void(oraddr_t memaddr, uint8_t value) |
{ |
return(setsim_mem8_atomic(memaddr, value, 0)); |
} |
|
void setsim_mem8_atomic(oraddr_t memaddr, uint8_t value, int cpu_access) |
{ |
uint32_t temp; |
if (verify_memoryarea(memaddr)) { |
switch (cur_area->granularity) { |
case 1: |
cur_area->writefunc(memaddr, value, cur_area->priv_dat); |
if (cpu_access) |
runtime.sim.mem_cycles += cur_area->delayw; |
break; |
case 2: |
temp = evalsim_mem16_void (memaddr & ~ADDR_C(1)); |
temp &= 0xff << ((memaddr & 1) ? 8 : 0); |
temp |= (unsigned short)(value & 0xff) << ((memaddr & 1) ? 0 : 8); |
setsim_mem16_atomic (memaddr & ~ADDR_C(1), temp, cpu_access); |
break; |
case 4: |
temp = evalsim_mem32_void (memaddr & ~ADDR_C(3)); |
temp &= ~(0xff << (8 * (3 - (memaddr & 3)))); |
temp |= (unsigned long)(value & 0xff) << (8 * (3 - (memaddr & 3))); |
setsim_mem32_atomic (memaddr & ~ADDR_C(3), temp, cpu_access); |
break; |
} |
#if DYNAMIC_EXECUTION |
/* FIXME: Do this with mprotect() */ |
struct dyn_page *dp; |
|
/* Since the locations 0x0-0xff are nearly always written to in an exception |
* handler, ignore any writes to these locations. If code ends up jumping |
* out there, we'll recompile when the jump actually happens. */ |
|
if((memaddr > 0x100) && (dp = find_dynd_page(memaddr)) && !dp->dirty) |
dirtyfy_page(dp); |
#endif |
} else { |
PRINTF("EXCEPTION: write out of memory (8-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, cur_vadd); |
} |
} |
|
/* Set mem, 32-bit. Big endian version. |
* |
* STATISTICS OK. (the only suspicious usage is in sim-cmd.c, |
* where this instruction is used for patching memory, |
* wether this is cpu or architectual access is yet to |
* be decided) |
*/ |
void set_mem32(oraddr_t memaddr, uint32_t value, int* breakpoint) |
{ |
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_32 | MPROF_WRITE); |
|
if (memaddr & 3) { |
except_handle (EXCEPT_ALIGN, memaddr); |
return; |
} |
|
cur_vadd = memaddr; |
memaddr = dmmu_translate(memaddr, 1);; |
/* If we produced exception don't set anything */ |
if (except_pending) |
return; |
|
if (config.debug.enabled) { |
*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr); /* 28/05/01 CZ */ |
*breakpoint += CheckDebugUnit(DebugStoreData,value); |
} |
|
dc_simulate_write(memaddr, value, 4); |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> write %08"PRIx32"\n", memaddr, |
value); |
} |
|
/* |
* STATISTICS NOT OK. |
*/ |
void set_direct32(oraddr_t memaddr, uint32_t value,int* breakpoint, |
int through_mmu, int through_dc) |
{ |
|
if (memaddr & 3) { |
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__); |
return; |
} |
|
cur_vadd = memaddr; |
|
if (through_mmu) { |
/* 0 - no write access, we do not want a DPF exception do we ;) |
*/ |
memaddr = peek_into_dtlb(memaddr, 1, through_dc); |
} |
|
|
/* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count, |
* and possibly also memory access times. |
*/ |
if (!through_dc) |
PRINTF("WARNING: statistics might not be OK\n"); |
dc_simulate_write(memaddr, value, 4); |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> DIRECT write %08"PRIx32"\n", |
memaddr, value); |
} |
|
|
/* Set mem, 16-bit. Big endian version. */ |
|
void set_mem16(oraddr_t memaddr, uint16_t value, int* breakpoint) |
{ |
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_16 | MPROF_WRITE); |
|
if (memaddr & 1) { |
except_handle (EXCEPT_ALIGN, memaddr); |
return; |
} |
|
cur_vadd = memaddr; |
memaddr = dmmu_translate(memaddr, 1);; |
/* If we produced exception don't set anything */ |
if (except_pending) |
return; |
|
if (config.debug.enabled) { |
*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr); /* 28/05/01 CZ */ |
*breakpoint += CheckDebugUnit(DebugStoreData,value); |
} |
|
dc_simulate_write(memaddr, value, 2); |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> write %04"PRIx16"\n", memaddr, |
value); |
} |
|
/* |
* STATISTICS NOT OK. |
*/ |
void set_direct16(oraddr_t memaddr, uint16_t value, int* breakpoint, |
int through_mmu, int through_dc) |
{ |
|
if (memaddr & 1) { |
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__); |
return; |
} |
|
cur_vadd = memaddr; |
|
if (through_mmu) { |
/* 0 - no write access, we do not want a DPF exception do we ;) |
*/ |
memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
} |
|
/* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count, |
* and possibly also memory access times. |
*/ |
if (!through_dc) |
PRINTF("WARNING: statistics might not be OK\n"); |
dc_simulate_write(memaddr, value, 2); |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> DIRECT write %04"PRIx16"\n", |
memaddr, value); |
} |
|
/* Set mem, 8-bit. */ |
|
void set_mem8(oraddr_t memaddr, uint8_t value, int* breakpoint) |
{ |
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_8 | MPROF_WRITE); |
|
cur_vadd = memaddr; |
memaddr = dmmu_translate(memaddr, 1);; |
/* If we produced exception don't set anything */ |
if (except_pending) return; |
|
if (config.debug.enabled) { |
*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr); /* 28/05/01 CZ */ |
*breakpoint += CheckDebugUnit(DebugStoreData,value); |
} |
|
dc_simulate_write(memaddr, value, 1); |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> write %02"PRIx8"\n", memaddr, |
value); |
} |
|
/* |
* STATISTICS NOT OK. |
*/ |
void set_direct8(oraddr_t memaddr, uint8_t value, int* breakpoint, |
int through_mmu, int through_dc) |
{ |
|
cur_vadd = memaddr; |
|
if (through_mmu) { |
/* 0 - no write access, we do not want a DPF exception do we ;) |
*/ |
memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
} |
|
/* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count, |
* and possibly also memory access times. |
*/ |
if (!through_dc) |
PRINTF("WARNING: statistics might not be OK\n"); |
dc_simulate_write(memaddr, value, 1); |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> DIRECT write %02"PRIx8"\n", |
memaddr, value); |
} |
|
|
void dumpmemory(oraddr_t from, oraddr_t to, int disasm, int nl) |
{ |
oraddr_t i, j; |
struct label_entry *tmp; |
int ilen = disasm ? 4 : 16; |
|
for(i = from; i < to; i += ilen) { |
PRINTF("%"PRIxADDR": ", i); |
for (j = 0; j < ilen;) { |
if (!disasm) { |
tmp = NULL; |
if (verify_memoryarea(i + j)) { |
struct label_entry *entry; |
entry = get_label(i + j); |
if (entry) |
PRINTF("(%s)", entry->name); |
PRINTF("%02"PRIx8" ", evalsim_mem8(i + j)); |
} else PRINTF("XX "); |
j++; |
} else { |
int breakpoint; |
uint32_t _insn = read_mem(i, &breakpoint); |
int index = insn_decode (_insn); |
int len = insn_len (index); |
|
tmp = NULL; |
if (verify_memoryarea(i + j)) { |
struct label_entry *entry; |
entry = get_label(i + j); |
if (entry) |
PRINTF("(%s)", entry->name); |
|
PRINTF(": %08"PRIx32" ", _insn); |
if (index >= 0) { |
disassemble_insn (_insn); |
PRINTF(" %s", disassembled); |
} else |
PRINTF("<invalid>"); |
} else PRINTF("XXXXXXXX"); |
j += len; |
} |
} |
if (nl) |
PRINTF ("\n"); |
} |
} |
|
uint32_t simmem_read_word(oraddr_t addr, void *priv_dat) { |
return *(uint32_t *)(priv_dat + (addr & cur_area->size_mask)); |
} |
|
void simmem_write_word(oraddr_t addr, uint32_t value, void *priv_dat) { |
*(uint32_t *)(priv_dat + (addr & cur_area->size_mask)) = value; |
} |
|
uint32_t simmem_read_zero(oraddr_t addr, void *dat) { |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: memory read from non-read memory area 0x%" |
PRIxADDR".\n", addr); |
return 0; |
} |
|
void simmem_write_null(oraddr_t addr, uint32_t value, void *dat) { |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: memory write to 0x%"PRIxADDR", non-write memory area (value 0x%08"PRIx32").\n", addr, value); |
} |
|
/* Initialize memory table from a config struct */ |
|
void init_memory_table () |
{ |
/* If nothing was defined, use default memory block */ |
if (config.memory.nmemories) { |
int i; |
for (i = 0; i < config.memory.nmemories; i++) { |
oraddr_t start = config.memory.table[i].baseaddr; |
uint32_t length = config.memory.table[i].size; |
char *type = config.memory.table[i].name; |
int rd = config.memory.table[i].delayr; |
int wd = config.memory.table[i].delayw; |
int ce = config.memory.table[i].ce; |
void *mem = malloc (length); |
|
if (config.sim.verbose) |
debug (1, "%"PRIxADDR" %08"PRIx32" (%"PRIi32" KB): %s (activated by CE%i; read delay = %icyc, write delay = %icyc)\n", |
start, length, length >> 10, type, ce, rd, wd); |
|
if (!mem) { |
fprintf (stderr, "Failed to allocate sim memory. Aborting\n"); |
exit (-1); |
} |
|
register_memoryarea(start, length, 4, 0, &simmem_read_word, |
&simmem_write_word, mem); |
cur_area->chip_select = ce; |
cur_area->valid = 1; |
cur_area->delayw = wd; |
cur_area->delayr = rd; |
if (config.memory.table[i].log[0] != '\0') { |
if ((cur_area->log = fopen (config.memory.table[i].log, "wt+")) == NULL) |
fprintf (stderr, "WARNING: Cannot open '%s'.\n", |
config.memory.table[i].log); |
} else |
cur_area->log = NULL; |
} |
PRINTF ("\n"); |
} else { |
void *mem = malloc (DEFAULT_MEMORY_LEN); |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: Memory not defined, assuming standard configuration.\n"); |
|
if (!mem) { |
fprintf (stderr, "Failed to allocate sim memory. Aborting\n"); |
exit (-1); |
} |
|
register_memoryarea(DEFAULT_MEMORY_START, DEFAULT_MEMORY_LEN, 4, 0, |
&simmem_read_word, &simmem_write_word, mem); |
cur_area->chip_select = 0; |
cur_area->valid = 1; |
cur_area->delayw = 1; |
cur_area->delayr = 1; |
cur_area->log = NULL; |
} |
} |
|
/* Changes read/write memory in read/write only */ |
|
void lock_memory_table () |
{ |
struct dev_memarea *ptmp; |
|
/* Check list of registered devices. */ |
for(ptmp = dev_list; ptmp; ptmp = ptmp->next) { |
if (ptmp->delayr < 0 && ptmp->readfunc == &simmem_read_word) |
ptmp->readfunc = &simmem_read_zero; |
if (ptmp->delayw < 0 && ptmp->writefunc == &simmem_write_word) |
ptmp->writefunc = &simmem_write_null; |
|
/* If this mem area is not for memory chip under MC control |
then this area is valid all the time */ |
if (ptmp->readfunc != &simmem_read_word) { |
ptmp->valid = 1; |
ptmp->chip_select = -1; |
} |
} |
} |
|
/* Closes files, etc. */ |
|
void done_memory_table () |
{ |
struct dev_memarea *ptmp; |
|
/* Check list of registered devices. */ |
for(ptmp = dev_list; ptmp; ptmp = ptmp->next) { |
if (ptmp->log) |
fclose (ptmp->log); |
} |
} |
|
/* Displays current memory configuration */ |
|
void memory_table_status () |
{ |
struct dev_memarea *ptmp; |
|
/* Check list of registered devices. */ |
for(ptmp = dev_list; ptmp; ptmp = ptmp->next) { |
PRINTF ("addr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR", size %"PRIx32 |
", gran %iB\n", |
ptmp->addr_mask, ptmp->addr_compare, ptmp->addr_compare | bit_mask (ptmp->size), |
ptmp->size, ptmp->granularity); |
PRINTF ("\t"); |
if (ptmp->delayr >= 0) |
PRINTF ("read delay = %i cycles, ", ptmp->delayr); |
else |
PRINTF ("reads not possible, "); |
|
if (ptmp->delayw >= 0) |
PRINTF ("write delay = %i cycles", ptmp->delayw); |
else |
PRINTF ("writes not possible"); |
|
if (ptmp->log) |
PRINTF (", (logged)\n"); |
else |
PRINTF ("\n"); |
} |
} |
|
/* Outputs time in pretty form to dest string */ |
|
char *generate_time_pretty (char *dest, long time_ps) |
{ |
int exp3 = 0; |
if (time_ps) { |
while ((time_ps % 1000) == 0) { |
time_ps /= 1000; |
exp3++; |
} |
} |
sprintf (dest, "%li%cs", time_ps, "pnum"[exp3]); |
return dest; |
} |
/execute.h
0,0 → 1,93
/* execute.h -- Header file for architecture dependent execute.c |
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program 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. |
|
This program 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 this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#if DYNAMIC_EXECUTION |
#include "dyn_rec.h" |
#endif |
|
struct cpu_state { |
/* General purpose registers. */ |
uorreg_t reg[MAX_GPRS]; |
|
/* Sprs */ |
uorreg_t sprs[MAX_SPRS]; |
|
/* Effective address of instructions that have an effective address. This is |
* only used to get dump_exe_log correct */ |
oraddr_t insn_ea; |
|
/* Is current instruction in execution in a delay slot? */ |
int delay_insn; |
|
/* Program counter (and translated PC) */ |
oraddr_t pc; |
|
/* Delay instruction effective address register */ |
oraddr_t pc_delay; |
|
/* Decoding of the just executed instruction. Only used in analysis(). */ |
struct iqueue_entry iqueue; |
|
/* decoding of the instruction that was executed before this one. Only used |
* in analysis(). */ |
struct iqueue_entry icomplet; |
|
#if DYNAMIC_EXECUTION |
/* Current page in execution */ |
struct dyn_page *curr_page; |
|
/* Linked list of recompiled pages with their status */ |
struct dyn_page *dyn_pages; |
|
/* Micro operation queue. Only used to speed up recompile_page */ |
struct op_queue *opqs; |
|
/* Cross references that reference the jumps from the infinite loop |
* instruction (l.j 0) */ |
struct x_ref *inf_xrefs; |
|
/* rfe cross-reference cache */ |
struct x_ref **rfe_held_xrefs; |
unsigned int rfe_held_xref_pos; |
|
/* Set if all temporaries are stored */ |
int ts_current; |
|
/* The contents of the temporaries. Only used in except_handle */ |
uorreg_t t0; |
uorreg_t t1; |
uorreg_t t2; |
#endif |
}; |
|
extern struct cpu_state cpu_state; |
|
#define CURINSN(INSN) (strcmp(cur->insn, (INSN)) == 0) |
|
/*extern machword eval_operand(char *srcoperand,int* breakpoint); |
extern void set_operand(char *dstoperand, unsigned long value,int* breakpoint);*/ |
void dumpreg(); |
inline void dump_exe_log(); |
inline int cpu_clock (); |
void cpu_reset (); |
uorreg_t evalsim_reg(unsigned int regno); |
void setsim_reg(unsigned int regno, uorreg_t value); |
|
extern oraddr_t pcnext; |
int depend_operands(struct iqueue_entry *prev, struct iqueue_entry *next); |
/abstract.h
0,0 → 1,174
/* abstract.c -- Abstract entities header file |
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program 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. |
|
This program 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 this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#include <stdio.h> |
|
#define DEFAULT_MEMORY_START 0 |
#define DEFAULT_MEMORY_LEN 0x800000 |
#define STACK_SIZE 20 |
#define LABELNAME_LEN 50 |
#define INSNAME_LEN 15 |
#define OPERANDNAME_LEN 50 |
|
#define MAX_OPERANDS (5) |
|
#define OP_MEM_ACCESS 0x80000000 |
|
/* Cache tag types. */ |
#define CT_NONE 0 |
#define CT_VIRTUAL 1 |
#define CT_PHYSICAL 2 |
|
/* Instruction queue */ |
struct iqueue_entry { |
int insn_index; |
uint32_t insn; |
oraddr_t insn_addr; |
}; |
|
/* Memory regions assigned to devices */ |
struct dev_memarea { |
struct dev_memarea *next; |
/*unsigned long start; |
unsigned long end;*/ /* if start + size > end, this block is disabled; to enable it recalculate end addr. */ |
oraddr_t addr_mask; |
oraddr_t addr_compare; |
uint32_t size; |
uint32_t size_mask; /* Address mask, calculated out of size */ |
unsigned int granularity; /* how many bytes read/write accepts: 1/2/4 */ |
int delayr; /* Read delay */ |
int delayw; /* Write delay */ |
|
int chip_select; /* Needed by memory controller; specifies chip |
* select number for this memory area. */ |
int valid; /* This bit reflect the memory controler valid bit */ |
FILE *log; /* log file if this device is to be logged, NULL otherwise */ |
|
uint32_t (*readfunc)(oraddr_t, void *); |
void (*writefunc)(oraddr_t, uint32_t, void *); |
/* private data */ |
void *priv_dat; |
}; |
|
extern void dumpmemory(oraddr_t from, oraddr_t to, int disasm, int nl); |
extern uint32_t eval_mem32(oraddr_t memaddr,int*); |
extern uint16_t eval_mem16(oraddr_t memaddr,int*); |
extern uint8_t eval_mem8(oraddr_t memaddr,int*); |
void set_mem32(oraddr_t memaddr, uint32_t value,int*); |
extern void set_mem16(oraddr_t memaddr, uint16_t value,int*); |
extern void set_mem8(oraddr_t memaddr, uint8_t value,int*); |
|
uint32_t evalsim_mem32(oraddr_t); |
uint16_t evalsim_mem16(oraddr_t); |
uint8_t evalsim_mem8(oraddr_t); |
|
uint32_t evalsim_mem32_atomic(oraddr_t, int); |
uint16_t evalsim_mem16_atomic(oraddr_t, int); |
uint8_t evalsim_mem8_atomic(oraddr_t, int); |
|
void setsim_mem32(oraddr_t, uint32_t); |
void setsim_mem16(oraddr_t, uint16_t); |
void setsim_mem8(oraddr_t, uint8_t); |
|
void setsim_mem32_atomic(oraddr_t, uint32_t, int); |
void setsim_mem16_atomic(oraddr_t, uint16_t, int); |
void setsim_mem8_atomic(oraddr_t, uint8_t, int); |
|
void init_memory_table (); |
|
/* Changes read/write memory in read/write only */ |
void lock_memory_table (); |
|
/* Closes files, etc. */ |
void done_memory_table (); |
|
/* Displays current memory configuration */ |
void memory_table_status (); |
|
/* Register read and write function for a memory area. |
addr is inside the area, if addr & addr_mask == addr_compare |
(used also by peripheral devices like 16450 UART etc.) */ |
void register_memoryarea_mask(oraddr_t addr_mask, oraddr_t addr_compare, |
uint32_t size, unsigned granularity, unsigned mc_dev, |
uint32_t (readfunc)(oraddr_t, void *), |
void (writefunc)(oraddr_t, uint32_t, void *), |
void *dat); |
|
/* Register read and write function for a memory area. |
Memory areas should be aligned. Memory area is rounded up to |
fit the nearest 2^n aligment. |
(used also by peripheral devices like 16450 UART etc.) |
If mc_dev is 1, this means that this device will be checked first for match |
and will be accessed in case in overlaping memory spaces. |
Only one device can have this set to 1 (used for memory controller) */ |
void register_memoryarea(oraddr_t addr, uint32_t size, unsigned granularity, |
unsigned mc_dev, uint32_t (readfunc)(oraddr_t, void *), |
void (writefunc)(oraddr_t, uint32_t, void *), |
void *dat); |
|
/* Finds the memory area for the address and adjust the read and write delays for it. */ |
void adjust_rw_delay(oraddr_t memaddr, unsigned int delayr, unsigned int delayw); |
|
/* Check if access is to registered area of memory. */ |
struct dev_memarea *verify_memoryarea(oraddr_t addr); |
|
/* Outputs time in pretty form to dest string. */ |
char *generate_time_pretty (char *dest, long time_ps); |
|
/* Returns 32-bit values from mem array. */ |
uint32_t eval_insn(oraddr_t, int *); |
|
uint32_t eval_insn_direct(oraddr_t memaddr, int* breakpoint, int through_mmu); |
|
uint8_t eval_direct8(oraddr_t memaddr, int *breakpoint, int through_mmu, int through_dc); |
uint16_t eval_direct16(oraddr_t memaddr, int *breakpoint, int through_mmu, int through_dc); |
uint32_t eval_direct32(oraddr_t addr, int *breakpoint, int through_mmu, int through_dc); |
|
void set_direct32(uint32_t addr, uint32_t value, int *breakpoint, int through_mmu, int through_dc); |
|
/* Temporary variable to increase speed. */ |
extern struct dev_memarea *cur_area; |
|
/* Virtual address of current access. */ |
extern oraddr_t cur_vadd; |
|
/* These are set by mmu if cache inhibit bit is set for current acces. */ |
extern int data_ci, insn_ci; |
|
/* Added by MM */ |
#ifndef LONGEST |
#define LONGEST long long |
#define ULONGEST unsigned long long |
#endif /* ! LONGEST */ |
|
/* Instructions left to execute */ |
extern int cont_run; |
|
/* Returns the page that addr belongs to */ |
#define ADDR_PAGE(addr) ((addr) & ~(ADDR_C(PAGE_SIZE) - 1)) |
|
/* History of execution */ |
#define HISTEXEC_LEN 200 |
struct hist_exec { |
oraddr_t addr; |
struct hist_exec *prev; |
struct hist_exec *next; |
}; |
|
extern struct hist_exec *hist_exec_tail; |
/trace.c
0,0 → 1,54
/* trace.c -- Simulator breakpoints |
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program 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. |
|
This program 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 this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#include <stdio.h> |
|
#include "config.h" |
|
#ifdef HAVE_INTTYPES_H |
#include <inttypes.h> |
#endif |
|
#include "port.h" |
#include "arch.h" |
#include "abstract.h" |
#include "labels.h" |
#include "sim-config.h" |
#include "trace.h" |
|
/* Set instruction execution breakpoint. */ |
|
void set_insnbrkpoint(oraddr_t addr) |
{ |
addr &= ~ADDR_C(3); /* 32-bit aligned */ |
|
if (!verify_memoryarea(addr)) |
PRINTF("WARNING: This breakpoint is out of the simulated memory range.\n"); |
|
if (has_breakpoint (addr)) { |
remove_breakpoint (addr); |
PRINTF("\nBreakpoint at 0x%"PRIxADDR" cleared.\n", addr); |
} else { |
add_breakpoint (addr); |
PRINTF("\nBreakpoint at 0x%"PRIxADDR" set.\n", addr); |
} |
|
return; |
} |
|
/stats.c
0,0 → 1,293
/* stats.c -- Various statistics about instruction scheduling etc. |
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program 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. |
|
This program 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 this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#include <stdio.h> |
#include <ctype.h> |
#include <string.h> |
|
#include "config.h" |
|
#ifdef HAVE_INTTYPES_H |
#include <inttypes.h> |
#endif |
|
#include "port.h" |
#include "arch.h" |
#include "abstract.h" |
#include "sim-config.h" |
#include "spr_defs.h" |
#include "opcode/or32.h" |
#include "execute.h" |
#include "sprs.h" |
#include "debug.h" |
#include "stats.h" |
|
struct branchstat { |
int taken; |
int nottaken; |
int forward; |
int backward; |
}; |
|
/* See also enum insn_type in abstract.h */ |
const char func_unit_str[30][30] = { "unknown", "exception", "arith", "shift", "compare", |
"branch", "jump", "load", "store", "movimm", "move", "extend", "nop", "mac" }; |
|
struct dstats_entry dstats[DSTATS_LEN]; /* dependency stats */ |
struct sstats_entry sstats[SSTATS_LEN]; /* single stats */ |
struct fstats_entry fstats[FSTATS_LEN]; /* functional units stats */ |
struct mstats_entry or1k_mstats = {0}; /* misc units stats */ |
struct cachestats_entry ic_stats = {0}; /* instruction cache stats */ |
struct cachestats_entry dc_stats = {0}; /* data cache stats */ |
struct immustats_entry immu_stats = {0}; /* insn mmu stats */ |
struct dmmustats_entry dmmu_stats = {0}; /* data mmu stats */ |
struct raw_stats raw_stats = {0}; /* RAW hazard stats */ |
|
void addsstats(int item, int cnt_dynamic) |
{ |
int i = 0; |
|
while(sstats[i].insn != item && sstats[i].insn >= 0 && i < SSTATS_LEN) i++; |
|
if (i >= SSTATS_LEN - 1) return; |
|
if (sstats[i].insn >= 0) { |
sstats[i].cnt_dynamic += cnt_dynamic; |
} else { |
sstats[i].insn = item; |
sstats[i].cnt_dynamic = cnt_dynamic; |
} |
} |
|
void adddstats(int item1, int item2, int cnt_dynamic, int depend) |
{ |
int i = 0; |
|
debug(7,"adddstats start\n"); |
|
while((dstats[i].insn1 != item1 || dstats[i].insn2 != item2) && (i < DSTATS_LEN) && dstats[i].insn1 >= 0) i++; |
|
if (i >= DSTATS_LEN - 1) return; |
|
if (dstats[i].insn1 >= 0) { |
dstats[i].cnt_dynamic += cnt_dynamic; |
dstats[i].depend += depend; |
} else { |
dstats[i].insn1 = item1; |
dstats[i].insn2 = item2; |
dstats[i].cnt_dynamic = cnt_dynamic; |
dstats[i].depend = depend; |
} |
} |
|
void addfstats(enum insn_type item1, enum insn_type item2, int cnt_dynamic, int depend) |
{ |
int i = 0; |
|
while(((fstats[i].insn1 != item1) || (fstats[i].insn2 != item2)) && |
(fstats[i].insn1 != it_unknown) && |
(i < FSTATS_LEN)) |
i++; |
|
if (i >= FSTATS_LEN - 1) return; |
|
if ((fstats[i].insn1 == item1) && |
(fstats[i].insn2 == item2)) { |
fstats[i].cnt_dynamic += cnt_dynamic; |
fstats[i].depend += depend; |
} |
else { |
fstats[i].insn1 = item1; |
fstats[i].insn2 = item2; |
fstats[i].cnt_dynamic = cnt_dynamic; |
fstats[i].depend = depend; |
} |
} |
|
void initstats() |
{ |
int i; |
memset(sstats, 0, sizeof(sstats)); |
for (i = 0; i < SSTATS_LEN; i++) |
sstats[i].insn = -1; |
memset(dstats, 0, sizeof(dstats)); |
for (i = 0; i < DSTATS_LEN; i++) |
dstats[i].insn1 = dstats[i].insn2 = -1; |
memset(fstats, 0, sizeof(fstats)); |
memset(&or1k_mstats, 0, sizeof(or1k_mstats)); |
memset(&ic_stats, 0, sizeof(ic_stats)); |
memset(&dc_stats, 0, sizeof(dc_stats)); |
memset(&raw_stats, 0, sizeof(raw_stats)); |
} |
|
void printotherstats(int which) |
{ |
PRINTF ("\n"); |
if (config.bpb.enabled) { |
struct branchstat bf; |
struct branchstat bnf; |
long bf_all, bnf_all; |
bf.taken = or1k_mstats.bf[1][0] + or1k_mstats.bf[1][1]; |
bf.nottaken = or1k_mstats.bf[0][0] + or1k_mstats.bf[0][1]; |
bf.forward = or1k_mstats.bf[0][1] + or1k_mstats.bf[1][1]; |
bf.backward = or1k_mstats.bf[0][0] + or1k_mstats.bf[1][0]; |
bf_all = bf.forward + bf.backward; |
|
bnf.taken = or1k_mstats.bnf[1][0] + or1k_mstats.bf[1][1]; |
bnf.nottaken = or1k_mstats.bnf[0][0] + or1k_mstats.bf[0][1]; |
bnf.forward = or1k_mstats.bnf[0][1] + or1k_mstats.bf[1][1]; |
bnf.backward = or1k_mstats.bnf[0][0] + or1k_mstats.bf[1][0]; |
bnf_all = bnf.forward + bnf.backward; |
|
PRINTF("bnf: %d (%ld%%) taken,", bf.taken, (bf.taken * 100) / SD(bf_all)); |
PRINTF(" %d (%ld%%) not taken,", bf.nottaken, (bf.nottaken * 100) / SD(bf_all)); |
PRINTF(" %d (%ld%%) forward,", bf.forward, (bf.forward * 100) / SD(bf_all)); |
PRINTF(" %d (%ld%%) backward\n", bf.backward, (bf.backward * 100) / SD(bf_all)); |
PRINTF("bf: %d (%ld%%) taken,", bnf.taken, (bnf.taken * 100) / SD(bnf_all)); |
PRINTF(" %d (%ld%%) not taken,", bnf.nottaken, (bnf.nottaken * 100) / SD(bnf_all)); |
PRINTF(" %d (%ld%%) forward,", bnf.forward, (bnf.forward * 100) / SD(bnf_all)); |
PRINTF(" %d (%ld%%) backward\n", bnf.backward, (bnf.backward * 100) / SD(bnf_all)); |
|
PRINTF("StaticBP bnf(%s): correct %ld%%\n", config.bpb.sbp_bnf_fwd ? "forward" : "backward", |
(or1k_mstats.bnf[0][config.bpb.sbp_bnf_fwd] * 100) / SD(bnf_all)); |
PRINTF("StaticBP bf(%s): correct %ld%%\n", config.bpb.sbp_bf_fwd ? "forward" : "backward", |
(or1k_mstats.bnf[1][config.bpb.sbp_bf_fwd] * 100) / SD(bf_all)); |
PRINTF("BPB: hit %d (correct %d%%), miss %d\n", or1k_mstats.bpb.hit, (or1k_mstats.bpb.correct * 100) / SD(or1k_mstats.bpb.hit), or1k_mstats.bpb.miss); |
} else |
PRINTF("BPB simulation disabled. Enable it to see BPB analysis\n"); |
|
if (config.bpb.btic) { |
PRINTF("BTIC: hit %d(%d%%), miss %d\n", or1k_mstats.btic.hit, (or1k_mstats.btic.hit * 100) / SD(or1k_mstats.btic.hit + or1k_mstats.btic.miss), or1k_mstats.btic.miss); |
} else |
PRINTF("BTIC simulation disabled. Enabled it to see BTIC analysis\n"); |
|
if (config.ic.enabled) { |
PRINTF("IC read: hit %d(%d%%), miss %d\n", ic_stats.readhit, (ic_stats.readhit * 100) / SD(ic_stats.readhit + ic_stats.readmiss), ic_stats.readmiss); |
} else |
PRINTF("No ICache. Enable it to see IC results.\n"); |
|
if (config.dc.enabled) { |
PRINTF("DC read: hit %d(%d%%), miss %d\n", dc_stats.readhit, (dc_stats.readhit * 100) / SD(dc_stats.readhit + dc_stats.readmiss), dc_stats.readmiss); |
PRINTF("DC write: hit %d(%d%%), miss %d\n", dc_stats.writehit, (dc_stats.writehit * 100) / SD(dc_stats.writehit + dc_stats.writemiss), dc_stats.writemiss); |
} else |
PRINTF("No DCache. Enable it to see DC results.\n"); |
|
if (testsprbits(SPR_UPR, SPR_UPR_IMP)) { |
PRINTF("IMMU read: hit %d(%d%%), miss %d\n", immu_stats.fetch_tlbhit, (immu_stats.fetch_tlbhit * 100) / SD(immu_stats.fetch_tlbhit + immu_stats.fetch_tlbmiss), immu_stats.fetch_tlbmiss); |
} else |
PRINTF("No IMMU. Set UPR[IMP]\n"); |
|
if (testsprbits(SPR_UPR, SPR_UPR_DMP)) { |
PRINTF("DMMU read: hit %d(%d%%), miss %d\n", dmmu_stats.loads_tlbhit, (dmmu_stats.loads_tlbhit * 100) / SD(dmmu_stats.loads_tlbhit + dmmu_stats.loads_tlbmiss), dmmu_stats.loads_tlbmiss); |
} else |
PRINTF("No DMMU. Set UPR[DMP]\n"); |
|
PRINTF("Additional LOAD CYCLES: %u STORE CYCLES: %u\n", runtime.sim.loadcycles, runtime.sim.storecycles); |
} |
|
void printstats(int which) |
{ |
int i, all = 0, dependall = 0; |
|
if (which > 1 && which <= 5 && !config.cpu.dependstats) { |
PRINTF("Hazard analysis disabled. Enable it to see analysis results.\n"); |
return; |
} |
|
switch (which) { |
case 1: |
PRINTF("stats 1: Misc stats\n"); |
printotherstats(which); |
break; |
case 2: |
PRINTF ("stats 2: Instruction usage\n"); |
for(i = 0; i < SSTATS_LEN; i++) |
all += sstats[i].cnt_dynamic; |
|
for(i = 0; i < SSTATS_LEN; i++) |
if (sstats[i].cnt_dynamic) |
PRINTF(" %-15s used %6dx (%5.1f%%)\n", insn_name(sstats[i].insn), sstats[i].cnt_dynamic, (sstats[i].cnt_dynamic * 100.)/SD(all)); |
|
PRINTF("%d instructions (dynamic, single stats)\n", all); |
break; |
|
case 3: |
PRINTF ("stats 3: Instruction dependencies\n"); |
for(i = 0; i < DSTATS_LEN; i++) { |
all += dstats[i].cnt_dynamic; |
dependall += dstats[i].depend; |
} |
|
for(i = 0; i < DSTATS_LEN; i++) |
if (dstats[i].cnt_dynamic) { |
char temp[100]; |
sprintf(temp, "%s, %s ", insn_name(dstats[i].insn1), insn_name(dstats[i].insn2)); |
PRINTF(" %-30s %6dx (%5.1f%%)", temp, dstats[i].cnt_dynamic, (dstats[i].cnt_dynamic * 100.)/SD(all)); |
PRINTF(" depend: %5.1f%%\n", (dstats[i].depend * 100.) / dstats[i].cnt_dynamic); |
} |
|
PRINTF("%d instructions (dynamic, dependency stats) depend: %d%%\n", all, (dependall * 100) / SD(all)); |
break; |
|
case 4: |
PRINTF("stats 4: Functional units dependencies\n"); |
for(i = 0; i < FSTATS_LEN; i++) { |
all += fstats[i].cnt_dynamic; |
dependall += fstats[i].depend; |
} |
|
for(i = 0; i < FSTATS_LEN; i++) |
if (fstats[i].cnt_dynamic) { |
char temp[100]; |
sprintf(temp, "%s, %s", func_unit_str[fstats[i].insn1], func_unit_str[fstats[i].insn2]); |
PRINTF(" %-30s %6dx (%5.1f%%)", temp, fstats[i].cnt_dynamic, (fstats[i].cnt_dynamic * 100.)/SD(all)); |
PRINTF(" depend: %5.1f%%\n", (fstats[i].depend * 100.) / fstats[i].cnt_dynamic); |
} |
PRINTF ("%d instructions (dynamic, functional units stats) depend: %d%%\n\n", all, (dependall * 100) / SD(all)); |
break; |
|
case 5: |
PRINTF("stats 5: Raw register usage over time\n"); |
#if RAW_RANGE_STATS |
for(i = 0; (i < MAX_RANGE); i++) |
PRINTF(" Register set and reused in %d. cycle: %d cases\n", i, raw_stats.range[i]); |
#endif |
break; |
case 6: |
if (config.cpu.sbuf_len) { |
extern int sbuf_total_cyc, sbuf_wait_cyc; |
PRINTF ("stats 6: Store buffer analysis\n"); |
PRINTF ("Using store buffer of length %i.\n", config.cpu.sbuf_len); |
PRINTF ("Number of total memory store cycles: %i/%lli\n", sbuf_total_cyc, |
runtime.sim.cycles + sbuf_total_cyc - sbuf_wait_cyc); |
PRINTF ("Number of cycles waiting for memory stores: %i\n", sbuf_wait_cyc); |
PRINTF ("Number of memory cycles spared: %i\n", sbuf_total_cyc - sbuf_wait_cyc); |
PRINTF ("Store speedup %3.2f%%, total speedup %3.2f%%\n", 100.*(sbuf_total_cyc - sbuf_wait_cyc)/sbuf_total_cyc, |
100.*(sbuf_total_cyc - sbuf_wait_cyc) / (runtime.sim.cycles + sbuf_total_cyc - sbuf_wait_cyc)); |
} else |
PRINTF ("Store buffer analysis disabled. Enable it to see analysis results.\n"); |
break; |
default: |
PRINTF ("Please specify a stats group (1-6).\n"); |
break; |
} |
#if 0 |
PRINTF("Byte ADD: %d instructions\n", or1k_mstats.byteadd); |
#endif |
} |
/stats.h
0,0 → 1,109
/* stats.h -- Header file for stats.c |
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program 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. |
|
This program 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 this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#define DSTATS_LEN 3000 |
#define SSTATS_LEN 300 |
#define FSTATS_LEN 200 |
#define RAW_RANGE 1000 |
|
/* Used by safe division - increment divisor by one if it is zero */ |
#define SD(X) (X != 0 ? X : 1) |
|
struct dstats_entry { |
int insn1; |
int insn2; |
int cnt_dynamic; |
int depend; |
}; |
|
struct sstats_entry { |
int insn; |
int cnt_dynamic; |
}; /* single stats */ |
|
struct fstats_entry { |
enum insn_type insn1; |
enum insn_type insn2; |
int cnt_dynamic; |
int depend; |
}; /* functional units stats */ |
|
struct bpbstat { |
int hit; |
int miss; |
int correct; |
int incorrect; |
}; |
|
struct bticstat { |
int hit; |
int miss; |
}; |
|
struct mstats_entry { |
int byteadd; |
int bf[2][2]; /* [taken][fwd/bwd] */ |
int bnf[2][2]; /* [taken][fwd/bwd] */ |
struct bpbstat bpb; |
struct bticstat btic; |
}; /* misc units stats */ |
|
struct cachestats_entry { |
int readhit; |
int readmiss; |
int writehit; |
int writemiss; |
}; /* cache stats */ |
|
struct immustats_entry { |
int fetch_tlbhit; |
int fetch_tlbmiss; |
int fetch_pagefaults; |
}; /* IMMU stats */ |
|
struct dmmustats_entry { |
int loads_tlbhit; |
int loads_tlbmiss; |
int loads_pagefaults; |
int stores_tlbhit; |
int stores_tlbmiss; |
int stores_pagefaults; |
}; /* DMMU stats */ |
|
struct raw_stats { |
int reg[64]; |
int range[RAW_RANGE]; |
}; /* RAW hazard stats */ |
|
/* Renamed mstats to or1k_mstats because Mac OS X has a lib function called mstats */ |
extern struct mstats_entry or1k_mstats; |
extern struct sstats_entry sstats[SSTATS_LEN]; |
extern struct dstats_entry dstats[DSTATS_LEN]; |
extern struct fstats_entry fstats[FSTATS_LEN]; |
extern struct cachestats_entry ic_stats; |
extern struct cachestats_entry dc_stats; |
extern struct immustats_entry immu_stats; |
extern struct dmmustats_entry dmmu_stats; |
extern struct raw_stats raw_stats; |
|
extern void addsstats(int item, int cnt_dynamic); |
extern void adddstats(int item1, int item2, int cnt_dynamic, int depend); |
extern void addfstats(enum insn_type item1, enum insn_type item2, int cnt_dynamic, int depend); |
extern void initstats(); |
extern void printstats(); |
/Makefile.in
0,0 → 1,338
# Makefile.in generated by automake 1.6.3 from Makefile.am. |
# @configure_input@ |
|
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 |
# Free Software Foundation, Inc. |
# This Makefile.in is free software; the Free Software Foundation |
# gives unlimited permission to copy and/or distribute it, |
# with or without modifications, as long as this notice is preserved. |
|
# This program is distributed in the hope that it will be useful, |
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without |
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
# PARTICULAR PURPOSE. |
|
@SET_MAKE@ |
|
# Makefile -- Makefile for cpu architecture independent simulation |
# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
# |
# This file is part of OpenRISC 1000 Architectural Simulator. |
# |
# This program 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. |
# |
# This program 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 this program; if not, write to the Free Software |
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
# |
SHELL = @SHELL@ |
|
srcdir = @srcdir@ |
top_srcdir = @top_srcdir@ |
VPATH = @srcdir@ |
prefix = @prefix@ |
exec_prefix = @exec_prefix@ |
|
bindir = @bindir@ |
sbindir = @sbindir@ |
libexecdir = @libexecdir@ |
datadir = @datadir@ |
sysconfdir = @sysconfdir@ |
sharedstatedir = @sharedstatedir@ |
localstatedir = @localstatedir@ |
libdir = @libdir@ |
infodir = @infodir@ |
mandir = @mandir@ |
includedir = @includedir@ |
oldincludedir = /usr/include |
pkgdatadir = $(datadir)/@PACKAGE@ |
pkglibdir = $(libdir)/@PACKAGE@ |
pkgincludedir = $(includedir)/@PACKAGE@ |
top_builddir = ../.. |
|
ACLOCAL = @ACLOCAL@ |
AUTOCONF = @AUTOCONF@ |
AUTOMAKE = @AUTOMAKE@ |
AUTOHEADER = @AUTOHEADER@ |
|
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd |
INSTALL = @INSTALL@ |
INSTALL_PROGRAM = @INSTALL_PROGRAM@ |
INSTALL_DATA = @INSTALL_DATA@ |
install_sh_DATA = $(install_sh) -c -m 644 |
install_sh_PROGRAM = $(install_sh) -c |
install_sh_SCRIPT = $(install_sh) -c |
INSTALL_SCRIPT = @INSTALL_SCRIPT@ |
INSTALL_HEADER = $(INSTALL_DATA) |
transform = @program_transform_name@ |
NORMAL_INSTALL = : |
PRE_INSTALL = : |
POST_INSTALL = : |
NORMAL_UNINSTALL = : |
PRE_UNINSTALL = : |
POST_UNINSTALL = : |
build_alias = @build_alias@ |
build_triplet = @build@ |
host_alias = @host_alias@ |
host_triplet = @host@ |
target_alias = @target_alias@ |
target_triplet = @target@ |
|
EXEEXT = @EXEEXT@ |
OBJEXT = @OBJEXT@ |
PATH_SEPARATOR = @PATH_SEPARATOR@ |
AMTAR = @AMTAR@ |
AR = @AR@ |
ARFLAGS = @ARFLAGS@ |
AWK = @AWK@ |
BUILD_DIR = @BUILD_DIR@ |
CC = @CC@ |
CFLAGS = @CFLAGS@ |
CPU_ARCH = @CPU_ARCH@ |
DEPDIR = @DEPDIR@ |
INCLUDES = @INCLUDES@ |
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ |
LOCAL_CFLAGS = @LOCAL_CFLAGS@ |
LOCAL_DEFS = @LOCAL_DEFS@ |
MAKE_SHELL = @MAKE_SHELL@ |
PACKAGE = @PACKAGE@ |
RANLIB = @RANLIB@ |
STRIP = @STRIP@ |
SUMVERSION = @SUMVERSION@ |
TERMCAP_LIB = @TERMCAP_LIB@ |
VERSION = @VERSION@ |
am__include = @am__include@ |
am__quote = @am__quote@ |
host = @host@ |
host_cpu = @host_cpu@ |
host_os = @host_os@ |
install_sh = @install_sh@ |
|
noinst_LIBRARIES = libcommon.a |
libcommon_a_SOURCES = abstract.c parse.c stats.c trace.c labels.c |
subdir = cpu/common |
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs |
CONFIG_HEADER = $(top_builddir)/config.h |
CONFIG_CLEAN_FILES = |
LIBRARIES = $(noinst_LIBRARIES) |
|
libcommon_a_AR = $(AR) cru |
libcommon_a_LIBADD = |
am_libcommon_a_OBJECTS = abstract.$(OBJEXT) parse.$(OBJEXT) \ |
stats.$(OBJEXT) trace.$(OBJEXT) labels.$(OBJEXT) |
libcommon_a_OBJECTS = $(am_libcommon_a_OBJECTS) |
|
DEFS = @DEFS@ |
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) |
CPPFLAGS = @CPPFLAGS@ |
LDFLAGS = @LDFLAGS@ |
LIBS = @LIBS@ |
depcomp = $(SHELL) $(top_srcdir)/depcomp |
am__depfiles_maybe = depfiles |
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/abstract.Po ./$(DEPDIR)/labels.Po \ |
@AMDEP_TRUE@ ./$(DEPDIR)/parse.Po ./$(DEPDIR)/stats.Po \ |
@AMDEP_TRUE@ ./$(DEPDIR)/trace.Po |
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ |
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) |
CCLD = $(CC) |
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ |
DIST_SOURCES = $(libcommon_a_SOURCES) |
DIST_COMMON = Makefile.am Makefile.in |
SOURCES = $(libcommon_a_SOURCES) |
|
all: all-am |
|
.SUFFIXES: |
.SUFFIXES: .c .o .obj |
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) |
cd $(top_srcdir) && \ |
$(AUTOMAKE) --gnu cpu/common/Makefile |
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status |
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) |
|
clean-noinstLIBRARIES: |
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) |
libcommon.a: $(libcommon_a_OBJECTS) $(libcommon_a_DEPENDENCIES) |
-rm -f libcommon.a |
$(libcommon_a_AR) libcommon.a $(libcommon_a_OBJECTS) $(libcommon_a_LIBADD) |
$(RANLIB) libcommon.a |
|
mostlyclean-compile: |
-rm -f *.$(OBJEXT) core *.core |
|
distclean-compile: |
-rm -f *.tab.c |
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/abstract.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/labels.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stats.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Po@am__quote@ |
|
distclean-depend: |
-rm -rf ./$(DEPDIR) |
|
.c.o: |
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ |
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
$(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< |
|
.c.obj: |
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ |
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
$(COMPILE) -c `cygpath -w $<` |
CCDEPMODE = @CCDEPMODE@ |
uninstall-info-am: |
|
ETAGS = etags |
ETAGSFLAGS = |
|
tags: TAGS |
|
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) |
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ |
unique=`for i in $$list; do \ |
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
done | \ |
$(AWK) ' { files[$$0] = 1; } \ |
END { for (i in files) print i; }'`; \ |
mkid -fID $$unique |
|
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ |
$(TAGS_FILES) $(LISP) |
tags=; \ |
here=`pwd`; \ |
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ |
unique=`for i in $$list; do \ |
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
done | \ |
$(AWK) ' { files[$$0] = 1; } \ |
END { for (i in files) print i; }'`; \ |
test -z "$(ETAGS_ARGS)$$tags$$unique" \ |
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ |
$$tags $$unique |
|
GTAGS: |
here=`$(am__cd) $(top_builddir) && pwd` \ |
&& cd $(top_srcdir) \ |
&& gtags -i $(GTAGS_ARGS) $$here |
|
distclean-tags: |
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH |
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
|
top_distdir = ../.. |
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) |
|
distdir: $(DISTFILES) |
@list='$(DISTFILES)'; for file in $$list; do \ |
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ |
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ |
if test "$$dir" != "$$file" && test "$$dir" != "."; then \ |
dir="/$$dir"; \ |
$(mkinstalldirs) "$(distdir)$$dir"; \ |
else \ |
dir=''; \ |
fi; \ |
if test -d $$d/$$file; then \ |
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ |
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ |
fi; \ |
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ |
else \ |
test -f $(distdir)/$$file \ |
|| cp -p $$d/$$file $(distdir)/$$file \ |
|| exit 1; \ |
fi; \ |
done |
check-am: all-am |
check: check-am |
all-am: Makefile $(LIBRARIES) |
|
installdirs: |
|
install: install-am |
install-exec: install-exec-am |
install-data: install-data-am |
uninstall: uninstall-am |
|
install-am: all-am |
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am |
|
installcheck: installcheck-am |
install-strip: |
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ |
INSTALL_STRIP_FLAG=-s \ |
`test -z '$(STRIP)' || \ |
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install |
mostlyclean-generic: |
|
clean-generic: |
|
distclean-generic: |
-rm -f Makefile $(CONFIG_CLEAN_FILES) |
|
maintainer-clean-generic: |
@echo "This command is intended for maintainers to use" |
@echo "it deletes files that may require special tools to rebuild." |
clean: clean-am |
|
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am |
|
distclean: distclean-am |
|
distclean-am: clean-am distclean-compile distclean-depend \ |
distclean-generic distclean-tags |
|
dvi: dvi-am |
|
dvi-am: |
|
info: info-am |
|
info-am: |
|
install-data-am: |
|
install-exec-am: |
|
install-info: install-info-am |
|
install-man: |
|
installcheck-am: |
|
maintainer-clean: maintainer-clean-am |
|
maintainer-clean-am: distclean-am maintainer-clean-generic |
|
mostlyclean: mostlyclean-am |
|
mostlyclean-am: mostlyclean-compile mostlyclean-generic |
|
uninstall-am: uninstall-info-am |
|
.PHONY: GTAGS all all-am check check-am clean clean-generic \ |
clean-noinstLIBRARIES distclean distclean-compile \ |
distclean-depend distclean-generic distclean-tags distdir dvi \ |
dvi-am info info-am install install-am install-data \ |
install-data-am install-exec install-exec-am install-info \ |
install-info-am install-man install-strip installcheck \ |
installcheck-am installdirs maintainer-clean \ |
maintainer-clean-generic mostlyclean mostlyclean-compile \ |
mostlyclean-generic tags uninstall uninstall-am \ |
uninstall-info-am |
|
# Tell versions [3.59,3.63) of GNU make to not export all variables. |
# Otherwise a system limit (for SysV at least) may be exceeded. |
.NOEXPORT: |
/labels.c
0,0 → 1,153
/* abstract.c -- Abstract entities, handling labels |
Copyright (C) 2001 Marko Mlinar, markom@opencores.org |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program 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. |
|
This program 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 this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
/* Abstract memory and routines that go with this. I need to |
add all sorts of other abstract entities. Currently we have |
only memory. */ |
|
#include <stdlib.h> |
#include <stdio.h> |
#include <ctype.h> |
#include <string.h> |
|
#include "config.h" |
|
#ifdef HAVE_INTTYPES_H |
#include <inttypes.h> |
#endif |
|
#include "port.h" |
#include "config.h" |
|
#include "arch.h" |
#include "sim-config.h" |
#include "labels.h" |
|
static struct label_entry *label_hash[LABELS_HASH_SIZE]; |
struct breakpoint_entry *breakpoints; |
|
void init_labels () { |
int i; |
for (i = 0; i < LABELS_HASH_SIZE; i++) |
label_hash[i] = NULL; |
} |
|
void add_label (oraddr_t addr, char *name) { |
struct label_entry **tmp; |
tmp = &(label_hash[addr % LABELS_HASH_SIZE]); |
for (; *tmp; tmp = &((*tmp)->next)); |
*tmp = malloc(sizeof(**tmp)); |
(*tmp)->name = malloc(strlen(name) + 1); |
(*tmp)->addr = addr; |
strcpy((*tmp)->name, name); |
(*tmp)->next = NULL; |
} |
|
struct label_entry *get_label (oraddr_t addr) { |
struct label_entry *tmp = label_hash[addr % LABELS_HASH_SIZE]; |
while (tmp) { |
if (tmp->addr == addr) |
return tmp; |
tmp = tmp->next; |
} |
return NULL; |
} |
|
struct label_entry *find_label (char *name) { |
int i; |
for (i = 0; i < LABELS_HASH_SIZE; i++) { |
struct label_entry *tmp = label_hash[i % LABELS_HASH_SIZE]; |
while (tmp) { |
if (strcmp (tmp->name, name) == 0) |
return tmp; |
tmp = tmp->next; |
} |
} |
return NULL; |
} |
|
/* Searches mem array for a particular label and returns label's address. |
If label does not exist, returns 0. */ |
oraddr_t eval_label (char *name) { |
struct label_entry *le; |
char *plus; |
char *minus; |
int positive_offset = 0; |
int negative_offset = 0; |
|
if ((plus = strchr(name, '+'))) { |
*plus = '\0'; |
positive_offset = atoi(++plus); |
} |
|
if ((minus = strchr(name, '-'))) { |
*minus = '\0'; |
negative_offset = atoi(++minus); |
} |
le = find_label (name); |
if (!le) |
return 0; |
|
return le->addr + positive_offset - negative_offset; |
} |
|
void init_breakpoints () { |
breakpoints = 0; |
} |
|
void add_breakpoint (oraddr_t addr) { |
struct breakpoint_entry *tmp; |
tmp = (struct breakpoint_entry *) malloc (sizeof (struct breakpoint_entry)); |
tmp->next = breakpoints; |
tmp->addr = addr; |
breakpoints = tmp; |
} |
|
void remove_breakpoint (oraddr_t addr) { |
struct breakpoint_entry **tmp = &breakpoints; |
while (*tmp) { |
if ((*tmp)->addr == addr) { |
struct breakpoint_entry *t = *tmp; |
(*tmp) = t->next; |
free (t); |
} else |
tmp = &((*tmp)->next); |
} |
} |
|
void print_breakpoints () { |
struct breakpoint_entry **tmp = &breakpoints; |
int i = 1; |
printf ("---[breakpoints]------------------\n"); |
while (*tmp) { |
printf ("Breakpoint %i at 0x%"PRIxADDR"\n", i, (*tmp)->addr); |
tmp = &((*tmp)->next); |
} |
printf ("---[breakpoints end]--------------\n"); |
} |
|
inline int has_breakpoint (oraddr_t addr) { |
struct breakpoint_entry *tmp = breakpoints; |
while (tmp) { |
if (tmp->addr == addr) |
return 1; |
tmp = tmp->next; |
} |
return 0; |
} |
labels.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: parse.h
===================================================================
--- parse.h (nonexistent)
+++ parse.h (revision 1765)
@@ -0,0 +1,41 @@
+/* parse.h -- Header file for parse.c
+ Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program 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.
+
+This program 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 this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Here we define some often used caharcters in assembly files.
+This wil probably go into architecture dependent directory. */
+
+#define COMMENT_CHAR '#'
+#define DIRECTIVE_CHAR '.'
+#define LABELEND_CHAR ":"
+/*#define OPERAND_DELIM ","*/
+
+/* Strip whitespace from the start and end of STRING. Return a pointer
+ into STRING. */
+#ifndef whitespace
+#define whitespace(a) ((a) == '\t' ? 1 : ((a) == ' '? 1 : 0))
+#endif
+
+/* Strips white spaces at beginning and at the end of the string */
+char *stripwhite (char *string);
+
+/* This function is very similar to strncpy, except it null terminates the string */
+char *strstrip (char *dst, const char *src, int n);
+
+/* Loads file to memory starting at address startaddr and returns freemem. */
+unsigned long loadcode(char *filename, oraddr_t startaddr, oraddr_t virtphy_transl);
Index: parse.c
===================================================================
--- parse.c (nonexistent)
+++ parse.c (revision 1765)
@@ -0,0 +1,697 @@
+/* parce.c -- Architecture independent load
+ Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program 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.
+
+This program 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 this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include
+#include
+#include
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "abstract.h"
+#include "dmmu.h"
+#include "coff.h"
+#include "elf.h"
+#include "debug_unit.h"
+#include "opcode/or32.h"
+#include "parse.h"
+#include "sim-config.h"
+#include "labels.h"
+#include "debug.h"
+
+#define MEMORY_LEN 0x100000000
+#define MAXLINE_LEN 18000
+
+/* Whether to do immediate statistics */
+#define IMM_STATS 0
+
+extern char *disassembled;
+
+/* Unused mem memory marker. It is used when allocating program and data memory
+ during parsing */
+unsigned int freemem;
+
+/* Translation table provided by microkernel. Only used if simulating microkernel. */
+static oraddr_t transl_table;
+
+/* Used to signal whether during loading of programs a translation fault occured. */
+static unsigned long transl_error;
+
+char *
+stripwhite (string)
+ char *string;
+{
+ register char *s, *t;
+
+ for (s = string; whitespace (*s); s++)
+ ;
+
+ if (*s == 0)
+ return (s);
+
+ t = s + strlen (s) - 1;
+ while (t > s && whitespace (*t))
+ t--;
+ *++t = '\0';
+
+ return s;
+}
+
+/* This function is very similar to strncpy, except it null terminates the string */
+char *strstrip (char *dst, const char *src, int n)
+{
+ strncpy (dst, src, n);
+ *(dst + n) = '\0';
+ return dst;
+}
+
+/* Used only by the simulator loader to translate logical addresses into physical.
+ If loadcode() is called with valid virtphy_transl pointer to a table of
+ translations then translate() performs translation otherwise phy address is
+ equal to logical. */
+static oraddr_t translate(oraddr_t laddr,int* breakpoint)
+{
+ int i;
+
+ /* No translation (i.e. when loading kernel into simulator) */
+/* PRINTF("transl_table=%x laddr=%x\n", transl_table, laddr);
+ PRINTF("laddr=%x\n", laddr);*/
+ if (transl_table == 0)
+ return laddr;
+
+ /* Try to find our translation in the table. */
+ for(i = 0; i < (MEMORY_LEN / PAGE_SIZE) * 16; i += 16)
+ if ((laddr & ~(PAGE_SIZE - 1)) == evalsim_mem32(transl_table + i)) {
+ setsim_mem32(transl_table + i + 8, -2); /* Page modified */
+ PRINTF("found paddr=%"PRIx32"\n",
+ evalsim_mem32(transl_table + i + 4) | (laddr & (PAGE_SIZE - 1)));
+ return (oraddr_t)evalsim_mem32(transl_table + i + 4) | (laddr & (oraddr_t)(PAGE_SIZE - 1));
+ }
+
+ /* Allocate new phy page for us. */
+ for(i = 0; i < (MEMORY_LEN / PAGE_SIZE) * 16; i += 16)
+ if (evalsim_mem32(transl_table + i + 8) == 0) {
+ setsim_mem32(transl_table + i, laddr & ~(PAGE_SIZE - 1)); /* VPN */
+ setsim_mem32(transl_table + i + 4, (i/16) * PAGE_SIZE); /* PPN */
+ setsim_mem32(transl_table + i + 8, -2); /* Page modified */
+ PRINTF("newly allocated ppn=%"PRIx32"\n",
+ evalsim_mem32(transl_table + i + 4));
+ PRINTF("newly allocated .ppn=%"PRIxADDR"\n", transl_table + i + 4);
+ PRINTF("newly allocated ofs=%"PRIxADDR"\n", (laddr & (PAGE_SIZE - 1)));
+ PRINTF("newly allocated paddr=%"PRIx32"\n",
+ evalsim_mem32(transl_table + i + 4) | (laddr & (PAGE_SIZE - 1)));
+ return (oraddr_t)evalsim_mem32(transl_table + i + 4) | (laddr & (oraddr_t)(PAGE_SIZE - 1));
+ }
+ /* If we come this far then all phy memory is used and we can't find our page
+ nor allocate new page. */
+ transl_error = 1;
+
+ PRINTF("can't translate %"PRIxADDR"\n", laddr);
+ exit(1);
+ return -1;
+}
+
+#if IMM_STATS
+int bcnt[33][3] = {0};
+int bsum[3] = {0};
+unsigned long movhi = 0;
+
+int bits (unsigned long val) {
+ int i = 1;
+ if (!val) return 0;
+ while (val != 0 && (signed long)val != -1) {i++; val = (signed long)val >> 1;}
+ return i;
+}
+
+void check_insn (uint32_t insn) {
+ int insn_index = insn_decode (insn);
+ struct insn_op_struct *opd = op_start[insn_index];
+ uint32_t data = 0;
+ int dis = 0;
+ const char *name;
+ if (!insn || insn_index < 0) return;
+ name = insn_name (insn_index);
+ if (strcmp (name, "l.nop") == 0 || strcmp (name, "l.sys") == 0) return;
+
+ while (1)
+ {
+ uint32_t tmp = 0
+ unsigned int nbits = 0;
+ while (1)
+ {
+ tmp |= ((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) << nbits;
+ nbits += opd->data;
+ if (opd->type & OPTYPE_OP)
+ break;
+ opd++;
+ }
+
+ /* Do we have to sign extend? */
+ if (opd->type & OPTYPE_SIG)
+ {
+ int sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
+ if (tmp & (1 << sbit))
+ tmp |= 0xFFFFFFFF << sbit;
+ }
+ if (opd->type & OPTYPE_DIS) {
+ /* We have to read register later. */
+ data += tmp;
+ dis = 1;
+ } else
+ {
+ if (!(opd->type & OPTYPE_REG) || dis) {
+ if (!dis) data = tmp;
+ if (strcmp (name, "l.movhi") == 0) {
+ movhi = data << 16;
+ } else {
+ data |= movhi;
+ //PRINTF ("%08x %s\n", data, name);
+ if (!(or32_opcodes[insn_index].flags & OR32_IF_DELAY)) {
+ bcnt[bits(data)][0]++; bsum[0]++;
+ } else {
+ if (strcmp (name, "l.bf") == 0 || strcmp (name, "l.bnf") == 0) {
+ bcnt[bits(data)][1]++; bsum[1]++;
+ } else {
+ bcnt[bits(data)][2]++; bsum[2]++;
+ }
+ }
+ }
+ }
+ data = 0;
+ dis = 0;
+ }
+ if(opd->type & OPTYPE_LAST) {
+ return;
+ }
+ opd++;
+ }
+}
+#endif
+
+/* Replaced several calls to translate(freemem) with vaddr */
+/* Added new mode execution code */
+/* Changed parameters so address can be passed as argument */
+void addprogram(oraddr_t address, uint32_t insn, int* breakpoint)
+{
+ int vaddr = (!runtime.sim.filename) ? translate(address,breakpoint) : translate(freemem,breakpoint);
+
+ setsim_mem32 (vaddr, insn);
+#if IMM_STATS
+ check_insn (insn);
+#endif
+ if(runtime.sim.filename)
+ freemem += insn_len (insn_decode (insn));
+}
+
+/* Load big-endian COFF file. */
+
+void readfile_coff(char *filename, short sections)
+{
+ FILE *inputfs;
+ char inputbuf[4];
+ uint32_t insn;
+ signed long sectsize;
+ COFF_AOUTHDR coffaouthdr;
+ struct COFF_scnhdr coffscnhdr;
+ int len;
+ int firstthree = 0;
+ int breakpoint = 0;
+
+ if (!(inputfs = fopen(filename, "r"))) {
+ perror("readfile_coff");
+ exit(1);
+ }
+
+ if (fseek(inputfs, sizeof(struct COFF_filehdr), SEEK_SET) == -1) {
+ fclose(inputfs);
+ perror("readfile_coff");
+ exit(1);
+ }
+
+ if (fread(&coffaouthdr, sizeof(coffaouthdr), 1, inputfs) != 1) {
+ fclose(inputfs);
+ perror("readfile_coff");
+ exit(1);
+ }
+
+ while(sections--) {
+ long scnhdr_pos = sizeof(struct COFF_filehdr) + sizeof(coffaouthdr)
+ + sizeof(struct COFF_scnhdr) * firstthree;
+ if (fseek(inputfs, scnhdr_pos, SEEK_SET) == -1) {
+ fclose(inputfs);
+ perror("readfile_coff");
+ exit(1);
+ }
+ if (fread(&coffscnhdr, sizeof(struct COFF_scnhdr), 1, inputfs) != 1) {
+ fclose(inputfs);
+ perror("readfile_coff");
+ exit(1);
+ }
+ PRINTF("Section: %s,", coffscnhdr.s_name);
+ PRINTF(" paddr: 0x%.8lx,", COFF_LONG_H(coffscnhdr.s_paddr));
+ PRINTF(" vaddr: 0x%.8lx,", COFF_LONG_H(coffscnhdr.s_vaddr));
+ PRINTF(" size: 0x%.8lx,", COFF_LONG_H(coffscnhdr.s_size));
+ PRINTF(" scnptr: 0x%.8lx\n", COFF_LONG_H(coffscnhdr.s_scnptr));
+
+ sectsize = COFF_LONG_H(coffscnhdr.s_size);
+#if 0
+ /* A couple of sanity checks. */
+ if (translate(COFF_LONG_H(coffscnhdr.s_vaddr),&breakpoint) < MEMORY_START) {
+ PRINTF("Section %s starts out of ", coffscnhdr.s_name);
+ PRINTF("memory (at %x)\n", COFF_LONG_H(coffscnhdr.s_vaddr));
+ exit(1);
+ }
+ if (translate(COFF_LONG_H(coffscnhdr.s_vaddr) + sectsize,&breakpoint) >
+ MEMORY_START + MEMORY_LEN) {
+ PRINTF("Section %s ends out of ", coffscnhdr.s_name);
+ PRINTF("memory.\n");
+ exit(1);
+ }
+#endif
+#if 0
+ if (++firstthree == 1 && strcmp(coffscnhdr.s_name, ".text") != 0) {
+ PRINTF("First section should be .text (%s instead)\n", coffscnhdr.s_name);
+ exit(1);
+ }
+ if (firstthree == 2 && strcmp(coffscnhdr.s_name, ".data") != 0) {
+ PRINTF("Second section should be .data (%s instead)\n", coffscnhdr.s_name);
+ exit(1);
+ }
+ if (firstthree == 3 && strcmp(coffscnhdr.s_name, ".bss") != 0) {
+ PRINTF("Third section should be .bss (%s instead)\n", coffscnhdr.s_name);
+ exit(1);
+ }
+#else
+ ++firstthree;
+#endif
+
+ /* loading section */
+ freemem = COFF_LONG_H(coffscnhdr.s_paddr);
+ debug(2,"Starting to load at 0x%x\n", freemem);
+ if (fseek(inputfs, COFF_LONG_H(coffscnhdr.s_scnptr), SEEK_SET) == -1) {
+ fclose(inputfs);
+ perror("readfile_coff");
+ exit(1);
+ }
+ while (sectsize > 0 && (len = fread(&inputbuf, sizeof(inputbuf), 1, inputfs))) {
+ insn = COFF_LONG_H(inputbuf);
+ len = insn_len (insn_decode (insn));
+ if (len == 2)
+ {
+ fseek(inputfs, -2, SEEK_CUR);
+ debug(8,"readfile_coff: %lx 0x%x \n", sectsize, insn >> 16);
+ }
+ else
+ debug(8,"readfile_coff: %lx 0x%x \n", sectsize, insn);
+ addprogram (freemem, insn, &breakpoint);
+ sectsize -= len;
+ }
+ }
+ if (firstthree < 3) {
+ PRINTF("One or more missing sections. At least");
+ PRINTF(" three sections expected (.text, .data, .bss).\n");
+ exit(1);
+ }
+ if (firstthree > 3) {
+ PRINTF("Warning: one or more extra sections. These");
+ PRINTF(" sections were handled as .data sections.\n");
+ }
+
+ fclose(inputfs);
+ PRINTF("Finished loading COFF.\n");
+ return;
+}
+
+/* Load symbols from big-endian COFF file. */
+
+void readsyms_coff(char *filename, unsigned long symptr, long syms)
+{
+ FILE *inputfs;
+ struct COFF_syment coffsymhdr;
+ int count = 0;
+ long nsyms = syms;
+ if (!(inputfs = fopen(filename, "r"))) {
+ perror("readsyms_coff");
+ exit(1);
+ }
+
+ if (fseek(inputfs, symptr, SEEK_SET) == -1) {
+ fclose(inputfs);
+ perror("readsyms_coff");
+ exit(1);
+ }
+
+ while(syms--) {
+ int i, n;
+ if (fread(&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1) {
+ fclose(inputfs);
+ perror("readsyms_coff");
+ exit(1);
+ }
+
+ n = (unsigned char)coffsymhdr.e_numaux[0];
+
+ /* check whether this symbol belongs to a section and is external symbol; ignore all others */
+ if (COFF_SHORT_H(coffsymhdr.e_scnum) >= 0 && coffsymhdr.e_sclass[0] == C_EXT) {
+#if 0
+ /* If not important or not in text, skip. */
+ if(COFF_SHORT_H(coffsymhdr.e_type) & COFF_N_TMASK & COFF_STYP_TEXT) {
+#endif
+
+ if (*((unsigned long *)coffsymhdr.e.e.e_zeroes)) {
+ if (strlen(coffsymhdr.e.e_name) && strlen(coffsymhdr.e.e_name) < 9)
+ add_label(COFF_LONG_H(coffsymhdr.e_value), coffsymhdr.e.e_name);
+ debug(8, "[%i] Symbol: %s,", count++, coffsymhdr.e.e_name);
+ } else {
+ long fpos = ftell (inputfs);
+
+ if (fseek(inputfs, symptr + nsyms * COFF_SYMESZ + COFF_LONG_H(coffsymhdr.e.e.e_offset), SEEK_SET) == 0) {
+ char tmp[33], *s = &tmp[0];
+ while (s != &tmp[32])
+ if ((*(s++) = fgetc(inputfs)) == 0) break;
+ tmp[32] = 0;
+ add_label(COFF_LONG_H(coffsymhdr.e_value), &tmp[0]);
+ debug(8, "[%i] Symbol: %s,", count++, &tmp[0]);
+ }
+ fseek(inputfs, fpos, SEEK_SET);
+ }
+
+ debug(9, " val: 0x%.8lx,", COFF_LONG_H(coffsymhdr.e_value));
+ debug(9, " type: %x, %x, auxs: %i\n", COFF_SHORT_H(coffsymhdr.e_type), *((unsigned short *)coffsymhdr.e_type), n);
+ }
+
+ for (i = 0; i < n; i++)
+ if (fread(&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1) {
+ fclose(inputfs);
+ perror("readsyms_coff3");
+ exit(1);
+ }
+ syms -= n;
+ count += n;
+ }
+
+ fclose(inputfs);
+ PRINTF("Finished loading symbols.\n");
+ return;
+}
+
+void readfile_elf(char *filename)
+{
+
+ FILE *inputfs;
+ struct elf32_hdr elfhdr;
+ struct elf32_phdr *elf_phdata;
+ struct elf32_shdr *elf_spnt, *elf_shdata;
+ struct elf32_sym *sym_tbl = (struct elf32_sym *)0;
+ unsigned long syms = 0;
+ char *str_tbl = (char *)0;
+ char *s_str = (char *)0;
+ int breakpoint = 0;
+ unsigned long inputbuf;
+ unsigned long padd;
+ uint32_t insn;
+ int i, j, sectsize, len;
+
+ if (!(inputfs = fopen(filename, "r"))) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ if (fread(&elfhdr, sizeof(elfhdr), 1, inputfs) != 1) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ if ((elf_shdata = (struct elf32_shdr *)malloc(ELF_SHORT_H(elfhdr.e_shentsize) * ELF_SHORT_H(elfhdr.e_shnum))) == NULL) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ if (fseek(inputfs, ELF_LONG_H(elfhdr.e_shoff), SEEK_SET) != 0) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ if (fread(elf_shdata, ELF_SHORT_H(elfhdr.e_shentsize) * ELF_SHORT_H(elfhdr.e_shnum), 1, inputfs) != 1) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ if (ELF_LONG_H(elfhdr.e_phoff)) {
+
+ if((elf_phdata = (struct elf32_phdr *)malloc(ELF_SHORT_H(elfhdr.e_phnum) * ELF_SHORT_H(elfhdr.e_phentsize))) == NULL) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ if (fseek(inputfs, ELF_LONG_H(elfhdr.e_phoff), SEEK_SET) != 0) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ if (fread(elf_phdata, ELF_SHORT_H(elfhdr.e_phnum) * ELF_SHORT_H(elfhdr.e_phentsize), 1, inputfs) != 1) {
+ perror("readfile_elf");
+ exit(1);
+ }
+ }
+
+ for(i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H(elfhdr.e_shnum); i++, elf_spnt++) {
+
+ if(ELF_LONG_H(elf_spnt->sh_type) == SHT_STRTAB) {
+
+ if((str_tbl = (char *)malloc(ELF_LONG_H(elf_spnt->sh_size))) == NULL) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ if (fseek(inputfs, ELF_LONG_H(elf_spnt->sh_offset), SEEK_SET) != 0) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ if (fread(str_tbl, ELF_LONG_H(elf_spnt->sh_size), 1, inputfs) != 1) {
+ perror("readfile_elf");
+ exit(1);
+ }
+ }
+ else if(ELF_LONG_H(elf_spnt->sh_type) == SHT_SYMTAB) {
+
+ if((sym_tbl = (struct elf32_sym *)malloc(ELF_LONG_H(elf_spnt->sh_size))) == NULL) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ if (fseek(inputfs, ELF_LONG_H(elf_spnt->sh_offset), SEEK_SET) != 0) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ if (fread(sym_tbl, ELF_LONG_H(elf_spnt->sh_size), 1, inputfs) != 1) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ syms = ELF_LONG_H(elf_spnt->sh_size) / ELF_LONG_H(elf_spnt->sh_entsize);
+ }
+ }
+
+ if (ELF_SHORT_H(elfhdr.e_shstrndx) != SHN_UNDEF) {
+ elf_spnt = &elf_shdata[ELF_SHORT_H(elfhdr.e_shstrndx)];
+
+ if((s_str = (char *)malloc(ELF_LONG_H(elf_spnt->sh_size))) == NULL) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ if (fseek(inputfs, ELF_LONG_H(elf_spnt->sh_offset), SEEK_SET) != 0) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ if (fread(s_str, ELF_LONG_H(elf_spnt->sh_size), 1, inputfs) != 1) {
+ perror("readfile_elf");
+ exit(1);
+ }
+ }
+
+
+ for(i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H(elfhdr.e_shnum); i++, elf_spnt++) {
+
+ if((ELF_LONG_H(elf_spnt->sh_type) & SHT_PROGBITS) && (ELF_LONG_H(elf_spnt->sh_flags) & SHF_ALLOC)) {
+
+ padd = ELF_LONG_H(elf_spnt->sh_addr);
+ for(j = 0; j < ELF_SHORT_H(elfhdr.e_phnum); j++) {
+ if(ELF_LONG_H(elf_phdata[j].p_offset) &&
+ ELF_LONG_H(elf_phdata[j].p_offset) <= ELF_LONG_H(elf_spnt->sh_offset) &&
+ (ELF_LONG_H(elf_phdata[j].p_offset) + ELF_LONG_H(elf_phdata[j].p_memsz)) > ELF_LONG_H(elf_spnt->sh_offset))
+ padd = ELF_LONG_H(elf_phdata[j].p_paddr) + ELF_LONG_H(elf_spnt->sh_offset) - ELF_LONG_H(elf_phdata[j].p_offset);
+ }
+
+
+
+ if (ELF_LONG_H(elf_spnt->sh_name) && s_str)
+ PRINTF("Section: %s,", &s_str[ELF_LONG_H(elf_spnt->sh_name)]);
+ else
+ PRINTF("Section: noname,");
+ PRINTF(" vaddr: 0x%.8lx,", ELF_LONG_H(elf_spnt->sh_addr));
+ PRINTF(" paddr: 0x%.8lx,", padd);
+ PRINTF(" offset: 0x%.8lx,", ELF_LONG_H(elf_spnt->sh_offset));
+ PRINTF(" size: 0x%.8lx\n", ELF_LONG_H(elf_spnt->sh_size));
+
+ freemem = padd;
+ sectsize = ELF_LONG_H(elf_spnt->sh_size);
+
+ if (fseek(inputfs, ELF_LONG_H(elf_spnt->sh_offset), SEEK_SET) != 0) {
+ perror("readfile_elf");
+ exit(1);
+ }
+
+ while (sectsize > 0 && (len = fread(&inputbuf, sizeof(inputbuf), 1, inputfs))) {
+ insn = ELF_LONG_H(inputbuf);
+ len = insn_len (insn_decode (insn));
+ if (len == 2)
+ {
+ fseek(inputfs, -2, SEEK_CUR);
+ debug(8, "readfile_elf: %x 0x%x \n", sectsize, insn >> 16);
+ }
+ else
+ debug(8, "readfile_elf: %x 0x%x \n", sectsize, insn);
+ addprogram (freemem, insn, &breakpoint);
+ sectsize -= len;
+ }
+ }
+ }
+
+ if (str_tbl) {
+ i = 0;
+ while(syms--) {
+ if (sym_tbl[i].st_name && sym_tbl[i].st_info && ELF_SHORT_H(sym_tbl[i].st_shndx) < 0x8000) {
+ add_label(ELF_LONG_H(sym_tbl[i].st_value), &str_tbl[ELF_LONG_H(sym_tbl[i].st_name)]);
+ debug (8, "%08lx(%s): %x %x %x\n", ELF_LONG_H(sym_tbl[i].st_value), &str_tbl[ELF_LONG_H(sym_tbl[i].st_name)], sym_tbl[i].st_info, sym_tbl[i].st_other, ELF_SHORT_H(sym_tbl[i].st_shndx));
+ }
+ i++;
+ }
+ }
+}
+
+/* Identify file type and call appropriate readfile_X routine. It only
+handles orX-coff-big executables at the moment. */
+
+void identifyfile(char *filename)
+{
+ FILE *inputfs;
+ struct COFF_filehdr coffhdr;
+ struct elf32_hdr elfhdr;
+
+ if (!(inputfs = fopen(filename, "r"))) {
+ perror(filename);
+ fflush(stdout);
+ fflush(stderr);
+ exit(1);
+ }
+
+ if (fread(&coffhdr, sizeof(coffhdr), 1, inputfs) == 1) {
+ if (COFF_SHORT_H(coffhdr.f_magic) == 0x17a) {
+ unsigned long opthdr_size;
+ PRINTF("COFF magic: 0x%.4x\n", COFF_SHORT_H(coffhdr.f_magic));
+ PRINTF("COFF flags: 0x%.4x\n", COFF_SHORT_H(coffhdr.f_flags));
+ PRINTF("COFF symptr: 0x%.8lx\n", COFF_LONG_H(coffhdr.f_symptr));
+ if ((COFF_SHORT_H(coffhdr.f_flags) & COFF_F_EXEC) != COFF_F_EXEC) {
+ PRINTF("This COFF is not an executable.\n");
+ exit(1);
+ }
+ opthdr_size = COFF_SHORT_H(coffhdr.f_opthdr);
+ if (opthdr_size != sizeof(COFF_AOUTHDR)) {
+ PRINTF("COFF optional header is missing or not recognized.\n");
+ PRINTF("COFF f_opthdr: 0x%.2lx\n", opthdr_size);
+ exit(1);
+ }
+ fclose(inputfs);
+ readfile_coff(filename, COFF_SHORT_H(coffhdr.f_nscns));
+ readsyms_coff(filename, COFF_LONG_H(coffhdr.f_symptr), COFF_LONG_H(coffhdr.f_nsyms));
+ return;
+ }
+ else {
+ PRINTF("Not COFF file format\n");
+ fseek(inputfs, 0, SEEK_SET);
+ }
+ }
+ if (fread(&elfhdr, sizeof(elfhdr), 1, inputfs) == 1) {
+ if (elfhdr.e_ident[0] == 0x7f && elfhdr.e_ident[1] == 0x45 && elfhdr.e_ident[2] == 0x4c && elfhdr.e_ident[3] == 0x46) {
+ PRINTF("ELF type: 0x%.4x\n", ELF_SHORT_H(elfhdr.e_type));
+ PRINTF("ELF machine: 0x%.4x\n", ELF_SHORT_H(elfhdr.e_machine));
+ PRINTF("ELF version: 0x%.8lx\n", ELF_LONG_H(elfhdr.e_version));
+ PRINTF("ELF sec = %d\n", ELF_SHORT_H(elfhdr.e_shnum));
+ if (ELF_SHORT_H(elfhdr.e_type) != ET_EXEC ) {
+ PRINTF("This ELF is not an executable.\n");
+ exit(1);
+ }
+ fclose(inputfs);
+ readfile_elf(filename);
+ return;
+ }
+ else {
+ PRINTF("Not ELF file format.\n");
+ fseek(inputfs, 0, SEEK_SET);
+ }
+ }
+
+ perror("identifyfile2");
+ fclose(inputfs);
+
+ return;
+}
+
+
+/* Loads file to memory starting at address startaddr and returns freemem. */
+unsigned long loadcode(char *filename, oraddr_t startaddr, oraddr_t virtphy_transl)
+{
+ int breakpoint = 0;
+
+ transl_error = 0;
+ transl_table = virtphy_transl;
+ freemem = startaddr;
+ PRINTF("loadcode: filename %s startaddr=%"PRIxADDR" virtphy_transl=%"PRIxADDR"\n",
+ filename, startaddr, virtphy_transl);
+ identifyfile(filename);
+
+#if IMM_STATS
+ {
+ int i = 0, a = 0, b = 0, c = 0;
+ PRINTF ("index:arith/branch/jump\n");
+ for (i = 0; i < 33; i++)
+ PRINTF ("%2i:\t%3.0f%% / %3.0f%%/ %3.0f%%\t%5i / %5i / %5i\n", i,
+ 100.* (a += bcnt[i][0])/bsum[0], 100.* (b += bcnt[i][1])/bsum[1],
+ 100.* (c += bcnt[i][2])/bsum[2], bcnt[i][0], bcnt[i][1], bcnt[i][2]);
+ PRINTF ("\nsum %i %i %i\n", bsum[0], bsum[1], bsum[2]);
+ }
+#endif
+
+ if (transl_error)
+ return -1;
+ else
+ return translate(freemem,&breakpoint);
+
+}
Index: trace.h
===================================================================
--- trace.h (nonexistent)
+++ trace.h (revision 1765)
@@ -0,0 +1,2 @@
+
+void set_insnbrkpoint(oraddr_t addr);
Index: labels.h
===================================================================
--- labels.h (nonexistent)
+++ labels.h (revision 1765)
@@ -0,0 +1,58 @@
+/* labels.h -- Abstract entities header file handling labels
+ Copyright (C) 2001 Marko Mlinar, markom@opencores.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program 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.
+
+This program 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 this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _LABELS_H_
+#define _LABELS_H_
+
+#define LABELS_HASH_SIZE 119
+
+/* Structure for holding one label per particular memory location */
+struct label_entry {
+ char *name;
+ oraddr_t addr;
+ struct label_entry *next;
+};
+
+struct breakpoint_entry {
+ oraddr_t addr;
+ struct breakpoint_entry *next;
+};
+
+/* Label handling */
+void init_labels();
+void add_label (oraddr_t addr, char *name);
+struct label_entry *get_label (oraddr_t addr);
+struct label_entry *find_label (char *name);
+
+/* Searches mem array for a particular label and returns label's address.
+ If label does not exist, returns 0. */
+oraddr_t eval_label (char *name);
+
+/* Breakpoint handling */
+void breakpoints_init ();
+void add_breakpoint (oraddr_t addr);
+void remove_breakpoint (oraddr_t addr);
+void print_breakpoints ();
+int has_breakpoint (oraddr_t addr);
+void init_breakpoints ();
+
+extern struct breakpoint_entry *breakpoints;
+#define CHECK_BREAKPOINTS (breakpoints)
+
+#endif /* _LABELS_H_ */
labels.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: coff.h
===================================================================
--- coff.h (nonexistent)
+++ coff.h (revision 1765)
@@ -0,0 +1,457 @@
+#if HAVE_CONFIG_H
+#include
+#endif
+
+/* This file is derived from the GAS 2.1.4 assembler control file.
+ The GAS product is under the GNU Public License, version 2 or later.
+ As such, this file is also under that license.
+
+ If the file format changes in the COFF object, this file should be
+ subsequently updated to reflect the changes.
+
+ The actual loader module only uses a few of these structures. The full
+ set is documented here because I received the full set. If you wish
+ more information about COFF, then O'Reilly has a very excellent book.
+*/
+
+#define E_SYMNMLEN 8 /* Number of characters in a symbol name */
+#define E_FILNMLEN 14 /* Number of characters in a file name */
+#define E_DIMNUM 4 /* Number of array dimensions in auxiliary entry */
+
+/*
+ * These defines are byte order independent. There is no alignment of fields
+ * permitted in the structures. Therefore they are declared as characters
+ * and the values loaded from the character positions. It also makes it
+ * nice to have it "endian" independent.
+ */
+#if !defined(WORDS_BIGENDIAN)
+/* Load a short int from the following tables with little-endian formats */
+#define COFF_SHORT_L SWAP_ENDIAN_SHORT
+/* Load a long int from the following tables with little-endian formats */
+#define COFF_LONG_L SWAP_ENDIAN_LONG
+/* Load a short int from the following tables with big-endian formats */
+#define COFF_SHORT_H KEEP_ENDIAN_SHORT
+/* Load a long int from the following tables with big-endian formats */
+#define COFF_LONG_H KEEP_ENDIAN_LONG
+#else
+#define COFF_SHORT_L KEEP_ENDIAN_SHORT
+#define COFF_LONG_L KEEP_ENDIAN_LONG
+#define COFF_SHORT_H SWAP_ENDIAN_SHORT
+#define COFF_LONG_H SWAP_ENDIAN_LONG
+#endif
+
+#define SWAP_ENDIAN_SHORT(ps) ((short)(((unsigned short)((unsigned char)ps[1])<<8)|\
+ ((unsigned short)((unsigned char)ps[0]))))
+
+#define SWAP_ENDIAN_LONG(ps) (((long)(((unsigned long)((unsigned char)ps[3])<<24) |\
+ ((unsigned long)((unsigned char)ps[2])<<16) |\
+ ((unsigned long)((unsigned char)ps[1])<<8) |\
+ ((unsigned long)((unsigned char)ps[0])))))
+
+#define KEEP_ENDIAN_SHORT(ps) ((short)(((unsigned short)((unsigned char)ps[0])<<8)|\
+ ((unsigned short)((unsigned char)ps[1]))))
+
+#define KEEP_ENDIAN_LONG(ps) (((long)(((unsigned long)((unsigned char)ps[0])<<24) |\
+ ((unsigned long)((unsigned char)ps[1])<<16) |\
+ ((unsigned long)((unsigned char)ps[2])<<8) |\
+ ((unsigned long)((unsigned char)ps[3])))))
+
+/* These may be overridden later by brain dead implementations which generate
+ a big-endian header with little-endian data. In that case, generate a
+ replacement macro which tests a flag and uses either of the two above
+ as appropriate. */
+
+#define COFF_LONG(v) COFF_LONG_L(v)
+#define COFF_SHORT(v) COFF_SHORT_L(v)
+
+/*** coff information for Intel 386/486. */
+
+/********************** FILE HEADER **********************/
+
+struct COFF_filehdr {
+ char f_magic[2]; /* magic number */
+ char f_nscns[2]; /* number of sections */
+ char f_timdat[4]; /* time & date stamp */
+ char f_symptr[4]; /* file pointer to symtab */
+ char f_nsyms[4]; /* number of symtab entries */
+ char f_opthdr[2]; /* sizeof(optional hdr) */
+ char f_flags[2]; /* flags */
+};
+
+/*
+ * Bits for f_flags:
+ *
+ * F_RELFLG relocation info stripped from file
+ * F_EXEC file is executable (i.e. no unresolved external
+ * references)
+ * F_LNNO line numbers stripped from file
+ * F_LSYMS local symbols stripped from file
+ * F_MINMAL this is a minimal object file (".m") output of fextract
+ * F_UPDATE this is a fully bound update file, output of ogen
+ * F_SWABD this file has had its bytes swabbed (in names)
+ * F_AR16WR this file has the byte ordering of an AR16WR
+ * (e.g. 11/70) machine
+ * F_AR32WR this file has the byte ordering of an AR32WR machine
+ * (e.g. vax and iNTEL 386)
+ * F_AR32W this file has the byte ordering of an AR32W machine
+ * (e.g. 3b,maxi)
+ * F_PATCH file contains "patch" list in optional header
+ * F_NODF (minimal file only) no decision functions for
+ * replaced functions
+ */
+
+#define COFF_F_RELFLG 0000001
+#define COFF_F_EXEC 0000002
+#define COFF_F_LNNO 0000004
+#define COFF_F_LSYMS 0000010
+#define COFF_F_MINMAL 0000020
+#define COFF_F_UPDATE 0000040
+#define COFF_F_SWABD 0000100
+#define COFF_F_AR16WR 0000200
+#define COFF_F_AR32WR 0000400
+#define COFF_F_AR32W 0001000
+#define COFF_F_PATCH 0002000
+#define COFF_F_NODF 0002000
+
+#define COFF_I386MAGIC 0x14c /* Linux's system */
+
+#if 0 /* Perhaps, someday, these formats may be used. */
+#define COFF_I386PTXMAGIC 0x154
+#define COFF_I386AIXMAGIC 0x175 /* IBM's AIX system */
+#define COFF_I386BADMAG(x) ((COFF_SHORT((x).f_magic) != COFF_I386MAGIC) \
+ && COFF_SHORT((x).f_magic) != COFF_I386PTXMAGIC \
+ && COFF_SHORT((x).f_magic) != COFF_I386AIXMAGIC)
+#else
+#define COFF_I386BADMAG(x) (COFF_SHORT((x).f_magic) != COFF_I386MAGIC)
+#endif
+
+#define COFF_FILHDR struct COFF_filehdr
+#define COFF_FILHSZ sizeof(COFF_FILHDR)
+
+/********************** AOUT "OPTIONAL HEADER" **********************/
+
+/* Linux COFF must have this "optional" header. Standard COFF has no entry
+ location for the "entry" point. They normally would start with the first
+ location of the .text section. This is not a good idea for linux. So,
+ the use of this "optional" header is not optional. It is required.
+
+ Do not be tempted to assume that the size of the optional header is
+ a constant and simply index the next byte by the size of this structure.
+ Use the 'f_opthdr' field in the main coff header for the size of the
+ structure actually written to the file!!
+*/
+
+typedef struct
+{
+ char magic[2]; /* type of file */
+ char vstamp[2]; /* version stamp */
+ char tsize[4]; /* text size in bytes, padded to FW bdry */
+ char dsize[4]; /* initialized data " " */
+ char bsize[4]; /* uninitialized data " " */
+ char entry[4]; /* entry pt. */
+ char text_start[4]; /* base of text used for this file */
+ char data_start[4]; /* base of data used for this file */
+}
+COFF_AOUTHDR;
+
+#define COFF_AOUTSZ (sizeof(COFF_AOUTHDR))
+
+#define COFF_STMAGIC 0401
+#define COFF_OMAGIC 0404
+#define COFF_JMAGIC 0407 /* dirty text and data image, can't share */
+#define COFF_DMAGIC 0410 /* dirty text segment, data aligned */
+#define COFF_ZMAGIC 0413 /* The proper magic number for executables */
+#define COFF_SHMAGIC 0443 /* shared library header */
+
+/********************** STORAGE CLASSES **********************/
+
+/* This used to be defined as -1, but now n_sclass is unsigned. */
+#define C_EFCN 0xff /* physical end of function */
+#define C_NULL 0
+#define C_AUTO 1 /* automatic variable */
+#define C_EXT 2 /* external symbol */
+#define C_STAT 3 /* static */
+#define C_REG 4 /* register variable */
+#define C_EXTDEF 5 /* external definition */
+#define C_LABEL 6 /* label */
+#define C_ULABEL 7 /* undefined label */
+#define C_MOS 8 /* member of structure */
+#define C_ARG 9 /* function argument */
+#define C_STRTAG 10 /* structure tag */
+#define C_MOU 11 /* member of union */
+#define C_UNTAG 12 /* union tag */
+#define C_TPDEF 13 /* type definition */
+#define C_USTATIC 14 /* undefined static */
+#define C_ENTAG 15 /* enumeration tag */
+#define C_MOE 16 /* member of enumeration */
+#define C_REGPARM 17 /* register parameter */
+#define C_FIELD 18 /* bit field */
+#define C_AUTOARG 19 /* auto argument */
+#define C_LASTENT 20 /* dummy entry (end of block) */
+#define C_BLOCK 100 /* ".bb" or ".eb" */
+#define C_FCN 101 /* ".bf" or ".ef" */
+#define C_EOS 102 /* end of structure */
+#define C_FILE 103 /* file name */
+#define C_LINE 104 /* line # reformatted as symbol table entry */
+#define C_ALIAS 105 /* duplicate tag */
+#define C_HIDDEN 106 /* ext symbol in dmert public lib */
+
+#define C_WEAKEXT 127 /* weak symbol -- GNU extension */
+
+/* New storage classes for TI COFF */
+#define C_UEXT 19 /* Tentative external definition */
+#define C_STATLAB 20 /* Static load time label */
+#define C_EXTLAB 21 /* External load time label */
+#define C_SYSTEM 23 /* System Wide variable */
+
+/* New storage classes for WINDOWS_NT */
+#define C_SECTION 104 /* section name */
+#define C_NT_WEAK 105 /* weak external */
+
+ /* New storage classes for 80960 */
+
+/* C_LEAFPROC is obsolete. Use C_LEAFEXT or C_LEAFSTAT */
+#define C_LEAFPROC 108 /* Leaf procedure, "call" via BAL */
+
+#define C_SCALL 107 /* Procedure reachable via system call */
+#define C_LEAFEXT 108 /* External leaf */
+#define C_LEAFSTAT 113 /* Static leaf */
+#define C_OPTVAR 109 /* Optimized variable */
+#define C_DEFINE 110 /* Preprocessor #define */
+#define C_PRAGMA 111 /* Advice to compiler or linker */
+#define C_SEGMENT 112 /* 80960 segment name */
+
+ /* Storage classes for m88k */
+#define C_SHADOW 107 /* shadow symbol */
+#define C_VERSION 108 /* coff version symbol */
+
+ /* New storage classes for RS/6000 */
+#define C_HIDEXT 107 /* Un-named external symbol */
+#define C_BINCL 108 /* Marks beginning of include file */
+#define C_EINCL 109 /* Marks ending of include file */
+
+ /* storage classes for stab symbols for RS/6000 */
+#define C_GSYM (0x80)
+#define C_LSYM (0x81)
+#define C_PSYM (0x82)
+#define C_RSYM (0x83)
+#define C_RPSYM (0x84)
+#define C_STSYM (0x85)
+#define C_TCSYM (0x86)
+#define C_BCOMM (0x87)
+#define C_ECOML (0x88)
+#define C_ECOMM (0x89)
+#define C_DECL (0x8c)
+#define C_ENTRY (0x8d)
+#define C_FUN (0x8e)
+#define C_BSTAT (0x8f)
+#define C_ESTAT (0x90)
+
+/* Storage classes for Thumb symbols */
+#define C_THUMBEXT (128 + C_EXT) /* 130 */
+#define C_THUMBSTAT (128 + C_STAT) /* 131 */
+#define C_THUMBLABEL (128 + C_LABEL) /* 134 */
+#define C_THUMBEXTFUNC (C_THUMBEXT + 20) /* 150 */
+#define C_THUMBSTATFUNC (C_THUMBSTAT + 20) /* 151 */
+
+/********************** SECTION HEADER **********************/
+
+struct COFF_scnhdr {
+ char s_name[8]; /* section name */
+ char s_paddr[4]; /* physical address, aliased s_nlib */
+ char s_vaddr[4]; /* virtual address */
+ char s_size[4]; /* section size */
+ char s_scnptr[4]; /* file ptr to raw data for section */
+ char s_relptr[4]; /* file ptr to relocation */
+ char s_lnnoptr[4]; /* file ptr to line numbers */
+ char s_nreloc[2]; /* number of relocation entries */
+ char s_nlnno[2]; /* number of line number entries */
+ char s_flags[4]; /* flags */
+};
+
+#define COFF_SCNHDR struct COFF_scnhdr
+#define COFF_SCNHSZ sizeof(COFF_SCNHDR)
+
+/*
+ * names of "special" sections
+ */
+
+#define COFF_TEXT ".text"
+#define COFF_DATA ".data"
+#define COFF_BSS ".bss"
+#define COFF_COMMENT ".comment"
+#define COFF_LIB ".lib"
+
+#define COFF_SECT_TEXT 0 /* Section for instruction code */
+#define COFF_SECT_DATA 1 /* Section for initialized globals */
+#define COFF_SECT_BSS 2 /* Section for un-initialized globals */
+#define COFF_SECT_REQD 3 /* Minimum number of sections for good file */
+
+#define COFF_STYP_REG 0x00 /* regular segment */
+#define COFF_STYP_DSECT 0x01 /* dummy segment */
+#define COFF_STYP_NOLOAD 0x02 /* no-load segment */
+#define COFF_STYP_GROUP 0x04 /* group segment */
+#define COFF_STYP_PAD 0x08 /* .pad segment */
+#define COFF_STYP_COPY 0x10 /* copy section */
+#define COFF_STYP_TEXT 0x20 /* .text segment */
+#define COFF_STYP_DATA 0x40 /* .data segment */
+#define COFF_STYP_BSS 0x80 /* .bss segment */
+#define COFF_STYP_INFO 0x200 /* .comment section */
+#define COFF_STYP_OVER 0x400 /* overlay section */
+#define COFF_STYP_LIB 0x800 /* library section */
+
+/*
+ * Shared libraries have the following section header in the data field for
+ * each library.
+ */
+
+struct COFF_slib {
+ char sl_entsz[4]; /* Size of this entry */
+ char sl_pathndx[4]; /* size of the header field */
+};
+
+#define COFF_SLIBHD struct COFF_slib
+#define COFF_SLIBSZ sizeof(COFF_SLIBHD)
+
+/********************** LINE NUMBERS **********************/
+
+/* 1 line number entry for every "breakpointable" source line in a section.
+ * Line numbers are grouped on a per function basis; first entry in a function
+ * grouping will have l_lnno = 0 and in place of physical address will be the
+ * symbol table index of the function name.
+ */
+
+struct COFF_lineno {
+ union {
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_paddr[4]; /* (physical) address of line number */
+ } l_addr;
+ char l_lnno[2]; /* line number */
+};
+
+#define COFF_LINENO struct COFF_lineno
+#define COFF_LINESZ 6
+
+/********************** SYMBOLS **********************/
+
+#define COFF_E_SYMNMLEN 8 /* # characters in a short symbol name */
+#define COFF_E_FILNMLEN 14 /* # characters in a file name */
+#define COFF_E_DIMNUM 4 /* # array dimensions in auxiliary entry */
+
+/*
+ * All symbols and sections have the following definition
+ */
+
+struct COFF_syment
+{
+ union {
+ char e_name[E_SYMNMLEN]; /* Symbol name (first 8 characters) */
+ struct {
+ char e_zeroes[4]; /* Leading zeros */
+ char e_offset[4]; /* Offset if this is a header section */
+ } e;
+ } e;
+
+ char e_value[4]; /* Value (address) of the segment */
+ char e_scnum[2]; /* Section number */
+ char e_type[2]; /* Type of section */
+ char e_sclass[1]; /* Loader class */
+ char e_numaux[1]; /* Number of auxiliary entries which follow */
+};
+
+#define COFF_N_BTMASK (0xf) /* Mask for important class bits */
+#define COFF_N_TMASK (0x30) /* Mask for important type bits */
+#define COFF_N_BTSHFT (4) /* # bits to shift class field */
+#define COFF_N_TSHIFT (2) /* # bits to shift type field */
+
+/*
+ * Auxiliary entries because the main table is too limiting.
+ */
+
+union COFF_auxent {
+
+/*
+ * Debugger information
+ */
+
+ struct {
+ char x_tagndx[4]; /* str, un, or enum tag indx */
+ union {
+ struct {
+ char x_lnno[2]; /* declaration line number */
+ char x_size[2]; /* str/union/array size */
+ } x_lnsz;
+ char x_fsize[4]; /* size of function */
+ } x_misc;
+
+ union {
+ struct { /* if ISFCN, tag, or .bb */
+ char x_lnnoptr[4]; /* ptr to fcn line # */
+ char x_endndx[4]; /* entry ndx past block end */
+ } x_fcn;
+
+ struct { /* if ISARY, up to 4 dimen. */
+ char x_dimen[E_DIMNUM][2];
+ } x_ary;
+ } x_fcnary;
+
+ char x_tvndx[2]; /* tv index */
+ } x_sym;
+
+/*
+ * Source file names (debugger information)
+ */
+
+ union {
+ char x_fname[E_FILNMLEN];
+ struct {
+ char x_zeroes[4];
+ char x_offset[4];
+ } x_n;
+ } x_file;
+
+/*
+ * Section information
+ */
+
+ struct {
+ char x_scnlen[4]; /* section length */
+ char x_nreloc[2]; /* # relocation entries */
+ char x_nlinno[2]; /* # line numbers */
+ } x_scn;
+
+/*
+ * Transfer vector (branch table)
+ */
+
+ struct {
+ char x_tvfill[4]; /* tv fill value */
+ char x_tvlen[2]; /* length of .tv */
+ char x_tvran[2][2]; /* tv range */
+ } x_tv; /* info about .tv section (in auxent of symbol .tv)) */
+};
+
+#define COFF_SYMENT struct COFF_syment
+#define COFF_SYMESZ 18
+#define COFF_AUXENT union COFF_auxent
+#define COFF_AUXESZ 18
+
+#define COFF_ETEXT "etext"
+
+/********************** RELOCATION DIRECTIVES **********************/
+
+struct COFF_reloc {
+ char r_vaddr[4]; /* Virtual address of item */
+ char r_symndx[4]; /* Symbol index in the symtab */
+ char r_type[2]; /* Relocation type */
+};
+
+#define COFF_RELOC struct COFF_reloc
+#define COFF_RELSZ 10
+
+#define COFF_DEF_DATA_SECTION_ALIGNMENT 4
+#define COFF_DEF_BSS_SECTION_ALIGNMENT 4
+#define COFF_DEF_TEXT_SECTION_ALIGNMENT 4
+
+/* For new sections we haven't heard of before */
+#define COFF_DEF_SECTION_ALIGNMENT 4
Index: elf.h
===================================================================
--- elf.h (nonexistent)
+++ elf.h (revision 1765)
@@ -0,0 +1,439 @@
+#ifndef _LINUX_ELF_H
+#define _LINUX_ELF_H
+
+#if HAVE_CONFIG_H
+#include
+#endif
+
+#ifdef WORDS_BIGENDIAN
+#define ELF_SHORT_H
+#define ELF_LONG_H
+#else
+/* Load a short int from the following tables with big-endian formats */
+#define ELF_SHORT_H(ps) ((((unsigned short)(ps) >> 8) & 0xff) |\
+ (((unsigned short)(ps) << 8) & 0xff00))
+
+/* Load a long int from the following tables with big-endian formats */
+#define ELF_LONG_H(ps) ((((unsigned long)(ps) >> 24) & 0xff) |\
+ (((unsigned long)(ps) >> 8) & 0xff00)|\
+ (((unsigned long)(ps) << 8) & 0xff0000)|\
+ (((unsigned long)(ps) << 24) & 0xff000000))
+#endif
+
+typedef unsigned long Elf32_Addr;
+typedef unsigned short Elf32_Half;
+typedef unsigned long Elf32_Off;
+typedef long Elf32_Sword;
+typedef unsigned long Elf32_Word;
+
+/* These constants are for the segment types stored in the image headers */
+#define PT_NULL 0
+#define PT_LOAD 1
+#define PT_DYNAMIC 2
+#define PT_INTERP 3
+#define PT_NOTE 4
+#define PT_SHLIB 5
+#define PT_PHDR 6
+#define PT_LOPROC 0x70000000
+#define PT_HIPROC 0x7fffffff
+
+/* These constants define the different elf file types */
+#define ET_NONE 0
+#define ET_REL 1
+#define ET_EXEC 2
+#define ET_DYN 3
+#define ET_CORE 4
+#define ET_LOPROC 5
+#define ET_HIPROC 6
+
+/* These constants define the various ELF target machines */
+#define EM_NONE 0
+#define EM_M32 1
+#define EM_SPARC 2
+#define EM_386 3
+#define EM_68K 4
+#define EM_88K 5
+#define EM_486 6 /* Perhaps disused */
+#define EM_860 7
+
+#define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */
+
+#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */
+
+#define EM_SPARC64 11 /* SPARC v9 (not official) 64-bit */
+
+#define EM_PARISC 15 /* HPPA */
+
+#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
+
+#define EM_PPC 20 /* PowerPC */
+
+/*
+ * This is an interim value that we will use until the committee comes
+ * up with a final number.
+ */
+#define EM_ALPHA 0x9026
+
+
+/* This is the info that is needed to parse the dynamic section of the file */
+#define DT_NULL 0
+#define DT_NEEDED 1
+#define DT_PLTRELSZ 2
+#define DT_PLTGOT 3
+#define DT_HASH 4
+#define DT_STRTAB 5
+#define DT_SYMTAB 6
+#define DT_RELA 7
+#define DT_RELASZ 8
+#define DT_RELAENT 9
+#define DT_STRSZ 10
+#define DT_SYMENT 11
+#define DT_INIT 12
+#define DT_FINI 13
+#define DT_SONAME 14
+#define DT_RPATH 15
+#define DT_SYMBOLIC 16
+#define DT_REL 17
+#define DT_RELSZ 18
+#define DT_RELENT 19
+#define DT_PLTREL 20
+#define DT_DEBUG 21
+#define DT_TEXTREL 22
+#define DT_JMPREL 23
+#define DT_LOPROC 0x70000000
+#define DT_HIPROC 0x7fffffff
+
+/* This info is needed when parsing the symbol table */
+#define STB_LOCAL 0
+#define STB_GLOBAL 1
+#define STB_WEAK 2
+
+#define STT_NOTYPE 0
+#define STT_OBJECT 1
+#define STT_FUNC 2
+#define STT_SECTION 3
+#define STT_FILE 4
+
+#define ELF32_ST_BIND(x) ((x) >> 4)
+#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf)
+
+/* Symbolic values for the entries in the auxiliary table
+ put on the initial stack */
+#define AT_NULL 0 /* end of vector */
+#define AT_IGNORE 1 /* entry should be ignored */
+#define AT_EXECFD 2 /* file descriptor of program */
+#define AT_PHDR 3 /* program headers for program */
+#define AT_PHENT 4 /* size of program header entry */
+#define AT_PHNUM 5 /* number of program headers */
+#define AT_PAGESZ 6 /* system page size */
+#define AT_BASE 7 /* base address of interpreter */
+#define AT_FLAGS 8 /* flags */
+#define AT_ENTRY 9 /* entry point of program */
+#define AT_NOTELF 10 /* program is not ELF */
+#define AT_UID 11 /* real uid */
+#define AT_EUID 12 /* effective uid */
+#define AT_GID 13 /* real gid */
+#define AT_EGID 14 /* effective gid */
+
+
+typedef struct dynamic{
+ Elf32_Sword d_tag;
+ union{
+ Elf32_Sword d_val;
+ Elf32_Addr d_ptr;
+ } d_un;
+} Elf32_Dyn;
+
+typedef struct {
+ unsigned long long d_tag; /* entry tag value */
+ union {
+ unsigned long long d_val;
+ unsigned long long d_ptr;
+ } d_un;
+} Elf64_Dyn;
+
+/* The following are used with relocations */
+#define ELF32_R_SYM(x) ((x) >> 8)
+#define ELF32_R_TYPE(x) ((x) & 0xff)
+
+#define R_386_NONE 0
+#define R_386_32 1
+#define R_386_PC32 2
+#define R_386_GOT32 3
+#define R_386_PLT32 4
+#define R_386_COPY 5
+#define R_386_GLOB_DAT 6
+#define R_386_JMP_SLOT 7
+#define R_386_RELATIVE 8
+#define R_386_GOTOFF 9
+#define R_386_GOTPC 10
+#define R_386_NUM 11
+
+#define R_68K_NONE 0
+#define R_68K_32 1
+#define R_68K_16 2
+#define R_68K_8 3
+#define R_68K_PC32 4
+#define R_68K_PC16 5
+#define R_68K_PC8 6
+#define R_68K_GOT32 7
+#define R_68K_GOT16 8
+#define R_68K_GOT8 9
+#define R_68K_GOT32O 10
+#define R_68K_GOT16O 11
+#define R_68K_GOT8O 12
+#define R_68K_PLT32 13
+#define R_68K_PLT16 14
+#define R_68K_PLT8 15
+#define R_68K_PLT32O 16
+#define R_68K_PLT16O 17
+#define R_68K_PLT8O 18
+#define R_68K_COPY 19
+#define R_68K_GLOB_DAT 20
+#define R_68K_JMP_SLOT 21
+#define R_68K_RELATIVE 22
+
+typedef struct elf32_rel {
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+} Elf32_Rel;
+
+typedef struct elf64_rel {
+ unsigned long long r_offset; /* Location at which to apply the action */
+ unsigned long long r_info; /* index and type of relocation */
+} Elf64_Rel;
+
+typedef struct elf32_rela{
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+ Elf32_Sword r_addend;
+} Elf32_Rela;
+
+typedef struct elf64_rela {
+ unsigned long long r_offset; /* Location at which to apply the action */
+ unsigned long long r_info; /* index and type of relocation */
+ unsigned long long r_addend; /* Constant addend used to compute value */
+} Elf64_Rela;
+
+typedef struct elf32_sym{
+ Elf32_Word st_name;
+ Elf32_Addr st_value;
+ Elf32_Word st_size;
+ unsigned char st_info;
+ unsigned char st_other;
+ Elf32_Half st_shndx;
+} Elf32_Sym;
+
+typedef struct elf64_sym {
+ unsigned int st_name; /* Symbol name, index in string tbl */
+ unsigned char st_info; /* Type and binding attributes */
+ unsigned char st_other; /* No defined meaning, 0 */
+ unsigned short st_shndx; /* Associated section index */
+ unsigned long long st_value; /* Value of the symbol */
+ unsigned long long st_size; /* Associated symbol size */
+} Elf64_Sym;
+
+
+#define EI_NIDENT 16
+
+typedef struct elf32_hdr{
+ unsigned char e_ident[EI_NIDENT];
+ Elf32_Half e_type;
+ Elf32_Half e_machine;
+ Elf32_Word e_version;
+ Elf32_Addr e_entry; /* Entry point */
+ Elf32_Off e_phoff;
+ Elf32_Off e_shoff;
+ Elf32_Word e_flags;
+ Elf32_Half e_ehsize;
+ Elf32_Half e_phentsize;
+ Elf32_Half e_phnum;
+ Elf32_Half e_shentsize;
+ Elf32_Half e_shnum;
+ Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+typedef struct elf64_hdr {
+ unsigned char e_ident[16]; /* ELF "magic number" */
+ short int e_type;
+ short unsigned int e_machine;
+ int e_version;
+ unsigned long long e_entry; /* Entry point virtual address */
+ unsigned long long e_phoff; /* Program header table file offset */
+ unsigned long long e_shoff; /* Section header table file offset */
+ int e_flags;
+ short int e_ehsize;
+ short int e_phentsize;
+ short int e_phnum;
+ short int e_shentsize;
+ short int e_shnum;
+ short int e_shstrndx;
+} Elf64_Ehdr;
+
+/* These constants define the permissions on sections in the program
+ header, p_flags. */
+#define PF_R 0x4
+#define PF_W 0x2
+#define PF_X 0x1
+
+typedef struct elf32_phdr{
+ Elf32_Word p_type;
+ Elf32_Off p_offset;
+ Elf32_Addr p_vaddr;
+ Elf32_Addr p_paddr;
+ Elf32_Word p_filesz;
+ Elf32_Word p_memsz;
+ Elf32_Word p_flags;
+ Elf32_Word p_align;
+} Elf32_Phdr;
+
+typedef struct elf64_phdr {
+ int p_type;
+ int p_flags;
+ unsigned long long p_offset; /* Segment file offset */
+ unsigned long long p_vaddr; /* Segment virtual address */
+ unsigned long long p_paddr; /* Segment physical address */
+ unsigned long long p_filesz; /* Segment size in file */
+ unsigned long long p_memsz; /* Segment size in memory */
+ unsigned long long p_align; /* Segment alignment, file & memory */
+} Elf64_Phdr;
+
+/* sh_type */
+#define SHT_NULL 0
+#define SHT_PROGBITS 1
+#define SHT_SYMTAB 2
+#define SHT_STRTAB 3
+#define SHT_RELA 4
+#define SHT_HASH 5
+#define SHT_DYNAMIC 6
+#define SHT_NOTE 7
+#define SHT_NOBITS 8
+#define SHT_REL 9
+#define SHT_SHLIB 10
+#define SHT_DYNSYM 11
+#define SHT_NUM 12
+#define SHT_LOPROC 0x70000000
+#define SHT_HIPROC 0x7fffffff
+#define SHT_LOUSER 0x80000000
+#define SHT_HIUSER 0xffffffff
+
+/* sh_flags */
+#define SHF_WRITE 0x1
+#define SHF_ALLOC 0x2
+#define SHF_EXECINSTR 0x4
+#define SHF_MASKPROC 0xf0000000
+
+/* special section indexes */
+#define SHN_UNDEF 0
+#define SHN_LORESERVE 0xff00
+#define SHN_LOPROC 0xff00
+#define SHN_HIPROC 0xff1f
+#define SHN_ABS 0xfff1
+#define SHN_COMMON 0xfff2
+#define SHN_HIRESERVE 0xffff
+
+typedef struct elf32_shdr {
+ Elf32_Word sh_name;
+ Elf32_Word sh_type;
+ Elf32_Word sh_flags;
+ Elf32_Addr sh_addr;
+ Elf32_Off sh_offset;
+ Elf32_Word sh_size;
+ Elf32_Word sh_link;
+ Elf32_Word sh_info;
+ Elf32_Word sh_addralign;
+ Elf32_Word sh_entsize;
+} Elf32_Shdr;
+
+typedef struct elf64_shdr {
+ unsigned int sh_name; /* Section name, index in string tbl */
+ unsigned int sh_type; /* Type of section */
+ unsigned long long sh_flags; /* Miscellaneous section attributes */
+ unsigned long long sh_addr; /* Section virtual addr at execution */
+ unsigned long long sh_offset; /* Section file offset */
+ unsigned long long sh_size; /* Size of section in bytes */
+ unsigned int sh_link; /* Index of another section */
+ unsigned int sh_info; /* Additional section information */
+ unsigned long long sh_addralign; /* Section alignment */
+ unsigned long long sh_entsize; /* Entry size if section holds table */
+} Elf64_Shdr;
+
+#define EI_MAG0 0 /* e_ident[] indexes */
+#define EI_MAG1 1
+#define EI_MAG2 2
+#define EI_MAG3 3
+#define EI_CLASS 4
+#define EI_DATA 5
+#define EI_VERSION 6
+#define EI_PAD 7
+
+#define ELFMAG0 0x7f /* EI_MAG */
+#define ELFMAG1 'E'
+#define ELFMAG2 'L'
+#define ELFMAG3 'F'
+#define ELFMAG "\177ELF"
+#define SELFMAG 4
+
+#define ELFCLASSNONE 0 /* EI_CLASS */
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+#define ELFCLASSNUM 3
+
+#define ELFDATANONE 0 /* e_ident[EI_DATA] */
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+
+#define EV_NONE 0 /* e_version, EI_VERSION */
+#define EV_CURRENT 1
+#define EV_NUM 2
+
+/* Notes used in ET_CORE */
+#define NT_PRSTATUS 1
+#define NT_PRFPREG 2
+#define NT_PRPSINFO 3
+#define NT_TASKSTRUCT 4
+
+/* Note header in a PT_NOTE section */
+typedef struct elf32_note {
+ Elf32_Word n_namesz; /* Name size */
+ Elf32_Word n_descsz; /* Content size */
+ Elf32_Word n_type; /* Content type */
+} Elf32_Nhdr;
+
+/* Note header in a PT_NOTE section */
+/*
+ * For now we use the 32 bit version of the structure until we figure
+ * out whether we need anything better. Note - on the Alpha, "unsigned int"
+ * is only 32 bits.
+ */
+typedef struct elf64_note {
+ unsigned int n_namesz; /* Name size */
+ unsigned int n_descsz; /* Content size */
+ unsigned int n_type; /* Content type */
+} Elf64_Nhdr;
+
+#ifdef __mc68000__
+#define ELF_START_MMAP 0xC0000000
+#endif
+#ifdef __i386__
+#define ELF_START_MMAP 0x80000000
+#endif
+
+#if ELF_CLASS == ELFCLASS32
+
+extern Elf32_Dyn _DYNAMIC [];
+#define elfhdr elf32_hdr
+#define elf_phdr elf32_phdr
+#define elf_note elf32_note
+
+#else
+
+extern Elf64_Dyn _DYNAMIC [];
+#define elfhdr elf64_hdr
+#define elf_phdr elf64_phdr
+#define elf_note elf64_note
+
+#endif
+
+
+#endif /* _LINUX_ELF_H */
Index: Makefile.am
===================================================================
--- Makefile.am (nonexistent)
+++ Makefile.am (revision 1765)
@@ -0,0 +1,22 @@
+# Makefile -- Makefile for cpu architecture independent simulation
+# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+#
+# This file is part of OpenRISC 1000 Architectural Simulator.
+#
+# This program 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.
+#
+# This program 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 this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+noinst_LIBRARIES = libcommon.a
+libcommon_a_SOURCES = abstract.c parse.c stats.c trace.c labels.c
Index: .
===================================================================
--- . (nonexistent)
+++ . (revision 1765)
.
Property changes :
Added: svn:ignore
## -0,0 +1,2 ##
+Makefile
+.deps