URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/or1k/tags/stable_0_2_0_rc2/or1ksim/cpu/common
- from Rev 1611 to Rev 1765
- ↔ Reverse comparison
Rev 1611 → Rev 1765
/abstract.c
0,0 → 1,1081
/* 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 = NULL; |
|
/* These are set by mmu if cache inhibit bit is set for current acces. */ |
int data_ci, insn_ci; |
|
/* Virtual address of current access. */ |
static oraddr_t cur_vadd; |
|
/* Read functions */ |
uint32_t eval_mem_32_inv(oraddr_t, void *); |
uint16_t eval_mem_16_inv(oraddr_t, void *); |
uint8_t eval_mem_8_inv(oraddr_t, void *); |
uint32_t eval_mem_32_inv_direct(oraddr_t, void *); |
uint16_t eval_mem_16_inv_direct(oraddr_t, void *); |
uint8_t eval_mem_8_inv_direct(oraddr_t, void *); |
|
/* Write functions */ |
void set_mem_32_inv(oraddr_t, uint32_t, void *); |
void set_mem_16_inv(oraddr_t, uint16_t, void *); |
void set_mem_8_inv(oraddr_t, uint8_t, void *); |
void set_mem_32_inv_direct(oraddr_t, uint32_t, void *); |
void set_mem_16_inv_direct(oraddr_t, uint16_t, void *); |
void set_mem_8_inv_direct(oraddr_t, uint8_t, void *); |
|
/* Calculates bit mask to fit the data */ |
static 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.) */ |
struct dev_memarea *register_memoryarea_mask(oraddr_t addr_mask, |
oraddr_t addr_compare, |
uint32_t size, unsigned mc_dev) |
{ |
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"\n", |
addr_mask, addr_compare, addr_compare | bit_mask (size), size); |
/* 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"\n", |
addr_mask, addr_compare, addr_compare | bit_mask (size), size); |
} |
found_error = 1; |
fprintf (stderr, "and\taddr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR |
", size %08"PRIx32"\n", |
(*pptmp)->addr_mask, (*pptmp)->addr_compare, |
(*pptmp)->addr_compare | (*pptmp)->size_mask, (*pptmp)->size); |
} |
|
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)->log = NULL; |
(*pptmp)->valid = 1; |
(*pptmp)->next = NULL; |
|
return *pptmp; |
} |
|
/* 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 device will be checked first for a match |
and will be accessed in case of overlaping memory areas. |
Only one device can have this set to 1 (used for memory controller) */ |
struct dev_memarea *reg_mem_area(oraddr_t addr, uint32_t size, unsigned mc_dev, |
struct mem_ops *ops) |
{ |
unsigned int size_mask = bit_mask (size); |
unsigned int addr_mask = ~size_mask; |
struct dev_memarea *mem; |
|
mem = register_memoryarea_mask(addr_mask, addr & addr_mask, size_mask + 1, |
mc_dev); |
|
memcpy(&mem->ops, ops, sizeof(struct mem_ops)); |
memcpy(&mem->direct_ops, ops, sizeof(struct mem_ops)); |
|
if(!ops->readfunc32) { |
mem->ops.readfunc32 = eval_mem_32_inv; |
mem->direct_ops.readfunc32 = eval_mem_32_inv_direct; |
mem->direct_ops.read_dat32 = mem; |
} |
if(!ops->readfunc16) { |
mem->ops.readfunc16 = eval_mem_16_inv; |
mem->direct_ops.readfunc16 = eval_mem_16_inv_direct; |
mem->direct_ops.read_dat16 = mem; |
} |
if(!ops->readfunc8) { |
mem->ops.readfunc8 = eval_mem_8_inv; |
mem->direct_ops.readfunc8 = eval_mem_8_inv_direct; |
mem->direct_ops.read_dat8 = mem; |
} |
|
if(!ops->writefunc32) { |
mem->ops.writefunc32 = set_mem_32_inv; |
mem->direct_ops.writefunc32 = set_mem_32_inv_direct; |
mem->direct_ops.write_dat32 = mem; |
} |
if(!ops->writefunc16) { |
mem->ops.writefunc16 = set_mem_16_inv; |
mem->direct_ops.writefunc16 = set_mem_16_inv_direct; |
mem->direct_ops.write_dat16 = mem; |
} |
if(!ops->writefunc8) { |
mem->ops.writefunc8 = set_mem_8_inv; |
mem->direct_ops.writefunc8 = set_mem_8_inv_direct; |
mem->direct_ops.write_dat8 = mem; |
} |
|
if(!ops->writeprog8) { |
mem->ops.writeprog8 = mem->ops.writefunc8; |
mem->ops.writeprog8_dat = mem->ops.write_dat8; |
} |
|
if(!ops->writeprog32) { |
mem->ops.writeprog32 = mem->ops.writefunc32; |
mem->ops.writeprog32_dat = mem->ops.write_dat32; |
} |
|
if(ops->log) { |
if(!(mem->log = fopen(ops->log, "w"))) |
PRINTF("ERR: Unable to open %s to log memory acesses to\n", ops->log); |
} |
|
return mem; |
} |
|
/* 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; |
} |
|
/* Sets the valid bit (Used only by memory controllers) */ |
void set_mem_valid(struct dev_memarea *mem, int valid) |
{ |
mem->valid = valid; |
} |
|
/* Adjusts the read and write delays for the memory area pointed to by mem. */ |
void adjust_rw_delay(struct dev_memarea *mem, int delayr, int delayw) |
{ |
mem->ops.delayr = delayr; |
mem->ops.delayw = delayw; |
} |
|
uint8_t eval_mem_8_inv(oraddr_t memaddr, void *dat) |
{ |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} |
|
uint16_t eval_mem_16_inv(oraddr_t memaddr, void *dat) |
{ |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} |
|
uint32_t eval_mem_32_inv(oraddr_t memaddr, void *dat) |
{ |
except_handle(EXCEPT_BUSERR, cur_vadd); |
return 0; |
} |
|
void set_mem_8_inv(oraddr_t memaddr, uint8_t val, void *dat) |
{ |
except_handle(EXCEPT_BUSERR, cur_vadd); |
} |
|
void set_mem_16_inv(oraddr_t memaddr, uint16_t val, void *dat) |
{ |
except_handle(EXCEPT_BUSERR, cur_vadd); |
} |
|
void set_mem_32_inv(oraddr_t memaddr, uint32_t val, void *dat) |
{ |
except_handle(EXCEPT_BUSERR, cur_vadd); |
} |
|
uint8_t eval_mem_8_inv_direct(oraddr_t memaddr, void *dat) |
{ |
struct dev_memarea *mem = dat; |
|
PRINTF("ERROR: Invalid 8-bit direct read from memory %"PRIxADDR"\n", |
mem->addr_compare | memaddr); |
return 0; |
} |
|
uint16_t eval_mem_16_inv_direct(oraddr_t memaddr, void *dat) |
{ |
struct dev_memarea *mem = dat; |
|
PRINTF("ERROR: Invalid 16-bit direct read from memory %"PRIxADDR"\n", |
mem->addr_compare | memaddr); |
return 0; |
} |
|
uint32_t eval_mem_32_inv_direct(oraddr_t memaddr, void *dat) |
{ |
struct dev_memarea *mem = dat; |
|
PRINTF("ERROR: Invalid 32-bit direct read from memory %"PRIxADDR"\n", |
mem->addr_compare | memaddr); |
return 0; |
} |
|
void set_mem_8_inv_direct(oraddr_t memaddr, uint8_t val, void *dat) |
{ |
struct dev_memarea *mem = dat; |
|
PRINTF("ERROR: Invalid 32-bit direct write to memory %"PRIxADDR"\n", |
mem->addr_compare | memaddr); |
} |
|
void set_mem_16_inv_direct(oraddr_t memaddr, uint16_t val, void *dat) |
{ |
struct dev_memarea *mem = dat; |
|
PRINTF("ERROR: Invalid 16-bit direct write to memory %"PRIxADDR"\n", |
mem->addr_compare | memaddr); |
} |
|
void set_mem_32_inv_direct(oraddr_t memaddr, uint32_t val, void *dat) |
{ |
struct dev_memarea *mem = dat; |
|
PRINTF("ERROR: Invalid 32-bit direct write to memory %"PRIxADDR"\n", |
mem->addr_compare | memaddr); |
} |
|
/* For cpu accesses |
* |
* NOTE: This function _is_ only called from eval_mem32 below and |
* {i,d}c_simulate_read. _Don't_ call it from anywere else. |
*/ |
inline uint32_t evalsim_mem32(oraddr_t memaddr, oraddr_t vaddr) |
{ |
struct dev_memarea *mem; |
|
if((mem = verify_memoryarea(memaddr))) { |
runtime.sim.mem_cycles += mem->ops.delayr; |
return mem->ops.readfunc32(memaddr & mem->size_mask, mem->ops.read_dat32); |
} else { |
PRINTF("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, vaddr); |
} |
|
return 0; |
} |
|
/* For cpu accesses |
* |
* NOTE: This function _is_ only called from eval_mem16 below and |
* {i,d}c_simulate_read. _Don't_ call it from anywere else. |
*/ |
inline uint16_t evalsim_mem16(oraddr_t memaddr, oraddr_t vaddr) |
{ |
struct dev_memarea *mem; |
|
if((mem = verify_memoryarea(memaddr))) { |
runtime.sim.mem_cycles += mem->ops.delayr; |
return mem->ops.readfunc16(memaddr & mem->size_mask, mem->ops.read_dat16); |
} else { |
PRINTF("EXCEPTION: read out of memory (16-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, vaddr); |
} |
|
return 0; |
} |
|
/* For cpu accesses |
* |
* NOTE: This function _is_ only called from eval_mem8 below and |
* {i,d}c_simulate_read. _Don't_ call it from anywere else. |
*/ |
inline uint8_t evalsim_mem8(oraddr_t memaddr, oraddr_t vaddr) |
{ |
struct dev_memarea *mem; |
|
if((mem = verify_memoryarea(memaddr))) { |
runtime.sim.mem_cycles += mem->ops.delayr; |
return mem->ops.readfunc8(memaddr & mem->size_mask, mem->ops.read_dat8); |
} else { |
PRINTF("EXCEPTION: read out of memory (8-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, vaddr); |
} |
|
return 0; |
} |
|
/* 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; |
oraddr_t phys_memaddr; |
|
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 */ |
|
phys_memaddr = dmmu_translate(memaddr, 0); |
if (except_pending) |
return 0; |
|
if (config.dc.enabled) |
temp = dc_simulate_read(phys_memaddr, memaddr, 4); |
else |
temp = evalsim_mem32(phys_memaddr, memaddr); |
|
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 through_mmu, int through_dc) |
{ |
oraddr_t phys_memaddr; |
struct dev_memarea *mem; |
|
if (memaddr & 3) { |
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__); |
return 0; |
} |
|
phys_memaddr = memaddr; |
|
if (through_mmu) |
phys_memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
|
if (through_dc) |
return dc_simulate_read(phys_memaddr, memaddr, 4); |
else { |
if((mem = verify_memoryarea(phys_memaddr))) |
return mem->direct_ops.readfunc32(phys_memaddr & mem->size_mask, |
mem->direct_ops.read_dat32); |
else |
PRINTF("ERR: 32-bit read out of memory area: %"PRIxADDR" (physical: %" |
PRIxADDR"\n", memaddr, phys_memaddr); |
} |
|
return 0; |
} |
|
|
/* 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; |
oraddr_t phys_memaddr; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_32 | MPROF_FETCH); |
// memaddr = simulate_ic_mmu_fetch(memaddr); |
|
phys_memaddr = memaddr; |
#if !(DYNAMIC_EXECUTION) |
phys_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(phys_memaddr, memaddr); |
else |
temp = evalsim_mem32(phys_memaddr, memaddr); |
|
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 through_mmu) |
{ |
if(through_mmu) |
memaddr = peek_into_itlb(memaddr); |
|
return eval_direct32(memaddr, 0, 0); |
} |
|
|
/* 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; |
oraddr_t phys_memaddr; |
|
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 */ |
|
phys_memaddr = dmmu_translate(memaddr, 0); |
if (except_pending) |
return 0; |
|
if (config.dc.enabled) |
temp = dc_simulate_read(phys_memaddr, memaddr, 2); |
else |
temp = evalsim_mem16(phys_memaddr, memaddr); |
|
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 through_mmu, int through_dc) |
{ |
oraddr_t phys_memaddr; |
struct dev_memarea *mem; |
|
if (memaddr & 1) { |
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__); |
return 0; |
} |
|
phys_memaddr = memaddr; |
|
if (through_mmu) |
phys_memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
|
if (through_dc) |
return dc_simulate_read(phys_memaddr, memaddr, 2); |
else { |
if((mem = verify_memoryarea(phys_memaddr))) |
return mem->direct_ops.readfunc16(phys_memaddr & mem->size_mask, |
mem->direct_ops.read_dat16); |
else |
PRINTF("ERR: 16-bit read out of memory area: %"PRIxADDR" (physical: %" |
PRIxADDR"\n", memaddr, phys_memaddr); |
} |
|
return 0; |
} |
|
/* 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; |
oraddr_t phys_memaddr; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_8 | MPROF_READ); |
|
if (config.debug.enabled) |
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */ |
|
phys_memaddr = dmmu_translate(memaddr, 0); |
if (except_pending) |
return 0; |
|
if (config.dc.enabled) |
temp = dc_simulate_read(phys_memaddr, memaddr, 1); |
else |
temp = evalsim_mem8(phys_memaddr, memaddr); |
|
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 through_mmu, int through_dc) |
{ |
oraddr_t phys_memaddr; |
struct dev_memarea *mem; |
|
phys_memaddr = memaddr; |
|
if (through_mmu) |
phys_memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
|
if (through_dc) |
return dc_simulate_read(phys_memaddr, memaddr, 1); |
else { |
if((mem = verify_memoryarea(phys_memaddr))) |
return mem->direct_ops.readfunc8(phys_memaddr & mem->size_mask, |
mem->direct_ops.read_dat8); |
else |
PRINTF("ERR: 8-bit read out of memory area: %"PRIxADDR" (physical: %" |
PRIxADDR"\n", memaddr, phys_memaddr); |
} |
|
return 0; |
} |
|
/* For cpu accesses |
* |
* NOTE: This function _is_ only called from set_mem32 below and |
* dc_simulate_write. _Don't_ call it from anywere else. |
*/ |
inline void setsim_mem32(oraddr_t memaddr, oraddr_t vaddr, uint32_t value) |
{ |
struct dev_memarea *mem; |
|
if((mem = verify_memoryarea(memaddr))) { |
cur_vadd = vaddr; |
runtime.sim.mem_cycles += mem->ops.delayw; |
mem->ops.writefunc32(memaddr & mem->size_mask, value, mem->ops.write_dat32); |
#if DYNAMIC_EXECUTION |
dyn_checkwrite(memaddr); |
#endif |
} else { |
PRINTF("EXCEPTION: write out of memory (32-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, vaddr); |
} |
} |
|
/* For cpu accesses |
* |
* NOTE: This function _is_ only called from set_mem16 below and |
* dc_simulate_write. _Don't_ call it from anywere else. |
*/ |
inline void setsim_mem16(oraddr_t memaddr, oraddr_t vaddr, uint16_t value) |
{ |
struct dev_memarea *mem; |
|
if((mem = verify_memoryarea(memaddr))) { |
cur_vadd = vaddr; |
runtime.sim.mem_cycles += mem->ops.delayw; |
mem->ops.writefunc16(memaddr & mem->size_mask, value, mem->ops.write_dat16); |
#if DYNAMIC_EXECUTION |
dyn_checkwrite(memaddr); |
#endif |
} else { |
PRINTF("EXCEPTION: write out of memory (16-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, vaddr); |
} |
} |
|
/* For cpu accesses |
* |
* NOTE: This function _is_ only called from set_mem8 below and |
* dc_simulate_write. _Don't_ call it from anywere else. |
*/ |
inline void setsim_mem8(oraddr_t memaddr, oraddr_t vaddr, uint8_t value) |
{ |
struct dev_memarea *mem; |
|
if((mem = verify_memoryarea(memaddr))) { |
cur_vadd = vaddr; |
runtime.sim.mem_cycles += mem->ops.delayw; |
mem->ops.writefunc8(memaddr & mem->size_mask, value, mem->ops.write_dat8); |
#if DYNAMIC_EXECUTION |
dyn_checkwrite(memaddr); |
#endif |
} else { |
PRINTF("EXCEPTION: write out of memory (8-bit access to %"PRIxADDR")\n", |
memaddr); |
except_handle(EXCEPT_BUSERR, vaddr); |
} |
} |
|
/* 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) |
{ |
oraddr_t phys_memaddr; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_32 | MPROF_WRITE); |
|
if (memaddr & 3) { |
except_handle (EXCEPT_ALIGN, memaddr); |
return; |
} |
|
phys_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); |
} |
|
if(config.dc.enabled) |
dc_simulate_write(phys_memaddr, memaddr, value, 4); |
else |
setsim_mem32(phys_memaddr, memaddr, value); |
|
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 through_mmu, |
int through_dc) |
{ |
oraddr_t phys_memaddr; |
struct dev_memarea *mem; |
|
if (memaddr & 3) { |
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__); |
return; |
} |
|
phys_memaddr = memaddr; |
|
if (through_mmu) { |
/* 0 - no write access, we do not want a DPF exception do we ;) |
*/ |
phys_memaddr = peek_into_dtlb(memaddr, 1, through_dc); |
} |
|
if(through_dc) |
dc_simulate_write(memaddr, memaddr, value, 4); |
else { |
if((mem = verify_memoryarea(phys_memaddr))) |
mem->direct_ops.writefunc32(phys_memaddr & mem->size_mask, value, |
mem->direct_ops.write_dat32); |
else |
PRINTF("ERR: 32-bit write out of memory area: %"PRIxADDR" (physical: %" |
PRIxADDR")\n", memaddr, phys_memaddr); |
} |
|
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) |
{ |
oraddr_t phys_memaddr; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_16 | MPROF_WRITE); |
|
if (memaddr & 1) { |
except_handle (EXCEPT_ALIGN, memaddr); |
return; |
} |
|
phys_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); |
} |
|
if(config.dc.enabled) |
dc_simulate_write(phys_memaddr, memaddr, value, 2); |
else |
setsim_mem16(phys_memaddr, memaddr, value); |
|
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 through_mmu, |
int through_dc) |
{ |
oraddr_t phys_memaddr; |
struct dev_memarea *mem; |
|
if (memaddr & 1) { |
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__); |
return; |
} |
|
phys_memaddr = memaddr; |
|
if (through_mmu) { |
/* 0 - no write access, we do not want a DPF exception do we ;) |
*/ |
phys_memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
} |
|
if(through_dc) |
dc_simulate_write(memaddr, memaddr, value, 2); |
else { |
if((mem = verify_memoryarea(phys_memaddr))) |
mem->direct_ops.writefunc16(phys_memaddr & mem->size_mask, value, |
mem->direct_ops.write_dat16); |
else |
PRINTF("ERR: 16-bit write out of memory area: %"PRIxADDR" (physical: %" |
PRIxADDR"\n", memaddr, phys_memaddr); |
} |
|
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) |
{ |
oraddr_t phys_memaddr; |
|
if (config.sim.mprofile) |
mprofile (memaddr, MPROF_8 | MPROF_WRITE); |
|
phys_memaddr = memaddr; |
|
phys_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); |
} |
|
if(config.dc.enabled) |
dc_simulate_write(phys_memaddr, memaddr, value, 1); |
else |
setsim_mem8(phys_memaddr, memaddr, value); |
|
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 through_mmu, |
int through_dc) |
{ |
oraddr_t phys_memaddr; |
struct dev_memarea *mem; |
|
phys_memaddr = memaddr; |
|
if (through_mmu) { |
/* 0 - no write access, we do not want a DPF exception do we ;) |
*/ |
phys_memaddr = peek_into_dtlb(memaddr, 0, through_dc); |
} |
|
if(through_dc) |
dc_simulate_write(phys_memaddr, memaddr, value, 1); |
else { |
if((mem = verify_memoryarea(phys_memaddr))) |
mem->direct_ops.writefunc8(phys_memaddr & mem->size_mask, value, |
mem->direct_ops.write_dat8); |
else |
PRINTF("ERR: 8-bit write out of memory area: %"PRIxADDR" (physical: %" |
PRIxADDR"\n", memaddr, phys_memaddr); |
} |
|
if (cur_area && cur_area->log) |
fprintf (cur_area->log, "[%"PRIxADDR"] -> DIRECT write %02"PRIx8"\n", |
memaddr, value); |
} |
|
|
/* set_program32 - same as set_direct32, but it also writes to memory that is |
* non-writeable to the rest of the sim. Used to do program |
* loading. |
*/ |
void set_program32(oraddr_t memaddr, uint32_t value) |
{ |
struct dev_memarea *mem; |
|
if(memaddr & 3) { |
PRINTF("%s(): ERR unaligned 32-bit program write\n", __FUNCTION__); |
return; |
} |
|
if((mem = verify_memoryarea(memaddr))) { |
mem->ops.writeprog32(memaddr & mem->size_mask, value, |
mem->ops.writeprog32_dat); |
} else |
PRINTF("ERR: 32-bit program load out of memory area: %"PRIxADDR"\n", |
memaddr); |
} |
|
/* set_program8 - same as set_direct8, but it also writes to memory that is |
* non-writeable to the rest of the sim. Used to do program |
* loading. |
*/ |
void set_program8(oraddr_t memaddr, uint8_t value) |
{ |
struct dev_memarea *mem; |
|
if((mem = verify_memoryarea(memaddr))) { |
mem->ops.writeprog8(memaddr & mem->size_mask, value, |
mem->ops.writeprog8_dat); |
} else |
PRINTF("ERR: 8-bit program load out of memory area: %"PRIxADDR"\n", |
memaddr); |
} |
|
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) { |
|
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("\n%"PRIxADDR": ", i); |
PRINTF("\n<%s>:\n", entry->name); |
PRINTF("%"PRIxADDR": ", i); |
} else { |
PRINTF("%"PRIxADDR": ", i); |
} |
|
PRINTF("%02"PRIx8" ", eval_direct8(i + j, 0, 0)); |
} else PRINTF("XX "); |
j++; |
} else { |
uint32_t _insn = eval_direct32(i, 0, 0); |
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("\n%"PRIxADDR": ", i); |
PRINTF("<%s>:\n", entry->name); |
PRINTF("%"PRIxADDR": ", i); |
} else { |
PRINTF("%"PRIxADDR": ", i); |
} |
|
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"); |
} |
} |
|
/* Closes files, etc. */ |
|
void done_memory_table (void) |
{ |
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 (void) |
{ |
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"\n", |
ptmp->addr_mask, ptmp->addr_compare, ptmp->addr_compare | bit_mask (ptmp->size), |
ptmp->size); |
PRINTF ("\t"); |
if (ptmp->ops.delayr >= 0) |
PRINTF ("read delay = %i cycles, ", ptmp->ops.delayr); |
else |
PRINTF ("reads not possible, "); |
|
if (ptmp->ops.delayw >= 0) |
PRINTF ("write delay = %i cycles", ptmp->ops.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; |
} |
/Makefile.in
0,0 → 1,424
# Makefile.in generated by automake 1.9.5 from Makefile.am. |
# @configure_input@ |
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
# 2003, 2004, 2005 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. |
# |
|
SOURCES = $(libcommon_a_SOURCES) |
|
srcdir = @srcdir@ |
top_srcdir = @top_srcdir@ |
VPATH = @srcdir@ |
pkgdatadir = $(datadir)/@PACKAGE@ |
pkglibdir = $(libdir)/@PACKAGE@ |
pkgincludedir = $(includedir)/@PACKAGE@ |
top_builddir = ../.. |
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd |
INSTALL = @INSTALL@ |
install_sh_DATA = $(install_sh) -c -m 644 |
install_sh_PROGRAM = $(install_sh) -c |
install_sh_SCRIPT = $(install_sh) -c |
INSTALL_HEADER = $(INSTALL_DATA) |
transform = $(program_transform_name) |
NORMAL_INSTALL = : |
PRE_INSTALL = : |
POST_INSTALL = : |
NORMAL_UNINSTALL = : |
PRE_UNINSTALL = : |
POST_UNINSTALL = : |
build_triplet = @build@ |
host_triplet = @host@ |
target_triplet = @target@ |
subdir = cpu/common |
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in |
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 |
am__aclocal_m4_deps = $(top_srcdir)/configure.in |
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ |
$(ACLOCAL_M4) |
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs |
CONFIG_HEADER = $(top_builddir)/config.h |
CONFIG_CLEAN_FILES = |
LIBRARIES = $(noinst_LIBRARIES) |
libcommon_a_AR = $(AR) $(ARFLAGS) |
libcommon_a_LIBADD = |
am_libcommon_a_OBJECTS = abstract.$(OBJEXT) parse.$(OBJEXT) \ |
stats.$(OBJEXT) trace.$(OBJEXT) labels.$(OBJEXT) |
libcommon_a_OBJECTS = $(am_libcommon_a_OBJECTS) |
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) |
depcomp = $(SHELL) $(top_srcdir)/depcomp |
am__depfiles_maybe = depfiles |
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ |
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) |
CCLD = $(CC) |
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ |
SOURCES = $(libcommon_a_SOURCES) |
DIST_SOURCES = $(libcommon_a_SOURCES) |
ETAGS = etags |
CTAGS = ctags |
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
ACLOCAL = @ACLOCAL@ |
AMDEP_FALSE = @AMDEP_FALSE@ |
AMDEP_TRUE = @AMDEP_TRUE@ |
AMTAR = @AMTAR@ |
AR = @AR@ |
ARFLAGS = @ARFLAGS@ |
AUTOCONF = @AUTOCONF@ |
AUTOHEADER = @AUTOHEADER@ |
AUTOMAKE = @AUTOMAKE@ |
AWK = @AWK@ |
BUILD_DIR = @BUILD_DIR@ |
CC = @CC@ |
CCDEPMODE = @CCDEPMODE@ |
CFLAGS = @CFLAGS@ |
CPP = @CPP@ |
CPPFLAGS = @CPPFLAGS@ |
CPU_ARCH = @CPU_ARCH@ |
CYGPATH_W = @CYGPATH_W@ |
DEFS = @DEFS@ |
DEPDIR = @DEPDIR@ |
DYNAMIC_EXECUTION_FALSE = @DYNAMIC_EXECUTION_FALSE@ |
DYNAMIC_EXECUTION_TRUE = @DYNAMIC_EXECUTION_TRUE@ |
ECHO_C = @ECHO_C@ |
ECHO_N = @ECHO_N@ |
ECHO_T = @ECHO_T@ |
EGREP = @EGREP@ |
EXEEXT = @EXEEXT@ |
GENERATE_NEEDED_FALSE = @GENERATE_NEEDED_FALSE@ |
GENERATE_NEEDED_TRUE = @GENERATE_NEEDED_TRUE@ |
INCLUDES = @INCLUDES@ |
INSTALL_DATA = @INSTALL_DATA@ |
INSTALL_PROGRAM = @INSTALL_PROGRAM@ |
INSTALL_SCRIPT = @INSTALL_SCRIPT@ |
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ |
LDFLAGS = @LDFLAGS@ |
LIBOBJS = @LIBOBJS@ |
LIBS = @LIBS@ |
LOCAL_CFLAGS = @LOCAL_CFLAGS@ |
LOCAL_DEFS = @LOCAL_DEFS@ |
LOCAL_LDFLAGS = @LOCAL_LDFLAGS@ |
LTLIBOBJS = @LTLIBOBJS@ |
MAKEINFO = @MAKEINFO@ |
MAKE_SHELL = @MAKE_SHELL@ |
OBJEXT = @OBJEXT@ |
PACKAGE = @PACKAGE@ |
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ |
PACKAGE_NAME = @PACKAGE_NAME@ |
PACKAGE_STRING = @PACKAGE_STRING@ |
PACKAGE_TARNAME = @PACKAGE_TARNAME@ |
PACKAGE_VERSION = @PACKAGE_VERSION@ |
PATH_SEPARATOR = @PATH_SEPARATOR@ |
RANLIB = @RANLIB@ |
SET_MAKE = @SET_MAKE@ |
SHELL = @SHELL@ |
STRIP = @STRIP@ |
SUMVERSION = @SUMVERSION@ |
TERMCAP_LIB = @TERMCAP_LIB@ |
VERSION = @VERSION@ |
ac_ct_CC = @ac_ct_CC@ |
ac_ct_RANLIB = @ac_ct_RANLIB@ |
ac_ct_STRIP = @ac_ct_STRIP@ |
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ |
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ |
am__include = @am__include@ |
am__leading_dot = @am__leading_dot@ |
am__quote = @am__quote@ |
am__tar = @am__tar@ |
am__untar = @am__untar@ |
bindir = @bindir@ |
build = @build@ |
build_alias = @build_alias@ |
build_cpu = @build_cpu@ |
build_os = @build_os@ |
build_vendor = @build_vendor@ |
datadir = @datadir@ |
exec_prefix = @exec_prefix@ |
host = @host@ |
host_alias = @host_alias@ |
host_cpu = @host_cpu@ |
host_os = @host_os@ |
host_vendor = @host_vendor@ |
includedir = @includedir@ |
infodir = @infodir@ |
install_sh = @install_sh@ |
libdir = @libdir@ |
libexecdir = @libexecdir@ |
localstatedir = @localstatedir@ |
mandir = @mandir@ |
mkdir_p = @mkdir_p@ |
oldincludedir = @oldincludedir@ |
prefix = @prefix@ |
program_transform_name = @program_transform_name@ |
sbindir = @sbindir@ |
sharedstatedir = @sharedstatedir@ |
sysconfdir = @sysconfdir@ |
target = @target@ |
target_alias = @target_alias@ |
target_cpu = @target_cpu@ |
target_os = @target_os@ |
target_vendor = @target_vendor@ |
noinst_LIBRARIES = libcommon.a |
libcommon_a_SOURCES = abstract.c parse.c stats.c trace.c labels.c |
all: all-am |
|
.SUFFIXES: |
.SUFFIXES: .c .o .obj |
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) |
@for dep in $?; do \ |
case '$(am__configure_deps)' in \ |
*$$dep*) \ |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ |
&& exit 0; \ |
exit 1;; \ |
esac; \ |
done; \ |
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu cpu/common/Makefile'; \ |
cd $(top_srcdir) && \ |
$(AUTOMAKE) --gnu cpu/common/Makefile |
.PRECIOUS: Makefile |
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status |
@case '$?' in \ |
*config.status*) \ |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ |
*) \ |
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ |
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ |
esac; |
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh |
|
$(top_srcdir)/configure: $(am__configure_deps) |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh |
$(ACLOCAL_M4): $(am__aclocal_m4_deps) |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh |
|
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) |
|
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@ |
|
.c.o: |
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ |
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
@am__fastdepCC_FALSE@ $(COMPILE) -c $< |
|
.c.obj: |
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ |
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` |
uninstall-info-am: |
|
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: TAGS |
|
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; }'`; \ |
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ |
test -n "$$unique" || unique=$$empty_fix; \ |
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ |
$$tags $$unique; \ |
fi |
ctags: CTAGS |
CTAGS: $(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 "$(CTAGS_ARGS)$$tags$$unique" \ |
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_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 tags |
|
distdir: $(DISTFILES) |
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ |
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ |
list='$(DISTFILES)'; for file in $$list; do \ |
case $$file in \ |
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ |
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ |
esac; \ |
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"; \ |
$(mkdir_p) "$(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_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ |
`test -z '$(STRIP)' || \ |
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install |
mostlyclean-generic: |
|
clean-generic: |
|
distclean-generic: |
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(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 |
-rm -rf ./$(DEPDIR) |
-rm -f Makefile |
distclean-am: clean-am distclean-compile distclean-generic \ |
distclean-tags |
|
dvi: dvi-am |
|
dvi-am: |
|
html: html-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 |
-rm -rf ./$(DEPDIR) |
-rm -f Makefile |
maintainer-clean-am: distclean-am maintainer-clean-generic |
|
mostlyclean: mostlyclean-am |
|
mostlyclean-am: mostlyclean-compile mostlyclean-generic |
|
pdf: pdf-am |
|
pdf-am: |
|
ps: ps-am |
|
ps-am: |
|
uninstall-am: uninstall-info-am |
|
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ |
clean-noinstLIBRARIES ctags distclean distclean-compile \ |
distclean-generic distclean-tags distdir dvi dvi-am html \ |
html-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 pdf pdf-am ps ps-am 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: |
/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; /* 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 (cpu_state.sprs[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 (cpu_state.sprs[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 |
} |
/parse.c
0,0 → 1,710
/* 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 <stdio.h> |
#include <ctype.h> |
#include <string.h> |
#include <stdlib.h> |
|
#include "config.h" |
|
#ifdef HAVE_INTTYPES_H |
#include <inttypes.h> |
#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)) == eval_direct32(transl_table + i, 0, 0)) { |
/* Page modified */ |
set_direct32(transl_table + i + 8, -2, 0, 0); |
PRINTF("found paddr=%"PRIx32"\n", |
eval_direct32(transl_table + i + 4, 0, 0) | |
(laddr & (PAGE_SIZE - 1))); |
return (oraddr_t)eval_direct32(transl_table + i + 4, 0, 0) | |
(laddr & (oraddr_t)(PAGE_SIZE - 1)); |
} |
|
/* Allocate new phy page for us. */ |
for(i = 0; i < (MEMORY_LEN / PAGE_SIZE) * 16; i += 16) |
if (eval_direct32(transl_table + i + 8, 0, 0) == 0) { |
/* VPN */ |
set_direct32(transl_table + i, laddr & ~(PAGE_SIZE - 1), 0, 0); |
/* PPN */ |
set_direct32(transl_table + i + 4, (i/16) * PAGE_SIZE, 0, 0); |
/* Page modified */ |
set_direct32(transl_table + i + 8, -2, 0, 0); |
PRINTF("newly allocated ppn=%"PRIx32"\n", |
eval_direct32(transl_table + i + 4, 0, 0)); |
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", |
eval_direct32(transl_table + i + 4, 0, 0) | |
(laddr & (PAGE_SIZE - 1))); |
return (oraddr_t)eval_direct32(transl_table + i + 4, 0, 0) | |
(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); |
|
/* We can't have set_program32 functions since it is not gauranteed that the |
* section we're loading is aligned on a 4-byte boundry */ |
set_program8 (vaddr, (insn >> 24) & 0xff); |
set_program8 (vaddr + 1, (insn >> 16) & 0xff); |
set_program8 (vaddr + 2, (insn >> 8) & 0xff); |
set_program8 (vaddr + 3, insn & 0xff); |
#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 = NULL; |
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); |
|
} |
/abstract.h
0,0 → 1,178
/* abstract.h -- 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; |
}; |
|
struct mem_ops { |
/* Read functions */ |
uint32_t (*readfunc32)(oraddr_t, void *); |
uint16_t (*readfunc16)(oraddr_t, void *); |
uint8_t (*readfunc8)(oraddr_t, void *); |
|
/* Read functions' data */ |
void *read_dat8; |
void *read_dat16; |
void *read_dat32; |
|
/* Write functions */ |
void (*writefunc32)(oraddr_t, uint32_t, void *); |
void (*writefunc16)(oraddr_t, uint16_t, void *); |
void (*writefunc8)(oraddr_t, uint8_t, void *); |
|
/* Write functions' data */ |
void *write_dat8; |
void *write_dat16; |
void *write_dat32; |
|
/* Program load function. If you have unwritteable memory but you would like |
* it if a program would be loaded here, make sure to set this. If this is |
* not set, then writefunc8 will be called to load the program */ |
void (*writeprog32)(oraddr_t, uint32_t, void *); |
void (*writeprog8)(oraddr_t, uint8_t, void *); |
|
void *writeprog32_dat; |
void *writeprog8_dat; |
|
/* Read/Write delays */ |
int delayr; |
int delayw; |
|
/* Name of log file */ |
const char *log; |
}; |
|
/* Memory regions assigned to devices */ |
struct dev_memarea { |
struct dev_memarea *next; |
oraddr_t addr_mask; |
oraddr_t addr_compare; |
uint32_t size; |
oraddr_t size_mask; /* Address mask, calculated out of size */ |
|
int valid; /* This bit reflects the memory controler valid bit */ |
FILE *log; /* log file if this device is to be logged, NULL otherwise */ |
|
struct mem_ops ops; |
struct mem_ops direct_ops; |
}; |
|
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, oraddr_t); |
uint16_t evalsim_mem16(oraddr_t, oraddr_t); |
uint8_t evalsim_mem8(oraddr_t, oraddr_t); |
|
void setsim_mem32(oraddr_t, oraddr_t, uint32_t); |
void setsim_mem16(oraddr_t, oraddr_t, uint16_t); |
void setsim_mem8(oraddr_t, oraddr_t, uint8_t); |
|
/* Closes files, etc. */ |
void done_memory_table (void); |
|
/* Displays current memory configuration */ |
void memory_table_status (void); |
|
/* Register memory area */ |
struct dev_memarea *reg_mem_area(oraddr_t addr, uint32_t size, unsigned mc_dev, |
struct mem_ops *ops); |
|
/* Adjusts the read and write delays for the memory area pointed to by mem. */ |
void adjust_rw_delay(struct dev_memarea *mem, int delayr, int delayw); |
|
/* Sets the valid bit (Used only by memory controllers) */ |
void set_mem_valid(struct dev_memarea *mem, int valid); |
|
/* 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 through_mmu); |
|
uint8_t eval_direct8(oraddr_t memaddr, int through_mmu, int through_dc); |
uint16_t eval_direct16(oraddr_t memaddr, int through_mmu, int through_dc); |
uint32_t eval_direct32(oraddr_t addr, int through_mmu, int through_dc); |
|
void set_direct8(oraddr_t, uint8_t, int, int); |
void set_direct16(oraddr_t, uint16_t, int, int); |
void set_direct32(oraddr_t, uint32_t, int, int); |
|
/* Same as set_direct32, but it also writes to memory that is non-writeable to |
* the rest of the sim. Used to do program loading. */ |
void set_program32(oraddr_t memaddr, uint32_t value); |
void set_program8(oraddr_t memaddr, uint8_t value); |
|
/* Temporary variable to increase speed. */ |
extern struct dev_memarea *cur_area; |
|
/* 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 */ |
|
/* Returns the page that addr belongs to */ |
#define IADDR_PAGE(addr) ((addr) & config.immu.page_mask) |
#define DADDR_PAGE(addr) ((addr) & config.dmmu.page_mask) |
|
/* 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; |
/execute.h
0,0 → 1,85
/* 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; |
|
/* Pointers to recompiled pages */ |
struct dyn_page **dyn_pages; |
|
/* Micro operation queue. Only used to speed up recompile_page */ |
struct op_queue *opqs; |
|
/* 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); |
/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.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(); |
/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: 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