1 /* mem.c --- memory for RL78 simulator.
3 Copyright (C) 2011-2020 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 int mirror_rom_base
= 0x01000;
67 int mirror_ram_base
= 0xf1000;
68 int mirror_length
= 0x7000;
71 mem_set_mirror (int rom_base
, int ram_base
, int length
)
73 mirror_rom_base
= rom_base
;
74 mirror_ram_base
= ram_base
;
75 mirror_length
= length
;
78 /* ---------------------------------------------------------------------- */
79 /* Note: the RL78 memory map has a few surprises. For starters, part
80 of the first 64k is mapped to the last 64k, depending on an SFR bit
81 and how much RAM the chip has. This is simulated here, as are a
84 /* This is stdout. We only care about the data byte, not the upper byte. */
89 /* RL78/G13 multiply/divide peripheral. */
97 static long long mduc_clock
= 0;
98 static int mda_set
= 0;
101 static int last_addr_was_mirror
;
104 address_mapping (int address
)
107 if (address
>= mirror_ram_base
&& address
< mirror_ram_base
+ mirror_length
)
109 address
= address
- mirror_ram_base
+ mirror_rom_base
;
110 if (memory
[RL78_SFR_PMC
] & 1)
114 last_addr_was_mirror
= 1;
117 last_addr_was_mirror
= 0;
123 mem_put_byte (int address
, unsigned char value
)
125 address
= address_mapping (address
);
126 memory
[address
] = value
;
127 initted
[address
] = 1;
128 if (address
== SDR00
)
135 if (timer_enabled
== 2)
139 memset (counts_per_insn
, 0, sizeof (counts_per_insn
));
140 memory
[0xf0180] = 0xff;
141 memory
[0xf0181] = 0xff;
148 if (address
== RL78_SFR_SP
&& value
& 1)
150 printf ("Warning: SP value 0x%04x truncated at pc=0x%05x\n", value
, pc
);
159 if ((value
& 0x81) == 0x81)
162 mduc_clock
= total_clocks
;
165 if ((address
& ~3) == MDAL
)
167 mda_set
|= (1 << (address
& 3));
168 if (mda_set
== MDA_SET
)
171 unsigned long alu
, ahu
;
176 switch (memory
[MDUC
] & 0xc8)
179 alu
= mem_get_hi (MDAL
);
180 ahu
= mem_get_hi (MDAH
);
182 tprintf ("MDUC: %lu * %lu = %lu\n", alu
, ahu
, rvu
);
183 mem_put_hi (MDBL
, rvu
& 0xffff);
184 mem_put_hi (MDBH
, rvu
>> 16);
187 als
= sign_ext (mem_get_hi (MDAL
), 16);
188 ahs
= sign_ext (mem_get_hi (MDAH
), 16);
190 tprintf ("MDUC: %ld * %ld = %ld\n", als
, ahs
, rvs
);
191 mem_put_hi (MDBL
, rvs
& 0xffff);
192 mem_put_hi (MDBH
, rvs
>> 16);
195 alu
= mem_get_hi (MDAL
);
196 ahu
= mem_get_hi (MDAH
);
198 mem_put_hi (MDBL
, rvu
& 0xffff);
199 mem_put_hi (MDBH
, rvu
>> 16);
200 mdc
= mem_get_si (MDCL
);
201 tprintf ("MDUC: %lu * %lu + %lu = ", alu
, ahu
, mdc
);
203 tprintf ("%lu\n", mdc
);
204 mem_put_si (MDCL
, mdc
);
207 als
= sign_ext (mem_get_hi (MDAL
), 16);
208 ahs
= sign_ext (mem_get_hi (MDAH
), 16);
210 mem_put_hi (MDBL
, rvs
& 0xffff);
211 mem_put_hi (MDBH
, rvs
>> 16);
212 mdc
= mem_get_si (MDCL
);
213 tprintf ("MDUC: %ld * %ld + %ld = ", als
, ahs
, mdc
);
214 tprintf ("%ld\n", mdc
);
216 mem_put_si (MDCL
, mdc
);
223 extern long long total_clocks
;
226 mem_get_byte (int address
)
228 address
= address_mapping (address
);
238 return memory
[address
];
242 unsigned char mduc
= memory
[MDUC
];
243 if ((mduc
& 0x81) == 0x81
244 && total_clocks
> mduc_clock
+ 16)
246 unsigned long a
, b
, q
, r
;
247 memory
[MDUC
] &= 0xfe;
248 a
= mem_get_si (MDAL
);
249 b
= mem_get_hi (MDBL
) | (mem_get_hi (MDBH
) << 16);
260 tprintf ("MDUC: %lu / %lu = q %lu, r %lu\n", a
, b
, q
, r
);
261 mem_put_si (MDAL
, q
);
262 mem_put_si (MDCL
, r
);
264 return memory
[address
];
270 return memory
[address
];
272 if (address
< 0xf1000 && address
>= 0xf0000)
275 /* Note: comment out this return to trap the invalid access
276 instead of returning an "undefined" value. */
279 fprintf (stderr
, "SFR access error: addr 0x%05x pc 0x%05x\n", address
, pc
);
284 /* Uncomment this block if you want to trap on reads from unwritten memory. */
285 if (!skip_init
&& !initted
[address
])
287 static int uninit_count
= 0;
288 fprintf (stderr
, "\033[31mwarning :read from uninit addr %05x pc %05x\033[0m\n", address
, pc
);
290 if (uninit_count
> 5)
294 return memory
[address
];
297 extern jmp_buf decode_jmp_buf
;
298 #define DO_RETURN(x) longjmp (decode_jmp_buf, x)
300 #define CHECK_ALIGNMENT(a,v,m) \
301 if (a & m) { printf ("Misalignment addr 0x%05x val 0x%04x pc %05x\n", (int)a, (int)v, (int)pc); \
302 DO_RETURN (RL78_MAKE_HIT_BREAK ()); }
304 /* ---------------------------------------------------------------------- */
305 #define SPECIAL_ADDR(a) (0xffff0 <= a || (0xffee0 <= a && a < 0xfff00))
308 mem_put_qi (int address
, unsigned char value
)
310 if (!SPECIAL_ADDR (address
))
311 tprintf ("\033[34m([%05X]<-%02X)\033[0m", address
, value
);
312 mem_put_byte (address
, value
);
316 mem_put_hi (int address
, unsigned short value
)
318 if (!SPECIAL_ADDR (address
))
319 tprintf ("\033[34m([%05X]<-%04X)\033[0m", address
, value
);
320 CHECK_ALIGNMENT (address
, value
, 1);
321 if (address
> 0xffff8 && address
!= RL78_SFR_SP
)
323 tprintf ("Word access to 0x%05x!!\n", address
);
324 DO_RETURN (RL78_MAKE_HIT_BREAK ());
326 mem_put_byte (address
, value
);
327 mem_put_byte (address
+ 1, value
>> 8);
331 mem_put_psi (int address
, unsigned long value
)
333 tprintf ("\033[34m([%05X]<-%06lX)\033[0m", address
, value
);
334 mem_put_byte (address
, value
);
335 mem_put_byte (address
+ 1, value
>> 8);
336 mem_put_byte (address
+ 2, value
>> 16);
340 mem_put_si (int address
, unsigned long value
)
342 tprintf ("\033[34m([%05X]<-%08lX)\033[0m", address
, value
);
343 CHECK_ALIGNMENT (address
, value
, 3);
344 mem_put_byte (address
, value
);
345 mem_put_byte (address
+ 1, value
>> 8);
346 mem_put_byte (address
+ 2, value
>> 16);
347 mem_put_byte (address
+ 3, value
>> 24);
351 mem_put_blk (int address
, const void *bufptr
, int nbytes
)
353 const unsigned char *bp
= (unsigned char *)bufptr
;
355 mem_put_byte (address
++, *bp
++);
359 mem_get_pc (int address
)
361 /* Catch obvious problems. */
362 if (address
>= rom_limit
&& address
< 0xf0000)
364 /* This does NOT go through the flash mirror area; you cannot
365 execute out of the mirror. */
366 return memory
[address
& MASK
];
370 mem_get_qi (int address
)
373 v
= mem_get_byte (address
);
374 if (!SPECIAL_ADDR (address
))
375 tprintf ("\033[35m([%05X]->%04X)\033[0m", address
, v
);
376 if (last_addr_was_mirror
)
379 tprintf ("ROM read\n");
385 mem_get_hi (int address
)
388 v
= mem_get_byte (address
)
389 | mem_get_byte (address
+ 1) * 256;
390 CHECK_ALIGNMENT (address
, v
, 1);
391 if (!SPECIAL_ADDR (address
))
392 tprintf ("\033[35m([%05X]->%04X)\033[0m", address
, v
);
393 if (last_addr_was_mirror
)
396 tprintf ("ROM read\n");
402 mem_get_psi (int address
)
405 v
= mem_get_byte (address
)
406 | mem_get_byte (address
+ 1) * 256
407 | mem_get_byte (address
+ 2) * 65536;
408 tprintf ("\033[35m([%05X]->%04X)\033[0m", address
, v
);
413 mem_get_si (int address
)
416 v
= mem_get_byte (address
)
417 | mem_get_byte (address
+ 1) * 256
418 | mem_get_byte (address
+ 2) * 65536
419 | mem_get_byte (address
+ 2) * 16777216;
420 CHECK_ALIGNMENT (address
, v
, 3);
421 tprintf ("(\033[35m[%05X]->%04X)\033[0m", address
, v
);
426 mem_get_blk (int address
, void *bufptr
, int nbytes
)
428 unsigned char *bp
= (unsigned char *)bufptr
;
430 *bp
++ = mem_get_byte (address
++);
434 sign_ext (int v
, int bits
)
436 if (bits
< 8 * sizeof (int))
438 v
&= (1 << bits
) - 1;
439 if (v
& (1 << (bits
- 1)))