BTST not working as expected to determine if number is odd - 68000

I'm confused as to why this code isn't working as expected. From what I understand BTST.L #1,D1 checks if the last bit of the value stored in D1 is 1, in which case the value in D1 would be odd and the program would branch to ADDSUM.
It seems to work correctly with some values (9*2, 8*2 or 10*10), but fails when I try and do others (11*11 gives me 110, same as 10*11). I believe it is whenever the multiplier is odd.
START:
MOVE.W #MULTIPLICAND,D0 ; Set D0 equal to the multiplicand
MOVE.W #MULTIPLIER,D1 ; Set D1 equal to the multiplier
MOVE.L #00000000,D2 ; Clear D2 as it will be used to store the product
LOOP BTST.L #1,D1 ; Check if D1 is odd
BEQ ADDSUM ; If so branch to ADDSUM
RETURN CMP #$01,D1 ; Check if the multiplier is equal to 1
BEQ END ; If so, terminate the loop
ASL #1,D0 ; Multiply the multiplicand by 2
ASR #1,D1 ; Divide the multiplier by two
BRA LOOP ; Branch back to the top of the loop
ADDSUM ADD.W D0,D2 ; Add D0 to D2
BRA RETURN ; After adding, we have to branch back to where we were in the loop
END SIMHALT

I figured it out. I figured I'd post it as an answer just in case anybody else ever stumbles upon this.
It turns out I didn't understand how the BTST.L #1,D1 instruction works. I thought the code in the original example was supposed to be checking if the last bit in D1 was equal to 1. In reality, BTST works by setting the Z condition code flag to 1 when the bit being tested is 0. The #1 in the instruction was specifying that it was testing the second bit from the right.
In order to determine even/odd, the rightmost bit is the one that has to be tested. I fixed my code by changing it to have the following:
LOOP BTST.L #0,D1 ; Check if D1 is even (Z-flag will be set to 1 if bit is zero)
BNE ADDSUM ; BNE will branch to ADDSUM if Z-flag is not set (meaning D1 is odd)
Hopefully this is able to help somebody else who is having the same problem.

Related

Excel Offset performance gain bij adding if()? Answer; NO

