1 /* dv-m68hc11.c -- CPU 68HC11&68HC12 as a device.
2 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
4 Written by Stephane Carrez (stcarrez@nerim.fr)
5 (From a driver model Contributed by Cygnus Solutions.)
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.
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.
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/>.
26 #include "sim-options.h"
32 m68hc11cpu - m68hc11 cpu virtual device
33 m68hc12cpu - m68hc12 cpu virtual device
37 Implements the external m68hc11/68hc12 functionality. This includes
38 the delivery of of interrupts generated from other devices and the
39 handling of device specific registers.
46 Register base (should be 0x1000 0x03f for C11, 0x0000 0x3ff for HC12).
50 Frequency of the quartz used by the processor.
52 mode [single | expanded | bootstrap | test]
54 Cpu operating mode (the MODA and MODB external pins).
61 Reset the cpu and generates a cpu-reset event (used to reset
66 Deliver a non-maskable interrupt to the processor.
73 Allow an external device to set the value of port A, C or D inputs.
78 Event generated after the CPU performs a reset.
86 Event generated when the value of the output port A, B, C or D
92 When delivering an interrupt, this code assumes that there is only
93 one processor (number 0).
99 OPTION_OSC_SET
= OPTION_START
,
104 static DECLARE_OPTION_HANDLER (m68hc11_option_handler
);
106 static const OPTION m68hc11_options
[] =
108 { {"osc-set", required_argument
, NULL
, OPTION_OSC_SET
},
109 '\0', "BIT,FREQ", "Set the oscillator on input port BIT",
110 m68hc11_option_handler
},
111 { {"osc-clear", required_argument
, NULL
, OPTION_OSC_CLEAR
},
112 '\0', "BIT", "Clear oscillator on input port BIT",
113 m68hc11_option_handler
},
114 { {"osc-info", no_argument
, NULL
, OPTION_OSC_INFO
},
115 '\0', NULL
, "Print information about current input oscillators",
116 m68hc11_option_handler
},
118 { {NULL
, no_argument
, NULL
, 0}, '\0', NULL
, NULL
, NULL
}
126 struct hw_event
*event
;
133 #define NR_PORT_A_OSC (4)
134 #define NR_PORT_B_OSC (0)
135 #define NR_PORT_C_OSC (8)
136 #define NR_PORT_D_OSC (6)
137 #define NR_OSC (NR_PORT_A_OSC + NR_PORT_B_OSC + NR_PORT_C_OSC + NR_PORT_D_OSC)
139 /* Pending interrupts for delivery by event handler. */
143 struct hw_event
*event
;
144 unsigned_word attach_address
;
148 struct input_osc oscillators
[NR_OSC
];
153 /* input port ID's */
172 static const struct hw_port_descriptor m68hc11cpu_ports
[] = {
174 /* Interrupt inputs. */
175 { "reset", RESET_PORT
, 0, input_port
, },
176 { "nmi", NMI_PORT
, 0, input_port
, },
177 { "irq", IRQ_PORT
, 0, input_port
, },
179 { "set-port-a", SET_PORT_A
, 0, input_port
, },
180 { "set-port-c", SET_PORT_C
, 0, input_port
, },
181 { "set-port-d", SET_PORT_D
, 0, input_port
, },
183 { "cpu-write-port", CPU_WRITE_PORT
, 0, input_port
, },
185 /* Events generated for connection to other devices. */
186 { "cpu-reset", CPU_RESET_PORT
, 0, output_port
, },
188 /* Events generated when the corresponding port is
189 changed by the program. */
190 { "port-a", PORT_A
, 0, output_port
, },
191 { "port-b", PORT_B
, 0, output_port
, },
192 { "port-c", PORT_C
, 0, output_port
, },
193 { "port-d", PORT_D
, 0, output_port
, },
195 { "capture", CAPTURE
, 0, output_port
, },
200 static hw_io_read_buffer_method m68hc11cpu_io_read_buffer
;
201 static hw_io_write_buffer_method m68hc11cpu_io_write_buffer
;
202 static hw_ioctl_method m68hc11_ioctl
;
204 /* Finish off the partially created hw device. Attach our local
205 callbacks. Wire up our port names etc. */
207 static hw_port_event_method m68hc11cpu_port_event
;
209 static void make_oscillator (struct m68hc11cpu
*controller
,
210 const char *id
, uint16 addr
, uint8 mask
);
211 static struct input_osc
*find_oscillator (struct m68hc11cpu
*controller
,
213 static void reset_oscillators (struct hw
*me
);
216 dv_m6811_attach_address_callback (struct hw
*me
,
220 address_word nr_bytes
,
223 HW_TRACE ((me
, "attach - level=%d, space=%d, addr=0x%lx, sz=%ld, client=%s",
224 level
, space
, (unsigned long) addr
, (unsigned long) nr_bytes
,
229 sim_core_attach (hw_system (me
),
232 access_read_write_exec
,
241 /*printf("Attach from sub device: %d\n", (long) addr);*/
242 sim_core_attach (hw_system (me
),
255 dv_m6811_detach_address_callback (struct hw
*me
,
259 address_word nr_bytes
,
262 sim_core_detach (hw_system (me
), NULL
, /*cpu*/
267 m68hc11_delete (struct hw
* me
)
269 struct m68hc11cpu
*controller
;
271 controller
= hw_data (me
);
273 reset_oscillators (me
);
274 hw_detach_address (me
, M6811_IO_LEVEL
,
275 controller
->attach_space
,
276 controller
->attach_address
,
277 controller
->attach_size
, me
);
282 attach_m68hc11_regs (struct hw
*me
,
283 struct m68hc11cpu
*controller
)
287 reg_property_spec reg
;
288 const char *cpu_mode
;
290 if (hw_find_property (me
, "reg") == NULL
)
291 hw_abort (me
, "Missing \"reg\" property");
293 if (!hw_find_reg_array_property (me
, "reg", 0, ®
))
294 hw_abort (me
, "\"reg\" property must contain one addr/size entry");
296 hw_unit_address_to_attach_address (hw_parent (me
),
298 &controller
->attach_space
,
299 &controller
->attach_address
,
301 hw_unit_size_to_attach_size (hw_parent (me
),
303 &controller
->attach_size
, me
);
305 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
,
306 controller
->attach_space
,
307 controller
->attach_address
,
308 controller
->attach_size
,
310 set_hw_delete (me
, m68hc11_delete
);
312 /* Get cpu frequency. */
314 cpu
= STATE_CPU (sd
, 0);
315 if (hw_find_property (me
, "clock") != NULL
)
317 cpu
->cpu_frequency
= hw_find_integer_property (me
, "clock");
321 cpu
->cpu_frequency
= 8*1000*1000;
324 if (hw_find_property (me
, "use_bank") != NULL
)
325 hw_attach_address (hw_parent (me
), 0,
328 cpu
->bank_end
- cpu
->bank_start
,
331 cpu_mode
= "expanded";
332 if (hw_find_property (me
, "mode") != NULL
)
333 cpu_mode
= hw_find_string_property (me
, "mode");
335 if (strcmp (cpu_mode
, "test") == 0)
336 cpu
->cpu_mode
= M6811_MDA
| M6811_SMOD
;
337 else if (strcmp (cpu_mode
, "bootstrap") == 0)
338 cpu
->cpu_mode
= M6811_SMOD
;
339 else if (strcmp (cpu_mode
, "single") == 0)
342 cpu
->cpu_mode
= M6811_MDA
;
344 controller
->last_oscillator
= 0;
346 /* Create oscillators for input port A. */
347 make_oscillator (controller
, "A7", M6811_PORTA
, 0x80);
348 make_oscillator (controller
, "A2", M6811_PORTA
, 0x04);
349 make_oscillator (controller
, "A1", M6811_PORTA
, 0x02);
350 make_oscillator (controller
, "A0", M6811_PORTA
, 0x01);
352 /* port B is output only. */
354 /* Create oscillators for input port C. */
355 make_oscillator (controller
, "C0", M6811_PORTC
, 0x01);
356 make_oscillator (controller
, "C1", M6811_PORTC
, 0x02);
357 make_oscillator (controller
, "C2", M6811_PORTC
, 0x04);
358 make_oscillator (controller
, "C3", M6811_PORTC
, 0x08);
359 make_oscillator (controller
, "C4", M6811_PORTC
, 0x10);
360 make_oscillator (controller
, "C5", M6811_PORTC
, 0x20);
361 make_oscillator (controller
, "C6", M6811_PORTC
, 0x40);
362 make_oscillator (controller
, "C7", M6811_PORTC
, 0x80);
364 /* Create oscillators for input port D. */
365 make_oscillator (controller
, "D0", M6811_PORTD
, 0x01);
366 make_oscillator (controller
, "D1", M6811_PORTD
, 0x02);
367 make_oscillator (controller
, "D2", M6811_PORTD
, 0x04);
368 make_oscillator (controller
, "D3", M6811_PORTD
, 0x08);
369 make_oscillator (controller
, "D4", M6811_PORTD
, 0x10);
370 make_oscillator (controller
, "D5", M6811_PORTD
, 0x20);
372 /* Add oscillator commands. */
373 sim_add_option_table (sd
, 0, m68hc11_options
);
377 m68hc11cpu_finish (struct hw
*me
)
379 struct m68hc11cpu
*controller
;
381 controller
= HW_ZALLOC (me
, struct m68hc11cpu
);
382 set_hw_data (me
, controller
);
383 set_hw_io_read_buffer (me
, m68hc11cpu_io_read_buffer
);
384 set_hw_io_write_buffer (me
, m68hc11cpu_io_write_buffer
);
385 set_hw_ports (me
, m68hc11cpu_ports
);
386 set_hw_port_event (me
, m68hc11cpu_port_event
);
387 set_hw_attach_address (me
, dv_m6811_attach_address_callback
);
388 set_hw_detach_address (me
, dv_m6811_detach_address_callback
);
390 set_hw_ioctl (me
, m68hc11_ioctl
);
392 me
->to_ioctl
= m68hc11_ioctl
;
395 /* Initialize the pending interrupt flags. */
396 controller
->pending_level
= 0;
397 controller
->pending_reset
= 0;
398 controller
->pending_nmi
= 0;
399 controller
->event
= NULL
;
401 attach_m68hc11_regs (me
, controller
);
404 /* An event arrives on an interrupt port. */
407 deliver_m68hc11cpu_interrupt (struct hw
*me
, void *data
)
412 make_oscillator (struct m68hc11cpu
*controller
, const char *name
,
413 uint16 addr
, uint8 mask
)
415 struct input_osc
*osc
;
417 if (controller
->last_oscillator
>= NR_OSC
)
418 hw_abort (0, "Too many oscillators");
420 osc
= &controller
->oscillators
[controller
->last_oscillator
];
424 controller
->last_oscillator
++;
427 /* Find the oscillator given the input port name. */
428 static struct input_osc
*
429 find_oscillator (struct m68hc11cpu
*controller
, const char *name
)
433 for (i
= 0; i
< controller
->last_oscillator
; i
++)
434 if (strcasecmp (controller
->oscillators
[i
].name
, name
) == 0)
435 return &controller
->oscillators
[i
];
441 oscillator_handler (struct hw
*me
, void *data
)
443 struct input_osc
*osc
= (struct input_osc
*) data
;
450 cpu
= STATE_CPU (sd
, 0);
452 /* Change the input bit. */
453 osc
->value
^= osc
->mask
;
454 val
= cpu
->ios
[osc
->addr
] & ~osc
->mask
;
456 m68hc11cpu_set_port (me
, cpu
, osc
->addr
, val
);
458 /* Setup event to toggle the bit. */
464 if (dt
&& --osc
->repeat
>= 0)
466 sim_events
*events
= STATE_EVENTS (sd
);
468 dt
+= events
->nr_ticks_to_process
;
469 osc
->event
= hw_event_queue_schedule (me
, dt
, oscillator_handler
, osc
);
476 reset_oscillators (struct hw
*me
)
478 struct m68hc11cpu
*controller
= hw_data (me
);
481 for (i
= 0; i
< controller
->last_oscillator
; i
++)
483 if (controller
->oscillators
[i
].event
)
485 hw_event_queue_deschedule (me
, controller
->oscillators
[i
].event
);
486 controller
->oscillators
[i
].event
= 0;
492 m68hc11cpu_port_event (struct hw
*me
,
498 struct m68hc11cpu
*controller
= hw_data (me
);
503 cpu
= STATE_CPU (sd
, 0);
507 HW_TRACE ((me
, "port-in reset"));
509 /* The reset is made in 3 steps:
510 - First, cleanup the current sim_cpu struct.
512 - Restart the cpu for the reset (get the CPU mode from the
513 CONFIG register that gets initialized by EEPROM device). */
515 reset_oscillators (me
);
516 hw_port_event (me
, CPU_RESET_PORT
, 1);
521 controller
->pending_nmi
= 1;
522 HW_TRACE ((me
, "port-in nmi"));
526 /* level == 0 means that the interrupt was cleared. */
528 controller
->pending_level
= -1; /* signal end of interrupt */
530 controller
->pending_level
= level
;
531 HW_TRACE ((me
, "port-in level=%d", level
));
535 m68hc11cpu_set_port (me
, cpu
, M6811_PORTA
, level
);
539 m68hc11cpu_set_port (me
, cpu
, M6811_PORTC
, level
);
543 m68hc11cpu_set_port (me
, cpu
, M6811_PORTD
, level
);
550 hw_abort (me
, "bad switch");
554 /* Schedule an event to be delivered immediately after current
556 if(controller
->event
!= NULL
)
557 hw_event_queue_deschedule(me
, controller
->event
);
559 hw_event_queue_schedule (me
, 0, deliver_m68hc11cpu_interrupt
, NULL
);
563 io_reg_desc config_desc
[] = {
564 { M6811_NOSEC
, "NOSEC ", "Security Mode Disable" },
565 { M6811_NOCOP
, "NOCOP ", "COP System Disable" },
566 { M6811_ROMON
, "ROMON ", "Enable On-chip Rom" },
567 { M6811_EEON
, "EEON ", "Enable On-chip EEprom" },
571 io_reg_desc hprio_desc
[] = {
572 { M6811_RBOOT
, "RBOOT ", "Read Bootstrap ROM" },
573 { M6811_SMOD
, "SMOD ", "Special Mode" },
574 { M6811_MDA
, "MDA ", "Mode Select A" },
575 { M6811_IRV
, "IRV ", "Internal Read Visibility" },
579 io_reg_desc option_desc
[] = {
580 { M6811_ADPU
, "ADPU ", "A/D Powerup" },
581 { M6811_CSEL
, "CSEL ", "A/D/EE Charge pump clock source select" },
582 { M6811_IRQE
, "IRQE ", "IRQ Edge/Level sensitive" },
583 { M6811_DLY
, "DLY ", "Stop exit turn on delay" },
584 { M6811_CME
, "CME ", "Clock Monitor Enable" },
585 { M6811_CR1
, "CR1 ", "COP timer rate select (CR1)" },
586 { M6811_CR0
, "CR0 ", "COP timer rate select (CR0)" },
591 m68hc11_info (struct hw
*me
)
596 struct m68hc11sio
*controller
;
600 cpu
= STATE_CPU (sd
, 0);
601 controller
= hw_data (me
);
603 base
= cpu_get_io_base (cpu
);
604 sim_io_printf (sd
, "M68HC11:\n");
606 val
= cpu
->ios
[M6811_HPRIO
];
607 print_io_byte (sd
, "HPRIO ", hprio_desc
, val
, base
+ M6811_HPRIO
);
608 switch (cpu
->cpu_mode
)
610 case M6811_MDA
| M6811_SMOD
:
611 sim_io_printf (sd
, "[test]\n");
614 sim_io_printf (sd
, "[bootstrap]\n");
617 sim_io_printf (sd
, "[extended]\n");
620 sim_io_printf (sd
, "[single]\n");
624 val
= cpu
->ios
[M6811_CONFIG
];
625 print_io_byte (sd
, "CONFIG", config_desc
, val
, base
+ M6811_CONFIG
);
626 sim_io_printf (sd
, "\n");
628 val
= cpu
->ios
[M6811_OPTION
];
629 print_io_byte (sd
, "OPTION", option_desc
, val
, base
+ M6811_OPTION
);
630 sim_io_printf (sd
, "\n");
632 val
= cpu
->ios
[M6811_INIT
];
633 print_io_byte (sd
, "INIT ", 0, val
, base
+ M6811_INIT
);
634 sim_io_printf (sd
, "Ram = 0x%04x IO = 0x%04x\n",
635 (((uint16
) (val
& 0xF0)) << 8),
636 (((uint16
) (val
& 0x0F)) << 12));
640 interrupts_info (sd
, &cpu
->cpu_interrupts
);
644 m68hc11_ioctl (struct hw
*me
,
645 hw_ioctl_request request
,
652 /* Setup an oscillator on an input port.
654 TON represents the time in seconds that the input port should be set to 1.
655 TOFF is the time in seconds for the input port to be set to 0.
657 The oscillator frequency is therefore 1 / (ton + toff).
659 REPEAT indicates the number of 1 <-> 0 transitions until the oscillator
662 m68hc11cpu_set_oscillator (SIM_DESC sd
, const char *port
,
663 double ton
, double toff
, signed64 repeat
)
666 struct input_osc
*osc
;
669 cpu
= STATE_CPU (sd
, 0);
671 /* Find oscillator that corresponds to the input port. */
672 osc
= find_oscillator (hw_data (cpu
->hw_cpu
), port
);
676 /* Compute the ON time in cpu cycles. */
677 f
= (double) (cpu
->cpu_frequency
) * ton
;
678 osc
->on_time
= (signed64
) (f
/ 4.0);
679 if (osc
->on_time
< 1)
682 /* Compute the OFF time in cpu cycles. */
683 f
= (double) (cpu
->cpu_frequency
) * toff
;
684 osc
->off_time
= (signed64
) (f
/ 4.0);
685 if (osc
->off_time
< 1)
688 osc
->repeat
= repeat
;
690 hw_event_queue_deschedule (cpu
->hw_cpu
, osc
->event
);
692 osc
->event
= hw_event_queue_schedule (cpu
->hw_cpu
,
693 osc
->value
? osc
->on_time
695 oscillator_handler
, osc
);
699 /* Clear the oscillator. */
701 m68hc11cpu_clear_oscillator (SIM_DESC sd
, const char *port
)
704 struct input_osc
*osc
;
706 cpu
= STATE_CPU (sd
, 0);
707 osc
= find_oscillator (hw_data (cpu
->hw_cpu
), port
);
712 hw_event_queue_deschedule (cpu
->hw_cpu
, osc
->event
);
719 get_frequency (const char *s
, double *f
)
729 if (strcasecmp (p
, "khz") == 0)
731 else if (strcasecmp (p
, "mhz") == 0)
733 else if (strcasecmp (p
, "hz") != 0)
740 m68hc11_option_handler (SIM_DESC sd
, sim_cpu
*cpu
,
741 int opt
, char *arg
, int is_command
)
743 struct m68hc11cpu
*controller
;
747 int title_printed
= 0;
750 cpu
= STATE_CPU (sd
, 0);
752 controller
= hw_data (cpu
->hw_cpu
);
756 p
= strchr (arg
, ',');
761 sim_io_eprintf (sd
, "No frequency specified\n");
762 else if (get_frequency (p
, &f
) < 0 || f
< 1.0e-8)
763 sim_io_eprintf (sd
, "Invalid frequency: '%s'\n", p
);
764 else if (m68hc11cpu_set_oscillator (sd
, arg
,
766 1.0 / (f
* 2.0), LONG_MAX
))
767 sim_io_eprintf (sd
, "Invalid input port: '%s'\n", arg
);
770 case OPTION_OSC_CLEAR
:
771 if (m68hc11cpu_clear_oscillator (sd
, arg
) != 0)
772 sim_io_eprintf (sd
, "Invalid input port: '%s'\n", arg
);
775 case OPTION_OSC_INFO
:
776 for (i
= 0; i
< controller
->last_oscillator
; i
++)
779 struct input_osc
*osc
;
781 osc
= &controller
->oscillators
[i
];
789 if (title_printed
== 0)
792 sim_io_printf (sd
, " PORT Frequency Current"
793 " Next Transition time\n");
796 f
= (double) (osc
->on_time
+ osc
->off_time
);
797 f
= (double) (cpu
->cpu_frequency
/ 4) / f
;
798 t
= hw_event_remain_time (cpu
->hw_cpu
, osc
->event
);
801 sprintf (freq
, "%6.2f", f
/ 1000.0);
803 sprintf (freq
, "%6.2f", f
);
804 cur_value
= osc
->value
? 1 : 0;
805 next_value
= osc
->value
? 0 : 1;
807 sim_io_printf (sd
, " %4.4s %8.8s khz"
810 cur_value
, next_value
,
811 cycle_to_string (cpu
, t
,
812 PRINT_TIME
| PRINT_CYCLE
));
814 sim_io_printf (sd
, " %4.4s %8.8s hz "
817 cur_value
, next_value
,
818 cycle_to_string (cpu
, t
,
819 PRINT_TIME
| PRINT_CYCLE
));
828 /* generic read/write */
831 m68hc11cpu_io_read_buffer (struct hw
*me
,
838 struct m68hc11cpu
*controller
= hw_data (me
);
843 HW_TRACE ((me
, "read 0x%08lx %d", (long) base
, (int) nr_bytes
));
846 cpu
= STATE_CPU (sd
, 0);
848 if (base
>= cpu
->bank_start
&& base
< cpu
->bank_end
)
850 address_word virt_addr
= phys_to_virt (cpu
, base
);
851 if (virt_addr
!= base
)
852 return sim_core_read_buffer (sd
, cpu
, space
, dest
,
853 virt_addr
, nr_bytes
);
856 /* Handle reads for the sub-devices. */
857 base
-= controller
->attach_address
;
858 result
= sim_core_read_buffer (sd
, cpu
,
859 io_map
, dest
, base
, nr_bytes
);
865 if (base
>= controller
->attach_size
)
868 memcpy (dest
, &cpu
->ios
[base
], 1);
869 dest
= (char*) dest
+ 1;
878 m68hc11cpu_set_port (struct hw
*me
, sim_cpu
*cpu
,
879 unsigned addr
, uint8 val
)
883 int check_interrupts
= 0;
889 if (cpu
->ios
[M6811_PACTL
] & M6811_DDRA7
)
895 val
|= cpu
->ios
[M6811_PORTA
] & ~mask
;
896 delta
= val
^ cpu
->ios
[M6811_PORTA
];
897 cpu
->ios
[M6811_PORTA
] = val
;
900 /* Pulse accumulator is enabled. */
901 if ((cpu
->ios
[M6811_PACTL
] & M6811_PAEN
)
902 && !(cpu
->ios
[M6811_PACTL
] & M6811_PAMOD
))
906 /* Increment event counter according to rising/falling edge. */
907 if (cpu
->ios
[M6811_PACTL
] & M6811_PEDGE
)
908 inc
= (val
& 0x80) ? 1 : 0;
910 inc
= (val
& 0x80) ? 0 : 1;
912 cpu
->ios
[M6811_PACNT
] += inc
;
914 /* Event counter overflowed. */
915 if (inc
&& cpu
->ios
[M6811_PACNT
] == 0)
917 cpu
->ios
[M6811_TFLG2
] |= M6811_PAOVI
;
918 check_interrupts
= 1;
923 /* Scan IC3, IC2 and IC1. Bit number is 3 - i. */
924 for (i
= 0; i
< 3; i
++)
926 uint8 mask
= (1 << i
);
933 edge
= cpu
->ios
[M6811_TCTL2
];
934 edge
= (edge
>> (2 * i
)) & 0x3;
941 captured
= (val
& mask
) != 0;
944 captured
= (val
& mask
) == 0;
952 cpu
->ios
[M6811_TFLG1
] |= (1 << i
);
953 hw_port_event (me
, CAPTURE
, M6811_TIC1
+ 3 - i
);
954 check_interrupts
= 1;
961 mask
= cpu
->ios
[M6811_DDRC
];
963 val
|= cpu
->ios
[M6811_PORTC
] & ~mask
;
964 cpu
->ios
[M6811_PORTC
] = val
;
968 mask
= cpu
->ios
[M6811_DDRD
];
970 val
|= cpu
->ios
[M6811_PORTD
] & ~mask
;
971 cpu
->ios
[M6811_PORTD
] = val
;
978 if (check_interrupts
)
979 interrupts_update_pending (&cpu
->cpu_interrupts
);
983 m68hc11cpu_io_write (struct hw
*me
, sim_cpu
*cpu
,
984 unsigned_word addr
, uint8 val
)
989 hw_port_event (me
, PORT_A
, val
);
996 hw_port_event (me
, PORT_C
, val
);
1000 hw_port_event (me
, PORT_B
, val
);
1010 hw_port_event (me
, PORT_D
, val
);
1020 /* Change the RAM and I/O mapping. */
1023 uint8 old_bank
= cpu
->ios
[M6811_INIT
];
1025 cpu
->ios
[M6811_INIT
] = val
;
1027 /* Update IO mapping. Detach from the old address
1028 and attach to the new one. */
1029 if ((old_bank
& 0x0F) != (val
& 0x0F))
1031 struct m68hc11cpu
*controller
= hw_data (me
);
1033 hw_detach_address (hw_parent (me
), M6811_IO_LEVEL
,
1034 controller
->attach_space
,
1035 controller
->attach_address
,
1036 controller
->attach_size
,
1038 controller
->attach_address
= (val
& 0x0F0) << 12;
1039 hw_attach_address (hw_parent (me
), M6811_IO_LEVEL
,
1040 controller
->attach_space
,
1041 controller
->attach_address
,
1042 controller
->attach_size
,
1045 if ((old_bank
& 0xF0) != (val
& 0xF0))
1052 /* Writing the config is similar to programing the eeprom.
1053 The config register value is the last byte of the EEPROM.
1054 This last byte is not mapped in memory (that's why we have
1055 to add '1' to 'end_addr'). */
1064 if (val
== 0xAA && cpu
->ios
[addr
] == 0x55)
1067 /* COP reset here. */
1075 cpu
->ios
[addr
] = val
;
1079 m68hc11cpu_io_write_buffer (struct hw
*me
,
1086 struct m68hc11cpu
*controller
= hw_data (me
);
1091 HW_TRACE ((me
, "write 0x%08lx %d", (long) base
, (int) nr_bytes
));
1093 sd
= hw_system (me
);
1094 cpu
= STATE_CPU (sd
, 0);
1096 if (base
>= cpu
->bank_start
&& base
< cpu
->bank_end
)
1098 address_word virt_addr
= phys_to_virt (cpu
, base
);
1099 if (virt_addr
!= base
)
1100 return sim_core_write_buffer (sd
, cpu
, space
, source
,
1101 virt_addr
, nr_bytes
);
1103 base
-= controller
->attach_address
;
1104 result
= sim_core_write_buffer (sd
, cpu
,
1105 io_map
, source
, base
, nr_bytes
);
1113 if (base
>= controller
->attach_size
)
1116 val
= *((uint8
*) source
);
1117 m68hc11cpu_io_write (me
, cpu
, base
, val
);
1118 source
= (char*) source
+ 1;
1126 const struct hw_descriptor dv_m68hc11_descriptor
[] = {
1127 { "m68hc11", m68hc11cpu_finish
},
1128 { "m68hc12", m68hc11cpu_finish
},