Skip to content

Commit 59c1ae7

Browse files
committed
Use alternate Flash program memory (code) base for AVR targets.
This is needed because the AVR CPU has separate code and data address spaces that both start from zero. Use 0x08000000 base for Flash memory and 0x00000000 base for CPU registers, IO registers and SRAM as the fast case. Signed-off-by: Glenn Baker <[email protected]>
1 parent e714348 commit 59c1ae7

File tree

5 files changed

+76
-13
lines changed

5 files changed

+76
-13
lines changed

include/unicorn/avr.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ typedef enum uc_cpu_avr {
2424
UC_CPU_AVR_AVR6 = 6,
2525
} uc_cpu_avr;
2626

27+
//> AVR memory
28+
typedef enum uc_avr_mem {
29+
// Flash program memory (code)
30+
UC_AVR_MEM_FLASH = 0x08000000,
31+
} uc_avr_mem;
32+
2733
//> AVR registers
2834
typedef enum uc_avr_reg {
2935
UC_AVR_REG_INVALID = 0,

qemu/target/avr/cpu.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,16 @@
6161
*
6262
* It's also useful to know where some things are, like the IO registers.
6363
*/
64+
#if 1
65+
// Unicorn:
66+
#define OFFSET_CODE 0x08000000 /* UC_AVR_MEM_FLASH */
67+
#define OFFSET_DATA 0x00000000
68+
#else
6469
/* Flash program memory */
6570
#define OFFSET_CODE 0x00000000
6671
/* CPU registers, IO registers, and SRAM */
6772
#define OFFSET_DATA 0x00800000
73+
#endif
6874
/* CPU registers specifically, these are mapped at the start of data */
6975
#define OFFSET_CPU_REGISTERS OFFSET_DATA
7076
/*
@@ -107,6 +113,8 @@ typedef enum AVRFeature {
107113
AVR_FEATURE_RAMPX,
108114
AVR_FEATURE_RAMPY,
109115
AVR_FEATURE_RAMPZ,
116+
117+
AVR_FEATURE_FLASH, /* Unicorn: was Flash program memory mapped? */
110118
} AVRFeature;
111119

112120
typedef struct CPUAVRState CPUAVRState;
@@ -188,6 +196,12 @@ static inline int avr_cpu_mmu_index(CPUAVRState *env, bool ifetch)
188196
return ifetch ? MMU_CODE_IDX : MMU_DATA_IDX;
189197
}
190198

199+
static inline uint32_t avr_code_base(CPUAVRState *env)
200+
{
201+
return OFFSET_CODE && avr_feature(env, AVR_FEATURE_FLASH) ?
202+
OFFSET_CODE : 0;
203+
}
204+
191205
void avr_cpu_tcg_init(struct uc_struct *uc);
192206

193207
void avr_cpu_list(void);

qemu/target/avr/helper.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,14 @@ bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
112112

113113
if (mmu_idx == MMU_CODE_IDX) {
114114
/* access to code in flash */
115-
paddr = OFFSET_CODE + address;
115+
paddr = avr_code_base(&AVR_CPU(cs)->env) | address;
116116
prot = PAGE_READ | PAGE_EXEC;
117+
#if 0
117118
if (paddr + TARGET_PAGE_SIZE > OFFSET_DATA) {
118119
error_report("execution left flash memory");
119120
abort();
120121
}
122+
#endif
121123
} else if (address < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) {
122124
/*
123125
* access to CPU registers, exit and rebuilt this TB to use full access
@@ -129,7 +131,7 @@ bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
129131
cpu_loop_exit_restore(cs, retaddr);
130132
} else {
131133
/* access to memory. nothing special */
132-
paddr = OFFSET_DATA + address;
134+
paddr = OFFSET_DATA | address;
133135
prot = PAGE_READ | PAGE_WRITE;
134136
}
135137

@@ -326,7 +328,7 @@ target_ulong helper_fullrd(CPUAVRState *env, uint32_t addr)
326328
data = helper_inb(env, addr - NUMBER_OF_CPU_REGISTERS);
327329
} else {
328330
/* memory */
329-
data = address_space_ldub(&address_space_memory, OFFSET_DATA + addr,
331+
data = address_space_ldub(&address_space_memory, OFFSET_DATA | addr,
330332
MEMTXATTRS_UNSPECIFIED, NULL);
331333
}
332334
return data;
@@ -356,7 +358,7 @@ void helper_fullwr(CPUAVRState *env, uint32_t data, uint32_t addr)
356358
helper_outb(env, addr - NUMBER_OF_CPU_REGISTERS, data);
357359
} else {
358360
/* memory */
359-
address_space_stb(&address_space_memory, OFFSET_DATA + addr, data,
361+
address_space_stb(&address_space_memory, OFFSET_DATA | addr, data,
360362
MEMTXATTRS_UNSPECIFIED, NULL);
361363
}
362364
}

qemu/target/avr/translate.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,8 @@ static int to_regs_00_30_by_two(DisasContext *ctx, int indx)
200200

201201
static uint16_t next_word(DisasContext *ctx)
202202
{
203-
return cpu_lduw_code(ctx->env, ctx->npc++ * 2);
203+
// Unicorn:
204+
return cpu_lduw_code(ctx->env, avr_code_base(ctx->env) | (ctx->npc++ * 2));
204205
}
205206

206207
static int append_16(DisasContext *ctx, int x)
@@ -1706,6 +1707,19 @@ static void gen_data_load(DisasContext *ctx, TCGv data, TCGv addr)
17061707
}
17071708
}
17081709

