OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/tags/nog_patch_52/or1ksim/cpu/common
    from Rev 1429 to Rev 1765
    Reverse comparison

Rev 1429 → Rev 1765

/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 "sprs.h"
#include "spr_defs.h"
#include "execute.h"
#include "opcode/or32.h"
#include "debug.h"
#include "stats.h"
 
struct branchstat {
int taken;
int nottaken;
int forward;
int backward;
};
 
/* See also enum insn_type in abstract.h */
const char func_unit_str[30][30] = { "unknown", "exception", "arith", "shift", "compare",
"branch", "jump", "load", "store", "movimm", "move", "extend", "nop", "mac" };
 
struct dstats_entry dstats[DSTATS_LEN]; /* dependency stats */
struct sstats_entry sstats[SSTATS_LEN]; /* single stats */
struct fstats_entry fstats[FSTATS_LEN]; /* functional units stats */
struct mstats_entry or1k_mstats = {0}; /* misc units stats */
struct cachestats_entry ic_stats = {0}; /* instruction cache stats */
struct cachestats_entry dc_stats = {0}; /* data cache stats */
struct immustats_entry immu_stats = {0}; /* insn mmu stats */
struct dmmustats_entry dmmu_stats = {0}; /* data mmu stats */
struct raw_stats raw_stats = {0}; /* RAW hazard stats */
 
void addsstats(int item, int cnt_dynamic)
{
int i = 0;
while(sstats[i].insn != item && sstats[i].insn >= 0 && i < SSTATS_LEN) i++;
 
if (i >= SSTATS_LEN - 1) return;
if (sstats[i].insn >= 0) {
sstats[i].cnt_dynamic += cnt_dynamic;
} else {
sstats[i].insn = item;
sstats[i].cnt_dynamic = cnt_dynamic;
}
}
 
void adddstats(int item1, int item2, int cnt_dynamic, int depend)
{
int i = 0;
debug(7,"adddstats start\n");
 
while((dstats[i].insn1 != item1 || dstats[i].insn2 != item2) && (i < DSTATS_LEN) && dstats[i].insn1 >= 0) i++;
 
if (i >= DSTATS_LEN - 1) return;
if (dstats[i].insn1 >= 0) {
dstats[i].cnt_dynamic += cnt_dynamic;
dstats[i].depend += depend;
} else {
dstats[i].insn1 = item1;
dstats[i].insn2 = item2;
dstats[i].cnt_dynamic = cnt_dynamic;
dstats[i].depend = depend;
}
}
 
void addfstats(enum insn_type item1, enum insn_type item2, int cnt_dynamic, int depend)
{
int i = 0;
while(((fstats[i].insn1 != item1) || (fstats[i].insn2 != item2)) &&
(fstats[i].insn1 != it_unknown) &&
(i < FSTATS_LEN))
i++;
 
if (i >= FSTATS_LEN - 1) return;
if ((fstats[i].insn1 == item1) &&
(fstats[i].insn2 == item2)) {
fstats[i].cnt_dynamic += cnt_dynamic;
fstats[i].depend += depend;
}
else {
fstats[i].insn1 = item1;
fstats[i].insn2 = item2;
fstats[i].cnt_dynamic = cnt_dynamic;
fstats[i].depend = depend;
}
}
 
void initstats()
{
int i;
memset(sstats, 0, sizeof(sstats));
for (i = 0; i < SSTATS_LEN; i++)
sstats[i].insn = -1;
memset(dstats, 0, sizeof(dstats));
for (i = 0; i < DSTATS_LEN; i++)
dstats[i].insn1 = dstats[i].insn2 = -1;
memset(fstats, 0, sizeof(fstats));
memset(&or1k_mstats, 0, sizeof(or1k_mstats));
memset(&ic_stats, 0, sizeof(ic_stats));
memset(&dc_stats, 0, sizeof(dc_stats));
memset(&raw_stats, 0, sizeof(raw_stats));
}
 
void printotherstats(int which)
{
PRINTF ("\n");
if (config.bpb.enabled) {
struct branchstat bf;
struct branchstat bnf;
long bf_all, bnf_all;
bf.taken = or1k_mstats.bf[1][0] + or1k_mstats.bf[1][1];
bf.nottaken = or1k_mstats.bf[0][0] + or1k_mstats.bf[0][1];
bf.forward = or1k_mstats.bf[0][1] + or1k_mstats.bf[1][1];
bf.backward = or1k_mstats.bf[0][0] + or1k_mstats.bf[1][0];
bf_all = bf.forward + bf.backward;
bnf.taken = or1k_mstats.bnf[1][0] + or1k_mstats.bf[1][1];
bnf.nottaken = or1k_mstats.bnf[0][0] + or1k_mstats.bf[0][1];
bnf.forward = or1k_mstats.bnf[0][1] + or1k_mstats.bf[1][1];
bnf.backward = or1k_mstats.bnf[0][0] + or1k_mstats.bf[1][0];
bnf_all = bnf.forward + bnf.backward;
PRINTF("bnf: %d (%ld%%) taken,", bf.taken, (bf.taken * 100) / SD(bf_all));
PRINTF(" %d (%ld%%) not taken,", bf.nottaken, (bf.nottaken * 100) / SD(bf_all));
PRINTF(" %d (%ld%%) forward,", bf.forward, (bf.forward * 100) / SD(bf_all));
PRINTF(" %d (%ld%%) backward\n", bf.backward, (bf.backward * 100) / SD(bf_all));
PRINTF("bf: %d (%ld%%) taken,", bnf.taken, (bnf.taken * 100) / SD(bnf_all));
PRINTF(" %d (%ld%%) not taken,", bnf.nottaken, (bnf.nottaken * 100) / SD(bnf_all));
PRINTF(" %d (%ld%%) forward,", bnf.forward, (bnf.forward * 100) / SD(bnf_all));
PRINTF(" %d (%ld%%) backward\n", bnf.backward, (bnf.backward * 100) / SD(bnf_all));
PRINTF("StaticBP bnf(%s): correct %ld%%\n", config.bpb.sbp_bnf_fwd ? "forward" : "backward",
(or1k_mstats.bnf[0][config.bpb.sbp_bnf_fwd] * 100) / SD(bnf_all));
PRINTF("StaticBP bf(%s): correct %ld%%\n", config.bpb.sbp_bf_fwd ? "forward" : "backward",
(or1k_mstats.bnf[1][config.bpb.sbp_bf_fwd] * 100) / SD(bf_all));
PRINTF("BPB: hit %d (correct %d%%), miss %d\n", or1k_mstats.bpb.hit, (or1k_mstats.bpb.correct * 100) / SD(or1k_mstats.bpb.hit), or1k_mstats.bpb.miss);
} else
PRINTF("BPB simulation disabled. Enable it to see BPB analysis\n");
 
if (config.bpb.btic) {
PRINTF("BTIC: hit %d(%d%%), miss %d\n", or1k_mstats.btic.hit, (or1k_mstats.btic.hit * 100) / SD(or1k_mstats.btic.hit + or1k_mstats.btic.miss), or1k_mstats.btic.miss);
} else
PRINTF("BTIC simulation disabled. Enabled it to see BTIC analysis\n");
 
if (config.ic.enabled) {
PRINTF("IC read: hit %d(%d%%), miss %d\n", ic_stats.readhit, (ic_stats.readhit * 100) / SD(ic_stats.readhit + ic_stats.readmiss), ic_stats.readmiss);
} else
PRINTF("No ICache. Enable it to see IC results.\n");
if (config.dc.enabled) {
PRINTF("DC read: hit %d(%d%%), miss %d\n", dc_stats.readhit, (dc_stats.readhit * 100) / SD(dc_stats.readhit + dc_stats.readmiss), dc_stats.readmiss);
PRINTF("DC write: hit %d(%d%%), miss %d\n", dc_stats.writehit, (dc_stats.writehit * 100) / SD(dc_stats.writehit + dc_stats.writemiss), dc_stats.writemiss);
} else
PRINTF("No DCache. Enable it to see DC results.\n");
 
if (testsprbits(SPR_UPR, SPR_UPR_IMP)) {
PRINTF("IMMU read: hit %d(%d%%), miss %d\n", immu_stats.fetch_tlbhit, (immu_stats.fetch_tlbhit * 100) / SD(immu_stats.fetch_tlbhit + immu_stats.fetch_tlbmiss), immu_stats.fetch_tlbmiss);
} else
PRINTF("No IMMU. Set UPR[IMP]\n");
 
if (testsprbits(SPR_UPR, SPR_UPR_DMP)) {
PRINTF("DMMU read: hit %d(%d%%), miss %d\n", dmmu_stats.loads_tlbhit, (dmmu_stats.loads_tlbhit * 100) / SD(dmmu_stats.loads_tlbhit + dmmu_stats.loads_tlbmiss), dmmu_stats.loads_tlbmiss);
} else
PRINTF("No DMMU. Set UPR[DMP]\n");
PRINTF("Additional LOAD CYCLES: %u STORE CYCLES: %u\n", runtime.sim.loadcycles, runtime.sim.storecycles);
}
 
void printstats(int which)
{
int i, all = 0, dependall = 0;
 
if (which > 1 && which <= 5 && !config.cpu.dependstats) {
PRINTF("Hazard analysis disabled. Enable it to see analysis results.\n");
return;
}
 
switch (which) {
case 1:
PRINTF("stats 1: Misc stats\n");
printotherstats(which);
break;
case 2:
PRINTF ("stats 2: Instruction usage\n");
for(i = 0; i < SSTATS_LEN; i++)
all += sstats[i].cnt_dynamic;
for(i = 0; i < SSTATS_LEN; i++)
if (sstats[i].cnt_dynamic)
PRINTF(" %-15s used %6dx (%5.1f%%)\n", insn_name(sstats[i].insn), sstats[i].cnt_dynamic, (sstats[i].cnt_dynamic * 100.)/SD(all));
PRINTF("%d instructions (dynamic, single stats)\n", all);
break;
case 3:
PRINTF ("stats 3: Instruction dependencies\n");
for(i = 0; i < DSTATS_LEN; i++) {
all += dstats[i].cnt_dynamic;
dependall += dstats[i].depend;
}
for(i = 0; i < DSTATS_LEN; i++)
if (dstats[i].cnt_dynamic) {
char temp[100];
sprintf(temp, "%s, %s ", insn_name(dstats[i].insn1), insn_name(dstats[i].insn2));
PRINTF(" %-30s %6dx (%5.1f%%)", temp, dstats[i].cnt_dynamic, (dstats[i].cnt_dynamic * 100.)/SD(all));
PRINTF(" depend: %5.1f%%\n", (dstats[i].depend * 100.) / dstats[i].cnt_dynamic);
}
PRINTF("%d instructions (dynamic, dependency stats) depend: %d%%\n", all, (dependall * 100) / SD(all));
break;
case 4:
PRINTF("stats 4: Functional units dependencies\n");
for(i = 0; i < FSTATS_LEN; i++) {
all += fstats[i].cnt_dynamic;
dependall += fstats[i].depend;
}
for(i = 0; i < FSTATS_LEN; i++)
if (fstats[i].cnt_dynamic) {
char temp[100];
sprintf(temp, "%s, %s", func_unit_str[fstats[i].insn1], func_unit_str[fstats[i].insn2]);
PRINTF(" %-30s %6dx (%5.1f%%)", temp, fstats[i].cnt_dynamic, (fstats[i].cnt_dynamic * 100.)/SD(all));
PRINTF(" depend: %5.1f%%\n", (fstats[i].depend * 100.) / fstats[i].cnt_dynamic);
}
PRINTF ("%d instructions (dynamic, functional units stats) depend: %d%%\n\n", all, (dependall * 100) / SD(all));
break;
case 5:
PRINTF("stats 5: Raw register usage over time\n");
#if RAW_RANGE_STATS
for(i = 0; (i < MAX_RANGE); i++)
PRINTF(" Register set and reused in %d. cycle: %d cases\n", i, raw_stats.range[i]);
#endif
break;
case 6:
if (config.cpu.sbuf_len) {
extern int sbuf_total_cyc, sbuf_wait_cyc;
PRINTF ("stats 6: Store buffer analysis\n");
PRINTF ("Using store buffer of length %i.\n", config.cpu.sbuf_len);
PRINTF ("Number of total memory store cycles: %i/%lli\n", sbuf_total_cyc,
runtime.sim.cycles + sbuf_total_cyc - sbuf_wait_cyc);
PRINTF ("Number of cycles waiting for memory stores: %i\n", sbuf_wait_cyc);
PRINTF ("Number of memory cycles spared: %i\n", sbuf_total_cyc - sbuf_wait_cyc);
PRINTF ("Store speedup %3.2f%%, total speedup %3.2f%%\n", 100.*(sbuf_total_cyc - sbuf_wait_cyc)/sbuf_total_cyc,
100.*(sbuf_total_cyc - sbuf_wait_cyc) / (runtime.sim.cycles + sbuf_total_cyc - sbuf_wait_cyc));
} else
PRINTF ("Store buffer analysis disabled. Enable it to see analysis results.\n");
break;
default:
PRINTF ("Please specify a stats group (1-6).\n");
break;
}
#if 0
PRINTF("Byte ADD: %d instructions\n", or1k_mstats.byteadd);
#endif
}
/stats.h
0,0 → 1,109
/* stats.h -- Header file for stats.c
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#define DSTATS_LEN 3000
#define SSTATS_LEN 300
#define FSTATS_LEN 200
#define RAW_RANGE 1000
 
/* Used by safe division - increment divisor by one if it is zero */
#define SD(X) (X != 0 ? X : 1)
 
