URL
https://opencores.org/ocsvn/zet86/zet86/trunk
Subversion Repositories zet86
Compare Revisions
- This comparison shows the changes necessary to convert path
/zet86/trunk/src/bochs-diff-2.3.7/instrument
- from Rev 43 to Rev 49
- ↔ Reverse comparison
Rev 43 → Rev 49
/zet/instrument.cc
0,0 → 1,295
///////////////////////////////////////////////////////////////////////// |
// $Id: instrument.cc,v 1.5 2009-02-06 03:48:31 zeus Exp $ |
///////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2001 MandrakeSoft S.A. |
// |
// MandrakeSoft S.A. |
// 43, rue d'Aboukir |
// 75002 Paris - France |
// http://www.linux-mandrake.com/ |
// http://www.mandrakesoft.com/ |
// |
// This library is free software; you can redistribute it and/or |
// modify it under the terms of the GNU Lesser General Public |
// License as published by the Free Software Foundation; either |
// version 2 of the License, or (at your option) any later version. |
// |
// This library 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 |
// Lesser General Public License for more details. |
// |
// You should have received a copy of the GNU Lesser General Public |
// License along with this library; if not, write to the Free Software |
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
|
#include <assert.h> |
#include <map> |
#include <string> |
#include <iostream> |
using std::cerr; |
using std::endl; |
|
|
#include "bochs.h" |
#include "cpu/cpu.h" |
|
// maximum size of an instruction |
#define MAX_OPCODE_SIZE 16 |
|
// maximum physical addresses an instruction can generate |
#define MAX_DATA_ACCESSES 1024 |
|
// Use this variable to turn on/off collection of instrumentation data |
// If you are not using the debugger to turn this on/off, then possibly |
// start this at 1 instead of 0. |
typedef std::map<std::string, unsigned> TStrUIntMap; |
TStrUIntMap *stats = 0; |
|
unsigned long ninstr = 0; |
|
static disassembler bx_disassembler; |
|
static struct instruction_t { |
bx_bool valid; // is current instruction valid |
unsigned opcode_size; |
unsigned nprefixes; |
Bit8u opcode[MAX_OPCODE_SIZE]; |
bx_bool is32, is64; |
unsigned num_data_accesses; |
struct { |
bx_address laddr; // linear address |
bx_phy_address paddr; // physical address |
unsigned op; // BX_READ, BX_WRITE or BX_RW |
unsigned size; // 1 .. 8 |
} data_access[MAX_DATA_ACCESSES]; |
bx_bool is_branch; |
bx_bool is_taken; |
bx_address target_linear; |
} *instruction; |
|
static logfunctions *instrument_log = new logfunctions (); |
#define LOG_THIS instrument_log-> |
|
void bx_instr_init(unsigned cpu) |
{ |
assert(cpu < BX_SMP_PROCESSORS); |
|
if (instruction == NULL) |
instruction = new struct instruction_t[BX_SMP_PROCESSORS]; |
|
fprintf(stderr, "Initialize cpu %d\n", cpu); |
|
bx_disassembler.toggle_syntax_mode(); |
} |
|
void bx_instr_reset(unsigned cpu) |
{ |
instruction[cpu].valid = 0; |
instruction[cpu].nprefixes = 0; |
instruction[cpu].num_data_accesses = 0; |
instruction[cpu].is_branch = 0; |
} |
|
void bx_instr_print() |
{ |
if (stats) |
{ |
cerr << "stats contains:\nKey\tValue\n"; |
|
// use const_iterator to walk through elements of pairs |
for ( std::map<std::string, unsigned> |
::const_iterator iter = stats->begin(); |
iter != stats->end(); ++iter ) |
|
cerr << iter->first << '\t' << iter->second << '\n'; |
|
cerr << endl; |
cerr << "# instr: " << ninstr << endl; |
} |
else |
{ |
cerr << "There's no statistics to show!" << endl; |
} |
} |
|
void bx_instr_start() |
{ |
if (stats) cerr << "instrumentation already started" << endl; |
else stats = new TStrUIntMap; |
} |
|
void bx_instr_stop() |
{ |
if (stats) |
{ |
delete stats; |
stats = 0; |
} |
else |
{ |
cerr << "there's no statistics to stop!" << endl; |
} |
} |
|
void bx_instr_new_instruction(unsigned cpu) |
{ |
Bit16u sel; |
if (!stats) return; |
|
ninstr++; |
instruction_t *i = &instruction[cpu]; |
|
if (i->valid) |
{ |
char disasm_tbuf[512]; // buffer for instruction disassembly |
unsigned length = i->opcode_size, n; |
|
bx_disassembler.disasm(i->is32, i->is64, 0, 0, i->opcode, disasm_tbuf); |
|
if(length != 0) |
{ |
sel = bx_cpu.sregs[BX_SEG_REG_CS].selector.value; |
if (sel!=0xf000 && sel!=0xc000) { |
(*stats)[std::string(disasm_tbuf)]++; |
} |
} |
} |
|
instruction[cpu].valid = 0; |
instruction[cpu].nprefixes = 0; |
instruction[cpu].num_data_accesses = 0; |
instruction[cpu].is_branch = 0; |
} |
|
static void branch_taken(unsigned cpu, bx_address new_eip) |
{ |
if (!stats || !instruction[cpu].valid) return; |
|
// find linear address |
bx_address laddr = BX_CPU(cpu)->get_laddr(BX_SEG_REG_CS, new_eip); |
|
instruction[cpu].is_branch = 1; |
instruction[cpu].is_taken = 1; |
instruction[cpu].target_linear = laddr; |
} |
|
void bx_instr_cnear_branch_taken(unsigned cpu, bx_address new_eip) |
{ |
branch_taken(cpu, new_eip); |
} |
|
void bx_instr_cnear_branch_not_taken(unsigned cpu) |
{ |
if (!stats || !instruction[cpu].valid) return; |
|
instruction[cpu].is_branch = 1; |
instruction[cpu].is_taken = 0; |
} |
|
void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address new_eip) |
{ |
branch_taken(cpu, new_eip); |
} |
|
void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip) |
{ |
branch_taken(cpu, new_eip); |
} |
|
void bx_instr_opcode(unsigned cpu, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64) |
{ |
if (!stats) return; |
|
for(unsigned i=0;i<len;i++) |
{ |
instruction[cpu].opcode[i] = opcode[i]; |
} |
|
instruction[cpu].is32 = is32; |
instruction[cpu].is64 = is64; |
instruction[cpu].opcode_size = len; |
} |
|
void bx_instr_fetch_decode_completed(unsigned cpu, bxInstruction_c *i) |
{ |
if(stats) instruction[cpu].valid = 1; |
} |
|
void bx_instr_prefix(unsigned cpu, Bit8u prefix) |
{ |
if(stats) instruction[cpu].nprefixes++; |
} |
|
void bx_instr_interrupt(unsigned cpu, unsigned vector) |
{ |
char tmpbuf[50]; |
Bit16u sel; |
if(stats) |
{ |
sel = bx_cpu.sregs[BX_SEG_REG_CS].selector.value; |
if (sel!=0xf000 && sel!=0xc000) { |
sprintf(tmpbuf, "int %02xh AH=%02x", vector, |
bx_cpu.gen_reg[0].word.byte.rh); |
(*stats)[std::string(tmpbuf)]++; |
} |
} |
} |
|
void bx_instr_exception(unsigned cpu, unsigned vector) |
{ |
char tmpbuf[50]; |
if(stats) |
{ |
sprintf(tmpbuf, "exc %02xh", vector); |
(*stats)[std::string(tmpbuf)]++; |
} |
} |
|
void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip) |
{ |
char tmpbuf[50]; |
if(stats) |
{ |
sprintf(tmpbuf, "hwint %02xh", vector); |
(*stats)[std::string(tmpbuf)]++; |
} |
} |
|
void bx_instr_mem_data(unsigned cpu, unsigned seg, bx_address offset, unsigned len, unsigned rw) |
{ |
unsigned index; |
bx_phy_address phy; |
|
if(!stats || !instruction[cpu].valid) return; |
|
if (instruction[cpu].num_data_accesses >= MAX_DATA_ACCESSES) |
{ |
return; |
} |
|
bx_address lin = BX_CPU(cpu)->get_laddr(seg, offset); |
bx_bool page_valid = BX_CPU(cpu)->dbg_xlate_linear2phy(lin, &phy); |
phy = A20ADDR(phy); |
|
// If linear translation doesn't exist, a paging exception will occur. |
// Invalidate physical address data for now. |
if (!page_valid) |
{ |
phy = 0; |
} |
|
index = instruction[cpu].num_data_accesses; |
instruction[cpu].data_access[index].laddr = lin; |
instruction[cpu].data_access[index].paddr = phy; |
instruction[cpu].data_access[index].op = rw; |
// instruction[cpu].data_access[index].size = size; |
instruction[cpu].num_data_accesses++; |
} |
|
void bx_instr_mem_data_access(unsigned cpu, unsigned seg, unsigned offset, unsigned len, unsigned rw) |
{ |
return; |
} |
/zet/instrument.h
0,0 → 1,213
///////////////////////////////////////////////////////////////////////// |
// $Id: instrument.h,v 1.5 2009-02-06 03:48:31 zeus Exp $ |
///////////////////////////////////////////////////////////////////////// |
// |
// Copyright (C) 2001 MandrakeSoft S.A. |
// |
// MandrakeSoft S.A. |
// 43, rue d'Aboukir |
// 75002 Paris - France |
// http://www.linux-mandrake.com/ |
// http://www.mandrakesoft.com/ |
// |
// This library is free software; you can redistribute it and/or |
// modify it under the terms of the GNU Lesser General Public |
// License as published by the Free Software Foundation; either |
// version 2 of the License, or (at your option) any later version. |
// |
// This library 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 |
// Lesser General Public License for more details. |
// |
// You should have received a copy of the GNU Lesser General Public |
// License along with this library; if not, write to the Free Software |
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
|
// possible types passed to BX_INSTR_TLB_CNTRL() |
#define BX_INSTR_MOV_CR3 10 |
#define BX_INSTR_INVLPG 11 |
#define BX_INSTR_TASKSWITCH 12 |
|
// possible types passed to BX_INSTR_CACHE_CNTRL() |
#define BX_INSTR_INVD 20 |
#define BX_INSTR_WBINVD 21 |
|
// possible types passed to BX_INSTR_FAR_BRANCH() |
#define BX_INSTR_IS_CALL 10 |
#define BX_INSTR_IS_RET 11 |
#define BX_INSTR_IS_IRET 12 |
#define BX_INSTR_IS_JMP 13 |
#define BX_INSTR_IS_INT 14 |
#define BX_INSTR_IS_SYSCALL 15 |
#define BX_INSTR_IS_SYSRET 16 |
#define BX_INSTR_IS_SYSENTER 17 |
#define BX_INSTR_IS_SYSEXIT 18 |
|
// possible types passed to BX_INSTR_PREFETCH_HINT() |
#define BX_INSTR_PREFETCH_NTA 0 |
#define BX_INSTR_PREFETCH_T0 1 |
#define BX_INSTR_PREFETCH_T1 2 |
#define BX_INSTR_PREFETCH_T2 3 |
|
|
#if BX_INSTRUMENTATION |
|
class bxInstruction_c; |
|
// called from the CPU core |
|
void bx_instr_init(unsigned cpu); |
void bx_instr_reset(unsigned cpu); |
void bx_instr_start(); |
void bx_instr_stop(); |
void bx_instr_print(); |
void bx_instr_new_instruction(unsigned cpu); |
|
void bx_instr_cnear_branch_taken(unsigned cpu, bx_address new_eip); |
void bx_instr_cnear_branch_not_taken(unsigned cpu); |
void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address new_eip); |
void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip); |
|
void bx_instr_opcode(unsigned cpu, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64); |
void bx_instr_fetch_decode_completed(unsigned cpu, bxInstruction_c *i); |
|
void bx_instr_prefix(unsigned cpu, Bit8u prefix); |
|
void bx_instr_interrupt(unsigned cpu, unsigned vector); |
void bx_instr_exception(unsigned cpu, unsigned vector); |
void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip); |
|
void bx_instr_mem_data_access(unsigned cpu, unsigned seg, bx_address offset, unsigned len, unsigned rw); |
|
/* simulation init, shutdown, reset */ |
# define BX_INSTR_INIT(cpu_id) bx_instr_init(cpu_id) |
# define BX_INSTR_EXIT(cpu_id) |
# define BX_INSTR_RESET(cpu_id) bx_instr_reset(cpu_id) |
# define BX_INSTR_HLT(cpu_id) |
# define BX_INSTR_MWAIT(cpu_id, addr, len, flags) |
# define BX_INSTR_NEW_INSTRUCTION(cpu_id) bx_instr_new_instruction(cpu_id) |
|
/* called from command line debugger */ |
# define BX_INSTR_DEBUG_PROMPT() |
# define BX_INSTR_START() bx_instr_start() |
# define BX_INSTR_STOP() bx_instr_stop() |
# define BX_INSTR_PRINT() bx_instr_print() |
|
/* branch resoultion */ |
# define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip) bx_instr_cnear_branch_taken(cpu_id, new_eip) |
# define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id) bx_instr_cnear_branch_not_taken(cpu_id) |
# define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip) bx_instr_ucnear_branch(cpu_id, what, new_eip) |
# define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) bx_instr_far_branch(cpu_id, what, new_cs, new_eip) |
|
/* decoding completed */ |
# define BX_INSTR_OPCODE(cpu_id, opcode, len, is32, is64) \ |
bx_instr_opcode(cpu_id, opcode, len, is32, is64) |
# define BX_INSTR_FETCH_DECODE_COMPLETED(cpu_id, i) \ |
bx_instr_fetch_decode_completed(cpu_id, i) |
|
/* prefix byte decoded */ |
# define BX_INSTR_PREFIX(cpu_id, prefix) bx_instr_prefix(cpu_id, prefix) |
|
/* exceptional case and interrupt */ |
# define BX_INSTR_EXCEPTION(cpu_id, vector) bx_instr_exception(cpu_id, vector) |
# define BX_INSTR_INTERRUPT(cpu_id, vector) bx_instr_interrupt(cpu_id, vector) |
# define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) bx_instr_hwinterrupt(cpu_id, vector, cs, eip) |
|
/* TLB/CACHE control instruction executed */ |
# define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr) |
# define BX_INSTR_CACHE_CNTRL(cpu_id, what) |
# define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3) |
# define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) |
|
/* execution */ |
# define BX_INSTR_BEFORE_EXECUTION(cpu_id, i) |
# define BX_INSTR_AFTER_EXECUTION(cpu_id, i) |
# define BX_INSTR_REPEAT_ITERATION(cpu_id, i) |
|
/* memory access */ |
# define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw) |
|
/* memory access */ |
# define BX_INSTR_MEM_DATA_ACCESS(cpu_id, seg, offset, len, rw) \ |
bx_instr_mem_data_access(cpu_id, seg, offset, len, rw) |
|
/* called from memory object */ |
# define BX_INSTR_PHY_WRITE(cpu_id, addr, len) |
# define BX_INSTR_PHY_READ(cpu_id, addr, len) |
|
/* feedback from device units */ |
# define BX_INSTR_INP(addr, len) |
# define BX_INSTR_INP2(addr, len, val) |
# define BX_INSTR_OUTP(addr, len) |
# define BX_INSTR_OUTP2(addr, len, val) |
|
/* wrmsr callback */ |
# define BX_INSTR_WRMSR(cpu_id, addr, value) |
|
#else |
|
/* simulation init, shutdown, reset */ |
# define BX_INSTR_INIT(cpu_id) |
# define BX_INSTR_EXIT(cpu_id) |
# define BX_INSTR_RESET(cpu_id) |
# define BX_INSTR_HLT(cpu_id) |
# define BX_INSTR_MWAIT(cpu_id, addr, len, flags) |
# define BX_INSTR_NEW_INSTRUCTION(cpu_id) |
|
/* called from command line debugger */ |
# define BX_INSTR_DEBUG_PROMPT() |
# define BX_INSTR_START() |
# define BX_INSTR_STOP() |
# define BX_INSTR_PRINT() |
|
/* branch resoultion */ |
# define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip) |
# define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id) |
# define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip) |
# define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) |
|
/* decoding completed */ |
# define BX_INSTR_OPCODE(cpu_id, opcode, len, is32, is64) |
# define BX_INSTR_FETCH_DECODE_COMPLETED(cpu_id, i) |
|
/* prefix byte decoded */ |
# define BX_INSTR_PREFIX(cpu_id, prefix) |
|
/* exceptional case and interrupt */ |
# define BX_INSTR_EXCEPTION(cpu_id, vector) |
# define BX_INSTR_INTERRUPT(cpu_id, vector) |
# define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) |
|
/* TLB/CACHE control instruction executed */ |
# define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr) |
# define BX_INSTR_CACHE_CNTRL(cpu_id, what) |
# define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3) |
# define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) |
|
/* execution */ |
# define BX_INSTR_BEFORE_EXECUTION(cpu_id, i) |
# define BX_INSTR_AFTER_EXECUTION(cpu_id, i) |
# define BX_INSTR_REPEAT_ITERATION(cpu_id, i) |
|
/* memory access */ |
# define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw) |
|
/* memory access */ |
# define BX_INSTR_MEM_DATA_ACCESS(cpu_id, seg, offset, len, rw) |
|
/* called from memory object */ |
# define BX_INSTR_PHY_WRITE(cpu_id, addr, len) |
# define BX_INSTR_PHY_READ(cpu_id, addr, len) |
|
/* feedback from device units */ |
# define BX_INSTR_INP(addr, len) |
# define BX_INSTR_INP2(addr, len, val) |
# define BX_INSTR_OUTP(addr, len) |
# define BX_INSTR_OUTP2(addr, len, val) |
|
/* wrmsr callback */ |
# define BX_INSTR_WRMSR(cpu_id, addr, value) |
|
#endif |
/zet/Makefile.in
0,0 → 1,77
# Copyright (C) 2001 MandrakeSoft S.A. |
# |
# MandrakeSoft S.A. |
# 43, rue d'Aboukir |
# 75002 Paris - France |
# http://www.linux-mandrake.com/ |
# http://www.mandrakesoft.com/ |
# |
# This library is free software; you can redistribute it and/or |
# modify it under the terms of the GNU Lesser General Public |
# License as published by the Free Software Foundation; either |
# version 2 of the License, or (at your option) any later version. |
# |
# This library 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 |
# Lesser General Public License for more details. |
# |
# You should have received a copy of the GNU Lesser General Public |
# License along with this library; if not, write to the Free Software |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
|
@SUFFIX_LINE@ |
|
srcdir = @srcdir@ |
VPATH = @srcdir@ |
|
SHELL = /bin/sh |
|
@SET_MAKE@ |
|
CC = @CC@ |
CFLAGS = @CFLAGS@ |
CXX = @CXX@ |
CXXFLAGS = @CXXFLAGS@ |
|
LDFLAGS = @LDFLAGS@ |
LIBS = @LIBS@ |
RANLIB = @RANLIB@ |
|
|
# =========================================================== |
# end of configurable options |
# =========================================================== |
|
|
BX_OBJS = \ |
instrument.o |
|
BX_INCLUDES = |
|
BX_INCDIRS = -I../.. -I$(srcdir)/../.. -I. -I$(srcdir)/. |
|
.@CPP_SUFFIX@.o: |
$(CXX) -c $(CXXFLAGS) $(BX_INCDIRS) @CXXFP@$< @OFP@$@ |
|
|
.c.o: |
$(CC) -c $(CFLAGS) $(BX_INCDIRS) @CFP@$< @OFP@$@ |
|
|
|
libinstrument.a: $(BX_OBJS) |
@RMCOMMAND@ libinstrument.a |
@MAKELIB@ $(BX_OBJS) |
$(RANLIB) libinstrument.a |
|
$(BX_OBJS): $(BX_INCLUDES) |
|
|
clean: |
@RMCOMMAND@ *.o |
@RMCOMMAND@ *.a |
|
dist-clean: clean |
@RMCOMMAND@ Makefile |