e2k: Implement basic v5 support.

Add gdb xml files for e2k.
Tags are partially disabled for better performance.

Signed-off-by: Denis Drakhnya <numas13@gmail.com>
e2k
Denis Drakhnia 2 years ago committed by Denis Drakhnia
parent 6fb98e718e
commit 8f4de9d485
  1. 1
      configs/targets/e2k-linux-user.mak
  2. 1
      configs/targets/e2k32-linux-user.mak
  3. 2464
      gdb-xml/e2k-v1.xml
  4. 6
      gdb-xml/e2k-v2.xml
  5. 6
      gdb-xml/e2k-v3.xml
  6. 86
      gdb-xml/e2k-v5.xml
  7. 2
      include/exec/poison.h
  8. 56
      linux-user/e2k/syscall_nr.h
  9. 1726
      target/e2k/alops.inc
  10. 3
      target/e2k/cpu.c
  11. 44
      target/e2k/cpu.h
  12. 75
      target/e2k/gdbstub.c
  13. 61
      target/e2k/helper.c
  14. 40
      target/e2k/helper.h
  15. 2
      target/e2k/helper_int.c
  16. 190
      target/e2k/helper_vec.c
  17. 3734
      target/e2k/translate.c

@ -1 +1,2 @@
TARGET_ARCH=e2k
TARGET_XML_FILES= gdb-xml/e2k-v1.xml gdb-xml/e2k-v2.xml gdb-xml/e2k-v3.xml gdb-xml/e2k-v5.xml

@ -2,3 +2,4 @@ TARGET_ARCH=e2k32
TARGET_BASE_ARCH=e2k
TARGET_ABI_DIR=e2k
TARGET_ABI32=y
TARGET_XML_FILES= gdb-xml/e2k-v1.xml gdb-xml/e2k-v2.xml gdb-xml/e2k-v3.xml gdb-xml/e2k-v5.xml

File diff suppressed because it is too large Load Diff

@ -0,0 +1,6 @@
<feature name="org.mcst.gdb.elbrus-v2.linux">
<!-- 840 -->
<reg name="idr" bitsize="64" type="uint64"/>
</feature>

@ -0,0 +1,6 @@
<feature name="org.mcst.gdb.elbrus-v3.linux">
<!-- 841 -->
<reg name="core_mode" bitsize="64" type="uint64"/>
</feature>

@ -0,0 +1,86 @@
<feature name="org.mcst.gdb.elbrus-v5.linux">
<!-- This type seems to be common for %lsr1 and %ilcr1 -->
<!-- lsr1 -->
<struct id="lsr1_bits" size="8">
<field name="lcnt_lo" start="0" end="31"/>
<field name="lcnt_hi" start="32" end="63"/>
</struct>
<union id="lsr1">
<field name="dword" type="uint64"/>
<field name="" type="lsr1_bits"/>
</union>
<reg name="lsr1" bitsize="64" type="lsr1"/>
<reg name="ilcr1" bitsize="64" type="lsr1"/>
<reg name="_gext_v5_0" bitsize="16" type="uint64"/>
<reg name="_gext_v5_1" bitsize="16" type="uint64"/>
<reg name="_gext_v5_2" bitsize="16" type="uint64"/>
<reg name="_gext_v5_3" bitsize="16" type="uint64"/>
<reg name="_gext_v5_4" bitsize="16" type="uint64"/>
<reg name="_gext_v5_5" bitsize="16" type="uint64"/>
<reg name="_gext_v5_6" bitsize="16" type="uint64"/>
<reg name="_gext_v5_7" bitsize="16" type="uint64"/>
<reg name="_gext_v5_8" bitsize="16" type="uint64"/>
<reg name="_gext_v5_9" bitsize="16" type="uint64"/>
<reg name="_gext_v5_10" bitsize="16" type="uint64"/>
<reg name="_gext_v5_11" bitsize="16" type="uint64"/>
<reg name="_gext_v5_12" bitsize="16" type="uint64"/>
<reg name="_gext_v5_13" bitsize="16" type="uint64"/>
<reg name="_gext_v5_14" bitsize="16" type="uint64"/>
<reg name="_gext_v5_15" bitsize="16" type="uint64"/>
<reg name="_gext_v5_16" bitsize="16" type="uint64"/>
<reg name="_gext_v5_17" bitsize="16" type="uint64"/>
<reg name="_gext_v5_18" bitsize="16" type="uint64"/>
<reg name="_gext_v5_19" bitsize="16" type="uint64"/>
<reg name="_gext_v5_20" bitsize="16" type="uint64"/>
<reg name="_gext_v5_21" bitsize="16" type="uint64"/>
<reg name="_gext_v5_22" bitsize="16" type="uint64"/>
<reg name="_gext_v5_23" bitsize="16" type="uint64"/>
<reg name="_gext_v5_24" bitsize="16" type="uint64"/>
<reg name="_gext_v5_25" bitsize="16" type="uint64"/>
<reg name="_gext_v5_26" bitsize="16" type="uint64"/>
<reg name="_gext_v5_27" bitsize="16" type="uint64"/>
<reg name="_gext_v5_28" bitsize="16" type="uint64"/>
<reg name="_gext_v5_29" bitsize="16" type="uint64"/>
<reg name="_gext_v5_30" bitsize="16" type="uint64"/>
<reg name="_gext_v5_31" bitsize="16" type="uint64"/>
<reg name="_gtag_v5_0" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_1" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_2" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_3" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_4" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_5" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_6" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_7" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_8" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_9" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_10" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_11" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_12" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_13" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_14" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_15" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_16" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_17" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_18" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_19" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_20" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_21" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_22" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_23" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_24" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_25" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_26" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_27" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_28" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_29" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_30" bitsize="8" type="uint8"/>
<reg name="_gtag_v5_31" bitsize="8" type="uint8"/>
</feature>

