[AArch64] MTE corefile support
[binutils-gdb.git] / sim / m68hc11 / sim-main.h
1 /* sim-main.h -- Simulator for Motorola 68HC11 & 68HC12
2 Copyright (C) 1999-2022 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@nerim.fr)
4
5 This file is part of GDB, the GNU debugger.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20 #ifndef _SIM_MAIN_H
21 #define _SIM_MAIN_H
22
23 #include "sim-basics.h"
24 #include "sim-base.h"
25
26 #include "bfd.h"
27
28 #include "opcode/m68hc11.h"
29
30 #include "sim/sim.h"
31 #include "opcode/m68hc11.h"
32 #include "sim-signal.h"
33 #include "sim-types.h"
34
35 struct _sim_cpu;
36
37 #include "interrupts.h"
38 #include <setjmp.h>
39
40 /* Specifies the level of mapping for the IO, EEprom, nvram and external
41 RAM. IO registers are mapped over everything and the external RAM
42 is last (ie, it can be hidden by everything above it in the list). */
43 enum m68hc11_map_level
44 {
45 M6811_IO_LEVEL,
46 M6811_EEPROM_LEVEL,
47 M6811_NVRAM_LEVEL,
48 M6811_RAM_LEVEL
49 };
50
51 enum cpu_type
52 {
53 CPU_M6811,
54 CPU_M6812
55 };
56
57 #define X_REGNUM 0
58 #define D_REGNUM 1
59 #define Y_REGNUM 2
60 #define SP_REGNUM 3
61 #define PC_REGNUM 4
62 #define A_REGNUM 5
63 #define B_REGNUM 6
64 #define PSW_REGNUM 7
65 #define PAGE_REGNUM 8
66 #define Z_REGNUM 9
67
68 typedef struct m6811_regs {
69 unsigned short d;
70 unsigned short ix;
71 unsigned short iy;
72 unsigned short sp;
73 unsigned short pc;
74 unsigned char ccr;
75 unsigned short page;
76 } m6811_regs;
77
78
79 /* Description of 68HC11 IO registers. Such description is only provided
80 for the info command to display the current setting of IO registers
81 from GDB. */
82 struct io_reg_desc
83 {
84 int mask;
85 const char *short_name;
86 const char *long_name;
87 };
88 typedef struct io_reg_desc io_reg_desc;
89
90 extern void print_io_reg_desc (SIM_DESC sd, io_reg_desc *desc, int val,
91 int mode);
92 extern void print_io_byte (SIM_DESC sd, const char *name,
93 io_reg_desc *desc, uint8_t val, uint16_t addr);
94 extern void print_io_word (SIM_DESC sd, const char *name,
95 io_reg_desc *desc, uint16_t val, uint16_t addr);
96
97
98 /* List of special 68HC11&68HC12 instructions that are not handled by the
99 'gencode.c' generator. These complex instructions are implemented
100 by 'cpu_special'. */
101 enum M6811_Special
102 {
103 /* 68HC11 instructions. */
104 M6811_DAA,
105 M6811_EMUL_SYSCALL,
106 M6811_ILLEGAL,
107 M6811_RTI,
108 M6811_STOP,
109 M6811_SWI,
110 M6811_TEST,
111 M6811_WAI,
112
113 /* 68HC12 instructions. */
114 M6812_BGND,
115 M6812_CALL,
116 M6812_CALL_INDIRECT,
117 M6812_IDIVS,
118 M6812_EDIV,
119 M6812_EDIVS,
120 M6812_EMACS,
121 M6812_EMUL,
122 M6812_EMULS,
123 M6812_ETBL,
124 M6812_MEM,
125 M6812_REV,
126 M6812_REVW,
127 M6812_RTC,
128 M6812_RTI,
129 M6812_WAV
130 };
131
132 #define M6811_MAX_PORTS (0x03f+1)
133 #define M6812_MAX_PORTS (0x3ff+1)
134 #define MAX_PORTS (M6812_MAX_PORTS)
135
136 struct _sim_cpu;
137
138 typedef void (* cpu_interp) (struct _sim_cpu*);
139
140 struct _sim_cpu {
141 /* CPU registers. */
142 struct m6811_regs cpu_regs;
143
144 /* CPU interrupts. */
145 struct interrupts cpu_interrupts;
146
147 /* Pointer to the interpretor routine. */
148 cpu_interp cpu_interpretor;
149
150 /* Pointer to the architecture currently configured in the simulator. */
151 const struct bfd_arch_info *cpu_configured_arch;
152
153 /* CPU absolute cycle time. The cycle time is updated after
154 each instruction, by the number of cycles taken by the instruction.
155 It is cleared only when reset occurs. */
156 int64_t cpu_absolute_cycle;
157
158 /* Number of cycles to increment after the current instruction.
159 This is also the number of ticks for the generic event scheduler. */
160 uint8_t cpu_current_cycle;
161 int cpu_emul_syscall;
162 int cpu_is_initialized;
163 int cpu_running;
164 int cpu_check_memory;
165 int cpu_stop_on_interrupt;
166
167 /* When this is set, start execution of program at address specified
168 in the ELF header. This is used for testing some programs that do not
169 have an interrupt table linked with them. Programs created during the
170 GCC validation are like this. A normal 68HC11 does not behave like
171 this (unless there is some OS or downloadable feature). */
172 int cpu_use_elf_start;
173
174 /* The starting address specified in ELF header. */
175 int cpu_elf_start;
176
177 uint16_t cpu_insn_pc;
178
179 /* CPU frequency. This is the quartz frequency. It is divided by 4 to
180 get the cycle time. This is used for the timer rate and for the baud
181 rate generation. */
182 unsigned long cpu_frequency;
183
184 /* The mode in which the CPU is configured (MODA and MODB pins). */
185 unsigned int cpu_mode;
186 const char* cpu_start_mode;
187
188 /* The cpu being configured. */
189 enum cpu_type cpu_type;
190
191 /* Initial value of the CONFIG register. */
192 uint8_t cpu_config;
193 uint8_t cpu_use_local_config;
194
195 uint8_t ios[MAX_PORTS];
196
197 /* Memory bank parameters which describe how the memory bank window
198 is mapped in memory and how to convert it in virtual address. */
199 uint16_t bank_start;
200 uint16_t bank_end;
201 address_word bank_virtual;
202 unsigned bank_shift;
203
204
205 struct hw *hw_cpu;
206
207 /* ... base type ... */
208 sim_cpu_base base;
209 };
210
211 /* Returns the cpu absolute cycle time (A virtual counter incremented
212 at each 68HC11 E clock). */
213 #define cpu_current_cycle(cpu) ((cpu)->cpu_absolute_cycle)
214 #define cpu_add_cycles(cpu, T) ((cpu)->cpu_current_cycle += (int64_t) (T))
215 #define cpu_is_running(cpu) ((cpu)->cpu_running)
216
217 /* Get the IO/RAM base addresses depending on the M6811_INIT register. */
218 #define cpu_get_io_base(cpu) \
219 (((uint16_t)(((cpu)->ios[M6811_INIT]) & 0x0F)) << 12)
220 #define cpu_get_reg_base(cpu) \
221 (((uint16_t)(((cpu)->ios[M6811_INIT]) & 0xF0)) << 8)
222
223 /* Returns the different CPU registers. */
224 #define cpu_get_ccr(cpu) ((cpu)->cpu_regs.ccr)
225 #define cpu_get_pc(cpu) ((cpu)->cpu_regs.pc)
226 #define cpu_get_d(cpu) ((cpu)->cpu_regs.d)
227 #define cpu_get_x(cpu) ((cpu)->cpu_regs.ix)
228 #define cpu_get_y(cpu) ((cpu)->cpu_regs.iy)
229 #define cpu_get_sp(cpu) ((cpu)->cpu_regs.sp)
230 #define cpu_get_a(cpu) (((cpu)->cpu_regs.d >> 8) & 0x0FF)
231 #define cpu_get_b(cpu) ((cpu)->cpu_regs.d & 0x0FF)
232 #define cpu_get_page(cpu) ((cpu)->cpu_regs.page)
233
234 /* 68HC12 specific and Motorola internal registers. */
235 #define cpu_get_tmp3(cpu) (0)
236 #define cpu_get_tmp2(cpu) (0)
237
238 #define cpu_set_d(cpu, val) ((cpu)->cpu_regs.d = (val))
239 #define cpu_set_x(cpu, val) ((cpu)->cpu_regs.ix = (val))
240 #define cpu_set_y(cpu, val) ((cpu)->cpu_regs.iy = (val))
241 #define cpu_set_page(cpu, val) ((cpu)->cpu_regs.page = (val))
242
243 /* 68HC12 specific and Motorola internal registers. */
244 #define cpu_set_tmp3(cpu, val) (0)
245 #define cpu_set_tmp2(cpu, val) (void) (0)
246
247 #if 0
248 /* This is a function in m68hc11_sim.c to keep track of the frame. */
249 #define cpu_set_sp(cpu, val) ((cpu)->cpu_regs.sp = (val))
250 #endif
251
252 #define cpu_set_pc(cpu, val) ((cpu)->cpu_regs.pc = (val))
253
254 #define cpu_set_a(cpu, val) \
255 cpu_set_d(cpu, ((val) << 8) | cpu_get_b (cpu))
256 #define cpu_set_b(cpu, val) \
257 cpu_set_d(cpu, ((cpu_get_a (cpu)) << 8) | ((val) & 0x0FF))
258
259 #define cpu_set_ccr(cpu, val) ((cpu)->cpu_regs.ccr = (val))
260 #define cpu_get_ccr_H(cpu) ((cpu_get_ccr (cpu) & M6811_H_BIT) ? 1 : 0)
261 #define cpu_get_ccr_X(cpu) ((cpu_get_ccr (cpu) & M6811_X_BIT) ? 1 : 0)
262 #define cpu_get_ccr_S(cpu) ((cpu_get_ccr (cpu) & M6811_S_BIT) ? 1 : 0)
263 #define cpu_get_ccr_N(cpu) ((cpu_get_ccr (cpu) & M6811_N_BIT) ? 1 : 0)
264 #define cpu_get_ccr_V(cpu) ((cpu_get_ccr (cpu) & M6811_V_BIT) ? 1 : 0)
265 #define cpu_get_ccr_C(cpu) ((cpu_get_ccr (cpu) & M6811_C_BIT) ? 1 : 0)
266 #define cpu_get_ccr_Z(cpu) ((cpu_get_ccr (cpu) & M6811_Z_BIT) ? 1 : 0)
267 #define cpu_get_ccr_I(cpu) ((cpu_get_ccr (cpu) & M6811_I_BIT) ? 1 : 0)
268
269 #define cpu_set_ccr_flag(S, B, V) \
270 cpu_set_ccr (S, (cpu_get_ccr (S) & ~(B)) | ((V) ? (B) : 0))
271
272 #define cpu_set_ccr_H(cpu, val) cpu_set_ccr_flag (cpu, M6811_H_BIT, val)
273 #define cpu_set_ccr_X(cpu, val) cpu_set_ccr_flag (cpu, M6811_X_BIT, val)
274 #define cpu_set_ccr_S(cpu, val) cpu_set_ccr_flag (cpu, M6811_S_BIT, val)
275 #define cpu_set_ccr_N(cpu, val) cpu_set_ccr_flag (cpu, M6811_N_BIT, val)
276 #define cpu_set_ccr_V(cpu, val) cpu_set_ccr_flag (cpu, M6811_V_BIT, val)
277 #define cpu_set_ccr_C(cpu, val) cpu_set_ccr_flag (cpu, M6811_C_BIT, val)
278 #define cpu_set_ccr_Z(cpu, val) cpu_set_ccr_flag (cpu, M6811_Z_BIT, val)
279 #define cpu_set_ccr_I(cpu, val) cpu_set_ccr_flag (cpu, M6811_I_BIT, val)
280
281 extern void cpu_memory_exception (sim_cpu *cpu,
282 SIM_SIGNAL excep,
283 uint16_t addr,
284 const char *message);
285
286 STATIC_INLINE UNUSED address_word
287 phys_to_virt (sim_cpu *cpu, address_word addr)
288 {
289 if (addr >= cpu->bank_start && addr < cpu->bank_end)
290 return ((address_word) (addr - cpu->bank_start)
291 + (((address_word) cpu->cpu_regs.page) << cpu->bank_shift)
292 + cpu->bank_virtual);
293 else
294 return (address_word) (addr);
295 }
296
297 STATIC_INLINE UNUSED uint8_t
298 memory_read8 (sim_cpu *cpu, uint16_t addr)
299 {
300 uint8_t val;
301
302 if (sim_core_read_buffer (CPU_STATE (cpu), cpu, 0, &val, addr, 1) != 1)
303 {
304 cpu_memory_exception (cpu, SIM_SIGSEGV, addr,
305 "Read error");
306 }
307 return val;
308 }
309
310 STATIC_INLINE UNUSED void
311 memory_write8 (sim_cpu *cpu, uint16_t addr, uint8_t val)
312 {
313 if (sim_core_write_buffer (CPU_STATE (cpu), cpu, 0, &val, addr, 1) != 1)
314 {
315 cpu_memory_exception (cpu, SIM_SIGSEGV, addr,
316 "Write error");
317 }
318 }
319
320 STATIC_INLINE UNUSED uint16_t
321 memory_read16 (sim_cpu *cpu, uint16_t addr)
322 {
323 uint8_t b[2];
324
325 if (sim_core_read_buffer (CPU_STATE (cpu), cpu, 0, b, addr, 2) != 2)
326 {
327 cpu_memory_exception (cpu, SIM_SIGSEGV, addr,
328 "Read error");
329 }
330 return (((uint16_t) (b[0])) << 8) | ((uint16_t) b[1]);
331 }
332
333 STATIC_INLINE UNUSED void
334 memory_write16 (sim_cpu *cpu, uint16_t addr, uint16_t val)
335 {
336 uint8_t b[2];
337
338 b[0] = val >> 8;
339 b[1] = val;
340 if (sim_core_write_buffer (CPU_STATE (cpu), cpu, 0, b, addr, 2) != 2)
341 {
342 cpu_memory_exception (cpu, SIM_SIGSEGV, addr,
343 "Write error");
344 }
345 }
346 extern void
347 cpu_ccr_update_tst8 (sim_cpu *cpu, uint8_t val);
348
349 STATIC_INLINE UNUSED void
350 cpu_ccr_update_tst16 (sim_cpu *cpu, uint16_t val)
351 {
352 cpu_set_ccr_V (cpu, 0);
353 cpu_set_ccr_N (cpu, val & 0x8000 ? 1 : 0);
354 cpu_set_ccr_Z (cpu, val == 0 ? 1 : 0);
355 }
356
357 STATIC_INLINE UNUSED void
358 cpu_ccr_update_shift8 (sim_cpu *cpu, uint8_t val)
359 {
360 cpu_set_ccr_N (cpu, val & 0x80 ? 1 : 0);
361 cpu_set_ccr_Z (cpu, val == 0 ? 1 : 0);
362 cpu_set_ccr_V (cpu, cpu_get_ccr_N (cpu) ^ cpu_get_ccr_C (cpu));
363 }
364
365 STATIC_INLINE UNUSED void
366 cpu_ccr_update_shift16 (sim_cpu *cpu, uint16_t val)
367 {
368 cpu_set_ccr_N (cpu, val & 0x8000 ? 1 : 0);
369 cpu_set_ccr_Z (cpu, val == 0 ? 1 : 0);
370 cpu_set_ccr_V (cpu, cpu_get_ccr_N (cpu) ^ cpu_get_ccr_C (cpu));
371 }
372
373 STATIC_INLINE UNUSED void
374 cpu_ccr_update_add8 (sim_cpu *cpu, uint8_t r, uint8_t a, uint8_t b)
375 {
376 cpu_set_ccr_C (cpu, ((a & b) | (b & ~r) | (a & ~r)) & 0x80 ? 1 : 0);
377 cpu_set_ccr_V (cpu, ((a & b & ~r) | (~a & ~b & r)) & 0x80 ? 1 : 0);
378 cpu_set_ccr_Z (cpu, r == 0);
379 cpu_set_ccr_N (cpu, r & 0x80 ? 1 : 0);
380 }
381
382
383 STATIC_INLINE UNUSED void
384 cpu_ccr_update_sub8 (sim_cpu *cpu, uint8_t r, uint8_t a, uint8_t b)
385 {
386 cpu_set_ccr_C (cpu, ((~a & b) | (b & r) | (~a & r)) & 0x80 ? 1 : 0);
387 cpu_set_ccr_V (cpu, ((a & ~b & ~r) | (~a & b & r)) & 0x80 ? 1 : 0);
388 cpu_set_ccr_Z (cpu, r == 0);
389 cpu_set_ccr_N (cpu, r & 0x80 ? 1 : 0);
390 }
391
392 STATIC_INLINE UNUSED void
393 cpu_ccr_update_add16 (sim_cpu *cpu, uint16_t r, uint16_t a, uint16_t b)
394 {
395 cpu_set_ccr_C (cpu, ((a & b) | (b & ~r) | (a & ~r)) & 0x8000 ? 1 : 0);
396 cpu_set_ccr_V (cpu, ((a & b & ~r) | (~a & ~b & r)) & 0x8000 ? 1 : 0);
397 cpu_set_ccr_Z (cpu, r == 0);
398 cpu_set_ccr_N (cpu, r & 0x8000 ? 1 : 0);
399 }
400
401 STATIC_INLINE UNUSED void
402 cpu_ccr_update_sub16 (sim_cpu *cpu, uint16_t r, uint16_t a, uint16_t b)
403 {
404 cpu_set_ccr_C (cpu, ((~a & b) | (b & r) | (~a & r)) & 0x8000 ? 1 : 0);
405 cpu_set_ccr_V (cpu, ((a & ~b & ~r) | (~a & b & r)) & 0x8000 ? 1 : 0);
406 cpu_set_ccr_Z (cpu, r == 0);
407 cpu_set_ccr_N (cpu, r & 0x8000 ? 1 : 0);
408 }
409
410 /* Push and pop instructions for 68HC11 (next-available stack mode). */
411 STATIC_INLINE UNUSED void
412 cpu_m68hc11_push_uint8 (sim_cpu *cpu, uint8_t val)
413 {
414 uint16_t addr = cpu->cpu_regs.sp;
415
416 memory_write8 (cpu, addr, val);
417 cpu->cpu_regs.sp = addr - 1;
418 }
419
420 STATIC_INLINE UNUSED void
421 cpu_m68hc11_push_uint16 (sim_cpu *cpu, uint16_t val)
422 {
423 uint16_t addr = cpu->cpu_regs.sp - 1;
424
425 memory_write16 (cpu, addr, val);
426 cpu->cpu_regs.sp = addr - 1;
427 }
428
429 STATIC_INLINE UNUSED uint8_t
430 cpu_m68hc11_pop_uint8 (sim_cpu *cpu)
431 {
432 uint16_t addr = cpu->cpu_regs.sp;
433 uint8_t val;
434
435 val = memory_read8 (cpu, addr + 1);
436 cpu->cpu_regs.sp = addr + 1;
437 return val;
438 }
439
440 STATIC_INLINE UNUSED uint16_t
441 cpu_m68hc11_pop_uint16 (sim_cpu *cpu)
442 {
443 uint16_t addr = cpu->cpu_regs.sp;
444 uint16_t val;
445
446 val = memory_read16 (cpu, addr + 1);
447 cpu->cpu_regs.sp = addr + 2;
448 return val;
449 }
450
451 /* Push and pop instructions for 68HC12 (last-used stack mode). */
452 STATIC_INLINE UNUSED void
453 cpu_m68hc12_push_uint8 (sim_cpu *cpu, uint8_t val)
454 {
455 uint16_t addr = cpu->cpu_regs.sp;
456
457 addr --;
458 memory_write8 (cpu, addr, val);
459 cpu->cpu_regs.sp = addr;
460 }
461
462 STATIC_INLINE UNUSED void
463 cpu_m68hc12_push_uint16 (sim_cpu *cpu, uint16_t val)
464 {
465 uint16_t addr = cpu->cpu_regs.sp;
466
467 addr -= 2;
468 memory_write16 (cpu, addr, val);
469 cpu->cpu_regs.sp = addr;
470 }
471
472 STATIC_INLINE UNUSED uint8_t
473 cpu_m68hc12_pop_uint8 (sim_cpu *cpu)
474 {
475 uint16_t addr = cpu->cpu_regs.sp;
476 uint8_t val;
477
478 val = memory_read8 (cpu, addr);
479 cpu->cpu_regs.sp = addr + 1;
480 return val;
481 }
482
483 STATIC_INLINE UNUSED uint16_t
484 cpu_m68hc12_pop_uint16 (sim_cpu *cpu)
485 {
486 uint16_t addr = cpu->cpu_regs.sp;
487 uint16_t val;
488
489 val = memory_read16 (cpu, addr);
490 cpu->cpu_regs.sp = addr + 2;
491 return val;
492 }
493
494 /* Fetch a 8/16 bit value and update the PC. */
495 STATIC_INLINE UNUSED uint8_t
496 cpu_fetch8 (sim_cpu *cpu)
497 {
498 uint16_t addr = cpu->cpu_regs.pc;
499 uint8_t val;
500
501 val = memory_read8 (cpu, addr);
502 cpu->cpu_regs.pc = addr + 1;
503 return val;
504 }
505
506 STATIC_INLINE UNUSED uint16_t
507 cpu_fetch16 (sim_cpu *cpu)
508 {
509 uint16_t addr = cpu->cpu_regs.pc;
510 uint16_t val;
511
512 val = memory_read16 (cpu, addr);
513 cpu->cpu_regs.pc = addr + 2;
514 return val;
515 }
516
517 extern void cpu_call (sim_cpu *cpu, uint16_t addr);
518 extern void cpu_exg (sim_cpu *cpu, uint8_t code);
519 extern void cpu_dbcc (sim_cpu *cpu);
520 extern void cpu_special (sim_cpu *cpu, enum M6811_Special special);
521 extern void cpu_move8 (sim_cpu *cpu, uint8_t op);
522 extern void cpu_move16 (sim_cpu *cpu, uint8_t op);
523
524 extern uint16_t cpu_fetch_relbranch (sim_cpu *cpu);
525 extern uint16_t cpu_fetch_relbranch16 (sim_cpu *cpu);
526 extern void cpu_push_all (sim_cpu *cpu);
527 extern void cpu_single_step (sim_cpu *cpu);
528
529 extern void cpu_info (SIM_DESC sd, sim_cpu *cpu);
530
531 extern int cpu_initialize (SIM_DESC sd, sim_cpu *cpu);
532
533 /* Returns the address of a 68HC12 indexed operand.
534 Pre and post modifications are handled on the source register. */
535 extern uint16_t cpu_get_indexed_operand_addr (sim_cpu *cpu, int restricted);
536
537 extern void cpu_return (sim_cpu *cpu);
538 extern void cpu_set_sp (sim_cpu *cpu, uint16_t val);
539 extern int cpu_reset (sim_cpu *cpu);
540 extern int cpu_restart (sim_cpu *cpu);
541 extern void sim_memory_error (sim_cpu *cpu, SIM_SIGNAL excep,
542 uint16_t addr, const char *message, ...);
543 extern void emul_os (int op, sim_cpu *cpu);
544 extern void cpu_interp_m6811 (sim_cpu *cpu);
545 extern void cpu_interp_m6812 (sim_cpu *cpu);
546
547 extern int m68hc11cpu_set_oscillator (SIM_DESC sd, const char *port,
548 double ton, double toff,
549 int64_t repeat);
550 extern int m68hc11cpu_clear_oscillator (SIM_DESC sd, const char *port);
551 extern void m68hc11cpu_set_port (struct hw *me, sim_cpu *cpu,
552 unsigned addr, uint8_t val);
553
554 extern void sim_board_reset (SIM_DESC sd);
555
556 #define PRINT_TIME 0x01
557 #define PRINT_CYCLE 0x02
558 extern const char *cycle_to_string (sim_cpu *cpu, int64_t t, int flags);
559
560 #endif
561
562