struct dstats_entry {
int insn1;
int insn2;
int cnt_dynamic;
int depend;
};
 
struct sstats_entry {
int insn;
int cnt_dynamic;
}; /* single stats */
 
struct fstats_entry {
enum insn_type insn1;
enum insn_type insn2;
int cnt_dynamic;
int depend;
}; /* functional units stats */
 
struct bpbstat {
int hit;
int miss;
int correct;
int incorrect;
};
 
struct bticstat {
int hit;
int miss;
};
 
struct mstats_entry {
int byteadd;
int bf[2][2]; /* [taken][fwd/bwd] */
int bnf[2][2]; /* [taken][fwd/bwd] */
struct bpbstat bpb;
struct bticstat btic;
}; /* misc units stats */
 
struct cachestats_entry {
int readhit;
int readmiss;
int writehit;
int writemiss;
}; /* cache stats */
 
struct immustats_entry {
int fetch_tlbhit;
int fetch_tlbmiss;
int fetch_pagefaults;
}; /* IMMU stats */
 
struct dmmustats_entry {
int loads_tlbhit;
int loads_tlbmiss;
int loads_pagefaults;
int stores_tlbhit;
int stores_tlbmiss;
int stores_pagefaults;
}; /* DMMU stats */
 
struct raw_stats {
int reg[64];
int range[RAW_RANGE];
}; /* RAW hazard stats */
 
/* Renamed mstats to or1k_mstats because Mac OS X has a lib function called mstats */
extern struct mstats_entry or1k_mstats;
extern struct sstats_entry sstats[SSTATS_LEN];
extern struct dstats_entry dstats[DSTATS_LEN];
extern struct fstats_entry fstats[FSTATS_LEN];
extern struct cachestats_entry ic_stats;
extern struct cachestats_entry dc_stats;
extern struct immustats_entry immu_stats;
extern struct dmmustats_entry dmmu_stats;
extern struct raw_stats raw_stats;
 
extern void addsstats(int item, int cnt_dynamic);
extern void adddstats(int item1, int item2, int cnt_dynamic, int depend);
extern void addfstats(enum insn_type item1, enum insn_type item2, int cnt_dynamic, int depend);
extern void initstats();
extern void printstats();
/abstract.h
0,0 → 1,175
/* abstract.c -- Abstract entities header file
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
#include <stdio.h>
 
#define DEFAULT_MEMORY_START 0
#define DEFAULT_MEMORY_LEN 0x800000
#define STACK_SIZE 20
#define LABELNAME_LEN 50
#define INSNAME_LEN 15
#define OPERANDNAME_LEN 50
 
#define MAX_OPERANDS (5)
 
#define OP_MEM_ACCESS 0x80000000
 
/* Cache tag types. */
#define CT_NONE 0
#define CT_VIRTUAL 1
#define CT_PHYSICAL 2
 
/* Instruction queue */
struct iqueue_entry {
int insn_index;
uint32_t insn;
oraddr_t insn_addr;
};
 
/* Memory regions assigned to devices */
struct dev_memarea {
struct dev_memarea *next;
/*unsigned long start;
unsigned long end;*/ /* if start + size > end, this block is disabled; to enable it recalculate end addr. */
oraddr_t addr_mask;
oraddr_t addr_compare;
uint32_t size;
uint32_t size_mask; /* Address mask, calculated out of size */
unsigned int granularity; /* how many bytes read/write accepts: 1/2/4 */
int delayr; /* Read delay */
int delayw; /* Write delay */
int chip_select; /* Needed by memory controller; specifies chip
* select number for this memory area. */
int valid; /* This bit reflect the memory controler valid bit */
FILE *log; /* log file if this device is to be logged, NULL otherwise */
 
uint32_t (*readfunc)(oraddr_t, void *);
void (*writefunc)(oraddr_t, uint32_t, void *);
/* private data */
void *priv_dat;
};
 
extern struct iqueue_entry iqueue[20];
extern struct iqueue_entry icomplet[20];
extern oraddr_t pc;
extern int mem_cycles; /* Number of memory cycles in during this instruction execution */
extern int cycles; /* Total number of cycles executed so far */
 
extern void dumpmemory(oraddr_t from, oraddr_t to, int disasm, int nl);
extern uint32_t eval_mem32(oraddr_t memaddr,int*);
extern uint16_t eval_mem16(oraddr_t memaddr,int*);
extern uint8_t eval_mem8(oraddr_t memaddr,int*);
void set_mem32(oraddr_t memaddr, uint32_t value,int*);
extern void set_mem16(oraddr_t memaddr, uint16_t value,int*);
extern void set_mem8(oraddr_t memaddr, uint8_t value,int*);
 
uint32_t evalsim_mem32(oraddr_t);
uint16_t evalsim_mem16(oraddr_t);
uint8_t evalsim_mem8(oraddr_t);
 
uint32_t evalsim_mem32_atomic(oraddr_t, int);
uint16_t evalsim_mem16_atomic(oraddr_t, int);
uint8_t evalsim_mem8_atomic(oraddr_t, int);
 
void setsim_mem32(oraddr_t, uint32_t);
void setsim_mem16(oraddr_t, uint16_t);
void setsim_mem8(oraddr_t, uint8_t);
 
void setsim_mem32_atomic(oraddr_t, uint32_t, int);
void setsim_mem16_atomic(oraddr_t, uint16_t, int);
void setsim_mem8_atomic(oraddr_t, uint8_t, int);
 
void init_memory_table ();
 
/* Changes read/write memory in read/write only */
void lock_memory_table ();
 
/* Closes files, etc. */
void done_memory_table ();
 
/* Displays current memory configuration */
void memory_table_status ();
 
/* Register read and write function for a memory area.
addr is inside the area, if addr & addr_mask == addr_compare
(used also by peripheral devices like 16450 UART etc.) */
void register_memoryarea_mask(oraddr_t addr_mask, oraddr_t addr_compare,
uint32_t size, unsigned granularity, unsigned mc_dev,
uint32_t (readfunc)(oraddr_t, void *),
void (writefunc)(oraddr_t, uint32_t, void *),
void *dat);
 
/* Register read and write function for a memory area.
Memory areas should be aligned. Memory area is rounded up to
fit the nearest 2^n aligment.
(used also by peripheral devices like 16450 UART etc.)
If mc_dev is 1, this means that this device will be checked first for match
and will be accessed in case in overlaping memory spaces.
Only one device can have this set to 1 (used for memory controller) */
void register_memoryarea(oraddr_t addr, uint32_t size, unsigned granularity,
unsigned mc_dev, uint32_t (readfunc)(oraddr_t, void *),
void (writefunc)(oraddr_t, uint32_t, void *),
void *dat);
 
/* Finds the memory area for the address and adjust the read and write delays for it. */
void adjust_rw_delay(oraddr_t memaddr, unsigned int delayr, unsigned int delayw);
 
/* Check if access is to registered area of memory. */
struct dev_memarea *verify_memoryarea(oraddr_t addr);
 
/* Outputs time in pretty form to dest string. */
char *generate_time_pretty (char *dest, long time_ps);
 
/* Returns 32-bit values from mem array. */
uint32_t eval_insn(oraddr_t, int *);
 
uint8_t eval_direct8(oraddr_t memaddr, int *breakpoint, int through_mmu, int through_dc);
uint16_t eval_direct16(oraddr_t memaddr, int *breakpoint, int through_mmu, int through_dc);
uint32_t eval_direct32(oraddr_t addr, int *breakpoint, int through_mmu, int through_dc);
 
void set_direct32(uint32_t addr, uint32_t value, int *breakpoint, int through_mmu, int through_dc);
 
/* Temporary variable to increase speed. */
extern struct dev_memarea *cur_area;
 
/* Virtual address of current access. */
extern oraddr_t cur_vadd;
 
/* These are set by mmu if cache inhibit bit is set for current acces. */
extern int data_ci, insn_ci;
 
/* Added by MM */
#ifndef LONGEST
#define LONGEST long long
#define ULONGEST unsigned long long
#endif /* ! LONGEST */
 
/* Instructions left to execute */
extern int cont_run;
 
/* 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;
/abstract.c
0,0 → 1,1144
/* 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 "execute.h"
#include "sprs.h"
#include "except.h"
#include "debug_unit.h"
#include "opcode/or32.h"
#include "support/profile.h"
#include "dmmu.h"
#include "dcache_model.h"
#include "icache_model.h"
#include "debug.h"
#include "stats.h"
 
extern char *disassembled;
 
/* Pointer to memory area descriptions that are assigned to individual
peripheral devices. */
struct dev_memarea *dev_list;
 
/* Temporary variable to increase speed. */
struct dev_memarea *cur_area;
 
/* Pointer to memory controller device descriptor. */
struct dev_memarea *mc_area = (struct dev_memarea *)0;
 
/* These are set by mmu if cache inhibit bit is set for current acces. */
int data_ci, insn_ci;
 
/* Virtual address of current access. */
oraddr_t cur_vadd;
 
/* Calculates bit mask to fit the data */
unsigned int bit_mask (uint32_t data) {
int i = 0;
data--;
while (data >> i)
data |= 1 << i++;
return data;
}
 
