You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SPDX-License-Identifier: GPL-2.0-only
(c) William Fonkou Tambe
PUxx Instruction Set
All instructions are 16 bits except for the instructions
li16/inc16/rli16, li32/inc32/rli32, li64/inc64/rli64
which are respectively 32, 48, 80 bits.
All instructions must be 16 bits aligned.
Notations
%ip is the instruction pointer register which hold
the address of the current instruction, or in other words,
the address of the instruction being decoded.
ipnext refers to the address of the next instruction.
%gpr refers to one of the general purpose registers %0 thru %15.
%gpr1 and %gpr2 are used when an instruction makes use of two
general purpose registers.
msb stands for most significant bit(s).
lsb stands for least significant bit(s).
An example of binary representation
of an instruction is as follow:
|op|010|rrrr|iiii|
'op' is a 5bits value in decimal; is
4bits in binary for li8/inc8.
'0' represent a bit with a value 0.
'1' represent a bit with a value 1.
'r' represent a bit of a gpr index;
when eight of them are used,
the first four correspond
to %gpr1, and the second four
correspond to %gpr2.
'i' represent a bit of an immediate value.
General Purpose Instructions
Arithmetic
add %gpr1, %gpr2 |23|000|rrrr|rrrr|
%gpr1 += %gpr2;
sub %gpr1, %gpr2 |23|001|rrrr|rrrr|
%gpr1 -= %gpr2;
mul %gpr1, %gpr2 |25|010|rrrr|rrrr|
Signed low multiplication.
%gpr1 *= %gpr2;
the result of the integer multiplication
is 32/64/128 bits, but only the 16/32/64 lsb of the result
get stored in %gpr1, while the 16/32/64 msb can be
retrieved using the instruction mulh.
mulu %gpr1, %gpr2 |25|000|rrrr|rrrr|
Unsigned low multiplication.
%gpr1 *= %gpr2;
the result of the integer multiplication
is 32/64/128 bits, but only the 16/32/64 lsb of the result
get stored in %gpr1, while the 16/32/64 msb can be
retrieved using the instruction mulhu.
mulh %gpr1, %gpr2 |25|011|rrrr|rrrr|
Signed high multiplication.
%gpr1 *= %gpr2;
the result of the integer multiplication
is 32/64/128 bits, but only the 16/32/64 msb of the result
get stored in %gpr1, while the 16/32/64 lsb can be
retrieved using the instruction mul.
mulhu %gpr1, %gpr2 |25|001|rrrr|rrrr|
Unsigned high multiplication.
%gpr1 *= %gpr2;
the result of the integer multiplication
is 32/64/128 bits, but only the 16/32/64 msb of the result
get stored in %gpr1, while the 16/32/64 lsb can be
retrieved using the instruction mulu.
div %gpr1, %gpr2 |25|110|rrrr|rrrr|
Signed integer division.
%gpr1 /= %gpr2;
the sign of the quotient is positive if
the dividend and divisor have the same sign
otherwise it is negative.
mod %gpr1, %gpr2 |25|111|rrrr|rrrr|
Signed integer modulo.
%gpr1 %= %gpr2;
the sign of the remainder is the same as
the sign of the dividend.
divu %gpr1, %gpr2 |25|100|rrrr|rrrr|
Unsigned integer division.
%gpr1 /= %gpr2;
modu %gpr1, %gpr2 |25|101|rrrr|rrrr|
Unsigned integer modulo.
%gpr1 %= %gpr2;
Bitwise
and %gpr1, %gpr2 |24|011|rrrr|rrrr|
%gpr1 &= %gpr2;
or %gpr1, %gpr2 |24|100|rrrr|rrrr|
%gpr1 |= %gpr2;
xor %gpr1, %gpr2 |24|101|rrrr|rrrr|
%gpr1 ^= %gpr2;
not %gpr1, %gpr2 |24|110|rrrr|rrrr|
%gpr1 = ~%gpr2;
cpy %gpr1, %gpr2 |24|111|rrrr|rrrr|
%gpr1 = %gpr2;
"cpy %0, %0" is the official
NOP instruction.
sll %gpr1, %gpr2 |24|000|rrrr|rrrr|
Logical left shift.
%gpr1 <<= %gpr2[5/4/3:0];
srl %gpr1, %gpr2 |24|001|rrrr|rrrr|
Logical right shift.
%gpr1 >>= %gpr2[5/4/3:0];
sra %gpr1, %gpr2 |24|010|rrrr|rrrr|
Arithmetic right shift.
%gpr1 >>= %gpr2[5/4/3:0];
jz %gpr1 %gpr2 |26|000|rrrr|rrrr|
if (!%gpr1) %ip = %gpr2;
The lsb of %gpr2 is ignored,
automatically aligning to 16 bits.
Hence, instruction alignfault
never occurs.
jnz %gpr1 %gpr2 |26|001|rrrr|rrrr|
if (%gpr1) %ip = %gpr2;
The lsb of %gpr2 is ignored,
automatically aligning to 16 bits.
Hence, instruction alignfault
never occurs.
jl %gpr1 %gpr2 |26|010|rrrr|rrrr|
Jump-and-link.
%gpr1 = ipnext; %ip = %gpr2;
The lsb of %gpr2 is ignored,
automatically aligning to 16 bits.
Hence, instruction alignfault
never occurs.
rli8 %gpr, imm |1110|iiii|rrrr|iiii|
Relative load-immediate.
Set %gpr using the sign extend
8bits immediate added to ipnext.
rli16 %gpr, imm |21|101|rrrr|0000|
|iiiiiiiiiiiiiiii|
Relative load-immediate.
Set %gpr using the sign extended
16bits little-endian immediate
added to ipnext.
rli32 %gpr, imm |21|110|rrrr|0000|
|iiiiiiiiiiiiiiii| 2 least-significant-bytes.
|iiiiiiiiiiiiiiii| 2 most-significant-bytes.
Relative load-immediate.
Set %gpr using the sign extended
32bits little-endian immediate
added to ipnext.
rli64 %gpr, imm |21|111|rrrr|0000|
|iiiiiiiiiiiiiiii| 2 least-significant-bytes.
|iiiiiiiiiiiiiiii|
|iiiiiiiiiiiiiiii|
|iiiiiiiiiiiiiiii| 2 most-significant-bytes.
Relative load-immediate.
Set %gpr using the sign extended
64bits little-endian immediate
added to ipnext.
Memory Access
ld8 %gpr1, %gpr2 |30|100|rrrr|rrrr|
Load an 8 bits value from
the memory location in %gpr2, and
save it in %gpr1, zero extending %gpr1.
ld16 %gpr1, %gpr2 |30|101|rrrr|rrrr|
Load a 16 bits value from
the memory location in %gpr2, and
save it in %gpr1, zero extending %gpr1.
In usermode an alignfault occurs
if the lsb of %gpr2 is non-null, but
in kernelmode the lsb of %gpr2 is ignored
automatically aligning to 16 bits.
ld32 %gpr1, %gpr2 |30|110|rrrr|rrrr|
Load a 32 bits value from
the memory location in %gpr2,
and save it in %gpr1.
In usermode an alignfault occurs
if either of the 2 lsb of %gpr2 are non-null,
but in kernelmode the 2 lsb of %gpr2 are ignored
automatically aligning to 32 bits.
ld64 %gpr1, %gpr2 |30|111|rrrr|rrrr|
Load a 64 bits value from
the memory location in %gpr2,
and save it in %gpr1.
In usermode an alignfault occurs
if either of the 3 lsb of %gpr2 are non-null,
but in kernelmode the 3 lsb of %gpr2 are ignored
automatically aligning to 64 bits.
st8 %gpr1, %gpr2 |30|000|rrrr|rrrr|
Store the 8 lsb of %gpr1 to
the memory location in %gpr2.
st16 %gpr1, %gpr2 |30|001|rrrr|rrrr|
Store the 16 lsb of %gpr1 to
the memory location in %gpr2.
In usermode an alignfault occurs
if the lsb of %gpr2 is non-null, but
in kernelmode the lsb of %gpr2 is ignored
automatically aligning to 16 bits.
st32 %gpr1, %gpr2 |30|010|rrrr|rrrr|
Store the value of %gpr1 to
the memory location in %gpr2.
In usermode an alignfault occurs
if either of the 2 lsb of %gpr2 are non-null,
but in kernelmode the 2 lsb of %gpr2 are ignored
automatically aligning to 32 bits.
st64 %gpr1, %gpr2 |30|011|rrrr|rrrr|
Store the value of %gpr1 to
the memory location in %gpr2.
In usermode an alignfault occurs
if either of the 3 lsb of %gpr2 are non-null,
but in kernelmode the 3 lsb of %gpr2 are ignored
automatically aligning to 64 bits.
ld8v %gpr1, %gpr2 |14|100|rrrr|rrrr|
Volatile ld8.
Bypass and update l1-dcache.
ld16v %gpr1, %gpr2 |14|101|rrrr|rrrr|
Volatile ld16.
Bypass and update l1-dcache.
ld32v %gpr1, %gpr2 |14|110|rrrr|rrrr|
Volatile ld32.
Bypass and update l1-dcache.
ld64v %gpr1, %gpr2 |14|111|rrrr|rrrr|
Volatile ld64.
Bypass and update l1-dcache.
st8v %gpr1, %gpr2 |14|000|rrrr|rrrr|
Volatile st8.
Bypass and update l1-dcache.
st16v %gpr1, %gpr2 |14|001|rrrr|rrrr|
Volatile st16.
Bypass and update l1-dcache.
st32v %gpr1, %gpr2 |14|010|rrrr|rrrr|
Volatile st32.
Bypass and update l1-dcache.
st64v %gpr1, %gpr2 |14|011|rrrr|rrrr|
Volatile st64.
Bypass and update l1-dcache.
ldst8 %gpr1, %gpr2 |31|000|rrrr|rrrr|
Atomically swap the 8 bits value
of the memory location in %gpr2
with %gpr1, zero extending %gpr1.
ldst16 %gpr1, %gpr2 |31|001|rrrr|rrrr|
Atomically swap the 16 bits value
of the memory location in %gpr2
with %gpr1, zero extending %gpr1.
In usermode an alignfault occurs
if the lsb of %gpr2 is non-null, but
in kernelmode the lsb of %gpr2 is ignored
automatically aligning to 16 bits.
ldst32 %gpr1, %gpr2 |31|010|rrrr|rrrr|
Atomically swap the 32 bits value
of the memory location in %gpr2
with the value of %gpr1.
In usermode an alignfault occurs
if either of the 2 lsb of %gpr2 are non-null,
but in kernelmode the 2 lsb of %gpr2 are ignored
automatically aligning to 32 bits.
ldst64 %gpr1, %gpr2 |31|011|rrrr|rrrr|
Atomically swap the 64 bits value
of the memory location in %gpr2
with the value of %gpr1.
In usermode an alignfault occurs
if either of the 3 lsb of %gpr2 are non-null,
but in kernelmode the 3 lsb of %gpr2 are ignored
automatically aligning to 64 bits.
cldst8 %gpr1, %gpr2 |31|100|rrrr|rrrr|
Atomically perform following:
- Load 8 bits value from memory
location in %gpr2, zero-extending it.
- Compare %sr with loaded value on whether equal.
- If above comparison is true, swap 8 bits value
of memory location in %gpr2 with %gpr1 value,
otherwise only save loaded value in %gpr1.
cldst16 %gpr1, %gpr2 |31|101|rrrr|rrrr|
Atomically perform following:
- Load 16 bits value from memory
location in %gpr2, zero-extending it.
- Compare %sr with loaded value on whether equal.
- If above comparison is true, swap 16 bits value
of memory location in %gpr2 with %gpr1 value,
otherwise only save loaded value in %gpr1.
cldst32 %gpr1, %gpr2 |31|110|rrrr|rrrr|
Atomically perform following:
- Load 32 bits value from memory
location in %gpr2.
- Compare %sr with loaded value on whether equal.
- If above comparison is true, swap 32 bits value
of memory location in %gpr2 with %gpr1 value,
otherwise only save loaded value in %gpr1.
cldst64 %gpr1, %gpr2 |31|111|rrrr|rrrr|
Atomically perform following:
- Load 64 bits value from memory
location in %gpr2.
- Compare %sr with loaded value on whether equal.
- If above comparison is true, swap 64 bits value
of memory location in %gpr2 with %gpr1 value,
otherwise only save loaded value in %gpr1.
Pseudo-Instructions
nop
cpy %0, %0;
inc16 %gpr1, imm
inc16 %gpr1, %gpr1, imm
inc32 %gpr1, imm
inc32 %gpr1, %gpr1, imm
inc64 %gpr1, imm
inc64 %gpr1, %gpr1, imm
preemptctx
inc8 %0, 0;
Triggers PreemptIntr when in usermode
and %flags.disPreemptIntr is not set.
j %gpr
jnz %gpr, %gpr;
Jump to address 0 is done using:
jz %gpr, %gpr;
syscall |0|001|0000|0000|
System-call instruction.
When used in kernelmode, it is a hypercall.
By convention, the system-call number
must be set in %sr.
brk |0|010|0000|0000|
Software breakpoint instruction.