* [PATCH RISU v2 0/8] ELF and Sparc64 support
@ 2024-05-22 3:44 Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 1/8] risu: Allow use of ELF test files Richard Henderson
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: Richard Henderson @ 2024-05-22 3:44 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, mark.cave-ayland
Let risu accept elf test files, adjusted from v1.
Adjust risugen to invoke the assembler and linker,
with a cross-compiler prefix if needed.
Add some sparc64 testing which utilizes this.
r~
Richard Henderson (8):
risu: Allow use of ELF test files
Build elf test cases instead of raw binaries
Introduce host_context_t
risu: Add initial sparc64 support
risugen: Be explicit about print destinations
risugen: Add sparc64 support
sparc64: Add a few logical insns
sparc64: Add VIS1 instructions
Makefile | 22 ++-
risu.h | 16 +-
risu_reginfo_aarch64.h | 2 +
risu_reginfo_arm.h | 2 +
risu_reginfo_i386.h | 2 +
risu_reginfo_loongarch64.h | 3 +
risu_reginfo_m68k.h | 2 +
risu_reginfo_ppc64.h | 2 +
risu_reginfo_s390x.h | 2 +
risu_reginfo_sparc64.h | 36 ++++
risu.c | 59 +++++-
risu_aarch64.c | 6 +-
risu_arm.c | 7 +-
risu_i386.c | 7 +-
risu_loongarch64.c | 6 +-
risu_m68k.c | 6 +-
risu_ppc64.c | 6 +-
risu_reginfo_loongarch64.c | 3 +-
risu_reginfo_sparc64.c | 186 ++++++++++++++++++
risu_s390x.c | 5 +-
risu_sparc64.c | 52 +++++
configure | 2 +
risugen | 10 +-
risugen_common.pm | 68 ++++++-
risugen_sparc64.pm | 385 +++++++++++++++++++++++++++++++++++++
sparc64.risu | 121 ++++++++++++
test.ld | 12 ++
test_aarch64.s | 4 +-
test_arm.s | 16 +-
test_i386.S | 4 +-
test_sparc64.s | 137 +++++++++++++
31 files changed, 1119 insertions(+), 72 deletions(-)
create mode 100644 risu_reginfo_sparc64.h
create mode 100644 risu_reginfo_sparc64.c
create mode 100644 risu_sparc64.c
create mode 100644 risugen_sparc64.pm
create mode 100644 sparc64.risu
create mode 100644 test.ld
create mode 100644 test_sparc64.s
--
2.34.1
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RISU v2 1/8] risu: Allow use of ELF test files
2024-05-22 3:44 [PATCH RISU v2 0/8] ELF and Sparc64 support Richard Henderson
@ 2024-05-22 3:44 ` Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 2/8] Build elf test cases instead of raw binaries Richard Henderson
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2024-05-22 3:44 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, mark.cave-ayland
By using elf files, we make it easier to disassemble
the test file, to match comparison failures to code.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
risu.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 52 insertions(+), 5 deletions(-)
diff --git a/risu.c b/risu.c
index c28b4a5..c9c3a38 100644
--- a/risu.c
+++ b/risu.c
@@ -24,6 +24,15 @@
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
+#include <elf.h>
+
+/* TODO: Improve configure. */
+#ifdef __linux__
+#include <endian.h>
+#define HOST_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
+#else
+#error Need HOST_BIG_ENDIAN
+#endif
#include "config.h"
#include "risu.h"
@@ -346,8 +355,11 @@ static void load_image(const char *imgfile)
{
/* Load image file into memory as executable */
struct stat st;
+ void *addr;
+ int fd;
+
fprintf(stderr, "loading test image %s...\n", imgfile);
- int fd = open(imgfile, O_RDONLY);
+ fd = open(imgfile, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "failed to open image file %s\n", imgfile);
exit(EXIT_FAILURE);
@@ -356,20 +368,55 @@ static void load_image(const char *imgfile)
perror("fstat");
exit(EXIT_FAILURE);
}
- size_t len = st.st_size;
- void *addr;
/* Map writable because we include the memory area for store
* testing in the image.
*/
- addr = mmap(0, len, PROT_READ | PROT_WRITE | PROT_EXEC,
+ addr = mmap(0, st.st_size, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE, fd, 0);
if (addr == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
close(fd);
- image_start = addr;
+
+ if (memcmp(addr, ELFMAG, SELFMAG) == 0) {
+ union {
+ unsigned char ident[EI_NIDENT];
+ Elf32_Ehdr h32;
+ Elf64_Ehdr h64;
+ } *e = addr;
+ size_t entry;
+
+ /*
+ * TODO: More complete parsing of ELF file, verify assumtion, namely:
+ * Single PT_LOAD covering the ELF header, code and data.
+ * For now, simply update image_start from the elf header.
+ */
+ if (e->ident[EI_DATA] !=
+ (HOST_BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB)) {
+ fprintf(stderr, "%s: Endian mismatch: EI_DATA = %x\n",
+ imgfile, e->ident[EI_DATA]);
+ exit(1);
+ }
+
+ switch (e->ident[EI_CLASS]) {
+ case ELFCLASS32:
+ entry = e->h32.e_entry;
+ break;
+ case ELFCLASS64:
+ entry = e->h64.e_entry;
+ break;
+ default:
+ fprintf(stderr, "%s: Bad elf header: EI_CLASS = %x\n",
+ imgfile, e->ident[EI_CLASS]);
+ exit(1);
+ }
+ image_start = addr + entry;
+ } else {
+ /* Raw binary image. */
+ image_start = addr;
+ }
image_start_address = (uintptr_t) addr;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RISU v2 2/8] Build elf test cases instead of raw binaries
2024-05-22 3:44 [PATCH RISU v2 0/8] ELF and Sparc64 support Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 1/8] risu: Allow use of ELF test files Richard Henderson
@ 2024-05-22 3:44 ` Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 3/8] Introduce host_context_t Richard Henderson
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2024-05-22 3:44 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, mark.cave-ayland, Philippe Mathieu-Daudé
For test_arch64.s and test_arm.s, use '.inst' so that the risu
control insns are marked as instructions for disassembly.
For test_i386.S, split the data to be loaded into the data section;
fix an error aligning the data: 16 not 2**16.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
Makefile | 19 ++++++++++---------
test.ld | 12 ++++++++++++
test_aarch64.s | 4 ++--
test_arm.s | 16 +++++++++++-----
test_i386.S | 4 +++-
5 files changed, 38 insertions(+), 17 deletions(-)
create mode 100644 test.ld
diff --git a/Makefile b/Makefile
index ad7f879..2bd08aa 100644
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,8 @@ ALL_CFLAGS = -Wall -D_GNU_SOURCE -DARCH=$(ARCH) -U$(ARCH) $(BUILD_INC) $(CFLAGS)
PROG=risu
SRCS=risu.c comms.c risu_$(ARCH).c risu_reginfo_$(ARCH).c
HDRS=risu.h risu_reginfo_$(ARCH).h
-BINS=test_$(ARCH).bin
+BINO=test_$(ARCH).o
+BINE=test_$(ARCH).elf
# For dumping test patterns
RISU_BINS=$(wildcard *.risu.bin)
@@ -30,7 +31,7 @@ RISU_ASMS=$(patsubst %.bin,%.asm,$(RISU_BINS))
OBJS=$(SRCS:.c=.o)
-all: $(PROG) $(BINS)
+all: $(PROG) $(BINE)
dump: $(RISU_ASMS)
@@ -43,17 +44,17 @@ $(PROG): $(OBJS)
%.o: %.c $(HDRS)
$(CC) $(CPPFLAGS) $(ALL_CFLAGS) -o $@ -c $<
-%_$(ARCH).bin: %_$(ARCH).elf
- $(OBJCOPY) -O binary $< $@
+%_$(ARCH).o: %_$(ARCH).s
+ $(CC) -o $@ -c $<
-%_$(ARCH).elf: %_$(ARCH).s
- $(AS) -o $@ $<
-
-%_$(ARCH).elf: %_$(ARCH).S
+%_$(ARCH).o: %_$(ARCH).S
$(CC) $(CPPFLAGS) -o $@ -c $<
+%_$(ARCH).elf: test.ld %_$(ARCH).o
+ $(LD) -o $@ -T $^
+
clean:
- rm -f $(PROG) $(OBJS) $(BINS)
+ rm -f $(PROG) $(OBJS) $(BINO) $(BINE)
distclean: clean
rm -f config.h Makefile.in
diff --git a/test.ld b/test.ld
new file mode 100644
index 0000000..eb0a76a
--- /dev/null
+++ b/test.ld
@@ -0,0 +1,12 @@
+ENTRY(start)
+
+PHDRS {
+ text PT_LOAD FILEHDR PHDRS;
+}
+
+SECTIONS {
+ . = SIZEOF_HEADERS;
+ PROVIDE(start = .);
+ .text : { *(.text) } :text
+ .data : { *(.data) } :text
+}
diff --git a/test_aarch64.s b/test_aarch64.s
index f75d588..88902c6 100644
--- a/test_aarch64.s
+++ b/test_aarch64.s
@@ -80,6 +80,6 @@ fmov d31, #31.0
/* do compare.
* The manual says instr with bits (28,27) == 0 0 are UNALLOCATED
*/
-.int 0x00005af0
+.inst 0x00005af0
/* exit test */
-.int 0x00005af1
+.inst 0x00005af1
diff --git a/test_arm.s b/test_arm.s
index 49552f2..62582e7 100644
--- a/test_arm.s
+++ b/test_arm.s
@@ -9,20 +9,26 @@
* Peter Maydell (Linaro) - initial implementation
*******************************************************************************/
+.text
+
/* magic instruction to force ARM mode whether we were in ARM or Thumb before */
-.int 0xe0004778
+.inst 0xe0004778
+
/* Initialise the gp regs */
add r0, pc, #4
ldmia r0, {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,r14}
-b next
+b 1f
+
.int 0,1,2,3,4,5,6,7,8,9,10,11,12,14
-next:
+
+1:
msr CPSR_fs, #0
+
/* do compare.
* The space 0xE7F___F_ is guaranteed to always UNDEF
* and not to be allocated for insns in future architecture
* revisions.
*/
-.int 0xe7fe5af0
+.inst 0xe7fe5af0
/* exit test */
-.int 0xe7fe5af1
+.inst 0xe7fe5af1
diff --git a/test_i386.S b/test_i386.S
index 05344d7..2e2b090 100644
--- a/test_i386.S
+++ b/test_i386.S
@@ -13,6 +13,7 @@
/* Initialise the registers to avoid spurious mismatches */
+.text
#ifdef __x86_64__
#define BASE %rax
lea 2f(%rip), BASE
@@ -71,7 +72,8 @@
/* exit test */
ud1 %ecx, %eax
- .p2align 16
+.data
+ .balign 16
2:
.set i, 0
.rept 256
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RISU v2 3/8] Introduce host_context_t
2024-05-22 3:44 [PATCH RISU v2 0/8] ELF and Sparc64 support Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 1/8] risu: Allow use of ELF test files Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 2/8] Build elf test cases instead of raw binaries Richard Henderson
@ 2024-05-22 3:44 ` Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 4/8] risu: Add initial sparc64 support Richard Henderson
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2024-05-22 3:44 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, mark.cave-ayland
Most hosts pass ucontext_t as the third parameter of signal handlers.
In one existing usage, loongarch64 is using the kernel's
struct ucontext instead of libc's ucontext_t. This is probably a
simple mistake that could be fixed, but the structure member names
differ, so the change would not be completely mechanical.
However, due to a sequence of historical mistakes, sparc64 linux
does not pass any kind of ucontext_t to the signal handler, but
uses struct sigcontext instead.
Prepare for that by adding a new indirection typedef.
This allows us to clean up existing usage with void*.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
risu.h | 16 ++++++++--------
risu_reginfo_aarch64.h | 2 ++
risu_reginfo_arm.h | 2 ++
risu_reginfo_i386.h | 2 ++
risu_reginfo_loongarch64.h | 3 +++
risu_reginfo_m68k.h | 2 ++
risu_reginfo_ppc64.h | 2 ++
risu_reginfo_s390x.h | 2 ++
risu_aarch64.c | 6 ++----
risu_arm.c | 7 ++-----
risu_i386.c | 7 ++-----
risu_loongarch64.c | 6 ++----
risu_m68k.c | 6 ++----
risu_ppc64.c | 6 ++----
risu_reginfo_loongarch64.c | 3 +--
risu_s390x.c | 5 ++---
16 files changed, 38 insertions(+), 39 deletions(-)
diff --git a/risu.h b/risu.h
index 4203178..0ac7d1e 100644
--- a/risu.h
+++ b/risu.h
@@ -68,7 +68,7 @@ typedef enum {
/* This is the data structure we pass over the socket for OP_COMPARE
* and OP_TESTEND. It is a simplified and reduced subset of what can
- * be obtained with a ucontext_t*, and is architecture specific
+ * be obtained with a ucontext_t, and is architecture specific
* (defined in risu_reginfo_*.h).
*/
struct reginfo;
@@ -93,14 +93,14 @@ void send_response_byte(int sock, int resp);
/* Interface provided by CPU-specific code: */
-/* Move the PC past this faulting insn by adjusting ucontext. */
-void advance_pc(void *uc);
+/* Move the PC past this faulting insn by adjusting signal context. */
+void advance_pc(host_context_t *hc);
-/* Set the parameter register in a ucontext_t to the specified value.
+/*
+ * Set the parameter register in a host_context_t to the specified value.
* (32-bit targets can ignore high 32 bits.)
- * vuc is a ucontext_t* cast to void*.
*/
-void set_ucontext_paramreg(void *vuc, uint64_t value);
+void set_ucontext_paramreg(host_context_t *hc, uint64_t value);
/* Return the value of the parameter register from a reginfo. */
uint64_t get_reginfo_paramreg(struct reginfo *ri);
@@ -114,8 +114,8 @@ RisuOp get_risuop(struct reginfo *ri);
/* Return the PC from a reginfo */
uintptr_t get_pc(struct reginfo *ri);
-/* initialize structure from a ucontext */
-void reginfo_init(struct reginfo *ri, ucontext_t *uc, void *siaddr);
+/* initialize structure from a host_context_t. */
+void reginfo_init(struct reginfo *ri, host_context_t *hc, void *siaddr);
/* return true if structs are equal, false otherwise. */
bool reginfo_is_eq(struct reginfo *r1, struct reginfo *r2);
diff --git a/risu_reginfo_aarch64.h b/risu_reginfo_aarch64.h
index 097b7ad..bc3a661 100644
--- a/risu_reginfo_aarch64.h
+++ b/risu_reginfo_aarch64.h
@@ -15,6 +15,8 @@
#include <signal.h>
+typedef ucontext_t host_context_t;
+
/* The kernel headers set this based on future arch extensions.
The current arch maximum is 16. Save space below. */
#undef SVE_VQ_MAX
diff --git a/risu_reginfo_arm.h b/risu_reginfo_arm.h
index 60754a9..1937e46 100644
--- a/risu_reginfo_arm.h
+++ b/risu_reginfo_arm.h
@@ -13,6 +13,8 @@
#ifndef RISU_REGINFO_ARM_H
#define RISU_REGINFO_ARM_H
+typedef ucontext_t host_context_t;
+
struct reginfo {
uint64_t fpregs[32];
uint32_t faulting_insn;
diff --git a/risu_reginfo_i386.h b/risu_reginfo_i386.h
index b468f79..abbfbe1 100644
--- a/risu_reginfo_i386.h
+++ b/risu_reginfo_i386.h
@@ -12,6 +12,8 @@
#ifndef RISU_REGINFO_I386_H
#define RISU_REGINFO_I386_H
+typedef ucontext_t host_context_t;
+
struct avx512_reg {
uint64_t q[8];
};
diff --git a/risu_reginfo_loongarch64.h b/risu_reginfo_loongarch64.h
index 892b477..6c85951 100644
--- a/risu_reginfo_loongarch64.h
+++ b/risu_reginfo_loongarch64.h
@@ -12,6 +12,9 @@
#ifndef RISU_REGINFO_LOONGARCH64_H
#define RISU_REGINFO_LOONGARCH64_H
+/* From kernel <asm/ucontext.h> not libc <ucontext.h>. */
+typedef struct ucontext host_context_t;
+
struct reginfo {
uint64_t regs[32];
uint64_t pc;
diff --git a/risu_reginfo_m68k.h b/risu_reginfo_m68k.h
index c1c9fe6..233f901 100644
--- a/risu_reginfo_m68k.h
+++ b/risu_reginfo_m68k.h
@@ -9,6 +9,8 @@
#ifndef RISU_REGINFO_M68K_H
#define RISU_REGINFO_M68K_H
+typedef ucontext_t host_context_t;
+
struct reginfo {
uint32_t faulting_insn;
uint32_t pc;
diff --git a/risu_reginfo_ppc64.h b/risu_reginfo_ppc64.h
index 4b1d8bd..424fd02 100644
--- a/risu_reginfo_ppc64.h
+++ b/risu_reginfo_ppc64.h
@@ -14,6 +14,8 @@
#ifndef RISU_REGINFO_PPC64LE_H
#define RISU_REGINFO_PPC64LE_H
+typedef ucontext_t host_context_t;
+
struct reginfo {
uint32_t faulting_insn;
uint32_t prev_insn;
diff --git a/risu_reginfo_s390x.h b/risu_reginfo_s390x.h
index c65fff7..5126fd5 100644
--- a/risu_reginfo_s390x.h
+++ b/risu_reginfo_s390x.h
@@ -12,6 +12,8 @@
#ifndef RISU_REGINFO_S390X_H
#define RISU_REGINFO_S390X_H
+typedef ucontext_t host_context_t;
+
struct reginfo {
uint64_t psw_mask;
uint64_t pc_offset;
diff --git a/risu_aarch64.c b/risu_aarch64.c
index f8a8412..af94539 100644
--- a/risu_aarch64.c
+++ b/risu_aarch64.c
@@ -12,15 +12,13 @@
#include "risu.h"
-void advance_pc(void *vuc)
+void advance_pc(ucontext_t *uc)
{
- ucontext_t *uc = vuc;
uc->uc_mcontext.pc += 4;
}
-void set_ucontext_paramreg(void *vuc, uint64_t value)
+void set_ucontext_paramreg(ucontext_t *uc, uint64_t value)
{
- ucontext_t *uc = vuc;
uc->uc_mcontext.regs[0] = value;
}
diff --git a/risu_arm.c b/risu_arm.c
index a20bf73..0e72fba 100644
--- a/risu_arm.c
+++ b/risu_arm.c
@@ -38,16 +38,13 @@ int insnsize(ucontext_t *uc)
return 4;
}
-void advance_pc(void *vuc)
+void advance_pc(ucontext_t *uc)
{
- ucontext_t *uc = vuc;
uc->uc_mcontext.arm_pc += insnsize(uc);
}
-
-void set_ucontext_paramreg(void *vuc, uint64_t value)
+void set_ucontext_paramreg(ucontext_t *uc, uint64_t value)
{
- ucontext_t *uc = vuc;
uc->uc_mcontext.arm_r0 = value;
}
diff --git a/risu_i386.c b/risu_i386.c
index 127e816..5d3b8aa 100644
--- a/risu_i386.c
+++ b/risu_i386.c
@@ -16,10 +16,8 @@
#include "risu.h"
#include "risu_reginfo_i386.h"
-void advance_pc(void *vuc)
+void advance_pc(ucontext_t *uc)
{
- ucontext_t *uc = (ucontext_t *) vuc;
-
/*
* We assume that this is UD1 as per get_risuop below.
* This would need tweaking if we want to test expected undefs.
@@ -27,9 +25,8 @@ void advance_pc(void *vuc)
uc->uc_mcontext.gregs[REG_E(IP)] += 3;
}
-void set_ucontext_paramreg(void *vuc, uint64_t value)
+void set_ucontext_paramreg(ucontext_t *uc, uint64_t value)
{
- ucontext_t *uc = (ucontext_t *) vuc;
uc->uc_mcontext.gregs[REG_E(AX)] = value;
}
diff --git a/risu_loongarch64.c b/risu_loongarch64.c
index b6c59cf..921a031 100644
--- a/risu_loongarch64.c
+++ b/risu_loongarch64.c
@@ -15,15 +15,13 @@
#include "risu.h"
-void advance_pc(void *vuc)
+void advance_pc(host_context_t *uc)
{
- struct ucontext *uc = vuc;
uc->uc_mcontext.sc_pc += 4;
}
-void set_ucontext_paramreg(void *vuc, uint64_t value)
+void set_ucontext_paramreg(host_context_t *uc, uint64_t value)
{
- struct ucontext *uc = vuc;
uc->uc_mcontext.sc_regs[4] = value;
}
diff --git a/risu_m68k.c b/risu_m68k.c
index acdd57a..bd6bece 100644
--- a/risu_m68k.c
+++ b/risu_m68k.c
@@ -8,15 +8,13 @@
#include "risu.h"
-void advance_pc(void *vuc)
+void advance_pc(ucontext_t *uc)
{
- ucontext_t *uc = (ucontext_t *) vuc;
uc->uc_mcontext.gregs[R_PC] += 4;
}
-void set_ucontext_paramreg(void *vuc, uint64_t value)
+void set_ucontext_paramreg(ucontext_t *uc, uint64_t value)
{
- ucontext_t *uc = vuc;
uc->uc_mcontext.gregs[R_A0] = value;
}
diff --git a/risu_ppc64.c b/risu_ppc64.c
index 62cf6aa..06cb8a8 100644
--- a/risu_ppc64.c
+++ b/risu_ppc64.c
@@ -14,15 +14,13 @@
#include "risu.h"
#include <sys/user.h>
-void advance_pc(void *vuc)
+void advance_pc(ucontext_t *uc)
{
- ucontext_t *uc = (ucontext_t *) vuc;
uc->uc_mcontext.regs->nip += 4;
}
-void set_ucontext_paramreg(void *vuc, uint64_t value)
+void set_ucontext_paramreg(ucontext_t *uc, uint64_t value)
{
- ucontext_t *uc = vuc;
uc->uc_mcontext.gp_regs[0] = value;
}
diff --git a/risu_reginfo_loongarch64.c b/risu_reginfo_loongarch64.c
index 6150a40..0719e8b 100644
--- a/risu_reginfo_loongarch64.c
+++ b/risu_reginfo_loongarch64.c
@@ -97,10 +97,9 @@ static int parse_extcontext(struct sigcontext *sc, struct extctx_layout *extctx)
}
/* reginfo_init: initialize with a ucontext */
-void reginfo_init(struct reginfo *ri, ucontext_t *context, void *siaddr)
+void reginfo_init(struct reginfo *ri, host_context_t *uc, void *siaddr)
{
int i;
- struct ucontext *uc = (struct ucontext *)context;
struct extctx_layout extctx;
memset(&extctx, 0, sizeof(struct extctx_layout));
diff --git a/risu_s390x.c b/risu_s390x.c
index cf9c72c..906766e 100644
--- a/risu_s390x.c
+++ b/risu_s390x.c
@@ -13,7 +13,7 @@
#include "risu.h"
-void advance_pc(void *vuc)
+void advance_pc(ucontext_t *uc)
{
/*
* Note: The PSW address already points to the next instruction
@@ -21,9 +21,8 @@ void advance_pc(void *vuc)
*/
}
-void set_ucontext_paramreg(void *vuc, uint64_t value)
+void set_ucontext_paramreg(ucontext_t *uc, uint64_t value)
{
- ucontext_t *uc = vuc;
uc->uc_mcontext.gregs[0] = value;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RISU v2 4/8] risu: Add initial sparc64 support
2024-05-22 3:44 [PATCH RISU v2 0/8] ELF and Sparc64 support Richard Henderson
` (2 preceding siblings ...)
2024-05-22 3:44 ` [PATCH RISU v2 3/8] Introduce host_context_t Richard Henderson
@ 2024-05-22 3:44 ` Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 5/8] risugen: Be explicit about print destinations Richard Henderson
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2024-05-22 3:44 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, mark.cave-ayland
Best effort for both Linux and Solaris as a host, since the
gcc compile farm has more working Sparc Solaris hosts than
Sparc Linux hosts.
What's missing is a value for %gsr from Solaris.
This could complicate comparison of VIS instructions.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
Makefile | 3 +
risu_reginfo_sparc64.h | 36 ++++++++
risu.c | 2 +
risu_reginfo_sparc64.c | 186 +++++++++++++++++++++++++++++++++++++++++
risu_sparc64.c | 52 ++++++++++++
configure | 2 +
test_sparc64.s | 137 ++++++++++++++++++++++++++++++
7 files changed, 418 insertions(+)
create mode 100644 risu_reginfo_sparc64.h
create mode 100644 risu_reginfo_sparc64.c
create mode 100644 risu_sparc64.c
create mode 100644 test_sparc64.s
diff --git a/Makefile b/Makefile
index 2bd08aa..f503499 100644
--- a/Makefile
+++ b/Makefile
@@ -53,6 +53,9 @@ $(PROG): $(OBJS)
%_$(ARCH).elf: test.ld %_$(ARCH).o
$(LD) -o $@ -T $^
+test_sparc64.o: test_sparc64.s
+ $(AS) -Av9a -o $@ $<
+
clean:
rm -f $(PROG) $(OBJS) $(BINO) $(BINE)
diff --git a/risu_reginfo_sparc64.h b/risu_reginfo_sparc64.h
new file mode 100644
index 0000000..b1d5341
--- /dev/null
+++ b/risu_reginfo_sparc64.h
@@ -0,0 +1,36 @@
+/******************************************************************************
+ * Copyright (c) 2024 Linaro Limited
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *****************************************************************************/
+
+#ifndef RISU_REGINFO_SPARC64_H
+#define RISU_REGINFO_SPARC64_H
+
+#ifdef __linux__
+typedef struct sigcontext host_context_t;
+#else
+typedef ucontext_t host_context_t;
+#endif
+
+struct reginfo {
+ uint32_t faulting_insn;
+ uint32_t ccr;
+
+ uint64_t pc;
+ uint64_t npc;
+
+ uint64_t g[8];
+ uint64_t o[8];
+ uint64_t l[8];
+ uint64_t i[8];
+
+ uint64_t y;
+ uint64_t fsr;
+
+ uint64_t fregs[32];
+};
+
+#endif /* RISU_REGINFO_SPARC64_H */
diff --git a/risu.c b/risu.c
index c9c3a38..422b32e 100644
--- a/risu.c
+++ b/risu.c
@@ -30,6 +30,8 @@
#ifdef __linux__
#include <endian.h>
#define HOST_BIG_ENDIAN (__BYTE_ORDER == __BIG_ENDIAN)
+#elif defined(__sparc__)
+#define HOST_BIG_ENDIAN 1
#else
#error Need HOST_BIG_ENDIAN
#endif
diff --git a/risu_reginfo_sparc64.c b/risu_reginfo_sparc64.c
new file mode 100644
index 0000000..be002e3
--- /dev/null
+++ b/risu_reginfo_sparc64.c
@@ -0,0 +1,186 @@
+/******************************************************************************
+ * Copyright (c) 2024 Linaro Limited
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <ucontext.h>
+#include <string.h>
+#include <signal.h>
+#include <stdlib.h>
+
+#include "risu.h"
+#include "risu_reginfo_sparc64.h"
+
+#define STACK_BIAS 2047
+
+const struct option * const arch_long_opts;
+const char * const arch_extra_help;
+
+void process_arch_opt(int opt, const char *arg)
+{
+ abort();
+}
+
+void arch_init(void)
+{
+}
+
+int reginfo_size(struct reginfo *ri)
+{
+ return sizeof(*ri);
+}
+
+/* reginfo_init: initialize with a ucontext */
+void reginfo_init(struct reginfo *ri, host_context_t *hc, void *siaddr)
+{
+ memset(ri, 0, sizeof(*ri));
+
+#ifdef __linux__
+ ri->pc = hc->sigc_regs.tpc;
+ ri->npc = hc->sigc_regs.tnpc;
+ ri->ccr = (hc->sigc_regs.tstate >> 32) & 0xff;
+ ri->y = hc->sigc_regs.y;
+
+ /* g + o */
+ memcpy(&ri->g, hc->sigc_regs.u_regs, 16 * 8);
+ /* l + i are just before sc */
+ memcpy(&ri->l, (void *)hc - 8 * 8 * 3, 16 * 8);
+
+ if (hc->sigc_fpu_save) {
+ ri->fsr = hc->sigc_fpu_save->si_fsr;
+ /* TODO: ri->gsr = hc->sigc_fpu_save->si_gsr; */
+ memcpy(ri->fregs, hc->sigc_fpu_save->si_float_regs, 32 * 8);
+ }
+#elif defined(__sun__)
+ ri->pc = hc->uc_mcontext.gregs[REG_PC];
+ ri->npc = hc->uc_mcontext.gregs[REG_nPC];
+ ri->ccr = hc->uc_mcontext.gregs[REG_CCR];
+
+ /* G and O are in the signal frame. */
+ memcpy(&ri->g[1], &hc->uc_mcontext.gregs[REG_G1], 7 * sizeof(greg_t));
+ memcpy(&ri->o[0], &hc->uc_mcontext.gregs[REG_O0], 8 * sizeof(greg_t));
+
+ /* L and I are flushed to the regular stack frame. */
+ memcpy(&ri->l[0], (void *)(ri->o[6] + STACK_BIAS), 16 * sizeof(greg_t));
+
+ ri->y = hc->uc_mcontext.gregs[REG_Y];
+ ri->fsr = hc->uc_mcontext.fpregs.fpu_fsr;
+ /* ??? Despite %gsr being asr19, uc->mc.asrs[19-16] is not populated. */
+
+ memcpy(&ri->fregs[0], &hc->uc_mcontext.fpregs.fpu_fr,
+ 32 * sizeof(uint64_t));
+#endif
+
+ ri->g[7] = 0xdeadbeefdeadbeeful; /* tp */
+ ri->o[6] = 0xdeadbeefdeadbeeful; /* sp */
+ ri->i[6] = 0xdeadbeefdeadbeeful; /* fp */
+
+ ri->faulting_insn = *(uint32_t *)ri->pc;
+
+ ri->pc -= image_start_address;
+ ri->npc -= image_start_address;
+}
+
+/* reginfo_is_eq: compare the reginfo structs, returns nonzero if equal */
+bool reginfo_is_eq(struct reginfo *r1, struct reginfo *r2)
+{
+ return memcmp(r1, r2, reginfo_size(r1)) == 0;
+}
+
+/* reginfo_dump: print state to a stream, returns nonzero on success */
+void reginfo_dump(struct reginfo *ri, FILE * f)
+{
+ int i;
+
+ fprintf(f, " insn : %08x\n", ri->faulting_insn);
+ fprintf(f, " ccr : %02x\n", ri->ccr);
+ fprintf(f, " pc : %016" PRIx64 "\n", ri->pc);
+ fprintf(f, " npc : %016" PRIx64 "\n", ri->npc);
+
+ for (i = 1; i < 8; i++) {
+ fprintf(f, " G%d : %016" PRIx64 "\n", i, ri->g[i]);
+ }
+ for (i = 0; i < 8; i++) {
+ fprintf(f, " O%d : %016" PRIx64 "\n", i, ri->o[i]);
+ }
+ for (i = 0; i < 8; i++) {
+ fprintf(f, " L%d : %016" PRIx64 "\n", i, ri->l[i]);
+ }
+ for (i = 0; i < 8; i++) {
+ fprintf(f, " I%d : %016" PRIx64 "\n", i, ri->i[i]);
+ }
+
+ fprintf(f, " y : %016" PRIx64 "\n", ri->y);
+ fprintf(f, " fsr : %016" PRIx64 "\n", ri->fsr);
+
+ for (i = 0; i < 32; i++) {
+ fprintf(f, " F%-2d : %016" PRIx64 "\n", i * 2, ri->fregs[i]);
+ }
+}
+
+/* reginfo_dump_mismatch: print mismatch details to a stream, ret nonzero=ok */
+void reginfo_dump_mismatch(struct reginfo *m, struct reginfo *a, FILE * f)
+{
+ int i;
+
+ if (m->faulting_insn != a->faulting_insn) {
+ fprintf(f, " insn : %08x vs %08x\n",
+ m->faulting_insn, a->faulting_insn);
+ }
+ if (m->ccr != a->ccr) {
+ fprintf(f, " ccr : %02x vs %02x\n", m->ccr, a->ccr);
+ }
+ if (m->pc != a->pc) {
+ fprintf(f, " pc : %016" PRIx64 " vs %016" PRIx64 "\n",
+ m->pc, a->pc);
+ }
+ if (m->npc != a->npc) {
+ fprintf(f, " npc : %016" PRIx64 " vs %016" PRIx64 "\n",
+ m->npc, a->npc);
+ }
+
+ for (i = 1; i < 8; i++) {
+ if (m->g[i] != a->g[i]) {
+ fprintf(f, " G%d : %016" PRIx64 " vs %016" PRIx64 "\n",
+ i, m->g[i], a->g[i]);
+ }
+ }
+ for (i = 0; i < 8; i++) {
+ if (m->o[i] != a->o[i]) {
+ fprintf(f, " O%d : %016" PRIx64 " vs %016" PRIx64 "\n",
+ i, m->o[i], a->o[i]);
+ }
+ }
+ for (i = 0; i < 8; i++) {
+ if (m->l[i] != a->l[i]) {
+ fprintf(f, " L%d : %016" PRIx64 " vs %016" PRIx64 "\n",
+ i, m->l[i], a->l[i]);
+ }
+ }
+ for (i = 0; i < 8; i++) {
+ if (m->i[i] != a->i[i]) {
+ fprintf(f, " I%d : %016" PRIx64 " vs %016" PRIx64 "\n",
+ i, m->i[i], a->i[i]);
+ }
+ }
+
+ if (m->y != a->y) {
+ fprintf(f, " y : %016" PRIx64 " vs %016" PRIx64 "\n",
+ m->y, a->y);
+ }
+ if (m->fsr != a->fsr) {
+ fprintf(f, " fsr : %016" PRIx64 " vs %016" PRIx64 "\n",
+ m->fsr, a->fsr);
+ }
+
+ for (i = 0; i < 32; i++) {
+ if (m->fregs[i] != a->fregs[i]) {
+ fprintf(f, " F%-2d : %016" PRIx64 " vs %016" PRIx64 "\n",
+ i * 2, m->fregs[i], a->fregs[i]);
+ }
+ }
+}
diff --git a/risu_sparc64.c b/risu_sparc64.c
new file mode 100644
index 0000000..48b5cfe
--- /dev/null
+++ b/risu_sparc64.c
@@ -0,0 +1,52 @@
+/******************************************************************************
+ * Copyright (c) 2024 Linaro Limited
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *****************************************************************************/
+
+#include <signal.h>
+#include "risu.h"
+
+void advance_pc(host_context_t *hc)
+{
+#ifdef __linux__
+ hc->sigc_regs.tpc = hc->sigc_regs.tnpc;
+ hc->sigc_regs.tnpc += 4;
+#else
+ hc->uc_mcontext.gregs[REG_PC] = hc->uc_mcontext.gregs[REG_nPC];
+ hc->uc_mcontext.gregs[REG_nPC] += 4;
+#endif
+}
+
+void set_ucontext_paramreg(host_context_t *hc, uint64_t value)
+{
+#ifdef __linux__
+ hc->sigc_regs.u_regs[15] = value;
+#else
+ hc->uc_mcontext.gregs[REG_O7] = value;
+#endif
+}
+
+uint64_t get_reginfo_paramreg(struct reginfo *ri)
+{
+ return ri->o[7];
+}
+
+RisuOp get_risuop(struct reginfo *ri)
+{
+ /* Return the risuop we have been asked to do
+ * (or OP_SIGILL if this was a SIGILL for a non-risuop insn)
+ */
+ uint32_t insn = ri->faulting_insn;
+ uint32_t op = insn & 0xf;
+ uint32_t key = insn & ~0xf;
+ uint32_t risukey = 0x000dead0;
+ return (key != risukey) ? OP_SIGILL : op;
+}
+
+uintptr_t get_pc(struct reginfo *ri)
+{
+ return ri->pc;
+}
diff --git a/configure b/configure
index 39275a2..965f338 100755
--- a/configure
+++ b/configure
@@ -62,6 +62,8 @@ guess_arch() {
ARCH="ppc64"
elif check_define __s390x__ ; then
ARCH="s390x"
+ elif check_define __sparc__ && check_define __arch64__ ; then
+ ARCH="sparc64"
else
echo "This cpu is not supported by risu. Try -h. " >&2
exit 1
diff --git a/test_sparc64.s b/test_sparc64.s
new file mode 100644
index 0000000..c131d81
--- /dev/null
+++ b/test_sparc64.s
@@ -0,0 +1,137 @@
+/*****************************************************************************
+ * Copyright (c) 2024 Linaro Limited
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *****************************************************************************/
+
+/* Initialise the fp regs */
+
+ .register %g2, #ignore
+ .register %g3, #ignore
+ .register %g6, #ignore
+
+.text
+ rd %pc, %g1
+ sethi %pc22(.Ldata+4), %g2
+ or %g2, %pc10(.Ldata+8), %g2
+ add %g2, %g1, %g1
+
+ ldd [%g1 + 4 * 0], %f0
+ ldd [%g1 + 4 * 2], %f2
+ ldd [%g1 + 4 * 4], %f4
+ ldd [%g1 + 4 * 6], %f6
+ ldd [%g1 + 4 * 8], %f8
+ ldd [%g1 + 4 * 10], %f10
+ ldd [%g1 + 4 * 12], %f12
+ ldd [%g1 + 4 * 14], %f14
+ ldd [%g1 + 4 * 16], %f16
+ ldd [%g1 + 4 * 18], %f18
+ ldd [%g1 + 4 * 20], %f20
+ ldd [%g1 + 4 * 22], %f22
+ ldd [%g1 + 4 * 24], %f24
+ ldd [%g1 + 4 * 26], %f26
+ ldd [%g1 + 4 * 28], %f28
+ ldd [%g1 + 4 * 30], %f30
+ ldd [%g1 + 4 * 32], %f32
+ ldd [%g1 + 4 * 34], %f34
+ ldd [%g1 + 4 * 36], %f36
+ ldd [%g1 + 4 * 38], %f38
+ ldd [%g1 + 4 * 40], %f40
+ ldd [%g1 + 4 * 42], %f42
+ ldd [%g1 + 4 * 44], %f44
+ ldd [%g1 + 4 * 46], %f46
+ ldd [%g1 + 4 * 48], %f48
+ ldd [%g1 + 4 * 50], %f50
+ ldd [%g1 + 4 * 52], %f52
+ ldd [%g1 + 4 * 54], %f54
+ ldd [%g1 + 4 * 56], %f56
+ ldd [%g1 + 4 * 58], %f58
+ ldd [%g1 + 4 * 60], %f60
+ ldd [%g1 + 4 * 62], %f62
+
+/* Initialize the special regs */
+
+ wr %g0, 0x100, %y
+ wr %g0, 0x200, %gsr
+ cmp %g0, %g0
+
+/* Initialise the gp regs */
+
+ mov 1, %g1
+ mov 2, %g2
+ mov 3, %g3
+ mov 4, %g4
+ mov 5, %g5
+ mov 6, %g6
+ /* g7 is the thread pointer */
+
+ mov 8, %o0
+ mov 9, %o1
+ mov 10, %o2
+ mov 11, %o3
+ mov 12, %o4
+ mov 13, %o5
+ /* o6 is the stack pointer */
+ mov 15, %o7
+
+ mov 16, %l0
+ mov 17, %l1
+ mov 18, %l2
+ mov 19, %l3
+ mov 20, %l4
+ mov 21, %l5
+ mov 22, %l6
+ mov 23, %l7
+
+ mov 24, %i0
+ mov 25, %i1
+ mov 26, %i2
+ mov 27, %i3
+ mov 28, %i4
+ mov 29, %i5
+ /* i6 is the frame pointer */
+ mov 31, %i7
+
+/* Do compare. */
+
+ illtrap 0xdead0
+ illtrap 0xdead1
+
+.data
+ .align 8
+.Ldata:
+ .double 1
+ .double 2
+ .double 3
+ .double 4
+ .double 5
+ .double 6
+ .double 7
+ .double 8
+ .double 9
+ .double 10
+ .double 11
+ .double 12
+ .double 13
+ .double 14
+ .double 15
+ .double 16
+ .double 17
+ .double 18
+ .double 19
+ .double 20
+ .double 21
+ .double 22
+ .double 23
+ .double 24
+ .double 25
+ .double 26
+ .double 27
+ .double 28
+ .double 29
+ .double 30
+ .double 31
+ .double 32
+
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RISU v2 5/8] risugen: Be explicit about print destinations
2024-05-22 3:44 [PATCH RISU v2 0/8] ELF and Sparc64 support Richard Henderson
` (3 preceding siblings ...)
2024-05-22 3:44 ` [PATCH RISU v2 4/8] risu: Add initial sparc64 support Richard Henderson
@ 2024-05-22 3:44 ` Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 6/8] risugen: Add sparc64 support Richard Henderson
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2024-05-22 3:44 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, mark.cave-ayland
Printing directly to STDOUT and STDERR will allow the
print destination to be selected elsewhere.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
risugen_common.pm | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/risugen_common.pm b/risugen_common.pm
index 71ee996..5207c0e 100644
--- a/risugen_common.pm
+++ b/risugen_common.pm
@@ -76,7 +76,7 @@ sub progress_start($$)
($proglen, $progmax) = @_;
$proglen -= 2; # allow for [] chars
$| = 1; # disable buffering so we can see the meter...
- print "[" . " " x $proglen . "]\r";
+ print STDOUT "[" . " " x $proglen . "]\r";
$lastprog = 0;
}
@@ -87,13 +87,13 @@ sub progress_update($)
my $barlen = int($proglen * $done / $progmax);
if ($barlen != $lastprog) {
$lastprog = $barlen;
- print "[" . "-" x $barlen . " " x ($proglen - $barlen) . "]\r";
+ print STDOUT "[" . "-" x $barlen . " " x ($proglen - $barlen) . "]\r";
}
}
sub progress_end()
{
- print "[" . "-" x $proglen . "]\n";
+ print STDOUT "[" . "-" x $proglen . "]\n";
$| = 0;
}
@@ -124,7 +124,7 @@ sub eval_with_fields($$$$$) {
$evalstr .= "}";
my $v = eval $evalstr;
if ($@) {
- print "Syntax error detected evaluating $insnname $blockname string:\n$block\n$@";
+ print STDERR "Syntax error detected evaluating $insnname $blockname string:\n$block\n$@";
exit(1);
}
return $v;
@@ -163,20 +163,20 @@ sub dump_insn_details($$)
{
# Dump the instruction details for one insn
my ($insn, $rec) = @_;
- print "insn $insn: ";
+ print STDOUT "insn $insn: ";
my $insnwidth = $rec->{width};
my $fixedbits = $rec->{fixedbits};
my $fixedbitmask = $rec->{fixedbitmask};
my $constraint = $rec->{blocks}{"constraints"};
- print sprintf(" insnwidth %d fixedbits %08x mask %08x ", $insnwidth, $fixedbits, $fixedbitmask);
+ print STDOUT sprintf(" insnwidth %d fixedbits %08x mask %08x ", $insnwidth, $fixedbits, $fixedbitmask);
if (defined $constraint) {
- print "constraint $constraint ";
+ print STDOUT "constraint $constraint ";
}
for my $tuple (@{ $rec->{fields} }) {
my ($var, $pos, $mask) = @$tuple;
- print "($var, $pos, " . sprintf("%08x", $mask) . ") ";
+ print STDOUT "($var, $pos, " . sprintf("%08x", $mask) . ") ";
}
- print "\n";
+ print STDOUT "\n";
}
1;
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RISU v2 6/8] risugen: Add sparc64 support
2024-05-22 3:44 [PATCH RISU v2 0/8] ELF and Sparc64 support Richard Henderson
` (4 preceding siblings ...)
2024-05-22 3:44 ` [PATCH RISU v2 5/8] risugen: Be explicit about print destinations Richard Henderson
@ 2024-05-22 3:44 ` Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 7/8] sparc64: Add a few logical insns Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 8/8] sparc64: Add VIS1 instructions Richard Henderson
7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2024-05-22 3:44 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, mark.cave-ayland
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
risugen | 10 +-
risugen_common.pm | 50 +++++-
risugen_sparc64.pm | 385 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 443 insertions(+), 2 deletions(-)
create mode 100644 risugen_sparc64.pm
diff --git a/risugen b/risugen
index 2800b8b..830dfd3 100755
--- a/risugen
+++ b/risugen
@@ -310,6 +310,8 @@ Valid options:
Useful to test before support for FP is available.
--sve : enable sve floating point
--be : generate instructions in Big-Endian byte order (ppc64 only).
+ --cross prefix : prefix for the assembler and linker
+ --keep : do not remove intermediate files
--help : print this message
EOT
}
@@ -322,6 +324,8 @@ sub main()
my $fp_enabled = 1;
my $sve_enabled = 0;
my $big_endian = 0;
+ my $cross_prefix = "";
+ my $keep = 0;
my ($infile, $outfile);
GetOptions( "help" => sub { usage(); exit(0); },
@@ -339,6 +343,8 @@ sub main()
"be" => sub { $big_endian = 1; },
"no-fp" => sub { $fp_enabled = 0; },
"sve" => sub { $sve_enabled = 1; },
+ "cross-prefix=s" => \$cross_prefix,
+ "keep" => sub { $keep = 1; },
) or return 1;
# allow "--pattern re,re" and "--pattern re --pattern re"
@pattern_re = split(/,/,join(',',@pattern_re));
@@ -372,7 +378,9 @@ sub main()
'keys' => \@insn_keys,
'arch' => $full_arch[0],
'subarch' => $full_arch[1] || '',
- 'bigendian' => $big_endian
+ 'bigendian' => $big_endian,
+ 'cross_prefix' => $cross_prefix,
+ 'keep' => $keep,
);
write_test_code(\%params);
diff --git a/risugen_common.pm b/risugen_common.pm
index 5207c0e..228082f 100644
--- a/risugen_common.pm
+++ b/risugen_common.pm
@@ -26,7 +26,8 @@ BEGIN {
our @EXPORT = qw(open_bin close_bin set_endian insn32 insn16 $bytecount
progress_start progress_update progress_end
eval_with_fields is_pow_of_2 sextract ctz
- dump_insn_details);
+ dump_insn_details
+ open_asm close_asm assemble_and_link);
}
our $bytecount;
@@ -66,6 +67,53 @@ sub insn16($)
$bytecount += 2;
}
+sub open_asm($)
+{
+ my ($basename) = @_;
+ my $fname = $basename . ".s";
+ open(ASM, ">", $fname) or die "can't open $fname: $!";
+ select ASM;
+}
+
+sub close_asm
+{
+ close(ASM) or die "can't close asm file: $!";
+ select STDOUT;
+}
+
+sub assemble_and_link($$$@)
+{
+ my ($basename, $cross_prefix, $keep, @asflags) = @_;
+ my $asmfile = $basename . ".s";
+ my $ldfile = $basename . ".ld";
+ my $objfile = $basename . ".o";
+
+ open(LD, ">", $ldfile) or die "can't open $ldfile: $!";
+ print LD '
+ ENTRY(start)
+ PHDRS { text PT_LOAD FILEHDR PHDRS; }
+ SECTIONS {
+ . = SIZEOF_HEADERS;
+ PROVIDE(start = .);
+ .text : { *(.text) } :text
+ .data : { *(.data) } :text
+ }
+ ';
+ close(LD);
+
+ my @as = ($cross_prefix . "as", @asflags, "-o", $objfile, $asmfile);
+ system(@as) == 0 or die "system @as failed: $?";
+
+ my @ld = ($cross_prefix . "ld", "-o", $basename, "-T", $ldfile, $objfile);
+ system(@ld) == 0 or die "system @ld failed: $?";
+
+ if (!$keep) {
+ unlink $asmfile;
+ unlink $ldfile;
+ unlink $objfile;
+ }
+}
+
# Progress bar implementation
my $lastprog;
my $proglen;
diff --git a/risugen_sparc64.pm b/risugen_sparc64.pm
new file mode 100644
index 0000000..c9f2ede
--- /dev/null
+++ b/risugen_sparc64.pm
@@ -0,0 +1,385 @@
+#!/usr/bin/perl -w
+###############################################################################
+# Copyright (c) 2024 Linaro Limited
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+###############################################################################
+
+# risugen -- generate a test binary file for use with risu
+# See 'risugen --help' for usage information.
+package risugen_sparc64;
+
+use strict;
+use warnings;
+
+use risugen_common;
+
+require Exporter;
+
+our @ISA = qw(Exporter);
+our @EXPORT = qw(write_test_code);
+
+my $periodic_reg_random = 1;
+
+# Maximum alignment restriction permitted for a memory op.
+my $MAXALIGN = 64;
+my $MAXBLOCK = 2048;
+my $PARAMREG = 15; # %o7
+
+my $OP_COMPARE = 0; # compare registers
+my $OP_TESTEND = 1; # end of test, stop
+my $OP_SETMEMBLOCK = 2; # g1 is address of memory block (8192 bytes)
+my $OP_GETMEMBLOCK = 3; # add the address of memory block to g1
+my $OP_COMPAREMEM = 4; # compare memory block
+
+my @GREGS = ( "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
+ "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%o6", "%o7",
+ "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
+ "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%i6", "%i7" );
+
+sub write_data32($)
+{
+ my ($val) = @_;
+ printf "\t.word\t%#x\n", $val;
+}
+
+sub write_data64($)
+{
+ my ($val) = @_;
+ printf "\t.quad\t%#x\n", $val;
+}
+
+sub write_risuop($)
+{
+ my ($op) = @_;
+ printf "\tilltrap\t%#x\n", 0xdead0 + $op;
+}
+
+sub write_mov_rr($$)
+{
+ my ($rd, $rs) = @_;
+ printf "\tmov\t%s,%s\n", $GREGS[$rs], $GREGS[$rd];
+}
+
+sub write_mov_ri($$)
+{
+ my ($rd, $imm) = @_;
+
+ if (-0x1000 <= $imm < 0x1000) {
+ printf "\tmov\t%d,%s\n", $imm, $GREGS[$rd];
+ } else {
+ my $immhi = $imm & 0xfffff000;
+ my $immlo = $imm & 0x00000fff;
+
+ if ($imm < 0) {
+ $immhi ^= 0xfffff000;
+ $immlo |= -0x1000;
+ }
+ printf "\tsethi\t%%hi(%d),%s\n", $immhi, $GREGS[$rd];
+ if ($immlo != 0) {
+ printf "\txor\t%s,%d,%s\n", $GREGS[$rd], $immlo, $GREGS[$rd];
+ }
+ }
+}
+
+sub write_add_rri($$$)
+{
+ my ($rd, $rs, $imm) = @_;
+ die "bad imm!" if ($imm < -0x1000 || $imm >= 0x1000);
+
+ printf "\txor\t%s,%d,%s\n", $GREGS[$rs], $imm, $GREGS[$rd];
+}
+
+sub write_sub_rrr($$$)
+{
+ my ($rd, $rs1, $rs2) = @_;
+
+ printf "\tsub\t%s,%s,%s\n", $GREGS[$rs1], $GREGS[$rs2], $GREGS[$rd];
+}
+
+sub begin_datablock($$)
+{
+ my ($align, $label) = @_;
+ die "bad align!" if ($align < 4 || $align > 255 || !is_pow_of_2($align));
+
+ printf ".data\n";
+ printf "\t.balign %d\n", $align;
+ printf "%s:\n", $label;
+}
+
+sub end_datablock()
+{
+ printf ".text\n"
+}
+
+sub write_ref_datablock($$$$)
+{
+ my ($rd, $offset, $scratch, $label) = @_;
+
+ printf "\trd\t%%pc,%s\n", $GREGS[$rd];
+ printf "\tsethi\t%%pc22(%s+%d),%s\n",
+ $label, $offset + 4, $GREGS[$scratch];
+ printf "\tor\t%s,%%pc10(%s+%d),%s\n",
+ $GREGS[$scratch], $label, $offset + 8, $GREGS[$scratch];
+ printf "\tadd\t%s,%s,%s\n", $GREGS[$scratch], $GREGS[$rd], $GREGS[$rd];
+}
+
+sub write_random_register_data($$)
+{
+ my ($fp_enabled, $fsr) = @_;
+ my $size = 32 * 8;
+
+ if ($fp_enabled) {
+ # random data for 32 double-precision regs plus %gsr
+ $size += $fp_enabled ? 33 * 8 : 0;
+ }
+
+ begin_datablock(8, "1");
+ for (my $i = 0; $i < $size; $i += 4) {
+ write_data32(rand(0xffffffff));
+ }
+ if ($fp_enabled) {
+ # %fsr gets constant data
+ write_data64($fsr);
+ }
+ end_datablock();
+
+ write_ref_datablock(1, 0, 2, "1b");
+
+ # Load floating point / SIMD registers
+ if ($fp_enabled) {
+ for (my $rt = 0; $rt < 64; $rt += 2) {
+ printf "\tldd\t[%s+%d],%%f%d\n", $GREGS[1], 32 * 8 + $rt * 4, $rt;
+ }
+ printf "\tldx\t[%s+%d],%s\n", $GREGS[1], 64 * 8, $GREGS[2];
+ printf "\twr\t%s,0,%%gsr\n", $GREGS[2];
+ printf "\tldx\t[%s+%d],%%fsr\n", $GREGS[1], 65 * 8;
+ }
+
+ # Load Y
+ printf "\tldx\t[%s],%s\n", $GREGS[1], $GREGS[2];
+ printf "\twr\t%s,0,%%y\n", $GREGS[2];
+
+ # Clear flags
+ printf "\twr\t%%g0,0,%%ccr\n";
+
+ # Load general purpose registers
+ for (my $i = 31; $i >= 1; --$i) {
+ if (reg_ok($i)) {
+ printf "\tldx\t[%s+%d],%s\n", $GREGS[1], $i * 8, $GREGS[$i];
+ }
+ }
+
+ write_risuop($OP_COMPARE);
+}
+
+sub write_memblock_setup()
+{
+ begin_datablock($MAXALIGN, "2");
+
+ for (my $i = 0; $i < $MAXBLOCK; $i += 4) {
+ write_data32(rand(0xffffffff));
+ }
+
+ end_datablock();
+ write_ref_datablock($PARAMREG, 0, 1, "2b");
+ write_risuop($OP_SETMEMBLOCK);
+}
+
+# Functions used in memory blocks to handle addressing modes.
+# These all have the same basic API: they get called with parameters
+# corresponding to the interesting fields of the instruction,
+# and should generate code to set up the base register to be
+# valid. They must return the register number of the base register.
+# The last (array) parameter lists the registers which are trashed
+# by the instruction (ie which are the targets of the load).
+# This is used to avoid problems when the base reg is a load target.
+
+# Global used to communicate between align(x) and reg() etc.
+my $alignment_restriction;
+
+sub align($)
+{
+ my ($a) = @_;
+ if (!is_pow_of_2($a) || !(0 < $a <= $MAXALIGN)) {
+ die "bad align() value $a\n";
+ }
+ $alignment_restriction = $a;
+}
+
+sub gen_memblock_offset()
+{
+ # Generate a random offset within the memory block, of the correct
+ # alignment. We require the offset to not be within 16 bytes of either
+ # end, to (more than) allow for the worst case data transfer.
+ return (rand($MAXBLOCK - 32) + 16) & ~($alignment_restriction - 1);
+}
+
+sub reg_ok($)
+{
+ my ($r) = @_;
+
+ # Avoid special registers %g7 (tp), %o6 (sp), %i6 (fp).
+ return $r != 7 && $r != 14 && $r != 30;
+}
+
+sub reg_plus_imm($$@)
+{
+ # Handle reg + immediate addressing mode
+ my ($base, $imm, @trashed) = @_;
+ my $offset = gen_memblock_offset();
+ my $scratch = $base != 1 ? 1 : 2;
+
+ write_ref_datablock($base, $offset - $imm, $scratch, "2b");
+ write_mov_ri($scratch, 0);
+
+ if (grep $_ == $base, @trashed) {
+ return -1;
+ }
+ return $base;
+}
+
+sub reg($@)
+{
+ my ($base, @trashed) = @_;
+ return reg_plus_imm($base, 0, @trashed);
+}
+
+sub reg_plus_reg($$@)
+{
+ # Handle reg + reg addressing mode
+ my ($base, $idx, @trashed) = @_;
+ my $offset = gen_memblock_offset();
+ my $scratch = 1;
+
+ if ($base == $idx) {
+ return -1;
+ }
+
+ while ($base == $scratch || $idx == $scratch) {
+ ++$scratch;
+ }
+
+ write_ref_datablock($base, $offset, $scratch, "2b");
+ write_mov_ri($scratch, 0);
+ write_sub_rrr($base, $base, $idx);
+
+ if (grep $_ == $base, @trashed) {
+ return -1;
+ }
+ return $base;
+}
+
+sub gen_one_insn($)
+{
+ my ($rec) = @_;
+ my $insnname = $rec->{name};
+ my $insnwidth = $rec->{width};
+ my $fixedbits = $rec->{fixedbits};
+ my $fixedbitmask = $rec->{fixedbitmask};
+ my $constraint = $rec->{blocks}{"constraints"};
+ my $memblock = $rec->{blocks}{"memory"};
+
+ # Given an instruction-details array, generate an instruction
+ my $constraintfailures = 0;
+
+ INSN: while(1) {
+ my $insn = int(rand(0xffffffff));
+
+ $insn &= ~$fixedbitmask;
+ $insn |= $fixedbits;
+
+ if (defined $constraint) {
+ # User-specified constraint: evaluate in an environment
+ # with variables set corresponding to the variable fields.
+ my $v = eval_with_fields($insnname, $insn, $rec, "constraints", $constraint);
+ if (!$v) {
+ $constraintfailures++;
+ if ($constraintfailures > 10000) {
+ print "10000 consecutive constraint failures for $insnname constraints string:\n$constraint\n";
+ exit (1);
+ }
+ next INSN;
+ }
+ }
+
+ # OK, we got a good one
+ $constraintfailures = 0;
+
+ my $basereg;
+
+ if (defined $memblock) {
+ # This is a load or store. We simply evaluate the block,
+ # which is expected to be a call to a function which emits
+ # the code to set up the base register and returns the
+ # number of the base register.
+ align(16);
+ $basereg = eval_with_fields($insnname, $insn, $rec, "memory", $memblock);
+ }
+
+ write_data32($insn);
+
+ if (defined $memblock) {
+ # Clean up following a memory access instruction:
+ # we need to turn the (possibly written-back) basereg
+ # into an offset from the base of the memory block,
+ # to avoid making register values depend on memory layout.
+ # $basereg -1 means the basereg was a target of a load
+ # (and so it doesn't contain a memory address after the op)
+ if ($basereg != -1) {
+ write_mov_ri($basereg, 0);
+ }
+ write_risuop($OP_COMPAREMEM);
+ }
+ return;
+ }
+}
+
+sub write_test_code($)
+{
+ my ($params) = @_;
+
+ my $fp_enabled = $params->{ 'fp_enabled' };
+ my $fsr = $params->{ 'fpscr' };
+ my $numinsns = $params->{ 'numinsns' };
+ my $outfile = $params->{ 'outfile' };
+
+ my %insn_details = %{ $params->{ 'details' } };
+ my @keys = @{ $params->{ 'keys' } };
+
+ open_asm($outfile);
+
+ # TODO better random number generator?
+ srand(0);
+
+ print STDOUT "Generating code using patterns: @keys...\n";
+ progress_start(78, $numinsns);
+
+ if (grep { defined($insn_details{$_}->{blocks}->{"memory"}) } @keys) {
+ write_memblock_setup();
+ }
+
+ # memblock setup doesn't clean its registers, so this must come afterwards.
+ write_random_register_data($fp_enabled, $fsr);
+
+ for my $i (1..$numinsns) {
+ my $insn_enc = $keys[int rand (@keys)];
+ gen_one_insn($insn_details{$insn_enc});
+ write_risuop($OP_COMPARE);
+ # Rewrite the registers periodically.
+ if ($periodic_reg_random && ($i % 100) == 0) {
+ write_random_register_data($fp_enabled, $fsr);
+ }
+ progress_update($i);
+ }
+ write_risuop($OP_TESTEND);
+ progress_end();
+
+ close_asm();
+ assemble_and_link($outfile, $params->{ 'cross_prefix' },
+ $params->{ 'keep' }, "-Av9a");
+}
+
+1;
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RISU v2 7/8] sparc64: Add a few logical insns
2024-05-22 3:44 [PATCH RISU v2 0/8] ELF and Sparc64 support Richard Henderson
` (5 preceding siblings ...)
2024-05-22 3:44 ` [PATCH RISU v2 6/8] risugen: Add sparc64 support Richard Henderson
@ 2024-05-22 3:44 ` Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 8/8] sparc64: Add VIS1 instructions Richard Henderson
7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2024-05-22 3:44 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, mark.cave-ayland
Just a token to verify the script is working.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
sparc64.risu | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
create mode 100644 sparc64.risu
diff --git a/sparc64.risu b/sparc64.risu
new file mode 100644
index 0000000..b45ea86
--- /dev/null
+++ b/sparc64.risu
@@ -0,0 +1,30 @@
+###############################################################################
+# Copyright (c) 2024 Linaro Limited
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+###############################################################################
+
+# Input file for risugen defining Sparc64 instructions
+.mode sparc64
+
+ADD_r SPARC 10 rd:5 0 cc:1 ci:1 000 rs1:5 0 00000000 rs2:5 \
+ !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+ADD_i SPARC 10 rd:5 0 cc:1 ci:1 000 rs1:5 1 imm:13 \
+ !constraints { reg_ok($rd) && reg_ok($rs1); }
+
+AND_r SPARC 10 rd:5 0 cc:1 0001 rs1:5 0 00000000 rs2:5 \
+ !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+AND_i SPARC 10 rd:5 0 cc:1 0001 rs1:5 1 imm:13 \
+ !constraints { reg_ok($rd) && reg_ok($rs1); }
+
+OR_r SPARC 10 rd:5 0 cc:1 0010 rs1:5 0 00000000 rs2:5 \
+ !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+OR_i SPARC 10 rd:5 0 cc:1 0010 rs1:5 1 imm:13 \
+ !constraints { reg_ok($rd) && reg_ok($rs1); }
+
+XOR_r SPARC 10 rd:5 0 cc:1 0011 rs1:5 0 00000000 rs2:5 \
+ !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+XOR_i SPARC 10 rd:5 0 cc:1 0011 rs1:5 1 imm:13 \
+ !constraints { reg_ok($rd) && reg_ok($rs1); }
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH RISU v2 8/8] sparc64: Add VIS1 instructions
2024-05-22 3:44 [PATCH RISU v2 0/8] ELF and Sparc64 support Richard Henderson
` (6 preceding siblings ...)
2024-05-22 3:44 ` [PATCH RISU v2 7/8] sparc64: Add a few logical insns Richard Henderson
@ 2024-05-22 3:44 ` Richard Henderson
7 siblings, 0 replies; 9+ messages in thread
From: Richard Henderson @ 2024-05-22 3:44 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, mark.cave-ayland
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
sparc64.risu | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)
diff --git a/sparc64.risu b/sparc64.risu
index b45ea86..10a8510 100644
--- a/sparc64.risu
+++ b/sparc64.risu
@@ -28,3 +28,94 @@ XOR_r SPARC 10 rd:5 0 cc:1 0011 rs1:5 0 00000000 rs2:5 \
!constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
XOR_i SPARC 10 rd:5 0 cc:1 0011 rs1:5 1 imm:13 \
!constraints { reg_ok($rd) && reg_ok($rs1); }
+
+#
+# VIS1
+#
+
+EDGE8cc VIS1 10 rd:5 110110 rs1:5 0 0000 0000 rs2:5 \
+ !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+EDGE8Lcc VIS1 10 rd:5 110110 rs1:5 0 0000 0010 rs2:5 \
+ !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+EDGE16cc VIS1 10 rd:5 110110 rs1:5 0 0000 0100 rs2:5 \
+ !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+EDGE16Lcc VIS1 10 rd:5 110110 rs1:5 0 0000 0110 rs2:5 \
+ !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+EDGE32cc VIS1 10 rd:5 110110 rs1:5 0 0000 1000 rs2:5 \
+ !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+EDGE32Lcc VIS1 10 rd:5 110110 rs1:5 0 0000 1010 rs2:5 \
+ !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+
+ARRAY8 VIS1 10 rd:5 110110 rs1:5 0 0001 0000 rs2:5 \
+ !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+ARRAY16 VIS1 10 rd:5 110110 rs1:5 0 0001 0010 rs2:5 \
+ !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+ARRAY32 VIS1 10 rd:5 110110 rs1:5 0 0001 0100 rs2:5 \
+ !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+
+FZEROd VIS1 10 rd:5 110110 00000 0 0110 0000 00000
+FZEROs VIS1 10 rd:5 110110 00000 0 0110 0001 00000
+FONEd VIS1 10 rd:5 110110 00000 0 0110 1110 00000
+FONEs VIS1 10 rd:5 110110 00000 0 0110 1111 00000
+
+FSRC1d VIS1 10 rd:5 110110 rs1:5 0 0111 0100 00000
+FSRC1s VIS1 10 rd:5 110110 rs1:5 0 0111 0101 00000
+FSRC2d VIS1 10 rd:5 110110 00000 0 0111 1000 rs2:5
+FSRC2s VIS1 10 rd:5 110110 00000 0 0111 1001 rs2:5
+FNOT1d VIS1 10 rd:5 110110 rs1:5 0 0110 1010 00000
+FNOT1s VIS1 10 rd:5 110110 rs1:5 0 0110 1011 00000
+FNOT2d VIS1 10 rd:5 110110 00000 0 0110 0110 rs2:5
+FNOT2s VIS1 10 rd:5 110110 00000 0 0110 0111 rs2:5
+
+FPADD16 VIS1 10 rd:5 110110 rs1:5 0 0101 0000 rs2:5
+FPADD16s VIS1 10 rd:5 110110 rs1:5 0 0101 0001 rs2:5
+FPADD32 VIS1 10 rd:5 110110 rs1:5 0 0101 0010 rs2:5
+FPADD32s VIS1 10 rd:5 110110 rs1:5 0 0101 0011 rs2:5
+FPSUB16 VIS1 10 rd:5 110110 rs1:5 0 0101 0100 rs2:5
+FPSUB16s VIS1 10 rd:5 110110 rs1:5 0 0101 0101 rs2:5
+FPSUB32 VIS1 10 rd:5 110110 rs1:5 0 0101 0110 rs2:5
+FPSUB32s VIS1 10 rd:5 110110 rs1:5 0 0101 0111 rs2:5
+
+FNORd VIS1 10 rd:5 110110 rs1:5 0 0110 0010 rs2:5
+FNORs VIS1 10 rd:5 110110 rs1:5 0 0110 0011 rs2:5
+FANDNOT1d VIS1 10 rd:5 110110 rs1:5 0 0110 0100 rs2:5
+FANDNOT1s VIS1 10 rd:5 110110 rs1:5 0 0110 0101 rs2:5
+FANDNOT2d VIS1 10 rd:5 110110 rs1:5 0 0110 1000 rs2:5
+FANDNOT2s VIS1 10 rd:5 110110 rs1:5 0 0110 1001 rs2:5
+FXORd VIS1 10 rd:5 110110 rs1:5 0 0110 1100 rs2:5
+FXORs VIS1 10 rd:5 110110 rs1:5 0 0110 1101 rs2:5
+FNANDd VIS1 10 rd:5 110110 rs1:5 0 0110 1110 rs2:5
+FNANDs VIS1 10 rd:5 110110 rs1:5 0 0110 1111 rs2:5
+FANDd VIS1 10 rd:5 110110 rs1:5 0 0111 0000 rs2:5
+FANDs VIS1 10 rd:5 110110 rs1:5 0 0111 0001 rs2:5
+FXNORd VIS1 10 rd:5 110110 rs1:5 0 0111 0010 rs2:5
+FXNORs VIS1 10 rd:5 110110 rs1:5 0 0111 0011 rs2:5
+FORNOT1d VIS1 10 rd:5 110110 rs1:5 0 0111 0110 rs2:5
+FORNOT1s VIS1 10 rd:5 110110 rs1:5 0 0111 0111 rs2:5
+FORNOT2d VIS1 10 rd:5 110110 rs1:5 0 0111 1010 rs2:5
+FORNOT2s VIS1 10 rd:5 110110 rs1:5 0 0111 1011 rs2:5
+FORd VIS1 10 rd:5 110110 rs1:5 0 0111 1100 rs2:5
+FORs VIS1 10 rd:5 110110 rs1:5 0 0111 1101 rs2:5
+
+FMUL8x16 VIS1 10 rd:5 110110 rs1:5 0 0011 0001 rs2:5
+FMUL8x16AU VIS1 10 rd:5 110110 rs1:5 0 0011 0011 rs2:5
+FMUL8x16AL VIS1 10 rd:5 110110 rs1:5 0 0011 0101 rs2:5
+FMUL8SUx16 VIS1 10 rd:5 110110 rs1:5 0 0011 0110 rs2:5
+FMUL8ULx16 VIS1 10 rd:5 110110 rs1:5 0 0011 0111 rs2:5
+FMULD8SUx16 VIS1 10 rd:5 110110 rs1:5 0 0011 1000 rs2:5
+FMULD8ULx16 VIS1 10 rd:5 110110 rs1:5 0 0011 1001 rs2:5
+
+FPACK32 VIS1 10 rd:5 110110 rs1:5 0 0011 1010 rs2:5
+FPACK16 VIS1 10 rd:5 110110 00000 0 0011 1011 rs2:5
+FPACKFIX VIS1 10 rd:5 110110 00000 0 0011 1101 rs2:5
+PDIST VIS1 10 rd:5 110110 rs1:5 0 0011 1110 rs2:5
+
+FPMERGE VIS1 10 rd:5 110110 rs1:5 0 0100 1011 rs2:5
+FEXPAND VIS1 10 rd:5 110110 00000 0 0100 1101 rs2:5
+
+# %gsr not handled by risu
+# ALIGNADDR VIS1 10 rd:5 110110 rs1:5 0 0001 1000 rs2:5 \
+# !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+# ALIGNADDRL VIS1 10 rd:5 110110 rs1:5 0 0001 1010 rs2:5 \
+# !constraints { reg_ok($rd) && reg_ok($rs1) && reg_ok($rs2); }
+# FALIGNDATAg VIS1 10 rd:5 110110 rs1:5 0 0100 1000 rs2:5
--
2.34.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2024-05-22 3:46 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-22 3:44 [PATCH RISU v2 0/8] ELF and Sparc64 support Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 1/8] risu: Allow use of ELF test files Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 2/8] Build elf test cases instead of raw binaries Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 3/8] Introduce host_context_t Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 4/8] risu: Add initial sparc64 support Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 5/8] risugen: Be explicit about print destinations Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 6/8] risugen: Add sparc64 support Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 7/8] sparc64: Add a few logical insns Richard Henderson
2024-05-22 3:44 ` [PATCH RISU v2 8/8] sparc64: Add VIS1 instructions Richard Henderson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).