1 /* dv-m68hc11.c -- CPU 68HC11&68HC12 as a device.
2 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2007
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 2 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, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 #include "sim-options.h"
33 m68hc11cpu - m68hc11 cpu virtual device
34 m68hc12cpu - m68hc12 cpu virtual device
38 Implements the external m68hc11/68hc12 functionality. This includes
39 the delivery of of interrupts generated from other devices and the
40 handling of device specific registers.
47 Register base (should be 0x1000 0x03f for C11, 0x0000 0x3ff for HC12).
51 Frequency of the quartz used by the processor.
53 mode [single | expanded | bootstrap | test]
55 Cpu operating mode (the MODA and MODB external pins).
62 Reset the cpu and generates a cpu-reset event (used to reset
67 Deliver a non-maskable interrupt to the processor.
74 Allow an external device to set the value of port A, C or D inputs.
79 Event generated after the CPU performs a reset.
87 Event generated when the value of the output port A, B, C or D
93 When delivering an interrupt, this code assumes that there is only
94 one processor (number 0).
100 OPTION_OSC_SET = OPTION_START,
105 static DECLARE_OPTION_HANDLER (m68hc11_option_handler);
107 static const OPTION m68hc11_options[] =
109 { {"osc-set", required_argument, NULL, OPTION_OSC_SET },
110 '\0', "BIT,FREQ", "Set the oscillator on input port BIT",
111 m68hc11_option_handler },
112 { {"osc-clear", required_argument, NULL, OPTION_OSC_CLEAR },
113 '\0', "BIT", "Clear oscillator on input port BIT",
114 m68hc11_option_handler },
115 { {"osc-info", no_argument, NULL, OPTION_OSC_INFO },
116 '\0', NULL, "Print information about current input oscillators",
117 m68hc11_option_handler },
119 { {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
127 struct hw_event *event;
134 #define NR_PORT_A_OSC (4)
135 #define NR_PORT_B_OSC (0)
136 #define NR_PORT_C_OSC (8)
137 #define NR_PORT_D_OSC (6)
138 #define NR_OSC (NR_PORT_A_OSC + NR_PORT_B_OSC + NR_PORT_C_OSC + NR_PORT_D_OSC)
140 /* Pending interrupts for delivery by event handler. */
144 struct hw_event *event;
145 unsigned_word attach_address;
149 struct input_osc oscillators[NR_OSC];
154 /* input port ID's */
173 static const struct hw_port_descriptor m68hc11cpu_ports[] = {
175 /* Interrupt inputs. */
176 { "reset", RESET_PORT, 0, input_port, },
177 { "nmi", NMI_PORT, 0, input_port, },
178 { "irq", IRQ_PORT, 0, input_port, },
180 { "set-port-a", SET_PORT_A, 0, input_port, },
181 { "set-port-c", SET_PORT_C, 0, input_port, },
182 { "set-port-d", SET_PORT_D, 0, input_port, },
184 { "cpu-write-port", CPU_WRITE_PORT, 0, input_port, },
186 /* Events generated for connection to other devices. */
187 { "cpu-reset", CPU_RESET_PORT, 0, output_port, },
189 /* Events generated when the corresponding port is
190 changed by the program. */
191 { "port-a", PORT_A, 0, output_port, },
192 { "port-b", PORT_B, 0, output_port, },
193 { "port-c", PORT_C, 0, output_port, },
194 { "port-d", PORT_D, 0, output_port, },
196 { "capture", CAPTURE, 0, output_port, },
201 static hw_io_read_buffer_method m68hc11cpu_io_read_buffer;
202 static hw_io_write_buffer_method m68hc11cpu_io_write_buffer;
203 static hw_ioctl_method m68hc11_ioctl;
205 /* Finish off the partially created hw device. Attach our local
206 callbacks. Wire up our port names etc. */
208 static hw_port_event_method m68hc11cpu_port_event;
210 static void make_oscillator (struct m68hc11cpu *controller,
211 const char *id, uint16 addr, uint8 mask);
212 static struct input_osc *find_oscillator (struct m68hc11cpu *controller,
214 static void reset_oscillators (struct hw *me);
217 dv_m6811_attach_address_callback (struct hw *me,
221 address_word nr_bytes,
224 HW_TRACE ((me, "attach - level=%d, space=%d, addr=0x%lx, sz=%ld, client=%s",
225 level, space, (unsigned long) addr, (unsigned long) nr_bytes,
230 sim_core_attach (hw_system (me),
233 access_read_write_exec,
242 /*printf("Attach from sub device: %d\n", (long) addr);*/
243 sim_core_attach (hw_system (me),
256 dv_m6811_detach_address_callback (struct hw *me,
260 address_word nr_bytes,
263 sim_core_detach (hw_system (me), NULL, /*cpu*/
268 m68hc11_delete (struct hw* me)
270 struct m68hc11cpu *controller;
272 controller = hw_data (me);
274 reset_oscillators (me);
275 hw_detach_address (me, M6811_IO_LEVEL,
276 controller->attach_space,
277 controller->attach_address,
278 controller->attach_size, me);
283 attach_m68hc11_regs (struct hw *me,
284 struct m68hc11cpu *controller)
288 reg_property_spec reg;
289 const char *cpu_mode;
291 if (hw_find_property (me, "reg") == NULL)
292 hw_abort (me, "Missing \"reg\" property");
294 if (!hw_find_reg_array_property (me, "reg", 0, ®))
295 hw_abort (me, "\"reg\" property must contain one addr/size entry");
297 hw_unit_address_to_attach_address (hw_parent (me),
299 &controller->attach_space,
300 &controller->attach_address,
302 hw_unit_size_to_attach_size (hw_parent (me),
304 &controller->attach_size, me);
306 hw_attach_address (hw_parent (me), M6811_IO_LEVEL,
307 controller->attach_space,
308 controller->attach_address,
309 controller->attach_size,
311 set_hw_delete (me, m68hc11_delete);
313 /* Get cpu frequency. */
315 cpu = STATE_CPU (sd, 0);
316 if (hw_find_property (me, "clock") != NULL)
318 cpu->cpu_frequency = hw_find_integer_property (me, "clock");
322 cpu->cpu_frequency = 8*1000*1000;
325 if (hw_find_property (me, "use_bank") != NULL)
326 hw_attach_address (hw_parent (me), 0,
329 cpu->bank_end - cpu->bank_start,
332 cpu_mode = "expanded";
333 if (hw_find_property (me, "mode") != NULL)
334 cpu_mode = hw_find_string_property (me, "mode");
336 if (strcmp (cpu_mode, "test") == 0)
337 cpu->cpu_mode = M6811_MDA | M6811_SMOD;
338 else if (strcmp (cpu_mode, "bootstrap") == 0)
339 cpu->cpu_mode = M6811_SMOD;
340 else if (strcmp (cpu_mode, "single") == 0)
343 cpu->cpu_mode = M6811_MDA;
345 controller->last_oscillator = 0;
347 /* Create oscillators for input port A. */
348 make_oscillator (controller, "A7", M6811_PORTA, 0x80);
349 make_oscillator (controller, "A2", M6811_PORTA, 0x04);
350 make_oscillator (controller, "A1", M6811_PORTA, 0x02);
351 make_oscillator (controller, "A0", M6811_PORTA, 0x01);
353 /* port B is output only. */
355 /* Create oscillators for input port C. */
356 make_oscillator (controller, "C0", M6811_PORTC, 0x01);
357 make_oscillator (controller, "C1", M6811_PORTC, 0x02);
358 make_oscillator (controller, "C2", M6811_PORTC, 0x04);
359 make_oscillator (controller, "C3", M6811_PORTC, 0x08);
360 make_oscillator (controller, "C4", M6811_PORTC, 0x10);
361 make_oscillator (controller, "C5", M6811_PORTC, 0x20);
362 make_oscillator (controller, "C6", M6811_PORTC, 0x40);
363 make_oscillator (controller, "C7", M6811_PORTC, 0x80);
365 /* Create oscillators for input port D. */
366 make_oscillator (controller, "D0", M6811_PORTD, 0x01);
367 make_oscillator (controller, "D1", M6811_PORTD, 0x02);
368 make_oscillator (controller, "D2", M6811_PORTD, 0x04);
369 make_oscillator (controller, "D3", M6811_PORTD, 0x08);
370 make_oscillator (controller, "D4", M6811_PORTD, 0x10);
371 make_oscillator (controller, "D5", M6811_PORTD, 0x20);
373 /* Add oscillator commands. */
374 sim_add_option_table (sd, 0, m68hc11_options);
378 m68hc11cpu_finish (struct hw *me)
380 struct m68hc11cpu *controller;
382 controller = HW_ZALLOC (me, struct m68hc11cpu);
383 set_hw_data (me, controller);
384 set_hw_io_read_buffer (me, m68hc11cpu_io_read_buffer);
385 set_hw_io_write_buffer (me, m68hc11cpu_io_write_buffer);
386 set_hw_ports (me, m68hc11cpu_ports);
387 set_hw_port_event (me, m68hc11cpu_port_event);
388 set_hw_attach_address (me, dv_m6811_attach_address_callback);
389 set_hw_detach_address (me, dv_m6811_detach_address_callback);
391 set_hw_ioctl (me, m68hc11_ioctl);
393 me->to_ioctl = m68hc11_ioctl;
396 /* Initialize the pending interrupt flags. */
397 controller->pending_level = 0;
398 controller->pending_reset = 0;
399 controller->pending_nmi = 0;
400 controller->event = NULL;
402 attach_m68hc11_regs (me, controller);
405 /* An event arrives on an interrupt port. */
408 deliver_m68hc11cpu_interrupt (struct hw *me, void *data)
413 make_oscillator (struct m68hc11cpu *controller, const char *name,
414 uint16 addr, uint8 mask)
416 struct input_osc *osc;
418 if (controller->last_oscillator >= NR_OSC)
419 hw_abort (0, "Too many oscillators");
421 osc = &controller->oscillators[controller->last_oscillator];
425 controller->last_oscillator++;
428 /* Find the oscillator given the input port name. */
429 static struct input_osc *
430 find_oscillator (struct m68hc11cpu *controller, const char *name)
434 for (i = 0; i < controller->last_oscillator; i++)
435 if (strcasecmp (controller->oscillators[i].name, name) == 0)
436 return &controller->oscillators[i];
442 oscillator_handler (struct hw *me, void *data)
444 struct input_osc *osc = (struct input_osc*) data;
451 cpu = STATE_CPU (sd, 0);
453 /* Change the input bit. */
454 osc->value ^= osc->mask;
455 val = cpu->ios[osc->addr] & ~osc->mask;
457 m68hc11cpu_set_port (me, cpu, osc->addr, val);
459 /* Setup event to toggle the bit. */
465 if (dt && --osc->repeat >= 0)
467 sim_events *events = STATE_EVENTS (sd);
469 dt += events->nr_ticks_to_process;
470 osc->event = hw_event_queue_schedule (me, dt, oscillator_handler, osc);
477 reset_oscillators (struct hw *me)
479 struct m68hc11cpu *controller = hw_data (me);
482 for (i = 0; i < controller->last_oscillator; i++)
484 if (controller->oscillators[i].event)
486 hw_event_queue_deschedule (me, controller->oscillators[i].event);
487 controller->oscillators[i].event = 0;
493 m68hc11cpu_port_event (struct hw *me,
499 struct m68hc11cpu *controller = hw_data (me);
504 cpu = STATE_CPU (sd, 0);
508 HW_TRACE ((me, "port-in reset"));
510 /* The reset is made in 3 steps:
511 - First, cleanup the current sim_cpu struct.
513 - Restart the cpu for the reset (get the CPU mode from the
514 CONFIG register that gets initialized by EEPROM device). */
516 reset_oscillators (me);
517 hw_port_event (me, CPU_RESET_PORT, 1);
522 controller->pending_nmi = 1;
523 HW_TRACE ((me, "port-in nmi"));
527 /* level == 0 means that the interrupt was cleared. */
529 controller->pending_level = -1; /* signal end of interrupt */
531 controller->pending_level = level;
532 HW_TRACE ((me, "port-in level=%d", level));
536 m68hc11cpu_set_port (me, cpu, M6811_PORTA, level);
540 m68hc11cpu_set_port (me, cpu, M6811_PORTC, level);
544 m68hc11cpu_set_port (me, cpu, M6811_PORTD, level);
551 hw_abort (me, "bad switch");
555 /* Schedule an event to be delivered immediately after current
557 if(controller->event != NULL)
558 hw_event_queue_deschedule(me, controller->event);
560 hw_event_queue_schedule (me, 0, deliver_m68hc11cpu_interrupt, NULL);
564 io_reg_desc config_desc[] = {
565 { M6811_NOSEC, "NOSEC ", "Security Mode Disable" },
566 { M6811_NOCOP, "NOCOP ", "COP System Disable" },
567 { M6811_ROMON, "ROMON ", "Enable On-chip Rom" },
568 { M6811_EEON, "EEON ", "Enable On-chip EEprom" },
572 io_reg_desc hprio_desc[] = {
573 { M6811_RBOOT, "RBOOT ", "Read Bootstrap ROM" },
574 { M6811_SMOD, "SMOD ", "Special Mode" },
575 { M6811_MDA, "MDA ", "Mode Select A" },
576 { M6811_IRV, "IRV ", "Internal Read Visibility" },
580 io_reg_desc option_desc[] = {
581 { M6811_ADPU, "ADPU ", "A/D Powerup" },
582 { M6811_CSEL, "CSEL ", "A/D/EE Charge pump clock source select" },
583 { M6811_IRQE, "IRQE ", "IRQ Edge/Level sensitive" },
584 { M6811_DLY, "DLY ", "Stop exit turn on delay" },
585 { M6811_CME, "CME ", "Clock Monitor Enable" },
586 { M6811_CR1, "CR1 ", "COP timer rate select (CR1)" },
587 { M6811_CR0, "CR0 ", "COP timer rate select (CR0)" },
592 m68hc11_info (struct hw *me)
597 struct m68hc11sio *controller;
601 cpu = STATE_CPU (sd, 0);
602 controller = hw_data (me);
604 base = cpu_get_io_base (cpu);
605 sim_io_printf (sd, "M68HC11:\n");
607 val = cpu->ios[M6811_HPRIO];
608 print_io_byte (sd, "HPRIO ", hprio_desc, val, base + M6811_HPRIO);
609 switch (cpu->cpu_mode)
611 case M6811_MDA | M6811_SMOD:
612 sim_io_printf (sd, "[test]\n");
615 sim_io_printf (sd, "[bootstrap]\n");
618 sim_io_printf (sd, "[extended]\n");
621 sim_io_printf (sd, "[single]\n");
625 val = cpu->ios[M6811_CONFIG];
626 print_io_byte (sd, "CONFIG", config_desc, val, base + M6811_CONFIG);
627 sim_io_printf (sd, "\n");
629 val = cpu->ios[M6811_OPTION];
630 print_io_byte (sd, "OPTION", option_desc, val, base + M6811_OPTION);
631 sim_io_printf (sd, "\n");
633 val = cpu->ios[M6811_INIT];
634 print_io_byte (sd, "INIT ", 0, val, base + M6811_INIT);
635 sim_io_printf (sd, "Ram = 0x%04x IO = 0x%04x\n",
636 (((uint16) (val & 0xF0)) << 8),
637 (((uint16) (val & 0x0F)) << 12));
641 interrupts_info (sd, &cpu->cpu_interrupts);
645 m68hc11_ioctl (struct hw *me,
646 hw_ioctl_request request,
653 /* Setup an oscillator on an input port.
655 TON represents the time in seconds that the input port should be set to 1.
656 TOFF is the time in seconds for the input port to be set to 0.
658 The oscillator frequency is therefore 1 / (ton + toff).
660 REPEAT indicates the number of 1 <-> 0 transitions until the oscillator
663 m68hc11cpu_set_oscillator (SIM_DESC sd, const char *port,
664 double ton, double toff, signed64 repeat)
667 struct input_osc *osc;
670 cpu = STATE_CPU (sd, 0);
672 /* Find oscillator that corresponds to the input port. */
673 osc = find_oscillator (hw_data (cpu->hw_cpu), port);
677 /* Compute the ON time in cpu cycles. */
678 f = (double) (cpu->cpu_frequency) * ton;
679 osc->on_time = (signed64) (f / 4.0);
680 if (osc->on_time < 1)
683 /* Compute the OFF time in cpu cycles. */
684 f = (double) (cpu->cpu_frequency) * toff;
685 osc->off_time = (signed64) (f / 4.0);
686 if (osc->off_time < 1)
689 osc->repeat = repeat;
691 hw_event_queue_deschedule (cpu->hw_cpu, osc->event);
693 osc->event = hw_event_queue_schedule (cpu->hw_cpu,
694 osc->value ? osc->on_time
696 oscillator_handler, osc);
700 /* Clear the oscillator. */
702 m68hc11cpu_clear_oscillator (SIM_DESC sd, const char *port)
705 struct input_osc *osc;
707 cpu = STATE_CPU (sd, 0);
708 osc = find_oscillator (hw_data (cpu->hw_cpu), port);
713 hw_event_queue_deschedule (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 m68hc11cpu *controller;
748 int title_printed = 0;
751 cpu = STATE_CPU (sd, 0);
753 controller = hw_data (cpu->hw_cpu);
757 p = strchr (arg, ',');
762 sim_io_eprintf (sd, "No frequency specified\n");
763 else if (get_frequency (p, &f) < 0 || f < 1.0e-8)
764 sim_io_eprintf (sd, "Invalid frequency: '%s'\n", p);
765 else if (m68hc11cpu_set_oscillator (sd, arg,
767 1.0 / (f * 2.0), LONG_MAX))
768 sim_io_eprintf (sd, "Invalid input port: '%s'\n", arg);
771 case OPTION_OSC_CLEAR:
772 if (m68hc11cpu_clear_oscillator (sd, arg) != 0)
773 sim_io_eprintf (sd, "Invalid input port: '%s'\n", arg);
776 case OPTION_OSC_INFO:
777 for (i = 0; i < controller->last_oscillator; i++)
780 struct input_osc *osc;
782 osc = &controller->oscillators[i];
790 if (title_printed == 0)
793 sim_io_printf (sd, " PORT Frequency Current"
794 " Next Transition time\n");
797 f = (double) (osc->on_time + osc->off_time);
798 f = (double) (cpu->cpu_frequency / 4) / f;
799 t = hw_event_remain_time (cpu->hw_cpu, osc->event);
802 sprintf (freq, "%6.2f", f / 1000.0);
804 sprintf (freq, "%6.2f", f);
805 cur_value = osc->value ? 1 : 0;
806 next_value = osc->value ? 0 : 1;
808 sim_io_printf (sd, " %4.4s %8.8s khz"
811 cur_value, next_value,
812 cycle_to_string (cpu, t,
813 PRINT_TIME | PRINT_CYCLE));
815 sim_io_printf (sd, " %4.4s %8.8s hz "
818 cur_value, next_value,
819 cycle_to_string (cpu, t,
820 PRINT_TIME | PRINT_CYCLE));
829 /* generic read/write */
832 m68hc11cpu_io_read_buffer (struct hw *me,
839 struct m68hc11cpu *controller = hw_data (me);
844 HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
847 cpu = STATE_CPU (sd, 0);
849 if (base >= cpu->bank_start && base < cpu->bank_end)
851 address_word virt_addr = phys_to_virt (cpu, base);
852 if (virt_addr != base)
853 return sim_core_read_buffer (sd, cpu, space, dest,
854 virt_addr, nr_bytes);
857 /* Handle reads for the sub-devices. */
858 base -= controller->attach_address;
859 result = sim_core_read_buffer (sd, cpu,
860 io_map, dest, base, nr_bytes);
866 if (base >= controller->attach_size)
869 memcpy (dest, &cpu->ios[base], 1);
870 dest = (char*) dest + 1;
879 m68hc11cpu_set_port (struct hw *me, sim_cpu *cpu,
880 unsigned addr, uint8 val)
884 int check_interrupts = 0;
890 if (cpu->ios[M6811_PACTL] & M6811_DDRA7)
896 val |= cpu->ios[M6811_PORTA] & ~mask;
897 delta = val ^ cpu->ios[M6811_PORTA];
898 cpu->ios[M6811_PORTA] = val;
901 /* Pulse accumulator is enabled. */
902 if ((cpu->ios[M6811_PACTL] & M6811_PAEN)
903 && !(cpu->ios[M6811_PACTL] & M6811_PAMOD))
907 /* Increment event counter according to rising/falling edge. */
908 if (cpu->ios[M6811_PACTL] & M6811_PEDGE)
909 inc = (val & 0x80) ? 1 : 0;
911 inc = (val & 0x80) ? 0 : 1;
913 cpu->ios[M6811_PACNT] += inc;
915 /* Event counter overflowed. */
916 if (inc && cpu->ios[M6811_PACNT] == 0)
918 cpu->ios[M6811_TFLG2] |= M6811_PAOVI;
919 check_interrupts = 1;
924 /* Scan IC3, IC2 and IC1. Bit number is 3 - i. */
925 for (i = 0; i < 3; i++)
927 uint8 mask = (1 << i);
934 edge = cpu->ios[M6811_TCTL2];
935 edge = (edge >> (2 * i)) & 0x3;
942 captured = (val & mask) != 0;
945 captured = (val & mask) == 0;
953 cpu->ios[M6811_TFLG1] |= (1 << i);
954 hw_port_event (me, CAPTURE, M6811_TIC1 + 3 - i);
955 check_interrupts = 1;
962 mask = cpu->ios[M6811_DDRC];
964 val |= cpu->ios[M6811_PORTC] & ~mask;
965 cpu->ios[M6811_PORTC] = val;
969 mask = cpu->ios[M6811_DDRD];
971 val |= cpu->ios[M6811_PORTD] & ~mask;
972 cpu->ios[M6811_PORTD] = val;
979 if (check_interrupts)
980 interrupts_update_pending (&cpu->cpu_interrupts);
984 m68hc11cpu_io_write (struct hw *me, sim_cpu *cpu,
985 unsigned_word addr, uint8 val)
990 hw_port_event (me, PORT_A, val);
997 hw_port_event (me, PORT_C, val);
1001 hw_port_event (me, PORT_B, val);
1011 hw_port_event (me, PORT_D, val);
1021 /* Change the RAM and I/O mapping. */
1024 uint8 old_bank = cpu->ios[M6811_INIT];
1026 cpu->ios[M6811_INIT] = val;
1028 /* Update IO mapping. Detach from the old address
1029 and attach to the new one. */
1030 if ((old_bank & 0x0F) != (val & 0x0F))
1032 struct m68hc11cpu *controller = hw_data (me);
1034 hw_detach_address (hw_parent (me), M6811_IO_LEVEL,
1035 controller->attach_space,
1036 controller->attach_address,
1037 controller->attach_size,
1039 controller->attach_address = (val & 0x0F0) << 12;
1040 hw_attach_address (hw_parent (me), M6811_IO_LEVEL,
1041 controller->attach_space,
1042 controller->attach_address,
1043 controller->attach_size,
1046 if ((old_bank & 0xF0) != (val & 0xF0))
1053 /* Writing the config is similar to programing the eeprom.
1054 The config register value is the last byte of the EEPROM.
1055 This last byte is not mapped in memory (that's why we have
1056 to add '1' to 'end_addr'). */
1065 if (val == 0xAA && cpu->ios[addr] == 0x55)
1068 /* COP reset here. */
1076 cpu->ios[addr] = val;
1080 m68hc11cpu_io_write_buffer (struct hw *me,
1087 struct m68hc11cpu *controller = hw_data (me);
1092 HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
1094 sd = hw_system (me);
1095 cpu = STATE_CPU (sd, 0);
1097 if (base >= cpu->bank_start && base < cpu->bank_end)
1099 address_word virt_addr = phys_to_virt (cpu, base);
1100 if (virt_addr != base)
1101 return sim_core_write_buffer (sd, cpu, space, source,
1102 virt_addr, nr_bytes);
1104 base -= controller->attach_address;
1105 result = sim_core_write_buffer (sd, cpu,
1106 io_map, source, base, nr_bytes);
1114 if (base >= controller->attach_size)
1117 val = *((uint8*) source);
1118 m68hc11cpu_io_write (me, cpu, base, val);
1119 source = (char*) source + 1;
1127 const struct hw_descriptor dv_m68hc11_descriptor[] = {
1128 { "m68hc11", m68hc11cpu_finish },
1129 { "m68hc12", m68hc11cpu_finish },