/* Register read and write function for a memory area.
addr is inside the area, if addr & addr_mask == addr_compare
(used also by peripheral devices like 16450 UART etc.) */
void register_memoryarea_mask(oraddr_t addr_mask, oraddr_t addr_compare,
uint32_t size, unsigned granularity, unsigned mc_dev,
uint32_t (readfunc)(oraddr_t, void *),
void (writefunc)(oraddr_t, uint32_t, void *),
void *dat)
{
struct dev_memarea **pptmp;
unsigned int size_mask = bit_mask (size);
int found_error = 0;
addr_compare &= addr_mask;
 
debug(5, "addr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR", size %08"PRIx32", gran %iB\n",
addr_mask, addr_compare, addr_compare | bit_mask (size), size,
granularity);
/* Go to the end of the list. */
for(pptmp = &dev_list; *pptmp; pptmp = &(*pptmp)->next)
if ((addr_compare >= (*pptmp)->addr_compare) && (addr_compare < (*pptmp)->addr_compare + (*pptmp)->size)
|| (addr_compare + size > (*pptmp)->addr_compare) && (addr_compare < (*pptmp)->addr_compare + (*pptmp)->size)) {
if (!found_error) {
fprintf (stderr, "ERROR: Overlapping memory area(s):\n");
fprintf (stderr, "\taddr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR
", size %08"PRIx32", gran %iB\n",
addr_mask, addr_compare, addr_compare | bit_mask (size), size,
granularity);
}
found_error = 1;
fprintf (stderr, "and\taddr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR
", size %08"PRIx32", gran %iB\n",
(*pptmp)->addr_mask, (*pptmp)->addr_compare,
(*pptmp)->addr_compare | (*pptmp)->size_mask,
(*pptmp)->size, (*pptmp)->granularity);
}
if (found_error)
exit (-1);
 
cur_area = *pptmp = (struct dev_memarea *)malloc(sizeof(struct dev_memarea));
 
if (mc_dev)
mc_area = *pptmp;
 
(*pptmp)->addr_mask = addr_mask;
(*pptmp)->addr_compare = addr_compare;
(*pptmp)->size = size;
(*pptmp)->size_mask = size_mask;
(*pptmp)->granularity = granularity;
(*pptmp)->readfunc = readfunc;
(*pptmp)->writefunc = writefunc;
(*pptmp)->log = 0;
(*pptmp)->delayr = 2;
(*pptmp)->delayw = 2;
(*pptmp)->priv_dat = dat;
(*pptmp)->chip_select = -1;
(*pptmp)->next = NULL;
}
 
/* Register read and write function for a memory area.
Memory areas should be aligned. Memory area is rounded up to
fit the nearest 2^n aligment.
(used also by peripheral devices like 16450 UART etc.)
If mc_dev is 1, this means that this device will be checked first for match
and will be accessed in case of overlaping memory spaces.
Only one device can have this set to 1 (used for memory controller) */
void register_memoryarea(oraddr_t addr, uint32_t size, unsigned granularity,
unsigned mc_dev,
uint32_t (readfunc)(oraddr_t, void *),
void (writefunc)(oraddr_t, uint32_t, void *),
void *dat)
{
unsigned int size_mask = bit_mask (size);
unsigned int addr_mask = ~size_mask;
register_memoryarea_mask (addr_mask, addr & addr_mask,
size_mask + 1, granularity, mc_dev,
readfunc, writefunc, dat);
}
 
 
/* Check if access is to registered area of memory. */
inline struct dev_memarea *verify_memoryarea(oraddr_t addr)
{
struct dev_memarea *ptmp;
 
/* Check memory controller space first */
if (mc_area && (addr & mc_area->addr_mask) == (mc_area->addr_compare & mc_area->addr_mask))
return cur_area = mc_area;
 
/* Check cached value */
if (cur_area && (addr & cur_area->addr_mask) == (cur_area->addr_compare & cur_area->addr_mask))
return cur_area;
 
/* When mc is enabled, we must check valid also, otherwise we assume it is nonzero */
/* Check list of registered devices. */
for(ptmp = dev_list; ptmp; ptmp = ptmp->next)
if ((addr & ptmp->addr_mask) == (ptmp->addr_compare & ptmp->addr_mask) && ptmp->valid)
return cur_area = ptmp;
return cur_area = NULL;
}
 
/* Finds the memory area for the address and adjust the read and write delays for it. */
void adjust_rw_delay(oraddr_t memaddr, unsigned int delayr, unsigned int delayw)
{
if (verify_memoryarea(memaddr)) {
cur_area->delayr = delayr;
cur_area->delayw = delayw;
}
}
 
/* for cpu accesses
*
* STATISTICS: check cpu/common/parse.c
*/
inline uint32_t evalsim_mem32(oraddr_t memaddr)
{
return(evalsim_mem32_atomic(memaddr, 1));
}
 
/* for simulator accesses, the ones that cpu wouldn't do */
inline uint32_t evalsim_mem32_void(oraddr_t memaddr)
{
return(evalsim_mem32_atomic(memaddr, 0));
}
 
uint32_t evalsim_mem32_atomic(oraddr_t memaddr, int cpu_access)
{
uint32_t temp = 0;
 
if (verify_memoryarea(memaddr)) {
switch(cur_area->granularity) {
case 4:
temp = cur_area->readfunc(memaddr, cur_area->priv_dat);
break;
case 1:
temp = cur_area->readfunc(memaddr, cur_area->priv_dat) << 24;
temp |= cur_area->readfunc(memaddr + 1, cur_area->priv_dat) << 16;
temp |= cur_area->readfunc(memaddr + 2, cur_area->priv_dat) << 8;
temp |= cur_area->readfunc(memaddr + 3, cur_area->priv_dat);
break;
case 2:
temp = cur_area->readfunc(memaddr, cur_area->priv_dat) << 16;
temp |= cur_area->readfunc(memaddr + 2, cur_area->priv_dat);
break;
default:
/* if you add new memory granularity be sure to check the formula
* below for the read delay and fix it if necessery
*/
PRINTF("unknown/unhandled memory granularuty\n");
exit(-1);
}
if (cpu_access)
runtime.sim.mem_cycles += cur_area->delayr * (4 / cur_area->granularity);
}
return temp;
}
 
/* for cpu accesses */
inline uint16_t evalsim_mem16(oraddr_t memaddr)
{
return(evalsim_mem16_atomic(memaddr, 1));
}
 
/* for simulator accesses, the ones that cpu wouldn't do */
inline uint16_t evalsim_mem16_void(oraddr_t memaddr)
{
return(evalsim_mem16_atomic(memaddr, 0));
}
 
uint16_t evalsim_mem16_atomic(oraddr_t memaddr, int cpu_access)
{
uint32_t temp = 0;
 
if (verify_memoryarea(memaddr)) {
switch(cur_area->granularity) {
case 1:
temp = cur_area->readfunc(memaddr, cur_area->priv_dat) << 8;
temp |= cur_area->readfunc(memaddr + 1, cur_area->priv_dat);
if (cpu_access)
runtime.sim.mem_cycles += cur_area->delayr * 2;
break;
case 2:
temp = cur_area->readfunc(memaddr, cur_area->priv_dat);
if (cpu_access)
runtime.sim.mem_cycles += cur_area->delayr;
break;
case 4:
temp = evalsim_mem32_atomic (memaddr & ~UINT32_C(3), cpu_access);
if (memaddr & 2)
temp &= 0xffff;
else
temp >>= 16;
break;
default:
/* if you add new memory granularity be sure to check the formula
* below for the read delay and fix it if necessery
*/
PRINTF("unknown/unhandled memory granularuty\n");
exit(-1);
}
}
return temp;
}
 
/* for cpu accesses */
inline uint8_t evalsim_mem8(oraddr_t memaddr)
{
return(evalsim_mem8_atomic(memaddr, 1));
}
 
/* for simulator accesses, the ones that cpu wouldn't do */
inline uint8_t evalsim_mem8_void(oraddr_t memaddr)
{
return(evalsim_mem8_atomic(memaddr, 0));
}
 
uint8_t evalsim_mem8_atomic(oraddr_t memaddr, int cpu_access)
{
uint32_t temp = 0;
 
if (verify_memoryarea(memaddr)) {
switch(cur_area->granularity) {
case 1:
temp = cur_area->readfunc(memaddr, cur_area->priv_dat);
if (cpu_access)
runtime.sim.mem_cycles += cur_area->delayr;
break;
case 2:
temp = evalsim_mem16_atomic (memaddr & ~ADDR_C(1), cpu_access);
if (memaddr & 1)
temp &= 0xff;
else
temp >>= 8;
break;
case 4:
temp = evalsim_mem32_atomic (memaddr & ~ADDR_C(3), cpu_access);
temp >>= 8 * (3 - (memaddr & 3));
temp &= 0xff;
break;
default:
/* if you add new memory granularity be sure to check the formula
* below for the read delay and fix it if necessery
*/
PRINTF("unknown/unhandled memory granularuty\n");
exit(-1);
}
}
return temp;
}
 
/* Returns 32-bit values from mem array. Big endian version.
*
* this function is only used in dumpmemory() below, so it's
* safe to asume it's for simulator purposes access only,
* hence the use of eval_mem32_void()
*
* STATISTICS OK.
*/
static uint32_t read_mem(oraddr_t memaddr, int* breakpoint)
{
uint32_t temp;
cur_vadd = memaddr;
if (config.debug.enabled)
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
temp = evalsim_mem32_void(memaddr);
if (!cur_area) {
PRINTF("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n",
memaddr);
except_handle(EXCEPT_BUSERR, cur_vadd);
temp = 0;
} else if (cur_area->log)
fprintf (cur_area->log, "[%"PRIxADDR"] -> read %08"PRIx32"\n", memaddr, temp);
 
if (config.debug.enabled)
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */
return temp;
}
 
/* Returns 32-bit values from mem array. Big endian version.
*
* STATISTICS OK (only used for cpu_access, that is architectural access)
*/
uint32_t eval_mem32(oraddr_t memaddr,int* breakpoint)
{
uint32_t temp;
 
if (config.sim.mprofile)
mprofile (memaddr, MPROF_32 | MPROF_READ);
 
if (memaddr & 3) {
except_handle (EXCEPT_ALIGN, memaddr);
return 0;
}
 
if (config.debug.enabled)
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
 
cur_vadd = memaddr;
 
memaddr = dmmu_translate(memaddr, 0);
if (except_pending)
return 0;
 
if (config.dc.enabled)
temp = dc_simulate_read(memaddr, 4);
else {
temp = evalsim_mem32(memaddr);
if (!cur_area) {
PRINTF("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n",
memaddr);
except_handle(EXCEPT_BUSERR, cur_vadd);
temp = 0;
}
}
 
if (config.debug.enabled)
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */
return temp;
}
 
/* for simulator accesses, the ones that cpu wouldn't do
*
* STATISTICS OK
*/
uint32_t eval_direct32(oraddr_t memaddr, int *breakpoint, int through_mmu,
int through_dc)
{
uint32_t temp;
 
if (memaddr & 3) {
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__);
return 0;
}
cur_vadd = memaddr;
 
if (through_mmu)
memaddr = peek_into_dtlb(memaddr, 0, through_dc);
 
if (through_dc)
temp = dc_simulate_read(memaddr, 4);
else {
temp = evalsim_mem32_void(memaddr);
if (!cur_area) {
PRINTF("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR
") in eval_direct32()\n", memaddr);
except_handle(EXCEPT_BUSERR, cur_vadd);
temp = 0;
}
}
return temp;
}
 
 
/* Returns 32-bit values from mem array. Big endian version.
*
* STATISTICS OK (only used for cpu_access, that is architectural access)
*/
uint32_t eval_insn(oraddr_t memaddr, int* breakpoint)
{
uint32_t temp;
 
if (config.sim.mprofile)
mprofile (memaddr, MPROF_32 | MPROF_FETCH);
// memaddr = simulate_ic_mmu_fetch(memaddr);
 
cur_vadd = memaddr;
 
memaddr = immu_translate(memaddr);
 
if (except_pending)
return 0;
 
if (config.debug.enabled)
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr);
 
if (config.ic.enabled)
temp = ic_simulate_fetch(memaddr);
else {
temp = evalsim_mem32(memaddr);
if (!cur_area) {
PRINTF("EXCEPTION: read out of memory (32-bit access to %"PRIxADDR")\n",
memaddr);
except_handle(EXCEPT_BUSERR, cur_vadd);
temp = 0;
}
}
 
