Commit | Line | Data |
---|---|---|
d45a4bef JB |
1 | /* mem.c --- memory for M32C simulator. |
2 | ||
3 | Copyright (C) 2005 Free Software Foundation, Inc. | |
4 | Contributed by Red Hat, Inc. | |
5 | ||
6 | This file is part of the GNU simulators. | |
7 | ||
8 | The GNU simulators are free software; you can redistribute them and/or | |
9 | modify them under the terms of the GNU General Public License as | |
10 | published by the Free Software Foundation; either version 2 of the | |
11 | License, or (at your option) any later version. | |
12 | ||
13 | The GNU simulators are distributed in the hope that they will be | |
14 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with the GNU simulators; if not, write to the Free Software | |
20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
21 | 02110-1301, USA */ | |
22 | ||
23 | ||
24 | #include <stdio.h> | |
25 | #include <stdlib.h> | |
26 | #include <string.h> | |
27 | ||
28 | #include "mem.h" | |
29 | #include "cpu.h" | |
30 | #include "syscalls.h" | |
31 | #include "misc.h" | |
32 | ||
33 | #define L1_BITS (10) | |
34 | #define L2_BITS (10) | |
35 | #define OFF_BITS (12) | |
36 | ||
37 | #define L1_LEN (1 << L1_BITS) | |
38 | #define L2_LEN (1 << L2_BITS) | |
39 | #define OFF_LEN (1 << OFF_BITS) | |
40 | ||
41 | static unsigned char **pt[L1_LEN]; | |
42 | ||
43 | /* [ get=0/put=1 ][ byte size ] */ | |
44 | static unsigned int mem_counters[2][4]; | |
45 | ||
46 | #define COUNT(isput,bytes) \ | |
47 | if (verbose && enable_counting) mem_counters[isput][bytes]++ | |
48 | ||
49 | void | |
50 | init_mem (void) | |
51 | { | |
52 | int i, j; | |
53 | ||
54 | for (i = 0; i < L1_LEN; i++) | |
55 | if (pt[i]) | |
56 | { | |
57 | for (j = 0; j < L2_LEN; j++) | |
58 | if (pt[i][j]) | |
59 | free (pt[i][j]); | |
60 | free (pt[i]); | |
61 | } | |
62 | memset (pt, 0, sizeof (pt)); | |
63 | memset (mem_counters, 0, sizeof (mem_counters)); | |
64 | } | |
65 | ||
66 | static unsigned char * | |
67 | mem_ptr (address) | |
68 | { | |
69 | int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1); | |
70 | int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1); | |
71 | int pto = address & ((1 << OFF_BITS) - 1); | |
72 | ||
73 | if (address == 0) | |
74 | { | |
75 | printf ("NULL pointer dereference\n"); | |
76 | exit (1); | |
77 | } | |
78 | ||
79 | if (pt[pt1] == 0) | |
80 | pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **)); | |
81 | if (pt[pt1][pt2] == 0) | |
82 | { | |
83 | pt[pt1][pt2] = (unsigned char *) malloc (OFF_LEN); | |
84 | memset (pt[pt1][pt2], 0, OFF_LEN); | |
85 | } | |
86 | ||
87 | return pt[pt1][pt2] + pto; | |
88 | } | |
89 | ||
90 | static void | |
91 | used (int rstart, int i, int j) | |
92 | { | |
93 | int rend = i << (L2_BITS + OFF_BITS); | |
94 | rend += j << OFF_BITS; | |
95 | if (rstart == 0xe0000 && rend == 0xe1000) | |
96 | return; | |
97 | printf ("mem: %08x - %08x (%dk bytes)\n", rstart, rend - 1, | |
98 | (rend - rstart) / 1024); | |
99 | } | |
100 | ||
101 | static char * | |
102 | mcs (int isput, int bytes) | |
103 | { | |
104 | return comma (mem_counters[isput][bytes]); | |
105 | } | |
106 | ||
107 | void | |
108 | mem_usage_stats () | |
109 | { | |
110 | int i, j; | |
111 | int rstart = 0; | |
112 | int pending = 0; | |
113 | ||
114 | for (i = 0; i < L1_LEN; i++) | |
115 | if (pt[i]) | |
116 | { | |
117 | for (j = 0; j < L2_LEN; j++) | |
118 | if (pt[i][j]) | |
119 | { | |
120 | if (!pending) | |
121 | { | |
122 | pending = 1; | |
123 | rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS); | |
124 | } | |
125 | } | |
126 | else if (pending) | |
127 | { | |
128 | pending = 0; | |
129 | used (rstart, i, j); | |
130 | } | |
131 | } | |
132 | else | |
133 | { | |
134 | if (pending) | |
135 | { | |
136 | pending = 0; | |
137 | used (rstart, i, 0); | |
138 | } | |
139 | } | |
140 | /* mem foo: 123456789012 123456789012 123456789012 123456789012 | |
141 | 123456789012 */ | |
142 | printf (" byte short pointer long" | |
143 | " fetch\n"); | |
144 | printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2), | |
145 | mcs (0, 3), mcs (0, 4), mcs (0, 0)); | |
146 | printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2), | |
147 | mcs (1, 3), mcs (1, 4)); | |
148 | } | |
149 | ||
150 | static int tpr = 0; | |
151 | static void | |
152 | s (int address, char *dir) | |
153 | { | |
154 | if (tpr == 0) | |
155 | printf ("MEM[%0*x] %s", membus_mask == 0xfffff ? 5 : 6, address, dir); | |
156 | tpr++; | |
157 | } | |
158 | ||
159 | #define S(d) if (trace) s(address, d) | |
160 | static void | |
161 | e () | |
162 | { | |
163 | if (!trace) | |
164 | return; | |
165 | tpr--; | |
166 | if (tpr == 0) | |
167 | printf ("\n"); | |
168 | } | |
169 | ||
170 | #define E() if (trace) e() | |
171 | ||
172 | void | |
173 | mem_put_byte (int address, unsigned char value) | |
174 | { | |
175 | unsigned char *m; | |
176 | address &= membus_mask; | |
177 | m = mem_ptr (address); | |
178 | if (trace) | |
179 | printf (" %02x", value); | |
180 | *m = value; | |
181 | switch (address) | |
182 | { | |
183 | case 0x00e1: | |
184 | { | |
185 | static int old_led = -1; | |
186 | static char *led_on[] = | |
187 | { "\033[31m O ", "\033[32m O ", "\033[34m O " }; |