View Single Post January 6th, 2020, 10:11 AM   #15
drbitboy  Join Date: Dec 2019
Location: Rochester, NY
Posts: 790

Mike Nash solved this issue in the first response, yet this thread hangs around like a stale phart; I apologize for bringing it up.

JesperMP: Go back to the original post of this thread: no matter what you mistakenly believe the 16-bit INTEGER product of two odd 16-bit INTEGERS might be, the correct answer should never be even.

Quote:
 Originally Posted by JesperMP I am mystified with the argumentation that multiplying 20077 and -20423 should result in 26181. Even if you argue that it is what the 16 LSB of the resulting long INT, that is never what should be the result of trying to squeze into a 16-bit INT.
I don't understand why there is any mystery, because 26181 is obviously the correct result, and it is exactly what should be the result of squeezing -410032571 into a 16-bit INTEGER; in fact, that is precisely what the emulator does, when MOVing that value, as a 32-bit LONG, into a 16-bit INTEGER, with proper overflow handling; see the attached files.

Also, to look at it mathematically, although in decimal instead of hexadecimal or binary:

Code:
``` 20077 x -20423 = -410032571
-410032571 AND 65535 = 26181```
Taking an alternate, but equivalent, approach yields the same correct result:
Code:
```-410032571 / 65536 = -6256.6xxx
65536 x -6257 = -410058752
-410032571 - -410058752 = 26181```
So, by using three separate (though equivalent) methods, including the emulator itself, it should be plain that 26181 is indeed the correct answer. The question is why the MUL operation in the emulator uses REALs instead of LONGs, as originally suggested by Mike Nash and verified (as much as possible) by me.

Quote:
 Originally Posted by JesperMP Your Micrologix should trigger a math overflow. It is the only "correct" result in this situation.
That there is a math overflow in this situation is about the only thing you got correct; how I choose to control and use the overflow and the result is my own affair.

Quote:
 Originally Posted by JesperMP I bet that the emulator is only tested to provide correct results when the result falls within -32768 and 32767.
You would lose that bet, because if you multiply 16-bit INTEGERs of 16384 and 3 in the emulator you get the correct low-16-bit answer of -16384; that assumes you handle the overflow correctly. Also if that is the level of testing, then that's a very very poor emulator, and someone was either naive or disingenuous in its design. Not that I am complaining or expecting it to be fixed: you get what you pay for and said emulator is free; the only reason I am using the emulator is that my test case is very simple and does not have physical I/O requirements, and I did not have an 1100 at hand. My only purpose in opening this thread was curiosity i.e. to understand the emulator's unexpected behavior and to bring it to others' attention; I knew all along that 32-bit integers were a workaround, but it was only later that I stumbled onto how to add a LONG data file to an 1100 program.

Quote:
 Originally Posted by JesperMP As I see it, your task requires you to multiply INTs (16 bit), which will produce a long INT (32 bit). So why bother with 16-bit INTs in the first place ?
Because I am only interested in the low 16 bits (15, actually).

In the end I had to go to 32-bit LONGs to get the correct 16-bit result from the emulator, obviously, but the point of this thread is why the 16-bit INTEGER MULtiply instruction gives the wrong answer in the emulator, while the MOVe instruction gives the correct answer.

I have another case where I MULtiply a 32-bit LONG by 1.1G in another LONG, and in that case I am still interested in the lower 31 bits regardless of any overflow condition. Should I have to go to 64-bit LONGLONGs? Are those even available on a MicroLogix controller? Why does a LONG MULtiply with overflow work correctly when the equivalent INTEGER multiply does not?

Since I only want the low 15 bits i.e. I want the result of

Code:
`[[20077 x -20423] MOD 32768]`
which will be identical, in the low 15 bits, to

Code:
`[[20077 x (32768 - 20423)] MOD 32768]`
but I don't have access to 32768 in signed, twos-complement 16-bit INTEGERs, however, what I want is available, in the low 15-bits, in this formula

Code:
`[20077 x -20423] OR -32768`
I do not care about overflow; I can turn on the [Math Overflow Selected] bit (S:2/14), and clear the [Overflow Trap] bit (S:5/0) when overflow occurs.
And every other CPU, that does 16-bit operations, will give me the correct result.

I'm still trying to get my hands on an actual 1100 to try this out; I suspect this is an emulator-only issue, but if not, then what the heck is going on?
Attached Files 32to16.zip (154.1 KB, 0 views)

Last edited by drbitboy; January 6th, 2020 at 10:20 AM. 