#include "sim-main.h"
#include "sim-hw.h"
#include "hw-main.h"
#include "sim-options.h"
#include "hw-base.h"
#include <limits.h>
enum
{
OPTION_OSC_SET = OPTION_START,
OPTION_OSC_CLEAR,
OPTION_OSC_INFO
};
static DECLARE_OPTION_HANDLER (m68hc11_option_handler);
static const OPTION m68hc11_options[] =
{
{ {"osc-set", required_argument, NULL, OPTION_OSC_SET },
'\0', "BIT,FREQ", "Set the oscillator on input port BIT",
m68hc11_option_handler },
{ {"osc-clear", required_argument, NULL, OPTION_OSC_CLEAR },
'\0', "BIT", "Clear oscillator on input port BIT",
m68hc11_option_handler },
{ {"osc-info", no_argument, NULL, OPTION_OSC_INFO },
'\0', NULL, "Print information about current input oscillators",
m68hc11_option_handler },
{ {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
};
struct input_osc
{
signed64 on_time;
signed64 off_time;
signed64 repeat;
struct hw_event *event;
const char *name;
uint8 mask;
uint8 value;
uint16 addr;
};
#define NR_PORT_A_OSC (4)
#define NR_PORT_B_OSC (0)
#define NR_PORT_C_OSC (8)
#define NR_PORT_D_OSC (6)
#define NR_OSC (NR_PORT_A_OSC + NR_PORT_B_OSC + NR_PORT_C_OSC + NR_PORT_D_OSC)
struct m68hc11cpu {
int pending_reset;
int pending_nmi;
int pending_level;
struct hw_event *event;
unsigned_word attach_address;
int attach_size;
int attach_space;
int last_oscillator;
struct input_osc oscillators[NR_OSC];
};
enum {
RESET_PORT,
NMI_PORT,
IRQ_PORT,
CPU_RESET_PORT,
SET_PORT_A,
SET_PORT_C,
SET_PORT_D,
CPU_WRITE_PORT,
PORT_A,
PORT_B,
PORT_C,
PORT_D,
CAPTURE
};
static const struct hw_port_descriptor m68hc11cpu_ports[] = {
{ "reset", RESET_PORT, 0, input_port, },
{ "nmi", NMI_PORT, 0, input_port, },
{ "irq", IRQ_PORT, 0, input_port, },
{ "set-port-a", SET_PORT_A, 0, input_port, },
{ "set-port-c", SET_PORT_C, 0, input_port, },
{ "set-port-d", SET_PORT_D, 0, input_port, },
{ "cpu-write-port", CPU_WRITE_PORT, 0, input_port, },
{ "cpu-reset", CPU_RESET_PORT, 0, output_port, },
{ "port-a", PORT_A, 0, output_port, },
{ "port-b", PORT_B, 0, output_port, },
{ "port-c", PORT_C, 0, output_port, },
{ "port-d", PORT_D, 0, output_port, },
{ "capture", CAPTURE, 0, output_port, },
{ NULL, },
};
static hw_io_read_buffer_method m68hc11cpu_io_read_buffer;
static hw_io_write_buffer_method m68hc11cpu_io_write_buffer;
static hw_ioctl_method m68hc11_ioctl;
static hw_port_event_method m68hc11cpu_port_event;
static void make_oscillator (struct m68hc11cpu *controller,
const char *id, uint16 addr, uint8 mask);
static struct input_osc *find_oscillator (struct m68hc11cpu *controller,
const char *id);
static void reset_oscillators (struct hw *me);
static void
dv_m6811_attach_address_callback (struct hw *me,
int level,
int space,
address_word addr,
address_word nr_bytes,
struct hw *client)
{
HW_TRACE ((me, "attach - level=%d, space=%d, addr=0x%lx, sz=%ld, client=%s",
level, space, (unsigned long) addr, (unsigned long) nr_bytes,
hw_path (client)));
if (space != io_map)
{
sim_core_attach (hw_system (me),
NULL,
level,
access_read_write_exec,
space, addr,
nr_bytes,
0,
client,
NULL);
}
else
{
sim_core_attach (hw_system (me),
NULL,
level,
access_io,
space, addr,
nr_bytes,
0,
client,
NULL);
}
}
static void
dv_m6811_detach_address_callback (struct hw *me,
int level,
int space,
address_word addr,
address_word nr_bytes,
struct hw *client)
{
sim_core_detach (hw_system (me), NULL,
level, space, addr);
}
static void
m68hc11_delete (struct hw* me)
{
struct m68hc11cpu *controller;
controller = hw_data (me);
reset_oscillators (me);
hw_detach_address (me, M6811_IO_LEVEL,
controller->attach_space,
controller->attach_address,
controller->attach_size, me);
}
static void
attach_m68hc11_regs (struct hw *me,
struct m68hc11cpu *controller)
{
SIM_DESC sd;
sim_cpu *cpu;
reg_property_spec reg;
const char *cpu_mode;
if (hw_find_property (me, "reg") == NULL)
hw_abort (me, "Missing \"reg\" property");
if (!hw_find_reg_array_property (me, "reg", 0, ®))
hw_abort (me, "\"reg\" property must contain one addr/size entry");
hw_unit_address_to_attach_address (hw_parent (me),
®.address,
&controller->attach_space,
&controller->attach_address,
me);
hw_unit_size_to_attach_size (hw_parent (me),
®.size,
&controller->attach_size, me);
hw_attach_address (hw_parent (me), M6811_IO_LEVEL,
controller->attach_space,
controller->attach_address,
controller->attach_size,
me);
set_hw_delete (me, m68hc11_delete);
sd = hw_system (me);
cpu = STATE_CPU (sd, 0);
if (hw_find_property (me, "clock") != NULL)
{
cpu->cpu_frequency = hw_find_integer_property (me, "clock");
}
else
{
cpu->cpu_frequency = 8*1000*1000;
}
if (hw_find_property (me, "use_bank") != NULL)
hw_attach_address (hw_parent (me), 0,
exec_map,
0x08000,
0x04000,
me);
cpu_mode = "expanded";
if (hw_find_property (me, "mode") != NULL)
cpu_mode = hw_find_string_property (me, "mode");
if (strcmp (cpu_mode, "test") == 0)
cpu->cpu_mode = M6811_MDA | M6811_SMOD;
else if (strcmp (cpu_mode, "bootstrap") == 0)
cpu->cpu_mode = M6811_SMOD;
else if (strcmp (cpu_mode, "single") == 0)
cpu->cpu_mode = 0;
else
cpu->cpu_mode = M6811_MDA;
controller->last_oscillator = 0;
make_oscillator (controller, "A7", M6811_PORTA, 0x80);
make_oscillator (controller, "A2", M6811_PORTA, 0x04);
make_oscillator (controller, "A1", M6811_PORTA, 0x02);
make_oscillator (controller, "A0", M6811_PORTA, 0x01);
make_oscillator (controller, "C0", M6811_PORTC, 0x01);
make_oscillator (controller, "C1", M6811_PORTC, 0x02);
make_oscillator (controller, "C2", M6811_PORTC, 0x04);
make_oscillator (controller, "C3", M6811_PORTC, 0x08);
make_oscillator (controller, "C4", M6811_PORTC, 0x10);
make_oscillator (controller, "C5", M6811_PORTC, 0x20);
make_oscillator (controller, "C6", M6811_PORTC, 0x40);
make_oscillator (controller, "C7", M6811_PORTC, 0x80);
make_oscillator (controller, "D0", M6811_PORTD, 0x01);
make_oscillator (controller, "D1", M6811_PORTD, 0x02);
make_oscillator (controller, "D2", M6811_PORTD, 0x04);
make_oscillator (controller, "D3", M6811_PORTD, 0x08);
make_oscillator (controller, "D4", M6811_PORTD, 0x10);
make_oscillator (controller, "D5", M6811_PORTD, 0x20);
sim_add_option_table (sd, 0, m68hc11_options);
}
static void
m68hc11cpu_finish (struct hw *me)
{
struct m68hc11cpu *controller;
controller = HW_ZALLOC (me, struct m68hc11cpu);
set_hw_data (me, controller);
set_hw_io_read_buffer (me, m68hc11cpu_io_read_buffer);
set_hw_io_write_buffer (me, m68hc11cpu_io_write_buffer);
set_hw_ports (me, m68hc11cpu_ports);
set_hw_port_event (me, m68hc11cpu_port_event);
set_hw_attach_address (me, dv_m6811_attach_address_callback);
set_hw_detach_address (me, dv_m6811_detach_address_callback);
#ifdef set_hw_ioctl
set_hw_ioctl (me, m68hc11_ioctl);
#else
me->to_ioctl = m68hc11_ioctl;
#endif
controller->pending_level = 0;
controller->pending_reset = 0;
controller->pending_nmi = 0;
controller->event = NULL;
attach_m68hc11_regs (me, controller);
}
static void
deliver_m68hc11cpu_interrupt (struct hw *me, void *data)
{
}
static void
make_oscillator (struct m68hc11cpu *controller, const char *name,
uint16 addr, uint8 mask)
{
struct input_osc *osc;
if (controller->last_oscillator >= NR_OSC)
hw_abort (0, "Too many oscillators");
osc = &controller->oscillators[controller->last_oscillator];
osc->name = name;
osc->addr = addr;
osc->mask = mask;
controller->last_oscillator++;
}
static struct input_osc *
find_oscillator (struct m68hc11cpu *controller, const char *name)
{
int i;
for (i = 0; i < controller->last_oscillator; i++)
if (strcasecmp (controller->oscillators[i].name, name) == 0)
return &controller->oscillators[i];
return 0;
}
static void
oscillator_handler (struct hw *me, void *data)
{
struct input_osc *osc = (struct input_osc*) data;
SIM_DESC sd;
sim_cpu *cpu;
signed64 dt;
uint8 val;
sd = hw_system (me);
cpu = STATE_CPU (sd, 0);
osc->value ^= osc->mask;
val = cpu->ios[osc->addr] & ~osc->mask;
val |= osc->value;
m68hc11cpu_set_port (me, cpu, osc->addr, val);
if (osc->value)
dt = osc->on_time;
else
dt = osc->off_time;
if (dt && --osc->repeat >= 0)
{
sim_events *events = STATE_EVENTS (sd);
dt += events->nr_ticks_to_process;
osc->event = hw_event_queue_schedule (me, dt, oscillator_handler, osc);
}
else
osc->event = 0;
}
static void
reset_oscillators (struct hw *me)
{
struct m68hc11cpu *controller = hw_data (me);
int i;
for (i = 0; i < controller->last_oscillator; i++)
{
if (controller->oscillators[i].event)
{
hw_event_queue_deschedule (me, controller->oscillators[i].event);
controller->oscillators[i].event = 0;
}
}
}
static void
m68hc11cpu_port_event (struct hw *me,
int my_port,
struct hw *source,
int source_port,
int level)
{
struct m68hc11cpu *controller = hw_data (me);
SIM_DESC sd;
sim_cpu* cpu;
sd = hw_system (me);
cpu = STATE_CPU (sd, 0);
switch (my_port)
{
case RESET_PORT:
HW_TRACE ((me, "port-in reset"));
cpu_reset (cpu);
reset_oscillators (me);
hw_port_event (me, CPU_RESET_PORT, 1);
cpu_restart (cpu);
break;
case NMI_PORT:
controller->pending_nmi = 1;
HW_TRACE ((me, "port-in nmi"));
break;
case IRQ_PORT:
if(level == 0)
controller->pending_level = -1;
else
controller->pending_level = level;
HW_TRACE ((me, "port-in level=%d", level));
break;
case SET_PORT_A:
m68hc11cpu_set_port (me, cpu, M6811_PORTA, level);
break;
case SET_PORT_C:
m68hc11cpu_set_port (me, cpu, M6811_PORTC, level);
break;
case SET_PORT_D:
m68hc11cpu_set_port (me, cpu, M6811_PORTD, level);
break;
case CPU_WRITE_PORT:
break;
default:
hw_abort (me, "bad switch");
break;
}
if(controller->event != NULL)
hw_event_queue_deschedule(me, controller->event);
controller->event =
hw_event_queue_schedule (me, 0, deliver_m68hc11cpu_interrupt, NULL);
}
io_reg_desc config_desc[] = {
{ M6811_NOSEC, "NOSEC ", "Security Mode Disable" },
{ M6811_NOCOP, "NOCOP ", "COP System Disable" },
{ M6811_ROMON, "ROMON ", "Enable On-chip Rom" },
{ M6811_EEON, "EEON ", "Enable On-chip EEprom" },
{ 0, 0, 0 }
};
io_reg_desc hprio_desc[] = {
{ M6811_RBOOT, "RBOOT ", "Read Bootstrap ROM" },
{ M6811_SMOD, "SMOD ", "Special Mode" },
{ M6811_MDA, "MDA ", "Mode Select A" },
{ M6811_IRV, "IRV ", "Internal Read Visibility" },
{ 0, 0, 0 }
};
io_reg_desc option_desc[] = {
{ M6811_ADPU, "ADPU ", "A/D Powerup" },
{ M6811_CSEL, "CSEL ", "A/D/EE Charge pump clock source select" },
{ M6811_IRQE, "IRQE ", "IRQ Edge/Level sensitive" },
{ M6811_DLY, "DLY ", "Stop exit turn on delay" },
{ M6811_CME, "CME ", "Clock Monitor Enable" },
{ M6811_CR1, "CR1 ", "COP timer rate select (CR1)" },
{ M6811_CR0, "CR0 ", "COP timer rate select (CR0)" },
{ 0, 0, 0 }
};
static void
m68hc11_info (struct hw *me)
{
SIM_DESC sd;
uint16 base = 0;
sim_cpu *cpu;
struct m68hc11sio *controller;
uint8 val;
sd = hw_system (me);
cpu = STATE_CPU (sd, 0);
controller = hw_data (me);
base = cpu_get_io_base (cpu);
sim_io_printf (sd, "M68HC11:\n");
val = cpu->ios[M6811_HPRIO];
print_io_byte (sd, "HPRIO ", hprio_desc, val, base + M6811_HPRIO);
switch (cpu->cpu_mode)
{
case M6811_MDA | M6811_SMOD:
sim_io_printf (sd, "[test]\n");
break;
case M6811_SMOD:
sim_io_printf (sd, "[bootstrap]\n");
break;
case M6811_MDA:
sim_io_printf (sd, "[extended]\n");
break;
default:
sim_io_printf (sd, "[single]\n");
break;
}
val = cpu->ios[M6811_CONFIG];
print_io_byte (sd, "CONFIG", config_desc, val, base + M6811_CONFIG);
sim_io_printf (sd, "\n");
val = cpu->ios[M6811_OPTION];
print_io_byte (sd, "OPTION", option_desc, val, base + M6811_OPTION);
sim_io_printf (sd, "\n");
val = cpu->ios[M6811_INIT];
print_io_byte (sd, "INIT ", 0, val, base + M6811_INIT);
sim_io_printf (sd, "Ram = 0x%04x IO = 0x%04x\n",
(((uint16) (val & 0xF0)) << 8),
(((uint16) (val & 0x0F)) << 12));
cpu_info (sd, cpu);
interrupts_info (sd, &cpu->cpu_interrupts);
}
static int
m68hc11_ioctl (struct hw *me,
hw_ioctl_request request,
va_list ap)
{
m68hc11_info (me);
return 0;
}
int
m68hc11cpu_set_oscillator (SIM_DESC sd, const char *port,
double ton, double toff, signed64 repeat)
{
sim_cpu *cpu;
struct input_osc *osc;
double f;
cpu = STATE_CPU (sd, 0);
osc = find_oscillator (hw_data (cpu->hw_cpu), port);
if (osc == 0)
return -1;
f = (double) (cpu->cpu_frequency) * ton;
osc->on_time = (signed64) (f / 4.0);
if (osc->on_time < 1)
osc->on_time = 1;
f = (double) (cpu->cpu_frequency) * toff;
osc->off_time = (signed64) (f / 4.0);
if (osc->off_time < 1)
osc->off_time = 1;
osc->repeat = repeat;
if (osc->event)
hw_event_queue_deschedule (cpu->hw_cpu, osc->event);
osc->event = hw_event_queue_schedule (cpu->hw_cpu,
osc->value ? osc->on_time
: osc->off_time,
oscillator_handler, osc);
return 0;
}
int
m68hc11cpu_clear_oscillator (SIM_DESC sd, const char *port)
{
sim_cpu *cpu;
struct input_osc *osc;
cpu = STATE_CPU (sd, 0);
osc = find_oscillator (hw_data (cpu->hw_cpu), port);
if (osc == 0)
return -1;
if (osc->event)
hw_event_queue_deschedule (cpu->hw_cpu, osc->event);
osc->event = 0;
osc->repeat = 0;
return 0;
}
static int
get_frequency (const char *s, double *f)
{
char *p;
*f = strtod (s, &p);
if (s == p)
return -1;
if (*p)
{
if (strcasecmp (p, "khz") == 0)
*f = *f * 1000.0;
else if (strcasecmp (p, "mhz") == 0)
*f = *f * 1000000.0;
else if (strcasecmp (p, "hz") != 0)
return -1;
}
return 0;
}
static SIM_RC
m68hc11_option_handler (SIM_DESC sd, sim_cpu *cpu,
int opt, char *arg, int is_command)
{
struct m68hc11cpu *controller;
double f;
char *p;
int i;
int title_printed = 0;
if (cpu == 0)
cpu = STATE_CPU (sd, 0);
controller = hw_data (cpu->hw_cpu);
switch (opt)
{
case OPTION_OSC_SET:
p = strchr (arg, ',');
if (p)
*p++ = 0;
if (p == 0)
sim_io_eprintf (sd, "No frequency specified\n");
else if (get_frequency (p, &f) < 0 || f < 1.0e-8)
sim_io_eprintf (sd, "Invalid frequency: '%s'\n", p);
else if (m68hc11cpu_set_oscillator (sd, arg,
1.0 / (f * 2.0),
1.0 / (f * 2.0), LONG_MAX))
sim_io_eprintf (sd, "Invalid input port: '%s'\n", arg);
break;
case OPTION_OSC_CLEAR:
if (m68hc11cpu_clear_oscillator (sd, arg) != 0)
sim_io_eprintf (sd, "Invalid input port: '%s'\n", arg);
break;
case OPTION_OSC_INFO:
for (i = 0; i < controller->last_oscillator; i++)
{
signed64 t;
struct input_osc *osc;
osc = &controller->oscillators[i];
if (osc->event)
{
double f;
int cur_value;
int next_value;
char freq[32];
if (title_printed == 0)
{
title_printed = 1;
sim_io_printf (sd, " PORT Frequency Current"
" Next Transition time\n");
}
f = (double) (osc->on_time + osc->off_time);
f = (double) (cpu->cpu_frequency / 4) / f;
t = hw_event_remain_time (cpu->hw_cpu, osc->event);
if (f > 10000.0)
sprintf (freq, "%6.2f", f / 1000.0);
else
sprintf (freq, "%6.2f", f);
cur_value = osc->value ? 1 : 0;
next_value = osc->value ? 0 : 1;
if (f > 10000.0)
sim_io_printf (sd, " %4.4s %8.8s khz"
" %d %d %35.35s\n",
osc->name, freq,
cur_value, next_value,
cycle_to_string (cpu, t));
else
sim_io_printf (sd, " %4.4s %8.8s hz "
" %d %d %35.35s\n",
osc->name, freq,
cur_value, next_value,
cycle_to_string (cpu, t));
}
}
break;
}
return SIM_RC_OK;
}
static unsigned
m68hc11cpu_io_read_buffer (struct hw *me,
void *dest,
int space,
unsigned_word base,
unsigned nr_bytes)
{
SIM_DESC sd;
struct m68hc11cpu *controller = hw_data (me);
sim_cpu *cpu;
unsigned byte = 0;
int result;
HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
sd = hw_system (me);
cpu = STATE_CPU (sd, 0);
if (base >= 0x8000 && base < 0xc000)
{
address_word virt_addr = phys_to_virt (cpu, base);
if (virt_addr != base)
return sim_core_read_buffer (sd, cpu, space, dest,
virt_addr, nr_bytes);
}
base -= controller->attach_address;
result = sim_core_read_buffer (sd, cpu,
io_map, dest, base, nr_bytes);
if (result > 0)
return result;
while (nr_bytes)
{
if (base >= controller->attach_size)
break;
memcpy (dest, &cpu->ios[base], 1);
dest++;
base++;
byte++;
nr_bytes--;
}
return byte;
}
void
m68hc11cpu_set_port (struct hw *me, sim_cpu *cpu,
unsigned addr, uint8 val)
{
uint8 mask;
uint8 delta;
int check_interrupts = 0;
int i;
switch (addr)
{
case M6811_PORTA:
if (cpu->ios[M6811_PACTL] & M6811_DDRA7)
mask = 3;
else
mask = 0x83;
val = val & mask;
val |= cpu->ios[M6811_PORTA] & ~mask;
delta = val ^ cpu->ios[M6811_PORTA];
cpu->ios[M6811_PORTA] = val;
if (delta & 0x80)
{
if ((cpu->ios[M6811_PACTL] & M6811_PAEN)
&& !(cpu->ios[M6811_PACTL] & M6811_PAMOD))
{
int inc;
if (cpu->ios[M6811_PACTL] & M6811_PEDGE)
inc = (val & 0x80) ? 1 : 0;
else
inc = (val & 0x80) ? 0 : 1;
cpu->ios[M6811_PACNT] += inc;
if (inc && cpu->ios[M6811_PACNT] == 0)
{
cpu->ios[M6811_TFLG2] |= M6811_PAOVI;
check_interrupts = 1;
}
}
}
for (i = 0; i < 3; i++)
{
uint8 mask = (1 << i);
if (delta & mask)
{
uint8 edge;
int captured;
edge = cpu->ios[M6811_TCTL2];
edge = (edge >> (2 * i)) & 0x3;
switch (edge)
{
case 0:
captured = 0;
break;
case 1:
captured = (val & mask) != 0;
break;
case 2:
captured = (val & mask) == 0;
break;
default:
captured = 1;
break;
}
if (captured)
{
cpu->ios[M6811_TFLG1] |= (1 << i);
hw_port_event (me, CAPTURE, M6811_TIC1 + 3 - i);
check_interrupts = 1;
}
}
}
break;
case M6811_PORTC:
mask = cpu->ios[M6811_DDRC];
val = val & mask;
val |= cpu->ios[M6811_PORTC] & ~mask;
cpu->ios[M6811_PORTC] = val;
break;
case M6811_PORTD:
mask = cpu->ios[M6811_DDRD];
val = val & mask;
val |= cpu->ios[M6811_PORTD] & ~mask;
cpu->ios[M6811_PORTD] = val;
break;
default:
break;
}
if (check_interrupts)
interrupts_update_pending (&cpu->cpu_interrupts);
}
static void
m68hc11cpu_io_write (struct hw *me, sim_cpu *cpu,
unsigned_word addr, uint8 val)
{
switch (addr)
{
case M6811_PORTA:
hw_port_event (me, PORT_A, val);
break;
case M6811_PIOC:
break;
case M6811_PORTC:
hw_port_event (me, PORT_C, val);
break;
case M6811_PORTB:
hw_port_event (me, PORT_B, val);
break;
case M6811_PORTCL:
break;
case M6811_DDRC:
break;
case M6811_PORTD:
hw_port_event (me, PORT_D, val);
break;
case M6811_DDRD:
break;
case M6811_TMSK2:
break;
case M6811_INIT:
{
uint8 old_bank = cpu->ios[M6811_INIT];
cpu->ios[M6811_INIT] = val;
if ((old_bank & 0x0F) != (val & 0x0F))
{
struct m68hc11cpu *controller = hw_data (me);
hw_detach_address (hw_parent (me), M6811_IO_LEVEL,
controller->attach_space,
controller->attach_address,
controller->attach_size,
me);
controller->attach_address = (val & 0x0F0) << 12;
hw_attach_address (hw_parent (me), M6811_IO_LEVEL,
controller->attach_space,
controller->attach_address,
controller->attach_size,
me);
}
if ((old_bank & 0xF0) != (val & 0xF0))
{
;
}
return;
}
case M6811_CONFIG:
{
return;
}
case M6811_COPRST:
if (val == 0xAA && cpu->ios[addr] == 0x55)
{
val = 0;
}
break;
default:
break;
}
cpu->ios[addr] = val;
}
static unsigned
m68hc11cpu_io_write_buffer (struct hw *me,
const void *source,
int space,
unsigned_word base,
unsigned nr_bytes)
{
SIM_DESC sd;
struct m68hc11cpu *controller = hw_data (me);
unsigned byte;
sim_cpu *cpu;
int result;
HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
sd = hw_system (me);
cpu = STATE_CPU (sd, 0);
if (base >= 0x8000 && base < 0xc000)
{
address_word virt_addr = phys_to_virt (cpu, base);
if (virt_addr != base)
return sim_core_write_buffer (sd, cpu, space, source,
virt_addr, nr_bytes);
}
base -= controller->attach_address;
result = sim_core_write_buffer (sd, cpu,
io_map, source, base, nr_bytes);
if (result > 0)
return result;
byte = 0;
while (nr_bytes)
{
uint8 val;
if (base >= controller->attach_size)
break;
val = *((uint8*) source);
m68hc11cpu_io_write (me, cpu, base, val);
source++;
base++;
byte++;
nr_bytes--;
}
return byte;
}
const struct hw_descriptor dv_m68hc11_descriptor[] = {
{ "m68hc11", m68hc11cpu_finish },
{ "m68hc12", m68hc11cpu_finish },
{ NULL },
};