filename | src/sh4/pmm.c |
changeset | 929:fd8cb0c82f5f |
prev | 841:808d64b05073 |
next | 975:007bf7eb944f |
author | nkeynes |
date | Sat Dec 27 02:59:35 2008 +0000 (15 years ago) |
branch | lxdream-mem |
permissions | -rw-r--r-- |
last change | Replace fpscr_mask/fpscr flags in xlat_cache_block with a single xlat_sh4_mode, which tracks the field of the same name in sh4r - actually a little faster this way. Now depends on SR.MD, FPSCR.PR and FPSCR.SZ (although it doesn't benefit from the SR flag yet). Also fixed the failure to check the flags in the common case (code address returned by previous block) which took away the performance benefits, but oh well. |
view | annotate | diff | log | raw |
1 /**
2 * $Id: pmm.c 833 2008-08-18 12:18:10Z nkeynes $
3 *
4 * PMM (performance counter) module
5 *
6 * Copyright (c) 2005 Nathan Keynes.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
19 #include "sh4/sh4mmio.h"
20 #include "sh4/sh4core.h"
21 #include "clock.h"
23 /*
24 * Performance counter list from Paul Mundt's OProfile patch
25 * Currently only 0x23 is actually supported, since it doesn't require any
26 * actual instrumentation
27 *
28 * 0x01 Operand read access
29 * 0x02 Operand write access
30 * 0x03 UTLB miss
31 * 0x04 Operand cache read miss
32 * 0x05 Operand cache write miss
33 * 0x06 Instruction fetch (w/ cache)
34 * 0x07 Instruction TLB miss
35 * 0x08 Instruction cache miss
36 * 0x09 All operand accesses
37 * 0x0a All instruction accesses
38 * 0x0b OC RAM operand access
39 * 0x0d On-chip I/O space access
40 * 0x0e Operand access (r/w)
41 * 0x0f Operand cache miss (r/w)
42 * 0x10 Branch instruction
43 * 0x11 Branch taken
44 * 0x12 BSR/BSRF/JSR
45 * 0x13 Instruction execution
46 * 0x14 Instruction execution in parallel
47 * 0x15 FPU Instruction execution
48 * 0x16 Interrupt
49 * 0x17 NMI
50 * 0x18 trapa instruction execution
51 * 0x19 UBCA match
52 * 0x1a UBCB match
53 * 0x21 Instruction cache fill
54 * 0x22 Operand cache fill
55 * 0x23 Elapsed time
56 * 0x24 Pipeline freeze by I-cache miss
57 * 0x25 Pipeline freeze by D-cache miss
58 * 0x27 Pipeline freeze by branch instruction
59 * 0x28 Pipeline freeze by CPU register
60 * 0x29 Pipeline freeze by FPU
61 */
62 struct PMM_counter_struct {
63 uint64_t count;
64 uint32_t mode; /* if running only, otherwise 0 */
65 uint32_t runfor;
66 };
68 static struct PMM_counter_struct PMM_counter[2] = {{0,0},{0,0}};
70 void PMM_reset(void)
71 {
72 PMM_counter[0].count = 0;
73 PMM_counter[0].mode = 0;
74 PMM_counter[0].runfor = 0;
75 PMM_counter[1].count = 0;
76 PMM_counter[1].mode = 0;
77 PMM_counter[1].runfor = 0;
78 }
80 void PMM_save_state( FILE *f ) {
81 fwrite( &PMM_counter, sizeof(PMM_counter), 1, f );
82 }
84 int PMM_load_state( FILE *f )
85 {
86 fread( &PMM_counter, sizeof(PMM_counter), 1, f );
87 return 0;
88 }
90 void PMM_count( int ctr, uint32_t runfor )
91 {
92 uint32_t delta = runfor - PMM_counter[ctr].runfor;
94 switch( PMM_counter[ctr].mode ) {
95 case 0x23:
96 PMM_counter[ctr].count += (delta / (1000/SH4_BASE_RATE));
97 break;
98 default:
99 break;
100 }
102 PMM_counter[ctr].runfor = runfor;
103 }
105 uint32_t PMM_run_slice( uint32_t nanosecs )
106 {
107 PMM_count( 0, nanosecs );
108 PMM_count( 1, nanosecs );
109 PMM_counter[0].runfor = 0;
110 PMM_counter[1].runfor = 0;
111 return nanosecs;
112 }
114 void PMM_write_control( int ctr, uint32_t val )
115 {
116 int is_running = ((val & PMCR_RUNNING) == PMCR_RUNNING);
118 PMM_count(ctr, sh4r.slice_cycle);
119 if( PMM_counter[ctr].mode == 0 && (val & PMCR_PMCLR) != 0 ) {
120 PMM_counter[ctr].count = 0;
121 }
122 if( is_running ) {
123 int mode = val & 0x3F;
124 if( mode != PMM_counter[ctr].mode ) {
125 /* Instrumentation setup goes here */
126 PMM_counter[ctr].mode = mode;
127 }
128 } else if( PMM_counter[ctr].mode != 0 ) {
129 /* Instrumentation removal goes here */
130 PMM_counter[ctr].mode = 0;
131 }
132 }
134 MMIO_REGION_READ_FN( PMM, reg )
135 {
136 switch( reg & 0x1F ) {
137 case 0: return 0; /* not a register */
138 case PMCTR1H:
139 PMM_count(0, sh4r.slice_cycle);
140 return ((uint32_t)(PMM_counter[0].count >> 32)) & 0x0000FFFF;
141 case PMCTR1L:
142 PMM_count(0, sh4r.slice_cycle);
143 return (uint32_t)PMM_counter[0].count;
144 case PMCTR2H:
145 PMM_count(1, sh4r.slice_cycle);
146 return ((uint32_t)(PMM_counter[1].count >> 32)) & 0x0000FFFF;
147 default:
148 PMM_count(1, sh4r.slice_cycle);
149 return (uint32_t)PMM_counter[1].count;
150 }
151 }
153 MMIO_REGION_WRITE_FN( PMM, reg, val )
154 {
155 /* Read-only */
156 }
.