1 /* mem.c --- memory for RL78 simulator.
3 Copyright (C) 2011-2014 Free Software Foundation, Inc.
4 Contributed by Red Hat, Inc.
6 This file is part of the GNU simulators.
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.
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.
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/>.
27 #include "opcode/rl78.h"
31 #define ILLEGAL_OPCODE 0xff
33 int rom_limit
= 0x100000;
34 int ram_base
= 0xf8000;
35 unsigned char memory
[MEM_SIZE
];
38 unsigned char initted
[MEM_SIZE
];
41 #define tprintf if (trace) printf
46 memset (memory
, ILLEGAL_OPCODE
, sizeof (memory
));
47 memset (memory
+ 0xf0000, 0x33, 0x10000);
49 memset (initted
, 0, sizeof (initted
));
50 memset (initted
+ 0xffee0, 1, 0x00120);
51 memset (initted
+ 0xf0000, 1, 0x01000);
55 mem_ram_size (int ram_bytes
)
57 ram_base
= 0x100000 - ram_bytes
;
61 mem_rom_size (int rom_bytes
)
63 rom_limit
= rom_bytes
;
66 /* ---------------------------------------------------------------------- */
67 /* Note: the RL78 memory map has a few surprises. For starters, part
68 of the first 64k is mapped to the last 64k, depending on an SFR bit
69 and how much RAM the chip has. This is simulated here, as are a
72 /* This is stdout. We only care about the data byte, not the upper byte. */
77 /* RL78/G13 multiply/divide peripheral. */
85 static long long mduc_clock
= 0;
86 static int mda_set
= 0;
89 static int last_addr_was_mirror
;
92 address_mapping (int address
)
95 if (address
>= 0xf1000 && address
< ram_base
)
99 if (memory
[RL78_SFR_PMC
] & 1)
104 last_addr_was_mirror
= 1;
107 last_addr_was_mirror
= 0;
113 mem_put_byte (int address
, unsigned char value
)
115 address
= address_mapping (address
);
116 memory
[address
] = value
;
117 initted
[address
] = 1;
118 if (address
== SDR00
)
125 if (timer_enabled
== 2)
129 memset (counts_per_insn
, 0, sizeof (counts_per_insn
));
130 memory
[0xf0180] = 0xff;
131 memory
[0xf0181] = 0xff;
138 if (address
== RL78_SFR_SP
&& value
& 1)
140 printf ("Warning: SP value 0x%04x truncated at pc=0x%05x\n", value
, pc
);
145 if ((value
& 0x81) == 0x81)
148 mduc_clock
= total_clocks
;
151 if ((address
& ~3) == MDAL
)
153 mda_set
|= (1 << (address
& 3));
154 if (mda_set
== MDA_SET
)
157 unsigned long alu
, ahu
;
162 switch (memory
[MDUC
] & 0xc8)
165 alu
= mem_get_hi (MDAL
);
166 ahu
= mem_get_hi (MDAH
);
168 tprintf ("MDUC: %lu * %lu = %lu\n", alu
, ahu
, rvu
);
169 mem_put_si (MDBL
, rvu
);
172 als
= sign_ext (mem_get_hi (MDAL
), 16);
173 ahs
= sign_ext (mem_get_hi (MDAH
), 16);
175 tprintf ("MDUC: %ld * %ld = %ld\n", als
, ahs
, rvs
);
176 mem_put_si (MDBL
, rvs
);
179 alu
= mem_get_hi (MDAL
);
180 ahu
= mem_get_hi (MDAH
);
182 mem_put_si (MDBL
, rvu
);
183 mdc
= mem_get_si (MDCL
);
184 tprintf ("MDUC: %lu * %lu + %lu = ", alu
, ahu
, mdc
);
186 tprintf ("%lu\n", mdc
);
187 mem_put_si (MDCL
, mdc
);
190 als
= sign_ext (mem_get_hi (MDAL
), 16);
191 ahs
= sign_ext (mem_get_hi (MDAH
), 16);
193 mem_put_si (MDBL
, rvs
);
194 mdc
= mem_get_si (MDCL
);
195 tprintf ("MDUC: %ld * %ld + %ld = ", als
, ahs
, mdc
);
196 tprintf ("%ld\n", mdc
);
198 mem_put_si (MDCL
, mdc
);
205 extern long long total_clocks
;
208 mem_get_byte (int address
)
210 address
= address_mapping (address
);
220 return memory
[address
];
224 unsigned char mduc
= memory
[MDUC
];
225 if ((mduc
& 0x81) == 0x81
226 && total_clocks
> mduc_clock
+ 16)
228 unsigned long a
, b
, q
, r
;
229 memory
[MDUC
] &= 0xfe;
230 a
= mem_get_si (MDAL
);
231 b
= mem_get_si (MDAL
);
242 tprintf ("MDUC: %lu / %lu = q %lu, r %lu\n", a
, b
, q
, r
);
243 mem_put_si (MDAL
, q
);
244 mem_put_si (MDCL
, r
);
246 return memory
[address
];
252 return memory
[address
];
254 if (address
< 0xf1000 && address
>= 0xf0000)
257 /* Note: comment out this return to trap the invalid access
258 instead of returning an "undefined" value. */
261 fprintf (stderr
, "SFR access error: addr 0x%05x pc 0x%05x\n", address
, pc
);
266 /* Uncomment this block if you want to trap on reads from unwritten memory. */
267 if (!skip_init
&& !initted
[address
])
269 static int uninit_count
= 0;
270 fprintf (stderr
, "\033[31mwarning :read from uninit addr %05x pc %05x\033[0m\n", address
, pc
);
272 if (uninit_count
> 5)
276 return memory
[address
];
279 extern jmp_buf decode_jmp_buf
;
280 #define DO_RETURN(x) longjmp (decode_jmp_buf, x)
282 #define CHECK_ALIGNMENT(a,v,m) \
283 if (a & m) { printf ("Misalignment addr 0x%05x val 0x%04x pc %05x\n", (int)a, (int)v, (int)pc); \
284 DO_RETURN (RL78_MAKE_HIT_BREAK ()); }
286 /* ---------------------------------------------------------------------- */
287 #define SPECIAL_ADDR(a) (0xffff0 <= a || (0xffee0 <= a && a < 0xfff00))
290 mem_put_qi (int address
, unsigned char value
)
292 if (!SPECIAL_ADDR (address
))
293 tprintf ("\033[34m([%05X]<-%02X)\033[0m", address
, value
);
294 mem_put_byte (address
, value
);
298 mem_put_hi (int address
, unsigned short value
)
300 if (!SPECIAL_ADDR (address
))
301 tprintf ("\033[34m([%05X]<-%04X)\033[0m", address
, value
);
302 CHECK_ALIGNMENT (address
, value
, 1);
303 if (address
> 0xffff8 && address
!= RL78_SFR_SP
)
305 tprintf ("Word access to 0x%05x!!\n", address
);
306 DO_RETURN (RL78_MAKE_HIT_BREAK ());
308 mem_put_byte (address
, value
);
309 mem_put_byte (address
+ 1, value
>> 8);
313 mem_put_psi (int address
, unsigned long value
)
315 tprintf ("\033[34m([%05X]<-%06lX)\033[0m", address
, value
);
316 mem_put_byte (address
, value
);
317 mem_put_byte (address
+ 1, value
>> 8);
318 mem_put_byte (address
+ 2, value
>> 16);
322 mem_put_si (int address
, unsigned long value
)
324 tprintf ("\033[34m([%05X]<-%08lX)\033[0m", address
, value
);
325 CHECK_ALIGNMENT (address
, value
, 3);
326 mem_put_byte (address
, value
);
327 mem_put_byte (address
+ 1, value
>> 8);
328 mem_put_byte (address
+ 2, value
>> 16);
329 mem_put_byte (address
+ 3, value
>> 24);
333 mem_put_blk (int address
, const void *bufptr
, int nbytes
)
335 const unsigned char *bp
= (unsigned char *)bufptr
;
337 mem_put_byte (address
++, *bp
++);
341 mem_get_pc (int address
)
343 /* Catch obvious problems. */
344 if (address
>= rom_limit
&& address
< 0xf0000)
346 /* This does NOT go through the flash mirror area; you cannot
347 execute out of the mirror. */
348 return memory
[address
& MASK
];
352 mem_get_qi (int address
)
355 v
= mem_get_byte (address
);
356 if (!SPECIAL_ADDR (address
))
357 tprintf ("\033[35m([%05X]->%04X)\033[0m", address
, v
);
358 if (last_addr_was_mirror
)
361 tprintf ("ROM read\n");
367 mem_get_hi (int address
)
370 v
= mem_get_byte (address
)
371 | mem_get_byte (address
+ 1) * 256;
372 CHECK_ALIGNMENT (address
, v
, 1);
373 if (!SPECIAL_ADDR (address
))
374 tprintf ("\033[35m([%05X]->%04X)\033[0m", address
, v
);
375 if (last_addr_was_mirror
)
378 tprintf ("ROM read\n");
384 mem_get_psi (int address
)
387 v
= mem_get_byte (address
)
388 | mem_get_byte (address
+ 1) * 256
389 | mem_get_byte (address
+ 2) * 65536;
390 tprintf ("\033[35m([%05X]->%04X)\033[0m", address
, v
);
395 mem_get_si (int address
)
398 v
= mem_get_byte (address
)
399 | mem_get_byte (address
+ 1) * 256
400 | mem_get_byte (address
+ 2) * 65536
401 | mem_get_byte (address
+ 2) * 16777216;
402 CHECK_ALIGNMENT (address
, v
, 3);
403 tprintf ("(\033[35m[%05X]->%04X)\033[0m", address
, v
);
408 mem_get_blk (int address
, void *bufptr
, int nbytes
)
410 unsigned char *bp
= (unsigned char *)bufptr
;
412 *bp
++ = mem_get_byte (address
++);
416 sign_ext (int v
, int bits
)
418 if (bits
< 8 * sizeof (int))
420 v
&= (1 << bits
) - 1;
421 if (v
& (1 << (bits
- 1)))
This page took 0.037043 seconds and 4 git commands to generate.