1 /* dv-m68hc11.c -- CPU 68HC11&68HC12 as a device.
2 Copyright (C) 1999-2022 Free Software Foundation, Inc.
3 Written by Stephane Carrez (stcarrez@nerim.fr)
4 (From a driver model Contributed by Cygnus Solutions.)
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 /* This must come before any other includes. */
27 #include "sim-options.h"
32 #include "m68hc11-sim.h"
36 m68hc11cpu - m68hc11 cpu virtual device
37 m68hc12cpu - m68hc12 cpu virtual device
41 Implements the external m68hc11/68hc12 functionality. This includes
42 the delivery of of interrupts generated from other devices and the
43 handling of device specific registers.
50 Register base (should be 0x1000 0x03f for C11, 0x0000 0x3ff for HC12).
54 Frequency of the quartz used by the processor.
56 mode [single | expanded | bootstrap | test]
58 Cpu operating mode (the MODA and MODB external pins).
65 Reset the cpu and generates a cpu-reset event (used to reset
70 Deliver a non-maskable interrupt to the processor.
77 Allow an external device to set the value of port A, C or D inputs.
82 Event generated after the CPU performs a reset.
90 Event generated when the value of the output port A, B, C or D
96 When delivering an interrupt, this code assumes that there is only
97 one processor (number 0).
103 OPTION_OSC_SET
= OPTION_START
,
108 static DECLARE_OPTION_HANDLER (m68hc11_option_handler
);
110 static const OPTION m68hc11_options
[] =
112 { {"osc-set", required_argument
, NULL
, OPTION_OSC_SET
},
113 '\0', "BIT,FREQ", "Set the oscillator on input port BIT",
114 m68hc11_option_handler
},
115 { {"osc-clear", required_argument
, NULL
, OPTION_OSC_CLEAR
},
116 '\0', "BIT", "Clear oscillator on input port BIT",
117 m68hc11_option_handler
},
118 { {"osc-info", no_argument
, NULL
, OPTION_OSC_INFO
},
119 '\0', NULL
, "Print information about current input oscillators",
120 m68hc11_option_handler
},
122 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
130 struct hw_event
*event
;
137 #define NR_PORT_A_OSC (4)
138 #define NR_PORT_B_OSC (0)
139 #define NR_PORT_C_OSC (8)
140 #define NR_PORT_D_OSC (6)
141 #define NR_OSC (NR_PORT_A_OSC + NR_PORT_B_OSC + NR_PORT_C_OSC + NR_PORT_D_OSC)
143 /* Pending interrupts for delivery by event handler. */
147 struct hw_event
*event
;
148 unsigned_word attach_address
;
149 unsigned int attach_size
;
152 struct input_osc oscillators
[NR_OSC
];
157 /* input port ID's */
176 static const struct hw_port_descriptor m68hc11cpu_ports
[] = {
178 /* Interrupt inputs. */
179 { "reset", RESET_PORT
, 0, input_port
, },
180 { "nmi", NMI_PORT
, 0, input_port
, },
181 { "irq", IRQ_PORT
, 0, input_port
, },
183 { "set-port-a", SET_PORT_A
, 0, input_port
, },
184 { "set-port-c", SET_PORT_C
, 0, input_port
, },
185 { "set-port-d", SET_PORT_D
, 0, input_port
, },
187 { "cpu-write-port", CPU_WRITE_PORT
, 0, input_port
, },
189 /* Events generated for connection to other devices. */
190 { "cpu-reset", CPU_RESET_PORT
, 0, output_port
, },
192 /* Events generated when the corresponding port is
193 changed by the program. */
194 { "port-a", PORT_A
, 0, output_port
, },
195 { "port-b", PORT_B
, 0, output_port
, },
196 { "port-c", PORT_C
, 0, output_port
, },
197 { "port-d", PORT_D
, 0, output_port
, },
199 { "capture", CAPTURE
, 0, output_port
, },
204 static hw_io_read_buffer_method m68hc11cpu_io_read_buffer
;
205 static hw_io_write_buffer_method m68hc11cpu_io_write_buffer
;
206 static hw_ioctl_method m68hc11_ioctl
;
208 /* Finish off the partially created hw device. Attach our local
209 callbacks. Wire up our port names etc. */
211 static hw_port_event_method m68hc11cpu_port_event
;
213 static void make_oscillator (struct m68hc11cpu
*controller
,
214 const char *id
, uint16_t addr
, uint8_t mask
);
215 static struct input_osc
*find_oscillator (struct m68hc11cpu
*controller
,
217 static void reset_oscillators (struct hw
*me
);
220 dv_m6811_attach_address_callback (struct hw
*me
,
224 address_word nr_bytes
,
227 HW_TRACE ((me
, "attach - level=%d, space=%d, addr=0x%lx, sz=%ld, client=%s",
228 level
, space
, (unsigned long) addr
, (unsigned long) nr_bytes
,
233 sim_core_attach (hw_system (me
),
236 access_read_write_exec
,
245 /*printf("Attach from sub device: %d\n", (long) addr);*/
246 sim_core_attach (hw_system (me
),
259 m68hc11_delete (struct hw
* me
)
261 struct m68hc11cpu
*controller
;
263 controller
= hw_data (me
);
265 reset_oscillators (me
);
266 hw_detach_address (me
, M6811_IO_LEVEL
,
267 controller
->attach_space
,
268 controller
->attach_address
,
269 controller
->attach_size
, me
);
274 attach_m68hc11_regs (struct hw
*me
,
275 struct m68hc11cpu
*controller
)
279 struct m68hc11_sim_cpu
*m68hc11_cpu
;
280 reg_property_spec reg
;
281 const char *cpu_mode
;
283 if (hw_find_property (me
, "reg") == NULL
)
284 hw_abort (me
, "Missing \"reg\" property");
286 if (!hw_find_reg_array_property (me
, "reg", 0, ®
))
287 hw_abort (me
, "\"reg\" property must contain one addr/size entry");
289 hw_unit_address_to_attach_address (hw_parent (me
),
291 &controller
->attach_space
,
292 &controller
->attach_address
,
294 hw_unit_size_to_attach_size (hw_parent (me
),
296 &controller
->attach_size
, me
);
298 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
,
299 controller
->attach_space
,
300 controller
->attach_address
,
301 controller
->attach_size
,
303 set_hw_delete (me
, m68hc11_delete
);
305 /* Get cpu frequency. */
307 cpu
= STATE_CPU (sd
, 0);
308 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
309 if (hw_find_property (me
, "clock") != NULL
)
311 m68hc11_cpu
->cpu_frequency
= hw_find_integer_property (me
, "clock");
315 m68hc11_cpu
->cpu_frequency
= 8*1000*1000;
318 if (hw_find_property (me
, "use_bank") != NULL
)
319 hw_attach_address (hw_parent (me
), 0,
321 m68hc11_cpu
->bank_start
,
322 m68hc11_cpu
->bank_end
- m68hc11_cpu
->bank_start
,
325 cpu_mode
= "expanded";
326 if (hw_find_property (me
, "mode") != NULL
)
327 cpu_mode
= hw_find_string_property (me
, "mode");
329 if (strcmp (cpu_mode
, "test") == 0)
330 m68hc11_cpu
->cpu_mode
= M6811_MDA
| M6811_SMOD
;
331 else if (strcmp (cpu_mode
, "bootstrap") == 0)
332 m68hc11_cpu
->cpu_mode
= M6811_SMOD
;
333 else if (strcmp (cpu_mode
, "single") == 0)
334 m68hc11_cpu
->cpu_mode
= 0;
336 m68hc11_cpu
->cpu_mode
= M6811_MDA
;
338 controller
->last_oscillator
= 0;
340 /* Create oscillators for input port A. */
341 make_oscillator (controller
, "A7", M6811_PORTA
, 0x80);
342 make_oscillator (controller
, "A2", M6811_PORTA
, 0x04);
343 make_oscillator (controller
, "A1", M6811_PORTA
, 0x02);
344 make_oscillator (controller
, "A0", M6811_PORTA
, 0x01);
346 /* port B is output only. */
348 /* Create oscillators for input port C. */
349 make_oscillator (controller
, "C0", M6811_PORTC
, 0x01);
350 make_oscillator (controller
, "C1", M6811_PORTC
, 0x02);
351 make_oscillator (controller
, "C2", M6811_PORTC
, 0x04);
352 make_oscillator (controller
, "C3", M6811_PORTC
, 0x08);
353 make_oscillator (controller
, "C4", M6811_PORTC
, 0x10);
354 make_oscillator (controller
, "C5", M6811_PORTC
, 0x20);
355 make_oscillator (controller
, "C6", M6811_PORTC
, 0x40);
356 make_oscillator (controller
, "C7", M6811_PORTC
, 0x80);
358 /* Create oscillators for input port D. */
359 make_oscillator (controller
, "D0", M6811_PORTD
, 0x01);
360 make_oscillator (controller
, "D1", M6811_PORTD
, 0x02);
361 make_oscillator (controller
, "D2", M6811_PORTD
, 0x04);
362 make_oscillator (controller
, "D3", M6811_PORTD
, 0x08);
363 make_oscillator (controller
, "D4", M6811_PORTD
, 0x10);
364 make_oscillator (controller
, "D5", M6811_PORTD
, 0x20);
366 /* Add oscillator commands. */
367 sim_add_option_table (sd
, 0, m68hc11_options
);
371 m68hc11cpu_finish (struct hw
*me
)
373 struct m68hc11cpu
*controller
;
375 controller
= HW_ZALLOC (me
, struct m68hc11cpu
);
376 set_hw_data (me
, controller
);
377 set_hw_io_read_buffer (me
, m68hc11cpu_io_read_buffer
);
378 set_hw_io_write_buffer (me
, m68hc11cpu_io_write_buffer
);
379 set_hw_ports (me
, m68hc11cpu_ports
);
380 set_hw_port_event (me
, m68hc11cpu_port_event
);
381 set_hw_attach_address (me
, dv_m6811_attach_address_callback
);
383 set_hw_ioctl (me
, m68hc11_ioctl
);
385 me
->to_ioctl
= m68hc11_ioctl
;
388 /* Initialize the pending interrupt flags. */
389 controller
->pending_level
= 0;
390 controller
->pending_reset
= 0;
391 controller
->pending_nmi
= 0;
392 controller
->event
= NULL
;
394 attach_m68hc11_regs (me
, controller
);
397 /* An event arrives on an interrupt port. */
400 deliver_m68hc11cpu_interrupt (struct hw
*me
, void *data
)
405 make_oscillator (struct m68hc11cpu
*controller
, const char *name
,
406 uint16_t addr
, uint8_t mask
)
408 struct input_osc
*osc
;
410 if (controller
->last_oscillator
>= NR_OSC
)
411 hw_abort (0, "Too many oscillators");
413 osc
= &controller
->oscillators
[controller
->last_oscillator
];
417 controller
->last_oscillator
++;
420 /* Find the oscillator given the input port name. */
421 static struct input_osc
*
422 find_oscillator (struct m68hc11cpu
*controller
, const char *name
)
426 for (i
= 0; i
< controller
->last_oscillator
; i
++)
427 if (strcasecmp (controller
->oscillators
[i
].name
, name
) == 0)
428 return &controller
->oscillators
[i
];
434 oscillator_handler (struct hw
*me
, void *data
)
436 struct input_osc
*osc
= (struct input_osc
*) data
;
439 struct m68hc11_sim_cpu
*m68hc11_cpu
;
444 cpu
= STATE_CPU (sd
, 0);
445 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
447 /* Change the input bit. */
448 osc
->value
^= osc
->mask
;
449 val
= m68hc11_cpu
->ios
[osc
->addr
] & ~osc
->mask
;
451 m68hc11cpu_set_port (me
, cpu
, osc
->addr
, val
);
453 /* Setup event to toggle the bit. */
459 if (dt
&& --osc
->repeat
>= 0)
461 sim_events
*events
= STATE_EVENTS (sd
);
463 dt
+= events
->nr_ticks_to_process
;
464 osc
->event
= hw_event_queue_schedule (me
, dt
, oscillator_handler
, osc
);
471 reset_oscillators (struct hw
*me
)
473 struct m68hc11cpu
*controller
= hw_data (me
);
476 for (i
= 0; i
< controller
->last_oscillator
; i
++)
478 if (controller
->oscillators
[i
].event
)
480 hw_event_queue_deschedule (me
, controller
->oscillators
[i
].event
);
481 controller
->oscillators
[i
].event
= 0;
487 m68hc11cpu_port_event (struct hw
*me
,
493 struct m68hc11cpu
*controller
= hw_data (me
);
498 cpu
= STATE_CPU (sd
, 0);
502 HW_TRACE ((me
, "port-in reset"));
504 /* The reset is made in 3 steps:
505 - First, cleanup the current sim_cpu struct.
507 - Restart the cpu for the reset (get the CPU mode from the
508 CONFIG register that gets initialized by EEPROM device). */
510 reset_oscillators (me
);
511 hw_port_event (me
, CPU_RESET_PORT
, 1);
516 controller
->pending_nmi
= 1;
517 HW_TRACE ((me
, "port-in nmi"));
521 /* level == 0 means that the interrupt was cleared. */
523 controller
->pending_level
= -1; /* signal end of interrupt */
525 controller
->pending_level
= level
;
526 HW_TRACE ((me
, "port-in level=%d", level
));
530 m68hc11cpu_set_port (me
, cpu
, M6811_PORTA
, level
);
534 m68hc11cpu_set_port (me
, cpu
, M6811_PORTC
, level
);
538 m68hc11cpu_set_port (me
, cpu
, M6811_PORTD
, level
);
545 hw_abort (me
, "bad switch");
549 /* Schedule an event to be delivered immediately after current
551 if(controller
->event
!= NULL
)
552 hw_event_queue_deschedule(me
, controller
->event
);
554 hw_event_queue_schedule (me
, 0, deliver_m68hc11cpu_interrupt
, NULL
);
558 io_reg_desc config_desc
[] = {
559 { M6811_NOSEC
, "NOSEC ", "Security Mode Disable" },
560 { M6811_NOCOP
, "NOCOP ", "COP System Disable" },
561 { M6811_ROMON
, "ROMON ", "Enable On-chip Rom" },
562 { M6811_EEON
, "EEON ", "Enable On-chip EEprom" },
566 io_reg_desc hprio_desc
[] = {
567 { M6811_RBOOT
, "RBOOT ", "Read Bootstrap ROM" },
568 { M6811_SMOD
, "SMOD ", "Special Mode" },
569 { M6811_MDA
, "MDA ", "Mode Select A" },
570 { M6811_IRV
, "IRV ", "Internal Read Visibility" },
574 io_reg_desc option_desc
[] = {
575 { M6811_ADPU
, "ADPU ", "A/D Powerup" },
576 { M6811_CSEL
, "CSEL ", "A/D/EE Charge pump clock source select" },
577 { M6811_IRQE
, "IRQE ", "IRQ Edge/Level sensitive" },
578 { M6811_DLY
, "DLY ", "Stop exit turn on delay" },
579 { M6811_CME
, "CME ", "Clock Monitor Enable" },
580 { M6811_CR1
, "CR1 ", "COP timer rate select (CR1)" },
581 { M6811_CR0
, "CR0 ", "COP timer rate select (CR0)" },
586 m68hc11_info (struct hw
*me
)
591 struct m68hc11_sim_cpu
*m68hc11_cpu
;
592 struct m68hc11sio
*controller
;
596 cpu
= STATE_CPU (sd
, 0);
597 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
598 controller
= hw_data (me
);
600 base
= cpu_get_io_base (cpu
);
601 sim_io_printf (sd
, "M68HC11:\n");
603 val
= m68hc11_cpu
->ios
[M6811_HPRIO
];
604 print_io_byte (sd
, "HPRIO ", hprio_desc
, val
, base
+ M6811_HPRIO
);
605 switch (m68hc11_cpu
->cpu_mode
)
607 case M6811_MDA
| M6811_SMOD
:
608 sim_io_printf (sd
, "[test]\n");
611 sim_io_printf (sd
, "[bootstrap]\n");
614 sim_io_printf (sd
, "[extended]\n");
617 sim_io_printf (sd
, "[single]\n");
621 val
= m68hc11_cpu
->ios
[M6811_CONFIG
];
622 print_io_byte (sd
, "CONFIG", config_desc
, val
, base
+ M6811_CONFIG
);
623 sim_io_printf (sd
, "\n");
625 val
= m68hc11_cpu
->ios
[M6811_OPTION
];
626 print_io_byte (sd
, "OPTION", option_desc
, val
, base
+ M6811_OPTION
);
627 sim_io_printf (sd
, "\n");
629 val
= m68hc11_cpu
->ios
[M6811_INIT
];
630 print_io_byte (sd
, "INIT ", 0, val
, base
+ M6811_INIT
);
631 sim_io_printf (sd
, "Ram = 0x%04x IO = 0x%04x\n",
632 (((uint16_t) (val
& 0xF0)) << 8),
633 (((uint16_t) (val
& 0x0F)) << 12));
637 interrupts_info (sd
, &m68hc11_cpu
->cpu_interrupts
);
641 m68hc11_ioctl (struct hw
*me
,
642 hw_ioctl_request request
,
649 /* Setup an oscillator on an input port.
651 TON represents the time in seconds that the input port should be set to 1.
652 TOFF is the time in seconds for the input port to be set to 0.
654 The oscillator frequency is therefore 1 / (ton + toff).
656 REPEAT indicates the number of 1 <-> 0 transitions until the oscillator
659 m68hc11cpu_set_oscillator (SIM_DESC sd
, const char *port
,
660 double ton
, double toff
, int64_t repeat
)
663 struct m68hc11_sim_cpu
*m68hc11_cpu
;
664 struct input_osc
*osc
;
667 cpu
= STATE_CPU (sd
, 0);
668 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
670 /* Find oscillator that corresponds to the input port. */
671 osc
= find_oscillator (hw_data (m68hc11_cpu
->hw_cpu
), port
);
675 /* Compute the ON time in cpu cycles. */
676 f
= (double) (m68hc11_cpu
->cpu_frequency
) * ton
;
677 osc
->on_time
= (int64_t) (f
/ 4.0);
678 if (osc
->on_time
< 1)
681 /* Compute the OFF time in cpu cycles. */
682 f
= (double) (m68hc11_cpu
->cpu_frequency
) * toff
;
683 osc
->off_time
= (int64_t) (f
/ 4.0);
684 if (osc
->off_time
< 1)
687 osc
->repeat
= repeat
;
689 hw_event_queue_deschedule (m68hc11_cpu
->hw_cpu
, osc
->event
);
691 osc
->event
= hw_event_queue_schedule (m68hc11_cpu
->hw_cpu
,
692 osc
->value
? osc
->on_time
694 oscillator_handler
, osc
);
698 /* Clear the oscillator. */
700 m68hc11cpu_clear_oscillator (SIM_DESC sd
, const char *port
)
703 struct m68hc11_sim_cpu
*m68hc11_cpu
;
704 struct input_osc
*osc
;
706 cpu
= STATE_CPU (sd
, 0);
707 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
708 osc
= find_oscillator (hw_data (m68hc11_cpu
->hw_cpu
), port
);
713 hw_event_queue_deschedule (m68hc11_cpu
->hw_cpu
, osc
->event
);
720 get_frequency (const char *s
, double *f
)
730 if (strcasecmp (p
, "khz") == 0)
732 else if (strcasecmp (p
, "mhz") == 0)
734 else if (strcasecmp (p
, "hz") != 0)
741 m68hc11_option_handler (SIM_DESC sd
, sim_cpu
*cpu
,
742 int opt
, char *arg
, int is_command
)
744 struct m68hc11_sim_cpu
*m68hc11_cpu
;
745 struct m68hc11cpu
*controller
;
749 int title_printed
= 0;
752 cpu
= STATE_CPU (sd
, 0);
753 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
755 controller
= hw_data (m68hc11_cpu
->hw_cpu
);
759 p
= strchr (arg
, ',');
764 sim_io_eprintf (sd
, "No frequency specified\n");
765 else if (get_frequency (p
, &f
) < 0 || f
< 1.0e-8)
766 sim_io_eprintf (sd
, "Invalid frequency: '%s'\n", p
);
767 else if (m68hc11cpu_set_oscillator (sd
, arg
,
769 1.0 / (f
* 2.0), LONG_MAX
))
770 sim_io_eprintf (sd
, "Invalid input port: '%s'\n", arg
);
773 case OPTION_OSC_CLEAR
:
774 if (m68hc11cpu_clear_oscillator (sd
, arg
) != 0)
775 sim_io_eprintf (sd
, "Invalid input port: '%s'\n", arg
);
778 case OPTION_OSC_INFO
:
779 for (i
= 0; i
< controller
->last_oscillator
; i
++)
782 struct input_osc
*osc
;
784 osc
= &controller
->oscillators
[i
];
792 if (title_printed
== 0)
795 sim_io_printf (sd
, " PORT Frequency Current"
796 " Next Transition time\n");
799 f
= (double) (osc
->on_time
+ osc
->off_time
);
800 f
= (double) (m68hc11_cpu
->cpu_frequency
/ 4) / f
;
801 t
= hw_event_remain_time (m68hc11_cpu
->hw_cpu
, osc
->event
);
804 sprintf (freq
, "%6.2f", f
/ 1000.0);
806 sprintf (freq
, "%6.2f", f
);
807 cur_value
= osc
->value
? 1 : 0;
808 next_value
= osc
->value
? 0 : 1;
810 sim_io_printf (sd
, " %4.4s %8.8s khz"
813 cur_value
, next_value
,
814 cycle_to_string (cpu
, t
,
815 PRINT_TIME
| PRINT_CYCLE
));
817 sim_io_printf (sd
, " %4.4s %8.8s hz "
820 cur_value
, next_value
,
821 cycle_to_string (cpu
, t
,
822 PRINT_TIME
| PRINT_CYCLE
));
831 /* generic read/write */
834 m68hc11cpu_io_read_buffer (struct hw
*me
,
841 struct m68hc11cpu
*controller
= hw_data (me
);
843 struct m68hc11_sim_cpu
*m68hc11_cpu
;
847 HW_TRACE ((me
, "read 0x%08lx %d", (long) base
, (int) nr_bytes
));
850 cpu
= STATE_CPU (sd
, 0);
851 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
853 if (base
>= m68hc11_cpu
->bank_start
&& base
< m68hc11_cpu
->bank_end
)
855 address_word virt_addr
= phys_to_virt (cpu
, base
);
856 if (virt_addr
!= base
)
857 return sim_core_read_buffer (sd
, cpu
, space
, dest
,
858 virt_addr
, nr_bytes
);
861 /* Handle reads for the sub-devices. */
862 base
-= controller
->attach_address
;
863 result
= sim_core_read_buffer (sd
, cpu
,
864 io_map
, dest
, base
, nr_bytes
);
870 if (base
>= controller
->attach_size
)
873 memcpy (dest
, &m68hc11_cpu
->ios
[base
], 1);
874 dest
= (char*) dest
+ 1;
883 m68hc11cpu_set_port (struct hw
*me
, sim_cpu
*cpu
,
884 unsigned addr
, uint8_t val
)
886 struct m68hc11_sim_cpu
*m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
889 int check_interrupts
= 0;
895 if (m68hc11_cpu
->ios
[M6811_PACTL
] & M6811_DDRA7
)
901 val
|= m68hc11_cpu
->ios
[M6811_PORTA
] & ~mask
;
902 delta
= val
^ m68hc11_cpu
->ios
[M6811_PORTA
];
903 m68hc11_cpu
->ios
[M6811_PORTA
] = val
;
906 /* Pulse accumulator is enabled. */
907 if ((m68hc11_cpu
->ios
[M6811_PACTL
] & M6811_PAEN
)
908 && !(m68hc11_cpu
->ios
[M6811_PACTL
] & M6811_PAMOD
))
912 /* Increment event counter according to rising/falling edge. */
913 if (m68hc11_cpu
->ios
[M6811_PACTL
] & M6811_PEDGE
)
914 inc
= (val
& 0x80) ? 1 : 0;
916 inc
= (val
& 0x80) ? 0 : 1;
918 m68hc11_cpu
->ios
[M6811_PACNT
] += inc
;
920 /* Event counter overflowed. */
921 if (inc
&& m68hc11_cpu
->ios
[M6811_PACNT
] == 0)
923 m68hc11_cpu
->ios
[M6811_TFLG2
] |= M6811_PAOVI
;
924 check_interrupts
= 1;
929 /* Scan IC3, IC2 and IC1. Bit number is 3 - i. */
930 for (i
= 0; i
< 3; i
++)
932 uint8_t mask
= (1 << i
);
939 edge
= m68hc11_cpu
->ios
[M6811_TCTL2
];
940 edge
= (edge
>> (2 * i
)) & 0x3;
947 captured
= (val
& mask
) != 0;
950 captured
= (val
& mask
) == 0;
958 m68hc11_cpu
->ios
[M6811_TFLG1
] |= (1 << i
);
959 hw_port_event (me
, CAPTURE
, M6811_TIC1
+ 3 - i
);
960 check_interrupts
= 1;
967 mask
= m68hc11_cpu
->ios
[M6811_DDRC
];
969 val
|= m68hc11_cpu
->ios
[M6811_PORTC
] & ~mask
;
970 m68hc11_cpu
->ios
[M6811_PORTC
] = val
;
974 mask
= m68hc11_cpu
->ios
[M6811_DDRD
];
976 val
|= m68hc11_cpu
->ios
[M6811_PORTD
] & ~mask
;
977 m68hc11_cpu
->ios
[M6811_PORTD
] = val
;
984 if (check_interrupts
)
985 interrupts_update_pending (&m68hc11_cpu
->cpu_interrupts
);
989 m68hc11cpu_io_write (struct hw
*me
, sim_cpu
*cpu
,
990 unsigned_word addr
, uint8_t val
)
992 struct m68hc11_sim_cpu
*m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
997 hw_port_event (me
, PORT_A
, val
);
1004 hw_port_event (me
, PORT_C
, val
);
1008 hw_port_event (me
, PORT_B
, val
);
1018 hw_port_event (me
, PORT_D
, val
);
1028 /* Change the RAM and I/O mapping. */
1031 uint8_t old_bank
= m68hc11_cpu
->ios
[M6811_INIT
];
1033 m68hc11_cpu
->ios
[M6811_INIT
] = val
;
1035 /* Update IO mapping. Detach from the old address
1036 and attach to the new one. */
1037 if ((old_bank
& 0x0F) != (val
& 0x0F))
1039 struct m68hc11cpu
*controller
= hw_data (me
);
1041 hw_detach_address (hw_parent (me
), M6811_IO_LEVEL
,
1042 controller
->attach_space
,
1043 controller
->attach_address
,
1044 controller
->attach_size
,
1046 controller
->attach_address
= (val
& 0x0F0) << 12;
1047 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
,
1048 controller
->attach_space
,
1049 controller
->attach_address
,
1050 controller
->attach_size
,
1053 if ((old_bank
& 0xF0) != (val
& 0xF0))
1060 /* Writing the config is similar to programing the eeprom.
1061 The config register value is the last byte of the EEPROM.
1062 This last byte is not mapped in memory (that's why we have
1063 to add '1' to 'end_addr'). */
1072 if (val
== 0xAA && m68hc11_cpu
->ios
[addr
] == 0x55)
1075 /* COP reset here. */
1083 m68hc11_cpu
->ios
[addr
] = val
;
1087 m68hc11cpu_io_write_buffer (struct hw
*me
,
1094 struct m68hc11cpu
*controller
= hw_data (me
);
1097 struct m68hc11_sim_cpu
*m68hc11_cpu
;
1100 HW_TRACE ((me
, "write 0x%08lx %d", (long) base
, (int) nr_bytes
));
1102 sd
= hw_system (me
);
1103 cpu
= STATE_CPU (sd
, 0);
1104 m68hc11_cpu
= M68HC11_SIM_CPU (cpu
);
1106 if (base
>= m68hc11_cpu
->bank_start
&& base
< m68hc11_cpu
->bank_end
)
1108 address_word virt_addr
= phys_to_virt (cpu
, base
);
1109 if (virt_addr
!= base
)
1110 return sim_core_write_buffer (sd
, cpu
, space
, source
,
1111 virt_addr
, nr_bytes
);
1113 base
-= controller
->attach_address
;
1114 result
= sim_core_write_buffer (sd
, cpu
,
1115 io_map
, source
, base
, nr_bytes
);
1123 if (base
>= controller
->attach_size
)
1126 val
= *((uint8_t*) source
);
1127 m68hc11cpu_io_write (me
, cpu
, base
, val
);
1128 source
= (char*) source
+ 1;
1136 const struct hw_descriptor dv_m68hc11_descriptor
[] = {
1137 { "m68hc11", m68hc11cpu_finish
},
1138 { "m68hc12", m68hc11cpu_finish
},