Commit d0c8b957 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/kraxel/tags/vga-20200701-pull-request' into staging



vga: bugfixes for ati and sm501, vgabios cleanup.

# gpg: Signature made Wed 01 Jul 2020 16:03:48 BST
# gpg:                using RSA key 4CB6D8EED3E87138
# gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" [full]
# gpg:                 aka "Gerd Hoffmann <gerd@kraxel.org>" [full]
# gpg:                 aka "Gerd Hoffmann (private) <kraxel@gmail.com>" [full]
# Primary key fingerprint: A032 8CFF B93A 17A7 9901  FE7D 4CB6 D8EE D3E8 7138

* remotes/kraxel/tags/vga-20200701-pull-request:
  configure: vgabios cleanups
  ati-vga: Add dummy MEM_SDRAM_MODE_REG
  ati-vga: Do not assert on error
  ati-vga: Support unaligned access to hardware cursor registers
  sm501: Fix and optimize overlap check
  sm501: Convert debug printfs to traces
  sm501: Do not allow guest to set invalid format
  sm501: Use stn_he_p/ldn_he_p instead of switch/case
  sm501: Optimise 1 pixel 2d ops
  sm501: Introduce variable for commonly used value for better readability
  sm501: Ignore no-op blits
  sm501: Drop unneded variable
  sm501: Fix bounds checks

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents fc1bff95 8db2a4fd
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -8486,14 +8486,14 @@ DIRS="tests tests/tcg tests/tcg/lm32 tests/qapi-schema tests/qtest/libqos"
DIRS="$DIRS tests/qtest tests/qemu-iotests tests/vm tests/fp tests/qgraph"
DIRS="$DIRS docs docs/interop fsdev scsi"
DIRS="$DIRS pc-bios/optionrom pc-bios/s390-ccw"
DIRS="$DIRS roms/seabios roms/vgabios"
DIRS="$DIRS roms/seabios"
LINKS="Makefile"
LINKS="$LINKS tests/tcg/lm32/Makefile po/Makefile"
LINKS="$LINKS tests/tcg/Makefile.target tests/fp/Makefile"
LINKS="$LINKS tests/plugin/Makefile"
LINKS="$LINKS pc-bios/optionrom/Makefile pc-bios/keymaps"
LINKS="$LINKS pc-bios/s390-ccw/Makefile"
LINKS="$LINKS roms/seabios/Makefile roms/vgabios/Makefile"
LINKS="$LINKS roms/seabios/Makefile"
LINKS="$LINKS pc-bios/qemu-icon.bmp"
LINKS="$LINKS .gdbinit scripts" # scripts needed by relative path in .gdbinit
LINKS="$LINKS tests/acceptance tests/data"
@@ -8526,7 +8526,7 @@ export target_list source_path use_containers
$source_path/tests/tcg/configure.sh)

# temporary config to build submodules
for rom in seabios vgabios ; do
for rom in seabios; do
    config_mak=roms/$rom/config.mak
    echo "# Automatically generated by configure - do not modify" > $config_mak
    echo "SRC_PATH=$source_path/roms/$rom" >> $config_mak
+63 −29
Original line number Diff line number Diff line
@@ -86,8 +86,8 @@ static void ati_vga_switch_mode(ATIVGAState *s)
                break;
            default:
                qemu_log_mask(LOG_UNIMP, "Unsupported bpp value\n");
                return;
            }
            assert(bpp != 0);
            DPRINTF("Switching to %dx%d %d %d @ %x\n", h, v, stride, bpp, offs);
            vbe_ioport_write_index(&s->vga, 0, VBE_DISPI_INDEX_ENABLE);
            vbe_ioport_write_data(&s->vga, 0, VBE_DISPI_DISABLED);
@@ -361,6 +361,11 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
    case MC_STATUS:
        val = 5;
        break;
    case MEM_SDRAM_MODE_REG:
        if (s->dev_id != PCI_DEVICE_ID_ATI_RAGE128_PF) {
            val = BIT(28) | BIT(20);
        }
        break;
    case RBBM_STATUS:
    case GUI_STAT:
        val = 64; /* free CMDFIFO entries */