update
The volatile functions can't be mitigated with the IF() statement. See answers below. 1
I've just heard my excel sheets need to run on potato speed laptops...
Would;
=IF(A1="Test"** ; OFFSET(B5 ; MATCH(C8 ; G10:G15) ; OFFSET(B5 ; MATCH(C8 ; G9:F9)) ; 0)
be quicker than just the offset functions
=OFFSET(B5 ; MATCH(C8 ; G10:G15) ; OFFSET(B5 ; MATCH(C8 ; G9:F9)) ; 0)
My gut says yes... But I can't find a clear answer if the "unused" part of the IF() function isn't calculated or "volatile".
I have around 120 offset functions on the sheet with 200 MATCH functions. Depending on a lot of variables between 50 and 90 offsets are actually used for the result at one time.
I hope to hear from you,
Koen.
PS; it wouldn't make a difference if I would switch the function and the zero right?
PS; it would be a temporal fix til I can put stuff into the (quicker?) index function.
update
The volatile functions can't be mitigated with the IF() statement.
Last I read, trying to short circuit a Volatile Function with IF still results in the Volatile function being executed, even if it is in the FALSE part of the statement. So what you want to do is remove the volatile OFFSET function rather than try to short circuit it. The INDEX function can return a dynamic range, so that's what I'd use. See my answer at Can Excel's INDEX function return array?
Here's Charles Williams on the matter:
Using a volatile function in a formula will flag the cell containing the formula as volatile, even if the volatile function never gets executed:
=IF(1<2,99,NOW()) will always return 99 and the volatile NOW() function will never be called, but the cell containing the IF formula
will be treated as volatile, (thanks to Stephen Bullen for pointing
this out).
If cell A1 contains =NOW() then =IF(1<2,99,A1) will always return 99,
but the cell containing the IF formula will NOT be treated as
volatile.

Verilog: Aligning valid and invalid bytes from a dynamic input

I'm trying to design a system that takes an 8 byte data input and an 8 bit valid input every clock cycle where each bit on the valid input either validates or invalidates a data byte.
input wire [63:0] d_in;
input wire [7:0] v_in;
The program should process d_in aligning all the valid bytes as follows.
(where B is a valid byte and X is an invalid byte)
Instance 1:
d_in = B1 B2 X X B3 X B4 B5
d_out = B1 B2 B3 B4 B5 X X X
Instance 2:
d_in = X B1 B2 B3 X B4 B5 B6
d_out = B1 B2 B3 B4 B5 B6 X X
I've mainly worked with algorithms before where all bit manipulation was the same every iteration e.g.assign d_out [7:0] = d_in [15:8]; but the fact that the quantity and order of valid bytes can change with every data input means this strategy cannot be used.
My question:
Is there a way to realise this function in using Verilog or VHDL? If so can someone point me towards a high level solution or some relevant reading so I can understand this concept better. I think if I understood at a high level then I'd be able to take a stab a coding it but currently I'm not even sure what I need to be coding.
Thanks
Zach
Since you asked for high level I will give a pseudocode example of something that might work, or at least get you going.
d_out = '0; //Assuming that the X bytes can be set to zero in the output.
bytes = 0;
for i in range(8)
if v_in[i]
d_out[bytes*8 +: 8] = d_in[i*8 +: 8] //Note the +: notation which is not pseudo, but verilog.
bytes++
Now perform this sequential code in an always block and you should be set.
Note: How the synthesized result from this will look is not entierly clear to me, but i suspect it will generate quite a bit of hardware.
I have something similar but not quite.
Input data into a FIFO, pre-calculate a byte-enable with the FIFO entries.
On the output side, read the the byte enable portions and use it to shift out bytes. So there are only eight conditions to satisfy for the byte enable...
1 byte, byteEn(0 downto 1) = "10", shift left 1 byte
2 bytes, byteEn(0 downto 2) = "110", shift left 2 bytes
3 bytes, byteEn(0 downto 3) = "1110", shift left 3 bytes
...and so on...
As you shift, read in the next word using the FIFOs read enable.
Note you will need to take care of when the FIFO is empty but not halt the pipeline so data already present continues to be shifted out.
Not sure how complicated it will be as I have glossed over it a bit.

What is >>>symbol in verilog?

May I know what is this symbol >>> in verilog. When should I use it? Thanks!
e.g
always #(posedge Clock) begin
if (Clear) begin
a < = c>>>8;
b < = d>>>16;
end
end
It is an arithmetic right shift operator (see page 19-20 of the link). It is the reverse case from Java (Java >> is arithmetic right shift, while >>> is logical right shift).
Arithmetic right shift is to handle case when the number right-shifted is positive/negative with this behavior:
Shift right specified number of bits, fill with value of sign bit if
expression is signed, othewise fill with zero
To illustrate, if you have signed expression with value of, say like this:
1000 1100
--------- >>> 2
1110 0011 //note the left most bits are 1
But for unsigned:
1000 1100
--------- >>> 2
0010 0011
The left most will be filled with 0.

Representing and adding negative numbers in Easy68k Assembly

I'm trying to write a simple program in Easy68k that stores to negative values, adds them together, and then outputs them in the console. I am having trouble figuring out how to represent the negative numbers. We are asked that they be in hex format and output in decimal. Everything seems correct but the values themselves. I used 2s complement and then converted the two numbers to hex.
First decimal number = -102
Second decimal number = -87
Using 2s complement I converted the two numbers to hex (though I'm not sure if this is even correct):
-102 -> 1A
-87 -> 29
Here's my code so far:
addr EQU $7CE0
data1 EQU $1A
data2 EQU $29
ORG $1000
START: ; first instruction of program
* Put program code here
MOVE #data2,D1
MOVEA.W #addr,A0
ADD #data1,D1
MOVE D1,(A0)
MOVE.B #3,D0
TRAP #15
* Variables and Strings
* Put variables and constants here
END START ; last line of source
I even tried to just convert binary versions of the negative numbers straight to hex:
-102 -> 11100110 -> E6
-87 -> 11010111 -> D7
Which didn't work either. I also tried storing the binary version and adding them, but got the same result.
Here's the question:
Write a program in assembly to add the two numbers (-102 and -87). Inputs should be in hexadecimal format. Store the result in hexadecimal at an address $7CE0. Print out the result in decimal.(Hint: use the track function task #3). If an error happens, you should also print out the error message as well.
I know I am misrepresenting the two negative numbers, but I just can't figure out how to do it right. I've looked everywhere and found nothing on how to store/add/output negative numbers in 68k. Any help is appreciated, this is for an assignment so I'm not expecting direct answers. Thanks!

How to convert a MIPS string of number to Hexadecimal

I am starting to write a MIPS program where I get a String in hexadecimal representation say A23B , and want to put it together into 1 Entire hex number. I am really lost in the part as how to extract say one Digit , say B and convert it into hex for mips then fetch the other one. I am not looking for an entire program as I know this is not what it is for but as something to start with as I am really lost, thank you.
Consider this. Say your data segment looks like this
.data
str: .space 5 #enough room for a 4 digit hex number
And further, that the memory pointed to by str contains the string you want to convert to a number. To get its first byte into $t1, you would use:
la $t0 str
lb $t1 0($t0)
Next, there are four cases:
'0' < $t1 < '9'
'a' < $t1 < 'f'
'A' < $t1 < 'F'
Error
I'll assume you know how to check these cases.
In all but the last case, we must increment sum by the given value; therefore the next step for the cases would be:
sum += $t1 - '0'
sum += $t1 - 'a' + 10
sum += $t1 - 'A' + 10
Obviously this is pseudo-code, but it illustrates the main point that the ASCII values for the digits and letters are sequential, so calculating their value is trivial.
Lastly, because we know that each digit represents exactly 4 bits, and because we begin reading from left to right, we must shift the sum left by 4 bits:
sll $sum $sum 4
That is the steps for one character, to convert an entire string you would need to loop over each character.

Resources