Fixes and updates for hppa target
This patchset fixes some important bugs in the hppa artist graphics driver: - Fix artist graphics for HP-UX and Linux - Mouse cursor fixes for HP-UX - Fix draw_line() function on artist graphic and it adds new qemu features for hppa: - Allow up to 16 emulated CPUs (instead of 8) - Add support for an emulated TOC/NMI button A new Seabios-hppa firmware is included as well: - Update SeaBIOS-hppa to VERSION 3 - New opt/hostid fw_cfg option to change hostid - Add opt/console fw_cfg option to select default console - Added 16x32 font to STI firmware Signed-off-by: Helge Deller <deller@gmx.de> -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQS86RI+GtKfB8BJu973ErUQojoPXwUCYfrIogAKCRD3ErUQojoP X93ZAP9hqp/FCz/goH7Tpqce6FspHriJm6Ej2Rd7HxZWmh4bpQD/cMjY8qpcA/6r Nx4bgRPT6kCZwwLx7v2jZ2QsA2KaZAM= =c0qO -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/hdeller/tags/hppa-updates-pull-request' into staging Fixes and updates for hppa target This patchset fixes some important bugs in the hppa artist graphics driver: - Fix artist graphics for HP-UX and Linux - Mouse cursor fixes for HP-UX - Fix draw_line() function on artist graphic and it adds new qemu features for hppa: - Allow up to 16 emulated CPUs (instead of 8) - Add support for an emulated TOC/NMI button A new Seabios-hppa firmware is included as well: - Update SeaBIOS-hppa to VERSION 3 - New opt/hostid fw_cfg option to change hostid - Add opt/console fw_cfg option to select default console - Added 16x32 font to STI firmware Signed-off-by: Helge Deller <deller@gmx.de> # gpg: Signature made Wed 02 Feb 2022 18:08:34 GMT # gpg: using EDDSA key BCE9123E1AD29F07C049BBDEF712B510A23A0F5F # gpg: Good signature from "Helge Deller <deller@gmx.de>" [unknown] # gpg: aka "Helge Deller <deller@kernel.org>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 4544 8228 2CD9 10DB EF3D 25F8 3E5F 3D04 A7A2 4603 # Subkey fingerprint: BCE9 123E 1AD2 9F07 C049 BBDE F712 B510 A23A 0F5F * remotes/hdeller/tags/hppa-updates-pull-request: hw/display/artist: Fix draw_line() artefacts hw/display/artist: Mouse cursor fixes for HP-UX hw/display/artist: rewrite vram access mode handling hppa: Add support for an emulated TOC/NMI button. hw/hppa: Allow up to 16 emulated CPUs seabios-hppa: Update SeaBIOS-hppa to VERSION 3 Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
8f3e5ce773
|
@ -80,6 +80,7 @@ struct ARTISTState {
|
||||||
uint32_t line_pattern_skip;
|
uint32_t line_pattern_skip;
|
||||||
|
|
||||||
uint32_t cursor_pos;
|
uint32_t cursor_pos;
|
||||||
|
uint32_t cursor_cntrl;
|
||||||
|
|
||||||
uint32_t cursor_height;
|
uint32_t cursor_height;
|
||||||
uint32_t cursor_width;
|
uint32_t cursor_width;
|
||||||
|
@ -91,7 +92,6 @@ struct ARTISTState {
|
||||||
uint32_t reg_300208;
|
uint32_t reg_300208;
|
||||||
uint32_t reg_300218;
|
uint32_t reg_300218;
|
||||||
|
|
||||||
uint32_t cmap_bm_access;
|
|
||||||
uint32_t dst_bm_access;
|
uint32_t dst_bm_access;
|
||||||
uint32_t src_bm_access;
|
uint32_t src_bm_access;
|
||||||
uint32_t control_plane;
|
uint32_t control_plane;
|
||||||
|
@ -134,7 +134,7 @@ typedef enum {
|
||||||
PATTERN_LINE_START = 0x100ecc,
|
PATTERN_LINE_START = 0x100ecc,
|
||||||
LINE_SIZE = 0x100e04,
|
LINE_SIZE = 0x100e04,
|
||||||
LINE_END = 0x100e44,
|
LINE_END = 0x100e44,
|
||||||
CMAP_BM_ACCESS = 0x118000,
|
DST_SRC_BM_ACCESS = 0x118000,
|
||||||
DST_BM_ACCESS = 0x118004,
|
DST_BM_ACCESS = 0x118004,
|
||||||
SRC_BM_ACCESS = 0x118008,
|
SRC_BM_ACCESS = 0x118008,
|
||||||
CONTROL_PLANE = 0x11800c,
|
CONTROL_PLANE = 0x11800c,
|
||||||
|
@ -176,7 +176,7 @@ static const char *artist_reg_name(uint64_t addr)
|
||||||
REG_NAME(TRANSFER_DATA);
|
REG_NAME(TRANSFER_DATA);
|
||||||
REG_NAME(CONTROL_PLANE);
|
REG_NAME(CONTROL_PLANE);
|
||||||
REG_NAME(IMAGE_BITMAP_OP);
|
REG_NAME(IMAGE_BITMAP_OP);
|
||||||
REG_NAME(CMAP_BM_ACCESS);
|
REG_NAME(DST_SRC_BM_ACCESS);
|
||||||
REG_NAME(DST_BM_ACCESS);
|
REG_NAME(DST_BM_ACCESS);
|
||||||
REG_NAME(SRC_BM_ACCESS);
|
REG_NAME(SRC_BM_ACCESS);
|
||||||
REG_NAME(CURSOR_POS);
|
REG_NAME(CURSOR_POS);
|
||||||
|
@ -222,40 +222,14 @@ static void artist_invalidate_lines(struct vram_buffer *buf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vram_write_pix_per_transfer(ARTISTState *s)
|
|
||||||
{
|
|
||||||
if (s->cmap_bm_access) {
|
|
||||||
return 1 << ((s->cmap_bm_access >> 27) & 0x0f);
|
|
||||||
} else {
|
|
||||||
return 1 << ((s->dst_bm_access >> 27) & 0x0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vram_pixel_length(ARTISTState *s)
|
|
||||||
{
|
|
||||||
if (s->cmap_bm_access) {
|
|
||||||
return (s->cmap_bm_access >> 24) & 0x07;
|
|
||||||
} else {
|
|
||||||
return (s->dst_bm_access >> 24) & 0x07;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int vram_write_bufidx(ARTISTState *s)
|
static int vram_write_bufidx(ARTISTState *s)
|
||||||
{
|
{
|
||||||
if (s->cmap_bm_access) {
|
return (s->dst_bm_access >> 12) & 0x0f;
|
||||||
return (s->cmap_bm_access >> 12) & 0x0f;
|
|
||||||
} else {
|
|
||||||
return (s->dst_bm_access >> 12) & 0x0f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vram_read_bufidx(ARTISTState *s)
|
static int vram_read_bufidx(ARTISTState *s)
|
||||||
{
|
{
|
||||||
if (s->cmap_bm_access) {
|
return (s->src_bm_access >> 12) & 0x0f;
|
||||||
return (s->cmap_bm_access >> 12) & 0x0f;
|
|
||||||
} else {
|
|
||||||
return (s->src_bm_access >> 12) & 0x0f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct vram_buffer *vram_read_buffer(ARTISTState *s)
|
static struct vram_buffer *vram_read_buffer(ARTISTState *s)
|
||||||
|
@ -328,19 +302,42 @@ static void artist_get_cursor_pos(ARTISTState *s, int *x, int *y)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Don't know whether these magic offset values are configurable via
|
* Don't know whether these magic offset values are configurable via
|
||||||
* some register. They are the same for all resolutions, so don't
|
* some register. They seem to be the same for all resolutions.
|
||||||
* bother about it.
|
* The cursor values provided in the registers are:
|
||||||
|
* X-value: -295 (for HP-UX 11) and 338 (for HP-UX 10.20) up to 2265
|
||||||
|
* Y-value: 1146 down to 0
|
||||||
|
* The emulated Artist graphic is like a CRX graphic, and as such
|
||||||
|
* it's usually fixed at 1280x1024 pixels.
|
||||||
|
* Because of the maximum Y-value of 1146 you can not choose a higher
|
||||||
|
* vertical resolution on HP-UX (unless you disable the mouse).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
*y = 0x47a - artist_get_y(s->cursor_pos);
|
static int offset = 338;
|
||||||
*x = ((artist_get_x(s->cursor_pos) - 338) / 2);
|
int lx;
|
||||||
|
|
||||||
|
/* ignore if uninitialized */
|
||||||
|
if (s->cursor_pos == 0) {
|
||||||
|
*x = *y = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lx = artist_get_x(s->cursor_pos);
|
||||||
|
if (lx < offset)
|
||||||
|
offset = lx;
|
||||||
|
*x = (lx - offset) / 2;
|
||||||
|
|
||||||
|
*y = 1146 - artist_get_y(s->cursor_pos);
|
||||||
|
|
||||||
|
/* subtract cursor offset from cursor control register */
|
||||||
|
*x -= (s->cursor_cntrl & 0xf0) >> 4;
|
||||||
|
*y -= (s->cursor_cntrl & 0x0f);
|
||||||
|
|
||||||
if (*x > s->width) {
|
if (*x > s->width) {
|
||||||
*x = 0;
|
*x = s->width;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*y > s->height) {
|
if (*y > s->height) {
|
||||||
*y = 0;
|
*y = s->height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,130 +349,6 @@ static void artist_invalidate_cursor(ARTISTState *s)
|
||||||
y, s->cursor_height);
|
y, s->cursor_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 posx, offset, width;
|
|
||||||
uint8_t *data8, *p;
|
|
||||||
|
|
||||||
pix_count = vram_write_pix_per_transfer(s);
|
|
||||||
pix_length = vram_pixel_length(s);
|
|
||||||
|
|
||||||
buf = vram_write_buffer(s);
|
|
||||||
width = buf->width;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!buf->size || offset >= buf->size) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = buf->data;
|
|
||||||
|
|
||||||
if (pix_count > size * 8) {
|
|
||||||
pix_count = size * 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (pix_length) {
|
|
||||||
case 0:
|
|
||||||
if (s->image_bitmap_op & 0x20000000) {
|
|
||||||
data &= vram_bitmask;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < pix_count; i++) {
|
|
||||||
uint32_t off = offset + pix_count - 1 - i;
|
|
||||||
if (off < buf->size) {
|
|
||||||
artist_rop8(s, buf, off,
|
|
||||||
(data & 1) ? (s->plane_mask >> 24) : 0);
|
|
||||||
}
|
|
||||||
data >>= 1;
|
|
||||||
}
|
|
||||||
memory_region_set_dirty(&buf->mr, offset, pix_count);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
if (s->cmap_bm_access) {
|
|
||||||
if (offset + 3 < buf->size) {
|
|
||||||
*(uint32_t *)(p + offset) = data;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
data8 = (uint8_t *)&data;
|
|
||||||
|
|
||||||
for (i = 3; i >= 0; i--) {
|
|
||||||
if (!(s->image_bitmap_op & 0x20000000) ||
|
|
||||||
s->vram_bitmask & (1 << (28 + i))) {
|
|
||||||
uint32_t off = offset + 3 - i;
|
|
||||||
if (off < buf->size) {
|
|
||||||
artist_rop8(s, buf, off, data8[ROP8OFF(i)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memory_region_set_dirty(&buf->mr, offset, 3);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
switch (size) {
|
|
||||||
default:
|
|
||||||
case 4:
|
|
||||||
vram_bitmask = s->vram_bitmask;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
vram_bitmask = s->vram_bitmask >> 16;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
vram_bitmask = s->vram_bitmask >> 24;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < pix_count && offset + i < buf->size; i++) {
|
|
||||||
mask = 1 << (pix_count - 1 - i);
|
|
||||||
|
|
||||||
if (!(s->image_bitmap_op & 0x20000000) ||
|
|
||||||
(vram_bitmask & mask)) {
|
|
||||||
if (data & mask) {
|
|
||||||
artist_rop8(s, buf, offset + i, s->fg_color);
|
|
||||||
} else {
|
|
||||||
if (!(s->image_bitmap_op & 0x10000002)) {
|
|
||||||
artist_rop8(s, buf, offset + i, s->bg_color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memory_region_set_dirty(&buf->mr, offset, pix_count);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
qemu_log_mask(LOG_UNIMP, "%s: unknown pixel length %d\n",
|
|
||||||
__func__, pix_length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (incr_x) {
|
|
||||||
if (s->cmap_bm_access) {
|
|
||||||
s->vram_pos += 4;
|
|
||||||
} else {
|
|
||||||
s->vram_pos += pix_count << 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vram_write_bufidx(s) == ARTIST_BUFFER_CURSOR1 ||
|
|
||||||
vram_write_bufidx(s) == ARTIST_BUFFER_CURSOR2) {
|
|
||||||
artist_invalidate_cursor(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void block_move(ARTISTState *s,
|
static void block_move(ARTISTState *s,
|
||||||
unsigned int source_x, unsigned int source_y,
|
unsigned int source_x, unsigned int source_y,
|
||||||
unsigned int dest_x, unsigned int dest_y,
|
unsigned int dest_x, unsigned int dest_y,
|
||||||
|
@ -680,10 +553,11 @@ static void draw_line(ARTISTState *s,
|
||||||
}
|
}
|
||||||
x++;
|
x++;
|
||||||
} while (x <= x2 && (max_pix == -1 || --max_pix > 0));
|
} while (x <= x2 && (max_pix == -1 || --max_pix > 0));
|
||||||
|
|
||||||
if (c1)
|
if (c1)
|
||||||
artist_invalidate_lines(buf, x, dy+1);
|
artist_invalidate_lines(buf, x1, x2 - x1);
|
||||||
else
|
else
|
||||||
artist_invalidate_lines(buf, y, dx+1);
|
artist_invalidate_lines(buf, y1 > y2 ? y2 : y1, x2 - x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_line_pattern_start(ARTISTState *s)
|
static void draw_line_pattern_start(ARTISTState *s)
|
||||||
|
@ -860,6 +734,151 @@ static void combine_write_reg(hwaddr addr, uint64_t val, int size, void *out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void artist_vram_write4(ARTISTState *s, struct vram_buffer *buf,
|
||||||
|
uint32_t offset, uint32_t data)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int mask = s->vram_bitmask >> 28;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
if (!(s->image_bitmap_op & 0x20000000) || (mask & 8)) {
|
||||||
|
artist_rop8(s, buf, offset + i, data >> 24);
|
||||||
|
data <<= 8;
|
||||||
|
mask <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memory_region_set_dirty(&buf->mr, offset, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void artist_vram_write32(ARTISTState *s, struct vram_buffer *buf,
|
||||||
|
uint32_t offset, int size, uint32_t data,
|
||||||
|
int fg, int bg)
|
||||||
|
{
|
||||||
|
uint32_t mask, vram_bitmask = s->vram_bitmask >> ((4 - size) * 8);
|
||||||
|
int i, pix_count = size * 8;
|
||||||
|
|
||||||
|
for (i = 0; i < pix_count && offset + i < buf->size; i++) {
|
||||||
|
mask = 1 << (pix_count - 1 - i);
|
||||||
|
|
||||||
|
if (!(s->image_bitmap_op & 0x20000000) || (vram_bitmask & mask)) {
|
||||||
|
if (data & mask) {
|
||||||
|
artist_rop8(s, buf, offset + i, fg);
|
||||||
|
} else {
|
||||||
|
if (!(s->image_bitmap_op & 0x10000002)) {
|
||||||
|
artist_rop8(s, buf, offset + i, bg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memory_region_set_dirty(&buf->mr, offset, pix_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_vram_offset(ARTISTState *s, struct vram_buffer *buf,
|
||||||
|
int pos, int posy)
|
||||||
|
{
|
||||||
|
unsigned int posx, width;
|
||||||
|
|
||||||
|
width = buf->width;
|
||||||
|
posx = ADDR_TO_X(pos);
|
||||||
|
posy += ADDR_TO_Y(pos);
|
||||||
|
return posy * width + posx;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vram_bit_write(ARTISTState *s, uint32_t pos, int posy,
|
||||||
|
uint32_t data, int size)
|
||||||
|
{
|
||||||
|
struct vram_buffer *buf = vram_write_buffer(s);
|
||||||
|
|
||||||
|
switch (s->dst_bm_access >> 16) {
|
||||||
|
case 0x3ba0:
|
||||||
|
case 0xbbe0:
|
||||||
|
artist_vram_write4(s, buf, pos, bswap32(data));
|
||||||
|
pos += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1360: /* linux */
|
||||||
|
artist_vram_write4(s, buf, get_vram_offset(s, buf, pos, posy), data);
|
||||||
|
pos += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x13a0:
|
||||||
|
artist_vram_write4(s, buf, get_vram_offset(s, buf, pos >> 2, posy),
|
||||||
|
data);
|
||||||
|
pos += 16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x2ea0:
|
||||||
|
artist_vram_write32(s, buf, get_vram_offset(s, buf, pos >> 2, posy),
|
||||||
|
size, data, s->fg_color, s->bg_color);
|
||||||
|
pos += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x28a0:
|
||||||
|
artist_vram_write32(s, buf, get_vram_offset(s, buf, pos >> 2, posy),
|
||||||
|
size, data, 1, 0);
|
||||||
|
pos += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
qemu_log_mask(LOG_UNIMP, "%s: unknown dst bm access %08x\n",
|
||||||
|
__func__, s->dst_bm_access);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vram_write_bufidx(s) == ARTIST_BUFFER_CURSOR1 ||
|
||||||
|
vram_write_bufidx(s) == ARTIST_BUFFER_CURSOR2) {
|
||||||
|
artist_invalidate_cursor(s);
|
||||||
|
}
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val,
|
||||||
|
unsigned size)
|
||||||
|
{
|
||||||
|
ARTISTState *s = opaque;
|
||||||
|
s->vram_char_y = 0;
|
||||||
|
trace_artist_vram_write(size, addr, val);
|
||||||
|
vram_bit_write(opaque, addr, 0, val, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t artist_vram_read(void *opaque, hwaddr addr, unsigned size)
|
||||||
|
{
|
||||||
|
ARTISTState *s = opaque;
|
||||||
|
struct vram_buffer *buf;
|
||||||
|
unsigned int offset;
|
||||||
|
uint64_t val;
|
||||||
|
|
||||||
|
buf = vram_read_buffer(s);
|
||||||
|
if (!buf->size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = get_vram_offset(s, buf, addr >> 2, 0);
|
||||||
|
|
||||||
|
if (offset > buf->size) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (s->src_bm_access >> 16) {
|
||||||
|
case 0x3ba0:
|
||||||
|
val = *(uint32_t *)(buf->data + offset);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x13a0:
|
||||||
|
case 0x2ea0:
|
||||||
|
val = bswap32(*(uint32_t *)(buf->data + offset));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
qemu_log_mask(LOG_UNIMP, "%s: unknown src bm access %08x\n",
|
||||||
|
__func__, s->dst_bm_access);
|
||||||
|
val = -1ULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
trace_artist_vram_read(size, addr, val);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
static void artist_reg_write(void *opaque, hwaddr addr, uint64_t val,
|
static void artist_reg_write(void *opaque, hwaddr addr, uint64_t val,
|
||||||
unsigned size)
|
unsigned size)
|
||||||
{
|
{
|
||||||
|
@ -886,12 +905,12 @@ static void artist_reg_write(void *opaque, hwaddr addr, uint64_t val,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VRAM_WRITE_INCR_Y:
|
case VRAM_WRITE_INCR_Y:
|
||||||
vram_bit_write(s, s->vram_char_y++, false, size, val);
|
vram_bit_write(s, s->vram_pos, s->vram_char_y++, val, size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VRAM_WRITE_INCR_X:
|
case VRAM_WRITE_INCR_X:
|
||||||
case VRAM_WRITE_INCR_X2:
|
case VRAM_WRITE_INCR_X2:
|
||||||
vram_bit_write(s, s->vram_char_y, true, size, val);
|
s->vram_pos = vram_bit_write(s, s->vram_pos, s->vram_char_y, val, size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VRAM_IDX:
|
case VRAM_IDX:
|
||||||
|
@ -993,18 +1012,17 @@ static void artist_reg_write(void *opaque, hwaddr addr, uint64_t val,
|
||||||
combine_write_reg(addr, val, size, &s->plane_mask);
|
combine_write_reg(addr, val, size, &s->plane_mask);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMAP_BM_ACCESS:
|
case DST_SRC_BM_ACCESS:
|
||||||
combine_write_reg(addr, val, size, &s->cmap_bm_access);
|
combine_write_reg(addr, val, size, &s->dst_bm_access);
|
||||||
|
combine_write_reg(addr, val, size, &s->src_bm_access);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DST_BM_ACCESS:
|
case DST_BM_ACCESS:
|
||||||
combine_write_reg(addr, val, size, &s->dst_bm_access);
|
combine_write_reg(addr, val, size, &s->dst_bm_access);
|
||||||
s->cmap_bm_access = 0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SRC_BM_ACCESS:
|
case SRC_BM_ACCESS:
|
||||||
combine_write_reg(addr, val, size, &s->src_bm_access);
|
combine_write_reg(addr, val, size, &s->src_bm_access);
|
||||||
s->cmap_bm_access = 0;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CONTROL_PLANE:
|
case CONTROL_PLANE:
|
||||||
|
@ -1034,6 +1052,7 @@ static void artist_reg_write(void *opaque, hwaddr addr, uint64_t val,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CURSOR_CTRL:
|
case CURSOR_CTRL:
|
||||||
|
combine_write_reg(addr, val, size, &s->cursor_cntrl);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IMAGE_BITMAP_OP:
|
case IMAGE_BITMAP_OP:
|
||||||
|
@ -1152,98 +1171,6 @@ static uint64_t artist_reg_read(void *opaque, hwaddr addr, unsigned size)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val,
|
|
||||||
unsigned size)
|
|
||||||
{
|
|
||||||
ARTISTState *s = opaque;
|
|
||||||
struct vram_buffer *buf;
|
|
||||||
unsigned int posy, posx;
|
|
||||||
unsigned int offset;
|
|
||||||
trace_artist_vram_write(size, addr, val);
|
|
||||||
|
|
||||||
if (s->cmap_bm_access) {
|
|
||||||
buf = &s->vram_buffer[ARTIST_BUFFER_CMAP];
|
|
||||||
if (addr + 3 < buf->size) {
|
|
||||||
*(uint32_t *)(buf->data + addr) = val;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = vram_write_buffer(s);
|
|
||||||
posy = ADDR_TO_Y(addr >> 2);
|
|
||||||
posx = ADDR_TO_X(addr >> 2);
|
|
||||||
|
|
||||||
if (!buf->size) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (posy > buf->height || posx > buf->width) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = posy * buf->width + posx;
|
|
||||||
if (offset >= buf->size) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (size) {
|
|
||||||
case 4:
|
|
||||||
if (offset + 3 < buf->size) {
|
|
||||||
*(uint32_t *)(buf->data + offset) = be32_to_cpu(val);
|
|
||||||
memory_region_set_dirty(&buf->mr, offset, 4);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
if (offset + 1 < buf->size) {
|
|
||||||
*(uint16_t *)(buf->data + offset) = be16_to_cpu(val);
|
|
||||||
memory_region_set_dirty(&buf->mr, offset, 2);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if (offset < buf->size) {
|
|
||||||
*(uint8_t *)(buf->data + offset) = val;
|
|
||||||
memory_region_set_dirty(&buf->mr, offset, 1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t artist_vram_read(void *opaque, hwaddr addr, unsigned size)
|
|
||||||
{
|
|
||||||
ARTISTState *s = opaque;
|
|
||||||
struct vram_buffer *buf;
|
|
||||||
uint64_t val;
|
|
||||||
unsigned int posy, posx;
|
|
||||||
|
|
||||||
if (s->cmap_bm_access) {
|
|
||||||
buf = &s->vram_buffer[ARTIST_BUFFER_CMAP];
|
|
||||||
val = 0;
|
|
||||||
if (addr < buf->size && addr + 3 < buf->size) {
|
|
||||||
val = *(uint32_t *)(buf->data + addr);
|
|
||||||
}
|
|
||||||
trace_artist_vram_read(size, addr, 0, 0, val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = vram_read_buffer(s);
|
|
||||||
if (!buf->size) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
posy = ADDR_TO_Y(addr >> 2);
|
|
||||||
posx = ADDR_TO_X(addr >> 2);
|
|
||||||
|
|
||||||
if (posy > buf->height || posx > buf->width) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
val = cpu_to_be32(*(uint32_t *)(buf->data + posy * buf->width + posx));
|
|
||||||
trace_artist_vram_read(size, addr, posx, posy, val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const MemoryRegionOps artist_reg_ops = {
|
static const MemoryRegionOps artist_reg_ops = {
|
||||||
.read = artist_reg_read,
|
.read = artist_reg_read,
|
||||||
.write = artist_reg_write,
|
.write = artist_reg_write,
|
||||||
|
@ -1410,6 +1337,14 @@ static void artist_realizefn(DeviceState *dev, Error **errp)
|
||||||
s->cursor_height = 32;
|
s->cursor_height = 32;
|
||||||
s->cursor_width = 32;
|
s->cursor_width = 32;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These two registers are not initialized by seabios's STI implementation.
|
||||||
|
* Initialize them here to sane values so artist also works with older
|
||||||
|
* (not-fixed) seabios versions.
|
||||||
|
*/
|
||||||
|
s->image_bitmap_op = 0x23000300;
|
||||||
|
s->plane_mask = 0xff;
|
||||||
|
|
||||||
s->con = graphic_console_init(dev, 0, &artist_ops, s);
|
s->con = graphic_console_init(dev, 0, &artist_ops, s);
|
||||||
qemu_console_resize(s->con, s->width, s->height);
|
qemu_console_resize(s->con, s->width, s->height);
|
||||||
}
|
}
|
||||||
|
@ -1422,8 +1357,8 @@ static int vmstate_artist_post_load(void *opaque, int version_id)
|
||||||
|
|
||||||
static const VMStateDescription vmstate_artist = {
|
static const VMStateDescription vmstate_artist = {
|
||||||
.name = "artist",
|
.name = "artist",
|
||||||
.version_id = 1,
|
.version_id = 2,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 2,
|
||||||
.post_load = vmstate_artist_post_load,
|
.post_load = vmstate_artist_post_load,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_UINT16(height, ARTISTState),
|
VMSTATE_UINT16(height, ARTISTState),
|
||||||
|
@ -1443,6 +1378,7 @@ static const VMStateDescription vmstate_artist = {
|
||||||
VMSTATE_UINT32(line_end, ARTISTState),
|
VMSTATE_UINT32(line_end, ARTISTState),
|
||||||
VMSTATE_UINT32(line_xy, ARTISTState),
|
VMSTATE_UINT32(line_xy, ARTISTState),
|
||||||
VMSTATE_UINT32(cursor_pos, ARTISTState),
|
VMSTATE_UINT32(cursor_pos, ARTISTState),
|
||||||
|
VMSTATE_UINT32(cursor_cntrl, ARTISTState),
|
||||||
VMSTATE_UINT32(cursor_height, ARTISTState),
|
VMSTATE_UINT32(cursor_height, ARTISTState),
|
||||||
VMSTATE_UINT32(cursor_width, ARTISTState),
|
VMSTATE_UINT32(cursor_width, ARTISTState),
|
||||||
VMSTATE_UINT32(plane_mask, ARTISTState),
|
VMSTATE_UINT32(plane_mask, ARTISTState),
|
||||||
|
@ -1450,7 +1386,6 @@ static const VMStateDescription vmstate_artist = {
|
||||||
VMSTATE_UINT32(reg_300200, ARTISTState),
|
VMSTATE_UINT32(reg_300200, ARTISTState),
|
||||||
VMSTATE_UINT32(reg_300208, ARTISTState),
|
VMSTATE_UINT32(reg_300208, ARTISTState),
|
||||||
VMSTATE_UINT32(reg_300218, ARTISTState),
|
VMSTATE_UINT32(reg_300218, ARTISTState),
|
||||||
VMSTATE_UINT32(cmap_bm_access, ARTISTState),
|
|
||||||
VMSTATE_UINT32(dst_bm_access, ARTISTState),
|
VMSTATE_UINT32(dst_bm_access, ARTISTState),
|
||||||
VMSTATE_UINT32(src_bm_access, ARTISTState),
|
VMSTATE_UINT32(src_bm_access, ARTISTState),
|
||||||
VMSTATE_UINT32(control_plane, ARTISTState),
|
VMSTATE_UINT32(control_plane, ARTISTState),
|
||||||
|
|
|
@ -140,10 +140,10 @@ ati_mm_read(unsigned int size, uint64_t addr, const char *name, uint64_t val) "%
|
||||||
ati_mm_write(unsigned int size, uint64_t addr, const char *name, uint64_t val) "%u 0x%"PRIx64 " %s <- 0x%"PRIx64
|
ati_mm_write(unsigned int size, uint64_t addr, const char *name, uint64_t val) "%u 0x%"PRIx64 " %s <- 0x%"PRIx64
|
||||||
|
|
||||||
# artist.c
|
# artist.c
|
||||||
artist_reg_read(unsigned int size, uint64_t addr, const char *name, uint64_t val) "%u 0x%"PRIx64 "%s -> 0x%"PRIx64
|
artist_reg_read(unsigned int size, uint64_t addr, const char *name, uint64_t val) "%u 0x%"PRIx64 "%s -> 0x%08"PRIx64
|
||||||
artist_reg_write(unsigned int size, uint64_t addr, const char *name, uint64_t val) "%u 0x%"PRIx64 "%s <- 0x%"PRIx64
|
artist_reg_write(unsigned int size, uint64_t addr, const char *name, uint64_t val) "%u 0x%"PRIx64 "%s <- 0x%08"PRIx64
|
||||||
artist_vram_read(unsigned int size, uint64_t addr, int posx, int posy, uint64_t val) "%u 0x%"PRIx64 " %ux%u-> 0x%"PRIx64
|
artist_vram_read(unsigned int size, uint64_t addr, uint64_t val) "%u 0x%08"PRIx64 " -> 0x%08"PRIx64
|
||||||
artist_vram_write(unsigned int size, uint64_t addr, uint64_t val) "%u 0x%"PRIx64 " <- 0x%"PRIx64
|
artist_vram_write(unsigned int size, uint64_t addr, uint64_t val) "%u 0x%08"PRIx64 " <- 0x%08"PRIx64
|
||||||
artist_fill_window(unsigned int start_x, unsigned int start_y, unsigned int width, unsigned int height, uint32_t op, uint32_t ctlpln) "start=%ux%u length=%ux%u op=0x%08x ctlpln=0x%08x"
|
artist_fill_window(unsigned int start_x, unsigned int start_y, unsigned int width, unsigned int height, uint32_t op, uint32_t ctlpln) "start=%ux%u length=%ux%u op=0x%08x ctlpln=0x%08x"
|
||||||
artist_block_move(unsigned int start_x, unsigned int start_y, unsigned int dest_x, unsigned int dest_y, unsigned int width, unsigned int height) "source %ux%u -> dest %ux%u size %ux%u"
|
artist_block_move(unsigned int start_x, unsigned int start_y, unsigned int dest_x, unsigned int dest_y, unsigned int width, unsigned int height) "source %ux%u -> dest %ux%u size %ux%u"
|
||||||
artist_draw_line(unsigned int start_x, unsigned int start_y, unsigned int end_x, unsigned int end_y) "%ux%u %ux%u"
|
artist_draw_line(unsigned int start_x, unsigned int start_y, unsigned int end_x, unsigned int end_y) "%ux%u %ux%u"
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
#define LASI_GFX_HPA 0xf8000000
|
#define LASI_GFX_HPA 0xf8000000
|
||||||
#define ARTIST_FB_ADDR 0xf9000000
|
#define ARTIST_FB_ADDR 0xf9000000
|
||||||
#define CPU_HPA 0xfffb0000
|
#define CPU_HPA 0xfffb0000
|
||||||
#define MEMORY_HPA 0xfffbf000
|
#define MEMORY_HPA 0xfffff000
|
||||||
|
|
||||||
#define PCI_HPA DINO_HPA /* PCI bus */
|
#define PCI_HPA DINO_HPA /* PCI bus */
|
||||||
#define IDE_HPA 0xf9000000 /* Boot disc controller */
|
#define IDE_HPA 0xf9000000 /* Boot disc controller */
|
||||||
|
@ -43,9 +43,10 @@
|
||||||
#define PORT_SERIAL1 (DINO_UART_HPA + 0x800)
|
#define PORT_SERIAL1 (DINO_UART_HPA + 0x800)
|
||||||
#define PORT_SERIAL2 (LASI_UART_HPA + 0x800)
|
#define PORT_SERIAL2 (LASI_UART_HPA + 0x800)
|
||||||
|
|
||||||
#define HPPA_MAX_CPUS 8 /* max. number of SMP CPUs */
|
#define HPPA_MAX_CPUS 16 /* max. number of SMP CPUs */
|
||||||
#define CPU_CLOCK_MHZ 250 /* emulate a 250 MHz CPU */
|
#define CPU_CLOCK_MHZ 250 /* emulate a 250 MHz CPU */
|
||||||
|
|
||||||
#define CPU_HPA_CR_REG 7 /* store CPU HPA in cr7 (SeaBIOS internal) */
|
#define CPU_HPA_CR_REG 7 /* store CPU HPA in cr7 (SeaBIOS internal) */
|
||||||
|
#define PIM_STORAGE_SIZE 600 /* storage size of pdc_pim_toc_struct (64bit) */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "hw/timer/i8254.h"
|
#include "hw/timer/i8254.h"
|
||||||
#include "hw/char/serial.h"
|
#include "hw/char/serial.h"
|
||||||
#include "hw/net/lasi_82596.h"
|
#include "hw/net/lasi_82596.h"
|
||||||
|
#include "hw/nmi.h"
|
||||||
#include "hppa_sys.h"
|
#include "hppa_sys.h"
|
||||||
#include "qemu/units.h"
|
#include "qemu/units.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
@ -355,6 +356,14 @@ static void hppa_machine_reset(MachineState *ms)
|
||||||
cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
|
cpu[0]->env.gr[19] = FW_CFG_IO_BASE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hppa_nmi(NMIState *n, int cpu_index, Error **errp)
|
||||||
|
{
|
||||||
|
CPUState *cs;
|
||||||
|
|
||||||
|
CPU_FOREACH(cs) {
|
||||||
|
cpu_interrupt(cs, CPU_INTERRUPT_NMI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void machine_hppa_machine_init(MachineClass *mc)
|
static void machine_hppa_machine_init(MachineClass *mc)
|
||||||
{
|
{
|
||||||
|
@ -371,4 +380,28 @@ static void machine_hppa_machine_init(MachineClass *mc)
|
||||||
mc->default_ram_id = "ram";
|
mc->default_ram_id = "ram";
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_MACHINE("hppa", machine_hppa_machine_init)
|
static void machine_hppa_machine_init_class_init(ObjectClass *oc, void *data)
|
||||||
|
{
|
||||||
|
MachineClass *mc = MACHINE_CLASS(oc);
|
||||||
|
machine_hppa_machine_init(mc);
|
||||||
|
|
||||||
|
NMIClass *nc = NMI_CLASS(oc);
|
||||||
|
nc->nmi_monitor_handler = hppa_nmi;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const TypeInfo machine_hppa_machine_init_typeinfo = {
|
||||||
|
.name = ("hppa" "-machine"),
|
||||||
|
.parent = "machine",
|
||||||
|
.class_init = machine_hppa_machine_init_class_init,
|
||||||
|
.interfaces = (InterfaceInfo[]) {
|
||||||
|
{ TYPE_NMI },
|
||||||
|
{ }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void machine_hppa_machine_init_register_types(void)
|
||||||
|
{
|
||||||
|
type_register_static(&machine_hppa_machine_init_typeinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
type_init(machine_hppa_machine_init_register_types)
|
||||||
|
|
Binary file not shown.
|
@ -1 +1 @@
|
||||||
Subproject commit b12acac4be27b6d5d9fbe48c4be1286dcc245fbb
|
Subproject commit bf3404006fd2c832857eb57e6f853862f97dacea
|
|
@ -62,7 +62,7 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
|
||||||
|
|
||||||
static bool hppa_cpu_has_work(CPUState *cs)
|
static bool hppa_cpu_has_work(CPUState *cs)
|
||||||
{
|
{
|
||||||
return cs->interrupt_request & CPU_INTERRUPT_HARD;
|
return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info)
|
static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info)
|
||||||
|
|
|
@ -69,6 +69,11 @@
|
||||||
#define EXCP_SYSCALL 30
|
#define EXCP_SYSCALL 30
|
||||||
#define EXCP_SYSCALL_LWS 31
|
#define EXCP_SYSCALL_LWS 31
|
||||||
|
|
||||||
|
/* Emulated hardware TOC button */
|
||||||
|
#define EXCP_TOC 32 /* TOC = Transfer of control (NMI) */
|
||||||
|
|
||||||
|
#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3 /* TOC */
|
||||||
|
|
||||||
/* Taken from Linux kernel: arch/parisc/include/asm/psw.h */
|
/* Taken from Linux kernel: arch/parisc/include/asm/psw.h */
|
||||||
#define PSW_I 0x00000001
|
#define PSW_I 0x00000001
|
||||||
#define PSW_D 0x00000002
|
#define PSW_D 0x00000002
|
||||||
|
|
|
@ -80,6 +80,7 @@ DEF_HELPER_FLAGS_0(read_interval_timer, TCG_CALL_NO_RWG, tr)
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
DEF_HELPER_1(halt, noreturn, env)
|
DEF_HELPER_1(halt, noreturn, env)
|
||||||
DEF_HELPER_1(reset, noreturn, env)
|
DEF_HELPER_1(reset, noreturn, env)
|
||||||
|
DEF_HELPER_1(getshadowregs, void, env)
|
||||||
DEF_HELPER_1(rfi, void, env)
|
DEF_HELPER_1(rfi, void, env)
|
||||||
DEF_HELPER_1(rfi_r, void, env)
|
DEF_HELPER_1(rfi_r, void, env)
|
||||||
DEF_HELPER_FLAGS_2(write_interval_timer, TCG_CALL_NO_RWG, void, env, tr)
|
DEF_HELPER_FLAGS_2(write_interval_timer, TCG_CALL_NO_RWG, void, env, tr)
|
||||||
|
|
|
@ -111,6 +111,7 @@ rfi_r 000000 ----- ----- --- 01100101 00000
|
||||||
# They are allocated from the unassigned instruction space.
|
# They are allocated from the unassigned instruction space.
|
||||||
halt 1111 1111 1111 1101 1110 1010 1101 0000
|
halt 1111 1111 1111 1101 1110 1010 1101 0000
|
||||||
reset 1111 1111 1111 1101 1110 1010 1101 0001
|
reset 1111 1111 1111 1101 1110 1010 1101 0001
|
||||||
|
getshadowregs 1111 1111 1111 1101 1110 1010 1101 0010
|
||||||
|
|
||||||
####
|
####
|
||||||
# Memory Management
|
# Memory Management
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
#include "hw/core/cpu.h"
|
#include "hw/core/cpu.h"
|
||||||
|
#include "hw/hppa/hppa_hardware.h"
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
static void eval_interrupt(HPPACPU *cpu)
|
static void eval_interrupt(HPPACPU *cpu)
|
||||||
|
@ -181,7 +182,14 @@ void hppa_cpu_do_interrupt(CPUState *cs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* step 7 */
|
/* step 7 */
|
||||||
env->iaoq_f = env->cr[CR_IVA] + 32 * i;
|
if (i == EXCP_TOC) {
|
||||||
|
env->iaoq_f = FIRMWARE_START;
|
||||||
|
/* help SeaBIOS and provide iaoq_b and iasq_back in shadow regs */
|
||||||
|
env->gr[24] = env->cr_back[0];
|
||||||
|
env->gr[25] = env->cr_back[1];
|
||||||
|
} else {
|
||||||
|
env->iaoq_f = env->cr[CR_IVA] + 32 * i;
|
||||||
|
}
|
||||||
env->iaoq_b = env->iaoq_f + 4;
|
env->iaoq_b = env->iaoq_f + 4;
|
||||||
env->iasq_f = 0;
|
env->iasq_f = 0;
|
||||||
env->iasq_b = 0;
|
env->iasq_b = 0;
|
||||||
|
@ -219,6 +227,7 @@ void hppa_cpu_do_interrupt(CPUState *cs)
|
||||||
[EXCP_PER_INTERRUPT] = "performance monitor interrupt",
|
[EXCP_PER_INTERRUPT] = "performance monitor interrupt",
|
||||||
[EXCP_SYSCALL] = "syscall",
|
[EXCP_SYSCALL] = "syscall",
|
||||||
[EXCP_SYSCALL_LWS] = "syscall-lws",
|
[EXCP_SYSCALL_LWS] = "syscall-lws",
|
||||||
|
[EXCP_TOC] = "TOC (transfer of control)",
|
||||||
};
|
};
|
||||||
static int count;
|
static int count;
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
|
@ -248,6 +257,14 @@ bool hppa_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||||
HPPACPU *cpu = HPPA_CPU(cs);
|
HPPACPU *cpu = HPPA_CPU(cs);
|
||||||
CPUHPPAState *env = &cpu->env;
|
CPUHPPAState *env = &cpu->env;
|
||||||
|
|
||||||
|
if (interrupt_request & CPU_INTERRUPT_NMI) {
|
||||||
|
/* Raise TOC (NMI) interrupt */
|
||||||
|
cpu_reset_interrupt(cs, CPU_INTERRUPT_NMI);
|
||||||
|
cs->exception_index = EXCP_TOC;
|
||||||
|
hppa_cpu_do_interrupt(cs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* If interrupts are requested and enabled, raise them. */
|
/* If interrupts are requested and enabled, raise them. */
|
||||||
if ((env->psw & PSW_I) && (interrupt_request & CPU_INTERRUPT_HARD)) {
|
if ((env->psw & PSW_I) && (interrupt_request & CPU_INTERRUPT_HARD)) {
|
||||||
cs->exception_index = EXCP_EXT_INTERRUPT;
|
cs->exception_index = EXCP_EXT_INTERRUPT;
|
||||||
|
|
|
@ -694,7 +694,7 @@ void HELPER(rfi)(CPUHPPAState *env)
|
||||||
cpu_hppa_put_psw(env, env->cr[CR_IPSW]);
|
cpu_hppa_put_psw(env, env->cr[CR_IPSW]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HELPER(rfi_r)(CPUHPPAState *env)
|
void HELPER(getshadowregs)(CPUHPPAState *env)
|
||||||
{
|
{
|
||||||
env->gr[1] = env->shadow[0];
|
env->gr[1] = env->shadow[0];
|
||||||
env->gr[8] = env->shadow[1];
|
env->gr[8] = env->shadow[1];
|
||||||
|
@ -703,6 +703,11 @@ void HELPER(rfi_r)(CPUHPPAState *env)
|
||||||
env->gr[17] = env->shadow[4];
|
env->gr[17] = env->shadow[4];
|
||||||
env->gr[24] = env->shadow[5];
|
env->gr[24] = env->shadow[5];
|
||||||
env->gr[25] = env->shadow[6];
|
env->gr[25] = env->shadow[6];
|
||||||
|
}
|
||||||
|
|
||||||
|
void HELPER(rfi_r)(CPUHPPAState *env)
|
||||||
|
{
|
||||||
|
helper_getshadowregs(env);
|
||||||
helper_rfi(env);
|
helper_rfi(env);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2393,6 +2393,16 @@ static bool trans_reset(DisasContext *ctx, arg_reset *a)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool trans_getshadowregs(DisasContext *ctx, arg_getshadowregs *a)
|
||||||
|
{
|
||||||
|
CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR);
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
nullify_over(ctx);
|
||||||
|
gen_helper_getshadowregs(cpu_env);
|
||||||
|
return nullify_end(ctx);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static bool trans_nop_addrx(DisasContext *ctx, arg_ldst *a)
|
static bool trans_nop_addrx(DisasContext *ctx, arg_ldst *a)
|
||||||
{
|
{
|
||||||
if (a->m) {
|
if (a->m) {
|
||||||
|
|
Loading…
Reference in New Issue