@@ -389,22 +394,28 @@ static uint64_t ati_mm_read(void *opaque, hwaddr addr, unsigned int size)
    case 0xf00 ... 0xfff:
        val = pci_default_read_config(&s->dev, addr - 0xf00, size);
        break;
    case CUR_OFFSET:
        val = s->regs.cur_offset;
    case CUR_OFFSET ... CUR_OFFSET + 3:
        val = ati_reg_read_offs(s->regs.cur_offset, addr - CUR_OFFSET, size);
        break;
    case CUR_HORZ_VERT_POSN:
        val = s->regs.cur_hv_pos;
        val |= s->regs.cur_offset & BIT(31);
    case CUR_HORZ_VERT_POSN ... CUR_HORZ_VERT_POSN + 3:
        val = ati_reg_read_offs(s->regs.cur_hv_pos,
                                addr - CUR_HORZ_VERT_POSN, size);
        if (addr + size > CUR_HORZ_VERT_POSN + 3) {
            val |= (s->regs.cur_offset & BIT(31)) >> (4 - size);
        }
        break;
    case CUR_HORZ_VERT_OFF:
        val = s->regs.cur_hv_offs;
        val |= s->regs.cur_offset & BIT(31);
    case CUR_HORZ_VERT_OFF ... CUR_HORZ_VERT_OFF + 3:
        val = ati_reg_read_offs(s->regs.cur_hv_offs,
                                addr - CUR_HORZ_VERT_OFF, size);
        if (addr + size > CUR_HORZ_VERT_OFF + 3) {
            val |= (s->regs.cur_offset & BIT(31)) >> (4 - size);
        }
        break;
    case CUR_CLR0:
        val = s->regs.cur_color0;
    case CUR_CLR0 ... CUR_CLR0 + 3:
        val = ati_reg_read_offs(s->regs.cur_color0, addr - CUR_CLR0, size);
        break;
    case CUR_CLR1:
        val = s->regs.cur_color1;
    case CUR_CLR1 ... CUR_CLR1 + 3:
        val = ati_reg_read_offs(s->regs.cur_color1, addr - CUR_CLR1, size);
        break;
    case DST_OFFSET:
        val = s->regs.dst_offset;
