diff --git a/target/avr/cpu.h b/target/avr/cpu.h
index f19dd72926..7c3895b65e 100644
--- a/target/avr/cpu.h
+++ b/target/avr/cpu.h
@@ -106,6 +106,8 @@ typedef enum AVRFeature {
     AVR_FEATURE_RAMPX,
     AVR_FEATURE_RAMPY,
     AVR_FEATURE_RAMPZ,
+
+    AVR_FEATURE_LARGE_RAM,
 } AVRFeature;
 
 typedef struct CPUArchState {
diff --git a/target/avr/translate.c b/target/avr/translate.c
index 552f739b3d..40b15d116e 100644
--- a/target/avr/translate.c
+++ b/target/avr/translate.c
@@ -1542,13 +1542,17 @@ static bool trans_BRBS(DisasContext *ctx, arg_BRBS *a)
  *  M assumed to be in 0x000000ff format
  *  L assumed to be in 0x000000ff format
  */
-static void gen_set_addr(TCGv addr, TCGv H, TCGv M, TCGv L)
+static void gen_set_addr_short(TCGv addr, TCGv M, TCGv L)
 {
-
     tcg_gen_andi_tl(L, addr, 0x000000ff);
 
     tcg_gen_andi_tl(M, addr, 0x0000ff00);
     tcg_gen_shri_tl(M, M, 8);
+}
+
+static void gen_set_addr(TCGv addr, TCGv H, TCGv M, TCGv L)
+{
+    gen_set_addr_short(addr, M, L);
 
     tcg_gen_andi_tl(H, addr, 0x00ff0000);
 }
@@ -1563,9 +1567,13 @@ static void gen_set_yaddr(TCGv addr)
     gen_set_addr(addr, cpu_rampY, cpu_r[29], cpu_r[28]);
 }
 
-static void gen_set_zaddr(TCGv addr)
+static void gen_set_zaddr(DisasContext *ctx, TCGv addr, bool ram)
 {
-    gen_set_addr(addr, cpu_rampZ, cpu_r[31], cpu_r[30]);
+    if (!ram || avr_feature(ctx->env, AVR_FEATURE_LARGE_RAM)) {
+        gen_set_addr(addr, cpu_rampZ, cpu_r[31], cpu_r[30]);
+    } else {
+        gen_set_addr_short(addr, cpu_r[31], cpu_r[30]);
+    }
 }
 
 static TCGv gen_get_addr(TCGv H, TCGv M, TCGv L)
@@ -1588,9 +1596,16 @@ static TCGv gen_get_yaddr(void)
     return gen_get_addr(cpu_rampY, cpu_r[29], cpu_r[28]);
 }
 
-static TCGv gen_get_zaddr(void)
+static TCGv gen_get_zaddr(DisasContext *ctx, bool ram)
 {
-    return gen_get_addr(cpu_rampZ, cpu_r[31], cpu_r[30]);
+    if (!ram || avr_feature(ctx->env, AVR_FEATURE_LARGE_RAM)) {
+        return gen_get_addr(cpu_rampZ, cpu_r[31], cpu_r[30]);
+    } else {
+        TCGv zero = tcg_const_i32(0);
+        TCGv res = gen_get_addr(zero, cpu_r[31], cpu_r[30]);
+        tcg_temp_free_i32(zero);
+        return res;
+    }
 }
 
 /*
@@ -1868,12 +1883,12 @@ static bool trans_LDDY(DisasContext *ctx, arg_LDDY *a)
 static bool trans_LDZ2(DisasContext *ctx, arg_LDZ2 *a)
 {
     TCGv Rd = cpu_r[a->rd];
-    TCGv addr = gen_get_zaddr();
+    TCGv addr = gen_get_zaddr(ctx, true);
 
     gen_data_load(ctx, Rd, addr);
     tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
 
-    gen_set_zaddr(addr);
+    gen_set_zaddr(ctx, addr, true);
 
     tcg_temp_free_i32(addr);
 
@@ -1883,12 +1898,12 @@ static bool trans_LDZ2(DisasContext *ctx, arg_LDZ2 *a)
 static bool trans_LDZ3(DisasContext *ctx, arg_LDZ3 *a)
 {
     TCGv Rd = cpu_r[a->rd];
-    TCGv addr = gen_get_zaddr();
+    TCGv addr = gen_get_zaddr(ctx, true);
 
     tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
     gen_data_load(ctx, Rd, addr);
 
-    gen_set_zaddr(addr);
+    gen_set_zaddr(ctx, addr, true);
 
     tcg_temp_free_i32(addr);
 
@@ -1898,7 +1913,7 @@ static bool trans_LDZ3(DisasContext *ctx, arg_LDZ3 *a)
 static bool trans_LDDZ(DisasContext *ctx, arg_LDDZ *a)
 {
     TCGv Rd = cpu_r[a->rd];
-    TCGv addr = gen_get_zaddr();
+    TCGv addr = gen_get_zaddr(ctx, true);
 
     tcg_gen_addi_tl(addr, addr, a->imm); /* addr = addr + q */
     gen_data_load(ctx, Rd, addr);
@@ -2088,12 +2103,12 @@ static bool trans_STDY(DisasContext *ctx, arg_STDY *a)
 static bool trans_STZ2(DisasContext *ctx, arg_STZ2 *a)
 {
     TCGv Rd = cpu_r[a->rd];
-    TCGv addr = gen_get_zaddr();
+    TCGv addr = gen_get_zaddr(ctx, true);
 
     gen_data_store(ctx, Rd, addr);
     tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
 
-    gen_set_zaddr(addr);
+    gen_set_zaddr(ctx, addr, true);
 
     tcg_temp_free_i32(addr);
 
@@ -2103,12 +2118,12 @@ static bool trans_STZ2(DisasContext *ctx, arg_STZ2 *a)
 static bool trans_STZ3(DisasContext *ctx, arg_STZ3 *a)
 {
     TCGv Rd = cpu_r[a->rd];
-    TCGv addr = gen_get_zaddr();
+    TCGv addr = gen_get_zaddr(ctx, true);
 
     tcg_gen_subi_tl(addr, addr, 1); /* addr = addr - 1 */
     gen_data_store(ctx, Rd, addr);
 
-    gen_set_zaddr(addr);
+    gen_set_zaddr(ctx, addr, true);
 
     tcg_temp_free_i32(addr);
 
@@ -2118,7 +2133,7 @@ static bool trans_STZ3(DisasContext *ctx, arg_STZ3 *a)
 static bool trans_STDZ(DisasContext *ctx, arg_STDZ *a)
 {
     TCGv Rd = cpu_r[a->rd];
-    TCGv addr = gen_get_zaddr();
+    TCGv addr = gen_get_zaddr(ctx, true);
 
     tcg_gen_addi_tl(addr, addr, a->imm); /* addr = addr + q */
     gen_data_store(ctx, Rd, addr);
@@ -2228,7 +2243,7 @@ static bool trans_ELPM1(DisasContext *ctx, arg_ELPM1 *a)
     }
 
     TCGv Rd = cpu_r[0];
-    TCGv addr = gen_get_zaddr();
+    TCGv addr = gen_get_zaddr(ctx, false);
 
     tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
 
@@ -2244,7 +2259,7 @@ static bool trans_ELPM2(DisasContext *ctx, arg_ELPM2 *a)
     }
 
     TCGv Rd = cpu_r[a->rd];
-    TCGv addr = gen_get_zaddr();
+    TCGv addr = gen_get_zaddr(ctx, false);
 
     tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
 
@@ -2260,11 +2275,11 @@ static bool trans_ELPMX(DisasContext *ctx, arg_ELPMX *a)
     }
 
     TCGv Rd = cpu_r[a->rd];
-    TCGv addr = gen_get_zaddr();
+    TCGv addr = gen_get_zaddr(ctx, false);
 
     tcg_gen_qemu_ld8u(Rd, addr, MMU_CODE_IDX); /* Rd = mem[addr] */
     tcg_gen_addi_tl(addr, addr, 1); /* addr = addr + 1 */
-    gen_set_zaddr(addr);
+    gen_set_zaddr(ctx, addr, false);
 
     tcg_temp_free_i32(addr);
 
@@ -2402,7 +2417,7 @@ static bool trans_XCH(DisasContext *ctx, arg_XCH *a)
 
     TCGv Rd = cpu_r[a->rd];
     TCGv t0 = tcg_temp_new_i32();
-    TCGv addr = gen_get_zaddr();
+    TCGv addr = gen_get_zaddr(ctx, true);
 
     gen_data_load(ctx, t0, addr);
     gen_data_store(ctx, Rd, addr);
@@ -2432,7 +2447,7 @@ static bool trans_LAS(DisasContext *ctx, arg_LAS *a)
     }
 
     TCGv Rr = cpu_r[a->rd];
-    TCGv addr = gen_get_zaddr();
+    TCGv addr = gen_get_zaddr(ctx, true);
     TCGv t0 = tcg_temp_new_i32();
     TCGv t1 = tcg_temp_new_i32();
 
@@ -2467,7 +2482,7 @@ static bool trans_LAC(DisasContext *ctx, arg_LAC *a)
     }
 
     TCGv Rr = cpu_r[a->rd];
-    TCGv addr = gen_get_zaddr();
+    TCGv addr = gen_get_zaddr(ctx, true);
     TCGv t0 = tcg_temp_new_i32();
     TCGv t1 = tcg_temp_new_i32();
 
@@ -2502,7 +2517,7 @@ static bool trans_LAT(DisasContext *ctx, arg_LAT *a)
     }
 
     TCGv Rd = cpu_r[a->rd];
-    TCGv addr = gen_get_zaddr();
+    TCGv addr = gen_get_zaddr(ctx, true);
     TCGv t0 = tcg_temp_new_i32();
     TCGv t1 = tcg_temp_new_i32();
 