1710+
static void gen_code_load(DisasContext *ctx, TCGv Rd, TCGv addr)
1711+
{
1712+
INIT_TCG_CONTEXT_FROM_DISAS(ctx);
1713+
// Unicorn:
1714+
const uint32_t code_base = avr_code_base(ctx->env);
1715+
if (code_base) {
1716+
TCGv Rc = tcg_const_i32(code_base);
1717+
tcg_gen_or_tl(addr, addr, Rc);
1718+
tcg_temp_free_i32(Rc);
1719+
}
1720+
tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
1721+
}
1722+
17091723
/*
17101724
* This instruction makes a copy of one register into another. The source
17111725
* register Rr is left unchanged, while the destination register Rd is loaded
@@ -2264,7 +2278,7 @@ static bool trans_LPM1(DisasContext *ctx, arg_LPM1 *a)
22642278

22652279
tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
22662280
tcg_gen_or_tl(addr, addr, L);
2267-
tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
2281+
gen_code_load(ctx, Rd, addr);
22682282

22692283
tcg_temp_free_i32(addr);
22702284

@@ -2285,7 +2299,7 @@ static bool trans_LPM2(DisasContext *ctx, arg_LPM2 *a)
22852299

22862300
tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
22872301
tcg_gen_or_tl(addr, addr, L);
2288-
tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
2302+
gen_code_load(ctx, Rd, addr);
22892303

22902304
tcg_temp_free_i32(addr);
22912305

@@ -2306,7 +2320,7 @@ static bool trans_LPMX(DisasContext *ctx, arg_LPMX *a)
23062320

23072321
tcg_gen_shli_tl(addr, H, 8); /* addr = H:L */
23082322
tcg_gen_or_tl(addr, addr, L);
2309-
tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
2323+
gen_code_load(ctx, Rd, addr);
23102324
tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
23112325
tcg_gen_andi_tl(L, addr, 0xff);
23122326
tcg_gen_shri_tl(addr, addr, 8);
@@ -2342,7 +2356,7 @@ static bool trans_ELPM1(DisasContext *ctx, arg_ELPM1 *a)
23422356
TCGv Rd = cpu_r[0];
23432357
TCGv addr = gen_get_zaddr();
23442358

2345-
tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
2359+
gen_code_load(ctx, Rd, addr);
23462360

23472361
tcg_temp_free_i32(addr);
23482362

@@ -2359,7 +2373,7 @@ static bool trans_ELPM2(DisasContext *ctx, arg_ELPM2 *a)
23592373
TCGv Rd = cpu_r[a->rd];
23602374
TCGv addr = gen_get_zaddr();
23612375

2362-
tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
2376+
gen_code_load(ctx, Rd, addr);
23632377

23642378
tcg_temp_free_i32(addr);
23652379

@@ -2376,7 +2390,7 @@ static bool trans_ELPMX(DisasContext *ctx, arg_ELPMX *a)
23762390
TCGv Rd = cpu_r[a->rd];
23772391
TCGv addr = gen_get_zaddr();
23782392

2379-
tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
2393+
gen_code_load(ctx, Rd, addr);
23802394
tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
23812395
gen_set_zaddr(addr);
23822396

@@ -3127,8 +3141,8 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
31273141
* b *0x100 - sets breakpoint at address 0x00800100 (data)
31283142
*/
31293143
if (unlikely(!ctx.singlestep &&
3130-
(cpu_breakpoint_test(cs, OFFSET_CODE + ctx.npc * 2, BP_ANY) ||
3131-
cpu_breakpoint_test(cs, OFFSET_DATA + ctx.npc * 2, BP_ANY)))) {
3144+
(cpu_breakpoint_test(cs, avr_code_base(env) | ctx.npc * 2, BP_ANY) ||
3145+
cpu_breakpoint_test(cs, OFFSET_DATA | ctx.npc * 2, BP_ANY)))) {
31323146
canonicalize_skip(&ctx);
31333147
tcg_gen_movi_tl(cpu_pc, ctx.npc);
31343148
gen_helper_debug(cpu_env);

qemu/target/avr/unicorn.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,31 @@ static void avr_release(void *ctx)
227227
}
228228
}
229229

230+
static inline bool is_flash_memory(hwaddr addr, size_t size, uint32_t perms)
231+
{
232+
if ((addr ^ UC_AVR_MEM_FLASH) >> 24)
233+
return false;
234+
if ((perms & UC_PROT_ALL) != (UC_PROT_READ|UC_PROT_EXEC))
235+
return false;
236+
return true;
237+
}
238+
239+
static MemoryRegion *avr_memory_map(struct uc_struct *uc, hwaddr begin, size_t size, uint32_t perms)
240+
{
241+
MemoryRegion *const mr = memory_map(uc, begin, size, perms);
242+
if (mr && is_flash_memory(begin, size, perms))
243+
set_avr_feature(&AVR_CPU(uc->cpu)->env, AVR_FEATURE_FLASH);
244+
return mr;
245+
}
246+
247+
static MemoryRegion *avr_memory_map_ptr(struct uc_struct *uc, hwaddr begin, size_t size, uint32_t perms, void *ptr)
248+
{
249+
MemoryRegion *const mr = memory_map_ptr(uc, begin, size, perms, ptr);
250+
if (mr && is_flash_memory(begin, size, perms))
251+
set_avr_feature(&AVR_CPU(uc->cpu)->env, AVR_FEATURE_FLASH);
252+
return mr;
253+
}
254+
230255
void avr_uc_init(struct uc_struct *uc)
231256
{
232257
uc->reg_read = avr_reg_read;
@@ -238,4 +263,6 @@ void avr_uc_init(struct uc_struct *uc)
238263
uc->release = avr_release;
239264
uc->cpu_context_size = offsetof(CPUAVRState, features);
240265
uc_common_init(uc);
266+
uc->memory_map = avr_memory_map;
267+
uc->memory_map_ptr = avr_memory_map_ptr;
241268
}

0 commit comments

Comments
 (0)