aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-12-02 12:48:32 +0200
committerAvi Kivity <avi@redhat.com>2009-12-02 12:48:32 +0200
commit2e88035e52dee6b6efac71fbd1432ed1c117eab8 (patch)
tree943ab9665347abb29fdf6eb3a47205f4adbb3a2f
parentkvm_handle_internal_error should return 1 (diff)
parentUpdate SeaBIOS (diff)
downloadqemu-kvm-2e88035e52dee6b6efac71fbd1432ed1c117eab8.tar.gz
qemu-kvm-2e88035e52dee6b6efac71fbd1432ed1c117eab8.tar.bz2
qemu-kvm-2e88035e52dee6b6efac71fbd1432ed1c117eab8.zip
Merge commit 'b0293e54af32bcf08f4b4e5b4b472534de343972' into upstream-merge
* commit 'b0293e54af32bcf08f4b4e5b4b472534de343972': Update SeaBIOS ARM atomic ops rewrite ARM RealView I2C GPIO I2C rework DS1338 RTC BCD cleanup Makefile dependencies for device configs target-mips: fix physical address type in MMU functions [WIN32] Enable -k option on Windows too target-mips: make CP0_LLAddr register CPU dependent target-mips: rename CP0_LLAddr into lladdr Conflicts: pc-bios/bios.bin (pick upstream's) Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--Makefile21
-rw-r--r--Makefile.target2
-rw-r--r--config.h11
-rwxr-xr-xconfigure4
-rw-r--r--default-configs/arm-softmmu.mak1
-rw-r--r--hw/bitbang_i2c.c245
-rw-r--r--hw/bitbang_i2c.h14
-rw-r--r--hw/ds1338.c132
-rw-r--r--hw/m48t59.c50
-rw-r--r--hw/mc146818rtc.c36
-rw-r--r--hw/musicpal.c2
-rw-r--r--hw/omap1.c70
-rw-r--r--hw/realview.c86
-rw-r--r--hw/twl92230.c10
-rw-r--r--linux-user/main.c84
-rw-r--r--pc-bios/bios.binbin131072 -> 131072 bytes
-rw-r--r--qemu-common.h11
m---------roms/seabios0
-rw-r--r--target-arm/cpu.h9
-rw-r--r--target-arm/helper.c84
-rw-r--r--target-arm/helpers.h4
-rw-r--r--target-arm/translate.c250
-rw-r--r--target-mips/cpu.h12
-rw-r--r--target-mips/helper.c14
-rw-r--r--target-mips/helper.h1
-rw-r--r--target-mips/machine.c4
-rw-r--r--target-mips/op_helper.c21
-rw-r--r--target-mips/translate.c19
-rw-r--r--target-mips/translate_init.c32
-rw-r--r--vl.c2
30 files changed, 802 insertions, 429 deletions
diff --git a/Makefile b/Makefile
index 199c0a3f1..4a5b0daea 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
# Makefile for QEMU.
# This needs to be defined before rules.mak
-GENERATED_HEADERS = config-host.h config-all-devices.h
+GENERATED_HEADERS = config-host.h
ifneq ($(wildcard config-host.mak),)
# Put the all: rule here so that config-host.mak can contain dependencies.
@@ -41,6 +41,19 @@ SUBDIR_DEVICES_MAK=$(patsubst %, %/config-devices.mak, $(TARGET_DIRS))
config-all-devices.mak: $(SUBDIR_DEVICES_MAK)
$(call quiet-command,cat $(SUBDIR_DEVICES_MAK) | grep "=y$$" | sort -u > $@," GEN $@")
+%/config-devices.mak: default-configs/%.mak
+ $(call quiet-command,cat $< > $@.tmp, " GEN $@")
+ @if test -f $@ ; then \
+ echo "WARNING: $@ out of date." ;\
+ echo "Run \"make defconfing\" to regenerate." ; \
+ rm $@.tmp ; \
+ else \
+ mv $@.tmp $@ ; \
+ fi
+
+defconfig:
+ rm -f config-all-devices.mak $(SUBDIR_DEVICES_MAK)
+
-include config-all-devices.mak
build-all: $(DOCS) $(TOOLS) recurse-all
@@ -48,9 +61,6 @@ build-all: $(DOCS) $(TOOLS) recurse-all
config-host.h: config-host.h-timestamp
config-host.h-timestamp: config-host.mak
-config-all-devices.h: config-all-devices.h-timestamp
-config-all-devices.h-timestamp: config-all-devices.mak
-
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
ifeq ($(KVM_KMOD),yes)
@@ -135,6 +145,7 @@ obj-$(CONFIG_SSD0303) += ssd0303.o
obj-$(CONFIG_SSD0323) += ssd0323.o
obj-$(CONFIG_ADS7846) += ads7846.o
obj-$(CONFIG_MAX111X) += max111x.o
+obj-$(CONFIG_DS1338) += ds1338.o
obj-y += i2c.o smbus.o smbus_eeprom.o
obj-y += eeprom93xx.o
obj-y += scsi-disk.o cdrom.o
@@ -259,7 +270,7 @@ clean:
distclean: clean
rm -f config-host.mak config-host.h* config-host.ld $(DOCS) qemu-options.texi qemu-img-cmds.texi qemu-monitor.texi
- rm -f config-all-devices.mak config-all-devices.h*
+ rm -f config-all-devices.mak
rm -f roms/seabios/config.mak roms/vgabios/config.mak
rm -f qemu-{doc,tech}.{info,aux,cp,dvi,fn,info,ky,log,pg,toc,tp,vr}
for d in $(TARGET_DIRS) libhw32 libhw64 libuser; do \
diff --git a/Makefile.target b/Makefile.target
index 9527404b5..cba0f4cf0 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -1,7 +1,7 @@
# -*- Mode: makefile -*-
# This needs to be defined before rules.mak
-GENERATED_HEADERS = config-target.h config-devices.h
+GENERATED_HEADERS = config-target.h
include ../config-host.mak
include config-devices.mak
diff --git a/config.h b/config.h
index 07d79d4ba..e20f78696 100644
--- a/config.h
+++ b/config.h
@@ -1,13 +1,2 @@
-
#include "config-host.h"
#include "config-target.h"
-
-/* We want to include different config files for specific targets
- And for the common library. They need a different name because
- we don't want to rely in paths */
-
-#if defined(NEED_CPU_H)
-#include "config-devices.h"
-#else
-#include "config-all-devices.h"
-#endif
diff --git a/configure b/configure
index 376c4583e..beb9bd782 100755
--- a/configure
+++ b/configure
@@ -2375,10 +2375,6 @@ if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" -o "$targ
mkdir -p $target_dir/nwfpe
fi
-if test ! -f $target_dir/config-devices.mak ; then
- cp $source_path/default-configs/${target}.mak $target_dir/config-devices.mak
-fi
-
#
# don't use ln -sf as not all "ln -sf" over write the file/link
#
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 35d2cb9c9..c1b7496c0 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -22,3 +22,4 @@ CONFIG_SSI=y
CONFIG_SSI_SD=y
CONFIG_LAN9118=y
CONFIG_SMC91C111=y
+CONFIG_DS1338=y
diff --git a/hw/bitbang_i2c.c b/hw/bitbang_i2c.c
index 443ddb2b0..4ee99a18b 100644
--- a/hw/bitbang_i2c.c
+++ b/hw/bitbang_i2c.c
@@ -7,12 +7,20 @@
* This code is licenced under the GNU GPL v2.
*/
#include "hw.h"
-#include "i2c.h"
+#include "bitbang_i2c.h"
#include "sysbus.h"
+//#define DEBUG_BITBANG_I2C
+
+#ifdef DEBUG_BITBANG_I2C
+#define DPRINTF(fmt, ...) \
+do { printf("bitbang_i2c: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while(0)
+#endif
+
typedef enum bitbang_i2c_state {
STOPPED = 0,
- INITIALIZING,
SENDING_BIT7,
SENDING_BIT6,
SENDING_BIT5,
@@ -33,138 +41,171 @@ typedef enum bitbang_i2c_state {
SENDING_ACK
} bitbang_i2c_state;
-typedef struct bitbang_i2c_interface {
- SysBusDevice busdev;
+struct bitbang_i2c_interface {
i2c_bus *bus;
bitbang_i2c_state state;
int last_data;
int last_clock;
+ int device_out;
uint8_t buffer;
int current_addr;
- qemu_irq out;
-} bitbang_i2c_interface;
+};
static void bitbang_i2c_enter_stop(bitbang_i2c_interface *i2c)
{
+ DPRINTF("STOP\n");
if (i2c->current_addr >= 0)
i2c_end_transfer(i2c->bus);
i2c->current_addr = -1;
i2c->state = STOPPED;
}
-static void bitbang_i2c_gpio_set(void *opaque, int irq, int level)
+/* Set device data pin. */
+static int bitbang_i2c_ret(bitbang_i2c_interface *i2c, int level)
+{
+ i2c->device_out = level;
+ //DPRINTF("%d %d %d\n", i2c->last_clock, i2c->last_data, i2c->device_out);
+ return level & i2c->last_data;
+}
+
+/* Leave device data pin unodified. */
+static int bitbang_i2c_nop(bitbang_i2c_interface *i2c)
+{
+ return bitbang_i2c_ret(i2c, i2c->device_out);
+}
+
+/* Returns data line level. */
+int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level)
{
- bitbang_i2c_interface *i2c = opaque;
int data;
- int clock;
- int data_goes_up;
- int data_goes_down;
- int clock_goes_up;
- int clock_goes_down;
-
- /* get pins states */
- data = i2c->last_data;
- clock = i2c->last_clock;
-
- if (irq == 0)
- data = level;
- if (irq == 1)
- clock = level;
-
- /* compute pins changes */
- data_goes_up = data == 1 && i2c->last_data == 0;
- data_goes_down = data == 0 && i2c->last_data == 1;
- clock_goes_up = clock == 1 && i2c->last_clock == 0;
- clock_goes_down = clock == 0 && i2c->last_clock == 1;
-
- if (data_goes_up == 0 && data_goes_down == 0 &&
- clock_goes_up == 0 && clock_goes_down == 0)
- return;
-
- if (!i2c)
- return;
-
- if ((RECEIVING_BIT7 > i2c->state && i2c->state > RECEIVING_BIT0)
- || i2c->state == WAITING_FOR_ACK)
- qemu_set_irq(i2c->out, 0);
- switch (i2c->state) {
- case STOPPED:
- if (data_goes_down && clock == 1)
- i2c->state = INITIALIZING;
- break;
+ if (level != 0 && level != 1) {
+ abort();
+ }
- case INITIALIZING:
- if (clock_goes_down && data == 0)
+ if (line == BITBANG_I2C_SDA) {
+ if (level == i2c->last_data) {
+ return bitbang_i2c_nop(i2c);
+ }
+ i2c->last_data = level;
+ if (i2c->last_clock == 0) {
+ return bitbang_i2c_nop(i2c);
+ }
+ if (level == 0) {
+ DPRINTF("START\n");
+ /* START condition. */
i2c->state = SENDING_BIT7;
- else
+ i2c->current_addr = -1;
+ } else {
+ /* STOP condition. */
bitbang_i2c_enter_stop(i2c);
- break;
+ }
+ return bitbang_i2c_ret(i2c, 1);
+ }
+
+ data = i2c->last_data;
+ if (i2c->last_clock == level) {
+ return bitbang_i2c_nop(i2c);
+ }
+ i2c->last_clock = level;
+ if (level == 0) {
+ /* State is set/read at the start of the clock pulse.
+ release the data line at the end. */
+ return bitbang_i2c_ret(i2c, 1);
+ }
+ switch (i2c->state) {
+ case STOPPED:
+ return bitbang_i2c_ret(i2c, 1);
case SENDING_BIT7 ... SENDING_BIT0:
- if (clock_goes_down) {
- i2c->buffer = (i2c->buffer << 1) | data;
- /* will end up in WAITING_FOR_ACK */
- i2c->state++;
- } else if (data_goes_up && clock == 1)
- bitbang_i2c_enter_stop(i2c);
- break;
+ i2c->buffer = (i2c->buffer << 1) | data;
+ /* will end up in WAITING_FOR_ACK */
+ i2c->state++;
+ return bitbang_i2c_ret(i2c, 1);
case WAITING_FOR_ACK:
- if (clock_goes_down) {
- if (i2c->current_addr < 0) {
- i2c->current_addr = i2c->buffer;
- i2c_start_transfer(i2c->bus, (i2c->current_addr & 0xfe) / 2,
- i2c->buffer & 1);
- } else
- i2c_send(i2c->bus, i2c->buffer);
- if (i2c->current_addr & 1) {
- i2c->state = RECEIVING_BIT7;
- i2c->buffer = i2c_recv(i2c->bus);
- } else
- i2c->state = SENDING_BIT7;
- } else if (data_goes_up && clock == 1)
- bitbang_i2c_enter_stop(i2c);
- break;
-
- case RECEIVING_BIT7 ... RECEIVING_BIT0:
- qemu_set_irq(i2c->out, i2c->buffer >> 7);
- if (clock_goes_down) {
- /* will end up in SENDING_ACK */
- i2c->state++;
- i2c->buffer <<= 1;
- } else if (data_goes_up && clock == 1)
- bitbang_i2c_enter_stop(i2c);
- break;
+ if (i2c->current_addr < 0) {
+ i2c->current_addr = i2c->buffer;
+ DPRINTF("Address 0x%02x\n", i2c->current_addr);
+ i2c_start_transfer(i2c->bus, i2c->current_addr >> 1,
+ i2c->current_addr & 1);
+ } else {
+ DPRINTF("Sent 0x%02x\n", i2c->buffer);
+ i2c_send(i2c->bus, i2c->buffer);
+ }
+ if (i2c->current_addr & 1) {
+ i2c->state = RECEIVING_BIT7;
+ } else {
+ i2c->state = SENDING_BIT7;
+ }
+ return bitbang_i2c_ret(i2c, 0);
+
+ case RECEIVING_BIT7:
+ i2c->buffer = i2c_recv(i2c->bus);
+ DPRINTF("RX byte 0x%02x\n", i2c->buffer);
+ /* Fall through... */
+ case RECEIVING_BIT6 ... RECEIVING_BIT0:
+ data = i2c->buffer >> 7;
+ /* will end up in SENDING_ACK */
+ i2c->state++;
+ i2c->buffer <<= 1;
+ return bitbang_i2c_ret(i2c, data);
case SENDING_ACK:
- if (clock_goes_down) {
- i2c->state = RECEIVING_BIT7;
- if (data == 0)
- i2c->buffer = i2c_recv(i2c->bus);
- else
- i2c_nack(i2c->bus);
- } else if (data_goes_up && clock == 1)
- bitbang_i2c_enter_stop(i2c);
- break;
+ i2c->state = RECEIVING_BIT7;
+ if (data != 0) {
+ DPRINTF("NACKED\n");
+ i2c_nack(i2c->bus);
+ } else {
+ DPRINTF("ACKED\n");
+ }
+ return bitbang_i2c_ret(i2c, 1);
}
+ abort();
+}
+
+bitbang_i2c_interface *bitbang_i2c_init(i2c_bus *bus)
+{
+ bitbang_i2c_interface *s;
+
+ s = qemu_mallocz(sizeof(bitbang_i2c_interface));
+
+ s->bus = bus;
+ s->last_data = 1;
+ s->last_clock = 1;
+ s->device_out = 1;
+
+ return s;
+}
- i2c->last_data = data;
- i2c->last_clock = clock;
+/* GPIO interface. */
+typedef struct {
+ SysBusDevice busdev;
+ bitbang_i2c_interface *bitbang;
+ int last_level;
+ qemu_irq out;
+} GPIOI2CState;
+
+static void bitbang_i2c_gpio_set(void *opaque, int irq, int level)
+{
+ GPIOI2CState *s = opaque;
+
+ level = bitbang_i2c_set(s->bitbang, irq, level);
+ if (level != s->last_level) {
+ s->last_level = level;
+ qemu_set_irq(s->out, level);
+ }
}
-static int bitbang_i2c_init(SysBusDevice *dev)
+static int gpio_i2c_init(SysBusDevice *dev)
{
- bitbang_i2c_interface *s = FROM_SYSBUS(bitbang_i2c_interface, dev);
+ GPIOI2CState *s = FROM_SYSBUS(GPIOI2CState, dev);
i2c_bus *bus;
sysbus_init_mmio(dev, 0x0, 0);
bus = i2c_init_bus(&dev->qdev, "i2c");
- s->bus = bus;
-
- s->last_data = 1;
- s->last_clock = 1;
+ s->bitbang = bitbang_i2c_init(bus);
qdev_init_gpio_in(&dev->qdev, bitbang_i2c_gpio_set, 2);
qdev_init_gpio_out(&dev->qdev, &s->out, 1);
@@ -172,10 +213,16 @@ static int bitbang_i2c_init(SysBusDevice *dev)
return 0;
}
+static SysBusDeviceInfo gpio_i2c_info = {
+ .init = gpio_i2c_init,
+ .qdev.name = "gpio_i2c",
+ .qdev.desc = "Virtual GPIO to I2C bridge",
+ .qdev.size = sizeof(GPIOI2CState),
+};
+
static void bitbang_i2c_register(void)
{
- sysbus_register_dev("bitbang_i2c",
- sizeof(bitbang_i2c_interface), bitbang_i2c_init);
+ sysbus_register_withprop(&gpio_i2c_info);
}
device_init(bitbang_i2c_register)
diff --git a/hw/bitbang_i2c.h b/hw/bitbang_i2c.h
new file mode 100644
index 000000000..519d2dc22
--- /dev/null
+++ b/hw/bitbang_i2c.h
@@ -0,0 +1,14 @@
+#ifndef BITBANG_I2C_H
+#define BITBANG_I2C_H
+
+#include "i2c.h"
+
+typedef struct bitbang_i2c_interface bitbang_i2c_interface;
+
+#define BITBANG_I2C_SDA 0
+#define BITBANG_I2C_SCL 1
+
+bitbang_i2c_interface *bitbang_i2c_init(i2c_bus *bus);
+int bitbang_i2c_set(bitbang_i2c_interface *i2c, int line, int level);
+
+#endif
diff --git a/hw/ds1338.c b/hw/ds1338.c
new file mode 100644
index 000000000..6f5ae5e6c
--- /dev/null
+++ b/hw/ds1338.c
@@ -0,0 +1,132 @@
+/*
+ * MAXIM DS1338 I2C RTC+NVRAM
+ *
+ * Copyright (c) 2009 CodeSourcery.
+ * Written by Paul Brook
+ *
+ * This code is licenced under the GNU GPL v2.
+ */
+
+#include "i2c.h"
+
+typedef struct {
+ i2c_slave i2c;
+ time_t offset;
+ struct tm now;
+ uint8_t nvram[56];
+ int ptr;
+ int addr_byte;
+} DS1338State;
+
+static void ds1338_event(i2c_slave *i2c, enum i2c_event event)
+{
+ DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c);
+
+ switch (event) {
+ case I2C_START_RECV:
+ qemu_get_timedate(&s->now, s->offset);
+ s->nvram[0] = to_bcd(s->now.tm_sec);
+ s->nvram[1] = to_bcd(s->now.tm_min);
+ if (s->nvram[2] & 0x40) {
+ s->nvram[2] = (to_bcd((s->now.tm_hour % 12)) + 1) | 0x40;
+ if (s->now.tm_hour >= 12) {
+ s->nvram[2] |= 0x20;
+ }
+ } else {
+ s->nvram[2] = to_bcd(s->now.tm_hour);
+ }
+ s->nvram[3] = to_bcd(s->now.tm_wday) + 1;
+ s->nvram[4] = to_bcd(s->now.tm_mday);
+ s->nvram[5] = to_bcd(s->now.tm_mon) + 1;
+ s->nvram[6] = to_bcd(s->now.tm_year - 100);
+ break;
+ case I2C_START_SEND:
+ s->addr_byte = 1;
+ break;
+ default:
+ break;
+ }
+}
+
+static int ds1338_recv(i2c_slave *i2c)
+{
+ DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c);
+ uint8_t res;
+
+ res = s->nvram[s->ptr];
+ s->ptr = (s->ptr + 1) & 0xff;
+ return res;
+}
+
+static int ds1338_send(i2c_slave *i2c, uint8_t data)
+{
+ DS1338State *s = FROM_I2C_SLAVE(DS1338State, i2c);
+ if (s->addr_byte) {
+ s->ptr = data;
+ s->addr_byte = 0;
+ return 0;
+ }
+ s->nvram[s->ptr - 8] = data;
+ if (data < 8) {
+ qemu_get_timedate(&s->now, s->offset);
+ switch(data) {
+ case 0:
+ /* TODO: Implement CH (stop) bit. */
+ s->now.tm_sec = from_bcd(data & 0x7f);
+ break;
+ case 1:
+ s->now.tm_min = from_bcd(data & 0x7f);
+ break;
+ case 2:
+ if (data & 0x40) {
+ if (data & 0x20) {
+ data = from_bcd(data & 0x4f) + 11;
+ } else {
+ data = from_bcd(data & 0x1f) - 1;
+ }
+ } else {
+ data = from_bcd(data);
+ }
+ s->now.tm_hour = data;
+ break;
+ case 3:
+ s->now.tm_wday = from_bcd(data & 7) - 1;
+ break;
+ case 4:
+ s->now.tm_mday = from_bcd(data & 0x3f);
+ break;
+ case 5:
+ s->now.tm_mon = from_bcd(data & 0x1f) - 1;
+ case 6:
+ s->now.tm_year = from_bcd(data) + 100;
+ break;
+ case 7:
+ /* Control register. Currently ignored. */
+ break;
+ }
+ s->offset = qemu_timedate_diff(&s->now);
+ }
+ s->ptr = (s->ptr + 1) & 0xff;
+ return 0;
+}
+
+static int ds1338_init(i2c_slave *i2c)
+{
+ return 0;
+}
+
+static I2CSlaveInfo ds1338_info = {
+ .qdev.name = "ds1338",
+ .qdev.size = sizeof(DS1338State),
+ .init = ds1338_init,
+ .event = ds1338_event,
+ .recv = ds1338_recv,
+ .send = ds1338_send,
+};
+
+static void ds1338_register_devices(void)
+{
+ i2c_register_slave(&ds1338_info);
+}
+
+device_init(ds1338_register_devices)
diff --git a/hw/m48t59.c b/hw/m48t59.c
index bb58419d2..ce38f8b6e 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -80,16 +80,6 @@ typedef struct M48t59SysBusState {
} M48t59SysBusState;
/* Fake timer functions */
-/* Generic helpers for BCD */
-static inline uint8_t toBCD (uint8_t value)
-{
- return (((value / 10) % 10) << 4) | (value % 10);
-}
-
-static inline uint8_t fromBCD (uint8_t BCD)
-{
- return ((BCD >> 4) * 10) + (BCD & 0x0F);
-}
/* Alarm management */
static void alarm_cb (void *opaque)
@@ -219,7 +209,7 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
break;
case 0x1FF2:
/* alarm seconds */
- tmp = fromBCD(val & 0x7F);
+ tmp = from_bcd(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
NVRAM->alarm.tm_sec = tmp;
NVRAM->buffer[0x1FF2] = val;
@@ -228,7 +218,7 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
break;
case 0x1FF3:
/* alarm minutes */
- tmp = fromBCD(val & 0x7F);
+ tmp = from_bcd(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
NVRAM->alarm.tm_min = tmp;
NVRAM->buffer[0x1FF3] = val;
@@ -237,7 +227,7 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
break;
case 0x1FF4:
/* alarm hours */
- tmp = fromBCD(val & 0x3F);
+ tmp = from_bcd(val & 0x3F);
if (tmp >= 0 && tmp <= 23) {
NVRAM->alarm.tm_hour = tmp;
NVRAM->buffer[0x1FF4] = val;
@@ -246,7 +236,7 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
break;
case 0x1FF5:
/* alarm date */
- tmp = fromBCD(val & 0x1F);
+ tmp = from_bcd(val & 0x1F);
if (tmp != 0) {
NVRAM->alarm.tm_mday = tmp;
NVRAM->buffer[0x1FF5] = val;
@@ -270,7 +260,7 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
case 0x1FF9:
case 0x07F9:
/* seconds (BCD) */
- tmp = fromBCD(val & 0x7F);
+ tmp = from_bcd(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm);
tm.tm_sec = tmp;
@@ -289,7 +279,7 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
case 0x1FFA:
case 0x07FA:
/* minutes (BCD) */
- tmp = fromBCD(val & 0x7F);
+ tmp = from_bcd(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm);
tm.tm_min = tmp;
@@ -299,7 +289,7 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
case 0x1FFB:
case 0x07FB:
/* hours (BCD) */
- tmp = fromBCD(val & 0x3F);
+ tmp = from_bcd(val & 0x3F);
if (tmp >= 0 && tmp <= 23) {
get_time(NVRAM, &tm);
tm.tm_hour = tmp;
@@ -309,7 +299,7 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
case 0x1FFC:
case 0x07FC:
/* day of the week / century */
- tmp = fromBCD(val & 0x07);
+ tmp = from_bcd(val & 0x07);
get_time(NVRAM, &tm);
tm.tm_wday = tmp;
set_time(NVRAM, &tm);
@@ -318,7 +308,7 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
case 0x1FFD:
case 0x07FD:
/* date */
- tmp = fromBCD(val & 0x1F);
+ tmp = from_bcd(val & 0x1F);
if (tmp != 0) {
get_time(NVRAM, &tm);
tm.tm_mday = tmp;
@@ -328,7 +318,7 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
case 0x1FFE:
case 0x07FE:
/* month */
- tmp = fromBCD(val & 0x1F);
+ tmp = from_bcd(val & 0x1F);
if (tmp >= 1 && tmp <= 12) {
get_time(NVRAM, &tm);
tm.tm_mon = tmp - 1;
@@ -338,13 +328,13 @@ void m48t59_write (void *opaque, uint32_t addr, uint32_t val)
case 0x1FFF:
case 0x07FF:
/* year */
- tmp = fromBCD(val);
+ tmp = from_bcd(val);
if (tmp >= 0 && tmp <= 99) {
get_time(NVRAM, &tm);
if (NVRAM->type == 8)
- tm.tm_year = fromBCD(val) + 68; // Base year is 1968
+ tm.tm_year = from_bcd(val) + 68; // Base year is 1968
else
- tm.tm_year = fromBCD(val);
+ tm.tm_year = from_bcd(val);
set_time(NVRAM, &tm);
}
break;
@@ -410,19 +400,19 @@ uint32_t m48t59_read (void *opaque, uint32_t addr)
case 0x07F9:
/* seconds (BCD) */
get_time(NVRAM, &tm);
- retval = (NVRAM->buffer[addr] & 0x80) | toBCD(tm.tm_sec);
+ retval = (NVRAM->buffer[addr] & 0x80) | to_bcd(tm.tm_sec);
break;
case 0x1FFA:
case 0x07FA:
/* minutes (BCD) */
get_time(NVRAM, &tm);
- retval = toBCD(tm.tm_min);
+ retval = to_bcd(tm.tm_min);
break;
case 0x1FFB:
case 0x07FB:
/* hours (BCD) */
get_time(NVRAM, &tm);
- retval = toBCD(tm.tm_hour);
+ retval = to_bcd(tm.tm_hour);
break;
case 0x1FFC:
case 0x07FC:
@@ -434,22 +424,22 @@ uint32_t m48t59_read (void *opaque, uint32_t addr)
case 0x07FD:
/* date */
get_time(NVRAM, &tm);
- retval = toBCD(tm.tm_mday);
+ retval = to_bcd(tm.tm_mday);
break;
case 0x1FFE:
case 0x07FE:
/* month */
get_time(NVRAM, &tm);
- retval = toBCD(tm.tm_mon + 1);
+ retval = to_bcd(tm.tm_mon + 1);
break;
case 0x1FFF:
case 0x07FF:
/* year */
get_time(NVRAM, &tm);
if (NVRAM->type == 8)
- retval = toBCD(tm.tm_year - 68); // Base year is 1968
+ retval = to_bcd(tm.tm_year - 68); // Base year is 1968
else
- retval = toBCD(tm.tm_year);
+ retval = to_bcd(tm.tm_year);
break;
default:
/* Check lock registers state */
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 61ddf0b35..b8c7b0c1b 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -259,7 +259,7 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
}
}
-static inline int to_bcd(RTCState *s, int a)
+static inline int rtc_to_bcd(RTCState *s, int a)
{
if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
return a;
@@ -268,7 +268,7 @@ static inline int to_bcd(RTCState *s, int a)
}
}
-static inline int from_bcd(RTCState *s, int a)
+static inline int rtc_from_bcd(RTCState *s, int a)
{
if (s->cmos_data[RTC_REG_B] & REG_B_DM) {
return a;
@@ -281,17 +281,17 @@ static void rtc_set_time(RTCState *s)
{
struct tm *tm = &s->current_tm;
- tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
- tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
- tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
+ tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
+ tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
+ tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
(s->cmos_data[RTC_HOURS] & 0x80)) {
tm->tm_hour += 12;
}
- tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1;
- tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
- tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
- tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900;
+ tm->tm_wday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]) - 1;
+ tm->tm_mday = rtc_from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
+ tm->tm_mon = rtc_from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
+ tm->tm_year = rtc_from_bcd(s, s->cmos_data[RTC_YEAR]) + s->base_year - 1900;
}
static void rtc_copy_date(RTCState *s)
@@ -299,24 +299,24 @@ static void rtc_copy_date(RTCState *s)
const struct tm *tm = &s->current_tm;
int year;
- s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
- s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
+ s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec);
+ s->cmos_data[RTC_MINUTES] = rtc_to_bcd(s, tm->tm_min);
if (s->cmos_data[RTC_REG_B] & 0x02) {
/* 24 hour format */
- s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
+ s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour);
} else {
/* 12 hour format */
- s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
+ s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour % 12);
if (tm->tm_hour >= 12)
s->cmos_data[RTC_HOURS] |= 0x80;
}
- s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday + 1);
- s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
- s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
+ s->cmos_data[RTC_DAY_OF_WEEK] = rtc_to_bcd(s, tm->tm_wday + 1);
+ s->cmos_data[RTC_DAY_OF_MONTH] = rtc_to_bcd(s, tm->tm_mday);
+ s->cmos_data[RTC_MONTH] = rtc_to_bcd(s, tm->tm_mon + 1);
year = (tm->tm_year - s->base_year) % 100;
if (year < 0)
year += 100;
- s->cmos_data[RTC_YEAR] = to_bcd(s, year);
+ s->cmos_data[RTC_YEAR] = rtc_to_bcd(s, year);
}
/* month is between 0 and 11. */
@@ -497,7 +497,7 @@ static void rtc_set_date_from_host(RTCState *s)
qemu_get_timedate(&tm, 0);
rtc_set_date(s, &tm);
- val = to_bcd(s, (tm.tm_year / 100) + 19);
+ val = rtc_to_bcd(s, (tm.tm_year / 100) + 19);
rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
}
diff --git a/hw/musicpal.c b/hw/musicpal.c
index 0d21f1778..264669f61 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1565,7 +1565,7 @@ static void musicpal_init(ram_addr_t ram_size,
musicpal_misc_init();
dev = sysbus_create_simple("musicpal_gpio", MP_GPIO_BASE, pic[MP_GPIO_IRQ]);
- i2c_dev = sysbus_create_simple("bitbang_i2c", 0, NULL);
+ i2c_dev = sysbus_create_simple("gpio_i2c", 0, NULL);
i2c = (i2c_bus *)qdev_get_child_bus(i2c_dev, "i2c");
lcd_dev = sysbus_create_simple("musicpal_lcd", MP_LCD_BASE, NULL);
diff --git a/hw/omap1.c b/hw/omap1.c
index e9676ecc8..b5d78cd91 100644
--- a/hw/omap1.c
+++ b/hw/omap1.c
@@ -3358,16 +3358,6 @@ static void omap_rtc_alarm_update(struct omap_rtc_s *s)
printf("%s: conversion failed\n", __FUNCTION__);
}
-static inline uint8_t omap_rtc_bcd(int num)
-{
- return ((num / 10) << 4) | (num % 10);
-}
-
-static inline int omap_rtc_bin(uint8_t num)
-{
- return (num & 15) + 10 * (num >> 4);
-}
-
static uint32_t omap_rtc_read(void *opaque, target_phys_addr_t addr)
{
struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
@@ -3376,51 +3366,51 @@ static uint32_t omap_rtc_read(void *opaque, target_phys_addr_t addr)
switch (offset) {
case 0x00: /* SECONDS_REG */
- return omap_rtc_bcd(s->current_tm.tm_sec);
+ return to_bcd(s->current_tm.tm_sec);
case 0x04: /* MINUTES_REG */
- return omap_rtc_bcd(s->current_tm.tm_min);
+ return to_bcd(s->current_tm.tm_min);
case 0x08: /* HOURS_REG */
if (s->pm_am)
return ((s->current_tm.tm_hour > 11) << 7) |
- omap_rtc_bcd(((s->current_tm.tm_hour - 1) % 12) + 1);
+ to_bcd(((s->current_tm.tm_hour - 1) % 12) + 1);
else
- return omap_rtc_bcd(s->current_tm.tm_hour);
+ return to_bcd(s->current_tm.tm_hour);
case 0x0c: /* DAYS_REG */
- return omap_rtc_bcd(s->current_tm.tm_mday);
+ return to_bcd(s->current_tm.tm_mday);
case 0x10: /* MONTHS_REG */
- return omap_rtc_bcd(s->current_tm.tm_mon + 1);
+ return to_bcd(s->current_tm.tm_mon + 1);
case 0x14: /* YEARS_REG */
- return omap_rtc_bcd(s->current_tm.tm_year % 100);
+ return to_bcd(s->current_tm.tm_year % 100);
case 0x18: /* WEEK_REG */
return s->current_tm.tm_wday;
case 0x20: /* ALARM_SECONDS_REG */
- return omap_rtc_bcd(s->alarm_tm.tm_sec);
+ return to_bcd(s->alarm_tm.tm_sec);
case 0x24: /* ALARM_MINUTES_REG */
- return omap_rtc_bcd(s->alarm_tm.tm_min);
+ return to_bcd(s->alarm_tm.tm_min);
case 0x28: /* ALARM_HOURS_REG */
if (s->pm_am)
return ((s->alarm_tm.tm_hour > 11) << 7) |
- omap_rtc_bcd(((s->alarm_tm.tm_hour - 1) % 12) + 1);
+ to_bcd(((s->alarm_tm.tm_hour - 1) % 12) + 1);
else
- return omap_rtc_bcd(s->alarm_tm.tm_hour);
+ return to_bcd(s->alarm_tm.tm_hour);
case 0x2c: /* ALARM_DAYS_REG */
- return omap_rtc_bcd(s->alarm_tm.tm_mday);
+ return to_bcd(s->alarm_tm.tm_mday);
case 0x30: /* ALARM_MONTHS_REG */
- return omap_rtc_bcd(s->alarm_tm.tm_mon + 1);
+ return to_bcd(s->alarm_tm.tm_mon + 1);
case 0x34: /* ALARM_YEARS_REG */
- return omap_rtc_bcd(s->alarm_tm.tm_year % 100);
+ return to_bcd(s->alarm_tm.tm_year % 100);
case 0x40: /* RTC_CTRL_REG */
return (s->pm_am << 3) | (s->auto_comp << 2) |
@@ -3459,7 +3449,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
printf("RTC SEC_REG <-- %02x\n", value);
#endif
s->ti -= s->current_tm.tm_sec;
- s->ti += omap_rtc_bin(value);
+ s->ti += from_bcd(value);
return;
case 0x04: /* MINUTES_REG */
@@ -3467,7 +3457,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
printf("RTC MIN_REG <-- %02x\n", value);
#endif
s->ti -= s->current_tm.tm_min * 60;
- s->ti += omap_rtc_bin(value) * 60;
+ s->ti += from_bcd(value) * 60;
return;
case 0x08: /* HOURS_REG */
@@ -3476,10 +3466,10 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
#endif
s->ti -= s->current_tm.tm_hour * 3600;
if (s->pm_am) {
- s->ti += (omap_rtc_bin(value & 0x3f) & 12) * 3600;
+ s->ti += (from_bcd(value & 0x3f) & 12) * 3600;
s->ti += ((value >> 7) & 1) * 43200;
} else
- s->ti += omap_rtc_bin(value & 0x3f) * 3600;
+ s->ti += from_bcd(value & 0x3f) * 3600;
return;
case 0x0c: /* DAYS_REG */
@@ -3487,7 +3477,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
printf("RTC DAY_REG <-- %02x\n", value);
#endif
s->ti -= s->current_tm.tm_mday * 86400;
- s->ti += omap_rtc_bin(value) * 86400;
+ s->ti += from_bcd(value) * 86400;
return;
case 0x10: /* MONTHS_REG */
@@ -3495,7 +3485,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
printf("RTC MTH_REG <-- %02x\n", value);
#endif
memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
- new_tm.tm_mon = omap_rtc_bin(value);
+ new_tm.tm_mon = from_bcd(value);
ti[0] = mktimegm(&s->current_tm);
ti[1] = mktimegm(&new_tm);
@@ -3505,7 +3495,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
} else {
/* A less accurate version */
s->ti -= s->current_tm.tm_mon * 2592000;
- s->ti += omap_rtc_bin(value) * 2592000;
+ s->ti += from_bcd(value) * 2592000;
}
return;
@@ -3514,7 +3504,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
printf("RTC YRS_REG <-- %02x\n", value);
#endif
memcpy(&new_tm, &s->current_tm, sizeof(new_tm));
- new_tm.tm_year += omap_rtc_bin(value) - (new_tm.tm_year % 100);
+ new_tm.tm_year += from_bcd(value) - (new_tm.tm_year % 100);
ti[0] = mktimegm(&s->current_tm);
ti[1] = mktimegm(&new_tm);
@@ -3524,7 +3514,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
} else {
/* A less accurate version */
s->ti -= (s->current_tm.tm_year % 100) * 31536000;
- s->ti += omap_rtc_bin(value) * 31536000;
+ s->ti += from_bcd(value) * 31536000;
}
return;
@@ -3535,7 +3525,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
#ifdef ALMDEBUG
printf("ALM SEC_REG <-- %02x\n", value);
#endif
- s->alarm_tm.tm_sec = omap_rtc_bin(value);
+ s->alarm_tm.tm_sec = from_bcd(value);
omap_rtc_alarm_update(s);
return;
@@ -3543,7 +3533,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
#ifdef ALMDEBUG
printf("ALM MIN_REG <-- %02x\n", value);
#endif
- s->alarm_tm.tm_min = omap_rtc_bin(value);
+ s->alarm_tm.tm_min = from_bcd(value);
omap_rtc_alarm_update(s);
return;
@@ -3553,10 +3543,10 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
#endif
if (s->pm_am)
s->alarm_tm.tm_hour =
- ((omap_rtc_bin(value & 0x3f)) % 12) +
+ ((from_bcd(value & 0x3f)) % 12) +
((value >> 7) & 1) * 12;
else
- s->alarm_tm.tm_hour = omap_rtc_bin(value);
+ s->alarm_tm.tm_hour = from_bcd(value);
omap_rtc_alarm_update(s);
return;
@@ -3564,7 +3554,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
#ifdef ALMDEBUG
printf("ALM DAY_REG <-- %02x\n", value);
#endif
- s->alarm_tm.tm_mday = omap_rtc_bin(value);
+ s->alarm_tm.tm_mday = from_bcd(value);
omap_rtc_alarm_update(s);
return;
@@ -3572,7 +3562,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
#ifdef ALMDEBUG
printf("ALM MON_REG <-- %02x\n", value);
#endif
- s->alarm_tm.tm_mon = omap_rtc_bin(value);
+ s->alarm_tm.tm_mon = from_bcd(value);
omap_rtc_alarm_update(s);
return;
@@ -3580,7 +3570,7 @@ static void omap_rtc_write(void *opaque, target_phys_addr_t addr,
#ifdef ALMDEBUG
printf("ALM YRS_REG <-- %02x\n", value);
#endif
- s->alarm_tm.tm_year = omap_rtc_bin(value);
+ s->alarm_tm.tm_year = from_bcd(value);
omap_rtc_alarm_update(s);
return;
diff --git a/hw/realview.c b/hw/realview.c
index 7aa127ee2..f0b834734 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -15,8 +15,86 @@
#include "net.h"
#include "sysemu.h"
#include "boards.h"
+#include "bitbang_i2c.h"
+#include "sysbus.h"
#define SMP_BOOT_ADDR 0xe0000000
+
+typedef struct {
+ SysBusDevice busdev;
+ bitbang_i2c_interface *bitbang;
+ int out;
+ int in;
+} RealViewI2CState;
+
+static uint32_t realview_i2c_read(void *opaque, target_phys_addr_t offset)
+{
+ RealViewI2CState *s = (RealViewI2CState *)opaque;
+
+ if (offset == 0) {
+ return (s->out & 1) | (s->in << 1);
+ } else {
+ hw_error("realview_i2c_read: Bad offset 0x%x\n", (int)offset);
+ return -1;
+ }
+}
+
+static void realview_i2c_write(void *opaque, target_phys_addr_t offset,
+ uint32_t value)
+{
+ RealViewI2CState *s = (RealViewI2CState *)opaque;
+
+ switch (offset) {
+ case 0:
+ s->out |= value & 3;
+ break;
+ case 4:
+ s->out &= ~value;
+ break;
+ default:
+ hw_error("realview_i2c_write: Bad offset 0x%x\n", (int)offset);
+ }
+ bitbang_i2c_set(s->bitbang, BITBANG_I2C_SCL, (s->out & 1) != 0);
+ s->in = bitbang_i2c_set(s->bitbang, BITBANG_I2C_SDA, (s->out & 2) != 0);
+}
+
+static CPUReadMemoryFunc * const realview_i2c_readfn[] = {
+ realview_i2c_read,
+ realview_i2c_read,
+ realview_i2c_read
+};
+
+static CPUWriteMemoryFunc * const realview_i2c_writefn[] = {
+ realview_i2c_write,
+ realview_i2c_write,
+ realview_i2c_write
+};
+
+static int realview_i2c_init(SysBusDevice *dev)
+{
+ RealViewI2CState *s = FROM_SYSBUS(RealViewI2CState, dev);
+ i2c_bus *bus;
+ int iomemtype;
+
+ bus = i2c_init_bus(&dev->qdev, "i2c");
+ s->bitbang = bitbang_i2c_init(bus);
+ iomemtype = cpu_register_io_memory(realview_i2c_readfn,
+ realview_i2c_writefn, s);
+ sysbus_init_mmio(dev, 0x1000, iomemtype);
+ return 0;
+}
+
+static SysBusDeviceInfo realview_i2c_info = {
+ .init = realview_i2c_init,
+ .qdev.name = "realview_i2c",
+ .qdev.size = sizeof(RealViewI2CState),
+};
+
+static void realview_register_devices(void)
+{
+ sysbus_register_withprop(&realview_i2c_info);
+}
+
/* Board init. */
static struct arm_boot_info realview_binfo = {
@@ -63,6 +141,7 @@ static void realview_init(ram_addr_t ram_size,
qemu_irq pic[64];
PCIBus *pci_bus;
NICInfo *nd;
+ i2c_bus *i2c;
int n;
int done_nic = 0;
qemu_irq cpu_irq[4];
@@ -202,10 +281,14 @@ static void realview_init(ram_addr_t ram_size,
}
}
+ dev = sysbus_create_simple("realview_i2c", 0x10002000, NULL);
+ i2c = (i2c_bus *)qdev_get_child_bus(dev, "i2c");
+ i2c_create_slave(i2c, "ds1338", 0x68);
+
/* Memory map for RealView Emulation Baseboard: */
/* 0x10000000 System registers. */
/* 0x10001000 System controller. */
- /* 0x10002000 Two-Wire Serial Bus. */
+ /* 0x10002000 Two-Wire Serial Bus. */
/* 0x10003000 Reserved. */
/* 0x10004000 AACI. */
/* 0x10005000 MCI. */
@@ -362,3 +445,4 @@ static void realview_machine_init(void)
}
machine_init(realview_machine_init);
+device_init(realview_register_devices)
diff --git a/hw/twl92230.c b/hw/twl92230.c
index a6c60ba2b..93232da2d 100644
--- a/hw/twl92230.c
+++ b/hw/twl92230.c
@@ -183,16 +183,6 @@ static void menelaus_reset(i2c_slave *i2c)
menelaus_update(s);
}
-static inline uint8_t to_bcd(int val)
-{
- return ((val / 10) << 4) | (val % 10);
-}
-
-static inline int from_bcd(uint8_t val)
-{
- return ((val >> 4) * 10) + (val & 0x0f);
-}
-
static void menelaus_gpio_set(void *opaque, int line, int level)
{
MenelausState *s = (MenelausState *) opaque;
diff --git a/linux-user/main.c b/linux-user/main.c
index bcc36f256..2b8bab1b6 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -524,6 +524,81 @@ do_kernel_trap(CPUARMState *env)
return 0;
}
+static int do_strex(CPUARMState *env)
+{
+ uint32_t val;
+ int size;
+ int rc = 1;
+ int segv = 0;
+ uint32_t addr;
+ start_exclusive();
+ addr = env->exclusive_addr;
+ if (addr != env->exclusive_test) {
+ goto fail;
+ }
+ size = env->exclusive_info & 0xf;
+ switch (size) {
+ case 0:
+ segv = get_user_u8(val, addr);
+ break;
+ case 1:
+ segv = get_user_u16(val, addr);
+ break;
+ case 2:
+ case 3:
+ segv = get_user_u32(val, addr);
+ break;
+ }
+ if (segv) {
+ env->cp15.c6_data = addr;
+ goto done;
+ }
+ if (val != env->exclusive_val) {
+ goto fail;
+ }
+ if (size == 3) {
+ segv = get_user_u32(val, addr + 4);
+ if (segv) {
+ env->cp15.c6_data = addr + 4;
+ goto done;
+ }
+ if (val != env->exclusive_high) {
+ goto fail;
+ }
+ }
+ val = env->regs[(env->exclusive_info >> 8) & 0xf];
+ switch (size) {
+ case 0:
+ segv = put_user_u8(val, addr);
+ break;
+ case 1:
+ segv = put_user_u16(val, addr);
+ break;
+ case 2:
+ case 3:
+ segv = put_user_u32(val, addr);
+ break;
+ }
+ if (segv) {
+ env->cp15.c6_data = addr;
+ goto done;
+ }
+ if (size == 3) {
+ val = env->regs[(env->exclusive_info >> 12) & 0xf];
+ segv = put_user_u32(val, addr);
+ if (segv) {
+ env->cp15.c6_data = addr + 4;
+ goto done;
+ }
+ }
+ rc = 0;
+fail:
+ env->regs[(env->exclusive_info >> 4) & 0xf] = rc;
+done:
+ end_exclusive();
+ return segv;
+}
+
void cpu_loop(CPUARMState *env)
{
int trapnr;
@@ -717,6 +792,11 @@ void cpu_loop(CPUARMState *env)
if (do_kernel_trap(env))
goto error;
break;
+ case EXCP_STREX:
+ if (do_strex(env)) {
+ addr = env->cp15.c6_data;
+ goto do_segv;
+ }
default:
error:
fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
@@ -1849,7 +1929,7 @@ static int do_store_exclusive(CPUMIPSState *env)
int reg;
int d;
- addr = env->CP0_LLAddr;
+ addr = env->lladdr;
page_addr = addr & TARGET_PAGE_MASK;
start_exclusive();
mmap_lock();
@@ -1879,7 +1959,7 @@ static int do_store_exclusive(CPUMIPSState *env)
}
}
}
- env->CP0_LLAddr = -1;
+ env->lladdr = -1;
if (!segv) {
env->active_tc.PC += 4;
}
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index bba1e5c84..294958019 100644
--- a/pc-bios/bios.bin
+++ b/pc-bios/bios.bin
Binary files differ
diff --git a/qemu-common.h b/qemu-common.h
index f08a1b670..05377b173 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -256,6 +256,17 @@ void qemu_iovec_from_buffer(QEMUIOVector *qiov, const void *buf, size_t count);
struct Monitor;
typedef struct Monitor Monitor;
+/* Convert a byte between binary and BCD. */
+static inline uint8_t to_bcd(uint8_t val)
+{
+ return ((val / 10) << 4) | (val % 10);
+}
+
+static inline uint8_t from_bcd(uint8_t val)
+{
+ return ((val >> 4) * 10) + (val & 0x0f);
+}
+
#include "module.h"
#endif /* dyngen-exec.h hack */
diff --git a/roms/seabios b/roms/seabios
-Subproject b021a57b6af2e1f055391b1d813f7e3a94f41b5
+Subproject 42bc3940d93911e382f5e72289f043d1faa9083
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index a83ce48c4..4a1c53f24 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -40,6 +40,7 @@
#define EXCP_BKPT 7
#define EXCP_EXCEPTION_EXIT 8 /* Return from v7M exception. */
#define EXCP_KERNEL_TRAP 9 /* Jumped to kernel code page. */
+#define EXCP_STREX 10
#define ARMV7M_EXCP_RESET 1
#define ARMV7M_EXCP_NMI 2
@@ -180,10 +181,12 @@ typedef struct CPUARMState {
float_status fp_status;
} vfp;
+ uint32_t exclusive_addr;
+ uint32_t exclusive_val;
+ uint32_t exclusive_high;
#if defined(CONFIG_USER_ONLY)
- struct mmon_state *mmon_entry;
-#else
- uint32_t mmon_addr;
+ uint32_t exclusive_test;
+ uint32_t exclusive_info;
#endif
/* iwMMXt coprocessor state. */
diff --git a/target-arm/helper.c b/target-arm/helper.c
index ffc14f032..b3aec9944 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -470,16 +470,6 @@ void do_interrupt (CPUState *env)
env->exception_index = -1;
}
-/* Structure used to record exclusive memory locations. */
-typedef struct mmon_state {
- struct mmon_state *next;
- CPUARMState *cpu_env;
- uint32_t addr;
-} mmon_state;
-
-/* Chain of current locks. */
-static mmon_state* mmon_head = NULL;
-
int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
int mmu_idx, int is_softmmu)
{
@@ -493,62 +483,6 @@ int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
return 1;
}
-static void allocate_mmon_state(CPUState *env)
-{
- env->mmon_entry = malloc(sizeof (mmon_state));
- memset (env->mmon_entry, 0, sizeof (mmon_state));
- env->mmon_entry->cpu_env = env;
- mmon_head = env->mmon_entry;
-}
-
-/* Flush any monitor locks for the specified address. */
-static void flush_mmon(uint32_t addr)
-{
- mmon_state *mon;
-
- for (mon = mmon_head; mon; mon = mon->next)
- {
- if (mon->addr != addr)
- continue;
-
- mon->addr = 0;
- break;
- }
-}
-
-/* Mark an address for exclusive access. */
-void HELPER(mark_exclusive)(CPUState *env, uint32_t addr)
-{
- if (!env->mmon_entry)
- allocate_mmon_state(env);
- /* Clear any previous locks. */
- flush_mmon(addr);
- env->mmon_entry->addr = addr;
-}
-
-/* Test if an exclusive address is still exclusive. Returns zero
- if the address is still exclusive. */
-uint32_t HELPER(test_exclusive)(CPUState *env, uint32_t addr)
-{
- int res;
-
- if (!env->mmon_entry)
- return 1;
- if (env->mmon_entry->addr == addr)
- res = 0;
- else
- res = 1;
- flush_mmon(addr);
- return res;
-}
-
-void HELPER(clrex)(CPUState *env)
-{
- if (!(env->mmon_entry && env->mmon_entry->addr))
- return;
- flush_mmon(env->mmon_entry->addr);
-}
-
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
{
return addr;
@@ -1273,24 +1207,6 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
return phys_addr;
}
-/* Not really implemented. Need to figure out a sane way of doing this.
- Maybe add generic watchpoint support and use that. */
-
-void HELPER(mark_exclusive)(CPUState *env, uint32_t addr)
-{
- env->mmon_addr = addr;
-}
-
-uint32_t HELPER(test_exclusive)(CPUState *env, uint32_t addr)
-{
- return (env->mmon_addr != addr);
-}
-
-void HELPER(clrex)(CPUState *env)
-{
- env->mmon_addr = -1;
-}
-
void HELPER(set_cp)(CPUState *env, uint32_t insn, uint32_t val)
{
int cp_num = (insn >> 8) & 0xf;
diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index dc25f185d..0d1bc47d0 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -68,10 +68,6 @@ DEF_HELPER_2(get_cp, i32, env, i32)
DEF_HELPER_2(get_r13_banked, i32, env, i32)
DEF_HELPER_3(set_r13_banked, void, env, i32, i32)
-DEF_HELPER_2(mark_exclusive, void, env, i32)
-DEF_HELPER_2(test_exclusive, i32, env, i32)
-DEF_HELPER_1(clrex, void, env)
-
DEF_HELPER_1(get_user_reg, i32, i32)
DEF_HELPER_2(set_user_reg, void, i32, i32)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index a002f7e02..45bf77256 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -76,6 +76,13 @@ static TCGv_ptr cpu_env;
/* We reuse the same 64-bit temporaries for efficiency. */
static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
static TCGv_i32 cpu_R[16];
+static TCGv_i32 cpu_exclusive_addr;
+static TCGv_i32 cpu_exclusive_val;
+static TCGv_i32 cpu_exclusive_high;
+#ifdef CONFIG_USER_ONLY
+static TCGv_i32 cpu_exclusive_test;
+static TCGv_i32 cpu_exclusive_info;
+#endif
/* FIXME: These should be removed. */
static TCGv cpu_F0s, cpu_F1s;
@@ -99,6 +106,18 @@ void arm_translate_init(void)
offsetof(CPUState, regs[i]),
regnames[i]);
}
+ cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUState, exclusive_addr), "exclusive_addr");
+ cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUState, exclusive_val), "exclusive_val");
+ cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUState, exclusive_high), "exclusive_high");
+#ifdef CONFIG_USER_ONLY
+ cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUState, exclusive_test), "exclusive_test");
+ cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUState, exclusive_info), "exclusive_info");
+#endif
#define GEN_HELPER 2
#include "helpers.h"
@@ -5819,6 +5838,132 @@ static void gen_logicq_cc(TCGv_i64 val)
dead_tmp(tmp);
}
+/* Load/Store exclusive instructions are implemented by remembering
+ the value/address loaded, and seeing if these are the same
+ when the store is performed. This should be is sufficient to implement
+ the architecturally mandated semantics, and avoids having to monitor
+ regular stores.
+
+ In system emulation mode only one CPU will be running at once, so
+ this sequence is effectively atomic. In user emulation mode we
+ throw an exception and handle the atomic operation elsewhere. */
+static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
+ TCGv addr, int size)
+{
+ TCGv tmp;
+
+ switch (size) {
+ case 0:
+ tmp = gen_ld8u(addr, IS_USER(s));
+ break;
+ case 1:
+ tmp = gen_ld16u(addr, IS_USER(s));
+ break;
+ case 2:
+ case 3:
+ tmp = gen_ld32(addr, IS_USER(s));
+ break;
+ default:
+ abort();
+ }
+ tcg_gen_mov_i32(cpu_exclusive_val, tmp);
+ store_reg(s, rt, tmp);
+ if (size == 3) {
+ tcg_gen_addi_i32(addr, addr, 4);
+ tmp = gen_ld32(addr, IS_USER(s));
+ tcg_gen_mov_i32(cpu_exclusive_high, tmp);
+ store_reg(s, rt2, tmp);
+ }
+ tcg_gen_mov_i32(cpu_exclusive_addr, addr);
+}
+
+static void gen_clrex(DisasContext *s)
+{
+ tcg_gen_movi_i32(cpu_exclusive_addr, -1);
+}
+
+#ifdef CONFIG_USER_ONLY
+static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
+ TCGv addr, int size)
+{
+ tcg_gen_mov_i32(cpu_exclusive_test, addr);
+ tcg_gen_movi_i32(cpu_exclusive_info,
+ size | (rd << 4) | (rt << 8) | (rt2 << 12));
+ gen_set_condexec(s);
+ gen_set_pc_im(s->pc - 4);
+ gen_exception(EXCP_STREX);
+ s->is_jmp = DISAS_JUMP;
+}
+#else
+static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
+ TCGv addr, int size)
+{
+ TCGv tmp;
+ int done_label;
+ int fail_label;
+
+ /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
+ [addr] = {Rt};
+ {Rd} = 0;
+ } else {
+ {Rd} = 1;
+ } */
+ fail_label = gen_new_label();
+ done_label = gen_new_label();
+ tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
+ switch (size) {
+ case 0:
+ tmp = gen_ld8u(addr, IS_USER(s));
+ break;
+ case 1:
+ tmp = gen_ld16u(addr, IS_USER(s));
+ break;
+ case 2:
+ case 3:
+ tmp = gen_ld32(addr, IS_USER(s));
+ break;
+ default:
+ abort();
+ }
+ tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
+ dead_tmp(tmp);
+ if (size == 3) {
+ TCGv tmp2 = new_tmp();
+ tcg_gen_addi_i32(tmp2, addr, 4);
+ tmp = gen_ld32(addr, IS_USER(s));
+ dead_tmp(tmp2);
+ tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
+ dead_tmp(tmp);
+ }
+ tmp = load_reg(s, rt);
+ switch (size) {
+ case 0:
+ gen_st8(tmp, addr, IS_USER(s));
+ break;
+ case 1:
+ gen_st16(tmp, addr, IS_USER(s));
+ break;
+ case 2:
+ case 3:
+ gen_st32(tmp, addr, IS_USER(s));
+ break;
+ default:
+ abort();
+ }
+ if (size == 3) {
+ tcg_gen_addi_i32(addr, addr, 4);
+ tmp = load_reg(s, rt2);
+ gen_st32(tmp, addr, IS_USER(s));
+ }
+ tcg_gen_movi_i32(cpu_R[rd], 0);
+ tcg_gen_br(done_label);
+ gen_set_label(fail_label);
+ tcg_gen_movi_i32(cpu_R[rd], 1);
+ gen_set_label(done_label);
+ tcg_gen_movi_i32(cpu_exclusive_addr, -1);
+}
+#endif
+
static void disas_arm_insn(CPUState * env, DisasContext *s)
{
unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
@@ -5869,7 +6014,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
switch ((insn >> 4) & 0xf) {
case 1: /* clrex */
ARCH(6K);
- gen_helper_clrex(cpu_env);
+ gen_clrex(s);
return;
case 4: /* dsb */
case 5: /* dmb */
@@ -6454,57 +6599,40 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
addr = tcg_temp_local_new_i32();
load_reg_var(s, addr, rn);
if (insn & (1 << 20)) {
- gen_helper_mark_exclusive(cpu_env, addr);
switch (op1) {
case 0: /* ldrex */
- tmp = gen_ld32(addr, IS_USER(s));
+ gen_load_exclusive(s, rd, 15, addr, 2);
break;
case 1: /* ldrexd */
- tmp = gen_ld32(addr, IS_USER(s));
- store_reg(s, rd, tmp);
- tcg_gen_addi_i32(addr, addr, 4);
- tmp = gen_ld32(addr, IS_USER(s));
- rd++;
+ gen_load_exclusive(s, rd, rd + 1, addr, 3);
break;
case 2: /* ldrexb */
- tmp = gen_ld8u(addr, IS_USER(s));
+ gen_load_exclusive(s, rd, 15, addr, 0);
break;
case 3: /* ldrexh */
- tmp = gen_ld16u(addr, IS_USER(s));
+ gen_load_exclusive(s, rd, 15, addr, 1);
break;
default:
abort();
}
- store_reg(s, rd, tmp);
} else {
- int label = gen_new_label();
rm = insn & 0xf;
- tmp2 = tcg_temp_local_new_i32();
- gen_helper_test_exclusive(tmp2, cpu_env, addr);
- tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
- tmp = load_reg(s,rm);
switch (op1) {
case 0: /* strex */
- gen_st32(tmp, addr, IS_USER(s));
+ gen_store_exclusive(s, rd, rm, 15, addr, 2);
break;
case 1: /* strexd */
- gen_st32(tmp, addr, IS_USER(s));
- tcg_gen_addi_i32(addr, addr, 4);
- tmp = load_reg(s, rm + 1);
- gen_st32(tmp, addr, IS_USER(s));
+ gen_store_exclusive(s, rd, rm, rm + 1, addr, 2);
break;
case 2: /* strexb */
- gen_st8(tmp, addr, IS_USER(s));
+ gen_store_exclusive(s, rd, rm, 15, addr, 0);
break;
case 3: /* strexh */
- gen_st16(tmp, addr, IS_USER(s));
+ gen_store_exclusive(s, rd, rm, 15, addr, 1);
break;
default:
abort();
}
- gen_set_label(label);
- tcg_gen_mov_i32(cpu_R[rd], tmp2);
- tcg_temp_free(tmp2);
}
tcg_temp_free(addr);
} else {
@@ -7259,20 +7387,11 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
/* Load/store exclusive word. */
addr = tcg_temp_local_new();
load_reg_var(s, addr, rn);
+ tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
if (insn & (1 << 20)) {
- gen_helper_mark_exclusive(cpu_env, addr);
- tmp = gen_ld32(addr, IS_USER(s));
- store_reg(s, rd, tmp);
+ gen_load_exclusive(s, rs, 15, addr, 2);
} else {
- int label = gen_new_label();
- tmp2 = tcg_temp_local_new();
- gen_helper_test_exclusive(tmp2, cpu_env, addr);
- tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
- tmp = load_reg(s, rs);
- gen_st32(tmp, addr, IS_USER(s));
- gen_set_label(label);
- tcg_gen_mov_i32(cpu_R[rd], tmp2);
- tcg_temp_free(tmp2);
+ gen_store_exclusive(s, rd, rs, 15, addr, 2);
}
tcg_temp_free(addr);
} else if ((insn & (1 << 6)) == 0) {
@@ -7300,56 +7419,17 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
store_reg(s, 15, tmp);
} else {
/* Load/store exclusive byte/halfword/doubleword. */
- /* ??? These are not really atomic. However we know
- we never have multiple CPUs running in parallel,
- so it is good enough. */
+ ARCH(7);
op = (insn >> 4) & 0x3;
+ if (op == 2) {
+ goto illegal_op;
+ }
addr = tcg_temp_local_new();
load_reg_var(s, addr, rn);
if (insn & (1 << 20)) {
- gen_helper_mark_exclusive(cpu_env, addr);
- switch (op) {
- case 0:
- tmp = gen_ld8u(addr, IS_USER(s));
- break;
- case 1:
- tmp = gen_ld16u(addr, IS_USER(s));
- break;
- case 3:
- tmp = gen_ld32(addr, IS_USER(s));
- tcg_gen_addi_i32(addr, addr, 4);
- tmp2 = gen_ld32(addr, IS_USER(s));
- store_reg(s, rd, tmp2);
- break;
- default:
- goto illegal_op;
- }
- store_reg(s, rs, tmp);
+ gen_load_exclusive(s, rs, rd, addr, op);
} else {
- int label = gen_new_label();
- tmp2 = tcg_temp_local_new();
- gen_helper_test_exclusive(tmp2, cpu_env, addr);
- tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
- tmp = load_reg(s, rs);
- switch (op) {
- case 0:
- gen_st8(tmp, addr, IS_USER(s));
- break;
- case 1:
- gen_st16(tmp, addr, IS_USER(s));
- break;
- case 3:
- gen_st32(tmp, addr, IS_USER(s));
- tcg_gen_addi_i32(addr, addr, 4);
- tmp = load_reg(s, rd);
- gen_st32(tmp, addr, IS_USER(s));
- break;
- default:
- goto illegal_op;
- }
- gen_set_label(label);
- tcg_gen_mov_i32(cpu_R[rm], tmp2);
- tcg_temp_free(tmp2);
+ gen_store_exclusive(s, rm, rs, rd, addr, op);
}
tcg_temp_free(addr);
}
@@ -7845,16 +7925,16 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
}
break;
case 3: /* Special control operations. */
+ ARCH(7);
op = (insn >> 4) & 0xf;
switch (op) {
case 2: /* clrex */
- gen_helper_clrex(cpu_env);
+ gen_clrex(s);
break;
case 4: /* dsb */
case 5: /* dmb */
case 6: /* isb */
/* These execute as NOPs. */
- ARCH(7);
break;
default:
goto illegal_op;
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index cefa5ae58..82f9a3816 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -40,7 +40,7 @@ typedef struct CPUMIPSTLBContext CPUMIPSTLBContext;
struct CPUMIPSTLBContext {
uint32_t nb_tlb;
uint32_t tlb_in_use;
- int (*map_address) (struct CPUMIPSState *env, target_ulong *physical, int *prot, target_ulong address, int rw, int access_type);
+ int (*map_address) (struct CPUMIPSState *env, target_phys_addr_t *physical, int *prot, target_ulong address, int rw, int access_type);
void (*helper_tlbwi) (void);
void (*helper_tlbwr) (void);
void (*helper_tlbp) (void);
@@ -372,10 +372,12 @@ struct CPUMIPSState {
int32_t CP0_Config6;
int32_t CP0_Config7;
/* XXX: Maybe make LLAddr per-TC? */
- target_ulong CP0_LLAddr;
+ target_ulong lladdr;
target_ulong llval;
target_ulong llnewval;
target_ulong llreg;
+ target_ulong CP0_LLAddr_rw_bitmask;
+ int CP0_LLAddr_shift;
target_ulong CP0_WatchLo[8];
int32_t CP0_WatchHi[8];
target_ulong CP0_XContext;
@@ -464,11 +466,11 @@ struct CPUMIPSState {
struct QEMUTimer *timer; /* Internal timer */
};
-int no_mmu_map_address (CPUMIPSState *env, target_ulong *physical, int *prot,
+int no_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
target_ulong address, int rw, int access_type);
-int fixed_mmu_map_address (CPUMIPSState *env, target_ulong *physical, int *prot,
+int fixed_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
target_ulong address, int rw, int access_type);
-int r4k_map_address (CPUMIPSState *env, target_ulong *physical, int *prot,
+int r4k_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
target_ulong address, int rw, int access_type);
void r4k_helper_tlbwi (void);
void r4k_helper_tlbwr (void);
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 7f659ae6b..4a372777c 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -35,7 +35,7 @@ enum {
};
/* no MMU emulation */
-int no_mmu_map_address (CPUState *env, target_ulong *physical, int *prot,
+int no_mmu_map_address (CPUState *env, target_phys_addr_t *physical, int *prot,
target_ulong address, int rw, int access_type)
{
*physical = address;
@@ -44,7 +44,7 @@ int no_mmu_map_address (CPUState *env, target_ulong *physical, int *prot,
}
/* fixed mapping MMU emulation */
-int fixed_mmu_map_address (CPUState *env, target_ulong *physical, int *prot,
+int fixed_mmu_map_address (CPUState *env, target_phys_addr_t *physical, int *prot,
target_ulong address, int rw, int access_type)
{
if (address <= (int32_t)0x7FFFFFFFUL) {
@@ -62,7 +62,7 @@ int fixed_mmu_map_address (CPUState *env, target_ulong *physical, int *prot,
}
/* MIPS32/MIPS64 R4000-style MMU emulation */
-int r4k_map_address (CPUState *env, target_ulong *physical, int *prot,
+int r4k_map_address (CPUState *env, target_phys_addr_t *physical, int *prot,
target_ulong address, int rw, int access_type)
{
uint8_t ASID = env->CP0_EntryHi & 0xFF;
@@ -99,7 +99,7 @@ int r4k_map_address (CPUState *env, target_ulong *physical, int *prot,
}
#if !defined(CONFIG_USER_ONLY)
-static int get_physical_address (CPUState *env, target_ulong *physical,
+static int get_physical_address (CPUState *env, target_phys_addr_t *physical,
int *prot, target_ulong address,
int rw, int access_type)
{
@@ -206,7 +206,7 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
#if defined(CONFIG_USER_ONLY)
return addr;
#else
- target_ulong phys_addr;
+ target_phys_addr_t phys_addr;
int prot;
if (get_physical_address(env, &phys_addr, &prot, addr, 0, ACCESS_INT) != 0)
@@ -219,7 +219,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
int mmu_idx, int is_softmmu)
{
#if !defined(CONFIG_USER_ONLY)
- target_ulong physical;
+ target_phys_addr_t physical;
int prot;
#endif
int exception = 0, error_code = 0;
@@ -243,7 +243,7 @@ int cpu_mips_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
#else
ret = get_physical_address(env, &physical, &prot,
address, rw, access_type);
- qemu_log("%s address=" TARGET_FMT_lx " ret %d physical " TARGET_FMT_lx " prot %d\n",
+ qemu_log("%s address=" TARGET_FMT_lx " ret %d physical " TARGET_FMT_plx " prot %d\n",
__func__, address, ret, physical, prot);
if (ret == TLBRET_MATCH) {
ret = tlb_set_page(env, address & TARGET_PAGE_MASK,
diff --git a/target-mips/helper.h b/target-mips/helper.h
index b8ec15eab..4f1de5193 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -122,6 +122,7 @@ DEF_HELPER_1(mtc0_cause, void, tl)
DEF_HELPER_1(mtc0_ebase, void, tl)
DEF_HELPER_1(mtc0_config0, void, tl)
DEF_HELPER_1(mtc0_config2, void, tl)
+DEF_HELPER_1(mtc0_lladdr, void, tl)
DEF_HELPER_2(mtc0_watchlo, void, tl, i32)
DEF_HELPER_2(mtc0_watchhi, void, tl, i32)
DEF_HELPER_1(mtc0_xcontext, void, tl)
diff --git a/target-mips/machine.c b/target-mips/machine.c
index 451931988..9ffac711c 100644
--- a/target-mips/machine.c
+++ b/target-mips/machine.c
@@ -127,7 +127,7 @@ void cpu_save(QEMUFile *f, void *opaque)
qemu_put_sbe32s(f, &env->CP0_Config3);
qemu_put_sbe32s(f, &env->CP0_Config6);
qemu_put_sbe32s(f, &env->CP0_Config7);
- qemu_put_betls(f, &env->CP0_LLAddr);
+ qemu_put_betls(f, &env->lladdr);
for(i = 0; i < 8; i++)
qemu_put_betls(f, &env->CP0_WatchLo[i]);
for(i = 0; i < 8; i++)
@@ -279,7 +279,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_sbe32s(f, &env->CP0_Config3);
qemu_get_sbe32s(f, &env->CP0_Config6);
qemu_get_sbe32s(f, &env->CP0_Config7);
- qemu_get_betls(f, &env->CP0_LLAddr);
+ qemu_get_betls(f, &env->lladdr);
for(i = 0; i < 8; i++)
qemu_get_betls(f, &env->CP0_WatchLo[i]);
for(i = 0; i < 8; i++)
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 83734b123..52d687d33 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -730,7 +730,7 @@ target_ulong helper_mftc0_status(void)
target_ulong helper_mfc0_lladdr (void)
{
- return (int32_t)env->CP0_LLAddr >> 4;
+ return (int32_t)(env->lladdr >> env->CP0_LLAddr_shift);
}
target_ulong helper_mfc0_watchlo (uint32_t sel)
@@ -795,7 +795,7 @@ target_ulong helper_dmfc0_tcschefback (void)
target_ulong helper_dmfc0_lladdr (void)
{
- return env->CP0_LLAddr >> 4;
+ return env->lladdr >> env->CP0_LLAddr_shift;
}
target_ulong helper_dmfc0_watchlo (uint32_t sel)
@@ -959,7 +959,7 @@ void helper_mtc0_tcrestart (target_ulong arg1)
{
env->active_tc.PC = arg1;
env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
- env->CP0_LLAddr = 0ULL;
+ env->lladdr = 0ULL;
/* MIPS16 not implemented. */
}
@@ -970,12 +970,12 @@ void helper_mttc0_tcrestart (target_ulong arg1)
if (other_tc == env->current_tc) {
env->active_tc.PC = arg1;
env->active_tc.CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
- env->CP0_LLAddr = 0ULL;
+ env->lladdr = 0ULL;
/* MIPS16 not implemented. */
} else {
env->tcs[other_tc].PC = arg1;
env->tcs[other_tc].CP0_TCStatus &= ~(1 << CP0TCSt_TDS);
- env->CP0_LLAddr = 0ULL;
+ env->lladdr = 0ULL;
/* MIPS16 not implemented. */
}
}
@@ -1243,6 +1243,13 @@ void helper_mtc0_config2 (target_ulong arg1)
env->CP0_Config2 = (env->CP0_Config2 & 0x8FFF0FFF);
}
+void helper_mtc0_lladdr (target_ulong arg1)
+{
+ target_long mask = env->CP0_LLAddr_rw_bitmask;
+ arg1 = arg1 << env->CP0_LLAddr_shift;
+ env->lladdr = (env->lladdr & ~mask) | (arg1 & mask);
+}
+
void helper_mtc0_watchlo (target_ulong arg1, uint32_t sel)
{
/* Watch exceptions for instructions, data loads, data stores
@@ -1702,7 +1709,7 @@ void helper_eret (void)
}
compute_hflags(env);
debug_post_eret();
- env->CP0_LLAddr = 1;
+ env->lladdr = 1;
}
void helper_deret (void)
@@ -1712,7 +1719,7 @@ void helper_deret (void)
env->hflags &= MIPS_HFLAG_DM;
compute_hflags(env);
debug_post_eret();
- env->CP0_LLAddr = 1;
+ env->lladdr = 1;
}
#endif /* !CONFIG_USER_ONLY */
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 7bae5414c..e9d92249e 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -918,7 +918,7 @@ static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
TCGv t0 = tcg_temp_new(); \
tcg_gen_mov_tl(t0, arg1); \
tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
- tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
+ tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
tcg_temp_free(t0); \
}
@@ -941,7 +941,7 @@ static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ct
tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
generate_exception(ctx, EXCP_AdES); \
gen_set_label(l1); \
- tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
+ tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
@@ -967,7 +967,7 @@ static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ct
tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
generate_exception(ctx, EXCP_AdES); \
gen_set_label(l1); \
- tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, CP0_LLAddr)); \
+ tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, llval)); \
tcg_gen_qemu_##ldname(t1, arg2, ctx->mem_idx); \
@@ -3841,7 +3841,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
case 17:
switch (sel) {
case 0:
- /* ignored */
+ gen_helper_mtc0_lladdr(arg);
rn = "LLAddr";
break;
default:
@@ -4998,7 +4998,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
case 17:
switch (sel) {
case 0:
- /* ignored */
+ gen_helper_mtc0_lladdr(arg);
rn = "LLAddr";
break;
default:
@@ -8501,8 +8501,8 @@ cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
if (!SIGN_EXT_P(env->CP0_EPC))
cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
- if (!SIGN_EXT_P(env->CP0_LLAddr))
- cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->CP0_LLAddr);
+ if (!SIGN_EXT_P(env->lladdr))
+ cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
}
#endif
@@ -8526,7 +8526,7 @@ void cpu_dump_state (CPUState *env, FILE *f,
cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
- env->CP0_Config0, env->CP0_Config1, env->CP0_LLAddr);
+ env->CP0_Config0, env->CP0_Config1, env->lladdr);
if (env->hflags & MIPS_HFLAG_FPU)
fpu_dump_state(env, f, cpu_fprintf, flags);
#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
@@ -8633,6 +8633,9 @@ void cpu_reset (CPUMIPSState *env)
env->CP0_Config3 = env->cpu_model->CP0_Config3;
env->CP0_Config6 = env->cpu_model->CP0_Config6;
env->CP0_Config7 = env->cpu_model->CP0_Config7;
+ env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
+ << env->cpu_model->CP0_LLAddr_shift;
+ env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
env->SYNCI_Step = env->cpu_model->SYNCI_Step;
env->CCRes = env->cpu_model->CCRes;
env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
index 088e2b4c2..c950eab1a 100644
--- a/target-mips/translate_init.c
+++ b/target-mips/translate_init.c
@@ -70,6 +70,8 @@ struct mips_def_t {
int32_t CP0_Config3;
int32_t CP0_Config6;
int32_t CP0_Config7;
+ target_ulong CP0_LLAddr_rw_bitmask;
+ int CP0_LLAddr_shift;
int32_t SYNCI_Step;
int32_t CCRes;
int32_t CP0_Status_rw_bitmask;
@@ -105,6 +107,8 @@ static const mips_def_t mips_defs[] =
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3,
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 4,
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x1278FF17,
@@ -124,6 +128,8 @@ static const mips_def_t mips_defs[] =
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3,
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 4,
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x1258FF17,
@@ -141,6 +147,8 @@ static const mips_def_t mips_defs[] =
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3,
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 4,
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x1278FF17,
@@ -158,6 +166,8 @@ static const mips_def_t mips_defs[] =
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3,
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 4,
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x1258FF17,
@@ -176,6 +186,8 @@ static const mips_def_t mips_defs[] =
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 4,
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x1278FF17,
@@ -194,6 +206,8 @@ static const mips_def_t mips_defs[] =
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3,
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 4,
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x1258FF17,
@@ -212,6 +226,8 @@ static const mips_def_t mips_defs[] =
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 4,
.SYNCI_Step = 32,
.CCRes = 2,
/* No DSP implemented. */
@@ -231,6 +247,8 @@ static const mips_def_t mips_defs[] =
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt),
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 4,
.SYNCI_Step = 32,
.CCRes = 2,
/* No DSP implemented. */
@@ -252,6 +270,8 @@ static const mips_def_t mips_defs[] =
(0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3 | (0 << CP0C3_VInt) | (1 << CP0C3_MT),
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 0,
.SYNCI_Step = 32,
.CCRes = 2,
/* No DSP implemented. */
@@ -294,6 +314,8 @@ static const mips_def_t mips_defs[] =
.CP0_Config0 = (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << CP0C0_K0),
/* Note: Config1 is only used internally, the R4000 has only Config0. */
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
+ .CP0_LLAddr_rw_bitmask = 0xFFFFFFFF,
+ .CP0_LLAddr_shift = 4,
.SYNCI_Step = 16,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x3678FFFF,
@@ -310,6 +332,8 @@ static const mips_def_t mips_defs[] =
/* No L2 cache, icache size 8k, dcache size 8k, uncached coherency. */
.CP0_Config0 = (1 << 17) | (0x1 << 9) | (0x1 << 6) | (0x2 << CP0C0_K0),
.CP0_Config1 = (1 << CP0C1_FP) | (47 << CP0C1_MMU),
+ .CP0_LLAddr_rw_bitmask = 0xFFFFFFFFL,
+ .CP0_LLAddr_shift = 4,
.SYNCI_Step = 16,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x3678FFFF,
@@ -331,6 +355,8 @@ static const mips_def_t mips_defs[] =
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3,
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 4,
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x32F8FFFF,
@@ -350,6 +376,8 @@ static const mips_def_t mips_defs[] =
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3,
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 4,
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x36F8FFFF,
@@ -374,6 +402,8 @@ static const mips_def_t mips_defs[] =
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3,
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 0,
.SYNCI_Step = 32,
.CCRes = 1,
.CP0_Status_rw_bitmask = 0x36FBFFFF,
@@ -399,6 +429,8 @@ static const mips_def_t mips_defs[] =
(1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
.CP0_Config2 = MIPS_CONFIG2,
.CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_LPA),
+ .CP0_LLAddr_rw_bitmask = 0,
+ .CP0_LLAddr_shift = 0,
.SYNCI_Step = 32,
.CCRes = 2,
.CP0_Status_rw_bitmask = 0x36FBFFFF,
diff --git a/vl.c b/vl.c
index 7be5512d6..f30cc2378 100644
--- a/vl.c
+++ b/vl.c
@@ -5102,11 +5102,9 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_S:
autostart = 0;
break;
-#ifndef _WIN32
case QEMU_OPTION_k:
keyboard_layout = optarg;
break;
-#endif
case QEMU_OPTION_localtime:
rtc_utc = 0;
break;