Compare commits

...

603 Commits

Author SHA1 Message Date
drmortalwombat 6ed4adb0ed OPtimize signed+unsigned char arithmetic 2025-06-19 21:54:23 +02:00
drmortalwombat f16c24363c Improve pointer compare constant folding 2025-06-19 12:58:40 +02:00
drmortalwombat fd7e68573c Fold CLC into prev block for dual pointer increment 2025-06-19 09:37:03 +02:00
drmortalwombat f1873f0794 Optimize carry flag analysis with indexed tables 2025-06-17 21:51:19 +02:00
drmortalwombat a01d98e584 Propagate closed bool variables to use sign bit instead of zero/one 2025-06-15 18:10:50 +02:00
drmortalwombat c7a53a5be6 Bump version number 2025-06-15 14:27:49 +02:00
drmortalwombat 4633631d7e Fix double condition propagation 2025-06-15 13:56:11 +02:00
drmortalwombat 100608e0ac Fix loop head split for infinite loops 2025-06-14 12:53:55 +02:00
drmortalwombat 35a0b36a0d Make rasterirq handler more resilient for timing glitches 2025-06-11 09:34:21 +02:00
drmortalwombat 5470db3a5f Fix sidfx state machine sequence end 2025-06-10 21:06:28 +02:00
drmortalwombat d6802f3cb9 Make loop head extraction explicit 2025-06-10 17:41:16 +02:00
drmortalwombat 5b4e0c2b55 Sidfx extend gate sprike condition 2025-06-08 18:19:37 +02:00
drmortalwombat 8175fae67a Add complex loop value forwarding, tweak sidfx state machine 2025-06-07 19:35:40 +02:00
drmortalwombat 13c90eb542 Change SIDFX state machine reset 2025-06-06 20:00:38 +02:00
drmortalwombat f98665c577 Fix bool artihmetic assign combos 2025-06-01 18:40:19 +02:00
drmortalwombat 8843f3feba Fix pointer loop reversal counting from one 2025-06-01 11:51:24 +02:00
drmortalwombat 514cf59398 More short loop reversal 2025-05-31 19:44:33 +02:00
drmortalwombat 03c133cd48 Swap shift/add if add fits in byte before but not after 2025-05-30 17:39:40 +02:00
drmortalwombat 880abea32e Shortcut tiny jump detours after placement 2025-05-29 13:38:00 +02:00
drmortalwombat fc9a8f2a89 Merge branch 'main' of https://github.com/drmortalwombat/oscar64 2025-05-28 20:49:00 +02:00
drmortalwombat 40c467d958 Improve copy elision 2025-05-28 20:48:37 +02:00
drmortalwombat 4bde6385b8
Merge pull request #250 from ilmich/fix-compiler-build
prepare output directory also to build only the compiler
2025-05-28 12:55:39 +02:00
drmortalwombat 688ef958e3 Add default move constructor and assignment operators 2025-05-27 20:47:03 +02:00
ilmich 6da7223472 prepare output directory also to build only the compiler 2025-05-27 16:33:36 +02:00
drmortalwombat a1d4bc8375 Improve const initialized simple type usage for local variables 2025-05-27 14:03:04 +02:00
drmortalwombat 197e2a91be Optimize carry propagation 2025-05-25 17:37:52 +02:00
drmortalwombat 4d9d628b67 Add static_assert 2025-05-25 12:31:15 +02:00
drmortalwombat f720feebbf Fix global register forward mixing up x and y in one case 2025-05-25 10:15:47 +02:00
drmortalwombat 6076808f5e Relax interrupt complexity limits for local variables on stack 2025-05-24 20:48:04 +02:00
drmortalwombat 0af17f0f40 Fix constness of reference parameter of standard copy assignment operator 2025-05-24 17:49:51 +02:00
drmortalwombat 81e5321bfc Return short simple structs in accu 2025-05-23 12:02:12 +02:00
drmortalwombat 27d3666285 Fix pass struct rvalue return to rvalue parameter conflicting zero page registers 2025-05-22 15:28:39 +02:00
drmortalwombat c6b794db3a Fix kernal io return values 2025-05-22 08:11:49 +02:00
drmortalwombat 1fa4c39a20 Add more math intrinsics 2025-05-21 16:59:52 +02:00
drmortalwombat 0ba148b6bb Make raster interrupt start more deterministic 2025-05-20 18:26:42 +02:00
drmortalwombat 65540da3f7 Optimize signed long compare 2025-05-20 16:05:09 +02:00
drmortalwombat e660757824 Some low level shift optimizations 2025-05-20 11:09:20 +02:00
drmortalwombat 05a6d16dde Some cascading store optimization 2025-05-19 17:23:28 +02:00
drmortalwombat 79ec9af3f2 Fix signed unsigned char compare to promote to int 2025-05-19 15:31:30 +02:00
drmortalwombat 8f37df448f Optimize constant array parameters 2025-05-19 10:03:45 +02:00
drmortalwombat d710a71ba0 Fix static const member qualification with dot 2025-05-19 08:16:58 +02:00
drmortalwombat 8dd211b662 Fix crash in peephole optimizer on potential oob static const array access 2025-05-18 19:25:47 +02:00
drmortalwombat 398ed22b09 Fix array member packing strategy 2025-05-18 18:41:37 +02:00
drmortalwombat 6f1da4335b Fix continue/break for unrolled loops 2025-05-18 14:04:14 +02:00
drmortalwombat c86dc364b1 Fixed array size template parameter 2025-05-18 11:35:13 +02:00
drmortalwombat 70eb7a5eab Fix assert with negative array offset in local variable of a recursive function 2025-05-18 11:03:04 +02:00
drmortalwombat c1cd2ba57e Fix crash with partial reference of ternary conditional operator 2025-05-18 09:42:37 +02:00
drmortalwombat 00da0ef87d Add CAPACITYCHECK to static_vector 2025-05-17 09:07:33 +02:00
drmortalwombat be9abbf510 Optimize vector copy 2025-05-16 18:20:23 +02:00
drmortalwombat 0b72e6b2f2 Force nop for breakpoint() to avoid elimination if alone in basic block 2025-05-16 17:25:58 +02:00
drmortalwombat 6ea39d7bfa CTT file import 2025-05-15 17:50:59 +02:00
drmortalwombat c0abe031ee Fix enum base type selection with trailing comma 2025-05-15 08:46:57 +02:00
drmortalwombat fe667863b2 Constant folding of absolute pointer difference 2025-05-15 07:58:58 +02:00
drmortalwombat e514e05dc8 Fix crash constant folding uninitialized constants 2025-05-14 20:22:25 +02:00
drmortalwombat d978d0a483 Fix error message location for integer const truncation 2025-05-14 18:25:20 +02:00
drmortalwombat 37cacdafa7 Improve cross compilation unit template matching 2025-05-14 18:18:13 +02:00
drmortalwombat 78e3696663 Improve nullptr check for addresses of placed linker objects 2025-05-14 17:09:12 +02:00
drmortalwombat a0215a4f21 Add fix for template overload with multiple includes 2025-05-14 15:15:24 +02:00
drmortalwombat 2310416c46 Propagate non aliasing initializers to compile time constants 2025-05-13 20:48:12 +02:00
drmortalwombat 52db653ec1 Optimize shift code generation 2025-05-12 20:09:57 +02:00
drmortalwombat 6fe76e478f Add -ii option to change default include path 2025-05-11 18:29:57 +02:00
drmortalwombat ba05ec743d Fix high byte address forwarding 2025-05-11 17:31:01 +02:00
drmortalwombat 05ef25a61e Add optimization -Ox to simplify pointer arithmetic by non page crossing 2025-05-11 12:41:40 +02:00
drmortalwombat b26cc4ede7 Remove assembly debug output 2025-05-10 20:24:30 +02:00
drmortalwombat 8dc5f703e8 Fix copy indirect lea elimination 2025-05-10 20:23:45 +02:00
drmortalwombat c05d7e47f4 Add assign to vector and static_vector 2025-05-10 18:50:13 +02:00
drmortalwombat 9dc8489693 Fix copy struct to value struct param, add vsprintf 2025-05-10 17:49:34 +02:00
drmortalwombat f443c97f70 Fix for default copy constructor on init calls 2025-05-10 13:40:36 +02:00
drmortalwombat 4837ceb73f Fix inline assembler optimzier for JSR returning result in X and Y 2025-05-10 13:13:27 +02:00
drmortalwombat 42299c9406 Improve const to immediate propagation 2025-05-10 10:50:42 +02:00
drmortalwombat 850bbfc31a Fix alignment increment problem 2025-05-10 09:53:31 +02:00
drmortalwombat 1e95f51469 Fix building object directly on call stack 2025-05-10 08:33:02 +02:00
drmortalwombat e525e5d62e Optimize copy of arrays of ints 2025-05-09 16:52:04 +02:00
drmortalwombat 18deb8846d Add full() to static_vector 2025-05-08 17:31:16 +02:00
drmortalwombat 34ce9afeae Fix memory use after free error in vector 2025-05-08 17:26:10 +02:00
drmortalwombat d0411b7d52 Fix more function overloads with const 2025-05-08 15:21:59 +02:00
drmortalwombat 34fda8c9b5 Fix const struct parameter overload matching 2025-05-08 13:50:51 +02:00
drmortalwombat b4a357e44f Add clear to vector and static_vector 2025-05-08 12:30:50 +02:00
drmortalwombat 2b224f262b Fix use of hash character in preprocessor defines 2025-05-08 08:18:57 +02:00
drmortalwombat 3c306e0899 Fix loss of register dependency chain when splitting 16bit adds into basic blocks 2025-05-07 13:13:33 +02:00
drmortalwombat e82ab0c7ca Improve shift carry combine 2025-05-06 18:38:44 +02:00
drmortalwombat 983064c694 Fix removal of reference returns when struct member used 2025-05-06 17:00:36 +02:00
drmortalwombat 9230d95bad Fix copy constructor selection in placement new 2025-05-06 08:53:57 +02:00
drmortalwombat 8b0790588b Fix integer range when combining same instruction on alternate paths 2025-05-05 16:52:17 +02:00
drmortalwombat 0a9c43757a Fix reference to value cast 2025-05-05 11:44:10 +02:00
drmortalwombat fccfe35c4f Fix 16bit const add propagation 2025-05-05 11:17:00 +02:00
drmortalwombat 064fed63f5 Fix operator() call on reference parameter 2025-05-04 16:18:07 +02:00
drmortalwombat f43f471124 Fix internal const cast 2025-05-04 16:00:08 +02:00
drmortalwombat f99abb32e2 Fix cost method selection for pointers to incomplete types 2025-05-04 15:27:28 +02:00
drmortalwombat 18f044e90c Fix crash in profile generation 2025-05-04 13:12:14 +02:00
drmortalwombat 5b961c031c Fix reference return from inlined function into inline parameter 2025-05-04 11:05:15 +02:00
drmortalwombat 500cce511f Fix removal of function reference result if only used as target 2025-05-03 17:22:18 +02:00
drmortalwombat 885d6ff706 Fix crash in complex select statement 2025-05-03 09:41:15 +02:00
drmortalwombat efc182ce27
Merge pull request #238 from polluks/patch-4
Fixed minor typo
2025-05-02 17:43:29 +02:00
drmortalwombat 06ef87fe63
Merge pull request #237 from polluks/patch-5
Fixed minor typo
2025-05-02 17:43:05 +02:00
drmortalwombat f3d8251072
Merge pull request #236 from polluks/patch-6
Fixed minor typo
2025-05-02 17:42:37 +02:00
drmortalwombat 0d5efc90ed
Merge pull request #235 from polluks/patch-7
Fixed minor typo
2025-05-02 17:42:18 +02:00
drmortalwombat 30b8e4e970
Merge pull request #234 from polluks/patch-8
Fixed minor typo
2025-05-02 17:41:52 +02:00
drmortalwombat 3da1ddf5da
Merge pull request #233 from polluks/patch-9
Fixed typo
2025-05-02 17:41:29 +02:00
drmortalwombat bfdd1b85fb
Merge pull request #239 from polluks/patch-3
Fixed minor typo
2025-05-02 17:40:59 +02:00
drmortalwombat 686d468d32
Merge pull request #240 from polluks/patch-2
Fixed minor typo
2025-05-02 17:40:39 +02:00
drmortalwombat 23b15678cd
Merge pull request #232 from polluks/patch-10
Fixed minor typo
2025-05-02 17:40:13 +02:00
Stefan d1054abd90
Fixed minor typo 2025-05-02 16:50:57 +02:00
Stefan d358c8359b
Fixed typo 2025-05-02 16:48:56 +02:00
Stefan 9e9494ebf9
Fixed minor typo 2025-05-02 16:46:27 +02:00
Stefan 015ada7a33
Fixed minor typo 2025-05-02 16:44:44 +02:00
drmortalwombat 12e832ebd3 Fix static constexpr in class context 2025-05-02 16:44:24 +02:00
Stefan e327d2a148
Fixed minor typo 2025-05-02 16:41:42 +02:00
Stefan 366f9686dd
Fixed minor typo 2025-05-02 16:39:17 +02:00
Stefan a2927401bc
Fixed minor typo 2025-05-02 16:36:01 +02:00
Stefan bbb339d641
Fixed minor typo 2025-05-02 16:33:35 +02:00
Stefan 8e76334c20
Fixed minor typo 2025-05-02 16:30:49 +02:00
drmortalwombat 739f1e2161 Improve conditional branch integer range propagation 2025-05-01 20:23:13 +02:00
drmortalwombat 4ee6ca5b94 Improve function automatic template matching 2025-05-01 16:04:10 +02:00
drmortalwombat 347898ea53 fix mixup of stack and fast call in virtual function parameter offsets 2025-05-01 10:21:35 +02:00
drmortalwombat 6caed58be4 Fix new operator broken with placement new fix 2025-04-30 22:38:43 +02:00
drmortalwombat c4185832ba Fix method invocation on rvalue reference 2025-04-30 17:06:28 +02:00
drmortalwombat 2b0994b086 Fix placement new for vector constructor 2025-04-29 20:12:48 +02:00
drmortalwombat f9acbc152d Merge branch 'main' of https://github.com/drmortalwombat/oscar64 2025-04-29 14:26:58 +02:00
drmortalwombat 3eed21567e Fix disabled warning bitset size 2025-04-29 14:26:55 +02:00
drmortalwombat f3370cb149
Merge pull request #226 from CTalkobt/main
Update to reflect mega65 in .md
2025-04-27 14:23:54 +02:00
ctalkobt@ctalkobt.net 494fb97e49 Update to reflect mega65 in .md 2025-04-27 07:38:14 -04:00
drmortalwombat bd8786af0b Improve carry propagation to eliminate sec and clc 2025-04-26 21:25:43 +02:00
drmortalwombat f0a7499814 Ignore nullptr access for volatile data 2025-04-24 15:31:39 +02:00
drmortalwombat da4a90b724 Merge branch 'main' of https://github.com/drmortalwombat/oscar64 2025-04-24 09:05:59 +02:00
drmortalwombat 96a9109915 Add warning pragma, improved token concatenation in preprocessing 2025-04-24 09:05:57 +02:00
drmortalwombat f5a33edcf4
Merge pull request #224 from polluks/patch-1
Changed make target everywhere
2025-04-23 16:58:45 +02:00
Stefan 1bd98bdeb2
Changed make target everywhere
oops
2025-04-23 15:32:26 +02:00
drmortalwombat e4696a6539
Merge pull request #223 from polluks/wildcard
More POSIX, fixed #190
2025-04-23 11:23:21 +02:00
polluks 74350d6133 oops 2025-04-23 10:40:28 +02:00
drmortalwombat cbf86b2e8f
Merge pull request #219 from polluks/patch-3
Changed make target
2025-04-22 08:21:40 +02:00
Stefan cb757dfaf9
Changed make target
https://www.gnu.org/software/make/manual/html_node/Standard-Targets.html
2025-04-21 22:22:40 +02:00
drmortalwombat 5ad94d01d4
Merge pull request #218 from CTalkobt/main
Correct end address for Mega 65
2025-04-21 20:13:40 +02:00
ctalkobt@ctalkobt.net cdba71b353 Correct end address for M65 2025-04-21 13:46:53 -04:00
drmortalwombat 01d187cf83
Merge pull request #217 from CTalkobt/main
Initial patch to add -tm=mega65 support
2025-04-21 18:48:38 +02:00
drmortalwombat ab06ce74c5 More global namespace fixes 2025-04-21 18:29:01 +02:00
Craig Taylor 1e2b227113
Merge branch 'drmortalwombat:main' into main 2025-04-21 11:53:36 -04:00
ctalkobt@ctalkobt.net 9d5dbe67fe Adjust M65 top of memory to $e000 2025-04-21 11:48:12 -04:00
ctalkobt@ctalkobt.net 9a409ca347 Initial patch to add -tm=mega65 support 2025-04-21 11:12:02 -04:00
drmortalwombat 449acece05 Fix global namespace access 2025-04-21 15:58:49 +02:00
drmortalwombat ee3f6fc4a5 Struct value forwarding 2025-04-21 08:18:55 +02:00
drmortalwombat e95b51609c Optimize loop unrolling 2025-04-18 17:16:56 +02:00
drmortalwombat 323589a484 Optimize compilation time 2025-04-18 12:55:10 +02:00
drmortalwombat 33f4b25f28 Fix C64 ascii to petscii output in conio 2025-04-17 22:38:54 +02:00
drmortalwombat 538d965636 Fix 16bit forward for middle 32bit registers 2025-04-17 18:55:53 +02:00
drmortalwombat 4b99110533 Bump version number 2025-04-10 08:47:24 +02:00
drmortalwombat 94f2489083 Fix TAXA range bypass with trailing multi store 2025-04-08 18:22:45 +02:00
drmortalwombat 6de1b1fd96 Code size optimizations 2025-03-31 17:30:57 +02:00
drmortalwombat 80abcdfe95 Optimize local struct variable usage 2025-03-30 20:22:50 +02:00
drmortalwombat 0dc6588a66 Improve double index register single block loops 2025-03-29 13:30:03 +01:00
drmortalwombat 65ad05c608 Merge branch 'main' of https://github.com/drmortalwombat/oscar64 2025-03-24 08:56:07 +01:00
drmortalwombat 2db8890453 Fix temp spilling in recursive functions 2025-03-24 08:56:03 +01:00
drmortalwombat 3f4268328e
Merge pull request #198 from root42/detect-basic-and-gotoxy-for-pet
Implement gotoxy for PET
2025-03-23 14:54:10 +01:00
Arne Schmitz 33cabb487b pure C implementation 2025-03-23 13:15:09 +01:00
Arne Schmitz ab2ca897ce pure asm implementation of bsplot 2025-03-22 12:31:05 +01:00
Arne Schmitz 2c37e150a9 comment 2025-03-22 12:31:05 +01:00
Arne Schmitz ee68f2575a better implementation, inspired by cc65 2025-03-22 12:31:05 +01:00
Arne Schmitz 4f100266c3 fix ldy 2025-03-22 12:31:05 +01:00
Arne Schmitz c22a67f95f basic version detection and and implement bsplot for PET 2025-03-22 12:31:05 +01:00
drmortalwombat e6bc6371c9 Fix PET target zero page variable range 2025-03-19 17:16:20 +01:00
drmortalwombat 2acca6d7b1 Fix register load/store bypass when register result still needed 2025-03-19 09:38:40 +01:00
drmortalwombat fc2095301d Fix aliasing problem when auto inlining non early embedded assembly stubs 2025-03-16 20:29:03 +01:00
drmortalwombat 32f0b8c6f3 Fix warnings in unreachable code 2025-03-16 15:53:27 +01:00
drmortalwombat 10c9b735e9 Fix short infinite loop code split 2025-03-15 21:17:21 +01:00
drmortalwombat fefb511404 Fix integer range loss in loop index reduction 2025-03-15 17:59:45 +01:00
drmortalwombat bedafe7b6f Fix loss of type reduction in loop causing overflow error 2025-03-15 12:05:34 +01:00
drmortalwombat 242d7f1700 Fix optimizer crash with volatile long ops 2025-03-14 08:10:36 +01:00
drmortalwombat 90e892dfa5
Merge pull request #199 from polluks/patch-2
Fixed install
2025-03-12 08:12:34 +01:00
drmortalwombat c98e0751b0 Fix carry usage check in inline assembler, add optional volatile to __asm 2025-03-12 08:11:23 +01:00
Stefan f3b4a4e5fc
Fixed install
Long options are not POSIX.
2025-03-11 23:01:49 +01:00
drmortalwombat 1c7d71cadb Fix loop unrolling changing boundary constant 2025-03-11 08:19:49 +01:00
drmortalwombat 840050738f Fix compare of enum in striped bitfield 2025-03-09 10:49:23 +01:00
drmortalwombat 2ee5cc7bf4 Fix loss of memory live status when reversing compare 2025-03-07 17:23:50 +01:00
drmortalwombat 490180f9dc Fix compare reversal and reuse if z flag used 2025-03-07 08:17:51 +01:00
drmortalwombat 2582f3076d Fix passing rvalue to non const reference 2025-03-02 15:02:01 +01:00
drmortalwombat 0032d42b2c Merge branch 'main' of https://github.com/drmortalwombat/oscar64 2025-02-28 16:20:10 +01:00
drmortalwombat 5c70c20c6e Reverse cross block accu to index propagation 2025-02-28 16:20:07 +01:00
drmortalwombat 71236aa405
Merge pull request #193 from polluks/patch-1
Fixed minor typos
2025-02-25 15:50:15 +01:00
Stefan 31a38e2a62
Fixed minor typos 2025-02-25 13:44:32 +01:00
drmortalwombat ee0e4d5428 Fix void pointer arithmetic 2025-02-23 11:04:29 +01:00
drmortalwombat f6296e83e5 Improve outliner for short loops 2025-02-18 14:51:42 +01:00
drmortalwombat 39840b5fb1 Convert add to compare if only flags needed 2025-02-18 11:35:06 +01:00
drmortalwombat fe0bfccfaa Reduce eagerness to join stores with short leas 2025-02-18 09:22:28 +01:00
drmortalwombat 25ee4e9b2b Shortcut known branch cascades 2025-02-17 13:12:28 +01:00
drmortalwombat 9f7d4c0ab0 Improved index register use in short loops 2025-02-16 17:16:27 +01:00
drmortalwombat 038928232c Propagate conditional stores behind blocks 2025-02-15 10:51:55 +01:00
drmortalwombat 100affa083 Reverse zp register alias move across single block loops 2025-02-14 10:40:00 +01:00
drmortalwombat e27075955d Optimize enums in bitfield usage 2025-02-12 15:12:06 +01:00
drmortalwombat 0959a15b10 Fixed striped structs with bitfields 2025-02-09 22:10:39 +01:00
drmortalwombat 4a87e4d97b Fix no inline for overloaded operators 2025-02-08 11:04:19 +01:00
drmortalwombat 9de7caa68d Fix enums in bitfields 2025-02-05 10:57:58 +01:00
drmortalwombat e23d78eb86 Fix move of store abs cross function call 2025-02-01 20:13:18 +01:00
drmortalwombat d0b45fce78 Merge branch 'main' of https://github.com/drmortalwombat/oscar64 2025-01-31 18:43:07 +01:00
drmortalwombat 0126dd53a3 Fix infinite optimizer loop 2025-01-31 18:43:01 +01:00
drmortalwombat 901c8459ec
Merge pull request #186 from seclorum/main
Created a CMakeLists.txt for the project
2025-01-24 20:09:43 +01:00
Jay Vaughan 746fed6704 Get target_sources through glob'ing instead of explicit filenames 2025-01-24 19:07:18 +01:00
Jay Vaughan 54c0f2a670 Created a CMakeLists.txt for the project - oscar64 can now be built on MacOS/Darwin with cmake 2025-01-24 15:17:31 +01:00
drmortalwombat 28ea8ef24f Fix integer value range for ext8to16 unsigned 2025-01-22 21:40:51 +01:00
drmortalwombat 115129e1dd Reorder lda x, cmp y to reuse y 2025-01-21 22:26:57 +01:00
drmortalwombat f41d594015 Fix load/binop/store with different sizes 2025-01-19 21:26:25 +01:00
drmortalwombat c8abb42c3c Optimize outliner compile time performance 2025-01-19 18:10:02 +01:00
drmortalwombat 95732265f6 Add experimental native code outliner 2025-01-19 17:28:20 +01:00
drmortalwombat 9f834c4232 Fix integer type coercion with cast operator 2025-01-18 10:13:29 +01:00
drmortalwombat d10d8bf7ae Optimize index register use for one bit high byte 2025-01-10 21:09:03 +01:00
drmortalwombat f6a2db7866 Reuse index register transfer to avoid compare 2025-01-09 20:12:09 +01:00
drmortalwombat d2fdbd29f5 Add loop sinking optimization 2025-01-09 10:54:45 +01:00
drmortalwombat f5dff9620b Fix degrading merge of stores that prevent absolute addressing 2025-01-07 22:07:36 +01:00
drmortalwombat 28e75a8fa2 Fix invalid double dereference reorder 2025-01-06 22:05:43 +01:00
drmortalwombat 6170c81af3 Improve 8 to 16 bit signed add 2025-01-06 18:54:21 +01:00
drmortalwombat 3d578170db Improve 16bit op pair reordering 2025-01-06 15:58:41 +01:00
drmortalwombat d99499b6e3 Improve double indexed pointer from table 2025-01-04 11:11:37 +01:00
drmortalwombat 950c434157 Improve const range propagation after byte compare 2025-01-04 09:12:56 +01:00
drmortalwombat d6362a305f Improve const bitmask optimization 2025-01-03 14:29:08 +01:00
drmortalwombat 38bb033328 Fix global variable changes bypassing assembly blocks 2024-12-30 18:06:26 +01:00
drmortalwombat 87f1ddd27f Fix usage of assembler labels as pointer initializer 2024-12-29 10:22:01 +01:00
drmortalwombat 9e994560a7 Improve double indexed loop with fixed stride 2024-12-29 09:46:33 +01:00
drmortalwombat e37de95079 Add bounded integer class 2024-12-26 14:57:23 +01:00
drmortalwombat 8e46ae95ec Improve unsigned compare result propagation 2024-12-24 15:23:02 +01:00
drmortalwombat e7cece0f0f Fix debug assert for negative array index intermediate result 2024-12-23 22:31:04 +01:00
drmortalwombat 890a4b996e Merge branch 'main' of https://github.com/drmortalwombat/oscar64 2024-12-22 21:22:08 +01:00
drmortalwombat 5b2ae228cc Improve table pointer forwarding 2024-12-22 21:22:05 +01:00
drmortalwombat 9fc8315f92
Merge pull request #179 from root42/pet-kbhit
kbhit variant for CBM PET
2024-12-18 12:02:31 +01:00
Arne Schmitz 32935cd7a1 use keyboard buffer instead 2024-12-18 11:59:01 +01:00
Arne Schmitz fd02382d38 kbhit variant for CBM PET 2024-12-18 11:47:26 +01:00
drmortalwombat 4fce263228 Optimize hires line draw 2024-12-15 16:34:53 +01:00
drmortalwombat 50c7e10814 Add forward declaration of __asm code 2024-12-08 12:05:02 +01:00
drmortalwombat 7c8ab991be Bump version number 2024-12-07 13:08:37 +01:00
drmortalwombat 067e169803 Fix analysis of register usage of inline assembler 2024-12-06 18:54:55 +01:00
drmortalwombat ccdbbe799a Fix assert in linux autotest 2024-12-05 08:05:43 +01:00
drmortalwombat fac53cfd54 Add "-strict" command line option, to loosen C syntax and allow default arguments when not set 2024-12-03 09:03:43 +01:00
drmortalwombat cfe2c7bed5 Fix infinite loop in parser due to failure to detect label 2024-12-02 16:27:13 +01:00
drmortalwombat f0b9b5cce4 More C++ aggregate initialization 2024-12-02 15:39:14 +01:00
drmortalwombat 803b868356 Improve zero page addressing of global variables in inline assembler 2024-12-01 15:33:51 +01:00
drmortalwombat 907452d918 Fix rirq_sort when called from within interrupt 2024-11-30 13:01:09 +01:00
drmortalwombat c12bca7b4e Fix crash in optimizer due to lack of updated register dependecy set when splitting block in loop 2024-11-30 09:40:26 +01:00
drmortalwombat e1736c8214 Reverse shift with negated distance 2024-11-21 22:02:25 +01:00
drmortalwombat d3e7a991a4 Fix int to bool coercion 2024-11-19 18:42:07 +01:00
drmortalwombat e7b0d17a83 Add some std library functions 2024-11-19 16:22:09 +01:00
drmortalwombat df18dc273e Forward binary op in txax 2024-11-17 21:54:55 +01:00
drmortalwombat b6341e402d Fix const bool to int conversion in loop 2024-11-16 13:48:47 +01:00
drmortalwombat 3f2f703936 Bump version number 2024-11-14 17:37:07 +01:00
drmortalwombat 4acee4531c Remove needless register transfers from inner loops 2024-11-12 13:37:50 +01:00
drmortalwombat 2a476d3372 Fix const void * type propagation 2024-11-07 10:56:21 +01:00
drmortalwombat 0a41cb044c Relax rules for argument forwarding in direct call chains 2024-11-05 17:20:22 +01:00
drmortalwombat 5a0f736d41 Fix in block branch collides with fcall proxy generation 2024-11-05 08:17:18 +01:00
drmortalwombat 020534dbc8 Bump version number 2024-11-03 17:35:19 +01:00
drmortalwombat cee2801847 Fixed negative offset leas 2024-11-03 15:36:53 +01:00
drmortalwombat 51c38a4723 Fix short lea coalescing with negative offsets 2024-11-03 10:14:18 +01:00
drmortalwombat bb01d1024a Fix striped indirect arrays 2024-11-02 14:52:06 +01:00
drmortalwombat 903a5d9b8b
Update README.md 2024-11-02 11:45:31 +01:00
drmortalwombat e360dea558 Fix link text 2024-11-02 11:40:02 +01:00
drmortalwombat 582443ef5c Split readme and reference 2024-11-02 11:36:30 +01:00
drmortalwombat 80a42216c7 Prepare split of readme and manual 2024-11-02 10:30:11 +01:00
drmortalwombat 6576f4d090
Merge pull request #170 from sehugg/main
Fixed stack-use-after-return bug found with -fsanitize=address,undefined
2024-11-01 22:37:25 +01:00
Steven Hugg 55e983e5a1 Fixed stack-use-after-return bug found with -fsanitize 2024-11-01 15:30:17 -05:00
drmortalwombat a6f9c733a1 Fix drop of reading from volatile with discarding result 2024-11-01 20:32:54 +01:00
drmortalwombat 3c129ff4e5 Fix complex diamond pointer forwarding
Forwarding failed when pointer was used and modified in one branch of the diamond
2024-10-31 22:48:34 +01:00
drmortalwombat db386a5958 Fix multi indirection lea propagation 2024-10-31 07:13:30 +01:00
drmortalwombat 179cc694e3 Reduce code size by recycling nearby jmp for far branches 2024-10-27 16:56:35 +01:00
drmortalwombat 887a51b176 Fix array in struct const declaration without braces 2024-10-26 18:35:29 +02:00
drmortalwombat 5b81379dac Fix const structs in arrays without braces 2024-10-26 17:28:13 +02:00
drmortalwombat 4fff9f7060 Add optional static memory profile output file 2024-10-24 13:58:14 +02:00
drmortalwombat 40c407782d Fix uppercase flag in iostream 2024-10-24 07:21:39 +02:00
drmortalwombat 5946f17632 Detangle XY abs load/store pairs 2024-10-22 17:17:29 +02:00
drmortalwombat 7e0ff7449c Fix address/register mismatch in 16bit sum forwarding 2024-10-22 13:21:16 +02:00
drmortalwombat d597219aea Fix loss of memory live status when shortcuting zp shift add 2024-10-21 21:36:18 +02:00
drmortalwombat a311396cf8 Loop optimization for x and y used in simple loop 2024-10-20 18:09:50 +02:00
drmortalwombat 94607cab7f Fix extern const struct merging 2024-10-20 11:11:43 +02:00
drmortalwombat 4d193a30b0 Fix cia init code 2024-10-19 09:19:07 +02:00
drmortalwombat c1ad265f47 Fix memory type propagation in loop strength reduction 2024-10-18 15:24:08 +02:00
drmortalwombat 4e2a2c99ba Fix x reg zp dependency during peephole shuffle 2024-10-17 18:12:08 +02:00
drmortalwombat ea33f253d4 Reduce branches in short basic block sequences 2024-10-15 07:37:35 +02:00
drmortalwombat ebc41560d9 Fix value forwarding register forgetting memory reference 2024-10-13 19:52:52 +02:00
drmortalwombat 2d2c696aa4 Add sprite pad tile import 2024-10-10 16:12:35 +02:00
drmortalwombat b622c25a56 FIx previous case for TYA as well 2024-10-06 22:31:22 +02:00
drmortalwombat 439cf499ed Fix peephole opt for while (x--) 2024-10-06 22:17:29 +02:00
drmortalwombat cd5f1daaba Fixing O3 cases for gcc tests 2024-10-06 16:44:22 +02:00
drmortalwombat ec95f6dc98 Fix dynamic variable initalizer 2024-10-06 13:59:06 +02:00
drmortalwombat 66dfe5df46 Fixed constant array bounds check regression 2024-10-06 12:47:53 +02:00
drmortalwombat 9117827cfc Bump version number 2024-10-05 21:57:23 +02:00
drmortalwombat ad115701d5 Fix sprite pad level 3 read 2024-10-05 21:39:51 +02:00
drmortalwombat a15125d6af Fix crash with const access to zero size array 2024-10-05 14:01:58 +02:00
drmortalwombat dadd8eb41c Extend number of usable variables in assembler block to 32 2024-10-05 13:42:39 +02:00
drmortalwombat 056b49e1d1 Optimize 8 by 16 bit multiply 2024-10-04 20:06:56 +02:00
drmortalwombat 1f492e7820 Improve size optimization 2024-10-03 20:57:01 +02:00
drmortalwombat 4c687dfa54 Improve struct value return propagation 2024-10-03 12:53:11 +02:00
drmortalwombat e1f5bdf48b Add named variadic macro arguments 2024-10-03 10:29:42 +02:00
drmortalwombat 3ba7e0a8a4 Bump Version Number 2024-10-02 21:58:35 +02:00
drmortalwombat a71fae5bb1 Add template based bank switch proxy code 2024-10-02 20:10:47 +02:00
drmortalwombat f6c78d57ef Add __forceinline storage specifier 2024-10-02 18:27:20 +02:00
drmortalwombat 6af50f5eae Add early dead code elimination to speed up template compilation 2024-10-01 18:30:07 +02:00
drmortalwombat 62ab925e01 Add raster IRQ handler for cartridge with ROM switching 2024-10-01 09:45:41 +02:00
drmortalwombat 5126ba482e Fixed placement of static class members 2024-09-30 20:41:33 +02:00
drmortalwombat fb477b33f7 Don't use floats as num counter replacement 2024-09-30 20:33:08 +02:00
drmortalwombat 756fe9354a Merge branch 'main' of https://github.com/drmortalwombat/oscar64 2024-09-30 20:14:02 +02:00
drmortalwombat 73c2206a1a Improve bankof implementation 2024-09-30 20:13:54 +02:00
drmortalwombat c1071ecd3c
Merge pull request #155 from jadziamd/main
Standardise Implementation of get_s C function
2024-09-30 20:13:22 +02:00
John Schneiderman 534ddc3a4c Removes the include for STD bool since it's no longer used. 2024-09-30 20:07:44 +02:00
John Schneiderman ebce50320f Fixes incorrect specification implementation not reading all the
characters.
Simplfies the buffer size checks.
2024-09-30 20:04:33 +02:00
John Schneiderman cfd2e5142a Changes from being mostly assembly to be based upon a C version.
Adds the additional error conditions for get_s: truncation
	and too small buffer.
2024-09-30 19:32:23 +02:00
drmortalwombat 581137ade7 Fix template void return of reference parameter 2024-09-30 16:54:50 +02:00
drmortalwombat c3b46d6a78 Fix condition hoisting side path check 2024-09-30 13:31:31 +02:00
drmortalwombat 84a8bf22e8 Constant folding of pointer type cast 2024-09-29 17:24:42 +02:00
drmortalwombat daeb3ddfdd Add non constant structured initializers 2024-09-29 14:31:05 +02:00
drmortalwombat bf5f5a807c Reduce inline assembly in stdio and conio 2024-09-28 12:25:44 +02:00
drmortalwombat 3dfba389ff Fix command line parsing for -O and -O1 2024-09-28 11:15:49 +02:00
drmortalwombat a4f1341587 bump version number 2024-09-27 20:14:10 +02:00
drmortalwombat 57d8747cb7 Reduce generated code size with -Os 2024-09-27 20:01:22 +02:00
drmortalwombat 1fb68c1bf3 Add -rpt option to generate error map and asm files if linker fails 2024-09-26 20:32:20 +02:00
drmortalwombat 5613a719c5 Fix linux make dependencies 2024-09-26 17:56:55 +02:00
drmortalwombat bf6343616b Fix XY detangling in loop 2024-09-26 14:03:42 +02:00
drmortalwombat 861eeaefe2 Improve signed integer compare 2024-09-26 12:39:38 +02:00
drmortalwombat db3c6a3135 Peephole optimizations 2024-09-26 09:15:09 +02:00
drmortalwombat 4c7dafed25 Bump version number 2024-09-24 11:36:36 +02:00
drmortalwombat b1440a9b3f Fix zero page parameter aliasing 2024-09-23 21:27:27 +02:00
drmortalwombat 21b5e75ddb Improve redundant loop counter removal 2024-09-23 17:53:12 +02:00
drmortalwombat 49893f6976 Fix various gcc torture tests 2024-09-22 21:40:27 +02:00
drmortalwombat c87887cbd1 Fix drop of Y register in asm code 2024-09-22 13:46:29 +02:00
drmortalwombat bcd118a8b3 Fix temporary object structured initialization 2024-09-21 23:02:59 +02:00
drmortalwombat d7bfd0a668 Fix invalid function parameter crossing 2024-09-21 22:00:54 +02:00
drmortalwombat aeceb36e2a Fix reverse 8bit unsigned range 2024-09-21 20:48:38 +02:00
drmortalwombat f67d537c7c Add abort to stddef calling exit(-1) 2024-09-21 18:12:10 +02:00
drmortalwombat 87d2163f2d Fix constant int value function return type coercion 2024-09-21 17:00:34 +02:00
drmortalwombat 639008b990 Fix direction of constant folded ordered bool comparison 2024-09-21 16:48:22 +02:00
drmortalwombat 3c21ecb1d3 Fix constant float and long conversion during data flow analysis 2024-09-21 16:24:24 +02:00
drmortalwombat f764cf1936 Avoid infinite recursion when coercing to base class reference 2024-09-21 15:36:05 +02:00
drmortalwombat 44a9aaf89b Fix range correction for post dec loop counters 2024-09-21 15:17:15 +02:00
drmortalwombat 925ee9d8f3 Fix constant pointer if conditions 2024-09-21 14:38:35 +02:00
drmortalwombat a04b09c737 Fix wrong loop invariant when result temp used before 2024-09-21 13:50:14 +02:00
drmortalwombat 2c9fd0e1a6 Fix immediate coalescing with zero flag loss 2024-09-21 13:06:06 +02:00
drmortalwombat d7c9f15593 Fix constant fold of byte right shift 2024-09-21 12:49:29 +02:00
drmortalwombat b61aa37f71 Disable const parameter optimization in variadic functions 2024-09-21 12:13:19 +02:00
drmortalwombat e80f9812ef Fix invalid destruct on shortcut evaluation 2024-09-20 19:22:12 +02:00
drmortalwombat 84a0a9660f Fix constructor call on declaration 2024-09-20 18:10:01 +02:00
drmortalwombat a93b495ac5 Fix param value range on store with index 2024-09-20 16:15:02 +02:00
drmortalwombat 5d7dcf9373 Fix crash on select statement with void result 2024-09-20 13:26:59 +02:00
drmortalwombat 2f5faaa5ab Fix compare value range of longs 2024-09-20 12:34:01 +02:00
drmortalwombat dfe233a95e Fix pointer to object size propagation 2024-09-19 21:55:24 +02:00
drmortalwombat 92b72b19ec Fix loop wrap around aliasing 2024-09-19 21:01:24 +02:00
drmortalwombat ff4a0802ea Fix invalid memory range requirements due to select statement 2024-09-19 20:05:19 +02:00
drmortalwombat 9adcbd2706 Avoid inline of functions with missing return statement 2024-09-19 18:02:01 +02:00
drmortalwombat 6981b28a64 Fixed assignment of numeric 0 to pointer after inline expansion 2024-09-19 14:24:56 +02:00
drmortalwombat 7f41936df0 Fix constant pointer difference 2024-09-19 14:10:23 +02:00
drmortalwombat ccf72c6b77 Fix returning numeric 0 as nullptr 2024-09-19 13:46:34 +02:00
drmortalwombat c508d94d7c Fix loop exit value of loop counter derived values 2024-09-19 11:27:30 +02:00
drmortalwombat ce710fca5d Add float long conversion 2024-09-19 09:49:16 +02:00
drmortalwombat ce0ac30280 Fix value propagation in loop dependency analysis 2024-09-19 08:12:04 +02:00
drmortalwombat dec7580d8d Revert address of array type to pointer to array
not realy sure why I changed it in the first place
2024-09-19 07:47:34 +02:00
drmortalwombat 40001164d4 Fix missing error in const function return 2024-09-18 22:33:40 +02:00
drmortalwombat 8bd5ec76c3 Fix optimizing loop with subtract negative constant on counter 2024-09-18 18:30:53 +02:00
drmortalwombat 534a42d2fe Implement C vs C++ void pointer semantics 2024-09-18 16:27:16 +02:00
drmortalwombat 226d8afc24 Fix type handling in pointer const folding 2024-09-18 14:47:09 +02:00
drmortalwombat 47531ac5e8 Fix flat initializer for stacked arrays 2024-09-18 14:14:11 +02:00
drmortalwombat b3be121f41 Fix constant fold mixed signed long 2024-09-17 20:53:13 +02:00
drmortalwombat e7e53580ea Add ul / lu suffix for numbers 2024-09-17 20:30:41 +02:00
drmortalwombat 8a1eeee22d Fix arrow dereferencing of array variables 2024-09-17 15:34:41 +02:00
drmortalwombat 3e78933e9c Fix negative range propabation on binary or 2024-09-17 15:19:01 +02:00
drmortalwombat 637a10b234 Fix float const propagation 2024-09-17 14:49:07 +02:00
drmortalwombat c5dff3caf3 Fix sizeof string literals with zero byte 2024-09-17 14:27:23 +02:00
drmortalwombat c529fc2b59 Fix lvalue in switch expression 2024-09-17 09:31:01 +02:00
drmortalwombat 4886d0194f Fix bit field member naming and placement 2024-09-17 09:19:16 +02:00
drmortalwombat aae7d81cc6 Fix bitfield delcaration in function local struct 2024-09-16 22:30:19 +02:00
drmortalwombat 8d18969940 Fix unsigned division constant folding 2024-09-16 18:05:03 +02:00
drmortalwombat 68b57bb9a8 Fix short param forwarding of struct elements 2024-09-16 17:45:32 +02:00
drmortalwombat 5aeec2fad4 Fix function pointer const propagation 2024-09-16 17:16:45 +02:00
drmortalwombat 73dece7b58 Fix crash with unnamed unions 2024-09-16 16:45:51 +02:00
drmortalwombat bfa1254eb7 Fix octal string escaped 2024-09-16 16:36:06 +02:00
drmortalwombat e89aa11e86 Implement parse of octal numbers 2024-09-16 13:31:03 +02:00
drmortalwombat 4423837888 fixed varadic function inlining 2024-09-15 20:18:33 +02:00
drmortalwombat 723f407757 FIx unary not for unsigned const long 2024-09-15 19:54:00 +02:00
drmortalwombat f2338f1d13 Allow "long unsigned" type 2024-09-15 18:38:53 +02:00
drmortalwombat 235cbbc227 Add list expressions in for statement 2024-09-15 18:31:10 +02:00
drmortalwombat a2ca0de809 Fix compare pointer to rvalue refs 2024-09-15 16:14:44 +02:00
drmortalwombat f7b00eff95 Fix object array member init regression 2024-09-15 13:00:33 +02:00
drmortalwombat 163354b33e
Merge pull request #94 from jadziamd/main
Adds Diagnostic Directives & Fixes comparison between different enumeration types
2024-09-15 12:16:24 +02:00
drmortalwombat 7efd512ee9 Fix class member array initialization 2024-09-15 12:13:28 +02:00
John Schneiderman 7b7fe6c5a9 Adds the warning diagnositc directive. 2024-09-15 10:49:33 +02:00
John Schneiderman 7abd615a18 Adds support for the error diagnostic directive. 2024-09-15 10:28:25 +02:00
John Schneiderman 14e5896e37 Fixes comparison between different enumeration types. 2024-09-15 08:53:38 +02:00
drmortalwombat 381aaa1509 Fix compiler crash with empty switch statement 2024-09-11 13:13:40 +02:00
drmortalwombat f0f174e439 Optimize conditional select of const values 2024-09-10 22:26:34 +02:00
drmortalwombat 1f9226255a Fix default member constructor for single sized member arrays 2024-09-04 12:17:58 +02:00
drmortalwombat dcfa50e36e Fix float fast parameter aliasing 2024-09-02 22:01:50 +02:00
drmortalwombat 0b2c36ab1a Fix for sidfx in tight loop
Change might have been disregarded due to missing volatile
2024-09-02 15:26:05 +02:00
drmortalwombat 0163fb729a
Merge pull request #86 from polluks/patch-1
Shorter build call
2024-09-02 13:03:42 +02:00
Stefan d6c4828bef
Shorter build call 2024-09-02 11:05:00 +02:00
drmortalwombat e7dbd39adf Fix macos build 2024-09-01 09:51:11 +02:00
drmortalwombat 759a701df8 Add kernal banking for plus/4 kernalio.c 2024-08-30 18:40:48 +02:00
drmortalwombat 17ec90cfe7 Bump version number 2024-08-29 14:36:08 +02:00
drmortalwombat e7ec859dfc Fix unused parameter optimization for deep call stacks 2024-08-29 14:18:01 +02:00
drmortalwombat da93410468 Fix cascaded type casts 2024-08-29 13:34:55 +02:00
drmortalwombat f38b366d81 Fix error message for undefined identifier in case statement 2024-08-27 08:05:28 +02:00
drmortalwombat 8fbe96b9ac Add options to disable BSS clear on startup 2024-08-23 20:31:17 +02:00
drmortalwombat b48b8b836d Extended line limit to 32k 2024-08-23 18:16:42 +02:00
drmortalwombat 967b315be5 Add qualified constructor invocation 2024-08-23 17:53:58 +02:00
drmortalwombat ca995bf342 Fix zero delimiter on opp::string for fixed range string constructor 2024-08-21 19:28:40 +02:00
drmortalwombat c58bb46e7e Fix invalid abs,y to abs,x propagation 2024-08-18 13:26:35 +02:00
drmortalwombat 122dc12d40 Eliminate stores to unused function arguments 2024-08-17 20:55:00 +02:00
drmortalwombat cc576bd640 Fix name space pollution in __asm sections 2024-08-17 17:03:57 +02:00
drmortalwombat 09641d16f5 Add PLx and PHx to non simple asm instructions 2024-08-17 16:08:36 +02:00
drmortalwombat 552c4945bf Fix template expansion of out of class constructor/destructor 2024-08-16 18:03:32 +02:00
drmortalwombat 34d6131471 Fix __asm example in readme 2024-08-15 17:00:57 +02:00
drmortalwombat 9ecf1546cc Fix invalid "ldx abs,x" code generation when propagating 16bit values in merge tree 2024-08-14 22:53:14 +02:00
drmortalwombat 7ffa623d92 Fix clrscr() for VIC20 2024-08-13 19:16:19 +02:00
drmortalwombat 8e81e6aad5
Merge pull request #82 from polluks/main
Fixed sh #81
2024-08-12 14:55:02 +02:00
Stefan 3a3a76a2e1
Update makefile 2024-08-12 14:23:40 +02:00
drmortalwombat 4027b2dbe0 Add optional define for basic upstart line 2024-08-11 14:54:50 +02:00
drmortalwombat 62cede95ce Optimize right shift with small 16 bit values 2024-08-11 14:11:07 +02:00
drmortalwombat abb2d7a417
Merge pull request #79 from jadziamd/main
Support Installed Oscar64 Usage
2024-08-11 14:03:59 +02:00
John Schneiderman f9afb3edb7 Fixes being unable to use the compiler when
installed in the system.
2024-08-11 13:41:55 +02:00
John Schneiderman 32c090880b Adds the definition files as they're needed when
building code outside the repository.
2024-08-11 13:28:59 +02:00
drmortalwombat be5626adc9
Merge pull request #78 from jadziamd/main
Adds the ability to build from the top-level directory.
2024-08-11 10:18:23 +02:00
John Schneiderman b1c68d04dd Adds the ability to build from the top-level directory. 2024-08-11 09:59:53 +02:00
drmortalwombat f9b7dd8418 Fix breakpoint to tail jmp conversion 2024-08-09 20:14:45 +02:00
drmortalwombat 8a6e3eb924 Add breakpoint intrinsic in oscar.h 2024-08-09 18:05:44 +02:00
drmortalwombat 932c7ec222 Fix static stack in recursion
Fix static stack allocation and placement for non recursive sub trees in a recursive call tree
2024-08-09 16:18:38 +02:00
drmortalwombat e4e997fef2 Fix gcc build autotest 2024-08-08 22:47:18 +02:00
drmortalwombat 3ec8a7bc06
Merge pull request #74 from jadziamd/main
Change to a packagable makefile
2024-08-08 22:08:20 +02:00
drmortalwombat d98c4b760f Optimize sprite multiplexer 2024-08-08 22:07:44 +02:00
John Schneiderman d67980d79f Updates the instructions on how to build. 2024-08-08 20:34:19 +02:00
John Schneiderman 092592a05b Adds an installation target.
Adds an uninstallation target.
2024-08-08 20:16:11 +02:00
John Schneiderman 586fab6b6b Changes to use a top-level variable for the Oscar compiler uses. 2024-08-07 21:24:40 +02:00
John Schneiderman eab2a490f4 Adds the tests to the all target.
Silences the cleaning targets.
2024-08-07 20:39:05 +02:00
John Schneiderman 95992df67d Adds the samples building to the all target. 2024-08-07 20:14:56 +02:00
John Schneiderman 89ba57e18d Adds disclean and prep targets for building. 2024-08-07 19:43:27 +02:00
drmortalwombat 6f069946ba Pointer arguments in constexpr evaluation 2024-08-05 18:19:54 +02:00
drmortalwombat 3df85b09fc Align heap allocation on four byte boundaries 2024-08-04 18:02:04 +02:00
John Schneiderman fb5b69ae5c Changes to use commands from variables. 2024-08-04 17:32:13 +02:00
John Schneiderman 7350b11001 Changes to compile all the files in the build directory. 2024-08-04 17:08:19 +02:00
John Schneiderman b7d7614471 Determines the directory lcoation of the project. 2024-08-04 16:47:25 +02:00
drmortalwombat f49027b2d7 Fix loss of carry when moving shift up to store 2024-08-04 11:53:26 +02:00
drmortalwombat d24e666f92 Fix left shift 1ul for upper 16 bits 2024-08-03 19:18:17 +02:00
drmortalwombat 2ba46283b2 Optimize line draw for vertical/horizontal lines 2024-08-02 19:56:38 +02:00
drmortalwombat 65b9c58504 Move zero page shift up to previous store 2024-08-01 22:19:16 +02:00
drmortalwombat 02a2874a19 Bump version number 2024-08-01 15:49:51 +02:00
drmortalwombat 60868c71d3 Fix single tail loop opt for search loops (e.g. strlen) 2024-07-31 21:11:13 +02:00
drmortalwombat 9013952431 Fix missing int range adaption on complex address optimization 2024-07-31 17:59:20 +02:00
drmortalwombat 0b8304b40d More cross block const pointer forwarding 2024-07-28 17:52:07 +02:00
drmortalwombat 1bc5a2ad7e Add compile time error for undefined labels 2024-07-28 14:41:29 +02:00
drmortalwombat 5bb8ca0b89 Improve fix point arithmetic 2024-07-28 14:41:17 +02:00
drmortalwombat 7ecd6adb20 Improve global address in register reuse 2024-07-24 15:31:23 +02:00
drmortalwombat 5b50389340 Optimize 32bit shifts 2024-07-21 21:43:59 +02:00
drmortalwombat 5f2e05d1dd Fix some partial value forwarding errors 2024-07-21 17:53:52 +02:00
drmortalwombat 3cc37acaa4 Bump version number 2024-07-21 11:47:37 +02:00
drmortalwombat 4680ee32f0 Allow defines for #embed arguments 2024-07-21 11:12:34 +02:00
drmortalwombat 3dd23ec789 Additional register allocation step after late inlining 2024-07-21 10:40:37 +02:00
drmortalwombat efd688320f Improve peephole optimizer for shifts 2024-07-18 14:18:06 +02:00
drmortalwombat d0fb062006 Make log and exp intrinsics for const evaluation 2024-07-17 12:42:15 +02:00
drmortalwombat c229a27992 Improve cross loop value propagation 2024-07-16 08:36:52 +02:00
drmortalwombat d3536a718e Merge partially common register loads across basic blocks 2024-07-13 20:44:49 +02:00
drmortalwombat 5909db71d5 Fix loss of dependency when propagating (zp),y single use load across basic blocks 2024-07-12 21:02:46 +02:00
drmortalwombat 96ada6e22a Optimize int->long conversion for known positive values 2024-07-11 16:32:11 +02:00
drmortalwombat 85f01b833c Fix invalid index propagation 2024-07-10 18:49:10 +02:00
drmortalwombat 68a648440a Fix crash on short lea optimization due to lost temp dependencies 2024-07-10 18:31:32 +02:00
drmortalwombat a3bf7296bb Reduce index register usage, where ORA Imm would suffice 2024-07-09 11:24:02 +02:00
drmortalwombat dd1f5b9043 Fix literal string concatenation in parser 2024-07-07 21:18:17 +02:00
drmortalwombat fcc2cbbebe Remove superfluous CPX/CPY with #0 2024-07-06 15:08:03 +02:00
drmortalwombat 470462fe8b Optimize consecutive increments 2024-07-05 22:59:16 +02:00
drmortalwombat 301431f12a Eliminate duplicate loop counting variables 2024-07-05 10:12:55 +02:00
drmortalwombat c0e524cd82 Bump version number 2024-07-04 11:01:58 +02:00
drmortalwombat 4068957442 Fix register dependency update in multi block loop optimization 2024-07-04 10:42:22 +02:00
drmortalwombat bf89d7af33 Improve loop register allocation 2024-07-03 22:23:27 +02:00
drmortalwombat d070e32b4d Loop unrolling for pointer limited short loops 2024-06-30 21:54:56 +02:00
drmortalwombat ad310f8484 Fix sign flag propagationa after immediate ora 2024-06-30 21:28:35 +02:00
drmortalwombat 7eb149a71b Optimize value range of right shifts 2024-06-30 15:45:34 +02:00
drmortalwombat 1c0db235a8 Fix emulator cycle count 2024-06-30 12:29:41 +02:00
drmortalwombat 94181326ca Add uppercase -D for define without separate argument 2024-06-28 16:00:48 +02:00
drmortalwombat cd7567452a Fix return of reference of simple type from inlined function into non ref argument 2024-06-27 19:34:57 +02:00
drmortalwombat 2fec9f066f Refactor large peephole optimizer loop 2024-06-27 15:28:21 +02:00
drmortalwombat fe736289e6 Fix goto to label connection in inlined functions 2024-06-25 21:56:36 +02:00
drmortalwombat 715f295f5e Add goto and labels in C code 2024-06-25 20:45:44 +02:00
drmortalwombat a71c433fc4 Add -D for gcc compliant defines 2024-06-24 18:14:07 +02:00
drmortalwombat 9678814654 Fix crash with extern object pointer arithmetic 2024-06-23 17:05:46 +02:00
drmortalwombat 1598360b65 Fix relational bool ops constant folding 2024-06-22 15:41:02 +02:00
drmortalwombat 9d890228bf
Merge pull request #68 from Kopromaster/main
Windows: support of GCC (MinGW)
2024-06-22 13:56:57 +02:00
Test User 2d82727565 Fixed spacing 2024-06-21 23:17:09 +02:00
Kopromaster 3851a4c2db
Merge branch 'drmortalwombat:main' into main 2024-06-21 21:08:24 +00:00
Test User 17f56d0a69 Bugfix for GCC: order of objects and libs matters; prepared list of libs for GCC (MinGW) 2024-06-21 23:00:17 +02:00
drmortalwombat 1a6a98e57e Reduce stack usage when compiled with MSVC due to optimizer function size limit 2024-06-21 12:04:39 +02:00
Test User 5ddfc628dc Bugfix: __try and __except are MSVC specific 2024-06-20 23:01:46 +02:00
drmortalwombat bf5099f57b Improve auto inline heuristics 2024-06-20 21:02:55 +02:00
drmortalwombat d4a381f71c Fix size heuristic of loop condition slicing 2024-06-20 09:42:22 +02:00
drmortalwombat 17002e4c78 More native code load/store forwarding 2024-06-19 21:40:38 +02:00
drmortalwombat cf9a006005 Retain Z flag when restoring Y after index reduction 2024-06-19 17:45:20 +02:00
drmortalwombat 1fa9828f6a Add additiona raster irq for kernal with potential no IO 2024-06-18 20:35:38 +02:00
drmortalwombat 3f9d042863 Optimize xy before loop index register assignment 2024-06-18 16:08:53 +02:00
drmortalwombat 277afd156d Fix over eager const pointer forwarding 2024-06-16 09:01:36 +02:00
drmortalwombat b428b608b5 Fix extern undefined struct in header file 2024-06-15 17:24:04 +02:00
drmortalwombat 58361e39b8 Fix crash on late const typecast to pointer 2024-06-15 13:35:17 +02:00
drmortalwombat 3770a05aee Add fast loader library flossiec 2024-06-13 21:16:42 +02:00
drmortalwombat 5993f75c92 Bump version number 2024-06-12 21:30:16 +02:00
drmortalwombat d7a2b98b4d Add buffered lzo decompress 2024-06-12 21:07:58 +02:00
drmortalwombat 02b28096af fix pragma optimize inline 2024-06-12 07:36:30 +02:00
drmortalwombat 02e921364b Add support for charpad 9 format 2024-06-11 22:26:10 +02:00
drmortalwombat 4cf64ee170 Fix loop inversion invariant integer range recovery 2024-06-11 21:01:20 +02:00
drmortalwombat c99c1756a9 Fix parameter address reference in __asm embedding 2024-06-11 13:07:50 +02:00
drmortalwombat 5ccfab0342 Fix IEC code for non interrupt usage 2024-06-11 12:12:29 +02:00
drmortalwombat 42eea7f8f4 Mark krnio_save as noinline to ensure zpage params 2024-06-10 22:36:07 +02:00
drmortalwombat ff6bb8ccd5 Fix type of addressof reference 2024-06-08 16:48:44 +02:00
drmortalwombat 2e3aea9d96 Fix reference parameter capture 2024-06-08 16:43:33 +02:00
drmortalwombat 4954a285e7 Add interleave option for sectors in disk image 2024-06-05 22:21:21 +02:00
drmortalwombat 46b52a57f7 Add binary not operator to inline assembler operand parsing 2024-06-04 09:07:50 +02:00
drmortalwombat 41ba2e73f2 Fix labels in inline assembler with an offset > 255 2024-06-03 13:06:45 +02:00
drmortalwombat fbc9607e17 Ensure actual update of index variable in loops in non debug builds 2024-05-30 17:51:59 +02:00
drmortalwombat 2e696d9e1a Optimize small inline function calls 2024-05-30 17:51:34 +02:00
drmortalwombat b09e9a2434 Delete oscar64.zip 2024-05-28 10:11:39 +02:00
drmortalwombat 2e1c020db4 Bump version number 2024-05-26 08:43:14 +02:00
drmortalwombat 13629c70d4 Fix auto deduction of void return type 2024-05-25 22:25:59 +02:00
drmortalwombat b1b5ee737b Fix functional for no parameters 2024-05-25 22:05:31 +02:00
drmortalwombat 884fe50dd7 Add missing assigns for opp::function 2024-05-25 21:26:23 +02:00
drmortalwombat af38f64a99 Add opp::function 2024-05-25 21:25:02 +02:00
drmortalwombat a22dfa6ba7 Add pure virtual functions 2024-05-23 21:15:47 +02:00
drmortalwombat 9fa8b644a7 Add object placement retry if page locking does not fit 2024-05-23 09:54:07 +02:00
drmortalwombat 375307822e Fix auto template expansion of class constructor 2024-05-22 22:44:53 +02:00
drmortalwombat c0152b1ce4 fix template deduction for member functions 2024-05-22 20:53:23 +02:00
drmortalwombat 3460c06508 Improve strength reduction in loops 2024-05-22 20:36:22 +02:00
drmortalwombat d3734a66e0 Fix complex loop intercode index reversal 2024-05-22 12:16:30 +02:00
drmortalwombat ccf13c78f0 Fix index register conflict when removing condition check after load 2024-05-21 22:03:51 +02:00
drmortalwombat 2c28551ca3 Improve index register cross block handling 2024-05-20 16:24:28 +02:00
drmortalwombat 4fb35a7af2 Add error when exceeding assembler limits 2024-05-20 09:03:41 +02:00
drmortalwombat a2a22476ed Add constexpr pointers for inline assembler 2024-05-19 22:20:52 +02:00
drmortalwombat 1b22a5e3c5 Fix constant fold error 2024-05-19 21:38:19 +02:00
drmortalwombat ab06d85a91 Add global inline assembler optimization for static const to immediate propagation 2024-05-19 20:48:14 +02:00
drmortalwombat 80b1683fa2 Document member offset in inline assembler 2024-05-19 19:14:01 +02:00
drmortalwombat d79aae3078 Fix inline mapper for inline assembler 2024-05-19 19:11:48 +02:00
drmortalwombat 4c0e737508 Fix over eager pre processor tokenizer 2024-05-19 17:16:14 +02:00
drmortalwombat 86e0cbf9c2 Alternate forward and backward int value range check 2024-05-19 10:19:42 +02:00
drmortalwombat 142bc988b1 Bump version number 2024-05-17 13:12:24 +02:00
drmortalwombat 3ea44d1979 Fix usage of "ldx abs,x" in some corner cases 2024-05-16 17:45:36 +02:00
drmortalwombat 04d1abd803 Some peephole loop optimizations 2024-05-12 21:06:50 +02:00
drmortalwombat ba1bc29b1a Fix X vz Z flag swapping 2024-05-05 20:54:21 +02:00
drmortalwombat 37776dfaee Remove more conditional branches from loops 2024-05-05 13:14:23 +02:00
drmortalwombat c28f342f3e Remove some superflous range violation warnings 2024-05-03 14:54:58 +02:00
drmortalwombat 354a420aa4 Bump version number 2024-05-01 15:49:17 +02:00
drmortalwombat fb72e8baf8 Fix over eager parameter reordering 2024-05-01 15:30:18 +02:00
drmortalwombat 976703f713 Fix O2 parameter forwarding optimization 2024-05-01 14:08:42 +02:00
drmortalwombat dc5afa6e79 Fix shift optimization had wrong address check 2024-04-30 08:51:22 +02:00
drmortalwombat 740762d4a1 Fix loss of zero flag in 16bit optimization 2024-04-30 08:06:20 +02:00
drmortalwombat f0b7cddeb1 Optimize indirecte 16bit store by flipping low/high order 2024-04-28 21:13:41 +02:00
drmortalwombat 9b47a34840 Improve reordering of function arguments 2024-04-28 20:15:17 +02:00
drmortalwombat bb8c31bf32 Some peephole optimization 2024-04-23 20:54:48 +02:00
drmortalwombat 87ca43e5b7 Add spritepad version 1 file parsing 2024-04-23 17:51:42 +02:00
drmortalwombat 411648b130 Improve long counting loops 2024-04-22 22:48:15 +02:00
drmortalwombat 611f672b81 Add warning for static buffer overflow 2024-04-15 15:40:37 +02:00
drmortalwombat 755c9234e1 Update C128 exit code 2024-04-13 19:49:40 +02:00
drmortalwombat c3c0583f19 Fix const array dereference 2024-04-12 16:51:26 +02:00
drmortalwombat 55ddce2211 Fix const array access folding 2024-04-12 16:11:47 +02:00
drmortalwombat 5971f9a80f bump version number 2024-04-12 15:54:54 +02:00
drmortalwombat fbfd597306 Fix float param to const propagation 2024-04-12 15:50:46 +02:00
drmortalwombat 0184a550c5 Fix volatile violation when recycling immediates 2024-04-10 15:15:22 +02:00
drmortalwombat 2cdc95ba05 Fix assert in samples 2024-04-09 15:57:53 +02:00
drmortalwombat fefa462730 Improve zero page variable usage 2024-04-08 22:04:50 +02:00
drmortalwombat 7b20e6cca0 Optimize 16 bit counting loops 2024-03-31 14:29:22 +02:00
drmortalwombat ed82e3595b Bump version number 2024-03-30 10:40:00 +01:00
drmortalwombat 6cfdc0ce5f Fix removal of consecutive indexed stores in unrolled loop 2024-03-29 18:49:58 +01:00
drmortalwombat 1f17f1c198 Fix assert in peephole optimizer 2024-03-26 08:23:13 +01:00
drmortalwombat 99da637734 Fix include guard of kernalio.h 2024-03-25 12:25:56 +01:00
drmortalwombat afcc8bc101
Merge pull request #53 from Ecte86/patch-2
Update kernalio.h
2024-03-25 12:24:00 +01:00
Ecte 4b2525b7a4
Update kernalio.h
Removed extra "#ifndef C64_KERNALIO_H" to fix "unterminated conditional directive" error.
2024-03-25 17:38:27 +10:30
drmortalwombat aa601a5727 Change memset and memclr to intrinsic functions 2024-03-24 11:22:13 +01:00
drmortalwombat 85fad64e9c Optimize post inc/dec while loop conditions 2024-03-21 19:33:50 +01:00
drmortalwombat 30d942478f Fix infinite loop in move condition out of loop 2024-03-13 22:14:29 +01:00
drmortalwombat 89750c3f73 promote array of const members to be const as well 2024-03-11 13:40:54 +01:00
drmortalwombat ee43223543 Fix missing member definition in opp string 2024-03-09 14:16:28 +01:00
drmortalwombat 89ac4ee9b9
Merge pull request #52 from Ecte86/patch-1
added standard c++ method c_str to opp::string that calls cstr method.
2024-03-09 14:14:32 +01:00
Ecte b411178aae
added standard c++ method c_str to opp::string that calls cstr method.
This should help Intellisense while allowing code that still uses the cstr method to work.
2024-03-09 19:44:59 +10:30
drmortalwombat 45246a2f2d Fix variable size when defining extern struct with anon struct 2024-03-07 20:42:21 +01:00
drmortalwombat 0c43952e37 Improve constant branch forwarding 2024-03-07 13:20:39 +01:00
drmortalwombat f877e5b8c2 Fix assert in linux sample build 2024-02-28 21:26:25 +01:00
drmortalwombat 2d50d56606 Fix copy and load with striped arrays 2024-02-27 18:02:12 +01:00
drmortalwombat bdecbe77e4 Fix 16bit zero page global variable inc/dec 2024-02-27 09:08:56 +01:00
drmortalwombat f39cb38eb3 Fix unary ops on striped struct members 2024-02-26 20:38:02 +01:00
drmortalwombat 148c288942 Add extract char operator to istream 2024-02-26 18:22:21 +01:00
drmortalwombat e2f822e7d1 Improve short function call loop 2024-02-25 18:43:53 +01:00
drmortalwombat 0b58e9eaaf Fix global aliasing collision with striped data 2024-02-25 18:00:10 +01:00
drmortalwombat 0a76a57f18 Bump version number 2024-02-24 15:50:47 +01:00
drmortalwombat 22ffbfa63c Fix source location when coalescing JSR and RTS in JMP 2024-02-24 09:52:32 +01:00
drmortalwombat 94a3097ba7 Fix find loop optimization with mirrored condition 2024-02-21 15:05:17 +01:00
drmortalwombat c05bd269ad Fix stop petscii definition 2024-02-21 12:12:29 +01:00
drmortalwombat aab71cbab3 Add more std c include files 2024-02-20 14:16:32 +01:00
drmortalwombat 1041ef03eb Bump version number 2024-02-19 14:30:53 +01:00
drmortalwombat e2f36bbb9a Fix parse embed with hex skip or size setting 2024-02-19 14:19:15 +01:00
drmortalwombat 5e9df61ffc Fix read after write hazzard in function param proxy size optimization 2024-02-18 20:35:07 +01:00
drmortalwombat cc5a90ac21 Fix long unsigned int comparison 2024-02-18 18:30:51 +01:00
drmortalwombat 3900e1cf92 fix pragma strings with petscii 2024-02-18 17:57:27 +01:00
drmortalwombat 6b98a44fc0 Improve auto inlining decision with O2 2024-02-18 14:35:41 +01:00
drmortalwombat 2698595302 bump version number 2024-02-18 10:02:29 +01:00
drmortalwombat f6ab79319f More compatibility fixes for -psci 2024-02-18 09:31:05 +01:00
drmortalwombat 264a80d88e Pausing petscii string options for #include and #embed 2024-02-17 17:43:24 +01:00
drmortalwombat 020ab117a4 Fix value copy crossing function call 2024-02-17 17:37:47 +01:00
drmortalwombat 8457316815 Fix unsigned promotion for binary not operator 2024-02-17 13:10:14 +01:00
drmortalwombat 58ffe2ad06 Fix hex arguments for pragmas 2024-02-17 12:53:31 +01:00
drmortalwombat 6f7efd9efc Optimized long multiply 2024-02-17 12:06:15 +01:00
drmortalwombat b84cce7609 Improve compatibility with some C quirks 2024-02-16 21:39:35 +01:00
drmortalwombat 8fc382c11e Fix high byte address calculation cascade 2024-02-15 20:52:10 +01:00
drmortalwombat fadcb61bc7 bump version number 2024-02-15 16:20:15 +01:00
drmortalwombat 7ebf71b161 Switch to Visual Studio 2022 toolset 2024-02-15 15:36:25 +01:00
drmortalwombat 003550337a Fix debug and linux build 2024-02-15 13:29:02 +01:00
drmortalwombat c909995011 Reduce compiler memory footprint 2024-02-15 09:58:26 +01:00
drmortalwombat 18cfbc713a Force some inline calls in vdc 2024-02-14 15:24:01 +01:00
drmortalwombat 806539a2d6 add "tan" to intrinsic functions 2024-02-13 20:49:11 +01:00
drmortalwombat 77f035e2b5
Merge pull request #47 from polluks/patch-1
Fixed warning
2024-02-13 19:12:33 +01:00
Stefan 1d49e0a987
Fixed warning
c++ -c -g -O2 -std=c++11 -Wno-switch ../oscar64/oscar64.cpp -o oscar64.o
../oscar64/Scanner.cpp:768:29: warning: using the result of an assignment as a condition without parentheses [-Wparentheses]
                                        while (mTokenString[i] = def->mString[i])
                                               ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
../oscar64/Scanner.cpp:768:29: note: place parentheses around the assignment to silence this warning
                                        while (mTokenString[i] = def->mString[i])
                                                               ^
                                               (                                )
../oscar64/Scanner.cpp:768:29: note: use '==' to turn this assignment into an equality comparison
                                        while (mTokenString[i] = def->mString[i])
                                                               ^
                                                               ==
1 warning generated.
2024-02-13 18:28:33 +01:00
151 changed files with 42500 additions and 13999 deletions

1
.gitignore vendored
View File

@ -353,3 +353,4 @@ make/oscar64
*.mapd *.mapd
*.idb *.idb
oscar64/Releasex64/oscar64.vcxproj.FileListAbsolute.txt oscar64/Releasex64/oscar64.vcxproj.FileListAbsolute.txt
/oscar64/Debugx64

67
CMakeLists.txt Normal file
View File

@ -0,0 +1,67 @@
cmake_minimum_required(VERSION 3.15)
# Project name and version
project(oscar64 VERSION 1.0 LANGUAGES CXX)
# Define the executable
add_executable(oscar64)
# Glob all source files in the oscar64/ directory
file(GLOB OSCAR64_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/oscar64/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/oscar64/*.h")
# Add the sources to the target
target_sources(${PROJECT_NAME} PRIVATE ${OSCAR64_SOURCES})
# Add header files
target_include_directories(oscar64 PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
# Compiler settings based on configuration
set_target_properties(oscar64 PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED YES
CXX_EXTENSIONS NO
)
# Set debug and release configurations
target_compile_definitions(oscar64 PRIVATE $<$<CONFIG:Debug>:_DEBUG;_CONSOLE> $<$<CONFIG:Release>:NDEBUG;_CONSOLE>)
target_compile_options(oscar64 PRIVATE $<$<CONFIG:Debug>:/W3 /WX> $<$<CONFIG:Release>:/O2 /W3>)
# Post-build steps (only for Release builds)
if(CMAKE_BUILD_TYPE STREQUAL "Release")
add_custom_command(TARGET oscar64 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:oscar64> ${CMAKE_BINARY_DIR}/bin
)
endif()
if (WIN32)
target_link_libraries(oscar64 PRIVATE kernel32 user32 gdi32 winspool comdlg32 advapi32 shell32 ole32 oleaut32 uuid odbc32 odbccp32 version)
elseif (APPLE)
# Add macOS-specific frameworks to replace Windows libraries
target_link_libraries(${PROJECT_NAME}
"-framework Cocoa" # For GUI and application support
"-framework CoreFoundation" # For Core Foundation utilities (similar to advapi32 or shell32)
"-framework CoreGraphics" # For graphics and rendering (similar to gdi32)
"-framework IOKit" # For hardware interaction
"-framework AppKit" # For GUI (equivalent to user32)
)
elseif (UNIX)
# Add Linux-specific libraries for equivalent functionality
target_link_libraries(${PROJECT_NAME}
pthread # For threading (similar to kernel32)
dl # For dynamic library loading (similar to LoadLibrary)
m # For math library (optional but common on Linux)
X11 # For X Window System (similar to user32 for GUI support)
)
endif()
# Output directories
set_target_properties(oscar64 PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/Debug
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/Release
)

1483
README.md

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,77 @@
#include <stdio.h>
#include <assert.h>
struct X
{
char t;
long l;
};
__striped X xs[16];
X xf[16];
char xp;
__noinline long tt(long n)
{
return n;
}
inline auto & tas(void)
{
return xs[xp].l;
}
inline auto & taf(void)
{
return xf[xp].l;
}
long ts(char n)
{
return tt(tas());
}
long tf(char n)
{
return tt(taf());
}
inline auto bas(void)
{
return xs[xp].l;
}
inline auto baf(void)
{
return xs[xp].l;
}
long bs(char n)
{
return tt(bas());
}
long bf(char n)
{
return tt(baf());
}
int main(void)
{
for(char i=0; i<16; i++)
{
xs[i].l = i * i;
xf[i].l = i * i;
}
for(char i=0; i<16; i++)
{
xp = i;
assert(ts(0) == i * i);
assert(tf(0) == i * i);
assert(bs(0) == i * i);
assert(bf(0) == i * i);
}
return 0;
}

View File

@ -1,8 +1,14 @@
rem @echo off rem @echo off
@call :test rolrortest.cpp
@if %errorlevel% neq 0 goto :error
@call :test bitfields.cpp @call :test bitfields.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :testn autorefreturn.cpp
@if %errorlevel% neq 0 goto :error
@call :testh opp_string.cpp @call :testh opp_string.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@ -12,9 +18,15 @@ rem @echo off
@call :testh opp_vector.cpp @call :testh opp_vector.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :testh opp_static_vector.cpp
@if %errorlevel% neq 0 goto :error
@call :testh opp_vector_string.cpp @call :testh opp_vector_string.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :testh opp_string_init.cpp
@if %errorlevel% neq 0 goto :error
@call :testh opp_streamtest.cpp @call :testh opp_streamtest.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@ -27,6 +39,9 @@ rem @echo off
@call :testh opp_list.cpp @call :testh opp_list.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :testn opp_functional.cpp
@if %errorlevel% neq 0 goto :error
@call :testh operatoroverload.cpp @call :testh operatoroverload.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@ -42,7 +57,7 @@ rem @echo off
@call :testh constructortest.cpp @call :testh constructortest.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :testh copyconstructor.cpp @call :testn copyconstructor.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :testh copyassign.cpp @call :testh copyassign.cpp
@ -81,6 +96,9 @@ rem @echo off
@call :test fastcalltest.c @call :test fastcalltest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :test strlen.c
@if %errorlevel% neq 0 goto :error
@call :test strcmptest.c @call :test strcmptest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@ -105,6 +123,9 @@ rem @echo off
@call :test floatmultest.c @call :test floatmultest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :test floatinttest.c
@if %errorlevel% neq 0 goto :error
@call :test staticconsttest.c @call :test staticconsttest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@ -144,6 +165,9 @@ rem @echo off
@call :test qsorttest.c @call :test qsorttest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :testn plasma.c
@if %errorlevel% neq 0 goto :error
@call :test loopdomtest.c @call :test loopdomtest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@ -171,6 +195,12 @@ rem @echo off
@call :test divmodtest.c @call :test divmodtest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :test divmod32test.c
@if %errorlevel% neq 0 goto :error
@call :test fixmathtest.c
@if %errorlevel% neq 0 goto :error
@call :test enumswitch.c @call :test enumswitch.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@ -225,6 +255,9 @@ rem @echo off
@call :testn mmultest.c @call :testn mmultest.c
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :test tileexpand.cpp
@if %errorlevel% neq 0 goto :error
@exit /b 0 @exit /b 0
:error :error
@ -232,115 +265,136 @@ echo Failed with error #%errorlevel%.
exit /b %errorlevel% exit /b %errorlevel%
:testh :testh
..\release\oscar64 -e -bc %~1 ..\bin\oscar64 -e -bc %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -n %~1 ..\bin\oscar64 -e -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O2 -bc %~1 ..\bin\oscar64 -e -O2 -bc %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O2 -n %~1 ..\bin\oscar64 -e -O2 -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O2 -n -dHEAPCHECK %~1 ..\bin\oscar64 -e -O2 -n -dHEAPCHECK %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O0 -bc %~1 ..\bin\oscar64 -e -O2 -xz -Oz -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O0 -n %~1 ..\bin\oscar64 -e -O2 -Oo -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -Os -bc %~1 ..\bin\oscar64 -e -O2 -Ox -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -Os -n %~1 ..\bin\oscar64 -e -O0 -bc %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O3 -bc %~1 ..\bin\oscar64 -e -O0 -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O3 -n %~1 ..\bin\oscar64 -e -Os -bc %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O3 -n -dHEAPCHECK %~1 ..\bin\oscar64 -e -Os -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O3 -bc %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O3 -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O3 -n -dHEAPCHECK %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@exit /b 0 @exit /b 0
:test :test
..\release\oscar64 -e -bc %~1 ..\bin\oscar64 -e -bc %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -n %~1 ..\bin\oscar64 -e -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O2 -bc %~1 ..\bin\oscar64 -e -O2 -bc %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O2 -n %~1 ..\bin\oscar64 -e -O2 -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O0 -bc %~1 ..\bin\oscar64 -e -O0 -bc %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O0 -n %~1 ..\bin\oscar64 -e -O0 -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -Os -bc %~1 ..\bin\oscar64 -e -Os -bc %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -Os -n %~1 ..\bin\oscar64 -e -Os -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O3 -bc %~1 ..\bin\oscar64 -e -O3 -bc %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O3 -n %~1 ..\bin\oscar64 -e -O3 -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O2 -xz -Oz -n %~1 ..\bin\oscar64 -e -O2 -xz -Oz -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -Oo -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -Ox -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@exit /b 0 @exit /b 0
:testb :testb
..\release\oscar64 -e -bc %~1 ..\bin\oscar64 -e -bc %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -bc -O2 %~1 ..\bin\oscar64 -e -bc -O2 %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -bc -O0 %~1 ..\bin\oscar64 -e -bc -O0 %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -bc -Os %~1 ..\bin\oscar64 -e -bc -Os %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -bc -O3 %~1 ..\bin\oscar64 -e -bc -O3 %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@exit /b 0 @exit /b 0
:testn :testn
..\release\oscar64 -e -n %~1 ..\bin\oscar64 -e -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O2 -n %~1 ..\bin\oscar64 -e -O2 -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O0 -n %~1 ..\bin\oscar64 -e -O0 -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -Os -n %~1 ..\bin\oscar64 -e -Os -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O3 -n %~1 ..\bin\oscar64 -e -O3 -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
..\release\oscar64 -e -O2 -xz -Oz -n %~1 ..\bin\oscar64 -e -O2 -xz -Oz -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -Oo -n %~1
@if %errorlevel% neq 0 goto :error
..\bin\oscar64 -e -O2 -Ox -n %~1
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@exit /b 0 @exit /b 0

View File

@ -334,7 +334,6 @@ void test_add_word_cross(void)
} }
int main(void) int main(void)
{ {
test_char_fit(); test_char_fit();
test_char_cross(); test_char_cross();
test_word_fit(); test_word_fit();

View File

@ -303,6 +303,18 @@ void shr32n(unsigned long xu, long xi)
} }
} }
void shl1_32n(void)
{
static const unsigned long m[] = {
#for(i, 32) 1ul << i,
};
for(int i=0; i<32; i++)
{
assert(1ul << i == m[i]);
}
}
#pragma native(shl32n) #pragma native(shl32n)
#pragma native(shr32n) #pragma native(shr32n)
@ -373,24 +385,30 @@ int main(void)
shr16n(0xfedc, 0xfedc); shr16n(0xfedc, 0xfedc);
shl32b(0x00000000UL, 0x00000000L); shl32b(0x00000000UL, 0x00000000L);
shl32b(0x00000001UL, 0x00000001L);
shl32b(0xffffffffUL, 0xffffffffL); shl32b(0xffffffffUL, 0xffffffffL);
shl32b(0x12345678UL, 0x12345678L); shl32b(0x12345678UL, 0x12345678L);
shl32b(0xfedcba98UL, 0xfedcba98L); shl32b(0xfedcba98UL, 0xfedcba98L);
shr32b(0x00000000UL, 0x00000000L); shr32b(0x00000000UL, 0x00000000L);
shr32b(0x00000001UL, 0x00000001L);
shr32b(0xffffffffUL, 0xffffffffL); shr32b(0xffffffffUL, 0xffffffffL);
shr32b(0x12345678UL, 0x12345678L); shr32b(0x12345678UL, 0x12345678L);
shr32b(0xfedcba98UL, 0xfedcba98L); shr32b(0xfedcba98UL, 0xfedcba98L);
shl32n(0x00000000UL, 0x00000000L); shl32n(0x00000000UL, 0x00000000L);
shl32n(0x00000001UL, 0x00000001L);
shl32n(0xffffffffUL, 0xffffffffL); shl32n(0xffffffffUL, 0xffffffffL);
shl32n(0x12345678UL, 0x12345678L); shl32n(0x12345678UL, 0x12345678L);
shl32n(0xfedcba98UL, 0xfedcba98L); shl32n(0xfedcba98UL, 0xfedcba98L);
shr32n(0x00000000UL, 0x00000000L); shr32n(0x00000000UL, 0x00000000L);
shr32n(0x00000001UL, 0x00000001L);
shr32n(0xffffffffUL, 0xffffffffL); shr32n(0xffffffffUL, 0xffffffffL);
shr32n(0x12345678UL, 0x12345678L); shr32n(0x12345678UL, 0x12345678L);
shr32n(0xfedcba98UL, 0xfedcba98L); shr32n(0xfedcba98UL, 0xfedcba98L);
shl1_32n();
return 0; return 0;
} }

View File

@ -1,4 +1,5 @@
#include <assert.h> #include <assert.h>
#include <stdio.h>
int t, n; int t, n;
@ -161,7 +162,7 @@ void test_return_value(void)
C2 c(test_ret_v()); C2 c(test_ret_v());
} }
assert(n == 4 && t == 0); assert(n == 6 && t == 0);
} }
void test_return_reference(void) void test_return_reference(void)
@ -184,7 +185,7 @@ void test_retparam_value(void)
test_param_fv(test_ret_v()); test_param_fv(test_ret_v());
} }
assert(n == 4 && t == 0); assert(n == 6 && t == 0);
} }
void test_retparam_reference(void) void test_retparam_reference(void)
@ -200,7 +201,6 @@ void test_retparam_reference(void)
int main(void) int main(void)
{ {
#if 0
test_dcopy_init(); test_dcopy_init();
test_copy_init(); test_copy_init();
test_minit(); test_minit();
@ -208,9 +208,8 @@ int main(void)
test_param_value(); test_param_value();
test_param_ref(); test_param_ref();
test_return_value(); test_return_value();
#endif
test_retparam_value(); test_retparam_value();
// test_retparam_reference(); test_retparam_reference();
return 0; return 0;
} }

36
autotest/divmod32test.c Normal file
View File

@ -0,0 +1,36 @@
#include <assert.h>
void check(unsigned long l, unsigned long r)
{
unsigned long d = l / r, m = l % r;
assert(d * r + m == l);
assert(m < r);
}
int main(void)
{
for(char i=0; i<28; i++)
{
for(char j=0; j<28; j++)
{
check(0xb3ul << i, 0x2bul << j);
check(0xb3ul << i, 0x01ul << j);
check(0x01ul << i, 0xc2ul << j);
check(0xb31ful << i, 0x2bul << j);
check(0xb354ul << i, 0x01ul << j);
check(0xb3ul << i, 0x2b1cul << j);
check(0xb3ul << i, 0x013ful << j);
check(0xb31ful << i, 0x2b23ul << j);
check(0xb354ul << i, 0x0145ul << j);
check(0xb31f24ul << i, 0x2bul << j);
check(0xb35421ul << i, 0x01ul << j);
check(0xb31f24ul << i, 0x2b23ul << j);
check(0xb35421ul << i, 0x0145ul << j);
check(0xb31f24ul << i, 0x2b2356ul << j);
check(0xb35421ul << i, 0x0145a7ul << j);
}
}
return 0;
}

90
autotest/fixmathtest.c Normal file
View File

@ -0,0 +1,90 @@
#include <fixmath.h>
#include <assert.h>
#include <stdlib.h>
unsigned tval[] = {
1, 2, 16, 128, 255, 256, 4096, 32768, 65535
};
void testmuldiv16u(void)
{
for (char i=0; i<9; i++)
{
assert(lmuldiv16u(tval[i], 0, tval[i]) == 0);
assert(lmuldiv16u(0, tval[i], tval[i]) == 0);
for(char j=0; j<9; j++)
{
assert(lmuldiv16u(tval[i], tval[j], tval[i]) == tval[j]);
assert(lmuldiv16u(tval[j], tval[i], tval[i]) == tval[j]);
}
}
for(int i=0; i<10000; i++)
{
unsigned a = rand();
unsigned b = rand();
unsigned c = rand();
if (c > 0)
{
unsigned long d = (unsigned long)a * (unsigned long) b / c;
if (d < 0x10000l)
assert(lmuldiv16u(a, b, c) == d);
}
}
}
unsigned ival[] = {
1, 2, 16, 128, 255, 256, 4096, 32767,
-1, -2, -16, -128, -255, -256, -4096, -32767
};
void testmuldiv16s(void)
{
for (char i=0; i<16; i++)
{
assert(lmuldiv16s(ival[i], 0, ival[i]) == 0);
assert(lmuldiv16s(0, ival[i], ival[i]) == 0);
for(char j=0; j<16; j++)
{
assert(lmuldiv16s(ival[i], ival[j], ival[i]) == ival[j]);
assert(lmuldiv16s(ival[j], ival[i], ival[i]) == ival[j]);
}
}
for(int i=0; i<10000; i++)
{
int a = rand();
int b = rand();
int c = rand();
if (c > 0)
{
long d = (long)a * (long)b / c;
if (d >= -32768 && d <= 32767)
assert(lmuldiv16s(a, b, c) == d);
}
}
}
void testlmul4f12s(void)
{
for(int i=0; i<20000; i++)
{
int a = rand();
int b = rand();
long d = ((long)a * (long)b) >> 12;
if (d >= -32768 && d <= 32767)
assert(lmul4f12s(a, b) == d);
}
}
int main(void)
{
testlmul4f12s();
testmuldiv16u();
testmuldiv16s();
return 0;
}

75
autotest/floatinttest.c Normal file
View File

@ -0,0 +1,75 @@
#include <assert.h>
#include <stdio.h>
#include <math.h>
int main(void)
{
float a;
int i;
long li;
unsigned u;
unsigned long lu;
a = 1.0;
i = 1;
for(int j=0; j<15; j++)
{
assert(i == (int)a);
assert(a == (float)i);
a *= 2.0;
i <<= 1;
}
a = -1.0;
i = -1;
for(int j=0; j<15; j++)
{
assert(i == (int)a);
assert(a == (float)i);
a *= 2.0;
i <<= 1;
}
a = 1.0;
u = 1;
for(int j=0; j<16; j++)
{
assert(u == (unsigned)a);
assert(a == (float)u);
a *= 2.0;
u <<= 1;
}
a = 1.0;
li = 1;
for(int j=0; j<31; j++)
{
assert(li == (long)a);
assert(a == (float)li);
a *= 2.0;
li <<= 1;
}
a = -1.0;
li = -1;
for(int j=0; j<31; j++)
{
assert(li == (long)a);
assert(a == (float)li);
a *= 2.0;
li <<= 1;
}
a = 1.0;
lu = 1;
for(int j=0; j<32; j++)
{
assert(lu == (unsigned long)a);
assert(a == (float)lu);
a *= 2.0;
lu <<= 1;
}
return 0;
}

View File

@ -1,5 +1,3 @@
CC=../bin/oscar64
CXX=$(CC)
SRCS=$(filter-out opp_part1.cpp opp_part2.cpp, $(wildcard *.c *.cpp)) SRCS=$(filter-out opp_part1.cpp opp_part2.cpp, $(wildcard *.c *.cpp))
EXES=$(patsubst %.c,%,$(SRCS)) EXES=$(patsubst %.c,%,$(SRCS))
EXES:=$(patsubst %.cpp,%,$(EXES)) EXES:=$(patsubst %.cpp,%,$(EXES))
@ -7,44 +5,56 @@ EXES:=$(patsubst %.cpp,%,$(EXES))
all: $(EXES) all: $(EXES)
%: %.c %: %.c
$(CC) -e -bc $< $(OSCAR64_CC) -e -bc $<
$(CC) -e -n $< $(OSCAR64_CC) -e -n $<
$(CC) -e -O2 -bc $< $(OSCAR64_CC) -e -O2 -bc $<
$(CC) -e -O2 -n $< $(OSCAR64_CC) -e -O2 -n $<
$(CC) -e -O0 -bc $< $(OSCAR64_CC) -e -O0 -bc $<
$(CC) -e -O0 -n $< $(OSCAR64_CC) -e -O0 -n $<
$(CC) -e -Os -bc $< $(OSCAR64_CC) -e -Os -bc $<
$(CC) -e -Os -n $< $(OSCAR64_CC) -e -Os -n $<
$(CC) -e -O3 -bc $< $(OSCAR64_CC) -e -O3 -bc $<
$(CC) -e -O3 -n $< $(OSCAR64_CC) -e -O3 -n $<
%: %.cpp %: %.cpp
$(CXX) -e -bc $< $(OSCAR64_CXX) -e -bc $<
$(CXX) -e -n $< $(OSCAR64_CXX) -e -n $<
$(CXX) -e -O2 -bc $< $(OSCAR64_CXX) -e -O2 -bc $<
$(CXX) -e -O2 -n $< $(OSCAR64_CXX) -e -O2 -n $<
$(CXX) -e -O0 -bc $< $(OSCAR64_CXX) -e -O0 -bc $<
$(CXX) -e -O0 -n $< $(OSCAR64_CXX) -e -O0 -n $<
$(CXX) -e -Os -bc $< $(OSCAR64_CXX) -e -Os -bc $<
$(CXX) -e -Os -n $< $(OSCAR64_CXX) -e -Os -n $<
$(CXX) -e -O3 -bc $< $(OSCAR64_CXX) -e -O3 -bc $<
$(CXX) -e -O3 -n $< $(OSCAR64_CXX) -e -O3 -n $<
# testb # testb
bitshifttest: bitshifttest.c bitshifttest: bitshifttest.c
$(CC) -e -bc $< $(OSCAR64_CC) -e -bc $<
$(CC) -e -bc -O2 $< $(OSCAR64_CC) -e -bc -O2 $<
$(CC) -e -bc -O0 $< $(OSCAR64_CC) -e -bc -O0 $<
$(CC) -e -bc -Os $< $(OSCAR64_CC) -e -bc -Os $<
$(CC) -e -bc -O3 $< $(OSCAR64_CC) -e -bc -O3 $<
$(CC) -e -n $< $(OSCAR64_CC) -e -n $<
# testn # testn
stripedarraytest: stripedarraytest.c stripedarraytest: stripedarraytest.c
$(CC) -e -O2 -n $< $(OSCAR64_CC) -e -O2 -n $<
$(CC) -e -O0 -n $< $(OSCAR64_CC) -e -O0 -n $<
$(CC) -e -Os -n $< $(OSCAR64_CC) -e -Os -n $<
$(CC) -e -O3 -n $< $(OSCAR64_CC) -e -O3 -n $<
autorefreturn: autorefreturn.cpp
$(OSCAR64_CC) -e -O2 -n $<
$(OSCAR64_CC) -e -O0 -n $<
$(OSCAR64_CC) -e -Os -n $<
$(OSCAR64_CC) -e -O3 -n $<
copyconstructor: copyconstructor.cpp
$(OSCAR64_CC) -e -O2 -n $<
$(OSCAR64_CC) -e -O0 -n $<
$(OSCAR64_CC) -e -Os -n $<
$(OSCAR64_CC) -e -O3 -n $<
clean: clean:
$(RM) *.asm *.bcs *.int *.lbl *.map *.prg @$(RM) *.asm *.bcs *.int *.lbl *.map *.prg

View File

@ -0,0 +1,46 @@
#include <opp/functional.h>
class Node
{
public:
virtual int eval(void) const = 0;
};
class ConstNode : public Node
{
private:
int v;
public:
ConstNode(int v_) : v(v_) {}
virtual int eval(void) const
{
return v;
}
};
class BinaryNode : public Node
{
private:
opp::function<int(int, int)> op;
Node * left, * right;
public:
BinaryNode(opp::function<int(int, int)> op_, Node * left_, Node * right_);
virtual int eval(void) const
{
return op(left->eval(), right->eval());
}
};
inline BinaryNode::BinaryNode(opp::function<int(int, int)> op_, Node * left_, Node * right_)
: op(op_), left(left_), right(right_) {}
int main(void)
{
Node * s1 =
new BinaryNode([=](int a, int b){return a + b;},
new ConstNode(7), new ConstNode(11)
);
return s1->eval() - 18;
}

View File

@ -0,0 +1,78 @@
#include <opp/static_vector.h>
#include <opp/algorithm.h>
#include <assert.h>
#include <opp/iostream.h>
int main(void)
{
opp::static_vector<int, 20> a;
for(int i=0; i<10; i++)
a.push_back(i);
int s = 0;
for(int i=0; i<a.size(); i++)
s += a[i];
assert(s == 45);
for(int i=0; i<5; i++)
a.erase(i);
s = 0;
for(int i=0; i<a.size(); i++)
s += a[i];
assert(s == 1 + 3 + 5 + 7 + 9);
opp::static_vector<int, 100> v;
for(int i=0; i<10; i++)
v.push_back(i);
assert(v.size() == 10);
v.insert(0, 20);
assert(v.size() == 11);
v.insert(6, 21);
assert(v.size() == 12);
v.insert(12, 22);
int * fi = opp::find(v.begin(), v.end(), 21);
fi = v.insert(fi, 30);
fi = v.insert(fi, 31);
fi = v.insert(fi, 32);
assert(v.size() == 16);
assert(v[0] == 20);
assert(v[15] == 22);
assert(v[8] == 32);
fi = opp::find(v.begin(), v.end(), 32);
for(int i=0; i<30; i++)
{
fi = v.insert(fi, i + 40);
}
assert(v.size() == 46);
assert(v[28] == 60);
v.erase(10, 10);
for(int i : v)
opp::cout << i << ", ";
opp::cout << "\n";
assert(v.size() == 36);
assert(v[18] == 60);
v.assign(42, 11);
assert(v.size() == 42);
assert(v[0] == 11);
assert(v[15] == 11);
assert(v[41] == 11);
return 0;
}

View File

@ -0,0 +1,193 @@
#include <opp/string.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
using opp::string;
const string s1;
const string s2 = "Hello";
const string s3{"World"};
const string a1[2];
const string a2[2] = {"Hello", "World"};
const string a3[2] = {opp::string("Hello"), opp::string("World")};
const string d1[3][2];
const string d2[3][2] = {{"Hello", "World"}, {"aaa", "bbb"}, {"ccc", "ddd"}};
const string d3[3][2] =
{{opp::string("Hello"), opp::string("World")},
{opp::string("aaa"), opp::string("bbb")},
{opp::string("ccc"), opp::string("ddd")}};
void test_global_init(void)
{
assert(!strcmp(s1.tocstr(), ""));
assert(!strcmp(s2.tocstr(), "Hello"));
assert(!strcmp(s3.tocstr(), "World"));
}
void test_global_ainit(void)
{
assert(!strcmp(a1[0].tocstr(), ""));
assert(!strcmp(a1[1].tocstr(), ""));
assert(!strcmp(a2[0].tocstr(), "Hello"));
assert(!strcmp(a2[1].tocstr(), "World"));
assert(!strcmp(a3[0].tocstr(), "Hello"));
assert(!strcmp(a3[1].tocstr(), "World"));
}
void test_global_dinit(void)
{
assert(!strcmp(d1[0][0].tocstr(), ""));
assert(!strcmp(d1[2][1].tocstr(), ""));
assert(!strcmp(d2[0][0].tocstr(), "Hello"));
assert(!strcmp(d2[2][1].tocstr(), "ddd"));
assert(!strcmp(d3[0][0].tocstr(), "Hello"));
assert(!strcmp(d3[2][1].tocstr(), "ddd"));
}
void test_local_init(void)
{
const string s1;
const string s2 = "Hello";
const string s3{"World"};
assert(!strcmp(s1.tocstr(), ""));
assert(!strcmp(s2.tocstr(), "Hello"));
assert(!strcmp(s3.tocstr(), "World"));
}
void test_local_ainit(void)
{
const string a1[2];
const string a2[2] = {"Hello", "World"};
const string a3[2] = {opp::string("Hello"), opp::string("World")};
assert(!strcmp(a1[0].tocstr(), ""));
assert(!strcmp(a1[1].tocstr(), ""));
assert(!strcmp(a2[0].tocstr(), "Hello"));
assert(!strcmp(a2[1].tocstr(), "World"));
assert(!strcmp(a3[0].tocstr(), "Hello"));
assert(!strcmp(a3[1].tocstr(), "World"));
}
void test_local_dinit(void)
{
const string d1[3][2];
const string d2[3][2] = {{"Hello", "World"}, {"aaa", "bbb"}, {"ccc", "ddd"}};
const string d3[3][2] =
{{opp::string("Hello"), opp::string("World")},
{opp::string("aaa"), opp::string("bbb")},
{opp::string("ccc"), opp::string("ddd")}};
assert(!strcmp(d1[0][0].tocstr(), ""));
assert(!strcmp(d1[2][1].tocstr(), ""));
assert(!strcmp(d2[0][0].tocstr(), "Hello"));
assert(!strcmp(d2[2][1].tocstr(), "ddd"));
assert(!strcmp(d3[0][0].tocstr(), "Hello"));
assert(!strcmp(d3[2][1].tocstr(), "ddd"));
}
class X
{
public:
const string s1;
const string s2 = "Hello";
const string s3;
const string a1[2];
const string a2[2] = {"Hello", "World"};
const string d1[3][2];
const string d2[3][2] = {{"Hello", "World"}, {"aaa", "bbb"}, {"ccc", "ddd"}};
X() : s3("World") {}
};
void test_member_init(void)
{
X x;
assert(!strcmp(x.s1.tocstr(), ""));
assert(!strcmp(x.s2.tocstr(), "Hello"));
assert(!strcmp(x.s3.tocstr(), "World"));
}
void test_member_ainit(void)
{
X x;
assert(!strcmp(x.a1[0].tocstr(), ""));
assert(!strcmp(x.a1[1].tocstr(), ""));
assert(!strcmp(x.a2[0].tocstr(), "Hello"));
assert(!strcmp(x.a2[1].tocstr(), "World"));
}
void test_member_dinit(void)
{
X x;
assert(!strcmp(x.d1[0][0].tocstr(), ""));
assert(!strcmp(x.d1[2][1].tocstr(), ""));
assert(!strcmp(x.d2[0][0].tocstr(), "Hello"));
assert(!strcmp(x.d2[2][1].tocstr(), "ddd"));
}
void test_copy_init(void)
{
X x;
X y(x);
assert(!strcmp(y.s1.tocstr(), ""));
assert(!strcmp(y.s2.tocstr(), "Hello"));
assert(!strcmp(y.s3.tocstr(), "World"));
}
void test_copy_ainit(void)
{
X x;
X y(x);
assert(!strcmp(y.a1[0].tocstr(), ""));
assert(!strcmp(y.a1[1].tocstr(), ""));
assert(!strcmp(y.a2[0].tocstr(), "Hello"));
assert(!strcmp(y.a2[1].tocstr(), "World"));
}
int main(void)
{
test_global_init();
test_global_ainit();
test_global_dinit();
for(int i=0; i<10000; i++)
{
test_local_init();
test_local_ainit();
}
test_member_init();
test_member_ainit();
test_copy_init();
test_copy_ainit();
return 0;
}

View File

@ -64,5 +64,15 @@ int main(void)
opp::cout << i << ", "; opp::cout << i << ", ";
opp::cout << "\n"; opp::cout << "\n";
assert(v.size() == 36);
assert(v[18] == 60);
v.assign(42, 11);
assert(v.size() == 42);
assert(v[0] == 11);
assert(v[15] == 11);
assert(v[41] == 11);
return 0; return 0;
} }

145
autotest/plasma.c Normal file
View File

@ -0,0 +1,145 @@
#include <stdlib.h>
static const char sintab[] = {
128, 131, 134, 137, 140, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177, 179, 182, 185, 188, 191, 193, 196, 199, 201, 204, 206, 209, 211, 213, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 235, 237, 239, 240, 241, 243, 244, 245, 246, 248, 249, 250, 250, 251, 252, 253, 253, 254, 254, 254, 255, 255, 255,
255, 255, 255, 255, 254, 254, 254, 253, 253, 252, 251, 250, 250, 249, 248, 246, 245, 244, 243, 241, 240, 239, 237, 235, 234, 232, 230, 228, 226, 224, 222, 220, 218, 216, 213, 211, 209, 206, 204, 201, 199, 196, 193, 191, 188, 185, 182, 179, 177, 174, 171, 168, 165, 162, 159, 156, 153, 150, 147, 144, 140, 137, 134, 131,
128, 125, 122, 119, 116, 112, 109, 106, 103, 100, 97, 94, 91, 88, 85, 82, 79, 77, 74, 71, 68, 65, 63, 60, 57, 55, 52, 50, 47, 45, 43, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 21, 19, 17, 16, 15, 13, 12, 11, 10, 8, 7, 6, 6, 5, 4, 3, 3, 2, 2, 2, 1, 1, 1,
1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 19, 21, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 43, 45, 47, 50, 52, 55, 57, 60, 63, 65, 68, 71, 74, 77, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106, 109, 112, 116, 119, 122, 125
};
char Screen0[1024], Screen1[1024];
char colormap0[256], colormap1[256];
char colors0[] = {0, 6, 14, 1, 13, 5, 0};
char colors1[] = {0, 9, 7, 1, 15, 12, 0};
unsigned c1A, c1B, c2A, c2B, c3A, c3B;
int d1A, d1B, d2A, d2B, d3A, d3B;
void inithires(void)
{
for(int i=0; i<256; i++)
{
colormap0[i] = colors0[i / 37];
colormap1[i] = colors1[i / 37] << 4;
}
}
inline void doplasma(char * scrn)
{
char xbuf0[40], xbuf1[40];
char ybuf0[25], ybuf1[25];
char c2a = c2A >> 8;
char c2b = c2B >> 8;
char c1a = c1A >> 8;
char c1b = c1B >> 8;
for (char i = 0; i < 25; i++) {
ybuf0[i] = sintab[(c1a + c2a) & 0xff] + sintab[c1b];
c1a += 13;
c1b -= 5;
}
for (char i = 0; i < 40; i++) {
xbuf0[i] = sintab[(c2a + c1b) & 0xff] + sintab[c2b];
c2a += 11;
c2b -= 7;
}
c2a = c2B >> 8;
c2b = c3A >> 8;
c1a = c1B >> 8;
c1b = c3B >> 8;
for (char i = 0; i < 25; i++) {
ybuf1[i] = sintab[(c1b + c2a) & 0xff] + sintab[c1a];
c1a += 4;
c1b -= 6;
}
for (char i = 0; i < 40; i++) {
xbuf1[i] = sintab[(c2b + c1a) & 0xff] + sintab[c2a];
c2a += 7;
c2b -= 9;
}
#pragma unroll(full)
for (char k=0; k<5; k++)
{
char tbuf0[5], tbuf1[5];
#pragma unroll(full)
for (char i = 0; i < 4; i++)
{
tbuf0[i] = ybuf0[5 * k + i + 1] - ybuf0[5 * k + i];
tbuf1[i] = ybuf1[5 * k + i + 1] - ybuf1[5 * k + i];
}
for (signed char i = 39; i >= 0; i--)
{
char t = xbuf0[i] + ybuf0[5 * k];
char u = xbuf1[i] + ybuf1[5 * k];
#pragma unroll(full)
for (char j = 0; j < 5; j++)
{
scrn[40 * j + 200 * k + i] = colormap0[u] | colormap1[u];
t += tbuf0[j];
u += tbuf1[j];
}
}
}
c1A += 8 * ((int)sintab[d1A] - 128);
c1B += 16 * ((int)sintab[d1B] - 128);
c2A += 8 * ((int)sintab[d2A] - 128);
c2B += 16 * ((int)sintab[d2B] - 128);
c3A += 6 * ((int)sintab[d3A] - 128);
c3B += 12 * ((int)sintab[d3B] - 128);
d1A += 3;
d1B += rand() & 3;
d2A += 5;
d2B += rand() & 3;
d3A += 2;
d3B += rand() & 3;
}
void doplasma0(void)
{
doplasma(Screen0);
}
void doplasma1(void)
{
doplasma(Screen1);
}
unsigned checksum(const char * scr)
{
unsigned s = 0x1234;
for(int i=0; i<1024; i++)
{
unsigned m = s & 1;
s >>= 1;
if (m)
s ^= 0x2152;
s ^= scr[i];
}
return s;
}
int main(void)
{
inithires();
doplasma0();
doplasma1();
doplasma0();
doplasma1();
doplasma0();
doplasma1();
return checksum(Screen0) + checksum(Screen1) - 16337;
}

76
autotest/rolrortest.cpp Normal file
View File

@ -0,0 +1,76 @@
#include <assert.h>
__noinline unsigned long rollright32(unsigned long a) {
unsigned long tmp = a & 1;
return ( a >> 1) + (tmp << 31);
}
__noinline unsigned rollright16(unsigned a) {
unsigned tmp = a & 1;
return ( a >> 1) + (tmp << 15);
}
__noinline char rollright8(char a) {
char tmp = a & 1;
return ( a >> 1) + (tmp << 7);
}
__noinline unsigned long rollleft32(unsigned long a) {
unsigned long tmp = (a >> 31) & 1;
return ( a << 1) + tmp;
}
__noinline unsigned rollleft16(unsigned a) {
unsigned tmp = (a >> 15) & 1;
return ( a << 1) + tmp;
}
__noinline char rollleft8(char a) {
char tmp = (a >> 7) & 1;
return ( a << 1) + tmp;
}
int main() {
unsigned long lv = 0x12345678ul;
unsigned val = 0x1234;
char c=0x12;
unsigned long lvt[33];
unsigned valt[17];
char ct[9];
lvt[0] = lv;
valt[0] = val;
ct[0] = c;
assert(rollleft8(rollright8(c)) == c);
assert(rollleft16(rollright16(val)) == val);
assert(rollleft32(rollright32(lv)) == lv);
for(int i=0; i<32; i++)
lvt[i + 1] = rollright32(lvt[i]);
for(int i=0; i<16; i++)
valt[i + 1] = rollright16(valt[i]);
for(int i=0; i<8; i++)
ct[i + 1] = rollright8(ct[i]);
for(int i=0; i<=32; i++)
{
assert(lvt[32 - i] == lv);
lv = rollleft32(lv);
}
for(int i=0; i<=16; i++)
{
assert(valt[16 - i] == val);
val = rollleft16(val);
}
for(int i=0; i<=8; i++)
{
assert(ct[8 - i] == c);
c = rollleft8(c);
}
return 0;
}

27
autotest/strlen.c Normal file
View File

@ -0,0 +1,27 @@
#include <string.h>
#include <assert.h>
char lstr[1025];
int main(void)
{
#if 1
assert(strlen("") == 0);
assert(strlen("1") == 1);
assert(strlen("12") == 2);
assert(strlen("123") == 3);
assert(strlen("1234") == 4);
assert(strlen("12345") == 5);
assert(strlen("123456") == 6);
#endif
#if 1
char * dp = lstr;
for(int i=0; i<1024; i++)
{
*dp = 0;
assert(strlen(lstr) == i);
*dp++ = 'a';
}
#endif
return 0;
}

View File

@ -5,6 +5,11 @@ void testmuli(long a, long b, long ab)
assert (a * b == ab); assert (a * b == ab);
} }
void testmulu(unsigned long a, unsigned long b, unsigned long ab)
{
assert (a * b == ab);
}
void testdivi(long a, long b, long ab) void testdivi(long a, long b, long ab)
{ {
assert (a / b == ab); assert (a / b == ab);
@ -80,6 +85,26 @@ int main(void)
testmuli( -1024, 1237, -1266688l); testmuli( -1024, 1237, -1266688l);
testmuli( -1024,-1237, 1266688l); testmuli( -1024,-1237, 1266688l);
testmulu(0x00000001, 0x0000003c, 0x0000003c);
testmulu(0x00000100, 0x0000003c, 0x00003c00);
testmulu(0x00010000, 0x0000003c, 0x003c0000);
testmulu(0x01000000, 0x0000003c, 0x3c000000);
testmulu(0x0000003c, 0x00000001, 0x0000003c);
testmulu(0x0000003c, 0x00000100, 0x00003c00);
testmulu(0x0000003c, 0x00010000, 0x003c0000);
testmulu(0x0000003c, 0x01000000, 0x3c000000);
testmulu(0x0000004b, 0x0000003c, 0x00001194);
testmulu(0x00004b00, 0x0000003c, 0x00119400);
testmulu(0x004b0000, 0x0000003c, 0x11940000);
testmulu(0x4b000000, 0x0000003c, 0x94000000);
testmulu(0x0000003c, 0x0000004b, 0x00001194);
testmulu(0x0000003c, 0x00004b00, 0x00119400);
testmulu(0x0000003c, 0x004b0000, 0x11940000);
testmulu(0x0000003c, 0x4b000000, 0x94000000);
testdivi( 1, 1, 1); testdivi( 1, 1, 1);
testdivi(-1, 1, -1); testdivi(-1, 1, -1);
testdivi( 1, -1, -1); testdivi( 1, -1, -1);

View File

@ -63,6 +63,33 @@ bool nge(long a, long b)
inline bool ieq(long a, long b)
{
return a == b;
}
inline bool ilt(long a, long b)
{
return a < b;
}
inline bool igt(long a, long b)
{
return a > b;
}
inline bool ile(long a, long b)
{
return a <= b;
}
inline bool ige(long a, long b)
{
return a >= b;
}
bool beqz(long a) bool beqz(long a)
{ {
return a == 0; return a == 0;
@ -188,7 +215,71 @@ bool nge1(long a)
void cmp(long a, long b) bool beqm(long a)
{
return a == -1;
}
bool bltm(long a)
{
return a < -1;
}
bool bgtm(long a)
{
return a > -1;
}
bool blem(long a)
{
return a <= -1;
}
bool bgem(long a)
{
return a >= -1;
}
bool neqm(long a)
{
return a == -1;
}
#pragma native(neqm)
bool nltm(long a)
{
return a < -1;
}
#pragma native(nltm)
bool ngtm(long a)
{
return a > -1;
}
#pragma native(ngtm)
bool nlem(long a)
{
return a <= -1;
}
#pragma native(nlem)
bool ngem(long a)
{
return a >= -1;
}
#pragma native(ngem)
void cmpc(long a, long b)
{ {
bool beqf = beq(a, b), bltf = blt(a, b), bgtf = bgt(a, b), blef = ble(a, b), bgef = bge(a, b); bool beqf = beq(a, b), bltf = blt(a, b), bgtf = bgt(a, b), blef = ble(a, b), bgef = bge(a, b);
bool neqf = neq(a, b), nltf = nlt(a, b), ngtf = ngt(a, b), nlef = nle(a, b), ngef = nge(a, b); bool neqf = neq(a, b), nltf = nlt(a, b), ngtf = ngt(a, b), nlef = nle(a, b), ngef = nge(a, b);
@ -203,6 +294,27 @@ void cmp(long a, long b)
assert(bgef == ngef); assert(bgef == ngef);
} }
void cmpi(long a, long b)
{
bool ieqf = ieq(a, b), iltf = ilt(a, b), igtf = igt(a, b), ilef = ile(a, b), igef = ige(a, b);
bool neqf = neq(a, b), nltf = nlt(a, b), ngtf = ngt(a, b), nlef = nle(a, b), ngef = nge(a, b);
printf("INLINE %ld, %ld : EQ %d LT %d GT %d\r", a, b, ieqf, iltf, igtf);
printf("NATIVE %ld, %ld : EQ %d LT %d GT %d\r", a, b, neqf, nltf, ngtf);
assert(ieqf == neqf);
assert(iltf == nltf);
assert(igtf == ngtf);
assert(ilef == nlef);
assert(igef == ngef);
}
void cmp(long a, long b)
{
cmpc(a, b);
cmpi(a, b);
}
void cmpz(long a) void cmpz(long a)
{ {
bool beqf = beqz(a), bltf = bltz(a), bgtf = bgtz(a), blef = blez(a), bgef = bgez(a); bool beqf = beqz(a), bltf = bltz(a), bgtf = bgtz(a), blef = blez(a), bgef = bgez(a);
@ -233,6 +345,21 @@ void cmp1(long a)
assert(bgef == ngef); assert(bgef == ngef);
} }
void cmpm(long a)
{
bool beqf = beqm(a), bltf = bltm(a), bgtf = bgtm(a), blef = blem(a), bgef = bgem(a);
bool neqf = neqm(a), nltf = nltm(a), ngtf = ngtm(a), nlef = nlem(a), ngef = ngem(a);
printf("BYTE %ld, 1 : EQ %d LT %d GT %d LE %d GE %d\r", a, beqf, bltf, bgtf, blef, bgef);
printf("NATIVE %ld, 1 : EQ %d LT %d GT %d LE %d GE %d\r", a, neqf, nltf, ngtf, nlef, ngef);
assert(beqf == neqf);
assert(bltf == nltf);
assert(bgtf == ngtf);
assert(blef == nlef);
assert(bgef == ngef);
}
int main(void) int main(void)
{ {
cmp( 0, 1); cmp( 0, 1);
@ -327,6 +454,10 @@ int main(void)
cmp1(256); cmp1(256);
cmp1(10000); cmp1(10000);
cmp1(20000); cmp1(20000);
cmp1(1000000l);
cmp1(2000000l);
cmp1(100000000l);
cmp1(200000000l);
cmp1(-1); cmp1(-1);
cmp1(-2); cmp1(-2);
cmp1(-3); cmp1(-3);
@ -334,6 +465,34 @@ int main(void)
cmp1(-256); cmp1(-256);
cmp1(-10000); cmp1(-10000);
cmp1(-20000); cmp1(-20000);
cmp1(-1000000l);
cmp1(-2000000l);
cmp1(-100000000l);
cmp1(-200000000l);
cmpm(0);
cmpm(1);
cmpm(2);
cmpm(3);
cmpm(255);
cmpm(256);
cmpm(10000);
cmpm(20000);
cmpm(1000000l);
cmpm(2000000l);
cmpm(100000000l);
cmpm(200000000l);
cmpm(-1);
cmpm(-2);
cmpm(-3);
cmpm(-255);
cmpm(-256);
cmpm(-10000);
cmpm(-20000);
cmpm(-1000000l);
cmpm(-2000000l);
cmpm(-100000000l);
cmpm(-200000000l);
return 0; return 0;

83
autotest/tileexpand.cpp Normal file
View File

@ -0,0 +1,83 @@
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#define MAP_WIDTH 10
#define MAP_HEIGHT 2
#define TITLE_TILE_WIDTH 4
#define TITLE_TILE_HEIGHT 4
#define PTR_SCREEN ((char *)0xc000)
#define PTR_BUFFER ((char *)0xc400)
#define PTR_COLOR ((char *)0xd800)
#define PTR_FONTCHARSET ((char *)0xd800)
const char TitleMap[1024] = {
#for(i, 1024) i * 17,
};
const char TitleTiles[4096] = {
#for(i, 4096) i * 31,
};
// Custom screen address
extern char* const Screen = PTR_SCREEN;
// Color mem address
extern char* const Color = PTR_COLOR;
void RenderLogo(char screenY)
{
char * sp = Screen;
char * cp = Color;
const char * mp = TitleMap;
for(char ty=0; ty < MAP_HEIGHT; ty++)
{
for(char tx=0; tx< MAP_WIDTH; tx++)
{
char ti = mp[tx];
const char* tp = TitleTiles + (TITLE_TILE_WIDTH * TITLE_TILE_HEIGHT) * ti;
for(char y=0; y<TITLE_TILE_HEIGHT; y++)
{
for(char x=0; x<TITLE_TILE_WIDTH; x++)
{
char c = tp[TITLE_TILE_WIDTH * y + x];
sp[40 * (y + screenY) + x] = c;
cp[40 * (y + screenY) + x] = 1;
}
}
sp += TITLE_TILE_WIDTH;
cp += TITLE_TILE_WIDTH;
}
sp += 120;
cp += 120;
mp += MAP_WIDTH;
}
}
void VerifyLogo(char screenY)
{
for(char dy=0; dy<MAP_HEIGHT * TITLE_TILE_HEIGHT; dy++)
{
for(char dx=0; dx<MAP_WIDTH * TITLE_TILE_WIDTH; dx++)
{
char ty = dy / TITLE_TILE_HEIGHT, iy = dy % TITLE_TILE_HEIGHT;
char tx = dx / TITLE_TILE_WIDTH, ix = dx % TITLE_TILE_WIDTH;
int si = TitleMap[MAP_WIDTH * ty + tx] * TITLE_TILE_WIDTH * TITLE_TILE_HEIGHT + TITLE_TILE_WIDTH * iy + ix;
int di = 40 * (dy + screenY) + dx;
assert(Screen[di] == TitleTiles[si]);
}
}
}
int main(void)
{
RenderLogo(1);
VerifyLogo(1);
return 0;
}

View File

@ -10,10 +10,11 @@ enum SIDFXState
SIDFX_WAIT SIDFX_WAIT
}; };
static struct SIDFXChannel __striped static struct SIDFXChannel
{ {
const SIDFX * com; const SIDFX * volatile com;
byte delay, cnt, priority; byte delay, priority;
volatile byte cnt;
volatile SIDFXState state; volatile SIDFXState state;
unsigned freq, pwm; unsigned freq, pwm;
@ -26,9 +27,20 @@ void sidfx_init(void)
channels[i].com = nullptr; channels[i].com = nullptr;
channels[i].state = SIDFX_IDLE; channels[i].state = SIDFX_IDLE;
channels[i].priority = 0; channels[i].priority = 0;
channels[i].delay = 1;
} }
} }
bool sidfx_idle(byte chn)
{
return channels[chn].state == SIDFX_IDLE;
}
char sidfx_cnt(byte chn)
{
return channels[chn].cnt;
}
void sidfx_play(byte chn, const SIDFX * fx, byte cnt) void sidfx_play(byte chn, const SIDFX * fx, byte cnt)
{ {
SIDFXState ns = channels[chn].state; SIDFXState ns = channels[chn].state;
@ -41,6 +53,7 @@ void sidfx_play(byte chn, const SIDFX * fx, byte cnt)
return; return;
channels[chn].state = SIDFX_IDLE; channels[chn].state = SIDFX_IDLE;
channels[chn].delay = 1;
channels[chn].com = fx; channels[chn].com = fx;
channels[chn].cnt = cnt - 1; channels[chn].cnt = cnt - 1;
@ -53,105 +66,128 @@ void sidfx_stop(byte chn)
{ {
channels[chn].com = nullptr; channels[chn].com = nullptr;
if (channels[chn].state != SIDFX_IDLE) if (channels[chn].state != SIDFX_IDLE)
{
channels[chn].state = SIDFX_RESET_0; channels[chn].state = SIDFX_RESET_0;
channels[chn].delay = 1;
}
} }
inline void sidfx_loop_ch(byte ch) inline void sidfx_loop_ch(byte ch)
{
if (channels[ch].state)
{
const SIDFX * com = channels[ch].com;
channels[ch].delay--;
if (channels[ch].delay)
{
if (com->dfreq)
{
channels[ch].freq += com->dfreq;
sid.voices[ch].freq = channels[ch].freq;
}
if (com->dpwm)
{
channels[ch].pwm += com->dpwm;
sid.voices[ch].pwm = channels[ch].pwm;
}
}
while (!channels[ch].delay)
{ {
switch (channels[ch].state) switch (channels[ch].state)
{ {
case SIDFX_IDLE: case SIDFX_IDLE:
channels[ch].delay = 1;
break; break;
case SIDFX_RESET_0: case SIDFX_RESET_0:
sid.voices[ch].ctrl = 0; sid.voices[ch].ctrl = 0;
sid.voices[ch].attdec = 0; sid.voices[ch].attdec = 0;
sid.voices[ch].susrel = 0; sid.voices[ch].susrel = 0;
channels[ch].state = SIDFX_RESET_1; if (com)
channels[ch].state = SIDFX_READY;
else
channels[ch].state = SIDFX_IDLE;
channels[ch].delay = 1;
break; break;
case SIDFX_RESET_1: case SIDFX_RESET_1:
sid.voices[ch].ctrl = SID_CTRL_TEST; sid.voices[ch].ctrl = SID_CTRL_TEST;
sid.voices[ch].ctrl = 0;
sid.voices[ch].attdec = 0;
sid.voices[ch].susrel = 0;
channels[ch].state = SIDFX_READY; channels[ch].state = SIDFX_READY;
break; break;
case SIDFX_READY: case SIDFX_READY:
if (channels[ch].com) channels[ch].freq = com->freq;
channels[ch].pwm = com->pwm;
sid.voices[ch].freq = com->freq;
sid.voices[ch].pwm = com->pwm;
sid.voices[ch].attdec = com->attdec;
sid.voices[ch].susrel = com->susrel;
sid.voices[ch].ctrl = com->ctrl;
if (com->ctrl & SID_CTRL_GATE)
{ {
channels[ch].freq = channels[ch].com->freq; channels[ch].delay = com->time1;
channels[ch].pwm = channels[ch].com->pwm;
sid.voices[ch].freq = channels[ch].com->freq;
sid.voices[ch].pwm = channels[ch].com->pwm;
sid.voices[ch].attdec = channels[ch].com->attdec;
sid.voices[ch].susrel = channels[ch].com->susrel;
sid.voices[ch].ctrl = channels[ch].com->ctrl;
channels[ch].delay = channels[ch].com->time1;
channels[ch].state = SIDFX_PLAY; channels[ch].state = SIDFX_PLAY;
} }
else else
channels[ch].state = SIDFX_IDLE; {
channels[ch].delay = com->time0;
channels[ch].state = SIDFX_PLAY;
}
break; break;
case SIDFX_PLAY: case SIDFX_PLAY:
if (channels[ch].com->dfreq) if (com->time0)
{ {
channels[ch].freq += channels[ch].com->dfreq; sid.voices[ch].ctrl = com->ctrl & ~SID_CTRL_GATE;
sid.voices[ch].freq = channels[ch].freq; channels[ch].delay = com->time0 - 1;
}
if (channels[ch].com->dpwm)
{
channels[ch].pwm += channels[ch].com->dpwm;
sid.voices[ch].pwm = channels[ch].pwm;
}
if (channels[ch].delay)
channels[ch].delay--;
else if (channels[ch].com->time0)
{
sid.voices[ch].ctrl = channels[ch].com->ctrl & ~SID_CTRL_GATE;
channels[ch].delay = channels[ch].com->time0;
channels[ch].state = SIDFX_WAIT; channels[ch].state = SIDFX_WAIT;
} }
else if (channels[ch].cnt) else if (channels[ch].cnt)
{ {
char sr = com->susrel & 0xf0;
com++;
char ctrl = com->ctrl;
if ((com->attdec & 0xef) == 0 && (ctrl & SID_CTRL_GATE) && (com->susrel & 0xf0) > sr)
{
sid.voices[ch].ctrl = ctrl & ~SID_CTRL_GATE;
sid.voices[ch].ctrl = ctrl | SID_CTRL_GATE;
}
channels[ch].cnt--; channels[ch].cnt--;
channels[ch].com++; channels[ch].com = com;
channels[ch].priority = channels[ch].com->priority; channels[ch].priority = com->priority;
channels[ch].state = SIDFX_READY; channels[ch].state = SIDFX_READY;
} }
else else
{ {
channels[ch].com = nullptr; com = nullptr;
channels[ch].state = SIDFX_RESET_0; channels[ch].state = SIDFX_RESET_0;
} }
break; break;
case SIDFX_WAIT: case SIDFX_WAIT:
if (channels[ch].com->dfreq) if (channels[ch].cnt)
{
channels[ch].freq += channels[ch].com->dfreq;
sid.voices[ch].freq = channels[ch].freq;
}
if (channels[ch].com->dpwm)
{
channels[ch].pwm += channels[ch].com->dpwm;
sid.voices[ch].pwm = channels[ch].pwm;
}
if (channels[ch].delay)
channels[ch].delay--;
else if (channels[ch].cnt)
{ {
com++;
channels[ch].cnt--; channels[ch].cnt--;
channels[ch].com++; channels[ch].com = com;
channels[ch].priority = channels[ch].com->priority; channels[ch].priority = com->priority;
if (com->ctrl & SID_CTRL_GATE)
channels[ch].state = SIDFX_RESET_0; channels[ch].state = SIDFX_RESET_0;
else
channels[ch].state = SIDFX_READY;
} }
else else
{ {
channels[ch].com = nullptr; com = nullptr;
channels[ch].state = SIDFX_RESET_0; channels[ch].state = SIDFX_RESET_0;
} }
break; break;
} }
} }
}
}
void sidfx_loop_2(void) void sidfx_loop_2(void)
{ {

View File

@ -14,10 +14,14 @@ struct SIDFX
void sidfx_init(void); void sidfx_init(void);
inline bool sidfx_idle(byte chn);
inline void sidfx_play(byte chn, const SIDFX * fx, byte cnt); inline void sidfx_play(byte chn, const SIDFX * fx, byte cnt);
void sidfx_stop(byte chn); void sidfx_stop(byte chn);
char sidfx_cnt(byte chn);
void sidfx_loop(void); void sidfx_loop(void);
void sidfx_loop_2(void); void sidfx_loop_2(void);

View File

@ -27,6 +27,7 @@ struct XMMU
#define xmmu (*((struct XMMU *)0xd500)) #define xmmu (*((struct XMMU *)0xd500))
inline char mmu_set(char cr);
#pragma compile("mmu.c") #pragma compile("mmu.c")

View File

@ -34,8 +34,11 @@ byte vdc_reg_read(VDCRegister reg)
void vdc_mem_addr(unsigned addr) void vdc_mem_addr(unsigned addr)
{ {
#pragma callinline()
vdc_reg_write(VDCR_ADDRH, addr >> 8); vdc_reg_write(VDCR_ADDRH, addr >> 8);
#pragma callinline()
vdc_reg_write(VDCR_ADDRL, addr); vdc_reg_write(VDCR_ADDRL, addr);
#pragma callinline()
vdc_reg(VDCR_DATA); vdc_reg(VDCR_DATA);
} }
@ -52,12 +55,14 @@ inline char vdc_mem_read(void)
void vdc_mem_write_at(unsigned addr, char data) void vdc_mem_write_at(unsigned addr, char data)
{ {
#pragma callinline()
vdc_mem_addr(addr); vdc_mem_addr(addr);
vdc_write(data); vdc_write(data);
} }
char vdc_mem_read_at(unsigned addr) char vdc_mem_read_at(unsigned addr)
{ {
#pragma callinline()
vdc_mem_addr(addr); vdc_mem_addr(addr);
return vdc_read(); return vdc_read();
} }

View File

@ -16,7 +16,7 @@ void cia_init(void)
cia2.ddrb = 0x00; cia2.ddrb = 0x00;
cia1.ddra = 0xff; cia1.ddra = 0xff;
cia2.prb = 0x07; cia2.pra = 0x07;
cia2.ddra = 0x3f; cia2.ddra = 0x3f;
char i0 = cia1.icr; char i0 = cia1.icr;

View File

@ -18,6 +18,46 @@ struct EasyFlash
#define eflash (*(EasyFlash *)0xde00) #define eflash (*(EasyFlash *)0xde00)
#ifdef __cplusplus
#ifdef EFPROX_SECTION
#pragma code(EFPROX_SECTION)
#endif
template<int back, class fn, class ... P>
__noinline auto ef_call_p(P... p)
{
if (back != __bankof(fn))
eflash.bank = __bankof(fn);
auto r = fn(p...);
if (back != 0xff && back != __bankof(fn))
eflash.bank = back;
return r;
}
#ifdef EFPROX_SECTION
#pragma code(code)
#endif
template<class fn>
class EFlashCall
{
public:
template<class ... P>
__forceinline auto operator()(P ... p) const
{
switch(__bankof(0))
{
#for(i,64) case i: return ef_call_p<i, fn, P...>(p...);
default:
return ef_call_p<0xff, fn, P...>(p...);
}
}
};
#define EF_CALL(fn) EFlashCall<fn##_p> fn
#endif
#endif #endif

608
include/c64/flossiec.c Normal file
View File

@ -0,0 +1,608 @@
#include "flossiec.h"
#include <c64/iecbus.h>
#include <c64/vic.h>
#include <c64/cia.h>
#include <c64/kernalio.h>
#ifndef FLOSSIEC_NODISPLAY
#define FLOSSIEC_NODISPLAY 0
#endif
#ifndef FLOSSIEC_NOIRQ
#define FLOSSIEC_NOIRQ 0
#endif
#ifndef FLOSSIEC_BORDER
#define FLOSSIEC_BORDER 0
#endif
#define VIA_ATNIN 0x80
#define VIA_ATNOUT 0x10
#define VIA_CLKOUT 0x08
#define VIA_DATAOUT 0x02
#define VIA_CLKIN 0x04
#define VIA_DATAIN 0x01
#define PORTB1 0x1800
#define PORTB2 0x1c00
#define WR 0x1d
#ifdef FLOSSIEC_CODE
#pragma code(FLOSSIEC_CODE)
#endif
#ifdef FLOSSIEC_BSS
#pragma bss(FLOSSIEC_BSS)
#endif
__asm diskcode
{
nop
nop
lda #VIA_CLKOUT
sta PORTB1
lda 0x0202
sta 0x0c
lda 0x0203
sta 0x0d
lda #$80
sta 0x03
ldx #0
l0:
txa
lsr
lsr
lsr
lsr
sta 0x0700,x
inx
bne l0
lr:
lda 0x03
bmi lr
sei
ldx #0
l2:
lda #0
sta PORTB1
lda 0x0600, x
tay
and #0x0f
ora #VIA_DATAIN
l1:
bit PORTB1
bne l1
l3:
sta PORTB1
tya
asl
and #0x0a
sta PORTB1
lda 0x0700,y
nop
sta PORTB1
asl
nop
and #0x0a
sta PORTB1
inx
bne l2
lda #VIA_CLKOUT
sta PORTB1
lda 0x0600
beq w1
sta 0x0c
lda 0x0601
sta 0x0d
lda #$80
sta 0x03
cli
bne lr
w1:
sta PORTB1
cli
rts
}
#define CIA2B_ATNOUT 0x08
#define CIA2B_CLKOUT 0x10
#define CIA2B_DATAOUT 0x20
#define CIA2B_CLKIN 0x40
#define CIA2B_DATAIN 0x80
#define CIA2PRA 0xdd00
static char remap[256];
static char rbuffer[256];
static char xbuffer[256];
static char flpos;
static char xcmd;
static char xi, xj;
static char fldrive;
static char flvxor;
__noinline void fl_read_buf(void)
{
__asm
{
#if FLOSSIEC_NOIRQ
php
sei
#endif
lda CIA2PRA
and #~CIA2B_CLKOUT
sta accu
sta CIA2PRA
and #~CIA2B_DATAOUT
sta accu + 1
l0:
lda CIA2PRA
and #CIA2B_CLKIN
beq l0
#if !FLOSSIEC_NOIRQ
php
pla
and #$04
beq iq
#endif
ldy #0
sec
l1:
ldx accu + 1
#if !FLOSSIEC_NODISPLAY
l2:
lda 0xd012
sbc #50
bcc w1
and #7
beq l2
#endif
w1:
stx CIA2PRA
#if FLOSSIEC_BORDER
inc 0xd020
#else
nop
nop
nop
#endif
ldx accu
nop
lda CIA2PRA
lsr
lsr
nop
eor CIA2PRA
lsr
lsr
nop
eor CIA2PRA
lsr
lsr
sec
eor CIA2PRA
stx CIA2PRA
sta rbuffer, y
iny
bne l1
jmp done
#if !FLOSSIEC_NOIRQ
iq:
ldy #0
sec
l1i:
ldx accu + 1
l2i:
cli
sei
#if !FLOSSIEC_NODISPLAY
lda 0xd012
sbc #50
bcc w1i
and #7
beq l2i
w1i:
#endif
stx CIA2PRA
#if FLOSSIEC_BORDER
inc 0xd020
#else
nop
nop
nop
#endif
ldx accu
nop
lda CIA2PRA
lsr
lsr
nop
eor CIA2PRA
lsr
lsr
nop
eor CIA2PRA
lsr
lsr
sec
eor CIA2PRA
stx CIA2PRA
sta rbuffer, y
iny
bne l1i
cli
#endif
done:
#if FLOSSIEC_NOIRQ
plp
#endif
}
}
inline char flossiec_get(void)
{
if (!flpos)
{
fl_read_buf();
flpos = 2;
}
return remap[rbuffer[flpos++]];
}
void flossiec_decompress(void)
{
char i = 0, j = xj, cmd = xcmd;
xi = 0;
for(;;)
{
if (cmd & 0x80)
{
if (i < cmd)
{
char t = i - cmd;
do {
char ch = xbuffer[j++];
xbuffer[i++] = ch;
} while (i != t);
cmd = 0;
}
else
{
cmd -= i;
do {
char ch = xbuffer[j++];
xbuffer[i++] = ch;
} while (i);
break;
}
}
else
{
char ch = flossiec_get();
if (cmd)
{
xbuffer[i++] = ch;
cmd--;
if (!i)
break;
}
else
{
cmd = ch;
if (!cmd)
break;
if (cmd & 0x80)
{
cmd ^= 0x7f;
cmd++;
j = i - flossiec_get();
}
}
}
}
xj = j;
xcmd = cmd;
}
inline char flossiec_get_lzo(void)
{
if (!xi)
flossiec_decompress();
return xbuffer[xi++];
}
inline bool flossiec_eof(void)
{
return !remap[rbuffer[0]] && flpos >= remap[rbuffer[1]];
}
char * flossiec_read(char * dp, unsigned size)
{
while (size)
{
*dp++ = flossiec_get();
size--;
}
return dp;
}
char * flossiec_read_lzo(char * dp, unsigned size)
{
char i = xi;
dp -= i;
size += i;
while (size)
{
if (!i)
flossiec_decompress();
if (size >= 256)
{
do {
dp[i] = xbuffer[i];
i++;
} while (i);
dp += 256;
size -= 256;
}
else
{
do {
dp[i] = xbuffer[i];
i++;
} while (i != (char)size);
dp += i;
break;
}
}
xi = i;
return dp;
}
static void vxorcheck(void)
{
char vxor = cia2.pra & 7;
vxor ^= vxor >> 2;
vxor ^= 0xff;
if (vxor != flvxor)
{
flvxor = vxor;
for(int i=0; i<256; i++)
{
char j = i ^ vxor;
char d = ((j & 0x11) << 3) |
(j & 0x66) |
((j & 0x88) >> 3);
remap[i] = d;
}
}
}
bool flossiec_init(char drive)
{
fldrive = drive;
flvxor = 0;
iec_open(drive, 2, "#2");
iec_listen(drive, 2);
for(char j=0; j<127; j++)
iec_write(((char *)diskcode)[j]);
iec_unlisten();
iec_close(drive, 2);
iec_open(drive, 15, "");
return true;
}
void flossiec_shutdown(void)
{
iec_close(fldrive, 15);
}
bool flossiec_open(char track, char sector)
{
iec_listen(fldrive, 15);
iec_write(P'U');
iec_write(P'4');
iec_write(track);
iec_write(sector);
iec_unlisten();
cia2.pra |= CIA2B_DATAOUT;
#if FLOSSIEC_NODISPLAY
vic.ctrl1 &= ~VIC_CTRL1_DEN;
#endif
vic_waitFrame();
vxorcheck();
vic_waitFrame();
flpos = 0;
xi = 0;
return true;
}
void flossiec_close(void)
{
cia2.pra |= CIA2B_DATAOUT;
#if FLOSSIEC_NODISPLAY
vic.ctrl1 |= VIC_CTRL1_DEN;
#endif
}
bool flosskio_init(char drive)
{
fldrive = drive;
flvxor = 0;
krnio_setnam_n("#2", 2);
krnio_open(2, drive, 2);
krnio_write(2, (char *)diskcode, 128);
krnio_close(2);
krnio_setnam_n(nullptr, 0);
krnio_open(15, drive, 15);
return true;
}
void flosskio_shutdown(void)
{
krnio_close(15);
}
bool flosskio_open(char track, char sector)
{
krnio_chkout(15);
krnio_chrout(P'U');
krnio_chrout(P'4');
krnio_chrout(track);
krnio_chrout(sector);
krnio_clrchn();
cia2.pra |= CIA2B_DATAOUT;
#if FLOSSIEC_NODISPLAY
vic.ctrl1 &= ~VIC_CTRL1_DEN;
#endif
vic_waitFrame();
vxorcheck();
vic_waitFrame();
flpos = 0;
xi = 0;
return true;
}
void flosskio_close(void)
{
cia2.pra |= CIA2B_DATAOUT;
#if FLOSSIEC_NODISPLAY
vic.ctrl1 |= VIC_CTRL1_DEN;
#endif
}
static bool mapdir(const char * fnames, floss_blk * blks)
{
do {
fl_read_buf();
char si = 0;
do
{
if (remap[rbuffer[si + 2]] == 0x82)
{
char fname[17];
char j = 0;
while (j < 16 && remap[rbuffer[si + j + 5]] != 0xa0)
{
fname[j] = remap[rbuffer[si + j + 5]];
j++;
}
fname[j] = 0;
char sj = 0;
char k = 0;
while (fnames[sj])
{
j = 0;
while (fname[j] && fname[j] == fnames[sj])
{
j++;
sj++;
}
if (!fname[j] && (!fnames[sj] || fnames[sj] == ','))
{
__assume(k < 128);
blks[k].track = remap[rbuffer[si + 3]];
blks[k].sector = remap[rbuffer[si + 4]];
break;
}
while (fnames[sj] && fnames[sj++] != ',')
;
k++;
}
}
si += 32;
} while (si);
} while (remap[rbuffer[0]]);
return true;
}
bool flosskio_mapdir(const char * fnames, floss_blk * blks)
{
if (flosskio_open(18, 1))
{
mapdir(fnames, blks);
flosskio_close();
return true;
}
return false;
}
bool flossiec_mapdir(const char * fnames, floss_blk * blks)
{
if (flossiec_open(18, 1))
{
mapdir(fnames, blks);
flossiec_close();
return true;
}
return false;
}

79
include/c64/flossiec.h Normal file
View File

@ -0,0 +1,79 @@
#ifndef FLOSSIEC_H
#define FLOSSIEC_H
// When building you can use various defines to change the behaviour
// FLOSSIEC_BORDER=1 Enable border flashing while loading
// FLOSSIEC_NODISPLAY=1 Disable the display while loading
// FLOSSIEC_NOIRQ=1 Disable IRQ during load
// FLOSSIEC_CODE=cseg Code segment to be used, when defined
// FLOSSIEC_BSS=bseg BSS segment to be used, when defined
// Initialize the fastloader to be used without the kernal
bool flossiec_init(char drive);
// Shutdown the fastloader when used without the kernal
void flossiec_shutdown(void);
// Open a file for read with the fastloader without the kernal.
// The file has to be read to completion before you can close
// it again,
bool flossiec_open(char track, char sector);
// Close a file after reading
void flossiec_close(void);
// Initialize the fastloader to be used with the kernal
bool flosskio_init(char drive);
// Shutdown the fastloader when used with the kernal
void flosskio_shutdown(void);
// Open a file for read with the fastloader with the kernal
// The file has to be read to completion before you can close
// it again,
bool flosskio_open(char track, char sector);
// Close a file after reading
void flosskio_close(void);
// Track and sector start of a file
struct floss_blk
{
char track, sector;
};
// Map a comma separated list of filenames to an array of
// block start positions by reading the directory, using the
// kernal.
bool flosskio_mapdir(const char * fnames, floss_blk * blks);
// Map a comma separated list of filenames to an array of
// block start positions by reading the directory, without the
// kernal.
bool flossiec_mapdir(const char * fnames, floss_blk * blks);
// Check for end of file while reading
inline bool flossiec_eof(void);
// Get one char from uncompressed file
inline char flossiec_get(void);
// Get one char from compressed file
inline char flossiec_get_lzo(void);
// Read a section of a file into memory up to size bytes,
// returns the first address after the read
char * flossiec_read(char * dp, unsigned size);
// Read and expand section of a file into memory up to size
// bytes, returns the first address after the read
char * flossiec_read_lzo(char * dp, unsigned size);
#pragma compile("flossiec.c")
#endif

View File

@ -3,6 +3,7 @@
#include <c64/vic.h> #include <c64/vic.h>
IEC_STATUS iec_status; IEC_STATUS iec_status;
char iec_queue;
#define CIA2B_ATNOUT 0x08 #define CIA2B_ATNOUT 0x08
#define CIA2B_CLKOUT 0x10 #define CIA2B_CLKOUT 0x10
@ -25,46 +26,59 @@ static void delay(char n)
} }
} }
static inline void data_low(void) static inline void data_true(void)
{ {
cia2.pra &= ~CIA2B_DATAOUT; cia2.pra &= ~CIA2B_DATAOUT;
} }
static inline void data_high(void) static inline void data_false(void)
{ {
cia2.pra |= CIA2B_DATAOUT; cia2.pra |= CIA2B_DATAOUT;
} }
static inline void clock_low(void) static inline void clock_true(void)
{ {
cia2.pra &= ~CIA2B_CLKOUT; cia2.pra &= ~CIA2B_CLKOUT;
} }
static inline void cdata_low(void) static inline void cdata_true(void)
{ {
cia2.pra &= ~(CIA2B_CLKOUT | CIA2B_DATAOUT); cia2.pra &= ~(CIA2B_CLKOUT | CIA2B_DATAOUT);
} }
static inline void clock_high(void) static inline void clock_false(void)
{ {
cia2.pra |= CIA2B_CLKOUT; cia2.pra |= CIA2B_CLKOUT;
} }
static inline void atn_low(void) static inline void atn_true(void)
{ {
cia2.pra &= ~CIA2B_ATNOUT; cia2.pra &= ~CIA2B_ATNOUT;
} }
static inline void atn_high(void) static inline void atn_false(void)
{ {
cia2.pra |= CIA2B_ATNOUT; cia2.pra |= CIA2B_ATNOUT;
} }
static inline bool data_in(void)
{
return (cia2.pra & CIA2B_DATAIN) != 0;
}
static inline bool clock_in(void)
{
return (cia2.pra & CIA2B_CLKIN) != 0;
}
static bool data_check(void) static bool data_check(void)
{ {
char cnt = 100; char cnt = 200;
while (cnt > 0 && (cia2.pra & CIA2B_DATAIN)) while (cnt > 0 && data_in())
{
delay(5);
cnt--; cnt--;
}
if (cnt) if (cnt)
return true; return true;
@ -75,68 +89,106 @@ static bool data_check(void)
} }
} }
bool iec_eoi(void) static bool iec_eoib(void)
{ {
cdata_low(); clock_true();
while (!data_in());
while (!(cia2.pra & CIA2B_DATAIN))
;
delay(40); delay(40);
return data_check(); return data_check();
} }
bool iec_write(char b) static void iec_writeb(char b)
{ {
cdata_low(); clock_true();
while (!(cia2.pra & CIA2B_DATAIN)) while (!data_in());
;
clock_high();
delay(5);
for(char i=0; i<8; i++) for(char i=0; i<8; i++)
{ {
if (b & 1) clock_false();
data_low();
else
data_high();
delay(5); delay(5);
clock_low(); if (b & 1)
data_true();
else
data_false();
clock_true();
b >>= 1; b >>= 1;
delay(5); delay(5);
clock_high(); }
data_low(); clock_false();
data_true();
} }
return data_check(); bool iec_write(char b)
{
if (iec_status == IEC_QUEUED)
{
__asm
{
php
sei
}
iec_status = IEC_OK;
iec_writeb(iec_queue);
__asm
{
plp
}
data_check();
}
if (iec_status < IEC_ERROR)
{
iec_queue = b;
iec_status = IEC_QUEUED;
return true;
}
return false;
} }
char iec_read(void) char iec_read(void)
{ {
while (!(cia2.pra & CIA2B_CLKIN)) while (!clock_in());
;
data_low(); __asm
{
php
sei
}
data_true();
char cnt = 100; char cnt = 100;
while (cnt > 0 && (cia2.pra & CIA2B_CLKIN)) while (cnt > 0 && clock_in())
cnt--; cnt--;
if (cnt == 0) if (cnt == 0)
{ {
iec_status = IEC_EOF; iec_status = IEC_EOF;
data_high(); data_false();
delay(4); delay(10);
data_low(); data_true();
cnt = 200; cnt = 200;
while (cnt > 0 && (cia2.pra & CIA2B_CLKIN)) while (cnt > 0 && clock_in())
cnt--; cnt--;
if (cnt == 0) if (cnt == 0)
{ {
iec_status = IEC_TIMEOUT; iec_status = IEC_TIMEOUT;
__asm
{
plp
}
return 0; return 0;
} }
} }
@ -155,25 +207,36 @@ char iec_read(void)
; ;
} }
data_high(); data_false();
__asm
{
plp
}
return b; return b;
} }
void iec_atn(char dev, char sec) void iec_atn(char dev, char sec)
{ {
cdata_low(); clock_true();
atn_high(); data_true();
clock_high(); atn_false();
clock_false();
delay(200); delay(200);
iec_write(dev); while (data_in());
if (sec != 0xff)
iec_write(sec);
data_high(); iec_writeb(dev);
atn_low(); data_check();
if (sec != 0xff)
{
iec_writeb(sec);
data_check();
}
atn_true();
} }
@ -182,7 +245,23 @@ void iec_talk(char dev, char sec)
iec_status = IEC_OK; iec_status = IEC_OK;
iec_atn(dev | 0x40, sec | 0x60); iec_atn(dev | 0x40, sec | 0x60);
clock_low(); data_false();
__asm
{
php
sei
}
clock_true();
char cnt = 200;
while (cnt > 0 && clock_in())
cnt--;
__asm
{
plp
}
delay(10); delay(10);
} }
@ -201,7 +280,27 @@ void iec_listen(char dev, char sec)
void iec_unlisten(void) void iec_unlisten(void)
{ {
__asm
{
php
sei
}
if (iec_status == IEC_QUEUED)
{
iec_status = IEC_OK;
iec_eoib();
iec_writeb(iec_queue);
data_check();
}
iec_atn(0x3f, 0xff); iec_atn(0x3f, 0xff);
clock_true();
__asm
{
plp
}
} }
void iec_open(char dev, char sec, const char * fname) void iec_open(char dev, char sec, const char * fname)
@ -213,8 +312,6 @@ void iec_open(char dev, char sec, const char * fname)
char i = 0; char i = 0;
while (fname[i]) while (fname[i])
{ {
if (!fname[i + 1])
iec_eoi();
iec_write(fname[i]); iec_write(fname[i]);
i++; i++;
} }
@ -239,7 +336,7 @@ int iec_write_bytes(const char * data, int num)
int iec_read_bytes(char * data, int num) int iec_read_bytes(char * data, int num)
{ {
char i = 0; int i = 0;
while (i < num) while (i < num)
{ {
char ch = iec_read(); char ch = iec_read();

View File

@ -5,6 +5,7 @@ enum IEC_STATUS
{ {
IEC_OK = 0x00, IEC_OK = 0x00,
IEC_EOF = 0x01, IEC_EOF = 0x01,
IEC_QUEUED = 0x02,
IEC_ERROR = 0x80, IEC_ERROR = 0x80,
IEC_TIMEOUT, IEC_TIMEOUT,
@ -13,8 +14,6 @@ enum IEC_STATUS
extern IEC_STATUS iec_status; extern IEC_STATUS iec_status;
bool iec_eoi(void);
bool iec_write(char b); bool iec_write(char b);
char iec_read(void); char iec_read(void);

View File

@ -16,7 +16,18 @@ void krnio_setbnk(char filebank, char namebank)
#pragma native(krnio_setbnk) #pragma native(krnio_setbnk)
#endif #endif
void krnio_setnam(const char * name) #if defined(__PLUS4__)
#pragma code(lowcode)
#define BANKIN sta 0xff3e
#define BANKOUT sta 0xff3f
#define BANKINLINE __noinline
#else
#define BANKIN
#define BANKOUT
#define BANKINLINE
#endif
BANKINLINE void krnio_setnam(const char * name)
{ {
__asm __asm
{ {
@ -31,35 +42,41 @@ void krnio_setnam(const char * name)
tya tya
W1: ldx name W1: ldx name
ldy name + 1 ldy name + 1
BANKIN
jsr $ffbd // setnam jsr $ffbd // setnam
BANKOUT
} }
} }
#pragma native(krnio_setnam) #pragma native(krnio_setnam)
void krnio_setnam_n(const char * name, char len) BANKINLINE void krnio_setnam_n(const char * name, char len)
{ {
__asm __asm
{ {
lda len lda len
ldx name ldx name
ldy name + 1 ldy name + 1
BANKIN
jsr $ffbd // setnam jsr $ffbd // setnam
BANKOUT
} }
} }
#pragma native(krnio_setnam_n) #pragma native(krnio_setnam_n)
bool krnio_open(char fnum, char device, char channel) BANKINLINE bool krnio_open(char fnum, char device, char channel)
{ {
krnio_pstatus[fnum] = KRNIO_OK; krnio_pstatus[fnum] = KRNIO_OK;
__asm return char(__asm
{ {
lda #0 lda #0
sta accu sta accu
sta accu + 1 sta accu + 1
BANKIN
lda fnum lda fnum
ldx device ldx device
ldy channel ldy channel
@ -74,42 +91,48 @@ bool krnio_open(char fnum, char device, char channel)
W1: W1:
lda #1 lda #1
sta accu sta accu
E2:
}
BANKOUT
E2:
});
} }
#pragma native(krnio_open) #pragma native(krnio_open)
void krnio_close(char fnum) BANKINLINE void krnio_close(char fnum)
{ {
__asm __asm
{ {
BANKIN
lda fnum lda fnum
jsr $ffc3 // close jsr $ffc3 // close
BANKOUT
} }
} }
#pragma native(krnio_close) #pragma native(krnio_close)
krnioerr krnio_status(void) BANKINLINE krnioerr krnio_status(void)
{ {
__asm return __asm
{ {
BANKIN
jsr $ffb7 // readst jsr $ffb7 // readst
BANKOUT
sta accu sta accu
lda #0 lda #0
sta accu + 1 sta accu + 1
} };
} }
#pragma native(krnio_status) #pragma native(krnio_status)
bool krnio_load(char fnum, char device, char channel) BANKINLINE bool krnio_load(char fnum, char device, char channel)
{ {
__asm return char(__asm
{ {
BANKIN
lda fnum lda fnum
ldx device ldx device
ldy channel ldy channel
@ -119,20 +142,22 @@ bool krnio_load(char fnum, char device, char channel)
ldx #0 ldx #0
ldy #0 ldy #0
jsr $FFD5 // load jsr $FFD5 // load
BANKOUT
lda #0 lda #0
bcs W1 rol
lda #1 eor #1
W1: sta accu sta accu
} });
} }
#pragma native(krnio_load) #pragma native(krnio_load)
bool krnio_save(char device, const char* start, const char* end) BANKINLINE bool krnio_save(char device, const char* start, const char* end)
{ {
__asm return char(__asm
{ {
BANKIN
lda #0 lda #0
ldx device ldx device
ldy #0 ldy #0
@ -143,83 +168,96 @@ bool krnio_save(char device, const char* start, const char* end)
ldy end+1 ldy end+1
jsr $FFD8 // save jsr $FFD8 // save
BANKOUT
lda #0 lda #0
bcs W1 rol
lda #1 eor #1
W1: sta accu sta accu
} });
} }
#pragma native(krnio_save) #pragma native(krnio_save)
bool krnio_chkout(char fnum) BANKINLINE bool krnio_chkout(char fnum)
{ {
__asm return char(__asm
{ {
BANKIN
ldx fnum ldx fnum
jsr $ffc9 // chkout jsr $ffc9 // chkout
BANKOUT
lda #0 lda #0
bcs W1 rol
lda #1 eor #1
W1: sta accu sta accu
} });
} }
#pragma native(krnio_chkout) #pragma native(krnio_chkout)
bool krnio_chkin(char fnum) BANKINLINE bool krnio_chkin(char fnum)
{ {
__asm return char(__asm
{ {
BANKIN
ldx fnum ldx fnum
jsr $ffc6 // chkin jsr $ffc6 // chkin
BANKOUT
lda #0 lda #0
sta accu + 1 rol
bcs W1 eor #1
lda #1 sta accu
W1: sta accu });
}
} }
#pragma native(krnio_chkin) #pragma native(krnio_chkin)
void krnio_clrchn(void) BANKINLINE void krnio_clrchn(void)
{ {
__asm __asm
{ {
BANKIN
jsr $ffcc // clrchn jsr $ffcc // clrchn
BANKOUT
} }
} }
#pragma native(krnio_clrchn) #pragma native(krnio_clrchn)
bool krnio_chrout(char ch) BANKINLINE bool krnio_chrout(char ch)
{ {
__asm return char(__asm
{ {
BANKIN
lda ch lda ch
jsr $ffd2 // chrout jsr $ffd2 // chrout
sta accu sta accu
lda #0 BANKOUT
sta accu + 1 });
}
} }
#pragma native(krnio_chrout) #pragma native(krnio_chrout)
int krnio_chrin(void) BANKINLINE char krnio_chrin(void)
{ {
__asm return __asm
{ {
BANKIN
jsr $ffcf // chrin jsr $ffcf // chrin
sta accu sta accu
lda #0 BANKOUT
sta accu + 1 };
}
} }
#pragma native(krnio_chrin) #pragma native(krnio_chrin)
#if defined(__PLUS4__)
#pragma code(code)
#endif
int krnio_getch(char fnum) int krnio_getch(char fnum)
{ {
if (krnio_pstatus[fnum] == KRNIO_EOF) if (krnio_pstatus[fnum] == KRNIO_EOF)
@ -383,7 +421,7 @@ int krnio_gets(char fnum, char * data, int num)
if (krnio_chkin(fnum)) if (krnio_chkin(fnum))
{ {
krnioerr err; krnioerr err = KRNIO_OK;
int i = 0; int i = 0;
int ch; int ch;
while (i + 1 < num) while (i + 1 < num)

View File

@ -1,5 +1,5 @@
#ifndef C64_KERNALIO_H #ifndef C64_KERNALIO_H
#ifndef C64_KERNALIO_H #define C64_KERNALIO_H
// Error and status codes returned by krnio_status // Error and status codes returned by krnio_status
@ -64,7 +64,7 @@ bool krnio_chrout(char ch);
// read a single byte from the current input channel // read a single byte from the current input channel
int krnio_chrin(void); char krnio_chrin(void);
// read a single byte from the given file/channel, returns // read a single byte from the given file/channel, returns
// a negative result on failure. If this was the last byte // a negative result on failure. If this was the last byte

View File

@ -5,16 +5,16 @@
#include <c64/asm6502.h> #include <c64/asm6502.h>
#include <stdlib.h> #include <stdlib.h>
volatile char npos = 1, tpos = 0;
volatile byte rirq_count; volatile byte rirq_count;
static byte rirq_pcount;
byte rasterIRQRows[NUM_IRQS + 1]; byte rasterIRQRows[NUM_IRQS + 1];
byte rasterIRQIndex[NUM_IRQS + 1]; byte rasterIRQIndex[NUM_IRQS + 1]; // Sort order of interrupt index, offset by one
#ifdef ZPAGE_IRQS #ifdef ZPAGE_IRQS
__zeropage __zeropage
#endif #endif
byte rasterIRQNext[NUM_IRQS + 1]; byte rasterIRQNext[NUM_IRQS + 1]; // Rasterline of interrupt, terminated by 0xff
byte rasterIRQLow[NUM_IRQS]; byte rasterIRQLow[NUM_IRQS]; // Address of interrupt code
byte rasterIRQHigh[NUM_IRQS]; byte rasterIRQHigh[NUM_IRQS];
#ifdef ZPAGE_IRQS #ifdef ZPAGE_IRQS
@ -22,28 +22,25 @@ __zeropage
#endif #endif
byte nextIRQ; byte nextIRQ;
__asm irq0 // nextIRQ is the index of the next expected IRQ, or $ff if no IRQ is scheduled
{
pha
txa
pha
tya
pha
asl $d019 __asm rirq_isr_ram_io
{
stx plrx + 1
ldx nextIRQ ldx nextIRQ
bmi exi
sta plra + 1
sty plry + 1
l1: l1:
lda rasterIRQNext, x lda rasterIRQNext, x
cmp #$ff
beq e1
ldy rasterIRQIndex + 1, x ldy rasterIRQIndex + 1, x
tax ldx rasterIRQLow, y
lda rasterIRQLow, y stx ji + 1
sta ji + 1 ldx rasterIRQHigh, y
lda rasterIRQHigh, y stx ji + 2
sta ji + 2
ji: ji:
jsr $0000 jsr $0000
@ -51,20 +48,82 @@ ji:
inc nextIRQ inc nextIRQ
ldx nextIRQ ldx nextIRQ
lda rasterIRQNext, x ldy rasterIRQNext, x
cmp #$ff
beq e2 asl $d019
// carry is cleared at this point
cpy #$ff
beq e2
tay
dey dey
sbc #2 sty $d012
cmp $d012 dey
cpy $d012
bcc l1 bcc l1
sty $d012 plry:
ldy #0
plra:
lda #0
plrx:
ldx #0
rti
ex: exi:
asl $d019
jmp plrx
// No more interrupts to service
e2:
inc rirq_count
ldy rasterIRQNext
dey
sty $d012
ldx #0
stx nextIRQ
beq plry
}
__asm rirq_isr_io
{
pha
txa
pha
tya
pha
kentry:
ldx nextIRQ
bmi exi
l1:
lda rasterIRQNext, x
ldy rasterIRQIndex + 1, x
ldx rasterIRQLow, y
stx ji + 1
ldx rasterIRQHigh, y
stx ji + 2
ji:
jsr $0000
inc nextIRQ
ldx nextIRQ
ldy rasterIRQNext, x
asl $d019
cpy #$ff
beq e2
dey
sty $d012
dey
cpy $d012
bcc l1
exd:
pla pla
tay tay
pla pla
@ -72,56 +131,44 @@ ex:
pla pla
rti rti
e2: exi:
asl $d019
jmp exd
ldx npos e2:
stx tpos
inc rirq_count inc rirq_count
bit $d011
bmi e1
sta $d012
jmp ex
e1:
ldx #0
stx nextIRQ
ldy rasterIRQNext ldy rasterIRQNext
dey dey
sty $d012 sty $d012
jmp ex ldx #0
stx nextIRQ
beq exd
} }
__asm irq2 __asm rirq_isr_noio
{ {
pha pha
txa txa
pha pha
tya tya
pha pha
kentry:
lda $01 lda $01
pha pha
lda #$35 lda #$35
sta $01 sta $01
asl $d019
ldx nextIRQ ldx nextIRQ
bmi exi
l1: l1:
lda rasterIRQNext, x lda rasterIRQNext, x
cmp #$ff
beq e1
ldy rasterIRQIndex + 1, x ldy rasterIRQIndex + 1, x
tax ldx rasterIRQLow, y
lda rasterIRQLow, y stx ji + 1
sta ji + 1 ldx rasterIRQHigh, y
lda rasterIRQHigh, y stx ji + 2
sta ji + 2
ji: ji:
jsr $0000 jsr $0000
@ -129,21 +176,20 @@ ji:
inc nextIRQ inc nextIRQ
ldx nextIRQ ldx nextIRQ
lda rasterIRQNext, x ldy rasterIRQNext, x
cmp #$ff
beq e2 asl $d019
// carry is cleared at this point
cpy #$ff
beq e2
tay
dey dey
sbc #2 sty $d012
cmp $d012 dey
cpy $d012
bcc l1 bcc l1
sty $d012 exd:
ex:
pla pla
sta $01 sta $01
@ -154,45 +200,35 @@ ex:
pla pla
rti rti
e2: exi:
asl $d019
jmp exd
ldx npos e2:
stx tpos
inc rirq_count inc rirq_count
bit $d011
bmi e1
sta $d012
jmp ex
e1:
ldx #0
stx nextIRQ
ldy rasterIRQNext ldy rasterIRQNext
dey dey
sty $d012 sty $d012
jmp ex ldx #0
stx nextIRQ
beq exd
} }
__asm irq1 __asm rirq_isr_kernal_io
{ {
lda $d019 lda $d019
bpl ex2 bpl ex2
ldx nextIRQ ldx nextIRQ
bmi exi
l1: l1:
lda rasterIRQNext, x lda rasterIRQNext, x
cmp #$ff
beq e1
ldy rasterIRQIndex + 1, x ldy rasterIRQIndex + 1, x
tax ldx rasterIRQLow, y
lda rasterIRQLow, y stx ji + 1
sta ji + 1 ldx rasterIRQHigh, y
lda rasterIRQHigh, y stx ji + 2
sta ji + 2
ji: ji:
jsr $0000 jsr $0000
@ -201,45 +237,36 @@ jx:
inc nextIRQ inc nextIRQ
ldx nextIRQ ldx nextIRQ
lda rasterIRQNext, x ldy rasterIRQNext, x
cmp #$ff
beq e2
tay
sec
sbc #4
cmp $d012
bcc l1
dey
sty $d012
w1:
jmp ex
e2:
ldx npos
stx tpos
inc rirq_count
bit $d011
bmi e1
sta $d012
jmp ex
e1:
ldx #0
stx nextIRQ
lda rasterIRQNext, x
sec
sbc #1
sta $d012
ex:
asl $d019 asl $d019
cpy #$ff
beq e2
dey
dey
sty $d012
dey
cpy $d012
bcc l1
exd:
jmp $ea81
exi:
asl $d019
jmp $ea81
e2:
inc rirq_count
ldy rasterIRQNext
dey
dey
sty $d012
ldx #0
stx nextIRQ
jmp $ea81 jmp $ea81
ex2: ex2:
@ -248,6 +275,76 @@ ex2:
jmp $ea31 jmp $ea31
} }
__asm rirq_isr_kernal_noio
{
lda $01
pha
lda #$36
sta $01
lda $d019
bpl ex2
ldx nextIRQ
bmi exi
l1:
lda rasterIRQNext, x
ldy rasterIRQIndex + 1, x
ldx rasterIRQLow, y
stx ji + 1
ldx rasterIRQHigh, y
stx ji + 2
ji:
jsr $0000
jx:
inc nextIRQ
ldx nextIRQ
ldy rasterIRQNext, x
asl $d019
cpy #$ff
beq e2
dey
dey
sty $d012
dey
cpy $d012
bcc l1
exd:
pla
sta $01
jmp $ea81
exi:
asl $d019
jmp exd
e2:
inc rirq_count
ldy rasterIRQNext
dey
dey
sty $d012
ldx #0
stx nextIRQ
beq exd
ex2:
LDA $DC0D
cli
pla
sta $01
jmp $ea31
}
// 0 lda #data0 // 0 lda #data0
// 2 ldy #data1 // 2 ldy #data1
// 4 cpx $d012 // 4 cpx $d012
@ -268,8 +365,8 @@ void rirq_build(RIRQCode * ic, byte size)
ic->size = size; ic->size = size;
asm_im(ic->code + 0, ASM_LDY, 0); asm_im(ic->code + 0, ASM_LDY, 0);
asm_im(ic->code + 2, ASM_LDA, 0); asm_im(ic->code + 2, ASM_LDX, 0);
asm_ab(ic->code + 4, ASM_CPX, 0xd012); asm_ab(ic->code + 4, ASM_CMP, 0xd012);
asm_rl(ic->code + 7, ASM_BCS, -5); asm_rl(ic->code + 7, ASM_BCS, -5);
asm_ab(ic->code + 9, ASM_STY, 0x0000); asm_ab(ic->code + 9, ASM_STY, 0x0000);
@ -283,7 +380,7 @@ void rirq_build(RIRQCode * ic, byte size)
} }
else else
{ {
asm_ab(ic->code + 12, ASM_STA, 0x0000); asm_ab(ic->code + 12, ASM_STX, 0x0000);
byte p = 15; byte p = 15;
for(byte i=2; i<size; i++) for(byte i=2; i<size; i++)
@ -342,7 +439,8 @@ void rirq_addrhi(RIRQCode * ic, byte n, byte hi)
void rirq_data(RIRQCode * ic, byte n, byte data) void rirq_data(RIRQCode * ic, byte n, byte data)
{ {
byte p = irqdi[n]; byte p = irqdi[n];
ic->code[p] = data; // ic->code[p] = data;
(volatile char *)(ic->code)[p] = data;
} }
void rirq_write(RIRQCode * ic, byte n, void * addr, byte data) void rirq_write(RIRQCode * ic, byte n, void * addr, byte data)
@ -402,7 +500,60 @@ void rirq_init_kernal(void)
sei sei
} }
*(void **)0x0314 = irq1; *(void **)0x0314 = rirq_isr_kernal_io;
vic.intr_enable = 1;
vic.ctrl1 &= 0x7f;
vic.raster = 255;
}
void rirq_init_kernal_noio(void)
{
rirq_init_tables();
__asm
{
sei
}
*(void **)0x0314 = rirq_isr_kernal_noio;
vic.intr_enable = 1;
vic.ctrl1 &= 0x7f;
vic.raster = 255;
}
void rirq_init_crt(void)
{
rirq_init_tables();
__asm
{
sei
}
*(void **)0x0314 = rirq_isr_io.kentry;
*(void **)0xfffe = rirq_isr_io;
vic.intr_enable = 1;
vic.ctrl1 &= 0x7f;
vic.raster = 255;
}
void rirq_init_crt_noio(void)
{
rirq_init_tables();
__asm
{
sei
}
*(void **)0x0314 = rirq_isr_noio.kentry;
*(void **)0xfffe = rirq_isr_noio;
vic.intr_enable = 1; vic.intr_enable = 1;
vic.ctrl1 &= 0x7f; vic.ctrl1 &= 0x7f;
@ -419,7 +570,7 @@ void rirq_init_io(void)
sei sei
} }
*(void **)0xfffe = irq0; *(void **)0xfffe = rirq_isr_ram_io;
vic.intr_enable = 1; vic.intr_enable = 1;
vic.ctrl1 &= 0x7f; vic.ctrl1 &= 0x7f;
@ -436,7 +587,7 @@ void rirq_init_memmap(void)
sei sei
} }
*(void **)0xfffe = irq2; *(void **)0xfffe = rirq_isr_noio;
vic.intr_enable = 1; vic.intr_enable = 1;
vic.ctrl1 &= 0x7f; vic.ctrl1 &= 0x7f;
@ -454,12 +605,18 @@ void rirq_init(bool kernalIRQ)
void rirq_wait(void) void rirq_wait(void)
{ {
while (tpos != npos) ; char i0 = rirq_pcount;
npos++; char i1;
do {
i1 = rirq_count;
} while (i0 == i1);
rirq_pcount = i1;
} }
void rirq_sort(void) void rirq_sort(bool inirq)
{ {
// disable raster interrupts while sorting
nextIRQ = 0xff;
#if 1 #if 1
byte maxr = rasterIRQRows[rasterIRQIndex[1]]; byte maxr = rasterIRQRows[rasterIRQIndex[1]];
for(byte i = 2; i<NUM_IRQS + 1; i++) for(byte i = 2; i<NUM_IRQS + 1; i++)
@ -494,13 +651,31 @@ void rirq_sort(void)
rasterIRQIndex[j] = ri; rasterIRQIndex[j] = ri;
} }
#endif #endif
#if NUM_IRQS & 3
for(sbyte i=NUM_IRQS-1; i>=0; i--) for(sbyte i=NUM_IRQS-1; i>=0; i--)
rasterIRQNext[i] = rasterIRQRows[rasterIRQIndex[i + 1]]; rasterIRQNext[i] = rasterIRQRows[rasterIRQIndex[i + 1]];
#else
for(sbyte i=NUM_IRQS/4-1; i>=0; i--)
{
#pragma unroll(full)
for(int j=0; j<4; j++)
rasterIRQNext[i + j * NUM_IRQS / 4] = rasterIRQRows[rasterIRQIndex[i + j * NUM_IRQS / 4 + 1]];
}
#endif
npos++; rirq_pcount = rirq_count;
byte yp = rasterIRQNext[nextIRQ]; if (inirq)
nextIRQ = NUM_IRQS - 1;
else
{
byte yp = rasterIRQNext[0];
if (yp != 0xff) if (yp != 0xff)
{
vic.raster = yp - 1; vic.raster = yp - 1;
nextIRQ = 0;
}
}
} }
void rirq_start(void) void rirq_start(void)
@ -514,6 +689,7 @@ void rirq_start(void)
lda #100 lda #100
sta $d012 sta $d012
asl $d019
cli cli
} }
} }

View File

@ -132,7 +132,8 @@ inline void rirq_data(RIRQCode * ic, byte n, byte data);
// Add a delay of 5 * cycles to a raster IRQ // Add a delay of 5 * cycles to a raster IRQ
inline void rirq_delay(RIRQCode * ic, byte cycles); inline void rirq_delay(RIRQCode * ic, byte cycles);
// Place a raster IRQ into one of the 16 slots // Place a raster IRQ into one of the 16 slots, the interrupt will fire
// one line below the given row
inline void rirq_set(byte n, byte row, RIRQCode * write); inline void rirq_set(byte n, byte row, RIRQCode * write);
// Remove a raster IRQ from one of the 16 slots // Remove a raster IRQ from one of the 16 slots
@ -147,10 +148,28 @@ inline void rirq_move(byte n, byte row);
// the less resource hungry option) // the less resource hungry option)
inline void rirq_init(bool kernalIRQ); inline void rirq_init(bool kernalIRQ);
// Raster IRQ through kernal, with IO range always enabled
// calls kernal continuation
void rirq_init_kernal(void); void rirq_init_kernal(void);
// Raster IRQ through kernal, with IO range not always enabled
// calls kernal continuation
void rirq_init_kernal_noio(void);
// Raster IRQ through RAM and ROM vector, with ROM disabled or not and IO range always enabled
// does not call kernal continuation
void rirq_init_crt(void);
// Raster IRQ through RAM and ROM vector, with ROM disabled or not and IO range not always enabled
// does not call kernal continuation
void rirq_init_crt_noio(void);
// Raster IRQ through RAM vector, with ROM disabled and IO range always enabled
// does not call kernal continuation
void rirq_init_io(void); void rirq_init_io(void);
// Raster IRQ through RAM vector, with ROM disabled and IO range not always enabled
// does not call kernal continuation
void rirq_init_memmap(void); void rirq_init_memmap(void);
// Start raster IRQ // Start raster IRQ
@ -160,8 +179,9 @@ void rirq_start(void);
void rirq_stop(void); void rirq_stop(void);
// Sort the raster IRQ, must be performed at the end of the frame after changing // Sort the raster IRQ, must be performed at the end of the frame after changing
// the vertical position of one of the interrupt operatins. // the vertical position of one of the interrupt operations.
void rirq_sort(void); // Set the inirq flag to true when calling this from an interrupt
void rirq_sort(bool inirq = false);
// Wait for the last raster IRQ op to have completed. Must be called before a // Wait for the last raster IRQ op to have completed. Must be called before a
// sort if the raster IRQ system is active // sort if the raster IRQ system is active

View File

@ -3,6 +3,9 @@
static volatile char * vspriteScreen; static volatile char * vspriteScreen;
#ifdef VSPRITE_BSS
#pragma bss(VSPRITE_BSS)
#endif
void spr_init(char * screen) void spr_init(char * screen)
{ {
@ -168,6 +171,12 @@ void vspr_init(char * screen)
} }
} }
void vspr_shutdown(void)
{
for(int i=0; i<VSPRITES_MAX - 7; i++)
rirq_clear(i);
}
void vspr_screen(char * screen) void vspr_screen(char * screen)
{ {
vspriteScreen = screen + 0x3f8; vspriteScreen = screen + 0x3f8;
@ -205,6 +214,21 @@ void vspr_move(char sp, int xpos, int ypos)
vspriteXHigh[sp] = (char)(xpos >> 8); vspriteXHigh[sp] = (char)(xpos >> 8);
} }
void vspr_movex(char sp, int xpos)
{
vspriteXLow[sp] = (char)xpos;
vspriteXHigh[sp] = (char)(xpos >> 8);
}
void vspr_movey(char sp, int ypos)
{
char yp = (char)ypos;
if (ypos & 0xff00)
yp = 0xff;
vspriteYLow[sp] = yp;
}
void vspr_image(char sp, char image) void vspr_image(char sp, char image)
{ {
vspriteImage[sp] = image; vspriteImage[sp] = image;
@ -255,7 +279,7 @@ void vspr_update(void)
{ {
char xymask = 0; char xymask = 0;
volatile char * vsprs = vspriteScreen; volatile char * vsprs = vspriteScreen;
char sypos[VSPRITES_MAX]; // char sypos[VSPRITES_MAX];
#pragma unroll(full) #pragma unroll(full)
@ -276,9 +300,9 @@ void vspr_update(void)
xymask = ((unsigned)xymask | (vspriteXHigh[ri] << 8)) >> 1; xymask = ((unsigned)xymask | (vspriteXHigh[ri] << 8)) >> 1;
#endif #endif
vic.spr_pos[uj].x = vspriteXLow[ri]; vic.spr_pos[uj].x = vspriteXLow[ri];
vic.spr_pos[uj].y = vspriteYLow[ri]; vic.spr_pos[uj].y = spriteYPos[ui + 1];
sypos[ui] = vspriteYLow[ri]; // sypos[ui] = vspriteYLow[ri];
} }
vic.spr_msbx = xymask; vic.spr_msbx = xymask;
@ -288,9 +312,11 @@ void vspr_update(void)
for(char ti=0; ti<VSPRITES_MAX - 8; ti++) for(char ti=0; ti<VSPRITES_MAX - 8; ti++)
{ {
byte ri = spriteOrder[ti + 8]; if (!done && spriteYPos[ti + 9] < 250)
if (!done && vspriteYLow[ri] < 250)
{ {
byte ri = spriteOrder[ti + 8];
rirq_move(ti, spriteYPos[ti + 1] + 23);
#ifdef VSPRITE_REVERSE #ifdef VSPRITE_REVERSE
char m = 0x80 >> (ti & 7); char m = 0x80 >> (ti & 7);
#else #else
@ -301,14 +327,13 @@ void vspr_update(void)
if (!(vspriteXHigh[ri] & 1)) if (!(vspriteXHigh[ri] & 1))
xymask ^= m; xymask ^= m;
rirq_data(spirq + ti, 2, vspriteYLow[ri]); rirq_data(spirq + ti, 2, spriteYPos[ti + 9]);
rirq_data(spirq + ti, 0, vspriteColor[ri]); rirq_data(spirq + ti, 0, vspriteColor[ri]);
rirq_data(spirq + ti, 1, vspriteXLow[ri]); rirq_data(spirq + ti, 1, vspriteXLow[ri]);
rirq_data(spirq + ti, 3, vspriteImage[ri]); rirq_data(spirq + ti, 3, vspriteImage[ri]);
rirq_data(spirq + ti, 4, xymask); rirq_data(spirq + ti, 4, xymask);
rirq_move(ti, sypos[ti] + 23); // spriteYPos[ti + 9] = vspriteYLow[ri];
sypos[ti + 8] = vspriteYLow[ri];
} }
else else
{ {

View File

@ -68,6 +68,8 @@ inline void spr_expand(char sp, bool xexpand, bool yexpand);
void vspr_init(char * screen); void vspr_init(char * screen);
void vspr_shutdown(void);
void vspr_screen(char * screen); void vspr_screen(char * screen);
// set one sprite with the given attribute // set one sprite with the given attribute
@ -78,6 +80,11 @@ void vspr_set(char sp, int xpos, int ypos, char image, char color);
inline void vspr_move(char sp, int xpos, int ypos); inline void vspr_move(char sp, int xpos, int ypos);
inline void vspr_movex(char sp, int xpos);
inline void vspr_movey(char sp, int ypos);
// change the image of a virtual sprite // change the image of a virtual sprite
inline void vspr_image(char sp, char image); inline void vspr_image(char sp, char image);

View File

@ -114,4 +114,21 @@ void vic_waitBelow(int line)
} }
} }
void vic_waitRange(char below, char above)
{
while (vic.ctrl1 & VIC_CTRL1_RST8)
;
if (vic.raster >= above)
{
while (!(vic.ctrl1 & VIC_CTRL1_RST8))
;
while (vic.ctrl1 & VIC_CTRL1_RST8)
;
}
while (vic.raster < below)
;
}
#pragma native(vic_waitLine) #pragma native(vic_waitLine)

View File

@ -118,6 +118,9 @@ void vic_waitLine(int line);
// wait for beam to be below a line // wait for beam to be below a line
void vic_waitBelow(int line); void vic_waitBelow(int line);
// wait for beam to be in a given range on screen
void vic_waitRange(char below, char above);
// reference to the VIC chip // reference to the VIC chip
#define vic (*((struct VIC *)0xd000)) #define vic (*((struct VIC *)0xd000))

View File

@ -18,6 +18,13 @@ __asm bsin
jsr 0xffe4 jsr 0xffe4
sta 0xff01 sta 0xff01
} }
__asm bsget
{
lda #0
sta 0xff00
jsr 0xffcf
sta 0xff01
}
__asm bsplot __asm bsplot
{ {
lda #0 lda #0
@ -43,6 +50,7 @@ __asm dswap
#define dswap 0xff5f #define dswap 0xff5f
#define bsout 0xffd2 #define bsout 0xffd2
#define bsin 0xffe4 #define bsin 0xffe4
#define bsget 0xffcf
#define bsplot 0xfff0 #define bsplot 0xfff0
#define bsinit 0xff81 #define bsinit 0xff81
#elif defined(__PLUS4__) #elif defined(__PLUS4__)
@ -59,6 +67,12 @@ __asm bsin
jsr 0xffe4 jsr 0xffe4
sta 0xff3f sta 0xff3f
} }
__asm bsget
{
sta 0xff3e
jsr 0xffcf
sta 0xff3f
}
__asm bsplot __asm bsplot
{ {
sta 0xff3e sta 0xff3e
@ -91,6 +105,14 @@ __asm bsin
pha pha
} }
__asm bsget
{
lda 0xe405
pha
lda 0xe404
pha
}
__asm bsplot __asm bsplot
{ {
@ -99,11 +121,34 @@ __asm bsinit
{ {
} }
#elif defined(__VIC20__)
#define bsout 0xffd2
#define bsin 0xffe4
#define bsplot 0xfff0
#define bsget 0xffcf
__asm bsinit
{
lda #147
jmp $ffd2
}
#elif defined(__CBMPET__)
#define bsout 0xffd2
#define bsin 0xffe4
__asm bsplot
{
/* no equivalent on PET */
}
__asm bsinit
{
/* no equivalent on PET */
}
#define bsget 0xffcf
#else #else
#define bsout 0xffd2 #define bsout 0xffd2
#define bsin 0xffe4 #define bsin 0xffe4
#define bsplot 0xfff0 #define bsplot 0xfff0
#define bsinit 0xff81 #define bsinit 0xff81
#define bsget 0xffcf
#endif #endif
#if defined(__C128__) || defined(__C128B__) || defined(__C128E__) #if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
@ -136,138 +181,13 @@ void iocharmap(IOCharMap chmap)
giocharmap = chmap; giocharmap = chmap;
#if !defined(__ATARI__) #if !defined(__ATARI__)
if (chmap == IOCHM_PETSCII_1) if (chmap == IOCHM_PETSCII_1)
putch(128 + 14); putrch(128 + 14);
else if (chmap == IOCHM_PETSCII_2) else if (chmap == IOCHM_PETSCII_2)
putch(14); putrch(14);
#endif #endif
} }
__asm putpch void putrch(char c)
{
ldx giocharmap
cpx #IOCHM_ASCII
bcc w3
cmp #10
bne w1
lda #13
w1:
cpx #IOCHM_PETSCII_1
bcc w3
cmp #65
bcc w3
cmp #123
bcs w3
#if defined(__CBMPET__)
cmp #97
bcs w4
cmp #91
bcs w3
w2:
eor #$a0
w4:
eor #$20
#else
cmp #97
bcs w2
cmp #91
bcs w3
w2:
eor #$20
#endif
cpx #IOCHM_PETSCII_2
beq w3
and #$df
w3:
jmp bsout
}
__asm getpch
{
jsr bsin
ldx giocharmap
cpx #IOCHM_ASCII
bcc w3
cmp #13
bne w1
lda #10
w1:
cpx #IOCHM_PETSCII_1
bcc w3
cmp #219
bcs w3
cmp #65
bcc w3
cmp #193
bcc w4
eor #$a0
w4:
cmp #123
bcs w3
cmp #97
bcs w2
cmp #91
bcs w3
w2:
eor #$20
w3:
}
char kbhit(void)
{
__asm
{
lda $c6
sta accu
}
}
char getche(void)
{
__asm
{
L1:
jsr getpch
cmp #0
beq L1
sta accu
jsr putpch
}
}
char getch(void)
{
__asm
{
L1:
jsr getpch
cmp #0
beq L1
sta accu
}
}
char getchx(void)
{
__asm
{
jsr getpch
sta accu
}
}
void putch(char c)
{ {
__asm { __asm {
lda c lda c
@ -275,21 +195,181 @@ void putch(char c)
} }
} }
void putpch(char c)
{
#if defined(__ATARI__)
if (c == 10)
c = 0x9b;
#else
if (giocharmap >= IOCHM_ASCII)
{
if (c == '\n')
c = 13;
else if (c == '\t')
{
char n = wherex() & 3;
do {
putrch(' ');
} while (++n < 4);
return;
}
else if (giocharmap >= IOCHM_PETSCII_1)
{
if (c >= 65 && c < 123)
{
if (c >= 97 || c < 91)
{
#if defined(__CBMPET__)
if (c >= 97)
c ^= 0xa0;
c ^= 0x20;
#else
c ^= 0x20;
#endif
if (giocharmap == IOCHM_PETSCII_1)
c &= 0xdf;
}
}
}
}
#endif
putrch(c);
}
static char convch(char ch)
{
#if !defined(__ATARI__)
if (giocharmap >= IOCHM_ASCII)
{
if (ch == 13)
ch = 10;
else if (giocharmap >= IOCHM_PETSCII_1)
{
if (ch >= 65 && ch < 219)
{
if (ch >= 193)
ch ^= 0xa0;
if (ch < 123 && (ch >= 97 || ch < 91))
ch ^= 0x20;
}
}
}
#endif
return ch;
}
char getrch(void)
{
return __asm {
jsr bsget
sta accu
};
}
char getpch(void)
{
return convch(getrch());
}
char kbhit(void)
{
#if defined(__CBMPET__)
return __asm
{
lda $9e
sta accu
};
#else
return __asm
{
lda $c6
sta accu
};
#endif
}
char getche(void)
{
char ch;
do {
ch = __asm {
jsr bsin
sta accu
};
} while (!ch);
__asm {
lda ch
jsr bsout
}
return convch(ch);
}
char getch(void)
{
char ch;
do {
ch = __asm {
jsr bsin
sta accu
};
} while (!ch);
return convch(ch);
}
char getchx(void)
{
char ch = __asm {
jsr bsin
sta accu
};
return convch(ch);
}
void putch(char c)
{
putpch(c);
}
void clrscr(void) void clrscr(void)
{ {
__asm putrch(147);
{
jsr bsinit
}
} }
void textcursor(bool show) void textcursor(bool show)
{ {
*(char *)0xcc = show ? 0 : 1; *(volatile char *)0xcc = show ? 0 : 1;
} }
void gotoxy(char cx, char cy) void gotoxy(char cx, char cy)
{ {
#if defined(__CBMPET__)
#define CURS_X 0xc6
#define CURS_Y 0xd8
#define SCREEN_PTR 0xc4
#define SCR_LINELEN 0xd5
__assume(cy < 25);
*(volatile char *)CURS_X = cx;
*(volatile char *)CURS_Y = cy;
if (*(volatile char *)SCR_LINELEN > 40)
cy <<= 1;
const unsigned off = cy * 40;
* (volatile unsigned *)SCREEN_PTR = off + 0x8000;
#else
__asm __asm
{ {
ldx cy ldx cy
@ -297,31 +377,50 @@ void gotoxy(char cx, char cy)
clc clc
jsr bsplot jsr bsplot
} }
#endif
} }
void textcolor(char c) void textcolor(char c)
{ {
__asm *(volatile char *)0x0286 = c;
{
lda c
sta $0286
} }
void bgcolor(char c)
{
*(volatile char *)0xd021 = c;
}
void bordercolor(char c)
{
*(volatile char *)0xd020 = c;
}
void revers(char r)
{
if (r)
putrch(18);
else
putrch(18 + 128);
} }
char wherex(void) char wherex(void)
{ {
__asm #if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
{ return *(volatile char *)0xec;
lda $d3 #elif defined(__PLUS4__)
sta accu return *(volatile char *)0xca;
} #else
return *(volatile char *)0xd3;
#endif
} }
char wherey(void) char wherey(void)
{ {
__asm #if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
{ return *(volatile char *)0xeb;
lda $d6 #elif defined(__PLUS4__)
sta accu return *(volatile char *)0xcd;
} #else
return *(volatile char *)0xd6;
#endif
} }

View File

@ -31,7 +31,7 @@ void dispmode80col(void);
#define PETSCII_CLEAR 0x94 #define PETSCII_CLEAR 0x94
#define PETSCII_DEL 0x14 #define PETSCII_DEL 0x14
#define PETSCII_INSERT 0x94 #define PETSCII_INSERT 0x94
#define PETSCII_STOP 0x0c #define PETSCII_STOP 0x03
#define PETSCII_RETURN 0x0d #define PETSCII_RETURN 0x0d
#define PETSCII_F1 0x85 #define PETSCII_F1 0x85
@ -43,6 +43,39 @@ void dispmode80col(void);
#define PETSCII_F7 0x88 #define PETSCII_F7 0x88
#define PETSCII_F8 0x8c #define PETSCII_F8 0x8c
enum ConioColors
{
COLOR_BLACK,
COLOR_WHITE,
COLOR_RED,
COLOR_CYAN,
COLOR_PURPLE,
COLOR_GREEN,
COLOR_BLUE,
COLOR_YELLOW,
COLOR_ORANGE,
COLOR_BROWN,
COLOR_LT_RED,
COLOR_DARK_GREY,
COLOR_MED_GREY,
COLOR_LT_GREEN,
COLOR_LT_BLUE,
COLOR_LT_GREY
};
// Lowlevel console in/out
// using petscii translation
void putpch(char c);
char getpch(void);
// using no translation
inline void putrch(char c);
inline char getrch(void);
// Standard console in/out
char kbhit(void); char kbhit(void);
char getche(void); char getche(void);
@ -59,15 +92,21 @@ void clrscr(void);
void gotoxy(char x, char y); void gotoxy(char x, char y);
void textcolor(char c); inline void textcolor(char c);
char wherex(void); inline void bgcolor(char c);
char wherey(void); inline void bordercolor(char c);
inline void revers(char r);
inline char wherex(void);
inline char wherey(void);
// show or hide the text cursor // show or hide the text cursor
void textcursor(bool show); inline void textcursor(bool show);
#pragma compile("conio.c") #pragma compile("conio.c")

File diff suppressed because it is too large Load Diff

View File

@ -144,8 +144,8 @@ enum ByteCode
BC_LOOP_U8, BC_LOOP_U8,
BC_MALLOC, BC_MALLOC,
BC_FREE, BC_FREE,
BC_UNUSED_4, BC_FILL,
BC_UNUSED_5, BC_FILL_LONG,
BC_UNUSED_6, BC_UNUSED_6,
BC_JSR, BC_JSR,
@ -186,6 +186,11 @@ enum ByteCode
BC_BINOP_SHR_I32, BC_BINOP_SHR_I32,
BC_BINOP_CMP_U32, BC_BINOP_CMP_U32,
BC_BINOP_CMP_S32, BC_BINOP_CMP_S32,
BC_CONV_U32_F32,
BC_CONV_I32_F32,
BC_CONV_F32_U32,
BC_CONV_F32_I32,
}; };
#endif #endif

View File

@ -116,31 +116,38 @@ int lmul4f12s(int x, int y)
{ {
__asm __asm
{ {
bit y + 1
bpl W0
sec sec
lda #0 lda x
sbc y ror
sta y sta accu
lda #0
sbc y + 1
sta y + 1
sec
lda #0
sbc x
sta x
lda #0
sbc x + 1
sta x + 1
W0:
ldx #15
lda #0 lda #0
sta accu + 1 sta accu + 1
L1: lsr x + 1 bcc W4
ror x L2:
tay
clc
lda accu + 1
adc y
sta accu + 1
tya
adc y + 1
W4:
ror
ror accu + 1
lsr accu
bcc W4
bne L2
ldx x + 1
stx accu
ldx #7
lsr accu
L1:
bcc W1 bcc W1
tay tay
clc clc
@ -156,23 +163,31 @@ W1:
dex dex
bne L1 bne L1
lsr x
bcc W2 bcc W2
tay tay
sec // sec ; we know it is set here
lda accu + 1 lda accu + 1
sbc y sbc y
sta accu + 1 sta accu + 1
tya tya
sbc y + 1 sbc y + 1
sec
W2: W2:
ror ror
ror accu + 1 ror accu + 1
ror accu ror accu
bit y + 1
bpl W3
tax
sec
lda accu + 1
sbc x
sta accu + 1
txa
sbc x + 1
W3:
lsr lsr
ror accu + 1 ror accu + 1
ror accu ror accu
@ -270,15 +285,17 @@ unsigned lmuldiv16u(unsigned a, unsigned b, unsigned c)
__asm __asm
{ {
lda #0 lda #0
sta __tmp + 0
sta __tmp + 1
sta __tmp + 2 sta __tmp + 2
sta __tmp + 3 sta __tmp + 3
ldx #16 lda a
L1: lsr a + 1 sec
ror a T1:
ldy #8
L1:
ror
bcc W1 bcc W1
tax
clc clc
lda __tmp + 2 lda __tmp + 2
adc b adc b
@ -286,20 +303,38 @@ unsigned lmuldiv16u(unsigned a, unsigned b, unsigned c)
lda __tmp + 3 lda __tmp + 3
adc b + 1 adc b + 1
sta __tmp + 3 sta __tmp + 3
txa
W1: W1:
ror __tmp + 3 ror __tmp + 3
ror __tmp + 2 ror __tmp + 2
ror __tmp + 1 dey
ror __tmp
dex
bne L1 bne L1
ror
bcc T2
lda #0 sta __tmp + 0
sta accu lda a + 1
sta accu + 1 clc
bcc T1
ldx #17 T2:
sec
L3:
sta __tmp + 1
ldx #8
L2: L2:
rol __tmp + 1
rol __tmp + 2
rol __tmp + 3
bcc W3
lda __tmp + 2
sbc c
tay
lda __tmp + 3
sbc c + 1
sec
bcs W4
W3:
sec sec
lda __tmp + 2 lda __tmp + 2
sbc c sbc c
@ -307,33 +342,23 @@ unsigned lmuldiv16u(unsigned a, unsigned b, unsigned c)
lda __tmp + 3 lda __tmp + 3
sbc c + 1 sbc c + 1
bcc W2 bcc W2
W4:
sta __tmp + 3 sta __tmp + 3
sty __tmp + 2 sty __tmp + 2
W2: W2:
rol accu
rol accu + 1
asl __tmp
rol __tmp + 1
rol __tmp + 2
rol __tmp + 3
dex dex
beq E2 bne L2
bcc L2 lda __tmp + 1
rol
lda __tmp + 2 bcc T3
sbc c
sta __tmp + 2
lda __tmp + 3
sbc c + 1
sta __tmp + 3
sec
bcs W2
E2:
sta accu + 1
lda __tmp + 0
clc
bcc L3
T3:
sta accu
} }
} }
int lmuldiv16s(int a, int b, int c) int lmuldiv16s(int a, int b, int c)
@ -358,15 +383,17 @@ int lmuldiv16s(int a, int b, int c)
__asm __asm
{ {
lda #0 lda #0
sta __tmp + 0
sta __tmp + 1
sta __tmp + 2 sta __tmp + 2
sta __tmp + 3 sta __tmp + 3
ldx #16 lda a
L1: lsr a + 1 sec
ror a T1:
ldy #8
L1:
ror
bcc W1 bcc W1
tax
clc clc
lda __tmp + 2 lda __tmp + 2
adc b adc b
@ -374,20 +401,38 @@ int lmuldiv16s(int a, int b, int c)
lda __tmp + 3 lda __tmp + 3
adc b + 1 adc b + 1
sta __tmp + 3 sta __tmp + 3
txa
W1: W1:
ror __tmp + 3 ror __tmp + 3
ror __tmp + 2 ror __tmp + 2
ror __tmp + 1 dey
ror __tmp
dex
bne L1 bne L1
ror
bcc T2
lda #0 sta __tmp + 0
sta accu lda a + 1
sta accu + 1 clc
bcc T1
ldx #17 T2:
sec
L3:
sta __tmp + 1
ldx #8
L2: L2:
rol __tmp + 1
rol __tmp + 2
rol __tmp + 3
bcc W3
lda __tmp + 2
sbc c
tay
lda __tmp + 3
sbc c + 1
sec
bcs W4
W3:
sec sec
lda __tmp + 2 lda __tmp + 2
sbc c sbc c
@ -395,30 +440,23 @@ int lmuldiv16s(int a, int b, int c)
lda __tmp + 3 lda __tmp + 3
sbc c + 1 sbc c + 1
bcc W2 bcc W2
W4:
sta __tmp + 3 sta __tmp + 3
sty __tmp + 2 sty __tmp + 2
W2: W2:
rol accu
rol accu + 1
asl __tmp
rol __tmp + 1
rol __tmp + 2
rol __tmp + 3
dex dex
beq E2 bne L2
bcc L2 lda __tmp + 1
rol
bcc T3
sta accu + 1
lda __tmp + 0
clc
bcc L3
T3:
sta accu
lda __tmp + 2
sbc c
sta __tmp + 2
lda __tmp + 3
sbc c + 1
sta __tmp + 3
sec
bcs W2
E2:
lda sign lda sign
beq E1 beq E1

View File

@ -579,25 +579,51 @@ static inline void buildline(char ly, char lx, int dx, int dy, int stride, bool
break; break;
} }
if (dy)
{
bool delta8 = false;
if (dx)
{
// m >= 0 // m >= 0
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + delta16); ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + delta16);
ip += asm_rl(BLIT_CODE + ip, ASM_BMI, delta16 ? 5 + 15 + 13 + 2 : 5 + 15 + 7 + 2); char n = delta16 ? 18 + 13 + 2 : 18 + 7 + 2;
if (!up) n++;
ip += asm_np(BLIT_CODE + ip, up ? ASM_DEY : ASM_INY); ip += asm_rl(BLIT_CODE + ip, ASM_BMI, n);
ip += asm_im(BLIT_CODE + ip, ASM_CPY, up ? 0xff : 0x08); delta8 = !delta16;
ip += asm_rl(BLIT_CODE + ip, ASM_BNE, 15); }
if (up)
{
ip += asm_np(BLIT_CODE + ip, ASM_DEY);
ip += asm_rl(BLIT_CODE + ip, ASM_BPL, delta8 ? 17 : 15);
ip += asm_np(BLIT_CODE + ip, ASM_CLC); ip += asm_np(BLIT_CODE + ip, ASM_CLC);
ip += asm_im(BLIT_CODE + ip, ASM_LDY, 0x07);
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP); ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP);
ip += asm_im(BLIT_CODE + ip, ASM_ADC, stride & 0xff); ip += asm_im(BLIT_CODE + ip, ASM_ADC, stride & 0xff);
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP); ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP);
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP + 1); ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP + 1);
ip += asm_im(BLIT_CODE + ip, ASM_ADC, stride >> 8); ip += asm_im(BLIT_CODE + ip, ASM_ADC, stride >> 8);
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP + 1); ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP + 1);
ip += asm_im(BLIT_CODE + ip, ASM_LDY, up ? 0x07 : 0x00); }
else
{
ip += asm_np(BLIT_CODE + ip, ASM_INY);
ip += asm_im(BLIT_CODE + ip, ASM_CPY, 0x08);
ip += asm_rl(BLIT_CODE + ip, ASM_BNE, delta8 ? 16 : 14);
ip += asm_im(BLIT_CODE + ip, ASM_LDY, 0x00);
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP);
ip += asm_im(BLIT_CODE + ip, ASM_ADC, (stride - 1) & 0xff);
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP);
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP + 1);
ip += asm_im(BLIT_CODE + ip, ASM_ADC, (stride - 1) >> 8);
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP + 1);
}
ip += asm_np(BLIT_CODE + ip, ASM_SEC); if (dx)
{
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP); ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP);
ip += asm_np(BLIT_CODE + ip, ASM_SEC);
ip += asm_im(BLIT_CODE + ip, ASM_SBC, dx & 0xff); ip += asm_im(BLIT_CODE + ip, ASM_SBC, dx & 0xff);
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP); ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP);
@ -606,33 +632,53 @@ static inline void buildline(char ly, char lx, int dx, int dy, int stride, bool
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1); ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1);
ip += asm_im(BLIT_CODE + ip, ASM_SBC, dx >> 8); ip += asm_im(BLIT_CODE + ip, ASM_SBC, dx >> 8);
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP + 1); ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP + 1);
} ip += asm_rl(BLIT_CODE + ip, ASM_BPL, 13 + 4 + 12);
// m < 0
ip += asm_rl(BLIT_CODE + ip, ASM_BPL, delta16 ? 4 + 15 + 13 : 4 + 15 + 7);
ip += asm_zp(BLIT_CODE + ip, left ? ASM_ASL : ASM_LSR, REG_D0);
ip += asm_rl(BLIT_CODE + ip, ASM_BCC, 15);
ip += asm_zp(BLIT_CODE + ip, left ? ASM_ROL : ASM_ROR, REG_D0);
ip += asm_np(BLIT_CODE + ip, ASM_CLC);
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP);
ip += asm_im(BLIT_CODE + ip, ASM_ADC, left ? 0xf8 : 0x08);
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP);
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP + 1);
ip += asm_im(BLIT_CODE + ip, ASM_ADC, left ? 0xff : 0x00);
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP + 1);
ip += asm_np(BLIT_CODE + ip, ASM_CLC); ip += asm_np(BLIT_CODE + ip, ASM_CLC);
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP); ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP);
ip += asm_im(BLIT_CODE + ip, ASM_ADC, dy & 0xff); ip += asm_im(BLIT_CODE + ip, ASM_ADC, dy & 0xff);
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP); ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP);
if (delta16)
{
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1); ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1);
ip += asm_im(BLIT_CODE + ip, ASM_ADC, dy >> 8); ip += asm_im(BLIT_CODE + ip, ASM_ADC, dy >> 8);
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP + 1); ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP + 1);
} }
else
{
// We know regdp to be in the accu at this point
ip += asm_rl(BLIT_CODE + ip, ASM_BPL, 5 + 4 + 12);
ip += asm_np(BLIT_CODE + ip, ASM_CLC);
ip += asm_im(BLIT_CODE + ip, ASM_ADC, dy & 0xff);
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP);
}
}
// m < 0
}
if (dx)
{
ip += asm_zp(BLIT_CODE + ip, left ? ASM_ASL : ASM_LSR, REG_D0);
ip += asm_rl(BLIT_CODE + ip, ASM_BCC, 12);
ip += asm_zp(BLIT_CODE + ip, left ? ASM_ROL : ASM_ROR, REG_D0);
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP);
if (left)
{
ip += asm_im(BLIT_CODE + ip, ASM_ADC, 0xf8);
ip += asm_rl(BLIT_CODE + ip, ASM_BCS, 2);
ip += asm_zp(BLIT_CODE + ip, ASM_DEC, REG_SP + 1);
}
else
{
ip += asm_im(BLIT_CODE + ip, ASM_ADC, 0x08);
ip += asm_rl(BLIT_CODE + ip, ASM_BCC, 2);
ip += asm_zp(BLIT_CODE + ip, ASM_INC, REG_SP + 1);
}
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP);
}
// l -- // l --
ip += asm_np(BLIT_CODE + ip, ASM_DEX); ip += asm_np(BLIT_CODE + ip, ASM_DEX);
@ -649,6 +695,7 @@ static inline void callline(byte * dst, byte bit, int m, char lh, char pattern)
{ {
__asm __asm
{ {
lda dst lda dst
sta REG_SP sta REG_SP
lda dst + 1 lda dst + 1

26
include/inttypes.c Normal file
View File

@ -0,0 +1,26 @@
#include "inttypes.h"
#include "stdlib.h"
intmax_t imaxabs(intmax_t n)
{
return n < 0 ? -n : n;
}
imaxdiv_t imaxdiv(intmax_t l, intmax_t r)
{
imaxdiv_t t;
t.quot = l / r;
t.rem = l % r;
return t;
}
inline intmax_t strtoimax(const char * s, char ** endp, int base)
{
return strtol(s, endp, base);
}
inline uintmax_t strtoumax(const char * s, char ** endp, int base)
{
return strtoul(s, endp, base);
}

98
include/inttypes.h Normal file
View File

@ -0,0 +1,98 @@
#ifndef INTTYPES_H
#define INTTYPES_H
#include <stdint.h>
#define PRId8 "d"
#define PRId16 "d"
#define PRId32 "ld"
#define PRIdLEAST8 "d"
#define PRIdLEAST16 "d"
#define PRIdLEAST32 "ld"
#define PRIdFAST8 "d"
#define PRIdFAST16 "d"
#define PRIdFAST32 "ld"
#define PRIdMAX "ld"
#define PRIdPTR "d"
#define PRIo8 "o"
#define PRIo16 "o"
#define PRIo32 "lo"
#define PRIoLEAST8 "o"
#define PRIoLEAST16 "o"
#define PRIoLEAST32 "lo"
#define PRIoFAST8 "o"
#define PRIoFAST16 "o"
#define PRIoFAST32 "lo"
#define PRIoMAX "lo"
#define PRIoPTR "o"
#define PRIu8 "u"
#define PRIu16 "u"
#define PRIu32 "lu"
#define PRIuLEAST8 "u"
#define PRIuLEAST16 "u"
#define PRIuLEAST32 "lu"
#define PRIuFAST8 "u"
#define PRIuFAST16 "u"
#define PRIuFAST32 "lu"
#define PRIuMAX "lu"
#define PRIuPTR "u"
#define PRIx8 "x"
#define PRIx16 "x"
#define PRIx32 "lx"
#define PRIxLEAST8 "x"
#define PRIxLEAST16 "x"
#define PRIxLEAST32 "lx"
#define PRIxFAST8 "x"
#define PRIxFAST16 "x"
#define PRIxFAST32 "lx"
#define PRIxMAX "lx"
#define PRIxPTR "x"
#define PRIX8 "X"
#define PRIX16 "X"
#define PRIX32 "lX"
#define PRIXLEAST8 "X"
#define PRIXLEAST16 "X"
#define PRIXLEAST32 "lX"
#define PRIXFAST8 "X"
#define PRIXFAST16 "X"
#define PRIXFAST32 "lX"
#define PRIXMAX "lX"
#define PRIXPTR "X"
typedef struct {
intmax_t quot;
intmax_t rem;
} imaxdiv_t;
intmax_t imaxabs(intmax_t n);
imaxdiv_t imaxdiv(intmax_t l, intmax_t r);
intmax_t strtoimax(const char * s, char ** endp, int base);
uintmax_t strtoumax(const char * s, char ** endp, int base);
#pragma compile("inttypes.c")
#endif

16
include/iso646.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef ISO646_H
#define ISO646_H
#define and &&
#define and_eq &=
#define bitand &
#define bitor |
#define compl ~
#define not !
#define not_eq !=
#define or ||
#define or_eq |=
#define xor ^
#define xor_eq ^=
#endif

View File

@ -11,7 +11,7 @@
#define CHAR_MIN SCHAR_MIN #define CHAR_MIN SCHAR_MIN
#define CHAR_MAX SCHAR_MAX #define CHAR_MAX SCHAR_MAX
#define INT_MIN -32767 #define INT_MIN (-32767-1)
#define INT_MAX 32767 #define INT_MAX 32767
#define UINT_MAX 65535 #define UINT_MAX 65535

View File

@ -110,12 +110,12 @@ float atan2(float p, float q)
return s; return s;
} }
#define F_EXP_0 1.0000003 #define F_EXP_0 1.0
#define F_EXP_1 0.693147059 #define F_EXP_1 0.69315668
#define F_EXP_2 0.240173099 #define F_EXP_2 0.240132068
#define F_EXP_3 0.055816392 #define F_EXP_3 0.055876024
#define F_EXP_4 0.008965036 #define F_EXP_4 0.008940801
#define F_EXP_5 0.001898429 #define F_EXP_5 0.001894414
float exp(float f) float exp(float f)
{ {
@ -143,12 +143,12 @@ float exp(float f)
return s * x.f; return s * x.f;
} }
#define F_LOG_0 -3.78712618 #define F_LOG_0 -3.78717706
#define F_LOG_1 10.0957081 #define F_LOG_1 10.0960498
#define F_LOG_2 -13.9747486 #define F_LOG_2 -13.975654
#define F_LOG_3 12.7568806 #define F_LOG_3 12.7580616
#define F_LOG_4 -6.48114552 #define F_LOG_4 -6.48190725
#define F_LOG_5 1.39045416 #define F_LOG_5 1.39064767
float log(float f) float log(float f)
{ {

View File

@ -32,6 +32,15 @@ bool isfinite(float f);
#pragma intrinsic(sin) #pragma intrinsic(sin)
#pragma intrinsic(cos) #pragma intrinsic(cos)
#pragma intrinsic(tan)
#pragma intrinsic(atan)
#pragma intrinsic(atan2)
#pragma intrinsic(log)
#pragma intrinsic(exp)
#pragma intrinsic(pow)
#pragma intrinsic(sqrt)
#pragma compile("math.c") #pragma compile("math.c")

59
include/opp/boundint.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef OPP_BOUNDINT_H
#define OPP_BOUNDINT_H
namespace opp {
template<int tmin, int tmax>
constexpr auto boundinttype(void)
{
if constexpr (tmin >= 0 && tmax <= 255)
return (char)0;
else if constexpr (tmin >= -128 && tmax <= 127)
return (signed char)0;
else
return (int)0;
}
template<int tmin, int tmax>
class boundint
{
protected:
decltype(boundinttype<tmin, tmax>()) v;
public:
boundint(int i)
: v(i)
{
}
void operator=(int k)
{
__assume(k >= tmin && k <= tmax);
v = k;
}
void operator+=(int k)
{
k += v;
__assume(k >= tmin && k <= tmax);
v = k;
}
void operator-=(int k)
{
k = v - k;
__assume(k >= tmin && k <= tmax);
v = k;
}
operator int() const
{
int k = v;
__assume(k >= tmin && k <= tmax);
return k;
}
};
}
#endif

93
include/opp/functional.h Normal file
View File

@ -0,0 +1,93 @@
#ifndef OPP_FUNCTIONAL_H
#define OPP_FUNCTIONAL_H
namespace opp
{
template <class F>
class function;
template <class R, class ... P>
class function<R(P...)>
{
private:
struct callif
{
virtual R call(P...) = 0;
virtual ~callif() {}
virtual callif * clone(void) const = 0;
};
template<class CA>
struct callable : callif
{
CA ca;
callable(CA ca_) : ca(ca_) {}
R call(P... p) {return ca(p...);}
callif * clone(void) const
{
return new callable(ca);
}
};
callif * c;
public:
template <class F>
function(F f)
{
c = new callable<F>(f);
}
function(const function & f)
{
c = f.c->clone();
}
function(function && f)
{
c = f.c;
f.c = nullptr;
}
function(void)
{
c = nullptr;
}
function & operator=(const function & f)
{
if (c != f.c)
{
delete c;
c = f.c;
}
return *this;
}
function & operator=(function && f)
{
if (c != f.c)
{
c = f.c;
f.c = nullptr;
}
return *this;
}
~function(void)
{
delete c;
}
R operator()(P ... p) const
{
return c->call(p...);
}
};
}
#endif

View File

@ -952,6 +952,13 @@ istream & istream::operator>>(float & val)
return *this; return *this;
} }
istream & istream::operator>>(char & val)
{
doskipws();
val = get();
return *this;
}
istream & istream::operator>>(char * p) istream & istream::operator>>(char * p)
{ {
doskipws(); doskipws();

View File

@ -37,7 +37,7 @@ public:
showpos = 0x0800, showpos = 0x0800,
skipws = 0x1000, skipws = 0x1000,
unitbuf = 0x2000, unitbuf = 0x2000,
uppercase = 0x3000, uppercase = 0x4000,
adjustfield = 0x00b0, adjustfield = 0x00b0,
basefield = 0x004a, basefield = 0x004a,
@ -124,6 +124,7 @@ public:
istream & putback(char c); istream & putback(char c);
istream & unget(void); istream & unget(void);
istream & operator>>(char & val);
istream & operator>>(bool & val); istream & operator>>(bool & val);
istream & operator>>(int & val); istream & operator>>(int & val);
istream & operator>>(unsigned & val); istream & operator>>(unsigned & val);

View File

@ -124,8 +124,8 @@ public:
{ {
head.succ = l.head.succ; head.succ = l.head.succ;
head.pred = l.head.pred; head.pred = l.head.pred;
head.succ->pred = head; head.succ->pred = (listnode<T> *)&head;
head.pred->succ = head; head.pred->succ = (listnode<T> *)&head;
l.head.succ = (listnode<T> *)&(l.head); l.head.succ = (listnode<T> *)&(l.head);
l.head.pred = (listnode<T> *)&(l.head); l.head.pred = (listnode<T> *)&(l.head);
} }
@ -136,8 +136,8 @@ public:
{ {
head.succ = l.head.succ; head.succ = l.head.succ;
head.pred = l.head.pred; head.pred = l.head.pred;
head.succ->pred = head; head.succ->pred = (listnode<T> *)&head;
head.pred->succ = head; head.pred->succ = (listnode<T> *)&head;
l.head.succ = (listnode<T> *)&(l.head); l.head.succ = (listnode<T> *)&(l.head);
l.head.pred = (listnode<T> *)&(l.head); l.head.pred = (listnode<T> *)&(l.head);
return *this; return *this;

View File

@ -20,12 +20,12 @@ void ostringstream::bput(char ch)
{ {
mBSize = 15; mBSize = 15;
mBFill = 0; mBFill = 0;
mBuffer = malloc(15); mBuffer = (char *)malloc(15);
} }
else if (mBFill == mBSize) else if (mBFill == mBSize)
{ {
mBSize *= 2; mBSize *= 2;
char * b = malloc(mBSize); char * b = (char *)malloc(mBSize);
for(char i=0; i<mBFill; i++) for(char i=0; i<mBFill; i++)
b[i] = mBuffer[i]; b[i] = mBuffer[i];
free(mBuffer); free(mBuffer);
@ -46,7 +46,7 @@ void ostringstream::str(const string & str)
{ {
free(mBuffer); free(mBuffer);
mBSize = mBFill; mBSize = mBFill;
mBuffer = malloc(mBSize); mBuffer = (char *)malloc(mBSize);
} }
str.copyseg(mBuffer, 0, mBFill); str.copyseg(mBuffer, 0, mBFill);
} }

View File

@ -4,6 +4,7 @@
#include <new> #include <new>
#include <stdlib.h> #include <stdlib.h>
#include <opp/utility.h> #include <opp/utility.h>
#include <oscar.h>
namespace opp { namespace opp {
@ -11,8 +12,8 @@ template <class T, int N>
class static_vector class static_vector
{ {
protected: protected:
char _space[N * sizeof(T)];
enum { m = N } _size; enum { m = N } _size;
char _space[N * sizeof(T)];
public: public:
typedef T element_type; typedef T element_type;
@ -20,23 +21,28 @@ public:
static_vector(size_t n) : _size(n) static_vector(size_t n) : _size(n)
{ {
#ifdef CAPACITYCHECK
if (n > N) debugcrash();
#endif
T * data = (T*)_space; T * data = (T*)_space;
for(size_t i=0; i<n; i++) for(size_t i=0; i<n; i++)
new (data + i) T; new (data + i) T();
} }
static_vector(const static_vector & v) static_vector(const static_vector & v)
: _size(v._size) : _size(v._size)
{ {
size_t n = _size;
T * data = (T*)_space, * vdata = (T*)(v._space); T * data = (T*)_space, * vdata = (T*)(v._space);
for(size_t i=0; i<_size; i++) for(size_t i=0; i<n; i++)
new (data + i)T(vdata[i]); new (data + i)T(vdata[i]);
} }
~static_vector(void) ~static_vector(void)
{ {
T * data = (T*)_space; T * data = (T*)_space;
for(size_t i=0; i<_size; i++) size_t n = _size;
for(size_t i=0; i<n; i++)
data[i].~T(); data[i].~T();
} }
@ -45,10 +51,12 @@ public:
if (this != &v) if (this != &v)
{ {
T * data = (T*)_space, * vdata = (T*)(v._space); T * data = (T*)_space, * vdata = (T*)(v._space);
for(size_t i=0; i<_size; i++) size_t n = _size;
for(size_t i=0; i<n; i++)
data[i].~T(); data[i].~T();
_size = v._size; _size = v._size;
for(size_t i=0; i<_size; i++) n = _size;
for(size_t i=0; i<n; i++)
new (data + i)T(vdata[i]); new (data + i)T(vdata[i]);
} }
return *this; return *this;
@ -69,6 +77,11 @@ public:
return _size == 0; return _size == 0;
} }
bool full(void) const
{
return _size == N;
}
size_t capacity(void) const size_t capacity(void) const
{ {
return N; return N;
@ -76,6 +89,8 @@ public:
void resize(size_t n); void resize(size_t n);
void clear(void);
T & at(size_t at) T & at(size_t at)
{ {
return ((T*)_space)[at]; return ((T*)_space)[at];
@ -166,6 +181,8 @@ public:
((T*)_space)[_size].~T(); ((T*)_space)[_size].~T();
} }
void assign(size_t count, const T & t);
void insert(size_t at, const T & t); void insert(size_t at, const T & t);
void erase(size_t at, size_t n = 1); void erase(size_t at, size_t n = 1);
@ -177,34 +194,50 @@ public:
}; };
template <class T, int N>
void static_vector<T, N>::clear(void)
{
T * data = (T*)_space;
for(size_t i=0; i<_size; i++)
data[i].~T();
_size = 0;
}
template <class T, int N> template <class T, int N>
void static_vector<T, N>::resize(size_t n) void static_vector<T, N>::resize(size_t n)
{ {
#ifdef CAPACITYCHECK
if (n > N) debugcrash();
#endif
T * data = (T*)_space; T * data = (T*)_space;
if (n < _size) if (n < _size)
{ {
for(size_t i=n; i<_size; i++) for(size_t i=n; i<_size; i++)
data[i].~T(); data[i].~T();
_size = n;
} }
else else if (n > 0)
{ {
for(size_t i=_size; i<n; i++) for(size_t i=_size; i<n; i++)
new(data + i)T; new(data + i)T();
_size = n;
} }
_size = n;
} }
template <class T, int N> template <class T, int N>
void static_vector<T, N>::push_back(const T & t) void static_vector<T, N>::push_back(const T & t)
{ {
#ifdef CAPACITYCHECK
if (_size >= N) debugcrash();
#endif
new ((T*)_space + _size++)T(t); new ((T*)_space + _size++)T(t);
} }
template <class T, int N> template <class T, int N>
void static_vector<T, N>::push_back(T && t) void static_vector<T, N>::push_back(T && t)
{ {
#ifdef CAPACITYCHECK
if (_size >= N) debugcrash();
#endif
new ((T*)_space + _size++)T(t); new ((T*)_space + _size++)T(t);
} }
@ -212,14 +245,28 @@ template <class T, int N>
template <typename ...P> template <typename ...P>
void static_vector<T, N>::emplace_back(const P&... p) void static_vector<T, N>::emplace_back(const P&... p)
{ {
#ifdef CAPACITYCHECK
if (_size >= N) debugcrash();
#endif
new ((T*)_space + _size++)T(p...); new ((T*)_space + _size++)T(p...);
} }
template <class T, int N>
void static_vector<T, N>::assign(size_t count, const T & t)
{
T * data = (T*)_space;
for(size_t i=0; i<_size; i++)
data[i].~T();
for(size_t i=0; i<count; i++)
new (data + i)T(t);
_size = count;
}
template <class T, int N> template <class T, int N>
void static_vector<T, N>::insert(size_t at, const T & t) void static_vector<T, N>::insert(size_t at, const T & t)
{ {
T * data = (T*)_space; T * data = (T*)_space;
new (data + _size)T; new (data + _size)T();
for(size_t i=_size; i>at; i--) for(size_t i=_size; i>at; i--)
data[i] = move(data[i - 1]); data[i] = move(data[i - 1]);
data[at] = t; data[at] = t;
@ -240,9 +287,12 @@ void static_vector<T, N>::erase(size_t at, size_t n)
template <class T, int N> template <class T, int N>
T * static_vector<T, N>::insert(T * at, const T & t) T * static_vector<T, N>::insert(T * at, const T & t)
{ {
#ifdef CAPACITYCHECK
if (_size >= N) debugcrash();
#endif
T * data = (T*)_space; T * data = (T*)_space;
T * dp = data + _size; T * dp = data + _size;
new (dp)T; new (dp)T();
while (dp != at) while (dp != at)
{ {
dp--; dp--;

View File

@ -32,7 +32,7 @@ string::string(const string & s)
if (s.cstr) if (s.cstr)
{ {
char l = s.cstr[0]; char l = s.cstr[0];
cstr = malloc(char(l + 2)); cstr = (char *)malloc(char(l + 2));
smemcpy(cstr, s.cstr, l + 2); smemcpy(cstr, s.cstr, l + 2);
} }
else else
@ -52,7 +52,7 @@ string::string(const char * s)
char l = sstrlen(s); char l = sstrlen(s);
if (l) if (l)
{ {
cstr = malloc(char(l + 2)); cstr = (char *)malloc(char(l + 2));
cstr[0] = l; cstr[0] = l;
smemcpy(cstr + 1, s, l + 1); smemcpy(cstr + 1, s, l + 1);
} }
@ -67,9 +67,10 @@ string::string(const char * s, char size)
{ {
if (size) if (size)
{ {
cstr = malloc(char(size + 2)); cstr = (char *)malloc(char(size + 2));
cstr[0] = size; cstr[0] = size;
smemcpy(cstr + 1, s, size + 1); smemcpy(cstr + 1, s, size);
cstr[size + 1] = 0;
} }
else else
cstr = nullptr; cstr = nullptr;
@ -77,7 +78,7 @@ string::string(const char * s, char size)
string::string(char c) string::string(char c)
{ {
cstr = malloc(3); cstr = (char *)malloc(3);
cstr[0] = 1; cstr[0] = 1;
cstr[1] = c; cstr[1] = c;
cstr[2] = 0; cstr[2] = 0;
@ -114,7 +115,7 @@ string & string::operator=(const string & s)
if (s.cstr) if (s.cstr)
{ {
char l = s.cstr[0]; char l = s.cstr[0];
cstr = malloc(char(l + 2)); cstr = (char *)malloc(char(l + 2));
smemcpy(cstr, s.cstr, l + 2); smemcpy(cstr, s.cstr, l + 2);
} }
else else
@ -144,7 +145,7 @@ string & string::operator=(const char * s)
char l = sstrlen(s); char l = sstrlen(s);
if (l) if (l)
{ {
cstr = malloc(char(l + 2)); cstr = (char *)malloc(char(l + 2));
cstr[0] = l; cstr[0] = l;
smemcpy(cstr + 1, s, l + 1); smemcpy(cstr + 1, s, l + 1);
} }
@ -166,7 +167,7 @@ string & string::operator+=(const string & s)
d = cstr[0]; d = cstr[0];
char l = s.cstr[0] + d; char l = s.cstr[0] + d;
char * c = malloc(char(l + 2)); char * c = (char *)malloc(char(l + 2));
c[0] = l; c[0] = l;
if (d) if (d)
@ -188,7 +189,7 @@ string & string::operator+=(const char * s)
if (cstr) if (cstr)
{ {
char l = sl + cstr[0]; char l = sl + cstr[0];
char * c = malloc(char(l + 2)); char * c = (char *)malloc(char(l + 2));
c[0] = l; c[0] = l;
smemcpy(c + 1, cstr + 1, cstr[0]); smemcpy(c + 1, cstr + 1, cstr[0]);
smemcpy(c + 1 + cstr[0], s, sl + 1); smemcpy(c + 1 + cstr[0], s, sl + 1);
@ -197,7 +198,7 @@ string & string::operator+=(const char * s)
} }
else else
{ {
cstr = malloc(char(sl + 2)); cstr = (char *)malloc(char(sl + 2));
cstr[0] = sl; cstr[0] = sl;
smemcpy(cstr + 1, s, sl + 1); smemcpy(cstr + 1, s, sl + 1);
} }
@ -211,7 +212,7 @@ string & string::operator+=(char c)
if (cstr) if (cstr)
{ {
char l = cstr[0] + 1; char l = cstr[0] + 1;
char * p = malloc(char(l + 2)); char * p = (char *)malloc(char(l + 2));
p[0] = l; p[0] = l;
smemcpy(p + 1, cstr + 1, cstr[0]); smemcpy(p + 1, cstr + 1, cstr[0]);
p[l] = c; p[l] = c;
@ -221,7 +222,7 @@ string & string::operator+=(char c)
} }
else else
{ {
cstr = malloc(3); cstr = (char *)malloc(3);
cstr[0] = 1; cstr[0] = 1;
cstr[1] = c; cstr[1] = c;
cstr[2] = 0; cstr[2] = 0;
@ -229,6 +230,10 @@ string & string::operator+=(char c)
return *this; return *this;
} }
inline const char * string::c_str(void) const
{
return this->tocstr();
}
inline const char * string::tocstr(void) const inline const char * string::tocstr(void) const
{ {
@ -253,7 +258,7 @@ string string::operator+(const string & s) const
if (s.cstr) if (s.cstr)
{ {
char l = cstr[0] + s.cstr[0]; char l = cstr[0] + s.cstr[0];
char * p = malloc(char(l + 2)); char * p = (char *)malloc(char(l + 2));
smemcpy(p + 1, cstr + 1, cstr[0]); smemcpy(p + 1, cstr + 1, cstr[0]);
smemcpy(p + 1 + cstr[0], s.cstr + 1, s.cstr[0]); smemcpy(p + 1 + cstr[0], s.cstr + 1, s.cstr[0]);
return string(l, p); return string(l, p);
@ -275,7 +280,7 @@ string string::operator+(const char * s) const
if (sl) if (sl)
{ {
char l = cstr[0] + sl; char l = cstr[0] + sl;
char * p = malloc(char(l + 2)); char * p = (char *)malloc(char(l + 2));
smemcpy(p + 1, cstr + 1, cstr[0]); smemcpy(p + 1, cstr + 1, cstr[0]);
smemcpy(p + 1 + cstr[0], s, sl); smemcpy(p + 1 + cstr[0], s, sl);
return string(l, p); return string(l, p);
@ -295,7 +300,7 @@ string string::operator+(char c) const
if (cstr) if (cstr)
{ {
char l = cstr[0] + 1; char l = cstr[0] + 1;
char * p = malloc(char(l + 2)); char * p = (char *)malloc(char(l + 2));
smemcpy(p + 1, cstr + 1, cstr[0]); smemcpy(p + 1, cstr + 1, cstr[0]);
p[l] = c; p[l] = c;
return string(l, p); return string(l, p);
@ -523,7 +528,7 @@ string string::substr(char pos, char len) const
if (pos + len > l) if (pos + len > l)
len = l - pos; len = l - pos;
char * p = malloc(len + 2); char * p = (char *)malloc(len + 2);
memcpy(p + 1, cstr + 1 + pos, len); memcpy(p + 1, cstr + 1 + pos, len);
return string(len, p); return string(len, p);
} }

View File

@ -67,6 +67,7 @@ public:
const char * end(void) const; const char * end(void) const;
const char * cend(void) const; const char * cend(void) const;
const char * c_str(void) const;
const char * tocstr(void) const; const char * tocstr(void) const;
string substr(char pos, char len) const; string substr(char pos, char len) const;

View File

@ -21,13 +21,14 @@ public:
vector(size_t n) : _data((T*)malloc(n * sizeof(T))), _size(n), _capacity(n) vector(size_t n) : _data((T*)malloc(n * sizeof(T))), _size(n), _capacity(n)
{ {
for(size_t i=0; i<n; i++) for(size_t i=0; i<n; i++)
new (_data + i) T; new (_data + i) T();
} }
vector(const vector & v) vector(const vector & v)
: _data((T*)malloc(v._size * sizeof(T))), _size(v._size), _capacity(v._size) : _data((T*)malloc(v._size * sizeof(T))), _size(v._size), _capacity(v._size)
{ {
for(size_t i=0; i<_size; i++) size_t n = _size;
for(size_t i=0; i<n; i++)
new (_data + i)T(v._data[i]); new (_data + i)T(v._data[i]);
} }
@ -50,14 +51,16 @@ public:
{ {
if (this != &v) if (this != &v)
{ {
for(size_t i=0; i<_size; i++) size_t n = _size;
for(size_t i=0; i<n; i++)
_data[i].~T(); _data[i].~T();
free(_data); free(_data);
_data = (T*)malloc(v._size * sizeof(T)); _data = (T*)malloc(v._size * sizeof(T));
_size = v._size; _size = v._size;
_capacity = v._size; _capacity = v._size;
for(size_t i=0; i<_size; i++) n = _size;
for(size_t i=0; i<n; i++)
new (_data + i)T(v._data[i]); new (_data + i)T(v._data[i]);
} }
return *this; return *this;
@ -94,6 +97,8 @@ public:
return _capacity; return _capacity;
} }
void clear(void);
void resize(size_t n); void resize(size_t n);
void reserve(size_t n); void reserve(size_t n);
@ -190,6 +195,8 @@ public:
_data[_size].~T(); _data[_size].~T();
} }
void assign(size_t count, const T & t);
void insert(size_t at, const T & t); void insert(size_t at, const T & t);
void erase(size_t at, size_t n = 1); void erase(size_t at, size_t n = 1);
@ -204,7 +211,7 @@ protected:
template <class T> template <class T>
void vector<T>::reserve(size_t n) __noinline void vector<T>::reserve(size_t n)
{ {
if (n > _capacity) if (n > _capacity)
{ {
@ -221,7 +228,15 @@ void vector<T>::reserve(size_t n)
} }
template <class T> template <class T>
void vector<T>::resize(size_t n) void vector<T>::clear(void)
{
for(size_t i=0; i<_size; i++)
_data[i].~T();
_size = 0;
}
template <class T>
__noinline void vector<T>::resize(size_t n)
{ {
if (n < _size) if (n < _size)
{ {
@ -232,7 +247,7 @@ void vector<T>::resize(size_t n)
else if (n < _capacity) else if (n < _capacity)
{ {
for(size_t i=_size; i<n; i++) for(size_t i=_size; i<n; i++)
new(_data + i)T; new(_data + i)T();
_size = n; _size = n;
} }
else else
@ -286,12 +301,27 @@ void vector<T>::emplace_back(const P&... p)
new (add_back())T(p...); new (add_back())T(p...);
} }
template <class T>
void vector<T>::assign(size_t count, const T & t)
{
for(size_t i=0; i<_size; i++)
_data[i].~T();
if (count > _capacity)
{
_size = 0;
reserve(count);
}
for(size_t i=0; i<count; i++)
new (_data + i)T(t);
_size = count;
}
template <class T> template <class T>
void vector<T>::insert(size_t at, const T & t) void vector<T>::insert(size_t at, const T & t)
{ {
if (_size == _capacity) if (_size == _capacity)
reserve(_size + 1 + (_size >> 1)); reserve(_size + 1 + (_size >> 1));
new (_data + _size)T; new (_data + _size)T();
for(size_t i=_size; i>at; i--) for(size_t i=_size; i>at; i--)
_data[i] = move(_data[i - 1]); _data[i] = move(_data[i - 1]);
_data[at] = t; _data[at] = t;
@ -318,7 +348,7 @@ T * vector<T>::insert(T * at, const T & t)
at = (T *)(f + unsigned(_data)); at = (T *)(f + unsigned(_data));
} }
T * dp = _data + _size; T * dp = _data + _size;
new (dp)T; new (dp)T();
while (dp != at) while (dp != at)
{ {
dp--; dp--;

View File

@ -86,3 +86,53 @@ const char * oscar_expand_rle(char * dp, const char * sp)
return sp + 1; return sp + 1;
} }
__native const char * oscar_expand_lzo_buf(char * dp, const char * sp)
{
char buf[256];
char b = 0;
char cmd = sp[0];
do
{
if (cmd & 0x80)
{
char i = b - sp[1];
cmd &= 0x7f;
sp += 2;
char n = 0;
do {
buf[b] = dp[n] = buf[i];
b++;
i++;
n++;
} while (n != cmd);
}
else
{
sp += 1;
char n = 0;
do {
buf[b] = dp[n] = sp[n];
b++;
n++;
} while (n != cmd);
sp += cmd;
}
dp += cmd;
cmd = sp[0];
} while (cmd);
return sp + 1;
}
void debugcrash(void)
{
__asm volatile {
byt $02
}
}

View File

@ -6,6 +6,19 @@ __native const char * oscar_expand_lzo(char * dp, const char * sp);
__native const char * oscar_expand_rle(char * dp, const char * sp); __native const char * oscar_expand_rle(char * dp, const char * sp);
// Same as oscar_expand_lzo, but does not need read access to the
// target memory area. On the downside, it uses 256 bytes of stack
// memory as buffer
__native const char * oscar_expand_lzo_buf(char * dp, const char * sp);
// Write a breakpoint instruction into the .lbl file for vice. This
// intrinsic function will change the behaviour of the optimizer to ensure
// that the breakpoint is not move around into wild places.
void breakpoint(void);
#pragma intrinsic(breakpoint)
void debugcrash(void);
#pragma compile("oscar.c") #pragma compile("oscar.c")

View File

@ -2,237 +2,50 @@
#include "conio.h" #include "conio.h"
#include "stdlib.h" #include "stdlib.h"
#if defined(__C128__)
#pragma code(lowcode)
__asm bsout
{
ldx #0
stx 0xff00
jsr 0xffd2
sta 0xff01
}
__asm bsplot
{
lda #0
sta 0xff00
jsr 0xfff0
sta 0xff01
}
__asm bsin
{
lda #0
sta 0xff00
jsr 0xffcf
sta 0xff01
}
#pragma code(code)
#elif defined(__PLUS4__)
#pragma code(lowcode)
__asm bsout
{
sta 0xff3e
jsr 0xffd2
sta 0xff3f
}
__asm bsin
{
sta 0xff3e
jsr 0xffe4
sta 0xff3f
}
__asm bsplot
{
sta 0xff3e
jsr 0xfff0
sta 0xff3f
}
#pragma code(code)
#elif defined(__ATARI__)
__asm bsout
{
tax
lda 0xe407
pha
lda 0xe406
pha
txa
}
__asm bsin
{
lda 0xe405
pha
lda 0xe404
pha
}
__asm bsplot
{
}
#else
#define bsout 0xffd2
#define bsplot 0xfff0
#define bsin 0xffcf
#endif
__asm putpch
{
#if defined(__ATARI__)
cmp #10
bne w1
lda #0x9b
w1:
jmp bsout
#else
ldx giocharmap
cpx #IOCHM_ASCII
bcc w3
cmp #10
bne w1
lda #13
w1:
cmp #9
beq t1
cpx #IOCHM_PETSCII_1
bcc w3
cmp #65
bcc w3
cmp #123
bcs w3
#if defined(__CBMPET__)
cmp #97
bcs w4
cmp #91
bcs w3
w2:
eor #$a0
w4:
eor #$20
#else
cmp #97
bcs w2
cmp #91
bcs w3
w2:
eor #$20
#endif
cpx #IOCHM_PETSCII_2
beq w3
and #$df
w3:
jmp bsout
t1:
sec
jsr bsplot
tya
and #3
eor #3
tax
lda #$20
l1:
jsr bsout
dex
bpl l1
#endif
}
__asm getpch
{
jsr bsin
#if !defined(__ATARI__)
ldx giocharmap
cpx #IOCHM_ASCII
bcc w3
cmp #13
bne w1
lda #10
w1:
cpx #IOCHM_PETSCII_1
bcc w3
cmp #219
bcs w3
cmp #65
bcc w3
cmp #193
bcc w4
eor #$a0
w4:
cmp #123
bcs w3
cmp #97
bcs w2
cmp #91
bcs w3
w2:
eor #$20
w3:
#endif
}
void putchar(char c) void putchar(char c)
{ {
__asm { putpch(c);
lda c
jsr putpch
}
} }
char getchar(void) char getchar(void)
{ {
__asm { return getpch();
jsr getpch
sta accu
lda #0
sta accu + 1
}
} }
void puts(const char * str) void puts(const char * str)
{ {
__asm { while (char ch = *str++)
ploop: putpch(ch);
ldy #0
lda (str), y
beq pdone
jsr putpch
inc str
bne ploop
inc str + 1
bne ploop
pdone:
}
} }
char * gets(char * str) char * gets(char * str)
{ {
__asm { char i = 0;
gloop: while ((char ch = getpch()) != '\n')
jsr getpch str[i++] = ch;
ldy #0 str[i] = 0;
cmp #10 return str;
beq gdone
sta (str), y
inc str
bne gloop
inc str + 1
bne gloop
gdone:
lda #0
sta (str), y
} }
char * gets_s(char * str, size_t n)
{
if (str == NULL)
return NULL;
if (n < 2)
return NULL;
char i = 0, t = n - 1;
while ((char ch = getpch()) != '\n')
{
if (i < t)
str[i] = ch;
++i;
}
str[(i < t) ? i : t] = '\0';
if (i > t)
return NULL;
return str; return str;
} }
@ -583,7 +396,7 @@ char * sformat(char * buff, const char * fmt, int * fps, bool print)
if (c >= '0' && c <='9') if (c >= '0' && c <='9')
{ {
int i = 0; char i = 0;
while (c >= '0' && c <='9') while (c >= '0' && c <='9')
{ {
i = i * 10 + c - '0'; i = i * 10 + c - '0';
@ -594,7 +407,7 @@ char * sformat(char * buff, const char * fmt, int * fps, bool print)
if (c == '.') if (c == '.')
{ {
int i = 0; char i = 0;
c = *p++; c = *p++;
while (c >= '0' && c <='9') while (c >= '0' && c <='9')
{ {
@ -604,7 +417,7 @@ char * sformat(char * buff, const char * fmt, int * fps, bool print)
si.precision = i; si.precision = i;
} }
if (c == 'd' || c == p'd') if (c == 'd' || c == p'd' || c == 'i' || c == p'i')
{ {
bi = nformi(&si, bp, *fps++, true); bi = nformi(&si, bp, *fps++, true);
} }
@ -743,6 +556,17 @@ int sprintf(char * str, const char * fmt, ...)
return d - str; return d - str;
} }
void vprintf(const char * fmt, va_list vlist)
{
char buff[50];
sformat(buff, fmt, (int *)vlist, true);
}
int vsprintf(char * str, const char * fmt, va_list vlist)
{
char * d = sformat(str, fmt, (int *)vlist, false);
return d - str;
}
static inline bool isspace(char c) static inline bool isspace(char c)
{ {

View File

@ -2,7 +2,8 @@
#define STDIO_H #define STDIO_H
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
void putchar(char c); void putchar(char c);
@ -12,10 +13,16 @@ void puts(const char * str);
char * gets(char * str); char * gets(char * str);
char * gets_s(char * str, size_t n);
void printf(const char * fmt, ...); void printf(const char * fmt, ...);
int sprintf(char * str, const char * fmt, ...); int sprintf(char * str, const char * fmt, ...);
void vprintf(const char * fmt, va_list vlist);
int vsprintf(char * str, const char * fmt, va_list vlist);
int scanf(const char * fmt, ...); int scanf(const char * fmt, ...);
int sscanf(const char * str, const char * fmt, ...); int sscanf(const char * str, const char * fmt, ...);

View File

@ -7,20 +7,17 @@
void itoa(int n, char * s, unsigned radix) void itoa(int n, char * s, unsigned radix)
{ {
bool neg = n < 0; bool neg = n < 0;
if (neg) unsigned un = neg ? -n : n;
{
n = - n;
}
char i = 0; char i = 0;
do { do {
int d = n % radix; unsigned d = un % radix;
if (d < 10) if (d < 10)
d += '0'; d += '0';
else else
d += 'A' - 10; d += 'A' - 10;
s[i++] = d; s[i++] = d;
} while ((n /= radix) > 0); } while ((un /= radix) > 0);
if (neg) if (neg)
{ {
@ -524,6 +521,12 @@ void exit(int status)
} }
} }
void abort(void)
{
exit(-1);
}
extern struct Heap { extern struct Heap {
Heap * next, * end; Heap * next, * end;
} HeapNode; } HeapNode;
@ -541,7 +544,7 @@ unsigned heapfree(void)
} }
#if 0 #if 0
struct Heap { struct Heap {q
unsigned int size; unsigned int size;
Heap * next; Heap * next;
} * freeHeap; } * freeHeap;
@ -664,6 +667,97 @@ void * calloc(int num, int size)
return p; return p;
} }
void * realloc(void * ptr, unsigned size)
{
if (ptr)
{
#ifdef HEAPCHECK
Heap * pheap = (Heap *)((char *)ptr - 6);
Heap * eheap = pheap->next;
unsigned psize = (char *)eheap - (char *)pheap;
void * nptr = malloc(size);
memcpy(nptr, ptr, psize - 6);
free(ptr);
return nptr;
#else
unsigned nsize = (size + 5) & ~3;
// Get heap info
Heap * pheap = (Heap *)((char *)ptr - 2);
Heap * eheap = pheap->next;
unsigned psize = (char *)eheap - (char *)pheap;
Heap * h = HeapNode.next;
Heap * hp = &HeapNode;
while (h && h < pheap)
{
hp = h;
h = h->next;
}
if (nsize <= psize)
{
// check if we should free some memory
if (nsize + sizeof(HeapNode) < psize)
{
Heap * nheap = (Heap *)((char *)pheap + nsize);
pheap->next = nheap;
if (h == eheap)
{
nheap->end = h->end;
nheap->next = h->next;
}
else
{
nheap->end = eheap;
nheap->next = h;
}
hp->next = nheap;
}
return ptr;
}
else if (h == eheap)
{
// Free space after this
// Check if enough space if extending
unsigned xsize = (char *)h->end - (char *)pheap;
if (xsize >= nsize)
{
if (xsize > nsize + sizeof(HeapNode))
{
Heap * nheap = (Heap *)((char *)pheap + nsize);
pheap->next = nheap;
nheap->end = h->end;
nheap->next = h->next;
hp->next = nheap;
}
else
{
pheap->next = h->end;
hp->next = h->next;
}
return ptr;
}
}
void * nptr = malloc(size);
memcpy(nptr, ptr, psize - 2);
free(ptr);
return nptr;
#endif
}
else
return malloc(size);
}
static unsigned seed = 31232; static unsigned seed = 31232;
unsigned int rand(void) unsigned int rand(void)

View File

@ -37,12 +37,16 @@ long labs(long n);
void exit(int status); void exit(int status);
void abort(void);
void * malloc(unsigned int size); void * malloc(unsigned int size);
void free(void * ptr); void free(void * ptr);
void * calloc(int num, int size); void * calloc(int num, int size);
void * realloc(void * ptr, unsigned size);
unsigned heapfree(void); unsigned heapfree(void);
unsigned int rand(void); unsigned int rand(void);

View File

@ -138,6 +138,20 @@ char * cpycat(char * dst, const char * src)
#pragma native(cpycat) #pragma native(cpycat)
char* strchr( const char* str, int ch )
{
char * p = (char *)str;
while (*p != (char)ch)
{
if (!*p)
return nullptr;
p++;
}
return p;
}
void * memset(void * dst, int value, int size) void * memset(void * dst, int value, int size)
{ {
__asm __asm
@ -223,8 +237,8 @@ void * memmove(void * dst, const void * src, int size)
int sz = size; int sz = size;
if (sz > 0) if (sz > 0)
{ {
char * d = dst; char * d = (char *)dst;
const char * s = src; const char * s = (const char *)src;
if (d < s) if (d < s)
{ {
do { do {
@ -245,7 +259,7 @@ void * memmove(void * dst, const void * src, int size)
int memcmp(const void * ptr1, const void * ptr2, int size) int memcmp(const void * ptr1, const void * ptr2, int size)
{ {
const char * p = ptr1, * q = ptr2; const char * p = (const char *)ptr1, * q = (const char *)ptr2;
char c, d; char c, d;
while (size--) while (size--)

View File

@ -21,10 +21,16 @@ int memcmp(const void * ptr1, const void * ptr2, int size);
void * memmove(void * dst, const void * src, int size); void * memmove(void * dst, const void * src, int size);
char* strchr( const char* str, int ch );
#pragma intrinsic(strcpy) #pragma intrinsic(strcpy)
#pragma intrinsic(memcpy) #pragma intrinsic(memcpy)
#pragma intrinsic(memset)
#pragma intrinsic(memclr)
#pragma compile("string.c") #pragma compile("string.c")
#endif #endif

View File

@ -1,12 +1,25 @@
project_dir := $(abspath $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))/../)
sources = $(wildcard $(project_dir)/oscar64/*.cpp)
sources = $(wildcard ../oscar64/*.cpp) srcdir := $(if $(srcdir),$(srcdir),$(project_dir)/build)
objects = $(patsubst ../oscar64/%.cpp,%.o,$(sources)) objects = $(patsubst $(project_dir)/oscar64/%.cpp,$(srcdir)/%.o,$(sources))
CXX = c++ CXX = c++
CPPFLAGS = -g -O2 -std=c++11 -Wno-switch CPPFLAGS = -g -O2 -std=c++11 -Wno-switch
SED = /usr/bin/sed
REMOVE_FORCE_ALL = $(RM) --recursive --dir
export OSCAR64_CC = $(project_dir)/bin/oscar64
export OSCAR64_CFLAGS =
export OSCAR64_CXX = $(project_dir)/bin/oscar64
MKDIR_PARENT = /bin/mkdir -p -m 755
INSTALL = /usr/bin/install
INSTALL_PROGRAM = $(INSTALL) -m 755
INSTALL_DATA = $(INSTALL) -m 644
DESTDIR =
prefix = /usr/local
exec_prefix = $(prefix)
bindir = $(exec_prefix)/bin
includedir = $(prefix)/include
$(shell mkdir -p ../bin)
ifdef WINDIR ifdef WINDIR
linklibs = -lpthread linklibs = -lpthread
@ -17,25 +30,86 @@ else
linklibs = -lpthread linklibs = -lpthread
else else
# MSVC
linklibs = -lrt -lpthread linklibs = -lrt -lpthread
# MinGW
#linklibs = -lversion -lpthread
endif endif
endif endif
%.o: ../oscar64/%.cpp
$(CXX) -c $(CPPFLAGS) $< -o $@
%.d: ../oscar64/%.cpp all: compiler samples check
@set -e; rm -f $@; \
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ $(srcdir)/%.o: $(project_dir)/oscar64/%.cpp
rm -f $@.$$$$ @echo "Compiling compiler file" $@ "..." $<
@$(CXX) -c $(CPPFLAGS) $< -o $@
$(srcdir)/%.d: $(project_dir)/oscar64/%.cpp
@$(MKDIR_PARENT) $(srcdir)
@echo "Transforming file" $@ "..." $<
@set -e; \
$(RM) $@; \
$(CC) -MM -MT $(patsubst %.d,%.o,$@) $(CPPFLAGS) $< > $@.$$$$; \
$(SED) 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
$(RM) $@.$$$$
compiler: --prep-build-dir $(objects)
@$(MKDIR_PARENT) $(srcdir)
@echo "Linking compiler..."
$(CXX) $(CPPFLAGS) $(objects) $(linklibs) -o $(project_dir)/bin/oscar64
../bin/oscar64 : $(objects)
$(CXX) $(CPPFLAGS) $(linklibs) $(objects) -o ../bin/oscar64
.PHONY : clean .PHONY : clean
clean : clean :
-rm *.o *.d ../bin/oscar64 @echo "Cleaning compiler..."
@$(RM) $(srcdir)/*.o
@$(RM) $(srcdir)/*.d
@$(RM) $(project_dir)/bin/oscar64
@$(MAKE) -C $(project_dir)/samples clean
@$(MAKE) -C $(project_dir)/autotest clean
.PHONY : distclean
distclean :
@echo "Distribution cleaning compiler..."
@$(REMOVE_FORCE_ALL) $(srcdir)
@$(REMOVE_FORCE_ALL) $(project_dir)/bin
@$(MAKE) -C $(project_dir)/samples clean
@$(MAKE) -C $(project_dir)/autotest clean
samples: compiler
@$(MAKE) -C $(project_dir)/samples all
check: compiler
@$(MAKE) -C $(project_dir)/autotest all
install: compiler
@echo "Installing to" $(DESTDIR)$(prefix)
@$(MKDIR_PARENT) $(DESTDIR)$(bindir)
$(INSTALL_PROGRAM) $(project_dir)/bin/oscar64 $(DESTDIR)$(bindir)
@$(MKDIR_PARENT) $(DESTDIR)$(includedir)/oscar64/{audio,c64,c128,cx16,gfx,nes,opp,plus4,vic20}
$(INSTALL_DATA) $(wildcard $(project_dir)/include/*.h $(project_dir)/include/*.c) $(DESTDIR)$(includedir)/oscar64
$(INSTALL_DATA) $(wildcard $(project_dir)/include/audio/*.h $(project_dir)/include/audio/*.c) $(DESTDIR)$(includedir)/oscar64/audio
$(INSTALL_DATA) $(wildcard $(project_dir)/include/c64/*.h $(project_dir)/include/c64/*.c) $(DESTDIR)$(includedir)/oscar64/c64
$(INSTALL_DATA) $(wildcard $(project_dir)/include/c128/*.h $(project_dir)/include/c128/*.c) $(DESTDIR)$(includedir)/oscar64/c128
$(INSTALL_DATA) $(wildcard $(project_dir)/include/cx16/*.h $(project_dir)/include/cx16/*.c) $(DESTDIR)$(includedir)/oscar64/cx16
$(INSTALL_DATA) $(wildcard $(project_dir)/include/gfx/*.h $(project_dir)/include/gfx/*.c) $(DESTDIR)$(includedir)/oscar64/gfx
$(INSTALL_DATA) $(wildcard $(project_dir)/include/nes/*.h $(project_dir)/include/nes/*.c) $(DESTDIR)$(includedir)/oscar64/nes
$(INSTALL_DATA) $(wildcard $(project_dir)/include/opp/*.h $(project_dir)/include/opp/*.cpp) $(DESTDIR)$(includedir)/oscar64/opp
$(INSTALL_DATA) $(wildcard $(project_dir)/include/plus4/*.h $(project_dir)/include/plus4/*.c) $(DESTDIR)$(includedir)/oscar64/plus4
$(INSTALL_DATA) $(wildcard $(project_dir)/include/vic20/*.h $(project_dir)/include/vic20/*.c) $(DESTDIR)$(includedir)/oscar64/vic20
uninstall:
@echo "Uninstalling..."
@$(RM) $(DESTDIR)$(bindir)/oscar64
@$(REMOVE_FORCE_ALL) $(DESTDIR)$(includedir)/oscar64/
ifeq ($(UNAME_S), Darwin) ifeq ($(UNAME_S), Darwin)
@ -44,3 +118,9 @@ else
include $(objects:.o=.d) include $(objects:.o=.d)
endif endif
--prep-build-dir:
echo "makedir"
@if [ ! -d $(srcdir) ]; then $(MKDIR_PARENT) $(srcdir); fi
@if [ ! -d $(project_dir)/bin ]; then $(MKDIR_PARENT) $(project_dir)/bin; fi

11
makezip.bat Normal file
View File

@ -0,0 +1,11 @@
mkdir r:\oscar64
mkdir r:\oscar64\bin
mkdir r:\oscar64\include
xcopy /y bin\oscar64.exe r:\oscar64\bin
xcopy /y /e include r:\oscar64\include
tar -caf r:\oscar64.zip r:\oscar64

1630
oscar64.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16 # Visual Studio Version 17
VisualStudioVersion = 16.0.31624.102 VisualStudioVersion = 17.13.35931.197
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oscar64", "oscar64\oscar64.vcxproj", "{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oscar64", "oscar64\oscar64.vcxproj", "{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}"
EndProject EndProject
@ -23,10 +23,14 @@ Global
{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}.Release|x64.Build.0 = Release|x64 {1DBC623E-6109-41FE-B1BB-9B43FC984F7D}.Release|x64.Build.0 = Release|x64
{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}.Release|x86.ActiveCfg = Release|Win32 {1DBC623E-6109-41FE-B1BB-9B43FC984F7D}.Release|x86.ActiveCfg = Release|Win32
{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}.Release|x86.Build.0 = Release|Win32 {1DBC623E-6109-41FE-B1BB-9B43FC984F7D}.Release|x86.Build.0 = Release|Win32
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x64.ActiveCfg = Debug {567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x64.ActiveCfg = Debug|x64
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x86.ActiveCfg = Debug {567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x64.Build.0 = Debug|x64
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x64.ActiveCfg = Release {567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x86.ActiveCfg = Debug|x86
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x86.ActiveCfg = Release {567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x86.Build.0 = Debug|x86
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x64.ActiveCfg = Release|x64
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x64.Build.0 = Release|x64
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x86.ActiveCfg = Release|x86
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x86.Build.0 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -421,9 +421,33 @@ protected:
array = a2; array = a2;
} }
for (int i = size; i < to; i++) array[i] = T{};
size = to; size = to;
} }
template<typename F>
void Partition(const F & f, int l, int r)
{
if (r > l + 1)
{
int pi = l;
T p(array[pi]);
for (int i = l + 1; i < r; i++)
{
if (f(array[i], p))
{
array[pi++] = array[i];
array[i] = array[pi];
}
}
array[pi] = p;
Partition(f, l, pi);
Partition(f, pi + 1, r);
}
}
public: public:
ExpandingArray(void) ExpandingArray(void)
{ {
@ -596,6 +620,24 @@ public:
return false; return false;
} }
void Fill(const T& t)
{
for (int i = 0; i < size; i++)
array[i] = t;
}
void Clear(void)
{
for (int i = 0; i < size; i++)
array[i] = T{};
}
template<typename F>
void Sort(const F & f)
{
Partition(f, 0, size);
}
__forceinline T& operator[](int n) __forceinline T& operator[](int n)
{ {
assert(n >= 0 && n < size); assert(n >= 0 && n < size);

View File

@ -293,7 +293,7 @@ const char* AsmInstructionNames[NUM_ASM_INS_TYPES] = {
"INV", "BYT" "INV", "BYT"
}; };
int AsmInsModeSize[NUM_ASM_INS_MODES] = { int AsmInsModeSize[NUM_ASM_INS_MODES_X] = {
1, 1,
2, 2,
2, 2,
@ -306,6 +306,8 @@ int AsmInsModeSize[NUM_ASM_INS_MODES] = {
2, 2,
2, 2,
2, 2,
0,
2
}; };
void InitAssembler(void) void InitAssembler(void)

View File

@ -31,7 +31,9 @@ enum AsmInsMode
NUM_ASM_INS_MODES, NUM_ASM_INS_MODES,
ASMIM_IMMEDIATE_ADDRESS ASMIM_IMMEDIATE_ADDRESS,
NUM_ASM_INS_MODES_X,
}; };
struct AsmInsData struct AsmInsData
@ -45,6 +47,8 @@ extern AsmInsData DecInsData[256];
extern short AsmInsOpcodes[NUM_ASM_INS_TYPES][NUM_ASM_INS_MODES]; extern short AsmInsOpcodes[NUM_ASM_INS_TYPES][NUM_ASM_INS_MODES];
extern int AsmInsModeSize[NUM_ASM_INS_MODES_X];
extern const char* AsmInstructionNames[NUM_ASM_INS_TYPES]; extern const char* AsmInstructionNames[NUM_ASM_INS_TYPES];
AsmInsType FindAsmInstruction(const char * ins); AsmInsType FindAsmInstruction(const char * ins);

View File

@ -3,6 +3,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <assert.h>
class BitVector class BitVector
{ {

View File

@ -144,8 +144,8 @@ static const char* ByteCodeNames[] = {
"LOOP_U8", "LOOP_U8",
"MALLOC", "MALLOC",
"FREE", "FREE",
nullptr, "FILL",
nullptr, "FILL_LONG",
nullptr, nullptr,
"JSR", //114 "JSR", //114
@ -623,6 +623,10 @@ bool ByteCodeInstruction::CheckAccuSize(uint32 & used)
case BC_OP_CEIL_F32: case BC_OP_CEIL_F32:
case BC_CONV_F32_U16: case BC_CONV_F32_U16:
case BC_CONV_F32_I16: case BC_CONV_F32_I16:
case BC_CONV_U32_F32:
case BC_CONV_I32_F32:
case BC_CONV_F32_U32:
case BC_CONV_F32_I32:
used = 0xffffffff; used = 0xffffffff;
break; break;
@ -680,6 +684,8 @@ bool ByteCodeInstruction::CheckAccuSize(uint32 & used)
used = 0xffffffff; used = 0xffffffff;
break; break;
case BC_FILL:
case BC_FILL_LONG:
case BC_COPY: case BC_COPY:
case BC_COPY_LONG: case BC_COPY_LONG:
case BC_STRCPY: case BC_STRCPY:
@ -780,7 +786,7 @@ bool ByteCodeInstruction::UsesRegister(uint32 reg) const
return true; return true;
if (mCode == BC_LEA_ACCU_INDEX) if (mCode == BC_LEA_ACCU_INDEX)
return true; return true;
if (mCode == BC_COPY || mCode == BC_STRCPY) if (mCode == BC_COPY || mCode == BC_STRCPY || mCode == BC_FILL)
return true; return true;
if (mCode == BC_BINOP_ADDA_16) if (mCode == BC_BINOP_ADDA_16)
return true; return true;
@ -793,7 +799,7 @@ bool ByteCodeInstruction::UsesRegister(uint32 reg) const
if (mCode >= BC_LOAD_ADDR_8 && mCode <= BC_STORE_ADDR_32) if (mCode >= BC_LOAD_ADDR_8 && mCode <= BC_STORE_ADDR_32)
return true; return true;
if (mCode == BC_COPY || mCode == BC_STRCPY) if (mCode == BC_COPY || mCode == BC_STRCPY || mCode == BC_FILL)
return true; return true;
if (mCode == BC_JSR || mCode == BC_CALL_ADDR || mCode == BC_CALL_ABS) if (mCode == BC_JSR || mCode == BC_CALL_ADDR || mCode == BC_CALL_ABS)
@ -1212,6 +1218,20 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
block->PutByte(mValue); block->PutByte(mValue);
break; break;
case BC_FILL:
case BC_FILL_LONG:
if (mValue < 256)
{
block->PutCode(generator, BC_FILL);
block->PutByte(uint8(mValue));
}
else
{
block->PutCode(generator, BC_FILL_LONG);
block->PutWord(uint16(mValue));
}
break;
case BC_COPY: case BC_COPY:
case BC_COPY_LONG: case BC_COPY_LONG:
if (mValue < 256) if (mValue < 256)
@ -1262,6 +1282,23 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
block->PutByte(mRegister); block->PutByte(mRegister);
break; break;
} }
case BC_CONV_U32_F32:
case BC_CONV_I32_F32:
case BC_CONV_F32_U32:
case BC_CONV_F32_I32:
{
block->PutCode(generator, BC_EXTRT);
LinkerReference rl;
rl.mOffset = block->mCode.Size();
rl.mFlags = LREF_HIGHBYTE | LREF_LOWBYTE;
rl.mRefObject = generator->mExtByteCodes[mCode - 128];
rl.mRefOffset = 0;
block->mRelocations.Push(rl);
block->PutWord(0);
block->PutByte(mRegister);
break;
}
default: default:
assert(false); assert(false);
@ -1567,6 +1604,30 @@ void ByteCodeBasicBlock::LoadConstant(InterCodeProcedure* proc, const InterInstr
} }
void ByteCodeBasicBlock::FillValue(InterCodeProcedure* proc, const InterInstruction* ins)
{
LoadOperandAddress(proc, ins->mSrc[1], BC_REG_ADDR);
if (ins->mSrc[0].mTemp < 0)
{
ByteCodeInstruction cins(BC_CONST_8);
cins.mRegister = BC_REG_ACCU;
cins.mValue = int(ins->mSrc[0].mIntConst);
mIns.Push(cins);
}
else
{
ByteCodeInstruction lins(BC_LOAD_REG_8);
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
lins.mRegisterFinal = ins->mSrc[0].mFinal;
mIns.Push(lins);
}
ByteCodeInstruction cins(BC_FILL);
cins.mValue = ins->mConst.mOperandSize;
mIns.Push(cins);
}
void ByteCodeBasicBlock::CopyValue(InterCodeProcedure* proc, const InterInstruction * ins) void ByteCodeBasicBlock::CopyValue(InterCodeProcedure* proc, const InterInstruction * ins)
{ {
LoadOperandAddress(proc, ins->mSrc[0], BC_REG_ACCU); LoadOperandAddress(proc, ins->mSrc[0], BC_REG_ACCU);
@ -3400,11 +3461,14 @@ ByteCode ByteCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const
else else
{ {
if (ins->mSrc[1].mTemp < 0) if (ins->mSrc[1].mTemp < 0)
{
if (ins->mSrc[1].mType == IT_INT16 || ins->mSrc[1].mMemory == IM_ABSOLUTE)
{ {
ByteCodeInstruction lins(BC_LOAD_REG_16); ByteCodeInstruction lins(BC_LOAD_REG_16);
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]; lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
lins.mRegisterFinal = ins->mSrc[0].mFinal; lins.mRegisterFinal = ins->mSrc[0].mFinal;
mIns.Push(lins); mIns.Push(lins);
if (csigned) if (csigned)
{ {
ByteCodeInstruction cins(BC_BINOP_CMPSI_16); ByteCodeInstruction cins(BC_BINOP_CMPSI_16);
@ -3418,7 +3482,36 @@ ByteCode ByteCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const
mIns.Push(cins); mIns.Push(cins);
} }
} }
else
{
ByteCodeInstruction bins(BC_LEA_ABS);
bins.mRegister = BC_REG_ACCU;
bins.mLinkerObject = ins->mSrc[1].mLinkerObject;
bins.mValue = int(ins->mSrc[1].mIntConst);
bins.mRelocate = true;
mIns.Push(bins);
if (csigned)
{
ByteCodeInstruction cins(BC_BINOP_CMPSR_16);
cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
cins.mRegisterFinal = ins->mSrc[0].mFinal;
mIns.Push(cins);
}
else
{
ByteCodeInstruction cins(BC_BINOP_CMPUR_16);
cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
cins.mRegisterFinal = ins->mSrc[0].mFinal;
mIns.Push(cins);
}
code = TransposeBranchCondition(code);
}
}
else if (ins->mSrc[0].mTemp < 0) else if (ins->mSrc[0].mTemp < 0)
{
if (ins->mSrc[0].mType == IT_INT16 || ins->mSrc[0].mMemory == IM_ABSOLUTE)
{ {
ByteCodeInstruction lins(BC_LOAD_REG_16); ByteCodeInstruction lins(BC_LOAD_REG_16);
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp]; lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
@ -3491,6 +3584,31 @@ ByteCode ByteCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const
code = TransposeBranchCondition(code); code = TransposeBranchCondition(code);
} }
else else
{
ByteCodeInstruction bins(BC_LEA_ABS);
bins.mRegister = BC_REG_ACCU;
bins.mLinkerObject = ins->mSrc[0].mLinkerObject;
bins.mValue = int(ins->mSrc[0].mIntConst);
bins.mRelocate = true;
mIns.Push(bins);
if (csigned)
{
ByteCodeInstruction cins(BC_BINOP_CMPSR_16);
cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
cins.mRegisterFinal = ins->mSrc[1].mFinal;
mIns.Push(cins);
}
else
{
ByteCodeInstruction cins(BC_BINOP_CMPUR_16);
cins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
cins.mRegisterFinal = ins->mSrc[1].mFinal;
mIns.Push(cins);
}
}
}
else
{ {
ByteCodeInstruction lins(BC_LOAD_REG_16); ByteCodeInstruction lins(BC_LOAD_REG_16);
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp]; lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
@ -3681,6 +3799,67 @@ void ByteCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, const Inter
} break; } break;
case IA_FLOAT2LINT:
{
ByteCodeInstruction lins(BC_LOAD_REG_32);
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
lins.mRegisterFinal = ins->mSrc[0].mFinal;
mIns.Push(lins);
ByteCodeInstruction bins(BC_CONV_F32_I32);
mIns.Push(bins);
ByteCodeInstruction sins(BC_STORE_REG_32);
sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
mIns.Push(sins);
} break;
case IA_LINT2FLOAT:
{
ByteCodeInstruction lins(BC_LOAD_REG_32);
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
lins.mRegisterFinal = ins->mSrc[0].mFinal;
mIns.Push(lins);
ByteCodeInstruction bins(BC_CONV_I32_F32);
mIns.Push(bins);
ByteCodeInstruction sins(BC_STORE_REG_32);
sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
mIns.Push(sins);
} break;
case IA_FLOAT2LUINT:
{
ByteCodeInstruction lins(BC_LOAD_REG_32);
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
lins.mRegisterFinal = ins->mSrc[0].mFinal;
mIns.Push(lins);
ByteCodeInstruction bins(BC_CONV_F32_U32);
mIns.Push(bins);
ByteCodeInstruction sins(BC_STORE_REG_32);
sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
mIns.Push(sins);
} break;
case IA_LUINT2FLOAT:
{
ByteCodeInstruction lins(BC_LOAD_REG_32);
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
lins.mRegisterFinal = ins->mSrc[0].mFinal;
mIns.Push(lins);
ByteCodeInstruction bins(BC_CONV_U32_F32);
mIns.Push(bins);
ByteCodeInstruction sins(BC_STORE_REG_32);
sins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mDst.mTemp];
mIns.Push(sins);
} break;
case IA_EXT8TO16S: case IA_EXT8TO16S:
{ {
if (ins->mSrc[0].mTemp == ins->mDst.mTemp) if (ins->mSrc[0].mTemp == ins->mDst.mTemp)
@ -4320,6 +4499,9 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p
else else
LoadDirectValue(iproc, ins); LoadDirectValue(iproc, ins);
break; break;
case IC_FILL:
FillValue(iproc, ins);
break;
case IC_COPY: case IC_COPY:
CopyValue(iproc, ins); CopyValue(iproc, ins);
break; break;
@ -6423,7 +6605,7 @@ void ByteCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedure
{ {
mID = proc->mID; mID = proc->mID;
mNumBlocks = proc->mBlocks.Size(); mNumBlocks = proc->mNumBlocks;
tblocks = new ByteCodeBasicBlock * [mNumBlocks]; tblocks = new ByteCodeBasicBlock * [mNumBlocks];
for (int i = 0; i < mNumBlocks; i++) for (int i = 0; i < mNumBlocks; i++)

View File

@ -145,8 +145,8 @@ enum ByteCode
BC_LOOP_U8, BC_LOOP_U8,
BC_MALLOC, BC_MALLOC,
BC_FREE, BC_FREE,
BC_UNUSED_4, BC_FILL,
BC_UNUSED_5, BC_FILL_LONG,
BC_UNUSED_6, BC_UNUSED_6,
BC_JSR, BC_JSR,
@ -186,7 +186,12 @@ enum ByteCode
BC_BINOP_SHR_U32, BC_BINOP_SHR_U32,
BC_BINOP_SHR_I32, BC_BINOP_SHR_I32,
BC_BINOP_CMP_U32, BC_BINOP_CMP_U32,
BC_BINOP_CMP_S32 BC_BINOP_CMP_S32,
BC_CONV_U32_F32,
BC_CONV_I32_F32,
BC_CONV_F32_U32,
BC_CONV_F32_I32,
}; };
class ByteCodeProcedure; class ByteCodeProcedure;
@ -281,6 +286,7 @@ public:
void IntConstToAddr(int64 val); void IntConstToAddr(int64 val);
void FloatConstToAccu(double val); void FloatConstToAccu(double val);
void FloatConstToWork(double val); void FloatConstToWork(double val);
void FillValue(InterCodeProcedure* proc, const InterInstruction* ins);
void CopyValue(InterCodeProcedure* proc, const InterInstruction * ins); void CopyValue(InterCodeProcedure* proc, const InterInstruction * ins);
void StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins); void StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins);
void CallMalloc(InterCodeProcedure* proc, const InterInstruction* ins); void CallMalloc(InterCodeProcedure* proc, const InterInstruction* ins);

View File

@ -174,13 +174,13 @@ void Compiler::RegisterRuntime(const Location & loc, const Ident* ident)
if (bcdec->mType == DT_CONST_ASSEMBLER) if (bcdec->mType == DT_CONST_ASSEMBLER)
{ {
if (!bcdec->mLinkerObject) if (!bcdec->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr); mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec, nullptr);
linkerObject = bcdec->mLinkerObject; linkerObject = bcdec->mLinkerObject;
} }
else if (bcdec->mType == DT_LABEL) else if (bcdec->mType == DT_LABEL)
{ {
if (!bcdec->mBase->mLinkerObject) if (!bcdec->mBase->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue, nullptr); mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase, nullptr);
linkerObject = bcdec->mBase->mLinkerObject; linkerObject = bcdec->mBase->mLinkerObject;
offset = int(bcdec->mInteger); offset = int(bcdec->mInteger);
@ -466,7 +466,7 @@ void Compiler::CompileProcedure(InterCodeProcedure* proc)
printf("Generate native code <%s>\n", proc->mIdent->mString); printf("Generate native code <%s>\n", proc->mIdent->mString);
ncproc->Compile(proc); ncproc->Compile(proc);
mNativeProcedures.Push(ncproc); mNativeCodeGenerator->mProcedures.Push(ncproc);
} }
else else
{ {
@ -508,6 +508,8 @@ bool Compiler::GenerateCode(void)
regionZeroPage = mLinker->AddRegion(identZeroPage, 0x00e0, 0x00ff); regionZeroPage = mLinker->AddRegion(identZeroPage, 0x00e0, 0x00ff);
else if (mCompilerOptions & (COPT_EXTENDED_ZERO_PAGE | COPT_TARGET_NES)) else if (mCompilerOptions & (COPT_EXTENDED_ZERO_PAGE | COPT_TARGET_NES))
regionZeroPage = mLinker->AddRegion(identZeroPage, 0x0080, 0x00ff); regionZeroPage = mLinker->AddRegion(identZeroPage, 0x0080, 0x00ff);
else if (mTargetMachine == TMACH_PET_8K || mTargetMachine == TMACH_PET_16K || mTargetMachine == TMACH_PET_32K)
regionZeroPage = mLinker->AddRegion(identZeroPage, 0x00ed, 0x00f7);
else else
regionZeroPage = mLinker->AddRegion(identZeroPage, 0x00f7, 0x00ff); regionZeroPage = mLinker->AddRegion(identZeroPage, 0x00f7, 0x00ff);
} }
@ -521,6 +523,12 @@ bool Compiler::GenerateCode(void)
{ {
switch (mTargetMachine) switch (mTargetMachine)
{ {
case TMACH_MEGA65:
if (mCompilerOptions & COPT_NATIVE)
regionStartup = mLinker->AddRegion(identStartup, 0x2001, 0x2080);
else
regionStartup = mLinker->AddRegion(identStartup, 0x2001, 0x2100);
break;
case TMACH_C64: case TMACH_C64:
case TMACH_X16: case TMACH_X16:
if (mCompilerOptions & COPT_NATIVE) if (mCompilerOptions & COPT_NATIVE)
@ -552,12 +560,12 @@ bool Compiler::GenerateCode(void)
if (mCompilerOptions & COPT_NATIVE) if (mCompilerOptions & COPT_NATIVE)
{ {
regionStartup = mLinker->AddRegion(identStartup, 0x1001, 0x1080); regionStartup = mLinker->AddRegion(identStartup, 0x1001, 0x1080);
regionLowcode = mLinker->AddRegion(identLowcode, 0x1080, 0x1100); regionLowcode = mLinker->AddRegion(identLowcode, 0x1080, 0x1180);
} }
else else
{ {
regionStartup = mLinker->AddRegion(identStartup, 0x1001, 0x1080); regionStartup = mLinker->AddRegion(identStartup, 0x1001, 0x1080);
regionLowcode = mLinker->AddRegion(identLowcode, 0x1080, 0x1000); regionLowcode = mLinker->AddRegion(identLowcode, 0x1080, 0x1180);
} }
regionLowcode->mSections.Push(mCompilationUnits->mSectionLowCode); regionLowcode->mSections.Push(mCompilationUnits->mSectionLowCode);
break; break;
@ -623,6 +631,9 @@ bool Compiler::GenerateCode(void)
{ {
switch (mTargetMachine) switch (mTargetMachine)
{ {
case TMACH_MEGA65:
regionBytecode = mLinker->AddRegion(identBytecode, 0x2100, 0x2200);
break;
case TMACH_C64: case TMACH_C64:
case TMACH_X16: case TMACH_X16:
regionBytecode = mLinker->AddRegion(identBytecode, 0x0900, 0x0a00); regionBytecode = mLinker->AddRegion(identBytecode, 0x0900, 0x0a00);
@ -633,6 +644,8 @@ bool Compiler::GenerateCode(void)
regionBytecode = mLinker->AddRegion(identBytecode, 0x1d00, 0x1e00); regionBytecode = mLinker->AddRegion(identBytecode, 0x1d00, 0x1e00);
break; break;
case TMACH_PLUS4: case TMACH_PLUS4:
regionBytecode = mLinker->AddRegion(identBytecode, 0x1200, 0x1300);
break;
case TMACH_VIC20: case TMACH_VIC20:
regionBytecode = mLinker->AddRegion(identBytecode, 0x1100, 0x1200); regionBytecode = mLinker->AddRegion(identBytecode, 0x1100, 0x1200);
break; break;
@ -682,6 +695,9 @@ bool Compiler::GenerateCode(void)
{ {
switch (mTargetMachine) switch (mTargetMachine)
{ {
case TMACH_MEGA65:
regionMain = mLinker->AddRegion(identMain, 0x2300, 0xc000);
break;
case TMACH_C64: case TMACH_C64:
regionMain = mLinker->AddRegion(identMain, 0x0a00, 0xa000); regionMain = mLinker->AddRegion(identMain, 0x0a00, 0xa000);
break; break;
@ -698,7 +714,7 @@ bool Compiler::GenerateCode(void)
regionMain = mLinker->AddRegion(identMain, 0x1e00, 0xc000); regionMain = mLinker->AddRegion(identMain, 0x1e00, 0xc000);
break; break;
case TMACH_PLUS4: case TMACH_PLUS4:
regionMain = mLinker->AddRegion(identMain, 0x1200, 0xfc00); regionMain = mLinker->AddRegion(identMain, 0x1300, 0xfc00);
break; break;
case TMACH_VIC20: case TMACH_VIC20:
regionMain = mLinker->AddRegion(identMain, 0x1200, 0x1e00); regionMain = mLinker->AddRegion(identMain, 0x1200, 0x1e00);
@ -733,6 +749,14 @@ bool Compiler::GenerateCode(void)
{ {
switch (mTargetMachine) switch (mTargetMachine)
{ {
case TMACH_MEGA65:
// TODO: Disable M65 cartridges for now.
//
// if (mCompilerOptions & (COPT_TARGET_CRT8 | COPT_TARGET_CRT16))
// regionMain = mLinker->AddRegion(identMain, 0x2666, 0xff00);
// else
regionMain = mLinker->AddRegion(identMain, 0x2080, 0xc000);
break;
case TMACH_C64: case TMACH_C64:
if (mCompilerOptions & (COPT_TARGET_CRT8 | COPT_TARGET_CRT16)) if (mCompilerOptions & (COPT_TARGET_CRT8 | COPT_TARGET_CRT16))
@ -753,7 +777,7 @@ bool Compiler::GenerateCode(void)
regionMain = mLinker->AddRegion(identMain, 0x1c80, 0xc000); regionMain = mLinker->AddRegion(identMain, 0x1c80, 0xc000);
break; break;
case TMACH_PLUS4: case TMACH_PLUS4:
regionMain = mLinker->AddRegion(identMain, 0x1100, 0xfc00); regionMain = mLinker->AddRegion(identMain, 0x1180, 0xfc00);
break; break;
case TMACH_VIC20: case TMACH_VIC20:
regionMain = mLinker->AddRegion(identMain, 0x1080, 0x1e00); regionMain = mLinker->AddRegion(identMain, 0x1080, 0x1e00);
@ -908,7 +932,7 @@ bool Compiler::GenerateCode(void)
if (mCompilerOptions & COPT_VERBOSE) if (mCompilerOptions & COPT_VERBOSE)
printf("Generate intermediate code\n"); printf("Generate intermediate code\n");
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, dcrtstart->mValue, nullptr); mInterCodeGenerator->TranslateAssembler(mInterCodeModule, dcrtstart, nullptr);
for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++) for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++)
{ {
Declaration* dec = mCompilationUnits->mReferenced[i]; Declaration* dec = mCompilationUnits->mReferenced[i];
@ -917,13 +941,19 @@ bool Compiler::GenerateCode(void)
if (!dec->mLinkerObject) if (!dec->mLinkerObject)
mInterCodeGenerator->TranslateProcedure(mInterCodeModule, dec->mValue, dec); mInterCodeGenerator->TranslateProcedure(mInterCodeModule, dec->mValue, dec);
} }
else }
for (int i = 0; i < mCompilationUnits->mReferenced.Size(); i++)
{
Declaration* dec = mCompilationUnits->mReferenced[i];
if (dec->mType != DT_CONST_FUNCTION)
{ {
if (!dec->mLinkerObject) if (!dec->mLinkerObject)
mInterCodeGenerator->InitGlobalVariable(mInterCodeModule, dec); mInterCodeGenerator->InitGlobalVariable(mInterCodeModule, dec);
} }
} }
mInterCodeGenerator->CompleteMainInit();
if (mErrors->mErrorCount != 0) if (mErrors->mErrorCount != 0)
return false; return false;
@ -935,7 +965,8 @@ bool Compiler::GenerateCode(void)
RegisterRuntime(loc, Ident::Unique("fsplitt")); RegisterRuntime(loc, Ident::Unique("fsplitt"));
RegisterRuntime(loc, Ident::Unique("fsplitx")); RegisterRuntime(loc, Ident::Unique("fsplitx"));
RegisterRuntime(loc, Ident::Unique("fsplita")); RegisterRuntime(loc, Ident::Unique("fsplita"));
RegisterRuntime(loc, Ident::Unique("faddsub")); RegisterRuntime(loc, Ident::Unique("fadd"));
RegisterRuntime(loc, Ident::Unique("fsub"));
RegisterRuntime(loc, Ident::Unique("fmul")); RegisterRuntime(loc, Ident::Unique("fmul"));
RegisterRuntime(loc, Ident::Unique("fdiv")); RegisterRuntime(loc, Ident::Unique("fdiv"));
RegisterRuntime(loc, Ident::Unique("mul16")); RegisterRuntime(loc, Ident::Unique("mul16"));
@ -948,8 +979,12 @@ bool Compiler::GenerateCode(void)
RegisterRuntime(loc, Ident::Unique("fceil")); RegisterRuntime(loc, Ident::Unique("fceil"));
RegisterRuntime(loc, Ident::Unique("ftoi")); RegisterRuntime(loc, Ident::Unique("ftoi"));
RegisterRuntime(loc, Ident::Unique("ftou")); RegisterRuntime(loc, Ident::Unique("ftou"));
RegisterRuntime(loc, Ident::Unique("ftoli"));
RegisterRuntime(loc, Ident::Unique("ftolu"));
RegisterRuntime(loc, Ident::Unique("ffromi")); RegisterRuntime(loc, Ident::Unique("ffromi"));
RegisterRuntime(loc, Ident::Unique("ffromu")); RegisterRuntime(loc, Ident::Unique("ffromu"));
RegisterRuntime(loc, Ident::Unique("ffromli"));
RegisterRuntime(loc, Ident::Unique("ffromlu"));
RegisterRuntime(loc, Ident::Unique("fcmp")); RegisterRuntime(loc, Ident::Unique("fcmp"));
RegisterRuntime(loc, Ident::Unique("bcexec")); RegisterRuntime(loc, Ident::Unique("bcexec"));
RegisterRuntime(loc, Ident::Unique("jmpaddr")); RegisterRuntime(loc, Ident::Unique("jmpaddr"));
@ -959,8 +994,12 @@ bool Compiler::GenerateCode(void)
RegisterRuntime(loc, Ident::Unique("divu32")); RegisterRuntime(loc, Ident::Unique("divu32"));
RegisterRuntime(loc, Ident::Unique("modu32")); RegisterRuntime(loc, Ident::Unique("modu32"));
RegisterRuntime(loc, Ident::Unique("store32"));
RegisterRuntime(loc, Ident::Unique("load32"));
RegisterRuntime(loc, Ident::Unique("malloc")); RegisterRuntime(loc, Ident::Unique("malloc"));
RegisterRuntime(loc, Ident::Unique("free")); RegisterRuntime(loc, Ident::Unique("free"));
RegisterRuntime(loc, Ident::Unique("breakpoint"));
} }
// Register extended byte code functions // Register extended byte code functions
@ -976,7 +1015,7 @@ bool Compiler::GenerateCode(void)
if (bcdec->mType == DT_CONST_ASSEMBLER) if (bcdec->mType == DT_CONST_ASSEMBLER)
{ {
if (!bcdec->mLinkerObject) if (!bcdec->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr); mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec, nullptr);
mByteCodeGenerator->mExtByteCodes[i] = bcdec->mLinkerObject; mByteCodeGenerator->mExtByteCodes[i] = bcdec->mLinkerObject;
} }
} }
@ -1019,13 +1058,18 @@ bool Compiler::GenerateCode(void)
mCompilationUnits->mSectionStack->mSections.Push(proc->mLinkerObject->mStackSection); mCompilationUnits->mSectionStack->mSections.Push(proc->mLinkerObject->mStackSection);
} }
mNativeCodeGenerator->OutlineFunctions();
mNativeCodeGenerator->BuildFunctionProxies(); mNativeCodeGenerator->BuildFunctionProxies();
for (int i = 0; i < mNativeProcedures.Size(); i++) for (int i = 0; i < mNativeCodeGenerator->mProcedures.Size(); i++)
{ {
if (mCompilerOptions & COPT_VERBOSE2) if (mCompilerOptions & COPT_VERBOSE2)
printf("Assemble native code <%s>\n", mNativeProcedures[i]->mInterProc->mIdent->mString); {
mNativeProcedures[i]->Assemble(); if (mNativeCodeGenerator->mProcedures[i]->mInterProc)
printf("Assemble native code <%s>\n", mNativeCodeGenerator->mProcedures[i]->mInterProc->mIdent->mString);
}
mNativeCodeGenerator->mProcedures[i]->Assemble();
} }
LinkerObject* byteCodeObject = nullptr; LinkerObject* byteCodeObject = nullptr;
@ -1051,13 +1095,13 @@ bool Compiler::GenerateCode(void)
if (bcdec->mType == DT_CONST_ASSEMBLER) if (bcdec->mType == DT_CONST_ASSEMBLER)
{ {
if (!bcdec->mLinkerObject) if (!bcdec->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr); mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec, nullptr);
linkerObject = bcdec->mLinkerObject; linkerObject = bcdec->mLinkerObject;
} }
else if (bcdec->mType == DT_LABEL) else if (bcdec->mType == DT_LABEL)
{ {
if (!bcdec->mBase->mLinkerObject) if (!bcdec->mBase->mLinkerObject)
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue, nullptr); mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase, nullptr);
linkerObject = bcdec->mBase->mLinkerObject; linkerObject = bcdec->mBase->mLinkerObject;
offset = int(bcdec->mInteger); offset = int(bcdec->mInteger);
} }
@ -1175,9 +1219,85 @@ bool Compiler::BuildLZO(const char* targetPath)
} }
} }
bool Compiler::RemoveErrorFile(const char* targetPath)
{
char prgPath[200], mapPath[200], asmPath[200], intPath[200];
char basePath[200];
strcpy_s(basePath, targetPath);
ptrdiff_t i = strlen(basePath);
while (i > 0 && basePath[i - 1] != '/' && basePath[i - 1] != '\\' && basePath[i - 1] != ':')
i--;
if (i > 0)
basePath[i] = 0;
strcpy_s(prgPath, targetPath);
i = strlen(prgPath);
while (i > 0 && prgPath[i - 1] != '.')
i--;
if (i > 0)
prgPath[i] = 0;
strcpy_s(mapPath, prgPath);
strcpy_s(asmPath, prgPath);
strcpy_s(intPath, prgPath);
strcat_s(mapPath, "error.map");
strcat_s(asmPath, "error.asm");
strcat_s(intPath, "error.int");
remove(mapPath);
remove(asmPath);
remove(intPath);
return true;
}
bool Compiler::WriteErrorFile(const char* targetPath)
{
char prgPath[200], mapPath[200], asmPath[200], intPath[200];
char basePath[200];
strcpy_s(basePath, targetPath);
ptrdiff_t i = strlen(basePath);
while (i > 0 && basePath[i - 1] != '/' && basePath[i - 1] != '\\' && basePath[i - 1] != ':')
i--;
if (i > 0)
basePath[i] = 0;
strcpy_s(prgPath, targetPath);
i = strlen(prgPath);
while (i > 0 && prgPath[i - 1] != '.')
i--;
if (i > 0)
prgPath[i] = 0;
strcpy_s(mapPath, prgPath);
strcpy_s(asmPath, prgPath);
strcpy_s(intPath, prgPath);
strcat_s(mapPath, "error.map");
strcat_s(asmPath, "error.asm");
strcat_s(intPath, "error.int");
if (mCompilerOptions & COPT_VERBOSE)
printf("Writing <%s>\n", mapPath);
mLinker->WriteMapFile(mapPath);
if (mCompilerOptions & COPT_VERBOSE)
printf("Writing <%s>\n", asmPath);
mLinker->WriteAsmFile(asmPath, mVersion);
if (mCompilerOptions & COPT_VERBOSE)
printf("Writing <%s>\n", intPath);
mInterCodeModule->Disassemble(intPath);
return true;
}
bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64) bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
{ {
char prgPath[200], mapPath[200], asmPath[200], lblPath[200], intPath[200], bcsPath[200], dbjPath[200]; char prgPath[200], mapPath[200], asmPath[200], lblPath[200], intPath[200], bcsPath[200], dbjPath[200], cszPath[200];
char basePath[200]; char basePath[200];
strcpy_s(basePath, targetPath); strcpy_s(basePath, targetPath);
@ -1200,6 +1320,7 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
strcpy_s(intPath, prgPath); strcpy_s(intPath, prgPath);
strcpy_s(bcsPath, prgPath); strcpy_s(bcsPath, prgPath);
strcpy_s(dbjPath, prgPath); strcpy_s(dbjPath, prgPath);
strcpy_s(cszPath, prgPath);
strcat_s(mapPath, "map"); strcat_s(mapPath, "map");
strcat_s(asmPath, "asm"); strcat_s(asmPath, "asm");
@ -1207,6 +1328,7 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
strcat_s(intPath, "int"); strcat_s(intPath, "int");
strcat_s(bcsPath, "bcs"); strcat_s(bcsPath, "bcs");
strcat_s(dbjPath, "dbj"); strcat_s(dbjPath, "dbj");
strcat_s(cszPath, "csz");
if (mCompilerOptions & COPT_TARGET_PRG) if (mCompilerOptions & COPT_TARGET_PRG)
{ {
@ -1289,6 +1411,9 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
if (mCompilerOptions & COPT_DEBUGINFO) if (mCompilerOptions & COPT_DEBUGINFO)
WriteDbjFile(dbjPath); WriteDbjFile(dbjPath);
if (mCompilerOptions & COPT_PROFILEINFO)
WriteCszFile(cszPath);
if (!(mCompilerOptions & COPT_NATIVE)) if (!(mCompilerOptions & COPT_NATIVE))
{ {
if (mCompilerOptions & COPT_VERBOSE) if (mCompilerOptions & COPT_VERBOSE)
@ -1355,6 +1480,111 @@ static void DumpReferences(FILE* file, Declaration* dec)
} }
bool Compiler::WriteCszFile(const char* filename)
{
FILE* file;
fopen_s(&file, filename, "wb");
if (file)
{
for (int i = 0; i < mInterCodeModule->mProcedures.Size(); i++)
{
InterCodeProcedure* p(mInterCodeModule->mProcedures[i]);
if (p->mLinkerObject && p->mIdent && p->mDeclaration)
{
LinkerObject* lo = p->mLinkerObject;
struct SourceCount
{
const char* mFileName;
int mLine, mAddress;
int mBytes;
};
ExpandingArray<SourceCount> ea;
for (int j = 0; j < lo->mCodeLocations.Size(); j++)
{
const CodeLocation& co(lo->mCodeLocations[j]);
const Location* ls = &(co.mLocation);
while (ls->mFrom)
ls = ls->mFrom;
int k = 0;
while (k < ea.Size() && (ea[k].mFileName != ls->mFileName || ea[k].mLine != ls->mLine))
k++;
if (k == ea.Size())
{
SourceCount sc;
sc.mFileName = ls->mFileName;
sc.mLine = ls->mLine;
sc.mBytes = 0;
sc.mAddress = co.mStart + lo->mAddress;
ea.Push(sc);
}
ea[k].mBytes += co.mEnd - co.mStart;
}
if (ea.Size())
{
ea.Sort([](const SourceCount& l, const SourceCount& r)->bool {
return l.mFileName == r.mFileName ? l.mLine < r.mLine : l.mAddress < r.mAddress;
});
FILE* fsrc;
fopen_s(&fsrc, ea[0].mFileName, "r");
if (fsrc)
{
fprintf(file, "<%s, %s>\n", p->mDeclaration->mQualIdent->mString, ea[0].mFileName);
#if 0
for (int i = 0; i < ea.Size(); i++)
{
fprintf(file, "%s:%d : %d\n", ea[i].mFileName, ea[i].mLine, ea[i].mBytes);
}
#endif
int k = 0, l = 1;
char line[1024];
while (k < ea.Size() && fgets(line, 1024, fsrc))
{
size_t ll = strlen(line);
while (ll > 0 && (line[ll - 1] == '\r' || line[ll - 1] == '\n'))
ll--;
line[ll] = 0;
if (l < ea[k].mLine)
{
if (k > 0)
fprintf(file, "%5d,---- ( ) : %s\n", l, line);
}
else
{
int ks = k, sum = 0;
do {
sum += ea[ks].mBytes;
ks++;
} while (ks < ea.Size() && ea[ks].mFileName != ea[0].mFileName);
fprintf(file, "%5d,%04x (%3d) : %s\n", l, ea[k].mAddress, ea[k].mBytes, line);
k = ks;
}
l++;
}
fclose(fsrc);
fprintf(file, "\n");
}
}
}
}
fclose(file);
return true;
}
else
return false;
}
bool Compiler::WriteDbjFile(const char* filename) bool Compiler::WriteDbjFile(const char* filename)
{ {
FILE* file; FILE* file;

View File

@ -29,7 +29,6 @@ public:
GlobalOptimizer* mGlobalOptimizer; GlobalOptimizer* mGlobalOptimizer;
GrowingArray<ByteCodeProcedure*> mByteCodeFunctions; GrowingArray<ByteCodeProcedure*> mByteCodeFunctions;
ExpandingArray<NativeCodeProcedure*> mNativeProcedures;
TargetMachine mTargetMachine; TargetMachine mTargetMachine;
uint64 mCompilerOptions; uint64 mCompilerOptions;
@ -48,6 +47,8 @@ public:
bool ParseSource(void); bool ParseSource(void);
bool GenerateCode(void); bool GenerateCode(void);
bool WriteOutputFile(const char* targetPath, DiskImage * d64); bool WriteOutputFile(const char* targetPath, DiskImage * d64);
bool WriteErrorFile(const char* targetPath);
bool RemoveErrorFile(const char* targetPath);
int ExecuteCode(bool profile, int trace); int ExecuteCode(bool profile, int trace);
void AddDefine(const Ident* ident, const char* value); void AddDefine(const Ident* ident, const char* value);
@ -59,4 +60,5 @@ public:
void CompleteTemplateExpansion(void); void CompleteTemplateExpansion(void);
bool WriteDbjFile(const char* filename); bool WriteDbjFile(const char* filename);
bool WriteCszFile(const char* filename);
}; };

View File

@ -14,6 +14,8 @@ static const uint64 COPT_OPTIMIZE_AUTO_ZEROPAGE = 1ULL << 8;
static const uint64 COPT_OPTIMIZE_CONST_PARAMS = 1ULL << 9; static const uint64 COPT_OPTIMIZE_CONST_PARAMS = 1ULL << 9;
static const uint64 COPT_OPTIMIZE_MERGE_CALLS = 1ULL << 10; static const uint64 COPT_OPTIMIZE_MERGE_CALLS = 1ULL << 10;
static const uint64 COPT_OPTIMIZE_GLOBAL = 1ULL << 11; static const uint64 COPT_OPTIMIZE_GLOBAL = 1ULL << 11;
static const uint64 COPT_OPTIMIZE_OUTLINE = 1ULL << 12;
static const uint64 COPT_OPTIMIZE_PAGE_CROSSING = 1ULL << 13;
static const uint64 COPT_OPTIMIZE_CODE_SIZE = 1ULL << 16; static const uint64 COPT_OPTIMIZE_CODE_SIZE = 1ULL << 16;
static const uint64 COPT_NATIVE = 1ULL << 17; static const uint64 COPT_NATIVE = 1ULL << 17;
@ -38,6 +40,11 @@ static const uint64 COPT_VERBOSE3 = 1ULL << 50;
static const uint64 COPT_DEBUGINFO = 1ULL << 51; static const uint64 COPT_DEBUGINFO = 1ULL << 51;
static const uint64 COPT_CPLUSPLUS = 1ULL << 52; static const uint64 COPT_CPLUSPLUS = 1ULL << 52;
static const uint64 COPT_PETSCII = 1ULL << 53;
static const uint64 COPT_ERROR_FILES = 1ULL << 54;
static const uint64 COPT_PROFILEINFO = 1ULL << 55;
static const uint64 COPT_STRICT = 1ULL << 56;
@ -45,7 +52,7 @@ static const uint64 COPT_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE |
static const uint64 COPT_OPTIMIZE_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS; static const uint64 COPT_OPTIMIZE_DEFAULT = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS;
static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL; static const uint64 COPT_OPTIMIZE_SIZE = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_CODE_SIZE | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL;// | COPT_OPTIMIZE_OUTLINE;
static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL; static const uint64 COPT_OPTIMIZE_SPEED = COPT_OPTIMIZE_BASIC | COPT_OPTIMIZE_INLINE | COPT_OPTIMIZE_AUTO_INLINE | COPT_OPTIMIZE_AUTO_UNROLL | COPT_OPTIMIZE_CONST_EXPRESSIONS | COPT_OPTIMIZE_ASSEMBLER | COPT_OPTIMIZE_CONST_PARAMS | COPT_OPTIMIZE_MERGE_CALLS | COPT_OPTIMIZE_GLOBAL;
@ -72,7 +79,8 @@ enum TargetMachine
TMACH_NES_MMC1, TMACH_NES_MMC1,
TMACH_NES_MMC3, TMACH_NES_MMC3,
TMACH_ATARI, TMACH_ATARI,
TMACH_X16 TMACH_X16,
TMACH_MEGA65
}; };

View File

@ -11,7 +11,7 @@ int CompressLZO(uint8* dst, const uint8* source, int size)
while (pi < 127 && pos < size) while (pi < 127 && pos < size)
{ {
int bi = pi, bj = 0; int bi = pi, bj = 0;
for (int i = 1; i < (pos < 255 ? pos : 255); i++) for (int i = 1; i <= (pos < 255 ? pos : 255); i++)
{ {
int j = 0; int j = 0;
while (j < 127 && pos + j < size && source[pos - i + j] == source[pos + j]) while (j < 127 && pos + j < size && source[pos - i + j] == source[pos + j])

View File

@ -2,7 +2,7 @@
#include <math.h> #include <math.h>
ConstexprInterpreter::Value::Value(void) ConstexprInterpreter::Value::Value(void)
: mDecType(TheVoidTypeDeclaration), : mDecType(TheVoidTypeDeclaration), mDecValue(nullptr),
mBaseValue(nullptr), mOffset(0), mBaseValue(nullptr), mOffset(0),
mData(mShortData), mDataSize(0) mData(mShortData), mDataSize(0)
{ {
@ -10,7 +10,7 @@ ConstexprInterpreter::Value::Value(void)
ConstexprInterpreter::Value::Value(const Location & location) ConstexprInterpreter::Value::Value(const Location & location)
: mLocation(location), : mLocation(location),
mDecType(TheVoidTypeDeclaration), mDecType(TheVoidTypeDeclaration), mDecValue(nullptr),
mBaseValue(nullptr), mOffset(0), mBaseValue(nullptr), mOffset(0),
mData(mShortData), mDataSize(0) mData(mShortData), mDataSize(0)
{ {
@ -18,7 +18,7 @@ ConstexprInterpreter::Value::Value(const Location & location)
ConstexprInterpreter::Value::Value(Expression* exp) ConstexprInterpreter::Value::Value(Expression* exp)
: mLocation(exp->mLocation), : mLocation(exp->mLocation),
mDecType(exp->mDecType), mDecType(exp->mDecType), mDecValue(nullptr),
mBaseValue(nullptr), mOffset(0), mBaseValue(nullptr), mOffset(0),
mDataSize(exp->mDecType->mSize) mDataSize(exp->mDecType->mSize)
{ {
@ -51,12 +51,15 @@ void ConstexprInterpreter::Value::PutConst(int offset, Declaration* dec)
for (int i = 0; i < dec->mBase->mSize; i++) for (int i = 0; i < dec->mBase->mSize; i++)
PutIntAt(dec->mData[i], offset + i, TheConstCharTypeDeclaration); PutIntAt(dec->mData[i], offset + i, TheConstCharTypeDeclaration);
break; break;
case DT_CONST_POINTER:
PutPtrAt(new Value(mLocation, dec->mValue->mDecValue, dec->mBase, 0), offset, dec);
break;
} }
} }
ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec) ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec)
: mLocation(location), : mLocation(location),
mDecType(dec), mDecType(dec), mDecValue(nullptr),
mBaseValue(nullptr), mOffset(0), mBaseValue(nullptr), mOffset(0),
mDataSize(dec->mSize) mDataSize(dec->mSize)
{ {
@ -68,7 +71,7 @@ ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec)
ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec, int size) ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec, int size)
: mLocation(location), : mLocation(location),
mDecType(dec), mDecType(dec), mDecValue(nullptr),
mBaseValue(nullptr), mOffset(0), mBaseValue(nullptr), mOffset(0),
mDataSize(size) mDataSize(size)
{ {
@ -80,7 +83,7 @@ ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec, i
ConstexprInterpreter::Value::Value(const Value& value) ConstexprInterpreter::Value::Value(const Value& value)
: mLocation(value.mLocation), : mLocation(value.mLocation),
mDecType(value.mDecType), mDecType(value.mDecType), mDecValue(nullptr),
mBaseValue(value.mBaseValue), mOffset(value.mOffset), mBaseValue(value.mBaseValue), mOffset(value.mOffset),
mDataSize(value.mDataSize) mDataSize(value.mDataSize)
@ -96,7 +99,7 @@ ConstexprInterpreter::Value::Value(const Value& value)
ConstexprInterpreter::Value::Value(Value&& value) ConstexprInterpreter::Value::Value(Value&& value)
: mLocation(value.mLocation), : mLocation(value.mLocation),
mDecType(value.mDecType), mDecType(value.mDecType), mDecValue(nullptr),
mBaseValue(value.mBaseValue), mOffset(value.mOffset), mBaseValue(value.mBaseValue), mOffset(value.mOffset),
mDataSize(value.mDataSize) mDataSize(value.mDataSize)
{ {
@ -115,7 +118,7 @@ ConstexprInterpreter::Value::Value(Value&& value)
ConstexprInterpreter::Value::Value(Value* value) ConstexprInterpreter::Value::Value(Value* value)
: mLocation(value->mLocation), : mLocation(value->mLocation),
mDecType(value->mDecType), mDecType(value->mDecType), mDecValue(value->mDecValue),
mBaseValue(value), mOffset(0), mBaseValue(value), mOffset(0),
mDataSize(0), mData(mShortData) mDataSize(0), mData(mShortData)
{ {
@ -123,15 +126,23 @@ ConstexprInterpreter::Value::Value(Value* value)
ConstexprInterpreter::Value::Value(const Location& location, Value* value, Declaration* type, int offset) ConstexprInterpreter::Value::Value(const Location& location, Value* value, Declaration* type, int offset)
: mLocation(location), : mLocation(location),
mDecType(type), mDecType(type), mDecValue(nullptr),
mBaseValue(value), mOffset(offset), mBaseValue(value), mOffset(offset),
mDataSize(0), mData(mShortData) mDataSize(0), mData(mShortData)
{ {
} }
ConstexprInterpreter::Value::Value(const Location& location, Declaration* value, Declaration* type, int offset)
: mLocation(location),
mDecType(type), mDecValue(value),
mBaseValue(nullptr), mOffset(offset),
mDataSize(0), mData(mShortData)
{
}
ConstexprInterpreter::Value::Value(const Location& location, const uint8* data, Declaration* type) ConstexprInterpreter::Value::Value(const Location& location, const uint8* data, Declaration* type)
: mLocation(location), : mLocation(location),
mDecType(type), mDecType(type), mDecValue(nullptr),
mBaseValue(nullptr), mOffset(0), mBaseValue(nullptr), mOffset(0),
mDataSize(type->mSize) mDataSize(type->mSize)
{ {
@ -146,7 +157,7 @@ ConstexprInterpreter::Value::Value(const Location& location, const uint8* data,
ConstexprInterpreter::Value::Value(const Location& location, const ValueItem* data, Declaration* type) ConstexprInterpreter::Value::Value(const Location& location, const ValueItem* data, Declaration* type)
: mLocation(location), : mLocation(location),
mDecType(type), mDecType(type), mDecValue(nullptr),
mBaseValue(nullptr), mOffset(0), mBaseValue(nullptr), mOffset(0),
mDataSize(type->mSize) mDataSize(type->mSize)
{ {
@ -339,6 +350,14 @@ ConstexprInterpreter::Value ConstexprInterpreter::Value::GetPtrAt(int at, Declar
return Value(mLocation, dp->mBaseValue, type, uint16(dp[0].mByte | ((uint32)(dp[1].mByte) << 8))); return Value(mLocation, dp->mBaseValue, type, uint16(dp[0].mByte | ((uint32)(dp[1].mByte) << 8)));
} }
void ConstexprInterpreter::Value::PutVarAt(Declaration* var, int64 v, int at, Declaration* type)
{
ValueItem* dp = GetAddr() + at;
dp[0].mByte = uint8(v & 0xff);
dp[1].mByte = uint8((v >> 8) & 0xff);
mDecValue = var;
}
void ConstexprInterpreter::Value::PutIntAt(int64 v, int at, Declaration* type) void ConstexprInterpreter::Value::PutIntAt(int64 v, int at, Declaration* type)
{ {
if (type->mType == DT_TYPE_FLOAT) if (type->mType == DT_TYPE_FLOAT)
@ -499,6 +518,9 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type
for (int i=0; i<type->mSize; i += type->mBase->mSize) for (int i=0; i<type->mSize; i += type->mBase->mSize)
{ {
Declaration* cdec = GetConst(offset + i, type->mBase, dataSection); Declaration* cdec = GetConst(offset + i, type->mBase, dataSection);
if (type->mStride)
cdec->mOffset = i / type->mBase->mSize;
else
cdec->mOffset = i; cdec->mOffset = i;
if (ldec) if (ldec)
@ -521,7 +543,26 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type
Declaration* target; Declaration* target;
if (vp.mBaseValue->mDecType->mType == DT_TYPE_ARRAY) if (vp.mBaseValue->mDecValue)
{
target = new Declaration(mLocation, DT_VARIABLE_REF);
if (vp.mBaseValue->mDecValue->mType == DT_VARIABLE_REF)
{
target->mBase = vp.mBaseValue->mDecValue->mBase;
target->mOffset = vp.mBaseValue->mDecValue->mOffset;
}
else
target->mBase = vp.mBaseValue->mDecValue;
target->mOffset += vp.mOffset;
dec->mValue = new Expression(mLocation, EX_CONSTANT);
dec->mValue->mDecType = type;
dec->mValue->mDecValue = target;
return dec;
}
else if (vp.mBaseValue->mDecType->mType == DT_TYPE_ARRAY)
{ {
target = new Declaration(mLocation, DT_CONST_DATA); target = new Declaration(mLocation, DT_CONST_DATA);
target->mSize = vp.mBaseValue->mDataSize; target->mSize = vp.mBaseValue->mDataSize;
@ -540,6 +581,14 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type
dec->mValue->mDecType = target->mBase; dec->mValue->mDecType = target->mBase;
dec->mValue->mDecValue = target; dec->mValue->mDecValue = target;
} }
else if (vp.mDecValue)
{
dec = new Declaration(mLocation, DT_VARIABLE_REF);
dec->mBase = vp.mDecValue;
dec->mFlags = 0;
dec->mSize = type->mSize;
dec->mOffset = vp.mOffset;
}
else else
{ {
dec = new Declaration(mLocation, DT_CONST_ADDRESS); dec = new Declaration(mLocation, DT_CONST_ADDRESS);
@ -602,6 +651,7 @@ Expression* ConstexprInterpreter::EvalConstructor(Expression* exp)
{ {
mProcType = exp->mLeft->mDecType; mProcType = exp->mLeft->mDecType;
Expression* pex = exp->mRight;
Declaration* cdec = exp->mLeft->mDecType->mParams; Declaration* cdec = exp->mLeft->mDecType->mParams;
int pos = 0; int pos = 0;
@ -610,6 +660,28 @@ Expression* ConstexprInterpreter::EvalConstructor(Expression* exp)
mParams[pos].PutPtr(Value(&mResult)); mParams[pos].PutPtr(Value(&mResult));
pos = 2; pos = 2;
if (pex->mType == EX_LIST)
pex = pex->mRight;
else
pex = nullptr;
cdec = cdec->mNext;
while (pex && pex->mType == EX_LIST)
{
if (!AddParam(pos, pex->mLeft, cdec))
return exp;
pex = pex->mRight;
if (cdec)
cdec = cdec->mNext;
}
if (pex)
{
if (!AddParam(pos, pex, cdec))
return exp;
}
mHeap = new ExpandingArray<Value*>(); mHeap = new ExpandingArray<Value*>();
Execute(exp->mLeft->mDecValue->mValue); Execute(exp->mLeft->mDecValue->mValue);
@ -690,7 +762,12 @@ bool ConstexprInterpreter::AddParam(int& pos, Expression* pex, Declaration* dec)
{ {
mParams[pos] = Value(pex->mLocation, pex->mDecValue->mBase); mParams[pos] = Value(pex->mLocation, pex->mDecValue->mBase);
if (pex->mDecValue->mSize > 0) if (pex->mDecValue->mSize > 0)
{
if (pex->mDecValue->mValue)
mParams[pos].PutConst(0, pex->mDecValue->mValue->mDecValue); mParams[pos].PutConst(0, pex->mDecValue->mValue->mDecValue);
else
return false;
}
} }
else else
return false; return false;
@ -700,6 +777,9 @@ bool ConstexprInterpreter::AddParam(int& pos, Expression* pex, Declaration* dec)
Expression* ConstexprInterpreter::EvalCall(Expression* exp) Expression* ConstexprInterpreter::EvalCall(Expression* exp)
{ {
if (!exp->mLeft->mDecValue || !exp->mLeft->mDecValue->mValue)
return exp;
mProcType = exp->mLeft->mDecType; mProcType = exp->mLeft->mDecType;
Expression* pex = exp->mRight; Expression* pex = exp->mRight;
@ -966,6 +1046,9 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalUnary(Expression* exp, con
break; break;
case TK_MUL: case TK_MUL:
return vl.GetPtr(); return vl.GetPtr();
case TK_SIZEOF:
v.PutInt(vl.mDecType->mSize);
break;
default: default:
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]);
} }
@ -1099,6 +1182,41 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons
mResult = Value(exp->mLocation, TheFloatTypeDeclaration); mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
mResult.PutFloat(cos(mParams[0].GetFloat())); mResult.PutFloat(cos(mParams[0].GetFloat()));
} }
else if (!strcmp(iname->mString, "tan"))
{
mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
mResult.PutFloat(tan(mParams[0].GetFloat()));
}
else if (!strcmp(iname->mString, "log"))
{
mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
mResult.PutFloat(log(mParams[0].GetFloat()));
}
else if (!strcmp(iname->mString, "exp"))
{
mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
mResult.PutFloat(::exp(mParams[0].GetFloat()));
}
else if (!strcmp(iname->mString, "sqrt"))
{
mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
mResult.PutFloat(::sqrt(mParams[0].GetFloat()));
}
else if (!strcmp(iname->mString, "atan"))
{
mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
mResult.PutFloat(::atan(mParams[0].GetFloat()));
}
else if (!strcmp(iname->mString, "atan2"))
{
mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
mResult.PutFloat(::atan2(mParams[0].GetFloat(), mParams[1].GetFloat()));
}
else if (!strcmp(iname->mString, "pow"))
{
mResult = Value(exp->mLocation, TheFloatTypeDeclaration);
mResult.PutFloat(::pow(mParams[0].GetFloat(), mParams[1].GetFloat()));
}
else else
mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname); mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname);
} }

View File

@ -35,6 +35,7 @@ protected:
Value(const Value& value); Value(const Value& value);
Value(Value&& value); Value(Value&& value);
Value(const Location& location, Value * value, Declaration * type, int offset); Value(const Location& location, Value * value, Declaration * type, int offset);
Value(const Location& location, Declaration * value, Declaration* type, int offset);
Value(Value* value); Value(Value* value);
Value(const Location& location, const uint8 * data, Declaration* type); Value(const Location& location, const uint8 * data, Declaration* type);
Value(const Location& location, const ValueItem* data, Declaration* type); Value(const Location& location, const ValueItem* data, Declaration* type);
@ -48,7 +49,7 @@ protected:
void Assign(const Value& v); void Assign(const Value& v);
Location mLocation; Location mLocation;
Declaration * mDecType; Declaration * mDecType, * mDecValue;
Value * mBaseValue; Value * mBaseValue;
int mOffset; int mOffset;
ValueItem * mData; ValueItem * mData;
@ -71,6 +72,7 @@ protected:
void PutIntAt(int64 v, int at, Declaration* type); void PutIntAt(int64 v, int at, Declaration* type);
void PutFloatAt(double v, int at, Declaration* type); void PutFloatAt(double v, int at, Declaration* type);
void PutPtrAt(const Value& v, int at, Declaration* type); void PutPtrAt(const Value& v, int at, Declaration* type);
void PutVarAt(Declaration* var, int64 v, int at, Declaration* type);
void PutConst(int offset, Declaration * dec); void PutConst(int offset, Declaration * dec);
Declaration* GetConst(int offset, Declaration* type, LinkerSection* dataSection) const; Declaration* GetConst(int offset, Declaration* type, LinkerSection* dataSection) const;

File diff suppressed because it is too large Load Diff

View File

@ -47,6 +47,7 @@ enum DecType
DT_PACK_VARIABLE, DT_PACK_VARIABLE,
DT_PACK_ARGUMENT, DT_PACK_ARGUMENT,
DT_PACK_TYPE, DT_PACK_TYPE,
DT_PACK_ANON,
DT_VARIABLE, DT_VARIABLE,
DT_ARGUMENT, DT_ARGUMENT,
@ -58,6 +59,7 @@ enum DecType
DT_LABEL_REF, DT_LABEL_REF,
DT_NAMESPACE, DT_NAMESPACE,
DT_BASECLASS, DT_BASECLASS,
DT_CLABEL,
DT_TEMPLATE, DT_TEMPLATE,
@ -101,6 +103,8 @@ static const uint64 DTF_CONSTEXPR = (1ULL << 31);
static const uint64 DTF_AUTO_TEMPLATE = (1ULL << 32); static const uint64 DTF_AUTO_TEMPLATE = (1ULL << 32);
static const uint64 DTF_BANK_INLAY = (1ULL << 33); static const uint64 DTF_BANK_INLAY = (1ULL << 33);
static const uint64 DTF_PURE_VIRTUAL = (1ULL << 34);
static const uint64 DTF_FORCE_INLINE = (1ULL << 35);
static const uint64 DTF_FUNC_VARIABLE = (1ULL << 36); static const uint64 DTF_FUNC_VARIABLE = (1ULL << 36);
static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 37); static const uint64 DTF_FUNC_ASSEMBLER = (1ULL << 37);
@ -120,6 +124,11 @@ static const uint64 DTF_FUNC_THIS = (1ULL << 47);
static const uint64 DTF_VAR_ALIASING = (1ULL << 48); static const uint64 DTF_VAR_ALIASING = (1ULL << 48);
static const uint64 DTF_FPARAM_UNUSED = (1ULL << 49); static const uint64 DTF_FPARAM_UNUSED = (1ULL << 49);
static const uint64 DTF_DEPRECATED = (1ULL << 50);
static const uint64 DTF_FUNC_NO_RETURN = (1ULL << 51);
static const uint64 DTF_PLACED = (1ULL << 52);
static const uint64 DTF_NO_PAGE_CROSS = (1ULL << 53);
class Declaration; class Declaration;
@ -158,6 +167,8 @@ public:
ScopeLevel mLevel; ScopeLevel mLevel;
const Ident * mName; const Ident * mName;
DeclarationScope* Clone(void) const;
DeclarationScope* mParent; DeclarationScope* mParent;
protected: protected:
struct Entry struct Entry
@ -207,6 +218,7 @@ enum ExpressionType
EX_IF, EX_IF,
EX_ELSE, EX_ELSE,
EX_FOR, EX_FOR,
EX_FORBODY,
EX_DO, EX_DO,
EX_SCOPE, EX_SCOPE,
EX_BREAK, EX_BREAK,
@ -229,14 +241,25 @@ enum ExpressionType
EX_RESULT, EX_RESULT,
EX_PACK, EX_PACK,
EX_PACK_TYPE, EX_PACK_TYPE,
EX_LABEL,
EX_GOTO,
EX_AGGREGATE
}; };
static const uint32 ANAFL_LHS = (1U << 0);
static const uint32 ANAFL_RHS = (1U << 1);
static const uint32 ANAFL_ASSIGN = (1U << 2);
static const uint32 ANAFL_ALIAS = (1U << 3);
class Expression class Expression
{ {
public: public:
Expression(const Location& loc, ExpressionType type); Expression(const Location& loc, ExpressionType type);
~Expression(void); ~Expression(void);
uint32 mUID;
Location mLocation, mEndLocation; Location mLocation, mEndLocation;
ExpressionType mType; ExpressionType mType;
Expression * mLeft, * mRight; Expression * mLeft, * mRight;
@ -245,15 +268,23 @@ public:
AsmInsType mAsmInsType; AsmInsType mAsmInsType;
AsmInsMode mAsmInsMode; AsmInsMode mAsmInsMode;
bool mConst; bool mConst;
uint32 mFlags;
Expression* LogicInvertExpression(void); Expression* LogicInvertExpression(void);
Expression* ConstantFold(Errors * errors, LinkerSection* dataSection, Linker * linker = nullptr); Expression* ConstantFold(Errors * errors, LinkerSection* dataSection, Linker * linker = nullptr);
Expression* ConstantDereference(Errors* errors, LinkerSection* dataSection);
bool HasSideEffects(void) const; bool HasSideEffects(void) const;
Expression* ListAppend(Expression* lexp);
Expression* ToAlternateThis(Declaration* pthis, Declaration* nthis);
void ReplaceVariable(Declaration* pvar, Declaration* nvar);
bool IsSame(const Expression* exp) const; bool IsSame(const Expression* exp) const;
bool IsRValue(void) const; bool IsRValue(void) const;
bool IsLValue(void) const; bool IsLValue(void) const;
bool IsConstRef(void) const; bool IsConstRef(void) const;
bool IsVolatile(void) const;
void Dump(int ident) const; void Dump(int ident) const;
}; };
@ -264,12 +295,14 @@ public:
Declaration(const Location & loc, DecType type); Declaration(const Location & loc, DecType type);
~Declaration(void); ~Declaration(void);
uint32 mUID;
Location mLocation, mEndLocation; Location mLocation, mEndLocation;
DecType mType; DecType mType;
Token mToken; Token mToken;
Declaration * mBase, * mParams, * mParamPack, * mNext, * mPrev, * mConst, * mMutable, * mVolatile; Declaration * mBase, * mParams, * mParamPack, * mNext, * mPrev, * mConst, * mMutable, * mVolatile;
Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment, * mMoveConstructor, * mMoveAssignment; Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment, * mMoveConstructor, * mMoveAssignment;
Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment; Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment, * mVectorMoveConstructor, * mVectorMoveAssignment;
Declaration * mVTable, * mClass, * mTemplate; Declaration * mVTable, * mClass, * mTemplate;
Declaration * mForwardParam, * mForwardCall; Declaration * mForwardParam, * mForwardCall;
@ -296,6 +329,7 @@ public:
bool IsSame(const Declaration* dec) const; bool IsSame(const Declaration* dec) const;
bool IsDerivedFrom(const Declaration* dec) const; bool IsDerivedFrom(const Declaration* dec) const;
bool IsSubType(const Declaration* dec) const; bool IsSubType(const Declaration* dec) const;
bool IsConstRefSame(const Declaration* dec) const;
bool IsConstSame(const Declaration* dec) const; bool IsConstSame(const Declaration* dec) const;
bool IsSameValue(const Declaration* dec) const; bool IsSameValue(const Declaration* dec) const;
bool IsSameParams(const Declaration* dec) const; bool IsSameParams(const Declaration* dec) const;
@ -310,12 +344,17 @@ public:
bool IsSimpleType(void) const; bool IsSimpleType(void) const;
bool IsReference(void) const; bool IsReference(void) const;
bool IsIndexed(void) const; bool IsIndexed(void) const;
bool ContainsArray(void) const;
bool IsShortIntStruct(void) const;
bool IsComplexStruct(void) const;
bool HasConstructor(void) const;
void SetDefined(void); void SetDefined(void);
Declaration* ToConstType(void); Declaration* ToConstType(void);
Declaration* ToMutableType(void); Declaration* ToMutableType(void);
Declaration* ToVolatileType(void); Declaration* ToVolatileType(void);
Declaration* ToAlternateThis(Declaration* pthis, int nthis = 1);
Declaration* ToStriped(int stripe); Declaration* ToStriped(int stripe);
Declaration* ToStriped(Errors* errors); Declaration* ToStriped(Errors* errors);
@ -339,8 +378,9 @@ public:
DecType ValueType(void) const; DecType ValueType(void) const;
bool CanResolveTemplate(Expression* pexp, Declaration* tdec); bool CanResolveTemplate(Expression* pexp, Declaration* tdec);
bool ResolveTemplate(Declaration* fdec, Declaration * tdec); bool ResolveTemplate(Declaration* fdec, Declaration * tdec, bool same, bool preliminary);
bool ResolveTemplate(Expression* pexp, Declaration* tdec); bool ResolveTemplate(Expression* pexp, Declaration* tdec);
bool ResolveTemplateParameterList(Expression* pexp, Declaration* pdec, bool preliminary);
Declaration* ExpandTemplate(DeclarationScope* scope); Declaration* ExpandTemplate(DeclarationScope* scope);
@ -357,6 +397,7 @@ extern Declaration* TheVoidTypeDeclaration, * TheConstVoidTypeDeclaration, * The
extern Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration, * TheConstVoidPointerTypeDeclaration, * TheSignedLongTypeDeclaration, * TheUnsignedLongTypeDeclaration; extern Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration, * TheConstVoidPointerTypeDeclaration, * TheSignedLongTypeDeclaration, * TheUnsignedLongTypeDeclaration;
extern Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration; extern Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration;
extern Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration; extern Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration;
extern Declaration* TheNullptrConstDeclaration, * TheZeroIntegerConstDeclaration, * TheZeroFloatConstDeclaration; extern Declaration* TheNullptrConstDeclaration, * TheZeroIntegerConstDeclaration, * TheZeroFloatConstDeclaration, * TheNullPointerTypeDeclaration;
extern Declaration* TheTrueConstDeclaration, * TheFalseConstDeclaration;
extern Expression* TheVoidExpression; extern Expression* TheVoidExpression;

View File

@ -429,6 +429,10 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int bank
i += 1; i += 1;
break; break;
case BC_FILL:
fprintf(file, "FILL\t#%d", memory[start + i + 0]);
i++;
break;
case BC_COPY: case BC_COPY:
fprintf(file, "COPY\t#%d", memory[start + i + 0]); fprintf(file, "COPY\t#%d", memory[start + i + 0]);
i++; i++;
@ -441,6 +445,10 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int bank
fprintf(file, "COPYL\t#%d", uint16(memory[start + i + 0] + 256 * memory[start + i + 1])); fprintf(file, "COPYL\t#%d", uint16(memory[start + i + 0] + 256 * memory[start + i + 1]));
i += 2; i += 2;
break; break;
case BC_FILL_LONG:
fprintf(file, "FILLL\t#%d", uint16(memory[start + i + 0] + 256 * memory[start + i + 1]));
i += 2;
break;
case BC_OP_NEGATE_16: case BC_OP_NEGATE_16:
fprintf(file, "NEG\tACCU"); fprintf(file, "NEG\tACCU");
@ -476,6 +484,19 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int bank
fprintf(file, "CNVFS\tACCU"); fprintf(file, "CNVFS\tACCU");
break; break;
case BC_CONV_U32_F32:
fprintf(file, "CNVLUF\tACCU");
break;
case BC_CONV_I32_F32:
fprintf(file, "CNVLSF\tACCU");
break;
case BC_CONV_F32_U32:
fprintf(file, "CNVFLU\tACCU");
break;
case BC_CONV_F32_I32:
fprintf(file, "CNVFLS\tACCU");
break;
case BC_MALLOC: case BC_MALLOC:
fprintf(file, "MALLOC\tACCU"); fprintf(file, "MALLOC\tACCU");
break; break;
@ -825,7 +846,7 @@ const char* NativeCodeDisassembler::TempName(uint8 tmp, char* buffer, InterCodeP
sprintf_s(buffer, 10, "ACCU + %d", tmp - BC_REG_ACCU); sprintf_s(buffer, 10, "ACCU + %d", tmp - BC_REG_ACCU);
return buffer; return buffer;
} }
else if (tmp >= BC_REG_WORK && tmp <= BC_REG_WORK + 7) else if (tmp >= BC_REG_WORK && tmp <= BC_REG_WORK + 8)
{ {
sprintf_s(buffer, 10, "WORK + %d", tmp - BC_REG_WORK); sprintf_s(buffer, 10, "WORK + %d", tmp - BC_REG_WORK);
return buffer; return buffer;

View File

@ -31,6 +31,8 @@ static char A2P(char ch)
DiskImage::DiskImage(const char* fname) DiskImage::DiskImage(const char* fname)
{ {
mInterleave = 10;
for (int i = 0; i < 41; i++) for (int i = 0; i < 41; i++)
for (int j = 0; j < 21; j++) for (int j = 0; j < 21; j++)
memset(mSectors[i][j], 0, 256); memset(mSectors[i][j], 0, 256);
@ -104,7 +106,7 @@ int DiskImage::AllocBAMSector(int track, int sector)
if (dp[0] > 0) if (dp[0] > 0)
{ {
sector += 4; sector += mInterleave;
if (sector >= SectorsPerTrack[track]) if (sector >= SectorsPerTrack[track])
sector -= SectorsPerTrack[track]; sector -= SectorsPerTrack[track];
@ -228,8 +230,10 @@ void DiskImage::CloseFile(void)
} }
bool DiskImage::WriteFile(const char* fname, bool compressed) bool DiskImage::WriteFile(const char* fname, bool compressed, int interleave)
{ {
mInterleave = interleave;
FILE* file; FILE* file;
fopen_s(&file, fname, "rb"); fopen_s(&file, fname, "rb");
if (file) if (file)

View File

@ -14,7 +14,7 @@ public:
void CloseFile(void); void CloseFile(void);
int WriteBytes(const uint8* data, ptrdiff_t size); int WriteBytes(const uint8* data, ptrdiff_t size);
bool WriteFile(const char* fname, bool compressed); bool WriteFile(const char* fname, bool compressed, int interleave);
protected: protected:
uint8 mSectors[41][21][256]; uint8 mSectors[41][21][256];
@ -24,6 +24,6 @@ protected:
int AllocBAMTrack(int track); int AllocBAMTrack(int track);
uint8 * mDirEntry; uint8 * mDirEntry;
int mTrack, mSector, mBytes; int mTrack, mSector, mBytes, mInterleave;
}; };

View File

@ -115,7 +115,7 @@ void Emulator::DumpCycles(void)
} }
} }
bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, int & cycles) bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, int & cycles, bool cross, bool indexed)
{ {
int t; int t;
@ -134,12 +134,14 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
mRegA = (t & 255); mRegA = (t & 255);
UpdateStatusCarry(mRegA, t >= 256); UpdateStatusCarry(mRegA, t >= 256);
if (cross) cycles++;
break; break;
case ASMIT_AND: case ASMIT_AND:
if (mode != ASMIM_IMMEDIATE) if (mode != ASMIM_IMMEDIATE)
addr = mMemory[addr]; addr = mMemory[addr];
mRegA &= addr; mRegA &= addr;
UpdateStatus(mRegA); UpdateStatus(mRegA);
if (cross) cycles++;
break; break;
case ASMIT_ASL: case ASMIT_ASL:
if (mode == ASMIM_IMPLIED) if (mode == ASMIM_IMPLIED)
@ -154,19 +156,29 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
mMemory[addr] = t & 255; mMemory[addr] = t & 255;
UpdateStatusCarry(t & 255, t >= 256); UpdateStatusCarry(t & 255, t >= 256);
cycles += 2; cycles += 2;
if (indexed) cycles++;
} }
break; break;
case ASMIT_BCC: case ASMIT_BCC:
if (!(mRegP & STATUS_CARRY)) if (!(mRegP & STATUS_CARRY))
{
mIP = addr; mIP = addr;
cycles++;
}
break; break;
case ASMIT_BCS: case ASMIT_BCS:
if ((mRegP & STATUS_CARRY)) if ((mRegP & STATUS_CARRY))
{
mIP = addr; mIP = addr;
cycles++;
}
break; break;
case ASMIT_BEQ: case ASMIT_BEQ:
if ((mRegP & STATUS_ZERO)) if ((mRegP & STATUS_ZERO))
{
mIP = addr; mIP = addr;
cycles++;
}
break; break;
case ASMIT_BIT: case ASMIT_BIT:
t = mMemory[addr]; t = mMemory[addr];
@ -235,6 +247,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
mRegP |= STATUS_OVERFLOW; mRegP |= STATUS_OVERFLOW;
UpdateStatusCarry(t & 255, t >= 256); UpdateStatusCarry(t & 255, t >= 256);
if (cross) cycles++;
break; break;
case ASMIT_CPX: case ASMIT_CPX:
if (mode != ASMIM_IMMEDIATE) if (mode != ASMIM_IMMEDIATE)
@ -275,6 +288,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
mMemory[addr] = t & 255; mMemory[addr] = t & 255;
UpdateStatus(t & 255); UpdateStatus(t & 255);
cycles += 2; cycles += 2;
if (indexed) cycles++;
} }
break; break;
case ASMIT_DEX: case ASMIT_DEX:
@ -292,6 +306,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
addr = mMemory[addr]; addr = mMemory[addr];
mRegA ^= addr; mRegA ^= addr;
UpdateStatus(mRegA); UpdateStatus(mRegA);
if (cross) cycles++;
break; break;
case ASMIT_INC: case ASMIT_INC:
if (mode == ASMIM_IMPLIED) if (mode == ASMIM_IMPLIED)
@ -306,6 +321,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
mMemory[addr] = t & 255; mMemory[addr] = t & 255;
UpdateStatus(t & 255); UpdateStatus(t & 255);
cycles += 2; cycles += 2;
if (indexed) cycles++;
} }
break; break;
case ASMIT_INX: case ASMIT_INX:
@ -334,18 +350,21 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
addr = mMemory[addr]; addr = mMemory[addr];
mRegA = addr; mRegA = addr;
UpdateStatus(mRegA); UpdateStatus(mRegA);
if (cross) cycles++;
break; break;
case ASMIT_LDX: case ASMIT_LDX:
if (mode != ASMIM_IMMEDIATE) if (mode != ASMIM_IMMEDIATE)
addr = mMemory[addr]; addr = mMemory[addr];
mRegX = addr; mRegX = addr;
UpdateStatus(mRegX); UpdateStatus(mRegX);
if (cross) cycles++;
break; break;
case ASMIT_LDY: case ASMIT_LDY:
if (mode != ASMIM_IMMEDIATE) if (mode != ASMIM_IMMEDIATE)
addr = mMemory[addr]; addr = mMemory[addr];
mRegY = addr; mRegY = addr;
UpdateStatus(mRegY); UpdateStatus(mRegY);
if (cross) cycles++;
break; break;
case ASMIT_LSR: case ASMIT_LSR:
if (mode == ASMIM_IMPLIED) if (mode == ASMIM_IMPLIED)
@ -362,6 +381,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
mMemory[addr] = t & 255; mMemory[addr] = t & 255;
UpdateStatusCarry(t & 255, c != 0); UpdateStatusCarry(t & 255, c != 0);
cycles += 2; cycles += 2;
if (indexed) cycles++;
} }
break; break;
case ASMIT_NOP: case ASMIT_NOP:
@ -371,6 +391,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
addr = mMemory[addr]; addr = mMemory[addr];
mRegA |= addr; mRegA |= addr;
UpdateStatus(mRegA); UpdateStatus(mRegA);
if (cross) cycles++;
break; break;
case ASMIT_PHA: case ASMIT_PHA:
mMemory[0x100 + mRegS] = mRegA; mMemory[0x100 + mRegS] = mRegA;
@ -405,6 +426,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
mMemory[addr] = t & 255; mMemory[addr] = t & 255;
UpdateStatusCarry(t & 255, t >= 256); UpdateStatusCarry(t & 255, t >= 256);
cycles+=2; cycles+=2;
if (indexed) cycles++;
} }
break; break;
case ASMIT_ROR: case ASMIT_ROR:
@ -422,6 +444,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
mMemory[addr] = t & 255; mMemory[addr] = t & 255;
UpdateStatusCarry(t & 255, c != 0); UpdateStatusCarry(t & 255, c != 0);
cycles += 2; cycles += 2;
if (indexed) cycles++;
} }
break; break;
case ASMIT_RTI: case ASMIT_RTI:
@ -444,6 +467,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
mRegA = (t & 255); mRegA = (t & 255);
UpdateStatusCarry(t & 255, t >= 256); UpdateStatusCarry(t & 255, t >= 256);
if (cross) cycles++;
break; break;
case ASMIT_SEC: case ASMIT_SEC:
mRegP |= STATUS_CARRY; mRegP |= STATUS_CARRY;
@ -454,6 +478,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
break; break;
case ASMIT_STA: case ASMIT_STA:
mMemory[addr] = mRegA; mMemory[addr] = mRegA;
if (indexed) cycles++;
break; break;
case ASMIT_STX: case ASMIT_STX:
mMemory[addr] = mRegX; mMemory[addr] = mRegX;
@ -512,13 +537,13 @@ int Emulator::Emulate(int startIP, int trace)
mMemory[0x1fe] = 0xff; mMemory[0x1fe] = 0xff;
mMemory[0x1ff] = 0xff; mMemory[0x1ff] = 0xff;
int ticks = 0; int tcycles = 0, cycles = 0;
int iip = 0;
while (mIP != 0) while (mIP != 0)
{ {
if (mJiffies) if (mJiffies)
{ {
ticks++; if (cycles >= tcycles + 16667)
if (ticks > 4500)
{ {
mMemory[0xa2]++; mMemory[0xa2]++;
if (!mMemory[0xa2]) if (!mMemory[0xa2])
@ -529,7 +554,7 @@ int Emulator::Emulate(int startIP, int trace)
mMemory[0xa0]++; mMemory[0xa0]++;
} }
} }
ticks = 0; tcycles += 16667;
} }
} }
@ -560,7 +585,12 @@ int Emulator::Emulate(int startIP, int trace)
AsmInsData d = DecInsData[opcode]; AsmInsData d = DecInsData[opcode];
int addr = 0, taddr; int addr = 0, taddr;
int ip = mIP; int ip = mIP;
int iip = mMemory[BC_REG_IP] + 256 * mMemory[BC_REG_IP + 1];
if (ip == 0x0862)
iip = mMemory[BC_REG_IP] + 256 * mMemory[BC_REG_IP + 1] + mRegY;
bool cross = false, indexed = false;
int icycles = 0;
mIP++; mIP++;
switch (d.mMode) switch (d.mMode)
@ -568,56 +598,60 @@ int Emulator::Emulate(int startIP, int trace)
case ASMIM_IMPLIED: case ASMIM_IMPLIED:
if (trace & 2) if (trace & 2)
printf("%04x : %04x %02x __ __ %s (A:%02x X:%02x Y:%02x P:%02x S:%02x)\n", iip, ip, mMemory[ip], AsmInstructionNames[d.mType], mRegA, mRegX, mRegY, mRegP, mRegS); printf("%04x : %04x %02x __ __ %s (A:%02x X:%02x Y:%02x P:%02x S:%02x)\n", iip, ip, mMemory[ip], AsmInstructionNames[d.mType], mRegA, mRegX, mRegY, mRegP, mRegS);
mCycles[ip] += 2; icycles = 2;
break; break;
case ASMIM_IMMEDIATE: case ASMIM_IMMEDIATE:
addr = mMemory[mIP++]; addr = mMemory[mIP++];
if (trace & 2) if (trace & 2)
printf("%04x : %04x %02x %02x __ %s #$%02x (A:%02x X:%02x Y:%02x P:%02x S:%02x)\n", iip, ip, mMemory[ip], mMemory[ip+1], AsmInstructionNames[d.mType], addr, mRegA, mRegX, mRegY, mRegP, mRegS); printf("%04x : %04x %02x %02x __ %s #$%02x (A:%02x X:%02x Y:%02x P:%02x S:%02x)\n", iip, ip, mMemory[ip], mMemory[ip+1], AsmInstructionNames[d.mType], addr, mRegA, mRegX, mRegY, mRegP, mRegS);
mCycles[ip] += 2; icycles = 2;
break; break;
case ASMIM_ZERO_PAGE: case ASMIM_ZERO_PAGE:
addr = mMemory[mIP++]; addr = mMemory[mIP++];
if (trace & 2) if (trace & 2)
printf("%04x : %04x %02x %02x __ %s $%02x (A:%02x X:%02x Y:%02x P:%02x S:%02x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr, mRegA, mRegX, mRegY, mRegP, mRegS, mMemory[addr]); printf("%04x : %04x %02x %02x __ %s $%02x (A:%02x X:%02x Y:%02x P:%02x S:%02x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], addr, mRegA, mRegX, mRegY, mRegP, mRegS, mMemory[addr]);
mCycles[ip] += 3; icycles = 3;
break; break;
case ASMIM_ZERO_PAGE_X: case ASMIM_ZERO_PAGE_X:
taddr = mMemory[mIP++]; taddr = mMemory[mIP++];
addr = (taddr + mRegX) & 0xff; addr = (taddr + mRegX) & 0xff;
if (trace & 2) if (trace & 2)
printf("%04x : %04x %02x %02x __ %s $%02x,x (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]); printf("%04x : %04x %02x %02x __ %s $%02x,x (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]);
mCycles[ip] += 3; icycles = 4;
break; break;
case ASMIM_ZERO_PAGE_Y: case ASMIM_ZERO_PAGE_Y:
taddr = mMemory[mIP++]; taddr = mMemory[mIP++];
addr = (taddr + mRegY) & 0xff; addr = (taddr + mRegY) & 0xff;
if (trace & 2) if (trace & 2)
printf("%04x : %04x %02x %02x __ %s $%02x,y (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]); printf("%04x : %04x %02x %02x __ %s $%02x,y (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]);
mCycles[ip] += 3; icycles = 4;
break; break;
case ASMIM_ABSOLUTE: case ASMIM_ABSOLUTE:
addr = mMemory[mIP] + 256 * mMemory[mIP + 1]; addr = mMemory[mIP] + 256 * mMemory[mIP + 1];
if (trace & 2) if (trace & 2)
printf("%04x : %04x %02x %02x %02x %s $%04x (A:%02x X:%02x Y:%02x P:%02x S:%02x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr, mRegA, mRegX, mRegY, mRegP, mRegS, mMemory[addr]); printf("%04x : %04x %02x %02x %02x %s $%04x (A:%02x X:%02x Y:%02x P:%02x S:%02x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], addr, mRegA, mRegX, mRegY, mRegP, mRegS, mMemory[addr]);
mIP += 2; mIP += 2;
mCycles[ip] += 4; icycles = 4;
break; break;
case ASMIM_ABSOLUTE_X: case ASMIM_ABSOLUTE_X:
taddr = mMemory[mIP] + 256 * mMemory[mIP + 1]; taddr = mMemory[mIP] + 256 * mMemory[mIP + 1];
addr = (taddr + mRegX) & 0xffff; addr = (taddr + mRegX) & 0xffff;
cross = mMemory[mIP] + mRegX >= 256;
indexed = true;
if (trace & 2) if (trace & 2)
printf("%04x : %04x %02x %02x %02x %s $%04x,x (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]); printf("%04x : %04x %02x %02x %02x %s $%04x,x (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]);
mIP += 2; mIP += 2;
mCycles[ip] += 5; icycles = 4;
break; break;
case ASMIM_ABSOLUTE_Y: case ASMIM_ABSOLUTE_Y:
taddr = mMemory[mIP] + 256 * mMemory[mIP + 1]; taddr = mMemory[mIP] + 256 * mMemory[mIP + 1];
addr = (taddr + mRegY) & 0xffff; addr = (taddr + mRegY) & 0xffff;
cross = mMemory[mIP] + mRegY >= 256;
indexed = true;
if (trace & 2) if (trace & 2)
printf("%04x : %04x %02x %02x %02x %s $%04x,y (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]); printf("%04x : %04x %02x %02x %02x %s $%04x,y (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]);
mIP += 2; mIP += 2;
mCycles[ip] += 5; icycles = 4;
break; break;
case ASMIM_INDIRECT: case ASMIM_INDIRECT:
taddr = mMemory[mIP] + 256 * mMemory[mIP + 1]; taddr = mMemory[mIP] + 256 * mMemory[mIP + 1];
@ -625,21 +659,23 @@ int Emulator::Emulate(int startIP, int trace)
addr = mMemory[taddr] + 256 * mMemory[taddr + 1]; addr = mMemory[taddr] + 256 * mMemory[taddr + 1];
if (trace & 2) if (trace & 2)
printf("%04x : %04x %02x %02x %02x %s ($%04x) (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr); printf("%04x : %04x %02x %02x %02x %s ($%04x) (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], mMemory[ip + 2], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr);
mCycles[ip] += 6; icycles = 6;
break; break;
case ASMIM_INDIRECT_X: case ASMIM_INDIRECT_X:
taddr = (mMemory[mIP++] + mRegX) & 0xff; taddr = (mMemory[mIP++] + mRegX) & 0xff;
addr = mMemory[taddr] + 256 * mMemory[taddr + 1]; addr = mMemory[taddr] + 256 * mMemory[taddr + 1];
if (trace & 2) if (trace & 2)
printf("%04x : %04x %02x %02x __ %s ($%02x,x) (A:%02x X:%02x Y:%02x P:%02x S:%02x %02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], mMemory[ip + 1], mRegA, mRegX, mRegY, mRegP, mRegS, taddr, addr, mMemory[addr]); printf("%04x : %04x %02x %02x __ %s ($%02x,x) (A:%02x X:%02x Y:%02x P:%02x S:%02x %02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], mMemory[ip + 1], mRegA, mRegX, mRegY, mRegP, mRegS, taddr, addr, mMemory[addr]);
mCycles[ip] += 6; icycles = 6;
break; break;
case ASMIM_INDIRECT_Y: case ASMIM_INDIRECT_Y:
taddr = mMemory[mIP++]; taddr = mMemory[mIP++];
addr = (mMemory[taddr] + 256 * mMemory[taddr + 1] + mRegY) & 0xffff; addr = (mMemory[taddr] + 256 * mMemory[taddr + 1] + mRegY) & 0xffff;
cross = mMemory[taddr] + mRegY >= 256;
indexed = true;
if (trace & 2) if (trace & 2)
printf("%04x : %04x %02x %02x __ %s ($%02x),y (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]); printf("%04x : %04x %02x %02x __ %s ($%02x),y (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x M:%02x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr, mMemory[addr]);
mCycles[ip] += 6; icycles = 5;
break; break;
case ASMIM_RELATIVE: case ASMIM_RELATIVE:
taddr = mMemory[mIP++]; taddr = mMemory[mIP++];
@ -649,7 +685,7 @@ int Emulator::Emulate(int startIP, int trace)
addr = taddr + mIP; addr = taddr + mIP;
if (trace & 2) if (trace & 2)
printf("%04x : %04x %02x %02x __ %s $%02x (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr); printf("%04x : %04x %02x %02x __ %s $%02x (A:%02x X:%02x Y:%02x P:%02x S:%02x %04x)\n", iip, ip, mMemory[ip], mMemory[ip + 1], AsmInstructionNames[d.mType], taddr, mRegA, mRegX, mRegY, mRegP, mRegS, addr);
mCycles[ip] += 2; icycles = 2;
break; break;
} }
@ -685,8 +721,11 @@ int Emulator::Emulate(int startIP, int trace)
); );
} }
if (!EmulateInstruction(d.mType, d.mMode, addr, mCycles[ip])) if (!EmulateInstruction(d.mType, d.mMode, addr, icycles, cross, indexed))
return -1; return -1;
mCycles[ip] += icycles;
cycles += icycles;
} }
if (mRegS == 0xff) if (mRegS == 0xff)

View File

@ -22,7 +22,7 @@ public:
int Emulate(int startIP, int trace); int Emulate(int startIP, int trace);
void DumpProfile(void); void DumpProfile(void);
bool EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, int & cycles); bool EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, int & cycles, bool cross, bool indexed);
protected: protected:
void UpdateStatus(uint8 result); void UpdateStatus(uint8 result);
void UpdateStatusCarry(uint8 result, bool carry); void UpdateStatusCarry(uint8 result, bool carry);

View File

@ -4,11 +4,18 @@
#include <stdlib.h> #include <stdlib.h>
Errors::Errors(void) Errors::Errors(void)
: mErrorCount(0) : mErrorCount(0), mMinLevel(EINFO_GENERIC), mDisabled(EERR_GENERIC)
{ {
} }
ErrorID Errors::SetMinLevel(ErrorID id)
{
ErrorID pid = mMinLevel;
mMinLevel = id;
return pid;
}
void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const Ident* info1, const Ident* info2) void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const Ident* info1, const Ident* info2)
{ {
if (!info1) if (!info1)
@ -21,6 +28,8 @@ void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const Iden
void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char* info1, const char * info2) void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char* info1, const char * info2)
{
if (eid >= mMinLevel && !(eid < EERR_GENERIC && mDisabled[eid]))
{ {
const char* level = "info"; const char* level = "info";
if (eid >= EERR_GENERIC) if (eid >= EERR_GENERIC)
@ -58,5 +67,6 @@ void Errors::Error(const Location& loc, ErrorID eid, const char* msg, const char
if (mErrorCount > 10 || eid >= EFATAL_GENERIC) if (mErrorCount > 10 || eid >= EFATAL_GENERIC)
exit(20); exit(20);
} }
}

View File

@ -1,5 +1,8 @@
#pragma once #pragma once
#include "NumberSet.h"
class Location class Location
{ {
public: public:
@ -10,7 +13,11 @@ public:
Location() : mFileName(nullptr), mLine(0), mColumn(0), mFrom(nullptr) {} Location() : mFileName(nullptr), mLine(0), mColumn(0), mFrom(nullptr) {}
Location(const Location& loc, const Location* from) Location(const Location& loc, const Location* from)
: mFileName(loc.mFileName), mLine(loc.mLine), mColumn(loc.mColumn), mFrom(from) : mFileName(loc.mFileName), mLine(loc.mLine), mColumn(loc.mColumn), mFrom(from)
{} {
static volatile int k;
if (from)
k = from->mLine;
}
}; };
class Ident; class Ident;
@ -39,6 +46,13 @@ enum ErrorID
EWARN_DESTRUCTOR_MISMATCH, EWARN_DESTRUCTOR_MISMATCH,
EWARN_NUMERIC_0_USED_AS_NULLPTR, EWARN_NUMERIC_0_USED_AS_NULLPTR,
EWARN_FLOAT_TO_INT, EWARN_FLOAT_TO_INT,
EWARN_UNDEFINED_POINTER_ARITHMETIC,
EWARN_INVALID_VALUE_RANGE,
EWARN_DEFAULT_COPY_DEPRECATED,
EWARN_INSUFFICIENT_MEMORY,
EWARN_FUNCTION_NOT_INLINED,
EWARN_INVALID_VOID_POINTER_ARITHMETIC,
EWARN_DIVISION_BY_ZERO,
EERR_GENERIC = 3000, EERR_GENERIC = 3000,
EERR_FILE_NOT_FOUND, EERR_FILE_NOT_FOUND,
@ -95,6 +109,10 @@ enum ErrorID
EERR_INVALID_CAPTURE, EERR_INVALID_CAPTURE,
EERR_INVALID_PACK_USAGE, EERR_INVALID_PACK_USAGE,
EERR_INVALID_FOLD_EXPRESSION, EERR_INVALID_FOLD_EXPRESSION,
ERRR_INSTANTIATE_ABSTRACT_CLASS,
ERRR_INVALID_GOTO,
EERR_INVALID_INITIALIZER,
ERRR_INVALID_VOID_POINTER_ARITHMETIC,
EERR_INVALID_CONSTEXPR, EERR_INVALID_CONSTEXPR,
EERR_DOUBLE_FREE, EERR_DOUBLE_FREE,
@ -103,12 +121,19 @@ enum ErrorID
ERRR_STACK_OVERFLOW, ERRR_STACK_OVERFLOW,
ERRR_INVALID_NUMBER, ERRR_INVALID_NUMBER,
EERR_OVERLAPPING_DATA_SECTIONS, EERR_OVERLAPPING_DATA_SECTIONS,
EERR_ASSEMBLER_LIMIT,
EERR_INVALID_PREPROCESSOR, EERR_INVALID_PREPROCESSOR,
EERR_INVALID_CLASS_INITIALIZER,
EERR_CALL_OF_DELETED_FUNCTION,
EERR_STATIC_ASSERT,
EFATAL_GENERIC = 4000, EFATAL_GENERIC = 4000,
EFATAL_OUT_OF_MEMORY, EFATAL_OUT_OF_MEMORY,
EFATAL_MACRO_EXPANSION_DEPTH, EFATAL_MACRO_EXPANSION_DEPTH,
ERROR_MAX = 5000
}; };
class Errors class Errors
@ -116,7 +141,12 @@ class Errors
public: public:
Errors(void); Errors(void);
ErrorID SetMinLevel(ErrorID id);
int mErrorCount; int mErrorCount;
ErrorID mMinLevel;
NumberSet mDisabled;
void Error(const Location& loc, ErrorID eid, const char* msg, const Ident* info1, const Ident* info2 = nullptr); void Error(const Location& loc, ErrorID eid, const char* msg, const Ident* info1, const Ident* info2 = nullptr);
void Error(const Location& loc, ErrorID eid, const char* msg, const char* info1 = nullptr, const char* info2 = nullptr); void Error(const Location& loc, ErrorID eid, const char* msg, const char* info1 = nullptr, const char* info2 = nullptr);

View File

@ -1,7 +1,7 @@
#include "GlobalAnalyzer.h" #include "GlobalAnalyzer.h"
GlobalAnalyzer::GlobalAnalyzer(Errors* errors, Linker* linker) GlobalAnalyzer::GlobalAnalyzer(Errors* errors, Linker* linker)
: mErrors(errors), mLinker(linker), mCalledFunctions(nullptr), mCallingFunctions(nullptr), mVariableFunctions(nullptr), mFunctions(nullptr), mGlobalVariables(nullptr), mCompilerOptions(COPT_DEFAULT) : mErrors(errors), mLinker(linker), mCalledFunctions(nullptr), mCallingFunctions(nullptr), mVariableFunctions(nullptr), mFunctions(nullptr), mGlobalVariables(nullptr), mTopoFunctions(nullptr), mCompilerOptions(COPT_DEFAULT)
{ {
} }
@ -132,24 +132,65 @@ void GlobalAnalyzer::AutoZeroPage(LinkerSection* lszp, int zpsize)
} }
} }
void GlobalAnalyzer::TopoSort(Declaration* procDec)
{
if (!(procDec->mFlags & DTF_FUNC_ANALYZING))
{
procDec->mFlags |= DTF_FUNC_ANALYZING;
if (!mTopoFunctions.Contains(procDec))
{
for (int i = 0; i < procDec->mCalled.Size(); i++)
TopoSort(procDec->mCalled[i]);
mTopoFunctions.Push(procDec);
}
procDec->mFlags &= ~DTF_FUNC_ANALYZING;
}
}
int GlobalAnalyzer::CallerInvokes(Declaration* called)
{
int n = 0;
for (int i = 0; i < called->mCallers.Size(); i++)
{
Declaration* f = called->mCallers[i];
n += CallerInvokes(f, called);
}
return n;
}
int GlobalAnalyzer::CallerInvokes(Declaration* caller, Declaration* called)
{
int n = 1;
if (caller->mType == DT_CONST_FUNCTION && (caller->mFlags & (DTF_INLINE | DTF_FORCE_INLINE | DTF_REQUEST_INLINE)) && !(caller->mFlags & DTF_PREVENT_INLINE) && !(caller->mFlags & DTF_FUNC_RECURSIVE) && !(caller->mFlags & DTF_FUNC_VARIABLE) && !(caller->mFlags & DTF_EXPORT))
n = CallerInvokes(caller);
return n > 1 ? n : 1;
}
void GlobalAnalyzer::AutoInline(void) void GlobalAnalyzer::AutoInline(void)
{ {
for (int i = 0; i < mFunctions.Size(); i++)
TopoSort(mFunctions[i]);
bool changed = false; bool changed = false;
do do
{ {
changed = false; changed = false;
for (int i = 0; i < mFunctions.Size(); i++) // Reverse order, to check inline from bottom to top of call graph
for (int i = 0; i< mTopoFunctions.Size(); i++)
{ {
Declaration* f = mFunctions[i]; Declaration* f = mTopoFunctions[i];
if (!(f->mFlags & DTF_INLINE) &&
if (f->mType == DT_CONST_FUNCTION &&
!(f->mFlags & DTF_INLINE) &&
!(f->mFlags & DTF_EXPORT) && !(f->mFlags & DTF_EXPORT) &&
!(f->mFlags & DTF_PREVENT_INLINE) && !(f->mFlags & DTF_PREVENT_INLINE) &&
!(f->mBase->mFlags & DTF_VARIADIC) && !(f->mBase->mFlags & DTF_VARIADIC) &&
!(f->mFlags & DTF_FUNC_VARIABLE) && !(f->mFlags & DTF_FUNC_VARIABLE) &&
!((f->mFlags & DTF_FUNC_ASSEMBLER) && !(f->mFlags & DTF_REQUEST_INLINE)) && !((f->mFlags & DTF_FUNC_ASSEMBLER) && !(f->mFlags & DTF_REQUEST_INLINE)) &&
!(f->mFlags & DTF_INTRINSIC) && !(f->mFlags & DTF_INTRINSIC) &&
!(f->mFlags & DTF_FUNC_RECURSIVE) && f->mLocalSize < 100) !(f->mFlags & DTF_FUNC_RECURSIVE) &&
!(f->mFlags & DTF_FUNC_NO_RETURN))
{ {
int nparams = 0; int nparams = 0;
Declaration* dec = f->mBase->mParams; Declaration* dec = f->mBase->mParams;
@ -159,21 +200,39 @@ void GlobalAnalyzer::AutoInline(void)
dec = dec->mNext; dec = dec->mNext;
} }
int cost = (f->mComplexity - 20 * nparams - 20); int invokes = CallerInvokes(f);
int cost = (f->mComplexity - 20 * nparams - 10);
// printf("CHEK INLINING %s %d * (%d - 1)\n", f->mIdent->mString, cost, f->mCallers.Size()); // printf("CHECK INLINING %s (%d) %d * (%d - 1)\n", f->mIdent->mString, f->mComplexity, cost, invokes);
bool doinline = false; bool doinline = false;
if ((f->mCompilerOptions & COPT_OPTIMIZE_INLINE) && (f->mFlags & DTF_REQUEST_INLINE)) if ((f->mCompilerOptions & COPT_OPTIMIZE_INLINE) && (f->mFlags & DTF_REQUEST_INLINE) || (f->mFlags & DTF_FORCE_INLINE))
doinline = true; doinline = true;
if ((f->mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE) && (cost * (f->mCallers.Size() - 1) <= 0)) if (f->mLocalSize < 100)
{
if ((f->mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE) && ((cost - 20) * (invokes - 1) <= 20))
{
if (f->mCompilerOptions & COPT_OPTIMIZE_CODE_SIZE)
{
if (invokes == 1 && f->mSection == f->mCallers[0]->mSection || cost < 0)
doinline = true; doinline = true;
if ((f->mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE_ALL) && (cost * (f->mCallers.Size() - 1) <= 10000)) }
else if (invokes == 1 && f->mComplexity > 100)
{
// printf("CHECK INLINING2 %s <- %s %d\n", f->mIdent->mString, f->mCallers[0]->mIdent->mString, f->mCallers[0]->mCalled.Size());
if (cost < 0 || f->mCallers[0]->mComplexity + cost < 1000 || f->mCallers[0]->mCalled.Size() == 1)
doinline = true; doinline = true;
}
else
doinline = true;
}
if ((f->mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE_ALL) && (cost * (invokes - 1) <= 10000))
doinline = true;
}
if (doinline) if (doinline)
{ {
// printf("INLINING %s %d * (%d - 1)\n", f->mIdent->mString, cost, f->mCallers.Size()); // printf("INLINING %s %d * (%d - 1)\n", f->mIdent->mString, cost, invokes);
f->mFlags |= DTF_INLINE; f->mFlags |= DTF_INLINE;
for (int j = 0; j < f->mCallers.Size(); j++) for (int j = 0; j < f->mCallers.Size(); j++)
@ -334,7 +393,7 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
if (procDec->mValue && procDec->mValue->mType == EX_DISPATCH) if (procDec->mValue && procDec->mValue->mType == EX_DISPATCH)
{ {
Declaration* maxf = nullptr; Declaration* maxf = nullptr, * reff = nullptr;
bool stackCall = false; bool stackCall = false;
@ -343,7 +402,10 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
Declaration* cf = procDec->mCalled[i]; Declaration* cf = procDec->mCalled[i];
if (cf->mBase->mFlags & DTF_STACKCALL) if (cf->mBase->mFlags & DTF_STACKCALL)
{
stackCall = true; stackCall = true;
reff = cf;
}
if (!maxf) if (!maxf)
maxf = cf; maxf = cf;
@ -351,6 +413,9 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
maxf = cf; maxf = cf;
} }
if (!reff)
reff = maxf;
for (int i = 0; i < procDec->mCalled.Size(); i++) for (int i = 0; i < procDec->mCalled.Size(); i++)
{ {
Declaration* cf = procDec->mCalled[i]; Declaration* cf = procDec->mCalled[i];
@ -361,9 +426,9 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
cf->mBase->mFlags |= DTF_STACKCALL; cf->mBase->mFlags |= DTF_STACKCALL;
} }
if (cf != maxf) if (cf != reff)
{ {
Declaration* fp = cf->mBase->mParams, * mp = maxf->mBase->mParams; Declaration* fp = cf->mBase->mParams, * mp = reff->mBase->mParams;
while (fp) while (fp)
{ {
fp->mVarIndex = mp->mVarIndex; fp->mVarIndex = mp->mVarIndex;
@ -372,10 +437,11 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
} }
assert(!mp); assert(!mp);
cf->mBase->mFastCallBase = cf->mFastCallBase = maxf->mBase->mFastCallBase;
cf->mBase->mFastCallSize = cf->mFastCallSize = maxf->mBase->mFastCallSize; cf->mBase->mFastCallSize = cf->mFastCallSize = maxf->mBase->mFastCallSize;
} }
if (cf != maxf)
cf->mBase->mFastCallBase = cf->mFastCallBase = maxf->mBase->mFastCallBase;
} }
procDec->mFastCallBase = procDec->mBase->mFastCallBase; procDec->mFastCallBase = procDec->mBase->mFastCallBase;
@ -415,7 +481,7 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
fplimit += 256; fplimit += 256;
} }
if (procDec->mBase->mBase->mType == DT_TYPE_STRUCT) if (procDec->mBase->mBase->IsComplexStruct())
{ {
if (nbase < numfpzero && nbase + 2 > numfpzero) if (nbase < numfpzero && nbase + 2 > numfpzero)
nbase = numfpzero; nbase = numfpzero;
@ -567,6 +633,13 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* cexp, Expression* exp, Declara
{ {
dec->mFlags |= DTF_FUNC_ANALYZING; dec->mFlags |= DTF_FUNC_ANALYZING;
if (dec->mFlags & DTF_DEPRECATED)
{
mErrors->Error(dec->mLocation, EWARN_DEFAULT_COPY_DEPRECATED, "Using deprecated function", dec->mQualIdent->mString);
if (cexp)
mErrors->Error(cexp->mLocation, EINFO_CALLED_FROM, "Called from here");
}
mFunctions.Push(dec); mFunctions.Push(dec);
Declaration* pdec = dec->mBase->mParams; Declaration* pdec = dec->mBase->mParams;
@ -579,6 +652,8 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* cexp, Expression* exp, Declara
dec->mFlags |= DTF_ANALYZED; dec->mFlags |= DTF_ANALYZED;
dec->mFlags |= DTF_FUNC_INTRSAVE; dec->mFlags |= DTF_FUNC_INTRSAVE;
if (dec->mBase->mBase && dec->mBase->mBase->mType != DT_TYPE_VOID)
dec->mFlags |= DTF_FUNC_NO_RETURN;
if (dec->mFlags & DTF_INTERRUPT) if (dec->mFlags & DTF_INTERRUPT)
dec->mFlags |= DTF_FUNC_INTRCALLED; dec->mFlags |= DTF_FUNC_INTRCALLED;
@ -590,7 +665,7 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* cexp, Expression* exp, Declara
if (mCompilerOptions & COPT_OPTIMIZE_CONST_EXPRESSIONS) if (mCompilerOptions & COPT_OPTIMIZE_CONST_EXPRESSIONS)
dec->mFlags |= DTF_FUNC_CONSTEXPR; dec->mFlags |= DTF_FUNC_CONSTEXPR;
dec->mFlags |= DTF_FUNC_PURE; dec->mFlags |= DTF_FUNC_PURE;
Analyze(exp, dec, false); Analyze(exp, dec, 0);
Declaration* pdec = dec->mBase->mParams; Declaration* pdec = dec->mBase->mParams;
int vi = 0; int vi = 0;
@ -610,7 +685,7 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* cexp, Expression* exp, Declara
} }
else else
{ {
mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mQualIdent); mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->FullIdent());
if (cexp) if (cexp)
mErrors->Error(cexp->mLocation, EINFO_CALLED_FROM, "Called from here"); mErrors->Error(cexp->mLocation, EINFO_CALLED_FROM, "Called from here");
@ -638,7 +713,10 @@ void GlobalAnalyzer::AnalyzeAssembler(Expression* exp, Declaration* procDec)
else if (adec->mType == DT_VARIABLE_REF) else if (adec->mType == DT_VARIABLE_REF)
{ {
if (adec->mBase->mFlags & DTF_GLOBAL) if (adec->mBase->mFlags & DTF_GLOBAL)
{
AnalyzeGlobalVariable(adec->mBase); AnalyzeGlobalVariable(adec->mBase);
adec->mBase->mFlags |= DTF_VAR_ALIASING;
}
} }
else if (adec->mType == DT_LABEL) else if (adec->mType == DT_LABEL)
{ {
@ -647,7 +725,10 @@ void GlobalAnalyzer::AnalyzeAssembler(Expression* exp, Declaration* procDec)
else if (adec->mType == DT_VARIABLE) else if (adec->mType == DT_VARIABLE)
{ {
if (adec->mFlags & DTF_GLOBAL) if (adec->mFlags & DTF_GLOBAL)
{
AnalyzeGlobalVariable(adec); AnalyzeGlobalVariable(adec);
adec->mFlags |= DTF_VAR_ALIASING;
}
} }
else if (adec->mType == DT_FUNCTION_REF) else if (adec->mType == DT_FUNCTION_REF)
{ {
@ -680,7 +761,7 @@ void GlobalAnalyzer::AnalyzeGlobalVariable(Declaration* dec)
if (dec->mValue) if (dec->mValue)
{ {
Analyze(dec->mValue, dec, false); Analyze(dec->mValue, dec, 0);
} }
} }
} }
@ -690,17 +771,19 @@ void GlobalAnalyzer::AnalyzeInit(Declaration* mdec)
while (mdec) while (mdec)
{ {
if (mdec->mValue) if (mdec->mValue)
RegisterProc(Analyze(mdec->mValue, mdec, false)); RegisterProc(Analyze(mdec->mValue, mdec, 0));
else if (mdec->mParams) else if (mdec->mParams)
AnalyzeInit(mdec->mParams); AnalyzeInit(mdec->mParams);
mdec = mdec->mNext; mdec = mdec->mNext;
} }
} }
Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, bool lhs) Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, uint32 flags)
{ {
Declaration* ldec, * rdec; Declaration* ldec, * rdec;
exp->mFlags = flags;
switch (exp->mType) switch (exp->mType)
{ {
case EX_ERROR: case EX_ERROR:
@ -718,7 +801,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
} }
else if (exp->mDecValue->mType == DT_CONST_POINTER) else if (exp->mDecValue->mType == DT_CONST_POINTER)
{ {
ldec = Analyze(exp->mDecValue->mValue, procDec, true); ldec = Analyze(exp->mDecValue->mValue, procDec, ANAFL_LHS | ANAFL_ALIAS);
if (ldec->mType == DT_VARIABLE) if (ldec->mType == DT_VARIABLE)
ldec->mFlags |= DTF_VAR_ALIASING; ldec->mFlags |= DTF_VAR_ALIASING;
RegisterProc(ldec); RegisterProc(ldec);
@ -734,9 +817,22 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
return exp->mDecValue; return exp->mDecValue;
case EX_VARIABLE: case EX_VARIABLE:
if (exp->mDecType->IsSimpleType())
procDec->mComplexity += 5 * exp->mDecType->mSize;
else
procDec->mComplexity += 10;
if (mCompilerOptions & COPT_DEBUGINFO) if (mCompilerOptions & COPT_DEBUGINFO)
exp->mDecValue->mReferences.Push(exp); exp->mDecValue->mReferences.Push(exp);
if (flags & ANAFL_ALIAS)
{
Declaration* dec = exp->mDecValue;
while (dec->mType == DT_VARIABLE_REF)
dec = dec->mBase;
dec->mFlags |= DTF_VAR_ALIASING;
}
if ((exp->mDecValue->mFlags & DTF_STATIC) || (exp->mDecValue->mFlags & DTF_GLOBAL)) if ((exp->mDecValue->mFlags & DTF_STATIC) || (exp->mDecValue->mFlags & DTF_GLOBAL))
{ {
Declaration* type = exp->mDecValue->mBase; Declaration* type = exp->mDecValue->mBase;
@ -746,14 +842,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
if (!(type->mFlags & DTF_CONST)) if (!(type->mFlags & DTF_CONST))
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
if (lhs) if (flags & ANAFL_LHS)
procDec->mFlags &= ~DTF_FUNC_PURE; procDec->mFlags &= ~DTF_FUNC_PURE;
AnalyzeGlobalVariable(exp->mDecValue); AnalyzeGlobalVariable(exp->mDecValue);
} }
else else
{ {
if (lhs) if (flags & ANAFL_LHS)
exp->mDecValue->mFlags |= DTF_VAR_ADDRESS; exp->mDecValue->mFlags |= DTF_VAR_ADDRESS;
if (!(exp->mDecValue->mFlags & DTF_ANALYZED)) if (!(exp->mDecValue->mFlags & DTF_ANALYZED))
@ -765,10 +861,10 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
return exp->mDecValue; return exp->mDecValue;
case EX_INITIALIZATION: case EX_INITIALIZATION:
case EX_ASSIGNMENT: case EX_ASSIGNMENT:
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize; procDec->mComplexity += 5 * exp->mLeft->mDecType->mSize;
ldec = Analyze(exp->mLeft, procDec, true); ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS);
rdec = Analyze(exp->mRight, procDec, false); rdec = Analyze(exp->mRight, procDec, ANAFL_RHS);
if (exp->mLeft->mType == EX_VARIABLE && exp->mRight->mType == EX_CALL && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT) if (exp->mLeft->mType == EX_VARIABLE && exp->mRight->mType == EX_CALL && exp->mLeft->mDecType->mType == DT_TYPE_STRUCT)
exp->mLeft->mDecValue->mFlags |= DTF_VAR_ALIASING; exp->mLeft->mDecValue->mFlags |= DTF_VAR_ALIASING;
RegisterProc(rdec); RegisterProc(rdec);
@ -777,33 +873,33 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
case EX_BINARY: case EX_BINARY:
procDec->mComplexity += 10 * exp->mDecType->mSize; procDec->mComplexity += 10 * exp->mDecType->mSize;
ldec = Analyze(exp->mLeft, procDec, lhs); ldec = Analyze(exp->mLeft, procDec, flags & ~ANAFL_ALIAS);
rdec = Analyze(exp->mRight, procDec, lhs); rdec = Analyze(exp->mRight, procDec, flags & ~ANAFL_ALIAS);
return ldec; return ldec;
case EX_RELATIONAL: case EX_RELATIONAL:
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize; procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
ldec = Analyze(exp->mLeft, procDec, false); ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
rdec = Analyze(exp->mRight, procDec, false); rdec = Analyze(exp->mRight, procDec, ANAFL_RHS);
return TheBoolTypeDeclaration; return TheBoolTypeDeclaration;
case EX_PREINCDEC: case EX_PREINCDEC:
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize; procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
return Analyze(exp->mLeft, procDec, true); return Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS);
case EX_PREFIX: case EX_PREFIX:
if (exp->mToken == TK_BINARY_AND) if (exp->mToken == TK_BINARY_AND)
{ {
ldec = Analyze(exp->mLeft, procDec, true); ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_ALIAS);
if (ldec->mType == DT_VARIABLE) if (ldec->mType == DT_VARIABLE)
ldec->mFlags |= DTF_VAR_ALIASING; ldec->mFlags |= DTF_VAR_ALIASING;
} }
else if (exp->mToken == TK_MUL) else if (exp->mToken == TK_MUL)
{ {
ldec = Analyze(exp->mLeft, procDec, false); ldec = Analyze(exp->mLeft, procDec, 0);
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
if (lhs) if (flags & ANAFL_LHS)
procDec->mFlags &= ~DTF_FUNC_PURE; procDec->mFlags &= ~DTF_FUNC_PURE;
return exp->mDecType; return exp->mDecType;
@ -812,10 +908,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
{ {
return TheUnsignedCharTypeDeclaration; return TheUnsignedCharTypeDeclaration;
} }
else if (exp->mToken == TK_SIZEOF)
{
return TheUnsignedIntTypeDeclaration;
}
else else
{ {
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize; procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
return Analyze(exp->mLeft, procDec, false); return Analyze(exp->mLeft, procDec, 0);
} }
break; break;
case EX_POSTFIX: case EX_POSTFIX:
@ -824,31 +924,31 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
case EX_POSTINCDEC: case EX_POSTINCDEC:
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize; procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
return Analyze(exp->mLeft, procDec, true); return Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS);
case EX_INDEX: case EX_INDEX:
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize; procDec->mComplexity += 10 * exp->mRight->mDecType->mSize;
ldec = Analyze(exp->mLeft, procDec, lhs); ldec = Analyze(exp->mLeft, procDec, flags & ~ANAFL_ALIAS);
if (ldec->mType == DT_VARIABLE || ldec->mType == DT_ARGUMENT) if (ldec->mType == DT_VARIABLE || ldec->mType == DT_ARGUMENT)
{ {
ldec = ldec->mBase; ldec = ldec->mBase;
if (ldec->mType == DT_TYPE_POINTER) if (ldec->mType == DT_TYPE_POINTER)
{ {
if (lhs) if (flags & ANAFL_LHS)
procDec->mFlags &= ~DTF_FUNC_PURE; procDec->mFlags &= ~DTF_FUNC_PURE;
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
} }
} }
rdec = Analyze(exp->mRight, procDec, false); rdec = Analyze(exp->mRight, procDec, 0);
if (ldec->mBase) if (ldec->mBase)
return ldec->mBase; return ldec->mBase;
break; break;
case EX_QUALIFY: case EX_QUALIFY:
Analyze(exp->mLeft, procDec, lhs); Analyze(exp->mLeft, procDec, flags);
return exp->mDecValue->mBase; return exp->mDecValue->mBase;
case EX_DISPATCH: case EX_DISPATCH:
procDec->mFlags |= DTF_PREVENT_INLINE; procDec->mFlags |= DTF_PREVENT_INLINE;
Analyze(exp->mLeft, procDec, lhs); Analyze(exp->mLeft, procDec, flags & ~ANAFL_ALIAS);
// RegisterCall(procDec, exp->mLeft->mDecType); // RegisterCall(procDec, exp->mLeft->mDecType);
break; break;
case EX_VCALL: case EX_VCALL:
@ -859,13 +959,19 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
case EX_INLINE: case EX_INLINE:
procDec->mComplexity += 10; procDec->mComplexity += 10;
ldec = Analyze(exp->mLeft, procDec, false); ldec = Analyze(exp->mLeft, procDec, 0);
if ((ldec->mFlags & DTF_INTRINSIC) && !ldec->mValue) if ((ldec->mFlags & DTF_INTRINSIC) && !ldec->mValue)
{ {
} }
else else
{ {
if (exp->mType == EX_INLINE)
{
for (int i = 0; i < ldec->mCalled.Size(); i++)
RegisterCall(procDec, ldec->mCalled[i]);
}
else
RegisterCall(procDec, ldec); RegisterCall(procDec, ldec);
if (!(GetProcFlags(ldec) & (DTF_FUNC_INTRSAVE | DTF_INTERRUPT))) if (!(GetProcFlags(ldec) & (DTF_FUNC_INTRSAVE | DTF_INTERRUPT)))
{ {
@ -940,7 +1046,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
if (pex->mType == EX_CALL && IsStackParam(pex->mDecType) && !(pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF))) if (pex->mType == EX_CALL && IsStackParam(pex->mDecType) && !(pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF)))
ldec->mBase->mFlags |= DTF_STACKCALL; ldec->mBase->mFlags |= DTF_STACKCALL;
RegisterProc(Analyze(pex, procDec, pdec && pdec->mBase->IsReference())); RegisterProc(Analyze(pex, procDec, (pdec && pdec->mBase->IsReference()) ? ANAFL_LHS : 0));
if (pdec) if (pdec)
pdec = pdec->mNext; pdec = pdec->mNext;
@ -954,12 +1060,12 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
break; break;
case EX_LIST: case EX_LIST:
case EX_COMMA: case EX_COMMA:
RegisterProc(Analyze(exp->mLeft, procDec, false)); RegisterProc(Analyze(exp->mLeft, procDec, 0));
return Analyze(exp->mRight, procDec, false); return Analyze(exp->mRight, procDec, 0);
case EX_RETURN: case EX_RETURN:
if (exp->mLeft) if (exp->mLeft)
{ {
RegisterProc(Analyze(exp->mLeft, procDec, procDec->mBase->mBase->IsReference())); RegisterProc(Analyze(exp->mLeft, procDec, procDec->mBase->mBase->IsReference() ? ANAFL_LHS : 0));
if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor) if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor)
{ {
if (procDec->mBase->mBase->mMoveConstructor) if (procDec->mBase->mBase->mMoveConstructor)
@ -970,6 +1076,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
AnalyzeProcedure(exp, procDec->mBase->mBase->mCopyConstructor->mValue, procDec->mBase->mBase->mCopyConstructor); AnalyzeProcedure(exp, procDec->mBase->mBase->mCopyConstructor->mValue, procDec->mBase->mBase->mCopyConstructor);
RegisterCall(procDec, procDec->mBase->mBase->mCopyConstructor); RegisterCall(procDec, procDec->mBase->mBase->mCopyConstructor);
} }
procDec->mFlags &= ~DTF_FUNC_NO_RETURN;
} }
break; break;
case EX_SEQUENCE: case EX_SEQUENCE:
@ -978,47 +1086,47 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
if (exp->mType == EX_SEQUENCE) if (exp->mType == EX_SEQUENCE)
{ {
if (exp->mLeft) if (exp->mLeft)
ldec = Analyze(exp->mLeft, procDec, false); ldec = Analyze(exp->mLeft, procDec, 0);
exp = exp->mRight; exp = exp->mRight;
} }
else else
return Analyze(exp, procDec, false); return Analyze(exp, procDec, 0);
} while (exp); } while (exp);
break; break;
case EX_SCOPE: case EX_SCOPE:
Analyze(exp->mLeft, procDec, false); Analyze(exp->mLeft, procDec, 0);
break; break;
case EX_CONSTRUCT: case EX_CONSTRUCT:
if (exp->mLeft->mLeft) if (exp->mLeft->mLeft)
Analyze(exp->mLeft->mLeft, procDec, false); Analyze(exp->mLeft->mLeft, procDec, 0);
if (exp->mLeft->mRight) if (exp->mLeft->mRight)
Analyze(exp->mLeft->mRight, procDec, false); Analyze(exp->mLeft->mRight, procDec, 0);
if (exp->mRight) if (exp->mRight)
return Analyze(exp->mRight, procDec, false); return Analyze(exp->mRight, procDec, 0);
break; break;
case EX_CLEANUP: case EX_CLEANUP:
Analyze(exp->mRight, procDec, false); Analyze(exp->mRight, procDec, 0);
return Analyze(exp->mLeft, procDec, lhs); return Analyze(exp->mLeft, procDec, flags & ~ANAFL_ALIAS);
case EX_WHILE: case EX_WHILE:
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
procDec->mComplexity += 20; procDec->mComplexity += 20;
ldec = Analyze(exp->mLeft, procDec, false); ldec = Analyze(exp->mLeft, procDec, 0);
rdec = Analyze(exp->mRight, procDec, false); rdec = Analyze(exp->mRight, procDec, 0);
break; break;
case EX_IF: case EX_IF:
procDec->mComplexity += 20; procDec->mComplexity += 20;
ldec = Analyze(exp->mLeft, procDec, false); ldec = Analyze(exp->mLeft, procDec, 0);
rdec = Analyze(exp->mRight->mLeft, procDec, false); rdec = Analyze(exp->mRight->mLeft, procDec, 0);
if (exp->mRight->mRight) if (exp->mRight->mRight)
rdec = Analyze(exp->mRight->mRight, procDec, false); rdec = Analyze(exp->mRight->mRight, procDec, 0);
break; break;
case EX_ELSE: case EX_ELSE:
break; break;
@ -1028,18 +1136,23 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
procDec->mComplexity += 30; procDec->mComplexity += 30;
if (exp->mLeft->mRight) if (exp->mLeft->mRight)
ldec = Analyze(exp->mLeft->mRight, procDec, false); ldec = Analyze(exp->mLeft->mRight, procDec, 0);
if (exp->mLeft->mLeft->mLeft) if (exp->mLeft->mLeft->mLeft)
ldec = Analyze(exp->mLeft->mLeft->mLeft, procDec, false); ldec = Analyze(exp->mLeft->mLeft->mLeft, procDec, 0);
rdec = Analyze(exp->mRight, procDec, false); rdec = Analyze(exp->mRight, procDec, 0);
if (exp->mLeft->mLeft->mRight) if (exp->mLeft->mLeft->mRight)
ldec = Analyze(exp->mLeft->mLeft->mRight, procDec, false); ldec = Analyze(exp->mLeft->mLeft->mRight, procDec, 0);
break;
case EX_FORBODY:
ldec = Analyze(exp->mLeft, procDec, 0);
if (exp->mRight)
Analyze(exp->mRight, procDec, 0);
break; break;
case EX_DO: case EX_DO:
procDec->mComplexity += 20; procDec->mComplexity += 20;
ldec = Analyze(exp->mLeft, procDec, false); ldec = Analyze(exp->mLeft, procDec, 0);
rdec = Analyze(exp->mRight, procDec, false); rdec = Analyze(exp->mRight, procDec, 0);
break; break;
case EX_BREAK: case EX_BREAK:
case EX_CONTINUE: case EX_CONTINUE:
@ -1048,18 +1161,18 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
case EX_TYPE: case EX_TYPE:
break; break;
case EX_TYPECAST: case EX_TYPECAST:
return Analyze(exp->mLeft, procDec, false); return Analyze(exp->mLeft, procDec, 0);
break; break;
case EX_LOGICAL_AND: case EX_LOGICAL_AND:
ldec = Analyze(exp->mLeft, procDec, false); ldec = Analyze(exp->mLeft, procDec, 0);
rdec = Analyze(exp->mRight, procDec, false); rdec = Analyze(exp->mRight, procDec, 0);
break; break;
case EX_LOGICAL_OR: case EX_LOGICAL_OR:
ldec = Analyze(exp->mLeft, procDec, false); ldec = Analyze(exp->mLeft, procDec, 0);
rdec = Analyze(exp->mRight, procDec, false); rdec = Analyze(exp->mRight, procDec, 0);
break; break;
case EX_LOGICAL_NOT: case EX_LOGICAL_NOT:
ldec = Analyze(exp->mLeft, procDec, false); ldec = Analyze(exp->mLeft, procDec, 0);
break; break;
case EX_ASSEMBLER: case EX_ASSEMBLER:
procDec->mFlags |= DTF_FUNC_ASSEMBLER; procDec->mFlags |= DTF_FUNC_ASSEMBLER;
@ -1070,14 +1183,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
case EX_UNDEFINED: case EX_UNDEFINED:
break; break;
case EX_SWITCH: case EX_SWITCH:
ldec = Analyze(exp->mLeft, procDec, false); ldec = Analyze(exp->mLeft, procDec, 0);
exp = exp->mRight; exp = exp->mRight;
while (exp) while (exp)
{ {
procDec->mComplexity += 10; procDec->mComplexity += 10;
if (exp->mLeft->mRight) if (exp->mLeft->mRight)
rdec = Analyze(exp->mLeft->mRight, procDec, false); rdec = Analyze(exp->mLeft->mRight, procDec, 0);
exp = exp->mRight; exp = exp->mRight;
} }
break; break;
@ -1088,9 +1201,9 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
case EX_CONDITIONAL: case EX_CONDITIONAL:
procDec->mComplexity += exp->mDecType->mSize * 10; procDec->mComplexity += exp->mDecType->mSize * 10;
ldec = Analyze(exp->mLeft, procDec, false); ldec = Analyze(exp->mLeft, procDec, 0);
RegisterProc(Analyze(exp->mRight->mLeft, procDec, lhs)); RegisterProc(Analyze(exp->mRight->mLeft, procDec, flags));
RegisterProc(Analyze(exp->mRight->mRight, procDec, lhs)); RegisterProc(Analyze(exp->mRight->mRight, procDec, flags));
break; break;
} }

View File

@ -11,6 +11,7 @@ public:
~GlobalAnalyzer(void); ~GlobalAnalyzer(void);
void DumpCallGraph(void); void DumpCallGraph(void);
void TopoSort(Declaration * procDec);
void AutoInline(void); void AutoInline(void);
void CheckFastcall(Declaration* procDec, bool head); void CheckFastcall(Declaration* procDec, bool head);
void CheckInterrupt(void); void CheckInterrupt(void);
@ -27,12 +28,14 @@ protected:
Errors* mErrors; Errors* mErrors;
Linker* mLinker; Linker* mLinker;
GrowingArray<Declaration*> mCalledFunctions, mCallingFunctions, mVariableFunctions, mFunctions; GrowingArray<Declaration*> mCalledFunctions, mCallingFunctions, mVariableFunctions, mFunctions, mTopoFunctions;
GrowingArray<Declaration*> mGlobalVariables; GrowingArray<Declaration*> mGlobalVariables;
void AnalyzeInit(Declaration* mdec); void AnalyzeInit(Declaration* mdec);
int CallerInvokes(Declaration* called);
int CallerInvokes(Declaration* caller, Declaration* called);
Declaration* Analyze(Expression* exp, Declaration* procDec, bool lhs); Declaration* Analyze(Expression* exp, Declaration* procDec, uint32 flags);
bool IsStackParam(const Declaration* pdec) const; bool IsStackParam(const Declaration* pdec) const;
bool MarkCycle(Declaration* rootDec, Declaration* procDec); bool MarkCycle(Declaration* rootDec, Declaration* procDec);

View File

@ -60,7 +60,7 @@ void GlobalOptimizer::Reset(void)
mFunctions.SetSize(0); mFunctions.SetSize(0);
mGlobalVariables.SetSize(0); mGlobalVariables.SetSize(0);
mCalledFunctions.SetSize(0); mCalledFunctions.SetSize(0);
mCalledFunctions.SetSize(0); mCallingFunctions.SetSize(0);
} }
void GlobalOptimizer::PropagateParamCommas(Expression*& fexp, Expression*& exp) void GlobalOptimizer::PropagateParamCommas(Expression*& fexp, Expression*& exp)
@ -134,7 +134,7 @@ bool GlobalOptimizer::CheckConstReturns(Expression*& exp)
Expression* lexp = new Expression(exp->mLocation, EX_COMMA); Expression* lexp = new Expression(exp->mLocation, EX_COMMA);
lexp->mLeft = exp; lexp->mLeft = exp;
lexp->mRight = new Expression(pcall->mReturn->mLocation, EX_CONSTANT); lexp->mRight = new Expression(pcall->mReturn->mLocation, EX_CONSTANT);
lexp->mRight->mDecValue = pcall->mReturn->mLeft->mDecValue; lexp->mRight->mDecValue = pcall->mReturn->mLeft->mDecValue->ConstCast(exp->mDecType);
lexp->mRight->mDecType = exp->mDecType; lexp->mRight->mDecType = exp->mDecType;
lexp->mDecType = exp->mDecType; lexp->mDecType = exp->mDecType;
exp->mDecType = TheVoidTypeDeclaration; exp->mDecType = TheVoidTypeDeclaration;
@ -160,6 +160,7 @@ bool GlobalOptimizer::CheckConstReturns(Expression*& exp)
lexp->mRight->mToken = TK_MUL; lexp->mRight->mToken = TK_MUL;
lexp->mRight->mLeft = pex; lexp->mRight->mLeft = pex;
lexp->mRight->mDecType = pcall->mBase->mBase; lexp->mRight->mDecType = pcall->mBase->mBase;
lexp->mDecType = lexp->mRight->mDecType;
exp->mDecType = TheVoidTypeDeclaration; exp->mDecType = TheVoidTypeDeclaration;
exp = lexp; exp = lexp;
return true; return true;
@ -188,7 +189,7 @@ bool GlobalOptimizer::CheckUnusedLocals(Expression*& exp)
if (vexp->mType == EX_VARIABLE) if (vexp->mType == EX_VARIABLE)
{ {
Declaration* vdec = vexp->mDecValue; Declaration* vdec = vexp->mDecValue;
if (vdec->mType == DT_VARIABLE && !(vdec->mFlags & (DTF_GLOBAL | DTF_STATIC)) && !(vdec->mOptFlags & OPTF_VAR_USED)) if (vdec->mType == DT_VARIABLE && !(vdec->mFlags & (DTF_GLOBAL | DTF_STATIC)) && !(vdec->mOptFlags & OPTF_VAR_USED) && !exp->mRight->IsVolatile())
{ {
exp = exp->mRight; exp = exp->mRight;
return true; return true;
@ -242,6 +243,19 @@ bool GlobalOptimizer::ReplaceParamConst(Expression* exp, Declaration* param)
bool changed = false; bool changed = false;
if (exp) if (exp)
{ {
if (ReplaceParamConst(exp->mLeft, param))
changed = true;
if (ReplaceParamConst(exp->mRight, param))
changed = true;
if (changed)
{
if (exp->mLeft)
exp->mLeft = exp->mLeft->ConstantFold(mErrors, nullptr);
if (exp->mRight)
exp->mRight = exp->mRight->ConstantFold(mErrors, nullptr);
}
if (exp->mType == EX_VARIABLE && exp->mDecValue == param) if (exp->mType == EX_VARIABLE && exp->mDecValue == param)
{ {
exp->mType = EX_CONSTANT; exp->mType = EX_CONSTANT;
@ -250,9 +264,39 @@ bool GlobalOptimizer::ReplaceParamConst(Expression* exp, Declaration* param)
changed = true; changed = true;
} }
if (ReplaceParamConst(exp->mLeft, param)) }
return changed;
}
bool GlobalOptimizer::ReplaceGlobalConst(Expression* exp)
{
bool changed = false;
if (exp)
{
if (exp->mType == EX_VARIABLE && (exp->mDecValue->mFlags & (DTF_GLOBAL | DTF_STATIC)) && !(exp->mDecValue->mOptFlags & (OPTF_VAR_MODIFIED | OPTF_VAR_ADDRESS)) && exp->mDecValue->mValue)
{
Expression* cexp = exp->mDecValue->mValue;
if (cexp->mType == EX_CONSTANT)
{
if (cexp->mDecValue->mType == DT_CONST_ADDRESS || cexp->mDecValue->mType == DT_CONST_INTEGER ||
cexp->mDecValue->mType == DT_CONST_POINTER || cexp->mDecValue->mType == DT_CONST_FLOAT)
{
exp->mType = EX_CONSTANT;
exp->mDecValue = cexp->mDecValue->ConstCast(exp->mDecType);
changed = true; changed = true;
if (ReplaceParamConst(exp->mRight, param)) }
else if (exp->mDecValue->mBase->mType == DT_TYPE_STRUCT)
{
exp->mDecValue->mBase = exp->mDecValue->mBase->ToConstType();
}
}
}
if (ReplaceGlobalConst(exp->mLeft))
changed = true;
if (ReplaceGlobalConst(exp->mRight))
changed = true; changed = true;
} }
return changed; return changed;
@ -281,6 +325,9 @@ bool GlobalOptimizer::Optimize(void)
if (CheckConstReturns(func->mValue)) if (CheckConstReturns(func->mValue))
changed = true; changed = true;
if (ReplaceGlobalConst(func->mValue))
changed = true;
if (func->mOptFlags & OPTF_MULTI_CALL) if (func->mOptFlags & OPTF_MULTI_CALL)
{ {
Declaration* pdata = ftype->mParams; Declaration* pdata = ftype->mParams;
@ -294,7 +341,7 @@ bool GlobalOptimizer::Optimize(void)
if (!(func->mOptFlags & OPTF_FUNC_VARIABLE) && !(func->mBase->mFlags & DTF_VIRTUAL)) if (!(func->mOptFlags & OPTF_FUNC_VARIABLE) && !(func->mBase->mFlags & DTF_VIRTUAL))
{ {
if (!(func->mOptFlags & OPTF_VAR_USED) && func->mBase->mBase && (func->mBase->mBase->IsSimpleType() || func->mBase->mBase->IsReference())) if (!(func->mOptFlags & (OPTF_VAR_USED | OPTF_VAR_ADDRESS)) && func->mBase->mBase && (func->mBase->mBase->IsSimpleType() || func->mBase->mBase->IsReference()))
{ {
#if DUMP_OPTS #if DUMP_OPTS
printf("Remove return value\n"); printf("Remove return value\n");
@ -312,7 +359,8 @@ bool GlobalOptimizer::Optimize(void)
changed = true; changed = true;
} }
if (!(ftype->mFlags & DTF_VARIADIC))
{
Declaration* pdec = ftype->mParams; Declaration* pdec = ftype->mParams;
int vi = 0; int vi = 0;
while (pdec) while (pdec)
@ -351,6 +399,7 @@ bool GlobalOptimizer::Optimize(void)
{ {
if (ReplaceParamConst(func->mValue, pdec)) if (ReplaceParamConst(func->mValue, pdec))
{ {
func->mValue = func->mValue->ConstantFold(mErrors, nullptr);
#if DUMP_OPTS #if DUMP_OPTS
printf("Const parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_"); printf("Const parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_");
#endif #endif
@ -362,6 +411,7 @@ bool GlobalOptimizer::Optimize(void)
pdec = pdec->mNext; pdec = pdec->mNext;
} }
} }
}
PropagateCommas(func->mValue); PropagateCommas(func->mValue);
} }
@ -412,7 +462,7 @@ void GlobalOptimizer::AnalyzeProcedure(Expression* exp, Declaration* procDec)
Analyze(exp, procDec, false); Analyze(exp, procDec, false);
} }
else else
mErrors->Error(procDec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", procDec->mQualIdent); mErrors->Error(procDec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", procDec->FullIdent());
procDec->mOptFlags &= ~OPTF_ANALYZING; procDec->mOptFlags &= ~OPTF_ANALYZING;
} }
@ -433,7 +483,6 @@ void GlobalOptimizer::AnalyzeAssembler(Expression* exp, Declaration* procDec)
{ {
if (adec->mBase->mFlags & DTF_GLOBAL) if (adec->mBase->mFlags & DTF_GLOBAL)
AnalyzeGlobalVariable(adec->mBase); AnalyzeGlobalVariable(adec->mBase);
else
adec->mBase->mOptFlags |= OPTF_VAR_USED | OPTF_VAR_ADDRESS; adec->mBase->mOptFlags |= OPTF_VAR_USED | OPTF_VAR_ADDRESS;
} }
else if (adec->mType == DT_LABEL) else if (adec->mType == DT_LABEL)
@ -444,7 +493,6 @@ void GlobalOptimizer::AnalyzeAssembler(Expression* exp, Declaration* procDec)
{ {
if (adec->mFlags & DTF_GLOBAL) if (adec->mFlags & DTF_GLOBAL)
AnalyzeGlobalVariable(adec); AnalyzeGlobalVariable(adec);
else
adec->mOptFlags |= OPTF_VAR_USED | OPTF_VAR_ADDRESS; adec->mOptFlags |= OPTF_VAR_USED | OPTF_VAR_ADDRESS;
} }
else if (adec->mType == DT_ARGUMENT) else if (adec->mType == DT_ARGUMENT)
@ -566,9 +614,6 @@ void GlobalOptimizer::RegisterProc(Declaration* to)
} }
} }
static const uint32 ANAFL_LHS = (1U << 0);
static const uint32 ANAFL_RHS = (1U << 1);
Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uint32 flags) Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uint32 flags)
{ {
Declaration* ldec, * rdec; Declaration* ldec, * rdec;
@ -610,14 +655,14 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin
AnalyzeGlobalVariable(exp->mDecValue); AnalyzeGlobalVariable(exp->mDecValue);
} }
else
{
if (flags & ANAFL_RHS) if (flags & ANAFL_RHS)
exp->mDecValue->mOptFlags |= OPTF_VAR_USED; exp->mDecValue->mOptFlags |= OPTF_VAR_USED;
if (flags & ANAFL_LHS) if (flags & ANAFL_LHS)
exp->mDecValue->mOptFlags |= OPTF_VAR_ADDRESS; exp->mDecValue->mOptFlags |= OPTF_VAR_ADDRESS;
} if (exp->mDecValue->mBase->IsReference() && (flags & ANAFL_ASSIGN))
if (exp->mDecValue->mType == DT_ARGUMENT) exp->mDecValue->mOptFlags |= OPTF_VAR_USED;
if (exp->mDecValue->mType == DT_ARGUMENT && (flags & ANAFL_LHS))
{ {
exp->mDecValue->mOptFlags |= OPTF_VAR_NO_FORWARD; exp->mDecValue->mOptFlags |= OPTF_VAR_NO_FORWARD;
exp->mDecValue->mForwardParam = nullptr; exp->mDecValue->mForwardParam = nullptr;
@ -627,7 +672,12 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin
case EX_INITIALIZATION: case EX_INITIALIZATION:
case EX_ASSIGNMENT: case EX_ASSIGNMENT:
if (exp->mToken == TK_ASSIGN) if (exp->mToken == TK_ASSIGN)
{
if (exp->mType == EX_ASSIGNMENT)
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_ASSIGN | flags);
else
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | flags); ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | flags);
}
else else
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS | flags); ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS | flags);
@ -775,6 +825,22 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin
pdec->mOptFlags |= OPTF_VAR_CONST; pdec->mOptFlags |= OPTF_VAR_CONST;
} }
} }
else if (pex->mType == EX_VARIABLE && pdec->mBase->mType == DT_TYPE_POINTER && pex->mDecType->mType == DT_TYPE_ARRAY && (pex->mDecValue->mFlags & (DTF_GLOBAL | DTF_STATIC)) && pdec->mBase->CanAssign(pex->mDecType))
{
if (pdec->mOptFlags & OPTF_VAR_CONST)
{
if (pdec->mValue->mType != EX_VARIABLE || pdec->mValue->mDecValue != pex->mDecValue)
{
pdec->mOptFlags |= OPTF_VAR_NOCONST;
pdec->mOptFlags &= ~OPTF_VAR_CONST;
}
}
else
{
pdec->mValue = pex;
pdec->mOptFlags |= OPTF_VAR_CONST;
}
}
else else
{ {
pdec->mOptFlags |= OPTF_VAR_NOCONST; pdec->mOptFlags |= OPTF_VAR_NOCONST;
@ -920,13 +986,20 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin
if (exp->mLeft->mLeft->mRight) if (exp->mLeft->mLeft->mRight)
ldec = Analyze(exp->mLeft->mLeft->mRight, procDec, 0); ldec = Analyze(exp->mLeft->mLeft->mRight, procDec, 0);
break; break;
case EX_FORBODY:
ldec = Analyze(exp->mLeft, procDec, 0);
if (exp->mRight)
rdec = Analyze(exp->mRight, procDec, 0);
break;
case EX_DO: case EX_DO:
ldec = Analyze(exp->mRight, procDec, 0); ldec = Analyze(exp->mRight, procDec, 0);
rdec = Analyze(exp->mLeft, procDec, ANAFL_RHS); rdec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
break; break;
case EX_BREAK: case EX_BREAK:
case EX_CONTINUE: case EX_CONTINUE:
break;
case EX_ASSUME: case EX_ASSUME:
return Analyze(exp->mLeft, procDec, ANAFL_RHS);
break; break;
case EX_TYPE: case EX_TYPE:
break; break;

View File

@ -39,5 +39,6 @@ protected:
bool ReplaceParamConst(Expression* exp, Declaration* param); bool ReplaceParamConst(Expression* exp, Declaration* param);
void PropagateCommas(Expression*& exp); void PropagateCommas(Expression*& exp);
void PropagateParamCommas(Expression *& fexp, Expression*& exp); void PropagateParamCommas(Expression *& fexp, Expression*& exp);
bool ReplaceGlobalConst(Expression* exp);
}; };

View File

@ -47,7 +47,7 @@ const Ident* Ident::Unique(const char* str)
const Ident* Ident::PreMangle(const char* str) const const Ident* Ident::PreMangle(const char* str) const
{ {
char buffer[200]; char buffer[1000];
strcpy_s(buffer, str); strcpy_s(buffer, str);
strcat_s(buffer, mString); strcat_s(buffer, mString);
return Unique(buffer); return Unique(buffer);
@ -55,14 +55,14 @@ const Ident* Ident::PreMangle(const char* str) const
const Ident* Ident::Unique(const char* str, int id) const Ident* Ident::Unique(const char* str, int id)
{ {
char buffer[200]; char buffer[1000];
sprintf_s(buffer, "%s#%d", str, id); sprintf_s(buffer, "%s#%d", str, id);
return Unique(buffer); return Unique(buffer);
} }
const Ident* Ident::Mangle(const char* str) const const Ident* Ident::Mangle(const char* str) const
{ {
char buffer[200]; char buffer[1000];
strcpy_s(buffer, mString); strcpy_s(buffer, mString);
strcat_s(buffer, str); strcat_s(buffer, str);
return Unique(buffer); return Unique(buffer);

Some files were not shown because too many files have changed in this diff Show More