OpenCores
Issue List
The BTT instruction on the open8 differs from that of the V8. #1
Closed khays opened this issue almost 14 years ago
khays commented almost 14 years ago

The BTT instruction on the open8 differs from that of the V8/ARClite.

The V8 version of the instruction uses the subop to create a mask to test the desired bit of R0, and the inverse of the bit is set into the Z Flag:

BTT n Z = R0 & (1 << n) ? 0 : 1 N = R07 & (1 << n)

On the Open8, the subop is used to address the register file, and the Z and N flags are set according to the value of Rn:

BTT n Z = (Rn == 0) N = Rn7

The publicly available description of the BTT instruction for the V8 gives the operation as:

"if R0#=0, Set Z else clear Z"

Indicating the nth bit of R0, not the nth register in the register file, is the correct source to test.

khays commented almost 14 years ago

The corrected VHDL would look something like this:

<p> <blockquote> <br> when ALU_BTT => <blockquote> -- Tests if bit n R0 is set or cleared. No change to R0, Flags N, Z <br> -- Flag N is set to R0(7), Flag Z is inverse of R0(Index) <br> Temp := "0" & Regfile(ACCUM); <br> Flags_D(FL_ZERO) <= '0'; <br> if( Temp(Index) = 0 )then <blockquote> Flags_D(FL_ZERO) <= '1'; <br> </blockquote> end if; <br> Flags_D(FL_NEG) <= Temp(7); </blockquote> </blockquote> <p> NB: I haven't compiled or tested this yet.
khays commented almost 14 years ago

This compiles - I apologize in advance for my VHDL skills...I'm sure there is a one-liner that does the same as the case statement, below.

<blockquote> when ALU_BTT => -- Tests if bit n R0 is set or cleared. No change to R0. Flags N, Z <br> -- Flag N is set to R0(7), Flag Z is inverse of R0(Index) <blockquote> Temp := "0" & not Regfile(0); <p> Flags_D(FL_NEG) <= '0'; <p> case Index is <blockquote>when 0 => <blockquote>Flags_D(FL_ZERO) <= Temp(0); </blockquote> when 1 => <blockquote>Flags_D(FL_ZERO) <= Temp(1); </blockquote> when 2 => <blockquote> Flags_D(FL_ZERO) <= Temp(2); </blockquote> when 3 =><blockquote> Flags_D(FL_ZERO) <= Temp(3);</blockquote> when 4 =><blockquote> Flags_D(FL_ZERO) <= Temp(4);</blockquote> when 5 =><blockquote> Flags_D(FL_ZERO) <= Temp(5);</blockquote>when 6 =><blockquote> Flags_D(FL_ZERO) <= Temp(6);</blockquote>when 7 =><blockquote> Flags_D(FL_ZERO) <= Temp(7);</blockquote> </blockquote> end case; <p> if (Temp(7) = '0') then <blockquote> Flags_D(FL_NEG) <= '1'; </blockquote> end if; </blockquote> </blockquote>
jshamlet was assigned almost 14 years ago
jshamlet commented almost 14 years ago

From the look of it, and I haven't tested it yet, I would think you could reduce this to:

when ALU_BTT => Flags_D(FL_ZERO) <= not Regfile(0)(Index); Flags_D(FL_NEG) <= Regfile(0)(7);

This assigns Z = !R0(n), where n = subop/index, and N = R0(7).

khays commented almost 14 years ago

I believe you are correct - again, I'm not a VHDL programmer - I can read it, but have no claims to writing it.

Incidentally, I have gnu binutils ported to the open8/v8/arclite, and am working through some linker issues this week, as well as starting the port of gcc.

jshamlet commented almost 14 years ago

I'm not terribly fluent in Verilog yet, so I'm not clear what is going on with the N flag, but I believe the Z flag is now working correctly, based on what you have found with the original core.

I have uploaded a corrected version to my web host, so I'm going to close this bug for now. If the N bit acts funny, open a new bug, and I'll try to translate the Verilog again.

jshamlet closed this almost 14 years ago

Assignee
jshamlet
Labels
Bug