1 /* dv-m68hc11.c -- CPU 68HC11&68HC12 as a device.
2 Copyright (C) 1999-2019 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/>.
25 #include "sim-options.h"
31 m68hc11cpu - m68hc11 cpu virtual device
32 m68hc12cpu - m68hc12 cpu virtual device
36 Implements the external m68hc11/68hc12 functionality. This includes
37 the delivery of of interrupts generated from other devices and the
38 handling of device specific registers.
45 Register base (should be 0x1000 0x03f for C11, 0x0000 0x3ff for HC12).
49 Frequency of the quartz used by the processor.
51 mode [single | expanded | bootstrap | test]
53 Cpu operating mode (the MODA and MODB external pins).
60 Reset the cpu and generates a cpu-reset event (used to reset
65 Deliver a non-maskable interrupt to the processor.
72 Allow an external device to set the value of port A, C or D inputs.
77 Event generated after the CPU performs a reset.
85 Event generated when the value of the output port A, B, C or D
91 When delivering an interrupt, this code assumes that there is only
92 one processor (number 0).
98 OPTION_OSC_SET
= OPTION_START
,
103 static DECLARE_OPTION_HANDLER (m68hc11_option_handler
);
105 static const OPTION m68hc11_options
[] =
107 { {"osc-set", required_argument
, NULL
, OPTION_OSC_SET
},
108 '\0', "BIT,FREQ", "Set the oscillator on input port BIT",
109 m68hc11_option_handler
},
110 { {"osc-clear", required_argument
, NULL
, OPTION_OSC_CLEAR
},
111 '\0', "BIT", "Clear oscillator on input port BIT",
112 m68hc11_option_handler
},
113 { {"osc-info", no_argument
, NULL
, OPTION_OSC_INFO
},
114 '\0', NULL
, "Print information about current input oscillators",
115 m68hc11_option_handler
},
117 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
125 struct hw_event
*event
;
132 #define NR_PORT_A_OSC (4)
133 #define NR_PORT_B_OSC (0)
134 #define NR_PORT_C_OSC (8)
135 #define NR_PORT_D_OSC (6)
136 #define NR_OSC (NR_PORT_A_OSC + NR_PORT_B_OSC + NR_PORT_C_OSC + NR_PORT_D_OSC)
138 /* Pending interrupts for delivery by event handler. */
142 struct hw_event
*event
;
143 unsigned_word attach_address
;
147 struct input_osc oscillators
[NR_OSC
];
152 /* input port ID's */
171 static const struct hw_port_descriptor m68hc11cpu_ports
[] = {
173 /* Interrupt inputs. */
174 { "reset", RESET_PORT
, 0, input_port
, },
175 { "nmi", NMI_PORT
, 0, input_port
, },
176 { "irq", IRQ_PORT
, 0, input_port
, },
178 { "set-port-a", SET_PORT_A
, 0, input_port
, },
179 { "set-port-c", SET_PORT_C
, 0, input_port
, },
180 { "set-port-d", SET_PORT_D
, 0, input_port
, },
182 { "cpu-write-port", CPU_WRITE_PORT
, 0, input_port
, },
184 /* Events generated for connection to other devices. */
185 { "cpu-reset", CPU_RESET_PORT
, 0, output_port
, },
187 /* Events generated when the corresponding port is
188 changed by the program. */
189 { "port-a", PORT_A
, 0, output_port
, },
190 { "port-b", PORT_B
, 0, output_port
, },
191 { "port-c", PORT_C
, 0, output_port
, },
192 { "port-d", PORT_D
, 0, output_port
, },
194 { "capture", CAPTURE
, 0, output_port
, },
199 static hw_io_read_buffer_method m68hc11cpu_io_read_buffer
;
200 static hw_io_write_buffer_method m68hc11cpu_io_write_buffer
;
201 static hw_ioctl_method m68hc11_ioctl
;
203 /* Finish off the partially created hw device. Attach our local
204 callbacks. Wire up our port names etc. */
206 static hw_port_event_method m68hc11cpu_port_event
;
208 static void make_oscillator (struct m68hc11cpu
*controller
,
209 const char *id
, uint16 addr
, uint8 mask
);
210 static struct input_osc
*find_oscillator (struct m68hc11cpu
*controller
,
212 static void reset_oscillators (struct hw
*me
);
215 dv_m6811_attach_address_callback (struct hw
*me
,
219 address_word nr_bytes
,
222 HW_TRACE ((me
, "attach - level=%d, space=%d, addr=0x%lx, sz=%ld, client=%s",
223 level
, space
, (unsigned long) addr
, (unsigned long) nr_bytes
,
228 sim_core_attach (hw_system (me
),
231 access_read_write_exec
,
240 /*printf("Attach from sub device: %d\n", (long) addr);*/
241 sim_core_attach (hw_system (me
),
254 dv_m6811_detach_address_callback (struct hw
*me
,
258 address_word nr_bytes
,
261 sim_core_detach (hw_system (me
), NULL
, /*cpu*/
266 m68hc11_delete (struct hw
* me
)
268 struct m68hc11cpu
*controller
;
270 controller
= hw_data (me
);
272 reset_oscillators (me
);
273 hw_detach_address (me
, M6811_IO_LEVEL
,
274 controller
->attach_space
,
275 controller
->attach_address
,
276 controller
->attach_size
, me
);
281 attach_m68hc11_regs (struct hw
*me
,
282 struct m68hc11cpu
*controller
)
286 reg_property_spec reg
;
287 const char *cpu_mode
;
289 if (hw_find_property (me
, "reg") == NULL
)
290 hw_abort (me
, "Missing \"reg\" property");
292 if (!hw_find_reg_array_property (me
, "reg", 0, ®
))
293 hw_abort (me
, "\"reg\" property must contain one addr/size entry");
295 hw_unit_address_to_attach_address (hw_parent (me
),
297 &controller
->attach_space
,
298 &controller
->attach_address
,
300 hw_unit_size_to_attach_size (hw_parent (me
),
302 &controller
->attach_size
, me
);
304 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
,
305 controller
->attach_space
,
306 controller
->attach_address
,
307 controller
->attach_size
,
309 set_hw_delete (me
, m68hc11_delete
);
311 /* Get cpu frequency. */
313 cpu
= STATE_CPU (sd
, 0);
314 if (hw_find_property (me
, "clock") != NULL
)
316 cpu
->cpu_frequency
= hw_find_integer_property (me
, "clock");
320 cpu
->cpu_frequency
= 8*1000*1000;
323 if (hw_find_property (me
, "use_bank") != NULL
)
324 hw_attach_address (hw_parent (me
), 0,
327 cpu
->bank_end
- cpu
->bank_start
,
330 cpu_mode
= "expanded";
331 if (hw_find_property (me
, "mode") != NULL
)
332 cpu_mode
= hw_find_string_property (me
, "mode");
334 if (strcmp (cpu_mode
, "test") == 0)
335 cpu
->cpu_mode
= M6811_MDA
| M6811_SMOD
;
336 else if (strcmp (cpu_mode
, "bootstrap") == 0)
337 cpu
->cpu_mode
= M6811_SMOD
;
338 else if (strcmp (cpu_mode
, "single") == 0)
341 cpu
->cpu_mode
= M6811_MDA
;
343 controller
->last_oscillator
= 0;
345 /* Create oscillators for input port A. */
346 make_oscillator (controller
, "A7", M6811_PORTA
, 0x80);
347 make_oscillator (controller
, "A2", M6811_PORTA
, 0x04);
348 make_oscillator (controller
, "A1", M6811_PORTA
, 0x02);
349 make_oscillator (controller
, "A0", M6811_PORTA
, 0x01);
351 /* port B is output only. */
353 /* Create oscillators for input port C. */
354 make_oscillator (controller
, "C0", M6811_PORTC
, 0x01);
355 make_oscillator (controller
, "C1", M6811_PORTC
, 0x02);
356 make_oscillator (controller
, "C2", M6811_PORTC
, 0x04);
357 make_oscillator (controller
, "C3", M6811_PORTC
, 0x08);
358 make_oscillator (controller
, "C4", M6811_PORTC
, 0x10);
359 make_oscillator (controller
, "C5", M6811_PORTC
, 0x20);
360 make_oscillator (controller
, "C6", M6811_PORTC
, 0x40);
361 make_oscillator (controller
, "C7", M6811_PORTC
, 0x80);
363 /* Create oscillators for input port D. */
364 make_oscillator (controller
, "D0", M6811_PORTD
, 0x01);
365 make_oscillator (controller
, "D1", M6811_PORTD
, 0x02);
366 make_oscillator (controller
, "D2", M6811_PORTD
, 0x04);
367 make_oscillator (controller
, "D3", M6811_PORTD
, 0x08);
368 make_oscillator (controller
, "D4", M6811_PORTD
, 0x10);
369 make_oscillator (controller
, "D5", M6811_PORTD
, 0x20);
371 /* Add oscillator commands. */
372 sim_add_option_table (sd
, 0, m68hc11_options
);
376 m68hc11cpu_finish (struct hw
*me
)
378 struct m68hc11cpu
*controller
;
380 controller
= HW_ZALLOC (me
, struct m68hc11cpu
);
381 set_hw_data (me
, controller
);
382 set_hw_io_read_buffer (me
, m68hc11cpu_io_read_buffer
);
383 set_hw_io_write_buffer (me
, m68hc11cpu_io_write_buffer
);
384 set_hw_ports (me
, m68hc11cpu_ports
);
385 set_hw_port_event (me
, m68hc11cpu_port_event
);
386 set_hw_attach_address (me
, dv_m6811_attach_address_callback
);
387 set_hw_detach_address (me
, dv_m6811_detach_address_callback
);
389 set_hw_ioctl (me
, m68hc11_ioctl
);
391 me
->to_ioctl
= m68hc11_ioctl
;
394 /* Initialize the pending interrupt flags. */
395 controller
->pending_level
= 0;
396 controller
->pending_reset
= 0;
397 controller
->pending_nmi
= 0;
398 controller
->event
= NULL
;
400 attach_m68hc11_regs (me
, controller
);
403 /* An event arrives on an interrupt port. */
406 deliver_m68hc11cpu_interrupt (struct hw
*me
, void *data
)
411 make_oscillator (struct m68hc11cpu
*controller
, const char *name
,
412 uint16 addr
, uint8 mask
)
414 struct input_osc
*osc
;
416 if (controller
->last_oscillator
>= NR_OSC
)
417 hw_abort (0, "Too many oscillators");
419 osc
= &controller
->oscillators
[controller
->last_oscillator
];
423 controller
->last_oscillator
++;
426 /* Find the oscillator given the input port name. */
427 static struct input_osc
*
428 find_oscillator (struct m68hc11cpu
*controller
, const char *name
)
432 for (i
= 0; i
< controller
->last_oscillator
; i
++)
433 if (strcasecmp (controller
->oscillators
[i
].name
, name
) == 0)
434 return &controller
->oscillators
[i
];
440 oscillator_handler (struct hw
*me
, void *data
)
442 struct input_osc
*osc
= (struct input_osc
*) data
;
449 cpu
= STATE_CPU (sd
, 0);
451 /* Change the input bit. */
452 osc
->value
^= osc
->mask
;
453 val
= cpu
->ios
[osc
->addr
] & ~osc
->mask
;
455 m68hc11cpu_set_port (me
, cpu
, osc
->addr
, val
);
457 /* Setup event to toggle the bit. */
463 if (dt
&& --osc
->repeat
>= 0)
465 sim_events
*events
= STATE_EVENTS (sd
);
467 dt
+= events
->nr_ticks_to_process
;
468 osc
->event
= hw_event_queue_schedule (me
, dt
, oscillator_handler
, osc
);
475 reset_oscillators (struct hw
*me
)
477 struct m68hc11cpu
*controller
= hw_data (me
);
480 for (i
= 0; i
< controller
->last_oscillator
; i
++)
482 if (controller
->oscillators
[i
].event
)
484 hw_event_queue_deschedule (me
, controller
->oscillators
[i
].event
);
485 controller
->oscillators
[i
].event
= 0;
491 m68hc11cpu_port_event (struct hw
*me
,
497 struct m68hc11cpu
*controller
= hw_data (me
);
502 cpu
= STATE_CPU (sd
, 0);
506 HW_TRACE ((me
, "port-in reset"));
508 /* The reset is made in 3 steps:
509 - First, cleanup the current sim_cpu struct.
511 - Restart the cpu for the reset (get the CPU mode from the
512 CONFIG register that gets initialized by EEPROM device). */
514 reset_oscillators (me
);
515 hw_port_event (me
, CPU_RESET_PORT
, 1);
520 controller
->pending_nmi
= 1;
521 HW_TRACE ((me
, "port-in nmi"));
525 /* level == 0 means that the interrupt was cleared. */
527 controller
->pending_level
= -1; /* signal end of interrupt */
529 controller
->pending_level
= level
;
530 HW_TRACE ((me
, "port-in level=%d", level
));
534 m68hc11cpu_set_port (me
, cpu
, M6811_PORTA
, level
);
538 m68hc11cpu_set_port (me
, cpu
, M6811_PORTC
, level
);
542 m68hc11cpu_set_port (me
, cpu
, M6811_PORTD
, level
);
549 hw_abort (me
, "bad switch");
553 /* Schedule an event to be delivered immediately after current
555 if(controller
->event
!= NULL
)
556 hw_event_queue_deschedule(me
, controller
->event
);
558 hw_event_queue_schedule (me
, 0, deliver_m68hc11cpu_interrupt
, NULL
);
562 io_reg_desc config_desc
[] = {
563 { M6811_NOSEC
, "NOSEC ", "Security Mode Disable" },
564 { M6811_NOCOP
, "NOCOP ", "COP System Disable" },
565 { M6811_ROMON
, "ROMON ", "Enable On-chip Rom" },
566 { M6811_EEON
, "EEON ", "Enable On-chip EEprom" },
570 io_reg_desc hprio_desc
[] = {
571 { M6811_RBOOT
, "RBOOT ", "Read Bootstrap ROM" },
572 { M6811_SMOD
, "SMOD ", "Special Mode" },
573 { M6811_MDA
, "MDA ", "Mode Select A" },
574 { M6811_IRV
, "IRV ", "Internal Read Visibility" },
578 io_reg_desc option_desc
[] = {
579 { M6811_ADPU
, "ADPU ", "A/D Powerup" },
580 { M6811_CSEL
, "CSEL ", "A/D/EE Charge pump clock source select" },
581 { M6811_IRQE
, "IRQE ", "IRQ Edge/Level sensitive" },
582 { M6811_DLY
, "DLY ", "Stop exit turn on delay" },
583 { M6811_CME
, "CME ", "Clock Monitor Enable" },
584 { M6811_CR1
, "CR1 ", "COP timer rate select (CR1)" },
585 { M6811_CR0
, "CR0 ", "COP timer rate select (CR0)" },
590 m68hc11_info (struct hw
*me
)
595 struct m68hc11sio
*controller
;
599 cpu
= STATE_CPU (sd
, 0);
600 controller
= hw_data (me
);
602 base
= cpu_get_io_base (cpu
);
603 sim_io_printf (sd
, "M68HC11:\n");
605 val
= cpu
->ios
[M6811_HPRIO
];
606 print_io_byte (sd
, "HPRIO ", hprio_desc
, val
, base
+ M6811_HPRIO
);
607 switch (cpu
->cpu_mode
)
609 case M6811_MDA
| M6811_SMOD
:
610 sim_io_printf (sd
, "[test]\n");
613 sim_io_printf (sd
, "[bootstrap]\n");
616 sim_io_printf (sd
, "[extended]\n");
619 sim_io_printf (sd
, "[single]\n");
623 val
= cpu
->ios
[M6811_CONFIG
];
624 print_io_byte (sd
, "CONFIG", config_desc
, val
, base
+ M6811_CONFIG
);
625 sim_io_printf (sd
, "\n");
627 val
= cpu
->ios
[M6811_OPTION
];
628 print_io_byte (sd
, "OPTION", option_desc
, val
, base
+ M6811_OPTION
);
629 sim_io_printf (sd
, "\n");
631 val
= cpu
->ios
[M6811_INIT
];
632 print_io_byte (sd
, "INIT ", 0, val
, base
+ M6811_INIT
);
633 sim_io_printf (sd
, "Ram = 0x%04x IO = 0x%04x\n",
634 (((uint16
) (val
& 0xF0)) << 8),
635 (((uint16
) (val
& 0x0F)) << 12));
639 interrupts_info (sd
, &cpu
->cpu_interrupts
);
643 m68hc11_ioctl (struct hw
*me
,
644 hw_ioctl_request request
,
651 /* Setup an oscillator on an input port.
653 TON represents the time in seconds that the input port should be set to 1.
654 TOFF is the time in seconds for the input port to be set to 0.
656 The oscillator frequency is therefore 1 / (ton + toff).
658 REPEAT indicates the number of 1 <-> 0 transitions until the oscillator
661 m68hc11cpu_set_oscillator (SIM_DESC sd
, const char *port
,
662 double ton
, double toff
, signed64 repeat
)
665 struct input_osc
*osc
;
668 cpu
= STATE_CPU (sd
, 0);
670 /* Find oscillator that corresponds to the input port. */
671 osc
= find_oscillator (hw_data (cpu
->hw_cpu
), port
);
675 /* Compute the ON time in cpu cycles. */
676 f
= (double) (cpu
->cpu_frequency
) * ton
;
677 osc
->on_time
= (signed64
) (f
/ 4.0);
678 if (osc
->on_time
< 1)
681 /* Compute the OFF time in cpu cycles. */
682 f
= (double) (cpu
->cpu_frequency
) * toff
;
683 osc
->off_time
= (signed64
) (f
/ 4.0);
684 if (osc
->off_time
< 1)
687 osc
->repeat
= repeat
;
689 hw_event_queue_deschedule (cpu
->hw_cpu
, osc
->event
);
691 osc
->event
= hw_event_queue_schedule (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 input_osc
*osc
;
705 cpu
= STATE_CPU (sd
, 0);
706 osc
= find_oscillator (hw_data (cpu
->hw_cpu
), port
);
711 hw_event_queue_deschedule (cpu
->hw_cpu
, osc
->event
);
718 get_frequency (const char *s
, double *f
)
728 if (strcasecmp (p
, "khz") == 0)
730 else if (strcasecmp (p
, "mhz") == 0)
732 else if (strcasecmp (p
, "hz") != 0)
739 m68hc11_option_handler (SIM_DESC sd
, sim_cpu
*cpu
,
740 int opt
, char *arg
, int is_command
)
742 struct m68hc11cpu
*controller
;
746 int title_printed
= 0;
749 cpu
= STATE_CPU (sd
, 0);
751 controller
= hw_data (cpu
->hw_cpu
);
755 p
= strchr (arg
, ',');
760 sim_io_eprintf (sd
, "No frequency specified\n");
761 else if (get_frequency (p
, &f
) < 0 || f
< 1.0e-8)
762 sim_io_eprintf (sd
, "Invalid frequency: '%s'\n", p
);
763 else if (m68hc11cpu_set_oscillator (sd
, arg
,
765 1.0 / (f
* 2.0), LONG_MAX
))
766 sim_io_eprintf (sd
, "Invalid input port: '%s'\n", arg
);
769 case OPTION_OSC_CLEAR
:
770 if (m68hc11cpu_clear_oscillator (sd
, arg
) != 0)
771 sim_io_eprintf (sd
, "Invalid input port: '%s'\n", arg
);
774 case OPTION_OSC_INFO
:
775 for (i
= 0; i
< controller
->last_oscillator
; i
++)
778 struct input_osc
*osc
;
780 osc
= &controller
->oscillators
[i
];
788 if (title_printed
== 0)
791 sim_io_printf (sd
, " PORT Frequency Current"
792 " Next Transition time\n");
795 f
= (double) (osc
->on_time
+ osc
->off_time
);
796 f
= (double) (cpu
->cpu_frequency
/ 4) / f
;
797 t
= hw_event_remain_time (cpu
->hw_cpu
, osc
->event
);
800 sprintf (freq
, "%6.2f", f
/ 1000.0);
802 sprintf (freq
, "%6.2f", f
);
803 cur_value
= osc
->value
? 1 : 0;
804 next_value
= osc
->value
? 0 : 1;
806 sim_io_printf (sd
, " %4.4s %8.8s khz"
809 cur_value
, next_value
,
810 cycle_to_string (cpu
, t
,
811 PRINT_TIME
| PRINT_CYCLE
));
813 sim_io_printf (sd
, " %4.4s %8.8s hz "
816 cur_value
, next_value
,
817 cycle_to_string (cpu
, t
,
818 PRINT_TIME
| PRINT_CYCLE
));
827 /* generic read/write */
830 m68hc11cpu_io_read_buffer (struct hw
*me
,
837 struct m68hc11cpu
*controller
= hw_data (me
);
842 HW_TRACE ((me
, "read 0x%08lx %d", (long) base
, (int) nr_bytes
));
845 cpu
= STATE_CPU (sd
, 0);
847 if (base
>= cpu
->bank_start
&& base
< cpu
->bank_end
)
849 address_word virt_addr
= phys_to_virt (cpu
, base
);
850 if (virt_addr
!= base
)
851 return sim_core_read_buffer (sd
, cpu
, space
, dest
,
852 virt_addr
, nr_bytes
);
855 /* Handle reads for the sub-devices. */
856 base
-= controller
->attach_address
;
857 result
= sim_core_read_buffer (sd
, cpu
,
858 io_map
, dest
, base
, nr_bytes
);
864 if (base
>= controller
->attach_size
)
867 memcpy (dest
, &cpu
->ios
[base
], 1);
868 dest
= (char*) dest
+ 1;
877 m68hc11cpu_set_port (struct hw
*me
, sim_cpu
*cpu
,
878 unsigned addr
, uint8 val
)
882 int check_interrupts
= 0;
888 if (cpu
->ios
[M6811_PACTL
] & M6811_DDRA7
)
894 val
|= cpu
->ios
[M6811_PORTA
] & ~mask
;
895 delta
= val
^ cpu
->ios
[M6811_PORTA
];
896 cpu
->ios
[M6811_PORTA
] = val
;
899 /* Pulse accumulator is enabled. */
900 if ((cpu
->ios
[M6811_PACTL
] & M6811_PAEN
)
901 && !(cpu
->ios
[M6811_PACTL
] & M6811_PAMOD
))
905 /* Increment event counter according to rising/falling edge. */
906 if (cpu
->ios
[M6811_PACTL
] & M6811_PEDGE
)
907 inc
= (val
& 0x80) ? 1 : 0;
909 inc
= (val
& 0x80) ? 0 : 1;
911 cpu
->ios
[M6811_PACNT
] += inc
;
913 /* Event counter overflowed. */
914 if (inc
&& cpu
->ios
[M6811_PACNT
] == 0)
916 cpu
->ios
[M6811_TFLG2
] |= M6811_PAOVI
;
917 check_interrupts
= 1;
922 /* Scan IC3, IC2 and IC1. Bit number is 3 - i. */
923 for (i
= 0; i
< 3; i
++)
925 uint8 mask
= (1 << i
);
932 edge
= cpu
->ios
[M6811_TCTL2
];
933 edge
= (edge
>> (2 * i
)) & 0x3;
940 captured
= (val
& mask
) != 0;
943 captured
= (val
& mask
) == 0;
951 cpu
->ios
[M6811_TFLG1
] |= (1 << i
);
952 hw_port_event (me
, CAPTURE
, M6811_TIC1
+ 3 - i
);
953 check_interrupts
= 1;
960 mask
= cpu
->ios
[M6811_DDRC
];
962 val
|= cpu
->ios
[M6811_PORTC
] & ~mask
;
963 cpu
->ios
[M6811_PORTC
] = val
;
967 mask
= cpu
->ios
[M6811_DDRD
];
969 val
|= cpu
->ios
[M6811_PORTD
] & ~mask
;
970 cpu
->ios
[M6811_PORTD
] = val
;
977 if (check_interrupts
)
978 interrupts_update_pending (&cpu
->cpu_interrupts
);
982 m68hc11cpu_io_write (struct hw
*me
, sim_cpu
*cpu
,
983 unsigned_word addr
, uint8 val
)
988 hw_port_event (me
, PORT_A
, val
);
995 hw_port_event (me
, PORT_C
, val
);
999 hw_port_event (me
, PORT_B
, val
);
1009 hw_port_event (me
, PORT_D
, val
);
1019 /* Change the RAM and I/O mapping. */
1022 uint8 old_bank
= cpu
->ios
[M6811_INIT
];
1024 cpu
->ios
[M6811_INIT
] = val
;
1026 /* Update IO mapping. Detach from the old address
1027 and attach to the new one. */
1028 if ((old_bank
& 0x0F) != (val
& 0x0F))
1030 struct m68hc11cpu
*controller
= hw_data (me
);
1032 hw_detach_address (hw_parent (me
), M6811_IO_LEVEL
,
1033 controller
->attach_space
,
1034 controller
->attach_address
,
1035 controller
->attach_size
,
1037 controller
->attach_address
= (val
& 0x0F0) << 12;
1038 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
,
1039 controller
->attach_space
,
1040 controller
->attach_address
,
1041 controller
->attach_size
,
1044 if ((old_bank
& 0xF0) != (val
& 0xF0))
1051 /* Writing the config is similar to programing the eeprom.
1052 The config register value is the last byte of the EEPROM.
1053 This last byte is not mapped in memory (that's why we have
1054 to add '1' to 'end_addr'). */
1063 if (val
== 0xAA && cpu
->ios
[addr
] == 0x55)
1066 /* COP reset here. */
1074 cpu
->ios
[addr
] = val
;
1078 m68hc11cpu_io_write_buffer (struct hw
*me
,
1085 struct m68hc11cpu
*controller
= hw_data (me
);
1090 HW_TRACE ((me
, "write 0x%08lx %d", (long) base
, (int) nr_bytes
));
1092 sd
= hw_system (me
);
1093 cpu
= STATE_CPU (sd
, 0);
1095 if (base
>= cpu
->bank_start
&& base
< cpu
->bank_end
)
1097 address_word virt_addr
= phys_to_virt (cpu
, base
);
1098 if (virt_addr
!= base
)
1099 return sim_core_write_buffer (sd
, cpu
, space
, source
,
1100 virt_addr
, nr_bytes
);
1102 base
-= controller
->attach_address
;
1103 result
= sim_core_write_buffer (sd
, cpu
,
1104 io_map
, source
, base
, nr_bytes
);
1112 if (base
>= controller
->attach_size
)
1115 val
= *((uint8
*) source
);
1116 m68hc11cpu_io_write (me
, cpu
, base
, val
);
1117 source
= (char*) source
+ 1;
1125 const struct hw_descriptor dv_m68hc11_descriptor
[] = {
1126 { "m68hc11", m68hc11cpu_finish
},
1127 { "m68hc12", m68hc11cpu_finish
},