@ -13,6 +13,8 @@
#pragma GCC poison TARGET_ARM
#pragma GCC poison TARGET_CRIS
#pragma GCC poison TARGET_HEXAGON
#pragma GCC poison TARGET_E2K
#pragma GCC poison TARGET_E2K32
#pragma GCC poison TARGET_HPPA
#pragma GCC poison TARGET_LOONGARCH64
#pragma GCC poison TARGET_M68K

@ -399,7 +399,59 @@
#define TARGET_NR_process_vm_readv 380
#define TARGET_NR_process_vm_writev 381
#define TARGET_NR_kcmp 382
#define TARGET_NR_finit_module 383
#define TARGET_NR_syscalls 384
#define TARGET_NR_finit_module 383
#define TARGET_NR_renameat2 384
#define TARGET_NR_getrandom 385
#define TARGET_NR_memfd_create 386
#define TARGET_NR_bpf 387
#define TARGET_NR_execveat 388
#define TARGET_NR_userfaultfd 389
#define TARGET_NR_membarrier 390
#define TARGET_NR_mlock2 391
#define TARGET_NR_seccomp 392
#define TARGET_NR_shutdown 393
#define TARGET_NR_copy_file_range 394
#define TARGET_NR_preadv2 395
#define TARGET_NR_pwritev2 396
#define TARGET_NR_pkey_mprotect 397
#define TARGET_NR_pkey_alloc 398
#define TARGET_NR_pkey_free 399
#define TARGET_NR_name_to_handle_at 400
#define TARGET_NR_open_by_handle_at 401
#define TARGET_NR_statx 402
/* added for compatibility with x86_64 */
#define TARGET_NR_socket 403
#define TARGET_NR_connect 404
#define TARGET_NR_accept 405
#define TARGET_NR_sendto 406
#define TARGET_NR_recvfrom 407
#define TARGET_NR_sendmsg 408
#define TARGET_NR_recvmsg 409
#define TARGET_NR_bind 410
#define TARGET_NR_listen 411
#define TARGET_NR_getsockname 412
#define TARGET_NR_getpeername 413
#define TARGET_NR_socketpair 414
#define TARGET_NR_setsockopt 415
#define TARGET_NR_getsockopt 416
/* free (unused) entries - reserve 417 - 418 */
/* TODO: #define TARGET_NR_arch_prctl 419 */
/* added for combability of protected system calls v1-v5 & v6 */
#define TARGET_NR_newuselib 420
#define TARGET_NR_rt_sigaction_ex 421
/* protected Mode specific memory allocation syscall number */
#define TARGET_NR_get_mem 422
#define TARGET_NR_free_mem 423
/* protected mode specific clean memory from old invalid descriptors */
#define TARGET_NR_clean_descriptors 424
/* protected mode specific unloading module from memory */
#define TARGET_NR_unuselib 425
#define TARGET_NR_clone3 426
#define TARGET_NR_fsopen 427
#define TARGET_NR_fsconfig 428
#define TARGET_NR_fsmount 429
#define TARGET_NR_fspick 430
#define TARGET_syscalls 431
#endif /* E2K_SYSCALL_NR_H */

File diff suppressed because it is too large Load Diff

@ -238,6 +238,8 @@ static void e2k_cpu_realizefn(DeviceState *dev, Error **errp)
return;
}
e2k_cpu_register_gdb_regs_for_features(cs);
qemu_init_vcpu(cs);
ecc->parent_realize(dev, errp);
@ -291,6 +293,7 @@ static void e2k_cpu_class_init(ObjectClass *oc, void *data)
cc->class_by_name = e2k_cpu_class_by_name;
cc->disas_set_info = cpu_e2k_disas_set_info;
cc->gdb_core_xml_file = "e2k-v1.xml";
cc->gdb_arch_name = e2k_cpu_gdb_arch_name;
cc->gdb_read_register = e2k_cpu_gdb_read_register;
cc->gdb_write_register = e2k_cpu_gdb_write_register;

