add sdivmod;
improve build system;
This commit is contained in:
parent
07c64779d8
commit
8480d55faf
11 changed files with 190 additions and 73 deletions
|
|
@ -1,21 +1,22 @@
|
|||
DIRECTORIES = divmod
|
||||
|
||||
all:
|
||||
for mydir in $(DIRECTORIES); do \
|
||||
make -C $$mydir; \
|
||||
done
|
||||
make -C lib
|
||||
|
||||
ir:
|
||||
make -C lib ir
|
||||
|
||||
test:
|
||||
for mydir in $(DIRECTORIES); do \
|
||||
make -C $$mydir test; \
|
||||
done
|
||||
make -C lib test
|
||||
|
||||
clean-test:
|
||||
for mydir in $(DIRECTORIES); do \
|
||||
make -C $$mydir clean-test; \
|
||||
done
|
||||
make -C lib clean-test
|
||||
|
||||
clean-temp:
|
||||
make -C lib clean-temp
|
||||
|
||||
clean:
|
||||
for mydir in $(DIRECTORIES); do \
|
||||
make -C $$mydir clean; \
|
||||
done
|
||||
make -C lib clean
|
||||
|
||||
install: ir
|
||||
make -C lib clean-test
|
||||
make -C lib clean-temp
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
CLANG = clang
|
||||
CF = -Wall -ansi
|
||||
OUTDIR = ..
|
||||
|
||||
all: ir
|
||||
|
||||
$(OUTPUT).c: $(OUTPUT).h
|
||||
|
||||
$(OUTPUT): test.c $(OUTPUT).c
|
||||
$(CLANG) $(CF) -ftrapv -o $@ $+
|
||||
|
||||
test: $(OUTPUT)
|
||||
python test.py
|
||||
|
||||
ir:
|
||||
CLANG -m32 $(CF) -O0 -emit-llvm -S $(OUTPUT).c -o $(OUTDIR)/x86/$(OUTPUT).ll
|
||||
CLANG -m64 $(CF) -O0 -emit-llvm -S $(OUTPUT).c -o $(OUTDIR)/x86_64/$(OUTPUT).ll
|
||||
python ../tools/striptriple.py $(OUTDIR)/x86/$(OUTPUT).ll
|
||||
python ../tools/striptriple.py $(OUTDIR)/x86_64/$(OUTPUT).ll
|
||||
|
||||
clean-test:
|
||||
rm -f $(OUTPUT)
|
||||
|
||||
clean: clean-test
|
||||
rm -f $(OUTDIR)/x86/$(OUTPUT).ll
|
||||
rm -f $(OUTDIR)/x86_64/$(OUTPUT).ll
|
||||
4
llrtc/lib/.gitignore
vendored
Normal file
4
llrtc/lib/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
*.o
|
||||
*.run
|
||||
*.out
|
||||
*.ll
|
||||
|
|
@ -1,44 +1,66 @@
|
|||
OUTPUT = llrt
|
||||
SOURCES = udivmod64.c
|
||||
SOURCES = udivmod64.c sdivmod64.c
|
||||
TESTS = test_udivmod64.c test_sdivmod64.c
|
||||
|
||||
CLANG = clang
|
||||
LLVM_LINK = llvm-link
|
||||
CF = -Wall -ansi
|
||||
CF_TEST = $(CF) -ftrapv
|
||||
CF_BUILD = $(CF) -O0 -emit-llvm
|
||||
OUTDIR = ..
|
||||
STRIPPER = ../tools/striptriple.py
|
||||
|
||||
all: ir
|
||||
|
||||
ir: $(SOURCES)
|
||||
$(CLANG) -m32 $(CF_BUILD) -S -o $(OUTDIR)/$(OUTPUT)_x86.ll -c $(SOURCES)
|
||||
python ../tools/striptriple.py $(OUTDIR)/$(OUTPUT)_x86.ll
|
||||
$(CLANG) -m64 $(CF_BUILD) -S -o $(OUTDIR)/$(OUTPUT)_x86_64.ll -c $(SOURCES)
|
||||
python ../tools/striptriple.py $(OUTDIR)/$(OUTPUT)_x86_64.ll
|
||||
ir: $(OUTDIR)/$(OUTPUT)_x86.ll $(OUTDIR)/$(OUTPUT)_x86_64.ll
|
||||
|
||||
lib$(OUTPUT).a: $(SOURCES)
|
||||
$(CLANG) $(CF) -o $@ -c $+
|
||||
$(OUTDIR)/$(OUTPUT)_x86.ll: $(SOURCES:.c=_x86.bc)
|
||||
$(LLVM_LINK) -S $+ -o $@
|
||||
python $(STRIPPER) $@
|
||||
|
||||
build-test: lib$(OUTPUT).a
|
||||
for src in $(SOURCES); do \
|
||||
$(CLANG) $(CF_TEST) -o test_$${src%.*} test_$$src -L. -lllrt; \
|
||||
done;
|
||||
$(OUTDIR)/$(OUTPUT)_x86_64.ll: $(SOURCES:.c=_x86_64.bc)
|
||||
$(LLVM_LINK) -S $+ -o $@
|
||||
python $(STRIPPER) $@
|
||||
|
||||
test: build-test
|
||||
for src in $(SOURCES); do \
|
||||
echo "testing $${src%.*}"; \
|
||||
python test_$${src%.*}.py > test_$${src%.*}.out; \
|
||||
build-test: $(SOURCES:.c=.o) $(TESTS:.c=.run)
|
||||
|
||||
lib$(OUTPUT).a: $(SOURCES:.c=.o)
|
||||
$(CLANG) -static $+ -o $@
|
||||
|
||||
test: $(TESTS:.c=.run)
|
||||
for src in $+; do \
|
||||
echo "testing $${src}"; \
|
||||
python $${src%.*}.py > $${src%.*}.out; \
|
||||
done;
|
||||
|
||||
clean-test:
|
||||
rm -f *.out
|
||||
rm -f *.a
|
||||
for src in $(SOURCES); do \
|
||||
rm -f test_$${src%.*} ;\
|
||||
done;
|
||||
rm -f *.o
|
||||
rm -f *.run
|
||||
|
||||
clean-dist:
|
||||
rm $(OUTDIR)/*.ll
|
||||
clean-dist: clean-temp
|
||||
rm -f *.ll
|
||||
|
||||
clean-temp:
|
||||
rm -f *.bc
|
||||
rm -f *.o
|
||||
rm -f *.out
|
||||
|
||||
clean: clean-test clean-dist
|
||||
|
||||
udivmod64.c: udivmod64.h
|
||||
%.c: llrt.h
|
||||
|
||||
%_x86.bc: %.c
|
||||
$(CLANG) -m32 $(CF_BUILD) -c $< -o $@
|
||||
|
||||
%_x86_64.bc: %.c
|
||||
$(CLANG) -m64 $(CF_BUILD) -c $< -o $@
|
||||
|
||||
%.o: %.c
|
||||
$(CLANG) $(CF_TEST) -c $<
|
||||
|
||||
%.run: %.c
|
||||
$(CLANG) $(CF_TEST) -o $@ $+
|
||||
|
||||
test_udivmod64.run: udivmod64.o
|
||||
test_sdivmod64.run: udivmod64.o sdivmod64.o
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
#ifndef LLRT_UDIVMOD_H_
|
||||
#define LLRT_UDIVMOD_H_
|
||||
#ifndef LLRT_H_
|
||||
#define LLRT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define BITS_PER_BYTE 8
|
||||
|
||||
uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder);
|
||||
int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder);
|
||||
|
||||
#endif /* LLRT_UDIVMOD_H_ */
|
||||
#endif /* LLRT_H_ */
|
||||
|
||||
40
llrtc/lib/sdivmod64.c
Normal file
40
llrtc/lib/sdivmod64.c
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#include "llrt.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
Calls to udivmod64 internally.
|
||||
Note: remainder uses sign of divisor.
|
||||
*/
|
||||
int64_t sdivmod64(int64_t dividend, int64_t divisor, int64_t *remainder)
|
||||
{
|
||||
int signbitidx = BITS_PER_BYTE * sizeof(dividend) - 1;
|
||||
int signed_dividend = dividend < 0;
|
||||
int signed_divisor = divisor < 0;
|
||||
int signed_result = signed_divisor ^ signed_dividend;
|
||||
|
||||
int64_t quotient;
|
||||
uint64_t udvd, udvr, uquotient, uremainder;
|
||||
|
||||
udvd = signed_dividend ? -dividend : dividend;
|
||||
udvr = signed_divisor ? -divisor : divisor;
|
||||
uquotient = udivmod64(udvd, udvr, &uremainder);
|
||||
|
||||
if (signed_result){
|
||||
if (uremainder) {
|
||||
quotient = -(int64_t)uquotient - 1;
|
||||
} else {
|
||||
quotient = -(int64_t)uquotient;
|
||||
}
|
||||
if (remainder) {
|
||||
/* if signed, there could be unsigned overflow
|
||||
causing undefined behavior */
|
||||
*remainder = (uint64_t)dividend - (uint64_t)quotient * (uint64_t)divisor;
|
||||
}
|
||||
} else {
|
||||
quotient = (int64_t)uquotient;
|
||||
if (remainder) {
|
||||
*remainder = signed_divisor ? -uremainder : uremainder;
|
||||
}
|
||||
}
|
||||
return quotient;
|
||||
}
|
||||
21
llrtc/lib/test_sdivmod64.c
Normal file
21
llrtc/lib/test_sdivmod64.c
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "llrt.h"
|
||||
|
||||
int main(int argc, char * argv[]){
|
||||
int64_t n, d, q, r;
|
||||
|
||||
if (argc != 3) {
|
||||
printf("invalid argument: %s dividend divisor", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
sscanf(argv[1], "%lld", &n);
|
||||
sscanf(argv[2], "%lld", &d);
|
||||
|
||||
q = sdivmod64(n, d, &r);
|
||||
|
||||
printf("%lld\n", q);
|
||||
printf("%lld\n", r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
56
llrtc/lib/test_sdivmod64.py
Normal file
56
llrtc/lib/test_sdivmod64.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import math
|
||||
import os
|
||||
import subprocess
|
||||
udt = os.path.join('.', 'test_sdivmod64.run')
|
||||
|
||||
def testcase(dividend, divisor):
|
||||
print 'divmod64(%d, %d)' % (dividend, divisor)
|
||||
|
||||
procargs = ('%s %s %s' % (udt, dividend, divisor)).split()
|
||||
result = subprocess.check_output(procargs)
|
||||
gotQ, gotR = map(int, result.splitlines())
|
||||
|
||||
expectQ = dividend // divisor
|
||||
expectR = dividend % divisor
|
||||
|
||||
print 'Q = %d, R = %d' % (gotQ, gotR)
|
||||
|
||||
if expectQ != gotQ:
|
||||
raise ValueError("invalid quotient: got=%d but expect=%d" %
|
||||
(gotQ, expectQ))
|
||||
if expectR != gotR:
|
||||
raise ValueError("invalid remainder: got=%d but expect=%d" %
|
||||
(gotR, expectR))
|
||||
print 'OK'
|
||||
|
||||
def testsequence():
|
||||
subjects = [
|
||||
(0, 1),
|
||||
(0, 0xffffffff),
|
||||
(1, 2),
|
||||
(1, 983219),
|
||||
(2, 2),
|
||||
(3, 2),
|
||||
(1024, 2),
|
||||
(2048, 512),
|
||||
(21321, 512),
|
||||
(9329189, 1031),
|
||||
(0xffffffff, 2),
|
||||
(0xffffffff, 0xffff),
|
||||
(0x1ffffffff, 2),
|
||||
(0x1ffffffff, 0xffff),
|
||||
(0xffff, 0xffffffff),
|
||||
(0x0fffffffffffffff, 0xffff),
|
||||
(0x7fffffffffffffff, 0x7fffffffffffffff),
|
||||
(0x7fffffffffffffff, 0x7ffffffffffffff0),
|
||||
(0x7fffffffffffffff, 87655678587161901),
|
||||
]
|
||||
|
||||
for dvd, dvr in subjects:
|
||||
testcase(dvd, dvr)
|
||||
testcase(dvd, -dvr)
|
||||
testcase(-dvd, dvr)
|
||||
testcase(-dvd, -dvr)
|
||||
|
||||
if __name__ == '__main__':
|
||||
testsequence()
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern uint64_t
|
||||
udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder);
|
||||
#include "llrt.h"
|
||||
|
||||
int main(int argc, char * argv[]){
|
||||
uint64_t n, d, q, r;
|
||||
|
|
@ -19,4 +17,4 @@ int main(int argc, char * argv[]){
|
|||
printf("%llu\n", r);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import math
|
||||
import os
|
||||
import subprocess
|
||||
udt = os.path.join('.', 'test_udivmod64')
|
||||
udt = os.path.join('.', 'test_udivmod64.run')
|
||||
|
||||
def testcase(dividend, divisor):
|
||||
print 'divmod64(%d, %d)' % (dividend, divisor)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
Implements unsigned divmod using for platform missing 64-bit division and/or
|
||||
modulo functions.
|
||||
*/
|
||||
#include "udivmod64.h"
|
||||
#include "llrt.h"
|
||||
|
||||
/*
|
||||
count left zero for 64-bit words
|
||||
|
|
@ -79,6 +79,6 @@ uint64_t udivmod64(uint64_t dividend, uint64_t divisor, uint64_t *remainder)
|
|||
quotient |= 1ull << (63 - i);
|
||||
}
|
||||
}
|
||||
*remainder = state.tmp;
|
||||
if (remainder) *remainder = state.tmp;
|
||||
return quotient;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue