From 009673edd938352d4238ba3dbe40a99da2c83e00 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 1 Sep 2020 18:29:59 +0200 Subject: seabios-hppa: Update SeaBIOS to hppa-qemu-5.2-2 tag Changes: * If only one bootable device is available, boot from it. * Silence PDC warnings with HP-UX 11.11 * Inform Linux about fw_cfg port addresses * Make power switch button configurable from qemu * Clear screen on machine reset * Add fw_cfg option to enable runtime debug info * Fix panic on OpenBSD/6.7 regarding STI console * Set text planes and used_bits in STI fields * Fix mon_tbl entries * Convert sti_region_list to an initialized struct Signed-off-by: Helge Deller --- pc-bios/hppa-firmware.img | Bin 783192 -> 785696 bytes roms/seabios-hppa | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/hppa-firmware.img b/pc-bios/hppa-firmware.img index f0f8d0e..4ba8c7f 100644 Binary files a/pc-bios/hppa-firmware.img and b/pc-bios/hppa-firmware.img differ diff --git a/roms/seabios-hppa b/roms/seabios-hppa index 4ff7639..73b740f 160000 --- a/roms/seabios-hppa +++ b/roms/seabios-hppa @@ -1 +1 @@ -Subproject commit 4ff7639e2b86d5775fa7d5cd0dbfa4d3a385a701 +Subproject commit 73b740f77190643b2ada5ee97a9a108c6ef2a37b -- cgit v1.1 From df5c6a50944697bf1373582dcea719697edbc9ed Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 27 Aug 2020 13:10:32 +0200 Subject: hw/hppa: Make number of TLB and BTLB entries configurable Until now the TLB size was fixed at 256 entries. To allow operating systems to utilize more TLB entries in the future, we need to tell firmware how many TLB entries we actually support in the emulation. Firmware then reports this to the operating system via the PDC_CACHE_INFO call. This patch simply does the preparation to allow more TLB entries. Signed-off-by: Helge Deller --- hw/hppa/machine.c | 8 ++++++++ target/hppa/cpu.h | 5 ++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 90aeefe..e9d84d0 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -72,6 +72,14 @@ static FWCfgState *create_fw_cfg(MachineState *ms) fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version", g_memdup(&val, sizeof(val)), sizeof(val)); + val = cpu_to_le64(HPPA_TLB_ENTRIES); + fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries", + g_memdup(&val, sizeof(val)), sizeof(val)); + + val = cpu_to_le64(HPPA_BTLB_ENTRIES); + fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries", + g_memdup(&val, sizeof(val)), sizeof(val)); + return fw_cfg; } diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 801a4fb..fb6c59d 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -196,9 +196,12 @@ struct CPUHPPAState { target_ureg shadow[7]; /* shadow registers */ /* ??? The number of entries isn't specified by the architecture. */ +#define HPPA_TLB_ENTRIES 256 +#define HPPA_BTLB_ENTRIES 0 + /* ??? Implement a unified itlb/dtlb for the moment. */ /* ??? We should use a more intelligent data structure. */ - hppa_tlb_entry tlb[256]; + hppa_tlb_entry tlb[HPPA_TLB_ENTRIES]; uint32_t tlb_last; }; -- cgit v1.1 From 32ff8bf248add5f2e64e75d3706c29a4f323832e Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 9 Aug 2020 17:06:50 +0200 Subject: hw/hppa: Store boot device in fw_cfg section Reviewed-by: Richard Henderson Signed-off-by: Helge Deller --- hw/hppa/machine.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index e9d84d0..4b35afc 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -58,6 +58,12 @@ static uint64_t cpu_hppa_to_phys(void *opaque, uint64_t addr) static HPPACPU *cpu[HPPA_MAX_CPUS]; static uint64_t firmware_entry; +static void fw_cfg_boot_set(void *opaque, const char *boot_device, + Error **errp) +{ + fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); +} + static FWCfgState *create_fw_cfg(MachineState *ms) { FWCfgState *fw_cfg; @@ -80,6 +86,9 @@ static FWCfgState *create_fw_cfg(MachineState *ms) fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries", g_memdup(&val, sizeof(val)), sizeof(val)); + fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_order[0]); + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); + return fw_cfg; } -- cgit v1.1 From 34743e9633ab4a76a9bbcf55a0daa11cb2be58c4 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 14 Aug 2020 21:09:40 +0200 Subject: hw/hppa: Change fw_cfg port address Devices on hppa occupy at least 4k starting at the HPA, so MEMORY_HPA+4k is blocked (by Linux) for the memory module. I noticed this when testing the new Linux kernel patch to let the fw_cfg entries show up in Linux under /proc. The Linux kernel driver could not allocate the region for fw_cfg. This new base address seems to not conflict. Signed-off-by: Helge Deller Reviewed-by: Richard Henderson --- hw/hppa/hppa_hardware.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/hppa/hppa_hardware.h b/hw/hppa/hppa_hardware.h index cdb7fa6..b2fbbc2 100644 --- a/hw/hppa/hppa_hardware.h +++ b/hw/hppa/hppa_hardware.h @@ -38,8 +38,7 @@ #define PORT_PCI_CMD (PCI_HPA + DINO_PCI_ADDR) #define PORT_PCI_DATA (PCI_HPA + DINO_CONFIG_DATA) -/* QEMU fw_cfg interface port */ -#define QEMU_FW_CFG_IO_BASE (MEMORY_HPA + 0x80) +#define QEMU_FW_CFG_IO_BASE 0xfffa0000 #define PORT_SERIAL1 (DINO_UART_HPA + 0x800) #define PORT_SERIAL2 (LASI_UART_HPA + 0x800) -- cgit v1.1 From 245760074a74500ce285cf1a08b3ea6a6e91128a Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 2 Sep 2020 21:21:01 +0200 Subject: hw/hppa: Tell SeaBIOS port address of fw_cfg Change QEMU_FW_CFG_IO_BASE to shorter variant FW_CFG_IO_BASE and hand over the actual port address in %r19 to SeaBIOS. Signed-off-by: Helge Deller Reviewed-by: Richard Henderson --- hw/hppa/hppa_hardware.h | 2 +- hw/hppa/machine.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/hw/hppa/hppa_hardware.h b/hw/hppa/hppa_hardware.h index b2fbbc2..bc25889 100644 --- a/hw/hppa/hppa_hardware.h +++ b/hw/hppa/hppa_hardware.h @@ -38,7 +38,7 @@ #define PORT_PCI_CMD (PCI_HPA + DINO_PCI_ADDR) #define PORT_PCI_DATA (PCI_HPA + DINO_CONFIG_DATA) -#define QEMU_FW_CFG_IO_BASE 0xfffa0000 +#define FW_CFG_IO_BASE 0xfffa0000 #define PORT_SERIAL1 (DINO_UART_HPA + 0x800) #define PORT_SERIAL2 (LASI_UART_HPA + 0x800) diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 4b35afc..2bed498 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -69,7 +69,7 @@ static FWCfgState *create_fw_cfg(MachineState *ms) FWCfgState *fw_cfg; uint64_t val; - fw_cfg = fw_cfg_init_mem(QEMU_FW_CFG_IO_BASE, QEMU_FW_CFG_IO_BASE + 4); + fw_cfg = fw_cfg_init_mem(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4); fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ram_size); @@ -290,6 +290,9 @@ static void machine_hppa_init(MachineState *machine) /* tell firmware how many SMP CPUs to present in inventory table */ cpu[0]->env.gr[21] = smp_cpus; + + /* tell firmware fw_cfg port */ + cpu[0]->env.gr[19] = FW_CFG_IO_BASE; } static void hppa_machine_reset(MachineState *ms) @@ -317,6 +320,8 @@ static void hppa_machine_reset(MachineState *ms) cpu[0]->env.gr[24] = 'c'; /* gr22/gr23 unused, no initrd while reboot. */ cpu[0]->env.gr[21] = smp_cpus; + /* tell firmware fw_cfg port */ + cpu[0]->env.gr[19] = FW_CFG_IO_BASE; } -- cgit v1.1 From b28c4a64973418a34cc0373a7462c64297aff623 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 26 Aug 2020 17:45:43 +0200 Subject: hw/hppa: Add power button emulation Emulate a power button switch, tell SeaBIOS the address via fw_cfg and bind the power button to the qemu UI. Signed-off-by: Helge Deller Reviewed-by: Richard Henderson --- hw/hppa/machine.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 2bed498..d516445 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -12,6 +12,7 @@ #include "qemu/error-report.h" #include "sysemu/reset.h" #include "sysemu/sysemu.h" +#include "sysemu/runstate.h" #include "hw/rtc/mc146818rtc.h" #include "hw/timer/i8254.h" #include "hw/char/serial.h" @@ -27,6 +28,30 @@ #define MIN_SEABIOS_HPPA_VERSION 1 /* require at least this fw version */ +#define HPA_POWER_BUTTON (FIRMWARE_END - 0x10) + +static void hppa_powerdown_req(Notifier *n, void *opaque) +{ + hwaddr soft_power_reg = HPA_POWER_BUTTON; + uint32_t val; + + val = ldl_be_phys(&address_space_memory, soft_power_reg); + if ((val >> 8) == 0) { + /* immediately shut down when under hardware control */ + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + return; + } + + /* clear bit 31 to indicate that the power switch was pressed. */ + val &= ~1; + stl_be_phys(&address_space_memory, soft_power_reg, val); +} + +static Notifier hppa_system_powerdown_notifier = { + .notify = hppa_powerdown_req +}; + + static ISABus *hppa_isa_bus(void) { ISABus *isa_bus; @@ -86,6 +111,10 @@ static FWCfgState *create_fw_cfg(MachineState *ms) fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries", g_memdup(&val, sizeof(val)), sizeof(val)); + val = cpu_to_le64(HPA_POWER_BUTTON); + fw_cfg_add_file(fw_cfg, "/etc/power-button-addr", + g_memdup(&val, sizeof(val)), sizeof(val)); + fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_order[0]); qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); @@ -177,6 +206,9 @@ static void machine_hppa_init(MachineState *machine) } } + /* register power switch emulation */ + qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier); + /* Load firmware. Given that this is not "real" firmware, but one explicitly written for the emulation, we might as well load it directly from an ELF image. */ -- cgit v1.1 From 3b65b742543bc6c2ad35e3b42401a26b48a87f26 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 30 Aug 2020 15:35:07 +0200 Subject: target/hppa: Fix boot with old Linux installation CDs The current qemu hppa emulation emulates a PA1.1 CPU, which can only execute the 32-bit instruction set. For unknown 64-bit instructions, a instruction trap is sent to the virtual CPU. This behaviour is correct in the sense that we emulate what the PA1.1 specification says. But when trying to boot older Linux installation images, e.g. ftp://parisc.parisc-linux.org/debian-cd/debian-5.0/lenny-5.0.10-hppa-iso-cd/cdimage.debian.org/debian-5010-hppa-netinst.iso one finds that qemu fails to boot those images. The problem is, that in the Linux kernel (e.g. 2.6.26) of those old images 64-bit instructions were used by mistake in the fault handlers. The relevant instructions (the ",*" indicates that it's a 64-bit instruction) I see are: 0: 09 3e 04 29 sub,* sp,r9,r9 0: 08 3d 06 3d add,* ret1,r1,ret1 0: 0a 09 02 61 or,* r9,r16,r1 0: 0a ba 00 3a andcm,* r26,r21,r26 0: 08 33 02 33 and,* r19,r1,r19 The interesting part is, that real physical 32-bit machines (like the 700/64 and B160L - which is the one we emulate) do boot those images and thus seem to simply ignore the 64-bit flag on those instructions. The patch below modifies the qemu instruction decoder to ignore the 64-bit flag too - which is what real 32-bit hardware seems to do. With this modification qemu now successfully boots those older images too. I suggest to apply the patch below - even if it does not reflect what the SPEC says. Instead it increases the compatibility to really existing hardware and seem to not create problems if we add real PA2.0 support anytime later. Signed-off-by: Helge Deller Reviewed-by: Richard Henderson --- target/hppa/insns.decode | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/target/hppa/insns.decode b/target/hppa/insns.decode index f0dd71d..dceaad6 100644 --- a/target/hppa/insns.decode +++ b/target/hppa/insns.decode @@ -149,9 +149,9 @@ lci 000001 ----- ----- -- 01001100 0 t:5 # Arith/Log #### -andcm 000010 ..... ..... .... 000000 0 ..... @rrr_cf -and 000010 ..... ..... .... 001000 0 ..... @rrr_cf -or 000010 ..... ..... .... 001001 0 ..... @rrr_cf +andcm 000010 ..... ..... .... 000000 - ..... @rrr_cf +and 000010 ..... ..... .... 001000 - ..... @rrr_cf +or 000010 ..... ..... .... 001001 - ..... @rrr_cf xor 000010 ..... ..... .... 001010 0 ..... @rrr_cf uxor 000010 ..... ..... .... 001110 0 ..... @rrr_cf ds 000010 ..... ..... .... 010001 0 ..... @rrr_cf @@ -161,13 +161,13 @@ uaddcm_tc 000010 ..... ..... .... 100111 0 ..... @rrr_cf dcor 000010 ..... 00000 .... 101110 0 ..... @rr_cf dcor_i 000010 ..... 00000 .... 101111 0 ..... @rr_cf -add 000010 ..... ..... .... 0110.. 0 ..... @rrr_cf_sh +add 000010 ..... ..... .... 0110.. - ..... @rrr_cf_sh add_l 000010 ..... ..... .... 1010.. 0 ..... @rrr_cf_sh add_tsv 000010 ..... ..... .... 1110.. 0 ..... @rrr_cf_sh add_c 000010 ..... ..... .... 011100 0 ..... @rrr_cf_sh0 add_c_tsv 000010 ..... ..... .... 111100 0 ..... @rrr_cf_sh0 -sub 000010 ..... ..... .... 010000 0 ..... @rrr_cf +sub 000010 ..... ..... .... 010000 - ..... @rrr_cf sub_tsv 000010 ..... ..... .... 110000 0 ..... @rrr_cf sub_tc 000010 ..... ..... .... 010011 0 ..... @rrr_cf sub_tsv_tc 000010 ..... ..... .... 110011 0 ..... @rrr_cf -- cgit v1.1 From 95aad497d9f1cc96b6913e61c95fca116af69b93 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 3 Sep 2020 07:09:31 +0200 Subject: hw/display/artist: Verify artist screen resolution Artist hardware is limited to 2048 x 2048 pixels. STI ROMs allow at minimum 640 x 480 pixels. Qemu users can adjust the screen size on the command line with: -global artist.width=800 -global artist.height=600 but we need to ensure that the screen size stays inside the given boundaries, otherwise print an error message and adjust. Signed-off-by: Helge Deller Reviewed-by: Richard Henderson --- hw/display/artist.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hw/display/artist.c b/hw/display/artist.c index 7198255..ff1532f 100644 --- a/hw/display/artist.c +++ b/hw/display/artist.c @@ -1374,6 +1374,18 @@ static void artist_realizefn(DeviceState *dev, Error **errp) struct vram_buffer *buf; hwaddr offset = 0; + if (s->width > 2048 || s->height > 2048) { + error_report("artist: screen size can not exceed 2048 x 2048 pixel."); + s->width = MIN(s->width, 2048); + s->height = MIN(s->height, 2048); + } + + if (s->width < 640 || s->height < 480) { + error_report("artist: minimum screen size is 640 x 480 pixel."); + s->width = MAX(s->width, 640); + s->height = MAX(s->height, 480); + } + memory_region_init(&s->mem_as_root, OBJECT(dev), "artist", ~0ull); address_space_init(&s->as, &s->mem_as_root, "artist"); -- cgit v1.1 From c7050f3f167b80e844c6c52f9586c4632a4f54f3 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 3 Sep 2020 07:23:47 +0200 Subject: hw/display/artist: Refactor x/y coordination extraction Simplify the code by using new introduced ADDR_TO_Y() and ADDR_TO_X() macros. Those macros extract the x/y-coordinate from the given uint32. As further simplification the extraction of the x/y coordinates for VRAM_WRITE_INCR_Y and VRAM_WRITE_INCR_X can be done centrally in vram_bit_write(), so move this code up into the function. ADDR_TO_Y() is still limited to 10 bits which allow to address up to of 1024 lines - this will be increased in a follow-up patch. Signed-off-by: Helge Deller Reviewed-by: Richard Henderson --- hw/display/artist.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/hw/display/artist.c b/hw/display/artist.c index ff1532f..16d85c6 100644 --- a/hw/display/artist.c +++ b/hw/display/artist.c @@ -192,6 +192,10 @@ static const char *artist_reg_name(uint64_t addr) } #undef REG_NAME +/* artist has a fixed line length of 2048 bytes. */ +#define ADDR_TO_Y(addr) extract32(addr, 11, 10) +#define ADDR_TO_X(addr) extract32(addr, 0, 11) + static int16_t artist_get_x(uint32_t reg) { return reg >> 16; @@ -348,13 +352,13 @@ static void artist_invalidate_cursor(ARTISTState *s) y, s->cursor_height); } -static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x, +static void vram_bit_write(ARTISTState *s, int posy, bool incr_x, int size, uint32_t data) { struct vram_buffer *buf; uint32_t vram_bitmask = s->vram_bitmask; int mask, i, pix_count, pix_length; - unsigned int offset, width; + unsigned int posx, offset, width; uint8_t *data8, *p; pix_count = vram_write_pix_per_transfer(s); @@ -366,6 +370,8 @@ static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x, if (s->cmap_bm_access) { offset = s->vram_pos; } else { + posx = ADDR_TO_X(s->vram_pos >> 2); + posy += ADDR_TO_Y(s->vram_pos >> 2); offset = posy * width + posx; } @@ -858,7 +864,6 @@ static void artist_reg_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { ARTISTState *s = opaque; - int posx, posy; int width, height; trace_artist_reg_write(size, addr, artist_reg_name(addr & ~3ULL), val); @@ -881,16 +886,12 @@ static void artist_reg_write(void *opaque, hwaddr addr, uint64_t val, break; case VRAM_WRITE_INCR_Y: - posx = (s->vram_pos >> 2) & 0x7ff; - posy = (s->vram_pos >> 13) & 0x3ff; - vram_bit_write(s, posx, posy + s->vram_char_y++, false, size, val); + vram_bit_write(s, s->vram_char_y++, false, size, val); break; case VRAM_WRITE_INCR_X: case VRAM_WRITE_INCR_X2: - posx = (s->vram_pos >> 2) & 0x7ff; - posy = (s->vram_pos >> 13) & 0x3ff; - vram_bit_write(s, posx, posy + s->vram_char_y, true, size, val); + vram_bit_write(s, s->vram_char_y, true, size, val); break; case VRAM_IDX: @@ -1156,8 +1157,7 @@ static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val, { ARTISTState *s = opaque; struct vram_buffer *buf; - int posy = (addr >> 11) & 0x3ff; - int posx = addr & 0x7ff; + unsigned int posy, posx; unsigned int offset; trace_artist_vram_write(size, addr, val); @@ -1170,6 +1170,9 @@ static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val, } buf = vram_write_buffer(s); + posy = ADDR_TO_Y(addr); + posx = ADDR_TO_X(addr); + if (!buf->size) { return; } @@ -1212,7 +1215,7 @@ static uint64_t artist_vram_read(void *opaque, hwaddr addr, unsigned size) ARTISTState *s = opaque; struct vram_buffer *buf; uint64_t val; - int posy, posx; + unsigned int posy, posx; if (s->cmap_bm_access) { buf = &s->vram_buffer[ARTIST_BUFFER_CMAP]; @@ -1229,8 +1232,8 @@ static uint64_t artist_vram_read(void *opaque, hwaddr addr, unsigned size) return 0; } - posy = (addr >> 13) & 0x3ff; - posx = (addr >> 2) & 0x7ff; + posy = ADDR_TO_Y(addr); + posx = ADDR_TO_X(addr); if (posy > buf->height || posx > buf->width) { return 0; -- cgit v1.1 From 32a2b033f0a406c0dd4cc7375367ee63cc36789a Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Thu, 3 Sep 2020 07:44:58 +0200 Subject: hw/display/artist: Allow screen size up to 2048 lines Adjust the ADDR_TO_Y() macro to extract 11 bits, which allows userspace to address screen sizes up to 2048 lines (instead of 1024 before). Signed-off-by: Helge Deller Reviewed-by: Richard Henderson --- hw/display/artist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/display/artist.c b/hw/display/artist.c index 16d85c6..955296d 100644 --- a/hw/display/artist.c +++ b/hw/display/artist.c @@ -193,7 +193,7 @@ static const char *artist_reg_name(uint64_t addr) #undef REG_NAME /* artist has a fixed line length of 2048 bytes. */ -#define ADDR_TO_Y(addr) extract32(addr, 11, 10) +#define ADDR_TO_Y(addr) extract32(addr, 11, 11) #define ADDR_TO_X(addr) extract32(addr, 0, 11) static int16_t artist_get_x(uint32_t reg) -- cgit v1.1