target-arm queue:

* Fix return value from LDSMIN/LDSMAX 8/16 bit atomics
  * Return correct result for LDG when ATA=0
  * Conversion of system insns, loads and stores to decodetree
  * hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1
  * hw/sd/allwinner-sdhost: Don't send non-boolean IRQ line levels
  * hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop
  * hw/arm/Kconfig: sbsa-ref uses Bochs display
  * imx_serial: set wake bit when we receive a data byte
  * docs: sbsa: document board to firmware interface
  * hw/misc/bcm2835_property: avoid hard-coded constants
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmSQZd0ZHHBldGVyLm1h
 eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3lvoEACHH2dWWb1WAMB4GSZbM0PA
 kStY9PO7Ex87BRN6cX2T6qv40eWvZsLsgJn/igDmuv9kXIuejgw5Ri36I+Jce0ZN
 +d2DyrsEH/GlIDcl86HnbG1WGB27uAu0imE8kiokNymsFbyvfLZrByi03rwPRxkp
 fBVK2aFXTq1cZhjo3/43ySbF4/09ajci8uHPtnLla+WpZzoxP38GZ8qsY6WdxgEv
 +ap1h2641DDCpkqqan+tEbFUczJ8QrSvUoofreOJhEAnAuqlRX8V4eiiK9McUX+P
 LLUYUAMeTf9Ts2YRuJd9eUvTmxJo2WBiXFpxSvOfu5YOR5pBiDkDrGLkbY5bUvNu
 Qte/O0gEG0GBwZptCnUWJtF1DoMDAnPjB3JjuBkAo0N5ch7G/McoGfNYEaNEbb6N
 uKetTzlR4s0Zxv/SGxow+/kEkiDNCwna2mni563bz+L7+sRJWFEORErcNHCWckkk
 1W+C1S+pKv9EZvO4lcvJgZus6i5VlWjEOm0IrRcYO+dbA1F7T3j4miIu8JYYIPFu
 IPyZytawpwq8irxTD0Z1hpsjrbkfOMb3hEbmtK4ruSCBRMBA3Zj2cd1ZrL9A00JE
 xC7rLXWxUAOxEXlJ0mDLMU3XGcp5j6wbMtin9odYR0ccXOHaV8dplzLNgAusXtWO
 GqKcq+m7oeSklKl/YIJsuQ==
 =5BGp
 -----END PGP SIGNATURE-----

Merge tag 'pull-target-arm-20230619' of https://git.linaro.org/people/pmaydell/qemu-arm into staging

target-arm queue:
 * Fix return value from LDSMIN/LDSMAX 8/16 bit atomics
 * Return correct result for LDG when ATA=0
 * Conversion of system insns, loads and stores to decodetree
 * hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1
 * hw/sd/allwinner-sdhost: Don't send non-boolean IRQ line levels
 * hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop
 * hw/arm/Kconfig: sbsa-ref uses Bochs display
 * imx_serial: set wake bit when we receive a data byte
 * docs: sbsa: document board to firmware interface
 * hw/misc/bcm2835_property: avoid hard-coded constants

# -----BEGIN PGP SIGNATURE-----
#
# iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmSQZd0ZHHBldGVyLm1h
# eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3lvoEACHH2dWWb1WAMB4GSZbM0PA
# kStY9PO7Ex87BRN6cX2T6qv40eWvZsLsgJn/igDmuv9kXIuejgw5Ri36I+Jce0ZN
# +d2DyrsEH/GlIDcl86HnbG1WGB27uAu0imE8kiokNymsFbyvfLZrByi03rwPRxkp
# fBVK2aFXTq1cZhjo3/43ySbF4/09ajci8uHPtnLla+WpZzoxP38GZ8qsY6WdxgEv
# +ap1h2641DDCpkqqan+tEbFUczJ8QrSvUoofreOJhEAnAuqlRX8V4eiiK9McUX+P
# LLUYUAMeTf9Ts2YRuJd9eUvTmxJo2WBiXFpxSvOfu5YOR5pBiDkDrGLkbY5bUvNu
# Qte/O0gEG0GBwZptCnUWJtF1DoMDAnPjB3JjuBkAo0N5ch7G/McoGfNYEaNEbb6N
# uKetTzlR4s0Zxv/SGxow+/kEkiDNCwna2mni563bz+L7+sRJWFEORErcNHCWckkk
# 1W+C1S+pKv9EZvO4lcvJgZus6i5VlWjEOm0IrRcYO+dbA1F7T3j4miIu8JYYIPFu
# IPyZytawpwq8irxTD0Z1hpsjrbkfOMb3hEbmtK4ruSCBRMBA3Zj2cd1ZrL9A00JE
# xC7rLXWxUAOxEXlJ0mDLMU3XGcp5j6wbMtin9odYR0ccXOHaV8dplzLNgAusXtWO
# GqKcq+m7oeSklKl/YIJsuQ==
# =5BGp
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 19 Jun 2023 04:27:41 PM CEST
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [full]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full]
# gpg:                 aka "Peter Maydell <peter@archaic.org.uk>" [unknown]

* tag 'pull-target-arm-20230619' of https://git.linaro.org/people/pmaydell/qemu-arm: (33 commits)
  hw/misc/bcm2835_property: Handle CORE_CLK_ID firmware property
  hw/misc/bcm2835_property: Replace magic frequency values by definitions
  hw/misc/bcm2835_property: Use 'raspberrypi-fw-defs.h' definitions
  hw/arm/raspi: Import Linux raspi definitions as 'raspberrypi-fw-defs.h'
  docs: sbsa: document board to firmware interface
  imx_serial: set wake bit when we receive a data byte
  hw/arm/Kconfig: sbsa-ref uses Bochs display
  hw/timer/nrf51_timer: Don't lose time when timer is queried in tight loop
  hw/sd/allwinner-sdhost: Don't send non-boolean IRQ line levels
  hw/intc/allwinner-a10-pic: Handle IRQ levels other than 0 or 1
  target/arm: Convert load/store tags insns to decodetree
  target/arm: Convert load/store single structure to decodetree
  target/arm: Convert load/store (multiple structures) to decodetree
  target/arm: Convert LDAPR/STLR (imm) to decodetree
  target/arm: Convert load (pointer auth) insns to decodetree
  target/arm: Convert atomic memory ops to decodetree
  target/arm: Convert LDR/STR reg+reg to decodetree
  target/arm: Convert LDR/STR with 12-bit immediate to decodetree
  target/arm: Convert ld/st reg+imm9 insns to decodetree
  target/arm: Convert load/store-pair to decodetree
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-06-19 16:32:25 +02:00
commit 48ab886d3d
12 changed files with 2157 additions and 1906 deletions

View File

