qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [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).