@ -28,6 +28,8 @@ void e2k_tcg_initialize(void);
*/
#define E2K_FORCE_FX true
//#define E2K_TAGS_ENABLE
#define GEN_MASK(start, len) (((1UL << (len)) - 1) << (start))
#define GET_BIT(v, index) (((v) >> (index)) & 1)
@ -55,12 +57,17 @@ void e2k_tcg_initialize(void);
typedef enum {
E2K_TAG_NUMBER32 = 0,
E2K_TAG_NUMBER64 = 0,
E2K_TAG_NON_NUMBER32 = 1,
E2K_TAG_NON_NUMBER64 = 5,
E2K_TAG_NUMBER80 = 0,
E2K_TAG_NUMBER128 = 0,
E2K_TAG_NON_NUMBER32 = 0x01,
E2K_TAG_NON_NUMBER64 = 0x05,
E2K_TAG_NON_NUMBER80 = 0x05,
E2K_TAG_NON_NUMBER128 = 0x55,
} E2kRegisterTag;
#define E2K_MOVA_RESULT_INVALID 0xeaed0f70eaed0f70
#define E2K_LD_RESULT_INVALID 0x0afafafa0afafafa
#define E2K_LD_RESULT_INVALID 0x4afafafa4afafafa
#define CRS_SIZE (sizeof(E2KCrs))
@ -689,14 +696,17 @@ typedef union {
uint32_t u32;
uint64_t u64;
floatx80 f80;
uint8_t u8v[16];
uint16_t u16v[8];
uint32_t u32v[4];
uint64_t u64v[2];
int8_t i8v[16];
int16_t i16v[8];
int32_t i32v[4];
int64_t i64v[2];
uint8_t ub[16];
uint16_t uh[8];
uint32_t uw[4];
uint64_t ud[2];
int8_t sb[16];
int16_t sh[8];
int32_t sw[4];
int64_t sd[2];
struct {
uint64_t lo;
uint64_t hi;
@ -714,7 +724,7 @@ typedef struct CPUArchState {
E2KReg t0, t1, t2, t3;
E2KReg tmp[8];
E2KReg al_result[6];
E2KReg al_result[16];
/* DAM */
E2KDamEntry dam[32];
@ -731,7 +741,7 @@ typedef struct CPUArchState {
/* loop status register */
uint64_t lsr;
uint32_t lsr_lcnt;
uint64_t lsr_lcnt;
uint32_t lsr_ecnt;
uint32_t lsr_vlc;
uint32_t lsr_over;
@ -763,7 +773,8 @@ typedef struct CPUArchState {
/* internal use */
uint32_t is_bp; /* breakpoint flag */
uint64_t last_value; /* ld mas=7 + st mas=2 */
uint64_t last_val0; /* ld mas=7 + st mas=2 */
uint64_t last_val1; /* ld mas=7 + st mas=2 */
/* zeroing upper register half for 32-bit instructions */
uint32_t wdbl;
@ -815,6 +826,7 @@ void e2k_cpu_list(void);
int e2k_cpu_signal_handler(int host_signum, void *pinfo, void *puc);
int e2k_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n);
int e2k_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n);
void e2k_cpu_register_gdb_regs_for_features(CPUState *cs);
bool e2k_cpu_tlb_fill(CPUState *cpu, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
@ -882,7 +894,7 @@ static inline uint32_t e2k_state_br(CPUE2KState *env)
ret = deposit32(ret, BR_RSZ_OFF, BR_RSZ_LEN, bn->size / 2 - 1);
ret = deposit32(ret, BR_RCUR_OFF, BR_RCUR_LEN, bn->cur / 2);
ret = deposit32(ret, BR_PSZ_OFF, BR_PSZ_LEN, bp->size);
ret = deposit32(ret, BR_PSZ_OFF, BR_PSZ_LEN, bp->size - 1);
ret = deposit32(ret, BR_PCUR_OFF, BR_PCUR_LEN, bp->cur);
return ret;
@ -897,7 +909,7 @@ static inline void e2k_state_br_set(CPUE2KState *env, uint32_t br)
bn->size = extract32(br, BR_RSZ_OFF, BR_RSZ_LEN) * 2 + 2;
bn->cur = extract32(br, BR_RCUR_OFF, BR_RCUR_LEN) * 2;
bp->size = extract32(br, BR_PSZ_OFF, BR_PSZ_LEN);
bp->size = extract32(br, BR_PSZ_OFF, BR_PSZ_LEN) + 1;
bp->cur = extract32(br, BR_PCUR_OFF, BR_PCUR_LEN);
}

@ -295,3 +295,78 @@ int e2k_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
// TODO: e2k_cpu_gdb_write_register
return 0;
}
static int gdb_get_v2(CPUE2KState *env, GByteArray *buf, int n)
{
if (n == 0) {
/* idr */
return gdb_get_reg64(buf, env->idr);
}
return 0;
}
static int gdb_set_v2(CPUE2KState *env, uint8_t *mem_buf, int n)
{
fprintf(stderr, "%s: unknown register %d\n", __FUNCTION__, n);
return 0;
}
static int gdb_get_v3(CPUE2KState *env, GByteArray *buf, int n)
{
if (n == 0) {
/* TODO: core_mode */
return gdb_get_reg64(buf, 0);
}
return 0;
}
static int gdb_set_v3(CPUE2KState *env, uint8_t *mem_buf, int n)
{
fprintf(stderr, "%s: unknown register %d\n", __FUNCTION__, n);
return 0;
}
static int gdb_get_v5(CPUE2KState *env, GByteArray *buf, int n)
{
if (n == 0) {
return gdb_get_reg64(buf, env->lsr_lcnt);
} else if (n == 1) {
// TODO: ilcr1
return gdb_get_reg64(buf, 0);
} else if (n >= 2 && n < 34) {
return gdb_get_reg64(buf, env->regs[E2K_NR_COUNT + n - 2].hi);
} else if (n >= 34 && n < 66) {
return gdb_get_reg8(buf, env->tags[E2K_NR_COUNT + n - 34]);
}
return 0;
}
static int gdb_set_v5(CPUE2KState *env, uint8_t *mem_buf, int n)
{
fprintf(stderr, "%s: unknown register %d\n", __FUNCTION__, n);
return 0;
}
void e2k_cpu_register_gdb_regs_for_features(CPUState *cs)
{
E2KCPU *cpu = E2K_CPU(cs);
CPUE2KState *env = &cpu->env;
if (env->version >= 2) {
gdb_register_coprocessor(cs, gdb_get_v2, gdb_set_v2,
1, "e2k-v2.xml", 574);
}
if (env->version >= 3) {
gdb_register_coprocessor(cs, gdb_get_v3, gdb_set_v3,
1, "e2k-v3.xml", 575);
}
if (env->version >= 5) {
gdb_register_coprocessor(cs, gdb_get_v5, gdb_set_v5,
66, "e2k-v5.xml", 576);
}
}

@ -23,7 +23,9 @@ static inline void ps_push(CPUE2KState *env, uint64_t value, uint8_t tag)
#endif
cpu_stq_le_data(env, env->psp.base + env->psp.index, value);
#ifdef E2K_TAGS_ENABLE
cpu_stb_data(env, env->psp.base_tag + env->psp.index / 8, tag);
#endif
env->psp.index += 8;
}
@ -34,20 +36,37 @@ static inline uint64_t ps_pop(CPUE2KState *env, uint8_t *ret_tag)
}
env->psp.index -= 8;
if (ret_tag != NULL) {
#ifdef E2K_TAGS_ENABLE
*ret_tag = cpu_ldub_data(env, env->psp.base_tag + env->psp.index / 8);
#else
*ret_tag = 0;
#endif
}
return cpu_ldq_le_data(env, env->psp.base + env->psp.index);
}
static void ps_spill(CPUE2KState *env, int n, bool fx)
{
int i;
for (i = 0; i < n; i += 2) {
ps_push(env, env->regs[i + 0].lo, env->tags[i]);
ps_push(env, env->regs[i + 1].lo, env->tags[i + 1]);
if (fx || E2K_FORCE_FX) {
ps_push(env, env->regs[i + 0].hi, 0);
ps_push(env, env->regs[i + 1].hi, 0);
if (env->version >= 5) {
for (i = 0; i < n; i++) {
ps_push(env, env->regs[i].lo, env->tags[i]);
if (fx || E2K_FORCE_FX) {
ps_push(env, env->regs[i].hi, 0);
}
}
} else{
for (i = 0; i < n; i += 2) {
E2KReg r0 = env->regs[i + 0];
E2KReg r1 = env->regs[i + 1];
ps_push(env, r0.lo, env->tags[i]);
ps_push(env, r1.lo, env->tags[i + 1]);
if (fx || E2K_FORCE_FX) {
ps_push(env, r0.hi, 0);
ps_push(env, r1.hi, 0);
}
}
}
}
@ -55,20 +74,34 @@ static void ps_spill(CPUE2KState *env, int n, bool fx)
static void ps_fill(CPUE2KState *env, int n, bool fx)
{
int i;
for (i = n; i > 0; i -= 2) {
if (fx || E2K_FORCE_FX) {
env->regs[i - 1].hi = ps_pop(env, NULL);
env->regs[i - 2].hi = ps_pop(env, NULL);
if (env->version >= 5) {
for (i = n; i-- > 0;) {
if (fx || E2K_FORCE_FX) {
env->regs[i].hi = ps_pop(env, NULL);
}
env->regs[i].lo = ps_pop(env, &env->tags[i]);
}
} else {
for (i = n; i > 0; i -= 2) {
E2KReg *r0 = &env->regs[i - 1];
E2KReg *r1 = &env->regs[i - 2];
if (fx || E2K_FORCE_FX) {
r0->hi = ps_pop(env, NULL);
r1->hi = ps_pop(env, NULL);
}
r0->lo = ps_pop(env, &env->tags[i - 1]);
r1->lo = ps_pop(env, &env->tags[i - 2]);
}
env->regs[i - 1].lo = ps_pop(env, &env->tags[i - 1]);
env->regs[i - 2].lo = ps_pop(env, &env->tags[i - 2]);
}
}
static void move_regs(CPUE2KState *env, int dst, int src, int n)
{
memmove(&env->regs[dst], &env->regs[src], n * sizeof(env->regs[0]));
#ifdef E2K_TAGS_ENABLE
memmove(&env->tags[dst], &env->tags[src], n * sizeof(env->tags[0]));
#endif
}
static void callee_window(CPUE2KState *env, int base, int size, bool fx)
@ -293,10 +326,12 @@ void HELPER(setwd)(CPUE2KState *env, int wsz, int nfx, int dbl)
if (diff > 0) {
// FIXME: zeroing registers is not needed, but useful for debugging
#if 1
#if 0
memset(&env->regs[env->wd.size], 0, diff * sizeof(env->regs[0]));
#endif
#ifdef E2K_TAGS_ENABLE
memset(&env->tags[env->wd.size], E2K_TAG_NON_NUMBER64, diff);
#endif
}
env->wd.size = size;

@ -1,12 +1,10 @@
// TODO: set helper call flags
#define dh_alias_Reg ptr
#define dh_alias_vec ptr
#define dh_alias_f80 ptr
#define dh_ctype_Reg E2KReg *
#define dh_ctype_vec E2KReg *
#define dh_ctype_f80 floatx80 *
#define dh_typecode_Reg dh_typecode_ptr
#define dh_typecode_vec dh_typecode_ptr
#define dh_typecode_f80 dh_typecode_ptr
#define dh_is_signed_Reg dh_is_signed_ptr
#define dh_is_signed_vec dh_is_signed_ptr
#define dh_is_signed_f80 dh_is_signed_ptr
DEF_HELPER_2(raise_exception, noreturn, env, int)
@ -67,11 +65,19 @@ DEF_HELPER_FLAGS_2(phaddh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(phaddw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(phaddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_3(qphaddh, TCG_CALL_NO_RWG, void, vec, vec, vec)
DEF_HELPER_FLAGS_3(qphaddw, TCG_CALL_NO_RWG, void, vec, vec, vec)
DEF_HELPER_FLAGS_3(qphaddsh, TCG_CALL_NO_RWG, void, vec, vec, vec)
/* Packed Horizontal Sub */
DEF_HELPER_FLAGS_2(phsubh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(phsubw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(phsubsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_3(qphsubh, TCG_CALL_NO_RWG, void, vec, vec, vec)
DEF_HELPER_FLAGS_3(qphsubw, TCG_CALL_NO_RWG, void, vec, vec, vec)
DEF_HELPER_FLAGS_3(qphsubsh, TCG_CALL_NO_RWG, void, vec, vec, vec)
/* Packed Add using saturation */
DEF_HELPER_FLAGS_2(paddsb, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(paddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
@ -87,8 +93,10 @@ DEF_HELPER_FLAGS_2(psubush, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed shifts */
DEF_HELPER_FLAGS_2(psllh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(psllw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(pslld, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(psrlh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(psrlw, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(psrld, TCG_CALL_NO_RWG_SE, i64, i64, i64)
/* Packed shifts with sign */
DEF_HELPER_FLAGS_2(psrah, TCG_CALL_NO_RWG_SE, i64, i64, i64)
@ -141,6 +149,14 @@ DEF_HELPER_FLAGS_2(phminposuh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_2(mpsadbh, TCG_CALL_NO_RWG_SE, i64, i64, i64)
DEF_HELPER_FLAGS_4(plog, TCG_CALL_NO_RWG_SE, i64, i32, i64, i64, i64)
DEF_HELPER_FLAGS_3(qpmpsadbh, TCG_CALL_NO_RWG, void, vec, vec, i32)
DEF_HELPER_FLAGS_3(qpmulubhh, TCG_CALL_NO_RWG, void, vec, i64, vec)
DEF_HELPER_FLAGS_2(qphminposuh, TCG_CALL_NO_RWG_SE, i64, vec, vec)
DEF_HELPER_FLAGS_1(qpsgn2mskb, TCG_CALL_NO_RWG_SE, i32, vec)
DEF_HELPER_FLAGS_3(qpmsk2sgnb, TCG_CALL_NO_RWG, void, vec, vec, i32)
DEF_HELPER_FLAGS_4(qppermb, TCG_CALL_NO_RWG, void, vec, vec, vec, vec)
DEF_HELPER_FLAGS_4(qpshufb, TCG_CALL_NO_RWG, void, vec, vec, vec, vec)
/* Float 32/64 Ops */
DEF_HELPER_FLAGS_3(fadds, TCG_CALL_NO_RWG, i32, env, i32, i32)
DEF_HELPER_FLAGS_3(fsubs, TCG_CALL_NO_RWG, i32, env, i32, i32)
@ -172,12 +188,24 @@ DEF_HELPER_FLAGS_3(pfmins, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(pfhadds, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(pfhsubs, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(pfaddsubs, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_FLAGS_4(qpfhadds, TCG_CALL_NO_RWG, void, vec, env, vec, vec)
DEF_HELPER_FLAGS_4(qpfhsubs, TCG_CALL_NO_RWG, void, vec, env, vec, vec)
DEF_HELPER_FLAGS_3(pfstoifs, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_FLAGS_2(pistofs, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_2(pfstois, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_2(pfstoistr, TCG_CALL_NO_RWG, i64, env, i64)
DEF_HELPER_FLAGS_3(qpfstoid, TCG_CALL_NO_RWG, void, vec, env, i64)
DEF_HELPER_FLAGS_3(qpfstoidtr, TCG_CALL_NO_RWG, void, vec, env, i64)
DEF_HELPER_FLAGS_3(qpistofd, TCG_CALL_NO_RWG, void, vec, env, i64)
DEF_HELPER_FLAGS_3(qpfstofd, TCG_CALL_NO_RWG, void, vec, env, i64)
DEF_HELPER_FLAGS_2(qpfdtois, TCG_CALL_NO_RWG, i64, env, vec)
DEF_HELPER_FLAGS_2(qpfdtoistr, TCG_CALL_NO_RWG, i64, env, vec)
DEF_HELPER_FLAGS_2(qpidtofs, TCG_CALL_NO_RWG, i64, env, vec)
DEF_HELPER_FLAGS_2(qpfdtofs, TCG_CALL_NO_RWG, i64, env, vec)
DEF_HELPER_FLAGS_3(pfcmpeqs, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(pfcmplts, TCG_CALL_NO_RWG, i64, env, i64, i64)
DEF_HELPER_FLAGS_3(pfcmples, TCG_CALL_NO_RWG, i64, env, i64, i64)

@ -68,6 +68,7 @@ uint64_t HELPER(rrd)(CPUE2KState *env, int idx)
case 0x86: return env->fpsr.raw; /* %fpsr */
case 0x8a: return env->idr; /* %idr */
case 0x90: return cpu_get_host_ticks(); /* %clkr */
case 0xc3: return env->lsr_lcnt; /* %lsr1 */
default:
qemu_log_mask(LOG_UNIMP, "read unknown state register 0x%x\n", idx);
return 0;
@ -98,6 +99,7 @@ void HELPER(rwd)(CPUE2KState *env, int idx, uint64_t val)
e2k_update_fx_status(env);
break;
case 0x86: env->fpsr.raw = val; break; /* %fpsr */
case 0xc3: env->lsr_lcnt = val; break; /* %lsr1 */
default:
qemu_log_mask(LOG_UNIMP, "rwd unknown state register 0x%x\n", idx);
break;

@ -26,6 +26,18 @@ static uint8_t reverse_bits(uint8_t b)
#define vec64_len(type) glue(vec64_, type)
#define vec128_ub 16
#define vec128_uh 8
#define vec128_uw 4
#define vec128_ud 2
#define vec128_sb vec128_ub
#define vec128_sh vec128_uh
#define vec128_sw vec128_uw
#define vec128_sd vec128_ud
#define vec128_len(type) glue(vec128_, type)
typedef union {
uint8_t ub[vec64_ub];
uint16_t uh[vec64_uh];
@ -63,10 +75,12 @@ typedef union {
}
#define GEN_HELPER_PACKED(name, type, code) \
GEN_HELPER_PACKED_N(name, vec64_len(type), code)
#define GEN_HELPER_PACKED_OP(name, type, op) \
GEN_HELPER_PACKED_N(name, vec64_len(type), { \
dst.type[i] = op(s1.type[i], s2.type[i]); \
})
#define GEN_HELPER_PACKED_SCALAR(name, type, code) \
uint64_t HELPER(name)(uint64_t src1, uint64_t s2) \
{ \
@ -77,11 +91,28 @@ typedef union {
} \
return dst.ud[0]; \
}
#define GEN_HELPER_PACKED_MINMAX(name, type, op) \
GEN_HELPER_PACKED(glue(name, type), type, { \
dst.type[i] = op(s1.type[i], s2.type[i]); \
#define IMPL_QPACKED_N(name, n, code) \
void HELPER(name)(E2KReg *r, E2KReg *s1, E2KReg *s2) \
{ \
int i; \
\
for (i = 0; i < n; i++) { \
code \
} \
}
#define IMPL_QPACKED(name, type, code) \
IMPL_QPACKED_N(name, vec64_len(type), code)
#define IMPL_QPACKED_OP(name, type, op) \
IMPL_QPACKED_N(name, vec128_len(type), { \
r->type[i] = op(s1->type[i], s2->type[i]); \
})
#define GEN_HELPER_PACKED_MINMAX(name, type, op) \
GEN_HELPER_PACKED_OP(glue(name, type), type, op)
GEN_HELPER_PACKED_MINMAX(pmin, ub, MIN)
GEN_HELPER_PACKED_MINMAX(pmin, sb, MIN)
GEN_HELPER_PACKED_MINMAX(pmin, uh, MIN)
@ -131,6 +162,11 @@ GEN_HELPER_PACKED_BINOP_MAP(psubush, uh, -, int32_t, satuh)
int j = i * 2; \
dst.type[i ] = map(op(s1.type[j], s1.type[j + 1])); \
dst.type[i + vec64_len(type) / 2] = map(op(s2.type[j], s2.type[j + 1])); \
}) \
IMPL_QPACKED_N(glue(q, name), vec128_len(type) / 2, { \
int j = i * 2; \
r->type[i ] = map(op(s1->type[j], s1->type[j + 1])); \
r->type[i + vec128_len(type) / 2] = map(op(s2->type[j], s2->type[j + 1])); \
})
GEN_HELPER_PACKED_HORIZONTAL_OP(phaddh, sh, add, ident)
@ -142,14 +178,15 @@ GEN_HELPER_PACKED_HORIZONTAL_OP(phsubsh, sh, sub, satsh)
#define GEN_HELPER_PACKED_SCALAR_BINOP(name, type, op) \
GEN_HELPER_PACKED_SCALAR(name, type, { \
int max = sizeof(s1.type[0]) * 8 - 1; \
dst.type[i] = s2 < s1.type[i] op ( s2 < max ? s2 : max); \
dst.type[i] = s2 < sizeof(s1.type[0]) * 8 ? s1.type[i] op s2 : 0; \
})
GEN_HELPER_PACKED_SCALAR_BINOP(psllh, uh, <<)
GEN_HELPER_PACKED_SCALAR_BINOP(psllw, uw, <<)
GEN_HELPER_PACKED_SCALAR_BINOP(pslld, ud, <<)
GEN_HELPER_PACKED_SCALAR_BINOP(psrlh, uh, >>)
GEN_HELPER_PACKED_SCALAR_BINOP(psrlw, uw, >>)
GEN_HELPER_PACKED_SCALAR_BINOP(psrld, ud, >>)
#define GEN_HELPER_PACKED_SRA(name, type, t) \
GEN_HELPER_PACKED_SCALAR(name, type, { \
@ -209,7 +246,7 @@ GEN_HELPER_PACKED_OP(psignw, sw, mul_sign)
dst.mask_type[0] |= (s2.type[i] < 0) << (i ); \
}
GEN_HELPER_PACKED(pmovmskb, sb, MOVMASK(uh, sb))
GEN_HELPER_PACKED(pmovmskb, sb, MOVMASK(uh, sb))
GEN_HELPER_PACKED(pmovmskps, sw, MOVMASK(ub, sw))
GEN_HELPER_PACKED(pmovmskpd, sd, MOVMASK(ub, sd))
@ -239,7 +276,7 @@ GEN_HELPER_PACKED_UNPACK(punpckhwd, uw, 1)
uint64_t HELPER(pshufb)(uint64_t src1, uint64_t src2, uint64_t src3)
{
vec64 ret, s1, s2, s3;
unsigned int i;
int i;
s1.ud[0] = src1;
s2.ud[0] = src2;
@ -272,7 +309,7 @@ uint64_t HELPER(pshufb)(uint64_t src1, uint64_t src2, uint64_t src3)
uint64_t HELPER(pmerge)(uint64_t src1, uint64_t src2, uint64_t src3)
{
vec64 r, s1, s2, s3;
unsigned int i;
int i;
s1.ud[0] = src1;
s2.ud[0] = src2;
@ -328,6 +365,83 @@ uint64_t HELPER(phminposuh)(uint64_t src1, uint64_t src2)
return dst.ud[0];
}
void HELPER(qpmpsadbh)(E2KReg *r, E2KReg *s1, uint32_t s2)
{
r->ud[0] = helper_mpsadbh(s1->ud[0], s2);
r->ud[1] = helper_mpsadbh(s1->ud[1], s2);
}
void HELPER(qpmulubhh)(E2KReg *r, uint64_t s1, E2KReg *s2)
{
r->ud[0] = helper_pmulubhh(s1 , s2->ud[0]);
r->ud[1] = helper_pmulubhh(s1 >> 32, s2->ud[1]);
}
uint64_t HELPER(qphminposuh)(E2KReg *s1, E2KReg *s2)
{
int i;
uint16_t v = s1->uh[0];
uint16_t p = 0;
for (i = 0; i < 8; i++) {
if (s1->uh[i] < v) {
v = s1->uh[i];
p = i;
}
}
for (i = 0; i < 8; i++) {
if (s2->uh[i] < v) {
v = s2->uh[i];
p = 8 + i;
}
}
return ((uint64_t) p << 16) | v;
}
uint32_t HELPER(qpsgn2mskb)(E2KReg *s2)
{
uint32_t r = 0;
int i;
for (i = 0; i < 16; i++) {
r |= s2->sb[i] < 0 ? 1 << i : 0;
}
return r;
}
void HELPER(qpmsk2sgnb)(E2KReg *r, E2KReg *s1, uint32_t s2)
{
int i;
for (i = 0; i < 16; i++) {
r->ub[i] = s2 & (1 << i) ? s1->ub[i] | 0x80 : s1->ub[i] & 0x7f;
}
}
void HELPER(qppermb)(E2KReg *r, E2KReg *s1, E2KReg *s2, E2KReg *s3)
{
int i;
for (i = 0; i < 16; i++) {
uint8_t sel = s3->ub[i];
int index = sel & 0x0f;
uint8_t byte = sel & 0x10 ? s1->ub[index] : s2->ub[index];
byte = sel & 0x20 ? ~byte : byte;
byte = sel & 0x40 ? reverse_bits(byte) : byte;
byte = sel & 0x80 ? (byte & 0x80 ? 0xff : 0) : byte;
r->ub[i] = byte;
}
}
void HELPER(qpshufb)(E2KReg *r, E2KReg *s1, E2KReg *s2, E2KReg *s3)
{
r->ud[0] = helper_pshufb(s2->ud[1], s2->ud[0], s3->ud[0]);
r->ud[1] = helper_pshufb(s1->ud[1], s1->ud[0], s3->ud[1]);
}
static uint64_t get_value_from_truth_table(bool x, bool y, bool z, uint32_t truth_table)
{
int pos = x << 2 | y << 1 | z;
@ -363,12 +477,15 @@ uint64_t HELPER(plog)(uint32_t opc, uint64_t src1, uint64_t src2, uint64_t src3)
} \
return dst.ud[0]; \
}
#define GEN_ENV_HELPER_PACKED(name, type, code) \
GEN_ENV_HELPER_PACKED_N(name, vec64_len(type), code)
#define GEN_ENV_HELPER_PACKED_OP(name, type, op) \
GEN_ENV_HELPER_PACKED_N(name, vec64_len(type), { \
dst.type[i] = op(env, s1.type[i], s2.type[i]); \
})
#define GEN_ENV_HELPER_PACKED_HORIZONTAL_OP(name, type, op, map) \
GEN_ENV_HELPER_PACKED_N(name, vec64_len(type) / 2, { \
int j = i * 2; \
@ -376,6 +493,31 @@ uint64_t HELPER(plog)(uint32_t opc, uint64_t src1, uint64_t src2, uint64_t src3)
dst.type[i + vec64_len(type) / 2] = map(op(env, s2.type[j], s2.type[j + 1])); \
})
#define IMPL_QPACKED_ENV_N(name, n, code) \
void HELPER(name)(E2KReg *r, CPUE2KState *env, E2KReg *s1, E2KReg *s2) \
{ \
int i; \
\
for (i = 0; i < n; i++) { \
code \
} \
}
#define IMPL_QPACKED_ENV(name, type, code) \
IMPL_QPACKED_ENV_N(name, vec128_len(type), code)
#define IMPL_QPACKED_ENV_OP(name, type, op) \
IMPL_QPACKED_ENV_N(name, vec128_len(type), { \
r->type[i] = op(env, s1->type[i], s2->type[i]); \
})
#define IMPL_QPACKED_ENV_HOP(name, type, op, map) \
IMPL_QPACKED_ENV_N(name, vec128_len(type) / 2, { \
int j = i * 2; \
r->type[i ] = map(op(env, s1->type[j], s1->type[j + 1])); \
r->type[i + vec128_len(type) / 2] = map(op(env, s2->type[j], s2->type[j + 1])); \
})
GEN_ENV_HELPER_PACKED_OP(pfadds, uw, helper_fadds)
GEN_ENV_HELPER_PACKED_OP(pfsubs, uw, helper_fsubs)
GEN_ENV_HELPER_PACKED_OP(pfmuls, uw, helper_fmuls)
@ -383,6 +525,8 @@ GEN_ENV_HELPER_PACKED_OP(pfmaxs, uw, helper_fmaxs)
GEN_ENV_HELPER_PACKED_OP(pfmins, uw, helper_fmins)
GEN_ENV_HELPER_PACKED_HORIZONTAL_OP(pfhadds, uw, helper_fadds, ident)
GEN_ENV_HELPER_PACKED_HORIZONTAL_OP(pfhsubs, uw, helper_fsubs, ident)
IMPL_QPACKED_ENV_HOP(qpfhadds, uw, helper_fadds, ident)
IMPL_QPACKED_ENV_HOP(qpfhsubs, uw, helper_fsubs, ident)
GEN_ENV_HELPER_PACKED_OP(pfcmpeqs, uw, helper_fcmpeqs)
GEN_ENV_HELPER_PACKED_OP(pfcmplts, uw, helper_fcmplts)
@ -428,3 +572,33 @@ GEN_ENV_HELPER_PACKED_OP_CVT(pfstoifs, uw, helper_fstoifs)
GEN_ENV_HELPER_PACKED_UNARY_OP(pistofs, uw, helper_istofs)
GEN_ENV_HELPER_PACKED_UNARY_OP(pfstois, uw, helper_fstois)
GEN_ENV_HELPER_PACKED_UNARY_OP(pfstoistr, uw, helper_fstoistr)
#define IMPL_QPACKED_ENV_CVT_EXT(name, op) \
void HELPER(name)(E2KReg *r, CPUE2KState *env, uint64_t src2) \
{ \
vec64 s2 = { .ud[0] = src2 }; \
\
r->ud[0] = op(env, s2.uw[0]); \
r->ud[1] = op(env, s2.uw[1]); \
}
IMPL_QPACKED_ENV_CVT_EXT(qpfstoid, helper_fstoid)
IMPL_QPACKED_ENV_CVT_EXT(qpfstoidtr, helper_fstoidtr)
IMPL_QPACKED_ENV_CVT_EXT(qpistofd, helper_istofd)
IMPL_QPACKED_ENV_CVT_EXT(qpfstofd, helper_fstofd)
#define IMPL_QPACKED_ENV_CVT_TRUNC(name, op) \
uint64_t HELPER(name)(CPUE2KState *env, E2KReg *s2) \
{ \
vec64 r; \
\
r.uw[0] = op(env, s2->ud[0]); \
r.uw[1] = op(env, s2->ud[1]); \
\
return r.ud[0]; \
}
IMPL_QPACKED_ENV_CVT_TRUNC(qpfdtois, helper_fdtois)
IMPL_QPACKED_ENV_CVT_TRUNC(qpfdtoistr, helper_fdtoistr)
IMPL_QPACKED_ENV_CVT_TRUNC(qpidtofs, helper_idtofs)
IMPL_QPACKED_ENV_CVT_TRUNC(qpfdtofs, helper_fdtofs)

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save