Compare commits
586 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6ed4adb0ed | ||
|
f16c24363c | ||
|
fd7e68573c | ||
|
f1873f0794 | ||
|
a01d98e584 | ||
|
c7a53a5be6 | ||
|
4633631d7e | ||
|
100608e0ac | ||
|
35a0b36a0d | ||
|
5470db3a5f | ||
|
d6802f3cb9 | ||
|
5b4e0c2b55 | ||
|
8175fae67a | ||
|
13c90eb542 | ||
|
f98665c577 | ||
|
8843f3feba | ||
|
514cf59398 | ||
|
03c133cd48 | ||
|
880abea32e | ||
|
fc9a8f2a89 | ||
|
40c467d958 | ||
|
4bde6385b8 | ||
|
688ef958e3 | ||
|
6da7223472 | ||
|
a1d4bc8375 | ||
|
197e2a91be | ||
|
4d9d628b67 | ||
|
f720feebbf | ||
|
6076808f5e | ||
|
0af17f0f40 | ||
|
81e5321bfc | ||
|
27d3666285 | ||
|
c6b794db3a | ||
|
1fa4c39a20 | ||
|
0ba148b6bb | ||
|
65540da3f7 | ||
|
e660757824 | ||
|
05a6d16dde | ||
|
79ec9af3f2 | ||
|
8f37df448f | ||
|
d710a71ba0 | ||
|
8dd211b662 | ||
|
398ed22b09 | ||
|
6f1da4335b | ||
|
c86dc364b1 | ||
|
70eb7a5eab | ||
|
c1cd2ba57e | ||
|
00da0ef87d | ||
|
be9abbf510 | ||
|
0b72e6b2f2 | ||
|
6ea39d7bfa | ||
|
c0abe031ee | ||
|
fe667863b2 | ||
|
e514e05dc8 | ||
|
d978d0a483 | ||
|
37cacdafa7 | ||
|
78e3696663 | ||
|
a0215a4f21 | ||
|
2310416c46 | ||
|
52db653ec1 | ||
|
6fe76e478f | ||
|
ba05ec743d | ||
|
05ef25a61e | ||
|
b26cc4ede7 | ||
|
8dc5f703e8 | ||
|
c05d7e47f4 | ||
|
9dc8489693 | ||
|
f443c97f70 | ||
|
4837ceb73f | ||
|
42299c9406 | ||
|
850bbfc31a | ||
|
1e95f51469 | ||
|
e525e5d62e | ||
|
18deb8846d | ||
|
34ce9afeae | ||
|
d0411b7d52 | ||
|
34fda8c9b5 | ||
|
b4a357e44f | ||
|
2b224f262b | ||
|
3c306e0899 | ||
|
e82ab0c7ca | ||
|
983064c694 | ||
|
9230d95bad | ||
|
8b0790588b | ||
|
0a9c43757a | ||
|
fccfe35c4f | ||
|
064fed63f5 | ||
|
f43f471124 | ||
|
f99abb32e2 | ||
|
18f044e90c | ||
|
5b961c031c | ||
|
500cce511f | ||
|
885d6ff706 | ||
|
efc182ce27 | ||
|
06ef87fe63 | ||
|
f3d8251072 | ||
|
0d5efc90ed | ||
|
30b8e4e970 | ||
|
3da1ddf5da | ||
|
bfdd1b85fb | ||
|
686d468d32 | ||
|
23b15678cd | ||
|
d1054abd90 | ||
|
d358c8359b | ||
|
9e9494ebf9 | ||
|
015ada7a33 | ||
|
12e832ebd3 | ||
|
e327d2a148 | ||
|
366f9686dd | ||
|
a2927401bc | ||
|
bbb339d641 | ||
|
8e76334c20 | ||
|
739f1e2161 | ||
|
4ee6ca5b94 | ||
|
347898ea53 | ||
|
6caed58be4 | ||
|
c4185832ba | ||
|
2b0994b086 | ||
|
f9acbc152d | ||
|
3eed21567e | ||
|
f3370cb149 | ||
|
494fb97e49 | ||
|
bd8786af0b | ||
|
f0a7499814 | ||
|
da4a90b724 | ||
|
96a9109915 | ||
|
f5a33edcf4 | ||
|
1bd98bdeb2 | ||
|
e4696a6539 | ||
|
74350d6133 | ||
|
cbf86b2e8f | ||
|
cb757dfaf9 | ||
|
5ad94d01d4 | ||
|
cdba71b353 | ||
|
01d187cf83 | ||
|
ab06ce74c5 | ||
|
1e2b227113 | ||
|
9d5dbe67fe | ||
|
9a409ca347 | ||
|
449acece05 | ||
|
ee3f6fc4a5 | ||
|
e95b51609c | ||
|
323589a484 | ||
|
33f4b25f28 | ||
|
538d965636 | ||
|
4b99110533 | ||
|
94f2489083 | ||
|
6de1b1fd96 | ||
|
80abcdfe95 | ||
|
0dc6588a66 | ||
|
65ad05c608 | ||
|
2db8890453 | ||
|
3f4268328e | ||
|
33cabb487b | ||
|
ab2ca897ce | ||
|
2c37e150a9 | ||
|
ee68f2575a | ||
|
4f100266c3 | ||
|
c22a67f95f | ||
|
e6bc6371c9 | ||
|
2acca6d7b1 | ||
|
fc2095301d | ||
|
32f0b8c6f3 | ||
|
10c9b735e9 | ||
|
fefb511404 | ||
|
bedafe7b6f | ||
|
242d7f1700 | ||
|
90e892dfa5 | ||
|
c98e0751b0 | ||
|
f3b4a4e5fc | ||
|
1c7d71cadb | ||
|
840050738f | ||
|
2ee5cc7bf4 | ||
|
490180f9dc | ||
|
2582f3076d | ||
|
0032d42b2c | ||
|
5c70c20c6e | ||
|
71236aa405 | ||
|
31a38e2a62 | ||
|
ee0e4d5428 | ||
|
f6296e83e5 | ||
|
39840b5fb1 | ||
|
fe0bfccfaa | ||
|
25ee4e9b2b | ||
|
9f7d4c0ab0 | ||
|
038928232c | ||
|
100affa083 | ||
|
e27075955d | ||
|
0959a15b10 | ||
|
4a87e4d97b | ||
|
9de7caa68d | ||
|
e23d78eb86 | ||
|
d0b45fce78 | ||
|
0126dd53a3 | ||
|
901c8459ec | ||
|
746fed6704 | ||
|
54c0f2a670 | ||
|
28ea8ef24f | ||
|
115129e1dd | ||
|
f41d594015 | ||
|
c8abb42c3c | ||
|
95732265f6 | ||
|
9f834c4232 | ||
|
d10d8bf7ae | ||
|
f6a2db7866 | ||
|
d2fdbd29f5 | ||
|
f5dff9620b | ||
|
28e75a8fa2 | ||
|
6170c81af3 | ||
|
3d578170db | ||
|
d99499b6e3 | ||
|
950c434157 | ||
|
d6362a305f | ||
|
38bb033328 | ||
|
87f1ddd27f | ||
|
9e994560a7 | ||
|
e37de95079 | ||
|
8e46ae95ec | ||
|
e7cece0f0f | ||
|
890a4b996e | ||
|
5b2ae228cc | ||
|
9fc8315f92 | ||
|
32935cd7a1 | ||
|
fd02382d38 | ||
|
4fce263228 | ||
|
50c7e10814 | ||
|
7c8ab991be | ||
|
067e169803 | ||
|
ccdbbe799a | ||
|
fac53cfd54 | ||
|
cfe2c7bed5 | ||
|
f0b9b5cce4 | ||
|
803b868356 | ||
|
907452d918 | ||
|
c12bca7b4e | ||
|
e1736c8214 | ||
|
d3e7a991a4 | ||
|
e7b0d17a83 | ||
|
df18dc273e | ||
|
b6341e402d | ||
|
3f2f703936 | ||
|
4acee4531c | ||
|
2a476d3372 | ||
|
0a41cb044c | ||
|
5a0f736d41 | ||
|
020534dbc8 | ||
|
cee2801847 | ||
|
51c38a4723 | ||
|
bb01d1024a | ||
|
903a5d9b8b | ||
|
e360dea558 | ||
|
582443ef5c | ||
|
80a42216c7 | ||
|
6576f4d090 | ||
|
55e983e5a1 | ||
|
a6f9c733a1 | ||
|
3c129ff4e5 | ||
|
db386a5958 | ||
|
179cc694e3 | ||
|
887a51b176 | ||
|
5b81379dac | ||
|
4fff9f7060 | ||
|
40c407782d | ||
|
5946f17632 | ||
|
7e0ff7449c | ||
|
d597219aea | ||
|
a311396cf8 | ||
|
94607cab7f | ||
|
4d193a30b0 | ||
|
c1ad265f47 | ||
|
4e2a2c99ba | ||
|
ea33f253d4 | ||
|
ebc41560d9 | ||
|
2d2c696aa4 | ||
|
b622c25a56 | ||
|
439cf499ed | ||
|
cd5f1daaba | ||
|
ec95f6dc98 | ||
|
66dfe5df46 | ||
|
9117827cfc | ||
|
ad115701d5 | ||
|
a15125d6af | ||
|
dadd8eb41c | ||
|
056b49e1d1 | ||
|
1f492e7820 | ||
|
4c687dfa54 | ||
|
e1f5bdf48b | ||
|
3ba7e0a8a4 | ||
|
a71fae5bb1 | ||
|
f6c78d57ef | ||
|
6af50f5eae | ||
|
62ab925e01 | ||
|
5126ba482e | ||
|
fb477b33f7 | ||
|
756fe9354a | ||
|
73c2206a1a | ||
|
c1071ecd3c | ||
|
534ddc3a4c | ||
|
ebce50320f | ||
|
cfd2e5142a | ||
|
581137ade7 | ||
|
c3b46d6a78 | ||
|
84a8bf22e8 | ||
|
daeb3ddfdd | ||
|
bf5f5a807c | ||
|
3dfba389ff | ||
|
a4f1341587 | ||
|
57d8747cb7 | ||
|
1fb68c1bf3 | ||
|
5613a719c5 | ||
|
bf6343616b | ||
|
861eeaefe2 | ||
|
db3c6a3135 | ||
|
4c7dafed25 | ||
|
b1440a9b3f | ||
|
21b5e75ddb | ||
|
49893f6976 | ||
|
c87887cbd1 | ||
|
bcd118a8b3 | ||
|
d7bfd0a668 | ||
|
aeceb36e2a | ||
|
f67d537c7c | ||
|
87d2163f2d | ||
|
639008b990 | ||
|
3c21ecb1d3 | ||
|
f764cf1936 | ||
|
44a9aaf89b | ||
|
925ee9d8f3 | ||
|
a04b09c737 | ||
|
2c9fd0e1a6 | ||
|
d7c9f15593 | ||
|
b61aa37f71 | ||
|
e80f9812ef | ||
|
84a0a9660f | ||
|
a93b495ac5 | ||
|
5d7dcf9373 | ||
|
2f5faaa5ab | ||
|
dfe233a95e | ||
|
92b72b19ec | ||
|
ff4a0802ea | ||
|
9adcbd2706 | ||
|
6981b28a64 | ||
|
7f41936df0 | ||
|
ccf72c6b77 | ||
|
c508d94d7c | ||
|
ce710fca5d | ||
|
ce0ac30280 | ||
|
dec7580d8d | ||
|
40001164d4 | ||
|
8bd5ec76c3 | ||
|
534a42d2fe | ||
|
226d8afc24 | ||
|
47531ac5e8 | ||
|
b3be121f41 | ||
|
e7e53580ea | ||
|
8a1eeee22d | ||
|
3e78933e9c | ||
|
637a10b234 | ||
|
c5dff3caf3 | ||
|
c529fc2b59 | ||
|
4886d0194f | ||
|
aae7d81cc6 | ||
|
8d18969940 | ||
|
68b57bb9a8 | ||
|
5aeec2fad4 | ||
|
73dece7b58 | ||
|
bfa1254eb7 | ||
|
e89aa11e86 | ||
|
4423837888 | ||
|
723f407757 | ||
|
f2338f1d13 | ||
|
235cbbc227 | ||
|
a2ca0de809 | ||
|
f7b00eff95 | ||
|
163354b33e | ||
|
7efd512ee9 | ||
|
7b7fe6c5a9 | ||
|
7abd615a18 | ||
|
14e5896e37 | ||
|
381aaa1509 | ||
|
f0f174e439 | ||
|
1f9226255a | ||
|
dcfa50e36e | ||
|
0b2c36ab1a | ||
|
0163fb729a | ||
|
d6c4828bef | ||
|
e7dbd39adf | ||
|
759a701df8 | ||
|
17ec90cfe7 | ||
|
e7ec859dfc | ||
|
da93410468 | ||
|
f38b366d81 | ||
|
8fbe96b9ac | ||
|
b48b8b836d | ||
|
967b315be5 | ||
|
ca995bf342 | ||
|
c58bb46e7e | ||
|
122dc12d40 | ||
|
cc576bd640 | ||
|
09641d16f5 | ||
|
552c4945bf | ||
|
34d6131471 | ||
|
9ecf1546cc | ||
|
7ffa623d92 | ||
|
8e81e6aad5 | ||
|
3a3a76a2e1 | ||
|
4027b2dbe0 | ||
|
62cede95ce | ||
|
abb2d7a417 | ||
|
f9afb3edb7 | ||
|
32c090880b | ||
|
be5626adc9 | ||
|
b1c68d04dd | ||
|
f9b7dd8418 | ||
|
8a6e3eb924 | ||
|
932c7ec222 | ||
|
e4e997fef2 | ||
|
3ec8a7bc06 | ||
|
d98c4b760f | ||
|
d67980d79f | ||
|
092592a05b | ||
|
586fab6b6b | ||
|
eab2a490f4 | ||
|
95992df67d | ||
|
89ba57e18d | ||
|
6f069946ba | ||
|
3df85b09fc | ||
|
fb5b69ae5c | ||
|
7350b11001 | ||
|
b7d7614471 | ||
|
f49027b2d7 | ||
|
d24e666f92 | ||
|
2ba46283b2 | ||
|
65b9c58504 | ||
|
02a2874a19 | ||
|
60868c71d3 | ||
|
9013952431 | ||
|
0b8304b40d | ||
|
1bc5a2ad7e | ||
|
5bb8ca0b89 | ||
|
7ecd6adb20 | ||
|
5b50389340 | ||
|
5f2e05d1dd | ||
|
3cc37acaa4 | ||
|
4680ee32f0 | ||
|
3dd23ec789 | ||
|
efd688320f | ||
|
d0fb062006 | ||
|
c229a27992 | ||
|
d3536a718e | ||
|
5909db71d5 | ||
|
96ada6e22a | ||
|
85f01b833c | ||
|
68a648440a | ||
|
a3bf7296bb | ||
|
dd1f5b9043 | ||
|
fcc2cbbebe | ||
|
470462fe8b | ||
|
301431f12a | ||
|
c0e524cd82 | ||
|
4068957442 | ||
|
bf89d7af33 | ||
|
d070e32b4d | ||
|
ad310f8484 | ||
|
7eb149a71b | ||
|
1c0db235a8 | ||
|
94181326ca | ||
|
cd7567452a | ||
|
2fec9f066f | ||
|
fe736289e6 | ||
|
715f295f5e | ||
|
a71c433fc4 | ||
|
9678814654 | ||
|
1598360b65 | ||
|
9d890228bf | ||
|
2d82727565 | ||
|
3851a4c2db | ||
|
17f56d0a69 | ||
|
1a6a98e57e | ||
|
5ddfc628dc | ||
|
bf5099f57b | ||
|
d4a381f71c | ||
|
17002e4c78 | ||
|
cf9a006005 | ||
|
1fa9828f6a | ||
|
3f9d042863 | ||
|
277afd156d | ||
|
b428b608b5 | ||
|
58361e39b8 | ||
|
3770a05aee | ||
|
5993f75c92 | ||
|
d7a2b98b4d | ||
|
02b28096af | ||
|
02e921364b | ||
|
4cf64ee170 | ||
|
c99c1756a9 | ||
|
5ccfab0342 | ||
|
42eea7f8f4 | ||
|
ff6bb8ccd5 | ||
|
2e3aea9d96 | ||
|
4954a285e7 | ||
|
46b52a57f7 | ||
|
41ba2e73f2 | ||
|
fbc9607e17 | ||
|
2e696d9e1a | ||
|
b09e9a2434 | ||
|
2e1c020db4 | ||
|
13629c70d4 | ||
|
b1b5ee737b | ||
|
884fe50dd7 | ||
|
af38f64a99 | ||
|
a22dfa6ba7 | ||
|
9fa8b644a7 | ||
|
375307822e | ||
|
c0152b1ce4 | ||
|
3460c06508 | ||
|
d3734a66e0 | ||
|
ccf13c78f0 | ||
|
2c28551ca3 | ||
|
4fb35a7af2 | ||
|
a2a22476ed | ||
|
1b22a5e3c5 | ||
|
ab06d85a91 | ||
|
80b1683fa2 | ||
|
d79aae3078 | ||
|
4c0e737508 | ||
|
86e0cbf9c2 | ||
|
142bc988b1 | ||
|
3ea44d1979 | ||
|
04d1abd803 | ||
|
ba1bc29b1a | ||
|
37776dfaee | ||
|
c28f342f3e | ||
|
354a420aa4 | ||
|
fb72e8baf8 | ||
|
976703f713 | ||
|
dc5afa6e79 | ||
|
740762d4a1 | ||
|
f0b7cddeb1 | ||
|
9b47a34840 | ||
|
bb8c31bf32 | ||
|
87ca43e5b7 | ||
|
411648b130 | ||
|
611f672b81 | ||
|
755c9234e1 | ||
|
c3c0583f19 | ||
|
55ddce2211 | ||
|
5971f9a80f | ||
|
fbfd597306 | ||
|
0184a550c5 | ||
|
2cdc95ba05 | ||
|
fefa462730 | ||
|
7b20e6cca0 | ||
|
ed82e3595b | ||
|
6cfdc0ce5f | ||
|
1f17f1c198 | ||
|
99da637734 | ||
|
afcc8bc101 | ||
|
4b2525b7a4 | ||
|
aa601a5727 | ||
|
85fad64e9c | ||
|
30d942478f | ||
|
89750c3f73 | ||
|
ee43223543 | ||
|
89ac4ee9b9 | ||
|
b411178aae | ||
|
45246a2f2d | ||
|
0c43952e37 | ||
|
f877e5b8c2 | ||
|
2d50d56606 | ||
|
bdecbe77e4 | ||
|
f39cb38eb3 | ||
|
148c288942 | ||
|
e2f822e7d1 | ||
|
0b58e9eaaf | ||
|
0a76a57f18 | ||
|
22ffbfa63c | ||
|
94a3097ba7 | ||
|
c05bd269ad | ||
|
aab71cbab3 | ||
|
1041ef03eb | ||
|
e2f36bbb9a | ||
|
5e9df61ffc | ||
|
cc5a90ac21 | ||
|
3900e1cf92 | ||
|
6b98a44fc0 |
|
@ -353,3 +353,4 @@ make/oscar64
|
|||
*.mapd
|
||||
*.idb
|
||||
oscar64/Releasex64/oscar64.vcxproj.FileListAbsolute.txt
|
||||
/oscar64/Debugx64
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -1,8 +1,14 @@
|
|||
rem @echo off
|
||||
|
||||
@call :test rolrortest.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :test bitfields.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :testn autorefreturn.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :testh opp_string.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
|
@ -12,9 +18,15 @@ rem @echo off
|
|||
@call :testh opp_vector.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :testh opp_static_vector.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :testh opp_vector_string.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :testh opp_string_init.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :testh opp_streamtest.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
|
@ -27,6 +39,9 @@ rem @echo off
|
|||
@call :testh opp_list.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :testn opp_functional.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :testh operatoroverload.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
|
@ -42,7 +57,7 @@ rem @echo off
|
|||
@call :testh constructortest.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :testh copyconstructor.cpp
|
||||
@call :testn copyconstructor.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :testh copyassign.cpp
|
||||
|
@ -81,6 +96,9 @@ rem @echo off
|
|||
@call :test fastcalltest.c
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :test strlen.c
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :test strcmptest.c
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
|
@ -105,6 +123,9 @@ rem @echo off
|
|||
@call :test floatmultest.c
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :test floatinttest.c
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :test staticconsttest.c
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
|
@ -144,6 +165,9 @@ rem @echo off
|
|||
@call :test qsorttest.c
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :testn plasma.c
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :test loopdomtest.c
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
|
@ -171,6 +195,12 @@ rem @echo off
|
|||
@call :test divmodtest.c
|
||||
@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
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
|
@ -225,6 +255,9 @@ rem @echo off
|
|||
@call :testn mmultest.c
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@call :test tileexpand.cpp
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
@exit /b 0
|
||||
|
||||
:error
|
||||
|
@ -247,6 +280,15 @@ exit /b %errorlevel%
|
|||
..\bin\oscar64 -e -O2 -n -dHEAPCHECK %~1
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
..\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
|
||||
|
||||
..\bin\oscar64 -e -O0 -bc %~1
|
||||
@if %errorlevel% neq 0 goto :error
|
||||
|
||||
|
@ -304,6 +346,12 @@ exit /b %errorlevel%
|
|||
..\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
|
||||
|
||||
@exit /b 0
|
||||
|
||||
:testb
|
||||
|
@ -343,4 +391,10 @@ exit /b %errorlevel%
|
|||
..\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
|
||||
|
||||
@exit /b 0
|
||||
|
|
|
@ -334,7 +334,6 @@ void test_add_word_cross(void)
|
|||
}
|
||||
int main(void)
|
||||
{
|
||||
|
||||
test_char_fit();
|
||||
test_char_cross();
|
||||
test_word_fit();
|
||||
|
|
|
@ -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(shr32n)
|
||||
|
||||
|
@ -373,24 +385,30 @@ int main(void)
|
|||
shr16n(0xfedc, 0xfedc);
|
||||
|
||||
shl32b(0x00000000UL, 0x00000000L);
|
||||
shl32b(0x00000001UL, 0x00000001L);
|
||||
shl32b(0xffffffffUL, 0xffffffffL);
|
||||
shl32b(0x12345678UL, 0x12345678L);
|
||||
shl32b(0xfedcba98UL, 0xfedcba98L);
|
||||
|
||||
shr32b(0x00000000UL, 0x00000000L);
|
||||
shr32b(0x00000001UL, 0x00000001L);
|
||||
shr32b(0xffffffffUL, 0xffffffffL);
|
||||
shr32b(0x12345678UL, 0x12345678L);
|
||||
shr32b(0xfedcba98UL, 0xfedcba98L);
|
||||
|
||||
shl32n(0x00000000UL, 0x00000000L);
|
||||
shl32n(0x00000001UL, 0x00000001L);
|
||||
shl32n(0xffffffffUL, 0xffffffffL);
|
||||
shl32n(0x12345678UL, 0x12345678L);
|
||||
shl32n(0xfedcba98UL, 0xfedcba98L);
|
||||
|
||||
shr32n(0x00000000UL, 0x00000000L);
|
||||
shr32n(0x00000001UL, 0x00000001L);
|
||||
shr32n(0xffffffffUL, 0xffffffffL);
|
||||
shr32n(0x12345678UL, 0x12345678L);
|
||||
shr32n(0xfedcba98UL, 0xfedcba98L);
|
||||
|
||||
shl1_32n();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int t, n;
|
||||
|
||||
|
@ -161,7 +162,7 @@ void test_return_value(void)
|
|||
C2 c(test_ret_v());
|
||||
}
|
||||
|
||||
assert(n == 4 && t == 0);
|
||||
assert(n == 6 && t == 0);
|
||||
}
|
||||
|
||||
void test_return_reference(void)
|
||||
|
@ -184,7 +185,7 @@ void test_retparam_value(void)
|
|||
test_param_fv(test_ret_v());
|
||||
}
|
||||
|
||||
assert(n == 4 && t == 0);
|
||||
assert(n == 6 && t == 0);
|
||||
}
|
||||
|
||||
void test_retparam_reference(void)
|
||||
|
@ -200,7 +201,6 @@ void test_retparam_reference(void)
|
|||
|
||||
int main(void)
|
||||
{
|
||||
#if 0
|
||||
test_dcopy_init();
|
||||
test_copy_init();
|
||||
test_minit();
|
||||
|
@ -208,9 +208,8 @@ int main(void)
|
|||
test_param_value();
|
||||
test_param_ref();
|
||||
test_return_value();
|
||||
#endif
|
||||
test_retparam_value();
|
||||
// test_retparam_reference();
|
||||
test_retparam_reference();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
CC=../bin/oscar64
|
||||
CXX=$(CC)
|
||||
SRCS=$(filter-out opp_part1.cpp opp_part2.cpp, $(wildcard *.c *.cpp))
|
||||
EXES=$(patsubst %.c,%,$(SRCS))
|
||||
EXES:=$(patsubst %.cpp,%,$(EXES))
|
||||
|
@ -7,44 +5,56 @@ EXES:=$(patsubst %.cpp,%,$(EXES))
|
|||
all: $(EXES)
|
||||
|
||||
%: %.c
|
||||
$(CC) -e -bc $<
|
||||
$(CC) -e -n $<
|
||||
$(CC) -e -O2 -bc $<
|
||||
$(CC) -e -O2 -n $<
|
||||
$(CC) -e -O0 -bc $<
|
||||
$(CC) -e -O0 -n $<
|
||||
$(CC) -e -Os -bc $<
|
||||
$(CC) -e -Os -n $<
|
||||
$(CC) -e -O3 -bc $<
|
||||
$(CC) -e -O3 -n $<
|
||||
$(OSCAR64_CC) -e -bc $<
|
||||
$(OSCAR64_CC) -e -n $<
|
||||
$(OSCAR64_CC) -e -O2 -bc $<
|
||||
$(OSCAR64_CC) -e -O2 -n $<
|
||||
$(OSCAR64_CC) -e -O0 -bc $<
|
||||
$(OSCAR64_CC) -e -O0 -n $<
|
||||
$(OSCAR64_CC) -e -Os -bc $<
|
||||
$(OSCAR64_CC) -e -Os -n $<
|
||||
$(OSCAR64_CC) -e -O3 -bc $<
|
||||
$(OSCAR64_CC) -e -O3 -n $<
|
||||
|
||||
%: %.cpp
|
||||
$(CXX) -e -bc $<
|
||||
$(CXX) -e -n $<
|
||||
$(CXX) -e -O2 -bc $<
|
||||
$(CXX) -e -O2 -n $<
|
||||
$(CXX) -e -O0 -bc $<
|
||||
$(CXX) -e -O0 -n $<
|
||||
$(CXX) -e -Os -bc $<
|
||||
$(CXX) -e -Os -n $<
|
||||
$(CXX) -e -O3 -bc $<
|
||||
$(CXX) -e -O3 -n $<
|
||||
$(OSCAR64_CXX) -e -bc $<
|
||||
$(OSCAR64_CXX) -e -n $<
|
||||
$(OSCAR64_CXX) -e -O2 -bc $<
|
||||
$(OSCAR64_CXX) -e -O2 -n $<
|
||||
$(OSCAR64_CXX) -e -O0 -bc $<
|
||||
$(OSCAR64_CXX) -e -O0 -n $<
|
||||
$(OSCAR64_CXX) -e -Os -bc $<
|
||||
$(OSCAR64_CXX) -e -Os -n $<
|
||||
$(OSCAR64_CXX) -e -O3 -bc $<
|
||||
$(OSCAR64_CXX) -e -O3 -n $<
|
||||
|
||||
# testb
|
||||
bitshifttest: bitshifttest.c
|
||||
$(CC) -e -bc $<
|
||||
$(CC) -e -bc -O2 $<
|
||||
$(CC) -e -bc -O0 $<
|
||||
$(CC) -e -bc -Os $<
|
||||
$(CC) -e -bc -O3 $<
|
||||
$(CC) -e -n $<
|
||||
$(OSCAR64_CC) -e -bc $<
|
||||
$(OSCAR64_CC) -e -bc -O2 $<
|
||||
$(OSCAR64_CC) -e -bc -O0 $<
|
||||
$(OSCAR64_CC) -e -bc -Os $<
|
||||
$(OSCAR64_CC) -e -bc -O3 $<
|
||||
$(OSCAR64_CC) -e -n $<
|
||||
|
||||
# testn
|
||||
stripedarraytest: stripedarraytest.c
|
||||
$(CC) -e -O2 -n $<
|
||||
$(CC) -e -O0 -n $<
|
||||
$(CC) -e -Os -n $<
|
||||
$(CC) -e -O3 -n $<
|
||||
$(OSCAR64_CC) -e -O2 -n $<
|
||||
$(OSCAR64_CC) -e -O0 -n $<
|
||||
$(OSCAR64_CC) -e -Os -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:
|
||||
$(RM) *.asm *.bcs *.int *.lbl *.map *.prg
|
||||
@$(RM) *.asm *.bcs *.int *.lbl *.map *.prg
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -64,5 +64,15 @@ int main(void)
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
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 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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
cmp( 0, 1);
|
||||
|
@ -327,6 +454,10 @@ int main(void)
|
|||
cmp1(256);
|
||||
cmp1(10000);
|
||||
cmp1(20000);
|
||||
cmp1(1000000l);
|
||||
cmp1(2000000l);
|
||||
cmp1(100000000l);
|
||||
cmp1(200000000l);
|
||||
cmp1(-1);
|
||||
cmp1(-2);
|
||||
cmp1(-3);
|
||||
|
@ -334,6 +465,34 @@ int main(void)
|
|||
cmp1(-256);
|
||||
cmp1(-10000);
|
||||
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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -10,12 +10,13 @@ enum SIDFXState
|
|||
SIDFX_WAIT
|
||||
};
|
||||
|
||||
static struct SIDFXChannel
|
||||
__striped static struct SIDFXChannel
|
||||
{
|
||||
const SIDFX * com;
|
||||
byte delay, cnt, priority;
|
||||
volatile SIDFXState state;
|
||||
unsigned freq, pwm;
|
||||
const SIDFX * volatile com;
|
||||
byte delay, priority;
|
||||
volatile byte cnt;
|
||||
volatile SIDFXState state;
|
||||
unsigned freq, pwm;
|
||||
|
||||
} channels[3];
|
||||
|
||||
|
@ -26,9 +27,20 @@ void sidfx_init(void)
|
|||
channels[i].com = nullptr;
|
||||
channels[i].state = SIDFX_IDLE;
|
||||
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)
|
||||
{
|
||||
SIDFXState ns = channels[chn].state;
|
||||
|
@ -41,6 +53,7 @@ void sidfx_play(byte chn, const SIDFX * fx, byte cnt)
|
|||
return;
|
||||
|
||||
channels[chn].state = SIDFX_IDLE;
|
||||
channels[chn].delay = 1;
|
||||
|
||||
channels[chn].com = fx;
|
||||
channels[chn].cnt = cnt - 1;
|
||||
|
@ -53,103 +66,126 @@ void sidfx_stop(byte chn)
|
|||
{
|
||||
channels[chn].com = nullptr;
|
||||
if (channels[chn].state != SIDFX_IDLE)
|
||||
{
|
||||
channels[chn].state = SIDFX_RESET_0;
|
||||
channels[chn].delay = 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline void sidfx_loop_ch(byte ch)
|
||||
{
|
||||
switch (channels[ch].state)
|
||||
if (channels[ch].state)
|
||||
{
|
||||
case SIDFX_IDLE:
|
||||
break;
|
||||
case SIDFX_RESET_0:
|
||||
sid.voices[ch].ctrl = 0;
|
||||
sid.voices[ch].attdec = 0;
|
||||
sid.voices[ch].susrel = 0;
|
||||
channels[ch].state = SIDFX_RESET_1;
|
||||
break;
|
||||
case SIDFX_RESET_1:
|
||||
sid.voices[ch].ctrl = SID_CTRL_TEST;
|
||||
channels[ch].state = SIDFX_READY;
|
||||
break;
|
||||
case SIDFX_READY:
|
||||
if (channels[ch].com)
|
||||
{
|
||||
channels[ch].freq = channels[ch].com->freq;
|
||||
channels[ch].pwm = channels[ch].com->pwm;
|
||||
const SIDFX * com = channels[ch].com;
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
channels[ch].state = SIDFX_IDLE;
|
||||
break;
|
||||
case SIDFX_PLAY:
|
||||
if (channels[ch].com->dfreq)
|
||||
channels[ch].delay--;
|
||||
if (channels[ch].delay)
|
||||
{
|
||||
if (com->dfreq)
|
||||
{
|
||||
channels[ch].freq += channels[ch].com->dfreq;
|
||||
channels[ch].freq += com->dfreq;
|
||||
sid.voices[ch].freq = channels[ch].freq;
|
||||
}
|
||||
if (channels[ch].com->dpwm)
|
||||
if (com->dpwm)
|
||||
{
|
||||
channels[ch].pwm += channels[ch].com->dpwm;
|
||||
channels[ch].pwm += com->dpwm;
|
||||
sid.voices[ch].pwm = channels[ch].pwm;
|
||||
}
|
||||
}
|
||||
|
||||
if (channels[ch].delay)
|
||||
channels[ch].delay--;
|
||||
else if (channels[ch].com->time0)
|
||||
while (!channels[ch].delay)
|
||||
{
|
||||
switch (channels[ch].state)
|
||||
{
|
||||
sid.voices[ch].ctrl = channels[ch].com->ctrl & ~SID_CTRL_GATE;
|
||||
channels[ch].delay = channels[ch].com->time0;
|
||||
channels[ch].state = SIDFX_WAIT;
|
||||
}
|
||||
else if (channels[ch].cnt)
|
||||
{
|
||||
channels[ch].cnt--;
|
||||
channels[ch].com++;
|
||||
channels[ch].priority = channels[ch].com->priority;
|
||||
case SIDFX_IDLE:
|
||||
channels[ch].delay = 1;
|
||||
break;
|
||||
case SIDFX_RESET_0:
|
||||
sid.voices[ch].ctrl = 0;
|
||||
sid.voices[ch].attdec = 0;
|
||||
sid.voices[ch].susrel = 0;
|
||||
if (com)
|
||||
channels[ch].state = SIDFX_READY;
|
||||
else
|
||||
channels[ch].state = SIDFX_IDLE;
|
||||
channels[ch].delay = 1;
|
||||
break;
|
||||
case SIDFX_RESET_1:
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
channels[ch].com = nullptr;
|
||||
channels[ch].state = SIDFX_RESET_0;
|
||||
}
|
||||
break;
|
||||
case SIDFX_WAIT:
|
||||
if (channels[ch].com->dfreq)
|
||||
{
|
||||
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;
|
||||
}
|
||||
break;
|
||||
case SIDFX_READY:
|
||||
channels[ch].freq = com->freq;
|
||||
channels[ch].pwm = com->pwm;
|
||||
|
||||
if (channels[ch].delay)
|
||||
channels[ch].delay--;
|
||||
else if (channels[ch].cnt)
|
||||
{
|
||||
channels[ch].cnt--;
|
||||
channels[ch].com++;
|
||||
channels[ch].priority = channels[ch].com->priority;
|
||||
channels[ch].state = SIDFX_RESET_0;
|
||||
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].delay = com->time1;
|
||||
channels[ch].state = SIDFX_PLAY;
|
||||
}
|
||||
else
|
||||
{
|
||||
channels[ch].delay = com->time0;
|
||||
channels[ch].state = SIDFX_PLAY;
|
||||
}
|
||||
break;
|
||||
case SIDFX_PLAY:
|
||||
if (com->time0)
|
||||
{
|
||||
sid.voices[ch].ctrl = com->ctrl & ~SID_CTRL_GATE;
|
||||
channels[ch].delay = com->time0 - 1;
|
||||
channels[ch].state = SIDFX_WAIT;
|
||||
}
|
||||
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].com = com;
|
||||
channels[ch].priority = com->priority;
|
||||
channels[ch].state = SIDFX_READY;
|
||||
}
|
||||
else
|
||||
{
|
||||
com = nullptr;
|
||||
channels[ch].state = SIDFX_RESET_0;
|
||||
}
|
||||
break;
|
||||
case SIDFX_WAIT:
|
||||
if (channels[ch].cnt)
|
||||
{
|
||||
com++;
|
||||
channels[ch].cnt--;
|
||||
channels[ch].com = com;
|
||||
channels[ch].priority = com->priority;
|
||||
if (com->ctrl & SID_CTRL_GATE)
|
||||
channels[ch].state = SIDFX_RESET_0;
|
||||
else
|
||||
channels[ch].state = SIDFX_READY;
|
||||
}
|
||||
else
|
||||
{
|
||||
com = nullptr;
|
||||
channels[ch].state = SIDFX_RESET_0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
channels[ch].com = nullptr;
|
||||
channels[ch].state = SIDFX_RESET_0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,14 @@ struct SIDFX
|
|||
|
||||
void sidfx_init(void);
|
||||
|
||||
inline bool sidfx_idle(byte chn);
|
||||
|
||||
inline void sidfx_play(byte chn, const SIDFX * fx, byte cnt);
|
||||
|
||||
void sidfx_stop(byte chn);
|
||||
|
||||
char sidfx_cnt(byte chn);
|
||||
|
||||
void sidfx_loop(void);
|
||||
|
||||
void sidfx_loop_2(void);
|
||||
|
|
|
@ -27,6 +27,7 @@ struct XMMU
|
|||
|
||||
#define xmmu (*((struct XMMU *)0xd500))
|
||||
|
||||
inline char mmu_set(char cr);
|
||||
|
||||
#pragma compile("mmu.c")
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ void cia_init(void)
|
|||
cia2.ddrb = 0x00;
|
||||
cia1.ddra = 0xff;
|
||||
|
||||
cia2.prb = 0x07;
|
||||
cia2.pra = 0x07;
|
||||
cia2.ddra = 0x3f;
|
||||
|
||||
char i0 = cia1.icr;
|
||||
|
|
|
@ -18,6 +18,46 @@ struct EasyFlash
|
|||
|
||||
#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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -2,7 +2,8 @@
|
|||
#include <c64/cia.h>
|
||||
#include <c64/vic.h>
|
||||
|
||||
IEC_STATUS iec_status;
|
||||
IEC_STATUS iec_status;
|
||||
char iec_queue;
|
||||
|
||||
#define CIA2B_ATNOUT 0x08
|
||||
#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;
|
||||
}
|
||||
|
||||
static inline void data_high(void)
|
||||
static inline void data_false(void)
|
||||
{
|
||||
cia2.pra |= CIA2B_DATAOUT;
|
||||
}
|
||||
|
||||
static inline void clock_low(void)
|
||||
static inline void clock_true(void)
|
||||
{
|
||||
cia2.pra &= ~CIA2B_CLKOUT;
|
||||
}
|
||||
|
||||
static inline void cdata_low(void)
|
||||
static inline void cdata_true(void)
|
||||
{
|
||||
cia2.pra &= ~(CIA2B_CLKOUT | CIA2B_DATAOUT);
|
||||
}
|
||||
|
||||
static inline void clock_high(void)
|
||||
static inline void clock_false(void)
|
||||
{
|
||||
cia2.pra |= CIA2B_CLKOUT;
|
||||
}
|
||||
|
||||
static inline void atn_low(void)
|
||||
static inline void atn_true(void)
|
||||
{
|
||||
cia2.pra &= ~CIA2B_ATNOUT;
|
||||
}
|
||||
|
||||
static inline void atn_high(void)
|
||||
static inline void atn_false(void)
|
||||
{
|
||||
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)
|
||||
{
|
||||
char cnt = 100;
|
||||
while (cnt > 0 && (cia2.pra & CIA2B_DATAIN))
|
||||
char cnt = 200;
|
||||
while (cnt > 0 && data_in())
|
||||
{
|
||||
delay(5);
|
||||
cnt--;
|
||||
}
|
||||
|
||||
if (cnt)
|
||||
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);
|
||||
|
||||
return data_check();
|
||||
}
|
||||
|
||||
bool iec_write(char b)
|
||||
static void iec_writeb(char b)
|
||||
{
|
||||
cdata_low();
|
||||
clock_true();
|
||||
|
||||
while (!(cia2.pra & CIA2B_DATAIN))
|
||||
;
|
||||
|
||||
clock_high();
|
||||
while (!data_in());
|
||||
|
||||
delay(5);
|
||||
for(char i=0; i<8; i++)
|
||||
{
|
||||
if (b & 1)
|
||||
data_low();
|
||||
else
|
||||
data_high();
|
||||
clock_false();
|
||||
delay(5);
|
||||
clock_low();
|
||||
if (b & 1)
|
||||
data_true();
|
||||
else
|
||||
data_false();
|
||||
clock_true();
|
||||
b >>= 1;
|
||||
delay(5);
|
||||
clock_high();
|
||||
data_low();
|
||||
}
|
||||
clock_false();
|
||||
data_true();
|
||||
}
|
||||
|
||||
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 data_check();
|
||||
return false;
|
||||
}
|
||||
|
||||
char iec_read(void)
|
||||
{
|
||||
while (!(cia2.pra & CIA2B_CLKIN))
|
||||
;
|
||||
while (!clock_in());
|
||||
|
||||
data_low();
|
||||
__asm
|
||||
{
|
||||
php
|
||||
sei
|
||||
}
|
||||
|
||||
data_true();
|
||||
|
||||
char cnt = 100;
|
||||
while (cnt > 0 && (cia2.pra & CIA2B_CLKIN))
|
||||
while (cnt > 0 && clock_in())
|
||||
cnt--;
|
||||
|
||||
if (cnt == 0)
|
||||
{
|
||||
iec_status = IEC_EOF;
|
||||
data_high();
|
||||
delay(4);
|
||||
data_low();
|
||||
data_false();
|
||||
delay(10);
|
||||
data_true();
|
||||
|
||||
cnt = 200;
|
||||
while (cnt > 0 && (cia2.pra & CIA2B_CLKIN))
|
||||
while (cnt > 0 && clock_in())
|
||||
cnt--;
|
||||
|
||||
if (cnt == 0)
|
||||
{
|
||||
iec_status = IEC_TIMEOUT;
|
||||
|
||||
__asm
|
||||
{
|
||||
plp
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -155,25 +207,36 @@ char iec_read(void)
|
|||
;
|
||||
}
|
||||
|
||||
data_high();
|
||||
data_false();
|
||||
|
||||
__asm
|
||||
{
|
||||
plp
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
void iec_atn(char dev, char sec)
|
||||
{
|
||||
cdata_low();
|
||||
atn_high();
|
||||
clock_high();
|
||||
{
|
||||
clock_true();
|
||||
data_true();
|
||||
atn_false();
|
||||
clock_false();
|
||||
|
||||
delay(200);
|
||||
|
||||
iec_write(dev);
|
||||
if (sec != 0xff)
|
||||
iec_write(sec);
|
||||
while (data_in());
|
||||
|
||||
data_high();
|
||||
atn_low();
|
||||
iec_writeb(dev);
|
||||
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_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);
|
||||
}
|
||||
|
@ -201,7 +280,27 @@ void iec_listen(char dev, char sec)
|
|||
|
||||
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);
|
||||
clock_true();
|
||||
|
||||
__asm
|
||||
{
|
||||
plp
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
while (fname[i])
|
||||
{
|
||||
if (!fname[i + 1])
|
||||
iec_eoi();
|
||||
iec_write(fname[i]);
|
||||
i++;
|
||||
}
|
||||
|
@ -239,7 +336,7 @@ int iec_write_bytes(const char * data, int num)
|
|||
|
||||
int iec_read_bytes(char * data, int num)
|
||||
{
|
||||
char i = 0;
|
||||
int i = 0;
|
||||
while (i < num)
|
||||
{
|
||||
char ch = iec_read();
|
||||
|
|
|
@ -5,6 +5,7 @@ enum IEC_STATUS
|
|||
{
|
||||
IEC_OK = 0x00,
|
||||
IEC_EOF = 0x01,
|
||||
IEC_QUEUED = 0x02,
|
||||
|
||||
IEC_ERROR = 0x80,
|
||||
IEC_TIMEOUT,
|
||||
|
@ -13,8 +14,6 @@ enum IEC_STATUS
|
|||
|
||||
extern IEC_STATUS iec_status;
|
||||
|
||||
bool iec_eoi(void);
|
||||
|
||||
bool iec_write(char b);
|
||||
|
||||
char iec_read(void);
|
||||
|
|
|
@ -16,7 +16,18 @@ void krnio_setbnk(char filebank, char namebank)
|
|||
#pragma native(krnio_setbnk)
|
||||
#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
|
||||
{
|
||||
|
@ -31,35 +42,41 @@ void krnio_setnam(const char * name)
|
|||
tya
|
||||
W1: ldx name
|
||||
ldy name + 1
|
||||
BANKIN
|
||||
jsr $ffbd // setnam
|
||||
BANKOUT
|
||||
}
|
||||
}
|
||||
|
||||
#pragma native(krnio_setnam)
|
||||
|
||||
void krnio_setnam_n(const char * name, char len)
|
||||
BANKINLINE void krnio_setnam_n(const char * name, char len)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
lda len
|
||||
ldx name
|
||||
ldy name + 1
|
||||
BANKIN
|
||||
jsr $ffbd // setnam
|
||||
BANKOUT
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
|
||||
__asm
|
||||
return char(__asm
|
||||
{
|
||||
lda #0
|
||||
sta accu
|
||||
sta accu + 1
|
||||
|
||||
BANKIN
|
||||
|
||||
lda fnum
|
||||
ldx device
|
||||
ldy channel
|
||||
|
@ -74,42 +91,48 @@ bool krnio_open(char fnum, char device, char channel)
|
|||
W1:
|
||||
lda #1
|
||||
sta accu
|
||||
E2:
|
||||
}
|
||||
|
||||
BANKOUT
|
||||
E2:
|
||||
});
|
||||
}
|
||||
|
||||
#pragma native(krnio_open)
|
||||
|
||||
void krnio_close(char fnum)
|
||||
BANKINLINE void krnio_close(char fnum)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
BANKIN
|
||||
lda fnum
|
||||
jsr $ffc3 // close
|
||||
BANKOUT
|
||||
}
|
||||
}
|
||||
|
||||
#pragma native(krnio_close)
|
||||
|
||||
krnioerr krnio_status(void)
|
||||
BANKINLINE krnioerr krnio_status(void)
|
||||
{
|
||||
__asm
|
||||
return __asm
|
||||
{
|
||||
BANKIN
|
||||
jsr $ffb7 // readst
|
||||
BANKOUT
|
||||
sta accu
|
||||
lda #0
|
||||
sta accu + 1
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#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
|
||||
ldx device
|
||||
ldy channel
|
||||
|
@ -119,20 +142,22 @@ bool krnio_load(char fnum, char device, char channel)
|
|||
ldx #0
|
||||
ldy #0
|
||||
jsr $FFD5 // load
|
||||
BANKOUT
|
||||
|
||||
lda #0
|
||||
bcs W1
|
||||
lda #1
|
||||
W1: sta accu
|
||||
}
|
||||
rol
|
||||
eor #1
|
||||
sta accu
|
||||
});
|
||||
}
|
||||
|
||||
#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
|
||||
ldx device
|
||||
ldy #0
|
||||
|
@ -143,83 +168,96 @@ bool krnio_save(char device, const char* start, const char* end)
|
|||
ldy end+1
|
||||
jsr $FFD8 // save
|
||||
|
||||
BANKOUT
|
||||
|
||||
lda #0
|
||||
bcs W1
|
||||
lda #1
|
||||
W1: sta accu
|
||||
}
|
||||
rol
|
||||
eor #1
|
||||
sta accu
|
||||
});
|
||||
}
|
||||
|
||||
#pragma native(krnio_save)
|
||||
|
||||
bool krnio_chkout(char fnum)
|
||||
BANKINLINE bool krnio_chkout(char fnum)
|
||||
{
|
||||
__asm
|
||||
return char(__asm
|
||||
{
|
||||
BANKIN
|
||||
ldx fnum
|
||||
jsr $ffc9 // chkout
|
||||
BANKOUT
|
||||
|
||||
lda #0
|
||||
bcs W1
|
||||
lda #1
|
||||
W1: sta accu
|
||||
}
|
||||
rol
|
||||
eor #1
|
||||
sta accu
|
||||
});
|
||||
}
|
||||
|
||||
#pragma native(krnio_chkout)
|
||||
|
||||
bool krnio_chkin(char fnum)
|
||||
BANKINLINE bool krnio_chkin(char fnum)
|
||||
{
|
||||
__asm
|
||||
return char(__asm
|
||||
{
|
||||
BANKIN
|
||||
ldx fnum
|
||||
jsr $ffc6 // chkin
|
||||
BANKOUT
|
||||
|
||||
lda #0
|
||||
sta accu + 1
|
||||
bcs W1
|
||||
lda #1
|
||||
W1: sta accu
|
||||
}
|
||||
rol
|
||||
eor #1
|
||||
sta accu
|
||||
});
|
||||
}
|
||||
|
||||
#pragma native(krnio_chkin)
|
||||
|
||||
void krnio_clrchn(void)
|
||||
BANKINLINE void krnio_clrchn(void)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
BANKIN
|
||||
jsr $ffcc // clrchn
|
||||
BANKOUT
|
||||
}
|
||||
}
|
||||
|
||||
#pragma native(krnio_clrchn)
|
||||
|
||||
bool krnio_chrout(char ch)
|
||||
BANKINLINE bool krnio_chrout(char ch)
|
||||
{
|
||||
__asm
|
||||
return char(__asm
|
||||
{
|
||||
BANKIN
|
||||
lda ch
|
||||
jsr $ffd2 // chrout
|
||||
sta accu
|
||||
lda #0
|
||||
sta accu + 1
|
||||
}
|
||||
BANKOUT
|
||||
});
|
||||
}
|
||||
|
||||
#pragma native(krnio_chrout)
|
||||
|
||||
int krnio_chrin(void)
|
||||
BANKINLINE char krnio_chrin(void)
|
||||
{
|
||||
__asm
|
||||
return __asm
|
||||
{
|
||||
BANKIN
|
||||
jsr $ffcf // chrin
|
||||
sta accu
|
||||
lda #0
|
||||
sta accu + 1
|
||||
}
|
||||
BANKOUT
|
||||
};
|
||||
}
|
||||
|
||||
#pragma native(krnio_chrin)
|
||||
|
||||
#if defined(__PLUS4__)
|
||||
#pragma code(code)
|
||||
#endif
|
||||
|
||||
int krnio_getch(char fnum)
|
||||
{
|
||||
if (krnio_pstatus[fnum] == KRNIO_EOF)
|
||||
|
@ -383,7 +421,7 @@ int krnio_gets(char fnum, char * data, int num)
|
|||
|
||||
if (krnio_chkin(fnum))
|
||||
{
|
||||
krnioerr err;
|
||||
krnioerr err = KRNIO_OK;
|
||||
int i = 0;
|
||||
int ch;
|
||||
while (i + 1 < num)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef C64_KERNALIO_H
|
||||
#ifndef C64_KERNALIO_H
|
||||
#define C64_KERNALIO_H
|
||||
|
||||
// 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
|
||||
|
||||
int krnio_chrin(void);
|
||||
char krnio_chrin(void);
|
||||
|
||||
// read a single byte from the given file/channel, returns
|
||||
// a negative result on failure. If this was the last byte
|
||||
|
|
|
@ -5,16 +5,16 @@
|
|||
#include <c64/asm6502.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
volatile char npos = 1, tpos = 0;
|
||||
volatile byte rirq_count;
|
||||
static byte rirq_pcount;
|
||||
|
||||
byte rasterIRQRows[NUM_IRQS + 1];
|
||||
byte rasterIRQIndex[NUM_IRQS + 1];
|
||||
byte rasterIRQRows[NUM_IRQS + 1];
|
||||
byte rasterIRQIndex[NUM_IRQS + 1]; // Sort order of interrupt index, offset by one
|
||||
#ifdef ZPAGE_IRQS
|
||||
__zeropage
|
||||
#endif
|
||||
byte rasterIRQNext[NUM_IRQS + 1];
|
||||
byte rasterIRQLow[NUM_IRQS];
|
||||
byte rasterIRQNext[NUM_IRQS + 1]; // Rasterline of interrupt, terminated by 0xff
|
||||
byte rasterIRQLow[NUM_IRQS]; // Address of interrupt code
|
||||
byte rasterIRQHigh[NUM_IRQS];
|
||||
|
||||
#ifdef ZPAGE_IRQS
|
||||
|
@ -22,28 +22,25 @@ __zeropage
|
|||
#endif
|
||||
byte nextIRQ;
|
||||
|
||||
__asm irq0
|
||||
{
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
tya
|
||||
pha
|
||||
// nextIRQ is the index of the next expected IRQ, or $ff if no IRQ is scheduled
|
||||
|
||||
asl $d019
|
||||
__asm rirq_isr_ram_io
|
||||
{
|
||||
stx plrx + 1
|
||||
|
||||
ldx nextIRQ
|
||||
l1:
|
||||
lda rasterIRQNext, x
|
||||
cmp #$ff
|
||||
beq e1
|
||||
bmi exi
|
||||
|
||||
sta plra + 1
|
||||
sty plry + 1
|
||||
|
||||
l1:
|
||||
lda rasterIRQNext, x
|
||||
ldy rasterIRQIndex + 1, x
|
||||
tax
|
||||
lda rasterIRQLow, y
|
||||
sta ji + 1
|
||||
lda rasterIRQHigh, y
|
||||
sta ji + 2
|
||||
ldx rasterIRQLow, y
|
||||
stx ji + 1
|
||||
ldx rasterIRQHigh, y
|
||||
stx ji + 2
|
||||
|
||||
ji:
|
||||
jsr $0000
|
||||
|
@ -51,20 +48,82 @@ ji:
|
|||
inc nextIRQ
|
||||
ldx nextIRQ
|
||||
|
||||
lda rasterIRQNext, x
|
||||
cmp #$ff
|
||||
ldy rasterIRQNext, x
|
||||
|
||||
asl $d019
|
||||
|
||||
cpy #$ff
|
||||
beq e2
|
||||
// carry is cleared at this point
|
||||
|
||||
tay
|
||||
dey
|
||||
sbc #2
|
||||
cmp $d012
|
||||
bcc l1
|
||||
|
||||
sty $d012
|
||||
dey
|
||||
cpy $d012
|
||||
bcc l1
|
||||
|
||||
ex:
|
||||
plry:
|
||||
ldy #0
|
||||
plra:
|
||||
lda #0
|
||||
plrx:
|
||||
ldx #0
|
||||
rti
|
||||
|
||||
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
|
||||
tay
|
||||
pla
|
||||
|
@ -72,56 +131,44 @@ ex:
|
|||
pla
|
||||
rti
|
||||
|
||||
e2:
|
||||
exi:
|
||||
asl $d019
|
||||
jmp exd
|
||||
|
||||
ldx npos
|
||||
stx tpos
|
||||
e2:
|
||||
inc rirq_count
|
||||
|
||||
bit $d011
|
||||
bmi e1
|
||||
|
||||
sta $d012
|
||||
jmp ex
|
||||
|
||||
e1:
|
||||
ldx #0
|
||||
stx nextIRQ
|
||||
ldy rasterIRQNext
|
||||
dey
|
||||
sty $d012
|
||||
jmp ex
|
||||
|
||||
ldx #0
|
||||
stx nextIRQ
|
||||
beq exd
|
||||
}
|
||||
|
||||
__asm irq2
|
||||
__asm rirq_isr_noio
|
||||
{
|
||||
pha
|
||||
txa
|
||||
pha
|
||||
tya
|
||||
pha
|
||||
|
||||
kentry:
|
||||
lda $01
|
||||
pha
|
||||
|
||||
lda #$35
|
||||
sta $01
|
||||
|
||||
asl $d019
|
||||
|
||||
ldx nextIRQ
|
||||
bmi exi
|
||||
l1:
|
||||
lda rasterIRQNext, x
|
||||
cmp #$ff
|
||||
beq e1
|
||||
|
||||
ldy rasterIRQIndex + 1, x
|
||||
tax
|
||||
lda rasterIRQLow, y
|
||||
sta ji + 1
|
||||
lda rasterIRQHigh, y
|
||||
sta ji + 2
|
||||
ldx rasterIRQLow, y
|
||||
stx ji + 1
|
||||
ldx rasterIRQHigh, y
|
||||
stx ji + 2
|
||||
|
||||
ji:
|
||||
jsr $0000
|
||||
|
@ -129,21 +176,20 @@ ji:
|
|||
inc nextIRQ
|
||||
ldx nextIRQ
|
||||
|
||||
lda rasterIRQNext, x
|
||||
cmp #$ff
|
||||
ldy rasterIRQNext, x
|
||||
|
||||
asl $d019
|
||||
|
||||
cpy #$ff
|
||||
beq e2
|
||||
// carry is cleared at this point
|
||||
|
||||
tay
|
||||
dey
|
||||
sbc #2
|
||||
cmp $d012
|
||||
bcc l1
|
||||
|
||||
sty $d012
|
||||
dey
|
||||
cpy $d012
|
||||
bcc l1
|
||||
|
||||
ex:
|
||||
|
||||
exd:
|
||||
pla
|
||||
sta $01
|
||||
|
||||
|
@ -154,45 +200,35 @@ ex:
|
|||
pla
|
||||
rti
|
||||
|
||||
e2:
|
||||
exi:
|
||||
asl $d019
|
||||
jmp exd
|
||||
|
||||
ldx npos
|
||||
stx tpos
|
||||
e2:
|
||||
inc rirq_count
|
||||
|
||||
bit $d011
|
||||
bmi e1
|
||||
|
||||
sta $d012
|
||||
jmp ex
|
||||
|
||||
e1:
|
||||
ldx #0
|
||||
stx nextIRQ
|
||||
ldy rasterIRQNext
|
||||
dey
|
||||
sty $d012
|
||||
jmp ex
|
||||
|
||||
ldx #0
|
||||
stx nextIRQ
|
||||
beq exd
|
||||
}
|
||||
|
||||
__asm irq1
|
||||
__asm rirq_isr_kernal_io
|
||||
{
|
||||
lda $d019
|
||||
bpl ex2
|
||||
|
||||
ldx nextIRQ
|
||||
bmi exi
|
||||
l1:
|
||||
lda rasterIRQNext, x
|
||||
cmp #$ff
|
||||
beq e1
|
||||
|
||||
ldy rasterIRQIndex + 1, x
|
||||
tax
|
||||
lda rasterIRQLow, y
|
||||
sta ji + 1
|
||||
lda rasterIRQHigh, y
|
||||
sta ji + 2
|
||||
ldx rasterIRQLow, y
|
||||
stx ji + 1
|
||||
ldx rasterIRQHigh, y
|
||||
stx ji + 2
|
||||
|
||||
ji:
|
||||
jsr $0000
|
||||
|
@ -201,45 +237,36 @@ jx:
|
|||
inc nextIRQ
|
||||
ldx nextIRQ
|
||||
|
||||
lda rasterIRQNext, x
|
||||
cmp #$ff
|
||||
beq e2
|
||||
ldy rasterIRQNext, x
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
ex2:
|
||||
|
@ -248,6 +275,76 @@ ex2:
|
|||
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
|
||||
// 2 ldy #data1
|
||||
// 4 cpx $d012
|
||||
|
@ -268,8 +365,8 @@ void rirq_build(RIRQCode * ic, byte size)
|
|||
ic->size = size;
|
||||
|
||||
asm_im(ic->code + 0, ASM_LDY, 0);
|
||||
asm_im(ic->code + 2, ASM_LDA, 0);
|
||||
asm_ab(ic->code + 4, ASM_CPX, 0xd012);
|
||||
asm_im(ic->code + 2, ASM_LDX, 0);
|
||||
asm_ab(ic->code + 4, ASM_CMP, 0xd012);
|
||||
asm_rl(ic->code + 7, ASM_BCS, -5);
|
||||
asm_ab(ic->code + 9, ASM_STY, 0x0000);
|
||||
|
||||
|
@ -283,7 +380,7 @@ void rirq_build(RIRQCode * ic, byte size)
|
|||
}
|
||||
else
|
||||
{
|
||||
asm_ab(ic->code + 12, ASM_STA, 0x0000);
|
||||
asm_ab(ic->code + 12, ASM_STX, 0x0000);
|
||||
|
||||
byte p = 15;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
@ -402,7 +500,60 @@ void rirq_init_kernal(void)
|
|||
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.ctrl1 &= 0x7f;
|
||||
|
@ -419,7 +570,7 @@ void rirq_init_io(void)
|
|||
sei
|
||||
}
|
||||
|
||||
*(void **)0xfffe = irq0;
|
||||
*(void **)0xfffe = rirq_isr_ram_io;
|
||||
|
||||
vic.intr_enable = 1;
|
||||
vic.ctrl1 &= 0x7f;
|
||||
|
@ -436,7 +587,7 @@ void rirq_init_memmap(void)
|
|||
sei
|
||||
}
|
||||
|
||||
*(void **)0xfffe = irq2;
|
||||
*(void **)0xfffe = rirq_isr_noio;
|
||||
|
||||
vic.intr_enable = 1;
|
||||
vic.ctrl1 &= 0x7f;
|
||||
|
@ -454,12 +605,18 @@ void rirq_init(bool kernalIRQ)
|
|||
|
||||
void rirq_wait(void)
|
||||
{
|
||||
while (tpos != npos) ;
|
||||
npos++;
|
||||
char i0 = rirq_pcount;
|
||||
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
|
||||
byte maxr = rasterIRQRows[rasterIRQIndex[1]];
|
||||
for(byte i = 2; i<NUM_IRQS + 1; i++)
|
||||
|
@ -494,13 +651,31 @@ void rirq_sort(void)
|
|||
rasterIRQIndex[j] = ri;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NUM_IRQS & 3
|
||||
for(sbyte i=NUM_IRQS-1; i>=0; i--)
|
||||
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++;
|
||||
byte yp = rasterIRQNext[nextIRQ];
|
||||
if (yp != 0xff)
|
||||
vic.raster = yp - 1;
|
||||
rirq_pcount = rirq_count;
|
||||
if (inirq)
|
||||
nextIRQ = NUM_IRQS - 1;
|
||||
else
|
||||
{
|
||||
byte yp = rasterIRQNext[0];
|
||||
if (yp != 0xff)
|
||||
{
|
||||
vic.raster = yp - 1;
|
||||
nextIRQ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rirq_start(void)
|
||||
|
@ -514,6 +689,7 @@ void rirq_start(void)
|
|||
lda #100
|
||||
sta $d012
|
||||
|
||||
asl $d019
|
||||
cli
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,8 @@ inline void rirq_data(RIRQCode * ic, byte n, byte data);
|
|||
// Add a delay of 5 * cycles to a raster IRQ
|
||||
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);
|
||||
|
||||
// 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)
|
||||
inline void rirq_init(bool kernalIRQ);
|
||||
|
||||
// Raster IRQ through kernal, with IO range always enabled
|
||||
// calls kernal continuation
|
||||
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);
|
||||
|
||||
// Raster IRQ through RAM vector, with ROM disabled and IO range not always enabled
|
||||
// does not call kernal continuation
|
||||
void rirq_init_memmap(void);
|
||||
|
||||
// Start raster IRQ
|
||||
|
@ -160,8 +179,9 @@ void rirq_start(void);
|
|||
void rirq_stop(void);
|
||||
|
||||
// Sort the raster IRQ, must be performed at the end of the frame after changing
|
||||
// the vertical position of one of the interrupt operatins.
|
||||
void rirq_sort(void);
|
||||
// the vertical position of one of the interrupt operations.
|
||||
// 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
|
||||
// sort if the raster IRQ system is active
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
static volatile char * vspriteScreen;
|
||||
|
||||
#ifdef VSPRITE_BSS
|
||||
#pragma bss(VSPRITE_BSS)
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
vspriteScreen = screen + 0x3f8;
|
||||
|
@ -205,6 +214,21 @@ void vspr_move(char sp, int xpos, int ypos)
|
|||
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)
|
||||
{
|
||||
vspriteImage[sp] = image;
|
||||
|
@ -255,7 +279,7 @@ void vspr_update(void)
|
|||
{
|
||||
char xymask = 0;
|
||||
volatile char * vsprs = vspriteScreen;
|
||||
char sypos[VSPRITES_MAX];
|
||||
// char sypos[VSPRITES_MAX];
|
||||
|
||||
#pragma unroll(full)
|
||||
|
||||
|
@ -276,9 +300,9 @@ void vspr_update(void)
|
|||
xymask = ((unsigned)xymask | (vspriteXHigh[ri] << 8)) >> 1;
|
||||
#endif
|
||||
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;
|
||||
|
@ -288,9 +312,11 @@ void vspr_update(void)
|
|||
|
||||
for(char ti=0; ti<VSPRITES_MAX - 8; ti++)
|
||||
{
|
||||
byte ri = spriteOrder[ti + 8];
|
||||
if (!done && vspriteYLow[ri] < 250)
|
||||
if (!done && spriteYPos[ti + 9] < 250)
|
||||
{
|
||||
byte ri = spriteOrder[ti + 8];
|
||||
rirq_move(ti, spriteYPos[ti + 1] + 23);
|
||||
|
||||
#ifdef VSPRITE_REVERSE
|
||||
char m = 0x80 >> (ti & 7);
|
||||
#else
|
||||
|
@ -301,14 +327,13 @@ void vspr_update(void)
|
|||
if (!(vspriteXHigh[ri] & 1))
|
||||
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, 1, vspriteXLow[ri]);
|
||||
rirq_data(spirq + ti, 3, vspriteImage[ri]);
|
||||
|
||||
rirq_data(spirq + ti, 4, xymask);
|
||||
rirq_move(ti, sypos[ti] + 23);
|
||||
sypos[ti + 8] = vspriteYLow[ri];
|
||||
// spriteYPos[ti + 9] = vspriteYLow[ri];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -68,6 +68,8 @@ inline void spr_expand(char sp, bool xexpand, bool yexpand);
|
|||
|
||||
void vspr_init(char * screen);
|
||||
|
||||
void vspr_shutdown(void);
|
||||
|
||||
void vspr_screen(char * screen);
|
||||
|
||||
// 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_movex(char sp, int xpos);
|
||||
|
||||
inline void vspr_movey(char sp, int ypos);
|
||||
|
||||
|
||||
// change the image of a virtual sprite
|
||||
|
||||
inline void vspr_image(char sp, char image);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -118,6 +118,9 @@ void vic_waitLine(int line);
|
|||
// wait for beam to be below a 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
|
||||
#define vic (*((struct VIC *)0xd000))
|
||||
|
||||
|
|
329
include/conio.c
329
include/conio.c
|
@ -18,6 +18,13 @@ __asm bsin
|
|||
jsr 0xffe4
|
||||
sta 0xff01
|
||||
}
|
||||
__asm bsget
|
||||
{
|
||||
lda #0
|
||||
sta 0xff00
|
||||
jsr 0xffcf
|
||||
sta 0xff01
|
||||
}
|
||||
__asm bsplot
|
||||
{
|
||||
lda #0
|
||||
|
@ -43,6 +50,7 @@ __asm dswap
|
|||
#define dswap 0xff5f
|
||||
#define bsout 0xffd2
|
||||
#define bsin 0xffe4
|
||||
#define bsget 0xffcf
|
||||
#define bsplot 0xfff0
|
||||
#define bsinit 0xff81
|
||||
#elif defined(__PLUS4__)
|
||||
|
@ -59,6 +67,12 @@ __asm bsin
|
|||
jsr 0xffe4
|
||||
sta 0xff3f
|
||||
}
|
||||
__asm bsget
|
||||
{
|
||||
sta 0xff3e
|
||||
jsr 0xffcf
|
||||
sta 0xff3f
|
||||
}
|
||||
__asm bsplot
|
||||
{
|
||||
sta 0xff3e
|
||||
|
@ -91,6 +105,14 @@ __asm bsin
|
|||
pha
|
||||
}
|
||||
|
||||
__asm bsget
|
||||
{
|
||||
lda 0xe405
|
||||
pha
|
||||
lda 0xe404
|
||||
pha
|
||||
}
|
||||
|
||||
__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
|
||||
#define bsout 0xffd2
|
||||
#define bsin 0xffe4
|
||||
#define bsplot 0xfff0
|
||||
#define bsinit 0xff81
|
||||
#define bsget 0xffcf
|
||||
#endif
|
||||
|
||||
#if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
|
||||
|
@ -136,192 +181,246 @@ void iocharmap(IOCharMap chmap)
|
|||
giocharmap = chmap;
|
||||
#if !defined(__ATARI__)
|
||||
if (chmap == IOCHM_PETSCII_1)
|
||||
putch(128 + 14);
|
||||
putrch(128 + 14);
|
||||
else if (chmap == IOCHM_PETSCII_2)
|
||||
putch(14);
|
||||
putrch(14);
|
||||
#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
|
||||
__asm {
|
||||
lda c
|
||||
jsr bsout
|
||||
}
|
||||
}
|
||||
|
||||
void putpch(char c)
|
||||
{
|
||||
#if defined(__ATARI__)
|
||||
if (c == 10)
|
||||
c = 0x9b;
|
||||
#else
|
||||
cmp #97
|
||||
bcs w2
|
||||
cmp #91
|
||||
bcs w3
|
||||
w2:
|
||||
eor #$20
|
||||
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
|
||||
cpx #IOCHM_PETSCII_2
|
||||
beq w3
|
||||
and #$df
|
||||
w3:
|
||||
jmp bsout
|
||||
|
||||
putrch(c);
|
||||
}
|
||||
|
||||
__asm getpch
|
||||
static char convch(char ch)
|
||||
{
|
||||
jsr bsin
|
||||
#if !defined(__ATARI__)
|
||||
|
||||
ldx giocharmap
|
||||
cpx #IOCHM_ASCII
|
||||
bcc w3
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cmp #13
|
||||
bne w1
|
||||
lda #10
|
||||
w1:
|
||||
cpx #IOCHM_PETSCII_1
|
||||
bcc w3
|
||||
#endif
|
||||
return ch;
|
||||
}
|
||||
|
||||
cmp #219
|
||||
bcs w3
|
||||
cmp #65
|
||||
bcc w3
|
||||
char getrch(void)
|
||||
{
|
||||
return __asm {
|
||||
jsr bsget
|
||||
sta accu
|
||||
};
|
||||
}
|
||||
|
||||
cmp #193
|
||||
bcc w4
|
||||
eor #$a0
|
||||
w4:
|
||||
cmp #123
|
||||
bcs w3
|
||||
cmp #97
|
||||
bcs w2
|
||||
cmp #91
|
||||
bcs w3
|
||||
w2:
|
||||
eor #$20
|
||||
w3:
|
||||
char getpch(void)
|
||||
{
|
||||
return convch(getrch());
|
||||
}
|
||||
|
||||
|
||||
char kbhit(void)
|
||||
{
|
||||
__asm
|
||||
#if defined(__CBMPET__)
|
||||
return __asm
|
||||
{
|
||||
lda $9e
|
||||
sta accu
|
||||
};
|
||||
#else
|
||||
return __asm
|
||||
{
|
||||
lda $c6
|
||||
sta accu
|
||||
}
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
char getche(void)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
L1:
|
||||
jsr getpch
|
||||
cmp #0
|
||||
beq L1
|
||||
char ch;
|
||||
do {
|
||||
ch = __asm {
|
||||
jsr bsin
|
||||
sta accu
|
||||
};
|
||||
} while (!ch);
|
||||
|
||||
sta accu
|
||||
jsr putpch
|
||||
__asm {
|
||||
lda ch
|
||||
jsr bsout
|
||||
}
|
||||
|
||||
return convch(ch);
|
||||
}
|
||||
|
||||
char getch(void)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
L1:
|
||||
jsr getpch
|
||||
cmp #0
|
||||
beq L1
|
||||
char ch;
|
||||
do {
|
||||
ch = __asm {
|
||||
jsr bsin
|
||||
sta accu
|
||||
};
|
||||
} while (!ch);
|
||||
|
||||
sta accu
|
||||
}
|
||||
return convch(ch);
|
||||
}
|
||||
|
||||
char getchx(void)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
jsr getpch
|
||||
sta accu
|
||||
}
|
||||
char ch = __asm {
|
||||
jsr bsin
|
||||
sta accu
|
||||
};
|
||||
|
||||
return convch(ch);
|
||||
}
|
||||
|
||||
void putch(char c)
|
||||
{
|
||||
__asm {
|
||||
lda c
|
||||
jsr bsout
|
||||
}
|
||||
putpch(c);
|
||||
}
|
||||
|
||||
void clrscr(void)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
jsr bsinit
|
||||
}
|
||||
putrch(147);
|
||||
}
|
||||
|
||||
void textcursor(bool show)
|
||||
{
|
||||
*(char *)0xcc = show ? 0 : 1;
|
||||
*(volatile char *)0xcc = show ? 0 : 1;
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
ldx cy
|
||||
ldy cx
|
||||
clc
|
||||
jsr bsplot
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void textcolor(char c)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
lda c
|
||||
sta $0286
|
||||
}
|
||||
*(volatile char *)0x0286 = c;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
lda $d3
|
||||
sta accu
|
||||
}
|
||||
#if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
|
||||
return *(volatile char *)0xec;
|
||||
#elif defined(__PLUS4__)
|
||||
return *(volatile char *)0xca;
|
||||
#else
|
||||
return *(volatile char *)0xd3;
|
||||
#endif
|
||||
}
|
||||
|
||||
char wherey(void)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
lda $d6
|
||||
sta accu
|
||||
}
|
||||
#if defined(__C128__) || defined(__C128B__) || defined(__C128E__)
|
||||
return *(volatile char *)0xeb;
|
||||
#elif defined(__PLUS4__)
|
||||
return *(volatile char *)0xcd;
|
||||
#else
|
||||
return *(volatile char *)0xd6;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ void dispmode80col(void);
|
|||
#define PETSCII_CLEAR 0x94
|
||||
#define PETSCII_DEL 0x14
|
||||
#define PETSCII_INSERT 0x94
|
||||
#define PETSCII_STOP 0x0c
|
||||
#define PETSCII_STOP 0x03
|
||||
#define PETSCII_RETURN 0x0d
|
||||
|
||||
#define PETSCII_F1 0x85
|
||||
|
@ -43,6 +43,39 @@ void dispmode80col(void);
|
|||
#define PETSCII_F7 0x88
|
||||
#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 getche(void);
|
||||
|
@ -59,15 +92,21 @@ void clrscr(void);
|
|||
|
||||
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
|
||||
|
||||
void textcursor(bool show);
|
||||
inline void textcursor(bool show);
|
||||
|
||||
#pragma compile("conio.c")
|
||||
|
||||
|
|
678
include/crt.c
678
include/crt.c
File diff suppressed because it is too large
Load Diff
|
@ -144,8 +144,8 @@ enum ByteCode
|
|||
BC_LOOP_U8,
|
||||
BC_MALLOC,
|
||||
BC_FREE,
|
||||
BC_UNUSED_4,
|
||||
BC_UNUSED_5,
|
||||
BC_FILL,
|
||||
BC_FILL_LONG,
|
||||
BC_UNUSED_6,
|
||||
|
||||
BC_JSR,
|
||||
|
@ -186,6 +186,11 @@ enum ByteCode
|
|||
BC_BINOP_SHR_I32,
|
||||
BC_BINOP_CMP_U32,
|
||||
BC_BINOP_CMP_S32,
|
||||
|
||||
BC_CONV_U32_F32,
|
||||
BC_CONV_I32_F32,
|
||||
BC_CONV_F32_U32,
|
||||
BC_CONV_F32_I32,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -116,31 +116,38 @@ int lmul4f12s(int x, int y)
|
|||
{
|
||||
__asm
|
||||
{
|
||||
bit y + 1
|
||||
bpl W0
|
||||
|
||||
sec
|
||||
lda #0
|
||||
sbc y
|
||||
sta y
|
||||
lda #0
|
||||
sbc y + 1
|
||||
sta y + 1
|
||||
lda x
|
||||
ror
|
||||
sta accu
|
||||
|
||||
sec
|
||||
lda #0
|
||||
sbc x
|
||||
sta x
|
||||
lda #0
|
||||
sbc x + 1
|
||||
sta x + 1
|
||||
W0:
|
||||
ldx #15
|
||||
lda #0
|
||||
sta accu + 1
|
||||
|
||||
L1: lsr x + 1
|
||||
ror x
|
||||
bcc W4
|
||||
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
|
||||
tay
|
||||
clc
|
||||
|
@ -156,23 +163,31 @@ W1:
|
|||
dex
|
||||
bne L1
|
||||
|
||||
lsr x
|
||||
bcc W2
|
||||
|
||||
tay
|
||||
sec
|
||||
// sec ; we know it is set here
|
||||
lda accu + 1
|
||||
sbc y
|
||||
sta accu + 1
|
||||
tya
|
||||
sbc y + 1
|
||||
|
||||
sec
|
||||
W2:
|
||||
ror
|
||||
ror accu + 1
|
||||
ror accu
|
||||
|
||||
bit y + 1
|
||||
bpl W3
|
||||
|
||||
tax
|
||||
sec
|
||||
lda accu + 1
|
||||
sbc x
|
||||
sta accu + 1
|
||||
txa
|
||||
sbc x + 1
|
||||
W3:
|
||||
lsr
|
||||
ror accu + 1
|
||||
ror accu
|
||||
|
@ -270,15 +285,17 @@ unsigned lmuldiv16u(unsigned a, unsigned b, unsigned c)
|
|||
__asm
|
||||
{
|
||||
lda #0
|
||||
sta __tmp + 0
|
||||
sta __tmp + 1
|
||||
sta __tmp + 2
|
||||
sta __tmp + 3
|
||||
|
||||
ldx #16
|
||||
L1: lsr a + 1
|
||||
ror a
|
||||
lda a
|
||||
sec
|
||||
T1:
|
||||
ldy #8
|
||||
L1:
|
||||
ror
|
||||
bcc W1
|
||||
tax
|
||||
clc
|
||||
lda __tmp + 2
|
||||
adc b
|
||||
|
@ -286,20 +303,38 @@ unsigned lmuldiv16u(unsigned a, unsigned b, unsigned c)
|
|||
lda __tmp + 3
|
||||
adc b + 1
|
||||
sta __tmp + 3
|
||||
txa
|
||||
W1:
|
||||
ror __tmp + 3
|
||||
ror __tmp + 2
|
||||
ror __tmp + 1
|
||||
ror __tmp
|
||||
dex
|
||||
dey
|
||||
bne L1
|
||||
ror
|
||||
bcc T2
|
||||
|
||||
lda #0
|
||||
sta accu
|
||||
sta accu + 1
|
||||
sta __tmp + 0
|
||||
lda a + 1
|
||||
clc
|
||||
bcc T1
|
||||
|
||||
ldx #17
|
||||
T2:
|
||||
sec
|
||||
L3:
|
||||
sta __tmp + 1
|
||||
ldx #8
|
||||
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
|
||||
lda __tmp + 2
|
||||
sbc c
|
||||
|
@ -307,33 +342,23 @@ unsigned lmuldiv16u(unsigned a, unsigned b, unsigned c)
|
|||
lda __tmp + 3
|
||||
sbc c + 1
|
||||
bcc W2
|
||||
W4:
|
||||
sta __tmp + 3
|
||||
sty __tmp + 2
|
||||
W2:
|
||||
rol accu
|
||||
rol accu + 1
|
||||
|
||||
asl __tmp
|
||||
rol __tmp + 1
|
||||
rol __tmp + 2
|
||||
rol __tmp + 3
|
||||
|
||||
dex
|
||||
beq E2
|
||||
bcc L2
|
||||
|
||||
lda __tmp + 2
|
||||
sbc c
|
||||
sta __tmp + 2
|
||||
lda __tmp + 3
|
||||
sbc c + 1
|
||||
sta __tmp + 3
|
||||
sec
|
||||
bcs W2
|
||||
E2:
|
||||
bne L2
|
||||
lda __tmp + 1
|
||||
rol
|
||||
bcc T3
|
||||
|
||||
sta accu + 1
|
||||
lda __tmp + 0
|
||||
clc
|
||||
bcc L3
|
||||
T3:
|
||||
sta accu
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int lmuldiv16s(int a, int b, int c)
|
||||
|
@ -358,15 +383,17 @@ int lmuldiv16s(int a, int b, int c)
|
|||
__asm
|
||||
{
|
||||
lda #0
|
||||
sta __tmp + 0
|
||||
sta __tmp + 1
|
||||
sta __tmp + 2
|
||||
sta __tmp + 3
|
||||
|
||||
ldx #16
|
||||
L1: lsr a + 1
|
||||
ror a
|
||||
lda a
|
||||
sec
|
||||
T1:
|
||||
ldy #8
|
||||
L1:
|
||||
ror
|
||||
bcc W1
|
||||
tax
|
||||
clc
|
||||
lda __tmp + 2
|
||||
adc b
|
||||
|
@ -374,20 +401,38 @@ int lmuldiv16s(int a, int b, int c)
|
|||
lda __tmp + 3
|
||||
adc b + 1
|
||||
sta __tmp + 3
|
||||
txa
|
||||
W1:
|
||||
ror __tmp + 3
|
||||
ror __tmp + 2
|
||||
ror __tmp + 1
|
||||
ror __tmp
|
||||
dex
|
||||
dey
|
||||
bne L1
|
||||
ror
|
||||
bcc T2
|
||||
|
||||
lda #0
|
||||
sta accu
|
||||
sta accu + 1
|
||||
sta __tmp + 0
|
||||
lda a + 1
|
||||
clc
|
||||
bcc T1
|
||||
|
||||
ldx #17
|
||||
T2:
|
||||
sec
|
||||
L3:
|
||||
sta __tmp + 1
|
||||
ldx #8
|
||||
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
|
||||
lda __tmp + 2
|
||||
sbc c
|
||||
|
@ -395,30 +440,23 @@ int lmuldiv16s(int a, int b, int c)
|
|||
lda __tmp + 3
|
||||
sbc c + 1
|
||||
bcc W2
|
||||
W4:
|
||||
sta __tmp + 3
|
||||
sty __tmp + 2
|
||||
W2:
|
||||
rol accu
|
||||
rol accu + 1
|
||||
|
||||
asl __tmp
|
||||
rol __tmp + 1
|
||||
rol __tmp + 2
|
||||
rol __tmp + 3
|
||||
|
||||
dex
|
||||
beq E2
|
||||
bcc L2
|
||||
bne 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
|
||||
beq E1
|
||||
|
||||
|
|
|
@ -525,7 +525,7 @@ void bm_polygon_nc_fill(const Bitmap * bm, const ClipRect * clip, int * px, int
|
|||
static inline void buildline(char ly, char lx, int dx, int dy, int stride, bool left, bool up, char pattern, LineOp op)
|
||||
{
|
||||
char ip = 0;
|
||||
bool delta16 = ((dx | dy) & 0xff80) != 0;
|
||||
bool delta16 =((dx | dy) & 0xff80) != 0;
|
||||
|
||||
// ylow
|
||||
ip += asm_im(BLIT_CODE + ip, ASM_LDY, ly);
|
||||
|
@ -579,59 +579,105 @@ static inline void buildline(char ly, char lx, int dx, int dy, int stride, bool
|
|||
break;
|
||||
}
|
||||
|
||||
// m >= 0
|
||||
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);
|
||||
|
||||
ip += asm_np(BLIT_CODE + ip, up ? ASM_DEY : ASM_INY);
|
||||
ip += asm_im(BLIT_CODE + ip, ASM_CPY, up ? 0xff : 0x08);
|
||||
ip += asm_rl(BLIT_CODE + ip, ASM_BNE, 15);
|
||||
|
||||
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, stride & 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 >> 8);
|
||||
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP + 1);
|
||||
ip += asm_im(BLIT_CODE + ip, ASM_LDY, up ? 0x07 : 0x00);
|
||||
|
||||
ip += asm_np(BLIT_CODE + ip, ASM_SEC);
|
||||
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP);
|
||||
ip += asm_im(BLIT_CODE + ip, ASM_SBC, dx & 0xff);
|
||||
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP);
|
||||
|
||||
if (delta16)
|
||||
if (dy)
|
||||
{
|
||||
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1);
|
||||
ip += asm_im(BLIT_CODE + ip, ASM_SBC, dx >> 8);
|
||||
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP + 1);
|
||||
bool delta8 = false;
|
||||
|
||||
if (dx)
|
||||
{
|
||||
// m >= 0
|
||||
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + delta16);
|
||||
char n = delta16 ? 18 + 13 + 2 : 18 + 7 + 2;
|
||||
if (!up) n++;
|
||||
ip += asm_rl(BLIT_CODE + ip, ASM_BMI, n);
|
||||
delta8 = !delta16;
|
||||
}
|
||||
|
||||
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_im(BLIT_CODE + ip, ASM_LDY, 0x07);
|
||||
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_SP);
|
||||
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_LDA, REG_SP + 1);
|
||||
ip += asm_im(BLIT_CODE + ip, ASM_ADC, stride >> 8);
|
||||
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_SP + 1);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
if (dx)
|
||||
{
|
||||
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_zp(BLIT_CODE + ip, ASM_STA, REG_DP);
|
||||
|
||||
if (delta16)
|
||||
{
|
||||
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1);
|
||||
ip += asm_im(BLIT_CODE + ip, ASM_SBC, dx >> 8);
|
||||
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP + 1);
|
||||
ip += asm_rl(BLIT_CODE + ip, ASM_BPL, 13 + 4 + 12);
|
||||
|
||||
ip += asm_np(BLIT_CODE + ip, ASM_CLC);
|
||||
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP);
|
||||
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_LDA, REG_DP + 1);
|
||||
ip += asm_im(BLIT_CODE + ip, ASM_ADC, dy >> 8);
|
||||
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
|
||||
}
|
||||
|
||||
// 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_zp(BLIT_CODE + ip, ASM_LDA, REG_DP);
|
||||
ip += asm_im(BLIT_CODE + ip, ASM_ADC, dy & 0xff);
|
||||
ip += asm_zp(BLIT_CODE + ip, ASM_STA, REG_DP);
|
||||
if (delta16)
|
||||
if (dx)
|
||||
{
|
||||
ip += asm_zp(BLIT_CODE + ip, ASM_LDA, REG_DP + 1);
|
||||
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, 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 --
|
||||
|
@ -649,6 +695,7 @@ static inline void callline(byte * dst, byte bit, int m, char lh, char pattern)
|
|||
{
|
||||
__asm
|
||||
{
|
||||
|
||||
lda dst
|
||||
sta REG_SP
|
||||
lda dst + 1
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -11,7 +11,7 @@
|
|||
#define CHAR_MIN SCHAR_MIN
|
||||
#define CHAR_MAX SCHAR_MAX
|
||||
|
||||
#define INT_MIN -32767
|
||||
#define INT_MIN (-32767-1)
|
||||
#define INT_MAX 32767
|
||||
#define UINT_MAX 65535
|
||||
|
||||
|
|
|
@ -110,12 +110,12 @@ float atan2(float p, float q)
|
|||
return s;
|
||||
}
|
||||
|
||||
#define F_EXP_0 1.0000003
|
||||
#define F_EXP_1 0.693147059
|
||||
#define F_EXP_2 0.240173099
|
||||
#define F_EXP_3 0.055816392
|
||||
#define F_EXP_4 0.008965036
|
||||
#define F_EXP_5 0.001898429
|
||||
#define F_EXP_0 1.0
|
||||
#define F_EXP_1 0.69315668
|
||||
#define F_EXP_2 0.240132068
|
||||
#define F_EXP_3 0.055876024
|
||||
#define F_EXP_4 0.008940801
|
||||
#define F_EXP_5 0.001894414
|
||||
|
||||
float exp(float f)
|
||||
{
|
||||
|
@ -143,12 +143,12 @@ float exp(float f)
|
|||
return s * x.f;
|
||||
}
|
||||
|
||||
#define F_LOG_0 -3.78712618
|
||||
#define F_LOG_1 10.0957081
|
||||
#define F_LOG_2 -13.9747486
|
||||
#define F_LOG_3 12.7568806
|
||||
#define F_LOG_4 -6.48114552
|
||||
#define F_LOG_5 1.39045416
|
||||
#define F_LOG_0 -3.78717706
|
||||
#define F_LOG_1 10.0960498
|
||||
#define F_LOG_2 -13.975654
|
||||
#define F_LOG_3 12.7580616
|
||||
#define F_LOG_4 -6.48190725
|
||||
#define F_LOG_5 1.39064767
|
||||
|
||||
float log(float f)
|
||||
{
|
||||
|
|
|
@ -33,6 +33,14 @@ bool isfinite(float f);
|
|||
#pragma intrinsic(sin)
|
||||
#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")
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -952,6 +952,13 @@ istream & istream::operator>>(float & val)
|
|||
return *this;
|
||||
}
|
||||
|
||||
istream & istream::operator>>(char & val)
|
||||
{
|
||||
doskipws();
|
||||
val = get();
|
||||
return *this;
|
||||
}
|
||||
|
||||
istream & istream::operator>>(char * p)
|
||||
{
|
||||
doskipws();
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
showpos = 0x0800,
|
||||
skipws = 0x1000,
|
||||
unitbuf = 0x2000,
|
||||
uppercase = 0x3000,
|
||||
uppercase = 0x4000,
|
||||
|
||||
adjustfield = 0x00b0,
|
||||
basefield = 0x004a,
|
||||
|
@ -124,6 +124,7 @@ public:
|
|||
istream & putback(char c);
|
||||
istream & unget(void);
|
||||
|
||||
istream & operator>>(char & val);
|
||||
istream & operator>>(bool & val);
|
||||
istream & operator>>(int & val);
|
||||
istream & operator>>(unsigned & val);
|
||||
|
|
|
@ -124,8 +124,8 @@ public:
|
|||
{
|
||||
head.succ = l.head.succ;
|
||||
head.pred = l.head.pred;
|
||||
head.succ->pred = head;
|
||||
head.pred->succ = head;
|
||||
head.succ->pred = (listnode<T> *)&head;
|
||||
head.pred->succ = (listnode<T> *)&head;
|
||||
l.head.succ = (listnode<T> *)&(l.head);
|
||||
l.head.pred = (listnode<T> *)&(l.head);
|
||||
}
|
||||
|
@ -136,8 +136,8 @@ public:
|
|||
{
|
||||
head.succ = l.head.succ;
|
||||
head.pred = l.head.pred;
|
||||
head.succ->pred = head;
|
||||
head.pred->succ = head;
|
||||
head.succ->pred = (listnode<T> *)&head;
|
||||
head.pred->succ = (listnode<T> *)&head;
|
||||
l.head.succ = (listnode<T> *)&(l.head);
|
||||
l.head.pred = (listnode<T> *)&(l.head);
|
||||
return *this;
|
||||
|
|
|
@ -20,12 +20,12 @@ void ostringstream::bput(char ch)
|
|||
{
|
||||
mBSize = 15;
|
||||
mBFill = 0;
|
||||
mBuffer = malloc(15);
|
||||
mBuffer = (char *)malloc(15);
|
||||
}
|
||||
else if (mBFill == mBSize)
|
||||
{
|
||||
mBSize *= 2;
|
||||
char * b = malloc(mBSize);
|
||||
char * b = (char *)malloc(mBSize);
|
||||
for(char i=0; i<mBFill; i++)
|
||||
b[i] = mBuffer[i];
|
||||
free(mBuffer);
|
||||
|
@ -46,7 +46,7 @@ void ostringstream::str(const string & str)
|
|||
{
|
||||
free(mBuffer);
|
||||
mBSize = mBFill;
|
||||
mBuffer = malloc(mBSize);
|
||||
mBuffer = (char *)malloc(mBSize);
|
||||
}
|
||||
str.copyseg(mBuffer, 0, mBFill);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <new>
|
||||
#include <stdlib.h>
|
||||
#include <opp/utility.h>
|
||||
#include <oscar.h>
|
||||
|
||||
namespace opp {
|
||||
|
||||
|
@ -11,8 +12,8 @@ template <class T, int N>
|
|||
class static_vector
|
||||
{
|
||||
protected:
|
||||
char _space[N * sizeof(T)];
|
||||
enum { m = N } _size;
|
||||
char _space[N * sizeof(T)];
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
|
@ -20,23 +21,28 @@ public:
|
|||
|
||||
static_vector(size_t n) : _size(n)
|
||||
{
|
||||
#ifdef CAPACITYCHECK
|
||||
if (n > N) debugcrash();
|
||||
#endif
|
||||
T * data = (T*)_space;
|
||||
for(size_t i=0; i<n; i++)
|
||||
new (data + i) T;
|
||||
new (data + i) T();
|
||||
}
|
||||
|
||||
static_vector(const static_vector & v)
|
||||
: _size(v._size)
|
||||
{
|
||||
size_t n = _size;
|
||||
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]);
|
||||
}
|
||||
|
||||
~static_vector(void)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -45,10 +51,12 @@ public:
|
|||
if (this != &v)
|
||||
{
|
||||
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();
|
||||
_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]);
|
||||
}
|
||||
return *this;
|
||||
|
@ -69,6 +77,11 @@ public:
|
|||
return _size == 0;
|
||||
}
|
||||
|
||||
bool full(void) const
|
||||
{
|
||||
return _size == N;
|
||||
}
|
||||
|
||||
size_t capacity(void) const
|
||||
{
|
||||
return N;
|
||||
|
@ -76,6 +89,8 @@ public:
|
|||
|
||||
void resize(size_t n);
|
||||
|
||||
void clear(void);
|
||||
|
||||
T & at(size_t at)
|
||||
{
|
||||
return ((T*)_space)[at];
|
||||
|
@ -166,6 +181,8 @@ public:
|
|||
((T*)_space)[_size].~T();
|
||||
}
|
||||
|
||||
void assign(size_t count, const T & t);
|
||||
|
||||
void insert(size_t at, const T & t);
|
||||
|
||||
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>
|
||||
void static_vector<T, N>::resize(size_t n)
|
||||
{
|
||||
#ifdef CAPACITYCHECK
|
||||
if (n > N) debugcrash();
|
||||
#endif
|
||||
T * data = (T*)_space;
|
||||
if (n < _size)
|
||||
{
|
||||
for(size_t i=n; i<_size; i++)
|
||||
data[i].~T();
|
||||
_size = n;
|
||||
}
|
||||
else
|
||||
else if (n > 0)
|
||||
{
|
||||
for(size_t i=_size; i<n; i++)
|
||||
new(data + i)T;
|
||||
_size = n;
|
||||
new(data + i)T();
|
||||
}
|
||||
_size = n;
|
||||
}
|
||||
|
||||
template <class T, int N>
|
||||
void static_vector<T, N>::push_back(const T & t)
|
||||
{
|
||||
#ifdef CAPACITYCHECK
|
||||
if (_size >= N) debugcrash();
|
||||
#endif
|
||||
new ((T*)_space + _size++)T(t);
|
||||
}
|
||||
|
||||
template <class T, int N>
|
||||
void static_vector<T, N>::push_back(T && t)
|
||||
{
|
||||
#ifdef CAPACITYCHECK
|
||||
if (_size >= N) debugcrash();
|
||||
#endif
|
||||
new ((T*)_space + _size++)T(t);
|
||||
}
|
||||
|
||||
|
@ -212,14 +245,28 @@ template <class T, int N>
|
|||
template <typename ...P>
|
||||
void static_vector<T, N>::emplace_back(const P&... p)
|
||||
{
|
||||
#ifdef CAPACITYCHECK
|
||||
if (_size >= N) debugcrash();
|
||||
#endif
|
||||
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>
|
||||
void static_vector<T, N>::insert(size_t at, const T & t)
|
||||
{
|
||||
T * data = (T*)_space;
|
||||
new (data + _size)T;
|
||||
new (data + _size)T();
|
||||
for(size_t i=_size; i>at; i--)
|
||||
data[i] = move(data[i - 1]);
|
||||
data[at] = t;
|
||||
|
@ -240,9 +287,12 @@ void static_vector<T, N>::erase(size_t at, size_t n)
|
|||
template <class T, int N>
|
||||
T * static_vector<T, N>::insert(T * at, const T & t)
|
||||
{
|
||||
#ifdef CAPACITYCHECK
|
||||
if (_size >= N) debugcrash();
|
||||
#endif
|
||||
T * data = (T*)_space;
|
||||
T * dp = data + _size;
|
||||
new (dp)T;
|
||||
new (dp)T();
|
||||
while (dp != at)
|
||||
{
|
||||
dp--;
|
||||
|
|
|
@ -32,7 +32,7 @@ string::string(const string & s)
|
|||
if (s.cstr)
|
||||
{
|
||||
char l = s.cstr[0];
|
||||
cstr = malloc(char(l + 2));
|
||||
cstr = (char *)malloc(char(l + 2));
|
||||
smemcpy(cstr, s.cstr, l + 2);
|
||||
}
|
||||
else
|
||||
|
@ -52,7 +52,7 @@ string::string(const char * s)
|
|||
char l = sstrlen(s);
|
||||
if (l)
|
||||
{
|
||||
cstr = malloc(char(l + 2));
|
||||
cstr = (char *)malloc(char(l + 2));
|
||||
cstr[0] = l;
|
||||
smemcpy(cstr + 1, s, l + 1);
|
||||
}
|
||||
|
@ -67,9 +67,10 @@ string::string(const char * s, char size)
|
|||
{
|
||||
if (size)
|
||||
{
|
||||
cstr = malloc(char(size + 2));
|
||||
cstr = (char *)malloc(char(size + 2));
|
||||
cstr[0] = size;
|
||||
smemcpy(cstr + 1, s, size + 1);
|
||||
smemcpy(cstr + 1, s, size);
|
||||
cstr[size + 1] = 0;
|
||||
}
|
||||
else
|
||||
cstr = nullptr;
|
||||
|
@ -77,7 +78,7 @@ string::string(const char * s, char size)
|
|||
|
||||
string::string(char c)
|
||||
{
|
||||
cstr = malloc(3);
|
||||
cstr = (char *)malloc(3);
|
||||
cstr[0] = 1;
|
||||
cstr[1] = c;
|
||||
cstr[2] = 0;
|
||||
|
@ -114,7 +115,7 @@ string & string::operator=(const string & s)
|
|||
if (s.cstr)
|
||||
{
|
||||
char l = s.cstr[0];
|
||||
cstr = malloc(char(l + 2));
|
||||
cstr = (char *)malloc(char(l + 2));
|
||||
smemcpy(cstr, s.cstr, l + 2);
|
||||
}
|
||||
else
|
||||
|
@ -144,7 +145,7 @@ string & string::operator=(const char * s)
|
|||
char l = sstrlen(s);
|
||||
if (l)
|
||||
{
|
||||
cstr = malloc(char(l + 2));
|
||||
cstr = (char *)malloc(char(l + 2));
|
||||
cstr[0] = l;
|
||||
smemcpy(cstr + 1, s, l + 1);
|
||||
}
|
||||
|
@ -166,7 +167,7 @@ string & string::operator+=(const string & s)
|
|||
d = cstr[0];
|
||||
|
||||
char l = s.cstr[0] + d;
|
||||
char * c = malloc(char(l + 2));
|
||||
char * c = (char *)malloc(char(l + 2));
|
||||
c[0] = l;
|
||||
|
||||
if (d)
|
||||
|
@ -188,7 +189,7 @@ string & string::operator+=(const char * s)
|
|||
if (cstr)
|
||||
{
|
||||
char l = sl + cstr[0];
|
||||
char * c = malloc(char(l + 2));
|
||||
char * c = (char *)malloc(char(l + 2));
|
||||
c[0] = l;
|
||||
smemcpy(c + 1, cstr + 1, cstr[0]);
|
||||
smemcpy(c + 1 + cstr[0], s, sl + 1);
|
||||
|
@ -197,7 +198,7 @@ string & string::operator+=(const char * s)
|
|||
}
|
||||
else
|
||||
{
|
||||
cstr = malloc(char(sl + 2));
|
||||
cstr = (char *)malloc(char(sl + 2));
|
||||
cstr[0] = sl;
|
||||
smemcpy(cstr + 1, s, sl + 1);
|
||||
}
|
||||
|
@ -211,7 +212,7 @@ string & string::operator+=(char c)
|
|||
if (cstr)
|
||||
{
|
||||
char l = cstr[0] + 1;
|
||||
char * p = malloc(char(l + 2));
|
||||
char * p = (char *)malloc(char(l + 2));
|
||||
p[0] = l;
|
||||
smemcpy(p + 1, cstr + 1, cstr[0]);
|
||||
p[l] = c;
|
||||
|
@ -221,7 +222,7 @@ string & string::operator+=(char c)
|
|||
}
|
||||
else
|
||||
{
|
||||
cstr = malloc(3);
|
||||
cstr = (char *)malloc(3);
|
||||
cstr[0] = 1;
|
||||
cstr[1] = c;
|
||||
cstr[2] = 0;
|
||||
|
@ -229,6 +230,10 @@ string & string::operator+=(char c)
|
|||
return *this;
|
||||
}
|
||||
|
||||
inline const char * string::c_str(void) const
|
||||
{
|
||||
return this->tocstr();
|
||||
}
|
||||
|
||||
inline const char * string::tocstr(void) const
|
||||
{
|
||||
|
@ -253,7 +258,7 @@ string string::operator+(const string & s) const
|
|||
if (s.cstr)
|
||||
{
|
||||
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[0], s.cstr + 1, s.cstr[0]);
|
||||
return string(l, p);
|
||||
|
@ -275,7 +280,7 @@ string string::operator+(const char * s) const
|
|||
if (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[0], s, sl);
|
||||
return string(l, p);
|
||||
|
@ -295,7 +300,7 @@ string string::operator+(char c) const
|
|||
if (cstr)
|
||||
{
|
||||
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]);
|
||||
p[l] = c;
|
||||
return string(l, p);
|
||||
|
@ -523,7 +528,7 @@ string string::substr(char pos, char len) const
|
|||
if (pos + len > l)
|
||||
len = l - pos;
|
||||
|
||||
char * p = malloc(len + 2);
|
||||
char * p = (char *)malloc(len + 2);
|
||||
memcpy(p + 1, cstr + 1 + pos, len);
|
||||
return string(len, p);
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@ public:
|
|||
const char * end(void) const;
|
||||
const char * cend(void) const;
|
||||
|
||||
const char * c_str(void) const;
|
||||
const char * tocstr(void) const;
|
||||
|
||||
string substr(char pos, char len) const;
|
||||
|
|
|
@ -21,13 +21,14 @@ public:
|
|||
vector(size_t n) : _data((T*)malloc(n * sizeof(T))), _size(n), _capacity(n)
|
||||
{
|
||||
for(size_t i=0; i<n; i++)
|
||||
new (_data + i) T;
|
||||
new (_data + i) T();
|
||||
}
|
||||
|
||||
vector(const vector & v)
|
||||
: _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]);
|
||||
}
|
||||
|
||||
|
@ -50,14 +51,16 @@ public:
|
|||
{
|
||||
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();
|
||||
free(_data);
|
||||
|
||||
_data = (T*)malloc(v._size * sizeof(T));
|
||||
_size = 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]);
|
||||
}
|
||||
return *this;
|
||||
|
@ -94,6 +97,8 @@ public:
|
|||
return _capacity;
|
||||
}
|
||||
|
||||
void clear(void);
|
||||
|
||||
void resize(size_t n);
|
||||
|
||||
void reserve(size_t n);
|
||||
|
@ -190,6 +195,8 @@ public:
|
|||
_data[_size].~T();
|
||||
}
|
||||
|
||||
void assign(size_t count, const T & t);
|
||||
|
||||
void insert(size_t at, const T & t);
|
||||
|
||||
void erase(size_t at, size_t n = 1);
|
||||
|
@ -204,7 +211,7 @@ protected:
|
|||
|
||||
|
||||
template <class T>
|
||||
void vector<T>::reserve(size_t n)
|
||||
__noinline void vector<T>::reserve(size_t n)
|
||||
{
|
||||
if (n > _capacity)
|
||||
{
|
||||
|
@ -221,7 +228,15 @@ void vector<T>::reserve(size_t n)
|
|||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -232,7 +247,7 @@ void vector<T>::resize(size_t n)
|
|||
else if (n < _capacity)
|
||||
{
|
||||
for(size_t i=_size; i<n; i++)
|
||||
new(_data + i)T;
|
||||
new(_data + i)T();
|
||||
_size = n;
|
||||
}
|
||||
else
|
||||
|
@ -286,12 +301,27 @@ void vector<T>::emplace_back(const P&... 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>
|
||||
void vector<T>::insert(size_t at, const T & t)
|
||||
{
|
||||
if (_size == _capacity)
|
||||
reserve(_size + 1 + (_size >> 1));
|
||||
new (_data + _size)T;
|
||||
new (_data + _size)T();
|
||||
for(size_t i=_size; i>at; i--)
|
||||
_data[i] = move(_data[i - 1]);
|
||||
_data[at] = t;
|
||||
|
@ -318,7 +348,7 @@ T * vector<T>::insert(T * at, const T & t)
|
|||
at = (T *)(f + unsigned(_data));
|
||||
}
|
||||
T * dp = _data + _size;
|
||||
new (dp)T;
|
||||
new (dp)T();
|
||||
while (dp != at)
|
||||
{
|
||||
dp--;
|
||||
|
|
|
@ -86,3 +86,53 @@ const char * oscar_expand_rle(char * dp, const char * sp)
|
|||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
// 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")
|
||||
|
||||
|
|
262
include/stdio.c
262
include/stdio.c
|
@ -2,237 +2,50 @@
|
|||
#include "conio.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)
|
||||
{
|
||||
__asm {
|
||||
lda c
|
||||
jsr putpch
|
||||
}
|
||||
putpch(c);
|
||||
}
|
||||
|
||||
char getchar(void)
|
||||
{
|
||||
__asm {
|
||||
jsr getpch
|
||||
sta accu
|
||||
lda #0
|
||||
sta accu + 1
|
||||
}
|
||||
return getpch();
|
||||
}
|
||||
|
||||
void puts(const char * str)
|
||||
{
|
||||
__asm {
|
||||
ploop:
|
||||
ldy #0
|
||||
lda (str), y
|
||||
beq pdone
|
||||
|
||||
jsr putpch
|
||||
|
||||
inc str
|
||||
bne ploop
|
||||
inc str + 1
|
||||
bne ploop
|
||||
pdone:
|
||||
}
|
||||
while (char ch = *str++)
|
||||
putpch(ch);
|
||||
}
|
||||
|
||||
char * gets(char * str)
|
||||
{
|
||||
__asm {
|
||||
gloop:
|
||||
jsr getpch
|
||||
ldy #0
|
||||
cmp #10
|
||||
beq gdone
|
||||
sta (str), y
|
||||
inc str
|
||||
bne gloop
|
||||
inc str + 1
|
||||
bne gloop
|
||||
gdone:
|
||||
lda #0
|
||||
sta (str), y
|
||||
char i = 0;
|
||||
while ((char ch = getpch()) != '\n')
|
||||
str[i++] = ch;
|
||||
str[i] = 0;
|
||||
return str;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -583,7 +396,7 @@ char * sformat(char * buff, const char * fmt, int * fps, bool print)
|
|||
|
||||
if (c >= '0' && c <='9')
|
||||
{
|
||||
int i = 0;
|
||||
char i = 0;
|
||||
while (c >= '0' && c <='9')
|
||||
{
|
||||
i = i * 10 + c - '0';
|
||||
|
@ -594,7 +407,7 @@ char * sformat(char * buff, const char * fmt, int * fps, bool print)
|
|||
|
||||
if (c == '.')
|
||||
{
|
||||
int i = 0;
|
||||
char i = 0;
|
||||
c = *p++;
|
||||
while (c >= '0' && c <='9')
|
||||
{
|
||||
|
@ -604,7 +417,7 @@ char * sformat(char * buff, const char * fmt, int * fps, bool print)
|
|||
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);
|
||||
}
|
||||
|
@ -743,6 +556,17 @@ int sprintf(char * str, const char * fmt, ...)
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
#define STDIO_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
void putchar(char c);
|
||||
|
||||
|
@ -12,10 +13,16 @@ void puts(const char * str);
|
|||
|
||||
char * gets(char * str);
|
||||
|
||||
char * gets_s(char * str, size_t n);
|
||||
|
||||
void printf(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 sscanf(const char * str, const char * fmt, ...);
|
||||
|
|
108
include/stdlib.c
108
include/stdlib.c
|
@ -7,20 +7,17 @@
|
|||
void itoa(int n, char * s, unsigned radix)
|
||||
{
|
||||
bool neg = n < 0;
|
||||
if (neg)
|
||||
{
|
||||
n = - n;
|
||||
}
|
||||
unsigned un = neg ? -n : n;
|
||||
|
||||
char i = 0;
|
||||
do {
|
||||
int d = n % radix;
|
||||
unsigned d = un % radix;
|
||||
if (d < 10)
|
||||
d += '0';
|
||||
else
|
||||
d += 'A' - 10;
|
||||
s[i++] = d;
|
||||
} while ((n /= radix) > 0);
|
||||
} while ((un /= radix) > 0);
|
||||
|
||||
if (neg)
|
||||
{
|
||||
|
@ -524,6 +521,12 @@ void exit(int status)
|
|||
}
|
||||
}
|
||||
|
||||
void abort(void)
|
||||
{
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
extern struct Heap {
|
||||
Heap * next, * end;
|
||||
} HeapNode;
|
||||
|
@ -541,7 +544,7 @@ unsigned heapfree(void)
|
|||
}
|
||||
|
||||
#if 0
|
||||
struct Heap {
|
||||
struct Heap {q
|
||||
unsigned int size;
|
||||
Heap * next;
|
||||
} * freeHeap;
|
||||
|
@ -664,6 +667,97 @@ void * calloc(int num, int size)
|
|||
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;
|
||||
|
||||
unsigned int rand(void)
|
||||
|
|
|
@ -37,12 +37,16 @@ long labs(long n);
|
|||
|
||||
void exit(int status);
|
||||
|
||||
void abort(void);
|
||||
|
||||
void * malloc(unsigned int size);
|
||||
|
||||
void free(void * ptr);
|
||||
|
||||
void * calloc(int num, int size);
|
||||
|
||||
void * realloc(void * ptr, unsigned size);
|
||||
|
||||
unsigned heapfree(void);
|
||||
|
||||
unsigned int rand(void);
|
||||
|
|
|
@ -138,6 +138,20 @@ char * cpycat(char * dst, const char * src)
|
|||
|
||||
#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)
|
||||
{
|
||||
__asm
|
||||
|
@ -223,8 +237,8 @@ void * memmove(void * dst, const void * src, int size)
|
|||
int sz = size;
|
||||
if (sz > 0)
|
||||
{
|
||||
char * d = dst;
|
||||
const char * s = src;
|
||||
char * d = (char *)dst;
|
||||
const char * s = (const char *)src;
|
||||
if (d < s)
|
||||
{
|
||||
do {
|
||||
|
@ -245,7 +259,7 @@ void * memmove(void * dst, const void * src, 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;
|
||||
|
||||
while (size--)
|
||||
|
|
|
@ -21,10 +21,16 @@ int memcmp(const void * ptr1, const void * ptr2, int size);
|
|||
|
||||
void * memmove(void * dst, const void * src, int size);
|
||||
|
||||
char* strchr( const char* str, int ch );
|
||||
|
||||
#pragma intrinsic(strcpy)
|
||||
|
||||
#pragma intrinsic(memcpy)
|
||||
|
||||
#pragma intrinsic(memset)
|
||||
|
||||
#pragma intrinsic(memclr)
|
||||
|
||||
#pragma compile("string.c")
|
||||
|
||||
#endif
|
||||
|
|
116
make/makefile
116
make/makefile
|
@ -1,12 +1,25 @@
|
|||
|
||||
|
||||
sources = $(wildcard ../oscar64/*.cpp)
|
||||
objects = $(patsubst ../oscar64/%.cpp,%.o,$(sources))
|
||||
project_dir := $(abspath $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))/../)
|
||||
sources = $(wildcard $(project_dir)/oscar64/*.cpp)
|
||||
srcdir := $(if $(srcdir),$(srcdir),$(project_dir)/build)
|
||||
objects = $(patsubst $(project_dir)/oscar64/%.cpp,$(srcdir)/%.o,$(sources))
|
||||
|
||||
CXX = c++
|
||||
CPPFLAGS = -g -O2 -std=c++11 -Wno-switch
|
||||
|
||||
$(shell mkdir -p ../bin)
|
||||
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
|
||||
|
||||
|
||||
ifdef WINDIR
|
||||
linklibs = -lpthread
|
||||
|
@ -16,26 +29,87 @@ else
|
|||
ifeq ($(UNAME_S), Darwin)
|
||||
|
||||
linklibs = -lpthread
|
||||
else
|
||||
else
|
||||
# MSVC
|
||||
linklibs = -lrt -lpthread
|
||||
# MinGW
|
||||
#linklibs = -lversion -lpthread
|
||||
endif
|
||||
endif
|
||||
|
||||
%.o: ../oscar64/%.cpp
|
||||
$(CXX) -c $(CPPFLAGS) $< -o $@
|
||||
|
||||
%.d: ../oscar64/%.cpp
|
||||
@set -e; rm -f $@; \
|
||||
$(CC) -MM $(CPPFLAGS) $< > $@.$$$$; \
|
||||
sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
|
||||
rm -f $@.$$$$
|
||||
|
||||
../bin/oscar64 : $(objects)
|
||||
$(CXX) $(CPPFLAGS) $(linklibs) $(objects) -o ../bin/oscar64
|
||||
all: compiler samples check
|
||||
|
||||
|
||||
$(srcdir)/%.o: $(project_dir)/oscar64/%.cpp
|
||||
@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
|
||||
|
||||
|
||||
.PHONY : 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)
|
||||
|
||||
|
@ -44,3 +118,9 @@ else
|
|||
include $(objects:.o=.d)
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
16
oscar64.sln
16
oscar64.sln
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31624.102
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.13.35931.197
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oscar64", "oscar64\oscar64.vcxproj", "{1DBC623E-6109-41FE-B1BB-9B43FC984F7D}"
|
||||
EndProject
|
||||
|
@ -23,10 +23,14 @@ Global
|
|||
{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.Build.0 = Release|Win32
|
||||
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x64.ActiveCfg = Debug
|
||||
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x86.ActiveCfg = Debug
|
||||
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x64.ActiveCfg = Release
|
||||
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Release|x86.ActiveCfg = Release
|
||||
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x64.Build.0 = Debug|x64
|
||||
{567F9C0F-5888-442A-BC9A-D7F9591E5AB4}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{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
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -421,9 +421,33 @@ protected:
|
|||
array = a2;
|
||||
}
|
||||
|
||||
for (int i = size; i < to; i++) array[i] = T{};
|
||||
|
||||
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:
|
||||
ExpandingArray(void)
|
||||
{
|
||||
|
@ -596,6 +620,24 @@ public:
|
|||
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)
|
||||
{
|
||||
assert(n >= 0 && n < size);
|
||||
|
|
|
@ -293,7 +293,7 @@ const char* AsmInstructionNames[NUM_ASM_INS_TYPES] = {
|
|||
"INV", "BYT"
|
||||
};
|
||||
|
||||
int AsmInsModeSize[NUM_ASM_INS_MODES] = {
|
||||
int AsmInsModeSize[NUM_ASM_INS_MODES_X] = {
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
|
@ -306,6 +306,8 @@ int AsmInsModeSize[NUM_ASM_INS_MODES] = {
|
|||
2,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
2
|
||||
};
|
||||
|
||||
void InitAssembler(void)
|
||||
|
|
|
@ -31,7 +31,9 @@ enum AsmInsMode
|
|||
|
||||
NUM_ASM_INS_MODES,
|
||||
|
||||
ASMIM_IMMEDIATE_ADDRESS
|
||||
ASMIM_IMMEDIATE_ADDRESS,
|
||||
|
||||
NUM_ASM_INS_MODES_X,
|
||||
};
|
||||
|
||||
struct AsmInsData
|
||||
|
@ -45,6 +47,8 @@ extern AsmInsData DecInsData[256];
|
|||
|
||||
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];
|
||||
|
||||
AsmInsType FindAsmInstruction(const char * ins);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
class BitVector
|
||||
{
|
||||
|
|
|
@ -144,8 +144,8 @@ static const char* ByteCodeNames[] = {
|
|||
"LOOP_U8",
|
||||
"MALLOC",
|
||||
"FREE",
|
||||
nullptr,
|
||||
nullptr,
|
||||
"FILL",
|
||||
"FILL_LONG",
|
||||
nullptr,
|
||||
|
||||
"JSR", //114
|
||||
|
@ -623,6 +623,10 @@ bool ByteCodeInstruction::CheckAccuSize(uint32 & used)
|
|||
case BC_OP_CEIL_F32:
|
||||
case BC_CONV_F32_U16:
|
||||
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;
|
||||
break;
|
||||
|
||||
|
@ -680,6 +684,8 @@ bool ByteCodeInstruction::CheckAccuSize(uint32 & used)
|
|||
used = 0xffffffff;
|
||||
break;
|
||||
|
||||
case BC_FILL:
|
||||
case BC_FILL_LONG:
|
||||
case BC_COPY:
|
||||
case BC_COPY_LONG:
|
||||
case BC_STRCPY:
|
||||
|
@ -780,7 +786,7 @@ bool ByteCodeInstruction::UsesRegister(uint32 reg) const
|
|||
return true;
|
||||
if (mCode == BC_LEA_ACCU_INDEX)
|
||||
return true;
|
||||
if (mCode == BC_COPY || mCode == BC_STRCPY)
|
||||
if (mCode == BC_COPY || mCode == BC_STRCPY || mCode == BC_FILL)
|
||||
return true;
|
||||
if (mCode == BC_BINOP_ADDA_16)
|
||||
return true;
|
||||
|
@ -793,7 +799,7 @@ bool ByteCodeInstruction::UsesRegister(uint32 reg) const
|
|||
if (mCode >= BC_LOAD_ADDR_8 && mCode <= BC_STORE_ADDR_32)
|
||||
return true;
|
||||
|
||||
if (mCode == BC_COPY || mCode == BC_STRCPY)
|
||||
if (mCode == BC_COPY || mCode == BC_STRCPY || mCode == BC_FILL)
|
||||
return true;
|
||||
|
||||
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);
|
||||
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_LONG:
|
||||
if (mValue < 256)
|
||||
|
@ -1262,6 +1282,23 @@ void ByteCodeInstruction::Assemble(ByteCodeGenerator* generator, ByteCodeBasicBl
|
|||
block->PutByte(mRegister);
|
||||
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:
|
||||
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)
|
||||
{
|
||||
LoadOperandAddress(proc, ins->mSrc[0], BC_REG_ACCU);
|
||||
|
@ -3401,94 +3462,151 @@ ByteCode ByteCodeBasicBlock::RelationalOperator(InterCodeProcedure* proc, const
|
|||
{
|
||||
if (ins->mSrc[1].mTemp < 0)
|
||||
{
|
||||
ByteCodeInstruction lins(BC_LOAD_REG_16);
|
||||
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
||||
lins.mRegisterFinal = ins->mSrc[0].mFinal;
|
||||
mIns.Push(lins);
|
||||
if (csigned)
|
||||
if (ins->mSrc[1].mType == IT_INT16 || ins->mSrc[1].mMemory == IM_ABSOLUTE)
|
||||
{
|
||||
ByteCodeInstruction cins(BC_BINOP_CMPSI_16);
|
||||
cins.mValue = int(ins->mSrc[1].mIntConst);
|
||||
mIns.Push(cins);
|
||||
}
|
||||
else
|
||||
{
|
||||
ByteCodeInstruction cins(BC_BINOP_CMPUI_16);
|
||||
cins.mValue = int(ins->mSrc[1].mIntConst);
|
||||
mIns.Push(cins);
|
||||
}
|
||||
}
|
||||
else if (ins->mSrc[0].mTemp < 0)
|
||||
{
|
||||
ByteCodeInstruction lins(BC_LOAD_REG_16);
|
||||
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
||||
lins.mRegisterFinal = ins->mSrc[1].mFinal;
|
||||
mIns.Push(lins);
|
||||
if (csigned)
|
||||
{
|
||||
if (optzero && ins->mSrc[0].mIntConst == 0)
|
||||
{
|
||||
switch (ins->mOperator)
|
||||
{
|
||||
case IA_CMPEQ:
|
||||
return BC_BRANCHS_EQ;
|
||||
case IA_CMPNE:
|
||||
return BC_BRANCHS_NE;
|
||||
case IA_CMPLES:
|
||||
return BC_BRANCHS_LE;
|
||||
case IA_CMPGS:
|
||||
return BC_BRANCHS_GT;
|
||||
case IA_CMPGES:
|
||||
return BC_BRANCHS_GE;
|
||||
case IA_CMPLS:
|
||||
return BC_BRANCHS_LT;
|
||||
}
|
||||
}
|
||||
else if (ins->mSrc[1].IsUByte())
|
||||
{
|
||||
ByteCodeInstruction cins(BC_BINOP_CMPUI_8);
|
||||
cins.mValue = int(ins->mSrc[0].mIntConst);
|
||||
mIns.Push(cins);
|
||||
}
|
||||
else
|
||||
ByteCodeInstruction lins(BC_LOAD_REG_16);
|
||||
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[0].mTemp];
|
||||
lins.mRegisterFinal = ins->mSrc[0].mFinal;
|
||||
mIns.Push(lins);
|
||||
|
||||
if (csigned)
|
||||
{
|
||||
ByteCodeInstruction cins(BC_BINOP_CMPSI_16);
|
||||
cins.mValue = int(ins->mSrc[0].mIntConst);
|
||||
mIns.Push(cins);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (optzero && ins->mSrc[0].mIntConst == 0)
|
||||
{
|
||||
switch (ins->mOperator)
|
||||
{
|
||||
case IA_CMPEQ:
|
||||
case IA_CMPLEU:
|
||||
return BC_BRANCHS_EQ;
|
||||
case IA_CMPNE:
|
||||
case IA_CMPGU:
|
||||
return BC_BRANCHS_NE;
|
||||
case IA_CMPGEU:
|
||||
return BC_JUMPS;
|
||||
case IA_CMPLU:
|
||||
return BC_NOP;
|
||||
}
|
||||
}
|
||||
else if (ins->mSrc[1].IsUByte())
|
||||
{
|
||||
ByteCodeInstruction cins(BC_BINOP_CMPUI_8);
|
||||
cins.mValue = int(ins->mSrc[0].mIntConst);
|
||||
cins.mValue = int(ins->mSrc[1].mIntConst);
|
||||
mIns.Push(cins);
|
||||
}
|
||||
else
|
||||
{
|
||||
ByteCodeInstruction cins(BC_BINOP_CMPUI_16);
|
||||
cins.mValue = int(ins->mSrc[0].mIntConst);
|
||||
cins.mValue = int(ins->mSrc[1].mIntConst);
|
||||
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)
|
||||
{
|
||||
if (ins->mSrc[0].mType == IT_INT16 || ins->mSrc[0].mMemory == IM_ABSOLUTE)
|
||||
{
|
||||
ByteCodeInstruction lins(BC_LOAD_REG_16);
|
||||
lins.mRegister = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
|
||||
lins.mRegisterFinal = ins->mSrc[1].mFinal;
|
||||
mIns.Push(lins);
|
||||
if (csigned)
|
||||
{
|
||||
if (optzero && ins->mSrc[0].mIntConst == 0)
|
||||
{
|
||||
switch (ins->mOperator)
|
||||
{
|
||||
case IA_CMPEQ:
|
||||
return BC_BRANCHS_EQ;
|
||||
case IA_CMPNE:
|
||||
return BC_BRANCHS_NE;
|
||||
case IA_CMPLES:
|
||||
return BC_BRANCHS_LE;
|
||||
case IA_CMPGS:
|
||||
return BC_BRANCHS_GT;
|
||||
case IA_CMPGES:
|
||||
return BC_BRANCHS_GE;
|
||||
case IA_CMPLS:
|
||||
return BC_BRANCHS_LT;
|
||||
}
|
||||
}
|
||||
else if (ins->mSrc[1].IsUByte())
|
||||
{
|
||||
ByteCodeInstruction cins(BC_BINOP_CMPUI_8);
|
||||
cins.mValue = int(ins->mSrc[0].mIntConst);
|
||||
mIns.Push(cins);
|
||||
}
|
||||
else
|
||||
{
|
||||
ByteCodeInstruction cins(BC_BINOP_CMPSI_16);
|
||||
cins.mValue = int(ins->mSrc[0].mIntConst);
|
||||
mIns.Push(cins);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (optzero && ins->mSrc[0].mIntConst == 0)
|
||||
{
|
||||
switch (ins->mOperator)
|
||||
{
|
||||
case IA_CMPEQ:
|
||||
case IA_CMPLEU:
|
||||
return BC_BRANCHS_EQ;
|
||||
case IA_CMPNE:
|
||||
case IA_CMPGU:
|
||||
return BC_BRANCHS_NE;
|
||||
case IA_CMPGEU:
|
||||
return BC_JUMPS;
|
||||
case IA_CMPLU:
|
||||
return BC_NOP;
|
||||
}
|
||||
}
|
||||
else if (ins->mSrc[1].IsUByte())
|
||||
{
|
||||
ByteCodeInstruction cins(BC_BINOP_CMPUI_8);
|
||||
cins.mValue = int(ins->mSrc[0].mIntConst);
|
||||
mIns.Push(cins);
|
||||
}
|
||||
else
|
||||
{
|
||||
ByteCodeInstruction cins(BC_BINOP_CMPUI_16);
|
||||
cins.mValue = int(ins->mSrc[0].mIntConst);
|
||||
mIns.Push(cins);
|
||||
}
|
||||
}
|
||||
code = TransposeBranchCondition(code);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
code = TransposeBranchCondition(code);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3681,6 +3799,67 @@ void ByteCodeBasicBlock::NumericConversion(InterCodeProcedure* proc, const Inter
|
|||
|
||||
} 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:
|
||||
{
|
||||
if (ins->mSrc[0].mTemp == ins->mDst.mTemp)
|
||||
|
@ -4320,6 +4499,9 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p
|
|||
else
|
||||
LoadDirectValue(iproc, ins);
|
||||
break;
|
||||
case IC_FILL:
|
||||
FillValue(iproc, ins);
|
||||
break;
|
||||
case IC_COPY:
|
||||
CopyValue(iproc, ins);
|
||||
break;
|
||||
|
@ -6423,7 +6605,7 @@ void ByteCodeProcedure::Compile(ByteCodeGenerator* generator, InterCodeProcedure
|
|||
{
|
||||
mID = proc->mID;
|
||||
|
||||
mNumBlocks = proc->mBlocks.Size();
|
||||
mNumBlocks = proc->mNumBlocks;
|
||||
|
||||
tblocks = new ByteCodeBasicBlock * [mNumBlocks];
|
||||
for (int i = 0; i < mNumBlocks; i++)
|
||||
|
|
|
@ -145,8 +145,8 @@ enum ByteCode
|
|||
BC_LOOP_U8,
|
||||
BC_MALLOC,
|
||||
BC_FREE,
|
||||
BC_UNUSED_4,
|
||||
BC_UNUSED_5,
|
||||
BC_FILL,
|
||||
BC_FILL_LONG,
|
||||
BC_UNUSED_6,
|
||||
|
||||
BC_JSR,
|
||||
|
@ -186,7 +186,12 @@ enum ByteCode
|
|||
BC_BINOP_SHR_U32,
|
||||
BC_BINOP_SHR_I32,
|
||||
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;
|
||||
|
@ -281,6 +286,7 @@ public:
|
|||
void IntConstToAddr(int64 val);
|
||||
void FloatConstToAccu(double val);
|
||||
void FloatConstToWork(double val);
|
||||
void FillValue(InterCodeProcedure* proc, const InterInstruction* ins);
|
||||
void CopyValue(InterCodeProcedure* proc, const InterInstruction * ins);
|
||||
void StrcpyValue(InterCodeProcedure* proc, const InterInstruction* ins);
|
||||
void CallMalloc(InterCodeProcedure* proc, const InterInstruction* ins);
|
||||
|
|
|
@ -174,13 +174,13 @@ void Compiler::RegisterRuntime(const Location & loc, const Ident* ident)
|
|||
if (bcdec->mType == DT_CONST_ASSEMBLER)
|
||||
{
|
||||
if (!bcdec->mLinkerObject)
|
||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr);
|
||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec, nullptr);
|
||||
linkerObject = bcdec->mLinkerObject;
|
||||
}
|
||||
else if (bcdec->mType == DT_LABEL)
|
||||
{
|
||||
if (!bcdec->mBase->mLinkerObject)
|
||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue, nullptr);
|
||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase, nullptr);
|
||||
|
||||
linkerObject = bcdec->mBase->mLinkerObject;
|
||||
offset = int(bcdec->mInteger);
|
||||
|
@ -466,7 +466,7 @@ void Compiler::CompileProcedure(InterCodeProcedure* proc)
|
|||
printf("Generate native code <%s>\n", proc->mIdent->mString);
|
||||
|
||||
ncproc->Compile(proc);
|
||||
mNativeProcedures.Push(ncproc);
|
||||
mNativeCodeGenerator->mProcedures.Push(ncproc);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -508,6 +508,8 @@ bool Compiler::GenerateCode(void)
|
|||
regionZeroPage = mLinker->AddRegion(identZeroPage, 0x00e0, 0x00ff);
|
||||
else if (mCompilerOptions & (COPT_EXTENDED_ZERO_PAGE | COPT_TARGET_NES))
|
||||
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
|
||||
regionZeroPage = mLinker->AddRegion(identZeroPage, 0x00f7, 0x00ff);
|
||||
}
|
||||
|
@ -521,6 +523,12 @@ bool Compiler::GenerateCode(void)
|
|||
{
|
||||
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_X16:
|
||||
if (mCompilerOptions & COPT_NATIVE)
|
||||
|
@ -552,12 +560,12 @@ bool Compiler::GenerateCode(void)
|
|||
if (mCompilerOptions & COPT_NATIVE)
|
||||
{
|
||||
regionStartup = mLinker->AddRegion(identStartup, 0x1001, 0x1080);
|
||||
regionLowcode = mLinker->AddRegion(identLowcode, 0x1080, 0x1100);
|
||||
regionLowcode = mLinker->AddRegion(identLowcode, 0x1080, 0x1180);
|
||||
}
|
||||
else
|
||||
{
|
||||
regionStartup = mLinker->AddRegion(identStartup, 0x1001, 0x1080);
|
||||
regionLowcode = mLinker->AddRegion(identLowcode, 0x1080, 0x1000);
|
||||
regionLowcode = mLinker->AddRegion(identLowcode, 0x1080, 0x1180);
|
||||
}
|
||||
regionLowcode->mSections.Push(mCompilationUnits->mSectionLowCode);
|
||||
break;
|
||||
|
@ -623,6 +631,9 @@ bool Compiler::GenerateCode(void)
|
|||
{
|
||||
switch (mTargetMachine)
|
||||
{
|
||||
case TMACH_MEGA65:
|
||||
regionBytecode = mLinker->AddRegion(identBytecode, 0x2100, 0x2200);
|
||||
break;
|
||||
case TMACH_C64:
|
||||
case TMACH_X16:
|
||||
regionBytecode = mLinker->AddRegion(identBytecode, 0x0900, 0x0a00);
|
||||
|
@ -633,6 +644,8 @@ bool Compiler::GenerateCode(void)
|
|||
regionBytecode = mLinker->AddRegion(identBytecode, 0x1d00, 0x1e00);
|
||||
break;
|
||||
case TMACH_PLUS4:
|
||||
regionBytecode = mLinker->AddRegion(identBytecode, 0x1200, 0x1300);
|
||||
break;
|
||||
case TMACH_VIC20:
|
||||
regionBytecode = mLinker->AddRegion(identBytecode, 0x1100, 0x1200);
|
||||
break;
|
||||
|
@ -682,6 +695,9 @@ bool Compiler::GenerateCode(void)
|
|||
{
|
||||
switch (mTargetMachine)
|
||||
{
|
||||
case TMACH_MEGA65:
|
||||
regionMain = mLinker->AddRegion(identMain, 0x2300, 0xc000);
|
||||
break;
|
||||
case TMACH_C64:
|
||||
regionMain = mLinker->AddRegion(identMain, 0x0a00, 0xa000);
|
||||
break;
|
||||
|
@ -698,7 +714,7 @@ bool Compiler::GenerateCode(void)
|
|||
regionMain = mLinker->AddRegion(identMain, 0x1e00, 0xc000);
|
||||
break;
|
||||
case TMACH_PLUS4:
|
||||
regionMain = mLinker->AddRegion(identMain, 0x1200, 0xfc00);
|
||||
regionMain = mLinker->AddRegion(identMain, 0x1300, 0xfc00);
|
||||
break;
|
||||
case TMACH_VIC20:
|
||||
regionMain = mLinker->AddRegion(identMain, 0x1200, 0x1e00);
|
||||
|
@ -733,6 +749,14 @@ bool Compiler::GenerateCode(void)
|
|||
{
|
||||
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:
|
||||
|
||||
if (mCompilerOptions & (COPT_TARGET_CRT8 | COPT_TARGET_CRT16))
|
||||
|
@ -753,7 +777,7 @@ bool Compiler::GenerateCode(void)
|
|||
regionMain = mLinker->AddRegion(identMain, 0x1c80, 0xc000);
|
||||
break;
|
||||
case TMACH_PLUS4:
|
||||
regionMain = mLinker->AddRegion(identMain, 0x1100, 0xfc00);
|
||||
regionMain = mLinker->AddRegion(identMain, 0x1180, 0xfc00);
|
||||
break;
|
||||
case TMACH_VIC20:
|
||||
regionMain = mLinker->AddRegion(identMain, 0x1080, 0x1e00);
|
||||
|
@ -908,7 +932,7 @@ bool Compiler::GenerateCode(void)
|
|||
if (mCompilerOptions & COPT_VERBOSE)
|
||||
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++)
|
||||
{
|
||||
Declaration* dec = mCompilationUnits->mReferenced[i];
|
||||
|
@ -917,13 +941,19 @@ bool Compiler::GenerateCode(void)
|
|||
if (!dec->mLinkerObject)
|
||||
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)
|
||||
mInterCodeGenerator->InitGlobalVariable(mInterCodeModule, dec);
|
||||
}
|
||||
}
|
||||
|
||||
mInterCodeGenerator->CompleteMainInit();
|
||||
|
||||
if (mErrors->mErrorCount != 0)
|
||||
return false;
|
||||
|
||||
|
@ -935,7 +965,8 @@ bool Compiler::GenerateCode(void)
|
|||
RegisterRuntime(loc, Ident::Unique("fsplitt"));
|
||||
RegisterRuntime(loc, Ident::Unique("fsplitx"));
|
||||
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("fdiv"));
|
||||
RegisterRuntime(loc, Ident::Unique("mul16"));
|
||||
|
@ -948,8 +979,12 @@ bool Compiler::GenerateCode(void)
|
|||
RegisterRuntime(loc, Ident::Unique("fceil"));
|
||||
RegisterRuntime(loc, Ident::Unique("ftoi"));
|
||||
RegisterRuntime(loc, Ident::Unique("ftou"));
|
||||
RegisterRuntime(loc, Ident::Unique("ftoli"));
|
||||
RegisterRuntime(loc, Ident::Unique("ftolu"));
|
||||
RegisterRuntime(loc, Ident::Unique("ffromi"));
|
||||
RegisterRuntime(loc, Ident::Unique("ffromu"));
|
||||
RegisterRuntime(loc, Ident::Unique("ffromli"));
|
||||
RegisterRuntime(loc, Ident::Unique("ffromlu"));
|
||||
RegisterRuntime(loc, Ident::Unique("fcmp"));
|
||||
RegisterRuntime(loc, Ident::Unique("bcexec"));
|
||||
RegisterRuntime(loc, Ident::Unique("jmpaddr"));
|
||||
|
@ -959,8 +994,12 @@ bool Compiler::GenerateCode(void)
|
|||
RegisterRuntime(loc, Ident::Unique("divu32"));
|
||||
RegisterRuntime(loc, Ident::Unique("modu32"));
|
||||
|
||||
RegisterRuntime(loc, Ident::Unique("store32"));
|
||||
RegisterRuntime(loc, Ident::Unique("load32"));
|
||||
|
||||
RegisterRuntime(loc, Ident::Unique("malloc"));
|
||||
RegisterRuntime(loc, Ident::Unique("free"));
|
||||
RegisterRuntime(loc, Ident::Unique("breakpoint"));
|
||||
}
|
||||
|
||||
// Register extended byte code functions
|
||||
|
@ -976,7 +1015,7 @@ bool Compiler::GenerateCode(void)
|
|||
if (bcdec->mType == DT_CONST_ASSEMBLER)
|
||||
{
|
||||
if (!bcdec->mLinkerObject)
|
||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr);
|
||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec, nullptr);
|
||||
mByteCodeGenerator->mExtByteCodes[i] = bcdec->mLinkerObject;
|
||||
}
|
||||
}
|
||||
|
@ -1019,13 +1058,18 @@ bool Compiler::GenerateCode(void)
|
|||
mCompilationUnits->mSectionStack->mSections.Push(proc->mLinkerObject->mStackSection);
|
||||
}
|
||||
|
||||
mNativeCodeGenerator->OutlineFunctions();
|
||||
|
||||
mNativeCodeGenerator->BuildFunctionProxies();
|
||||
|
||||
for (int i = 0; i < mNativeProcedures.Size(); i++)
|
||||
for (int i = 0; i < mNativeCodeGenerator->mProcedures.Size(); i++)
|
||||
{
|
||||
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;
|
||||
|
@ -1051,13 +1095,13 @@ bool Compiler::GenerateCode(void)
|
|||
if (bcdec->mType == DT_CONST_ASSEMBLER)
|
||||
{
|
||||
if (!bcdec->mLinkerObject)
|
||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mValue, nullptr);
|
||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec, nullptr);
|
||||
linkerObject = bcdec->mLinkerObject;
|
||||
}
|
||||
else if (bcdec->mType == DT_LABEL)
|
||||
{
|
||||
if (!bcdec->mBase->mLinkerObject)
|
||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase->mValue, nullptr);
|
||||
mInterCodeGenerator->TranslateAssembler(mInterCodeModule, bcdec->mBase, nullptr);
|
||||
linkerObject = bcdec->mBase->mLinkerObject;
|
||||
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)
|
||||
{
|
||||
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];
|
||||
|
||||
strcpy_s(basePath, targetPath);
|
||||
|
@ -1200,6 +1320,7 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
|
|||
strcpy_s(intPath, prgPath);
|
||||
strcpy_s(bcsPath, prgPath);
|
||||
strcpy_s(dbjPath, prgPath);
|
||||
strcpy_s(cszPath, prgPath);
|
||||
|
||||
strcat_s(mapPath, "map");
|
||||
strcat_s(asmPath, "asm");
|
||||
|
@ -1207,6 +1328,7 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
|
|||
strcat_s(intPath, "int");
|
||||
strcat_s(bcsPath, "bcs");
|
||||
strcat_s(dbjPath, "dbj");
|
||||
strcat_s(cszPath, "csz");
|
||||
|
||||
if (mCompilerOptions & COPT_TARGET_PRG)
|
||||
{
|
||||
|
@ -1289,6 +1411,9 @@ bool Compiler::WriteOutputFile(const char* targetPath, DiskImage * d64)
|
|||
if (mCompilerOptions & COPT_DEBUGINFO)
|
||||
WriteDbjFile(dbjPath);
|
||||
|
||||
if (mCompilerOptions & COPT_PROFILEINFO)
|
||||
WriteCszFile(cszPath);
|
||||
|
||||
if (!(mCompilerOptions & COPT_NATIVE))
|
||||
{
|
||||
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)
|
||||
{
|
||||
FILE* file;
|
||||
|
|
|
@ -29,7 +29,6 @@ public:
|
|||
GlobalOptimizer* mGlobalOptimizer;
|
||||
|
||||
GrowingArray<ByteCodeProcedure*> mByteCodeFunctions;
|
||||
ExpandingArray<NativeCodeProcedure*> mNativeProcedures;
|
||||
|
||||
TargetMachine mTargetMachine;
|
||||
uint64 mCompilerOptions;
|
||||
|
@ -48,6 +47,8 @@ public:
|
|||
bool ParseSource(void);
|
||||
bool GenerateCode(void);
|
||||
bool WriteOutputFile(const char* targetPath, DiskImage * d64);
|
||||
bool WriteErrorFile(const char* targetPath);
|
||||
bool RemoveErrorFile(const char* targetPath);
|
||||
int ExecuteCode(bool profile, int trace);
|
||||
|
||||
void AddDefine(const Ident* ident, const char* value);
|
||||
|
@ -59,4 +60,5 @@ public:
|
|||
void CompleteTemplateExpansion(void);
|
||||
|
||||
bool WriteDbjFile(const char* filename);
|
||||
bool WriteCszFile(const char* filename);
|
||||
};
|
||||
|
|
|
@ -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_MERGE_CALLS = 1ULL << 10;
|
||||
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_NATIVE = 1ULL << 17;
|
||||
|
@ -39,6 +41,10 @@ static const uint64 COPT_DEBUGINFO = 1ULL << 51;
|
|||
|
||||
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;
|
||||
|
||||
|
||||
|
||||
|
@ -46,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_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;
|
||||
|
||||
|
@ -73,7 +79,8 @@ enum TargetMachine
|
|||
TMACH_NES_MMC1,
|
||||
TMACH_NES_MMC3,
|
||||
TMACH_ATARI,
|
||||
TMACH_X16
|
||||
TMACH_X16,
|
||||
TMACH_MEGA65
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ int CompressLZO(uint8* dst, const uint8* source, int size)
|
|||
while (pi < 127 && pos < size)
|
||||
{
|
||||
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;
|
||||
while (j < 127 && pos + j < size && source[pos - i + j] == source[pos + j])
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include <math.h>
|
||||
|
||||
ConstexprInterpreter::Value::Value(void)
|
||||
: mDecType(TheVoidTypeDeclaration),
|
||||
: mDecType(TheVoidTypeDeclaration), mDecValue(nullptr),
|
||||
mBaseValue(nullptr), mOffset(0),
|
||||
mData(mShortData), mDataSize(0)
|
||||
{
|
||||
|
@ -10,7 +10,7 @@ ConstexprInterpreter::Value::Value(void)
|
|||
|
||||
ConstexprInterpreter::Value::Value(const Location & location)
|
||||
: mLocation(location),
|
||||
mDecType(TheVoidTypeDeclaration),
|
||||
mDecType(TheVoidTypeDeclaration), mDecValue(nullptr),
|
||||
mBaseValue(nullptr), mOffset(0),
|
||||
mData(mShortData), mDataSize(0)
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ ConstexprInterpreter::Value::Value(const Location & location)
|
|||
|
||||
ConstexprInterpreter::Value::Value(Expression* exp)
|
||||
: mLocation(exp->mLocation),
|
||||
mDecType(exp->mDecType),
|
||||
mDecType(exp->mDecType), mDecValue(nullptr),
|
||||
mBaseValue(nullptr), mOffset(0),
|
||||
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++)
|
||||
PutIntAt(dec->mData[i], offset + i, TheConstCharTypeDeclaration);
|
||||
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)
|
||||
: mLocation(location),
|
||||
mDecType(dec),
|
||||
mDecType(dec), mDecValue(nullptr),
|
||||
mBaseValue(nullptr), mOffset(0),
|
||||
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)
|
||||
: mLocation(location),
|
||||
mDecType(dec),
|
||||
mDecType(dec), mDecValue(nullptr),
|
||||
mBaseValue(nullptr), mOffset(0),
|
||||
mDataSize(size)
|
||||
{
|
||||
|
@ -80,7 +83,7 @@ ConstexprInterpreter::Value::Value(const Location& location, Declaration* dec, i
|
|||
|
||||
ConstexprInterpreter::Value::Value(const Value& value)
|
||||
: mLocation(value.mLocation),
|
||||
mDecType(value.mDecType),
|
||||
mDecType(value.mDecType), mDecValue(nullptr),
|
||||
mBaseValue(value.mBaseValue), mOffset(value.mOffset),
|
||||
mDataSize(value.mDataSize)
|
||||
|
||||
|
@ -96,7 +99,7 @@ ConstexprInterpreter::Value::Value(const Value& value)
|
|||
|
||||
ConstexprInterpreter::Value::Value(Value&& value)
|
||||
: mLocation(value.mLocation),
|
||||
mDecType(value.mDecType),
|
||||
mDecType(value.mDecType), mDecValue(nullptr),
|
||||
mBaseValue(value.mBaseValue), mOffset(value.mOffset),
|
||||
mDataSize(value.mDataSize)
|
||||
{
|
||||
|
@ -115,7 +118,7 @@ ConstexprInterpreter::Value::Value(Value&& value)
|
|||
|
||||
ConstexprInterpreter::Value::Value(Value* value)
|
||||
: mLocation(value->mLocation),
|
||||
mDecType(value->mDecType),
|
||||
mDecType(value->mDecType), mDecValue(value->mDecValue),
|
||||
mBaseValue(value), mOffset(0),
|
||||
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)
|
||||
: mLocation(location),
|
||||
mDecType(type),
|
||||
mDecType(type), mDecValue(nullptr),
|
||||
mBaseValue(value), mOffset(offset),
|
||||
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)
|
||||
: mLocation(location),
|
||||
mDecType(type),
|
||||
mDecType(type), mDecValue(nullptr),
|
||||
mBaseValue(nullptr), mOffset(0),
|
||||
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)
|
||||
: mLocation(location),
|
||||
mDecType(type),
|
||||
mDecType(type), mDecValue(nullptr),
|
||||
mBaseValue(nullptr), mOffset(0),
|
||||
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)));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (type->mType == DT_TYPE_FLOAT)
|
||||
|
@ -499,7 +518,10 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type
|
|||
for (int i=0; i<type->mSize; i += type->mBase->mSize)
|
||||
{
|
||||
Declaration* cdec = GetConst(offset + i, type->mBase, dataSection);
|
||||
cdec->mOffset = i;
|
||||
if (type->mStride)
|
||||
cdec->mOffset = i / type->mBase->mSize;
|
||||
else
|
||||
cdec->mOffset = i;
|
||||
|
||||
if (ldec)
|
||||
ldec->mNext = cdec;
|
||||
|
@ -521,7 +543,26 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type
|
|||
|
||||
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->mSize = vp.mBaseValue->mDataSize;
|
||||
|
@ -540,6 +581,14 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type
|
|||
dec->mValue->mDecType = target->mBase;
|
||||
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
|
||||
{
|
||||
dec = new Declaration(mLocation, DT_CONST_ADDRESS);
|
||||
|
@ -602,6 +651,7 @@ Expression* ConstexprInterpreter::EvalConstructor(Expression* exp)
|
|||
{
|
||||
mProcType = exp->mLeft->mDecType;
|
||||
|
||||
Expression* pex = exp->mRight;
|
||||
Declaration* cdec = exp->mLeft->mDecType->mParams;
|
||||
|
||||
int pos = 0;
|
||||
|
@ -610,6 +660,28 @@ Expression* ConstexprInterpreter::EvalConstructor(Expression* exp)
|
|||
mParams[pos].PutPtr(Value(&mResult));
|
||||
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*>();
|
||||
|
||||
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);
|
||||
if (pex->mDecValue->mSize > 0)
|
||||
mParams[pos].PutConst(0, pex->mDecValue->mValue->mDecValue);
|
||||
{
|
||||
if (pex->mDecValue->mValue)
|
||||
mParams[pos].PutConst(0, pex->mDecValue->mValue->mDecValue);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
@ -700,6 +777,9 @@ bool ConstexprInterpreter::AddParam(int& pos, Expression* pex, Declaration* dec)
|
|||
|
||||
Expression* ConstexprInterpreter::EvalCall(Expression* exp)
|
||||
{
|
||||
if (!exp->mLeft->mDecValue || !exp->mLeft->mDecValue->mValue)
|
||||
return exp;
|
||||
|
||||
mProcType = exp->mLeft->mDecType;
|
||||
|
||||
Expression* pex = exp->mRight;
|
||||
|
@ -966,6 +1046,9 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalUnary(Expression* exp, con
|
|||
break;
|
||||
case TK_MUL:
|
||||
return vl.GetPtr();
|
||||
case TK_SIZEOF:
|
||||
v.PutInt(vl.mDecType->mSize);
|
||||
break;
|
||||
default:
|
||||
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]);
|
||||
}
|
||||
|
@ -1104,6 +1187,36 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons
|
|||
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
|
||||
mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname);
|
||||
}
|
||||
|
|
|
@ -19,8 +19,8 @@ protected:
|
|||
|
||||
struct ValueItem
|
||||
{
|
||||
uint8 mByte;
|
||||
Value* mBaseValue;
|
||||
uint8 mByte;
|
||||
Value * mBaseValue;
|
||||
|
||||
ValueItem(void);
|
||||
};
|
||||
|
@ -35,6 +35,7 @@ protected:
|
|||
Value(const Value& value);
|
||||
Value(Value&& value);
|
||||
Value(const Location& location, Value * value, Declaration * type, int offset);
|
||||
Value(const Location& location, Declaration * value, Declaration* type, int offset);
|
||||
Value(Value* value);
|
||||
Value(const Location& location, const uint8 * data, Declaration* type);
|
||||
Value(const Location& location, const ValueItem* data, Declaration* type);
|
||||
|
@ -48,7 +49,7 @@ protected:
|
|||
void Assign(const Value& v);
|
||||
|
||||
Location mLocation;
|
||||
Declaration * mDecType;
|
||||
Declaration * mDecType, * mDecValue;
|
||||
Value * mBaseValue;
|
||||
int mOffset;
|
||||
ValueItem * mData;
|
||||
|
@ -71,6 +72,7 @@ protected:
|
|||
void PutIntAt(int64 v, int at, Declaration* type);
|
||||
void PutFloatAt(double 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);
|
||||
Declaration* GetConst(int offset, Declaration* type, LinkerSection* dataSection) const;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -47,6 +47,7 @@ enum DecType
|
|||
DT_PACK_VARIABLE,
|
||||
DT_PACK_ARGUMENT,
|
||||
DT_PACK_TYPE,
|
||||
DT_PACK_ANON,
|
||||
|
||||
DT_VARIABLE,
|
||||
DT_ARGUMENT,
|
||||
|
@ -58,6 +59,7 @@ enum DecType
|
|||
DT_LABEL_REF,
|
||||
DT_NAMESPACE,
|
||||
DT_BASECLASS,
|
||||
DT_CLABEL,
|
||||
|
||||
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_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_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_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;
|
||||
|
@ -158,6 +167,8 @@ public:
|
|||
ScopeLevel mLevel;
|
||||
const Ident * mName;
|
||||
|
||||
DeclarationScope* Clone(void) const;
|
||||
|
||||
DeclarationScope* mParent;
|
||||
protected:
|
||||
struct Entry
|
||||
|
@ -207,6 +218,7 @@ enum ExpressionType
|
|||
EX_IF,
|
||||
EX_ELSE,
|
||||
EX_FOR,
|
||||
EX_FORBODY,
|
||||
EX_DO,
|
||||
EX_SCOPE,
|
||||
EX_BREAK,
|
||||
|
@ -229,14 +241,25 @@ enum ExpressionType
|
|||
EX_RESULT,
|
||||
EX_PACK,
|
||||
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
|
||||
{
|
||||
public:
|
||||
Expression(const Location& loc, ExpressionType type);
|
||||
~Expression(void);
|
||||
|
||||
uint32 mUID;
|
||||
|
||||
Location mLocation, mEndLocation;
|
||||
ExpressionType mType;
|
||||
Expression * mLeft, * mRight;
|
||||
|
@ -245,15 +268,23 @@ public:
|
|||
AsmInsType mAsmInsType;
|
||||
AsmInsMode mAsmInsMode;
|
||||
bool mConst;
|
||||
uint32 mFlags;
|
||||
|
||||
Expression* LogicInvertExpression(void);
|
||||
Expression* ConstantFold(Errors * errors, LinkerSection* dataSection, Linker * linker = nullptr);
|
||||
Expression* ConstantDereference(Errors* errors, LinkerSection* dataSection);
|
||||
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 IsRValue(void) const;
|
||||
bool IsLValue(void) const;
|
||||
bool IsConstRef(void) const;
|
||||
bool IsVolatile(void) const;
|
||||
|
||||
|
||||
void Dump(int ident) const;
|
||||
};
|
||||
|
@ -264,12 +295,14 @@ public:
|
|||
Declaration(const Location & loc, DecType type);
|
||||
~Declaration(void);
|
||||
|
||||
uint32 mUID;
|
||||
|
||||
Location mLocation, mEndLocation;
|
||||
DecType mType;
|
||||
Token mToken;
|
||||
Declaration * mBase, * mParams, * mParamPack, * mNext, * mPrev, * mConst, * mMutable, * mVolatile;
|
||||
Declaration * mDefaultConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment, * mMoveConstructor, * mMoveAssignment;
|
||||
Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment;
|
||||
Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment, * mVectorMoveConstructor, * mVectorMoveAssignment;
|
||||
Declaration * mVTable, * mClass, * mTemplate;
|
||||
Declaration * mForwardParam, * mForwardCall;
|
||||
|
||||
|
@ -296,6 +329,7 @@ public:
|
|||
bool IsSame(const Declaration* dec) const;
|
||||
bool IsDerivedFrom(const Declaration* dec) const;
|
||||
bool IsSubType(const Declaration* dec) const;
|
||||
bool IsConstRefSame(const Declaration* dec) const;
|
||||
bool IsConstSame(const Declaration* dec) const;
|
||||
bool IsSameValue(const Declaration* dec) const;
|
||||
bool IsSameParams(const Declaration* dec) const;
|
||||
|
@ -310,12 +344,17 @@ public:
|
|||
bool IsSimpleType(void) const;
|
||||
bool IsReference(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);
|
||||
|
||||
Declaration* ToConstType(void);
|
||||
Declaration* ToMutableType(void);
|
||||
Declaration* ToVolatileType(void);
|
||||
Declaration* ToAlternateThis(Declaration* pthis, int nthis = 1);
|
||||
|
||||
Declaration* ToStriped(int stripe);
|
||||
Declaration* ToStriped(Errors* errors);
|
||||
|
@ -339,8 +378,9 @@ public:
|
|||
DecType ValueType(void) const;
|
||||
|
||||
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 ResolveTemplateParameterList(Expression* pexp, Declaration* pdec, bool preliminary);
|
||||
|
||||
Declaration* ExpandTemplate(DeclarationScope* scope);
|
||||
|
||||
|
@ -357,6 +397,7 @@ extern Declaration* TheVoidTypeDeclaration, * TheConstVoidTypeDeclaration, * The
|
|||
extern Declaration* TheBoolTypeDeclaration, * TheFloatTypeDeclaration, * TheVoidPointerTypeDeclaration, * TheConstVoidPointerTypeDeclaration, * TheSignedLongTypeDeclaration, * TheUnsignedLongTypeDeclaration;
|
||||
extern Declaration* TheVoidFunctionTypeDeclaration, * TheConstVoidValueDeclaration;
|
||||
extern Declaration* TheCharPointerTypeDeclaration, * TheConstCharPointerTypeDeclaration;
|
||||
extern Declaration* TheNullptrConstDeclaration, * TheZeroIntegerConstDeclaration, * TheZeroFloatConstDeclaration;
|
||||
extern Declaration* TheNullptrConstDeclaration, * TheZeroIntegerConstDeclaration, * TheZeroFloatConstDeclaration, * TheNullPointerTypeDeclaration;
|
||||
extern Declaration* TheTrueConstDeclaration, * TheFalseConstDeclaration;
|
||||
extern Expression* TheVoidExpression;
|
||||
|
||||
|
|
|
@ -429,6 +429,10 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int bank
|
|||
i += 1;
|
||||
break;
|
||||
|
||||
case BC_FILL:
|
||||
fprintf(file, "FILL\t#%d", memory[start + i + 0]);
|
||||
i++;
|
||||
break;
|
||||
case BC_COPY:
|
||||
fprintf(file, "COPY\t#%d", memory[start + i + 0]);
|
||||
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]));
|
||||
i += 2;
|
||||
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:
|
||||
fprintf(file, "NEG\tACCU");
|
||||
|
@ -476,6 +484,19 @@ void ByteCodeDisassembler::Disassemble(FILE* file, const uint8* memory, int bank
|
|||
fprintf(file, "CNVFS\tACCU");
|
||||
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:
|
||||
fprintf(file, "MALLOC\tACCU");
|
||||
break;
|
||||
|
@ -825,7 +846,7 @@ const char* NativeCodeDisassembler::TempName(uint8 tmp, char* buffer, InterCodeP
|
|||
sprintf_s(buffer, 10, "ACCU + %d", tmp - BC_REG_ACCU);
|
||||
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);
|
||||
return buffer;
|
||||
|
|
|
@ -31,6 +31,8 @@ static char A2P(char ch)
|
|||
|
||||
DiskImage::DiskImage(const char* fname)
|
||||
{
|
||||
mInterleave = 10;
|
||||
|
||||
for (int i = 0; i < 41; i++)
|
||||
for (int j = 0; j < 21; j++)
|
||||
memset(mSectors[i][j], 0, 256);
|
||||
|
@ -104,7 +106,7 @@ int DiskImage::AllocBAMSector(int track, int sector)
|
|||
|
||||
if (dp[0] > 0)
|
||||
{
|
||||
sector += 4;
|
||||
sector += mInterleave;
|
||||
if (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;
|
||||
fopen_s(&file, fname, "rb");
|
||||
if (file)
|
||||
|
|
|
@ -14,7 +14,7 @@ public:
|
|||
void CloseFile(void);
|
||||
|
||||
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:
|
||||
uint8 mSectors[41][21][256];
|
||||
|
@ -24,6 +24,6 @@ protected:
|
|||
int AllocBAMTrack(int track);
|
||||
|
||||
uint8 * mDirEntry;
|
||||
int mTrack, mSector, mBytes;
|
||||
int mTrack, mSector, mBytes, mInterleave;
|
||||
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -134,12 +134,14 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
|
|||
|
||||
mRegA = (t & 255);
|
||||
UpdateStatusCarry(mRegA, t >= 256);
|
||||
if (cross) cycles++;
|
||||
break;
|
||||
case ASMIT_AND:
|
||||
if (mode != ASMIM_IMMEDIATE)
|
||||
addr = mMemory[addr];
|
||||
mRegA &= addr;
|
||||
UpdateStatus(mRegA);
|
||||
if (cross) cycles++;
|
||||
break;
|
||||
case ASMIT_ASL:
|
||||
if (mode == ASMIM_IMPLIED)
|
||||
|
@ -154,19 +156,29 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
|
|||
mMemory[addr] = t & 255;
|
||||
UpdateStatusCarry(t & 255, t >= 256);
|
||||
cycles += 2;
|
||||
if (indexed) cycles++;
|
||||
}
|
||||
break;
|
||||
case ASMIT_BCC:
|
||||
if (!(mRegP & STATUS_CARRY))
|
||||
{
|
||||
mIP = addr;
|
||||
cycles++;
|
||||
}
|
||||
break;
|
||||
case ASMIT_BCS:
|
||||
if ((mRegP & STATUS_CARRY))
|
||||
{
|
||||
mIP = addr;
|
||||
cycles++;
|
||||
}
|
||||
break;
|
||||
case ASMIT_BEQ:
|
||||
if ((mRegP & STATUS_ZERO))
|
||||
{
|
||||
mIP = addr;
|
||||
cycles++;
|
||||
}
|
||||
break;
|
||||
case ASMIT_BIT:
|
||||
t = mMemory[addr];
|
||||
|
@ -235,6 +247,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
|
|||
mRegP |= STATUS_OVERFLOW;
|
||||
|
||||
UpdateStatusCarry(t & 255, t >= 256);
|
||||
if (cross) cycles++;
|
||||
break;
|
||||
case ASMIT_CPX:
|
||||
if (mode != ASMIM_IMMEDIATE)
|
||||
|
@ -275,6 +288,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
|
|||
mMemory[addr] = t & 255;
|
||||
UpdateStatus(t & 255);
|
||||
cycles += 2;
|
||||
if (indexed) cycles++;
|
||||
}
|
||||
break;
|
||||
case ASMIT_DEX:
|
||||
|
@ -292,6 +306,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
|
|||
addr = mMemory[addr];
|
||||
mRegA ^= addr;
|
||||
UpdateStatus(mRegA);
|
||||
if (cross) cycles++;
|
||||
break;
|
||||
case ASMIT_INC:
|
||||
if (mode == ASMIM_IMPLIED)
|
||||
|
@ -306,6 +321,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
|
|||
mMemory[addr] = t & 255;
|
||||
UpdateStatus(t & 255);
|
||||
cycles += 2;
|
||||
if (indexed) cycles++;
|
||||
}
|
||||
break;
|
||||
case ASMIT_INX:
|
||||
|
@ -334,18 +350,21 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
|
|||
addr = mMemory[addr];
|
||||
mRegA = addr;
|
||||
UpdateStatus(mRegA);
|
||||
if (cross) cycles++;
|
||||
break;
|
||||
case ASMIT_LDX:
|
||||
if (mode != ASMIM_IMMEDIATE)
|
||||
addr = mMemory[addr];
|
||||
mRegX = addr;
|
||||
UpdateStatus(mRegX);
|
||||
if (cross) cycles++;
|
||||
break;
|
||||
case ASMIT_LDY:
|
||||
if (mode != ASMIM_IMMEDIATE)
|
||||
addr = mMemory[addr];
|
||||
mRegY = addr;
|
||||
UpdateStatus(mRegY);
|
||||
if (cross) cycles++;
|
||||
break;
|
||||
case ASMIT_LSR:
|
||||
if (mode == ASMIM_IMPLIED)
|
||||
|
@ -362,6 +381,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
|
|||
mMemory[addr] = t & 255;
|
||||
UpdateStatusCarry(t & 255, c != 0);
|
||||
cycles += 2;
|
||||
if (indexed) cycles++;
|
||||
}
|
||||
break;
|
||||
case ASMIT_NOP:
|
||||
|
@ -371,6 +391,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
|
|||
addr = mMemory[addr];
|
||||
mRegA |= addr;
|
||||
UpdateStatus(mRegA);
|
||||
if (cross) cycles++;
|
||||
break;
|
||||
case ASMIT_PHA:
|
||||
mMemory[0x100 + mRegS] = mRegA;
|
||||
|
@ -405,6 +426,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
|
|||
mMemory[addr] = t & 255;
|
||||
UpdateStatusCarry(t & 255, t >= 256);
|
||||
cycles+=2;
|
||||
if (indexed) cycles++;
|
||||
}
|
||||
break;
|
||||
case ASMIT_ROR:
|
||||
|
@ -422,6 +444,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
|
|||
mMemory[addr] = t & 255;
|
||||
UpdateStatusCarry(t & 255, c != 0);
|
||||
cycles += 2;
|
||||
if (indexed) cycles++;
|
||||
}
|
||||
break;
|
||||
case ASMIT_RTI:
|
||||
|
@ -444,6 +467,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
|
|||
|
||||
mRegA = (t & 255);
|
||||
UpdateStatusCarry(t & 255, t >= 256);
|
||||
if (cross) cycles++;
|
||||
break;
|
||||
case ASMIT_SEC:
|
||||
mRegP |= STATUS_CARRY;
|
||||
|
@ -454,6 +478,7 @@ bool Emulator::EmulateInstruction(AsmInsType type, AsmInsMode mode, int addr, in
|
|||
break;
|
||||
case ASMIT_STA:
|
||||
mMemory[addr] = mRegA;
|
||||
if (indexed) cycles++;
|
||||
break;
|
||||
case ASMIT_STX:
|
||||
mMemory[addr] = mRegX;
|
||||
|
@ -512,13 +537,13 @@ int Emulator::Emulate(int startIP, int trace)
|
|||
mMemory[0x1fe] = 0xff;
|
||||
mMemory[0x1ff] = 0xff;
|
||||
|
||||
int ticks = 0;
|
||||
int tcycles = 0, cycles = 0;
|
||||
int iip = 0;
|
||||
while (mIP != 0)
|
||||
{
|
||||
if (mJiffies)
|
||||
{
|
||||
ticks++;
|
||||
if (ticks > 4500)
|
||||
if (cycles >= tcycles + 16667)
|
||||
{
|
||||
mMemory[0xa2]++;
|
||||
if (!mMemory[0xa2])
|
||||
|
@ -529,7 +554,7 @@ int Emulator::Emulate(int startIP, int trace)
|
|||
mMemory[0xa0]++;
|
||||
}
|
||||
}
|
||||
ticks = 0;
|
||||
tcycles += 16667;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -556,11 +581,16 @@ int Emulator::Emulate(int startIP, int trace)
|
|||
mRegS += 2;
|
||||
}
|
||||
|
||||
uint8 opcode = mMemory[mIP];
|
||||
uint8 opcode = mMemory[mIP];
|
||||
AsmInsData d = DecInsData[opcode];
|
||||
int addr = 0, taddr;
|
||||
int ip = mIP;
|
||||
int iip = mMemory[BC_REG_IP] + 256 * mMemory[BC_REG_IP + 1];
|
||||
int addr = 0, taddr;
|
||||
int ip = mIP;
|
||||
|
||||
if (ip == 0x0862)
|
||||
iip = mMemory[BC_REG_IP] + 256 * mMemory[BC_REG_IP + 1] + mRegY;
|
||||
|
||||
bool cross = false, indexed = false;
|
||||
int icycles = 0;
|
||||
|
||||
mIP++;
|
||||
switch (d.mMode)
|
||||
|
@ -568,56 +598,60 @@ int Emulator::Emulate(int startIP, int trace)
|
|||
case ASMIM_IMPLIED:
|
||||
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);
|
||||
mCycles[ip] += 2;
|
||||
icycles = 2;
|
||||
break;
|
||||
case ASMIM_IMMEDIATE:
|
||||
addr = mMemory[mIP++];
|
||||
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);
|
||||
mCycles[ip] += 2;
|
||||
icycles = 2;
|
||||
break;
|
||||
case ASMIM_ZERO_PAGE:
|
||||
addr = mMemory[mIP++];
|
||||
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]);
|
||||
mCycles[ip] += 3;
|
||||
icycles = 3;
|
||||
break;
|
||||
case ASMIM_ZERO_PAGE_X:
|
||||
taddr = mMemory[mIP++];
|
||||
addr = (taddr + mRegX) & 0xff;
|
||||
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]);
|
||||
mCycles[ip] += 3;
|
||||
icycles = 4;
|
||||
break;
|
||||
case ASMIM_ZERO_PAGE_Y:
|
||||
taddr = mMemory[mIP++];
|
||||
addr = (taddr + mRegY) & 0xff;
|
||||
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]);
|
||||
mCycles[ip] += 3;
|
||||
icycles = 4;
|
||||
break;
|
||||
case ASMIM_ABSOLUTE:
|
||||
addr = mMemory[mIP] + 256 * mMemory[mIP + 1];
|
||||
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]);
|
||||
mIP += 2;
|
||||
mCycles[ip] += 4;
|
||||
icycles = 4;
|
||||
break;
|
||||
case ASMIM_ABSOLUTE_X:
|
||||
taddr = mMemory[mIP] + 256 * mMemory[mIP + 1];
|
||||
addr = (taddr + mRegX) & 0xffff;
|
||||
cross = mMemory[mIP] + mRegX >= 256;
|
||||
indexed = true;
|
||||
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]);
|
||||
mIP += 2;
|
||||
mCycles[ip] += 5;
|
||||
icycles = 4;
|
||||
break;
|
||||
case ASMIM_ABSOLUTE_Y:
|
||||
taddr = mMemory[mIP] + 256 * mMemory[mIP + 1];
|
||||
addr = (taddr + mRegY) & 0xffff;
|
||||
cross = mMemory[mIP] + mRegY >= 256;
|
||||
indexed = true;
|
||||
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]);
|
||||
mIP += 2;
|
||||
mCycles[ip] += 5;
|
||||
icycles = 4;
|
||||
break;
|
||||
case ASMIM_INDIRECT:
|
||||
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];
|
||||
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);
|
||||
mCycles[ip] += 6;
|
||||
icycles = 6;
|
||||
break;
|
||||
case ASMIM_INDIRECT_X:
|
||||
taddr = (mMemory[mIP++] + mRegX) & 0xff;
|
||||
addr = mMemory[taddr] + 256 * mMemory[taddr + 1];
|
||||
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]);
|
||||
mCycles[ip] += 6;
|
||||
icycles = 6;
|
||||
break;
|
||||
case ASMIM_INDIRECT_Y:
|
||||
taddr = mMemory[mIP++];
|
||||
addr = (mMemory[taddr] + 256 * mMemory[taddr + 1] + mRegY) & 0xffff;
|
||||
cross = mMemory[taddr] + mRegY >= 256;
|
||||
indexed = true;
|
||||
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]);
|
||||
mCycles[ip] += 6;
|
||||
icycles = 5;
|
||||
break;
|
||||
case ASMIM_RELATIVE:
|
||||
taddr = mMemory[mIP++];
|
||||
|
@ -649,7 +685,7 @@ int Emulator::Emulate(int startIP, int trace)
|
|||
addr = taddr + mIP;
|
||||
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);
|
||||
mCycles[ip] += 2;
|
||||
icycles = 2;
|
||||
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;
|
||||
|
||||
mCycles[ip] += icycles;
|
||||
cycles += icycles;
|
||||
}
|
||||
|
||||
if (mRegS == 0xff)
|
||||
|
|
|
@ -22,7 +22,7 @@ public:
|
|||
|
||||
int Emulate(int startIP, int trace);
|
||||
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:
|
||||
void UpdateStatus(uint8 result);
|
||||
void UpdateStatusCarry(uint8 result, bool carry);
|
||||
|
|
|
@ -4,11 +4,18 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
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)
|
||||
{
|
||||
if (!info1)
|
||||
|
@ -22,41 +29,44 @@ 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)
|
||||
{
|
||||
const char* level = "info";
|
||||
if (eid >= EERR_GENERIC)
|
||||
if (eid >= mMinLevel && !(eid < EERR_GENERIC && mDisabled[eid]))
|
||||
{
|
||||
level = "error";
|
||||
mErrorCount++;
|
||||
}
|
||||
else if (eid >= EWARN_GENERIC)
|
||||
{
|
||||
level = "warning";
|
||||
}
|
||||
const char* level = "info";
|
||||
if (eid >= EERR_GENERIC)
|
||||
{
|
||||
level = "error";
|
||||
mErrorCount++;
|
||||
}
|
||||
else if (eid >= EWARN_GENERIC)
|
||||
{
|
||||
level = "warning";
|
||||
}
|
||||
|
||||
if (loc.mFileName)
|
||||
{
|
||||
if (!info1)
|
||||
fprintf(stderr, "%s(%d, %d) : %s %d: %s\n", loc.mFileName, loc.mLine, loc.mColumn, level, eid, msg);
|
||||
else if (!info2)
|
||||
fprintf(stderr, "%s(%d, %d) : %s %d: %s '%s'\n", loc.mFileName, loc.mLine, loc.mColumn, level, eid, msg, info1);
|
||||
if (loc.mFileName)
|
||||
{
|
||||
if (!info1)
|
||||
fprintf(stderr, "%s(%d, %d) : %s %d: %s\n", loc.mFileName, loc.mLine, loc.mColumn, level, eid, msg);
|
||||
else if (!info2)
|
||||
fprintf(stderr, "%s(%d, %d) : %s %d: %s '%s'\n", loc.mFileName, loc.mLine, loc.mColumn, level, eid, msg, info1);
|
||||
else
|
||||
fprintf(stderr, "%s(%d, %d) : %s %d: %s '%s' != '%s'\n", loc.mFileName, loc.mLine, loc.mColumn, level, eid, msg, info1, info2);
|
||||
|
||||
if (loc.mFrom)
|
||||
Error(*(loc.mFrom), EINFO_EXPANDED, "While expanding here");
|
||||
}
|
||||
else
|
||||
fprintf(stderr, "%s(%d, %d) : %s %d: %s '%s' != '%s'\n", loc.mFileName, loc.mLine, loc.mColumn, level, eid, msg, info1, info2);
|
||||
{
|
||||
if (!info1)
|
||||
fprintf(stderr, "oscar64: %s %d: %s\n", level, eid, msg);
|
||||
else if (!info2)
|
||||
fprintf(stderr, "oscar64: %s %d: %s '%s'\n", level, eid, msg, info1);
|
||||
else
|
||||
fprintf(stderr, "oscar64: %s %d: %s '%s' != '%s'\n", level, eid, msg, info1, info2);
|
||||
}
|
||||
|
||||
if (loc.mFrom)
|
||||
Error(*(loc.mFrom), EINFO_EXPANDED, "While expanding here");
|
||||
if (mErrorCount > 10 || eid >= EFATAL_GENERIC)
|
||||
exit(20);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!info1)
|
||||
fprintf(stderr, "oscar64: %s %d: %s\n", level, eid, msg);
|
||||
else if (!info2)
|
||||
fprintf(stderr, "oscar64: %s %d: %s '%s'\n", level, eid, msg, info1);
|
||||
else
|
||||
fprintf(stderr, "oscar64: %s %d: %s '%s' != '%s'\n", level, eid, msg, info1, info2);
|
||||
}
|
||||
|
||||
if (mErrorCount > 10 || eid >= EFATAL_GENERIC)
|
||||
exit(20);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "NumberSet.h"
|
||||
|
||||
|
||||
class Location
|
||||
{
|
||||
public:
|
||||
|
@ -10,7 +13,11 @@ public:
|
|||
Location() : mFileName(nullptr), mLine(0), mColumn(0), mFrom(nullptr) {}
|
||||
Location(const Location& loc, const Location* from)
|
||||
: mFileName(loc.mFileName), mLine(loc.mLine), mColumn(loc.mColumn), mFrom(from)
|
||||
{}
|
||||
{
|
||||
static volatile int k;
|
||||
if (from)
|
||||
k = from->mLine;
|
||||
}
|
||||
};
|
||||
|
||||
class Ident;
|
||||
|
@ -39,6 +46,13 @@ enum ErrorID
|
|||
EWARN_DESTRUCTOR_MISMATCH,
|
||||
EWARN_NUMERIC_0_USED_AS_NULLPTR,
|
||||
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_FILE_NOT_FOUND,
|
||||
|
@ -95,6 +109,10 @@ enum ErrorID
|
|||
EERR_INVALID_CAPTURE,
|
||||
EERR_INVALID_PACK_USAGE,
|
||||
EERR_INVALID_FOLD_EXPRESSION,
|
||||
ERRR_INSTANTIATE_ABSTRACT_CLASS,
|
||||
ERRR_INVALID_GOTO,
|
||||
EERR_INVALID_INITIALIZER,
|
||||
ERRR_INVALID_VOID_POINTER_ARITHMETIC,
|
||||
|
||||
EERR_INVALID_CONSTEXPR,
|
||||
EERR_DOUBLE_FREE,
|
||||
|
@ -103,12 +121,19 @@ enum ErrorID
|
|||
ERRR_STACK_OVERFLOW,
|
||||
ERRR_INVALID_NUMBER,
|
||||
EERR_OVERLAPPING_DATA_SECTIONS,
|
||||
EERR_ASSEMBLER_LIMIT,
|
||||
|
||||
EERR_INVALID_PREPROCESSOR,
|
||||
EERR_INVALID_CLASS_INITIALIZER,
|
||||
EERR_CALL_OF_DELETED_FUNCTION,
|
||||
|
||||
EERR_STATIC_ASSERT,
|
||||
|
||||
EFATAL_GENERIC = 4000,
|
||||
EFATAL_OUT_OF_MEMORY,
|
||||
EFATAL_MACRO_EXPANSION_DEPTH,
|
||||
|
||||
ERROR_MAX = 5000
|
||||
};
|
||||
|
||||
class Errors
|
||||
|
@ -116,7 +141,12 @@ class Errors
|
|||
public:
|
||||
Errors(void);
|
||||
|
||||
ErrorID SetMinLevel(ErrorID id);
|
||||
|
||||
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 char* info1 = nullptr, const char* info2 = nullptr);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "GlobalAnalyzer.h"
|
||||
|
||||
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)
|
||||
{
|
||||
for (int i = 0; i < mFunctions.Size(); i++)
|
||||
TopoSort(mFunctions[i]);
|
||||
|
||||
bool changed = false;
|
||||
do
|
||||
{
|
||||
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];
|
||||
if (!(f->mFlags & DTF_INLINE) &&
|
||||
Declaration* f = mTopoFunctions[i];
|
||||
|
||||
if (f->mType == DT_CONST_FUNCTION &&
|
||||
!(f->mFlags & DTF_INLINE) &&
|
||||
!(f->mFlags & DTF_EXPORT) &&
|
||||
!(f->mFlags & DTF_PREVENT_INLINE) &&
|
||||
!(f->mBase->mFlags & DTF_VARIADIC) &&
|
||||
!(f->mFlags & DTF_FUNC_VARIABLE) &&
|
||||
!((f->mFlags & DTF_FUNC_ASSEMBLER) && !(f->mFlags & DTF_REQUEST_INLINE)) &&
|
||||
!(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;
|
||||
Declaration* dec = f->mBase->mParams;
|
||||
|
@ -159,21 +200,39 @@ void GlobalAnalyzer::AutoInline(void)
|
|||
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;
|
||||
if ((f->mCompilerOptions & COPT_OPTIMIZE_INLINE) && (f->mFlags & DTF_REQUEST_INLINE))
|
||||
doinline = true;
|
||||
if ((f->mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE) && (cost * (f->mCallers.Size() - 1) <= 0))
|
||||
doinline = true;
|
||||
if ((f->mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE_ALL) && (cost * (f->mCallers.Size() - 1) <= 10000))
|
||||
if ((f->mCompilerOptions & COPT_OPTIMIZE_INLINE) && (f->mFlags & DTF_REQUEST_INLINE) || (f->mFlags & DTF_FORCE_INLINE))
|
||||
doinline = true;
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
else
|
||||
doinline = true;
|
||||
}
|
||||
if ((f->mCompilerOptions & COPT_OPTIMIZE_AUTO_INLINE_ALL) && (cost * (invokes - 1) <= 10000))
|
||||
doinline = true;
|
||||
}
|
||||
|
||||
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;
|
||||
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)
|
||||
{
|
||||
Declaration* maxf = nullptr;
|
||||
Declaration* maxf = nullptr, * reff = nullptr;
|
||||
|
||||
bool stackCall = false;
|
||||
|
||||
|
@ -343,7 +402,10 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
|
|||
Declaration* cf = procDec->mCalled[i];
|
||||
|
||||
if (cf->mBase->mFlags & DTF_STACKCALL)
|
||||
{
|
||||
stackCall = true;
|
||||
reff = cf;
|
||||
}
|
||||
|
||||
if (!maxf)
|
||||
maxf = cf;
|
||||
|
@ -351,6 +413,9 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
|
|||
maxf = cf;
|
||||
}
|
||||
|
||||
if (!reff)
|
||||
reff = maxf;
|
||||
|
||||
for (int i = 0; i < procDec->mCalled.Size(); i++)
|
||||
{
|
||||
Declaration* cf = procDec->mCalled[i];
|
||||
|
@ -361,9 +426,9 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
|
|||
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)
|
||||
{
|
||||
fp->mVarIndex = mp->mVarIndex;
|
||||
|
@ -372,10 +437,11 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
|
|||
}
|
||||
|
||||
assert(!mp);
|
||||
|
||||
cf->mBase->mFastCallBase = cf->mFastCallBase = maxf->mBase->mFastCallBase;
|
||||
cf->mBase->mFastCallSize = cf->mFastCallSize = maxf->mBase->mFastCallSize;
|
||||
}
|
||||
|
||||
if (cf != maxf)
|
||||
cf->mBase->mFastCallBase = cf->mFastCallBase = maxf->mBase->mFastCallBase;
|
||||
}
|
||||
|
||||
procDec->mFastCallBase = procDec->mBase->mFastCallBase;
|
||||
|
@ -415,7 +481,7 @@ void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
|
|||
fplimit += 256;
|
||||
}
|
||||
|
||||
if (procDec->mBase->mBase->mType == DT_TYPE_STRUCT)
|
||||
if (procDec->mBase->mBase->IsComplexStruct())
|
||||
{
|
||||
if (nbase < numfpzero && nbase + 2 > numfpzero)
|
||||
nbase = numfpzero;
|
||||
|
@ -567,6 +633,13 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* cexp, Expression* exp, Declara
|
|||
{
|
||||
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);
|
||||
|
||||
Declaration* pdec = dec->mBase->mParams;
|
||||
|
@ -579,6 +652,8 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* cexp, Expression* exp, Declara
|
|||
|
||||
dec->mFlags |= DTF_ANALYZED;
|
||||
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)
|
||||
dec->mFlags |= DTF_FUNC_INTRCALLED;
|
||||
|
@ -590,7 +665,7 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* cexp, Expression* exp, Declara
|
|||
if (mCompilerOptions & COPT_OPTIMIZE_CONST_EXPRESSIONS)
|
||||
dec->mFlags |= DTF_FUNC_CONSTEXPR;
|
||||
dec->mFlags |= DTF_FUNC_PURE;
|
||||
Analyze(exp, dec, false);
|
||||
Analyze(exp, dec, 0);
|
||||
|
||||
Declaration* pdec = dec->mBase->mParams;
|
||||
int vi = 0;
|
||||
|
@ -610,7 +685,7 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* cexp, Expression* exp, Declara
|
|||
}
|
||||
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)
|
||||
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)
|
||||
{
|
||||
if (adec->mBase->mFlags & DTF_GLOBAL)
|
||||
{
|
||||
AnalyzeGlobalVariable(adec->mBase);
|
||||
adec->mBase->mFlags |= DTF_VAR_ALIASING;
|
||||
}
|
||||
}
|
||||
else if (adec->mType == DT_LABEL)
|
||||
{
|
||||
|
@ -647,7 +725,10 @@ void GlobalAnalyzer::AnalyzeAssembler(Expression* exp, Declaration* procDec)
|
|||
else if (adec->mType == DT_VARIABLE)
|
||||
{
|
||||
if (adec->mFlags & DTF_GLOBAL)
|
||||
{
|
||||
AnalyzeGlobalVariable(adec);
|
||||
adec->mFlags |= DTF_VAR_ALIASING;
|
||||
}
|
||||
}
|
||||
else if (adec->mType == DT_FUNCTION_REF)
|
||||
{
|
||||
|
@ -680,7 +761,7 @@ void GlobalAnalyzer::AnalyzeGlobalVariable(Declaration* dec)
|
|||
|
||||
if (dec->mValue)
|
||||
{
|
||||
Analyze(dec->mValue, dec, false);
|
||||
Analyze(dec->mValue, dec, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -690,17 +771,19 @@ void GlobalAnalyzer::AnalyzeInit(Declaration* mdec)
|
|||
while (mdec)
|
||||
{
|
||||
if (mdec->mValue)
|
||||
RegisterProc(Analyze(mdec->mValue, mdec, false));
|
||||
RegisterProc(Analyze(mdec->mValue, mdec, 0));
|
||||
else if (mdec->mParams)
|
||||
AnalyzeInit(mdec->mParams);
|
||||
mdec = mdec->mNext;
|
||||
}
|
||||
}
|
||||
|
||||
Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, bool lhs)
|
||||
Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, uint32 flags)
|
||||
{
|
||||
Declaration* ldec, * rdec;
|
||||
|
||||
exp->mFlags = flags;
|
||||
|
||||
switch (exp->mType)
|
||||
{
|
||||
case EX_ERROR:
|
||||
|
@ -718,7 +801,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
}
|
||||
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)
|
||||
ldec->mFlags |= DTF_VAR_ALIASING;
|
||||
RegisterProc(ldec);
|
||||
|
@ -734,9 +817,22 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
|
||||
return exp->mDecValue;
|
||||
case EX_VARIABLE:
|
||||
if (exp->mDecType->IsSimpleType())
|
||||
procDec->mComplexity += 5 * exp->mDecType->mSize;
|
||||
else
|
||||
procDec->mComplexity += 10;
|
||||
|
||||
if (mCompilerOptions & COPT_DEBUGINFO)
|
||||
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))
|
||||
{
|
||||
Declaration* type = exp->mDecValue->mBase;
|
||||
|
@ -746,14 +842,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
if (!(type->mFlags & DTF_CONST))
|
||||
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
|
||||
|
||||
if (lhs)
|
||||
if (flags & ANAFL_LHS)
|
||||
procDec->mFlags &= ~DTF_FUNC_PURE;
|
||||
|
||||
AnalyzeGlobalVariable(exp->mDecValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lhs)
|
||||
if (flags & ANAFL_LHS)
|
||||
exp->mDecValue->mFlags |= DTF_VAR_ADDRESS;
|
||||
|
||||
if (!(exp->mDecValue->mFlags & DTF_ANALYZED))
|
||||
|
@ -765,10 +861,10 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
return exp->mDecValue;
|
||||
case EX_INITIALIZATION:
|
||||
case EX_ASSIGNMENT:
|
||||
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
|
||||
procDec->mComplexity += 5 * exp->mLeft->mDecType->mSize;
|
||||
|
||||
ldec = Analyze(exp->mLeft, procDec, true);
|
||||
rdec = Analyze(exp->mRight, procDec, false);
|
||||
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_RHS);
|
||||
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)
|
||||
exp->mLeft->mDecValue->mFlags |= DTF_VAR_ALIASING;
|
||||
RegisterProc(rdec);
|
||||
|
@ -777,33 +873,33 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
case EX_BINARY:
|
||||
procDec->mComplexity += 10 * exp->mDecType->mSize;
|
||||
|
||||
ldec = Analyze(exp->mLeft, procDec, lhs);
|
||||
rdec = Analyze(exp->mRight, procDec, lhs);
|
||||
ldec = Analyze(exp->mLeft, procDec, flags & ~ANAFL_ALIAS);
|
||||
rdec = Analyze(exp->mRight, procDec, flags & ~ANAFL_ALIAS);
|
||||
return ldec;
|
||||
|
||||
case EX_RELATIONAL:
|
||||
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
|
||||
|
||||
ldec = Analyze(exp->mLeft, procDec, false);
|
||||
rdec = Analyze(exp->mRight, procDec, false);
|
||||
ldec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||
rdec = Analyze(exp->mRight, procDec, ANAFL_RHS);
|
||||
return TheBoolTypeDeclaration;
|
||||
|
||||
case EX_PREINCDEC:
|
||||
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:
|
||||
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)
|
||||
ldec->mFlags |= DTF_VAR_ALIASING;
|
||||
}
|
||||
else if (exp->mToken == TK_MUL)
|
||||
{
|
||||
ldec = Analyze(exp->mLeft, procDec, false);
|
||||
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
|
||||
if (lhs)
|
||||
if (flags & ANAFL_LHS)
|
||||
procDec->mFlags &= ~DTF_FUNC_PURE;
|
||||
|
||||
return exp->mDecType;
|
||||
|
@ -812,10 +908,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
{
|
||||
return TheUnsignedCharTypeDeclaration;
|
||||
}
|
||||
else if (exp->mToken == TK_SIZEOF)
|
||||
{
|
||||
return TheUnsignedIntTypeDeclaration;
|
||||
}
|
||||
else
|
||||
{
|
||||
procDec->mComplexity += 10 * exp->mLeft->mDecType->mSize;
|
||||
return Analyze(exp->mLeft, procDec, false);
|
||||
return Analyze(exp->mLeft, procDec, 0);
|
||||
}
|
||||
break;
|
||||
case EX_POSTFIX:
|
||||
|
@ -824,31 +924,31 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
case EX_POSTINCDEC:
|
||||
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:
|
||||
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)
|
||||
{
|
||||
ldec = ldec->mBase;
|
||||
if (ldec->mType == DT_TYPE_POINTER)
|
||||
{
|
||||
if (lhs)
|
||||
if (flags & ANAFL_LHS)
|
||||
procDec->mFlags &= ~DTF_FUNC_PURE;
|
||||
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
|
||||
}
|
||||
}
|
||||
rdec = Analyze(exp->mRight, procDec, false);
|
||||
rdec = Analyze(exp->mRight, procDec, 0);
|
||||
if (ldec->mBase)
|
||||
return ldec->mBase;
|
||||
break;
|
||||
case EX_QUALIFY:
|
||||
Analyze(exp->mLeft, procDec, lhs);
|
||||
Analyze(exp->mLeft, procDec, flags);
|
||||
return exp->mDecValue->mBase;
|
||||
case EX_DISPATCH:
|
||||
procDec->mFlags |= DTF_PREVENT_INLINE;
|
||||
Analyze(exp->mLeft, procDec, lhs);
|
||||
Analyze(exp->mLeft, procDec, flags & ~ANAFL_ALIAS);
|
||||
// RegisterCall(procDec, exp->mLeft->mDecType);
|
||||
break;
|
||||
case EX_VCALL:
|
||||
|
@ -859,7 +959,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
case EX_INLINE:
|
||||
procDec->mComplexity += 10;
|
||||
|
||||
ldec = Analyze(exp->mLeft, procDec, false);
|
||||
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||
if ((ldec->mFlags & DTF_INTRINSIC) && !ldec->mValue)
|
||||
{
|
||||
|
||||
|
@ -946,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)))
|
||||
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)
|
||||
pdec = pdec->mNext;
|
||||
|
@ -960,12 +1060,12 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
break;
|
||||
case EX_LIST:
|
||||
case EX_COMMA:
|
||||
RegisterProc(Analyze(exp->mLeft, procDec, false));
|
||||
return Analyze(exp->mRight, procDec, false);
|
||||
RegisterProc(Analyze(exp->mLeft, procDec, 0));
|
||||
return Analyze(exp->mRight, procDec, 0);
|
||||
case EX_RETURN:
|
||||
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->mMoveConstructor)
|
||||
|
@ -976,6 +1076,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
AnalyzeProcedure(exp, procDec->mBase->mBase->mCopyConstructor->mValue, procDec->mBase->mBase->mCopyConstructor);
|
||||
RegisterCall(procDec, procDec->mBase->mBase->mCopyConstructor);
|
||||
}
|
||||
|
||||
procDec->mFlags &= ~DTF_FUNC_NO_RETURN;
|
||||
}
|
||||
break;
|
||||
case EX_SEQUENCE:
|
||||
|
@ -984,47 +1086,47 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
if (exp->mType == EX_SEQUENCE)
|
||||
{
|
||||
if (exp->mLeft)
|
||||
ldec = Analyze(exp->mLeft, procDec, false);
|
||||
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||
exp = exp->mRight;
|
||||
}
|
||||
else
|
||||
return Analyze(exp, procDec, false);
|
||||
return Analyze(exp, procDec, 0);
|
||||
|
||||
} while (exp);
|
||||
break;
|
||||
|
||||
case EX_SCOPE:
|
||||
Analyze(exp->mLeft, procDec, false);
|
||||
Analyze(exp->mLeft, procDec, 0);
|
||||
break;
|
||||
|
||||
case EX_CONSTRUCT:
|
||||
if (exp->mLeft->mLeft)
|
||||
Analyze(exp->mLeft->mLeft, procDec, false);
|
||||
Analyze(exp->mLeft->mLeft, procDec, 0);
|
||||
if (exp->mLeft->mRight)
|
||||
Analyze(exp->mLeft->mRight, procDec, false);
|
||||
Analyze(exp->mLeft->mRight, procDec, 0);
|
||||
if (exp->mRight)
|
||||
return Analyze(exp->mRight, procDec, false);
|
||||
return Analyze(exp->mRight, procDec, 0);
|
||||
break;
|
||||
|
||||
case EX_CLEANUP:
|
||||
Analyze(exp->mRight, procDec, false);
|
||||
return Analyze(exp->mLeft, procDec, lhs);
|
||||
Analyze(exp->mRight, procDec, 0);
|
||||
return Analyze(exp->mLeft, procDec, flags & ~ANAFL_ALIAS);
|
||||
|
||||
case EX_WHILE:
|
||||
procDec->mFlags &= ~DTF_FUNC_CONSTEXPR;
|
||||
|
||||
procDec->mComplexity += 20;
|
||||
|
||||
ldec = Analyze(exp->mLeft, procDec, false);
|
||||
rdec = Analyze(exp->mRight, procDec, false);
|
||||
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||
rdec = Analyze(exp->mRight, procDec, 0);
|
||||
break;
|
||||
case EX_IF:
|
||||
procDec->mComplexity += 20;
|
||||
|
||||
ldec = Analyze(exp->mLeft, procDec, false);
|
||||
rdec = Analyze(exp->mRight->mLeft, procDec, false);
|
||||
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||
rdec = Analyze(exp->mRight->mLeft, procDec, 0);
|
||||
if (exp->mRight->mRight)
|
||||
rdec = Analyze(exp->mRight->mRight, procDec, false);
|
||||
rdec = Analyze(exp->mRight->mRight, procDec, 0);
|
||||
break;
|
||||
case EX_ELSE:
|
||||
break;
|
||||
|
@ -1034,18 +1136,23 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
procDec->mComplexity += 30;
|
||||
|
||||
if (exp->mLeft->mRight)
|
||||
ldec = Analyze(exp->mLeft->mRight, procDec, false);
|
||||
ldec = Analyze(exp->mLeft->mRight, procDec, 0);
|
||||
if (exp->mLeft->mLeft->mLeft)
|
||||
ldec = Analyze(exp->mLeft->mLeft->mLeft, procDec, false);
|
||||
rdec = Analyze(exp->mRight, procDec, false);
|
||||
ldec = Analyze(exp->mLeft->mLeft->mLeft, procDec, 0);
|
||||
rdec = Analyze(exp->mRight, procDec, 0);
|
||||
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;
|
||||
case EX_DO:
|
||||
procDec->mComplexity += 20;
|
||||
|
||||
ldec = Analyze(exp->mLeft, procDec, false);
|
||||
rdec = Analyze(exp->mRight, procDec, false);
|
||||
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||
rdec = Analyze(exp->mRight, procDec, 0);
|
||||
break;
|
||||
case EX_BREAK:
|
||||
case EX_CONTINUE:
|
||||
|
@ -1054,18 +1161,18 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
case EX_TYPE:
|
||||
break;
|
||||
case EX_TYPECAST:
|
||||
return Analyze(exp->mLeft, procDec, false);
|
||||
return Analyze(exp->mLeft, procDec, 0);
|
||||
break;
|
||||
case EX_LOGICAL_AND:
|
||||
ldec = Analyze(exp->mLeft, procDec, false);
|
||||
rdec = Analyze(exp->mRight, procDec, false);
|
||||
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||
rdec = Analyze(exp->mRight, procDec, 0);
|
||||
break;
|
||||
case EX_LOGICAL_OR:
|
||||
ldec = Analyze(exp->mLeft, procDec, false);
|
||||
rdec = Analyze(exp->mRight, procDec, false);
|
||||
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||
rdec = Analyze(exp->mRight, procDec, 0);
|
||||
break;
|
||||
case EX_LOGICAL_NOT:
|
||||
ldec = Analyze(exp->mLeft, procDec, false);
|
||||
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||
break;
|
||||
case EX_ASSEMBLER:
|
||||
procDec->mFlags |= DTF_FUNC_ASSEMBLER;
|
||||
|
@ -1076,14 +1183,14 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
case EX_UNDEFINED:
|
||||
break;
|
||||
case EX_SWITCH:
|
||||
ldec = Analyze(exp->mLeft, procDec, false);
|
||||
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||
exp = exp->mRight;
|
||||
while (exp)
|
||||
{
|
||||
procDec->mComplexity += 10;
|
||||
|
||||
if (exp->mLeft->mRight)
|
||||
rdec = Analyze(exp->mLeft->mRight, procDec, false);
|
||||
rdec = Analyze(exp->mLeft->mRight, procDec, 0);
|
||||
exp = exp->mRight;
|
||||
}
|
||||
break;
|
||||
|
@ -1094,9 +1201,9 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
|
|||
case EX_CONDITIONAL:
|
||||
procDec->mComplexity += exp->mDecType->mSize * 10;
|
||||
|
||||
ldec = Analyze(exp->mLeft, procDec, false);
|
||||
RegisterProc(Analyze(exp->mRight->mLeft, procDec, lhs));
|
||||
RegisterProc(Analyze(exp->mRight->mRight, procDec, lhs));
|
||||
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||
RegisterProc(Analyze(exp->mRight->mLeft, procDec, flags));
|
||||
RegisterProc(Analyze(exp->mRight->mRight, procDec, flags));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ public:
|
|||
~GlobalAnalyzer(void);
|
||||
|
||||
void DumpCallGraph(void);
|
||||
void TopoSort(Declaration * procDec);
|
||||
void AutoInline(void);
|
||||
void CheckFastcall(Declaration* procDec, bool head);
|
||||
void CheckInterrupt(void);
|
||||
|
@ -27,12 +28,14 @@ protected:
|
|||
Errors* mErrors;
|
||||
Linker* mLinker;
|
||||
|
||||
GrowingArray<Declaration*> mCalledFunctions, mCallingFunctions, mVariableFunctions, mFunctions;
|
||||
GrowingArray<Declaration*> mCalledFunctions, mCallingFunctions, mVariableFunctions, mFunctions, mTopoFunctions;
|
||||
GrowingArray<Declaration*> mGlobalVariables;
|
||||
|
||||
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 MarkCycle(Declaration* rootDec, Declaration* procDec);
|
||||
|
|
|
@ -60,7 +60,7 @@ void GlobalOptimizer::Reset(void)
|
|||
mFunctions.SetSize(0);
|
||||
mGlobalVariables.SetSize(0);
|
||||
mCalledFunctions.SetSize(0);
|
||||
mCalledFunctions.SetSize(0);
|
||||
mCallingFunctions.SetSize(0);
|
||||
}
|
||||
|
||||
void GlobalOptimizer::PropagateParamCommas(Expression*& fexp, Expression*& exp)
|
||||
|
@ -134,7 +134,7 @@ bool GlobalOptimizer::CheckConstReturns(Expression*& exp)
|
|||
Expression* lexp = new Expression(exp->mLocation, EX_COMMA);
|
||||
lexp->mLeft = exp;
|
||||
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->mDecType = exp->mDecType;
|
||||
exp->mDecType = TheVoidTypeDeclaration;
|
||||
|
@ -160,6 +160,7 @@ bool GlobalOptimizer::CheckConstReturns(Expression*& exp)
|
|||
lexp->mRight->mToken = TK_MUL;
|
||||
lexp->mRight->mLeft = pex;
|
||||
lexp->mRight->mDecType = pcall->mBase->mBase;
|
||||
lexp->mDecType = lexp->mRight->mDecType;
|
||||
exp->mDecType = TheVoidTypeDeclaration;
|
||||
exp = lexp;
|
||||
return true;
|
||||
|
@ -188,7 +189,7 @@ bool GlobalOptimizer::CheckUnusedLocals(Expression*& exp)
|
|||
if (vexp->mType == EX_VARIABLE)
|
||||
{
|
||||
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;
|
||||
return true;
|
||||
|
@ -242,6 +243,19 @@ bool GlobalOptimizer::ReplaceParamConst(Expression* exp, Declaration* param)
|
|||
bool changed = false;
|
||||
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)
|
||||
{
|
||||
exp->mType = EX_CONSTANT;
|
||||
|
@ -250,9 +264,39 @@ bool GlobalOptimizer::ReplaceParamConst(Expression* exp, Declaration* param)
|
|||
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;
|
||||
}
|
||||
else if (exp->mDecValue->mBase->mType == DT_TYPE_STRUCT)
|
||||
{
|
||||
exp->mDecValue->mBase = exp->mDecValue->mBase->ToConstType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ReplaceGlobalConst(exp->mLeft))
|
||||
changed = true;
|
||||
if (ReplaceParamConst(exp->mRight, param))
|
||||
if (ReplaceGlobalConst(exp->mRight))
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
|
@ -281,6 +325,9 @@ bool GlobalOptimizer::Optimize(void)
|
|||
if (CheckConstReturns(func->mValue))
|
||||
changed = true;
|
||||
|
||||
if (ReplaceGlobalConst(func->mValue))
|
||||
changed = true;
|
||||
|
||||
if (func->mOptFlags & OPTF_MULTI_CALL)
|
||||
{
|
||||
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_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
|
||||
printf("Remove return value\n");
|
||||
|
@ -312,54 +359,57 @@ bool GlobalOptimizer::Optimize(void)
|
|||
changed = true;
|
||||
}
|
||||
|
||||
|
||||
Declaration* pdec = ftype->mParams;
|
||||
int vi = 0;
|
||||
while (pdec)
|
||||
if (!(ftype->mFlags & DTF_VARIADIC))
|
||||
{
|
||||
pdec->mVarIndex += vi;
|
||||
if (!(pdec->mOptFlags & OPTF_VAR_USED) && !(pdec->mFlags & DTF_FPARAM_UNUSED))
|
||||
Declaration* pdec = ftype->mParams;
|
||||
int vi = 0;
|
||||
while (pdec)
|
||||
{
|
||||
if (!pdec->mBase->IsReference() || !(pdec->mOptFlags & OPTF_VAR_ADDRESS))
|
||||
pdec->mVarIndex += vi;
|
||||
if (!(pdec->mOptFlags & OPTF_VAR_USED) && !(pdec->mFlags & DTF_FPARAM_UNUSED))
|
||||
{
|
||||
if (!pdec->mBase->IsReference() || !(pdec->mOptFlags & OPTF_VAR_ADDRESS))
|
||||
{
|
||||
#if DUMP_OPTS
|
||||
printf("Unused parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_");
|
||||
#endif
|
||||
vi -= pdec->mSize;
|
||||
|
||||
pdec->mFlags |= DTF_FPARAM_UNUSED;
|
||||
pdec->mVarIndex = func->mNumVars++;
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else if (!(pdec->mOptFlags & OPTF_VAR_ADDRESS) && pdec->mBase->IsReference() && pdec->mBase->mBase->IsSimpleType())
|
||||
{
|
||||
#if DUMP_OPTS
|
||||
printf("Unused parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_");
|
||||
printf("Reference parameter %s to value\n", pdec->mIdent ? pdec->mIdent->mString : "_");
|
||||
#endif
|
||||
vi -= pdec->mSize;
|
||||
vi += pdec->mSize - 2;
|
||||
|
||||
pdec->mFlags |= DTF_FPARAM_UNUSED;
|
||||
pdec->mVarIndex = func->mNumVars++;
|
||||
pdec->mBase = pdec->mBase->mBase;
|
||||
pdec->mSize = pdec->mBase->mSize;
|
||||
|
||||
UndoParamReference(func->mValue, pdec);
|
||||
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
else if (!(pdec->mOptFlags & OPTF_VAR_ADDRESS) && pdec->mBase->IsReference() && pdec->mBase->mBase->IsSimpleType())
|
||||
{
|
||||
#if DUMP_OPTS
|
||||
printf("Reference parameter %s to value\n", pdec->mIdent ? pdec->mIdent->mString : "_");
|
||||
#endif
|
||||
vi += pdec->mSize - 2;
|
||||
|
||||
pdec->mBase = pdec->mBase->mBase;
|
||||
pdec->mSize = pdec->mBase->mSize;
|
||||
|
||||
UndoParamReference(func->mValue, pdec);
|
||||
|
||||
changed = true;
|
||||
}
|
||||
else if ((pdec->mOptFlags & OPTF_VAR_CONST) && !(pdec->mOptFlags & OPTF_VAR_ADDRESS))
|
||||
{
|
||||
if (ReplaceParamConst(func->mValue, pdec))
|
||||
else if ((pdec->mOptFlags & OPTF_VAR_CONST) && !(pdec->mOptFlags & OPTF_VAR_ADDRESS))
|
||||
{
|
||||
if (ReplaceParamConst(func->mValue, pdec))
|
||||
{
|
||||
func->mValue = func->mValue->ConstantFold(mErrors, nullptr);
|
||||
#if DUMP_OPTS
|
||||
printf("Const parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_");
|
||||
printf("Const parameter %s\n", pdec->mIdent ? pdec->mIdent->mString : "_");
|
||||
#endif
|
||||
changed = true;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pdec->mOptFlags = 0;
|
||||
pdec = pdec->mNext;
|
||||
pdec->mOptFlags = 0;
|
||||
pdec = pdec->mNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,7 +462,7 @@ void GlobalOptimizer::AnalyzeProcedure(Expression* exp, Declaration* procDec)
|
|||
Analyze(exp, procDec, false);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -433,8 +483,7 @@ void GlobalOptimizer::AnalyzeAssembler(Expression* exp, Declaration* procDec)
|
|||
{
|
||||
if (adec->mBase->mFlags & DTF_GLOBAL)
|
||||
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)
|
||||
{
|
||||
|
@ -444,8 +493,7 @@ void GlobalOptimizer::AnalyzeAssembler(Expression* exp, Declaration* procDec)
|
|||
{
|
||||
if (adec->mFlags & DTF_GLOBAL)
|
||||
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)
|
||||
{
|
||||
|
@ -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* ldec, * rdec;
|
||||
|
@ -610,14 +655,14 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin
|
|||
|
||||
AnalyzeGlobalVariable(exp->mDecValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & ANAFL_RHS)
|
||||
exp->mDecValue->mOptFlags |= OPTF_VAR_USED;
|
||||
if (flags & ANAFL_LHS)
|
||||
exp->mDecValue->mOptFlags |= OPTF_VAR_ADDRESS;
|
||||
}
|
||||
if (exp->mDecValue->mType == DT_ARGUMENT)
|
||||
if (flags & ANAFL_RHS)
|
||||
exp->mDecValue->mOptFlags |= OPTF_VAR_USED;
|
||||
if (flags & ANAFL_LHS)
|
||||
exp->mDecValue->mOptFlags |= OPTF_VAR_ADDRESS;
|
||||
if (exp->mDecValue->mBase->IsReference() && (flags & ANAFL_ASSIGN))
|
||||
exp->mDecValue->mOptFlags |= OPTF_VAR_USED;
|
||||
|
||||
if (exp->mDecValue->mType == DT_ARGUMENT && (flags & ANAFL_LHS))
|
||||
{
|
||||
exp->mDecValue->mOptFlags |= OPTF_VAR_NO_FORWARD;
|
||||
exp->mDecValue->mForwardParam = nullptr;
|
||||
|
@ -627,7 +672,12 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin
|
|||
case EX_INITIALIZATION:
|
||||
case EX_ASSIGNMENT:
|
||||
if (exp->mToken == TK_ASSIGN)
|
||||
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | flags);
|
||||
{
|
||||
if (exp->mType == EX_ASSIGNMENT)
|
||||
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | ANAFL_ASSIGN | flags);
|
||||
else
|
||||
ldec = Analyze(exp->mLeft, procDec, ANAFL_LHS | flags);
|
||||
}
|
||||
else
|
||||
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;
|
||||
}
|
||||
}
|
||||
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
|
||||
{
|
||||
pdec->mOptFlags |= OPTF_VAR_NOCONST;
|
||||
|
@ -920,13 +986,20 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin
|
|||
if (exp->mLeft->mLeft->mRight)
|
||||
ldec = Analyze(exp->mLeft->mLeft->mRight, procDec, 0);
|
||||
break;
|
||||
case EX_FORBODY:
|
||||
ldec = Analyze(exp->mLeft, procDec, 0);
|
||||
if (exp->mRight)
|
||||
rdec = Analyze(exp->mRight, procDec, 0);
|
||||
break;
|
||||
case EX_DO:
|
||||
ldec = Analyze(exp->mRight, procDec, 0);
|
||||
rdec = Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||
break;
|
||||
case EX_BREAK:
|
||||
case EX_CONTINUE:
|
||||
break;
|
||||
case EX_ASSUME:
|
||||
return Analyze(exp->mLeft, procDec, ANAFL_RHS);
|
||||
break;
|
||||
case EX_TYPE:
|
||||
break;
|
||||
|
|
|
@ -39,5 +39,6 @@ protected:
|
|||
bool ReplaceParamConst(Expression* exp, Declaration* param);
|
||||
void PropagateCommas(Expression*& exp);
|
||||
void PropagateParamCommas(Expression *& fexp, Expression*& exp);
|
||||
bool ReplaceGlobalConst(Expression* exp);
|
||||
|
||||
};
|
||||
|
|
|
@ -47,7 +47,7 @@ const Ident* Ident::Unique(const char* str)
|
|||
|
||||
const Ident* Ident::PreMangle(const char* str) const
|
||||
{
|
||||
char buffer[200];
|
||||
char buffer[1000];
|
||||
strcpy_s(buffer, str);
|
||||
strcat_s(buffer, mString);
|
||||
return Unique(buffer);
|
||||
|
@ -55,14 +55,14 @@ const Ident* Ident::PreMangle(const char* str) const
|
|||
|
||||
const Ident* Ident::Unique(const char* str, int id)
|
||||
{
|
||||
char buffer[200];
|
||||
char buffer[1000];
|
||||
sprintf_s(buffer, "%s#%d", str, id);
|
||||
return Unique(buffer);
|
||||
}
|
||||
|
||||
const Ident* Ident::Mangle(const char* str) const
|
||||
{
|
||||
char buffer[200];
|
||||
char buffer[1000];
|
||||
strcpy_s(buffer, mString);
|
||||
strcat_s(buffer, str);
|
||||
return Unique(buffer);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -24,6 +24,7 @@ enum InterCode
|
|||
IC_LEA,
|
||||
IC_COPY, // Copy from src[0] to src[1]
|
||||
IC_STRCPY,
|
||||
IC_FILL, // Fill src[1] with src[0]
|
||||
IC_MALLOC,
|
||||
IC_FREE,
|
||||
IC_TYPECAST,
|
||||
|
@ -41,7 +42,8 @@ enum InterCode
|
|||
IC_JUMPF,
|
||||
IC_SELECT,
|
||||
IC_DISPATCH,
|
||||
IC_UNREACHABLE
|
||||
IC_UNREACHABLE,
|
||||
IC_BREAKPOINT
|
||||
};
|
||||
|
||||
enum InterType
|
||||
|
@ -103,10 +105,15 @@ enum InterOperator
|
|||
IA_CMPLEU,
|
||||
IA_CMPGU,
|
||||
IA_CMPLU,
|
||||
|
||||
IA_FLOAT2INT,
|
||||
IA_INT2FLOAT,
|
||||
IA_FLOAT2UINT,
|
||||
IA_UINT2FLOAT,
|
||||
IA_FLOAT2LINT,
|
||||
IA_LINT2FLOAT,
|
||||
IA_FLOAT2LUINT,
|
||||
IA_LUINT2FLOAT,
|
||||
|
||||
IA_EXT8TO16U,
|
||||
IA_EXT8TO32U,
|
||||
|
@ -162,15 +169,21 @@ public:
|
|||
} mMinState, mMaxState;
|
||||
|
||||
bool Same(const IntegerValueRange& range) const;
|
||||
bool Weaker(const IntegerValueRange& range) const;
|
||||
bool Merge(const IntegerValueRange& range, bool head, bool initial);
|
||||
void Expand(const IntegerValueRange& range);
|
||||
void Union(const IntegerValueRange& range);
|
||||
|
||||
void Limit(const IntegerValueRange& range);
|
||||
void LimitWeak(const IntegerValueRange& range);
|
||||
void MergeUnknown(const IntegerValueRange& range);
|
||||
void SetLimit(int64 minValue, int64 maxValue);
|
||||
void SetBounds(State minState, int64 minValue, State maxState, int64 maxValue);
|
||||
void SetConstant(int64 value);
|
||||
|
||||
bool IsBound(void) const;
|
||||
bool IsConstant(void) const;
|
||||
bool IsInvalid(void) const;
|
||||
|
||||
void LimitMin(int64 value);
|
||||
void LimitMax(int64 value);
|
||||
|
@ -180,11 +193,13 @@ public:
|
|||
|
||||
void LimitMinWeak(int64 value);
|
||||
void LimitMaxWeak(int64 value);
|
||||
|
||||
void AddConstValue(InterType type, int64 value);
|
||||
};
|
||||
|
||||
|
||||
|
||||
typedef GrowingArray<IntegerValueRange> GrowingIntegerValueRangeArray;
|
||||
typedef ExpandingArray<IntegerValueRange> GrowingIntegerValueRangeArray;
|
||||
|
||||
class ValueSet
|
||||
{
|
||||
|
@ -206,7 +221,7 @@ public:
|
|||
void RemoveValue(int index);
|
||||
void InsertValue(InterInstruction * ins);
|
||||
|
||||
void UpdateValue(InterInstruction * ins, const GrowingInstructionPtrArray& tvalue, const NumberSet& aliasedLocals, const NumberSet& aliasedParams, const GrowingVariableArray& staticVars);
|
||||
void UpdateValue(InterCodeBasicBlock* block, InterInstruction * ins, const GrowingInstructionPtrArray& tvalue, const NumberSet& aliasedLocals, const NumberSet& aliasedParams, const GrowingVariableArray& staticVars, const GrowingInterCodeProcedurePtrArray& staticProcs);
|
||||
void Intersect(ValueSet& set);
|
||||
};
|
||||
|
||||
|
@ -298,15 +313,18 @@ class InterInstruction
|
|||
public:
|
||||
Location mLocation;
|
||||
InterCode mCode;
|
||||
InterOperand mSrc[8];
|
||||
InterOperand * mSrc;
|
||||
InterOperand mDst;
|
||||
InterOperand mConst;
|
||||
InterOperator mOperator;
|
||||
InterOperand mOps[4];
|
||||
int mNumOperands;
|
||||
|
||||
bool mInUse, mInvariant, mVolatile, mExpensive, mSingleAssignment, mNoSideEffects, mConstExpr, mRemove;
|
||||
bool mInUse, mInvariant, mVolatile, mExpensive, mSingleAssignment, mNoSideEffects, mConstExpr, mRemove, mAliasing;
|
||||
|
||||
InterInstruction(const Location& loc, InterCode code);
|
||||
InterInstruction(const InterInstruction&) = delete;
|
||||
InterInstruction& operator=(const InterInstruction&) = delete;
|
||||
|
||||
bool IsEqual(const InterInstruction* ins) const;
|
||||
bool IsEqualSource(const InterInstruction* ins) const;
|
||||
|
@ -363,7 +381,8 @@ public:
|
|||
InterCodeBasicBlock * mTrueJump, * mFalseJump, * mLoopPrefix, * mDominator;
|
||||
GrowingInstructionArray mInstructions;
|
||||
|
||||
bool mVisited, mInPath, mLoopHead, mChecked, mConditionBlockTrue, mUnreachable, mLoopPath, mValueRangeValid;
|
||||
bool mVisited, mInPath, mLoopHead, mChecked, mConditionBlockTrue, mUnreachable, mLoopPath, mValueRangeValid, mPatched, mLoopDebug;
|
||||
mutable int mMark;
|
||||
|
||||
NumberSet mLocalUsedTemps, mLocalModifiedTemps;
|
||||
NumberSet mLocalRequiredTemps, mLocalProvidedTemps;
|
||||
|
@ -384,6 +403,8 @@ public:
|
|||
NumberSet mEntryRequiredParams, mEntryProvidedParams;
|
||||
NumberSet mExitRequiredParams, mExitProvidedParams;
|
||||
|
||||
NumberSet mEntryRequiredArgs;
|
||||
|
||||
GrowingInstructionArray mLoadStoreInstructions;
|
||||
|
||||
GrowingIntegerValueRangeArray mEntryValueRange, mTrueValueRange, mFalseValueRange;
|
||||
|
@ -403,17 +424,20 @@ public:
|
|||
InterCodeBasicBlock* Clone(void);
|
||||
|
||||
void Append(InterInstruction * code);
|
||||
void AppendBeforeBranch(InterInstruction* code, bool loopindex = false);
|
||||
const InterInstruction* FindByDst(int dst) const;
|
||||
void Close(InterCodeBasicBlock* trueJump, InterCodeBasicBlock* falseJump);
|
||||
|
||||
void CollectEntries(void);
|
||||
void CollectEntryBlocks(InterCodeBasicBlock* from);
|
||||
void GenerateTraces(bool expand, bool compact);
|
||||
void GenerateTraces(int expand, bool compact);
|
||||
void BuildDominatorTree(InterCodeBasicBlock * from);
|
||||
bool StripLoopHead(void);
|
||||
|
||||
bool MergeSameConditionTraces(void);
|
||||
|
||||
void LocalToTemp(int vindex, int temp);
|
||||
void LoadConstantFold(InterInstruction* ins, InterInstruction* ains, const GrowingVariableArray& staticVars, const GrowingInterCodeProcedurePtrArray& staticProcs);
|
||||
|
||||
void CollectAllUsedDefinedTemps(NumberSet& defined, NumberSet& used);
|
||||
|
||||
|
@ -426,6 +450,9 @@ public:
|
|||
void CollectConstTemps(GrowingInstructionPtrArray& ctemps, NumberSet& assignedTemps);
|
||||
bool PropagateConstTemps(const GrowingInstructionPtrArray& ctemps);
|
||||
bool ForwardConstTemps(const GrowingInstructionPtrArray& ctemps);
|
||||
bool PropagateConstCompareResults(void);
|
||||
|
||||
bool EarlyBranchElimination(const GrowingInstructionPtrArray& ctemps);
|
||||
|
||||
bool PropagateVariableCopy(const GrowingInstructionPtrArray& ctemps, const GrowingVariableArray& staticVars, const NumberSet & aliasedLocals, const NumberSet & aliasedParams);
|
||||
|
||||
|
@ -444,6 +471,8 @@ public:
|
|||
bool RemoveUnusedStoreInstructions(const GrowingVariableArray& localVars, const GrowingVariableArray& params, InterMemory paramMemory);
|
||||
bool RemoveUnusedIndirectStoreInstructions(void);
|
||||
|
||||
bool RemoveUnusedArgumentStoreInstructions(void);
|
||||
|
||||
void BuildStaticVariableSet(const GrowingVariableArray& staticVars);
|
||||
void BuildGlobalProvidedStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet fromProvidedVars);
|
||||
bool BuildGlobalRequiredStaticVariableSet(const GrowingVariableArray& staticVars, NumberSet& fromRequiredVars);
|
||||
|
@ -454,9 +483,15 @@ public:
|
|||
|
||||
bool CheckSingleBlockLimitedLoop(InterCodeBasicBlock*& pblock, int64 & nloop);
|
||||
|
||||
bool TempIsUnsigned(int temp);
|
||||
|
||||
void RestartLocalIntegerRangeSets(int num, const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars);
|
||||
void BuildLocalIntegerRangeSets(int num, const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars);
|
||||
void UpdateLocalIntegerRangeSets(const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars);
|
||||
|
||||
void UpdateLocalIntegerRangeSetsForward(const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars);
|
||||
void UpdateLocalIntegerRangeSetsBackward(const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars);
|
||||
|
||||
bool BuildGlobalIntegerRangeSets(bool initial, const GrowingVariableArray& localVars, const GrowingVariableArray& paramVars);
|
||||
void SimplifyIntegerRangeRelops(void);
|
||||
void MarkIntegerRangeBoundUp(int temp, int64 value, GrowingIntegerValueRangeArray& range);
|
||||
|
@ -479,12 +514,14 @@ public:
|
|||
void GlobalRenameRegister(const GrowingIntArray& renameTable, GrowingTypeArray& temporaries);
|
||||
void RenameValueRanges(const GrowingIntArray& renameTable, int numTemps);
|
||||
|
||||
void CheckValueUsage(InterInstruction * ins, const GrowingInstructionPtrArray& tvalue, const GrowingVariableArray& staticVars, FastNumberSet& fsingle);
|
||||
void CheckValueUsage(InterInstruction * ins, const GrowingInstructionPtrArray& tvalue, const GrowingVariableArray& staticVars, const GrowingInterCodeProcedurePtrArray& staticProcs, FastNumberSet& fsingle);
|
||||
void PerformTempForwarding(const TempForwardingTable& forwardingTable, bool reverse, bool checkloops);
|
||||
void PerformValueForwarding(const GrowingInstructionPtrArray& tvalue, const ValueSet& values, FastNumberSet& tvalid, const NumberSet& aliasedLocals, const NumberSet& aliasedParams, int & spareTemps, const GrowingVariableArray& staticVars);
|
||||
void PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars, FastNumberSet& fsingle);
|
||||
void PerformValueForwarding(const GrowingInstructionPtrArray& tvalue, const ValueSet& values, FastNumberSet& tvalid, const NumberSet& aliasedLocals, const NumberSet& aliasedParams, int & spareTemps, const GrowingVariableArray& staticVars, const GrowingInterCodeProcedurePtrArray& staticProcs);
|
||||
void PerformMachineSpecificValueUsageCheck(const GrowingInstructionPtrArray& tvalue, FastNumberSet& tvalid, const GrowingVariableArray& staticVars, const GrowingInterCodeProcedurePtrArray& staticProcs, FastNumberSet& fsingle);
|
||||
bool EliminateDeadBranches(void);
|
||||
|
||||
bool EliminateIntegerSumAliasTemps(const GrowingInstructionPtrArray& tvalue);
|
||||
|
||||
bool MergeIndexedLoadStore(const GrowingInstructionPtrArray& tvalue);
|
||||
bool SimplifyIntegerNumeric(const GrowingInstructionPtrArray& tvalue, int& spareTemps);
|
||||
bool SimplifyPointerOffsets(void);
|
||||
|
@ -523,7 +560,10 @@ public:
|
|||
|
||||
bool MoveTrainCrossBlock(void);
|
||||
bool HoistCommonConditionalPath(void);
|
||||
bool IsDominator(InterCodeBasicBlock* block);
|
||||
bool IsDirectDominatorBlock(InterCodeBasicBlock* block);
|
||||
bool IsDirectLoopPathBlock(InterCodeBasicBlock* block);
|
||||
bool CollectBlocksToDominator(InterCodeBasicBlock* dblock, ExpandingArray<InterCodeBasicBlock*>& body);
|
||||
|
||||
void MarkRelevantStatics(void);
|
||||
void RemoveNonRelevantStatics(void);
|
||||
|
@ -531,12 +571,22 @@ public:
|
|||
bool IsTempModifiedOnPath(int temp, int at) const;
|
||||
bool IsTempReferencedOnPath(int temp, int at) const;
|
||||
|
||||
// The memory referenced by lins may be writtne by sind
|
||||
bool DestroyingMem(const InterInstruction* lins, const InterInstruction* sins) const;
|
||||
bool DestroyingMem(InterCodeBasicBlock* block, InterInstruction* lins, int from, int to) const;
|
||||
|
||||
// The two memory operations may have overlapping reads/writs and writes
|
||||
bool CollidingMem(const InterInstruction* ins1, const InterInstruction* ins2) const;
|
||||
bool CollidingMem(const InterOperand& op, InterType type, const InterInstruction* ins) const;
|
||||
bool CollidingMem(const InterOperand& op1, InterType type1, const InterOperand& op2, InterType type2) const;
|
||||
bool CollidingMem(InterCodeBasicBlock* block, InterInstruction* lins, int from, int to) const;
|
||||
bool InvalidatedBy(const InterInstruction* ins, const InterInstruction* by) const;
|
||||
|
||||
// The two memory regions may be aliased but not just the same
|
||||
bool AliasingMem(const InterInstruction* ins1, const InterInstruction* ins2) const;
|
||||
bool AliasingMem(const InterOperand& op, InterType type, const InterInstruction* ins) const;
|
||||
bool AliasingMem(const InterOperand& op1, InterType type1, const InterOperand& op2, InterType type2) const;
|
||||
bool AliasingMem(InterCodeBasicBlock* block, InterInstruction* lins, int from, int to) const;
|
||||
|
||||
bool PushSinglePathResultInstructions(void);
|
||||
|
||||
|
@ -558,8 +608,11 @@ public:
|
|||
bool IsInsModifiedInRange(int from, int to, const InterInstruction* ins);
|
||||
|
||||
InterInstruction* FindTempOrigin(int temp) const;
|
||||
InterInstruction* FindTempOriginSinglePath(int temp) const;
|
||||
|
||||
bool CheapInlining(int & numTemps);
|
||||
bool CollapseDispatch();
|
||||
bool StructReturnPropagation(void);
|
||||
|
||||
void CheckFinalLocal(void);
|
||||
void CheckFinal(void);
|
||||
|
@ -569,31 +622,51 @@ public:
|
|||
bool CommonTailCodeMerge(void);
|
||||
bool SplitSingleBranchUseConst(void);
|
||||
|
||||
void PeepholeOptimization(const GrowingVariableArray& staticVars);
|
||||
bool PeepholeReplaceOptimization(const GrowingVariableArray& staticVars);
|
||||
void PeepholeOptimization(const GrowingVariableArray& staticVars, const GrowingInterCodeProcedurePtrArray& staticProcs);
|
||||
bool PeepholeReplaceOptimization(const GrowingVariableArray& staticVars, const GrowingInterCodeProcedurePtrArray& staticProcs);
|
||||
|
||||
bool MoveLoopHeadCheckToTail(void);
|
||||
void SingleBlockLoopOptimisation(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars);
|
||||
void SingleBlockLoopUnrolling(void);
|
||||
bool SingleBlockLoopPointerSplit(int& spareTemps);
|
||||
bool SingleBlockLoopPointerToByte(int& spareTemps);
|
||||
bool SingleBlockLoopSinking(int& spareTemps);
|
||||
bool CollectLoopBody(InterCodeBasicBlock* head, ExpandingArray<InterCodeBasicBlock*> & body);
|
||||
bool CollectLoopBodyRecursive(InterCodeBasicBlock* head, ExpandingArray<InterCodeBasicBlock*>& body);
|
||||
void CollectLoopPath(const ExpandingArray<InterCodeBasicBlock*>& body, ExpandingArray<InterCodeBasicBlock*>& path);
|
||||
void InnerLoopOptimization(const NumberSet& aliasedParams);
|
||||
void ConstLoopOptimization(void);
|
||||
bool EmptyLoopOptimization(void);
|
||||
void EliminateDoubleLoopCounter(void);
|
||||
void PushMoveOutOfLoop(void);
|
||||
bool MoveConditionOutOfLoop(void);
|
||||
void SingleLoopCountZeroCheck(void);
|
||||
void InnerLoopCountZeroCheck(void);
|
||||
bool PostDecLoopOptimization(void);
|
||||
bool Flatten2DLoop(void);
|
||||
|
||||
void PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue);
|
||||
void PropagateMemoryAliasingInfo(const GrowingInstructionPtrArray& tvalue, bool loops);
|
||||
void RemoveUnusedMallocs(void);
|
||||
|
||||
bool CollectSingleHeadLoopBody(InterCodeBasicBlock* head, InterCodeBasicBlock* tail, GrowingArray<InterCodeBasicBlock*>& body);
|
||||
bool PullStoreUpToConstAddress(void);
|
||||
|
||||
bool CollectSingleHeadLoopBody(InterCodeBasicBlock* head, InterCodeBasicBlock* tail, ExpandingArray<InterCodeBasicBlock*>& body);
|
||||
|
||||
bool CollectGenericLoop(ExpandingArray<InterCodeBasicBlock*>& lblocks);
|
||||
bool CollectSingleEntryGenericLoop(ExpandingArray<InterCodeBasicBlock*>& lblocks);
|
||||
void CollectReachable(ExpandingArray<InterCodeBasicBlock*>& lblock);
|
||||
|
||||
bool SingleTailLoopOptimization(const NumberSet& aliasedParams, const GrowingVariableArray& staticVars);
|
||||
bool MergeLoopTails(void);
|
||||
|
||||
bool ChangeTrueJump(InterCodeBasicBlock* block);
|
||||
bool ChangeFalseJump(InterCodeBasicBlock* block);
|
||||
|
||||
InterCodeBasicBlock* CheckIsSimpleIntRangeBranch(const GrowingIntegerValueRangeArray & irange);
|
||||
InterCodeBasicBlock* CheckIsConstBranch(const GrowingInstructionPtrArray& cins);
|
||||
bool ShortcutConstBranches(const GrowingInstructionPtrArray& cins);
|
||||
bool ShortcutDuplicateBranches(void);
|
||||
|
||||
InterCodeBasicBlock* BuildLoopPrefix(void);
|
||||
void BuildLoopSuffix(void);
|
||||
|
||||
|
@ -602,6 +675,9 @@ public:
|
|||
void SplitBranches(void);
|
||||
void FollowJumps(void);
|
||||
|
||||
bool ShortLeaMerge(int& spareTemps);
|
||||
bool ShortLeaCleanup(void);
|
||||
|
||||
bool IsEqual(const InterCodeBasicBlock* block) const;
|
||||
|
||||
void CompactInstructions(void);
|
||||
|
@ -612,16 +688,19 @@ public:
|
|||
bool CheckStaticStack(void);
|
||||
void ApplyStaticStack(InterOperand& iop, const GrowingVariableArray& localVars);
|
||||
void CollectStaticStack(LinkerObject * lobj, const GrowingVariableArray& localVars);
|
||||
void CollectStaticStackDependencies(LinkerObject* lobj);
|
||||
void PromoteStaticStackParams(LinkerObject* paramlobj);
|
||||
|
||||
bool SameExitCode(const InterCodeBasicBlock* block) const;
|
||||
|
||||
void WarnUsedUndefinedVariables(void);
|
||||
void WarnInvalidValueRanges(void);
|
||||
void CheckValueReturn(void);
|
||||
void CheckNullptrDereference(void);
|
||||
|
||||
void CollectGlobalReferences(NumberSet& referencedGlobals, NumberSet& modifiedGlobals, bool & storesIndirect, bool & loadsIndirect, bool & globalsChecked);
|
||||
|
||||
void MarkAliasing(const NumberSet& aliasedParams);
|
||||
};
|
||||
|
||||
class InterCodeProcedure
|
||||
|
@ -634,9 +713,11 @@ protected:
|
|||
GrowingIntegerValueRangeArray mLocalValueRange, mReverseValueRange;
|
||||
|
||||
void ResetVisited(void);
|
||||
void ResetPatched(void);
|
||||
void ResetEntryBlocks(void);
|
||||
public:
|
||||
InterCodeBasicBlock * mEntryBlock;
|
||||
int mNumBlocks;
|
||||
GrowingInterCodeBasicBlockPtrArray mBlocks;
|
||||
GrowingTypeArray mTemporaries;
|
||||
GrowingIntArray mTempOffset, mTempSizes;
|
||||
|
@ -652,7 +733,7 @@ public:
|
|||
InterCodeModule * mModule;
|
||||
int mID;
|
||||
|
||||
int mLocalSize, mNumLocals;
|
||||
int mLocalSize, mNumLocals, mNumParams;
|
||||
GrowingVariableArray mLocalVars, mParamVars;
|
||||
NumberSet mLocalAliasedSet, mParamAliasedSet;
|
||||
|
||||
|
@ -689,12 +770,14 @@ public:
|
|||
bool ModifiesGlobal(int varindex);
|
||||
|
||||
void MapVariables(void);
|
||||
void ReduceTemporaries(void);
|
||||
void ReduceTemporaries(bool final = false);
|
||||
void Disassemble(FILE* file);
|
||||
void Disassemble(const char* name, bool dumpSets = false);
|
||||
protected:
|
||||
void BuildLocalAliasTable(void);
|
||||
void BuildTraces(bool expand, bool dominators = true, bool compact = false);
|
||||
void BuildTraces(int expand, bool dominators = true, bool compact = false);
|
||||
void TrimBlocks(void);
|
||||
void EarlyBranchElimination(void);
|
||||
void BuildDataFlowSets(void);
|
||||
void RenameTemporaries(void);
|
||||
void TempForwarding(bool reverse = false, bool checkloops = false);
|
||||
|
@ -713,7 +796,9 @@ protected:
|
|||
void SimplifyIntegerNumeric(FastNumberSet& activeSet);
|
||||
void SingleBlockLoopPointerSplit(FastNumberSet& activeSet);
|
||||
void SingleBlockLoopPointerToByte(FastNumberSet& activeSet);
|
||||
void SingleBlockLoopSinking(FastNumberSet& activeSet);
|
||||
void MergeIndexedLoadStore(void);
|
||||
void EliminateIntegerSumAliasTemps(void);
|
||||
void EliminateAliasValues();
|
||||
void LoadStoreForwarding(InterMemory paramMemory);
|
||||
void ReduceRecursionTempSpilling(InterMemory paramMemory);
|
||||
|
@ -727,12 +812,20 @@ protected:
|
|||
void RecheckLocalAliased(void);
|
||||
void ConstLoopOptimization(void);
|
||||
|
||||
void MergeBasicBlocks(void);
|
||||
bool ShortLeaMerge(FastNumberSet& activeSet);
|
||||
|
||||
void MergeBasicBlocks(FastNumberSet& activeSet);
|
||||
void CheckUsedDefinedTemps(void);
|
||||
void WarnUsedUndefinedVariables(void);
|
||||
void PropagateMemoryAliasingInfo(void);
|
||||
void WarnInvalidValueRanges(void);
|
||||
void PropagateMemoryAliasingInfo(bool loops);
|
||||
void MoveConditionsOutOfLoop(void);
|
||||
void ShortcutConstBranches(void);
|
||||
void ShortcutDuplicateBranches(void);
|
||||
void EliminateDoubleLoopCounter(void);
|
||||
void StructReturnPropagation(void);
|
||||
|
||||
void CollapseDispatch(void);
|
||||
|
||||
void PeepholeOptimization(void);
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue