|
Author |
Message |
xxxxx
Member |
Does anyone know how to do a divide in VBCC without it becoming a function call, when compiling for 68000?
if I have 2 shorts and I divide one with the other, the linker complains that it needs to link in __ldivs()? Same thing happens if I have 2 unsigned shorts (with __ldivu). I would have expected them to become divs/divu assembler instructions, and glancing at the 68000 code generator, it looks like it is supposed to generate that code.
Any hints?
Cheers
|
Todi
Member |
One solution would be to write your own like this:
short __divu(__reg("d0") short numerator, __reg("d1") short denumerator)="\tdivu\td1,d0\n\text.l\td0\n"; #define divu(numerator, denumerator) __divu(numerator, denumerator)
short __divs(__reg("d0") short numerator, __reg("d1") short denumerator)="\tdivs\td1,d0\n\text.l\td0\n"; #define divs(numerator, denumerator) __divs(numerator, denumerator)
in an own mymath.h file. and the just:
#include "mymath.h"
unsigned short a = divu(x, y); short b = divs(x, y);
|
xxxxx
Member |
Yeah, I guess I will do something similar. I was just hoping I didn't have to :-)
I wrote up a bug in the vbcc bug tracker, but if anyone feels like debugging it, here is what I found out:
I didn't try debugging into the compiler, but looked briefly at the source. There code generation for 68000 checks if the type is long then it does a function call (this is not an issue for 68020 and above, as they can do long divides.
It looks like this condition check in gen_code() must true, because thats what causes it to store the function call: if(x_t[t&NQ]=='l'&&CPU<68020)
My best guess is that the shorts gets converted to a long somewhere, or that assumes that results are longs?
To repro, just compile this code
short TestDiv(short a,short b) { return a/b; }
and watch it spit out this:
_TestDiv movem.l l6,-(a7) move.w (6+l8,a7),d1 ext.l d1 move.w (10+l8,a7),d0 ext.l d0 move.l d1,-(a7) move.l d0,-(a7) move.l d1,-(a7) public __ldivs jsr __ldivs addq.w #8,a7 movem.l (a7)+,d1 l6 reg l8 equ 0 rts
|
ZEROblue
Member |
The operands are subject to integer promotion as mandated by the language specs - there's no such thing as 16/16->16 in the C language. You'll see it does the same for multiplication, and even addition and subtraction unless you cast explicitly. Technically it's not a bug, but of course the code generator could be more clever. I don't know of any fix other than Todi's, but if you're not dependent on C99 you could always try SAS/C and see if it does a better job: http://dl.dropbox.com/u/8177628/sasc658.lha
|
xxxxx
Member |
Ah yeah, that makes sense - I guess that's the fun of a c compiler with 32-bit ints, on a cpu that doesn't support all 32-bit operations :-)
You are right, it doesn't sound like a bug, but would be useful if it was supported :-)
|
xxxxx
Member |
Especially useful if it took could work with both 16-bit and 32-bit numerator, if denominator and output sizes are are 16 bits :-) Anyway, I can dream :-)
|
Raylight
Member |
xxxxx: Especially useful if it took could work with both 16-bit and 32-bit numerator, if denominator and output sizes are are 16 bits :-) Anyway, I can dream :-) if(x_t[t&NQ]=='l'&&CPU<68020) /* das hier ist auch nicht allzu schoen */ (very loosely: "the following ain't exactly pretty") :-) Or... You could grow your own VBCC and implement all non-standard dreams of yours.. :-P I did that myself - building VBCC and VASM for the purpose of being able to tinker with them. I also wanted to test having both 68k and x86 targets on both.. :) They were surprisingly easy to build considering what they are btw..
|
sp_
Member |
You've got the wrong compiler my friend Download the latest at: http://aminet.net/package/dev/asm/AsmPro1.18src
|
|
|