VOGONS


Bug report: imul

Topic actions

First post, by bavi

User metadata
Rank Newbie
Rank
Newbie

Dear DOSBox developers!

I used your nice program for making some tests for a clone of Intel microprocessor. I found that the instruction "imul", the ternary variant, sometimes puts incorrect values into the flags.

Example:

mov si, 7fffh
imul dx, si, 1

DOSBox sets carry flag and overflow flag (CF = 1, OF = 1), while we must have CF = 0 and OF = 0 according to the logic of Intel.

Well, bug report generated, thanks for paying attention!

Reply 1 of 6, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Seems like it could be the IMUL result range checks in instructions.h:

#define DIMULW(op1,op2,op3,load,save)                  \
{ \
Bits res=((Bit16s)op2) * ((Bit16s)op3); \
save(op1,res & 0xffff); \
FillFlagsNoCFOF(); \
if ((res> -32768) && (res<32767)) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
} else { \
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
} \
}

#define DIMULD(op1,op2,op3,load,save) \
{ \
Bit64s res=((Bit64s)((Bit32s)op2))*((Bit64s)((Bit32s)op3)); \
save(op1,(Bit32s)res); \
FillFlagsNoCFOF(); \
if ((res>-((Bit64s)(2147483647)+1)) && \
(res<(Bit64s)2147483647)) { \
SETFLAGBIT(CF,false);SETFLAGBIT(OF,false); \
} else { \
SETFLAGBIT(CF,true);SETFLAGBIT(OF,true); \
} \
}

Should the res<32767 and res<2147483647 be less than or equal?... or the constants greater by one, but that could flip the sign bit depending on the data size.

Reply 2 of 6, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

according to the logic of Intel.

According to the logic of the intel docs or the real processors?

Reply 3 of 6, by ripsaw8080

User metadata
Rank DOSBox Author
Rank
DOSBox Author

FWIW, dynamic core on my system does not set the carry or overflow flag with the given example, but normal and simple core do.

Reply 4 of 6, by bavi

User metadata
Rank Newbie
Rank
Newbie

According to the logic of the intel docs or the real processors?

The question is interesting. Of course, when we run the example on a real processor, we have CF = OF = 0. But if we look through the official documentation of Intel 80186, where this instruction appeared first... There are two tables there: a table of the strict instruction descriptions and the table of the instruction codes. We find this instruction in the second table (though they don't describe there the code of the variant when the second operand is a pointer to memory). But they don't describe it in the first table! Did they forget to do this, or maybe they didn't do it on purpose?.. Or I just saw a wrong paper? Does not clear.

But, in any case:

if ((res> -32768)  && (res<32767))

Of course, there must be

if ((res>= -32768)  && (res<=32767))

Because in my example we have 32767 as the result, and this is not overflow. And, analogously:

if ((res>-((Bit64s)(2147483647)+1)) &&               \
(res<(Bit64s)2147483647))

We must have there instead:

if ((res>=-((Bit64s)(2147483647)+1)) &&               \
(res<=(Bit64s)2147483647))

Reply 5 of 6, by wd

User metadata
Rank DOSBox Author
Rank
DOSBox Author

Of course, when we run the example on a real processor, we have CF = OF = 0.

Did you test this on a 8086 or 80386? As flags behaviour is by times considerably
different from those to the pentium+ generation.

But most likely this is indeed an off by one mistake.

Reply 6 of 6, by bavi

User metadata
Rank Newbie
Rank
Newbie

The tests were run on an Intel Pentium IV and on a clone of Intel 80186c processor.