mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-23 19:49:43 +00:00
Initial commit for the Qualcomm Hexagon processor.
-----BEGIN PGP SIGNATURE----- iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmAulUwdHHJpY2hhcmQu aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV+2Vwf7BvUWIqL0UTaQWj/s 2esOf50lV7f5BloKMKsDrOJTQS8UUTKAcrJKLjBjWkUdKZvUvRNDP+co1JFXLGBY YFdvDgkd/1daXLOnX09CyzwAozyLzEDztHWChzBvSp/SrsoYXTrGsnK7tybr1vam Aum3VcGjmvChi0fokQxWYBcK03XO7UJqHhgeczc4tt9Ok9LO+hPzpdep6oHLZicQ qhbej3HokiZ40tFY4kB/8l9W+4XSwJhuGj4z5LPqQk3j544jr6z4Azqo+VmSgWJS sgFOAqP5DHIYbLQSvR1yApP1ValgFd5BK/jCPGov/HNZgw31u45JwZarnyR8ylBe DcRHDw== =h1qI -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-hex-20210218' into staging Initial commit for the Qualcomm Hexagon processor. # gpg: Signature made Thu 18 Feb 2021 16:26:52 GMT # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full] # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * remotes/rth-gitlab/tags/pull-hex-20210218: (35 commits) Hexagon build infrastructure Hexagon (tests/tcg/hexagon) TCG tests - floating point Hexagon (tests/tcg/hexagon) TCG tests - atomics/load/store/misc Hexagon (tests/tcg/hexagon) TCG tests - multiarch Hexagon (linux-user/hexagon) Linux user emulation Hexagon (target/hexagon) translation Hexagon (target/hexagon) TCG for floating point instructions Hexagon (target/hexagon) TCG for instructions with multiple definitions Hexagon (target/hexagon) TCG generation Hexagon (target/hexagon) instruction classes Hexagon (target/hexagon) macros Hexagon (target/hexagon) opcode data structures Hexagon (target/hexagon) generater phase 4 - decode tree Hexagon (target/hexagon) generator phase 3 - C preprocessor for decode tree Hexagon (target/hexagon) generator phase 2 - generate header files Hexagon (target/hexagon) generator phase 1 - C preprocessor for semantics Hexagon (target/hexagon/imported) arch import Hexagon (target/hexagon/fma_emu.[ch]) utility functions Hexagon (target/hexagon/conv_emu.[ch]) utility functions Hexagon (target/hexagon/arch.[ch]) utility functions ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
c79f01c945
@ -188,6 +188,15 @@ F: include/hw/cris/
|
||||
F: tests/tcg/cris/
|
||||
F: disas/cris.c
|
||||
|
||||
Hexagon TCG CPUs
|
||||
M: Taylor Simpson <tsimpson@quicinc.com>
|
||||
S: Supported
|
||||
F: target/hexagon/
|
||||
F: linux-user/hexagon/
|
||||
F: tests/tcg/hexagon/
|
||||
F: disas/hexagon.c
|
||||
F: default-configs/targets/hexagon-linux-user.mak
|
||||
|
||||
HPPA (PA-RISC) TCG CPUs
|
||||
M: Richard Henderson <richard.henderson@linaro.org>
|
||||
S: Maintained
|
||||
|
1
default-configs/targets/hexagon-linux-user.mak
Normal file
1
default-configs/targets/hexagon-linux-user.mak
Normal file
@ -0,0 +1 @@
|
||||
TARGET_ARCH=hexagon
|
65
disas/hexagon.c
Normal file
65
disas/hexagon.c
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* QEMU Hexagon Disassembler
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "disas/dis-asm.h"
|
||||
#include "target/hexagon/cpu_bits.h"
|
||||
|
||||
/*
|
||||
* We will disassemble a packet with up to 4 instructions, so we need
|
||||
* a hefty size buffer.
|
||||
*/
|
||||
#define PACKET_BUFFER_LEN 1028
|
||||
|
||||
int print_insn_hexagon(bfd_vma memaddr, struct disassemble_info *info)
|
||||
{
|
||||
uint32_t words[PACKET_WORDS_MAX];
|
||||
bool found_end = false;
|
||||
GString *buf = g_string_sized_new(PACKET_BUFFER_LEN);
|
||||
int i, len;
|
||||
|
||||
for (i = 0; i < PACKET_WORDS_MAX && !found_end; i++) {
|
||||
int status = (*info->read_memory_func)(memaddr + i * sizeof(uint32_t),
|
||||
(bfd_byte *)&words[i],
|
||||
sizeof(uint32_t), info);
|
||||
if (status) {
|
||||
if (i > 0) {
|
||||
break;
|
||||
}
|
||||
(*info->memory_error_func)(status, memaddr, info);
|
||||
return status;
|
||||
}
|
||||
if (is_packet_end(words[i])) {
|
||||
found_end = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_end) {
|
||||
(*info->fprintf_func)(info->stream, "<invalid>");
|
||||
return PACKET_WORDS_MAX * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
len = disassemble_hexagon(words, i, memaddr, buf);
|
||||
(*info->fprintf_func)(info->stream, "%s", buf->str);
|
||||
g_string_free(buf, true);
|
||||
|
||||
return len;
|
||||
}
|
@ -6,6 +6,7 @@ common_ss.add(when: 'CONFIG_ARM_A64_DIS', if_true: files('arm-a64.cc'))
|
||||
common_ss.add_all(when: 'CONFIG_ARM_A64_DIS', if_true: libvixl_ss)
|
||||
common_ss.add(when: 'CONFIG_ARM_DIS', if_true: files('arm.c'))
|
||||
common_ss.add(when: 'CONFIG_CRIS_DIS', if_true: files('cris.c'))
|
||||
common_ss.add(when: 'CONFIG_HEXAGON_DIS', if_true: files('hexagon.c'))
|
||||
common_ss.add(when: 'CONFIG_HPPA_DIS', if_true: files('hppa.c'))
|
||||
common_ss.add(when: 'CONFIG_I386_DIS', if_true: files('i386.c'))
|
||||
common_ss.add(when: 'CONFIG_LM32_DIS', if_true: files('lm32.c'))
|
||||
|
@ -459,6 +459,7 @@ int print_insn_xtensa (bfd_vma, disassemble_info*);
|
||||
int print_insn_riscv32 (bfd_vma, disassemble_info*);
|
||||
int print_insn_riscv64 (bfd_vma, disassemble_info*);
|
||||
int print_insn_rx(bfd_vma, disassemble_info *);
|
||||
int print_insn_hexagon(bfd_vma, disassemble_info *);
|
||||
|
||||
#ifdef CONFIG_CAPSTONE
|
||||
bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size);
|
||||
|
@ -176,6 +176,7 @@ typedef struct mips_elf_abiflags_v0 {
|
||||
|
||||
#define EM_UNICORE32 110 /* UniCore32 */
|
||||
|
||||
#define EM_HEXAGON 164 /* Qualcomm Hexagon */
|
||||
#define EM_RX 173 /* Renesas RX family */
|
||||
|
||||
#define EM_RISCV 243 /* RISC-V */
|
||||
|
@ -58,6 +58,11 @@ static inline Int128 int128_and(Int128 a, Int128 b)
|
||||
return a & b;
|
||||
}
|
||||
|
||||
static inline Int128 int128_or(Int128 a, Int128 b)
|
||||
{
|
||||
return a | b;
|
||||
}
|
||||
|
||||
static inline Int128 int128_rshift(Int128 a, int n)
|
||||
{
|
||||
return a >> n;
|
||||
@ -208,6 +213,11 @@ static inline Int128 int128_and(Int128 a, Int128 b)
|
||||
return (Int128) { a.lo & b.lo, a.hi & b.hi };
|
||||
}
|
||||
|
||||
static inline Int128 int128_or(Int128 a, Int128 b)
|
||||
{
|
||||
return (Int128) { a.lo | b.lo, a.hi | b.hi };
|
||||
}
|
||||
|
||||
static inline Int128 int128_rshift(Int128 a, int n)
|
||||
{
|
||||
int64_t h;
|
||||
|
@ -1514,6 +1514,22 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs,
|
||||
|
||||
#endif /* TARGET_XTENSA */
|
||||
|
||||
#ifdef TARGET_HEXAGON
|
||||
|
||||
#define ELF_START_MMAP 0x20000000
|
||||
|
||||
#define ELF_CLASS ELFCLASS32
|
||||
#define ELF_ARCH EM_HEXAGON
|
||||
|
||||
static inline void init_thread(struct target_pt_regs *regs,
|
||||
struct image_info *infop)
|
||||
{
|
||||
regs->sepc = infop->entry;
|
||||
regs->sp = infop->start_stack;
|
||||
}
|
||||
|
||||
#endif /* TARGET_HEXAGON */
|
||||
|
||||
#ifndef ELF_PLATFORM
|
||||
#define ELF_PLATFORM (NULL)
|
||||
#endif
|
||||
|
100
linux-user/hexagon/cpu_loop.c
Normal file
100
linux-user/hexagon/cpu_loop.c
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* qemu user cpu loop
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "cpu_loop-common.h"
|
||||
#include "internal.h"
|
||||
|
||||
void cpu_loop(CPUHexagonState *env)
|
||||
{
|
||||
CPUState *cs = CPU(hexagon_env_get_cpu(env));
|
||||
int trapnr, signum, sigcode;
|
||||
target_ulong sigaddr;
|
||||
target_ulong syscallnum;
|
||||
target_ulong ret;
|
||||
|
||||
for (;;) {
|
||||
cpu_exec_start(cs);
|
||||
trapnr = cpu_exec(cs);
|
||||
cpu_exec_end(cs);
|
||||
process_queued_cpu_work(cs);
|
||||
|
||||
signum = 0;
|
||||
sigcode = 0;
|
||||
sigaddr = 0;
|
||||
|
||||
switch (trapnr) {
|
||||
case EXCP_INTERRUPT:
|
||||
/* just indicate that signals should be handled asap */
|
||||
break;
|
||||
case HEX_EXCP_TRAP0:
|
||||
syscallnum = env->gpr[6];
|
||||
env->gpr[HEX_REG_PC] += 4;
|
||||
ret = do_syscall(env,
|
||||
syscallnum,
|
||||
env->gpr[0],
|
||||
env->gpr[1],
|
||||
env->gpr[2],
|
||||
env->gpr[3],
|
||||
env->gpr[4],
|
||||
env->gpr[5],
|
||||
0, 0);
|
||||
if (ret == -TARGET_ERESTARTSYS) {
|
||||
env->gpr[HEX_REG_PC] -= 4;
|
||||
} else if (ret != -TARGET_QEMU_ESIGRETURN) {
|
||||
env->gpr[0] = ret;
|
||||
}
|
||||
break;
|
||||
case HEX_EXCP_FETCH_NO_UPAGE:
|
||||
case HEX_EXCP_PRIV_NO_UREAD:
|
||||
case HEX_EXCP_PRIV_NO_UWRITE:
|
||||
signum = TARGET_SIGSEGV;
|
||||
sigcode = TARGET_SEGV_MAPERR;
|
||||
break;
|
||||
case EXCP_ATOMIC:
|
||||
cpu_exec_step_atomic(cs);
|
||||
break;
|
||||
default:
|
||||
EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
|
||||
trapnr);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (signum) {
|
||||
target_siginfo_t info = {
|
||||
.si_signo = signum,
|
||||
.si_errno = 0,
|
||||
.si_code = sigcode,
|
||||
._sifields._sigfault._addr = sigaddr
|
||||
};
|
||||
queue_signal(env, info.si_signo, QEMU_SI_KILL, &info);
|
||||
}
|
||||
|
||||
process_pending_signals(env);
|
||||
}
|
||||
}
|
||||
|
||||
void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
|
||||
{
|
||||
env->gpr[HEX_REG_PC] = regs->sepc;
|
||||
env->gpr[HEX_REG_SP] = regs->sp;
|
||||
env->gpr[HEX_REG_USR] = 0x56000;
|
||||
}
|
276
linux-user/hexagon/signal.c
Normal file
276
linux-user/hexagon/signal.c
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Emulation of Linux signals
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu.h"
|
||||
#include "signal-common.h"
|
||||
#include "linux-user/trace.h"
|
||||
|
||||
struct target_sigcontext {
|
||||
target_ulong r0, r1, r2, r3;
|
||||
target_ulong r4, r5, r6, r7;
|
||||
target_ulong r8, r9, r10, r11;
|
||||
target_ulong r12, r13, r14, r15;
|
||||
target_ulong r16, r17, r18, r19;
|
||||
target_ulong r20, r21, r22, r23;
|
||||
target_ulong r24, r25, r26, r27;
|
||||
target_ulong r28, r29, r30, r31;
|
||||
target_ulong sa0;
|
||||
target_ulong lc0;
|
||||
target_ulong sa1;
|
||||
target_ulong lc1;
|
||||
target_ulong m0;
|
||||
target_ulong m1;
|
||||
target_ulong usr;
|
||||
target_ulong p3_0;
|
||||
target_ulong gp;
|
||||
target_ulong ugp;
|
||||
target_ulong pc;
|
||||
target_ulong cause;
|
||||
target_ulong badva;
|
||||
target_ulong pad1;
|
||||
target_ulong pad2;
|
||||
target_ulong pad3;
|
||||
};
|
||||
|
||||
struct target_ucontext {
|
||||
unsigned long uc_flags;
|
||||
target_ulong uc_link; /* target pointer */
|
||||
target_stack_t uc_stack;
|
||||
struct target_sigcontext uc_mcontext;
|
||||
target_sigset_t uc_sigmask;
|
||||
};
|
||||
|
||||
struct target_rt_sigframe {
|
||||
uint32_t tramp[2];
|
||||
struct target_siginfo info;
|
||||
struct target_ucontext uc;
|
||||
};
|
||||
|
||||
static abi_ulong get_sigframe(struct target_sigaction *ka,
|
||||
CPUHexagonState *regs, size_t framesize)
|
||||
{
|
||||
abi_ulong sp = get_sp_from_cpustate(regs);
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
sp = target_sigsp(sp, ka) - framesize;
|
||||
|
||||
sp = QEMU_ALIGN_DOWN(sp, 8);
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
||||
static void setup_sigcontext(struct target_sigcontext *sc, CPUHexagonState *env)
|
||||
{
|
||||
__put_user(env->gpr[HEX_REG_R00], &sc->r0);
|
||||
__put_user(env->gpr[HEX_REG_R01], &sc->r1);
|
||||
__put_user(env->gpr[HEX_REG_R02], &sc->r2);
|
||||
__put_user(env->gpr[HEX_REG_R03], &sc->r3);
|
||||
__put_user(env->gpr[HEX_REG_R04], &sc->r4);
|
||||
__put_user(env->gpr[HEX_REG_R05], &sc->r5);
|
||||
__put_user(env->gpr[HEX_REG_R06], &sc->r6);
|
||||
__put_user(env->gpr[HEX_REG_R07], &sc->r7);
|
||||
__put_user(env->gpr[HEX_REG_R08], &sc->r8);
|
||||
__put_user(env->gpr[HEX_REG_R09], &sc->r9);
|
||||
__put_user(env->gpr[HEX_REG_R10], &sc->r10);
|
||||
__put_user(env->gpr[HEX_REG_R11], &sc->r11);
|
||||
__put_user(env->gpr[HEX_REG_R12], &sc->r12);
|
||||
__put_user(env->gpr[HEX_REG_R13], &sc->r13);
|
||||
__put_user(env->gpr[HEX_REG_R14], &sc->r14);
|
||||
__put_user(env->gpr[HEX_REG_R15], &sc->r15);
|
||||
__put_user(env->gpr[HEX_REG_R16], &sc->r16);
|
||||
__put_user(env->gpr[HEX_REG_R17], &sc->r17);
|
||||
__put_user(env->gpr[HEX_REG_R18], &sc->r18);
|
||||
__put_user(env->gpr[HEX_REG_R19], &sc->r19);
|
||||
__put_user(env->gpr[HEX_REG_R20], &sc->r20);
|
||||
__put_user(env->gpr[HEX_REG_R21], &sc->r21);
|
||||
__put_user(env->gpr[HEX_REG_R22], &sc->r22);
|
||||
__put_user(env->gpr[HEX_REG_R23], &sc->r23);
|
||||
__put_user(env->gpr[HEX_REG_R24], &sc->r24);
|
||||
__put_user(env->gpr[HEX_REG_R25], &sc->r25);
|
||||
__put_user(env->gpr[HEX_REG_R26], &sc->r26);
|
||||
__put_user(env->gpr[HEX_REG_R27], &sc->r27);
|
||||
__put_user(env->gpr[HEX_REG_R28], &sc->r28);
|
||||
__put_user(env->gpr[HEX_REG_R29], &sc->r29);
|
||||
__put_user(env->gpr[HEX_REG_R30], &sc->r30);
|
||||
__put_user(env->gpr[HEX_REG_R31], &sc->r31);
|
||||
__put_user(env->gpr[HEX_REG_SA0], &sc->sa0);
|
||||
__put_user(env->gpr[HEX_REG_LC0], &sc->lc0);
|
||||
__put_user(env->gpr[HEX_REG_SA1], &sc->sa1);
|
||||
__put_user(env->gpr[HEX_REG_LC1], &sc->lc1);
|
||||
__put_user(env->gpr[HEX_REG_M0], &sc->m0);
|
||||
__put_user(env->gpr[HEX_REG_M1], &sc->m1);
|
||||
__put_user(env->gpr[HEX_REG_USR], &sc->usr);
|
||||
__put_user(env->gpr[HEX_REG_P3_0], &sc->p3_0);
|
||||
__put_user(env->gpr[HEX_REG_GP], &sc->gp);
|
||||
__put_user(env->gpr[HEX_REG_UGP], &sc->ugp);
|
||||
__put_user(env->gpr[HEX_REG_PC], &sc->pc);
|
||||
}
|
||||
|
||||
static void setup_ucontext(struct target_ucontext *uc,
|
||||
CPUHexagonState *env, target_sigset_t *set)
|
||||
{
|
||||
__put_user(0, &(uc->uc_flags));
|
||||
__put_user(0, &(uc->uc_link));
|
||||
|
||||
target_save_altstack(&uc->uc_stack, env);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||
__put_user(set->sig[i], &(uc->uc_sigmask.sig[i]));
|
||||
}
|
||||
|
||||
setup_sigcontext(&uc->uc_mcontext, env);
|
||||
}
|
||||
|
||||
static inline void install_sigtramp(uint32_t *tramp)
|
||||
{
|
||||
__put_user(0x7800d166, tramp + 0); /* { r6=#__NR_rt_sigreturn } */
|
||||
__put_user(0x5400c004, tramp + 1); /* { trap0(#1) } */
|
||||
}
|
||||
|
||||
void setup_rt_frame(int sig, struct target_sigaction *ka,
|
||||
target_siginfo_t *info,
|
||||
target_sigset_t *set, CPUHexagonState *env)
|
||||
{
|
||||
abi_ulong frame_addr;
|
||||
struct target_rt_sigframe *frame;
|
||||
|
||||
frame_addr = get_sigframe(ka, env, sizeof(*frame));
|
||||
trace_user_setup_rt_frame(env, frame_addr);
|
||||
|
||||
if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) {
|
||||
goto badframe;
|
||||
}
|
||||
|
||||
setup_ucontext(&frame->uc, env, set);
|
||||
tswap_siginfo(&frame->info, info);
|
||||
install_sigtramp(frame->tramp);
|
||||
|
||||
env->gpr[HEX_REG_PC] = ka->_sa_handler;
|
||||
env->gpr[HEX_REG_SP] = frame_addr;
|
||||
env->gpr[HEX_REG_R00] = sig;
|
||||
env->gpr[HEX_REG_R01] =
|
||||
frame_addr + offsetof(struct target_rt_sigframe, info);
|
||||
env->gpr[HEX_REG_R02] =
|
||||
frame_addr + offsetof(struct target_rt_sigframe, uc);
|
||||
env->gpr[HEX_REG_LR] =
|
||||
frame_addr + offsetof(struct target_rt_sigframe, tramp);
|
||||
|
||||
return;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 1);
|
||||
if (sig == TARGET_SIGSEGV) {
|
||||
ka->_sa_handler = TARGET_SIG_DFL;
|
||||
}
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
}
|
||||
|
||||
static void restore_sigcontext(CPUHexagonState *env,
|
||||
struct target_sigcontext *sc)
|
||||
{
|
||||
__get_user(env->gpr[HEX_REG_R00], &sc->r0);
|
||||
__get_user(env->gpr[HEX_REG_R01], &sc->r1);
|
||||
__get_user(env->gpr[HEX_REG_R02], &sc->r2);
|
||||
__get_user(env->gpr[HEX_REG_R03], &sc->r3);
|
||||
__get_user(env->gpr[HEX_REG_R04], &sc->r4);
|
||||
__get_user(env->gpr[HEX_REG_R05], &sc->r5);
|
||||
__get_user(env->gpr[HEX_REG_R06], &sc->r6);
|
||||
__get_user(env->gpr[HEX_REG_R07], &sc->r7);
|
||||
__get_user(env->gpr[HEX_REG_R08], &sc->r8);
|
||||
__get_user(env->gpr[HEX_REG_R09], &sc->r9);
|
||||
__get_user(env->gpr[HEX_REG_R10], &sc->r10);
|
||||
__get_user(env->gpr[HEX_REG_R11], &sc->r11);
|
||||
__get_user(env->gpr[HEX_REG_R12], &sc->r12);
|
||||
__get_user(env->gpr[HEX_REG_R13], &sc->r13);
|
||||
__get_user(env->gpr[HEX_REG_R14], &sc->r14);
|
||||
__get_user(env->gpr[HEX_REG_R15], &sc->r15);
|
||||
__get_user(env->gpr[HEX_REG_R16], &sc->r16);
|
||||
__get_user(env->gpr[HEX_REG_R17], &sc->r17);
|
||||
__get_user(env->gpr[HEX_REG_R18], &sc->r18);
|
||||
__get_user(env->gpr[HEX_REG_R19], &sc->r19);
|
||||
__get_user(env->gpr[HEX_REG_R20], &sc->r20);
|
||||
__get_user(env->gpr[HEX_REG_R21], &sc->r21);
|
||||
__get_user(env->gpr[HEX_REG_R22], &sc->r22);
|
||||
__get_user(env->gpr[HEX_REG_R23], &sc->r23);
|
||||
__get_user(env->gpr[HEX_REG_R24], &sc->r24);
|
||||
__get_user(env->gpr[HEX_REG_R25], &sc->r25);
|
||||
__get_user(env->gpr[HEX_REG_R26], &sc->r26);
|
||||
__get_user(env->gpr[HEX_REG_R27], &sc->r27);
|
||||
__get_user(env->gpr[HEX_REG_R28], &sc->r28);
|
||||
__get_user(env->gpr[HEX_REG_R29], &sc->r29);
|
||||
__get_user(env->gpr[HEX_REG_R30], &sc->r30);
|
||||
__get_user(env->gpr[HEX_REG_R31], &sc->r31);
|
||||
__get_user(env->gpr[HEX_REG_SA0], &sc->sa0);
|
||||
__get_user(env->gpr[HEX_REG_LC0], &sc->lc0);
|
||||
__get_user(env->gpr[HEX_REG_SA1], &sc->sa1);
|
||||
__get_user(env->gpr[HEX_REG_LC1], &sc->lc1);
|
||||
__get_user(env->gpr[HEX_REG_M0], &sc->m0);
|
||||
__get_user(env->gpr[HEX_REG_M1], &sc->m1);
|
||||
__get_user(env->gpr[HEX_REG_USR], &sc->usr);
|
||||
__get_user(env->gpr[HEX_REG_P3_0], &sc->p3_0);
|
||||
__get_user(env->gpr[HEX_REG_GP], &sc->gp);
|
||||
__get_user(env->gpr[HEX_REG_UGP], &sc->ugp);
|
||||
__get_user(env->gpr[HEX_REG_PC], &sc->pc);
|
||||
}
|
||||
|
||||
static void restore_ucontext(CPUHexagonState *env, struct target_ucontext *uc)
|
||||
{
|
||||
sigset_t blocked;
|
||||
target_sigset_t target_set;
|
||||
int i;
|
||||
|
||||
target_sigemptyset(&target_set);
|
||||
for (i = 0; i < TARGET_NSIG_WORDS; i++) {
|
||||
__get_user(target_set.sig[i], &(uc->uc_sigmask.sig[i]));
|
||||
}
|
||||
|
||||
target_to_host_sigset_internal(&blocked, &target_set);
|
||||
set_sigmask(&blocked);
|
||||
|
||||
restore_sigcontext(env, &uc->uc_mcontext);
|
||||
}
|
||||
|
||||
long do_rt_sigreturn(CPUHexagonState *env)
|
||||
{
|
||||
struct target_rt_sigframe *frame;
|
||||
abi_ulong frame_addr;
|
||||
|
||||
frame_addr = env->gpr[HEX_REG_SP];
|
||||
trace_user_do_sigreturn(env, frame_addr);
|
||||
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
|
||||
goto badframe;
|
||||
}
|
||||
|
||||
restore_ucontext(env, &frame->uc);
|
||||
|
||||
if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
|
||||
uc.uc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) {
|
||||
goto badframe;
|
||||
}
|
||||
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
return -TARGET_QEMU_ESIGRETURN;
|
||||
|
||||
badframe:
|
||||
unlock_user_struct(frame, frame_addr, 0);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
return 0;
|
||||
}
|
18
linux-user/hexagon/sockbits.h
Normal file
18
linux-user/hexagon/sockbits.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../generic/sockbits.h"
|
322
linux-user/hexagon/syscall_nr.h
Normal file
322
linux-user/hexagon/syscall_nr.h
Normal file
@ -0,0 +1,322 @@
|
||||
/*
|
||||
* This file contains the system call numbers.
|
||||
* Do not modify.
|
||||
* This file is generated by scripts/gensyscalls.sh
|
||||
*/
|
||||
#ifndef LINUX_USER_HEXAGON_SYSCALL_NR_H
|
||||
#define LINUX_USER_HEXAGON_SYSCALL_NR_H
|
||||
|
||||
#define TARGET_NR_io_setup 0
|
||||
#define TARGET_NR_io_destroy 1
|
||||
#define TARGET_NR_io_submit 2
|
||||
#define TARGET_NR_io_cancel 3
|
||||
#define TARGET_NR_io_getevents 4
|
||||
#define TARGET_NR_setxattr 5
|
||||
#define TARGET_NR_lsetxattr 6
|
||||
#define TARGET_NR_fsetxattr 7
|
||||
#define TARGET_NR_getxattr 8
|
||||
#define TARGET_NR_lgetxattr 9
|
||||
#define TARGET_NR_fgetxattr 10
|
||||
#define TARGET_NR_listxattr 11
|
||||
#define TARGET_NR_llistxattr 12
|
||||
#define TARGET_NR_flistxattr 13
|
||||
#define TARGET_NR_removexattr 14
|
||||
#define TARGET_NR_lremovexattr 15
|
||||
#define TARGET_NR_fremovexattr 16
|
||||
#define TARGET_NR_getcwd 17
|
||||
#define TARGET_NR_lookup_dcookie 18
|
||||
#define TARGET_NR_eventfd2 19
|
||||
#define TARGET_NR_epoll_create1 20
|
||||
#define TARGET_NR_epoll_ctl 21
|
||||
#define TARGET_NR_epoll_pwait 22
|
||||
#define TARGET_NR_dup 23
|
||||
#define TARGET_NR_dup3 24
|
||||
#define TARGET_NR_fcntl64 25
|
||||
#define TARGET_NR_inotify_init1 26
|
||||
#define TARGET_NR_inotify_add_watch 27
|
||||
#define TARGET_NR_inotify_rm_watch 28
|
||||
#define TARGET_NR_ioctl 29
|
||||
#define TARGET_NR_ioprio_set 30
|
||||
#define TARGET_NR_ioprio_get 31
|
||||
#define TARGET_NR_flock 32
|
||||
#define TARGET_NR_mknodat 33
|
||||
#define TARGET_NR_mkdirat 34
|
||||
#define TARGET_NR_unlinkat 35
|
||||
#define TARGET_NR_symlinkat 36
|
||||
#define TARGET_NR_linkat 37
|
||||
#define TARGET_NR_renameat 38
|
||||
#define TARGET_NR_umount2 39
|
||||
#define TARGET_NR_mount 40
|
||||
#define TARGET_NR_pivot_root 41
|
||||
#define TARGET_NR_nfsservctl 42
|
||||
#define TARGET_NR_statfs64 43
|
||||
#define TARGET_NR_fstatfs64 44
|
||||
#define TARGET_NR_truncate64 45
|
||||
#define TARGET_NR_ftruncate64 46
|
||||
#define TARGET_NR_fallocate 47
|
||||
#define TARGET_NR_faccessat 48
|
||||
#define TARGET_NR_chdir 49
|
||||
#define TARGET_NR_fchdir 50
|
||||
#define TARGET_NR_chroot 51
|
||||
#define TARGET_NR_fchmod 52
|
||||
#define TARGET_NR_fchmodat 53
|
||||
#define TARGET_NR_fchownat 54
|
||||
#define TARGET_NR_fchown 55
|
||||
#define TARGET_NR_openat 56
|
||||
#define TARGET_NR_close 57
|
||||
#define TARGET_NR_vhangup 58
|
||||
#define TARGET_NR_pipe2 59
|
||||
#define TARGET_NR_quotactl 60
|
||||
#define TARGET_NR_getdents64 61
|
||||
#define TARGET_NR_llseek 62
|
||||
#define TARGET_NR_read 63
|
||||
#define TARGET_NR_write 64
|
||||
#define TARGET_NR_readv 65
|
||||
#define TARGET_NR_writev 66
|
||||
#define TARGET_NR_pread64 67
|
||||
#define TARGET_NR_pwrite64 68
|
||||
#define TARGET_NR_preadv 69
|
||||
#define TARGET_NR_pwritev 70
|
||||
#define TARGET_NR_sendfile64 71
|
||||
#define TARGET_NR_pselect6 72
|
||||
#define TARGET_NR_ppoll 73
|
||||
#define TARGET_NR_signalfd4 74
|
||||
#define TARGET_NR_vmsplice 75
|
||||
#define TARGET_NR_splice 76
|
||||
#define TARGET_NR_tee 77
|
||||
#define TARGET_NR_readlinkat 78
|
||||
#define TARGET_NR_fstatat64 79
|
||||
#define TARGET_NR_fstat64 80
|
||||
#define TARGET_NR_sync 81
|
||||
#define TARGET_NR_fsync 82
|
||||
#define TARGET_NR_fdatasync 83
|
||||
#define TARGET_NR_sync_file_range 84
|
||||
#define TARGET_NR_timerfd_create 85
|
||||
#define TARGET_NR_timerfd_settime 86
|
||||
#define TARGET_NR_timerfd_gettime 87
|
||||
#define TARGET_NR_utimensat 88
|
||||
#define TARGET_NR_acct 89
|
||||
#define TARGET_NR_capget 90
|
||||
#define TARGET_NR_capset 91
|
||||
#define TARGET_NR_personality 92
|
||||
#define TARGET_NR_exit 93
|
||||
#define TARGET_NR_exit_group 94
|
||||
#define TARGET_NR_waitid 95
|
||||
#define TARGET_NR_set_tid_address 96
|
||||
#define TARGET_NR_unshare 97
|
||||
#define TARGET_NR_futex 98
|
||||
#define TARGET_NR_set_robust_list 99
|
||||
#define TARGET_NR_get_robust_list 100
|
||||
#define TARGET_NR_nanosleep 101
|
||||
#define TARGET_NR_getitimer 102
|
||||
#define TARGET_NR_setitimer 103
|
||||
#define TARGET_NR_kexec_load 104
|
||||
#define TARGET_NR_init_module 105
|
||||
#define TARGET_NR_delete_module 106
|
||||
#define TARGET_NR_timer_create 107
|
||||
#define TARGET_NR_timer_gettime 108
|
||||
#define TARGET_NR_timer_getoverrun 109
|
||||
#define TARGET_NR_timer_settime 110
|
||||
#define TARGET_NR_timer_delete 111
|
||||
#define TARGET_NR_clock_settime 112
|
||||
#define TARGET_NR_clock_gettime 113
|
||||
#define TARGET_NR_clock_getres 114
|
||||
#define TARGET_NR_clock_nanosleep 115
|
||||
#define TARGET_NR_syslog 116
|
||||
#define TARGET_NR_ptrace 117
|
||||
#define TARGET_NR_sched_setparam 118
|
||||
#define TARGET_NR_sched_setscheduler 119
|
||||
#define TARGET_NR_sched_getscheduler 120
|
||||
#define TARGET_NR_sched_getparam 121
|
||||
#define TARGET_NR_sched_setaffinity 122
|
||||
#define TARGET_NR_sched_getaffinity 123
|
||||
#define TARGET_NR_sched_yield 124
|
||||
#define TARGET_NR_sched_get_priority_max 125
|
||||
#define TARGET_NR_sched_get_priority_min 126
|
||||
#define TARGET_NR_sched_rr_get_interval 127
|
||||
#define TARGET_NR_restart_syscall 128
|
||||
#define TARGET_NR_kill 129
|
||||
#define TARGET_NR_tkill 130
|
||||
#define TARGET_NR_tgkill 131
|
||||
#define TARGET_NR_sigaltstack 132
|
||||
#define TARGET_NR_rt_sigsuspend 133
|
||||
#define TARGET_NR_rt_sigaction 134
|
||||
#define TARGET_NR_rt_sigprocmask 135
|
||||
#define TARGET_NR_rt_sigpending 136
|
||||
#define TARGET_NR_rt_sigtimedwait 137
|
||||
#define TARGET_NR_rt_sigqueueinfo 138
|
||||
#define TARGET_NR_rt_sigreturn 139
|
||||
#define TARGET_NR_setpriority 140
|
||||
#define TARGET_NR_getpriority 141
|
||||
#define TARGET_NR_reboot 142
|
||||
#define TARGET_NR_setregid 143
|
||||
#define TARGET_NR_setgid 144
|
||||
#define TARGET_NR_setreuid 145
|
||||
#define TARGET_NR_setuid 146
|
||||
#define TARGET_NR_setresuid 147
|
||||
#define TARGET_NR_getresuid 148
|
||||
#define TARGET_NR_setresgid 149
|
||||
#define TARGET_NR_getresgid 150
|
||||
#define TARGET_NR_setfsuid 151
|
||||
#define TARGET_NR_setfsgid 152
|
||||
#define TARGET_NR_times 153
|
||||
#define TARGET_NR_setpgid 154
|
||||
#define TARGET_NR_getpgid 155
|
||||
#define TARGET_NR_getsid 156
|
||||
#define TARGET_NR_setsid 157
|
||||
#define TARGET_NR_getgroups 158
|
||||
#define TARGET_NR_setgroups 159
|
||||
#define TARGET_NR_uname 160
|
||||
#define TARGET_NR_sethostname 161
|
||||
#define TARGET_NR_setdomainname 162
|
||||
#define TARGET_NR_getrlimit 163
|
||||
#define TARGET_NR_setrlimit 164
|
||||
#define TARGET_NR_getrusage 165
|
||||
#define TARGET_NR_umask 166
|
||||
#define TARGET_NR_prctl 167
|
||||
#define TARGET_NR_getcpu 168
|
||||
#define TARGET_NR_gettimeofday 169
|
||||
#define TARGET_NR_settimeofday 170
|
||||
#define TARGET_NR_adjtimex 171
|
||||
#define TARGET_NR_getpid 172
|
||||
#define TARGET_NR_getppid 173
|
||||
#define TARGET_NR_getuid 174
|
||||
#define TARGET_NR_geteuid 175
|
||||
#define TARGET_NR_getgid 176
|
||||
#define TARGET_NR_getegid 177
|
||||
#define TARGET_NR_gettid 178
|
||||
#define TARGET_NR_sysinfo 179
|
||||
#define TARGET_NR_mq_open 180
|
||||
#define TARGET_NR_mq_unlink 181
|
||||
#define TARGET_NR_mq_timedsend 182
|
||||
#define TARGET_NR_mq_timedreceive 183
|
||||
#define TARGET_NR_mq_notify 184
|
||||
#define TARGET_NR_mq_getsetattr 185
|
||||
#define TARGET_NR_msgget 186
|
||||
#define TARGET_NR_msgctl 187
|
||||
#define TARGET_NR_msgrcv 188
|
||||
#define TARGET_NR_msgsnd 189
|
||||
#define TARGET_NR_semget 190
|
||||
#define TARGET_NR_semctl 191
|
||||
#define TARGET_NR_semtimedop 192
|
||||
#define TARGET_NR_semop 193
|
||||
#define TARGET_NR_shmget 194
|
||||
#define TARGET_NR_shmctl 195
|
||||
#define TARGET_NR_shmat 196
|
||||
#define TARGET_NR_shmdt 197
|
||||
#define TARGET_NR_socket 198
|
||||
#define TARGET_NR_socketpair 199
|
||||
#define TARGET_NR_bind 200
|
||||
#define TARGET_NR_listen 201
|
||||
#define TARGET_NR_accept 202
|
||||
#define TARGET_NR_connect 203
|
||||
#define TARGET_NR_getsockname 204
|
||||
#define TARGET_NR_getpeername 205
|
||||
#define TARGET_NR_sendto 206
|
||||
#define TARGET_NR_recvfrom 207
|
||||
#define TARGET_NR_setsockopt 208
|
||||
#define TARGET_NR_getsockopt 209
|
||||
#define TARGET_NR_shutdown 210
|
||||
#define TARGET_NR_sendmsg 211
|
||||
#define TARGET_NR_recvmsg 212
|
||||
#define TARGET_NR_readahead 213
|
||||
#define TARGET_NR_brk 214
|
||||
#define TARGET_NR_munmap 215
|
||||
#define TARGET_NR_mremap 216
|
||||
#define TARGET_NR_add_key 217
|
||||
#define TARGET_NR_request_key 218
|
||||
#define TARGET_NR_keyctl 219
|
||||
#define TARGET_NR_clone 220
|
||||
#define TARGET_NR_execve 221
|
||||
#define TARGET_NR_mmap2 222
|
||||
#define TARGET_NR_fadvise64_64 223
|
||||
#define TARGET_NR_swapon 224
|
||||
#define TARGET_NR_swapoff 225
|
||||
#define TARGET_NR_mprotect 226
|
||||
#define TARGET_NR_msync 227
|
||||
#define TARGET_NR_mlock 228
|
||||
#define TARGET_NR_munlock 229
|
||||
#define TARGET_NR_mlockall 230
|
||||
#define TARGET_NR_munlockall 231
|
||||
#define TARGET_NR_mincore 232
|
||||
#define TARGET_NR_madvise 233
|
||||
#define TARGET_NR_remap_file_pages 234
|
||||
#define TARGET_NR_mbind 235
|
||||
#define TARGET_NR_get_mempolicy 236
|
||||
#define TARGET_NR_set_mempolicy 237
|
||||
#define TARGET_NR_migrate_pages 238
|
||||
#define TARGET_NR_move_pages 239
|
||||
#define TARGET_NR_rt_tgsigqueueinfo 240
|
||||
#define TARGET_NR_perf_event_open 241
|
||||
#define TARGET_NR_accept4 242
|
||||
#define TARGET_NR_recvmmsg 243
|
||||
#define TARGET_NR_arch_specific_syscall 244
|
||||
#define TARGET_NR_wait4 260
|
||||
#define TARGET_NR_prlimit64 261
|
||||
#define TARGET_NR_fanotify_init 262
|
||||
#define TARGET_NR_fanotify_mark 263
|
||||
#define TARGET_NR_name_to_handle_at 264
|
||||
#define TARGET_NR_open_by_handle_at 265
|
||||
#define TARGET_NR_clock_adjtime 266
|
||||
#define TARGET_NR_syncfs 267
|
||||
#define TARGET_NR_setns 268
|
||||
#define TARGET_NR_sendmmsg 269
|
||||
#define TARGET_NR_process_vm_readv 270
|
||||
#define TARGET_NR_process_vm_writev 271
|
||||
#define TARGET_NR_kcmp 272
|
||||
#define TARGET_NR_finit_module 273
|
||||
#define TARGET_NR_sched_setattr 274
|
||||
#define TARGET_NR_sched_getattr 275
|
||||
#define TARGET_NR_renameat2 276
|
||||
#define TARGET_NR_seccomp 277
|
||||
#define TARGET_NR_getrandom 278
|
||||
#define TARGET_NR_memfd_create 279
|
||||
#define TARGET_NR_bpf 280
|
||||
#define TARGET_NR_execveat 281
|
||||
#define TARGET_NR_userfaultfd 282
|
||||
#define TARGET_NR_membarrier 283
|
||||
#define TARGET_NR_mlock2 284
|
||||
#define TARGET_NR_copy_file_range 285
|
||||
#define TARGET_NR_preadv2 286
|
||||
#define TARGET_NR_pwritev2 287
|
||||
#define TARGET_NR_pkey_mprotect 288
|
||||
#define TARGET_NR_pkey_alloc 289
|
||||
#define TARGET_NR_pkey_free 290
|
||||
#define TARGET_NR_statx 291
|
||||
#define TARGET_NR_io_pgetevents 292
|
||||
#define TARGET_NR_rseq 293
|
||||
#define TARGET_NR_kexec_file_load 294
|
||||
#define TARGET_NR_clock_gettime64 403
|
||||
#define TARGET_NR_clock_settime64 404
|
||||
#define TARGET_NR_clock_adjtime64 405
|
||||
#define TARGET_NR_clock_getres_time64 406
|
||||
#define TARGET_NR_clock_nanosleep_time64 407
|
||||
#define TARGET_NR_timer_gettime64 408
|
||||
#define TARGET_NR_timer_settime64 409
|
||||
#define TARGET_NR_timerfd_gettime64 410
|
||||
#define TARGET_NR_timerfd_settime64 411
|
||||
#define TARGET_NR_utimensat_time64 412
|
||||
#define TARGET_NR_pselect6_time64 413
|
||||
#define TARGET_NR_ppoll_time64 414
|
||||
#define TARGET_NR_io_pgetevents_time64 416
|
||||
#define TARGET_NR_recvmmsg_time64 417
|
||||
#define TARGET_NR_mq_timedsend_time64 418
|
||||
#define TARGET_NR_mq_timedreceive_time64 419
|
||||
#define TARGET_NR_semtimedop_time64 420
|
||||
#define TARGET_NR_rt_sigtimedwait_time64 421
|
||||
#define TARGET_NR_futex_time64 422
|
||||
#define TARGET_NR_sched_rr_get_interval_time64 423
|
||||
#define TARGET_NR_pidfd_send_signal 424
|
||||
#define TARGET_NR_io_uring_setup 425
|
||||
#define TARGET_NR_io_uring_enter 426
|
||||
#define TARGET_NR_io_uring_register 427
|
||||
#define TARGET_NR_open_tree 428
|
||||
#define TARGET_NR_move_mount 429
|
||||
#define TARGET_NR_fsopen 430
|
||||
#define TARGET_NR_fsconfig 431
|
||||
#define TARGET_NR_fsmount 432
|
||||
#define TARGET_NR_fspick 433
|
||||
#define TARGET_NR_pidfd_open 434
|
||||
#define TARGET_NR_syscalls 436
|
||||
|
||||
#endif /* LINUX_USER_HEXAGON_SYSCALL_NR_H */
|
44
linux-user/hexagon/target_cpu.h
Normal file
44
linux-user/hexagon/target_cpu.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_TARGET_CPU_H
|
||||
#define HEXAGON_TARGET_CPU_H
|
||||
|
||||
static inline void cpu_clone_regs_child(CPUHexagonState *env,
|
||||
target_ulong newsp, unsigned flags)
|
||||
{
|
||||
if (newsp) {
|
||||
env->gpr[HEX_REG_SP] = newsp;
|
||||
}
|
||||
env->gpr[0] = 0;
|
||||
}
|
||||
|
||||
static inline void cpu_clone_regs_parent(CPUHexagonState *env, unsigned flags)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void cpu_set_tls(CPUHexagonState *env, target_ulong newtls)
|
||||
{
|
||||
env->gpr[HEX_REG_UGP] = newtls;
|
||||
}
|
||||
|
||||
static inline abi_ulong get_sp_from_cpustate(CPUHexagonState *state)
|
||||
{
|
||||
return state->gpr[HEX_REG_SP];
|
||||
}
|
||||
|
||||
#endif
|
40
linux-user/hexagon/target_elf.h
Normal file
40
linux-user/hexagon/target_elf.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_TARGET_ELF_H
|
||||
#define HEXAGON_TARGET_ELF_H
|
||||
|
||||
static inline const char *cpu_get_model(uint32_t eflags)
|
||||
{
|
||||
/* For now, treat anything newer than v5 as a v67 */
|
||||
/* FIXME - Disable instructions that are newer than the specified arch */
|
||||
if (eflags == 0x04 || /* v5 */
|
||||
eflags == 0x05 || /* v55 */
|
||||
eflags == 0x60 || /* v60 */
|
||||
eflags == 0x61 || /* v61 */
|
||||
eflags == 0x62 || /* v62 */
|
||||
eflags == 0x65 || /* v65 */
|
||||
eflags == 0x66 || /* v66 */
|
||||
eflags == 0x67 || /* v67 */
|
||||
eflags == 0x8067 /* v67t */
|
||||
) {
|
||||
return "v67";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
#endif
|
18
linux-user/hexagon/target_fcntl.h
Normal file
18
linux-user/hexagon/target_fcntl.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../generic/fcntl.h"
|
34
linux-user/hexagon/target_signal.h
Normal file
34
linux-user/hexagon/target_signal.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_TARGET_SIGNAL_H
|
||||
#define HEXAGON_TARGET_SIGNAL_H
|
||||
|
||||
typedef struct target_sigaltstack {
|
||||
abi_ulong ss_sp;
|
||||
abi_int ss_flags;
|
||||
abi_ulong ss_size;
|
||||
} target_stack_t;
|
||||
|
||||
#define TARGET_SS_ONSTACK 1
|
||||
#define TARGET_SS_DISABLE 2
|
||||
|
||||
#define TARGET_MINSIGSTKSZ 2048
|
||||
|
||||
#include "../generic/signal.h"
|
||||
|
||||
#endif /* TARGET_SIGNAL_H */
|
54
linux-user/hexagon/target_structs.h
Normal file
54
linux-user/hexagon/target_structs.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Hexagon specific structures for linux-user
|
||||
*/
|
||||
#ifndef HEXAGON_TARGET_STRUCTS_H
|
||||
#define HEXAGON_TARGET_STRUCTS_H
|
||||
|
||||
struct target_ipc_perm {
|
||||
abi_int __key; /* Key. */
|
||||
abi_uint uid; /* Owner's user ID. */
|
||||
abi_uint gid; /* Owner's group ID. */
|
||||
abi_uint cuid; /* Creator's user ID. */
|
||||
abi_uint cgid; /* Creator's group ID. */
|
||||
abi_ushort mode; /* Read/write permission. */
|
||||
abi_ushort __pad1;
|
||||
abi_ushort __seq; /* Sequence number. */
|
||||
abi_ushort __pad2;
|
||||
abi_ulong __unused1;
|
||||
abi_ulong __unused2;
|
||||
};
|
||||
|
||||
struct target_shmid_ds {
|
||||
struct target_ipc_perm shm_perm; /* operation permission struct */
|
||||
abi_long shm_segsz; /* size of segment in bytes */
|
||||
abi_ulong shm_atime; /* time of last shmat() */
|
||||
abi_ulong __unused1;
|
||||
abi_ulong shm_dtime; /* time of last shmdt() */
|
||||
abi_ulong __unused2;
|
||||
abi_ulong shm_ctime; /* time of last change by shmctl() */
|
||||
abi_ulong __unused3;
|
||||
abi_int shm_cpid; /* pid of creator */
|
||||
abi_int shm_lpid; /* pid of last shmop */
|
||||
abi_ulong shm_nattch; /* number of current attaches */
|
||||
abi_ulong __unused4;
|
||||
abi_ulong __unused5;
|
||||
};
|
||||
|
||||
#endif
|
36
linux-user/hexagon/target_syscall.h
Normal file
36
linux-user/hexagon/target_syscall.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_TARGET_SYSCALL_H
|
||||
#define HEXAGON_TARGET_SYSCALL_H
|
||||
|
||||
struct target_pt_regs {
|
||||
abi_long sepc;
|
||||
abi_long sp;
|
||||
};
|
||||
|
||||
#define UNAME_MACHINE "hexagon"
|
||||
#define UNAME_MINIMUM_RELEASE "4.15.0"
|
||||
|
||||
#define TARGET_MLOCKALL_MCL_CURRENT 1
|
||||
#define TARGET_MLOCKALL_MCL_FUTURE 2
|
||||
|
||||
#define TARGET_MCL_CURRENT 1
|
||||
#define TARGET_MCL_FUTURE 2
|
||||
#define TARGET_MCL_ONFAULT 4
|
||||
|
||||
#endif
|
18
linux-user/hexagon/termbits.h
Normal file
18
linux-user/hexagon/termbits.h
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../generic/termbits.h"
|
@ -718,6 +718,8 @@ static inline int regpairs_aligned(void *cpu_env, int num)
|
||||
}
|
||||
#elif defined(TARGET_XTENSA)
|
||||
static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
|
||||
#elif defined(TARGET_HEXAGON)
|
||||
static inline int regpairs_aligned(void *cpu_env, int num) { return 1; }
|
||||
#else
|
||||
static inline int regpairs_aligned(void *cpu_env, int num) { return 0; }
|
||||
#endif
|
||||
|
@ -104,6 +104,14 @@
|
||||
#define TARGET_IOC_WRITE 2U
|
||||
#define TARGET_IOC_READ 1U
|
||||
|
||||
#elif defined(TARGET_HEXAGON)
|
||||
|
||||
#define TARGET_IOC_SIZEBITS 14
|
||||
|
||||
#define TARGET_IOC_NONE 0U
|
||||
#define TARGET_IOC_WRITE 1U
|
||||
#define TARGET_IOC_READ 2U
|
||||
|
||||
#else
|
||||
#error unsupported CPU
|
||||
#endif
|
||||
@ -2253,6 +2261,31 @@ struct target_stat64 {
|
||||
uint64_t st_ino;
|
||||
};
|
||||
|
||||
#elif defined(TARGET_HEXAGON)
|
||||
|
||||
struct target_stat {
|
||||
unsigned long long st_dev;
|
||||
unsigned long long st_ino;
|
||||
unsigned int st_mode;
|
||||
unsigned int st_nlink;
|
||||
unsigned int st_uid;
|
||||
unsigned int st_gid;
|
||||
unsigned long long st_rdev;
|
||||
target_ulong __pad1;
|
||||
long long st_size;
|
||||
target_long st_blksize;
|
||||
int __pad2;
|
||||
long long st_blocks;
|
||||
|
||||
target_long target_st_atime;
|
||||
target_long target_st_atime_nsec;
|
||||
target_long target_st_mtime;
|
||||
target_long target_st_mtime_nsec;
|
||||
target_long target_st_ctime;
|
||||
target_long target_st_ctime_nsec;
|
||||
int __unused[2];
|
||||
};
|
||||
|
||||
#else
|
||||
#error unsupported CPU
|
||||
#endif
|
||||
|
@ -1188,6 +1188,7 @@ disassemblers = {
|
||||
'arm' : ['CONFIG_ARM_DIS'],
|
||||
'avr' : ['CONFIG_AVR_DIS'],
|
||||
'cris' : ['CONFIG_CRIS_DIS'],
|
||||
'hexagon' : ['CONFIG_HEXAGON_DIS'],
|
||||
'hppa' : ['CONFIG_HPPA_DIS'],
|
||||
'i386' : ['CONFIG_I386_DIS'],
|
||||
'x86_64' : ['CONFIG_I386_DIS'],
|
||||
|
@ -98,4 +98,5 @@ generate_syscall_nr openrisc 32 "$output/linux-user/openrisc/syscall_nr.h"
|
||||
|
||||
generate_syscall_nr riscv 32 "$output/linux-user/riscv/syscall32_nr.h"
|
||||
generate_syscall_nr riscv 64 "$output/linux-user/riscv/syscall64_nr.h"
|
||||
generate_syscall_nr hexagon 32 "$output/linux-user/hexagon/syscall_nr.h"
|
||||
rm -fr "$TMP"
|
||||
|
@ -4,7 +4,7 @@
|
||||
qemu_target_list="i386 i486 alpha arm armeb sparc sparc32plus sparc64 \
|
||||
ppc ppc64 ppc64le m68k mips mipsel mipsn32 mipsn32el mips64 mips64el \
|
||||
sh4 sh4eb s390x aarch64 aarch64_be hppa riscv32 riscv64 xtensa xtensaeb \
|
||||
microblaze microblazeel or1k x86_64"
|
||||
microblaze microblazeel or1k x86_64 hexagon"
|
||||
|
||||
i386_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00'
|
||||
i386_mask='\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
|
||||
@ -136,6 +136,10 @@ or1k_magic='\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\
|
||||
or1k_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff'
|
||||
or1k_family=or1k
|
||||
|
||||
hexagon_magic='\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xa4\x00'
|
||||
hexagon_mask='\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff'
|
||||
hexagon_family=hexagon
|
||||
|
||||
qemu_get_family() {
|
||||
cpu=${HOST_ARCH:-$(uname -m)}
|
||||
case "$cpu" in
|
||||
|
235
target/hexagon/README
Normal file
235
target/hexagon/README
Normal file
@ -0,0 +1,235 @@
|
||||
Hexagon is Qualcomm's very long instruction word (VLIW) digital signal
|
||||
processor(DSP).
|
||||
|
||||
The following versions of the Hexagon core are supported
|
||||
Scalar core: v67
|
||||
https://developer.qualcomm.com/downloads/qualcomm-hexagon-v67-programmer-s-reference-manual
|
||||
|
||||
We presented an overview of the project at the 2019 KVM Forum.
|
||||
https://kvmforum2019.sched.com/event/Tmwc/qemu-hexagon-automatic-translation-of-the-isa-manual-pseudcode-to-tiny-code-instructions-of-a-vliw-architecture-niccolo-izzo-revng-taylor-simpson-qualcomm-innovation-center
|
||||
|
||||
*** Tour of the code ***
|
||||
|
||||
The qemu-hexagon implementation is a combination of qemu and the Hexagon
|
||||
architecture library (aka archlib). The three primary directories with
|
||||
Hexagon-specific code are
|
||||
|
||||
qemu/target/hexagon
|
||||
This has all the instruction and packet semantics
|
||||
qemu/target/hexagon/imported
|
||||
These files are imported with very little modification from archlib
|
||||
*.idef Instruction semantics definition
|
||||
macros.def Mapping of macros to instruction attributes
|
||||
encode*.def Encoding patterns for each instruction
|
||||
iclass.def Instruction class definitions used to determine
|
||||
legal VLIW slots for each instruction
|
||||
qemu/linux-user/hexagon
|
||||
Helpers for loading the ELF file and making Linux system calls,
|
||||
signals, etc
|
||||
|
||||
We start with scripts that generate a bunch of include files. This
|
||||
is a two step process. The first step is to use the C preprocessor to expand
|
||||
macros inside the architecture definition files. This is done in
|
||||
target/hexagon/gen_semantics.c. This step produces
|
||||
<BUILD_DIR>/target/hexagon/semantics_generated.pyinc.
|
||||
That file is consumed by the following python scripts to produce the indicated
|
||||
header files in <BUILD_DIR>/target/hexagon
|
||||
gen_opcodes_def.py -> opcodes_def_generated.h.inc
|
||||
gen_op_regs.py -> op_regs_generated.h.inc
|
||||
gen_printinsn.py -> printinsn_generated.h.inc
|
||||
gen_op_attribs.py -> op_attribs_generated.h.inc
|
||||
gen_helper_protos.py -> helper_protos_generated.h.inc
|
||||
gen_shortcode.py -> shortcode_generated.h.inc
|
||||
gen_tcg_funcs.py -> tcg_funcs_generated.c.inc
|
||||
gen_tcg_func_table.py -> tcg_func_table_generated.c.inc
|
||||
gen_helper_funcs.py -> helper_funcs_generated.c.inc
|
||||
|
||||
Qemu helper functions have 3 parts
|
||||
DEF_HELPER declaration indicates the signature of the helper
|
||||
gen_helper_<NAME> will generate a TCG call to the helper function
|
||||
The helper implementation
|
||||
|
||||
Here's an example of the A2_add instruction.
|
||||
Instruction tag A2_add
|
||||
Assembly syntax "Rd32=add(Rs32,Rt32)"
|
||||
Instruction semantics "{ RdV=RsV+RtV;}"
|
||||
|
||||
By convention, the operands are identified by letter
|
||||
RdV is the destination register
|
||||
RsV, RtV are source registers
|
||||
|
||||
The generator uses the operand naming conventions (see large comment in
|
||||
hex_common.py) to determine the signature of the helper function. Here are the
|
||||
results for A2_add
|
||||
|
||||
helper_protos_generated.h.inc
|
||||
DEF_HELPER_3(A2_add, s32, env, s32, s32)
|
||||
|
||||
tcg_funcs_generated.c.inc
|
||||
static void generate_A2_add(
|
||||
CPUHexagonState *env,
|
||||
DisasContext *ctx,
|
||||
Insn *insn,
|
||||
Packet *pkt)
|
||||
{
|
||||
TCGv RdV = tcg_temp_local_new();
|
||||
const int RdN = insn->regno[0];
|
||||
TCGv RsV = hex_gpr[insn->regno[1]];
|
||||
TCGv RtV = hex_gpr[insn->regno[2]];
|
||||
gen_helper_A2_add(RdV, cpu_env, RsV, RtV);
|
||||
gen_log_reg_write(RdN, RdV);
|
||||
ctx_log_reg_write(ctx, RdN);
|
||||
tcg_temp_free(RdV);
|
||||
}
|
||||
|
||||
helper_funcs_generated.c.inc
|
||||
int32_t HELPER(A2_add)(CPUHexagonState *env, int32_t RsV, int32_t RtV)
|
||||
{
|
||||
uint32_t slot __attribute__((unused)) = 4;
|
||||
int32_t RdV = 0;
|
||||
{ RdV=RsV+RtV;}
|
||||
return RdV;
|
||||
}
|
||||
|
||||
Note that generate_A2_add updates the disassembly context to be processed
|
||||
when the packet commits (see "Packet Semantics" below).
|
||||
|
||||
The generator checks for fGEN_TCG_<tag> macro. This allows us to generate
|
||||
TCG code instead of a call to the helper. If defined, the macro takes 1
|
||||
argument.
|
||||
C semantics (aka short code)
|
||||
|
||||
This allows the code generator to override the auto-generated code. In some
|
||||
cases this is necessary for correct execution. We can also override for
|
||||
faster emulation. For example, calling a helper for add is more expensive
|
||||
than generating a TCG add operation.
|
||||
|
||||
The gen_tcg.h file has any overrides. For example, we could write
|
||||
#define fGEN_TCG_A2_add(GENHLPR, SHORTCODE) \
|
||||
tcg_gen_add_tl(RdV, RsV, RtV)
|
||||
|
||||
The instruction semantics C code relies heavily on macros. In cases where the
|
||||
C semantics are specified only with macros, we can override the default with
|
||||
the short semantics option and #define the macros to generate TCG code. One
|
||||
example is L2_loadw_locked:
|
||||
Instruction tag L2_loadw_locked
|
||||
Assembly syntax "Rd32=memw_locked(Rs32)"
|
||||
Instruction semantics "{ fEA_REG(RsV); fLOAD_LOCKED(1,4,u,EA,RdV) }"
|
||||
|
||||
In gen_tcg.h, we use the shortcode
|
||||
#define fGEN_TCG_L2_loadw_locked(SHORTCODE) \
|
||||
SHORTCODE
|
||||
|
||||
There are also cases where we brute force the TCG code generation.
|
||||
Instructions with multiple definitions are examples. These require special
|
||||
handling because qemu helpers can only return a single value.
|
||||
|
||||
In addition to instruction semantics, we use a generator to create the decode
|
||||
tree. This generation is also a two step process. The first step is to run
|
||||
target/hexagon/gen_dectree_import.c to produce
|
||||
<BUILD_DIR>/target/hexagon/iset.py
|
||||
This file is imported by target/hexagon/dectree.py to produce
|
||||
<BUILD_DIR>/target/hexagon/dectree_generated.h.inc
|
||||
|
||||
*** Key Files ***
|
||||
|
||||
cpu.h
|
||||
|
||||
This file contains the definition of the CPUHexagonState struct. It is the
|
||||
runtime information for each thread and contains stuff like the GPR and
|
||||
predicate registers.
|
||||
|
||||
macros.h
|
||||
|
||||
The Hexagon arch lib relies heavily on macros for the instruction semantics.
|
||||
This is a great advantage for qemu because we can override them for different
|
||||
purposes. You will also notice there are sometimes two definitions of a macro.
|
||||
The QEMU_GENERATE variable determines whether we want the macro to generate TCG
|
||||
code. If QEMU_GENERATE is not defined, we want the macro to generate vanilla
|
||||
C code that will work in the helper implementation.
|
||||
|
||||
translate.c
|
||||
|
||||
The functions in this file generate TCG code for a translation block. Some
|
||||
important functions in this file are
|
||||
|
||||
gen_start_packet - initialize the data structures for packet semantics
|
||||
gen_commit_packet - commit the register writes, stores, etc for a packet
|
||||
decode_and_translate_packet - disassemble a packet and generate code
|
||||
|
||||
genptr.c
|
||||
gen_tcg.h
|
||||
|
||||
These files create a function for each instruction. It is mostly composed of
|
||||
fGEN_TCG_<tag> definitions followed by including tcg_funcs_generated.c.inc.
|
||||
|
||||
op_helper.c
|
||||
|
||||
This file contains the implementations of all the helpers. There are a few
|
||||
general purpose helpers, but most of them are generated by including
|
||||
helper_funcs_generated.c.inc. There are also several helpers used for debugging.
|
||||
|
||||
|
||||
*** Packet Semantics ***
|
||||
|
||||
VLIW packet semantics differ from serial semantics in that all input operands
|
||||
are read, then the operations are performed, then all the results are written.
|
||||
For exmaple, this packet performs a swap of registers r0 and r1
|
||||
{ r0 = r1; r1 = r0 }
|
||||
Note that the result is different if the instructions are executed serially.
|
||||
|
||||
Packet semantics dictate that we defer any changes of state until the entire
|
||||
packet is committed. We record the results of each instruction in a side data
|
||||
structure, and update the visible processor state when we commit the packet.
|
||||
|
||||
The data structures are divided between the runtime state and the translation
|
||||
context.
|
||||
|
||||
During the TCG generation (see translate.[ch]), we use the DisasContext to
|
||||
track what needs to be done during packet commit. Here are the relevant
|
||||
fields
|
||||
|
||||
reg_log list of registers written
|
||||
reg_log_idx index into ctx_reg_log
|
||||
pred_log list of predicates written
|
||||
pred_log_idx index into ctx_pred_log
|
||||
store_width width of stores (indexed by slot)
|
||||
|
||||
During runtime, the following fields in CPUHexagonState (see cpu.h) are used
|
||||
|
||||
new_value new value of a given register
|
||||
reg_written boolean indicating if register was written
|
||||
new_pred_value new value of a predicate register
|
||||
pred_written boolean indicating if predicate was written
|
||||
mem_log_stores record of the stores (indexed by slot)
|
||||
|
||||
*** Debugging ***
|
||||
|
||||
You can turn on a lot of debugging by changing the HEX_DEBUG macro to 1 in
|
||||
internal.h. This will stream a lot of information as it generates TCG and
|
||||
executes the code.
|
||||
|
||||
To track down nasty issues with Hexagon->TCG generation, we compare the
|
||||
execution results with actual hardware running on a Hexagon Linux target.
|
||||
Run qemu with the "-d cpu" option. Then, we can diff the results and figure
|
||||
out where qemu and hardware behave differently.
|
||||
|
||||
The stacks are located at different locations. We handle this by changing
|
||||
env->stack_adjust in translate.c. First, set this to zero and run qemu.
|
||||
Then, change env->stack_adjust to the difference between the two stack
|
||||
locations. Then rebuild qemu and run again. That will produce a very
|
||||
clean diff.
|
||||
|
||||
Here are some handy places to set breakpoints
|
||||
|
||||
At the call to gen_start_packet for a given PC (note that the line number
|
||||
might change in the future)
|
||||
br translate.c:602 if ctx->base.pc_next == 0xdeadbeef
|
||||
The helper function for each instruction is named helper_<TAG>, so here's
|
||||
an example that will set a breakpoint at the start
|
||||
br helper_A2_add
|
||||
If you have the HEX_DEBUG macro set, the following will be useful
|
||||
At the start of execution of a packet for a given PC
|
||||
br helper_debug_start_packet if env->gpr[41] == 0xdeadbeef
|
||||
At the end of execution of a packet for a given PC
|
||||
br helper_debug_commit_end if env->this_PC == 0xdeadbeef
|
300
target/hexagon/arch.c
Normal file
300
target/hexagon/arch.c
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "fpu/softfloat.h"
|
||||
#include "cpu.h"
|
||||
#include "fma_emu.h"
|
||||
#include "arch.h"
|
||||
#include "macros.h"
|
||||
|
||||
#define SF_BIAS 127
|
||||
#define SF_MAXEXP 254
|
||||
#define SF_MANTBITS 23
|
||||
#define float32_nan make_float32(0xffffffff)
|
||||
|
||||
#define BITS_MASK_8 0x5555555555555555ULL
|
||||
#define PAIR_MASK_8 0x3333333333333333ULL
|
||||
#define NYBL_MASK_8 0x0f0f0f0f0f0f0f0fULL
|
||||
#define BYTE_MASK_8 0x00ff00ff00ff00ffULL
|
||||
#define HALF_MASK_8 0x0000ffff0000ffffULL
|
||||
#define WORD_MASK_8 0x00000000ffffffffULL
|
||||
|
||||
uint64_t interleave(uint32_t odd, uint32_t even)
|
||||
{
|
||||
/* Convert to long long */
|
||||
uint64_t myodd = odd;
|
||||
uint64_t myeven = even;
|
||||
/* First, spread bits out */
|
||||
myodd = (myodd | (myodd << 16)) & HALF_MASK_8;
|
||||
myeven = (myeven | (myeven << 16)) & HALF_MASK_8;
|
||||
myodd = (myodd | (myodd << 8)) & BYTE_MASK_8;
|
||||
myeven = (myeven | (myeven << 8)) & BYTE_MASK_8;
|
||||
myodd = (myodd | (myodd << 4)) & NYBL_MASK_8;
|
||||
myeven = (myeven | (myeven << 4)) & NYBL_MASK_8;
|
||||
myodd = (myodd | (myodd << 2)) & PAIR_MASK_8;
|
||||
myeven = (myeven | (myeven << 2)) & PAIR_MASK_8;
|
||||
myodd = (myodd | (myodd << 1)) & BITS_MASK_8;
|
||||
myeven = (myeven | (myeven << 1)) & BITS_MASK_8;
|
||||
/* Now OR together */
|
||||
return myeven | (myodd << 1);
|
||||
}
|
||||
|
||||
uint64_t deinterleave(uint64_t src)
|
||||
{
|
||||
/* Get odd and even bits */
|
||||
uint64_t myodd = ((src >> 1) & BITS_MASK_8);
|
||||
uint64_t myeven = (src & BITS_MASK_8);
|
||||
|
||||
/* Unspread bits */
|
||||
myeven = (myeven | (myeven >> 1)) & PAIR_MASK_8;
|
||||
myodd = (myodd | (myodd >> 1)) & PAIR_MASK_8;
|
||||
myeven = (myeven | (myeven >> 2)) & NYBL_MASK_8;
|
||||
myodd = (myodd | (myodd >> 2)) & NYBL_MASK_8;
|
||||
myeven = (myeven | (myeven >> 4)) & BYTE_MASK_8;
|
||||
myodd = (myodd | (myodd >> 4)) & BYTE_MASK_8;
|
||||
myeven = (myeven | (myeven >> 8)) & HALF_MASK_8;
|
||||
myodd = (myodd | (myodd >> 8)) & HALF_MASK_8;
|
||||
myeven = (myeven | (myeven >> 16)) & WORD_MASK_8;
|
||||
myodd = (myodd | (myodd >> 16)) & WORD_MASK_8;
|
||||
|
||||
/* Return odd bits in upper half */
|
||||
return myeven | (myodd << 32);
|
||||
}
|
||||
|
||||
uint32_t carry_from_add64(uint64_t a, uint64_t b, uint32_t c)
|
||||
{
|
||||
uint64_t tmpa, tmpb, tmpc;
|
||||
tmpa = fGETUWORD(0, a);
|
||||
tmpb = fGETUWORD(0, b);
|
||||
tmpc = tmpa + tmpb + c;
|
||||
tmpa = fGETUWORD(1, a);
|
||||
tmpb = fGETUWORD(1, b);
|
||||
tmpc = tmpa + tmpb + fGETUWORD(1, tmpc);
|
||||
tmpc = fGETUWORD(1, tmpc);
|
||||
return tmpc;
|
||||
}
|
||||
|
||||
int32_t conv_round(int32_t a, int n)
|
||||
{
|
||||
int64_t val;
|
||||
|
||||
if (n == 0) {
|
||||
val = a;
|
||||
} else if ((a & ((1 << (n - 1)) - 1)) == 0) { /* N-1..0 all zero? */
|
||||
/* Add LSB from int part */
|
||||
val = ((fSE32_64(a)) + (int64_t) (((uint32_t) ((1 << n) & a)) >> 1));
|
||||
} else {
|
||||
val = ((fSE32_64(a)) + (1 << (n - 1)));
|
||||
}
|
||||
|
||||
val = val >> n;
|
||||
return (int32_t)val;
|
||||
}
|
||||
|
||||
/* Floating Point Stuff */
|
||||
|
||||
static const int softfloat_roundingmodes[] = {
|
||||
float_round_nearest_even,
|
||||
float_round_to_zero,
|
||||
float_round_down,
|
||||
float_round_up,
|
||||
};
|
||||
|
||||
void arch_fpop_start(CPUHexagonState *env)
|
||||
{
|
||||
set_float_exception_flags(0, &env->fp_status);
|
||||
set_float_rounding_mode(
|
||||
softfloat_roundingmodes[fREAD_REG_FIELD(USR, USR_FPRND)],
|
||||
&env->fp_status);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/*
|
||||
* Hexagon Linux kernel only sets the relevant bits in USR (user status
|
||||
* register). The exception isn't raised to user mode, so we don't
|
||||
* model it in qemu user mode.
|
||||
*/
|
||||
#define RAISE_FP_EXCEPTION do {} while (0)
|
||||
#endif
|
||||
|
||||
#define SOFTFLOAT_TEST_FLAG(FLAG, MYF, MYE) \
|
||||
do { \
|
||||
if (flags & FLAG) { \
|
||||
if (GET_USR_FIELD(USR_##MYF) == 0) { \
|
||||
SET_USR_FIELD(USR_##MYF, 1); \
|
||||
if (GET_USR_FIELD(USR_##MYE)) { \
|
||||
RAISE_FP_EXCEPTION; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void arch_fpop_end(CPUHexagonState *env)
|
||||
{
|
||||
int flags = get_float_exception_flags(&env->fp_status);
|
||||
if (flags != 0) {
|
||||
SOFTFLOAT_TEST_FLAG(float_flag_inexact, FPINPF, FPINPE);
|
||||
SOFTFLOAT_TEST_FLAG(float_flag_divbyzero, FPDBZF, FPDBZE);
|
||||
SOFTFLOAT_TEST_FLAG(float_flag_invalid, FPINVF, FPINVE);
|
||||
SOFTFLOAT_TEST_FLAG(float_flag_overflow, FPOVFF, FPOVFE);
|
||||
SOFTFLOAT_TEST_FLAG(float_flag_underflow, FPUNFF, FPUNFE);
|
||||
}
|
||||
}
|
||||
|
||||
static float32 float32_mul_pow2(float32 a, uint32_t p, float_status *fp_status)
|
||||
{
|
||||
float32 b = make_float32((SF_BIAS + p) << SF_MANTBITS);
|
||||
return float32_mul(a, b, fp_status);
|
||||
}
|
||||
|
||||
int arch_sf_recip_common(float32 *Rs, float32 *Rt, float32 *Rd, int *adjust,
|
||||
float_status *fp_status)
|
||||
{
|
||||
int n_exp;
|
||||
int d_exp;
|
||||
int ret = 0;
|
||||
float32 RsV, RtV, RdV;
|
||||
int PeV = 0;
|
||||
RsV = *Rs;
|
||||
RtV = *Rt;
|
||||
if (float32_is_any_nan(RsV) && float32_is_any_nan(RtV)) {
|
||||
if (extract32(RsV & RtV, 22, 1) == 0) {
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
}
|
||||
RdV = RsV = RtV = float32_nan;
|
||||
} else if (float32_is_any_nan(RsV)) {
|
||||
if (extract32(RsV, 22, 1) == 0) {
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
}
|
||||
RdV = RsV = RtV = float32_nan;
|
||||
} else if (float32_is_any_nan(RtV)) {
|
||||
/* or put NaN in num/den fixup? */
|
||||
if (extract32(RtV, 22, 1) == 0) {
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
}
|
||||
RdV = RsV = RtV = float32_nan;
|
||||
} else if (float32_is_infinity(RsV) && float32_is_infinity(RtV)) {
|
||||
/* or put Inf in num fixup? */
|
||||
RdV = RsV = RtV = float32_nan;
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
} else if (float32_is_zero(RsV) && float32_is_zero(RtV)) {
|
||||
/* or put zero in num fixup? */
|
||||
RdV = RsV = RtV = float32_nan;
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
} else if (float32_is_zero(RtV)) {
|
||||
/* or put Inf in num fixup? */
|
||||
uint8_t RsV_sign = float32_is_neg(RsV);
|
||||
uint8_t RtV_sign = float32_is_neg(RtV);
|
||||
RsV = infinite_float32(RsV_sign ^ RtV_sign);
|
||||
RtV = float32_one;
|
||||
RdV = float32_one;
|
||||
if (float32_is_infinity(RsV)) {
|
||||
float_raise(float_flag_divbyzero, fp_status);
|
||||
}
|
||||
} else if (float32_is_infinity(RtV)) {
|
||||
RsV = make_float32(0x80000000 & (RsV ^ RtV));
|
||||
RtV = float32_one;
|
||||
RdV = float32_one;
|
||||
} else if (float32_is_zero(RsV)) {
|
||||
/* Does this just work itself out? */
|
||||
/* No, 0/Inf causes problems. */
|
||||
RsV = make_float32(0x80000000 & (RsV ^ RtV));
|
||||
RtV = float32_one;
|
||||
RdV = float32_one;
|
||||
} else if (float32_is_infinity(RsV)) {
|
||||
uint8_t RsV_sign = float32_is_neg(RsV);
|
||||
uint8_t RtV_sign = float32_is_neg(RtV);
|
||||
RsV = infinite_float32(RsV_sign ^ RtV_sign);
|
||||
RtV = float32_one;
|
||||
RdV = float32_one;
|
||||
} else {
|
||||
PeV = 0x00;
|
||||
/* Basic checks passed */
|
||||
n_exp = float32_getexp(RsV);
|
||||
d_exp = float32_getexp(RtV);
|
||||
if ((n_exp - d_exp + SF_BIAS) <= SF_MANTBITS) {
|
||||
/* Near quotient underflow / inexact Q */
|
||||
PeV = 0x80;
|
||||
RtV = float32_mul_pow2(RtV, -64, fp_status);
|
||||
RsV = float32_mul_pow2(RsV, 64, fp_status);
|
||||
} else if ((n_exp - d_exp + SF_BIAS) > (SF_MAXEXP - 24)) {
|
||||
/* Near quotient overflow */
|
||||
PeV = 0x40;
|
||||
RtV = float32_mul_pow2(RtV, 32, fp_status);
|
||||
RsV = float32_mul_pow2(RsV, -32, fp_status);
|
||||
} else if (n_exp <= SF_MANTBITS + 2) {
|
||||
RtV = float32_mul_pow2(RtV, 64, fp_status);
|
||||
RsV = float32_mul_pow2(RsV, 64, fp_status);
|
||||
} else if (d_exp <= 1) {
|
||||
RtV = float32_mul_pow2(RtV, 32, fp_status);
|
||||
RsV = float32_mul_pow2(RsV, 32, fp_status);
|
||||
} else if (d_exp > 252) {
|
||||
RtV = float32_mul_pow2(RtV, -32, fp_status);
|
||||
RsV = float32_mul_pow2(RsV, -32, fp_status);
|
||||
}
|
||||
RdV = 0;
|
||||
ret = 1;
|
||||
}
|
||||
*Rs = RsV;
|
||||
*Rt = RtV;
|
||||
*Rd = RdV;
|
||||
*adjust = PeV;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int arch_sf_invsqrt_common(float32 *Rs, float32 *Rd, int *adjust,
|
||||
float_status *fp_status)
|
||||
{
|
||||
float32 RsV, RdV;
|
||||
int PeV = 0;
|
||||
int r_exp;
|
||||
int ret = 0;
|
||||
RsV = *Rs;
|
||||
if (float32_is_infinity(RsV)) {
|
||||
if (extract32(RsV, 22, 1) == 0) {
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
}
|
||||
RdV = RsV = float32_nan;
|
||||
} else if (float32_lt(RsV, float32_zero, fp_status)) {
|
||||
/* Negative nonzero values are NaN */
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
RsV = float32_nan;
|
||||
RdV = float32_nan;
|
||||
} else if (float32_is_infinity(RsV)) {
|
||||
/* or put Inf in num fixup? */
|
||||
RsV = infinite_float32(1);
|
||||
RdV = infinite_float32(1);
|
||||
} else if (float32_is_zero(RsV)) {
|
||||
/* or put zero in num fixup? */
|
||||
RdV = float32_one;
|
||||
} else {
|
||||
PeV = 0x00;
|
||||
/* Basic checks passed */
|
||||
r_exp = float32_getexp(RsV);
|
||||
if (r_exp <= 24) {
|
||||
RsV = float32_mul_pow2(RsV, 64, fp_status);
|
||||
PeV = 0xe0;
|
||||
}
|
||||
RdV = 0;
|
||||
ret = 1;
|
||||
}
|
||||
*Rs = RsV;
|
||||
*Rd = RdV;
|
||||
*adjust = PeV;
|
||||
return ret;
|
||||
}
|
34
target/hexagon/arch.h
Normal file
34
target/hexagon/arch.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_ARCH_H
|
||||
#define HEXAGON_ARCH_H
|
||||
|
||||
#include "qemu/int128.h"
|
||||
|
||||
uint64_t interleave(uint32_t odd, uint32_t even);
|
||||
uint64_t deinterleave(uint64_t src);
|
||||
uint32_t carry_from_add64(uint64_t a, uint64_t b, uint32_t c);
|
||||
int32_t conv_round(int32_t a, int n);
|
||||
void arch_fpop_start(CPUHexagonState *env);
|
||||
void arch_fpop_end(CPUHexagonState *env);
|
||||
int arch_sf_recip_common(float32 *Rs, float32 *Rt, float32 *Rd,
|
||||
int *adjust, float_status *fp_status);
|
||||
int arch_sf_invsqrt_common(float32 *Rs, float32 *Rd, int *adjust,
|
||||
float_status *fp_status);
|
||||
|
||||
#endif
|
35
target/hexagon/attribs.h
Normal file
35
target/hexagon/attribs.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_ATTRIBS_H
|
||||
#define HEXAGON_ATTRIBS_H
|
||||
|
||||
#include "qemu/bitmap.h"
|
||||
#include "opcodes.h"
|
||||
|
||||
enum {
|
||||
#define DEF_ATTRIB(NAME, ...) A_##NAME,
|
||||
#include "attribs_def.h.inc"
|
||||
#undef DEF_ATTRIB
|
||||
};
|
||||
|
||||
extern DECLARE_BITMAP(opcode_attribs[XX_LAST_OPCODE], A_ZZ_LASTATTRIB);
|
||||
|
||||
#define GET_ATTRIB(opcode, attrib) \
|
||||
test_bit(attrib, opcode_attribs[opcode])
|
||||
|
||||
#endif /* ATTRIBS_H */
|
97
target/hexagon/attribs_def.h.inc
Normal file
97
target/hexagon/attribs_def.h.inc
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Keep this as the first attribute: */
|
||||
DEF_ATTRIB(AA_DUMMY, "Dummy Zeroth Attribute", "", "")
|
||||
|
||||
/* Misc */
|
||||
DEF_ATTRIB(EXTENSION, "Extension instruction", "", "")
|
||||
|
||||
DEF_ATTRIB(PRIV, "Not available in user or guest mode", "", "")
|
||||
DEF_ATTRIB(GUEST, "Not available in user mode", "", "")
|
||||
|
||||
DEF_ATTRIB(FPOP, "Floating Point Operation", "", "")
|
||||
|
||||
DEF_ATTRIB(EXTENDABLE, "Immediate may be extended", "", "")
|
||||
|
||||
DEF_ATTRIB(ARCHV2, "V2 architecture", "", "")
|
||||
DEF_ATTRIB(ARCHV3, "V3 architecture", "", "")
|
||||
DEF_ATTRIB(ARCHV4, "V4 architecture", "", "")
|
||||
DEF_ATTRIB(ARCHV5, "V5 architecture", "", "")
|
||||
|
||||
DEF_ATTRIB(SUBINSN, "sub-instruction", "", "")
|
||||
|
||||
/* Load and Store attributes */
|
||||
DEF_ATTRIB(LOAD, "Loads from memory", "", "")
|
||||
DEF_ATTRIB(STORE, "Stores to memory", "", "")
|
||||
DEF_ATTRIB(MEMLIKE, "Memory-like instruction", "", "")
|
||||
DEF_ATTRIB(MEMLIKE_PACKET_RULES, "follows Memory-like packet rules", "", "")
|
||||
|
||||
|
||||
/* Change-of-flow attributes */
|
||||
DEF_ATTRIB(JUMP, "Jump-type instruction", "", "")
|
||||
DEF_ATTRIB(INDIRECT, "Absolute register jump", "", "")
|
||||
DEF_ATTRIB(CALL, "Function call instruction", "", "")
|
||||
DEF_ATTRIB(COF, "Change-of-flow instruction", "", "")
|
||||
DEF_ATTRIB(CONDEXEC, "May be cancelled by a predicate", "", "")
|
||||
DEF_ATTRIB(DOTNEWVALUE, "Uses a register value generated in this pkt", "", "")
|
||||
DEF_ATTRIB(NEWCMPJUMP, "Compound compare and jump", "", "")
|
||||
|
||||
/* access to implicit registers */
|
||||
DEF_ATTRIB(IMPLICIT_WRITES_LR, "Writes the link register", "", "UREG.LR")
|
||||
DEF_ATTRIB(IMPLICIT_WRITES_SP, "Writes the stack pointer", "", "UREG.SP")
|
||||
DEF_ATTRIB(IMPLICIT_WRITES_FP, "Writes the frame pointer", "", "UREG.FP")
|
||||
DEF_ATTRIB(IMPLICIT_WRITES_LC0, "Writes loop count for loop 0", "", "UREG.LC0")
|
||||
DEF_ATTRIB(IMPLICIT_WRITES_LC1, "Writes loop count for loop 1", "", "UREG.LC1")
|
||||
DEF_ATTRIB(IMPLICIT_WRITES_SA0, "Writes start addr for loop 0", "", "UREG.SA0")
|
||||
DEF_ATTRIB(IMPLICIT_WRITES_SA1, "Writes start addr for loop 1", "", "UREG.SA1")
|
||||
DEF_ATTRIB(IMPLICIT_WRITES_P0, "Writes Predicate 0", "", "UREG.P0")
|
||||
DEF_ATTRIB(IMPLICIT_WRITES_P1, "Writes Predicate 1", "", "UREG.P1")
|
||||
DEF_ATTRIB(IMPLICIT_WRITES_P2, "Writes Predicate 1", "", "UREG.P2")
|
||||
DEF_ATTRIB(IMPLICIT_WRITES_P3, "May write Predicate 3", "", "UREG.P3")
|
||||
DEF_ATTRIB(IMPLICIT_READS_PC, "Reads the PC register", "", "")
|
||||
DEF_ATTRIB(WRITES_PRED_REG, "Writes a predicate register", "", "")
|
||||
|
||||
DEF_ATTRIB(CRSLOT23, "Can execute in slot 2 or slot 3 (CR)", "", "")
|
||||
DEF_ATTRIB(IT_NOP, "nop instruction", "", "")
|
||||
DEF_ATTRIB(IT_EXTENDER, "constant extender instruction", "", "")
|
||||
|
||||
|
||||
/* Restrictions to make note of */
|
||||
DEF_ATTRIB(RESTRICT_SLOT0ONLY, "Must execute on slot0", "", "")
|
||||
DEF_ATTRIB(RESTRICT_SLOT1ONLY, "Must execute on slot1", "", "")
|
||||
DEF_ATTRIB(RESTRICT_SLOT2ONLY, "Must execute on slot2", "", "")
|
||||
DEF_ATTRIB(RESTRICT_SLOT3ONLY, "Must execute on slot3", "", "")
|
||||
DEF_ATTRIB(RESTRICT_NOSLOT1, "No slot 1 instruction in parallel", "", "")
|
||||
DEF_ATTRIB(RESTRICT_PREFERSLOT0, "Try to encode into slot 0", "", "")
|
||||
|
||||
DEF_ATTRIB(ICOP, "Instruction cache op", "", "")
|
||||
|
||||
DEF_ATTRIB(HWLOOP0_END, "Ends HW loop0", "", "")
|
||||
DEF_ATTRIB(HWLOOP1_END, "Ends HW loop1", "", "")
|
||||
DEF_ATTRIB(DCZEROA, "dczeroa type", "", "")
|
||||
DEF_ATTRIB(ICFLUSHOP, "icflush op type", "", "")
|
||||
DEF_ATTRIB(DCFLUSHOP, "dcflush op type", "", "")
|
||||
DEF_ATTRIB(DCFETCH, "dcfetch type", "", "")
|
||||
|
||||
DEF_ATTRIB(L2FETCH, "Instruction is l2fetch type", "", "")
|
||||
|
||||
DEF_ATTRIB(ICINVA, "icinva", "", "")
|
||||
DEF_ATTRIB(DCCLEANINVA, "dccleaninva", "", "")
|
||||
|
||||
/* Keep this as the last attribute: */
|
||||
DEF_ATTRIB(ZZ_LASTATTRIB, "Last attribute in the file", "", "")
|
177
target/hexagon/conv_emu.c
Normal file
177
target/hexagon/conv_emu.c
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "fpu/softfloat.h"
|
||||
#include "macros.h"
|
||||
#include "conv_emu.h"
|
||||
|
||||
#define LL_MAX_POS 0x7fffffffffffffffULL
|
||||
#define MAX_POS 0x7fffffffU
|
||||
|
||||
static uint64_t conv_f64_to_8u_n(float64 in, int will_negate,
|
||||
float_status *fp_status)
|
||||
{
|
||||
uint8_t sign = float64_is_neg(in);
|
||||
if (float64_is_infinity(in)) {
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
if (float64_is_neg(in)) {
|
||||
return 0ULL;
|
||||
} else {
|
||||
return ~0ULL;
|
||||
}
|
||||
}
|
||||
if (float64_is_any_nan(in)) {
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
return ~0ULL;
|
||||
}
|
||||
if (float64_is_zero(in)) {
|
||||
return 0;
|
||||
}
|
||||
if (sign) {
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
return 0;
|
||||
}
|
||||
if (float64_lt(in, float64_half, fp_status)) {
|
||||
/* Near zero, captures large fracshifts, denorms, etc */
|
||||
float_raise(float_flag_inexact, fp_status);
|
||||
switch (get_float_rounding_mode(fp_status)) {
|
||||
case float_round_down:
|
||||
if (will_negate) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
case float_round_up:
|
||||
if (!will_negate) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
return 0; /* nearest or towards zero */
|
||||
}
|
||||
}
|
||||
return float64_to_uint64(in, fp_status);
|
||||
}
|
||||
|
||||
static void clr_float_exception_flags(uint8_t flag, float_status *fp_status)
|
||||
{
|
||||
uint8_t flags = fp_status->float_exception_flags;
|
||||
flags &= ~flag;
|
||||
set_float_exception_flags(flags, fp_status);
|
||||
}
|
||||
|
||||
static uint32_t conv_df_to_4u_n(float64 fp64, int will_negate,
|
||||
float_status *fp_status)
|
||||
{
|
||||
uint64_t tmp;
|
||||
tmp = conv_f64_to_8u_n(fp64, will_negate, fp_status);
|
||||
if (tmp > 0x00000000ffffffffULL) {
|
||||
clr_float_exception_flags(float_flag_inexact, fp_status);
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
return ~0U;
|
||||
}
|
||||
return (uint32_t)tmp;
|
||||
}
|
||||
|
||||
uint64_t conv_df_to_8u(float64 in, float_status *fp_status)
|
||||
{
|
||||
return conv_f64_to_8u_n(in, 0, fp_status);
|
||||
}
|
||||
|
||||
uint32_t conv_df_to_4u(float64 in, float_status *fp_status)
|
||||
{
|
||||
return conv_df_to_4u_n(in, 0, fp_status);
|
||||
}
|
||||
|
||||
int64_t conv_df_to_8s(float64 in, float_status *fp_status)
|
||||
{
|
||||
uint8_t sign = float64_is_neg(in);
|
||||
uint64_t tmp;
|
||||
if (float64_is_any_nan(in)) {
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
return -1;
|
||||
}
|
||||
if (sign) {
|
||||
float64 minus_fp64 = float64_abs(in);
|
||||
tmp = conv_f64_to_8u_n(minus_fp64, 1, fp_status);
|
||||
} else {
|
||||
tmp = conv_f64_to_8u_n(in, 0, fp_status);
|
||||
}
|
||||
if (tmp > (LL_MAX_POS + sign)) {
|
||||
clr_float_exception_flags(float_flag_inexact, fp_status);
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
tmp = (LL_MAX_POS + sign);
|
||||
}
|
||||
if (sign) {
|
||||
return -tmp;
|
||||
} else {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t conv_df_to_4s(float64 in, float_status *fp_status)
|
||||
{
|
||||
uint8_t sign = float64_is_neg(in);
|
||||
uint64_t tmp;
|
||||
if (float64_is_any_nan(in)) {
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
return -1;
|
||||
}
|
||||
if (sign) {
|
||||
float64 minus_fp64 = float64_abs(in);
|
||||
tmp = conv_f64_to_8u_n(minus_fp64, 1, fp_status);
|
||||
} else {
|
||||
tmp = conv_f64_to_8u_n(in, 0, fp_status);
|
||||
}
|
||||
if (tmp > (MAX_POS + sign)) {
|
||||
clr_float_exception_flags(float_flag_inexact, fp_status);
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
tmp = (MAX_POS + sign);
|
||||
}
|
||||
if (sign) {
|
||||
return -tmp;
|
||||
} else {
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t conv_sf_to_8u(float32 in, float_status *fp_status)
|
||||
{
|
||||
float64 fp64 = float32_to_float64(in, fp_status);
|
||||
return conv_df_to_8u(fp64, fp_status);
|
||||
}
|
||||
|
||||
uint32_t conv_sf_to_4u(float32 in, float_status *fp_status)
|
||||
{
|
||||
float64 fp64 = float32_to_float64(in, fp_status);
|
||||
return conv_df_to_4u(fp64, fp_status);
|
||||
}
|
||||
|
||||
int64_t conv_sf_to_8s(float32 in, float_status *fp_status)
|
||||
{
|
||||
float64 fp64 = float32_to_float64(in, fp_status);
|
||||
return conv_df_to_8s(fp64, fp_status);
|
||||
}
|
||||
|
||||
int32_t conv_sf_to_4s(float32 in, float_status *fp_status)
|
||||
{
|
||||
float64 fp64 = float32_to_float64(in, fp_status);
|
||||
return conv_df_to_4s(fp64, fp_status);
|
||||
}
|
31
target/hexagon/conv_emu.h
Normal file
31
target/hexagon/conv_emu.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_CONV_EMU_H
|
||||
#define HEXAGON_CONV_EMU_H
|
||||
|
||||
uint64_t conv_sf_to_8u(float32 in, float_status *fp_status);
|
||||
uint32_t conv_sf_to_4u(float32 in, float_status *fp_status);
|
||||
int64_t conv_sf_to_8s(float32 in, float_status *fp_status);
|
||||
int32_t conv_sf_to_4s(float32 in, float_status *fp_status);
|
||||
|
||||
uint64_t conv_df_to_8u(float64 in, float_status *fp_status);
|
||||
uint32_t conv_df_to_4u(float64 in, float_status *fp_status);
|
||||
int64_t conv_df_to_8s(float64 in, float_status *fp_status);
|
||||
int32_t conv_df_to_4s(float64 in, float_status *fp_status);
|
||||
|
||||
#endif
|
29
target/hexagon/cpu-param.h
Normal file
29
target/hexagon/cpu-param.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_CPU_PARAM_H
|
||||
#define HEXAGON_CPU_PARAM_H
|
||||
|
||||
#define TARGET_PAGE_BITS 16 /* 64K pages */
|
||||
#define TARGET_LONG_BITS 32
|
||||
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 36
|
||||
#define TARGET_VIRT_ADDR_SPACE_BITS 32
|
||||
|
||||
#define NB_MMU_MODES 1
|
||||
|
||||
#endif
|
318
target/hexagon/cpu.c
Normal file
318
target/hexagon/cpu.c
Normal file
@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
|
||||
static void hexagon_v67_cpu_init(Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
static ObjectClass *hexagon_cpu_class_by_name(const char *cpu_model)
|
||||
{
|
||||
ObjectClass *oc;
|
||||
char *typename;
|
||||
char **cpuname;
|
||||
|
||||
cpuname = g_strsplit(cpu_model, ",", 1);
|
||||
typename = g_strdup_printf(HEXAGON_CPU_TYPE_NAME("%s"), cpuname[0]);
|
||||
oc = object_class_by_name(typename);
|
||||
g_strfreev(cpuname);
|
||||
g_free(typename);
|
||||
if (!oc || !object_class_dynamic_cast(oc, TYPE_HEXAGON_CPU) ||
|
||||
object_class_is_abstract(oc)) {
|
||||
return NULL;
|
||||
}
|
||||
return oc;
|
||||
}
|
||||
|
||||
static Property hexagon_lldb_compat_property =
|
||||
DEFINE_PROP_BOOL("lldb-compat", HexagonCPU, lldb_compat, false);
|
||||
static Property hexagon_lldb_stack_adjust_property =
|
||||
DEFINE_PROP_UNSIGNED("lldb-stack-adjust", HexagonCPU, lldb_stack_adjust,
|
||||
0, qdev_prop_uint32, target_ulong);
|
||||
|
||||
const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS] = {
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
||||
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
|
||||
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
|
||||
"sa0", "lc0", "sa1", "lc1", "p3_0", "c5", "m0", "m1",
|
||||
"usr", "pc", "ugp", "gp", "cs0", "cs1", "c14", "c15",
|
||||
"c16", "c17", "c18", "c19", "pkt_cnt", "insn_cnt", "c22", "c23",
|
||||
"c24", "c25", "c26", "c27", "c28", "c29", "c30", "c31",
|
||||
};
|
||||
|
||||
/*
|
||||
* One of the main debugging techniques is to use "-d cpu" and compare against
|
||||
* LLDB output when single stepping. However, the target and qemu put the
|
||||
* stacks at different locations. This is used to compensate so the diff is
|
||||
* cleaner.
|
||||
*/
|
||||
static inline target_ulong adjust_stack_ptrs(CPUHexagonState *env,
|
||||
target_ulong addr)
|
||||
{
|
||||
HexagonCPU *cpu = container_of(env, HexagonCPU, env);
|
||||
target_ulong stack_adjust = cpu->lldb_stack_adjust;
|
||||
target_ulong stack_start = env->stack_start;
|
||||
target_ulong stack_size = 0x10000;
|
||||
|
||||
if (stack_adjust == 0) {
|
||||
return addr;
|
||||
}
|
||||
|
||||
if (stack_start + 0x1000 >= addr && addr >= (stack_start - stack_size)) {
|
||||
return addr - stack_adjust;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* HEX_REG_P3_0 (aka C4) is an alias for the predicate registers */
|
||||
static inline target_ulong read_p3_0(CPUHexagonState *env)
|
||||
{
|
||||
int32_t control_reg = 0;
|
||||
int i;
|
||||
for (i = NUM_PREGS - 1; i >= 0; i--) {
|
||||
control_reg <<= 8;
|
||||
control_reg |= env->pred[i] & 0xff;
|
||||
}
|
||||
return control_reg;
|
||||
}
|
||||
|
||||
static void print_reg(FILE *f, CPUHexagonState *env, int regnum)
|
||||
{
|
||||
target_ulong value;
|
||||
|
||||
if (regnum == HEX_REG_P3_0) {
|
||||
value = read_p3_0(env);
|
||||
} else {
|
||||
value = regnum < 32 ? adjust_stack_ptrs(env, env->gpr[regnum])
|
||||
: env->gpr[regnum];
|
||||
}
|
||||
|
||||
qemu_fprintf(f, " %s = 0x" TARGET_FMT_lx "\n",
|
||||
hexagon_regnames[regnum], value);
|
||||
}
|
||||
|
||||
static void hexagon_dump(CPUHexagonState *env, FILE *f)
|
||||
{
|
||||
HexagonCPU *cpu = container_of(env, HexagonCPU, env);
|
||||
|
||||
if (cpu->lldb_compat) {
|
||||
/*
|
||||
* When comparing with LLDB, it doesn't step through single-cycle
|
||||
* hardware loops the same way. So, we just skip them here
|
||||
*/
|
||||
if (env->gpr[HEX_REG_PC] == env->last_pc_dumped) {
|
||||
return;
|
||||
}
|
||||
env->last_pc_dumped = env->gpr[HEX_REG_PC];
|
||||
}
|
||||
|
||||
qemu_fprintf(f, "General Purpose Registers = {\n");
|
||||
for (int i = 0; i < 32; i++) {
|
||||
print_reg(f, env, i);
|
||||
}
|
||||
print_reg(f, env, HEX_REG_SA0);
|
||||
print_reg(f, env, HEX_REG_LC0);
|
||||
print_reg(f, env, HEX_REG_SA1);
|
||||
print_reg(f, env, HEX_REG_LC1);
|
||||
print_reg(f, env, HEX_REG_M0);
|
||||
print_reg(f, env, HEX_REG_M1);
|
||||
print_reg(f, env, HEX_REG_USR);
|
||||
print_reg(f, env, HEX_REG_P3_0);
|
||||
print_reg(f, env, HEX_REG_GP);
|
||||
print_reg(f, env, HEX_REG_UGP);
|
||||
print_reg(f, env, HEX_REG_PC);
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/*
|
||||
* Not modelled in user mode, print junk to minimize the diff's
|
||||
* with LLDB output
|
||||
*/
|
||||
qemu_fprintf(f, " cause = 0x000000db\n");
|
||||
qemu_fprintf(f, " badva = 0x00000000\n");
|
||||
qemu_fprintf(f, " cs0 = 0x00000000\n");
|
||||
qemu_fprintf(f, " cs1 = 0x00000000\n");
|
||||
#else
|
||||
print_reg(f, env, HEX_REG_CAUSE);
|
||||
print_reg(f, env, HEX_REG_BADVA);
|
||||
print_reg(f, env, HEX_REG_CS0);
|
||||
print_reg(f, env, HEX_REG_CS1);
|
||||
#endif
|
||||
qemu_fprintf(f, "}\n");
|
||||
}
|
||||
|
||||
static void hexagon_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
{
|
||||
HexagonCPU *cpu = HEXAGON_CPU(cs);
|
||||
CPUHexagonState *env = &cpu->env;
|
||||
|
||||
hexagon_dump(env, f);
|
||||
}
|
||||
|
||||
void hexagon_debug(CPUHexagonState *env)
|
||||
{
|
||||
hexagon_dump(env, stdout);
|
||||
}
|
||||
|
||||
static void hexagon_cpu_set_pc(CPUState *cs, vaddr value)
|
||||
{
|
||||
HexagonCPU *cpu = HEXAGON_CPU(cs);
|
||||
CPUHexagonState *env = &cpu->env;
|
||||
env->gpr[HEX_REG_PC] = value;
|
||||
}
|
||||
|
||||
static void hexagon_cpu_synchronize_from_tb(CPUState *cs,
|
||||
const TranslationBlock *tb)
|
||||
{
|
||||
HexagonCPU *cpu = HEXAGON_CPU(cs);
|
||||
CPUHexagonState *env = &cpu->env;
|
||||
env->gpr[HEX_REG_PC] = tb->pc;
|
||||
}
|
||||
|
||||
static bool hexagon_cpu_has_work(CPUState *cs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void restore_state_to_opc(CPUHexagonState *env, TranslationBlock *tb,
|
||||
target_ulong *data)
|
||||
{
|
||||
env->gpr[HEX_REG_PC] = data[0];
|
||||
}
|
||||
|
||||
static void hexagon_cpu_reset(DeviceState *dev)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
HexagonCPU *cpu = HEXAGON_CPU(cs);
|
||||
HexagonCPUClass *mcc = HEXAGON_CPU_GET_CLASS(cpu);
|
||||
|
||||
mcc->parent_reset(dev);
|
||||
}
|
||||
|
||||
static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info)
|
||||
{
|
||||
info->print_insn = print_insn_hexagon;
|
||||
}
|
||||
|
||||
static void hexagon_cpu_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
HexagonCPUClass *mcc = HEXAGON_CPU_GET_CLASS(dev);
|
||||
Error *local_err = NULL;
|
||||
|
||||
cpu_exec_realizefn(cs, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_init_vcpu(cs);
|
||||
cpu_reset(cs);
|
||||
|
||||
mcc->parent_realize(dev, errp);
|
||||
}
|
||||
|
||||
static void hexagon_cpu_init(Object *obj)
|
||||
{
|
||||
HexagonCPU *cpu = HEXAGON_CPU(obj);
|
||||
|
||||
cpu_set_cpustate_pointers(cpu);
|
||||
qdev_property_add_static(DEVICE(obj), &hexagon_lldb_compat_property);
|
||||
qdev_property_add_static(DEVICE(obj), &hexagon_lldb_stack_adjust_property);
|
||||
}
|
||||
|
||||
static bool hexagon_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool probe, uintptr_t retaddr)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
switch (access_type) {
|
||||
case MMU_INST_FETCH:
|
||||
cs->exception_index = HEX_EXCP_FETCH_NO_UPAGE;
|
||||
break;
|
||||
case MMU_DATA_LOAD:
|
||||
cs->exception_index = HEX_EXCP_PRIV_NO_UREAD;
|
||||
break;
|
||||
case MMU_DATA_STORE:
|
||||
cs->exception_index = HEX_EXCP_PRIV_NO_UWRITE;
|
||||
break;
|
||||
}
|
||||
cpu_loop_exit_restore(cs, retaddr);
|
||||
#else
|
||||
#error System mode not implemented for Hexagon
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "hw/core/tcg-cpu-ops.h"
|
||||
|
||||
static struct TCGCPUOps hexagon_tcg_ops = {
|
||||
.initialize = hexagon_translate_init,
|
||||
.synchronize_from_tb = hexagon_cpu_synchronize_from_tb,
|
||||
.tlb_fill = hexagon_tlb_fill,
|
||||
};
|
||||
|
||||
static void hexagon_cpu_class_init(ObjectClass *c, void *data)
|
||||
{
|
||||
HexagonCPUClass *mcc = HEXAGON_CPU_CLASS(c);
|
||||
CPUClass *cc = CPU_CLASS(c);
|
||||
DeviceClass *dc = DEVICE_CLASS(c);
|
||||
|
||||
device_class_set_parent_realize(dc, hexagon_cpu_realize,
|
||||
&mcc->parent_realize);
|
||||
|
||||
device_class_set_parent_reset(dc, hexagon_cpu_reset, &mcc->parent_reset);
|
||||
|
||||
cc->class_by_name = hexagon_cpu_class_by_name;
|
||||
cc->has_work = hexagon_cpu_has_work;
|
||||
cc->dump_state = hexagon_dump_state;
|
||||
cc->set_pc = hexagon_cpu_set_pc;
|
||||
cc->gdb_read_register = hexagon_gdb_read_register;
|
||||
cc->gdb_write_register = hexagon_gdb_write_register;
|
||||
cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS;
|
||||
cc->gdb_stop_before_watchpoint = true;
|
||||
cc->disas_set_info = hexagon_cpu_disas_set_info;
|
||||
cc->tcg_ops = &hexagon_tcg_ops;
|
||||
}
|
||||
|
||||
#define DEFINE_CPU(type_name, initfn) \
|
||||
{ \
|
||||
.name = type_name, \
|
||||
.parent = TYPE_HEXAGON_CPU, \
|
||||
.instance_init = initfn \
|
||||
}
|
||||
|
||||
static const TypeInfo hexagon_cpu_type_infos[] = {
|
||||
{
|
||||
.name = TYPE_HEXAGON_CPU,
|
||||
.parent = TYPE_CPU,
|
||||
.instance_size = sizeof(HexagonCPU),
|
||||
.instance_init = hexagon_cpu_init,
|
||||
.abstract = true,
|
||||
.class_size = sizeof(HexagonCPUClass),
|
||||
.class_init = hexagon_cpu_class_init,
|
||||
},
|
||||
DEFINE_CPU(TYPE_HEXAGON_CPU_V67, hexagon_v67_cpu_init),
|
||||
};
|
||||
|
||||
DEFINE_TYPES(hexagon_cpu_type_infos)
|
159
target/hexagon/cpu.h
Normal file
159
target/hexagon/cpu.h
Normal file
@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_CPU_H
|
||||
#define HEXAGON_CPU_H
|
||||
|
||||
/* Forward declaration needed by some of the header files */
|
||||
typedef struct CPUHexagonState CPUHexagonState;
|
||||
|
||||
#include "fpu/softfloat-types.h"
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "exec/cpu-defs.h"
|
||||
#include "hex_regs.h"
|
||||
|
||||
#define NUM_PREGS 4
|
||||
#define TOTAL_PER_THREAD_REGS 64
|
||||
|
||||
#define SLOTS_MAX 4
|
||||
#define STORES_MAX 2
|
||||
#define REG_WRITES_MAX 32
|
||||
#define PRED_WRITES_MAX 5 /* 4 insns + endloop */
|
||||
|
||||
#define TYPE_HEXAGON_CPU "hexagon-cpu"
|
||||
|
||||
#define HEXAGON_CPU_TYPE_SUFFIX "-" TYPE_HEXAGON_CPU
|
||||
#define HEXAGON_CPU_TYPE_NAME(name) (name HEXAGON_CPU_TYPE_SUFFIX)
|
||||
#define CPU_RESOLVING_TYPE TYPE_HEXAGON_CPU
|
||||
|
||||
#define TYPE_HEXAGON_CPU_V67 HEXAGON_CPU_TYPE_NAME("v67")
|
||||
|
||||
#define MMU_USER_IDX 0
|
||||
|
||||
typedef struct {
|
||||
target_ulong va;
|
||||
uint8_t width;
|
||||
uint32_t data32;
|
||||
uint64_t data64;
|
||||
} MemLog;
|
||||
|
||||
#define EXEC_STATUS_OK 0x0000
|
||||
#define EXEC_STATUS_STOP 0x0002
|
||||
#define EXEC_STATUS_REPLAY 0x0010
|
||||
#define EXEC_STATUS_LOCKED 0x0020
|
||||
#define EXEC_STATUS_EXCEPTION 0x0100
|
||||
|
||||
|
||||
#define EXCEPTION_DETECTED (env->status & EXEC_STATUS_EXCEPTION)
|
||||
#define REPLAY_DETECTED (env->status & EXEC_STATUS_REPLAY)
|
||||
#define CLEAR_EXCEPTION (env->status &= (~EXEC_STATUS_EXCEPTION))
|
||||
#define SET_EXCEPTION (env->status |= EXEC_STATUS_EXCEPTION)
|
||||
|
||||
struct CPUHexagonState {
|
||||
target_ulong gpr[TOTAL_PER_THREAD_REGS];
|
||||
target_ulong pred[NUM_PREGS];
|
||||
target_ulong branch_taken;
|
||||
target_ulong next_PC;
|
||||
|
||||
/* For comparing with LLDB on target - see adjust_stack_ptrs function */
|
||||
target_ulong last_pc_dumped;
|
||||
target_ulong stack_start;
|
||||
|
||||
uint8_t slot_cancelled;
|
||||
target_ulong new_value[TOTAL_PER_THREAD_REGS];
|
||||
|
||||
/*
|
||||
* Only used when HEX_DEBUG is on, but unconditionally included
|
||||
* to reduce recompile time when turning HEX_DEBUG on/off.
|
||||
*/
|
||||
target_ulong this_PC;
|
||||
target_ulong reg_written[TOTAL_PER_THREAD_REGS];
|
||||
|
||||
target_ulong new_pred_value[NUM_PREGS];
|
||||
target_ulong pred_written;
|
||||
|
||||
MemLog mem_log_stores[STORES_MAX];
|
||||
target_ulong pkt_has_store_s1;
|
||||
target_ulong dczero_addr;
|
||||
|
||||
float_status fp_status;
|
||||
|
||||
target_ulong llsc_addr;
|
||||
target_ulong llsc_val;
|
||||
uint64_t llsc_val_i64;
|
||||
|
||||
target_ulong is_gather_store_insn;
|
||||
target_ulong gather_issued;
|
||||
};
|
||||
|
||||
#define HEXAGON_CPU_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(HexagonCPUClass, (klass), TYPE_HEXAGON_CPU)
|
||||
#define HEXAGON_CPU(obj) \
|
||||
OBJECT_CHECK(HexagonCPU, (obj), TYPE_HEXAGON_CPU)
|
||||
#define HEXAGON_CPU_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(HexagonCPUClass, (obj), TYPE_HEXAGON_CPU)
|
||||
|
||||
typedef struct HexagonCPUClass {
|
||||
/*< private >*/
|
||||
CPUClass parent_class;
|
||||
/*< public >*/
|
||||
DeviceRealize parent_realize;
|
||||
DeviceReset parent_reset;
|
||||
} HexagonCPUClass;
|
||||
|
||||
typedef struct HexagonCPU {
|
||||
/*< private >*/
|
||||
CPUState parent_obj;
|
||||
/*< public >*/
|
||||
CPUNegativeOffsetState neg;
|
||||
CPUHexagonState env;
|
||||
|
||||
bool lldb_compat;
|
||||
target_ulong lldb_stack_adjust;
|
||||
} HexagonCPU;
|
||||
|
||||
static inline HexagonCPU *hexagon_env_get_cpu(CPUHexagonState *env)
|
||||
{
|
||||
return container_of(env, HexagonCPU, env);
|
||||
}
|
||||
|
||||
#include "cpu_bits.h"
|
||||
|
||||
#define cpu_signal_handler cpu_hexagon_signal_handler
|
||||
int cpu_hexagon_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUHexagonState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, uint32_t *flags)
|
||||
{
|
||||
*pc = env->gpr[HEX_REG_PC];
|
||||
*cs_base = 0;
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
*flags = 0;
|
||||
#else
|
||||
#error System mode not supported on Hexagon yet
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef struct CPUHexagonState CPUArchState;
|
||||
typedef HexagonCPU ArchCPU;
|
||||
|
||||
void hexagon_translate_init(void);
|
||||
|
||||
#include "exec/cpu-all.h"
|
||||
|
||||
#endif /* HEXAGON_CPU_H */
|
58
target/hexagon/cpu_bits.h
Normal file
58
target/hexagon/cpu_bits.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_CPU_BITS_H
|
||||
#define HEXAGON_CPU_BITS_H
|
||||
|
||||
#include "qemu/bitops.h"
|
||||
|
||||
#define HEX_EXCP_FETCH_NO_UPAGE 0x012
|
||||
#define HEX_EXCP_INVALID_PACKET 0x015
|
||||
#define HEX_EXCP_INVALID_OPCODE 0x015
|
||||
#define HEX_EXCP_PRIV_NO_UREAD 0x024
|
||||
#define HEX_EXCP_PRIV_NO_UWRITE 0x025
|
||||
|
||||
#define HEX_EXCP_TRAP0 0x172
|
||||
|
||||
#define PACKET_WORDS_MAX 4
|
||||
|
||||
static inline uint32_t parse_bits(uint32_t encoding)
|
||||
{
|
||||
/* The parse bits are [15:14] */
|
||||
return extract32(encoding, 14, 2);
|
||||
}
|
||||
|
||||
static inline uint32_t iclass_bits(uint32_t encoding)
|
||||
{
|
||||
/* The instruction class is encoded in bits [31:28] */
|
||||
uint32_t iclass = extract32(encoding, 28, 4);
|
||||
/* If parse bits are zero, this is a duplex */
|
||||
if (parse_bits(encoding) == 0) {
|
||||
iclass += 16;
|
||||
}
|
||||
return iclass;
|
||||
}
|
||||
|
||||
static inline int is_packet_end(uint32_t endocing)
|
||||
{
|
||||
uint32_t bits = parse_bits(endocing);
|
||||
return ((bits == 0x3) || (bits == 0x0));
|
||||
}
|
||||
|
||||
int disassemble_hexagon(uint32_t *words, int nwords, bfd_vma pc, GString *buf);
|
||||
|
||||
#endif
|
957
target/hexagon/decode.c
Normal file
957
target/hexagon/decode.c
Normal file
@ -0,0 +1,957 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "iclass.h"
|
||||
#include "attribs.h"
|
||||
#include "genptr.h"
|
||||
#include "decode.h"
|
||||
#include "insn.h"
|
||||
#include "printinsn.h"
|
||||
|
||||
#define fZXTN(N, M, VAL) ((VAL) & ((1LL << (N)) - 1))
|
||||
|
||||
enum {
|
||||
EXT_IDX_noext = 0,
|
||||
EXT_IDX_noext_AFTER = 4,
|
||||
EXT_IDX_mmvec = 4,
|
||||
EXT_IDX_mmvec_AFTER = 8,
|
||||
XX_LAST_EXT_IDX
|
||||
};
|
||||
|
||||
/*
|
||||
* Certain operand types represent a non-contiguous set of values.
|
||||
* For example, the compound compare-and-jump instruction can only access
|
||||
* registers R0-R7 and R16-23.
|
||||
* This table represents the mapping from the encoding to the actual values.
|
||||
*/
|
||||
|
||||
#define DEF_REGMAP(NAME, ELEMENTS, ...) \
|
||||
static const unsigned int DECODE_REGISTER_##NAME[ELEMENTS] = \
|
||||
{ __VA_ARGS__ };
|
||||
/* Name Num Table */
|
||||
DEF_REGMAP(R_16, 16, 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 23)
|
||||
DEF_REGMAP(R__8, 8, 0, 2, 4, 6, 16, 18, 20, 22)
|
||||
|
||||
#define DECODE_MAPPED_REG(REGNO, NAME) \
|
||||
insn->regno[REGNO] = DECODE_REGISTER_##NAME[insn->regno[REGNO]];
|
||||
|
||||
typedef struct {
|
||||
const struct DectreeTable *table_link;
|
||||
const struct DectreeTable *table_link_b;
|
||||
Opcode opcode;
|
||||
enum {
|
||||
DECTREE_ENTRY_INVALID,
|
||||
DECTREE_TABLE_LINK,
|
||||
DECTREE_SUBINSNS,
|
||||
DECTREE_EXTSPACE,
|
||||
DECTREE_TERMINAL
|
||||
} type;
|
||||
} DectreeEntry;
|
||||
|
||||
typedef struct DectreeTable {
|
||||
unsigned int (*lookup_function)(int startbit, int width, uint32_t opcode);
|
||||
unsigned int size;
|
||||
unsigned int startbit;
|
||||
unsigned int width;
|
||||
const DectreeEntry table[];
|
||||
} DectreeTable;
|
||||
|
||||
#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT) \
|
||||
static const DectreeTable dectree_table_##TAG;
|
||||
#define TABLE_LINK(TABLE) /* NOTHING */
|
||||
#define TERMINAL(TAG, ENC) /* NOTHING */
|
||||
#define SUBINSNS(TAG, CLASSA, CLASSB, ENC) /* NOTHING */
|
||||
#define EXTSPACE(TAG, ENC) /* NOTHING */
|
||||
#define INVALID() /* NOTHING */
|
||||
#define DECODE_END_TABLE(...) /* NOTHING */
|
||||
#define DECODE_MATCH_INFO(...) /* NOTHING */
|
||||
#define DECODE_LEGACY_MATCH_INFO(...) /* NOTHING */
|
||||
#define DECODE_OPINFO(...) /* NOTHING */
|
||||
|
||||
#include "dectree_generated.h.inc"
|
||||
|
||||
#undef DECODE_OPINFO
|
||||
#undef DECODE_MATCH_INFO
|
||||
#undef DECODE_LEGACY_MATCH_INFO
|
||||
#undef DECODE_END_TABLE
|
||||
#undef INVALID
|
||||
#undef TERMINAL
|
||||
#undef SUBINSNS
|
||||
#undef EXTSPACE
|
||||
#undef TABLE_LINK
|
||||
#undef DECODE_NEW_TABLE
|
||||
#undef DECODE_SEPARATOR_BITS
|
||||
|
||||
#define DECODE_SEPARATOR_BITS(START, WIDTH) NULL, START, WIDTH
|
||||
#define DECODE_NEW_TABLE_HELPER(TAG, SIZE, FN, START, WIDTH) \
|
||||
static const DectreeTable dectree_table_##TAG = { \
|
||||
.size = SIZE, \
|
||||
.lookup_function = FN, \
|
||||
.startbit = START, \
|
||||
.width = WIDTH, \
|
||||
.table = {
|
||||
#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT) \
|
||||
DECODE_NEW_TABLE_HELPER(TAG, SIZE, WHATNOT)
|
||||
|
||||
#define TABLE_LINK(TABLE) \
|
||||
{ .type = DECTREE_TABLE_LINK, .table_link = &dectree_table_##TABLE },
|
||||
#define TERMINAL(TAG, ENC) \
|
||||
{ .type = DECTREE_TERMINAL, .opcode = TAG },
|
||||
#define SUBINSNS(TAG, CLASSA, CLASSB, ENC) \
|
||||
{ \
|
||||
.type = DECTREE_SUBINSNS, \
|
||||
.table_link = &dectree_table_DECODE_SUBINSN_##CLASSA, \
|
||||
.table_link_b = &dectree_table_DECODE_SUBINSN_##CLASSB \
|
||||
},
|
||||
#define EXTSPACE(TAG, ENC) { .type = DECTREE_EXTSPACE },
|
||||
#define INVALID() { .type = DECTREE_ENTRY_INVALID, .opcode = XX_LAST_OPCODE },
|
||||
|
||||
#define DECODE_END_TABLE(...) } };
|
||||
|
||||
#define DECODE_MATCH_INFO(...) /* NOTHING */
|
||||
#define DECODE_LEGACY_MATCH_INFO(...) /* NOTHING */
|
||||
#define DECODE_OPINFO(...) /* NOTHING */
|
||||
|
||||
#include "dectree_generated.h.inc"
|
||||
|
||||
#undef DECODE_OPINFO
|
||||
#undef DECODE_MATCH_INFO
|
||||
#undef DECODE_LEGACY_MATCH_INFO
|
||||
#undef DECODE_END_TABLE
|
||||
#undef INVALID
|
||||
#undef TERMINAL
|
||||
#undef SUBINSNS
|
||||
#undef EXTSPACE
|
||||
#undef TABLE_LINK
|
||||
#undef DECODE_NEW_TABLE
|
||||
#undef DECODE_NEW_TABLE_HELPER
|
||||
#undef DECODE_SEPARATOR_BITS
|
||||
|
||||
static const DectreeTable dectree_table_DECODE_EXT_EXT_noext = {
|
||||
.size = 1, .lookup_function = NULL, .startbit = 0, .width = 0,
|
||||
.table = {
|
||||
{ .type = DECTREE_ENTRY_INVALID, .opcode = XX_LAST_OPCODE },
|
||||
}
|
||||
};
|
||||
|
||||
static const DectreeTable *ext_trees[XX_LAST_EXT_IDX];
|
||||
|
||||
static void decode_ext_init(void)
|
||||
{
|
||||
int i;
|
||||
for (i = EXT_IDX_noext; i < EXT_IDX_noext_AFTER; i++) {
|
||||
ext_trees[i] = &dectree_table_DECODE_EXT_EXT_noext;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint32_t mask;
|
||||
uint32_t match;
|
||||
} DecodeITableEntry;
|
||||
|
||||
#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT) /* NOTHING */
|
||||
#define TABLE_LINK(TABLE) /* NOTHING */
|
||||
#define TERMINAL(TAG, ENC) /* NOTHING */
|
||||
#define SUBINSNS(TAG, CLASSA, CLASSB, ENC) /* NOTHING */
|
||||
#define EXTSPACE(TAG, ENC) /* NOTHING */
|
||||
#define INVALID() /* NOTHING */
|
||||
#define DECODE_END_TABLE(...) /* NOTHING */
|
||||
#define DECODE_OPINFO(...) /* NOTHING */
|
||||
|
||||
#define DECODE_MATCH_INFO_NORMAL(TAG, MASK, MATCH) \
|
||||
[TAG] = { \
|
||||
.mask = MASK, \
|
||||
.match = MATCH, \
|
||||
},
|
||||
|
||||
#define DECODE_MATCH_INFO_NULL(TAG, MASK, MATCH) \
|
||||
[TAG] = { .match = ~0 },
|
||||
|
||||
#define DECODE_MATCH_INFO(...) DECODE_MATCH_INFO_NORMAL(__VA_ARGS__)
|
||||
#define DECODE_LEGACY_MATCH_INFO(...) /* NOTHING */
|
||||
|
||||
static const DecodeITableEntry decode_itable[XX_LAST_OPCODE] = {
|
||||
#include "dectree_generated.h.inc"
|
||||
};
|
||||
|
||||
#undef DECODE_MATCH_INFO
|
||||
#define DECODE_MATCH_INFO(...) DECODE_MATCH_INFO_NULL(__VA_ARGS__)
|
||||
|
||||
#undef DECODE_LEGACY_MATCH_INFO
|
||||
#define DECODE_LEGACY_MATCH_INFO(...) DECODE_MATCH_INFO_NORMAL(__VA_ARGS__)
|
||||
|
||||
static const DecodeITableEntry decode_legacy_itable[XX_LAST_OPCODE] = {
|
||||
#include "dectree_generated.h.inc"
|
||||
};
|
||||
|
||||
#undef DECODE_OPINFO
|
||||
#undef DECODE_MATCH_INFO
|
||||
#undef DECODE_LEGACY_MATCH_INFO
|
||||
#undef DECODE_END_TABLE
|
||||
#undef INVALID
|
||||
#undef TERMINAL
|
||||
#undef SUBINSNS
|
||||
#undef EXTSPACE
|
||||
#undef TABLE_LINK
|
||||
#undef DECODE_NEW_TABLE
|
||||
#undef DECODE_SEPARATOR_BITS
|
||||
|
||||
void decode_init(void)
|
||||
{
|
||||
decode_ext_init();
|
||||
}
|
||||
|
||||
void decode_send_insn_to(Packet *packet, int start, int newloc)
|
||||
{
|
||||
Insn tmpinsn;
|
||||
int direction;
|
||||
int i;
|
||||
if (start == newloc) {
|
||||
return;
|
||||
}
|
||||
if (start < newloc) {
|
||||
/* Move towards end */
|
||||
direction = 1;
|
||||
} else {
|
||||
/* move towards beginning */
|
||||
direction = -1;
|
||||
}
|
||||
for (i = start; i != newloc; i += direction) {
|
||||
tmpinsn = packet->insn[i];
|
||||
packet->insn[i] = packet->insn[i + direction];
|
||||
packet->insn[i + direction] = tmpinsn;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill newvalue registers with the correct regno */
|
||||
static void
|
||||
decode_fill_newvalue_regno(Packet *packet)
|
||||
{
|
||||
int i, use_regidx, offset, def_idx, dst_idx;
|
||||
uint16_t def_opcode, use_opcode;
|
||||
char *dststr;
|
||||
|
||||
for (i = 1; i < packet->num_insns; i++) {
|
||||
if (GET_ATTRIB(packet->insn[i].opcode, A_DOTNEWVALUE) &&
|
||||
!GET_ATTRIB(packet->insn[i].opcode, A_EXTENSION)) {
|
||||
use_opcode = packet->insn[i].opcode;
|
||||
|
||||
/* It's a store, so we're adjusting the Nt field */
|
||||
if (GET_ATTRIB(use_opcode, A_STORE)) {
|
||||
use_regidx = strchr(opcode_reginfo[use_opcode], 't') -
|
||||
opcode_reginfo[use_opcode];
|
||||
} else { /* It's a Jump, so we're adjusting the Ns field */
|
||||
use_regidx = strchr(opcode_reginfo[use_opcode], 's') -
|
||||
opcode_reginfo[use_opcode];
|
||||
}
|
||||
|
||||
/*
|
||||
* What's encoded at the N-field is the offset to who's producing
|
||||
* the value. Shift off the LSB which indicates odd/even register,
|
||||
* then walk backwards and skip over the constant extenders.
|
||||
*/
|
||||
offset = packet->insn[i].regno[use_regidx] >> 1;
|
||||
def_idx = i - offset;
|
||||
for (int j = 0; j < offset; j++) {
|
||||
if (GET_ATTRIB(packet->insn[i - j - 1].opcode, A_IT_EXTENDER)) {
|
||||
def_idx--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for a badly encoded N-field which points to an instruction
|
||||
* out-of-range
|
||||
*/
|
||||
g_assert(!((def_idx < 0) || (def_idx > (packet->num_insns - 1))));
|
||||
|
||||
/*
|
||||
* packet->insn[def_idx] is the producer
|
||||
* Figure out which type of destination it produces
|
||||
* and the corresponding index in the reginfo
|
||||
*/
|
||||
def_opcode = packet->insn[def_idx].opcode;
|
||||
dststr = strstr(opcode_wregs[def_opcode], "Rd");
|
||||
if (dststr) {
|
||||
dststr = strchr(opcode_reginfo[def_opcode], 'd');
|
||||
} else {
|
||||
dststr = strstr(opcode_wregs[def_opcode], "Rx");
|
||||
if (dststr) {
|
||||
dststr = strchr(opcode_reginfo[def_opcode], 'x');
|
||||
} else {
|
||||
dststr = strstr(opcode_wregs[def_opcode], "Re");
|
||||
if (dststr) {
|
||||
dststr = strchr(opcode_reginfo[def_opcode], 'e');
|
||||
} else {
|
||||
dststr = strstr(opcode_wregs[def_opcode], "Ry");
|
||||
if (dststr) {
|
||||
dststr = strchr(opcode_reginfo[def_opcode], 'y');
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g_assert(dststr != NULL);
|
||||
|
||||
/* Now patch up the consumer with the register number */
|
||||
dst_idx = dststr - opcode_reginfo[def_opcode];
|
||||
packet->insn[i].regno[use_regidx] =
|
||||
packet->insn[def_idx].regno[dst_idx];
|
||||
/*
|
||||
* We need to remember who produces this value to later
|
||||
* check if it was dynamically cancelled
|
||||
*/
|
||||
packet->insn[i].new_value_producer_slot =
|
||||
packet->insn[def_idx].slot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Split CJ into a compare and a jump */
|
||||
static void decode_split_cmpjump(Packet *pkt)
|
||||
{
|
||||
int last, i;
|
||||
int numinsns = pkt->num_insns;
|
||||
|
||||
/*
|
||||
* First, split all compare-jumps.
|
||||
* The compare is sent to the end as a new instruction.
|
||||
* Do it this way so we don't reorder dual jumps. Those need to stay in
|
||||
* original order.
|
||||
*/
|
||||
for (i = 0; i < numinsns; i++) {
|
||||
/* It's a cmp-jump */
|
||||
if (GET_ATTRIB(pkt->insn[i].opcode, A_NEWCMPJUMP)) {
|
||||
last = pkt->num_insns;
|
||||
pkt->insn[last] = pkt->insn[i]; /* copy the instruction */
|
||||
pkt->insn[last].part1 = 1; /* last instruction does the CMP */
|
||||
pkt->insn[i].part1 = 0; /* existing instruction does the JUMP */
|
||||
pkt->num_insns++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now re-shuffle all the compares back to the beginning */
|
||||
for (i = 0; i < pkt->num_insns; i++) {
|
||||
if (pkt->insn[i].part1) {
|
||||
decode_send_insn_to(pkt, i, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline int decode_opcode_can_jump(int opcode)
|
||||
{
|
||||
if ((GET_ATTRIB(opcode, A_JUMP)) ||
|
||||
(GET_ATTRIB(opcode, A_CALL)) ||
|
||||
(opcode == J2_trap0) ||
|
||||
(opcode == J2_pause)) {
|
||||
/* Exception to A_JUMP attribute */
|
||||
if (opcode == J4_hintjumpr) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int decode_opcode_ends_loop(int opcode)
|
||||
{
|
||||
return GET_ATTRIB(opcode, A_HWLOOP0_END) ||
|
||||
GET_ATTRIB(opcode, A_HWLOOP1_END);
|
||||
}
|
||||
|
||||
/* Set the is_* fields in each instruction */
|
||||
static void decode_set_insn_attr_fields(Packet *pkt)
|
||||
{
|
||||
int i;
|
||||
int numinsns = pkt->num_insns;
|
||||
uint16_t opcode;
|
||||
|
||||
pkt->pkt_has_cof = 0;
|
||||
pkt->pkt_has_endloop = 0;
|
||||
pkt->pkt_has_dczeroa = 0;
|
||||
|
||||
for (i = 0; i < numinsns; i++) {
|
||||
opcode = pkt->insn[i].opcode;
|
||||
if (pkt->insn[i].part1) {
|
||||
continue; /* Skip compare of cmp-jumps */
|
||||
}
|
||||
|
||||
if (GET_ATTRIB(opcode, A_DCZEROA)) {
|
||||
pkt->pkt_has_dczeroa = 1;
|
||||
}
|
||||
|
||||
if (GET_ATTRIB(opcode, A_STORE)) {
|
||||
if (pkt->insn[i].slot == 0) {
|
||||
pkt->pkt_has_store_s0 = 1;
|
||||
} else {
|
||||
pkt->pkt_has_store_s1 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
pkt->pkt_has_cof |= decode_opcode_can_jump(opcode);
|
||||
|
||||
pkt->insn[i].is_endloop = decode_opcode_ends_loop(opcode);
|
||||
|
||||
pkt->pkt_has_endloop |= pkt->insn[i].is_endloop;
|
||||
|
||||
pkt->pkt_has_cof |= pkt->pkt_has_endloop;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Shuffle for execution
|
||||
* Move stores to end (in same order as encoding)
|
||||
* Move compares to beginning (for use by .new insns)
|
||||
*/
|
||||
static void decode_shuffle_for_execution(Packet *packet)
|
||||
{
|
||||
int changed = 0;
|
||||
int i;
|
||||
int flag; /* flag means we've seen a non-memory instruction */
|
||||
int n_mems;
|
||||
int last_insn = packet->num_insns - 1;
|
||||
|
||||
/*
|
||||
* Skip end loops, somehow an end loop is getting in and messing
|
||||
* up the order
|
||||
*/
|
||||
if (decode_opcode_ends_loop(packet->insn[last_insn].opcode)) {
|
||||
last_insn--;
|
||||
}
|
||||
|
||||
do {
|
||||
changed = 0;
|
||||
/*
|
||||
* Stores go last, must not reorder.
|
||||
* Cannot shuffle stores past loads, either.
|
||||
* Iterate backwards. If we see a non-memory instruction,
|
||||
* then a store, shuffle the store to the front. Don't shuffle
|
||||
* stores wrt each other or a load.
|
||||
*/
|
||||
for (flag = n_mems = 0, i = last_insn; i >= 0; i--) {
|
||||
int opcode = packet->insn[i].opcode;
|
||||
|
||||
if (flag && GET_ATTRIB(opcode, A_STORE)) {
|
||||
decode_send_insn_to(packet, i, last_insn - n_mems);
|
||||
n_mems++;
|
||||
changed = 1;
|
||||
} else if (GET_ATTRIB(opcode, A_STORE)) {
|
||||
n_mems++;
|
||||
} else if (GET_ATTRIB(opcode, A_LOAD)) {
|
||||
/*
|
||||
* Don't set flag, since we don't want to shuffle a
|
||||
* store past a load
|
||||
*/
|
||||
n_mems++;
|
||||
} else if (GET_ATTRIB(opcode, A_DOTNEWVALUE)) {
|
||||
/*
|
||||
* Don't set flag, since we don't want to shuffle past
|
||||
* a .new value
|
||||
*/
|
||||
} else {
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
continue;
|
||||
}
|
||||
/* Compares go first, may be reordered wrt each other */
|
||||
for (flag = 0, i = 0; i < last_insn + 1; i++) {
|
||||
int opcode = packet->insn[i].opcode;
|
||||
|
||||
if ((strstr(opcode_wregs[opcode], "Pd4") ||
|
||||
strstr(opcode_wregs[opcode], "Pe4")) &&
|
||||
GET_ATTRIB(opcode, A_STORE) == 0) {
|
||||
/* This should be a compare (not a store conditional) */
|
||||
if (flag) {
|
||||
decode_send_insn_to(packet, i, 0);
|
||||
changed = 1;
|
||||
continue;
|
||||
}
|
||||
} else if (GET_ATTRIB(opcode, A_IMPLICIT_WRITES_P3) &&
|
||||
!decode_opcode_ends_loop(packet->insn[i].opcode)) {
|
||||
/*
|
||||
* spNloop instruction
|
||||
* Don't reorder endloops; they are not valid for .new uses,
|
||||
* and we want to match HW
|
||||
*/
|
||||
if (flag) {
|
||||
decode_send_insn_to(packet, i, 0);
|
||||
changed = 1;
|
||||
continue;
|
||||
}
|
||||
} else if (GET_ATTRIB(opcode, A_IMPLICIT_WRITES_P0) &&
|
||||
!GET_ATTRIB(opcode, A_NEWCMPJUMP)) {
|
||||
if (flag) {
|
||||
decode_send_insn_to(packet, i, 0);
|
||||
changed = 1;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
flag = 1;
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
continue;
|
||||
}
|
||||
} while (changed);
|
||||
|
||||
/*
|
||||
* If we have a .new register compare/branch, move that to the very
|
||||
* very end, past stores
|
||||
*/
|
||||
for (i = 0; i < last_insn; i++) {
|
||||
if (GET_ATTRIB(packet->insn[i].opcode, A_DOTNEWVALUE)) {
|
||||
decode_send_insn_to(packet, i, last_insn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
apply_extender(Packet *pkt, int i, uint32_t extender)
|
||||
{
|
||||
int immed_num;
|
||||
uint32_t base_immed;
|
||||
|
||||
immed_num = opcode_which_immediate_is_extended(pkt->insn[i].opcode);
|
||||
base_immed = pkt->insn[i].immed[immed_num];
|
||||
|
||||
pkt->insn[i].immed[immed_num] = extender | fZXTN(6, 32, base_immed);
|
||||
}
|
||||
|
||||
static void decode_apply_extenders(Packet *packet)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < packet->num_insns; i++) {
|
||||
if (GET_ATTRIB(packet->insn[i].opcode, A_IT_EXTENDER)) {
|
||||
packet->insn[i + 1].extension_valid = 1;
|
||||
apply_extender(packet, i + 1, packet->insn[i].immed[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_remove_extenders(Packet *packet)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < packet->num_insns; i++) {
|
||||
if (GET_ATTRIB(packet->insn[i].opcode, A_IT_EXTENDER)) {
|
||||
/* Remove this one by moving the remaining instructions down */
|
||||
for (j = i;
|
||||
(j < packet->num_insns - 1) && (j < INSTRUCTIONS_MAX - 1);
|
||||
j++) {
|
||||
packet->insn[j] = packet->insn[j + 1];
|
||||
}
|
||||
packet->num_insns--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SlotMask get_valid_slots(const Packet *pkt, unsigned int slot)
|
||||
{
|
||||
return find_iclass_slots(pkt->insn[slot].opcode,
|
||||
pkt->insn[slot].iclass);
|
||||
}
|
||||
|
||||
#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT) /* NOTHING */
|
||||
#define TABLE_LINK(TABLE) /* NOTHING */
|
||||
#define TERMINAL(TAG, ENC) /* NOTHING */
|
||||
#define SUBINSNS(TAG, CLASSA, CLASSB, ENC) /* NOTHING */
|
||||
#define EXTSPACE(TAG, ENC) /* NOTHING */
|
||||
#define INVALID() /* NOTHING */
|
||||
#define DECODE_END_TABLE(...) /* NOTHING */
|
||||
#define DECODE_MATCH_INFO(...) /* NOTHING */
|
||||
#define DECODE_LEGACY_MATCH_INFO(...) /* NOTHING */
|
||||
|
||||
#define DECODE_REG(REGNO, WIDTH, STARTBIT) \
|
||||
insn->regno[REGNO] = ((encoding >> STARTBIT) & ((1 << WIDTH) - 1));
|
||||
|
||||
#define DECODE_IMPL_REG(REGNO, VAL) \
|
||||
insn->regno[REGNO] = VAL;
|
||||
|
||||
#define DECODE_IMM(IMMNO, WIDTH, STARTBIT, VALSTART) \
|
||||
insn->immed[IMMNO] |= (((encoding >> STARTBIT) & ((1 << WIDTH) - 1))) << \
|
||||
(VALSTART);
|
||||
|
||||
#define DECODE_IMM_SXT(IMMNO, WIDTH) \
|
||||
insn->immed[IMMNO] = ((((int32_t)insn->immed[IMMNO]) << (32 - WIDTH)) >> \
|
||||
(32 - WIDTH));
|
||||
|
||||
#define DECODE_IMM_NEG(IMMNO, WIDTH) \
|
||||
insn->immed[IMMNO] = -insn->immed[IMMNO];
|
||||
|
||||
#define DECODE_IMM_SHIFT(IMMNO, SHAMT) \
|
||||
if ((!insn->extension_valid) || \
|
||||
(insn->which_extended != IMMNO)) { \
|
||||
insn->immed[IMMNO] <<= SHAMT; \
|
||||
}
|
||||
|
||||
#define DECODE_OPINFO(TAG, BEH) \
|
||||
case TAG: \
|
||||
{ BEH } \
|
||||
break; \
|
||||
|
||||
/*
|
||||
* Fill in the operands of the instruction
|
||||
* dectree_generated.h.inc has a DECODE_OPINFO entry for each opcode
|
||||
* For example,
|
||||
* DECODE_OPINFO(A2_addi,
|
||||
* DECODE_REG(0,5,0)
|
||||
* DECODE_REG(1,5,16)
|
||||
* DECODE_IMM(0,7,21,9)
|
||||
* DECODE_IMM(0,9,5,0)
|
||||
* DECODE_IMM_SXT(0,16)
|
||||
* with the macros defined above, we'll fill in a switch statement
|
||||
* where each case is an opcode tag.
|
||||
*/
|
||||
static void
|
||||
decode_op(Insn *insn, Opcode tag, uint32_t encoding)
|
||||
{
|
||||
insn->immed[0] = 0;
|
||||
insn->immed[1] = 0;
|
||||
insn->opcode = tag;
|
||||
if (insn->extension_valid) {
|
||||
insn->which_extended = opcode_which_immediate_is_extended(tag);
|
||||
}
|
||||
|
||||
switch (tag) {
|
||||
#include "dectree_generated.h.inc"
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
insn->generate = opcode_genptr[tag];
|
||||
|
||||
insn->iclass = iclass_bits(encoding);
|
||||
}
|
||||
|
||||
#undef DECODE_REG
|
||||
#undef DECODE_IMPL_REG
|
||||
#undef DECODE_IMM
|
||||
#undef DECODE_IMM_SHIFT
|
||||
#undef DECODE_OPINFO
|
||||
#undef DECODE_MATCH_INFO
|
||||
#undef DECODE_LEGACY_MATCH_INFO
|
||||
#undef DECODE_END_TABLE
|
||||
#undef INVALID
|
||||
#undef TERMINAL
|
||||
#undef SUBINSNS
|
||||
#undef EXTSPACE
|
||||
#undef TABLE_LINK
|
||||
#undef DECODE_NEW_TABLE
|
||||
#undef DECODE_SEPARATOR_BITS
|
||||
|
||||
static unsigned int
|
||||
decode_subinsn_tablewalk(Insn *insn, const DectreeTable *table,
|
||||
uint32_t encoding)
|
||||
{
|
||||
unsigned int i;
|
||||
Opcode opc;
|
||||
if (table->lookup_function) {
|
||||
i = table->lookup_function(table->startbit, table->width, encoding);
|
||||
} else {
|
||||
i = extract32(encoding, table->startbit, table->width);
|
||||
}
|
||||
if (table->table[i].type == DECTREE_TABLE_LINK) {
|
||||
return decode_subinsn_tablewalk(insn, table->table[i].table_link,
|
||||
encoding);
|
||||
} else if (table->table[i].type == DECTREE_TERMINAL) {
|
||||
opc = table->table[i].opcode;
|
||||
if ((encoding & decode_itable[opc].mask) != decode_itable[opc].match) {
|
||||
return 0;
|
||||
}
|
||||
decode_op(insn, opc, encoding);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int get_insn_a(uint32_t encoding)
|
||||
{
|
||||
return extract32(encoding, 0, 13);
|
||||
}
|
||||
|
||||
static unsigned int get_insn_b(uint32_t encoding)
|
||||
{
|
||||
return extract32(encoding, 16, 13);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
decode_insns_tablewalk(Insn *insn, const DectreeTable *table,
|
||||
uint32_t encoding)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int a, b;
|
||||
Opcode opc;
|
||||
if (table->lookup_function) {
|
||||
i = table->lookup_function(table->startbit, table->width, encoding);
|
||||
} else {
|
||||
i = extract32(encoding, table->startbit, table->width);
|
||||
}
|
||||
if (table->table[i].type == DECTREE_TABLE_LINK) {
|
||||
return decode_insns_tablewalk(insn, table->table[i].table_link,
|
||||
encoding);
|
||||
} else if (table->table[i].type == DECTREE_SUBINSNS) {
|
||||
a = get_insn_a(encoding);
|
||||
b = get_insn_b(encoding);
|
||||
b = decode_subinsn_tablewalk(insn, table->table[i].table_link_b, b);
|
||||
a = decode_subinsn_tablewalk(insn + 1, table->table[i].table_link, a);
|
||||
if ((a == 0) || (b == 0)) {
|
||||
return 0;
|
||||
}
|
||||
return 2;
|
||||
} else if (table->table[i].type == DECTREE_TERMINAL) {
|
||||
opc = table->table[i].opcode;
|
||||
if ((encoding & decode_itable[opc].mask) != decode_itable[opc].match) {
|
||||
if ((encoding & decode_legacy_itable[opc].mask) !=
|
||||
decode_legacy_itable[opc].match) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
decode_op(insn, opc, encoding);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
decode_insns(Insn *insn, uint32_t encoding)
|
||||
{
|
||||
const DectreeTable *table;
|
||||
if (parse_bits(encoding) != 0) {
|
||||
/* Start with PP table - 32 bit instructions */
|
||||
table = &dectree_table_DECODE_ROOT_32;
|
||||
} else {
|
||||
/* start with EE table - duplex instructions */
|
||||
table = &dectree_table_DECODE_ROOT_EE;
|
||||
}
|
||||
return decode_insns_tablewalk(insn, table, encoding);
|
||||
}
|
||||
|
||||
static void decode_add_endloop_insn(Insn *insn, int loopnum)
|
||||
{
|
||||
if (loopnum == 10) {
|
||||
insn->opcode = J2_endloop01;
|
||||
insn->generate = opcode_genptr[J2_endloop01];
|
||||
} else if (loopnum == 1) {
|
||||
insn->opcode = J2_endloop1;
|
||||
insn->generate = opcode_genptr[J2_endloop1];
|
||||
} else if (loopnum == 0) {
|
||||
insn->opcode = J2_endloop0;
|
||||
insn->generate = opcode_genptr[J2_endloop0];
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
static inline int decode_parsebits_is_loopend(uint32_t encoding32)
|
||||
{
|
||||
uint32_t bits = parse_bits(encoding32);
|
||||
return bits == 0x2;
|
||||
}
|
||||
|
||||
static void
|
||||
decode_set_slot_number(Packet *pkt)
|
||||
{
|
||||
int slot;
|
||||
int i;
|
||||
int hit_mem_insn = 0;
|
||||
int hit_duplex = 0;
|
||||
|
||||
/*
|
||||
* The slots are encoded in reverse order
|
||||
* For each instruction, count down until you find a suitable slot
|
||||
*/
|
||||
for (i = 0, slot = 3; i < pkt->num_insns; i++) {
|
||||
SlotMask valid_slots = get_valid_slots(pkt, i);
|
||||
|
||||
while (!(valid_slots & (1 << slot))) {
|
||||
slot--;
|
||||
}
|
||||
pkt->insn[i].slot = slot;
|
||||
if (slot) {
|
||||
/* I've assigned the slot, now decrement it for the next insn */
|
||||
slot--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix the exceptions - mem insns to slot 0,1 */
|
||||
for (i = pkt->num_insns - 1; i >= 0; i--) {
|
||||
/* First memory instruction always goes to slot 0 */
|
||||
if ((GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE) ||
|
||||
GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE_PACKET_RULES)) &&
|
||||
!hit_mem_insn) {
|
||||
hit_mem_insn = 1;
|
||||
pkt->insn[i].slot = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Next memory instruction always goes to slot 1 */
|
||||
if ((GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE) ||
|
||||
GET_ATTRIB(pkt->insn[i].opcode, A_MEMLIKE_PACKET_RULES)) &&
|
||||
hit_mem_insn) {
|
||||
pkt->insn[i].slot = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix the exceptions - duplex always slot 0,1 */
|
||||
for (i = pkt->num_insns - 1; i >= 0; i--) {
|
||||
/* First subinsn always goes to slot 0 */
|
||||
if (GET_ATTRIB(pkt->insn[i].opcode, A_SUBINSN) && !hit_duplex) {
|
||||
hit_duplex = 1;
|
||||
pkt->insn[i].slot = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Next subinsn always goes to slot 1 */
|
||||
if (GET_ATTRIB(pkt->insn[i].opcode, A_SUBINSN) && hit_duplex) {
|
||||
pkt->insn[i].slot = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix the exceptions - slot 1 is never empty, always aligns to slot 0 */
|
||||
int slot0_found = 0;
|
||||
int slot1_found = 0;
|
||||
int slot1_iidx = 0;
|
||||
for (i = pkt->num_insns - 1; i >= 0; i--) {
|
||||
/* Is slot0 used? */
|
||||
if (pkt->insn[i].slot == 0) {
|
||||
int is_endloop = (pkt->insn[i].opcode == J2_endloop01);
|
||||
is_endloop |= (pkt->insn[i].opcode == J2_endloop0);
|
||||
is_endloop |= (pkt->insn[i].opcode == J2_endloop1);
|
||||
|
||||
/*
|
||||
* Make sure it's not endloop since, we're overloading
|
||||
* slot0 for endloop
|
||||
*/
|
||||
if (!is_endloop) {
|
||||
slot0_found = 1;
|
||||
}
|
||||
}
|
||||
/* Is slot1 used? */
|
||||
if (pkt->insn[i].slot == 1) {
|
||||
slot1_found = 1;
|
||||
slot1_iidx = i;
|
||||
}
|
||||
}
|
||||
/* Is slot0 empty and slot1 used? */
|
||||
if ((slot0_found == 0) && (slot1_found == 1)) {
|
||||
/* Then push it to slot0 */
|
||||
pkt->insn[slot1_iidx].slot = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* decode_packet
|
||||
* Decodes packet with given words
|
||||
* Returns 0 on insufficient words,
|
||||
* or number of words used on success
|
||||
*/
|
||||
|
||||
int decode_packet(int max_words, const uint32_t *words, Packet *pkt,
|
||||
bool disas_only)
|
||||
{
|
||||
int num_insns = 0;
|
||||
int words_read = 0;
|
||||
int end_of_packet = 0;
|
||||
int new_insns = 0;
|
||||
uint32_t encoding32;
|
||||
|
||||
/* Initialize */
|
||||
memset(pkt, 0, sizeof(*pkt));
|
||||
/* Try to build packet */
|
||||
while (!end_of_packet && (words_read < max_words)) {
|
||||
encoding32 = words[words_read];
|
||||
end_of_packet = is_packet_end(encoding32);
|
||||
new_insns = decode_insns(&pkt->insn[num_insns], encoding32);
|
||||
g_assert(new_insns > 0);
|
||||
/*
|
||||
* If we saw an extender, mark next word extended so immediate
|
||||
* decode works
|
||||
*/
|
||||
if (pkt->insn[num_insns].opcode == A4_ext) {
|
||||
pkt->insn[num_insns + 1].extension_valid = 1;
|
||||
}
|
||||
num_insns += new_insns;
|
||||
words_read++;
|
||||
}
|
||||
|
||||
pkt->num_insns = num_insns;
|
||||
if (!end_of_packet) {
|
||||
/* Ran out of words! */
|
||||
return 0;
|
||||
}
|
||||
pkt->encod_pkt_size_in_bytes = words_read * 4;
|
||||
|
||||
/*
|
||||
* Check for :endloop in the parse bits
|
||||
* Section 10.6 of the Programmer's Reference describes the encoding
|
||||
* The end of hardware loop 0 can be encoded with 2 words
|
||||
* The end of hardware loop 1 needs 3 words
|
||||
*/
|
||||
if ((words_read == 2) && (decode_parsebits_is_loopend(words[0]))) {
|
||||
decode_add_endloop_insn(&pkt->insn[pkt->num_insns++], 0);
|
||||
}
|
||||
if (words_read >= 3) {
|
||||
uint32_t has_loop0, has_loop1;
|
||||
has_loop0 = decode_parsebits_is_loopend(words[0]);
|
||||
has_loop1 = decode_parsebits_is_loopend(words[1]);
|
||||
if (has_loop0 && has_loop1) {
|
||||
decode_add_endloop_insn(&pkt->insn[pkt->num_insns++], 10);
|
||||
} else if (has_loop1) {
|
||||
decode_add_endloop_insn(&pkt->insn[pkt->num_insns++], 1);
|
||||
} else if (has_loop0) {
|
||||
decode_add_endloop_insn(&pkt->insn[pkt->num_insns++], 0);
|
||||
}
|
||||
}
|
||||
|
||||
decode_apply_extenders(pkt);
|
||||
if (!disas_only) {
|
||||
decode_remove_extenders(pkt);
|
||||
}
|
||||
decode_set_slot_number(pkt);
|
||||
decode_fill_newvalue_regno(pkt);
|
||||
|
||||
if (!disas_only) {
|
||||
decode_shuffle_for_execution(pkt);
|
||||
decode_split_cmpjump(pkt);
|
||||
decode_set_insn_attr_fields(pkt);
|
||||
}
|
||||
|
||||
return words_read;
|
||||
}
|
||||
|
||||
/* Used for "-d in_asm" logging */
|
||||
int disassemble_hexagon(uint32_t *words, int nwords, bfd_vma pc,
|
||||
GString *buf)
|
||||
{
|
||||
Packet pkt;
|
||||
|
||||
if (decode_packet(nwords, words, &pkt, true) > 0) {
|
||||
snprint_a_pkt_disas(buf, &pkt, words, pc);
|
||||
return pkt.encod_pkt_size_in_bytes;
|
||||
} else {
|
||||
g_string_assign(buf, "<invalid>");
|
||||
return 0;
|
||||
}
|
||||
}
|
32
target/hexagon/decode.h
Normal file
32
target/hexagon/decode.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_DECODE_H
|
||||
#define HEXAGON_DECODE_H
|
||||
|
||||
#include "cpu.h"
|
||||
#include "opcodes.h"
|
||||
#include "insn.h"
|
||||
|
||||
void decode_init(void);
|
||||
|
||||
void decode_send_insn_to(Packet *packet, int start, int newloc);
|
||||
|
||||
int decode_packet(int max_words, const uint32_t *words, Packet *pkt,
|
||||
bool disas_only);
|
||||
|
||||
#endif
|
351
target/hexagon/dectree.py
Executable file
351
target/hexagon/dectree.py
Executable file
@ -0,0 +1,351 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
import io
|
||||
import re
|
||||
|
||||
import sys
|
||||
import iset
|
||||
|
||||
encs = {tag : ''.join(reversed(iset.iset[tag]['enc'].replace(' ', '')))
|
||||
for tag in iset.tags if iset.iset[tag]['enc'] != 'MISSING ENCODING'}
|
||||
|
||||
enc_classes = set([iset.iset[tag]['enc_class'] for tag in encs.keys()])
|
||||
subinsn_enc_classes = \
|
||||
set([enc_class for enc_class in enc_classes \
|
||||
if enc_class.startswith('SUBINSN_')])
|
||||
ext_enc_classes = \
|
||||
set([enc_class for enc_class in enc_classes \
|
||||
if enc_class not in ('NORMAL', '16BIT') and \
|
||||
not enc_class.startswith('SUBINSN_')])
|
||||
|
||||
try:
|
||||
subinsn_groupings = iset.subinsn_groupings
|
||||
except AttributeError:
|
||||
subinsn_groupings = {}
|
||||
|
||||
for (tag, subinsn_grouping) in subinsn_groupings.items():
|
||||
encs[tag] = ''.join(reversed(subinsn_grouping['enc'].replace(' ', '')))
|
||||
|
||||
dectree_normal = {'leaves' : set()}
|
||||
dectree_16bit = {'leaves' : set()}
|
||||
dectree_subinsn_groupings = {'leaves' : set()}
|
||||
dectree_subinsns = {name : {'leaves' : set()} for name in subinsn_enc_classes}
|
||||
dectree_extensions = {name : {'leaves' : set()} for name in ext_enc_classes}
|
||||
|
||||
for tag in encs.keys():
|
||||
if tag in subinsn_groupings:
|
||||
dectree_subinsn_groupings['leaves'].add(tag)
|
||||
continue
|
||||
enc_class = iset.iset[tag]['enc_class']
|
||||
if enc_class.startswith('SUBINSN_'):
|
||||
if len(encs[tag]) != 32:
|
||||
encs[tag] = encs[tag] + '0' * (32 - len(encs[tag]))
|
||||
dectree_subinsns[enc_class]['leaves'].add(tag)
|
||||
elif enc_class == '16BIT':
|
||||
if len(encs[tag]) != 16:
|
||||
raise Exception('Tag "{}" has enc_class "{}" and not an encoding ' +
|
||||
'width of 16 bits!'.format(tag, enc_class))
|
||||
dectree_16bit['leaves'].add(tag)
|
||||
else:
|
||||
if len(encs[tag]) != 32:
|
||||
raise Exception('Tag "{}" has enc_class "{}" and not an encoding ' +
|
||||
'width of 32 bits!'.format(tag, enc_class))
|
||||
if enc_class == 'NORMAL':
|
||||
dectree_normal['leaves'].add(tag)
|
||||
else:
|
||||
dectree_extensions[enc_class]['leaves'].add(tag)
|
||||
|
||||
faketags = set()
|
||||
for (tag, enc) in iset.enc_ext_spaces.items():
|
||||
faketags.add(tag)
|
||||
encs[tag] = ''.join(reversed(enc.replace(' ', '')))
|
||||
dectree_normal['leaves'].add(tag)
|
||||
|
||||
faketags |= set(subinsn_groupings.keys())
|
||||
|
||||
def every_bit_counts(bitset):
|
||||
for i in range(1, len(next(iter(bitset)))):
|
||||
if len(set([bits[:i] + bits[i+1:] for bits in bitset])) == len(bitset):
|
||||
return False
|
||||
return True
|
||||
|
||||
def auto_separate(node):
|
||||
tags = node['leaves']
|
||||
if len(tags) <= 1:
|
||||
return
|
||||
enc_width = len(encs[next(iter(tags))])
|
||||
opcode_bit_for_all = \
|
||||
[all([encs[tag][i] in '01' \
|
||||
for tag in tags]) for i in range(enc_width)]
|
||||
opcode_bit_is_0_for_all = \
|
||||
[opcode_bit_for_all[i] and all([encs[tag][i] == '0' \
|
||||
for tag in tags]) for i in range(enc_width)]
|
||||
opcode_bit_is_1_for_all = \
|
||||
[opcode_bit_for_all[i] and all([encs[tag][i] == '1' \
|
||||
for tag in tags]) for i in range(enc_width)]
|
||||
differentiator_opcode_bit = \
|
||||
[opcode_bit_for_all[i] and \
|
||||
not (opcode_bit_is_0_for_all[i] or \
|
||||
opcode_bit_is_1_for_all[i]) \
|
||||
for i in range(enc_width)]
|
||||
best_width = 0
|
||||
for width in range(4, 0, -1):
|
||||
for lsb in range(enc_width - width, -1, -1):
|
||||
bitset = set([encs[tag][lsb:lsb+width] for tag in tags])
|
||||
if all(differentiator_opcode_bit[lsb:lsb+width]) and \
|
||||
(len(bitset) == len(tags) or every_bit_counts(bitset)):
|
||||
best_width = width
|
||||
best_lsb = lsb
|
||||
caught_all_tags = len(bitset) == len(tags)
|
||||
break
|
||||
if best_width != 0:
|
||||
break
|
||||
if best_width == 0:
|
||||
raise Exception('Could not find a way to differentiate the encodings ' +
|
||||
'of the following tags:\n{}'.format('\n'.join(tags)))
|
||||
if caught_all_tags:
|
||||
for width in range(1, best_width):
|
||||
for lsb in range(enc_width - width, -1, -1):
|
||||
bitset = set([encs[tag][lsb:lsb+width] for tag in tags])
|
||||
if all(differentiator_opcode_bit[lsb:lsb+width]) and \
|
||||
len(bitset) == len(tags):
|
||||
best_width = width
|
||||
best_lsb = lsb
|
||||
break
|
||||
else:
|
||||
continue
|
||||
break
|
||||
node['separator_lsb'] = best_lsb
|
||||
node['separator_width'] = best_width
|
||||
node['children'] = []
|
||||
for value in range(2 ** best_width):
|
||||
child = {}
|
||||
bits = ''.join(reversed('{:0{}b}'.format(value, best_width)))
|
||||
child['leaves'] = \
|
||||
set([tag for tag in tags \
|
||||
if encs[tag][best_lsb:best_lsb+best_width] == bits])
|
||||
node['children'].append(child)
|
||||
for child in node['children']:
|
||||
auto_separate(child)
|
||||
|
||||
auto_separate(dectree_normal)
|
||||
auto_separate(dectree_16bit)
|
||||
if subinsn_groupings:
|
||||
auto_separate(dectree_subinsn_groupings)
|
||||
for dectree_subinsn in dectree_subinsns.values():
|
||||
auto_separate(dectree_subinsn)
|
||||
for dectree_ext in dectree_extensions.values():
|
||||
auto_separate(dectree_ext)
|
||||
|
||||
for tag in faketags:
|
||||
del encs[tag]
|
||||
|
||||
def table_name(parents, node):
|
||||
path = parents + [node]
|
||||
root = path[0]
|
||||
tag = next(iter(node['leaves']))
|
||||
if tag in subinsn_groupings:
|
||||
enc_width = len(subinsn_groupings[tag]['enc'].replace(' ', ''))
|
||||
else:
|
||||
tag = next(iter(node['leaves'] - faketags))
|
||||
enc_width = len(encs[tag])
|
||||
determining_bits = ['_'] * enc_width
|
||||
for (parent, child) in zip(path[:-1], path[1:]):
|
||||
lsb = parent['separator_lsb']
|
||||
width = parent['separator_width']
|
||||
value = parent['children'].index(child)
|
||||
determining_bits[lsb:lsb+width] = \
|
||||
list(reversed('{:0{}b}'.format(value, width)))
|
||||
if tag in subinsn_groupings:
|
||||
name = 'DECODE_ROOT_EE'
|
||||
else:
|
||||
enc_class = iset.iset[tag]['enc_class']
|
||||
if enc_class in ext_enc_classes:
|
||||
name = 'DECODE_EXT_{}'.format(enc_class)
|
||||
elif enc_class in subinsn_enc_classes:
|
||||
name = 'DECODE_SUBINSN_{}'.format(enc_class)
|
||||
else:
|
||||
name = 'DECODE_ROOT_{}'.format(enc_width)
|
||||
if node != root:
|
||||
name += '_' + ''.join(reversed(determining_bits))
|
||||
return name
|
||||
|
||||
def print_node(f, node, parents):
|
||||
if len(node['leaves']) <= 1:
|
||||
return
|
||||
name = table_name(parents, node)
|
||||
lsb = node['separator_lsb']
|
||||
width = node['separator_width']
|
||||
print('DECODE_NEW_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))'.\
|
||||
format(name, 2 ** width, lsb, width), file=f)
|
||||
for child in node['children']:
|
||||
if len(child['leaves']) == 0:
|
||||
print('INVALID()', file=f)
|
||||
elif len(child['leaves']) == 1:
|
||||
(tag,) = child['leaves']
|
||||
if tag in subinsn_groupings:
|
||||
class_a = subinsn_groupings[tag]['class_a']
|
||||
class_b = subinsn_groupings[tag]['class_b']
|
||||
enc = subinsn_groupings[tag]['enc'].replace(' ', '')
|
||||
if 'RESERVED' in tag:
|
||||
print('INVALID()', file=f)
|
||||
else:
|
||||
print('SUBINSNS({},{},{},"{}")'.\
|
||||
format(tag, class_a, class_b, enc), file=f)
|
||||
elif tag in iset.enc_ext_spaces:
|
||||
enc = iset.enc_ext_spaces[tag].replace(' ', '')
|
||||
print('EXTSPACE({},"{}")'.format(tag, enc), file=f)
|
||||
else:
|
||||
enc = ''.join(reversed(encs[tag]))
|
||||
print('TERMINAL({},"{}")'.format(tag, enc), file=f)
|
||||
else:
|
||||
print('TABLE_LINK({})'.format(table_name(parents + [node], child)),
|
||||
file=f)
|
||||
print('DECODE_END_TABLE({},{},DECODE_SEPARATOR_BITS({},{}))'.\
|
||||
format(name, 2 ** width, lsb, width), file=f)
|
||||
print(file=f)
|
||||
parents.append(node)
|
||||
for child in node['children']:
|
||||
print_node(f, child, parents)
|
||||
parents.pop()
|
||||
|
||||
def print_tree(f, tree):
|
||||
print_node(f, tree, [])
|
||||
|
||||
def print_match_info(f):
|
||||
for tag in sorted(encs.keys(), key=iset.tags.index):
|
||||
enc = ''.join(reversed(encs[tag]))
|
||||
mask = int(re.sub(r'[^1]', r'0', enc.replace('0', '1')), 2)
|
||||
match = int(re.sub(r'[^01]', r'0', enc), 2)
|
||||
suffix = ''
|
||||
print('DECODE{}_MATCH_INFO({},0x{:x}U,0x{:x}U)'.\
|
||||
format(suffix, tag, mask, match), file=f)
|
||||
|
||||
regre = re.compile(
|
||||
r'((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)')
|
||||
immre = re.compile(r'[#]([rRsSuUm])(\d+)(?:[:](\d+))?')
|
||||
|
||||
def ordered_unique(l):
|
||||
return sorted(set(l), key=l.index)
|
||||
|
||||
implicit_registers = {
|
||||
'SP' : 29,
|
||||
'FP' : 30,
|
||||
'LR' : 31
|
||||
}
|
||||
|
||||
num_registers = {
|
||||
'R' : 32,
|
||||
'V' : 32
|
||||
}
|
||||
|
||||
def print_op_info(f):
|
||||
for tag in sorted(encs.keys(), key=iset.tags.index):
|
||||
enc = encs[tag]
|
||||
print(file=f)
|
||||
print('DECODE_OPINFO({},'.format(tag), file=f)
|
||||
regs = ordered_unique(regre.findall(iset.iset[tag]['syntax']))
|
||||
imms = ordered_unique(immre.findall(iset.iset[tag]['syntax']))
|
||||
regno = 0
|
||||
for reg in regs:
|
||||
reg_type = reg[0]
|
||||
reg_letter = reg[1][0]
|
||||
reg_num_choices = int(reg[3].rstrip('S'))
|
||||
reg_mapping = reg[0] + ''.join(['_' for letter in reg[1]]) + reg[3]
|
||||
reg_enc_fields = re.findall(reg_letter + '+', enc)
|
||||
if len(reg_enc_fields) == 0:
|
||||
raise Exception('Tag "{}" missing register field!'.format(tag))
|
||||
if len(reg_enc_fields) > 1:
|
||||
raise Exception('Tag "{}" has split register field!'.\
|
||||
format(tag))
|
||||
reg_enc_field = reg_enc_fields[0]
|
||||
if 2 ** len(reg_enc_field) != reg_num_choices:
|
||||
raise Exception('Tag "{}" has incorrect register field width!'.\
|
||||
format(tag))
|
||||
print(' DECODE_REG({},{},{})'.\
|
||||
format(regno, len(reg_enc_field), enc.index(reg_enc_field)),
|
||||
file=f)
|
||||
if reg_type in num_registers and \
|
||||
reg_num_choices != num_registers[reg_type]:
|
||||
print(' DECODE_MAPPED_REG({},{})'.\
|
||||
format(regno, reg_mapping), file=f)
|
||||
regno += 1
|
||||
def implicit_register_key(reg):
|
||||
return implicit_registers[reg]
|
||||
for reg in sorted(
|
||||
set([r for r in (iset.iset[tag]['rregs'].split(',') + \
|
||||
iset.iset[tag]['wregs'].split(',')) \
|
||||
if r in implicit_registers]), key=implicit_register_key):
|
||||
print(' DECODE_IMPL_REG({},{})'.\
|
||||
format(regno, implicit_registers[reg]), file=f)
|
||||
regno += 1
|
||||
if imms and imms[0][0].isupper():
|
||||
imms = reversed(imms)
|
||||
for imm in imms:
|
||||
if imm[0].isupper():
|
||||
immno = 1
|
||||
else:
|
||||
immno = 0
|
||||
imm_type = imm[0]
|
||||
imm_width = int(imm[1])
|
||||
imm_shift = imm[2]
|
||||
if imm_shift:
|
||||
imm_shift = int(imm_shift)
|
||||
else:
|
||||
imm_shift = 0
|
||||
if imm_type.islower():
|
||||
imm_letter = 'i'
|
||||
else:
|
||||
imm_letter = 'I'
|
||||
remainder = imm_width
|
||||
for m in reversed(list(re.finditer(imm_letter + '+', enc))):
|
||||
remainder -= m.end() - m.start()
|
||||
print(' DECODE_IMM({},{},{},{})'.\
|
||||
format(immno, m.end() - m.start(), m.start(), remainder),
|
||||
file=f)
|
||||
if remainder != 0:
|
||||
if imm[2]:
|
||||
imm[2] = ':' + imm[2]
|
||||
raise Exception('Tag "{}" has an incorrect number of ' + \
|
||||
'encoding bits for immediate "{}"'.\
|
||||
format(tag, ''.join(imm)))
|
||||
if imm_type.lower() in 'sr':
|
||||
print(' DECODE_IMM_SXT({},{})'.\
|
||||
format(immno, imm_width), file=f)
|
||||
if imm_type.lower() == 'n':
|
||||
print(' DECODE_IMM_NEG({},{})'.\
|
||||
format(immno, imm_width), file=f)
|
||||
if imm_shift:
|
||||
print(' DECODE_IMM_SHIFT({},{})'.\
|
||||
format(immno, imm_shift), file=f)
|
||||
print(')', file=f)
|
||||
|
||||
if __name__ == '__main__':
|
||||
with open(sys.argv[1], 'w') as f:
|
||||
print_tree(f, dectree_normal)
|
||||
print_tree(f, dectree_16bit)
|
||||
if subinsn_groupings:
|
||||
print_tree(f, dectree_subinsn_groupings)
|
||||
for (name, dectree_subinsn) in sorted(dectree_subinsns.items()):
|
||||
print_tree(f, dectree_subinsn)
|
||||
for (name, dectree_ext) in sorted(dectree_extensions.items()):
|
||||
print_tree(f, dectree_ext)
|
||||
print_match_info(f)
|
||||
print_op_info(f)
|
702
target/hexagon/fma_emu.c
Normal file
702
target/hexagon/fma_emu.c
Normal file
@ -0,0 +1,702 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/int128.h"
|
||||
#include "fpu/softfloat.h"
|
||||
#include "macros.h"
|
||||
#include "conv_emu.h"
|
||||
#include "fma_emu.h"
|
||||
|
||||
#define DF_INF_EXP 0x7ff
|
||||
#define DF_BIAS 1023
|
||||
#define DF_MANTBITS 52
|
||||
#define DF_NAN 0xffffffffffffffffULL
|
||||
#define DF_INF 0x7ff0000000000000ULL
|
||||
#define DF_MINUS_INF 0xfff0000000000000ULL
|
||||
#define DF_MAXF 0x7fefffffffffffffULL
|
||||
#define DF_MINUS_MAXF 0xffefffffffffffffULL
|
||||
|
||||
#define SF_INF_EXP 0xff
|
||||
#define SF_BIAS 127
|
||||
#define SF_MANTBITS 23
|
||||
#define SF_INF 0x7f800000
|
||||
#define SF_MINUS_INF 0xff800000
|
||||
#define SF_MAXF 0x7f7fffff
|
||||
#define SF_MINUS_MAXF 0xff7fffff
|
||||
|
||||
#define HF_INF_EXP 0x1f
|
||||
#define HF_BIAS 15
|
||||
|
||||
#define WAY_BIG_EXP 4096
|
||||
|
||||
typedef union {
|
||||
double f;
|
||||
uint64_t i;
|
||||
struct {
|
||||
uint64_t mant:52;
|
||||
uint64_t exp:11;
|
||||
uint64_t sign:1;
|
||||
};
|
||||
} Double;
|
||||
|
||||
typedef union {
|
||||
float f;
|
||||
uint32_t i;
|
||||
struct {
|
||||
uint32_t mant:23;
|
||||
uint32_t exp:8;
|
||||
uint32_t sign:1;
|
||||
};
|
||||
} Float;
|
||||
|
||||
static inline uint64_t float64_getmant(float64 f64)
|
||||
{
|
||||
Double a = { .i = f64 };
|
||||
if (float64_is_normal(f64)) {
|
||||
return a.mant | 1ULL << 52;
|
||||
}
|
||||
if (float64_is_zero(f64)) {
|
||||
return 0;
|
||||
}
|
||||
if (float64_is_denormal(f64)) {
|
||||
return a.mant;
|
||||
}
|
||||
return ~0ULL;
|
||||
}
|
||||
|
||||
int32_t float64_getexp(float64 f64)
|
||||
{
|
||||
Double a = { .i = f64 };
|
||||
if (float64_is_normal(f64)) {
|
||||
return a.exp;
|
||||
}
|
||||
if (float64_is_denormal(f64)) {
|
||||
return a.exp + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline uint64_t float32_getmant(float32 f32)
|
||||
{
|
||||
Float a = { .i = f32 };
|
||||
if (float32_is_normal(f32)) {
|
||||
return a.mant | 1ULL << 23;
|
||||
}
|
||||
if (float32_is_zero(f32)) {
|
||||
return 0;
|
||||
}
|
||||
if (float32_is_denormal(f32)) {
|
||||
return a.mant;
|
||||
}
|
||||
return ~0ULL;
|
||||
}
|
||||
|
||||
int32_t float32_getexp(float32 f32)
|
||||
{
|
||||
Float a = { .i = f32 };
|
||||
if (float32_is_normal(f32)) {
|
||||
return a.exp;
|
||||
}
|
||||
if (float32_is_denormal(f32)) {
|
||||
return a.exp + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline uint32_t int128_getw0(Int128 x)
|
||||
{
|
||||
return int128_getlo(x);
|
||||
}
|
||||
|
||||
static inline uint32_t int128_getw1(Int128 x)
|
||||
{
|
||||
return int128_getlo(x) >> 32;
|
||||
}
|
||||
|
||||
static inline Int128 int128_mul_6464(uint64_t ai, uint64_t bi)
|
||||
{
|
||||
Int128 a, b;
|
||||
uint64_t pp0, pp1a, pp1b, pp1s, pp2;
|
||||
|
||||
a = int128_make64(ai);
|
||||
b = int128_make64(bi);
|
||||
pp0 = (uint64_t)int128_getw0(a) * (uint64_t)int128_getw0(b);
|
||||
pp1a = (uint64_t)int128_getw1(a) * (uint64_t)int128_getw0(b);
|
||||
pp1b = (uint64_t)int128_getw1(b) * (uint64_t)int128_getw0(a);
|
||||
pp2 = (uint64_t)int128_getw1(a) * (uint64_t)int128_getw1(b);
|
||||
|
||||
pp1s = pp1a + pp1b;
|
||||
if ((pp1s < pp1a) || (pp1s < pp1b)) {
|
||||
pp2 += (1ULL << 32);
|
||||
}
|
||||
uint64_t ret_low = pp0 + (pp1s << 32);
|
||||
if ((ret_low < pp0) || (ret_low < (pp1s << 32))) {
|
||||
pp2 += 1;
|
||||
}
|
||||
|
||||
return int128_make128(ret_low, pp2 + (pp1s >> 32));
|
||||
}
|
||||
|
||||
static inline Int128 int128_sub_borrow(Int128 a, Int128 b, int borrow)
|
||||
{
|
||||
Int128 ret = int128_sub(a, b);
|
||||
if (borrow != 0) {
|
||||
ret = int128_sub(ret, int128_one());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
Int128 mant;
|
||||
int32_t exp;
|
||||
uint8_t sign;
|
||||
uint8_t guard;
|
||||
uint8_t round;
|
||||
uint8_t sticky;
|
||||
} Accum;
|
||||
|
||||
static inline void accum_init(Accum *p)
|
||||
{
|
||||
p->mant = int128_zero();
|
||||
p->exp = 0;
|
||||
p->sign = 0;
|
||||
p->guard = 0;
|
||||
p->round = 0;
|
||||
p->sticky = 0;
|
||||
}
|
||||
|
||||
static inline Accum accum_norm_left(Accum a)
|
||||
{
|
||||
a.exp--;
|
||||
a.mant = int128_lshift(a.mant, 1);
|
||||
a.mant = int128_or(a.mant, int128_make64(a.guard));
|
||||
a.guard = a.round;
|
||||
a.round = a.sticky;
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline Accum accum_norm_right(Accum a, int amt)
|
||||
{
|
||||
if (amt > 130) {
|
||||
a.sticky |=
|
||||
a.round | a.guard | int128_nz(a.mant);
|
||||
a.guard = a.round = 0;
|
||||
a.mant = int128_zero();
|
||||
a.exp += amt;
|
||||
return a;
|
||||
|
||||
}
|
||||
while (amt >= 64) {
|
||||
a.sticky |= a.round | a.guard | (int128_getlo(a.mant) != 0);
|
||||
a.guard = (int128_getlo(a.mant) >> 63) & 1;
|
||||
a.round = (int128_getlo(a.mant) >> 62) & 1;
|
||||
a.mant = int128_make64(int128_gethi(a.mant));
|
||||
a.exp += 64;
|
||||
amt -= 64;
|
||||
}
|
||||
while (amt > 0) {
|
||||
a.exp++;
|
||||
a.sticky |= a.round;
|
||||
a.round = a.guard;
|
||||
a.guard = int128_getlo(a.mant) & 1;
|
||||
a.mant = int128_rshift(a.mant, 1);
|
||||
amt--;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/*
|
||||
* On the add/sub, we need to be able to shift out lots of bits, but need a
|
||||
* sticky bit for what was shifted out, I think.
|
||||
*/
|
||||
static Accum accum_add(Accum a, Accum b);
|
||||
|
||||
static inline Accum accum_sub(Accum a, Accum b, int negate)
|
||||
{
|
||||
Accum ret;
|
||||
accum_init(&ret);
|
||||
int borrow;
|
||||
|
||||
if (a.sign != b.sign) {
|
||||
b.sign = !b.sign;
|
||||
return accum_add(a, b);
|
||||
}
|
||||
if (b.exp > a.exp) {
|
||||
/* small - big == - (big - small) */
|
||||
return accum_sub(b, a, !negate);
|
||||
}
|
||||
if ((b.exp == a.exp) && (int128_gt(b.mant, a.mant))) {
|
||||
/* small - big == - (big - small) */
|
||||
return accum_sub(b, a, !negate);
|
||||
}
|
||||
|
||||
while (a.exp > b.exp) {
|
||||
/* Try to normalize exponents: shrink a exponent and grow mantissa */
|
||||
if (int128_gethi(a.mant) & (1ULL << 62)) {
|
||||
/* Can't grow a any more */
|
||||
break;
|
||||
} else {
|
||||
a = accum_norm_left(a);
|
||||
}
|
||||
}
|
||||
|
||||
while (a.exp > b.exp) {
|
||||
/* Try to normalize exponents: grow b exponent and shrink mantissa */
|
||||
/* Keep around shifted out bits... we might need those later */
|
||||
b = accum_norm_right(b, a.exp - b.exp);
|
||||
}
|
||||
|
||||
if ((int128_gt(b.mant, a.mant))) {
|
||||
return accum_sub(b, a, !negate);
|
||||
}
|
||||
|
||||
/* OK, now things should be normalized! */
|
||||
ret.sign = a.sign;
|
||||
ret.exp = a.exp;
|
||||
assert(!int128_gt(b.mant, a.mant));
|
||||
borrow = (b.round << 2) | (b.guard << 1) | b.sticky;
|
||||
ret.mant = int128_sub_borrow(a.mant, b.mant, (borrow != 0));
|
||||
borrow = 0 - borrow;
|
||||
ret.guard = (borrow >> 2) & 1;
|
||||
ret.round = (borrow >> 1) & 1;
|
||||
ret.sticky = (borrow >> 0) & 1;
|
||||
if (negate) {
|
||||
ret.sign = !ret.sign;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Accum accum_add(Accum a, Accum b)
|
||||
{
|
||||
Accum ret;
|
||||
accum_init(&ret);
|
||||
if (a.sign != b.sign) {
|
||||
b.sign = !b.sign;
|
||||
return accum_sub(a, b, 0);
|
||||
}
|
||||
if (b.exp > a.exp) {
|
||||
/* small + big == (big + small) */
|
||||
return accum_add(b, a);
|
||||
}
|
||||
if ((b.exp == a.exp) && int128_gt(b.mant, a.mant)) {
|
||||
/* small + big == (big + small) */
|
||||
return accum_add(b, a);
|
||||
}
|
||||
|
||||
while (a.exp > b.exp) {
|
||||
/* Try to normalize exponents: shrink a exponent and grow mantissa */
|
||||
if (int128_gethi(a.mant) & (1ULL << 62)) {
|
||||
/* Can't grow a any more */
|
||||
break;
|
||||
} else {
|
||||
a = accum_norm_left(a);
|
||||
}
|
||||
}
|
||||
|
||||
while (a.exp > b.exp) {
|
||||
/* Try to normalize exponents: grow b exponent and shrink mantissa */
|
||||
/* Keep around shifted out bits... we might need those later */
|
||||
b = accum_norm_right(b, a.exp - b.exp);
|
||||
}
|
||||
|
||||
/* OK, now things should be normalized! */
|
||||
if (int128_gt(b.mant, a.mant)) {
|
||||
return accum_add(b, a);
|
||||
};
|
||||
ret.sign = a.sign;
|
||||
ret.exp = a.exp;
|
||||
assert(!int128_gt(b.mant, a.mant));
|
||||
ret.mant = int128_add(a.mant, b.mant);
|
||||
ret.guard = b.guard;
|
||||
ret.round = b.round;
|
||||
ret.sticky = b.sticky;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Return an infinity with requested sign */
|
||||
static inline float64 infinite_float64(uint8_t sign)
|
||||
{
|
||||
if (sign) {
|
||||
return make_float64(DF_MINUS_INF);
|
||||
} else {
|
||||
return make_float64(DF_INF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a maximum finite value with requested sign */
|
||||
static inline float64 maxfinite_float64(uint8_t sign)
|
||||
{
|
||||
if (sign) {
|
||||
return make_float64(DF_MINUS_MAXF);
|
||||
} else {
|
||||
return make_float64(DF_MAXF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a zero value with requested sign */
|
||||
static inline float64 zero_float64(uint8_t sign)
|
||||
{
|
||||
if (sign) {
|
||||
return make_float64(0x8000000000000000);
|
||||
} else {
|
||||
return float64_zero;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return an infinity with the requested sign */
|
||||
float32 infinite_float32(uint8_t sign)
|
||||
{
|
||||
if (sign) {
|
||||
return make_float32(SF_MINUS_INF);
|
||||
} else {
|
||||
return make_float32(SF_INF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a maximum finite value with the requested sign */
|
||||
static inline float32 maxfinite_float32(uint8_t sign)
|
||||
{
|
||||
if (sign) {
|
||||
return make_float32(SF_MINUS_MAXF);
|
||||
} else {
|
||||
return make_float32(SF_MAXF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a zero value with requested sign */
|
||||
static inline float32 zero_float32(uint8_t sign)
|
||||
{
|
||||
if (sign) {
|
||||
return make_float32(0x80000000);
|
||||
} else {
|
||||
return float32_zero;
|
||||
}
|
||||
}
|
||||
|
||||
#define GEN_XF_ROUND(SUFFIX, MANTBITS, INF_EXP, INTERNAL_TYPE) \
|
||||
static inline SUFFIX accum_round_##SUFFIX(Accum a, float_status * fp_status) \
|
||||
{ \
|
||||
if ((int128_gethi(a.mant) == 0) && (int128_getlo(a.mant) == 0) \
|
||||
&& ((a.guard | a.round | a.sticky) == 0)) { \
|
||||
/* result zero */ \
|
||||
switch (fp_status->float_rounding_mode) { \
|
||||
case float_round_down: \
|
||||
return zero_##SUFFIX(1); \
|
||||
default: \
|
||||
return zero_##SUFFIX(0); \
|
||||
} \
|
||||
} \
|
||||
/* Normalize right */ \
|
||||
/* We want MANTBITS bits of mantissa plus the leading one. */ \
|
||||
/* That means that we want MANTBITS+1 bits, or 0x000000000000FF_FFFF */ \
|
||||
/* So we need to normalize right while the high word is non-zero and \
|
||||
* while the low word is nonzero when masked with 0xffe0_0000_0000_0000 */ \
|
||||
while ((int128_gethi(a.mant) != 0) || \
|
||||
((int128_getlo(a.mant) >> (MANTBITS + 1)) != 0)) { \
|
||||
a = accum_norm_right(a, 1); \
|
||||
} \
|
||||
/* \
|
||||
* OK, now normalize left \
|
||||
* We want to normalize left until we have a leading one in bit 24 \
|
||||
* Theoretically, we only need to shift a maximum of one to the left if we \
|
||||
* shifted out lots of bits from B, or if we had no shift / 1 shift sticky \
|
||||
* shoudl be 0 \
|
||||
*/ \
|
||||
while ((int128_getlo(a.mant) & (1ULL << MANTBITS)) == 0) { \
|
||||
a = accum_norm_left(a); \
|
||||
} \
|
||||
/* \
|
||||
* OK, now we might need to denormalize because of potential underflow. \
|
||||
* We need to do this before rounding, and rounding might make us normal \
|
||||
* again \
|
||||
*/ \
|
||||
while (a.exp <= 0) { \
|
||||
a = accum_norm_right(a, 1 - a.exp); \
|
||||
/* \
|
||||
* Do we have underflow? \
|
||||
* That's when we get an inexact answer because we ran out of bits \
|
||||
* in a denormal. \
|
||||
*/ \
|
||||
if (a.guard || a.round || a.sticky) { \
|
||||
float_raise(float_flag_underflow, fp_status); \
|
||||
} \
|
||||
} \
|
||||
/* OK, we're relatively canonical... now we need to round */ \
|
||||
if (a.guard || a.round || a.sticky) { \
|
||||
float_raise(float_flag_inexact, fp_status); \
|
||||
switch (fp_status->float_rounding_mode) { \
|
||||
case float_round_to_zero: \
|
||||
/* Chop and we're done */ \
|
||||
break; \
|
||||
case float_round_up: \
|
||||
if (a.sign == 0) { \
|
||||
a.mant = int128_add(a.mant, int128_one()); \
|
||||
} \
|
||||
break; \
|
||||
case float_round_down: \
|
||||
if (a.sign != 0) { \
|
||||
a.mant = int128_add(a.mant, int128_one()); \
|
||||
} \
|
||||
break; \
|
||||
default: \
|
||||
if (a.round || a.sticky) { \
|
||||
/* round up if guard is 1, down if guard is zero */ \
|
||||
a.mant = int128_add(a.mant, int128_make64(a.guard)); \
|
||||
} else if (a.guard) { \
|
||||
/* exactly .5, round up if odd */ \
|
||||
a.mant = int128_add(a.mant, int128_and(a.mant, int128_one())); \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
/* \
|
||||
* OK, now we might have carried all the way up. \
|
||||
* So we might need to shr once \
|
||||
* at least we know that the lsb should be zero if we rounded and \
|
||||
* got a carry out... \
|
||||
*/ \
|
||||
if ((int128_getlo(a.mant) >> (MANTBITS + 1)) != 0) { \
|
||||
a = accum_norm_right(a, 1); \
|
||||
} \
|
||||
/* Overflow? */ \
|
||||
if (a.exp >= INF_EXP) { \
|
||||
/* Yep, inf result */ \
|
||||
float_raise(float_flag_overflow, fp_status); \
|
||||
float_raise(float_flag_inexact, fp_status); \
|
||||
switch (fp_status->float_rounding_mode) { \
|
||||
case float_round_to_zero: \
|
||||
return maxfinite_##SUFFIX(a.sign); \
|
||||
case float_round_up: \
|
||||
if (a.sign == 0) { \
|
||||
return infinite_##SUFFIX(a.sign); \
|
||||
} else { \
|
||||
return maxfinite_##SUFFIX(a.sign); \
|
||||
} \
|
||||
case float_round_down: \
|
||||
if (a.sign != 0) { \
|
||||
return infinite_##SUFFIX(a.sign); \
|
||||
} else { \
|
||||
return maxfinite_##SUFFIX(a.sign); \
|
||||
} \
|
||||
default: \
|
||||
return infinite_##SUFFIX(a.sign); \
|
||||
} \
|
||||
} \
|
||||
/* Underflow? */ \
|
||||
if (int128_getlo(a.mant) & (1ULL << MANTBITS)) { \
|
||||
/* Leading one means: No, we're normal. So, we should be done... */ \
|
||||
INTERNAL_TYPE ret; \
|
||||
ret.i = 0; \
|
||||
ret.sign = a.sign; \
|
||||
ret.exp = a.exp; \
|
||||
ret.mant = int128_getlo(a.mant); \
|
||||
return ret.i; \
|
||||
} \
|
||||
assert(a.exp == 1); \
|
||||
INTERNAL_TYPE ret; \
|
||||
ret.i = 0; \
|
||||
ret.sign = a.sign; \
|
||||
ret.exp = 0; \
|
||||
ret.mant = int128_getlo(a.mant); \
|
||||
return ret.i; \
|
||||
}
|
||||
|
||||
GEN_XF_ROUND(float64, DF_MANTBITS, DF_INF_EXP, Double)
|
||||
GEN_XF_ROUND(float32, SF_MANTBITS, SF_INF_EXP, Float)
|
||||
|
||||
static bool is_inf_prod(float64 a, float64 b)
|
||||
{
|
||||
return ((float64_is_infinity(a) && float64_is_infinity(b)) ||
|
||||
(float64_is_infinity(a) && is_finite(b) && (!float64_is_zero(b))) ||
|
||||
(float64_is_infinity(b) && is_finite(a) && (!float64_is_zero(a))));
|
||||
}
|
||||
|
||||
static inline float64 special_fma(float64 a, float64 b, float64 c,
|
||||
float_status *fp_status)
|
||||
{
|
||||
float64 ret = make_float64(0);
|
||||
|
||||
/*
|
||||
* If A multiplied by B is an exact infinity and C is also an infinity
|
||||
* but with the opposite sign, FMA returns NaN and raises invalid.
|
||||
*/
|
||||
uint8_t a_sign = float64_is_neg(a);
|
||||
uint8_t b_sign = float64_is_neg(b);
|
||||
uint8_t c_sign = float64_is_neg(c);
|
||||
if (is_inf_prod(a, b) && float64_is_infinity(c)) {
|
||||
if ((a_sign ^ b_sign) != c_sign) {
|
||||
ret = make_float64(DF_NAN);
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if ((float64_is_infinity(a) && float64_is_zero(b)) ||
|
||||
(float64_is_zero(a) && float64_is_infinity(b))) {
|
||||
ret = make_float64(DF_NAN);
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* If none of the above checks are true and C is a NaN,
|
||||
* a NaN shall be returned
|
||||
* If A or B are NaN, a NAN shall be returned.
|
||||
*/
|
||||
if (float64_is_any_nan(a) ||
|
||||
float64_is_any_nan(b) ||
|
||||
float64_is_any_nan(c)) {
|
||||
if (float64_is_any_nan(a) && (fGETBIT(51, a) == 0)) {
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
}
|
||||
if (float64_is_any_nan(b) && (fGETBIT(51, b) == 0)) {
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
}
|
||||
if (float64_is_any_nan(c) && (fGETBIT(51, c) == 0)) {
|
||||
float_raise(float_flag_invalid, fp_status);
|
||||
}
|
||||
ret = make_float64(DF_NAN);
|
||||
return ret;
|
||||
}
|
||||
/*
|
||||
* We have checked for adding opposite-signed infinities.
|
||||
* Other infinities return infinity with the correct sign
|
||||
*/
|
||||
if (float64_is_infinity(c)) {
|
||||
ret = infinite_float64(c_sign);
|
||||
return ret;
|
||||
}
|
||||
if (float64_is_infinity(a) || float64_is_infinity(b)) {
|
||||
ret = infinite_float64(a_sign ^ b_sign);
|
||||
return ret;
|
||||
}
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
static inline float32 special_fmaf(float32 a, float32 b, float32 c,
|
||||
float_status *fp_status)
|
||||
{
|
||||
float64 aa, bb, cc;
|
||||
aa = float32_to_float64(a, fp_status);
|
||||
bb = float32_to_float64(b, fp_status);
|
||||
cc = float32_to_float64(c, fp_status);
|
||||
return float64_to_float32(special_fma(aa, bb, cc, fp_status), fp_status);
|
||||
}
|
||||
|
||||
float32 internal_fmafx(float32 a, float32 b, float32 c, int scale,
|
||||
float_status *fp_status)
|
||||
{
|
||||
Accum prod;
|
||||
Accum acc;
|
||||
Accum result;
|
||||
accum_init(&prod);
|
||||
accum_init(&acc);
|
||||
accum_init(&result);
|
||||
|
||||
uint8_t a_sign = float32_is_neg(a);
|
||||
uint8_t b_sign = float32_is_neg(b);
|
||||
uint8_t c_sign = float32_is_neg(c);
|
||||
if (float32_is_infinity(a) ||
|
||||
float32_is_infinity(b) ||
|
||||
float32_is_infinity(c)) {
|
||||
return special_fmaf(a, b, c, fp_status);
|
||||
}
|
||||
if (float32_is_any_nan(a) ||
|
||||
float32_is_any_nan(b) ||
|
||||
float32_is_any_nan(c)) {
|
||||
return special_fmaf(a, b, c, fp_status);
|
||||
}
|
||||
if ((scale == 0) && (float32_is_zero(a) || float32_is_zero(b))) {
|
||||
float32 tmp = float32_mul(a, b, fp_status);
|
||||
tmp = float32_add(tmp, c, fp_status);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* (a * 2**b) * (c * 2**d) == a*c * 2**(b+d) */
|
||||
prod.mant = int128_mul_6464(float32_getmant(a), float32_getmant(b));
|
||||
|
||||
/*
|
||||
* Note: extracting the mantissa into an int is multiplying by
|
||||
* 2**23, so adjust here
|
||||
*/
|
||||
prod.exp = float32_getexp(a) + float32_getexp(b) - SF_BIAS - 23;
|
||||
prod.sign = a_sign ^ b_sign;
|
||||
if (float32_is_zero(a) || float32_is_zero(b)) {
|
||||
prod.exp = -2 * WAY_BIG_EXP;
|
||||
}
|
||||
if ((scale > 0) && float32_is_denormal(c)) {
|
||||
acc.mant = int128_mul_6464(0, 0);
|
||||
acc.exp = -WAY_BIG_EXP;
|
||||
acc.sign = c_sign;
|
||||
acc.sticky = 1;
|
||||
result = accum_add(prod, acc);
|
||||
} else if (!float32_is_zero(c)) {
|
||||
acc.mant = int128_mul_6464(float32_getmant(c), 1);
|
||||
acc.exp = float32_getexp(c);
|
||||
acc.sign = c_sign;
|
||||
result = accum_add(prod, acc);
|
||||
} else {
|
||||
result = prod;
|
||||
}
|
||||
result.exp += scale;
|
||||
return accum_round_float32(result, fp_status);
|
||||
}
|
||||
|
||||
float32 internal_mpyf(float32 a, float32 b, float_status *fp_status)
|
||||
{
|
||||
if (float32_is_zero(a) || float32_is_zero(b)) {
|
||||
return float32_mul(a, b, fp_status);
|
||||
}
|
||||
return internal_fmafx(a, b, float32_zero, 0, fp_status);
|
||||
}
|
||||
|
||||
float64 internal_mpyhh(float64 a, float64 b,
|
||||
unsigned long long int accumulated,
|
||||
float_status *fp_status)
|
||||
{
|
||||
Accum x;
|
||||
unsigned long long int prod;
|
||||
unsigned int sticky;
|
||||
uint8_t a_sign, b_sign;
|
||||
|
||||
sticky = accumulated & 1;
|
||||
accumulated >>= 1;
|
||||
accum_init(&x);
|
||||
if (float64_is_zero(a) ||
|
||||
float64_is_any_nan(a) ||
|
||||
float64_is_infinity(a)) {
|
||||
return float64_mul(a, b, fp_status);
|
||||
}
|
||||
if (float64_is_zero(b) ||
|
||||
float64_is_any_nan(b) ||
|
||||
float64_is_infinity(b)) {
|
||||
return float64_mul(a, b, fp_status);
|
||||
}
|
||||
x.mant = int128_mul_6464(accumulated, 1);
|
||||
x.sticky = sticky;
|
||||
prod = fGETUWORD(1, float64_getmant(a)) * fGETUWORD(1, float64_getmant(b));
|
||||
x.mant = int128_add(x.mant, int128_mul_6464(prod, 0x100000000ULL));
|
||||
x.exp = float64_getexp(a) + float64_getexp(b) - DF_BIAS - 20;
|
||||
if (!float64_is_normal(a) || !float64_is_normal(b)) {
|
||||
/* crush to inexact zero */
|
||||
x.sticky = 1;
|
||||
x.exp = -4096;
|
||||
}
|
||||
a_sign = float64_is_neg(a);
|
||||
b_sign = float64_is_neg(b);
|
||||
x.sign = a_sign ^ b_sign;
|
||||
return accum_round_float64(x, fp_status);
|
||||
}
|
36
target/hexagon/fma_emu.h
Normal file
36
target/hexagon/fma_emu.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_FMA_EMU_H
|
||||
#define HEXAGON_FMA_EMU_H
|
||||
|
||||
static inline bool is_finite(float64 x)
|
||||
{
|
||||
return !float64_is_any_nan(x) && !float64_is_infinity(x);
|
||||
}
|
||||
|
||||
int32_t float64_getexp(float64 f64);
|
||||
int32_t float32_getexp(float32 f32);
|
||||
float32 infinite_float32(uint8_t sign);
|
||||
float32 internal_fmafx(float32 a, float32 b, float32 c,
|
||||
int scale, float_status *fp_status);
|
||||
float32 internal_mpyf(float32 a, float32 b, float_status *fp_status);
|
||||
float64 internal_mpyhh(float64 a, float64 b,
|
||||
unsigned long long int accumulated,
|
||||
float_status *fp_status);
|
||||
|
||||
#endif
|
47
target/hexagon/gdbstub.c
Normal file
47
target/hexagon/gdbstub.c
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
|
||||
int hexagon_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
{
|
||||
HexagonCPU *cpu = HEXAGON_CPU(cs);
|
||||
CPUHexagonState *env = &cpu->env;
|
||||
|
||||
if (n < TOTAL_PER_THREAD_REGS) {
|
||||
return gdb_get_regl(mem_buf, env->gpr[n]);
|
||||
}
|
||||
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
int hexagon_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
{
|
||||
HexagonCPU *cpu = HEXAGON_CPU(cs);
|
||||
CPUHexagonState *env = &cpu->env;
|
||||
|
||||
if (n < TOTAL_PER_THREAD_REGS) {
|
||||
env->gpr[n] = ldtul_p(mem_buf);
|
||||
return sizeof(target_ulong);
|
||||
}
|
||||
|
||||
g_assert_not_reached();
|
||||
}
|
188
target/hexagon/gen_dectree_import.c
Normal file
188
target/hexagon/gen_dectree_import.c
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program generates the encodings file that is processed by
|
||||
* the dectree.py script to produce the decoding tree. We use the C
|
||||
* preprocessor to manipulate the files imported from the Hexagon
|
||||
* architecture library.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "opcodes.h"
|
||||
|
||||
#define STRINGIZE(X) #X
|
||||
|
||||
const char * const opcode_names[] = {
|
||||
#define OPCODE(IID) STRINGIZE(IID)
|
||||
#include "opcodes_def_generated.h.inc"
|
||||
NULL
|
||||
#undef OPCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Process the instruction definitions
|
||||
* Scalar core instructions have the following form
|
||||
* Q6INSN(A2_add,"Rd32=add(Rs32,Rt32)",ATTRIBS(),
|
||||
* "Add 32-bit registers",
|
||||
* { RdV=RsV+RtV;})
|
||||
*/
|
||||
const char * const opcode_syntax[XX_LAST_OPCODE] = {
|
||||
#define Q6INSN(TAG, BEH, ATTRIBS, DESCR, SEM) \
|
||||
[TAG] = BEH,
|
||||
#define EXTINSN(TAG, BEH, ATTRIBS, DESCR, SEM) \
|
||||
[TAG] = BEH,
|
||||
#include "imported/allidefs.def"
|
||||
#undef Q6INSN
|
||||
#undef EXTINSN
|
||||
};
|
||||
|
||||
const char * const opcode_rregs[] = {
|
||||
#define REGINFO(TAG, REGINFO, RREGS, WREGS) RREGS,
|
||||
#define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */
|
||||
#include "op_regs_generated.h.inc"
|
||||
NULL
|
||||
#undef REGINFO
|
||||
#undef IMMINFO
|
||||
};
|
||||
|
||||
const char * const opcode_wregs[] = {
|
||||
#define REGINFO(TAG, REGINFO, RREGS, WREGS) WREGS,
|
||||
#define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */
|
||||
#include "op_regs_generated.h.inc"
|
||||
NULL
|
||||
#undef REGINFO
|
||||
#undef IMMINFO
|
||||
};
|
||||
|
||||
const OpcodeEncoding opcode_encodings[] = {
|
||||
#define DEF_ENC32(TAG, ENCSTR) \
|
||||
[TAG] = { .encoding = ENCSTR },
|
||||
#define DEF_ENC_SUBINSN(TAG, CLASS, ENCSTR) \
|
||||
[TAG] = { .encoding = ENCSTR, .enc_class = CLASS },
|
||||
#define DEF_EXT_ENC(TAG, CLASS, ENCSTR) \
|
||||
[TAG] = { .encoding = ENCSTR, .enc_class = CLASS },
|
||||
#include "imported/encode.def"
|
||||
#undef DEF_ENC32
|
||||
#undef DEF_ENC_SUBINSN
|
||||
#undef DEF_EXT_ENC
|
||||
};
|
||||
|
||||
static const char * const opcode_enc_class_names[XX_LAST_ENC_CLASS] = {
|
||||
"NORMAL",
|
||||
"16BIT",
|
||||
"SUBINSN_A",
|
||||
"SUBINSN_L1",
|
||||
"SUBINSN_L2",
|
||||
"SUBINSN_S1",
|
||||
"SUBINSN_S2",
|
||||
"EXT_noext",
|
||||
"EXT_mmvec",
|
||||
};
|
||||
|
||||
static const char *get_opcode_enc(int opcode)
|
||||
{
|
||||
const char *tmp = opcode_encodings[opcode].encoding;
|
||||
if (tmp == NULL) {
|
||||
tmp = "MISSING ENCODING";
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static const char *get_opcode_enc_class(int opcode)
|
||||
{
|
||||
return opcode_enc_class_names[opcode_encodings[opcode].enc_class];
|
||||
}
|
||||
|
||||
static void gen_iset_table(FILE *out)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(out, "iset = {\n");
|
||||
for (i = 0; i < XX_LAST_OPCODE; i++) {
|
||||
fprintf(out, "\t\'%s\' : {\n", opcode_names[i]);
|
||||
fprintf(out, "\t\t\'tag\' : \'%s\',\n", opcode_names[i]);
|
||||
fprintf(out, "\t\t\'syntax\' : \'%s\',\n", opcode_syntax[i]);
|
||||
fprintf(out, "\t\t\'rregs\' : \'%s\',\n", opcode_rregs[i]);
|
||||
fprintf(out, "\t\t\'wregs\' : \'%s\',\n", opcode_wregs[i]);
|
||||
fprintf(out, "\t\t\'enc\' : \'%s\',\n", get_opcode_enc(i));
|
||||
fprintf(out, "\t\t\'enc_class\' : \'%s\',\n", get_opcode_enc_class(i));
|
||||
fprintf(out, "\t},\n");
|
||||
}
|
||||
fprintf(out, "};\n\n");
|
||||
}
|
||||
|
||||
static void gen_tags_list(FILE *out)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(out, "tags = [\n");
|
||||
for (i = 0; i < XX_LAST_OPCODE; i++) {
|
||||
fprintf(out, "\t\'%s\',\n", opcode_names[i]);
|
||||
}
|
||||
fprintf(out, "];\n\n");
|
||||
}
|
||||
|
||||
static void gen_enc_ext_spaces_table(FILE *out)
|
||||
{
|
||||
fprintf(out, "enc_ext_spaces = {\n");
|
||||
#define DEF_EXT_SPACE(SPACEID, ENCSTR) \
|
||||
fprintf(out, "\t\'%s\' : \'%s\',\n", #SPACEID, ENCSTR);
|
||||
#include "imported/encode.def"
|
||||
#undef DEF_EXT_SPACE
|
||||
fprintf(out, "};\n\n");
|
||||
}
|
||||
|
||||
static void gen_subinsn_groupings_table(FILE *out)
|
||||
{
|
||||
fprintf(out, "subinsn_groupings = {\n");
|
||||
#define DEF_PACKED32(TAG, TYPEA, TYPEB, ENCSTR) \
|
||||
do { \
|
||||
fprintf(out, "\t\'%s\' : {\n", #TAG); \
|
||||
fprintf(out, "\t\t\'name\' : \'%s\',\n", #TAG); \
|
||||
fprintf(out, "\t\t\'class_a\' : \'%s\',\n", #TYPEA); \
|
||||
fprintf(out, "\t\t\'class_b\' : \'%s\',\n", #TYPEB); \
|
||||
fprintf(out, "\t\t\'enc\' : \'%s\',\n", ENCSTR); \
|
||||
fprintf(out, "\t},\n"); \
|
||||
} while (0);
|
||||
#include "imported/encode.def"
|
||||
#undef DEF_PACKED32
|
||||
fprintf(out, "};\n\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
FILE *outfile;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: gen_dectree_import ouptputfile\n");
|
||||
return 1;
|
||||
}
|
||||
outfile = fopen(argv[1], "w");
|
||||
if (outfile == NULL) {
|
||||
fprintf(stderr, "Cannot open %s for writing\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
gen_iset_table(outfile);
|
||||
gen_tags_list(outfile);
|
||||
gen_enc_ext_spaces_table(outfile);
|
||||
gen_subinsn_groupings_table(outfile);
|
||||
|
||||
fclose(outfile);
|
||||
return 0;
|
||||
}
|
220
target/hexagon/gen_helper_funcs.py
Executable file
220
target/hexagon/gen_helper_funcs.py
Executable file
@ -0,0 +1,220 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
import hex_common
|
||||
|
||||
##
|
||||
## Helpers for gen_helper_function
|
||||
##
|
||||
def gen_decl_ea(f):
|
||||
f.write(" uint32_t EA;\n")
|
||||
|
||||
def gen_helper_return_type(f,regtype,regid,regno):
|
||||
if regno > 1 : f.write(", ")
|
||||
f.write("int32_t")
|
||||
|
||||
def gen_helper_return_type_pair(f,regtype,regid,regno):
|
||||
if regno > 1 : f.write(", ")
|
||||
f.write("int64_t")
|
||||
|
||||
def gen_helper_arg(f,regtype,regid,regno):
|
||||
if regno > 0 : f.write(", " )
|
||||
f.write("int32_t %s%sV" % (regtype,regid))
|
||||
|
||||
def gen_helper_arg_new(f,regtype,regid,regno):
|
||||
if regno >= 0 : f.write(", " )
|
||||
f.write("int32_t %s%sN" % (regtype,regid))
|
||||
|
||||
def gen_helper_arg_pair(f,regtype,regid,regno):
|
||||
if regno >= 0 : f.write(", ")
|
||||
f.write("int64_t %s%sV" % (regtype,regid))
|
||||
|
||||
def gen_helper_arg_opn(f,regtype,regid,i,tag):
|
||||
if (hex_common.is_pair(regid)):
|
||||
gen_helper_arg_pair(f,regtype,regid,i)
|
||||
elif (hex_common.is_single(regid)):
|
||||
if hex_common.is_old_val(regtype, regid, tag):
|
||||
gen_helper_arg(f,regtype,regid,i)
|
||||
elif hex_common.is_new_val(regtype, regid, tag):
|
||||
gen_helper_arg_new(f,regtype,regid,i)
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
|
||||
def gen_helper_arg_imm(f,immlett):
|
||||
f.write(", int32_t %s" % (hex_common.imm_name(immlett)))
|
||||
|
||||
def gen_helper_dest_decl(f,regtype,regid,regno,subfield=""):
|
||||
f.write(" int32_t %s%sV%s = 0;\n" % \
|
||||
(regtype,regid,subfield))
|
||||
|
||||
def gen_helper_dest_decl_pair(f,regtype,regid,regno,subfield=""):
|
||||
f.write(" int64_t %s%sV%s = 0;\n" % \
|
||||
(regtype,regid,subfield))
|
||||
|
||||
def gen_helper_dest_decl_opn(f,regtype,regid,i):
|
||||
if (hex_common.is_pair(regid)):
|
||||
gen_helper_dest_decl_pair(f,regtype,regid,i)
|
||||
elif (hex_common.is_single(regid)):
|
||||
gen_helper_dest_decl(f,regtype,regid,i)
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
|
||||
def gen_helper_return(f,regtype,regid,regno):
|
||||
f.write(" return %s%sV;\n" % (regtype,regid))
|
||||
|
||||
def gen_helper_return_pair(f,regtype,regid,regno):
|
||||
f.write(" return %s%sV;\n" % (regtype,regid))
|
||||
|
||||
def gen_helper_return_opn(f, regtype, regid, i):
|
||||
if (hex_common.is_pair(regid)):
|
||||
gen_helper_return_pair(f,regtype,regid,i)
|
||||
elif (hex_common.is_single(regid)):
|
||||
gen_helper_return(f,regtype,regid,i)
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
|
||||
##
|
||||
## Generate the TCG code to call the helper
|
||||
## For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
|
||||
## We produce:
|
||||
## int32_t HELPER(A2_add)(CPUHexagonState *env, int32_t RsV, int32_t RtV)
|
||||
## {
|
||||
## uint32_t slot __attribute__(unused)) = 4;
|
||||
## int32_t RdV = 0;
|
||||
## { RdV=RsV+RtV;}
|
||||
## COUNT_HELPER(A2_add);
|
||||
## return RdV;
|
||||
## }
|
||||
##
|
||||
def gen_helper_function(f, tag, tagregs, tagimms):
|
||||
regs = tagregs[tag]
|
||||
imms = tagimms[tag]
|
||||
|
||||
numresults = 0
|
||||
numscalarresults = 0
|
||||
numscalarreadwrite = 0
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
if (hex_common.is_written(regid)):
|
||||
numresults += 1
|
||||
if (hex_common.is_scalar_reg(regtype)):
|
||||
numscalarresults += 1
|
||||
if (hex_common.is_readwrite(regid)):
|
||||
if (hex_common.is_scalar_reg(regtype)):
|
||||
numscalarreadwrite += 1
|
||||
|
||||
if (numscalarresults > 1):
|
||||
## The helper is bogus when there is more than one result
|
||||
f.write("void HELPER(%s)(CPUHexagonState *env) { BOGUS_HELPER(%s); }\n"
|
||||
% (tag, tag))
|
||||
else:
|
||||
## The return type of the function is the type of the destination
|
||||
## register
|
||||
i=0
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
if (hex_common.is_written(regid)):
|
||||
if (hex_common.is_pair(regid)):
|
||||
gen_helper_return_type_pair(f,regtype,regid,i)
|
||||
elif (hex_common.is_single(regid)):
|
||||
gen_helper_return_type(f,regtype,regid,i)
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
i += 1
|
||||
|
||||
if (numscalarresults == 0):
|
||||
f.write("void")
|
||||
f.write(" HELPER(%s)(CPUHexagonState *env" % tag)
|
||||
|
||||
i = 1
|
||||
|
||||
## Arguments to the helper function are the source regs and immediates
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
if (hex_common.is_read(regid)):
|
||||
gen_helper_arg_opn(f,regtype,regid,i,tag)
|
||||
i += 1
|
||||
for immlett,bits,immshift in imms:
|
||||
gen_helper_arg_imm(f,immlett)
|
||||
i += 1
|
||||
if hex_common.need_slot(tag):
|
||||
if i > 0: f.write(", ")
|
||||
f.write("uint32_t slot")
|
||||
i += 1
|
||||
if hex_common.need_part1(tag):
|
||||
if i > 0: f.write(", ")
|
||||
f.write("uint32_t part1")
|
||||
f.write(")\n{\n")
|
||||
if (not hex_common.need_slot(tag)):
|
||||
f.write(" uint32_t slot __attribute__((unused)) = 4;\n" )
|
||||
if hex_common.need_ea(tag): gen_decl_ea(f)
|
||||
## Declare the return variable
|
||||
i=0
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
if (hex_common.is_writeonly(regid)):
|
||||
gen_helper_dest_decl_opn(f,regtype,regid,i)
|
||||
i += 1
|
||||
|
||||
if 'A_FPOP' in hex_common.attribdict[tag]:
|
||||
f.write(' arch_fpop_start(env);\n');
|
||||
|
||||
f.write(" %s\n" % hex_common.semdict[tag])
|
||||
|
||||
if 'A_FPOP' in hex_common.attribdict[tag]:
|
||||
f.write(' arch_fpop_end(env);\n');
|
||||
|
||||
## Save/return the return variable
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
if (hex_common.is_written(regid)):
|
||||
gen_helper_return_opn(f, regtype, regid, i)
|
||||
f.write("}\n\n")
|
||||
## End of the helper definition
|
||||
|
||||
def main():
|
||||
hex_common.read_semantics_file(sys.argv[1])
|
||||
hex_common.read_attribs_file(sys.argv[2])
|
||||
hex_common.read_overrides_file(sys.argv[3])
|
||||
hex_common.calculate_attribs()
|
||||
tagregs = hex_common.get_tagregs()
|
||||
tagimms = hex_common.get_tagimms()
|
||||
|
||||
with open(sys.argv[4], 'w') as f:
|
||||
for tag in hex_common.tags:
|
||||
## Skip the priv instructions
|
||||
if ( "A_PRIV" in hex_common.attribdict[tag] ) :
|
||||
continue
|
||||
## Skip the guest instructions
|
||||
if ( "A_GUEST" in hex_common.attribdict[tag] ) :
|
||||
continue
|
||||
## Skip the diag instructions
|
||||
if ( tag == "Y6_diag" ) :
|
||||
continue
|
||||
if ( tag == "Y6_diag0" ) :
|
||||
continue
|
||||
if ( tag == "Y6_diag1" ) :
|
||||
continue
|
||||
if ( hex_common.skip_qemu_helper(tag) ):
|
||||
continue
|
||||
|
||||
gen_helper_function(f, tag, tagregs, tagimms)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
150
target/hexagon/gen_helper_protos.py
Executable file
150
target/hexagon/gen_helper_protos.py
Executable file
@ -0,0 +1,150 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
import hex_common
|
||||
|
||||
##
|
||||
## Helpers for gen_helper_prototype
|
||||
##
|
||||
def_helper_types = {
|
||||
'N' : 's32',
|
||||
'O' : 's32',
|
||||
'P' : 's32',
|
||||
'M' : 's32',
|
||||
'C' : 's32',
|
||||
'R' : 's32',
|
||||
'V' : 'ptr',
|
||||
'Q' : 'ptr'
|
||||
}
|
||||
|
||||
def_helper_types_pair = {
|
||||
'R' : 's64',
|
||||
'C' : 's64',
|
||||
'S' : 's64',
|
||||
'G' : 's64',
|
||||
'V' : 'ptr',
|
||||
'Q' : 'ptr'
|
||||
}
|
||||
|
||||
def gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i):
|
||||
if (hex_common.is_pair(regid)):
|
||||
f.write(", %s" % (def_helper_types_pair[regtype]))
|
||||
elif (hex_common.is_single(regid)):
|
||||
f.write(", %s" % (def_helper_types[regtype]))
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
|
||||
##
|
||||
## Generate the DEF_HELPER prototype for an instruction
|
||||
## For A2_add: Rd32=add(Rs32,Rt32)
|
||||
## We produce:
|
||||
## DEF_HELPER_3(A2_add, s32, env, s32, s32)
|
||||
##
|
||||
def gen_helper_prototype(f, tag, tagregs, tagimms):
|
||||
regs = tagregs[tag]
|
||||
imms = tagimms[tag]
|
||||
|
||||
numresults = 0
|
||||
numscalarresults = 0
|
||||
numscalarreadwrite = 0
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
if (hex_common.is_written(regid)):
|
||||
numresults += 1
|
||||
if (hex_common.is_scalar_reg(regtype)):
|
||||
numscalarresults += 1
|
||||
if (hex_common.is_readwrite(regid)):
|
||||
if (hex_common.is_scalar_reg(regtype)):
|
||||
numscalarreadwrite += 1
|
||||
|
||||
if (numscalarresults > 1):
|
||||
## The helper is bogus when there is more than one result
|
||||
f.write('DEF_HELPER_1(%s, void, env)\n' % tag)
|
||||
else:
|
||||
## Figure out how many arguments the helper will take
|
||||
if (numscalarresults == 0):
|
||||
def_helper_size = len(regs)+len(imms)+numscalarreadwrite+1
|
||||
if hex_common.need_part1(tag): def_helper_size += 1
|
||||
if hex_common.need_slot(tag): def_helper_size += 1
|
||||
f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
|
||||
## The return type is void
|
||||
f.write(', void' )
|
||||
else:
|
||||
def_helper_size = len(regs)+len(imms)+numscalarreadwrite
|
||||
if hex_common.need_part1(tag): def_helper_size += 1
|
||||
if hex_common.need_slot(tag): def_helper_size += 1
|
||||
f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
|
||||
|
||||
## Generate the qemu DEF_HELPER type for each result
|
||||
i=0
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
if (hex_common.is_written(regid)):
|
||||
gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i)
|
||||
i += 1
|
||||
|
||||
## Put the env between the outputs and inputs
|
||||
f.write(', env' )
|
||||
i += 1
|
||||
|
||||
## Generate the qemu type for each input operand (regs and immediates)
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
if (hex_common.is_read(regid)):
|
||||
gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i)
|
||||
i += 1
|
||||
for immlett,bits,immshift in imms:
|
||||
f.write(", s32")
|
||||
|
||||
## Add the arguments for the instruction slot and part1 (if needed)
|
||||
if hex_common.need_slot(tag): f.write(', i32' )
|
||||
if hex_common.need_part1(tag): f.write(' , i32' )
|
||||
f.write(')\n')
|
||||
|
||||
def main():
|
||||
hex_common.read_semantics_file(sys.argv[1])
|
||||
hex_common.read_attribs_file(sys.argv[2])
|
||||
hex_common.read_overrides_file(sys.argv[3])
|
||||
hex_common.calculate_attribs()
|
||||
tagregs = hex_common.get_tagregs()
|
||||
tagimms = hex_common.get_tagimms()
|
||||
|
||||
with open(sys.argv[4], 'w') as f:
|
||||
for tag in hex_common.tags:
|
||||
## Skip the priv instructions
|
||||
if ( "A_PRIV" in hex_common.attribdict[tag] ) :
|
||||
continue
|
||||
## Skip the guest instructions
|
||||
if ( "A_GUEST" in hex_common.attribdict[tag] ) :
|
||||
continue
|
||||
## Skip the diag instructions
|
||||
if ( tag == "Y6_diag" ) :
|
||||
continue
|
||||
if ( tag == "Y6_diag0" ) :
|
||||
continue
|
||||
if ( tag == "Y6_diag1" ) :
|
||||
continue
|
||||
|
||||
if ( hex_common.skip_qemu_helper(tag) ):
|
||||
continue
|
||||
|
||||
gen_helper_prototype(f, tag, tagregs, tagimms)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
39
target/hexagon/gen_op_attribs.py
Executable file
39
target/hexagon/gen_op_attribs.py
Executable file
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
import hex_common
|
||||
|
||||
def main():
|
||||
hex_common.read_semantics_file(sys.argv[1])
|
||||
hex_common.read_attribs_file(sys.argv[2])
|
||||
hex_common.calculate_attribs()
|
||||
|
||||
##
|
||||
## Generate all the attributes associated with each instruction
|
||||
##
|
||||
with open(sys.argv[3], 'w') as f:
|
||||
for tag in hex_common.tags:
|
||||
f.write('OP_ATTRIB(%s,ATTRIBS(%s))\n' % \
|
||||
(tag, ','.join(sorted(hex_common.attribdict[tag]))))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
110
target/hexagon/gen_op_regs.py
Executable file
110
target/hexagon/gen_op_regs.py
Executable file
@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
import hex_common
|
||||
|
||||
##
|
||||
## Generate the register and immediate operands for each instruction
|
||||
##
|
||||
def calculate_regid_reg(tag):
|
||||
def letter_inc(x): return chr(ord(x)+1)
|
||||
ordered_implregs = [ 'SP','FP','LR' ]
|
||||
srcdst_lett = 'X'
|
||||
src_lett = 'S'
|
||||
dst_lett = 'D'
|
||||
retstr = ""
|
||||
mapdict = {}
|
||||
for reg in ordered_implregs:
|
||||
reg_rd = 0
|
||||
reg_wr = 0
|
||||
if ('A_IMPLICIT_WRITES_'+reg) in hex_common.attribdict[tag]: reg_wr = 1
|
||||
if reg_rd and reg_wr:
|
||||
retstr += srcdst_lett
|
||||
mapdict[srcdst_lett] = reg
|
||||
srcdst_lett = letter_inc(srcdst_lett)
|
||||
elif reg_rd:
|
||||
retstr += src_lett
|
||||
mapdict[src_lett] = reg
|
||||
src_lett = letter_inc(src_lett)
|
||||
elif reg_wr:
|
||||
retstr += dst_lett
|
||||
mapdict[dst_lett] = reg
|
||||
dst_lett = letter_inc(dst_lett)
|
||||
return retstr,mapdict
|
||||
|
||||
def calculate_regid_letters(tag):
|
||||
retstr,mapdict = calculate_regid_reg(tag)
|
||||
return retstr
|
||||
|
||||
def strip_reg_prefix(x):
|
||||
y=x.replace('UREG.','')
|
||||
y=y.replace('MREG.','')
|
||||
return y.replace('GREG.','')
|
||||
|
||||
def main():
|
||||
hex_common.read_semantics_file(sys.argv[1])
|
||||
hex_common.read_attribs_file(sys.argv[2])
|
||||
tagregs = hex_common.get_tagregs()
|
||||
tagimms = hex_common.get_tagimms()
|
||||
|
||||
with open(sys.argv[3], 'w') as f:
|
||||
for tag in hex_common.tags:
|
||||
regs = tagregs[tag]
|
||||
rregs = []
|
||||
wregs = []
|
||||
regids = ""
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
if hex_common.is_read(regid):
|
||||
if regid[0] not in regids: regids += regid[0]
|
||||
rregs.append(regtype+regid+numregs)
|
||||
if hex_common.is_written(regid):
|
||||
wregs.append(regtype+regid+numregs)
|
||||
if regid[0] not in regids: regids += regid[0]
|
||||
for attrib in hex_common.attribdict[tag]:
|
||||
if hex_common.attribinfo[attrib]['rreg']:
|
||||
rregs.append(strip_reg_prefix(attribinfo[attrib]['rreg']))
|
||||
if hex_common.attribinfo[attrib]['wreg']:
|
||||
wregs.append(strip_reg_prefix(attribinfo[attrib]['wreg']))
|
||||
regids += calculate_regid_letters(tag)
|
||||
f.write('REGINFO(%s,"%s",\t/*RD:*/\t"%s",\t/*WR:*/\t"%s")\n' % \
|
||||
(tag,regids,",".join(rregs),",".join(wregs)))
|
||||
|
||||
for tag in hex_common.tags:
|
||||
imms = tagimms[tag]
|
||||
f.write( 'IMMINFO(%s' % tag)
|
||||
if not imms:
|
||||
f.write(''','u',0,0,'U',0,0''')
|
||||
for sign,size,shamt in imms:
|
||||
if sign == 'r': sign = 's'
|
||||
if not shamt:
|
||||
shamt = "0"
|
||||
f.write(''','%s',%s,%s''' % (sign,size,shamt))
|
||||
if len(imms) == 1:
|
||||
if sign.isupper():
|
||||
myu = 'u'
|
||||
else:
|
||||
myu = 'U'
|
||||
f.write(''','%s',0,0''' % myu)
|
||||
f.write(')\n')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
36
target/hexagon/gen_opcodes_def.py
Executable file
36
target/hexagon/gen_opcodes_def.py
Executable file
@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
import hex_common
|
||||
|
||||
def main():
|
||||
hex_common.read_semantics_file(sys.argv[1])
|
||||
|
||||
##
|
||||
## Generate a list of all the opcodes
|
||||
##
|
||||
with open(sys.argv[3], 'w') as f:
|
||||
for tag in hex_common.tags:
|
||||
f.write ( "OPCODE(%s),\n" % (tag) )
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
173
target/hexagon/gen_printinsn.py
Executable file
173
target/hexagon/gen_printinsn.py
Executable file
@ -0,0 +1,173 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
import hex_common
|
||||
|
||||
##
|
||||
## Generate data for printing each instruction (format string + operands)
|
||||
##
|
||||
def regprinter(m):
|
||||
str = m.group(1)
|
||||
str += ":".join(["%d"]*len(m.group(2)))
|
||||
str += m.group(3)
|
||||
if ('S' in m.group(1)) and (len(m.group(2)) == 1):
|
||||
str += "/%s"
|
||||
elif ('C' in m.group(1)) and (len(m.group(2)) == 1):
|
||||
str += "/%s"
|
||||
return str
|
||||
|
||||
def spacify(s):
|
||||
# Regular expression that matches any operator that contains '=' character:
|
||||
opswithequal_re = '[-+^&|!<>=]?='
|
||||
# Regular expression that matches any assignment operator.
|
||||
assignment_re = '[-+^&|]?='
|
||||
|
||||
# Out of the operators that contain the = sign, if the operator is also an
|
||||
# assignment, spaces will be added around it, unless it's enclosed within
|
||||
# parentheses, or spaces are already present.
|
||||
|
||||
equals = re.compile(opswithequal_re)
|
||||
assign = re.compile(assignment_re)
|
||||
|
||||
slen = len(s)
|
||||
paren_count = {}
|
||||
i = 0
|
||||
pc = 0
|
||||
while i < slen:
|
||||
c = s[i]
|
||||
if c == '(':
|
||||
pc += 1
|
||||
elif c == ')':
|
||||
pc -= 1
|
||||
paren_count[i] = pc
|
||||
i += 1
|
||||
|
||||
# Iterate over all operators that contain the equal sign. If any
|
||||
# match is also an assignment operator, add spaces around it if
|
||||
# the parenthesis count is 0.
|
||||
pos = 0
|
||||
out = []
|
||||
for m in equals.finditer(s):
|
||||
ms = m.start()
|
||||
me = m.end()
|
||||
# t is the string that matched opswithequal_re.
|
||||
t = m.string[ms:me]
|
||||
out += s[pos:ms]
|
||||
pos = me
|
||||
if paren_count[ms] == 0:
|
||||
# Check if the entire string t is an assignment.
|
||||
am = assign.match(t)
|
||||
if am and len(am.group(0)) == me-ms:
|
||||
# Don't add spaces if they are already there.
|
||||
if ms > 0 and s[ms-1] != ' ':
|
||||
out.append(' ')
|
||||
out += t
|
||||
if me < slen and s[me] != ' ':
|
||||
out.append(' ')
|
||||
continue
|
||||
# If this is not an assignment, just append it to the output
|
||||
# string.
|
||||
out += t
|
||||
|
||||
# Append the remaining part of the string.
|
||||
out += s[pos:len(s)]
|
||||
return ''.join(out)
|
||||
|
||||
def main():
|
||||
hex_common.read_semantics_file(sys.argv[1])
|
||||
hex_common.read_attribs_file(sys.argv[2])
|
||||
|
||||
immext_casere = re.compile(r'IMMEXT\(([A-Za-z])')
|
||||
|
||||
with open(sys.argv[3], 'w') as f:
|
||||
for tag in hex_common.tags:
|
||||
if not hex_common.behdict[tag]: continue
|
||||
extendable_upper_imm = False
|
||||
extendable_lower_imm = False
|
||||
m = immext_casere.search(hex_common.semdict[tag])
|
||||
if m:
|
||||
if m.group(1).isupper():
|
||||
extendable_upper_imm = True
|
||||
else:
|
||||
extendable_lower_imm = True
|
||||
beh = hex_common.behdict[tag]
|
||||
beh = hex_common.regre.sub(regprinter,beh)
|
||||
beh = hex_common.absimmre.sub(r"#%s0x%x",beh)
|
||||
beh = hex_common.relimmre.sub(r"PC+%s%d",beh)
|
||||
beh = spacify(beh)
|
||||
# Print out a literal "%s" at the end, used to match empty string
|
||||
# so C won't complain at us
|
||||
if ("A_VECX" in hex_common.attribdict[tag]):
|
||||
macname = "DEF_VECX_PRINTINFO"
|
||||
else: macname = "DEF_PRINTINFO"
|
||||
f.write('%s(%s,"%s%%s"' % (macname,tag,beh))
|
||||
regs_or_imms = \
|
||||
hex_common.reg_or_immre.findall(hex_common.behdict[tag])
|
||||
ri = 0
|
||||
seenregs = {}
|
||||
for allregs,a,b,c,d,allimm,immlett,bits,immshift in regs_or_imms:
|
||||
if a:
|
||||
#register
|
||||
if b in seenregs:
|
||||
regno = seenregs[b]
|
||||
else:
|
||||
regno = ri
|
||||
if len(b) == 1:
|
||||
f.write(', insn->regno[%d]' % regno)
|
||||
if 'S' in a:
|
||||
f.write(', sreg2str(insn->regno[%d])' % regno)
|
||||
elif 'C' in a:
|
||||
f.write(', creg2str(insn->regno[%d])' % regno)
|
||||
elif len(b) == 2:
|
||||
f.write(', insn->regno[%d] + 1, insn->regno[%d]' % \
|
||||
(regno,regno))
|
||||
else:
|
||||
print("Put some stuff to handle quads here")
|
||||
if b not in seenregs:
|
||||
seenregs[b] = ri
|
||||
ri += 1
|
||||
else:
|
||||
#immediate
|
||||
if (immlett.isupper()):
|
||||
if extendable_upper_imm:
|
||||
if immlett in 'rR':
|
||||
f.write(',insn->extension_valid?"##":""')
|
||||
else:
|
||||
f.write(',insn->extension_valid?"#":""')
|
||||
else:
|
||||
f.write(',""')
|
||||
ii = 1
|
||||
else:
|
||||
if extendable_lower_imm:
|
||||
if immlett in 'rR':
|
||||
f.write(',insn->extension_valid?"##":""')
|
||||
else:
|
||||
f.write(',insn->extension_valid?"#":""')
|
||||
else:
|
||||
f.write(',""')
|
||||
ii = 0
|
||||
f.write(', insn->immed[%d]' % ii)
|
||||
# append empty string so there is at least one more arg
|
||||
f.write(',"")\n')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
88
target/hexagon/gen_semantics.c
Normal file
88
target/hexagon/gen_semantics.c
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program generates the semantics file that is processed by
|
||||
* the do_qemu.py script. We use the C preporcessor to manipulate the
|
||||
* files imported from the Hexagon architecture library.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#define STRINGIZE(X) #X
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
FILE *outfile;
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "Usage: gen_semantics ouptputfile\n");
|
||||
return 1;
|
||||
}
|
||||
outfile = fopen(argv[1], "w");
|
||||
if (outfile == NULL) {
|
||||
fprintf(stderr, "Cannot open %s for writing\n", argv[1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process the instruction definitions
|
||||
* Scalar core instructions have the following form
|
||||
* Q6INSN(A2_add,"Rd32=add(Rs32,Rt32)",ATTRIBS(),
|
||||
* "Add 32-bit registers",
|
||||
* { RdV=RsV+RtV;})
|
||||
*/
|
||||
#define Q6INSN(TAG, BEH, ATTRIBS, DESCR, SEM) \
|
||||
do { \
|
||||
fprintf(outfile, "SEMANTICS( \\\n" \
|
||||
" \"%s\", \\\n" \
|
||||
" %s, \\\n" \
|
||||
" \"\"\"%s\"\"\" \\\n" \
|
||||
")\n", \
|
||||
#TAG, STRINGIZE(BEH), STRINGIZE(SEM)); \
|
||||
fprintf(outfile, "ATTRIBUTES( \\\n" \
|
||||
" \"%s\", \\\n" \
|
||||
" \"%s\" \\\n" \
|
||||
")\n", \
|
||||
#TAG, STRINGIZE(ATTRIBS)); \
|
||||
} while (0);
|
||||
#include "imported/allidefs.def"
|
||||
#undef Q6INSN
|
||||
|
||||
/*
|
||||
* Process the macro definitions
|
||||
* Macros definitions have the following form
|
||||
* DEF_MACRO(
|
||||
* fLSBNEW0,
|
||||
* predlog_read(thread,0),
|
||||
* ()
|
||||
* )
|
||||
* The important part here is the attributes. Whenever an instruction
|
||||
* invokes a macro, we add the macro's attributes to the instruction.
|
||||
*/
|
||||
#define DEF_MACRO(MNAME, BEH, ATTRS) \
|
||||
fprintf(outfile, "MACROATTRIB( \\\n" \
|
||||
" \"%s\", \\\n" \
|
||||
" \"\"\"%s\"\"\", \\\n" \
|
||||
" \"%s\" \\\n" \
|
||||
")\n", \
|
||||
#MNAME, STRINGIZE(BEH), STRINGIZE(ATTRS));
|
||||
#include "imported/macros.def"
|
||||
#undef DEF_MACRO
|
||||
|
||||
fclose(outfile);
|
||||
return 0;
|
||||
}
|
60
target/hexagon/gen_shortcode.py
Executable file
60
target/hexagon/gen_shortcode.py
Executable file
@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
import hex_common
|
||||
|
||||
def gen_shortcode(f, tag):
|
||||
f.write('DEF_SHORTCODE(%s, %s)\n' % (tag, hex_common.semdict[tag]))
|
||||
|
||||
def main():
|
||||
hex_common.read_semantics_file(sys.argv[1])
|
||||
hex_common.read_attribs_file(sys.argv[2])
|
||||
hex_common.calculate_attribs()
|
||||
tagregs = hex_common.get_tagregs()
|
||||
tagimms = hex_common.get_tagimms()
|
||||
|
||||
with open(sys.argv[3], 'w') as f:
|
||||
f.write("#ifndef DEF_SHORTCODE\n")
|
||||
f.write("#define DEF_SHORTCODE(TAG,SHORTCODE) /* Nothing */\n")
|
||||
f.write("#endif\n")
|
||||
|
||||
for tag in hex_common.tags:
|
||||
## Skip the priv instructions
|
||||
if ( "A_PRIV" in hex_common.attribdict[tag] ) :
|
||||
continue
|
||||
## Skip the guest instructions
|
||||
if ( "A_GUEST" in hex_common.attribdict[tag] ) :
|
||||
continue
|
||||
## Skip the diag instructions
|
||||
if ( tag == "Y6_diag" ) :
|
||||
continue
|
||||
if ( tag == "Y6_diag0" ) :
|
||||
continue
|
||||
if ( tag == "Y6_diag1" ) :
|
||||
continue
|
||||
|
||||
gen_shortcode(f, tag)
|
||||
|
||||
f.write("#undef DEF_SHORTCODE\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
319
target/hexagon/gen_tcg.h
Normal file
319
target/hexagon/gen_tcg.h
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_GEN_TCG_H
|
||||
#define HEXAGON_GEN_TCG_H
|
||||
|
||||
/*
|
||||
* Here is a primer to understand the tag names for load/store instructions
|
||||
*
|
||||
* Data types
|
||||
* b signed byte r0 = memb(r2+#0)
|
||||
* ub unsigned byte r0 = memub(r2+#0)
|
||||
* h signed half word (16 bits) r0 = memh(r2+#0)
|
||||
* uh unsigned half word r0 = memuh(r2+#0)
|
||||
* i integer (32 bits) r0 = memw(r2+#0)
|
||||
* d double word (64 bits) r1:0 = memd(r2+#0)
|
||||
*
|
||||
* Addressing modes
|
||||
* _io indirect with offset r0 = memw(r1+#4)
|
||||
* _ur absolute with register offset r0 = memw(r1<<#4+##variable)
|
||||
* _rr indirect with register offset r0 = memw(r1+r4<<#2)
|
||||
* gp global pointer relative r0 = memw(gp+#200)
|
||||
* _sp stack pointer relative r0 = memw(r29+#12)
|
||||
* _ap absolute set r0 = memw(r1=##variable)
|
||||
* _pr post increment register r0 = memw(r1++m1)
|
||||
* _pi post increment immediate r0 = memb(r1++#1)
|
||||
*/
|
||||
|
||||
/* Macros for complex addressing modes */
|
||||
#define GET_EA_ap \
|
||||
do { \
|
||||
fEA_IMM(UiV); \
|
||||
tcg_gen_movi_tl(ReV, UiV); \
|
||||
} while (0)
|
||||
#define GET_EA_pr \
|
||||
do { \
|
||||
fEA_REG(RxV); \
|
||||
fPM_M(RxV, MuV); \
|
||||
} while (0)
|
||||
#define GET_EA_pi \
|
||||
do { \
|
||||
fEA_REG(RxV); \
|
||||
fPM_I(RxV, siV); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Instructions with multiple definitions */
|
||||
#define fGEN_TCG_LOAD_AP(RES, SIZE, SIGN) \
|
||||
do { \
|
||||
fMUST_IMMEXT(UiV); \
|
||||
fEA_IMM(UiV); \
|
||||
fLOAD(1, SIZE, SIGN, EA, RES); \
|
||||
tcg_gen_movi_tl(ReV, UiV); \
|
||||
} while (0)
|
||||
|
||||
#define fGEN_TCG_L4_loadrub_ap(SHORTCODE) \
|
||||
fGEN_TCG_LOAD_AP(RdV, 1, u)
|
||||
#define fGEN_TCG_L4_loadrb_ap(SHORTCODE) \
|
||||
fGEN_TCG_LOAD_AP(RdV, 1, s)
|
||||
#define fGEN_TCG_L4_loadruh_ap(SHORTCODE) \
|
||||
fGEN_TCG_LOAD_AP(RdV, 2, u)
|
||||
#define fGEN_TCG_L4_loadrh_ap(SHORTCODE) \
|
||||
fGEN_TCG_LOAD_AP(RdV, 2, s)
|
||||
#define fGEN_TCG_L4_loadri_ap(SHORTCODE) \
|
||||
fGEN_TCG_LOAD_AP(RdV, 4, u)
|
||||
#define fGEN_TCG_L4_loadrd_ap(SHORTCODE) \
|
||||
fGEN_TCG_LOAD_AP(RddV, 8, u)
|
||||
|
||||
#define fGEN_TCG_L2_loadrub_pr(SHORTCODE) SHORTCODE
|
||||
#define fGEN_TCG_L2_loadrub_pi(SHORTCODE) SHORTCODE
|
||||
#define fGEN_TCG_L2_loadrb_pr(SHORTCODE) SHORTCODE
|
||||
#define fGEN_TCG_L2_loadrb_pi(SHORTCODE) SHORTCODE;
|
||||
#define fGEN_TCG_L2_loadruh_pr(SHORTCODE) SHORTCODE
|
||||
#define fGEN_TCG_L2_loadruh_pi(SHORTCODE) SHORTCODE;
|
||||
#define fGEN_TCG_L2_loadrh_pr(SHORTCODE) SHORTCODE
|
||||
#define fGEN_TCG_L2_loadrh_pi(SHORTCODE) SHORTCODE
|
||||
#define fGEN_TCG_L2_loadri_pr(SHORTCODE) SHORTCODE
|
||||
#define fGEN_TCG_L2_loadri_pi(SHORTCODE) SHORTCODE
|
||||
#define fGEN_TCG_L2_loadrd_pr(SHORTCODE) SHORTCODE
|
||||
#define fGEN_TCG_L2_loadrd_pi(SHORTCODE) SHORTCODE
|
||||
|
||||
/*
|
||||
* Predicated loads
|
||||
* Here is a primer to understand the tag names
|
||||
*
|
||||
* Predicate used
|
||||
* t true "old" value if (p0) r0 = memb(r2+#0)
|
||||
* f false "old" value if (!p0) r0 = memb(r2+#0)
|
||||
* tnew true "new" value if (p0.new) r0 = memb(r2+#0)
|
||||
* fnew false "new" value if (!p0.new) r0 = memb(r2+#0)
|
||||
*/
|
||||
#define fGEN_TCG_PRED_LOAD(GET_EA, PRED, SIZE, SIGN) \
|
||||
do { \
|
||||
TCGv LSB = tcg_temp_local_new(); \
|
||||
TCGLabel *label = gen_new_label(); \
|
||||
GET_EA; \
|
||||
PRED; \
|
||||
PRED_LOAD_CANCEL(LSB, EA); \
|
||||
tcg_gen_movi_tl(RdV, 0); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
|
||||
fLOAD(1, SIZE, SIGN, EA, RdV); \
|
||||
gen_set_label(label); \
|
||||
tcg_temp_free(LSB); \
|
||||
} while (0)
|
||||
|
||||
#define fGEN_TCG_L2_ploadrubt_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 1, u)
|
||||
#define fGEN_TCG_L2_ploadrubf_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 1, u)
|
||||
#define fGEN_TCG_L2_ploadrubtnew_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 1, u)
|
||||
#define fGEN_TCG_L2_ploadrubfnew_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEWNOT(PtN), 1, u)
|
||||
#define fGEN_TCG_L2_ploadrbt_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 1, s)
|
||||
#define fGEN_TCG_L2_ploadrbf_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 1, s)
|
||||
#define fGEN_TCG_L2_ploadrbtnew_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 1, s)
|
||||
#define fGEN_TCG_L2_ploadrbfnew_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD({ fEA_REG(RxV); fPM_I(RxV, siV); }, \
|
||||
fLSBNEWNOT(PtN), 1, s)
|
||||
|
||||
#define fGEN_TCG_L2_ploadruht_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 2, u)
|
||||
#define fGEN_TCG_L2_ploadruhf_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 2, u)
|
||||
#define fGEN_TCG_L2_ploadruhtnew_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 2, u)
|
||||
#define fGEN_TCG_L2_ploadruhfnew_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEWNOT(PtN), 2, u)
|
||||
#define fGEN_TCG_L2_ploadrht_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 2, s)
|
||||
#define fGEN_TCG_L2_ploadrhf_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 2, s)
|
||||
#define fGEN_TCG_L2_ploadrhtnew_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 2, s)
|
||||
#define fGEN_TCG_L2_ploadrhfnew_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEWNOT(PtN), 2, s)
|
||||
|
||||
#define fGEN_TCG_L2_ploadrit_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLD(PtV), 4, u)
|
||||
#define fGEN_TCG_L2_ploadrif_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBOLDNOT(PtV), 4, u)
|
||||
#define fGEN_TCG_L2_ploadritnew_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEW(PtN), 4, u)
|
||||
#define fGEN_TCG_L2_ploadrifnew_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD(GET_EA_pi, fLSBNEWNOT(PtN), 4, u)
|
||||
|
||||
/* Predicated loads into a register pair */
|
||||
#define fGEN_TCG_PRED_LOAD_PAIR(GET_EA, PRED) \
|
||||
do { \
|
||||
TCGv LSB = tcg_temp_local_new(); \
|
||||
TCGLabel *label = gen_new_label(); \
|
||||
GET_EA; \
|
||||
PRED; \
|
||||
PRED_LOAD_CANCEL(LSB, EA); \
|
||||
tcg_gen_movi_i64(RddV, 0); \
|
||||
tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, label); \
|
||||
fLOAD(1, 8, u, EA, RddV); \
|
||||
gen_set_label(label); \
|
||||
tcg_temp_free(LSB); \
|
||||
} while (0)
|
||||
|
||||
#define fGEN_TCG_L2_ploadrdt_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD_PAIR(GET_EA_pi, fLSBOLD(PtV))
|
||||
#define fGEN_TCG_L2_ploadrdf_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD_PAIR(GET_EA_pi, fLSBOLDNOT(PtV))
|
||||
#define fGEN_TCG_L2_ploadrdtnew_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD_PAIR(GET_EA_pi, fLSBNEW(PtN))
|
||||
#define fGEN_TCG_L2_ploadrdfnew_pi(SHORTCODE) \
|
||||
fGEN_TCG_PRED_LOAD_PAIR(GET_EA_pi, fLSBNEWNOT(PtN))
|
||||
|
||||
/* load-locked and store-locked */
|
||||
#define fGEN_TCG_L2_loadw_locked(SHORTCODE) \
|
||||
SHORTCODE
|
||||
#define fGEN_TCG_L4_loadd_locked(SHORTCODE) \
|
||||
SHORTCODE
|
||||
#define fGEN_TCG_S2_storew_locked(SHORTCODE) \
|
||||
do { SHORTCODE; READ_PREG(PdV, PdN); } while (0)
|
||||
#define fGEN_TCG_S4_stored_locked(SHORTCODE) \
|
||||
do { SHORTCODE; READ_PREG(PdV, PdN); } while (0)
|
||||
|
||||
/* Floating point */
|
||||
#define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \
|
||||
gen_helper_conv_sf2df(RddV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_conv_df2sf(SHORTCODE) \
|
||||
gen_helper_conv_df2sf(RdV, cpu_env, RssV)
|
||||
#define fGEN_TCG_F2_conv_uw2sf(SHORTCODE) \
|
||||
gen_helper_conv_uw2sf(RdV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_conv_uw2df(SHORTCODE) \
|
||||
gen_helper_conv_uw2df(RddV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_conv_w2sf(SHORTCODE) \
|
||||
gen_helper_conv_w2sf(RdV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_conv_w2df(SHORTCODE) \
|
||||
gen_helper_conv_w2df(RddV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_conv_ud2sf(SHORTCODE) \
|
||||
gen_helper_conv_ud2sf(RdV, cpu_env, RssV)
|
||||
#define fGEN_TCG_F2_conv_ud2df(SHORTCODE) \
|
||||
gen_helper_conv_ud2df(RddV, cpu_env, RssV)
|
||||
#define fGEN_TCG_F2_conv_d2sf(SHORTCODE) \
|
||||
gen_helper_conv_d2sf(RdV, cpu_env, RssV)
|
||||
#define fGEN_TCG_F2_conv_d2df(SHORTCODE) \
|
||||
gen_helper_conv_d2df(RddV, cpu_env, RssV)
|
||||
#define fGEN_TCG_F2_conv_sf2uw(SHORTCODE) \
|
||||
gen_helper_conv_sf2uw(RdV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_conv_sf2w(SHORTCODE) \
|
||||
gen_helper_conv_sf2w(RdV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_conv_sf2ud(SHORTCODE) \
|
||||
gen_helper_conv_sf2ud(RddV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_conv_sf2d(SHORTCODE) \
|
||||
gen_helper_conv_sf2d(RddV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_conv_df2uw(SHORTCODE) \
|
||||
gen_helper_conv_df2uw(RdV, cpu_env, RssV)
|
||||
#define fGEN_TCG_F2_conv_df2w(SHORTCODE) \
|
||||
gen_helper_conv_df2w(RdV, cpu_env, RssV)
|
||||
#define fGEN_TCG_F2_conv_df2ud(SHORTCODE) \
|
||||
gen_helper_conv_df2ud(RddV, cpu_env, RssV)
|
||||
#define fGEN_TCG_F2_conv_df2d(SHORTCODE) \
|
||||
gen_helper_conv_df2d(RddV, cpu_env, RssV)
|
||||
#define fGEN_TCG_F2_conv_sf2uw_chop(SHORTCODE) \
|
||||
gen_helper_conv_sf2uw_chop(RdV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_conv_sf2w_chop(SHORTCODE) \
|
||||
gen_helper_conv_sf2w_chop(RdV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_conv_sf2ud_chop(SHORTCODE) \
|
||||
gen_helper_conv_sf2ud_chop(RddV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_conv_sf2d_chop(SHORTCODE) \
|
||||
gen_helper_conv_sf2d_chop(RddV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_conv_df2uw_chop(SHORTCODE) \
|
||||
gen_helper_conv_df2uw_chop(RdV, cpu_env, RssV)
|
||||
#define fGEN_TCG_F2_conv_df2w_chop(SHORTCODE) \
|
||||
gen_helper_conv_df2w_chop(RdV, cpu_env, RssV)
|
||||
#define fGEN_TCG_F2_conv_df2ud_chop(SHORTCODE) \
|
||||
gen_helper_conv_df2ud_chop(RddV, cpu_env, RssV)
|
||||
#define fGEN_TCG_F2_conv_df2d_chop(SHORTCODE) \
|
||||
gen_helper_conv_df2d_chop(RddV, cpu_env, RssV)
|
||||
#define fGEN_TCG_F2_sfadd(SHORTCODE) \
|
||||
gen_helper_sfadd(RdV, cpu_env, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sfsub(SHORTCODE) \
|
||||
gen_helper_sfsub(RdV, cpu_env, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sfcmpeq(SHORTCODE) \
|
||||
gen_helper_sfcmpeq(PdV, cpu_env, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sfcmpgt(SHORTCODE) \
|
||||
gen_helper_sfcmpgt(PdV, cpu_env, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sfcmpge(SHORTCODE) \
|
||||
gen_helper_sfcmpge(PdV, cpu_env, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sfcmpuo(SHORTCODE) \
|
||||
gen_helper_sfcmpuo(PdV, cpu_env, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sfmax(SHORTCODE) \
|
||||
gen_helper_sfmax(RdV, cpu_env, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sfmin(SHORTCODE) \
|
||||
gen_helper_sfmin(RdV, cpu_env, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sfclass(SHORTCODE) \
|
||||
do { \
|
||||
TCGv imm = tcg_const_tl(uiV); \
|
||||
gen_helper_sfclass(PdV, cpu_env, RsV, imm); \
|
||||
tcg_temp_free(imm); \
|
||||
} while (0)
|
||||
#define fGEN_TCG_F2_sffixupn(SHORTCODE) \
|
||||
gen_helper_sffixupn(RdV, cpu_env, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sffixupd(SHORTCODE) \
|
||||
gen_helper_sffixupd(RdV, cpu_env, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sffixupr(SHORTCODE) \
|
||||
gen_helper_sffixupr(RdV, cpu_env, RsV)
|
||||
#define fGEN_TCG_F2_dfadd(SHORTCODE) \
|
||||
gen_helper_dfadd(RddV, cpu_env, RssV, RttV)
|
||||
#define fGEN_TCG_F2_dfsub(SHORTCODE) \
|
||||
gen_helper_dfsub(RddV, cpu_env, RssV, RttV)
|
||||
#define fGEN_TCG_F2_dfmax(SHORTCODE) \
|
||||
gen_helper_dfmax(RddV, cpu_env, RssV, RttV)
|
||||
#define fGEN_TCG_F2_dfmin(SHORTCODE) \
|
||||
gen_helper_dfmin(RddV, cpu_env, RssV, RttV)
|
||||
#define fGEN_TCG_F2_dfcmpeq(SHORTCODE) \
|
||||
gen_helper_dfcmpeq(PdV, cpu_env, RssV, RttV)
|
||||
#define fGEN_TCG_F2_dfcmpgt(SHORTCODE) \
|
||||
gen_helper_dfcmpgt(PdV, cpu_env, RssV, RttV)
|
||||
#define fGEN_TCG_F2_dfcmpge(SHORTCODE) \
|
||||
gen_helper_dfcmpge(PdV, cpu_env, RssV, RttV)
|
||||
#define fGEN_TCG_F2_dfcmpuo(SHORTCODE) \
|
||||
gen_helper_dfcmpuo(PdV, cpu_env, RssV, RttV)
|
||||
#define fGEN_TCG_F2_dfclass(SHORTCODE) \
|
||||
do { \
|
||||
TCGv imm = tcg_const_tl(uiV); \
|
||||
gen_helper_dfclass(PdV, cpu_env, RssV, imm); \
|
||||
tcg_temp_free(imm); \
|
||||
} while (0)
|
||||
#define fGEN_TCG_F2_sfmpy(SHORTCODE) \
|
||||
gen_helper_sfmpy(RdV, cpu_env, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sffma(SHORTCODE) \
|
||||
gen_helper_sffma(RxV, cpu_env, RxV, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sffma_sc(SHORTCODE) \
|
||||
gen_helper_sffma_sc(RxV, cpu_env, RxV, RsV, RtV, PuV)
|
||||
#define fGEN_TCG_F2_sffms(SHORTCODE) \
|
||||
gen_helper_sffms(RxV, cpu_env, RxV, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sffma_lib(SHORTCODE) \
|
||||
gen_helper_sffma_lib(RxV, cpu_env, RxV, RsV, RtV)
|
||||
#define fGEN_TCG_F2_sffms_lib(SHORTCODE) \
|
||||
gen_helper_sffms_lib(RxV, cpu_env, RxV, RsV, RtV)
|
||||
|
||||
#define fGEN_TCG_F2_dfmpyfix(SHORTCODE) \
|
||||
gen_helper_dfmpyfix(RddV, cpu_env, RssV, RttV)
|
||||
#define fGEN_TCG_F2_dfmpyhh(SHORTCODE) \
|
||||
gen_helper_dfmpyhh(RxxV, cpu_env, RxxV, RssV, RttV)
|
||||
|
||||
#endif
|
58
target/hexagon/gen_tcg_func_table.py
Executable file
58
target/hexagon/gen_tcg_func_table.py
Executable file
@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
import hex_common
|
||||
|
||||
def main():
|
||||
hex_common.read_semantics_file(sys.argv[1])
|
||||
hex_common.read_attribs_file(sys.argv[2])
|
||||
hex_common.calculate_attribs()
|
||||
tagregs = hex_common.get_tagregs()
|
||||
tagimms = hex_common.get_tagimms()
|
||||
|
||||
with open(sys.argv[3], 'w') as f:
|
||||
f.write("#ifndef HEXAGON_FUNC_TABLE_H\n")
|
||||
f.write("#define HEXAGON_FUNC_TABLE_H\n\n")
|
||||
|
||||
f.write("const SemanticInsn opcode_genptr[XX_LAST_OPCODE] = {\n")
|
||||
for tag in hex_common.tags:
|
||||
## Skip the priv instructions
|
||||
if ( "A_PRIV" in hex_common.attribdict[tag] ) :
|
||||
continue
|
||||
## Skip the guest instructions
|
||||
if ( "A_GUEST" in hex_common.attribdict[tag] ) :
|
||||
continue
|
||||
## Skip the diag instructions
|
||||
if ( tag == "Y6_diag" ) :
|
||||
continue
|
||||
if ( tag == "Y6_diag0" ) :
|
||||
continue
|
||||
if ( tag == "Y6_diag1" ) :
|
||||
continue
|
||||
|
||||
f.write(" [%s] = generate_%s,\n" % (tag, tag))
|
||||
f.write("};\n\n")
|
||||
|
||||
f.write("#endif /* HEXAGON_FUNC_TABLE_H */\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
485
target/hexagon/gen_tcg_funcs.py
Executable file
485
target/hexagon/gen_tcg_funcs.py
Executable file
@ -0,0 +1,485 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
import hex_common
|
||||
|
||||
##
|
||||
## Helpers for gen_tcg_func
|
||||
##
|
||||
def gen_decl_ea_tcg(f, tag):
|
||||
if ('A_CONDEXEC' in hex_common.attribdict[tag] or
|
||||
'A_LOAD' in hex_common.attribdict[tag]):
|
||||
f.write(" TCGv EA = tcg_temp_local_new();\n")
|
||||
else:
|
||||
f.write(" TCGv EA = tcg_temp_new();\n")
|
||||
|
||||
def gen_free_ea_tcg(f):
|
||||
f.write(" tcg_temp_free(EA);\n")
|
||||
|
||||
def genptr_decl_pair_writeble(f, tag, regtype, regid, regno):
|
||||
regN="%s%sN" % (regtype,regid)
|
||||
f.write(" TCGv_i64 %s%sV = tcg_temp_local_new_i64();\n" % \
|
||||
(regtype, regid))
|
||||
if (regtype == "C"):
|
||||
f.write(" const int %s = insn->regno[%d] + HEX_REG_SA0;\n" % \
|
||||
(regN, regno))
|
||||
else:
|
||||
f.write(" const int %s = insn->regno[%d];\n" % (regN, regno))
|
||||
if ('A_CONDEXEC' in hex_common.attribdict[tag]):
|
||||
f.write(" if (!is_preloaded(ctx, %s)) {\n" % regN)
|
||||
f.write(" tcg_gen_mov_tl(hex_new_value[%s], hex_gpr[%s]);\n" % \
|
||||
(regN, regN))
|
||||
f.write(" }\n")
|
||||
f.write(" if (!is_preloaded(ctx, %s + 1)) {\n" % regN)
|
||||
f.write(" tcg_gen_mov_tl(hex_new_value[%s + 1], hex_gpr[%s + 1]);\n" % \
|
||||
(regN, regN))
|
||||
f.write(" }\n")
|
||||
|
||||
def genptr_decl_writeble(f, tag, regtype, regid, regno):
|
||||
regN="%s%sN" % (regtype,regid)
|
||||
f.write(" TCGv %s%sV = tcg_temp_local_new();\n" % \
|
||||
(regtype, regid))
|
||||
if (regtype == "C"):
|
||||
f.write(" const int %s = insn->regno[%d] + HEX_REG_SA0;\n" % \
|
||||
(regN, regno))
|
||||
else:
|
||||
f.write(" const int %s = insn->regno[%d];\n" % (regN, regno))
|
||||
if ('A_CONDEXEC' in hex_common.attribdict[tag]):
|
||||
f.write(" if (!is_preloaded(ctx, %s)) {\n" % regN)
|
||||
f.write(" tcg_gen_mov_tl(hex_new_value[%s], hex_gpr[%s]);\n" % \
|
||||
(regN, regN))
|
||||
f.write(" }\n")
|
||||
|
||||
def genptr_decl(f, tag, regtype, regid, regno):
|
||||
regN="%s%sN" % (regtype,regid)
|
||||
if (regtype == "R"):
|
||||
if (regid in {"ss", "tt"}):
|
||||
f.write(" TCGv_i64 %s%sV = tcg_temp_local_new_i64();\n" % \
|
||||
(regtype, regid))
|
||||
f.write(" const int %s = insn->regno[%d];\n" % \
|
||||
(regN, regno))
|
||||
elif (regid in {"dd", "ee", "xx", "yy"}):
|
||||
genptr_decl_pair_writeble(f, tag, regtype, regid, regno)
|
||||
elif (regid in {"s", "t", "u", "v"}):
|
||||
f.write(" TCGv %s%sV = hex_gpr[insn->regno[%d]];\n" % \
|
||||
(regtype, regid, regno))
|
||||
elif (regid in {"d", "e", "x", "y"}):
|
||||
genptr_decl_writeble(f, tag, regtype, regid, regno)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
elif (regtype == "P"):
|
||||
if (regid in {"s", "t", "u", "v"}):
|
||||
f.write(" TCGv %s%sV = hex_pred[insn->regno[%d]];\n" % \
|
||||
(regtype, regid, regno))
|
||||
elif (regid in {"d", "e", "x"}):
|
||||
genptr_decl_writeble(f, tag, regtype, regid, regno)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
elif (regtype == "C"):
|
||||
if (regid == "ss"):
|
||||
f.write(" TCGv_i64 %s%sV = tcg_temp_local_new_i64();\n" % \
|
||||
(regtype, regid))
|
||||
f.write(" const int %s = insn->regno[%d] + HEX_REG_SA0;\n" % \
|
||||
(regN, regno))
|
||||
elif (regid == "dd"):
|
||||
genptr_decl_pair_writeble(f, tag, regtype, regid, regno)
|
||||
elif (regid == "s"):
|
||||
f.write(" TCGv %s%sV = tcg_temp_local_new();\n" % \
|
||||
(regtype, regid))
|
||||
f.write(" const int %s%sN = insn->regno[%d] + HEX_REG_SA0;\n" % \
|
||||
(regtype, regid, regno))
|
||||
elif (regid == "d"):
|
||||
genptr_decl_writeble(f, tag, regtype, regid, regno)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
elif (regtype == "M"):
|
||||
if (regid == "u"):
|
||||
f.write(" const int %s%sN = insn->regno[%d];\n"% \
|
||||
(regtype, regid, regno))
|
||||
f.write(" TCGv %s%sV = hex_gpr[%s%sN + HEX_REG_M0];\n" % \
|
||||
(regtype, regid, regtype, regid))
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
|
||||
def genptr_decl_new(f,regtype,regid,regno):
|
||||
if (regtype == "N"):
|
||||
if (regid in {"s", "t"}):
|
||||
f.write(" TCGv %s%sN = hex_new_value[insn->regno[%d]];\n" % \
|
||||
(regtype, regid, regno))
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
elif (regtype == "P"):
|
||||
if (regid in {"t", "u", "v"}):
|
||||
f.write(" TCGv %s%sN = hex_new_pred_value[insn->regno[%d]];\n" % \
|
||||
(regtype, regid, regno))
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
|
||||
def genptr_decl_opn(f, tag, regtype, regid, toss, numregs, i):
|
||||
if (hex_common.is_pair(regid)):
|
||||
genptr_decl(f, tag, regtype, regid, i)
|
||||
elif (hex_common.is_single(regid)):
|
||||
if hex_common.is_old_val(regtype, regid, tag):
|
||||
genptr_decl(f,tag, regtype, regid, i)
|
||||
elif hex_common.is_new_val(regtype, regid, tag):
|
||||
genptr_decl_new(f,regtype,regid,i)
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
|
||||
def genptr_decl_imm(f,immlett):
|
||||
if (immlett.isupper()):
|
||||
i = 1
|
||||
else:
|
||||
i = 0
|
||||
f.write(" int %s = insn->immed[%d];\n" % \
|
||||
(hex_common.imm_name(immlett), i))
|
||||
|
||||
def genptr_free(f,regtype,regid,regno):
|
||||
if (regtype == "R"):
|
||||
if (regid in {"dd", "ss", "tt", "xx", "yy"}):
|
||||
f.write(" tcg_temp_free_i64(%s%sV);\n" % (regtype, regid))
|
||||
elif (regid in {"d", "e", "x", "y"}):
|
||||
f.write(" tcg_temp_free(%s%sV);\n" % (regtype, regid))
|
||||
elif (regid not in {"s", "t", "u", "v"}):
|
||||
print("Bad register parse: ",regtype,regid)
|
||||
elif (regtype == "P"):
|
||||
if (regid in {"d", "e", "x"}):
|
||||
f.write(" tcg_temp_free(%s%sV);\n" % (regtype, regid))
|
||||
elif (regid not in {"s", "t", "u", "v"}):
|
||||
print("Bad register parse: ",regtype,regid)
|
||||
elif (regtype == "C"):
|
||||
if (regid in {"dd", "ss"}):
|
||||
f.write(" tcg_temp_free_i64(%s%sV);\n" % (regtype, regid))
|
||||
elif (regid in {"d", "s"}):
|
||||
f.write(" tcg_temp_free(%s%sV);\n" % (regtype, regid))
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid)
|
||||
elif (regtype == "M"):
|
||||
if (regid != "u"):
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
|
||||
def genptr_free_new(f,regtype,regid,regno):
|
||||
if (regtype == "N"):
|
||||
if (regid not in {"s", "t"}):
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
elif (regtype == "P"):
|
||||
if (regid not in {"t", "u", "v"}):
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
|
||||
def genptr_free_opn(f,regtype,regid,i,tag):
|
||||
if (hex_common.is_pair(regid)):
|
||||
genptr_free(f,regtype,regid,i)
|
||||
elif (hex_common.is_single(regid)):
|
||||
if hex_common.is_old_val(regtype, regid, tag):
|
||||
genptr_free(f,regtype,regid,i)
|
||||
elif hex_common.is_new_val(regtype, regid, tag):
|
||||
genptr_free_new(f,regtype,regid,i)
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
|
||||
def genptr_src_read(f,regtype,regid):
|
||||
if (regtype == "R"):
|
||||
if (regid in {"ss", "tt", "xx", "yy"}):
|
||||
f.write(" tcg_gen_concat_i32_i64(%s%sV, hex_gpr[%s%sN],\n" % \
|
||||
(regtype, regid, regtype, regid))
|
||||
f.write(" hex_gpr[%s%sN + 1]);\n" % \
|
||||
(regtype, regid))
|
||||
elif (regid in {"x", "y"}):
|
||||
f.write(" tcg_gen_mov_tl(%s%sV, hex_gpr[%s%sN]);\n" % \
|
||||
(regtype,regid,regtype,regid))
|
||||
elif (regid not in {"s", "t", "u", "v"}):
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
elif (regtype == "P"):
|
||||
if (regid == "x"):
|
||||
f.write(" tcg_gen_mov_tl(%s%sV, hex_pred[%s%sN]);\n" % \
|
||||
(regtype, regid, regtype, regid))
|
||||
elif (regid not in {"s", "t", "u", "v"}):
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
elif (regtype == "C"):
|
||||
if (regid == "ss"):
|
||||
f.write(" gen_read_ctrl_reg_pair(ctx, %s%sN, %s%sV);\n" % \
|
||||
(regtype, regid, regtype, regid))
|
||||
elif (regid == "s"):
|
||||
f.write(" gen_read_ctrl_reg(ctx, %s%sN, %s%sV);\n" % \
|
||||
(regtype, regid, regtype, regid))
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
elif (regtype == "M"):
|
||||
if (regid != "u"):
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
|
||||
def genptr_src_read_new(f,regtype,regid):
|
||||
if (regtype == "N"):
|
||||
if (regid not in {"s", "t"}):
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
elif (regtype == "P"):
|
||||
if (regid not in {"t", "u", "v"}):
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
|
||||
def genptr_src_read_opn(f,regtype,regid,tag):
|
||||
if (hex_common.is_pair(regid)):
|
||||
genptr_src_read(f,regtype,regid)
|
||||
elif (hex_common.is_single(regid)):
|
||||
if hex_common.is_old_val(regtype, regid, tag):
|
||||
genptr_src_read(f,regtype,regid)
|
||||
elif hex_common.is_new_val(regtype, regid, tag):
|
||||
genptr_src_read_new(f,regtype,regid)
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
|
||||
def gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i):
|
||||
if (i > 0): f.write(", ")
|
||||
if (hex_common.is_pair(regid)):
|
||||
f.write("%s%sV" % (regtype,regid))
|
||||
elif (hex_common.is_single(regid)):
|
||||
if hex_common.is_old_val(regtype, regid, tag):
|
||||
f.write("%s%sV" % (regtype,regid))
|
||||
elif hex_common.is_new_val(regtype, regid, tag):
|
||||
f.write("%s%sN" % (regtype,regid))
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
|
||||
def gen_helper_decl_imm(f,immlett):
|
||||
f.write(" TCGv tcgv_%s = tcg_const_tl(%s);\n" % \
|
||||
(hex_common.imm_name(immlett), hex_common.imm_name(immlett)))
|
||||
|
||||
def gen_helper_call_imm(f,immlett):
|
||||
f.write(", tcgv_%s" % hex_common.imm_name(immlett))
|
||||
|
||||
def gen_helper_free_imm(f,immlett):
|
||||
f.write(" tcg_temp_free(tcgv_%s);\n" % hex_common.imm_name(immlett))
|
||||
|
||||
def genptr_dst_write_pair(f, tag, regtype, regid):
|
||||
if ('A_CONDEXEC' in hex_common.attribdict[tag]):
|
||||
f.write(" gen_log_predicated_reg_write_pair(%s%sN, %s%sV, insn->slot);\n" % \
|
||||
(regtype, regid, regtype, regid))
|
||||
else:
|
||||
f.write(" gen_log_reg_write_pair(%s%sN, %s%sV);\n" % \
|
||||
(regtype, regid, regtype, regid))
|
||||
f.write(" ctx_log_reg_write_pair(ctx, %s%sN);\n" % \
|
||||
(regtype, regid))
|
||||
|
||||
def genptr_dst_write(f, tag, regtype, regid):
|
||||
if (regtype == "R"):
|
||||
if (regid in {"dd", "xx", "yy"}):
|
||||
genptr_dst_write_pair(f, tag, regtype, regid)
|
||||
elif (regid in {"d", "e", "x", "y"}):
|
||||
if ('A_CONDEXEC' in hex_common.attribdict[tag]):
|
||||
f.write(" gen_log_predicated_reg_write(%s%sN, %s%sV,\n" % \
|
||||
(regtype, regid, regtype, regid))
|
||||
f.write(" insn->slot);\n")
|
||||
else:
|
||||
f.write(" gen_log_reg_write(%s%sN, %s%sV);\n" % \
|
||||
(regtype, regid, regtype, regid))
|
||||
f.write(" ctx_log_reg_write(ctx, %s%sN);\n" % \
|
||||
(regtype, regid))
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
elif (regtype == "P"):
|
||||
if (regid in {"d", "e", "x"}):
|
||||
f.write(" gen_log_pred_write(%s%sN, %s%sV);\n" % \
|
||||
(regtype, regid, regtype, regid))
|
||||
f.write(" ctx_log_pred_write(ctx, %s%sN);\n" % \
|
||||
(regtype, regid))
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
elif (regtype == "C"):
|
||||
if (regid == "dd"):
|
||||
f.write(" gen_write_ctrl_reg_pair(ctx, %s%sN, %s%sV);\n" % \
|
||||
(regtype, regid, regtype, regid))
|
||||
elif (regid == "d"):
|
||||
f.write(" gen_write_ctrl_reg(ctx, %s%sN, %s%sV);\n" % \
|
||||
(regtype, regid, regtype, regid))
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
|
||||
def genptr_dst_write_opn(f,regtype, regid, tag):
|
||||
if (hex_common.is_pair(regid)):
|
||||
genptr_dst_write(f, tag, regtype, regid)
|
||||
elif (hex_common.is_single(regid)):
|
||||
genptr_dst_write(f, tag, regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ",regtype,regid,toss,numregs)
|
||||
|
||||
##
|
||||
## Generate the TCG code to call the helper
|
||||
## For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
|
||||
## We produce:
|
||||
## static void generate_A2_add()
|
||||
## CPUHexagonState *env
|
||||
## DisasContext *ctx,
|
||||
## Insn *insn,
|
||||
## Packet *pkt)
|
||||
## {
|
||||
## TCGv RdV = tcg_temp_local_new();
|
||||
## const int RdN = insn->regno[0];
|
||||
## TCGv RsV = hex_gpr[insn->regno[1]];
|
||||
## TCGv RtV = hex_gpr[insn->regno[2]];
|
||||
## <GEN>
|
||||
## gen_log_reg_write(RdN, RdV);
|
||||
## ctx_log_reg_write(ctx, RdN);
|
||||
## tcg_temp_free(RdV);
|
||||
## }
|
||||
##
|
||||
## where <GEN> depends on hex_common.skip_qemu_helper(tag)
|
||||
## if hex_common.skip_qemu_helper(tag) is True
|
||||
## <GEN> is fGEN_TCG_A2_add({ RdV=RsV+RtV;});
|
||||
## if hex_common.skip_qemu_helper(tag) is False
|
||||
## <GEN> is gen_helper_A2_add(RdV, cpu_env, RsV, RtV);
|
||||
##
|
||||
def gen_tcg_func(f, tag, regs, imms):
|
||||
f.write("static void generate_%s(\n" %tag)
|
||||
f.write(" CPUHexagonState *env,\n")
|
||||
f.write(" DisasContext *ctx,\n")
|
||||
f.write(" Insn *insn,\n")
|
||||
f.write(" Packet *pkt)\n")
|
||||
f.write('{\n')
|
||||
if hex_common.need_ea(tag): gen_decl_ea_tcg(f, tag)
|
||||
i=0
|
||||
## Declare all the operands (regs and immediates)
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
genptr_decl_opn(f, tag, regtype, regid, toss, numregs, i)
|
||||
i += 1
|
||||
for immlett,bits,immshift in imms:
|
||||
genptr_decl_imm(f,immlett)
|
||||
|
||||
if 'A_PRIV' in hex_common.attribdict[tag]:
|
||||
f.write(' fCHECKFORPRIV();\n')
|
||||
if 'A_GUEST' in hex_common.attribdict[tag]:
|
||||
f.write(' fCHECKFORGUEST();\n')
|
||||
|
||||
## Read all the inputs
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
if (hex_common.is_read(regid)):
|
||||
genptr_src_read_opn(f,regtype,regid,tag)
|
||||
|
||||
if ( hex_common.skip_qemu_helper(tag) ):
|
||||
f.write(" fGEN_TCG_%s(%s);\n" % (tag, hex_common.semdict[tag]))
|
||||
else:
|
||||
## Generate the call to the helper
|
||||
for immlett,bits,immshift in imms:
|
||||
gen_helper_decl_imm(f,immlett)
|
||||
if hex_common.need_part1(tag):
|
||||
f.write(" TCGv part1 = tcg_const_tl(insn->part1);\n")
|
||||
if hex_common.need_slot(tag):
|
||||
f.write(" TCGv slot = tcg_const_tl(insn->slot);\n")
|
||||
f.write(" gen_helper_%s(" % (tag))
|
||||
i=0
|
||||
## If there is a scalar result, it is the return type
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
if (hex_common.is_written(regid)):
|
||||
gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i)
|
||||
i += 1
|
||||
if (i > 0): f.write(", ")
|
||||
f.write("cpu_env")
|
||||
i=1
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
if (hex_common.is_read(regid)):
|
||||
gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i)
|
||||
i += 1
|
||||
for immlett,bits,immshift in imms:
|
||||
gen_helper_call_imm(f,immlett)
|
||||
|
||||
if hex_common.need_slot(tag): f.write(", slot")
|
||||
if hex_common.need_part1(tag): f.write(", part1" )
|
||||
f.write(");\n")
|
||||
if hex_common.need_slot(tag):
|
||||
f.write(" tcg_temp_free(slot);\n")
|
||||
if hex_common.need_part1(tag):
|
||||
f.write(" tcg_temp_free(part1);\n")
|
||||
for immlett,bits,immshift in imms:
|
||||
gen_helper_free_imm(f,immlett)
|
||||
|
||||
## Write all the outputs
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
if (hex_common.is_written(regid)):
|
||||
genptr_dst_write_opn(f,regtype, regid, tag)
|
||||
|
||||
## Free all the operands (regs and immediates)
|
||||
if hex_common.need_ea(tag): gen_free_ea_tcg(f)
|
||||
for regtype,regid,toss,numregs in regs:
|
||||
genptr_free_opn(f,regtype,regid,i,tag)
|
||||
i += 1
|
||||
|
||||
f.write("}\n\n")
|
||||
|
||||
def gen_def_tcg_func(f, tag, tagregs, tagimms):
|
||||
regs = tagregs[tag]
|
||||
imms = tagimms[tag]
|
||||
|
||||
gen_tcg_func(f, tag, regs, imms)
|
||||
|
||||
def main():
|
||||
hex_common.read_semantics_file(sys.argv[1])
|
||||
hex_common.read_attribs_file(sys.argv[2])
|
||||
hex_common.read_overrides_file(sys.argv[3])
|
||||
hex_common.calculate_attribs()
|
||||
tagregs = hex_common.get_tagregs()
|
||||
tagimms = hex_common.get_tagimms()
|
||||
|
||||
with open(sys.argv[4], 'w') as f:
|
||||
f.write("#ifndef HEXAGON_TCG_FUNCS_H\n")
|
||||
f.write("#define HEXAGON_TCG_FUNCS_H\n\n")
|
||||
|
||||
for tag in hex_common.tags:
|
||||
## Skip the priv instructions
|
||||
if ( "A_PRIV" in hex_common.attribdict[tag] ) :
|
||||
continue
|
||||
## Skip the guest instructions
|
||||
if ( "A_GUEST" in hex_common.attribdict[tag] ) :
|
||||
continue
|
||||
## Skip the diag instructions
|
||||
if ( tag == "Y6_diag" ) :
|
||||
continue
|
||||
if ( tag == "Y6_diag0" ) :
|
||||
continue
|
||||
if ( tag == "Y6_diag1" ) :
|
||||
continue
|
||||
|
||||
gen_def_tcg_func(f, tag, tagregs, tagimms)
|
||||
|
||||
f.write("#endif /* HEXAGON_TCG_FUNCS_H */\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
331
target/hexagon/genptr.c
Normal file
331
target/hexagon/genptr.c
Normal file
@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define QEMU_GENERATE
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
#include "internal.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "insn.h"
|
||||
#include "opcodes.h"
|
||||
#include "translate.h"
|
||||
#include "macros.h"
|
||||
#include "gen_tcg.h"
|
||||
|
||||
static inline TCGv gen_read_preg(TCGv pred, uint8_t num)
|
||||
{
|
||||
tcg_gen_mov_tl(pred, hex_pred[num]);
|
||||
return pred;
|
||||
}
|
||||
|
||||
static inline void gen_log_predicated_reg_write(int rnum, TCGv val, int slot)
|
||||
{
|
||||
TCGv one = tcg_const_tl(1);
|
||||
TCGv zero = tcg_const_tl(0);
|
||||
TCGv slot_mask = tcg_temp_new();
|
||||
|
||||
tcg_gen_andi_tl(slot_mask, hex_slot_cancelled, 1 << slot);
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum], slot_mask, zero,
|
||||
val, hex_new_value[rnum]);
|
||||
#if HEX_DEBUG
|
||||
/* Do this so HELPER(debug_commit_end) will know */
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, hex_reg_written[rnum], slot_mask, zero,
|
||||
one, hex_reg_written[rnum]);
|
||||
#endif
|
||||
|
||||
tcg_temp_free(one);
|
||||
tcg_temp_free(zero);
|
||||
tcg_temp_free(slot_mask);
|
||||
}
|
||||
|
||||
static inline void gen_log_reg_write(int rnum, TCGv val)
|
||||
{
|
||||
tcg_gen_mov_tl(hex_new_value[rnum], val);
|
||||
#if HEX_DEBUG
|
||||
/* Do this so HELPER(debug_commit_end) will know */
|
||||
tcg_gen_movi_tl(hex_reg_written[rnum], 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gen_log_predicated_reg_write_pair(int rnum, TCGv_i64 val, int slot)
|
||||
{
|
||||
TCGv val32 = tcg_temp_new();
|
||||
TCGv one = tcg_const_tl(1);
|
||||
TCGv zero = tcg_const_tl(0);
|
||||
TCGv slot_mask = tcg_temp_new();
|
||||
|
||||
tcg_gen_andi_tl(slot_mask, hex_slot_cancelled, 1 << slot);
|
||||
/* Low word */
|
||||
tcg_gen_extrl_i64_i32(val32, val);
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum], slot_mask, zero,
|
||||
val32, hex_new_value[rnum]);
|
||||
#if HEX_DEBUG
|
||||
/* Do this so HELPER(debug_commit_end) will know */
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, hex_reg_written[rnum],
|
||||
slot_mask, zero,
|
||||
one, hex_reg_written[rnum]);
|
||||
#endif
|
||||
|
||||
/* High word */
|
||||
tcg_gen_extrh_i64_i32(val32, val);
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, hex_new_value[rnum + 1],
|
||||
slot_mask, zero,
|
||||
val32, hex_new_value[rnum + 1]);
|
||||
#if HEX_DEBUG
|
||||
/* Do this so HELPER(debug_commit_end) will know */
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, hex_reg_written[rnum + 1],
|
||||
slot_mask, zero,
|
||||
one, hex_reg_written[rnum + 1]);
|
||||
#endif
|
||||
|
||||
tcg_temp_free(val32);
|
||||
tcg_temp_free(one);
|
||||
tcg_temp_free(zero);
|
||||
tcg_temp_free(slot_mask);
|
||||
}
|
||||
|
||||
static void gen_log_reg_write_pair(int rnum, TCGv_i64 val)
|
||||
{
|
||||
/* Low word */
|
||||
tcg_gen_extrl_i64_i32(hex_new_value[rnum], val);
|
||||
#if HEX_DEBUG
|
||||
/* Do this so HELPER(debug_commit_end) will know */
|
||||
tcg_gen_movi_tl(hex_reg_written[rnum], 1);
|
||||
#endif
|
||||
|
||||
/* High word */
|
||||
tcg_gen_extrh_i64_i32(hex_new_value[rnum + 1], val);
|
||||
#if HEX_DEBUG
|
||||
/* Do this so HELPER(debug_commit_end) will know */
|
||||
tcg_gen_movi_tl(hex_reg_written[rnum + 1], 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void gen_log_pred_write(int pnum, TCGv val)
|
||||
{
|
||||
TCGv zero = tcg_const_tl(0);
|
||||
TCGv base_val = tcg_temp_new();
|
||||
TCGv and_val = tcg_temp_new();
|
||||
TCGv pred_written = tcg_temp_new();
|
||||
|
||||
/* Multiple writes to the same preg are and'ed together */
|
||||
tcg_gen_andi_tl(base_val, val, 0xff);
|
||||
tcg_gen_and_tl(and_val, base_val, hex_new_pred_value[pnum]);
|
||||
tcg_gen_andi_tl(pred_written, hex_pred_written, 1 << pnum);
|
||||
tcg_gen_movcond_tl(TCG_COND_NE, hex_new_pred_value[pnum],
|
||||
pred_written, zero,
|
||||
and_val, base_val);
|
||||
tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pnum);
|
||||
|
||||
tcg_temp_free(zero);
|
||||
tcg_temp_free(base_val);
|
||||
tcg_temp_free(and_val);
|
||||
tcg_temp_free(pred_written);
|
||||
}
|
||||
|
||||
static inline void gen_read_p3_0(TCGv control_reg)
|
||||
{
|
||||
tcg_gen_movi_tl(control_reg, 0);
|
||||
for (int i = 0; i < NUM_PREGS; i++) {
|
||||
tcg_gen_deposit_tl(control_reg, control_reg, hex_pred[i], i * 8, 8);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Certain control registers require special handling on read
|
||||
* HEX_REG_P3_0 aliased to the predicate registers
|
||||
* -> concat the 4 predicate registers together
|
||||
* HEX_REG_PC actual value stored in DisasContext
|
||||
* -> assign from ctx->base.pc_next
|
||||
* HEX_REG_QEMU_*_CNT changes in current TB in DisasContext
|
||||
* -> add current TB changes to existing reg value
|
||||
*/
|
||||
static inline void gen_read_ctrl_reg(DisasContext *ctx, const int reg_num,
|
||||
TCGv dest)
|
||||
{
|
||||
if (reg_num == HEX_REG_P3_0) {
|
||||
gen_read_p3_0(dest);
|
||||
} else if (reg_num == HEX_REG_PC) {
|
||||
tcg_gen_movi_tl(dest, ctx->base.pc_next);
|
||||
} else if (reg_num == HEX_REG_QEMU_PKT_CNT) {
|
||||
tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_PKT_CNT],
|
||||
ctx->num_packets);
|
||||
} else if (reg_num == HEX_REG_QEMU_INSN_CNT) {
|
||||
tcg_gen_addi_tl(dest, hex_gpr[HEX_REG_QEMU_INSN_CNT],
|
||||
ctx->num_insns);
|
||||
} else {
|
||||
tcg_gen_mov_tl(dest, hex_gpr[reg_num]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gen_read_ctrl_reg_pair(DisasContext *ctx, const int reg_num,
|
||||
TCGv_i64 dest)
|
||||
{
|
||||
if (reg_num == HEX_REG_P3_0) {
|
||||
TCGv p3_0 = tcg_temp_new();
|
||||
gen_read_p3_0(p3_0);
|
||||
tcg_gen_concat_i32_i64(dest, p3_0, hex_gpr[reg_num + 1]);
|
||||
tcg_temp_free(p3_0);
|
||||
} else if (reg_num == HEX_REG_PC - 1) {
|
||||
TCGv pc = tcg_const_tl(ctx->base.pc_next);
|
||||
tcg_gen_concat_i32_i64(dest, hex_gpr[reg_num], pc);
|
||||
tcg_temp_free(pc);
|
||||
} else if (reg_num == HEX_REG_QEMU_PKT_CNT) {
|
||||
TCGv pkt_cnt = tcg_temp_new();
|
||||
TCGv insn_cnt = tcg_temp_new();
|
||||
tcg_gen_addi_tl(pkt_cnt, hex_gpr[HEX_REG_QEMU_PKT_CNT],
|
||||
ctx->num_packets);
|
||||
tcg_gen_addi_tl(insn_cnt, hex_gpr[HEX_REG_QEMU_INSN_CNT],
|
||||
ctx->num_insns);
|
||||
tcg_gen_concat_i32_i64(dest, pkt_cnt, insn_cnt);
|
||||
tcg_temp_free(pkt_cnt);
|
||||
tcg_temp_free(insn_cnt);
|
||||
} else {
|
||||
tcg_gen_concat_i32_i64(dest,
|
||||
hex_gpr[reg_num],
|
||||
hex_gpr[reg_num + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gen_write_p3_0(TCGv control_reg)
|
||||
{
|
||||
for (int i = 0; i < NUM_PREGS; i++) {
|
||||
tcg_gen_extract_tl(hex_pred[i], control_reg, i * 8, 8);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Certain control registers require special handling on write
|
||||
* HEX_REG_P3_0 aliased to the predicate registers
|
||||
* -> break the value across 4 predicate registers
|
||||
* HEX_REG_QEMU_*_CNT changes in current TB in DisasContext
|
||||
* -> clear the changes
|
||||
*/
|
||||
static inline void gen_write_ctrl_reg(DisasContext *ctx, int reg_num,
|
||||
TCGv val)
|
||||
{
|
||||
if (reg_num == HEX_REG_P3_0) {
|
||||
gen_write_p3_0(val);
|
||||
} else {
|
||||
gen_log_reg_write(reg_num, val);
|
||||
ctx_log_reg_write(ctx, reg_num);
|
||||
if (reg_num == HEX_REG_QEMU_PKT_CNT) {
|
||||
ctx->num_packets = 0;
|
||||
}
|
||||
if (reg_num == HEX_REG_QEMU_INSN_CNT) {
|
||||
ctx->num_insns = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gen_write_ctrl_reg_pair(DisasContext *ctx, int reg_num,
|
||||
TCGv_i64 val)
|
||||
{
|
||||
if (reg_num == HEX_REG_P3_0) {
|
||||
TCGv val32 = tcg_temp_new();
|
||||
tcg_gen_extrl_i64_i32(val32, val);
|
||||
gen_write_p3_0(val32);
|
||||
tcg_gen_extrh_i64_i32(val32, val);
|
||||
gen_log_reg_write(reg_num + 1, val32);
|
||||
tcg_temp_free(val32);
|
||||
ctx_log_reg_write(ctx, reg_num + 1);
|
||||
} else {
|
||||
gen_log_reg_write_pair(reg_num, val);
|
||||
ctx_log_reg_write_pair(ctx, reg_num);
|
||||
if (reg_num == HEX_REG_QEMU_PKT_CNT) {
|
||||
ctx->num_packets = 0;
|
||||
ctx->num_insns = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void gen_load_locked4u(TCGv dest, TCGv vaddr, int mem_index)
|
||||
{
|
||||
tcg_gen_qemu_ld32u(dest, vaddr, mem_index);
|
||||
tcg_gen_mov_tl(hex_llsc_addr, vaddr);
|
||||
tcg_gen_mov_tl(hex_llsc_val, dest);
|
||||
}
|
||||
|
||||
static inline void gen_load_locked8u(TCGv_i64 dest, TCGv vaddr, int mem_index)
|
||||
{
|
||||
tcg_gen_qemu_ld64(dest, vaddr, mem_index);
|
||||
tcg_gen_mov_tl(hex_llsc_addr, vaddr);
|
||||
tcg_gen_mov_i64(hex_llsc_val_i64, dest);
|
||||
}
|
||||
|
||||
static inline void gen_store_conditional4(CPUHexagonState *env,
|
||||
DisasContext *ctx, int prednum,
|
||||
TCGv pred, TCGv vaddr, TCGv src)
|
||||
{
|
||||
TCGLabel *fail = gen_new_label();
|
||||
TCGLabel *done = gen_new_label();
|
||||
TCGv one, zero, tmp;
|
||||
|
||||
tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail);
|
||||
|
||||
one = tcg_const_tl(0xff);
|
||||
zero = tcg_const_tl(0);
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_atomic_cmpxchg_tl(tmp, hex_llsc_addr, hex_llsc_val, src,
|
||||
ctx->mem_idx, MO_32);
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, hex_pred[prednum], tmp, hex_llsc_val,
|
||||
one, zero);
|
||||
tcg_temp_free(one);
|
||||
tcg_temp_free(zero);
|
||||
tcg_temp_free(tmp);
|
||||
tcg_gen_br(done);
|
||||
|
||||
gen_set_label(fail);
|
||||
tcg_gen_movi_tl(pred, 0);
|
||||
|
||||
gen_set_label(done);
|
||||
tcg_gen_movi_tl(hex_llsc_addr, ~0);
|
||||
}
|
||||
|
||||
static inline void gen_store_conditional8(CPUHexagonState *env,
|
||||
DisasContext *ctx, int prednum,
|
||||
TCGv pred, TCGv vaddr, TCGv_i64 src)
|
||||
{
|
||||
TCGLabel *fail = gen_new_label();
|
||||
TCGLabel *done = gen_new_label();
|
||||
TCGv_i64 one, zero, tmp;
|
||||
|
||||
tcg_gen_brcond_tl(TCG_COND_NE, vaddr, hex_llsc_addr, fail);
|
||||
|
||||
one = tcg_const_i64(0xff);
|
||||
zero = tcg_const_i64(0);
|
||||
tmp = tcg_temp_new_i64();
|
||||
tcg_gen_atomic_cmpxchg_i64(tmp, hex_llsc_addr, hex_llsc_val_i64, src,
|
||||
ctx->mem_idx, MO_64);
|
||||
tcg_gen_movcond_i64(TCG_COND_EQ, tmp, tmp, hex_llsc_val_i64,
|
||||
one, zero);
|
||||
tcg_gen_extrl_i64_i32(hex_pred[prednum], tmp);
|
||||
tcg_temp_free_i64(one);
|
||||
tcg_temp_free_i64(zero);
|
||||
tcg_temp_free_i64(tmp);
|
||||
tcg_gen_br(done);
|
||||
|
||||
gen_set_label(fail);
|
||||
tcg_gen_movi_tl(pred, 0);
|
||||
|
||||
gen_set_label(done);
|
||||
tcg_gen_movi_tl(hex_llsc_addr, ~0);
|
||||
}
|
||||
|
||||
#include "tcg_funcs_generated.c.inc"
|
||||
#include "tcg_func_table_generated.c.inc"
|
25
target/hexagon/genptr.h
Normal file
25
target/hexagon/genptr.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_GENPTR_H
|
||||
#define HEXAGON_GENPTR_H
|
||||
|
||||
#include "insn.h"
|
||||
|
||||
extern const SemanticInsn opcode_genptr[];
|
||||
|
||||
#endif
|
88
target/hexagon/helper.h
Normal file
88
target/hexagon/helper.h
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "internal.h"
|
||||
#include "helper_protos_generated.h.inc"
|
||||
|
||||
DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_RETURN, noreturn, env, i32)
|
||||
#if HEX_DEBUG
|
||||
DEF_HELPER_1(debug_start_packet, void, env)
|
||||
DEF_HELPER_FLAGS_3(debug_check_store_width, TCG_CALL_NO_WG, void, env, int, int)
|
||||
DEF_HELPER_FLAGS_3(debug_commit_end, TCG_CALL_NO_WG, void, env, int, int)
|
||||
#endif
|
||||
DEF_HELPER_2(commit_store, void, env, int)
|
||||
DEF_HELPER_FLAGS_4(fcircadd, TCG_CALL_NO_RWG_SE, s32, s32, s32, s32, s32)
|
||||
|
||||
/* Floating point */
|
||||
DEF_HELPER_2(conv_sf2df, f64, env, f32)
|
||||
DEF_HELPER_2(conv_df2sf, f32, env, f64)
|
||||
DEF_HELPER_2(conv_uw2sf, f32, env, s32)
|
||||
DEF_HELPER_2(conv_uw2df, f64, env, s32)
|
||||
DEF_HELPER_2(conv_w2sf, f32, env, s32)
|
||||
DEF_HELPER_2(conv_w2df, f64, env, s32)
|
||||
DEF_HELPER_2(conv_ud2sf, f32, env, s64)
|
||||
DEF_HELPER_2(conv_ud2df, f64, env, s64)
|
||||
DEF_HELPER_2(conv_d2sf, f32, env, s64)
|
||||
DEF_HELPER_2(conv_d2df, f64, env, s64)
|
||||
DEF_HELPER_2(conv_sf2uw, s32, env, f32)
|
||||
DEF_HELPER_2(conv_sf2w, s32, env, f32)
|
||||
DEF_HELPER_2(conv_sf2ud, s64, env, f32)
|
||||
DEF_HELPER_2(conv_sf2d, s64, env, f32)
|
||||
DEF_HELPER_2(conv_df2uw, s32, env, f64)
|
||||
DEF_HELPER_2(conv_df2w, s32, env, f64)
|
||||
DEF_HELPER_2(conv_df2ud, s64, env, f64)
|
||||
DEF_HELPER_2(conv_df2d, s64, env, f64)
|
||||
DEF_HELPER_2(conv_sf2uw_chop, s32, env, f32)
|
||||
DEF_HELPER_2(conv_sf2w_chop, s32, env, f32)
|
||||
DEF_HELPER_2(conv_sf2ud_chop, s64, env, f32)
|
||||
DEF_HELPER_2(conv_sf2d_chop, s64, env, f32)
|
||||
DEF_HELPER_2(conv_df2uw_chop, s32, env, f64)
|
||||
DEF_HELPER_2(conv_df2w_chop, s32, env, f64)
|
||||
DEF_HELPER_2(conv_df2ud_chop, s64, env, f64)
|
||||
DEF_HELPER_2(conv_df2d_chop, s64, env, f64)
|
||||
DEF_HELPER_3(sfadd, f32, env, f32, f32)
|
||||
DEF_HELPER_3(sfsub, f32, env, f32, f32)
|
||||
DEF_HELPER_3(sfcmpeq, s32, env, f32, f32)
|
||||
DEF_HELPER_3(sfcmpgt, s32, env, f32, f32)
|
||||
DEF_HELPER_3(sfcmpge, s32, env, f32, f32)
|
||||
DEF_HELPER_3(sfcmpuo, s32, env, f32, f32)
|
||||
DEF_HELPER_3(sfmax, f32, env, f32, f32)
|
||||
DEF_HELPER_3(sfmin, f32, env, f32, f32)
|
||||
DEF_HELPER_3(sfclass, s32, env, f32, s32)
|
||||
DEF_HELPER_3(sffixupn, f32, env, f32, f32)
|
||||
DEF_HELPER_3(sffixupd, f32, env, f32, f32)
|
||||
DEF_HELPER_2(sffixupr, f32, env, f32)
|
||||
|
||||
DEF_HELPER_3(dfadd, f64, env, f64, f64)
|
||||
DEF_HELPER_3(dfsub, f64, env, f64, f64)
|
||||
DEF_HELPER_3(dfmax, f64, env, f64, f64)
|
||||
DEF_HELPER_3(dfmin, f64, env, f64, f64)
|
||||
DEF_HELPER_3(dfcmpeq, s32, env, f64, f64)
|
||||
DEF_HELPER_3(dfcmpgt, s32, env, f64, f64)
|
||||
DEF_HELPER_3(dfcmpge, s32, env, f64, f64)
|
||||
DEF_HELPER_3(dfcmpuo, s32, env, f64, f64)
|
||||
DEF_HELPER_3(dfclass, s32, env, f64, s32)
|
||||
|
||||
DEF_HELPER_3(sfmpy, f32, env, f32, f32)
|
||||
DEF_HELPER_4(sffma, f32, env, f32, f32, f32)
|
||||
DEF_HELPER_5(sffma_sc, f32, env, f32, f32, f32, f32)
|
||||
DEF_HELPER_4(sffms, f32, env, f32, f32, f32)
|
||||
DEF_HELPER_4(sffma_lib, f32, env, f32, f32, f32)
|
||||
DEF_HELPER_4(sffms_lib, f32, env, f32, f32, f32)
|
||||
|
||||
DEF_HELPER_3(dfmpyfix, f64, env, f64, f64)
|
||||
DEF_HELPER_4(dfmpyhh, f64, env, f64, f64, f64)
|
38
target/hexagon/hex_arch_types.h
Normal file
38
target/hexagon/hex_arch_types.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_ARCH_TYPES_H
|
||||
#define HEXAGON_ARCH_TYPES_H
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/int128.h"
|
||||
|
||||
/*
|
||||
* These types are used by the code imported from the Hexagon
|
||||
* architecture library.
|
||||
*/
|
||||
typedef uint8_t size1u_t;
|
||||
typedef int8_t size1s_t;
|
||||
typedef uint16_t size2u_t;
|
||||
typedef int16_t size2s_t;
|
||||
typedef uint32_t size4u_t;
|
||||
typedef int32_t size4s_t;
|
||||
typedef uint64_t size8u_t;
|
||||
typedef int64_t size8s_t;
|
||||
typedef Int128 size16s_t;
|
||||
|
||||
#endif
|
234
target/hexagon/hex_common.py
Executable file
234
target/hexagon/hex_common.py
Executable file
@ -0,0 +1,234 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
|
||||
behdict = {} # tag ->behavior
|
||||
semdict = {} # tag -> semantics
|
||||
attribdict = {} # tag -> attributes
|
||||
macros = {} # macro -> macro information...
|
||||
attribinfo = {} # Register information and misc
|
||||
tags = [] # list of all tags
|
||||
overrides = {} # tags with helper overrides
|
||||
|
||||
# We should do this as a hash for performance,
|
||||
# but to keep order let's keep it as a list.
|
||||
def uniquify(seq):
|
||||
seen = set()
|
||||
seen_add = seen.add
|
||||
return [x for x in seq if x not in seen and not seen_add(x)]
|
||||
|
||||
regre = re.compile(
|
||||
r"((?<!DUP)[MNORCPQXSGVZA])([stuvwxyzdefg]+)([.]?[LlHh]?)(\d+S?)")
|
||||
immre = re.compile(r"[#]([rRsSuUm])(\d+)(?:[:](\d+))?")
|
||||
reg_or_immre = \
|
||||
re.compile(r"(((?<!DUP)[MNRCOPQXSGVZA])([stuvwxyzdefg]+)" + \
|
||||
"([.]?[LlHh]?)(\d+S?))|([#]([rRsSuUm])(\d+)[:]?(\d+)?)")
|
||||
relimmre = re.compile(r"[#]([rR])(\d+)(?:[:](\d+))?")
|
||||
absimmre = re.compile(r"[#]([sSuUm])(\d+)(?:[:](\d+))?")
|
||||
|
||||
finished_macros = set()
|
||||
|
||||
def expand_macro_attribs(macro,allmac_re):
|
||||
if macro.key not in finished_macros:
|
||||
# Get a list of all things that might be macros
|
||||
l = allmac_re.findall(macro.beh)
|
||||
for submacro in l:
|
||||
if not submacro: continue
|
||||
if not macros[submacro]:
|
||||
raise Exception("Couldn't find macro: <%s>" % l)
|
||||
macro.attribs |= expand_macro_attribs(
|
||||
macros[submacro], allmac_re)
|
||||
finished_macros.add(macro.key)
|
||||
return macro.attribs
|
||||
|
||||
# When qemu needs an attribute that isn't in the imported files,
|
||||
# we'll add it here.
|
||||
def add_qemu_macro_attrib(name, attrib):
|
||||
macros[name].attribs.add(attrib)
|
||||
|
||||
immextre = re.compile(r'f(MUST_)?IMMEXT[(]([UuSsRr])')
|
||||
def calculate_attribs():
|
||||
add_qemu_macro_attrib('fREAD_PC', 'A_IMPLICIT_READS_PC')
|
||||
add_qemu_macro_attrib('fTRAP', 'A_IMPLICIT_READS_PC')
|
||||
add_qemu_macro_attrib('fWRITE_P0', 'A_WRITES_PRED_REG')
|
||||
add_qemu_macro_attrib('fWRITE_P1', 'A_WRITES_PRED_REG')
|
||||
add_qemu_macro_attrib('fWRITE_P2', 'A_WRITES_PRED_REG')
|
||||
add_qemu_macro_attrib('fWRITE_P3', 'A_WRITES_PRED_REG')
|
||||
|
||||
# Recurse down macros, find attributes from sub-macros
|
||||
macroValues = list(macros.values())
|
||||
allmacros_restr = "|".join(set([ m.re.pattern for m in macroValues ]))
|
||||
allmacros_re = re.compile(allmacros_restr)
|
||||
for macro in macroValues:
|
||||
expand_macro_attribs(macro,allmacros_re)
|
||||
# Append attributes to all instructions
|
||||
for tag in tags:
|
||||
for macname in allmacros_re.findall(semdict[tag]):
|
||||
if not macname: continue
|
||||
macro = macros[macname]
|
||||
attribdict[tag] |= set(macro.attribs)
|
||||
# Figure out which instructions write predicate registers
|
||||
tagregs = get_tagregs()
|
||||
for tag in tags:
|
||||
regs = tagregs[tag]
|
||||
for regtype, regid, toss, numregs in regs:
|
||||
if regtype == "P" and is_written(regid):
|
||||
attribdict[tag].add('A_WRITES_PRED_REG')
|
||||
|
||||
def SEMANTICS(tag, beh, sem):
|
||||
#print tag,beh,sem
|
||||
behdict[tag] = beh
|
||||
semdict[tag] = sem
|
||||
attribdict[tag] = set()
|
||||
tags.append(tag) # dicts have no order, this is for order
|
||||
|
||||
def ATTRIBUTES(tag, attribstring):
|
||||
attribstring = \
|
||||
attribstring.replace("ATTRIBS","").replace("(","").replace(")","")
|
||||
if not attribstring:
|
||||
return
|
||||
attribs = attribstring.split(",")
|
||||
for attrib in attribs:
|
||||
attribdict[tag].add(attrib.strip())
|
||||
|
||||
class Macro(object):
|
||||
__slots__ = ['key','name', 'beh', 'attribs', 're']
|
||||
def __init__(self, name, beh, attribs):
|
||||
self.key = name
|
||||
self.name = name
|
||||
self.beh = beh
|
||||
self.attribs = set(attribs)
|
||||
self.re = re.compile("\\b" + name + "\\b")
|
||||
|
||||
def MACROATTRIB(macname,beh,attribstring):
|
||||
attribstring = attribstring.replace("(","").replace(")","")
|
||||
if attribstring:
|
||||
attribs = attribstring.split(",")
|
||||
else:
|
||||
attribs = []
|
||||
macros[macname] = Macro(macname,beh,attribs)
|
||||
|
||||
def compute_tag_regs(tag):
|
||||
return uniquify(regre.findall(behdict[tag]))
|
||||
|
||||
def compute_tag_immediates(tag):
|
||||
return uniquify(immre.findall(behdict[tag]))
|
||||
|
||||
##
|
||||
## tagregs is the main data structure we'll use
|
||||
## tagregs[tag] will contain the registers used by an instruction
|
||||
## Within each entry, we'll use the regtype and regid fields
|
||||
## regtype can be one of the following
|
||||
## C control register
|
||||
## N new register value
|
||||
## P predicate register
|
||||
## R GPR register
|
||||
## M modifier register
|
||||
## regid can be one of the following
|
||||
## d, e destination register
|
||||
## dd destination register pair
|
||||
## s, t, u, v, w source register
|
||||
## ss, tt, uu, vv source register pair
|
||||
## x, y read-write register
|
||||
## xx, yy read-write register pair
|
||||
##
|
||||
def get_tagregs():
|
||||
return dict(zip(tags, list(map(compute_tag_regs, tags))))
|
||||
|
||||
def get_tagimms():
|
||||
return dict(zip(tags, list(map(compute_tag_immediates, tags))))
|
||||
|
||||
def is_pair(regid):
|
||||
return len(regid) == 2
|
||||
|
||||
def is_single(regid):
|
||||
return len(regid) == 1
|
||||
|
||||
def is_written(regid):
|
||||
return regid[0] in "dexy"
|
||||
|
||||
def is_writeonly(regid):
|
||||
return regid[0] in "de"
|
||||
|
||||
def is_read(regid):
|
||||
return regid[0] in "stuvwxy"
|
||||
|
||||
def is_readwrite(regid):
|
||||
return regid[0] in "xy"
|
||||
|
||||
def is_scalar_reg(regtype):
|
||||
return regtype in "RPC"
|
||||
|
||||
def is_old_val(regtype, regid, tag):
|
||||
return regtype+regid+'V' in semdict[tag]
|
||||
|
||||
def is_new_val(regtype, regid, tag):
|
||||
return regtype+regid+'N' in semdict[tag]
|
||||
|
||||
def need_slot(tag):
|
||||
if ('A_CONDEXEC' in attribdict[tag] or
|
||||
'A_STORE' in attribdict[tag] or
|
||||
'A_LOAD' in attribdict[tag]):
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def need_part1(tag):
|
||||
return re.compile(r"fPART1").search(semdict[tag])
|
||||
|
||||
def need_ea(tag):
|
||||
return re.compile(r"\bEA\b").search(semdict[tag])
|
||||
|
||||
def skip_qemu_helper(tag):
|
||||
return tag in overrides.keys()
|
||||
|
||||
def imm_name(immlett):
|
||||
return "%siV" % immlett
|
||||
|
||||
def read_semantics_file(name):
|
||||
eval_line = ""
|
||||
for line in open(name, 'rt').readlines():
|
||||
if not line.startswith("#"):
|
||||
eval_line += line
|
||||
if line.endswith("\\\n"):
|
||||
eval_line.rstrip("\\\n")
|
||||
else:
|
||||
eval(eval_line.strip())
|
||||
eval_line = ""
|
||||
|
||||
def read_attribs_file(name):
|
||||
attribre = re.compile(r'DEF_ATTRIB\(([A-Za-z0-9_]+), ([^,]*), ' +
|
||||
r'"([A-Za-z0-9_\.]*)", "([A-Za-z0-9_\.]*)"\)')
|
||||
for line in open(name, 'rt').readlines():
|
||||
if not attribre.match(line):
|
||||
continue
|
||||
(attrib_base,descr,rreg,wreg) = attribre.findall(line)[0]
|
||||
attrib_base = 'A_' + attrib_base
|
||||
attribinfo[attrib_base] = {'rreg':rreg, 'wreg':wreg, 'descr':descr}
|
||||
|
||||
def read_overrides_file(name):
|
||||
overridere = re.compile("#define fGEN_TCG_([A-Za-z0-9_]+)\(.*")
|
||||
for line in open(name, 'rt').readlines():
|
||||
if not overridere.match(line):
|
||||
continue
|
||||
tag = overridere.findall(line)[0]
|
||||
overrides[tag] = True
|
83
target/hexagon/hex_regs.h
Normal file
83
target/hexagon/hex_regs.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_REGS_H
|
||||
#define HEXAGON_REGS_H
|
||||
|
||||
enum {
|
||||
HEX_REG_R00 = 0,
|
||||
HEX_REG_R01 = 1,
|
||||
HEX_REG_R02 = 2,
|
||||
HEX_REG_R03 = 3,
|
||||
HEX_REG_R04 = 4,
|
||||
HEX_REG_R05 = 5,
|
||||
HEX_REG_R06 = 6,
|
||||
HEX_REG_R07 = 7,
|
||||
HEX_REG_R08 = 8,
|
||||
HEX_REG_R09 = 9,
|
||||
HEX_REG_R10 = 10,
|
||||
HEX_REG_R11 = 11,
|
||||
HEX_REG_R12 = 12,
|
||||
HEX_REG_R13 = 13,
|
||||
HEX_REG_R14 = 14,
|
||||
HEX_REG_R15 = 15,
|
||||
HEX_REG_R16 = 16,
|
||||
HEX_REG_R17 = 17,
|
||||
HEX_REG_R18 = 18,
|
||||
HEX_REG_R19 = 19,
|
||||
HEX_REG_R20 = 20,
|
||||
HEX_REG_R21 = 21,
|
||||
HEX_REG_R22 = 22,
|
||||
HEX_REG_R23 = 23,
|
||||
HEX_REG_R24 = 24,
|
||||
HEX_REG_R25 = 25,
|
||||
HEX_REG_R26 = 26,
|
||||
HEX_REG_R27 = 27,
|
||||
HEX_REG_R28 = 28,
|
||||
HEX_REG_R29 = 29,
|
||||
HEX_REG_SP = 29,
|
||||
HEX_REG_FP = 30,
|
||||
HEX_REG_R30 = 30,
|
||||
HEX_REG_LR = 31,
|
||||
HEX_REG_R31 = 31,
|
||||
HEX_REG_SA0 = 32,
|
||||
HEX_REG_LC0 = 33,
|
||||
HEX_REG_SA1 = 34,
|
||||
HEX_REG_LC1 = 35,
|
||||
HEX_REG_P3_0 = 36,
|
||||
HEX_REG_M0 = 38,
|
||||
HEX_REG_M1 = 39,
|
||||
HEX_REG_USR = 40,
|
||||
HEX_REG_PC = 41,
|
||||
HEX_REG_UGP = 42,
|
||||
HEX_REG_GP = 43,
|
||||
HEX_REG_CS0 = 44,
|
||||
HEX_REG_CS1 = 45,
|
||||
HEX_REG_UPCYCLELO = 46,
|
||||
HEX_REG_UPCYCLEHI = 47,
|
||||
HEX_REG_FRAMELIMIT = 48,
|
||||
HEX_REG_FRAMEKEY = 49,
|
||||
HEX_REG_PKTCNTLO = 50,
|
||||
HEX_REG_PKTCNTHI = 51,
|
||||
/* Use reserved control registers for qemu execution counts */
|
||||
HEX_REG_QEMU_PKT_CNT = 52,
|
||||
HEX_REG_QEMU_INSN_CNT = 53,
|
||||
HEX_REG_UTIMERLO = 62,
|
||||
HEX_REG_UTIMERHI = 63,
|
||||
};
|
||||
|
||||
#endif
|
73
target/hexagon/iclass.c
Normal file
73
target/hexagon/iclass.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "iclass.h"
|
||||
|
||||
static const SlotMask iclass_info[] = {
|
||||
|
||||
#define DEF_PP_ICLASS32(TYPE, SLOTS, UNITS) \
|
||||
[ICLASS_FROM_TYPE(TYPE)] = SLOTS_##SLOTS,
|
||||
#define DEF_EE_ICLASS32(TYPE, SLOTS, UNITS) \
|
||||
[ICLASS_FROM_TYPE(TYPE)] = SLOTS_##SLOTS,
|
||||
#include "imported/iclass.def"
|
||||
#undef DEF_PP_ICLASS32
|
||||
#undef DEF_EE_ICLASS32
|
||||
};
|
||||
|
||||
SlotMask find_iclass_slots(Opcode opcode, int itype)
|
||||
{
|
||||
/* There are some exceptions to what the iclass dictates */
|
||||
if (GET_ATTRIB(opcode, A_ICOP)) {
|
||||
return SLOTS_2;
|
||||
} else if (GET_ATTRIB(opcode, A_RESTRICT_SLOT0ONLY)) {
|
||||
return SLOTS_0;
|
||||
} else if (GET_ATTRIB(opcode, A_RESTRICT_SLOT1ONLY)) {
|
||||
return SLOTS_1;
|
||||
} else if (GET_ATTRIB(opcode, A_RESTRICT_SLOT2ONLY)) {
|
||||
return SLOTS_2;
|
||||
} else if (GET_ATTRIB(opcode, A_RESTRICT_SLOT3ONLY)) {
|
||||
return SLOTS_3;
|
||||
} else if (GET_ATTRIB(opcode, A_COF) &&
|
||||
GET_ATTRIB(opcode, A_INDIRECT) &&
|
||||
!GET_ATTRIB(opcode, A_MEMLIKE) &&
|
||||
!GET_ATTRIB(opcode, A_MEMLIKE_PACKET_RULES)) {
|
||||
return SLOTS_2;
|
||||
} else if (GET_ATTRIB(opcode, A_RESTRICT_NOSLOT1)) {
|
||||
return SLOTS_0;
|
||||
} else if ((opcode == J2_trap0) ||
|
||||
(opcode == Y2_isync) ||
|
||||
(opcode == J2_pause) || (opcode == J4_hintjumpr)) {
|
||||
return SLOTS_2;
|
||||
} else if ((itype == ICLASS_V2LDST) && (GET_ATTRIB(opcode, A_STORE))) {
|
||||
return SLOTS_01;
|
||||
} else if ((itype == ICLASS_V2LDST) && (!GET_ATTRIB(opcode, A_STORE))) {
|
||||
return SLOTS_01;
|
||||
} else if (GET_ATTRIB(opcode, A_CRSLOT23)) {
|
||||
return SLOTS_23;
|
||||
} else if (GET_ATTRIB(opcode, A_RESTRICT_PREFERSLOT0)) {
|
||||
return SLOTS_0;
|
||||
} else if (GET_ATTRIB(opcode, A_SUBINSN)) {
|
||||
return SLOTS_01;
|
||||
} else if (GET_ATTRIB(opcode, A_CALL)) {
|
||||
return SLOTS_23;
|
||||
} else if ((opcode == J4_jumpseti) || (opcode == J4_jumpsetr)) {
|
||||
return SLOTS_23;
|
||||
} else {
|
||||
return iclass_info[itype];
|
||||
}
|
||||
}
|
50
target/hexagon/iclass.h
Normal file
50
target/hexagon/iclass.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_ICLASS_H
|
||||
#define HEXAGON_ICLASS_H
|
||||
|
||||
#include "attribs.h"
|
||||
|
||||
#define ICLASS_FROM_TYPE(TYPE) ICLASS_##TYPE
|
||||
|
||||
enum {
|
||||
|
||||
#define DEF_PP_ICLASS32(TYPE, SLOTS, UNITS) ICLASS_FROM_TYPE(TYPE),
|
||||
#define DEF_EE_ICLASS32(TYPE, SLOTS, UNITS) ICLASS_FROM_TYPE(TYPE),
|
||||
#include "imported/iclass.def"
|
||||
#undef DEF_PP_ICLASS32
|
||||
#undef DEF_EE_ICLASS32
|
||||
|
||||
ICLASS_FROM_TYPE(COPROC_VX),
|
||||
ICLASS_FROM_TYPE(COPROC_VMEM),
|
||||
NUM_ICLASSES
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SLOTS_0 = (1 << 0),
|
||||
SLOTS_1 = (1 << 1),
|
||||
SLOTS_2 = (1 << 2),
|
||||
SLOTS_3 = (1 << 3),
|
||||
SLOTS_01 = SLOTS_0 | SLOTS_1,
|
||||
SLOTS_23 = SLOTS_2 | SLOTS_3,
|
||||
SLOTS_0123 = SLOTS_0 | SLOTS_1 | SLOTS_2 | SLOTS_3,
|
||||
} SlotMask;
|
||||
|
||||
SlotMask find_iclass_slots(Opcode opcode, int itype);
|
||||
|
||||
#endif
|
30
target/hexagon/imported/allidefs.def
Normal file
30
target/hexagon/imported/allidefs.def
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Top level instruction definition file
|
||||
*/
|
||||
|
||||
#include "branch.idef"
|
||||
#include "ldst.idef"
|
||||
#include "compare.idef"
|
||||
#include "mpy.idef"
|
||||
#include "alu.idef"
|
||||
#include "float.idef"
|
||||
#include "shift.idef"
|
||||
#include "system.idef"
|
||||
#include "subinsns.idef"
|
1258
target/hexagon/imported/alu.idef
Normal file
1258
target/hexagon/imported/alu.idef
Normal file
File diff suppressed because it is too large
Load Diff
326
target/hexagon/imported/branch.idef
Normal file
326
target/hexagon/imported/branch.idef
Normal file
@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
/*********************************************/
|
||||
/* Jump instructions */
|
||||
/*********************************************/
|
||||
|
||||
#define A_JDIR A_JUMP
|
||||
#define A_CJNEWDIR A_JUMP
|
||||
#define A_CJOLDDIR A_JUMP
|
||||
#define A_NEWVALUEJ A_JUMP,A_DOTNEWVALUE,A_MEMLIKE_PACKET_RULES
|
||||
#define A_JINDIR A_JUMP,A_INDIRECT
|
||||
#define A_JINDIRNEW A_JUMP,A_INDIRECT
|
||||
#define A_JINDIROLD A_JUMP,A_INDIRECT
|
||||
|
||||
Q6INSN(J2_jump,"jump #r22:2",ATTRIBS(A_JDIR), "direct unconditional jump",
|
||||
{fIMMEXT(riV); fPCALIGN(riV); fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);})
|
||||
|
||||
Q6INSN(J2_jumpr,"jumpr Rs32",ATTRIBS(A_JINDIR), "indirect unconditional jump",
|
||||
{fJUMPR(RsN,RsV,COF_TYPE_JUMPR);})
|
||||
|
||||
#define OLDCOND_JUMP(TAG,OPER,OPER2,ATTRIB,DESCR,SEMANTICS) \
|
||||
Q6INSN(TAG##t,"if (Pu4) "OPER":nt "OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBOLD(PuV),,SPECULATE_NOT_TAKEN,12,0); if (fLSBOLD(PuV)) { SEMANTICS; }}) \
|
||||
Q6INSN(TAG##f,"if (!Pu4) "OPER":nt "OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBOLDNOT(PuV),,SPECULATE_NOT_TAKEN,12,0); if (fLSBOLDNOT(PuV)) { SEMANTICS; }}) \
|
||||
Q6INSN(TAG##tpt,"if (Pu4) "OPER":t "OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBOLD(PuV),,SPECULATE_TAKEN,12,0); if (fLSBOLD(PuV)) { SEMANTICS; }}) \
|
||||
Q6INSN(TAG##fpt,"if (!Pu4) "OPER":t "OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBOLDNOT(PuV),,SPECULATE_TAKEN,12,0); if (fLSBOLDNOT(PuV)) { SEMANTICS; }})
|
||||
|
||||
OLDCOND_JUMP(J2_jump,"jump","#r15:2",ATTRIBS(A_CJOLDDIR),"direct conditional jump",
|
||||
fIMMEXT(riV);fPCALIGN(riV); fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);)
|
||||
|
||||
OLDCOND_JUMP(J2_jumpr,"jumpr","Rs32",ATTRIBS(A_JINDIROLD),"indirect conditional jump",
|
||||
fJUMPR(RsN,RsV,COF_TYPE_JUMPR);)
|
||||
|
||||
#define NEWCOND_JUMP(TAG,OPER,OPER2,ATTRIB,DESCR,SEMANTICS)\
|
||||
Q6INSN(TAG##tnew,"if (Pu4.new) "OPER":nt "OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBNEW(PuN),, SPECULATE_NOT_TAKEN , 12,0)} {if(fLSBNEW(PuN)){SEMANTICS;}})\
|
||||
Q6INSN(TAG##fnew,"if (!Pu4.new) "OPER":nt "OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBNEWNOT(PuN),, SPECULATE_NOT_TAKEN , 12,0)} {if(fLSBNEWNOT(PuN)){SEMANTICS;}})\
|
||||
Q6INSN(TAG##tnewpt,"if (Pu4.new) "OPER":t "OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBNEW(PuN),, SPECULATE_TAKEN , 12,0)} {if(fLSBNEW(PuN)){SEMANTICS;}})\
|
||||
Q6INSN(TAG##fnewpt,"if (!Pu4.new) "OPER":t "OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBNEWNOT(PuN),, SPECULATE_TAKEN , 12,0)} {if(fLSBNEWNOT(PuN)){SEMANTICS;}})
|
||||
|
||||
NEWCOND_JUMP(J2_jump,"jump","#r15:2",ATTRIBS(A_CJNEWDIR,A_ARCHV2),"direct conditional jump",
|
||||
fIMMEXT(riV); fPCALIGN(riV); fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMPNEW);)
|
||||
|
||||
NEWCOND_JUMP(J2_jumpr,"jumpr","Rs32",ATTRIBS(A_JINDIRNEW,A_ARCHV3),"indirect conditional jump",
|
||||
fJUMPR(RsN,RsV,COF_TYPE_JUMPR);)
|
||||
|
||||
|
||||
|
||||
Q6INSN(J4_hintjumpr,"hintjr(Rs32)",ATTRIBS(A_JINDIR),"hint indirect conditional jump",
|
||||
{fHINTJR(RsV);})
|
||||
|
||||
|
||||
/*********************************************/
|
||||
/* Compound Compare-Jumps */
|
||||
/*********************************************/
|
||||
Q6INSN(J2_jumprz,"if (Rs32!=#0) jump:nt #r13:2",ATTRIBS(A_CJNEWDIR,A_ARCHV3),"direct conditional jump if register true",
|
||||
{fBRANCH_SPECULATE_STALL((RsV!=0), , SPECULATE_NOT_TAKEN,12,0) if (RsV != 0) { fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})
|
||||
|
||||
Q6INSN(J2_jumprnz,"if (Rs32==#0) jump:nt #r13:2",ATTRIBS(A_CJNEWDIR,A_ARCHV3),"direct conditional jump if register false",
|
||||
{fBRANCH_SPECULATE_STALL((RsV==0), , SPECULATE_NOT_TAKEN,12,0) if (RsV == 0) {fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})
|
||||
|
||||
Q6INSN(J2_jumprzpt,"if (Rs32!=#0) jump:t #r13:2",ATTRIBS(A_CJNEWDIR,A_ARCHV3),"direct conditional jump if register true",
|
||||
{fBRANCH_SPECULATE_STALL((RsV!=0), , SPECULATE_TAKEN,12,0) if (RsV != 0) { fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})
|
||||
|
||||
Q6INSN(J2_jumprnzpt,"if (Rs32==#0) jump:t #r13:2",ATTRIBS(A_CJNEWDIR,A_ARCHV3),"direct conditional jump if register false",
|
||||
{fBRANCH_SPECULATE_STALL((RsV==0), , SPECULATE_TAKEN,12,0) if (RsV == 0) {fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})
|
||||
|
||||
Q6INSN(J2_jumprgtez,"if (Rs32>=#0) jump:nt #r13:2",ATTRIBS(A_CJNEWDIR,A_ARCHV3),"direct conditional jump if register greater or equal to zero",
|
||||
{fBRANCH_SPECULATE_STALL((RsV>=0), , SPECULATE_NOT_TAKEN,12,0) if (RsV>=0) { fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})
|
||||
|
||||
Q6INSN(J2_jumprgtezpt,"if (Rs32>=#0) jump:t #r13:2",ATTRIBS(A_CJNEWDIR,A_ARCHV3),"direct conditional jump if register greater or equal to zero",
|
||||
{fBRANCH_SPECULATE_STALL((RsV>=0), , SPECULATE_TAKEN,12,0) if (RsV>=0) { fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})
|
||||
|
||||
Q6INSN(J2_jumprltez,"if (Rs32<=#0) jump:nt #r13:2",ATTRIBS(A_CJNEWDIR,A_ARCHV3),"direct conditional jump if register less than or equal to zero",
|
||||
{fBRANCH_SPECULATE_STALL((RsV<=0), , SPECULATE_NOT_TAKEN,12,0) if (RsV<=0) { fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})
|
||||
|
||||
Q6INSN(J2_jumprltezpt,"if (Rs32<=#0) jump:t #r13:2",ATTRIBS(A_CJNEWDIR,A_ARCHV3),"direct conditional jump if register less than or equal to zero",
|
||||
{fBRANCH_SPECULATE_STALL((RsV<=0), , SPECULATE_TAKEN,12,0) if (RsV<=0) { fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})
|
||||
|
||||
|
||||
|
||||
/*********************************************/
|
||||
/* V4 Compound Compare-Jumps */
|
||||
/*********************************************/
|
||||
|
||||
|
||||
/* V4 compound compare jumps (CJ) */
|
||||
#define STD_CMPJUMP(TAG,TST,TSTSEM)\
|
||||
Q6INSN(J4_##TAG##_tp0_jump_nt, "p0="TST"; if (p0.new) jump:nt #r9:2", ATTRIBS(A_CJNEWDIR,A_NEWCMPJUMP),"compound compare-jump", {fPART1(fWRITE_P0(f8BITSOF(TSTSEM))) fBRANCH_SPECULATE_STALL(fLSBNEW0,,SPECULATE_NOT_TAKEN,13,0) if (fLSBNEW0) {fIMMEXT(riV); fPCALIGN(riV); fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})\
|
||||
Q6INSN(J4_##TAG##_fp0_jump_nt, "p0="TST"; if (!p0.new) jump:nt #r9:2", ATTRIBS(A_CJNEWDIR,A_NEWCMPJUMP),"compound compare-jump",{fPART1(fWRITE_P0(f8BITSOF(TSTSEM))) fBRANCH_SPECULATE_STALL(fLSBNEW0NOT,,SPECULATE_NOT_TAKEN,13,0) if (fLSBNEW0NOT) {fIMMEXT(riV); fPCALIGN(riV); fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})\
|
||||
Q6INSN(J4_##TAG##_tp0_jump_t, "p0="TST"; if (p0.new) jump:t #r9:2", ATTRIBS(A_CJNEWDIR,A_NEWCMPJUMP),"compound compare-jump", {fPART1(fWRITE_P0(f8BITSOF(TSTSEM))) fBRANCH_SPECULATE_STALL(fLSBNEW0,,SPECULATE_TAKEN,13,0) if (fLSBNEW0) {fIMMEXT(riV); fPCALIGN(riV); fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})\
|
||||
Q6INSN(J4_##TAG##_fp0_jump_t, "p0="TST"; if (!p0.new) jump:t #r9:2", ATTRIBS(A_CJNEWDIR,A_NEWCMPJUMP),"compound compare-jump", {fPART1(fWRITE_P0(f8BITSOF(TSTSEM))) fBRANCH_SPECULATE_STALL(fLSBNEW0NOT,,SPECULATE_TAKEN,13,0) if (fLSBNEW0NOT) {fIMMEXT(riV); fPCALIGN(riV); fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})\
|
||||
Q6INSN(J4_##TAG##_tp1_jump_nt, "p1="TST"; if (p1.new) jump:nt #r9:2", ATTRIBS(A_CJNEWDIR,A_NEWCMPJUMP),"compound compare-jump", {fPART1(fWRITE_P1(f8BITSOF(TSTSEM))) fBRANCH_SPECULATE_STALL(fLSBNEW1,,SPECULATE_NOT_TAKEN,13,0) if (fLSBNEW1) {fIMMEXT(riV); fPCALIGN(riV); fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})\
|
||||
Q6INSN(J4_##TAG##_fp1_jump_nt, "p1="TST"; if (!p1.new) jump:nt #r9:2", ATTRIBS(A_CJNEWDIR,A_NEWCMPJUMP),"compound compare-jump",{fPART1(fWRITE_P1(f8BITSOF(TSTSEM))) fBRANCH_SPECULATE_STALL(fLSBNEW1NOT,,SPECULATE_NOT_TAKEN,13,0) if (fLSBNEW1NOT) {fIMMEXT(riV); fPCALIGN(riV); fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})\
|
||||
Q6INSN(J4_##TAG##_tp1_jump_t, "p1="TST"; if (p1.new) jump:t #r9:2", ATTRIBS(A_CJNEWDIR,A_NEWCMPJUMP),"compound compare-jump", {fPART1(fWRITE_P1(f8BITSOF(TSTSEM))) fBRANCH_SPECULATE_STALL(fLSBNEW1,,SPECULATE_TAKEN,13,0) if (fLSBNEW1) {fIMMEXT(riV); fPCALIGN(riV); fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})\
|
||||
Q6INSN(J4_##TAG##_fp1_jump_t, "p1="TST"; if (!p1.new) jump:t #r9:2", ATTRIBS(A_CJNEWDIR,A_NEWCMPJUMP),"compound compare-jump", {fPART1(fWRITE_P1(f8BITSOF(TSTSEM))) fBRANCH_SPECULATE_STALL(fLSBNEW1NOT,,SPECULATE_TAKEN,13,0) if (fLSBNEW1NOT) {fIMMEXT(riV); fPCALIGN(riV); fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})
|
||||
|
||||
|
||||
STD_CMPJUMP(cmpeqi,"cmp.eq(Rs16,#U5)",(RsV==UiV))
|
||||
STD_CMPJUMP(cmpgti,"cmp.gt(Rs16,#U5)",(RsV>UiV))
|
||||
STD_CMPJUMP(cmpgtui,"cmp.gtu(Rs16,#U5)",(fCAST4u(RsV)>UiV))
|
||||
|
||||
STD_CMPJUMP(cmpeqn1,"cmp.eq(Rs16,#-1)",(RsV==-1))
|
||||
STD_CMPJUMP(cmpgtn1,"cmp.gt(Rs16,#-1)",(RsV>-1))
|
||||
STD_CMPJUMP(tstbit0,"tstbit(Rs16,#0)",(RsV & 1))
|
||||
|
||||
STD_CMPJUMP(cmpeq,"cmp.eq(Rs16,Rt16)",(RsV==RtV))
|
||||
STD_CMPJUMP(cmpgt,"cmp.gt(Rs16,Rt16)",(RsV>RtV))
|
||||
STD_CMPJUMP(cmpgtu,"cmp.gtu(Rs16,Rt16)",(fCAST4u(RsV)>RtV))
|
||||
|
||||
|
||||
|
||||
/* V4 jump and transfer (CJ) */
|
||||
Q6INSN(J4_jumpseti,"Rd16=#U6 ; jump #r9:2",ATTRIBS(A_JDIR), "direct unconditional jump and set register to immediate",
|
||||
{fIMMEXT(riV); fPCALIGN(riV); RdV=UiV; fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);})
|
||||
|
||||
Q6INSN(J4_jumpsetr,"Rd16=Rs16 ; jump #r9:2",ATTRIBS(A_JDIR), "direct unconditional jump and transfer register",
|
||||
{fIMMEXT(riV); fPCALIGN(riV); RdV=RsV; fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);})
|
||||
|
||||
|
||||
/* V4 new-value jumps (NCJ) */
|
||||
#define STD_CMPJUMPNEWRS(TAG,TST,TSTSEM)\
|
||||
Q6INSN(J4_##TAG##_jumpnv_t, "if ("TST") jump:t #r9:2", ATTRIBS(A_NEWVALUEJ),"compound compare-jump",{fBRANCH_SPECULATE_STALL(TSTSEM,,SPECULATE_TAKEN,13,0);if (TSTSEM) {fIMMEXT(riV); fPCALIGN(riV); fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})\
|
||||
Q6INSN(J4_##TAG##_jumpnv_nt,"if ("TST") jump:nt #r9:2",ATTRIBS(A_NEWVALUEJ),"compound compare-jump",{fBRANCH_SPECULATE_STALL(TSTSEM,,SPECULATE_NOT_TAKEN,13,0); if (TSTSEM) {fIMMEXT(riV); fPCALIGN(riV); fBRANCH(fREAD_PC()+riV,COF_TYPE_JUMP);}})
|
||||
|
||||
|
||||
|
||||
|
||||
STD_CMPJUMPNEWRS(cmpeqi_t,"cmp.eq(Ns8.new,#U5)",(fNEWREG(NsN)==(UiV)))
|
||||
STD_CMPJUMPNEWRS(cmpeqi_f,"!cmp.eq(Ns8.new,#U5)",(fNEWREG(NsN)!=(UiV)))
|
||||
STD_CMPJUMPNEWRS(cmpgti_t,"cmp.gt(Ns8.new,#U5)",(fNEWREG(NsN)>(UiV)))
|
||||
STD_CMPJUMPNEWRS(cmpgti_f,"!cmp.gt(Ns8.new,#U5)",!(fNEWREG(NsN)>(UiV)))
|
||||
STD_CMPJUMPNEWRS(cmpgtui_t,"cmp.gtu(Ns8.new,#U5)",(fCAST4u(fNEWREG(NsN))>(UiV)))
|
||||
STD_CMPJUMPNEWRS(cmpgtui_f,"!cmp.gtu(Ns8.new,#U5)",!(fCAST4u(fNEWREG(NsN))>(UiV)))
|
||||
|
||||
|
||||
STD_CMPJUMPNEWRS(cmpeqn1_t,"cmp.eq(Ns8.new,#-1)",(fNEWREG(NsN)==(-1)))
|
||||
STD_CMPJUMPNEWRS(cmpeqn1_f,"!cmp.eq(Ns8.new,#-1)",(fNEWREG(NsN)!=(-1)))
|
||||
STD_CMPJUMPNEWRS(cmpgtn1_t,"cmp.gt(Ns8.new,#-1)",(fNEWREG(NsN)>(-1)))
|
||||
STD_CMPJUMPNEWRS(cmpgtn1_f,"!cmp.gt(Ns8.new,#-1)",!(fNEWREG(NsN)>(-1)))
|
||||
STD_CMPJUMPNEWRS(tstbit0_t,"tstbit(Ns8.new,#0)",((fNEWREG(NsN)) & 1))
|
||||
STD_CMPJUMPNEWRS(tstbit0_f,"!tstbit(Ns8.new,#0)",!((fNEWREG(NsN)) & 1))
|
||||
|
||||
|
||||
STD_CMPJUMPNEWRS(cmpeq_t, "cmp.eq(Ns8.new,Rt32)", (fNEWREG(NsN)==RtV))
|
||||
STD_CMPJUMPNEWRS(cmpgt_t, "cmp.gt(Ns8.new,Rt32)", (fNEWREG(NsN)>RtV))
|
||||
STD_CMPJUMPNEWRS(cmpgtu_t,"cmp.gtu(Ns8.new,Rt32)",(fCAST4u(fNEWREG(NsN))>fCAST4u(RtV)))
|
||||
STD_CMPJUMPNEWRS(cmplt_t, "cmp.gt(Rt32,Ns8.new)", (RtV>fNEWREG(NsN)))
|
||||
STD_CMPJUMPNEWRS(cmpltu_t,"cmp.gtu(Rt32,Ns8.new)",(fCAST4u(RtV)>fCAST4u(fNEWREG(NsN))))
|
||||
STD_CMPJUMPNEWRS(cmpeq_f, "!cmp.eq(Ns8.new,Rt32)", (fNEWREG(NsN)!=RtV))
|
||||
STD_CMPJUMPNEWRS(cmpgt_f, "!cmp.gt(Ns8.new,Rt32)", !(fNEWREG(NsN)>RtV))
|
||||
STD_CMPJUMPNEWRS(cmpgtu_f,"!cmp.gtu(Ns8.new,Rt32)",!(fCAST4u(fNEWREG(NsN))>fCAST4u(RtV)))
|
||||
STD_CMPJUMPNEWRS(cmplt_f, "!cmp.gt(Rt32,Ns8.new)", !(RtV>fNEWREG(NsN)))
|
||||
STD_CMPJUMPNEWRS(cmpltu_f,"!cmp.gtu(Rt32,Ns8.new)",!(fCAST4u(RtV)>fCAST4u(fNEWREG(NsN))))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************************/
|
||||
/* Subroutine Call instructions */
|
||||
/*********************************************/
|
||||
|
||||
#define CDIR_STD A_CALL
|
||||
#define CINDIR_STD A_CALL,A_INDIRECT
|
||||
|
||||
Q6INSN(J2_call,"call #r22:2",ATTRIBS(CDIR_STD), "direct unconditional call",
|
||||
{fIMMEXT(riV); fPCALIGN(riV); fCALL(fREAD_PC()+riV); })
|
||||
|
||||
Q6INSN(J2_callt,"if (Pu4) call #r15:2",ATTRIBS(CDIR_STD),"direct conditional call if true",
|
||||
{fIMMEXT(riV); fPCALIGN(riV); fBRANCH_SPECULATE_STALL(fLSBOLD(PuV),,SPECULATE_NOT_TAKEN,12,0); if (fLSBOLD(PuV)) { fCALL(fREAD_PC()+riV); }})
|
||||
|
||||
Q6INSN(J2_callf,"if (!Pu4) call #r15:2",ATTRIBS(CDIR_STD),"direct conditional call if false",
|
||||
{fIMMEXT(riV); fPCALIGN(riV); fBRANCH_SPECULATE_STALL(fLSBOLDNOT(PuV),,SPECULATE_NOT_TAKEN,12,0);if (fLSBOLDNOT(PuV)) { fCALL(fREAD_PC()+riV); }})
|
||||
|
||||
Q6INSN(J2_callr,"callr Rs32",ATTRIBS(CINDIR_STD), "indirect unconditional call",
|
||||
{ fCALLR(RsV); })
|
||||
|
||||
Q6INSN(J2_callrt,"if (Pu4) callr Rs32",ATTRIBS(CINDIR_STD),"indirect conditional call if true",
|
||||
{fBRANCH_SPECULATE_STALL(fLSBOLD(PuV),,SPECULATE_NOT_TAKEN,12,0);if (fLSBOLD(PuV)) { fCALLR(RsV); }})
|
||||
|
||||
Q6INSN(J2_callrf,"if (!Pu4) callr Rs32",ATTRIBS(CINDIR_STD),"indirect conditional call if false",
|
||||
{fBRANCH_SPECULATE_STALL(fLSBOLDNOT(PuV),,SPECULATE_NOT_TAKEN,12,0);if (fLSBOLDNOT(PuV)) { fCALLR(RsV); }})
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************************/
|
||||
/* HW Loop instructions */
|
||||
/*********************************************/
|
||||
|
||||
Q6INSN(J2_loop0r,"loop0(#r7:2,Rs32)",ATTRIBS(),"Initialize HW loop 0",
|
||||
{ fIMMEXT(riV); fPCALIGN(riV);
|
||||
fWRITE_LOOP_REGS0(/*sa,lc*/ fREAD_PC()+riV, RsV);
|
||||
fSET_LPCFG(0);
|
||||
})
|
||||
|
||||
Q6INSN(J2_loop1r,"loop1(#r7:2,Rs32)",ATTRIBS(),"Initialize HW loop 1",
|
||||
{ fIMMEXT(riV); fPCALIGN(riV);
|
||||
fWRITE_LOOP_REGS1(/*sa,lc*/ fREAD_PC()+riV, RsV);
|
||||
})
|
||||
|
||||
Q6INSN(J2_loop0i,"loop0(#r7:2,#U10)",ATTRIBS(),"Initialize HW loop 0",
|
||||
{ fIMMEXT(riV); fPCALIGN(riV);
|
||||
fWRITE_LOOP_REGS0(/*sa,lc*/ fREAD_PC()+riV, UiV);
|
||||
fSET_LPCFG(0);
|
||||
})
|
||||
|
||||
Q6INSN(J2_loop1i,"loop1(#r7:2,#U10)",ATTRIBS(),"Initialize HW loop 1",
|
||||
{ fIMMEXT(riV); fPCALIGN(riV);
|
||||
fWRITE_LOOP_REGS1(/*sa,lc*/ fREAD_PC()+riV, UiV);
|
||||
})
|
||||
|
||||
|
||||
Q6INSN(J2_ploop1sr,"p3=sp1loop0(#r7:2,Rs32)",ATTRIBS(A_ARCHV2),"Initialize HW loop 0",
|
||||
{ fIMMEXT(riV); fPCALIGN(riV);
|
||||
fWRITE_LOOP_REGS0(/*sa,lc*/ fREAD_PC()+riV, RsV);
|
||||
fSET_LPCFG(1);
|
||||
fWRITE_P3(0);
|
||||
})
|
||||
Q6INSN(J2_ploop1si,"p3=sp1loop0(#r7:2,#U10)",ATTRIBS(A_ARCHV2),"Initialize HW loop 0",
|
||||
{ fIMMEXT(riV); fPCALIGN(riV);
|
||||
fWRITE_LOOP_REGS0(/*sa,lc*/ fREAD_PC()+riV, UiV);
|
||||
fSET_LPCFG(1);
|
||||
fWRITE_P3(0);
|
||||
})
|
||||
|
||||
Q6INSN(J2_ploop2sr,"p3=sp2loop0(#r7:2,Rs32)",ATTRIBS(A_ARCHV2),"Initialize HW loop 0",
|
||||
{ fIMMEXT(riV); fPCALIGN(riV);
|
||||
fWRITE_LOOP_REGS0(/*sa,lc*/ fREAD_PC()+riV, RsV);
|
||||
fSET_LPCFG(2);
|
||||
fWRITE_P3(0);
|
||||
})
|
||||
Q6INSN(J2_ploop2si,"p3=sp2loop0(#r7:2,#U10)",ATTRIBS(A_ARCHV2),"Initialize HW loop 0",
|
||||
{ fIMMEXT(riV); fPCALIGN(riV);
|
||||
fWRITE_LOOP_REGS0(/*sa,lc*/ fREAD_PC()+riV, UiV);
|
||||
fSET_LPCFG(2);
|
||||
fWRITE_P3(0);
|
||||
})
|
||||
|
||||
Q6INSN(J2_ploop3sr,"p3=sp3loop0(#r7:2,Rs32)",ATTRIBS(A_ARCHV2),"Initialize HW loop 0",
|
||||
{ fIMMEXT(riV); fPCALIGN(riV);
|
||||
fWRITE_LOOP_REGS0(/*sa,lc*/ fREAD_PC()+riV, RsV);
|
||||
fSET_LPCFG(3);
|
||||
fWRITE_P3(0);
|
||||
})
|
||||
Q6INSN(J2_ploop3si,"p3=sp3loop0(#r7:2,#U10)",ATTRIBS(A_ARCHV2),"Initialize HW loop 0",
|
||||
{ fIMMEXT(riV); fPCALIGN(riV);
|
||||
fWRITE_LOOP_REGS0(/*sa,lc*/ fREAD_PC()+riV, UiV);
|
||||
fSET_LPCFG(3);
|
||||
fWRITE_P3(0);
|
||||
})
|
||||
|
||||
|
||||
|
||||
Q6INSN(J2_endloop01,"endloop01",ATTRIBS(A_HWLOOP0_END,A_HWLOOP1_END),"Loopend for inner and outer loop",
|
||||
{
|
||||
|
||||
/* V2: With predicate control */
|
||||
if (fGET_LPCFG) {
|
||||
fHIDE( if (fGET_LPCFG >= 2) { /* Nothing */ } else )
|
||||
if (fGET_LPCFG==1) {
|
||||
fWRITE_P3(0xff);
|
||||
}
|
||||
fSET_LPCFG(fGET_LPCFG-1);
|
||||
}
|
||||
|
||||
/* check if iterate */
|
||||
if (fREAD_LC0>1) {
|
||||
fBRANCH(fREAD_SA0,COF_TYPE_LOOPEND0);
|
||||
/* decrement loop count */
|
||||
fWRITE_LC0(fREAD_LC0-1);
|
||||
} else {
|
||||
/* check if iterate */
|
||||
if (fREAD_LC1>1) {
|
||||
fBRANCH(fREAD_SA1,COF_TYPE_LOOPEND1);
|
||||
/* decrement loop count */
|
||||
fWRITE_LC1(fREAD_LC1-1);
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
Q6INSN(J2_endloop0,"endloop0",ATTRIBS(A_HWLOOP0_END),"Loopend for inner loop",
|
||||
{
|
||||
|
||||
/* V2: With predicate control */
|
||||
if (fGET_LPCFG) {
|
||||
fHIDE( if (fGET_LPCFG >= 2) { /* Nothing */ } else )
|
||||
if (fGET_LPCFG==1) {
|
||||
fWRITE_P3(0xff);
|
||||
}
|
||||
fSET_LPCFG(fGET_LPCFG-1);
|
||||
}
|
||||
|
||||
/* check if iterate */
|
||||
if (fREAD_LC0>1) {
|
||||
fBRANCH(fREAD_SA0,COF_TYPE_LOOPEND0);
|
||||
/* decrement loop count */
|
||||
fWRITE_LC0(fREAD_LC0-1);
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(J2_endloop1,"endloop1",ATTRIBS(A_HWLOOP1_END),"Loopend for outer loop",
|
||||
{
|
||||
/* check if iterate */
|
||||
if (fREAD_LC1>1) {
|
||||
fBRANCH(fREAD_SA1,COF_TYPE_LOOPEND1);
|
||||
/* decrement loop count */
|
||||
fWRITE_LC1(fREAD_LC1-1);
|
||||
}
|
||||
})
|
619
target/hexagon/imported/compare.idef
Normal file
619
target/hexagon/imported/compare.idef
Normal file
@ -0,0 +1,619 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Compare Instructions
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*********************************************/
|
||||
/* Scalar compare instructions */
|
||||
/*********************************************/
|
||||
|
||||
Q6INSN(C2_cmpeq,"Pd4=cmp.eq(Rs32,Rt32)",ATTRIBS(),
|
||||
"Compare for Equal",
|
||||
{PdV=f8BITSOF(RsV==RtV);})
|
||||
|
||||
Q6INSN(C2_cmpgt,"Pd4=cmp.gt(Rs32,Rt32)",ATTRIBS(),
|
||||
"Compare for signed Greater Than",
|
||||
{PdV=f8BITSOF(RsV>RtV);})
|
||||
|
||||
Q6INSN(C2_cmpgtu,"Pd4=cmp.gtu(Rs32,Rt32)",ATTRIBS(),
|
||||
"Compare for Greater Than Unsigned",
|
||||
{PdV=f8BITSOF(fCAST4u(RsV)>fCAST4u(RtV));})
|
||||
|
||||
Q6INSN(C2_cmpeqp,"Pd4=cmp.eq(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Compare for Equal",
|
||||
{PdV=f8BITSOF(RssV==RttV);})
|
||||
|
||||
Q6INSN(C2_cmpgtp,"Pd4=cmp.gt(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Compare for signed Greater Than",
|
||||
{PdV=f8BITSOF(RssV>RttV);})
|
||||
|
||||
Q6INSN(C2_cmpgtup,"Pd4=cmp.gtu(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Compare for Greater Than Unsigned",
|
||||
{PdV=f8BITSOF(fCAST8u(RssV)>fCAST8u(RttV));})
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************************/
|
||||
/* Compare and put result in GPR */
|
||||
/* typically for function I/O */
|
||||
/*********************************************/
|
||||
|
||||
Q6INSN(A4_rcmpeqi,"Rd32=cmp.eq(Rs32,#s8)",ATTRIBS(),
|
||||
"Compare for Equal",
|
||||
{fIMMEXT(siV); RdV=(RsV==siV); })
|
||||
|
||||
Q6INSN(A4_rcmpneqi,"Rd32=!cmp.eq(Rs32,#s8)",ATTRIBS(),
|
||||
"Compare for Equal",
|
||||
{fIMMEXT(siV); RdV=(RsV!=siV); })
|
||||
|
||||
|
||||
Q6INSN(A4_rcmpeq,"Rd32=cmp.eq(Rs32,Rt32)",ATTRIBS(),
|
||||
"Compare for Equal",
|
||||
{RdV=(RsV==RtV); })
|
||||
|
||||
Q6INSN(A4_rcmpneq,"Rd32=!cmp.eq(Rs32,Rt32)",ATTRIBS(),
|
||||
"Compare for Equal",
|
||||
{RdV=(RsV!=RtV); })
|
||||
|
||||
|
||||
|
||||
/*********************************************/
|
||||
/* Scalar compare instructions */
|
||||
/*********************************************/
|
||||
|
||||
|
||||
Q6INSN(C2_bitsset,"Pd4=bitsset(Rs32,Rt32)",ATTRIBS(A_ARCHV2),
|
||||
"Compare for selected bits set",
|
||||
{PdV=f8BITSOF((RsV&RtV)==RtV);})
|
||||
|
||||
Q6INSN(C2_bitsclr,"Pd4=bitsclr(Rs32,Rt32)",ATTRIBS(A_ARCHV2),
|
||||
"Compare for selected bits clear",
|
||||
{PdV=f8BITSOF((RsV&RtV)==0);})
|
||||
|
||||
|
||||
Q6INSN(C4_nbitsset,"Pd4=!bitsset(Rs32,Rt32)",ATTRIBS(A_ARCHV2),
|
||||
"Compare for selected bits set",
|
||||
{PdV=f8BITSOF((RsV&RtV)!=RtV);})
|
||||
|
||||
Q6INSN(C4_nbitsclr,"Pd4=!bitsclr(Rs32,Rt32)",ATTRIBS(A_ARCHV2),
|
||||
"Compare for selected bits clear",
|
||||
{PdV=f8BITSOF((RsV&RtV)!=0);})
|
||||
|
||||
|
||||
|
||||
/*********************************************/
|
||||
/* Scalar compare instructions W/ immediate */
|
||||
/*********************************************/
|
||||
|
||||
Q6INSN(C2_cmpeqi,"Pd4=cmp.eq(Rs32,#s10)",ATTRIBS(),
|
||||
"Compare for Equal",
|
||||
{fIMMEXT(siV); PdV=f8BITSOF(RsV==siV);})
|
||||
|
||||
Q6INSN(C2_cmpgti,"Pd4=cmp.gt(Rs32,#s10)",ATTRIBS(),
|
||||
"Compare for signed Greater Than",
|
||||
{fIMMEXT(siV); PdV=f8BITSOF(RsV>siV);})
|
||||
|
||||
Q6INSN(C2_cmpgtui,"Pd4=cmp.gtu(Rs32,#u9)",ATTRIBS(),
|
||||
"Compare for Greater Than Unsigned",
|
||||
{fIMMEXT(uiV); PdV=f8BITSOF(fCAST4u(RsV)>fCAST4u(uiV));})
|
||||
|
||||
Q6INSN(C2_bitsclri,"Pd4=bitsclr(Rs32,#u6)",ATTRIBS(A_ARCHV2),
|
||||
"Compare for selected bits clear",
|
||||
{PdV=f8BITSOF((RsV&uiV)==0);})
|
||||
|
||||
Q6INSN(C4_nbitsclri,"Pd4=!bitsclr(Rs32,#u6)",ATTRIBS(A_ARCHV2),
|
||||
"Compare for selected bits clear",
|
||||
{PdV=f8BITSOF((RsV&uiV)!=0);})
|
||||
|
||||
|
||||
|
||||
|
||||
Q6INSN(C4_cmpneqi,"Pd4=!cmp.eq(Rs32,#s10)",ATTRIBS(), "Compare for Not Equal", {fIMMEXT(siV); PdV=f8BITSOF(RsV!=siV);})
|
||||
Q6INSN(C4_cmpltei,"Pd4=!cmp.gt(Rs32,#s10)",ATTRIBS(), "Compare for Less Than or Equal", {fIMMEXT(siV); PdV=f8BITSOF(RsV<=siV);})
|
||||
Q6INSN(C4_cmplteui,"Pd4=!cmp.gtu(Rs32,#u9)",ATTRIBS(), "Compare for Less Than or Equal Unsigned", {fIMMEXT(uiV); PdV=f8BITSOF(fCAST4u(RsV)<=fCAST4u(uiV));})
|
||||
|
||||
Q6INSN(C4_cmpneq,"Pd4=!cmp.eq(Rs32,Rt32)",ATTRIBS(), "And-Compare for Equal", {PdV=f8BITSOF(RsV!=RtV);})
|
||||
Q6INSN(C4_cmplte,"Pd4=!cmp.gt(Rs32,Rt32)",ATTRIBS(), "And-Compare for signed Greater Than", {PdV=f8BITSOF(RsV<=RtV);})
|
||||
Q6INSN(C4_cmplteu,"Pd4=!cmp.gtu(Rs32,Rt32)",ATTRIBS(), "And-Compare for Greater Than Unsigned", {PdV=f8BITSOF(fCAST4u(RsV)<=fCAST4u(RtV));})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Predicate Logical Operations */
|
||||
|
||||
Q6INSN(C2_and,"Pd4=and(Pt4,Ps4)",ATTRIBS(A_CRSLOT23),
|
||||
"Predicate AND",
|
||||
{PdV=PsV & PtV;})
|
||||
|
||||
Q6INSN(C2_or,"Pd4=or(Pt4,Ps4)",ATTRIBS(A_CRSLOT23),
|
||||
"Predicate OR",
|
||||
{PdV=PsV | PtV;})
|
||||
|
||||
Q6INSN(C2_xor,"Pd4=xor(Ps4,Pt4)",ATTRIBS(A_CRSLOT23),
|
||||
"Predicate XOR",
|
||||
{PdV=PsV ^ PtV;})
|
||||
|
||||
Q6INSN(C2_andn,"Pd4=and(Pt4,!Ps4)",ATTRIBS(A_CRSLOT23),
|
||||
"Predicate AND NOT",
|
||||
{PdV=PtV & (~PsV);})
|
||||
|
||||
Q6INSN(C2_not,"Pd4=not(Ps4)",ATTRIBS(A_CRSLOT23),
|
||||
"Logical NOT Predicate",
|
||||
{PdV=~PsV;})
|
||||
|
||||
Q6INSN(C2_orn,"Pd4=or(Pt4,!Ps4)",ATTRIBS(A_ARCHV2,A_CRSLOT23),
|
||||
"Predicate OR NOT",
|
||||
{PdV=PtV | (~PsV);})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Q6INSN(C4_and_and,"Pd4=and(Ps4,and(Pt4,Pu4))",ATTRIBS(A_CRSLOT23),
|
||||
"Compound And-And", { PdV = PsV & PtV & PuV; })
|
||||
|
||||
Q6INSN(C4_and_or,"Pd4=and(Ps4,or(Pt4,Pu4))",ATTRIBS(A_CRSLOT23),
|
||||
"Compound And-Or", { PdV = PsV & (PtV | PuV); })
|
||||
|
||||
Q6INSN(C4_or_and,"Pd4=or(Ps4,and(Pt4,Pu4))",ATTRIBS(A_CRSLOT23),
|
||||
"Compound Or-And", { PdV = PsV | (PtV & PuV); })
|
||||
|
||||
Q6INSN(C4_or_or,"Pd4=or(Ps4,or(Pt4,Pu4))",ATTRIBS(A_CRSLOT23),
|
||||
"Compound Or-Or", { PdV = PsV | PtV | PuV; })
|
||||
|
||||
|
||||
|
||||
Q6INSN(C4_and_andn,"Pd4=and(Ps4,and(Pt4,!Pu4))",ATTRIBS(A_CRSLOT23),
|
||||
"Compound And-And", { PdV = PsV & PtV & (~PuV); })
|
||||
|
||||
Q6INSN(C4_and_orn,"Pd4=and(Ps4,or(Pt4,!Pu4))",ATTRIBS(A_CRSLOT23),
|
||||
"Compound And-Or", { PdV = PsV & (PtV | (~PuV)); })
|
||||
|
||||
Q6INSN(C4_or_andn,"Pd4=or(Ps4,and(Pt4,!Pu4))",ATTRIBS(A_CRSLOT23),
|
||||
"Compound Or-And", { PdV = PsV | (PtV & (~PuV)); })
|
||||
|
||||
Q6INSN(C4_or_orn,"Pd4=or(Ps4,or(Pt4,!Pu4))",ATTRIBS(A_CRSLOT23),
|
||||
"Compound Or-Or", { PdV = PsV | PtV | (~PuV); })
|
||||
|
||||
|
||||
Q6INSN(C2_any8,"Pd4=any8(Ps4)",ATTRIBS(A_CRSLOT23),
|
||||
"Logical ANY of low 8 predicate bits",
|
||||
{ PsV ? (PdV=0xff) : (PdV=0x00); })
|
||||
|
||||
Q6INSN(C2_all8,"Pd4=all8(Ps4)",ATTRIBS(A_CRSLOT23),
|
||||
"Logical ALL of low 8 predicate bits",
|
||||
{ (PsV==0xff) ? (PdV=0xff) : (PdV=0x00); })
|
||||
|
||||
Q6INSN(C2_vitpack,"Rd32=vitpack(Ps4,Pt4)",ATTRIBS(),
|
||||
"Pack the odd and even bits of two predicate registers",
|
||||
{ RdV = (PsV&0x55) | (PtV&0xAA); })
|
||||
|
||||
/* Mux instructions */
|
||||
|
||||
Q6INSN(C2_mux,"Rd32=mux(Pu4,Rs32,Rt32)",ATTRIBS(),
|
||||
"Scalar MUX",
|
||||
{ (fLSBOLD(PuV)) ? (RdV=RsV):(RdV=RtV); })
|
||||
|
||||
|
||||
Q6INSN(C2_cmovenewit,"if (Pu4.new) Rd32=#s12",ATTRIBS(A_ARCHV2),
|
||||
"Scalar conditional move",
|
||||
{ fIMMEXT(siV); if (fLSBNEW(PuN)) RdV=siV; else CANCEL;})
|
||||
|
||||
Q6INSN(C2_cmovenewif,"if (!Pu4.new) Rd32=#s12",ATTRIBS(A_ARCHV2),
|
||||
"Scalar conditional move",
|
||||
{ fIMMEXT(siV); if (fLSBNEWNOT(PuN)) RdV=siV; else CANCEL;})
|
||||
|
||||
Q6INSN(C2_cmoveit,"if (Pu4) Rd32=#s12",ATTRIBS(A_ARCHV2),
|
||||
"Scalar conditional move",
|
||||
{ fIMMEXT(siV); if (fLSBOLD(PuV)) RdV=siV; else CANCEL;})
|
||||
|
||||
Q6INSN(C2_cmoveif,"if (!Pu4) Rd32=#s12",ATTRIBS(A_ARCHV2),
|
||||
"Scalar conditional move",
|
||||
{ fIMMEXT(siV); if (fLSBOLDNOT(PuV)) RdV=siV; else CANCEL;})
|
||||
|
||||
|
||||
|
||||
Q6INSN(C2_ccombinewnewt,"if (Pu4.new) Rdd32=combine(Rs32,Rt32)",ATTRIBS(A_ARCHV2),
|
||||
"Conditionally combine two words into a register pair",
|
||||
{ if (fLSBNEW(PuN)) {
|
||||
fSETWORD(0,RddV,RtV);
|
||||
fSETWORD(1,RddV,RsV);
|
||||
} else {CANCEL;}
|
||||
})
|
||||
|
||||
Q6INSN(C2_ccombinewnewf,"if (!Pu4.new) Rdd32=combine(Rs32,Rt32)",ATTRIBS(A_ARCHV2),
|
||||
"Conditionally combine two words into a register pair",
|
||||
{ if (fLSBNEWNOT(PuN)) {
|
||||
fSETWORD(0,RddV,RtV);
|
||||
fSETWORD(1,RddV,RsV);
|
||||
} else {CANCEL;}
|
||||
})
|
||||
|
||||
Q6INSN(C2_ccombinewt,"if (Pu4) Rdd32=combine(Rs32,Rt32)",ATTRIBS(A_ARCHV2),
|
||||
"Conditionally combine two words into a register pair",
|
||||
{ if (fLSBOLD(PuV)) {
|
||||
fSETWORD(0,RddV,RtV);
|
||||
fSETWORD(1,RddV,RsV);
|
||||
} else {CANCEL;}
|
||||
})
|
||||
|
||||
Q6INSN(C2_ccombinewf,"if (!Pu4) Rdd32=combine(Rs32,Rt32)",ATTRIBS(A_ARCHV2),
|
||||
"Conditionally combine two words into a register pair",
|
||||
{ if (fLSBOLDNOT(PuV)) {
|
||||
fSETWORD(0,RddV,RtV);
|
||||
fSETWORD(1,RddV,RsV);
|
||||
} else {CANCEL;}
|
||||
})
|
||||
|
||||
|
||||
|
||||
Q6INSN(C2_muxii,"Rd32=mux(Pu4,#s8,#S8)",ATTRIBS(A_ARCHV2),
|
||||
"Scalar MUX immediates",
|
||||
{ fIMMEXT(siV); (fLSBOLD(PuV)) ? (RdV=siV):(RdV=SiV); })
|
||||
|
||||
|
||||
|
||||
Q6INSN(C2_muxir,"Rd32=mux(Pu4,Rs32,#s8)",ATTRIBS(A_ARCHV2),
|
||||
"Scalar MUX register immediate",
|
||||
{ fIMMEXT(siV); (fLSBOLD(PuV)) ? (RdV=RsV):(RdV=siV); })
|
||||
|
||||
|
||||
Q6INSN(C2_muxri,"Rd32=mux(Pu4,#s8,Rs32)",ATTRIBS(A_ARCHV2),
|
||||
"Scalar MUX register immediate",
|
||||
{ fIMMEXT(siV); (fLSBOLD(PuV)) ? (RdV=siV):(RdV=RsV); })
|
||||
|
||||
|
||||
|
||||
Q6INSN(C2_vmux,"Rdd32=vmux(Pu4,Rss32,Rtt32)",ATTRIBS(),
|
||||
"Vector MUX",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 8; i++) {
|
||||
fSETBYTE(i,RddV,(fGETBIT(i,PuV)?(fGETBYTE(i,RssV)):(fGETBYTE(i,RttV))));
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(C2_mask,"Rdd32=mask(Pt4)",ATTRIBS(),
|
||||
"Vector Mask Generation",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 8; i++) {
|
||||
fSETBYTE(i,RddV,(fGETBIT(i,PtV)?(0xff):(0x00)));
|
||||
}
|
||||
})
|
||||
|
||||
/* VCMP */
|
||||
|
||||
Q6INSN(A2_vcmpbeq,"Pd4=vcmpb.eq(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 8; i++) {
|
||||
fSETBIT(i,PdV,(fGETBYTE(i,RssV) == fGETBYTE(i,RttV)));
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(A4_vcmpbeqi,"Pd4=vcmpb.eq(Rss32,#u8)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 8; i++) {
|
||||
fSETBIT(i,PdV,(fGETUBYTE(i,RssV) == uiV));
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(A4_vcmpbeq_any,"Pd4=any8(vcmpb.eq(Rss32,Rtt32))",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
PdV = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (fGETBYTE(i,RssV) == fGETBYTE(i,RttV)) PdV = 0xff;
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(A6_vcmpbeq_notany,"Pd4=!any8(vcmpb.eq(Rss32,Rtt32))",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
PdV = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (fGETBYTE(i,RssV) == fGETBYTE(i,RttV)) PdV = 0xff;
|
||||
}
|
||||
PdV = ~PdV;
|
||||
})
|
||||
|
||||
Q6INSN(A2_vcmpbgtu,"Pd4=vcmpb.gtu(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 8; i++) {
|
||||
fSETBIT(i,PdV,(fGETUBYTE(i,RssV) > fGETUBYTE(i,RttV)));
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(A4_vcmpbgtui,"Pd4=vcmpb.gtu(Rss32,#u7)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 8; i++) {
|
||||
fSETBIT(i,PdV,(fGETUBYTE(i,RssV) > uiV));
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(A4_vcmpbgt,"Pd4=vcmpb.gt(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 8; i++) {
|
||||
fSETBIT(i,PdV,(fGETBYTE(i,RssV) > fGETBYTE(i,RttV)));
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(A4_vcmpbgti,"Pd4=vcmpb.gt(Rss32,#s8)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 8; i++) {
|
||||
fSETBIT(i,PdV,(fGETBYTE(i,RssV) > siV));
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
Q6INSN(A4_cmpbeq,"Pd4=cmpb.eq(Rs32,Rt32)",ATTRIBS(),
|
||||
"Compare bytes ",
|
||||
{
|
||||
PdV=f8BITSOF(fGETBYTE(0,RsV) == fGETBYTE(0,RtV));
|
||||
})
|
||||
|
||||
Q6INSN(A4_cmpbeqi,"Pd4=cmpb.eq(Rs32,#u8)",ATTRIBS(),
|
||||
"Compare bytes ",
|
||||
{
|
||||
PdV=f8BITSOF(fGETUBYTE(0,RsV) == uiV);
|
||||
})
|
||||
|
||||
Q6INSN(A4_cmpbgtu,"Pd4=cmpb.gtu(Rs32,Rt32)",ATTRIBS(),
|
||||
"Compare bytes ",
|
||||
{
|
||||
PdV=f8BITSOF(fGETUBYTE(0,RsV) > fGETUBYTE(0,RtV));
|
||||
})
|
||||
|
||||
Q6INSN(A4_cmpbgtui,"Pd4=cmpb.gtu(Rs32,#u7)",ATTRIBS(),
|
||||
"Compare bytes ",
|
||||
{
|
||||
fIMMEXT(uiV);
|
||||
PdV=f8BITSOF(fGETUBYTE(0,RsV) > fCAST4u(uiV));
|
||||
})
|
||||
|
||||
Q6INSN(A4_cmpbgt,"Pd4=cmpb.gt(Rs32,Rt32)",ATTRIBS(),
|
||||
"Compare bytes ",
|
||||
{
|
||||
PdV=f8BITSOF(fGETBYTE(0,RsV) > fGETBYTE(0,RtV));
|
||||
})
|
||||
|
||||
Q6INSN(A4_cmpbgti,"Pd4=cmpb.gt(Rs32,#s8)",ATTRIBS(),
|
||||
"Compare bytes ",
|
||||
{
|
||||
PdV=f8BITSOF(fGETBYTE(0,RsV) > siV);
|
||||
})
|
||||
|
||||
Q6INSN(A2_vcmpheq,"Pd4=vcmph.eq(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 4; i++) {
|
||||
fSETBIT(i*2,PdV, (fGETHALF(i,RssV) == fGETHALF(i,RttV)));
|
||||
fSETBIT(i*2+1,PdV,(fGETHALF(i,RssV) == fGETHALF(i,RttV)));
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(A2_vcmphgt,"Pd4=vcmph.gt(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 4; i++) {
|
||||
fSETBIT(i*2, PdV, (fGETHALF(i,RssV) > fGETHALF(i,RttV)));
|
||||
fSETBIT(i*2+1,PdV, (fGETHALF(i,RssV) > fGETHALF(i,RttV)));
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(A2_vcmphgtu,"Pd4=vcmph.gtu(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 4; i++) {
|
||||
fSETBIT(i*2, PdV, (fGETUHALF(i,RssV) > fGETUHALF(i,RttV)));
|
||||
fSETBIT(i*2+1,PdV, (fGETUHALF(i,RssV) > fGETUHALF(i,RttV)));
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(A4_vcmpheqi,"Pd4=vcmph.eq(Rss32,#s8)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 4; i++) {
|
||||
fSETBIT(i*2,PdV, (fGETHALF(i,RssV) == siV));
|
||||
fSETBIT(i*2+1,PdV,(fGETHALF(i,RssV) == siV));
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(A4_vcmphgti,"Pd4=vcmph.gt(Rss32,#s8)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 4; i++) {
|
||||
fSETBIT(i*2, PdV, (fGETHALF(i,RssV) > siV));
|
||||
fSETBIT(i*2+1,PdV, (fGETHALF(i,RssV) > siV));
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Q6INSN(A4_vcmphgtui,"Pd4=vcmph.gtu(Rss32,#u7)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
for (i = 0; i < 4; i++) {
|
||||
fSETBIT(i*2, PdV, (fGETUHALF(i,RssV) > uiV));
|
||||
fSETBIT(i*2+1,PdV, (fGETUHALF(i,RssV) > uiV));
|
||||
}
|
||||
})
|
||||
|
||||
Q6INSN(A4_cmpheq,"Pd4=cmph.eq(Rs32,Rt32)",ATTRIBS(),
|
||||
"Compare halfwords ",
|
||||
{
|
||||
PdV=f8BITSOF(fGETHALF(0,RsV) == fGETHALF(0,RtV));
|
||||
})
|
||||
|
||||
Q6INSN(A4_cmphgt,"Pd4=cmph.gt(Rs32,Rt32)",ATTRIBS(),
|
||||
"Compare halfwords ",
|
||||
{
|
||||
PdV=f8BITSOF(fGETHALF(0,RsV) > fGETHALF(0,RtV));
|
||||
})
|
||||
|
||||
Q6INSN(A4_cmphgtu,"Pd4=cmph.gtu(Rs32,Rt32)",ATTRIBS(),
|
||||
"Compare halfwords ",
|
||||
{
|
||||
PdV=f8BITSOF(fGETUHALF(0,RsV) > fGETUHALF(0,RtV));
|
||||
})
|
||||
|
||||
Q6INSN(A4_cmpheqi,"Pd4=cmph.eq(Rs32,#s8)",ATTRIBS(),
|
||||
"Compare halfwords ",
|
||||
{
|
||||
fIMMEXT(siV);
|
||||
PdV=f8BITSOF(fGETHALF(0,RsV) == siV);
|
||||
})
|
||||
|
||||
Q6INSN(A4_cmphgti,"Pd4=cmph.gt(Rs32,#s8)",ATTRIBS(),
|
||||
"Compare halfwords ",
|
||||
{
|
||||
fIMMEXT(siV);
|
||||
PdV=f8BITSOF(fGETHALF(0,RsV) > siV);
|
||||
})
|
||||
|
||||
Q6INSN(A4_cmphgtui,"Pd4=cmph.gtu(Rs32,#u7)",ATTRIBS(),
|
||||
"Compare halfwords ",
|
||||
{
|
||||
fIMMEXT(uiV);
|
||||
PdV=f8BITSOF(fGETUHALF(0,RsV) > fCAST4u(uiV));
|
||||
})
|
||||
|
||||
Q6INSN(A2_vcmpweq,"Pd4=vcmpw.eq(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fSETBITS(3,0,PdV,(fGETWORD(0,RssV)==fGETWORD(0,RttV)));
|
||||
fSETBITS(7,4,PdV,(fGETWORD(1,RssV)==fGETWORD(1,RttV)));
|
||||
})
|
||||
|
||||
Q6INSN(A2_vcmpwgt,"Pd4=vcmpw.gt(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fSETBITS(3,0,PdV,(fGETWORD(0,RssV)>fGETWORD(0,RttV)));
|
||||
fSETBITS(7,4,PdV,(fGETWORD(1,RssV)>fGETWORD(1,RttV)));
|
||||
})
|
||||
|
||||
Q6INSN(A2_vcmpwgtu,"Pd4=vcmpw.gtu(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fSETBITS(3,0,PdV,(fGETUWORD(0,RssV)>fGETUWORD(0,RttV)));
|
||||
fSETBITS(7,4,PdV,(fGETUWORD(1,RssV)>fGETUWORD(1,RttV)));
|
||||
})
|
||||
|
||||
Q6INSN(A4_vcmpweqi,"Pd4=vcmpw.eq(Rss32,#s8)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fSETBITS(3,0,PdV,(fGETWORD(0,RssV)==siV));
|
||||
fSETBITS(7,4,PdV,(fGETWORD(1,RssV)==siV));
|
||||
})
|
||||
|
||||
Q6INSN(A4_vcmpwgti,"Pd4=vcmpw.gt(Rss32,#s8)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fSETBITS(3,0,PdV,(fGETWORD(0,RssV)>siV));
|
||||
fSETBITS(7,4,PdV,(fGETWORD(1,RssV)>siV));
|
||||
})
|
||||
|
||||
Q6INSN(A4_vcmpwgtui,"Pd4=vcmpw.gtu(Rss32,#u7)",ATTRIBS(),
|
||||
"Compare elements of two vectors ",
|
||||
{
|
||||
fSETBITS(3,0,PdV,(fGETUWORD(0,RssV)>fCAST4u(uiV)));
|
||||
fSETBITS(7,4,PdV,(fGETUWORD(1,RssV)>fCAST4u(uiV)));
|
||||
})
|
||||
|
||||
Q6INSN(A4_boundscheck_hi,"Pd4=boundscheck(Rss32,Rtt32):raw:hi",ATTRIBS(),
|
||||
"Detect if a register is within bounds",
|
||||
{
|
||||
fHIDE(size4u_t src;)
|
||||
src = fGETUWORD(1,RssV);
|
||||
PdV = f8BITSOF((fCAST4u(src) >= fGETUWORD(0,RttV)) && (fCAST4u(src) < fGETUWORD(1,RttV)));
|
||||
})
|
||||
|
||||
Q6INSN(A4_boundscheck_lo,"Pd4=boundscheck(Rss32,Rtt32):raw:lo",ATTRIBS(),
|
||||
"Detect if a register is within bounds",
|
||||
{
|
||||
fHIDE(size4u_t src;)
|
||||
src = fGETUWORD(0,RssV);
|
||||
PdV = f8BITSOF((fCAST4u(src) >= fGETUWORD(0,RttV)) && (fCAST4u(src) < fGETUWORD(1,RttV)));
|
||||
})
|
||||
|
||||
Q6INSN(A4_tlbmatch,"Pd4=tlbmatch(Rss32,Rt32)",ATTRIBS(),
|
||||
"Detect if a VA/ASID matches a TLB entry",
|
||||
{
|
||||
fHIDE(size4u_t TLBHI; size4u_t TLBLO; size4u_t MASK; size4u_t SIZE;)
|
||||
MASK = 0x07ffffff;
|
||||
TLBLO = fGETUWORD(0,RssV);
|
||||
TLBHI = fGETUWORD(1,RssV);
|
||||
SIZE = fMIN(6,fCL1_4(~fBREV_4(TLBLO)));
|
||||
MASK &= (0xffffffff << 2*SIZE);
|
||||
PdV = f8BITSOF(fGETBIT(31,TLBHI) && ((TLBHI & MASK) == (RtV & MASK)));
|
||||
})
|
||||
|
||||
Q6INSN(C2_tfrpr,"Rd32=Ps4",ATTRIBS(),
|
||||
"Transfer predicate to general register", { RdV = fZXTN(8,32,PsV); })
|
||||
|
||||
Q6INSN(C2_tfrrp,"Pd4=Rs32",ATTRIBS(),
|
||||
"Transfer general register to Predicate", { PdV = fGETUBYTE(0,RsV); })
|
||||
|
||||
Q6INSN(C4_fastcorner9,"Pd4=fastcorner9(Ps4,Pt4)",ATTRIBS(A_CRSLOT23),
|
||||
"Determine whether the predicate sources define a corner",
|
||||
{
|
||||
fHIDE(size4u_t tmp = 0; size4u_t i;)
|
||||
fSETHALF(0,tmp,(PsV<<8)|PtV);
|
||||
fSETHALF(1,tmp,(PsV<<8)|PtV);
|
||||
for (i = 1; i < 9; i++) {
|
||||
tmp &= tmp >> 1;
|
||||
}
|
||||
PdV = f8BITSOF(tmp != 0);
|
||||
})
|
||||
|
||||
Q6INSN(C4_fastcorner9_not,"Pd4=!fastcorner9(Ps4,Pt4)",ATTRIBS(A_CRSLOT23),
|
||||
"Determine whether the predicate sources define a corner",
|
||||
{
|
||||
fHIDE(size4u_t tmp = 0; size4u_t i;)
|
||||
fSETHALF(0,tmp,(PsV<<8)|PtV);
|
||||
fSETHALF(1,tmp,(PsV<<8)|PtV);
|
||||
for (i = 1; i < 9; i++) {
|
||||
tmp &= tmp >> 1;
|
||||
}
|
||||
PdV = f8BITSOF(tmp == 0);
|
||||
})
|
124
target/hexagon/imported/encode.def
Normal file
124
target/hexagon/imported/encode.def
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This just includes all encoding files
|
||||
*/
|
||||
|
||||
#ifndef DEF_FIELD32
|
||||
#define __SELF_DEF_FIELD32
|
||||
#define DEF_FIELD32(...) /* nothing */
|
||||
#endif
|
||||
|
||||
#ifndef DEF_CLASS32
|
||||
#define __SELF_DEF_CLASS32
|
||||
#define DEF_CLASS32(...) /* nothing */
|
||||
#endif
|
||||
|
||||
#ifndef DEF_ANTICLASS32
|
||||
#define __SELF_DEF_ANTICLASS32
|
||||
#define DEF_ANTICLASS32(...) /* nothing */
|
||||
#endif
|
||||
|
||||
#ifndef LEGACY_DEF_ENC32
|
||||
#define __SELF_DEF_LEGACY_DEF_ENC32
|
||||
#define LEGACY_DEF_ENC32(...) /* nothing */
|
||||
#endif
|
||||
|
||||
#ifndef DEF_FIELDROW_DESC32
|
||||
#define __SELF_DEF_FIELDROW_DESC32
|
||||
#define DEF_FIELDROW_DESC32(...) /* nothing */
|
||||
#endif
|
||||
|
||||
#ifndef DEF_ENC32
|
||||
#define __SELF_DEF_ENC32
|
||||
#define DEF_ENC32(...) /* nothing */
|
||||
#endif
|
||||
|
||||
#ifndef DEF_PACKED32
|
||||
#define __SELF_DEF_PACKED32
|
||||
#define DEF_PACKED32(...) /* nothing */
|
||||
#endif
|
||||
|
||||
#ifndef DEF_ENC_SUBINSN
|
||||
#define __SELF_DEF_ENC_SUBINSN
|
||||
#define DEF_ENC_SUBINSN(...) /* nothing */
|
||||
#endif
|
||||
|
||||
#ifndef DEF_EXT_ENC
|
||||
#define __SELF_DEF_EXT_ENC
|
||||
#define DEF_EXT_ENC(...) /* nothing */
|
||||
#endif
|
||||
|
||||
#ifndef DEF_EXT_SPACE
|
||||
#define __SELF_DEF_EXT_SPACE
|
||||
#define DEF_EXT_SPACE(...) /* nothing */
|
||||
#endif
|
||||
|
||||
#include "encode_pp.def"
|
||||
#include "encode_subinsn.def"
|
||||
|
||||
#ifdef __SELF_DEF_FIELD32
|
||||
#undef __SELF_DEF_FIELD32
|
||||
#undef DEF_FIELD32
|
||||
#endif
|
||||
|
||||
#ifdef __SELF_DEF_CLASS32
|
||||
#undef __SELF_DEF_CLASS32
|
||||
#undef DEF_CLASS32
|
||||
#endif
|
||||
|
||||
#ifdef __SELF_DEF_ANTICLASS32
|
||||
#undef __SELF_DEF_ANTICLASS32
|
||||
#undef DEF_ANTICLASS32
|
||||
#endif
|
||||
|
||||
#ifdef __SELF_DEF_LEGACY_DEF_ENC32
|
||||
#undef __SELF_DEF_LEGACY_DEF_ENC32
|
||||
#undef LEGACY_DEF_ENC32
|
||||
#endif
|
||||
|
||||
#ifdef __SELF_DEF_FIELDROW_DESC32
|
||||
#undef __SELF_DEF_FIELDROW_DESC32
|
||||
#undef DEF_FIELDROW_DESC32
|
||||
#endif
|
||||
|
||||
#ifdef __SELF_DEF_ENC32
|
||||
#undef __SELF_DEF_ENC32
|
||||
#undef DEF_ENC32
|
||||
#endif
|
||||
|
||||
#ifdef __SELF_DEF_EXT_SPACE
|
||||
#undef __SELF_DEF_EXT_SPACE
|
||||
#undef DEF_EXT_SPACE
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __SELF_DEF_PACKED32
|
||||
#undef __SELF_DEF_PACKED32
|
||||
#undef DEF_PACKED32
|
||||
#endif
|
||||
|
||||
#ifdef __SELF_DEF_ENC_SUBINSN
|
||||
#undef __SELF_DEF_ENC_SUBINSN
|
||||
#undef DEF_ENC_SUBINSN
|
||||
#endif
|
||||
|
||||
#ifdef __SELF_DEF_EXT_ENC
|
||||
#undef __SELF_DEF_EXT_ENC
|
||||
#undef DEF_EXT_ENC
|
||||
#endif
|
2110
target/hexagon/imported/encode_pp.def
Normal file
2110
target/hexagon/imported/encode_pp.def
Normal file
File diff suppressed because it is too large
Load Diff
149
target/hexagon/imported/encode_subinsn.def
Normal file
149
target/hexagon/imported/encode_subinsn.def
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
/* DEF_ENC_SUBINSN(TAG, CLASS, ENCSTR) */
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************/
|
||||
/* Ld1-type subinsns */
|
||||
/*********************/
|
||||
DEF_ENC_SUBINSN(SL1_loadri_io, SUBINSN_L1, "0iiiissssdddd")
|
||||
DEF_ENC_SUBINSN(SL1_loadrub_io, SUBINSN_L1, "1iiiissssdddd")
|
||||
|
||||
/*********************/
|
||||
/* St1-type subinsns */
|
||||
/*********************/
|
||||
DEF_ENC_SUBINSN(SS1_storew_io, SUBINSN_S1, "0ii iisssstttt")
|
||||
DEF_ENC_SUBINSN(SS1_storeb_io, SUBINSN_S1, "1ii iisssstttt")
|
||||
|
||||
|
||||
/*********************/
|
||||
/* Ld2-type subinsns */
|
||||
/*********************/
|
||||
DEF_ENC_SUBINSN(SL2_loadrh_io, SUBINSN_L2, "00i iissssdddd")
|
||||
DEF_ENC_SUBINSN(SL2_loadruh_io, SUBINSN_L2, "01i iissssdddd")
|
||||
DEF_ENC_SUBINSN(SL2_loadrb_io, SUBINSN_L2, "10i iissssdddd")
|
||||
DEF_ENC_SUBINSN(SL2_loadri_sp, SUBINSN_L2, "111 0iiiiidddd")
|
||||
DEF_ENC_SUBINSN(SL2_loadrd_sp, SUBINSN_L2, "111 10iiiiiddd")
|
||||
|
||||
DEF_ENC_SUBINSN(SL2_deallocframe,SUBINSN_L2, "111 1100---0--")
|
||||
|
||||
DEF_ENC_SUBINSN(SL2_return, SUBINSN_L2, "111 1101---0--")
|
||||
DEF_ENC_SUBINSN(SL2_return_t, SUBINSN_L2, "111 1101---100")
|
||||
DEF_ENC_SUBINSN(SL2_return_f, SUBINSN_L2, "111 1101---101")
|
||||
DEF_ENC_SUBINSN(SL2_return_tnew, SUBINSN_L2, "111 1101---110")
|
||||
DEF_ENC_SUBINSN(SL2_return_fnew, SUBINSN_L2, "111 1101---111")
|
||||
|
||||
DEF_ENC_SUBINSN(SL2_jumpr31, SUBINSN_L2, "111 1111---0--")
|
||||
DEF_ENC_SUBINSN(SL2_jumpr31_t, SUBINSN_L2, "111 1111---100")
|
||||
DEF_ENC_SUBINSN(SL2_jumpr31_f, SUBINSN_L2, "111 1111---101")
|
||||
DEF_ENC_SUBINSN(SL2_jumpr31_tnew,SUBINSN_L2, "111 1111---110")
|
||||
DEF_ENC_SUBINSN(SL2_jumpr31_fnew,SUBINSN_L2, "111 1111---111")
|
||||
|
||||
|
||||
/*********************/
|
||||
/* St2-type subinsns */
|
||||
/*********************/
|
||||
DEF_ENC_SUBINSN(SS2_storeh_io, SUBINSN_S2, "00i iisssstttt")
|
||||
DEF_ENC_SUBINSN(SS2_storew_sp, SUBINSN_S2, "010 0iiiiitttt")
|
||||
DEF_ENC_SUBINSN(SS2_stored_sp, SUBINSN_S2, "010 1iiiiiittt")
|
||||
|
||||
DEF_ENC_SUBINSN(SS2_storewi0, SUBINSN_S2, "100 00ssssiiii")
|
||||
DEF_ENC_SUBINSN(SS2_storewi1, SUBINSN_S2, "100 01ssssiiii")
|
||||
DEF_ENC_SUBINSN(SS2_storebi0, SUBINSN_S2, "100 10ssssiiii")
|
||||
DEF_ENC_SUBINSN(SS2_storebi1, SUBINSN_S2, "100 11ssssiiii")
|
||||
|
||||
DEF_ENC_SUBINSN(SS2_allocframe, SUBINSN_S2, "111 0iiiii----")
|
||||
|
||||
|
||||
|
||||
/*******************/
|
||||
/* A-type subinsns */
|
||||
/*******************/
|
||||
DEF_ENC_SUBINSN(SA1_addi, SUBINSN_A, "00i iiiiiixxxx")
|
||||
DEF_ENC_SUBINSN(SA1_seti, SUBINSN_A, "010 iiiiiidddd")
|
||||
DEF_ENC_SUBINSN(SA1_addsp, SUBINSN_A, "011 iiiiiidddd")
|
||||
|
||||
DEF_ENC_SUBINSN(SA1_tfr, SUBINSN_A, "100 00ssssdddd")
|
||||
DEF_ENC_SUBINSN(SA1_inc, SUBINSN_A, "100 01ssssdddd")
|
||||
DEF_ENC_SUBINSN(SA1_and1, SUBINSN_A, "100 10ssssdddd")
|
||||
DEF_ENC_SUBINSN(SA1_dec, SUBINSN_A, "100 11ssssdddd")
|
||||
|
||||
DEF_ENC_SUBINSN(SA1_sxth, SUBINSN_A, "101 00ssssdddd")
|
||||
DEF_ENC_SUBINSN(SA1_sxtb, SUBINSN_A, "101 01ssssdddd")
|
||||
DEF_ENC_SUBINSN(SA1_zxth, SUBINSN_A, "101 10ssssdddd")
|
||||
DEF_ENC_SUBINSN(SA1_zxtb, SUBINSN_A, "101 11ssssdddd")
|
||||
|
||||
|
||||
DEF_ENC_SUBINSN(SA1_addrx, SUBINSN_A, "110 00ssssxxxx")
|
||||
DEF_ENC_SUBINSN(SA1_cmpeqi, SUBINSN_A, "110 01ssss--ii")
|
||||
DEF_ENC_SUBINSN(SA1_setin1, SUBINSN_A, "110 1--0--dddd")
|
||||
DEF_ENC_SUBINSN(SA1_clrtnew, SUBINSN_A, "110 1--100dddd")
|
||||
DEF_ENC_SUBINSN(SA1_clrfnew, SUBINSN_A, "110 1--101dddd")
|
||||
DEF_ENC_SUBINSN(SA1_clrt, SUBINSN_A, "110 1--110dddd")
|
||||
DEF_ENC_SUBINSN(SA1_clrf, SUBINSN_A, "110 1--111dddd")
|
||||
|
||||
|
||||
DEF_ENC_SUBINSN(SA1_combine0i, SUBINSN_A, "111 -0-ii00ddd")
|
||||
DEF_ENC_SUBINSN(SA1_combine1i, SUBINSN_A, "111 -0-ii01ddd")
|
||||
DEF_ENC_SUBINSN(SA1_combine2i, SUBINSN_A, "111 -0-ii10ddd")
|
||||
DEF_ENC_SUBINSN(SA1_combine3i, SUBINSN_A, "111 -0-ii11ddd")
|
||||
DEF_ENC_SUBINSN(SA1_combinezr, SUBINSN_A, "111 -1ssss0ddd")
|
||||
DEF_ENC_SUBINSN(SA1_combinerz, SUBINSN_A, "111 -1ssss1ddd")
|
||||
|
||||
|
||||
|
||||
|
||||
/* maybe R=cmpeq ? */
|
||||
|
||||
|
||||
/* Add a group of NCJ: if (R.new==#0) jump:hint #r9 */
|
||||
/* Add a group of NCJ: if (R.new!=#0) jump:hint #r9 */
|
||||
/* NCJ goes with LD1, LD2 */
|
||||
|
||||
|
||||
|
||||
|
||||
DEF_FIELD32("---! !!!! !!!!!!!! EE------ --------",SUBFIELD_B_SLOT1,"B: Slot1 Instruction")
|
||||
DEF_FIELD32("---- ---- -------- EE-!!!!! !!!!!!!!",SUBFIELD_A_SLOT0,"A: Slot0 Instruction")
|
||||
|
||||
|
||||
/* DEF_PACKED32(TAG, CLASSA, CLASSB, ENCSTR) */
|
||||
|
||||
DEF_PACKED32(P2_PACKED_L1_L1, SUBINSN_L1, SUBINSN_L1, "000B BBBB BBBB BBBB EE0A AAAA AAAA AAAA")
|
||||
DEF_PACKED32(P2_PACKED_L1_L2, SUBINSN_L2, SUBINSN_L1, "000B BBBB BBBB BBBB EE1A AAAA AAAA AAAA")
|
||||
DEF_PACKED32(P2_PACKED_L2_L2, SUBINSN_L2, SUBINSN_L2, "001B BBBB BBBB BBBB EE0A AAAA AAAA AAAA")
|
||||
DEF_PACKED32(P2_PACKED_A_A, SUBINSN_A, SUBINSN_A, "001B BBBB BBBB BBBB EE1A AAAA AAAA AAAA")
|
||||
|
||||
DEF_PACKED32(P2_PACKED_L1_A, SUBINSN_L1, SUBINSN_A, "010B BBBB BBBB BBBB EE0A AAAA AAAA AAAA")
|
||||
DEF_PACKED32(P2_PACKED_L2_A, SUBINSN_L2, SUBINSN_A, "010B BBBB BBBB BBBB EE1A AAAA AAAA AAAA")
|
||||
DEF_PACKED32(P2_PACKED_S1_A, SUBINSN_S1, SUBINSN_A, "011B BBBB BBBB BBBB EE0A AAAA AAAA AAAA")
|
||||
DEF_PACKED32(P2_PACKED_S2_A, SUBINSN_S2, SUBINSN_A, "011B BBBB BBBB BBBB EE1A AAAA AAAA AAAA")
|
||||
|
||||
DEF_PACKED32(P2_PACKED_S1_L1, SUBINSN_S1, SUBINSN_L1, "100B BBBB BBBB BBBB EE0A AAAA AAAA AAAA")
|
||||
DEF_PACKED32(P2_PACKED_S1_L2, SUBINSN_S1, SUBINSN_L2, "100B BBBB BBBB BBBB EE1A AAAA AAAA AAAA")
|
||||
DEF_PACKED32(P2_PACKED_S1_S1, SUBINSN_S1, SUBINSN_S1, "101B BBBB BBBB BBBB EE0A AAAA AAAA AAAA")
|
||||
DEF_PACKED32(P2_PACKED_S1_S2, SUBINSN_S2, SUBINSN_S1, "101B BBBB BBBB BBBB EE1A AAAA AAAA AAAA")
|
||||
|
||||
DEF_PACKED32(P2_PACKED_S2_L1, SUBINSN_S2, SUBINSN_L1, "110B BBBB BBBB BBBB EE0A AAAA AAAA AAAA")
|
||||
DEF_PACKED32(P2_PACKED_S2_L2, SUBINSN_S2, SUBINSN_L2, "110B BBBB BBBB BBBB EE1A AAAA AAAA AAAA")
|
||||
DEF_PACKED32(P2_PACKED_S2_S2, SUBINSN_S2, SUBINSN_S2, "111B BBBB BBBB BBBB EE0A AAAA AAAA AAAA")
|
||||
|
||||
DEF_PACKED32(P2_PACKED_RESERVED, SUBINSN_INVALID, SUBINSN_INVALID, "111B BBBB BBBB BBBB EE1A AAAA AAAA AAAA")
|
312
target/hexagon/imported/float.idef
Normal file
312
target/hexagon/imported/float.idef
Normal file
@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Floating-Point Instructions
|
||||
*/
|
||||
|
||||
/*************************************/
|
||||
/* Scalar FP */
|
||||
/*************************************/
|
||||
Q6INSN(F2_sfadd,"Rd32=sfadd(Rs32,Rt32)",ATTRIBS(),
|
||||
"Floating-Point Add",
|
||||
{ RdV=fUNFLOAT(fFLOAT(RsV)+fFLOAT(RtV));})
|
||||
|
||||
Q6INSN(F2_sfsub,"Rd32=sfsub(Rs32,Rt32)",ATTRIBS(),
|
||||
"Floating-Point Subtract",
|
||||
{ RdV=fUNFLOAT(fFLOAT(RsV)-fFLOAT(RtV));})
|
||||
|
||||
Q6INSN(F2_sfmpy,"Rd32=sfmpy(Rs32,Rt32)",ATTRIBS(),
|
||||
"Floating-Point Multiply",
|
||||
{ RdV=fUNFLOAT(fSFMPY(fFLOAT(RsV),fFLOAT(RtV)));})
|
||||
|
||||
Q6INSN(F2_sffma,"Rx32+=sfmpy(Rs32,Rt32)",ATTRIBS(),
|
||||
"Floating-Point Fused Multiply Add",
|
||||
{ RxV=fUNFLOAT(fFMAF(fFLOAT(RsV),fFLOAT(RtV),fFLOAT(RxV)));})
|
||||
|
||||
Q6INSN(F2_sffma_sc,"Rx32+=sfmpy(Rs32,Rt32,Pu4):scale",ATTRIBS(),
|
||||
"Floating-Point Fused Multiply Add w/ Additional Scaling (2**Pu)",
|
||||
{
|
||||
fHIDE(size4s_t tmp;)
|
||||
fCHECKSFNAN3(RxV,RxV,RsV,RtV);
|
||||
tmp=fUNFLOAT(fFMAFX(fFLOAT(RsV),fFLOAT(RtV),fFLOAT(RxV),PuV));
|
||||
if (!((fFLOAT(RxV) == 0.0) && fISZEROPROD(fFLOAT(RsV),fFLOAT(RtV)))) RxV = tmp;
|
||||
})
|
||||
|
||||
Q6INSN(F2_sffms,"Rx32-=sfmpy(Rs32,Rt32)",ATTRIBS(),
|
||||
"Floating-Point Fused Multiply Add",
|
||||
{ RxV=fUNFLOAT(fFMAF(-fFLOAT(RsV),fFLOAT(RtV),fFLOAT(RxV))); })
|
||||
|
||||
Q6INSN(F2_sffma_lib,"Rx32+=sfmpy(Rs32,Rt32):lib",ATTRIBS(),
|
||||
"Floating-Point Fused Multiply Add for Library Routines",
|
||||
{ fFPSETROUND_NEAREST(); fHIDE(int infinp; int infminusinf; size4s_t tmp;)
|
||||
infminusinf = ((isinf(fFLOAT(RxV))) &&
|
||||
(fISINFPROD(fFLOAT(RsV),fFLOAT(RtV))) &&
|
||||
(fGETBIT(31,RsV ^ RxV ^ RtV) != 0));
|
||||
infinp = (isinf(fFLOAT(RxV))) || (isinf(fFLOAT(RtV))) || (isinf(fFLOAT(RsV)));
|
||||
fCHECKSFNAN3(RxV,RxV,RsV,RtV);
|
||||
tmp=fUNFLOAT(fFMAF(fFLOAT(RsV),fFLOAT(RtV),fFLOAT(RxV)));
|
||||
if (!((fFLOAT(RxV) == 0.0) && fISZEROPROD(fFLOAT(RsV),fFLOAT(RtV)))) RxV = tmp;
|
||||
fFPCANCELFLAGS();
|
||||
if (isinf(fFLOAT(RxV)) && !infinp) RxV = RxV - 1;
|
||||
if (infminusinf) RxV = 0;
|
||||
})
|
||||
|
||||
Q6INSN(F2_sffms_lib,"Rx32-=sfmpy(Rs32,Rt32):lib",ATTRIBS(),
|
||||
"Floating-Point Fused Multiply Add for Library Routines",
|
||||
{ fFPSETROUND_NEAREST(); fHIDE(int infinp; int infminusinf; size4s_t tmp;)
|
||||
infminusinf = ((isinf(fFLOAT(RxV))) &&
|
||||
(fISINFPROD(fFLOAT(RsV),fFLOAT(RtV))) &&
|
||||
(fGETBIT(31,RsV ^ RxV ^ RtV) == 0));
|
||||
infinp = (isinf(fFLOAT(RxV))) || (isinf(fFLOAT(RtV))) || (isinf(fFLOAT(RsV)));
|
||||
fCHECKSFNAN3(RxV,RxV,RsV,RtV);
|
||||
tmp=fUNFLOAT(fFMAF(-fFLOAT(RsV),fFLOAT(RtV),fFLOAT(RxV)));
|
||||
if (!((fFLOAT(RxV) == 0.0) && fISZEROPROD(fFLOAT(RsV),fFLOAT(RtV)))) RxV = tmp;
|
||||
fFPCANCELFLAGS();
|
||||
if (isinf(fFLOAT(RxV)) && !infinp) RxV = RxV - 1;
|
||||
if (infminusinf) RxV = 0;
|
||||
})
|
||||
|
||||
|
||||
Q6INSN(F2_sfcmpeq,"Pd4=sfcmp.eq(Rs32,Rt32)",ATTRIBS(),
|
||||
"Floating Point Compare for Equal",
|
||||
{PdV=f8BITSOF(fFLOAT(RsV)==fFLOAT(RtV));})
|
||||
|
||||
Q6INSN(F2_sfcmpgt,"Pd4=sfcmp.gt(Rs32,Rt32)",ATTRIBS(),
|
||||
"Floating-Point Compare for Greater Than",
|
||||
{PdV=f8BITSOF(fFLOAT(RsV)>fFLOAT(RtV));})
|
||||
|
||||
/* cmpge is not the same as !cmpgt(swapops) in IEEE */
|
||||
|
||||
Q6INSN(F2_sfcmpge,"Pd4=sfcmp.ge(Rs32,Rt32)",ATTRIBS(),
|
||||
"Floating-Point Compare for Greater Than / Equal To",
|
||||
{PdV=f8BITSOF(fFLOAT(RsV)>=fFLOAT(RtV));})
|
||||
|
||||
/* Everyone seems to have this... */
|
||||
|
||||
Q6INSN(F2_sfcmpuo,"Pd4=sfcmp.uo(Rs32,Rt32)",ATTRIBS(),
|
||||
"Floating-Point Compare for Unordered",
|
||||
{PdV=f8BITSOF(isunordered(fFLOAT(RsV),fFLOAT(RtV)));})
|
||||
|
||||
|
||||
Q6INSN(F2_sfmax,"Rd32=sfmax(Rs32,Rt32)",ATTRIBS(),
|
||||
"Maximum of Floating-Point values",
|
||||
{ RdV = fUNFLOAT(fSF_MAX(fFLOAT(RsV),fFLOAT(RtV))); })
|
||||
|
||||
Q6INSN(F2_sfmin,"Rd32=sfmin(Rs32,Rt32)",ATTRIBS(),
|
||||
"Minimum of Floating-Point values",
|
||||
{ RdV = fUNFLOAT(fSF_MIN(fFLOAT(RsV),fFLOAT(RtV))); })
|
||||
|
||||
|
||||
Q6INSN(F2_sfclass,"Pd4=sfclass(Rs32,#u5)",ATTRIBS(),
|
||||
"Classify Floating-Point Value",
|
||||
{
|
||||
fHIDE(int class;)
|
||||
PdV = 0;
|
||||
class = fpclassify(fFLOAT(RsV));
|
||||
/* Is the value zero? */
|
||||
if (fGETBIT(0,uiV) && (class == FP_ZERO)) PdV = 0xff;
|
||||
if (fGETBIT(1,uiV) && (class == FP_NORMAL)) PdV = 0xff;
|
||||
if (fGETBIT(2,uiV) && (class == FP_SUBNORMAL)) PdV = 0xff;
|
||||
if (fGETBIT(3,uiV) && (class == FP_INFINITE)) PdV = 0xff;
|
||||
if (fGETBIT(4,uiV) && (class == FP_NAN)) PdV = 0xff;
|
||||
fFPCANCELFLAGS();
|
||||
})
|
||||
|
||||
/* Range: +/- (1.0 .. 1+(63/64)) * 2**(-6 .. +9) */
|
||||
/* More immediate bits should probably be used for more precision? */
|
||||
|
||||
Q6INSN(F2_sfimm_p,"Rd32=sfmake(#u10):pos",ATTRIBS(),
|
||||
"Make Floating Point Value",
|
||||
{
|
||||
RdV = (127 - 6) << 23;
|
||||
RdV += uiV << 17;
|
||||
})
|
||||
|
||||
Q6INSN(F2_sfimm_n,"Rd32=sfmake(#u10):neg",ATTRIBS(),
|
||||
"Make Floating Point Value",
|
||||
{
|
||||
RdV = (127 - 6) << 23;
|
||||
RdV += (uiV << 17);
|
||||
RdV |= (1 << 31);
|
||||
})
|
||||
|
||||
|
||||
Q6INSN(F2_sffixupn,"Rd32=sffixupn(Rs32,Rt32)",ATTRIBS(),
|
||||
"Fix Up Numerator",
|
||||
{
|
||||
fHIDE(int adjust;)
|
||||
fSF_RECIP_COMMON(RsV,RtV,RdV,adjust);
|
||||
RdV = RsV;
|
||||
})
|
||||
|
||||
Q6INSN(F2_sffixupd,"Rd32=sffixupd(Rs32,Rt32)",ATTRIBS(),
|
||||
"Fix Up Denominator",
|
||||
{
|
||||
fHIDE(int adjust;)
|
||||
fSF_RECIP_COMMON(RsV,RtV,RdV,adjust);
|
||||
RdV = RtV;
|
||||
})
|
||||
|
||||
Q6INSN(F2_sffixupr,"Rd32=sffixupr(Rs32)",ATTRIBS(),
|
||||
"Fix Up Radicand",
|
||||
{
|
||||
fHIDE(int adjust;)
|
||||
fSF_INVSQRT_COMMON(RsV,RdV,adjust);
|
||||
RdV = RsV;
|
||||
})
|
||||
|
||||
/*************************************/
|
||||
/* Scalar DP */
|
||||
/*************************************/
|
||||
Q6INSN(F2_dfadd,"Rdd32=dfadd(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Floating-Point Add",
|
||||
{ RddV=fUNDOUBLE(fDOUBLE(RssV)+fDOUBLE(RttV));})
|
||||
|
||||
Q6INSN(F2_dfsub,"Rdd32=dfsub(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Floating-Point Subtract",
|
||||
{ RddV=fUNDOUBLE(fDOUBLE(RssV)-fDOUBLE(RttV));})
|
||||
|
||||
Q6INSN(F2_dfmax,"Rdd32=dfmax(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Maximum of Floating-Point values",
|
||||
{ RddV = fUNDOUBLE(fDF_MAX(fDOUBLE(RssV),fDOUBLE(RttV))); })
|
||||
|
||||
Q6INSN(F2_dfmin,"Rdd32=dfmin(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Minimum of Floating-Point values",
|
||||
{ RddV = fUNDOUBLE(fDF_MIN(fDOUBLE(RssV),fDOUBLE(RttV))); })
|
||||
|
||||
Q6INSN(F2_dfmpyfix,"Rdd32=dfmpyfix(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Fix Up Multiplicand for Multiplication",
|
||||
{
|
||||
if (fDF_ISDENORM(RssV) && fDF_ISBIG(RttV) && fDF_ISNORMAL(RttV)) RddV = fUNDOUBLE(fDOUBLE(RssV) * 0x1.0p52);
|
||||
else if (fDF_ISDENORM(RttV) && fDF_ISBIG(RssV) && fDF_ISNORMAL(RssV)) RddV = fUNDOUBLE(fDOUBLE(RssV) * 0x1.0p-52);
|
||||
else RddV = RssV;
|
||||
})
|
||||
|
||||
Q6INSN(F2_dfmpyll,"Rdd32=dfmpyll(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Multiply low*low and shift off low 32 bits into sticky (in MSB)",
|
||||
{
|
||||
fHIDE(size8u_t prod;)
|
||||
prod = fMPY32UU(fGETUWORD(0,RssV),fGETUWORD(0,RttV));
|
||||
RddV = (prod >> 32) << 1;
|
||||
if (fGETUWORD(0,prod) != 0) fSETBIT(0,RddV,1);
|
||||
})
|
||||
|
||||
Q6INSN(F2_dfmpylh,"Rxx32+=dfmpylh(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Multiply low*high and accumulate",
|
||||
{
|
||||
RxxV += (fGETUWORD(0,RssV) * (0x00100000 | fZXTN(20,64,fGETUWORD(1,RttV)))) << 1;
|
||||
})
|
||||
|
||||
Q6INSN(F2_dfmpyhh,"Rxx32+=dfmpyhh(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Multiply high*high and accumulate with L*H value",
|
||||
{
|
||||
RxxV = fUNDOUBLE(fDF_MPY_HH(fDOUBLE(RssV),fDOUBLE(RttV),RxxV));
|
||||
})
|
||||
|
||||
|
||||
|
||||
Q6INSN(F2_dfcmpeq,"Pd4=dfcmp.eq(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Floating Point Compare for Equal",
|
||||
{PdV=f8BITSOF(fDOUBLE(RssV)==fDOUBLE(RttV));})
|
||||
|
||||
Q6INSN(F2_dfcmpgt,"Pd4=dfcmp.gt(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Floating-Point Compare for Greater Than",
|
||||
{PdV=f8BITSOF(fDOUBLE(RssV)>fDOUBLE(RttV));})
|
||||
|
||||
|
||||
/* cmpge is not the same as !cmpgt(swapops) in IEEE */
|
||||
|
||||
Q6INSN(F2_dfcmpge,"Pd4=dfcmp.ge(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Floating-Point Compare for Greater Than / Equal To",
|
||||
{PdV=f8BITSOF(fDOUBLE(RssV)>=fDOUBLE(RttV));})
|
||||
|
||||
/* Everyone seems to have this... */
|
||||
|
||||
Q6INSN(F2_dfcmpuo,"Pd4=dfcmp.uo(Rss32,Rtt32)",ATTRIBS(),
|
||||
"Floating-Point Compare for Unordered",
|
||||
{PdV=f8BITSOF(isunordered(fDOUBLE(RssV),fDOUBLE(RttV)));})
|
||||
|
||||
|
||||
Q6INSN(F2_dfclass,"Pd4=dfclass(Rss32,#u5)",ATTRIBS(),
|
||||
"Classify Floating-Point Value",
|
||||
{
|
||||
fHIDE(int class;)
|
||||
PdV = 0;
|
||||
class = fpclassify(fDOUBLE(RssV));
|
||||
/* Is the value zero? */
|
||||
if (fGETBIT(0,uiV) && (class == FP_ZERO)) PdV = 0xff;
|
||||
if (fGETBIT(1,uiV) && (class == FP_NORMAL)) PdV = 0xff;
|
||||
if (fGETBIT(2,uiV) && (class == FP_SUBNORMAL)) PdV = 0xff;
|
||||
if (fGETBIT(3,uiV) && (class == FP_INFINITE)) PdV = 0xff;
|
||||
if (fGETBIT(4,uiV) && (class == FP_NAN)) PdV = 0xff;
|
||||
fFPCANCELFLAGS();
|
||||
})
|
||||
|
||||
|
||||
/* Range: +/- (1.0 .. 1+(63/64)) * 2**(-6 .. +9) */
|
||||
/* More immediate bits should probably be used for more precision? */
|
||||
|
||||
Q6INSN(F2_dfimm_p,"Rdd32=dfmake(#u10):pos",ATTRIBS(),
|
||||
"Make Floating Point Value",
|
||||
{
|
||||
RddV = (1023ULL - 6) << 52;
|
||||
RddV += (fHIDE((size8u_t))uiV) << 46;
|
||||
})
|
||||
|
||||
Q6INSN(F2_dfimm_n,"Rdd32=dfmake(#u10):neg",ATTRIBS(),
|
||||
"Make Floating Point Value",
|
||||
{
|
||||
RddV = (1023ULL - 6) << 52;
|
||||
RddV += (fHIDE((size8u_t))uiV) << 46;
|
||||
RddV |= ((1ULL) << 63);
|
||||
})
|
||||
|
||||
|
||||
/* CONVERSION */
|
||||
|
||||
#define CONVERT(TAG,DEST,DESTV,SRC,SRCV,OUTCAST,OUTTYPE,INCAST,INTYPE,MODETAG,MODESYN,MODEBEH) \
|
||||
Q6INSN(F2_conv_##TAG##MODETAG,#DEST"=convert_"#TAG"("#SRC")"#MODESYN,ATTRIBS(), \
|
||||
"Floating point format conversion", \
|
||||
{ MODEBEH DESTV = OUTCAST(conv_##INTYPE##_to_##OUTTYPE(INCAST(SRCV))); })
|
||||
|
||||
CONVERT(sf2df,Rdd32,RddV,Rs32,RsV,fUNDOUBLE,df,fFLOAT,sf,,,)
|
||||
CONVERT(df2sf,Rd32,RdV,Rss32,RssV,fUNFLOAT,sf,fDOUBLE,df,,,)
|
||||
|
||||
#define ALLINTDST(TAGSTART,SRC,SRCV,INCAST,INTYPE,MODETAG,MODESYN,MODEBEH) \
|
||||
CONVERT(TAGSTART##uw,Rd32,RdV,SRC,SRCV,fCAST4u,4u,INCAST,INTYPE,MODETAG,MODESYN,MODEBEH) \
|
||||
CONVERT(TAGSTART##w,Rd32,RdV,SRC,SRCV,fCAST4s,4s,INCAST,INTYPE,MODETAG,MODESYN,MODEBEH) \
|
||||
CONVERT(TAGSTART##ud,Rdd32,RddV,SRC,SRCV,fCAST8u,8u,INCAST,INTYPE,MODETAG,MODESYN,MODEBEH) \
|
||||
CONVERT(TAGSTART##d,Rdd32,RddV,SRC,SRCV,fCAST8s,8s,INCAST,INTYPE,MODETAG,MODESYN,MODEBEH)
|
||||
|
||||
#define ALLFPDST(TAGSTART,SRC,SRCV,INCAST,INTYPE,MODETAG,MODESYN,MODEBEH) \
|
||||
CONVERT(TAGSTART##sf,Rd32,RdV,SRC,SRCV,fUNFLOAT,sf,INCAST,INTYPE,MODETAG,MODESYN,MODEBEH) \
|
||||
CONVERT(TAGSTART##df,Rdd32,RddV,SRC,SRCV,fUNDOUBLE,df,INCAST,INTYPE,MODETAG,MODESYN,MODEBEH)
|
||||
|
||||
#define ALLINTSRC(GEN,MODETAG,MODESYN,MODEBEH) \
|
||||
GEN(uw##2,Rs32,RsV,fCAST4u,4u,MODETAG,MODESYN,MODEBEH) \
|
||||
GEN(w##2,Rs32,RsV,fCAST4s,4s,MODETAG,MODESYN,MODEBEH) \
|
||||
GEN(ud##2,Rss32,RssV,fCAST8u,8u,MODETAG,MODESYN,MODEBEH) \
|
||||
GEN(d##2,Rss32,RssV,fCAST8s,8s,MODETAG,MODESYN,MODEBEH)
|
||||
|
||||
#define ALLFPSRC(GEN,MODETAG,MODESYN,MODEBEH) \
|
||||
GEN(sf##2,Rs32,RsV,fFLOAT,sf,MODETAG,MODESYN,MODEBEH) \
|
||||
GEN(df##2,Rss32,RssV,fDOUBLE,df,MODETAG,MODESYN,MODEBEH)
|
||||
|
||||
ALLINTSRC(ALLFPDST,,,)
|
||||
ALLFPSRC(ALLINTDST,,,)
|
||||
ALLFPSRC(ALLINTDST,_chop,:chop,fFPSETROUND_CHOP();)
|
51
target/hexagon/imported/iclass.def
Normal file
51
target/hexagon/imported/iclass.def
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* DEF_*(TYPE,SLOTS,UNITS) */
|
||||
DEF_PP_ICLASS32(EXTENDER,0123,LDST|SUNIT|MUNIT) /* 0 */
|
||||
DEF_PP_ICLASS32(CJ,0123,CTRLFLOW) /* 1 */
|
||||
DEF_PP_ICLASS32(NCJ,01,LDST|CTRLFLOW) /* 2 */
|
||||
DEF_PP_ICLASS32(V4LDST,01,LDST) /* 3 */
|
||||
DEF_PP_ICLASS32(V2LDST,01,LDST) /* 4 */
|
||||
DEF_PP_ICLASS32(J,0123,CTRLFLOW) /* 5 */
|
||||
DEF_PP_ICLASS32(CR,3,SUNIT) /* 6 */
|
||||
DEF_PP_ICLASS32(ALU32_2op,0123,LDST|SUNIT|MUNIT) /* 7 */
|
||||
DEF_PP_ICLASS32(S_2op,23,SUNIT|MUNIT) /* 8 */
|
||||
DEF_PP_ICLASS32(LD,01,LDST) /* 9 */
|
||||
DEF_PP_ICLASS32(ST,01,LDST) /* 10 */
|
||||
DEF_PP_ICLASS32(ALU32_ADDI,0123,LDST|SUNIT|MUNIT) /* 11 */
|
||||
DEF_PP_ICLASS32(S_3op,23,SUNIT|MUNIT) /* 12 */
|
||||
DEF_PP_ICLASS32(ALU64,23,SUNIT|MUNIT) /* 13 */
|
||||
DEF_PP_ICLASS32(M,23,SUNIT|MUNIT) /* 14 */
|
||||
DEF_PP_ICLASS32(ALU32_3op,0123,LDST|SUNIT|MUNIT) /* 15 */
|
||||
|
||||
DEF_EE_ICLASS32(EE0,01,INVALID) /* 0 */
|
||||
DEF_EE_ICLASS32(EE1,01,INVALID) /* 1 */
|
||||
DEF_EE_ICLASS32(EE2,01,INVALID) /* 2 */
|
||||
DEF_EE_ICLASS32(EE3,01,INVALID) /* 3 */
|
||||
DEF_EE_ICLASS32(EE4,01,INVALID) /* 4 */
|
||||
DEF_EE_ICLASS32(EE5,01,INVALID) /* 5 */
|
||||
DEF_EE_ICLASS32(EE6,01,INVALID) /* 6 */
|
||||
DEF_EE_ICLASS32(EE7,01,INVALID) /* 7 */
|
||||
DEF_EE_ICLASS32(EE8,01,INVALID) /* 8 */
|
||||
DEF_EE_ICLASS32(EE9,01,INVALID) /* 9 */
|
||||
DEF_EE_ICLASS32(EEA,01,INVALID) /* 10 */
|
||||
DEF_EE_ICLASS32(EEB,01,INVALID) /* 11 */
|
||||
DEF_EE_ICLASS32(EEC,01,INVALID) /* 12 */
|
||||
DEF_EE_ICLASS32(EED,01,INVALID) /* 13 */
|
||||
DEF_EE_ICLASS32(EEE,01,INVALID) /* 14 */
|
||||
DEF_EE_ICLASS32(EEF,01,INVALID) /* 15 */
|
286
target/hexagon/imported/ldst.idef
Normal file
286
target/hexagon/imported/ldst.idef
Normal file
@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Load and Store instruction definitions
|
||||
*/
|
||||
|
||||
/* The set of addressing modes standard to all Load instructions */
|
||||
#define STD_LD_AMODES(TAG,OPER,DESCR,ATTRIB,SHFT,SEMANTICS,SCALE)\
|
||||
Q6INSN(L2_##TAG##_io, OPER"(Rs32+#s11:"SHFT")", ATTRIB,DESCR,{fIMMEXT(siV); fEA_RI(RsV,siV); SEMANTICS; })\
|
||||
Q6INSN(L4_##TAG##_ur, OPER"(Rt32<<#u2+#U6)", ATTRIB,DESCR,{fMUST_IMMEXT(UiV); fEA_IRs(UiV,RtV,uiV); SEMANTICS;})\
|
||||
Q6INSN(L4_##TAG##_ap, OPER"(Re32=#U6)", ATTRIB,DESCR,{fMUST_IMMEXT(UiV); fEA_IMM(UiV); SEMANTICS; ReV=UiV; })\
|
||||
Q6INSN(L2_##TAG##_pr, OPER"(Rx32++Mu2)", ATTRIB,DESCR,{fEA_REG(RxV); fPM_M(RxV,MuV); SEMANTICS;})\
|
||||
Q6INSN(L2_##TAG##_pi, OPER"(Rx32++#s4:"SHFT")", ATTRIB,DESCR,{fEA_REG(RxV); fPM_I(RxV,siV); SEMANTICS;})\
|
||||
|
||||
/* The set of 32-bit load instructions */
|
||||
STD_LD_AMODES(loadrub,"Rd32=memub","Load Unsigned Byte",ATTRIBS(A_LOAD),"0",fLOAD(1,1,u,EA,RdV),0)
|
||||
STD_LD_AMODES(loadrb, "Rd32=memb", "Load signed Byte",ATTRIBS(A_LOAD),"0",fLOAD(1,1,s,EA,RdV),0)
|
||||
STD_LD_AMODES(loadruh,"Rd32=memuh","Load unsigned Half integer",ATTRIBS(A_LOAD),"1",fLOAD(1,2,u,EA,RdV),1)
|
||||
STD_LD_AMODES(loadrh, "Rd32=memh", "Load signed Half integer",ATTRIBS(A_LOAD),"1",fLOAD(1,2,s,EA,RdV),1)
|
||||
STD_LD_AMODES(loadri, "Rd32=memw", "Load Word",ATTRIBS(A_LOAD),"2",fLOAD(1,4,u,EA,RdV),2)
|
||||
STD_LD_AMODES(loadrd, "Rdd32=memd","Load Double integer",ATTRIBS(A_LOAD),"3",fLOAD(1,8,u,EA,RddV),3)
|
||||
|
||||
/* The set of addressing modes standard to all Store instructions */
|
||||
#define STD_ST_AMODES(TAG,DEST,OPER,DESCR,ATTRIB,SHFT,SEMANTICS,SCALE)\
|
||||
Q6INSN(S2_##TAG##_io, OPER"(Rs32+#s11:"SHFT")="DEST, ATTRIB,DESCR,{fIMMEXT(siV); fEA_RI(RsV,siV); SEMANTICS; })\
|
||||
Q6INSN(S2_##TAG##_pi, OPER"(Rx32++#s4:"SHFT")="DEST, ATTRIB,DESCR,{fEA_REG(RxV); fPM_I(RxV,siV); SEMANTICS; })\
|
||||
Q6INSN(S4_##TAG##_ap, OPER"(Re32=#U6)="DEST, ATTRIB,DESCR,{fMUST_IMMEXT(UiV); fEA_IMM(UiV); SEMANTICS; ReV=UiV; })\
|
||||
Q6INSN(S2_##TAG##_pr, OPER"(Rx32++Mu2)="DEST, ATTRIB,DESCR,{fEA_REG(RxV); fPM_M(RxV,MuV); SEMANTICS; })\
|
||||
Q6INSN(S4_##TAG##_ur, OPER"(Ru32<<#u2+#U6)="DEST, ATTRIB,DESCR,{fMUST_IMMEXT(UiV); fEA_IRs(UiV,RuV,uiV); SEMANTICS;})\
|
||||
|
||||
|
||||
/* The set of 32-bit store instructions */
|
||||
STD_ST_AMODES(storerb, "Rt32", "memb","Store Byte",ATTRIBS(A_STORE),"0",fSTORE(1,1,EA,fGETBYTE(0,RtV)),0)
|
||||
STD_ST_AMODES(storerh, "Rt32", "memh","Store Half integer",ATTRIBS(A_STORE),"1",fSTORE(1,2,EA,fGETHALF(0,RtV)),1)
|
||||
STD_ST_AMODES(storerf, "Rt.H32", "memh","Store Upper Half integer",ATTRIBS(A_STORE),"1",fSTORE(1,2,EA,fGETHALF(1,RtV)),1)
|
||||
STD_ST_AMODES(storeri, "Rt32", "memw","Store Word",ATTRIBS(A_STORE),"2",fSTORE(1,4,EA,RtV),2)
|
||||
STD_ST_AMODES(storerd, "Rtt32","memd","Store Double integer",ATTRIBS(A_STORE),"3",fSTORE(1,8,EA,RttV),3)
|
||||
STD_ST_AMODES(storerinew, "Nt8.new", "memw","Store Word",ATTRIBS(A_STORE),"2",fSTORE(1,4,EA,fNEWREG_ST(NtN)),2)
|
||||
STD_ST_AMODES(storerbnew, "Nt8.new", "memb","Store Byte",ATTRIBS(A_STORE),"0",fSTORE(1,1,EA,fGETBYTE(0,fNEWREG_ST(NtN))),0)
|
||||
STD_ST_AMODES(storerhnew, "Nt8.new", "memh","Store Half integer",ATTRIBS(A_STORE),"1",fSTORE(1,2,EA,fGETHALF(0,fNEWREG_ST(NtN))),1)
|
||||
|
||||
|
||||
Q6INSN(S2_allocframe,"allocframe(Rx32,#u11:3):raw", ATTRIBS(A_STORE,A_RESTRICT_SLOT0ONLY), "Allocate stack frame",
|
||||
{ fEA_RI(RxV,-8); fSTORE(1,8,EA,fFRAME_SCRAMBLE((fCAST8_8u(fREAD_LR()) << 32) | fCAST4_4u(fREAD_FP()))); fWRITE_FP(EA); fFRAMECHECK(EA-uiV,EA); RxV = EA-uiV; })
|
||||
|
||||
#define A_RETURN A_RESTRICT_SLOT0ONLY
|
||||
|
||||
Q6INSN(L2_deallocframe,"Rdd32=deallocframe(Rs32):raw", ATTRIBS(A_LOAD), "Deallocate stack frame",
|
||||
{ fHIDE(size8u_t tmp;) fEA_REG(RsV);
|
||||
fLOAD(1,8,u,EA,tmp);
|
||||
RddV = fFRAME_UNSCRAMBLE(tmp);
|
||||
fWRITE_SP(EA+8); })
|
||||
|
||||
Q6INSN(L4_return,"Rdd32=dealloc_return(Rs32):raw", ATTRIBS(A_JINDIR,A_LOAD,A_RETURN), "Deallocate stack frame and return",
|
||||
{ fHIDE(size8u_t tmp;) fEA_REG(RsV);
|
||||
fLOAD(1,8,u,EA,tmp);
|
||||
RddV = fFRAME_UNSCRAMBLE(tmp);
|
||||
fWRITE_SP(EA+8);
|
||||
fJUMPR(REG_LR,fGETWORD(1,RddV),COF_TYPE_JUMPR);})
|
||||
|
||||
#define CONDSEM(SRCREG,STALLBITS0,STALLBITS1,PREDFUNC,PREDARG,STALLSPEC,PREDCOND) \
|
||||
{ \
|
||||
fHIDE(size8u_t tmp;) \
|
||||
fBRANCH_SPECULATE_STALL(PREDFUNC##PREDCOND(PREDARG),,STALLSPEC,STALLBITS0,STALLBITS1); \
|
||||
fEA_REG(SRCREG); \
|
||||
if (PREDFUNC##PREDCOND(PREDARG)) { \
|
||||
fLOAD(1,8,u,EA,tmp); \
|
||||
RddV = fFRAME_UNSCRAMBLE(tmp); \
|
||||
fWRITE_SP(EA+8); \
|
||||
fJUMPR(REG_LR,fGETWORD(1,RddV),COF_TYPE_JUMPR); \
|
||||
} else { \
|
||||
LOAD_CANCEL(EA); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define COND_RETURN_TF(TG,TG2,DOTNEW,STALLBITS0,STALLBITS1,STALLSPEC,ATTRIBS,PREDFUNC,PREDARG,T_NT) \
|
||||
Q6INSN(TG##_t##TG2,"if (Pv4"DOTNEW") Rdd32=dealloc_return(Rs32)"T_NT":raw",ATTRIBS,"deallocate stack frame and return", \
|
||||
CONDSEM(RsV,STALLBITS0,STALLBITS1,PREDFUNC,PREDARG,STALLSPEC,)) \
|
||||
Q6INSN(TG##_f##TG2,"if (!Pv4"DOTNEW") Rdd32=dealloc_return(Rs32)"T_NT":raw",ATTRIBS,"deallocate stack frame and return", \
|
||||
CONDSEM(RsV,STALLBITS0,STALLBITS1,PREDFUNC##NOT,PREDARG,STALLSPEC,))
|
||||
|
||||
#define COND_RETURN_NEW(TG,STALLBITS0,STALLBITS1,ATTRIBS) \
|
||||
COND_RETURN_TF(TG,new_pt,".new",12,0,SPECULATE_TAKEN,ATTRIBS,fLSBNEW,PvN,":t") \
|
||||
COND_RETURN_TF(TG,new_pnt,".new",12,0,SPECULATE_NOT_TAKEN,ATTRIBS,fLSBNEW,PvN,":nt") \
|
||||
|
||||
#define RETURN_ATTRIBS A_LOAD,A_RETURN
|
||||
|
||||
COND_RETURN_TF(L4_return,,,7,0,SPECULATE_NOT_TAKEN,ATTRIBS(RETURN_ATTRIBS,A_JINDIROLD),fLSBOLD,PvV,)
|
||||
COND_RETURN_NEW(L4_return,12,0,ATTRIBS(RETURN_ATTRIBS,A_JINDIRNEW))
|
||||
|
||||
|
||||
|
||||
|
||||
Q6INSN(L2_loadw_locked,"Rd32=memw_locked(Rs32)", ATTRIBS(A_LOAD,A_RESTRICT_SLOT0ONLY), "Load word with lock",
|
||||
{ fEA_REG(RsV); fLOAD_LOCKED(1,4,u,EA,RdV) })
|
||||
|
||||
|
||||
Q6INSN(S2_storew_locked,"memw_locked(Rs32,Pd4)=Rt32", ATTRIBS(A_STORE,A_RESTRICT_SLOT0ONLY), "Store word with lock",
|
||||
{ fEA_REG(RsV); fSTORE_LOCKED(1,4,EA,RtV,PdV) })
|
||||
|
||||
|
||||
Q6INSN(L4_loadd_locked,"Rdd32=memd_locked(Rs32)", ATTRIBS(A_LOAD,A_RESTRICT_SLOT0ONLY), "Load double with lock",
|
||||
{ fEA_REG(RsV); fLOAD_LOCKED(1,8,u,EA,RddV) })
|
||||
|
||||
Q6INSN(S4_stored_locked,"memd_locked(Rs32,Pd4)=Rtt32", ATTRIBS(A_STORE,A_RESTRICT_SLOT0ONLY), "Store word with lock",
|
||||
{ fEA_REG(RsV); fSTORE_LOCKED(1,8,EA,RttV,PdV) })
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************/
|
||||
/* */
|
||||
/* Predicated LDST */
|
||||
/* */
|
||||
/*****************************************************************/
|
||||
|
||||
#define STD_PLD_AMODES(TAG,OPER,DESCR,ATTRIB,SHFT,SHFTNUM,SEMANTICS)\
|
||||
Q6INSN(L4_##TAG##_rr, OPER"(Rs32+Rt32<<#u2)", ATTRIB,DESCR,{fEA_RRs(RsV,RtV,uiV); SEMANTICS;})\
|
||||
Q6INSN(L2_p##TAG##t_io, "if (Pt4) "OPER"(Rs32+#u6:"SHFT")", ATTRIB,DESCR,{fIMMEXT(uiV); fEA_RI(RsV,uiV); if(fLSBOLD(PtV)){SEMANTICS;} else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L2_p##TAG##t_pi, "if (Pt4) "OPER"(Rx32++#s4:"SHFT")", ATTRIB,DESCR,{fEA_REG(RxV); if(fLSBOLD(PtV)){ fPM_I(RxV,siV); SEMANTICS;} else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L2_p##TAG##f_io, "if (!Pt4) "OPER"(Rs32+#u6:"SHFT")", ATTRIB,DESCR,{fIMMEXT(uiV); fEA_RI(RsV,uiV); if(fLSBOLDNOT(PtV)){ SEMANTICS; } else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L2_p##TAG##f_pi, "if (!Pt4) "OPER"(Rx32++#s4:"SHFT")", ATTRIB,DESCR,{fEA_REG(RxV); if(fLSBOLDNOT(PtV)){ fPM_I(RxV,siV); SEMANTICS;} else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L2_p##TAG##tnew_io,"if (Pt4.new) "OPER"(Rs32+#u6:"SHFT")",ATTRIB,DESCR,{fIMMEXT(uiV); fEA_RI(RsV,uiV); if (fLSBNEW(PtN)) { SEMANTICS; } else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L2_p##TAG##fnew_io,"if (!Pt4.new) "OPER"(Rs32+#u6:"SHFT")",ATTRIB,DESCR,{fIMMEXT(uiV); fEA_RI(RsV,uiV); if (fLSBNEWNOT(PtN)) { SEMANTICS; } else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L4_p##TAG##t_rr, "if (Pv4) "OPER"(Rs32+Rt32<<#u2)", ATTRIB,DESCR,{fEA_RRs(RsV,RtV,uiV); if(fLSBOLD(PvV)){ SEMANTICS;} else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L4_p##TAG##f_rr, "if (!Pv4) "OPER"(Rs32+Rt32<<#u2)", ATTRIB,DESCR,{fEA_RRs(RsV,RtV,uiV); if(fLSBOLDNOT(PvV)){ SEMANTICS; } else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L4_p##TAG##tnew_rr,"if (Pv4.new) "OPER"(Rs32+Rt32<<#u2)",ATTRIB,DESCR,{fEA_RRs(RsV,RtV,uiV); if (fLSBNEW(PvN)) { SEMANTICS; } else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L4_p##TAG##fnew_rr,"if (!Pv4.new) "OPER"(Rs32+Rt32<<#u2)",ATTRIB,DESCR,{fEA_RRs(RsV,RtV,uiV); if (fLSBNEWNOT(PvN)) { SEMANTICS; } else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L2_p##TAG##tnew_pi, "if (Pt4.new) "OPER"(Rx32++#s4:"SHFT")", ATTRIB,DESCR,{fEA_REG(RxV); if(fLSBNEW(PtN)){ fPM_I(RxV,siV); SEMANTICS;} else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L2_p##TAG##fnew_pi, "if (!Pt4.new) "OPER"(Rx32++#s4:"SHFT")", ATTRIB,DESCR,{fEA_REG(RxV); if(fLSBNEWNOT(PtN)){ fPM_I(RxV,siV); SEMANTICS;} else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L4_p##TAG##t_abs, "if (Pt4) "OPER"(#u6)", ATTRIB,DESCR,{fMUST_IMMEXT(uiV); fEA_IMM(uiV); if(fLSBOLD(PtV)){ SEMANTICS;} else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L4_p##TAG##f_abs, "if (!Pt4) "OPER"(#u6)", ATTRIB,DESCR,{fMUST_IMMEXT(uiV); fEA_IMM(uiV); if(fLSBOLDNOT(PtV)){ SEMANTICS; } else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L4_p##TAG##tnew_abs,"if (Pt4.new) "OPER"(#u6)",ATTRIB,DESCR,{fMUST_IMMEXT(uiV); fEA_IMM(uiV);if (fLSBNEW(PtN)) { SEMANTICS; } else {LOAD_CANCEL(EA);}})\
|
||||
Q6INSN(L4_p##TAG##fnew_abs,"if (!Pt4.new) "OPER"(#u6)",ATTRIB,DESCR,{fMUST_IMMEXT(uiV); fEA_IMM(uiV);if (fLSBNEWNOT(PtN)) { SEMANTICS; } else {LOAD_CANCEL(EA);}})
|
||||
|
||||
|
||||
|
||||
/* The set of 32-bit predicated load instructions */
|
||||
STD_PLD_AMODES(loadrub,"Rd32=memub","Load Unsigned Byte",ATTRIBS(A_ARCHV2,A_LOAD),"0",0,fLOAD(1,1,u,EA,RdV))
|
||||
STD_PLD_AMODES(loadrb, "Rd32=memb", "Load signed Byte",ATTRIBS(A_ARCHV2,A_LOAD),"0",0,fLOAD(1,1,s,EA,RdV))
|
||||
STD_PLD_AMODES(loadruh,"Rd32=memuh","Load unsigned Half integer",ATTRIBS(A_ARCHV2,A_LOAD),"1",1,fLOAD(1,2,u,EA,RdV))
|
||||
STD_PLD_AMODES(loadrh, "Rd32=memh", "Load signed Half integer",ATTRIBS(A_ARCHV2,A_LOAD),"1",1,fLOAD(1,2,s,EA,RdV))
|
||||
STD_PLD_AMODES(loadri, "Rd32=memw", "Load Word",ATTRIBS(A_ARCHV2,A_LOAD),"2",2,fLOAD(1,4,u,EA,RdV))
|
||||
STD_PLD_AMODES(loadrd, "Rdd32=memd","Load Double integer",ATTRIBS(A_ARCHV2,A_LOAD),"3",3,fLOAD(1,8,u,EA,RddV))
|
||||
|
||||
/* The set of addressing modes standard to all predicated store instructions */
|
||||
#define STD_PST_AMODES(TAG,DEST,OPER,DESCR,ATTRIB,SHFT,SHFTNUM,SEMANTICS)\
|
||||
Q6INSN(S4_##TAG##_rr, OPER"(Rs32+Ru32<<#u2)="DEST, ATTRIB,DESCR,{fEA_RRs(RsV,RuV,uiV); SEMANTICS;})\
|
||||
Q6INSN(S2_p##TAG##t_io, "if (Pv4) "OPER"(Rs32+#u6:"SHFT")="DEST, ATTRIB,DESCR,{fIMMEXT(uiV); fEA_RI(RsV,uiV); if (fLSBOLD(PvV)){ SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S2_p##TAG##t_pi, "if (Pv4) "OPER"(Rx32++#s4:"SHFT")="DEST, ATTRIB,DESCR,{fEA_REG(RxV); if (fLSBOLD(PvV)){ fPM_I(RxV,siV); SEMANTICS;} else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S2_p##TAG##f_io, "if (!Pv4) "OPER"(Rs32+#u6:"SHFT")="DEST, ATTRIB,DESCR,{fIMMEXT(uiV); fEA_RI(RsV,uiV); if (fLSBOLDNOT(PvV)){ SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S2_p##TAG##f_pi, "if (!Pv4) "OPER"(Rx32++#s4:"SHFT")="DEST, ATTRIB,DESCR,{fEA_REG(RxV); if (fLSBOLDNOT(PvV)){ fPM_I(RxV,siV); SEMANTICS;} else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S4_p##TAG##t_rr, "if (Pv4) "OPER"(Rs32+Ru32<<#u2)="DEST, ATTRIB,DESCR,{fEA_RRs(RsV,RuV,uiV); if (fLSBOLD(PvV)){ SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S4_p##TAG##f_rr, "if (!Pv4) "OPER"(Rs32+Ru32<<#u2)="DEST, ATTRIB,DESCR,{fEA_RRs(RsV,RuV,uiV); if (fLSBOLDNOT(PvV)){ SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S4_p##TAG##tnew_io,"if (Pv4.new) "OPER"(Rs32+#u6:"SHFT")="DEST,ATTRIB,DESCR,{fIMMEXT(uiV); fEA_RI(RsV,uiV); if ( fLSBNEW(PvN)) { SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S4_p##TAG##fnew_io,"if (!Pv4.new) "OPER"(Rs32+#u6:"SHFT")="DEST,ATTRIB,DESCR,{fIMMEXT(uiV); fEA_RI(RsV,uiV); if (fLSBNEWNOT(PvN)) { SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S4_p##TAG##tnew_rr,"if (Pv4.new) "OPER"(Rs32+Ru32<<#u2)="DEST,ATTRIB,DESCR,{fEA_RRs(RsV,RuV,uiV); if ( fLSBNEW(PvN)) { SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S4_p##TAG##fnew_rr,"if (!Pv4.new) "OPER"(Rs32+Ru32<<#u2)="DEST,ATTRIB,DESCR,{fEA_RRs(RsV,RuV,uiV); if (fLSBNEWNOT(PvN)) { SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S2_p##TAG##tnew_pi, "if (Pv4.new) "OPER"(Rx32++#s4:"SHFT")="DEST, ATTRIB,DESCR,{fEA_REG(RxV); if (fLSBNEW(PvN)){ fPM_I(RxV,siV); SEMANTICS;} else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S2_p##TAG##fnew_pi, "if (!Pv4.new) "OPER"(Rx32++#s4:"SHFT")="DEST, ATTRIB,DESCR,{fEA_REG(RxV); if (fLSBNEWNOT(PvN)){ fPM_I(RxV,siV); SEMANTICS;} else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S4_p##TAG##t_abs, "if (Pv4) "OPER"(#u6)="DEST, ATTRIB,DESCR,{fMUST_IMMEXT(uiV); fEA_IMM(uiV); if (fLSBOLD(PvV)){ SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S4_p##TAG##f_abs, "if (!Pv4) "OPER"(#u6)="DEST, ATTRIB,DESCR,{fMUST_IMMEXT(uiV);fEA_IMM(uiV); if (fLSBOLDNOT(PvV)){ SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S4_p##TAG##tnew_abs,"if (Pv4.new) "OPER"(#u6)="DEST,ATTRIB,DESCR,{fMUST_IMMEXT(uiV);fEA_IMM(uiV); if ( fLSBNEW(PvN)) { SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S4_p##TAG##fnew_abs,"if (!Pv4.new) "OPER"(#u6)="DEST,ATTRIB,DESCR,{fMUST_IMMEXT(uiV);fEA_IMM(uiV); if (fLSBNEWNOT(PvN)) { SEMANTICS; } else {STORE_CANCEL(EA);}})
|
||||
|
||||
|
||||
|
||||
|
||||
/* The set of 32-bit predicated store instructions */
|
||||
STD_PST_AMODES(storerb,"Rt32","memb","Store Byte",ATTRIBS(A_ARCHV2,A_STORE),"0",0,fSTORE(1,1,EA,fGETBYTE(0,RtV)))
|
||||
STD_PST_AMODES(storerh,"Rt32","memh","Store Half integer",ATTRIBS(A_ARCHV2,A_STORE),"1",1,fSTORE(1,2,EA,fGETHALF(0,RtV)))
|
||||
STD_PST_AMODES(storerf,"Rt.H32","memh","Store Upper Half integer",ATTRIBS(A_ARCHV2,A_STORE),"1",1,fSTORE(1,2,EA,fGETHALF(1,RtV)))
|
||||
STD_PST_AMODES(storeri,"Rt32","memw","Store Word",ATTRIBS(A_ARCHV2,A_STORE),"2",2,fSTORE(1,4,EA,RtV))
|
||||
STD_PST_AMODES(storerd,"Rtt32","memd","Store Double integer",ATTRIBS(A_ARCHV2,A_STORE),"3",3,fSTORE(1,8,EA,RttV))
|
||||
STD_PST_AMODES(storerinew,"Nt8.new","memw","Store Word",ATTRIBS(A_ARCHV2,A_STORE),"2",2,fSTORE(1,4,EA,fNEWREG_ST(NtN)))
|
||||
STD_PST_AMODES(storerbnew,"Nt8.new","memb","Store Byte",ATTRIBS(A_ARCHV2,A_STORE),"0",0,fSTORE(1,1,EA,fGETBYTE(0,fNEWREG_ST(NtN))))
|
||||
STD_PST_AMODES(storerhnew,"Nt8.new","memh","Store Half integer",ATTRIBS(A_ARCHV2,A_STORE),"1",1,fSTORE(1,2,EA,fGETHALF(0,fNEWREG_ST(NtN))))
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************/
|
||||
/* */
|
||||
/* Mem-Ops (Load-op-Store) */
|
||||
/* */
|
||||
/*****************************************************************/
|
||||
|
||||
/* The set of 32-bit non-predicated mem-ops */
|
||||
#define STD_MEMOP_AMODES(TAG,OPER,DESCR,SEMANTICS)\
|
||||
Q6INSN(L4_##TAG##w_io, "memw(Rs32+#u6:2)"OPER, ATTRIBS(A_RESTRICT_SLOT0ONLY),DESCR,{fIMMEXT(uiV); fEA_RI(RsV,uiV); fHIDE(size4s_t tmp;) fLOAD(1,4,s,EA,tmp); SEMANTICS; fSTORE(1,4,EA,tmp); })\
|
||||
Q6INSN(L4_##TAG##b_io, "memb(Rs32+#u6:0)"OPER, ATTRIBS(A_RESTRICT_SLOT0ONLY),DESCR,{fIMMEXT(uiV); fEA_RI(RsV,uiV); fHIDE(size4s_t tmp;) fLOAD(1,1,s,EA,tmp); SEMANTICS; fSTORE(1,1,EA,tmp); })\
|
||||
Q6INSN(L4_##TAG##h_io, "memh(Rs32+#u6:1)"OPER, ATTRIBS(A_RESTRICT_SLOT0ONLY),DESCR,{fIMMEXT(uiV); fEA_RI(RsV,uiV); fHIDE(size4s_t tmp;) fLOAD(1,2,s,EA,tmp); SEMANTICS; fSTORE(1,2,EA,tmp); })
|
||||
|
||||
|
||||
|
||||
STD_MEMOP_AMODES(add_memop, "+=Rt32", "Add Register to Memory Word", tmp += RtV)
|
||||
STD_MEMOP_AMODES(sub_memop, "-=Rt32", "Sub Register from Memory Word", tmp -= RtV)
|
||||
STD_MEMOP_AMODES(and_memop, "&=Rt32", "Logical AND Register to Memory Word", tmp &= RtV)
|
||||
STD_MEMOP_AMODES(or_memop, "|=Rt32", "Logical OR Register to Memory Word", tmp |= RtV)
|
||||
|
||||
|
||||
STD_MEMOP_AMODES(iadd_memop, "+=#U5", "Add Immediate to Memory Word", tmp += UiV)
|
||||
STD_MEMOP_AMODES(isub_memop, "-=#U5", "Sub Immediate to Memory Word", tmp -= UiV)
|
||||
STD_MEMOP_AMODES(iand_memop, "=clrbit(#U5)", "Clear a bit in memory", tmp &= (~(1<<UiV)))
|
||||
STD_MEMOP_AMODES(ior_memop, "=setbit(#U5)", "Set a bit in memory", tmp |= (1<<UiV))
|
||||
|
||||
|
||||
/*****************************************************************/
|
||||
/* */
|
||||
/* V4 store immediates */
|
||||
/* */
|
||||
/*****************************************************************/
|
||||
/* Predicated Store immediates */
|
||||
#define V4_PSTI_AMODES(TAG,DEST,OPER,DESCR,ATTRIB,SHFT,SEMANTICS)\
|
||||
Q6INSN(S4_##TAG##t_io,"if (Pv4) "OPER"(Rs32+#u6:"SHFT")="DEST,ATTRIB,DESCR,{fEA_RI(RsV,uiV); if (fLSBOLD(PvV)){ SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S4_##TAG##f_io,"if (!Pv4) "OPER"(Rs32+#u6:"SHFT")="DEST,ATTRIB,DESCR,{fEA_RI(RsV,uiV); if (fLSBOLDNOT(PvV)){ SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S4_##TAG##tnew_io,"if (Pv4.new) "OPER"(Rs32+#u6:"SHFT")="DEST,ATTRIB,DESCR,{fEA_RI(RsV,uiV); if (fLSBNEW(PvN)){ SEMANTICS; } else {STORE_CANCEL(EA);}})\
|
||||
Q6INSN(S4_##TAG##fnew_io,"if (!Pv4.new) "OPER"(Rs32+#u6:"SHFT")="DEST,ATTRIB,DESCR,{fEA_RI(RsV,uiV); if (fLSBNEWNOT(PvN)){ SEMANTICS; } else {STORE_CANCEL(EA);}})
|
||||
|
||||
/* The set of 32-bit store immediate instructions */
|
||||
V4_PSTI_AMODES(storeirb,"#S6","memb","Store Immediate Byte",ATTRIBS(A_ARCHV2,A_STORE),"0",fIMMEXT(SiV); fSTORE(1,1,EA,SiV))
|
||||
V4_PSTI_AMODES(storeirh,"#S6","memh","Store Immediate Half integer",ATTRIBS(A_ARCHV2,A_STORE),"1",fIMMEXT(SiV); fSTORE(1,2,EA,SiV))
|
||||
V4_PSTI_AMODES(storeiri,"#S6","memw","Store Immediate Word",ATTRIBS(A_ARCHV2,A_STORE),"2",fIMMEXT(SiV); fSTORE(1,4,EA,SiV))
|
||||
|
||||
|
||||
/* Non-predicated store immediates */
|
||||
#define V4_STI_AMODES(TAG,DEST,OPER,DESCR,ATTRIB,SHFT,SEMANTICS)\
|
||||
Q6INSN(S4_##TAG##_io, OPER"(Rs32+#u6:"SHFT")="DEST, ATTRIB,DESCR,{fEA_RI(RsV,uiV); SEMANTICS; })
|
||||
|
||||
/* The set of 32-bit store immediate instructions */
|
||||
V4_STI_AMODES(storeirb,"#S8","memb","Store Immediate Byte",ATTRIBS(A_ARCHV2,A_STORE),"0",fIMMEXT(SiV); fSTORE(1,1,EA,SiV))
|
||||
V4_STI_AMODES(storeirh,"#S8","memh","Store Immediate Half integer",ATTRIBS(A_ARCHV2,A_STORE),"1",fIMMEXT(SiV); fSTORE(1,2,EA,SiV))
|
||||
V4_STI_AMODES(storeiri,"#S8","memw","Store Immediate Word",ATTRIBS(A_ARCHV2,A_STORE),"2",fIMMEXT(SiV); fSTORE(1,4,EA,SiV))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************/
|
||||
/* */
|
||||
/* V2 GP-relative LD/ST */
|
||||
/* */
|
||||
/*****************************************************************/
|
||||
|
||||
#define STD_GPLD_AMODES(TAG,OPER,DESCR,ATTRIB,SHFT,SEMANTICS)\
|
||||
Q6INSN(L2_##TAG##gp, OPER"(gp+#u16:"SHFT")", ATTRIB,DESCR,{fIMMEXT(uiV); fEA_GPI(uiV); SEMANTICS; })
|
||||
|
||||
/* The set of 32-bit load instructions */
|
||||
STD_GPLD_AMODES(loadrub,"Rd32=memub","Load Unsigned Byte",ATTRIBS(A_LOAD,A_ARCHV2),"0",fLOAD(1,1,u,EA,RdV))
|
||||
STD_GPLD_AMODES(loadrb, "Rd32=memb", "Load signed Byte",ATTRIBS(A_LOAD,A_ARCHV2),"0",fLOAD(1,1,s,EA,RdV))
|
||||
STD_GPLD_AMODES(loadruh,"Rd32=memuh","Load unsigned Half integer",ATTRIBS(A_LOAD,A_ARCHV2),"1",fLOAD(1,2,u,EA,RdV))
|
||||
STD_GPLD_AMODES(loadrh, "Rd32=memh", "Load signed Half integer",ATTRIBS(A_LOAD,A_ARCHV2),"1",fLOAD(1,2,s,EA,RdV))
|
||||
STD_GPLD_AMODES(loadri, "Rd32=memw", "Load Word",ATTRIBS(A_LOAD,A_ARCHV2),"2",fLOAD(1,4,u,EA,RdV))
|
||||
STD_GPLD_AMODES(loadrd, "Rdd32=memd","Load Double integer",ATTRIBS(A_LOAD,A_ARCHV2),"3",fLOAD(1,8,u,EA,RddV))
|
||||
|
||||
|
||||
#define STD_GPST_AMODES(TAG,DEST,OPER,DESCR,ATTRIB,SHFT,SEMANTICS)\
|
||||
Q6INSN(S2_##TAG##gp, OPER"(gp+#u16:"SHFT")="DEST, ATTRIB,DESCR,{fIMMEXT(uiV); fEA_GPI(uiV); SEMANTICS; })
|
||||
|
||||
/* The set of 32-bit store instructions */
|
||||
STD_GPST_AMODES(storerb, "Rt32", "memb","Store Byte",ATTRIBS(A_STORE,A_ARCHV2),"0",fSTORE(1,1,EA,fGETBYTE(0,RtV)))
|
||||
STD_GPST_AMODES(storerh, "Rt32", "memh","Store Half integer",ATTRIBS(A_STORE,A_ARCHV2),"1",fSTORE(1,2,EA,fGETHALF(0,RtV)))
|
||||
STD_GPST_AMODES(storerf, "Rt.H32", "memh","Store Upper Half integer",ATTRIBS(A_STORE,A_ARCHV2),"1",fSTORE(1,2,EA,fGETHALF(1,RtV)))
|
||||
STD_GPST_AMODES(storeri, "Rt32", "memw","Store Word",ATTRIBS(A_STORE,A_ARCHV2),"2",fSTORE(1,4,EA,RtV))
|
||||
STD_GPST_AMODES(storerd, "Rtt32","memd","Store Double integer",ATTRIBS(A_STORE,A_ARCHV2),"3",fSTORE(1,8,EA,RttV))
|
||||
STD_GPST_AMODES(storerinew, "Nt8.new", "memw","Store Word",ATTRIBS(A_STORE,A_ARCHV2),"2",fSTORE(1,4,EA,fNEWREG_ST(NtN)))
|
||||
STD_GPST_AMODES(storerbnew, "Nt8.new", "memb","Store Byte",ATTRIBS(A_STORE,A_ARCHV2),"0",fSTORE(1,1,EA,fGETBYTE(0,fNEWREG_ST(NtN))))
|
||||
STD_GPST_AMODES(storerhnew, "Nt8.new", "memh","Store Half integer",ATTRIBS(A_STORE,A_ARCHV2),"1",fSTORE(1,2,EA,fGETHALF(0,fNEWREG_ST(NtN))))
|
1531
target/hexagon/imported/macros.def
Executable file
1531
target/hexagon/imported/macros.def
Executable file
File diff suppressed because it is too large
Load Diff
1208
target/hexagon/imported/mpy.idef
Normal file
1208
target/hexagon/imported/mpy.idef
Normal file
File diff suppressed because it is too large
Load Diff
1066
target/hexagon/imported/shift.idef
Normal file
1066
target/hexagon/imported/shift.idef
Normal file
File diff suppressed because it is too large
Load Diff
149
target/hexagon/imported/subinsns.idef
Normal file
149
target/hexagon/imported/subinsns.idef
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* sub-instructions
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*****************************************************************/
|
||||
/* */
|
||||
/* A-type subinsns */
|
||||
/* */
|
||||
/*****************************************************************/
|
||||
|
||||
Q6INSN(SA1_addi, "Rx16=add(Rx16,#s7)", ATTRIBS(A_SUBINSN),"Add", { fIMMEXT(siV); RxV=RxV+siV;})
|
||||
Q6INSN(SA1_tfr, "Rd16=Rs16", ATTRIBS(A_SUBINSN),"Tfr", { RdV=RsV;})
|
||||
Q6INSN(SA1_seti, "Rd16=#u6", ATTRIBS(A_SUBINSN),"Set immed", { fIMMEXT(uiV); RdV=uiV;})
|
||||
Q6INSN(SA1_setin1, "Rd16=#-1", ATTRIBS(A_SUBINSN),"Set to -1", { RdV=-1;})
|
||||
Q6INSN(SA1_clrtnew, "if (p0.new) Rd16=#0", ATTRIBS(A_SUBINSN),"clear if true", { if (fLSBNEW0) {RdV=0;} else {CANCEL;} })
|
||||
Q6INSN(SA1_clrfnew, "if (!p0.new) Rd16=#0", ATTRIBS(A_SUBINSN),"clear if false",{ if (fLSBNEW0NOT) {RdV=0;} else {CANCEL;} })
|
||||
Q6INSN(SA1_clrt, "if (p0) Rd16=#0", ATTRIBS(A_SUBINSN),"clear if true", { if (fLSBOLD(fREAD_P0())) {RdV=0;} else {CANCEL;} })
|
||||
Q6INSN(SA1_clrf, "if (!p0) Rd16=#0", ATTRIBS(A_SUBINSN),"clear if false",{ if (fLSBOLDNOT(fREAD_P0())) {RdV=0;} else {CANCEL;} })
|
||||
|
||||
Q6INSN(SA1_addsp, "Rd16=add(r29,#u6:2)", ATTRIBS(A_SUBINSN),"Add", { RdV=fREAD_SP()+uiV; })
|
||||
Q6INSN(SA1_inc, "Rd16=add(Rs16,#1)", ATTRIBS(A_SUBINSN),"Inc", { RdV=RsV+1;})
|
||||
Q6INSN(SA1_dec, "Rd16=add(Rs16,#-1)", ATTRIBS(A_SUBINSN),"Dec", { RdV=RsV-1;})
|
||||
Q6INSN(SA1_addrx, "Rx16=add(Rx16,Rs16)", ATTRIBS(A_SUBINSN),"Add", { RxV=RxV+RsV; })
|
||||
Q6INSN(SA1_zxtb, "Rd16=and(Rs16,#255)", ATTRIBS(A_SUBINSN),"Zxtb", { RdV= fZXTN(8,32,RsV);})
|
||||
Q6INSN(SA1_and1, "Rd16=and(Rs16,#1)", ATTRIBS(A_SUBINSN),"And #1", { RdV= RsV&1;})
|
||||
Q6INSN(SA1_sxtb, "Rd16=sxtb(Rs16)", ATTRIBS(A_SUBINSN),"Sxtb", { RdV= fSXTN(8,32,RsV);})
|
||||
Q6INSN(SA1_zxth, "Rd16=zxth(Rs16)", ATTRIBS(A_SUBINSN),"Zxth", { RdV= fZXTN(16,32,RsV);})
|
||||
Q6INSN(SA1_sxth, "Rd16=sxth(Rs16)", ATTRIBS(A_SUBINSN),"Sxth", { RdV= fSXTN(16,32,RsV);})
|
||||
Q6INSN(SA1_combinezr,"Rdd8=combine(#0,Rs16)", ATTRIBS(A_SUBINSN),"Combines", { fSETWORD(0,RddV,RsV); fSETWORD(1,RddV,0); })
|
||||
Q6INSN(SA1_combinerz,"Rdd8=combine(Rs16,#0)", ATTRIBS(A_SUBINSN),"Combines", { fSETWORD(0,RddV,0); fSETWORD(1,RddV,RsV); })
|
||||
Q6INSN(SA1_combine0i,"Rdd8=combine(#0,#u2)", ATTRIBS(A_SUBINSN),"Combines", { fSETWORD(0,RddV,uiV); fSETWORD(1,RddV,0); })
|
||||
Q6INSN(SA1_combine1i,"Rdd8=combine(#1,#u2)", ATTRIBS(A_SUBINSN),"Combines", { fSETWORD(0,RddV,uiV); fSETWORD(1,RddV,1); })
|
||||
Q6INSN(SA1_combine2i,"Rdd8=combine(#2,#u2)", ATTRIBS(A_SUBINSN),"Combines", { fSETWORD(0,RddV,uiV); fSETWORD(1,RddV,2); })
|
||||
Q6INSN(SA1_combine3i,"Rdd8=combine(#3,#u2)", ATTRIBS(A_SUBINSN),"Combines", { fSETWORD(0,RddV,uiV); fSETWORD(1,RddV,3); })
|
||||
Q6INSN(SA1_cmpeqi, "p0=cmp.eq(Rs16,#u2)", ATTRIBS(A_SUBINSN),"CompareImmed",{fWRITE_P0(f8BITSOF(RsV==uiV));})
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************/
|
||||
/* */
|
||||
/* Ld1/2 subinsns */
|
||||
/* */
|
||||
/*****************************************************************/
|
||||
|
||||
Q6INSN(SL1_loadri_io, "Rd16=memw(Rs16+#u4:2)", ATTRIBS(A_LOAD,A_SUBINSN),"load word", {fEA_RI(RsV,uiV); fLOAD(1,4,u,EA,RdV);})
|
||||
Q6INSN(SL1_loadrub_io, "Rd16=memub(Rs16+#u4:0)",ATTRIBS(A_LOAD,A_SUBINSN),"load byte", {fEA_RI(RsV,uiV); fLOAD(1,1,u,EA,RdV);})
|
||||
|
||||
Q6INSN(SL2_loadrh_io, "Rd16=memh(Rs16+#u3:1)", ATTRIBS(A_LOAD,A_SUBINSN),"load half", {fEA_RI(RsV,uiV); fLOAD(1,2,s,EA,RdV);})
|
||||
Q6INSN(SL2_loadruh_io, "Rd16=memuh(Rs16+#u3:1)",ATTRIBS(A_LOAD,A_SUBINSN),"load half", {fEA_RI(RsV,uiV); fLOAD(1,2,u,EA,RdV);})
|
||||
Q6INSN(SL2_loadrb_io, "Rd16=memb(Rs16+#u3:0)", ATTRIBS(A_LOAD,A_SUBINSN),"load byte", {fEA_RI(RsV,uiV); fLOAD(1,1,s,EA,RdV);})
|
||||
Q6INSN(SL2_loadri_sp, "Rd16=memw(r29+#u5:2)", ATTRIBS(A_LOAD,A_SUBINSN),"load word", {fEA_RI(fREAD_SP(),uiV); fLOAD(1,4,u,EA,RdV);})
|
||||
Q6INSN(SL2_loadrd_sp, "Rdd8=memd(r29+#u5:3)", ATTRIBS(A_LOAD,A_SUBINSN),"load dword",{fEA_RI(fREAD_SP(),uiV); fLOAD(1,8,u,EA,RddV);})
|
||||
|
||||
Q6INSN(SL2_deallocframe,"deallocframe", ATTRIBS(A_SUBINSN,A_LOAD), "Deallocate stack frame",
|
||||
{ fHIDE(size8u_t tmp;) fEA_REG(fREAD_FP());
|
||||
fLOAD(1,8,u,EA,tmp);
|
||||
tmp = fFRAME_UNSCRAMBLE(tmp);
|
||||
fWRITE_LR(fGETWORD(1,tmp));
|
||||
fWRITE_FP(fGETWORD(0,tmp));
|
||||
fWRITE_SP(EA+8); })
|
||||
|
||||
Q6INSN(SL2_return,"dealloc_return", ATTRIBS(A_JINDIR,A_SUBINSN,A_LOAD,A_RETURN,A_RESTRICT_SLOT0ONLY), "Deallocate stack frame and return",
|
||||
{ fHIDE(size8u_t tmp;) fEA_REG(fREAD_FP());
|
||||
fLOAD(1,8,u,EA,tmp);
|
||||
tmp = fFRAME_UNSCRAMBLE(tmp);
|
||||
fWRITE_LR(fGETWORD(1,tmp));
|
||||
fWRITE_FP(fGETWORD(0,tmp));
|
||||
fWRITE_SP(EA+8);
|
||||
fJUMPR(REG_LR,fGETWORD(1,tmp),COF_TYPE_JUMPR);})
|
||||
|
||||
Q6INSN(SL2_return_t,"if (p0) dealloc_return", ATTRIBS(A_JINDIROLD,A_SUBINSN,A_LOAD,A_RETURN,A_RESTRICT_SLOT0ONLY), "Deallocate stack frame and return",
|
||||
{ fHIDE(size8u_t tmp;); fBRANCH_SPECULATE_STALL(fLSBOLD(fREAD_P0()),, SPECULATE_NOT_TAKEN,4,0); fEA_REG(fREAD_FP()); if (fLSBOLD(fREAD_P0())) { fLOAD(1,8,u,EA,tmp); tmp = fFRAME_UNSCRAMBLE(tmp); fWRITE_LR(fGETWORD(1,tmp)); fWRITE_FP(fGETWORD(0,tmp)); fWRITE_SP(EA+8);
|
||||
fJUMPR(REG_LR,fGETWORD(1,tmp),COF_TYPE_JUMPR);} else {LOAD_CANCEL(EA);} })
|
||||
|
||||
Q6INSN(SL2_return_f,"if (!p0) dealloc_return", ATTRIBS(A_JINDIROLD,A_SUBINSN,A_LOAD,A_RETURN,A_RESTRICT_SLOT0ONLY), "Deallocate stack frame and return",
|
||||
{ fHIDE(size8u_t tmp;);fBRANCH_SPECULATE_STALL(fLSBOLDNOT(fREAD_P0()),, SPECULATE_NOT_TAKEN,4,0); fEA_REG(fREAD_FP()); if (fLSBOLDNOT(fREAD_P0())) { fLOAD(1,8,u,EA,tmp); tmp = fFRAME_UNSCRAMBLE(tmp); fWRITE_LR(fGETWORD(1,tmp)); fWRITE_FP(fGETWORD(0,tmp)); fWRITE_SP(EA+8);
|
||||
fJUMPR(REG_LR,fGETWORD(1,tmp),COF_TYPE_JUMPR);} else {LOAD_CANCEL(EA);} })
|
||||
|
||||
|
||||
|
||||
Q6INSN(SL2_return_tnew,"if (p0.new) dealloc_return:nt", ATTRIBS(A_JINDIRNEW,A_SUBINSN,A_LOAD,A_RETURN,A_RESTRICT_SLOT0ONLY), "Deallocate stack frame and return",
|
||||
{ fHIDE(size8u_t tmp;) fBRANCH_SPECULATE_STALL(fLSBNEW0,, SPECULATE_NOT_TAKEN , 4,3); fEA_REG(fREAD_FP()); if (fLSBNEW0) { fLOAD(1,8,u,EA,tmp); tmp = fFRAME_UNSCRAMBLE(tmp); fWRITE_LR(fGETWORD(1,tmp)); fWRITE_FP(fGETWORD(0,tmp)); fWRITE_SP(EA+8);
|
||||
fJUMPR(REG_LR,fGETWORD(1,tmp),COF_TYPE_JUMPR);} else {LOAD_CANCEL(EA);} })
|
||||
|
||||
Q6INSN(SL2_return_fnew,"if (!p0.new) dealloc_return:nt", ATTRIBS(A_JINDIRNEW,A_SUBINSN,A_LOAD,A_RETURN,A_RESTRICT_SLOT0ONLY), "Deallocate stack frame and return",
|
||||
{ fHIDE(size8u_t tmp;) fBRANCH_SPECULATE_STALL(fLSBNEW0NOT,, SPECULATE_NOT_TAKEN , 4,3); fEA_REG(fREAD_FP()); if (fLSBNEW0NOT) { fLOAD(1,8,u,EA,tmp); tmp = fFRAME_UNSCRAMBLE(tmp); fWRITE_LR(fGETWORD(1,tmp)); fWRITE_FP(fGETWORD(0,tmp)); fWRITE_SP(EA+8);
|
||||
fJUMPR(REG_LR,fGETWORD(1,tmp),COF_TYPE_JUMPR);} else {LOAD_CANCEL(EA);} })
|
||||
|
||||
|
||||
Q6INSN(SL2_jumpr31,"jumpr r31",ATTRIBS(A_SUBINSN,A_JINDIR,A_RESTRICT_SLOT0ONLY),"indirect unconditional jump",
|
||||
{ fJUMPR(REG_LR,fREAD_LR(),COF_TYPE_JUMPR);})
|
||||
|
||||
Q6INSN(SL2_jumpr31_t,"if (p0) jumpr r31",ATTRIBS(A_SUBINSN,A_JINDIROLD,A_RESTRICT_SLOT0ONLY),"indirect conditional jump if true",
|
||||
{fBRANCH_SPECULATE_STALL(fLSBOLD(fREAD_P0()),, SPECULATE_TAKEN,4,0); if (fLSBOLD(fREAD_P0())) {fJUMPR(REG_LR,fREAD_LR(),COF_TYPE_JUMPR);}})
|
||||
|
||||
Q6INSN(SL2_jumpr31_f,"if (!p0) jumpr r31",ATTRIBS(A_SUBINSN,A_JINDIROLD,A_RESTRICT_SLOT0ONLY),"indirect conditional jump if false",
|
||||
{fBRANCH_SPECULATE_STALL(fLSBOLDNOT(fREAD_P0()),, SPECULATE_TAKEN,4,0); if (fLSBOLDNOT(fREAD_P0())) {fJUMPR(REG_LR,fREAD_LR(),COF_TYPE_JUMPR);}})
|
||||
|
||||
|
||||
|
||||
Q6INSN(SL2_jumpr31_tnew,"if (p0.new) jumpr:nt r31",ATTRIBS(A_SUBINSN,A_JINDIRNEW,A_RESTRICT_SLOT0ONLY),"indirect conditional jump if true",
|
||||
{fBRANCH_SPECULATE_STALL(fLSBNEW0,, SPECULATE_NOT_TAKEN , 4,3); if (fLSBNEW0) {fJUMPR(REG_LR,fREAD_LR(),COF_TYPE_JUMPR);}})
|
||||
|
||||
Q6INSN(SL2_jumpr31_fnew,"if (!p0.new) jumpr:nt r31",ATTRIBS(A_SUBINSN,A_JINDIRNEW,A_RESTRICT_SLOT0ONLY),"indirect conditional jump if false",
|
||||
{fBRANCH_SPECULATE_STALL(fLSBNEW0NOT,, SPECULATE_NOT_TAKEN , 4,3); if (fLSBNEW0NOT) {fJUMPR(REG_LR,fREAD_LR(),COF_TYPE_JUMPR);}})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*****************************************************************/
|
||||
/* */
|
||||
/* St1/2 subinsns */
|
||||
/* */
|
||||
/*****************************************************************/
|
||||
|
||||
Q6INSN(SS1_storew_io, "memw(Rs16+#u4:2)=Rt16", ATTRIBS(A_STORE,A_SUBINSN), "store word", {fEA_RI(RsV,uiV); fSTORE(1,4,EA,RtV);})
|
||||
Q6INSN(SS1_storeb_io, "memb(Rs16+#u4:0)=Rt16", ATTRIBS(A_STORE,A_SUBINSN), "store byte", {fEA_RI(RsV,uiV); fSTORE(1,1,EA,fGETBYTE(0,RtV));})
|
||||
Q6INSN(SS2_storeh_io, "memh(Rs16+#u3:1)=Rt16", ATTRIBS(A_STORE,A_SUBINSN), "store half", {fEA_RI(RsV,uiV); fSTORE(1,2,EA,fGETHALF(0,RtV));})
|
||||
Q6INSN(SS2_stored_sp, "memd(r29+#s6:3)=Rtt8", ATTRIBS(A_STORE,A_SUBINSN), "store dword",{fEA_RI(fREAD_SP(),siV); fSTORE(1,8,EA,RttV);})
|
||||
Q6INSN(SS2_storew_sp, "memw(r29+#u5:2)=Rt16", ATTRIBS(A_STORE,A_SUBINSN), "store word", {fEA_RI(fREAD_SP(),uiV); fSTORE(1,4,EA,RtV);})
|
||||
Q6INSN(SS2_storewi0, "memw(Rs16+#u4:2)=#0", ATTRIBS(A_STORE,A_SUBINSN), "store word", {fEA_RI(RsV,uiV); fSTORE(1,4,EA,0);})
|
||||
Q6INSN(SS2_storebi0, "memb(Rs16+#u4:0)=#0", ATTRIBS(A_STORE,A_SUBINSN), "store byte", {fEA_RI(RsV,uiV); fSTORE(1,1,EA,0);})
|
||||
Q6INSN(SS2_storewi1, "memw(Rs16+#u4:2)=#1", ATTRIBS(A_STORE,A_SUBINSN), "store word", {fEA_RI(RsV,uiV); fSTORE(1,4,EA,1);})
|
||||
Q6INSN(SS2_storebi1, "memb(Rs16+#u4:0)=#1", ATTRIBS(A_STORE,A_SUBINSN), "store byte", {fEA_RI(RsV,uiV); fSTORE(1,1,EA,1);})
|
||||
|
||||
|
||||
Q6INSN(SS2_allocframe,"allocframe(#u5:3)", ATTRIBS(A_SUBINSN,A_STORE,A_RESTRICT_SLOT0ONLY), "Allocate stack frame",
|
||||
{ fEA_RI(fREAD_SP(),-8); fSTORE(1,8,EA,fFRAME_SCRAMBLE((fCAST8_8u(fREAD_LR()) << 32) | fCAST4_4u(fREAD_FP()))); fWRITE_FP(EA); fFRAMECHECK(EA-uiV,EA); fWRITE_SP(EA-uiV); })
|
68
target/hexagon/imported/system.idef
Normal file
68
target/hexagon/imported/system.idef
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* System Interface Instructions
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/********************************************/
|
||||
/* User->OS interface */
|
||||
/********************************************/
|
||||
|
||||
Q6INSN(J2_trap0,"trap0(#u8)",ATTRIBS(A_COF),
|
||||
"Trap to Operating System",
|
||||
fTRAP(0,uiV);
|
||||
)
|
||||
|
||||
Q6INSN(J2_pause,"pause(#u8)",ATTRIBS(A_COF),
|
||||
"Enter low-power state for #u8 cycles",{fPAUSE(uiV);})
|
||||
|
||||
Q6INSN(Y2_icinva,"icinva(Rs32)",ATTRIBS(A_ICOP,A_ICFLUSHOP),"Instruction Cache Invalidate Address",{fEA_REG(RsV); fICINVA(EA);})
|
||||
|
||||
Q6INSN(Y2_isync,"isync",ATTRIBS(),"Memory Synchronization",{fISYNC();})
|
||||
Q6INSN(Y2_barrier,"barrier",ATTRIBS(A_RESTRICT_SLOT0ONLY),"Memory Barrier",{fBARRIER();})
|
||||
Q6INSN(Y2_syncht,"syncht",ATTRIBS(A_RESTRICT_SLOT0ONLY),"Memory Synchronization",{fSYNCH();})
|
||||
|
||||
|
||||
Q6INSN(Y2_dcfetchbo,"dcfetch(Rs32+#u11:3)",ATTRIBS(A_RESTRICT_PREFERSLOT0,A_DCFETCH),"Data Cache Prefetch",{fEA_RI(RsV,uiV); fDCFETCH(EA);})
|
||||
|
||||
|
||||
Q6INSN(Y2_dczeroa,"dczeroa(Rs32)",ATTRIBS(A_STORE,A_RESTRICT_SLOT0ONLY,A_DCZEROA),"Zero an aligned 32-byte cacheline",{fEA_REG(RsV); fDCZEROA(EA);})
|
||||
Q6INSN(Y2_dccleana,"dccleana(Rs32)",ATTRIBS(A_RESTRICT_SLOT0ONLY,A_DCFLUSHOP),"Data Cache Clean Address",{fEA_REG(RsV); fDCCLEANA(EA);})
|
||||
Q6INSN(Y2_dccleaninva,"dccleaninva(Rs32)",ATTRIBS(A_RESTRICT_SLOT0ONLY,A_DCFLUSHOP),"Data Cache Clean and Invalidate Address",{fEA_REG(RsV); fDCCLEANINVA(EA);})
|
||||
Q6INSN(Y2_dcinva,"dcinva(Rs32)",ATTRIBS(A_RESTRICT_SLOT0ONLY,A_DCFLUSHOP),"Data Cache Invalidate Address",{fEA_REG(RsV); fDCCLEANINVA(EA);})
|
||||
|
||||
|
||||
Q6INSN(Y4_l2fetch,"l2fetch(Rs32,Rt32)",ATTRIBS(A_RESTRICT_SLOT0ONLY),"L2 Cache Prefetch",
|
||||
{ fL2FETCH(RsV,
|
||||
(RtV&0xff), /*height*/
|
||||
((RtV>>8)&0xff), /*width*/
|
||||
((RtV>>16)&0xffff), /*stride*/
|
||||
0); /*extra attrib flags*/
|
||||
})
|
||||
|
||||
|
||||
|
||||
Q6INSN(Y5_l2fetch,"l2fetch(Rs32,Rtt32)",ATTRIBS(A_RESTRICT_SLOT0ONLY),"L2 Cache Prefetch",
|
||||
{ fL2FETCH(RsV,
|
||||
fGETUHALF(0,RttV), /*height*/
|
||||
fGETUHALF(1,RttV), /*width*/
|
||||
fGETUHALF(2,RttV), /*stride*/
|
||||
fGETUHALF(3,RttV)); /*flags*/
|
||||
})
|
74
target/hexagon/insn.h
Normal file
74
target/hexagon/insn.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_INSN_H
|
||||
#define HEXAGON_INSN_H
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
#define INSTRUCTIONS_MAX 7 /* 2 pairs + loopend */
|
||||
#define REG_OPERANDS_MAX 5
|
||||
#define IMMEDS_MAX 2
|
||||
|
||||
struct Instruction;
|
||||
struct Packet;
|
||||
struct DisasContext;
|
||||
|
||||
typedef void (*SemanticInsn)(CPUHexagonState *env,
|
||||
struct DisasContext *ctx,
|
||||
struct Instruction *insn,
|
||||
struct Packet *pkt);
|
||||
|
||||
struct Instruction {
|
||||
SemanticInsn generate; /* pointer to genptr routine */
|
||||
uint8_t regno[REG_OPERANDS_MAX]; /* reg operands including predicates */
|
||||
uint16_t opcode;
|
||||
|
||||
uint32_t iclass:6;
|
||||
uint32_t slot:3;
|
||||
uint32_t part1:1; /*
|
||||
* cmp-jumps are split into two insns.
|
||||
* set for the compare and clear for the jump
|
||||
*/
|
||||
uint32_t extension_valid:1; /* Has a constant extender attached */
|
||||
uint32_t which_extended:1; /* If has an extender, which immediate */
|
||||
uint32_t is_endloop:1; /* This is an end of loop */
|
||||
uint32_t new_value_producer_slot:4;
|
||||
int32_t immed[IMMEDS_MAX]; /* immediate field */
|
||||
};
|
||||
|
||||
typedef struct Instruction Insn;
|
||||
|
||||
struct Packet {
|
||||
uint16_t num_insns;
|
||||
uint16_t encod_pkt_size_in_bytes;
|
||||
|
||||
/* Pre-decodes about COF */
|
||||
uint32_t pkt_has_cof:1; /* Has any change-of-flow */
|
||||
uint32_t pkt_has_endloop:1;
|
||||
|
||||
uint32_t pkt_has_dczeroa:1;
|
||||
|
||||
uint32_t pkt_has_store_s0:1;
|
||||
uint32_t pkt_has_store_s1:1;
|
||||
|
||||
Insn insn[INSTRUCTIONS_MAX];
|
||||
};
|
||||
|
||||
typedef struct Packet Packet;
|
||||
|
||||
#endif
|
37
target/hexagon/internal.h
Normal file
37
target/hexagon/internal.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_INTERNAL_H
|
||||
#define HEXAGON_INTERNAL_H
|
||||
|
||||
/*
|
||||
* Change HEX_DEBUG to 1 to turn on debugging output
|
||||
*/
|
||||
#define HEX_DEBUG 0
|
||||
#if HEX_DEBUG
|
||||
#define HEX_DEBUG_LOG(...) qemu_log(__VA_ARGS__)
|
||||
#else
|
||||
#define HEX_DEBUG_LOG(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
int hexagon_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
int hexagon_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
|
||||
void hexagon_debug(CPUHexagonState *env);
|
||||
|
||||
extern const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS];
|
||||
|
||||
#endif
|
592
target/hexagon/macros.h
Normal file
592
target/hexagon/macros.h
Normal file
@ -0,0 +1,592 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_MACROS_H
|
||||
#define HEXAGON_MACROS_H
|
||||
|
||||
#include "cpu.h"
|
||||
#include "hex_regs.h"
|
||||
#include "reg_fields.h"
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
#define READ_REG(dest, NUM) gen_read_reg(dest, NUM)
|
||||
#define READ_PREG(dest, NUM) gen_read_preg(dest, (NUM))
|
||||
#else
|
||||
#define READ_REG(NUM) (env->gpr[(NUM)])
|
||||
#define READ_PREG(NUM) (env->pred[NUM])
|
||||
|
||||
#define WRITE_RREG(NUM, VAL) log_reg_write(env, NUM, VAL, slot)
|
||||
#define WRITE_PREG(NUM, VAL) log_pred_write(env, NUM, VAL)
|
||||
#endif
|
||||
|
||||
#define PCALIGN 4
|
||||
#define PCALIGN_MASK (PCALIGN - 1)
|
||||
|
||||
#define GET_FIELD(FIELD, REGIN) \
|
||||
fEXTRACTU_BITS(REGIN, reg_field_info[FIELD].width, \
|
||||
reg_field_info[FIELD].offset)
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
#define GET_USR_FIELD(FIELD, DST) \
|
||||
tcg_gen_extract_tl(DST, hex_gpr[HEX_REG_USR], \
|
||||
reg_field_info[FIELD].offset, \
|
||||
reg_field_info[FIELD].width)
|
||||
|
||||
#define TYPE_INT(X) __builtin_types_compatible_p(typeof(X), int)
|
||||
#define TYPE_TCGV(X) __builtin_types_compatible_p(typeof(X), TCGv)
|
||||
#define TYPE_TCGV_I64(X) __builtin_types_compatible_p(typeof(X), TCGv_i64)
|
||||
|
||||
#define SET_USR_FIELD_FUNC(X) \
|
||||
__builtin_choose_expr(TYPE_INT(X), \
|
||||
gen_set_usr_fieldi, \
|
||||
__builtin_choose_expr(TYPE_TCGV(X), \
|
||||
gen_set_usr_field, (void)0))
|
||||
#define SET_USR_FIELD(FIELD, VAL) \
|
||||
SET_USR_FIELD_FUNC(VAL)(FIELD, VAL)
|
||||
#else
|
||||
#define GET_USR_FIELD(FIELD) \
|
||||
fEXTRACTU_BITS(env->gpr[HEX_REG_USR], reg_field_info[FIELD].width, \
|
||||
reg_field_info[FIELD].offset)
|
||||
|
||||
#define SET_USR_FIELD(FIELD, VAL) \
|
||||
fINSERT_BITS(env->gpr[HEX_REG_USR], reg_field_info[FIELD].width, \
|
||||
reg_field_info[FIELD].offset, (VAL))
|
||||
#endif
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
/*
|
||||
* Section 5.5 of the Hexagon V67 Programmer's Reference Manual
|
||||
*
|
||||
* Slot 1 store with slot 0 load
|
||||
* A slot 1 store operation with a slot 0 load operation can appear in a packet.
|
||||
* The packet attribute :mem_noshuf inhibits the instruction reordering that
|
||||
* would otherwise be done by the assembler. For example:
|
||||
* {
|
||||
* memw(R5) = R2 // slot 1 store
|
||||
* R3 = memh(R6) // slot 0 load
|
||||
* }:mem_noshuf
|
||||
* Unlike most packetized operations, these memory operations are not executed
|
||||
* in parallel (Section 3.3.1). Instead, the store instruction in Slot 1
|
||||
* effectively executes first, followed by the load instruction in Slot 0. If
|
||||
* the addresses of the two operations are overlapping, the load will receive
|
||||
* the newly stored data. This feature is supported in processor versions
|
||||
* V65 or greater.
|
||||
*
|
||||
*
|
||||
* For qemu, we look for a load in slot 0 when there is a store in slot 1
|
||||
* in the same packet. When we see this, we call a helper that merges the
|
||||
* bytes from the store buffer with the value loaded from memory.
|
||||
*/
|
||||
#define CHECK_NOSHUF \
|
||||
do { \
|
||||
if (insn->slot == 0 && pkt->pkt_has_store_s1) { \
|
||||
process_store(ctx, pkt, 1); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define MEM_LOAD1s(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
tcg_gen_qemu_ld8s(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
#define MEM_LOAD1u(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
tcg_gen_qemu_ld8u(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
#define MEM_LOAD2s(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
tcg_gen_qemu_ld16s(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
#define MEM_LOAD2u(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
tcg_gen_qemu_ld16u(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
#define MEM_LOAD4s(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
tcg_gen_qemu_ld32s(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
#define MEM_LOAD4u(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
tcg_gen_qemu_ld32s(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
#define MEM_LOAD8u(DST, VA) \
|
||||
do { \
|
||||
CHECK_NOSHUF; \
|
||||
tcg_gen_qemu_ld64(DST, VA, ctx->mem_idx); \
|
||||
} while (0)
|
||||
#else
|
||||
#define MEM_LOAD1s(VA) ((int8_t)mem_load1(env, slot, VA))
|
||||
#define MEM_LOAD1u(VA) ((uint8_t)mem_load1(env, slot, VA))
|
||||
#define MEM_LOAD2s(VA) ((int16_t)mem_load2(env, slot, VA))
|
||||
#define MEM_LOAD2u(VA) ((uint16_t)mem_load2(env, slot, VA))
|
||||
#define MEM_LOAD4s(VA) ((int32_t)mem_load4(env, slot, VA))
|
||||
#define MEM_LOAD4u(VA) ((uint32_t)mem_load4(env, slot, VA))
|
||||
#define MEM_LOAD8s(VA) ((int64_t)mem_load8(env, slot, VA))
|
||||
#define MEM_LOAD8u(VA) ((uint64_t)mem_load8(env, slot, VA))
|
||||
|
||||
#define MEM_STORE1(VA, DATA, SLOT) log_store32(env, VA, DATA, 1, SLOT)
|
||||
#define MEM_STORE2(VA, DATA, SLOT) log_store32(env, VA, DATA, 2, SLOT)
|
||||
#define MEM_STORE4(VA, DATA, SLOT) log_store32(env, VA, DATA, 4, SLOT)
|
||||
#define MEM_STORE8(VA, DATA, SLOT) log_store64(env, VA, DATA, 8, SLOT)
|
||||
#endif
|
||||
|
||||
#define CANCEL cancel_slot(env, slot)
|
||||
|
||||
#define LOAD_CANCEL(EA) do { CANCEL; } while (0)
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
static inline void gen_pred_cancel(TCGv pred, int slot_num)
|
||||
{
|
||||
TCGv slot_mask = tcg_const_tl(1 << slot_num);
|
||||
TCGv tmp = tcg_temp_new();
|
||||
TCGv zero = tcg_const_tl(0);
|
||||
TCGv one = tcg_const_tl(1);
|
||||
tcg_gen_or_tl(slot_mask, hex_slot_cancelled, slot_mask);
|
||||
tcg_gen_andi_tl(tmp, pred, 1);
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, hex_slot_cancelled, tmp, zero,
|
||||
slot_mask, hex_slot_cancelled);
|
||||
tcg_temp_free(slot_mask);
|
||||
tcg_temp_free(tmp);
|
||||
tcg_temp_free(zero);
|
||||
tcg_temp_free(one);
|
||||
}
|
||||
#define PRED_LOAD_CANCEL(PRED, EA) \
|
||||
gen_pred_cancel(PRED, insn->is_endloop ? 4 : insn->slot)
|
||||
#endif
|
||||
|
||||
#define STORE_CANCEL(EA) { env->slot_cancelled |= (1 << slot); }
|
||||
|
||||
#define fMAX(A, B) (((A) > (B)) ? (A) : (B))
|
||||
|
||||
#define fMIN(A, B) (((A) < (B)) ? (A) : (B))
|
||||
|
||||
#define fABS(A) (((A) < 0) ? (-(A)) : (A))
|
||||
#define fINSERT_BITS(REG, WIDTH, OFFSET, INVAL) \
|
||||
REG = ((WIDTH) ? deposit64(REG, (OFFSET), (WIDTH), (INVAL)) : REG)
|
||||
#define fEXTRACTU_BITS(INREG, WIDTH, OFFSET) \
|
||||
((WIDTH) ? extract64((INREG), (OFFSET), (WIDTH)) : 0LL)
|
||||
#define fEXTRACTU_BIDIR(INREG, WIDTH, OFFSET) \
|
||||
(fZXTN(WIDTH, 32, fBIDIR_LSHIFTR((INREG), (OFFSET), 4_8)))
|
||||
#define fEXTRACTU_RANGE(INREG, HIBIT, LOWBIT) \
|
||||
(((HIBIT) - (LOWBIT) + 1) ? \
|
||||
extract64((INREG), (LOWBIT), ((HIBIT) - (LOWBIT) + 1)) : \
|
||||
0LL)
|
||||
|
||||
#define f8BITSOF(VAL) ((VAL) ? 0xff : 0x00)
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
#define fLSBOLD(VAL) tcg_gen_andi_tl(LSB, (VAL), 1)
|
||||
#else
|
||||
#define fLSBOLD(VAL) ((VAL) & 1)
|
||||
#endif
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
#define fLSBNEW(PVAL) tcg_gen_mov_tl(LSB, (PVAL))
|
||||
#define fLSBNEW0 tcg_gen_mov_tl(LSB, hex_new_pred_value[0])
|
||||
#define fLSBNEW1 tcg_gen_mov_tl(LSB, hex_new_pred_value[1])
|
||||
#else
|
||||
#define fLSBNEW(PVAL) (PVAL)
|
||||
#define fLSBNEW0 new_pred_value(env, 0)
|
||||
#define fLSBNEW1 new_pred_value(env, 1)
|
||||
#endif
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
static inline void gen_logical_not(TCGv dest, TCGv src)
|
||||
{
|
||||
TCGv one = tcg_const_tl(1);
|
||||
TCGv zero = tcg_const_tl(0);
|
||||
|
||||
tcg_gen_movcond_tl(TCG_COND_NE, dest, src, zero, zero, one);
|
||||
|
||||
tcg_temp_free(one);
|
||||
tcg_temp_free(zero);
|
||||
}
|
||||
#define fLSBOLDNOT(VAL) \
|
||||
do { \
|
||||
tcg_gen_andi_tl(LSB, (VAL), 1); \
|
||||
tcg_gen_xori_tl(LSB, LSB, 1); \
|
||||
} while (0)
|
||||
#define fLSBNEWNOT(PNUM) \
|
||||
gen_logical_not(LSB, (PNUM))
|
||||
#else
|
||||
#define fLSBNEWNOT(PNUM) (!fLSBNEW(PNUM))
|
||||
#define fLSBOLDNOT(VAL) (!fLSBOLD(VAL))
|
||||
#define fLSBNEW0NOT (!fLSBNEW0)
|
||||
#define fLSBNEW1NOT (!fLSBNEW1)
|
||||
#endif
|
||||
|
||||
#define fNEWREG(VAL) ((int32_t)(VAL))
|
||||
|
||||
#define fNEWREG_ST(VAL) (VAL)
|
||||
|
||||
#define fSATUVALN(N, VAL) \
|
||||
({ \
|
||||
fSET_OVERFLOW(); \
|
||||
((VAL) < 0) ? 0 : ((1LL << (N)) - 1); \
|
||||
})
|
||||
#define fSATVALN(N, VAL) \
|
||||
({ \
|
||||
fSET_OVERFLOW(); \
|
||||
((VAL) < 0) ? (-(1LL << ((N) - 1))) : ((1LL << ((N) - 1)) - 1); \
|
||||
})
|
||||
#define fZXTN(N, M, VAL) (((N) != 0) ? extract64((VAL), 0, (N)) : 0LL)
|
||||
#define fSXTN(N, M, VAL) (((N) != 0) ? sextract64((VAL), 0, (N)) : 0LL)
|
||||
#define fSATN(N, VAL) \
|
||||
((fSXTN(N, 64, VAL) == (VAL)) ? (VAL) : fSATVALN(N, VAL))
|
||||
#define fADDSAT64(DST, A, B) \
|
||||
do { \
|
||||
uint64_t __a = fCAST8u(A); \
|
||||
uint64_t __b = fCAST8u(B); \
|
||||
uint64_t __sum = __a + __b; \
|
||||
uint64_t __xor = __a ^ __b; \
|
||||
const uint64_t __mask = 0x8000000000000000ULL; \
|
||||
if (__xor & __mask) { \
|
||||
DST = __sum; \
|
||||
} \
|
||||
else if ((__a ^ __sum) & __mask) { \
|
||||
if (__sum & __mask) { \
|
||||
DST = 0x7FFFFFFFFFFFFFFFLL; \
|
||||
fSET_OVERFLOW(); \
|
||||
} else { \
|
||||
DST = 0x8000000000000000LL; \
|
||||
fSET_OVERFLOW(); \
|
||||
} \
|
||||
} else { \
|
||||
DST = __sum; \
|
||||
} \
|
||||
} while (0)
|
||||
#define fSATUN(N, VAL) \
|
||||
((fZXTN(N, 64, VAL) == (VAL)) ? (VAL) : fSATUVALN(N, VAL))
|
||||
#define fSATH(VAL) (fSATN(16, VAL))
|
||||
#define fSATUH(VAL) (fSATUN(16, VAL))
|
||||
#define fSATUB(VAL) (fSATUN(8, VAL))
|
||||
#define fSATB(VAL) (fSATN(8, VAL))
|
||||
#define fIMMEXT(IMM) (IMM = IMM)
|
||||
#define fMUST_IMMEXT(IMM) fIMMEXT(IMM)
|
||||
|
||||
#define fPCALIGN(IMM) IMM = (IMM & ~PCALIGN_MASK)
|
||||
|
||||
#define fREAD_LR() (READ_REG(HEX_REG_LR))
|
||||
|
||||
#define fWRITE_LR(A) WRITE_RREG(HEX_REG_LR, A)
|
||||
#define fWRITE_FP(A) WRITE_RREG(HEX_REG_FP, A)
|
||||
#define fWRITE_SP(A) WRITE_RREG(HEX_REG_SP, A)
|
||||
|
||||
#define fREAD_SP() (READ_REG(HEX_REG_SP))
|
||||
#define fREAD_LC0 (READ_REG(HEX_REG_LC0))
|
||||
#define fREAD_LC1 (READ_REG(HEX_REG_LC1))
|
||||
#define fREAD_SA0 (READ_REG(HEX_REG_SA0))
|
||||
#define fREAD_SA1 (READ_REG(HEX_REG_SA1))
|
||||
#define fREAD_FP() (READ_REG(HEX_REG_FP))
|
||||
#ifdef FIXME
|
||||
/* Figure out how to get insn->extension_valid to helper */
|
||||
#define fREAD_GP() \
|
||||
(insn->extension_valid ? 0 : READ_REG(HEX_REG_GP))
|
||||
#else
|
||||
#define fREAD_GP() READ_REG(HEX_REG_GP)
|
||||
#endif
|
||||
#define fREAD_PC() (READ_REG(HEX_REG_PC))
|
||||
|
||||
#define fREAD_NPC() (env->next_PC & (0xfffffffe))
|
||||
|
||||
#define fREAD_P0() (READ_PREG(0))
|
||||
#define fREAD_P3() (READ_PREG(3))
|
||||
|
||||
#define fCHECK_PCALIGN(A)
|
||||
|
||||
#define fWRITE_NPC(A) write_new_pc(env, A)
|
||||
|
||||
#define fBRANCH(LOC, TYPE) fWRITE_NPC(LOC)
|
||||
#define fJUMPR(REGNO, TARGET, TYPE) fBRANCH(TARGET, COF_TYPE_JUMPR)
|
||||
#define fHINTJR(TARGET) { /* Not modelled in qemu */}
|
||||
#define fCALL(A) \
|
||||
do { \
|
||||
fWRITE_LR(fREAD_NPC()); \
|
||||
fBRANCH(A, COF_TYPE_CALL); \
|
||||
} while (0)
|
||||
#define fCALLR(A) \
|
||||
do { \
|
||||
fWRITE_LR(fREAD_NPC()); \
|
||||
fBRANCH(A, COF_TYPE_CALLR); \
|
||||
} while (0)
|
||||
#define fWRITE_LOOP_REGS0(START, COUNT) \
|
||||
do { \
|
||||
WRITE_RREG(HEX_REG_LC0, COUNT); \
|
||||
WRITE_RREG(HEX_REG_SA0, START); \
|
||||
} while (0)
|
||||
#define fWRITE_LOOP_REGS1(START, COUNT) \
|
||||
do { \
|
||||
WRITE_RREG(HEX_REG_LC1, COUNT); \
|
||||
WRITE_RREG(HEX_REG_SA1, START);\
|
||||
} while (0)
|
||||
#define fWRITE_LC0(VAL) WRITE_RREG(HEX_REG_LC0, VAL)
|
||||
#define fWRITE_LC1(VAL) WRITE_RREG(HEX_REG_LC1, VAL)
|
||||
|
||||
#define fCARRY_FROM_ADD(A, B, C) carry_from_add64(A, B, C)
|
||||
|
||||
#define fSET_OVERFLOW() SET_USR_FIELD(USR_OVF, 1)
|
||||
#define fSET_LPCFG(VAL) SET_USR_FIELD(USR_LPCFG, (VAL))
|
||||
#define fGET_LPCFG (GET_USR_FIELD(USR_LPCFG))
|
||||
#define fWRITE_P0(VAL) WRITE_PREG(0, VAL)
|
||||
#define fWRITE_P1(VAL) WRITE_PREG(1, VAL)
|
||||
#define fWRITE_P2(VAL) WRITE_PREG(2, VAL)
|
||||
#define fWRITE_P3(VAL) WRITE_PREG(3, VAL)
|
||||
#define fPART1(WORK) if (part1) { WORK; return; }
|
||||
#define fCAST4u(A) ((uint32_t)(A))
|
||||
#define fCAST4s(A) ((int32_t)(A))
|
||||
#define fCAST8u(A) ((uint64_t)(A))
|
||||
#define fCAST8s(A) ((int64_t)(A))
|
||||
#define fCAST4_4s(A) ((int32_t)(A))
|
||||
#define fCAST4_4u(A) ((uint32_t)(A))
|
||||
#define fCAST4_8s(A) ((int64_t)((int32_t)(A)))
|
||||
#define fCAST4_8u(A) ((uint64_t)((uint32_t)(A)))
|
||||
#define fCAST8_8s(A) ((int64_t)(A))
|
||||
#define fCAST8_8u(A) ((uint64_t)(A))
|
||||
#define fCAST2_8s(A) ((int64_t)((int16_t)(A)))
|
||||
#define fCAST2_8u(A) ((uint64_t)((uint16_t)(A)))
|
||||
#define fZE8_16(A) ((int16_t)((uint8_t)(A)))
|
||||
#define fSE8_16(A) ((int16_t)((int8_t)(A)))
|
||||
#define fSE16_32(A) ((int32_t)((int16_t)(A)))
|
||||
#define fZE16_32(A) ((uint32_t)((uint16_t)(A)))
|
||||
#define fSE32_64(A) ((int64_t)((int32_t)(A)))
|
||||
#define fZE32_64(A) ((uint64_t)((uint32_t)(A)))
|
||||
#define fSE8_32(A) ((int32_t)((int8_t)(A)))
|
||||
#define fZE8_32(A) ((int32_t)((uint8_t)(A)))
|
||||
#define fMPY8UU(A, B) (int)(fZE8_16(A) * fZE8_16(B))
|
||||
#define fMPY8US(A, B) (int)(fZE8_16(A) * fSE8_16(B))
|
||||
#define fMPY8SU(A, B) (int)(fSE8_16(A) * fZE8_16(B))
|
||||
#define fMPY8SS(A, B) (int)((short)(A) * (short)(B))
|
||||
#define fMPY16SS(A, B) fSE32_64(fSE16_32(A) * fSE16_32(B))
|
||||
#define fMPY16UU(A, B) fZE32_64(fZE16_32(A) * fZE16_32(B))
|
||||
#define fMPY16SU(A, B) fSE32_64(fSE16_32(A) * fZE16_32(B))
|
||||
#define fMPY16US(A, B) fMPY16SU(B, A)
|
||||
#define fMPY32SS(A, B) (fSE32_64(A) * fSE32_64(B))
|
||||
#define fMPY32UU(A, B) (fZE32_64(A) * fZE32_64(B))
|
||||
#define fMPY32SU(A, B) (fSE32_64(A) * fZE32_64(B))
|
||||
#define fMPY3216SS(A, B) (fSE32_64(A) * fSXTN(16, 64, B))
|
||||
#define fMPY3216SU(A, B) (fSE32_64(A) * fZXTN(16, 64, B))
|
||||
#define fROUND(A) (A + 0x8000)
|
||||
#define fCLIP(DST, SRC, U) \
|
||||
do { \
|
||||
int32_t maxv = (1 << U) - 1; \
|
||||
int32_t minv = -(1 << U); \
|
||||
DST = fMIN(maxv, fMAX(SRC, minv)); \
|
||||
} while (0)
|
||||
#define fCRND(A) ((((A) & 0x3) == 0x3) ? ((A) + 1) : ((A)))
|
||||
#define fRNDN(A, N) ((((N) == 0) ? (A) : (((fSE32_64(A)) + (1 << ((N) - 1))))))
|
||||
#define fCRNDN(A, N) (conv_round(A, N))
|
||||
#define fADD128(A, B) (int128_add(A, B))
|
||||
#define fSUB128(A, B) (int128_sub(A, B))
|
||||
#define fSHIFTR128(A, B) (int128_rshift(A, B))
|
||||
#define fSHIFTL128(A, B) (int128_lshift(A, B))
|
||||
#define fAND128(A, B) (int128_and(A, B))
|
||||
#define fCAST8S_16S(A) (int128_exts64(A))
|
||||
#define fCAST16S_8S(A) (int128_getlo(A))
|
||||
|
||||
#define fEA_RI(REG, IMM) \
|
||||
do { \
|
||||
EA = REG + IMM; \
|
||||
} while (0)
|
||||
#define fEA_RRs(REG, REG2, SCALE) \
|
||||
do { \
|
||||
EA = REG + (REG2 << SCALE); \
|
||||
} while (0)
|
||||
#define fEA_IRs(IMM, REG, SCALE) \
|
||||
do { \
|
||||
EA = IMM + (REG << SCALE); \
|
||||
} while (0)
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
#define fEA_IMM(IMM) tcg_gen_movi_tl(EA, IMM)
|
||||
#define fEA_REG(REG) tcg_gen_mov_tl(EA, REG)
|
||||
#define fPM_I(REG, IMM) tcg_gen_addi_tl(REG, REG, IMM)
|
||||
#define fPM_M(REG, MVAL) tcg_gen_add_tl(REG, REG, MVAL)
|
||||
#else
|
||||
#define fEA_IMM(IMM) do { EA = (IMM); } while (0)
|
||||
#define fEA_REG(REG) do { EA = (REG); } while (0)
|
||||
#define fEA_GPI(IMM) do { EA = (fREAD_GP() + (IMM)); } while (0)
|
||||
#define fPM_I(REG, IMM) do { REG = REG + (IMM); } while (0)
|
||||
#define fPM_M(REG, MVAL) do { REG = REG + (MVAL); } while (0)
|
||||
#endif
|
||||
#define fSCALE(N, A) (((int64_t)(A)) << N)
|
||||
#define fSATW(A) fSATN(32, ((long long)A))
|
||||
#define fSAT(A) fSATN(32, (A))
|
||||
#define fSAT_ORIG_SHL(A, ORIG_REG) \
|
||||
((((int32_t)((fSAT(A)) ^ ((int32_t)(ORIG_REG)))) < 0) \
|
||||
? fSATVALN(32, ((int32_t)(ORIG_REG))) \
|
||||
: ((((ORIG_REG) > 0) && ((A) == 0)) ? fSATVALN(32, (ORIG_REG)) \
|
||||
: fSAT(A)))
|
||||
#define fPASS(A) A
|
||||
#define fBIDIR_SHIFTL(SRC, SHAMT, REGSTYPE) \
|
||||
(((SHAMT) < 0) ? ((fCAST##REGSTYPE(SRC) >> ((-(SHAMT)) - 1)) >> 1) \
|
||||
: (fCAST##REGSTYPE(SRC) << (SHAMT)))
|
||||
#define fBIDIR_ASHIFTL(SRC, SHAMT, REGSTYPE) \
|
||||
fBIDIR_SHIFTL(SRC, SHAMT, REGSTYPE##s)
|
||||
#define fBIDIR_LSHIFTL(SRC, SHAMT, REGSTYPE) \
|
||||
fBIDIR_SHIFTL(SRC, SHAMT, REGSTYPE##u)
|
||||
#define fBIDIR_ASHIFTL_SAT(SRC, SHAMT, REGSTYPE) \
|
||||
(((SHAMT) < 0) ? ((fCAST##REGSTYPE##s(SRC) >> ((-(SHAMT)) - 1)) >> 1) \
|
||||
: fSAT_ORIG_SHL(fCAST##REGSTYPE##s(SRC) << (SHAMT), (SRC)))
|
||||
#define fBIDIR_SHIFTR(SRC, SHAMT, REGSTYPE) \
|
||||
(((SHAMT) < 0) ? ((fCAST##REGSTYPE(SRC) << ((-(SHAMT)) - 1)) << 1) \
|
||||
: (fCAST##REGSTYPE(SRC) >> (SHAMT)))
|
||||
#define fBIDIR_ASHIFTR(SRC, SHAMT, REGSTYPE) \
|
||||
fBIDIR_SHIFTR(SRC, SHAMT, REGSTYPE##s)
|
||||
#define fBIDIR_LSHIFTR(SRC, SHAMT, REGSTYPE) \
|
||||
fBIDIR_SHIFTR(SRC, SHAMT, REGSTYPE##u)
|
||||
#define fBIDIR_ASHIFTR_SAT(SRC, SHAMT, REGSTYPE) \
|
||||
(((SHAMT) < 0) ? fSAT_ORIG_SHL((fCAST##REGSTYPE##s(SRC) \
|
||||
<< ((-(SHAMT)) - 1)) << 1, (SRC)) \
|
||||
: (fCAST##REGSTYPE##s(SRC) >> (SHAMT)))
|
||||
#define fASHIFTR(SRC, SHAMT, REGSTYPE) (fCAST##REGSTYPE##s(SRC) >> (SHAMT))
|
||||
#define fLSHIFTR(SRC, SHAMT, REGSTYPE) \
|
||||
(((SHAMT) >= 64) ? 0 : (fCAST##REGSTYPE##u(SRC) >> (SHAMT)))
|
||||
#define fROTL(SRC, SHAMT, REGSTYPE) \
|
||||
(((SHAMT) == 0) ? (SRC) : ((fCAST##REGSTYPE##u(SRC) << (SHAMT)) | \
|
||||
((fCAST##REGSTYPE##u(SRC) >> \
|
||||
((sizeof(SRC) * 8) - (SHAMT))))))
|
||||
#define fROTR(SRC, SHAMT, REGSTYPE) \
|
||||
(((SHAMT) == 0) ? (SRC) : ((fCAST##REGSTYPE##u(SRC) >> (SHAMT)) | \
|
||||
((fCAST##REGSTYPE##u(SRC) << \
|
||||
((sizeof(SRC) * 8) - (SHAMT))))))
|
||||
#define fASHIFTL(SRC, SHAMT, REGSTYPE) \
|
||||
(((SHAMT) >= 64) ? 0 : (fCAST##REGSTYPE##s(SRC) << (SHAMT)))
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
#define fLOAD(NUM, SIZE, SIGN, EA, DST) MEM_LOAD##SIZE##SIGN(DST, EA)
|
||||
#else
|
||||
#define fLOAD(NUM, SIZE, SIGN, EA, DST) \
|
||||
DST = (size##SIZE##SIGN##_t)MEM_LOAD##SIZE##SIGN(EA)
|
||||
#endif
|
||||
|
||||
#define fMEMOP(NUM, SIZE, SIGN, EA, FNTYPE, VALUE)
|
||||
|
||||
#define fGET_FRAMEKEY() READ_REG(HEX_REG_FRAMEKEY)
|
||||
#define fFRAME_SCRAMBLE(VAL) ((VAL) ^ (fCAST8u(fGET_FRAMEKEY()) << 32))
|
||||
#define fFRAME_UNSCRAMBLE(VAL) fFRAME_SCRAMBLE(VAL)
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
#define fFRAMECHECK(ADDR, EA) do { } while (0) /* Not modelled in linux-user */
|
||||
#else
|
||||
/* System mode not implemented yet */
|
||||
#define fFRAMECHECK(ADDR, EA) g_assert_not_reached();
|
||||
#endif
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
#define fLOAD_LOCKED(NUM, SIZE, SIGN, EA, DST) \
|
||||
gen_load_locked##SIZE##SIGN(DST, EA, ctx->mem_idx);
|
||||
#endif
|
||||
|
||||
#define fSTORE(NUM, SIZE, EA, SRC) MEM_STORE##SIZE(EA, SRC, slot)
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
#define fSTORE_LOCKED(NUM, SIZE, EA, SRC, PRED) \
|
||||
gen_store_conditional##SIZE(env, ctx, PdN, PRED, EA, SRC);
|
||||
#endif
|
||||
|
||||
#define fGETBYTE(N, SRC) ((int8_t)((SRC >> ((N) * 8)) & 0xff))
|
||||
#define fGETUBYTE(N, SRC) ((uint8_t)((SRC >> ((N) * 8)) & 0xff))
|
||||
|
||||
#define fSETBYTE(N, DST, VAL) \
|
||||
do { \
|
||||
DST = (DST & ~(0x0ffLL << ((N) * 8))) | \
|
||||
(((uint64_t)((VAL) & 0x0ffLL)) << ((N) * 8)); \
|
||||
} while (0)
|
||||
#define fGETHALF(N, SRC) ((int16_t)((SRC >> ((N) * 16)) & 0xffff))
|
||||
#define fGETUHALF(N, SRC) ((uint16_t)((SRC >> ((N) * 16)) & 0xffff))
|
||||
#define fSETHALF(N, DST, VAL) \
|
||||
do { \
|
||||
DST = (DST & ~(0x0ffffLL << ((N) * 16))) | \
|
||||
(((uint64_t)((VAL) & 0x0ffff)) << ((N) * 16)); \
|
||||
} while (0)
|
||||
#define fSETHALFw fSETHALF
|
||||
#define fSETHALFd fSETHALF
|
||||
|
||||
#define fGETWORD(N, SRC) \
|
||||
((int64_t)((int32_t)((SRC >> ((N) * 32)) & 0x0ffffffffLL)))
|
||||
#define fGETUWORD(N, SRC) \
|
||||
((uint64_t)((uint32_t)((SRC >> ((N) * 32)) & 0x0ffffffffLL)))
|
||||
|
||||
#define fSETWORD(N, DST, VAL) \
|
||||
do { \
|
||||
DST = (DST & ~(0x0ffffffffLL << ((N) * 32))) | \
|
||||
(((VAL) & 0x0ffffffffLL) << ((N) * 32)); \
|
||||
} while (0)
|
||||
|
||||
#define fSETBIT(N, DST, VAL) \
|
||||
do { \
|
||||
DST = (DST & ~(1ULL << (N))) | (((uint64_t)(VAL)) << (N)); \
|
||||
} while (0)
|
||||
|
||||
#define fGETBIT(N, SRC) (((SRC) >> N) & 1)
|
||||
#define fSETBITS(HI, LO, DST, VAL) \
|
||||
do { \
|
||||
int j; \
|
||||
for (j = LO; j <= HI; j++) { \
|
||||
fSETBIT(j, DST, VAL); \
|
||||
} \
|
||||
} while (0)
|
||||
#define fCOUNTONES_4(VAL) ctpop32(VAL)
|
||||
#define fCOUNTONES_8(VAL) ctpop64(VAL)
|
||||
#define fBREV_8(VAL) revbit64(VAL)
|
||||
#define fBREV_4(VAL) revbit32(VAL)
|
||||
#define fCL1_8(VAL) clo64(VAL)
|
||||
#define fCL1_4(VAL) clo32(VAL)
|
||||
#define fINTERLEAVE(ODD, EVEN) interleave(ODD, EVEN)
|
||||
#define fDEINTERLEAVE(MIXED) deinterleave(MIXED)
|
||||
#define fHIDE(A) A
|
||||
#define fCONSTLL(A) A##LL
|
||||
#define fECHO(A) (A)
|
||||
|
||||
#define fTRAP(TRAPTYPE, IMM) helper_raise_exception(env, HEX_EXCP_TRAP0)
|
||||
#define fPAUSE(IMM)
|
||||
|
||||
#define fALIGN_REG_FIELD_VALUE(FIELD, VAL) \
|
||||
((VAL) << reg_field_info[FIELD].offset)
|
||||
#define fGET_REG_FIELD_MASK(FIELD) \
|
||||
(((1 << reg_field_info[FIELD].width) - 1) << reg_field_info[FIELD].offset)
|
||||
#define fREAD_REG_FIELD(REG, FIELD) \
|
||||
fEXTRACTU_BITS(env->gpr[HEX_REG_##REG], \
|
||||
reg_field_info[FIELD].width, \
|
||||
reg_field_info[FIELD].offset)
|
||||
#define fGET_FIELD(VAL, FIELD)
|
||||
#define fSET_FIELD(VAL, FIELD, NEWVAL)
|
||||
#define fBARRIER()
|
||||
#define fSYNCH()
|
||||
#define fISYNC()
|
||||
#define fDCFETCH(REG) \
|
||||
do { (void)REG; } while (0) /* Nothing to do in qemu */
|
||||
#define fICINVA(REG) \
|
||||
do { (void)REG; } while (0) /* Nothing to do in qemu */
|
||||
#define fL2FETCH(ADDR, HEIGHT, WIDTH, STRIDE, FLAGS)
|
||||
#define fDCCLEANA(REG) \
|
||||
do { (void)REG; } while (0) /* Nothing to do in qemu */
|
||||
#define fDCCLEANINVA(REG) \
|
||||
do { (void)REG; } while (0) /* Nothing to do in qemu */
|
||||
|
||||
#define fDCZEROA(REG) do { env->dczero_addr = (REG); } while (0)
|
||||
|
||||
#define fBRANCH_SPECULATE_STALL(DOTNEWVAL, JUMP_COND, SPEC_DIR, HINTBITNUM, \
|
||||
STRBITNUM) /* Nothing */
|
||||
|
||||
|
||||
#endif
|
191
target/hexagon/meson.build
Normal file
191
target/hexagon/meson.build
Normal file
@ -0,0 +1,191 @@
|
||||
##
|
||||
## Copyright(c) 2020-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
hexagon_ss = ss.source_set()
|
||||
|
||||
hex_common_py = 'hex_common.py'
|
||||
attribs_def = meson.current_source_dir() / 'attribs_def.h.inc'
|
||||
gen_tcg_h = meson.current_source_dir() / 'gen_tcg.h'
|
||||
|
||||
#
|
||||
# Step 1
|
||||
# We use a C program to create semantics_generated.pyinc
|
||||
#
|
||||
gen_semantics = executable(
|
||||
'gen_semantics',
|
||||
'gen_semantics.c',
|
||||
native: true, build_by_default: false)
|
||||
|
||||
semantics_generated = custom_target(
|
||||
'semantics_generated.pyinc',
|
||||
output: 'semantics_generated.pyinc',
|
||||
input: gen_semantics,
|
||||
command: ['@INPUT@', '@OUTPUT@'],
|
||||
)
|
||||
hexagon_ss.add(semantics_generated)
|
||||
|
||||
#
|
||||
# Step 2
|
||||
# We use Python scripts to generate the following files
|
||||
# shortcode_generated.h.inc
|
||||
# helper_protos_generated.h.inc
|
||||
# tcg_funcs_generated.c.inc
|
||||
# tcg_func_table_generated.c.inc
|
||||
# helper_funcs_generated.c.inc
|
||||
# printinsn_generated.h.inc
|
||||
# op_regs_generated.h.inc
|
||||
# op_attribs_generated.h.inc
|
||||
# opcodes_def_generated.h.inc
|
||||
#
|
||||
shortcode_generated = custom_target(
|
||||
'shortcode_generated.h.inc',
|
||||
output: 'shortcode_generated.h.inc',
|
||||
input: 'gen_shortcode.py',
|
||||
depends: [semantics_generated],
|
||||
depend_files: [hex_common_py, attribs_def],
|
||||
command: [python, '@INPUT@', semantics_generated, attribs_def, '@OUTPUT@'],
|
||||
)
|
||||
hexagon_ss.add(shortcode_generated)
|
||||
|
||||
helper_protos_generated = custom_target(
|
||||
'helper_protos_generated.h.inc',
|
||||
output: 'helper_protos_generated.h.inc',
|
||||
input: 'gen_helper_protos.py',
|
||||
depends: [semantics_generated],
|
||||
depend_files: [hex_common_py, attribs_def, gen_tcg_h],
|
||||
command: [python, '@INPUT@', semantics_generated, attribs_def, gen_tcg_h, '@OUTPUT@'],
|
||||
)
|
||||
hexagon_ss.add(helper_protos_generated)
|
||||
|
||||
tcg_funcs_generated = custom_target(
|
||||
'tcg_funcs_generated.c.inc',
|
||||
output: 'tcg_funcs_generated.c.inc',
|
||||
input: 'gen_tcg_funcs.py',
|
||||
depends: [semantics_generated],
|
||||
depend_files: [hex_common_py, attribs_def, gen_tcg_h],
|
||||
command: [python, '@INPUT@', semantics_generated, attribs_def, gen_tcg_h, '@OUTPUT@'],
|
||||
)
|
||||
hexagon_ss.add(tcg_funcs_generated)
|
||||
|
||||
tcg_func_table_generated = custom_target(
|
||||
'tcg_func_table_generated.c.inc',
|
||||
output: 'tcg_func_table_generated.c.inc',
|
||||
input: 'gen_tcg_func_table.py',
|
||||
depends: [semantics_generated],
|
||||
depend_files: [hex_common_py, attribs_def],
|
||||
command: [python, '@INPUT@', semantics_generated, attribs_def, '@OUTPUT@'],
|
||||
)
|
||||
hexagon_ss.add(tcg_func_table_generated)
|
||||
|
||||
helper_funcs_generated = custom_target(
|
||||
'helper_funcs_generated.c.inc',
|
||||
output: 'helper_funcs_generated.c.inc',
|
||||
input: 'gen_helper_funcs.py',
|
||||
depends: [semantics_generated],
|
||||
depend_files: [hex_common_py, attribs_def, gen_tcg_h],
|
||||
command: [python, '@INPUT@', semantics_generated, attribs_def, gen_tcg_h, '@OUTPUT@'],
|
||||
)
|
||||
hexagon_ss.add(helper_funcs_generated)
|
||||
|
||||
printinsn_generated = custom_target(
|
||||
'printinsn_generated.h.inc',
|
||||
output: 'printinsn_generated.h.inc',
|
||||
input: 'gen_printinsn.py',
|
||||
depends: [semantics_generated],
|
||||
depend_files: [hex_common_py, attribs_def],
|
||||
command: [python, '@INPUT@', semantics_generated, attribs_def, '@OUTPUT@'],
|
||||
)
|
||||
hexagon_ss.add(printinsn_generated)
|
||||
|
||||
op_regs_generated = custom_target(
|
||||
'op_regs_generated.h.inc',
|
||||
output: 'op_regs_generated.h.inc',
|
||||
input: 'gen_op_regs.py',
|
||||
depends: [semantics_generated],
|
||||
depend_files: [hex_common_py, attribs_def],
|
||||
command: [python, '@INPUT@', semantics_generated, attribs_def, '@OUTPUT@'],
|
||||
)
|
||||
hexagon_ss.add(op_regs_generated)
|
||||
|
||||
op_attribs_generated = custom_target(
|
||||
'op_attribs_generated.h.inc',
|
||||
output: 'op_attribs_generated.h.inc',
|
||||
input: 'gen_op_attribs.py',
|
||||
depends: [semantics_generated],
|
||||
depend_files: [hex_common_py, attribs_def],
|
||||
command: [python, '@INPUT@', semantics_generated, attribs_def, '@OUTPUT@'],
|
||||
)
|
||||
hexagon_ss.add(op_attribs_generated)
|
||||
|
||||
opcodes_def_generated = custom_target(
|
||||
'opcodes_def_generated.h.inc',
|
||||
output: 'opcodes_def_generated.h.inc',
|
||||
input: 'gen_opcodes_def.py',
|
||||
depends: [semantics_generated],
|
||||
depend_files: [hex_common_py, attribs_def],
|
||||
command: [python, '@INPUT@', semantics_generated, attribs_def, '@OUTPUT@'],
|
||||
)
|
||||
hexagon_ss.add(opcodes_def_generated)
|
||||
|
||||
#
|
||||
# Step 3
|
||||
# We use a C program to create iset.py which is imported into dectree.py
|
||||
# to create the decode tree
|
||||
#
|
||||
gen_dectree_import = executable(
|
||||
'gen_dectree_import',
|
||||
'gen_dectree_import.c', opcodes_def_generated, op_regs_generated,
|
||||
native: true, build_by_default: false)
|
||||
|
||||
iset_py = custom_target(
|
||||
'iset.py',
|
||||
output: 'iset.py',
|
||||
input: gen_dectree_import,
|
||||
command: ['@INPUT@', '@OUTPUT@'],
|
||||
)
|
||||
hexagon_ss.add(iset_py)
|
||||
|
||||
#
|
||||
# Step 4
|
||||
# We use the dectree.py script to generate the decode tree header file
|
||||
#
|
||||
dectree_generated = custom_target(
|
||||
'dectree_generated.h.inc',
|
||||
output: 'dectree_generated.h.inc',
|
||||
input: 'dectree.py',
|
||||
depends: [iset_py],
|
||||
command: ['PYTHONPATH=' + meson.current_build_dir(), '@INPUT@', '@OUTPUT@'],
|
||||
)
|
||||
hexagon_ss.add(dectree_generated)
|
||||
|
||||
hexagon_ss.add(files(
|
||||
'cpu.c',
|
||||
'translate.c',
|
||||
'op_helper.c',
|
||||
'gdbstub.c',
|
||||
'genptr.c',
|
||||
'reg_fields.c',
|
||||
'decode.c',
|
||||
'iclass.c',
|
||||
'opcodes.c',
|
||||
'printinsn.c',
|
||||
'arch.c',
|
||||
'fma_emu.c',
|
||||
'conv_emu.c',
|
||||
))
|
||||
|
||||
target_arch += {'hexagon': hexagon_ss}
|
1064
target/hexagon/op_helper.c
Normal file
1064
target/hexagon/op_helper.c
Normal file
File diff suppressed because it is too large
Load Diff
142
target/hexagon/opcodes.c
Normal file
142
target/hexagon/opcodes.c
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* opcodes.c
|
||||
*
|
||||
* data tables generated automatically
|
||||
* Maybe some functions too
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "attribs.h"
|
||||
#include "decode.h"
|
||||
|
||||
#define VEC_DESCR(A, B, C) DESCR(A, B, C)
|
||||
#define DONAME(X) #X
|
||||
|
||||
const char * const opcode_names[] = {
|
||||
#define OPCODE(IID) DONAME(IID)
|
||||
#include "opcodes_def_generated.h.inc"
|
||||
NULL
|
||||
#undef OPCODE
|
||||
};
|
||||
|
||||
const char * const opcode_reginfo[] = {
|
||||
#define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */
|
||||
#define REGINFO(TAG, REGINFO, RREGS, WREGS) REGINFO,
|
||||
#include "op_regs_generated.h.inc"
|
||||
NULL
|
||||
#undef REGINFO
|
||||
#undef IMMINFO
|
||||
};
|
||||
|
||||
|
||||
const char * const opcode_rregs[] = {
|
||||
#define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */
|
||||
#define REGINFO(TAG, REGINFO, RREGS, WREGS) RREGS,
|
||||
#include "op_regs_generated.h.inc"
|
||||
NULL
|
||||
#undef REGINFO
|
||||
#undef IMMINFO
|
||||
};
|
||||
|
||||
|
||||
const char * const opcode_wregs[] = {
|
||||
#define IMMINFO(TAG, SIGN, SIZE, SHAMT, SIGN2, SIZE2, SHAMT2) /* nothing */
|
||||
#define REGINFO(TAG, REGINFO, RREGS, WREGS) WREGS,
|
||||
#include "op_regs_generated.h.inc"
|
||||
NULL
|
||||
#undef REGINFO
|
||||
#undef IMMINFO
|
||||
};
|
||||
|
||||
const char * const opcode_short_semantics[] = {
|
||||
#define DEF_SHORTCODE(TAG, SHORTCODE) [TAG] = #SHORTCODE,
|
||||
#include "shortcode_generated.h.inc"
|
||||
#undef DEF_SHORTCODE
|
||||
NULL
|
||||
};
|
||||
|
||||
DECLARE_BITMAP(opcode_attribs[XX_LAST_OPCODE], A_ZZ_LASTATTRIB);
|
||||
|
||||
static void init_attribs(int tag, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int attr;
|
||||
va_start(ap, tag);
|
||||
while ((attr = va_arg(ap, int)) != 0) {
|
||||
set_bit(attr, opcode_attribs[tag]);
|
||||
}
|
||||
}
|
||||
|
||||
const OpcodeEncoding opcode_encodings[] = {
|
||||
#define DEF_ENC32(OPCODE, ENCSTR) \
|
||||
[OPCODE] = { .encoding = ENCSTR },
|
||||
|
||||
#define DEF_ENC_SUBINSN(OPCODE, CLASS, ENCSTR) \
|
||||
[OPCODE] = { .encoding = ENCSTR, .enc_class = CLASS },
|
||||
|
||||
#define DEF_EXT_ENC(OPCODE, CLASS, ENCSTR) \
|
||||
[OPCODE] = { .encoding = ENCSTR, .enc_class = CLASS },
|
||||
|
||||
#include "imported/encode.def"
|
||||
|
||||
#undef DEF_ENC32
|
||||
#undef DEF_ENC_SUBINSN
|
||||
#undef DEF_EXT_ENC
|
||||
};
|
||||
|
||||
void opcode_init(void)
|
||||
{
|
||||
init_attribs(0, 0);
|
||||
|
||||
#define ATTRIBS(...) , ## __VA_ARGS__, 0
|
||||
#define OP_ATTRIB(TAG, ARGS) init_attribs(TAG ARGS);
|
||||
#include "op_attribs_generated.h.inc"
|
||||
#undef OP_ATTRIB
|
||||
#undef ATTRIBS
|
||||
|
||||
decode_init();
|
||||
}
|
||||
|
||||
|
||||
#define NEEDLE "IMMEXT("
|
||||
|
||||
int opcode_which_immediate_is_extended(Opcode opcode)
|
||||
{
|
||||
const char *p;
|
||||
|
||||
g_assert(opcode < XX_LAST_OPCODE);
|
||||
g_assert(GET_ATTRIB(opcode, A_EXTENDABLE));
|
||||
|
||||
p = opcode_short_semantics[opcode];
|
||||
p = strstr(p, NEEDLE);
|
||||
g_assert(p);
|
||||
p += strlen(NEEDLE);
|
||||
while (isspace(*p)) {
|
||||
p++;
|
||||
}
|
||||
/* lower is always imm 0, upper always imm 1. */
|
||||
if (islower(*p)) {
|
||||
return 0;
|
||||
} else if (isupper(*p)) {
|
||||
return 1;
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
58
target/hexagon/opcodes.h
Normal file
58
target/hexagon/opcodes.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_OPCODES_H
|
||||
#define HEXAGON_OPCODES_H
|
||||
|
||||
typedef enum {
|
||||
#define OPCODE(IID) IID
|
||||
#include "opcodes_def_generated.h.inc"
|
||||
XX_LAST_OPCODE
|
||||
#undef OPCODE
|
||||
} Opcode;
|
||||
|
||||
typedef enum {
|
||||
NORMAL,
|
||||
HALF,
|
||||
SUBINSN_A,
|
||||
SUBINSN_L1,
|
||||
SUBINSN_L2,
|
||||
SUBINSN_S1,
|
||||
SUBINSN_S2,
|
||||
EXT_noext,
|
||||
EXT_mmvec,
|
||||
XX_LAST_ENC_CLASS
|
||||
} EncClass;
|
||||
|
||||
extern const char * const opcode_names[];
|
||||
|
||||
extern const char * const opcode_reginfo[];
|
||||
extern const char * const opcode_rregs[];
|
||||
extern const char * const opcode_wregs[];
|
||||
|
||||
typedef struct {
|
||||
const char * const encoding;
|
||||
const EncClass enc_class;
|
||||
} OpcodeEncoding;
|
||||
|
||||
extern const OpcodeEncoding opcode_encodings[XX_LAST_OPCODE];
|
||||
|
||||
void opcode_init(void);
|
||||
|
||||
int opcode_which_immediate_is_extended(Opcode opcode);
|
||||
|
||||
#endif
|
146
target/hexagon/printinsn.c
Normal file
146
target/hexagon/printinsn.c
Normal file
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "attribs.h"
|
||||
#include "printinsn.h"
|
||||
#include "insn.h"
|
||||
#include "reg_fields.h"
|
||||
#include "internal.h"
|
||||
|
||||
static const char *sreg2str(unsigned int reg)
|
||||
{
|
||||
if (reg < TOTAL_PER_THREAD_REGS) {
|
||||
return hexagon_regnames[reg];
|
||||
} else {
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *creg2str(unsigned int reg)
|
||||
{
|
||||
return sreg2str(reg + HEX_REG_SA0);
|
||||
}
|
||||
|
||||
static void snprintinsn(GString *buf, Insn *insn)
|
||||
{
|
||||
switch (insn->opcode) {
|
||||
#define DEF_VECX_PRINTINFO(TAG, FMT, ...) DEF_PRINTINFO(TAG, FMT, __VA_ARGS__)
|
||||
#define DEF_PRINTINFO(TAG, FMT, ...) \
|
||||
case TAG: \
|
||||
g_string_append_printf(buf, FMT, __VA_ARGS__); \
|
||||
break;
|
||||
#include "printinsn_generated.h.inc"
|
||||
#undef DEF_VECX_PRINTINFO
|
||||
#undef DEF_PRINTINFO
|
||||
}
|
||||
}
|
||||
|
||||
void snprint_a_pkt_disas(GString *buf, Packet *pkt, uint32_t *words,
|
||||
target_ulong pc)
|
||||
{
|
||||
bool has_endloop0 = false;
|
||||
bool has_endloop1 = false;
|
||||
bool has_endloop01 = false;
|
||||
|
||||
for (int i = 0; i < pkt->num_insns; i++) {
|
||||
if (pkt->insn[i].part1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We'll print the endloop's at the end of the packet */
|
||||
if (pkt->insn[i].opcode == J2_endloop0) {
|
||||
has_endloop0 = true;
|
||||
continue;
|
||||
}
|
||||
if (pkt->insn[i].opcode == J2_endloop1) {
|
||||
has_endloop1 = true;
|
||||
continue;
|
||||
}
|
||||
if (pkt->insn[i].opcode == J2_endloop01) {
|
||||
has_endloop01 = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
g_string_append_printf(buf, "0x" TARGET_FMT_lx "\t", words[i]);
|
||||
|
||||
if (i == 0) {
|
||||
g_string_append(buf, "{");
|
||||
}
|
||||
|
||||
g_string_append(buf, "\t");
|
||||
snprintinsn(buf, &(pkt->insn[i]));
|
||||
|
||||
if (i < pkt->num_insns - 1) {
|
||||
/*
|
||||
* Subinstructions are two instructions encoded
|
||||
* in the same word. Print them on the same line.
|
||||
*/
|
||||
if (GET_ATTRIB(pkt->insn[i].opcode, A_SUBINSN)) {
|
||||
g_string_append(buf, "; ");
|
||||
snprintinsn(buf, &(pkt->insn[i + 1]));
|
||||
i++;
|
||||
} else if (pkt->insn[i + 1].opcode != J2_endloop0 &&
|
||||
pkt->insn[i + 1].opcode != J2_endloop1 &&
|
||||
pkt->insn[i + 1].opcode != J2_endloop01) {
|
||||
pc += 4;
|
||||
g_string_append_printf(buf, "\n0x" TARGET_FMT_lx ": ", pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_string_append(buf, " }");
|
||||
if (has_endloop0) {
|
||||
g_string_append(buf, " :endloop0");
|
||||
}
|
||||
if (has_endloop1) {
|
||||
g_string_append(buf, " :endloop1");
|
||||
}
|
||||
if (has_endloop01) {
|
||||
g_string_append(buf, " :endloop01");
|
||||
}
|
||||
}
|
||||
|
||||
void snprint_a_pkt_debug(GString *buf, Packet *pkt)
|
||||
{
|
||||
int slot, opcode;
|
||||
|
||||
if (pkt->num_insns > 1) {
|
||||
g_string_append(buf, "\n{\n");
|
||||
}
|
||||
|
||||
for (int i = 0; i < pkt->num_insns; i++) {
|
||||
if (pkt->insn[i].part1) {
|
||||
continue;
|
||||
}
|
||||
g_string_append(buf, "\t");
|
||||
snprintinsn(buf, &(pkt->insn[i]));
|
||||
|
||||
if (GET_ATTRIB(pkt->insn[i].opcode, A_SUBINSN)) {
|
||||
g_string_append(buf, " //subinsn");
|
||||
}
|
||||
if (pkt->insn[i].extension_valid) {
|
||||
g_string_append(buf, " //constant extended");
|
||||
}
|
||||
slot = pkt->insn[i].slot;
|
||||
opcode = pkt->insn[i].opcode;
|
||||
g_string_append_printf(buf, " //slot=%d:tag=%s\n",
|
||||
slot, opcode_names[opcode]);
|
||||
}
|
||||
if (pkt->num_insns > 1) {
|
||||
g_string_append(buf, "}\n");
|
||||
}
|
||||
}
|
27
target/hexagon/printinsn.h
Normal file
27
target/hexagon/printinsn.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_PRINTINSN_H
|
||||
#define HEXAGON_PRINTINSN_H
|
||||
|
||||
#include "insn.h"
|
||||
|
||||
void snprint_a_pkt_disas(GString *buf, Packet *pkt, uint32_t *words,
|
||||
target_ulong pc);
|
||||
void snprint_a_pkt_debug(GString *buf, Packet *pkt);
|
||||
|
||||
#endif
|
27
target/hexagon/reg_fields.c
Normal file
27
target/hexagon/reg_fields.c
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "reg_fields.h"
|
||||
|
||||
const RegField reg_field_info[] = {
|
||||
#define DEF_REG_FIELD(TAG, START, WIDTH) \
|
||||
{ START, WIDTH },
|
||||
#include "reg_fields_def.h.inc"
|
||||
{ 0, 0 }
|
||||
#undef DEF_REG_FIELD
|
||||
};
|
36
target/hexagon/reg_fields.h
Normal file
36
target/hexagon/reg_fields.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_REG_FIELDS_H
|
||||
#define HEXAGON_REG_FIELDS_H
|
||||
|
||||
typedef struct {
|
||||
int offset;
|
||||
int width;
|
||||
} RegField;
|
||||
|
||||
extern const RegField reg_field_info[];
|
||||
|
||||
enum {
|
||||
#define DEF_REG_FIELD(TAG, START, WIDTH) \
|
||||
TAG,
|
||||
#include "reg_fields_def.h.inc"
|
||||
NUM_REG_FIELDS
|
||||
#undef DEF_REG_FIELD
|
||||
};
|
||||
|
||||
#endif
|
41
target/hexagon/reg_fields_def.h.inc
Normal file
41
target/hexagon/reg_fields_def.h.inc
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* For registers that have individual fields, explain them here
|
||||
* DEF_REG_FIELD(tag,
|
||||
* bit start offset,
|
||||
* width
|
||||
*/
|
||||
|
||||
/* USR fields */
|
||||
DEF_REG_FIELD(USR_OVF, 0, 1)
|
||||
DEF_REG_FIELD(USR_FPINVF, 1, 1)
|
||||
DEF_REG_FIELD(USR_FPDBZF, 2, 1)
|
||||
DEF_REG_FIELD(USR_FPOVFF, 3, 1)
|
||||
DEF_REG_FIELD(USR_FPUNFF, 4, 1)
|
||||
DEF_REG_FIELD(USR_FPINPF, 5, 1)
|
||||
|
||||
DEF_REG_FIELD(USR_LPCFG, 8, 2)
|
||||
|
||||
DEF_REG_FIELD(USR_FPRND, 22, 2)
|
||||
|
||||
DEF_REG_FIELD(USR_FPINVE, 25, 1)
|
||||
DEF_REG_FIELD(USR_FPDBZE, 26, 1)
|
||||
DEF_REG_FIELD(USR_FPOVFE, 27, 1)
|
||||
DEF_REG_FIELD(USR_FPUNFE, 28, 1)
|
||||
DEF_REG_FIELD(USR_FPINPE, 29, 1)
|
748
target/hexagon/translate.c
Normal file
748
target/hexagon/translate.c
Normal file
@ -0,0 +1,748 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define QEMU_GENERATE
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/log.h"
|
||||
#include "internal.h"
|
||||
#include "attribs.h"
|
||||
#include "insn.h"
|
||||
#include "decode.h"
|
||||
#include "translate.h"
|
||||
#include "printinsn.h"
|
||||
|
||||
TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
|
||||
TCGv hex_pred[NUM_PREGS];
|
||||
TCGv hex_next_PC;
|
||||
TCGv hex_this_PC;
|
||||
TCGv hex_slot_cancelled;
|
||||
TCGv hex_branch_taken;
|
||||
TCGv hex_new_value[TOTAL_PER_THREAD_REGS];
|
||||
#if HEX_DEBUG
|
||||
TCGv hex_reg_written[TOTAL_PER_THREAD_REGS];
|
||||
#endif
|
||||
TCGv hex_new_pred_value[NUM_PREGS];
|
||||
TCGv hex_pred_written;
|
||||
TCGv hex_store_addr[STORES_MAX];
|
||||
TCGv hex_store_width[STORES_MAX];
|
||||
TCGv hex_store_val32[STORES_MAX];
|
||||
TCGv_i64 hex_store_val64[STORES_MAX];
|
||||
TCGv hex_pkt_has_store_s1;
|
||||
TCGv hex_dczero_addr;
|
||||
TCGv hex_llsc_addr;
|
||||
TCGv hex_llsc_val;
|
||||
TCGv_i64 hex_llsc_val_i64;
|
||||
|
||||
static const char * const hexagon_prednames[] = {
|
||||
"p0", "p1", "p2", "p3"
|
||||
};
|
||||
|
||||
void gen_exception(int excp)
|
||||
{
|
||||
TCGv_i32 helper_tmp = tcg_const_i32(excp);
|
||||
gen_helper_raise_exception(cpu_env, helper_tmp);
|
||||
tcg_temp_free_i32(helper_tmp);
|
||||
}
|
||||
|
||||
void gen_exception_debug(void)
|
||||
{
|
||||
gen_exception(EXCP_DEBUG);
|
||||
}
|
||||
|
||||
#if HEX_DEBUG
|
||||
#define PACKET_BUFFER_LEN 1028
|
||||
static void print_pkt(Packet *pkt)
|
||||
{
|
||||
GString *buf = g_string_sized_new(PACKET_BUFFER_LEN);
|
||||
snprint_a_pkt_debug(buf, pkt);
|
||||
HEX_DEBUG_LOG("%s", buf->str);
|
||||
g_string_free(buf, true);
|
||||
}
|
||||
#define HEX_DEBUG_PRINT_PKT(pkt) print_pkt(pkt)
|
||||
#else
|
||||
#define HEX_DEBUG_PRINT_PKT(pkt) /* nothing */
|
||||
#endif
|
||||
|
||||
static int read_packet_words(CPUHexagonState *env, DisasContext *ctx,
|
||||
uint32_t words[])
|
||||
{
|
||||
bool found_end = false;
|
||||
int nwords, max_words;
|
||||
|
||||
memset(words, 0, PACKET_WORDS_MAX * sizeof(uint32_t));
|
||||
for (nwords = 0; !found_end && nwords < PACKET_WORDS_MAX; nwords++) {
|
||||
words[nwords] = cpu_ldl_code(env,
|
||||
ctx->base.pc_next + nwords * sizeof(uint32_t));
|
||||
found_end = is_packet_end(words[nwords]);
|
||||
}
|
||||
if (!found_end) {
|
||||
/* Read too many words without finding the end */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check for page boundary crossing */
|
||||
max_words = -(ctx->base.pc_next | TARGET_PAGE_MASK) / sizeof(uint32_t);
|
||||
if (nwords > max_words) {
|
||||
/* We can only cross a page boundary at the beginning of a TB */
|
||||
g_assert(ctx->base.num_insns == 1);
|
||||
}
|
||||
|
||||
HEX_DEBUG_LOG("decode_packet: pc = 0x%x\n", ctx->base.pc_next);
|
||||
HEX_DEBUG_LOG(" words = { ");
|
||||
for (int i = 0; i < nwords; i++) {
|
||||
HEX_DEBUG_LOG("0x%x, ", words[i]);
|
||||
}
|
||||
HEX_DEBUG_LOG("}\n");
|
||||
|
||||
return nwords;
|
||||
}
|
||||
|
||||
static bool check_for_attrib(Packet *pkt, int attrib)
|
||||
{
|
||||
for (int i = 0; i < pkt->num_insns; i++) {
|
||||
if (GET_ATTRIB(pkt->insn[i].opcode, attrib)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool need_pc(Packet *pkt)
|
||||
{
|
||||
return check_for_attrib(pkt, A_IMPLICIT_READS_PC);
|
||||
}
|
||||
|
||||
static bool need_slot_cancelled(Packet *pkt)
|
||||
{
|
||||
return check_for_attrib(pkt, A_CONDEXEC);
|
||||
}
|
||||
|
||||
static bool need_pred_written(Packet *pkt)
|
||||
{
|
||||
return check_for_attrib(pkt, A_WRITES_PRED_REG);
|
||||
}
|
||||
|
||||
static void gen_start_packet(DisasContext *ctx, Packet *pkt)
|
||||
{
|
||||
target_ulong next_PC = ctx->base.pc_next + pkt->encod_pkt_size_in_bytes;
|
||||
int i;
|
||||
|
||||
/* Clear out the disassembly context */
|
||||
ctx->reg_log_idx = 0;
|
||||
bitmap_zero(ctx->regs_written, TOTAL_PER_THREAD_REGS);
|
||||
ctx->preg_log_idx = 0;
|
||||
for (i = 0; i < STORES_MAX; i++) {
|
||||
ctx->store_width[i] = 0;
|
||||
}
|
||||
tcg_gen_movi_tl(hex_pkt_has_store_s1, pkt->pkt_has_store_s1);
|
||||
ctx->s1_store_processed = 0;
|
||||
|
||||
#if HEX_DEBUG
|
||||
/* Handy place to set a breakpoint before the packet executes */
|
||||
gen_helper_debug_start_packet(cpu_env);
|
||||
tcg_gen_movi_tl(hex_this_PC, ctx->base.pc_next);
|
||||
#endif
|
||||
|
||||
/* Initialize the runtime state for packet semantics */
|
||||
if (need_pc(pkt)) {
|
||||
tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->base.pc_next);
|
||||
}
|
||||
if (need_slot_cancelled(pkt)) {
|
||||
tcg_gen_movi_tl(hex_slot_cancelled, 0);
|
||||
}
|
||||
if (pkt->pkt_has_cof) {
|
||||
tcg_gen_movi_tl(hex_branch_taken, 0);
|
||||
tcg_gen_movi_tl(hex_next_PC, next_PC);
|
||||
}
|
||||
if (need_pred_written(pkt)) {
|
||||
tcg_gen_movi_tl(hex_pred_written, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The LOG_*_WRITE macros mark most of the writes in a packet
|
||||
* However, there are some implicit writes marked as attributes
|
||||
* of the applicable instructions.
|
||||
*/
|
||||
static void mark_implicit_reg_write(DisasContext *ctx, Insn *insn,
|
||||
int attrib, int rnum)
|
||||
{
|
||||
if (GET_ATTRIB(insn->opcode, attrib)) {
|
||||
int is_predicated = GET_ATTRIB(insn->opcode, A_CONDEXEC);
|
||||
if (is_predicated && !is_preloaded(ctx, rnum)) {
|
||||
tcg_gen_mov_tl(hex_new_value[rnum], hex_gpr[rnum]);
|
||||
}
|
||||
|
||||
ctx_log_reg_write(ctx, rnum);
|
||||
}
|
||||
}
|
||||
|
||||
static void mark_implicit_pred_write(DisasContext *ctx, Insn *insn,
|
||||
int attrib, int pnum)
|
||||
{
|
||||
if (GET_ATTRIB(insn->opcode, attrib)) {
|
||||
ctx_log_pred_write(ctx, pnum);
|
||||
}
|
||||
}
|
||||
|
||||
static void mark_implicit_writes(DisasContext *ctx, Insn *insn)
|
||||
{
|
||||
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_FP, HEX_REG_FP);
|
||||
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SP, HEX_REG_SP);
|
||||
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_LR, HEX_REG_LR);
|
||||
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_LC0, HEX_REG_LC0);
|
||||
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SA0, HEX_REG_SA0);
|
||||
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_LC1, HEX_REG_LC1);
|
||||
mark_implicit_reg_write(ctx, insn, A_IMPLICIT_WRITES_SA1, HEX_REG_SA1);
|
||||
|
||||
mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P0, 0);
|
||||
mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P1, 1);
|
||||
mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P2, 2);
|
||||
mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P3, 3);
|
||||
}
|
||||
|
||||
static void gen_insn(CPUHexagonState *env, DisasContext *ctx,
|
||||
Insn *insn, Packet *pkt)
|
||||
{
|
||||
if (insn->generate) {
|
||||
mark_implicit_writes(ctx, insn);
|
||||
insn->generate(env, ctx, insn, pkt);
|
||||
} else {
|
||||
gen_exception(HEX_EXCP_INVALID_OPCODE);
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helpers for generating the packet commit
|
||||
*/
|
||||
static void gen_reg_writes(DisasContext *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ctx->reg_log_idx; i++) {
|
||||
int reg_num = ctx->reg_log[i];
|
||||
|
||||
tcg_gen_mov_tl(hex_gpr[reg_num], hex_new_value[reg_num]);
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_pred_writes(DisasContext *ctx, Packet *pkt)
|
||||
{
|
||||
TCGv zero, control_reg, pval;
|
||||
int i;
|
||||
|
||||
/* Early exit if the log is empty */
|
||||
if (!ctx->preg_log_idx) {
|
||||
return;
|
||||
}
|
||||
|
||||
zero = tcg_const_tl(0);
|
||||
control_reg = tcg_temp_new();
|
||||
pval = tcg_temp_new();
|
||||
|
||||
/*
|
||||
* Only endloop instructions will conditionally
|
||||
* write a predicate. If there are no endloop
|
||||
* instructions, we can use the non-conditional
|
||||
* write of the predicates.
|
||||
*/
|
||||
if (pkt->pkt_has_endloop) {
|
||||
TCGv pred_written = tcg_temp_new();
|
||||
for (i = 0; i < ctx->preg_log_idx; i++) {
|
||||
int pred_num = ctx->preg_log[i];
|
||||
|
||||
tcg_gen_andi_tl(pred_written, hex_pred_written, 1 << pred_num);
|
||||
tcg_gen_movcond_tl(TCG_COND_NE, hex_pred[pred_num],
|
||||
pred_written, zero,
|
||||
hex_new_pred_value[pred_num],
|
||||
hex_pred[pred_num]);
|
||||
}
|
||||
tcg_temp_free(pred_written);
|
||||
} else {
|
||||
for (i = 0; i < ctx->preg_log_idx; i++) {
|
||||
int pred_num = ctx->preg_log[i];
|
||||
tcg_gen_mov_tl(hex_pred[pred_num], hex_new_pred_value[pred_num]);
|
||||
#if HEX_DEBUG
|
||||
/* Do this so HELPER(debug_commit_end) will know */
|
||||
tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pred_num);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
tcg_temp_free(zero);
|
||||
tcg_temp_free(control_reg);
|
||||
tcg_temp_free(pval);
|
||||
}
|
||||
|
||||
#if HEX_DEBUG
|
||||
static inline void gen_check_store_width(DisasContext *ctx, int slot_num)
|
||||
{
|
||||
TCGv slot = tcg_const_tl(slot_num);
|
||||
TCGv check = tcg_const_tl(ctx->store_width[slot_num]);
|
||||
gen_helper_debug_check_store_width(cpu_env, slot, check);
|
||||
tcg_temp_free(slot);
|
||||
tcg_temp_free(check);
|
||||
}
|
||||
#define HEX_DEBUG_GEN_CHECK_STORE_WIDTH(ctx, slot_num) \
|
||||
gen_check_store_width(ctx, slot_num)
|
||||
#else
|
||||
#define HEX_DEBUG_GEN_CHECK_STORE_WIDTH(ctx, slot_num) /* nothing */
|
||||
#endif
|
||||
|
||||
static bool slot_is_predicated(Packet *pkt, int slot_num)
|
||||
{
|
||||
for (int i = 0; i < pkt->num_insns; i++) {
|
||||
if (pkt->insn[i].slot == slot_num) {
|
||||
return GET_ATTRIB(pkt->insn[i].opcode, A_CONDEXEC);
|
||||
}
|
||||
}
|
||||
/* If we get to here, we didn't find an instruction in the requested slot */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
void process_store(DisasContext *ctx, Packet *pkt, int slot_num)
|
||||
{
|
||||
bool is_predicated = slot_is_predicated(pkt, slot_num);
|
||||
TCGLabel *label_end = NULL;
|
||||
|
||||
/*
|
||||
* We may have already processed this store
|
||||
* See CHECK_NOSHUF in macros.h
|
||||
*/
|
||||
if (slot_num == 1 && ctx->s1_store_processed) {
|
||||
return;
|
||||
}
|
||||
ctx->s1_store_processed = 1;
|
||||
|
||||
if (is_predicated) {
|
||||
TCGv cancelled = tcg_temp_new();
|
||||
label_end = gen_new_label();
|
||||
|
||||
/* Don't do anything if the slot was cancelled */
|
||||
tcg_gen_extract_tl(cancelled, hex_slot_cancelled, slot_num, 1);
|
||||
tcg_gen_brcondi_tl(TCG_COND_NE, cancelled, 0, label_end);
|
||||
tcg_temp_free(cancelled);
|
||||
}
|
||||
{
|
||||
TCGv address = tcg_temp_local_new();
|
||||
tcg_gen_mov_tl(address, hex_store_addr[slot_num]);
|
||||
|
||||
/*
|
||||
* If we know the width from the DisasContext, we can
|
||||
* generate much cleaner code.
|
||||
* Unfortunately, not all instructions execute the fSTORE
|
||||
* macro during code generation. Anything that uses the
|
||||
* generic helper will have this problem. Instructions
|
||||
* that use fWRAP to generate proper TCG code will be OK.
|
||||
*/
|
||||
switch (ctx->store_width[slot_num]) {
|
||||
case 1:
|
||||
HEX_DEBUG_GEN_CHECK_STORE_WIDTH(ctx, slot_num);
|
||||
tcg_gen_qemu_st8(hex_store_val32[slot_num],
|
||||
hex_store_addr[slot_num],
|
||||
ctx->mem_idx);
|
||||
break;
|
||||
case 2:
|
||||
HEX_DEBUG_GEN_CHECK_STORE_WIDTH(ctx, slot_num);
|
||||
tcg_gen_qemu_st16(hex_store_val32[slot_num],
|
||||
hex_store_addr[slot_num],
|
||||
ctx->mem_idx);
|
||||
break;
|
||||
case 4:
|
||||
HEX_DEBUG_GEN_CHECK_STORE_WIDTH(ctx, slot_num);
|
||||
tcg_gen_qemu_st32(hex_store_val32[slot_num],
|
||||
hex_store_addr[slot_num],
|
||||
ctx->mem_idx);
|
||||
break;
|
||||
case 8:
|
||||
HEX_DEBUG_GEN_CHECK_STORE_WIDTH(ctx, slot_num);
|
||||
tcg_gen_qemu_st64(hex_store_val64[slot_num],
|
||||
hex_store_addr[slot_num],
|
||||
ctx->mem_idx);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
/*
|
||||
* If we get to here, we don't know the width at
|
||||
* TCG generation time, we'll use a helper to
|
||||
* avoid branching based on the width at runtime.
|
||||
*/
|
||||
TCGv slot = tcg_const_tl(slot_num);
|
||||
gen_helper_commit_store(cpu_env, slot);
|
||||
tcg_temp_free(slot);
|
||||
}
|
||||
}
|
||||
tcg_temp_free(address);
|
||||
}
|
||||
if (is_predicated) {
|
||||
gen_set_label(label_end);
|
||||
}
|
||||
}
|
||||
|
||||
static void process_store_log(DisasContext *ctx, Packet *pkt)
|
||||
{
|
||||
/*
|
||||
* When a packet has two stores, the hardware processes
|
||||
* slot 1 and then slot 2. This will be important when
|
||||
* the memory accesses overlap.
|
||||
*/
|
||||
if (pkt->pkt_has_store_s1 && !pkt->pkt_has_dczeroa) {
|
||||
process_store(ctx, pkt, 1);
|
||||
}
|
||||
if (pkt->pkt_has_store_s0 && !pkt->pkt_has_dczeroa) {
|
||||
process_store(ctx, pkt, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Zero out a 32-bit cache line */
|
||||
static void process_dczeroa(DisasContext *ctx, Packet *pkt)
|
||||
{
|
||||
if (pkt->pkt_has_dczeroa) {
|
||||
/* Store 32 bytes of zero starting at (addr & ~0x1f) */
|
||||
TCGv addr = tcg_temp_new();
|
||||
TCGv_i64 zero = tcg_const_i64(0);
|
||||
|
||||
tcg_gen_andi_tl(addr, hex_dczero_addr, ~0x1f);
|
||||
tcg_gen_qemu_st64(zero, addr, ctx->mem_idx);
|
||||
tcg_gen_addi_tl(addr, addr, 8);
|
||||
tcg_gen_qemu_st64(zero, addr, ctx->mem_idx);
|
||||
tcg_gen_addi_tl(addr, addr, 8);
|
||||
tcg_gen_qemu_st64(zero, addr, ctx->mem_idx);
|
||||
tcg_gen_addi_tl(addr, addr, 8);
|
||||
tcg_gen_qemu_st64(zero, addr, ctx->mem_idx);
|
||||
|
||||
tcg_temp_free(addr);
|
||||
tcg_temp_free_i64(zero);
|
||||
}
|
||||
}
|
||||
|
||||
static void update_exec_counters(DisasContext *ctx, Packet *pkt)
|
||||
{
|
||||
int num_insns = pkt->num_insns;
|
||||
int num_real_insns = 0;
|
||||
|
||||
for (int i = 0; i < num_insns; i++) {
|
||||
if (!pkt->insn[i].is_endloop &&
|
||||
!pkt->insn[i].part1 &&
|
||||
!GET_ATTRIB(pkt->insn[i].opcode, A_IT_NOP)) {
|
||||
num_real_insns++;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->num_packets++;
|
||||
ctx->num_insns += num_real_insns;
|
||||
}
|
||||
|
||||
static void gen_exec_counters(DisasContext *ctx)
|
||||
{
|
||||
tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_PKT_CNT],
|
||||
hex_gpr[HEX_REG_QEMU_PKT_CNT], ctx->num_packets);
|
||||
tcg_gen_addi_tl(hex_gpr[HEX_REG_QEMU_INSN_CNT],
|
||||
hex_gpr[HEX_REG_QEMU_INSN_CNT], ctx->num_insns);
|
||||
}
|
||||
|
||||
static void gen_commit_packet(DisasContext *ctx, Packet *pkt)
|
||||
{
|
||||
gen_reg_writes(ctx);
|
||||
gen_pred_writes(ctx, pkt);
|
||||
process_store_log(ctx, pkt);
|
||||
process_dczeroa(ctx, pkt);
|
||||
update_exec_counters(ctx, pkt);
|
||||
#if HEX_DEBUG
|
||||
{
|
||||
TCGv has_st0 =
|
||||
tcg_const_tl(pkt->pkt_has_store_s0 && !pkt->pkt_has_dczeroa);
|
||||
TCGv has_st1 =
|
||||
tcg_const_tl(pkt->pkt_has_store_s1 && !pkt->pkt_has_dczeroa);
|
||||
|
||||
/* Handy place to set a breakpoint at the end of execution */
|
||||
gen_helper_debug_commit_end(cpu_env, has_st0, has_st1);
|
||||
|
||||
tcg_temp_free(has_st0);
|
||||
tcg_temp_free(has_st1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pkt->pkt_has_cof) {
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_and_translate_packet(CPUHexagonState *env, DisasContext *ctx)
|
||||
{
|
||||
uint32_t words[PACKET_WORDS_MAX];
|
||||
int nwords;
|
||||
Packet pkt;
|
||||
int i;
|
||||
|
||||
nwords = read_packet_words(env, ctx, words);
|
||||
if (!nwords) {
|
||||
gen_exception(HEX_EXCP_INVALID_PACKET);
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
return;
|
||||
}
|
||||
|
||||
if (decode_packet(nwords, words, &pkt, false) > 0) {
|
||||
HEX_DEBUG_PRINT_PKT(&pkt);
|
||||
gen_start_packet(ctx, &pkt);
|
||||
for (i = 0; i < pkt.num_insns; i++) {
|
||||
gen_insn(env, ctx, &pkt.insn[i], &pkt);
|
||||
}
|
||||
gen_commit_packet(ctx, &pkt);
|
||||
ctx->base.pc_next += pkt.encod_pkt_size_in_bytes;
|
||||
} else {
|
||||
gen_exception(HEX_EXCP_INVALID_PACKET);
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
}
|
||||
|
||||
static void hexagon_tr_init_disas_context(DisasContextBase *dcbase,
|
||||
CPUState *cs)
|
||||
{
|
||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
|
||||
ctx->mem_idx = MMU_USER_IDX;
|
||||
ctx->num_packets = 0;
|
||||
ctx->num_insns = 0;
|
||||
}
|
||||
|
||||
static void hexagon_tr_tb_start(DisasContextBase *db, CPUState *cpu)
|
||||
{
|
||||
}
|
||||
|
||||
static void hexagon_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
|
||||
{
|
||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
|
||||
tcg_gen_insn_start(ctx->base.pc_next);
|
||||
}
|
||||
|
||||
static bool hexagon_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
|
||||
const CPUBreakpoint *bp)
|
||||
{
|
||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
|
||||
tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->base.pc_next);
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
gen_exception_debug();
|
||||
/*
|
||||
* The address covered by the breakpoint must be included in
|
||||
* [tb->pc, tb->pc + tb->size) in order to for it to be
|
||||
* properly cleared -- thus we increment the PC here so that
|
||||
* the logic setting tb->size below does the right thing.
|
||||
*/
|
||||
ctx->base.pc_next += 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool pkt_crosses_page(CPUHexagonState *env, DisasContext *ctx)
|
||||
{
|
||||
target_ulong page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
|
||||
bool found_end = false;
|
||||
int nwords;
|
||||
|
||||
for (nwords = 0; !found_end && nwords < PACKET_WORDS_MAX; nwords++) {
|
||||
uint32_t word = cpu_ldl_code(env,
|
||||
ctx->base.pc_next + nwords * sizeof(uint32_t));
|
||||
found_end = is_packet_end(word);
|
||||
}
|
||||
uint32_t next_ptr = ctx->base.pc_next + nwords * sizeof(uint32_t);
|
||||
return found_end && next_ptr - page_start >= TARGET_PAGE_SIZE;
|
||||
}
|
||||
|
||||
static void hexagon_tr_translate_packet(DisasContextBase *dcbase, CPUState *cpu)
|
||||
{
|
||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
CPUHexagonState *env = cpu->env_ptr;
|
||||
|
||||
decode_and_translate_packet(env, ctx);
|
||||
|
||||
if (ctx->base.is_jmp == DISAS_NEXT) {
|
||||
target_ulong page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
|
||||
target_ulong bytes_max = PACKET_WORDS_MAX * sizeof(target_ulong);
|
||||
|
||||
if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE ||
|
||||
(ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE - bytes_max &&
|
||||
pkt_crosses_page(env, ctx))) {
|
||||
ctx->base.is_jmp = DISAS_TOO_MANY;
|
||||
}
|
||||
|
||||
/*
|
||||
* The CPU log is used to compare against LLDB single stepping,
|
||||
* so end the TLB after every packet.
|
||||
*/
|
||||
HexagonCPU *hex_cpu = container_of(env, HexagonCPU, env);
|
||||
if (hex_cpu->lldb_compat && qemu_loglevel_mask(CPU_LOG_TB_CPU)) {
|
||||
ctx->base.is_jmp = DISAS_TOO_MANY;
|
||||
}
|
||||
#if HEX_DEBUG
|
||||
/* When debugging, only put one packet per TB */
|
||||
ctx->base.is_jmp = DISAS_TOO_MANY;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void hexagon_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
|
||||
{
|
||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
|
||||
switch (ctx->base.is_jmp) {
|
||||
case DISAS_TOO_MANY:
|
||||
gen_exec_counters(ctx);
|
||||
tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->base.pc_next);
|
||||
if (ctx->base.singlestep_enabled) {
|
||||
gen_exception_debug();
|
||||
} else {
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
}
|
||||
break;
|
||||
case DISAS_NORETURN:
|
||||
gen_exec_counters(ctx);
|
||||
tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], hex_next_PC);
|
||||
if (ctx->base.singlestep_enabled) {
|
||||
gen_exception_debug();
|
||||
} else {
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
static void hexagon_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
|
||||
{
|
||||
qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
|
||||
log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
|
||||
}
|
||||
|
||||
|
||||
static const TranslatorOps hexagon_tr_ops = {
|
||||
.init_disas_context = hexagon_tr_init_disas_context,
|
||||
.tb_start = hexagon_tr_tb_start,
|
||||
.insn_start = hexagon_tr_insn_start,
|
||||
.breakpoint_check = hexagon_tr_breakpoint_check,
|
||||
.translate_insn = hexagon_tr_translate_packet,
|
||||
.tb_stop = hexagon_tr_tb_stop,
|
||||
.disas_log = hexagon_tr_disas_log,
|
||||
};
|
||||
|
||||
void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
|
||||
{
|
||||
DisasContext ctx;
|
||||
|
||||
translator_loop(&hexagon_tr_ops, &ctx.base, cs, tb, max_insns);
|
||||
}
|
||||
|
||||
#define NAME_LEN 64
|
||||
static char new_value_names[TOTAL_PER_THREAD_REGS][NAME_LEN];
|
||||
#if HEX_DEBUG
|
||||
static char reg_written_names[TOTAL_PER_THREAD_REGS][NAME_LEN];
|
||||
#endif
|
||||
static char new_pred_value_names[NUM_PREGS][NAME_LEN];
|
||||
static char store_addr_names[STORES_MAX][NAME_LEN];
|
||||
static char store_width_names[STORES_MAX][NAME_LEN];
|
||||
static char store_val32_names[STORES_MAX][NAME_LEN];
|
||||
static char store_val64_names[STORES_MAX][NAME_LEN];
|
||||
|
||||
void hexagon_translate_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
opcode_init();
|
||||
|
||||
#if HEX_DEBUG
|
||||
if (!qemu_logfile) {
|
||||
qemu_set_log(qemu_loglevel);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
|
||||
hex_gpr[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, gpr[i]),
|
||||
hexagon_regnames[i]);
|
||||
|
||||
snprintf(new_value_names[i], NAME_LEN, "new_%s", hexagon_regnames[i]);
|
||||
hex_new_value[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, new_value[i]),
|
||||
new_value_names[i]);
|
||||
|
||||
#if HEX_DEBUG
|
||||
snprintf(reg_written_names[i], NAME_LEN, "reg_written_%s",
|
||||
hexagon_regnames[i]);
|
||||
hex_reg_written[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, reg_written[i]),
|
||||
reg_written_names[i]);
|
||||
#endif
|
||||
}
|
||||
for (i = 0; i < NUM_PREGS; i++) {
|
||||
hex_pred[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, pred[i]),
|
||||
hexagon_prednames[i]);
|
||||
|
||||
snprintf(new_pred_value_names[i], NAME_LEN, "new_pred_%s",
|
||||
hexagon_prednames[i]);
|
||||
hex_new_pred_value[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, new_pred_value[i]),
|
||||
new_pred_value_names[i]);
|
||||
}
|
||||
hex_pred_written = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, pred_written), "pred_written");
|
||||
hex_next_PC = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, next_PC), "next_PC");
|
||||
hex_this_PC = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, this_PC), "this_PC");
|
||||
hex_slot_cancelled = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, slot_cancelled), "slot_cancelled");
|
||||
hex_branch_taken = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, branch_taken), "branch_taken");
|
||||
hex_pkt_has_store_s1 = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, pkt_has_store_s1), "pkt_has_store_s1");
|
||||
hex_dczero_addr = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, dczero_addr), "dczero_addr");
|
||||
hex_llsc_addr = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, llsc_addr), "llsc_addr");
|
||||
hex_llsc_val = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, llsc_val), "llsc_val");
|
||||
hex_llsc_val_i64 = tcg_global_mem_new_i64(cpu_env,
|
||||
offsetof(CPUHexagonState, llsc_val_i64), "llsc_val_i64");
|
||||
for (i = 0; i < STORES_MAX; i++) {
|
||||
snprintf(store_addr_names[i], NAME_LEN, "store_addr_%d", i);
|
||||
hex_store_addr[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, mem_log_stores[i].va),
|
||||
store_addr_names[i]);
|
||||
|
||||
snprintf(store_width_names[i], NAME_LEN, "store_width_%d", i);
|
||||
hex_store_width[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, mem_log_stores[i].width),
|
||||
store_width_names[i]);
|
||||
|
||||
snprintf(store_val32_names[i], NAME_LEN, "store_val32_%d", i);
|
||||
hex_store_val32[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, mem_log_stores[i].data32),
|
||||
store_val32_names[i]);
|
||||
|
||||
snprintf(store_val64_names[i], NAME_LEN, "store_val64_%d", i);
|
||||
hex_store_val64[i] = tcg_global_mem_new_i64(cpu_env,
|
||||
offsetof(CPUHexagonState, mem_log_stores[i].data64),
|
||||
store_val64_names[i]);
|
||||
}
|
||||
}
|
93
target/hexagon/translate.h
Normal file
93
target/hexagon/translate.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HEXAGON_TRANSLATE_H
|
||||
#define HEXAGON_TRANSLATE_H
|
||||
|
||||
#include "qemu/bitmap.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/translator.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
#include "internal.h"
|
||||
|
||||
typedef struct DisasContext {
|
||||
DisasContextBase base;
|
||||
uint32_t mem_idx;
|
||||
uint32_t num_packets;
|
||||
uint32_t num_insns;
|
||||
int reg_log[REG_WRITES_MAX];
|
||||
int reg_log_idx;
|
||||
DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS);
|
||||
int preg_log[PRED_WRITES_MAX];
|
||||
int preg_log_idx;
|
||||
uint8_t store_width[STORES_MAX];
|
||||
uint8_t s1_store_processed;
|
||||
} DisasContext;
|
||||
|
||||
static inline void ctx_log_reg_write(DisasContext *ctx, int rnum)
|
||||
{
|
||||
#if HEX_DEBUG
|
||||
if (test_bit(rnum, ctx->regs_written)) {
|
||||
HEX_DEBUG_LOG("WARNING: Multiple writes to r%d\n", rnum);
|
||||
}
|
||||
#endif
|
||||
ctx->reg_log[ctx->reg_log_idx] = rnum;
|
||||
ctx->reg_log_idx++;
|
||||
set_bit(rnum, ctx->regs_written);
|
||||
}
|
||||
|
||||
static inline void ctx_log_reg_write_pair(DisasContext *ctx, int rnum)
|
||||
{
|
||||
ctx_log_reg_write(ctx, rnum);
|
||||
ctx_log_reg_write(ctx, rnum + 1);
|
||||
}
|
||||
|
||||
static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
|
||||
{
|
||||
ctx->preg_log[ctx->preg_log_idx] = pnum;
|
||||
ctx->preg_log_idx++;
|
||||
}
|
||||
|
||||
static inline bool is_preloaded(DisasContext *ctx, int num)
|
||||
{
|
||||
return test_bit(num, ctx->regs_written);
|
||||
}
|
||||
|
||||
extern TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
|
||||
extern TCGv hex_pred[NUM_PREGS];
|
||||
extern TCGv hex_next_PC;
|
||||
extern TCGv hex_this_PC;
|
||||
extern TCGv hex_slot_cancelled;
|
||||
extern TCGv hex_branch_taken;
|
||||
extern TCGv hex_new_value[TOTAL_PER_THREAD_REGS];
|
||||
extern TCGv hex_reg_written[TOTAL_PER_THREAD_REGS];
|
||||
extern TCGv hex_new_pred_value[NUM_PREGS];
|
||||
extern TCGv hex_pred_written;
|
||||
extern TCGv hex_store_addr[STORES_MAX];
|
||||
extern TCGv hex_store_width[STORES_MAX];
|
||||
extern TCGv hex_store_val32[STORES_MAX];
|
||||
extern TCGv_i64 hex_store_val64[STORES_MAX];
|
||||
extern TCGv hex_dczero_addr;
|
||||
extern TCGv hex_llsc_addr;
|
||||
extern TCGv hex_llsc_val;
|
||||
extern TCGv_i64 hex_llsc_val_i64;
|
||||
|
||||
void gen_exception(int excp);
|
||||
void gen_exception_debug(void);
|
||||
|
||||
void process_store(DisasContext *ctx, Packet *pkt, int slot_num);
|
||||
#endif
|
@ -2,6 +2,7 @@ subdir('alpha')
|
||||
subdir('arm')
|
||||
subdir('avr')
|
||||
subdir('cris')
|
||||
subdir('hexagon')
|
||||
subdir('hppa')
|
||||
subdir('i386')
|
||||
subdir('lm32')
|
||||
|
@ -49,6 +49,8 @@ fi
|
||||
: $(cross_cc_alpha="alpha-linux-gnu-gcc")
|
||||
: ${cross_cc_arm="arm-linux-gnueabihf-gcc"}
|
||||
: ${cross_cc_cflags_armeb="-mbig-endian"}
|
||||
: ${cross_cc_hexagon="hexagon-unknown-linux-musl-clang"}
|
||||
: ${cross_cc_cflags_hexagon="-mv67 -O2 -static"}
|
||||
: ${cross_cc_hppa="hppa-linux-gnu-gcc"}
|
||||
: ${cross_cc_i386="i386-pc-linux-gnu-gcc"}
|
||||
: ${cross_cc_cflags_i386="-m32"}
|
||||
@ -94,7 +96,7 @@ for target in $target_list; do
|
||||
xtensa|xtensaeb)
|
||||
arches=xtensa
|
||||
;;
|
||||
alpha|cris|hppa|i386|lm32|microblaze|microblazeel|m68k|openrisc|riscv64|s390x|sh4|sparc64)
|
||||
alpha|cris|hexagon|hppa|i386|lm32|microblaze|microblazeel|m68k|openrisc|riscv64|s390x|sh4|sparc64)
|
||||
arches=$target
|
||||
;;
|
||||
*)
|
||||
|
46
tests/tcg/hexagon/Makefile.target
Normal file
46
tests/tcg/hexagon/Makefile.target
Normal file
@ -0,0 +1,46 @@
|
||||
##
|
||||
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 2 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
# Hexagon doesn't support gdb, so skip the EXTRA_RUNS
|
||||
EXTRA_RUNS =
|
||||
|
||||
# Hexagon has 64K pages, so increase the timeout to keep
|
||||
# test-mmap from timing out
|
||||
ifeq ($(CONFIG_DEBUG_TCG),y)
|
||||
TIMEOUT=800
|
||||
else
|
||||
TIMEOUT=500
|
||||
endif
|
||||
|
||||
|
||||
CFLAGS += -Wno-incompatible-pointer-types -Wno-undefined-internal
|
||||
|
||||
HEX_SRC=$(SRC_PATH)/tests/tcg/hexagon
|
||||
VPATH += $(HEX_SRC)
|
||||
|
||||
first: $(HEX_SRC)/first.S
|
||||
$(CC) -static -mv67 -nostdlib $^ -o $@
|
||||
|
||||
HEX_TESTS = first
|
||||
HEX_TESTS += misc
|
||||
HEX_TESTS += preg_alias
|
||||
HEX_TESTS += dual_stores
|
||||
HEX_TESTS += mem_noshuf
|
||||
HEX_TESTS += atomics
|
||||
HEX_TESTS += fpstuff
|
||||
|
||||
TESTS += $(HEX_TESTS)
|
139
tests/tcg/hexagon/atomics.c
Normal file
139
tests/tcg/hexagon/atomics.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/* Using volatile because we are testing atomics */
|
||||
static inline int atomic_inc32(volatile int *x)
|
||||
{
|
||||
int old, dummy;
|
||||
__asm__ __volatile__(
|
||||
"1: %0 = memw_locked(%2)\n\t"
|
||||
" %1 = add(%0, #1)\n\t"
|
||||
" memw_locked(%2, p0) = %1\n\t"
|
||||
" if (!p0) jump 1b\n\t"
|
||||
: "=&r"(old), "=&r"(dummy)
|
||||
: "r"(x)
|
||||
: "p0", "memory");
|
||||
return old;
|
||||
}
|
||||
|
||||
/* Using volatile because we are testing atomics */
|
||||
static inline long long atomic_inc64(volatile long long *x)
|
||||
{
|
||||
long long old, dummy;
|
||||
__asm__ __volatile__(
|
||||
"1: %0 = memd_locked(%2)\n\t"
|
||||
" %1 = #1\n\t"
|
||||
" %1 = add(%0, %1)\n\t"
|
||||
" memd_locked(%2, p0) = %1\n\t"
|
||||
" if (!p0) jump 1b\n\t"
|
||||
: "=&r"(old), "=&r"(dummy)
|
||||
: "r"(x)
|
||||
: "p0", "memory");
|
||||
return old;
|
||||
}
|
||||
|
||||
/* Using volatile because we are testing atomics */
|
||||
static inline int atomic_dec32(volatile int *x)
|
||||
{
|
||||
int old, dummy;
|
||||
__asm__ __volatile__(
|
||||
"1: %0 = memw_locked(%2)\n\t"
|
||||
" %1 = add(%0, #-1)\n\t"
|
||||
" memw_locked(%2, p0) = %1\n\t"
|
||||
" if (!p0) jump 1b\n\t"
|
||||
: "=&r"(old), "=&r"(dummy)
|
||||
: "r"(x)
|
||||
: "p0", "memory");
|
||||
return old;
|
||||
}
|
||||
|
||||
/* Using volatile because we are testing atomics */
|
||||
static inline long long atomic_dec64(volatile long long *x)
|
||||
{
|
||||
long long old, dummy;
|
||||
__asm__ __volatile__(
|
||||
"1: %0 = memd_locked(%2)\n\t"
|
||||
" %1 = #-1\n\t"
|
||||
" %1 = add(%0, %1)\n\t"
|
||||
" memd_locked(%2, p0) = %1\n\t"
|
||||
" if (!p0) jump 1b\n\t"
|
||||
: "=&r"(old), "=&r"(dummy)
|
||||
: "r"(x)
|
||||
: "p0", "memory");
|
||||
return old;
|
||||
}
|
||||
|
||||
#define LOOP_CNT 1000
|
||||
/* Using volatile because we are testing atomics */
|
||||
volatile int tick32 = 1;
|
||||
/* Using volatile because we are testing atomics */
|
||||
volatile long long tick64 = 1;
|
||||
int err;
|
||||
|
||||
void *thread1_func(void *arg)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < LOOP_CNT; i++) {
|
||||
atomic_inc32(&tick32);
|
||||
atomic_dec64(&tick64);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *thread2_func(void *arg)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < LOOP_CNT; i++) {
|
||||
atomic_dec32(&tick32);
|
||||
atomic_inc64(&tick64);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void test_pthread(void)
|
||||
{
|
||||
pthread_t tid1, tid2;
|
||||
|
||||
pthread_create(&tid1, NULL, thread1_func, "hello1");
|
||||
pthread_create(&tid2, NULL, thread2_func, "hello2");
|
||||
pthread_join(tid1, NULL);
|
||||
pthread_join(tid2, NULL);
|
||||
|
||||
if (tick32 != 1) {
|
||||
printf("ERROR: tick32 %d != 1\n", tick32);
|
||||
err++;
|
||||
}
|
||||
if (tick64 != 1) {
|
||||
printf("ERROR: tick64 %lld != 1\n", tick64);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
test_pthread();
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err;
|
||||
}
|
60
tests/tcg/hexagon/dual_stores.c
Normal file
60
tests/tcg/hexagon/dual_stores.c
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Make sure that two stores in the same packet honor proper
|
||||
* semantics: slot 1 executes first, then slot 0.
|
||||
* This is important when the addresses overlap.
|
||||
*/
|
||||
static inline void dual_stores(int *p, char *q, int x, char y)
|
||||
{
|
||||
asm volatile("{\n\t"
|
||||
" memw(%0) = %2\n\t"
|
||||
" memb(%1) = %3\n\t"
|
||||
"}\n"
|
||||
:: "r"(p), "r"(q), "r"(x), "r"(y)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
typedef union {
|
||||
int word;
|
||||
char byte;
|
||||
} Dual;
|
||||
|
||||
int err;
|
||||
|
||||
static void check(Dual d, int expect)
|
||||
{
|
||||
if (d.word != expect) {
|
||||
printf("ERROR: 0x%08x != 0x%08x\n", d.word, expect);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Dual d;
|
||||
|
||||
d.word = ~0;
|
||||
dual_stores(&d.word, &d.byte, 0x12345678, 0xff);
|
||||
check(d, 0x123456ff);
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err;
|
||||
}
|
56
tests/tcg/hexagon/first.S
Normal file
56
tests/tcg/hexagon/first.S
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define SYS_write 64
|
||||
#define SYS_exit_group 94
|
||||
#define SYS_exit 93
|
||||
|
||||
#define FD_STDOUT 1
|
||||
|
||||
.type str,@object
|
||||
.section .rodata
|
||||
str:
|
||||
.string "Hello!\n"
|
||||
.size str, 8
|
||||
|
||||
.text
|
||||
.global _start
|
||||
_start:
|
||||
r6 = #SYS_write
|
||||
r0 = #FD_STDOUT
|
||||
r1 = ##str
|
||||
r2 = #7
|
||||
trap0(#1)
|
||||
|
||||
r0 = #0
|
||||
r6 = #SYS_exit_group
|
||||
trap0(#1)
|
||||
|
||||
.section ".note.ABI-tag", "a"
|
||||
.align 4
|
||||
.long 1f - 0f /* name length */
|
||||
.long 3f - 2f /* data length */
|
||||
.long 1 /* note type */
|
||||
|
||||
/*
|
||||
* vendor name seems like this should be MUSL but lldb doesn't agree.
|
||||
*/
|
||||
0: .asciz "GNU"
|
||||
1: .align 4
|
||||
2: .long 0 /* linux */
|
||||
.long 3,0,0
|
||||
3: .align 4
|
748
tests/tcg/hexagon/float_convs.ref
Normal file
748
tests/tcg/hexagon/float_convs.ref
Normal file
@ -0,0 +1,748 @@
|
||||
### Rounding to nearest
|
||||
from single: f32(-nan:0xffa00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (INVALID)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-nan:0xffc00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (OK)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-inf:0xff800000)
|
||||
to double: f64(-inf:0x00fff0000000000000) (OK)
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (INEXACT )
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (INEXACT )
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (INEXACT )
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
to double: f64(-0x1.00000000000000000000p-126:0x00b810000000000000) (OK)
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(0x0.00000000000000000000p+0:0000000000)
|
||||
to double: f64(0x0.00000000000000000000p+0:00000000000000000000) (OK)
|
||||
to int32: 0 (OK)
|
||||
to int64: 0 (OK)
|
||||
to uint32: 0 (OK)
|
||||
to uint64: 0 (OK)
|
||||
from single: f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
to double: f64(0x1.00000000000000000000p-126:0x003810000000000000) (OK)
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
to double: f64(0x1.00000000000000000000p-25:0x003e60000000000000) (OK)
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
to double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) (OK)
|
||||
to int32: 1 (OK)
|
||||
to int64: 1 (OK)
|
||||
to uint32: 1 (OK)
|
||||
to uint64: 1 (OK)
|
||||
from single: f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (INEXACT )
|
||||
to int32: 1 (INEXACT )
|
||||
to int64: 1 (INEXACT )
|
||||
to uint32: 1 (INEXACT )
|
||||
to uint64: 1 (INEXACT )
|
||||
from single: f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
to double: f64(0x1.00000000000000000000p+1:0x004000000000000000) (OK)
|
||||
to int32: 2 (OK)
|
||||
to int64: 2 (OK)
|
||||
to uint32: 2 (OK)
|
||||
to uint64: 2 (OK)
|
||||
from single: f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (INEXACT )
|
||||
to int32: 2 (INEXACT )
|
||||
to int64: 2 (INEXACT )
|
||||
to uint32: 2 (INEXACT )
|
||||
to uint64: 2 (INEXACT )
|
||||
from single: f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (INEXACT )
|
||||
to int32: 3 (INEXACT )
|
||||
to int64: 3 (INEXACT )
|
||||
to uint32: 3 (INEXACT )
|
||||
to uint64: 3 (INEXACT )
|
||||
from single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (INEXACT )
|
||||
to int32: 65503 (OK)
|
||||
to int64: 65503 (OK)
|
||||
to uint32: 65503 (OK)
|
||||
to uint64: 65503 (OK)
|
||||
from single: f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (INEXACT )
|
||||
to int32: 65504 (OK)
|
||||
to int64: 65504 (OK)
|
||||
to uint32: 65504 (OK)
|
||||
to uint64: 65504 (OK)
|
||||
from single: f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (INEXACT )
|
||||
to int32: 65505 (OK)
|
||||
to int64: 65505 (OK)
|
||||
to uint32: 65505 (OK)
|
||||
to uint64: 65505 (OK)
|
||||
from single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (INEXACT )
|
||||
to int32: 131007 (OK)
|
||||
to int64: 131007 (OK)
|
||||
to uint32: 131007 (OK)
|
||||
to uint64: 131007 (OK)
|
||||
from single: f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (INEXACT )
|
||||
to int32: 131008 (OK)
|
||||
to int64: 131008 (OK)
|
||||
to uint32: 131008 (OK)
|
||||
to uint64: 131008 (OK)
|
||||
from single: f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (INEXACT )
|
||||
to int32: 131009 (OK)
|
||||
to int64: 131009 (OK)
|
||||
to uint32: 131009 (OK)
|
||||
to uint64: 131009 (OK)
|
||||
from single: f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (INEXACT )
|
||||
to int32: 2147483647 (INVALID)
|
||||
to int64: 9223372036854775807 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (INEXACT )
|
||||
to int32: 2147483647 (INVALID)
|
||||
to int64: 9223372036854775807 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(inf:0x7f800000)
|
||||
to double: f64(inf:0x007ff0000000000000) (OK)
|
||||
to int32: 2147483647 (INVALID)
|
||||
to int64: 9223372036854775807 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-nan:0x7fc00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (OK)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-nan:0x7fa00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (INVALID)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
### Rounding upwards
|
||||
from single: f32(-nan:0xffa00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (INVALID)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-nan:0xffc00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (OK)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-inf:0xff800000)
|
||||
to double: f64(-inf:0x00fff0000000000000) (OK)
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (INEXACT )
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (INEXACT )
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (INEXACT )
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
to double: f64(-0x1.00000000000000000000p-126:0x00b810000000000000) (OK)
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(0x0.00000000000000000000p+0:0000000000)
|
||||
to double: f64(0x0.00000000000000000000p+0:00000000000000000000) (OK)
|
||||
to int32: 0 (OK)
|
||||
to int64: 0 (OK)
|
||||
to uint32: 0 (OK)
|
||||
to uint64: 0 (OK)
|
||||
from single: f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
to double: f64(0x1.00000000000000000000p-126:0x003810000000000000) (OK)
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
to double: f64(0x1.00000000000000000000p-25:0x003e60000000000000) (OK)
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
to double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) (OK)
|
||||
to int32: 1 (OK)
|
||||
to int64: 1 (OK)
|
||||
to uint32: 1 (OK)
|
||||
to uint64: 1 (OK)
|
||||
from single: f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (INEXACT )
|
||||
to int32: 1 (INEXACT )
|
||||
to int64: 1 (INEXACT )
|
||||
to uint32: 1 (INEXACT )
|
||||
to uint64: 1 (INEXACT )
|
||||
from single: f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
to double: f64(0x1.00000000000000000000p+1:0x004000000000000000) (OK)
|
||||
to int32: 2 (OK)
|
||||
to int64: 2 (OK)
|
||||
to uint32: 2 (OK)
|
||||
to uint64: 2 (OK)
|
||||
from single: f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (INEXACT )
|
||||
to int32: 2 (INEXACT )
|
||||
to int64: 2 (INEXACT )
|
||||
to uint32: 2 (INEXACT )
|
||||
to uint64: 2 (INEXACT )
|
||||
from single: f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (INEXACT )
|
||||
to int32: 3 (INEXACT )
|
||||
to int64: 3 (INEXACT )
|
||||
to uint32: 3 (INEXACT )
|
||||
to uint64: 3 (INEXACT )
|
||||
from single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (INEXACT )
|
||||
to int32: 65503 (OK)
|
||||
to int64: 65503 (OK)
|
||||
to uint32: 65503 (OK)
|
||||
to uint64: 65503 (OK)
|
||||
from single: f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (INEXACT )
|
||||
to int32: 65504 (OK)
|
||||
to int64: 65504 (OK)
|
||||
to uint32: 65504 (OK)
|
||||
to uint64: 65504 (OK)
|
||||
from single: f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (INEXACT )
|
||||
to int32: 65505 (OK)
|
||||
to int64: 65505 (OK)
|
||||
to uint32: 65505 (OK)
|
||||
to uint64: 65505 (OK)
|
||||
from single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (INEXACT )
|
||||
to int32: 131007 (OK)
|
||||
to int64: 131007 (OK)
|
||||
to uint32: 131007 (OK)
|
||||
to uint64: 131007 (OK)
|
||||
from single: f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (INEXACT )
|
||||
to int32: 131008 (OK)
|
||||
to int64: 131008 (OK)
|
||||
to uint32: 131008 (OK)
|
||||
to uint64: 131008 (OK)
|
||||
from single: f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (INEXACT )
|
||||
to int32: 131009 (OK)
|
||||
to int64: 131009 (OK)
|
||||
to uint32: 131009 (OK)
|
||||
to uint64: 131009 (OK)
|
||||
from single: f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (INEXACT )
|
||||
to int32: 2147483647 (INVALID)
|
||||
to int64: 9223372036854775807 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (INEXACT )
|
||||
to int32: 2147483647 (INVALID)
|
||||
to int64: 9223372036854775807 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(inf:0x7f800000)
|
||||
to double: f64(inf:0x007ff0000000000000) (OK)
|
||||
to int32: 2147483647 (INVALID)
|
||||
to int64: 9223372036854775807 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-nan:0x7fc00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (OK)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-nan:0x7fa00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (INVALID)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
### Rounding downwards
|
||||
from single: f32(-nan:0xffa00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (INVALID)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-nan:0xffc00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (OK)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-inf:0xff800000)
|
||||
to double: f64(-inf:0x00fff0000000000000) (OK)
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (INEXACT )
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (INEXACT )
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (INEXACT )
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
to double: f64(-0x1.00000000000000000000p-126:0x00b810000000000000) (OK)
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(0x0.00000000000000000000p+0:0000000000)
|
||||
to double: f64(0x0.00000000000000000000p+0:00000000000000000000) (OK)
|
||||
to int32: 0 (OK)
|
||||
to int64: 0 (OK)
|
||||
to uint32: 0 (OK)
|
||||
to uint64: 0 (OK)
|
||||
from single: f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
to double: f64(0x1.00000000000000000000p-126:0x003810000000000000) (OK)
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
to double: f64(0x1.00000000000000000000p-25:0x003e60000000000000) (OK)
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
to double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) (OK)
|
||||
to int32: 1 (OK)
|
||||
to int64: 1 (OK)
|
||||
to uint32: 1 (OK)
|
||||
to uint64: 1 (OK)
|
||||
from single: f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (INEXACT )
|
||||
to int32: 1 (INEXACT )
|
||||
to int64: 1 (INEXACT )
|
||||
to uint32: 1 (INEXACT )
|
||||
to uint64: 1 (INEXACT )
|
||||
from single: f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
to double: f64(0x1.00000000000000000000p+1:0x004000000000000000) (OK)
|
||||
to int32: 2 (OK)
|
||||
to int64: 2 (OK)
|
||||
to uint32: 2 (OK)
|
||||
to uint64: 2 (OK)
|
||||
from single: f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (INEXACT )
|
||||
to int32: 2 (INEXACT )
|
||||
to int64: 2 (INEXACT )
|
||||
to uint32: 2 (INEXACT )
|
||||
to uint64: 2 (INEXACT )
|
||||
from single: f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (INEXACT )
|
||||
to int32: 3 (INEXACT )
|
||||
to int64: 3 (INEXACT )
|
||||
to uint32: 3 (INEXACT )
|
||||
to uint64: 3 (INEXACT )
|
||||
from single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (INEXACT )
|
||||
to int32: 65503 (OK)
|
||||
to int64: 65503 (OK)
|
||||
to uint32: 65503 (OK)
|
||||
to uint64: 65503 (OK)
|
||||
from single: f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (INEXACT )
|
||||
to int32: 65504 (OK)
|
||||
to int64: 65504 (OK)
|
||||
to uint32: 65504 (OK)
|
||||
to uint64: 65504 (OK)
|
||||
from single: f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (INEXACT )
|
||||
to int32: 65505 (OK)
|
||||
to int64: 65505 (OK)
|
||||
to uint32: 65505 (OK)
|
||||
to uint64: 65505 (OK)
|
||||
from single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (INEXACT )
|
||||
to int32: 131007 (OK)
|
||||
to int64: 131007 (OK)
|
||||
to uint32: 131007 (OK)
|
||||
to uint64: 131007 (OK)
|
||||
from single: f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (INEXACT )
|
||||
to int32: 131008 (OK)
|
||||
to int64: 131008 (OK)
|
||||
to uint32: 131008 (OK)
|
||||
to uint64: 131008 (OK)
|
||||
from single: f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (INEXACT )
|
||||
to int32: 131009 (OK)
|
||||
to int64: 131009 (OK)
|
||||
to uint32: 131009 (OK)
|
||||
to uint64: 131009 (OK)
|
||||
from single: f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (INEXACT )
|
||||
to int32: 2147483647 (INVALID)
|
||||
to int64: 9223372036854775807 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (INEXACT )
|
||||
to int32: 2147483647 (INVALID)
|
||||
to int64: 9223372036854775807 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(inf:0x7f800000)
|
||||
to double: f64(inf:0x007ff0000000000000) (OK)
|
||||
to int32: 2147483647 (INVALID)
|
||||
to int64: 9223372036854775807 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-nan:0x7fc00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (OK)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-nan:0x7fa00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (INVALID)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
### Rounding to zero
|
||||
from single: f32(-nan:0xffa00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (INVALID)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-nan:0xffc00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (OK)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-inf:0xff800000)
|
||||
to double: f64(-inf:0x00fff0000000000000) (OK)
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
to double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) (INEXACT )
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
to double: f64(-0x1.1874b200000000000000p+103:0x00c661874b20000000) (INEXACT )
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
to double: f64(-0x1.c0bab600000000000000p+99:0x00c62c0bab60000000) (INEXACT )
|
||||
to int32: -2147483648 (INVALID)
|
||||
to int64: -9223372036854775808 (INVALID)
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
to double: f64(-0x1.31f75000000000000000p-40:0x00bd731f7500000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
to double: f64(-0x1.50544400000000000000p-66:0x00bbd5054440000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
to double: f64(-0x1.00000000000000000000p-126:0x00b810000000000000) (OK)
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INVALID)
|
||||
to uint64: 0 (INVALID)
|
||||
from single: f32(0x0.00000000000000000000p+0:0000000000)
|
||||
to double: f64(0x0.00000000000000000000p+0:00000000000000000000) (OK)
|
||||
to int32: 0 (OK)
|
||||
to int64: 0 (OK)
|
||||
to uint32: 0 (OK)
|
||||
to uint64: 0 (OK)
|
||||
from single: f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
to double: f64(0x1.00000000000000000000p-126:0x003810000000000000) (OK)
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
to double: f64(0x1.00000000000000000000p-25:0x003e60000000000000) (OK)
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
to double: f64(0x1.ffffe600000000000000p-25:0x003e6ffffe60000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
to double: f64(0x1.ff801a00000000000000p-15:0x003f0ff801a0000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
to double: f64(0x1.00000c00000000000000p-14:0x003f100000c0000000) (INEXACT )
|
||||
to int32: 0 (INEXACT )
|
||||
to int64: 0 (INEXACT )
|
||||
to uint32: 0 (INEXACT )
|
||||
to uint64: 0 (INEXACT )
|
||||
from single: f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
to double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) (OK)
|
||||
to int32: 1 (OK)
|
||||
to int64: 1 (OK)
|
||||
to uint32: 1 (OK)
|
||||
to uint64: 1 (OK)
|
||||
from single: f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
to double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) (INEXACT )
|
||||
to int32: 1 (INEXACT )
|
||||
to int64: 1 (INEXACT )
|
||||
to uint32: 1 (INEXACT )
|
||||
to uint64: 1 (INEXACT )
|
||||
from single: f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
to double: f64(0x1.00000000000000000000p+1:0x004000000000000000) (OK)
|
||||
to int32: 2 (OK)
|
||||
to int64: 2 (OK)
|
||||
to uint32: 2 (OK)
|
||||
to uint64: 2 (OK)
|
||||
from single: f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
to double: f64(0x1.5bf0a800000000000000p+1:0x004005bf0a80000000) (INEXACT )
|
||||
to int32: 2 (INEXACT )
|
||||
to int64: 2 (INEXACT )
|
||||
to uint32: 2 (INEXACT )
|
||||
to uint64: 2 (INEXACT )
|
||||
from single: f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
to double: f64(0x1.921fb600000000000000p+1:0x00400921fb60000000) (INEXACT )
|
||||
to int32: 3 (INEXACT )
|
||||
to int64: 3 (INEXACT )
|
||||
to uint32: 3 (INEXACT )
|
||||
to uint64: 3 (INEXACT )
|
||||
from single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
to double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) (INEXACT )
|
||||
to int32: 65503 (OK)
|
||||
to int64: 65503 (OK)
|
||||
to uint32: 65503 (OK)
|
||||
to uint64: 65503 (OK)
|
||||
from single: f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
to double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) (INEXACT )
|
||||
to int32: 65504 (OK)
|
||||
to int64: 65504 (OK)
|
||||
to uint32: 65504 (OK)
|
||||
to uint64: 65504 (OK)
|
||||
from single: f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
to double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) (INEXACT )
|
||||
to int32: 65505 (OK)
|
||||
to int64: 65505 (OK)
|
||||
to uint32: 65505 (OK)
|
||||
to uint64: 65505 (OK)
|
||||
from single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
to double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) (INEXACT )
|
||||
to int32: 131007 (OK)
|
||||
to int64: 131007 (OK)
|
||||
to uint32: 131007 (OK)
|
||||
to uint64: 131007 (OK)
|
||||
from single: f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
to double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) (INEXACT )
|
||||
to int32: 131008 (OK)
|
||||
to int64: 131008 (OK)
|
||||
to uint32: 131008 (OK)
|
||||
to uint64: 131008 (OK)
|
||||
from single: f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
to double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) (INEXACT )
|
||||
to int32: 131009 (OK)
|
||||
to int64: 131009 (OK)
|
||||
to uint32: 131009 (OK)
|
||||
to uint64: 131009 (OK)
|
||||
from single: f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
to double: f64(0x1.c0bab600000000000000p+99:0x00462c0bab60000000) (INEXACT )
|
||||
to int32: 2147483647 (INVALID)
|
||||
to int64: 9223372036854775807 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
to double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) (INEXACT )
|
||||
to int32: 2147483647 (INVALID)
|
||||
to int64: 9223372036854775807 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(inf:0x7f800000)
|
||||
to double: f64(inf:0x007ff0000000000000) (OK)
|
||||
to int32: 2147483647 (INVALID)
|
||||
to int64: 9223372036854775807 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-nan:0x7fc00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (OK)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
||||
from single: f32(-nan:0x7fa00000)
|
||||
to double: f64(-nan:0x00ffffffffffffffff) (INVALID)
|
||||
to int32: -1 (INVALID)
|
||||
to int64: -1 (INVALID)
|
||||
to uint32: -1 (INVALID)
|
||||
to uint64: -1 (INVALID)
|
768
tests/tcg/hexagon/float_madds.ref
Normal file
768
tests/tcg/hexagon/float_madds.ref
Normal file
@ -0,0 +1,768 @@
|
||||
### Rounding to nearest
|
||||
op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(-inf:0xff800000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (0/0)
|
||||
op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-nan:0xffa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (0/1)
|
||||
op : f32(-inf:0xff800000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (0/2)
|
||||
op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
res: f32(-nan:0xffffffff) flags=OK (1/0)
|
||||
op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-nan:0xffc00000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (1/1)
|
||||
op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-nan:0xffc00000) + f32(-inf:0xff800000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (1/2)
|
||||
op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
res: f32(inf:0x7f800000) flags=OK (2/0)
|
||||
op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-inf:0xff800000)
|
||||
res: f32(-inf:0xff800000) flags=OK (2/1)
|
||||
op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
res: f32(inf:0x7f800000) flags=OK (2/2)
|
||||
op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (3/0)
|
||||
op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (3/1)
|
||||
op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (3/2)
|
||||
op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (4/0)
|
||||
op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
res: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) flags=INEXACT (4/1)
|
||||
op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
res: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) flags=INEXACT (4/2)
|
||||
op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
res: f32(0x1.0c27fa00000000000000p+60:0x5d8613fd) flags=INEXACT (5/0)
|
||||
op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
res: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) flags=INEXACT (5/1)
|
||||
op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
res: f32(0x1.26c46200000000000000p+34:0x50936231) flags=INEXACT (5/2)
|
||||
op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
res: f32(0x1.91f94000000000000000p-106:0x0ac8fca0) flags=INEXACT (6/0)
|
||||
op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
res: f32(-0x1.31f75000000000000000p-40:0xab98fba8) flags=INEXACT (6/1)
|
||||
op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (6/2)
|
||||
op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (7/0)
|
||||
op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (7/1)
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (7/2)
|
||||
op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (8/0)
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (8/1)
|
||||
op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(-0x0.00000000000000000000p+0:0x80000000) flags=UNDERFLOW INEXACT (8/2)
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
res: f32(0x1.00000000000000000000p-25:0x33000000) flags=OK (9/0)
|
||||
op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (9/1)
|
||||
op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (9/2)
|
||||
op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
res: f32(0x1.ffffe600000000000000p-25:0x337ffff3) flags=INEXACT (10/0)
|
||||
op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
res: f32(0x1.ffffe600000000000000p-50:0x26fffff3) flags=INEXACT (10/1)
|
||||
op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
res: f32(0x1.00000000000000000000p-25:0x33000000) flags=INEXACT (10/2)
|
||||
op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
res: f32(0x1.ff801a00000000000000p-15:0x387fc00d) flags=INEXACT (11/0)
|
||||
op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
res: f32(0x1.0007fe00000000000000p-25:0x330003ff) flags=INEXACT (11/1)
|
||||
op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
res: f32(0x1.0001f200000000000000p-24:0x338000f9) flags=INEXACT (11/2)
|
||||
op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
res: f32(0x1.00000c00000000000000p-14:0x38800006) flags=INEXACT (12/0)
|
||||
op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
res: f32(0x1.0ffbf400000000000000p-24:0x3387fdfa) flags=INEXACT (12/1)
|
||||
op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
res: f32(0x1.ff801c00000000000000p-15:0x387fc00e) flags=INEXACT (12/2)
|
||||
op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
res: f32(0x1.00000000000000000000p+0:0x3f800000) flags=INEXACT (13/0)
|
||||
op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
res: f32(0x1.ffc01800000000000000p-14:0x38ffe00c) flags=INEXACT (13/1)
|
||||
op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
res: f32(0x1.ffc01800000000000000p-14:0x38ffe00c) flags=INEXACT (13/2)
|
||||
op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/0)
|
||||
op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/1)
|
||||
op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
res: f32(0x1.00040200000000000000p+0:0x3f800201) flags=INEXACT (14/2)
|
||||
op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/0)
|
||||
op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
res: f32(0x1.80400000000000000000p+1:0x40402000) flags=INEXACT (15/1)
|
||||
op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/2)
|
||||
op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=INEXACT (16/0)
|
||||
op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=INEXACT (16/1)
|
||||
op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
res: f32(0x1.2e23d200000000000000p+2:0x409711e9) flags=INEXACT (16/2)
|
||||
op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
res: f32(0x1.12804200000000000000p+3:0x41094021) flags=INEXACT (17/0)
|
||||
op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
res: f32(0x1.51458000000000000000p+3:0x4128a2c0) flags=INEXACT (17/1)
|
||||
op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
res: f32(0x1.200c0400000000000000p+3:0x41100602) flags=INEXACT (17/2)
|
||||
op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
res: f32(0x1.ffcf1400000000000000p+15:0x477fe78a) flags=INEXACT (18/0)
|
||||
op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
res: f32(0x1.91ed3c00000000000000p+17:0x4848f69e) flags=INEXACT (18/1)
|
||||
op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
res: f32(0x1.5bc56000000000000000p+17:0x482de2b0) flags=INEXACT (18/2)
|
||||
op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
res: f32(0x1.08edf000000000000000p+18:0x488476f8) flags=INEXACT (19/0)
|
||||
op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
res: f32(0x1.ff7e0800000000000000p+31:0x4f7fbf04) flags=INEXACT (19/1)
|
||||
op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
res: f32(0x1.08ee7a00000000000000p+18:0x4884773d) flags=INEXACT (19/2)
|
||||
op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
res: f32(0x1.ff800800000000000000p+31:0x4f7fc004) flags=INEXACT (20/0)
|
||||
op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
res: f32(0x1.ff840800000000000000p+31:0x4f7fc204) flags=INEXACT (20/1)
|
||||
op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
res: f32(0x1.ff820800000000000000p+31:0x4f7fc104) flags=INEXACT (20/2)
|
||||
op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
res: f32(0x1.ff860800000000000000p+31:0x4f7fc304) flags=INEXACT (21/0)
|
||||
op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
res: f32(0x1.ff820800000000000000p+32:0x4fffc104) flags=INEXACT (21/1)
|
||||
op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
res: f32(0x1.ff800800000000000000p+32:0x4fffc004) flags=INEXACT (21/2)
|
||||
op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
res: f32(0x1.ff830800000000000000p+32:0x4fffc184) flags=INEXACT (22/0)
|
||||
op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
res: f32(0x1.ff7f8800000000000000p+33:0x507fbfc4) flags=INEXACT (22/1)
|
||||
op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
res: f32(0x1.ff840800000000000000p+32:0x4fffc204) flags=INEXACT (22/2)
|
||||
op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
res: f32(0x1.ff800800000000000000p+33:0x507fc004) flags=INEXACT (23/0)
|
||||
op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
res: f32(0x1.ff820800000000000000p+33:0x507fc104) flags=INEXACT (23/1)
|
||||
op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
res: f32(0x1.ff810800000000000000p+33:0x507fc084) flags=INEXACT (23/2)
|
||||
op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
res: f32(0x1.c0bab600000000000000p+99:0x71605d5b) flags=INEXACT (24/0)
|
||||
op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
res: f32(0x1.c0838000000000000000p+116:0x79e041c0) flags=INEXACT (24/1)
|
||||
op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
res: f32(0x1.c0829e00000000000000p+116:0x79e0414f) flags=INEXACT (24/2)
|
||||
op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (25/0)
|
||||
op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (25/1)
|
||||
op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (25/2)
|
||||
op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000)
|
||||
res: f32(inf:0x7f800000) flags=OK (26/0)
|
||||
op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
res: f32(inf:0x7f800000) flags=OK (26/1)
|
||||
op : f32(inf:0x7f800000) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
res: f32(inf:0x7f800000) flags=OK (26/2)
|
||||
op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(-nan:0x7fc00000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (27/0)
|
||||
op : f32(inf:0x7f800000) * f32(-nan:0x7fc00000) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
res: f32(-nan:0xffffffff) flags=OK (27/1)
|
||||
op : f32(-nan:0x7fc00000) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (27/2)
|
||||
op : f32(inf:0x7f800000) * f32(-nan:0x7fc00000) + f32(-nan:0x7fa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (28/0)
|
||||
op : f32(-nan:0x7fc00000) * f32(-nan:0x7fa00000) + f32(inf:0x7f800000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (28/1)
|
||||
op : f32(-nan:0x7fa00000) * f32(inf:0x7f800000) + f32(-nan:0x7fc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (28/2)
|
||||
op : f32(-nan:0x7fc00000) * f32(-nan:0x7fa00000) + f32(-nan:0xffa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (29/0)
|
||||
op : f32(-nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(-nan:0x7fc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (29/1)
|
||||
op : f32(-nan:0xffa00000) * f32(-nan:0x7fc00000) + f32(-nan:0x7fa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (29/2)
|
||||
op : f32(-nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (30/0)
|
||||
op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(-nan:0x7fa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (30/1)
|
||||
op : f32(-nan:0xffc00000) * f32(-nan:0x7fa00000) + f32(-nan:0xffa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (30/2)
|
||||
# LP184149
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-1:0x3f000000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(0x0.00000000000000000000p+0:0000000000) flags=OK (31/0)
|
||||
op : f32(0x1.00000000000000000000p-149:0x00000001) * f32(0x1.00000000000000000000p-149:0x00000001) + f32(0x1.00000000000000000000p-149:0x00000001)
|
||||
res: f32(0x1.00000000000000000000p-149:0x00000001) flags=UNDERFLOW INEXACT (32/0)
|
||||
### Rounding upwards
|
||||
op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(-inf:0xff800000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (0/0)
|
||||
op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-nan:0xffa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (0/1)
|
||||
op : f32(-inf:0xff800000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (0/2)
|
||||
op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
res: f32(-nan:0xffffffff) flags=OK (1/0)
|
||||
op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-nan:0xffc00000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (1/1)
|
||||
op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-nan:0xffc00000) + f32(-inf:0xff800000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (1/2)
|
||||
op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
res: f32(inf:0x7f800000) flags=OK (2/0)
|
||||
op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-inf:0xff800000)
|
||||
res: f32(-inf:0xff800000) flags=OK (2/1)
|
||||
op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
res: f32(inf:0x7f800000) flags=OK (2/2)
|
||||
op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (3/0)
|
||||
op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (3/1)
|
||||
op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (3/2)
|
||||
op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (4/0)
|
||||
op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
res: f32(-0x1.1874b000000000000000p+103:0xf30c3a58) flags=INEXACT (4/1)
|
||||
op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
res: f32(-0x1.c0bab400000000000000p+99:0xf1605d5a) flags=INEXACT (4/2)
|
||||
op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
res: f32(0x1.0c27fa00000000000000p+60:0x5d8613fd) flags=INEXACT (5/0)
|
||||
op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
res: f32(-0x1.c0bab400000000000000p+99:0xf1605d5a) flags=INEXACT (5/1)
|
||||
op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
res: f32(0x1.26c46200000000000000p+34:0x50936231) flags=INEXACT (5/2)
|
||||
op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
res: f32(0x1.91f94000000000000000p-106:0x0ac8fca0) flags=INEXACT (6/0)
|
||||
op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
res: f32(-0x1.31f74e00000000000000p-40:0xab98fba7) flags=INEXACT (6/1)
|
||||
op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
res: f32(-0x1.50544200000000000000p-66:0x9ea82a21) flags=INEXACT (6/2)
|
||||
op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(0x1.00000000000000000000p-149:0x00000001) flags=UNDERFLOW INEXACT (7/0)
|
||||
op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (7/1)
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (7/2)
|
||||
op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (8/0)
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (8/1)
|
||||
op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(-0x0.00000000000000000000p+0:0x80000000) flags=UNDERFLOW INEXACT (8/2)
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
res: f32(0x1.00000000000000000000p-25:0x33000000) flags=OK (9/0)
|
||||
op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(0x1.00000000000000000000p-149:0x00000001) flags=UNDERFLOW INEXACT (9/1)
|
||||
op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (9/2)
|
||||
op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
res: f32(0x1.ffffe800000000000000p-25:0x337ffff4) flags=INEXACT (10/0)
|
||||
op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
res: f32(0x1.ffffe800000000000000p-50:0x26fffff4) flags=INEXACT (10/1)
|
||||
op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
res: f32(0x1.00000200000000000000p-25:0x33000001) flags=INEXACT (10/2)
|
||||
op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
res: f32(0x1.ff801c00000000000000p-15:0x387fc00e) flags=INEXACT (11/0)
|
||||
op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
res: f32(0x1.00080000000000000000p-25:0x33000400) flags=INEXACT (11/1)
|
||||
op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
res: f32(0x1.0001f400000000000000p-24:0x338000fa) flags=INEXACT (11/2)
|
||||
op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
res: f32(0x1.00000e00000000000000p-14:0x38800007) flags=INEXACT (12/0)
|
||||
op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
res: f32(0x1.0ffbf600000000000000p-24:0x3387fdfb) flags=INEXACT (12/1)
|
||||
op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
res: f32(0x1.ff801c00000000000000p-15:0x387fc00e) flags=INEXACT (12/2)
|
||||
op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
res: f32(0x1.00000200000000000000p+0:0x3f800001) flags=INEXACT (13/0)
|
||||
op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
res: f32(0x1.ffc01a00000000000000p-14:0x38ffe00d) flags=INEXACT (13/1)
|
||||
op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
res: f32(0x1.ffc01a00000000000000p-14:0x38ffe00d) flags=INEXACT (13/2)
|
||||
op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
res: f32(0x1.00440200000000000000p+0:0x3f802201) flags=INEXACT (14/0)
|
||||
op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
res: f32(0x1.00440200000000000000p+0:0x3f802201) flags=INEXACT (14/1)
|
||||
op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
res: f32(0x1.00040200000000000000p+0:0x3f800201) flags=INEXACT (14/2)
|
||||
op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/0)
|
||||
op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
res: f32(0x1.80400000000000000000p+1:0x40402000) flags=INEXACT (15/1)
|
||||
op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/2)
|
||||
op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=INEXACT (16/0)
|
||||
op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=INEXACT (16/1)
|
||||
op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
res: f32(0x1.2e23d400000000000000p+2:0x409711ea) flags=INEXACT (16/2)
|
||||
op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
res: f32(0x1.12804200000000000000p+3:0x41094021) flags=INEXACT (17/0)
|
||||
op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
res: f32(0x1.51458200000000000000p+3:0x4128a2c1) flags=INEXACT (17/1)
|
||||
op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
res: f32(0x1.200c0600000000000000p+3:0x41100603) flags=INEXACT (17/2)
|
||||
op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
res: f32(0x1.ffcf1600000000000000p+15:0x477fe78b) flags=INEXACT (18/0)
|
||||
op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
res: f32(0x1.91ed3c00000000000000p+17:0x4848f69e) flags=INEXACT (18/1)
|
||||
op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
res: f32(0x1.5bc56200000000000000p+17:0x482de2b1) flags=INEXACT (18/2)
|
||||
op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
res: f32(0x1.08edf000000000000000p+18:0x488476f8) flags=INEXACT (19/0)
|
||||
op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
res: f32(0x1.ff7e0a00000000000000p+31:0x4f7fbf05) flags=INEXACT (19/1)
|
||||
op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
res: f32(0x1.08ee7a00000000000000p+18:0x4884773d) flags=INEXACT (19/2)
|
||||
op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
res: f32(0x1.ff800a00000000000000p+31:0x4f7fc005) flags=INEXACT (20/0)
|
||||
op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
res: f32(0x1.ff840800000000000000p+31:0x4f7fc204) flags=INEXACT (20/1)
|
||||
op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
res: f32(0x1.ff820800000000000000p+31:0x4f7fc104) flags=INEXACT (20/2)
|
||||
op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
res: f32(0x1.ff860800000000000000p+31:0x4f7fc304) flags=INEXACT (21/0)
|
||||
op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
res: f32(0x1.ff820800000000000000p+32:0x4fffc104) flags=INEXACT (21/1)
|
||||
op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
res: f32(0x1.ff800a00000000000000p+32:0x4fffc005) flags=INEXACT (21/2)
|
||||
op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
res: f32(0x1.ff830800000000000000p+32:0x4fffc184) flags=INEXACT (22/0)
|
||||
op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
res: f32(0x1.ff7f8a00000000000000p+33:0x507fbfc5) flags=INEXACT (22/1)
|
||||
op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
res: f32(0x1.ff840800000000000000p+32:0x4fffc204) flags=INEXACT (22/2)
|
||||
op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
res: f32(0x1.ff800a00000000000000p+33:0x507fc005) flags=INEXACT (23/0)
|
||||
op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
res: f32(0x1.ff820800000000000000p+33:0x507fc104) flags=INEXACT (23/1)
|
||||
op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
res: f32(0x1.ff810800000000000000p+33:0x507fc084) flags=INEXACT (23/2)
|
||||
op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
res: f32(0x1.c0bab800000000000000p+99:0x71605d5c) flags=INEXACT (24/0)
|
||||
op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
res: f32(0x1.c0838000000000000000p+116:0x79e041c0) flags=INEXACT (24/1)
|
||||
op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
res: f32(0x1.c082a000000000000000p+116:0x79e04150) flags=INEXACT (24/2)
|
||||
op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (25/0)
|
||||
op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (25/1)
|
||||
op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
res: f32(inf:0x7f800000) flags=OVERFLOW INEXACT (25/2)
|
||||
op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000)
|
||||
res: f32(inf:0x7f800000) flags=OK (26/0)
|
||||
op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
res: f32(inf:0x7f800000) flags=OK (26/1)
|
||||
op : f32(inf:0x7f800000) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
res: f32(inf:0x7f800000) flags=OK (26/2)
|
||||
op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(-nan:0x7fc00000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (27/0)
|
||||
op : f32(inf:0x7f800000) * f32(-nan:0x7fc00000) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
res: f32(-nan:0xffffffff) flags=OK (27/1)
|
||||
op : f32(-nan:0x7fc00000) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (27/2)
|
||||
op : f32(inf:0x7f800000) * f32(-nan:0x7fc00000) + f32(-nan:0x7fa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (28/0)
|
||||
op : f32(-nan:0x7fc00000) * f32(-nan:0x7fa00000) + f32(inf:0x7f800000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (28/1)
|
||||
op : f32(-nan:0x7fa00000) * f32(inf:0x7f800000) + f32(-nan:0x7fc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (28/2)
|
||||
op : f32(-nan:0x7fc00000) * f32(-nan:0x7fa00000) + f32(-nan:0xffa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (29/0)
|
||||
op : f32(-nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(-nan:0x7fc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (29/1)
|
||||
op : f32(-nan:0xffa00000) * f32(-nan:0x7fc00000) + f32(-nan:0x7fa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (29/2)
|
||||
op : f32(-nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (30/0)
|
||||
op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(-nan:0x7fa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (30/1)
|
||||
op : f32(-nan:0xffc00000) * f32(-nan:0x7fa00000) + f32(-nan:0xffa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (30/2)
|
||||
# LP184149
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-1:0x3f000000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(0x0.00000000000000000000p+0:0000000000) flags=OK (31/0)
|
||||
op : f32(0x1.00000000000000000000p-149:0x00000001) * f32(0x1.00000000000000000000p-149:0x00000001) + f32(0x1.00000000000000000000p-149:0x00000001)
|
||||
res: f32(0x1.00000000000000000000p-148:0x00000002) flags=UNDERFLOW INEXACT (32/0)
|
||||
### Rounding downwards
|
||||
op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(-inf:0xff800000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (0/0)
|
||||
op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-nan:0xffa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (0/1)
|
||||
op : f32(-inf:0xff800000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (0/2)
|
||||
op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
res: f32(-nan:0xffffffff) flags=OK (1/0)
|
||||
op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-nan:0xffc00000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (1/1)
|
||||
op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-nan:0xffc00000) + f32(-inf:0xff800000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (1/2)
|
||||
op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
res: f32(inf:0x7f800000) flags=OK (2/0)
|
||||
op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-inf:0xff800000)
|
||||
res: f32(-inf:0xff800000) flags=OK (2/1)
|
||||
op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
res: f32(inf:0x7f800000) flags=OK (2/2)
|
||||
op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (3/0)
|
||||
op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (3/1)
|
||||
op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (3/2)
|
||||
op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (4/0)
|
||||
op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
res: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) flags=INEXACT (4/1)
|
||||
op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
res: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) flags=INEXACT (4/2)
|
||||
op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
res: f32(0x1.0c27f800000000000000p+60:0x5d8613fc) flags=INEXACT (5/0)
|
||||
op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
res: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) flags=INEXACT (5/1)
|
||||
op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
res: f32(0x1.26c46000000000000000p+34:0x50936230) flags=INEXACT (5/2)
|
||||
op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
res: f32(0x1.91f93e00000000000000p-106:0x0ac8fc9f) flags=INEXACT (6/0)
|
||||
op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
res: f32(-0x1.31f75000000000000000p-40:0xab98fba8) flags=INEXACT (6/1)
|
||||
op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (6/2)
|
||||
op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (7/0)
|
||||
op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (7/1)
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (7/2)
|
||||
op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (8/0)
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (8/1)
|
||||
op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(-0x1.00000000000000000000p-149:0x80000001) flags=UNDERFLOW INEXACT (8/2)
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
res: f32(0x1.00000000000000000000p-25:0x33000000) flags=OK (9/0)
|
||||
op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (9/1)
|
||||
op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (9/2)
|
||||
op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
res: f32(0x1.ffffe600000000000000p-25:0x337ffff3) flags=INEXACT (10/0)
|
||||
op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
res: f32(0x1.ffffe600000000000000p-50:0x26fffff3) flags=INEXACT (10/1)
|
||||
op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
res: f32(0x1.00000000000000000000p-25:0x33000000) flags=INEXACT (10/2)
|
||||
op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
res: f32(0x1.ff801a00000000000000p-15:0x387fc00d) flags=INEXACT (11/0)
|
||||
op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
res: f32(0x1.0007fe00000000000000p-25:0x330003ff) flags=INEXACT (11/1)
|
||||
op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
res: f32(0x1.0001f200000000000000p-24:0x338000f9) flags=INEXACT (11/2)
|
||||
op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
res: f32(0x1.00000c00000000000000p-14:0x38800006) flags=INEXACT (12/0)
|
||||
op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
res: f32(0x1.0ffbf400000000000000p-24:0x3387fdfa) flags=INEXACT (12/1)
|
||||
op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
res: f32(0x1.ff801a00000000000000p-15:0x387fc00d) flags=INEXACT (12/2)
|
||||
op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
res: f32(0x1.00000000000000000000p+0:0x3f800000) flags=INEXACT (13/0)
|
||||
op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
res: f32(0x1.ffc01800000000000000p-14:0x38ffe00c) flags=INEXACT (13/1)
|
||||
op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
res: f32(0x1.ffc01800000000000000p-14:0x38ffe00c) flags=INEXACT (13/2)
|
||||
op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/0)
|
||||
op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/1)
|
||||
op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
res: f32(0x1.00040000000000000000p+0:0x3f800200) flags=INEXACT (14/2)
|
||||
op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/0)
|
||||
op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
res: f32(0x1.80400000000000000000p+1:0x40402000) flags=INEXACT (15/1)
|
||||
op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/2)
|
||||
op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=INEXACT (16/0)
|
||||
op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=INEXACT (16/1)
|
||||
op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
res: f32(0x1.2e23d200000000000000p+2:0x409711e9) flags=INEXACT (16/2)
|
||||
op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
res: f32(0x1.12804000000000000000p+3:0x41094020) flags=INEXACT (17/0)
|
||||
op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
res: f32(0x1.51458000000000000000p+3:0x4128a2c0) flags=INEXACT (17/1)
|
||||
op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
res: f32(0x1.200c0400000000000000p+3:0x41100602) flags=INEXACT (17/2)
|
||||
op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
res: f32(0x1.ffcf1400000000000000p+15:0x477fe78a) flags=INEXACT (18/0)
|
||||
op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
res: f32(0x1.91ed3a00000000000000p+17:0x4848f69d) flags=INEXACT (18/1)
|
||||
op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
res: f32(0x1.5bc56000000000000000p+17:0x482de2b0) flags=INEXACT (18/2)
|
||||
op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
res: f32(0x1.08edee00000000000000p+18:0x488476f7) flags=INEXACT (19/0)
|
||||
op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
res: f32(0x1.ff7e0800000000000000p+31:0x4f7fbf04) flags=INEXACT (19/1)
|
||||
op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
res: f32(0x1.08ee7800000000000000p+18:0x4884773c) flags=INEXACT (19/2)
|
||||
op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
res: f32(0x1.ff800800000000000000p+31:0x4f7fc004) flags=INEXACT (20/0)
|
||||
op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
res: f32(0x1.ff840600000000000000p+31:0x4f7fc203) flags=INEXACT (20/1)
|
||||
op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
res: f32(0x1.ff820600000000000000p+31:0x4f7fc103) flags=INEXACT (20/2)
|
||||
op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
res: f32(0x1.ff860600000000000000p+31:0x4f7fc303) flags=INEXACT (21/0)
|
||||
op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
res: f32(0x1.ff820600000000000000p+32:0x4fffc103) flags=INEXACT (21/1)
|
||||
op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
res: f32(0x1.ff800800000000000000p+32:0x4fffc004) flags=INEXACT (21/2)
|
||||
op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
res: f32(0x1.ff830600000000000000p+32:0x4fffc183) flags=INEXACT (22/0)
|
||||
op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
res: f32(0x1.ff7f8800000000000000p+33:0x507fbfc4) flags=INEXACT (22/1)
|
||||
op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
res: f32(0x1.ff840600000000000000p+32:0x4fffc203) flags=INEXACT (22/2)
|
||||
op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
res: f32(0x1.ff800800000000000000p+33:0x507fc004) flags=INEXACT (23/0)
|
||||
op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
res: f32(0x1.ff820600000000000000p+33:0x507fc103) flags=INEXACT (23/1)
|
||||
op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
res: f32(0x1.ff810600000000000000p+33:0x507fc083) flags=INEXACT (23/2)
|
||||
op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
res: f32(0x1.c0bab600000000000000p+99:0x71605d5b) flags=INEXACT (24/0)
|
||||
op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
res: f32(0x1.c0837e00000000000000p+116:0x79e041bf) flags=INEXACT (24/1)
|
||||
op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
res: f32(0x1.c0829e00000000000000p+116:0x79e0414f) flags=INEXACT (24/2)
|
||||
op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (25/0)
|
||||
op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (25/1)
|
||||
op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (25/2)
|
||||
op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000)
|
||||
res: f32(inf:0x7f800000) flags=OK (26/0)
|
||||
op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
res: f32(inf:0x7f800000) flags=OK (26/1)
|
||||
op : f32(inf:0x7f800000) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
res: f32(inf:0x7f800000) flags=OK (26/2)
|
||||
op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(-nan:0x7fc00000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (27/0)
|
||||
op : f32(inf:0x7f800000) * f32(-nan:0x7fc00000) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
res: f32(-nan:0xffffffff) flags=OK (27/1)
|
||||
op : f32(-nan:0x7fc00000) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (27/2)
|
||||
op : f32(inf:0x7f800000) * f32(-nan:0x7fc00000) + f32(-nan:0x7fa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (28/0)
|
||||
op : f32(-nan:0x7fc00000) * f32(-nan:0x7fa00000) + f32(inf:0x7f800000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (28/1)
|
||||
op : f32(-nan:0x7fa00000) * f32(inf:0x7f800000) + f32(-nan:0x7fc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (28/2)
|
||||
op : f32(-nan:0x7fc00000) * f32(-nan:0x7fa00000) + f32(-nan:0xffa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (29/0)
|
||||
op : f32(-nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(-nan:0x7fc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (29/1)
|
||||
op : f32(-nan:0xffa00000) * f32(-nan:0x7fc00000) + f32(-nan:0x7fa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (29/2)
|
||||
op : f32(-nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (30/0)
|
||||
op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(-nan:0x7fa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (30/1)
|
||||
op : f32(-nan:0xffc00000) * f32(-nan:0x7fa00000) + f32(-nan:0xffa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (30/2)
|
||||
# LP184149
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-1:0x3f000000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(0x0.00000000000000000000p+0:0000000000) flags=OK (31/0)
|
||||
op : f32(0x1.00000000000000000000p-149:0x00000001) * f32(0x1.00000000000000000000p-149:0x00000001) + f32(0x1.00000000000000000000p-149:0x00000001)
|
||||
res: f32(0x1.00000000000000000000p-149:0x00000001) flags=UNDERFLOW INEXACT (32/0)
|
||||
### Rounding to zero
|
||||
op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(-inf:0xff800000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (0/0)
|
||||
op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-nan:0xffa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (0/1)
|
||||
op : f32(-inf:0xff800000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (0/2)
|
||||
op : f32(-nan:0xffc00000) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
res: f32(-nan:0xffffffff) flags=OK (1/0)
|
||||
op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-nan:0xffc00000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (1/1)
|
||||
op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-nan:0xffc00000) + f32(-inf:0xff800000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (1/2)
|
||||
op : f32(-inf:0xff800000) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
res: f32(inf:0x7f800000) flags=OK (2/0)
|
||||
op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-inf:0xff800000)
|
||||
res: f32(-inf:0xff800000) flags=OK (2/1)
|
||||
op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-inf:0xff800000) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
res: f32(inf:0x7f800000) flags=OK (2/2)
|
||||
op : f32(-0x1.fffffe00000000000000p+127:0xff7fffff) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (3/0)
|
||||
op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.fffffe00000000000000p+127:0xff7fffff)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (3/1)
|
||||
op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.fffffe00000000000000p+127:0xff7fffff) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (3/2)
|
||||
op : f32(-0x1.1874b200000000000000p+103:0xf30c3a59) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (4/0)
|
||||
op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.1874b200000000000000p+103:0xf30c3a59)
|
||||
res: f32(-0x1.1874b000000000000000p+103:0xf30c3a58) flags=INEXACT (4/1)
|
||||
op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.1874b200000000000000p+103:0xf30c3a59) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
res: f32(-0x1.c0bab400000000000000p+99:0xf1605d5a) flags=INEXACT (4/2)
|
||||
op : f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
res: f32(0x1.0c27f800000000000000p+60:0x5d8613fc) flags=INEXACT (5/0)
|
||||
op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.c0bab600000000000000p+99:0xf1605d5b)
|
||||
res: f32(-0x1.c0bab400000000000000p+99:0xf1605d5a) flags=INEXACT (5/1)
|
||||
op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) + f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
res: f32(0x1.26c46000000000000000p+34:0x50936230) flags=INEXACT (5/2)
|
||||
op : f32(-0x1.31f75000000000000000p-40:0xab98fba8) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
res: f32(0x1.91f93e00000000000000p-106:0x0ac8fc9f) flags=INEXACT (6/0)
|
||||
op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(-0x1.31f75000000000000000p-40:0xab98fba8)
|
||||
res: f32(-0x1.31f74e00000000000000p-40:0xab98fba7) flags=INEXACT (6/1)
|
||||
op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(-0x1.31f75000000000000000p-40:0xab98fba8) + f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
res: f32(-0x1.50544200000000000000p-66:0x9ea82a21) flags=INEXACT (6/2)
|
||||
op : f32(-0x1.50544400000000000000p-66:0x9ea82a22) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (7/0)
|
||||
op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(-0x1.50544400000000000000p-66:0x9ea82a22)
|
||||
res: f32(-0x1.50544400000000000000p-66:0x9ea82a22) flags=INEXACT (7/1)
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(-0x1.50544400000000000000p-66:0x9ea82a22) + f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (7/2)
|
||||
op : f32(-0x1.00000000000000000000p-126:0x80800000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (8/0)
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(-0x1.00000000000000000000p-126:0x80800000)
|
||||
res: f32(-0x1.00000000000000000000p-126:0x80800000) flags=OK (8/1)
|
||||
op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(-0x1.00000000000000000000p-126:0x80800000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(-0x0.00000000000000000000p+0:0x80000000) flags=UNDERFLOW INEXACT (8/2)
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
res: f32(0x1.00000000000000000000p-25:0x33000000) flags=OK (9/0)
|
||||
op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(0x0.00000000000000000000p+0:0000000000) flags=UNDERFLOW INEXACT (9/1)
|
||||
op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x0.00000000000000000000p+0:0000000000) + f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
res: f32(0x1.00000000000000000000p-126:0x00800000) flags=OK (9/2)
|
||||
op : f32(0x1.00000000000000000000p-126:0x00800000) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
res: f32(0x1.ffffe600000000000000p-25:0x337ffff3) flags=INEXACT (10/0)
|
||||
op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.00000000000000000000p-126:0x00800000)
|
||||
res: f32(0x1.ffffe600000000000000p-50:0x26fffff3) flags=INEXACT (10/1)
|
||||
op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.00000000000000000000p-126:0x00800000) + f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
res: f32(0x1.00000000000000000000p-25:0x33000000) flags=INEXACT (10/2)
|
||||
op : f32(0x1.00000000000000000000p-25:0x33000000) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
res: f32(0x1.ff801a00000000000000p-15:0x387fc00d) flags=INEXACT (11/0)
|
||||
op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000000000000000000p-25:0x33000000)
|
||||
res: f32(0x1.0007fe00000000000000p-25:0x330003ff) flags=INEXACT (11/1)
|
||||
op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000000000000000000p-25:0x33000000) + f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
res: f32(0x1.0001f200000000000000p-24:0x338000f9) flags=INEXACT (11/2)
|
||||
op : f32(0x1.ffffe600000000000000p-25:0x337ffff3) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
res: f32(0x1.00000c00000000000000p-14:0x38800006) flags=INEXACT (12/0)
|
||||
op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.ffffe600000000000000p-25:0x337ffff3)
|
||||
res: f32(0x1.0ffbf400000000000000p-24:0x3387fdfa) flags=INEXACT (12/1)
|
||||
op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.ffffe600000000000000p-25:0x337ffff3) + f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
res: f32(0x1.ff801a00000000000000p-15:0x387fc00d) flags=INEXACT (12/2)
|
||||
op : f32(0x1.ff801a00000000000000p-15:0x387fc00d) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
res: f32(0x1.00000000000000000000p+0:0x3f800000) flags=INEXACT (13/0)
|
||||
op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.ff801a00000000000000p-15:0x387fc00d)
|
||||
res: f32(0x1.ffc01800000000000000p-14:0x38ffe00c) flags=INEXACT (13/1)
|
||||
op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.ff801a00000000000000p-15:0x387fc00d) + f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
res: f32(0x1.ffc01800000000000000p-14:0x38ffe00c) flags=INEXACT (13/2)
|
||||
op : f32(0x1.00000c00000000000000p-14:0x38800006) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/0)
|
||||
op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000c00000000000000p-14:0x38800006)
|
||||
res: f32(0x1.00440000000000000000p+0:0x3f802200) flags=INEXACT (14/1)
|
||||
op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000c00000000000000p-14:0x38800006) + f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
res: f32(0x1.00040000000000000000p+0:0x3f800200) flags=INEXACT (14/2)
|
||||
op : f32(0x1.00000000000000000000p+0:0x3f800000) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/0)
|
||||
op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.00000000000000000000p+0:0x3f800000)
|
||||
res: f32(0x1.80400000000000000000p+1:0x40402000) flags=INEXACT (15/1)
|
||||
op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.00000000000000000000p+0:0x3f800000) + f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
res: f32(0x1.80200000000000000000p+1:0x40401000) flags=INEXACT (15/2)
|
||||
op : f32(0x1.00400000000000000000p+0:0x3f802000) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
res: f32(0x1.2e185400000000000000p+2:0x40970c2a) flags=INEXACT (16/0)
|
||||
op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.00400000000000000000p+0:0x3f802000)
|
||||
res: f32(0x1.9c00a800000000000000p+2:0x40ce0054) flags=INEXACT (16/1)
|
||||
op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.00400000000000000000p+0:0x3f802000) + f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
res: f32(0x1.2e23d200000000000000p+2:0x409711e9) flags=INEXACT (16/2)
|
||||
op : f32(0x1.00000000000000000000p+1:0x40000000) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
res: f32(0x1.12804000000000000000p+3:0x41094020) flags=INEXACT (17/0)
|
||||
op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.00000000000000000000p+1:0x40000000)
|
||||
res: f32(0x1.51458000000000000000p+3:0x4128a2c0) flags=INEXACT (17/1)
|
||||
op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.00000000000000000000p+1:0x40000000) + f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
res: f32(0x1.200c0400000000000000p+3:0x41100602) flags=INEXACT (17/2)
|
||||
op : f32(0x1.5bf0a800000000000000p+1:0x402df854) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
res: f32(0x1.ffcf1400000000000000p+15:0x477fe78a) flags=INEXACT (18/0)
|
||||
op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.5bf0a800000000000000p+1:0x402df854)
|
||||
res: f32(0x1.91ed3a00000000000000p+17:0x4848f69d) flags=INEXACT (18/1)
|
||||
op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.5bf0a800000000000000p+1:0x402df854) + f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
res: f32(0x1.5bc56000000000000000p+17:0x482de2b0) flags=INEXACT (18/2)
|
||||
op : f32(0x1.921fb600000000000000p+1:0x40490fdb) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
res: f32(0x1.08edee00000000000000p+18:0x488476f7) flags=INEXACT (19/0)
|
||||
op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.921fb600000000000000p+1:0x40490fdb)
|
||||
res: f32(0x1.ff7e0800000000000000p+31:0x4f7fbf04) flags=INEXACT (19/1)
|
||||
op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.921fb600000000000000p+1:0x40490fdb) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
res: f32(0x1.08ee7800000000000000p+18:0x4884773c) flags=INEXACT (19/2)
|
||||
op : f32(0x1.ffbe0000000000000000p+15:0x477fdf00) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
res: f32(0x1.ff800800000000000000p+31:0x4f7fc004) flags=INEXACT (20/0)
|
||||
op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbe0000000000000000p+15:0x477fdf00)
|
||||
res: f32(0x1.ff840600000000000000p+31:0x4f7fc203) flags=INEXACT (20/1)
|
||||
op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbe0000000000000000p+15:0x477fdf00) + f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
res: f32(0x1.ff820600000000000000p+31:0x4f7fc103) flags=INEXACT (20/2)
|
||||
op : f32(0x1.ffc00000000000000000p+15:0x477fe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
res: f32(0x1.ff860600000000000000p+31:0x4f7fc303) flags=INEXACT (21/0)
|
||||
op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+15:0x477fe000)
|
||||
res: f32(0x1.ff820600000000000000p+32:0x4fffc103) flags=INEXACT (21/1)
|
||||
op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+15:0x477fe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
res: f32(0x1.ff800800000000000000p+32:0x4fffc004) flags=INEXACT (21/2)
|
||||
op : f32(0x1.ffc20000000000000000p+15:0x477fe100) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
res: f32(0x1.ff830600000000000000p+32:0x4fffc183) flags=INEXACT (22/0)
|
||||
op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc20000000000000000p+15:0x477fe100)
|
||||
res: f32(0x1.ff7f8800000000000000p+33:0x507fbfc4) flags=INEXACT (22/1)
|
||||
op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc20000000000000000p+15:0x477fe100) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
res: f32(0x1.ff840600000000000000p+32:0x4fffc203) flags=INEXACT (22/2)
|
||||
op : f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
res: f32(0x1.ff800800000000000000p+33:0x507fc004) flags=INEXACT (23/0)
|
||||
op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.ffbf0000000000000000p+16:0x47ffdf80)
|
||||
res: f32(0x1.ff820600000000000000p+33:0x507fc103) flags=INEXACT (23/1)
|
||||
op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) + f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
res: f32(0x1.ff810600000000000000p+33:0x507fc083) flags=INEXACT (23/2)
|
||||
op : f32(0x1.ffc00000000000000000p+16:0x47ffe000) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
res: f32(0x1.c0bab600000000000000p+99:0x71605d5b) flags=INEXACT (24/0)
|
||||
op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.ffc00000000000000000p+16:0x47ffe000)
|
||||
res: f32(0x1.c0837e00000000000000p+116:0x79e041bf) flags=INEXACT (24/1)
|
||||
op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.ffc00000000000000000p+16:0x47ffe000) + f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
res: f32(0x1.c0829e00000000000000p+116:0x79e0414f) flags=INEXACT (24/2)
|
||||
op : f32(0x1.ffc10000000000000000p+16:0x47ffe080) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (25/0)
|
||||
op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(0x1.ffc10000000000000000p+16:0x47ffe080)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (25/1)
|
||||
op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(0x1.ffc10000000000000000p+16:0x47ffe080) + f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
res: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) flags=OVERFLOW INEXACT (25/2)
|
||||
op : f32(0x1.c0bab600000000000000p+99:0x71605d5b) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000)
|
||||
res: f32(inf:0x7f800000) flags=OK (26/0)
|
||||
op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(0x1.c0bab600000000000000p+99:0x71605d5b)
|
||||
res: f32(inf:0x7f800000) flags=OK (26/1)
|
||||
op : f32(inf:0x7f800000) * f32(0x1.c0bab600000000000000p+99:0x71605d5b) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
res: f32(inf:0x7f800000) flags=OK (26/2)
|
||||
op : f32(0x1.fffffe00000000000000p+127:0x7f7fffff) * f32(inf:0x7f800000) + f32(-nan:0x7fc00000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (27/0)
|
||||
op : f32(inf:0x7f800000) * f32(-nan:0x7fc00000) + f32(0x1.fffffe00000000000000p+127:0x7f7fffff)
|
||||
res: f32(-nan:0xffffffff) flags=OK (27/1)
|
||||
op : f32(-nan:0x7fc00000) * f32(0x1.fffffe00000000000000p+127:0x7f7fffff) + f32(inf:0x7f800000)
|
||||
res: f32(-nan:0xffffffff) flags=OK (27/2)
|
||||
op : f32(inf:0x7f800000) * f32(-nan:0x7fc00000) + f32(-nan:0x7fa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (28/0)
|
||||
op : f32(-nan:0x7fc00000) * f32(-nan:0x7fa00000) + f32(inf:0x7f800000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (28/1)
|
||||
op : f32(-nan:0x7fa00000) * f32(inf:0x7f800000) + f32(-nan:0x7fc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (28/2)
|
||||
op : f32(-nan:0x7fc00000) * f32(-nan:0x7fa00000) + f32(-nan:0xffa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (29/0)
|
||||
op : f32(-nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(-nan:0x7fc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (29/1)
|
||||
op : f32(-nan:0xffa00000) * f32(-nan:0x7fc00000) + f32(-nan:0x7fa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (29/2)
|
||||
op : f32(-nan:0x7fa00000) * f32(-nan:0xffa00000) + f32(-nan:0xffc00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (30/0)
|
||||
op : f32(-nan:0xffa00000) * f32(-nan:0xffc00000) + f32(-nan:0x7fa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (30/1)
|
||||
op : f32(-nan:0xffc00000) * f32(-nan:0x7fa00000) + f32(-nan:0xffa00000)
|
||||
res: f32(-nan:0xffffffff) flags=INVALID (30/2)
|
||||
# LP184149
|
||||
op : f32(0x0.00000000000000000000p+0:0000000000) * f32(0x1.00000000000000000000p-1:0x3f000000) + f32(0x0.00000000000000000000p+0:0000000000)
|
||||
res: f32(0x0.00000000000000000000p+0:0000000000) flags=OK (31/0)
|
||||
op : f32(0x1.00000000000000000000p-149:0x00000001) * f32(0x1.00000000000000000000p-149:0x00000001) + f32(0x1.00000000000000000000p-149:0x00000001)
|
||||
res: f32(0x1.00000000000000000000p-149:0x00000001) flags=UNDERFLOW INEXACT (32/0)
|
370
tests/tcg/hexagon/fpstuff.c
Normal file
370
tests/tcg/hexagon/fpstuff.c
Normal file
@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright(c) 2020-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This test checks various FP operations performed on Hexagon
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
const int FPINVF_BIT = 1; /* Invalid */
|
||||
const int FPINVF = 1 << FPINVF_BIT;
|
||||
const int FPDBZF_BIT = 2; /* Divide by zero */
|
||||
const int FPDBZF = 1 << FPDBZF_BIT;
|
||||
const int FPOVFF_BIT = 3; /* Overflow */
|
||||
const int FPOVFF = 1 << FPOVFF_BIT;
|
||||
const int FPUNFF_BIT = 4; /* Underflow */
|
||||
const int FPUNFF = 1 << FPUNFF_BIT;
|
||||
const int FPINPF_BIT = 5; /* Inexact */
|
||||
const int FPINPF = 1 << FPINPF_BIT;
|
||||
|
||||
const int SF_ZERO = 0x00000000;
|
||||
const int SF_NaN = 0x7fc00000;
|
||||
const int SF_NaN_special = 0x7f800001;
|
||||
const int SF_ANY = 0x3f800000;
|
||||
const int SF_HEX_NAN = 0xffffffff;
|
||||
|
||||
const long long DF_NaN = 0x7ff8000000000000ULL;
|
||||
const long long DF_ANY = 0x3f80000000000000ULL;
|
||||
const long long DF_HEX_NAN = 0xffffffffffffffffULL;
|
||||
|
||||
int err;
|
||||
|
||||
#define CLEAR_FPSTATUS \
|
||||
"r2 = usr\n\t" \
|
||||
"r2 = clrbit(r2, #1)\n\t" \
|
||||
"r2 = clrbit(r2, #2)\n\t" \
|
||||
"r2 = clrbit(r2, #3)\n\t" \
|
||||
"r2 = clrbit(r2, #4)\n\t" \
|
||||
"r2 = clrbit(r2, #5)\n\t" \
|
||||
"usr = r2\n\t"
|
||||
|
||||
static void check_fpstatus_bit(int usr, int expect, int flag, const char *n)
|
||||
{
|
||||
int bit = 1 << flag;
|
||||
if ((usr & bit) != (expect & bit)) {
|
||||
printf("ERROR %s: usr = %d, expect = %d\n", n,
|
||||
(usr >> flag) & 1, (expect >> flag) & 1);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
static void check_fpstatus(int usr, int expect)
|
||||
{
|
||||
check_fpstatus_bit(usr, expect, FPINVF_BIT, "Invalid");
|
||||
check_fpstatus_bit(usr, expect, FPDBZF_BIT, "Div by zero");
|
||||
check_fpstatus_bit(usr, expect, FPOVFF_BIT, "Overflow");
|
||||
check_fpstatus_bit(usr, expect, FPUNFF_BIT, "Underflow");
|
||||
check_fpstatus_bit(usr, expect, FPINPF_BIT, "Inexact");
|
||||
}
|
||||
|
||||
static void check32(int val, int expect)
|
||||
{
|
||||
if (val != expect) {
|
||||
printf("ERROR: 0x%x != 0x%x\n", val, expect);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
static void check64(unsigned long long val, unsigned long long expect)
|
||||
{
|
||||
if (val != expect) {
|
||||
printf("ERROR: 0x%llx != 0x%llx\n", val, expect);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
static void check_compare_exception(void)
|
||||
{
|
||||
int cmp;
|
||||
int usr;
|
||||
|
||||
/* Check that FP compares are quiet (don't raise any execptions) */
|
||||
asm (CLEAR_FPSTATUS
|
||||
"p0 = sfcmp.eq(%2, %3)\n\t"
|
||||
"%0 = p0\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
|
||||
: "r2", "p0", "usr");
|
||||
check32(cmp, 0);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
asm (CLEAR_FPSTATUS
|
||||
"p0 = sfcmp.gt(%2, %3)\n\t"
|
||||
"%0 = p0\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
|
||||
: "r2", "p0", "usr");
|
||||
check32(cmp, 0);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
asm (CLEAR_FPSTATUS
|
||||
"p0 = sfcmp.ge(%2, %3)\n\t"
|
||||
"%0 = p0\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(cmp), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
|
||||
: "r2", "p0", "usr");
|
||||
check32(cmp, 0);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
asm (CLEAR_FPSTATUS
|
||||
"p0 = dfcmp.eq(%2, %3)\n\t"
|
||||
"%0 = p0\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(cmp), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
|
||||
: "r2", "p0", "usr");
|
||||
check32(cmp, 0);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
asm (CLEAR_FPSTATUS
|
||||
"p0 = dfcmp.gt(%2, %3)\n\t"
|
||||
"%0 = p0\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(cmp), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
|
||||
: "r2", "p0", "usr");
|
||||
check32(cmp, 0);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
asm (CLEAR_FPSTATUS
|
||||
"p0 = dfcmp.ge(%2, %3)\n\t"
|
||||
"%0 = p0\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(cmp), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
|
||||
: "r2", "p0", "usr");
|
||||
check32(cmp, 0);
|
||||
check_fpstatus(usr, 0);
|
||||
}
|
||||
|
||||
static void check_sfminmax(void)
|
||||
{
|
||||
int minmax;
|
||||
int usr;
|
||||
|
||||
/*
|
||||
* Execute sfmin/sfmax instructions with one operand as NaN
|
||||
* Check that
|
||||
* Result is the other operand
|
||||
* Invalid bit in USR is not set
|
||||
*/
|
||||
asm (CLEAR_FPSTATUS
|
||||
"%0 = sfmin(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
|
||||
: "r2", "usr");
|
||||
check64(minmax, SF_ANY);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
asm (CLEAR_FPSTATUS
|
||||
"%0 = sfmax(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
|
||||
: "r2", "usr");
|
||||
check64(minmax, SF_ANY);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
/*
|
||||
* Execute sfmin/sfmax instructions with both operands NaN
|
||||
* Check that
|
||||
* Result is SF_HEX_NAN
|
||||
* Invalid bit in USR is set
|
||||
*/
|
||||
asm (CLEAR_FPSTATUS
|
||||
"%0 = sfmin(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_NaN)
|
||||
: "r2", "usr");
|
||||
check64(minmax, SF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
asm (CLEAR_FPSTATUS
|
||||
"%0 = sfmax(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(minmax), "=r"(usr) : "r"(SF_NaN), "r"(SF_NaN)
|
||||
: "r2", "usr");
|
||||
check64(minmax, SF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
}
|
||||
|
||||
static void check_dfminmax(void)
|
||||
{
|
||||
unsigned long long minmax;
|
||||
int usr;
|
||||
|
||||
/*
|
||||
* Execute dfmin/dfmax instructions with one operand as NaN
|
||||
* Check that
|
||||
* Result is the other operand
|
||||
* Invalid bit in USR is set
|
||||
*/
|
||||
asm (CLEAR_FPSTATUS
|
||||
"%0 = dfmin(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
|
||||
: "r2", "usr");
|
||||
check64(minmax, DF_ANY);
|
||||
check_fpstatus(usr, FPINVF);
|
||||
|
||||
asm (CLEAR_FPSTATUS
|
||||
"%0 = dfmax(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
|
||||
: "r2", "usr");
|
||||
check64(minmax, DF_ANY);
|
||||
check_fpstatus(usr, FPINVF);
|
||||
|
||||
/*
|
||||
* Execute dfmin/dfmax instructions with both operands NaN
|
||||
* Check that
|
||||
* Result is DF_HEX_NAN
|
||||
* Invalid bit in USR is set
|
||||
*/
|
||||
asm (CLEAR_FPSTATUS
|
||||
"%0 = dfmin(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_NaN)
|
||||
: "r2", "usr");
|
||||
check64(minmax, DF_HEX_NAN);
|
||||
check_fpstatus(usr, FPINVF);
|
||||
|
||||
asm (CLEAR_FPSTATUS
|
||||
"%0 = dfmax(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(minmax), "=r"(usr) : "r"(DF_NaN), "r"(DF_NaN)
|
||||
: "r2", "usr");
|
||||
check64(minmax, DF_HEX_NAN);
|
||||
check_fpstatus(usr, FPINVF);
|
||||
}
|
||||
|
||||
static void check_canonical_NaN(void)
|
||||
{
|
||||
int sf_result;
|
||||
unsigned long long df_result;
|
||||
int usr;
|
||||
|
||||
/* Check that each FP instruction properly returns SF_HEX_NAN/DF_HEX_NAN */
|
||||
asm(CLEAR_FPSTATUS
|
||||
"%0 = sfadd(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
|
||||
: "r2", "usr");
|
||||
check32(sf_result, SF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
asm(CLEAR_FPSTATUS
|
||||
"%0 = sfsub(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
|
||||
: "r2", "usr");
|
||||
check32(sf_result, SF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
asm(CLEAR_FPSTATUS
|
||||
"%0 = sfmpy(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
|
||||
: "r2", "usr");
|
||||
check32(sf_result, SF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
sf_result = SF_ZERO;
|
||||
asm(CLEAR_FPSTATUS
|
||||
"%0 += sfmpy(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
|
||||
: "r2", "usr");
|
||||
check32(sf_result, SF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
sf_result = SF_ZERO;
|
||||
asm(CLEAR_FPSTATUS
|
||||
"p0 = !cmp.eq(r0, r0)\n\t"
|
||||
"%0 += sfmpy(%2, %3, p0):scale\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
|
||||
: "r2", "usr", "p0");
|
||||
check32(sf_result, SF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
sf_result = SF_ZERO;
|
||||
asm(CLEAR_FPSTATUS
|
||||
"%0 -= sfmpy(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
|
||||
: "r2", "usr");
|
||||
check32(sf_result, SF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
sf_result = SF_ZERO;
|
||||
asm(CLEAR_FPSTATUS
|
||||
"%0 += sfmpy(%2, %3):lib\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
|
||||
: "r2", "usr");
|
||||
check32(sf_result, SF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
sf_result = SF_ZERO;
|
||||
asm(CLEAR_FPSTATUS
|
||||
"%0 -= sfmpy(%2, %3):lib\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "+r"(sf_result), "=r"(usr) : "r"(SF_NaN), "r"(SF_ANY)
|
||||
: "r2", "usr");
|
||||
check32(sf_result, SF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
asm(CLEAR_FPSTATUS
|
||||
"%0 = convert_df2sf(%2)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(sf_result), "=r"(usr) : "r"(DF_NaN)
|
||||
: "r2", "usr");
|
||||
check32(sf_result, SF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
asm(CLEAR_FPSTATUS
|
||||
"%0 = dfadd(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(df_result), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
|
||||
: "r2", "usr");
|
||||
check64(df_result, DF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
asm(CLEAR_FPSTATUS
|
||||
"%0 = dfsub(%2, %3)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(df_result), "=r"(usr) : "r"(DF_NaN), "r"(DF_ANY)
|
||||
: "r2", "usr");
|
||||
check64(df_result, DF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
|
||||
asm(CLEAR_FPSTATUS
|
||||
"%0 = convert_sf2df(%2)\n\t"
|
||||
"%1 = usr\n\t"
|
||||
: "=r"(df_result), "=r"(usr) : "r"(SF_NaN)
|
||||
: "r2", "usr");
|
||||
check64(df_result, DF_HEX_NAN);
|
||||
check_fpstatus(usr, 0);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
check_compare_exception();
|
||||
check_sfminmax();
|
||||
check_dfminmax();
|
||||
check_canonical_NaN();
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err ? 1 : 0;
|
||||
}
|
328
tests/tcg/hexagon/mem_noshuf.c
Normal file
328
tests/tcg/hexagon/mem_noshuf.c
Normal file
@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
* Make sure that the :mem_noshuf packet attribute is honored.
|
||||
* This is important when the addresses overlap.
|
||||
* The store instruction in slot 1 effectively executes first,
|
||||
* followed by the load instruction in slot 0.
|
||||
*/
|
||||
|
||||
#define MEM_NOSHUF32(NAME, ST_TYPE, LD_TYPE, ST_OP, LD_OP) \
|
||||
static inline unsigned int NAME(ST_TYPE * p, LD_TYPE * q, ST_TYPE x) \
|
||||
{ \
|
||||
unsigned int ret; \
|
||||
asm volatile("{\n\t" \
|
||||
" " #ST_OP "(%1) = %3\n\t" \
|
||||
" %0 = " #LD_OP "(%2)\n\t" \
|
||||
"}:mem_noshuf\n" \
|
||||
: "=r"(ret) \
|
||||
: "r"(p), "r"(q), "r"(x) \
|
||||
: "memory"); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define MEM_NOSHUF64(NAME, ST_TYPE, LD_TYPE, ST_OP, LD_OP) \
|
||||
static inline unsigned long long NAME(ST_TYPE * p, LD_TYPE * q, ST_TYPE x) \
|
||||
{ \
|
||||
unsigned long long ret; \
|
||||
asm volatile("{\n\t" \
|
||||
" " #ST_OP "(%1) = %3\n\t" \
|
||||
" %0 = " #LD_OP "(%2)\n\t" \
|
||||
"}:mem_noshuf\n" \
|
||||
: "=r"(ret) \
|
||||
: "r"(p), "r"(q), "r"(x) \
|
||||
: "memory"); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
/* Store byte combinations */
|
||||
MEM_NOSHUF32(mem_noshuf_sb_lb, signed char, signed char, memb, memb)
|
||||
MEM_NOSHUF32(mem_noshuf_sb_lub, signed char, unsigned char, memb, memub)
|
||||
MEM_NOSHUF32(mem_noshuf_sb_lh, signed char, signed short, memb, memh)
|
||||
MEM_NOSHUF32(mem_noshuf_sb_luh, signed char, unsigned short, memb, memuh)
|
||||
MEM_NOSHUF32(mem_noshuf_sb_lw, signed char, signed int, memb, memw)
|
||||
MEM_NOSHUF64(mem_noshuf_sb_ld, signed char, signed long long, memb, memd)
|
||||
|
||||
/* Store half combinations */
|
||||
MEM_NOSHUF32(mem_noshuf_sh_lb, signed short, signed char, memh, memb)
|
||||
MEM_NOSHUF32(mem_noshuf_sh_lub, signed short, unsigned char, memh, memub)
|
||||
MEM_NOSHUF32(mem_noshuf_sh_lh, signed short, signed short, memh, memh)
|
||||
MEM_NOSHUF32(mem_noshuf_sh_luh, signed short, unsigned short, memh, memuh)
|
||||
MEM_NOSHUF32(mem_noshuf_sh_lw, signed short, signed int, memh, memw)
|
||||
MEM_NOSHUF64(mem_noshuf_sh_ld, signed short, signed long long, memh, memd)
|
||||
|
||||
/* Store word combinations */
|
||||
MEM_NOSHUF32(mem_noshuf_sw_lb, signed int, signed char, memw, memb)
|
||||
MEM_NOSHUF32(mem_noshuf_sw_lub, signed int, unsigned char, memw, memub)
|
||||
MEM_NOSHUF32(mem_noshuf_sw_lh, signed int, signed short, memw, memh)
|
||||
MEM_NOSHUF32(mem_noshuf_sw_luh, signed int, unsigned short, memw, memuh)
|
||||
MEM_NOSHUF32(mem_noshuf_sw_lw, signed int, signed int, memw, memw)
|
||||
MEM_NOSHUF64(mem_noshuf_sw_ld, signed int, signed long long, memw, memd)
|
||||
|
||||
/* Store double combinations */
|
||||
MEM_NOSHUF32(mem_noshuf_sd_lb, long long, signed char, memd, memb)
|
||||
MEM_NOSHUF32(mem_noshuf_sd_lub, long long, unsigned char, memd, memub)
|
||||
MEM_NOSHUF32(mem_noshuf_sd_lh, long long, signed short, memd, memh)
|
||||
MEM_NOSHUF32(mem_noshuf_sd_luh, long long, unsigned short, memd, memuh)
|
||||
MEM_NOSHUF32(mem_noshuf_sd_lw, long long, signed int, memd, memw)
|
||||
MEM_NOSHUF64(mem_noshuf_sd_ld, long long, signed long long, memd, memd)
|
||||
|
||||
static inline unsigned int cancel_sw_lb(int pred, int *p, signed char *q, int x)
|
||||
{
|
||||
unsigned int ret;
|
||||
asm volatile("p0 = cmp.eq(%4, #0)\n\t"
|
||||
"{\n\t"
|
||||
" if (!p0) memw(%1) = %3\n\t"
|
||||
" %0 = memb(%2)\n\t"
|
||||
"}:mem_noshuf\n"
|
||||
: "=r"(ret)
|
||||
: "r"(p), "r"(q), "r"(x), "r"(pred)
|
||||
: "p0", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned long long cancel_sw_ld(int pred, int *p, long long *q, int x)
|
||||
{
|
||||
long long ret;
|
||||
asm volatile("p0 = cmp.eq(%4, #0)\n\t"
|
||||
"{\n\t"
|
||||
" if (!p0) memw(%1) = %3\n\t"
|
||||
" %0 = memd(%2)\n\t"
|
||||
"}:mem_noshuf\n"
|
||||
: "=r"(ret)
|
||||
: "r"(p), "r"(q), "r"(x), "r"(pred)
|
||||
: "p0", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef union {
|
||||
signed long long d[2];
|
||||
unsigned long long ud[2];
|
||||
signed int w[4];
|
||||
unsigned int uw[4];
|
||||
signed short h[8];
|
||||
unsigned short uh[8];
|
||||
signed char b[16];
|
||||
unsigned char ub[16];
|
||||
} Memory;
|
||||
|
||||
int err;
|
||||
|
||||
static void check32(int n, int expect)
|
||||
{
|
||||
if (n != expect) {
|
||||
printf("ERROR: 0x%08x != 0x%08x\n", n, expect);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
static void check64(long long n, long long expect)
|
||||
{
|
||||
if (n != expect) {
|
||||
printf("ERROR: 0x%08llx != 0x%08llx\n", n, expect);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
Memory n;
|
||||
unsigned int res32;
|
||||
unsigned long long res64;
|
||||
|
||||
/*
|
||||
* Store byte combinations
|
||||
*/
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sb_lb(&n.b[0], &n.b[0], 0x87);
|
||||
check32(res32, 0xffffff87);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sb_lub(&n.b[0], &n.ub[0], 0x87);
|
||||
check32(res32, 0x00000087);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sb_lh(&n.b[0], &n.h[0], 0x87);
|
||||
check32(res32, 0xffffff87);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sb_luh(&n.b[0], &n.uh[0], 0x87);
|
||||
check32(res32, 0x0000ff87);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sb_lw(&n.b[0], &n.w[0], 0x87);
|
||||
check32(res32, 0xffffff87);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res64 = mem_noshuf_sb_ld(&n.b[0], &n.d[0], 0x87);
|
||||
check64(res64, 0xffffffffffffff87LL);
|
||||
|
||||
/*
|
||||
* Store half combinations
|
||||
*/
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sh_lb(&n.h[0], &n.b[0], 0x8787);
|
||||
check32(res32, 0xffffff87);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sh_lub(&n.h[0], &n.ub[1], 0x8f87);
|
||||
check32(res32, 0x0000008f);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sh_lh(&n.h[0], &n.h[0], 0x8a87);
|
||||
check32(res32, 0xffff8a87);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sh_luh(&n.h[0], &n.uh[0], 0x8a87);
|
||||
check32(res32, 0x8a87);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sh_lw(&n.h[1], &n.w[0], 0x8a87);
|
||||
check32(res32, 0x8a87ffff);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res64 = mem_noshuf_sh_ld(&n.h[1], &n.d[0], 0x8a87);
|
||||
check64(res64, 0xffffffff8a87ffffLL);
|
||||
|
||||
/*
|
||||
* Store word combinations
|
||||
*/
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sw_lb(&n.w[0], &n.b[0], 0x12345687);
|
||||
check32(res32, 0xffffff87);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sw_lub(&n.w[0], &n.ub[0], 0x12345687);
|
||||
check32(res32, 0x00000087);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sw_lh(&n.w[0], &n.h[0], 0x1234f678);
|
||||
check32(res32, 0xfffff678);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sw_luh(&n.w[0], &n.uh[0], 0x12345678);
|
||||
check32(res32, 0x00005678);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sw_lw(&n.w[0], &n.w[0], 0x12345678);
|
||||
check32(res32, 0x12345678);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res64 = mem_noshuf_sw_ld(&n.w[0], &n.d[0], 0x12345678);
|
||||
check64(res64, 0xffffffff12345678LL);
|
||||
|
||||
/*
|
||||
* Store double combinations
|
||||
*/
|
||||
n.d[0] = ~0LL;
|
||||
res32 = mem_noshuf_sd_lb(&n.d[0], &n.b[1], 0x123456789abcdef0);
|
||||
check32(res32, 0xffffffde);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res32 = mem_noshuf_sd_lub(&n.d[0], &n.ub[1], 0x123456789abcdef0);
|
||||
check32(res32, 0x000000de);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res32 = mem_noshuf_sd_lh(&n.d[0], &n.h[1], 0x123456789abcdef0);
|
||||
check32(res32, 0xffff9abc);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res32 = mem_noshuf_sd_luh(&n.d[0], &n.uh[1], 0x123456789abcdef0);
|
||||
check32(res32, 0x00009abc);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res32 = mem_noshuf_sd_lw(&n.d[0], &n.w[1], 0x123456789abcdef0);
|
||||
check32(res32, 0x12345678);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res64 = mem_noshuf_sd_ld(&n.d[0], &n.d[0], 0x123456789abcdef0);
|
||||
check64(res64, 0x123456789abcdef0LL);
|
||||
|
||||
/*
|
||||
* Predicated word stores
|
||||
*/
|
||||
n.w[0] = ~0;
|
||||
res32 = cancel_sw_lb(0, &n.w[0], &n.b[0], 0x12345678);
|
||||
check32(res32, 0xffffffff);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = cancel_sw_lb(1, &n.w[0], &n.b[0], 0x12345687);
|
||||
check32(res32, 0xffffff87);
|
||||
|
||||
/*
|
||||
* Predicated double stores
|
||||
*/
|
||||
n.d[0] = ~0LL;
|
||||
res64 = cancel_sw_ld(0, &n.w[0], &n.d[0], 0x12345678);
|
||||
check64(res64, 0xffffffffffffffffLL);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res64 = cancel_sw_ld(1, &n.w[0], &n.d[0], 0x12345678);
|
||||
check64(res64, 0xffffffff12345678LL);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res64 = cancel_sw_ld(0, &n.w[1], &n.d[0], 0x12345678);
|
||||
check64(res64, 0xffffffffffffffffLL);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res64 = cancel_sw_ld(1, &n.w[1], &n.d[0], 0x12345678);
|
||||
check64(res64, 0x12345678ffffffffLL);
|
||||
|
||||
/*
|
||||
* No overlap tests
|
||||
*/
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sb_lb(&n.b[1], &n.b[0], 0x87);
|
||||
check32(res32, 0xffffffff);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sb_lb(&n.b[0], &n.b[1], 0x87);
|
||||
check32(res32, 0xffffffff);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sh_lh(&n.h[1], &n.h[0], 0x8787);
|
||||
check32(res32, 0xffffffff);
|
||||
|
||||
n.w[0] = ~0;
|
||||
res32 = mem_noshuf_sh_lh(&n.h[0], &n.h[1], 0x8787);
|
||||
check32(res32, 0xffffffff);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res32 = mem_noshuf_sw_lw(&n.w[0], &n.w[1], 0x12345678);
|
||||
check32(res32, 0xffffffff);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
res32 = mem_noshuf_sw_lw(&n.w[1], &n.w[0], 0x12345678);
|
||||
check32(res32, 0xffffffff);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
n.d[1] = ~0LL;
|
||||
res64 = mem_noshuf_sd_ld(&n.d[1], &n.d[0], 0x123456789abcdef0LL);
|
||||
check64(res64, 0xffffffffffffffffLL);
|
||||
|
||||
n.d[0] = ~0LL;
|
||||
n.d[1] = ~0LL;
|
||||
res64 = mem_noshuf_sd_ld(&n.d[0], &n.d[1], 0x123456789abcdef0LL);
|
||||
check64(res64, 0xffffffffffffffffLL);
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user