1 /*
2 * Copyright © 2021 Google, Inc.
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include <assert.h>
7 #include <ctype.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10
11 #include "emu.h"
12 #include "util.h"
13
14 /*
15 * Emulation for draw-state (ie. CP_SET_DRAW_STATE) related control registers:
16 */
17
18 EMU_CONTROL_REG(DRAW_STATE_SET_HDR);
19 EMU_CONTROL_REG(DRAW_STATE_SEL);
20 EMU_CONTROL_REG(DRAW_STATE_ACTIVE_BITMASK);
21 EMU_CONTROL_REG(DRAW_STATE_HDR);
22 EMU_CONTROL_REG(DRAW_STATE_BASE);
23 EMU_CONTROL_REG(SDS_BASE);
24 EMU_CONTROL_REG(SDS_DWORDS);
25
26 uint32_t
emu_get_draw_state_reg(struct emu * emu,unsigned n)27 emu_get_draw_state_reg(struct emu *emu, unsigned n)
28 {
29 // TODO maybe we don't need to do anything here
30 return emu->control_regs.val[n];
31 }
32
33 void
emu_set_draw_state_base(struct emu * emu,unsigned n,uint32_t val)34 emu_set_draw_state_base(struct emu *emu, unsigned n, uint32_t val)
35 {
36 struct emu_draw_state *ds = &emu->draw_state;
37
38 unsigned cur_idx = (emu_get_reg32(emu, &DRAW_STATE_SET_HDR) >> 24) & 0x1f;
39 ds->state[cur_idx].base_lohi[n] = val;
40 }
41
42 void
emu_set_draw_state_reg(struct emu * emu,unsigned n,uint32_t val)43 emu_set_draw_state_reg(struct emu *emu, unsigned n, uint32_t val)
44 {
45 struct emu_draw_state *ds = &emu->draw_state;
46 unsigned cur_idx = emu_get_reg32(emu, &DRAW_STATE_SEL);
47
48 if (n == emu_reg_offset(&DRAW_STATE_SET_HDR)) {
49 cur_idx = (val >> 24) & 0x1f;
50 ds->state[cur_idx].count = val & 0xffff;
51 ds->state[cur_idx].mode_mask = (val >> 20) & 0x7;
52
53 unsigned active_mask = emu_get_reg32(emu, &DRAW_STATE_ACTIVE_BITMASK);
54 active_mask |= (1 << cur_idx);
55
56 emu_set_reg32(emu, &DRAW_STATE_ACTIVE_BITMASK, active_mask);
57 } else if (n == emu_reg_offset(&DRAW_STATE_SEL)) {
58 emu_set_reg32(emu, &DRAW_STATE_HDR, ds->state[val].hdr);
59 emu_set_reg64(emu, &DRAW_STATE_BASE, ds->state[val].base);
60
61 /* It seems that SDS_BASE/SDS_DWORDS is also per draw-state group,
62 * and that when a new state-group is selected, SQE compares to
63 * the previous values to new DRAW_STATE_BASE & count to detect
64 * that new state has been appended to existing draw-state group:
65 */
66 unsigned prev_idx = ds->prev_draw_state_sel;
67 ds->state[prev_idx].sds_base = emu_get_reg64(emu, &SDS_BASE);
68 ds->state[prev_idx].sds_dwords = emu_get_reg32(emu, &SDS_DWORDS);
69
70 emu_set_reg64(emu, &SDS_BASE, ds->state[val].sds_base);
71 emu_set_reg32(emu, &SDS_DWORDS, ds->state[val].sds_dwords);
72
73 ds->prev_draw_state_sel = val;
74 }
75 }
76