S21 A Hypothetical 32-bit Processor
This is a typical simple 32-bit CPU. It has a three-address
instruction architecture, with 32 registers and load/store
instructions. This document presents only S21 assembly language view.
It does not give details about microarchitecture (such as pipeline).
S21 has three-address instruction set. A general format of an
instruction (register to register operations) is:
op
r1 r2 r3 means R[r1] = R[r2] op R[r3]
To pass values between memory and registers, load/store instructions
are used. There are three addressing mode: absolute, indirect and
index.
load means R <- mem
store means mem <- R
ld
r1,ads R[r1] =
M[ads] absolute
ld
r1,d(r2) R[r1] =
M[d+R[r2]] indirect
ld
r1,(r2+r3) R[r1] = M[R[r2]+R[r3]] index
st
r1,ads M[ads] =
R[r1] absolute
st
r1,d(r2) M[d+R[r2]] =
R[r1] indirect
st
r1,(r2+r3) M[R[r2]+R[r3]] = R[r1] index
In assembly language, these addressing modes are written as (using the
convention op dest <- source):
ld
r1,ads ld r1 ads
ld
r1,d(r2) ld r1 @d r2
ld
r1,(r2+r3) ld r1 +r2 r3
st
r1,ads st ads r1
st
r1,d(r2) st @d r2 r1
st
r1,(r2+r3) st +r2 r3 r1
There are three flags: Zero, Carry, Overflow/underflow.
Instruction type
arith & logic: add sub
mul div and or xor eq ne lt le gt ge shl shr
control flow: jmp jt jf
jal ret
data:
ld st mv push pop
Instruction meaning
false == 0
true != 0
R[0] always zero
op r1 r2
r3 is R[r1] = R[r2] op R[r3]
op r1 r2
#n is R[r1] = R[r2] op n
ld
r1,ads is R[r1] =
M[ads] absolute
ld
r1,d(r2) is R[r1] =
M[d+R[r2]] indirect
ld r1,(r2+r3)
is R[r1] = M[R[r2]+R[r3]] index
st
r1,ads is M[ads]
= R[r1] absolute
st
r1,d(r2) is M[d+R[r2]] =
R[r1] indirect
st r1,(r2+r3)
is M[R[r2]+R[r3]] = R[r1] index
jmp
ads
is pc = ads
jt r1
ads is if R[r1]
!= 0 pc = ads
jf r1
ads is if R[r1]
== 0 pc = ads
jal
r1,ads is R[r1] = PC;
PC = ads
// jump and link, to subroutine
ret
r1
is PC = R[r1]
// return from subroutine
mv r1
r2 is R[r1]
= R[r2]
mv r1
#n is R[r1]
= #n
push r1
r2 is R[r1]++; M[R[r1]]
= R[r2]
// push r2, r1 as sp
pop r1
r2 is R[r2] = M[R[r1]];
R[r1]--
// pop to r2, r1 as sp
arithmetic
two-complement integer arithmetic
add
r1,r2,r3 R[r1] = R[r2] + R[r3]
add
r1,r2,#n R[r1] = R[r2] + sign extended n (n is
17 bits)
add, sub affect Z,C -- C indicates carry (add) or borrow (sub)
mul, div affect Z,O -- O indicates overlow (mul) or underflow (div) and
divide by zero
logic (bitwise)
and
r1,r2,r3 R[r1] = R[r2] bitand R[r3]
and
r1,r2,#n R[r1] = R[r2] bitand sign extended n
. . .
eq
r1,r2,r3 R[r1] = R[r2] == R[r3]
eq
r1,r2,#n R[r1] = R[r2] == #n
. . .
shl
r1,r2,r3 R[r1] = R[r2] << R[r3]
shl
r1,r2,#n R[r1] = R[r2] << #n
. . .
affect Z,S bits
trap
n special
instruction, n is in r1-field.
trap
0
stop simulation
trap
1
print integer in R[30]
trap
2
print character in R[30]
stack operation
To facilitate passing the parameters to a subroutine and also to save
state (link register) for recursive call, two stack operations are
defined: push, pop. r1-field is used as a stack pointer.
Instruction format
L-format
op:5 rd1:5 ads:22
D-format op:5
rd1:5 rs2:5 disp:17
X-format op:5
rd1:5 rs2:5 rs3:5 xop:12
(rd dest, rs source, ads and disp sign extended)
Instructions are fixed length at 32-bit. Register set is 32, with
R[0] always return zero. The address space is 32-bit, addressing is
word. Flags are: Z zero, S sign, C carry, O overflow/underflow.
ISA and opcode encoding
mode:
a - absolute
d - displacement
x - index
i - immediate
r - register
r2 - register 2 operands
s - special 1 operand
opcode op mode format
0 nop
1 ld
a L ld r1 ads
2 ld
d D ld r1 d(r2)
3 st
a L st ads r1
4 st
d D st d(r2) r1
5 mv
a L mv r1 #n (22 bits)
6 jmp
a L
r1 = 0
7 jal
a L jal r1 ads
8 jt
a L
9 jf
a L
10 add
i D add r1 r2 #n
11 sub
i D
12 mul
i D
13 div
i D
14 and
i D
15 or
i D
16 xor
i D
17 eq
i D
18 ne
i D
19 lt
i D
20 le
i D
21 gt
i D
22 ge
i D
23 shl
i D
24 shr
i D
25..30 undefined
31 xop
- X
xop
0 add
r X add r1 r2 r3
1 sub
r X
2 mul
r X
3 div
r X
4 and
r X
5 or
r X
6 xor
r X
7 eq
r X
8 ne
r X
9 lt
r X
10 le
r X
11 gt
r X
12 ge
r X
13 shl
r X
14 shr
r X
15 mv
r2 X mv r1 r2
16 ld
x X ld r1 (r2+r3)
17 st
x X st (r2+r3) r1
18 ret
s X use r1
19 trap
s X use r1 as number
of trap
20 push
r2 X use r1
as stack pointer
21 pop
r2 X use r1
as stack pointer
22 not
r2 X
23..4095 undefined
Historical fact
S21 is an extension of S2 in 2007, as a result of my experience in
teaching assembly language. S2 has been used for teaching since
2001.
S2 itself is an "extended" version of S1 (a 16-bit cpu) which is used
since 1997.
To improve understandability of S2 assembly language, flags are not
used. Instead, new logical instructions that have 3-address are
introduced. They are similar to existing arith
instructions. The result (true/false) is stored in a
register. Two new conditional jumps are introduced "jt", "jf" to
make use of the result from logical instructions. Also to avoid
the confusion between absolute addressing and moving between registers,
a new instruction "mv" is introduced. (and to make ld/st symmetry, "ld
r1 #n" is eliminated.)
The opcode format and assembly language format for S2 follow the
tradition dest = source1 op source2 from PDP, VAX and IBM S360. As r0
always is zero, many instructions can be synthesis using r0.
or
r1,r2,r0 move r1 <-
r2
or
r1,r0,r0 clear r1
sub
r0,r1,r2 compare r1 r2
affects flags
To complement a register, xor with 0xFFFFFFFF (-1) can be used.
xor
r1,r2,#-1 r1 = complement r2
last update 20 Nov 2010