A.D.A. Amiga Demoscene Archive

        Welcome guest!




log in with SceneID


Demos Amiga Demoscene Archive Forum / Coding / divs/divu from VBCC's C compiler


Author Message
#1 - Posted: 2 Mar 2013 17:00
Reply Quote
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?

#2 - Posted: 2 Mar 2013 19:49 - Edited
Reply Quote
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);

#3 - Posted: 3 Mar 2013 07:56
Reply Quote
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:

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:

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
#4 - Posted: 3 Mar 2013 15:55
Reply Quote
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:

#5 - Posted: 4 Mar 2013 05:12
Reply Quote
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 :-)
#6 - Posted: 4 Mar 2013 05:46
Reply Quote
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 :-)
#7 - Posted: 22 Jun 2013 14:03
Reply Quote
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 :-)

/* 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..
#8 - Posted: 21 Dec 2013 05:23
Reply Quote
You've got the wrong compiler my friend

Download the latest at:



  Please log in to comment





A.D.A. Amiga Demoscene Archive, Version 3.0