diff --git a/cfg/kim1-60k.cfg b/cfg/kim1-60k.cfg new file mode 100644 index 000000000..a6704d9dd --- /dev/null +++ b/cfg/kim1-60k.cfg @@ -0,0 +1,41 @@ +# kim1.cfg (4k) +# +# for unexpanded Kim-1 +# +# ld65 --config kim1.cfg -o .bin .o + +FEATURES { + STARTADDRESS: default = $2000; + CONDES: segment = STARTUP, + type = constructor, + label = __CONSTRUCTOR_TABLE__, + count = __CONSTRUCTOR_COUNT__; + CONDES: segment = STARTUP, + type = destructor, + label = __DESTRUCTOR_TABLE__, + count = __DESTRUCTOR_COUNT__; +} + +SYMBOLS { + __STACKSIZE__: type = weak, value = $0080; # 128 byte program stack + __STARTADDRESS__: type = export, value = %S; +} + +MEMORY { + ZP: file = %O, define = yes, start = $0000, size = $00EE; + CPUSTACK: file = "", define = yes, start = $0100, size = $0100; + RAM: file = %O, define = yes, start = %S, size = $E000 - %S - __STACKSIZE__; + MAINROM: file = "", define = yes, start = $E000, size = $1000; + TOP: file = "", define = yes, start = $F000, size = $1000; +} + +SEGMENTS { + ZEROPAGE: load = ZP, type = zp, define = yes; + STARTUP: load = RAM, type = ro, define = yes; + CODE: load = RAM, type = ro, define = yes; + RODATA: load = RAM, type = ro, define = yes; + ONCE: load = RAM, type = ro, define = yes; + DATA: load = RAM, type = rw, define = yes; + BSS: load = RAM, type = bss, define = yes; +} + diff --git a/include/kim1.h b/include/kim1.h index 52e690c9d..bb616f7a0 100644 --- a/include/kim1.h +++ b/include/kim1.h @@ -2,7 +2,7 @@ /* */ /* kim1.h */ /* */ -/* Kim-1 system-specific definitions */ +/* KIM-1 system-specific definitions */ /* */ /* */ /* */ @@ -33,7 +33,7 @@ /* Check for errors */ #if !defined(__KIM1__) -# error This module may only be used when compiling for the Kim-1! +# error This module may only be used when compiling for the KIM-1! #endif diff --git a/libsrc/kim1/crt0.s b/libsrc/kim1/crt0.s index 7e7dd485b..aefdc3545 100644 --- a/libsrc/kim1/crt0.s +++ b/libsrc/kim1/crt0.s @@ -1,5 +1,5 @@ ; -; Startup code for cc65 (kim-1 version) +; Startup code for cc65 (KIM-1 version) ; .export _init, _exit diff --git a/samples/kim1/Makefile b/samples/kim1/Makefile index 89600ad5a..74c415fdc 100644 --- a/samples/kim1/Makefile +++ b/samples/kim1/Makefile @@ -32,7 +32,8 @@ else endif EXELIST_kim1 = \ - kimHello.bin + kimHello.bin \ + kimSieve.bin ifneq ($(EXELIST_$(SYS)),) samples: $(EXELIST_$(SYS)) @@ -49,8 +50,13 @@ else @echo > $(NULLDEV) endif +kimSieve.bin: kimSieve.c + $(CL) -t kim1 -C kim1-60k.cfg -O -o kimSieve.bin kimSieve.c + kimHello.bin: kimHello.c $(CL) -t kim1 -O -o kimHello.bin kimHello.c clean: + @$(DEL) kimSieve.bin 2>$(NULLDEV) @$(DEL) kimHello.bin 2>$(NULLDEV) + diff --git a/samples/kim1/kimSieve.c b/samples/kim1/kimSieve.c new file mode 100644 index 000000000..29cd7c7e9 --- /dev/null +++ b/samples/kim1/kimSieve.c @@ -0,0 +1,125 @@ +#include +#include + +typedef unsigned char byte; +typedef unsigned short int ushort; +typedef unsigned long int ulong; + +#define LIMIT 100000L + +// BITARRAY +// +// My bit-access macros pre-divide by two on the presumption that you'll never +// try try access both odd and even bits! + +#define GETBIT(array, bit) (array[bit >> 4] & (1 << ((bit >> 1) & 7))) +#define SETBIT(array, bit) (array[bit >> 4] |= (1 << ((bit >> 1) & 7))) +#define CLRBIT(array, bit) (array[bit >> 4] &= ~(1 << ((bit >> 1) & 7))) + +// RepeatChar +// +// Outputs a given character N times + +void RepeatChar(char c, size_t count) +{ + while (count--) + putc(c, stdout); +} + +// sqrti +// +// Binary search integer square root + +ushort sqrti(ulong num) +{ + long i; + ulong ret = 0; + + for(i = 15; i >= 0; i--) + { + ulong temp = ret | (1L << (ulong)i); + if(temp * temp <= num) + { + ret = temp; + } + } + return ret; +} + +// main() +// +// CC65 main function receives no parameters + +int main(void) +{ + // CC65 cannot mix code and data so we have to declare all variables here in the function prolog + + ulong iNumber; + ushort currentFactor; + ulong numBytesAllocated, rootOfLimit; + byte *array; + ulong countOfPrimes; + + rootOfLimit = sqrti(LIMIT); + puts("\r\n\r\n"); + RepeatChar('*', 70); + puts("\r\n** Prime Number Sieve - Dave Plummer 2022 **"); + RepeatChar('*', 70); + + printf("\r\n\r\nCalculating primes to %ld using a sqrt of %ld...\r\n", LIMIT, rootOfLimit); + + // Calculate how much memory should be allocated + + numBytesAllocated = (LIMIT + 15) / 16; + array = malloc(numBytesAllocated); + if (!array) + { + printf("Unable to allocate %ld bytes for %ld bits\r\n", numBytesAllocated, LIMIT); + return 0; + } + else + { + printf("Allocated %ld bytes for %ld slots\r\n", numBytesAllocated, LIMIT); + + // Preset all the bits to true + + for (iNumber = 0; iNumber < numBytesAllocated; iNumber++) + array[iNumber] = 0xFF; + } + + // Search for next unmarked factor + + currentFactor = 3; + while (currentFactor <= rootOfLimit) + { + ulong num, n; + + for (num = currentFactor; num <= LIMIT; num += 2) + { + if (GETBIT(array, num)) + { + currentFactor = num; + break; + } + } + + for (n = (ulong) currentFactor * currentFactor; n <= LIMIT; n += currentFactor * 2) + CLRBIT(array, n); + + currentFactor += 2; + } + + // Display results + // + // printf("The following primes were found at or below %ld:\r\n2, ", LIMIT); + + countOfPrimes = 1; + for (iNumber = 3; iNumber <= LIMIT; iNumber += 2) + if (GETBIT(array, iNumber)) + countOfPrimes++; + + printf("[END: Count = %ld]\r\n", countOfPrimes); + + free(array); + return 1; +}