mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-03-11 02:40:39 +01:00
freedreno: Rename afuc to QRisc
In [1] the AQE is called the "Application QRisc Engine." Thus the real
name of afuc is QRisc. Rename everything.
[1] a698ebd321
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40287>
This commit is contained in:
parent
554eec159b
commit
6e3d805735
26 changed files with 248 additions and 250 deletions
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2021 Google, Inc.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef _UTIL_H_
|
||||
#define _UTIL_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* AFUC disasm / asm helpers
|
||||
*/
|
||||
|
||||
unsigned afuc_control_reg(const char *name);
|
||||
char * afuc_control_reg_name(unsigned id);
|
||||
|
||||
unsigned afuc_sqe_reg(const char *name);
|
||||
char * afuc_sqe_reg_name(unsigned id);
|
||||
|
||||
unsigned afuc_pipe_reg(const char *name);
|
||||
char * afuc_pipe_reg_name(unsigned id);
|
||||
bool afuc_pipe_reg_is_void(unsigned id);
|
||||
|
||||
unsigned afuc_gpu_reg(const char *name);
|
||||
char * afuc_gpu_reg_name(unsigned id);
|
||||
|
||||
unsigned afuc_gpr_reg(const char *name);
|
||||
|
||||
int afuc_pm4_id(const char *name);
|
||||
const char * afuc_pm_id_name(unsigned id);
|
||||
|
||||
enum afuc_color {
|
||||
AFUC_ERR,
|
||||
AFUC_LBL,
|
||||
};
|
||||
|
||||
void afuc_printc(enum afuc_color c, const char *fmt, ...);
|
||||
|
||||
enum afuc_fwid {
|
||||
AFUC_A730 = 0x730,
|
||||
AFUC_A740 = 0x740,
|
||||
AFUC_GEN70500 = 0x512,
|
||||
AFUC_A750 = 0x520,
|
||||
|
||||
AFUC_A630 = 0x6ee,
|
||||
AFUC_A650 = 0x6dc,
|
||||
AFUC_A660 = 0x6dd,
|
||||
|
||||
AFUC_A530 = 0x5ff,
|
||||
};
|
||||
|
||||
static inline enum afuc_fwid
|
||||
afuc_get_fwid(uint32_t first_dword)
|
||||
{
|
||||
/* The firmware ID is in bits 12-24 of the first dword */
|
||||
return (first_dword >> 12) & 0xfff;
|
||||
}
|
||||
|
||||
int afuc_util_init(enum afuc_fwid fw_id, int *gpuver, bool colors);
|
||||
|
||||
#endif /* _UTIL_H_ */
|
||||
|
|
@ -40,7 +40,7 @@ endif
|
|||
if dep_libxml2.found() and with_tools.contains('freedreno')
|
||||
subdir('rnn')
|
||||
subdir('decode')
|
||||
subdir('afuc')
|
||||
subdir('qrisc')
|
||||
elif with_tools.contains('freedreno')
|
||||
message('libxml2 not found, skipping tools that depend on it')
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
=====================
|
||||
Adreno Five Microcode
|
||||
QRisc Microcode
|
||||
=====================
|
||||
|
||||
.. contents::
|
||||
|
||||
.. _afuc-introduction:
|
||||
.. _qrisc-introduction:
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
|
@ -30,9 +30,7 @@ Starting with Adreno 5xx, a new microcontroller with a unified
|
|||
instruction set was introduced, although the overall architecture
|
||||
and purpose of the two microcontrollers remains the same.
|
||||
|
||||
For lack of a better name, this new instruction set is called
|
||||
"Adreno Five MicroCode" or "afuc". (No idea what Qualcomm calls
|
||||
it internally).
|
||||
This new instruction set is called "QRisc".
|
||||
|
||||
With Adreno 6xx, the separate PFP and ME are replaced with a single
|
||||
SQE microcontroller using the same instruction set as 5xx.
|
||||
|
|
@ -45,12 +43,12 @@ booting LPAC. On 7xx, to implement concurrent binning the SQE is split into two
|
|||
processors called BR and BV. Again, the firmware for all three is bundled
|
||||
together and BR is responsible for booting both BV and LPAC.
|
||||
|
||||
.. _afuc-overview:
|
||||
.. _qrisc-overview:
|
||||
|
||||
Instruction Set Overview
|
||||
========================
|
||||
|
||||
The afuc instruction set is heavily inspired by MIPS, but not exactly
|
||||
The QRisc instruction set is heavily inspired by MIPS, but not exactly
|
||||
compatible.
|
||||
|
||||
Registers
|
||||
|
|
@ -71,12 +69,12 @@ Unlike in MIPS, there is a special small hardware-managed stack and special
|
|||
instructions ``call``/``ret`` which use it. The stack only contains return
|
||||
addresses, there is no "stack frame" to spill values to. As a result, ``$sp``,
|
||||
``$fp``, and ``$ra`` don't exist as on MIPS. Instead the last 3 registers are
|
||||
used to :ref:`afuc-read<read>` from various queues and
|
||||
:ref:`afuc-reg-writes<write GPU registers>`. In addition there is a ``$rem``
|
||||
used to :ref:`qrisc-read<read>` from various queues and
|
||||
:ref:`qrisc-reg-writes<write GPU registers>`. In addition there is a ``$rem``
|
||||
register which normally contains the number of words remaining in the packet
|
||||
but can also be used as a normal register in combination with the rep prefix.
|
||||
|
||||
.. _afuc-alu:
|
||||
.. _qrisc-alu:
|
||||
|
||||
ALU Instructions
|
||||
================
|
||||
|
|
@ -119,7 +117,7 @@ instruction that can shift the 16-bit immediate by a given amount::
|
|||
This replaces ``lui`` on MIPS (just use a shift of 16) while also allowing the
|
||||
quick construction of small bitfields, which comes in handy in various places.
|
||||
|
||||
.. _afuc-alu-cmp:
|
||||
.. _qrisc-alu-cmp:
|
||||
|
||||
The ``cmp`` instruction returns:
|
||||
|
||||
|
|
@ -127,10 +125,10 @@ The ``cmp`` instruction returns:
|
|||
- ``0x2b`` if src1 == src2
|
||||
- ``0x1e`` if src1 < src2
|
||||
|
||||
See explanation in :ref:`afuc-branch`
|
||||
See explanation in :ref:`qrisc-branch`
|
||||
|
||||
|
||||
.. _afuc-branch:
|
||||
.. _qrisc-branch:
|
||||
|
||||
Branch Instructions
|
||||
===================
|
||||
|
|
@ -151,7 +149,7 @@ The branch instructions are encoded with a 16b relative offset.
|
|||
Since ``$00`` always reads back zero, it can be used to construct
|
||||
an unconditional relative jump.
|
||||
|
||||
The :ref:`cmp <afuc-alu-cmp>` instruction can be paired with the
|
||||
The :ref:`cmp <qrisc-alu-cmp>` instruction can be paired with the
|
||||
bit-test variants of ``brne``/``breq`` to implement gt/ge/lt/le,
|
||||
due to the bit pattern it returns, for example::
|
||||
|
||||
|
|
@ -186,7 +184,7 @@ requires two delay slots::
|
|||
b #bar
|
||||
nop ; b delay slot
|
||||
|
||||
In afuc this only requires a delay slot for the second branch::
|
||||
In QRisc this only requires a delay slot for the second branch::
|
||||
|
||||
breq $02, 0x1, #foo
|
||||
brne $02, 0x1, #bar
|
||||
|
|
@ -196,7 +194,7 @@ Note that for the second branch we had to use a conditional branch with the
|
|||
opposite condition instead of an unconditional branch as in the MIPS example,
|
||||
to guarantee that at most one is ever taken.
|
||||
|
||||
.. _afuc-call:
|
||||
.. _qrisc-call:
|
||||
|
||||
Call/Return
|
||||
===========
|
||||
|
|
@ -209,12 +207,12 @@ jump instruction encodes a fixed offset from the SQE instruction base.
|
|||
levels of fxn call, see in PFP: CP_CONTEXT_SWITCH_YIELD -> f13 ->
|
||||
f22.
|
||||
|
||||
.. _afuc-nop:
|
||||
.. _qrisc-nop:
|
||||
|
||||
NOPs
|
||||
====
|
||||
|
||||
Afuc has a special NOP encoding where the low 24 bits are ignored by the
|
||||
QRisc has a special NOP encoding where the low 24 bits are ignored by the
|
||||
processor. On a5xx the high 8 bits are ``00``, on a6xx they are ``01``
|
||||
(probably to make sure that 0 is not a legal instruction, increasing the
|
||||
chances of halting immediately when something is misconfigured). This is used
|
||||
|
|
@ -223,7 +221,7 @@ first 2 instructions of the firmware typically contain the firmware ID and
|
|||
version followed by the packet handling table offset encoded as NOPs. They are
|
||||
skipped when executed but they are later read as data by the bootstrap routine.
|
||||
|
||||
.. _afuc-control:
|
||||
.. _qrisc-control:
|
||||
|
||||
Control Registers
|
||||
=================
|
||||
|
|
@ -289,7 +287,7 @@ but on a6xx::
|
|||
cwrite $0b, [$05 + @IB1_BASE+0x1]
|
||||
cwrite $04, [$05 + @IB1_DWORDS]
|
||||
|
||||
.. _afuc-sqe-regs:
|
||||
.. _qrisc-sqe-regs:
|
||||
|
||||
SQE Registers
|
||||
=============
|
||||
|
|
@ -300,7 +298,7 @@ through ``sread``/``swrite`` instructions that work identically to
|
|||
``call``/``ret`` stack. This is mainly used during the preemption routine but
|
||||
it's also used to set the entrypoint for preemption.
|
||||
|
||||
.. _afuc-read:
|
||||
.. _qrisc-read:
|
||||
|
||||
Reading Memory and Registers
|
||||
============================
|
||||
|
|
@ -328,7 +326,7 @@ the Visibility Stream Decoder (VSD) which is setup via a similar control
|
|||
register pair but is read by a fixed-function parser that the CP accesses via a
|
||||
few control registers.
|
||||
|
||||
.. _afuc-reg-writes:
|
||||
.. _qrisc-reg-writes:
|
||||
|
||||
Writing Registers
|
||||
=================
|
||||
|
|
@ -357,7 +355,7 @@ which cluster(s) the register belongs to and push the write onto the
|
|||
appropriate per-cluster queue(s) letting the SQE run ahead of the GPU.
|
||||
|
||||
When bit 18 of ``$addr`` is set, the auto-incrementing is disabled. This is
|
||||
often used with :ref:`afuc-mem-writes <NRT_DATA>`.
|
||||
often used with :ref:`qrisc-mem-writes <NRT_DATA>`.
|
||||
|
||||
On a5xx ME, ``$regdata`` can also be used to directly read a register::
|
||||
|
||||
|
|
@ -393,7 +391,7 @@ registers that have their own queues and on a5xx is used by the PFP::
|
|||
Like with the ``$addr``/``$data`` approach, the destination register address
|
||||
increments on each write to ``@REG_WRITE``.
|
||||
|
||||
.. _afuc-pipe-regs:
|
||||
.. _qrisc-pipe-regs:
|
||||
|
||||
Pipe Registers
|
||||
--------------
|
||||
|
|
@ -419,7 +417,7 @@ In short, they behave more like normal registers but are not expected to be
|
|||
read/written by anything other than CP. Over time more and more GPU registers
|
||||
not touched by the kernel driver have been converted to pipe registers.
|
||||
|
||||
.. _afuc-mem-writes:
|
||||
.. _qrisc-mem-writes:
|
||||
|
||||
Writing Memory
|
||||
==============
|
||||
|
|
@ -454,7 +452,7 @@ Memory Read example::
|
|||
mov $05, $addr
|
||||
|
||||
On a6xx ``CP_ME_NRT_ADDR`` and ``CP_ME_NRT_DATA`` have been replaced by
|
||||
:ref:`afuc-pipe-regs <pipe registers>` and they can only be used for writes but
|
||||
:ref:`qrisc-pipe-regs <pipe registers>` and they can only be used for writes but
|
||||
it otherwise works similarly.
|
||||
|
||||
Load and Store Instructions
|
||||
|
|
@ -463,7 +461,7 @@ Load and Store Instructions
|
|||
a6xx adds ``load`` and ``store`` instruction that work similarly to ``cread``
|
||||
and ``cwrite``. Because the address is 64-bits but registers are 32-bit, the
|
||||
high 32 bits come from the ``@LOAD_STORE_HI``
|
||||
:ref:`afuc-control <control register>`. They are mostly used by the context
|
||||
:ref:`qrisc-control <control register>`. They are mostly used by the context
|
||||
switch routine and even then very sparingly, before the memory read/write queue
|
||||
state is saved while it is being restored.
|
||||
|
||||
|
|
@ -473,7 +471,7 @@ Modifiers
|
|||
There are two modifiers that enable more compact and efficient implementations
|
||||
of common patterns:
|
||||
|
||||
.. _afuc-rep:
|
||||
.. _qrisc-rep:
|
||||
|
||||
Repeat
|
||||
------
|
||||
|
|
@ -494,7 +492,7 @@ Note the use of pre-increment mode, so that the first execution clears
|
|||
``0x100`` and updates ``$03`` to ``0x100``, the second execution clears
|
||||
``0x101`` and updates ``$03`` to ``0x101``, and so on.
|
||||
|
||||
.. _afuc-xmov:
|
||||
.. _qrisc-xmov:
|
||||
|
||||
eXtra Moves
|
||||
-----------
|
||||
|
|
@ -563,7 +561,7 @@ Although ``(xmovN)`` is often used in combination with ``(rep)``, it doesn't
|
|||
have to be. For example, ``(xmov1)mov $data, $data`` moves the next 2 packet
|
||||
words to 2 successive registers.
|
||||
|
||||
.. _afuc-sds:
|
||||
.. _qrisc-sds:
|
||||
|
||||
Set Draw State
|
||||
--------------
|
||||
|
|
@ -585,7 +583,7 @@ In testing with other control registers, ``(sdsN)`` causes the source to be
|
|||
read ``N`` extra times and then thrown away. Only when used in combination with
|
||||
``@DRAW_STATE_SET_HDR`` do the extra source reads have an effect.
|
||||
|
||||
.. _afuc-peek:
|
||||
.. _qrisc-peek:
|
||||
|
||||
Peek
|
||||
----
|
||||
|
|
@ -630,7 +628,7 @@ Let's examine an implementation of ``CP_MEM_WRITE``::
|
|||
mov $addr, 0x00a0 << 24 ; |NRT_ADDR
|
||||
|
||||
First, we setup the register to write to, which is the ``NRT_ADDR``
|
||||
:ref:`afuc-pipe-regs <pipe register>`. It turns out that the low 2 bits of
|
||||
:ref:`qrisc-pipe-regs <pipe register>`. It turns out that the low 2 bits of
|
||||
``NRT_ADDR`` are a flag which when 1 disables auto-incrementing ``NRT_ADDR``
|
||||
when ``NRT_DATA`` is written, but we don't want this behavior so we have to
|
||||
make sure they are clear::
|
||||
|
|
@ -652,7 +650,7 @@ handy::
|
|||
|
||||
Finally, we have to repeatedly copy the remaining PM4 packet data to the
|
||||
``NRT_DATA`` register, which we can do in one instruction with
|
||||
:ref:`afuc-rep <(rep)>`. Furthermore we can use :ref:`afuc-xmov <(xmov1)>` to
|
||||
:ref:`qrisc-rep <(rep)>`. Furthermore we can use :ref:`qrisc-xmov <(xmov1)>` to
|
||||
squeeze out some more performance::
|
||||
|
||||
(rep)(xmov1)mov $data, $data
|
||||
|
|
@ -671,7 +669,7 @@ work out-of-the-box, and should give you back an identical firmware, but there
|
|||
is a caveat if you want to reassemble a modified firmware and use preemption.
|
||||
The preemption routines contain a few tables embedded in the firmware, and they
|
||||
load the offset of the table with a ``mov`` instruction that needs to be turned
|
||||
into a relocation and then add it to ``CP_SQE_INSTR_BASE``. ``afuc-asm``
|
||||
into a relocation and then add it to ``CP_SQE_INSTR_BASE``. ``qrisc-asm``
|
||||
supports using labels as immediates for this::
|
||||
|
||||
foo:
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#include "util/macros.h"
|
||||
#include "util/log.h"
|
||||
#include "afuc.h"
|
||||
#include "qrisc.h"
|
||||
#include "asm.h"
|
||||
#include "parser.h"
|
||||
#include "util.h"
|
||||
|
|
@ -26,8 +26,8 @@ struct encode_state {
|
|||
unsigned gen;
|
||||
};
|
||||
|
||||
static afuc_opc
|
||||
__instruction_case(struct encode_state *s, const struct afuc_instr *instr)
|
||||
static qrisc_opc
|
||||
__instruction_case(struct encode_state *s, const struct qrisc_instr *instr)
|
||||
{
|
||||
switch (instr->opc) {
|
||||
#define ALU(name) \
|
||||
|
|
@ -67,7 +67,7 @@ __instruction_case(struct encode_state *s, const struct afuc_instr *instr)
|
|||
int gpuver;
|
||||
|
||||
/* bit lame to hard-code max but fw sizes are small */
|
||||
static struct afuc_instr instructions[0x4000];
|
||||
static struct qrisc_instr instructions[0x4000];
|
||||
static unsigned num_instructions;
|
||||
|
||||
static unsigned instr_offset;
|
||||
|
|
@ -77,10 +77,10 @@ static unsigned num_labels;
|
|||
|
||||
static int outfd;
|
||||
|
||||
struct afuc_instr *
|
||||
next_instr(afuc_opc opc)
|
||||
struct qrisc_instr *
|
||||
next_instr(qrisc_opc opc)
|
||||
{
|
||||
struct afuc_instr *ai = &instructions[num_instructions++];
|
||||
struct qrisc_instr *ai = &instructions[num_instructions++];
|
||||
assert(num_instructions < ARRAY_SIZE(instructions));
|
||||
memset(ai, 0, sizeof(*ai));
|
||||
instr_offset++;
|
||||
|
|
@ -91,12 +91,12 @@ next_instr(afuc_opc opc)
|
|||
static void usage(void);
|
||||
|
||||
void
|
||||
parse_version(struct afuc_instr *instr)
|
||||
parse_version(struct qrisc_instr *instr)
|
||||
{
|
||||
if (gpuver != 0)
|
||||
return;
|
||||
|
||||
int ret = afuc_util_init(afuc_get_fwid(instr->literal), &gpuver, false);
|
||||
int ret = qrisc_util_init(qrisc_get_fwid(instr->literal), &gpuver, false);
|
||||
if (ret < 0) {
|
||||
usage();
|
||||
exit(1);
|
||||
|
|
@ -117,7 +117,7 @@ decl_label(const char *str)
|
|||
void
|
||||
decl_jumptbl(void)
|
||||
{
|
||||
struct afuc_instr *ai = &instructions[num_instructions++];
|
||||
struct qrisc_instr *ai = &instructions[num_instructions++];
|
||||
assert(num_instructions < ARRAY_SIZE(instructions));
|
||||
ai->opc = OPC_JUMPTBL;
|
||||
instr_offset += 0x80;
|
||||
|
|
@ -156,7 +156,7 @@ emit_jumptable(int outfd)
|
|||
|
||||
for (i = 0; i < num_labels; i++) {
|
||||
struct asm_label *label = &labels[i];
|
||||
int id = afuc_pm4_id(label->label);
|
||||
int id = qrisc_pm4_id(label->label);
|
||||
|
||||
/* if it doesn't match a known PM4 packet-id, try to match UNKN%d: */
|
||||
if (id < 0) {
|
||||
|
|
@ -183,7 +183,7 @@ emit_instructions(int outfd)
|
|||
|
||||
/* Expand some meta opcodes, and resolve branch targets */
|
||||
for (i = 0; i < num_instructions; i++) {
|
||||
struct afuc_instr *ai = &instructions[i];
|
||||
struct qrisc_instr *ai = &instructions[i];
|
||||
|
||||
switch (ai->opc) {
|
||||
case OPC_BREQ:
|
||||
|
|
@ -231,7 +231,7 @@ emit_instructions(int outfd)
|
|||
|
||||
if (ai->opc == OPC_RAW_LITERAL) {
|
||||
if (ai->label) {
|
||||
ai->literal = afuc_nop_literal(resolve_label(ai->label), gpuver);
|
||||
ai->literal = qrisc_nop_literal(resolve_label(ai->label), gpuver);
|
||||
}
|
||||
write(outfd, &ai->literal, 4);
|
||||
continue;
|
||||
|
|
@ -259,14 +259,14 @@ unsigned
|
|||
parse_control_reg(const char *name)
|
||||
{
|
||||
/* skip leading "@" */
|
||||
return afuc_control_reg(name + 1);
|
||||
return qrisc_control_reg(name + 1);
|
||||
}
|
||||
|
||||
unsigned
|
||||
parse_sqe_reg(const char *name)
|
||||
{
|
||||
/* skip leading "%" */
|
||||
return afuc_sqe_reg(name + 1);
|
||||
return qrisc_sqe_reg(name + 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "afuc.h"
|
||||
#include "qrisc.h"
|
||||
|
||||
extern int gpuver;
|
||||
|
||||
|
|
@ -17,12 +17,12 @@ struct asm_label {
|
|||
const char *label;
|
||||
};
|
||||
|
||||
struct afuc_instr *next_instr(afuc_opc opc);
|
||||
struct qrisc_instr *next_instr(qrisc_opc opc);
|
||||
void decl_label(const char *str);
|
||||
void decl_jumptbl(void);
|
||||
void align_instr(unsigned alignment);
|
||||
void next_section(void);
|
||||
void parse_version(struct afuc_instr *instr);
|
||||
void parse_version(struct qrisc_instr *instr);
|
||||
|
||||
static inline uint32_t
|
||||
parse_reg(const char *str)
|
||||
|
|
@ -21,8 +21,8 @@
|
|||
|
||||
#include "freedreno_pm4.h"
|
||||
|
||||
#include "afuc.h"
|
||||
#include "afuc-isa.h"
|
||||
#include "qrisc.h"
|
||||
#include "qrisc-isa.h"
|
||||
#include "util.h"
|
||||
#include "emu.h"
|
||||
|
||||
|
|
@ -37,13 +37,13 @@ static bool verbose = false;
|
|||
/* emulator mode: */
|
||||
static bool emulator = false;
|
||||
|
||||
#define printerr(fmt, ...) afuc_printc(AFUC_ERR, fmt, ##__VA_ARGS__)
|
||||
#define printlbl(fmt, ...) afuc_printc(AFUC_LBL, fmt, ##__VA_ARGS__)
|
||||
#define printerr(fmt, ...) qrisc_printc(QRISC_ERR, fmt, ##__VA_ARGS__)
|
||||
#define printlbl(fmt, ...) qrisc_printc(QRISC_LBL, fmt, ##__VA_ARGS__)
|
||||
|
||||
static const char *
|
||||
getpm4(uint32_t id)
|
||||
{
|
||||
return afuc_pm_id_name(id);
|
||||
return qrisc_pm_id_name(id);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -52,7 +52,7 @@ print_gpu_reg(FILE *out, uint32_t regbase)
|
|||
if (regbase < 0x100)
|
||||
return;
|
||||
|
||||
char *name = afuc_gpu_reg_name(regbase);
|
||||
char *name = qrisc_gpu_reg_name(regbase);
|
||||
if (name) {
|
||||
fprintf(out, "\t; %s", name);
|
||||
free(name);
|
||||
|
|
@ -62,7 +62,7 @@ print_gpu_reg(FILE *out, uint32_t regbase)
|
|||
void
|
||||
print_control_reg(uint32_t id)
|
||||
{
|
||||
char *name = afuc_control_reg_name(id);
|
||||
char *name = qrisc_control_reg_name(id);
|
||||
if (name) {
|
||||
printf("@%s", name);
|
||||
free(name);
|
||||
|
|
@ -74,7 +74,7 @@ print_control_reg(uint32_t id)
|
|||
void
|
||||
print_sqe_reg(uint32_t id)
|
||||
{
|
||||
char *name = afuc_sqe_reg_name(id);
|
||||
char *name = qrisc_sqe_reg_name(id);
|
||||
if (name) {
|
||||
printf("@%s", name);
|
||||
free(name);
|
||||
|
|
@ -86,7 +86,7 @@ print_sqe_reg(uint32_t id)
|
|||
void
|
||||
print_pipe_reg(uint32_t id)
|
||||
{
|
||||
char *name = afuc_pipe_reg_name(id);
|
||||
char *name = qrisc_pipe_reg_name(id);
|
||||
if (name) {
|
||||
printf("|%s", name);
|
||||
free(name);
|
||||
|
|
@ -106,7 +106,7 @@ static void
|
|||
field_print_cb(struct isa_print_state *state, const char *field_name, uint64_t val)
|
||||
{
|
||||
if (!strcmp(field_name, "CONTROLREG")) {
|
||||
char *name = afuc_control_reg_name(val);
|
||||
char *name = qrisc_control_reg_name(val);
|
||||
if (name) {
|
||||
isa_print(state, "@%s", name);
|
||||
free(name);
|
||||
|
|
@ -114,7 +114,7 @@ field_print_cb(struct isa_print_state *state, const char *field_name, uint64_t v
|
|||
isa_print(state, "0x%03x", (unsigned)val);
|
||||
}
|
||||
} else if (!strcmp(field_name, "SQEREG")) {
|
||||
char *name = afuc_sqe_reg_name(val);
|
||||
char *name = qrisc_sqe_reg_name(val);
|
||||
if (name) {
|
||||
isa_print(state, "%%%s", name);
|
||||
free(name);
|
||||
|
|
@ -180,7 +180,7 @@ uint32_t jumptbl_offset = ~0;
|
|||
static void
|
||||
no_match(FILE *out, const BITSET_WORD *bitset, size_t size)
|
||||
{
|
||||
if (jumptbl_offset != ~0 && bitset[0] == afuc_nop_literal(jumptbl_offset, gpuver)) {
|
||||
if (jumptbl_offset != ~0 && bitset[0] == qrisc_nop_literal(jumptbl_offset, gpuver)) {
|
||||
fprintf(out, "[#jumptbl]\n");
|
||||
} else {
|
||||
fprintf(out, "[%08x]", bitset[0]);
|
||||
|
|
@ -206,7 +206,7 @@ get_decode_options(struct isa_decode_options *options)
|
|||
static void
|
||||
disasm_instr(struct isa_decode_options *options, uint32_t *instrs, unsigned pc)
|
||||
{
|
||||
afuc_isa_disasm(&instrs[pc], 4, stdout, options);
|
||||
qrisc_isa_disasm(&instrs[pc], 4, stdout, options);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -218,7 +218,7 @@ setup_packet_table(struct isa_decode_options *options,
|
|||
for (unsigned i = 0; i < sizedwords; i++) {
|
||||
entrypoints[i].offset = jmptbl[i];
|
||||
unsigned n = i; // + CP_NOP;
|
||||
entrypoints[i].name = afuc_pm_id_name(n);
|
||||
entrypoints[i].name = qrisc_pm_id_name(n);
|
||||
if (!entrypoints[i].name) {
|
||||
char *name;
|
||||
asprintf(&name, "UNKN%d", n);
|
||||
|
|
@ -313,7 +313,7 @@ disasm(struct emu *emu)
|
|||
}
|
||||
|
||||
/* print instructions: */
|
||||
afuc_isa_disasm(emu->instrs, MIN2(sizedwords, jumptbl_offset) * 4, stdout, &options);
|
||||
qrisc_isa_disasm(emu->instrs, MIN2(sizedwords, jumptbl_offset) * 4, stdout, &options);
|
||||
|
||||
/* print jump table */
|
||||
if (jumptbl_offset != ~0) {
|
||||
|
|
@ -357,7 +357,7 @@ disasm(struct emu *emu)
|
|||
jumptbl_offset = find_jump_table(emu->instrs, sizedwords, emu->jmptbl,
|
||||
ARRAY_SIZE(emu->jmptbl));
|
||||
|
||||
afuc_isa_disasm(emu->instrs, MIN2(sizedwords, jumptbl_offset) * 4, stdout, &options);
|
||||
qrisc_isa_disasm(emu->instrs, MIN2(sizedwords, jumptbl_offset) * 4, stdout, &options);
|
||||
|
||||
if (jumptbl_offset != ~0) {
|
||||
printf(".align 32\n");
|
||||
|
|
@ -393,7 +393,7 @@ disasm(struct emu *emu)
|
|||
jumptbl_offset = find_jump_table(emu->instrs, emu->sizedwords, emu->jmptbl,
|
||||
ARRAY_SIZE(emu->jmptbl));
|
||||
|
||||
afuc_isa_disasm(emu->instrs, MIN2(emu->sizedwords, jumptbl_offset) * 4, stdout, &options);
|
||||
qrisc_isa_disasm(emu->instrs, MIN2(emu->sizedwords, jumptbl_offset) * 4, stdout, &options);
|
||||
|
||||
if (jumptbl_offset != ~0) {
|
||||
printf("jumptbl:\n");
|
||||
|
|
@ -417,7 +417,7 @@ disasm_raw(uint32_t *instrs, int sizedwords)
|
|||
get_decode_options(&options);
|
||||
options.cbdata = &state;
|
||||
|
||||
afuc_isa_disasm(instrs, sizedwords * 4, stdout, &options);
|
||||
qrisc_isa_disasm(instrs, sizedwords * 4, stdout, &options);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -437,7 +437,7 @@ disasm_legacy(uint32_t *buf, int sizedwords)
|
|||
setup_packet_table(&options, jmptbl, 0x80);
|
||||
|
||||
/* print instructions: */
|
||||
afuc_isa_disasm(instrs, sizedwords * 4, stdout, &options);
|
||||
qrisc_isa_disasm(instrs, sizedwords * 4, stdout, &options);
|
||||
|
||||
/* print jumptable: */
|
||||
if (verbose) {
|
||||
|
|
@ -483,7 +483,7 @@ main(int argc, char **argv)
|
|||
int c, ret;
|
||||
bool unit_test = false;
|
||||
bool raw = false;
|
||||
enum afuc_fwid fw_id = 0;
|
||||
enum qrisc_fwid fw_id = 0;
|
||||
|
||||
/* Argument parsing: */
|
||||
while ((c = getopt(argc, argv, "ceg:rvu")) != -1) {
|
||||
|
|
@ -525,9 +525,9 @@ main(int argc, char **argv)
|
|||
buf = (uint32_t *)os_read_file(file, &sz);
|
||||
|
||||
if (!fw_id)
|
||||
fw_id = afuc_get_fwid(buf[1]);
|
||||
fw_id = qrisc_get_fwid(buf[1]);
|
||||
|
||||
ret = afuc_util_init(fw_id, &gpuver, colors);
|
||||
ret = qrisc_util_init(fw_id, &gpuver, colors);
|
||||
if (ret < 0) {
|
||||
usage();
|
||||
}
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
static bool
|
||||
is_draw_state_control_reg(unsigned n)
|
||||
{
|
||||
char *reg_name = afuc_control_reg_name(n);
|
||||
char *reg_name = qrisc_control_reg_name(n);
|
||||
if (!reg_name)
|
||||
return false;
|
||||
bool ret = !!strstr(reg_name, "DRAW_STATE");
|
||||
|
|
@ -197,7 +197,7 @@ emu_get_fifo_reg(struct emu *emu, unsigned n, bool peek)
|
|||
unsigned read_dwords = emu_get_reg32(emu, &MEM_READ_DWORDS);
|
||||
uintptr_t read_addr = emu_get_reg64(emu, &MEM_READ_ADDR);
|
||||
uintptr_t read_addr_hi = 0;
|
||||
if (emu->fw_id == AFUC_A750)
|
||||
if (emu->fw_id == QRISC_A750)
|
||||
read_addr_hi = emu_get_reg64(emu, &MEM_READ_ADDR_HI_PREEMPTION);
|
||||
|
||||
/* We don't model privileged vs. non-privileged accesses here, so just
|
||||
|
|
@ -290,7 +290,7 @@ emu_set_fifo_reg(struct emu *emu, unsigned n, uint32_t val)
|
|||
/* "void" pipe regs don't have a value to write, so just
|
||||
* treat it as writing zero to the pipe reg:
|
||||
*/
|
||||
if (afuc_pipe_reg_is_void(val >> 24))
|
||||
if (qrisc_pipe_reg_is_void(val >> 24))
|
||||
emu_set_pipe_reg(emu, val >> 24, 0);
|
||||
emu->data_mode = DATA_PIPE;
|
||||
}
|
||||
|
|
@ -376,25 +376,25 @@ struct emu_reg_accessor {
|
|||
};
|
||||
|
||||
const struct emu_reg_accessor emu_control_accessor = {
|
||||
.get_offset = afuc_control_reg,
|
||||
.get_offset = qrisc_control_reg,
|
||||
.get = emu_get_control_reg,
|
||||
.set = emu_set_control_reg,
|
||||
};
|
||||
|
||||
const struct emu_reg_accessor emu_sqe_accessor = {
|
||||
.get_offset = afuc_sqe_reg,
|
||||
.get_offset = qrisc_sqe_reg,
|
||||
.get = emu_get_sqe_reg,
|
||||
.set = emu_set_sqe_reg,
|
||||
};
|
||||
|
||||
const struct emu_reg_accessor emu_pipe_accessor = {
|
||||
.get_offset = afuc_pipe_reg,
|
||||
.get_offset = qrisc_pipe_reg,
|
||||
.get = emu_get_pipe_reg,
|
||||
.set = emu_set_pipe_reg,
|
||||
};
|
||||
|
||||
const struct emu_reg_accessor emu_gpu_accessor = {
|
||||
.get_offset = afuc_gpu_reg,
|
||||
.get_offset = qrisc_gpu_reg,
|
||||
.get = emu_get_gpu_reg,
|
||||
.set = emu_set_gpu_reg,
|
||||
};
|
||||
|
|
@ -166,7 +166,7 @@ static void
|
|||
dump_gpu_register(struct emu *emu, unsigned n)
|
||||
{
|
||||
printf(" GPU: ");
|
||||
char *name = afuc_gpu_reg_name(n);
|
||||
char *name = qrisc_gpu_reg_name(n);
|
||||
if (name) {
|
||||
printf("%s", name);
|
||||
free(name);
|
||||
|
|
@ -254,7 +254,7 @@ emu_write_gpr_prompt(struct emu *emu)
|
|||
if (read_two_values(&name, &value))
|
||||
return;
|
||||
|
||||
unsigned offset = afuc_gpr_reg(name);
|
||||
unsigned offset = qrisc_gpr_reg(name);
|
||||
uint32_t val = strtoul(value, NULL, 0);
|
||||
|
||||
emu_set_gpr_reg(emu, offset, val);
|
||||
|
|
@ -272,7 +272,7 @@ emu_write_control_prompt(struct emu *emu)
|
|||
if (read_two_values(&name, &value))
|
||||
return;
|
||||
|
||||
unsigned offset = afuc_control_reg(name);
|
||||
unsigned offset = qrisc_control_reg(name);
|
||||
uint32_t val = strtoul(value, NULL, 0);
|
||||
|
||||
emu_set_control_reg(emu, offset, val);
|
||||
|
|
@ -291,7 +291,7 @@ emu_dump_control_prompt(struct emu *emu)
|
|||
|
||||
printf("\n");
|
||||
|
||||
unsigned offset = afuc_control_reg(name);
|
||||
unsigned offset = qrisc_control_reg(name);
|
||||
dump_control_register(emu, offset);
|
||||
}
|
||||
|
||||
|
|
@ -307,7 +307,7 @@ emu_write_sqe_prompt(struct emu *emu)
|
|||
if (read_two_values(&name, &value))
|
||||
return;
|
||||
|
||||
unsigned offset = afuc_sqe_reg(name);
|
||||
unsigned offset = qrisc_sqe_reg(name);
|
||||
uint32_t val = strtoul(value, NULL, 0);
|
||||
|
||||
emu_set_sqe_reg(emu, offset, val);
|
||||
|
|
@ -325,7 +325,7 @@ emu_write_gpu_prompt(struct emu *emu)
|
|||
if (read_two_values(&name, &value))
|
||||
return;
|
||||
|
||||
unsigned offset = afuc_gpu_reg(name);
|
||||
unsigned offset = qrisc_gpu_reg(name);
|
||||
uint32_t val = strtoul(value, NULL, 0);
|
||||
|
||||
emu_set_gpu_reg(emu, offset, val);
|
||||
|
|
@ -344,7 +344,7 @@ emu_dump_gpu_prompt(struct emu *emu)
|
|||
|
||||
printf("\n");
|
||||
|
||||
unsigned offset = afuc_gpu_reg(name);
|
||||
unsigned offset = qrisc_gpu_reg(name);
|
||||
dump_gpu_register(emu, offset);
|
||||
}
|
||||
|
||||
|
|
@ -480,11 +480,11 @@ emu_packet_prompt(struct emu *emu)
|
|||
} while (true);
|
||||
|
||||
uint32_t hdr;
|
||||
if (afuc_pm4_id(name) >= 0) {
|
||||
unsigned opcode = afuc_pm4_id(name);
|
||||
if (qrisc_pm4_id(name) >= 0) {
|
||||
unsigned opcode = qrisc_pm4_id(name);
|
||||
hdr = pm4_pkt7_hdr(opcode, cnt);
|
||||
} else {
|
||||
unsigned regindx = afuc_gpu_reg(name);
|
||||
unsigned regindx = qrisc_gpu_reg(name);
|
||||
hdr = pm4_pkt4_hdr(regindx, cnt);
|
||||
}
|
||||
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include "freedreno_pm4.h"
|
||||
|
||||
#include "afuc-isa.h"
|
||||
#include "qrisc-isa.h"
|
||||
|
||||
#include "emu.h"
|
||||
#include "util.h"
|
||||
|
|
@ -29,14 +29,14 @@ EMU_SQE_REG(STACK0);
|
|||
EMU_CONTROL_REG(DRAW_STATE_SET_HDR);
|
||||
|
||||
/**
|
||||
* AFUC emulator. Currently only supports a6xx
|
||||
* QRISC emulator. Currently only supports a6xx
|
||||
*
|
||||
* TODO to add a5xx it might be easier to compile this multiple times
|
||||
* with conditional compile to deal with differences between generations.
|
||||
*/
|
||||
|
||||
static uint32_t
|
||||
emu_alu(struct emu *emu, afuc_opc opc, uint32_t src1, uint32_t src2)
|
||||
emu_alu(struct emu *emu, qrisc_opc opc, uint32_t src1, uint32_t src2)
|
||||
{
|
||||
uint64_t tmp;
|
||||
switch (opc) {
|
||||
|
|
@ -115,7 +115,7 @@ load_store_addr(struct emu *emu, unsigned gpr)
|
|||
}
|
||||
|
||||
static void
|
||||
emu_instr(struct emu *emu, struct afuc_instr *instr)
|
||||
emu_instr(struct emu *emu, struct qrisc_instr *instr)
|
||||
{
|
||||
uint32_t rem = emu_get_gpr_reg(emu, REG_REM);
|
||||
|
||||
|
|
@ -364,9 +364,9 @@ emu_instr(struct emu *emu, struct afuc_instr *instr)
|
|||
void
|
||||
emu_step(struct emu *emu)
|
||||
{
|
||||
struct afuc_instr *instr;
|
||||
struct qrisc_instr *instr;
|
||||
bool decoded =
|
||||
afuc_isa_decode((void *)&instr, (void *)&emu->instrs[emu->gpr_regs.pc],
|
||||
qrisc_isa_decode((void *)&instr, (void *)&emu->instrs[emu->gpr_regs.pc],
|
||||
&(struct isa_decode_options){
|
||||
.gpu_id = gpuver,
|
||||
});
|
||||
|
|
@ -377,7 +377,7 @@ emu_step(struct emu *emu)
|
|||
/* This is printed as an undecoded literal to show the immediate
|
||||
* payload, but when executing it's just a NOP.
|
||||
*/
|
||||
instr = calloc(1, sizeof(struct afuc_instr));
|
||||
instr = calloc(1, sizeof(struct qrisc_instr));
|
||||
instr->opc = OPC_NOP;
|
||||
} else {
|
||||
printf("unmatched instruction: 0x%08x\n", instr_val);
|
||||
|
|
@ -423,7 +423,7 @@ emu_step(struct emu *emu)
|
|||
uint32_t id, count;
|
||||
|
||||
if (pkt_is_type4(hdr)) {
|
||||
id = afuc_pm4_id("PKT4");
|
||||
id = qrisc_pm4_id("PKT4");
|
||||
count = type4_pkt_size(hdr);
|
||||
|
||||
/* Possibly a hack, not sure what the hw actually
|
||||
|
|
@ -549,16 +549,16 @@ emu_init(struct emu *emu)
|
|||
break;
|
||||
}
|
||||
|
||||
if (emu->fw_id == AFUC_A750) {
|
||||
if (emu->fw_id == QRISC_A750) {
|
||||
emu_set_control_reg(emu, 0, 7 << 28);
|
||||
emu_set_control_reg(emu, 2, 0x40 << 8);
|
||||
} else if (emu->fw_id == AFUC_A730 || emu->fw_id == AFUC_A740 ||
|
||||
emu->fw_id == AFUC_GEN70500) {
|
||||
} else if (emu->fw_id == QRISC_A730 || emu->fw_id == QRISC_A740 ||
|
||||
emu->fw_id == QRISC_GEN70500) {
|
||||
emu_set_control_reg(emu, 0xef, 1 << 21);
|
||||
emu_set_control_reg(emu, 0, 7 << 28);
|
||||
} else if (emu->fw_id == AFUC_A660) {
|
||||
} else if (emu->fw_id == QRISC_A660) {
|
||||
emu_set_control_reg(emu, 0, 3 << 28);
|
||||
} else if (emu->fw_id == AFUC_A650) {
|
||||
} else if (emu->fw_id == QRISC_A650) {
|
||||
emu_set_control_reg(emu, 0, 1 << 28);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include "util/bitset.h"
|
||||
|
||||
#include "afuc.h"
|
||||
#include "qrisc.h"
|
||||
|
||||
extern int gpuver;
|
||||
|
||||
|
|
@ -298,6 +298,6 @@ void emu_set_draw_state_reg(struct emu *emu, unsigned n, uint32_t val);
|
|||
void emu_set_draw_state_base(struct emu *emu, unsigned n, uint32_t val);
|
||||
|
||||
/* Helpers: */
|
||||
#define printdelta(fmt, ...) afuc_printc(AFUC_ERR, fmt, ##__VA_ARGS__)
|
||||
#define printdelta(fmt, ...) qrisc_printc(QRISC_ERR, fmt, ##__VA_ARGS__)
|
||||
|
||||
#endif /* _ASM_H_ */
|
||||
|
|
@ -10,11 +10,11 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#include "compiler/isaspec/isaspec.h"
|
||||
#include "afuc.h"
|
||||
#include "qrisc.h"
|
||||
|
||||
static inline struct afuc_instr *__instruction_create(afuc_opc opc)
|
||||
static inline struct qrisc_instr *__instruction_create(qrisc_opc opc)
|
||||
{
|
||||
struct afuc_instr *instr = calloc(1, sizeof(struct afuc_instr));
|
||||
struct qrisc_instr *instr = calloc(1, sizeof(struct qrisc_instr));
|
||||
|
||||
switch (opc) {
|
||||
#define ALU(name) \
|
||||
|
|
@ -5,7 +5,7 @@ if with_tests
|
|||
diff = find_program('diff')
|
||||
endif
|
||||
|
||||
afuc_parser = custom_target(
|
||||
qrisc_parser = custom_target(
|
||||
'parser.[ch]',
|
||||
input: 'parser.y',
|
||||
output: ['parser.c', 'parser.h'],
|
||||
|
|
@ -14,7 +14,7 @@ afuc_parser = custom_target(
|
|||
]
|
||||
)
|
||||
|
||||
afuc_lexer = custom_target(
|
||||
qrisc_lexer = custom_target(
|
||||
'lexer.c',
|
||||
input: 'lexer.l',
|
||||
output: 'lexer.c',
|
||||
|
|
@ -25,7 +25,7 @@ afuc_lexer = custom_target(
|
|||
|
||||
encode_h = custom_target(
|
||||
'encode.h',
|
||||
input: ['afuc.xml'],
|
||||
input: ['qrisc.xml'],
|
||||
output: 'encode.h',
|
||||
command: [
|
||||
prog_isaspec_encode, '--xml', '@INPUT@', '--out-h', '@OUTPUT@'
|
||||
|
|
@ -33,13 +33,13 @@ encode_h = custom_target(
|
|||
)
|
||||
|
||||
asm = executable(
|
||||
'afuc-asm',
|
||||
'qrisc-asm',
|
||||
[
|
||||
'asm.c',
|
||||
'util.c',
|
||||
'util.h',
|
||||
afuc_lexer,
|
||||
afuc_parser,
|
||||
qrisc_lexer,
|
||||
qrisc_parser,
|
||||
encode_h,
|
||||
],
|
||||
include_directories: [
|
||||
|
|
@ -53,32 +53,32 @@ asm = executable(
|
|||
install: install_fd_decode_tools,
|
||||
)
|
||||
if with_tests
|
||||
asm_fw = custom_target('afuc_test.fw',
|
||||
output: 'afuc_test.fw',
|
||||
command: [asm, files('../tests/traces/afuc_test.asm'), '@OUTPUT@'],
|
||||
asm_fw = custom_target('qrisc_test.fw',
|
||||
output: 'qrisc_test.fw',
|
||||
command: [asm, files('../tests/traces/qrisc_test.asm'), '@OUTPUT@'],
|
||||
)
|
||||
asm_fw_a7xx = custom_target('afuc_test_a7xx.fw',
|
||||
output: 'afuc_test_a7xx.fw',
|
||||
command: [asm, files('../tests/traces/afuc_test_a7xx.asm'), '@OUTPUT@'],
|
||||
asm_fw_a7xx = custom_target('qrisc_test_a7xx.fw',
|
||||
output: 'qrisc_test_a7xx.fw',
|
||||
command: [asm, files('../tests/traces/qrisc_test_a7xx.asm'), '@OUTPUT@'],
|
||||
)
|
||||
test('afuc-asm',
|
||||
test('qrisc-asm',
|
||||
diff,
|
||||
args: ['-u', files('../tests/reference/afuc_test.fw'), asm_fw],
|
||||
args: ['-u', files('../tests/reference/qrisc_test.fw'), asm_fw],
|
||||
suite: 'freedreno',
|
||||
workdir: dir_source_root
|
||||
)
|
||||
test('afuc-asm-a7xx',
|
||||
test('qrisc-asm-a7xx',
|
||||
diff,
|
||||
args: ['-u', files('../tests/reference/afuc_test_a7xx.fw'), asm_fw_a7xx],
|
||||
args: ['-u', files('../tests/reference/qrisc_test_a7xx.fw'), asm_fw_a7xx],
|
||||
suite: 'freedreno',
|
||||
workdir: dir_source_root
|
||||
)
|
||||
endif
|
||||
|
||||
afuc_isa = custom_target(
|
||||
'afuc-isa',
|
||||
input: ['afuc.xml'],
|
||||
output: ['afuc-isa.c', 'afuc-isa.h'],
|
||||
qrisc_isa = custom_target(
|
||||
'qrisc-isa',
|
||||
input: ['qrisc.xml'],
|
||||
output: ['qrisc-isa.c', 'qrisc-isa.h'],
|
||||
command: [
|
||||
prog_isaspec_decode, '--xml', '@INPUT@',
|
||||
'--out-c', '@OUTPUT0@', '--out-h', '@OUTPUT1@',
|
||||
|
|
@ -88,7 +88,7 @@ afuc_isa = custom_target(
|
|||
# Disasm requires mmaping >4GB
|
||||
if cc.sizeof('size_t') > 4
|
||||
disasm = executable(
|
||||
'afuc-disasm',
|
||||
'qrisc-disasm',
|
||||
[
|
||||
'disasm.c',
|
||||
'emu.c',
|
||||
|
|
@ -98,7 +98,7 @@ if cc.sizeof('size_t') > 4
|
|||
'emu-ui.c',
|
||||
'util.c',
|
||||
'util.h',
|
||||
afuc_isa,
|
||||
qrisc_isa,
|
||||
freedreno_pm4_xml_header_file,
|
||||
],
|
||||
include_directories: [
|
||||
|
|
@ -118,25 +118,25 @@ if cc.sizeof('size_t') > 4
|
|||
)
|
||||
|
||||
if with_tests
|
||||
disasm_fw = custom_target('afuc_test.asm',
|
||||
output: 'afuc_test.asm',
|
||||
command: [disasm, '-u', files('../tests/reference/afuc_test.fw')],
|
||||
disasm_fw = custom_target('qrisc_test.asm',
|
||||
output: 'qrisc_test.asm',
|
||||
command: [disasm, '-u', files('../tests/reference/qrisc_test.fw')],
|
||||
capture: true
|
||||
)
|
||||
disasm_fw_a7xx = custom_target('afuc_test_a7xx.asm',
|
||||
output: 'afuc_test_a7xx.asm',
|
||||
command: [disasm, '-u', files('../tests/reference/afuc_test_a7xx.fw')],
|
||||
disasm_fw_a7xx = custom_target('qrisc_test_a7xx.asm',
|
||||
output: 'qrisc_test_a7xx.asm',
|
||||
command: [disasm, '-u', files('../tests/reference/qrisc_test_a7xx.fw')],
|
||||
capture: true
|
||||
)
|
||||
test('afuc-disasm',
|
||||
test('qrisc-disasm',
|
||||
diff,
|
||||
args: ['-u', files('../tests/reference/afuc_test.asm'), disasm_fw],
|
||||
args: ['-u', files('../tests/reference/qrisc_test.asm'), disasm_fw],
|
||||
suite: 'freedreno',
|
||||
workdir: dir_source_root
|
||||
)
|
||||
test('afuc-disasm-a7xx',
|
||||
test('qrisc-disasm-a7xx',
|
||||
diff,
|
||||
args: ['-u', files('../tests/reference/afuc_test_a7xx.asm'), disasm_fw_a7xx],
|
||||
args: ['-u', files('../tests/reference/qrisc_test_a7xx.asm'), disasm_fw_a7xx],
|
||||
suite: 'freedreno',
|
||||
workdir: dir_source_root
|
||||
)
|
||||
|
|
@ -50,10 +50,10 @@ void yyerror(const char *error)
|
|||
fprintf(stderr, "error at line %d: %s\n", yyget_lineno(), error);
|
||||
}
|
||||
|
||||
static struct afuc_instr *instr; /* current instruction */
|
||||
static struct qrisc_instr *instr; /* current instruction */
|
||||
|
||||
static void
|
||||
new_instr(afuc_opc opc)
|
||||
new_instr(qrisc_opc opc)
|
||||
{
|
||||
instr = next_instr(opc);
|
||||
}
|
||||
|
|
@ -3,8 +3,8 @@
|
|||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef _AFUC_H_
|
||||
#define _AFUC_H_
|
||||
#ifndef _QRISC_H_
|
||||
#define _QRISC_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ typedef enum {
|
|||
OPC_JUMP,
|
||||
OPC_RAW_LITERAL,
|
||||
OPC_JUMPTBL,
|
||||
} afuc_opc;
|
||||
} qrisc_opc;
|
||||
|
||||
/**
|
||||
* Special GPR registers:
|
||||
|
|
@ -147,10 +147,10 @@ typedef enum {
|
|||
REG_REGDATA = 0x1e, /* when used as src */
|
||||
REG_USRADDR = 0x1e, /* when used as dst */
|
||||
REG_DATA = 0x1f,
|
||||
} afuc_reg;
|
||||
} qrisc_reg;
|
||||
|
||||
struct afuc_instr {
|
||||
afuc_opc opc;
|
||||
struct qrisc_instr {
|
||||
qrisc_opc opc;
|
||||
|
||||
uint8_t dst;
|
||||
uint8_t src1;
|
||||
|
|
@ -177,7 +177,7 @@ struct afuc_instr {
|
|||
* must have a high 8 bits of 0x01.
|
||||
*/
|
||||
static inline uint32_t
|
||||
afuc_nop_literal(uint32_t x, unsigned gpuver)
|
||||
qrisc_nop_literal(uint32_t x, unsigned gpuver)
|
||||
{
|
||||
assert((x >> 24) == 0);
|
||||
return gpuver < 6 ? x : x | (1 << 24);
|
||||
|
|
@ -187,4 +187,4 @@ void print_control_reg(uint32_t id);
|
|||
void print_sqe_reg(uint32_t id);
|
||||
void print_pipe_reg(uint32_t id);
|
||||
|
||||
#endif /* _AFUC_H_ */
|
||||
#endif /* _QRISC_H_ */
|
||||
|
|
@ -27,9 +27,9 @@ SOFTWARE.
|
|||
|
||||
<bitset name="#instruction" size="32">
|
||||
<doc>
|
||||
Encoding of an afuc instruction. All instructions are 32b.
|
||||
Encoding of a QRisc instruction. All instructions are 32b.
|
||||
</doc>
|
||||
<encode type="struct afuc_instr *" case-prefix="OPC_">
|
||||
<encode type="struct qrisc_instr *" case-prefix="OPC_">
|
||||
<map name="XMOV">src->xmov</map>
|
||||
<map name="DST">src->dst</map>
|
||||
<map name="SRC1">src->src1</map>
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
#include "rnn.h"
|
||||
#include "rnndec.h"
|
||||
|
||||
#include "afuc.h"
|
||||
#include "qrisc.h"
|
||||
#include "util.h"
|
||||
|
||||
static struct rnndeccontext *ctx;
|
||||
|
|
@ -66,7 +66,7 @@ reg_name(struct rnndomain *dom, unsigned id)
|
|||
* Map control reg name to offset.
|
||||
*/
|
||||
unsigned
|
||||
afuc_control_reg(const char *name)
|
||||
qrisc_control_reg(const char *name)
|
||||
{
|
||||
return reg(control_regs, "control", name);
|
||||
}
|
||||
|
|
@ -75,7 +75,7 @@ afuc_control_reg(const char *name)
|
|||
* Map offset to SQE reg name (or NULL), caller frees
|
||||
*/
|
||||
char *
|
||||
afuc_sqe_reg_name(unsigned id)
|
||||
qrisc_sqe_reg_name(unsigned id)
|
||||
{
|
||||
return reg_name(sqe_regs, id);
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ afuc_sqe_reg_name(unsigned id)
|
|||
* Map SQE reg name to offset.
|
||||
*/
|
||||
unsigned
|
||||
afuc_sqe_reg(const char *name)
|
||||
qrisc_sqe_reg(const char *name)
|
||||
{
|
||||
return reg(sqe_regs, "SQE", name);
|
||||
}
|
||||
|
|
@ -93,7 +93,7 @@ afuc_sqe_reg(const char *name)
|
|||
* Map offset to control reg name (or NULL), caller frees
|
||||
*/
|
||||
char *
|
||||
afuc_control_reg_name(unsigned id)
|
||||
qrisc_control_reg_name(unsigned id)
|
||||
{
|
||||
return reg_name(control_regs, id);
|
||||
}
|
||||
|
|
@ -102,7 +102,7 @@ afuc_control_reg_name(unsigned id)
|
|||
* Map pipe reg name to offset.
|
||||
*/
|
||||
unsigned
|
||||
afuc_pipe_reg(const char *name)
|
||||
qrisc_pipe_reg(const char *name)
|
||||
{
|
||||
return reg(pipe_regs, "pipe", name);
|
||||
}
|
||||
|
|
@ -112,7 +112,7 @@ afuc_pipe_reg(const char *name)
|
|||
* enough to trigger what they do
|
||||
*/
|
||||
bool
|
||||
afuc_pipe_reg_is_void(unsigned id)
|
||||
qrisc_pipe_reg_is_void(unsigned id)
|
||||
{
|
||||
if (rnndec_checkaddr(ctx, pipe_regs, id, 0)) {
|
||||
struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, pipe_regs, id, 0);
|
||||
|
|
@ -129,7 +129,7 @@ afuc_pipe_reg_is_void(unsigned id)
|
|||
* Map offset to pipe reg name (or NULL), caller frees
|
||||
*/
|
||||
char *
|
||||
afuc_pipe_reg_name(unsigned id)
|
||||
qrisc_pipe_reg_name(unsigned id)
|
||||
{
|
||||
return reg_name(pipe_regs, id);
|
||||
}
|
||||
|
|
@ -138,7 +138,7 @@ afuc_pipe_reg_name(unsigned id)
|
|||
* Map GPU reg name to offset.
|
||||
*/
|
||||
unsigned
|
||||
afuc_gpu_reg(const char *name)
|
||||
qrisc_gpu_reg(const char *name)
|
||||
{
|
||||
int val = find_reg(dom[0], name);
|
||||
if (val < 0)
|
||||
|
|
@ -158,7 +158,7 @@ afuc_gpu_reg(const char *name)
|
|||
* Map offset to gpu reg name (or NULL), caller frees
|
||||
*/
|
||||
char *
|
||||
afuc_gpu_reg_name(unsigned id)
|
||||
qrisc_gpu_reg_name(unsigned id)
|
||||
{
|
||||
struct rnndomain *d = NULL;
|
||||
|
||||
|
|
@ -181,7 +181,7 @@ afuc_gpu_reg_name(unsigned id)
|
|||
}
|
||||
|
||||
unsigned
|
||||
afuc_gpr_reg(const char *name)
|
||||
qrisc_gpr_reg(const char *name)
|
||||
{
|
||||
/* If it starts with '$' just swallow it: */
|
||||
if (name[0] == '$')
|
||||
|
|
@ -227,24 +227,24 @@ find_enum_val(struct rnnenum *en, const char *name)
|
|||
* Map pm4 packet name to id
|
||||
*/
|
||||
int
|
||||
afuc_pm4_id(const char *name)
|
||||
qrisc_pm4_id(const char *name)
|
||||
{
|
||||
return find_enum_val(pm4_packets, name);
|
||||
}
|
||||
|
||||
const char *
|
||||
afuc_pm_id_name(unsigned id)
|
||||
qrisc_pm_id_name(unsigned id)
|
||||
{
|
||||
return rnndec_decode_enum(ctx, "adreno_pm4_type3_packets", id);
|
||||
}
|
||||
|
||||
void
|
||||
afuc_printc(enum afuc_color c, const char *fmt, ...)
|
||||
qrisc_printc(enum qrisc_color c, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
if (c == AFUC_ERR) {
|
||||
if (c == QRISC_ERR) {
|
||||
printf("%s", ctx->colors->err);
|
||||
} else if (c == AFUC_LBL) {
|
||||
} else if (c == QRISC_LBL) {
|
||||
printf("%s", ctx->colors->btarg);
|
||||
}
|
||||
va_start(args, fmt);
|
||||
|
|
@ -253,38 +253,38 @@ afuc_printc(enum afuc_color c, const char *fmt, ...)
|
|||
printf("%s", ctx->colors->reset);
|
||||
}
|
||||
|
||||
int afuc_util_init(enum afuc_fwid fw_id, int *gpuver_out, bool colors)
|
||||
int qrisc_util_init(enum qrisc_fwid fw_id, int *gpuver_out, bool colors)
|
||||
{
|
||||
char *name, *control_reg_name, *variant;
|
||||
char *pipe_reg_name = NULL;
|
||||
|
||||
switch (fw_id) {
|
||||
case AFUC_A750:
|
||||
case QRISC_A750:
|
||||
name = "A6XX";
|
||||
variant = "A7XX";
|
||||
control_reg_name = "A7XX_GEN3_CONTROL_REG";
|
||||
pipe_reg_name = "A7XX_PIPE_REG";
|
||||
*gpuver_out = 7;
|
||||
break;
|
||||
case AFUC_A730:
|
||||
case AFUC_A740:
|
||||
case AFUC_GEN70500:
|
||||
case QRISC_A730:
|
||||
case QRISC_A740:
|
||||
case QRISC_GEN70500:
|
||||
name = "A6XX";
|
||||
variant = "A7XX";
|
||||
control_reg_name = "A7XX_CONTROL_REG";
|
||||
pipe_reg_name = "A7XX_PIPE_REG";
|
||||
*gpuver_out = 7;
|
||||
break;
|
||||
case AFUC_A630:
|
||||
case AFUC_A650:
|
||||
case AFUC_A660:
|
||||
case QRISC_A630:
|
||||
case QRISC_A650:
|
||||
case QRISC_A660:
|
||||
name = "A6XX";
|
||||
variant = "A6XX";
|
||||
control_reg_name = "A6XX_CONTROL_REG";
|
||||
pipe_reg_name = "A6XX_PIPE_REG";
|
||||
*gpuver_out = 6;
|
||||
break;
|
||||
case AFUC_A530:
|
||||
case QRISC_A530:
|
||||
name = "A5XX";
|
||||
variant = "A5XX";
|
||||
control_reg_name = "A5XX_CONTROL_REG";
|
||||
62
src/freedreno/qrisc/util.h
Normal file
62
src/freedreno/qrisc/util.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright © 2021 Google, Inc.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef _UTIL_H_
|
||||
#define _UTIL_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* QRisc disasm / asm helpers
|
||||
*/
|
||||
|
||||
unsigned qrisc_control_reg(const char *name);
|
||||
char * qrisc_control_reg_name(unsigned id);
|
||||
|
||||
unsigned qrisc_sqe_reg(const char *name);
|
||||
char * qrisc_sqe_reg_name(unsigned id);
|
||||
|
||||
unsigned qrisc_pipe_reg(const char *name);
|
||||
char * qrisc_pipe_reg_name(unsigned id);
|
||||
bool qrisc_pipe_reg_is_void(unsigned id);
|
||||
|
||||
unsigned qrisc_gpu_reg(const char *name);
|
||||
char * qrisc_gpu_reg_name(unsigned id);
|
||||
|
||||
unsigned qrisc_gpr_reg(const char *name);
|
||||
|
||||
int qrisc_pm4_id(const char *name);
|
||||
const char * qrisc_pm_id_name(unsigned id);
|
||||
|
||||
enum qrisc_color {
|
||||
QRISC_ERR,
|
||||
QRISC_LBL,
|
||||
};
|
||||
|
||||
void qrisc_printc(enum qrisc_color c, const char *fmt, ...);
|
||||
|
||||
enum qrisc_fwid {
|
||||
QRISC_A730 = 0x730,
|
||||
QRISC_A740 = 0x740,
|
||||
QRISC_GEN70500 = 0x512,
|
||||
QRISC_A750 = 0x520,
|
||||
|
||||
QRISC_A630 = 0x6ee,
|
||||
QRISC_A650 = 0x6dc,
|
||||
QRISC_A660 = 0x6dd,
|
||||
|
||||
QRISC_A530 = 0x5ff,
|
||||
};
|
||||
|
||||
static inline enum qrisc_fwid
|
||||
qrisc_get_fwid(uint32_t first_dword)
|
||||
{
|
||||
/* The firmware ID is in bits 12-24 of the first dword */
|
||||
return (first_dword >> 12) & 0xfff;
|
||||
}
|
||||
|
||||
int qrisc_util_init(enum qrisc_fwid fw_id, int *gpuver, bool colors);
|
||||
|
||||
#endif /* _UTIL_H_ */
|
||||
|
|
@ -6,7 +6,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
|
||||
<!--
|
||||
This documents the internal register spaces used by the CP firmware since
|
||||
the afuc instruction set was introduced.
|
||||
the QRisc instruction set was introduced.
|
||||
-->
|
||||
|
||||
<domain name="A6XX_SQE_REG" width="32">
|
||||
|
|
@ -37,7 +37,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<reg32 name="REG_WRITE_ADDR" offset="0x010"/>
|
||||
<reg32 name="REG_WRITE" offset="0x011"/>
|
||||
|
||||
<doc> Controls high 32 bits used by store afuc instruction </doc>
|
||||
<doc> Controls high 32 bits used by store QRisc instruction </doc>
|
||||
<reg32 name="STORE_HI" offset="0x038"/>
|
||||
|
||||
<reg64 name="IB1_BASE" offset="0x0b0"/>
|
||||
|
|
@ -150,7 +150,7 @@ xsi:schemaLocation="https://gitlab.freedesktop.org/freedreno/ rules-fd.xsd">
|
|||
<doc> Controls whether RB, IB1, or IB2 is executed </doc>
|
||||
<reg32 name="IB_LEVEL" offset="0x054"/>
|
||||
|
||||
<doc> Controls high 32 bits used by load and store afuc instructions </doc>
|
||||
<doc> Controls high 32 bits used by load and store QRisc instructions </doc>
|
||||
<reg32 name="LOAD_STORE_HI" offset="0x058"/>
|
||||
|
||||
<doc>
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
;
|
||||
;
|
||||
; This file is the source for a simple mock firmware used to regression test
|
||||
; the afuc assembler/disassembler. Note, it won't actually work if you try to
|
||||
; the QRisc assembler/disassembler. Note, it won't actually work if you try to
|
||||
; load it on the GPU! First this is assembled, compared to the reference
|
||||
; binary, then disassambled and compared to the reference disassembly. We do
|
||||
; this to avoid having to host the actual firmware, especially the disassembled
|
||||
|
|
@ -121,8 +121,8 @@ waitin
|
|||
mov $01, $data
|
||||
|
||||
euclid:
|
||||
; Euclid's algorithm in afuc: https://en.wikipedia.org/wiki/Euclidean_algorithm
|
||||
; Since afuc doesn't do modulo, we implement the subtraction-based version.
|
||||
; Euclid's algorithm in QRisc: https://en.wikipedia.org/wiki/Euclidean_algorithm
|
||||
; Since QRisc doesn't do modulo, we implement the subtraction-based version.
|
||||
;
|
||||
; Demonstrates/tests comparisons and conditional branches. This also
|
||||
; demonstrates the common trick of branching in a delay slot. Note that if a
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
;
|
||||
;
|
||||
; This file is the source for a simple mock firmware used to regression test
|
||||
; the afuc assembler/disassembler. This is the a7xx variant, for testing new
|
||||
; the QRisc assembler/disassembler. This is the a7xx variant, for testing new
|
||||
; features introduced in a7xx.
|
||||
[01730001]
|
||||
[#jumptbl]
|
||||
|
|
@ -150,8 +150,8 @@ waitin
|
|||
mov $01, $data
|
||||
|
||||
euclid:
|
||||
; Euclid's algorithm in afuc: https://en.wikipedia.org/wiki/Euclidean_algorithm
|
||||
; Since afuc doesn't do modulo, we implement the subtraction-based version.
|
||||
; Euclid's algorithm in QRisc: https://en.wikipedia.org/wiki/Euclidean_algorithm
|
||||
; Since QRisc doesn't do modulo, we implement the subtraction-based version.
|
||||
;
|
||||
; Demonstrates/tests comparisons and conditional branches. This also
|
||||
; demonstrates the common trick of branching in a delay slot. Note that if a
|
||||
Loading…
Add table
Reference in a new issue