Switch the license of all files explicitly copyright the FSF
[external/binutils.git] / sim / m32c / mem.c
1 /* mem.c --- memory for M32C simulator.
2
3 Copyright (C) 2005, 2007 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
5
6 This file is part of the GNU simulators.
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 3 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
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "mem.h"
27 #include "cpu.h"
28 #include "syscalls.h"
29 #include "misc.h"
30
31 #define L1_BITS  (10)
32 #define L2_BITS  (10)
33 #define OFF_BITS (12)
34
35 #define L1_LEN  (1 << L1_BITS)
36 #define L2_LEN  (1 << L2_BITS)
37 #define OFF_LEN (1 << OFF_BITS)
38
39 static unsigned char **pt[L1_LEN];
40
41 /* [ get=0/put=1 ][ byte size ] */
42 static unsigned int mem_counters[2][4];
43
44 #define COUNT(isput,bytes)                                      \
45   if (verbose && enable_counting) mem_counters[isput][bytes]++
46
47 void
48 init_mem (void)
49 {
50   int i, j;
51
52   for (i = 0; i < L1_LEN; i++)
53     if (pt[i])
54       {
55         for (j = 0; j < L2_LEN; j++)
56           if (pt[i][j])
57             free (pt[i][j]);
58         free (pt[i]);
59       }
60   memset (pt, 0, sizeof (pt));
61   memset (mem_counters, 0, sizeof (mem_counters));
62 }
63
64 static unsigned char *
65 mem_ptr (address)
66 {
67   int pt1 = (address >> (L2_BITS + OFF_BITS)) & ((1 << L1_BITS) - 1);
68   int pt2 = (address >> OFF_BITS) & ((1 << L2_BITS) - 1);
69   int pto = address & ((1 << OFF_BITS) - 1);
70
71   if (address == 0)
72     {
73       printf ("NULL pointer dereference\n");
74       exit (1);
75     }
76
77   if (pt[pt1] == 0)
78     pt[pt1] = (unsigned char **) calloc (L2_LEN, sizeof (char **));
79   if (pt[pt1][pt2] == 0)
80     {
81       pt[pt1][pt2] = (unsigned char *) malloc (OFF_LEN);
82       memset (pt[pt1][pt2], 0, OFF_LEN);
83     }
84
85   return pt[pt1][pt2] + pto;
86 }
87
88 static void
89 used (int rstart, int i, int j)
90 {
91   int rend = i << (L2_BITS + OFF_BITS);
92   rend += j << OFF_BITS;
93   if (rstart == 0xe0000 && rend == 0xe1000)
94     return;
95   printf ("mem:   %08x - %08x (%dk bytes)\n", rstart, rend - 1,
96           (rend - rstart) / 1024);
97 }
98
99 static char *
100 mcs (int isput, int bytes)
101 {
102   return comma (mem_counters[isput][bytes]);
103 }
104
105 void
106 mem_usage_stats ()
107 {
108   int i, j;
109   int rstart = 0;
110   int pending = 0;
111
112   for (i = 0; i < L1_LEN; i++)
113     if (pt[i])
114       {
115         for (j = 0; j < L2_LEN; j++)
116           if (pt[i][j])
117             {
118               if (!pending)
119                 {
120                   pending = 1;
121                   rstart = (i << (L2_BITS + OFF_BITS)) + (j << OFF_BITS);
122                 }
123             }
124           else if (pending)
125             {
126               pending = 0;
127               used (rstart, i, j);
128             }
129       }
130     else
131       {
132         if (pending)
133           {
134             pending = 0;
135             used (rstart, i, 0);
136           }
137       }
138   /*       mem foo: 123456789012 123456789012 123456789012 123456789012
139             123456789012 */
140   printf ("                 byte        short      pointer         long"
141           "        fetch\n");
142   printf ("mem get: %12s %12s %12s %12s %12s\n", mcs (0, 1), mcs (0, 2),
143           mcs (0, 3), mcs (0, 4), mcs (0, 0));
144   printf ("mem put: %12s %12s %12s %12s\n", mcs (1, 1), mcs (1, 2),
145           mcs (1, 3), mcs (1, 4));
146 }
147
148 static int tpr = 0;
149 static void
150 s (int address, char *dir)
151 {
152   if (tpr == 0)
153     printf ("MEM[%0*x] %s", membus_mask == 0xfffff ? 5 : 6, address, dir);
154   tpr++;
155 }
156
157 #define S(d) if (trace) s(address, d)
158 static void
159 e ()
160 {
161   if (!trace)
162     return;
163   tpr--;
164   if (tpr == 0)
165     printf ("\n");
166 }
167
168 #define E() if (trace) e()
169
170 void
171 mem_put_byte (int address, unsigned char value)
172 {
173   unsigned char *m;
174   address &= membus_mask;
175   m = mem_ptr (address);
176   if (trace)
177     printf (" %02x", value);
178   *m = value;
179   switch (address)
180     {
181     case 0x00e1:
182       {
183         static int old_led = -1;
184         static char *led_on[] =
185           { "\033[31m O ", "\033[32m O ", "\033[34m O " };
186         static char *led_off[] = { "\033[0m · ", "\033[0m · ", "\033[0m · " };
187         int i;
188         if (old_led != value)
189           {
190             fputs ("  ", stdout);
191             for (i = 0; i < 3; i++)
192               if (value & (1 << i))
193                 fputs (led_off[i], stdout);
194               else
195                 fputs (led_on[i], stdout);
196             fputs ("\033[0m\r", stdout);
197             fflush (stdout);
198             old_led = value;
199           }
200       }
201       break;
202
203     case 0x3aa: /* uart1tx */
204       {
205         static int pending_exit = 0;
206         if (value == 0)
207           {
208             if (pending_exit)
209               {
210                 step_result = M32C_MAKE_EXITED(value);
211                 return;
212               }
213             pending_exit = 1;
214           }
215         else
216           putchar(value);
217       }
218       break;
219
220     case 0x400:
221       m32c_syscall (value);
222       break;
223
224     case 0x401:
225       putchar (value);
226       break;
227
228     case 0x402:
229       printf ("SimTrace: %06lx %02x\n", regs.r_pc, value);
230       break;
231
232     case 0x403:
233       printf ("SimTrap: %06lx %02x\n", regs.r_pc, value);
234       abort ();
235     }
236 }
237
238 void
239 mem_put_qi (int address, unsigned char value)
240 {
241   S ("<=");
242   mem_put_byte (address, value & 0xff);
243   E ();
244   COUNT (1, 1);
245 }
246
247 void
248 mem_put_hi (int address, unsigned short value)
249 {
250   if (address == 0x402)
251     {
252       printf ("SimTrace: %06lx %04x\n", regs.r_pc, value);
253       return;
254     }
255   S ("<=");
256   mem_put_byte (address, value & 0xff);
257   mem_put_byte (address + 1, value >> 8);
258   E ();
259   COUNT (1, 2);
260 }
261
262 void
263 mem_put_psi (int address, unsigned long value)
264 {
265   S ("<=");
266   mem_put_byte (address, value & 0xff);
267   mem_put_byte (address + 1, (value >> 8) & 0xff);
268   mem_put_byte (address + 2, value >> 16);
269   E ();
270   COUNT (1, 3);
271 }
272
273 void
274 mem_put_si (int address, unsigned long value)
275 {
276   S ("<=");
277   mem_put_byte (address, value & 0xff);
278   mem_put_byte (address + 1, (value >> 8) & 0xff);
279   mem_put_byte (address + 2, (value >> 16) & 0xff);
280   mem_put_byte (address + 3, (value >> 24) & 0xff);
281   E ();
282   COUNT (1, 4);
283 }
284
285 void
286 mem_put_blk (int address, void *bufptr, int nbytes)
287 {
288   S ("<=");
289   if (enable_counting)
290     mem_counters[1][1] += nbytes;
291   while (nbytes--)
292     mem_put_byte (address++, *(unsigned char *) bufptr++);
293   E ();
294 }
295
296 unsigned char
297 mem_get_pc ()
298 {
299   unsigned char *m = mem_ptr (regs.r_pc & membus_mask);
300   COUNT (0, 0);
301   return *m;
302 }
303
304 static unsigned char
305 mem_get_byte (int address)
306 {
307   unsigned char *m;
308   address &= membus_mask;
309   S ("=>");
310   m = mem_ptr (address);
311   switch (address)
312     {
313     case 0x3ad: /* uart1c1 */
314       E();
315       return 2; /* transmitter empty */
316       break;
317     default: 
318       if (trace)
319         printf (" %02x", *m);
320       break;
321     }
322   E ();
323   return *m;
324 }
325
326 unsigned char
327 mem_get_qi (int address)
328 {
329   unsigned char rv;
330   S ("=>");
331   rv = mem_get_byte (address);
332   COUNT (0, 1);
333   E ();
334   return rv;
335 }
336
337 unsigned short
338 mem_get_hi (int address)
339 {
340   unsigned short rv;
341   S ("=>");
342   rv = mem_get_byte (address);
343   rv |= mem_get_byte (address + 1) * 256;
344   COUNT (0, 2);
345   E ();
346   return rv;
347 }
348
349 unsigned long
350 mem_get_psi (int address)
351 {
352   unsigned long rv;
353   S ("=>");
354   rv = mem_get_byte (address);
355   rv |= mem_get_byte (address + 1) * 256;
356   rv |= mem_get_byte (address + 2) * 65536;
357   COUNT (0, 3);
358   E ();
359   return rv;
360 }
361
362 unsigned long
363 mem_get_si (int address)
364 {
365   unsigned long rv;
366   S ("=>");
367   rv = mem_get_byte (address);
368   rv |= mem_get_byte (address + 1) << 8;
369   rv |= mem_get_byte (address + 2) << 16;
370   rv |= mem_get_byte (address + 3) << 24;
371   COUNT (0, 4);
372   E ();
373   return rv;
374 }
375
376 void
377 mem_get_blk (int address, void *bufptr, int nbytes)
378 {
379   S ("=>");
380   if (enable_counting)
381     mem_counters[0][1] += nbytes;
382   while (nbytes--)
383     *(char *) bufptr++ = mem_get_byte (address++);
384   E ();
385 }
386
387 int
388 sign_ext (int v, int bits)
389 {
390   if (bits < 32)
391     {
392       v &= (1 << bits) - 1;
393       if (v & (1 << (bits - 1)))
394         v -= (1 << bits);
395     }
396   return v;
397 }