@ -6,12 +6,7 @@ any real hardware the ``sbsa-ref`` board intends to look like real
hardware. The `Server Base System Architecture
<https://developer.arm.com/documentation/den0029/latest>`_ defines a
minimum base line of hardware support and importantly how the firmware
reports that to any operating system. It is a static system that
reports a very minimal DT to the firmware for non-discoverable
information about components affected by the qemu command line (i.e.
cpus and memory). As a result it must have a firmware specifically
built to expect a certain hardware layout (as you would in a real
machine).
reports that to any operating system.
It is intended to be a machine for developing firmware and testing
standards compliance with operating systems.
@ -19,7 +14,7 @@ standards compliance with operating systems.
Supported devices
"""""""""""""""""
The sbsa-ref board supports:
The ``sbsa-ref`` board supports:
- A configurable number of AArch64 CPUs
- GIC version 3
@ -30,3 +25,32 @@ The sbsa-ref board supports:
- Bochs display adapter on PCIe bus
- A generic SBSA watchdog device
Board to firmware interface
"""""""""""""""""""""""""""
``sbsa-ref`` is a static system that reports a very minimal devicetree to the
firmware for non-discoverable information about system components. This
includes both internal hardware and parts affected by the qemu command line
(i.e. CPUs and memory). As a result it must have a firmware specifically built
to expect a certain hardware layout (as you would in a real machine).
DeviceTree information
''''''''''''''''''''''
The devicetree provided by the board model to the firmware is not intended
to be a complete compliant DT. It currently reports:
- CPUs
- memory
- platform version
- GIC addresses
The platform version is only for informing platform firmware about
what kind of ``sbsa-ref`` board it is running on. It is neither
a QEMU versioned machine type nor a reflection of the level of the
SBSA/SystemReady SR support provided.
The ``machine-version-major`` value is updated when changes breaking
fw compatibility are introduced. The ``machine-version-minor`` value
is updated when features are added that don't break fw compatibility.

View File

@ -268,6 +268,7 @@ config SBSA_REF
select PL061 # GPIO
select USB_EHCI_SYSBUS
select WDT_SBSA
select BOCHS_DISPLAY
config SABRELITE
bool

View File

@ -80,7 +80,7 @@ static void imx_update(IMXSerialState *s)
* TCEN and TXDC are both bit 3
* RDR and DREN are both bit 0
*/
mask |= s->ucr4 & (UCR4_TCEN | UCR4_DREN);
mask |= s->ucr4 & (UCR4_WKEN | UCR4_TCEN | UCR4_DREN);
usr2 = s->usr2 & mask;
@ -321,6 +321,9 @@ static void imx_put_data(void *opaque, uint32_t value)
static void imx_receive(void *opaque, const uint8_t *buf, int size)
{
IMXSerialState *s = (IMXSerialState *)opaque;
s->usr2 |= USR2_WAKE;
imx_put_data(opaque, *buf);
}

View File

@ -51,7 +51,7 @@ static void aw_a10_pic_set_irq(void *opaque, int irq, int level)
AwA10PICState *s = opaque;
uint32_t *pending_reg = &s->irq_pending[irq / 32];
*pending_reg = deposit32(*pending_reg, irq % 32, 1, level);
*pending_reg = deposit32(*pending_reg, irq % 32, 1, !!level);
aw_a10_pic_update(s);
}

View File

@ -12,10 +12,12 @@
#include "migration/vmstate.h"
#include "hw/irq.h"
#include "hw/misc/bcm2835_mbox_defs.h"
#include "hw/misc/raspberrypi-fw-defs.h"
#include "sysemu/dma.h"
#include "qemu/log.h"
#include "qemu/module.h"
#include "trace.h"
#include "hw/arm/raspi_platform.h"
/* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */
@ -51,48 +53,48 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
/* @(value + 8) : Request/response indicator */
resplen = 0;
switch (tag) {
case 0x00000000: /* End tag */
case RPI_FWREQ_PROPERTY_END:
break;
case 0x00000001: /* Get firmware revision */
case RPI_FWREQ_GET_FIRMWARE_REVISION:
stl_le_phys(&s->dma_as, value + 12, 346337);
resplen = 4;
break;
case 0x00010001: /* Get board model */
case RPI_FWREQ_GET_BOARD_MODEL:
qemu_log_mask(LOG_UNIMP,
"bcm2835_property: 0x%08x get board model NYI\n",
tag);
resplen = 4;
break;
case 0x00010002: /* Get board revision */
case RPI_FWREQ_GET_BOARD_REVISION:
stl_le_phys(&s->dma_as, value + 12, s->board_rev);
resplen = 4;
break;
case 0x00010003: /* Get board MAC address */
case RPI_FWREQ_GET_BOARD_MAC_ADDRESS:
resplen = sizeof(s->macaddr.a);
dma_memory_write(&s->dma_as, value + 12, s->macaddr.a, resplen,
MEMTXATTRS_UNSPECIFIED);
break;
case 0x00010004: /* Get board serial */
case RPI_FWREQ_GET_BOARD_SERIAL:
qemu_log_mask(LOG_UNIMP,
"bcm2835_property: 0x%08x get board serial NYI\n",
tag);
resplen = 8;
break;
case 0x00010005: /* Get ARM memory */
case RPI_FWREQ_GET_ARM_MEMORY:
/* base */
stl_le_phys(&s->dma_as, value + 12, 0);
/* size */
stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_base);
resplen = 8;
break;
case 0x00010006: /* Get VC memory */
case RPI_FWREQ_GET_VC_MEMORY:
/* base */
stl_le_phys(&s->dma_as, value + 12, s->fbdev->vcram_base);
/* size */
stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_size);
resplen = 8;
break;
case 0x00028001: /* Set power state */
case RPI_FWREQ_SET_POWER_STATE:
/* Assume that whatever device they asked for exists,
* and we'll just claim we set it to the desired state
*/
@ -103,38 +105,42 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
/* Clocks */
case 0x00030001: /* Get clock state */
case RPI_FWREQ_GET_CLOCK_STATE:
stl_le_phys(&s->dma_as, value + 16, 0x1);
resplen = 8;
break;
case 0x00038001: /* Set clock state */
case RPI_FWREQ_SET_CLOCK_STATE:
qemu_log_mask(LOG_UNIMP,
"bcm2835_property: 0x%08x set clock state NYI\n",
tag);
resplen = 8;
break;
case 0x00030002: /* Get clock rate */
case 0x00030004: /* Get max clock rate */
case 0x00030007: /* Get min clock rate */
case RPI_FWREQ_GET_CLOCK_RATE:
case RPI_FWREQ_GET_MAX_CLOCK_RATE:
case RPI_FWREQ_GET_MIN_CLOCK_RATE:
switch (ldl_le_phys(&s->dma_as, value + 12)) {
case 1: /* EMMC */
stl_le_phys(&s->dma_as, value + 16, 50000000);
case RPI_FIRMWARE_EMMC_CLK_ID:
stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_EMMC_CLK_RATE);
break;
case 2: /* UART */
stl_le_phys(&s->dma_as, value + 16, 3000000);
case RPI_FIRMWARE_UART_CLK_ID:
stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_UART_CLK_RATE);
break;
case RPI_FIRMWARE_CORE_CLK_ID:
stl_le_phys(&s->dma_as, value + 16, RPI_FIRMWARE_CORE_CLK_RATE);
break;
default:
stl_le_phys(&s->dma_as, value + 16, 700000000);
stl_le_phys(&s->dma_as, value + 16,
RPI_FIRMWARE_DEFAULT_CLK_RATE);
break;
}
resplen = 8;
break;
case 0x00038002: /* Set clock rate */
case 0x00038004: /* Set max clock rate */
case 0x00038007: /* Set min clock rate */
case RPI_FWREQ_SET_CLOCK_RATE:
case RPI_FWREQ_SET_MAX_CLOCK_RATE:
case RPI_FWREQ_SET_MIN_CLOCK_RATE:
qemu_log_mask(LOG_UNIMP,
"bcm2835_property: 0x%08x set clock rate NYI\n",
tag);
@ -143,121 +149,121 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
/* Temperature */
case 0x00030006: /* Get temperature */
case RPI_FWREQ_GET_TEMPERATURE:
stl_le_phys(&s->dma_as, value + 16, 25000);
resplen = 8;
break;
case 0x0003000A: /* Get max temperature */
case RPI_FWREQ_GET_MAX_TEMPERATURE:
stl_le_phys(&s->dma_as, value + 16, 99000);
resplen = 8;
break;
/* Frame buffer */
case 0x00040001: /* Allocate buffer */
case RPI_FWREQ_FRAMEBUFFER_ALLOCATE:
stl_le_phys(&s->dma_as, value + 12, fbconfig.base);
stl_le_phys(&s->dma_as, value + 16,
bcm2835_fb_get_size(&fbconfig));
resplen = 8;
break;
case 0x00048001: /* Release buffer */
case RPI_FWREQ_FRAMEBUFFER_RELEASE:
resplen = 0;
break;
case 0x00040002: /* Blank screen */
case RPI_FWREQ_FRAMEBUFFER_BLANK:
resplen = 4;
break;
case 0x00044003: /* Test physical display width/height */
case 0x00044004: /* Test virtual display width/height */
case RPI_FWREQ_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT:
case RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT:
resplen = 8;
break;
case 0x00048003: /* Set physical display width/height */
case RPI_FWREQ_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT:
fbconfig.xres = ldl_le_phys(&s->dma_as, value + 12);
fbconfig.yres = ldl_le_phys(&s->dma_as, value + 16);
bcm2835_fb_validate_config(&fbconfig);
fbconfig_updated = true;
/* fall through */
case 0x00040003: /* Get physical display width/height */
case RPI_FWREQ_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT:
stl_le_phys(&s->dma_as, value + 12, fbconfig.xres);
stl_le_phys(&s->dma_as, value + 16, fbconfig.yres);
resplen = 8;
break;
case 0x00048004: /* Set virtual display width/height */
case RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT:
fbconfig.xres_virtual = ldl_le_phys(&s->dma_as, value + 12);
fbconfig.yres_virtual = ldl_le_phys(&s->dma_as, value + 16);
bcm2835_fb_validate_config(&fbconfig);
fbconfig_updated = true;
/* fall through */
case 0x00040004: /* Get virtual display width/height */
case RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT:
stl_le_phys(&s->dma_as, value + 12, fbconfig.xres_virtual);
stl_le_phys(&s->dma_as, value + 16, fbconfig.yres_virtual);
resplen = 8;
break;
case 0x00044005: /* Test depth */
case RPI_FWREQ_FRAMEBUFFER_TEST_DEPTH:
resplen = 4;
break;
case 0x00048005: /* Set depth */
case RPI_FWREQ_FRAMEBUFFER_SET_DEPTH:
fbconfig.bpp = ldl_le_phys(&s->dma_as, value + 12);
bcm2835_fb_validate_config(&fbconfig);
fbconfig_updated = true;
/* fall through */
case 0x00040005: /* Get depth */
case RPI_FWREQ_FRAMEBUFFER_GET_DEPTH:
stl_le_phys(&s->dma_as, value + 12, fbconfig.bpp);
resplen = 4;
break;
case 0x00044006: /* Test pixel order */
case RPI_FWREQ_FRAMEBUFFER_TEST_PIXEL_ORDER:
resplen = 4;
break;
case 0x00048006: /* Set pixel order */
case RPI_FWREQ_FRAMEBUFFER_SET_PIXEL_ORDER:
fbconfig.pixo = ldl_le_phys(&s->dma_as, value + 12);
bcm2835_fb_validate_config(&fbconfig);
fbconfig_updated = true;
/* fall through */
case 0x00040006: /* Get pixel order */
case RPI_FWREQ_FRAMEBUFFER_GET_PIXEL_ORDER:
stl_le_phys(&s->dma_as, value + 12, fbconfig.pixo);
resplen = 4;
break;
case 0x00044007: /* Test pixel alpha */
case RPI_FWREQ_FRAMEBUFFER_TEST_ALPHA_MODE:
resplen = 4;
break;
case 0x00048007: /* Set alpha */
case RPI_FWREQ_FRAMEBUFFER_SET_ALPHA_MODE:
fbconfig.alpha = ldl_le_phys(&s->dma_as, value + 12);
bcm2835_fb_validate_config(&fbconfig);
fbconfig_updated = true;
/* fall through */
case 0x00040007: /* Get alpha */
case RPI_FWREQ_FRAMEBUFFER_GET_ALPHA_MODE:
stl_le_phys(&s->dma_as, value + 12, fbconfig.alpha);
resplen = 4;
break;
case 0x00040008: /* Get pitch */
case RPI_FWREQ_FRAMEBUFFER_GET_PITCH:
stl_le_phys(&s->dma_as, value + 12,
bcm2835_fb_get_pitch(&fbconfig));
resplen = 4;
break;
case 0x00044009: /* Test virtual offset */
case RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_OFFSET:
resplen = 8;
break;
case 0x00048009: /* Set virtual offset */
case RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_OFFSET:
fbconfig.xoffset = ldl_le_phys(&s->dma_as, value + 12);
fbconfig.yoffset = ldl_le_phys(&s->dma_as, value + 16);
bcm2835_fb_validate_config(&fbconfig);
fbconfig_updated = true;
/* fall through */
case 0x00040009: /* Get virtual offset */
case RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_OFFSET:
stl_le_phys(&s->dma_as, value + 12, fbconfig.xoffset);
stl_le_phys(&s->dma_as, value + 16, fbconfig.yoffset);
resplen = 8;
break;
case 0x0004000a: /* Get/Test/Set overscan */
case 0x0004400a:
case 0x0004800a:
case RPI_FWREQ_FRAMEBUFFER_GET_OVERSCAN:
case RPI_FWREQ_FRAMEBUFFER_TEST_OVERSCAN:
case RPI_FWREQ_FRAMEBUFFER_SET_OVERSCAN:
stl_le_phys(&s->dma_as, value + 12, 0);
stl_le_phys(&s->dma_as, value + 16, 0);
stl_le_phys(&s->dma_as, value + 20, 0);
stl_le_phys(&s->dma_as, value + 24, 0);
resplen = 16;
break;
case 0x0004800b: /* Set palette */
case RPI_FWREQ_FRAMEBUFFER_SET_PALETTE:
offset = ldl_le_phys(&s->dma_as, value + 12);
length = ldl_le_phys(&s->dma_as, value + 16);
n = 0;
@ -270,18 +276,18 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
stl_le_phys(&s->dma_as, value + 12, 0);
resplen = 4;
break;
case 0x00040013: /* Get number of displays */
case RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS:
stl_le_phys(&s->dma_as, value + 12, 1);
resplen = 4;
break;
case 0x00060001: /* Get DMA channels */
case RPI_FWREQ_GET_DMA_CHANNELS:
/* channels 2-5 */
stl_le_phys(&s->dma_as, value + 12, 0x003C);
resplen = 4;
break;
case 0x00050001: /* Get command line */
case RPI_FWREQ_GET_COMMAND_LINE:
/*
* We follow the firmware behaviour: no NUL terminator is
* written to the buffer, and if the buffer is too short

View File

@ -193,7 +193,7 @@ static void allwinner_sdhost_update_irq(AwSdHostState *s)
}
trace_allwinner_sdhost_update_irq(irq);
qemu_set_irq(s->irq, irq);
qemu_set_irq(s->irq, !!irq);
}
static void allwinner_sdhost_update_transfer_cnt(AwSdHostState *s,

View File

@ -45,7 +45,12 @@ static uint32_t update_counter(NRF51TimerState *s, int64_t now)
uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns);
s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]);
s->update_counter_ns = now;
/*
* Only advance the sync time to the timestamp of the last tick,
* not all the way to 'now', so we don't lose time if we do
* multiple resyncs in a single tick.
*/
s->update_counter_ns += ticks_to_ns(s, ticks);
return ticks;
}

View File

@ -170,4 +170,14 @@
#define INTERRUPT_ILLEGAL_TYPE0 6
#define INTERRUPT_ILLEGAL_TYPE1 7
/* Clock rates */
#define RPI_FIRMWARE_EMMC_CLK_RATE 50000000
#define RPI_FIRMWARE_UART_CLK_RATE 3000000
/*
* TODO: this is really SoC-specific; we might want to
* set it per-SoC if it turns out any guests care.
*/
#define RPI_FIRMWARE_CORE_CLK_RATE 350000000
#define RPI_FIRMWARE_DEFAULT_CLK_RATE 700000000
#endif

View File

@ -71,6 +71,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(IMXSerialState, IMX_SERIAL)
#define UCR4_DREN BIT(0) /* Receive Data Ready interrupt enable */
#define UCR4_TCEN BIT(3) /* TX complete interrupt enable */
#define UCR4_WKEN BIT(7) /* WAKE interrupt enable */
#define UTS1_TXEMPTY (1<<6)
#define UTS1_RXEMPTY (1<<5)

View File

@ -0,0 +1,163 @@
/*
* Raspberry Pi firmware definitions
*
* Copyright (C) 2022 Auriga LLC, based on Linux kernel
* `include/soc/bcm2835/raspberrypi-firmware.h` (Copyright © 2015 Broadcom)
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_
#define INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_
#include "qemu/osdep.h"
enum rpi_firmware_property_tag {
RPI_FWREQ_PROPERTY_END = 0,
RPI_FWREQ_GET_FIRMWARE_REVISION = 0x00000001,
RPI_FWREQ_GET_FIRMWARE_VARIANT = 0x00000002,
RPI_FWREQ_GET_FIRMWARE_HASH = 0x00000003,
RPI_FWREQ_SET_CURSOR_INFO = 0x00008010,
RPI_FWREQ_SET_CURSOR_STATE = 0x00008011,
RPI_FWREQ_GET_BOARD_MODEL = 0x00010001,
RPI_FWREQ_GET_BOARD_REVISION = 0x00010002,
RPI_FWREQ_GET_BOARD_MAC_ADDRESS = 0x00010003,
RPI_FWREQ_GET_BOARD_SERIAL = 0x00010004,
RPI_FWREQ_GET_ARM_MEMORY = 0x00010005,
RPI_FWREQ_GET_VC_MEMORY = 0x00010006,
RPI_FWREQ_GET_CLOCKS = 0x00010007,
RPI_FWREQ_GET_POWER_STATE = 0x00020001,
RPI_FWREQ_GET_TIMING = 0x00020002,
RPI_FWREQ_SET_POWER_STATE = 0x00028001,
RPI_FWREQ_GET_CLOCK_STATE = 0x00030001,
RPI_FWREQ_GET_CLOCK_RATE = 0x00030002,
RPI_FWREQ_GET_VOLTAGE = 0x00030003,
RPI_FWREQ_GET_MAX_CLOCK_RATE = 0x00030004,
RPI_FWREQ_GET_MAX_VOLTAGE = 0x00030005,
RPI_FWREQ_GET_TEMPERATURE = 0x00030006,
RPI_FWREQ_GET_MIN_CLOCK_RATE = 0x00030007,
RPI_FWREQ_GET_MIN_VOLTAGE = 0x00030008,
RPI_FWREQ_GET_TURBO = 0x00030009,
RPI_FWREQ_GET_MAX_TEMPERATURE = 0x0003000a,
RPI_FWREQ_GET_STC = 0x0003000b,
RPI_FWREQ_ALLOCATE_MEMORY = 0x0003000c,
RPI_FWREQ_LOCK_MEMORY = 0x0003000d,
RPI_FWREQ_UNLOCK_MEMORY = 0x0003000e,
RPI_FWREQ_RELEASE_MEMORY = 0x0003000f,
RPI_FWREQ_EXECUTE_CODE = 0x00030010,
RPI_FWREQ_EXECUTE_QPU = 0x00030011,
RPI_FWREQ_SET_ENABLE_QPU = 0x00030012,
RPI_FWREQ_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014,
RPI_FWREQ_GET_EDID_BLOCK = 0x00030020,
RPI_FWREQ_GET_CUSTOMER_OTP = 0x00030021,
RPI_FWREQ_GET_EDID_BLOCK_DISPLAY = 0x00030023,
RPI_FWREQ_GET_DOMAIN_STATE = 0x00030030,
RPI_FWREQ_GET_THROTTLED = 0x00030046,
RPI_FWREQ_GET_CLOCK_MEASURED = 0x00030047,
RPI_FWREQ_NOTIFY_REBOOT = 0x00030048,
RPI_FWREQ_SET_CLOCK_STATE = 0x00038001,
RPI_FWREQ_SET_CLOCK_RATE = 0x00038002,
RPI_FWREQ_SET_VOLTAGE = 0x00038003,
RPI_FWREQ_SET_MAX_CLOCK_RATE = 0x00038004,
RPI_FWREQ_SET_MIN_CLOCK_RATE = 0x00038007,
RPI_FWREQ_SET_TURBO = 0x00038009,
RPI_FWREQ_SET_CUSTOMER_OTP = 0x00038021,
RPI_FWREQ_SET_DOMAIN_STATE = 0x00038030,
RPI_FWREQ_GET_GPIO_STATE = 0x00030041,
RPI_FWREQ_SET_GPIO_STATE = 0x00038041,
RPI_FWREQ_SET_SDHOST_CLOCK = 0x00038042,
RPI_FWREQ_GET_GPIO_CONFIG = 0x00030043,
RPI_FWREQ_SET_GPIO_CONFIG = 0x00038043,
RPI_FWREQ_GET_PERIPH_REG = 0x00030045,
RPI_FWREQ_SET_PERIPH_REG = 0x00038045,
RPI_FWREQ_GET_POE_HAT_VAL = 0x00030049,
RPI_FWREQ_SET_POE_HAT_VAL = 0x00038049,
RPI_FWREQ_SET_POE_HAT_VAL_OLD = 0x00030050,
RPI_FWREQ_NOTIFY_XHCI_RESET = 0x00030058,
RPI_FWREQ_GET_REBOOT_FLAGS = 0x00030064,
RPI_FWREQ_SET_REBOOT_FLAGS = 0x00038064,
RPI_FWREQ_NOTIFY_DISPLAY_DONE = 0x00030066,
/* Dispmanx TAGS */
RPI_FWREQ_FRAMEBUFFER_ALLOCATE = 0x00040001,
RPI_FWREQ_FRAMEBUFFER_BLANK = 0x00040002,
RPI_FWREQ_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003,
RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004,
RPI_FWREQ_FRAMEBUFFER_GET_DEPTH = 0x00040005,
RPI_FWREQ_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006,
RPI_FWREQ_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007,
RPI_FWREQ_FRAMEBUFFER_GET_PITCH = 0x00040008,
RPI_FWREQ_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009,
RPI_FWREQ_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a,
RPI_FWREQ_FRAMEBUFFER_GET_PALETTE = 0x0004000b,
RPI_FWREQ_FRAMEBUFFER_GET_LAYER = 0x0004000c,
RPI_FWREQ_FRAMEBUFFER_GET_TRANSFORM = 0x0004000d,
RPI_FWREQ_FRAMEBUFFER_GET_VSYNC = 0x0004000e,
RPI_FWREQ_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f,
RPI_FWREQ_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010,
RPI_FWREQ_FRAMEBUFFER_RELEASE = 0x00048001,
RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_ID = 0x00040016,
RPI_FWREQ_FRAMEBUFFER_SET_DISPLAY_NUM = 0x00048013,
RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS = 0x00040013,
RPI_FWREQ_FRAMEBUFFER_GET_DISPLAY_SETTINGS = 0x00040014,
RPI_FWREQ_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003,
RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004,
RPI_FWREQ_FRAMEBUFFER_TEST_DEPTH = 0x00044005,
RPI_FWREQ_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006,
RPI_FWREQ_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007,
RPI_FWREQ_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009,
RPI_FWREQ_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a,
RPI_FWREQ_FRAMEBUFFER_TEST_PALETTE = 0x0004400b,
RPI_FWREQ_FRAMEBUFFER_TEST_LAYER = 0x0004400c,
RPI_FWREQ_FRAMEBUFFER_TEST_TRANSFORM = 0x0004400d,
RPI_FWREQ_FRAMEBUFFER_TEST_VSYNC = 0x0004400e,
RPI_FWREQ_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003,
RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004,
RPI_FWREQ_FRAMEBUFFER_SET_DEPTH = 0x00048005,
RPI_FWREQ_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006,
RPI_FWREQ_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007,
RPI_FWREQ_FRAMEBUFFER_SET_PITCH = 0x00048008,
RPI_FWREQ_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009,
RPI_FWREQ_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a,
RPI_FWREQ_FRAMEBUFFER_SET_PALETTE = 0x0004800b,
RPI_FWREQ_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f,
RPI_FWREQ_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020,
RPI_FWREQ_FRAMEBUFFER_SET_VSYNC = 0x0004800e,
RPI_FWREQ_FRAMEBUFFER_SET_LAYER = 0x0004800c,
RPI_FWREQ_FRAMEBUFFER_SET_TRANSFORM = 0x0004800d,
RPI_FWREQ_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f,
RPI_FWREQ_VCHIQ_INIT = 0x00048010,
RPI_FWREQ_SET_PLANE = 0x00048015,
RPI_FWREQ_GET_DISPLAY_TIMING = 0x00040017,
RPI_FWREQ_SET_TIMING = 0x00048017,
RPI_FWREQ_GET_DISPLAY_CFG = 0x00040018,
RPI_FWREQ_SET_DISPLAY_POWER = 0x00048019,
RPI_FWREQ_GET_COMMAND_LINE = 0x00050001,
RPI_FWREQ_GET_DMA_CHANNELS = 0x00060001,
};
enum rpi_firmware_clk_id {
RPI_FIRMWARE_EMMC_CLK_ID = 1,
RPI_FIRMWARE_UART_CLK_ID,
RPI_FIRMWARE_ARM_CLK_ID,
RPI_FIRMWARE_CORE_CLK_ID,
RPI_FIRMWARE_V3D_CLK_ID,
RPI_FIRMWARE_H264_CLK_ID,
RPI_FIRMWARE_ISP_CLK_ID,
RPI_FIRMWARE_SDRAM_CLK_ID,
RPI_FIRMWARE_PIXEL_CLK_ID,
RPI_FIRMWARE_PWM_CLK_ID,
RPI_FIRMWARE_HEVC_CLK_ID,
RPI_FIRMWARE_EMMC2_CLK_ID,
RPI_FIRMWARE_M2MC_CLK_ID,
RPI_FIRMWARE_PIXEL_BVB_CLK_ID,
RPI_FIRMWARE_VEC_CLK_ID,
RPI_FIRMWARE_NUM_CLK_ID,
};
#endif /* INCLUDE_HW_MISC_RASPBERRYPI_FW_DEFS_H_ */

View File

@ -150,3 +150,406 @@ ERETA 1101011 0100 11111 00001 m:1 11111 11111 &reta # ERETAA, ERETAB
# the processor is in halting debug state (which we don't implement).
# The pattern is listed here as documentation.
# DRPS 1101011 0101 11111 000000 11111 00000
# Hint instruction group
{
[
YIELD 1101 0101 0000 0011 0010 0000 001 11111
WFE 1101 0101 0000 0011 0010 0000 010 11111
WFI 1101 0101 0000 0011 0010 0000 011 11111
# We implement WFE to never block, so our SEV/SEVL are NOPs
# SEV 1101 0101 0000 0011 0010 0000 100 11111
# SEVL 1101 0101 0000 0011 0010 0000 101 11111
# Our DGL is a NOP because we don't merge memory accesses anyway.
# DGL 1101 0101 0000 0011 0010 0000 110 11111
XPACLRI 1101 0101 0000 0011 0010 0000 111 11111
PACIA1716 1101 0101 0000 0011 0010 0001 000 11111
PACIB1716 1101 0101 0000 0011 0010 0001 010 11111
AUTIA1716 1101 0101 0000 0011 0010 0001 100 11111
AUTIB1716 1101 0101 0000 0011 0010 0001 110 11111
ESB 1101 0101 0000 0011 0010 0010 000 11111
PACIAZ 1101 0101 0000 0011 0010 0011 000 11111
PACIASP 1101 0101 0000 0011 0010 0011 001 11111
PACIBZ 1101 0101 0000 0011 0010 0011 010 11111
PACIBSP 1101 0101 0000 0011 0010 0011 011 11111
AUTIAZ 1101 0101 0000 0011 0010 0011 100 11111
AUTIASP 1101 0101 0000 0011 0010 0011 101 11111
AUTIBZ 1101 0101 0000 0011 0010 0011 110 11111
AUTIBSP 1101 0101 0000 0011 0010 0011 111 11111
]
# The canonical NOP has CRm == op2 == 0, but all of the space
# that isn't specifically allocated to an instruction must NOP
NOP 1101 0101 0000 0011 0010 ---- --- 11111
}
# Barriers
CLREX 1101 0101 0000 0011 0011 ---- 010 11111
DSB_DMB 1101 0101 0000 0011 0011 domain:2 types:2 10- 11111
ISB 1101 0101 0000 0011 0011 ---- 110 11111
SB 1101 0101 0000 0011 0011 0000 111 11111
# PSTATE
CFINV 1101 0101 0000 0 000 0100 0000 000 11111
XAFLAG 1101 0101 0000 0 000 0100 0000 001 11111
AXFLAG 1101 0101 0000 0 000 0100 0000 010 11111
# These are architecturally all "MSR (immediate)"; we decode the destination
# register too because there is no commonality in our implementation.
@msr_i .... .... .... . ... .... imm:4 ... .....
MSR_i_UAO 1101 0101 0000 0 000 0100 .... 011 11111 @msr_i
MSR_i_PAN 1101 0101 0000 0 000 0100 .... 100 11111 @msr_i
MSR_i_SPSEL 1101 0101 0000 0 000 0100 .... 101 11111 @msr_i
MSR_i_SBSS 1101 0101 0000 0 011 0100 .... 001 11111 @msr_i
MSR_i_DIT 1101 0101 0000 0 011 0100 .... 010 11111 @msr_i
MSR_i_TCO 1101 0101 0000 0 011 0100 .... 100 11111 @msr_i
MSR_i_DAIFSET 1101 0101 0000 0 011 0100 .... 110 11111 @msr_i
MSR_i_DAIFCLEAR 1101 0101 0000 0 011 0100 .... 111 11111 @msr_i
MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111
# MRS, MSR (register), SYS, SYSL. These are all essentially the
# same instruction as far as QEMU is concerned.
# NB: op0 is bits [20:19], but op0=0b00 is other insns, so we have
# to hand-decode it.
SYS 1101 0101 00 l:1 01 op1:3 crn:4 crm:4 op2:3 rt:5 op0=1
SYS 1101 0101 00 l:1 10 op1:3 crn:4 crm:4 op2:3 rt:5 op0=2
SYS 1101 0101 00 l:1 11 op1:3 crn:4 crm:4 op2:3 rt:5 op0=3
# Exception generation
@i16 .... .... ... imm:16 ... .. &i
SVC 1101 0100 000 ................ 000 01 @i16
HVC 1101 0100 000 ................ 000 10 @i16
SMC 1101 0100 000 ................ 000 11 @i16
BRK 1101 0100 001 ................ 000 00 @i16
HLT 1101 0100 010 ................ 000 00 @i16
# These insns always UNDEF unless in halting debug state, which
# we don't implement. So we don't need to decode them. The patterns
# are listed here as documentation.
# DCPS1 1101 0100 101 ................ 000 01 @i16
# DCPS2 1101 0100 101 ................ 000 10 @i16
# DCPS3 1101 0100 101 ................ 000 11 @i16
# Loads and stores
&stxr rn rt rt2 rs sz lasr
&stlr rn rt sz lasr
@stxr sz:2 ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr
@stlr sz:2 ...... ... ..... lasr:1 ..... rn:5 rt:5 &stlr
%imm1_30_p2 30:1 !function=plus_2
@stxp .. ...... ... rs:5 lasr:1 rt2:5 rn:5 rt:5 &stxr sz=%imm1_30_p2
STXR .. 001000 000 ..... . ..... ..... ..... @stxr # inc STLXR
LDXR .. 001000 010 ..... . ..... ..... ..... @stxr # inc LDAXR
STLR .. 001000 100 11111 . 11111 ..... ..... @stlr # inc STLLR
LDAR .. 001000 110 11111 . 11111 ..... ..... @stlr # inc LDLAR
STXP 1 . 001000 001 ..... . ..... ..... ..... @stxp # inc STLXP
LDXP 1 . 001000 011 ..... . ..... ..... ..... @stxp # inc LDAXP
# CASP, CASPA, CASPAL, CASPL (we don't decode the bits that determine
# acquire/release semantics because QEMU's cmpxchg always has those)
CASP 0 . 001000 0 - 1 rs:5 - 11111 rn:5 rt:5 sz=%imm1_30_p2
# CAS, CASA, CASAL, CASL
CAS sz:2 001000 1 - 1 rs:5 - 11111 rn:5 rt:5
&ldlit rt imm sz sign
@ldlit .. ... . .. ................... rt:5 &ldlit imm=%imm19
LD_lit 00 011 0 00 ................... ..... @ldlit sz=2 sign=0
LD_lit 01 011 0 00 ................... ..... @ldlit sz=3 sign=0
LD_lit 10 011 0 00 ................... ..... @ldlit sz=2 sign=1
LD_lit_v 00 011 1 00 ................... ..... @ldlit sz=2 sign=0
LD_lit_v 01 011 1 00 ................... ..... @ldlit sz=3 sign=0
LD_lit_v 10 011 1 00 ................... ..... @ldlit sz=4 sign=0
# PRFM
NOP 11 011 0 00 ------------------- -----
&ldstpair rt2 rt rn imm sz sign w p
@ldstpair .. ... . ... . imm:s7 rt2:5 rn:5 rt:5 &ldstpair
# STNP, LDNP: Signed offset, non-temporal hint. We don't emulate caches
# so we ignore hints about data access patterns, and handle these like
# plain signed offset.
STP 00 101 0 000 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
LDP 00 101 0 000 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
STP 10 101 0 000 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
LDP 10 101 0 000 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
STP_v 00 101 1 000 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
LDP_v 00 101 1 000 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
STP_v 01 101 1 000 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
LDP_v 01 101 1 000 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
STP_v 10 101 1 000 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
LDP_v 10 101 1 000 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
# STP and LDP: post-indexed
STP 00 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
LDP 00 101 0 001 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
LDP 01 101 0 001 1 ....... ..... ..... ..... @ldstpair sz=2 sign=1 p=1 w=1
STP 10 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
LDP 10 101 0 001 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
STP_v 00 101 1 001 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
LDP_v 00 101 1 001 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=1 w=1
STP_v 01 101 1 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
LDP_v 01 101 1 001 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
STP_v 10 101 1 001 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=1 w=1
LDP_v 10 101 1 001 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=1 w=1
# STP and LDP: offset
STP 00 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
LDP 00 101 0 010 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
LDP 01 101 0 010 1 ....... ..... ..... ..... @ldstpair sz=2 sign=1 p=0 w=0
STP 10 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
LDP 10 101 0 010 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
STP_v 00 101 1 010 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
LDP_v 00 101 1 010 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=0
STP_v 01 101 1 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
LDP_v 01 101 1 010 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
STP_v 10 101 1 010 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
LDP_v 10 101 1 010 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=0
# STP and LDP: pre-indexed
STP 00 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
LDP 00 101 0 011 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
LDP 01 101 0 011 1 ....... ..... ..... ..... @ldstpair sz=2 sign=1 p=0 w=1
STP 10 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
LDP 10 101 0 011 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
STP_v 00 101 1 011 0 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
LDP_v 00 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=2 sign=0 p=0 w=1
STP_v 01 101 1 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
LDP_v 01 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
STP_v 10 101 1 011 0 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=1
LDP_v 10 101 1 011 1 ....... ..... ..... ..... @ldstpair sz=4 sign=0 p=0 w=1
# STGP: store tag and pair
STGP 01 101 0 001 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=1 w=1
STGP 01 101 0 010 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=0
STGP 01 101 0 011 0 ....... ..... ..... ..... @ldstpair sz=3 sign=0 p=0 w=1
# Load/store register (unscaled immediate)
&ldst_imm rt rn imm sz sign w p unpriv ext
@ldst_imm .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=0
@ldst_imm_pre .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=1
@ldst_imm_post .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=0 p=1 w=1
@ldst_imm_user .. ... . .. .. . imm:s9 .. rn:5 rt:5 &ldst_imm unpriv=1 p=0 w=0
STR_i sz:2 111 0 00 00 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0
LDR_i 00 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=1 sz=0
LDR_i 01 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=1 sz=1
LDR_i 10 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=1 sz=2
LDR_i 11 111 0 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0 sz=3
LDR_i 00 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=0 sz=0
LDR_i 01 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=0 sz=1
LDR_i 10 111 0 00 10 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=0 sz=2
LDR_i 00 111 0 00 11 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=1 sz=0
LDR_i 01 111 0 00 11 0 ......... 00 ..... ..... @ldst_imm sign=1 ext=1 sz=1
STR_i sz:2 111 0 00 00 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0
LDR_i 00 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=1 sz=0
LDR_i 01 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=1 sz=1
LDR_i 10 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=1 sz=2
LDR_i 11 111 0 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0 sz=3
LDR_i 00 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=0 sz=0
LDR_i 01 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=0 sz=1
LDR_i 10 111 0 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=0 sz=2
LDR_i 00 111 0 00 11 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=1 sz=0
LDR_i 01 111 0 00 11 0 ......... 01 ..... ..... @ldst_imm_post sign=1 ext=1 sz=1
STR_i sz:2 111 0 00 00 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=0
LDR_i 00 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=1 sz=0
LDR_i 01 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=1 sz=1
LDR_i 10 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=1 sz=2
LDR_i 11 111 0 00 01 0 ......... 10 ..... ..... @ldst_imm_user sign=0 ext=0 sz=3
LDR_i 00 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=0 sz=0
LDR_i 01 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=0 sz=1
LDR_i 10 111 0 00 10 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=0 sz=2
LDR_i 00 111 0 00 11 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=1 sz=0
LDR_i 01 111 0 00 11 0 ......... 10 ..... ..... @ldst_imm_user sign=1 ext=1 sz=1
STR_i sz:2 111 0 00 00 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
LDR_i 00 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=1 sz=0
LDR_i 01 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=1 sz=1
LDR_i 10 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=1 sz=2
LDR_i 11 111 0 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=3
LDR_i 00 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=0 sz=0
LDR_i 01 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=0 sz=1
LDR_i 10 111 0 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=0 sz=2
LDR_i 00 111 0 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=1 sz=0
LDR_i 01 111 0 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=1 ext=1 sz=1
# PRFM : prefetch memory: a no-op for QEMU
NOP 11 111 0 00 10 0 --------- 00 ----- -----
STR_v_i sz:2 111 1 00 00 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0
STR_v_i 00 111 1 00 10 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0 sz=4
LDR_v_i sz:2 111 1 00 01 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0
LDR_v_i 00 111 1 00 11 0 ......... 00 ..... ..... @ldst_imm sign=0 ext=0 sz=4
STR_v_i sz:2 111 1 00 00 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0
STR_v_i 00 111 1 00 10 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0 sz=4
LDR_v_i sz:2 111 1 00 01 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0
LDR_v_i 00 111 1 00 11 0 ......... 01 ..... ..... @ldst_imm_post sign=0 ext=0 sz=4
STR_v_i sz:2 111 1 00 00 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
STR_v_i 00 111 1 00 10 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
LDR_v_i sz:2 111 1 00 01 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0
LDR_v_i 00 111 1 00 11 0 ......... 11 ..... ..... @ldst_imm_pre sign=0 ext=0 sz=4
# Load/store with an unsigned 12 bit immediate, which is scaled by the
# element size. The function gets the sz:imm and returns the scaled immediate.
%uimm_scaled 10:12 sz:3 !function=uimm_scaled
@ldst_uimm .. ... . .. .. ............ rn:5 rt:5 &ldst_imm unpriv=0 p=0 w=0 imm=%uimm_scaled
STR_i sz:2 111 0 01 00 ............ ..... ..... @ldst_uimm sign=0 ext=0
LDR_i 00 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=1 sz=0
LDR_i 01 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=1 sz=1
LDR_i 10 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=1 sz=2
LDR_i 11 111 0 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=3
LDR_i 00 111 0 01 10 ............ ..... ..... @ldst_uimm sign=1 ext=0 sz=0
LDR_i 01 111 0 01 10 ............ ..... ..... @ldst_uimm sign=1 ext=0 sz=1
LDR_i 10 111 0 01 10 ............ ..... ..... @ldst_uimm sign=1 ext=0 sz=2
LDR_i 00 111 0 01 11 ............ ..... ..... @ldst_uimm sign=1 ext=1 sz=0
LDR_i 01 111 0 01 11 ............ ..... ..... @ldst_uimm sign=1 ext=1 sz=1
# PRFM
NOP 11 111 0 01 10 ------------ ----- -----
STR_v_i sz:2 111 1 01 00 ............ ..... ..... @ldst_uimm sign=0 ext=0
STR_v_i 00 111 1 01 10 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
LDR_v_i sz:2 111 1 01 01 ............ ..... ..... @ldst_uimm sign=0 ext=0
LDR_v_i 00 111 1 01 11 ............ ..... ..... @ldst_uimm sign=0 ext=0 sz=4
# Load/store with register offset
&ldst rm rn rt sign ext sz opt s
@ldst .. ... . .. .. . rm:5 opt:3 s:1 .. rn:5 rt:5 &ldst
STR sz:2 111 0 00 00 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
LDR 00 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=1 sz=0
LDR 01 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=1 sz=1
LDR 10 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=1 sz=2
LDR 11 111 0 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=3
LDR 00 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=0 sz=0
LDR 01 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=0 sz=1
LDR 10 111 0 00 10 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=0 sz=2
LDR 00 111 0 00 11 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=1 sz=0
LDR 01 111 0 00 11 1 ..... ... . 10 ..... ..... @ldst sign=1 ext=1 sz=1
# PRFM
NOP 11 111 0 00 10 1 ----- -1- - 10 ----- -----
STR_v sz:2 111 1 00 00 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
STR_v 00 111 1 00 10 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=4
LDR_v sz:2 111 1 00 01 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0
LDR_v 00 111 1 00 11 1 ..... ... . 10 ..... ..... @ldst sign=0 ext=0 sz=4
# Atomic memory operations
&atomic rs rn rt a r sz
@atomic sz:2 ... . .. a:1 r:1 . rs:5 . ... .. rn:5 rt:5 &atomic
LDADD .. 111 0 00 . . 1 ..... 0000 00 ..... ..... @atomic
LDCLR .. 111 0 00 . . 1 ..... 0001 00 ..... ..... @atomic
LDEOR .. 111 0 00 . . 1 ..... 0010 00 ..... ..... @atomic
LDSET .. 111 0 00 . . 1 ..... 0011 00 ..... ..... @atomic
LDSMAX .. 111 0 00 . . 1 ..... 0100 00 ..... ..... @atomic
LDSMIN .. 111 0 00 . . 1 ..... 0101 00 ..... ..... @atomic
LDUMAX .. 111 0 00 . . 1 ..... 0110 00 ..... ..... @atomic
LDUMIN .. 111 0 00 . . 1 ..... 0111 00 ..... ..... @atomic
SWP .. 111 0 00 . . 1 ..... 1000 00 ..... ..... @atomic
LDAPR sz:2 111 0 00 1 0 1 11111 1100 00 rn:5 rt:5
# Load/store register (pointer authentication)
# LDRA immediate is 10 bits signed and scaled, but the bits aren't all contiguous
%ldra_imm 22:s1 12:9 !function=times_2
LDRA 11 111 0 00 m:1 . 1 ......... w:1 1 rn:5 rt:5 imm=%ldra_imm
&ldapr_stlr_i rn rt imm sz sign ext
@ldapr_stlr_i .. ...... .. . imm:9 .. rn:5 rt:5 &ldapr_stlr_i
STLR_i sz:2 011001 00 0 ......... 00 ..... ..... @ldapr_stlr_i sign=0 ext=0
LDAPR_i sz:2 011001 01 0 ......... 00 ..... ..... @ldapr_stlr_i sign=0 ext=0
LDAPR_i 00 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=0
LDAPR_i 01 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=1
LDAPR_i 10 011001 10 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=0 sz=2
LDAPR_i 00 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=0
LDAPR_i 01 011001 11 0 ......... 00 ..... ..... @ldapr_stlr_i sign=1 ext=1 sz=1
# Load/store multiple structures
# The 4-bit opcode in [15:12] encodes repeat count and structure elements
&ldst_mult rm rn rt sz q p rpt selem
@ldst_mult . q:1 ...... p:1 . . rm:5 .... sz:2 rn:5 rt:5 &ldst_mult
ST_mult 0 . 001100 . 0 0 ..... 0000 .. ..... ..... @ldst_mult rpt=1 selem=4
ST_mult 0 . 001100 . 0 0 ..... 0010 .. ..... ..... @ldst_mult rpt=4 selem=1
ST_mult 0 . 001100 . 0 0 ..... 0100 .. ..... ..... @ldst_mult rpt=1 selem=3
ST_mult 0 . 001100 . 0 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 selem=1
ST_mult 0 . 001100 . 0 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
ST_mult 0 . 001100 . 0 0 ..... 1000 .. ..... ..... @ldst_mult rpt=1 selem=2
ST_mult 0 . 001100 . 0 0 ..... 1010 .. ..... ..... @ldst_mult rpt=2 selem=1
LD_mult 0 . 001100 . 1 0 ..... 0000 .. ..... ..... @ldst_mult rpt=1 selem=4
LD_mult 0 . 001100 . 1 0 ..... 0010 .. ..... ..... @ldst_mult rpt=4 selem=1
LD_mult 0 . 001100 . 1 0 ..... 0100 .. ..... ..... @ldst_mult rpt=1 selem=3
LD_mult 0 . 001100 . 1 0 ..... 0110 .. ..... ..... @ldst_mult rpt=3 selem=1
LD_mult 0 . 001100 . 1 0 ..... 0111 .. ..... ..... @ldst_mult rpt=1 selem=1
LD_mult 0 . 001100 . 1 0 ..... 1000 .. ..... ..... @ldst_mult rpt=1 selem=2
LD_mult 0 . 001100 . 1 0 ..... 1010 .. ..... ..... @ldst_mult rpt=2 selem=1
# Load/store single structure
&ldst_single rm rn rt p selem index scale
%ldst_single_selem 13:1 21:1 !function=plus_1
%ldst_single_index_b 30:1 10:3
%ldst_single_index_h 30:1 11:2
%ldst_single_index_s 30:1 12:1
@ldst_single_b .. ...... p:1 .. rm:5 ...... rn:5 rt:5 \
&ldst_single scale=0 selem=%ldst_single_selem \
index=%ldst_single_index_b
@ldst_single_h .. ...... p:1 .. rm:5 ...... rn:5 rt:5 \
&ldst_single scale=1 selem=%ldst_single_selem \
index=%ldst_single_index_h
@ldst_single_s .. ...... p:1 .. rm:5 ...... rn:5 rt:5 \
&ldst_single scale=2 selem=%ldst_single_selem \
index=%ldst_single_index_s
@ldst_single_d . index:1 ...... p:1 .. rm:5 ...... rn:5 rt:5 \
&ldst_single scale=3 selem=%ldst_single_selem
ST_single 0 . 001101 . 0 . ..... 00 . ... ..... ..... @ldst_single_b
ST_single 0 . 001101 . 0 . ..... 01 . ..0 ..... ..... @ldst_single_h
ST_single 0 . 001101 . 0 . ..... 10 . .00 ..... ..... @ldst_single_s
ST_single 0 . 001101 . 0 . ..... 10 . 001 ..... ..... @ldst_single_d
LD_single 0 . 001101 . 1 . ..... 00 . ... ..... ..... @ldst_single_b
LD_single 0 . 001101 . 1 . ..... 01 . ..0 ..... ..... @ldst_single_h
LD_single 0 . 001101 . 1 . ..... 10 . .00 ..... ..... @ldst_single_s
LD_single 0 . 001101 . 1 . ..... 10 . 001 ..... ..... @ldst_single_d
# Replicating load case
LD_single_repl 0 q:1 001101 p:1 1 . rm:5 11 . 0 scale:2 rn:5 rt:5 selem=%ldst_single_selem
%tag_offset 12:s9 !function=scale_by_log2_tag_granule
&ldst_tag rn rt imm p w
@ldst_tag ........ .. . ......... .. rn:5 rt:5 &ldst_tag imm=%tag_offset
@ldst_tag_mult ........ .. . 000000000 .. rn:5 rt:5 &ldst_tag imm=0
STZGM 11011001 00 1 ......... 00 ..... ..... @ldst_tag_mult p=0 w=0
STG 11011001 00 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
STG 11011001 00 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
STG 11011001 00 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
LDG 11011001 01 1 ......... 00 ..... ..... @ldst_tag p=0 w=0
STZG 11011001 01 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
STZG 11011001 01 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
STZG 11011001 01 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
STGM 11011001 10 1 ......... 00 ..... ..... @ldst_tag_mult p=0 w=0
ST2G 11011001 10 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
ST2G 11011001 10 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
ST2G 11011001 10 1 ......... 11 ..... ..... @ldst_tag p=0 w=1
LDGM 11011001 11 1 ......... 00 ..... ..... @ldst_tag_mult p=0 w=0
STZ2G 11011001 11 1 ......... 01 ..... ..... @ldst_tag p=1 w=1
STZ2G 11011001 11 1 ......... 10 ..... ..... @ldst_tag p=0 w=0
STZ2G 11011001 11 1 ......... 11 ..... ..... @ldst_tag p=0 w=1

File diff suppressed because it is too large Load Diff