if (config.debug.enabled)
*breakpoint += CheckDebugUnit(DebugLoadData,temp);
return temp;
}
 
/* Returns 16-bit values from mem array. Big endian version.
*
* STATISTICS OK (only used for cpu_access, that is architectural access)
*/
uint16_t eval_mem16(oraddr_t memaddr,int* breakpoint)
{
uint16_t temp;
if (config.sim.mprofile)
mprofile (memaddr, MPROF_16 | MPROF_READ);
 
if (memaddr & 1) {
except_handle (EXCEPT_ALIGN, memaddr);
return 0;
}
 
if (config.debug.enabled)
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
 
cur_vadd = memaddr;
 
memaddr = dmmu_translate(memaddr, 0);
if (except_pending)
return 0;
 
if (config.dc.enabled)
temp = (uint16_t)dc_simulate_read(memaddr, 2);
else {
temp = evalsim_mem16(memaddr);
if (!cur_area) {
PRINTF("EXCEPTION: read out of memory (16-bit access to %"PRIxADDR")\n",
memaddr);
except_handle(EXCEPT_BUSERR, cur_vadd);
temp = 0;
}
}
 
if (config.debug.enabled)
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */
return temp;
}
 
/* for simulator accesses, the ones that cpu wouldn't do
*
* STATISTICS OK.
*/
uint16_t eval_direct16(oraddr_t memaddr, int *breakpoint, int through_mmu,
int through_dc)
{
uint32_t temp;
 
if (memaddr & 1) {
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__);
return 0;
}
cur_vadd = memaddr;
 
if (through_mmu)
memaddr = peek_into_dtlb(memaddr, 0, through_dc);
 
if (through_dc)
temp = dc_simulate_read(memaddr, 2);
else {
temp = evalsim_mem16_void(memaddr);
if (!cur_area) {
PRINTF("EXCEPTION: read out of memory (16-bit access to %"PRIxADDR
") in eval_direct16()\n", memaddr);
except_handle(EXCEPT_BUSERR, cur_vadd);
temp = 0;
}
}
return temp;
}
 
 
/* Returns 8-bit values from mem array.
*
* STATISTICS OK (only used for cpu_access, that is architectural access)
*/
uint8_t eval_mem8(oraddr_t memaddr,int* breakpoint)
{
uint8_t temp;
 
if (config.sim.mprofile)
mprofile (memaddr, MPROF_8 | MPROF_READ);
 
if (config.debug.enabled)
*breakpoint += CheckDebugUnit(DebugLoadAddress,memaddr); /* 28/05/01 CZ */
 
cur_vadd = memaddr;
 
memaddr = dmmu_translate(memaddr, 0);
if (except_pending)
return 0;
 
if (config.dc.enabled)
temp = (uint8_t)dc_simulate_read(memaddr, 1);
else {
temp = evalsim_mem8(memaddr);
if (!cur_area) {
PRINTF("EXCEPTION: read out of memory (8-bit access to %"PRIxADDR")\n",
memaddr);
except_handle(EXCEPT_BUSERR, cur_vadd);
temp = 0;
}
}
 
if (config.debug.enabled)
*breakpoint += CheckDebugUnit(DebugLoadData,temp); /* MM170901 */
return temp;
}
 
/* for simulator accesses, the ones that cpu wouldn't do
*
* STATISTICS OK.
*/
uint8_t eval_direct8(oraddr_t memaddr, int *breakpoint, int through_mmu,
int through_dc)
{
uint8_t temp;
 
cur_vadd = memaddr;
if (through_mmu)
memaddr = peek_into_dtlb(memaddr, 0, through_dc);
if (through_dc)
temp = (unsigned char)dc_simulate_read(memaddr, 1);
else {
temp = evalsim_mem8_void(memaddr);
if (!cur_area) {
PRINTF("EXCEPTION: read out of memory (8-bit access to %"PRIxADDR
") in eval_direct8()\n", memaddr);
except_handle(EXCEPT_BUSERR, cur_vadd);
temp = 0;
}
}
return temp;
}
 
/* for cpu accesses */
inline void setsim_mem32(oraddr_t memaddr, uint32_t value)
{
return(setsim_mem32_atomic(memaddr, value, 1));
}
 
/* for simulator accesses, the ones that cpu wouldn't do */
inline void setsim_mem32_void(oraddr_t memaddr, uint32_t value)
{
return(setsim_mem32_atomic(memaddr, value, 0));
}
 
void setsim_mem32_atomic(oraddr_t memaddr, uint32_t value, int cpu_access)
{
if (verify_memoryarea(memaddr)) {
switch(cur_area->granularity) {
case 4:
cur_area->writefunc(memaddr, value, cur_area->priv_dat);
if (cpu_access)
runtime.sim.mem_cycles += cur_area->delayw;
break;
case 1:
cur_area->writefunc(memaddr , (value >> 24) & 0xFF, cur_area->priv_dat);
cur_area->writefunc(memaddr + 1, (value >> 16) & 0xFF, cur_area->priv_dat);
cur_area->writefunc(memaddr + 2, (value >> 8) & 0xFF, cur_area->priv_dat);
cur_area->writefunc(memaddr + 3, (value ) & 0xFF, cur_area->priv_dat);
if (cpu_access)
runtime.sim.mem_cycles += cur_area->delayw * 4;
break;
case 2:
cur_area->writefunc(memaddr, (value >> 16) & 0xFFFF, cur_area->priv_dat);
cur_area->writefunc(memaddr + 2, value & 0xFFFF, cur_area->priv_dat);
if (cpu_access)
runtime.sim.mem_cycles += cur_area->delayw * 2;
break;
default:
/* if you add new memory granularity be sure to check the formula
* below for the read delay and fix it if necessery
*/
PRINTF("unknown/unhandled memory granularuty\n");
exit(-1);
}
} else {
PRINTF("EXCEPTION: write out of memory (32-bit access to %"PRIxADDR")\n",
memaddr);
except_handle(EXCEPT_BUSERR, cur_vadd);
}
}
 
/* for cpu accesses */
inline void setsim_mem16(oraddr_t memaddr, uint16_t value)
{
return(setsim_mem16_atomic(memaddr, value, 1));
}
 
/* for simulator accesses, the ones that cpu wouldn't do */
inline void setsim_mem16_void(oraddr_t memaddr, uint16_t value)
{
return(setsim_mem16_atomic(memaddr, value, 0));
}
 
void setsim_mem16_atomic(oraddr_t memaddr, uint16_t value, int cpu_access)
{
uint32_t temp;
if (verify_memoryarea(memaddr)) {
switch(cur_area->granularity) {
case 1:
cur_area->writefunc(memaddr, (value >> 8) & 0xFF, cur_area->priv_dat);
cur_area->writefunc(memaddr + 1, value & 0xFF, cur_area->priv_dat);
if (cpu_access)
runtime.sim.mem_cycles += cur_area->delayw * 2;
break;
case 2:
cur_area->writefunc(memaddr, value & 0xFFFF, cur_area->priv_dat);
if (cpu_access)
runtime.sim.mem_cycles += cur_area->delayw;
break;
case 4:
temp = evalsim_mem32_void(memaddr & ~ADDR_C(3));
temp &= 0xffff << ((memaddr & 2) ? 16 : 0);
temp |= (unsigned long)(value & 0xffff) << ((memaddr & 2) ? 0 : 16);
setsim_mem32_atomic(memaddr & ~ADDR_C(3), temp, cpu_access);
break;
default:
/* if you add new memory granularity be sure to check the formula
* below for the read delay and fix it if necessery
*/
PRINTF("unknown/unhandled memory granularuty\n");
exit(-1);
}
} else {
PRINTF("EXCEPTION: write out of memory (16-bit access to %"PRIxADDR")\n",
memaddr);
except_handle(EXCEPT_BUSERR, cur_vadd);
}
}
 
/* for cpu accesses */
inline void setsim_mem8(oraddr_t memaddr, uint8_t value)
{
return(setsim_mem8_atomic(memaddr, value, 1));
}
 
/* for simulator accesses, the ones that cpu wouldn't do */
inline void setsim_mem8_void(oraddr_t memaddr, uint8_t value)
{
return(setsim_mem8_atomic(memaddr, value, 0));
}
 
void setsim_mem8_atomic(oraddr_t memaddr, uint8_t value, int cpu_access)
{
uint32_t temp;
if (verify_memoryarea(memaddr)) {
switch (cur_area->granularity) {
case 1:
cur_area->writefunc(memaddr, value, cur_area->priv_dat);
if (cpu_access)
runtime.sim.mem_cycles += cur_area->delayw;
break;
case 2:
temp = evalsim_mem16_void (memaddr & ~ADDR_C(1));
temp &= 0xff << ((memaddr & 1) ? 8 : 0);
temp |= (unsigned short)(value & 0xff) << ((memaddr & 1) ? 0 : 8);
setsim_mem16_atomic (memaddr & ~ADDR_C(1), temp, cpu_access);
break;
case 4:
temp = evalsim_mem32_void (memaddr & ~ADDR_C(3));
temp &= ~(0xff << (8 * (3 - (memaddr & 3))));
temp |= (unsigned long)(value & 0xff) << (8 * (3 - (memaddr & 3)));
setsim_mem32_atomic (memaddr & ~ADDR_C(3), temp, cpu_access);
break;
}
} else {
PRINTF("EXCEPTION: write out of memory (8-bit access to %"PRIxADDR")\n",
memaddr);
except_handle(EXCEPT_BUSERR, cur_vadd);
}
}
 
/* Set mem, 32-bit. Big endian version.
*
* STATISTICS OK. (the only suspicious usage is in toplevel.c,
* where this instruction is used for patching memory,
* wether this is cpu or architectual access is yet to
* be decided)
*/
void set_mem32(oraddr_t memaddr, uint32_t value, int* breakpoint)
{
if (config.sim.mprofile)
mprofile (memaddr, MPROF_32 | MPROF_WRITE);
 
if (memaddr & 3) {
except_handle (EXCEPT_ALIGN, memaddr);
return;
}
 
cur_vadd = memaddr;
memaddr = dmmu_translate(memaddr, 1);;
/* If we produced exception don't set anything */
if (except_pending)
return;
 
if (config.debug.enabled) {
*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr); /* 28/05/01 CZ */
*breakpoint += CheckDebugUnit(DebugStoreData,value);
}
 
dc_simulate_write(memaddr, value, 4);
 
if (cur_area && cur_area->log)
fprintf (cur_area->log, "[%"PRIxADDR"] -> write %08"PRIx32"\n", memaddr,
value);
}
 
/*
* STATISTICS NOT OK.
*/
void set_direct32(oraddr_t memaddr, uint32_t value,int* breakpoint,
int through_mmu, int through_dc)
{
 
if (memaddr & 3) {
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__);
return;
}
 
cur_vadd = memaddr;
if (through_mmu) {
/* 0 - no write access, we do not want a DPF exception do we ;)
*/
memaddr = peek_into_dtlb(memaddr, 1, through_dc);
}
 
 
/* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count,
* and possibly also memory access times.
*/
if (!through_dc)
PRINTF("WARNING: statistics might not be OK\n");
dc_simulate_write(memaddr, value, 4);
 
if (cur_area && cur_area->log)
fprintf (cur_area->log, "[%"PRIxADDR"] -> DIRECT write %08"PRIx32"\n",
memaddr, value);
}
 
 
/* Set mem, 16-bit. Big endian version. */
 
