The Instruction Set Manual is nearing completion.
As if things weren't serious enough, I'm now reviewing the Load and Store
instructions. And since there is none, I removed them.
Confused ? It's normal : the YASEP has no load or store operation. But there
were opcodes named after this, thinking they would make people feel more
comforable. Which was not the brightest idea ever.
So I removed them and kept the aliases I had created : the Insert and
Extract opcodes. As the name says, they insert and extract bytes or half-words
(8 or 16 bits).
So far the YASEP had these opcodes : IB IH
IHH ESB EZB ESH EZH
End of story ? NO !
Register set ports
The review of the Instruction Set Manual unearthed some concerns I had for a
while : the "Load" and "Store" instructions get auxiliary data from other
implicit registers. Which can create quite an electronic mess... And it's not
flexible enough. It was created for the sake of load and stores, using the
"register pair" system where the Address register provides its LSB to the
shifting unit, so it knows how much alignment is necessary.
While reviewing the ESB / EZB instructions, I remarked that it was a
one-read, one-write instruction (in FORM_RR or FORM_IR). What a waste of coding
space, let's make it a RRR or IRR instruction and get rid of the implicit
operand that must be fetched in the other registers. Easy, and architecturally
But the Insert instructions (IB and IH) are another beast, they need 3 operands
and a destination. The first operand is the register that contains the data to
insert, the second is the word that will receive the data, and the 3rd operand
is the implicit shift count that comes from the corresponding A register if a D
register is written...
It's not cool. First there is this rule, that I thought was critical, of having
only two read ports for the register set. Second, splitting the register set
for performing parallel reads is a trick that can backfire mercilessly later.
Going 3reads-1write would be great... At what cost ?
But wait, the YASEP is already 3reads-1write because there are the conditions
to read. The microYASEP implements this by passing both halves of the extended
instruction through the 2-reads register set. And there is one result that
remains unused during the second cycle... That's it !
So in practice, despite the limitations, the microYASEP is a 4-reads 1-write
engine. 1 read for condition, 3 reads for operands and the destination register
is one of the operands. Great. Now let's create the new flags "READ_DST3" and
"IMM_LSB" and change a lot of the code that is already around... Lots of work
The return of the carry flag
The YASEP has a carry flag and a zero flag so let's put them to good
One concern of the YASEP32 when inserting and extracting unaligned
half-words, is the case when the offset is 3 bytes : only one byte is available
in this case. This means that the result is partial and not working as
expected. The simulator sends an error message but that's not very handy. The
assembly code that detects this case could take at least a pair of
instructions, then there is the leftover to align...
The little stroke of genius is to change the carry flag when such a
situation occurs. Then, for the user's code, it's just a matter of a few
conditional instructions to increment the pointer and store the remaining byte
at the new address (or just skip the alignment sequence). Something like
; Unaligned write :
; memory is pointed to by A2:D2,
; the code stores 16 bits located in R1
IH A2 R1 D2 ; set the carry flag if A2's LSB are 11
EZB 1 R1 R2 CARRY ; If out-of-word then
; extract the high byte to temporary register
ADD 1 A2 CARRY ; point to the next byte
IB R2 A2 D2 CARRY ; now D2 points to the next word
; and its value, R1's high byte is inserted
; in D2's lower byte
It's a bit far fetched but it's still RISC.
Is IHH still needed ?
The instruction "Insert Halfword High" is a special case of IH that was
created to supplement MOV so the user could overwrite the high half-word of a
register. The intended use was this:
; put 12345678h in R1
MOV 5678h R1 ; LSB
IHH 1234h R1 ; MSB
A special opcode was needed because IH would get the shift from one of the A
registers, or use 0, yet we needed to shift by 2 bytes...
Now we have a new IH that gets the shift amount from a register or an
immediate field so things would be great in theory. In practice, there can be
only one immediate number so IH is ruled out.
What we need is a MOV instruction that can shift the immediate value by 16
bits. So here we have it : MOVH. The instruction
sequence is modified a bit :
; put 12345678h in R1
MOVH 1234h R1 ; MSB
OR 5678h R1 ; LSB
YASEP2013 looks better and better...