@@ -679,48 +690,71 @@ static void ati_mm_write(void *opaque, hwaddr addr,
    case 0xf00 ... 0xfff:
        /* read-only copy of PCI config space so ignore writes */
        break;
    case CUR_OFFSET:
        if (s->regs.cur_offset != (data & 0x87fffff0)) {
            s->regs.cur_offset = data & 0x87fffff0;
    case CUR_OFFSET ... CUR_OFFSET + 3:
    {
        uint32_t t = s->regs.cur_offset;

        ati_reg_write_offs(&t, addr - CUR_OFFSET, data, size);
        t &= 0x87fffff0;
        if (s->regs.cur_offset != t) {
            s->regs.cur_offset = t;
            ati_cursor_define(s);
        }
        break;
    case CUR_HORZ_VERT_POSN:
        s->regs.cur_hv_pos = data & 0x3fff0fff;
        if (data & BIT(31)) {
            s->regs.cur_offset |= data & BIT(31);
    }
    case CUR_HORZ_VERT_POSN ... CUR_HORZ_VERT_POSN + 3:
    {
        uint32_t t = s->regs.cur_hv_pos | (s->regs.cur_offset & BIT(31));

        ati_reg_write_offs(&t, addr - CUR_HORZ_VERT_POSN, data, size);
        s->regs.cur_hv_pos = t & 0x3fff0fff;
        if (t & BIT(31)) {
            s->regs.cur_offset |= t & BIT(31);
        } else if (s->regs.cur_offset & BIT(31)) {
            s->regs.cur_offset &= ~BIT(31);
            ati_cursor_define(s);
        }
        if (!s->cursor_guest_mode &&
            (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) && !(data & BIT(31))) {
            (s->regs.crtc_gen_cntl & CRTC2_CUR_EN) && !(t & BIT(31))) {
            dpy_mouse_set(s->vga.con, s->regs.cur_hv_pos >> 16,
                          s->regs.cur_hv_pos & 0xffff, 1);
        }
        break;
    }
    case CUR_HORZ_VERT_OFF:
        s->regs.cur_hv_offs = data & 0x3f003f;
        if (data & BIT(31)) {
            s->regs.cur_offset |= data & BIT(31);
    {
        uint32_t t = s->regs.cur_hv_offs | (s->regs.cur_offset & BIT(31));

        ati_reg_write_offs(&t, addr - CUR_HORZ_VERT_OFF, data, size);
        s->regs.cur_hv_offs = t & 0x3f003f;
        if (t & BIT(31)) {
            s->regs.cur_offset |= t & BIT(31);
        } else if (s->regs.cur_offset & BIT(31)) {
            s->regs.cur_offset &= ~BIT(31);
            ati_cursor_define(s);
        }
        break;
    case CUR_CLR0:
        if (s->regs.cur_color0 != (data & 0xffffff)) {
            s->regs.cur_color0 = data & 0xffffff;
    }
    case CUR_CLR0 ... CUR_CLR0 + 3:
    {
        uint32_t t = s->regs.cur_color0;

        ati_reg_write_offs(&t, addr - CUR_CLR0, data, size);
        t &= 0xffffff;
        if (s->regs.cur_color0 != t) {
            s->regs.cur_color0 = t;
            ati_cursor_define(s);
        }
        break;
    case CUR_CLR1:
    }
    case CUR_CLR1 ... CUR_CLR1 + 3:
        /*
         * Update cursor unconditionally here because some clients set up
         * other registers before actually writing cursor data to memory at
         * offset so we would miss cursor change unless always updating here
         */
        s->regs.cur_color1 = data & 0xffffff;
        ati_reg_write_offs(&s->regs.cur_color1, addr - CUR_CLR1, data, size);
        s->regs.cur_color1 &= 0xffffff;
        ati_cursor_define(s);
        break;
    case DST_OFFSET:
+1 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ static struct ati_regdesc ati_reg_names[] = {
    {"MC_FB_LOCATION", 0x0148},
    {"MC_AGP_LOCATION", 0x014C},
    {"MC_STATUS", 0x0150},
    {"MEM_SDRAM_MODE_REG", 0x0158},
    {"MEM_POWER_MISC", 0x015c},
    {"AGP_BASE", 0x0170},
    {"AGP_CNTL", 0x0174},
+1 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@
#define MC_FB_LOCATION                          0x0148
#define MC_AGP_LOCATION                         0x014C
#define MC_STATUS                               0x0150
#define MEM_SDRAM_MODE_REG                      0x0158
#define MEM_POWER_MISC                          0x015c
#define AGP_BASE                                0x0170
#define AGP_CNTL                                0x0174
+75 −82
Original line number Diff line number Diff line
@@ -39,15 +39,7 @@
#include "qemu/range.h"
#include "ui/pixel_ops.h"
#include "qemu/bswap.h"

/*#define DEBUG_SM501*/
/*#define DEBUG_BITBLT*/

#ifdef DEBUG_SM501
#define SM501_DPRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
#else
#define SM501_DPRINTF(fmt, ...) do {} while (0)
#endif
#include "trace.h"

#define MMIO_BASE_OFFSET 0x3e00000
#define MMIO_SIZE 0x200000
@@ -684,10 +676,11 @@ static void sm501_2d_operation(SM501State *s)
{
    int cmd = (s->twoD_control >> 16) & 0x1F;
    int rtl = s->twoD_control & BIT(27);
    int format = (s->twoD_stretch >> 20) & 0x3;
    int rop_mode = (s->twoD_control >> 15) & 0x1; /* 1 for rop2, else rop3 */
    int format = (s->twoD_stretch >> 20) & 3;
    int bypp = 1 << format; /* bytes per pixel */
    int rop_mode = (s->twoD_control >> 15) & 1; /* 1 for rop2, else rop3 */
    /* 1 if rop2 source is the pattern, otherwise the source is the bitmap */
    int rop2_source_is_pattern = (s->twoD_control >> 14) & 0x1;
    int rop2_source_is_pattern = (s->twoD_control >> 14) & 1;
    int rop = s->twoD_control & 0xFF;
    unsigned int dst_x = (s->twoD_destination >> 16) & 0x01FFF;
    unsigned int dst_y = s->twoD_destination & 0xFFFF;
@@ -697,6 +690,7 @@ static void sm501_2d_operation(SM501State *s)
    unsigned int dst_pitch = (s->twoD_pitch >> 16) & 0x1FFF;
    int crt = (s->dc_crt_control & SM501_DC_CRT_CONTROL_SEL) ? 1 : 0;
    int fb_len = get_width(s, crt) * get_height(s, crt) * get_bpp(s, crt);
    bool overlap = false;

    if ((s->twoD_stretch >> 16) & 0xF) {
        qemu_log_mask(LOG_UNIMP, "sm501: only XY addressing is supported.\n");
@@ -723,9 +717,9 @@ static void sm501_2d_operation(SM501State *s)
        dst_y -= height - 1;
    }

    if (dst_base >= get_local_mem_size(s) || dst_base +
        (dst_x + width + (dst_y + height) * (dst_pitch + width)) *
        (1 << format) >= get_local_mem_size(s)) {
    if (dst_base >= get_local_mem_size(s) ||
        dst_base + (dst_x + width + (dst_y + height) * dst_pitch) * bypp >=
        get_local_mem_size(s)) {
        qemu_log_mask(LOG_GUEST_ERROR, "sm501: 2D op dest is outside vram.\n");
        return;
    }
@@ -749,9 +743,9 @@ static void sm501_2d_operation(SM501State *s)
            src_y -= height - 1;
        }

        if (src_base >= get_local_mem_size(s) || src_base +
            (src_x + width + (src_y + height) * (src_pitch + width)) *
            (1 << format) >= get_local_mem_size(s)) {
        if (src_base >= get_local_mem_size(s) ||
            src_base + (src_x + width + (src_y + height) * src_pitch) * bypp >=
            get_local_mem_size(s)) {
            qemu_log_mask(LOG_GUEST_ERROR,
                          "sm501: 2D op src is outside vram.\n");
            return;
@@ -763,19 +757,9 @@ static void sm501_2d_operation(SM501State *s)
            uint8_t *d = s->local_mem + dst_base;

            for (y = 0; y < height; y++) {
                i = (dst_x + (dst_y + y) * dst_pitch) * (1 << format);
                for (x = 0; x < width; x++, i += (1 << format)) {
                    switch (format) {
                    case 0:
                        d[i] = ~d[i];
                        break;
                    case 1:
                        *(uint16_t *)&d[i] = ~*(uint16_t *)&d[i];
                        break;
                    case 2:
                        *(uint32_t *)&d[i] = ~*(uint32_t *)&d[i];
                        break;
                    }
                i = (dst_x + (dst_y + y) * dst_pitch) * bypp;
                for (x = 0; x < width; x++, i += bypp) {
                    stn_he_p(&d[i], bypp, ~ldn_he_p(&d[i], bypp));
                }
            }
        } else {
@@ -788,40 +772,57 @@ static void sm501_2d_operation(SM501State *s)
                              (rop2_source_is_pattern ?
                                  " with pattern source" : ""));
            }
            /* Check for overlaps, this could be made more exact */
            uint32_t sb, se, db, de;
            sb = src_base + src_x + src_y * (width + src_pitch);
            se = sb + width + height * (width + src_pitch);
            db = dst_base + dst_x + dst_y * (width + dst_pitch);
            de = db + width + height * (width + dst_pitch);
            if (rtl && ((db >= sb && db <= se) || (de >= sb && de <= se))) {
                /* regions may overlap: copy via temporary */
                int free_buf = 0, llb = width * (1 << format);
                int tmp_stride = DIV_ROUND_UP(llb, sizeof(uint32_t));
            /* Ignore no-op blits, some guests seem to do this */
            if (src_base == dst_base && src_pitch == dst_pitch &&
                src_x == dst_x && src_y == dst_y) {
                break;
            }
            /* Some clients also do 1 pixel blits, avoid overhead for these */
            if (width == 1 && height == 1) {
                unsigned int si = (src_x + src_y * src_pitch) * bypp;
                unsigned int di = (dst_x + dst_y * dst_pitch) * bypp;
                stn_he_p(&s->local_mem[dst_base + di], bypp,
                         ldn_he_p(&s->local_mem[src_base + si], bypp));
                break;
            }
            /* If reverse blit do simple check for overlaps */
            if (rtl && src_base == dst_base && src_pitch == dst_pitch) {
                overlap = (src_x < dst_x + width && src_x + width > dst_x &&
                           src_y < dst_y + height && src_y + height > dst_y);
            } else if (rtl) {
                unsigned int sb, se, db, de;
                sb = src_base + (src_x + src_y * src_pitch) * bypp;
                se = sb + (width + (height - 1) * src_pitch) * bypp;
                db = dst_base + (dst_x + dst_y * dst_pitch) * bypp;
                de = db + (width + (height - 1) * dst_pitch) * bypp;
                overlap = (db < se && sb < de);
            }
            if (overlap) {
                /* pixman can't do reverse blit: copy via temporary */
                int tmp_stride = DIV_ROUND_UP(width * bypp, sizeof(uint32_t));
                uint32_t *tmp = tmp_buf;

                if (tmp_stride * sizeof(uint32_t) * height > sizeof(tmp_buf)) {
                    tmp = g_malloc(tmp_stride * sizeof(uint32_t) * height);
                    free_buf = 1;
                }
                pixman_blt((uint32_t *)&s->local_mem[src_base], tmp,
                           src_pitch * (1 << format) / sizeof(uint32_t),
                           tmp_stride, 8 * (1 << format), 8 * (1 << format),
                           src_pitch * bypp / sizeof(uint32_t),
                           tmp_stride, 8 * bypp, 8 * bypp,
                           src_x, src_y, 0, 0, width, height);
                pixman_blt(tmp, (uint32_t *)&s->local_mem[dst_base],
                           tmp_stride,
                           dst_pitch * (1 << format) / sizeof(uint32_t),
                           8 * (1 << format), 8 * (1 << format),
                           dst_pitch * bypp / sizeof(uint32_t),
                           8 * bypp, 8 * bypp,
                           0, 0, dst_x, dst_y, width, height);
                if (free_buf) {
                if (tmp != tmp_buf) {
                    g_free(tmp);
                }
            } else {
                pixman_blt((uint32_t *)&s->local_mem[src_base],
                           (uint32_t *)&s->local_mem[dst_base],
                           src_pitch * (1 << format) / sizeof(uint32_t),
                           dst_pitch * (1 << format) / sizeof(uint32_t),
                           8 * (1 << format), 8 * (1 << format),
                           src_pitch * bypp / sizeof(uint32_t),
                           dst_pitch * bypp / sizeof(uint32_t),
                           8 * bypp, 8 * bypp,
                           src_x, src_y, dst_x, dst_y, width, height);
            }
        }
@@ -837,9 +838,14 @@ static void sm501_2d_operation(SM501State *s)
            color = cpu_to_le16(color);
        }

        if (width == 1 && height == 1) {
            unsigned int i = (dst_x + dst_y * dst_pitch) * bypp;
            stn_he_p(&s->local_mem[dst_base + i], bypp, color);
        } else {
            pixman_fill((uint32_t *)&s->local_mem[dst_base],
                    dst_pitch * (1 << format) / sizeof(uint32_t),
                    8 * (1 << format), dst_x, dst_y, width, height, color);
                        dst_pitch * bypp / sizeof(uint32_t),
                        8 * bypp, dst_x, dst_y, width, height, color);
        }
        break;
    }
    default:
@@ -851,7 +857,7 @@ static void sm501_2d_operation(SM501State *s)
    if (dst_base >= get_fb_addr(s, crt) &&
        dst_base <= get_fb_addr(s, crt) + fb_len) {
        int dst_len = MIN(fb_len, ((dst_y + height - 1) * dst_pitch +
                          dst_x + width) * (1 << format));
                          dst_x + width) * bypp);
        if (dst_len) {
            memory_region_set_dirty(&s->local_mem_region, dst_base, dst_len);
        }
@@ -863,7 +869,6 @@ static uint64_t sm501_system_config_read(void *opaque, hwaddr addr,
{
    SM501State *s = (SM501State *)opaque;
    uint32_t ret = 0;
    SM501_DPRINTF("sm501 system config regs : read addr=%x\n", (int)addr);

    switch (addr) {
    case SM501_SYSTEM_CONTROL:
@@ -915,7 +920,7 @@ static uint64_t sm501_system_config_read(void *opaque, hwaddr addr,
        qemu_log_mask(LOG_UNIMP, "sm501: not implemented system config"
                      "register read. addr=%" HWADDR_PRIx "\n", addr);
    }

    trace_sm501_system_config_read(addr, ret);
    return ret;
}

@@ -923,9 +928,8 @@ static void sm501_system_config_write(void *opaque, hwaddr addr,
                                      uint64_t value, unsigned size)
{
    SM501State *s = (SM501State *)opaque;
    SM501_DPRINTF("sm501 system config regs : write addr=%x, val=%x\n",
                  (uint32_t)addr, (uint32_t)value);

    trace_sm501_system_config_write((uint32_t)addr, (uint32_t)value);
    switch (addr) {
    case SM501_SYSTEM_CONTROL:
        s->system_control &= 0x10DB0000;
@@ -1011,9 +1015,7 @@ static uint64_t sm501_i2c_read(void *opaque, hwaddr addr, unsigned size)
        qemu_log_mask(LOG_UNIMP, "sm501 i2c : not implemented register read."
                      " addr=0x%" HWADDR_PRIx "\n", addr);
    }

    SM501_DPRINTF("sm501 i2c regs : read addr=%" HWADDR_PRIx " val=%x\n",
                  addr, ret);
    trace_sm501_i2c_read((uint32_t)addr, ret);
    return ret;
}

@@ -1021,9 +1023,8 @@ static void sm501_i2c_write(void *opaque, hwaddr addr, uint64_t value,
                            unsigned size)
{
    SM501State *s = (SM501State *)opaque;
    SM501_DPRINTF("sm501 i2c regs : write addr=%" HWADDR_PRIx
                  " val=%" PRIx64 "\n", addr, value);

    trace_sm501_i2c_write((uint32_t)addr, (uint32_t)value);
    switch (addr) {
    case SM501_I2C_BYTE_COUNT:
        s->i2c_byte_count = value & 0xf;
@@ -1037,25 +1038,19 @@ static void sm501_i2c_write(void *opaque, hwaddr addr, uint64_t value,
                s->i2c_status |= (res ? SM501_I2C_STATUS_ERROR : 0);
                if (!res) {
                    int i;
                    SM501_DPRINTF("sm501 i2c : transferring %d bytes to 0x%x\n",
                                  s->i2c_byte_count + 1, s->i2c_addr >> 1);
                    for (i = 0; i <= s->i2c_byte_count; i++) {
                        res = i2c_send_recv(s->i2c_bus, &s->i2c_data[i],
                                            !(s->i2c_addr & 1));
                        if (res) {
                            SM501_DPRINTF("sm501 i2c : transfer failed"
                                          " i=%d, res=%d\n", i, res);
                            s->i2c_status |= SM501_I2C_STATUS_ERROR;
                            return;
                        }
                    }
                    if (i) {
                        SM501_DPRINTF("sm501 i2c : transferred %d bytes\n", i);
                        s->i2c_status = SM501_I2C_STATUS_COMPLETE;
                    }
                }
            } else {
                SM501_DPRINTF("sm501 i2c : end transfer\n");
                i2c_end_transfer(s->i2c_bus);
                s->i2c_status &= ~SM501_I2C_STATUS_ERROR;
            }
@@ -1095,7 +1090,8 @@ static const MemoryRegionOps sm501_i2c_ops = {
static uint32_t sm501_palette_read(void *opaque, hwaddr addr)
{
    SM501State *s = (SM501State *)opaque;
    SM501_DPRINTF("sm501 palette read addr=%x\n", (int)addr);

    trace_sm501_palette_read((uint32_t)addr);

    /* TODO : consider BYTE/WORD access */
    /* TODO : consider endian */
@@ -1108,8 +1104,8 @@ static void sm501_palette_write(void *opaque, hwaddr addr,
                                uint32_t value)
{
    SM501State *s = (SM501State *)opaque;
    SM501_DPRINTF("sm501 palette write addr=%x, val=%x\n",
                  (int)addr, value);

    trace_sm501_palette_write((uint32_t)addr, value);

    /* TODO : consider BYTE/WORD access */
    /* TODO : consider endian */
@@ -1124,7 +1120,6 @@ static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr,
{
    SM501State *s = (SM501State *)opaque;
    uint32_t ret = 0;
    SM501_DPRINTF("sm501 disp ctrl regs : read addr=%x\n", (int)addr);

    switch (addr) {

@@ -1229,7 +1224,7 @@ static uint64_t sm501_disp_ctrl_read(void *opaque, hwaddr addr,
        qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register "
                      "read. addr=%" HWADDR_PRIx "\n", addr);
    }

    trace_sm501_disp_ctrl_read((uint32_t)addr, ret);
    return ret;
}

@@ -1237,9 +1232,8 @@ static void sm501_disp_ctrl_write(void *opaque, hwaddr addr,
                                  uint64_t value, unsigned size)
{
    SM501State *s = (SM501State *)opaque;
    SM501_DPRINTF("sm501 disp ctrl regs : write addr=%x, val=%x\n",
                  (unsigned)addr, (unsigned)value);

    trace_sm501_disp_ctrl_write((uint32_t)addr, (uint32_t)value);
    switch (addr) {
    case SM501_DC_PANEL_CONTROL:
        s->dc_panel_control = value & 0x0FFF73FF;
@@ -1384,7 +1378,6 @@ static uint64_t sm501_2d_engine_read(void *opaque, hwaddr addr,
{
    SM501State *s = (SM501State *)opaque;
    uint32_t ret = 0;
    SM501_DPRINTF("sm501 2d engine regs : read addr=%x\n", (int)addr);

    switch (addr) {
    case SM501_2D_SOURCE:
@@ -1454,7 +1447,7 @@ static uint64_t sm501_2d_engine_read(void *opaque, hwaddr addr,
        qemu_log_mask(LOG_UNIMP, "sm501: not implemented disp ctrl register "
                      "read. addr=%" HWADDR_PRIx "\n", addr);
    }

    trace_sm501_2d_engine_read((uint32_t)addr, ret);
    return ret;
}

@@ -1462,9 +1455,8 @@ static void sm501_2d_engine_write(void *opaque, hwaddr addr,
                                  uint64_t value, unsigned size)
{
    SM501State *s = (SM501State *)opaque;
    SM501_DPRINTF("sm501 2d engine regs : write addr=%x, val=%x\n",
                  (unsigned)addr, (unsigned)value);

    trace_sm501_2d_engine_write((uint32_t)addr, (uint32_t)value);
    switch (addr) {
    case SM501_2D_SOURCE:
        s->twoD_source = value;
@@ -1495,6 +1487,9 @@ static void sm501_2d_engine_write(void *opaque, hwaddr addr,
        s->twoD_background = value;
        break;
    case SM501_2D_STRETCH:
        if (((value >> 20) & 3) == 3) {
            value &= ~BIT(20);
        }
        s->twoD_stretch = value;
        break;
    case SM501_2D_COLOR_COMPARE:
@@ -1819,8 +1814,6 @@ static void sm501_init(SM501State *s, DeviceState *dev,
                       uint32_t local_mem_bytes)
{
    s->local_mem_size_index = get_local_mem_size_index(local_mem_bytes);
    SM501_DPRINTF("sm501 local mem size=%x. index=%d\n", get_local_mem_size(s),
                  s->local_mem_size_index);

    /* local memory */
    memory_region_init_ram(&s->local_mem_region, OBJECT(dev), "sm501.local",
Loading