void set_mem16(oraddr_t memaddr, uint16_t value, int* breakpoint)
{
if (config.sim.mprofile)
mprofile (memaddr, MPROF_16 | MPROF_WRITE);
if (memaddr & 1) {
except_handle (EXCEPT_ALIGN, memaddr);
return;
}
cur_vadd = memaddr;
memaddr = dmmu_translate(memaddr, 1);;
/* If we produced exception don't set anything */
if (except_pending)
return;
 
if (config.debug.enabled) {
*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr); /* 28/05/01 CZ */
*breakpoint += CheckDebugUnit(DebugStoreData,value);
}
dc_simulate_write(memaddr, (unsigned long)value, 2);
 
if (cur_area && cur_area->log)
fprintf (cur_area->log, "[%"PRIxADDR"] -> write %04"PRIx16"\n", memaddr,
value);
}
 
/*
* STATISTICS NOT OK.
*/
void set_direct16(oraddr_t memaddr, uint16_t value, int* breakpoint,
int through_mmu, int through_dc)
{
 
if (memaddr & 1) {
PRINTF("%s:%d %s(): ERR unaligned access\n", __FILE__, __LINE__, __FUNCTION__);
return;
}
 
cur_vadd = memaddr;
if (through_mmu) {
/* 0 - no write access, we do not want a DPF exception do we ;)
*/
memaddr = peek_into_dtlb(memaddr, 0, through_dc);
}
 
/* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count,
* and possibly also memory access times.
*/
if (!through_dc)
PRINTF("WARNING: statistics might not be OK\n");
dc_simulate_write(memaddr, value, 2);
 
if (cur_area && cur_area->log)
fprintf (cur_area->log, "[%"PRIxADDR"] -> DIRECT write %04"PRIx16"\n",
memaddr, value);
}
 
/* Set mem, 8-bit. */
 
void set_mem8(oraddr_t memaddr, uint8_t value, int* breakpoint)
{
if (config.sim.mprofile)
mprofile (memaddr, MPROF_8 | MPROF_WRITE);
cur_vadd = memaddr;
memaddr = dmmu_translate(memaddr, 1);;
/* If we produced exception don't set anything */
if (except_pending) return;
 
if (config.debug.enabled) {
*breakpoint += CheckDebugUnit(DebugStoreAddress,memaddr); /* 28/05/01 CZ */
*breakpoint += CheckDebugUnit(DebugStoreData,value);
}
 
dc_simulate_write(memaddr, value, 1);
 
if (cur_area && cur_area->log)
fprintf (cur_area->log, "[%"PRIxADDR"] -> write %02"PRIx8"\n", memaddr,
value);
}
 
/*
* STATISTICS NOT OK.
*/
void set_direct8(oraddr_t memaddr, uint8_t value, int* breakpoint,
int through_mmu, int through_dc)
{
 
cur_vadd = memaddr;
if (through_mmu) {
/* 0 - no write access, we do not want a DPF exception do we ;)
*/
memaddr = peek_into_dtlb(memaddr, 0, through_dc);
}
 
/* __PHX__ fixme: we'll get cache hit/miss delay added to cycles count,
* and possibly also memory access times.
*/
if (!through_dc)
PRINTF("WARNING: statistics might not be OK\n");
dc_simulate_write(memaddr, value, 1);
 
if (cur_area && cur_area->log)
fprintf (cur_area->log, "[%"PRIxADDR"] -> DIRECT write %02"PRIx8"\n",
memaddr, value);
}
 
 
void dumpmemory(oraddr_t from, oraddr_t to, int disasm, int nl)
{
oraddr_t i, j;
struct label_entry *tmp;
int ilen = disasm ? 4 : 16;
 
for(i = from; i < to; i += ilen) {
PRINTF("%"PRIxADDR": ", i);
for (j = 0; j < ilen;) {
if (!disasm) {
tmp = NULL;
if (verify_memoryarea(i + j)) {
struct label_entry *entry;
entry = get_label(i + j);
if (entry)
PRINTF("(%s)", entry->name);
PRINTF("%02"PRIx8" ", evalsim_mem8(i + j));
} else PRINTF("XX ");
j++;
} else {
int breakpoint;
uint32_t _insn = read_mem(i, &breakpoint);
int index = insn_decode (_insn);
int len = insn_len (index);
tmp = NULL;
if (verify_memoryarea(i + j)) {
struct label_entry *entry;
entry = get_label(i + j);
if (entry)
PRINTF("(%s)", entry->name);
 
PRINTF(": %08"PRIx32" ", _insn);
if (index >= 0) {
disassemble_insn (_insn);
PRINTF(" %s", disassembled);
} else
PRINTF("<invalid>");
} else PRINTF("XXXXXXXX");
j += len;
}
}
if (nl)
PRINTF ("\n");
}
}
 
uint32_t simmem_read_word(oraddr_t addr, void *priv_dat) {
return *(uint32_t *)(priv_dat + (addr & cur_area->size_mask));
}
 
void simmem_write_word(oraddr_t addr, uint32_t value, void *priv_dat) {
*(uint32_t *)(priv_dat + (addr & cur_area->size_mask)) = value;
}
 
uint32_t simmem_read_zero(oraddr_t addr, void *dat) {
if (config.sim.verbose)
fprintf (stderr, "WARNING: memory read from non-read memory area 0x%"
PRIxADDR".\n", addr);
return 0;
}
 
void simmem_write_null(oraddr_t addr, uint32_t value, void *dat) {
if (config.sim.verbose)
fprintf (stderr, "WARNING: memory write to 0x%"PRIxADDR", non-write memory area (value 0x%08"PRIx32").\n", addr, value);
}
 
/* Initialize memory table from a config struct */
 
void init_memory_table ()
{
/* If nothing was defined, use default memory block */
if (config.memory.nmemories) {
int i;
for (i = 0; i < config.memory.nmemories; i++) {
oraddr_t start = config.memory.table[i].baseaddr;
uint32_t length = config.memory.table[i].size;
char *type = config.memory.table[i].name;
int rd = config.memory.table[i].delayr;
int wd = config.memory.table[i].delayw;
int ce = config.memory.table[i].ce;
void *mem = malloc (length);
 
if (config.sim.verbose)
debug (1, "%"PRIxADDR" %08"PRIx32" (%"PRIi32" KB): %s (activated by CE%i; read delay = %icyc, write delay = %icyc)\n",
start, length, length >> 10, type, ce, rd, wd);
 
if (!mem) {
fprintf (stderr, "Failed to allocate sim memory. Aborting\n");
exit (-1);
}
 
register_memoryarea(start, length, 4, 0, &simmem_read_word,
&simmem_write_word, mem);
cur_area->chip_select = ce;
cur_area->valid = 1;
cur_area->delayw = wd;
cur_area->delayr = rd;
if (config.memory.table[i].log[0] != '\0') {
if ((cur_area->log = fopen (config.memory.table[i].log, "wt+")) == NULL)
fprintf (stderr, "WARNING: Cannot open '%s'.\n",
config.memory.table[i].log);
} else
cur_area->log = NULL;
}
PRINTF ("\n");
} else {
void *mem = malloc (DEFAULT_MEMORY_LEN);
if (config.sim.verbose)
fprintf (stderr, "WARNING: Memory not defined, assuming standard configuration.\n");
 
if (!mem) {
fprintf (stderr, "Failed to allocate sim memory. Aborting\n");
exit (-1);
}
 
register_memoryarea(DEFAULT_MEMORY_START, DEFAULT_MEMORY_LEN, 4, 0,
&simmem_read_word, &simmem_write_word, mem);
cur_area->chip_select = 0;
cur_area->valid = 1;
cur_area->delayw = 1;
cur_area->delayr = 1;
cur_area->log = NULL;
}
}
 
/* Changes read/write memory in read/write only */
 
void lock_memory_table ()
{
struct dev_memarea *ptmp;
 
/* Check list of registered devices. */
for(ptmp = dev_list; ptmp; ptmp = ptmp->next) {
if (ptmp->delayr < 0 && ptmp->readfunc == &simmem_read_word)
ptmp->readfunc = &simmem_read_zero;
if (ptmp->delayw < 0 && ptmp->writefunc == &simmem_write_word)
ptmp->writefunc = &simmem_write_null;
 
/* If this mem area is not for memory chip under MC control
then this area is valid all the time */
if (ptmp->readfunc != &simmem_read_word) {
ptmp->valid = 1;
ptmp->chip_select = -1;
}
}
}
 
/* Closes files, etc. */
 
void done_memory_table ()
{
struct dev_memarea *ptmp;
 
/* Check list of registered devices. */
for(ptmp = dev_list; ptmp; ptmp = ptmp->next) {
if (ptmp->log)
fclose (ptmp->log);
}
}
 
/* Displays current memory configuration */
 
void memory_table_status ()
{
struct dev_memarea *ptmp;
 
/* Check list of registered devices. */
for(ptmp = dev_list; ptmp; ptmp = ptmp->next) {
PRINTF ("addr & %"PRIxADDR" == %"PRIxADDR" to %"PRIxADDR", size %"PRIx32
", gran %iB\n",
ptmp->addr_mask, ptmp->addr_compare, ptmp->addr_compare | bit_mask (ptmp->size),
ptmp->size, ptmp->granularity);
PRINTF ("\t");
if (ptmp->delayr >= 0)
PRINTF ("read delay = %i cycles, ", ptmp->delayr);
else
PRINTF ("reads not possible, ");
 
if (ptmp->delayw >= 0)
PRINTF ("write delay = %i cycles", ptmp->delayw);
else
PRINTF ("writes not possible");
if (ptmp->log)
PRINTF (", (logged)\n");
else
PRINTF ("\n");
}
}
 
/* Outputs time in pretty form to dest string */
 
char *generate_time_pretty (char *dest, long time_ps)
{
int exp3 = 0;
if (time_ps) {
while ((time_ps % 1000) == 0) {
time_ps /= 1000;
exp3++;
}
}
sprintf (dest, "%li%cs", time_ps, "pnum"[exp3]);
return dest;
}
/Makefile.in
0,0 → 1,338
# Makefile.in generated by automake 1.6.3 from Makefile.am.
# @configure_input@
 
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
 
@SET_MAKE@
 
# Makefile -- Makefile for cpu architecture independent simulation
# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
#
# This file is part of OpenRISC 1000 Architectural Simulator.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
SHELL = @SHELL@
 
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
 
bindir = @bindir@
sbindir = @sbindir@
libexecdir = @libexecdir@
datadir = @datadir@
sysconfdir = @sysconfdir@
sharedstatedir = @sharedstatedir@
localstatedir = @localstatedir@
libdir = @libdir@
infodir = @infodir@
mandir = @mandir@
includedir = @includedir@
oldincludedir = /usr/include
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ../..
 
ACLOCAL = @ACLOCAL@
AUTOCONF = @AUTOCONF@
AUTOMAKE = @AUTOMAKE@
AUTOHEADER = @AUTOHEADER@
 
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_HEADER = $(INSTALL_DATA)
transform = @program_transform_name@
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_alias = @build_alias@
build_triplet = @build@
host_alias = @host_alias@
host_triplet = @host@
target_alias = @target_alias@
target_triplet = @target@
 
EXEEXT = @EXEEXT@
OBJEXT = @OBJEXT@
PATH_SEPARATOR = @PATH_SEPARATOR@
AMTAR = @AMTAR@
AR = @AR@
ARFLAGS = @ARFLAGS@
AWK = @AWK@
BUILD_DIR = @BUILD_DIR@
CC = @CC@
CFLAGS = @CFLAGS@
CPU_ARCH = @CPU_ARCH@
DEPDIR = @DEPDIR@
INCLUDES = @INCLUDES@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LOCAL_CFLAGS = @LOCAL_CFLAGS@
LOCAL_DEFS = @LOCAL_DEFS@
MAKE_SHELL = @MAKE_SHELL@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
STRIP = @STRIP@
SUMVERSION = @SUMVERSION@
TERMCAP_LIB = @TERMCAP_LIB@
VERSION = @VERSION@
am__include = @am__include@
am__quote = @am__quote@
host = @host@
host_cpu = @host_cpu@
host_os = @host_os@
install_sh = @install_sh@
 
