diff --git a/examples/standalone/cpp_tireal_pi_montecarlo/src/main.cpp b/examples/standalone/cpp_tireal_pi_montecarlo/src/main.cpp index 1f9352002..998141916 100644 --- a/examples/standalone/cpp_tireal_pi_montecarlo/src/main.cpp +++ b/examples/standalone/cpp_tireal_pi_montecarlo/src/main.cpp @@ -2,54 +2,57 @@ #include #include -#define ITER_MAX 15000 - using namespace ti::literals; -static char buf[24] = "PI is about "; -#define buf_offset 12 - int main(void) { - int count = 0; /* points in the unit circle's first quadrant */ - /* Clear the screen */ os_ClrHomeFull(); /* Set the random seed based off the real time clock */ srand(rtc_Time()); - os_SetCursorPos(0, 0); + unsigned i = 0; + constexpr unsigned iMax = 10'000; + unsigned count = 0; /* points in the unit circle's first quadrant */ + + auto print = [&]() + { + const auto piApprox = ti::real(count) / i * 4; + + char buf[24] = "PI is about "; + constexpr size_t bufOffset = 12; + piApprox.toCString(buf + bufOffset); - for (int i = 0; i < ITER_MAX; i++) + os_PutStrFull(buf); + os_NewLine(); + }; + + while (++i <= iMax) { - const ti::real x = ti::real(rand()) / RAND_MAX; - const ti::real y = ti::real(rand()) / RAND_MAX; - const ti::real z = x*x + y*y; + const auto x = ti::real(rand()) / RAND_MAX; + const auto y = ti::real(rand()) / RAND_MAX; + const auto z = x*x + y*y; if (z <= 1) { count++; } - if (i % 150 == 0) // Just to print some things along the way... - { - (ti::real(count) / ITER_MAX * 4).toCString(buf+buf_offset); - os_PutStrFull(buf); - os_NewLine(); - } + if (os_GetCSC()) { break; } + + if (i % 100 == 0) + { + print(); + } } - (ti::real(count) / ITER_MAX * 4).toCString(buf+buf_offset); - os_PutStrFull(buf); - os_NewLine(); + print(); - os_NewLine(); os_PutStrFull("Press any key to quit"); - os_NewLine(); - while (!os_GetCSC()); + return 0; } diff --git a/examples/standalone/math_test/autotest.json b/examples/standalone/math_test/autotest.json new file mode 100644 index 000000000..ac6436982 --- /dev/null +++ b/examples/standalone/math_test/autotest.json @@ -0,0 +1,228 @@ +{ + "transfer_files": [ + "bin/DEMO.8xp" + ], + "target": { + "name": "DEMO", + "isASM": true + }, + "sequence": [ + "key|clear", + "delay|1000", + "key|0", + "key|enter", + "action|launch", + "hashWait|not", + "key|enter", + "hashWait|neg", + "key|enter", + "hashWait|abs", + "key|enter", + "hashWait|bitrev", + "key|enter", + "hashWait|popcnt", + "key|enter", + "hashWait|and", + "key|enter", + "hashWait|or", + "key|enter", + "hashWait|xor", + "key|enter", + "hashWait|add", + "key|enter", + "hashWait|sub", + "key|enter", + "hashWait|shl", + "key|enter", + "hashWait|shru", + "key|enter", + "hashWait|shrs", + "key|enter", + "hashWait|mulu", + "key|enter", + "hashWait|divu", + "key|enter", + "hashWait|remu", + "key|enter", + "hashWait|divs", + "key|enter", + "hashWait|rems", + "key|enter", + "hashWait|div_q", + "key|enter", + "hashWait|div_r", + "key|enter", + "hashWait|done" + ], + "hashes": { + "not": { + "description": "not", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "0B3D9374" + ] + }, + "neg": { + "description": "neg", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "10A84E1B" + ] + }, + "abs": { + "description": "abs", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "D7807035" + ] + }, + "bitrev": { + "description": "bitrev", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "BBADF82E" + ] + }, + "popcnt": { + "description": "popcnt", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "62628040" + ] + }, + "and": { + "description": "and", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "32DEF9D5" + ] + }, + "or": { + "description": "or", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "4E247920" + ] + }, + "xor": { + "description": "xor", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "257F7002" + ] + }, + "add": { + "description": "add", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "CD575A4D" + ] + }, + "sub": { + "description": "sub", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "EE1C5453" + ] + }, + "shl": { + "description": "shl", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "FD8CA2EC" + ] + }, + "shru": { + "description": "shru", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "9754CB4F" + ] + }, + "shrs": { + "description": "shrs", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "AB5BE5CB" + ] + }, + "mulu": { + "description": "mulu", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "C6A6FF7D" + ] + }, + "divu": { + "description": "divu", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "F973C020" + ] + }, + "remu": { + "description": "remu", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "5196C205" + ] + }, + "divs": { + "description": "divs", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "2A13A348" + ] + }, + "rems": { + "description": "rems", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "F45969EF" + ] + }, + "div_q": { + "description": "div_q", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "EAFFC6D3" + ] + }, + "div_r": { + "description": "div_r", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "B9786654" + ] + }, + "done": { + "description": "done", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "101734A5", + "FFAF89BA" + ] + } + } +} \ No newline at end of file diff --git a/examples/standalone/math_test/makefile b/examples/standalone/math_test/makefile new file mode 100644 index 000000000..c1d0ec367 --- /dev/null +++ b/examples/standalone/math_test/makefile @@ -0,0 +1,21 @@ +# ---------------------------- +# Makefile Options +# ---------------------------- + +NAME ?= DEMO +ICON ?= icon.png +DESCRIPTION ?= "CE C Toolchain Demo" +COMPRESSED ?= NO +ARCHIVED ?= NO +# STATIC_CRT ?= NO + +CFLAGS ?= -Os -mllvm -inline-threshold=100 -Wall -Wextra +CXXFLAGS ?= -Os -mllvm -inline-threshold=100 -Wall -Wextra + +# ---------------------------- + +ifndef CEDEV +$(error CEDEV environment path variable is not set) +endif + +include $(CEDEV)/meta/makefile.mk diff --git a/examples/standalone/math_test/readme.md b/examples/standalone/math_test/readme.md new file mode 100644 index 000000000..85e36d880 --- /dev/null +++ b/examples/standalone/math_test/readme.md @@ -0,0 +1,7 @@ +### Math test + +Exercises a bunch of math functions. + +--- + +This demo is part of the CE C SDK Toolchain. diff --git a/examples/standalone/math_test/src/main.c b/examples/standalone/math_test/src/main.c new file mode 100644 index 000000000..f7ccf219b --- /dev/null +++ b/examples/standalone/math_test/src/main.c @@ -0,0 +1,391 @@ +#define INTERACTIVE 1 + + +#undef NDEBUG + +#include +#include +#include +#include +#include +#include +#include + + +#ifdef _EZ80 +# include +# include + +# if INTERACTIVE +# define x_printf printf +# else +# define x_printf(...) dbg_printf(__VA_ARGS__) +# endif + +#else +# ifndef __cplusplus +typedef int32_t int24_t; +typedef uint32_t uint24_t; +# else +template +struct IntN final +{ +private: + static constexpr int extraBits = sizeof(U) * 8 - bits; + static_assert(extraBits >= 0, "underlying type is not big enough"); + +public: + constexpr IntN(U value) : value(value * (1ULL << extraBits)) {} + constexpr operator U() const { return value >> extraBits; } + +private: + U value; +}; +using uint24_t = IntN<24, uint_fast32_t>; +using int24_t = IntN<24, int_fast32_t>; +# endif + +static int24_t __builtin_bitreverse24(int24_t x) +{ + return __builtin_bitreverse32(x) >> 8; +} +#endif + + +#if INTERACTIVE || !defined(_EZ80) +# define x_printf printf +#else +# define x_printf(...) dbg_printf(__VA_ARGS__) +#endif + +static void separateOutput() +{ +#if INTERACTIVE && defined(_EZ80) + os_ClrHomeFull(); +#else + x_printf("\n--------------------------\n"); +#endif +} + +static void waitForKey() +{ +#if INTERACTIVE && defined(_EZ80) + while (!os_GetCSC()) + ; +#endif +} + +static void finishOutput() +{ + waitForKey(); + separateOutput(); +} + + +#define DEFINE_UNOP_PREFIX_FUNC(type, name, op) \ + static type name##_(type x) \ + { \ + return (type)(op(x)); \ + } + +#define DEFINE_BINOP_FUNC_FUNC(type, name, func, post) \ + static type name##_(type x, type y) \ + { \ + return (type)(func(x, y)post); \ + } + +#define DEFINE_BINOP_INFIX_FUNC(type, name, op) \ + static type name##_(type x, type y) \ + { \ + return (type)(x op y); \ + } + +#define DEFINE_UNOP_PREFIX_FUNC_B(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC(u##int8_t, b##name, op) +#define DEFINE_UNOP_PREFIX_FUNC_S(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC(u##int16_t, s##name, op) +#define DEFINE_UNOP_PREFIX_FUNC_I(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC(u##int24_t, i##name, op) +#define DEFINE_UNOP_PREFIX_FUNC_L(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC(u##int32_t, l##name, op) +#define DEFINE_UNOP_PREFIX_FUNC_LL(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC(u##int64_t, ll##name, op) + +#define DEFINE_BINOP_FUNC_FUNC_B(u, name, func, post) \ + DEFINE_BINOP_FUNC_FUNC(u##int8_t, b##name, b##func, post) +#define DEFINE_BINOP_FUNC_FUNC_S(u, name, func, post) \ + DEFINE_BINOP_FUNC_FUNC(u##int16_t, s##name, s##func, post) +#define DEFINE_BINOP_FUNC_FUNC_I(u, name, func, post) \ + DEFINE_BINOP_FUNC_FUNC(u##int24_t, i##name, func, post) +#define DEFINE_BINOP_FUNC_FUNC_L(u, name, func, post) \ + DEFINE_BINOP_FUNC_FUNC(u##int32_t, l##name, l##func, post) +#define DEFINE_BINOP_FUNC_FUNC_LL(u, name, func, post) \ + DEFINE_BINOP_FUNC_FUNC(u##int64_t, ll##name, ll##func, post) + +#define DEFINE_BINOP_INFIX_FUNC_B(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC(u##int8_t, b##name, op) +#define DEFINE_BINOP_INFIX_FUNC_S(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC(u##int16_t, s##name, op) +#define DEFINE_BINOP_INFIX_FUNC_I(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC(u##int24_t, i##name, op) +#define DEFINE_BINOP_INFIX_FUNC_L(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC(u##int32_t, l##name, op) +#define DEFINE_BINOP_INFIX_FUNC_LL(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC(u##int64_t, ll##name, op) + +#define DEFINE_UNOP_PREFIX_FUNC_B_TO_S(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_B(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_S(u, name, op) +#define DEFINE_UNOP_PREFIX_FUNC_B_TO_I(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_B_TO_S(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_I(u, name, op) +#define DEFINE_UNOP_PREFIX_FUNC_B_TO_L(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_B_TO_I(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_L(u, name, op) +#define DEFINE_UNOP_PREFIX_FUNC_B_TO_LL(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_B_TO_L(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_LL(u, name, op) + +#define DEFINE_BINOP_INFIX_FUNC_B_TO_S(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_B(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_S(u, name, op) +#define DEFINE_BINOP_INFIX_FUNC_B_TO_I(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_B_TO_S(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_I(u, name, op) +#define DEFINE_BINOP_INFIX_FUNC_B_TO_L(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_B_TO_I(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_L(u, name, op) +#define DEFINE_BINOP_INFIX_FUNC_B_TO_LL(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_B_TO_L(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_LL(u, name, op) + +#define DEFINE_BINOP_FUNC_FUNC_I_TO_L(u, name, func, post) \ + DEFINE_BINOP_FUNC_FUNC_I(u, name, func, post) \ + DEFINE_BINOP_FUNC_FUNC_L(u, name, func, post) +#define DEFINE_BINOP_FUNC_FUNC_I_TO_LL(u, name, func, post) \ + DEFINE_BINOP_FUNC_FUNC_I_TO_L(u, name, func, post) \ + DEFINE_BINOP_FUNC_FUNC_LL(u, name, func, post) + + +#define DEFINE_UNOP_TYPE(u) \ + typedef struct u##UnOp_ \ + { \ + const char *name; \ + u##int8_t (*b)(u##int8_t); \ + u##int16_t (*s)(u##int16_t); \ + u##int24_t (*i)(u##int24_t); \ + u##int32_t (*l)(u##int32_t); \ + u##int64_t (*ll)(u##int64_t); \ + } u##UnOp; + +#define DEFINE_BINOP_TYPE(u) \ + typedef struct u##BinOp_ \ + { \ + const char *name; \ + u##int8_t (*b)(u##int8_t, u##int8_t); \ + u##int16_t (*s)(u##int16_t, u##int16_t); \ + u##int24_t (*i)(u##int24_t, u##int24_t); \ + u##int32_t (*l)(u##int32_t, u##int32_t); \ + u##int64_t (*ll)(u##int64_t, u##int64_t); \ + } u##BinOp; + +DEFINE_UNOP_TYPE() +DEFINE_UNOP_TYPE(u) + +DEFINE_BINOP_TYPE() +DEFINE_BINOP_TYPE(u) + +#define DEFINE_UNOP_STRUCT_B(u, name) \ + static const u##UnOp unop_##name = {#name, b##name##_}; +#define DEFINE_UNOP_STRUCT_B_TO_S(u, name) \ + static const u##UnOp unop_##name = {#name, b##name##_, s##name##_}; +#define DEFINE_UNOP_STRUCT_B_TO_I(u, name) \ + static const u##UnOp unop_##name = {#name, b##name##_, s##name##_, i##name##_}; +#define DEFINE_UNOP_STRUCT_B_TO_L(u, name) \ + static const u##UnOp unop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_}; +#define DEFINE_UNOP_STRUCT_B_TO_LL(u, name) \ + static const u##UnOp unop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_, ll##name##_}; + +#define DEFINE_BINOP_STRUCT_B(u, name) \ + static const u##BinOp binop_##name = {#name, b##name##_}; +#define DEFINE_BINOP_STRUCT_B_TO_S(u, name) \ + static const u##BinOp binop_##name = {#name, b##name##_, s##name##_}; +#define DEFINE_BINOP_STRUCT_B_TO_I(u, name) \ + static const u##BinOp binop_##name = {#name, b##name##_, s##name##_, i##name##_}; +#define DEFINE_BINOP_STRUCT_B_TO_L(u, name) \ + static const u##BinOp binop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_}; +#define DEFINE_BINOP_STRUCT_B_TO_LL(u, name) \ + static const u##BinOp binop_##name = {#name, b##name##_, s##name##_, i##name##_, l##name##_, ll##name##_}; +#define DEFINE_BINOP_STRUCT_I_TO_L(u, name) \ + static const u##BinOp binop_##name = {#name, NULL, NULL, i##name##_, l##name##_}; +#define DEFINE_BINOP_STRUCT_I_TO_LL(u, name) \ + static const u##BinOp binop_##name = {#name, NULL, NULL, i##name##_, l##name##_, ll##name##_}; + + +#define DEFINE_UNOP_PREFIX_B(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_B(u, name, op) \ + DEFINE_UNOP_STRUCT_B(u, name) +#define DEFINE_UNOP_PREFIX_B_TO_S(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_B_TO_S(u, name, op) \ + DEFINE_UNOP_STRUCT_B_TO_S(u, name) +#define DEFINE_UNOP_PREFIX_B_TO_I(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_B_TO_I(u, name, op) \ + DEFINE_UNOP_STRUCT_B_TO_I(u, name) +#define DEFINE_UNOP_PREFIX_B_TO_L(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_B_TO_L(u, name, op) \ + DEFINE_UNOP_STRUCT_B_TO_L(u, name) +#define DEFINE_UNOP_PREFIX_B_TO_LL(u, name, op) \ + DEFINE_UNOP_PREFIX_FUNC_B_TO_LL(u, name, op) \ + DEFINE_UNOP_STRUCT_B_TO_LL(u, name) + +#define DEFINE_BINOP_INFIX_B(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_B(u, name, op) \ + DEFINE_BINOP_STRUCT_B(u, name) +#define DEFINE_BINOP_INFIX_B_TO_S(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_B_TO_S(u, name, op) \ + DEFINE_BINOP_STRUCT_B_TO_S(u, name) +#define DEFINE_BINOP_INFIX_B_TO_I(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_B_TO_I(u, name, op) \ + DEFINE_BINOP_STRUCT_B_TO_I(u, name) +#define DEFINE_BINOP_INFIX_B_TO_L(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_B_TO_L(u, name, op) \ + DEFINE_BINOP_STRUCT_B_TO_L(u, name) +#define DEFINE_BINOP_INFIX_B_TO_LL(u, name, op) \ + DEFINE_BINOP_INFIX_FUNC_B_TO_LL(u, name, op) \ + DEFINE_BINOP_STRUCT_B_TO_LL(u, name) + + +static void testOp(bool isBinOp, const BinOp *op, int64_t x, int64_t y) +{ + unsigned lhsLength = 8; + unsigned nameLength = strlen(op->name); + unsigned prefixLength = lhsLength - nameLength; + + x_printf("%*s=%016llX\n", lhsLength, "x", (long long)x); + if (!isBinOp) + { + x_printf("\n"); + } + else + { + x_printf("%*s=%016llX\n", lhsLength, "y", (long long)y); + } + +#define TEST_OP(prefix, bits) \ + x_printf("\n"); \ + if (op->prefix) \ + { \ + unsigned digits = (bits + 3) / 4; \ + unsigned long long result = (op->prefix)(x, y) & ((1ULL << (bits - 1) << 1) - 1); \ + x_printf("%*s%s=%*s%0*llX", prefixLength, #prefix, op->name, 16 - digits, "", digits, result); \ + } + + TEST_OP(b, 8) + TEST_OP(s, 16) + TEST_OP(i, 24) + TEST_OP(l, 32) + TEST_OP(ll, 64) + + finishOutput(); +} + +static void testUnOp(const UnOp *op, int64_t x) +{ + testOp(false, (const BinOp*)op, x, 0); +} + +static void testBinOp(const BinOp *op, int64_t x, int64_t y) +{ + testOp(true, op, x, y); +} + + +DEFINE_UNOP_PREFIX_B_TO_LL( , not, ~) +DEFINE_UNOP_PREFIX_B_TO_LL( , neg, -) + +DEFINE_UNOP_PREFIX_FUNC_B_TO_I( , abs, abs) +DEFINE_UNOP_PREFIX_FUNC_L( , abs, labs) +DEFINE_UNOP_PREFIX_FUNC_LL( , abs, llabs) +DEFINE_UNOP_STRUCT_B_TO_LL( , abs) + +DEFINE_UNOP_PREFIX_FUNC_B( , bitrev, __builtin_bitreverse8) +DEFINE_UNOP_PREFIX_FUNC_S( , bitrev, __builtin_bitreverse16) +DEFINE_UNOP_PREFIX_FUNC_I( , bitrev, __builtin_bitreverse24) +DEFINE_UNOP_PREFIX_FUNC_L( , bitrev, __builtin_bitreverse32) +DEFINE_UNOP_PREFIX_FUNC_LL( , bitrev, __builtin_bitreverse64) +DEFINE_UNOP_STRUCT_B_TO_LL( , bitrev) + +// Needs to be unsigned to avoid extra bits from sign extension +DEFINE_UNOP_PREFIX_FUNC_B_TO_I(u, popcnt, __builtin_popcount) +DEFINE_UNOP_PREFIX_FUNC_L(u, popcnt, __builtin_popcountl) +DEFINE_UNOP_PREFIX_FUNC_LL(u, popcnt, __builtin_popcountll) +DEFINE_UNOP_STRUCT_B_TO_LL(u, popcnt) + +DEFINE_BINOP_INFIX_B_TO_LL( , and, &) +DEFINE_BINOP_INFIX_B_TO_LL( , or, |) +DEFINE_BINOP_INFIX_B_TO_LL( , xor, ^) +DEFINE_BINOP_INFIX_B_TO_LL( , add, +) +DEFINE_BINOP_INFIX_B_TO_LL( , sub, -) +DEFINE_BINOP_INFIX_B_TO_LL( , shl, <<) +DEFINE_BINOP_INFIX_B_TO_LL(u, shru, >>) +DEFINE_BINOP_INFIX_B_TO_LL( , shrs, >>) +DEFINE_BINOP_INFIX_B_TO_LL(u, mulu, *) +DEFINE_BINOP_INFIX_B_TO_LL(u, divu, /) +DEFINE_BINOP_INFIX_B_TO_LL(u, remu, %) +DEFINE_BINOP_INFIX_B_TO_LL( , divs, /) +DEFINE_BINOP_INFIX_B_TO_LL( , rems, %) + + +DEFINE_BINOP_FUNC_FUNC_I_TO_LL( , div_q, div, .quot) +DEFINE_BINOP_STRUCT_I_TO_LL( , div_q) + +DEFINE_BINOP_FUNC_FUNC_I_TO_LL( , div_r, div, .rem) +DEFINE_BINOP_STRUCT_I_TO_LL( , div_r) + + +static const UnOp *unops[] = { + &unop_not, + &unop_neg, + &unop_abs, + &unop_bitrev, + (const UnOp *)&unop_popcnt, +}; + +static const BinOp *binops[] = { + &binop_and, + &binop_or, + &binop_xor, + &binop_add, + &binop_sub, + &binop_shl, + (const BinOp *)&binop_shru, + &binop_shrs, + (const BinOp *)&binop_mulu, + (const BinOp *)&binop_divu, + (const BinOp *)&binop_remu, + &binop_divs, + &binop_rems, + &binop_div_q, + &binop_div_r, +}; + + +int main(int argc, char *argv[]) +{ + int64_t x = argc > 1 ? atoll(argv[1]) : (int64_t)0xDFA5FBC197EDB389LL; + int64_t y = argc > 2 ? atoll(argv[2]) : (int64_t)0x08010A030C050E07LL; + + separateOutput(); + + for (size_t i = 0; i < sizeof(unops) / sizeof(*unops); i++) + { + testUnOp(unops[i], x); + } + + for (size_t i = 0; i < sizeof(binops) / sizeof(*binops); i++) + { + testBinOp(binops[i], x, y); + } + + return 0; +} diff --git a/src/makefile.mk b/src/makefile.mk index f5c2503e2..9b0e96d28 100644 --- a/src/makefile.mk +++ b/src/makefile.mk @@ -39,7 +39,9 @@ CUSTOM_FILE_FILE ?= stdio_file.h DEPS ?= #---------------------------- HAS_UPPERCASE_NAME ?= YES -HAS_FLASH_FUNCTIONS ?= YES +# Prefer static crt functions. +# These will increase output size but are usually faster than those from TI-OS. +STATIC_CRT ?= YES HAS_PRINTF ?= YES HAS_CUSTOM_FILE ?= NO #---------------------------- @@ -181,8 +183,8 @@ ifeq ($(HAS_CUSTOM_FILE),YES) DEFCUSTOMFILE := -DHAS_CUSTOM_FILE=1 -DCUSTOM_FILE_FILE=\"$(CUSTOM_FILE_FILE)\" endif -# choose static or linked flash functions -ifeq ($(HAS_FLASH_FUNCTIONS),YES) +# prefer static crt functions +ifeq ($(STATIC_CRT),YES) LDSTATIC := 1 endif diff --git a/src/std/inttypes.h b/src/std/inttypes.h index 41a8baf89..61414ea72 100644 --- a/src/std/inttypes.h +++ b/src/std/inttypes.h @@ -175,7 +175,10 @@ __BEGIN_DECLS extern intmax_t imaxabs(intmax_t __n) __NOEXCEPT __attribute__((__const__)); -typedef struct { intmax_t quot, rem; } imaxdiv_t; +typedef struct { + intmax_t rem; + intmax_t quot; +} imaxdiv_t; extern imaxdiv_t imaxdiv(intmax_t __numer, intmax_t __denom) __NOEXCEPT __attribute__((__const__)); diff --git a/src/std/linked/linked.src b/src/std/linked/linked.src index e9be5eefa..06113dbd2 100644 --- a/src/std/linked/linked.src +++ b/src/std/linked/linked.src @@ -1,4 +1,5 @@ public __u_flt_info, __u_flt_rnd, _acosf, _asinf, _atanf, _atan2f, _atoff, _ceilf, _cosf, _coshf, _expf, _fabsf, _floorf, _fmodf, _frexpf, _ldexpf, _logf, _log10f, _modff, _powf, _sinf, _sinhf, _sqrtf, _strtodf, _tanf, _tanhf, _acos, _asin, _atan, _atan2, _atof, _ceil, _cos, _cosh, _exp, _fabs, _floor, _fmod, _frexp, _ldexp, _log, _log10, _modf, _pow, _sin, _sinh, _sqrt, _strtod, _tan, _tanh + __u_flt_info := 022128h __u_flt_rnd := 02212Ch _acosf := 022100h @@ -52,4 +53,119 @@ _strtod := 0220E0h _tan := 022120h _tanh := 022138h +; byte (8-bit) math + public __bshl +__bshl := 000100h + public __bshru +__bshru := 000104h + +; short (16-bit) math + public __sand +__sand := 000200h + public __sdivs +__sdivs := 000208h + public __sdivu +__sdivu := 00020Ch + public __smuls +__smuls := 000224h + public __smulu +__smulu := 000228h + public __sneg +__sneg := 00022Ch + public __snot +__snot := 000230h + public __sor +__sor := 000234h + public __srems +__srems := 000238h + public __sremu +__sremu := 00023Ch + public __sshl +__sshl := 000240h + public __sshrs +__sshrs := 000248h + public __sshru +__sshru := 000250h + public __sxor +__sxor := 000268h + +; int (24-bit) math + public __iand +__iand := 000134h + public __idivs +__idivs := 00013Ch + public __idivu +__idivu := 000140h + public __idvrmu +__idvrmu := 000144h + public __imuls +__imuls := 000154h + public __imulu +__imulu := 000158h + public __ineg +__ineg := 000160h + public __inot +__inot := 000164h + public __ior +__ior := 000168h + public __irems +__irems := 00016Ch + public __iremu +__iremu := 000170h + public __ishl +__ishl := 000174h + public __ishrs +__ishrs := 00017Ch + public __ishru +__ishru := 000184h + public __ixor +__ixor := 000198h + +; long (32-bit) math + public __ladd +__ladd := 00019Ch + public __ladd_b +__ladd_b := 0001A0h + public __land +__land := 0001A4h + public __lcmps +__lcmps := 0001A8h + public __lcmpu +__lcmpu := 0001ACh + public __ldivs +__ldivs := 0001B4h + public __ldivu +__ldivu := 0001B8h + public __ldvrmu +__ldvrmu := 0001BCh + public __lmuls +__lmuls := 0001C8h + public __lmulu +__lmulu := 0001CCh + public __lneg +__lneg := 0001D0h + public __lnot +__lnot := 0001D4h + public __lor +__lor := 0001D8h +; Bug: Does not ensure `nc` before `sbc hl, hl` to negate divisor. +; public __lrems +; __lrems := 0001DCh + public __lremu +__lremu := 0001E0h + public __lshl +__lshl := 0001E4h + public __lshrs +__lshrs := 0001E8h + public __lshru +__lshru := 0001ECh + public __lsub +__lsub := 0001F8h + public __lxor +__lxor := 0001FCh +; C standard library + public _tolower +_tolower := 021E34h + public _toupper +_toupper := 021E38h diff --git a/src/std/shared/abs.src b/src/std/shared/abs.src index 95b7bfc59..43d8826d4 100644 --- a/src/std/shared/abs.src +++ b/src/std/shared/abs.src @@ -1,5 +1,4 @@ -; int abs(int); - assume adl=1 + assume adl=1 section .text public _abs diff --git a/src/std/shared/atoi.src b/src/std/shared/atol.src similarity index 72% rename from src/std/shared/atoi.src rename to src/std/shared/atol.src index 798c543ee..ee1bc9435 100644 --- a/src/std/shared/atoi.src +++ b/src/std/shared/atol.src @@ -1,10 +1,9 @@ assume adl=1 section .text - public _atos, _atol, _atoi -_atos: -_atol: + public _atoi, _atol _atoi: +_atol: pop bc ex (sp),hl push bc @@ -14,9 +13,9 @@ _atoi: push bc push hl call _strtol - pop bc - pop bc - pop bc + pop af + pop af + pop af ret extern _strtol diff --git a/src/std/shared/atoll.src b/src/std/shared/atoll.src new file mode 100644 index 000000000..d9f5f4903 --- /dev/null +++ b/src/std/shared/atoll.src @@ -0,0 +1,20 @@ + assume adl=1 + + section .text + public _atoll +_atoll: + pop bc + ex (sp),hl + push bc + ld bc,10 + push bc + ld c,b + push bc + push hl + call _strtoll + pop af + pop af + pop af + ret + + extern _strtoll diff --git a/src/std/shared/bctlz.src b/src/std/shared/bctlz.src new file mode 100644 index 000000000..8a9579b69 --- /dev/null +++ b/src/std/shared/bctlz.src @@ -0,0 +1,18 @@ + assume adl=1 + + section .text + public __bctlz +__bctlz: + push hl + + scf + sbc hl, hl + +.loop: + rla + inc hl + jr nc, .loop + + ld a, l + pop hl + ret diff --git a/src/std/shared/bdivs.src b/src/std/shared/bdivs.src index d998d34ac..dad74b4b0 100644 --- a/src/std/shared/bdivs.src +++ b/src/std/shared/bdivs.src @@ -1,45 +1,25 @@ -; (c) Copyright 2001-2008 Zilog Inc. -;------------------------------------------------------------------------- -; Signed Byte Division. -; Input: -; Operand1: -; B : 8 bit dividend (numerator) -; -; Operand2: -; C : 8 bit divisor (denominator) -; -; Output: -; Result: A : 8 bit quotient -; Registers Used: -; d, e -;------------------------------------------------------------------------- - assume adl=1 + assume adl=1 section .text public __bdivs __bdivs: - push bc - xor a,a - sub a,b - jp m,_L0 - ld b,a -_L0: - xor a,a - sub a,c - jp m,_L1 - ld c,a -_L1: - call __bdivu - pop bc +; I: B=dividend, C=divisor +; O: a=B/C + push hl - ld l,a - ld a,b - xor a,c - ld a,l - jp p,_L2 - neg -_L2: + + ld l, b + call __bdvrms_abs + + ld a, c + xor a, b + + ld a, l pop hl + ret p + + neg ret - extern __bdivu + + extern __bdvrms_abs diff --git a/src/std/shared/bdivu.src b/src/std/shared/bdivu.src index 89633caf9..f9bc91657 100644 --- a/src/std/shared/bdivu.src +++ b/src/std/shared/bdivu.src @@ -1,42 +1,20 @@ -; (c) Copyright 2007-2008 Zilog, Inc. -;------------------------------------------------------------------------- -; Unsigned Byte Division. -; Input: -; Operand1: -; B : 8 bit dividend (numerator x) -; -; Operand2: -; C : 8 bit divisor (denominator y) -; -; Output: -; Result: A : 8 bit quotient -; Registers Used: -; none -;------------------------------------------------------------------------- - assume adl=1 + assume adl=1 section .text public __bdivu __bdivu: +; I: B=dividend, C=divisor +; O: a=B/C + push bc push hl - ld h,b - xor a,a - ld b,8 ; i = 8 (bit counter) -loop: - sla h - rla - jr c,over - cp a,c - jr c,under -over: - sub a,c - inc h -under: - djnz loop - ld a,h + call __bdvrmu + ld a, l + pop hl pop bc ret + + extern __bdvrmu diff --git a/src/std/shared/bdvrms_abs.src b/src/std/shared/bdvrms_abs.src new file mode 100644 index 000000000..3c0fc9c1b --- /dev/null +++ b/src/std/shared/bdvrms_abs.src @@ -0,0 +1,36 @@ + assume adl=1 + + section .text + public __bdvrms_abs +__bdvrms_abs: +; I: C=divisor, L=dividend +; O: a=?, h=abs(L)%abs(C), l=abs(L)/abs(C) + + ld a, l + public __bdvrms_abs.hijack_a_l_dividend +.hijack_a_l_dividend: + rla + jr nc, .neg_dividend_skip + xor a, a + sub a, l + ld l, a +.neg_dividend_skip: + + push bc + + ld a, c + rla + jr nc, .neg_divisor_skip + xor a, a + sub a, c + ld c, a + jr nc, .neg_dividend_skip +.neg_divisor_skip: + + call __bdvrmu.hijack_l_dividend + + pop bc + ret + + + extern __bdvrmu.hijack_l_dividend diff --git a/src/std/shared/bdvrmu.src b/src/std/shared/bdvrmu.src new file mode 100644 index 000000000..8f7af268d --- /dev/null +++ b/src/std/shared/bdvrmu.src @@ -0,0 +1,29 @@ + assume adl=1 + + section .text + public __bdvrmu +__bdvrmu: +; I: B=dividend, C=divisor +; O: a=?, b=0, h=B%C, l=B/C + + ld l, b + public __bdvrmu.hijack_l_dividend +.hijack_l_dividend: + ld h, 0 + + ld b, 8 + +.loop: + add hl, hl + + ld a, h + sub a, c + + jr c, .bit_skip + ld h, a + inc l +.bit_skip: + + djnz .loop + + ret diff --git a/src/std/shared/bmuls.src b/src/std/shared/bmuls.src index b84de035b..2f94fa278 100644 --- a/src/std/shared/bmuls.src +++ b/src/std/shared/bmuls.src @@ -1,19 +1,4 @@ -; (c) Copyright 2007-2008 Zilog, Inc. -;------------------------------------------------------------------------- -; Signed Byte Multiply -; Input: -; Operand1: -; A : 8 bit -; -; Operand2: -; B : 8 bit -; -; Output: -; Result: A : 8 bit product -; Registers Used: -; none -;------------------------------------------------------------------------- - assume adl=1 + assume adl=1 section .text public __bmuls diff --git a/src/std/shared/bmulu.src b/src/std/shared/bmulu.src index 55dfa90a9..fa1b2ce66 100644 --- a/src/std/shared/bmulu.src +++ b/src/std/shared/bmulu.src @@ -1,19 +1,4 @@ -; (c) Copyright 2007-2008 Zilog, Inc. -;------------------------------------------------------------------------- -; Unsigned Byte Multiply -; Input: -; Operand1: -; B : 8 bit -; -; Operand2: -; C : 8 bit -; -; Output: -; Result: A : 8 bit product -; Registers Used: -; none -;------------------------------------------------------------------------- - assume adl=1 + assume adl=1 section .text public __bmulu diff --git a/src/std/shared/bpopcnt.src b/src/std/shared/bpopcnt.src index bcf2e8451..d30300ef8 100644 --- a/src/std/shared/bpopcnt.src +++ b/src/std/shared/bpopcnt.src @@ -25,4 +25,3 @@ __bpopcnt: and a,$f ; a=A+B+C+D+E+F+G+H pop bc ret - diff --git a/src/std/shared/brems.src b/src/std/shared/brems.src index a102f9f20..ca1c80c8f 100644 --- a/src/std/shared/brems.src +++ b/src/std/shared/brems.src @@ -1,42 +1,25 @@ -; (c) Copyright 2007-2008 Zilog, Inc. -;------------------------------------------------------------------------- -; Signed Byte Modulus -; Input: -; Operand1: -; A : 8 bit dividend (numerator) -; -; Operand2: -; C : 8 bit divisor (denominator) -; -; Output: -; Result: A : 8 bit modulus -; Registers Used: -; -;------------------------------------------------------------------------- - assume adl=1 + assume adl=1 section .text public __brems __brems: - push bc - ld b,a - bit 7,c - jr z,skip1 - ld a,c - neg - ld c,a -skip1: - ld a,b - bit 7,a - jr z,skip2 - neg -skip2: - call __bremu - bit 7,b - jr z,skip3 +; I: A=dividend, C=divisor +; O: a=A%C + + push hl + + ld l, a + push hl + call __bdvrms_abs.hijack_a_l_dividend + + pop af + + ld a, h + pop hl + ret p + neg -skip3: - pop bc ret - extern __bremu + + extern __bdvrms_abs.hijack_a_l_dividend diff --git a/src/std/shared/bremu.src b/src/std/shared/bremu.src index 55d563ed6..ca5701717 100644 --- a/src/std/shared/bremu.src +++ b/src/std/shared/bremu.src @@ -1,39 +1,21 @@ -; (c) Copyright 2007-2008 Zilog, Inc. -;------------------------------------------------------------------------- -; Unsigned Byte Modulus -; Input: -; Operand1: -; A : 8 bit dividend (numerator) -; -; Operand2: -; C : 8 bit divisor (denominator) -; -; Output: -; Result: A : 8 bit modulus -; Registers Used: -; none -;------------------------------------------------------------------------- - assume adl=1 + assume adl=1 section .text public __bremu __bremu: +; I: A=dividend, C=divisor +; O: a=A%C + push bc push hl - ld h,a - xor a,a - ld b,8 -loop: - sla h - rla - jr c,over - cp a,c - jr c,under -over: - sub a,c - inc h -under: - djnz loop + + ld b, a + call __bdvrmu + ld a, h + pop hl pop bc ret + + + extern __bdvrmu diff --git a/src/std/shared/bshrs.src b/src/std/shared/bshrs.src index ec909ea64..8461f9bb8 100644 --- a/src/std/shared/bshrs.src +++ b/src/std/shared/bshrs.src @@ -1,29 +1,16 @@ -; (c) Copyright 2007-2008 Zilog, Inc. -;------------------------------------------------------------------------- -; Byte Shift Right Signed -; Input: -; Operand1: -; A : 8 bit number to shift -; Operand2: -; B : 8 bit shift count -; -; Output: -; Result: A : 8 bit -; Registers Used: -; flags -;------------------------------------------------------------------------- - assume adl=1 + assume adl=1 + section .text public __bshrs __bshrs: - push bc +; CC: if B!=0: B*(5*r(PC)+1)+6*r(PC)+(ADL?6*r(SPL)+3*w(SPL):4*r(SPS)+2*w(SPS))+1 +; if B==0: 4*r(PC)+(ADL?3*r(SPL):2*r(SPS))+2 inc b - jr test - -loop: + dec b + ret z + push bc +.loop: sra a -test: - djnz loop - + djnz .loop pop bc ret diff --git a/src/std/shared/clock.src b/src/std/shared/clock.src index 988d7e0ca..064600998 100644 --- a/src/std/shared/clock.src +++ b/src/std/shared/clock.src @@ -1,7 +1,7 @@ mpTmr2Counter := 0F20010h - assume adl = 1 + assume adl=1 section .text public _clock diff --git a/src/std/shared/div.src b/src/std/shared/div.src index 5aab8fde4..b9a9f4a48 100644 --- a/src/std/shared/div.src +++ b/src/std/shared/div.src @@ -1,53 +1,21 @@ -; Copyright 1992-2008 Zilog, Inc. -;------------------------------------------------------------------------- -; Div function -; -; div_t div(int numer,int denom); -; -;------------------------------------------------------------------------- - assume adl=1 + assume adl=1 section .text public _div _div: - push af - push bc - push hl - push de - - ld hl,21 - add hl,sp - ld bc,(hl) ; bc=val of denominator - dec hl - dec hl - dec hl - ld hl,(hl) ; hl=val of numerator - push hl - call __idivs - ex de,hl ; de= quotient - pop hl ; hl=val of numerator - call __irems - push hl - pop bc - - ld hl,15 - add hl,sp - ld hl,(hl) - inc hl - inc hl - inc hl - ld (hl),bc ; remainder - dec hl - dec hl - dec hl - ld (hl),de ; quotient - pop de + pop iy + pop hl pop bc - pop bc - pop af + push de + push de + push de + push de + + call __idvrms + ld (iy), hl + ld (iy + 3), de ret - extern __idivs - extern __irems + extern __idvrms diff --git a/src/std/shared/frimuls.src b/src/std/shared/frimuls.src index 15cd56ed9..800c38df3 100644 --- a/src/std/shared/frimuls.src +++ b/src/std/shared/frimuls.src @@ -1,19 +1,3 @@ -; (c) Copyright 2004-2008 Zilog, Inc. -;------------------------------------------------------------------------- -; fract interger Multiplication Unsigned. -; -; Input: -; Operand1: -; uHL : 24 bits -; -; Operand2: -; uBC : 24 bits -; -; Output: -; Result: uHL : 24 bit -; Registers Used: -; none -;------------------------------------------------------------------------- assume adl=1 section .text diff --git a/src/std/shared/frimulu.src b/src/std/shared/frimulu.src index e79827382..021730040 100644 --- a/src/std/shared/frimulu.src +++ b/src/std/shared/frimulu.src @@ -1,19 +1,3 @@ -; (c) Copyright 2004-2008 Zilog, Inc. -;------------------------------------------------------------------------- -; fract interger Multiplication Unsigned. -; -; Input: -; Operand1: -; uHL : 24 bits -; -; Operand2: -; uBC : 24 bits -; -; Output: -; Result: uHL : 24 bits -; Registers Used: -; none -;------------------------------------------------------------------------- assume adl=1 section .text diff --git a/src/std/shared/frsmuls.src b/src/std/shared/frsmuls.src index 71198cafc..22da523df 100644 --- a/src/std/shared/frsmuls.src +++ b/src/std/shared/frsmuls.src @@ -1,19 +1,3 @@ -; (c) Copyright 2004-2008 Zilog, Inc. -;------------------------------------------------------------------------- -; fract short Multiplication signed. -; -; Input: -; Operand1: -; HL : 16 bits -; -; Operand2: -; BC : 16 bits -; -; Output: -; Result: HL : 16 bits -; Registers Used: -; none -;------------------------------------------------------------------------- assume adl=1 section .text diff --git a/src/std/shared/getchar.src b/src/std/shared/getchar.src index 11e44fd71..ff9ba0d2a 100644 --- a/src/std/shared/getchar.src +++ b/src/std/shared/getchar.src @@ -1,4 +1,4 @@ - assume adl = 1 + assume adl=1 section .text public _getchar diff --git a/src/std/shared/iand_fast.src b/src/std/shared/iand_fast.src new file mode 100644 index 000000000..b4dbc4fea --- /dev/null +++ b/src/std/shared/iand_fast.src @@ -0,0 +1,25 @@ + assume adl=1 + + section .text + public __iand_fast +__iand_fast: + push bc + inc sp + inc sp + push hl + ld hl, 2 + add hl, sp + ld a, (hl) + inc hl + and a, (hl) + dec hl + ld (hl), a + pop hl + inc sp + ld a, h + and a, b + ld h, a + ld a, l + and a, c + ld l, a + ret diff --git a/src/std/shared/ibitrev.src b/src/std/shared/ibitrev.src index 570af810c..7f4425551 100644 --- a/src/std/shared/ibitrev.src +++ b/src/std/shared/ibitrev.src @@ -4,16 +4,18 @@ public __ibitrev __ibitrev: push af - ld a,l - call __bbitrev - ld l,a - ld a,h - call __bbitrev - ld h,a - call $21D5C - call __bbitrev - call $21D70 + ld a, h ; a=H + ld h, l + ld l, a ; uhl=[HLU]LH + call __internal_bitrev_byte ; a=HLU', uhl=LH0 + ld l, a ; uhl=LH[HLU'] + call __internal_bitrev_byte ; a=L', uhl=H[HLU']0 + ld l, h + ld h, a ; uhl=HL'[HLU'] + call __internal_bitrev_byte ; a=H', uhl=L'[HLU']0 + ld l, h + ld h, a ; uhl=L'H'[HLU'] pop af ret - extern __bbitrev + extern __internal_bitrev_byte diff --git a/src/std/shared/ibitrev_fast.src b/src/std/shared/ibitrev_fast.src new file mode 100644 index 000000000..e1b508bf3 --- /dev/null +++ b/src/std/shared/ibitrev_fast.src @@ -0,0 +1,62 @@ + assume adl=1 + + section .text + public __ibitrev_fast +__ibitrev_fast: + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + ld c, a + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + ld b, a + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + push af + dec sp + pop hl + inc sp + ld l, c + ld h, b + ret diff --git a/src/std/shared/icmpzero.src b/src/std/shared/icmpzero.src new file mode 100644 index 000000000..286355bf0 --- /dev/null +++ b/src/std/shared/icmpzero.src @@ -0,0 +1,9 @@ + assume adl=1 + + section .text + public __icmpzero +__icmpzero: + add hl, de + or a, a + sbc hl, de + ret diff --git a/src/std/shared/ictlz.src b/src/std/shared/ictlz.src new file mode 100644 index 000000000..34dcb3ed1 --- /dev/null +++ b/src/std/shared/ictlz.src @@ -0,0 +1,17 @@ + assume adl=1 + + section .text + public __ictlz +__ictlz: + push hl + + scf + sbc a, a + +.loop: + adc hl, hl + inc a + jr nc, .loop + + pop hl + ret diff --git a/src/std/shared/imulu_fast.src b/src/std/shared/imulu_fast.src new file mode 100644 index 000000000..cd015c232 --- /dev/null +++ b/src/std/shared/imulu_fast.src @@ -0,0 +1,54 @@ + assume adl=1 + + section .text + public __imuls_fast, __imulu_fast +__imuls_fast: +__imulu_fast: + +; Multiplies UHL by UBC and returns the 24-bit product uhl. +; I: UBC=multiplier, UHL=multiplicand, ADL=1 +; O: a=UHL*UBC-L*C>>16, ubc=L*B, ude=L*C, uhl=UHL*UBC +; FO: sz(a), vc((UHL*UBC-L*C&0xFFFFFF)+L*C) +; CC: 43*r(PC)+9*r(SPL)+6*w(SPL)+25 +; ; a ubc ude uhl u(sp) +Mul_UHL_UBC_UHL_Fast: ;--------------+---------------+---------------+---------------+------------------------ + ld d, b + ld e, h ; de=BH + mlt de ; ude=H*B + ld a, e ; a=H*B + dec sp + push hl + push bc + inc sp ; (sp)=[HLU]H + ; (sp)=[BCU]B + pop de ; de=[BCU]B -- + ld e, l ; de=[BCU]L + mlt de ; ude=L*BCU + add a, e ; a=H*B+L*BCU + pop de ; de=[HLU]H -- + ld e, c ; de=[HLU]C + mlt de ; ude=HLU*C + add a, e ; a=HLU*C+H*B+L*BCU + ld d, c + ld e, l ; de=CL + ld l, d ; hl=HC + ld c, e ; bc=BL + mlt bc ; ubc=L*B + mlt de ; ude=L*C + mlt hl ; uhl=H*C + add hl, bc ; uhl=H*C+L*B + add a, h ; a=(H*C+L*B>>8)+HLU*C+H*B+L*BCU + ld h, a ; hl=H*C+L*B+(HLU*C+H*B+L*BCU<<8) + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl ; uhl=(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16) + add hl, de ; uhl=L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16) + ret + +; (UHL*UBC)&0xFFFFFF=L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16)+(HLU*B+H*BCU<<24)+(HLU*BCU<<32)&0xFFFFFF +; =L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16)&0xFFFFFF diff --git a/src/std/shared/inchar.src b/src/std/shared/inchar.src index cc2f51b1f..fda121fca 100644 --- a/src/std/shared/inchar.src +++ b/src/std/shared/inchar.src @@ -1,4 +1,4 @@ - assume adl = 1 + assume adl=1 section .text weak _inchar diff --git a/src/std/shared/ineg_fast.src b/src/std/shared/ineg_fast.src new file mode 100644 index 000000000..0527ff957 --- /dev/null +++ b/src/std/shared/ineg_fast.src @@ -0,0 +1,12 @@ + assume adl=1 + + section .text + public __ineg_fast +__ineg_fast: + add hl, de ; uhl=UHL+UDE + ex de, hl ; ude=UHL+UDE, uhl=UDE + or a, a + sbc hl, de ; uhl=UDE-(UHL+UDE) + ; =UDE-UHL-UDE + ; =-UHL + ret diff --git a/src/std/shared/inot_fast.src b/src/std/shared/inot_fast.src new file mode 100644 index 000000000..3c32bf605 --- /dev/null +++ b/src/std/shared/inot_fast.src @@ -0,0 +1,13 @@ + assume adl=1 + + section .text + public __inot_fast +__inot_fast: + add hl, de ; uhl=UHL+UDE + ex de, hl ; ude=UHL+UDE, uhl=UDE + scf + sbc hl, de ; uhl=UDE-(UHL+UDE)-1 + ; =UDE-UHL-UDE-1 + ; =-UHL-1 + ; =~UHL + ret diff --git a/src/std/shared/internal_bitrev_byte.src b/src/std/shared/internal_bitrev_byte.src new file mode 100644 index 000000000..3677ddb9b --- /dev/null +++ b/src/std/shared/internal_bitrev_byte.src @@ -0,0 +1,22 @@ + assume adl=1 + + section .text + public __internal_bitrev_byte +__internal_bitrev_byte: + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + add hl, hl + rra + ret diff --git a/src/std/shared/ior_fast.src b/src/std/shared/ior_fast.src new file mode 100644 index 000000000..65288f73e --- /dev/null +++ b/src/std/shared/ior_fast.src @@ -0,0 +1,25 @@ + assume adl=1 + + section .text + public __ior_fast +__ior_fast: + push bc + inc sp + inc sp + push hl + ld hl, 2 + add hl, sp + ld a, (hl) + inc hl + or a, (hl) + dec hl + ld (hl), a + pop hl + inc sp + ld a, h + or a, b + ld h, a + ld a, l + or a, c + ld l, a + ret diff --git a/src/std/shared/ipopcnt.src b/src/std/shared/ipopcnt.src index c4baf8d62..c1c1f4323 100644 --- a/src/std/shared/ipopcnt.src +++ b/src/std/shared/ipopcnt.src @@ -3,19 +3,8 @@ section .text public __ipopcnt __ipopcnt: - push hl - ld a,l - call __bpopcnt - ld l,a - ld a,h - call __bpopcnt - ld h,a - call $21D5C - call __bpopcnt - add a,l - add a,h - pop hl - ret - - extern __bpopcnt + push bc + ld b, 3 + jp __lpopcnt.hijack1 + extern __lpopcnt.hijack1 diff --git a/src/std/shared/isalnum.src b/src/std/shared/isalnum.src index b75c79dfa..1048b0347 100644 --- a/src/std/shared/isalnum.src +++ b/src/std/shared/isalnum.src @@ -1,10 +1,3 @@ -; original source -; int isalnum(int c) { -; if( (unsigned char)c & (unsigned char)0x80 ) -; return (0); -; return(__maptab[c] & (unsigned char)(UC|LC|DIG)); -; } - assume adl=1 section .text diff --git a/src/std/shared/isalpha.src b/src/std/shared/isalpha.src index 6901bf5f6..071a98d38 100644 --- a/src/std/shared/isalpha.src +++ b/src/std/shared/isalpha.src @@ -1,8 +1,3 @@ -; original source -; int isalnum(int c) { -; if( (unsigned char)c & (unsigned char)0x80 ) -; return (0); -; return(__maptab[c] & (unsigned char)(UC|LC)); assume adl=1 section .text diff --git a/src/std/shared/isascii.src b/src/std/shared/isascii.src index 6c3d9a5f3..4211f43b5 100644 --- a/src/std/shared/isascii.src +++ b/src/std/shared/isascii.src @@ -1,7 +1,3 @@ -; original source -; int isascii(int c) { -; return c >= 0 && c < 128; -; } assume adl=1 section .text diff --git a/src/std/shared/iscntrl.src b/src/std/shared/iscntrl.src index a4dc9c0dd..3d027c9f9 100644 --- a/src/std/shared/iscntrl.src +++ b/src/std/shared/iscntrl.src @@ -1,8 +1,3 @@ -;int iscntrl(int c) { -; if( (unsigned char)c & (unsigned char)0x80 ) -; return (0); -; return(__maptab[c] & (unsigned char)(CTL)); -;} assume adl=1 section .text diff --git a/src/std/shared/isdigit.src b/src/std/shared/isdigit.src index ca5cdc79b..9d37b03aa 100644 --- a/src/std/shared/isdigit.src +++ b/src/std/shared/isdigit.src @@ -1,8 +1,3 @@ -;int isdigit(int c) { -; if( (unsigned char)c & (unsigned char)0x80 ) -; return (0); -; return(__maptab[c] & (unsigned char)(DIG)); -;} assume adl=1 section .text diff --git a/src/std/shared/isgraph.src b/src/std/shared/isgraph.src index 32b9dcfb1..839783ecf 100644 --- a/src/std/shared/isgraph.src +++ b/src/std/shared/isgraph.src @@ -1,9 +1,3 @@ -; original source -; int isgraph(int c) { -; if( (unsigned char)c & (unsigned char)0x80 ) -; return (0); -; return(__maptab[c] & (unsigned char)(UC|LC|DIG|PUN)); -; } assume adl=1 section .text diff --git a/src/std/shared/ishrs_1_fast.src b/src/std/shared/ishrs_1_fast.src new file mode 100644 index 000000000..b5c676d8a --- /dev/null +++ b/src/std/shared/ishrs_1_fast.src @@ -0,0 +1,13 @@ + assume adl=1 + + section .text + public __ishru_1_fast +__ishru_1_fast: + push hl + ld hl, 2 + add hl, sp + sra (hl) + pop hl + rr h + rr l + ret diff --git a/src/std/shared/ishru_1_fast.src b/src/std/shared/ishru_1_fast.src new file mode 100644 index 000000000..c68dbc8b3 --- /dev/null +++ b/src/std/shared/ishru_1_fast.src @@ -0,0 +1,13 @@ + assume adl=1 + + section .text + public __ishru_1_fast +__ishru_1_fast: + push hl + ld hl, 2 + add hl, sp + srl (hl) + pop hl + rr h + rr l + ret diff --git a/src/std/shared/islower.src b/src/std/shared/islower.src index 92afe2cb8..864dec6d9 100644 --- a/src/std/shared/islower.src +++ b/src/std/shared/islower.src @@ -1,9 +1,3 @@ -; original source -; int islower(int c) { -; if( (unsigned char)c & (unsigned char)0x80 ) -; return (0); -; return(__maptab[c] & (unsigned char)(LC)); -; } assume adl=1 section .text diff --git a/src/std/shared/isprint.src b/src/std/shared/isprint.src index 748c7666a..5a0aec5a0 100644 --- a/src/std/shared/isprint.src +++ b/src/std/shared/isprint.src @@ -1,9 +1,3 @@ -; original source -; int isprint(int c) { -; if( (unsigned char)c & (unsigned char)0x80 ) -; return (0); -; return(__maptab[c] & (unsigned char)(UC|LC|DIG|PUN|SP)); -; } assume adl=1 section .text diff --git a/src/std/shared/ispunct.src b/src/std/shared/ispunct.src index 34174a8e4..ccc542fa5 100644 --- a/src/std/shared/ispunct.src +++ b/src/std/shared/ispunct.src @@ -1,9 +1,3 @@ -; original source -; int ispunct(int c) { -; if( (unsigned char)c & (unsigned char)0x80 ) -; return (0); -; return(__maptab[c] & (unsigned char)(PUN)); -; } assume adl=1 section .text diff --git a/src/std/shared/isspace.src b/src/std/shared/isspace.src index ee8282d30..b8face4db 100644 --- a/src/std/shared/isspace.src +++ b/src/std/shared/isspace.src @@ -1,9 +1,3 @@ -; original source -; int isspace(int c) { -; if( (unsigned char)c & (unsigned char)0x80 ) -; return (0); -; return(__maptab[c] & (unsigned char)(WS)); -; } assume adl=1 section .text diff --git a/src/std/shared/isupper.src b/src/std/shared/isupper.src index 8ce4d0815..2de883b3c 100644 --- a/src/std/shared/isupper.src +++ b/src/std/shared/isupper.src @@ -1,9 +1,3 @@ -; original source -; int isupper(int c) { -; if( (unsigned char)c & (unsigned char)0x80 ) -; return (0); -; return(__maptab[c] & (unsigned char)(UC)); -; } assume adl=1 section .text diff --git a/src/std/shared/isxdigit.src b/src/std/shared/isxdigit.src index 884bc9f42..d5485ce15 100644 --- a/src/std/shared/isxdigit.src +++ b/src/std/shared/isxdigit.src @@ -1,9 +1,3 @@ -; original source -; int isxdigit(int c) { -; if( (unsigned char)c & (unsigned char)0x80 ) -; return (0); -; return(__maptab[c] & (unsigned char)(DIG|HEX)); -; } assume adl=1 section .text diff --git a/src/std/shared/ixor_fast.src b/src/std/shared/ixor_fast.src new file mode 100644 index 000000000..36a90a3e9 --- /dev/null +++ b/src/std/shared/ixor_fast.src @@ -0,0 +1,25 @@ + assume adl=1 + + section .text + public __ixor_fast +__ixor_fast: + push bc + inc sp + inc sp + push hl + ld hl, 2 + add hl, sp + ld a, (hl) + inc hl + xor a, (hl) + dec hl + ld (hl), a + pop hl + inc sp + ld a, h + xor a, b + ld h, a + ld a, l + xor a, c + ld l, a + ret diff --git a/src/std/shared/labs.src b/src/std/shared/labs.src index b6e9f2621..c12cd8ebd 100644 --- a/src/std/shared/labs.src +++ b/src/std/shared/labs.src @@ -1,25 +1,16 @@ -; long labs(long j); assume adl=1 section .text public _labs _labs: - call __frameset0 - ld hl,(ix+6) - ld e,(ix+9) - push hl - push de - call __lcmpzero - call __setflag - pop de + pop bc pop hl - jp p,l_1 - call __lneg -l_1: ld sp,ix - pop ix - ret + pop de + push de + push hl + push bc + bit 7, e + ret z + jp __lneg - extern __frameset0 - extern __lcmpzero - extern __setflag extern __lneg diff --git a/src/std/shared/ladd_1.src b/src/std/shared/ladd_1.src new file mode 100644 index 000000000..01833819a --- /dev/null +++ b/src/std/shared/ladd_1.src @@ -0,0 +1,12 @@ + assume adl=1 + + section .text + public __ladd_1 +__ladd_1: + inc hl + add hl, bc + or a, a + sbc hl, bc + ret nz + inc e + ret diff --git a/src/std/shared/ladd_b_fast.src b/src/std/shared/ladd_b_fast.src new file mode 100644 index 000000000..17f93486b --- /dev/null +++ b/src/std/shared/ladd_b_fast.src @@ -0,0 +1,15 @@ + assume adl=1 + + section .text + public __ladd_b_fast +__ladd_b_fast: + add a, l + ld l, a + ret nc + inc h + ret nz + ld bc, 1 shl 16 + add hl, bc + ret nc + inc e + ret diff --git a/src/std/shared/ladd_fast.src b/src/std/shared/ladd_fast.src new file mode 100644 index 000000000..247fedc0a --- /dev/null +++ b/src/std/shared/ladd_fast.src @@ -0,0 +1,9 @@ + assume adl=1 + + section .text + public __ladd_fast +__ladd_fast: + add hl, bc + adc a, e + ld e, a + ret diff --git a/src/std/shared/land_fast.src b/src/std/shared/land_fast.src new file mode 100644 index 000000000..c26514514 --- /dev/null +++ b/src/std/shared/land_fast.src @@ -0,0 +1,27 @@ + assume adl=1 + + section .text + public __land_fast +__land_fast: + and a, e + ld e, a + push bc + inc sp + inc sp + push hl + ld hl, 2 + add hl, sp + ld a, (hl) + inc hl + and a, (hl) + dec hl + ld (hl), a + pop hl + inc sp + ld a, h + and a, b + ld h, a + ld a, l + and a, c + ld l, a + ret diff --git a/src/std/shared/lbitrev.src b/src/std/shared/lbitrev.src index 5f6bcd8a1..a0dbcbfdd 100644 --- a/src/std/shared/lbitrev.src +++ b/src/std/shared/lbitrev.src @@ -4,20 +4,17 @@ public __lbitrev __lbitrev: push af - ld a,l - call __bbitrev - ld l,a - ld a,h - call __bbitrev - ld h,a - call $21D5C - call __bbitrev - call $21D70 - ld a,e - call __bbitrev - ld e,a + call __internal_bitrev_byte ; a=HLU', UHL=HL0 + ld l, e ; uhl=HLE + ld e, a ; e=HLU' + call __internal_bitrev_byte ; a=H', uhl=LE0 + ld l, a ; uhl=LEH' + call __internal_bitrev_byte ; a=L', uhl=EH'0 + ld l, e ; uhl=EH'HLU' + ld e, a ; e=L' + call __internal_bitrev_byte ; a=E', uhl=H'HLU' + ld l, a ; uhl=H'HLU'E' pop af ret - extern __bbitrev - + extern __internal_bitrev_byte diff --git a/src/std/shared/lcmps_fast.src b/src/std/shared/lcmps_fast.src new file mode 100644 index 000000000..aa3fcb1d5 --- /dev/null +++ b/src/std/shared/lcmps_fast.src @@ -0,0 +1,11 @@ + assume adl=1 + + section .text + public __lcmps_fast +__lcmps_fast: + ld d, a + ld a, e + sub a, d + ret nz + sbc hl, bc + ret diff --git a/src/std/shared/lcmpu_fast.src b/src/std/shared/lcmpu_fast.src new file mode 100644 index 000000000..6ef89132e --- /dev/null +++ b/src/std/shared/lcmpu_fast.src @@ -0,0 +1,11 @@ + assume adl=1 + + section .text + public __lcmpu_fast +__lcmpu_fast: + sub a, e + ccf + ret nz + or a, a + sbc hl, bc + ret diff --git a/src/std/shared/lcmpzero.src b/src/std/shared/lcmpzero.src new file mode 100644 index 000000000..11d15d16a --- /dev/null +++ b/src/std/shared/lcmpzero.src @@ -0,0 +1,12 @@ + assume adl=1 + + section .text + public __lcmpzero +__lcmpzero: + inc e + dec e + ret nz + add hl, bc + or a, a + sbc hl, bc + ret diff --git a/src/std/shared/lctlz.src b/src/std/shared/lctlz.src new file mode 100644 index 000000000..9943bad91 --- /dev/null +++ b/src/std/shared/lctlz.src @@ -0,0 +1,20 @@ + assume adl=1 + + section .text + public __lctlz +__lctlz: + push de + push hl + + scf + sbc a, a + +.loop: + adc hl, hl + rl e + inc a + jr nc, .loop + + pop hl + pop de + ret diff --git a/src/std/shared/ldiv.src b/src/std/shared/ldiv.src index 5b1757f65..b893a8941 100644 --- a/src/std/shared/ldiv.src +++ b/src/std/shared/ldiv.src @@ -1,81 +1,56 @@ -; Copyright (C) 1999-2008 Zilog, Inc, All Rights Reserved -;------------------------------------------------------------------------- -; ldiv function -; -; ldiv_t ldiv(long numer, long denom); -; -;------------------------------------------------------------------------- assume adl=1 section .text public _ldiv _ldiv: - push bc + pop hl + pop iy + pop de + pop bc + ld a, c + pop bc + ex (sp), hl + ex de, hl + + ld d, a + xor a, e push af - push de - push hl - ld hl,27 - add hl,sp - ld a,(hl) - dec hl - dec hl - dec hl - ld bc,(hl) ; aBC : denominator - dec hl - dec hl - dec hl - ld e,(hl) - dec hl - dec hl - dec hl - ld hl,(hl) ; eHL: Numerator - call __ldivs + ld a, e + ld e, d push de - push hl ; eHL : quotient - - ld hl,27 - add hl,sp - ld e,(hl) - dec hl - dec hl - dec hl - ld hl,(hl) - call __lrems - ld a,e - ex de,hl ;aDE :remainder - ld hl,21 - add hl,sp - ld hl,(hl) - push hl + bit 7, e + call __ldivs_lrems_common - ld bc, 7 - add hl, bc - ld (hl),a - dec hl - dec hl - dec hl - ld (hl),de ; aDE : remainder + call __ldvrmu - pop hl - pop bc - ld (hl),bc ; bc : 3 LSB of quotient - pop bc - push hl - inc hl - inc hl - inc hl - ld (hl),c ; c : MSB of quotient - pop hl + exx + ld e, a + pop af + call m, __lneg + ld (iy + 4), hl + ld (iy + 7), e - pop de - pop de + exx pop af - pop bc + call m, __lneg + ld (iy), hl + ld (iy + 3), e + + ex (sp), hl + push de + push de + push de + push de + bit 2, c + jr z, .ei_skip + ei +.ei_skip: + jp (hl) - ret - extern __ldivs - extern __lrems + extern __ldivs_lrems_common + extern __ldvrmu + extern __lneg diff --git a/src/std/shared/llabs.src b/src/std/shared/llabs.src new file mode 100644 index 000000000..4a48520d7 --- /dev/null +++ b/src/std/shared/llabs.src @@ -0,0 +1,20 @@ + assume adl=1 + + section .text + public _imaxabs, _llabs +_imaxabs: +_llabs: + pop iy + pop hl + pop de + pop bc + push bc + push de + push hl + ld a, b + or a, a + call m, __llneg.hijack_nc + jp (iy) + + + extern __llneg.hijack_nc diff --git a/src/std/shared/lladd.src b/src/std/shared/lladd.src new file mode 100644 index 000000000..71e215ed5 --- /dev/null +++ b/src/std/shared/lladd.src @@ -0,0 +1,24 @@ + assume adl=1 + + section .text + public __lladd +__lladd: + push iy + ld iy, 0 + add iy, sp + push bc + ld bc, (iy + 6) + add hl, bc + ex de, hl + ld bc, (iy + 9) + adc hl, bc + ex de, hl + pop bc + jr nc, .nc48 + inc bc +.nc48: + ld iy, (iy + 12) + add iy, bc + lea bc, iy + pop iy + ret diff --git a/src/std/shared/lladd_1.src b/src/std/shared/lladd_1.src new file mode 100644 index 000000000..402f5bbb7 --- /dev/null +++ b/src/std/shared/lladd_1.src @@ -0,0 +1,16 @@ + assume adl=1 + + section .text + public __lladd_1 +__lladd_1: + inc hl + add hl, de + or a, a + sbc hl, de + ret nz + inc de + sbc hl, de + add hl, de + ret nz + inc bc + ret diff --git a/src/std/shared/lladd_b.src b/src/std/shared/lladd_b.src new file mode 100644 index 000000000..2003f5d71 --- /dev/null +++ b/src/std/shared/lladd_b.src @@ -0,0 +1,20 @@ + assume adl=1 + + section .text + public __lladd_b +__lladd_b: + push bc + inc.s bc + ld c, a + ld b, 0 + add hl, bc + jr nc, .finish + ld c, 1 + ex de, hl + add hl, bc + ex de, hl +.finish: + pop bc + ret nc + inc bc + ret diff --git a/src/std/shared/lladd_b_fast.src b/src/std/shared/lladd_b_fast.src new file mode 100644 index 000000000..864a0132f --- /dev/null +++ b/src/std/shared/lladd_b_fast.src @@ -0,0 +1,36 @@ + assume adl=1 + + section .text + public __lladd_b_fast +__lladd_b_fast: + add a, l ; a=L+A + ld l, a ; l=L+A + ret nc + ; cf=1 + inc h ; h=H+1 + ret nz + ; h=0 + dec h + ld l, h ; uhl=(HLU<<16)+0xFFFF + inc hl ; uhl=HLU+1<<16 + add hl, bc + or a, a + sbc hl, bc + ld l, a ; uhl=(HLU+1<<16)+(L+A&0xFF) + ret nz + ; uhl=L+A&0xFF, cf=0 + inc e ; e=E+1 + ret nz + ; e=0 + inc d ; d=D+1 + ret nz + ; d=0 + dec d + ld e, d ; ude=(DEU<<16)+0xFFFF + inc de ; ude=DEU+1<<16 + sbc hl, de + add hl, de + ret c + ; ude=0 + inc bc ; ubc=UBC+1 + ret diff --git a/src/std/shared/lladd_fast.src b/src/std/shared/lladd_fast.src new file mode 100644 index 000000000..a73610681 --- /dev/null +++ b/src/std/shared/lladd_fast.src @@ -0,0 +1,22 @@ + assume adl=1 + + section .text + public __lladd_fast +__lladd_fast: + ld iy, 0 + add iy, sp + push bc + ld bc, (iy + 3) + add hl, bc + ex de, hl + ld bc, (iy + 6) + adc hl, bc + ex de, hl + pop bc + ld a, c + adc a, (iy + 9) + ld c, a + ld a, b + adc a, (iy + 10) + ld b, a + ret diff --git a/src/std/shared/lland.src b/src/std/shared/lland.src new file mode 100644 index 000000000..79ab59823 --- /dev/null +++ b/src/std/shared/lland.src @@ -0,0 +1,48 @@ + assume adl=1 + + section .text + public __lland +__lland: +; CC: 62*r(PC)+25*r(SPL)+14*w(SPL)+1 + push af + push iy + ld iy, 0 + add iy, sp + push hl + push de + lea hl, iy + 16 + ld a, b + and a, (hl) + ld b, a + dec hl + ld a, c + and a, (hl) + ld c, a + dec hl + lea de, iy - 4 + ld a, (de) + and a, (hl) + ld (de), a + pop de + dec hl + ld a, d + and a, (hl) + ld d, a + dec hl + ld a, e + and a, (hl) + ld e, a + dec hl + ld a, (iy - 1) + and a, (hl) + ld (iy - 1), a + pop hl + ld a, h + and a, (iy + 10) + ld h, a + ld a, l + and a, (iy + 9) + ld l, a + pop iy + pop af + ret diff --git a/src/std/shared/lland_fast.src b/src/std/shared/lland_fast.src new file mode 100644 index 000000000..dec0f7560 --- /dev/null +++ b/src/std/shared/lland_fast.src @@ -0,0 +1,44 @@ + assume adl=1 + + section .text + public __lland_fast +__lland_fast: +; CC: 56*r(PC)+19*r(SPL)+8*w(SPL)+1 + ld iy, 0 + add iy, sp + push hl + push de + lea hl, iy + 10 + ld a, b + and a, (hl) + ld b, a + dec hl + ld a, c + and a, (hl) + ld c, a + dec hl + lea de, iy - 4 + ld a, (de) + and a, (hl) + ld (de), a + pop de + dec hl + ld a, d + and a, (hl) + ld d, a + dec hl + ld a, e + and a, (hl) + ld e, a + dec hl + ld a, (iy - 1) + and a, (hl) + ld (iy - 1), a + pop hl + ld a, h + and a, (iy + 4) + ld h, a + ld a, l + and a, (iy + 3) + ld l, a + ret diff --git a/src/std/shared/llbitrev.src b/src/std/shared/llbitrev.src new file mode 100644 index 000000000..16696b1a5 --- /dev/null +++ b/src/std/shared/llbitrev.src @@ -0,0 +1,42 @@ + assume adl=1 + + section .text + public __llbitrev +__llbitrev: + push af ; stack: 0AF + call __internal_bitrev_byte ; a=HLU', UHL=HL0 + ld l, b ; uhl=HLB + push af ; stack: 0AF0[HLU']? + call __internal_bitrev_byte ; a=H', uhl=LB0 + ld l, c ; uhl=LBC + ld c, a ; c=H' + call __internal_bitrev_byte ; a=L', uhl=BC0 + ld b, a ; bc=L'H' + push de ; stack: 0AF0[HLU']?[DEU]DE + inc sp ; stack: 0AF0[HLU']?[DEU]D + pop af ; a=DEU + ; stack: 0AF0[HLU'] + ld l, a ; uhl=BC[DEU] + call __internal_bitrev_byte ; a=B', uhl=C[DEU]0 + ld l, d ; uhl=C[DEU]D + ld d, a ; d=B' + call __internal_bitrev_byte ; a=C', uhl=[DEU]D0 + ld l, e ; uhl=[DEU]DE + ld e, a ; e=C' + call __internal_bitrev_byte ; a=DEU', uhl=DE0 + ld l, a ; uhl=DE[DEU'] + call __internal_bitrev_byte ; a=D', uhl=E[DEU']0 + ld l, e ; uhl=E[DEU']C' + push af ; stack: 0AF0[HLU']0D'? + inc sp ; stack: 0AF0[HLU']0D' + call __internal_bitrev_byte ; a=E', uhl=[DEU']C'0 + ld l, d ; uhl=[DEU]'C'B' + pop de ; ude=[HLU']0D' + ; stack: 0AF0 + inc sp ; stack: 0AF + ld d, a ; ude=[HLU']E'D' + pop af ; af=AF + ; stack: + ret + + extern __internal_bitrev_byte diff --git a/src/std/shared/llcmps.src b/src/std/shared/llcmps.src new file mode 100644 index 000000000..42fbf4687 --- /dev/null +++ b/src/std/shared/llcmps.src @@ -0,0 +1,29 @@ + assume adl=1 + + section .text + public __llcmps +__llcmps: + push iy + ld iy, 0 + add iy, sp + push bc + push hl + ld l, c + ld h, b + ld bc, (iy + 12) + sbc.s hl, bc + pop hl + jr nz, .ne + ld bc, (iy + 9) + ex de, hl + sbc hl, de + add hl, de + ex de, hl + jr nz, .ne + ld bc, (iy + 6) + sbc hl, bc + add hl, bc +.ne: + pop bc + pop iy + ret diff --git a/src/std/shared/llcmpu.src b/src/std/shared/llcmpu.src new file mode 100644 index 000000000..16b9f3131 --- /dev/null +++ b/src/std/shared/llcmpu.src @@ -0,0 +1,29 @@ + assume adl=1 + + section .text + public __llcmpu +__llcmpu: + push iy + ld iy, 0 + add iy, sp + push hl + ld hl, (iy + 12) + sbc.s hl, bc + jr nz, .ne + ld hl, (iy + 9) + sbc hl, de + jr nz, .ne + pop hl + push bc + ld bc, (iy + 6) + sbc hl, bc + add hl, bc + pop bc + pop iy + ret + +.ne: + ccf + pop hl + pop iy + ret diff --git a/src/std/shared/llcmpu_fast.src b/src/std/shared/llcmpu_fast.src new file mode 100644 index 000000000..e8e8f0ea3 --- /dev/null +++ b/src/std/shared/llcmpu_fast.src @@ -0,0 +1,23 @@ + assume adl=1 + + section .text + public __llcmps_fast +__llcmps_fast: + public __llcmpu_fast +__llcmpu_fast: + ld iy, 0 + add iy, sp + ld a, b + sub a, (iy + 10) + ret nz + ld a, c + sub a, (iy + 9) + ret nz + ex de, hl + ld bc, (iy + 6) + sbc hl, bc + ret nz + ex de, hl + ld bc, (iy + 3) + sbc hl, bc + ret diff --git a/src/std/shared/llcmpzero.src b/src/std/shared/llcmpzero.src new file mode 100644 index 000000000..5b2b19b44 --- /dev/null +++ b/src/std/shared/llcmpzero.src @@ -0,0 +1,21 @@ + assume adl=1 + + section .text + public __llcmpzero +__llcmpzero: + inc b + dec b + ret nz + inc.s bc + dec c + jr nz, .p_nz + or a, a + sbc hl, bc + jr nz, .p_nz + sbc hl, de + ret z + add hl, de +.p_nz: + inc b + ld b, 0 + ret diff --git a/src/std/shared/llcmpzero_fast.src b/src/std/shared/llcmpzero_fast.src new file mode 100644 index 000000000..d68547aac --- /dev/null +++ b/src/std/shared/llcmpzero_fast.src @@ -0,0 +1,18 @@ + assume adl=1 + + section .text + public __llcmpzero_fast +__llcmpzero_fast: + xor a, a + add a, b + ret nz + cp a, c + jr nz, .p_nz + mlt bc + adc hl, bc + jr nz, .p_nz + adc hl, de + ret z +.p_nz: + inc a + ret diff --git a/src/std/shared/llctlz.src b/src/std/shared/llctlz.src new file mode 100644 index 000000000..ad43d18ae --- /dev/null +++ b/src/std/shared/llctlz.src @@ -0,0 +1,26 @@ + assume adl=1 + + section .text + public __llctlz +__llctlz: + push bc + push de + push hl + + scf + sbc a, a + +.loop: + adc hl, hl + ex de, hl + adc hl, hl + ex de, hl + rl c + rl b + inc a + jr nc, .loop + + pop hl + pop de + pop bc + ret diff --git a/src/std/shared/lldiv.src b/src/std/shared/lldiv.src new file mode 100644 index 000000000..9a49bb01c --- /dev/null +++ b/src/std/shared/lldiv.src @@ -0,0 +1,46 @@ + assume adl=1 + + section .text + public _imaxdiv, _lldiv +_imaxdiv: +_lldiv: + + pop hl + pop iy + ld (iy + 11), hl + pop hl + pop de + pop bc + + call __llrems + + ld (iy), hl + ld (iy + 3), de + ld (iy + 6), bc + + pop hl + pop de + ex (sp), hl + push hl + add hl, hl + pop bc + pop hl + call c, __llneg + + ld (iy + 8), hl + + ld hl, -21 + add hl, sp + ld sp, hl + + ld hl, (iy + 11) + + ld (iy + 11), de + ld (iy + 14), c + ld (iy + 15), b + + jp (hl) + + + extern __llneg + extern __llrems diff --git a/src/std/shared/lldivs.src b/src/std/shared/lldivs.src new file mode 100644 index 000000000..75c166e40 --- /dev/null +++ b/src/std/shared/lldivs.src @@ -0,0 +1,75 @@ + assume adl=1 + + section .text + public __llrems +__llrems: + + scf +virtual + jr nc, $ + 2 + load .jr_nc: 1 from $$ +end virtual + db .jr_nc + + public __lldivs +__lldivs: + + or a, a + + push iy + push af + + ld iy, 2 + add iy, sp + + ld a, b + ld (iy), a + xor a, (iy + 14) + ld (iy + 15), a + + xor a, b + rla + jr nc, .neg_divisor_skip + + push bc + push hl + + lea hl, iy + 7 + xor a, a + ld c, a + ld b, 8 + +.neg_divisor_loop: + ld a, c + sbc a, (hl) + ld (hl), a + inc hl + djnz .neg_divisor_loop + + pop hl + pop bc +.neg_divisor_skip: + + bit 7, b + call nz, __llneg + + or a, a + call __lldvrmu.hijack + + pop af + bit 7, (iy + 8) + jr c, .div_quotient_skip + ld hl, (iy + 15) + ld de, (iy + 18) + ld bc, (iy + 21) + bit 7, (iy + 23) +.div_quotient_skip: + + call nz, __llneg + + pop iy + + ret + + extern __lldvrmu.hijack + extern __llneg diff --git a/src/std/shared/lldivu.src b/src/std/shared/lldivu.src new file mode 100644 index 000000000..53d1e0043 --- /dev/null +++ b/src/std/shared/lldivu.src @@ -0,0 +1,21 @@ + assume adl=1 + + section .text + public __lldivu +__lldivu: + + push iy + push af + + call __lldvrmu + + ld hl, (iy + 15) + ld de, (iy + 18) + ld bc, (iy + 21) + + pop af + pop iy + + ret + + extern __lldvrmu diff --git a/src/std/shared/lldivu_b.src b/src/std/shared/lldivu_b.src new file mode 100644 index 000000000..9dcd5780d --- /dev/null +++ b/src/std/shared/lldivu_b.src @@ -0,0 +1,33 @@ + assume adl=1 + + section .text + public __lldivu_b +__lldivu_b: +; Very slow + push af + push iy + ld iy, 0 + add iy, sp + ld iy, (iy + 9) + xor a, a + ld iyh, 64 +.loop: + add hl, hl + ex de, hl + adc hl, hl + ex de, hl + rl c + rl b + rla + jr c, .1 + cp a, iyl + jr c, .0 +.1: + sub a, iyl + inc l +.0: + dec iyh + jr nz, .loop + pop iy + pop af + ret diff --git a/src/std/shared/lldvrmu.src b/src/std/shared/lldvrmu.src new file mode 100644 index 000000000..0e31c87ac --- /dev/null +++ b/src/std/shared/lldvrmu.src @@ -0,0 +1,107 @@ + assume adl=1 + + section .text + public __lldvrmu +__lldvrmu: +; Atrociously slow. + + ld iy, 5 + add iy, sp + public __lldvrmu.hijack +.hijack: + + ld a, i + di + push af + + push bc + push de + push hl +; Stack frame: +; iy - 17 -> dividend +; iy - 14 -> dividend >> 24 +; iy - 11 -> dividend >> 48 +; iy - 8 -> interrupts state +; iy - 5 -> return vector +; iy - 2 -> ??? +; iy + 1 -> ??? +; iy + 4 -> ??? +; iy + 7 -> divisor +; iy + 10 -> divisor >> 24 +; iy + 13 -> divisor >> 48 + + ld bc, (iy + 10) + sbc hl, hl + ex de, hl + sbc hl, hl + exx + ld hl, (iy + 13) + ex.s de, hl + ld hl, (iy + 7) + ld sp, hl + sbc hl, hl + + ld c, 8 + +.byte_loop: + dec iy + ld a, (iy - 9) + + ld b, 8 + +.bit_loop: + adc a, a + exx + adc hl, hl + ex de, hl + adc hl, hl + ex de, hl + exx + adc hl, hl + + exx + sbc hl, sp + ex de, hl + sbc hl, bc + ex de, hl + exx + sbc hl, de + + jr nc, .add_back_skip + exx + add hl, sp + ex de, hl + adc hl, bc + ex de, hl + exx + adc hl, de +.add_back_skip: + + djnz .bit_loop + + adc a, a + cpl + ld (iy + 15), a + + dec c + jr nz, .byte_loop + + ld sp, iy +; Stack frame: +; iy -> interrupts state +; iy + 3 -> return vector +; iy + 6 -> ??? +; iy + 9 -> ??? +; iy + 12 -> ??? +; iy + 15 -> quotient +; iy + 18 -> quotient >> 24 +; iy + 21 -> quotient >> 48 + + push hl + exx + pop bc + + pop af + ret po + ei + ret diff --git a/src/std/shared/llmulu.src b/src/std/shared/llmulu.src new file mode 100644 index 000000000..f48d80887 --- /dev/null +++ b/src/std/shared/llmulu.src @@ -0,0 +1,75 @@ + assume adl=1 + + section .text + public __llmuls, __llmulu +__llmuls: +__llmulu: +; Really slow + + push ix + push iy + push af + + ld ix, 0 + lea iy, ix - 6 + add iy, sp ; cf=1 + + push de + push hl + ld l, c + ld h, b + ld.s sp, hl + + lea hl, iy + 18 + ld b, 8 +.push_loop: + push af + ld a, (hl) + inc hl + or a, a ; cf=0 + djnz .push_loop + + sbc hl, hl + ld e, l + ld d, h + +.byte_loop: + scf + adc a, a + +.bit_loop: + push af + add ix, ix + adc hl, hl + ex de, hl + adc hl, hl + ex de, hl + pop af + + jr nc, .add_end + ld bc, (iy) + add ix, bc + ld bc, (iy + 3) + adc hl, bc + ex de, hl + adc.s hl, sp + ex de, hl +.add_end: + + add a, a + jr nz, .bit_loop + + pop af + jr nc, .byte_loop + + ld b, d + ld c, e + ex de, hl + lea hl, ix + + pop af + pop af + pop af + pop iy + pop ix + ret diff --git a/src/std/shared/llmulu_b.src b/src/std/shared/llmulu_b.src new file mode 100644 index 000000000..a2c0b9fd3 --- /dev/null +++ b/src/std/shared/llmulu_b.src @@ -0,0 +1,68 @@ + assume adl=1 + + section .text + public __llmulu_b +__llmulu_b: + push af + push iy + ld iy, 0 + add iy, sp + push de + push hl + ld a, (iy + 9) + ld h, a + mlt hl + ld (iy - 6), l + ld d, a + ld e, (iy - 5) + mlt de + ld l, h + ld h, 0 + add hl, de + ld (iy - 5), l + ld d, a + ld e, (iy - 4) + mlt de + ld l, h + ld h, 0 + add hl, de + ld (iy - 4), l + ld d, a + ld e, (iy - 3) + mlt de + ld l, h + ld h, 0 + add hl, de + ld (iy - 3), l + ld d, a + ld e, (iy - 2) + mlt de + ld l, h + ld h, 0 + add hl, de + ld (iy - 2), l + ld d, a + ld e, (iy - 1) + mlt de + ld l, h + ld h, 0 + add hl, de + ld (iy - 1), l + ld d, a + ld e, c + mlt de + ld l, h + ld h, 0 + add hl, de + ld c, l + ld d, a + ld e, b + mlt de + ld a, h + add a, e + ld b, a + pop hl + pop de + pop iy + pop af + ret diff --git a/src/std/shared/llneg.src b/src/std/shared/llneg.src new file mode 100644 index 000000000..bf13f5dfa --- /dev/null +++ b/src/std/shared/llneg.src @@ -0,0 +1,26 @@ + assume adl=1 + + section .text + public __llneg +__llneg: + or a, a + public __llneg.hijack_nc +.hijack_nc: + ex de, hl ; ude=UHL, uhl=UDE + push hl ; *spl=UDE + sbc hl, hl ; uhl=0 + sbc hl, de ; uhl=-UHL + ex (sp), hl ; uhl=UDE, *spl=-UHL + ex de, hl ; ude=UDE, uhl=UHL + ld hl, 0 ; uhl=0 + sbc hl, de ; uhl=-UDE-(UHL!=0) + ; =-UDEUHL>>24 + ex de, hl ; ude=-UDEUHL>>24, uhl=UDE + sbc hl, hl ; uhl=-(UDEUHL!=0) + or a, a + sbc hl, bc ; uhl=-UBC-(UDEUHL!=0) + ; =-UBCUDEUHL>>48 + ld c, l + ld b, h ; bc=-BCUDEUHL>>48 + pop hl ; bcudeuhl=-BCUDEUHL + ret diff --git a/src/std/shared/llneg_fast.src b/src/std/shared/llneg_fast.src new file mode 100644 index 000000000..bd4373850 --- /dev/null +++ b/src/std/shared/llneg_fast.src @@ -0,0 +1,26 @@ + assume adl=1 + + section .text + public __llneg_fast +__llneg_fast: + push de ; *spl=UDE + ex de, hl ; ude=UHL, uhl=UDE + xor a, a ; a=0 + sbc hl, hl ; uhl=0 + sbc hl, de ; uhl=-UHL + ex (sp), hl ; uhl=UDE, *spl=-UHL + ex de, hl ; ude=UDE, uhl=UHL + ld l, a ; l=0 + mlt hl ; uhl=0 + sbc hl, de ; uhl=-UDE-(UHL!=0) + ; =-UDEUHL>>24 + ex de, hl ; ude=-UDEUHL>>24, uhl=UDE + sbc a, c ; a=-C-(UDEUHL!=0) + ; =-CUDEUHL>>48 + ld c, a ; c=-CUDEUHL>>48 + sbc a, a ; a=-(CUDEUHL!=0) + sub a, b ; a=-B-(CUDEUHL!=0) + ; =-BCUDEUHL>>56 + ld b, a ; b=-BCUDEUHL>>56 + pop hl ; bcudeuhl=-BCUDEUHL + ret diff --git a/src/std/shared/llnot.src b/src/std/shared/llnot.src new file mode 100644 index 000000000..d2151e07f --- /dev/null +++ b/src/std/shared/llnot.src @@ -0,0 +1,30 @@ + assume adl=1 + + section .text + public __llnot +__llnot: + push hl ; *spl=UHL + add hl, de ; uhl=UHL+UDE + ex de, hl ; ude=UHL+UDE, uhl=UDE + scf + sbc hl, de ; uhl=UDE-(UHL+UDE)-1 + ; =UDE-UHL-UDE-1 + ; =-UHL-1 + ; =~UHL + ex (sp), hl ; uhl=UHL, *spl=~UHL + scf + sbc hl, de ; uhl=UHL-(UHL+UDE)-1 + ; =UHL-UHL-UDE-1 + ; =-UDE-1 + ; =~UDE + ex de, hl ; ude=~UDE, uhl=UHL+UDE + sbc hl, hl ; uhl=-some_bool + ccf ; cf=!some_bool + sbc hl, bc ; uhl=-some_bool-UBC-!some_bool + ; =-UBC-(some_bool+!some_bool) + ; =-UBC-1 + ; =~UBC + ld c, l + ld b, h ; bc=~BC + pop hl ; uhl=~UHL + ret diff --git a/src/std/shared/llnot_fast.src b/src/std/shared/llnot_fast.src new file mode 100644 index 000000000..9b7ce9465 --- /dev/null +++ b/src/std/shared/llnot_fast.src @@ -0,0 +1,28 @@ + assume adl=1 + + section .text + public __llnot_fast +__llnot_fast: + push hl ; *spl=UHL + add hl, de ; uhl=UHL+UDE + ex de, hl ; ude=UHL+UDE, uhl=UDE + scf + sbc hl, de ; uhl=UDE-(UHL+UDE)-1 + ; =UDE-UHL-UDE-1 + ; =-UHL-1 + ; =~UHL + ex (sp), hl ; uhl=UHL, *spl=~UHL + scf + sbc hl, de ; uhl=UHL-(UHL+UDE)-1 + ; =UHL-UHL-UDE-1 + ; =-UDE-1 + ; =~UDE + ex de, hl ; ude=~UDE, uhl=UHL+UDE + pop hl ; uhl=~UHL + ld a, c ; a=C + cpl ; a=~C + ld c, a ; c=~C + ld a, b ; a=B + cpl ; a=~B + ld b, a ; bc=~BC + ret diff --git a/src/std/shared/llor.src b/src/std/shared/llor.src new file mode 100644 index 000000000..03ba491ed --- /dev/null +++ b/src/std/shared/llor.src @@ -0,0 +1,48 @@ + assume adl=1 + + section .text + public __llor +__llor: +; CC: 62*r(PC)+25*r(SPL)+14*w(SPL)+1 + push af + push iy + ld iy, 0 + add iy, sp + push hl + push de + lea hl, iy + 16 + ld a, b + or a, (hl) + ld b, a + dec hl + ld a, c + or a, (hl) + ld c, a + dec hl + lea de, iy - 4 + ld a, (de) + or a, (hl) + ld (de), a + pop de + dec hl + ld a, d + or a, (hl) + ld d, a + dec hl + ld a, e + or a, (hl) + ld e, a + dec hl + ld a, (iy - 1) + or a, (hl) + ld (iy - 1), a + pop hl + ld a, h + or a, (iy + 10) + ld h, a + ld a, l + or a, (iy + 9) + ld l, a + pop iy + pop af + ret diff --git a/src/std/shared/llor_fast.src b/src/std/shared/llor_fast.src new file mode 100644 index 000000000..ad2bbc3b8 --- /dev/null +++ b/src/std/shared/llor_fast.src @@ -0,0 +1,44 @@ + assume adl=1 + + section .text + public __llor_fast +__llor_fast: +; CC: 56*r(PC)+19*r(SPL)+8*w(SPL)+1 + ld iy, 0 + add iy, sp + push hl + push de + lea hl, iy + 10 + ld a, b + or a, (hl) + ld b, a + dec hl + ld a, c + or a, (hl) + ld c, a + dec hl + lea de, iy - 4 + ld a, (de) + or a, (hl) + ld (de), a + pop de + dec hl + ld a, d + or a, (hl) + ld d, a + dec hl + ld a, e + or a, (hl) + ld e, a + dec hl + ld a, (iy - 1) + or a, (hl) + ld (iy - 1), a + pop hl + ld a, h + or a, (iy + 4) + ld h, a + ld a, l + or a, (iy + 3) + ld l, a + ret diff --git a/src/std/shared/llpopcnt.src b/src/std/shared/llpopcnt.src new file mode 100644 index 000000000..cc6425748 --- /dev/null +++ b/src/std/shared/llpopcnt.src @@ -0,0 +1,19 @@ + assume adl=1 + + section .text + public __llpopcnt +__llpopcnt: + call __lpopcnt + push de + push hl + ex de, hl + ld l, b + ld e, c + ld d, a + call __lpopcnt + add a, d + pop hl + pop de + ret + + extern __lpopcnt diff --git a/src/std/shared/llremu.src b/src/std/shared/llremu.src new file mode 100644 index 000000000..431799162 --- /dev/null +++ b/src/std/shared/llremu.src @@ -0,0 +1,17 @@ + assume adl=1 + + section .text + public __llremu +__llremu: + + push iy + push af + + call __lldvrmu + + pop af + pop iy + + ret + + extern __lldvrmu diff --git a/src/std/shared/llshl.src b/src/std/shared/llshl.src new file mode 100644 index 000000000..b2e700bc9 --- /dev/null +++ b/src/std/shared/llshl.src @@ -0,0 +1,31 @@ + assume adl=1 + + section .text + public __llshl +__llshl: +; Suboptimal for large shift amounts + push af + ld a, b + + push hl + ld hl, 9 + add hl, sp + ld b, (hl) + pop hl + + inc b + jr .begin + +.loop: + add hl, hl + ex de, hl + adc hl, hl + ex de, hl + rl c + rla +.begin: + djnz .loop + + ld b, a + pop af + ret diff --git a/src/std/shared/llshl_1_fast.src b/src/std/shared/llshl_1_fast.src new file mode 100644 index 000000000..6cb8a0fa3 --- /dev/null +++ b/src/std/shared/llshl_1_fast.src @@ -0,0 +1,12 @@ + assume adl=1 + + section .text + public __llshl_1_fast +__llshl_1_fast: + add hl, hl + ex de, hl + adc hl, hl + ex de, hl + rl c + rl b + ret diff --git a/src/std/shared/llshrs.src b/src/std/shared/llshrs.src new file mode 100644 index 000000000..da6cfb832 --- /dev/null +++ b/src/std/shared/llshrs.src @@ -0,0 +1,35 @@ + assume adl=1 + + section .text + public __llshrs +__llshrs: +; Suboptimal for large shift amounts + push af + push iy + ld iy, 0 + add iy, sp + ld a, (iy + 9) + or a, a + jr z, .finish + push de + push hl +.loop: + sra b + public __llshrs.hijack_llshru +.hijack_llshru: + rr c + rr (iy - 1) + rr (iy - 2) + rr (iy - 3) + rr (iy - 4) + rr (iy - 5) + rr (iy - 6) + dec a + jr nz, .loop + pop hl + pop de + public __llshrs.finish +.finish: + pop iy + pop af + ret diff --git a/src/std/shared/llshrs_1_fast.src b/src/std/shared/llshrs_1_fast.src new file mode 100644 index 000000000..76452de02 --- /dev/null +++ b/src/std/shared/llshrs_1_fast.src @@ -0,0 +1,23 @@ + assume adl=1 + + section .text + public __llshrs_1_fast +__llshrs_1_fast: + push hl + push de + ld hl, 2 + add hl, sp + sra b + rr c + rr (hl) + pop de + inc hl + inc hl + inc hl + rr d + rr e + rr (hl) + pop hl + rr h + rr l + ret diff --git a/src/std/shared/llshrs_fast.src b/src/std/shared/llshrs_fast.src new file mode 100644 index 000000000..01e603c45 --- /dev/null +++ b/src/std/shared/llshrs_fast.src @@ -0,0 +1,172 @@ + assume adl=1 + + section .text + public __llshrs_fast +__llshrs_fast: +; Could use optimization for shifting whole bytes at a time. + ld iy, 0 + add iy, sp + + ld a, c + ld c, b + ld b, (iy + 3) + inc b + dec b + jr z, .skip + + push de + push hl + +.loop: + sra c + public __llshrs_fast.hijack_llshru +.hijack_llshru: + rra + rr (iy - 1) + rr d + rr e + rr (iy - 4) + rr h + rr l + djnz .loop + + ld b, e + ld (iy - 2), d + + ex de, hl + pop hl + ld l, e + ld h, d + + pop de + ld e, b + +.skip: + ld b, c + ld c, a + + ret + + +if 0 + push bc + ld iy, 0 + add iy, sp + ld a, (iy + 6) + ld c, a + dec a + and a, 00111000b + ld (.byteshift_smc) + xor a, a + sub a, c + jr $+1 +.byteshift_smc := $-1 +.shr1_8: + ld c, b + ld iyh, a + push de + push hl + inc sp + ld a, l + pop hl + pop de + inc sp + inc sp +.shr1_8_loop: + add a, a + adc hl, hl + ex de, hl + adc hl, hl + ex de, hl + rl c + rl b + dec iyh + jr nz, .shr1_8_loop + +.shr9_16: + push de + push hl + inc sp + inc sp + ld a, h + pop hl + pop de + inc sp + +.shr17_24: + dec sp + push hl + inc sp + pop af + ex de, hl + ld e, c + ld d, b + +.shr25_32: + push de + inc sp + ld a, e + pop hl + ld e, b +.shr33_40: +.shr41_48: + rl b + pop bc + sbc hl, hl + ex de, hl + sbc hl, hl + ld l, c + ld h, b + and a, 00000111b + jr z, .shr48 + +.shr49_56_loop: + add a, a + adc hl, hl + djnz .shr49_56_loop +.shr48: + +.shr49_56: + rl b + pop bc + sbc hl, hl + ex de, hl + sbc hl, hl + ld l, b + and a, 00000111b + jr z, .shr56 + ld b, a + ld a, c +.shr49_56_loop: + add a, a + adc hl, hl + djnz .shr49_56_loop +.shr56: + ld c, d + ld b, c + ret + +.shr57_63_0: + and a, 00000111b + jr z, .shr0 +.shr57_63: + rl b + pop bc + sbc hl, hl + ex de, hl + sbc hl, hl + ld l, b + ld b, a +.shr57_63_loop: + add hl, hl + djnz .shr57_63_loop + ld l, h + ld h, e + ld c, d + ld b, c + ret + +.shr0: + pop bc + ret +end if diff --git a/src/std/shared/llshru.src b/src/std/shared/llshru.src new file mode 100644 index 000000000..d2f30982d --- /dev/null +++ b/src/std/shared/llshru.src @@ -0,0 +1,20 @@ + assume adl=1 + + section .text + public __llshru +__llshru: +; Suboptimal for large shift amounts + push af + push iy + ld iy, 0 + add iy, sp + ld a, (iy + 9) + or a, a + jp z, __llshrs.finish + push de + push hl + srl b + jp __llshrs.hijack_llshru + + extern __llshrs.finish + extern __llshrs.hijack_llshru diff --git a/src/std/shared/llshru_1_fast.src b/src/std/shared/llshru_1_fast.src new file mode 100644 index 000000000..6af6e39fd --- /dev/null +++ b/src/std/shared/llshru_1_fast.src @@ -0,0 +1,23 @@ + assume adl=1 + + section .text + public __llshru_1_fast +__llshru_1_fast: + push hl + push de + ld hl, 2 + add hl, sp + srl b + rr c + rr (hl) + pop de + inc hl + inc hl + inc hl + rr d + rr e + rr (hl) + pop hl + rr h + rr l + ret diff --git a/src/std/shared/llshru_fast.src b/src/std/shared/llshru_fast.src new file mode 100644 index 000000000..09d162c84 --- /dev/null +++ b/src/std/shared/llshru_fast.src @@ -0,0 +1,24 @@ + assume adl=1 + + section .text + public __llshru_fast +__llshru_fast: + ld iy, 0 + add iy, sp + + ld a, (iy + 3) + or a, a + ret z + + ld a, c + ld c, b + ld b, (iy + 3) + + push de + push hl + + srl c + jp __llshrs_fast.hijack_llshru + + + extern __llshrs_fast.hijack_llshru diff --git a/src/std/shared/llsub.src b/src/std/shared/llsub.src new file mode 100644 index 000000000..bbdca06a2 --- /dev/null +++ b/src/std/shared/llsub.src @@ -0,0 +1,23 @@ + assume adl=1 + + section .text + public __llsub +__llsub: + push iy + ld iy, 0 + add iy, sp + push bc + ld bc, (iy + 6) + sbc hl, bc + ex de, hl + ld bc, (iy + 9) + sbc hl, bc + ex de, hl + ex (sp), hl + ld bc, (iy + 12) + sbc hl, bc + ld c, l + ld b, h + pop hl + pop iy + ret diff --git a/src/std/shared/llsub_1.src b/src/std/shared/llsub_1.src new file mode 100644 index 000000000..d21d768fd --- /dev/null +++ b/src/std/shared/llsub_1.src @@ -0,0 +1,16 @@ + assume adl=1 + + section .text + public __llsub_1 +__llsub_1: + add hl, de + or a, a + sbc hl, de + dec hl + ret nz + ex de, hl + add hl, de + ex de, hl + ret c + dec bc + ret diff --git a/src/std/shared/llsub_fast.src b/src/std/shared/llsub_fast.src new file mode 100644 index 000000000..374a5a3b7 --- /dev/null +++ b/src/std/shared/llsub_fast.src @@ -0,0 +1,22 @@ + assume adl=1 + + section .text + public __llsub_fast +__llsub_fast: + ld iy, 0 + add iy, sp + push bc + ld bc, (iy + 3) + sbc hl, bc + ex de, hl + ld bc, (iy + 6) + sbc hl, bc + ex de, hl + pop bc + ld a, c + sbc a, (iy + 9) + ld c, a + ld a, b + sbc a, (iy + 10) + ld b, a + ret diff --git a/src/std/shared/llxor.src b/src/std/shared/llxor.src new file mode 100644 index 000000000..8a3d3cefa --- /dev/null +++ b/src/std/shared/llxor.src @@ -0,0 +1,48 @@ + assume adl=1 + + section .text + public __llxor +__llxor: +; CC: 62*r(PC)+25*r(SPL)+14*w(SPL)+1 + push af + push iy + ld iy, 0 + add iy, sp + push hl + push de + lea hl, iy + 16 + ld a, b + xor a, (hl) + ld b, a + dec hl + ld a, c + xor a, (hl) + ld c, a + dec hl + lea de, iy - 4 + ld a, (de) + xor a, (hl) + ld (de), a + pop de + dec hl + ld a, d + xor a, (hl) + ld d, a + dec hl + ld a, e + xor a, (hl) + ld e, a + dec hl + ld a, (iy - 1) + xor a, (hl) + ld (iy - 1), a + pop hl + ld a, h + xor a, (iy + 10) + ld h, a + ld a, l + xor a, (iy + 9) + ld l, a + pop iy + pop af + ret diff --git a/src/std/shared/llxor_fast.src b/src/std/shared/llxor_fast.src new file mode 100644 index 000000000..26ce685a4 --- /dev/null +++ b/src/std/shared/llxor_fast.src @@ -0,0 +1,44 @@ + assume adl=1 + + section .text + public __llxor_fast +__llxor_fast: +; CC: 56*r(PC)+19*r(SPL)+8*w(SPL)+1 + ld iy, 0 + add iy, sp + push hl + push de + lea hl, iy + 10 + ld a, b + xor a, (hl) + ld b, a + dec hl + ld a, c + xor a, (hl) + ld c, a + dec hl + lea de, iy - 4 + ld a, (de) + xor a, (hl) + ld (de), a + pop de + dec hl + ld a, d + xor a, (hl) + ld d, a + dec hl + ld a, e + xor a, (hl) + ld e, a + dec hl + ld a, (iy - 1) + xor a, (hl) + ld (iy - 1), a + pop hl + ld a, h + xor a, (iy + 4) + ld h, a + ld a, l + xor a, (iy + 3) + ld l, a + ret diff --git a/src/std/shared/lmulu_fast.src b/src/std/shared/lmulu_fast.src new file mode 100644 index 000000000..59b1e40a4 --- /dev/null +++ b/src/std/shared/lmulu_fast.src @@ -0,0 +1,82 @@ + assume adl=1 + + section .text + public __lmuls_fast, __lmulu_fast +__lmuls_fast: +__lmulu_fast: + +; Multiplies EUHL by AUBC and returns the 32-bit product euhl. +; I: AUBC=multiplier, EUHL=multiplicand, ADL=1 +; O: a=EUHL*AUBC-L*C>>24, ubc=L*C, deu=0, d=H*C>>8, euhl=EUHL*AUBC +; FO: sz(e), vc((EUHL*AUBC-L*C&0xFFFFFFFF)+L*C) +; CC: (86+2*cf)*r(PC)+9*w(SPL)+9*r(SPL)+42 +; ; a ubc ude uhl uix u(sp) +Mul_EUHL_AUBC_EUHL_Fast: ;--------------+---------------+---------------+---------------+---------------+------------------------ + push ix ; u(sp)=UIX + ld d, c ; de=CE + mlt de ; ude=E*C + ld d, a ; d =A + ld a, e ; a=E*C + ld e, l ; de=AL + ld ixl, e ; ixl=L + mlt de ; ude=L*A + add a, e ; a=E*C+L*A + dec sp + push bc + inc sp + inc sp + push hl + inc sp + inc sp ; (sp)=[BCU][HLU] + ld d, h ; d =H + ld ixh, d ; ix=HL + pop hl ; hl=[BCU][HLU] -- + ld e, h ; de=H[BCU] + mlt de ; ude=H*BCU + add a, e ; a=E*C+H*BCU+L*A + ld d, b ; d =B + ld e, l ; de=B[HLU] + mlt de ; ude=HLU*B + add a, e ; a=E*C+HLU*B+H*BCU+L*A + ld d, h ; d =BCU + ld e, ixl ; de=[BCU]L + ld h, c ; hl=C[HLU] + mlt de ; ude=L*BCU + mlt hl ; uhl=HLU*C + add hl, de ; uhl=HLU*C+L*BCU + ld d, b ; d =B + ld e, ixh ; de=BH + mlt de ; ude=H*B + add hl, de ; uhl=HLU*C+H*B+L*BCU + add a, h ; a=(HLU*C+H*B+L*BCU>>8)+E*C+HLU*B+H*BCU+L*A + ld h, l ; h =HLU*C+H*B+L*BCU + ld l, 0 ; hl=HLU*C+H*B+L*BCU<<8 + ld d, b ; d =B + ld e, ixl ; de=BL + mlt de ; ude=L*B + add.s hl, de ; uhl=L*B+(HLU*C+H*B+L*BCU<<8)&0xFFFF + adc a, 0 ; a=L*B+(HLU*C+H*B+L*BCU<<8)+(E*C+HLU*B+H*BCU+L*A<<16)>>16 + ld d, ixh ; d =H + ld e, c ; de=HC + mlt de ; ude=H*C + add hl, de ; uhl=H*C+(L*B+(HLU*C+H*B+L*BCU<<8)&0xFFFF) + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl ; uhl=(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16) + adc a, l ; a=H*C+L*B+(HLU*C+H*B+L*BCU<<8)+(E*C+HLU*B+H*BCU+L*A<<16)>>16 + ld b, ixl ; bc =LC + mlt bc ; ubc=L*C + add hl, bc ; uhl=L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16) + pop ix ; uix=UIX -- + ld e, a ; e=H*C+L*B+(HLU*C+H*B+L*BCU<<8)+(E*C+HLU*B+H*BCU+L*A<<16)>>16 + ret nc ; nc => e=L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16)+(E*C+HLU*B+H*BCU+L*A<<24)>>24 + inc e ; e=L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16)+(E*C+HLU*B+H*BCU+L*A<<24)>>24 + ret + +; (EUHL*AUBC)&0xFFFFFFFF=L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16)+(E*C+HLU*B+H*BCU+L*A<<24)+(E*B+HLU*BCU+H*A<<32)+(E*BCU+HLU*A<<40)+(E*A<<48)&0xFFFFFFFF +; =L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16)+(E*C+HLU*B+H*BCU+L*A<<24)&0xFFFFFFFF diff --git a/src/std/shared/lneg_fast.src b/src/std/shared/lneg_fast.src new file mode 100644 index 000000000..7c5d9dad9 --- /dev/null +++ b/src/std/shared/lneg_fast.src @@ -0,0 +1,13 @@ + assume adl=1 + + section .text + public __lneg_fast +__lneg_fast: + ld c, e ; c=E + ex de, hl ; ude=UHL, l=E + xor a, a ; a=0 + sbc hl, hl ; uhl=0 + sbc hl, de ; uhl=-UHL + sbc a, c + ld e, a ; euhl=-EUHL + ret diff --git a/src/std/shared/lnot_fast.src b/src/std/shared/lnot_fast.src new file mode 100644 index 000000000..474cd6527 --- /dev/null +++ b/src/std/shared/lnot_fast.src @@ -0,0 +1,16 @@ + assume adl=1 + + section .text + public __lnot_fast +__lnot_fast: + ld a, e ; a=E + add hl, de ; uhl=UHL+x + ex de, hl ; ude=UHL+x, uhl=x + scf + sbc hl, de ; uhl=x-(UHL+x)-1 + ; =x-UHL-x-1 + ; =-UHL-1 + ; =~UHL + cpl ; a=~E + ld e, a ; e=~E + ret diff --git a/src/std/shared/lor_fast.src b/src/std/shared/lor_fast.src new file mode 100644 index 000000000..f8d8d8db4 --- /dev/null +++ b/src/std/shared/lor_fast.src @@ -0,0 +1,27 @@ + assume adl=1 + + section .text + public __lor_fast +__lor_fast: + or a, e + ld e, a + push bc + inc sp + inc sp + push hl + ld hl, 2 + add hl, sp + ld a, (hl) + inc hl + or a, (hl) + dec hl + ld (hl), a + pop hl + inc sp + ld a, h + or a, b + ld h, a + ld a, l + or a, c + ld l, a + ret diff --git a/src/std/shared/lpopcnt.src b/src/std/shared/lpopcnt.src index 6a2e03b9d..9ace25d2e 100644 --- a/src/std/shared/lpopcnt.src +++ b/src/std/shared/lpopcnt.src @@ -3,23 +3,32 @@ section .text public __lpopcnt __lpopcnt: - push hl,de - ld a,l - call __bpopcnt - ld l,a - ld a,h - call __bpopcnt - ld h,a - ld a,e - call __bpopcnt - ld e,a - call $21D5C - call __bpopcnt - add a,e - add a,l - add a,h - pop de,hl + push bc + ld b, 4 + public __lpopcnt.hijack1 +.hijack1: + push hl + xor a, a + ld c, a +.loop: + add hl, hl + adc a, c + add hl, hl + adc a, c + add hl, hl + adc a, c + add hl, hl + adc a, c + add hl, hl + adc a, c + add hl, hl + adc a, c + add hl, hl + adc a, c + add hl, hl + adc a, c + ld l, e + djnz .loop + pop hl + pop bc ret - - extern __bpopcnt - diff --git a/src/std/shared/lrems.src b/src/std/shared/lrems.src new file mode 100644 index 000000000..5b8f8f386 --- /dev/null +++ b/src/std/shared/lrems.src @@ -0,0 +1,25 @@ + assume adl=1 + + section .text + public __lrems +__lrems: +; I: EUHL=dividend, AUBC=divisor +; O: euhl=EUHL%AUBC + + bit 7, e + push af + push bc + + call __ldivs_lrems_common + + call __lremu + + pop bc + pop af + ret z + jp __lneg + + + extern __ldivs_lrems_common + extern __lneg + extern __lremu diff --git a/src/std/shared/lshrs_1_fast.src b/src/std/shared/lshrs_1_fast.src new file mode 100644 index 000000000..f5a3d85a6 --- /dev/null +++ b/src/std/shared/lshrs_1_fast.src @@ -0,0 +1,14 @@ + assume adl=1 + + section .text + public __lshru_1_fast +__lshru_1_fast: + push hl + ld hl, 2 + add hl, sp + sra e + rr (hl) + pop hl + rr h + rr l + ret diff --git a/src/std/shared/lshru_1_fast.src b/src/std/shared/lshru_1_fast.src new file mode 100644 index 000000000..86c81891e --- /dev/null +++ b/src/std/shared/lshru_1_fast.src @@ -0,0 +1,14 @@ + assume adl=1 + + section .text + public __lshru_1_fast +__lshru_1_fast: + push hl + ld hl, 2 + add hl, sp + srl e + rr (hl) + pop hl + rr h + rr l + ret diff --git a/src/std/shared/lsub_1.src b/src/std/shared/lsub_1.src new file mode 100644 index 000000000..61a0d8ee0 --- /dev/null +++ b/src/std/shared/lsub_1.src @@ -0,0 +1,12 @@ + assume adl=1 + + section .text + public __lsub_1 +__lsub_1: + add hl, bc + or a, a + sbc hl, bc + dec hl + ret nz + dec e + ret diff --git a/src/std/shared/lsub_fast.src b/src/std/shared/lsub_fast.src new file mode 100644 index 000000000..2e8776118 --- /dev/null +++ b/src/std/shared/lsub_fast.src @@ -0,0 +1,12 @@ + assume adl=1 + + section .text + public __lsub_fast +__lsub_fast: + or a, a + sbc hl, bc + cpl + ccf + adc a, e + ld e, a + ret diff --git a/src/std/shared/lxor_fast.src b/src/std/shared/lxor_fast.src new file mode 100644 index 000000000..6dae8c1d8 --- /dev/null +++ b/src/std/shared/lxor_fast.src @@ -0,0 +1,27 @@ + assume adl=1 + + section .text + public __lxor_fast +__lxor_fast: + xor a, e + ld e, a + push bc + inc sp + inc sp + push hl + ld hl, 2 + add hl, sp + ld a, (hl) + inc hl + xor a, (hl) + dec hl + ld (hl), a + pop hl + inc sp + ld a, h + xor a, b + ld h, a + ld a, l + xor a, c + ld l, a + ret diff --git a/src/std/shared/memset.src b/src/std/shared/memset.src index f6ff66fa1..6e2dff1d0 100644 --- a/src/std/shared/memset.src +++ b/src/std/shared/memset.src @@ -1,4 +1,3 @@ -; void *memset(void *dest, int c, size_t count); assume adl=1 section .text diff --git a/src/std/shared/outchar.src b/src/std/shared/outchar.src index 62b6efd6b..81ef54839 100644 --- a/src/std/shared/outchar.src +++ b/src/std/shared/outchar.src @@ -1,4 +1,4 @@ - assume adl = 1 + assume adl=1 section .text weak _outchar diff --git a/src/std/shared/printf.c b/src/std/shared/printf.c index 0d6ef49f8..5852015e4 100644 --- a/src/std/shared/printf.c +++ b/src/std/shared/printf.c @@ -38,8 +38,8 @@ #include // Exclude these from printf support because no one uses them -#define PRINTF_DISABLE_SUPPORT_PTRDIFF_T -#define PRINTF_DISABLE_SUPPORT_LONG_LONG +// #define PRINTF_DISABLE_SUPPORT_PTRDIFF_T +// #define PRINTF_DISABLE_SUPPORT_LONG_LONG // 'ntoa' conversion buffer size, this must be big enough to hold one converted // numeric number including padded zeros (dynamically created on stack) diff --git a/src/std/shared/putchar.src b/src/std/shared/putchar.src index ec1e0ec6c..8cbb72c58 100644 --- a/src/std/shared/putchar.src +++ b/src/std/shared/putchar.src @@ -1,4 +1,4 @@ - assume adl = 1 + assume adl=1 section .text public _putchar diff --git a/src/std/shared/puts.src b/src/std/shared/puts.src index b4691396e..0dc70d5c1 100644 --- a/src/std/shared/puts.src +++ b/src/std/shared/puts.src @@ -1,4 +1,4 @@ - assume adl = 1 + assume adl=1 section .text public _puts diff --git a/src/std/shared/sand_fast.src b/src/std/shared/sand_fast.src new file mode 100644 index 000000000..78d91ee15 --- /dev/null +++ b/src/std/shared/sand_fast.src @@ -0,0 +1,12 @@ + assume adl=1 + + section .text + public __sand_fast +__sand_fast: + ld a, h + and a, b + ld h, a + ld a, l + and a, c + ld l, a + ret diff --git a/src/std/shared/sbitrev.src b/src/std/shared/sbitrev.src index ef1b03e83..05d9a81d1 100644 --- a/src/std/shared/sbitrev.src +++ b/src/std/shared/sbitrev.src @@ -4,13 +4,16 @@ public __sbitrev __sbitrev: push af - ld a,l - call __bbitrev - ld l,a - ld a,h - call __bbitrev - ld h,a + push hl + dec sp + pop hl + inc sp ; uhl=HL? + call __internal_bitrev_byte ; a=H', uhl=L?0 + ld l, a ; uhl=L?H' + call __internal_bitrev_byte ; a=L', hl=H'0 + ld l, h + ld h, a ; hl=L'H' pop af ret - extern __bbitrev + extern __internal_bitrev_byte diff --git a/src/std/shared/scmpzero.src b/src/std/shared/scmpzero.src new file mode 100644 index 000000000..4fc7510d8 --- /dev/null +++ b/src/std/shared/scmpzero.src @@ -0,0 +1,9 @@ + assume adl=1 + + section .text + public __scmpzero +__scmpzero: + add hl, de + or a, a + sbc.s hl, de + ret diff --git a/src/std/shared/sctlz.src b/src/std/shared/sctlz.src new file mode 100644 index 000000000..96815e2c9 --- /dev/null +++ b/src/std/shared/sctlz.src @@ -0,0 +1,17 @@ + assume adl=1 + + section .text + public __sctlz +__sctlz: + push hl + + scf + sbc a, a + +.loop: + adc.s hl, hl + inc a + jr nc, .loop + + pop hl + ret diff --git a/src/std/shared/shared.src b/src/std/shared/shared.src index 4df054f0c..d82a7f87d 100644 --- a/src/std/shared/shared.src +++ b/src/std/shared/shared.src @@ -1,121 +1,128 @@ - public __bshl, __bshru, __case, __case16, __case16D, __case24, __case24D, __case8, __case8D, __fadd, __fcmp, __fdiv, __fmul, __fppack, __frbtof, __frftob, __frftoi, __frftos, __frftoub, __frftoui, __frftous, __fritof, __frstof, __frubtof, __fruitof, __frustof, __fsub, __ftol, __iand, __icmpzero, __idivs, __idivu, __idvrmu, __imul_b, __imuls, __imulu, __indcall, __ineg, __inot, __ior, __irems, __iremu, __ishl, __ishl_b, __ishrs, __ishrs_b, __ishru, __ishru_b, __itol, __ixor, __ladd, __ladd_b, __land, __lcmps, __lcmpu, __lcmpzero, __ldivs, __ldivu, __ldvrmu, __lmuls, __lmulu, __lneg, __lnot, __lor, __lrems, __lremu, __lshl, __lshrs, __lshru, __lsub, __ltof, __lxor, __sand, __scmpzero, __sdivs, __sdivu, __seqcase, __seqcaseD, __setflag, __smuls, __smulu, __sneg, __snot, __sor, __srems, __sremu, __sshl, __sshl_b, __sshrs, __sshrs_b, __sshru, __sshru_b, __stoi, __stoiu, __sxor, __ultof, _longjmp, _memchr, _memcmp, _memcpy, _memmove, _setjmp, ___sprintf, _sqrtf, _strcasecmp, _strcat, _strchr, _strcmp, _strcpy, _strcspn, _strlen, _strncat, _strncmp, _strncpy, _strpbrk, _strspn, _strstr, _strtok, _tolower, _toupper -__bshl := 000100h -__bshru := 000104h + public __case __case := 000110h + public __case16 __case16 := 000114h + public __case16D __case16D := 000118h + public __case24 __case24 := 00011Ch + public __case24D __case24D := 000120h + public __case8 __case8 := 000124h + public __case8D __case8D := 000128h + public __fadd __fadd := 000270h + public __fcmp __fcmp := 000274h + public __fdiv __fdiv := 000278h + public __fmul __fmul := 000288h + public __fppack __fppack := 00026Ch + public __frbtof __frbtof := 00029Ch + public __frftob __frftob := 0002A0h + public __frftoi __frftoi := 0002A8h + public __frftos __frftos := 0002B0h + public __frftoub __frftoub := 0002A4h + public __frftoui __frftoui := 0002ACh + public __frftous __frftous := 0002B4h + public __fritof __fritof := 0002B8h + public __frstof __frstof := 0002C0h + public __frubtof __frubtof := 0002C4h + public __fruitof __fruitof := 0002BCh + public __frustof __frustof := 0002C8h + public __fsub __fsub := 000290h + public __ftol __ftol := 00027Ch -__iand := 000134h -__icmpzero := 000138h -__idivs := 00013Ch -__idivu := 000140h -__idvrmu := 000144h + public __imul_b __imul_b := 000150h -__imuls := 000154h -__imulu := 000158h + public __indcall __indcall := 00015Ch -__ineg := 000160h -__inot := 000164h -__ior := 000168h -__irems := 00016Ch -__iremu := 000170h -__ishl := 000174h + public __ishl_b __ishl_b := 000178h -__ishrs := 00017Ch + public __ishrs_b __ishrs_b := 000180h -__ishru := 000184h + public __ishru_b __ishru_b := 000188h + public __itol __itol := 000194h -__ixor := 000198h -__ladd := 00019Ch -__ladd_b := 0001A0h -__land := 0001A4h -__lcmps := 0001A8h -__lcmpu := 0001ACh -__lcmpzero := 0001B0h -__ldivs := 0001B4h -__ldivu := 0001B8h -__ldvrmu := 0001BCh -__lmuls := 0001C8h -__lmulu := 0001CCh -__lneg := 0001D0h -__lnot := 0001D4h -__lor := 0001D8h -__lrems := 0001DCh -__lremu := 0001E0h -__lshl := 0001E4h -__lshrs := 0001E8h -__lshru := 0001ECh -__lsub := 0001F8h + public __ltof __ltof := 000284h -__lxor := 0001FCh -__sand := 000200h -__scmpzero := 000204h -__sdivs := 000208h -__sdivu := 00020Ch + public __seqcase __seqcase := 000210h + public __seqcaseD __seqcaseD := 000214h + public __setflag __setflag := 000218h -__smuls := 000224h -__smulu := 000228h -__sneg := 00022Ch -__snot := 000230h -__sor := 000234h -__srems := 000238h -__sremu := 00023Ch -__sshl := 000240h + public __sshl_b __sshl_b := 000244h -__sshrs := 000248h + public __sshrs_b __sshrs_b := 00024Ch -__sshru := 000250h + public __sshru_b __sshru_b := 000254h + public __stoi __stoi := 000260h + public __stoiu __stoiu := 000264h -__sxor := 000268h + public __ultof __ultof := 000280h + public _longjmp _longjmp := 000098h + public _memchr _memchr := 00009Ch + public _memcmp _memcmp := 0000A0h + public _memcpy _memcpy := 0000A4h + public _memmove _memmove := 0000A8h + public _setjmp _setjmp := 0000B8h + public ___sprintf ___sprintf := 0000BCh + public _sqrtf _sqrtf := 000298h + public _strcasecmp _strcasecmp := 021E3Ch + public _strcat _strcat := 0000C0h + public _strchr _strchr := 0000C4h + public _strcmp _strcmp := 0000C8h + public _strcpy _strcpy := 0000CCh + public _strcspn _strcspn := 0000D0h + public _strlen _strlen := 0000D4h + public _strncat _strncat := 0000D8h + public _strncmp _strncmp := 0000DCh + public _strncpy _strncpy := 0000E0h + public _strpbrk _strpbrk := 0000E4h + public _strspn _strspn := 0000ECh + public _strstr _strstr := 0000F0h + public _strtok _strtok := 0000F4h -_tolower := 021E34h -_toupper := 021E38h diff --git a/src/std/shared/smulu_fast.src b/src/std/shared/smulu_fast.src new file mode 100644 index 000000000..434997af9 --- /dev/null +++ b/src/std/shared/smulu_fast.src @@ -0,0 +1,29 @@ + assume adl=1 + + section .text + public __smuls_fast, __smulu_fast +__smuls_fast: +__smulu_fast: + +; Multiplies HL by BC and returns the 16-bit product hl. +; I: BC=multiplier, HL=multiplicand +; O: a=h, ubc=H*C, ude=L*B, hl=HL*BC, hlu=0 +; FO: sz(h), p/v=?, c=? +; CC: 16*r(PC)+(ADL?3*r(SPL):2*r(SPS))+13 + ; a ubc ude uhl +Mul_HL_BC_HL_Fast: ;--------------+---------------+---------------+---------------- + ld d, b + ld e, l ; de=BL + ld b, h ; bc=HC + ld h, c ; hl=CL + mlt bc ; ubc=H*C + mlt de ; ude=L*B + mlt hl ; uhl=L*C + ld a, h ; a=L*C>>8 + add a, c ; a=(L*C>>8)+H*C + add a, e ; a=(L*C>>8)+H*C+L*B + ld h, a ; hl=L*C+((H*C)+(L*B)<<8) + ret + +; HL*BC&0xFFFF=L*C+(H*C+L*B<<8)+(H*B<<16)&0xFFFF +; =L*C+(H*C+L*B<<8)&0xFFFF diff --git a/src/std/shared/sneg_fast.src b/src/std/shared/sneg_fast.src new file mode 100644 index 000000000..dac70fdd7 --- /dev/null +++ b/src/std/shared/sneg_fast.src @@ -0,0 +1,7 @@ + assume adl=1 + + section .text + public __sneg_fast +__sneg_fast := __ineg_fast + + extern __ineg_fast diff --git a/src/std/shared/snot_fast.src b/src/std/shared/snot_fast.src new file mode 100644 index 000000000..6ebdb78cf --- /dev/null +++ b/src/std/shared/snot_fast.src @@ -0,0 +1,7 @@ + assume adl=1 + + section .text + public __snot_fast +__snot_fast := __inot_fast + + extern __inot_fast diff --git a/src/std/shared/sor_fast.src b/src/std/shared/sor_fast.src new file mode 100644 index 000000000..0ccb26a81 --- /dev/null +++ b/src/std/shared/sor_fast.src @@ -0,0 +1,12 @@ + assume adl=1 + + section .text + public __sor_fast +__sor_fast: + ld a, h + or a, b + ld h, a + ld a, l + or a, c + ld l, a + ret diff --git a/src/std/shared/spopcnt.src b/src/std/shared/spopcnt.src index 47a167a67..8ebd42c7b 100644 --- a/src/std/shared/spopcnt.src +++ b/src/std/shared/spopcnt.src @@ -5,7 +5,7 @@ __spopcnt: push hl ld a,l - call __bpopcnt + call __bpopcnt ld l,a ld a,h call __bpopcnt diff --git a/src/std/shared/spopcnt_fast.src b/src/std/shared/spopcnt_fast.src new file mode 100644 index 000000000..ad7685838 --- /dev/null +++ b/src/std/shared/spopcnt_fast.src @@ -0,0 +1,49 @@ + assume adl=1 + + section .text + public __spopcnt_fast +__spopcnt_fast: + push hl + xor a, a + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + add hl, hl + adc a, l + pop hl + ret diff --git a/src/std/shared/srand.src b/src/std/shared/srand.src index e0a95ebb4..ba7313bfc 100644 --- a/src/std/shared/srand.src +++ b/src/std/shared/srand.src @@ -1,4 +1,3 @@ -; void srand(unsigned int seed); assume adl=1 section .text diff --git a/src/std/shared/strncasecmp.src b/src/std/shared/strncasecmp.src index 1c05b27c3..74d0880f1 100644 --- a/src/std/shared/strncasecmp.src +++ b/src/std/shared/strncasecmp.src @@ -1,4 +1,3 @@ -; int strncasecmp ( const char *str1 , const char *str2 , int len ); assume adl=1 section .text diff --git a/src/std/shared/strtoll.c b/src/std/shared/strtoll.c new file mode 100644 index 000000000..ce543d598 --- /dev/null +++ b/src/std/shared/strtoll.c @@ -0,0 +1,97 @@ +/************************************************************************/ +/* */ +/* Copyright (C)1987-2008 by */ +/* Zilog, Inc. */ +/* */ +/* San Jose, California */ +/* */ +/************************************************************************/ +#include +#include +#include +#include +#include +#include + +/************************************************* +* +* strtoll - string to long long conversion +* +* Inputs: +* cp - pointer to the character string +* endptr - place to put ptr to first invalid character +* base - radix +* +* Returns: +* the value of the number +* +*************************************************/ +long long strtoll(const char *__restrict nptr, + char **__restrict endptr, int base) +{ + long long sum,psum; + char sign; + int radix = base; + char *cp = (char*)nptr; + char digit; + + while (isspace(*cp)) + ++cp; + + sign = 0; + if ( *cp == (char)'-' ) { + sign = 1; + ++cp; + } + else if ( *cp == (char)'+' ) + ++cp; + + if (base == 0) + { + radix = 10; + if (*cp == (char)'0') + { + if (cp[1] == (char)'x' || cp[1] == (char)'X') + { + radix = 16; + } + else + { + radix = 8; + } + } + } + + if (base == 16 && *cp == (char)'0' && (cp[1] == (char)'x' || cp[1] == (char)'X')) + cp += 2; + + sum = 0; + for (;;) { + digit = toupper(*(cp++)); + if (digit >= (char)'A') + digit = (digit - (char)'A') + (char)10; + else + digit -= (char)'0'; + if (digit < (char)0 || digit >= (char)radix) + break; + psum = sum; + sum *= radix; + sum += digit; + if (sum < psum) { /* overflow */ + sum = sign ? LLONG_MIN : LLONG_MAX; + errno=ERANGE; + break; + } + } + + if (endptr) { + --cp; + if (base == 0) { + while (*cp == (char)'h' || *cp == (char)'u' || + *cp == (char)'l' || *cp == (char)'L') + ++cp; + } + *endptr = (char*)cp; + } + return(sign ? -sum : sum); +} diff --git a/src/std/shared/strtoull.c b/src/std/shared/strtoull.c new file mode 100644 index 000000000..7c921d7a1 --- /dev/null +++ b/src/std/shared/strtoull.c @@ -0,0 +1,95 @@ +/************************************************* + * Copyright (C) 2006-2008 by Zilog, Inc. + * All Rights Reserved + *************************************************/ + +#include +#include +#include +#include +#include +#include + +/************************************************* +* +* strtoull - string to unsigned long long conversion +* +* Inputs: +* nptr - pointer to the character string +* endptr - place to put ptr to first invalid character +* base - radix +* +* Returns: +* the value of the number +* +*************************************************/ +unsigned long long strtoull(const char *__restrict nptr, + char **__restrict endptr, int base) +{ + unsigned long long sum, psum; + unsigned char sign; + unsigned char digit; + unsigned char radix = base; + char *cp = (char*)nptr; + + while (isspace(*cp)) + ++cp; + + sign = 0; + + if ( *cp == '+' ) { + ++cp; + } + else if ( *cp == '-' ) { + ++cp; + sign = 1; + } + + if (base == 0) { + if (*cp == '0') + if (cp[1] == 'x' || cp[1] == 'X') + radix = 16; + else + radix = 8; + else + radix = 10; + } + + /* If the base is declared as 16, the "0x" prefix may be ignored. */ + if (base == 16 && *cp == '0' && (cp[1] == 'x' || cp[1] == 'X')) + cp += 2; + + sum = 0; + for (;;) { + digit = toupper(*(cp++)); + if (digit >= 'A') + digit = digit - ('A' - 10); + else + digit -= '0'; + if (digit >= radix) + break; + psum = sum; + sum = sum * radix + digit; + if (sum < psum) { /* overflow */ + errno = ERANGE; + sum = ULLONG_MAX; + } + } + + if (sign) { + // errno = ERANGE; + // sum = 0; + sum = -sum; + } + + if (endptr) { + --cp; + if (base == 0) { + while (*cp == 'h' || *cp == 'u' || + *cp == 'l' || *cp == 'L') + ++cp; + } + *endptr = (char*)cp; + } + return(sum); +} diff --git a/src/std/shared/sxor_fast.src b/src/std/shared/sxor_fast.src new file mode 100644 index 000000000..beeb04b0c --- /dev/null +++ b/src/std/shared/sxor_fast.src @@ -0,0 +1,12 @@ + assume adl=1 + + section .text + public __sxor_fast +__sxor_fast: + ld a, h + xor a, b + ld h, a + ld a, l + xor a, c + ld l, a + ret diff --git a/src/std/static/bshl.src b/src/std/static/bshl.src new file mode 100644 index 000000000..851efb589 --- /dev/null +++ b/src/std/static/bshl.src @@ -0,0 +1,16 @@ + assume adl=1 + + section .text + public __bshl +__bshl: +; CC: if B!=0: B*(4*r(PC)+1)+6*r(PC)+(ADL?6*r(SPL)+3*w(SPL):4*r(SPS)+2*w(SPS))+1 +; if B==0: 4*r(PC)+(ADL?3*r(SPL):2*r(SPS))+2 + inc b + dec b + ret z + push bc +.loop: + add a, a + djnz .loop + pop bc + ret diff --git a/src/std/static/bshru.src b/src/std/static/bshru.src new file mode 100644 index 000000000..e7976e6b9 --- /dev/null +++ b/src/std/static/bshru.src @@ -0,0 +1,16 @@ + assume adl=1 + + section .text + public __bshru +__bshru: +; CC: if B!=0: B*(5*r(PC)+1)+6*r(PC)+(ADL?6*r(SPL)+3*w(SPL):4*r(SPS)+2*w(SPS))+1 +; if B==0: 4*r(PC)+(ADL?3*r(SPL):2*r(SPS))+2 + inc b + dec b + ret z + push bc +.loop: + srl a + djnz .loop + pop bc + ret diff --git a/src/std/static/cos.src b/src/std/static/cos.src index 84b2579a6..b46b685c0 100644 --- a/src/std/static/cos.src +++ b/src/std/static/cos.src @@ -1,4 +1,3 @@ -; double cos(double arg); assume adl=1 section .text diff --git a/src/std/static/iand.src b/src/std/static/iand.src new file mode 100644 index 000000000..294895f2c --- /dev/null +++ b/src/std/static/iand.src @@ -0,0 +1,27 @@ + assume adl=1 + + section .text + public __iand +__iand: + push af + push bc + inc sp + inc sp + push hl + ld hl, 2 + add hl, sp + ld a, (hl) + inc hl + and a, (hl) + dec hl + ld (hl), a + pop hl + inc sp + ld a, h + and a, b + ld h, a + ld a, l + and a, c + ld l, a + pop af + ret diff --git a/src/std/static/idivs.src b/src/std/static/idivs.src new file mode 100644 index 000000000..b6b97d407 --- /dev/null +++ b/src/std/static/idivs.src @@ -0,0 +1,17 @@ + assume adl=1 + + section .text + public __idivs +__idivs: +; I: UHL=dividend, UBC=divisor +; O: uhl=UHL/UBC + + push de + + call __idvrms + + pop de + ret + + + extern __idvrms diff --git a/src/std/static/idivu.src b/src/std/static/idivu.src new file mode 100644 index 000000000..17039c500 --- /dev/null +++ b/src/std/static/idivu.src @@ -0,0 +1,18 @@ + assume adl=1 + + section .text + public __idivu +__idivu: +; I: UHL=dividend, UBC=divisor +; O: uhl=UHL/UBC + + push de + + call __idvrmu + ex de, hl + + pop de + ret + + + extern __idvrmu diff --git a/src/std/static/idvrms.src b/src/std/static/idvrms.src new file mode 100644 index 000000000..81ab79a37 --- /dev/null +++ b/src/std/static/idvrms.src @@ -0,0 +1,47 @@ + assume adl=1 + + section .text + public __idvrms +__idvrms: +; I: UHL=dividend, UBC=divisor +; O: ude=UHL%UBC, uhl=UHL/UBC + + push bc + push af + + ex de, hl + + sbc hl, hl + ccf + sbc hl, bc + inc hl + jp m, .neg_divisor_skip + cpl + push hl + pop bc +.neg_divisor_skip: + + sbc hl, hl + ccf + sbc hl, de + inc hl + jp p, .pos_dividend_skip + cpl + ex de, hl +.pos_dividend_skip: + + call __idvrmu + + call p, __ineg + + ld b, a + pop af + cp a, b + pop bc + ex de, hl + ret nz + jp __ineg + + + extern __idvrmu + extern __ineg diff --git a/src/std/static/idvrmu.src b/src/std/static/idvrmu.src new file mode 100644 index 000000000..967669dd6 --- /dev/null +++ b/src/std/static/idvrmu.src @@ -0,0 +1,37 @@ + assume adl=1 + + section .text + public __idvrmu +__idvrmu: +; I: UHL=dividend, UBC=divisor +; O: ude=UHL/UBC, uhl=UHL%UBC + + ex de, hl + + push af + ld a, 24 + public __idvrmu.hijack_a_iters_ude_dividend +.hijack_a_iters_ude_dividend: + + or a, a + sbc hl, hl + +.loop: + ex de, hl + add hl, hl + ex de, hl + adc hl, hl + + sbc hl, bc + inc e + + jr nc, .restore_skip + add hl, bc + dec e +.restore_skip: + + dec a + jr nz, .loop + + pop af + ret diff --git a/src/std/static/imulu.src b/src/std/static/imulu.src new file mode 100644 index 000000000..f52ec8843 --- /dev/null +++ b/src/std/static/imulu.src @@ -0,0 +1,60 @@ + assume adl=1 + + section .text + public __imuls, __imulu +__imuls: +__imulu: + +; Multiplies UHL by UBC and returns the 24-bit product uhl. +; I: UBC=multiplier, UHL=multiplicand, ADL=1 +; O: uhl=UHL*UBC +; FO: -- +; CC: 49*r(PC)+15*r(SPL)+12*w(SPL)+25 +; ; a ude uhl u(sp) +Mul_UHL_UBC_UHL: ;--------------+---------------+---------------+---------------------------------------- + push af ; u(sp)=AF + push de ; u(sp)=UDE + ld d, b + ld e, h ; de=BH + mlt de ; ude=H*B + ld a, e ; a=H*B + dec sp + push hl + push bc + inc sp ; (sp)=[HLU]H + ; (sp)=[BCU]B + pop de ; de=[BCU]B -- + ld e, l ; de=[BCU]L + mlt de ; ude=L*BCU + add a, e ; a=H*B+L*BCU + pop de ; de=[HLU]H -- + ld e, c ; de=[HLU]C + mlt de ; ude=HLU*C + add a, e ; a=HLU*C+H*B+L*BCU + ld e, l ; e=L + ld l, c ; hl=HC + mlt hl ; uhl=H*C + add a, h ; a=(H*C>>8)+HLU*C+H*B+L*BCU + ld h, a ; uhl=H*C+(HLU*C+H*B+L*BCU<<8)&0xFFFF + ld a, e ; a=L + ld d, b ; de=BL + mlt de ; ude=L*B + add hl, de ; uhl=L*B+(H*C+(HLU*C+H*B+L*BCU<<8)&0xFFFF) + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl ; uhl=(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16) + ld d, a ; d =L + ld e, c ; de=LC + mlt de ; ude=L*C + add hl, de ; uhl=L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16) + pop de ; ude=UDE -- + pop af ; a=A -- + ret + +; (UHL*UBC)&0xFFFFFF=L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16)+(HLU*B+H*BCU<<24)+(HLU*BCU<<32)&0xFFFFFF +; =L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16)&0xFFFFFF diff --git a/src/std/static/ineg.src b/src/std/static/ineg.src new file mode 100644 index 000000000..dec4d057a --- /dev/null +++ b/src/std/static/ineg.src @@ -0,0 +1,23 @@ + assume adl=1 + + section .text + public __ineg +__ineg: +if 0 + push de +end if + add hl, de ; uhl=UHL+UDE + ex de, hl ; ude=UHL+UDE, uhl=UDE + or a, a + sbc hl, de ; uhl=UDE-(UHL+UDE) + ; =UDE-UHL-UDE + ; =-UHL +if 0 + pop de +else + ex de, hl ; ude=-UHL, uhl=UHL+UDE + add hl, de ; uhl=UHL+UDE+-UHL + ; =UDE + ex de, hl ; ude=UDE, uhl=-UHL +end if + ret diff --git a/src/std/static/inot.src b/src/std/static/inot.src new file mode 100644 index 000000000..e133ee514 --- /dev/null +++ b/src/std/static/inot.src @@ -0,0 +1,27 @@ + assume adl=1 + + section .text + public __inot +__inot: +if 0 + push de +end if + add hl, de ; uhl=UHL+UDE + ex de, hl ; ude=UHL+UDE, uhl=UDE + scf + sbc hl, de ; uhl=UDE-(UHL+UDE)-1 + ; =UDE-UHL-UDE-1 + ; =-UHL-1 + ; =~UHL +if 0 + pop de +else + ex de, hl ; ude=~UHL, uhl=UHL+UDE + add hl, de ; uhl=UHL+UDE+~UHL + ; =UHL+UDE+(-UHL-1) + ; =UHL+UDE-UHL-1 + ; =UDE-1 + inc hl ; uhl=UDE + ex de, hl ; ude=UDE, uhl=~UHL +end if + ret diff --git a/src/std/static/ior.src b/src/std/static/ior.src new file mode 100644 index 000000000..9fc3e3d40 --- /dev/null +++ b/src/std/static/ior.src @@ -0,0 +1,27 @@ + assume adl=1 + + section .text + public __ior +__ior: + push af + push bc + inc sp + inc sp + push hl + ld hl, 2 + add hl, sp + ld a, (hl) + inc hl + or a, (hl) + dec hl + ld (hl), a + pop hl + inc sp + ld a, h + or a, b + ld h, a + ld a, l + or a, c + ld l, a + pop af + ret diff --git a/src/std/static/irems.src b/src/std/static/irems.src new file mode 100644 index 000000000..fed933a7c --- /dev/null +++ b/src/std/static/irems.src @@ -0,0 +1,18 @@ + assume adl=1 + + section .text + public __irems +__irems: +; I: UHL=dividend, UBC=divisor +; O: uhl=UHL%UBC + + push de + + call __idvrms + ex de, hl + + pop de + ret + + + extern __idvrms diff --git a/src/std/static/iremu.src b/src/std/static/iremu.src new file mode 100644 index 000000000..105428371 --- /dev/null +++ b/src/std/static/iremu.src @@ -0,0 +1,17 @@ + assume adl=1 + + section .text + public __iremu +__iremu: +; I: UHL=dividend, UBC=divisor +; O: uhl=UHL%UBC + + push de + + call __idvrmu + + pop de + ret + + + extern __idvrmu diff --git a/src/std/static/ishl.src b/src/std/static/ishl.src new file mode 100644 index 000000000..2dc3749f5 --- /dev/null +++ b/src/std/static/ishl.src @@ -0,0 +1,18 @@ + assume adl=1 + + section .text + public __ishl +__ishl: +; Suboptimal for large shift amounts +; CC: if C!=0: C*(4*r(PC)+1)+7*r(PC)+(ADL?6*r(SPL)+3*w(SPL):4*r(SPS)+2*w(SPS))+1 +; if C==0: 4*r(PC)+(ADL?3*r(SPL):2*r(SPS))+2 + inc c + dec c + ret z + push bc + ld b, c +.loop: + add hl, hl + djnz .loop + pop bc + ret diff --git a/src/std/static/ishrs.src b/src/std/static/ishrs.src new file mode 100644 index 000000000..9e623e560 --- /dev/null +++ b/src/std/static/ishrs.src @@ -0,0 +1,31 @@ + assume adl=1 + + section .text + public __ishrs +__ishrs: +; Suboptimal for large shift amounts +; CC: if C!=0: C*(13*r(PC)+3*r(SPL)+3*w(SPL)+4)+13*r(PC)+9*r(SPL)+6*w(SPL)+1 +; if C==0: 4*r(PC)+3*r(SPL)+2 + inc c + dec c + ret z + push bc + push hl + ld b, c + or a, a + sbc hl, hl + add hl, sp +.loop: + inc hl + inc hl + sra (hl) + public __ishrs.hijack_ishru +.hijack_ishru: + dec hl + rr (hl) + dec hl + rr (hl) + djnz .loop + pop hl + pop bc + ret diff --git a/src/std/static/ishru.src b/src/std/static/ishru.src new file mode 100644 index 000000000..bc92ad1a5 --- /dev/null +++ b/src/std/static/ishru.src @@ -0,0 +1,24 @@ + assume adl=1 + + section .text + public __ishru +__ishru: +; Suboptimal for large shift amounts +; CC: if C!=0: C*(13*r(PC)+3*r(SPL)+3*w(SPL)+4)+17*r(PC)+9*r(SPL)+6*w(SPL)+2 +; if C==0: 4*r(PC)+3*r(SPL)+2 + inc c + dec c + ret z + push bc + push hl + ld b, c + or a, a + sbc hl, hl + add hl, sp +.loop: + inc hl + inc hl + srl (hl) + jp __ishrs.hijack_ishru + + extern __ishrs.hijack_ishru diff --git a/src/std/static/ixor.src b/src/std/static/ixor.src new file mode 100644 index 000000000..637d5f021 --- /dev/null +++ b/src/std/static/ixor.src @@ -0,0 +1,27 @@ + assume adl=1 + + section .text + public __ixor +__ixor: + push af + push bc + inc sp + inc sp + push hl + ld hl, 2 + add hl, sp + ld a, (hl) + inc hl + xor a, (hl) + dec hl + ld (hl), a + pop hl + inc sp + ld a, h + xor a, b + ld h, a + ld a, l + xor a, c + ld l, a + pop af + ret diff --git a/src/std/static/ladd.src b/src/std/static/ladd.src new file mode 100644 index 000000000..5cfb14e4f --- /dev/null +++ b/src/std/static/ladd.src @@ -0,0 +1,11 @@ + assume adl=1 + + section .text + public __ladd +__ladd: + push af + add hl, bc + adc a, e + ld e, a + pop af + ret diff --git a/src/std/static/ladd_b.src b/src/std/static/ladd_b.src new file mode 100644 index 000000000..51f34a8cb --- /dev/null +++ b/src/std/static/ladd_b.src @@ -0,0 +1,14 @@ + assume adl=1 + + section .text + public __ladd_b +__ladd_b: + push bc + inc.s bc + ld c, a + ld b, 0 + add hl, bc + pop bc + ret nc + inc e + ret diff --git a/src/std/static/land.src b/src/std/static/land.src new file mode 100644 index 000000000..b75886bb5 --- /dev/null +++ b/src/std/static/land.src @@ -0,0 +1,29 @@ + assume adl=1 + + section .text + public __land +__land: + push af + and a, e + ld e, a + push bc + inc sp + inc sp + push hl + ld hl, 2 + add hl, sp + ld a, (hl) + inc hl + and a, (hl) + dec hl + ld (hl), a + pop hl + inc sp + ld a, h + and a, b + ld h, a + ld a, l + and a, c + ld l, a + pop af + ret diff --git a/src/std/static/lcmps.src b/src/std/static/lcmps.src new file mode 100644 index 000000000..f2caf241d --- /dev/null +++ b/src/std/static/lcmps.src @@ -0,0 +1,16 @@ + assume adl=1 + + section .text + public __lcmps +__lcmps: + push de + ld d, a + ld a, e + sub a, d + jr nz, .finish + sbc hl, bc + add hl, bc +.finish: + ld a, d + pop de + ret diff --git a/src/std/static/lcmpu.src b/src/std/static/lcmpu.src new file mode 100644 index 000000000..af4ca875a --- /dev/null +++ b/src/std/static/lcmpu.src @@ -0,0 +1,12 @@ + assume adl=1 + + section .text + public __lcmpu +__lcmpu: + cp a, e + ccf + ret nz + or a, a + sbc hl, bc + add hl, bc + ret diff --git a/src/std/static/ldivs.src b/src/std/static/ldivs.src new file mode 100644 index 000000000..28312d862 --- /dev/null +++ b/src/std/static/ldivs.src @@ -0,0 +1,32 @@ + assume adl=1 + + section .text + public __ldivs +__ldivs: +; I: EUHL=dividend, AUBC=divisor +; O: euhl=EUHL/AUBC + + bit 7, e + push af + push bc + + call __ldivs_lrems_common + + call __ldivu + + pop bc + pop af + + rlca + rrca + jr nz, .pos_dividend_skip + ccf +.pos_dividend_skip: + + ret c + jp __lneg + + + extern __ldivs_lrems_common + extern __ldivu + extern __lneg diff --git a/src/std/static/ldivs_lrems_common.src b/src/std/static/ldivs_lrems_common.src new file mode 100644 index 000000000..771f9903e --- /dev/null +++ b/src/std/static/ldivs_lrems_common.src @@ -0,0 +1,25 @@ + assume adl=1 + + section .text + public __ldivs_lrems_common +__ldivs_lrems_common: +; I: ZF=EUHL>=0 +; O: aubc=abs(AUBC), euhl=abs(EUHL) + + call nz, __lneg + + or a, a + ret p + + push hl + sbc hl, hl + sbc hl, bc + ex (sp), hl + pop bc + cpl + sbc a, -1 + + ret + + + extern __lneg diff --git a/src/std/static/ldivu.src b/src/std/static/ldivu.src new file mode 100644 index 000000000..9c9446028 --- /dev/null +++ b/src/std/static/ldivu.src @@ -0,0 +1,35 @@ + assume adl=1 + + section .text + public __ldivu +__ldivu: +; I: EUHL=dividend, AUBC=divisor +; O: euhl=EUHL/AUBC + +if 1 + push bc + + call __ldvrmu + + ld a, b + pop bc + + ret z + ei + ret + +else + push ix + push iy + + call __ldvrmu + ld a, iyh + pop iy + ex (sp), ix + pop hl + + ret +end if + + + extern __ldvrmu diff --git a/src/std/static/ldvrmu.src b/src/std/static/ldvrmu.src new file mode 100644 index 000000000..a798757b3 --- /dev/null +++ b/src/std/static/ldvrmu.src @@ -0,0 +1,118 @@ + assume adl=1 + + section .text +;;; struct u32div_t { +;;; uint32_t rem; +;;; uint32_t quot; +;;; }; +;;; u32div_t _ldvrmu(uint32_t dividend, uint32_t divisor) { + public __ldvrmu +__ldvrmu: +if 1 +; I: EUHL=dividend, AUBC=divisor +; O: a[uhl']=EUHL%AUBC, bcu=0, b=A, c=?, euhl=EUHL/AUBC, eubc'=AUBC, zf=!IEF2 + +;;; u32div_t result; +;;; result.quot = dividend; + ; euhl : result.quot + + push bc + + ld c, a ; c = A + ld a, i ; a = I + ; pf = IEF2 + di + + ld a, c ; a = A + exx + pop bc + ld e, a ; eubc' : divisor + + push af + +;;; result.rem = 0; + xor a, a + sbc hl, hl ; auhl' : result.rem + +;;; int i = 32; + exx + ld b, 32 ; b : i + +;;; do { +.loop: + +;;; bool dividendBit = result.quot >> 31; +;;; result.quot <<= 1; + add hl, hl + rl e +;;; result.rem = (result.rem << 1) + dividendBit; + exx + adc hl, hl + adc a, a + +;;; bool quotBit = result.rem >= divisor; +;;; result.rem -= divisor; + sbc hl, bc + sbc a, e + +;;; if (!quotBit) { + jr nc, .restore_skip +;;; result.rem += divisor; + add hl, bc + adc a, e +;;; } +.restore_skip: + +;;; if (quotBit) { + exx + jr c, .1_skip +;;; result.quot++; + inc l +;;; } +.1_skip: + +;;; } while (--i != 0); + djnz .loop + +;;; return result; + pop bc + bit 2, c + ret +;;; } + +else +; I: EUHL=dividend, AUBC=divisor +; O: auhl=EUHL%AUBC, euix=EUHL/AUBC, iyh=A, iyl=0 + + push hl + pop ix ; euix = dividend + + ld iyh, a ; [iyh]ubc = divisor + + xor a, a + sbc hl, hl ; auhl = remainder + + ld iyl, 32 + +.loop: + add ix, ix + rl e + adc hl, hl + rla + + sbc hl, bc + sbc a, iyh + inc ixl + + jr nc, .restore_skip + add hl, bc + adc a, iyh + dec ixl +.restore_skip: + + dec iyl + jr nz, .loop + + ret + +end if diff --git a/src/std/static/lmulu.src b/src/std/static/lmulu.src new file mode 100644 index 000000000..371343b36 --- /dev/null +++ b/src/std/static/lmulu.src @@ -0,0 +1,86 @@ + assume adl=1 + + section .text + public __lmuls, __lmulu +__lmuls: +__lmulu: + +; Multiplies EUHL by AUBC and returns the 32-bit product euhl. +; I: AUBC=multiplier, EUHL=multiplicand, ADL=1 +; O: euhl=EUHL*AUBC +; FO: -- +; CC: 93*r(PC)+15*w(SPL)+15*r(SPL)+41 +; ; a ude uhl uix u(sp) +Mul_EUHL_AUBC_EUHL: ;--------------+---------------+---------------+---------------+---------------------------------------- + push af ; u(sp)=AF + push de ; u(sp)=UDE + push ix ; u(sp)=UIX + ld d, c ; de=CE + mlt de ; ude=E*C + ld d, a ; d =A + ld a, e ; a=E*C + ld e, l ; de=AL + ld ixl, e ; ixl=L + mlt de ; ude=L*A + add a, e ; a=E*C+L*A + dec sp + push bc + inc sp + inc sp + push hl + inc sp + inc sp ; (sp)=[BCU][HLU] + ld d, h ; d =H + ld ixh, d ; ix=HL + pop hl ; hl=[BCU][HLU] -- + ld e, h ; de=H[BCU] + mlt de ; ude=H*BCU + add a, e ; a=E*C+H*BCU+L*A + ld d, b ; d =B + ld e, l ; de=B[HLU] + mlt de ; ude=HLU*B + add a, e ; a=E*C+HLU*B+H*BCU+L*A + ld d, h ; d =BCU + ld e, ixl ; de=[BCU]L + ld h, c ; hl=C[HLU] + mlt de ; ude=L*BCU + mlt hl ; uhl=HLU*C + add hl, de ; uhl=HLU*C+L*BCU + ld d, b ; d =B + ld e, ixh ; de=BH + mlt de ; ude=H*B + add hl, de ; uhl=HLU*C+H*B+L*BCU + add a, h ; a=(HLU*C+H*B+L*BCU>>8)+E*C+HLU*B+H*BCU+L*A + ld h, l ; h =HLU*C+H*B+L*BCU + ld l, 0 ; hl=HLU*C+H*B+L*BCU<<8 + ld d, b ; d =B + ld e, ixl ; de=BL + mlt de ; ude=L*B + add.s hl, de ; uhl=L*B+(HLU*C+H*B+L*BCU<<8)&0xFFFF + adc a, 0 ; a=L*B+(HLU*C+H*B+L*BCU<<8)+(E*C+HLU*B+H*BCU+L*A<<16)>>16 + ld d, ixh ; d =H + ld e, c ; de=HC + mlt de ; ude=H*C + add hl, de ; uhl=H*C+(L*B+(HLU*C+H*B+L*BCU<<8)&0xFFFF) + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl + add hl, hl ; uhl=(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16) + adc a, l ; a=H*C+L*B+(HLU*C+H*B+L*BCU<<8)+(E*C+HLU*B+H*BCU+L*A<<16)>>16 + ld d, ixl ; d =L + ld e, c ; de=LC + mlt de ; ude=L*C + add hl, de ; uhl=L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16) + adc a, 0 ; a=L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16)+(E*C+HLU*B+H*BCU+L*A<<24)>>24 + pop ix ; uix=UIX -- + pop de ; ude=UDE -- + ld e, a ; e=H*C+L*B+(HLU*C+H*B+L*BCU<<8)+(E*C+HLU*B+H*BCU+L*A<<16)>>16 + pop af ; a=A -- + ret + +; (EUHL*AUBC)&0xFFFFFFFF=L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16)+(E*C+HLU*B+H*BCU+L*A<<24)+(E*B+HLU*BCU+H*A<<32)+(E*BCU+HLU*A<<40)+(E*A<<48)&0xFFFFFFFF +; =L*C+(H*C+L*B<<8)+(HLU*C+H*B+L*BCU<<16)+(E*C+HLU*B+H*BCU+L*A<<24)&0xFFFFFFFF diff --git a/src/std/static/lneg.src b/src/std/static/lneg.src new file mode 100644 index 000000000..de7718ce3 --- /dev/null +++ b/src/std/static/lneg.src @@ -0,0 +1,16 @@ + assume adl=1 + + section .text + public __lneg +__lneg: + push af + push de + ex de, hl ; ude=UHL, l=E + xor a, a ; a=0 + sbc hl, hl ; uhl=0 + sbc hl, de ; uhl=-UHL + pop de ; e=E + sbc a, e + ld e, a ; euhl=-EUHL + pop af + ret diff --git a/src/std/static/lnot.src b/src/std/static/lnot.src new file mode 100644 index 000000000..04341a3fd --- /dev/null +++ b/src/std/static/lnot.src @@ -0,0 +1,20 @@ + assume adl=1 + + section .text + public __lnot +__lnot: + push af + ld a, e ; a=E + cpl ; a=~E + ld e, a ; e=~E + pop af + push de + add hl, de ; uhl=UHL+x + ex de, hl ; ude=UHL+x, uhl=x + scf + sbc hl, de ; uhl=x-(UHL+x)-1 + ; =x-UHL-x-1 + ; =-UHL-1 + ; =~UHL + pop de + ret diff --git a/src/std/static/lor.src b/src/std/static/lor.src new file mode 100644 index 000000000..314b7f818 --- /dev/null +++ b/src/std/static/lor.src @@ -0,0 +1,29 @@ + assume adl=1 + + section .text + public __lor +__lor: + push af + or a, e + ld e, a + push bc + inc sp + inc sp + push hl + ld hl, 2 + add hl, sp + ld a, (hl) + inc hl + or a, (hl) + dec hl + ld (hl), a + pop hl + inc sp + ld a, h + or a, b + ld h, a + ld a, l + or a, c + ld l, a + pop af + ret diff --git a/src/std/static/lremu.src b/src/std/static/lremu.src new file mode 100644 index 000000000..b866be210 --- /dev/null +++ b/src/std/static/lremu.src @@ -0,0 +1,35 @@ + assume adl=1 + + section .text + public __lremu +__lremu: +; I: EUHL=dividend, AUBC=divisor +; O: euhl=EUHL%AUBC + +if 1 + call __ldvrmu + ld e, a + push de + exx + ld a, e + pop de + + ret z + ei + ret + +else + push ix + push iy + + call __ldvrmu + ld e, a + ld a, iyh + + pop iy + pop ix + ret +end if + + + extern __ldvrmu diff --git a/src/std/static/lshl.src b/src/std/static/lshl.src new file mode 100644 index 000000000..fef7f3734 --- /dev/null +++ b/src/std/static/lshl.src @@ -0,0 +1,21 @@ + assume adl=1 + + section .text + public __lshl +__lshl: +; Suboptimal for large shift amounts +; CC: if L!=0: L*(5*r(PC)+1)+9*r(PC)+(ADL?12*r(SPL)+9*w(SPL):8*r(SPS)+6*w(SPS))+1 +; if L==0: 4*r(PC)+(ADL?3*r(SPL):2*r(SPS))+2 + inc l + dec l + ret z + push bc + ld b, l + ex (sp), hl +.loop: + add hl, hl + rla + djnz .loop + ex (sp), hl + pop bc + ret diff --git a/src/std/static/lshrs.src b/src/std/static/lshrs.src new file mode 100644 index 000000000..4c8d5adff --- /dev/null +++ b/src/std/static/lshrs.src @@ -0,0 +1,32 @@ + assume adl=1 + + section .text + public __lshrs +__lshrs: +; Suboptimal for large shift amounts +; CC: if C!=0: C*(15*r(PC)+3*r(SPL)+3*w(SPL)+4)+13*r(PC)+9*r(SPL)+6*w(SPL)+1 +; if C==0: 4*r(PC)+3*r(SPL)+2 + inc l + dec l + ret z + push hl + push bc + ld b, l + or a, a + sbc hl, hl + add hl, sp +.loop: + sra a + public __lshrs.hijack_lshru +.hijack_lshru: + inc hl + inc hl + rr (hl) + dec hl + rr (hl) + dec hl + rr (hl) + djnz .loop + pop bc + pop hl + ret diff --git a/src/std/static/lshru.src b/src/std/static/lshru.src new file mode 100644 index 000000000..8fd765b9e --- /dev/null +++ b/src/std/static/lshru.src @@ -0,0 +1,22 @@ + assume adl=1 + + section .text + public __lshru +__lshru: +; Suboptimal for large shift amounts +; CC: if C!=0: C*(15*r(PC)+3*r(SPL)+3*w(SPL)+4)+17*r(PC)+9*r(SPL)+6*w(SPL)+2 +; if C==0: 4*r(PC)+3*r(SPL)+2 + inc l + dec l + ret z + push hl + push bc + ld b, l + or a, a + sbc hl, hl + add hl, sp +.loop: + srl a + jp __lshrs.hijack_lshru + + extern __lshrs.hijack_lshru diff --git a/src/std/static/lsub.src b/src/std/static/lsub.src new file mode 100644 index 000000000..b18b06e6f --- /dev/null +++ b/src/std/static/lsub.src @@ -0,0 +1,14 @@ + assume adl=1 + + section .text + public __lsub +__lsub: + push af + or a, a + sbc hl, bc + cpl + ccf + adc a, e + ld e, a + pop af + ret diff --git a/src/std/static/lxor.src b/src/std/static/lxor.src new file mode 100644 index 000000000..2e6555735 --- /dev/null +++ b/src/std/static/lxor.src @@ -0,0 +1,29 @@ + assume adl=1 + + section .text + public __lxor +__lxor: + push af + xor a, e + ld e, a + push bc + inc sp + inc sp + push hl + ld hl, 2 + add hl, sp + ld a, (hl) + inc hl + xor a, (hl) + dec hl + ld (hl), a + pop hl + inc sp + ld a, h + xor a, b + ld h, a + ld a, l + xor a, c + ld l, a + pop af + ret diff --git a/src/std/static/sand.src b/src/std/static/sand.src new file mode 100644 index 000000000..643a9e706 --- /dev/null +++ b/src/std/static/sand.src @@ -0,0 +1,14 @@ + assume adl=1 + + section .text + public __sand +__sand: + push af + ld a, h + and a, b + ld h, a + ld a, l + and a, c + ld l, a + pop af + ret diff --git a/src/std/static/sdivs.src b/src/std/static/sdivs.src new file mode 100644 index 000000000..9a741a1ab --- /dev/null +++ b/src/std/static/sdivs.src @@ -0,0 +1,21 @@ + assume adl=1 + + section .text + public __sdivs +__sdivs: +; I: HL=dividend, BC=divisor +; O: uhl=HL/BC + + push de + + call __sdvrms_abs + ex de, hl + + pop de + ret p + + jp __ineg + + + extern __ineg + extern __sdvrms_abs diff --git a/src/std/static/sdivu.src b/src/std/static/sdivu.src new file mode 100644 index 000000000..f255645bb --- /dev/null +++ b/src/std/static/sdivu.src @@ -0,0 +1,18 @@ + assume adl=1 + + section .text + public __sdivu +__sdivu: +; I: HL=dividend, BC=divisor +; O: uhl=HL/BC + + push de + + call __sdvrmu + ex de, hl + + pop de + ret + + + extern __sdvrmu diff --git a/src/std/static/sdvrms_abs.src b/src/std/static/sdvrms_abs.src new file mode 100644 index 000000000..9bbb1496b --- /dev/null +++ b/src/std/static/sdvrms_abs.src @@ -0,0 +1,44 @@ + assume adl=1 + + section .text + public __sdvrms_abs +__sdvrms_abs: +; I: HL=dividend, BC=divisor +; O: ude=abs(HL)/abs(BC), uhl=abs(HL)%abs(BC), sf=(HL<0)^(BC<0), cf=HL<0 + + push bc + + ld e, a + ld a, h + xor a, b + ld a, h + rla + ld a, e + push af + + jr nc, .neg_dividend_skip + add hl, de + ex de, hl + or a, a + sbc hl, de +.neg_dividend_skip: + + ld a, b + rla + jr nc, .neg_divisor_skip + xor a, a + sub a, c + ld c, a + sbc a, a + sub a, b + ld b, a +.neg_divisor_skip: + + pop af + call __sdvrmu + + pop bc + ret + + + extern __sdvrmu diff --git a/src/std/static/sdvrmu.src b/src/std/static/sdvrmu.src new file mode 100644 index 000000000..27fe2a40d --- /dev/null +++ b/src/std/static/sdvrmu.src @@ -0,0 +1,24 @@ + assume adl=1 + + section .text + public __sdvrmu +__sdvrmu: +; I: HL=dividend, BC=divisor +; O: a=0, ude=HL/BC, uhl=HL%BC + + push hl + dec sp + pop de + inc sp + ld e, 0 + + inc bc + dec.s bc + + push af + ld a, 16 + + jp __idvrmu.hijack_a_iters_ude_dividend + + + extern __idvrmu.hijack_a_iters_ude_dividend diff --git a/src/std/static/smulu.src b/src/std/static/smulu.src new file mode 100644 index 000000000..0b3767889 --- /dev/null +++ b/src/std/static/smulu.src @@ -0,0 +1,32 @@ + assume adl=1 + + section .text + public __smuls, __smulu +__smuls: +__smulu: + +; Multiplies HL by BC and returns the 16-bit product hl. +; I: BC=multiplier, HL=multiplicand +; O: hl=HL*BC, hlu=ADL&&(L*C+(H*C+L*B<<8&0xFFFF)>>16) +; FO: c=!ADL&&(L*C+(H*C+L*B<<8&0xFFFF)>>16) +; CC: 20*r(PC)+(ADL?6*r(SPL)+3*w(SPL):4*r(SPS)+2*w(SPS))+13 + ; ude uhl u(sp) +Mul_HL_BC_HL: ;--------------+---------------+---------------- + push de ; u(sp)=UDE + ld d, h ; d =H + ld e, c ; de=HC + mlt de ; ude=H*C + ld d, l ; d=L + ld h, b ; hl=BL + mlt hl ; uhl=L*B + add hl, de ; uhl=(L<<8)+(H*C&0xFF)+L*B + ld h, l + ld l, 0 ; uhl=H*C+L*B<<8&0xFFFF + ld e, c ; ude=LC + mlt de ; ude=L*C + add hl, de ; uhl=L*C+(H*C+L*B<<8&0xFFFF) + pop de ; ude=UDE ------ + ret + +; HL*BC&0xFFFF=L*C+(H*C+L*B<<8)+(H*B<<16)&0xFFFF +; =L*C+(H*C+L*B<<8)&0xFFFF diff --git a/src/std/static/sneg.src b/src/std/static/sneg.src new file mode 100644 index 000000000..3d63da803 --- /dev/null +++ b/src/std/static/sneg.src @@ -0,0 +1,7 @@ + assume adl=1 + + section .text + public __sneg +__sneg := __ineg + + extern __ineg diff --git a/src/std/static/snot.src b/src/std/static/snot.src new file mode 100644 index 000000000..f46a13485 --- /dev/null +++ b/src/std/static/snot.src @@ -0,0 +1,7 @@ + assume adl=1 + + section .text + public __snot +__snot := __inot + + extern __inot diff --git a/src/std/static/sor.src b/src/std/static/sor.src new file mode 100644 index 000000000..354125f0d --- /dev/null +++ b/src/std/static/sor.src @@ -0,0 +1,14 @@ + assume adl=1 + + section .text + public __sor +__sor: + push af + ld a, h + or a, b + ld h, a + ld a, l + or a, c + ld l, a + pop af + ret diff --git a/src/std/static/srems.src b/src/std/static/srems.src new file mode 100644 index 000000000..c608922b5 --- /dev/null +++ b/src/std/static/srems.src @@ -0,0 +1,20 @@ + assume adl=1 + + section .text + public __srems +__srems: +; I: HL=dividend, BC=divisor +; O: uhl=HL%BC + + push de + + call __sdvrms_abs + + pop de + ret nc + + jp __ineg + + + extern __ineg + extern __sdvrms_abs diff --git a/src/std/static/sremu.src b/src/std/static/sremu.src new file mode 100644 index 000000000..4da4be230 --- /dev/null +++ b/src/std/static/sremu.src @@ -0,0 +1,17 @@ + assume adl=1 + + section .text + public __sremu +__sremu: +; I: HL=dividend, BC=divisor +; O: uhl=HL%BC + + push de + + call __sdvrmu + + pop de + ret + + + extern __sdvrmu diff --git a/src/std/static/sshl.src b/src/std/static/sshl.src new file mode 100644 index 000000000..4300b4d22 --- /dev/null +++ b/src/std/static/sshl.src @@ -0,0 +1,7 @@ + assume adl=1 + + section .text + public __sshl +__sshl := __ishl + + extern __ishl diff --git a/src/std/static/sshrs.src b/src/std/static/sshrs.src new file mode 100644 index 000000000..cafd166da --- /dev/null +++ b/src/std/static/sshrs.src @@ -0,0 +1,19 @@ + assume adl=1 + + section .text + public __sshrs +__sshrs: +; Suboptimal for large shift amounts +; CC: if C!=0: C*(7*r(PC)+1)+7*r(PC)+(ADL?6*r(SPL)+3*w(SPL):4*r(SPS)+2*w(SPS))+1 +; if C==0: 4*r(PC)+(ADL?3*r(SPL):2*r(SPS))+2 + inc c + dec c + ret z + push bc + ld b, c +.loop: + sra h + rr l + djnz .loop + pop bc + ret diff --git a/src/std/static/sshru.src b/src/std/static/sshru.src new file mode 100644 index 000000000..379e56c8a --- /dev/null +++ b/src/std/static/sshru.src @@ -0,0 +1,19 @@ + assume adl=1 + + section .text + public __sshru +__sshru: +; Suboptimal for large shift amounts +; CC: if C!=0: C*(7*r(PC)+1)+7*r(PC)+(ADL?6*r(SPL)+3*w(SPL):4*r(SPS)+2*w(SPS))+1 +; if C==0: 4*r(PC)+(ADL?3*r(SPL):2*r(SPS))+2 + inc c + dec c + ret z + push bc + ld b, c +.loop: + srl h + rr l + djnz .loop + pop bc + ret diff --git a/src/std/static/sxor.src b/src/std/static/sxor.src new file mode 100644 index 000000000..21a9d4041 --- /dev/null +++ b/src/std/static/sxor.src @@ -0,0 +1,14 @@ + assume adl=1 + + section .text + public __sxor +__sxor: + push af + ld a, h + xor a, b + ld h, a + ld a, l + xor a, c + ld l, a + pop af + ret diff --git a/src/std/static/tolower.src b/src/std/static/tolower.src new file mode 100644 index 000000000..ff8fc5d49 --- /dev/null +++ b/src/std/static/tolower.src @@ -0,0 +1,17 @@ + assume adl=1 + + section .text + public _tolower +_tolower: + pop de + ex (sp), hl + push de + + ld a, l + sub a, 'A' + cp a, 1+'Z'-'A' + ret nc + + add a, 'a' + ld l, a + ret diff --git a/src/std/static/toupper.src b/src/std/static/toupper.src new file mode 100644 index 000000000..ddfba1900 --- /dev/null +++ b/src/std/static/toupper.src @@ -0,0 +1,17 @@ + assume adl=1 + + section .text + public _toupper +_toupper: + pop de + ex (sp), hl + push de + + ld a, l + sub a, 'a' + cp a, 1+'z'-'a' + ret nc + + add a, 'A' + ld l, a + ret diff --git a/src/std/stdlib.h b/src/std/stdlib.h index 5376daffd..a94702f5a 100644 --- a/src/std/stdlib.h +++ b/src/std/stdlib.h @@ -13,6 +13,11 @@ typedef struct { long rem; } ldiv_t; +typedef struct { + long long rem; + long long quot; +} lldiv_t; + typedef char __align; union header { struct { @@ -48,6 +53,8 @@ int atoi(const char *nptr) __attribute__((nonnull(1))); long atol(const char *nptr) __attribute__((nonnull(1))); +long long atoll(const char *nptr) __attribute__((nonnull(1))); + float strtof(const char *__restrict nptr, char **__restrict endptr) __attribute__((nonnull(1))); @@ -57,10 +64,18 @@ double strtod(const char *__restrict nptr, long strtol(const char *__restrict nptr, char **__restrict endptr, int base) __attribute__((nonnull(1))); +long long strtoll(const char *__restrict nptr, + char **__restrict endptr, + int base) __attribute__((nonnull(1))); + unsigned long strtoul(const char *__restrict nptr, char **__restrict endptr, int base) __attribute__((nonnull(1))); +unsigned long long strtoull(const char *__restrict nptr, + char **__restrict endptr, int base) + __attribute__((nonnull(1))); + void srand(unsigned int seed); int rand(void); @@ -87,14 +102,18 @@ void quick_exit(int) __NOEXCEPT __attribute__((noreturn)); void _Exit(int) __NOEXCEPT __attribute__((noreturn)); -int abs(int j); +int abs(int n); + +long labs(long n); -long labs(long j); +long long llabs(long long n); div_t div(int numer, int denom); ldiv_t ldiv(long numer, long denom); +lldiv_t lldiv(long long numer, long long denom); + __END_DECLS #endif /* _STDLIB_H */