A simple instruction set architecture (ISA) that operates within the game Turing Complete.
This repository contains its corresponding assembler.
Assembly implementation of the ArchP ISA
Usage: archp_asmc [OPTIONS] [SRC_FILE]
Arguments:
[SRC_FILE] File path to the source assembly file
Options:
--complete <COMPLETE> Print shell auto completions for the specified shell [possible values: bash, elvish, fish, powershell, zsh]
-o, --output <OUTPUT> The output file path [default: <stdout>]
--bin Output binary machine code instead of formatted hex
--disable-macro Disable the macro-instructions
-h, --help Print help
-V, --version Print version
- Comments start with
#or;and continue to the end of the line. - Definite constants using
constdirective:const NAME VALUE(only allowed at the beginning of the file). - Labels are defined by writing the label name followed by a colon (
:) at the beginning of a line. - Operands are separated by spaces or tabs (not
,). - Instructions and labels are case-insensitive.
- Only one instruction or label definition is allowed per line (label and instruction can be on the same line).
- See examples for more details.
Note
The schematic may not be the latest version; please check the commit list to locate the most up-to-date implementation.
Alternatively, you may just get a fixed version from the git tags.
See assets/schematics.
This section is intended for users. If you require detailed information on the encoding formats, please refer to isa.txt.
- 24 general-purpose registers:
r1tor24. - special registers:
r0: always contains 0, you can write to it but it has no effect.io: the level input/output (only in level mode).kb: the keyboard input (only in sandbox mode, read-only).rng: the random number generator (read-only).tmp: used by the assembler for expanding macro-instructions.
In this section:
instr: the instruction name.rd: the destination register.rs1: the first source register.rs2: the second source register.imm12: 12-bit signed immediate value, from-2048to2047.addr12,addr20: 12/20-bit signed relative address offset in the unit of 2-byte.- This usually indicates:
pc = pc + sign_extend(addr << 1).
- This usually indicates:
immX: will be specified in the instruction description.- numeric literal:
42,-7,0b010101,0xFE42, etc.
Note
The 'signed' and 'unsigned' are merely formal distinctions,
you can always use 0xFFFFFFFE (or 0xFFE in 12 bits) to represent -2.
Note
You can not write addr12 directly as a numeric literal, you must use a label.
Note
The macro features are enabled by default.
You can disable them using the --disable-macro option when invoking the assembler.
- instructions:
add,sub,mul,mulh,mulhu,mulhsu,div,remaddi,subi,muli,mulhi,mulhiu,mulhisu,divi,remi
- format:
instr rd rs1 rs2/imm12 - pseudo:
li rd imm12=>addi rd r0 imm12mv rd rs1=>addi rd rs1 0inc rd=>addi rd rd 1dec rd=>subi rd rd 1clr rd=>addi rd r0 0neg rd rs1=>sub rd r0 rs1
- macros:
- When using register series instructions, if the third operand is a numeric literal, it will be automatically replaced with an immediate series instruction.
- When using immediate series instructions, if the immediate is larger the 12-bit, it will be automatically expanded into multiple instructions to load the immediate into a temporary register first.
- e.g.
sub r1 r2 0x1234=>subi r1 r2 0x1234=>lui tmp 0x1; addi tmp tmp 0x234; sub r1 r2 tmp
- instructions:
and,or,xor,nand,nor,xnorandi,ori,xori,nandi,norixnori
- format:
instr rd rs1 rs2/imm12 - pseudo:
not rd rs1=>xori rd rs1 -1
- macros: Same as the Arithmetic instructions.
- instructions:
sll,srl,rol,ror,sra,slli,srli,roli,rori,srai - format:
instr rd rs1 rs2/imm5, whereimm5is a 5-bit unsigned immediate value from0to31. - macros: Same as the Arithmetic instructions.
- instructions:
seq,sne,slt,sge,sltu,sgeuseqi,snei,slti,sgei,sltiu,sgeiu
- format:
instr rd rs1 rs2/imm12 - pseudo:
sgt rd rs1 rs2=>slt rd rs2 rs1sle rd rs1 rs2=>sge rd rs2 rs1sgtu rd rs1 rs2=>sltu rd rs2 rs1sleu rd rs1 rs2=>sgeu rd rs2 rs1s**z rd rs1=>s** rd rs1 r0(forseqz,snez,sltz,sgez,sgtz,slez)
- macros:
- Same as the arithmetic instructions, but with special handling for the pseudo-instructions like
sgt. - e.g.
slt r1 r2 0x1234=>slti r1 r2 0x1234=>lui tmp 0x1; addi tmp tmp 0x234; slt r1 r2 tmp - e.g.
sgt r1 r2 0x1234=>li tmp 0x1234; sgt r1 r2 tmp=>lui tmp 0x1; addi tmp tmp 0x234; slt r1 tmp r2
- Same as the arithmetic instructions, but with special handling for the pseudo-instructions like
lw rd rs1 imm12: load word from memory addressrs1 + imm12intord.lh rd rs1 imm12: load half-word from memory addressrs1 + imm12into the lower 16 bits ofrd, sign-extended.lhu rd rs1 imm12: load half-word from memory addressrs1 + imm12into the lower 16 bits ofrd, zero-extended.lb rd rs1 imm12: load byte from memory addressrs1 + imm12into the lower 8 bits ofrd, sign-extended.lbu rd rs1 imm12: load byte from memory addressrs1 + imm12into the lower 8 bits ofrd, zero-extended.sw rs1 rs2 imm12: store word fromrs2into memory addressrs1 + imm12.sh rs1 rs2 imm12: store the lower 16 bits ofrs2into memory addressrs1 + imm12.sb rs1 rs2 imm12: store the lower 8 bits ofrs2into memory addressrs1 + imm12.- note:
- The unit of memory address is in bytes.
- macros:
- It allows you to use a RISC-V-style offset syntax.
- e.g.
lw rd rs1 4=>lw rd 4(rs1);sw rs1 rs2 -8=>sw rs2 -8(rs1)
Caution
Please ensure that the memory addresses accessed by load and store instructions are properly aligned:
lw,sw: 4-bytelh,lhu,sh: 2-bytelb,lbu,sb: 1-byte (no alignment needed) Unaligned memory accesses is an undefined behavior at the hardware level and may lead to unexpected results.
Note
If you are simulating the hardware stack using a stack pointer register (e.g. const sp r10),
remember to initialize it to point to the top of the stack memory region. (e.g. li sp 4096)
Example: fib.asm
lui rd imm20:rd = imm20 << 12.auipc rd imm20:rd = pc + (imm20 << 12).
- instructions:
beq,bne,blt,bge,bltu,bgeu - format:
instr rs1 rs2 addr12 - pseudo:
bgt rs1 rs2 addr12=>blt rs2 rs1 addr12ble rs1 rs2 addr12=>bge rs2 rs1 addr12bgtu rs1 rs2 addr12=>bltu rs2 rs1 addr12bleu rs1 rs2 addr12=>bgeu rs2 rs1 addr12b**z rs1 addr12=>b** rs1 r0 addr12(forbeqz,bnez,bltz,bgez,bgtz,blez)
- macros:
- If the
rs2operand is a numeric literal, it will be automatically expanded to use a temporary register. - A 32-bit immediate literal is also supported.
- e.g.
beq r1 0x1234 10=>li tmp 0x1234; beq r1 tmp 10=>lui tmp 0x1; addi tmp tmp 0x234; beq r1 tmp 10
- If the
push rs1: push the value ofrs1onto the stack.pop rd: pop the top value from the stack intord.
call addr20: call a subroutine at an address.callr rs1 imm12: call a subroutine at the address(rs1 + sign_extend(imm12)) & ~1.ret: return from the current subroutine.- note:
- The return address is automatically managed by the hardware stack.
jal rd addr20: jump to an address and write the return address (pc + 4) intord.jalr rd rs1 imm12: jump to the address(rs1 + sign_extend(imm12)) & ~1and write the return address (pc + 4) intord.- pseudo:
j addr12=>jal r0 addr12jr rs1=>jalr r0 rs1
- note:
- You may know how to use this instruction if you are familiar with the RISC-V architecture.
col imm24u: set the display color to the 24-bit unsigned immediate valueimm24u(format:0xRRGGBB).spx rs1 rs2: set the(rs1, rs2)position to the color specified by the lastcolinstruction.seg rs1: display the value ofrs1(as 8-bit unsigned) on a 7-segment display.segi imm8u: display the 8-bit unsigned immediate valueimm8uon a 7-segment display.

