freedreno: Rename afuc to QRisc
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

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:
Connor Abbott 2026-03-07 10:04:13 -05:00 committed by Marge Bot
parent 554eec159b
commit 6e3d805735
26 changed files with 248 additions and 250 deletions

View file

@ -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_ */

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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)

View file

@ -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();
}

View file

@ -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,
};

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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_ */

View file

@ -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) \

View file

@ -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
)

View file

@ -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);
}

View file

@ -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_ */

View file

@ -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>

View file

@ -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";

View 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_ */

View file

@ -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>

View file

@ -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

View file

@ -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