b’DIVEMU.tgz’
#include “DIVEMU.h”
#include
// emulates unsigned integer division, returns divuRet — does not check for divide-by-zero
divuRet emulatedDivu(uint32_t dividend, uint32_t divisor){
divuRet result; // overwritten at end, never read before writing; no init needed
uint64_t reg64=dividend; // init to upper bits = 0, lower bits = dividend
for (unsigned int i =0; i<32; ++i){ // for every bit
reg64=reg64<<1; // bring down a bit of the remainder
uint32_t upper = reg64 >> 32; // upper 32 bits of 64 bit value = positional remainder
unsigned int shouldSub = upper >= divisor; // Boolean value — either 0:False or 1:True
if(shouldSub){
reg64 -= ((uint64_t) divisor)<<32; // no carry from lower 32 bits, due to check
}
reg64=reg64|shouldSub; // output 1 bit of quotient; space is there due to earlier shift
}
result.quotient=reg64 & 0xFFFFFFFF; // extract quotient field
result.remainder=reg64 >> 32; // extract remainder field
return result;
}
// helper function for emulating a 64 bit value with two 32-bit values
void splitshifter(uint32_t * upper, uint32_t * lower){
unsigned int lower31 = ((*lower) >> 31) & 1; // get msb of lower 32-bit value
*upper = ((*upper)<<1) | lower31; // shift upper to make room, or in saved msb
*lower = (*lower)<<1; // shift lower bits
}
// emulates signed integer division, returns divRet -- does not check for divide-by-zero, remainder and dividend signs must be equal
divRet emulatedDiv(int32_t dividend, int32_t divisor){
divRet result;
uint32_t reg64upper=0; // init
uint32_t reg64lower; // will be initialized later
uint32_t dividendMagnitude = (dividend>=0)?dividend:(~dividend + 1); // convert to unsigned
uint32_t divisorMagnitude = (divisor>=0)?divisor:(~divisor + 1); // convert to unsigned
unsigned int shouldInvertQuotient = (divisor>>31 & 1) ^ (dividend>>31 & 1); // Check if sign bits are the same or different
reg64lower=dividendMagnitude; // init
for (unsigned int i = 0; i<32; ++i){
splitshifter(®64upper, ®64lower); // bring down bit of remainder
unsigned int shouldSub = reg64upper >= divisorMagnitude;
if ( shouldSub){
reg64upper -= divisorMagnitude; // check precludes borrow from lower 32
}
reg64lower = reg64lower | shouldSub; // generate one bit of quotient
}
// fix sign issues
result.quotient = (shouldInvertQuotient)?(~reg64lower + 1):reg64lower; // fix quotient sign
if(reg64upper && ((dividend>>31 & 1) ^ (reg64upper>>31 & 1))){ // make remainder agree
result.remainder = reg64upper-divisorMagnitude; // with sign of divisor
} else {
result.remainder = reg64upper;
}
return result;
}
#include
// return value pair for unsigned integer division
typedef struct divuRet{
uint32_t quotient;
uint32_t remainder;
} divuRet;
// return value pair for signed integer division
typedef struct divRet{
int32_t quotient;
int32_t remainder;
} divRet;
// emulates unsigned integer division, returns divuRet — does not check for divide-by-zero
divuRet emulatedDivu(uint32_t dividend, uint32_t divisor);
// emulates signed integer division, returns divRet — does not check for divide-by-zero, remainder and dividend signs must be equal
divRet emulatedDiv(int32_t dividend, int32_t divisor);
#include
#include “DIVEMU.h”
int main(int argc, char** argv){
uint32_t A = 43;
uint32_t B = 7;
divuRet unsignedResult=emulatedDivu(A,B);
fprintf(stdout, “A = %u, B = %u, A/B =
B = 0;
unsignedResult=emulatedDivu(A,B);
fprintf(stdout, “A = %u, B = %u, A/B =
A = 7;
B= 43;
unsignedResult=emulatedDivu(A,B);
fprintf(stdout, “A = %u, B = %u, A/B =
A = 24;
B= 7;
unsignedResult=emulatedDivu(A,B);
fprintf(stdout, “A = %u, B = %u, A/B =
int32_t C = 18;
int32_t D = 2;
divRet signedResult=emulatedDiv(C,D);
fprintf(stdout, “C = %d, D = %d, C/D =
C = -18;
D = -2;
signedResult=emulatedDiv(C,D);
fprintf(stdout, “C = %d, D = %d, C/D =
C = -18;
D = 2;
signedResult=emulatedDiv(C,D);
fprintf(stdout, “C = %d, D = %d, C/D =
C = 18;
D = -2;
signedResult=emulatedDiv(C,D);
fprintf(stdout, “C = %d, D = %d, C/D =
C = 18;
D = 4;
signedResult=emulatedDiv(C,D);
fprintf(stdout, “C = %d, D = %d, C/D =
C = -18;
D = -4;
signedResult=emulatedDiv(C,D);
fprintf(stdout, “C = %d, D = %d, C/D =
C = -18;
D = 4;
signedResult=emulatedDiv(C,D);
fprintf(stdout, “C = %d, D = %d, C/D =
C = 18;
D = -4;
signedResult=emulatedDiv(C,D);
fprintf(stdout, “C = %d, D = %d, C/D =
return 0;
}
DIVEMU/DIVEMU.c
DIVEMU/DIVEMU.h
DIVEMU/main.c