diff --git a/Makefile b/Makefile index f5b9d5f..9dbbbac 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,7 @@ mspdebug: main.o fet.o rf2500.o dis.o uif.o olimex.o ihex.o elf32.o stab.o \ reader.o vector.o output_util.o expr.o fet_error.o binfile.o \ fet_db.o usbutil.o titext.o srec.o device.o coff.o opdb.o output.o \ cmddb.o stdcmd.o prog.o flash_bsl.o list.o simio.o simio_tracer.o \ - simio_timer.o simio_wdt.o + simio_timer.o simio_wdt.o simio_hwmult.o $(CC) $(LDFLAGS) $(PORTS_LDFLAGS) -o $@ $^ -lusb $(READLINE_LIBS) .c.o: diff --git a/mspdebug.man b/mspdebug.man index 45f64f1..69d1410 100644 --- a/mspdebug.man +++ b/mspdebug.man @@ -435,6 +435,9 @@ device classes in detail. In the list below, each device class is listed, followed by its constructor arguments. +.IP "\fBhwmult\fR" +This peripheral simulates the hardware multiplier. It has no constructor or +configuration parameters, and does not provide any extended information. .IP "\fBtimer\fR [\fIsize\fR]" This peripheral simulators Timer_A modules, and can be used to simulate Timer_B modules, provided that the extended features aren't required. diff --git a/simio.c b/simio.c index f2fc750..392cf58 100644 --- a/simio.c +++ b/simio.c @@ -27,11 +27,13 @@ #include "simio_tracer.h" #include "simio_timer.h" #include "simio_wdt.h" +#include "simio_hwmult.h" static const struct simio_class *const class_db[] = { &simio_tracer, &simio_timer, - &simio_wdt + &simio_wdt, + &simio_hwmult }; /* Simulator data. We keep a list of devices on the bus, and the special @@ -157,7 +159,10 @@ static int cmd_devices(char **arg_text) for (n = device_list.next; n != &device_list; n = n->next) { struct simio_device *dev = (struct simio_device *)n; - int irq = dev->type->check_interrupt(dev); + int irq = -1; + + if (dev->type->check_interrupt) + irq = dev->type->check_interrupt(dev); printc(" %-10s (type %s", dev->name, dev->type->name); if (irq < 0) @@ -228,6 +233,12 @@ static int cmd_config(char **arg_text) return -1; } + if (!dev->type->config) { + printc_err("simio config: no configuration parameters are " + "defined for this device\n"); + return -1; + } + return dev->type->config(dev, param, arg_text); } @@ -247,6 +258,11 @@ static int cmd_info(char **arg_text) return -1; } + if (!dev->type->info) { + printc_err("simio config: no information available\n"); + return -1; + } + return dev->type->info(dev); } diff --git a/simio_hwmult.c b/simio_hwmult.c new file mode 100644 index 0000000..05cd8a9 --- /dev/null +++ b/simio_hwmult.c @@ -0,0 +1,163 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009, 2010 Daniel Beer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "simio_device.h" +#include "simio_hwmult.h" +#include "output.h" +#include "expr.h" + +/* Multiplier register addresses - taken from mspgcc */ +#define MPY 0x0130 /* Multiply Unsigned/Operand 1 */ +#define MPYS 0x0132 /* Multiply Signed/Operand 1 */ +#define MAC 0x0134 /* Multiply Unsigned and Accumulate/Operand 1 */ +#define MACS 0x0136 /* Multiply Signed and Accumulate/Operand 1 */ +#define OP2 0x0138 /* Operand 2 */ +#define RESLO 0x013A /* Result Low Word */ +#define RESHI 0x013C /* Result High Word */ +#define SUMEXT 0x013E /* Sum Extend */ + +struct hwmult { + struct simio_device base; + + int mode; + + uint16_t op1; + uint16_t op2; + uint32_t result; + uint16_t sumext; +}; + +struct simio_device *hwmult_create(char **arg_text) +{ + struct hwmult *h = malloc(sizeof(*h)); + + if (!h) { + pr_error("hwmult: can't allocate memory"); + return NULL; + } + + memset(h, 0, sizeof(*h)); + h->base.type = &simio_hwmult; + + return (struct simio_device *)h; +} + +static void hwmult_destroy(struct simio_device *dev) +{ + free(dev); +} + +static void do_multiply(struct hwmult *h) +{ + uint32_t im; + + /* Multiply */ + if (h->mode & 2) + im = (int16_t)h->op1 * (int16_t)h->op2; + else + im = h->op1 * h->op2; + + /* Accumulate or store */ + if (h->mode & 4) + h->result += im; + else + h->result = im; + + /* Set SUMEXT */ + if (h->mode & 2) + h->sumext = (h->result & 0x80000000) ? 0xffff : 0; + else if (h->mode == MPY) + h->sumext = (h->result < im) ? 1 : 0; + else + h->sumext = 0; +} + +static int hwmult_write(struct simio_device *dev, address_t addr, uint16_t data) +{ + struct hwmult *h = (struct hwmult *)dev; + + switch (addr) { + case RESHI: + h->result = (h->result & 0xffff) | ((uint32_t)data << 16); + return 0; + + case RESLO: + h->result = (h->result & 0xffff0000) | data; + return 0; + + case OP2: + h->op2 = data; + do_multiply(h); + return 0; + + case MPY: + case MPYS: + case MAC: + case MACS: + h->op1 = data; + h->mode = addr; + return 0; + } + + return 1; +} + +static int hwmult_read(struct simio_device *dev, address_t addr, uint16_t *data) +{ + struct hwmult *h = (struct hwmult *)dev; + + switch (addr) { + case MPY: + case MPYS: + case MAC: + case MACS: + *data = h->op1; + return 0; + + case OP2: + *data = h->op2; + return 0; + + case RESLO: + *data = h->result & 0xffff; + return 0; + + case RESHI: + *data = h->result >> 16; + return 0; + + case SUMEXT: + *data = h->sumext; + return 0; + } + + return 1; +} + +const struct simio_class simio_hwmult = { + .name = "hwmult", + .help = +"This module simulates the hardware multiplier.\n", + .create = hwmult_create, + .destroy = hwmult_destroy, + .write = hwmult_write, + .read = hwmult_read +}; diff --git a/simio_hwmult.h b/simio_hwmult.h new file mode 100644 index 0000000..f15b8f0 --- /dev/null +++ b/simio_hwmult.h @@ -0,0 +1,24 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009, 2010 Daniel Beer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SIMIO_HWMULT_H_ +#define SIMIO_HWMULT_H_ + +extern const struct simio_class simio_hwmult; + +#endif