Improve tracing a bit, also in interpreter mode
This commit is contained in:
parent
46d8616a9f
commit
bd39c03992
5 changed files with 137 additions and 102 deletions
1
Makefile
1
Makefile
|
@ -499,6 +499,7 @@ ifeq ($(MMAP_JIT_CACHE), 1)
|
||||||
CFLAGS += -DMMAP_JIT_CACHE
|
CFLAGS += -DMMAP_JIT_CACHE
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Add -DTRACE_EVENTS to trace relevant events (IRQs, SMC, etc)
|
||||||
# Add -DTRACE_INSTRUCTIONS to trace instruction execution
|
# Add -DTRACE_INSTRUCTIONS to trace instruction execution
|
||||||
# Can add -DTRACE_REGISTERS to additionally print register values
|
# Can add -DTRACE_REGISTERS to additionally print register values
|
||||||
ifeq ($(DEBUG), 1)
|
ifeq ($(DEBUG), 1)
|
||||||
|
|
112
cpu.c
112
cpu.c
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
|
#include "cpu_instrument.h"
|
||||||
|
|
||||||
u32 memory_region_access_read_u8[16];
|
u32 memory_region_access_read_u8[16];
|
||||||
u32 memory_region_access_read_s8[16];
|
u32 memory_region_access_read_s8[16];
|
||||||
u32 memory_region_access_read_u16[16];
|
u32 memory_region_access_read_u16[16];
|
||||||
|
@ -57,108 +59,6 @@ const u8 bit_count[256] =
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef REGISTER_USAGE_ANALYZE
|
|
||||||
|
|
||||||
u64 instructions_total = 0;
|
|
||||||
|
|
||||||
u64 arm_reg_freq[16];
|
|
||||||
u64 arm_reg_access_total = 0;
|
|
||||||
u64 arm_instructions_total = 0;
|
|
||||||
|
|
||||||
u64 thumb_reg_freq[16];
|
|
||||||
u64 thumb_reg_access_total = 0;
|
|
||||||
u64 thumb_instructions_total = 0;
|
|
||||||
|
|
||||||
// mla/long mla's addition operand are not counted yet.
|
|
||||||
|
|
||||||
#define using_register(instruction_set, register, type) \
|
|
||||||
instruction_set##_reg_freq[register]++; \
|
|
||||||
instruction_set##_reg_access_total++ \
|
|
||||||
|
|
||||||
#define using_register_list(instruction_set, rlist, count) \
|
|
||||||
{ \
|
|
||||||
u32 i; \
|
|
||||||
for(i = 0; i < count; i++) \
|
|
||||||
{ \
|
|
||||||
if((reg_list >> i) & 0x01) \
|
|
||||||
{ \
|
|
||||||
using_register(instruction_set, i, memory_target); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
|
|
||||||
#define using_instruction(instruction_set) \
|
|
||||||
instruction_set##_instructions_total++; \
|
|
||||||
instructions_total++ \
|
|
||||||
|
|
||||||
int sort_tagged_element(const void *_a, const void *_b)
|
|
||||||
{
|
|
||||||
const u64 *a = _a;
|
|
||||||
const u64 *b = _b;
|
|
||||||
|
|
||||||
return (int)(b[1] - a[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_register_usage(void)
|
|
||||||
{
|
|
||||||
u32 i;
|
|
||||||
u64 arm_reg_freq_tagged[32];
|
|
||||||
u64 thumb_reg_freq_tagged[32];
|
|
||||||
double percent;
|
|
||||||
double percent_total = 0.0;
|
|
||||||
|
|
||||||
for(i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
arm_reg_freq_tagged[i * 2] = i;
|
|
||||||
arm_reg_freq_tagged[(i * 2) + 1] = arm_reg_freq[i];
|
|
||||||
thumb_reg_freq_tagged[i * 2] = i;
|
|
||||||
thumb_reg_freq_tagged[(i * 2) + 1] = thumb_reg_freq[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort(arm_reg_freq_tagged, 16, sizeof(u64) * 2, sort_tagged_element);
|
|
||||||
qsort(thumb_reg_freq_tagged, 16, sizeof(u64) * 2, sort_tagged_element);
|
|
||||||
|
|
||||||
printf("ARM register usage (%lf%% ARM instructions):\n",
|
|
||||||
(arm_instructions_total * 100.0) / instructions_total);
|
|
||||||
for(i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
percent = (arm_reg_freq_tagged[(i * 2) + 1] * 100.0) /
|
|
||||||
arm_reg_access_total;
|
|
||||||
percent_total += percent;
|
|
||||||
printf("r%02d: %lf%% (-- %lf%%)\n",
|
|
||||||
(u32)arm_reg_freq_tagged[(i * 2)], percent, percent_total);
|
|
||||||
}
|
|
||||||
|
|
||||||
percent_total = 0.0;
|
|
||||||
|
|
||||||
printf("\nThumb register usage (%lf%% Thumb instructions):\n",
|
|
||||||
(thumb_instructions_total * 100.0) / instructions_total);
|
|
||||||
for(i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
percent = (thumb_reg_freq_tagged[(i * 2) + 1] * 100.0) /
|
|
||||||
thumb_reg_access_total;
|
|
||||||
percent_total += percent;
|
|
||||||
printf("r%02d: %lf%% (-- %lf%%)\n",
|
|
||||||
(u32)thumb_reg_freq_tagged[(i * 2)], percent, percent_total);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(arm_reg_freq, 0, sizeof(u64) * 16);
|
|
||||||
memset(thumb_reg_freq, 0, sizeof(u64) * 16);
|
|
||||||
arm_reg_access_total = 0;
|
|
||||||
thumb_reg_access_total = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#define using_register(instruction_set, register, type) \
|
|
||||||
|
|
||||||
#define using_register_list(instruction_set, rlist, count) \
|
|
||||||
|
|
||||||
#define using_instruction(instruction_set) \
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#define arm_decode_data_proc_reg(opcode) \
|
#define arm_decode_data_proc_reg(opcode) \
|
||||||
u32 rn = (opcode >> 16) & 0x0F; \
|
u32 rn = (opcode >> 16) & 0x0F; \
|
||||||
u32 rd = (opcode >> 12) & 0x0F; \
|
u32 rd = (opcode >> 12) & 0x0F; \
|
||||||
|
@ -1785,6 +1685,10 @@ arm_loop:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TRACE_INSTRUCTIONS
|
||||||
|
interp_trace_instruction(pc, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
switch((opcode >> 20) & 0xFF)
|
switch((opcode >> 20) & 0xFF)
|
||||||
{
|
{
|
||||||
case 0x00:
|
case 0x00:
|
||||||
|
@ -3274,6 +3178,10 @@ thumb_loop:
|
||||||
pc &= ~0x01;
|
pc &= ~0x01;
|
||||||
opcode = readaddress16(pc_address_block, (pc & 0x7FFF));
|
opcode = readaddress16(pc_address_block, (pc & 0x7FFF));
|
||||||
|
|
||||||
|
#ifdef TRACE_INSTRUCTIONS
|
||||||
|
interp_trace_instruction(pc, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
switch((opcode >> 8) & 0xFF)
|
switch((opcode >> 8) & 0xFF)
|
||||||
{
|
{
|
||||||
case 0x00 ... 0x07:
|
case 0x00 ... 0x07:
|
||||||
|
|
117
cpu_instrument.h
Normal file
117
cpu_instrument.h
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
|
||||||
|
// Instrumentation and debugging code
|
||||||
|
// Used to count instruction and register usage
|
||||||
|
// Also provides some tracing capabilities
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef REGISTER_USAGE_ANALYZE
|
||||||
|
|
||||||
|
u64 instructions_total = 0;
|
||||||
|
u64 arm_reg_freq[16];
|
||||||
|
u64 arm_reg_access_total = 0;
|
||||||
|
u64 arm_instructions_total = 0;
|
||||||
|
u64 thumb_reg_freq[16];
|
||||||
|
u64 thumb_reg_access_total = 0;
|
||||||
|
u64 thumb_instructions_total = 0;
|
||||||
|
|
||||||
|
// mla/long mla's addition operand are not counted yet.
|
||||||
|
|
||||||
|
#define using_register(instruction_set, register, type) \
|
||||||
|
instruction_set##_reg_freq[register]++; \
|
||||||
|
instruction_set##_reg_access_total++ \
|
||||||
|
|
||||||
|
#define using_register_list(instruction_set, rlist, count) \
|
||||||
|
{ \
|
||||||
|
u32 i; \
|
||||||
|
for(i = 0; i < count; i++) \
|
||||||
|
{ \
|
||||||
|
if((reg_list >> i) & 0x01) \
|
||||||
|
{ \
|
||||||
|
using_register(instruction_set, i, memory_target); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
#define using_instruction(instruction_set) \
|
||||||
|
instruction_set##_instructions_total++; \
|
||||||
|
instructions_total++ \
|
||||||
|
|
||||||
|
int sort_tagged_element(const void *_a, const void *_b)
|
||||||
|
{
|
||||||
|
const u64 *a = _a;
|
||||||
|
const u64 *b = _b;
|
||||||
|
|
||||||
|
return (int)(b[1] - a[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_register_usage(void)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
u64 arm_reg_freq_tagged[32];
|
||||||
|
u64 thumb_reg_freq_tagged[32];
|
||||||
|
double percent;
|
||||||
|
double percent_total = 0.0;
|
||||||
|
|
||||||
|
for(i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
arm_reg_freq_tagged[i * 2] = i;
|
||||||
|
arm_reg_freq_tagged[(i * 2) + 1] = arm_reg_freq[i];
|
||||||
|
thumb_reg_freq_tagged[i * 2] = i;
|
||||||
|
thumb_reg_freq_tagged[(i * 2) + 1] = thumb_reg_freq[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort(arm_reg_freq_tagged, 16, sizeof(u64) * 2, sort_tagged_element);
|
||||||
|
qsort(thumb_reg_freq_tagged, 16, sizeof(u64) * 2, sort_tagged_element);
|
||||||
|
|
||||||
|
printf("ARM register usage (%lf%% ARM instructions):\n",
|
||||||
|
(arm_instructions_total * 100.0) / instructions_total);
|
||||||
|
for(i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
percent = (arm_reg_freq_tagged[(i * 2) + 1] * 100.0) /
|
||||||
|
arm_reg_access_total;
|
||||||
|
percent_total += percent;
|
||||||
|
printf("r%02d: %lf%% (-- %lf%%)\n",
|
||||||
|
(u32)arm_reg_freq_tagged[(i * 2)], percent, percent_total);
|
||||||
|
}
|
||||||
|
|
||||||
|
percent_total = 0.0;
|
||||||
|
|
||||||
|
printf("\nThumb register usage (%lf%% Thumb instructions):\n",
|
||||||
|
(thumb_instructions_total * 100.0) / instructions_total);
|
||||||
|
for(i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
percent = (thumb_reg_freq_tagged[(i * 2) + 1] * 100.0) /
|
||||||
|
thumb_reg_access_total;
|
||||||
|
percent_total += percent;
|
||||||
|
printf("r%02d: %lf%% (-- %lf%%)\n",
|
||||||
|
(u32)thumb_reg_freq_tagged[(i * 2)], percent, percent_total);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(arm_reg_freq, 0, sizeof(u64) * 16);
|
||||||
|
memset(thumb_reg_freq, 0, sizeof(u64) * 16);
|
||||||
|
arm_reg_access_total = 0;
|
||||||
|
thumb_reg_access_total = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* REGISTER_USAGE_ANALYZE */
|
||||||
|
|
||||||
|
#define using_register(instruction_set, register, type)
|
||||||
|
#define using_register_list(instruction_set, rlist, count)
|
||||||
|
#define using_instruction(instruction_set)
|
||||||
|
|
||||||
|
#endif /* REGISTER_USAGE_ANALYZE */
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef TRACE_INSTRUCTIONS
|
||||||
|
static void interp_trace_instruction(u32 pc, u32 mode)
|
||||||
|
{
|
||||||
|
if (mode)
|
||||||
|
printf("Executed arm %x\n", pc);
|
||||||
|
else
|
||||||
|
printf("Executed thumb %x\n", pc);
|
||||||
|
#ifdef TRACE_REGISTERS
|
||||||
|
print_regs();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
2
main.c
2
main.c
|
@ -111,6 +111,8 @@ u32 function_cc update_gba(int remaining_cycles)
|
||||||
{
|
{
|
||||||
irq_type irq_raised = IRQ_NONE;
|
irq_type irq_raised = IRQ_NONE;
|
||||||
int dma_cycles;
|
int dma_cycles;
|
||||||
|
trace_update_gba(remaining_cycles);
|
||||||
|
|
||||||
remaining_cycles = MAX(remaining_cycles, -64);
|
remaining_cycles = MAX(remaining_cycles, -64);
|
||||||
|
|
||||||
do
|
do
|
||||||
|
|
7
main.h
7
main.h
|
@ -93,6 +93,13 @@ extern boot_mode selected_boot_mode;
|
||||||
void print_regs(void);
|
void print_regs(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef TRACE_EVENTS
|
||||||
|
#define trace_update_gba(remcyc) \
|
||||||
|
printf("update_gba: %d remaining cycles\n", (remcyc));
|
||||||
|
#else /* TRACE_EVENTS */
|
||||||
|
#define trace_update_gba(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue