diff --git a/target/e2k/cpu.h b/target/e2k/cpu.h index 7e4c3682ad..b4a2a33584 100644 --- a/target/e2k/cpu.h +++ b/target/e2k/cpu.h @@ -286,6 +286,88 @@ typedef struct { bool fx; } E2KWdState; +typedef enum { + AASR_NULL = 0, + AASR_READY = 1, + AASR_ACTIVE = 3, + AASR_STOPPED = 5, +} E2KAasrState; + +typedef union { + struct { + uint32_t unused : 5; + uint32_t stb : 1; + uint32_t iab : 1; + uint32_t lds : 3; + }; + uint32_t raw; +} E2KAasr; + +typedef enum { + AAD_TAG_UNV = 0, + AAD_TAG_UDT = 1, + AAD_TAG_UET = 2, + AAD_TAG_UAP = 4, + AAD_TAG_USAP = 5, + AAD_TAG_UDS = 6, +} E2KAadTag; + +typedef struct { + union { + struct { + uint64_t base : 48; + uint64_t unused1 : 6; + uint64_t tag : 3; + uint64_t mb : 1; + uint64_t ed : 1; + uint64_t rw : 2; + uint64_t unused2 : 3; + }; + uint64_t lo; + }; + union { + struct { + uint64_t unused3 : 32; + uint64_t size : 32; + }; + uint64_t hi; + }; +} E2KAad; + +typedef enum { + AALDA_EXC_EIO = 1, + AALDA_EXC_EPM = 2, + AALDA_EXC_EPMSI = 3, +} E2KAaldaExc; + +typedef union { + struct { + uint8_t exc: 2; + uint8_t cincr: 1; + uint8_t unused1: 1; + uint8_t root: 1; + uint8_t unused2: 3; + }; + uint8_t raw; +} E2KAalda; + +typedef struct { + E2KAasr sr; + uint32_t fstr; + uint64_t ldm; + uint64_t ldv; + uint32_t stis[16]; + uint32_t sti_tags; + uint32_t incrs[8]; + uint32_t incr_tags; + uint32_t inds[16]; + uint32_t ind_tags; + E2KAad ds[32]; + uint32_t ldi[64]; + E2KAalda lda[64]; +} E2KAauState; + +typedef struct { typedef struct CPUArchState { /* register file */ uint64_t regs[E2K_REG_COUNT]; /* registers */ @@ -334,6 +416,8 @@ typedef struct CPUArchState { uint32_t fpcr; // Floating point control register (FPCR) uint32_t fpsr; // Floating point state register (FPSR) + E2KAauState aau; + int interrupt_index; uint32_t is_bp; /* breakpoint flag */ int syscall_wbs; // FIXME: temp for syscall diff --git a/target/e2k/gdbstub.c b/target/e2k/gdbstub.c index f808fbdd80..db63c7ccee 100644 --- a/target/e2k/gdbstub.c +++ b/target/e2k/gdbstub.c @@ -90,42 +90,42 @@ int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) if (76 <= n && n < 140) { if (n & 1) { - return gdb_get_reg64(mem_buf, 0); // addN_hi + return gdb_get_reg64(mem_buf, env->aau.ds[n - 76].hi); // addN_hi } else { - return gdb_get_reg64(mem_buf, 0); // addN_lo + return gdb_get_reg64(mem_buf, env->aau.ds[n - 76].lo); // addN_lo } } if (140 <= n && n < 156) { - return gdb_get_reg64(mem_buf, 0); // aaindN + return gdb_get_reg64(mem_buf, env->aau.inds[n - 140]); // aaindN } if (156 <= n && n < 164) { - return gdb_get_reg64(mem_buf, 0); // aaincrN + return gdb_get_reg64(mem_buf, env->aau.incrs[n - 156]); // aaincrN } if (164 <= n && n < 228) { - return gdb_get_reg64(mem_buf, 0); // aaldiN + return gdb_get_reg64(mem_buf, env->aau.ldi[n - 164]); // aaldiN } if (n == 228) { - return gdb_get_reg64(mem_buf, 0); // aaldv + return gdb_get_reg64(mem_buf, env->aau.ldv); // aaldv } if (229 <= n && n < 293) { - return gdb_get_reg64(mem_buf, 0); // aaldaN + return gdb_get_reg64(mem_buf, env->aau.lda[n - 229].raw); // aaldaN } switch (n) { - case 293: return gdb_get_reg64(mem_buf, 0); // aaldm - case 294: return gdb_get_reg64(mem_buf, 0); // aasr - case 295: return gdb_get_reg64(mem_buf, 0); // aafstr + case 293: return gdb_get_reg64(mem_buf, env->aau.ldm); // aaldm + case 294: return gdb_get_reg64(mem_buf, env->aau.sr.raw); // aasr + case 295: return gdb_get_reg64(mem_buf, env->aau.fstr); // aafstr default: break; } if (296 <= n && n < 312) { - return gdb_get_reg64(mem_buf, 0); // aastiN + return gdb_get_reg64(mem_buf, env->aau.stis[n - 296]); // aastiN } switch (n) { diff --git a/target/e2k/helper.h b/target/e2k/helper.h index ae10b2fa09..ae59aeb94d 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -16,3 +16,9 @@ DEF_HELPER_2(setwd, void, env, i32) DEF_HELPER_2(probe_read_access, int, env, tl) DEF_HELPER_2(probe_write_access, int, env, tl) DEF_HELPER_3(packed_shuffle_i64, i64, i64, i64, i64) +DEF_HELPER_4(set_aad_i64, void, env, i64, int, int) +DEF_HELPER_4(set_aad_i32, void, env, i32, int, int) +DEF_HELPER_3(set_aasti_i64, void, env, i64, int) +DEF_HELPER_3(set_aasti_i32, void, env, i32, int) +DEF_HELPER_7(staa_i64, void, env, i64, i32, int, int, int, int) +DEF_HELPER_7(staa_i32, void, env, i32, i32, int, int, int, int) diff --git a/target/e2k/helper_aau.c b/target/e2k/helper_aau.c new file mode 100644 index 0000000000..3b56ad2fda --- /dev/null +++ b/target/e2k/helper_aau.c @@ -0,0 +1,64 @@ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "cpu.h" +#include "exec/exec-all.h" +#include "qemu/host-utils.h" +#include "exec/helper-proto.h" + +void HELPER(set_aad_i64)(CPUE2KState *env, uint64_t src4, int incr, int d) +{ + assert(d < 32); + + // FIXME: What register default values should be? + env->aau.ds[d].lo = 0; + env->aau.ds[d].hi = 0; + + env->aau.ds[d].base = extract64(src4, 0, 48); + env->aau.ds[d].rw = 3; + env->aau.incrs[incr] = 1; +} + +void HELPER(set_aad_i32)(CPUE2KState *env, uint32_t src4, int incr, int d) +{ + assert(d < 32); + + // FIXME: What register default values should be? + env->aau.ds[d].lo = 0; + env->aau.ds[d].hi = 0; + + env->aau.ds[d].base = src4; + env->aau.ds[d].rw = 3; + env->aau.incrs[incr] = 1; +} + +void HELPER(set_aasti_i64)(CPUE2KState *env, uint64_t src4, int ind) +{ + assert(ind < 16); + env->aau.stis[ind] = src4; +} + +void HELPER(set_aasti_i32)(CPUE2KState *env, uint32_t src4, int ind) +{ + assert(ind < 16); + env->aau.stis[ind] = src4; +} + +void HELPER(staa_i64)(CPUE2KState *env, uint64_t src4, uint32_t lit, int am, + int incr, int ind, int d) +{ + abi_ulong ptr = env->aau.ds[d].base + env->aau.stis[ind] + lit; + cpu_stq_le_data_ra(env, ptr, src4, GETPC()); + if (am) { + env->aau.stis[ind] += env->aau.incrs[incr] * 8; + } +} + +void HELPER(staa_i32)(CPUE2KState *env, uint32_t src4, uint32_t lit, int am, + int incr, int ind, int d) +{ + abi_ulong ptr = env->aau.ds[d].base + env->aau.stis[ind] + lit; + cpu_stl_le_data_ra(env, ptr, src4, GETPC()); + if (am) { + env->aau.stis[ind] += env->aau.incrs[incr] * 4; + } +} diff --git a/target/e2k/meson.build b/target/e2k/meson.build index 6eb1ed13d1..dc29367042 100644 --- a/target/e2k/meson.build +++ b/target/e2k/meson.build @@ -6,6 +6,7 @@ e2k_ss.add(files( 'helper_int.c', 'helper_sm.c', 'helper_vec.c', + 'helper_aau.c', 'translate.c', 'translate/state.c', 'translate/control.c', diff --git a/target/e2k/translate/alc.c b/target/e2k/translate/alc.c index 7c7dcd759b..0b5d80e9d8 100644 --- a/target/e2k/translate/alc.c +++ b/target/e2k/translate/alc.c @@ -1020,6 +1020,109 @@ static void gen_ld(DisasContext *ctx, int chan, MemOp memop) tcg_temp_free_i64(t0); } +static void gen_staa_i64(DisasContext *ctx, int chan) +{ + uint32_t als = ctx->bundle.als[chan]; + uint8_t mas = ctx->mas[chan]; + bool sm = extract32(als, 31, 1); + int lit = extract32(als, 8, 2); + int am = extract32(als, 10, 1); + int incr = extract32(als, 12, 3); + int ind = extract32(als, 15, 4); + int d = extract32(als, 19, 5); + Src64 s4 = get_src4_i64(ctx, chan); + TCGv_i32 t0 = tcg_const_i32(am); + TCGv_i32 t1 = tcg_const_i32(incr); + TCGv_i32 t2 = tcg_const_i32(ind); + TCGv_i32 t3 = tcg_const_i32(d); + TCGv_i32 t4; + + if (lit) { + if (!ctx->bundle.lts_present[lit - 1]) { + e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPN); + return; + } + t4 = tcg_const_i32(ctx->bundle.lts[lit - 1]); + } else { + t4 = tcg_const_i32(0); + } + + if (sm) { + qemu_log_mask(LOG_UNIMP, "staad: sm is not implemented\n"); + abort(); + } + + if (mas == 0) { + gen_helper_staa_i64(cpu_env, s4.value, t4, t0, t1, t2, t3); + } else if (mas == 0x3f) { + if (!am) { + gen_helper_set_aad_i64(cpu_env, s4.value, t1, t3); + } else { + gen_helper_set_aasti_i64(cpu_env, s4.value, t2); + } + } else { + qemu_log_mask(LOG_UNIMP, "staad: not implemented mas\n"); + abort(); + } + + tcg_temp_free_i32(t4); + tcg_temp_free_i32(t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); +} +static void gen_staa_i32(DisasContext *ctx, int chan) +{ + uint32_t als = ctx->bundle.als[chan]; + uint8_t mas = ctx->mas[chan]; + bool sm = extract32(als, 31, 1); + int lit = extract32(als, 8, 2); + int am = extract32(als, 10, 1); + int incr = extract32(als, 12, 3); + int ind = extract32(als, 15, 4); + int d = extract32(als, 19, 5); + Src32 s4 = get_src4_i32(ctx, chan); + TCGv_i32 t0 = tcg_const_i32(am); + TCGv_i32 t1 = tcg_const_i32(incr); + TCGv_i32 t2 = tcg_const_i32(ind); + TCGv_i32 t3 = tcg_const_i32(d); + TCGv_i32 t4; + + if (lit) { + if (!ctx->bundle.lts_present[lit - 1]) { + e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPN); + return; + } + t4 = tcg_const_i32(ctx->bundle.lts[lit - 1]); + } else { + t4 = tcg_const_i32(0); + } + + if (sm) { + qemu_log_mask(LOG_UNIMP, "staaw: sm is not implemented\n"); + abort(); + } + + if (mas == 0) { + gen_helper_staa_i32(cpu_env, s4.value, t4, t0, t1, t2, t3); + } else if (mas == 0x3f) { + if (!am) { + gen_helper_set_aad_i32(cpu_env, s4.value, t1, t3); + } else { + gen_helper_set_aasti_i32(cpu_env, s4.value, t2); + } + } else { + qemu_log_mask(LOG_UNIMP, "staaw: not implemented mas\n"); + abort(); + } + + tcg_temp_free_i32(t4); + tcg_temp_free_i32(t3); + tcg_temp_free_i32(t2); + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); +} + static void gen_st(DisasContext *ctx, int chan, MemOp memop) { bool sm = GET_BIT(ctx->bundle.als[chan], 31); @@ -1452,31 +1555,18 @@ static void execute_ext_01_25(DisasContext *ctx, int chan) { uint8_t opc = GET_FIELD(ctx->bundle.als[chan], 24, 7); + if (chan != 2 && chan != 5) { + e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC); + return; + } + switch(opc) { - case 0x08: if (chan == 2 || chan == 5) { - gen_gettag_i32(ctx, chan); /* gettags */ - } else { - e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC); - } - break; - case 0x09: if (chan == 2 || chan == 5) { - gen_gettag_i64(ctx, chan); /* gettagd */ - } else { - e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC); - } - break; - case 0x0a: if (chan == 2 || chan == 5) { - gen_puttag_i32(ctx, chan); /* puttags */ - } else { - e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC); - } - break; - case 0x0b: if (chan == 2 || chan == 5) { - gen_puttag_i64(ctx, chan); /* puttagd */ - } else { - e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC); - } - break; + case 0x08: gen_gettag_i32(ctx, chan); break; /* gettags */ + case 0x09: gen_gettag_i64(ctx, chan); break; /* gettagd */ + case 0x0a: gen_puttag_i32(ctx, chan); break; /* puttags */ + case 0x0b: gen_puttag_i64(ctx, chan); break; /* puttagd */ + case 0x1e: gen_staa_i32(ctx, chan); break; /* staaw */ + case 0x1f: gen_staa_i64(ctx, chan); break; /* staad */ default: e2k_tr_gen_exception(ctx, E2K_EXCP_ILLOPC); break;