noinst_LIBRARIES = libcommon.a
libcommon_a_SOURCES = abstract.c parse.c stats.c trace.c labels.c
subdir = cpu/common
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
 
libcommon_a_AR = $(AR) cru
libcommon_a_LIBADD =
am_libcommon_a_OBJECTS = abstract.$(OBJEXT) parse.$(OBJEXT) \
stats.$(OBJEXT) trace.$(OBJEXT) labels.$(OBJEXT)
libcommon_a_OBJECTS = $(am_libcommon_a_OBJECTS)
 
DEFS = @DEFS@
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/abstract.Po ./$(DEPDIR)/labels.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/parse.Po ./$(DEPDIR)/stats.Po \
@AMDEP_TRUE@ ./$(DEPDIR)/trace.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
DIST_SOURCES = $(libcommon_a_SOURCES)
DIST_COMMON = Makefile.am Makefile.in
SOURCES = $(libcommon_a_SOURCES)
 
all: all-am
 
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu cpu/common/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
 
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
libcommon.a: $(libcommon_a_OBJECTS) $(libcommon_a_DEPENDENCIES)
-rm -f libcommon.a
$(libcommon_a_AR) libcommon.a $(libcommon_a_OBJECTS) $(libcommon_a_LIBADD)
$(RANLIB) libcommon.a
 
mostlyclean-compile:
-rm -f *.$(OBJEXT) core *.core
 
distclean-compile:
-rm -f *.tab.c
 
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/abstract.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/labels.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stats.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Po@am__quote@
 
distclean-depend:
-rm -rf ./$(DEPDIR)
 
.c.o:
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
 
.c.obj:
@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
$(COMPILE) -c `cygpath -w $<`
CCDEPMODE = @CCDEPMODE@
uninstall-info-am:
 
ETAGS = etags
ETAGSFLAGS =
 
tags: TAGS
 
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
 
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
 
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
 
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 
top_distdir = ../..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
 
distdir: $(DISTFILES)
@list='$(DISTFILES)'; for file in $$list; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LIBRARIES)
 
installdirs:
 
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
 
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
 
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
 
clean-generic:
 
distclean-generic:
-rm -f Makefile $(CONFIG_CLEAN_FILES)
 
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
 
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
 
distclean: distclean-am
 
distclean-am: clean-am distclean-compile distclean-depend \
distclean-generic distclean-tags
 
dvi: dvi-am
 
dvi-am:
 
info: info-am
 
info-am:
 
install-data-am:
 
install-exec-am:
 
install-info: install-info-am
 
install-man:
 
installcheck-am:
 
maintainer-clean: maintainer-clean-am
 
maintainer-clean-am: distclean-am maintainer-clean-generic
 
mostlyclean: mostlyclean-am
 
mostlyclean-am: mostlyclean-compile mostlyclean-generic
 
uninstall-am: uninstall-info-am
 
.PHONY: GTAGS all all-am check check-am clean clean-generic \
clean-noinstLIBRARIES distclean distclean-compile \
distclean-depend distclean-generic distclean-tags distdir dvi \
dvi-am info info-am install install-am install-data \
install-data-am install-exec install-exec-am install-info \
install-info-am install-man install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic tags uninstall uninstall-am \
uninstall-info-am
 
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
/labels.c
0,0 → 1,153
/* abstract.c -- Abstract entities, handling labels
Copyright (C) 2001 Marko Mlinar, markom@opencores.org
 
This file is part of OpenRISC 1000 Architectural Simulator.
 
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
 
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
/* Abstract memory and routines that go with this. I need to
add all sorts of other abstract entities. Currently we have
only memory. */
 
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
 
#include "config.h"
 
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#endif
 
#include "port.h"
#include "config.h"
 
#include "arch.h"
#include "sim-config.h"
#include "labels.h"
 
static struct label_entry *label_hash[LABELS_HASH_SIZE];
struct breakpoint_entry *breakpoints;
 
void init_labels () {
int i;
for (i = 0; i < LABELS_HASH_SIZE; i++)
label_hash[i] = NULL;
}
 
void add_label (oraddr_t addr, char *name) {
struct label_entry **tmp;
tmp = &(label_hash[addr % LABELS_HASH_SIZE]);
for (; *tmp; tmp = &((*tmp)->next));
*tmp = malloc(sizeof(**tmp));
(*tmp)->name = malloc(strlen(name) + 1);
(*tmp)->addr = addr;
strcpy((*tmp)->name, name);
(*tmp)->next = NULL;
}
 
struct label_entry *get_label (oraddr_t addr) {
struct label_entry *tmp = label_hash[addr % LABELS_HASH_SIZE];
while (tmp) {
if (tmp->addr == addr)
return tmp;
tmp = tmp->next;
}
return NULL;
}
 
struct label_entry *find_label (char *name) {
int i;
for (i = 0; i < LABELS_HASH_SIZE; i++) {
struct label_entry *tmp = label_hash[i % LABELS_HASH_SIZE];
while (tmp) {
if (strcmp (tmp->name, name) == 0)
return tmp;
tmp = tmp->next;
}
}
return NULL;
}
 
/* Searches mem array for a particular label and returns label's address.
If label does not exist, returns 0. */
oraddr_t eval_label (char *name) {
struct label_entry *le;
char *plus;
char *minus;
int positive_offset = 0;
int negative_offset = 0;
 
if ((plus = strchr(name, '+'))) {
*plus = '\0';
positive_offset = atoi(++plus);
}
 
if ((minus = strchr(name, '-'))) {
*minus = '\0';
negative_offset = atoi(++minus);
}
le = find_label (name);
if (!le)
return 0;
return le->addr + positive_offset - negative_offset;
}
 
void init_breakpoints () {
breakpoints = 0;
}
 
void add_breakpoint (oraddr_t addr) {
struct breakpoint_entry *tmp;
tmp = (struct breakpoint_entry *) malloc (sizeof (struct breakpoint_entry));
tmp->next = breakpoints;
tmp->addr = addr;
breakpoints = tmp;
}
 
void remove_breakpoint (oraddr_t addr) {
struct breakpoint_entry **tmp = &breakpoints;
while (*tmp) {
if ((*tmp)->addr == addr) {
struct breakpoint_entry *t = *tmp;
(*tmp) = t->next;
free (t);
} else
tmp = &((*tmp)->next);
}
}
 
void print_breakpoints () {
struct breakpoint_entry **tmp = &breakpoints;
int i = 1;
printf ("---[breakpoints]------------------\n");
while (*tmp) {
printf ("Breakpoint %i at 0x%"PRIxADDR"\n", i, (*tmp)->addr);
tmp = &((*tmp)->next);
}
printf ("---[breakpoints end]--------------\n");
}
 
