Open sparr opened 1 year ago
I did not check carefully but I guess you are right about the flag being set due to ldi $a 0
because of its implementation through the sub
opcode.
There is actually a good reason why this is implemented this way. Therefore, I would say this is a design choice; the ALU flags should be considered valid only after a cmp or sub operation. You could still reserve a whole set of opcodes for that operation and "solve" the issue this way.
$a
, therefore the syntax is sub $a $x $dest
-> for any register the operation results in $a - $a -> $dest
.sub reg reg
is a 1-byte instruction, move imm reg
is a 2-byte instruction, therefore it requires an extra fetch cycle to complete.I hope this helps :)
#subruledef reg_gp
{
$a => 0
$b => 1
$c => 2
$d => 3
}
#subruledef reg_all
{
{dst: reg_gp} => dst
$sp => 4
$pc => 5
$out => 6
}
I'll go ahead and close this since the major concerns aren't valid, and the fix for item 4 is going to touch a lot more than just this instruction anyway.
PS: I have a very unrealistic new concern... Implementing ldi 0
differently from other ldi imm
could expose cryptographic implementations on the cpu to timing attacks :)
I should preface this by saying that I haven't built your computer yet, but I want to, either in a simulator or on breadboards, and I prefer to dive into the repository and code before getting physical. So, I'm sorry if some (or, hopefully not, all) of my "will" and "should" below are inaccurate or off base.
ldi {dst: reg} 0 => 0b11 @ 0b01 @ 0b00 @ dst[1:0]
This seems to convert
ldi $a 0
into0b11 01 00 00
which microcode.txt tells me is equivalent tosub $a $a
instead of themove 0 $a
that I would otherwise expect. While that instruction will produce the clearly desired effect of putting 0 into the a register, I think there are a few problems with this:sub
sets flags whilemove
does not. That meansldi $a 0
will set the zero flag, butldi $a 1
will not clear the zero flag. As a programmer, this is not behavior I would expect or desire.ldi $b 0
is converted to0b11 01 00 01
which issub $a $b
. Should the third crumb0b00
here be anotherdst[1:0]
instead so that this will produce0b11 01 01 01
orsub $b $b
?sub reg reg
andmove imm reg
take 4 steps. This optimization saves a byte of code, but costs some power activating a bunch of extra control lines and circuits.dst[1:0]
truncates the dst parameter to 2 bits, soldi $sp 0
is accepted by the assembler and produces identical machine code toldi $a 0
, and ditto for$pc
/$b
and$out
/$c
. This line should include{ assert(reg <= 4) ... }
or equivalent. This concern also applies to{op: alu_op} {operand_1: reg} {operand_2: reg} => 0b11 @ op[1:0] @ operand_1[1:0] @ operand_2[1:0]
I hope at least some of this makes sense and is helpful.