* [PULL 0/9] target/avr: Increase TARGET_PAGE_BITS to 10 @ 2025-04-22 21:11 Richard Henderson 2025-04-22 21:11 ` [PULL 1/9] target/avr: Improve decode of LDS, STS Richard Henderson ` (9 more replies) 0 siblings, 10 replies; 11+ messages in thread From: Richard Henderson @ 2025-04-22 21:11 UTC (permalink / raw) To: qemu-devel The following changes since commit 1da8f3a3c53b604edfe0d55e475102640490549e: Open 10.1 development tree (2025-04-22 15:09:23 -0400) are available in the Git repository at: https://gitlab.com/rth7680/qemu.git tags/pull-avr-20250422 for you to fetch changes up to eba24b60a72115e21e850977b3019aaf037c66c9: target/avr: Increase TARGET_PAGE_BITS to 10 (2025-04-22 14:07:12 -0700) ---------------------------------------------------------------- target/avr: Fix buffer read in avr_print_insn target/avr: Improve decode of LDS, STS target/avr: Move cpu register accesses into system memory target/avr: Increase TARGET_PAGE_BITS to 10 ---------------------------------------------------------------- Richard Henderson (9): target/avr: Improve decode of LDS, STS target/avr: Remove OFFSET_CPU_REGISTERS target/avr: Add defines for i/o port registers target/avr: Move cpu register accesses into system memory target/avr: Remove NUMBER_OF_IO_REGISTERS target/avr: Use cpu_stb_mmuidx_ra in helper_fullwr target/avr: Use do_stb in avr_cpu_do_interrupt hw/avr: Prepare for TARGET_PAGE_SIZE > 256 target/avr: Increase TARGET_PAGE_BITS to 10 hw/avr/atmega.h | 1 + target/avr/cpu-param.h | 8 +- target/avr/cpu.h | 21 +++- target/avr/helper.h | 3 - hw/avr/atmega.c | 39 ++++++-- target/avr/cpu.c | 16 +++ target/avr/helper.c | 262 +++++++++++++++++++++---------------------------- target/avr/translate.c | 44 +++++---- target/avr/insn.decode | 7 +- 9 files changed, 205 insertions(+), 196 deletions(-) ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PULL 1/9] target/avr: Improve decode of LDS, STS 2025-04-22 21:11 [PULL 0/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson @ 2025-04-22 21:11 ` Richard Henderson 2025-04-22 21:11 ` [PULL 2/9] target/avr: Remove OFFSET_CPU_REGISTERS Richard Henderson ` (8 subsequent siblings) 9 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2025-04-22 21:11 UTC (permalink / raw) To: qemu-devel; +Cc: qemu-stable, Pierrick Bouvier The comment about not being able to define a field with zero bits is out of date since 94597b6146f3 ("decodetree: Allow !function with no input bits"). This fixes the missing load of imm in the disassembler. Cc: qemu-stable@nongnu.org Fixes: 9d8caa67a24 ("target/avr: Add support for disassembling via option '-d in_asm'") Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/avr/translate.c | 2 -- target/avr/insn.decode | 7 ++----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/target/avr/translate.c b/target/avr/translate.c index 4ab71d8138..e7f8ced9b3 100644 --- a/target/avr/translate.c +++ b/target/avr/translate.c @@ -1578,7 +1578,6 @@ static bool trans_LDS(DisasContext *ctx, arg_LDS *a) TCGv Rd = cpu_r[a->rd]; TCGv addr = tcg_temp_new_i32(); TCGv H = cpu_rampD; - a->imm = next_word(ctx); tcg_gen_mov_tl(addr, H); /* addr = H:M:L */ tcg_gen_shli_tl(addr, addr, 16); @@ -1783,7 +1782,6 @@ static bool trans_STS(DisasContext *ctx, arg_STS *a) TCGv Rd = cpu_r[a->rd]; TCGv addr = tcg_temp_new_i32(); TCGv H = cpu_rampD; - a->imm = next_word(ctx); tcg_gen_mov_tl(addr, H); /* addr = H:M:L */ tcg_gen_shli_tl(addr, addr, 16); diff --git a/target/avr/insn.decode b/target/avr/insn.decode index 482c23ad0c..cc302249db 100644 --- a/target/avr/insn.decode +++ b/target/avr/insn.decode @@ -118,11 +118,8 @@ BRBC 1111 01 ....... ... @op_bit_imm @io_rd_imm .... . .. ..... .... &rd_imm rd=%rd imm=%io_imm @ldst_d .. . . .. . rd:5 . ... &rd_imm imm=%ldst_d_imm -# The 16-bit immediate is completely in the next word. -# Fields cannot be defined with no bits, so we cannot play -# the same trick and append to a zero-bit value. -# Defer reading the immediate until trans_{LDS,STS}. -@ldst_s .... ... rd:5 .... imm=0 +%ldst_imm !function=next_word +@ldst_s .... ... rd:5 .... imm=%ldst_imm MOV 0010 11 . ..... .... @op_rd_rr MOVW 0000 0001 .... .... &rd_rr rd=%rd_d rr=%rr_d -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PULL 2/9] target/avr: Remove OFFSET_CPU_REGISTERS 2025-04-22 21:11 [PULL 0/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson 2025-04-22 21:11 ` [PULL 1/9] target/avr: Improve decode of LDS, STS Richard Henderson @ 2025-04-22 21:11 ` Richard Henderson 2025-04-22 21:11 ` [PULL 3/9] target/avr: Add defines for i/o port registers Richard Henderson ` (7 subsequent siblings) 9 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2025-04-22 21:11 UTC (permalink / raw) To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Pierrick Bouvier This define isn't really used. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/avr/cpu.h | 2 -- target/avr/helper.c | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/target/avr/cpu.h b/target/avr/cpu.h index 06f5ae4d1b..84a8f5cc8c 100644 --- a/target/avr/cpu.h +++ b/target/avr/cpu.h @@ -60,8 +60,6 @@ #define OFFSET_CODE 0x00000000 /* CPU registers, IO registers, and SRAM */ #define OFFSET_DATA 0x00800000 -/* CPU registers specifically, these are mapped at the start of data */ -#define OFFSET_CPU_REGISTERS OFFSET_DATA /* * IO registers, including status register, stack pointer, and memory * mapped peripherals, mapped just after CPU registers diff --git a/target/avr/helper.c b/target/avr/helper.c index 3412312ad5..e5bf16c6b7 100644 --- a/target/avr/helper.c +++ b/target/avr/helper.c @@ -340,8 +340,7 @@ void helper_fullwr(CPUAVRState *env, uint32_t data, uint32_t addr) env->fullacc = false; /* Following logic assumes this: */ - assert(OFFSET_CPU_REGISTERS == OFFSET_DATA); - assert(OFFSET_IO_REGISTERS == OFFSET_CPU_REGISTERS + + assert(OFFSET_IO_REGISTERS == OFFSET_DATA + NUMBER_OF_CPU_REGISTERS); if (addr < NUMBER_OF_CPU_REGISTERS) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PULL 3/9] target/avr: Add defines for i/o port registers 2025-04-22 21:11 [PULL 0/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson 2025-04-22 21:11 ` [PULL 1/9] target/avr: Improve decode of LDS, STS Richard Henderson 2025-04-22 21:11 ` [PULL 2/9] target/avr: Remove OFFSET_CPU_REGISTERS Richard Henderson @ 2025-04-22 21:11 ` Richard Henderson 2025-04-22 21:11 ` [PULL 4/9] target/avr: Move cpu register accesses into system memory Richard Henderson ` (6 subsequent siblings) 9 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2025-04-22 21:11 UTC (permalink / raw) To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/avr/cpu.h | 10 ++++++++++ target/avr/helper.c | 36 ++++++++++++++++++------------------ 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/target/avr/cpu.h b/target/avr/cpu.h index 84a8f5cc8c..1a5a5b8e3e 100644 --- a/target/avr/cpu.h +++ b/target/avr/cpu.h @@ -47,6 +47,16 @@ /* Number of IO registers accessible by ld/st/in/out */ #define NUMBER_OF_IO_REGISTERS 64 +/* CPU registers mapped into i/o ports 0x38-0x3f. */ +#define REG_38_RAMPD 0 +#define REG_38_RAMPX 1 +#define REG_38_RAMPY 2 +#define REG_38_RAMPZ 3 +#define REG_38_EIDN 4 +#define REG_38_SPL 5 +#define REG_38_SPH 6 +#define REG_38_SREG 7 + /* * Offsets of AVR memory regions in host memory space. * diff --git a/target/avr/helper.c b/target/avr/helper.c index e5bf16c6b7..f8ada8b106 100644 --- a/target/avr/helper.c +++ b/target/avr/helper.c @@ -216,29 +216,29 @@ target_ulong helper_inb(CPUAVRState *env, uint32_t port) { target_ulong data = 0; - switch (port) { - case 0x38: /* RAMPD */ + switch (port - 0x38) { + case REG_38_RAMPD: data = 0xff & (env->rampD >> 16); break; - case 0x39: /* RAMPX */ + case REG_38_RAMPX: data = 0xff & (env->rampX >> 16); break; - case 0x3a: /* RAMPY */ + case REG_38_RAMPY: data = 0xff & (env->rampY >> 16); break; - case 0x3b: /* RAMPZ */ + case REG_38_RAMPZ: data = 0xff & (env->rampZ >> 16); break; - case 0x3c: /* EIND */ + case REG_38_EIDN: data = 0xff & (env->eind >> 16); break; - case 0x3d: /* SPL */ + case REG_38_SPL: data = env->sp & 0x00ff; break; - case 0x3e: /* SPH */ + case REG_38_SPH: data = env->sp >> 8; break; - case 0x3f: /* SREG */ + case REG_38_SREG: data = cpu_get_sreg(env); break; default: @@ -265,39 +265,39 @@ void helper_outb(CPUAVRState *env, uint32_t port, uint32_t data) { data &= 0x000000ff; - switch (port) { - case 0x38: /* RAMPD */ + switch (port - 0x38) { + case REG_38_RAMPD: if (avr_feature(env, AVR_FEATURE_RAMPD)) { env->rampD = (data & 0xff) << 16; } break; - case 0x39: /* RAMPX */ + case REG_38_RAMPX: if (avr_feature(env, AVR_FEATURE_RAMPX)) { env->rampX = (data & 0xff) << 16; } break; - case 0x3a: /* RAMPY */ + case REG_38_RAMPY: if (avr_feature(env, AVR_FEATURE_RAMPY)) { env->rampY = (data & 0xff) << 16; } break; - case 0x3b: /* RAMPZ */ + case REG_38_RAMPZ: if (avr_feature(env, AVR_FEATURE_RAMPZ)) { env->rampZ = (data & 0xff) << 16; } break; - case 0x3c: /* EIDN */ + case REG_38_EIDN: env->eind = (data & 0xff) << 16; break; - case 0x3d: /* SPL */ + case REG_38_SPL: env->sp = (env->sp & 0xff00) | (data); break; - case 0x3e: /* SPH */ + case REG_38_SPH: if (avr_feature(env, AVR_FEATURE_2_BYTE_SP)) { env->sp = (env->sp & 0x00ff) | (data << 8); } break; - case 0x3f: /* SREG */ + case REG_38_SREG: cpu_set_sreg(env, data); break; default: -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PULL 4/9] target/avr: Move cpu register accesses into system memory 2025-04-22 21:11 [PULL 0/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson ` (2 preceding siblings ...) 2025-04-22 21:11 ` [PULL 3/9] target/avr: Add defines for i/o port registers Richard Henderson @ 2025-04-22 21:11 ` Richard Henderson 2025-04-22 21:11 ` [PULL 5/9] target/avr: Remove NUMBER_OF_IO_REGISTERS Richard Henderson ` (5 subsequent siblings) 9 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2025-04-22 21:11 UTC (permalink / raw) To: qemu-devel; +Cc: Pierrick Bouvier Integrate the i/o 0x00-0x1f and 0x38-0x3f loopbacks into the cpu registers with normal address space accesses. We no longer need to trap accesses to the first page within avr_cpu_tlb_fill but can wait until a write occurs. Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/avr/cpu.h | 7 ++ target/avr/helper.h | 3 - target/avr/cpu.c | 16 +++ target/avr/helper.c | 223 +++++++++++++++++------------------------ target/avr/translate.c | 42 ++++---- 5 files changed, 138 insertions(+), 153 deletions(-) diff --git a/target/avr/cpu.h b/target/avr/cpu.h index 1a5a5b8e3e..6f68060ab0 100644 --- a/target/avr/cpu.h +++ b/target/avr/cpu.h @@ -23,6 +23,7 @@ #include "cpu-qom.h" #include "exec/cpu-defs.h" +#include "exec/memory.h" #ifdef CONFIG_USER_ONLY #error "AVR 8-bit does not support user mode" @@ -152,6 +153,9 @@ struct ArchCPU { CPUAVRState env; + MemoryRegion cpu_reg1; + MemoryRegion cpu_reg2; + /* Initial value of stack pointer */ uint32_t init_sp; }; @@ -252,6 +256,9 @@ bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); +extern const MemoryRegionOps avr_cpu_reg1; +extern const MemoryRegionOps avr_cpu_reg2; + #include "exec/cpu-all.h" #endif /* QEMU_AVR_CPU_H */ diff --git a/target/avr/helper.h b/target/avr/helper.h index 4d02e648fa..e8d13e925f 100644 --- a/target/avr/helper.h +++ b/target/avr/helper.h @@ -23,7 +23,4 @@ DEF_HELPER_1(debug, noreturn, env) DEF_HELPER_1(break, noreturn, env) DEF_HELPER_1(sleep, noreturn, env) DEF_HELPER_1(unsupported, noreturn, env) -DEF_HELPER_3(outb, void, env, i32, i32) -DEF_HELPER_2(inb, tl, env, i32) DEF_HELPER_3(fullwr, void, env, i32, i32) -DEF_HELPER_2(fullrd, tl, env, i32) diff --git a/target/avr/cpu.c b/target/avr/cpu.c index 834c7082aa..0b14b36c17 100644 --- a/target/avr/cpu.c +++ b/target/avr/cpu.c @@ -23,6 +23,7 @@ #include "qemu/qemu-print.h" #include "exec/exec-all.h" #include "exec/translation-block.h" +#include "exec/address-spaces.h" #include "cpu.h" #include "disas/dis-asm.h" #include "tcg/debug-assert.h" @@ -110,6 +111,8 @@ static void avr_cpu_disas_set_info(CPUState *cpu, disassemble_info *info) static void avr_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); + CPUAVRState *env = cpu_env(cs); + AVRCPU *cpu = env_archcpu(env); AVRCPUClass *mcc = AVR_CPU_GET_CLASS(dev); Error *local_err = NULL; @@ -122,6 +125,19 @@ static void avr_cpu_realizefn(DeviceState *dev, Error **errp) cpu_reset(cs); mcc->parent_realize(dev, errp); + + /* + * Two blocks in the low data space loop back into cpu registers. + */ + memory_region_init_io(&cpu->cpu_reg1, OBJECT(cpu), &avr_cpu_reg1, env, + "avr-cpu-reg1", 32); + memory_region_add_subregion(get_system_memory(), + OFFSET_DATA, &cpu->cpu_reg1); + + memory_region_init_io(&cpu->cpu_reg2, OBJECT(cpu), &avr_cpu_reg2, env, + "avr-cpu-reg2", 8); + memory_region_add_subregion(get_system_memory(), + OFFSET_DATA + 0x58, &cpu->cpu_reg2); } static void avr_cpu_set_int(void *opaque, int irq, int level) diff --git a/target/avr/helper.c b/target/avr/helper.c index f8ada8b106..d0e86f5614 100644 --- a/target/avr/helper.c +++ b/target/avr/helper.c @@ -108,7 +108,7 @@ bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr) { - int prot, page_size = TARGET_PAGE_SIZE; + int prot; uint32_t paddr; address &= TARGET_PAGE_MASK; @@ -133,23 +133,9 @@ bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size, /* Access to memory. */ paddr = OFFSET_DATA + address; prot = PAGE_READ | PAGE_WRITE; - if (address < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) { - /* - * Access to CPU registers, exit and rebuilt this TB to use - * full access in case it touches specially handled registers - * like SREG or SP. For probing, set page_size = 1, in order - * to force tlb_fill to be called for the next access. - */ - if (probe) { - page_size = 1; - } else { - cpu_env(cs)->fullacc = 1; - cpu_loop_exit_restore(cs, retaddr); - } - } } - tlb_set_page(cs, address, paddr, prot, mmu_idx, page_size); + tlb_set_page(cs, address, paddr, prot, mmu_idx, TARGET_PAGE_SIZE); return true; } @@ -203,134 +189,78 @@ void helper_wdr(CPUAVRState *env) } /* - * This function implements IN instruction - * - * It does the following - * a. if an IO register belongs to CPU, its value is read and returned - * b. otherwise io address is translated to mem address and physical memory - * is read. - * c. it caches the value for sake of SBI, SBIC, SBIS & CBI implementation - * + * The first 32 bytes of the data space are mapped to the cpu regs. + * We cannot write these from normal store operations because TCG + * does not expect global temps to be modified -- a global may be + * live in a host cpu register across the store. We can however + * read these, as TCG does make sure the global temps are saved + * in case the load operation traps. */ -target_ulong helper_inb(CPUAVRState *env, uint32_t port) + +static uint64_t avr_cpu_reg1_read(void *opaque, hwaddr addr, unsigned size) { - target_ulong data = 0; + CPUAVRState *env = opaque; - switch (port - 0x38) { - case REG_38_RAMPD: - data = 0xff & (env->rampD >> 16); - break; - case REG_38_RAMPX: - data = 0xff & (env->rampX >> 16); - break; - case REG_38_RAMPY: - data = 0xff & (env->rampY >> 16); - break; - case REG_38_RAMPZ: - data = 0xff & (env->rampZ >> 16); - break; - case REG_38_EIDN: - data = 0xff & (env->eind >> 16); - break; - case REG_38_SPL: - data = env->sp & 0x00ff; - break; - case REG_38_SPH: - data = env->sp >> 8; - break; - case REG_38_SREG: - data = cpu_get_sreg(env); - break; - default: - /* not a special register, pass to normal memory access */ - data = address_space_ldub(&address_space_memory, - OFFSET_IO_REGISTERS + port, - MEMTXATTRS_UNSPECIFIED, NULL); - } - - return data; + assert(addr < 32); + return env->r[addr]; } /* - * This function implements OUT instruction - * - * It does the following - * a. if an IO register belongs to CPU, its value is written into the register - * b. otherwise io address is translated to mem address and physical memory - * is written. - * c. it caches the value for sake of SBI, SBIC, SBIS & CBI implementation - * + * The range 0x38-0x3f of the i/o space is mapped to cpu regs. + * As above, we cannot write these from normal store operations. */ -void helper_outb(CPUAVRState *env, uint32_t port, uint32_t data) -{ - data &= 0x000000ff; - switch (port - 0x38) { +static uint64_t avr_cpu_reg2_read(void *opaque, hwaddr addr, unsigned size) +{ + CPUAVRState *env = opaque; + + switch (addr) { case REG_38_RAMPD: - if (avr_feature(env, AVR_FEATURE_RAMPD)) { - env->rampD = (data & 0xff) << 16; - } - break; + return 0xff & (env->rampD >> 16); case REG_38_RAMPX: - if (avr_feature(env, AVR_FEATURE_RAMPX)) { - env->rampX = (data & 0xff) << 16; - } - break; + return 0xff & (env->rampX >> 16); case REG_38_RAMPY: - if (avr_feature(env, AVR_FEATURE_RAMPY)) { - env->rampY = (data & 0xff) << 16; - } - break; + return 0xff & (env->rampY >> 16); case REG_38_RAMPZ: - if (avr_feature(env, AVR_FEATURE_RAMPZ)) { - env->rampZ = (data & 0xff) << 16; - } - break; + return 0xff & (env->rampZ >> 16); case REG_38_EIDN: - env->eind = (data & 0xff) << 16; - break; + return 0xff & (env->eind >> 16); case REG_38_SPL: - env->sp = (env->sp & 0xff00) | (data); - break; + return env->sp & 0x00ff; case REG_38_SPH: - if (avr_feature(env, AVR_FEATURE_2_BYTE_SP)) { - env->sp = (env->sp & 0x00ff) | (data << 8); - } - break; + return 0xff & (env->sp >> 8); case REG_38_SREG: - cpu_set_sreg(env, data); - break; - default: - /* not a special register, pass to normal memory access */ - address_space_stb(&address_space_memory, OFFSET_IO_REGISTERS + port, - data, MEMTXATTRS_UNSPECIFIED, NULL); + return cpu_get_sreg(env); } + g_assert_not_reached(); } -/* - * this function implements LD instruction when there is a possibility to read - * from a CPU register - */ -target_ulong helper_fullrd(CPUAVRState *env, uint32_t addr) +static void avr_cpu_trap_write(void *opaque, hwaddr addr, + uint64_t data64, unsigned size) { - uint8_t data; + CPUAVRState *env = opaque; + CPUState *cs = env_cpu(env); - env->fullacc = false; - - if (addr < NUMBER_OF_CPU_REGISTERS) { - /* CPU registers */ - data = env->r[addr]; - } else if (addr < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) { - /* IO registers */ - data = helper_inb(env, addr - NUMBER_OF_CPU_REGISTERS); - } else { - /* memory */ - data = address_space_ldub(&address_space_memory, OFFSET_DATA + addr, - MEMTXATTRS_UNSPECIFIED, NULL); - } - return data; + env->fullacc = true; + cpu_loop_exit_restore(cs, cs->mem_io_pc); } +const MemoryRegionOps avr_cpu_reg1 = { + .read = avr_cpu_reg1_read, + .write = avr_cpu_trap_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid.min_access_size = 1, + .valid.max_access_size = 1, +}; + +const MemoryRegionOps avr_cpu_reg2 = { + .read = avr_cpu_reg2_read, + .write = avr_cpu_trap_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid.min_access_size = 1, + .valid.max_access_size = 1, +}; + /* * this function implements ST instruction when there is a possibility to write * into a CPU register @@ -339,19 +269,50 @@ void helper_fullwr(CPUAVRState *env, uint32_t data, uint32_t addr) { env->fullacc = false; - /* Following logic assumes this: */ - assert(OFFSET_IO_REGISTERS == OFFSET_DATA + - NUMBER_OF_CPU_REGISTERS); - - if (addr < NUMBER_OF_CPU_REGISTERS) { + switch (addr) { + case 0 ... 31: /* CPU registers */ env->r[addr] = data; - } else if (addr < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) { - /* IO registers */ - helper_outb(env, addr - NUMBER_OF_CPU_REGISTERS, data); - } else { - /* memory */ + break; + + case REG_38_RAMPD + 0x38 + NUMBER_OF_CPU_REGISTERS: + if (avr_feature(env, AVR_FEATURE_RAMPD)) { + env->rampD = data << 16; + } + break; + case REG_38_RAMPX + 0x38 + NUMBER_OF_CPU_REGISTERS: + if (avr_feature(env, AVR_FEATURE_RAMPX)) { + env->rampX = data << 16; + } + break; + case REG_38_RAMPY + 0x38 + NUMBER_OF_CPU_REGISTERS: + if (avr_feature(env, AVR_FEATURE_RAMPY)) { + env->rampY = data << 16; + } + break; + case REG_38_RAMPZ + 0x38 + NUMBER_OF_CPU_REGISTERS: + if (avr_feature(env, AVR_FEATURE_RAMPZ)) { + env->rampZ = data << 16; + } + break; + case REG_38_EIDN + 0x38 + NUMBER_OF_CPU_REGISTERS: + env->eind = data << 16; + break; + case REG_38_SPL + 0x38 + NUMBER_OF_CPU_REGISTERS: + env->sp = (env->sp & 0xff00) | data; + break; + case REG_38_SPH + 0x38 + NUMBER_OF_CPU_REGISTERS: + if (avr_feature(env, AVR_FEATURE_2_BYTE_SP)) { + env->sp = (env->sp & 0x00ff) | (data << 8); + } + break; + case REG_38_SREG + 0x38 + NUMBER_OF_CPU_REGISTERS: + cpu_set_sreg(env, data); + break; + + default: address_space_stb(&address_space_memory, OFFSET_DATA + addr, data, MEMTXATTRS_UNSPECIFIED, NULL); + break; } } diff --git a/target/avr/translate.c b/target/avr/translate.c index e7f8ced9b3..0490936cd5 100644 --- a/target/avr/translate.c +++ b/target/avr/translate.c @@ -194,6 +194,9 @@ static bool avr_have_feature(DisasContext *ctx, int feature) static bool decode_insn(DisasContext *ctx, uint16_t insn); #include "decode-insn.c.inc" +static void gen_inb(DisasContext *ctx, TCGv data, int port); +static void gen_outb(DisasContext *ctx, TCGv data, int port); + /* * Arithmetic Instructions */ @@ -1293,9 +1296,8 @@ static bool trans_SBRS(DisasContext *ctx, arg_SBRS *a) static bool trans_SBIC(DisasContext *ctx, arg_SBIC *a) { TCGv data = tcg_temp_new_i32(); - TCGv port = tcg_constant_i32(a->reg); - gen_helper_inb(data, tcg_env, port); + gen_inb(ctx, data, a->reg); tcg_gen_andi_tl(data, data, 1 << a->bit); ctx->skip_cond = TCG_COND_EQ; ctx->skip_var0 = data; @@ -1311,9 +1313,8 @@ static bool trans_SBIC(DisasContext *ctx, arg_SBIC *a) static bool trans_SBIS(DisasContext *ctx, arg_SBIS *a) { TCGv data = tcg_temp_new_i32(); - TCGv port = tcg_constant_i32(a->reg); - gen_helper_inb(data, tcg_env, port); + gen_inb(ctx, data, a->reg); tcg_gen_andi_tl(data, data, 1 << a->bit); ctx->skip_cond = TCG_COND_NE; ctx->skip_var0 = data; @@ -1502,11 +1503,18 @@ static void gen_data_store(DisasContext *ctx, TCGv data, TCGv addr) static void gen_data_load(DisasContext *ctx, TCGv data, TCGv addr) { - if (ctx->base.tb->flags & TB_FLAGS_FULL_ACCESS) { - gen_helper_fullrd(data, tcg_env, addr); - } else { - tcg_gen_qemu_ld_tl(data, addr, MMU_DATA_IDX, MO_UB); - } + tcg_gen_qemu_ld_tl(data, addr, MMU_DATA_IDX, MO_UB); +} + +static void gen_inb(DisasContext *ctx, TCGv data, int port) +{ + gen_data_load(ctx, data, tcg_constant_i32(port + NUMBER_OF_CPU_REGISTERS)); +} + +static void gen_outb(DisasContext *ctx, TCGv data, int port) +{ + gen_helper_fullwr(tcg_env, data, + tcg_constant_i32(port + NUMBER_OF_CPU_REGISTERS)); } /* @@ -2126,9 +2134,8 @@ static bool trans_SPMX(DisasContext *ctx, arg_SPMX *a) static bool trans_IN(DisasContext *ctx, arg_IN *a) { TCGv Rd = cpu_r[a->rd]; - TCGv port = tcg_constant_i32(a->imm); - gen_helper_inb(Rd, tcg_env, port); + gen_inb(ctx, Rd, a->imm); return true; } @@ -2139,9 +2146,8 @@ static bool trans_IN(DisasContext *ctx, arg_IN *a) static bool trans_OUT(DisasContext *ctx, arg_OUT *a) { TCGv Rd = cpu_r[a->rd]; - TCGv port = tcg_constant_i32(a->imm); - gen_helper_outb(tcg_env, port, Rd); + gen_outb(ctx, Rd, a->imm); return true; } @@ -2407,11 +2413,10 @@ static bool trans_SWAP(DisasContext *ctx, arg_SWAP *a) static bool trans_SBI(DisasContext *ctx, arg_SBI *a) { TCGv data = tcg_temp_new_i32(); - TCGv port = tcg_constant_i32(a->reg); - gen_helper_inb(data, tcg_env, port); + gen_inb(ctx, data, a->reg); tcg_gen_ori_tl(data, data, 1 << a->bit); - gen_helper_outb(tcg_env, port, data); + gen_outb(ctx, data, a->reg); return true; } @@ -2422,11 +2427,10 @@ static bool trans_SBI(DisasContext *ctx, arg_SBI *a) static bool trans_CBI(DisasContext *ctx, arg_CBI *a) { TCGv data = tcg_temp_new_i32(); - TCGv port = tcg_constant_i32(a->reg); - gen_helper_inb(data, tcg_env, port); + gen_inb(ctx, data, a->reg); tcg_gen_andi_tl(data, data, ~(1 << a->bit)); - gen_helper_outb(tcg_env, port, data); + gen_outb(ctx, data, a->reg); return true; } -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PULL 5/9] target/avr: Remove NUMBER_OF_IO_REGISTERS 2025-04-22 21:11 [PULL 0/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson ` (3 preceding siblings ...) 2025-04-22 21:11 ` [PULL 4/9] target/avr: Move cpu register accesses into system memory Richard Henderson @ 2025-04-22 21:11 ` Richard Henderson 2025-04-22 21:11 ` [PULL 6/9] target/avr: Use cpu_stb_mmuidx_ra in helper_fullwr Richard Henderson ` (4 subsequent siblings) 9 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2025-04-22 21:11 UTC (permalink / raw) To: qemu-devel; +Cc: Pierrick Bouvier This define is no longer used. Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/avr/cpu.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/target/avr/cpu.h b/target/avr/cpu.h index 6f68060ab0..9862705c6a 100644 --- a/target/avr/cpu.h +++ b/target/avr/cpu.h @@ -45,8 +45,6 @@ /* Number of CPU registers */ #define NUMBER_OF_CPU_REGISTERS 32 -/* Number of IO registers accessible by ld/st/in/out */ -#define NUMBER_OF_IO_REGISTERS 64 /* CPU registers mapped into i/o ports 0x38-0x3f. */ #define REG_38_RAMPD 0 -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PULL 6/9] target/avr: Use cpu_stb_mmuidx_ra in helper_fullwr 2025-04-22 21:11 [PULL 0/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson ` (4 preceding siblings ...) 2025-04-22 21:11 ` [PULL 5/9] target/avr: Remove NUMBER_OF_IO_REGISTERS Richard Henderson @ 2025-04-22 21:11 ` Richard Henderson 2025-04-22 21:11 ` [PULL 7/9] target/avr: Use do_stb in avr_cpu_do_interrupt Richard Henderson ` (3 subsequent siblings) 9 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2025-04-22 21:11 UTC (permalink / raw) To: qemu-devel; +Cc: Pierrick Bouvier Avoid direct use of address_space_memory. Make use of the softmmu cache of the i/o page. Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/avr/helper.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/target/avr/helper.c b/target/avr/helper.c index d0e86f5614..7d6954ec26 100644 --- a/target/avr/helper.c +++ b/target/avr/helper.c @@ -23,10 +23,10 @@ #include "qemu/error-report.h" #include "cpu.h" #include "accel/tcg/cpu-ops.h" +#include "accel/tcg/getpc.h" #include "exec/cputlb.h" #include "exec/page-protection.h" #include "exec/cpu_ldst.h" -#include "exec/address-spaces.h" #include "exec/helper-proto.h" bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request) @@ -67,6 +67,11 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request) return false; } +static void do_stb(CPUAVRState *env, uint32_t addr, uint8_t data, uintptr_t ra) +{ + cpu_stb_mmuidx_ra(env, addr, data, MMU_DATA_IDX, ra); +} + void avr_cpu_do_interrupt(CPUState *cs) { CPUAVRState *env = cpu_env(cs); @@ -311,8 +316,7 @@ void helper_fullwr(CPUAVRState *env, uint32_t data, uint32_t addr) break; default: - address_space_stb(&address_space_memory, OFFSET_DATA + addr, data, - MEMTXATTRS_UNSPECIFIED, NULL); + do_stb(env, addr, data, GETPC()); break; } } -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PULL 7/9] target/avr: Use do_stb in avr_cpu_do_interrupt 2025-04-22 21:11 [PULL 0/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson ` (5 preceding siblings ...) 2025-04-22 21:11 ` [PULL 6/9] target/avr: Use cpu_stb_mmuidx_ra in helper_fullwr Richard Henderson @ 2025-04-22 21:11 ` Richard Henderson 2025-04-22 21:11 ` [PULL 8/9] hw/avr: Prepare for TARGET_PAGE_SIZE > 256 Richard Henderson ` (2 subsequent siblings) 9 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2025-04-22 21:11 UTC (permalink / raw) To: qemu-devel; +Cc: Philippe Mathieu-Daudé, Pierrick Bouvier Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/avr/helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target/avr/helper.c b/target/avr/helper.c index 7d6954ec26..f23fa3e8ba 100644 --- a/target/avr/helper.c +++ b/target/avr/helper.c @@ -88,14 +88,14 @@ void avr_cpu_do_interrupt(CPUState *cs) } if (avr_feature(env, AVR_FEATURE_3_BYTE_PC)) { - cpu_stb_data(env, env->sp--, (ret & 0x0000ff)); - cpu_stb_data(env, env->sp--, (ret & 0x00ff00) >> 8); - cpu_stb_data(env, env->sp--, (ret & 0xff0000) >> 16); + do_stb(env, env->sp--, ret, 0); + do_stb(env, env->sp--, ret >> 8, 0); + do_stb(env, env->sp--, ret >> 16, 0); } else if (avr_feature(env, AVR_FEATURE_2_BYTE_PC)) { - cpu_stb_data(env, env->sp--, (ret & 0x0000ff)); - cpu_stb_data(env, env->sp--, (ret & 0x00ff00) >> 8); + do_stb(env, env->sp--, ret, 0); + do_stb(env, env->sp--, ret >> 8, 0); } else { - cpu_stb_data(env, env->sp--, (ret & 0x0000ff)); + do_stb(env, env->sp--, ret, 0); } env->pc_w = base + vector * size; -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PULL 8/9] hw/avr: Prepare for TARGET_PAGE_SIZE > 256 2025-04-22 21:11 [PULL 0/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson ` (6 preceding siblings ...) 2025-04-22 21:11 ` [PULL 7/9] target/avr: Use do_stb in avr_cpu_do_interrupt Richard Henderson @ 2025-04-22 21:11 ` Richard Henderson 2025-04-22 21:11 ` [PULL 9/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson 2025-04-23 17:57 ` [PULL 0/9] " Stefan Hajnoczi 9 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2025-04-22 21:11 UTC (permalink / raw) To: qemu-devel; +Cc: Pierrick Bouvier If i/o does not cover the entire first page, allocate a portion of ram as an i/o device, so that the entire first page is i/o. While memory_region_init_ram_device_ptr is happy to allocate the RAMBlock, it does not register the ram for migration. Do this by hand. Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- hw/avr/atmega.h | 1 + hw/avr/atmega.c | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/hw/avr/atmega.h b/hw/avr/atmega.h index a99ee15c7e..9ac4678231 100644 --- a/hw/avr/atmega.h +++ b/hw/avr/atmega.h @@ -41,6 +41,7 @@ struct AtmegaMcuState { MemoryRegion flash; MemoryRegion eeprom; MemoryRegion sram; + MemoryRegion sram_io; DeviceState *io; AVRMaskState pwr[POWER_MAX]; AVRUsartState usart[USART_MAX]; diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c index f6844bf118..11fab184de 100644 --- a/hw/avr/atmega.c +++ b/hw/avr/atmega.c @@ -19,6 +19,7 @@ #include "hw/sysbus.h" #include "qom/object.h" #include "hw/misc/unimp.h" +#include "migration/vmstate.h" #include "atmega.h" enum AtmegaPeripheral { @@ -224,8 +225,6 @@ static void atmega_realize(DeviceState *dev, Error **errp) char *devname; size_t i; - assert(mc->io_size <= 0x200); - if (!s->xtal_freq_hz) { error_setg(errp, "\"xtal-frequency-hz\" property must be provided."); return; @@ -240,11 +239,37 @@ static void atmega_realize(DeviceState *dev, Error **errp) qdev_realize(DEVICE(&s->cpu), NULL, &error_abort); cpudev = DEVICE(&s->cpu); - /* SRAM */ - memory_region_init_ram(&s->sram, OBJECT(dev), "sram", mc->sram_size, - &error_abort); - memory_region_add_subregion(get_system_memory(), - OFFSET_DATA + mc->io_size, &s->sram); + /* + * SRAM + * + * Softmmu is not able mix i/o and ram on the same page. + * Therefore in all cases, the first page exclusively contains i/o. + * + * If the MCU's i/o region matches the page size, then we can simply + * allocate all ram starting at the second page. Otherwise, we must + * allocate some ram as i/o to complete the first page. + */ + assert(mc->io_size == 0x100 || mc->io_size == 0x200); + if (mc->io_size >= TARGET_PAGE_SIZE) { + memory_region_init_ram(&s->sram, OBJECT(dev), "sram", mc->sram_size, + &error_abort); + memory_region_add_subregion(get_system_memory(), + OFFSET_DATA + mc->io_size, &s->sram); + } else { + int sram_io_size = TARGET_PAGE_SIZE - mc->io_size; + void *sram_io_mem = g_malloc0(sram_io_size); + + memory_region_init_ram_device_ptr(&s->sram_io, OBJECT(dev), "sram-as-io", + sram_io_size, sram_io_mem); + memory_region_add_subregion(get_system_memory(), + OFFSET_DATA + mc->io_size, &s->sram_io); + vmstate_register_ram(&s->sram_io, dev); + + memory_region_init_ram(&s->sram, OBJECT(dev), "sram", + mc->sram_size - sram_io_size, &error_abort); + memory_region_add_subregion(get_system_memory(), + OFFSET_DATA + TARGET_PAGE_SIZE, &s->sram); + } /* Flash */ memory_region_init_rom(&s->flash, OBJECT(dev), -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PULL 9/9] target/avr: Increase TARGET_PAGE_BITS to 10 2025-04-22 21:11 [PULL 0/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson ` (7 preceding siblings ...) 2025-04-22 21:11 ` [PULL 8/9] hw/avr: Prepare for TARGET_PAGE_SIZE > 256 Richard Henderson @ 2025-04-22 21:11 ` Richard Henderson 2025-04-23 17:57 ` [PULL 0/9] " Stefan Hajnoczi 9 siblings, 0 replies; 11+ messages in thread From: Richard Henderson @ 2025-04-22 21:11 UTC (permalink / raw) To: qemu-devel; +Cc: Pierrick Bouvier Now that we can handle the MCU allocating only a portion of the first page to i/o, increase the page size. Choose 10 as larger than the i/o on every MCU, just so that this path is tested. Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/avr/cpu-param.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/target/avr/cpu-param.h b/target/avr/cpu-param.h index 81f3f49ee1..f5248ce9e7 100644 --- a/target/avr/cpu-param.h +++ b/target/avr/cpu-param.h @@ -21,13 +21,7 @@ #ifndef AVR_CPU_PARAM_H #define AVR_CPU_PARAM_H -/* - * TARGET_PAGE_BITS cannot be more than 8 bits because - * 1. all IO registers occupy [0x0000 .. 0x00ff] address range, and they - * should be implemented as a device and not memory - * 2. SRAM starts at the address 0x0100 - */ -#define TARGET_PAGE_BITS 8 +#define TARGET_PAGE_BITS 10 #define TARGET_PHYS_ADDR_SPACE_BITS 24 #define TARGET_VIRT_ADDR_SPACE_BITS 24 -- 2.43.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PULL 0/9] target/avr: Increase TARGET_PAGE_BITS to 10 2025-04-22 21:11 [PULL 0/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson ` (8 preceding siblings ...) 2025-04-22 21:11 ` [PULL 9/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson @ 2025-04-23 17:57 ` Stefan Hajnoczi 9 siblings, 0 replies; 11+ messages in thread From: Stefan Hajnoczi @ 2025-04-23 17:57 UTC (permalink / raw) To: Richard Henderson; +Cc: qemu-devel [-- Attachment #1: Type: text/plain, Size: 116 bytes --] Applied, thanks. Please update the changelog at https://wiki.qemu.org/ChangeLog/10.0 for any user-visible changes. [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-04-23 17:59 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-04-22 21:11 [PULL 0/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson 2025-04-22 21:11 ` [PULL 1/9] target/avr: Improve decode of LDS, STS Richard Henderson 2025-04-22 21:11 ` [PULL 2/9] target/avr: Remove OFFSET_CPU_REGISTERS Richard Henderson 2025-04-22 21:11 ` [PULL 3/9] target/avr: Add defines for i/o port registers Richard Henderson 2025-04-22 21:11 ` [PULL 4/9] target/avr: Move cpu register accesses into system memory Richard Henderson 2025-04-22 21:11 ` [PULL 5/9] target/avr: Remove NUMBER_OF_IO_REGISTERS Richard Henderson 2025-04-22 21:11 ` [PULL 6/9] target/avr: Use cpu_stb_mmuidx_ra in helper_fullwr Richard Henderson 2025-04-22 21:11 ` [PULL 7/9] target/avr: Use do_stb in avr_cpu_do_interrupt Richard Henderson 2025-04-22 21:11 ` [PULL 8/9] hw/avr: Prepare for TARGET_PAGE_SIZE > 256 Richard Henderson 2025-04-22 21:11 ` [PULL 9/9] target/avr: Increase TARGET_PAGE_BITS to 10 Richard Henderson 2025-04-23 17:57 ` [PULL 0/9] " Stefan Hajnoczi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).