On 06/06/2016 03:37 AM, Michael Rolnik wrote:
+void write_Rx(CPUAVRState *env, int inst, uint8_t data) +{ + env->r[inst] = data; +} +uint8_t read_Rx(CPUAVRState *env, int inst)
Spacing. But more importantly...
+static +void sample_io_write(void *opaque, hwaddr offset, uint64_t value, unsigned size) +{ + SAMPLEIOState *s = SAMPLEIO(opaque); + AVRCPU *cpu = s->cpu; + CPUAVRState *env = &cpu->env; + + assert(size == 1); + + if (AVR_IO_CPU_REGS_BASE <= offset + && offset < (AVR_IO_CPU_REGS_BASE + AVR_IO_CPU_REGS_SIZE)) { + return write_Rx(env, offset - AVR_IO_CPU_REGS_BASE, value);
...
+static +int sample_io_init(DeviceState *dev) +{ + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + SAMPLEIOState *s = SAMPLEIO(dev); + + assert(AVR_IO_SIZE <= TARGET_PAGE_SIZE); + + s->cpu = AVR_CPU(qemu_get_cpu(0)); + + memory_region_init_io( + &s->iomem, + OBJECT(s), + &sample_io_ops, + s, + TYPE_SAMPLEIO, + AVR_IO_SIZE); + sysbus_init_mmio(sbd, &s->iomem);
This is a memory-mapped device, and you can't modify cpu registers with a memory write.
You can read cpu registers, since all TCG globals will have been synced back to ENV before the memory operation. But they'll still be live in TB, and so the next instruction may not see the value that you just wrote.
If this write is really something that you need to support, then you'll have to figure out some other way of implementing it.
My first guess at a workable solution is to keep the page for this memory device read-only. Detect writes via tlb_fill and throw a special exception. In do_interrupt, either handle the write (probably tricky); or set a flag in ENV, which in turn sets a flag in TB, which in turn tells translate to use a function (helper_writeb?) instead of using tcg_gen_qemu_st_tl. That helper would be marked such that modifications to TCG registers is expected. Then clear the flag in ENV so that subsequent stores use the normal path.
r~