inline int has_breakpoint (oraddr_t addr) {
struct breakpoint_entry *tmp = breakpoints;
while (tmp) {
if (tmp->addr == addr)
return 1;
tmp = tmp->next;
}
return 0;
}
labels.c Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: parse.h =================================================================== --- parse.h (nonexistent) +++ parse.h (revision 1765) @@ -0,0 +1,41 @@ +/* parse.h -- Header file for parse.c + Copyright (C) 1999 Damjan Lampret, lampret@opencores.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* Here we define some often used caharcters in assembly files. +This wil probably go into architecture dependent directory. */ + +#define COMMENT_CHAR '#' +#define DIRECTIVE_CHAR '.' +#define LABELEND_CHAR ":" +/*#define OPERAND_DELIM ","*/ + +/* Strip whitespace from the start and end of STRING. Return a pointer + into STRING. */ +#ifndef whitespace +#define whitespace(a) ((a) == '\t' ? 1 : ((a) == ' '? 1 : 0)) +#endif + +/* Strips white spaces at beginning and at the end of the string */ +char *stripwhite (char *string); + +/* This function is very similar to strncpy, except it null terminates the string */ +char *strstrip (char *dst, const char *src, int n); + +/* Loads file to memory starting at address startaddr and returns freemem. */ +unsigned long loadcode(char *filename, oraddr_t startaddr, oraddr_t virtphy_transl); Index: parse.c =================================================================== --- parse.c (nonexistent) +++ parse.c (revision 1765) @@ -0,0 +1,697 @@ +/* parce.c -- Architecture independent load + Copyright (C) 1999 Damjan Lampret, lampret@opencores.org + +This file is part of OpenRISC 1000 Architectural Simulator. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include +#include +#include + +#include "config.h" + +#ifdef HAVE_INTTYPES_H +#include +#endif + +#include "port.h" +#include "arch.h" +#include "abstract.h" +#include "dmmu.h" +#include "coff.h" +#include "elf.h" +#include "debug_unit.h" +#include "opcode/or32.h" +#include "parse.h" +#include "sim-config.h" +#include "labels.h" +#include "debug.h" + +#define MEMORY_LEN 0x100000000 +#define MAXLINE_LEN 18000 + +/* Whether to do immediate statistics */ +#define IMM_STATS 0 + +extern char *disassembled; + +/* Unused mem memory marker. It is used when allocating program and data memory + during parsing */ +unsigned int freemem; + +/* Translation table provided by microkernel. Only used if simulating microkernel. */ +static oraddr_t transl_table; + +/* Used to signal whether during loading of programs a translation fault occured. */ +static unsigned long transl_error; + +char * +stripwhite (string) + char *string; +{ + register char *s, *t; + + for (s = string; whitespace (*s); s++) + ; + + if (*s == 0) + return (s); + + t = s + strlen (s) - 1; + while (t > s && whitespace (*t)) + t--; + *++t = '\0'; + + return s; +} + +/* This function is very similar to strncpy, except it null terminates the string */ +char *strstrip (char *dst, const char *src, int n) +{ + strncpy (dst, src, n); + *(dst + n) = '\0'; + return dst; +} + +/* Used only by the simulator loader to translate logical addresses into physical. + If loadcode() is called with valid virtphy_transl pointer to a table of + translations then translate() performs translation otherwise phy address is + equal to logical. */ +static oraddr_t translate(oraddr_t laddr,int* breakpoint) +{ + int i; + + /* No translation (i.e. when loading kernel into simulator) */ +/* PRINTF("transl_table=%x laddr=%x\n", transl_table, laddr); + PRINTF("laddr=%x\n", laddr);*/ + if (transl_table == 0) + return laddr; + + /* Try to find our translation in the table. */ + for(i = 0; i < (MEMORY_LEN / PAGE_SIZE) * 16; i += 16) + if ((laddr & ~(PAGE_SIZE - 1)) == evalsim_mem32(transl_table + i)) { + setsim_mem32(transl_table + i + 8, -2); /* Page modified */ + PRINTF("found paddr=%"PRIx32"\n", + evalsim_mem32(transl_table + i + 4) | (laddr & (PAGE_SIZE - 1))); + return (oraddr_t)evalsim_mem32(transl_table + i + 4) | (laddr & (oraddr_t)(PAGE_SIZE - 1)); + } + + /* Allocate new phy page for us. */ + for(i = 0; i < (MEMORY_LEN / PAGE_SIZE) * 16; i += 16) + if (evalsim_mem32(transl_table + i + 8) == 0) { + setsim_mem32(transl_table + i, laddr & ~(PAGE_SIZE - 1)); /* VPN */ + setsim_mem32(transl_table + i + 4, (i/16) * PAGE_SIZE); /* PPN */ + setsim_mem32(transl_table + i + 8, -2); /* Page modified */ + PRINTF("newly allocated ppn=%"PRIx32"\n", + evalsim_mem32(transl_table + i + 4)); + PRINTF("newly allocated .ppn=%"PRIxADDR"\n", transl_table + i + 4); + PRINTF("newly allocated ofs=%"PRIxADDR"\n", (laddr & (PAGE_SIZE - 1))); + PRINTF("newly allocated paddr=%"PRIx32"\n", + evalsim_mem32(transl_table + i + 4) | (laddr & (PAGE_SIZE - 1))); + return (oraddr_t)evalsim_mem32(transl_table + i + 4) | (laddr & (oraddr_t)(PAGE_SIZE - 1)); + } + /* If we come this far then all phy memory is used and we can't find our page + nor allocate new page. */ + transl_error = 1; + + PRINTF("can't translate %"PRIxADDR"\n", laddr); + exit(1); + return -1; +} + +#if IMM_STATS +int bcnt[33][3] = {0}; +int bsum[3] = {0}; +unsigned long movhi = 0; + +int bits (unsigned long val) { + int i = 1; + if (!val) return 0; + while (val != 0 && (signed long)val != -1) {i++; val = (signed long)val >> 1;} + return i; +} + +void check_insn (uint32_t insn) { + int insn_index = insn_decode (insn); + struct insn_op_struct *opd = op_start[insn_index]; + uint32_t data = 0; + int dis = 0; + const char *name; + if (!insn || insn_index < 0) return; + name = insn_name (insn_index); + if (strcmp (name, "l.nop") == 0 || strcmp (name, "l.sys") == 0) return; + + while (1) + { + uint32_t tmp = 0 + unsigned int nbits = 0; + while (1) + { + tmp |= ((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) << nbits; + nbits += opd->data; + if (opd->type & OPTYPE_OP) + break; + opd++; + } + + /* Do we have to sign extend? */ + if (opd->type & OPTYPE_SIG) + { + int sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR; + if (tmp & (1 << sbit)) + tmp |= 0xFFFFFFFF << sbit; + } + if (opd->type & OPTYPE_DIS) { + /* We have to read register later. */ + data += tmp; + dis = 1; + } else + { + if (!(opd->type & OPTYPE_REG) || dis) { + if (!dis) data = tmp; + if (strcmp (name, "l.movhi") == 0) { + movhi = data << 16; + } else { + data |= movhi; + //PRINTF ("%08x %s\n", data, name); + if (!(or32_opcodes[insn_index].flags & OR32_IF_DELAY)) { + bcnt[bits(data)][0]++; bsum[0]++; + } else { + if (strcmp (name, "l.bf") == 0 || strcmp (name, "l.bnf") == 0) { + bcnt[bits(data)][1]++; bsum[1]++; + } else { + bcnt[bits(data)][2]++; bsum[2]++; + } + } + } + } + data = 0; + dis = 0; + } + if(opd->type & OPTYPE_LAST) { + return; + } + opd++; + } +} +#endif + +/* Replaced several calls to translate(freemem) with vaddr */ +/* Added new mode execution code */ +/* Changed parameters so address can be passed as argument */ +void addprogram(oraddr_t address, uint32_t insn, int* breakpoint) +{ + int vaddr = (!runtime.sim.filename) ? translate(address,breakpoint) : translate(freemem,breakpoint); + + setsim_mem32 (vaddr, insn); +#if IMM_STATS + check_insn (insn); +#endif + if(runtime.sim.filename) + freemem += insn_len (insn_decode (insn)); +} + +/* Load big-endian COFF file. */ + +void readfile_coff(char *filename, short sections) +{ + FILE *inputfs; + char inputbuf[4]; + uint32_t insn; + signed long sectsize; + COFF_AOUTHDR coffaouthdr; + struct COFF_scnhdr coffscnhdr; + int len; + int firstthree = 0; + int breakpoint = 0; + + if (!(inputfs = fopen(filename, "r"))) { + perror("readfile_coff"); + exit(1); + } + + if (fseek(inputfs, sizeof(struct COFF_filehdr), SEEK_SET) == -1) { + fclose(inputfs); + perror("readfile_coff"); + exit(1); + } + + if (fread(&coffaouthdr, sizeof(coffaouthdr), 1, inputfs) != 1) { + fclose(inputfs); + perror("readfile_coff"); + exit(1); + } + + while(sections--) { + long scnhdr_pos = sizeof(struct COFF_filehdr) + sizeof(coffaouthdr) + + sizeof(struct COFF_scnhdr) * firstthree; + if (fseek(inputfs, scnhdr_pos, SEEK_SET) == -1) { + fclose(inputfs); + perror("readfile_coff"); + exit(1); + } + if (fread(&coffscnhdr, sizeof(struct COFF_scnhdr), 1, inputfs) != 1) { + fclose(inputfs); + perror("readfile_coff"); + exit(1); + } + PRINTF("Section: %s,", coffscnhdr.s_name); + PRINTF(" paddr: 0x%.8lx,", COFF_LONG_H(coffscnhdr.s_paddr)); + PRINTF(" vaddr: 0x%.8lx,", COFF_LONG_H(coffscnhdr.s_vaddr)); + PRINTF(" size: 0x%.8lx,", COFF_LONG_H(coffscnhdr.s_size)); + PRINTF(" scnptr: 0x%.8lx\n", COFF_LONG_H(coffscnhdr.s_scnptr)); + + sectsize = COFF_LONG_H(coffscnhdr.s_size); +#if 0 + /* A couple of sanity checks. */ + if (translate(COFF_LONG_H(coffscnhdr.s_vaddr),&breakpoint) < MEMORY_START) { + PRINTF("Section %s starts out of ", coffscnhdr.s_name); + PRINTF("memory (at %x)\n", COFF_LONG_H(coffscnhdr.s_vaddr)); + exit(1); + } + if (translate(COFF_LONG_H(coffscnhdr.s_vaddr) + sectsize,&breakpoint) > + MEMORY_START + MEMORY_LEN) { + PRINTF("Section %s ends out of ", coffscnhdr.s_name); + PRINTF("memory.\n"); + exit(1); + } +#endif +#if 0 + if (++firstthree == 1 && strcmp(coffscnhdr.s_name, ".text") != 0) { + PRINTF("First section should be .text (%s instead)\n", coffscnhdr.s_name); + exit(1); + } + if (firstthree == 2 && strcmp(coffscnhdr.s_name, ".data") != 0) { + PRINTF("Second section should be .data (%s instead)\n", coffscnhdr.s_name); + exit(1); + } + if (firstthree == 3 && strcmp(coffscnhdr.s_name, ".bss") != 0) { + PRINTF("Third section should be .bss (%s instead)\n", coffscnhdr.s_name); + exit(1); + } +#else + ++firstthree; +#endif + + /* loading section */ + freemem = COFF_LONG_H(coffscnhdr.s_paddr); + debug(2,"Starting to load at 0x%x\n", freemem); + if (fseek(inputfs, COFF_LONG_H(coffscnhdr.s_scnptr), SEEK_SET) == -1) { + fclose(inputfs); + perror("readfile_coff"); + exit(1); + } + while (sectsize > 0 && (len = fread(&inputbuf, sizeof(inputbuf), 1, inputfs))) { + insn = COFF_LONG_H(inputbuf); + len = insn_len (insn_decode (insn)); + if (len == 2) + { + fseek(inputfs, -2, SEEK_CUR); + debug(8,"readfile_coff: %lx 0x%x \n", sectsize, insn >> 16); + } + else + debug(8,"readfile_coff: %lx 0x%x \n", sectsize, insn); + addprogram (freemem, insn, &breakpoint); + sectsize -= len; + } + } + if (firstthree < 3) { + PRINTF("One or more missing sections. At least"); + PRINTF(" three sections expected (.text, .data, .bss).\n"); + exit(1); + } + if (firstthree > 3) { + PRINTF("Warning: one or more extra sections. These"); + PRINTF(" sections were handled as .data sections.\n"); + } + + fclose(inputfs); + PRINTF("Finished loading COFF.\n"); + return; +} + +/* Load symbols from big-endian COFF file. */ + +void readsyms_coff(char *filename, unsigned long symptr, long syms) +{ + FILE *inputfs; + struct COFF_syment coffsymhdr; + int count = 0; + long nsyms = syms; + if (!(inputfs = fopen(filename, "r"))) { + perror("readsyms_coff"); + exit(1); + } + + if (fseek(inputfs, symptr, SEEK_SET) == -1) { + fclose(inputfs); + perror("readsyms_coff"); + exit(1); + } + + while(syms--) { + int i, n; + if (fread(&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1) { + fclose(inputfs); + perror("readsyms_coff"); + exit(1); + } + + n = (unsigned char)coffsymhdr.e_numaux[0]; + + /* check whether this symbol belongs to a section and is external symbol; ignore all others */ + if (COFF_SHORT_H(coffsymhdr.e_scnum) >= 0 && coffsymhdr.e_sclass[0] == C_EXT) { +#if 0 + /* If not important or not in text, skip. */ + if(COFF_SHORT_H(coffsymhdr.e_type) & COFF_N_TMASK & COFF_STYP_TEXT) { +#endif + + if (*((unsigned long *)coffsymhdr.e.e.e_zeroes)) { + if (strlen(coffsymhdr.e.e_name) && strlen(coffsymhdr.e.e_name) < 9) + add_label(COFF_LONG_H(coffsymhdr.e_value), coffsymhdr.e.e_name); + debug(8, "[%i] Symbol: %s,", count++, coffsymhdr.e.e_name); + } else { + long fpos = ftell (inputfs); + + if (fseek(inputfs, symptr + nsyms * COFF_SYMESZ + COFF_LONG_H(coffsymhdr.e.e.e_offset), SEEK_SET) == 0) { + char tmp[33], *s = &tmp[0]; + while (s != &tmp[32]) + if ((*(s++) = fgetc(inputfs)) == 0) break; + tmp[32] = 0; + add_label(COFF_LONG_H(coffsymhdr.e_value), &tmp[0]); + debug(8, "[%i] Symbol: %s,", count++, &tmp[0]); + } + fseek(inputfs, fpos, SEEK_SET); + } + + debug(9, " val: 0x%.8lx,", COFF_LONG_H(coffsymhdr.e_value)); + debug(9, " type: %x, %x, auxs: %i\n", COFF_SHORT_H(coffsymhdr.e_type), *((unsigned short *)coffsymhdr.e_type), n); + } + + for (i = 0; i < n; i++) + if (fread(&coffsymhdr, COFF_SYMESZ, 1, inputfs) != 1) { + fclose(inputfs); + perror("readsyms_coff3"); + exit(1); + } + syms -= n; + count += n; + } + + fclose(inputfs); + PRINTF("Finished loading symbols.\n"); + return; +} + +void readfile_elf(char *filename) +{ + + FILE *inputfs; + struct elf32_hdr elfhdr; + struct elf32_phdr *elf_phdata; + struct elf32_shdr *elf_spnt, *elf_shdata; + struct elf32_sym *sym_tbl = (struct elf32_sym *)0; + unsigned long syms = 0; + char *str_tbl = (char *)0; + char *s_str = (char *)0; + int breakpoint = 0; + unsigned long inputbuf; + unsigned long padd; + uint32_t insn; + int i, j, sectsize, len; + + if (!(inputfs = fopen(filename, "r"))) { + perror("readfile_elf"); + exit(1); + } + + if (fread(&elfhdr, sizeof(elfhdr), 1, inputfs) != 1) { + perror("readfile_elf"); + exit(1); + } + + if ((elf_shdata = (struct elf32_shdr *)malloc(ELF_SHORT_H(elfhdr.e_shentsize) * ELF_SHORT_H(elfhdr.e_shnum))) == NULL) { + perror("readfile_elf"); + exit(1); + } + + if (fseek(inputfs, ELF_LONG_H(elfhdr.e_shoff), SEEK_SET) != 0) { + perror("readfile_elf"); + exit(1); + } + + if (fread(elf_shdata, ELF_SHORT_H(elfhdr.e_shentsize) * ELF_SHORT_H(elfhdr.e_shnum), 1, inputfs) != 1) { + perror("readfile_elf"); + exit(1); + } + + if (ELF_LONG_H(elfhdr.e_phoff)) { + + if((elf_phdata = (struct elf32_phdr *)malloc(ELF_SHORT_H(elfhdr.e_phnum) * ELF_SHORT_H(elfhdr.e_phentsize))) == NULL) { + perror("readfile_elf"); + exit(1); + } + + if (fseek(inputfs, ELF_LONG_H(elfhdr.e_phoff), SEEK_SET) != 0) { + perror("readfile_elf"); + exit(1); + } + + if (fread(elf_phdata, ELF_SHORT_H(elfhdr.e_phnum) * ELF_SHORT_H(elfhdr.e_phentsize), 1, inputfs) != 1) { + perror("readfile_elf"); + exit(1); + } + } + + for(i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H(elfhdr.e_shnum); i++, elf_spnt++) { + + if(ELF_LONG_H(elf_spnt->sh_type) == SHT_STRTAB) { + + if((str_tbl = (char *)malloc(ELF_LONG_H(elf_spnt->sh_size))) == NULL) { + perror("readfile_elf"); + exit(1); + } + + if (fseek(inputfs, ELF_LONG_H(elf_spnt->sh_offset), SEEK_SET) != 0) { + perror("readfile_elf"); + exit(1); + } + + if (fread(str_tbl, ELF_LONG_H(elf_spnt->sh_size), 1, inputfs) != 1) { + perror("readfile_elf"); + exit(1); + } + } + else if(ELF_LONG_H(elf_spnt->sh_type) == SHT_SYMTAB) { + + if((sym_tbl = (struct elf32_sym *)malloc(ELF_LONG_H(elf_spnt->sh_size))) == NULL) { + perror("readfile_elf"); + exit(1); + } + + if (fseek(inputfs, ELF_LONG_H(elf_spnt->sh_offset), SEEK_SET) != 0) { + perror("readfile_elf"); + exit(1); + } + + if (fread(sym_tbl, ELF_LONG_H(elf_spnt->sh_size), 1, inputfs) != 1) { + perror("readfile_elf"); + exit(1); + } + + syms = ELF_LONG_H(elf_spnt->sh_size) / ELF_LONG_H(elf_spnt->sh_entsize); + } + } + + if (ELF_SHORT_H(elfhdr.e_shstrndx) != SHN_UNDEF) { + elf_spnt = &elf_shdata[ELF_SHORT_H(elfhdr.e_shstrndx)]; + + if((s_str = (char *)malloc(ELF_LONG_H(elf_spnt->sh_size))) == NULL) { + perror("readfile_elf"); + exit(1); + } + + if (fseek(inputfs, ELF_LONG_H(elf_spnt->sh_offset), SEEK_SET) != 0) { + perror("readfile_elf"); + exit(1); + } + + if (fread(s_str, ELF_LONG_H(elf_spnt->sh_size), 1, inputfs) != 1) { + perror("readfile_elf"); + exit(1); + } + } + + + for(i = 0, elf_spnt = elf_shdata; i < ELF_SHORT_H(elfhdr.e_shnum); i++, elf_spnt++) { + + if((ELF_LONG_H(elf_spnt->sh_type) & SHT_PROGBITS) && (ELF_LONG_H(elf_spnt->sh_flags) & SHF_ALLOC)) { + + padd = ELF_LONG_H(elf_spnt->sh_addr); + for(j = 0; j < ELF_SHORT_H(elfhdr.e_phnum); j++) { + if(ELF_LONG_H(elf_phdata[j].p_offset) && + ELF_LONG_H(elf_phdata[j].p_offset) <= ELF_LONG_H(elf_spnt->sh_offset) && + (ELF_LONG_H(elf_phdata[j].p_offset) + ELF_LONG_H(elf_phdata[j].p_memsz)) > ELF_LONG_H(elf_spnt->sh_offset)) + padd = ELF_LONG_H(elf_phdata[j].p_paddr) + ELF_LONG_H(elf_spnt->sh_offset) - ELF_LONG_H(elf_phdata[j].p_offset); + } + + + + if (ELF_LONG_H(elf_spnt->sh_name) && s_str) + PRINTF("Section: %s,", &s_str[ELF_LONG_H(elf_spnt->sh_name)]); + else + PRINTF("Section: noname,"); + PRINTF(" vaddr: 0x%.8lx,", ELF_LONG_H(elf_spnt->sh_addr)); + PRINTF(" paddr: 0x%.8lx,", padd); + PRINTF(" offset: 0x%.8lx,", ELF_LONG_H(elf_spnt->sh_offset)); + PRINTF(" size: 0x%.8lx\n", ELF_LONG_H(elf_spnt->sh_size)); + + freemem = padd; + sectsize = ELF_LONG_H(elf_spnt->sh_size); + + if (fseek(inputfs, ELF_LONG_H(elf_spnt->sh_offset), SEEK_SET) != 0) { + perror("readfile_elf"); + exit(1); + } + + while (sectsize > 0 && (len = fread(&inputbuf, sizeof(inputbuf), 1, inputfs))) { + insn = ELF_LONG_H(inputbuf); + len = insn_len (insn_decode (insn)); + if (len == 2) + { + fseek(inputfs, -2, SEEK_CUR); + debug(8, "readfile_elf: %x 0x%x \n", sectsize, insn >> 16); + } + else + debug(8, "readfile_elf: %x 0x%x \n", sectsize, insn); + addprogram (freemem, insn, &breakpoint); + sectsize -= len; + } + } + } + + if (str_tbl) { + i = 0; + while(syms--) { + if (sym_tbl[i].st_name && sym_tbl[i].st_info && ELF_SHORT_H(sym_tbl[i].st_shndx) < 0x8000) { + add_label(ELF_LONG_H(sym_tbl[i].st_value), &str_tbl[ELF_LONG_H(sym_tbl[i].st_name)]); + debug (8, "%08lx(%s): %x %x %x\n", ELF_LONG_H(sym_tbl[i].st_value), &str_tbl[ELF_LONG_H(sym_tbl[i].st_name)], sym_tbl[i].st_info, sym_tbl[i].st_other, ELF_SHORT_H(sym_tbl[i].st_shndx)); + } + i++; + } + } +} + +/* Identify file type and call appropriate readfile_X routine. It only +handles orX-coff-big executables at the moment. */ + +void identifyfile(char *filename) +{ + FILE *inputfs; + struct COFF_filehdr coffhdr; + struct elf32_hdr elfhdr; + + if (!(inputfs = fopen(filename, "r"))) { + perror(filename); + fflush(stdout); + fflush(stderr); + exit(1); + } + + if (fread(&coffhdr, sizeof(coffhdr), 1, inputfs) == 1) { + if (COFF_SHORT_H(coffhdr.f_magic) == 0x17a) { + unsigned long opthdr_size; + PRINTF("COFF magic: 0x%.4x\n", COFF_SHORT_H(coffhdr.f_magic)); + PRINTF("COFF flags: 0x%.4x\n", COFF_SHORT_H(coffhdr.f_flags)); + PRINTF("COFF symptr: 0x%.8lx\n", COFF_LONG_H(coffhdr.f_symptr)); + if ((COFF_SHORT_H(coffhdr.f_flags) & COFF_F_EXEC) != COFF_F_EXEC) { + PRINTF("This COFF is not an executable.\n"); + exit(1); + } + opthdr_size = COFF_SHORT_H(coffhdr.f_opthdr); + if (opthdr_size != sizeof(COFF_AOUTHDR)) { + PRINTF("COFF optional header is missing or not recognized.\n"); + PRINTF("COFF f_opthdr: 0x%.2lx\n", opthdr_size); + exit(1); + } + fclose(inputfs); + readfile_coff(filename, COFF_SHORT_H(coffhdr.f_nscns)); + readsyms_coff(filename, COFF_LONG_H(coffhdr.f_symptr), COFF_LONG_H(coffhdr.f_nsyms)); + return; + } + else { + PRINTF("Not COFF file format\n"); + fseek(inputfs, 0, SEEK_SET); + } + } + if (fread(&elfhdr, sizeof(elfhdr), 1, inputfs) == 1) { + if (elfhdr.e_ident[0] == 0x7f && elfhdr.e_ident[1] == 0x45 && elfhdr.e_ident[2] == 0x4c && elfhdr.e_ident[3] == 0x46) { + PRINTF("ELF type: 0x%.4x\n", ELF_SHORT_H(elfhdr.e_type)); + PRINTF("ELF machine: 0x%.4x\n", ELF_SHORT_H(elfhdr.e_machine)); + PRINTF("ELF version: 0x%.8lx\n", ELF_LONG_H(elfhdr.e_version)); + PRINTF("ELF sec = %d\n", ELF_SHORT_H(elfhdr.e_shnum)); + if (ELF_SHORT_H(elfhdr.e_type) != ET_EXEC ) { + PRINTF("This ELF is not an executable.\n"); + exit(1); + } + fclose(inputfs); + readfile_elf(filename); + return; + } + else { + PRINTF("Not ELF file format.\n"); + fseek(inputfs, 0, SEEK_SET); + } + } + + perror("identifyfile2"); + fclose(inputfs); + + return; +} + + +/* Loads file to memory starting at address startaddr and returns freemem. */ +unsigned long loadcode(char *filename, oraddr_t startaddr, oraddr_t virtphy_transl) +{ + int breakpoint = 0; + + transl_error = 0; + transl_table = virtphy_transl; + freemem = startaddr; + PRINTF("loadcode: filename %s startaddr=%"PRIxADDR" virtphy_transl=%"PRIxADDR"\n", + filename, startaddr, virtphy_transl); + identifyfile(filename); + +#if IMM_STATS + { + int i = 0, a = 0, b = 0, c = 0; + PRINTF ("index:arith/branch/jump\n"); + for (i = 0; i < 33; i++) + PRINTF ("%2i:\t%3.0f%% / %3.0f%%/ %3.0f%%\t%5i / %5i / %5i\n", i, + 100.* (a += bcnt[i][0])/bsum[0], 100.* (b += bcnt[i][1])/bsum[1], + 100.* (c += bcnt[i][2])/bsum[2], bcnt[i][0], bcnt[i][1], bcnt[i][2]); + PRINTF ("\nsum %i %i %i\n", bsum[0], bsum[1], bsum[2]); + } +#endif + + if (transl_error) + return -1; + else + return translate(freemem,&breakpoint); + +} Index: trace.c =================================================================== --- trace.c (nonexistent) +++ trace.c (revision 1765) @@ -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 + +#include "config.h" + +#ifdef HAVE_INTTYPES_H +#include +#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 &= 0xfffffffc; /* 32-bit aligned */ + + if (verify_memoryarea(addr)) + 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); + } + else + PRINTF("ERROR: Can't set this breakpoint out of memory.\n"); + + return; +} + Index: trace.h =================================================================== --- trace.h (nonexistent) +++ trace.h (revision 1765) @@ -0,0 +1,2 @@ + +void set_insnbrkpoint(oraddr_t addr); Index: execute.h =================================================================== --- execute.h (nonexistent) +++ execute.h (revision 1765) @@ -0,0 +1,32 @@ +/* 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. */ + +#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_reg32(unsigned int regno, uorreg_t value); + +extern oraddr_t pcnext; +int depend_operands(struct iqueue_entry *prev, struct iqueue_entry *next); 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

powered by: WebSVN 2.1.0

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